Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp6361486imu; Mon, 21 Jan 2019 07:37:28 -0800 (PST) X-Google-Smtp-Source: ALg8bN74iD8RW7E9RroyBtO5IQz2tBuRmNwGrii5K/+4vvpEnD4qs5ipP1xe55Rl17QsxuAl2IN5 X-Received: by 2002:a62:75d1:: with SMTP id q200mr30093704pfc.254.1548085048422; Mon, 21 Jan 2019 07:37:28 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1548085048; cv=none; d=google.com; s=arc-20160816; b=xpcgMGakAssEAWGUUTaRgZ4mGuyrvQ9MKYDlZhhliiK+7hsUjFfgzreBKCXxcWRIX0 E0ZuGPryqP1hIHigwBWBKblY6bpTwrcrsRplEEw7fTHOAPfIxDzZiH1ynFyXm6CTGzW+ 8NMDo4hlzk2bPVkhbvuZJnxsGq2HNLTBQwkruLTT4t1//wbBk4xKuec8a0bsQb/s+jY1 TznS8dthGE2hgpYpFQl/TNt/yEJuZ/R41ycfXftWNJj3owZsX49Wp6ZI2zsnZH4RBALR 4d/CGwgLax9urXhT2FBeged0T7ubcEJBZV5iNwh43yeVBw/PNobjT5kbqXk8FCVGD5S0 Whbg== 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=+5UUK7YANK9oxtubve1frYu4+lRYO0+2kQNs2J0jJYQ=; b=K9LUmJwi7Ekx9uIZ5mRUZhziNnokyqcMM3cYYeikH9akAJ+BukIyHJ/D8nI7pDkYMn Mkj9hC3ZrE0PE9kyCGO1eNJmbv7ZNK9S+mcrc4fDHf4rBtv2H2itHqmANbnDKsM9n2fG 79QjjQ021z6hFK03VJr0d+twkMjD85TZLhFcYqklU+0DElj1LvCxlT9euymaRBaSY259 ntGpm/Z/nnLKSwnMVfnMd4iG2YlVU5hxZOMIucwkh7qJZLJWnEfKN5o+Hyt2NpLByA6C fXtqO7MocOU9aHjHhQv8ihc8chBVvD5NMYdFpCs0mrkupxVQZGpjn53fBTcRBdxJF7Ga BcUg== 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 r11si8844051pli.175.2019.01.21.07.37.12; Mon, 21 Jan 2019 07:37:28 -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 S1730549AbfAUPez (ORCPT + 99 others); Mon, 21 Jan 2019 10:34:55 -0500 Received: from usa-sjc-mx-foss1.foss.arm.com ([217.140.101.70]:36660 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730440AbfAUPex (ORCPT ); Mon, 21 Jan 2019 10:34:53 -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 3DBBD1684; Mon, 21 Jan 2019 07:34:53 -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 063593F5C1; Mon, 21 Jan 2019 07:34:50 -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, mark.rutland@arm.com, Julien Thierry , Thomas Gleixner , Jason Cooper Subject: [PATCH v9 22/26] irqchip/gic-v3: Allow interrupts to be set as pseudo-NMI Date: Mon, 21 Jan 2019 15:33:41 +0000 Message-Id: <1548084825-8803-23-git-send-email-julien.thierry@arm.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1548084825-8803-1-git-send-email-julien.thierry@arm.com> References: <1548084825-8803-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 4df1e94..447d8ab 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 @@ -93,6 +94,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); @@ -320,6 +324,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)); @@ -958,6 +1028,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, @@ -973,6 +1045,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, @@ -1176,7 +1250,17 @@ static bool gic_enable_quirk_msm8996(void *data) 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