From patchwork Thu Jun 5 09:53:08 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Thompson X-Patchwork-Id: 4304231 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id C5B3A9F433 for ; Thu, 5 Jun 2014 09:56:33 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DA49E202F8 for ; Thu, 5 Jun 2014 09:56:32 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E1C172034A for ; Thu, 5 Jun 2014 09:56:31 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1WsUN3-0001Ih-5M; Thu, 05 Jun 2014 09:54:05 +0000 Received: from mail-wg0-f42.google.com ([74.125.82.42]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1WsUMp-0001DZ-Mw for linux-arm-kernel@lists.infradead.org; Thu, 05 Jun 2014 09:53:52 +0000 Received: by mail-wg0-f42.google.com with SMTP id y10so783908wgg.13 for ; Thu, 05 Jun 2014 02:53:29 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=QyFH5hlobHFywppNpSKyZ0jPB12nbr1ZQeqLssx1+vc=; b=XbAS7fkt/tY/yMjmoQ+kf3OcIUbMeKJ4lf21XBDGZZM171oQY7S0Q+lnXmDhx2kLaV ZS09r8xOzzjjLd9Am/PfqpW7YYsShxUnMKhgfE48kpU9flqFVi2eW1ZThYy17L53o5HH EBtfzAqBC1uk3krk9pMID8Kz+NhVXUP8fAxQqeoZl5dF4OCQhczyP7mAje5Kd7gnZOnv 2JNH3KhwEkhwMCcrUf9lkuW0hHIKa3d07Y5TjbJJui1VnBZulDhjNhQKVXYEvXb/VHyT JY7JCiiAbhqCoMt+/Fmtoa8SRvdp7SC1GQ6nCqlpw6kFnan5ynf6Kuxb/Ucty9NW9/SS SdXQ== X-Gm-Message-State: ALoCoQnvqlOZh2UmRVvK1oFieE4xy9FDRk+r13pusiR8774UtUKTO+aks3AvZR0yA9rWZeEcTMj4 X-Received: by 10.180.211.146 with SMTP id nc18mr13900941wic.53.1401962009306; Thu, 05 Jun 2014 02:53:29 -0700 (PDT) Received: from sundance.lan (cpc4-aztw19-0-0-cust157.18-1.cable.virginm.net. [82.33.25.158]) by mx.google.com with ESMTPSA id s3sm7337863wje.36.2014.06.05.02.53.27 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 05 Jun 2014 02:53:28 -0700 (PDT) From: Daniel Thompson To: Jason Wessel Subject: [RFC v3 3/9] irqchip: gic: Provide support for interrupt grouping Date: Thu, 5 Jun 2014 10:53:08 +0100 Message-Id: <1401961994-18033-4-git-send-email-daniel.thompson@linaro.org> X-Mailer: git-send-email 1.9.0 In-Reply-To: <1401961994-18033-1-git-send-email-daniel.thompson@linaro.org> References: <1400853478-5824-1-git-send-email-daniel.thompson@linaro.org> <1401961994-18033-1-git-send-email-daniel.thompson@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140605_025352_055123_AB59AD9D X-CRM114-Status: GOOD ( 18.77 ) X-Spam-Score: -0.7 (/) Cc: Mark Rutland , Nicolas Pitre , kernel@stlinux.com, kgdb-bugreport@lists.sourceforge.net, Linus Walleij , Sricharan R , Jiri Slaby , Daniel Thompson , Dirk Behme , Russell King , Nicolas Pitre , Ian Campbell , Anton Vorontsov , "David A. Long" , linux-serial@vger.kernel.org, Catalin Marinas , kernel-team@android.com, devicetree@vger.kernel.org, linaro-kernel@lists.linaro.org, Jason Cooper , Pawel Moll , patches@linaro.org, Kumar Gala , Rob Herring , John Stultz , Thomas Gleixner , linux-arm-kernel@lists.infradead.org, Greg Kroah-Hartman , linux-kernel@vger.kernel.org, Colin Cross , Frederic Weisbecker , Christoffer Dall X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-2.5 required=5.0 tests=BAYES_00,RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP All GIC hardware except GICv1 without TrustZone support provides a means to group exceptions into group 0 (which can optionally be signally using use FIQ) and group 1. The kernel currently provides no means to exploit this. This patch alters the initialization of the GIC to place all interrupts into group 1, this is a foundational requirement to meaningfully use FIQ. Note that the hardware functionality is unavailable to the kernel when a secure monitor is present because access to the grouping registers are prohibited outside "secure world". This allows grouping to be used to allow hardware peripherals to send interrupts into the secure world. On systems without TrustZone support the kernel has the power to route interrupt sources to FIQ, potentially allowing a driver to exploit the NMI-like properties of FIQ. The registers involved are RAZ/WI when unimplemented or protected by security policy. This patch therefore applies grouping unconditionally. Tested on a qemu GICv2 model (self-written from GICv2 spec) and an STiH416 (ARM Cortex A9, GICv1, TZ). Signed-off-by: Daniel Thompson Cc: Thomas Gleixner Cc: Jason Cooper Cc: Nicolas Pitre Cc: Christoffer Dall Cc: Sricharan R Acked-by: Dirk Behme --- drivers/irqchip/irq-gic.c | 35 ++++++++++++++++++++++++++++++----- include/linux/irqchip/arm-gic.h | 3 +++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 57d165e..aa8efe4 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -408,13 +408,27 @@ static void __init gic_dist_init(struct gic_chip_data *gic) writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4); /* + * Set all global interrupts to be group 1. + * + * If grouping is not available (not implemented or prohibited by + * security mode) these registers a read-as-zero/write-ignored. + */ + for (i = 32; i < gic_irqs; i += 32) + writel_relaxed(0xffffffff, base + GIC_DIST_IGROUP + i * 4 / 32); + + /* * Disable all interrupts. Leave the PPI and SGIs alone * as these enables are banked registers. */ for (i = 32; i < gic_irqs; i += 32) writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i * 4 / 32); - writel_relaxed(1, base + GIC_DIST_CTRL); + /* + * Set EnableGrp1/EnableGrp0 (bit 1 and 0) or EnableGrp (bit 0 only, + * bit 1 ignored) + */ + writel_relaxed(GIC_DIST_CTRL_ENABLE_GRP0_BIT | + GIC_DIST_CTRL_ENABLE_GRP1_BIT, base + GIC_DIST_CTRL); } static void gic_cpu_init(struct gic_chip_data *gic) @@ -452,8 +466,16 @@ static void gic_cpu_init(struct gic_chip_data *gic) for (i = 0; i < 32; i += 4) writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4 / 4); + /* + * Set all PPI and SGI interrupts to be group 1. + * + * If grouping is not available (not implemented or prohibited by + * security mode) these registers are read-as-zero/write-ignored. + */ + writel_relaxed(0xffffffff, dist_base + GIC_DIST_IGROUP + 0); + writel_relaxed(0xf0, base + GIC_CPU_PRIMASK); - writel_relaxed(1, base + GIC_CPU_CTRL); + writel_relaxed(0x1f, base + GIC_CPU_CTRL); } void gic_cpu_if_down(void) @@ -537,7 +559,9 @@ static void gic_dist_restore(unsigned int gic_nr) writel_relaxed(gic_data[gic_nr].saved_spi_enable[i], dist_base + GIC_DIST_ENABLE_SET + i * 4); - writel_relaxed(1, dist_base + GIC_DIST_CTRL); + writel_relaxed(GIC_DIST_CTRL_ENABLE_GRP0_BIT | + GIC_DIST_CTRL_ENABLE_GRP1_BIT, + dist_base + GIC_DIST_CTRL); } static void gic_cpu_save(unsigned int gic_nr) @@ -594,7 +618,7 @@ static void gic_cpu_restore(unsigned int gic_nr) writel_relaxed(0xa0a0a0a0, dist_base + GIC_DIST_PRI + i * 4); writel_relaxed(0xf0, cpu_base + GIC_CPU_PRIMASK); - writel_relaxed(1, cpu_base + GIC_CPU_CTRL); + writel_relaxed(0x1f, cpu_base + GIC_CPU_CTRL); } static int gic_notifier(struct notifier_block *self, unsigned long cmd, void *v) @@ -670,7 +694,8 @@ static void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) dmb(ishst); /* this always happens on GIC0 */ - writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); + writel_relaxed(map << 16 | irq | 0x8000, + gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT); raw_spin_unlock_irqrestore(&irq_controller_lock, flags); } diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index 7ed92d0..919502f 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h @@ -37,6 +37,9 @@ #define GIC_DIST_SGI_PENDING_CLEAR 0xf10 #define GIC_DIST_SGI_PENDING_SET 0xf20 +#define GIC_DIST_CTRL_ENABLE_GRP0_BIT (1 << 0) +#define GIC_DIST_CTRL_ENABLE_GRP1_BIT (1 << 1) + #define GICH_HCR 0x0 #define GICH_VTR 0x4 #define GICH_VMCR 0x8