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