195 lines
5.5 KiB
Diff
195 lines
5.5 KiB
Diff
|
# HG changeset patch
|
||
|
# User Allen Kay <allen.m.kay@intel.com>
|
||
|
# Date 1301755765 -3600
|
||
|
# Node ID 1046830079376a4b29fcad0cd037a834e808ed06
|
||
|
# Parent 89c23f58aa986092da0c9a7dfac1c41befbe1f3f
|
||
|
[VTD] check BIOS settings before enabling interrupt remapping or x2apic
|
||
|
|
||
|
Check flags field in ACPI DMAR structure before enabling interrupt
|
||
|
remapping or x2apic. This allows platform vendors to disable
|
||
|
interrupt remapping or x2apic features if on board BIOS does not
|
||
|
support them.
|
||
|
|
||
|
Signed-off-by: Allen Kay <allen.m.kay@intel.com>
|
||
|
|
||
|
# HG changeset patch
|
||
|
# User Allen Kay <allen.m.kay@intel.com>
|
||
|
# Date 1302077462 -3600
|
||
|
# Node ID c7916d6f4dfba9d6c7eeb0fc2796068d75e2fb4a
|
||
|
# Parent 42fa70e0761bbb0596618ca5323664f31a2faa76
|
||
|
[VTD] Fixes to ACPI DMAR flag checks.
|
||
|
|
||
|
* platform_supports_{intremap,x2apic} should not be marked __init as
|
||
|
they are used during S3 resume.
|
||
|
* DMAR flags should be taken from the table passed to
|
||
|
acpi_parse_dmar() -- this is the trusted copy of the DMAR, when
|
||
|
running in TXT mode.
|
||
|
|
||
|
Signed-off-by: Allen Kay <allen.m.kay@intel.com>
|
||
|
|
||
|
--- a/xen/arch/x86/apic.c
|
||
|
+++ b/xen/arch/x86/apic.c
|
||
|
@@ -531,7 +531,7 @@ static void resume_x2apic(void)
|
||
|
mask_8259A();
|
||
|
mask_IO_APIC_setup(ioapic_entries);
|
||
|
|
||
|
- iommu_enable_IR();
|
||
|
+ iommu_enable_x2apic_IR();
|
||
|
__enable_x2apic();
|
||
|
|
||
|
restore_IO_APIC_setup(ioapic_entries);
|
||
|
@@ -751,7 +751,7 @@ int lapic_suspend(void)
|
||
|
|
||
|
local_irq_save(flags);
|
||
|
disable_local_APIC();
|
||
|
- iommu_disable_IR();
|
||
|
+ iommu_disable_x2apic_IR();
|
||
|
local_irq_restore(flags);
|
||
|
return 0;
|
||
|
}
|
||
|
@@ -997,7 +997,7 @@ void __init x2apic_bsp_setup(void)
|
||
|
mask_8259A();
|
||
|
mask_IO_APIC_setup(ioapic_entries);
|
||
|
|
||
|
- if ( iommu_enable_IR() )
|
||
|
+ if ( iommu_enable_x2apic_IR() )
|
||
|
{
|
||
|
if ( x2apic_enabled )
|
||
|
panic("Interrupt remapping could not be enabled while "
|
||
|
--- a/xen/drivers/passthrough/vtd/dmar.c
|
||
|
+++ b/xen/drivers/passthrough/vtd/dmar.c
|
||
|
@@ -46,6 +46,7 @@ LIST_HEAD(acpi_rmrr_units);
|
||
|
LIST_HEAD(acpi_atsr_units);
|
||
|
LIST_HEAD(acpi_rhsa_units);
|
||
|
|
||
|
+static int __read_mostly dmar_flags;
|
||
|
static u64 igd_drhd_address;
|
||
|
u8 dmar_host_address_width;
|
||
|
|
||
|
@@ -682,6 +683,7 @@ static int __init acpi_parse_dmar(struct
|
||
|
int ret = 0;
|
||
|
|
||
|
dmar = (struct acpi_table_dmar *)table;
|
||
|
+ dmar_flags = dmar->flags;
|
||
|
|
||
|
if ( !iommu_enabled )
|
||
|
{
|
||
|
@@ -802,3 +804,22 @@ void acpi_dmar_zap(void)
|
||
|
dmar_table->signature[0] = 'X';
|
||
|
dmar_table->checksum -= 'X'-'D';
|
||
|
}
|
||
|
+
|
||
|
+int platform_supports_intremap(void)
|
||
|
+{
|
||
|
+ unsigned int flags = 0;
|
||
|
+
|
||
|
+ flags = DMAR_INTR_REMAP;
|
||
|
+ return ((dmar_flags & flags) == DMAR_INTR_REMAP);
|
||
|
+}
|
||
|
+
|
||
|
+int platform_supports_x2apic(void)
|
||
|
+{
|
||
|
+ unsigned int flags = 0;
|
||
|
+
|
||
|
+ if (!cpu_has_x2apic)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ flags = DMAR_INTR_REMAP | DMAR_X2APIC_OPT_OUT;
|
||
|
+ return ((dmar_flags & flags) == DMAR_INTR_REMAP);
|
||
|
+}
|
||
|
--- a/xen/drivers/passthrough/vtd/extern.h
|
||
|
+++ b/xen/drivers/passthrough/vtd/extern.h
|
||
|
@@ -87,5 +87,7 @@ void vtd_ops_preamble_quirk(struct iommu
|
||
|
void vtd_ops_postamble_quirk(struct iommu* iommu);
|
||
|
void me_wifi_quirk(struct domain *domain, u8 bus, u8 devfn, int map);
|
||
|
void pci_vtd_quirk(struct pci_dev *pdev);
|
||
|
+int platform_supports_intremap(void);
|
||
|
+int platform_supports_x2apic(void);
|
||
|
|
||
|
#endif // _VTD_EXTERN_H_
|
||
|
--- a/xen/drivers/passthrough/vtd/intremap.c
|
||
|
+++ b/xen/drivers/passthrough/vtd/intremap.c
|
||
|
@@ -735,6 +735,13 @@ int enable_intremap(struct iommu *iommu,
|
||
|
|
||
|
ASSERT(ecap_intr_remap(iommu->ecap) && iommu_intremap);
|
||
|
|
||
|
+ if ( !platform_supports_intremap() )
|
||
|
+ {
|
||
|
+ dprintk(XENLOG_ERR VTDPREFIX,
|
||
|
+ "Platform firmware does not support interrupt remapping\n");
|
||
|
+ return -EINVAL;
|
||
|
+ }
|
||
|
+
|
||
|
ir_ctrl = iommu_ir_ctrl(iommu);
|
||
|
sts = dmar_readl(iommu->reg, DMAR_GSTS_REG);
|
||
|
|
||
|
@@ -821,10 +828,10 @@ out:
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
- * This function is used to enable Interrutp remapping when
|
||
|
+ * This function is used to enable Interrupt remapping when
|
||
|
* enable x2apic
|
||
|
*/
|
||
|
-int iommu_enable_IR(void)
|
||
|
+int iommu_enable_x2apic_IR(void)
|
||
|
{
|
||
|
struct acpi_drhd_unit *drhd;
|
||
|
struct iommu *iommu;
|
||
|
@@ -832,6 +839,9 @@ int iommu_enable_IR(void)
|
||
|
if ( !iommu_supports_eim() )
|
||
|
return -1;
|
||
|
|
||
|
+ if ( !platform_supports_x2apic() )
|
||
|
+ return -1;
|
||
|
+
|
||
|
for_each_drhd_unit ( drhd )
|
||
|
{
|
||
|
struct qi_ctrl *qi_ctrl = NULL;
|
||
|
@@ -881,7 +891,7 @@ int iommu_enable_IR(void)
|
||
|
* This function is used to disable Interrutp remapping when
|
||
|
* suspend local apic
|
||
|
*/
|
||
|
-void iommu_disable_IR(void)
|
||
|
+void iommu_disable_x2apic_IR(void)
|
||
|
{
|
||
|
struct acpi_drhd_unit *drhd;
|
||
|
|
||
|
--- a/xen/drivers/passthrough/vtd/iommu.c
|
||
|
+++ b/xen/drivers/passthrough/vtd/iommu.c
|
||
|
@@ -2014,7 +2014,7 @@ static int init_vtd_hw(void)
|
||
|
if ( enable_intremap(iommu, 0) != 0 )
|
||
|
{
|
||
|
dprintk(XENLOG_WARNING VTDPREFIX,
|
||
|
- "Failed to enable Interrupt Remapping!\n");
|
||
|
+ "Interrupt Remapping not enabled\n");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
--- a/xen/drivers/passthrough/vtd/iommu.h
|
||
|
+++ b/xen/drivers/passthrough/vtd/iommu.h
|
||
|
@@ -22,6 +22,10 @@
|
||
|
|
||
|
#include <xen/types.h>
|
||
|
|
||
|
+/* DMAR Flags bits */
|
||
|
+#define DMAR_INTR_REMAP 0x1
|
||
|
+#define DMAR_X2APIC_OPT_OUT 0x2
|
||
|
+
|
||
|
/*
|
||
|
* Intel IOMMU register specification per version 1.0 public spec.
|
||
|
*/
|
||
|
--- a/xen/include/xen/iommu.h
|
||
|
+++ b/xen/include/xen/iommu.h
|
||
|
@@ -63,8 +63,8 @@ struct iommu {
|
||
|
|
||
|
int iommu_setup(void);
|
||
|
int iommu_supports_eim(void);
|
||
|
-int iommu_enable_IR(void);
|
||
|
-void iommu_disable_IR(void);
|
||
|
+int iommu_enable_x2apic_IR(void);
|
||
|
+void iommu_disable_x2apic_IR(void);
|
||
|
|
||
|
int iommu_add_device(struct pci_dev *pdev);
|
||
|
int iommu_remove_device(struct pci_dev *pdev);
|