|
|
@@ -1153,6 +1153,17 @@ static void amd_iommu_flush_tlb_all(struct amd_iommu *iommu)
|
|
|
iommu_completion_wait(iommu);
|
|
|
}
|
|
|
|
|
|
+static void amd_iommu_flush_tlb_domid(struct amd_iommu *iommu, u32 dom_id)
|
|
|
+{
|
|
|
+ struct iommu_cmd cmd;
|
|
|
+
|
|
|
+ build_inv_iommu_pages(&cmd, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS,
|
|
|
+ dom_id, 1);
|
|
|
+ iommu_queue_command(iommu, &cmd);
|
|
|
+
|
|
|
+ iommu_completion_wait(iommu);
|
|
|
+}
|
|
|
+
|
|
|
static void amd_iommu_flush_all(struct amd_iommu *iommu)
|
|
|
{
|
|
|
struct iommu_cmd cmd;
|
|
|
@@ -1838,6 +1849,7 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain,
|
|
|
{
|
|
|
u64 pte_root = 0;
|
|
|
u64 flags = 0;
|
|
|
+ u32 old_domid;
|
|
|
|
|
|
if (domain->mode != PAGE_MODE_NONE)
|
|
|
pte_root = iommu_virt_to_phys(domain->pt_root);
|
|
|
@@ -1887,8 +1899,20 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain,
|
|
|
flags &= ~DEV_DOMID_MASK;
|
|
|
flags |= domain->id;
|
|
|
|
|
|
+ old_domid = amd_iommu_dev_table[devid].data[1] & DEV_DOMID_MASK;
|
|
|
amd_iommu_dev_table[devid].data[1] = flags;
|
|
|
amd_iommu_dev_table[devid].data[0] = pte_root;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * A kdump kernel might be replacing a domain ID that was copied from
|
|
|
+ * the previous kernel--if so, it needs to flush the translation cache
|
|
|
+ * entries for the old domain ID that is being overwritten
|
|
|
+ */
|
|
|
+ if (old_domid) {
|
|
|
+ struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
|
|
|
+
|
|
|
+ amd_iommu_flush_tlb_domid(iommu, old_domid);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static void clear_dte_entry(u16 devid)
|