]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/netbsd-tests/sys/uvm/t_uvm_physseg.c
MFC r314450,r313439:
[FreeBSD/stable/10.git] / contrib / netbsd-tests / sys / uvm / t_uvm_physseg.c
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 }