-/* $OpenBSD: uvm_map.c,v 1.292 2022/08/07 19:39:25 miod Exp $ */
+/* $OpenBSD: uvm_map.c,v 1.293 2022/08/15 03:12:12 jsg Exp $ */
/* $NetBSD: uvm_map.c,v 1.86 2000/11/27 08:40:03 chs Exp $ */
/*
vaddr_t, vaddr_t, int);
struct vm_map_entry *uvm_map_fix_space(struct vm_map*, struct vm_map_entry*,
vaddr_t, vaddr_t, int);
-int uvm_map_sel_limits(vaddr_t*, vaddr_t*, vsize_t, int,
- struct vm_map_entry*, vaddr_t, vaddr_t, vaddr_t,
- int);
int uvm_map_findspace(struct vm_map*,
struct vm_map_entry**, struct vm_map_entry**,
vaddr_t*, vsize_t, vaddr_t, vaddr_t, vm_prot_t,
#define DEAD_ENTRY_PUSH(_headptr, _entry) \
dead_entry_push((_headptr), (_entry))
-/*
- * Helper function for uvm_map_findspace_tree.
- *
- * Given allocation constraints and pmap constraints, finds the
- * lowest and highest address in a range that can be used for the
- * allocation.
- *
- * pmap_align and pmap_off are ignored on non-PMAP_PREFER archs.
- *
- *
- * Big chunk of math with a seasoning of dragons.
- */
-int
-uvm_map_sel_limits(vaddr_t *min, vaddr_t *max, vsize_t sz, int guardpg,
- struct vm_map_entry *sel, vaddr_t align,
- vaddr_t pmap_align, vaddr_t pmap_off, int bias)
-{
- vaddr_t sel_min, sel_max;
-#ifdef PMAP_PREFER
- vaddr_t pmap_min, pmap_max;
-#endif /* PMAP_PREFER */
-#ifdef DIAGNOSTIC
- int bad;
-#endif /* DIAGNOSTIC */
-
- sel_min = VMMAP_FREE_START(sel);
- sel_max = VMMAP_FREE_END(sel) - sz - (guardpg ? PAGE_SIZE : 0);
-
-#ifdef PMAP_PREFER
-
- /*
- * There are two special cases, in which we can satisfy the align
- * requirement and the pmap_prefer requirement.
- * - when pmap_off == 0, we always select the largest of the two
- * - when pmap_off % align == 0 and pmap_align > align, we simply
- * satisfy the pmap_align requirement and automatically
- * satisfy the align requirement.
- */
- if (align > PAGE_SIZE &&
- !(pmap_align > align && (pmap_off & (align - 1)) == 0)) {
- /*
- * Simple case: only use align.
- */
- sel_min = roundup(sel_min, align);
- sel_max &= ~(align - 1);
-
- if (sel_min > sel_max)
- return ENOMEM;
-
- /* Correct for bias. */
- if (sel_max - sel_min > FSPACE_BIASGAP) {
- if (bias > 0) {
- sel_min = sel_max - FSPACE_BIASGAP;
- sel_min = roundup(sel_min, align);
- } else if (bias < 0) {
- sel_max = sel_min + FSPACE_BIASGAP;
- sel_max &= ~(align - 1);
- }
- }
- } else if (pmap_align != 0) {
- /*
- * Special case: satisfy both pmap_prefer and
- * align argument.
- */
- pmap_max = sel_max & ~(pmap_align - 1);
- pmap_min = sel_min;
- if (pmap_max < sel_min)
- return ENOMEM;
-
- /* Adjust pmap_min for BIASGAP for top-addr bias. */
- if (bias > 0 && pmap_max - pmap_min > FSPACE_BIASGAP)
- pmap_min = pmap_max - FSPACE_BIASGAP;
- /* Align pmap_min. */
- pmap_min &= ~(pmap_align - 1);
- if (pmap_min < sel_min)
- pmap_min += pmap_align;
- if (pmap_min > pmap_max)
- return ENOMEM;
-
- /* Adjust pmap_max for BIASGAP for bottom-addr bias. */
- if (bias < 0 && pmap_max - pmap_min > FSPACE_BIASGAP) {
- pmap_max = (pmap_min + FSPACE_BIASGAP) &
- ~(pmap_align - 1);
- }
- if (pmap_min > pmap_max)
- return ENOMEM;
-
- /* Apply pmap prefer offset. */
- pmap_max |= pmap_off;
- if (pmap_max > sel_max)
- pmap_max -= pmap_align;
- pmap_min |= pmap_off;
- if (pmap_min < sel_min)
- pmap_min += pmap_align;
-
- /*
- * Fixup: it's possible that pmap_min and pmap_max
- * cross each other. In this case, try to find one
- * address that is allowed.
- * (This usually happens in biased case.)
- */
- if (pmap_min > pmap_max) {
- if (pmap_min < sel_max)
- pmap_max = pmap_min;
- else if (pmap_max > sel_min)
- pmap_min = pmap_max;
- else
- return ENOMEM;
- }
-
- /* Internal validation. */
- KDASSERT(pmap_min <= pmap_max);
-
- sel_min = pmap_min;
- sel_max = pmap_max;
- } else if (bias > 0 && sel_max - sel_min > FSPACE_BIASGAP)
- sel_min = sel_max - FSPACE_BIASGAP;
- else if (bias < 0 && sel_max - sel_min > FSPACE_BIASGAP)
- sel_max = sel_min + FSPACE_BIASGAP;
-
-#else
-
- if (align > PAGE_SIZE) {
- sel_min = roundup(sel_min, align);
- sel_max &= ~(align - 1);
- if (sel_min > sel_max)
- return ENOMEM;
-
- if (bias != 0 && sel_max - sel_min > FSPACE_BIASGAP) {
- if (bias > 0) {
- sel_min = roundup(sel_max - FSPACE_BIASGAP,
- align);
- } else {
- sel_max = (sel_min + FSPACE_BIASGAP) &
- ~(align - 1);
- }
- }
- } else if (bias > 0 && sel_max - sel_min > FSPACE_BIASGAP)
- sel_min = sel_max - FSPACE_BIASGAP;
- else if (bias < 0 && sel_max - sel_min > FSPACE_BIASGAP)
- sel_max = sel_min + FSPACE_BIASGAP;
-
-#endif
-
- if (sel_min > sel_max)
- return ENOMEM;
-
-#ifdef DIAGNOSTIC
- bad = 0;
- /* Lower boundary check. */
- if (sel_min < VMMAP_FREE_START(sel)) {
- printf("sel_min: 0x%lx, but should be at least 0x%lx\n",
- sel_min, VMMAP_FREE_START(sel));
- bad++;
- }
- /* Upper boundary check. */
- if (sel_max > VMMAP_FREE_END(sel) - sz - (guardpg ? PAGE_SIZE : 0)) {
- printf("sel_max: 0x%lx, but should be at most 0x%lx\n",
- sel_max,
- VMMAP_FREE_END(sel) - sz - (guardpg ? PAGE_SIZE : 0));
- bad++;
- }
- /* Lower boundary alignment. */
- if (align != 0 && (sel_min & (align - 1)) != 0) {
- printf("sel_min: 0x%lx, not aligned to 0x%lx\n",
- sel_min, align);
- bad++;
- }
- /* Upper boundary alignment. */
- if (align != 0 && (sel_max & (align - 1)) != 0) {
- printf("sel_max: 0x%lx, not aligned to 0x%lx\n",
- sel_max, align);
- bad++;
- }
- /* Lower boundary PMAP_PREFER check. */
- if (pmap_align != 0 && align == 0 &&
- (sel_min & (pmap_align - 1)) != pmap_off) {
- printf("sel_min: 0x%lx, aligned to 0x%lx, expected 0x%lx\n",
- sel_min, sel_min & (pmap_align - 1), pmap_off);
- bad++;
- }
- /* Upper boundary PMAP_PREFER check. */
- if (pmap_align != 0 && align == 0 &&
- (sel_max & (pmap_align - 1)) != pmap_off) {
- printf("sel_max: 0x%lx, aligned to 0x%lx, expected 0x%lx\n",
- sel_max, sel_max & (pmap_align - 1), pmap_off);
- bad++;
- }
-
- if (bad) {
- panic("uvm_map_sel_limits(sz = %lu, guardpg = %c, "
- "align = 0x%lx, pmap_align = 0x%lx, pmap_off = 0x%lx, "
- "bias = %d, "
- "FREE_START(sel) = 0x%lx, FREE_END(sel) = 0x%lx)",
- sz, (guardpg ? 'T' : 'F'), align, pmap_align, pmap_off,
- bias, VMMAP_FREE_START(sel), VMMAP_FREE_END(sel));
- }
-#endif /* DIAGNOSTIC */
-
- *min = sel_min;
- *max = sel_max;
- return 0;
-}
-
/*
* Test if memory starting at addr with sz bytes is free.
*