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#include <stdio.h> 16#include <stdlib.h> 17#include <sel4/sel4.h> 18#include <sel4utils/arch/util.h> 19#include <utils/util.h> 20 21#include <vka/object.h> 22 23#include "../test.h" 24#include "../helpers.h" 25 26enum { 27 FAULT_DATA_READ_PAGEFAULT = 1, 28 FAULT_DATA_WRITE_PAGEFAULT = 2, 29 FAULT_INSTRUCTION_PAGEFAULT = 3, 30 FAULT_BAD_SYSCALL = 4, 31 FAULT_BAD_INSTRUCTION = 5, 32}; 33 34enum { 35 BADGED = seL4_WordBits - 1, 36 RESTART = seL4_WordBits - 2, 37}; 38 39/* Use a different test virtual address on 32 and 64-bit systems so that we can exercise 40 the full address space to make sure fault messages are not truncating fault information. */ 41#if CONFIG_WORD_SIZE == 32 42#ifdef CONFIG_ARCH_RISCV32 43#define BAD_VADDR 0x7ffedcba /* 32-bit RISCV userspace */ 44#else 45#define BAD_VADDR 0xf123456C 46#endif 47#elif CONFIG_WORD_SIZE == 64 48#ifdef CONFIG_ARCH_RISCV64 49#define BAD_VADDR 0x3CBA987650 /* Valid Sv39 Virtual Address */ 50#else 51/* virtual address we test is in the valid 48-bit portion of the virtual address space */ 52#define BAD_VADDR 0x7EDCBA987650 53#endif 54#endif 55#define GOOD_MAGIC 0x15831851 56#define BAD_MAGIC ~GOOD_MAGIC 57#define BAD_SYSCALL_NUMBER 0xc1 58 59#define EXPECTED_BADGE 0xabababa 60 61#ifdef CONFIG_ARCH_RISCV 62#if __riscv_xlen == 32 63#define LOAD lw 64#define STORE sw 65#else /* __riscv_xlen == 64 */ 66#define LOAD ld 67#define STORE sd 68#endif 69 70#define LOAD_S STRINGIFY(LOAD) 71#define STORE_S STRINGIFY(STORE) 72#endif 73 74extern char read_fault_address[]; 75extern char read_fault_restart_address[]; 76static void __attribute__((noinline)) 77do_read_fault(void) 78{ 79 int *x = (int *)BAD_VADDR; 80 int val = BAD_MAGIC; 81 /* Do a read fault. */ 82#if defined(CONFIG_ARCH_AARCH32) 83 asm volatile( 84 "mov r0, %[val]\n\t" 85 "read_fault_address:\n\t" 86 "ldr r0, [%[addrreg]]\n\t" 87 "read_fault_restart_address:\n\t" 88 "mov %[val], r0\n\t" 89 : [val] "+r"(val) 90 : [addrreg] "r"(x) 91 : "r0" 92 ); 93#elif defined(CONFIG_ARCH_AARCH64) 94 asm volatile( 95 "mov x0, %[val]\n\t" 96 "read_fault_address:\n\t" 97 "ldr x0, [%[addrreg]]\n\t" 98 "read_fault_restart_address:\n\t" 99 "mov %[val], x0\n\t" 100 : [val] "+r"(val) 101 : [addrreg] "r"(x) 102 : "x0" 103 ); 104#elif defined(CONFIG_ARCH_RISCV) 105 asm volatile( 106 "mv a0, %[val]\n\t" 107 "read_fault_address:\n\t" 108 LOAD_S " a0, 0(%[addrreg])\n\t" 109 "read_fault_restart_address:\n\t" 110 "mv %[val], a0\n\t" 111 : [val] "+r"(val) 112 : [addrreg] "r"(x) 113 : "a0" 114 ); 115#elif defined(CONFIG_ARCH_X86) 116 asm volatile( 117 "mov %[val], %%eax\n\t" 118 "read_fault_address:\n\t" 119 "mov (%[addrreg]), %%eax\n\t" 120 "read_fault_restart_address:\n\t" 121 "mov %%eax, %[val]\n\t" 122 : [val] "+r"(val) 123 : [addrreg] "r"(x) 124 : "eax" 125 ); 126#else 127#error "Unknown architecture." 128#endif 129 test_check(val == GOOD_MAGIC); 130} 131 132extern char write_fault_address[]; 133extern char write_fault_restart_address[]; 134static void __attribute__((noinline)) 135do_write_fault(void) 136{ 137 int *x = (int *)BAD_VADDR; 138 int val = BAD_MAGIC; 139 /* Do a write fault. */ 140#if defined(CONFIG_ARCH_AARCH32) 141 asm volatile( 142 "mov r0, %[val]\n\t" 143 "write_fault_address:\n\t" 144 "str r0, [%[addrreg]]\n\t" 145 "write_fault_restart_address:\n\t" 146 "mov %[val], r0\n\t" 147 : [val] "+r"(val) 148 : [addrreg] "r"(x) 149 : "r0" 150 ); 151#elif defined(CONFIG_ARCH_AARCH64) 152 asm volatile( 153 "mov x0, %[val]\n\t" 154 "write_fault_address:\n\t" 155 "str x0, [%[addrreg]]\n\t" 156 "write_fault_restart_address:\n\t" 157 "mov %[val], x0\n\t" 158 : [val] "+r"(val) 159 : [addrreg] "r"(x) 160 : "x0" 161 ); 162#elif defined(CONFIG_ARCH_RISCV) 163 asm volatile( 164 "mv a0, %[val]\n\t" 165 "write_fault_address:\n\t" 166 STORE_S " a0, 0(%[addrreg])\n\t" 167 "write_fault_restart_address:\n\t" 168 "mv %[val], a0\n\t" 169 : [val] "+r"(val) 170 : [addrreg] "r"(x) 171 : "a0" 172 ); 173#elif defined(CONFIG_ARCH_X86) 174 asm volatile( 175 "mov %[val], %%eax\n\t" 176 "write_fault_address:\n\t" 177 "mov %%eax, (%[addrreg])\n\t" 178 "write_fault_restart_address:\n\t" 179 "mov %%eax, %[val]\n\t" 180 : [val] "+r"(val) 181 : [addrreg] "r"(x) 182 : "eax" 183 ); 184#else 185#error "Unknown architecture." 186#endif 187 test_check(val == GOOD_MAGIC); 188} 189 190extern char instruction_fault_restart_address[]; 191static void __attribute__((noinline)) 192do_instruction_fault(void) 193{ 194 int *x = (int *)BAD_VADDR; 195 int val = BAD_MAGIC; 196 /* Jump to a crazy address. */ 197#if defined(CONFIG_ARCH_AARCH32) 198 asm volatile( 199 "mov r0, %[val]\n\t" 200 "blx %[addrreg]\n\t" 201 "instruction_fault_restart_address:\n\t" 202 "mov %[val], r0\n\t" 203 : [val] "+r"(val) 204 : [addrreg] "r"(x) 205 : "r0", "lr" 206 ); 207#elif defined(CONFIG_ARCH_AARCH64) 208 asm volatile( 209 "mov x0, %[val]\n\t" 210 "blr %[addrreg]\n\t" 211 "instruction_fault_restart_address:\n\t" 212 "mov %[val], x0\n\t" 213 : [val] "+r"(val) 214 : [addrreg] "r"(x) 215 : "x0", "x30" 216 ); 217#elif defined(CONFIG_ARCH_RISCV) 218 asm volatile( 219 "mv a0, %[val]\n\t" 220 "jalr %[addrreg]\n\t" 221 "instruction_fault_restart_address:\n\t" 222 "mv %[val], a0\n\t" 223 : [val] "+r"(val) 224 : [addrreg] "r"(x) 225 : "a0", "ra" 226 ); 227#elif defined(CONFIG_ARCH_X86) 228 asm volatile( 229 "mov %[val], %%eax\n\t" 230 "instruction_fault_address:\n\t" 231 "jmp *%[addrreg]\n\t" 232 "instruction_fault_restart_address:\n\t" 233 "mov %%eax, %[val]\n\t" 234 : [val] "+r"(val) 235 : [addrreg] "r"(x) 236 : "eax" 237 ); 238#else 239#error "Unknown architecture." 240#endif 241 test_check(val == GOOD_MAGIC); 242} 243 244extern char bad_syscall_address[]; 245extern char bad_syscall_restart_address[]; 246static void __attribute__((noinline)) 247do_bad_syscall(void) 248{ 249 int *x = (int *)BAD_VADDR; 250 int val = BAD_MAGIC; 251 /* Do an undefined system call. */ 252#if defined(CONFIG_ARCH_AARCH32) 253 asm volatile( 254 "mov r7, %[scno]\n\t" 255 "mov r0, %[val]\n\t" 256 "bad_syscall_address:\n\t" 257 "svc %[scno]\n\t" 258 "bad_syscall_restart_address:\n\t" 259 "mov %[val], r0\n\t" 260 : [val] "+r"(val) 261 : [addrreg] "r"(x), 262 [scno] "i"(BAD_SYSCALL_NUMBER) 263 : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "memory", "cc" 264 ); 265#elif defined(CONFIG_ARCH_AARCH64) 266 asm volatile( 267 "mov x7, %[scno]\n\t" 268 "mov x0, %[val]\n\t" 269 "bad_syscall_address:\n\t" 270 "svc %[scno]\n\t" 271 "bad_syscall_restart_address:\n\t" 272 "mov %[val], x0\n\t" 273 : [val] "+r"(val) 274 : [addrreg] "r"(x), 275 [scno] "i"(BAD_SYSCALL_NUMBER) 276 : "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "memory", "cc" 277 ); 278#elif defined(CONFIG_ARCH_RISCV) 279 asm volatile( 280 "li a7, %[scno]\n\t" 281 "mv a0, %[val]\n\t" 282 "bad_syscall_address:\n\t" 283 "ecall \n\t" 284 "bad_syscall_restart_address:\n\t" 285 "mv %[val], a0\n\t" 286 : [val] "+r"(val) 287 : [addrreg] "r"(x), 288 [scno] "i"(BAD_SYSCALL_NUMBER) 289 : "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "memory", "cc" 290 ); 291#elif defined(CONFIG_ARCH_X86_64) && defined(CONFIG_SYSENTER) 292 asm volatile( 293 "movl %[val], %%ebx\n\t" 294 "movq %%rsp, %%rcx\n\t" 295 "leaq 1f, %%rdx\n\t" 296 "bad_syscall_address:\n\t" 297 "1: \n\t" 298 "sysenter\n\t" 299 "bad_syscall_restart_address:\n\t" 300 "movl %%ebx, %[val]\n\t" 301 : [val] "+r"(val) 302 : [addrreg] "r"(x), 303 [scno] "a"(BAD_SYSCALL_NUMBER) 304 : "rbx", "rcx", "rdx" 305 ); 306#elif defined(CONFIG_SYSCALL) 307 asm volatile( 308 "movl %[val], %%ebx\n\t" 309 "movq %%rsp, %%r12\n\t" 310 "bad_syscall_address:\n\t" 311 "syscall\n\t" 312 "bad_syscall_restart_address:\n\t" 313 "movq %%r12, %%rsp\n" 314 "movl %%ebx, %[val]\n\t" 315 : [val] "+r"(val) 316 : [addrreg] "r"(x), 317 [scno] "d"(BAD_SYSCALL_NUMBER) 318 : "rax", "rbx", "rcx", "r11", "r12" 319 ); 320#elif defined(CONFIG_ARCH_IA32) 321 asm volatile( 322 "mov %[scno], %%eax\n\t" 323 "mov %[val], %%ebx\n\t" 324 "mov %%esp, %%ecx\n\t" 325 "leal 1f, %%edx\n\t" 326 "bad_syscall_address:\n\t" 327 "1:\n\t" 328 "sysenter\n\t" 329 "bad_syscall_restart_address:\n\t" 330 "mov %%ebx, %[val]\n\t" 331 : [val] "+r"(val) 332 : [addrreg] "r"(x), 333 [scno] "i"(BAD_SYSCALL_NUMBER) 334 : "eax", "ebx", "ecx", "edx" 335 ); 336#else 337#error "Unknown architecture." 338#endif 339 test_check(val == GOOD_MAGIC); 340} 341 342extern char bad_instruction_address[]; 343extern char bad_instruction_restart_address[]; 344static seL4_Word bad_instruction_sp; /* To reset afterwards. */ 345static seL4_Word bad_instruction_cpsr; /* For checking against. */ 346static void __attribute__((noinline)) 347do_bad_instruction(void) 348{ 349 int val = BAD_MAGIC; 350 /* Execute an undefined instruction. */ 351#if defined(CONFIG_ARCH_AARCH32) 352 asm volatile( 353 /* Save SP */ 354 "str sp, [%[sp]]\n\t" 355 356 /* Save CPSR */ 357 "mrs r0, cpsr\n\t" 358 "str r0, [%[cpsr]]\n\t" 359 360 /* Set SP to val. */ 361 "mov sp, %[valptr]\n\t" 362 363 "bad_instruction_address:\n\t" 364 ".word 0xe7f000f0\n\t" /* Guaranteed to be undefined by ARM. */ 365 "bad_instruction_restart_address:\n\t" 366 : 367 : [sp] "r"(&bad_instruction_sp), 368 [cpsr] "r"(&bad_instruction_cpsr), 369 [valptr] "r"(&val) 370 : "r0", "memory" 371 ); 372#elif defined(CONFIG_ARCH_AARCH64) 373 asm volatile( 374 /* Save SP */ 375 "mov x0, sp\n\t" 376 "str x0, [%[sp]]\n\t" 377 378 /* Save PSTATE.nzcv */ 379 "mrs x0, nzcv\n\t" 380 "str x0, [%[cpsr]]\n\t" 381 382 /* Set SP to val. */ 383 "mov sp, %[valptr]\n\t" 384 385 "bad_instruction_address:\n\t" 386 ".word 0xe7f000f0\n\t" /* Guaranteed to be undefined by ARM. */ 387 "bad_instruction_restart_address:\n\t" 388 : 389 : [sp] "r"(&bad_instruction_sp), 390 [cpsr] "r"(&bad_instruction_cpsr), 391 [valptr] "r"(&val) 392 : "x0", "memory" 393 ); 394#elif defined(CONFIG_ARCH_RISCV) 395 asm volatile( 396 /* Save SP */ 397 "mv a0, sp\n\t" 398 STORE_S " a0, 0(%[sp])\n\t" 399 400 /* Set SP to val. */ 401 "mv sp, %[valptr]\n\t" 402 403 "bad_instruction_address:\n\t" 404 ".word 0xffffffff\n\t" 405 "bad_instruction_restart_address:\n\t" 406 : 407 : [sp] "r"(&bad_instruction_sp), 408 [valptr] "r"(&val) 409 : "a0", "memory" 410 ); 411#elif defined(CONFIG_ARCH_X86_64) 412 asm volatile( 413 /* save RSP */ 414 "movq %%rsp, (%[sp])\n\t" 415 "pushf\n\t" 416 "pop %%rax\n\t" 417 "movq %%rax, (%[cpsr])\n\t" 418 "movq %[valptr], %%rsp\n\t" 419 "bad_instruction_address:\n\t" 420 "ud2\n\t" 421 "bad_instruction_restart_address:\n\t" 422 : 423 : [sp] "r"(&bad_instruction_sp), 424 [cpsr] "r"(&bad_instruction_cpsr), 425 [valptr] "r"(&val) 426 : "rax", "memory" 427 ); 428#elif defined(CONFIG_ARCH_IA32) 429 asm volatile( 430 /* Save SP */ 431 "mov %%esp, (%[sp])\n\t" 432 433 /* Save CPSR */ 434 "pushf\n\t" 435 "pop %%eax\n\t" 436 "mov %%eax, (%[cpsr])\n\t" 437 438 /* Set SP to val. */ 439 "mov %[valptr], %%esp\n\t" 440 441 "bad_instruction_address:\n\t" 442 "ud2\n\t" 443 "bad_instruction_restart_address:\n\t" 444 : 445 : [sp] "r"(&bad_instruction_sp), 446 [cpsr] "r"(&bad_instruction_cpsr), 447 [valptr] "r"(&val) 448 : "eax", "memory" 449 ); 450#else 451#error "Unknown architecture." 452#endif 453 test_check(val == GOOD_MAGIC); 454} 455 456static void __attribute__((noinline)) 457set_good_magic_and_set_pc(seL4_CPtr tcb, seL4_Word new_pc) 458{ 459 /* Set their register to GOOD_MAGIC and set PC past fault. */ 460 int error; 461 seL4_UserContext ctx; 462 error = seL4_TCB_ReadRegisters(tcb, 463 false, 464 0, 465 sizeof(ctx) / sizeof(seL4_Word), 466 &ctx); 467 test_check(!error); 468#if defined(CONFIG_ARCH_AARCH32) 469 test_check(ctx.r0 == BAD_MAGIC); 470 ctx.r0 = GOOD_MAGIC; 471 ctx.pc = new_pc; 472#elif defined(CONFIG_ARCH_AARCH64) 473 test_check((int)ctx.x0 == BAD_MAGIC); 474 ctx.x0 = GOOD_MAGIC; 475 ctx.pc = new_pc; 476#elif defined(CONFIG_ARCH_RISCV) 477 test_check((int)ctx.a0 == BAD_MAGIC); 478 ctx.a0 = GOOD_MAGIC; 479 ctx.pc = new_pc; 480#elif defined(CONFIG_ARCH_X86_64) 481 test_check((int)ctx.rax == BAD_MAGIC); 482 ctx.rax = GOOD_MAGIC; 483 ctx.rip = new_pc; 484#elif defined(CONFIG_ARCH_IA32) 485 test_check(ctx.eax == BAD_MAGIC); 486 ctx.eax = GOOD_MAGIC; 487 ctx.eip = new_pc; 488#else 489#error "Unknown architecture." 490#endif 491 error = seL4_TCB_WriteRegisters(tcb, 492 false, 493 0, 494 sizeof(ctx) / sizeof(seL4_Word), 495 &ctx); 496 test_check(!error); 497} 498 499static int handle_fault(seL4_CPtr fault_ep, seL4_CPtr tcb, seL4_Word expected_fault, 500 seL4_Word flags_and_reply) 501{ 502 seL4_MessageInfo_t tag; 503 seL4_Word sender_badge = 0; 504 seL4_CPtr reply = flags_and_reply & MASK(RESTART); 505 bool badged = flags_and_reply & BIT(BADGED); 506 bool restart = flags_and_reply & BIT(RESTART); 507 508 tag = api_recv(fault_ep, &sender_badge, reply); 509 510 if (badged) { 511 test_check(sender_badge == EXPECTED_BADGE); 512 } else { 513 test_check(sender_badge == 0); 514 } 515 516 switch (expected_fault) { 517 case FAULT_DATA_READ_PAGEFAULT: 518 test_check(seL4_MessageInfo_get_label(tag) == seL4_Fault_VMFault); 519 test_check(seL4_MessageInfo_get_length(tag) == seL4_VMFault_Length); 520 test_check(seL4_GetMR(seL4_VMFault_IP) == (seL4_Word)read_fault_address); 521 test_check(seL4_GetMR(seL4_VMFault_Addr) == BAD_VADDR); 522 test_check(seL4_GetMR(seL4_VMFault_PrefetchFault) == 0); 523 test_check(sel4utils_is_read_fault()); 524 525 /* Clear MRs to ensure they get repopulated. */ 526 seL4_SetMR(seL4_VMFault_Addr, 0); 527 528 set_good_magic_and_set_pc(tcb, (seL4_Word)read_fault_restart_address); 529 if (restart) { 530 api_reply(reply, tag); 531 } 532 break; 533 534 case FAULT_DATA_WRITE_PAGEFAULT: 535 test_check(seL4_MessageInfo_get_label(tag) == seL4_Fault_VMFault); 536 test_check(seL4_MessageInfo_get_length(tag) == seL4_VMFault_Length); 537 test_check(seL4_GetMR(seL4_VMFault_IP) == (seL4_Word)write_fault_address); 538 test_check(seL4_GetMR(seL4_VMFault_Addr) == BAD_VADDR); 539 test_check(seL4_GetMR(seL4_VMFault_PrefetchFault) == 0); 540 test_check(!sel4utils_is_read_fault()); 541 542 /* Clear MRs to ensure they get repopulated. */ 543 seL4_SetMR(seL4_VMFault_Addr, 0); 544 545 set_good_magic_and_set_pc(tcb, (seL4_Word)write_fault_restart_address); 546 if (restart) { 547 api_reply(reply, tag); 548 } 549 break; 550 551 case FAULT_INSTRUCTION_PAGEFAULT: 552 test_check(seL4_MessageInfo_get_label(tag) == seL4_Fault_VMFault); 553 test_check(seL4_MessageInfo_get_length(tag) == seL4_VMFault_Length); 554 test_check(seL4_GetMR(seL4_VMFault_IP) == BAD_VADDR); 555 test_check(seL4_GetMR(seL4_VMFault_Addr) == BAD_VADDR); 556#if defined(CONFIG_ARCH_ARM) || defined(CONFIG_ARCH_RISCV) 557 /* Prefetch fault is only set on ARM and RISCV. */ 558 test_check(seL4_GetMR(seL4_VMFault_PrefetchFault) == 1); 559#endif 560 test_check(sel4utils_is_read_fault()); 561 562 /* Clear MRs to ensure they get repopulated. */ 563 seL4_SetMR(seL4_VMFault_Addr, 0); 564 565 set_good_magic_and_set_pc(tcb, (seL4_Word)instruction_fault_restart_address); 566 if (restart) { 567 api_reply(reply, tag); 568 } 569 break; 570 571 case FAULT_BAD_SYSCALL: 572 test_eq(seL4_MessageInfo_get_label(tag), (seL4_Word) seL4_Fault_UnknownSyscall); 573 test_eq(seL4_MessageInfo_get_length(tag), (seL4_Word) seL4_UnknownSyscall_Length); 574 test_eq(seL4_GetMR(seL4_UnknownSyscall_FaultIP), (seL4_Word) bad_syscall_address); 575 test_eq((int)seL4_GetMR(seL4_UnknownSyscall_Syscall), BAD_SYSCALL_NUMBER); 576 seL4_SetMR(seL4_UnknownSyscall_FaultIP, (seL4_Word)bad_syscall_restart_address); 577#if defined(CONFIG_ARCH_AARCH32) 578 test_eq(seL4_GetMR(seL4_UnknownSyscall_R0), BAD_MAGIC); 579 seL4_SetMR(seL4_UnknownSyscall_R0, GOOD_MAGIC); 580#elif defined(CONFIG_ARCH_AARCH64) 581 test_eq((int)seL4_GetMR(seL4_UnknownSyscall_X0), BAD_MAGIC); 582 seL4_SetMR(seL4_UnknownSyscall_X0, GOOD_MAGIC); 583#elif defined(CONFIG_ARCH_X86_64) 584 test_eq((int)seL4_GetMR(seL4_UnknownSyscall_RBX), BAD_MAGIC); 585 test_eq(seL4_GetMR(seL4_UnknownSyscall_FaultIP), (seL4_Word) bad_syscall_restart_address); 586 seL4_SetMR(seL4_UnknownSyscall_RBX, GOOD_MAGIC); 587#elif defined(CONFIG_ARCH_RISCV) 588 test_eq((int)seL4_GetMR(seL4_UnknownSyscall_A0), BAD_MAGIC); 589 test_eq(seL4_GetMR(seL4_UnknownSyscall_FaultIP), (seL4_Word) bad_syscall_restart_address); 590 seL4_SetMR(seL4_UnknownSyscall_A0, GOOD_MAGIC); 591 seL4_SetMR(seL4_UnknownSyscall_FaultIP, (seL4_Word)bad_syscall_restart_address); 592#elif defined(CONFIG_ARCH_IA32) 593 test_eq(seL4_GetMR(seL4_UnknownSyscall_EBX), BAD_MAGIC); 594 seL4_SetMR(seL4_UnknownSyscall_EBX, GOOD_MAGIC); 595 /* Syscalls on ia32 seem to restart themselves with sysenter. */ 596#else 597#error "Unknown architecture." 598#endif 599 600 /* Flag that the thread should be restarted. */ 601 if (restart) { 602 seL4_MessageInfo_ptr_set_label(&tag, 0); 603 } else { 604 seL4_MessageInfo_ptr_set_label(&tag, 1); 605 } 606 api_reply(reply, tag); 607 break; 608 609 case FAULT_BAD_INSTRUCTION: 610 test_check(seL4_MessageInfo_get_label(tag) == seL4_Fault_UserException); 611 test_check(seL4_MessageInfo_get_length(tag) == seL4_UserException_Length); 612 test_check(seL4_GetMR(0) == (seL4_Word)bad_instruction_address); 613 int *valptr = (int *)seL4_GetMR(1); 614 test_check(*valptr == BAD_MAGIC); 615#if defined(CONFIG_ARCH_AARCH32) 616 test_check(seL4_GetMR(2) == bad_instruction_cpsr); 617 test_check(seL4_GetMR(3) == 0); 618 test_check(seL4_GetMR(4) == 0); 619#elif defined(CONFIG_ARCH_AARCH64) 620 /* We only can access PSTATE.nzcv flags in EL0 in aarch64 621 * so, just make sure ther are preserved ... */ 622 test_check((seL4_GetMR(2) & ~MASK(27)) == bad_instruction_cpsr); 623 /* instruction fault on a 32 bit instruction with ISS = 0 */ 624 test_check(seL4_GetMR(3) == 0x02000000); 625 test_check(seL4_GetMR(4) == 0); 626#elif defined(CONFIG_ARCH_RISCV) 627 test_check(seL4_GetMR(2) == 2); 628 test_check(seL4_GetMR(3) == 0); 629#elif defined(CONFIG_ARCH_X86) 630 /* 631 * Curiously, the "resume flag" (bit 16) is set between the 632 * undefined syscall and seL4 grabbing the tasks's flags. This only 633 * happens on x86 hardware, but not qemu. Just ignore it when 634 * checking flags. 635 */ 636 seL4_Word mask_out = ~(1 << 16); 637 test_check(((seL4_GetMR(2) ^ bad_instruction_cpsr) & mask_out) == 0); 638#else 639#error "Unknown architecture." 640#endif 641 642 *valptr = GOOD_MAGIC; 643 seL4_SetMR(0, (seL4_Word)bad_instruction_restart_address); 644 seL4_SetMR(1, bad_instruction_sp); 645 646 /* Flag that the thread should be restarted. */ 647 if (restart) { 648 seL4_MessageInfo_ptr_set_label(&tag, 0); 649 } else { 650 seL4_MessageInfo_ptr_set_label(&tag, 1); 651 } 652 653 api_reply(reply, tag); 654 break; 655 656 default: 657 /* What? Why are we here? What just happened? */ 658 test_assert(0); 659 break; 660 } 661 662 return 0; 663} 664 665static int cause_fault(int fault_type) 666{ 667 switch (fault_type) { 668 case FAULT_DATA_READ_PAGEFAULT: 669 do_read_fault(); 670 break; 671 case FAULT_DATA_WRITE_PAGEFAULT: 672 do_write_fault(); 673 break; 674 case FAULT_INSTRUCTION_PAGEFAULT: 675 do_instruction_fault(); 676 break; 677 case FAULT_BAD_SYSCALL: 678 do_bad_syscall(); 679 break; 680 case FAULT_BAD_INSTRUCTION: 681 do_bad_instruction(); 682 break; 683 } 684 685 return 0; 686} 687 688static int test_fault(env_t env, int fault_type, bool inter_as) 689{ 690 helper_thread_t handler_thread; 691 helper_thread_t faulter_thread; 692 int error; 693 694 vka_object_t reply; 695 error = vka_alloc_reply(&env->vka, &reply); 696 697 for (int restart = 0; restart <= 1; restart++) { 698 for (int prio = 100; prio <= 102; prio++) { 699 for (int badged = 0; badged <= 1; badged++) { 700 seL4_Word handler_arg0, handler_arg1; 701 /* The endpoint on which faults are received. */ 702 seL4_CPtr fault_ep = vka_alloc_endpoint_leaky(&env->vka); 703 if (badged) { 704 seL4_CPtr badged_fault_ep = get_free_slot(env); 705 cnode_mint(env, fault_ep, badged_fault_ep, seL4_AllRights, EXPECTED_BADGE); 706 707 fault_ep = badged_fault_ep; 708 } 709 710 seL4_CPtr faulter_vspace, faulter_cspace, reply_cptr; 711 712 if (inter_as) { 713 create_helper_process(env, &faulter_thread); 714 create_helper_process(env, &handler_thread); 715 716 /* copy the fault endpoint to the faulter */ 717 cspacepath_t path; 718 vka_cspace_make_path(&env->vka, fault_ep, &path); 719 seL4_CPtr remote_fault_ep = sel4utils_copy_path_to_process(&faulter_thread.process, path); 720 assert(remote_fault_ep != -1); 721 722 if (!config_set(CONFIG_KERNEL_MCS)) { 723 fault_ep = remote_fault_ep; 724 } 725 726 /* copy the fault endpoint to the handler */ 727 handler_arg0 = sel4utils_copy_path_to_process(&handler_thread.process, path); 728 assert(handler_arg0 != -1); 729 730 /* copy the fault tcb to the handler */ 731 vka_cspace_make_path(&env->vka, get_helper_tcb(&faulter_thread), &path); 732 handler_arg1 = sel4utils_copy_path_to_process(&handler_thread.process, path); 733 assert(handler_arg1 != -1); 734 735 reply_cptr = sel4utils_copy_cap_to_process(&handler_thread.process, &env->vka, 736 reply.cptr); 737 faulter_cspace = faulter_thread.process.cspace.cptr; 738 faulter_vspace = faulter_thread.process.pd.cptr; 739 } else { 740 create_helper_thread(env, &faulter_thread); 741 create_helper_thread(env, &handler_thread); 742 faulter_cspace = env->cspace_root; 743 faulter_vspace = env->page_directory; 744 handler_arg0 = fault_ep; 745 handler_arg1 = get_helper_tcb(&faulter_thread); 746 reply_cptr = reply.cptr; 747 } 748 749 set_helper_priority(env, &handler_thread, 101); 750 error = api_tcb_set_space(get_helper_tcb(&faulter_thread), 751 fault_ep, 752 faulter_cspace, 753 api_make_guard_skip_word(seL4_WordBits - env->cspace_size_bits), 754 faulter_vspace, seL4_NilData); 755 test_error_eq(error, seL4_NoError); 756 set_helper_priority(env, &faulter_thread, prio); 757 758 // Ensure that the BADGED and RESTART bits are not 759 // already set on the cptr. 760 test_assert(!(reply_cptr & (BIT(RESTART) | BIT(BADGED)))); 761 seL4_Word flags_and_reply = reply_cptr | 762 (badged ? BIT(BADGED) : 0) | 763 (restart ? BIT(RESTART) : 0); 764 765 start_helper(env, &handler_thread, (helper_fn_t) handle_fault, 766 handler_arg0, handler_arg1, fault_type, flags_and_reply); 767 start_helper(env, &faulter_thread, (helper_fn_t) cause_fault, 768 fault_type, 0, 0, 0); 769 wait_for_helper(&handler_thread); 770 771 if (restart) { 772 wait_for_helper(&faulter_thread); 773 } 774 775 cleanup_helper(env, &handler_thread); 776 cleanup_helper(env, &faulter_thread); 777 } 778 } 779 } 780 781 return sel4test_get_result(); 782} 783 784static int test_read_fault(env_t env) 785{ 786 return test_fault(env, FAULT_DATA_READ_PAGEFAULT, false); 787} 788DEFINE_TEST(PAGEFAULT0001, "Test read page fault", test_read_fault, !config_set(CONFIG_FT)) 789 790static int test_write_fault(env_t env) 791{ 792 return test_fault(env, FAULT_DATA_WRITE_PAGEFAULT, false); 793} 794DEFINE_TEST(PAGEFAULT0002, "Test write page fault", test_write_fault, !config_set(CONFIG_FT)) 795 796static int test_execute_fault(env_t env) 797{ 798 return test_fault(env, FAULT_INSTRUCTION_PAGEFAULT, false); 799} 800DEFINE_TEST(PAGEFAULT0003, "Test execute page fault", test_execute_fault, !config_set(CONFIG_FT)) 801 802static int test_bad_syscall(env_t env) 803{ 804 return test_fault(env, FAULT_BAD_SYSCALL, false); 805} 806DEFINE_TEST(PAGEFAULT0004, "Test unknown system call", test_bad_syscall, true) 807 808static int test_bad_instruction(env_t env) 809{ 810 return test_fault(env, FAULT_BAD_INSTRUCTION, false); 811} 812DEFINE_TEST(PAGEFAULT0005, "Test undefined instruction", test_bad_instruction, true) 813 814static int test_read_fault_interas(env_t env) 815{ 816 return test_fault(env, FAULT_DATA_READ_PAGEFAULT, true); 817} 818DEFINE_TEST(PAGEFAULT1001, "Test read page fault (inter-AS)", test_read_fault_interas, true) 819 820static int test_write_fault_interas(env_t env) 821{ 822 return test_fault(env, FAULT_DATA_WRITE_PAGEFAULT, true); 823} 824DEFINE_TEST(PAGEFAULT1002, "Test write page fault (inter-AS)", test_write_fault_interas, true) 825 826static int test_execute_fault_interas(env_t env) 827{ 828 return test_fault(env, FAULT_INSTRUCTION_PAGEFAULT, true); 829} 830DEFINE_TEST(PAGEFAULT1003, "Test execute page fault (inter-AS)", test_execute_fault_interas, true) 831 832static int test_bad_syscall_interas(env_t env) 833{ 834 return test_fault(env, FAULT_BAD_SYSCALL, true); 835} 836DEFINE_TEST(PAGEFAULT1004, "Test unknown system call (inter-AS)", test_bad_syscall_interas, true) 837 838/* This test currently fails. It is disabled until it can be investigated and fixed. */ 839static int test_bad_instruction_interas(env_t env) 840{ 841 return test_fault(env, FAULT_BAD_INSTRUCTION, true); 842} 843DEFINE_TEST(PAGEFAULT1005, "Test undefined instruction (inter-AS)", test_bad_instruction_interas, false) 844 845static void 846timeout_fault_0001_fn(void) 847{ 848 while (1); 849} 850 851int test_timeout_fault(env_t env) 852{ 853 helper_thread_t helper; 854 seL4_Word data = 1; 855 seL4_CPtr endpoint = vka_alloc_endpoint_leaky(&env->vka); 856 seL4_CPtr ro = vka_alloc_reply_leaky(&env->vka); 857 858 create_helper_thread(env, &helper); 859 set_helper_sched_params(env, &helper, US_IN_MS, US_IN_S, data); 860 set_helper_tfep(env, &helper, endpoint); 861 start_helper(env, &helper, (helper_fn_t) timeout_fault_0001_fn, 0, 0, 0, 0); 862 863 /* wait for timeout fault */ 864 UNUSED seL4_MessageInfo_t info = api_recv(endpoint, NULL, ro); 865 for (int i = 0; i < 10; i++) { 866#ifdef CONFIG_KERNEL_MCS 867 test_eq(seL4_MessageInfo_get_length(info), (seL4_Word) seL4_Timeout_Length); 868 test_check(seL4_isTimeoutFault_tag(info)); 869 test_eq(seL4_GetMR(seL4_Timeout_Data), data); 870#endif 871 info = api_reply_recv(endpoint, seL4_MessageInfo_new(0, 0, 0, 0), NULL, ro); 872 } 873 874 return sel4test_get_result(); 875} 876DEFINE_TEST(TIMEOUTFAULT0001, "Test timeout fault", test_timeout_fault, config_set(CONFIG_KERNEL_MCS)) 877 878void 879timeout_fault_server_fn(seL4_CPtr ep, env_t env, seL4_CPtr ro) 880{ 881 /* signal to initialiser that we are done, and wait for a message from 882 * the client */ 883 ZF_LOGD("Server signal recv"); 884 api_nbsend_recv(ep, seL4_MessageInfo_new(0, 0, 0, 0), ep, NULL, ro); 885 /* spin, this will use up all of the clients budget */ 886 while (true); 887 /* we should not get here, as a timeout fault should have been raised 888 * and the handler will reset us */ 889 ZF_LOGF("Should not get here"); 890} 891 892static int timeout_fault_client_fn(seL4_CPtr ep) 893{ 894 seL4_MessageInfo_t info = seL4_MessageInfo_new(0, 0, 0, 0); 895 while (1) { 896 info = seL4_Call(ep, info); 897 /* call should have failed, timeout fault handler will send a -1 */ 898 test_eq(seL4_GetMR(0), (seL4_Word) - 1); 899 } 900 return 0; 901} 902 903int create_passive_thread_with_tfep(env_t env, helper_thread_t *passive, seL4_CPtr tfep, 904 seL4_Word badge, helper_fn_t fn, seL4_CPtr ep, seL4_Word arg1, 905 seL4_Word arg2, seL4_Word arg3, sel4utils_checkpoint_t *cp) 906{ 907 seL4_CPtr minted_tfep = get_free_slot(env); 908 int error = cnode_mint(env, tfep, minted_tfep, seL4_AllRights, badge); 909 test_eq(error, seL4_NoError); 910 911 error = create_passive_thread(env, passive, fn, ep, arg1, arg2, arg3); 912 set_helper_tfep(env, passive, minted_tfep); 913 test_eq(error, 0); 914 915 /* checkpoint */ 916 return sel4utils_checkpoint_thread(&passive->thread, cp, false); 917} 918 919static int handle_timeout_fault(seL4_CPtr tfep, seL4_Word expected_badge, sel4utils_thread_t *server, 920 seL4_CPtr reply, sel4utils_checkpoint_t *cp, seL4_CPtr ep, 921 seL4_Word expected_data, env_t env) 922{ 923 seL4_Word badge; 924 seL4_CPtr server_reply = vka_alloc_reply_leaky(&env->vka); 925 926 /* wait for timeout fault */ 927 ZF_LOGD("Wait for tf"); 928 seL4_MessageInfo_t info = api_recv(tfep, &badge, server_reply); 929 test_eq(badge, expected_badge); 930#ifdef CONFIG_KERNEL_MCS 931 test_check(seL4_isTimeoutFault_tag(info)); 932 test_eq(seL4_GetMR(seL4_Timeout_Data), expected_data); 933 test_eq(seL4_MessageInfo_get_length(info), (seL4_Word) seL4_Timeout_Length); 934#endif 935 /* reply to client on behalf of server */ 936 seL4_SetMR(0, -1); 937 seL4_Send(reply, info); 938 939 size_t stack_size = (uintptr_t) cp->thread->stack_top - cp->sp; 940 memcpy((void *) cp->sp, cp->stack, stack_size); 941 942 /* restore server */ 943 ZF_LOGD("Restoring server"); 944 int error = api_sc_bind(server->sched_context.cptr, server->tcb.cptr); 945 test_eq(error, seL4_NoError); 946 947 ZF_LOGD("Reply to server"); 948#ifdef CONFIG_KERNEL_MCS 949 info = seL4_TimeoutReply_new(true, cp->regs, sizeof(seL4_UserContext) / sizeof(seL4_Word)); 950#endif 951 /* reply, restoring server state, and wait for server to init */ 952 api_reply_recv(ep, info, NULL, server_reply); 953 954 error = api_sc_unbind(server->sched_context.cptr); 955 test_eq(error, seL4_NoError); 956 957 return 0; 958} 959 960static int test_timeout_fault_in_server(env_t env) 961{ 962 helper_thread_t client, server; 963 seL4_Word client_data = 1; 964 seL4_Word server_badge = 2; 965 sel4utils_checkpoint_t cp; 966 967 seL4_CPtr tfep = vka_alloc_endpoint_leaky(&env->vka); 968 seL4_CPtr ep = vka_alloc_endpoint_leaky(&env->vka); 969 seL4_CPtr ro = vka_alloc_reply_leaky(&env->vka); 970 971 /* create the server */ 972 int error = create_passive_thread_with_tfep(env, &server, tfep, server_badge, 973 (helper_fn_t) timeout_fault_server_fn, ep, 974 (seL4_Word)env, ro, 0, &cp); 975 test_eq(error, 0); 976 977 /* create the client */ 978 create_helper_thread(env, &client); 979 set_helper_sched_params(env, &client, 0.1 * US_IN_S, US_IN_S, client_data); 980 start_helper(env, &client, (helper_fn_t) timeout_fault_client_fn, ep, 0, 0, 0); 981 982 /* handle a few faults */ 983 for (int i = 0; i < 5; i++) { 984 ZF_LOGD("Handling fault"); 985 error = handle_timeout_fault(tfep, server_badge, &server.thread, ro, &cp, ep, 986 client_data, env); 987 test_eq(error, 0); 988 } 989 990 return sel4test_get_result(); 991 992} 993DEFINE_TEST(TIMEOUTFAULT0002, "Handle a timeout fault in a server", 994 test_timeout_fault_in_server, config_set(CONFIG_KERNEL_MCS)) 995 996static void 997timeout_fault_proxy_fn(seL4_CPtr in, seL4_CPtr out, seL4_CPtr ro) 998{ 999 seL4_MessageInfo_t info = seL4_MessageInfo_new(0, 0, 0, 1); 1000 info = api_nbsend_recv(in, info, in, NULL, ro); 1001 while (1) { 1002 info = seL4_Call(out, info); 1003 api_reply_recv(in, info, NULL, ro); 1004 } 1005} 1006 1007static int test_timeout_fault_nested_servers(env_t env) 1008{ 1009 helper_thread_t client, server, proxy; 1010 sel4utils_checkpoint_t proxy_cp, server_cp; 1011 1012 seL4_Word client_data = 1; 1013 seL4_Word server_badge = 2; 1014 seL4_Word proxy_badge = 3; 1015 1016 seL4_CPtr client_proxy_ep = vka_alloc_endpoint_leaky(&env->vka); 1017 seL4_CPtr proxy_server_ep = vka_alloc_endpoint_leaky(&env->vka); 1018 seL4_CPtr tfep = vka_alloc_endpoint_leaky(&env->vka); 1019 seL4_CPtr proxy_ro = vka_alloc_reply_leaky(&env->vka); 1020 seL4_CPtr server_ro = vka_alloc_reply_leaky(&env->vka); 1021 1022 /* create server */ 1023 int error = create_passive_thread_with_tfep(env, &server, tfep, server_badge, 1024 (helper_fn_t) timeout_fault_server_fn, proxy_server_ep, 1025 (seL4_Word)env, server_ro, 0, &server_cp); 1026 test_eq(error, 0); 1027 1028 /* create proxy */ 1029 error = create_passive_thread_with_tfep(env, &proxy, tfep, proxy_badge, 1030 (helper_fn_t) timeout_fault_proxy_fn, client_proxy_ep, 1031 proxy_server_ep, proxy_ro, 0, &proxy_cp); 1032 test_eq(error, 0); 1033 1034 /* create client */ 1035 create_helper_thread(env, &client); 1036 1037 error = api_sched_ctrl_configure(simple_get_sched_ctrl(&env->simple, 0), 1038 client.thread.sched_context.cptr, 1039 0.1 * US_IN_S, 0.5 * US_IN_S, 0, client_data); 1040 test_eq(error, 0); 1041 1042 start_helper(env, &client, (helper_fn_t) timeout_fault_client_fn, client_proxy_ep, 0, 0, 0); 1043 1044 /* handle some faults */ 1045 for (int i = 0; i < 5; i++) { 1046 /* server fault */ 1047 ZF_LOGD("server fault\n"); 1048 error = handle_timeout_fault(tfep, server_badge, &server.thread, server_ro, &server_cp, 1049 proxy_server_ep, client_data, env); 1050 test_eq(error, 0); 1051 1052 /* proxy fault */ 1053 ZF_LOGD("proxy fault\n"); 1054 error = handle_timeout_fault(tfep, proxy_badge, &proxy.thread, proxy_ro, &proxy_cp, 1055 client_proxy_ep, client_data, env); 1056 test_eq(error, 0); 1057 } 1058 1059 return sel4test_get_result(); 1060} 1061/* this test is disabled for the same reason as TIMEOUTFAULT0002 */ 1062DEFINE_TEST(TIMEOUTFAULT0003, "Nested timeout fault", test_timeout_fault_nested_servers, config_set(CONFIG_KERNEL_MCS)) 1063 1064static void vm_enter(void) 1065{ 1066#ifdef CONFIG_VTX 1067 seL4_VMEnter(NULL); 1068#endif 1069} 1070 1071static int test_vm_enter_non_vm(env_t env) 1072{ 1073 seL4_Error err; 1074 helper_thread_t helper; 1075 seL4_CPtr fault_ep = vka_alloc_endpoint_leaky(&env->vka); 1076 create_helper_thread(env, &helper); 1077 1078 seL4_Word guard = seL4_WordBits - env->cspace_size_bits; 1079 err = api_tcb_set_space(get_helper_tcb(&helper), fault_ep, env->cspace_root, 1080 api_make_guard_skip_word(guard), 1081 env->page_directory, seL4_NilData); 1082 test_eq(err, 0); 1083 1084 seL4_CPtr reply = vka_alloc_reply_leaky(&env->vka); 1085 start_helper(env, &helper, (helper_fn_t) vm_enter, 0, 0, 0, 0); 1086 seL4_MessageInfo_t tag = api_recv(fault_ep, NULL, reply); 1087 test_eq(seL4_MessageInfo_get_label(tag), (seL4_Word) seL4_Fault_UnknownSyscall); 1088 return sel4test_get_result(); 1089} 1090DEFINE_TEST(UNKNOWN_SYSCALL_001, "Test seL4_VMEnter in a non-vm thread", 1091 test_vm_enter_non_vm, config_set(CONFIG_VTX)); 1092