1312123Sngie/* $NetBSD: t_uvm_physseg.c,v 1.2 2016/12/22 08:15:20 cherry Exp $ */
2312123Sngie
3312123Sngie/*-
4312123Sngie * Copyright (c) 2015, 2016 The NetBSD Foundation, Inc.
5312123Sngie * All rights reserved.
6312123Sngie *
7312123Sngie * This code is derived from software contributed to The NetBSD Foundation
8312123Sngie * by Santhosh N. Raju <santhosh.raju@gmail.com> and
9312123Sngie * by Cherry G. Mathew
10312123Sngie *
11312123Sngie * Redistribution and use in source and binary forms, with or without
12312123Sngie * modification, are permitted provided that the following conditions
13312123Sngie * are met:
14312123Sngie * 1. Redistributions of source code must retain the above copyright
15312123Sngie *    notice, this list of conditions and the following disclaimer.
16312123Sngie * 2. Redistributions in binary form must reproduce the above copyright
17312123Sngie *    notice, this list of conditions and the following disclaimer in the
18312123Sngie *    documentation and/or other materials provided with the distribution.
19312123Sngie *
20312123Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21312123Sngie * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22312123Sngie * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23312123Sngie * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24312123Sngie * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25312123Sngie * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26312123Sngie * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27312123Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28312123Sngie * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29312123Sngie * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30312123Sngie * POSSIBILITY OF SUCH DAMAGE.
31312123Sngie */
32312123Sngie
33312123Sngie#include <sys/cdefs.h>
34312123Sngie__RCSID("$NetBSD: t_uvm_physseg.c,v 1.2 2016/12/22 08:15:20 cherry Exp $");
35312123Sngie
36312123Sngie/*
37312123Sngie * If this line is commented out tests related to uvm_physseg_get_pmseg()
38312123Sngie * wont run.
39312123Sngie *
40312123Sngie * Have a look at machine/uvm_physseg.h for more details.
41312123Sngie */
42312123Sngie#define __HAVE_PMAP_PHYSSEG
43312123Sngie
44312123Sngie/*
45312123Sngie * This is a dummy struct used for testing purposes
46312123Sngie *
47312123Sngie * In reality this struct would exist in the MD part of the code residing in
48312123Sngie * machines/vmparam.h
49312123Sngie */
50312123Sngie
51312123Sngie#ifdef __HAVE_PMAP_PHYSSEG
52312123Sngiestruct pmap_physseg {
53312123Sngie	int dummy_variable;		/* Dummy variable use for testing */
54312123Sngie};
55312123Sngie#endif
56312123Sngie
57312123Sngie/* Testing API - assumes userland */
58312123Sngie/* Provide Kernel API equivalents */
59312123Sngie#include <assert.h>
60312123Sngie#include <errno.h>
61312123Sngie#include <stdbool.h>
62312123Sngie#include <string.h> /* memset(3) et. al */
63312123Sngie#include <stdio.h> /* printf(3) */
64312123Sngie#include <stdlib.h> /* malloc(3) */
65312123Sngie#include <stdarg.h>
66312123Sngie#include <stddef.h>
67312123Sngie
68312123Sngie#define	PRIxPADDR	"lx"
69312123Sngie#define	PRIxPSIZE	"lx"
70312123Sngie#define	PRIuPSIZE	"lu"
71312123Sngie#define	PRIxVADDR	"lx"
72312123Sngie#define	PRIxVSIZE	"lx"
73312123Sngie#define	PRIuVSIZE	"lu"
74312123Sngie
75312123Sngie#define UVM_HOTPLUG /* Enable hotplug with rbtree. */
76312123Sngie#define PMAP_STEAL_MEMORY
77312123Sngie#define DEBUG /* Enable debug functionality. */
78312123Sngie
79312123Sngietypedef unsigned long vaddr_t;
80312123Sngietypedef unsigned long paddr_t;
81312123Sngietypedef unsigned long psize_t;
82312123Sngietypedef unsigned long vsize_t;
83312123Sngie
84312123Sngie#include <uvm/uvm_physseg.h>
85312123Sngie#include <uvm/uvm_page.h>
86312123Sngie
87312123Sngie#ifndef DIAGNOSTIC
88312123Sngie#define	KASSERTMSG(e, msg, ...)	/* NOTHING */
89312123Sngie#define	KASSERT(e)		/* NOTHING */
90312123Sngie#else
91312123Sngie#define	KASSERT(a)		assert(a)
92312123Sngie#define KASSERTMSG(exp, ...)    printf(__VA_ARGS__); assert((exp))
93312123Sngie#endif
94312123Sngie
95312123Sngie#define VM_PHYSSEG_STRAT VM_PSTRAT_BSEARCH
96312123Sngie
97312123Sngie#define VM_NFREELIST            4
98312123Sngie#define VM_FREELIST_DEFAULT     0
99312123Sngie#define VM_FREELIST_FIRST16     3
100312123Sngie#define VM_FREELIST_FIRST1G     2
101312123Sngie#define VM_FREELIST_FIRST4G     1
102312123Sngie
103312123Sngie/*
104312123Sngie * Used in tests when Array implementation is tested
105312123Sngie */
106312123Sngie#if !defined(VM_PHYSSEG_MAX)
107312123Sngie#define VM_PHYSSEG_MAX          1
108312123Sngie#endif
109312123Sngie
110312123Sngie#define PAGE_SHIFT              12
111312123Sngie#define PAGE_SIZE               (1 << PAGE_SHIFT)
112312123Sngie#define	PAGE_MASK	(PAGE_SIZE - 1)
113312123Sngie#define atop(x)         (((paddr_t)(x)) >> PAGE_SHIFT)
114312123Sngie#define ptoa(x)         (((paddr_t)(x)) << PAGE_SHIFT)
115312123Sngie
116312123Sngie#define	mutex_enter(l)
117312123Sngie#define	mutex_exit(l)
118312123Sngie
119312123Sngiepsize_t physmem;
120312123Sngie
121312123Sngiestruct uvmexp uvmexp;        /* decl */
122312123Sngie
123312123Sngie/*
124312123Sngie * uvm structure borrowed from uvm.h
125312123Sngie *
126312123Sngie * Remember this is a dummy structure used within the ATF Tests and
127312123Sngie * uses only necessary fields from the original uvm struct.
128312123Sngie * See uvm/uvm.h for the full struct.
129312123Sngie */
130312123Sngie
131312123Sngiestruct uvm {
132312123Sngie	/* vm_page related parameters */
133312123Sngie
134312123Sngie	bool page_init_done;		/* TRUE if uvm_page_init() finished */
135312123Sngie} uvm;
136312123Sngie
137312123Sngie#include <sys/kmem.h>
138312123Sngie
139312123Sngievoid *
140312123Sngiekmem_alloc(size_t size, km_flag_t flags)
141312123Sngie{
142312123Sngie	return malloc(size);
143312123Sngie}
144312123Sngie
145312123Sngievoid *
146312123Sngiekmem_zalloc(size_t size, km_flag_t flags)
147312123Sngie{
148312123Sngie	void *ptr;
149312123Sngie	ptr = malloc(size);
150312123Sngie
151312123Sngie	memset(ptr, 0, size);
152312123Sngie
153312123Sngie	return ptr;
154312123Sngie}
155312123Sngie
156312123Sngievoid
157312123Sngiekmem_free(void *mem, size_t size)
158312123Sngie{
159312123Sngie	free(mem);
160312123Sngie}
161312123Sngie
162312123Sngiestatic void
163312123Sngiepanic(const char *fmt, ...)
164312123Sngie{
165312123Sngie	va_list ap;
166312123Sngie
167312123Sngie	va_start(ap, fmt);
168312123Sngie	vprintf(fmt, ap);
169312123Sngie	printf("\n");
170312123Sngie	va_end(ap);
171312123Sngie	KASSERT(false);
172312123Sngie
173312123Sngie	/*NOTREACHED*/
174312123Sngie}
175312123Sngie
176312123Sngiestatic void
177312123Sngieuvm_pagefree(struct vm_page *pg)
178312123Sngie{
179312123Sngie	return;
180312123Sngie}
181312123Sngie
182312123Sngie#if defined(UVM_HOTPLUG)
183312123Sngiestatic void
184312123Sngieuvmpdpol_reinit(void)
185312123Sngie{
186312123Sngie	return;
187312123Sngie}
188312123Sngie#endif /* UVM_HOTPLUG */
189312123Sngie
190312123Sngie/* end - Provide Kernel API equivalents */
191312123Sngie
192312123Sngie
193312123Sngie#include "uvm/uvm_physseg.c"
194312123Sngie
195312123Sngie#include <atf-c.h>
196312123Sngie
197312123Sngie#define SIXTYFOUR_KILO (64 * 1024)
198312123Sngie#define ONETWENTYEIGHT_KILO (128 * 1024)
199312123Sngie#define TWOFIFTYSIX_KILO (256 * 1024)
200312123Sngie#define FIVEONETWO_KILO (512 * 1024)
201312123Sngie#define ONE_MEGABYTE (1024 * 1024)
202312123Sngie#define TWO_MEGABYTE (2 * 1024 * 1024)
203312123Sngie
204312123Sngie/* Sample Page Frame Numbers */
205312123Sngie#define VALID_START_PFN_1 atop(0)
206312123Sngie#define VALID_END_PFN_1 atop(ONE_MEGABYTE)
207312123Sngie#define VALID_AVAIL_START_PFN_1 atop(0)
208312123Sngie#define VALID_AVAIL_END_PFN_1 atop(ONE_MEGABYTE)
209312123Sngie
210312123Sngie#define VALID_START_PFN_2 atop(ONE_MEGABYTE + 1)
211312123Sngie#define VALID_END_PFN_2 atop(ONE_MEGABYTE * 2)
212312123Sngie#define VALID_AVAIL_START_PFN_2 atop(ONE_MEGABYTE + 1)
213312123Sngie#define VALID_AVAIL_END_PFN_2 atop(ONE_MEGABYTE * 2)
214312123Sngie
215312123Sngie#define VALID_START_PFN_3 atop((ONE_MEGABYTE * 2) + 1)
216312123Sngie#define VALID_END_PFN_3 atop(ONE_MEGABYTE * 3)
217312123Sngie#define VALID_AVAIL_START_PFN_3 atop((ONE_MEGABYTE * 2) + 1)
218312123Sngie#define VALID_AVAIL_END_PFN_3 atop(ONE_MEGABYTE * 3)
219312123Sngie
220312123Sngie#define VALID_START_PFN_4 atop((ONE_MEGABYTE * 3) + 1)
221312123Sngie#define VALID_END_PFN_4 atop(ONE_MEGABYTE * 4)
222312123Sngie#define VALID_AVAIL_START_PFN_4 atop((ONE_MEGABYTE * 3) + 1)
223312123Sngie#define VALID_AVAIL_END_PFN_4 atop(ONE_MEGABYTE * 4)
224312123Sngie
225312123Sngie/*
226312123Sngie * Total number of pages (of 4K size each) should be 256 for 1MB of memory.
227312123Sngie */
228312123Sngie#define PAGE_COUNT_1M      256
229312123Sngie
230312123Sngie/*
231312123Sngie * A debug fucntion to print the content of upm.
232312123Sngie */
233312123Sngie	static inline void
234312123Sngie	uvm_physseg_dump_seg(uvm_physseg_t upm)
235312123Sngie	{
236312123Sngie#if defined(DEBUG)
237312123Sngie		printf("%s: seg->start == %ld\n", __func__,
238312123Sngie		    uvm_physseg_get_start(upm));
239312123Sngie		printf("%s: seg->end == %ld\n", __func__,
240312123Sngie		    uvm_physseg_get_end(upm));
241312123Sngie		printf("%s: seg->avail_start == %ld\n", __func__,
242312123Sngie		    uvm_physseg_get_avail_start(upm));
243312123Sngie		printf("%s: seg->avail_end == %ld\n", __func__,
244312123Sngie		    uvm_physseg_get_avail_end(upm));
245312123Sngie
246312123Sngie		printf("====\n\n");
247312123Sngie#else
248312123Sngie		return;
249312123Sngie#endif /* DEBUG */
250312123Sngie	}
251312123Sngie
252312123Sngie/*
253312123Sngie * Private accessor that gets the value of uvm_physseg_graph.nentries
254312123Sngie */
255312123Sngiestatic int
256312123Sngieuvm_physseg_get_entries(void)
257312123Sngie{
258312123Sngie#if defined(UVM_HOTPLUG)
259312123Sngie	return uvm_physseg_graph.nentries;
260312123Sngie#else
261312123Sngie	return vm_nphysmem;
262312123Sngie#endif /* UVM_HOTPLUG */
263312123Sngie}
264312123Sngie
265312123Sngie#if !defined(UVM_HOTPLUG)
266312123Sngiestatic void *
267312123Sngieuvm_physseg_alloc(size_t sz)
268312123Sngie{
269312123Sngie	return &vm_physmem[vm_nphysseg++];
270312123Sngie}
271312123Sngie#endif
272312123Sngie
273312123Sngie/*
274312123Sngie * Test Fixture SetUp().
275312123Sngie */
276312123Sngiestatic void
277312123Sngiesetup(void)
278312123Sngie{
279312123Sngie	/* Prerequisites for running certain calls in uvm_physseg */
280312123Sngie	uvmexp.pagesize = PAGE_SIZE;
281312123Sngie	uvmexp.npages = 0;
282312123Sngie	uvm.page_init_done = false;
283312123Sngie	uvm_physseg_init();
284312123Sngie}
285312123Sngie
286312123Sngie
287312123Sngie/* <---- Tests for Internal functions ----> */
288312123Sngie#if defined(UVM_HOTPLUG)
289312123SngieATF_TC(uvm_physseg_alloc_atboot_mismatch);
290312123SngieATF_TC_HEAD(uvm_physseg_alloc_atboot_mismatch, tc)
291312123Sngie{
292312123Sngie	atf_tc_set_md_var(tc, "descr", "boot time uvm_physseg_alloc() sanity"
293312123Sngie	    "size mismatch alloc() test.");
294312123Sngie}
295312123Sngie
296312123SngieATF_TC_BODY(uvm_physseg_alloc_atboot_mismatch, tc)
297312123Sngie{
298312123Sngie	uvm.page_init_done = false;
299312123Sngie
300312123Sngie	atf_tc_expect_signal(SIGABRT, "size mismatch alloc()");
301312123Sngie
302312123Sngie	uvm_physseg_alloc(sizeof(struct uvm_physseg) - 1);
303312123Sngie}
304312123Sngie
305312123SngieATF_TC(uvm_physseg_alloc_atboot_overrun);
306312123SngieATF_TC_HEAD(uvm_physseg_alloc_atboot_overrun, tc)
307312123Sngie{
308312123Sngie	atf_tc_set_md_var(tc, "descr", "boot time uvm_physseg_alloc() sanity"
309312123Sngie	    "array overrun alloc() test.");
310312123Sngie}
311312123Sngie
312312123SngieATF_TC_BODY(uvm_physseg_alloc_atboot_overrun, tc)
313312123Sngie{
314312123Sngie	uvm.page_init_done = false;
315312123Sngie
316312123Sngie	atf_tc_expect_signal(SIGABRT, "array overrun alloc()");
317312123Sngie
318312123Sngie	uvm_physseg_alloc((VM_PHYSSEG_MAX + 1) * sizeof(struct uvm_physseg));
319312123Sngie
320312123Sngie}
321312123Sngie
322312123SngieATF_TC(uvm_physseg_alloc_sanity);
323312123SngieATF_TC_HEAD(uvm_physseg_alloc_sanity, tc)
324312123Sngie{
325312123Sngie	atf_tc_set_md_var(tc, "descr", "further uvm_physseg_alloc() sanity checks");
326312123Sngie}
327312123Sngie
328312123SngieATF_TC_BODY(uvm_physseg_alloc_sanity, tc)
329312123Sngie{
330312123Sngie
331312123Sngie	/* At boot time */
332312123Sngie	uvm.page_init_done = false;
333312123Sngie
334312123Sngie	/* Correct alloc */
335312123Sngie	ATF_REQUIRE(uvm_physseg_alloc(VM_PHYSSEG_MAX * sizeof(struct uvm_physseg)));
336312123Sngie
337312123Sngie	/* Retry static alloc()s as dynamic - we expect them to pass */
338312123Sngie	uvm.page_init_done = true;
339312123Sngie	ATF_REQUIRE(uvm_physseg_alloc(sizeof(struct uvm_physseg) - 1));
340312123Sngie	ATF_REQUIRE(uvm_physseg_alloc(2 * VM_PHYSSEG_MAX * sizeof(struct uvm_physseg)));
341312123Sngie}
342312123Sngie
343312123SngieATF_TC(uvm_physseg_free_atboot_mismatch);
344312123SngieATF_TC_HEAD(uvm_physseg_free_atboot_mismatch, tc)
345312123Sngie{
346312123Sngie	atf_tc_set_md_var(tc, "descr", "boot time uvm_physseg_free() sanity"
347312123Sngie	    "size mismatch free() test.");
348312123Sngie}
349312123Sngie
350312123SngieATF_TC_BODY(uvm_physseg_free_atboot_mismatch, tc)
351312123Sngie{
352312123Sngie	uvm.page_init_done = false;
353312123Sngie
354312123Sngie	atf_tc_expect_signal(SIGABRT, "size mismatch free()");
355312123Sngie
356312123Sngie	uvm_physseg_free(&uvm_physseg[0], sizeof(struct uvm_physseg) - 1);
357312123Sngie}
358312123Sngie
359312123SngieATF_TC(uvm_physseg_free_sanity);
360312123SngieATF_TC_HEAD(uvm_physseg_free_sanity, tc)
361312123Sngie{
362312123Sngie	atf_tc_set_md_var(tc, "descr", "further uvm_physseg_free() sanity checks");
363312123Sngie}
364312123Sngie
365312123SngieATF_TC_BODY(uvm_physseg_free_sanity, tc)
366312123Sngie{
367312123Sngie
368312123Sngie	/* At boot time */
369312123Sngie	uvm.page_init_done = false;
370312123Sngie
371312123Sngie	struct uvm_physseg *seg;
372312123Sngie
373312123Sngie#if VM_PHYSSEG_MAX > 1
374312123Sngie	/*
375312123Sngie	 * Note: free()ing the entire array is considered to be an
376312123Sngie	 * error. Thus VM_PHYSSEG_MAX - 1.
377312123Sngie	 */
378312123Sngie
379312123Sngie	seg = uvm_physseg_alloc((VM_PHYSSEG_MAX - 1) * sizeof(*seg));
380312123Sngie	uvm_physseg_free(seg, (VM_PHYSSEG_MAX - 1) * sizeof(struct uvm_physseg));
381312123Sngie#endif
382312123Sngie
383312123Sngie	/* Retry static alloc()s as dynamic - we expect them to pass */
384312123Sngie	uvm.page_init_done = true;
385312123Sngie
386312123Sngie	seg = uvm_physseg_alloc(sizeof(struct uvm_physseg) - 1);
387312123Sngie	uvm_physseg_free(seg, sizeof(struct uvm_physseg) - 1);
388312123Sngie
389312123Sngie	seg = uvm_physseg_alloc(2 * VM_PHYSSEG_MAX * sizeof(struct uvm_physseg));
390312123Sngie
391312123Sngie	uvm_physseg_free(seg, 2 * VM_PHYSSEG_MAX * sizeof(struct uvm_physseg));
392312123Sngie}
393312123Sngie
394312123Sngie#if VM_PHYSSEG_MAX > 1
395312123SngieATF_TC(uvm_physseg_atboot_free_leak);
396312123SngieATF_TC_HEAD(uvm_physseg_atboot_free_leak, tc)
397312123Sngie{
398312123Sngie	atf_tc_set_md_var(tc, "descr",
399312123Sngie	    "does free() leak at boot ?\n"
400312123Sngie	    "This test needs VM_PHYSSEG_MAX > 1)");
401312123Sngie}
402312123Sngie
403312123SngieATF_TC_BODY(uvm_physseg_atboot_free_leak, tc)
404312123Sngie{
405312123Sngie
406312123Sngie	/* At boot time */
407312123Sngie	uvm.page_init_done = false;
408312123Sngie
409312123Sngie	/* alloc to array size */
410312123Sngie	struct uvm_physseg *seg;
411312123Sngie	seg = uvm_physseg_alloc(VM_PHYSSEG_MAX * sizeof(*seg));
412312123Sngie
413312123Sngie	uvm_physseg_free(seg, sizeof(*seg));
414312123Sngie
415312123Sngie	atf_tc_expect_signal(SIGABRT, "array overrun on alloc() after leak");
416312123Sngie
417312123Sngie	ATF_REQUIRE(uvm_physseg_alloc(sizeof(struct uvm_physseg)));
418312123Sngie}
419312123Sngie#endif /* VM_PHYSSEG_MAX */
420312123Sngie#endif /* UVM_HOTPLUG */
421312123Sngie
422312123Sngie/*
423312123Sngie * Note: This function replicates verbatim what happens in
424312123Sngie * uvm_page.c:uvm_page_init().
425312123Sngie *
426312123Sngie * Please track any changes that happen there.
427312123Sngie */
428312123Sngiestatic void
429312123Sngieuvm_page_init_fake(struct vm_page *pagearray, psize_t pagecount)
430312123Sngie{
431312123Sngie	uvm_physseg_t bank;
432312123Sngie	size_t n;
433312123Sngie
434312123Sngie	for (bank = uvm_physseg_get_first(),
435312123Sngie		 uvm_physseg_seg_chomp_slab(bank, pagearray, pagecount);
436312123Sngie	     uvm_physseg_valid_p(bank);
437312123Sngie	     bank = uvm_physseg_get_next(bank)) {
438312123Sngie
439312123Sngie		n = uvm_physseg_get_end(bank) - uvm_physseg_get_start(bank);
440312123Sngie		uvm_physseg_seg_alloc_from_slab(bank, n);
441312123Sngie		uvm_physseg_init_seg(bank, pagearray);
442312123Sngie
443312123Sngie		/* set up page array pointers */
444312123Sngie		pagearray += n;
445312123Sngie		pagecount -= n;
446312123Sngie	}
447312123Sngie
448312123Sngie	uvm.page_init_done = true;
449312123Sngie}
450312123Sngie
451312123SngieATF_TC(uvm_physseg_plug);
452312123SngieATF_TC_HEAD(uvm_physseg_plug, tc)
453312123Sngie{
454312123Sngie	atf_tc_set_md_var(tc, "descr",
455312123Sngie	    "Test plug functionality.");
456312123Sngie}
457312123Sngie/* Note: We only do the second boot time plug if VM_PHYSSEG_MAX > 1 */
458312123SngieATF_TC_BODY(uvm_physseg_plug, tc)
459312123Sngie{
460312123Sngie	int nentries = 0; /* Count of entries via plug done so far */
461312123Sngie	uvm_physseg_t upm1;
462312123Sngie#if VM_PHYSSEG_MAX > 2
463312123Sngie	uvm_physseg_t upm2;
464312123Sngie#endif
465312123Sngie
466312123Sngie#if VM_PHYSSEG_MAX > 1
467312123Sngie	uvm_physseg_t upm3;
468312123Sngie#endif
469312123Sngie	uvm_physseg_t upm4;
470312123Sngie	psize_t npages1 = (VALID_END_PFN_1 - VALID_START_PFN_1);
471312123Sngie	psize_t npages2 = (VALID_END_PFN_2 - VALID_START_PFN_2);
472312123Sngie	psize_t npages3 = (VALID_END_PFN_3 - VALID_START_PFN_3);
473312123Sngie	psize_t npages4 = (VALID_END_PFN_4 - VALID_START_PFN_4);
474312123Sngie	struct vm_page *pgs, *slab = malloc(sizeof(struct vm_page) * (npages1
475312123Sngie#if VM_PHYSSEG_MAX > 2
476312123Sngie		+ npages2
477312123Sngie#endif
478312123Sngie		+ npages3));
479312123Sngie
480312123Sngie	/* Fake early boot */
481312123Sngie
482312123Sngie	setup();
483312123Sngie
484312123Sngie	/* Vanilla plug x 2 */
485312123Sngie	ATF_REQUIRE_EQ(uvm_physseg_plug(VALID_START_PFN_1, npages1, &upm1), true);
486312123Sngie	ATF_REQUIRE_EQ(++nentries, uvm_physseg_get_entries());
487312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
488312123Sngie
489312123Sngie#if VM_PHYSSEG_MAX > 2
490312123Sngie	ATF_REQUIRE_EQ(uvm_physseg_plug(VALID_START_PFN_2, npages2, &upm2), true);
491312123Sngie	ATF_REQUIRE_EQ(++nentries, uvm_physseg_get_entries());
492312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
493312123Sngie#endif
494312123Sngie	/* Post boot: Fake all segments and pages accounted for. */
495312123Sngie	uvm_page_init_fake(slab, npages1 + npages2 + npages3);
496312123Sngie
497312123Sngie	ATF_CHECK_EQ(npages1
498312123Sngie#if VM_PHYSSEG_MAX > 2
499312123Sngie	    + npages2
500312123Sngie#endif
501312123Sngie	    , uvmexp.npages);
502312123Sngie#if VM_PHYSSEG_MAX > 1
503312123Sngie	/* Scavenge plug - goes into the same slab */
504312123Sngie	ATF_REQUIRE_EQ(uvm_physseg_plug(VALID_START_PFN_3, npages3, &upm3), true);
505312123Sngie	ATF_REQUIRE_EQ(++nentries, uvm_physseg_get_entries());
506312123Sngie	ATF_REQUIRE_EQ(npages1
507312123Sngie#if VM_PHYSSEG_MAX > 2
508312123Sngie	    + npages2
509312123Sngie#endif
510312123Sngie	    + npages3, uvmexp.npages);
511312123Sngie
512312123Sngie	/* Scavenge plug should fit right in the slab */
513312123Sngie	pgs = uvm_physseg_get_pg(upm3, 0);
514312123Sngie	ATF_REQUIRE(pgs > slab && pgs < (slab + npages1 + npages2 + npages3));
515312123Sngie#endif
516312123Sngie	/* Hot plug - goes into a brand new slab */
517312123Sngie	ATF_REQUIRE_EQ(uvm_physseg_plug(VALID_START_PFN_4, npages4, &upm4), true);
518312123Sngie	/* The hot plug slab should have nothing to do with the original slab */
519312123Sngie	pgs = uvm_physseg_get_pg(upm4, 0);
520312123Sngie	ATF_REQUIRE(pgs < slab || pgs > (slab + npages1
521312123Sngie#if VM_PHYSSEG_MAX > 2
522312123Sngie		+ npages2
523312123Sngie#endif
524312123Sngie		+ npages3));
525312123Sngie
526312123Sngie}
527312123SngieATF_TC(uvm_physseg_unplug);
528312123SngieATF_TC_HEAD(uvm_physseg_unplug, tc)
529312123Sngie{
530312123Sngie	atf_tc_set_md_var(tc, "descr",
531312123Sngie	    "Test unplug functionality.");
532312123Sngie}
533312123SngieATF_TC_BODY(uvm_physseg_unplug, tc)
534312123Sngie{
535312123Sngie	paddr_t pa = 0;
536312123Sngie
537312123Sngie	psize_t npages1 = (VALID_END_PFN_1 - VALID_START_PFN_1);
538312123Sngie	psize_t npages2 = (VALID_END_PFN_2 - VALID_START_PFN_2);
539312123Sngie	psize_t npages3 = (VALID_END_PFN_3 - VALID_START_PFN_3);
540312123Sngie
541312123Sngie	struct vm_page *slab = malloc(sizeof(struct vm_page) * (npages1 + npages2 + npages3));
542312123Sngie
543312123Sngie	uvm_physseg_t upm;
544312123Sngie
545312123Sngie	/* Boot time */
546312123Sngie	setup();
547312123Sngie
548312123Sngie	/* We start with zero segments */
549312123Sngie	ATF_REQUIRE_EQ(true, uvm_physseg_plug(atop(0), atop(ONE_MEGABYTE), NULL));
550312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
551312123Sngie	/* Do we have an arbitrary offset in there ? */
552312123Sngie	uvm_physseg_find(atop(TWOFIFTYSIX_KILO), &pa);
553312123Sngie	ATF_REQUIRE_EQ(pa, atop(TWOFIFTYSIX_KILO));
554312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages); /* Boot time sanity */
555312123Sngie
556312123Sngie#if VM_PHYSSEG_MAX == 1
557312123Sngie	/*
558312123Sngie	 * This is the curious case at boot time, of having one
559312123Sngie	 * extent(9) static entry per segment, which means that a
560312123Sngie	 * fragmenting unplug will fail.
561312123Sngie	 */
562312123Sngie	atf_tc_expect_signal(SIGABRT, "fragmenting unplug for single segment");
563312123Sngie
564312123Sngie	/*
565312123Sngie	 * In order to test the fragmenting cases, please set
566312123Sngie	 * VM_PHYSSEG_MAX > 1
567312123Sngie	 */
568312123Sngie#endif
569312123Sngie	/* Now let's unplug from the middle */
570312123Sngie	ATF_REQUIRE_EQ(true, uvm_physseg_unplug(atop(TWOFIFTYSIX_KILO), atop(FIVEONETWO_KILO)));
571312123Sngie	/* verify that a gap exists at TWOFIFTYSIX_KILO */
572312123Sngie	pa = 0; /* reset */
573312123Sngie	uvm_physseg_find(atop(TWOFIFTYSIX_KILO), &pa);
574312123Sngie	ATF_REQUIRE_EQ(pa, 0);
575312123Sngie
576312123Sngie	/* Post boot: Fake all segments and pages accounted for. */
577312123Sngie	uvm_page_init_fake(slab, npages1 + npages2 + npages3);
578312123Sngie	/* Account for the unplug */
579312123Sngie	ATF_CHECK_EQ(atop(FIVEONETWO_KILO), uvmexp.npages);
580312123Sngie
581312123Sngie	/* Original entry should fragment into two */
582312123Sngie	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
583312123Sngie
584312123Sngie	upm = uvm_physseg_find(atop(TWOFIFTYSIX_KILO + FIVEONETWO_KILO), NULL);
585312123Sngie
586312123Sngie	ATF_REQUIRE(uvm_physseg_valid_p(upm));
587312123Sngie
588312123Sngie	/* Now unplug the tail fragment - should swallow the complete entry */
589312123Sngie	ATF_REQUIRE_EQ(true, uvm_physseg_unplug(atop(TWOFIFTYSIX_KILO + FIVEONETWO_KILO), atop(TWOFIFTYSIX_KILO)));
590312123Sngie
591312123Sngie	/* The "swallow" above should have invalidated the handle */
592312123Sngie	ATF_REQUIRE_EQ(false, uvm_physseg_valid_p(upm));
593312123Sngie
594312123Sngie	/* Only the first one is left now */
595312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
596312123Sngie
597312123Sngie	/* Unplug from the back */
598312123Sngie	ATF_REQUIRE_EQ(true, uvm_physseg_unplug(atop(ONETWENTYEIGHT_KILO), atop(ONETWENTYEIGHT_KILO)));
599312123Sngie	/* Shouldn't change the number of segments */
600312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
601312123Sngie
602312123Sngie	/* Unplug from the front */
603312123Sngie	ATF_REQUIRE_EQ(true, uvm_physseg_unplug(0, atop(SIXTYFOUR_KILO)));
604312123Sngie	/* Shouldn't change the number of segments */
605312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
606312123Sngie
607312123Sngie	/* Unplugging the final fragment should fail */
608312123Sngie	atf_tc_expect_signal(SIGABRT, "Unplugging the last segment");
609312123Sngie	ATF_REQUIRE_EQ(true, uvm_physseg_unplug(atop(SIXTYFOUR_KILO), atop(SIXTYFOUR_KILO)));
610312123Sngie}
611312123Sngie
612312123Sngie
613312123Sngie/* <---- end Tests for Internal functions ----> */
614312123Sngie
615312123Sngie/* Tests for functions exported via uvm_physseg.h */
616312123SngieATF_TC(uvm_physseg_init);
617312123SngieATF_TC_HEAD(uvm_physseg_init, tc)
618312123Sngie{
619312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the basic uvm_page_init() call\
620312123Sngie	    initializes the vm_physmem struct which holds the rb_tree.");
621312123Sngie}
622312123SngieATF_TC_BODY(uvm_physseg_init, tc)
623312123Sngie{
624312123Sngie	uvm_physseg_init();
625312123Sngie
626312123Sngie	ATF_REQUIRE_EQ(0, uvm_physseg_get_entries());
627312123Sngie}
628312123Sngie
629312123SngieATF_TC(uvm_page_physload_preload);
630312123SngieATF_TC_HEAD(uvm_page_physload_preload, tc)
631312123Sngie{
632312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the basic uvm_page_physload() \
633312123Sngie	    call works without a panic() in a preload scenario.");
634312123Sngie}
635312123SngieATF_TC_BODY(uvm_page_physload_preload, tc)
636312123Sngie{
637312123Sngie	uvm_physseg_t upm;
638312123Sngie
639312123Sngie	setup();
640312123Sngie
641312123Sngie	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
642312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
643312123Sngie
644312123Sngie	/* Should return a valid handle */
645312123Sngie	ATF_REQUIRE(uvm_physseg_valid_p(upm));
646312123Sngie
647312123Sngie	/* No pages should be allocated yet */
648312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
649312123Sngie
650312123Sngie	/* After the first call one segment should exist */
651312123Sngie	ATF_CHECK_EQ(1, uvm_physseg_get_entries());
652312123Sngie
653312123Sngie	/* Insert more than one segment iff VM_PHYSSEG_MAX > 1 */
654312123Sngie#if VM_PHYSSEG_MAX > 1
655312123Sngie	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
656312123Sngie	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
657312123Sngie
658312123Sngie	/* Should return a valid handle */
659312123Sngie	ATF_REQUIRE(uvm_physseg_valid_p(upm));
660312123Sngie
661312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
662312123Sngie
663312123Sngie	/* After the second call two segments should exist */
664312123Sngie	ATF_CHECK_EQ(2, uvm_physseg_get_entries());
665312123Sngie#endif
666312123Sngie}
667312123Sngie
668312123SngieATF_TC(uvm_page_physload_postboot);
669312123SngieATF_TC_HEAD(uvm_page_physload_postboot, tc)
670312123Sngie{
671312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the basic uvm_page_physload() \
672312123Sngie	     panic()s in a post boot scenario.");
673312123Sngie}
674312123SngieATF_TC_BODY(uvm_page_physload_postboot, tc)
675312123Sngie{
676312123Sngie	uvm_physseg_t upm;
677312123Sngie
678312123Sngie	psize_t npages1 = (VALID_END_PFN_1 - VALID_START_PFN_1);
679312123Sngie	psize_t npages2 = (VALID_END_PFN_2 - VALID_START_PFN_2);
680312123Sngie
681312123Sngie	struct vm_page *slab = malloc(sizeof(struct vm_page) * (npages1 + npages2));
682312123Sngie
683312123Sngie	setup();
684312123Sngie
685312123Sngie	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
686312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
687312123Sngie
688312123Sngie	/* Should return a valid handle */
689312123Sngie	ATF_REQUIRE(uvm_physseg_valid_p(upm));
690312123Sngie
691312123Sngie	/* No pages should be allocated yet */
692312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
693312123Sngie
694312123Sngie	/* After the first call one segment should exist */
695312123Sngie	ATF_CHECK_EQ(1, uvm_physseg_get_entries());
696312123Sngie
697312123Sngie	/* Post boot: Fake all segments and pages accounted for. */
698312123Sngie	uvm_page_init_fake(slab, npages1 + npages2);
699312123Sngie
700312123Sngie	atf_tc_expect_signal(SIGABRT,
701312123Sngie	    "uvm_page_physload() called post boot");
702312123Sngie
703312123Sngie	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
704312123Sngie	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
705312123Sngie
706312123Sngie	/* Should return a valid handle */
707312123Sngie	ATF_REQUIRE(uvm_physseg_valid_p(upm));
708312123Sngie
709312123Sngie	ATF_REQUIRE_EQ(npages1 + npages2, uvmexp.npages);
710312123Sngie
711312123Sngie	/* After the second call two segments should exist */
712312123Sngie	ATF_CHECK_EQ(2, uvm_physseg_get_entries());
713312123Sngie}
714312123Sngie
715312123SngieATF_TC(uvm_physseg_handle_immutable);
716312123SngieATF_TC_HEAD(uvm_physseg_handle_immutable, tc)
717312123Sngie{
718312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the uvm_physseg_t handle is \
719312123Sngie	    immutable.");
720312123Sngie}
721312123SngieATF_TC_BODY(uvm_physseg_handle_immutable, tc)
722312123Sngie{
723312123Sngie	uvm_physseg_t upm;
724312123Sngie
725312123Sngie	/* We insert the segments in out of order */
726312123Sngie
727312123Sngie	setup();
728312123Sngie
729312123Sngie	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
730312123Sngie	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
731312123Sngie
732312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
733312123Sngie
734312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
735312123Sngie
736312123Sngie	ATF_CHECK_EQ(UVM_PHYSSEG_TYPE_INVALID_EMPTY, uvm_physseg_get_prev(upm));
737312123Sngie
738312123Sngie	/* Insert more than one segment iff VM_PHYSSEG_MAX > 1 */
739312123Sngie#if VM_PHYSSEG_MAX > 1
740312123Sngie	uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
741312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
742312123Sngie
743312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
744312123Sngie
745312123Sngie	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
746312123Sngie
747312123Sngie	/* Fetch Previous, we inserted a lower value */
748312123Sngie	upm = uvm_physseg_get_prev(upm);
749312123Sngie
750312123Sngie#if !defined(UVM_HOTPLUG)
751312123Sngie	/*
752312123Sngie	 * This test is going to fail for the Array Implementation but is
753312123Sngie	 * expected to pass in the RB Tree implementation.
754312123Sngie	 */
755312123Sngie	/* Failure can be expected iff there are more than one handles */
756312123Sngie	atf_tc_expect_fail("Mutable handle in static array impl.");
757312123Sngie#endif
758312123Sngie	ATF_CHECK(UVM_PHYSSEG_TYPE_INVALID_EMPTY != upm);
759312123Sngie	ATF_CHECK_EQ(VALID_START_PFN_1, uvm_physseg_get_start(upm));
760312123Sngie	ATF_CHECK_EQ(VALID_END_PFN_1, uvm_physseg_get_end(upm));
761312123Sngie#endif
762312123Sngie}
763312123Sngie
764312123SngieATF_TC(uvm_physseg_seg_chomp_slab);
765312123SngieATF_TC_HEAD(uvm_physseg_seg_chomp_slab, tc)
766312123Sngie{
767312123Sngie	atf_tc_set_md_var(tc, "descr", "The slab import code.()");
768312123Sngie
769312123Sngie}
770312123SngieATF_TC_BODY(uvm_physseg_seg_chomp_slab, tc)
771312123Sngie{
772312123Sngie	int err;
773312123Sngie	size_t i;
774312123Sngie	struct uvm_physseg *seg;
775312123Sngie	struct vm_page *slab, *pgs;
776312123Sngie	const size_t npages = UVM_PHYSSEG_BOOT_UNPLUG_MAX; /* Number of pages */
777312123Sngie
778312123Sngie	setup();
779312123Sngie
780312123Sngie	/* This is boot time */
781312123Sngie	slab = malloc(sizeof(struct vm_page) * npages * 2);
782312123Sngie
783312123Sngie	seg = uvm_physseg_alloc(sizeof(struct uvm_physseg));
784312123Sngie
785312123Sngie	uvm_physseg_seg_chomp_slab(PHYSSEG_NODE_TO_HANDLE(seg), slab, npages * 2);
786312123Sngie
787312123Sngie	/* Should be able to allocate two 128 * sizeof(*slab) */
788312123Sngie	ATF_REQUIRE_EQ(0, extent_alloc(seg->ext, sizeof(*slab), 1, 0, EX_BOUNDZERO, (void *)&pgs));
789312123Sngie	err = extent_free(seg->ext, (u_long) pgs, sizeof(*slab), EX_BOUNDZERO);
790312123Sngie
791312123Sngie#if VM_PHYSSEG_MAX == 1
792312123Sngie	/*
793312123Sngie	 * free() needs an extra region descriptor, but we only have
794312123Sngie	 * one! The classic alloc() at free() problem
795312123Sngie	 */
796312123Sngie
797312123Sngie	ATF_REQUIRE_EQ(ENOMEM, err);
798312123Sngie#else
799312123Sngie	/* Try alloc/free at static time */
800312123Sngie	for (i = 0; i < npages; i++) {
801312123Sngie		ATF_REQUIRE_EQ(0, extent_alloc(seg->ext, sizeof(*slab), 1, 0, EX_BOUNDZERO, (void *)&pgs));
802312123Sngie		err = extent_free(seg->ext, (u_long) pgs, sizeof(*slab), EX_BOUNDZERO);
803312123Sngie		ATF_REQUIRE_EQ(0, err);
804312123Sngie	}
805312123Sngie#endif
806312123Sngie
807312123Sngie	/* Now setup post boot */
808312123Sngie	uvm.page_init_done = true;
809312123Sngie
810312123Sngie	uvm_physseg_seg_chomp_slab(PHYSSEG_NODE_TO_HANDLE(seg), slab, npages * 2);
811312123Sngie
812312123Sngie	/* Try alloc/free after uvm_page.c:uvm_page_init() as well */
813312123Sngie	for (i = 0; i < npages; i++) {
814312123Sngie		ATF_REQUIRE_EQ(0, extent_alloc(seg->ext, sizeof(*slab), 1, 0, EX_BOUNDZERO, (void *)&pgs));
815312123Sngie		err = extent_free(seg->ext, (u_long) pgs, sizeof(*slab), EX_BOUNDZERO);
816312123Sngie		ATF_REQUIRE_EQ(0, err);
817312123Sngie	}
818312123Sngie
819312123Sngie}
820312123Sngie
821312123SngieATF_TC(uvm_physseg_alloc_from_slab);
822312123SngieATF_TC_HEAD(uvm_physseg_alloc_from_slab, tc)
823312123Sngie{
824312123Sngie	atf_tc_set_md_var(tc, "descr", "The slab alloc code.()");
825312123Sngie
826312123Sngie}
827312123SngieATF_TC_BODY(uvm_physseg_alloc_from_slab, tc)
828312123Sngie{
829312123Sngie	struct uvm_physseg *seg;
830312123Sngie	struct vm_page *slab, *pgs;
831312123Sngie	const size_t npages = UVM_PHYSSEG_BOOT_UNPLUG_MAX; /* Number of pages */
832312123Sngie
833312123Sngie	setup();
834312123Sngie
835312123Sngie	/* This is boot time */
836312123Sngie	slab = malloc(sizeof(struct vm_page) * npages * 2);
837312123Sngie
838312123Sngie	seg = uvm_physseg_alloc(sizeof(struct uvm_physseg));
839312123Sngie
840312123Sngie	uvm_physseg_seg_chomp_slab(PHYSSEG_NODE_TO_HANDLE(seg), slab, npages * 2);
841312123Sngie
842312123Sngie	pgs = uvm_physseg_seg_alloc_from_slab(PHYSSEG_NODE_TO_HANDLE(seg), npages);
843312123Sngie
844312123Sngie	ATF_REQUIRE(pgs != NULL);
845312123Sngie
846312123Sngie	/* Now setup post boot */
847312123Sngie	uvm.page_init_done = true;
848312123Sngie
849312123Sngie#if VM_PHYSSEG_MAX > 1
850312123Sngie	pgs = uvm_physseg_seg_alloc_from_slab(PHYSSEG_NODE_TO_HANDLE(seg), npages);
851312123Sngie	ATF_REQUIRE(pgs != NULL);
852312123Sngie#endif
853312123Sngie	atf_tc_expect_fail("alloc beyond extent");
854312123Sngie
855312123Sngie	pgs = uvm_physseg_seg_alloc_from_slab(PHYSSEG_NODE_TO_HANDLE(seg), npages);
856312123Sngie	ATF_REQUIRE(pgs != NULL);
857312123Sngie}
858312123Sngie
859312123SngieATF_TC(uvm_physseg_init_seg);
860312123SngieATF_TC_HEAD(uvm_physseg_init_seg, tc)
861312123Sngie{
862312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if uvm_physseg_init_seg adds pages to"
863312123Sngie	    "uvmexp.npages");
864312123Sngie}
865312123SngieATF_TC_BODY(uvm_physseg_init_seg, tc)
866312123Sngie{
867312123Sngie	struct uvm_physseg *seg;
868312123Sngie	struct vm_page *slab, *pgs;
869312123Sngie	const size_t npages = UVM_PHYSSEG_BOOT_UNPLUG_MAX; /* Number of pages */
870312123Sngie
871312123Sngie	setup();
872312123Sngie
873312123Sngie	/* This is boot time */
874312123Sngie	slab = malloc(sizeof(struct vm_page) * npages * 2);
875312123Sngie
876312123Sngie	seg = uvm_physseg_alloc(sizeof(struct uvm_physseg));
877312123Sngie
878312123Sngie	uvm_physseg_seg_chomp_slab(PHYSSEG_NODE_TO_HANDLE(seg), slab, npages * 2);
879312123Sngie
880312123Sngie	pgs = uvm_physseg_seg_alloc_from_slab(PHYSSEG_NODE_TO_HANDLE(seg), npages);
881312123Sngie
882312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
883312123Sngie
884312123Sngie	seg->start = 0;
885312123Sngie	seg->end = npages;
886312123Sngie
887312123Sngie	seg->avail_start = 0;
888312123Sngie	seg->avail_end = npages;
889312123Sngie
890312123Sngie	uvm_physseg_init_seg(PHYSSEG_NODE_TO_HANDLE(seg), pgs);
891312123Sngie
892312123Sngie	ATF_REQUIRE_EQ(npages, uvmexp.npages);
893312123Sngie}
894312123Sngie
895312123Sngie#if 0
896312123SngieATF_TC(uvm_physseg_init_seg);
897312123SngieATF_TC_HEAD(uvm_physseg_init_seg, tc)
898312123Sngie{
899312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the basic uvm_page_physload() \
900312123Sngie	    call works without a panic() after Segment is inited.");
901312123Sngie}
902312123SngieATF_TC_BODY(uvm_physseg_init_seg, tc)
903312123Sngie{
904312123Sngie	uvm_physseg_t upm;
905312123Sngie	psize_t npages = (VALID_END_PFN_1 - VALID_START_PFN_1);
906312123Sngie	struct vm_page *pgs = malloc(sizeof(struct vm_page) * npages);
907312123Sngie
908312123Sngie	setup();
909312123Sngie	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
910312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
911312123Sngie
912312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
913312123Sngie
914312123Sngie	ATF_CHECK_EQ(0, uvmexp.npages);
915312123Sngie
916312123Sngie	/*
917312123Sngie	 * Boot time physplug needs explicit external init,
918312123Sngie	 * Duplicate what uvm_page.c:uvm_page_init() does.
919312123Sngie	 * Note: not everything uvm_page_init() does gets done here.
920312123Sngie	 * Read the source.
921312123Sngie	 */
922312123Sngie	/* suck in backing slab, initialise extent. */
923312123Sngie	uvm_physseg_seg_chomp_slab(upm, pgs, npages);
924312123Sngie
925312123Sngie	/*
926312123Sngie	 * Actual pgs[] allocation, from extent.
927312123Sngie	 */
928312123Sngie	uvm_physseg_alloc_from_slab(upm, npages);
929312123Sngie
930312123Sngie	/* Now we initialize the segment */
931312123Sngie	uvm_physseg_init_seg(upm, pgs);
932312123Sngie
933312123Sngie	/* Done with boot simulation */
934312123Sngie	extent_init();
935312123Sngie	uvm.page_init_done = true;
936312123Sngie
937312123Sngie	/* We have total memory of 1MB */
938312123Sngie	ATF_CHECK_EQ(PAGE_COUNT_1M, uvmexp.npages);
939312123Sngie
940312123Sngie	upm =uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
941312123Sngie	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
942312123Sngie	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
943312123Sngie
944312123Sngie	/* We added another 1MB so PAGE_COUNT_1M + PAGE_COUNT_1M */
945312123Sngie	ATF_CHECK_EQ(PAGE_COUNT_1M + PAGE_COUNT_1M, uvmexp.npages);
946312123Sngie
947312123Sngie}
948312123Sngie#endif
949312123Sngie
950312123SngieATF_TC(uvm_physseg_get_start);
951312123SngieATF_TC_HEAD(uvm_physseg_get_start, tc)
952312123Sngie{
953312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the start PFN is returned \
954312123Sngie	    correctly from a segment created via uvm_page_physload().");
955312123Sngie}
956312123SngieATF_TC_BODY(uvm_physseg_get_start, tc)
957312123Sngie{
958312123Sngie	uvm_physseg_t upm;
959312123Sngie
960312123Sngie	/* Fake early boot */
961312123Sngie	setup();
962312123Sngie
963312123Sngie	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
964312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
965312123Sngie
966312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
967312123Sngie
968312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
969312123Sngie
970312123Sngie	ATF_CHECK_EQ(VALID_START_PFN_1, uvm_physseg_get_start(upm));
971312123Sngie
972312123Sngie	/* This test will be triggered only if there are 2 or more segments. */
973312123Sngie#if VM_PHYSSEG_MAX > 1
974312123Sngie	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
975312123Sngie	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
976312123Sngie
977312123Sngie	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
978312123Sngie
979312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
980312123Sngie
981312123Sngie	ATF_CHECK_EQ(VALID_START_PFN_2, uvm_physseg_get_start(upm));
982312123Sngie#endif
983312123Sngie}
984312123Sngie
985312123SngieATF_TC(uvm_physseg_get_start_invalid);
986312123SngieATF_TC_HEAD(uvm_physseg_get_start_invalid, tc)
987312123Sngie{
988312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests the invalid / error conditions \
989312123Sngie	    correctly when uvm_physseg_get_start() is called with invalid \
990312123Sngie	    parameter values.");
991312123Sngie}
992312123SngieATF_TC_BODY(uvm_physseg_get_start_invalid, tc)
993312123Sngie{
994312123Sngie	/* Check for pgs == NULL */
995312123Sngie	setup();
996312123Sngie	uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
997312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
998312123Sngie
999312123Sngie	/* Force other check conditions */
1000312123Sngie	uvm.page_init_done = true;
1001312123Sngie
1002312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1003312123Sngie
1004312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
1005312123Sngie
1006312123Sngie	ATF_REQUIRE_EQ(true, uvm.page_init_done);
1007312123Sngie
1008312123Sngie	/* Invalid uvm_physseg_t */
1009312123Sngie	ATF_CHECK_EQ((paddr_t) -1,
1010312123Sngie	    uvm_physseg_get_start(UVM_PHYSSEG_TYPE_INVALID));
1011312123Sngie}
1012312123Sngie
1013312123SngieATF_TC(uvm_physseg_get_end);
1014312123SngieATF_TC_HEAD(uvm_physseg_get_end, tc)
1015312123Sngie{
1016312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the end PFN is returned \
1017312123Sngie	    correctly from a segment created via uvm_page_physload().");
1018312123Sngie}
1019312123SngieATF_TC_BODY(uvm_physseg_get_end, tc)
1020312123Sngie{
1021312123Sngie	uvm_physseg_t upm;
1022312123Sngie
1023312123Sngie	setup();
1024312123Sngie	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1025312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1026312123Sngie
1027312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1028312123Sngie
1029312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
1030312123Sngie
1031312123Sngie	ATF_CHECK_EQ(VALID_END_PFN_1, uvm_physseg_get_end(upm));
1032312123Sngie
1033312123Sngie	/* This test will be triggered only if there are 2 or more segments. */
1034312123Sngie#if VM_PHYSSEG_MAX > 1
1035312123Sngie	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
1036312123Sngie	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
1037312123Sngie
1038312123Sngie	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
1039312123Sngie
1040312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1041312123Sngie
1042312123Sngie	ATF_CHECK_EQ(VALID_END_PFN_2, uvm_physseg_get_end(upm));
1043312123Sngie#endif
1044312123Sngie}
1045312123Sngie
1046312123SngieATF_TC(uvm_physseg_get_end_invalid);
1047312123SngieATF_TC_HEAD(uvm_physseg_get_end_invalid, tc)
1048312123Sngie{
1049312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests the invalid / error conditions \
1050312123Sngie	    correctly when uvm_physseg_get_end() is called with invalid \
1051312123Sngie	    parameter values.");
1052312123Sngie}
1053312123SngieATF_TC_BODY(uvm_physseg_get_end_invalid, tc)
1054312123Sngie{
1055312123Sngie	/* Check for pgs == NULL */
1056312123Sngie	setup();
1057312123Sngie	uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1058312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1059312123Sngie
1060312123Sngie	/* Force other check conditions */
1061312123Sngie	uvm.page_init_done = true;
1062312123Sngie
1063312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1064312123Sngie
1065312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
1066312123Sngie
1067312123Sngie	ATF_REQUIRE_EQ(true, uvm.page_init_done);
1068312123Sngie
1069312123Sngie	/* Invalid uvm_physseg_t */
1070312123Sngie	ATF_CHECK_EQ((paddr_t) -1,
1071312123Sngie	    uvm_physseg_get_end(UVM_PHYSSEG_TYPE_INVALID));
1072312123Sngie}
1073312123Sngie
1074312123SngieATF_TC(uvm_physseg_get_avail_start);
1075312123SngieATF_TC_HEAD(uvm_physseg_get_avail_start, tc)
1076312123Sngie{
1077312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the avail_start PFN is \
1078312123Sngie	    returned correctly from a segment created via uvm_page_physload().");
1079312123Sngie}
1080312123SngieATF_TC_BODY(uvm_physseg_get_avail_start, tc)
1081312123Sngie{
1082312123Sngie	uvm_physseg_t upm;
1083312123Sngie
1084312123Sngie	setup();
1085312123Sngie	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1086312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1087312123Sngie
1088312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1089312123Sngie
1090312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
1091312123Sngie
1092312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_1, uvm_physseg_get_avail_start(upm));
1093312123Sngie
1094312123Sngie	/* This test will be triggered only if there are 2 or more segments. */
1095312123Sngie#if VM_PHYSSEG_MAX > 1
1096312123Sngie	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
1097312123Sngie	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
1098312123Sngie
1099312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1100312123Sngie
1101312123Sngie	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
1102312123Sngie
1103312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_2, uvm_physseg_get_avail_start(upm));
1104312123Sngie#endif
1105312123Sngie}
1106312123Sngie
1107312123SngieATF_TC(uvm_physseg_get_avail_start_invalid);
1108312123SngieATF_TC_HEAD(uvm_physseg_get_avail_start_invalid, tc)
1109312123Sngie{
1110312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests the invalid / error conditions \
1111312123Sngie	    correctly when uvm_physseg_get_avail_start() is called with invalid\
1112312123Sngie	    parameter values.");
1113312123Sngie}
1114312123SngieATF_TC_BODY(uvm_physseg_get_avail_start_invalid, tc)
1115312123Sngie{
1116312123Sngie	/* Check for pgs == NULL */
1117312123Sngie	setup();
1118312123Sngie	uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1119312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1120312123Sngie
1121312123Sngie	/* Force other check conditions */
1122312123Sngie	uvm.page_init_done = true;
1123312123Sngie
1124312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1125312123Sngie
1126312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
1127312123Sngie
1128312123Sngie	ATF_REQUIRE_EQ(true, uvm.page_init_done);
1129312123Sngie
1130312123Sngie	/* Invalid uvm_physseg_t */
1131312123Sngie	ATF_CHECK_EQ((paddr_t) -1,
1132312123Sngie	    uvm_physseg_get_avail_start(UVM_PHYSSEG_TYPE_INVALID));
1133312123Sngie}
1134312123Sngie
1135312123SngieATF_TC(uvm_physseg_get_avail_end);
1136312123SngieATF_TC_HEAD(uvm_physseg_get_avail_end, tc)
1137312123Sngie{
1138312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the avail_end PFN is \
1139312123Sngie	    returned correctly from a segment created via uvm_page_physload().");
1140312123Sngie}
1141312123SngieATF_TC_BODY(uvm_physseg_get_avail_end, tc)
1142312123Sngie{
1143312123Sngie	uvm_physseg_t upm;
1144312123Sngie
1145312123Sngie	setup();
1146312123Sngie	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1147312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1148312123Sngie
1149312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1150312123Sngie
1151312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
1152312123Sngie
1153312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_1, uvm_physseg_get_avail_end(upm));
1154312123Sngie
1155312123Sngie	/* This test will be triggered only if there are 2 or more segments. */
1156312123Sngie#if VM_PHYSSEG_MAX > 1
1157312123Sngie	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
1158312123Sngie	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
1159312123Sngie
1160312123Sngie	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
1161312123Sngie
1162312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1163312123Sngie
1164312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_2, uvm_physseg_get_avail_end(upm));
1165312123Sngie#endif
1166312123Sngie}
1167312123Sngie
1168312123SngieATF_TC(uvm_physseg_get_avail_end_invalid);
1169312123SngieATF_TC_HEAD(uvm_physseg_get_avail_end_invalid, tc)
1170312123Sngie{
1171312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests the invalid / error conditions \
1172312123Sngie	    correctly when uvm_physseg_get_avail_end() is called with invalid\
1173312123Sngie	    parameter values.");
1174312123Sngie}
1175312123SngieATF_TC_BODY(uvm_physseg_get_avail_end_invalid, tc)
1176312123Sngie{
1177312123Sngie	/* Check for pgs == NULL */
1178312123Sngie	setup();
1179312123Sngie	uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1180312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1181312123Sngie
1182312123Sngie	/* Force other check conditions */
1183312123Sngie	uvm.page_init_done = true;
1184312123Sngie
1185312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1186312123Sngie
1187312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
1188312123Sngie
1189312123Sngie	ATF_REQUIRE_EQ(true, uvm.page_init_done);
1190312123Sngie
1191312123Sngie	/* Invalid uvm_physseg_t */
1192312123Sngie	ATF_CHECK_EQ((paddr_t) -1,
1193312123Sngie	    uvm_physseg_get_avail_end(UVM_PHYSSEG_TYPE_INVALID));
1194312123Sngie}
1195312123Sngie
1196312123SngieATF_TC(uvm_physseg_get_next);
1197312123SngieATF_TC_HEAD(uvm_physseg_get_next, tc)
1198312123Sngie{
1199312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests the pointer values for next \
1200312123Sngie	    segment using the uvm_physseg_get_next() call.");
1201312123Sngie}
1202312123SngieATF_TC_BODY(uvm_physseg_get_next, tc)
1203312123Sngie{
1204312123Sngie	uvm_physseg_t upm;
1205312123Sngie#if VM_PHYSSEG_MAX > 1
1206312123Sngie	uvm_physseg_t upm_next;
1207312123Sngie#endif
1208312123Sngie
1209312123Sngie	/* We insert the segments in ascending order */
1210312123Sngie
1211312123Sngie	setup();
1212312123Sngie	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1213312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1214312123Sngie
1215312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1216312123Sngie
1217312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
1218312123Sngie
1219312123Sngie	ATF_CHECK_EQ(UVM_PHYSSEG_TYPE_INVALID_OVERFLOW,
1220312123Sngie	    uvm_physseg_get_next(upm));
1221312123Sngie
1222312123Sngie	/* This test will be triggered only if there are 2 or more segments. */
1223312123Sngie#if VM_PHYSSEG_MAX > 1
1224312123Sngie	upm_next = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
1225312123Sngie	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
1226312123Sngie
1227312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1228312123Sngie
1229312123Sngie	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
1230312123Sngie
1231312123Sngie	upm = uvm_physseg_get_next(upm); /* Fetch Next */
1232312123Sngie
1233312123Sngie	ATF_CHECK_EQ(upm_next, upm);
1234312123Sngie	ATF_CHECK_EQ(VALID_START_PFN_2, uvm_physseg_get_start(upm));
1235312123Sngie	ATF_CHECK_EQ(VALID_END_PFN_2, uvm_physseg_get_end(upm));
1236312123Sngie#endif
1237312123Sngie
1238312123Sngie	/* This test will be triggered only if there are 3 or more segments. */
1239312123Sngie#if VM_PHYSSEG_MAX > 2
1240312123Sngie	upm_next = uvm_page_physload(VALID_START_PFN_3, VALID_END_PFN_3,
1241312123Sngie	    VALID_AVAIL_START_PFN_3, VALID_AVAIL_END_PFN_3, VM_FREELIST_DEFAULT);
1242312123Sngie
1243312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1244312123Sngie
1245312123Sngie	ATF_REQUIRE_EQ(3, uvm_physseg_get_entries());
1246312123Sngie
1247312123Sngie	upm = uvm_physseg_get_next(upm); /* Fetch Next */
1248312123Sngie
1249312123Sngie	ATF_CHECK_EQ(upm_next, upm);
1250312123Sngie	ATF_CHECK_EQ(VALID_START_PFN_3, uvm_physseg_get_start(upm));
1251312123Sngie	ATF_CHECK_EQ(VALID_END_PFN_3, uvm_physseg_get_end(upm));
1252312123Sngie#endif
1253312123Sngie}
1254312123Sngie
1255312123SngieATF_TC(uvm_physseg_get_next_invalid);
1256312123SngieATF_TC_HEAD(uvm_physseg_get_next_invalid, tc)
1257312123Sngie{
1258312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests the invalid / error conditions \
1259312123Sngie	    correctly when uvm_physseg_get_next() is called with invalid \
1260312123Sngie	    parameter values.");
1261312123Sngie}
1262312123SngieATF_TC_BODY(uvm_physseg_get_next_invalid, tc)
1263312123Sngie{
1264312123Sngie	uvm_physseg_t upm = UVM_PHYSSEG_TYPE_INVALID;
1265312123Sngie
1266312123Sngie	ATF_CHECK_EQ(UVM_PHYSSEG_TYPE_INVALID, uvm_physseg_get_next(upm));
1267312123Sngie}
1268312123Sngie
1269312123SngieATF_TC(uvm_physseg_get_prev);
1270312123SngieATF_TC_HEAD(uvm_physseg_get_prev, tc)
1271312123Sngie{
1272312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests the pointer values for previous \
1273312123Sngie	    segment using the uvm_physseg_get_prev() call.");
1274312123Sngie}
1275312123SngieATF_TC_BODY(uvm_physseg_get_prev, tc)
1276312123Sngie{
1277312123Sngie#if VM_PHYSSEG_MAX > 1
1278312123Sngie	uvm_physseg_t upm;
1279312123Sngie#endif
1280312123Sngie	uvm_physseg_t upm_prev;
1281312123Sngie
1282312123Sngie
1283312123Sngie	setup();
1284312123Sngie	upm_prev = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1285312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1286312123Sngie
1287312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1288312123Sngie
1289312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
1290312123Sngie
1291312123Sngie	ATF_CHECK_EQ(UVM_PHYSSEG_TYPE_INVALID_EMPTY,
1292312123Sngie	    uvm_physseg_get_prev(upm_prev));
1293312123Sngie
1294312123Sngie	/* This test will be triggered only if there are 2 or more segments. */
1295312123Sngie#if VM_PHYSSEG_MAX > 1
1296312123Sngie	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
1297312123Sngie	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
1298312123Sngie
1299312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1300312123Sngie
1301312123Sngie	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
1302312123Sngie
1303312123Sngie	/* Fetch Previous, we inserted a lower value */
1304312123Sngie	upm = uvm_physseg_get_prev(upm);
1305312123Sngie
1306312123Sngie	ATF_CHECK_EQ(upm_prev, upm);
1307312123Sngie	ATF_CHECK_EQ(VALID_START_PFN_1, uvm_physseg_get_start(upm));
1308312123Sngie	ATF_CHECK_EQ(VALID_END_PFN_1, uvm_physseg_get_end(upm));
1309312123Sngie#endif
1310312123Sngie
1311312123Sngie	/* This test will be triggered only if there are 3 or more segments. */
1312312123Sngie#if VM_PHYSSEG_MAX > 2
1313312123Sngie	uvm_page_physload(VALID_START_PFN_3, VALID_END_PFN_3,
1314312123Sngie	    VALID_AVAIL_START_PFN_3, VALID_AVAIL_END_PFN_3, VM_FREELIST_DEFAULT);
1315312123Sngie
1316312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1317312123Sngie
1318312123Sngie	ATF_REQUIRE_EQ(3, uvm_physseg_get_entries());
1319312123Sngie
1320312123Sngie	/*
1321312123Sngie	 * This will return a UVM_PHYSSEG_TYPE_INVALID_EMPTY we are at the
1322312123Sngie	 * lowest
1323312123Sngie	 */
1324312123Sngie	upm = uvm_physseg_get_prev(upm);
1325312123Sngie
1326312123Sngie	ATF_CHECK_EQ(UVM_PHYSSEG_TYPE_INVALID_EMPTY, upm);
1327312123Sngie#endif
1328312123Sngie}
1329312123Sngie
1330312123SngieATF_TC(uvm_physseg_get_prev_invalid);
1331312123SngieATF_TC_HEAD(uvm_physseg_get_prev_invalid, tc)
1332312123Sngie{
1333312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests the invalid / error conditions \
1334312123Sngie	    correctly when uvm_physseg_get_prev() is called with invalid \
1335312123Sngie	    parameter values.");
1336312123Sngie}
1337312123SngieATF_TC_BODY(uvm_physseg_get_prev_invalid, tc)
1338312123Sngie{
1339312123Sngie	uvm_physseg_t upm = UVM_PHYSSEG_TYPE_INVALID;
1340312123Sngie
1341312123Sngie	ATF_CHECK_EQ(UVM_PHYSSEG_TYPE_INVALID, uvm_physseg_get_prev(upm));
1342312123Sngie}
1343312123Sngie
1344312123SngieATF_TC(uvm_physseg_get_first);
1345312123SngieATF_TC_HEAD(uvm_physseg_get_first, tc)
1346312123Sngie{
1347312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests the pointer values for first \
1348312123Sngie	    segment (lowest node) using the uvm_physseg_get_first() call.");
1349312123Sngie}
1350312123SngieATF_TC_BODY(uvm_physseg_get_first, tc)
1351312123Sngie{
1352312123Sngie	uvm_physseg_t upm = UVM_PHYSSEG_TYPE_INVALID_EMPTY;
1353312123Sngie	uvm_physseg_t upm_first;
1354312123Sngie
1355312123Sngie	/* Fake early boot */
1356312123Sngie	setup();
1357312123Sngie
1358312123Sngie	/* No nodes exist */
1359312123Sngie	ATF_CHECK_EQ(upm, uvm_physseg_get_first());
1360312123Sngie
1361312123Sngie	upm_first = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
1362312123Sngie	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
1363312123Sngie
1364312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1365312123Sngie
1366312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
1367312123Sngie
1368312123Sngie	/* Pointer to first should be the least valued node */
1369312123Sngie	upm = uvm_physseg_get_first();
1370312123Sngie	ATF_CHECK_EQ(upm_first, upm);
1371312123Sngie	ATF_CHECK_EQ(VALID_START_PFN_2, uvm_physseg_get_start(upm));
1372312123Sngie	ATF_CHECK_EQ(VALID_END_PFN_2, uvm_physseg_get_end(upm));
1373312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_2, uvm_physseg_get_avail_start(upm));
1374312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_2, uvm_physseg_get_avail_end(upm));
1375312123Sngie
1376312123Sngie	/* This test will be triggered only if there are 2 or more segments. */
1377312123Sngie#if VM_PHYSSEG_MAX > 1
1378312123Sngie	/* Insert a node of lesser value */
1379312123Sngie	upm_first = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1380312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1381312123Sngie
1382312123Sngie	ATF_CHECK_EQ(0, uvmexp.npages);
1383312123Sngie
1384312123Sngie	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
1385312123Sngie
1386312123Sngie	/* Pointer to first should be the least valued node */
1387312123Sngie	upm = uvm_physseg_get_first();
1388312123Sngie	ATF_CHECK_EQ(upm_first, upm);
1389312123Sngie	ATF_CHECK_EQ(VALID_START_PFN_1, uvm_physseg_get_start(upm));
1390312123Sngie	ATF_CHECK_EQ(VALID_END_PFN_1, uvm_physseg_get_end(upm));
1391312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_1, uvm_physseg_get_avail_start(upm));
1392312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_1, uvm_physseg_get_avail_end(upm));
1393312123Sngie#endif
1394312123Sngie
1395312123Sngie	/* This test will be triggered only if there are 3 or more segments. */
1396312123Sngie#if VM_PHYSSEG_MAX > 2
1397312123Sngie	/* Insert a node of higher value */
1398312123Sngie	upm_first =uvm_page_physload(VALID_START_PFN_3, VALID_END_PFN_3,
1399312123Sngie	    VALID_AVAIL_START_PFN_3, VALID_AVAIL_END_PFN_3, VM_FREELIST_DEFAULT);
1400312123Sngie
1401312123Sngie	ATF_CHECK_EQ(0, uvmexp.npages);
1402312123Sngie
1403312123Sngie	ATF_REQUIRE_EQ(3, uvm_physseg_get_entries());
1404312123Sngie
1405312123Sngie	/* Pointer to first should be the least valued node */
1406312123Sngie	upm = uvm_physseg_get_first();
1407312123Sngie	ATF_CHECK(upm_first != upm);
1408312123Sngie	ATF_CHECK_EQ(VALID_START_PFN_1, uvm_physseg_get_start(upm));
1409312123Sngie	ATF_CHECK_EQ(VALID_END_PFN_1, uvm_physseg_get_end(upm));
1410312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_1, uvm_physseg_get_avail_start(upm));
1411312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_1, uvm_physseg_get_avail_end(upm));
1412312123Sngie#endif
1413312123Sngie}
1414312123Sngie
1415312123SngieATF_TC(uvm_physseg_get_last);
1416312123SngieATF_TC_HEAD(uvm_physseg_get_last, tc)
1417312123Sngie{
1418312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests the pointer values for last \
1419312123Sngie	    segment using the uvm_physseg_get_last() call.");
1420312123Sngie}
1421312123SngieATF_TC_BODY(uvm_physseg_get_last, tc)
1422312123Sngie{
1423312123Sngie	uvm_physseg_t upm = UVM_PHYSSEG_TYPE_INVALID_EMPTY;
1424312123Sngie	uvm_physseg_t upm_last;
1425312123Sngie
1426312123Sngie	setup();
1427312123Sngie
1428312123Sngie	/* No nodes exist */
1429312123Sngie	ATF_CHECK_EQ(upm, uvm_physseg_get_last());
1430312123Sngie
1431312123Sngie	upm_last = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1432312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1433312123Sngie
1434312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1435312123Sngie
1436312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
1437312123Sngie
1438312123Sngie	/* Pointer to last should be the most valued node */
1439312123Sngie	upm = uvm_physseg_get_last();
1440312123Sngie	ATF_CHECK_EQ(upm_last, upm);
1441312123Sngie	ATF_CHECK_EQ(VALID_START_PFN_1, uvm_physseg_get_start(upm));
1442312123Sngie	ATF_CHECK_EQ(VALID_END_PFN_1, uvm_physseg_get_end(upm));
1443312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_1, uvm_physseg_get_avail_start(upm));
1444312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_1, uvm_physseg_get_avail_end(upm));
1445312123Sngie
1446312123Sngie	/* This test will be triggered only if there are 2 or more segments. */
1447312123Sngie#if VM_PHYSSEG_MAX > 1
1448312123Sngie	/* Insert node of greater value */
1449312123Sngie	upm_last = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
1450312123Sngie	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
1451312123Sngie
1452312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1453312123Sngie
1454312123Sngie	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
1455312123Sngie
1456312123Sngie	/* Pointer to last should be the most valued node */
1457312123Sngie	upm = uvm_physseg_get_last();
1458312123Sngie	ATF_CHECK_EQ(upm_last, upm);
1459312123Sngie	ATF_CHECK_EQ(VALID_START_PFN_2, uvm_physseg_get_start(upm));
1460312123Sngie	ATF_CHECK_EQ(VALID_END_PFN_2, uvm_physseg_get_end(upm));
1461312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_2, uvm_physseg_get_avail_start(upm));
1462312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_2, uvm_physseg_get_avail_end(upm));
1463312123Sngie#endif
1464312123Sngie
1465312123Sngie	/* This test will be triggered only if there are 3 or more segments. */
1466312123Sngie#if VM_PHYSSEG_MAX > 2
1467312123Sngie	/* Insert node of greater value */
1468312123Sngie	upm_last = uvm_page_physload(VALID_START_PFN_3, VALID_END_PFN_3,
1469312123Sngie	    VALID_AVAIL_START_PFN_3, VALID_AVAIL_END_PFN_3, VM_FREELIST_DEFAULT);
1470312123Sngie
1471312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1472312123Sngie
1473312123Sngie	ATF_REQUIRE_EQ(3, uvm_physseg_get_entries());
1474312123Sngie
1475312123Sngie	/* Pointer to last should be the most valued node */
1476312123Sngie	upm = uvm_physseg_get_last();
1477312123Sngie	ATF_CHECK_EQ(upm_last, upm);
1478312123Sngie	ATF_CHECK_EQ(VALID_START_PFN_3, uvm_physseg_get_start(upm));
1479312123Sngie	ATF_CHECK_EQ(VALID_END_PFN_3, uvm_physseg_get_end(upm));
1480312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_3, uvm_physseg_get_avail_start(upm));
1481312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_3, uvm_physseg_get_avail_end(upm));
1482312123Sngie#endif
1483312123Sngie}
1484312123Sngie
1485312123SngieATF_TC(uvm_physseg_valid);
1486312123SngieATF_TC_HEAD(uvm_physseg_valid, tc)
1487312123Sngie{
1488312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests the pointer value for current \
1489312123Sngie	    segment is valid using the uvm_physseg_valid_p() call.");
1490312123Sngie}
1491312123SngieATF_TC_BODY(uvm_physseg_valid, tc)
1492312123Sngie{
1493312123Sngie	psize_t npages = (VALID_END_PFN_1 - VALID_START_PFN_1);
1494312123Sngie
1495312123Sngie	struct vm_page *pgs = malloc(sizeof(struct vm_page) * npages);
1496312123Sngie
1497312123Sngie	uvm_physseg_t upm;
1498312123Sngie
1499312123Sngie	setup();
1500312123Sngie	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1501312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1502312123Sngie
1503312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1504312123Sngie
1505312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
1506312123Sngie
1507312123Sngie	uvm_physseg_init_seg(upm, pgs);
1508312123Sngie
1509312123Sngie	ATF_REQUIRE_EQ(PAGE_COUNT_1M, uvmexp.npages);
1510312123Sngie
1511312123Sngie	ATF_CHECK_EQ(true, uvm_physseg_valid_p(upm));
1512312123Sngie}
1513312123Sngie
1514312123SngieATF_TC(uvm_physseg_valid_invalid);
1515312123SngieATF_TC_HEAD(uvm_physseg_valid_invalid, tc)
1516312123Sngie{
1517312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests the pointer value for current \
1518312123Sngie	    segment is invalid using the uvm_physseg_valid_p() call.");
1519312123Sngie}
1520312123SngieATF_TC_BODY(uvm_physseg_valid_invalid, tc)
1521312123Sngie{
1522312123Sngie	uvm_physseg_t upm;
1523312123Sngie
1524312123Sngie	setup();
1525312123Sngie	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1526312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1527312123Sngie
1528312123Sngie	/* Force other check conditions */
1529312123Sngie	uvm.page_init_done = true;
1530312123Sngie
1531312123Sngie	ATF_REQUIRE_EQ(true, uvm.page_init_done);
1532312123Sngie
1533312123Sngie	/* Invalid uvm_physseg_t */
1534312123Sngie	ATF_CHECK_EQ(false, uvm_physseg_valid_p(UVM_PHYSSEG_TYPE_INVALID));
1535312123Sngie
1536312123Sngie	/*
1537312123Sngie	 * Without any pages initialized for segment, it is considered
1538312123Sngie	 * invalid
1539312123Sngie	 */
1540312123Sngie	ATF_CHECK_EQ(false, uvm_physseg_valid_p(upm));
1541312123Sngie}
1542312123Sngie
1543312123SngieATF_TC(uvm_physseg_get_highest);
1544312123SngieATF_TC_HEAD(uvm_physseg_get_highest, tc)
1545312123Sngie{
1546312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the returned PFN matches  \
1547312123Sngie	    the highest PFN in use by the system.");
1548312123Sngie}
1549312123SngieATF_TC_BODY(uvm_physseg_get_highest, tc)
1550312123Sngie{
1551312123Sngie	setup();
1552312123Sngie	uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1553312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1554312123Sngie
1555312123Sngie	/* Only one segment so highest is the current */
1556312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_1 - 1, uvm_physseg_get_highest_frame());
1557312123Sngie
1558312123Sngie	/* This test will be triggered only if there are 2 or more segments. */
1559312123Sngie#if VM_PHYSSEG_MAX > 1
1560312123Sngie	uvm_page_physload(VALID_START_PFN_3, VALID_END_PFN_3,
1561312123Sngie	    VALID_AVAIL_START_PFN_3, VALID_AVAIL_END_PFN_3, VM_FREELIST_DEFAULT);
1562312123Sngie
1563312123Sngie	/* PFN_3 > PFN_1 */
1564312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_3 - 1, uvm_physseg_get_highest_frame());
1565312123Sngie#endif
1566312123Sngie
1567312123Sngie	/* This test will be triggered only if there are 3 or more segments. */
1568312123Sngie#if VM_PHYSSEG_MAX > 2
1569312123Sngie	uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
1570312123Sngie	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
1571312123Sngie
1572312123Sngie	/* PFN_3 > PFN_2 */
1573312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_3 - 1, uvm_physseg_get_highest_frame());
1574312123Sngie#endif
1575312123Sngie}
1576312123Sngie
1577312123SngieATF_TC(uvm_physseg_get_free_list);
1578312123SngieATF_TC_HEAD(uvm_physseg_get_free_list, tc)
1579312123Sngie{
1580312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the returned Free List type \
1581312123Sngie	    of a segment matches the one returned from \
1582312123Sngie	    uvm_physseg_get_free_list() call.");
1583312123Sngie}
1584312123SngieATF_TC_BODY(uvm_physseg_get_free_list, tc)
1585312123Sngie{
1586312123Sngie	uvm_physseg_t upm;
1587312123Sngie
1588312123Sngie	/* Fake early boot */
1589312123Sngie	setup();
1590312123Sngie
1591312123Sngie	/* Insertions are made in ascending order */
1592312123Sngie	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1593312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1594312123Sngie
1595312123Sngie	ATF_CHECK_EQ(VM_FREELIST_DEFAULT, uvm_physseg_get_free_list(upm));
1596312123Sngie
1597312123Sngie	/* This test will be triggered only if there are 2 or more segments. */
1598312123Sngie#if VM_PHYSSEG_MAX > 1
1599312123Sngie	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
1600312123Sngie	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_FIRST16);
1601312123Sngie
1602312123Sngie	ATF_CHECK_EQ(VM_FREELIST_FIRST16, uvm_physseg_get_free_list(upm));
1603312123Sngie#endif
1604312123Sngie
1605312123Sngie	/* This test will be triggered only if there are 3 or more segments. */
1606312123Sngie#if VM_PHYSSEG_MAX > 2
1607312123Sngie	upm = uvm_page_physload(VALID_START_PFN_3, VALID_END_PFN_3,
1608312123Sngie	    VALID_AVAIL_START_PFN_3, VALID_AVAIL_END_PFN_3, VM_FREELIST_FIRST1G);
1609312123Sngie
1610312123Sngie	ATF_CHECK_EQ(VM_FREELIST_FIRST1G, uvm_physseg_get_free_list(upm));
1611312123Sngie#endif
1612312123Sngie}
1613312123Sngie
1614312123SngieATF_TC(uvm_physseg_get_start_hint);
1615312123SngieATF_TC_HEAD(uvm_physseg_get_start_hint, tc)
1616312123Sngie{
1617312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the returned start_hint value \
1618312123Sngie	    of a segment matches the one returned from \
1619312123Sngie	    uvm_physseg_get_start_hint() call.");
1620312123Sngie}
1621312123SngieATF_TC_BODY(uvm_physseg_get_start_hint, tc)
1622312123Sngie{
1623312123Sngie	uvm_physseg_t upm;
1624312123Sngie
1625312123Sngie	setup();
1626312123Sngie	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1627312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1628312123Sngie
1629312123Sngie	/* Will be Zero since no specific value is set during init */
1630312123Sngie	ATF_CHECK_EQ(0, uvm_physseg_get_start_hint(upm));
1631312123Sngie}
1632312123Sngie
1633312123SngieATF_TC(uvm_physseg_set_start_hint);
1634312123SngieATF_TC_HEAD(uvm_physseg_set_start_hint, tc)
1635312123Sngie{
1636312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the returned start_hint value \
1637312123Sngie	    of a segment matches the one set by the \
1638312123Sngie	    uvm_physseg_set_start_hint() call.");
1639312123Sngie}
1640312123SngieATF_TC_BODY(uvm_physseg_set_start_hint, tc)
1641312123Sngie{
1642312123Sngie	psize_t npages = (VALID_END_PFN_1 - VALID_START_PFN_1);
1643312123Sngie
1644312123Sngie	struct vm_page *pgs = malloc(sizeof(struct vm_page) * npages);
1645312123Sngie
1646312123Sngie	uvm_physseg_t upm;
1647312123Sngie
1648312123Sngie	setup();
1649312123Sngie	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1650312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1651312123Sngie
1652312123Sngie	uvm_physseg_init_seg(upm, pgs);
1653312123Sngie
1654312123Sngie	ATF_CHECK_EQ(true, uvm_physseg_set_start_hint(upm, atop(128)));
1655312123Sngie
1656312123Sngie	/* Will be atop(128) since no specific value is set above */
1657312123Sngie	ATF_CHECK_EQ(atop(128), uvm_physseg_get_start_hint(upm));
1658312123Sngie}
1659312123Sngie
1660312123SngieATF_TC(uvm_physseg_set_start_hint_invalid);
1661312123SngieATF_TC_HEAD(uvm_physseg_set_start_hint_invalid, tc)
1662312123Sngie{
1663312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the returned value is false \
1664312123Sngie	    when an invalid segment matches the one trying to set by the \
1665312123Sngie	    uvm_physseg_set_start_hint() call.");
1666312123Sngie}
1667312123SngieATF_TC_BODY(uvm_physseg_set_start_hint_invalid, tc)
1668312123Sngie{
1669312123Sngie	uvm_physseg_t upm;
1670312123Sngie
1671312123Sngie	setup();
1672312123Sngie	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1673312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1674312123Sngie
1675312123Sngie	/* Force other check conditions */
1676312123Sngie	uvm.page_init_done = true;
1677312123Sngie
1678312123Sngie	ATF_REQUIRE_EQ(true, uvm.page_init_done);
1679312123Sngie
1680312123Sngie	ATF_CHECK_EQ(false, uvm_physseg_set_start_hint(upm, atop(128)));
1681312123Sngie
1682312123Sngie	/*
1683312123Sngie	 * Will be Zero since no specific value is set after the init
1684312123Sngie	 * due to failure
1685312123Sngie	 */
1686312123Sngie	atf_tc_expect_signal(SIGABRT, "invalid uvm_physseg_t handle");
1687312123Sngie
1688312123Sngie	ATF_CHECK_EQ(0, uvm_physseg_get_start_hint(upm));
1689312123Sngie}
1690312123Sngie
1691312123SngieATF_TC(uvm_physseg_get_pg);
1692312123SngieATF_TC_HEAD(uvm_physseg_get_pg, tc)
1693312123Sngie{
1694312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the returned vm_page struct \
1695312123Sngie	    is correct when fetched by uvm_physseg_get_pg() call.");
1696312123Sngie}
1697312123SngieATF_TC_BODY(uvm_physseg_get_pg, tc)
1698312123Sngie{
1699312123Sngie	psize_t npages = (VALID_END_PFN_1 - VALID_START_PFN_1);
1700312123Sngie
1701312123Sngie	struct vm_page *pgs = malloc(sizeof(struct vm_page) * npages);
1702312123Sngie
1703312123Sngie	struct vm_page *extracted_pg = NULL;
1704312123Sngie
1705312123Sngie	uvm_physseg_t upm;
1706312123Sngie
1707312123Sngie	setup();
1708312123Sngie	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1709312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1710312123Sngie
1711312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
1712312123Sngie
1713312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1714312123Sngie
1715312123Sngie	/* Now we initialize the segment */
1716312123Sngie	uvm_physseg_init_seg(upm, pgs);
1717312123Sngie
1718312123Sngie	ATF_REQUIRE_EQ(PAGE_COUNT_1M, uvmexp.npages);
1719312123Sngie
1720312123Sngie	ATF_REQUIRE_EQ(NULL, extracted_pg);
1721312123Sngie
1722312123Sngie	/* Try fetching the 5th Page in the Segment */
1723312123Sngie	extracted_pg = uvm_physseg_get_pg(upm, 5);
1724312123Sngie
1725312123Sngie	/* Values of phys_addr is n * PAGE_SIZE where n is the page number */
1726312123Sngie	ATF_CHECK_EQ(5 * PAGE_SIZE, extracted_pg->phys_addr);
1727312123Sngie
1728312123Sngie	/* Try fetching the 113th Page in the Segment */
1729312123Sngie	extracted_pg = uvm_physseg_get_pg(upm, 113);
1730312123Sngie
1731312123Sngie	ATF_CHECK_EQ(113 * PAGE_SIZE, extracted_pg->phys_addr);
1732312123Sngie}
1733312123Sngie
1734312123Sngie#ifdef __HAVE_PMAP_PHYSSEG
1735312123SngieATF_TC(uvm_physseg_get_pmseg);
1736312123SngieATF_TC_HEAD(uvm_physseg_get_pmseg, tc)
1737312123Sngie{
1738312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the returned pmap_physseg \
1739312123Sngie	    struct is correct when fetched by uvm_physseg_get_pmseg() call.");
1740312123Sngie}
1741312123SngieATF_TC_BODY(uvm_physseg_get_pmseg, tc)
1742312123Sngie{
1743312123Sngie	psize_t npages = (VALID_END_PFN_1 - VALID_START_PFN_1);
1744312123Sngie
1745312123Sngie	struct vm_page *pgs = malloc(sizeof(struct vm_page) * npages);
1746312123Sngie
1747312123Sngie	struct pmap_physseg pmseg = { true };
1748312123Sngie
1749312123Sngie	struct pmap_physseg *extracted_pmseg = NULL;
1750312123Sngie
1751312123Sngie	uvm_physseg_t upm;
1752312123Sngie
1753312123Sngie	setup();
1754312123Sngie	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1755312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1756312123Sngie
1757312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
1758312123Sngie
1759312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1760312123Sngie
1761312123Sngie	/* Now we initialize the segment */
1762312123Sngie	uvm_physseg_init_seg(upm, pgs);
1763312123Sngie
1764312123Sngie	ATF_REQUIRE_EQ(PAGE_COUNT_1M, uvmexp.npages);
1765312123Sngie
1766312123Sngie	ATF_REQUIRE_EQ(NULL, extracted_pmseg);
1767312123Sngie
1768312123Sngie	ATF_REQUIRE_EQ(true, pmseg.dummy_variable);
1769312123Sngie
1770312123Sngie	/* Extract the current pmseg */
1771312123Sngie	extracted_pmseg = uvm_physseg_get_pmseg(upm);
1772312123Sngie
1773312123Sngie	/*
1774312123Sngie	 * We can only check if it is not NULL
1775312123Sngie	 * We do not know the value it contains
1776312123Sngie	 */
1777312123Sngie	ATF_CHECK(NULL != extracted_pmseg);
1778312123Sngie
1779312123Sngie	extracted_pmseg->dummy_variable = pmseg.dummy_variable;
1780312123Sngie
1781312123Sngie	/* Invert value to ensure test integrity */
1782312123Sngie	pmseg.dummy_variable = false;
1783312123Sngie
1784312123Sngie	ATF_REQUIRE_EQ(false, pmseg.dummy_variable);
1785312123Sngie
1786312123Sngie	extracted_pmseg = uvm_physseg_get_pmseg(upm);
1787312123Sngie
1788312123Sngie	ATF_CHECK(NULL != extracted_pmseg);
1789312123Sngie
1790312123Sngie	ATF_CHECK_EQ(true, extracted_pmseg->dummy_variable);
1791312123Sngie}
1792312123Sngie#endif
1793312123Sngie
1794312123SngieATF_TC(vm_physseg_find);
1795312123SngieATF_TC_HEAD(vm_physseg_find, tc)
1796312123Sngie{
1797312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the returned segment number \
1798312123Sngie	    is correct when an PFN is passed into uvm_physseg_find() call. \
1799312123Sngie	    In addition	to this the offset of the PFN from the start of \
1800312123Sngie	    segment is also set if the parameter is passed in as not NULL.");
1801312123Sngie}
1802312123SngieATF_TC_BODY(vm_physseg_find, tc)
1803312123Sngie{
1804312123Sngie	psize_t offset = (psize_t) -1;
1805312123Sngie
1806312123Sngie	uvm_physseg_t upm_first, result;
1807312123Sngie#if VM_PHYSSEG_MAX > 1
1808312123Sngie	uvm_physseg_t upm_second;
1809312123Sngie#endif
1810312123Sngie
1811312123Sngie	setup();
1812312123Sngie
1813312123Sngie	upm_first = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1814312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1815312123Sngie
1816312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
1817312123Sngie
1818312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1819312123Sngie
1820312123Sngie	/* This test will be triggered only if there are 2 or more segments. */
1821312123Sngie#if VM_PHYSSEG_MAX > 1
1822312123Sngie	upm_second = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
1823312123Sngie	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
1824312123Sngie
1825312123Sngie	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
1826312123Sngie
1827312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1828312123Sngie#endif
1829312123Sngie
1830312123Sngie	/* Under ONE_MEGABYTE is segment upm_first */
1831312123Sngie	result = uvm_physseg_find(atop(ONE_MEGABYTE - 1024), NULL);
1832312123Sngie	ATF_CHECK_EQ(upm_first, result);
1833312123Sngie	ATF_CHECK_EQ(uvm_physseg_get_start(upm_first),
1834312123Sngie	    uvm_physseg_get_start(result));
1835312123Sngie	ATF_CHECK_EQ(uvm_physseg_get_end(upm_first),
1836312123Sngie	    uvm_physseg_get_end(result));
1837312123Sngie	ATF_CHECK_EQ(uvm_physseg_get_avail_start(upm_first),
1838312123Sngie	    uvm_physseg_get_avail_start(result));
1839312123Sngie	ATF_CHECK_EQ(uvm_physseg_get_avail_end(upm_first),
1840312123Sngie	    uvm_physseg_get_avail_end(result));
1841312123Sngie
1842312123Sngie	ATF_REQUIRE_EQ((psize_t) -1, offset);
1843312123Sngie
1844312123Sngie	/* This test will be triggered only if there are 2 or more segments. */
1845312123Sngie#if VM_PHYSSEG_MAX > 1
1846312123Sngie	/* Over ONE_MEGABYTE is segment upm_second */
1847312123Sngie	result = uvm_physseg_find(atop(ONE_MEGABYTE + 8192), &offset);
1848312123Sngie	ATF_CHECK_EQ(upm_second, result);
1849312123Sngie	ATF_CHECK_EQ(uvm_physseg_get_start(upm_second),
1850312123Sngie	    uvm_physseg_get_start(result));
1851312123Sngie	ATF_CHECK_EQ(uvm_physseg_get_end(upm_second),
1852312123Sngie	    uvm_physseg_get_end(result));
1853312123Sngie	ATF_CHECK_EQ(uvm_physseg_get_avail_start(upm_second),
1854312123Sngie	    uvm_physseg_get_avail_start(result));
1855312123Sngie	ATF_CHECK_EQ(uvm_physseg_get_avail_end(upm_second),
1856312123Sngie	    uvm_physseg_get_avail_end(result));
1857312123Sngie
1858312123Sngie	/* Offset is calculated based on PAGE_SIZE */
1859312123Sngie	/* atop(ONE_MEGABYTE + (2 * PAGE_SIZE)) - VALID_START_PFN1  = 2 */
1860312123Sngie	ATF_CHECK_EQ(2, offset);
1861312123Sngie#else
1862312123Sngie	/* Under ONE_MEGABYTE is segment upm_first */
1863312123Sngie	result = uvm_physseg_find(atop(ONE_MEGABYTE - 12288), &offset);
1864312123Sngie	ATF_CHECK_EQ(upm_first, result);
1865312123Sngie	ATF_CHECK_EQ(uvm_physseg_get_start(upm_first),
1866312123Sngie	    uvm_physseg_get_start(result));
1867312123Sngie	ATF_CHECK_EQ(uvm_physseg_get_end(upm_first),
1868312123Sngie	    uvm_physseg_get_end(result));
1869312123Sngie	ATF_CHECK_EQ(uvm_physseg_get_avail_start(upm_first),
1870312123Sngie	    uvm_physseg_get_avail_start(result));
1871312123Sngie	ATF_CHECK_EQ(uvm_physseg_get_avail_end(upm_first),
1872312123Sngie	    uvm_physseg_get_avail_end(result));
1873312123Sngie
1874312123Sngie	/* Offset is calculated based on PAGE_SIZE */
1875312123Sngie	/* atop(ONE_MEGABYTE - (3 * PAGE_SIZE)) - VALID_START_PFN1  = 253 */
1876312123Sngie	ATF_CHECK_EQ(253, offset);
1877312123Sngie#endif
1878312123Sngie}
1879312123Sngie
1880312123SngieATF_TC(vm_physseg_find_invalid);
1881312123SngieATF_TC_HEAD(vm_physseg_find_invalid, tc)
1882312123Sngie{
1883312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the returned segment number \
1884312123Sngie	    is (paddr_t) -1  when a non existant PFN is passed into \
1885312123Sngie	    uvm_physseg_find() call.");
1886312123Sngie}
1887312123SngieATF_TC_BODY(vm_physseg_find_invalid, tc)
1888312123Sngie{
1889312123Sngie	psize_t offset = (psize_t) -1;
1890312123Sngie
1891312123Sngie	setup();
1892312123Sngie	uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
1893312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
1894312123Sngie
1895312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
1896312123Sngie
1897312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1898312123Sngie
1899312123Sngie	/* No segments over 3 MB exists at the moment */
1900312123Sngie	ATF_CHECK_EQ(UVM_PHYSSEG_TYPE_INVALID,
1901312123Sngie	    uvm_physseg_find(atop(ONE_MEGABYTE * 3), NULL));
1902312123Sngie
1903312123Sngie	ATF_REQUIRE_EQ((psize_t) -1, offset);
1904312123Sngie
1905312123Sngie	/* No segments over 3 MB exists at the moment */
1906312123Sngie	ATF_CHECK_EQ(UVM_PHYSSEG_TYPE_INVALID,
1907312123Sngie	    uvm_physseg_find(atop(ONE_MEGABYTE * 3), &offset));
1908312123Sngie
1909312123Sngie	ATF_CHECK_EQ((psize_t) -1, offset);
1910312123Sngie}
1911312123Sngie
1912312123SngieATF_TC(uvm_page_physunload_start);
1913312123SngieATF_TC_HEAD(uvm_page_physunload_start, tc)
1914312123Sngie{
1915312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the basic uvm_page_physunload()\
1916312123Sngie	    call works without a panic(). Unloads from Start of the segment.");
1917312123Sngie}
1918312123SngieATF_TC_BODY(uvm_page_physunload_start, tc)
1919312123Sngie{
1920312123Sngie	/*
1921312123Sngie	 * Would uvmexp.npages reduce everytime an uvm_page_physunload is called?
1922312123Sngie	 */
1923312123Sngie	psize_t npages = (VALID_END_PFN_2 - VALID_START_PFN_2);
1924312123Sngie
1925312123Sngie	struct vm_page *pgs = malloc(sizeof(struct vm_page) * npages);
1926312123Sngie
1927312123Sngie	paddr_t p = 0;
1928312123Sngie
1929312123Sngie	uvm_physseg_t upm;
1930312123Sngie
1931312123Sngie	setup();
1932312123Sngie	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
1933312123Sngie	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
1934312123Sngie
1935312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
1936312123Sngie
1937312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1938312123Sngie
1939312123Sngie	uvm_physseg_init_seg(upm, pgs);
1940312123Sngie
1941312123Sngie	ATF_CHECK_EQ(true, uvm_page_physunload(upm, VM_FREELIST_DEFAULT, &p));
1942312123Sngie
1943312123Sngie	/*
1944312123Sngie	 * When called for first time, uvm_page_physload() removes the first PFN
1945312123Sngie	 *
1946312123Sngie	 * New avail start will be VALID_AVAIL_START_PFN_2 + 1
1947312123Sngie	 */
1948312123Sngie	ATF_CHECK_EQ(VALID_START_PFN_2, atop(p));
1949312123Sngie
1950312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_2 + 1,
1951312123Sngie	    uvm_physseg_get_avail_start(upm));
1952312123Sngie
1953312123Sngie	ATF_CHECK_EQ(VALID_START_PFN_2 + 1, uvm_physseg_get_start(upm));
1954312123Sngie
1955312123Sngie	/* Rest of the stuff should remain the same */
1956312123Sngie	ATF_CHECK_EQ(VALID_END_PFN_2, uvm_physseg_get_end(upm));
1957312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_2, uvm_physseg_get_avail_end(upm));
1958312123Sngie}
1959312123Sngie
1960312123SngieATF_TC(uvm_page_physunload_end);
1961312123SngieATF_TC_HEAD(uvm_page_physunload_end, tc)
1962312123Sngie{
1963312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the basic uvm_page_physunload()\
1964312123Sngie	    call works without a panic(). Unloads from End of the segment.");
1965312123Sngie}
1966312123SngieATF_TC_BODY(uvm_page_physunload_end, tc)
1967312123Sngie{
1968312123Sngie	/*
1969312123Sngie	 * Would uvmexp.npages reduce everytime an uvm_page_physunload is called?
1970312123Sngie	 */
1971312123Sngie	paddr_t p = 0;
1972312123Sngie
1973312123Sngie	uvm_physseg_t upm;
1974312123Sngie
1975312123Sngie	setup();
1976312123Sngie	/* Note: start != avail_start to remove from end. */
1977312123Sngie	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
1978312123Sngie	    VALID_AVAIL_START_PFN_2 + 1, VALID_AVAIL_END_PFN_2,
1979312123Sngie	    VM_FREELIST_DEFAULT);
1980312123Sngie
1981312123Sngie	p = 0;
1982312123Sngie
1983312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
1984312123Sngie
1985312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
1986312123Sngie
1987312123Sngie	ATF_REQUIRE(
1988312123Sngie		uvm_physseg_get_avail_start(upm) != uvm_physseg_get_start(upm));
1989312123Sngie
1990312123Sngie	ATF_CHECK_EQ(true, uvm_page_physunload(upm, VM_FREELIST_DEFAULT, &p));
1991312123Sngie
1992312123Sngie	/*
1993312123Sngie	 * Remember if X is the upper limit the actual valid pointer is X - 1
1994312123Sngie	 *
1995312123Sngie	 * For example if 256 is the upper limit for 1MB memory, last valid
1996312123Sngie	 * pointer is 256 - 1 = 255
1997312123Sngie	 */
1998312123Sngie
1999312123Sngie	ATF_CHECK_EQ(VALID_END_PFN_2 - 1, atop(p));
2000312123Sngie
2001312123Sngie	/*
2002312123Sngie	 * When called for second time, uvm_page_physload() removes the last PFN
2003312123Sngie	 *
2004312123Sngie	 * New avail end will be VALID_AVAIL_END_PFN_2 - 1
2005312123Sngie	 * New end will be VALID_AVAIL_PFN_2 - 1
2006312123Sngie	 */
2007312123Sngie
2008312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_2 - 1, uvm_physseg_get_avail_end(upm));
2009312123Sngie
2010312123Sngie	ATF_CHECK_EQ(VALID_END_PFN_2 - 1, uvm_physseg_get_end(upm));
2011312123Sngie
2012312123Sngie	/* Rest of the stuff should remain the same */
2013312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_2 + 1,
2014312123Sngie	    uvm_physseg_get_avail_start(upm));
2015312123Sngie	ATF_CHECK_EQ(VALID_START_PFN_2, uvm_physseg_get_start(upm));
2016312123Sngie}
2017312123Sngie
2018312123SngieATF_TC(uvm_page_physunload_none);
2019312123SngieATF_TC_HEAD(uvm_page_physunload_none, tc)
2020312123Sngie{
2021312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the basic uvm_page_physunload()\
2022312123Sngie	    call works without a panic(). Does not unload from start or end \
2023312123Sngie	    because of non-aligned start / avail_start and end / avail_end \
2024312123Sngie	    respectively.");
2025312123Sngie}
2026312123SngieATF_TC_BODY(uvm_page_physunload_none, tc)
2027312123Sngie{
2028312123Sngie	psize_t npages = (VALID_END_PFN_2 - VALID_START_PFN_2);
2029312123Sngie
2030312123Sngie	struct vm_page *pgs = malloc(sizeof(struct vm_page) * npages);
2031312123Sngie
2032312123Sngie	paddr_t p = 0;
2033312123Sngie
2034312123Sngie	uvm_physseg_t upm;
2035312123Sngie
2036312123Sngie	setup();
2037312123Sngie	/*
2038312123Sngie	 * Note: start != avail_start and end != avail_end.
2039312123Sngie	 *
2040312123Sngie	 * This prevents any unload from occuring.
2041312123Sngie	 */
2042312123Sngie	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
2043312123Sngie	    VALID_AVAIL_START_PFN_2 + 1, VALID_AVAIL_END_PFN_2 - 1,
2044312123Sngie	    VM_FREELIST_DEFAULT);
2045312123Sngie
2046312123Sngie	p = 0;
2047312123Sngie
2048312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
2049312123Sngie
2050312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
2051312123Sngie
2052312123Sngie	ATF_REQUIRE(
2053312123Sngie		uvm_physseg_get_avail_start(upm) != uvm_physseg_get_start(upm));
2054312123Sngie
2055312123Sngie	uvm_physseg_init_seg(upm, pgs);
2056312123Sngie
2057312123Sngie	ATF_CHECK_EQ(false, uvm_page_physunload(upm, VM_FREELIST_DEFAULT, &p));
2058312123Sngie
2059312123Sngie	/* uvm_page_physload() will no longer unload memory */
2060312123Sngie	ATF_CHECK_EQ(0, p);
2061312123Sngie
2062312123Sngie	/* Rest of the stuff should remain the same */
2063312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_2 + 1,
2064312123Sngie	    uvm_physseg_get_avail_start(upm));
2065312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_2 - 1,
2066312123Sngie	    uvm_physseg_get_avail_end(upm));
2067312123Sngie	ATF_CHECK_EQ(VALID_START_PFN_2, uvm_physseg_get_start(upm));
2068312123Sngie	ATF_CHECK_EQ(VALID_END_PFN_2, uvm_physseg_get_end(upm));
2069312123Sngie}
2070312123Sngie
2071312123SngieATF_TC(uvm_page_physunload_delete_start);
2072312123SngieATF_TC_HEAD(uvm_page_physunload_delete_start, tc)
2073312123Sngie{
2074312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the  uvm_page_physunload() \
2075312123Sngie	    works when the segment gets small enough to be deleted scenario. \
2076312123Sngie	    NOTE: This one works deletes from start.");
2077312123Sngie}
2078312123SngieATF_TC_BODY(uvm_page_physunload_delete_start, tc)
2079312123Sngie{
2080312123Sngie	/*
2081312123Sngie	 * Would uvmexp.npages reduce everytime an uvm_page_physunload is called?
2082312123Sngie	 */
2083312123Sngie	paddr_t p = 0;
2084312123Sngie
2085312123Sngie	uvm_physseg_t upm;
2086312123Sngie
2087312123Sngie	setup();
2088312123Sngie
2089312123Sngie	/*
2090312123Sngie	 * Setup the Nuke from Starting point
2091312123Sngie	 */
2092312123Sngie
2093312123Sngie	upm = uvm_page_physload(VALID_END_PFN_1 - 1, VALID_END_PFN_1,
2094312123Sngie	    VALID_AVAIL_END_PFN_1 - 1, VALID_AVAIL_END_PFN_1,
2095312123Sngie	    VM_FREELIST_DEFAULT);
2096312123Sngie
2097312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
2098312123Sngie
2099312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
2100312123Sngie
2101312123Sngie	/* Insert more than one segment iff VM_PHYSSEG_MAX > 1 */
2102312123Sngie#if VM_PHYSSEG_MAX > 1
2103312123Sngie	uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
2104312123Sngie	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
2105312123Sngie
2106312123Sngie	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
2107312123Sngie#endif
2108312123Sngie
2109312123Sngie#if VM_PHYSSEG_MAX == 1
2110312123Sngie	atf_tc_expect_signal(SIGABRT,
2111312123Sngie	    "cannot uvm_page_physunload() the last segment");
2112312123Sngie#endif
2113312123Sngie
2114312123Sngie	ATF_CHECK_EQ(true, uvm_page_physunload(upm, VM_FREELIST_DEFAULT, &p));
2115312123Sngie
2116312123Sngie	ATF_CHECK_EQ(VALID_END_PFN_1 - 1, atop(p));
2117312123Sngie
2118312123Sngie	ATF_CHECK_EQ(1, uvm_physseg_get_entries());
2119312123Sngie
2120312123Sngie	/* The only node now is the one we inserted second. */
2121312123Sngie	upm = uvm_physseg_get_first();
2122312123Sngie
2123312123Sngie	ATF_CHECK_EQ(VALID_START_PFN_2, uvm_physseg_get_start(upm));
2124312123Sngie	ATF_CHECK_EQ(VALID_END_PFN_2, uvm_physseg_get_end(upm));
2125312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_2, uvm_physseg_get_avail_start(upm));
2126312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_2, uvm_physseg_get_avail_end(upm));
2127312123Sngie}
2128312123Sngie
2129312123SngieATF_TC(uvm_page_physunload_delete_end);
2130312123SngieATF_TC_HEAD(uvm_page_physunload_delete_end, tc)
2131312123Sngie{
2132312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the  uvm_page_physunload() \
2133312123Sngie	    works when the segment gets small enough to be deleted scenario. \
2134312123Sngie	    NOTE: This one works deletes from end.");
2135312123Sngie}
2136312123SngieATF_TC_BODY(uvm_page_physunload_delete_end, tc)
2137312123Sngie{
2138312123Sngie	/*
2139312123Sngie	 * Would uvmexp.npages reduce everytime an uvm_page_physunload is called?
2140312123Sngie	 */
2141312123Sngie
2142312123Sngie	paddr_t p = 0;
2143312123Sngie
2144312123Sngie	uvm_physseg_t upm;
2145312123Sngie
2146312123Sngie	setup();
2147312123Sngie
2148312123Sngie	/*
2149312123Sngie	 * Setup the Nuke from Ending point
2150312123Sngie	 */
2151312123Sngie
2152312123Sngie	upm = uvm_page_physload(VALID_START_PFN_1, VALID_START_PFN_1 + 2,
2153312123Sngie	    VALID_AVAIL_START_PFN_1 + 1, VALID_AVAIL_START_PFN_1 + 2,
2154312123Sngie	    VM_FREELIST_DEFAULT);
2155312123Sngie
2156312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
2157312123Sngie
2158312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
2159312123Sngie
2160312123Sngie	/* Insert more than one segment iff VM_PHYSSEG_MAX > 1 */
2161312123Sngie#if VM_PHYSSEG_MAX > 1
2162312123Sngie	uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
2163312123Sngie	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
2164312123Sngie
2165312123Sngie	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
2166312123Sngie#endif
2167312123Sngie
2168312123Sngie#if VM_PHYSSEG_MAX == 1
2169312123Sngie	atf_tc_expect_signal(SIGABRT,
2170312123Sngie	    "cannot uvm_page_physunload() the last segment");
2171312123Sngie#endif
2172312123Sngie
2173312123Sngie	ATF_CHECK_EQ(true, uvm_page_physunload(upm, VM_FREELIST_DEFAULT, &p));
2174312123Sngie
2175312123Sngie	p = 0;
2176312123Sngie
2177312123Sngie	ATF_CHECK_EQ(true, uvm_page_physunload(upm, VM_FREELIST_DEFAULT, &p));
2178312123Sngie
2179312123Sngie	ATF_CHECK_EQ(VALID_START_PFN_1 + 2, atop(p));
2180312123Sngie
2181312123Sngie	ATF_CHECK_EQ(1, uvm_physseg_get_entries());
2182312123Sngie
2183312123Sngie	/* The only node now is the one we inserted second. */
2184312123Sngie	upm = uvm_physseg_get_first();
2185312123Sngie
2186312123Sngie	ATF_CHECK_EQ(VALID_START_PFN_2, uvm_physseg_get_start(upm));
2187312123Sngie	ATF_CHECK_EQ(VALID_END_PFN_2, uvm_physseg_get_end(upm));
2188312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_START_PFN_2, uvm_physseg_get_avail_start(upm));
2189312123Sngie	ATF_CHECK_EQ(VALID_AVAIL_END_PFN_2, uvm_physseg_get_avail_end(upm));
2190312123Sngie}
2191312123Sngie
2192312123SngieATF_TC(uvm_page_physunload_invalid);
2193312123SngieATF_TC_HEAD(uvm_page_physunload_invalid, tc)
2194312123Sngie{
2195312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the  uvm_page_physunload() \
2196312123Sngie	    fails when then Free list does not match.");
2197312123Sngie}
2198312123SngieATF_TC_BODY(uvm_page_physunload_invalid, tc)
2199312123Sngie{
2200312123Sngie	psize_t npages = (VALID_END_PFN_2 - VALID_START_PFN_2);
2201312123Sngie
2202312123Sngie	struct vm_page *pgs = malloc(sizeof(struct vm_page) * npages);
2203312123Sngie
2204312123Sngie	paddr_t p = 0;
2205312123Sngie
2206312123Sngie	uvm_physseg_t upm;
2207312123Sngie
2208312123Sngie	setup();
2209312123Sngie	upm = uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
2210312123Sngie	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
2211312123Sngie
2212312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
2213312123Sngie
2214312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
2215312123Sngie
2216312123Sngie	uvm_physseg_init_seg(upm, pgs);
2217312123Sngie
2218312123Sngie	ATF_CHECK_EQ(false, uvm_page_physunload(upm, VM_FREELIST_FIRST4G, &p));
2219312123Sngie}
2220312123Sngie
2221312123SngieATF_TC(uvm_page_physunload_force);
2222312123SngieATF_TC_HEAD(uvm_page_physunload_force, tc)
2223312123Sngie{
2224312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the basic \
2225312123Sngie	    uvm_page_physunload_force() including delete works without.");
2226312123Sngie}
2227312123SngieATF_TC_BODY(uvm_page_physunload_force, tc)
2228312123Sngie{
2229312123Sngie	/*
2230312123Sngie	 * Would uvmexp.npages reduce everytime an uvm_page_physunload is called?
2231312123Sngie	 */
2232312123Sngie	paddr_t p = 0;
2233312123Sngie
2234312123Sngie	uvm_physseg_t upm;
2235312123Sngie
2236312123Sngie	setup();
2237312123Sngie	upm = uvm_page_physload(VALID_START_PFN_1, VALID_END_PFN_1,
2238312123Sngie	    VALID_AVAIL_START_PFN_1, VALID_AVAIL_END_PFN_1, VM_FREELIST_DEFAULT);
2239312123Sngie
2240312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
2241312123Sngie
2242312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
2243312123Sngie
2244312123Sngie	/* Insert more than one segment iff VM_PHYSSEG_MAX > 1 */
2245312123Sngie#if VM_PHYSSEG_MAX > 1
2246312123Sngie	/*
2247312123Sngie	 * We have couple of physloads done this is bacause of the fact that if
2248312123Sngie	 * we physunload all the PFs from a given range and we have only one
2249312123Sngie	 * segment in total a panic() is called
2250312123Sngie	 */
2251312123Sngie	uvm_page_physload(VALID_START_PFN_2, VALID_END_PFN_2,
2252312123Sngie	    VALID_AVAIL_START_PFN_2, VALID_AVAIL_END_PFN_2, VM_FREELIST_DEFAULT);
2253312123Sngie
2254312123Sngie	ATF_REQUIRE_EQ(2, uvm_physseg_get_entries());
2255312123Sngie#endif
2256312123Sngie
2257312123Sngie#if VM_PHYSSEG_MAX == 1
2258312123Sngie	atf_tc_expect_signal(SIGABRT,
2259312123Sngie	    "cannot uvm_page_physunload() the last segment");
2260312123Sngie#endif
2261312123Sngie
2262312123Sngie	ATF_REQUIRE_EQ(VALID_AVAIL_START_PFN_1,
2263312123Sngie	    uvm_physseg_get_avail_start(upm));
2264312123Sngie
2265312123Sngie	for(paddr_t i = VALID_AVAIL_START_PFN_1;
2266312123Sngie	    i < VALID_AVAIL_END_PFN_1; i++) {
2267312123Sngie		ATF_CHECK_EQ(true,
2268312123Sngie		    uvm_page_physunload_force(upm, VM_FREELIST_DEFAULT, &p));
2269312123Sngie		ATF_CHECK_EQ(i, atop(p));
2270312123Sngie
2271312123Sngie		if(i + 1 < VALID_AVAIL_END_PFN_1)
2272312123Sngie			ATF_CHECK_EQ(i + 1, uvm_physseg_get_avail_start(upm));
2273312123Sngie	}
2274312123Sngie
2275312123Sngie	/*
2276312123Sngie	 * Now we try to retrieve the segment, which has been removed
2277312123Sngie	 * from the system through force unloading all the pages inside it.
2278312123Sngie	 */
2279312123Sngie	upm = uvm_physseg_find(VALID_AVAIL_END_PFN_1 - 1, NULL);
2280312123Sngie
2281312123Sngie	/* It should no longer exist */
2282312123Sngie	ATF_CHECK_EQ(NULL, upm);
2283312123Sngie
2284312123Sngie	ATF_CHECK_EQ(1, uvm_physseg_get_entries());
2285312123Sngie}
2286312123Sngie
2287312123SngieATF_TC(uvm_page_physunload_force_invalid);
2288312123SngieATF_TC_HEAD(uvm_page_physunload_force_invalid, tc)
2289312123Sngie{
2290312123Sngie	atf_tc_set_md_var(tc, "descr", "Tests if the invalid conditions for \
2291312123Sngie	    uvm_page_physunload_force_invalid().");
2292312123Sngie}
2293312123SngieATF_TC_BODY(uvm_page_physunload_force_invalid, tc)
2294312123Sngie{
2295312123Sngie	paddr_t p = 0;
2296312123Sngie
2297312123Sngie	uvm_physseg_t upm;
2298312123Sngie
2299312123Sngie	setup();
2300312123Sngie	upm = uvm_page_physload(VALID_START_PFN_2, VALID_START_PFN_2+ 1,
2301312123Sngie	    VALID_START_PFN_2, VALID_START_PFN_2, VM_FREELIST_DEFAULT);
2302312123Sngie
2303312123Sngie	ATF_REQUIRE_EQ(1, uvm_physseg_get_entries());
2304312123Sngie
2305312123Sngie	ATF_REQUIRE_EQ(0, uvmexp.npages);
2306312123Sngie
2307312123Sngie	ATF_CHECK_EQ(false,
2308312123Sngie	    uvm_page_physunload_force(upm, VM_FREELIST_DEFAULT, &p));
2309312123Sngie
2310312123Sngie	ATF_CHECK_EQ(0, p);
2311312123Sngie}
2312312123Sngie
2313312123SngieATF_TP_ADD_TCS(tp)
2314312123Sngie{
2315312123Sngie#if defined(UVM_HOTPLUG)
2316312123Sngie	/* Internal */
2317312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_alloc_atboot_mismatch);
2318312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_alloc_atboot_overrun);
2319312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_alloc_sanity);
2320312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_free_atboot_mismatch);
2321312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_free_sanity);
2322312123Sngie#if VM_PHYSSEG_MAX > 1
2323312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_atboot_free_leak);
2324312123Sngie#endif
2325312123Sngie#endif /* UVM_HOTPLUG */
2326312123Sngie
2327312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_plug);
2328312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_unplug);
2329312123Sngie
2330312123Sngie	/* Exported */
2331312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_init);
2332312123Sngie	ATF_TP_ADD_TC(tp, uvm_page_physload_preload);
2333312123Sngie	ATF_TP_ADD_TC(tp, uvm_page_physload_postboot);
2334312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_handle_immutable);
2335312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_seg_chomp_slab);
2336312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_alloc_from_slab);
2337312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_init_seg);
2338312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_get_start);
2339312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_get_start_invalid);
2340312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_get_end);
2341312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_get_end_invalid);
2342312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_get_avail_start);
2343312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_get_avail_start_invalid);
2344312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_get_avail_end);
2345312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_get_avail_end_invalid);
2346312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_get_next);
2347312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_get_next_invalid);
2348312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_get_prev);
2349312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_get_prev_invalid);
2350312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_get_first);
2351312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_get_last);
2352312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_valid);
2353312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_valid_invalid);
2354312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_get_highest);
2355312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_get_free_list);
2356312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_get_start_hint);
2357312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_set_start_hint);
2358312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_set_start_hint_invalid);
2359312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_get_pg);
2360312123Sngie
2361312123Sngie#ifdef __HAVE_PMAP_PHYSSEG
2362312123Sngie	ATF_TP_ADD_TC(tp, uvm_physseg_get_pmseg);
2363312123Sngie#endif
2364312123Sngie	ATF_TP_ADD_TC(tp, vm_physseg_find);
2365312123Sngie	ATF_TP_ADD_TC(tp, vm_physseg_find_invalid);
2366312123Sngie
2367312123Sngie	ATF_TP_ADD_TC(tp, uvm_page_physunload_start);
2368312123Sngie	ATF_TP_ADD_TC(tp, uvm_page_physunload_end);
2369312123Sngie	ATF_TP_ADD_TC(tp, uvm_page_physunload_none);
2370312123Sngie	ATF_TP_ADD_TC(tp, uvm_page_physunload_delete_start);
2371312123Sngie	ATF_TP_ADD_TC(tp, uvm_page_physunload_delete_end);
2372312123Sngie	ATF_TP_ADD_TC(tp, uvm_page_physunload_invalid);
2373312123Sngie	ATF_TP_ADD_TC(tp, uvm_page_physunload_force);
2374312123Sngie	ATF_TP_ADD_TC(tp, uvm_page_physunload_force_invalid);
2375312123Sngie
2376312123Sngie	return atf_no_error();
2377312123Sngie}
2378