# HG changeset patch # User Keir Fraser # Date 1281367965 -3600 # Node ID add40eb478680b6f8de7102e87fba259f721ce1d # Parent fe930e1b2ce8f205fb368d0cc86876cc54d761a9 vt-d: Fix ioapic write order in io_apic_write_remap_rte At the end of io_apic_write_remap_rte, it writes new entry (remapped interrupt) to ioapic. But it writes low 32 bits before high 32 bits, it unmasks interrupt before writing high 32 bits if 'mask' bit in low 32 bits is cleared. Thus it may result in issues. This patch fixes this issue by writing high 32 bits before low 32 bits. Signed-off-by: Jiang, Yunhong Signed-off-by: Weidong Han # HG changeset patch # User Keir Fraser # Date 1281368025 -3600 # Node ID befd1814c0a262ce0d6c96727a76b907cdeecdc4 # Parent add40eb478680b6f8de7102e87fba259f721ce1d vt-d: Fix ioapic_rte_to_remap_entry error path. When ioapic_rte_to_remap_entry fails, currently it just writes value to ioapic. But the 'mask' bit may be changed if it writes to the upper half of RTE. This patch ensures to recover the original value of 'mask' bit in this case. Signed-off-by: Weidong Han --- a/xen/drivers/passthrough/vtd/intremap.c +++ b/xen/drivers/passthrough/vtd/intremap.c @@ -438,14 +438,21 @@ void io_apic_write_remap_rte( { *IO_APIC_BASE(apic) = rte_upper ? (reg + 1) : reg; *(IO_APIC_BASE(apic)+4) = value; + + /* Recover the original value of 'mask' bit */ + if ( rte_upper ) + { + *IO_APIC_BASE(apic) = reg; + *(IO_APIC_BASE(apic)+4) = *(((u32 *)&old_rte)+0); + } return; } /* write new entry to ioapic */ - *IO_APIC_BASE(apic) = reg; - *(IO_APIC_BASE(apic)+4) = *(((u32 *)&old_rte)+0); *IO_APIC_BASE(apic) = reg + 1; *(IO_APIC_BASE(apic)+4) = *(((u32 *)&old_rte)+1); + *IO_APIC_BASE(apic) = reg; + *(IO_APIC_BASE(apic)+4) = *(((u32 *)&old_rte)+0); } #if defined(__i386__) || defined(__x86_64__)