From 41750d31fc9599fd81763e685a6b7b42d298c4f8 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 23 Aug 2011 17:05:18 -0700 Subject: x86, x2apic: Enable the bios request for x2apic optout On the platforms which are x2apic and interrupt-remapping capable, Linux kernel is enabling x2apic even if the BIOS doesn't. This is to take advantage of the features that x2apic brings in. Some of the OEM platforms are running into issues because of this, as their bios is not x2apic aware. For example, this was resulting in interrupt migration issues on one of the platforms. Also if the BIOS SMI handling uses APIC interface to send SMI's, then the BIOS need to be aware of x2apic mode that OS has enabled. On some of these platforms, BIOS doesn't have a HW mechanism to turnoff the x2apic feature to prevent OS from enabling it. To resolve this mess, recent changes to the VT-d2 specification: http://download.intel.com/technology/computing/vptech/Intel(r)_VT_for_Direct_IO.pdf includes a mechanism that provides BIOS a way to request system software to opt out of enabling x2apic mode. Look at the x2apic optout flag in the DMAR tables before enabling the x2apic mode in the platform. Also print a warning that we have disabled x2apic based on the BIOS request. Kernel boot parameter "intremap=no_x2apic_optout" can be used to override the BIOS x2apic optout request. Signed-off-by: Youquan Song Signed-off-by: Suresh Siddha Cc: yinghai@kernel.org Cc: joerg.roedel@amd.com Cc: tony.luck@intel.com Cc: dwmw2@infradead.org Link: http://lkml.kernel.org/r/20110824001456.171766616@sbsiddha-desk.sc.intel.com Signed-off-by: Ingo Molnar --- include/linux/dmar.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/dmar.h b/include/linux/dmar.h index 7b776d7..2dc810e 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -26,8 +26,13 @@ #include #include +/* DMAR Flags */ +#define DMAR_INTR_REMAP 0x1 +#define DMAR_X2APIC_OPT_OUT 0x2 + struct intel_iommu; #if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP) +extern struct acpi_table_header *dmar_tbl; struct dmar_drhd_unit { struct list_head list; /* list of drhd units */ struct acpi_dmar_header *hdr; /* ACPI header */ @@ -110,7 +115,7 @@ struct irte { #ifdef CONFIG_INTR_REMAP extern int intr_remapping_enabled; extern int intr_remapping_supported(void); -extern int enable_intr_remapping(int); +extern int enable_intr_remapping(void); extern void disable_intr_remapping(void); extern int reenable_intr_remapping(int); @@ -177,7 +182,7 @@ static inline int set_msi_sid(struct irte *irte, struct pci_dev *dev) #define intr_remapping_enabled (0) -static inline int enable_intr_remapping(int eim) +static inline int enable_intr_remapping(void) { return -1; } @@ -192,6 +197,11 @@ static inline int reenable_intr_remapping(int eim) } #endif +enum { + IRQ_REMAP_XAPIC_MODE, + IRQ_REMAP_X2APIC_MODE, +}; + /* Can't use the common MSI interrupt functions * since DMAR is not a pci device */ -- cgit v1.1 From 318fe7df9d8456f778451b01913b5d0dc0a25854 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 23 Aug 2011 17:05:20 -0700 Subject: iommu: Move IOMMU specific code to intel-iommu.c Move the IOMMU specific routines to intel-iommu.c leaving the dmar.c to the common ACPI dmar code shared between DMA-remapping and Interrupt-remapping. Signed-off-by: Suresh Siddha Cc: yinghai@kernel.org Cc: youquan.song@intel.com Cc: joerg.roedel@amd.com Cc: tony.luck@intel.com Cc: dwmw2@infradead.org Link: http://lkml.kernel.org/r/20110824001456.282401285@sbsiddha-desk.sc.intel.com Signed-off-by: Ingo Molnar --- include/linux/dma_remapping.h | 5 ++++- include/linux/dmar.h | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/dma_remapping.h b/include/linux/dma_remapping.h index bbd8661..aaa12cb 100644 --- a/include/linux/dma_remapping.h +++ b/include/linux/dma_remapping.h @@ -25,9 +25,9 @@ struct intel_iommu; struct dmar_domain; struct root_entry; -extern void free_dmar_iommu(struct intel_iommu *iommu); #ifdef CONFIG_DMAR +extern void free_dmar_iommu(struct intel_iommu *iommu); extern int iommu_calculate_agaw(struct intel_iommu *iommu); extern int iommu_calculate_max_sagaw(struct intel_iommu *iommu); #else @@ -39,6 +39,9 @@ static inline int iommu_calculate_max_sagaw(struct intel_iommu *iommu) { return 0; } +static inline void free_dmar_iommu(struct intel_iommu *iommu) +{ +} #endif extern int dmar_disabled; diff --git a/include/linux/dmar.h b/include/linux/dmar.h index 2dc810e..a7992ec 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -237,9 +237,26 @@ struct dmar_atsr_unit { u8 include_all:1; /* include all ports */ }; +int dmar_parse_rmrr_atsr_dev(void); +extern int dmar_parse_one_rmrr(struct acpi_dmar_header *header); +extern int dmar_parse_one_atsr(struct acpi_dmar_header *header); +extern int dmar_parse_dev_scope(void *start, void *end, int *cnt, + struct pci_dev ***devices, u16 segment); extern int intel_iommu_init(void); #else /* !CONFIG_DMAR: */ static inline int intel_iommu_init(void) { return -ENODEV; } +static inline int dmar_parse_one_rmrr(struct acpi_dmar_header *header) +{ + return 0; +} +static inline int dmar_parse_one_atsr(struct acpi_dmar_header *header) +{ + return 0; +} +static inline int dmar_parse_rmrr_atsr_dev(void) +{ + return 0; +} #endif /* CONFIG_DMAR */ #endif /* __DMAR_H__ */ -- cgit v1.1 From f5d1b97bcdd8ac195f48c645bffcb88bcea533e4 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 23 Aug 2011 17:05:22 -0700 Subject: iommu: Cleanup ifdefs in detect_intel_iommu() Signed-off-by: Suresh Siddha Cc: yinghai@kernel.org Cc: youquan.song@intel.com Cc: joerg.roedel@amd.com Cc: tony.luck@intel.com Cc: dwmw2@infradead.org Link: http://lkml.kernel.org/r/20110824001456.386003047@sbsiddha-desk.sc.intel.com Signed-off-by: Ingo Molnar --- include/linux/dma_remapping.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/dma_remapping.h b/include/linux/dma_remapping.h index aaa12cb..b98b61b 100644 --- a/include/linux/dma_remapping.h +++ b/include/linux/dma_remapping.h @@ -30,6 +30,7 @@ struct root_entry; extern void free_dmar_iommu(struct intel_iommu *iommu); extern int iommu_calculate_agaw(struct intel_iommu *iommu); extern int iommu_calculate_max_sagaw(struct intel_iommu *iommu); +extern int dmar_disabled; #else static inline int iommu_calculate_agaw(struct intel_iommu *iommu) { @@ -42,8 +43,8 @@ static inline int iommu_calculate_max_sagaw(struct intel_iommu *iommu) static inline void free_dmar_iommu(struct intel_iommu *iommu) { } +#define dmar_disabled (1) #endif -extern int dmar_disabled; #endif -- cgit v1.1 From d3f138106b4b40640dc667f0222fd9f137387b32 Mon Sep 17 00:00:00 2001 From: Suresh Siddha Date: Tue, 23 Aug 2011 17:05:25 -0700 Subject: iommu: Rename the DMAR and INTR_REMAP config options Change the CONFIG_DMAR to CONFIG_INTEL_IOMMU to be consistent with the other IOMMU options. Rename the CONFIG_INTR_REMAP to CONFIG_IRQ_REMAP to match the irq subsystem name. And define the CONFIG_DMAR_TABLE for the common ACPI DMAR routines shared by both CONFIG_INTEL_IOMMU and CONFIG_IRQ_REMAP. Signed-off-by: Suresh Siddha Cc: yinghai@kernel.org Cc: youquan.song@intel.com Cc: joerg.roedel@amd.com Cc: tony.luck@intel.com Cc: dwmw2@infradead.org Link: http://lkml.kernel.org/r/20110824001456.558630224@sbsiddha-desk.sc.intel.com Signed-off-by: Ingo Molnar --- include/linux/dma_remapping.h | 2 +- include/linux/dmar.h | 12 ++++++------ include/linux/intel-iommu.h | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/include/linux/dma_remapping.h b/include/linux/dma_remapping.h index b98b61b..ef90cbd 100644 --- a/include/linux/dma_remapping.h +++ b/include/linux/dma_remapping.h @@ -26,7 +26,7 @@ struct dmar_domain; struct root_entry; -#ifdef CONFIG_DMAR +#ifdef CONFIG_INTEL_IOMMU extern void free_dmar_iommu(struct intel_iommu *iommu); extern int iommu_calculate_agaw(struct intel_iommu *iommu); extern int iommu_calculate_max_sagaw(struct intel_iommu *iommu); diff --git a/include/linux/dmar.h b/include/linux/dmar.h index a7992ec..a8b1a84 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h @@ -31,7 +31,7 @@ #define DMAR_X2APIC_OPT_OUT 0x2 struct intel_iommu; -#if defined(CONFIG_DMAR) || defined(CONFIG_INTR_REMAP) +#ifdef CONFIG_DMAR_TABLE extern struct acpi_table_header *dmar_tbl; struct dmar_drhd_unit { struct list_head list; /* list of drhd units */ @@ -81,7 +81,7 @@ static inline int enable_drhd_fault_handling(void) { return -1; } -#endif /* !CONFIG_DMAR && !CONFIG_INTR_REMAP */ +#endif /* !CONFIG_DMAR_TABLE */ struct irte { union { @@ -112,7 +112,7 @@ struct irte { }; }; -#ifdef CONFIG_INTR_REMAP +#ifdef CONFIG_IRQ_REMAP extern int intr_remapping_enabled; extern int intr_remapping_supported(void); extern int enable_intr_remapping(void); @@ -214,7 +214,7 @@ extern int dmar_set_interrupt(struct intel_iommu *iommu); extern irqreturn_t dmar_fault(int irq, void *dev_id); extern int arch_setup_dmar_msi(unsigned int irq); -#ifdef CONFIG_DMAR +#ifdef CONFIG_INTEL_IOMMU extern int iommu_detected, no_iommu; extern struct list_head dmar_rmrr_units; struct dmar_rmrr_unit { @@ -243,7 +243,7 @@ extern int dmar_parse_one_atsr(struct acpi_dmar_header *header); extern int dmar_parse_dev_scope(void *start, void *end, int *cnt, struct pci_dev ***devices, u16 segment); extern int intel_iommu_init(void); -#else /* !CONFIG_DMAR: */ +#else /* !CONFIG_INTEL_IOMMU: */ static inline int intel_iommu_init(void) { return -ENODEV; } static inline int dmar_parse_one_rmrr(struct acpi_dmar_header *header) { @@ -257,6 +257,6 @@ static inline int dmar_parse_rmrr_atsr_dev(void) { return 0; } -#endif /* CONFIG_DMAR */ +#endif /* CONFIG_INTEL_IOMMU */ #endif /* __DMAR_H__ */ diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 9310c69..235b887 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -279,7 +279,7 @@ struct q_inval { int free_cnt; }; -#ifdef CONFIG_INTR_REMAP +#ifdef CONFIG_IRQ_REMAP /* 1MB - maximum possible interrupt remapping table size */ #define INTR_REMAP_PAGE_ORDER 8 #define INTR_REMAP_TABLE_REG_SIZE 0xf @@ -318,7 +318,7 @@ struct intel_iommu { unsigned int irq; unsigned char name[13]; /* Device Name */ -#ifdef CONFIG_DMAR +#ifdef CONFIG_INTEL_IOMMU unsigned long *domain_ids; /* bitmap of domains */ struct dmar_domain **domains; /* ptr to domains */ spinlock_t lock; /* protect context, domain ids */ @@ -329,7 +329,7 @@ struct intel_iommu { struct q_inval *qi; /* Queued invalidation info */ u32 *iommu_state; /* Store iommu states between suspend and resume.*/ -#ifdef CONFIG_INTR_REMAP +#ifdef CONFIG_IRQ_REMAP struct ir_table *ir_table; /* Interrupt remapping info */ #endif int node; -- cgit v1.1