Home | History | Annotate | Line # | Download | only in uvm
      1 /* $NetBSD: t_uvm_physseg.c,v 1.11 2022/07/26 19:49:32 andvar Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2015, 2016 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Santhosh N. Raju <santhosh.raju (at) gmail.com> and
      9  * by Cherry G. Mathew
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30  * POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include <sys/cdefs.h>
     34 __RCSID("$NetBSD: t_uvm_physseg.c,v 1.11 2022/07/26 19:49:32 andvar Exp $");
     35 
     36 /*
     37  * If this line is commented out tests related to uvm_physseg_get_pmseg()
     38  * wont run.
     39  *
     40  * Have a look at machine/uvm_physseg.h for more details.
     41  */
     42 #define __HAVE_PMAP_PHYSSEG
     43 
     44 /*
     45  * This is a dummy struct used for testing purposes
     46  *
     47  * In reality this struct would exist in the MD part of the code residing in
     48  * machines/vmparam.h
     49  */
     50 
     51 #ifdef __HAVE_PMAP_PHYSSEG
     52 struct pmap_physseg {
     53 	int dummy_variable;		/* Dummy variable use for testing */
     54 };
     55 #endif
     56 
     57 /* Testing API - assumes userland */
     58 /* Provide Kernel API equivalents */
     59 #include <assert.h>
     60 #include <errno.h>
     61 #include <stdbool.h>
     62 #include <string.h> /* memset(3) et. al */
     63 #include <stdio.h> /* printf(3) */
     64 #include <stdlib.h> /* malloc(3) */
     65 #include <stdarg.h>
     66 #include <stddef.h>
     67 
     68 #define	PRIxPADDR	"lx"
     69 #define	PRIxPSIZE	"lx"
     70 #define	PRIuPSIZE	"lu"
     71 #define	PRIxVADDR	"lx"
     72 #define	PRIxVSIZE	"lx"
     73 #define	PRIuVSIZE	"lu"
     74 
     75 #define UVM_HOTPLUG /* Enable hotplug with rbtree. */
     76 #define PMAP_STEAL_MEMORY
     77 #define DEBUG /* Enable debug functionality. */
     78 
     79 typedef unsigned long vaddr_t;
     80 typedef unsigned long paddr_t;
     81 typedef unsigned long psize_t;
     82 typedef unsigned long vsize_t;
     83 
     84 #include <uvm/uvm_physseg.h>
     85 #include <uvm/uvm_page.h>
     86 
     87 #ifndef DIAGNOSTIC
     88 #define	KASSERTMSG(e, msg, ...)	/* NOTHING */
     89 #define	KASSERT(e)		/* NOTHING */
     90 #else
     91 #define	KASSERT(a)		assert(a)
     92 #define KASSERTMSG(exp, ...)    printf(__VA_ARGS__); assert((exp))
     93 #endif
     94 
     95 #define VM_PHYSSEG_STRAT VM_PSTRAT_BSEARCH
     96 
     97 #define VM_NFREELIST            4
     98 #define VM_FREELIST_DEFAULT     0
     99 #define VM_FREELIST_FIRST16     3
    100 #define VM_FREELIST_FIRST1G     2
    101 #define VM_FREELIST_FIRST4G     1
    102 
    103 /*
    104  * Used in tests when Array implementation is tested
    105  */
    106 #if !defined(VM_PHYSSEG_MAX)
    107 #define VM_PHYSSEG_MAX          1
    108 #endif
    109 
    110 #define PAGE_SHIFT              12
    111 #define PAGE_SIZE               (1 << PAGE_SHIFT)
    112 #define	PAGE_MASK	(PAGE_SIZE - 1)
    113 #define atop(x)         (((paddr_t)(x)) >> PAGE_SHIFT)
    114 #define ptoa(x)         (((paddr_t)(x)) << PAGE_SHIFT)
    115 
    116 #define	mutex_enter(l)
    117 #define	mutex_exit(l)
    118 
    119 psize_t physmem;
    120 
    121 struct uvmexp uvmexp;        /* decl */
    122 
    123 /*
    124  * uvm structure borrowed from uvm.h
    125  *
    126  * Remember this is a dummy structure used within the ATF Tests and
    127  * uses only necessary fields from the original uvm struct.
    128  * See uvm/uvm.h for the full struct.
    129  */
    130 
    131 struct uvm {
    132 	/* vm_page related parameters */
    133 
    134 	bool page_init_done;		/* TRUE if uvm_page_init() finished */
    135 } uvm;
    136 
    137 #include <sys/kmem.h>
    138 
    139 void *
    140 kmem_alloc(size_t size, km_flag_t flags)
    141 {
    142 	return malloc(size);
    143 }
    144 
    145 void *
    146 kmem_zalloc(size_t size, km_flag_t flags)
    147 {
    148 	void *ptr;
    149 	ptr = malloc(size);
    150 
    151 	memset(ptr, 0, size);
    152 
    153 	return ptr;
    154 }
    155 
    156 void
    157 kmem_free(void *mem, size_t size)
    158 {
    159 	free(mem);
    160 }
    161 
    162 static void
    163 panic(const char *fmt, ...)
    164 {
    165 	va_list ap;
    166 
    167 	va_start(ap, fmt);
    168 	vprintf(fmt, ap);
    169 	printf("\n");
    170 	va_end(ap);
    171 	KASSERT(false);
    172 
    173 	/*NOTREACHED*/
    174 }
    175 
    176 static void
    177 uvm_pagefree(struct vm_page *pg)
    178 {
    179 	return;
    180 }
    181 
    182 #if defined(UVM_HOTPLUG)
    183 static void
    184 uvmpdpol_reinit(void)
    185 {
    186 	return;
    187 }
    188 #endif /* UVM_HOTPLUG */
    189 
    190 /* end - Provide Kernel API equivalents */
    191 
    192 
    193 #include "uvm/uvm_physseg.c"
    194 
    195 #include <atf-c.h>
    196 
    197 #define SIXTYFOUR_KILO (64 * 1024)
    198 #define ONETWENTYEIGHT_KILO (128 * 1024)
    199 #define TWOFIFTYSIX_KILO (256 * 1024)
    200 #define FIVEONETWO_KILO (512 * 1024)
    201 #define ONE_MEGABYTE (1024 * 1024)
    202 #define TWO_MEGABYTE (2 * 1024 * 1024)
    203 
    204 /* Sample Page Frame Numbers */
    205 #define VALID_START_PFN_1 atop(0)
    206 #define VALID_END_PFN_1 atop(ONE_MEGABYTE)
    207 #define VALID_AVAIL_START_PFN_1 atop(0)
    208 #define VALID_AVAIL_END_PFN_1 atop(ONE_MEGABYTE)
    209 
    210 #define VALID_START_PFN_2 atop(ONE_MEGABYTE + 1)
    211 #define VALID_END_PFN_2 atop(ONE_MEGABYTE * 2)
    212 #define VALID_AVAIL_START_PFN_2 atop(ONE_MEGABYTE + 1)
    213 #define VALID_AVAIL_END_PFN_2 atop(ONE_MEGABYTE * 2)
    214 
    215 #define VALID_START_PFN_3 atop((ONE_MEGABYTE * 2) + 1)
    216 #define VALID_END_PFN_3 atop(ONE_MEGABYTE * 3)
    217 #define VALID_AVAIL_START_PFN_3 atop((ONE_MEGABYTE * 2) + 1)
    218 #define VALID_AVAIL_END_PFN_3 atop(ONE_MEGABYTE * 3)
    219 
    220 #define VALID_START_PFN_4 atop((ONE_MEGABYTE * 3) + 1)
    221 #define VALID_END_PFN_4 atop(ONE_MEGABYTE * 4)
    222 #define VALID_AVAIL_START_PFN_4 atop((ONE_MEGABYTE * 3) + 1)
    223 #define VALID_AVAIL_END_PFN_4 atop(ONE_MEGABYTE * 4)
    224 
    225 /*
    226  * Total number of pages (of 4K size each) should be 256 for 1MB of memory.
    227  */
    228 #define PAGE_COUNT_1M      256
    229 
    230 /*
    231  * A debug function to print the content of upm.
    232  */
    233 	static inline void
    234 	uvm_physseg_dump_seg(uvm_physseg_t upm)
    235 	{
    236 #if defined(DEBUG)
    237 		printf("%s: seg->start == %ld\n", __func__,
    238 		    uvm_physseg_get_start(upm));
    239 		printf("%s: seg->end == %ld\n", __func__,
    240 		    uvm_physseg_get_end(upm));
    241 		printf("%s: seg->avail_start == %ld\n", __func__,
    242 		    uvm_physseg_get_avail_start(upm));
    243 		printf("%s: seg->avail_end == %ld\n", __func__,
    244 		    uvm_physseg_get_avail_end(upm));
    245 
    246 		printf("====\n\n");
    247 #else
    248 		return;
    249 #endif /* DEBUG */
    250 	}
    251 
    252 /*
    253  * Private accessor that gets the value of uvm_physseg_graph.nentries
    254  */
    255 static int
    256 uvm_physseg_get_entries(void)
    257 {
    258 #if defined(UVM_HOTPLUG)
    259 	return uvm_physseg_graph.nentries;
    260 #else
    261 	return vm_nphysmem;
    262 #endif /* UVM_HOTPLUG */
    263 }
    264 
    265 #if !defined(UVM_HOTPLUG)
    266 static void *
    267 uvm_physseg_alloc(size_t sz)
    268 {
    269 	return &vm_physmem[vm_nphysseg++];
    270 }
    271 #endif
    272 
    273 /*
    274  * This macro was added to convert uvmexp.npages from int to psize_t
    275  */
    276 #define INT_TO_PSIZE_T(X) (psize_t)X
    277 
    278 /*
    279  * Test Fixture SetUp().
    280  */
    281 static void
    282 setup(void)
    283 {
    284 	/* Prerequisites for running certain calls in uvm_physseg */
    285 	uvmexp.pagesize = PAGE_SIZE;
    286 	uvmexp.npages = 0;
    287 	uvm.page_init_done = false;
    288 	uvm_physseg_init();
    289 }
    290 
    291 
    292 /* <---- Tests for Internal functions ----> */
    293 #if defined(UVM_HOTPLUG)
    294 ATF_TC(uvm_physseg_alloc_atboot_mismatch);
    295 ATF_TC_HEAD(uvm_physseg_alloc_atboot_mismatch, tc)
    296 {
    297 	atf_tc_set_md_var(tc, "descr", "boot time uvm_physseg_alloc() sanity"
    298 	    "size mismatch alloc() test.");
    299 }
    300 
    301 ATF_TC_BODY(uvm_physseg_alloc_atboot_mismatch, tc)
    302 {
    303 	uvm.page_init_done = false;
    304 
    305 	atf_tc_expect_signal(SIGABRT, "size mismatch alloc()");
    306 
    307 	uvm_physseg_alloc(sizeof(struct uvm_physseg) - 1);
    308 }
    309 
    310 ATF_TC(uvm_physseg_alloc_atboot_overrun);
    311 ATF_TC_HEAD(uvm_physseg_alloc_atboot_overrun, tc)
    312 {
    313 	atf_tc_set_md_var(tc, "descr", "boot time uvm_physseg_alloc() sanity"
    314 	    "array overrun alloc() test.");
    315 }
    316 
    317 ATF_TC_BODY(uvm_physseg_alloc_atboot_overrun, tc)
    318 {
    319 	uvm.page_init_done = false;
    320 
    321 	atf_tc_expect_signal(SIGABRT, "array overrun alloc()");
    322 
    323 	uvm_physseg_alloc((VM_PHYSSEG_MAX + 1) * sizeof(struct uvm_physseg));
    324 
    325 }
    326 
    327 ATF_TC(uvm_physseg_alloc_sanity);
    328 ATF_TC_HEAD(uvm_physseg_alloc_sanity, tc)
    329 {
    330 	atf_tc_set_md_var(tc, "descr", "further uvm_physseg_alloc() sanity checks");
    331 }
    332 
    333 ATF_TC_BODY(uvm_physseg_alloc_sanity, tc)
    334 {
    335 
    336 	/* At boot time */
    337 	uvm.page_init_done = false;
    338 
    339 	/* Correct alloc */
    340 	ATF_REQUIRE(uvm_physseg_alloc(VM_PHYSSEG_MAX * sizeof(struct uvm_physseg)));
    341 
    342 	/* Retry static alloc()s as dynamic - we expect them to pass */
    343 	uvm.page_init_done = true;
    344 	ATF_REQUIRE(uvm_physseg_alloc(sizeof(struct uvm_physseg) - 1));
    345 	ATF_REQUIRE(uvm_physseg_alloc(2 * VM_PHYSSEG_MAX * sizeof(struct uvm_physseg)));
    346 }
    347 
    348 ATF_TC(uvm_physseg_free_atboot_mismatch);
    349 ATF_TC_HEAD(uvm_physseg_free_atboot_mismatch, tc)
    350 {
    351 	atf_tc_set_md_var(tc, "descr", "boot time uvm_physseg_free() sanity"
    352 	    "size mismatch free() test.");
    353 }
    354 
    355 ATF_TC_BODY(uvm_physseg_free_atboot_mismatch, tc)
    356 {
    357 	uvm.page_init_done = false;
    358 
    359 	atf_tc_expect_signal(SIGABRT, "size mismatch free()");
    360 
    361 	uvm_physseg_free(&uvm_physseg[0], sizeof(struct uvm_physseg) - 1);
    362 }
    363 
    364 ATF_TC(uvm_physseg_free_sanity);
    365 ATF_TC_HEAD(uvm_physseg_free_sanity, tc)
    366 {
    367 	atf_tc_set_md_var(tc, "descr", "further uvm_physseg_free() sanity checks");
    368 }
    369 
    370 ATF_TC_BODY(uvm_physseg_free_sanity, tc)
    371 {
    372 
    373 	/* At boot time */
    374 	uvm.page_init_done = false;
    375 
    376 	struct uvm_physseg *seg;
    377 
    378 #if VM_PHYSSEG_MAX > 1
    379 	/*
    380 	 * Note: free()ing the entire array is considered to be an
    381 	 * error. Thus VM_PHYSSEG_MAX - 1.
    382 	 */
    383 
    384 	seg = uvm_physseg_alloc((VM_PHYSSEG_MAX - 1) * sizeof(*seg));
    385 	uvm_physseg_free(seg, (VM_PHYSSEG_MAX - 1) * sizeof(struct uvm_physseg));
    386 #endif
    387 
    388 	/* Retry static alloc()s as dynamic - we expect them to pass */
    389 	uvm.page_init_done = true;
    390 
    391 	seg = uvm_physseg_alloc(sizeof(struct uvm_physseg) - 1);
    392 	uvm_physseg_free(seg, sizeof(struct uvm_physseg) - 1);
    393 
    394 	seg = uvm_physseg_alloc(2 * VM_PHYSSEG_MAX * sizeof(struct uvm_physseg));
    395 
    396 	uvm_physseg_free(seg, 2 * VM_PHYSSEG_MAX * sizeof(struct uvm_physseg));
    397 }
    398 
    399 #if VM_PHYSSEG_MAX > 1
    400 ATF_TC(uvm_physseg_atboot_free_leak);
    401 ATF_TC_HEAD(uvm_physseg_atboot_free_leak, tc)
    402 {
    403 	atf_tc_set_md_var(tc, "descr",
    404 	    "does free() leak at boot ?"
    405 	    "This test needs VM_PHYSSEG_MAX > 1)");
    406 }
    407 
    408 ATF_TC_BODY(uvm_physseg_atboot_free_leak, tc)
    409 {
    410 
    411 	/* At boot time */
    412 	uvm.page_init_done = false;
    413 
    414 	/* alloc to array size */
    415 	struct uvm_physseg *seg;
    416 	seg = uvm_physseg_alloc(VM_PHYSSEG_MAX * sizeof(*seg));
    417 
    418 	uvm_physseg_free(seg, sizeof(*seg));
    419 
    420 	atf_tc_expect_signal(SIGABRT, "array overrun on alloc() after leak");
    421 
    422 	ATF_REQUIRE(uvm_physseg_alloc(sizeof(struct uvm_physseg)));
    423 }
    424 #endif /* VM_PHYSSEG_MAX */
    425 #endif /* UVM_HOTPLUG */
    426 
    427 /*
    428  * Note: This function replicates verbatim what happens in
    429  * uvm_page.c:uvm_page_init().
    430  *
    431  * Please track any changes that happen there.
    432  */
    433 static void
    434 uvm_page_init_fake(struct vm_page *pagearray, psize_t pagecount)
    435 {
    436 	uvm_physseg_t bank;
    437 	size_t n;
    438 
    439 	for (bank = uvm_physseg_get_first(),
    440 		 uvm_physseg_seg_chomp_slab(bank, pagearray, pagecount);
    441 	     uvm_physseg_valid_p(bank);
    442 	     bank = uvm_physseg_get_next(bank)) {
    443 
    444 		n = uvm_physseg_get_end(bank) - uvm_physseg_get_start(bank);
    445 		uvm_physseg_seg_alloc_from_slab(bank, n);
    446 		uvm_physseg_init_seg(bank, pagearray);
    447 
    448 		/* set up page array pointers */
    449 		pagearray += n;
    450 		pagecount -= n;
    451 	}
    452 
    453 	uvm.page_init_done = true;
    454 }
    455 
    456 ATF_TC(uvm_physseg_plug);
    457 ATF_TC_HEAD(uvm_physseg_plug, tc)
    458 {
    459 	atf_tc_set_md_var(tc, "descr",
    460 	    "Test plug functionality.");
    461 }
    462 /* Note: We only do the second boot time plug if VM_PHYSSEG_MAX > 1 */
    463 ATF_TC_BODY(uvm_physseg_plug, tc)
    464 {
    465 	int nentries = 0; /* Count of entries via plug done so far */
    466 	uvm_physseg_t upm1;
    467 #if VM_PHYSSEG_MAX > 2
    468 	uvm_physseg_t upm2;
    469 #endif
    470 
    471 #if VM_PHYSSEG_MAX > 1
    472 	uvm_physseg_t upm3;
    473 #endif
    474 	uvm_physseg_t upm4;
    475 	psize_t npages1 = (VALID_END_PFN_1 - VALID_START_PFN_1);
    476 	psize_t npages2 = (VALID_END_PFN_2 - VALID_START_PFN_2);
    477 	psize_t npages3 = (VALID_END_PFN_3 - VALID_START_PFN_3);
    478 	psize_t npages4 = (VALID_END_PFN_4 - VALID_START_PFN_4);
    479 	struct vm_page *pgs, *slab = malloc(sizeof(struct vm_page) * (npages1
    480 #if VM_PHYSSEG_MAX > 2
    481 		+ npages2
    482 #endif
    483 		+ npages3));
    484 
    485 	/* Fake early boot */
    486 
    487 	setup();
    488 
    489 	/* Vanilla plug x 2 */
    490 	ATF_REQUIRE_EQ(uvm_physseg_plug(VALID_START_PFN_1, npages1, &upm1), true);
    491 	ATF_REQUIRE_EQ(++nentries, uvm_physseg_get_entries());
    492 	ATF_REQUIRE_EQ(0, uvmexp.npages);
    493 
    494 #if VM_PHYSSEG_MAX > 2
    495 	ATF_REQUIRE_EQ(uvm_physseg_plug(VALID_START_PFN_2, npages2, &upm2), true);
    496 	ATF_REQUIRE_EQ(++nentries, uvm_physseg_get_entries());
    497 	ATF_REQUIRE_EQ(0, uvmexp.npages);
    498 #endif
    499 	/* Post boot: Fake all segments and pages accounted for. */
    500 	uvm_page_init_fake(slab, npages1 + npages2 + npages3);
    501 
    502 	ATF_CHECK_EQ(npages1
    503 #if VM_PHYSSEG_MAX > 2
    504 	    + npages2
    505 #endif
    506 	    , INT_TO_PSIZE_T(uvmexp.npages));
    507 #if VM_PHYSSEG_MAX > 1
    508 	/* Scavenge plug - goes into the same slab */
    509 	ATF_REQUIRE_EQ(uvm_physseg_plug(VALID_START_PFN_3, npages3, &upm3), true);
    510 	ATF_REQUIRE_EQ(++nentries, uvm_physseg_get_entries());
    511 	ATF_REQUIRE_EQ(npages1
    512 #if VM_PHYSSEG_MAX > 2
    513 	    + npages2
    514 #endif
    515 	    + npages3, INT_TO_PSIZE_T(uvmexp.npages));
    516 
    517 	/* Scavenge plug should fit right in the slab */
    518 	pgs = uvm_physseg_get_pg(upm3, 0);
    519 	ATF_REQUIRE(pgs > slab && pgs < (slab + npages1 + npages2 + npages3));
    520 #endif
    521 	/* Hot plug - goes into a brand new slab */
    522 	ATF_REQUIRE_EQ(uvm_physseg_plug(VALID_START_PFN_4, npages4, &upm4), true);
    523 	/* The hot plug slab should have nothing to do with the original slab */
    524 	pgs = uvm_physseg_get_pg(upm4, 0);
    525 	ATF_REQUIRE(pgs < slab || pgs >= (slab + npages1
    526 #if VM_PHYSSEG_MAX > 2
    527 		+ npages2
    528 #endif
    529 		+ npages3));
    530 
    531 }
    532 ATF_TC(uvm_physseg_unplug);
    533 ATF_TC_HEAD(uvm_physseg_unplug, tc)
    534 {
    535 	atf_tc_set_md_var(tc, "descr",
    536 	    "Test unplug functionality.");
    537 }
    538 ATF_TC_BODY(uvm_physseg_unplug, tc)
    539 {
    540 	paddr_t pa = 0;
    541 
    542 	psize_t npages1 = (VALID_END_PFN_1 - VALID_START_PFN_1);
    543 	psize_t npages2 = (VALID_END_PFN_2 - VALID_START_PFN_2);
    544 	psize_t npages3 = (VALID_END_PFN_3 - VALID_START_PFN_3);
    545 
    546 	struct vm_page *slab = malloc(sizeof(struct vm_page) * (npages1 + npages2 + npages3));
    547 
    548 	uvm_physseg_t upm;
    549 
    550 	/* Boot time */
    551 	setup();
    552 
    553 	/* We start with zero segments */
    554 	ATF_REQUIRE_EQ(true, uvm_physseg_plug(atop(0), atop(ONE_MEGABYTE), NULL));
    555 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
    556 	/* Do we have an arbitrary offset in there ? */
    557 	uvm_physseg_find(atop(TWOFIFTYSIX_KILO), &pa);
    558 	ATF_REQUIRE_EQ(pa, atop(TWOFIFTYSIX_KILO));
    559 	ATF_REQUIRE_EQ(0, uvmexp.npages); /* Boot time sanity */
    560 
    561 #if VM_PHYSSEG_MAX == 1
    562 	/*
    563 	 * This is the curious case at boot time, of having one
    564 	 * extent(9) static entry per segment, which means that a
    565 	 * fragmenting unplug will fail.
    566 	 */
    567 	atf_tc_expect_signal(SIGABRT, "fragmenting unplug for single segment");
    568 
    569 	/*
    570 	 * In order to test the fragmenting cases, please set
    571 	 * VM_PHYSSEG_MAX > 1
    572 	 */
    573 #endif
    574 	/* Now let's unplug from the middle */
    575 	ATF_REQUIRE_EQ(true, uvm_physseg_unplug(atop(TWOFIFTYSIX_KILO), atop(FIVEONETWO_KILO)));
    576 	/* verify that a gap exists at TWOFIFTYSIX_KILO */
    577 	pa = 0; /* reset */
    578 	uvm_physseg_find(atop(TWOFIFTYSIX_KILO), &pa);
    579 	ATF_REQUIRE_EQ(pa, 0);
    580 
    581 	/* Post boot: Fake all segments and pages accounted for. */
    582 	uvm_page_init_fake(slab, npages1 + npages2 + npages3);
    583 	/* Account for the unplug */
    584 	ATF_CHECK_EQ(atop(FIVEONETWO_KILO), uvmexp.npages);
    585 
    586 	/* Original entry should fragment into two */
    587 	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
    588 
    589 	upm = uvm_physseg_find(atop(TWOFIFTYSIX_KILO + FIVEONETWO_KILO), NULL);
    590 
    591 	ATF_REQUIRE(uvm_physseg_valid_p(upm));
    592 
    593 	/* Now unplug the tail fragment - should swallow the complete entry */
    594 	ATF_REQUIRE_EQ(true, uvm_physseg_unplug(atop(TWOFIFTYSIX_KILO + FIVEONETWO_KILO), atop(TWOFIFTYSIX_KILO)));
    595 
    596 	/* The "swallow" above should have invalidated the handle */
    597 	ATF_REQUIRE_EQ(false, uvm_physseg_valid_p(upm));
    598 
    599 	/* Only the first one is left now */
    600 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
    601 
    602 	/* Unplug from the back */
    603 	ATF_REQUIRE_EQ(true, uvm_physseg_unplug(atop(ONETWENTYEIGHT_KILO), atop(ONETWENTYEIGHT_KILO)));
    604 	/* Shouldn't change the number of segments */
    605 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
    606 
    607 	/* Unplug from the front */
    608 	ATF_REQUIRE_EQ(true, uvm_physseg_unplug(0, atop(SIXTYFOUR_KILO)));
    609 	/* Shouldn't change the number of segments */
    610 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
    611 
    612 	/* Unplugging the final fragment should fail */
    613 	atf_tc_expect_signal(SIGABRT, "Unplugging the last segment");
    614 	ATF_REQUIRE_EQ(true, uvm_physseg_unplug(atop(SIXTYFOUR_KILO), atop(SIXTYFOUR_KILO)));
    615 }
    616 
    617 
    618 /* <---- end Tests for Internal functions ----> */
    619 
    620 /* Tests for functions exported via uvm_physseg.h */
    621 ATF_TC(uvm_physseg_init);
    622 ATF_TC_HEAD(uvm_physseg_init, tc)
    623 {
    624 	atf_tc_set_md_var(tc, "descr", "Tests if the basic uvm_page_init() call\
    625 	    initializes the vm_physmem struct which holds the rb_tree.");
    626 }
    627 ATF_TC_BODY(uvm_physseg_init, tc)
    628 {
    629 	uvm_physseg_init();
    630 
    631 	ATF_REQUIRE_EQ(0, uvm_physseg_get_entries());
    632 }
    633 
    634 ATF_TC(uvm_page_physload_preload);
    635 ATF_TC_HEAD(uvm_page_physload_preload, tc)
    636 {
    637 	atf_tc_set_md_var(tc, "descr", "Tests if the basic uvm_page_physload() \
    638 	    call works without a panic() in a preload scenario.");
    639 }
    640 ATF_TC_BODY(uvm_page_physload_preload, tc)
    641 {
    642 	uvm_physseg_t upm;
    643 
    644 	setup();
    645 
    646 	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
    647 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
    648 
    649 	/* Should return a valid handle */
    650 	ATF_REQUIRE(uvm_physseg_valid_p(upm));
    651 
    652 	/* No pages should be allocated yet */
    653 	ATF_REQUIRE_EQ(0, uvmexp.npages);
    654 
    655 	/* After the first call one segment should exist */
    656 	ATF_CHECK_EQ(1, uvm_physseg_get_entries());
    657 
    658 	/* Insert more than one segment iff VM_PHYSSEG_MAX > 1 */
    659 #if VM_PHYSSEG_MAX > 1
    660 	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
    661 	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
    662 
    663 	/* Should return a valid handle */
    664 	ATF_REQUIRE(uvm_physseg_valid_p(upm));
    665 
    666 	ATF_REQUIRE_EQ(0, uvmexp.npages);
    667 
    668 	/* After the second call two segments should exist */
    669 	ATF_CHECK_EQ(2, uvm_physseg_get_entries());
    670 #endif
    671 }
    672 
    673 ATF_TC(uvm_page_physload_postboot);
    674 ATF_TC_HEAD(uvm_page_physload_postboot, tc)
    675 {
    676 	atf_tc_set_md_var(tc, "descr", "Tests if the basic uvm_page_physload() \
    677 	     panic()s in a post boot scenario.");
    678 }
    679 ATF_TC_BODY(uvm_page_physload_postboot, tc)
    680 {
    681 	uvm_physseg_t upm;
    682 
    683 	psize_t npages1 = (VALID_END_PFN_1 - VALID_START_PFN_1);
    684 	psize_t npages2 = (VALID_END_PFN_2 - VALID_START_PFN_2);
    685 
    686 	struct vm_page *slab = malloc(sizeof(struct vm_page) * (npages1 + npages2));
    687 
    688 	setup();
    689 
    690 	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
    691 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
    692 
    693 	/* Should return a valid handle */
    694 	ATF_REQUIRE(uvm_physseg_valid_p(upm));
    695 
    696 	/* No pages should be allocated yet */
    697 	ATF_REQUIRE_EQ(0, uvmexp.npages);
    698 
    699 	/* After the first call one segment should exist */
    700 	ATF_CHECK_EQ(1, uvm_physseg_get_entries());
    701 
    702 	/* Post boot: Fake all segments and pages accounted for. */
    703 	uvm_page_init_fake(slab, npages1 + npages2);
    704 
    705 	atf_tc_expect_signal(SIGABRT,
    706 	    "uvm_page_physload() called post boot");
    707 
    708 	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
    709 	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
    710 
    711 	/* Should return a valid handle */
    712 	ATF_REQUIRE(uvm_physseg_valid_p(upm));
    713 
    714 	ATF_REQUIRE_EQ(npages1 + npages2, INT_TO_PSIZE_T(uvmexp.npages));
    715 
    716 	/* After the second call two segments should exist */
    717 	ATF_CHECK_EQ(2, uvm_physseg_get_entries());
    718 }
    719 
    720 ATF_TC(uvm_physseg_handle_immutable);
    721 ATF_TC_HEAD(uvm_physseg_handle_immutable, tc)
    722 {
    723 	atf_tc_set_md_var(tc, "descr", "Tests if the uvm_physseg_t handle is \
    724 	    immutable.");
    725 }
    726 ATF_TC_BODY(uvm_physseg_handle_immutable, tc)
    727 {
    728 	uvm_physseg_t upm;
    729 
    730 	/* We insert the segments in out of order */
    731 
    732 	setup();
    733 
    734 	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
    735 	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
    736 
    737 	ATF_REQUIRE_EQ(0, uvmexp.npages);
    738 
    739 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
    740 
    741 	ATF_CHECK_EQ(UVM_PHYSSEG_TYPE_INVALID_EMPTY, uvm_physseg_get_prev(upm));
    742 
    743 	/* Insert more than one segment iff VM_PHYSSEG_MAX > 1 */
    744 #if VM_PHYSSEG_MAX > 1
    745 	uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
    746 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
    747 
    748 	ATF_REQUIRE_EQ(0, uvmexp.npages);
    749 
    750 	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
    751 
    752 	/* Fetch Previous, we inserted a lower value */
    753 	upm = uvm_physseg_get_prev(upm);
    754 
    755 #if !defined(UVM_HOTPLUG)
    756 	/*
    757 	 * This test is going to fail for the Array Implementation but is
    758 	 * expected to pass in the RB Tree implementation.
    759 	 */
    760 	/* Failure can be expected iff there are more than one handles */
    761 	atf_tc_expect_fail("Mutable handle in static array impl.");
    762 #endif
    763 	ATF_CHECK(UVM_PHYSSEG_TYPE_INVALID_EMPTY != upm);
    764 	ATF_CHECK_EQ(VALID_START_PFN_1, uvm_physseg_get_start(upm));
    765 	ATF_CHECK_EQ(VALID_END_PFN_1, uvm_physseg_get_end(upm));
    766 #endif
    767 }
    768 
    769 ATF_TC(uvm_physseg_seg_chomp_slab);
    770 ATF_TC_HEAD(uvm_physseg_seg_chomp_slab, tc)
    771 {
    772 	atf_tc_set_md_var(tc, "descr", "The slab import code.()");
    773 
    774 }
    775 ATF_TC_BODY(uvm_physseg_seg_chomp_slab, tc)
    776 {
    777 	int err;
    778 	size_t i;
    779 	struct uvm_physseg *seg;
    780 	struct vm_page *slab, *pgs;
    781 	const size_t npages = UVM_PHYSSEG_BOOT_UNPLUG_MAX; /* Number of pages */
    782 
    783 	setup();
    784 
    785 	/* This is boot time */
    786 	slab = malloc(sizeof(struct vm_page) * npages * 2);
    787 
    788 	seg = uvm_physseg_alloc(sizeof(struct uvm_physseg));
    789 
    790 	uvm_physseg_seg_chomp_slab(PHYSSEG_NODE_TO_HANDLE(seg), slab, npages * 2);
    791 
    792 	/* Should be able to allocate two 128 * sizeof(*slab) */
    793 	ATF_REQUIRE_EQ(0, extent_alloc(seg->ext, sizeof(*slab), 1, 0, EX_BOUNDZERO, (void *)&pgs));
    794 	err = extent_free(seg->ext, (u_long) pgs, sizeof(*slab), EX_BOUNDZERO);
    795 
    796 #if VM_PHYSSEG_MAX == 1
    797 	/*
    798 	 * free() needs an extra region descriptor, but we only have
    799 	 * one! The classic alloc() at free() problem
    800 	 */
    801 
    802 	ATF_REQUIRE_EQ(ENOMEM, err);
    803 #else
    804 	/* Try alloc/free at static time */
    805 	for (i = 0; i < npages; i++) {
    806 		ATF_REQUIRE_EQ(0, extent_alloc(seg->ext, sizeof(*slab), 1, 0, EX_BOUNDZERO, (void *)&pgs));
    807 		err = extent_free(seg->ext, (u_long) pgs, sizeof(*slab), EX_BOUNDZERO);
    808 		ATF_REQUIRE_EQ(0, err);
    809 	}
    810 #endif
    811 
    812 	/* Now setup post boot */
    813 	uvm.page_init_done = true;
    814 
    815 	uvm_physseg_seg_chomp_slab(PHYSSEG_NODE_TO_HANDLE(seg), slab, npages * 2);
    816 
    817 	/* Try alloc/free after uvm_page.c:uvm_page_init() as well */
    818 	for (i = 0; i < npages; i++) {
    819 		ATF_REQUIRE_EQ(0, extent_alloc(seg->ext, sizeof(*slab), 1, 0, EX_BOUNDZERO, (void *)&pgs));
    820 		err = extent_free(seg->ext, (u_long) pgs, sizeof(*slab), EX_BOUNDZERO);
    821 		ATF_REQUIRE_EQ(0, err);
    822 	}
    823 
    824 }
    825 
    826 ATF_TC(uvm_physseg_alloc_from_slab);
    827 ATF_TC_HEAD(uvm_physseg_alloc_from_slab, tc)
    828 {
    829 	atf_tc_set_md_var(tc, "descr", "The slab alloc code.()");
    830 
    831 }
    832 ATF_TC_BODY(uvm_physseg_alloc_from_slab, tc)
    833 {
    834 	struct uvm_physseg *seg;
    835 	struct vm_page *slab, *pgs;
    836 	const size_t npages = UVM_PHYSSEG_BOOT_UNPLUG_MAX; /* Number of pages */
    837 
    838 	setup();
    839 
    840 	/* This is boot time */
    841 	slab = malloc(sizeof(struct vm_page) * npages * 2);
    842 
    843 	seg = uvm_physseg_alloc(sizeof(struct uvm_physseg));
    844 
    845 	uvm_physseg_seg_chomp_slab(PHYSSEG_NODE_TO_HANDLE(seg), slab, npages * 2);
    846 
    847 	pgs = uvm_physseg_seg_alloc_from_slab(PHYSSEG_NODE_TO_HANDLE(seg), npages);
    848 
    849 	ATF_REQUIRE(pgs != NULL);
    850 
    851 	/* Now setup post boot */
    852 	uvm.page_init_done = true;
    853 
    854 #if VM_PHYSSEG_MAX > 1
    855 	pgs = uvm_physseg_seg_alloc_from_slab(PHYSSEG_NODE_TO_HANDLE(seg), npages);
    856 	ATF_REQUIRE(pgs != NULL);
    857 #endif
    858 	atf_tc_expect_fail("alloc beyond extent");
    859 
    860 	pgs = uvm_physseg_seg_alloc_from_slab(PHYSSEG_NODE_TO_HANDLE(seg), npages);
    861 	ATF_REQUIRE(pgs != NULL);
    862 }
    863 
    864 ATF_TC(uvm_physseg_init_seg);
    865 ATF_TC_HEAD(uvm_physseg_init_seg, tc)
    866 {
    867 	atf_tc_set_md_var(tc, "descr", "Tests if uvm_physseg_init_seg adds pages to"
    868 	    "uvmexp.npages");
    869 }
    870 ATF_TC_BODY(uvm_physseg_init_seg, tc)
    871 {
    872 	struct uvm_physseg *seg;
    873 	struct vm_page *slab, *pgs;
    874 	const size_t npages = UVM_PHYSSEG_BOOT_UNPLUG_MAX; /* Number of pages */
    875 
    876 	setup();
    877 
    878 	/* This is boot time */
    879 	slab = malloc(sizeof(struct vm_page) * npages * 2);
    880 
    881 	seg = uvm_physseg_alloc(sizeof(struct uvm_physseg));
    882 
    883 	uvm_physseg_seg_chomp_slab(PHYSSEG_NODE_TO_HANDLE(seg), slab, npages * 2);
    884 
    885 	pgs = uvm_physseg_seg_alloc_from_slab(PHYSSEG_NODE_TO_HANDLE(seg), npages);
    886 
    887 	ATF_REQUIRE_EQ(0, uvmexp.npages);
    888 
    889 	seg->start = 0;
    890 	seg->end = npages;
    891 
    892 	seg->avail_start = 0;
    893 	seg->avail_end = npages;
    894 
    895 	uvm_physseg_init_seg(PHYSSEG_NODE_TO_HANDLE(seg), pgs);
    896 
    897 	ATF_REQUIRE_EQ(npages, INT_TO_PSIZE_T(uvmexp.npages));
    898 }
    899 
    900 #if 0
    901 ATF_TC(uvm_physseg_init_seg);
    902 ATF_TC_HEAD(uvm_physseg_init_seg, tc)
    903 {
    904 	atf_tc_set_md_var(tc, "descr", "Tests if the basic uvm_page_physload() \
    905 	    call works without a panic() after Segment is inited.");
    906 }
    907 ATF_TC_BODY(uvm_physseg_init_seg, tc)
    908 {
    909 	uvm_physseg_t upm;
    910 	psize_t npages = (VALID_END_PFN_1 - VALID_START_PFN_1);
    911 	struct vm_page *pgs = malloc(sizeof(struct vm_page) * npages);
    912 
    913 	setup();
    914 	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
    915 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
    916 
    917 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
    918 
    919 	ATF_CHECK_EQ(0, uvmexp.npages);
    920 
    921 	/*
    922 	 * Boot time physplug needs explicit external init,
    923 	 * Duplicate what uvm_page.c:uvm_page_init() does.
    924 	 * Note: not everything uvm_page_init() does gets done here.
    925 	 * Read the source.
    926 	 */
    927 	/* suck in backing slab, initialise extent. */
    928 	uvm_physseg_seg_chomp_slab(upm, pgs, npages);
    929 
    930 	/*
    931 	 * Actual pgs[] allocation, from extent.
    932 	 */
    933 	uvm_physseg_alloc_from_slab(upm, npages);
    934 
    935 	/* Now we initialize the segment */
    936 	uvm_physseg_init_seg(upm, pgs);
    937 
    938 	/* Done with boot simulation */
    939 	extent_init();
    940 	uvm.page_init_done = true;
    941 
    942 	/* We have total memory of 1MB */
    943 	ATF_CHECK_EQ(PAGE_COUNT_1M, uvmexp.npages);
    944 
    945 	upm =uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
    946 	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
    947 	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
    948 
    949 	/* We added another 1MB so PAGE_COUNT_1M + PAGE_COUNT_1M */
    950 	ATF_CHECK_EQ(PAGE_COUNT_1M + PAGE_COUNT_1M, uvmexp.npages);
    951 
    952 }
    953 #endif
    954 
    955 ATF_TC(uvm_physseg_get_start);
    956 ATF_TC_HEAD(uvm_physseg_get_start, tc)
    957 {
    958 	atf_tc_set_md_var(tc, "descr", "Tests if the start PFN is returned \
    959 	    correctly from a segment created via uvm_page_physload().");
    960 }
    961 ATF_TC_BODY(uvm_physseg_get_start, tc)
    962 {
    963 	uvm_physseg_t upm;
    964 
    965 	/* Fake early boot */
    966 	setup();
    967 
    968 	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
    969 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
    970 
    971 	ATF_REQUIRE_EQ(0, uvmexp.npages);
    972 
    973 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
    974 
    975 	ATF_CHECK_EQ(VALID_START_PFN_1, uvm_physseg_get_start(upm));
    976 
    977 	/* This test will be triggered only if there are 2 or more segments. */
    978 #if VM_PHYSSEG_MAX > 1
    979 	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
    980 	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
    981 
    982 	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
    983 
    984 	ATF_REQUIRE_EQ(0, uvmexp.npages);
    985 
    986 	ATF_CHECK_EQ(VALID_START_PFN_2, uvm_physseg_get_start(upm));
    987 #endif
    988 }
    989 
    990 ATF_TC(uvm_physseg_get_start_invalid);
    991 ATF_TC_HEAD(uvm_physseg_get_start_invalid, tc)
    992 {
    993 	atf_tc_set_md_var(tc, "descr", "Tests the invalid / error conditions \
    994 	    correctly when uvm_physseg_get_start() is called with invalid \
    995 	    parameter values.");
    996 }
    997 ATF_TC_BODY(uvm_physseg_get_start_invalid, tc)
    998 {
    999 	/* Check for pgs == NULL */
   1000 	setup();
   1001 	uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1002 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1003 
   1004 	/* Force other check conditions */
   1005 	uvm.page_init_done = true;
   1006 
   1007 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1008 
   1009 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   1010 
   1011 	ATF_REQUIRE_EQ(true, uvm.page_init_done);
   1012 
   1013 	/* Invalid uvm_physseg_t */
   1014 	ATF_CHECK_EQ((paddr_t) -1,
   1015 	    uvm_physseg_get_start(UVM_PHYSSEG_TYPE_INVALID));
   1016 }
   1017 
   1018 ATF_TC(uvm_physseg_get_end);
   1019 ATF_TC_HEAD(uvm_physseg_get_end, tc)
   1020 {
   1021 	atf_tc_set_md_var(tc, "descr", "Tests if the end PFN is returned \
   1022 	    correctly from a segment created via uvm_page_physload().");
   1023 }
   1024 ATF_TC_BODY(uvm_physseg_get_end, tc)
   1025 {
   1026 	uvm_physseg_t upm;
   1027 
   1028 	setup();
   1029 	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1030 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1031 
   1032 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1033 
   1034 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   1035 
   1036 	ATF_CHECK_EQ(VALID_END_PFN_1, uvm_physseg_get_end(upm));
   1037 
   1038 	/* This test will be triggered only if there are 2 or more segments. */
   1039 #if VM_PHYSSEG_MAX > 1
   1040 	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
   1041 	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
   1042 
   1043 	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
   1044 
   1045 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1046 
   1047 	ATF_CHECK_EQ(VALID_END_PFN_2, uvm_physseg_get_end(upm));
   1048 #endif
   1049 }
   1050 
   1051 ATF_TC(uvm_physseg_get_end_invalid);
   1052 ATF_TC_HEAD(uvm_physseg_get_end_invalid, tc)
   1053 {
   1054 	atf_tc_set_md_var(tc, "descr", "Tests the invalid / error conditions \
   1055 	    correctly when uvm_physseg_get_end() is called with invalid \
   1056 	    parameter values.");
   1057 }
   1058 ATF_TC_BODY(uvm_physseg_get_end_invalid, tc)
   1059 {
   1060 	/* Check for pgs == NULL */
   1061 	setup();
   1062 	uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1063 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1064 
   1065 	/* Force other check conditions */
   1066 	uvm.page_init_done = true;
   1067 
   1068 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1069 
   1070 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   1071 
   1072 	ATF_REQUIRE_EQ(true, uvm.page_init_done);
   1073 
   1074 	/* Invalid uvm_physseg_t */
   1075 	ATF_CHECK_EQ((paddr_t) -1,
   1076 	    uvm_physseg_get_end(UVM_PHYSSEG_TYPE_INVALID));
   1077 }
   1078 
   1079 ATF_TC(uvm_physseg_get_avail_start);
   1080 ATF_TC_HEAD(uvm_physseg_get_avail_start, tc)
   1081 {
   1082 	atf_tc_set_md_var(tc, "descr", "Tests if the avail_start PFN is \
   1083 	    returned correctly from a segment created via uvm_page_physload().");
   1084 }
   1085 ATF_TC_BODY(uvm_physseg_get_avail_start, tc)
   1086 {
   1087 	uvm_physseg_t upm;
   1088 
   1089 	setup();
   1090 	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1091 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1092 
   1093 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1094 
   1095 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   1096 
   1097 	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_1, uvm_physseg_get_avail_start(upm));
   1098 
   1099 	/* This test will be triggered only if there are 2 or more segments. */
   1100 #if VM_PHYSSEG_MAX > 1
   1101 	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
   1102 	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
   1103 
   1104 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1105 
   1106 	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
   1107 
   1108 	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_2, uvm_physseg_get_avail_start(upm));
   1109 #endif
   1110 }
   1111 
   1112 ATF_TC(uvm_physseg_get_avail_start_invalid);
   1113 ATF_TC_HEAD(uvm_physseg_get_avail_start_invalid, tc)
   1114 {
   1115 	atf_tc_set_md_var(tc, "descr", "Tests the invalid / error conditions \
   1116 	    correctly when uvm_physseg_get_avail_start() is called with invalid\
   1117 	    parameter values.");
   1118 }
   1119 ATF_TC_BODY(uvm_physseg_get_avail_start_invalid, tc)
   1120 {
   1121 	/* Check for pgs == NULL */
   1122 	setup();
   1123 	uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1124 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1125 
   1126 	/* Force other check conditions */
   1127 	uvm.page_init_done = true;
   1128 
   1129 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1130 
   1131 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   1132 
   1133 	ATF_REQUIRE_EQ(true, uvm.page_init_done);
   1134 
   1135 	/* Invalid uvm_physseg_t */
   1136 	ATF_CHECK_EQ((paddr_t) -1,
   1137 	    uvm_physseg_get_avail_start(UVM_PHYSSEG_TYPE_INVALID));
   1138 }
   1139 
   1140 ATF_TC(uvm_physseg_get_avail_end);
   1141 ATF_TC_HEAD(uvm_physseg_get_avail_end, tc)
   1142 {
   1143 	atf_tc_set_md_var(tc, "descr", "Tests if the avail_end PFN is \
   1144 	    returned correctly from a segment created via uvm_page_physload().");
   1145 }
   1146 ATF_TC_BODY(uvm_physseg_get_avail_end, tc)
   1147 {
   1148 	uvm_physseg_t upm;
   1149 
   1150 	setup();
   1151 	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1152 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1153 
   1154 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1155 
   1156 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   1157 
   1158 	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_1, uvm_physseg_get_avail_end(upm));
   1159 
   1160 	/* This test will be triggered only if there are 2 or more segments. */
   1161 #if VM_PHYSSEG_MAX > 1
   1162 	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
   1163 	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
   1164 
   1165 	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
   1166 
   1167 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1168 
   1169 	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_2, uvm_physseg_get_avail_end(upm));
   1170 #endif
   1171 }
   1172 
   1173 ATF_TC(uvm_physseg_get_avail_end_invalid);
   1174 ATF_TC_HEAD(uvm_physseg_get_avail_end_invalid, tc)
   1175 {
   1176 	atf_tc_set_md_var(tc, "descr", "Tests the invalid / error conditions \
   1177 	    correctly when uvm_physseg_get_avail_end() is called with invalid\
   1178 	    parameter values.");
   1179 }
   1180 ATF_TC_BODY(uvm_physseg_get_avail_end_invalid, tc)
   1181 {
   1182 	/* Check for pgs == NULL */
   1183 	setup();
   1184 	uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1185 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1186 
   1187 	/* Force other check conditions */
   1188 	uvm.page_init_done = true;
   1189 
   1190 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1191 
   1192 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   1193 
   1194 	ATF_REQUIRE_EQ(true, uvm.page_init_done);
   1195 
   1196 	/* Invalid uvm_physseg_t */
   1197 	ATF_CHECK_EQ((paddr_t) -1,
   1198 	    uvm_physseg_get_avail_end(UVM_PHYSSEG_TYPE_INVALID));
   1199 }
   1200 
   1201 ATF_TC(uvm_physseg_get_next);
   1202 ATF_TC_HEAD(uvm_physseg_get_next, tc)
   1203 {
   1204 	atf_tc_set_md_var(tc, "descr", "Tests the pointer values for next \
   1205 	    segment using the uvm_physseg_get_next() call.");
   1206 }
   1207 ATF_TC_BODY(uvm_physseg_get_next, tc)
   1208 {
   1209 	uvm_physseg_t upm;
   1210 #if VM_PHYSSEG_MAX > 1
   1211 	uvm_physseg_t upm_next;
   1212 #endif
   1213 
   1214 	/* We insert the segments in ascending order */
   1215 
   1216 	setup();
   1217 	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1218 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1219 
   1220 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1221 
   1222 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   1223 
   1224 	ATF_CHECK_EQ(UVM_PHYSSEG_TYPE_INVALID_OVERFLOW,
   1225 	    uvm_physseg_get_next(upm));
   1226 
   1227 	/* This test will be triggered only if there are 2 or more segments. */
   1228 #if VM_PHYSSEG_MAX > 1
   1229 	upm_next = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
   1230 	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
   1231 
   1232 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1233 
   1234 	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
   1235 
   1236 	upm = uvm_physseg_get_next(upm); /* Fetch Next */
   1237 
   1238 	ATF_CHECK_EQ(upm_next, upm);
   1239 	ATF_CHECK_EQ(VALID_START_PFN_2, uvm_physseg_get_start(upm));
   1240 	ATF_CHECK_EQ(VALID_END_PFN_2, uvm_physseg_get_end(upm));
   1241 #endif
   1242 
   1243 	/* This test will be triggered only if there are 3 or more segments. */
   1244 #if VM_PHYSSEG_MAX > 2
   1245 	upm_next = uvm_page_physload(VALID_START_PFN_3, VALID_END_PFN_3,
   1246 	    VALID_AVAIL_START_PFN_3, VALID_AVAIL_END_PFN_3, VM_FREELIST_DEFAULT);
   1247 
   1248 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1249 
   1250 	ATF_REQUIRE_EQ(3, uvm_physseg_get_entries());
   1251 
   1252 	upm = uvm_physseg_get_next(upm); /* Fetch Next */
   1253 
   1254 	ATF_CHECK_EQ(upm_next, upm);
   1255 	ATF_CHECK_EQ(VALID_START_PFN_3, uvm_physseg_get_start(upm));
   1256 	ATF_CHECK_EQ(VALID_END_PFN_3, uvm_physseg_get_end(upm));
   1257 #endif
   1258 }
   1259 
   1260 ATF_TC(uvm_physseg_get_next_invalid);
   1261 ATF_TC_HEAD(uvm_physseg_get_next_invalid, tc)
   1262 {
   1263 	atf_tc_set_md_var(tc, "descr", "Tests the invalid / error conditions \
   1264 	    correctly when uvm_physseg_get_next() is called with invalid \
   1265 	    parameter values.");
   1266 }
   1267 ATF_TC_BODY(uvm_physseg_get_next_invalid, tc)
   1268 {
   1269 	uvm_physseg_t upm = UVM_PHYSSEG_TYPE_INVALID;
   1270 
   1271 	ATF_CHECK_EQ(UVM_PHYSSEG_TYPE_INVALID, uvm_physseg_get_next(upm));
   1272 }
   1273 
   1274 ATF_TC(uvm_physseg_get_prev);
   1275 ATF_TC_HEAD(uvm_physseg_get_prev, tc)
   1276 {
   1277 	atf_tc_set_md_var(tc, "descr", "Tests the pointer values for previous \
   1278 	    segment using the uvm_physseg_get_prev() call.");
   1279 }
   1280 ATF_TC_BODY(uvm_physseg_get_prev, tc)
   1281 {
   1282 #if VM_PHYSSEG_MAX > 1
   1283 	uvm_physseg_t upm;
   1284 #endif
   1285 	uvm_physseg_t upm_prev;
   1286 
   1287 
   1288 	setup();
   1289 	upm_prev = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1290 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1291 
   1292 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1293 
   1294 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   1295 
   1296 	ATF_CHECK_EQ(UVM_PHYSSEG_TYPE_INVALID_EMPTY,
   1297 	    uvm_physseg_get_prev(upm_prev));
   1298 
   1299 	/* This test will be triggered only if there are 2 or more segments. */
   1300 #if VM_PHYSSEG_MAX > 1
   1301 	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
   1302 	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
   1303 
   1304 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1305 
   1306 	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
   1307 
   1308 	/* Fetch Previous, we inserted a lower value */
   1309 	upm = uvm_physseg_get_prev(upm);
   1310 
   1311 	ATF_CHECK_EQ(upm_prev, upm);
   1312 	ATF_CHECK_EQ(VALID_START_PFN_1, uvm_physseg_get_start(upm));
   1313 	ATF_CHECK_EQ(VALID_END_PFN_1, uvm_physseg_get_end(upm));
   1314 #endif
   1315 
   1316 	/* This test will be triggered only if there are 3 or more segments. */
   1317 #if VM_PHYSSEG_MAX > 2
   1318 	uvm_page_physload(VALID_START_PFN_3, VALID_END_PFN_3,
   1319 	    VALID_AVAIL_START_PFN_3, VALID_AVAIL_END_PFN_3, VM_FREELIST_DEFAULT);
   1320 
   1321 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1322 
   1323 	ATF_REQUIRE_EQ(3, uvm_physseg_get_entries());
   1324 
   1325 	/*
   1326 	 * This will return a UVM_PHYSSEG_TYPE_INVALID_EMPTY we are at the
   1327 	 * lowest
   1328 	 */
   1329 	upm = uvm_physseg_get_prev(upm);
   1330 
   1331 	ATF_CHECK_EQ(UVM_PHYSSEG_TYPE_INVALID_EMPTY, upm);
   1332 #endif
   1333 }
   1334 
   1335 ATF_TC(uvm_physseg_get_prev_invalid);
   1336 ATF_TC_HEAD(uvm_physseg_get_prev_invalid, tc)
   1337 {
   1338 	atf_tc_set_md_var(tc, "descr", "Tests the invalid / error conditions \
   1339 	    correctly when uvm_physseg_get_prev() is called with invalid \
   1340 	    parameter values.");
   1341 }
   1342 ATF_TC_BODY(uvm_physseg_get_prev_invalid, tc)
   1343 {
   1344 	uvm_physseg_t upm = UVM_PHYSSEG_TYPE_INVALID;
   1345 
   1346 	ATF_CHECK_EQ(UVM_PHYSSEG_TYPE_INVALID, uvm_physseg_get_prev(upm));
   1347 }
   1348 
   1349 ATF_TC(uvm_physseg_get_first);
   1350 ATF_TC_HEAD(uvm_physseg_get_first, tc)
   1351 {
   1352 	atf_tc_set_md_var(tc, "descr", "Tests the pointer values for first \
   1353 	    segment (lowest node) using the uvm_physseg_get_first() call.");
   1354 }
   1355 ATF_TC_BODY(uvm_physseg_get_first, tc)
   1356 {
   1357 	uvm_physseg_t upm = UVM_PHYSSEG_TYPE_INVALID_EMPTY;
   1358 	uvm_physseg_t upm_first;
   1359 
   1360 	/* Fake early boot */
   1361 	setup();
   1362 
   1363 	/* No nodes exist */
   1364 	ATF_CHECK_EQ(upm, uvm_physseg_get_first());
   1365 
   1366 	upm_first = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
   1367 	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
   1368 
   1369 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1370 
   1371 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   1372 
   1373 	/* Pointer to first should be the least valued node */
   1374 	upm = uvm_physseg_get_first();
   1375 	ATF_CHECK_EQ(upm_first, upm);
   1376 	ATF_CHECK_EQ(VALID_START_PFN_2, uvm_physseg_get_start(upm));
   1377 	ATF_CHECK_EQ(VALID_END_PFN_2, uvm_physseg_get_end(upm));
   1378 	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_2, uvm_physseg_get_avail_start(upm));
   1379 	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_2, uvm_physseg_get_avail_end(upm));
   1380 
   1381 	/* This test will be triggered only if there are 2 or more segments. */
   1382 #if VM_PHYSSEG_MAX > 1
   1383 	/* Insert a node of lesser value */
   1384 	upm_first = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1385 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1386 
   1387 	ATF_CHECK_EQ(0, uvmexp.npages);
   1388 
   1389 	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
   1390 
   1391 	/* Pointer to first should be the least valued node */
   1392 	upm = uvm_physseg_get_first();
   1393 	ATF_CHECK_EQ(upm_first, upm);
   1394 	ATF_CHECK_EQ(VALID_START_PFN_1, uvm_physseg_get_start(upm));
   1395 	ATF_CHECK_EQ(VALID_END_PFN_1, uvm_physseg_get_end(upm));
   1396 	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_1, uvm_physseg_get_avail_start(upm));
   1397 	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_1, uvm_physseg_get_avail_end(upm));
   1398 #endif
   1399 
   1400 	/* This test will be triggered only if there are 3 or more segments. */
   1401 #if VM_PHYSSEG_MAX > 2
   1402 	/* Insert a node of higher value */
   1403 	upm_first =uvm_page_physload(VALID_START_PFN_3, VALID_END_PFN_3,
   1404 	    VALID_AVAIL_START_PFN_3, VALID_AVAIL_END_PFN_3, VM_FREELIST_DEFAULT);
   1405 
   1406 	ATF_CHECK_EQ(0, uvmexp.npages);
   1407 
   1408 	ATF_REQUIRE_EQ(3, uvm_physseg_get_entries());
   1409 
   1410 	/* Pointer to first should be the least valued node */
   1411 	upm = uvm_physseg_get_first();
   1412 	ATF_CHECK(upm_first != upm);
   1413 	ATF_CHECK_EQ(VALID_START_PFN_1, uvm_physseg_get_start(upm));
   1414 	ATF_CHECK_EQ(VALID_END_PFN_1, uvm_physseg_get_end(upm));
   1415 	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_1, uvm_physseg_get_avail_start(upm));
   1416 	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_1, uvm_physseg_get_avail_end(upm));
   1417 #endif
   1418 }
   1419 
   1420 ATF_TC(uvm_physseg_get_last);
   1421 ATF_TC_HEAD(uvm_physseg_get_last, tc)
   1422 {
   1423 	atf_tc_set_md_var(tc, "descr", "Tests the pointer values for last \
   1424 	    segment using the uvm_physseg_get_last() call.");
   1425 }
   1426 ATF_TC_BODY(uvm_physseg_get_last, tc)
   1427 {
   1428 	uvm_physseg_t upm = UVM_PHYSSEG_TYPE_INVALID_EMPTY;
   1429 	uvm_physseg_t upm_last;
   1430 
   1431 	setup();
   1432 
   1433 	/* No nodes exist */
   1434 	ATF_CHECK_EQ(upm, uvm_physseg_get_last());
   1435 
   1436 	upm_last = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1437 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1438 
   1439 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1440 
   1441 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   1442 
   1443 	/* Pointer to last should be the most valued node */
   1444 	upm = uvm_physseg_get_last();
   1445 	ATF_CHECK_EQ(upm_last, upm);
   1446 	ATF_CHECK_EQ(VALID_START_PFN_1, uvm_physseg_get_start(upm));
   1447 	ATF_CHECK_EQ(VALID_END_PFN_1, uvm_physseg_get_end(upm));
   1448 	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_1, uvm_physseg_get_avail_start(upm));
   1449 	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_1, uvm_physseg_get_avail_end(upm));
   1450 
   1451 	/* This test will be triggered only if there are 2 or more segments. */
   1452 #if VM_PHYSSEG_MAX > 1
   1453 	/* Insert node of greater value */
   1454 	upm_last = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
   1455 	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
   1456 
   1457 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1458 
   1459 	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
   1460 
   1461 	/* Pointer to last should be the most valued node */
   1462 	upm = uvm_physseg_get_last();
   1463 	ATF_CHECK_EQ(upm_last, upm);
   1464 	ATF_CHECK_EQ(VALID_START_PFN_2, uvm_physseg_get_start(upm));
   1465 	ATF_CHECK_EQ(VALID_END_PFN_2, uvm_physseg_get_end(upm));
   1466 	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_2, uvm_physseg_get_avail_start(upm));
   1467 	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_2, uvm_physseg_get_avail_end(upm));
   1468 #endif
   1469 
   1470 	/* This test will be triggered only if there are 3 or more segments. */
   1471 #if VM_PHYSSEG_MAX > 2
   1472 	/* Insert node of greater value */
   1473 	upm_last = uvm_page_physload(VALID_START_PFN_3, VALID_END_PFN_3,
   1474 	    VALID_AVAIL_START_PFN_3, VALID_AVAIL_END_PFN_3, VM_FREELIST_DEFAULT);
   1475 
   1476 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1477 
   1478 	ATF_REQUIRE_EQ(3, uvm_physseg_get_entries());
   1479 
   1480 	/* Pointer to last should be the most valued node */
   1481 	upm = uvm_physseg_get_last();
   1482 	ATF_CHECK_EQ(upm_last, upm);
   1483 	ATF_CHECK_EQ(VALID_START_PFN_3, uvm_physseg_get_start(upm));
   1484 	ATF_CHECK_EQ(VALID_END_PFN_3, uvm_physseg_get_end(upm));
   1485 	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_3, uvm_physseg_get_avail_start(upm));
   1486 	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_3, uvm_physseg_get_avail_end(upm));
   1487 #endif
   1488 }
   1489 
   1490 ATF_TC(uvm_physseg_valid);
   1491 ATF_TC_HEAD(uvm_physseg_valid, tc)
   1492 {
   1493 	atf_tc_set_md_var(tc, "descr", "Tests the pointer value for current \
   1494 	    segment is valid using the uvm_physseg_valid_p() call.");
   1495 }
   1496 ATF_TC_BODY(uvm_physseg_valid, tc)
   1497 {
   1498 	psize_t npages = (VALID_END_PFN_1 - VALID_START_PFN_1);
   1499 
   1500 	struct vm_page *pgs = malloc(sizeof(struct vm_page) * npages);
   1501 
   1502 	uvm_physseg_t upm;
   1503 
   1504 	setup();
   1505 	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1506 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1507 
   1508 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1509 
   1510 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   1511 
   1512 	uvm_physseg_init_seg(upm, pgs);
   1513 
   1514 	ATF_REQUIRE_EQ(PAGE_COUNT_1M, uvmexp.npages);
   1515 
   1516 	ATF_CHECK_EQ(true, uvm_physseg_valid_p(upm));
   1517 }
   1518 
   1519 ATF_TC(uvm_physseg_valid_invalid);
   1520 ATF_TC_HEAD(uvm_physseg_valid_invalid, tc)
   1521 {
   1522 	atf_tc_set_md_var(tc, "descr", "Tests the pointer value for current \
   1523 	    segment is invalid using the uvm_physseg_valid_p() call.");
   1524 }
   1525 ATF_TC_BODY(uvm_physseg_valid_invalid, tc)
   1526 {
   1527 	uvm_physseg_t upm;
   1528 
   1529 	setup();
   1530 	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1531 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1532 
   1533 	/* Force other check conditions */
   1534 	uvm.page_init_done = true;
   1535 
   1536 	ATF_REQUIRE_EQ(true, uvm.page_init_done);
   1537 
   1538 	/* Invalid uvm_physseg_t */
   1539 	ATF_CHECK_EQ(false, uvm_physseg_valid_p(UVM_PHYSSEG_TYPE_INVALID));
   1540 
   1541 	/*
   1542 	 * Without any pages initialized for segment, it is considered
   1543 	 * invalid
   1544 	 */
   1545 	ATF_CHECK_EQ(false, uvm_physseg_valid_p(upm));
   1546 }
   1547 
   1548 ATF_TC(uvm_physseg_get_highest);
   1549 ATF_TC_HEAD(uvm_physseg_get_highest, tc)
   1550 {
   1551 	atf_tc_set_md_var(tc, "descr", "Tests if the returned PFN matches  \
   1552 	    the highest PFN in use by the system.");
   1553 }
   1554 ATF_TC_BODY(uvm_physseg_get_highest, tc)
   1555 {
   1556 	setup();
   1557 	uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1558 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1559 
   1560 	/* Only one segment so highest is the current */
   1561 	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_1 - 1, uvm_physseg_get_highest_frame());
   1562 
   1563 	/* This test will be triggered only if there are 2 or more segments. */
   1564 #if VM_PHYSSEG_MAX > 1
   1565 	uvm_page_physload(VALID_START_PFN_3, VALID_END_PFN_3,
   1566 	    VALID_AVAIL_START_PFN_3, VALID_AVAIL_END_PFN_3, VM_FREELIST_DEFAULT);
   1567 
   1568 	/* PFN_3 > PFN_1 */
   1569 	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_3 - 1, uvm_physseg_get_highest_frame());
   1570 #endif
   1571 
   1572 	/* This test will be triggered only if there are 3 or more segments. */
   1573 #if VM_PHYSSEG_MAX > 2
   1574 	uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
   1575 	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
   1576 
   1577 	/* PFN_3 > PFN_2 */
   1578 	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_3 - 1, uvm_physseg_get_highest_frame());
   1579 #endif
   1580 }
   1581 
   1582 ATF_TC(uvm_physseg_get_free_list);
   1583 ATF_TC_HEAD(uvm_physseg_get_free_list, tc)
   1584 {
   1585 	atf_tc_set_md_var(tc, "descr", "Tests if the returned Free List type \
   1586 	    of a segment matches the one returned from \
   1587 	    uvm_physseg_get_free_list() call.");
   1588 }
   1589 ATF_TC_BODY(uvm_physseg_get_free_list, tc)
   1590 {
   1591 	uvm_physseg_t upm;
   1592 
   1593 	/* Fake early boot */
   1594 	setup();
   1595 
   1596 	/* Insertions are made in ascending order */
   1597 	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1598 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1599 
   1600 	ATF_CHECK_EQ(VM_FREELIST_DEFAULT, uvm_physseg_get_free_list(upm));
   1601 
   1602 	/* This test will be triggered only if there are 2 or more segments. */
   1603 #if VM_PHYSSEG_MAX > 1
   1604 	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
   1605 	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_FIRST16);
   1606 
   1607 	ATF_CHECK_EQ(VM_FREELIST_FIRST16, uvm_physseg_get_free_list(upm));
   1608 #endif
   1609 
   1610 	/* This test will be triggered only if there are 3 or more segments. */
   1611 #if VM_PHYSSEG_MAX > 2
   1612 	upm = uvm_page_physload(VALID_START_PFN_3, VALID_END_PFN_3,
   1613 	    VALID_AVAIL_START_PFN_3, VALID_AVAIL_END_PFN_3, VM_FREELIST_FIRST1G);
   1614 
   1615 	ATF_CHECK_EQ(VM_FREELIST_FIRST1G, uvm_physseg_get_free_list(upm));
   1616 #endif
   1617 }
   1618 
   1619 ATF_TC(uvm_physseg_get_start_hint);
   1620 ATF_TC_HEAD(uvm_physseg_get_start_hint, tc)
   1621 {
   1622 	atf_tc_set_md_var(tc, "descr", "Tests if the returned start_hint value \
   1623 	    of a segment matches the one returned from \
   1624 	    uvm_physseg_get_start_hint() call.");
   1625 }
   1626 ATF_TC_BODY(uvm_physseg_get_start_hint, tc)
   1627 {
   1628 	uvm_physseg_t upm;
   1629 
   1630 	setup();
   1631 	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1632 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1633 
   1634 	/* Will be Zero since no specific value is set during init */
   1635 	ATF_CHECK_EQ(0, uvm_physseg_get_start_hint(upm));
   1636 }
   1637 
   1638 ATF_TC(uvm_physseg_set_start_hint);
   1639 ATF_TC_HEAD(uvm_physseg_set_start_hint, tc)
   1640 {
   1641 	atf_tc_set_md_var(tc, "descr", "Tests if the returned start_hint value \
   1642 	    of a segment matches the one set by the \
   1643 	    uvm_physseg_set_start_hint() call.");
   1644 }
   1645 ATF_TC_BODY(uvm_physseg_set_start_hint, tc)
   1646 {
   1647 	psize_t npages = (VALID_END_PFN_1 - VALID_START_PFN_1);
   1648 
   1649 	struct vm_page *pgs = malloc(sizeof(struct vm_page) * npages);
   1650 
   1651 	uvm_physseg_t upm;
   1652 
   1653 	setup();
   1654 	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1655 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1656 
   1657 	uvm_physseg_init_seg(upm, pgs);
   1658 
   1659 	ATF_CHECK_EQ(true, uvm_physseg_set_start_hint(upm, atop(128)));
   1660 
   1661 	/* Will be atop(128) since no specific value is set above */
   1662 	ATF_CHECK_EQ(atop(128), uvm_physseg_get_start_hint(upm));
   1663 }
   1664 
   1665 ATF_TC(uvm_physseg_set_start_hint_invalid);
   1666 ATF_TC_HEAD(uvm_physseg_set_start_hint_invalid, tc)
   1667 {
   1668 	atf_tc_set_md_var(tc, "descr", "Tests if the returned value is false \
   1669 	    when an invalid segment matches the one trying to set by the \
   1670 	    uvm_physseg_set_start_hint() call.");
   1671 }
   1672 ATF_TC_BODY(uvm_physseg_set_start_hint_invalid, tc)
   1673 {
   1674 	uvm_physseg_t upm;
   1675 
   1676 	setup();
   1677 	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1678 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1679 
   1680 	/* Force other check conditions */
   1681 	uvm.page_init_done = true;
   1682 
   1683 	ATF_REQUIRE_EQ(true, uvm.page_init_done);
   1684 
   1685 	ATF_CHECK_EQ(false, uvm_physseg_set_start_hint(upm, atop(128)));
   1686 
   1687 	/*
   1688 	 * Will be Zero since no specific value is set after the init
   1689 	 * due to failure
   1690 	 */
   1691 	atf_tc_expect_signal(SIGABRT, "invalid uvm_physseg_t handle");
   1692 
   1693 	ATF_CHECK_EQ(0, uvm_physseg_get_start_hint(upm));
   1694 }
   1695 
   1696 ATF_TC(uvm_physseg_get_pg);
   1697 ATF_TC_HEAD(uvm_physseg_get_pg, tc)
   1698 {
   1699 	atf_tc_set_md_var(tc, "descr", "Tests if the returned vm_page struct \
   1700 	    is correct when fetched by uvm_physseg_get_pg() call.");
   1701 }
   1702 ATF_TC_BODY(uvm_physseg_get_pg, tc)
   1703 {
   1704 	psize_t npages = (VALID_END_PFN_1 - VALID_START_PFN_1);
   1705 
   1706 	struct vm_page *pgs = malloc(sizeof(struct vm_page) * npages);
   1707 
   1708 	struct vm_page *extracted_pg = NULL;
   1709 
   1710 	uvm_physseg_t upm;
   1711 
   1712 	setup();
   1713 	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1714 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1715 
   1716 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   1717 
   1718 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1719 
   1720 	/* Now we initialize the segment */
   1721 	uvm_physseg_init_seg(upm, pgs);
   1722 
   1723 	ATF_REQUIRE_EQ(PAGE_COUNT_1M, uvmexp.npages);
   1724 
   1725 	ATF_REQUIRE_EQ(NULL, extracted_pg);
   1726 
   1727 	/* Try fetching the 5th Page in the Segment */
   1728 	extracted_pg = uvm_physseg_get_pg(upm, 5);
   1729 
   1730 	/* Values of phys_addr is n * PAGE_SIZE where n is the page number */
   1731 	ATF_CHECK_EQ(5 * PAGE_SIZE, extracted_pg->phys_addr);
   1732 
   1733 	/* Try fetching the 113th Page in the Segment */
   1734 	extracted_pg = uvm_physseg_get_pg(upm, 113);
   1735 
   1736 	ATF_CHECK_EQ(113 * PAGE_SIZE, extracted_pg->phys_addr);
   1737 }
   1738 
   1739 #ifdef __HAVE_PMAP_PHYSSEG
   1740 ATF_TC(uvm_physseg_get_pmseg);
   1741 ATF_TC_HEAD(uvm_physseg_get_pmseg, tc)
   1742 {
   1743 	atf_tc_set_md_var(tc, "descr", "Tests if the returned pmap_physseg \
   1744 	    struct is correct when fetched by uvm_physseg_get_pmseg() call.");
   1745 }
   1746 ATF_TC_BODY(uvm_physseg_get_pmseg, tc)
   1747 {
   1748 	psize_t npages = (VALID_END_PFN_1 - VALID_START_PFN_1);
   1749 
   1750 	struct vm_page *pgs = malloc(sizeof(struct vm_page) * npages);
   1751 
   1752 	struct pmap_physseg pmseg = { true };
   1753 
   1754 	struct pmap_physseg *extracted_pmseg = NULL;
   1755 
   1756 	uvm_physseg_t upm;
   1757 
   1758 	setup();
   1759 	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1760 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1761 
   1762 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   1763 
   1764 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1765 
   1766 	/* Now we initialize the segment */
   1767 	uvm_physseg_init_seg(upm, pgs);
   1768 
   1769 	ATF_REQUIRE_EQ(PAGE_COUNT_1M, uvmexp.npages);
   1770 
   1771 	ATF_REQUIRE_EQ(NULL, extracted_pmseg);
   1772 
   1773 	ATF_REQUIRE_EQ(true, pmseg.dummy_variable);
   1774 
   1775 	/* Extract the current pmseg */
   1776 	extracted_pmseg = uvm_physseg_get_pmseg(upm);
   1777 
   1778 	/*
   1779 	 * We can only check if it is not NULL
   1780 	 * We do not know the value it contains
   1781 	 */
   1782 	ATF_CHECK(NULL != extracted_pmseg);
   1783 
   1784 	extracted_pmseg->dummy_variable = pmseg.dummy_variable;
   1785 
   1786 	/* Invert value to ensure test integrity */
   1787 	pmseg.dummy_variable = false;
   1788 
   1789 	ATF_REQUIRE_EQ(false, pmseg.dummy_variable);
   1790 
   1791 	extracted_pmseg = uvm_physseg_get_pmseg(upm);
   1792 
   1793 	ATF_CHECK(NULL != extracted_pmseg);
   1794 
   1795 	ATF_CHECK_EQ(true, extracted_pmseg->dummy_variable);
   1796 }
   1797 #endif
   1798 
   1799 ATF_TC(vm_physseg_find);
   1800 ATF_TC_HEAD(vm_physseg_find, tc)
   1801 {
   1802 	atf_tc_set_md_var(tc, "descr", "Tests if the returned segment number \
   1803 	    is correct when an PFN is passed into uvm_physseg_find() call. \
   1804 	    In addition	to this the offset of the PFN from the start of \
   1805 	    segment is also set if the parameter is passed in as not NULL.");
   1806 }
   1807 ATF_TC_BODY(vm_physseg_find, tc)
   1808 {
   1809 	psize_t offset = (psize_t) -1;
   1810 
   1811 	uvm_physseg_t upm_first, result;
   1812 #if VM_PHYSSEG_MAX > 1
   1813 	uvm_physseg_t upm_second;
   1814 #endif
   1815 
   1816 	setup();
   1817 
   1818 	upm_first = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1819 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1820 
   1821 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   1822 
   1823 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1824 
   1825 	/* This test will be triggered only if there are 2 or more segments. */
   1826 #if VM_PHYSSEG_MAX > 1
   1827 	upm_second = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
   1828 	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
   1829 
   1830 	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
   1831 
   1832 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1833 #endif
   1834 
   1835 	/* Under ONE_MEGABYTE is segment upm_first */
   1836 	result = uvm_physseg_find(atop(ONE_MEGABYTE - 1024), NULL);
   1837 	ATF_CHECK_EQ(upm_first, result);
   1838 	ATF_CHECK_EQ(uvm_physseg_get_start(upm_first),
   1839 	    uvm_physseg_get_start(result));
   1840 	ATF_CHECK_EQ(uvm_physseg_get_end(upm_first),
   1841 	    uvm_physseg_get_end(result));
   1842 	ATF_CHECK_EQ(uvm_physseg_get_avail_start(upm_first),
   1843 	    uvm_physseg_get_avail_start(result));
   1844 	ATF_CHECK_EQ(uvm_physseg_get_avail_end(upm_first),
   1845 	    uvm_physseg_get_avail_end(result));
   1846 
   1847 	ATF_REQUIRE_EQ((psize_t) -1, offset);
   1848 
   1849 	/* This test will be triggered only if there are 2 or more segments. */
   1850 #if VM_PHYSSEG_MAX > 1
   1851 	/* Over ONE_MEGABYTE is segment upm_second */
   1852 	result = uvm_physseg_find(atop(ONE_MEGABYTE + 8192), &offset);
   1853 	ATF_CHECK_EQ(upm_second, result);
   1854 	ATF_CHECK_EQ(uvm_physseg_get_start(upm_second),
   1855 	    uvm_physseg_get_start(result));
   1856 	ATF_CHECK_EQ(uvm_physseg_get_end(upm_second),
   1857 	    uvm_physseg_get_end(result));
   1858 	ATF_CHECK_EQ(uvm_physseg_get_avail_start(upm_second),
   1859 	    uvm_physseg_get_avail_start(result));
   1860 	ATF_CHECK_EQ(uvm_physseg_get_avail_end(upm_second),
   1861 	    uvm_physseg_get_avail_end(result));
   1862 
   1863 	/* Offset is calculated based on PAGE_SIZE */
   1864 	/* atop(ONE_MEGABYTE + (2 * PAGE_SIZE)) - VALID_START_PFN1  = 2 */
   1865 	ATF_CHECK_EQ(2, offset);
   1866 #else
   1867 	/* Under ONE_MEGABYTE is segment upm_first */
   1868 	result = uvm_physseg_find(atop(ONE_MEGABYTE - 12288), &offset);
   1869 	ATF_CHECK_EQ(upm_first, result);
   1870 	ATF_CHECK_EQ(uvm_physseg_get_start(upm_first),
   1871 	    uvm_physseg_get_start(result));
   1872 	ATF_CHECK_EQ(uvm_physseg_get_end(upm_first),
   1873 	    uvm_physseg_get_end(result));
   1874 	ATF_CHECK_EQ(uvm_physseg_get_avail_start(upm_first),
   1875 	    uvm_physseg_get_avail_start(result));
   1876 	ATF_CHECK_EQ(uvm_physseg_get_avail_end(upm_first),
   1877 	    uvm_physseg_get_avail_end(result));
   1878 
   1879 	/* Offset is calculated based on PAGE_SIZE */
   1880 	/* atop(ONE_MEGABYTE - (3 * PAGE_SIZE)) - VALID_START_PFN1  = 253 */
   1881 	ATF_CHECK_EQ(253, offset);
   1882 #endif
   1883 }
   1884 
   1885 ATF_TC(vm_physseg_find_invalid);
   1886 ATF_TC_HEAD(vm_physseg_find_invalid, tc)
   1887 {
   1888 	atf_tc_set_md_var(tc, "descr", "Tests if the returned segment number \
   1889 	    is (paddr_t) -1  when a non-existent PFN is passed into \
   1890 	    uvm_physseg_find() call.");
   1891 }
   1892 ATF_TC_BODY(vm_physseg_find_invalid, tc)
   1893 {
   1894 	psize_t offset = (psize_t) -1;
   1895 
   1896 	setup();
   1897 	uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   1898 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   1899 
   1900 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   1901 
   1902 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1903 
   1904 	/* No segments over 3 MB exists at the moment */
   1905 	ATF_CHECK_EQ(UVM_PHYSSEG_TYPE_INVALID,
   1906 	    uvm_physseg_find(atop(ONE_MEGABYTE * 3), NULL));
   1907 
   1908 	ATF_REQUIRE_EQ((psize_t) -1, offset);
   1909 
   1910 	/* No segments over 3 MB exists at the moment */
   1911 	ATF_CHECK_EQ(UVM_PHYSSEG_TYPE_INVALID,
   1912 	    uvm_physseg_find(atop(ONE_MEGABYTE * 3), &offset));
   1913 
   1914 	ATF_CHECK_EQ((psize_t) -1, offset);
   1915 }
   1916 
   1917 ATF_TC(uvm_page_physunload_start);
   1918 ATF_TC_HEAD(uvm_page_physunload_start, tc)
   1919 {
   1920 	atf_tc_set_md_var(tc, "descr", "Tests if the basic uvm_page_physunload()\
   1921 	    call works without a panic(). Unloads from Start of the segment.");
   1922 }
   1923 ATF_TC_BODY(uvm_page_physunload_start, tc)
   1924 {
   1925 	/*
   1926 	 * Would uvmexp.npages reduce everytime an uvm_page_physunload is called?
   1927 	 */
   1928 	psize_t npages = (VALID_END_PFN_2 - VALID_START_PFN_2);
   1929 
   1930 	struct vm_page *pgs = malloc(sizeof(struct vm_page) * npages);
   1931 
   1932 	paddr_t p = 0;
   1933 
   1934 	uvm_physseg_t upm;
   1935 
   1936 	setup();
   1937 	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
   1938 	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
   1939 
   1940 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   1941 
   1942 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1943 
   1944 	uvm_physseg_init_seg(upm, pgs);
   1945 
   1946 	ATF_CHECK_EQ(true, uvm_page_physunload(upm, VM_FREELIST_DEFAULT, &p));
   1947 
   1948 	/*
   1949 	 * When called for first time, uvm_page_physload() removes the first PFN
   1950 	 *
   1951 	 * New avail start will be VALID_AVAIL_START_PFN_2 + 1
   1952 	 */
   1953 	ATF_CHECK_EQ(VALID_START_PFN_2, atop(p));
   1954 
   1955 	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_2 + 1,
   1956 	    uvm_physseg_get_avail_start(upm));
   1957 
   1958 	ATF_CHECK_EQ(VALID_START_PFN_2 + 1, uvm_physseg_get_start(upm));
   1959 
   1960 	/* Rest of the stuff should remain the same */
   1961 	ATF_CHECK_EQ(VALID_END_PFN_2, uvm_physseg_get_end(upm));
   1962 	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_2, uvm_physseg_get_avail_end(upm));
   1963 }
   1964 
   1965 ATF_TC(uvm_page_physunload_end);
   1966 ATF_TC_HEAD(uvm_page_physunload_end, tc)
   1967 {
   1968 	atf_tc_set_md_var(tc, "descr", "Tests if the basic uvm_page_physunload()\
   1969 	    call works without a panic(). Unloads from End of the segment.");
   1970 }
   1971 ATF_TC_BODY(uvm_page_physunload_end, tc)
   1972 {
   1973 	/*
   1974 	 * Would uvmexp.npages reduce everytime an uvm_page_physunload is called?
   1975 	 */
   1976 	paddr_t p = 0;
   1977 
   1978 	uvm_physseg_t upm;
   1979 
   1980 	setup();
   1981 	/* Note: start != avail_start to remove from end. */
   1982 	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
   1983 	    VALID_AVAIL_START_PFN_2 + 1, VALID_AVAIL_END_PFN_2,
   1984 	    VM_FREELIST_DEFAULT);
   1985 
   1986 	p = 0;
   1987 
   1988 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   1989 
   1990 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   1991 
   1992 	ATF_REQUIRE(
   1993 		uvm_physseg_get_avail_start(upm) != uvm_physseg_get_start(upm));
   1994 
   1995 	ATF_CHECK_EQ(true, uvm_page_physunload(upm, VM_FREELIST_DEFAULT, &p));
   1996 
   1997 	/*
   1998 	 * Remember if X is the upper limit the actual valid pointer is X - 1
   1999 	 *
   2000 	 * For example if 256 is the upper limit for 1MB memory, last valid
   2001 	 * pointer is 256 - 1 = 255
   2002 	 */
   2003 
   2004 	ATF_CHECK_EQ(VALID_END_PFN_2 - 1, atop(p));
   2005 
   2006 	/*
   2007 	 * When called for second time, uvm_page_physload() removes the last PFN
   2008 	 *
   2009 	 * New avail end will be VALID_AVAIL_END_PFN_2 - 1
   2010 	 * New end will be VALID_AVAIL_PFN_2 - 1
   2011 	 */
   2012 
   2013 	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_2 - 1, uvm_physseg_get_avail_end(upm));
   2014 
   2015 	ATF_CHECK_EQ(VALID_END_PFN_2 - 1, uvm_physseg_get_end(upm));
   2016 
   2017 	/* Rest of the stuff should remain the same */
   2018 	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_2 + 1,
   2019 	    uvm_physseg_get_avail_start(upm));
   2020 	ATF_CHECK_EQ(VALID_START_PFN_2, uvm_physseg_get_start(upm));
   2021 }
   2022 
   2023 ATF_TC(uvm_page_physunload_none);
   2024 ATF_TC_HEAD(uvm_page_physunload_none, tc)
   2025 {
   2026 	atf_tc_set_md_var(tc, "descr", "Tests if the basic uvm_page_physunload()\
   2027 	    call works without a panic(). Does not unload from start or end \
   2028 	    because of non-aligned start / avail_start and end / avail_end \
   2029 	    respectively.");
   2030 }
   2031 ATF_TC_BODY(uvm_page_physunload_none, tc)
   2032 {
   2033 	psize_t npages = (VALID_END_PFN_2 - VALID_START_PFN_2);
   2034 
   2035 	struct vm_page *pgs = malloc(sizeof(struct vm_page) * npages);
   2036 
   2037 	paddr_t p = 0;
   2038 
   2039 	uvm_physseg_t upm;
   2040 
   2041 	setup();
   2042 	/*
   2043 	 * Note: start != avail_start and end != avail_end.
   2044 	 *
   2045 	 * This prevents any unload from occurring.
   2046 	 */
   2047 	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
   2048 	    VALID_AVAIL_START_PFN_2 + 1, VALID_AVAIL_END_PFN_2 - 1,
   2049 	    VM_FREELIST_DEFAULT);
   2050 
   2051 	p = 0;
   2052 
   2053 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   2054 
   2055 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   2056 
   2057 	ATF_REQUIRE(
   2058 		uvm_physseg_get_avail_start(upm) != uvm_physseg_get_start(upm));
   2059 
   2060 	uvm_physseg_init_seg(upm, pgs);
   2061 
   2062 	ATF_CHECK_EQ(false, uvm_page_physunload(upm, VM_FREELIST_DEFAULT, &p));
   2063 
   2064 	/* uvm_page_physload() will no longer unload memory */
   2065 	ATF_CHECK_EQ(0, p);
   2066 
   2067 	/* Rest of the stuff should remain the same */
   2068 	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_2 + 1,
   2069 	    uvm_physseg_get_avail_start(upm));
   2070 	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_2 - 1,
   2071 	    uvm_physseg_get_avail_end(upm));
   2072 	ATF_CHECK_EQ(VALID_START_PFN_2, uvm_physseg_get_start(upm));
   2073 	ATF_CHECK_EQ(VALID_END_PFN_2, uvm_physseg_get_end(upm));
   2074 }
   2075 
   2076 ATF_TC(uvm_page_physunload_delete_start);
   2077 ATF_TC_HEAD(uvm_page_physunload_delete_start, tc)
   2078 {
   2079 	atf_tc_set_md_var(tc, "descr", "Tests if the  uvm_page_physunload() \
   2080 	    works when the segment gets small enough to be deleted scenario. \
   2081 	    NOTE: This one works deletes from start.");
   2082 }
   2083 ATF_TC_BODY(uvm_page_physunload_delete_start, tc)
   2084 {
   2085 	/*
   2086 	 * Would uvmexp.npages reduce everytime an uvm_page_physunload is called?
   2087 	 */
   2088 	paddr_t p = 0;
   2089 
   2090 	uvm_physseg_t upm;
   2091 
   2092 	setup();
   2093 
   2094 	/*
   2095 	 * Setup the Nuke from Starting point
   2096 	 */
   2097 
   2098 	upm = uvm_page_physload(VALID_END_PFN_1 - 1, VALID_END_PFN_1,
   2099 	    VALID_AVAIL_END_PFN_1 - 1, VALID_AVAIL_END_PFN_1,
   2100 	    VM_FREELIST_DEFAULT);
   2101 
   2102 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   2103 
   2104 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   2105 
   2106 	/* Insert more than one segment iff VM_PHYSSEG_MAX > 1 */
   2107 #if VM_PHYSSEG_MAX > 1
   2108 	uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
   2109 	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
   2110 
   2111 	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
   2112 #endif
   2113 
   2114 #if VM_PHYSSEG_MAX == 1
   2115 	atf_tc_expect_signal(SIGABRT,
   2116 	    "cannot uvm_page_physunload() the last segment");
   2117 #endif
   2118 
   2119 	ATF_CHECK_EQ(true, uvm_page_physunload(upm, VM_FREELIST_DEFAULT, &p));
   2120 
   2121 	ATF_CHECK_EQ(VALID_END_PFN_1 - 1, atop(p));
   2122 
   2123 	ATF_CHECK_EQ(1, uvm_physseg_get_entries());
   2124 
   2125 	/* The only node now is the one we inserted second. */
   2126 	upm = uvm_physseg_get_first();
   2127 
   2128 	ATF_CHECK_EQ(VALID_START_PFN_2, uvm_physseg_get_start(upm));
   2129 	ATF_CHECK_EQ(VALID_END_PFN_2, uvm_physseg_get_end(upm));
   2130 	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_2, uvm_physseg_get_avail_start(upm));
   2131 	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_2, uvm_physseg_get_avail_end(upm));
   2132 }
   2133 
   2134 ATF_TC(uvm_page_physunload_delete_end);
   2135 ATF_TC_HEAD(uvm_page_physunload_delete_end, tc)
   2136 {
   2137 	atf_tc_set_md_var(tc, "descr", "Tests if the  uvm_page_physunload() \
   2138 	    works when the segment gets small enough to be deleted scenario. \
   2139 	    NOTE: This one works deletes from end.");
   2140 }
   2141 ATF_TC_BODY(uvm_page_physunload_delete_end, tc)
   2142 {
   2143 	/*
   2144 	 * Would uvmexp.npages reduce everytime an uvm_page_physunload is called?
   2145 	 */
   2146 
   2147 	paddr_t p = 0;
   2148 
   2149 	uvm_physseg_t upm;
   2150 
   2151 	setup();
   2152 
   2153 	/*
   2154 	 * Setup the Nuke from Ending point
   2155 	 */
   2156 
   2157 	upm = uvm_page_physload(VALID_START_PFN_1, VALID_START_PFN_1 + 2,
   2158 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_START_PFN_1 + 2,
   2159 	    VM_FREELIST_DEFAULT);
   2160 
   2161 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   2162 
   2163 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   2164 
   2165 	/* Insert more than one segment iff VM_PHYSSEG_MAX > 1 */
   2166 #if VM_PHYSSEG_MAX > 1
   2167 	uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
   2168 	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
   2169 
   2170 	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
   2171 #endif
   2172 
   2173 #if VM_PHYSSEG_MAX == 1
   2174 	atf_tc_expect_signal(SIGABRT,
   2175 	    "cannot uvm_page_physunload() the last segment");
   2176 #endif
   2177 
   2178 	ATF_CHECK_EQ(true, uvm_page_physunload(upm, VM_FREELIST_DEFAULT, &p));
   2179 
   2180 	ATF_CHECK_EQ(VALID_START_PFN_1, atop(p));
   2181 
   2182 	p = 0;
   2183 
   2184 	ATF_CHECK_EQ(true, uvm_page_physunload(upm, VM_FREELIST_DEFAULT, &p));
   2185 
   2186 	ATF_CHECK_EQ(VALID_START_PFN_1 + 1, atop(p));
   2187 
   2188 	ATF_CHECK_EQ(1, uvm_physseg_get_entries());
   2189 
   2190 	/* The only node now is the one we inserted second. */
   2191 	upm = uvm_physseg_get_first();
   2192 
   2193 	ATF_CHECK_EQ(VALID_START_PFN_2, uvm_physseg_get_start(upm));
   2194 	ATF_CHECK_EQ(VALID_END_PFN_2, uvm_physseg_get_end(upm));
   2195 	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_2, uvm_physseg_get_avail_start(upm));
   2196 	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_2, uvm_physseg_get_avail_end(upm));
   2197 }
   2198 
   2199 ATF_TC(uvm_page_physunload_invalid);
   2200 ATF_TC_HEAD(uvm_page_physunload_invalid, tc)
   2201 {
   2202 	atf_tc_set_md_var(tc, "descr", "Tests if the  uvm_page_physunload() \
   2203 	    fails when then Free list does not match.");
   2204 }
   2205 ATF_TC_BODY(uvm_page_physunload_invalid, tc)
   2206 {
   2207 	psize_t npages = (VALID_END_PFN_2 - VALID_START_PFN_2);
   2208 
   2209 	struct vm_page *pgs = malloc(sizeof(struct vm_page) * npages);
   2210 
   2211 	paddr_t p = 0;
   2212 
   2213 	uvm_physseg_t upm;
   2214 
   2215 	setup();
   2216 	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
   2217 	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
   2218 
   2219 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   2220 
   2221 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   2222 
   2223 	uvm_physseg_init_seg(upm, pgs);
   2224 
   2225 	ATF_CHECK_EQ(false, uvm_page_physunload(upm, VM_FREELIST_FIRST4G, &p));
   2226 }
   2227 
   2228 ATF_TC(uvm_page_physunload_force);
   2229 ATF_TC_HEAD(uvm_page_physunload_force, tc)
   2230 {
   2231 	atf_tc_set_md_var(tc, "descr", "Tests if the basic \
   2232 	    uvm_page_physunload_force() including delete works without.");
   2233 }
   2234 ATF_TC_BODY(uvm_page_physunload_force, tc)
   2235 {
   2236 	/*
   2237 	 * Would uvmexp.npages reduce everytime an uvm_page_physunload is called?
   2238 	 */
   2239 	paddr_t p = 0;
   2240 
   2241 	uvm_physseg_t upm;
   2242 
   2243 	setup();
   2244 	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
   2245 	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
   2246 
   2247 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   2248 
   2249 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   2250 
   2251 	/* Insert more than one segment iff VM_PHYSSEG_MAX > 1 */
   2252 #if VM_PHYSSEG_MAX > 1
   2253 	/*
   2254 	 * We have couple of physloads done this is because of the fact that if
   2255 	 * we physunload all the PFs from a given range and we have only one
   2256 	 * segment in total a panic() is called
   2257 	 */
   2258 	uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
   2259 	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
   2260 
   2261 	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
   2262 #endif
   2263 
   2264 #if VM_PHYSSEG_MAX == 1
   2265 	atf_tc_expect_signal(SIGABRT,
   2266 	    "cannot uvm_page_physunload() the last segment");
   2267 #endif
   2268 
   2269 	ATF_REQUIRE_EQ(VALID_AVAIL_START_PFN_1,
   2270 	    uvm_physseg_get_avail_start(upm));
   2271 
   2272 	for(paddr_t i = VALID_AVAIL_START_PFN_1;
   2273 	    i < VALID_AVAIL_END_PFN_1; i++) {
   2274 		ATF_CHECK_EQ(true,
   2275 		    uvm_page_physunload_force(upm, VM_FREELIST_DEFAULT, &p));
   2276 		ATF_CHECK_EQ(i, atop(p));
   2277 
   2278 		if(i + 1 < VALID_AVAIL_END_PFN_1)
   2279 			ATF_CHECK_EQ(i + 1, uvm_physseg_get_avail_start(upm));
   2280 	}
   2281 
   2282 	/*
   2283 	 * Now we try to retrieve the segment, which has been removed
   2284 	 * from the system through force unloading all the pages inside it.
   2285 	 */
   2286 	upm = uvm_physseg_find(VALID_AVAIL_END_PFN_1 - 1, NULL);
   2287 
   2288 	/* It should no longer exist */
   2289 #if defined(UVM_HOTPLUG)
   2290 	ATF_CHECK_EQ(NULL, upm);
   2291 #else
   2292 	ATF_CHECK_EQ(-1, upm);
   2293 #endif
   2294 
   2295 	ATF_CHECK_EQ(1, uvm_physseg_get_entries());
   2296 }
   2297 
   2298 ATF_TC(uvm_page_physunload_force_invalid);
   2299 ATF_TC_HEAD(uvm_page_physunload_force_invalid, tc)
   2300 {
   2301 	atf_tc_set_md_var(tc, "descr", "Tests if the invalid conditions for \
   2302 	    uvm_page_physunload_force_invalid().");
   2303 }
   2304 ATF_TC_BODY(uvm_page_physunload_force_invalid, tc)
   2305 {
   2306 	paddr_t p = 0;
   2307 
   2308 	uvm_physseg_t upm;
   2309 
   2310 	setup();
   2311 	upm = uvm_page_physload(VALID_START_PFN_2, VALID_START_PFN_2+ 1,
   2312 	    VALID_START_PFN_2, VALID_START_PFN_2, VM_FREELIST_DEFAULT);
   2313 
   2314 	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
   2315 
   2316 	ATF_REQUIRE_EQ(0, uvmexp.npages);
   2317 
   2318 	ATF_CHECK_EQ(false,
   2319 	    uvm_page_physunload_force(upm, VM_FREELIST_DEFAULT, &p));
   2320 
   2321 	ATF_CHECK_EQ(0, p);
   2322 }
   2323 
   2324 ATF_TP_ADD_TCS(tp)
   2325 {
   2326 #if defined(UVM_HOTPLUG)
   2327 	/* Internal */
   2328 	ATF_TP_ADD_TC(tp, uvm_physseg_alloc_atboot_mismatch);
   2329 	ATF_TP_ADD_TC(tp, uvm_physseg_alloc_atboot_overrun);
   2330 	ATF_TP_ADD_TC(tp, uvm_physseg_alloc_sanity);
   2331 	ATF_TP_ADD_TC(tp, uvm_physseg_free_atboot_mismatch);
   2332 	ATF_TP_ADD_TC(tp, uvm_physseg_free_sanity);
   2333 #if VM_PHYSSEG_MAX > 1
   2334 	ATF_TP_ADD_TC(tp, uvm_physseg_atboot_free_leak);
   2335 #endif
   2336 #endif /* UVM_HOTPLUG */
   2337 
   2338 	ATF_TP_ADD_TC(tp, uvm_physseg_plug);
   2339 	ATF_TP_ADD_TC(tp, uvm_physseg_unplug);
   2340 
   2341 	/* Exported */
   2342 	ATF_TP_ADD_TC(tp, uvm_physseg_init);
   2343 	ATF_TP_ADD_TC(tp, uvm_page_physload_preload);
   2344 	ATF_TP_ADD_TC(tp, uvm_page_physload_postboot);
   2345 	ATF_TP_ADD_TC(tp, uvm_physseg_handle_immutable);
   2346 	ATF_TP_ADD_TC(tp, uvm_physseg_seg_chomp_slab);
   2347 	ATF_TP_ADD_TC(tp, uvm_physseg_alloc_from_slab);
   2348 	ATF_TP_ADD_TC(tp, uvm_physseg_init_seg);
   2349 	ATF_TP_ADD_TC(tp, uvm_physseg_get_start);
   2350 	ATF_TP_ADD_TC(tp, uvm_physseg_get_start_invalid);
   2351 	ATF_TP_ADD_TC(tp, uvm_physseg_get_end);
   2352 	ATF_TP_ADD_TC(tp, uvm_physseg_get_end_invalid);
   2353 	ATF_TP_ADD_TC(tp, uvm_physseg_get_avail_start);
   2354 	ATF_TP_ADD_TC(tp, uvm_physseg_get_avail_start_invalid);
   2355 	ATF_TP_ADD_TC(tp, uvm_physseg_get_avail_end);
   2356 	ATF_TP_ADD_TC(tp, uvm_physseg_get_avail_end_invalid);
   2357 	ATF_TP_ADD_TC(tp, uvm_physseg_get_next);
   2358 	ATF_TP_ADD_TC(tp, uvm_physseg_get_next_invalid);
   2359 	ATF_TP_ADD_TC(tp, uvm_physseg_get_prev);
   2360 	ATF_TP_ADD_TC(tp, uvm_physseg_get_prev_invalid);
   2361 	ATF_TP_ADD_TC(tp, uvm_physseg_get_first);
   2362 	ATF_TP_ADD_TC(tp, uvm_physseg_get_last);
   2363 	ATF_TP_ADD_TC(tp, uvm_physseg_valid);
   2364 	ATF_TP_ADD_TC(tp, uvm_physseg_valid_invalid);
   2365 	ATF_TP_ADD_TC(tp, uvm_physseg_get_highest);
   2366 	ATF_TP_ADD_TC(tp, uvm_physseg_get_free_list);
   2367 	ATF_TP_ADD_TC(tp, uvm_physseg_get_start_hint);
   2368 	ATF_TP_ADD_TC(tp, uvm_physseg_set_start_hint);
   2369 	ATF_TP_ADD_TC(tp, uvm_physseg_set_start_hint_invalid);
   2370 	ATF_TP_ADD_TC(tp, uvm_physseg_get_pg);
   2371 
   2372 #ifdef __HAVE_PMAP_PHYSSEG
   2373 	ATF_TP_ADD_TC(tp, uvm_physseg_get_pmseg);
   2374 #endif
   2375 	ATF_TP_ADD_TC(tp, vm_physseg_find);
   2376 	ATF_TP_ADD_TC(tp, vm_physseg_find_invalid);
   2377 
   2378 	ATF_TP_ADD_TC(tp, uvm_page_physunload_start);
   2379 	ATF_TP_ADD_TC(tp, uvm_page_physunload_end);
   2380 	ATF_TP_ADD_TC(tp, uvm_page_physunload_none);
   2381 	ATF_TP_ADD_TC(tp, uvm_page_physunload_delete_start);
   2382 	ATF_TP_ADD_TC(tp, uvm_page_physunload_delete_end);
   2383 	ATF_TP_ADD_TC(tp, uvm_page_physunload_invalid);
   2384 	ATF_TP_ADD_TC(tp, uvm_page_physunload_force);
   2385 	ATF_TP_ADD_TC(tp, uvm_page_physunload_force_invalid);
   2386 
   2387 	return atf_no_error();
   2388 }
   2389