From patchwork Fri Jan 29 16:36:45 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandru Elisei X-Patchwork-Id: 12056043 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3CCFEC43381 for ; Fri, 29 Jan 2021 16:39:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 12E7964E00 for ; Fri, 29 Jan 2021 16:39:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231374AbhA2Qjv (ORCPT ); Fri, 29 Jan 2021 11:39:51 -0500 Received: from foss.arm.com ([217.140.110.172]:51180 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231715AbhA2QjB (ORCPT ); Fri, 29 Jan 2021 11:39:01 -0500 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 2CA5D15AD; Fri, 29 Jan 2021 08:37:19 -0800 (PST) Received: from monolith.localdoman (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 4F2633F71B; Fri, 29 Jan 2021 08:37:18 -0800 (PST) From: Alexandru Elisei To: drjones@redhat.com, kvm@vger.kernel.org, kvmarm@lists.cs.columbia.edu Cc: andre.przywara@arm.com, Eric Auger Subject: [kvm-unit-tests PATCH v3 09/11] arm/arm64: gic: Make check_acked() more generic Date: Fri, 29 Jan 2021 16:36:45 +0000 Message-Id: <20210129163647.91564-10-alexandru.elisei@arm.com> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20210129163647.91564-1-alexandru.elisei@arm.com> References: <20210129163647.91564-1-alexandru.elisei@arm.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org 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 Reviewed-by: Eric Auger Reviewed-by: Andre Przywara Signed-off-by: Alexandru Elisei --- arm/gic.c | 68 +++++++++++++++++++++++++++---------------------------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/arm/gic.c b/arm/gic.c index 2c96cf49ce8c..af2c112336e7 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -34,7 +34,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) @@ -56,8 +56,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,35 +146,27 @@ 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); - 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 */ @@ -311,40 +306,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(); } @@ -393,6 +390,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; @@ -405,11 +403,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]; } }