Message ID | 20201217141400.106137-10-alexandru.elisei@arm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | GIC fixes and improvements | expand |
On 17/12/2020 14:13, Alexandru Elisei wrote: > Testing that an interrupt is received as expected is done in three places: > in check_ipi_sender(), check_irqnr() and check_acked(). check_irqnr() > compares the interrupt ID with IPI_IRQ and records a failure in bad_irq, > and check_ipi_sender() compares the sender with IPI_SENDER and writes to > bad_sender when they don't match. > > Let's move all the checks to check_acked() by renaming > bad_sender->irq_sender and bad_irq->irq_number and changing their semantics > so they record the interrupt sender, respectively the irq number. > check_acked() now takes two new parameters: the expected interrupt number > and sender. > > This has two distinct advantages: > > 1. check_acked() and ipi_handler() can now be used for interrupts other > than IPIs. > 2. Correctness checks are consolidated in one function. > > CC: Andre Przywara <andre.przywara@arm.com> > Reviewed-by: Eric Auger <eric.auger@redhat.com> > Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com> Look all like valid transformations to me, and indeed it's more reusable now: Reviewed-by: Andre Przywara <andre.przywara@arm.com> Cheers, Andre > --- > arm/gic.c | 68 +++++++++++++++++++++++++++---------------------------- > 1 file changed, 33 insertions(+), 35 deletions(-) > > diff --git a/arm/gic.c b/arm/gic.c > index a9ef1a5def56..fb91861900b7 100644 > --- a/arm/gic.c > +++ b/arm/gic.c > @@ -35,7 +35,7 @@ struct gic { > > static struct gic *gic; > static int acked[NR_CPUS], spurious[NR_CPUS]; > -static int bad_sender[NR_CPUS], bad_irq[NR_CPUS]; > +static int irq_sender[NR_CPUS], irq_number[NR_CPUS]; > static cpumask_t ready; > > static void nr_cpu_check(int nr) > @@ -57,8 +57,8 @@ static void stats_reset(void) > > for (i = 0; i < nr_cpus; ++i) { > acked[i] = 0; > - bad_sender[i] = -1; > - bad_irq[i] = -1; > + irq_sender[i] = -1; > + irq_number[i] = -1; > } > } > > @@ -92,9 +92,10 @@ static void wait_for_interrupts(cpumask_t *mask) > report_info("interrupts timed-out (5s)"); > } > > -static bool check_acked(cpumask_t *mask) > +static bool check_acked(cpumask_t *mask, int sender, int irqnum) > { > int missing = 0, extra = 0, unexpected = 0; > + bool has_gicv2 = (gic_version() == 2); > bool pass = true; > int cpu; > > @@ -108,17 +109,19 @@ static bool check_acked(cpumask_t *mask) > if (acked[cpu]) > ++unexpected; > } > + if (!acked[cpu]) > + continue; > smp_rmb(); /* pairs with smp_wmb in ipi_handler */ > > - if (bad_sender[cpu] != -1) { > + if (has_gicv2 && irq_sender[cpu] != sender) { > report_info("cpu%d received IPI from wrong sender %d", > - cpu, bad_sender[cpu]); > + cpu, irq_sender[cpu]); > pass = false; > } > > - if (bad_irq[cpu] != -1) { > + if (irq_number[cpu] != irqnum) { > report_info("cpu%d received wrong irq %d", > - cpu, bad_irq[cpu]); > + cpu, irq_number[cpu]); > pass = false; > } > } > @@ -143,26 +146,18 @@ static void check_spurious(void) > } > } > > -static void check_ipi_sender(u32 irqstat, int sender) > +static int gic_get_sender(int irqstat) > { > - if (gic_version() == 2) { > - int src = (irqstat >> 10) & 7; > - > - if (src != sender) > - bad_sender[smp_processor_id()] = src; > - } > -} > - > -static void check_irqnr(u32 irqnr) > -{ > - if (irqnr != IPI_IRQ) > - bad_irq[smp_processor_id()] = irqnr; > + if (gic_version() == 2) > + return (irqstat >> 10) & 7; > + return -1; > } > > static void ipi_handler(struct pt_regs *regs __unused) > { > u32 irqstat = gic_read_iar(); > u32 irqnr = gic_iar_irqnr(irqstat); > + int this_cpu = smp_processor_id(); > > if (irqnr != GICC_INT_SPURIOUS) { > gic_write_eoir(irqstat); > @@ -173,12 +168,12 @@ static void ipi_handler(struct pt_regs *regs __unused) > */ > if (gic_version() == 2) > smp_rmb(); > - check_ipi_sender(irqstat, IPI_SENDER); > - check_irqnr(irqnr); > + irq_sender[this_cpu] = gic_get_sender(irqstat); > + irq_number[this_cpu] = irqnr; > smp_wmb(); /* pairs with smp_rmb in check_acked */ > - ++acked[smp_processor_id()]; > + ++acked[this_cpu]; > } else { > - ++spurious[smp_processor_id()]; > + ++spurious[this_cpu]; > } > > /* Wait for writes to acked/spurious to complete */ > @@ -314,40 +309,42 @@ static void gicv3_ipi_send_broadcast(void) > > static void ipi_test_self(void) > { > + int this_cpu = smp_processor_id(); > cpumask_t mask; > > report_prefix_push("self"); > stats_reset(); > cpumask_clear(&mask); > - cpumask_set_cpu(smp_processor_id(), &mask); > + cpumask_set_cpu(this_cpu, &mask); > gic->ipi.send_self(); > wait_for_interrupts(&mask); > - report(check_acked(&mask), "Interrupts received"); > + report(check_acked(&mask, this_cpu, IPI_IRQ), "Interrupts received"); > report_prefix_pop(); > } > > static void ipi_test_smp(void) > { > + int this_cpu = smp_processor_id(); > cpumask_t mask; > int i; > > report_prefix_push("target-list"); > stats_reset(); > cpumask_copy(&mask, &cpu_present_mask); > - for (i = smp_processor_id() & 1; i < nr_cpus; i += 2) > + for (i = this_cpu & 1; i < nr_cpus; i += 2) > cpumask_clear_cpu(i, &mask); > gic_ipi_send_mask(IPI_IRQ, &mask); > wait_for_interrupts(&mask); > - report(check_acked(&mask), "Interrupts received"); > + report(check_acked(&mask, this_cpu, IPI_IRQ), "Interrupts received"); > report_prefix_pop(); > > report_prefix_push("broadcast"); > stats_reset(); > cpumask_copy(&mask, &cpu_present_mask); > - cpumask_clear_cpu(smp_processor_id(), &mask); > + cpumask_clear_cpu(this_cpu, &mask); > gic->ipi.send_broadcast(); > wait_for_interrupts(&mask); > - report(check_acked(&mask), "Interrupts received"); > + report(check_acked(&mask, this_cpu, IPI_IRQ), "Interrupts received"); > report_prefix_pop(); > } > > @@ -396,6 +393,7 @@ static void ipi_clear_active_handler(struct pt_regs *regs __unused) > { > u32 irqstat = gic_read_iar(); > u32 irqnr = gic_iar_irqnr(irqstat); > + int this_cpu = smp_processor_id(); > > if (irqnr != GICC_INT_SPURIOUS) { > void *base; > @@ -408,11 +406,11 @@ static void ipi_clear_active_handler(struct pt_regs *regs __unused) > > writel(val, base + GICD_ICACTIVER); > > - check_ipi_sender(irqstat, smp_processor_id()); > - check_irqnr(irqnr); > - ++acked[smp_processor_id()]; > + irq_sender[this_cpu] = gic_get_sender(irqstat); > + irq_number[this_cpu] = irqnr; > + ++acked[this_cpu]; > } else { > - ++spurious[smp_processor_id()]; > + ++spurious[this_cpu]; > } > } > >
diff --git a/arm/gic.c b/arm/gic.c index a9ef1a5def56..fb91861900b7 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -35,7 +35,7 @@ struct gic { static struct gic *gic; static int acked[NR_CPUS], spurious[NR_CPUS]; -static int bad_sender[NR_CPUS], bad_irq[NR_CPUS]; +static int irq_sender[NR_CPUS], irq_number[NR_CPUS]; static cpumask_t ready; static void nr_cpu_check(int nr) @@ -57,8 +57,8 @@ static void stats_reset(void) for (i = 0; i < nr_cpus; ++i) { acked[i] = 0; - bad_sender[i] = -1; - bad_irq[i] = -1; + irq_sender[i] = -1; + irq_number[i] = -1; } } @@ -92,9 +92,10 @@ static void wait_for_interrupts(cpumask_t *mask) report_info("interrupts timed-out (5s)"); } -static bool check_acked(cpumask_t *mask) +static bool check_acked(cpumask_t *mask, int sender, int irqnum) { int missing = 0, extra = 0, unexpected = 0; + bool has_gicv2 = (gic_version() == 2); bool pass = true; int cpu; @@ -108,17 +109,19 @@ static bool check_acked(cpumask_t *mask) if (acked[cpu]) ++unexpected; } + if (!acked[cpu]) + continue; smp_rmb(); /* pairs with smp_wmb in ipi_handler */ - if (bad_sender[cpu] != -1) { + if (has_gicv2 && irq_sender[cpu] != sender) { report_info("cpu%d received IPI from wrong sender %d", - cpu, bad_sender[cpu]); + cpu, irq_sender[cpu]); pass = false; } - if (bad_irq[cpu] != -1) { + if (irq_number[cpu] != irqnum) { report_info("cpu%d received wrong irq %d", - cpu, bad_irq[cpu]); + cpu, irq_number[cpu]); pass = false; } } @@ -143,26 +146,18 @@ static void check_spurious(void) } } -static void check_ipi_sender(u32 irqstat, int sender) +static int gic_get_sender(int irqstat) { - if (gic_version() == 2) { - int src = (irqstat >> 10) & 7; - - if (src != sender) - bad_sender[smp_processor_id()] = src; - } -} - -static void check_irqnr(u32 irqnr) -{ - if (irqnr != IPI_IRQ) - bad_irq[smp_processor_id()] = irqnr; + if (gic_version() == 2) + return (irqstat >> 10) & 7; + return -1; } static void ipi_handler(struct pt_regs *regs __unused) { u32 irqstat = gic_read_iar(); u32 irqnr = gic_iar_irqnr(irqstat); + int this_cpu = smp_processor_id(); if (irqnr != GICC_INT_SPURIOUS) { gic_write_eoir(irqstat); @@ -173,12 +168,12 @@ static void ipi_handler(struct pt_regs *regs __unused) */ if (gic_version() == 2) smp_rmb(); - check_ipi_sender(irqstat, IPI_SENDER); - check_irqnr(irqnr); + irq_sender[this_cpu] = gic_get_sender(irqstat); + irq_number[this_cpu] = irqnr; smp_wmb(); /* pairs with smp_rmb in check_acked */ - ++acked[smp_processor_id()]; + ++acked[this_cpu]; } else { - ++spurious[smp_processor_id()]; + ++spurious[this_cpu]; } /* Wait for writes to acked/spurious to complete */ @@ -314,40 +309,42 @@ static void gicv3_ipi_send_broadcast(void) static void ipi_test_self(void) { + int this_cpu = smp_processor_id(); cpumask_t mask; report_prefix_push("self"); stats_reset(); cpumask_clear(&mask); - cpumask_set_cpu(smp_processor_id(), &mask); + cpumask_set_cpu(this_cpu, &mask); gic->ipi.send_self(); wait_for_interrupts(&mask); - report(check_acked(&mask), "Interrupts received"); + report(check_acked(&mask, this_cpu, IPI_IRQ), "Interrupts received"); report_prefix_pop(); } static void ipi_test_smp(void) { + int this_cpu = smp_processor_id(); cpumask_t mask; int i; report_prefix_push("target-list"); stats_reset(); cpumask_copy(&mask, &cpu_present_mask); - for (i = smp_processor_id() & 1; i < nr_cpus; i += 2) + for (i = this_cpu & 1; i < nr_cpus; i += 2) cpumask_clear_cpu(i, &mask); gic_ipi_send_mask(IPI_IRQ, &mask); wait_for_interrupts(&mask); - report(check_acked(&mask), "Interrupts received"); + report(check_acked(&mask, this_cpu, IPI_IRQ), "Interrupts received"); report_prefix_pop(); report_prefix_push("broadcast"); stats_reset(); cpumask_copy(&mask, &cpu_present_mask); - cpumask_clear_cpu(smp_processor_id(), &mask); + cpumask_clear_cpu(this_cpu, &mask); gic->ipi.send_broadcast(); wait_for_interrupts(&mask); - report(check_acked(&mask), "Interrupts received"); + report(check_acked(&mask, this_cpu, IPI_IRQ), "Interrupts received"); report_prefix_pop(); } @@ -396,6 +393,7 @@ static void ipi_clear_active_handler(struct pt_regs *regs __unused) { u32 irqstat = gic_read_iar(); u32 irqnr = gic_iar_irqnr(irqstat); + int this_cpu = smp_processor_id(); if (irqnr != GICC_INT_SPURIOUS) { void *base; @@ -408,11 +406,11 @@ static void ipi_clear_active_handler(struct pt_regs *regs __unused) writel(val, base + GICD_ICACTIVER); - check_ipi_sender(irqstat, smp_processor_id()); - check_irqnr(irqnr); - ++acked[smp_processor_id()]; + irq_sender[this_cpu] = gic_get_sender(irqstat); + irq_number[this_cpu] = irqnr; + ++acked[this_cpu]; } else { - ++spurious[smp_processor_id()]; + ++spurious[this_cpu]; } }