From patchwork Mon May 21 11:35:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julien Thierry X-Patchwork-Id: 10414877 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 9B8F060365 for ; Mon, 21 May 2018 11:39:51 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 894DF2882B for ; Mon, 21 May 2018 11:39:51 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7B1A32882E; Mon, 21 May 2018 11:39:51 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id EA7BC2882B for ; Mon, 21 May 2018 11:39:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=U7LTM5xzROpMWFCbwJ8t7xIMNsRMSzGqQDBQVgT3x2c=; b=nXseTP937bdO7YE57Auhd3SNKl JqQ2MIUSARSS8N+85kN7VJV3utFACkJnO+OqZ74SaDrVupKWZAa4ItNreB8cGqdNoSEURruDdBkxa MyTEwmEAkd7ytSJh8u8fdwFjeEhQtjaZA5v3ocSHWPjh5YvoNhfdqEIMA6Z2fTr4FjTqUTsijrc0e kG7vIxp7SFNMTXaGAHqUbgPmnMtD8jRdJMXdrNzetAiQzzOrhFL2hl3cCZvcw7kfObcQLwQ/PMwG5 3faT4ksTIcfBH8VA4IwRgeL/Jj4a9Ip7fp3uo4AgSCLyHJBwx0S4JK0d6nFgj9D572+PgWFPOevSw rVkWkfIw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1fKjAK-00011u-4V; Mon, 21 May 2018 11:39:48 +0000 Received: from foss.arm.com ([217.140.101.70]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1fKj6h-0006KX-De for linux-arm-kernel@lists.infradead.org; Mon, 21 May 2018 11:36:19 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id C9358169F; Mon, 21 May 2018 04:35:49 -0700 (PDT) Received: from e112298-lin.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 9565A3F25D; Mon, 21 May 2018 04:35:47 -0700 (PDT) From: Julien Thierry To: linux-arm-kernel@lists.infradead.org Subject: [PATCH v3 5/6] arm64: Detect current view of GIC priorities Date: Mon, 21 May 2018 12:35:14 +0100 Message-Id: <1526902515-13769-6-git-send-email-julien.thierry@arm.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1526902515-13769-1-git-send-email-julien.thierry@arm.com> References: <1526902515-13769-1-git-send-email-julien.thierry@arm.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180521_043603_508030_1C1180DD X-CRM114-Status: GOOD ( 21.43 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.rutland@arm.com, joelaf@google.com, daniel.thompson@linaro.org, joel.opensrc@gmail.com, Jason Cooper , Julien Thierry , marc.zyngier@arm.com, catalin.marinas@arm.com, will.deacon@arm.com, linux-kernel@vger.kernel.org, christoffer.dall@arm.com, james.morse@arm.com, Thomas Gleixner MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP The values non secure EL1 needs to use for PMR and RPR registers depends on the value of SCR_EL3.FIQ. The values non secure EL1 sees from the distributor and redistributor depend on whether security is enabled for the GIC or not. Figure out what values we are dealing with to know if the values we use for PMR and RPR match the priority values that have been configured in the distributor and redistributors. Also, add firmware requirements related to SCR_EL3. Signed-off-by: Julien Thierry Cc: Will Deacon Cc: Thomas Gleixner Cc: Jason Cooper Cc: Marc Zyngier --- Documentation/arm64/booting.txt | 5 +++ arch/arm64/include/asm/sysreg.h | 1 + drivers/irqchip/irq-gic-v3.c | 99 ++++++++++++++++++++++++++++++----------- 3 files changed, 80 insertions(+), 25 deletions(-) -- 1.9.1 diff --git a/Documentation/arm64/booting.txt b/Documentation/arm64/booting.txt index 8d0df62..e387938 100644 --- a/Documentation/arm64/booting.txt +++ b/Documentation/arm64/booting.txt @@ -188,6 +188,11 @@ Before jumping into the kernel, the following conditions must be met: the kernel image will be entered must be initialised by software at a higher exception level to prevent execution in an UNKNOWN state. + - SCR_EL3.FIQ must have the same value across all CPUs the kernel is + executing on. + - The value of SCR_EL3.FIQ must be the same as the one present at boot + time whenever the kernel is executing. + For systems with a GICv3 interrupt controller to be used in v3 mode: - If EL3 is present: ICC_SRE_EL3.Enable (bit 3) must be initialiased to 0b1. diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 6171178..fb8320a 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -322,6 +322,7 @@ #define SYS_ICC_SRE_EL1 sys_reg(3, 0, 12, 12, 5) #define SYS_ICC_IGRPEN0_EL1 sys_reg(3, 0, 12, 12, 6) #define SYS_ICC_IGRPEN1_EL1 sys_reg(3, 0, 12, 12, 7) +#define SYS_ICC_RPR_EL1 sys_reg(3, 0, 12, 11, 3) #define SYS_CONTEXTIDR_EL1 sys_reg(3, 0, 13, 0, 1) #define SYS_TPIDR_EL1 sys_reg(3, 0, 13, 0, 4) diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index 82cfacf..3c44918 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -63,6 +63,30 @@ struct gic_chip_data { static struct gic_chip_data gic_data __read_mostly; static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key); +#ifdef CONFIG_USE_ICC_SYSREGS_FOR_IRQFLAGS +/* + * The behaviours of RPR and PMR registers differ depending on the value of + * SCR_EL3.FIQ, and the behaviour of non-secure priority registers of the + * distributor and redistributors depends on whether security is enabled in the + * GIC. + * + * When security is enabled, non-secure priority values from the (re)distributor + * are presented to the GIC CPUIF as follow: + * (GIC_(R)DIST_PRI[irq] >> 1) | 0x80; + * + * If SCR_EL3.FIQ == 1, the values writen to/read from PMR and RPR at non-secure + * EL1 are subject to a similar operation thus matching the priorities presented + * from the (re)distributor when security is enabled. + * + * see GICv3/GICv4 Architecture Specification (IHI0069D): + * - section 4.8.1 Non-secure accesses to register fields for Secure interrupt + * priorities. + * - Figure 4-7 Secure read of the priority field for a Non-secure Group 1 + * interrupt. + */ +DEFINE_STATIC_KEY_FALSE(have_non_secure_prio_view); +#endif + static struct gic_kvm_info gic_v3_kvm_info; static DEFINE_PER_CPU(bool, has_rss); @@ -531,28 +555,26 @@ static void gic_update_vlpi_properties(void) !gic_data.rdists.has_direct_lpi ? "no " : ""); } -static void gic_cpu_sys_reg_init(void) +/* Check whether it's single security state view */ +static inline bool gic_dist_security_disabled(void) { - int i, cpu = smp_processor_id(); - u64 mpidr = cpu_logical_map(cpu); - u64 need_rss = MPIDR_RS(mpidr); - bool group0; - u32 val, pribits; + return readl_relaxed(gic_data.dist_base + GICD_CTLR) & GICD_CTLR_DS; +} - /* - * Need to check that the SRE bit has actually been set. If - * not, it means that SRE is disabled at EL2. We're going to - * die painfully, and there is nothing we can do about it. - * - * Kindly inform the luser. - */ - if (!gic_enable_sre()) - pr_err("GIC: unable to set SRE (disabled at EL2), panic ahead\n"); +static inline u32 gic_get_cpu_pri_bits(void) +{ + u32 pribits; pribits = gic_read_ctlr(); pribits &= ICC_CTLR_EL1_PRI_BITS_MASK; pribits >>= ICC_CTLR_EL1_PRI_BITS_SHIFT; - pribits++; + + return pribits + 1; +} + +static inline bool gic_cpu_has_group0(void) +{ + u32 pmr_val; /* * Let's find out if Group0 is under control of EL3 or not by @@ -565,13 +587,41 @@ static void gic_cpu_sys_reg_init(void) * becomes 0x80. Reading it back returns 0, indicating that * we're don't have access to Group0. */ - write_gicreg(BIT(8 - pribits), ICC_PMR_EL1); - val = read_gicreg(ICC_PMR_EL1); - group0 = val != 0; + write_gicreg(BIT(8 - gic_get_cpu_pri_bits()), ICC_PMR_EL1); + pmr_val = read_gicreg(ICC_PMR_EL1); + + return pmr_val != 0; +} + +static void gic_cpu_sys_reg_init(void) +{ + int i, cpu = smp_processor_id(); + u64 mpidr = cpu_logical_map(cpu); + u64 need_rss = MPIDR_RS(mpidr); + bool group0; + u32 pribits; + + /* + * Need to check that the SRE bit has actually been set. If + * not, it means that SRE is disabled at EL2. We're going to + * die painfully, and there is nothing we can do about it. + * + * Kindly inform the luser. + */ + if (!gic_enable_sre()) + pr_err("GIC: unable to set SRE (disabled at EL2), panic ahead\n"); + + pribits = gic_get_cpu_pri_bits(); + + group0 = gic_cpu_has_group0(); #ifndef CONFIG_USE_ICC_SYSREGS_FOR_IRQFLAGS /* Set priority mask register */ write_gicreg(ICC_PMR_EL1_UNMASKED, ICC_PMR_EL1); +#else + if (static_branch_likely(&have_non_secure_prio_view) && group0) + /* Mismatch configuration with boot CPU */ + WARN_ON(group0 && !gic_dist_security_disabled()); #endif /* @@ -825,12 +875,6 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, #endif #ifdef CONFIG_CPU_PM -/* Check whether it's single security state view */ -static bool gic_dist_security_disabled(void) -{ - return readl_relaxed(gic_data.dist_base + GICD_CTLR) & GICD_CTLR_DS; -} - static int gic_cpu_pm_notifier(struct notifier_block *self, unsigned long cmd, void *v) { @@ -1130,6 +1174,11 @@ static int __init gic_init_bases(void __iomem *dist_base, gic_cpu_init(); gic_cpu_pm_init(); +#ifdef CONFIG_USE_ICC_SYSREGS_FOR_IRQFLAGS + if (!gic_cpu_has_group0() || gic_dist_security_disabled()) + static_branch_enable(&have_non_secure_prio_view); +#endif + return 0; out_free: