x2apic_phys = !iommu_intremap ||
(acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL);
}
- else if ( !x2apic_phys && !iommu_intremap )
- {
- printk("WARNING: x2APIC cluster mode is not supported without interrupt remapping\n"
- "x2APIC: forcing phys mode\n");
- x2apic_phys = true;
- }
+ else if ( !x2apic_phys )
+ switch ( iommu_intremap )
+ {
+ case iommu_intremap_off:
+ case iommu_intremap_restricted:
+ printk("WARNING: x2APIC cluster mode is not supported %s interrupt remapping -"
+ " forcing phys mode\n",
+ iommu_intremap == iommu_intremap_off ? "without"
+ : "with restricted");
+ x2apic_phys = true;
+ break;
+
+ case iommu_intremap_full:
+ break;
+ }
if ( x2apic_phys )
return &apic_x2apic_phys;
iommu_enabled = 0;
iommu_hwdom_passthrough = false;
- iommu_intremap = 0;
+ iommu_intremap = iommu_intremap_off;
iommuv2_enabled = 0;
}
iommu->ctrl.int_cap_xt_en = xt && has_xt;
}
+ if ( iommu_intremap && !has_xt )
+ iommu_intremap = iommu_intremap_restricted;
+
rc = amd_iommu_update_ivrs_mapping_acpi();
error_out:
if ( (amd_iommu_detect_acpi() !=0) || (iommu_found() == 0) )
{
- iommu_intremap = 0;
+ iommu_intremap = iommu_intremap_off;
return -ENODEV;
}
bool_t __read_mostly iommu_igfx = 1;
bool_t __read_mostly iommu_snoop = 1;
bool_t __read_mostly iommu_qinval = 1;
-bool_t __read_mostly iommu_intremap = 1;
+enum iommu_intremap __read_mostly iommu_intremap = iommu_intremap_full;
bool_t __read_mostly iommu_crash_disable;
static bool __hwdom_initdata iommu_hwdom_none;
else if ( (val = parse_boolean("qinval", s, ss)) >= 0 )
iommu_qinval = val;
else if ( (val = parse_boolean("intremap", s, ss)) >= 0 )
- iommu_intremap = val;
+ iommu_intremap = val ? iommu_intremap_full : iommu_intremap_off;
else if ( (val = parse_boolean("intpost", s, ss)) >= 0 )
iommu_intpost = val;
#ifdef CONFIG_KEXEC
iommu_enabled = (rc == 0);
}
if ( !iommu_enabled )
- iommu_intremap = 0;
+ iommu_intremap = iommu_intremap_off;
if ( (force_iommu && !iommu_enabled) ||
(force_intremap && !iommu_intremap) )
if ( iommu_enabled )
iommu_get_ops()->crash_shutdown();
- iommu_enabled = iommu_intremap = iommu_intpost = 0;
+ iommu_enabled = iommu_intpost = 0;
+ iommu_intremap = iommu_intremap_off;
}
int iommu_get_reserved_device_memory(iommu_grdm_t *func, void *ctxt)
{
if ( ioapic_to_iommu(IO_APIC_ID(apic)) == NULL )
{
- iommu_intremap = 0;
+ iommu_intremap = iommu_intremap_off;
dprintk(XENLOG_ERR VTDPREFIX,
"ioapic_to_iommu: ioapic %#x (id: %#x) is NULL! "
"Will not try to enable Interrupt Remapping.\n",
iommu = drhd->iommu;
if ( enable_intremap(iommu, 0) != 0 )
{
- iommu_intremap = 0;
+ iommu_intremap = iommu_intremap_off;
dprintk(XENLOG_WARNING VTDPREFIX,
"Interrupt Remapping not enabled\n");
iommu_qinval = 0;
if ( iommu_intremap && !ecap_intr_remap(iommu->ecap) )
- iommu_intremap = 0;
+ iommu_intremap = iommu_intremap_off;
/*
* We cannot use posted interrupt if X86_FEATURE_CX16 is
if ( !iommu_qinval && iommu_intremap )
{
- iommu_intremap = 0;
+ iommu_intremap = iommu_intremap_off;
dprintk(XENLOG_WARNING VTDPREFIX, "Interrupt Remapping disabled "
"since Queued Invalidation isn't supported or enabled.\n");
}
iommu_snoop = 0;
iommu_hwdom_passthrough = false;
iommu_qinval = 0;
- iommu_intremap = 0;
+ iommu_intremap = iommu_intremap_off;
iommu_intpost = 0;
return ret;
}
extern bool_t iommu_enable, iommu_enabled;
extern bool force_iommu, iommu_quarantine, iommu_verbose, iommu_igfx;
-extern bool_t iommu_snoop, iommu_qinval, iommu_intremap, iommu_intpost;
+extern bool_t iommu_snoop, iommu_qinval, iommu_intpost;
+extern enum __packed iommu_intremap {
+ /*
+ * In order to allow traditional boolean uses of the iommu_intremap
+ * variable, the "off" value has to come first (yielding a value of zero).
+ */
+ iommu_intremap_off,
+#ifdef CONFIG_X86
+ /*
+ * Interrupt remapping enabled, but only able to generate interrupts
+ * with an 8-bit APIC ID.
+ */
+ iommu_intremap_restricted,
+#endif
+ iommu_intremap_full,
+} iommu_intremap;
#if defined(CONFIG_IOMMU_FORCE_PT_SHARE)
#define iommu_hap_pt_share true