1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13#include <autoconf.h> 14#include <assert.h> 15 16#include <sel4/sel4.h> 17#include <vka/object.h> 18#include <utils/util.h> 19 20#include "../helpers.h" 21#include "frame_type.h" 22 23#if defined(CONFIG_ARCH_ARM) 24static int fill_memory(seL4_Word addr, seL4_Word size_bytes) 25{ 26 test_assert(IS_ALIGNED(addr, sizeof(seL4_Word))); 27 test_assert(IS_ALIGNED(size_bytes, sizeof(seL4_Word))); 28 seL4_Word *p = (void *)addr; 29 seL4_Word size_words = size_bytes / sizeof(seL4_Word); 30 while (size_words--) { 31 *p++ = size_words ^ 0xbeefcafe; 32 } 33 return SUCCESS; 34} 35 36static int __attribute__((warn_unused_result)) 37check_memory(seL4_Word addr, seL4_Word size_bytes) 38{ 39 test_assert(IS_ALIGNED(addr, sizeof(seL4_Word))); 40 test_assert(IS_ALIGNED(size_bytes, sizeof(seL4_Word))); 41 seL4_Word *p = (void *)addr; 42 seL4_Word size_words = size_bytes / sizeof(seL4_Word); 43 while (size_words--) { 44 if (*p++ != (size_words ^ 0xbeefcafe)) { 45 return 0; 46 } 47 } 48 return 1; 49} 50 51#if defined(CONFIG_ARCH_AARCH32) 52#define LPAGE_SIZE (1 << (vka_get_object_size(seL4_ARM_LargePageObject, 0))) 53#define SECT_SIZE (1 << (vka_get_object_size(seL4_ARM_SectionObject, 0))) 54#define SUPSECT_SIZE (1 << (vka_get_object_size(seL4_ARM_SuperSectionObject, 0))) 55 56/* Assumes caps can be mapped in at vaddr (= [vaddr,vaddr + 3*size) */ 57static int do_test_pagetable_tlbflush_on_vaddr_reuse(env_t env, seL4_CPtr cap1, seL4_CPtr cap2, seL4_Word vstart, 58 seL4_Word size) 59{ 60 int error; 61 seL4_Word vaddr; 62 volatile seL4_Word *vptr = NULL; 63 64 /* map, touch page 1 */ 65 vaddr = vstart; 66 vptr = (seL4_Word *)vaddr; 67 error = seL4_ARM_Page_Map(cap1, env->page_directory, 68 vaddr, seL4_AllRights, 69 seL4_ARM_Default_VMAttributes); 70 test_error_eq(error, 0); 71 vptr[0] = 1; 72 error = seL4_ARM_Page_Unmap(cap1); 73 test_error_eq(error, 0); 74 75 /* map, touch page 2 */ 76 vaddr = vstart + size; 77 vptr = (seL4_Word *)vaddr; 78 error = seL4_ARM_Page_Map(cap2, env->page_directory, 79 vaddr, seL4_AllRights, 80 seL4_ARM_Default_VMAttributes); 81 test_error_eq(error, 0); 82 vptr[0] = 2; 83 error = seL4_ARM_Page_Unmap(cap2); 84 test_error_eq(error, 0); 85 86 /* Test TLB */ 87 vaddr = vstart + 2 * size; 88 vptr = (seL4_Word *)vaddr; 89 error = seL4_ARM_Page_Map(cap1, env->page_directory, 90 vaddr, seL4_AllRights, 91 seL4_ARM_Default_VMAttributes); 92 test_error_eq(error, 0); 93 test_check(vptr[0] == 1); 94 95 error = seL4_ARM_Page_Map(cap2, env->page_directory, 96 vaddr, seL4_AllRights, 97 seL4_ARM_Default_VMAttributes); 98 test_error_eq(error, 0); 99 test_check(vptr[0] == 2 || !"TLB contains stale entry"); 100 101 /* clean up */ 102 error = seL4_ARM_Page_Unmap(cap1); 103 test_error_eq(error, 0); 104 error = seL4_ARM_Page_Unmap(cap2); 105 test_error_eq(error, 0); 106 return sel4test_get_result(); 107} 108 109static int test_pagetable_arm(env_t env) 110{ 111 int error; 112 113 /* Grab some free vspace big enough to hold a couple of supersections. */ 114 seL4_Word vstart; 115 reservation_t reserve = vspace_reserve_range(&env->vspace, SUPSECT_SIZE * 4, 116 seL4_AllRights, 1, (void **) &vstart); 117 vstart = ALIGN_UP(vstart, SUPSECT_SIZE * 2); 118 119 /* Create us some frames to play with. */ 120 seL4_CPtr small_page = vka_alloc_object_leaky(&env->vka, seL4_ARM_SmallPageObject, 0); 121 seL4_CPtr small_page2 = vka_alloc_object_leaky(&env->vka, seL4_ARM_SmallPageObject, 0); 122 seL4_CPtr large_page = vka_alloc_object_leaky(&env->vka, seL4_ARM_LargePageObject, 0); 123 seL4_CPtr section = vka_alloc_object_leaky(&env->vka, seL4_ARM_SectionObject, 0); 124 seL4_CPtr supersection = vka_alloc_object_leaky(&env->vka, seL4_ARM_SuperSectionObject, 0); 125 126 test_assert(small_page != 0); 127 test_assert(small_page2 != 0); 128 test_assert(large_page != 0); 129 test_assert(section != 0); 130 test_assert(supersection != 0); 131 132 /* Also create a pagetable to map the pages into. */ 133 seL4_CPtr pt = vka_alloc_page_table_leaky(&env->vka); 134 135 /* Check we can't map the supersection in at an address it's not aligned 136 * to. */ 137 test_assert(supersection != 0); 138 error = seL4_ARM_Page_Map(supersection, env->page_directory, 139 vstart + SUPSECT_SIZE / 2, seL4_AllRights, seL4_ARM_Default_VMAttributes); 140 test_error_eq(error, seL4_AlignmentError); 141 142 /* Check we can map it in somewhere correctly aligned. */ 143 error = seL4_ARM_Page_Map(supersection, env->page_directory, 144 vstart + SUPSECT_SIZE, seL4_AllRights, seL4_ARM_Default_VMAttributes); 145 test_error_eq(error, 0); 146 147 /* Now fill it with stuff to check later. */ 148 /* TDDO fx these constants */ 149 error = fill_memory(vstart + SUPSECT_SIZE, SUPSECT_SIZE); 150 test_assert(error == SUCCESS); 151 152 /* Check we now can't map a section over the top. */ 153 error = seL4_ARM_Page_Map(section, env->page_directory, 154 vstart + SUPSECT_SIZE + SUPSECT_SIZE / 2, seL4_AllRights, 155 seL4_ARM_Default_VMAttributes); 156 test_error_eq(error, seL4_DeleteFirst); 157 158 /* Unmapping the section shouldn't do anything. */ 159 error = seL4_ARM_Page_Unmap(section); 160 test_error_eq(error, 0); 161 162 /* Unmap supersection and try again. */ 163 error = seL4_ARM_Page_Unmap(supersection); 164 test_error_eq(error, 0); 165 166 error = seL4_ARM_Page_Map(section, env->page_directory, 167 vstart + SUPSECT_SIZE + SUPSECT_SIZE / 2, seL4_AllRights, 168 seL4_ARM_Default_VMAttributes); 169 test_error_eq(error, 0); 170 171 fill_memory(vstart + SUPSECT_SIZE + SUPSECT_SIZE / 2, SECT_SIZE); 172 173 /* Now that a section is there, see if we can map a supersection over the 174 * top. */ 175 error = seL4_ARM_Page_Map(supersection, env->page_directory, 176 vstart + SUPSECT_SIZE, seL4_AllRights, seL4_ARM_Default_VMAttributes); 177 test_error_eq(error, seL4_DeleteFirst); 178 179 if (!check_memory(vstart + SUPSECT_SIZE + SUPSECT_SIZE / 2, SECT_SIZE)) { 180 return FAILURE; 181 } 182 183 /* Unmap the section, leaving nothing mapped. */ 184 error = seL4_ARM_Page_Unmap(section); 185 test_error_eq(error, 0); 186 187 /* Now, try mapping in the supersection into two places. */ 188 error = seL4_ARM_Page_Map(supersection, env->page_directory, 189 vstart, seL4_AllRights, seL4_ARM_Default_VMAttributes); 190 test_error_eq(error, 0); 191 error = seL4_ARM_Page_Map(supersection, env->page_directory, 192 vstart + SUPSECT_SIZE, seL4_AllRights, seL4_ARM_Default_VMAttributes); 193 test_error_eq(error, seL4_InvalidArgument); 194 195 /* Now check what we'd written earlier is still there. */ 196 test_assert(check_memory(vstart, SUPSECT_SIZE)); 197 198 /* Try mapping the section into two places. */ 199 error = seL4_ARM_Page_Map(section, env->page_directory, 200 vstart + 2 * SUPSECT_SIZE, seL4_AllRights, seL4_ARM_Default_VMAttributes); 201 test_error_eq(error, 0); 202 error = seL4_ARM_Page_Map(section, env->page_directory, 203 vstart + SUPSECT_SIZE, seL4_AllRights, seL4_ARM_Default_VMAttributes); 204 test_error_eq(error, seL4_InvalidArgument); 205 206 /* Unmap everything again. */ 207 error = seL4_ARM_Page_Unmap(section); 208 test_error_eq(error, 0); 209 error = seL4_ARM_Page_Unmap(supersection); 210 test_error_eq(error, 0); 211 212 /* Map a large page somewhere with no pagetable. */ 213 error = seL4_ARM_Page_Map(large_page, env->page_directory, 214 vstart, seL4_AllRights, seL4_ARM_Default_VMAttributes); 215 test_error_eq(error, seL4_FailedLookup); 216 217 /* Map a pagetable at an unaligned address. Oddly enough, this will succeed 218 * as the kernel silently truncates the address to the nearest correct 219 * boundary. */ 220 error = seL4_ARM_PageTable_Map(pt, env->page_directory, 221 vstart + SECT_SIZE + 10, seL4_ARM_Default_VMAttributes); 222 test_error_eq(error, 0); 223 224 /* Map the large page in at an unaligned address. */ 225 error = seL4_ARM_Page_Map(large_page, env->page_directory, 226 vstart + SECT_SIZE + LPAGE_SIZE / 2, 227 seL4_AllRights, seL4_ARM_Default_VMAttributes); 228 test_error_eq(error, seL4_AlignmentError); 229 230 /* Map the large page in at an aligned address. */ 231 error = seL4_ARM_Page_Map(large_page, env->page_directory, 232 vstart + SECT_SIZE + LPAGE_SIZE, 233 seL4_AllRights, seL4_ARM_Default_VMAttributes); 234 test_error_eq(error, 0); 235 236 /* Map it again, to a different vaddr, and it should fail. */ 237 error = seL4_ARM_Page_Map(large_page, env->page_directory, 238 vstart + SECT_SIZE + 2 * LPAGE_SIZE, 239 seL4_AllRights, seL4_ARM_Default_VMAttributes); 240 test_error_eq(error, seL4_InvalidArgument); 241 242 /* Fill it with more stuff to check. */ 243 fill_memory(vstart + SECT_SIZE + LPAGE_SIZE, LPAGE_SIZE); 244 245 /* Try mapping a small page over the top of it. */ 246 error = seL4_ARM_Page_Map(small_page, env->page_directory, 247 vstart + SECT_SIZE + LPAGE_SIZE, 248 seL4_AllRights, seL4_ARM_Default_VMAttributes); 249 test_error_eq(error, seL4_DeleteFirst); 250 251 /* Try mapping a small page elsewhere useful. */ 252 error = seL4_ARM_Page_Map(small_page, env->page_directory, 253 vstart + SECT_SIZE + 3 * LPAGE_SIZE, 254 seL4_AllRights, seL4_ARM_Default_VMAttributes); 255 test_error_eq(error, 0); 256 257 /* Fill the small page with useful data too. */ 258 fill_memory(vstart + SECT_SIZE + 3 * LPAGE_SIZE, PAGE_SIZE_4K); 259 260 /* Pull the plug on the page table. Apparently a recycle isn't good enough. 261 * Get another pagetable! */ 262 error = seL4_CNode_Delete(env->cspace_root, pt, seL4_WordBits); 263 test_error_eq(error, 0); 264 error = seL4_ARM_Page_Unmap(small_page); 265 test_error_eq(error, 0); 266 error = seL4_ARM_Page_Unmap(large_page); 267 test_error_eq(error, 0); 268 pt = vka_alloc_page_table_leaky(&env->vka); 269 270 /* Map the pagetable somewhere new. */ 271 error = seL4_ARM_PageTable_Map(pt, env->page_directory, 272 vstart, seL4_ARM_Default_VMAttributes); 273 test_error_eq(error, 0); 274 275 /* Map our small page and large page back in. */ 276 error = seL4_ARM_Page_Map(small_page, env->page_directory, 277 vstart + PAGE_SIZE_4K, 278 seL4_AllRights, seL4_ARM_Default_VMAttributes); 279 test_error_eq(error, 0); 280 281 error = seL4_ARM_Page_Map(large_page, env->page_directory, 282 vstart + LPAGE_SIZE, 283 seL4_AllRights, seL4_ARM_Default_VMAttributes); 284 test_error_eq(error, 0); 285 286 /* Check their contents. */ 287 test_assert(check_memory(vstart + PAGE_SIZE_4K, PAGE_SIZE_4K)); 288 test_assert(check_memory(vstart + LPAGE_SIZE, LPAGE_SIZE)); 289 290 /* Now unmap the small page */ 291 error = seL4_ARM_Page_Unmap(small_page); 292 test_error_eq(error, 0); 293 294 /* Unmap the large page. */ 295 error = seL4_ARM_Page_Unmap(large_page); 296 test_error_eq(error, 0); 297 298 /* Now map the large page where the small page was. */ 299 error = seL4_ARM_Page_Map(large_page, env->page_directory, 300 vstart, 301 seL4_AllRights, seL4_ARM_Default_VMAttributes); 302 test_error_eq(error, 0); 303 304 /* Now check the contents of the large page. */ 305 test_assert(check_memory(vstart, LPAGE_SIZE)); 306 307 /* Map the small page elsewhere. */ 308 error = seL4_ARM_Page_Map(small_page, env->page_directory, 309 vstart + LPAGE_SIZE, 310 seL4_AllRights, seL4_ARM_Default_VMAttributes); 311 test_error_eq(error, 0); 312 313 /* Now unmap the small page */ 314 error = seL4_ARM_Page_Unmap(small_page); 315 test_error_eq(error, 0); 316 317 /* Map a different small page in its place. */ 318 error = seL4_ARM_Page_Map(small_page2, env->page_directory, 319 vstart + LPAGE_SIZE, 320 seL4_AllRights, seL4_ARM_Default_VMAttributes); 321 test_error_eq(error, 0); 322 323 /* Fill it in with stuff. */ 324 fill_memory(vstart + LPAGE_SIZE, PAGE_SIZE_4K); 325 326 vspace_free_reservation(&env->vspace, reserve); 327 328 return sel4test_get_result(); 329} 330DEFINE_TEST(PT0001, "Fun with page tables on ARM", test_pagetable_arm, true) 331 332static int 333test_pagetable_tlbflush_on_vaddr_reuse(env_t env) 334{ 335 int error; 336 int result = SUCCESS; 337 338 /* Grab some free vspace big enough to hold a couple of supersections. */ 339 void *vstart; 340 reservation_t reserve = vspace_reserve_range_aligned(&env->vspace, VSPACE_RV_SIZE, VSPACE_RV_ALIGN_BITS, 341 seL4_AllRights, 1, &vstart); 342 test_assert(reserve.res); 343 344 seL4_CPtr cap1, cap2; 345 /* Create us some frames to play with. */ 346 347 /* Also create a pagetable to map the pages into. */ 348 seL4_CPtr pt = vka_alloc_page_table_leaky(&env->vka); 349 350 /* supersection */ 351 cap1 = vka_alloc_object_leaky(&env->vka, seL4_ARM_SuperSectionObject, 0); 352 cap2 = vka_alloc_object_leaky(&env->vka, seL4_ARM_SuperSectionObject, 0); 353 if (do_test_pagetable_tlbflush_on_vaddr_reuse(env, cap1, cap2, (uintptr_t)vstart, SUPSECT_SIZE) == FAILURE) { 354 result = FAILURE; 355 } 356 /* section */ 357 cap1 = vka_alloc_object_leaky(&env->vka, seL4_ARM_SectionObject, 0); 358 cap2 = vka_alloc_object_leaky(&env->vka, seL4_ARM_SectionObject, 0); 359 if (do_test_pagetable_tlbflush_on_vaddr_reuse(env, cap1, cap2, (uintptr_t)vstart, SUPSECT_SIZE) == FAILURE) { 360 result = FAILURE; 361 } 362 363 /* map a PT for smaller page objects */ 364 error = seL4_ARM_PageTable_Map(pt, env->page_directory, 365 (seL4_Word)vstart, seL4_ARM_Default_VMAttributes); 366 test_error_eq(error, 0); 367 368 /* Large page */ 369 cap1 = vka_alloc_object_leaky(&env->vka, seL4_ARM_LargePageObject, 0); 370 cap2 = vka_alloc_object_leaky(&env->vka, seL4_ARM_LargePageObject, 0); 371 if (do_test_pagetable_tlbflush_on_vaddr_reuse(env, cap1, cap2, (uintptr_t)vstart, LPAGE_SIZE) == FAILURE) { 372 result = FAILURE; 373 } 374 /* small page */ 375 cap1 = vka_alloc_object_leaky(&env->vka, seL4_ARM_SmallPageObject, 0); 376 cap2 = vka_alloc_object_leaky(&env->vka, seL4_ARM_SmallPageObject, 0); 377 if (do_test_pagetable_tlbflush_on_vaddr_reuse(env, cap1, cap2, (uintptr_t)vstart, PAGE_SIZE_4K) == FAILURE) { 378 result = FAILURE; 379 } 380 381 return result; 382} 383DEFINE_TEST(PT0002, "Reusing virtual addresses flushes TLB", test_pagetable_tlbflush_on_vaddr_reuse, true) 384 385#elif defined(CONFIG_ARCH_AARCH64) 386#define LPAGE_SIZE (1 << (vka_get_object_size(seL4_ARM_LargePageObject, 0))) 387 388static int 389test_pagetable_arm(env_t env) 390{ 391 int error; 392 393 /* Grab some free vspace big enough to hold a couple of large pages. */ 394 seL4_Word vstart; 395 reservation_t reserve = vspace_reserve_range(&env->vspace, LPAGE_SIZE * 4, 396 seL4_AllRights, 1, (void **) &vstart); 397 vstart = ALIGN_UP(vstart, LPAGE_SIZE * 2); 398 399 /* Create us some frames to play with. */ 400 seL4_CPtr small_page = vka_alloc_object_leaky(&env->vka, seL4_ARM_SmallPageObject, 0); 401 seL4_CPtr small_page2 = vka_alloc_object_leaky(&env->vka, seL4_ARM_SmallPageObject, 0); 402 seL4_CPtr large_page = vka_alloc_object_leaky(&env->vka, seL4_ARM_LargePageObject, 0); 403 404 test_assert(small_page != 0); 405 test_assert(small_page2 != 0); 406 test_assert(large_page != 0); 407 408 /* Also create a pagetable to map the pages into. */ 409 seL4_CPtr pt = vka_alloc_page_table_leaky(&env->vka); 410 411 /* Check we can't map the large page in at an address it's not aligned to. */ 412 error = seL4_ARM_Page_Map(large_page, env->page_directory, 413 vstart + LPAGE_SIZE / 2, seL4_AllRights, seL4_ARM_Default_VMAttributes); 414 test_error_eq(error, seL4_AlignmentError); 415 416 /* Check we can map it in somewhere correctly aligned. */ 417 error = seL4_ARM_Page_Map(large_page, env->page_directory, 418 vstart + LPAGE_SIZE, seL4_AllRights, seL4_ARM_Default_VMAttributes); 419 test_error_eq(error, 0); 420 421 /* Unmap large page and try again. */ 422 error = seL4_ARM_Page_Unmap(large_page); 423 test_error_eq(error, 0); 424 425 error = seL4_ARM_Page_Map(large_page, env->page_directory, 426 vstart + LPAGE_SIZE, seL4_AllRights, seL4_ARM_Default_VMAttributes); 427 test_error_eq(error, 0); 428 429 fill_memory(vstart + LPAGE_SIZE, LPAGE_SIZE); 430 431 /* Unmap the large page, leaving nothing mapped. */ 432 error = seL4_ARM_Page_Unmap(large_page); 433 test_error_eq(error, 0); 434 435 /* Now, try mapping in the large page into two places. */ 436 error = seL4_ARM_Page_Map(large_page, env->page_directory, 437 vstart, seL4_AllRights, seL4_ARM_Default_VMAttributes); 438 test_error_eq(error, 0); 439 440 /* Trying to remap to a different vaddr */ 441 error = seL4_ARM_Page_Map(large_page, env->page_directory, 442 vstart + LPAGE_SIZE, seL4_AllRights, seL4_ARM_Default_VMAttributes); 443 test_error_eq(error, seL4_InvalidArgument); 444 445 /* Now check what we'd written earlier is still there. */ 446 test_assert(check_memory(vstart, LPAGE_SIZE)); 447 448 /* Unmap everything again. */ 449 error = seL4_ARM_Page_Unmap(large_page); 450 test_error_eq(error, 0); 451 452 /* Map a small page somewhere with no pagetable. */ 453 error = seL4_ARM_Page_Map(small_page, env->page_directory, 454 vstart, seL4_AllRights, seL4_ARM_Default_VMAttributes); 455 test_error_eq(error, seL4_FailedLookup); 456 457 /* Map a pagetable at an unaligned address. Oddly enough, this will succeed 458 * as the kernel silently truncates the address to the nearest correct 459 * boundary. */ 460 error = seL4_ARM_PageTable_Map(pt, env->page_directory, 461 vstart + LPAGE_SIZE + 10, seL4_ARM_Default_VMAttributes); 462 test_error_eq(error, 0); 463 464 /* Try mapping a small page. */ 465 error = seL4_ARM_Page_Map(small_page, env->page_directory, vstart + LPAGE_SIZE + PAGE_SIZE_4K, 466 seL4_AllRights, seL4_ARM_Default_VMAttributes); 467 test_error_eq(error, 0); 468 469 /* Fill the small page with useful data too. */ 470 fill_memory(vstart + LPAGE_SIZE + PAGE_SIZE_4K, PAGE_SIZE_4K); 471 472 /* Pull the plug on the page table. Apparently a recycle isn't good enough. 473 * Get another pagetable! */ 474 error = seL4_CNode_Delete(env->cspace_root, pt, seL4_WordBits); 475 test_error_eq(error, 0); 476 error = seL4_ARM_Page_Unmap(small_page); 477 test_error_eq(error, 0); 478 error = seL4_ARM_Page_Unmap(large_page); 479 test_error_eq(error, 0); 480 pt = vka_alloc_page_table_leaky(&env->vka); 481 482 /* Map the pagetable somewhere new. */ 483 error = seL4_ARM_PageTable_Map(pt, env->page_directory, 484 vstart, seL4_ARM_Default_VMAttributes); 485 test_error_eq(error, 0); 486 487 /* Map our small page and large page back in. */ 488 error = seL4_ARM_Page_Map(small_page, env->page_directory, 489 vstart + PAGE_SIZE_4K, 490 seL4_AllRights, seL4_ARM_Default_VMAttributes); 491 test_error_eq(error, 0); 492 493 error = seL4_ARM_Page_Map(large_page, env->page_directory, 494 vstart + LPAGE_SIZE, 495 seL4_AllRights, seL4_ARM_Default_VMAttributes); 496 test_error_eq(error, 0); 497 498 /* Check their contents. */ 499 test_assert(check_memory(vstart + PAGE_SIZE_4K, PAGE_SIZE_4K)); 500 test_assert(check_memory(vstart + LPAGE_SIZE, LPAGE_SIZE)); 501 502 /* Now unmap the small page */ 503 error = seL4_ARM_Page_Unmap(small_page); 504 test_error_eq(error, 0); 505 506 /* Unmap the large page. */ 507 error = seL4_ARM_Page_Unmap(large_page); 508 test_error_eq(error, 0); 509 510 vspace_free_reservation(&env->vspace, reserve); 511 512 return sel4test_get_result(); 513} 514DEFINE_TEST(PT0001, "Fun with page tables on ARM", test_pagetable_arm, true) 515#endif /* CONFIG_ARCH_AARCHxx */ 516#endif /* CONFIG_ARCH_ARM */ 517