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