# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1252309563 -3600
# Node ID cb249398f3eff1560b2a4934b0da08ec6b355eba
# Parent be45bf6fe25135cf704d9621faa1742cc7f74e7e
vt-d: use 32-bit Destination ID when Interrupt Remapping with EIM is
enabled
When x2APIC and Interrupt Remapping(IR) with EIM are enabled, we
should use 32-bit Destination ID for IOAPIC and MSI.
We implemented the IR support in xen by hooking the functions like
io_apic_write(),io_apic_modify(), write_msi_message(), and as a
result, in the hook functions in intremap.c, we can only see the 8-bit
dest id rather the 32-bit id, so we can't set IR table Entry that
requires a 32-bit dest id.
To solve the issue throughly, we need find every place in io_apic.c
and msi.c that could write ioapic RTE and and device's msi message and
explicitly handle the 32-bit dest id carefully (namely, when genapic
is x2apic, cpu_mask_to_apic could return a 32-bit value); and we have
to change the iommu_ops->{.update_ire_from_apic, .update_ire_from_msi}
interfaces. We may have to write an over-1000-LOC patch for this.
Instead, we could use a workround:
1) for ioapic, in the struct IO_APIC_route_entry, we could use a new
"dest32" to refer to the dest field;
2) for msi, in the struct msi_msg, we could add a new "u32 dest".
And in intremap.c, if x2apic_enabled, we use the new names to refer to
the dest fields.
We can improve this in future.
Signed-off-by: Dexuan Cui <dexuan.cui@xxxxxxxxx>
---
xen/arch/x86/io_apic.c | 28 +++++++++++++++++-----------
xen/arch/x86/msi.c | 2 ++
xen/drivers/passthrough/vtd/intremap.c | 12 +++++++++---
xen/include/asm-x86/io_apic.h | 3 +++
xen/include/asm-x86/msi.h | 1 +
5 files changed, 32 insertions(+), 14 deletions(-)
diff -r be45bf6fe251 -r cb249398f3ef xen/arch/x86/io_apic.c
--- a/xen/arch/x86/io_apic.c Mon Sep 07 08:44:50 2009 +0100
+++ b/xen/arch/x86/io_apic.c Mon Sep 07 08:46:03 2009 +0100
@@ -355,8 +355,8 @@ set_ioapic_affinity_irq_desc(struct irq_
spin_lock_irqsave(&ioapic_lock, flags);
dest = set_desc_affinity(desc, mask);
if (dest != BAD_APICID) {
- /* Only the high 8 bits are valid. */
- dest = SET_APIC_LOGICAL_ID(dest);
+ if ( !x2apic_enabled )
+ dest = SET_APIC_LOGICAL_ID(dest);
entry = irq_2_pin + irq;
for (;;) {
unsigned int data;
@@ -769,6 +769,9 @@ static struct hw_interrupt_type ioapic_e
#define IOAPIC_AUTO -1
#define IOAPIC_EDGE 0
#define IOAPIC_LEVEL 1
+
+#define SET_DEST(x, y, value) \
+ do { if ( x2apic_enabled ) x = value; else y = value; } while(0)
static inline void ioapic_register_intr(int irq, unsigned long trigger)
{
@@ -845,8 +848,8 @@ static void __init setup_IO_APIC_irqs(vo
disable_8259A_irq(irq);
}
cfg = irq_cfg(irq);
- entry.dest.logical.logical_dest =
- cpu_mask_to_apicid(cfg->domain);
+ SET_DEST(entry.dest.dest32, entry.dest.logical.logical_dest,
+ cpu_mask_to_apicid(cfg->domain));
spin_lock_irqsave(&ioapic_lock, flags);
io_apic_write(apic, 0x11+2*pin, *(((int *)&entry)+1));
io_apic_write(apic, 0x10+2*pin, *(((int *)&entry)+0));
@@ -880,7 +883,8 @@ static void __init setup_ExtINT_IRQ0_pin
*/
entry.dest_mode = INT_DEST_MODE;
entry.mask = 0; /* unmask IRQ now */
- entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
+ SET_DEST(entry.dest.dest32, entry.dest.logical.logical_dest,
+ cpu_mask_to_apicid(TARGET_CPUS));
entry.delivery_mode = INT_DELIVERY_MODE;
entry.polarity = 0;
entry.trigger = 0;
@@ -1156,8 +1160,8 @@ void disable_IO_APIC(void)
entry.dest_mode = 0; /* Physical */
entry.delivery_mode = dest_ExtINT; /* ExtInt */
entry.vector = 0;
- entry.dest.physical.physical_dest =
- get_apic_id();
+ SET_DEST(entry.dest.dest32, entry.dest.physical.physical_dest,
+ get_apic_id());
/*
* Add it to the IO-APIC irq-routing table:
@@ -1667,7 +1671,8 @@ static inline void unlock_ExtINT_logic(v
entry1.dest_mode = 0; /* physical delivery */
entry1.mask = 0; /* unmask IRQ now */
- entry1.dest.physical.physical_dest = hard_smp_processor_id();
+ SET_DEST(entry1.dest.dest32, entry1.dest.physical.physical_dest,
+ hard_smp_processor_id());
entry1.delivery_mode = dest_ExtINT;
entry1.polarity = entry0.polarity;
entry1.trigger = 0;
@@ -2051,7 +2056,8 @@ int io_apic_set_pci_routing (int ioapic,
entry.delivery_mode = INT_DELIVERY_MODE;
entry.dest_mode = INT_DEST_MODE;
- entry.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
+ SET_DEST(entry.dest.dest32, entry.dest.logical.logical_dest,
+ cpu_mask_to_apicid(TARGET_CPUS));
entry.trigger = edge_level;
entry.polarity = active_high_low;
entry.mask = 1;
@@ -2230,8 +2236,8 @@ int ioapic_guest_write(unsigned long phy
/* Set the vector field to the real vector! */
rte.vector = cfg->vector;
- rte.dest.logical.logical_dest =
- cpu_mask_to_apicid(cfg->domain);
+ SET_DEST(rte.dest.dest32, rte.dest.logical.logical_dest,
+ cpu_mask_to_apicid(cfg->domain));
io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&rte) + 0));
io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&rte) + 1));
diff -r be45bf6fe251 -r cb249398f3ef xen/arch/x86/msi.c
--- a/xen/arch/x86/msi.c Mon Sep 07 08:44:50 2009 +0100
+++ b/xen/arch/x86/msi.c Mon Sep 07 08:46:03 2009 +0100
@@ -144,6 +144,7 @@ void msi_compose_msg(struct pci_dev *pde
MSI_ADDR_REDIRECTION_CPU:
MSI_ADDR_REDIRECTION_LOWPRI) |
MSI_ADDR_DEST_ID(dest);
+ msg->dest32 = dest;
msg->data =
MSI_DATA_TRIGGER_EDGE |
@@ -283,6 +284,7 @@ void set_msi_affinity(unsigned int irq,
msg.data |= MSI_DATA_VECTOR(cfg->vector);
msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
msg.address_lo |= MSI_ADDR_DEST_ID(dest);
+ msg.dest32 = dest;
write_msi_msg(msi_desc, &msg);
}
diff -r be45bf6fe251 -r cb249398f3ef xen/drivers/passthrough/vtd/intremap.c
--- a/xen/drivers/passthrough/vtd/intremap.c Mon Sep 07 08:44:50 2009 +0100
+++ b/xen/drivers/passthrough/vtd/intremap.c Mon Sep 07 08:46:03 2009 +0100
@@ -225,7 +225,10 @@ static int ioapic_rte_to_remap_entry(str
if ( rte_upper )
{
#if defined(__i386__) || defined(__x86_64__)
- new_ire.lo.dst = (value >> 24) << 8;
+ if ( x2apic_enabled )
+ new_ire.lo.dst = value;
+ else
+ new_ire.lo.dst = (value >> 24) << 8;
#else /* __ia64__ */
new_ire.lo.dst = value >> 16;
#endif
@@ -552,8 +555,11 @@ static int msi_msg_to_remap_entry(
new_ire.lo.vector = (msg->data >> MSI_DATA_VECTOR_SHIFT) &
MSI_DATA_VECTOR_MASK;
new_ire.lo.res_2 = 0;
- new_ire.lo.dst = ((msg->address_lo >> MSI_ADDR_DEST_ID_SHIFT)
- & 0xff) << 8;
+ if ( x2apic_enabled )
+ new_ire.lo.dst = msg->dest32;
+ else
+ new_ire.lo.dst = ((msg->address_lo >> MSI_ADDR_DEST_ID_SHIFT)
+ & 0xff) << 8;
set_msi_source_id(pdev, &new_ire);
new_ire.hi.res_1 = 0;
diff -r be45bf6fe251 -r cb249398f3ef xen/include/asm-x86/io_apic.h
--- a/xen/include/asm-x86/io_apic.h Mon Sep 07 08:44:50 2009 +0100
+++ b/xen/include/asm-x86/io_apic.h Mon Sep 07 08:46:03 2009 +0100
@@ -105,6 +105,9 @@ struct IO_APIC_route_entry {
__reserved_1 : 24,
logical_dest : 8;
} logical;
+
+ /* used when Interrupt Remapping with EIM is enabled */
+ __u32 dest32;
} dest;
} __attribute__ ((packed));
diff -r be45bf6fe251 -r cb249398f3ef xen/include/asm-x86/msi.h
--- a/xen/include/asm-x86/msi.h Mon Sep 07 08:44:50 2009 +0100
+++ b/xen/include/asm-x86/msi.h Mon Sep 07 08:46:03 2009 +0100
@@ -65,6 +65,7 @@ struct msi_msg {
u32 address_lo; /* low 32 bits of msi message address */
u32 address_hi; /* high 32 bits of msi message address */
u32 data; /* 16 bits of msi message data */
+ u32 dest32; /* used when Interrupt Remapping with EIM is
enabled */
};
struct msi_desc;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|