1 /* $NetBSD: t_uvm_physseg_load.c,v 1.2 2016/12/22 08:15:20 cherry Exp $ */ 2 3 /*- 4 * Copyright (c) 2015, 2016 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Santhosh N. Raju <santhosh.raju@gmail.com> and 9 * by Cherry G. Mathew 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 #include <sys/cdefs.h> 34 __RCSID("$NetBSD: t_uvm_physseg_load.c,v 1.2 2016/12/22 08:15:20 cherry Exp $"); 35 36 /* 37 * If this line is commented out tests related touvm_physseg_get_pmseg() 38 * wont run. 39 * 40 * Have a look at machine/uvm_physseg.h for more details. 41 */ 42 #define __HAVE_PMAP_PHYSSEG 43 44 /* 45 * This is a dummy struct used for testing purposes 46 * 47 * In reality this struct would exist in the MD part of the code residing in 48 * machines/vmparam.h 49 */ 50 51 #ifdef __HAVE_PMAP_PHYSSEG 52 struct pmap_physseg { 53 int dummy_variable; /* Dummy variable use for testing */ 54 }; 55 #endif 56 57 /* Testing API - assumes userland */ 58 /* Provide Kernel API equivalents */ 59 #include <assert.h> 60 #include <stdbool.h> 61 #include <string.h> /* memset(3) et. al */ 62 #include <stdio.h> /* printf(3) */ 63 #include <stdlib.h> /* malloc(3) */ 64 #include <stdarg.h> 65 #include <stddef.h> 66 #include <time.h> 67 68 #define PRIxPADDR "lx" 69 #define PRIxPSIZE "lx" 70 #define PRIuPSIZE "lu" 71 #define PRIxVADDR "lx" 72 #define PRIxVSIZE "lx" 73 #define PRIuVSIZE "lu" 74 75 #define UVM_HOTPLUG /* Enable hotplug with rbtree. */ 76 #define PMAP_STEAL_MEMORY 77 #define DEBUG /* Enable debug functionality. */ 78 79 typedef unsigned long vaddr_t; 80 typedef unsigned long paddr_t; 81 typedef unsigned long psize_t; 82 typedef unsigned long vsize_t; 83 84 #include <uvm/uvm_physseg.h> 85 #include <uvm/uvm_page.h> 86 87 #ifndef DIAGNOSTIC 88 #define KASSERTMSG(e, msg, ...) /* NOTHING */ 89 #define KASSERT(e) /* NOTHING */ 90 #else 91 #define KASSERT(a) assert(a) 92 #define KASSERTMSG(exp, ...) printf(__VA_ARGS__); assert((exp)) 93 #endif 94 95 #define VM_PHYSSEG_STRAT VM_PSTRAT_BSEARCH 96 97 #define VM_NFREELIST 4 98 #define VM_FREELIST_DEFAULT 0 99 #define VM_FREELIST_FIRST16 3 100 #define VM_FREELIST_FIRST1G 2 101 #define VM_FREELIST_FIRST4G 1 102 103 /* 104 * Used in tests when Array implementation is tested 105 */ 106 #if !defined(VM_PHYSSEG_MAX) 107 #define VM_PHYSSEG_MAX 32 108 #endif 109 110 #define PAGE_SIZE 4096 111 #define PAGE_SHIFT 12 112 #define atop(x) (((paddr_t)(x)) >> PAGE_SHIFT) 113 114 #define mutex_enter(l) 115 #define mutex_exit(l) 116 117 #define _SYS_KMEM_H_ /* Disallow the real kmem API (see below) */ 118 /* free(p) XXX: pgs management need more thought */ 119 #define kmem_alloc(size, flags) malloc(size) 120 #define kmem_zalloc(size, flags) malloc(size) 121 #define kmem_free(p, size) free(p) 122 123 psize_t physmem; 124 125 struct uvmexp uvmexp; /* decl */ 126 127 /* 128 * uvm structure borrowed from uvm.h 129 * 130 * Remember this is a dummy structure used within the ATF Tests and 131 * uses only necessary fields from the original uvm struct. 132 * See uvm/uvm.h for the full struct. 133 */ 134 135 struct uvm { 136 /* vm_page related parameters */ 137 138 bool page_init_done; /* TRUE if uvm_page_init() finished */ 139 } uvm; 140 141 static void 142 panic(const char *fmt, ...) 143 { 144 va_list ap; 145 146 va_start(ap, fmt); 147 vprintf(fmt, ap); 148 printf("\n"); 149 va_end(ap); 150 KASSERT(false); 151 152 /*NOTREACHED*/ 153 } 154 155 static void 156 uvm_pagefree(struct vm_page *pg) 157 { 158 return; 159 } 160 161 #if defined(UVM_HOTPLUG) 162 static void 163 uvmpdpol_reinit(void) 164 { 165 return; 166 } 167 #endif /* UVM_HOTPLUG */ 168 169 /* end - Provide Kernel API equivalents */ 170 171 #include "uvm/uvm_physseg.c" 172 173 #include <atf-c.h> 174 175 #define ONE_MEGABYTE 1024 * 1024 176 177 /* Sample Page Frame Numbers */ 178 #define VALID_START_PFN_1 atop(0) 179 #define VALID_END_PFN_1 atop(ONE_MEGABYTE) 180 #define VALID_AVAIL_START_PFN_1 atop(0) 181 #define VALID_AVAIL_END_PFN_1 atop(ONE_MEGABYTE) 182 183 #define VALID_START_PFN_2 atop(ONE_MEGABYTE + 1) 184 #define VALID_END_PFN_2 atop(ONE_MEGABYTE * 2) 185 #define VALID_AVAIL_START_PFN_2 atop(ONE_MEGABYTE + 1) 186 #define VALID_AVAIL_END_PFN_2 atop(ONE_MEGABYTE * 2) 187 188 #define VALID_START_PFN_3 atop((ONE_MEGABYTE * 2) + 1) 189 #define VALID_END_PFN_3 atop(ONE_MEGABYTE * 3) 190 #define VALID_AVAIL_START_PFN_3 atop((ONE_MEGABYTE * 2) + 1) 191 #define VALID_AVAIL_END_PFN_3 atop(ONE_MEGABYTE * 3) 192 193 #define VALID_START_PFN_4 atop(ONE_MEGABYTE + 1) 194 #define VALID_END_PFN_4 atop(ONE_MEGABYTE * 128) 195 #define VALID_AVAIL_START_PFN_4 atop(ONE_MEGABYTE + 1) 196 #define VALID_AVAIL_END_PFN_4 atop(ONE_MEGABYTE * 128) 197 198 #define VALID_START_PFN_5 atop(ONE_MEGABYTE + 1) 199 #define VALID_END_PFN_5 atop(ONE_MEGABYTE * 256) 200 #define VALID_AVAIL_START_PFN_5 atop(ONE_MEGABYTE + 1) 201 #define VALID_AVAIL_END_PFN_5 atop(ONE_MEGABYTE * 256) 202 203 /* 204 * Total number of pages (of 4K size each) should be 256 for 1MB of memory. 205 */ 206 #define PAGE_COUNT_1M 256 207 208 /* 209 * The number of Page Frames to allot per segment 210 */ 211 #define PF_STEP 8 212 213 /* 214 * A debug fucntion to print the content of upm. 215 */ 216 static inline void 217 uvm_physseg_dump_seg(uvm_physseg_t upm) 218 { 219 #if defined(DEBUG) 220 printf("%s: seg->start == %ld\n", __func__, 221 uvm_physseg_get_start(upm)); 222 printf("%s: seg->end == %ld\n", __func__, 223 uvm_physseg_get_end(upm)); 224 printf("%s: seg->avail_start == %ld\n", __func__, 225 uvm_physseg_get_avail_start(upm)); 226 printf("%s: seg->avail_end == %ld\n", __func__, 227 uvm_physseg_get_avail_end(upm)); 228 229 printf("====\n\n"); 230 #else 231 return; 232 #endif /* DEBUG */ 233 } 234 235 /* 236 * Private accessor that gets the value of vm_physmem.nentries 237 */ 238 static int 239 uvm_physseg_get_entries(void) 240 { 241 #if defined(UVM_HOTPLUG) 242 return uvm_physseg_graph.nentries; 243 #else 244 return vm_nphysmem; 245 #endif /* UVM_HOTPLUG */ 246 } 247 248 /* 249 * Note: This function replicates verbatim what happens in 250 * uvm_page.c:uvm_page_init(). 251 * 252 * Please track any changes that happen there. 253 */ 254 static void 255 uvm_page_init_fake(struct vm_page *pagearray, psize_t pagecount) 256 { 257 uvm_physseg_t bank; 258 size_t n; 259 260 for (bank = uvm_physseg_get_first(), 261 uvm_physseg_seg_chomp_slab(bank, pagearray, pagecount); 262 uvm_physseg_valid_p(bank); 263 bank = uvm_physseg_get_next(bank)) { 264 265 n = uvm_physseg_get_end(bank) - uvm_physseg_get_start(bank); 266 uvm_physseg_seg_alloc_from_slab(bank, n); 267 uvm_physseg_init_seg(bank, pagearray); 268 269 /* set up page array pointers */ 270 pagearray += n; 271 pagecount -= n; 272 } 273 274 uvm.page_init_done = true; 275 } 276 277 /* 278 * PHYS_TO_VM_PAGE: find vm_page for a PA. used by MI code to get vm_pages 279 * back from an I/O mapping (ugh!). used in some MD code as well. 280 */ 281 static struct vm_page * 282 uvm_phys_to_vm_page(paddr_t pa) 283 { 284 paddr_t pf = atop(pa); 285 paddr_t off; 286 uvm_physseg_t psi; 287 288 psi = uvm_physseg_find(pf, &off); 289 if (psi != UVM_PHYSSEG_TYPE_INVALID) 290 return uvm_physseg_get_pg(psi, off); 291 return(NULL); 292 } 293 294 //static paddr_t 295 //uvm_vm_page_to_phys(const struct vm_page *pg) 296 //{ 297 // 298 // return pg->phys_addr; 299 //} 300 301 /* 302 * XXX: To do, write control test cases for uvm_vm_page_to_phys(). 303 */ 304 305 /* #define VM_PAGE_TO_PHYS(entry) uvm_vm_page_to_phys(entry) */ 306 307 #define PHYS_TO_VM_PAGE(pa) uvm_phys_to_vm_page(pa) 308 309 /* 310 * Test Fixture SetUp(). 311 */ 312 static void 313 setup(void) 314 { 315 /* Prerequisites for running certain calls in uvm_physseg */ 316 uvmexp.pagesize = PAGE_SIZE; 317 uvmexp.npages = 0; 318 uvm.page_init_done = false; 319 uvm_physseg_init(); 320 } 321 322 ATF_TC(uvm_physseg_100); 323 ATF_TC_HEAD(uvm_physseg_100, tc) 324 { 325 atf_tc_set_md_var(tc, "descr", "Load test uvm_phys_to_vm_page() with \ 326 100 calls, VM_PHYSSEG_MAX is 32."); 327 } 328 ATF_TC_BODY(uvm_physseg_100, tc) 329 { 330 paddr_t pa; 331 332 setup(); 333 334 for(paddr_t i = VALID_START_PFN_1; 335 i < VALID_END_PFN_1; i += PF_STEP) { 336 uvm_page_physload(i, i + PF_STEP, i, i + PF_STEP, 337 VM_FREELIST_DEFAULT); 338 } 339 340 ATF_REQUIRE_EQ(VM_PHYSSEG_MAX, uvm_physseg_get_entries()); 341 342 srandom((unsigned)time(NULL)); 343 for(int i = 0; i < 100; i++) { 344 pa = (paddr_t) random() % (paddr_t) ctob(VALID_END_PFN_1); 345 PHYS_TO_VM_PAGE(pa); 346 } 347 348 ATF_CHECK_EQ(true, true); 349 } 350 351 ATF_TC(uvm_physseg_1K); 352 ATF_TC_HEAD(uvm_physseg_1K, tc) 353 { 354 atf_tc_set_md_var(tc, "descr", "Load test uvm_phys_to_vm_page() with \ 355 1000 calls, VM_PHYSSEG_MAX is 32."); 356 } 357 ATF_TC_BODY(uvm_physseg_1K, tc) 358 { 359 paddr_t pa; 360 361 setup(); 362 363 for(paddr_t i = VALID_START_PFN_1; 364 i < VALID_END_PFN_1; i += PF_STEP) { 365 uvm_page_physload(i, i + PF_STEP, i, i + PF_STEP, 366 VM_FREELIST_DEFAULT); 367 } 368 369 ATF_REQUIRE_EQ(VM_PHYSSEG_MAX, uvm_physseg_get_entries()); 370 371 srandom((unsigned)time(NULL)); 372 for(int i = 0; i < 1000; i++) { 373 pa = (paddr_t) random() % (paddr_t) ctob(VALID_END_PFN_1); 374 PHYS_TO_VM_PAGE(pa); 375 } 376 377 ATF_CHECK_EQ(true, true); 378 } 379 380 ATF_TC(uvm_physseg_10K); 381 ATF_TC_HEAD(uvm_physseg_10K, tc) 382 { 383 atf_tc_set_md_var(tc, "descr", "Load test uvm_phys_to_vm_page() with \ 384 10,000 calls, VM_PHYSSEG_MAX is 32."); 385 } 386 ATF_TC_BODY(uvm_physseg_10K, tc) 387 { 388 paddr_t pa; 389 390 setup(); 391 392 for(paddr_t i = VALID_START_PFN_1; 393 i < VALID_END_PFN_1; i += PF_STEP) { 394 uvm_page_physload(i, i + PF_STEP, i, i + PF_STEP, 395 VM_FREELIST_DEFAULT); 396 } 397 398 ATF_REQUIRE_EQ(VM_PHYSSEG_MAX, uvm_physseg_get_entries()); 399 400 srandom((unsigned)time(NULL)); 401 for(int i = 0; i < 10000; i++) { 402 pa = (paddr_t) random() % (paddr_t) ctob(VALID_END_PFN_1); 403 PHYS_TO_VM_PAGE(pa); 404 } 405 406 ATF_CHECK_EQ(true, true); 407 } 408 409 ATF_TC(uvm_physseg_100K); 410 ATF_TC_HEAD(uvm_physseg_100K, tc) 411 { 412 atf_tc_set_md_var(tc, "descr", "Load test uvm_phys_to_vm_page() with \ 413 100,000 calls, VM_PHYSSEG_MAX is 32."); 414 } 415 ATF_TC_BODY(uvm_physseg_100K, tc) 416 { 417 paddr_t pa; 418 419 setup(); 420 421 for(paddr_t i = VALID_START_PFN_1; 422 i < VALID_END_PFN_1; i += PF_STEP) { 423 uvm_page_physload(i, i + PF_STEP, i, i + PF_STEP, 424 VM_FREELIST_DEFAULT); 425 } 426 427 ATF_REQUIRE_EQ(VM_PHYSSEG_MAX, uvm_physseg_get_entries()); 428 429 srandom((unsigned)time(NULL)); 430 for(int i = 0; i < 100000; i++) { 431 pa = (paddr_t) random() % (paddr_t) ctob(VALID_END_PFN_1); 432 PHYS_TO_VM_PAGE(pa); 433 } 434 435 ATF_CHECK_EQ(true, true); 436 } 437 438 ATF_TC(uvm_physseg_1M); 439 ATF_TC_HEAD(uvm_physseg_1M, tc) 440 { 441 atf_tc_set_md_var(tc, "descr", "Load test uvm_phys_to_vm_page() with \ 442 1,000,000 calls, VM_PHYSSEG_MAX is 32."); 443 } 444 ATF_TC_BODY(uvm_physseg_1M, tc) 445 { 446 paddr_t pa; 447 448 setup(); 449 450 for(paddr_t i = VALID_START_PFN_1; 451 i < VALID_END_PFN_1; i += PF_STEP) { 452 uvm_page_physload(i, i + PF_STEP, i, i + PF_STEP, 453 VM_FREELIST_DEFAULT); 454 } 455 456 ATF_REQUIRE_EQ(VM_PHYSSEG_MAX, uvm_physseg_get_entries()); 457 458 srandom((unsigned)time(NULL)); 459 for(int i = 0; i < 1000000; i++) { 460 pa = (paddr_t) random() % (paddr_t) ctob(VALID_END_PFN_1); 461 PHYS_TO_VM_PAGE(pa); 462 } 463 464 ATF_CHECK_EQ(true, true); 465 } 466 467 ATF_TC(uvm_physseg_10M); 468 ATF_TC_HEAD(uvm_physseg_10M, tc) 469 { 470 atf_tc_set_md_var(tc, "descr", "Load test uvm_phys_to_vm_page() with \ 471 10,000,000 calls, VM_PHYSSEG_MAX is 32."); 472 } 473 ATF_TC_BODY(uvm_physseg_10M, tc) 474 { 475 paddr_t pa; 476 477 setup(); 478 479 for(paddr_t i = VALID_START_PFN_1; 480 i < VALID_END_PFN_1; i += PF_STEP) { 481 uvm_page_physload(i, i + PF_STEP, i, i + PF_STEP, 482 VM_FREELIST_DEFAULT); 483 } 484 485 ATF_REQUIRE_EQ(VM_PHYSSEG_MAX, uvm_physseg_get_entries()); 486 487 srandom((unsigned)time(NULL)); 488 for(int i = 0; i < 10000000; i++) { 489 pa = (paddr_t) random() % (paddr_t) ctob(VALID_END_PFN_1); 490 PHYS_TO_VM_PAGE(pa); 491 } 492 493 ATF_CHECK_EQ(true, true); 494 } 495 496 ATF_TC(uvm_physseg_100M); 497 ATF_TC_HEAD(uvm_physseg_100M, tc) 498 { 499 atf_tc_set_md_var(tc, "descr", "Load test uvm_phys_to_vm_page() with \ 500 100,000,000 calls, VM_PHYSSEG_MAX is 32."); 501 } 502 ATF_TC_BODY(uvm_physseg_100M, tc) 503 { 504 paddr_t pa; 505 506 setup(); 507 508 for(paddr_t i = VALID_START_PFN_1; 509 i < VALID_END_PFN_1; i += PF_STEP) { 510 uvm_page_physload(i, i + PF_STEP, i, i + PF_STEP, 511 VM_FREELIST_DEFAULT); 512 } 513 514 ATF_REQUIRE_EQ(VM_PHYSSEG_MAX, uvm_physseg_get_entries()); 515 516 srandom((unsigned)time(NULL)); 517 for(int i = 0; i < 100000000; i++) { 518 pa = (paddr_t) random() % (paddr_t) ctob(VALID_END_PFN_1); 519 PHYS_TO_VM_PAGE(pa); 520 } 521 522 ATF_CHECK_EQ(true, true); 523 } 524 525 ATF_TC(uvm_physseg_1MB); 526 ATF_TC_HEAD(uvm_physseg_1MB, tc) 527 { 528 atf_tc_set_md_var(tc, "descr", "Load test uvm_phys_to_vm_page() with \ 529 10,000,000 calls, VM_PHYSSEG_MAX is 32 on 1 MB Segment."); 530 } 531 ATF_TC_BODY(uvm_physseg_1MB, t) 532 { 533 paddr_t pa = 0; 534 535 paddr_t pf = 0; 536 537 psize_t pf_chunk_size = 0; 538 539 psize_t npages1 = (VALID_END_PFN_1 - VALID_START_PFN_1); 540 541 psize_t npages2 = (VALID_END_PFN_2 - VALID_START_PFN_2); 542 543 struct vm_page *slab = malloc(sizeof(struct vm_page) * 544 (npages1 + npages2)); 545 546 setup(); 547 548 /* We start with zero segments */ 549 ATF_REQUIRE_EQ(true, uvm_physseg_plug(VALID_START_PFN_1, npages1, NULL)); 550 ATF_REQUIRE_EQ(1, uvm_physseg_get_entries()); 551 552 /* Post boot: Fake all segments and pages accounted for. */ 553 uvm_page_init_fake(slab, npages1 + npages2); 554 555 ATF_REQUIRE_EQ(true, uvm_physseg_plug(VALID_START_PFN_2, npages2, NULL)); 556 ATF_REQUIRE_EQ(2, uvm_physseg_get_entries()); 557 558 srandom((unsigned)time(NULL)); 559 for(pf = VALID_START_PFN_2; pf < VALID_END_PFN_2; pf += PF_STEP) { 560 pf_chunk_size = (psize_t) random() % (psize_t) (PF_STEP - 1) + 1; 561 uvm_physseg_unplug(pf, pf_chunk_size); 562 } 563 564 for(int i = 0; i < 10000000; i++) { 565 pa = (paddr_t) random() % (paddr_t) ctob(VALID_END_PFN_2); 566 if(pa < ctob(VALID_START_PFN_2)) 567 pa += ctob(VALID_START_PFN_2); 568 PHYS_TO_VM_PAGE(pa); 569 } 570 571 ATF_CHECK_EQ(true, true); 572 } 573 574 ATF_TC(uvm_physseg_64MB); 575 ATF_TC_HEAD(uvm_physseg_64MB, tc) 576 { 577 atf_tc_set_md_var(tc, "descr", "Load test uvm_phys_to_vm_page() with \ 578 10,000,000 calls, VM_PHYSSEG_MAX is 32 on 64 MB Segment."); 579 } 580 ATF_TC_BODY(uvm_physseg_64MB, t) 581 { 582 paddr_t pa = 0; 583 584 paddr_t pf = 0; 585 586 psize_t pf_chunk_size = 0; 587 588 psize_t npages1 = (VALID_END_PFN_1 - VALID_START_PFN_1); 589 590 psize_t npages2 = (VALID_END_PFN_3 - VALID_START_PFN_3); 591 592 struct vm_page *slab = malloc(sizeof(struct vm_page) * 593 (npages1 + npages2)); 594 595 setup(); 596 597 /* We start with zero segments */ 598 ATF_REQUIRE_EQ(true, uvm_physseg_plug(VALID_START_PFN_1, npages1, NULL)); 599 ATF_REQUIRE_EQ(1, uvm_physseg_get_entries()); 600 601 /* Post boot: Fake all segments and pages accounted for. */ 602 uvm_page_init_fake(slab, npages1 + npages2); 603 604 ATF_REQUIRE_EQ(true, uvm_physseg_plug(VALID_START_PFN_3, npages2, NULL)); 605 ATF_REQUIRE_EQ(2, uvm_physseg_get_entries()); 606 607 srandom((unsigned)time(NULL)); 608 for(pf = VALID_START_PFN_3; pf < VALID_END_PFN_3; pf += PF_STEP) { 609 pf_chunk_size = (psize_t) random() % (psize_t) (PF_STEP - 1) + 1; 610 uvm_physseg_unplug(pf, pf_chunk_size); 611 } 612 613 for(int i = 0; i < 10000000; i++) { 614 pa = (paddr_t) random() % (paddr_t) ctob(VALID_END_PFN_3); 615 if(pa < ctob(VALID_START_PFN_3)) 616 pa += ctob(VALID_START_PFN_3); 617 PHYS_TO_VM_PAGE(pa); 618 } 619 620 ATF_CHECK_EQ(true, true); 621 } 622 623 ATF_TC(uvm_physseg_128MB); 624 ATF_TC_HEAD(uvm_physseg_128MB, tc) 625 { 626 atf_tc_set_md_var(tc, "descr", "Load test uvm_phys_to_vm_page() with \ 627 10,000,000 calls, VM_PHYSSEG_MAX is 32 on 128 MB Segment."); 628 } 629 ATF_TC_BODY(uvm_physseg_128MB, t) 630 { 631 paddr_t pa = 0; 632 633 paddr_t pf = 0; 634 635 psize_t pf_chunk_size = 0; 636 637 psize_t npages1 = (VALID_END_PFN_1 - VALID_START_PFN_1); 638 639 psize_t npages2 = (VALID_END_PFN_4 - VALID_START_PFN_4); 640 641 struct vm_page *slab = malloc(sizeof(struct vm_page) 642 * (npages1 + npages2)); 643 644 setup(); 645 646 /* We start with zero segments */ 647 ATF_REQUIRE_EQ(true, uvm_physseg_plug(VALID_START_PFN_1, npages1, NULL)); 648 ATF_REQUIRE_EQ(1, uvm_physseg_get_entries()); 649 650 /* Post boot: Fake all segments and pages accounted for. */ 651 uvm_page_init_fake(slab, npages1 + npages2); 652 653 ATF_REQUIRE_EQ(true, uvm_physseg_plug(VALID_START_PFN_2, npages2, NULL)); 654 ATF_REQUIRE_EQ(2, uvm_physseg_get_entries()); 655 656 srandom((unsigned)time(NULL)); 657 for(pf = VALID_START_PFN_4; pf < VALID_END_PFN_4; pf += PF_STEP) { 658 pf_chunk_size = (psize_t) random() % (psize_t) (PF_STEP - 1) + 1; 659 uvm_physseg_unplug(pf, pf_chunk_size); 660 } 661 662 for(int i = 0; i < 10000000; i++) { 663 pa = (paddr_t) random() % (paddr_t) ctob(VALID_END_PFN_4); 664 if(pa < ctob(VALID_START_PFN_4)) 665 pa += ctob(VALID_START_PFN_4); 666 PHYS_TO_VM_PAGE(pa); 667 } 668 669 ATF_CHECK_EQ(true, true); 670 } 671 672 ATF_TC(uvm_physseg_256MB); 673 ATF_TC_HEAD(uvm_physseg_256MB, tc) 674 { 675 atf_tc_set_md_var(tc, "descr", "Load test uvm_phys_to_vm_page() with \ 676 10,000,000 calls, VM_PHYSSEG_MAX is 32 on 256 MB Segment."); 677 } 678 ATF_TC_BODY(uvm_physseg_256MB, t) 679 { 680 paddr_t pa = 0; 681 682 paddr_t pf = 0; 683 684 psize_t pf_chunk_size = 0; 685 686 psize_t npages1 = (VALID_END_PFN_1 - VALID_START_PFN_1); 687 688 psize_t npages2 = (VALID_END_PFN_5 - VALID_START_PFN_5); 689 690 struct vm_page *slab = malloc(sizeof(struct vm_page) * (npages1 + npages2)); 691 692 setup(); 693 694 /* We start with zero segments */ 695 ATF_REQUIRE_EQ(true, uvm_physseg_plug(VALID_START_PFN_1, npages1, NULL)); 696 ATF_REQUIRE_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_REQUIRE_EQ(true, uvm_physseg_plug(VALID_START_PFN_2, npages2, NULL)); 702 ATF_REQUIRE_EQ(2, uvm_physseg_get_entries()); 703 704 srandom((unsigned)time(NULL)); 705 for(pf = VALID_START_PFN_5; pf < VALID_END_PFN_5; pf += PF_STEP) { 706 pf_chunk_size = (psize_t) random() % (psize_t) (PF_STEP - 1) + 1; 707 uvm_physseg_unplug(pf, pf_chunk_size); 708 } 709 710 for(int i = 0; i < 10000000; i++) { 711 pa = (paddr_t) random() % (paddr_t) ctob(VALID_END_PFN_5); 712 if(pa < ctob(VALID_END_PFN_5)) 713 pa += ctob(VALID_START_PFN_5); 714 PHYS_TO_VM_PAGE(pa); 715 } 716 717 ATF_CHECK_EQ(true, true); 718 } 719 720 ATF_TP_ADD_TCS(tp) 721 { 722 /* Fixed memory size tests. */ 723 ATF_TP_ADD_TC(tp, uvm_physseg_100); 724 ATF_TP_ADD_TC(tp, uvm_physseg_1K); 725 ATF_TP_ADD_TC(tp, uvm_physseg_10K); 726 ATF_TP_ADD_TC(tp, uvm_physseg_100K); 727 ATF_TP_ADD_TC(tp, uvm_physseg_1M); 728 ATF_TP_ADD_TC(tp, uvm_physseg_10M); 729 ATF_TP_ADD_TC(tp, uvm_physseg_100M); 730 731 #if defined(UVM_HOTPLUG) 732 /* Variable memory size tests. */ 733 ATF_TP_ADD_TC(tp, uvm_physseg_1MB); 734 ATF_TP_ADD_TC(tp, uvm_physseg_64MB); 735 ATF_TP_ADD_TC(tp, uvm_physseg_128MB); 736 ATF_TP_ADD_TC(tp, uvm_physseg_256MB); 737 #endif /* UVM_HOTPLUG */ 738 739 return atf_no_error(); 740 } 741