1 /* $NetBSD: t_uvm_physseg.c,v 1.2 2016/12/22 08:15:20 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@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.2 2016/12/22 08:15:20 cherry 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 occuring.
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