From a1dafe857db56c35878c71560089a4694ac841fd Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 7 Jan 2015 15:31:28 +0800 Subject: iommu, x86: Restructure setup of the irq remapping feature enable_IR_x2apic() calls setup_irq_remapping_ops() which by default installs the intel dmar remapping ops and then calls the amd iommu irq remapping prepare callback to figure out whether we are running on an AMD machine with irq remapping hardware. Right after that it calls irq_remapping_prepare() which pointlessly checks: if (!remap_ops || !remap_ops->prepare) return -ENODEV; and then calls remap_ops->prepare() which is silly in the AMD case as it got called from setup_irq_remapping_ops() already a few microseconds ago. Simplify this and just collapse everything into irq_remapping_prepare(). The irq_remapping_prepare() remains still silly as it assigns blindly the intel ops, but that's not scope of this patch. The scope here is to move the preperatory work, i.e. memory allocations out of the atomic section which is required to enable irq remapping. Signed-off-by: Thomas Gleixner Tested-by: Borislav Petkov Acked-and-tested-by: Joerg Roedel Cc: Tony Luck Cc: iommu@lists.linux-foundation.org Cc: Joerg Roedel Cc: H. Peter Anvin Cc: Benjamin Herrenschmidt Cc: Yinghai Lu Cc: David Rientjes Cc: HATAYAMA Daisuke Cc: Jan Beulich Cc: Richard Weinberger Cc: Oren Twaig Cc: x86@kernel.org Link: http://lkml.kernel.org/r/20141205084147.232633738@linutronix.de Link: http://lkml.kernel.org/r/1420615903-28253-2-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Jiang Liu Signed-off-by: Thomas Gleixner --- drivers/iommu/irq_remapping.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'drivers/iommu') diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 89c4846683be..91d5884d3ed9 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c @@ -194,16 +194,6 @@ static __init int setup_irqremap(char *str) } early_param("intremap", setup_irqremap); -void __init setup_irq_remapping_ops(void) -{ - remap_ops = &intel_irq_remap_ops; - -#ifdef CONFIG_AMD_IOMMU - if (amd_iommu_irq_ops.prepare() == 0) - remap_ops = &amd_iommu_irq_ops; -#endif -} - void set_irq_remapping_broken(void) { irq_remap_broken = 1; @@ -222,9 +212,14 @@ int irq_remapping_supported(void) int __init irq_remapping_prepare(void) { - if (!remap_ops || !remap_ops->prepare) - return -ENODEV; + remap_ops = &intel_irq_remap_ops; +#ifdef CONFIG_AMD_IOMMU + if (amd_iommu_irq_ops.prepare() == 0) { + remap_ops = &amd_iommu_irq_ops; + return 0; + } +#endif return remap_ops->prepare(); } -- cgit v1.2.3-59-g8ed1b From 11190302400dc5825e429e79dda30d59c2d9525a Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 7 Jan 2015 15:31:29 +0800 Subject: iommu/vt-d: Move iommu preparatory allocations to irq_remap_ops.prepare The whole iommu setup for irq remapping is a convoluted mess. The iommu detect function gets called from mem_init() and the prepare callback gets called from enable_IR_x2apic() for unknown reasons. Of course AMD and Intel setup differs in nonsensical ways. Intels prepare callback is explicit while AMDs prepare callback is implicit in setup_irq_remapping_ops() just to be called in the prepare call again. Because all of this gets called from enable_IR_x2apic() and the dmar prepare function merily parses the ACPI tables, but does not allocate memory we end up with memory allocation from irq disabled context later on. AMDs iommu code at least allocates the required memory from the prepare function. That has issues as well, but thats not scope of this patch. The goal of this change is to distangle the allocation from the actual enablement. There is no point to allocate memory from irq disabled regions with GFP_ATOMIC just because it does not matter at that point in the boot stage. It matters with physical hotplug later on. There is another issue with the current setup. Due to the conversion to stacked irqdomains we end up with a call into the irqdomain allocation code from irq disabled context, but that code does GFP_KERNEL allocations rightfully as there is no reason to do preperatory allocations with GFP_ATOMIC. That change caused the allocator code to complain about GFP_KERNEL allocations invoked in atomic context. Boris provided a temporary hackaround which changed the GFP flags if irq_domain_add() got called from atomic context. Not pretty and we really dont want to get this into a mainline release for obvious reasons. Move the ACPI table parsing and the resulting memory allocations from the enable to the prepare function. That allows to get rid of the horrible hackaround in irq_domain_add() later. [Jiang] Rebased onto v3.19 Signed-off-by: Thomas Gleixner Tested-by: Borislav Petkov Acked-and-tested-by: Joerg Roedel Cc: Tony Luck Cc: iommu@lists.linux-foundation.org Cc: Benjamin Herrenschmidt Cc: Yinghai Lu Cc: x86@kernel.org Link: http://lkml.kernel.org/r/20141205084147.313026156@linutronix.de Link: http://lkml.kernel.org/r/1420615903-28253-3-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Jiang Liu Signed-off-by: Thomas Gleixner --- drivers/iommu/intel_irq_remapping.c | 64 +++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 20 deletions(-) (limited to 'drivers/iommu') diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index a55b207b9425..2360cb6a8896 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -595,22 +595,57 @@ static int __init intel_irq_remapping_supported(void) return 1; } -static int __init intel_enable_irq_remapping(void) +static void __init intel_cleanup_irq_remapping(void) +{ + struct dmar_drhd_unit *drhd; + struct intel_iommu *iommu; + + for_each_iommu(iommu, drhd) { + if (ecap_ir_support(iommu->ecap)) { + iommu_disable_irq_remapping(iommu); + intel_teardown_irq_remapping(iommu); + } + } + + if (x2apic_supported()) + pr_warn("Failed to enable irq remapping. You are vulnerable to irq-injection attacks.\n"); +} + +static int __init intel_prepare_irq_remapping(void) { struct dmar_drhd_unit *drhd; struct intel_iommu *iommu; - bool x2apic_present; - int setup = 0; - int eim = 0; - x2apic_present = x2apic_supported(); + if (dmar_table_init() < 0) + return -1; if (parse_ioapics_under_ir() != 1) { - printk(KERN_INFO "Not enable interrupt remapping\n"); + printk(KERN_INFO "Not enabling interrupt remapping\n"); goto error; } - if (x2apic_present) { + for_each_iommu(iommu, drhd) { + if (!ecap_ir_support(iommu->ecap)) + continue; + + /* Do the allocations early */ + if (intel_setup_irq_remapping(iommu)) + goto error; + } + return 0; +error: + intel_cleanup_irq_remapping(); + return -1; +} + +static int __init intel_enable_irq_remapping(void) +{ + struct dmar_drhd_unit *drhd; + struct intel_iommu *iommu; + int setup = 0; + int eim = 0; + + if (x2apic_supported()) { pr_info("Queued invalidation will be enabled to support x2apic and Intr-remapping.\n"); eim = !dmar_x2apic_optout(); @@ -678,9 +713,6 @@ static int __init intel_enable_irq_remapping(void) if (!ecap_ir_support(iommu->ecap)) continue; - if (intel_setup_irq_remapping(iommu)) - goto error; - iommu_set_irq_remapping(iommu, eim); setup = 1; } @@ -702,15 +734,7 @@ static int __init intel_enable_irq_remapping(void) return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE; error: - for_each_iommu(iommu, drhd) - if (ecap_ir_support(iommu->ecap)) { - iommu_disable_irq_remapping(iommu); - intel_teardown_irq_remapping(iommu); - } - - if (x2apic_present) - pr_warn("Failed to enable irq remapping. You are vulnerable to irq-injection attacks.\n"); - + intel_cleanup_irq_remapping(); return -1; } @@ -1200,7 +1224,7 @@ static int intel_alloc_hpet_msi(unsigned int irq, unsigned int id) struct irq_remap_ops intel_irq_remap_ops = { .supported = intel_irq_remapping_supported, - .prepare = dmar_table_init, + .prepare = intel_prepare_irq_remapping, .enable = intel_enable_irq_remapping, .disable = disable_irq_remapping, .reenable = reenable_irq_remapping, -- cgit v1.2.3-59-g8ed1b From e3a981d61d156c1a9ea0aac253d2d3f33c081906 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 7 Jan 2015 15:31:30 +0800 Subject: iommu/vt-d: Convert allocations to GFP_KERNEL No reason anymore to do GFP_ATOMIC allocations which are not harmful in the normal bootup case, but matter in the physical hotplug scenario. Signed-off-by: Thomas Gleixner Tested-by: Borislav Petkov Acked-and-tested-by: Joerg Roedel Cc: Tony Luck Cc: iommu@lists.linux-foundation.org Cc: Benjamin Herrenschmidt Cc: Yinghai Lu Cc: x86@kernel.org Link: http://lkml.kernel.org/r/20141205084147.472428339@linutronix.de Link: http://lkml.kernel.org/r/1420615903-28253-4-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Jiang Liu Signed-off-by: Thomas Gleixner --- drivers/iommu/intel_irq_remapping.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/iommu') diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 2360cb6a8896..1e7e09327753 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -481,11 +481,11 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu) if (iommu->ir_table) return 0; - ir_table = kzalloc(sizeof(struct ir_table), GFP_ATOMIC); + ir_table = kzalloc(sizeof(struct ir_table), GFP_KERNEL); if (!ir_table) return -ENOMEM; - pages = alloc_pages_node(iommu->node, GFP_ATOMIC | __GFP_ZERO, + pages = alloc_pages_node(iommu->node, GFP_KERNEL | __GFP_ZERO, INTR_REMAP_PAGE_ORDER); if (!pages) { -- cgit v1.2.3-59-g8ed1b From 2966d9566beb39c53477c96525820b9415de7a7d Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Wed, 7 Jan 2015 15:31:35 +0800 Subject: iommu/vt-d: Prepare for killing function irq_remapping_supported() Prepare for killing function irq_remapping_supported() by moving code from intel_irq_remapping_supported() into intel_prepare_irq_remapping(). Combined with patch from Joerg at https://lkml.org/lkml/2014/12/15/487, so assume an signed-off from Joerg. Signed-off-by: Jiang Liu Signed-off-by: Joerg Roedel Tested-by: Joerg Roedel Cc: Tony Luck Cc: iommu@lists.linux-foundation.org Cc: Benjamin Herrenschmidt Cc: Yinghai Lu Cc: Borislav Petkov Link: http://lkml.kernel.org/r/1420615903-28253-9-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner --- drivers/iommu/intel_irq_remapping.c | 58 ++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 33 deletions(-) (limited to 'drivers/iommu') diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 1e7e09327753..8ccc7aa7e43a 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -568,30 +568,6 @@ static int __init dmar_x2apic_optout(void) static int __init intel_irq_remapping_supported(void) { - struct dmar_drhd_unit *drhd; - struct intel_iommu *iommu; - - if (disable_irq_remap) - return 0; - if (irq_remap_broken) { - printk(KERN_WARNING - "This system BIOS has enabled interrupt remapping\n" - "on a chipset that contains an erratum making that\n" - "feature unstable. To maintain system stability\n" - "interrupt remapping is being disabled. Please\n" - "contact your BIOS vendor for an update\n"); - add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); - disable_irq_remap = 1; - return 0; - } - - if (!dmar_ir_support()) - return 0; - - for_each_iommu(iommu, drhd) - if (!ecap_ir_support(iommu->ecap)) - return 0; - return 1; } @@ -616,26 +592,42 @@ static int __init intel_prepare_irq_remapping(void) struct dmar_drhd_unit *drhd; struct intel_iommu *iommu; + /* First check whether IRQ remapping should be enabled */ + if (disable_irq_remap) + return -ENODEV; + + if (irq_remap_broken) { + printk(KERN_WARNING + "This system BIOS has enabled interrupt remapping\n" + "on a chipset that contains an erratum making that\n" + "feature unstable. To maintain system stability\n" + "interrupt remapping is being disabled. Please\n" + "contact your BIOS vendor for an update\n"); + add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); + disable_irq_remap = 1; + return -ENODEV; + } + if (dmar_table_init() < 0) - return -1; + return -ENODEV; + + if (!dmar_ir_support()) + return -ENODEV; if (parse_ioapics_under_ir() != 1) { printk(KERN_INFO "Not enabling interrupt remapping\n"); goto error; } - for_each_iommu(iommu, drhd) { - if (!ecap_ir_support(iommu->ecap)) - continue; - - /* Do the allocations early */ - if (intel_setup_irq_remapping(iommu)) + for_each_iommu(iommu, drhd) + if (!ecap_ir_support(iommu->ecap) || + intel_setup_irq_remapping(iommu)) goto error; - } return 0; + error: intel_cleanup_irq_remapping(); - return -1; + return -ENODEV; } static int __init intel_enable_irq_remapping(void) -- cgit v1.2.3-59-g8ed1b From 69cf1d8a1286a7bfbeec497b69c43cc7ebb2a787 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 7 Jan 2015 15:31:36 +0800 Subject: iommu/vt-d: Allocate IRQ remapping data structures only for all IOMMUs IRQ remapping is only supported when all IOMMUs in the system support it. So check if all IOMMUs in the system support IRQ remapping before doing the allocations. [Jiang] 1) Rebased to v3.19. 2) Remove redundant check of ecap_ir_support(iommu->ecap) in function intel_enable_irq_remapping(). Signed-off-by: Joerg Roedel Signed-off-by: Jiang Liu Tested-by: Joerg Roedel Cc: Tony Luck Cc: iommu@lists.linux-foundation.org Cc: Benjamin Herrenschmidt Cc: Yinghai Lu Cc: Borislav Petkov Link: http://lkml.kernel.org/r/1420615903-28253-10-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner --- drivers/iommu/intel_irq_remapping.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'drivers/iommu') diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 8ccc7aa7e43a..137663bd5da2 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -619,10 +619,16 @@ static int __init intel_prepare_irq_remapping(void) goto error; } + /* First make sure all IOMMUs support IRQ remapping */ for_each_iommu(iommu, drhd) - if (!ecap_ir_support(iommu->ecap) || - intel_setup_irq_remapping(iommu)) + if (!ecap_ir_support(iommu->ecap)) + goto error; + + /* Do the allocations early */ + for_each_iommu(iommu, drhd) + if (intel_setup_irq_remapping(iommu)) goto error; + return 0; error: @@ -673,16 +679,12 @@ static int __init intel_enable_irq_remapping(void) /* * check for the Interrupt-remapping support */ - for_each_iommu(iommu, drhd) { - if (!ecap_ir_support(iommu->ecap)) - continue; - + for_each_iommu(iommu, drhd) if (eim && !ecap_eim_support(iommu->ecap)) { printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, " " ecap %Lx\n", drhd->reg_base_addr, iommu->ecap); goto error; } - } /* * Enable queued invalidation for all the DRHD's. @@ -702,9 +704,6 @@ static int __init intel_enable_irq_remapping(void) * Setup Interrupt-remapping for all the DRHD's now. */ for_each_iommu(iommu, drhd) { - if (!ecap_ir_support(iommu->ecap)) - continue; - iommu_set_irq_remapping(iommu, eim); setup = 1; } -- cgit v1.2.3-59-g8ed1b From 13d09b6603df9df3aa3e410bc2a876889a55c744 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Wed, 7 Jan 2015 15:31:37 +0800 Subject: iommu/vt-d: Allow IR works in XAPIC mode though CPU works in X2APIC mode Currently if CPU supports X2APIC, IR hardware must work in X2APIC mode or disabled. Change the code to support IR working in XAPIC mode when CPU supports X2APIC. Then the CPU APIC driver will decide how to handle such as configuration by: 1) Disabling X2APIC mode 2) Forcing X2APIC physical mode This change also fixes a live locking when 1) BIOS enables CPU X2APIC 2) DMAR table disables X2APIC mode or IR hardware doesn't support X2APIC with following messages: [ 37.863463] dmar: INTR-REMAP: Request device [[f0:1f.7] fault index 2 [ 37.863463] INTR-REMAP:[fault reason 36] Detected reserved fields in the IRTE entry [ 37.879372] dmar: INTR-REMAP: Request device [[f0:1f.7] fault index 2 [ 37.879372] INTR-REMAP:[fault reason 36] Detected reserved fields in the IRTE entry [ 37.895282] dmar: INTR-REMAP: Request device [[f0:1f.7] fault index 2 [ 37.895282] INTR-REMAP:[fault reason 36] Detected reserved fields in the IRTE entry [ 37.911192] dmar: INTR-REMAP: Request device [[f0:1f.7] fault index 2 Signed-off-by: Jiang Liu Tested-by: Joerg Roedel Cc: Tony Luck Cc: iommu@lists.linux-foundation.org Cc: Benjamin Herrenschmidt Cc: Yinghai Lu Cc: Borislav Petkov Link: http://lkml.kernel.org/r/1420615903-28253-11-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner --- drivers/iommu/intel_irq_remapping.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers/iommu') diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 137663bd5da2..9d67c12c2ffb 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -32,8 +32,9 @@ struct hpet_scope { }; #define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0) -#define IRTE_DEST(dest) ((x2apic_mode) ? dest : dest << 8) +#define IRTE_DEST(dest) ((eim_mode) ? dest : dest << 8) +static int __read_mostly eim_mode; static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; static struct hpet_scope ir_hpet[MAX_HPET_TBS]; @@ -644,8 +645,6 @@ static int __init intel_enable_irq_remapping(void) int eim = 0; if (x2apic_supported()) { - pr_info("Queued invalidation will be enabled to support x2apic and Intr-remapping.\n"); - eim = !dmar_x2apic_optout(); if (!eim) printk(KERN_WARNING @@ -683,8 +682,11 @@ static int __init intel_enable_irq_remapping(void) if (eim && !ecap_eim_support(iommu->ecap)) { printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, " " ecap %Lx\n", drhd->reg_base_addr, iommu->ecap); - goto error; + eim = 0; } + eim_mode = eim; + if (eim) + pr_info("Queued invalidation will be enabled to support x2apic and Intr-remapping.\n"); /* * Enable queued invalidation for all the DRHD's. -- cgit v1.2.3-59-g8ed1b From 84d0779304b5c45134311dfc31b5a2325ce3ad84 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Wed, 7 Jan 2015 15:31:39 +0800 Subject: iommu/amd: Check for irq-remap support amd_iommu_prepare() This allows to get rid of the irq_remapping_supported() function and all its call-backs into the Intel and AMD IOMMU drivers. Signed-off-by: Joerg Roedel Signed-off-by: Jiang Liu Tested-by: Joerg Roedel Cc: Tony Luck Cc: iommu@lists.linux-foundation.org Cc: Benjamin Herrenschmidt Cc: Yinghai Lu Cc: Borislav Petkov Link: http://lkml.kernel.org/r/1420615903-28253-13-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner --- drivers/iommu/amd_iommu_init.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/iommu') diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index b0522f15730f..0039f87f48b8 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -2123,6 +2123,9 @@ static int __init iommu_go_to_state(enum iommu_init_state state) #ifdef CONFIG_IRQ_REMAP int __init amd_iommu_prepare(void) { + if (!amd_iommu_irq_remap) + return -1; + return iommu_go_to_state(IOMMU_ACPI_FINISHED); } -- cgit v1.2.3-59-g8ed1b From c392f56c946033bd136043079a62b9188888828d Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Wed, 7 Jan 2015 15:31:40 +0800 Subject: iommu/irq_remapping: Kill function irq_remapping_supported() and related code Simplify irq_remapping code by killing irq_remapping_supported() and related interfaces. Joerg posted a similar patch at https://lkml.org/lkml/2014/12/15/490, so assume an signed-off from Joerg. Signed-off-by: Jiang Liu Signed-off-by: Joerg Roedel Tested-by: Joerg Roedel Cc: Tony Luck Cc: iommu@lists.linux-foundation.org Cc: H. Peter Anvin Cc: Benjamin Herrenschmidt Cc: Yinghai Lu Cc: Borislav Petkov Cc: David Rientjes Cc: HATAYAMA Daisuke Cc: Jan Beulich Cc: Richard Weinberger Cc: Oren Twaig Link: http://lkml.kernel.org/r/1420615903-28253-14-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/irq_remapping.h | 2 -- arch/x86/kernel/apic/apic.c | 7 +------ drivers/iommu/amd_iommu.c | 1 - drivers/iommu/amd_iommu_init.c | 5 ----- drivers/iommu/amd_iommu_proto.h | 1 - drivers/iommu/intel_irq_remapping.c | 6 ------ drivers/iommu/irq_remapping.c | 12 ++---------- drivers/iommu/irq_remapping.h | 3 --- 8 files changed, 3 insertions(+), 34 deletions(-) (limited to 'drivers/iommu') diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h index f1b619e5a50d..6224d316c405 100644 --- a/arch/x86/include/asm/irq_remapping.h +++ b/arch/x86/include/asm/irq_remapping.h @@ -33,7 +33,6 @@ struct irq_cfg; #ifdef CONFIG_IRQ_REMAP -extern int irq_remapping_supported(void); extern void set_irq_remapping_broken(void); extern int irq_remapping_prepare(void); extern int irq_remapping_enable(void); @@ -59,7 +58,6 @@ void irq_remap_modify_chip_defaults(struct irq_chip *chip); #else /* CONFIG_IRQ_REMAP */ -static inline int irq_remapping_supported(void) { return 0; } static inline void set_irq_remapping_broken(void) { } static inline int irq_remapping_prepare(void) { return -ENODEV; } static inline int irq_remapping_enable(void) { return -ENODEV; } diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 2f16116ced90..35e6d09294ed 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -1575,12 +1575,7 @@ void enable_x2apic(void) static int __init try_to_enable_IR(void) { -#ifdef CONFIG_IRQ_REMAP - if (!irq_remapping_supported()) { - pr_debug("intr-remapping not supported\n"); - return -1; - } - +#ifdef CONFIG_X86_IO_APIC if (!x2apic_enabled() && skip_ioapic_setup) { pr_info("Skipped enabling intr-remap because of skipping " "io-apic setup\n"); diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 98024856df07..59de6364a910 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -4284,7 +4284,6 @@ static int alloc_hpet_msi(unsigned int irq, unsigned int id) } struct irq_remap_ops amd_iommu_irq_ops = { - .supported = amd_iommu_supported, .prepare = amd_iommu_prepare, .enable = amd_iommu_enable, .disable = amd_iommu_disable, diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 0039f87f48b8..970979ecbebb 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -2129,11 +2129,6 @@ int __init amd_iommu_prepare(void) return iommu_go_to_state(IOMMU_ACPI_FINISHED); } -int __init amd_iommu_supported(void) -{ - return amd_iommu_irq_remap ? 1 : 0; -} - int __init amd_iommu_enable(void) { int ret; diff --git a/drivers/iommu/amd_iommu_proto.h b/drivers/iommu/amd_iommu_proto.h index 95ed6deae47f..861af9d8338a 100644 --- a/drivers/iommu/amd_iommu_proto.h +++ b/drivers/iommu/amd_iommu_proto.h @@ -33,7 +33,6 @@ extern void amd_iommu_init_notifier(void); extern void amd_iommu_init_api(void); /* Needed for interrupt remapping */ -extern int amd_iommu_supported(void); extern int amd_iommu_prepare(void); extern int amd_iommu_enable(void); extern void amd_iommu_disable(void); diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 9d67c12c2ffb..fb72bd5f438c 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -567,11 +567,6 @@ static int __init dmar_x2apic_optout(void) return dmar->flags & DMAR_X2APIC_OPT_OUT; } -static int __init intel_irq_remapping_supported(void) -{ - return 1; -} - static void __init intel_cleanup_irq_remapping(void) { struct dmar_drhd_unit *drhd; @@ -1216,7 +1211,6 @@ static int intel_alloc_hpet_msi(unsigned int irq, unsigned int id) } struct irq_remap_ops intel_irq_remap_ops = { - .supported = intel_irq_remapping_supported, .prepare = intel_prepare_irq_remapping, .enable = intel_enable_irq_remapping, .disable = disable_irq_remapping, diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 91d5884d3ed9..e7449b42504d 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c @@ -199,19 +199,11 @@ void set_irq_remapping_broken(void) irq_remap_broken = 1; } -int irq_remapping_supported(void) +int __init irq_remapping_prepare(void) { if (disable_irq_remap) - return 0; - - if (!remap_ops || !remap_ops->supported) - return 0; + return -ENOSYS; - return remap_ops->supported(); -} - -int __init irq_remapping_prepare(void) -{ remap_ops = &intel_irq_remap_ops; #ifdef CONFIG_AMD_IOMMU diff --git a/drivers/iommu/irq_remapping.h b/drivers/iommu/irq_remapping.h index fde250f86e60..a8edfea0ab5d 100644 --- a/drivers/iommu/irq_remapping.h +++ b/drivers/iommu/irq_remapping.h @@ -38,9 +38,6 @@ extern int no_x2apic_optout; extern int irq_remapping_enabled; struct irq_remap_ops { - /* Check whether Interrupt Remapping is supported */ - int (*supported)(void); - /* Initializes hardware and makes it ready for remapping interrupts */ int (*prepare)(void); -- cgit v1.2.3-59-g8ed1b From 30969e34ae6edf10a003f6c0be1fecf6dadcd421 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Wed, 7 Jan 2015 15:31:41 +0800 Subject: iommu/irq_remapping: Refine function irq_remapping_prepare() for maintenance Assign intel_irq_remap_ops to remap_ops only if intel_irq_remap_ops.prepare() succeeds. Signed-off-by: Jiang Liu Tested-by: Joerg Roedel Cc: Tony Luck Cc: iommu@lists.linux-foundation.org Cc: Benjamin Herrenschmidt Cc: Yinghai Lu Cc: Borislav Petkov Link: http://lkml.kernel.org/r/1420615903-28253-15-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner --- drivers/iommu/irq_remapping.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/iommu') diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index e7449b42504d..7d85d2ba0e8b 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c @@ -204,15 +204,15 @@ int __init irq_remapping_prepare(void) if (disable_irq_remap) return -ENOSYS; - remap_ops = &intel_irq_remap_ops; - -#ifdef CONFIG_AMD_IOMMU - if (amd_iommu_irq_ops.prepare() == 0) { + if (intel_irq_remap_ops.prepare() == 0) + remap_ops = &intel_irq_remap_ops; + else if (IS_ENABLED(CONFIG_AMD_IOMMU) && + amd_iommu_irq_ops.prepare() == 0) remap_ops = &amd_iommu_irq_ops; - return 0; - } -#endif - return remap_ops->prepare(); + else + return -ENOSYS; + + return 0; } int __init irq_remapping_enable(void) -- cgit v1.2.3-59-g8ed1b From 7fa1c842caca3b1d8a55a64033403cab8ca8583a Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Wed, 7 Jan 2015 15:31:42 +0800 Subject: iommu/irq_remapping: Change variable disable_irq_remap to be static Change variable disable_irq_remap to be static and simplify the code. Signed-off-by: Jiang Liu Tested-by: Joerg Roedel Cc: Tony Luck Cc: iommu@lists.linux-foundation.org Cc: Benjamin Herrenschmidt Cc: Yinghai Lu Cc: Borislav Petkov Link: http://lkml.kernel.org/r/1420615903-28253-16-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner --- drivers/iommu/amd_iommu_init.c | 6 +----- drivers/iommu/intel_irq_remapping.c | 5 ----- drivers/iommu/irq_remapping.c | 3 +-- drivers/iommu/irq_remapping.h | 2 -- 4 files changed, 2 insertions(+), 14 deletions(-) (limited to 'drivers/iommu') diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 970979ecbebb..e430dc8dffdf 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -2014,9 +2014,6 @@ static bool detect_ivrs(void) /* Make sure ACS will be enabled during PCI probe */ pci_request_acs(); - if (!disable_irq_remap) - amd_iommu_irq_remap = true; - return true; } @@ -2123,8 +2120,7 @@ static int __init iommu_go_to_state(enum iommu_init_state state) #ifdef CONFIG_IRQ_REMAP int __init amd_iommu_prepare(void) { - if (!amd_iommu_irq_remap) - return -1; + amd_iommu_irq_remap = true; return iommu_go_to_state(IOMMU_ACPI_FINISHED); } diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index fb72bd5f438c..14de1ab223c8 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -588,10 +588,6 @@ static int __init intel_prepare_irq_remapping(void) struct dmar_drhd_unit *drhd; struct intel_iommu *iommu; - /* First check whether IRQ remapping should be enabled */ - if (disable_irq_remap) - return -ENODEV; - if (irq_remap_broken) { printk(KERN_WARNING "This system BIOS has enabled interrupt remapping\n" @@ -600,7 +596,6 @@ static int __init intel_prepare_irq_remapping(void) "interrupt remapping is being disabled. Please\n" "contact your BIOS vendor for an update\n"); add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK); - disable_irq_remap = 1; return -ENODEV; } diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 7d85d2ba0e8b..5585c4e17e39 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c @@ -17,12 +17,11 @@ #include "irq_remapping.h" int irq_remapping_enabled; - -int disable_irq_remap; int irq_remap_broken; int disable_sourceid_checking; int no_x2apic_optout; +static int disable_irq_remap; static struct irq_remap_ops *remap_ops; static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec); diff --git a/drivers/iommu/irq_remapping.h b/drivers/iommu/irq_remapping.h index a8edfea0ab5d..c448eb48340a 100644 --- a/drivers/iommu/irq_remapping.h +++ b/drivers/iommu/irq_remapping.h @@ -31,7 +31,6 @@ struct cpumask; struct pci_dev; struct msi_msg; -extern int disable_irq_remap; extern int irq_remap_broken; extern int disable_sourceid_checking; extern int no_x2apic_optout; @@ -86,7 +85,6 @@ extern struct irq_remap_ops amd_iommu_irq_ops; #else /* CONFIG_IRQ_REMAP */ #define irq_remapping_enabled 0 -#define disable_irq_remap 1 #define irq_remap_broken 0 #endif /* CONFIG_IRQ_REMAP */ -- cgit v1.2.3-59-g8ed1b From e901176046e6729e002839d7296f27f17599ccb8 Mon Sep 17 00:00:00 2001 From: Jiang Liu Date: Wed, 7 Jan 2015 15:31:43 +0800 Subject: iommu/irq_remapping: Normailize the way to detect whether IR is enabled Refine code by normailizing the way to detect whether IR is enabled. Signed-off-by: Jiang Liu Tested-by: Joerg Roedel Cc: Tony Luck Cc: iommu@lists.linux-foundation.org Cc: Benjamin Herrenschmidt Cc: Yinghai Lu Cc: Borislav Petkov Link: http://lkml.kernel.org/r/1420615903-28253-17-git-send-email-jiang.liu@linux.intel.com Signed-off-by: Thomas Gleixner --- drivers/iommu/irq_remapping.c | 38 ++++++++++++++------------------------ 1 file changed, 14 insertions(+), 24 deletions(-) (limited to 'drivers/iommu') diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index 5585c4e17e39..390079ee1350 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c @@ -218,7 +218,7 @@ int __init irq_remapping_enable(void) { int ret; - if (!remap_ops || !remap_ops->enable) + if (!remap_ops->enable) return -ENODEV; ret = remap_ops->enable(); @@ -231,22 +231,16 @@ int __init irq_remapping_enable(void) void irq_remapping_disable(void) { - if (!irq_remapping_enabled || - !remap_ops || - !remap_ops->disable) - return; - - remap_ops->disable(); + if (irq_remapping_enabled && remap_ops->disable) + remap_ops->disable(); } int irq_remapping_reenable(int mode) { - if (!irq_remapping_enabled || - !remap_ops || - !remap_ops->reenable) - return 0; + if (irq_remapping_enabled && remap_ops->reenable) + return remap_ops->reenable(mode); - return remap_ops->reenable(mode); + return 0; } int __init irq_remap_enable_fault_handling(void) @@ -254,7 +248,7 @@ int __init irq_remap_enable_fault_handling(void) if (!irq_remapping_enabled) return 0; - if (!remap_ops || !remap_ops->enable_faulting) + if (!remap_ops->enable_faulting) return -ENODEV; return remap_ops->enable_faulting(); @@ -265,7 +259,7 @@ int setup_ioapic_remapped_entry(int irq, unsigned int destination, int vector, struct io_apic_irq_attr *attr) { - if (!remap_ops || !remap_ops->setup_ioapic_entry) + if (!remap_ops->setup_ioapic_entry) return -ENODEV; return remap_ops->setup_ioapic_entry(irq, entry, destination, @@ -275,8 +269,7 @@ int setup_ioapic_remapped_entry(int irq, static int set_remapped_irq_affinity(struct irq_data *data, const struct cpumask *mask, bool force) { - if (!config_enabled(CONFIG_SMP) || !remap_ops || - !remap_ops->set_affinity) + if (!config_enabled(CONFIG_SMP) || !remap_ops->set_affinity) return 0; return remap_ops->set_affinity(data, mask, force); @@ -286,10 +279,7 @@ void free_remapped_irq(int irq) { struct irq_cfg *cfg = irq_cfg(irq); - if (!remap_ops || !remap_ops->free_irq) - return; - - if (irq_remapped(cfg)) + if (irq_remapped(cfg) && remap_ops->free_irq) remap_ops->free_irq(irq); } @@ -301,13 +291,13 @@ void compose_remapped_msi_msg(struct pci_dev *pdev, if (!irq_remapped(cfg)) native_compose_msi_msg(pdev, irq, dest, msg, hpet_id); - else if (remap_ops && remap_ops->compose_msi_msg) + else if (remap_ops->compose_msi_msg) remap_ops->compose_msi_msg(pdev, irq, dest, msg, hpet_id); } static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec) { - if (!remap_ops || !remap_ops->msi_alloc_irq) + if (!remap_ops->msi_alloc_irq) return -ENODEV; return remap_ops->msi_alloc_irq(pdev, irq, nvec); @@ -316,7 +306,7 @@ static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec) static int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq, int index, int sub_handle) { - if (!remap_ops || !remap_ops->msi_setup_irq) + if (!remap_ops->msi_setup_irq) return -ENODEV; return remap_ops->msi_setup_irq(pdev, irq, index, sub_handle); @@ -326,7 +316,7 @@ int setup_hpet_msi_remapped(unsigned int irq, unsigned int id) { int ret; - if (!remap_ops || !remap_ops->alloc_hpet_msi) + if (!remap_ops->alloc_hpet_msi) return -ENODEV; ret = remap_ops->alloc_hpet_msi(irq, id); -- cgit v1.2.3-59-g8ed1b From 3f4cb7c064847569c9a6b7ab5c6cf0f67c80c55a Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Fri, 23 Jan 2015 14:32:46 +0100 Subject: iommu/amd: Fix irq remapping detection logic Commit 7fa1c842caca "iommu/irq_remapping: Change variable disable_irq_remap to be static" returns unconditionally success from the irq remapping prepare callback if the iommu can be initialized. The change assumed that iommu_go_to_state(IOMMU_ACPI_FINISHED) returns a failure if irq remapping is not enabled, but thats not the case. The function returns success when the iommu is initialized to the point which is required for remapping to work. The actual state of the irq remapping feature is reflected in the status variable amd_iommu_irq_remap, which is not considered in the return value. The fix is simple: If the iommu_go_to_state() returns success, evaluate the remapping state amd_iommu_irq_remap and reflect it in the return value. Fixes: 7fa1c842caca iommu/irq_remapping: Change variable disable_irq_remap to be static Reported-and-tested-by: Borislav Petkov Signed-off-by: Thomas Gleixner Cc: Jiang Liu Cc: Joerg Roedel --- drivers/iommu/amd_iommu_init.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/iommu') diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index e430dc8dffdf..9a20248e7068 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -2120,9 +2120,14 @@ static int __init iommu_go_to_state(enum iommu_init_state state) #ifdef CONFIG_IRQ_REMAP int __init amd_iommu_prepare(void) { + int ret; + amd_iommu_irq_remap = true; - return iommu_go_to_state(IOMMU_ACPI_FINISHED); + ret = iommu_go_to_state(IOMMU_ACPI_FINISHED); + if (ret) + return ret; + return amd_iommu_irq_remap ? 0 : -ENODEV; } int __init amd_iommu_enable(void) -- cgit v1.2.3-59-g8ed1b