1 /* 2 * GIC tests 3 * 4 * GICv2 5 * + test sending/receiving IPIs 6 * + MMIO access tests 7 * GICv3 8 * + test sending/receiving IPIs 9 * 10 * Copyright (C) 2016, Red Hat Inc, Andrew Jones <drjones@redhat.com> 11 * 12 * This work is licensed under the terms of the GNU LGPL, version 2. 13 */ 14 #include <libcflat.h> 15 #include <asm/setup.h> 16 #include <asm/processor.h> 17 #include <asm/delay.h> 18 #include <asm/gic.h> 19 #include <asm/smp.h> 20 #include <asm/barrier.h> 21 #include <asm/io.h> 22 23 #define IPI_SENDER 1 24 #define IPI_IRQ 1 25 26 struct gic { 27 struct { 28 void (*send_self)(void); 29 void (*send_broadcast)(void); 30 } ipi; 31 }; 32 33 static struct gic *gic; 34 static int acked[NR_CPUS], spurious[NR_CPUS]; 35 static int bad_sender[NR_CPUS], bad_irq[NR_CPUS]; 36 static cpumask_t ready; 37 38 static void nr_cpu_check(int nr) 39 { 40 if (nr_cpus < nr) 41 report_abort("At least %d cpus required", nr); 42 } 43 44 static void wait_on_ready(void) 45 { 46 cpumask_set_cpu(smp_processor_id(), &ready); 47 while (!cpumask_full(&ready)) 48 cpu_relax(); 49 } 50 51 static void stats_reset(void) 52 { 53 int i; 54 55 for (i = 0; i < nr_cpus; ++i) { 56 acked[i] = 0; 57 bad_sender[i] = -1; 58 bad_irq[i] = -1; 59 } 60 smp_wmb(); 61 } 62 63 static void check_acked(cpumask_t *mask) 64 { 65 int missing = 0, extra = 0, unexpected = 0; 66 int nr_pass, cpu, i; 67 bool bad = false; 68 69 /* Wait up to 5s for all interrupts to be delivered */ 70 for (i = 0; i < 50; ++i) { 71 mdelay(100); 72 nr_pass = 0; 73 for_each_present_cpu(cpu) { 74 smp_rmb(); 75 nr_pass += cpumask_test_cpu(cpu, mask) ? 76 acked[cpu] == 1 : acked[cpu] == 0; 77 78 if (bad_sender[cpu] != -1) { 79 printf("cpu%d received IPI from wrong sender %d\n", 80 cpu, bad_sender[cpu]); 81 bad = true; 82 } 83 84 if (bad_irq[cpu] != -1) { 85 printf("cpu%d received wrong irq %d\n", 86 cpu, bad_irq[cpu]); 87 bad = true; 88 } 89 } 90 if (nr_pass == nr_cpus) { 91 report("Completed in %d ms", !bad, ++i * 100); 92 return; 93 } 94 } 95 96 for_each_present_cpu(cpu) { 97 if (cpumask_test_cpu(cpu, mask)) { 98 if (!acked[cpu]) 99 ++missing; 100 else if (acked[cpu] > 1) 101 ++extra; 102 } else { 103 if (acked[cpu]) 104 ++unexpected; 105 } 106 } 107 108 report("Timed-out (5s). ACKS: missing=%d extra=%d unexpected=%d", 109 false, missing, extra, unexpected); 110 } 111 112 static void check_spurious(void) 113 { 114 int cpu; 115 116 smp_rmb(); 117 for_each_present_cpu(cpu) { 118 if (spurious[cpu]) 119 report_info("WARN: cpu%d got %d spurious interrupts", 120 cpu, spurious[cpu]); 121 } 122 } 123 124 static void check_ipi_sender(u32 irqstat) 125 { 126 if (gic_version() == 2) { 127 int src = (irqstat >> 10) & 7; 128 129 if (src != IPI_SENDER) 130 bad_sender[smp_processor_id()] = src; 131 } 132 } 133 134 static void check_irqnr(u32 irqnr) 135 { 136 if (irqnr != IPI_IRQ) 137 bad_irq[smp_processor_id()] = irqnr; 138 } 139 140 static void ipi_handler(struct pt_regs *regs __unused) 141 { 142 u32 irqstat = gic_read_iar(); 143 u32 irqnr = gic_iar_irqnr(irqstat); 144 145 if (irqnr != GICC_INT_SPURIOUS) { 146 gic_write_eoir(irqstat); 147 smp_rmb(); /* pairs with wmb in stats_reset */ 148 ++acked[smp_processor_id()]; 149 check_ipi_sender(irqstat); 150 check_irqnr(irqnr); 151 smp_wmb(); /* pairs with rmb in check_acked */ 152 } else { 153 ++spurious[smp_processor_id()]; 154 smp_wmb(); 155 } 156 } 157 158 static void gicv2_ipi_send_self(void) 159 { 160 writel(2 << 24 | IPI_IRQ, gicv2_dist_base() + GICD_SGIR); 161 } 162 163 static void gicv2_ipi_send_broadcast(void) 164 { 165 writel(1 << 24 | IPI_IRQ, gicv2_dist_base() + GICD_SGIR); 166 } 167 168 static void gicv3_ipi_send_self(void) 169 { 170 gic_ipi_send_single(IPI_IRQ, smp_processor_id()); 171 } 172 173 static void gicv3_ipi_send_broadcast(void) 174 { 175 gicv3_write_sgi1r(1ULL << 40 | IPI_IRQ << 24); 176 isb(); 177 } 178 179 static void ipi_test_self(void) 180 { 181 cpumask_t mask; 182 183 report_prefix_push("self"); 184 stats_reset(); 185 cpumask_clear(&mask); 186 cpumask_set_cpu(smp_processor_id(), &mask); 187 gic->ipi.send_self(); 188 check_acked(&mask); 189 report_prefix_pop(); 190 } 191 192 static void ipi_test_smp(void) 193 { 194 cpumask_t mask; 195 int i; 196 197 report_prefix_push("target-list"); 198 stats_reset(); 199 cpumask_copy(&mask, &cpu_present_mask); 200 for (i = smp_processor_id() & 1; i < nr_cpus; i += 2) 201 cpumask_clear_cpu(i, &mask); 202 gic_ipi_send_mask(IPI_IRQ, &mask); 203 check_acked(&mask); 204 report_prefix_pop(); 205 206 report_prefix_push("broadcast"); 207 stats_reset(); 208 cpumask_copy(&mask, &cpu_present_mask); 209 cpumask_clear_cpu(smp_processor_id(), &mask); 210 gic->ipi.send_broadcast(); 211 check_acked(&mask); 212 report_prefix_pop(); 213 } 214 215 static void ipi_enable(void) 216 { 217 gic_enable_defaults(); 218 #ifdef __arm__ 219 install_exception_handler(EXCPTN_IRQ, ipi_handler); 220 #else 221 install_irq_handler(EL1H_IRQ, ipi_handler); 222 #endif 223 local_irq_enable(); 224 } 225 226 static void ipi_send(void) 227 { 228 ipi_enable(); 229 wait_on_ready(); 230 ipi_test_self(); 231 ipi_test_smp(); 232 check_spurious(); 233 exit(report_summary()); 234 } 235 236 static void ipi_recv(void) 237 { 238 ipi_enable(); 239 cpumask_set_cpu(smp_processor_id(), &ready); 240 while (1) 241 wfi(); 242 } 243 244 static void ipi_test(void *data __unused) 245 { 246 if (smp_processor_id() == IPI_SENDER) 247 ipi_send(); 248 else 249 ipi_recv(); 250 } 251 252 static struct gic gicv2 = { 253 .ipi = { 254 .send_self = gicv2_ipi_send_self, 255 .send_broadcast = gicv2_ipi_send_broadcast, 256 }, 257 }; 258 259 static struct gic gicv3 = { 260 .ipi = { 261 .send_self = gicv3_ipi_send_self, 262 .send_broadcast = gicv3_ipi_send_broadcast, 263 }, 264 }; 265 266 static void ipi_clear_active_handler(struct pt_regs *regs __unused) 267 { 268 u32 irqstat = gic_read_iar(); 269 u32 irqnr = gic_iar_irqnr(irqstat); 270 271 if (irqnr != GICC_INT_SPURIOUS) { 272 void *base; 273 u32 val = 1 << IPI_IRQ; 274 275 if (gic_version() == 2) 276 base = gicv2_dist_base(); 277 else 278 base = gicv3_sgi_base(); 279 280 writel(val, base + GICD_ICACTIVER); 281 282 smp_rmb(); /* pairs with wmb in stats_reset */ 283 ++acked[smp_processor_id()]; 284 check_irqnr(irqnr); 285 smp_wmb(); /* pairs with rmb in check_acked */ 286 } else { 287 ++spurious[smp_processor_id()]; 288 smp_wmb(); 289 } 290 } 291 292 static void run_active_clear_test(void) 293 { 294 report_prefix_push("active"); 295 gic_enable_defaults(); 296 #ifdef __arm__ 297 install_exception_handler(EXCPTN_IRQ, ipi_clear_active_handler); 298 #else 299 install_irq_handler(EL1H_IRQ, ipi_clear_active_handler); 300 #endif 301 local_irq_enable(); 302 303 ipi_test_self(); 304 report_prefix_pop(); 305 } 306 307 static bool test_ro_pattern_32(void *address, u32 pattern, u32 orig) 308 { 309 u32 reg; 310 311 writel(pattern, address); 312 reg = readl(address); 313 314 if (reg != orig) 315 writel(orig, address); 316 317 return reg == orig; 318 } 319 320 static bool test_readonly_32(void *address, bool razwi) 321 { 322 u32 orig, pattern; 323 324 orig = readl(address); 325 if (razwi && orig) 326 return false; 327 328 pattern = 0xffffffff; 329 if (orig != pattern) { 330 if (!test_ro_pattern_32(address, pattern, orig)) 331 return false; 332 } 333 334 pattern = 0xa5a55a5a; 335 if (orig != pattern) { 336 if (!test_ro_pattern_32(address, pattern, orig)) 337 return false; 338 } 339 340 pattern = 0; 341 if (orig != pattern) { 342 if (!test_ro_pattern_32(address, pattern, orig)) 343 return false; 344 } 345 346 return true; 347 } 348 349 static void test_typer_v2(uint32_t reg) 350 { 351 int nr_gic_cpus = ((reg >> 5) & 0x7) + 1; 352 353 report("all %d CPUs have interrupts", nr_cpus == nr_gic_cpus, 354 nr_gic_cpus); 355 } 356 357 #define BYTE(reg32, byte) (((reg32) >> ((byte) * 8)) & 0xff) 358 #define REPLACE_BYTE(reg32, byte, new) (((reg32) & ~(0xff << ((byte) * 8))) |\ 359 ((new) << ((byte) * 8))) 360 361 /* 362 * Some registers are byte accessible, do a byte-wide read and write of known 363 * content to check for this. 364 * Apply a @mask to cater for special register properties. 365 * @pattern contains the value already in the register. 366 */ 367 static void test_byte_access(void *base_addr, u32 pattern, u32 mask) 368 { 369 u32 reg = readb(base_addr + 1); 370 371 report("byte reads successful (0x%08x => 0x%02x)", 372 reg == (BYTE(pattern, 1) & (mask >> 8)), 373 pattern & mask, reg); 374 375 pattern = REPLACE_BYTE(pattern, 2, 0x1f); 376 writeb(BYTE(pattern, 2), base_addr + 2); 377 reg = readl(base_addr); 378 report("byte writes successful (0x%02x => 0x%08x)", 379 reg == (pattern & mask), BYTE(pattern, 2), reg); 380 } 381 382 static void test_priorities(int nr_irqs, void *priptr) 383 { 384 u32 orig_prio, reg, pri_bits; 385 u32 pri_mask, pattern; 386 void *first_spi = priptr + GIC_FIRST_SPI; 387 388 orig_prio = readl(first_spi); 389 report_prefix_push("IPRIORITYR"); 390 391 /* 392 * Determine implemented number of priority bits by writing all 1's 393 * and checking the number of cleared bits in the value read back. 394 */ 395 writel(0xffffffff, first_spi); 396 pri_mask = readl(first_spi); 397 398 reg = ~pri_mask; 399 report("consistent priority masking (0x%08x)", 400 (((reg >> 16) == (reg & 0xffff)) && 401 ((reg & 0xff) == ((reg >> 8) & 0xff))), pri_mask); 402 403 reg = reg & 0xff; 404 for (pri_bits = 8; reg & 1; reg >>= 1, pri_bits--) 405 ; 406 report("implements at least 4 priority bits (%d)", 407 pri_bits >= 4, pri_bits); 408 409 pattern = 0; 410 writel(pattern, first_spi); 411 report("clearing priorities", readl(first_spi) == pattern); 412 413 /* setting all priorities to their max valus was tested above */ 414 415 report("accesses beyond limit RAZ/WI", 416 test_readonly_32(priptr + nr_irqs, true)); 417 418 writel(pattern, priptr + nr_irqs - 4); 419 report("accessing last SPIs", 420 readl(priptr + nr_irqs - 4) == (pattern & pri_mask)); 421 422 pattern = 0xff7fbf3f; 423 writel(pattern, first_spi); 424 report("priorities are preserved", 425 readl(first_spi) == (pattern & pri_mask)); 426 427 /* The PRIORITY registers are byte accessible. */ 428 test_byte_access(first_spi, pattern, pri_mask); 429 430 report_prefix_pop(); 431 writel(orig_prio, first_spi); 432 } 433 434 /* GICD_ITARGETSR is only used by GICv2. */ 435 static void test_targets(int nr_irqs) 436 { 437 void *targetsptr = gicv2_dist_base() + GICD_ITARGETSR; 438 u32 orig_targets; 439 u32 cpu_mask; 440 u32 pattern, reg; 441 442 orig_targets = readl(targetsptr + GIC_FIRST_SPI); 443 report_prefix_push("ITARGETSR"); 444 445 cpu_mask = (1 << nr_cpus) - 1; 446 cpu_mask |= cpu_mask << 8; 447 cpu_mask |= cpu_mask << 16; 448 449 /* Check that bits for non implemented CPUs are RAZ/WI. */ 450 if (nr_cpus < 8) { 451 writel(0xffffffff, targetsptr + GIC_FIRST_SPI); 452 report("bits for %d non-existent CPUs masked", 453 !(readl(targetsptr + GIC_FIRST_SPI) & ~cpu_mask), 454 8 - nr_cpus); 455 } else { 456 report_skip("CPU masking (all CPUs implemented)"); 457 } 458 459 report("accesses beyond limit RAZ/WI", 460 test_readonly_32(targetsptr + nr_irqs, true)); 461 462 pattern = 0x0103020f; 463 writel(pattern, targetsptr + GIC_FIRST_SPI); 464 reg = readl(targetsptr + GIC_FIRST_SPI); 465 report("register content preserved (%08x => %08x)", 466 reg == (pattern & cpu_mask), pattern & cpu_mask, reg); 467 468 /* The TARGETS registers are byte accessible. */ 469 test_byte_access(targetsptr + GIC_FIRST_SPI, pattern, cpu_mask); 470 471 writel(orig_targets, targetsptr + GIC_FIRST_SPI); 472 } 473 474 static void gic_test_mmio(void) 475 { 476 u32 reg; 477 int nr_irqs; 478 void *gic_dist_base, *idreg; 479 480 switch(gic_version()) { 481 case 0x2: 482 gic_dist_base = gicv2_dist_base(); 483 idreg = gic_dist_base + GICD_ICPIDR2; 484 break; 485 case 0x3: 486 report_abort("GICv3 MMIO tests NYI"); 487 default: 488 report_abort("GIC version %d not supported", gic_version()); 489 } 490 491 reg = readl(gic_dist_base + GICD_TYPER); 492 nr_irqs = GICD_TYPER_IRQS(reg); 493 report_info("number of implemented SPIs: %d", nr_irqs - GIC_FIRST_SPI); 494 495 test_typer_v2(reg); 496 497 report_info("IIDR: 0x%08x", readl(gic_dist_base + GICD_IIDR)); 498 499 report("GICD_TYPER is read-only", 500 test_readonly_32(gic_dist_base + GICD_TYPER, false)); 501 report("GICD_IIDR is read-only", 502 test_readonly_32(gic_dist_base + GICD_IIDR, false)); 503 504 reg = readl(idreg); 505 report("ICPIDR2 is read-only (0x%08x)", 506 test_readonly_32(idreg, false), 507 reg); 508 509 test_priorities(nr_irqs, gic_dist_base + GICD_IPRIORITYR); 510 511 if (gic_version() == 2) 512 test_targets(nr_irqs); 513 } 514 515 int main(int argc, char **argv) 516 { 517 if (!gic_init()) { 518 printf("No supported gic present, skipping tests...\n"); 519 return report_summary(); 520 } 521 522 report_prefix_pushf("gicv%d", gic_version()); 523 524 switch (gic_version()) { 525 case 2: 526 gic = &gicv2; 527 break; 528 case 3: 529 gic = &gicv3; 530 break; 531 } 532 533 if (argc < 2) 534 report_abort("no test specified"); 535 536 if (strcmp(argv[1], "ipi") == 0) { 537 report_prefix_push(argv[1]); 538 nr_cpu_check(2); 539 on_cpus(ipi_test, NULL); 540 } else if (strcmp(argv[1], "active") == 0) { 541 run_active_clear_test(); 542 } else if (strcmp(argv[1], "mmio") == 0) { 543 report_prefix_push(argv[1]); 544 gic_test_mmio(); 545 report_prefix_pop(); 546 } else { 547 report_abort("Unknown subtest '%s'", argv[1]); 548 } 549 550 return report_summary(); 551 } 552