diff options
author | Baoquan He <bhe@redhat.com> | 2017-08-09 11:33:43 +0300 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2017-08-15 19:14:41 +0300 |
commit | daae2d25a4779b272a66ddd01f5810bcee822b9e (patch) | |
tree | 739b63a3bdaf1d65e4edc17681637e0b2bf39a69 /drivers/iommu/amd_iommu_init.c | |
parent | b336781b82cc12c7940a2b1c806fbe7f78ecd72a (diff) | |
download | linux-daae2d25a4779b272a66ddd01f5810bcee822b9e.tar.xz |
iommu/amd: Don't copy GCR3 table root pointer
When iommu is pre_enabled in kdump kernel, if a device is set up with
guest translations (DTE.GV=1), then don't copy GCR3 table root pointer
but move the device over to an empty guest-cr3 table and handle the
faults in the PPR log (which answer them with INVALID). After all these
PPR faults are recoverable for the device and we should not allow the
device to change old-kernels data when we don't have to.
Signed-off-by: Baoquan He <bhe@redhat.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/amd_iommu_init.c')
-rw-r--r-- | drivers/iommu/amd_iommu_init.c | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index c348732f27d7..88e7a6e950ae 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -214,6 +214,7 @@ u16 *amd_iommu_alias_table; * for a specific device. It is also indexed by the PCI device id. */ struct amd_iommu **amd_iommu_rlookup_table; +EXPORT_SYMBOL(amd_iommu_rlookup_table); /* * This table is used to find the irq remapping table for a given device id @@ -269,6 +270,7 @@ bool translation_pre_enabled(struct amd_iommu *iommu) { return (iommu->flags & AMD_IOMMU_FLAG_TRANS_PRE_ENABLED); } +EXPORT_SYMBOL(translation_pre_enabled); static void clear_translation_pre_enabled(struct amd_iommu *iommu) { @@ -859,6 +861,7 @@ static bool copy_device_table(void) struct amd_iommu *iommu; u16 dom_id, dte_v, irq_v; gfp_t gfp_flag; + u64 tmp; if (!amd_iommu_pre_enabled) return false; @@ -910,6 +913,15 @@ static bool copy_device_table(void) old_dev_tbl_cpy[devid].data[0] = old_devtb[devid].data[0]; old_dev_tbl_cpy[devid].data[1] = old_devtb[devid].data[1]; __set_bit(dom_id, amd_iommu_pd_alloc_bitmap); + /* If gcr3 table existed, mask it out */ + if (old_devtb[devid].data[0] & DTE_FLAG_GV) { + tmp = DTE_GCR3_VAL_B(~0ULL) << DTE_GCR3_SHIFT_B; + tmp |= DTE_GCR3_VAL_C(~0ULL) << DTE_GCR3_SHIFT_C; + old_dev_tbl_cpy[devid].data[1] &= ~tmp; + tmp = DTE_GCR3_VAL_A(~0ULL) << DTE_GCR3_SHIFT_A; + tmp |= DTE_FLAG_GV; + old_dev_tbl_cpy[devid].data[0] &= ~tmp; + } } irq_v = old_devtb[devid].data[2] & DTE_IRQ_REMAP_ENABLE; |