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