On Fri, Jul 20, 2018 at 04:39:40PM +0100, Andre Przywara wrote: > This adds an MMIO subtest to the GIC test. > It accesses some generic GICv2 registers and does some sanity tests, > like checking for some of them being read-only. > > Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx> > --- > arm/gic.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > arm/unittests.cfg | 18 +++++++++++ > lib/arm/asm/gic.h | 4 +++ > 3 files changed, 113 insertions(+) > > diff --git a/arm/gic.c b/arm/gic.c > index 5dd958e..23cb9a4 100644 > --- a/arm/gic.c > +++ b/arm/gic.c > @@ -3,6 +3,7 @@ > * > * GICv2 > * + test sending/receiving IPIs > + * + MMIO access tests > * GICv3 > * + test sending/receiving IPIs > * > @@ -303,6 +304,92 @@ static void run_active_clear_test(void) > report_prefix_pop(); > } > > +static bool test_ro_pattern_32(void *address, u32 pattern, u32 orig) > +{ > + u32 reg; > + > + writel(pattern, address); > + reg = readl(address); > + > + if (reg != orig) > + writel(orig, address); > + > + return reg == orig; > +} > + > +static bool test_readonly_32(void *address, bool razwi) > +{ > + u32 orig, pattern; > + > + orig = readl(address); > + if (razwi && orig) > + return false; > + > + pattern = 0xffffffff; > + if (orig != pattern) { > + if (!test_ro_pattern_32(address, pattern, orig)) > + return false; > + } > + > + pattern = 0xa5a55a5a; > + if (orig != pattern) { > + if (!test_ro_pattern_32(address, pattern, orig)) > + return false; > + } > + > + pattern = 0; > + if (orig != pattern) { > + if (!test_ro_pattern_32(address, pattern, orig)) > + return false; > + } > + > + return true; > +} > + > +static void test_typer_v2(uint32_t reg) > +{ > + int nr_gic_cpus = ((reg >> 5) & 0x7) + 1; > + > + report("all %d CPUs have interrupts", nr_cpus == nr_gic_cpus, > + nr_gic_cpus); > +} > + > +static void gic_test_mmio(void) > +{ > + u32 reg; > + int nr_irqs; > + void *gic_dist_base, *idreg; > + > + switch(gic_version()) { > + case 0x2: > + gic_dist_base = gicv2_dist_base(); > + idreg = gic_dist_base + GICD_ICPIDR2; > + break; > + case 0x3: > + report_abort("GICv3 MMIO tests NYI"); > + default: > + report_abort("GIC version %d not supported", gic_version()); > + } > + > + reg = readl(gic_dist_base + GICD_TYPER); > + nr_irqs = GICD_TYPER_IRQS(reg); > + report_info("number of implemented SPIs: %d", nr_irqs - GIC_FIRST_SPI); > + > + test_typer_v2(reg); > + > + report_info("IIDR: 0x%08x", readl(gic_dist_base + GICD_IIDR)); > + > + report("GICD_TYPER is read-only", > + test_readonly_32(gic_dist_base + GICD_TYPER, false)); > + report("GICD_IIDR is read-only", > + test_readonly_32(gic_dist_base + GICD_IIDR, false)); > + > + reg = readl(idreg); > + report("ICPIDR2 is read-only (0x%08x)", > + test_readonly_32(idreg, false), > + reg); > +} > + > int main(int argc, char **argv) > { > if (!gic_init()) { > @@ -330,6 +417,10 @@ int main(int argc, char **argv) > on_cpus(ipi_test, NULL); > } else if (strcmp(argv[1], "active") == 0) { > run_active_clear_test(); > + } else if (strcmp(argv[1], "mmio") == 0) { > + report_prefix_push(argv[1]); > + gic_test_mmio(); > + report_prefix_pop(); > } else { > report_abort("Unknown subtest '%s'", argv[1]); > } > diff --git a/arm/unittests.cfg b/arm/unittests.cfg > index 44b98cf..7f3a321 100644 > --- a/arm/unittests.cfg > +++ b/arm/unittests.cfg > @@ -86,6 +86,24 @@ smp = $((($MAX_SMP < 8)?$MAX_SMP:8)) > extra_params = -machine gic-version=2 -append 'ipi' > groups = gic > > +[gicv2-mmio] > +file = gic.flat > +smp = $((($MAX_SMP < 8)?$MAX_SMP:8)) > +extra_params = -machine gic-version=2 -append 'mmio' > +groups = gic > + > +[gicv2-mmio-up] > +file = gic.flat > +smp = 1 > +extra_params = -machine gic-version=2 -append 'mmio' > +groups = gic > + > +[gicv2-mmio-3p] > +file = gic.flat > +smp = $((($MAX_SMP < 3)?$MAX_SMP:3)) If MAX_SMP is less than 3, then we'll still run the test with whatever it is, possibly 1, which probably isn't want the test intends. Maybe we should put a if (nr_cpus < 3) { report_skip("host doesn't support guests with at least 3 vcpus"); return report_summary(); } in the test case as well? That said, I'm not overly worried about that ever happening, so we could just fail the test less gracefully in that case by setting 'smp = 3' here in the unittests.cfg file instead. And, that said, I won't worry about this enough for a respin at all, so Reviewed-by: Andrew Jones <drjones@xxxxxxxxxx> Thanks, drew > +extra_params = -machine gic-version=2 -append 'mmio' > +groups = gic > + > [gicv3-ipi] > file = gic.flat > smp = $MAX_SMP > diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h > index 2eb4af8..a469645 100644 > --- a/lib/arm/asm/gic.h > +++ b/lib/arm/asm/gic.h > @@ -6,10 +6,13 @@ > #ifndef _ASMARM_GIC_H_ > #define _ASMARM_GIC_H_ > > +#define GIC_NR_PRIVATE_IRQS 32 > +#define GIC_FIRST_SPI GIC_NR_PRIVATE_IRQS > > /* Distributor registers */ > #define GICD_CTLR 0x0000 > #define GICD_TYPER 0x0004 > +#define GICD_IIDR 0x0008 > #define GICD_IGROUPR 0x0080 > #define GICD_ISENABLER 0x0100 > #define GICD_ISPENDR 0x0200 > @@ -18,6 +21,7 @@ > #define GICD_ICACTIVER 0x0380 > #define GICD_IPRIORITYR 0x0400 > #define GICD_SGIR 0x0f00 > +#define GICD_ICPIDR2 0x0fe8 > > #define GICD_TYPER_IRQS(typer) ((((typer) & 0x1f) + 1) * 32) > #define GICD_INT_EN_SET_SGI 0x0000ffff > -- > 2.14.4 >