aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBaoquan He <bhe@redhat.com>2017-08-09 04:33:38 -0400
committerJoerg Roedel <jroedel@suse.de>2017-08-15 12:14:39 -0400
commit3ac3e5ee5ed56b07448f295902e44916eb6979fc (patch)
tree1e6c62c314a67922605b7d959708c77157e13d50
parent45a01c42933b93e59811099f97aa4179d499a42c (diff)
iommu/amd: Copy old trans table from old kernel
Here several things need be done: - If iommu is pre-enabled in a normal kernel, just disable it and print warning. - If any one of IOMMUs is not pre-enabled in kdump kernel, just continue as it does in normal kernel. - If failed to copy dev table of old kernel, continue to proceed as it does in normal kernel. - Only if all IOMMUs are pre-enabled and copy dev table is done well, free the dev table allocated in early_amd_iommu_init() and make amd_iommu_dev_table point to the copied one. - Disable and Re-enable event/cmd buffer, install the copied DTE table to reg, and detect and enable guest vapic. - Flush all caches Signed-off-by: Baoquan He <bhe@redhat.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--drivers/iommu/amd_iommu_init.c59
1 files changed, 51 insertions, 8 deletions
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index e2857204d32a..959c25d997e1 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -37,6 +37,7 @@
37#include <asm/io_apic.h> 37#include <asm/io_apic.h>
38#include <asm/irq_remapping.h> 38#include <asm/irq_remapping.h>
39 39
40#include <linux/crash_dump.h>
40#include "amd_iommu_proto.h" 41#include "amd_iommu_proto.h"
41#include "amd_iommu_types.h" 42#include "amd_iommu_types.h"
42#include "irq_remapping.h" 43#include "irq_remapping.h"
@@ -262,6 +263,8 @@ static int amd_iommu_enable_interrupts(void);
262static int __init iommu_go_to_state(enum iommu_init_state state); 263static int __init iommu_go_to_state(enum iommu_init_state state);
263static void init_device_table_dma(void); 264static void init_device_table_dma(void);
264 265
266static bool __initdata amd_iommu_pre_enabled = true;
267
265bool translation_pre_enabled(struct amd_iommu *iommu) 268bool translation_pre_enabled(struct amd_iommu *iommu)
266{ 269{
267 return (iommu->flags & AMD_IOMMU_FLAG_TRANS_PRE_ENABLED); 270 return (iommu->flags & AMD_IOMMU_FLAG_TRANS_PRE_ENABLED);
@@ -857,6 +860,8 @@ static bool copy_device_table(void)
857 u16 dom_id, dte_v; 860 u16 dom_id, dte_v;
858 gfp_t gfp_flag; 861 gfp_t gfp_flag;
859 862
863 if (!amd_iommu_pre_enabled)
864 return false;
860 865
861 pr_warn("Translation is already enabled - trying to copy translation structures\n"); 866 pr_warn("Translation is already enabled - trying to copy translation structures\n");
862 for_each_iommu(iommu) { 867 for_each_iommu(iommu) {
@@ -1496,9 +1501,14 @@ static int __init init_iommu_one(struct amd_iommu *iommu, struct ivhd_header *h)
1496 iommu->int_enabled = false; 1501 iommu->int_enabled = false;
1497 1502
1498 init_translation_status(iommu); 1503 init_translation_status(iommu);
1499 1504 if (translation_pre_enabled(iommu) && !is_kdump_kernel()) {
1500 if (translation_pre_enabled(iommu)) 1505 iommu_disable(iommu);
1501 pr_warn("Translation is already enabled - trying to copy translation structures\n"); 1506 clear_translation_pre_enabled(iommu);
1507 pr_warn("Translation was enabled for IOMMU:%d but we are not in kdump mode\n",
1508 iommu->index);
1509 }
1510 if (amd_iommu_pre_enabled)
1511 amd_iommu_pre_enabled = translation_pre_enabled(iommu);
1502 1512
1503 ret = init_iommu_from_acpi(iommu, h); 1513 ret = init_iommu_from_acpi(iommu, h);
1504 if (ret) 1514 if (ret)
@@ -1993,8 +2003,7 @@ static int __init init_memory_definitions(struct acpi_table_header *table)
1993} 2003}
1994 2004
1995/* 2005/*
1996 * Init the device table to not allow DMA access for devices and 2006 * Init the device table to not allow DMA access for devices
1997 * suppress all page faults
1998 */ 2007 */
1999static void init_device_table_dma(void) 2008static void init_device_table_dma(void)
2000{ 2009{
@@ -2130,14 +2139,48 @@ static void early_enable_iommu(struct amd_iommu *iommu)
2130 2139
2131/* 2140/*
2132 * This function finally enables all IOMMUs found in the system after 2141 * This function finally enables all IOMMUs found in the system after
2133 * they have been initialized 2142 * they have been initialized.
2143 *
2144 * Or if in kdump kernel and IOMMUs are all pre-enabled, try to copy
2145 * the old content of device table entries. Not this case or copy failed,
2146 * just continue as normal kernel does.
2134 */ 2147 */
2135static void early_enable_iommus(void) 2148static void early_enable_iommus(void)
2136{ 2149{
2137 struct amd_iommu *iommu; 2150 struct amd_iommu *iommu;
2138 2151
2139 for_each_iommu(iommu) 2152
2140 early_enable_iommu(iommu); 2153 if (!copy_device_table()) {
2154 /*
2155 * If come here because of failure in copying device table from old
2156 * kernel with all IOMMUs enabled, print error message and try to
2157 * free allocated old_dev_tbl_cpy.
2158 */
2159 if (amd_iommu_pre_enabled)
2160 pr_err("Failed to copy DEV table from previous kernel.\n");
2161 if (old_dev_tbl_cpy != NULL)
2162 free_pages((unsigned long)old_dev_tbl_cpy,
2163 get_order(dev_table_size));
2164
2165 for_each_iommu(iommu) {
2166 clear_translation_pre_enabled(iommu);
2167 early_enable_iommu(iommu);
2168 }
2169 } else {
2170 pr_info("Copied DEV table from previous kernel.\n");
2171 free_pages((unsigned long)amd_iommu_dev_table,
2172 get_order(dev_table_size));
2173 amd_iommu_dev_table = old_dev_tbl_cpy;
2174 for_each_iommu(iommu) {
2175 iommu_disable_command_buffer(iommu);
2176 iommu_disable_event_buffer(iommu);
2177 iommu_enable_command_buffer(iommu);
2178 iommu_enable_event_buffer(iommu);
2179 iommu_enable_ga(iommu);
2180 iommu_set_device_table(iommu);
2181 iommu_flush_all_caches(iommu);
2182 }
2183 }
2141 2184
2142#ifdef CONFIG_IRQ_REMAP 2185#ifdef CONFIG_IRQ_REMAP
2143 if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir)) 2186 if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir))