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