From patchwork Mon Jul 21 14:47:18 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Daniel Thompson X-Patchwork-Id: 33973 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ig0-f198.google.com (mail-ig0-f198.google.com [209.85.213.198]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 06C5323961 for ; Mon, 21 Jul 2014 14:48:51 +0000 (UTC) Received: by mail-ig0-f198.google.com with SMTP id h18sf14689234igc.9 for ; Mon, 21 Jul 2014 07:48:51 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=Ryz7mtaVqrzkpvyGDPWSHJVWe2zyVZbh2xzOPsdu1p0=; b=i8tD/roTaMYDdLXRT5t0T/JDF1Qyx2GZagTWAAJ2Lulz8OPhFPCNFpXSpgphftwKK9 UUwZYRACbv98XmjKhv28lIJOQuyk79hYPqDKDVra1bakqk0wRrN056pMJ1C4DaRPvdwL Mw4XY+FPre0E7Ak3XsIshh21wcZBfg3ErwLCQM+ZlUpNOVJ0hVOJogKsuzoLfg9/9LB+ 3KtzHyIcm5RJLDPk57OyVAznM9R/3KpoTPPN+JaE9sW+3yutPa2KWovoSywbxm+eO9xW p07R4zVVA5jVjrGz3HsCHEuVvDu4fYMBe0b5Ct0SZWocYHcNGXNZCpyTGH6TgLtxZjQH MBOQ== X-Gm-Message-State: ALoCoQljDwFOfPTISSzRV709JV6+rMyti65XGYpWizuuyjDT7k41/F51q4y+RPPaJ1mKT0iVbdk2 X-Received: by 10.182.230.133 with SMTP id sy5mr13234909obc.22.1405954130760; Mon, 21 Jul 2014 07:48:50 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.84.35 with SMTP id k32ls1846420qgd.73.gmail; Mon, 21 Jul 2014 07:48:50 -0700 (PDT) X-Received: by 10.221.56.5 with SMTP id wa5mr26479266vcb.25.1405954130635; Mon, 21 Jul 2014 07:48:50 -0700 (PDT) Received: from mail-vc0-f178.google.com (mail-vc0-f178.google.com [209.85.220.178]) by mx.google.com with ESMTPS id rw10si11471298vcb.44.2014.07.21.07.48.50 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 21 Jul 2014 07:48:50 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.178 as permitted sender) client-ip=209.85.220.178; Received: by mail-vc0-f178.google.com with SMTP id la4so12383867vcb.9 for ; Mon, 21 Jul 2014 07:48:50 -0700 (PDT) X-Received: by 10.52.37.81 with SMTP id w17mr2137117vdj.95.1405954130533; Mon, 21 Jul 2014 07:48:50 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.221.37.5 with SMTP id tc5csp118444vcb; Mon, 21 Jul 2014 07:48:49 -0700 (PDT) X-Received: by 10.180.9.71 with SMTP id x7mr4955830wia.61.1405954129185; Mon, 21 Jul 2014 07:48:49 -0700 (PDT) Received: from mail-wi0-f175.google.com (mail-wi0-f175.google.com [209.85.212.175]) by mx.google.com with ESMTPS id cu10si20993998wib.82.2014.07.21.07.48.48 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Mon, 21 Jul 2014 07:48:49 -0700 (PDT) Received-SPF: pass (google.com: domain of daniel.thompson@linaro.org designates 209.85.212.175 as permitted sender) client-ip=209.85.212.175; Received: by mail-wi0-f175.google.com with SMTP id ho1so4254827wib.2 for ; Mon, 21 Jul 2014 07:48:48 -0700 (PDT) X-Received: by 10.194.5.103 with SMTP id r7mr24189870wjr.41.1405954128576; Mon, 21 Jul 2014 07:48:48 -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 di7sm38135166wjb.34.2014.07.21.07.48.44 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 21 Jul 2014 07:48:47 -0700 (PDT) From: Daniel Thompson To: Russell King , Thomas Gleixner , Jason Cooper Cc: Daniel Thompson , Marex Vasut , Harro Haan , linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, patches@linaro.org, linaro-kernel@lists.linaro.org, John Stultz Subject: [PATCH RFC 7/9] irqchip: gic: Use non-secure aliased register set when FIQ is enabled Date: Mon, 21 Jul 2014 15:47:18 +0100 Message-Id: <1405954040-30399-8-git-send-email-daniel.thompson@linaro.org> X-Mailer: git-send-email 1.9.3 In-Reply-To: <1405954040-30399-1-git-send-email-daniel.thompson@linaro.org> References: <1405954040-30399-1-git-send-email-daniel.thompson@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: daniel.thompson@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.178 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Signed-off-by: Daniel Thompson --- drivers/irqchip/irq-gic.c | 76 ++++++++++++++++++++++++++++++++++++----- include/linux/irqchip/arm-gic.h | 4 +-- 2 files changed, 70 insertions(+), 10 deletions(-) diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 5c934a4..8faa271 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c @@ -59,6 +59,7 @@ union gic_base { struct gic_chip_data { union gic_base dist_base; union gic_base cpu_base; + union gic_base aliased_cpu_base; #ifdef CONFIG_CPU_PM u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)]; u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)]; @@ -126,6 +127,12 @@ static inline void __iomem *gic_data_cpu_base(struct gic_chip_data *data) return data->get_base(&data->cpu_base); } +static inline void __iomem *gic_data_aliased_cpu_base( + struct gic_chip_data *data) +{ + return data->get_base(&data->aliased_cpu_base); +} + static inline void gic_set_base_accessor(struct gic_chip_data *data, void __iomem *(*f)(union gic_base *)) { @@ -134,6 +141,7 @@ static inline void gic_set_base_accessor(struct gic_chip_data *data, #else #define gic_data_dist_base(d) ((d)->dist_base.common_base) #define gic_data_cpu_base(d) ((d)->cpu_base.common_base) +#define gic_data_aliased_cpu_base(d) ((d)->aliased_cpu_base.common_base) #define gic_set_base_accessor(d, f) #endif @@ -159,6 +167,13 @@ static inline void __iomem *gic_cpu_base(struct irq_data *d) return gic_data_cpu_base(gic_data); } +static inline void __iomem *gic_aliased_cpu_base(struct irq_data *d) +{ + struct gic_chip_data *gic_data = irq_data_get_irq_chip_data(d); + + return gic_data_aliased_cpu_base(gic_data); +} + static inline unsigned int gic_irq(struct irq_data *d) { return d->hwirq; @@ -194,7 +209,7 @@ static void gic_eoi_irq(struct irq_data *d) if (gic_arch_extn.irq_eoi) gic_arch_extn.irq_eoi(d); - writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI); + writel_relaxed(gic_irq(d), gic_aliased_cpu_base(d) + GIC_CPU_EOI); } static int gic_set_type(struct irq_data *d, unsigned int type) @@ -300,7 +315,7 @@ static void __exception_irq_entry gic_handle_irq(struct pt_regs *regs) { u32 irqstat, irqnr; struct gic_chip_data *gic = &gic_data[0]; - void __iomem *cpu_base = gic_data_cpu_base(gic); + void __iomem *cpu_base = gic_data_aliased_cpu_base(gic); do { irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK); @@ -332,7 +347,8 @@ static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) chained_irq_enter(chip, desc); raw_spin_lock(&irq_controller_lock); - status = readl_relaxed(gic_data_cpu_base(chip_data) + GIC_CPU_INTACK); + status = readl_relaxed(gic_data_aliased_cpu_base(chip_data) + + GIC_CPU_INTACK); raw_spin_unlock(&irq_controller_lock); gic_irq = (status & 0x3ff); @@ -419,11 +435,19 @@ static int gic_ack_fiq(struct irq_data *d) return irq_find_mapping(gic->domain, irqnr); } +static void gic_eoi_fiq(struct irq_data *d) +{ + if (gic_arch_extn.irq_eoi) + gic_arch_extn.irq_eoi(d); + + writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI); +} + static struct fiq_chip gic_fiq = { .fiq_enable = gic_enable_fiq, .fiq_disable = gic_disable_fiq, .fiq_ack = gic_ack_fiq, - .fiq_eoi = gic_eoi_irq, + .fiq_eoi = gic_eoi_fiq, }; static void __init gic_init_fiq(struct gic_chip_data *gic, @@ -453,6 +477,10 @@ static void __init gic_init_fiq(struct gic_chip_data *gic, */ for (i = 0; i < num_irqs; i++) fiq_register_mapping(first_irq + i, &gic_fiq); + + /* This is not a fatal problem for some use-cases so WARN() is enough */ + WARN(gic_data_cpu_base(gic_data) == gic_data_aliased_cpu_base(gic_data), + "No non-secure alias; IRQ handler may spuriously ack FIQs\n"); } #else /* CONFIG_FIQ */ static inline void gic_init_fiq(struct gic_chip_data *gic, @@ -1076,7 +1104,9 @@ const struct irq_domain_ops *gic_routable_irq_domain_ops = void __init gic_init_bases(unsigned int gic_nr, int irq_start, void __iomem *dist_base, void __iomem *cpu_base, - u32 percpu_offset, struct device_node *node) + void __iomem *aliased_cpu_base, + u32 percpu_offset, + struct device_node *node) { irq_hw_number_t hwirq_base; struct gic_chip_data *gic; @@ -1085,6 +1115,9 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, BUG_ON(gic_nr >= MAX_GIC_NR); + if (!aliased_cpu_base) + aliased_cpu_base = cpu_base; + gic = &gic_data[gic_nr]; #ifdef CONFIG_GIC_NON_BANKED if (percpu_offset) { /* Frankein-GIC without banked registers... */ @@ -1092,10 +1125,14 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, gic->dist_base.percpu_base = alloc_percpu(void __iomem *); gic->cpu_base.percpu_base = alloc_percpu(void __iomem *); + gic->aliased_cpu_base.percpu_base = + alloc_percpu(void __iomem *); if (WARN_ON(!gic->dist_base.percpu_base || - !gic->cpu_base.percpu_base)) { + !gic->cpu_base.percpu_base || + !gic->aliased_cpu_base.percpu_base)) { free_percpu(gic->dist_base.percpu_base); free_percpu(gic->cpu_base.percpu_base); + free_percpu(gic->aliased_cpu_base.percpu_base); return; } @@ -1103,6 +1140,8 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, unsigned long offset = percpu_offset * cpu_logical_map(cpu); *per_cpu_ptr(gic->dist_base.percpu_base, cpu) = dist_base + offset; *per_cpu_ptr(gic->cpu_base.percpu_base, cpu) = cpu_base + offset; + *per_cpu_ptr(gic->aliased_cpu_base.percpu_base, cpu) = + aliased_cpu_base + offset; } gic_set_base_accessor(gic, gic_get_percpu_base); @@ -1114,6 +1153,7 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, percpu_offset); gic->dist_base.common_base = dist_base; gic->cpu_base.common_base = cpu_base; + gic->aliased_cpu_base.common_base = aliased_cpu_base; gic_set_base_accessor(gic, gic_get_common_base); } @@ -1188,11 +1228,27 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start, #ifdef CONFIG_OF static int gic_cnt __initdata; +static void __init __iomem *gic_arm_iomap_nonsecure(struct device_node *np, + int index) +{ +#if defined(CONFIG_ARM) && defined(CONFIG_FIQ) + struct resource res; + + if (of_address_to_resource(np, index, &res)) + return NULL; + + return __arm_ioremap(res.start, resource_size(&res), MT_DEVICE_NS); +#else + return NULL; +#endif +} + static int __init gic_of_init(struct device_node *node, struct device_node *parent) { - void __iomem *cpu_base; void __iomem *dist_base; + void __iomem *cpu_base; + void __iomem *aliased_cpu_base; u32 percpu_offset; int irq; @@ -1205,10 +1261,14 @@ gic_of_init(struct device_node *node, struct device_node *parent) cpu_base = of_iomap(node, 1); WARN(!cpu_base, "unable to map gic cpu registers\n"); + aliased_cpu_base = gic_arm_iomap_nonsecure(node, 1); + /* no NULL check because NULL is a legimate value */ + if (of_property_read_u32(node, "cpu-offset", &percpu_offset)) percpu_offset = 0; - gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset, node); + gic_init_bases(gic_cnt, -1, dist_base, cpu_base, aliased_cpu_base, + percpu_offset, node); if (!gic_cnt) gic_init_physaddr(node); diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h index 45e2d8c..15cf913 100644 --- a/include/linux/irqchip/arm-gic.h +++ b/include/linux/irqchip/arm-gic.h @@ -80,14 +80,14 @@ struct device_node; extern struct irq_chip gic_arch_extn; void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *, - u32 offset, struct device_node *); + void __iomem *, u32 offset, struct device_node *); void gic_cascade_irq(unsigned int gic_nr, unsigned int irq); void gic_cpu_if_down(void); static inline void gic_init(unsigned int nr, int start, void __iomem *dist , void __iomem *cpu) { - gic_init_bases(nr, start, dist, cpu, 0, NULL); + gic_init_bases(nr, start, dist, cpu, NULL, 0, NULL); } void gic_send_sgi(unsigned int cpu_id, unsigned int irq);