mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
x86/ioapic: Handle Extended Destination ID field in RTE
Bits 63-48 of the I/OAPIC Redirection Table Entry map directly to bits 19-4 of the address used in the resulting MSI cycle. Historically, the x86 MSI format only used the top 8 of those 16 bits as the destination APIC ID, and the "Extended Destination ID" in the lower 8 bits was unused. With interrupt remapping, the lowest bit of the Extended Destination ID (bit 48 of RTE, bit 4 of MSI address) is now used to indicate a remappable format MSI. A hypervisor can use the other 7 bits of the Extended Destination ID to permit guests to address up to 15 bits of APIC IDs, thus allowing 32768 vCPUs before having to expose a vIOMMU and interrupt remapping to the guest. No behavioural change in this patch, since nothing yet permits APIC IDs above 255 to be used with the non-IR I/OAPIC domain. [ tglx: Converted it to the cleaned up entry/msi_msg format and added commentry ] Signed-off-by: David Woodhouse <dwmw@amazon.co.uk> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Link: https://lore.kernel.org/r/20201024213535.443185-32-dwmw2@infradead.org
This commit is contained in:
parent
79eb3581bc
commit
51130d2188
2 changed files with 17 additions and 6 deletions
|
@ -67,7 +67,8 @@ struct IO_APIC_route_entry {
|
||||||
is_level : 1,
|
is_level : 1,
|
||||||
masked : 1,
|
masked : 1,
|
||||||
reserved_0 : 15,
|
reserved_0 : 15,
|
||||||
reserved_1 : 24,
|
reserved_1 : 17,
|
||||||
|
virt_destid_8_14 : 7,
|
||||||
destid_0_7 : 8;
|
destid_0_7 : 8;
|
||||||
};
|
};
|
||||||
struct {
|
struct {
|
||||||
|
|
|
@ -1238,9 +1238,10 @@ static void io_apic_print_entries(unsigned int apic, unsigned int nr_entries)
|
||||||
(entry.ir_index_15 << 15) | entry.ir_index_0_14,
|
(entry.ir_index_15 << 15) | entry.ir_index_0_14,
|
||||||
entry.ir_zero);
|
entry.ir_zero);
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_DEBUG "%s, %s, D(%02X), M(%1d)\n", buf,
|
printk(KERN_DEBUG "%s, %s, D(%02X%02X), M(%1d)\n", buf,
|
||||||
entry.dest_mode_logical ? "logical " : "physical",
|
entry.dest_mode_logical ? "logical " : "physical",
|
||||||
entry.destid_0_7, entry.delivery_mode);
|
entry.virt_destid_8_14, entry.destid_0_7,
|
||||||
|
entry.delivery_mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1409,6 +1410,7 @@ void native_restore_boot_irq_mode(void)
|
||||||
*/
|
*/
|
||||||
if (ioapic_i8259.pin != -1) {
|
if (ioapic_i8259.pin != -1) {
|
||||||
struct IO_APIC_route_entry entry;
|
struct IO_APIC_route_entry entry;
|
||||||
|
u32 apic_id = read_apic_id();
|
||||||
|
|
||||||
memset(&entry, 0, sizeof(entry));
|
memset(&entry, 0, sizeof(entry));
|
||||||
entry.masked = false;
|
entry.masked = false;
|
||||||
|
@ -1416,7 +1418,8 @@ void native_restore_boot_irq_mode(void)
|
||||||
entry.active_low = false;
|
entry.active_low = false;
|
||||||
entry.dest_mode_logical = false;
|
entry.dest_mode_logical = false;
|
||||||
entry.delivery_mode = APIC_DELIVERY_MODE_EXTINT;
|
entry.delivery_mode = APIC_DELIVERY_MODE_EXTINT;
|
||||||
entry.destid_0_7 = read_apic_id();
|
entry.destid_0_7 = apic_id & 0xFF;
|
||||||
|
entry.virt_destid_8_14 = apic_id >> 8;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Add it to the IO-APIC irq-routing table:
|
* Add it to the IO-APIC irq-routing table:
|
||||||
|
@ -1885,7 +1888,11 @@ static void ioapic_setup_msg_from_msi(struct irq_data *irq_data,
|
||||||
/* DMAR/IR: 1, 0 for all other modes */
|
/* DMAR/IR: 1, 0 for all other modes */
|
||||||
entry->ir_format = msg.arch_addr_lo.dmar_format;
|
entry->ir_format = msg.arch_addr_lo.dmar_format;
|
||||||
/*
|
/*
|
||||||
* DMAR/IR: index bit 0-14.
|
* - DMAR/IR: index bit 0-14.
|
||||||
|
*
|
||||||
|
* - Virt: If the host supports x2apic without a virtualized IR
|
||||||
|
* unit then bit 0-6 of dmar_index_0_14 are providing bit
|
||||||
|
* 8-14 of the destination id.
|
||||||
*
|
*
|
||||||
* All other modes have bit 0-6 of dmar_index_0_14 cleared and the
|
* All other modes have bit 0-6 of dmar_index_0_14 cleared and the
|
||||||
* topmost 8 bits are destination id bit 0-7 (entry::destid_0_7).
|
* topmost 8 bits are destination id bit 0-7 (entry::destid_0_7).
|
||||||
|
@ -2063,6 +2070,7 @@ static inline void __init unlock_ExtINT_logic(void)
|
||||||
int apic, pin, i;
|
int apic, pin, i;
|
||||||
struct IO_APIC_route_entry entry0, entry1;
|
struct IO_APIC_route_entry entry0, entry1;
|
||||||
unsigned char save_control, save_freq_select;
|
unsigned char save_control, save_freq_select;
|
||||||
|
u32 apic_id;
|
||||||
|
|
||||||
pin = find_isa_irq_pin(8, mp_INT);
|
pin = find_isa_irq_pin(8, mp_INT);
|
||||||
if (pin == -1) {
|
if (pin == -1) {
|
||||||
|
@ -2078,11 +2086,13 @@ static inline void __init unlock_ExtINT_logic(void)
|
||||||
entry0 = ioapic_read_entry(apic, pin);
|
entry0 = ioapic_read_entry(apic, pin);
|
||||||
clear_IO_APIC_pin(apic, pin);
|
clear_IO_APIC_pin(apic, pin);
|
||||||
|
|
||||||
|
apic_id = hard_smp_processor_id();
|
||||||
memset(&entry1, 0, sizeof(entry1));
|
memset(&entry1, 0, sizeof(entry1));
|
||||||
|
|
||||||
entry1.dest_mode_logical = true;
|
entry1.dest_mode_logical = true;
|
||||||
entry1.masked = false;
|
entry1.masked = false;
|
||||||
entry1.destid_0_7 = hard_smp_processor_id();
|
entry1.destid_0_7 = apic_id & 0xFF;
|
||||||
|
entry1.virt_destid_8_14 = apic_id >> 8;
|
||||||
entry1.delivery_mode = APIC_DELIVERY_MODE_EXTINT;
|
entry1.delivery_mode = APIC_DELIVERY_MODE_EXTINT;
|
||||||
entry1.active_low = entry0.active_low;
|
entry1.active_low = entry0.active_low;
|
||||||
entry1.is_level = false;
|
entry1.is_level = false;
|
||||||
|
|
Loading…
Add table
Reference in a new issue