[PATCH v6 02/29] x86/apic: Add irq_cfg::delivery_mode

From: Ricardo Neri
Date: Thu May 05 2022 - 19:58:00 EST


Currently, the delivery mode of all interrupts is set to the mode of the
APIC driver in use. There are no restrictions in hardware to configure the
delivery mode of each interrupt individually. Also, certain IRQs need to be
configured with a specific delivery mode (e.g., NMI).

Add a new member, delivery_mode, to struct irq_cfg. Subsequent changesets
will update every irq_domain to set the delivery mode of each IRQ to that
specified in its irq_cfg data.

To keep the current behavior, when allocating an IRQ in the root domain
(i.e., the x86_vector_domain), set the delivery mode of the IRQ as that of
the APIC driver.

Cc: Andi Kleen <ak@xxxxxxxxxxxxxxx>
Cc: "Ravi V. Shankar" <ravi.v.shankar@xxxxxxxxx>
Cc: Stephane Eranian <eranian@xxxxxxxxxx>
Cc: iommu@xxxxxxxxxxxxxxxxxxxxxxxxxx
Cc: linuxppc-dev@xxxxxxxxxxxxxxxx
Cc: x86@xxxxxxxxxx
Reviewed-by: Ashok Raj <ashok.raj@xxxxxxxxx>
Reviewed-by: Tony Luck <tony.luck@xxxxxxxxx>
Signed-off-by: Ricardo Neri <ricardo.neri-calderon@xxxxxxxxxxxxxxx>
---
Changes since v5:
* Updated indentation of the existing members of struct irq_cfg.
* Reworded the commit message.

Changes since v4:
* Rebased to use new enumeration apic_delivery_modes.

Changes since v3:
* None

Changes since v2:
* Reduced scope to only add the interrupt delivery mode in
struct irq_alloc_info.

Changes since v1:
* Introduced this patch.
---
arch/x86/include/asm/hw_irq.h | 5 +++--
arch/x86/kernel/apic/vector.c | 9 +++++++++
2 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h
index d465ece58151..5ac5e6c603ee 100644
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -88,8 +88,9 @@ struct irq_alloc_info {
};

struct irq_cfg {
- unsigned int dest_apicid;
- unsigned int vector;
+ unsigned int dest_apicid;
+ unsigned int vector;
+ enum apic_delivery_modes delivery_mode;
};

extern struct irq_cfg *irq_cfg(unsigned int irq);
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c
index 3e6f6b448f6a..838e220e8860 100644
--- a/arch/x86/kernel/apic/vector.c
+++ b/arch/x86/kernel/apic/vector.c
@@ -567,6 +567,7 @@ static int x86_vector_alloc_irqs(struct irq_domain *domain, unsigned int virq,
irqd->chip_data = apicd;
irqd->hwirq = virq + i;
irqd_set_single_target(irqd);
+
/*
* Prevent that any of these interrupts is invoked in
* non interrupt context via e.g. generic_handle_irq()
@@ -577,6 +578,14 @@ static int x86_vector_alloc_irqs(struct irq_domain *domain, unsigned int virq,
/* Don't invoke affinity setter on deactivated interrupts */
irqd_set_affinity_on_activate(irqd);

+ /*
+ * Initialize the delivery mode of this irq to match the
+ * default delivery mode of the APIC. Children irq domains
+ * may take the delivery mode from the individual irq
+ * configuration rather than from the APIC driver.
+ */
+ apicd->hw_irq_cfg.delivery_mode = apic->delivery_mode;
+
/*
* Legacy vectors are already assigned when the IOAPIC
* takes them over. They stay on the same vector. This is
--
2.17.1