{
struct IO_APIC_route_entry **ioapic_entries = NULL;
const char *orig_name;
+ bool intremap_enabled;
if ( !cpu_has_x2apic )
return;
switch ( iommu_enable_x2apic() )
{
case 0:
+ intremap_enabled = true;
break;
case -ENXIO: /* ACPI_DMAR_X2APIC_OPT_OUT set */
if ( !x2apic_enabled )
{
printk("Not enabling x2APIC (upon firmware request)\n");
+ intremap_enabled = false;
goto restore_out;
}
/* fall through */
printk(XENLOG_ERR
"Failed to enable Interrupt Remapping: Will not enable x2APIC.\n");
+ intremap_enabled = false;
goto restore_out;
}
printk("Switched to APIC driver %s\n", genapic.name);
restore_out:
- restore_IO_APIC_setup(ioapic_entries);
+ /*
+ * NB: do not use raw mode when restoring entries if the iommu has been
+ * enabled during the process, because the entries need to be translated
+ * and added to the remapping table in that case.
+ */
+ restore_IO_APIC_setup(ioapic_entries, !intremap_enabled);
unmask_8259A();
out:
/*
* Restore IO APIC entries which was saved in ioapic_entries.
*/
-int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries)
+int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries,
+ bool raw)
{
int apic, pin;
return -ENOMEM;
for (pin = 0; pin < nr_ioapic_entries[apic]; pin++)
- ioapic_write_entry(apic, pin, 1, ioapic_entries[apic][pin]);
+ ioapic_write_entry(apic, pin, raw, ioapic_entries[apic][pin]);
}
return 0;
extern void free_ioapic_entries(struct IO_APIC_route_entry **ioapic_entries);
extern int save_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
extern void mask_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
-extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries);
+extern int restore_IO_APIC_setup(struct IO_APIC_route_entry **ioapic_entries,
+ bool raw);
unsigned highest_gsi(void);