Joerg Roedel cc9aff
From: David Woodhouse <dwmw@amazon.co.uk>
Joerg Roedel cc9aff
Date: Wed, 7 Oct 2020 13:20:44 +0100
Joerg Roedel cc9aff
Subject: [PATCH 3/5] x86/ioapic: Handle Extended Destination ID field in RTE
Joerg Roedel cc9aff
Patch-mainline: Never, upstream uses different implementation
Joerg Roedel cc9aff
References: bsc#1181001, jsc#ECO-3191
Joerg Roedel cc9aff
Joerg Roedel cc9aff
The IOAPIC Redirection Table Entries contain an 8-bit Extended
Joerg Roedel cc9aff
Destination ID field which maps to bits 11-4 of the MSI address.
Joerg Roedel cc9aff
Joerg Roedel cc9aff
The lowest bit is used to indicate remappable format, when interrupt
Joerg Roedel cc9aff
remapping is in use. A hypervisor can use the other 7 bits to permit
Joerg Roedel cc9aff
guests to address up to 15 bits of APIC IDs, thus allowing 32768 vCPUs
Joerg Roedel cc9aff
before having to expose a vIOMMU and interrupt remapping to the guest.
Joerg Roedel cc9aff
Joerg Roedel cc9aff
No behavioural change in this patch, since nothing yet permits APIC IDs
Joerg Roedel cc9aff
above 255 to be used with the non-IR IOAPIC domain. Except for the case
Joerg Roedel cc9aff
where IR is enabled but there are IOAPICs which aren't in the scope of
Joerg Roedel cc9aff
any IOMMU, which is totally hosed anyway and needs fixing independently
Joerg Roedel cc9aff
of this change.
Joerg Roedel cc9aff
Joerg Roedel cc9aff
Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Joerg Roedel cc9aff
Acked-by: Joerg Roedel <jroedel@suse.de>
Joerg Roedel cc9aff
---
Joerg Roedel cc9aff
 arch/x86/include/asm/io_apic.h |    3 ++-
Joerg Roedel cc9aff
 arch/x86/kernel/apic/io_apic.c |   19 +++++++++++++------
Joerg Roedel cc9aff
 2 files changed, 15 insertions(+), 7 deletions(-)
Joerg Roedel cc9aff
Joerg Roedel cc9aff
--- a/arch/x86/include/asm/io_apic.h
Joerg Roedel cc9aff
+++ b/arch/x86/include/asm/io_apic.h
Joerg Roedel cc9aff
@@ -77,7 +77,8 @@ struct IO_APIC_route_entry {
Joerg Roedel cc9aff
 		mask		:  1,	/* 0: enabled, 1: disabled */
Joerg Roedel cc9aff
 		__reserved_2	: 15;
Joerg Roedel cc9aff
 
Joerg Roedel cc9aff
-	__u32	__reserved_3	: 24,
Joerg Roedel cc9aff
+	__u32	__reserved_3	: 17,
Joerg Roedel cc9aff
+		ext_dest	:  7,
Joerg Roedel cc9aff
 		dest		:  8;
Joerg Roedel cc9aff
 } __attribute__ ((packed));
Joerg Roedel cc9aff
 
Joerg Roedel cc9aff
--- a/arch/x86/kernel/apic/io_apic.c
Joerg Roedel cc9aff
+++ b/arch/x86/kernel/apic/io_apic.c
Joerg Roedel cc9aff
@@ -1268,10 +1268,10 @@ static void io_apic_print_entries(unsign
Joerg Roedel cc9aff
 			       buf, (ir_entry->index << 15) | ir_entry->index,
Joerg Roedel cc9aff
 			       ir_entry->zero);
Joerg Roedel cc9aff
 		else
Joerg Roedel cc9aff
-			printk(KERN_DEBUG "%s, %s, D(%02X), M(%1d)\n",
Joerg Roedel cc9aff
+			printk(KERN_DEBUG "%s, %s, D(%02X%02X), M(%1d)\n",
Joerg Roedel cc9aff
 			       buf,
Joerg Roedel cc9aff
 			       entry.dest_mode == IOAPIC_DEST_MODE_LOGICAL ?
Joerg Roedel cc9aff
-			       "logical " : "physical",
Joerg Roedel cc9aff
+			       "logical " : "physical", entry.ext_dest,
Joerg Roedel cc9aff
 			       entry.dest, entry.delivery_mode);
Joerg Roedel cc9aff
 	}
Joerg Roedel cc9aff
 }
Joerg Roedel cc9aff
@@ -1439,6 +1439,7 @@ void native_disable_io_apic(void)
Joerg Roedel cc9aff
 	 */
Joerg Roedel cc9aff
 	if (ioapic_i8259.pin != -1) {
Joerg Roedel cc9aff
 		struct IO_APIC_route_entry entry;
Joerg Roedel cc9aff
+		u32 apic_id = read_apic_id();
Joerg Roedel cc9aff
 
Joerg Roedel cc9aff
 		memset(&entry, 0, sizeof(entry));
Joerg Roedel cc9aff
 		entry.mask		= IOAPIC_UNMASKED;
Joerg Roedel cc9aff
@@ -1446,7 +1447,8 @@ void native_disable_io_apic(void)
Joerg Roedel cc9aff
 		entry.polarity		= IOAPIC_POL_HIGH;
Joerg Roedel cc9aff
 		entry.dest_mode		= IOAPIC_DEST_MODE_PHYSICAL;
Joerg Roedel cc9aff
 		entry.delivery_mode	= dest_ExtINT;
Joerg Roedel cc9aff
-		entry.dest		= read_apic_id();
Joerg Roedel cc9aff
+		entry.dest		= apic_id & 0xff;
Joerg Roedel cc9aff
+		entry.ext_dest		= apic_id >> 8;
Joerg Roedel cc9aff
 
Joerg Roedel cc9aff
 		/*
Joerg Roedel cc9aff
 		 * Add it to the IO-APIC irq-routing table:
Joerg Roedel cc9aff
@@ -1861,7 +1863,8 @@ static int ioapic_set_affinity(struct ir
Joerg Roedel cc9aff
 	raw_spin_lock_irqsave(&ioapic_lock, flags);
Joerg Roedel cc9aff
 	if (ret >= 0 && ret != IRQ_SET_MASK_OK_DONE) {
Joerg Roedel cc9aff
 		cfg = irqd_cfg(irq_data);
Joerg Roedel cc9aff
-		data->entry.dest = cfg->dest_apicid;
Joerg Roedel cc9aff
+		data->entry.dest = cfg->dest_apicid & 0xff;
Joerg Roedel cc9aff
+		data->entry.ext_dest = cfg->dest_apicid >> 8;
Joerg Roedel cc9aff
 		data->entry.vector = cfg->vector;
Joerg Roedel cc9aff
 		for_each_irq_pin(entry, data->irq_2_pin)
Joerg Roedel cc9aff
 			__ioapic_write_entry(entry->apic, entry->pin,
Joerg Roedel cc9aff
@@ -1969,6 +1972,7 @@ static inline void __init unlock_ExtINT_
Joerg Roedel cc9aff
 	int apic, pin, i;
Joerg Roedel cc9aff
 	struct IO_APIC_route_entry entry0, entry1;
Joerg Roedel cc9aff
 	unsigned char save_control, save_freq_select;
Joerg Roedel cc9aff
+	u32 apic_id;
Joerg Roedel cc9aff
 
Joerg Roedel cc9aff
 	pin  = find_isa_irq_pin(8, mp_INT);
Joerg Roedel cc9aff
 	if (pin == -1) {
Joerg Roedel cc9aff
@@ -1984,11 +1988,13 @@ static inline void __init unlock_ExtINT_
Joerg Roedel cc9aff
 	entry0 = ioapic_read_entry(apic, pin);
Joerg Roedel cc9aff
 	clear_IO_APIC_pin(apic, pin);
Joerg Roedel cc9aff
 
Joerg Roedel cc9aff
+	apic_id = hard_smp_processor_id();
Joerg Roedel cc9aff
 	memset(&entry1, 0, sizeof(entry1));
Joerg Roedel cc9aff
 
Joerg Roedel cc9aff
 	entry1.dest_mode = IOAPIC_DEST_MODE_PHYSICAL;
Joerg Roedel cc9aff
 	entry1.mask = IOAPIC_UNMASKED;
Joerg Roedel cc9aff
-	entry1.dest = hard_smp_processor_id();
Joerg Roedel cc9aff
+	entry1.dest = apic_id & 0xff;
Joerg Roedel cc9aff
+	entry1.ext_dest = apic_id >> 8;
Joerg Roedel cc9aff
 	entry1.delivery_mode = dest_ExtINT;
Joerg Roedel cc9aff
 	entry1.polarity = entry0.polarity;
Joerg Roedel cc9aff
 	entry1.trigger = IOAPIC_EDGE;
Joerg Roedel cc9aff
@@ -2896,7 +2902,8 @@ static void mp_setup_entry(struct irq_cf
Joerg Roedel cc9aff
 	memset(entry, 0, sizeof(*entry));
Joerg Roedel cc9aff
 	entry->delivery_mode = apic->irq_delivery_mode;
Joerg Roedel cc9aff
 	entry->dest_mode     = apic->irq_dest_mode;
Joerg Roedel cc9aff
-	entry->dest	     = cfg->dest_apicid;
Joerg Roedel cc9aff
+	entry->dest	     = cfg->dest_apicid & 0xff;
Joerg Roedel cc9aff
+	entry->ext_dest	     = cfg->dest_apicid >> 8;
Joerg Roedel cc9aff
 	entry->vector	     = cfg->vector;
Joerg Roedel cc9aff
 	entry->trigger	     = data->trigger;
Joerg Roedel cc9aff
 	entry->polarity	     = data->polarity;