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