1 /* 2 * Test the framework itself. These tests confirm that setup works. 3 * 4 * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com> 5 * 6 * This work is licensed under the terms of the GNU LGPL, version 2. 7 */ 8 #include <libcflat.h> 9 #include <util.h> 10 #include <devicetree.h> 11 #include <memregions.h> 12 #include <vmalloc.h> 13 #include <asm/setup.h> 14 #include <asm/ptrace.h> 15 #include <asm/asm-offsets.h> 16 #include <asm/processor.h> 17 #include <asm/thread_info.h> 18 #include <asm/psci.h> 19 #include <asm/smp.h> 20 #include <asm/mmu.h> 21 #include <asm/barrier.h> 22 23 static cpumask_t ready, valid; 24 25 static void __user_psci_system_off(void) 26 { 27 psci_system_off(); 28 halt(); 29 __builtin_unreachable(); 30 } 31 32 static void check_setup(int argc, char **argv) 33 { 34 int nr_tests = 0, len, i; 35 long val; 36 37 for (i = 0; i < argc; ++i) { 38 39 len = parse_keyval(argv[i], &val); 40 if (len == -1) 41 continue; 42 43 argv[i][len] = '\0'; 44 report_prefix_push(argv[i]); 45 46 if (strcmp(argv[i], "mem") == 0) { 47 48 phys_addr_t memsize = PHYS_END - PHYS_OFFSET; 49 phys_addr_t expected = ((phys_addr_t)val)*1024*1024; 50 51 report(memsize == expected, 52 "memory size matches expectation"); 53 report_info("found %" PRIu64 " MB", memsize/1024/1024); 54 ++nr_tests; 55 56 } else if (strcmp(argv[i], "smp") == 0) { 57 58 report(nr_cpus == (int)val, 59 "number of CPUs matches expectation"); 60 report_info("found %d CPUs", nr_cpus); 61 ++nr_tests; 62 } 63 64 report_prefix_pop(); 65 } 66 67 if (nr_tests < 2) 68 report_abort("missing input"); 69 } 70 71 unsigned long check_pabt_invalid_paddr; 72 static bool check_pabt_init(void) 73 { 74 phys_addr_t highest_end = 0; 75 unsigned long vaddr; 76 struct mem_region *r; 77 78 /* 79 * We need a physical address that isn't backed by anything. Without 80 * fully parsing the device tree there's no way to be certain of any 81 * address, but an unknown address immediately following the highest 82 * memory region has a reasonable chance. This is because we can 83 * assume that that memory region could have been larger, if the user 84 * had configured more RAM, and therefore no MMIO region should be 85 * there. 86 */ 87 for (r = mem_regions; r->end; ++r) { 88 if (r->flags & MR_F_IO) 89 continue; 90 if (r->end > highest_end) 91 highest_end = PAGE_ALIGN(r->end); 92 } 93 94 if (memregions_get_flags(highest_end) != MR_F_UNKNOWN) 95 return false; 96 97 vaddr = (unsigned long)vmap(highest_end, PAGE_SIZE); 98 mmu_clear_user(current_thread_info()->pgtable, vaddr); 99 check_pabt_invalid_paddr = vaddr; 100 101 return true; 102 } 103 104 static struct pt_regs expected_regs; 105 static bool und_works; 106 static bool svc_works; 107 static bool pabt_works; 108 #if defined(__arm__) 109 /* 110 * Capture the current register state and execute an instruction 111 * that causes an exception. The test handler will check that its 112 * capture of the current register state matches the capture done 113 * here. 114 */ 115 #define test_exception(pre_insns, excptn_insn, post_insns, clobbers...) \ 116 asm volatile( \ 117 pre_insns "\n" \ 118 "mov r0, %0\n" \ 119 "stmia r0, { r0-lr }\n" \ 120 "mrs r1, cpsr\n" \ 121 "str r1, [r0, #" xstr(S_PSR) "]\n" \ 122 "mov r1, #-1\n" \ 123 "str r1, [r0, #" xstr(S_OLD_R0) "]\n" \ 124 "add r1, pc, #8\n" \ 125 "str r1, [r0, #" xstr(S_R1) "]\n" \ 126 "str r1, [r0, #" xstr(S_PC) "]\n" \ 127 excptn_insn "\n" \ 128 post_insns "\n" \ 129 :: "r" (&expected_regs) : "r0", "r1", ##clobbers) 130 131 static bool check_regs(struct pt_regs *regs) 132 { 133 unsigned i; 134 135 /* exception handlers should always run in svc mode */ 136 if (current_mode() != SVC_MODE) 137 return false; 138 139 for (i = 0; i < ARRAY_SIZE(regs->uregs); ++i) { 140 if (regs->uregs[i] != expected_regs.uregs[i]) 141 return false; 142 } 143 144 return true; 145 } 146 147 static void und_handler(struct pt_regs *regs) 148 { 149 und_works = check_regs(regs); 150 } 151 152 static bool check_und(void) 153 { 154 install_exception_handler(EXCPTN_UND, und_handler); 155 156 /* issue an instruction to a coprocessor we don't have */ 157 test_exception("", "mcr p2, 0, r0, c0, c0", "", "r0"); 158 159 install_exception_handler(EXCPTN_UND, NULL); 160 161 return und_works; 162 } 163 164 static void svc_handler(struct pt_regs *regs) 165 { 166 u32 svc = *(u32 *)(regs->ARM_pc - 4) & 0xffffff; 167 168 if (processor_mode(regs) == SVC_MODE) { 169 /* 170 * When issuing an svc from supervisor mode lr_svc will 171 * get corrupted. So before issuing the svc, callers must 172 * always push it on the stack. We pushed it to offset 4. 173 */ 174 regs->ARM_lr = *(unsigned long *)(regs->ARM_sp + 4); 175 } 176 177 svc_works = check_regs(regs) && svc == 123; 178 } 179 180 static bool check_svc(void) 181 { 182 install_exception_handler(EXCPTN_SVC, svc_handler); 183 184 if (current_mode() == SVC_MODE) { 185 /* 186 * An svc from supervisor mode will corrupt lr_svc and 187 * spsr_svc. We need to save/restore them separately. 188 */ 189 test_exception( 190 "mrs r0, spsr\n" 191 "push { r0,lr }\n", 192 "svc #123\n", 193 "pop { r0,lr }\n" 194 "msr spsr_cxsf, r0\n", 195 "r0", "lr" 196 ); 197 } else { 198 test_exception("", "svc #123", ""); 199 } 200 201 install_exception_handler(EXCPTN_SVC, NULL); 202 203 return svc_works; 204 } 205 206 static void pabt_handler(struct pt_regs *regs) 207 { 208 expected_regs.ARM_lr = expected_regs.ARM_pc; 209 expected_regs.ARM_pc = expected_regs.ARM_r9; 210 211 pabt_works = check_regs(regs); 212 213 regs->ARM_pc = regs->ARM_lr; 214 } 215 216 static bool check_pabt(void) 217 { 218 install_exception_handler(EXCPTN_PABT, pabt_handler); 219 220 test_exception("ldr r9, =check_pabt_invalid_paddr\n" 221 "ldr r9, [r9]\n", 222 "blx r9\n", 223 "", "r9", "lr"); 224 225 install_exception_handler(EXCPTN_PABT, NULL); 226 227 return pabt_works; 228 } 229 230 static void user_psci_system_off(struct pt_regs *regs) 231 { 232 __user_psci_system_off(); 233 } 234 #elif defined(__aarch64__) 235 236 /* 237 * Capture the current register state and execute an instruction 238 * that causes an exception. The test handler will check that its 239 * capture of the current register state matches the capture done 240 * here. 241 */ 242 #define test_exception(pre_insns, excptn_insn, post_insns, clobbers...) \ 243 asm volatile( \ 244 pre_insns "\n" \ 245 "mov x1, %0\n" \ 246 "ldr x0, [x1, #" xstr(S_PSTATE) "]\n" \ 247 "mrs x1, nzcv\n" \ 248 "orr w0, w0, w1\n" \ 249 "mov x1, %0\n" \ 250 "str w0, [x1, #" xstr(S_PSTATE) "]\n" \ 251 "mov x0, sp\n" \ 252 "str x0, [x1, #" xstr(S_SP) "]\n" \ 253 "adr x0, 1f\n" \ 254 "str x0, [x1, #" xstr(S_PC) "]\n" \ 255 "stp x2, x3, [x1, #16]\n" \ 256 "stp x4, x5, [x1, #32]\n" \ 257 "stp x6, x7, [x1, #48]\n" \ 258 "stp x8, x9, [x1, #64]\n" \ 259 "stp x10, x11, [x1, #80]\n" \ 260 "stp x12, x13, [x1, #96]\n" \ 261 "stp x14, x15, [x1, #112]\n" \ 262 "stp x16, x17, [x1, #128]\n" \ 263 "stp x18, x19, [x1, #144]\n" \ 264 "stp x20, x21, [x1, #160]\n" \ 265 "stp x22, x23, [x1, #176]\n" \ 266 "stp x24, x25, [x1, #192]\n" \ 267 "stp x26, x27, [x1, #208]\n" \ 268 "stp x28, x29, [x1, #224]\n" \ 269 "str x30, [x1, #" xstr(S_LR) "]\n" \ 270 "stp x0, x1, [x1]\n" \ 271 "1:" excptn_insn "\n" \ 272 post_insns "\n" \ 273 :: "r" (&expected_regs) : "x0", "x1", ##clobbers) 274 275 static bool check_regs(struct pt_regs *regs) 276 { 277 unsigned i; 278 279 /* exception handlers should always run in EL1 */ 280 if (current_level() != CurrentEL_EL1) 281 return false; 282 283 for (i = 0; i < ARRAY_SIZE(regs->regs); ++i) { 284 if (regs->regs[i] != expected_regs.regs[i]) 285 return false; 286 } 287 288 regs->pstate &= 0xf0000000 /* NZCV */ | 0x3c0 /* DAIF */ 289 | PSR_MODE_MASK; 290 291 return regs->sp == expected_regs.sp 292 && regs->pc == expected_regs.pc 293 && regs->pstate == expected_regs.pstate; 294 } 295 296 static enum vector check_vector_prep(void) 297 { 298 unsigned long daif; 299 300 if (is_user()) 301 return EL0_SYNC_64; 302 303 asm volatile("mrs %0, daif" : "=r" (daif) ::); 304 expected_regs.pstate = daif | PSR_MODE_EL1h; 305 return EL1H_SYNC; 306 } 307 308 static void unknown_handler(struct pt_regs *regs, unsigned int esr __unused) 309 { 310 und_works = check_regs(regs); 311 regs->pc += 4; 312 } 313 314 static bool check_und(void) 315 { 316 enum vector v = check_vector_prep(); 317 318 install_exception_handler(v, ESR_EL1_EC_UNKNOWN, unknown_handler); 319 320 /* try to read an el2 sysreg from el0/1 */ 321 test_exception("", "mrs x0, sctlr_el2", "", "x0"); 322 323 install_exception_handler(v, ESR_EL1_EC_UNKNOWN, NULL); 324 325 return und_works; 326 } 327 328 static void svc_handler(struct pt_regs *regs, unsigned int esr) 329 { 330 u16 svc = esr & 0xffff; 331 332 expected_regs.pc += 4; 333 svc_works = check_regs(regs) && svc == 123; 334 } 335 336 static bool check_svc(void) 337 { 338 enum vector v = check_vector_prep(); 339 340 install_exception_handler(v, ESR_EL1_EC_SVC64, svc_handler); 341 342 test_exception("", "svc #123", ""); 343 344 install_exception_handler(v, ESR_EL1_EC_SVC64, NULL); 345 346 return svc_works; 347 } 348 349 static void pabt_handler(struct pt_regs *regs, unsigned int esr) 350 { 351 bool is_extabt = (esr & ESR_EL1_FSC_MASK) == ESR_EL1_FSC_EXTABT; 352 353 expected_regs.regs[30] = expected_regs.pc + 4; 354 expected_regs.pc = expected_regs.regs[9]; 355 356 pabt_works = check_regs(regs) && is_extabt; 357 358 regs->pc = regs->regs[30]; 359 } 360 361 static bool check_pabt(void) 362 { 363 enum vector v = check_vector_prep(); 364 365 install_exception_handler(v, ESR_EL1_EC_IABT_EL1, pabt_handler); 366 367 test_exception("adrp x9, check_pabt_invalid_paddr\n" 368 "add x9, x9, :lo12:check_pabt_invalid_paddr\n" 369 "ldr x9, [x9]\n", 370 "blr x9\n", 371 "", "x9", "x30"); 372 373 install_exception_handler(v, ESR_EL1_EC_IABT_EL1, NULL); 374 375 return pabt_works; 376 } 377 378 static void user_psci_system_off(struct pt_regs *regs, unsigned int esr) 379 { 380 __user_psci_system_off(); 381 } 382 #endif 383 384 static void check_vectors(void *arg __unused) 385 { 386 report(check_und(), "und"); 387 report(check_svc(), "svc"); 388 if (is_user()) { 389 #ifdef __arm__ 390 install_exception_handler(EXCPTN_UND, user_psci_system_off); 391 #else 392 install_exception_handler(EL0_SYNC_64, ESR_EL1_EC_UNKNOWN, 393 user_psci_system_off); 394 #endif 395 } else { 396 if (!check_pabt_init()) 397 report_skip("Couldn't guess an invalid physical address"); 398 else 399 report(check_pabt(), "pabt"); 400 } 401 exit(report_summary()); 402 } 403 404 static void psci_print(void) 405 { 406 int ver = psci_invoke(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0); 407 report_info("PSCI version: %d.%d", PSCI_VERSION_MAJOR(ver), 408 PSCI_VERSION_MINOR(ver)); 409 report_info("PSCI method: %s", psci_invoke == psci_invoke_hvc ? 410 "hvc" : "smc"); 411 } 412 413 static void cpu_report(void *data __unused) 414 { 415 uint64_t mpidr = get_mpidr(); 416 int cpu = smp_processor_id(); 417 418 if (mpidr_to_cpu(mpidr) == cpu) 419 cpumask_set_cpu(smp_processor_id(), &valid); 420 smp_wmb(); /* Paired with rmb in main(). */ 421 cpumask_set_cpu(smp_processor_id(), &ready); 422 report_info("CPU%3d: MPIDR=%010" PRIx64, cpu, mpidr); 423 } 424 425 int main(int argc, char **argv) 426 { 427 report_prefix_push("selftest"); 428 429 if (argc < 2) 430 report_abort("no test specified"); 431 432 report_prefix_push(argv[1]); 433 434 if (strcmp(argv[1], "setup") == 0) { 435 436 check_setup(argc-2, &argv[2]); 437 438 } else if (strcmp(argv[1], "vectors-kernel") == 0) { 439 440 check_vectors(NULL); 441 442 } else if (strcmp(argv[1], "vectors-user") == 0) { 443 444 start_usr(check_vectors, NULL, 445 (unsigned long)thread_stack_alloc()); 446 447 } else if (strcmp(argv[1], "smp") == 0) { 448 449 psci_print(); 450 on_cpus(cpu_report, NULL); 451 while (!cpumask_full(&ready)) 452 cpu_relax(); 453 smp_rmb(); /* Paired with wmb in cpu_report(). */ 454 report(cpumask_full(&valid), "MPIDR test on all CPUs"); 455 report_info("%d CPUs reported back", nr_cpus); 456 457 } else { 458 printf("Unknown subtest\n"); 459 abort(); 460 } 461 462 return report_summary(); 463 } 464