Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp3982768imu; Mon, 12 Nov 2018 03:59:28 -0800 (PST) X-Google-Smtp-Source: AJdET5ejPiAGK7tQjYtNAPm4qOmRMpLB1aIrZBrPhDfHq2bOruWcRB1VOb4JbH68r3WE/xSiBkq/ X-Received: by 2002:a62:3707:: with SMTP id e7-v6mr633413pfa.70.1542023968015; Mon, 12 Nov 2018 03:59:28 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1542023967; cv=none; d=google.com; s=arc-20160816; b=sNzmh4P8ezsIrCmWRUG/mDJfmKD0b0pvOrjd5WBojTmI7IaMKAZAEdhyKDPqYxVSNu vGvWOpALvqlq2w5LPb6iJrBRm1bQXG4zSuZBUxfPhEhmHEqf1Bpr6PI+bdBXR31DSloK Tcl5mVVv7BvjFJGdjPf4dK6eVpRHVWsWDaQVrSfjGJgzPPnCs5oYEdPhfwILyL35PRHT CiVc274Y+izb8ykV7gqpGu0bsqqrV05aSAE3D8zMdWhRtZAOHoej8BEzgnpfBCNT/l/s V3kZUsjgo/zpHSA8RwBUl3WhGmmTexbuGCM5eQpFYa9OwDsoXJvNUposElcEiauQPY0l d/0w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=yI5r+KTkQ0yiSxyUyKOgTUauBL481TMdL4kk2JLxsfM=; b=XfQvLkE5ZKKgvJU1loxNH90h47pkfDLJXCvCY2YOa6Fv4Ch/s6aIpMmfpi/6mSK7Xh UWOW4Oe+R4XiMjisw8BiwZPha7lHL9pI9yE9njI+ovqUv0MtdkW4DLl/kxS99abDTcQo Q0faMIkamk7SCHyJdpSsWwTo2OfIGagxTp2nNGKQKgnGTx3oY0LWfPyRCw8D2ISXqHWh NvQrPPC6Bj5M4COACkjqTDLepLeZ9nt3J0mWVyMjpTb9c//xsJglzVv1X4YcZShVHin2 fcYEuhBrJdGP06lyOhbCZQoFJu0SPRKUWozeLnrLviXPiS8fJG8czGX6/Q0/b9lgEwWR r8fw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 1-v6si5967509plp.383.2018.11.12.03.59.12; Mon, 12 Nov 2018 03:59:27 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730068AbeKLVvJ (ORCPT + 99 others); Mon, 12 Nov 2018 16:51:09 -0500 Received: from foss.arm.com ([217.140.101.70]:34774 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730054AbeKLVvI (ORCPT ); Mon, 12 Nov 2018 16:51:08 -0500 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 9983380D; Mon, 12 Nov 2018 03:58:11 -0800 (PST) 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 870E23F5A0; Mon, 12 Nov 2018 03:58:09 -0800 (PST) From: Julien Thierry To: linux-arm-kernel@lists.infradead.org Cc: linux-kernel@vger.kernel.org, daniel.thompson@linaro.org, joel@joelfernandes.org, marc.zyngier@arm.com, christoffer.dall@arm.com, james.morse@arm.com, catalin.marinas@arm.com, will.deacon@arm.com, Julien Thierry , Thomas Gleixner , Jason Cooper Subject: [PATCH v6 20/24] irqchip/gic-v3: Allow interrupts to be set as pseudo-NMI Date: Mon, 12 Nov 2018 11:57:11 +0000 Message-Id: <1542023835-21446-21-git-send-email-julien.thierry@arm.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1542023835-21446-1-git-send-email-julien.thierry@arm.com> References: <1542023835-21446-1-git-send-email-julien.thierry@arm.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Implement NMI callbacks for GICv3 irqchip. Install NMI safe handlers when setting up interrupt line as NMI. Only SPIs and PPIs are allowed to be set up as NMI. Signed-off-by: Julien Thierry Cc: Thomas Gleixner Cc: Jason Cooper Cc: Marc Zyngier --- drivers/irqchip/irq-gic-v3.c | 84 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c index c763f1a..f22ae49 100644 --- a/drivers/irqchip/irq-gic-v3.c +++ b/drivers/irqchip/irq-gic-v3.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -90,6 +91,9 @@ struct gic_chip_data { */ static DEFINE_STATIC_KEY_FALSE(supports_pseudo_nmis); +/* ppi_nmi_refs[n] == number of cpus having ppi[n + 16] set as NMI */ +static refcount_t ppi_nmi_refs[16]; + static struct gic_kvm_info gic_v3_kvm_info; static DEFINE_PER_CPU(bool, has_rss); @@ -314,6 +318,72 @@ static int gic_irq_get_irqchip_state(struct irq_data *d, return 0; } +static int gic_irq_nmi_setup(struct irq_data *d) +{ + struct irq_desc *desc = irq_to_desc(d->irq); + + if (!gic_supports_nmi()) + return -EINVAL; + + if (gic_peek_irq(d, GICD_ISENABLER)) { + pr_err("Cannot set NMI property of enabled IRQ %u\n", d->irq); + return -EINVAL; + } + + /* + * A secondary irq_chip should be in charge of LPI request, + * it should not be possible to get there + */ + if (WARN_ON(gic_irq(d) >= 8192)) + return -EINVAL; + + /* desc lock should already be held */ + if (gic_irq(d) < 32) { + /* Setting up PPI as NMI, only switch handler for first NMI */ + if (!refcount_inc_not_zero(&ppi_nmi_refs[gic_irq(d) - 16])) { + refcount_set(&ppi_nmi_refs[gic_irq(d) - 16], 1); + desc->handle_irq = handle_percpu_devid_fasteoi_nmi; + } + } else { + desc->handle_irq = handle_fasteoi_nmi; + } + + gic_set_irq_prio(gic_irq(d), gic_dist_base(d), GICD_INT_NMI_PRI); + + return 0; +} + +static void gic_irq_nmi_teardown(struct irq_data *d) +{ + struct irq_desc *desc = irq_to_desc(d->irq); + + if (WARN_ON(!gic_supports_nmi())) + return; + + if (gic_peek_irq(d, GICD_ISENABLER)) { + pr_err("Cannot set NMI property of enabled IRQ %u\n", d->irq); + return; + } + + /* + * A secondary irq_chip should be in charge of LPI request, + * it should not be possible to get there + */ + if (WARN_ON(gic_irq(d) >= 8192)) + return; + + /* desc lock should already be held */ + if (gic_irq(d) < 32) { + /* Tearing down NMI, only switch handler for last NMI */ + if (refcount_dec_and_test(&ppi_nmi_refs[gic_irq(d) - 16])) + desc->handle_irq = handle_percpu_devid_irq; + } else { + desc->handle_irq = handle_fasteoi_irq; + } + + gic_set_irq_prio(gic_irq(d), gic_dist_base(d), GICD_INT_DEF_PRI); +} + static void gic_eoi_irq(struct irq_data *d) { gic_write_eoir(gic_irq(d)); @@ -950,6 +1020,8 @@ static inline void gic_cpu_pm_init(void) { } .irq_set_affinity = gic_set_affinity, .irq_get_irqchip_state = gic_irq_get_irqchip_state, .irq_set_irqchip_state = gic_irq_set_irqchip_state, + .irq_nmi_setup = gic_irq_nmi_setup, + .irq_nmi_teardown = gic_irq_nmi_teardown, .flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND, @@ -965,6 +1037,8 @@ static inline void gic_cpu_pm_init(void) { } .irq_get_irqchip_state = gic_irq_get_irqchip_state, .irq_set_irqchip_state = gic_irq_set_irqchip_state, .irq_set_vcpu_affinity = gic_irq_set_vcpu_affinity, + .irq_nmi_setup = gic_irq_nmi_setup, + .irq_nmi_teardown = gic_irq_nmi_teardown, .flags = IRQCHIP_SET_TYPE_MASKED | IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND, @@ -1159,7 +1233,17 @@ static int partition_domain_translate(struct irq_domain *d, static void gic_enable_nmi_support(void) { + int i; + + for (i = 0; i < 16; i++) + refcount_set(&ppi_nmi_refs[i], 0); + static_branch_enable(&supports_pseudo_nmis); + + if (static_branch_likely(&supports_deactivate_key)) + gic_eoimode1_chip.flags |= IRQCHIP_SUPPORTS_NMI; + else + gic_chip.flags |= IRQCHIP_SUPPORTS_NMI; } static int __init gic_init_bases(void __iomem *dist_base, -- 1.9.1