From ecaf2f40636d722d955675482a7dee48814b8405 Mon Sep 17 00:00:00 2001 From: tnn Date: Sat, 13 Jan 2024 09:44:42 +0000 Subject: [PATCH] uvm: change type of uvm_physseg.start_hint from u_int to u_long Avoids assertion failure in uvm_pglistalloc_s_ps() with large paddrs. PR kern/57683. --- sys/uvm/uvm_pglist.c | 38 ++++++++++++++++++++------------------ sys/uvm/uvm_physseg.c | 8 ++++---- sys/uvm/uvm_physseg.h | 6 +++--- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/sys/uvm/uvm_pglist.c b/sys/uvm/uvm_pglist.c index 0c4c91dea0a8..3d5e89bae0f8 100644 --- a/sys/uvm/uvm_pglist.c +++ b/sys/uvm/uvm_pglist.c @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_pglist.c,v 1.90 2021/12/21 08:27:49 skrll Exp $ */ +/* $NetBSD: uvm_pglist.c,v 1.91 2024/01/13 09:44:42 tnn Exp $ */ /*- * Copyright (c) 1997, 2019 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: uvm_pglist.c,v 1.90 2021/12/21 08:27:49 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_pglist.c,v 1.91 2024/01/13 09:44:42 tnn Exp $"); #include #include @@ -112,8 +112,9 @@ static int uvm_pglistalloc_c_ps(uvm_physseg_t psi, int num, paddr_t low, paddr_t high, paddr_t alignment, paddr_t boundary, struct pglist *rlist) { - signed int candidate, limit, candidateidx, end, idx, skip; - int pagemask; + long candidate, limit, candidateidx, end, idx; + int skip; + long pagemask; bool second_pass; #ifdef DEBUG paddr_t idxpa, lastidxpa; @@ -138,9 +139,9 @@ uvm_pglistalloc_c_ps(uvm_physseg_t psi, int num, paddr_t low, paddr_t high, * succeeded. */ alignment = atop(alignment); - candidate = roundup2(uimax(low, uvm_physseg_get_avail_start(psi) + + candidate = roundup2(ulmax(low, uvm_physseg_get_avail_start(psi) + uvm_physseg_get_start_hint(psi)), alignment); - limit = uimin(high, uvm_physseg_get_avail_end(psi)); + limit = ulmin(high, uvm_physseg_get_avail_end(psi)); pagemask = ~((boundary >> PAGE_SHIFT) - 1); skip = 0; second_pass = false; @@ -162,8 +163,8 @@ uvm_pglistalloc_c_ps(uvm_physseg_t psi, int num, paddr_t low, paddr_t high, * is were we started. */ second_pass = true; - candidate = roundup2(uimax(low, uvm_physseg_get_avail_start(psi)), alignment); - limit = uimin(limit, uvm_physseg_get_avail_start(psi) + + candidate = roundup2(ulmax(low, uvm_physseg_get_avail_start(psi)), alignment); + limit = ulmin(limit, uvm_physseg_get_avail_start(psi) + uvm_physseg_get_start_hint(psi)); skip = 0; continue; @@ -200,7 +201,7 @@ uvm_pglistalloc_c_ps(uvm_physseg_t psi, int num, paddr_t low, paddr_t high, * Found a suitable starting page. See if the range is free. */ #ifdef PGALLOC_VERBOSE - printf("%s: psi=%d candidate=%#x end=%#x skip=%#x, align=%#"PRIxPADDR, + printf("%s: psi=%d candidate=%#lx end=%#lx skip=%#x, align=%#"PRIxPADDR, __func__, psi, candidateidx, end, skip, alignment); #endif /* @@ -283,7 +284,7 @@ uvm_pglistalloc_c_ps(uvm_physseg_t psi, int num, paddr_t low, paddr_t high, uvm_physseg_get_avail_start(psi)); KASSERTMSG(uvm_physseg_get_start_hint(psi) <= uvm_physseg_get_avail_end(psi) - uvm_physseg_get_avail_start(psi), - "%x %u (%#x) <= %#"PRIxPADDR" - %#"PRIxPADDR" (%#"PRIxPADDR")", + "%lx %lu (%#lx) <= %#"PRIxPADDR" - %#"PRIxPADDR" (%#"PRIxPADDR")", candidate + num, uvm_physseg_get_start_hint(psi), uvm_physseg_get_start_hint(psi), uvm_physseg_get_avail_end(psi), uvm_physseg_get_avail_start(psi), @@ -523,7 +524,8 @@ static int uvm_pglistalloc_s_ps(uvm_physseg_t psi, int num, paddr_t low, paddr_t high, struct pglist *rlist) { - int todo, limit, candidate; + int todo; + long limit, candidate; struct vm_page *pg; bool second_pass; #ifdef PGALLOC_VERBOSE @@ -546,9 +548,9 @@ uvm_pglistalloc_s_ps(uvm_physseg_t psi, int num, paddr_t low, paddr_t high, return -1; todo = num; - candidate = uimax(low, uvm_physseg_get_avail_start(psi) + + candidate = ulmax(low, uvm_physseg_get_avail_start(psi) + uvm_physseg_get_start_hint(psi)); - limit = uimin(high, uvm_physseg_get_avail_end(psi)); + limit = ulmin(high, uvm_physseg_get_avail_end(psi)); pg = uvm_physseg_get_pg(psi, candidate - uvm_physseg_get_start(psi)); second_pass = false; @@ -560,8 +562,8 @@ again: break; } second_pass = true; - candidate = uimax(low, uvm_physseg_get_avail_start(psi)); - limit = uimin(limit, uvm_physseg_get_avail_start(psi) + + candidate = ulmax(low, uvm_physseg_get_avail_start(psi)); + limit = ulmin(limit, uvm_physseg_get_avail_start(psi) + uvm_physseg_get_start_hint(psi)); pg = uvm_physseg_get_pg(psi, candidate - uvm_physseg_get_start(psi)); goto again; @@ -571,10 +573,10 @@ again: paddr_t cidx = 0; const uvm_physseg_t bank = uvm_physseg_find(candidate, &cidx); KDASSERTMSG(bank == psi, - "uvm_physseg_find(%#x) (%"PRIxPHYSSEG ") != psi %"PRIxPHYSSEG, + "uvm_physseg_find(%#lx) (%"PRIxPHYSSEG ") != psi %"PRIxPHYSSEG, candidate, bank, psi); KDASSERTMSG(cidx == candidate - uvm_physseg_get_start(psi), - "uvm_physseg_find(%#x): %#"PRIxPADDR" != off %"PRIxPADDR, + "uvm_physseg_find(%#lx): %#"PRIxPADDR" != off %"PRIxPADDR, candidate, cidx, candidate - uvm_physseg_get_start(psi)); } #endif @@ -594,7 +596,7 @@ again: uvm_physseg_set_start_hint(psi, candidate + 1 - uvm_physseg_get_avail_start(psi)); KASSERTMSG(uvm_physseg_get_start_hint(psi) <= uvm_physseg_get_avail_end(psi) - uvm_physseg_get_avail_start(psi), - "%#x %u (%#x) <= %#"PRIxPADDR" - %#"PRIxPADDR" (%#"PRIxPADDR")", + "%#lx %lu (%#lx) <= %#"PRIxPADDR" - %#"PRIxPADDR" (%#"PRIxPADDR")", candidate + 1, uvm_physseg_get_start_hint(psi), uvm_physseg_get_start_hint(psi), diff --git a/sys/uvm/uvm_physseg.c b/sys/uvm/uvm_physseg.c index 10535fd19ecc..94593106b73c 100644 --- a/sys/uvm/uvm_physseg.c +++ b/sys/uvm/uvm_physseg.c @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_physseg.c,v 1.19 2023/09/23 18:20:20 ad Exp $ */ +/* $NetBSD: uvm_physseg.c,v 1.20 2024/01/13 09:44:42 tnn Exp $ */ /* * Copyright (c) 1997 Charles D. Cranor and Washington University. @@ -100,7 +100,7 @@ struct uvm_physseg { paddr_t avail_end; /* (PF# of last free page in segment) +1 */ struct extent *ext; /* extent(9) structure to manage pgs[] */ int free_list; /* which free list they belong on */ - u_int start_hint; /* start looking for free pages here */ + u_long start_hint; /* start looking for free pages here */ #ifdef __HAVE_PMAP_PHYSSEG struct pmap_physseg pmseg; /* pmap specific (MD) data */ #endif @@ -1108,7 +1108,7 @@ uvm_physseg_get_free_list(uvm_physseg_t upm) return HANDLE_TO_PHYSSEG_NODE(upm)->free_list; } -u_int +u_long uvm_physseg_get_start_hint(uvm_physseg_t upm) { KASSERT(uvm_physseg_valid_p(upm)); @@ -1116,7 +1116,7 @@ uvm_physseg_get_start_hint(uvm_physseg_t upm) } bool -uvm_physseg_set_start_hint(uvm_physseg_t upm, u_int start_hint) +uvm_physseg_set_start_hint(uvm_physseg_t upm, u_long start_hint) { if (uvm_physseg_valid_p(upm) == false) return false; diff --git a/sys/uvm/uvm_physseg.h b/sys/uvm/uvm_physseg.h index 2538564ddd00..df4ae5478b7c 100644 --- a/sys/uvm/uvm_physseg.h +++ b/sys/uvm/uvm_physseg.h @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_physseg.h,v 1.8 2017/01/02 20:08:32 cherry Exp $ */ +/* $NetBSD: uvm_physseg.h,v 1.9 2024/01/13 09:44:42 tnn Exp $ */ /*- * Copyright (c) 2016 The NetBSD Foundation, Inc. @@ -106,8 +106,8 @@ struct pmap_physseg * uvm_physseg_get_pmseg(uvm_physseg_t); #endif int uvm_physseg_get_free_list(uvm_physseg_t); -u_int uvm_physseg_get_start_hint(uvm_physseg_t); -bool uvm_physseg_set_start_hint(uvm_physseg_t, u_int); +u_long uvm_physseg_get_start_hint(uvm_physseg_t); +bool uvm_physseg_set_start_hint(uvm_physseg_t, u_long); /* * Functions to help walk the list of segments.