From patchwork Fri Nov 8 14:42:24 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 11234977 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id E72991599 for ; Fri, 8 Nov 2019 14:42:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id CFBED222C5 for ; Fri, 8 Nov 2019 14:42:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726977AbfKHOmx (ORCPT ); Fri, 8 Nov 2019 09:42:53 -0500 Received: from foss.arm.com ([217.140.110.172]:44522 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726036AbfKHOmw (ORCPT ); Fri, 8 Nov 2019 09:42:52 -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 D80CD7A7; Fri, 8 Nov 2019 06:42:51 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id BAD8A3F719; Fri, 8 Nov 2019 06:42:50 -0800 (PST) From: Andre Przywara To: Andrew Jones , Paolo Bonzini Cc: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, Marc Zyngier , Alexandru Elisei Subject: [kvm-unit-tests PATCH 01/17] arm: gic: Enable GIC MMIO tests for GICv3 as well Date: Fri, 8 Nov 2019 14:42:24 +0000 Message-Id: <20191108144240.204202-2-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191108144240.204202-1-andre.przywara@arm.com> References: <20191108144240.204202-1-andre.przywara@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org So far the GIC MMIO tests were only enabled for a GICv2 guest. Modern machines tend to have a GICv3-only GIC, so can't run those tests. It turns out that most GIC distributor registers we test in the unit tests are actually the same in GICv3, so we can just enable those tests for GICv3 guests as well. The only exception is the CPU number in the TYPER register, which is only valid in the GICv2 compat mode (ARE=0), which KVM does not support. So we protect this test against running on a GICv3 guest. Signed-off-by: Andre Przywara --- arm/gic.c | 13 +++++++++++-- arm/unittests.cfg | 26 ++++++++++++++++++++++---- lib/arm/asm/gic-v3.h | 2 ++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/arm/gic.c b/arm/gic.c index adb6aa4..04b3337 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -6,6 +6,7 @@ * + MMIO access tests * GICv3 * + test sending/receiving IPIs + * + MMIO access tests * * Copyright (C) 2016, Red Hat Inc, Andrew Jones * @@ -496,7 +497,14 @@ static void gic_test_mmio(void) idreg = gic_dist_base + GICD_ICPIDR2; break; case 0x3: - report_abort("GICv3 MMIO tests NYI"); + /* + * We only test generic registers or those affecting + * SPIs, so don't need to consider the SGI base in + * the redistributor here. + */ + gic_dist_base = gicv3_dist_base(); + idreg = gic_dist_base + GICD_PIDR2; + break; default: report_abort("GIC version %d not supported", gic_version()); } @@ -505,7 +513,8 @@ static void gic_test_mmio(void) nr_irqs = GICD_TYPER_IRQS(reg); report_info("number of implemented SPIs: %d", nr_irqs - GIC_FIRST_SPI); - test_typer_v2(reg); + if (gic_version() == 0x2) + test_typer_v2(reg); report_info("IIDR: 0x%08x", readl(gic_dist_base + GICD_IIDR)); diff --git a/arm/unittests.cfg b/arm/unittests.cfg index daeb5a0..12ac142 100644 --- a/arm/unittests.cfg +++ b/arm/unittests.cfg @@ -86,28 +86,46 @@ smp = $((($MAX_SMP < 8)?$MAX_SMP:8)) extra_params = -machine gic-version=2 -append 'ipi' groups = gic -[gicv2-mmio] +[gicv3-ipi] +file = gic.flat +smp = $MAX_SMP +extra_params = -machine gic-version=3 -append 'ipi' +groups = gic + +[gicv2-max-mmio] file = gic.flat smp = $((($MAX_SMP < 8)?$MAX_SMP:8)) extra_params = -machine gic-version=2 -append 'mmio' groups = gic +[gicv3-max-mmio] +file = gic.flat +smp = $MAX_SMP +extra_params = -machine gic-version=3 -append 'mmio' +groups = gic + [gicv2-mmio-up] file = gic.flat smp = 1 extra_params = -machine gic-version=2 -append 'mmio' groups = gic +[gicv3-mmio-up] +file = gic.flat +smp = 1 +extra_params = -machine gic-version=3 -append 'mmio' +groups = gic + [gicv2-mmio-3p] file = gic.flat smp = $((($MAX_SMP < 3)?$MAX_SMP:3)) extra_params = -machine gic-version=2 -append 'mmio' groups = gic -[gicv3-ipi] +[gicv3-mmio-3p] file = gic.flat -smp = $MAX_SMP -extra_params = -machine gic-version=3 -append 'ipi' +smp = $((($MAX_SMP < 3)?$MAX_SMP:3)) +extra_params = -machine gic-version=2 -append 'mmio' groups = gic [gicv2-active] diff --git a/lib/arm/asm/gic-v3.h b/lib/arm/asm/gic-v3.h index 347be2f..ed6a5ad 100644 --- a/lib/arm/asm/gic-v3.h +++ b/lib/arm/asm/gic-v3.h @@ -23,6 +23,8 @@ #define GICD_CTLR_ENABLE_G1A (1U << 1) #define GICD_CTLR_ENABLE_G1 (1U << 0) +#define GICD_PIDR2 0xffe8 + /* Re-Distributor registers, offsets from RD_base */ #define GICR_TYPER 0x0008 From patchwork Fri Nov 8 14:42:25 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 11234979 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 1F0AB1575 for ; Fri, 8 Nov 2019 14:42:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 0729B222C9 for ; Fri, 8 Nov 2019 14:42:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727296AbfKHOmy (ORCPT ); Fri, 8 Nov 2019 09:42:54 -0500 Received: from foss.arm.com ([217.140.110.172]:44536 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726036AbfKHOmx (ORCPT ); Fri, 8 Nov 2019 09:42:53 -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 35203AB6; Fri, 8 Nov 2019 06:42:53 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 182873F719; Fri, 8 Nov 2019 06:42:51 -0800 (PST) From: Andre Przywara To: Andrew Jones , Paolo Bonzini Cc: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, Marc Zyngier , Alexandru Elisei Subject: [kvm-unit-tests PATCH 02/17] arm: gic: Generalise function names Date: Fri, 8 Nov 2019 14:42:25 +0000 Message-Id: <20191108144240.204202-3-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191108144240.204202-1-andre.przywara@arm.com> References: <20191108144240.204202-1-andre.przywara@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org In preparation for adding functions to test SPI interrupts, generalise some existing functions dealing with IPIs so far, since most of them are actually generic for all kind of interrupts. This also reformats the irq_handler() function, to later expand it more easily. Signed-off-by: Andre Przywara Reviewed-by: Eric Auger --- arm/gic.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/arm/gic.c b/arm/gic.c index 04b3337..a114009 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -135,28 +135,30 @@ static void check_ipi_sender(u32 irqstat) } } -static void check_irqnr(u32 irqnr) +static void check_irqnr(u32 irqnr, int expected) { - if (irqnr != IPI_IRQ) + if (irqnr != expected) bad_irq[smp_processor_id()] = irqnr; } -static void ipi_handler(struct pt_regs *regs __unused) +static void irq_handler(struct pt_regs *regs __unused) { u32 irqstat = gic_read_iar(); u32 irqnr = gic_iar_irqnr(irqstat); - if (irqnr != GICC_INT_SPURIOUS) { - gic_write_eoir(irqstat); - smp_rmb(); /* pairs with wmb in stats_reset */ - ++acked[smp_processor_id()]; - check_ipi_sender(irqstat); - check_irqnr(irqnr); - smp_wmb(); /* pairs with rmb in check_acked */ - } else { + if (irqnr == GICC_INT_SPURIOUS) { ++spurious[smp_processor_id()]; smp_wmb(); + return; } + + gic_write_eoir(irqstat); + + smp_rmb(); /* pairs with wmb in stats_reset */ + ++acked[smp_processor_id()]; + check_ipi_sender(irqstat); + check_irqnr(irqnr, IPI_IRQ); + smp_wmb(); /* pairs with rmb in check_acked */ } static void gicv2_ipi_send_self(void) @@ -216,20 +218,20 @@ static void ipi_test_smp(void) report_prefix_pop(); } -static void ipi_enable(void) +static void irqs_enable(void) { gic_enable_defaults(); #ifdef __arm__ - install_exception_handler(EXCPTN_IRQ, ipi_handler); + install_exception_handler(EXCPTN_IRQ, irq_handler); #else - install_irq_handler(EL1H_IRQ, ipi_handler); + install_irq_handler(EL1H_IRQ, irq_handler); #endif local_irq_enable(); } static void ipi_send(void) { - ipi_enable(); + irqs_enable(); wait_on_ready(); ipi_test_self(); ipi_test_smp(); @@ -237,9 +239,9 @@ static void ipi_send(void) exit(report_summary()); } -static void ipi_recv(void) +static void irq_recv(void) { - ipi_enable(); + irqs_enable(); cpumask_set_cpu(smp_processor_id(), &ready); while (1) wfi(); @@ -250,7 +252,7 @@ static void ipi_test(void *data __unused) if (smp_processor_id() == IPI_SENDER) ipi_send(); else - ipi_recv(); + irq_recv(); } static struct gic gicv2 = { @@ -285,7 +287,7 @@ static void ipi_clear_active_handler(struct pt_regs *regs __unused) smp_rmb(); /* pairs with wmb in stats_reset */ ++acked[smp_processor_id()]; - check_irqnr(irqnr); + check_irqnr(irqnr, IPI_IRQ); smp_wmb(); /* pairs with rmb in check_acked */ } else { ++spurious[smp_processor_id()]; From patchwork Fri Nov 8 14:42:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 11234981 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 8FF151575 for ; Fri, 8 Nov 2019 14:42:56 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 791DF214DB for ; Fri, 8 Nov 2019 14:42:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727903AbfKHOmz (ORCPT ); Fri, 8 Nov 2019 09:42:55 -0500 Received: from foss.arm.com ([217.140.110.172]:44550 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727461AbfKHOmz (ORCPT ); Fri, 8 Nov 2019 09:42:55 -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 86E55CFC; Fri, 8 Nov 2019 06:42:54 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 696023F719; Fri, 8 Nov 2019 06:42:53 -0800 (PST) From: Andre Przywara To: Andrew Jones , Paolo Bonzini Cc: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, Marc Zyngier , Alexandru Elisei Subject: [kvm-unit-tests PATCH 03/17] arm: gic: Provide per-IRQ helper functions Date: Fri, 8 Nov 2019 14:42:26 +0000 Message-Id: <20191108144240.204202-4-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191108144240.204202-1-andre.przywara@arm.com> References: <20191108144240.204202-1-andre.przywara@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org A common theme when accessing per-IRQ parameters in the GIC distributor is to set fields of a certain bit width in a range of MMIO registers. Examples are the enabled status (one bit per IRQ), the level/edge configuration (2 bits per IRQ) or the priority (8 bits per IRQ). Add a generic helper function which is able to mask and set the respective number of bits, given the IRQ number and the MMIO offset. Provide wrappers using this function to easily allow configuring an IRQ. For now assume that private IRQ numbers always refer to the current CPU. In a GICv2 accessing the "other" private IRQs is not easily doable (the registers are banked per CPU on the same MMIO address), so we impose the same limitation on GICv3, even though those registers are not banked there anymore. Signed-off-by: Andre Przywara --- lib/arm/asm/gic-v3.h | 1 + lib/arm/asm/gic.h | 9 +++++ lib/arm/gic.c | 90 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) diff --git a/lib/arm/asm/gic-v3.h b/lib/arm/asm/gic-v3.h index ed6a5ad..8cfaed1 100644 --- a/lib/arm/asm/gic-v3.h +++ b/lib/arm/asm/gic-v3.h @@ -23,6 +23,7 @@ #define GICD_CTLR_ENABLE_G1A (1U << 1) #define GICD_CTLR_ENABLE_G1 (1U << 0) +#define GICD_IROUTER 0x6000 #define GICD_PIDR2 0xffe8 /* Re-Distributor registers, offsets from RD_base */ diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h index 1fc10a0..21cdb58 100644 --- a/lib/arm/asm/gic.h +++ b/lib/arm/asm/gic.h @@ -15,6 +15,7 @@ #define GICD_IIDR 0x0008 #define GICD_IGROUPR 0x0080 #define GICD_ISENABLER 0x0100 +#define GICD_ICENABLER 0x0180 #define GICD_ISPENDR 0x0200 #define GICD_ICPENDR 0x0280 #define GICD_ISACTIVER 0x0300 @@ -73,5 +74,13 @@ extern void gic_write_eoir(u32 irqstat); extern void gic_ipi_send_single(int irq, int cpu); extern void gic_ipi_send_mask(int irq, const cpumask_t *dest); +void gic_set_irq_bit(int irq, int offset); +void gic_enable_irq(int irq); +void gic_disable_irq(int irq); +void gic_set_irq_priority(int irq, u8 prio); +void gic_set_irq_target(int irq, int cpu); +void gic_set_irq_group(int irq, int group); +int gic_get_irq_group(int irq); + #endif /* !__ASSEMBLY__ */ #endif /* _ASMARM_GIC_H_ */ diff --git a/lib/arm/gic.c b/lib/arm/gic.c index 9430116..cf4e811 100644 --- a/lib/arm/gic.c +++ b/lib/arm/gic.c @@ -146,3 +146,93 @@ void gic_ipi_send_mask(int irq, const cpumask_t *dest) assert(gic_common_ops && gic_common_ops->ipi_send_mask); gic_common_ops->ipi_send_mask(irq, dest); } + +enum gic_bit_access { + ACCESS_READ, + ACCESS_SET, + ACCESS_RMW +}; + +static u8 gic_masked_irq_bits(int irq, int offset, int bits, u8 value, + enum gic_bit_access access) +{ + void *base; + int split = 32 / bits; + int shift = (irq % split) * bits; + u32 reg, mask = ((1U << bits) - 1) << shift; + + switch (gic_version()) { + case 2: + base = gicv2_dist_base(); + break; + case 3: + if (irq < 32) + base = gicv3_sgi_base(); + else + base = gicv3_dist_base(); + break; + default: + return 0; + } + base += offset + (irq / split) * 4; + + switch (access) { + case ACCESS_READ: + return (readl(base) & mask) >> shift; + case ACCESS_SET: + reg = 0; + break; + case ACCESS_RMW: + reg = readl(base) & ~mask; + break; + } + + writel(reg | ((u32)value << shift), base); + + return 0; +} + +void gic_set_irq_bit(int irq, int offset) +{ + gic_masked_irq_bits(irq, offset, 1, 1, ACCESS_SET); +} + +void gic_enable_irq(int irq) +{ + gic_set_irq_bit(irq, GICD_ISENABLER); +} + +void gic_disable_irq(int irq) +{ + gic_set_irq_bit(irq, GICD_ICENABLER); +} + +void gic_set_irq_priority(int irq, u8 prio) +{ + gic_masked_irq_bits(irq, GICD_IPRIORITYR, 8, prio, ACCESS_RMW); +} + +void gic_set_irq_target(int irq, int cpu) +{ + if (irq < 32) + return; + + if (gic_version() == 2) { + gic_masked_irq_bits(irq, GICD_ITARGETSR, 8, 1U << cpu, + ACCESS_RMW); + + return; + } + + writeq(cpus[cpu], gicv3_dist_base() + GICD_IROUTER + irq * 8); +} + +void gic_set_irq_group(int irq, int group) +{ + gic_masked_irq_bits(irq, GICD_IGROUPR, 1, group, ACCESS_RMW); +} + +int gic_get_irq_group(int irq) +{ + return gic_masked_irq_bits(irq, GICD_IGROUPR, 1, 0, ACCESS_READ); +} From patchwork Fri Nov 8 14:42:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 11234983 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 295371599 for ; Fri, 8 Nov 2019 14:42:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 07135214DB for ; Fri, 8 Nov 2019 14:42:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728015AbfKHOm4 (ORCPT ); Fri, 8 Nov 2019 09:42:56 -0500 Received: from foss.arm.com ([217.140.110.172]:44560 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727927AbfKHOm4 (ORCPT ); Fri, 8 Nov 2019 09:42:56 -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 D844446A; Fri, 8 Nov 2019 06:42:55 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id BB2813F719; Fri, 8 Nov 2019 06:42:54 -0800 (PST) From: Andre Przywara To: Andrew Jones , Paolo Bonzini Cc: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, Marc Zyngier , Alexandru Elisei Subject: [kvm-unit-tests PATCH 04/17] arm: gic: Support no IRQs test case Date: Fri, 8 Nov 2019 14:42:27 +0000 Message-Id: <20191108144240.204202-5-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191108144240.204202-1-andre.przywara@arm.com> References: <20191108144240.204202-1-andre.przywara@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org For some tests it would be important to check that an IRQ was *not* triggered, for instance to test certain masking operations. Extend the check_added() function to recognise an empty cpumask to detect this situation. The timeout duration is reduced, and the "no IRQs triggered" case is actually reported as a success in this case. Signed-off-by: Andre Przywara --- arm/gic.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/arm/gic.c b/arm/gic.c index a114009..eca9188 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -66,9 +66,10 @@ static void check_acked(const char *testname, cpumask_t *mask) int missing = 0, extra = 0, unexpected = 0; int nr_pass, cpu, i; bool bad = false; + bool noirqs = cpumask_empty(mask); /* Wait up to 5s for all interrupts to be delivered */ - for (i = 0; i < 50; ++i) { + for (i = 0; i < (noirqs ? 15 : 50); ++i) { mdelay(100); nr_pass = 0; for_each_present_cpu(cpu) { @@ -88,7 +89,7 @@ static void check_acked(const char *testname, cpumask_t *mask) bad = true; } } - if (nr_pass == nr_cpus) { + if (!noirqs && nr_pass == nr_cpus) { report("%s", !bad, testname); if (i) report_info("took more than %d ms", i * 100); @@ -96,6 +97,11 @@ static void check_acked(const char *testname, cpumask_t *mask) } } + if (noirqs && nr_pass == nr_cpus) { + report("%s", !bad, testname); + return; + } + for_each_present_cpu(cpu) { if (cpumask_test_cpu(cpu, mask)) { if (!acked[cpu]) From patchwork Fri Nov 8 14:42:28 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 11234985 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 834AB1747 for ; Fri, 8 Nov 2019 14:42:58 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 637C8222CB for ; Fri, 8 Nov 2019 14:42:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727821AbfKHOm5 (ORCPT ); Fri, 8 Nov 2019 09:42:57 -0500 Received: from foss.arm.com ([217.140.110.172]:44578 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728051AbfKHOm5 (ORCPT ); Fri, 8 Nov 2019 09:42:57 -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 35BC7DA7; Fri, 8 Nov 2019 06:42:57 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 187D13F719; Fri, 8 Nov 2019 06:42:55 -0800 (PST) From: Andre Przywara To: Andrew Jones , Paolo Bonzini Cc: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, Marc Zyngier , Alexandru Elisei Subject: [kvm-unit-tests PATCH 05/17] arm: gic: Prepare IRQ handler for handling SPIs Date: Fri, 8 Nov 2019 14:42:28 +0000 Message-Id: <20191108144240.204202-6-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191108144240.204202-1-andre.przywara@arm.com> References: <20191108144240.204202-1-andre.przywara@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org So far our IRQ handler routine checks that the received IRQ is actually the one SGI (IPI) that we are using for our testing. To make the IRQ testing routine more versatile, also allow the IRQ to be one test SPI (shared interrupt). We use the penultimate IRQ of the first SPI group for that purpose. Signed-off-by: Andre Przywara Reviewed-by: Alexandru Elisei --- arm/gic.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/arm/gic.c b/arm/gic.c index eca9188..c909668 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -23,6 +23,7 @@ #define IPI_SENDER 1 #define IPI_IRQ 1 +#define SPI_IRQ (GIC_FIRST_SPI + 30) struct gic { struct { @@ -162,8 +163,12 @@ static void irq_handler(struct pt_regs *regs __unused) smp_rmb(); /* pairs with wmb in stats_reset */ ++acked[smp_processor_id()]; - check_ipi_sender(irqstat); - check_irqnr(irqnr, IPI_IRQ); + if (irqnr < GIC_NR_PRIVATE_IRQS) { + check_ipi_sender(irqstat); + check_irqnr(irqnr, IPI_IRQ); + } else { + check_irqnr(irqnr, SPI_IRQ); + } smp_wmb(); /* pairs with rmb in check_acked */ } From patchwork Fri Nov 8 14:42:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 11234989 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 69C691747 for ; Fri, 8 Nov 2019 14:43:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 526B7222CD for ; Fri, 8 Nov 2019 14:43:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726036AbfKHOnA (ORCPT ); Fri, 8 Nov 2019 09:43:00 -0500 Received: from foss.arm.com ([217.140.110.172]:44596 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727148AbfKHOm7 (ORCPT ); Fri, 8 Nov 2019 09:42:59 -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 870D346A; Fri, 8 Nov 2019 06:42:58 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 6A1ED3F719; Fri, 8 Nov 2019 06:42:57 -0800 (PST) From: Andre Przywara To: Andrew Jones , Paolo Bonzini Cc: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, Marc Zyngier , Alexandru Elisei Subject: [kvm-unit-tests PATCH 06/17] arm: gic: Add simple shared IRQ test Date: Fri, 8 Nov 2019 14:42:29 +0000 Message-Id: <20191108144240.204202-7-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191108144240.204202-1-andre.przywara@arm.com> References: <20191108144240.204202-1-andre.przywara@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org So far we were testing the GIC's MMIO interface and IPI delivery. Add a simple test to trigger a shared IRQ (SPI), using the ISPENDR register in the (emulated) GIC distributor. This tests configuration of an IRQ (target CPU) and whether it can be properly enabled or disabled. This is a bit more sophisticated than actually needed at this time, but paves the way for extending this to FIQs in the future. Signed-off-by: Andre Przywara --- arm/gic.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++ arm/unittests.cfg | 12 +++++++ 2 files changed, 91 insertions(+) diff --git a/arm/gic.c b/arm/gic.c index c909668..3be76cb 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -546,6 +546,81 @@ static void gic_test_mmio(void) test_targets(nr_irqs); } +static void gic_spi_trigger(int irq) +{ + gic_set_irq_bit(irq, GICD_ISPENDR); +} + +static void spi_configure_irq(int irq, int cpu) +{ + gic_set_irq_target(irq, cpu); + gic_set_irq_priority(irq, 0xa0); + gic_enable_irq(irq); +} + +#define IRQ_STAT_NONE 0 +#define IRQ_STAT_IRQ 1 +#define IRQ_STAT_TYPE_MASK 0x3 +#define IRQ_STAT_NO_CLEAR 4 + +/* + * Wait for an SPI to fire (or not) on a certain CPU. + * Clears the pending bit if requested afterwards. + */ +static void trigger_and_check_spi(const char *test_name, + unsigned int irq_stat, + int cpu) +{ + cpumask_t cpumask; + + stats_reset(); + gic_spi_trigger(SPI_IRQ); + cpumask_clear(&cpumask); + switch (irq_stat & IRQ_STAT_TYPE_MASK) { + case IRQ_STAT_NONE: + break; + case IRQ_STAT_IRQ: + cpumask_set_cpu(cpu, &cpumask); + break; + } + + check_acked(test_name, &cpumask); + + /* Clean up pending bit in case this IRQ wasn't taken. */ + if (!(irq_stat & IRQ_STAT_NO_CLEAR)) + gic_set_irq_bit(SPI_IRQ, GICD_ICPENDR); +} + +static void spi_test_single(void) +{ + cpumask_t cpumask; + int cpu = smp_processor_id(); + + spi_configure_irq(SPI_IRQ, cpu); + + trigger_and_check_spi("SPI triggered by CPU write", IRQ_STAT_IRQ, cpu); + + gic_disable_irq(SPI_IRQ); + trigger_and_check_spi("disabled SPI does not fire", + IRQ_STAT_NONE | IRQ_STAT_NO_CLEAR, cpu); + + stats_reset(); + cpumask_clear(&cpumask); + cpumask_set_cpu(cpu, &cpumask); + gic_enable_irq(SPI_IRQ); + check_acked("now enabled SPI fires", &cpumask); +} + +static void spi_send(void) +{ + irqs_enable(); + + spi_test_single(); + + check_spurious(); + exit(report_summary()); +} + int main(int argc, char **argv) { if (!gic_init()) { @@ -577,6 +652,10 @@ int main(int argc, char **argv) report_prefix_push(argv[1]); gic_test_mmio(); report_prefix_pop(); + } else if (strcmp(argv[1], "irq") == 0) { + report_prefix_push(argv[1]); + spi_send(); + report_prefix_pop(); } else { report_abort("Unknown subtest '%s'", argv[1]); } diff --git a/arm/unittests.cfg b/arm/unittests.cfg index 12ac142..7a78275 100644 --- a/arm/unittests.cfg +++ b/arm/unittests.cfg @@ -92,6 +92,18 @@ smp = $MAX_SMP extra_params = -machine gic-version=3 -append 'ipi' groups = gic +[gicv2-spi] +file = gic.flat +smp = $((($MAX_SMP < 8)?$MAX_SMP:8)) +extra_params = -machine gic-version=2 -append 'irq' +groups = gic + +[gicv3-spi] +file = gic.flat +smp = $MAX_SMP +extra_params = -machine gic-version=3 -append 'irq' +groups = gic + [gicv2-max-mmio] file = gic.flat smp = $((($MAX_SMP < 8)?$MAX_SMP:8)) From patchwork Fri Nov 8 14:42:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 11234991 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 40B151575 for ; Fri, 8 Nov 2019 14:43:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 29A952245A for ; Fri, 8 Nov 2019 14:43:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728253AbfKHOnA (ORCPT ); Fri, 8 Nov 2019 09:43:00 -0500 Received: from foss.arm.com ([217.140.110.172]:44606 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727148AbfKHOnA (ORCPT ); Fri, 8 Nov 2019 09:43:00 -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 D84807A7; Fri, 8 Nov 2019 06:42:59 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id BB5E13F719; Fri, 8 Nov 2019 06:42:58 -0800 (PST) From: Andre Przywara To: Andrew Jones , Paolo Bonzini Cc: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, Marc Zyngier , Alexandru Elisei Subject: [kvm-unit-tests PATCH 07/17] arm: gic: Extend check_acked() to allow silent call Date: Fri, 8 Nov 2019 14:42:30 +0000 Message-Id: <20191108144240.204202-8-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191108144240.204202-1-andre.przywara@arm.com> References: <20191108144240.204202-1-andre.przywara@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org For future tests we will need to call check_acked() twice for the same interrupt (to test delivery of Group 0 and Group 1 interrupts). This should be reported as a single test, so allow check_acked() to be called with a "NULL" test name, to suppress output. We report the test result via the return value, so the outcome is not lost. Also this amends the new trigger_and_check_spi() wrapper, to propagate the test result to callers of that function. Signed-off-by: Andre Przywara --- arm/gic.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/arm/gic.c b/arm/gic.c index 3be76cb..63aa9f4 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -62,7 +62,7 @@ static void stats_reset(void) smp_wmb(); } -static void check_acked(const char *testname, cpumask_t *mask) +static int check_acked(const char *testname, cpumask_t *mask) { int missing = 0, extra = 0, unexpected = 0; int nr_pass, cpu, i; @@ -91,16 +91,20 @@ static void check_acked(const char *testname, cpumask_t *mask) } } if (!noirqs && nr_pass == nr_cpus) { - report("%s", !bad, testname); - if (i) - report_info("took more than %d ms", i * 100); - return; + if (testname) { + report("%s", !bad, testname); + if (i) + report_info("took more than %d ms", + i * 100); + } + return i * 100; } } if (noirqs && nr_pass == nr_cpus) { - report("%s", !bad, testname); - return; + if (testname) + report("%s", !bad, testname); + return i * 100; } for_each_present_cpu(cpu) { @@ -115,9 +119,11 @@ static void check_acked(const char *testname, cpumask_t *mask) } } - report("%s", false, testname); + if (testname) + report("%s", false, testname); report_info("Timed-out (5s). ACKS: missing=%d extra=%d unexpected=%d", missing, extra, unexpected); + return -1; } static void check_spurious(void) @@ -567,11 +573,12 @@ static void spi_configure_irq(int irq, int cpu) * Wait for an SPI to fire (or not) on a certain CPU. * Clears the pending bit if requested afterwards. */ -static void trigger_and_check_spi(const char *test_name, +static bool trigger_and_check_spi(const char *test_name, unsigned int irq_stat, int cpu) { cpumask_t cpumask; + bool ret = true; stats_reset(); gic_spi_trigger(SPI_IRQ); @@ -584,11 +591,13 @@ static void trigger_and_check_spi(const char *test_name, break; } - check_acked(test_name, &cpumask); + ret = (check_acked(test_name, &cpumask) >= 0); /* Clean up pending bit in case this IRQ wasn't taken. */ if (!(irq_stat & IRQ_STAT_NO_CLEAR)) gic_set_irq_bit(SPI_IRQ, GICD_ICPENDR); + + return ret; } static void spi_test_single(void) From patchwork Fri Nov 8 14:42:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 11234993 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 12D1A1575 for ; Fri, 8 Nov 2019 14:43:03 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E3BF2222CE for ; Fri, 8 Nov 2019 14:43:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726200AbfKHOnC (ORCPT ); Fri, 8 Nov 2019 09:43:02 -0500 Received: from foss.arm.com ([217.140.110.172]:44618 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727024AbfKHOnB (ORCPT ); Fri, 8 Nov 2019 09:43: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 35E5446A; Fri, 8 Nov 2019 06:43:01 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 18ADD3F719; Fri, 8 Nov 2019 06:42:59 -0800 (PST) From: Andre Przywara To: Andrew Jones , Paolo Bonzini Cc: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, Marc Zyngier , Alexandru Elisei Subject: [kvm-unit-tests PATCH 08/17] arm: gic: Add simple SPI MP test Date: Fri, 8 Nov 2019 14:42:31 +0000 Message-Id: <20191108144240.204202-9-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191108144240.204202-1-andre.przywara@arm.com> References: <20191108144240.204202-1-andre.przywara@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Shared Peripheral Interrupts (SPI) can target a specific CPU. Test this feature by routing the test SPI to each of the vCPUs, then triggering it and confirm its reception on that requested core. Signed-off-by: Andre Przywara --- arm/gic.c | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/arm/gic.c b/arm/gic.c index 63aa9f4..304b7b9 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -620,16 +620,45 @@ static void spi_test_single(void) check_acked("now enabled SPI fires", &cpumask); } +static void spi_test_smp(void) +{ + int cpu; + int cores = 1; + + wait_on_ready(); + for_each_present_cpu(cpu) { + if (cpu == smp_processor_id()) + continue; + spi_configure_irq(SPI_IRQ, cpu); + if (trigger_and_check_spi(NULL, IRQ_STAT_IRQ, cpu)) + cores++; + else + report_info("SPI delivery failed on core %d", cpu); + } + report("SPI delievered on all cores", cores == nr_cpus); +} + static void spi_send(void) { irqs_enable(); spi_test_single(); + if (nr_cpus > 1) + spi_test_smp(); + check_spurious(); exit(report_summary()); } +static void spi_test(void *data __unused) +{ + if (smp_processor_id() == 0) + spi_send(); + else + irq_recv(); +} + int main(int argc, char **argv) { if (!gic_init()) { @@ -663,7 +692,7 @@ int main(int argc, char **argv) report_prefix_pop(); } else if (strcmp(argv[1], "irq") == 0) { report_prefix_push(argv[1]); - spi_send(); + on_cpus(spi_test, NULL); report_prefix_pop(); } else { report_abort("Unknown subtest '%s'", argv[1]); From patchwork Fri Nov 8 14:42:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 11234995 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id BC8C51599 for ; Fri, 8 Nov 2019 14:43:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A565D222CF for ; Fri, 8 Nov 2019 14:43:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728149AbfKHOnD (ORCPT ); Fri, 8 Nov 2019 09:43:03 -0500 Received: from foss.arm.com ([217.140.110.172]:44632 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727024AbfKHOnD (ORCPT ); Fri, 8 Nov 2019 09:43:03 -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 88B927A7; Fri, 8 Nov 2019 06:43:02 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 6A5A73F719; Fri, 8 Nov 2019 06:43:01 -0800 (PST) From: Andre Przywara To: Andrew Jones , Paolo Bonzini Cc: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, Marc Zyngier , Alexandru Elisei Subject: [kvm-unit-tests PATCH 09/17] arm: gic: Add test for flipping GICD_CTLR.DS Date: Fri, 8 Nov 2019 14:42:32 +0000 Message-Id: <20191108144240.204202-10-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191108144240.204202-1-andre.przywara@arm.com> References: <20191108144240.204202-1-andre.przywara@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org The DS (Disable Security) bit in the GICv3 GICD_CTLR register controls access to Group 0 interrupts from the non-secure side. The KVM VGIC emulation provides a "GIC with a single security state", so both groups should be accessible. Provide a test to check this bit can be set to one. The current KVM emulation should treat this is as RAO/WI (which we also check here). It would be architecturally compliant though to have this bit at 0 as well, so we refrain from treating different behaviour as a FAIL. However we use this as a gateway for further Group 0 IRQ tests. Signed-off-by: Andre Przywara --- arm/gic.c | 62 ++++++++++++++++++++++++++++++++++++++++++++ lib/arm/asm/gic-v3.h | 1 + 2 files changed, 63 insertions(+) diff --git a/arm/gic.c b/arm/gic.c index 304b7b9..c882a24 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -531,6 +531,8 @@ static void gic_test_mmio(void) 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); + report_info("GIC %s security extension", + reg & (1U << 10) ? "has" : "does not have"); if (gic_version() == 0x2) test_typer_v2(reg); @@ -638,6 +640,60 @@ static void spi_test_smp(void) report("SPI delievered on all cores", cores == nr_cpus); } +/* + * Check the security state configuration of the GIC. + * Test whether we can switch to a single security state, to test both + * group 0 and group 1 interrupts. + * Architecturally a GIC can be configured in different ways, so we don't + * insist on the current way KVM emulates the GIC. + */ +static bool gicv3_check_security(void *gicd_base) +{ + u32 ctlr = readl(gicd_base + GICD_CTLR); + + if (ctlr & GICD_CTLR_DS) { + writel(ctlr & ~GICD_CTLR_DS, gicd_base + GICD_CTLR); + ctlr = readl(gicd_base + GICD_CTLR); + if (!(ctlr & GICD_CTLR_DS)) + report_info("GIC allowing two security states"); + else + report_info("GIC is one security state only"); + } else { + report_info("GIC resets to two security states"); + } + + writel(ctlr | GICD_CTLR_DS, gicd_base + GICD_CTLR); + ctlr = readl(gicd_base + GICD_CTLR); + report("switching to single security state", ctlr & GICD_CTLR_DS); + + /* Group0 delivery only works in single security state. */ + return ctlr & GICD_CTLR_DS; +} + +/* + * The GIC architecture describes two interrupt groups, group 0 and group 1. + * On bare-metal systems, running in non-secure world on a GIC with the + * security extensions, there is only one group available: group 1. + * However in the kernel KVM emulates a GIC with only one security state, + * so both groups are available to guests. + * Check whether this works as expected (as Linux will not use this feature). + * We can only verify this state on a GICv3, so we check it there and silently + * assume it's valid for GICv2. + */ +static void test_irq_group(void *gicd_base) +{ + bool is_gicv3 = (gic_version() == 3); + + report_prefix_push("GROUP"); + gic_enable_defaults(); + + if (is_gicv3) { + /* GICv3 features a bit to read and set the security state. */ + if (!gicv3_check_security(gicd_base)) + return; + } +} + static void spi_send(void) { irqs_enable(); @@ -647,6 +703,12 @@ static void spi_send(void) if (nr_cpus > 1) spi_test_smp(); + if (gic_version() == 3) + test_irq_group(gicv3_dist_base()); + + if (gic_version() == 2) + test_irq_group(gicv2_dist_base()); + check_spurious(); exit(report_summary()); } diff --git a/lib/arm/asm/gic-v3.h b/lib/arm/asm/gic-v3.h index 8cfaed1..2eaf944 100644 --- a/lib/arm/asm/gic-v3.h +++ b/lib/arm/asm/gic-v3.h @@ -19,6 +19,7 @@ * group1 enable bits with respect to that view. */ #define GICD_CTLR_RWP (1U << 31) +#define GICD_CTLR_DS (1U << 6) #define GICD_CTLR_ARE_NS (1U << 4) #define GICD_CTLR_ENABLE_G1A (1U << 1) #define GICD_CTLR_ENABLE_G1 (1U << 0) From patchwork Fri Nov 8 14:42:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 11234997 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C52EB1599 for ; Fri, 8 Nov 2019 14:43:05 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id A4A022245A for ; Fri, 8 Nov 2019 14:43:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728691AbfKHOnE (ORCPT ); Fri, 8 Nov 2019 09:43:04 -0500 Received: from foss.arm.com ([217.140.110.172]:44644 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727673AbfKHOnE (ORCPT ); Fri, 8 Nov 2019 09:43:04 -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 DA65346A; Fri, 8 Nov 2019 06:43:03 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id BD1F73F719; Fri, 8 Nov 2019 06:43:02 -0800 (PST) From: Andre Przywara To: Andrew Jones , Paolo Bonzini Cc: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, Marc Zyngier , Alexandru Elisei Subject: [kvm-unit-tests PATCH 10/17] arm: gic: Check for writable IGROUPR registers Date: Fri, 8 Nov 2019 14:42:33 +0000 Message-Id: <20191108144240.204202-11-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191108144240.204202-1-andre.przywara@arm.com> References: <20191108144240.204202-1-andre.przywara@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org When both groups are avaiable to the non-secure side, the MMIO group registers need to be writable, so that the group that an IRQ belongs to can be programmed. Check that the group can be flipped, after having established that both groups are usable. Signed-off-by: Andre Przywara --- arm/gic.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arm/gic.c b/arm/gic.c index c882a24..485ca4f 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -683,6 +683,7 @@ static bool gicv3_check_security(void *gicd_base) static void test_irq_group(void *gicd_base) { bool is_gicv3 = (gic_version() == 3); + u32 reg; report_prefix_push("GROUP"); gic_enable_defaults(); @@ -692,6 +693,16 @@ static void test_irq_group(void *gicd_base) if (!gicv3_check_security(gicd_base)) return; } + + /* + * On a security aware GIC in non-secure world the IGROUPR registers + * are RAZ/WI. KVM emulates a single-security-state GIC, so both + * groups are available and the IGROUPR registers are writable. + */ + reg = gic_get_irq_group(SPI_IRQ); + gic_set_irq_group(SPI_IRQ, !reg); + report("IGROUPR is writable", gic_get_irq_group(SPI_IRQ) != reg); + gic_set_irq_group(SPI_IRQ, reg); } static void spi_send(void) From patchwork Fri Nov 8 14:42:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 11234999 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 05CE71575 for ; Fri, 8 Nov 2019 14:43:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id E3762222C9 for ; Fri, 8 Nov 2019 14:43:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728266AbfKHOnG (ORCPT ); Fri, 8 Nov 2019 09:43:06 -0500 Received: from foss.arm.com ([217.140.110.172]:44662 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727148AbfKHOnF (ORCPT ); Fri, 8 Nov 2019 09:43:05 -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 378267A7; Fri, 8 Nov 2019 06:43:05 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 1A6AF3F719; Fri, 8 Nov 2019 06:43:03 -0800 (PST) From: Andre Przywara To: Andrew Jones , Paolo Bonzini Cc: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, Marc Zyngier , Alexandru Elisei Subject: [kvm-unit-tests PATCH 11/17] arm: gic: Check for validity of both group enable bits Date: Fri, 8 Nov 2019 14:42:34 +0000 Message-Id: <20191108144240.204202-12-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191108144240.204202-1-andre.przywara@arm.com> References: <20191108144240.204202-1-andre.przywara@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org The GIC distributor actually supports *two* enable bits, one per interrupt group. Linux itself won't care and will only ever use one bit. In a VM however we have two groups available, so we should be able to flip the two separate enable bits. Provide tests that try to flip the two available bits and check whether they stick. Signed-off-by: Andre Przywara --- arm/gic.c | 21 +++++++++++++++++++++ lib/arm/asm/gic-v3.h | 4 ++-- lib/arm/gic-v3.c | 2 +- 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/arm/gic.c b/arm/gic.c index 485ca4f..a0511e5 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -640,6 +640,8 @@ static void spi_test_smp(void) report("SPI delievered on all cores", cores == nr_cpus); } +#define GICD_CTLR_ENABLE_BOTH (GICD_CTLR_ENABLE_G0 | GICD_CTLR_ENABLE_G1) + /* * Check the security state configuration of the GIC. * Test whether we can switch to a single security state, to test both @@ -694,6 +696,25 @@ static void test_irq_group(void *gicd_base) return; } + /* Check whether the group enable bits stick. */ + reg = readl(gicd_base + GICD_CTLR); + writel(reg & ~GICD_CTLR_ENABLE_BOTH, gicd_base + GICD_CTLR); + reg = readl(gicd_base + GICD_CTLR); + report("both groups disabled sticks", + (reg & GICD_CTLR_ENABLE_BOTH) == 0); + + reg &= ~GICD_CTLR_ENABLE_BOTH; + writel(reg | GICD_CTLR_ENABLE_G1, gicd_base + GICD_CTLR); + reg = readl(gicd_base + GICD_CTLR); + report("group 1 enabled sticks", + (reg & GICD_CTLR_ENABLE_BOTH) == GICD_CTLR_ENABLE_G1); + + reg &= ~GICD_CTLR_ENABLE_BOTH; + writel(reg | GICD_CTLR_ENABLE_G0, gicd_base + GICD_CTLR); + reg = readl(gicd_base + GICD_CTLR); + report("group 0 enabled sticks", + (reg & GICD_CTLR_ENABLE_BOTH) == GICD_CTLR_ENABLE_G0); + /* * On a security aware GIC in non-secure world the IGROUPR registers * are RAZ/WI. KVM emulates a single-security-state GIC, so both diff --git a/lib/arm/asm/gic-v3.h b/lib/arm/asm/gic-v3.h index 2eaf944..0a29610 100644 --- a/lib/arm/asm/gic-v3.h +++ b/lib/arm/asm/gic-v3.h @@ -21,8 +21,8 @@ #define GICD_CTLR_RWP (1U << 31) #define GICD_CTLR_DS (1U << 6) #define GICD_CTLR_ARE_NS (1U << 4) -#define GICD_CTLR_ENABLE_G1A (1U << 1) -#define GICD_CTLR_ENABLE_G1 (1U << 0) +#define GICD_CTLR_ENABLE_G1 (1U << 1) +#define GICD_CTLR_ENABLE_G0 (1U << 0) #define GICD_IROUTER 0x6000 #define GICD_PIDR2 0xffe8 diff --git a/lib/arm/gic-v3.c b/lib/arm/gic-v3.c index feecb5e..d6a5186 100644 --- a/lib/arm/gic-v3.c +++ b/lib/arm/gic-v3.c @@ -42,7 +42,7 @@ void gicv3_enable_defaults(void) writel(0, dist + GICD_CTLR); gicv3_dist_wait_for_rwp(); - writel(GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1, + writel(GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G0 | GICD_CTLR_ENABLE_G1, dist + GICD_CTLR); gicv3_dist_wait_for_rwp(); From patchwork Fri Nov 8 14:42:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 11235001 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 24C7F1575 for ; Fri, 8 Nov 2019 14:43:08 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F2E552247C for ; Fri, 8 Nov 2019 14:43:07 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728734AbfKHOnH (ORCPT ); Fri, 8 Nov 2019 09:43:07 -0500 Received: from foss.arm.com ([217.140.110.172]:44676 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728206AbfKHOnG (ORCPT ); Fri, 8 Nov 2019 09:43:06 -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 88F9446A; Fri, 8 Nov 2019 06:43:06 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 6BB433F719; Fri, 8 Nov 2019 06:43:05 -0800 (PST) From: Andre Przywara To: Andrew Jones , Paolo Bonzini Cc: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, Marc Zyngier , Alexandru Elisei Subject: [kvm-unit-tests PATCH 12/17] arm: gic: Change gic_read_iar() to take group parameter Date: Fri, 8 Nov 2019 14:42:35 +0000 Message-Id: <20191108144240.204202-13-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191108144240.204202-1-andre.przywara@arm.com> References: <20191108144240.204202-1-andre.przywara@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org Acknowledging a GIC group 0 interrupt requires us to use a different system register on GICv3. To allow us to differentiate the two groups later, add a group parameter to gic_read_iar(). For GICv2 we can use the same CPU interface register to acknowledge group 0 as well, so we ignore the parameter here. For now this is still using group 1 on every caller. Signed-off-by: Andre Przywara --- arm/gic.c | 4 ++-- arm/micro-bench.c | 2 +- arm/pl031.c | 2 +- arm/timer.c | 2 +- lib/arm/asm/arch_gicv3.h | 11 +++++++++-- lib/arm/asm/gic-v2.h | 2 +- lib/arm/asm/gic-v3.h | 2 +- lib/arm/asm/gic.h | 2 +- lib/arm/gic-v2.c | 3 ++- lib/arm/gic.c | 6 +++--- lib/arm64/asm/arch_gicv3.h | 10 ++++++++-- 11 files changed, 30 insertions(+), 16 deletions(-) diff --git a/arm/gic.c b/arm/gic.c index a0511e5..7be13a6 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -156,7 +156,7 @@ static void check_irqnr(u32 irqnr, int expected) static void irq_handler(struct pt_regs *regs __unused) { - u32 irqstat = gic_read_iar(); + u32 irqstat = gic_read_iar(1); u32 irqnr = gic_iar_irqnr(irqstat); if (irqnr == GICC_INT_SPURIOUS) { @@ -288,7 +288,7 @@ static struct gic gicv3 = { static void ipi_clear_active_handler(struct pt_regs *regs __unused) { - u32 irqstat = gic_read_iar(); + u32 irqstat = gic_read_iar(1); u32 irqnr = gic_iar_irqnr(irqstat); if (irqnr != GICC_INT_SPURIOUS) { diff --git a/arm/micro-bench.c b/arm/micro-bench.c index 4612f41..2bfee68 100644 --- a/arm/micro-bench.c +++ b/arm/micro-bench.c @@ -33,7 +33,7 @@ static void ipi_irq_handler(struct pt_regs *regs) { ipi_ready = false; ipi_received = true; - gic_write_eoir(gic_read_iar()); + gic_write_eoir(gic_read_iar(1)); ipi_ready = true; } diff --git a/arm/pl031.c b/arm/pl031.c index 5672f36..5be3d76 100644 --- a/arm/pl031.c +++ b/arm/pl031.c @@ -134,7 +134,7 @@ static void gic_irq_unmask(void) static void irq_handler(struct pt_regs *regs) { - u32 irqstat = gic_read_iar(); + u32 irqstat = gic_read_iar(1); u32 irqnr = gic_iar_irqnr(irqstat); gic_write_eoir(irqstat); diff --git a/arm/timer.c b/arm/timer.c index 0b808d5..e5cc3b4 100644 --- a/arm/timer.c +++ b/arm/timer.c @@ -150,7 +150,7 @@ static void set_timer_irq_enabled(struct timer_info *info, bool enabled) static void irq_handler(struct pt_regs *regs) { struct timer_info *info; - u32 irqstat = gic_read_iar(); + u32 irqstat = gic_read_iar(1); u32 irqnr = gic_iar_irqnr(irqstat); if (irqnr != GICC_INT_SPURIOUS) diff --git a/lib/arm/asm/arch_gicv3.h b/lib/arm/asm/arch_gicv3.h index 45b6096..52e7bba 100644 --- a/lib/arm/asm/arch_gicv3.h +++ b/lib/arm/asm/arch_gicv3.h @@ -16,6 +16,7 @@ #define ICC_PMR __ACCESS_CP15(c4, 0, c6, 0) #define ICC_SGI1R __ACCESS_CP15_64(0, c12) +#define ICC_IAR0 __ACCESS_CP15(c12, 0, c8, 0) #define ICC_IAR1 __ACCESS_CP15(c12, 0, c12, 0) #define ICC_EOIR1 __ACCESS_CP15(c12, 0, c12, 1) #define ICC_IGRPEN1 __ACCESS_CP15(c12, 0, c12, 7) @@ -30,9 +31,15 @@ static inline void gicv3_write_sgi1r(u64 val) write_sysreg(val, ICC_SGI1R); } -static inline u32 gicv3_read_iar(void) +static inline u32 gicv3_read_iar(int group) { - u32 irqstat = read_sysreg(ICC_IAR1); + u32 irqstat; + + if (group == 0) + irqstat = read_sysreg(ICC_IAR0); + else + irqstat = read_sysreg(ICC_IAR1); + dsb(sy); return irqstat; } diff --git a/lib/arm/asm/gic-v2.h b/lib/arm/asm/gic-v2.h index 1fcfd43..d50c610 100644 --- a/lib/arm/asm/gic-v2.h +++ b/lib/arm/asm/gic-v2.h @@ -32,7 +32,7 @@ extern struct gicv2_data gicv2_data; extern int gicv2_init(void); extern void gicv2_enable_defaults(void); -extern u32 gicv2_read_iar(void); +extern u32 gicv2_read_iar(int group); extern u32 gicv2_iar_irqnr(u32 iar); extern void gicv2_write_eoir(u32 irqstat); extern void gicv2_ipi_send_single(int irq, int cpu); diff --git a/lib/arm/asm/gic-v3.h b/lib/arm/asm/gic-v3.h index 0a29610..ca19110 100644 --- a/lib/arm/asm/gic-v3.h +++ b/lib/arm/asm/gic-v3.h @@ -69,7 +69,7 @@ extern struct gicv3_data gicv3_data; extern int gicv3_init(void); extern void gicv3_enable_defaults(void); -extern u32 gicv3_read_iar(void); +extern u32 gicv3_read_iar(int group); extern u32 gicv3_iar_irqnr(u32 iar); extern void gicv3_write_eoir(u32 irqstat); extern void gicv3_ipi_send_single(int irq, int cpu); diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h index 21cdb58..09663e7 100644 --- a/lib/arm/asm/gic.h +++ b/lib/arm/asm/gic.h @@ -68,7 +68,7 @@ extern void gic_enable_defaults(void); * below will work with any supported gic version. */ extern int gic_version(void); -extern u32 gic_read_iar(void); +extern u32 gic_read_iar(int group); extern u32 gic_iar_irqnr(u32 iar); extern void gic_write_eoir(u32 irqstat); extern void gic_ipi_send_single(int irq, int cpu); diff --git a/lib/arm/gic-v2.c b/lib/arm/gic-v2.c index dc6a97c..b60967e 100644 --- a/lib/arm/gic-v2.c +++ b/lib/arm/gic-v2.c @@ -26,8 +26,9 @@ void gicv2_enable_defaults(void) writel(GICC_ENABLE, cpu_base + GICC_CTLR); } -u32 gicv2_read_iar(void) +u32 gicv2_read_iar(int group) { + /* GICv2 acks both group0 and group1 IRQs with the same register. */ return readl(gicv2_cpu_base() + GICC_IAR); } diff --git a/lib/arm/gic.c b/lib/arm/gic.c index cf4e811..b51eff5 100644 --- a/lib/arm/gic.c +++ b/lib/arm/gic.c @@ -12,7 +12,7 @@ struct gicv3_data gicv3_data; struct gic_common_ops { void (*enable_defaults)(void); - u32 (*read_iar)(void); + u32 (*read_iar)(int group); u32 (*iar_irqnr)(u32 iar); void (*write_eoir)(u32 irqstat); void (*ipi_send_single)(int irq, int cpu); @@ -117,10 +117,10 @@ void gic_enable_defaults(void) gic_common_ops->enable_defaults(); } -u32 gic_read_iar(void) +u32 gic_read_iar(int group) { assert(gic_common_ops && gic_common_ops->read_iar); - return gic_common_ops->read_iar(); + return gic_common_ops->read_iar(group); } u32 gic_iar_irqnr(u32 iar) diff --git a/lib/arm64/asm/arch_gicv3.h b/lib/arm64/asm/arch_gicv3.h index a7994ec..876e1fc 100644 --- a/lib/arm64/asm/arch_gicv3.h +++ b/lib/arm64/asm/arch_gicv3.h @@ -11,6 +11,7 @@ #include #define ICC_PMR_EL1 sys_reg(3, 0, 4, 6, 0) +#define ICC_IAR0_EL1 sys_reg(3, 0, 12, 8, 0) #define ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5) #define ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0) #define ICC_EOIR1_EL1 sys_reg(3, 0, 12, 12, 1) @@ -38,10 +39,15 @@ static inline void gicv3_write_sgi1r(u64 val) asm volatile("msr_s " xstr(ICC_SGI1R_EL1) ", %0" : : "r" (val)); } -static inline u32 gicv3_read_iar(void) +static inline u32 gicv3_read_iar(int group) { u64 irqstat; - asm volatile("mrs_s %0, " xstr(ICC_IAR1_EL1) : "=r" (irqstat)); + + if (group == 0) + asm volatile("mrs_s %0, " xstr(ICC_IAR0_EL1) : "=r" (irqstat)); + else + asm volatile("mrs_s %0, " xstr(ICC_IAR1_EL1) : "=r" (irqstat)); + dsb(sy); return (u64)irqstat; } From patchwork Fri Nov 8 14:42:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 11235003 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 67BAD1599 for ; Fri, 8 Nov 2019 14:43:09 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 4768422466 for ; Fri, 8 Nov 2019 14:43:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728914AbfKHOnI (ORCPT ); Fri, 8 Nov 2019 09:43:08 -0500 Received: from foss.arm.com ([217.140.110.172]:44688 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728091AbfKHOnI (ORCPT ); Fri, 8 Nov 2019 09:43:08 -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 DA773AB6; Fri, 8 Nov 2019 06:43:07 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id BD5B53F719; Fri, 8 Nov 2019 06:43:06 -0800 (PST) From: Andre Przywara To: Andrew Jones , Paolo Bonzini Cc: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, Marc Zyngier , Alexandru Elisei Subject: [kvm-unit-tests PATCH 13/17] arm: gic: Change write_eoir() to take group parameter Date: Fri, 8 Nov 2019 14:42:36 +0000 Message-Id: <20191108144240.204202-14-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191108144240.204202-1-andre.przywara@arm.com> References: <20191108144240.204202-1-andre.przywara@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org EOIing GIC group 0 interrupt requires us to use a different system register on GICv3. To allow us to differentiate the two groups later, add a group parameter to write_eoir(). For GICv2 we can use the same CPU interface register to EOI group 0 IRQs as well, so we ignore the parameter here. For now this is still using group 1 on every caller. Signed-off-by: Andre Przywara --- arm/gic.c | 2 +- arm/micro-bench.c | 6 +++--- arm/pl031.c | 2 +- arm/timer.c | 2 +- lib/arm/asm/arch_gicv3.h | 8 ++++++-- lib/arm/asm/gic-v2.h | 2 +- lib/arm/asm/gic-v3.h | 2 +- lib/arm/asm/gic.h | 2 +- lib/arm/gic-v2.c | 2 +- lib/arm/gic.c | 6 +++--- lib/arm64/asm/arch_gicv3.h | 10 ++++++++-- 11 files changed, 27 insertions(+), 17 deletions(-) diff --git a/arm/gic.c b/arm/gic.c index 7be13a6..c68b5b5 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -165,7 +165,7 @@ static void irq_handler(struct pt_regs *regs __unused) return; } - gic_write_eoir(irqstat); + gic_write_eoir(irqstat, 1); smp_rmb(); /* pairs with wmb in stats_reset */ ++acked[smp_processor_id()]; diff --git a/arm/micro-bench.c b/arm/micro-bench.c index 2bfee68..a8f100f 100644 --- a/arm/micro-bench.c +++ b/arm/micro-bench.c @@ -27,13 +27,13 @@ static u32 cntfrq; static volatile bool ipi_ready, ipi_received; static void *vgic_dist_base; -static void (*write_eoir)(u32 irqstat); +static void (*write_eoir)(u32 irqstat, int group); static void ipi_irq_handler(struct pt_regs *regs) { ipi_ready = false; ipi_received = true; - gic_write_eoir(gic_read_iar(1)); + gic_write_eoir(gic_read_iar(1), 1); ipi_ready = true; } @@ -135,7 +135,7 @@ static void eoi_exec(void) int spurious_id = 1023; /* writes to EOI are ignored */ /* Avoid measuring assert(..) in gic_write_eoir */ - write_eoir(spurious_id); + write_eoir(spurious_id, 1); } struct exit_test { diff --git a/arm/pl031.c b/arm/pl031.c index 5be3d76..7103e7b 100644 --- a/arm/pl031.c +++ b/arm/pl031.c @@ -137,7 +137,7 @@ static void irq_handler(struct pt_regs *regs) u32 irqstat = gic_read_iar(1); u32 irqnr = gic_iar_irqnr(irqstat); - gic_write_eoir(irqstat); + gic_write_eoir(irqstat, 1); if (irqnr == pl031_irq) { report(" RTC RIS == 1", readl(&pl031->ris) == 1); diff --git a/arm/timer.c b/arm/timer.c index e5cc3b4..642e715 100644 --- a/arm/timer.c +++ b/arm/timer.c @@ -154,7 +154,7 @@ static void irq_handler(struct pt_regs *regs) u32 irqnr = gic_iar_irqnr(irqstat); if (irqnr != GICC_INT_SPURIOUS) - gic_write_eoir(irqstat); + gic_write_eoir(irqstat, 1); if (irqnr == PPI(vtimer_info.irq)) { info = &vtimer_info; diff --git a/lib/arm/asm/arch_gicv3.h b/lib/arm/asm/arch_gicv3.h index 52e7bba..163008d 100644 --- a/lib/arm/asm/arch_gicv3.h +++ b/lib/arm/asm/arch_gicv3.h @@ -17,6 +17,7 @@ #define ICC_PMR __ACCESS_CP15(c4, 0, c6, 0) #define ICC_SGI1R __ACCESS_CP15_64(0, c12) #define ICC_IAR0 __ACCESS_CP15(c12, 0, c8, 0) +#define ICC_EOIR0 __ACCESS_CP15(c12, 0, c8, 1) #define ICC_IAR1 __ACCESS_CP15(c12, 0, c12, 0) #define ICC_EOIR1 __ACCESS_CP15(c12, 0, c12, 1) #define ICC_IGRPEN1 __ACCESS_CP15(c12, 0, c12, 7) @@ -44,9 +45,12 @@ static inline u32 gicv3_read_iar(int group) return irqstat; } -static inline void gicv3_write_eoir(u32 irq) +static inline void gicv3_write_eoir(u32 irq, int group) { - write_sysreg(irq, ICC_EOIR1); + if (group == 0) + write_sysreg(irq, ICC_EOIR0); + else + write_sysreg(irq, ICC_EOIR1); isb(); } diff --git a/lib/arm/asm/gic-v2.h b/lib/arm/asm/gic-v2.h index d50c610..b57ee35 100644 --- a/lib/arm/asm/gic-v2.h +++ b/lib/arm/asm/gic-v2.h @@ -34,7 +34,7 @@ extern int gicv2_init(void); extern void gicv2_enable_defaults(void); extern u32 gicv2_read_iar(int group); extern u32 gicv2_iar_irqnr(u32 iar); -extern void gicv2_write_eoir(u32 irqstat); +extern void gicv2_write_eoir(u32 irqstat, int group); extern void gicv2_ipi_send_single(int irq, int cpu); extern void gicv2_ipi_send_mask(int irq, const cpumask_t *dest); diff --git a/lib/arm/asm/gic-v3.h b/lib/arm/asm/gic-v3.h index ca19110..210e07a 100644 --- a/lib/arm/asm/gic-v3.h +++ b/lib/arm/asm/gic-v3.h @@ -71,7 +71,7 @@ extern int gicv3_init(void); extern void gicv3_enable_defaults(void); extern u32 gicv3_read_iar(int group); extern u32 gicv3_iar_irqnr(u32 iar); -extern void gicv3_write_eoir(u32 irqstat); +extern void gicv3_write_eoir(u32 irqstat, int group); extern void gicv3_ipi_send_single(int irq, int cpu); extern void gicv3_ipi_send_mask(int irq, const cpumask_t *dest); extern void gicv3_set_redist_base(size_t stride); diff --git a/lib/arm/asm/gic.h b/lib/arm/asm/gic.h index 09663e7..c4fedd6 100644 --- a/lib/arm/asm/gic.h +++ b/lib/arm/asm/gic.h @@ -70,7 +70,7 @@ extern void gic_enable_defaults(void); extern int gic_version(void); extern u32 gic_read_iar(int group); extern u32 gic_iar_irqnr(u32 iar); -extern void gic_write_eoir(u32 irqstat); +extern void gic_write_eoir(u32 irqstat, int group); extern void gic_ipi_send_single(int irq, int cpu); extern void gic_ipi_send_mask(int irq, const cpumask_t *dest); diff --git a/lib/arm/gic-v2.c b/lib/arm/gic-v2.c index b60967e..d2af01e 100644 --- a/lib/arm/gic-v2.c +++ b/lib/arm/gic-v2.c @@ -37,7 +37,7 @@ u32 gicv2_iar_irqnr(u32 iar) return iar & GICC_IAR_INT_ID_MASK; } -void gicv2_write_eoir(u32 irqstat) +void gicv2_write_eoir(u32 irqstat, int group) { writel(irqstat, gicv2_cpu_base() + GICC_EOIR); } diff --git a/lib/arm/gic.c b/lib/arm/gic.c index b51eff5..b9e64b9 100644 --- a/lib/arm/gic.c +++ b/lib/arm/gic.c @@ -14,7 +14,7 @@ struct gic_common_ops { void (*enable_defaults)(void); u32 (*read_iar)(int group); u32 (*iar_irqnr)(u32 iar); - void (*write_eoir)(u32 irqstat); + void (*write_eoir)(u32 irqstat, int group); void (*ipi_send_single)(int irq, int cpu); void (*ipi_send_mask)(int irq, const cpumask_t *dest); }; @@ -129,10 +129,10 @@ u32 gic_iar_irqnr(u32 iar) return gic_common_ops->iar_irqnr(iar); } -void gic_write_eoir(u32 irqstat) +void gic_write_eoir(u32 irqstat, int group) { assert(gic_common_ops && gic_common_ops->write_eoir); - gic_common_ops->write_eoir(irqstat); + gic_common_ops->write_eoir(irqstat, group); } void gic_ipi_send_single(int irq, int cpu) diff --git a/lib/arm64/asm/arch_gicv3.h b/lib/arm64/asm/arch_gicv3.h index 876e1fc..972b97e 100644 --- a/lib/arm64/asm/arch_gicv3.h +++ b/lib/arm64/asm/arch_gicv3.h @@ -12,6 +12,7 @@ #define ICC_PMR_EL1 sys_reg(3, 0, 4, 6, 0) #define ICC_IAR0_EL1 sys_reg(3, 0, 12, 8, 0) +#define ICC_EOIR0_EL1 sys_reg(3, 0, 12, 8, 1) #define ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5) #define ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0) #define ICC_EOIR1_EL1 sys_reg(3, 0, 12, 12, 1) @@ -52,9 +53,14 @@ static inline u32 gicv3_read_iar(int group) return (u64)irqstat; } -static inline void gicv3_write_eoir(u32 irq) +static inline void gicv3_write_eoir(u32 irq, int group) { - asm volatile("msr_s " xstr(ICC_EOIR1_EL1) ", %0" : : "r" ((u64)irq)); + if (group == 0) + asm volatile("msr_s " xstr(ICC_EOIR0_EL1) ", %0" + : : "r" ((u64)irq)); + else + asm volatile("msr_s " xstr(ICC_EOIR1_EL1) ", %0" + : : "r" ((u64)irq)); isb(); } From patchwork Fri Nov 8 14:42:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 11235005 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 538691599 for ; Fri, 8 Nov 2019 14:43:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 3D2452245A for ; Fri, 8 Nov 2019 14:43:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728172AbfKHOnK (ORCPT ); Fri, 8 Nov 2019 09:43:10 -0500 Received: from foss.arm.com ([217.140.110.172]:44706 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729286AbfKHOnK (ORCPT ); Fri, 8 Nov 2019 09:43:10 -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 38E0046A; Fri, 8 Nov 2019 06:43:09 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 1AB153F719; Fri, 8 Nov 2019 06:43:07 -0800 (PST) From: Andre Przywara To: Andrew Jones , Paolo Bonzini Cc: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, Marc Zyngier , Alexandru Elisei Subject: [kvm-unit-tests PATCH 14/17] arm: gic: Prepare for receiving GIC group 0 interrupts via FIQs Date: Fri, 8 Nov 2019 14:42:37 +0000 Message-Id: <20191108144240.204202-15-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191108144240.204202-1-andre.przywara@arm.com> References: <20191108144240.204202-1-andre.przywara@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org To differentiate between the two interrupt groups, we will configure group 0 to be delivered as FIQs, while group 1 interrupts still use the IRQ "pin". For this we need to teach kvm-unit-tests to deal with FIQs, also need to tell the VGIC to deliver FIQs. This requires some bits here and there to be set, which are annoyingly different between GICv2 and GICv3. Add the required code in the GIC library to easily enable FIQ delivery later on, in gic.c. Signed-off-by: Andre Przywara --- lib/arm/asm/arch_gicv3.h | 7 +++++++ lib/arm/asm/gic-v2.h | 7 ++++++- lib/arm/asm/processor.h | 10 ++++++++++ lib/arm/gic-v2.c | 34 +++++++++++++++++++++++++++++++++- lib/arm64/asm/arch_gicv3.h | 9 +++++++++ lib/arm64/asm/processor.h | 10 ++++++++++ lib/arm64/processor.c | 2 ++ 7 files changed, 77 insertions(+), 2 deletions(-) diff --git a/lib/arm/asm/arch_gicv3.h b/lib/arm/asm/arch_gicv3.h index 163008d..33fd75c 100644 --- a/lib/arm/asm/arch_gicv3.h +++ b/lib/arm/asm/arch_gicv3.h @@ -20,6 +20,7 @@ #define ICC_EOIR0 __ACCESS_CP15(c12, 0, c8, 1) #define ICC_IAR1 __ACCESS_CP15(c12, 0, c12, 0) #define ICC_EOIR1 __ACCESS_CP15(c12, 0, c12, 1) +#define ICC_IGRPEN0 __ACCESS_CP15(c12, 0, c12, 6) #define ICC_IGRPEN1 __ACCESS_CP15(c12, 0, c12, 7) static inline void gicv3_write_pmr(u32 val) @@ -54,6 +55,12 @@ static inline void gicv3_write_eoir(u32 irq, int group) isb(); } +static inline void gicv3_write_grpen0(u32 val) +{ + write_sysreg(val, ICC_IGRPEN0); + isb(); +} + static inline void gicv3_write_grpen1(u32 val) { write_sysreg(val, ICC_IGRPEN1); diff --git a/lib/arm/asm/gic-v2.h b/lib/arm/asm/gic-v2.h index b57ee35..ed083ea 100644 --- a/lib/arm/asm/gic-v2.h +++ b/lib/arm/asm/gic-v2.h @@ -14,7 +14,10 @@ #define GICD_ENABLE 0x1 -#define GICC_ENABLE 0x1 +#define GICC_GRP0_ENABLE 0x1 +#define GICC_GRP1_ENABLE 0x2 +#define GICC_ACKCTL 0x4 +#define GICC_FIQEN 0x8 #define GICC_IAR_INT_ID_MASK 0x3ff #ifndef __ASSEMBLY__ @@ -32,6 +35,8 @@ extern struct gicv2_data gicv2_data; extern int gicv2_init(void); extern void gicv2_enable_defaults(void); +extern void gicv2_enable_group1(bool enable); +extern void gicv2_enable_fiq(bool enable); extern u32 gicv2_read_iar(int group); extern u32 gicv2_iar_irqnr(u32 iar); extern void gicv2_write_eoir(u32 irqstat, int group); diff --git a/lib/arm/asm/processor.h b/lib/arm/asm/processor.h index a8c4628..6b5dd1e 100644 --- a/lib/arm/asm/processor.h +++ b/lib/arm/asm/processor.h @@ -35,6 +35,16 @@ static inline unsigned long current_cpsr(void) #define current_mode() (current_cpsr() & MODE_MASK) +static inline void local_fiq_enable(void) +{ + asm volatile("cpsie f" : : : "memory", "cc"); +} + +static inline void local_fiq_disable(void) +{ + asm volatile("cpsid f" : : : "memory", "cc"); +} + static inline void local_irq_enable(void) { asm volatile("cpsie i" : : : "memory", "cc"); diff --git a/lib/arm/gic-v2.c b/lib/arm/gic-v2.c index d2af01e..360aaa3 100644 --- a/lib/arm/gic-v2.c +++ b/lib/arm/gic-v2.c @@ -23,7 +23,39 @@ void gicv2_enable_defaults(void) writel(GICD_ENABLE, dist + GICD_CTLR); writel(GICC_INT_PRI_THRESHOLD, cpu_base + GICC_PMR); - writel(GICC_ENABLE, cpu_base + GICC_CTLR); + writel(GICC_GRP0_ENABLE, cpu_base + GICC_CTLR); +} + +void gicv2_enable_fiq(bool enable) +{ + void *cpu_base = gicv2_cpu_base(); + u32 reg = readl(cpu_base + GICC_CTLR); + + if (enable) { + reg |= GICC_GRP0_ENABLE; + reg |= GICC_FIQEN; + } else { + reg &= ~GICC_GRP0_ENABLE; + reg &= ~GICC_FIQEN; + } + + writel(reg, cpu_base + GICC_CTLR); +} + +void gicv2_enable_group1(bool enable) +{ + void *cpu_base = gicv2_cpu_base(); + u32 reg = readl(cpu_base + GICC_CTLR); + + if (enable) { + reg |= GICC_GRP1_ENABLE; + reg |= GICC_ACKCTL; + } else { + reg &= ~GICC_GRP1_ENABLE; + reg &= ~GICC_ACKCTL; + } + + writel(reg, cpu_base + GICC_CTLR); } u32 gicv2_read_iar(int group) diff --git a/lib/arm64/asm/arch_gicv3.h b/lib/arm64/asm/arch_gicv3.h index 972b97e..6938bc5 100644 --- a/lib/arm64/asm/arch_gicv3.h +++ b/lib/arm64/asm/arch_gicv3.h @@ -14,8 +14,11 @@ #define ICC_IAR0_EL1 sys_reg(3, 0, 12, 8, 0) #define ICC_EOIR0_EL1 sys_reg(3, 0, 12, 8, 1) #define ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5) +#define ICC_IAR0_EL1 sys_reg(3, 0, 12, 8, 0) #define ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0) +#define ICC_EOIR0_EL1 sys_reg(3, 0, 12, 8, 1) #define ICC_EOIR1_EL1 sys_reg(3, 0, 12, 12, 1) +#define ICC_GRPEN0_EL1 sys_reg(3, 0, 12, 12, 6) #define ICC_GRPEN1_EL1 sys_reg(3, 0, 12, 12, 7) #ifndef __ASSEMBLY__ @@ -64,6 +67,12 @@ static inline void gicv3_write_eoir(u32 irq, int group) isb(); } +static inline void gicv3_write_grpen0(u32 val) +{ + asm volatile("msr_s " xstr(ICC_GRPEN0_EL1) ", %0" : : "r" ((u64)val)); + isb(); +} + static inline void gicv3_write_grpen1(u32 val) { asm volatile("msr_s " xstr(ICC_GRPEN1_EL1) ", %0" : : "r" ((u64)val)); diff --git a/lib/arm64/asm/processor.h b/lib/arm64/asm/processor.h index 1d9223f..69086e9 100644 --- a/lib/arm64/asm/processor.h +++ b/lib/arm64/asm/processor.h @@ -68,6 +68,16 @@ static inline unsigned long current_level(void) return el & 0xc; } +static inline void local_fiq_enable(void) +{ + asm volatile("msr daifclr, #1" : : : "memory"); +} + +static inline void local_fiq_disable(void) +{ + asm volatile("msr daifset, #1" : : : "memory"); +} + static inline void local_irq_enable(void) { asm volatile("msr daifclr, #2" : : : "memory"); diff --git a/lib/arm64/processor.c b/lib/arm64/processor.c index 2a024e3..8d7b921 100644 --- a/lib/arm64/processor.c +++ b/lib/arm64/processor.c @@ -190,8 +190,10 @@ void vector_handlers_default_init(vector_fn *handlers) { handlers[EL1H_SYNC] = default_vector_sync_handler; handlers[EL1H_IRQ] = default_vector_irq_handler; + handlers[EL1H_FIQ] = default_vector_irq_handler; handlers[EL0_SYNC_64] = default_vector_sync_handler; handlers[EL0_IRQ_64] = default_vector_irq_handler; + handlers[EL0_FIQ_64] = default_vector_irq_handler; } /* Needed to compile with -Wmissing-prototypes */ From patchwork Fri Nov 8 14:42:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 11235007 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 428D11575 for ; Fri, 8 Nov 2019 14:43:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 2C4FA222C9 for ; Fri, 8 Nov 2019 14:43:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728091AbfKHOnN (ORCPT ); Fri, 8 Nov 2019 09:43:13 -0500 Received: from foss.arm.com ([217.140.110.172]:44712 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727673AbfKHOnN (ORCPT ); Fri, 8 Nov 2019 09:43:13 -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 8B9147A7; Fri, 8 Nov 2019 06:43:10 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 6D3A13F719; Fri, 8 Nov 2019 06:43:09 -0800 (PST) From: Andre Przywara To: Andrew Jones , Paolo Bonzini Cc: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, Marc Zyngier , Alexandru Elisei Subject: [kvm-unit-tests PATCH 15/17] arm: gic: Provide FIQ handler Date: Fri, 8 Nov 2019 14:42:38 +0000 Message-Id: <20191108144240.204202-16-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191108144240.204202-1-andre.przywara@arm.com> References: <20191108144240.204202-1-andre.przywara@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org When configuring an interrupt as Group 0, we can ask the GIC to deliver them as a FIQ. For this we need a separate exception handler. Provide this to be used later. Signed-off-by: Andre Przywara --- arm/gic.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/arm/gic.c b/arm/gic.c index c68b5b5..6756850 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -178,6 +178,30 @@ static void irq_handler(struct pt_regs *regs __unused) smp_wmb(); /* pairs with rmb in check_acked */ } +static inline void fiq_handler(struct pt_regs *regs __unused) +{ + u32 irqstat = gic_read_iar(0); + u32 irqnr = gic_iar_irqnr(irqstat); + + if (irqnr == GICC_INT_SPURIOUS) { + ++spurious[smp_processor_id()]; + smp_wmb(); + return; + } + + gic_write_eoir(irqstat, 0); + + smp_rmb(); /* pairs with wmb in stats_reset */ + ++acked[smp_processor_id()]; + if (irqnr < GIC_NR_PRIVATE_IRQS) { + check_ipi_sender(irqstat); + check_irqnr(irqnr, IPI_IRQ); + } else { + check_irqnr(irqnr, SPI_IRQ); + } + smp_wmb(); /* pairs with rmb in check_acked */ +} + static void gicv2_ipi_send_self(void) { writel(2 << 24 | IPI_IRQ, gicv2_dist_base() + GICD_SGIR); From patchwork Fri Nov 8 14:42:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 11235009 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D4C0B1599 for ; Fri, 8 Nov 2019 14:43:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id B50F12247A for ; Fri, 8 Nov 2019 14:43:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729007AbfKHOnN (ORCPT ); Fri, 8 Nov 2019 09:43:13 -0500 Received: from foss.arm.com ([217.140.110.172]:44738 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726946AbfKHOnN (ORCPT ); Fri, 8 Nov 2019 09:43:13 -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 DD57446A; Fri, 8 Nov 2019 06:43:11 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id BFE9C3F719; Fri, 8 Nov 2019 06:43:10 -0800 (PST) From: Andre Przywara To: Andrew Jones , Paolo Bonzini Cc: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, Marc Zyngier , Alexandru Elisei Subject: [kvm-unit-tests PATCH 16/17] arm: gic: Prepare interrupt statistics for both groups Date: Fri, 8 Nov 2019 14:42:39 +0000 Message-Id: <20191108144240.204202-17-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191108144240.204202-1-andre.przywara@arm.com> References: <20191108144240.204202-1-andre.przywara@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org The arrays storing information about received interrupts need to differentiate between IRQs and FIQs, to detect interrupts firing in the wrong group. Extend the acked, spurious, bad_sender and bad_irq arrays to get another dimension, so that we can check the kind of interrupt easily. The fiq_handler marks its result using index 0, the irq_handler uses index 1. Also we add a group parameter to check_acked() and friends, to let them use the right group. Signed-off-by: Andre Przywara --- arm/gic.c | 78 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/arm/gic.c b/arm/gic.c index 6756850..43a272b 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -33,8 +33,8 @@ 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 acked[2][NR_CPUS], spurious[2][NR_CPUS]; +static int bad_sender[2][NR_CPUS], bad_irq[2][NR_CPUS]; static cpumask_t ready; static void nr_cpu_check(int nr) @@ -55,14 +55,17 @@ static void stats_reset(void) int i; for (i = 0; i < nr_cpus; ++i) { - acked[i] = 0; - bad_sender[i] = -1; - bad_irq[i] = -1; + acked[0][i] = 0; + acked[1][i] = 0; + bad_sender[0][i] = -1; + bad_sender[1][i] = -1; + bad_irq[0][i] = -1; + bad_irq[1][i] = -1; } smp_wmb(); } -static int check_acked(const char *testname, cpumask_t *mask) +static int check_acked(const char *testname, cpumask_t *mask, int group) { int missing = 0, extra = 0, unexpected = 0; int nr_pass, cpu, i; @@ -76,17 +79,17 @@ static int check_acked(const char *testname, cpumask_t *mask) for_each_present_cpu(cpu) { smp_rmb(); nr_pass += cpumask_test_cpu(cpu, mask) ? - acked[cpu] == 1 : acked[cpu] == 0; + acked[group][cpu] == 1 : acked[group][cpu] == 0; - if (bad_sender[cpu] != -1) { + if (bad_sender[group][cpu] != -1) { printf("cpu%d received IPI from wrong sender %d\n", - cpu, bad_sender[cpu]); + cpu, bad_sender[group][cpu]); bad = true; } - if (bad_irq[cpu] != -1) { + if (bad_irq[group][cpu] != -1) { printf("cpu%d received wrong irq %d\n", - cpu, bad_irq[cpu]); + cpu, bad_irq[group][cpu]); bad = true; } } @@ -109,12 +112,12 @@ static int check_acked(const char *testname, cpumask_t *mask) for_each_present_cpu(cpu) { if (cpumask_test_cpu(cpu, mask)) { - if (!acked[cpu]) + if (!acked[group][cpu]) ++missing; - else if (acked[cpu] > 1) + else if (acked[group][cpu] > 1) ++extra; } else { - if (acked[cpu]) + if (acked[group][cpu]) ++unexpected; } } @@ -132,9 +135,12 @@ static void check_spurious(void) smp_rmb(); for_each_present_cpu(cpu) { - if (spurious[cpu]) - report_info("WARN: cpu%d got %d spurious interrupts", - cpu, spurious[cpu]); + if (spurious[0][cpu]) + report_info("WARN: cpu%d got %d spurious FIQs", + cpu, spurious[0][cpu]); + if (spurious[1][cpu]) + report_info("WARN: cpu%d got %d spurious IRQs", + cpu, spurious[1][cpu]); } } @@ -144,14 +150,14 @@ static void check_ipi_sender(u32 irqstat) int src = (irqstat >> 10) & 7; if (src != IPI_SENDER) - bad_sender[smp_processor_id()] = src; + bad_sender[1][smp_processor_id()] = src; } } -static void check_irqnr(u32 irqnr, int expected) +static void check_irqnr(u32 irqnr, int expected, int group) { if (irqnr != expected) - bad_irq[smp_processor_id()] = irqnr; + bad_irq[group][smp_processor_id()] = irqnr; } static void irq_handler(struct pt_regs *regs __unused) @@ -160,7 +166,7 @@ static void irq_handler(struct pt_regs *regs __unused) u32 irqnr = gic_iar_irqnr(irqstat); if (irqnr == GICC_INT_SPURIOUS) { - ++spurious[smp_processor_id()]; + ++spurious[1][smp_processor_id()]; smp_wmb(); return; } @@ -168,12 +174,12 @@ static void irq_handler(struct pt_regs *regs __unused) gic_write_eoir(irqstat, 1); smp_rmb(); /* pairs with wmb in stats_reset */ - ++acked[smp_processor_id()]; + ++acked[1][smp_processor_id()]; if (irqnr < GIC_NR_PRIVATE_IRQS) { check_ipi_sender(irqstat); - check_irqnr(irqnr, IPI_IRQ); + check_irqnr(irqnr, IPI_IRQ, 1); } else { - check_irqnr(irqnr, SPI_IRQ); + check_irqnr(irqnr, SPI_IRQ, 1); } smp_wmb(); /* pairs with rmb in check_acked */ } @@ -184,7 +190,7 @@ static inline void fiq_handler(struct pt_regs *regs __unused) u32 irqnr = gic_iar_irqnr(irqstat); if (irqnr == GICC_INT_SPURIOUS) { - ++spurious[smp_processor_id()]; + ++spurious[0][smp_processor_id()]; smp_wmb(); return; } @@ -192,12 +198,12 @@ static inline void fiq_handler(struct pt_regs *regs __unused) gic_write_eoir(irqstat, 0); smp_rmb(); /* pairs with wmb in stats_reset */ - ++acked[smp_processor_id()]; + ++acked[0][smp_processor_id()]; if (irqnr < GIC_NR_PRIVATE_IRQS) { check_ipi_sender(irqstat); - check_irqnr(irqnr, IPI_IRQ); + check_irqnr(irqnr, IPI_IRQ, 0); } else { - check_irqnr(irqnr, SPI_IRQ); + check_irqnr(irqnr, SPI_IRQ, 0); } smp_wmb(); /* pairs with rmb in check_acked */ } @@ -232,7 +238,7 @@ static void ipi_test_self(void) cpumask_clear(&mask); cpumask_set_cpu(smp_processor_id(), &mask); gic->ipi.send_self(); - check_acked("IPI: self", &mask); + check_acked("IPI: self", &mask, 1); report_prefix_pop(); } @@ -247,7 +253,7 @@ static void ipi_test_smp(void) for (i = smp_processor_id() & 1; i < nr_cpus; i += 2) cpumask_clear_cpu(i, &mask); gic_ipi_send_mask(IPI_IRQ, &mask); - check_acked("IPI: directed", &mask); + check_acked("IPI: directed", &mask, 1); report_prefix_pop(); report_prefix_push("broadcast"); @@ -255,7 +261,7 @@ static void ipi_test_smp(void) cpumask_copy(&mask, &cpu_present_mask); cpumask_clear_cpu(smp_processor_id(), &mask); gic->ipi.send_broadcast(); - check_acked("IPI: broadcast", &mask); + check_acked("IPI: broadcast", &mask, 1); report_prefix_pop(); } @@ -327,11 +333,11 @@ static void ipi_clear_active_handler(struct pt_regs *regs __unused) writel(val, base + GICD_ICACTIVER); smp_rmb(); /* pairs with wmb in stats_reset */ - ++acked[smp_processor_id()]; - check_irqnr(irqnr, IPI_IRQ); + ++acked[1][smp_processor_id()]; + check_irqnr(irqnr, IPI_IRQ, 1); smp_wmb(); /* pairs with rmb in check_acked */ } else { - ++spurious[smp_processor_id()]; + ++spurious[1][smp_processor_id()]; smp_wmb(); } } @@ -617,7 +623,7 @@ static bool trigger_and_check_spi(const char *test_name, break; } - ret = (check_acked(test_name, &cpumask) >= 0); + ret = (check_acked(test_name, &cpumask, 1) >= 0); /* Clean up pending bit in case this IRQ wasn't taken. */ if (!(irq_stat & IRQ_STAT_NO_CLEAR)) @@ -643,7 +649,7 @@ static void spi_test_single(void) cpumask_clear(&cpumask); cpumask_set_cpu(cpu, &cpumask); gic_enable_irq(SPI_IRQ); - check_acked("now enabled SPI fires", &cpumask); + check_acked("now enabled SPI fires", &cpumask, 1); } static void spi_test_smp(void) From patchwork Fri Nov 8 14:42:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andre Przywara X-Patchwork-Id: 11235011 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 15FE21575 for ; Fri, 8 Nov 2019 14:43:15 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F32FC2245A for ; Fri, 8 Nov 2019 14:43:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729301AbfKHOnO (ORCPT ); Fri, 8 Nov 2019 09:43:14 -0500 Received: from foss.arm.com ([217.140.110.172]:44750 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1728378AbfKHOnO (ORCPT ); Fri, 8 Nov 2019 09:43:14 -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 487157A7; Fri, 8 Nov 2019 06:43:13 -0800 (PST) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.44]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 26E563F719; Fri, 8 Nov 2019 06:43:12 -0800 (PST) From: Andre Przywara To: Andrew Jones , Paolo Bonzini Cc: kvmarm@lists.cs.columbia.edu, linux-arm-kernel@lists.infradead.org, kvm@vger.kernel.org, Marc Zyngier , Alexandru Elisei Subject: [kvm-unit-tests PATCH 17/17] arm: gic: Test Group0 SPIs Date: Fri, 8 Nov 2019 14:42:40 +0000 Message-Id: <20191108144240.204202-18-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20191108144240.204202-1-andre.przywara@arm.com> References: <20191108144240.204202-1-andre.przywara@arm.com> Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org With the newly gained building blocks we can now actually test Group 0 interrupts on our emulated/virtualized GIC. The least common denominator for the groups usage on both GICv2 and GICv3 is to configure group 0 interrupts to trigger FIQs, and group 1 interrupts to trigger IRQs. For testing this we first configure our test SPI to belong to group 0, then trigger it to see that it is actually delivered as an FIQ, and not as an IRQ. The we change the group to become 1, and trigger again, this time expecting the opposite behaviour. Signed-off-by: Andre Przywara --- arm/gic.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 101 insertions(+), 2 deletions(-) diff --git a/arm/gic.c b/arm/gic.c index 43a272b..9942314 100644 --- a/arm/gic.c +++ b/arm/gic.c @@ -276,6 +276,22 @@ static void irqs_enable(void) local_irq_enable(); } +static void fiqs_enable(void) +{ +#ifdef __arm__ + install_exception_handler(EXCPTN_FIQ, fiq_handler); +#else + install_irq_handler(EL1H_FIQ, fiq_handler); +#endif + if (gic_version() == 3) { + gicv3_write_grpen0(1); + } else { + gicv2_enable_fiq(true); + gicv2_enable_group1(true); + } + local_fiq_enable(); +} + static void ipi_send(void) { irqs_enable(); @@ -598,6 +614,7 @@ static void spi_configure_irq(int irq, int cpu) #define IRQ_STAT_NONE 0 #define IRQ_STAT_IRQ 1 +#define IRQ_STAT_FIQ 2 #define IRQ_STAT_TYPE_MASK 0x3 #define IRQ_STAT_NO_CLEAR 4 @@ -617,14 +634,21 @@ static bool trigger_and_check_spi(const char *test_name, cpumask_clear(&cpumask); switch (irq_stat & IRQ_STAT_TYPE_MASK) { case IRQ_STAT_NONE: + ret &= (check_acked(NULL, &cpumask, 0) >= 0); + ret &= (check_acked(test_name, &cpumask, 1) >= 0); break; case IRQ_STAT_IRQ: + ret &= (check_acked(NULL, &cpumask, 0) >= 0); + cpumask_set_cpu(cpu, &cpumask); + ret &= (check_acked(test_name, &cpumask, 1) >= 0); + break; + case IRQ_STAT_FIQ: + ret &= (check_acked(NULL, &cpumask, 1) >= 0); cpumask_set_cpu(cpu, &cpumask); + ret &= (check_acked(test_name, &cpumask, 0) >= 0); break; } - ret = (check_acked(test_name, &cpumask, 1) >= 0); - /* Clean up pending bit in case this IRQ wasn't taken. */ if (!(irq_stat & IRQ_STAT_NO_CLEAR)) gic_set_irq_bit(SPI_IRQ, GICD_ICPENDR); @@ -657,6 +681,9 @@ static void spi_test_smp(void) int cpu; int cores = 1; + if (nr_cpus > 8) + printf("triggering SPIs on all %d cores, takes %d seconds\n", + nr_cpus, (nr_cpus - 1) * 3 / 2); wait_on_ready(); for_each_present_cpu(cpu) { if (cpu == smp_processor_id()) @@ -671,6 +698,46 @@ static void spi_test_smp(void) } #define GICD_CTLR_ENABLE_BOTH (GICD_CTLR_ENABLE_G0 | GICD_CTLR_ENABLE_G1) +#define EXPECT_FIQ true +#define EXPECT_IRQ false + +/* + * Check whether our SPI interrupt is correctly delivered as an FIQ or as + * an IRQ, as configured. + * This tries to enable the two groups independently, to check whether + * the relation group0->FIQ and group1->IRQ holds. + */ +static void gic_check_irq_delivery(void *gicd_base, bool as_fiq) +{ + u32 reg = readl(gicd_base + GICD_CTLR) & ~GICD_CTLR_ENABLE_BOTH; + int cpu = smp_processor_id(); + + /* Check that both groups disabled block the IRQ. */ + writel(reg, gicd_base + GICD_CTLR); + trigger_and_check_spi("no IRQs with both groups disabled", + IRQ_STAT_NONE, cpu); + + /* Check that just the *other* group enabled blocks the IRQ. */ + if (as_fiq) + writel(reg | GICD_CTLR_ENABLE_G1, gicd_base + GICD_CTLR); + else + writel(reg | GICD_CTLR_ENABLE_G0, gicd_base + GICD_CTLR); + trigger_and_check_spi("no IRQs with just the other group enabled", + IRQ_STAT_NONE, cpu); + + /* Check that just this group enabled fires the IRQ. */ + if (as_fiq) + writel(reg | GICD_CTLR_ENABLE_G0, gicd_base + GICD_CTLR); + else + writel(reg | GICD_CTLR_ENABLE_G1, gicd_base + GICD_CTLR); + trigger_and_check_spi("just this group enabled", + as_fiq ? IRQ_STAT_FIQ : IRQ_STAT_IRQ, cpu); + + /* Check that both groups enabled fires the IRQ. */ + writel(reg | GICD_CTLR_ENABLE_BOTH, gicd_base + GICD_CTLR); + trigger_and_check_spi("both groups enabled", + as_fiq ? IRQ_STAT_FIQ : IRQ_STAT_IRQ, cpu); +} /* * Check the security state configuration of the GIC. @@ -711,6 +778,9 @@ static bool gicv3_check_security(void *gicd_base) * Check whether this works as expected (as Linux will not use this feature). * We can only verify this state on a GICv3, so we check it there and silently * assume it's valid for GICv2. + * GICv2 and GICv3 handle the groups differently, but we use the common + * denominator (Group0 as FIQ, Group1 as IRQ) and rely on the GIC library for + * abstraction. */ static void test_irq_group(void *gicd_base) { @@ -754,6 +824,35 @@ static void test_irq_group(void *gicd_base) gic_set_irq_group(SPI_IRQ, !reg); report("IGROUPR is writable", gic_get_irq_group(SPI_IRQ) != reg); gic_set_irq_group(SPI_IRQ, reg); + + /* + * Configure group 0 interrupts as FIQs, install both an FIQ and IRQ + * handler and allow both types to be delivered to the core. + */ + irqs_enable(); + fiqs_enable(); + + /* Configure one SPI to be a group0 interrupt. */ + gic_set_irq_group(SPI_IRQ, 0); + spi_configure_irq(SPI_IRQ, smp_processor_id()); + report_prefix_push("FIQ"); + gic_check_irq_delivery(gicd_base, EXPECT_FIQ); + report_prefix_pop(); + + /* Configure the SPI to be a group1 interrupt instead. */ + gic_set_irq_group(SPI_IRQ, 1); + report_prefix_push("IRQ"); + gic_check_irq_delivery(gicd_base, EXPECT_IRQ); + report_prefix_pop(); + + /* Reset the IRQ to the default group. */ + if (is_gicv3) + gic_set_irq_group(SPI_IRQ, 1); + else + gic_set_irq_group(SPI_IRQ, 0); + gic_disable_irq(SPI_IRQ); + + report_prefix_pop(); } static void spi_send(void)