xref: /kvm-unit-tests/arm/gic.c (revision 06846df56370af39fb4c9cfd71c032197133929b)
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