Skip to content

Commit c2e8dc1

Browse files
sarunkodjoergroedel
authored andcommitted
amd/iommu: Preserve domain ids inside the kdump kernel
Currently AMD IOMMU driver does not reserve domain ids programmed in the DTE while reusing the device table inside kdump kernel. This can cause reallocation of these domain ids for newer domains that are created by the kdump kernel, which can lead to potential IO_PAGE_FAULTs Hence reserve these ids inside pdom_ids. Fixes: 38e5f33 ("iommu/amd: Reuse device table for kdump") Signed-off-by: Sairaj Kodilkar <sarunkod@amd.com> Reported-by: Jason Gunthorpe <jgg@nvidia.com> Reviewed-by: Vasant Hegde <vasant.hegde@amd.com> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
1 parent 7a089c5 commit c2e8dc1

1 file changed

Lines changed: 22 additions & 1 deletion

File tree

drivers/iommu/amd/init.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1136,9 +1136,13 @@ static void set_dte_bit(struct dev_table_entry *dte, u8 bit)
11361136
static bool __reuse_device_table(struct amd_iommu *iommu)
11371137
{
11381138
struct amd_iommu_pci_seg *pci_seg = iommu->pci_seg;
1139-
u32 lo, hi, old_devtb_size;
1139+
struct dev_table_entry *old_dev_tbl_entry;
1140+
u32 lo, hi, old_devtb_size, devid;
11401141
phys_addr_t old_devtb_phys;
1142+
u16 dom_id;
1143+
bool dte_v;
11411144
u64 entry;
1145+
int ret;
11421146

11431147
/* Each IOMMU use separate device table with the same size */
11441148
lo = readl(iommu->mmio_base + MMIO_DEV_TABLE_OFFSET);
@@ -1173,6 +1177,23 @@ static bool __reuse_device_table(struct amd_iommu *iommu)
11731177
return false;
11741178
}
11751179

1180+
for (devid = 0; devid <= pci_seg->last_bdf; devid++) {
1181+
old_dev_tbl_entry = &pci_seg->old_dev_tbl_cpy[devid];
1182+
dte_v = FIELD_GET(DTE_FLAG_V, old_dev_tbl_entry->data[0]);
1183+
dom_id = FIELD_GET(DEV_DOMID_MASK, old_dev_tbl_entry->data[1]);
1184+
1185+
if (!dte_v || !dom_id)
1186+
continue;
1187+
/*
1188+
* ID reservation can fail with -ENOSPC when there
1189+
* are multiple devices present in the same domain,
1190+
* hence check only for -ENOMEM.
1191+
*/
1192+
ret = ida_alloc_range(&pdom_ids, dom_id, dom_id, GFP_KERNEL);
1193+
if (ret == -ENOMEM)
1194+
return false;
1195+
}
1196+
11761197
return true;
11771198
}
11781199

0 commit comments

Comments
 (0)