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