AMD IOMMU introduces support for Guest I/O protection where the request from the I/O device without a PASID are treated as if they have PASID 0.
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpa...@amd.com> --- drivers/iommu/amd/amd_iommu_types.h | 3 +++ drivers/iommu/amd/init.c | 8 ++++++++ drivers/iommu/amd/iommu.c | 4 ++++ 3 files changed, 15 insertions(+) diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h index 25062eb86c8b..876ba1adf73e 100644 --- a/drivers/iommu/amd/amd_iommu_types.h +++ b/drivers/iommu/amd/amd_iommu_types.h @@ -93,6 +93,7 @@ #define FEATURE_HE (1ULL<<8) #define FEATURE_PC (1ULL<<9) #define FEATURE_GAM_VAPIC (1ULL<<21) +#define FEATURE_GIOSUP (1ULL<<48) #define FEATURE_EPHSUP (1ULL<<50) #define FEATURE_SNP (1ULL<<63) @@ -366,6 +367,7 @@ #define DTE_FLAG_IW (1ULL << 62) #define DTE_FLAG_IOTLB (1ULL << 32) +#define DTE_FLAG_GIOV (1ULL << 54) #define DTE_FLAG_GV (1ULL << 55) #define DTE_FLAG_MASK (0x3ffULL << 32) #define DTE_GLX_SHIFT (56) @@ -519,6 +521,7 @@ struct protection_domain { spinlock_t lock; /* mostly used to lock the page table*/ u16 id; /* the domain id written to the device table */ int glx; /* Number of levels for GCR3 table */ + bool giov; /* guest IO protection domain */ u64 *gcr3_tbl; /* Guest CR3 table */ unsigned long flags; /* flags to find out type of domain */ unsigned dev_cnt; /* devices assigned to this domain */ diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 5def566de6f6..9265c1bf1d84 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -1895,6 +1895,12 @@ static int __init iommu_init_pci(struct amd_iommu *iommu) init_iommu_perf_ctr(iommu); + if (amd_iommu_pgtable == AMD_IOMMU_V2 && + !iommu_feature(iommu, FEATURE_GIOSUP)) { + pr_warn("Cannot enable v2 page table for DMA-API. Fallback to v1.\n"); + amd_iommu_pgtable = AMD_IOMMU_V1; + } + if (is_rd890_iommu(iommu->dev)) { int i, j; @@ -1969,6 +1975,8 @@ static void print_iommu_info(void) if (amd_iommu_xt_mode == IRQ_REMAP_X2APIC_MODE) pr_info("X2APIC enabled\n"); } + if (amd_iommu_pgtable == AMD_IOMMU_V2) + pr_info("GIOV enabled\n"); } static int __init amd_iommu_init_pci(void) diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c index f3800efdbb29..e29ece6e1e68 100644 --- a/drivers/iommu/amd/iommu.c +++ b/drivers/iommu/amd/iommu.c @@ -1405,6 +1405,10 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain, pte_root |= (domain->iop.mode & DEV_ENTRY_MODE_MASK) << DEV_ENTRY_MODE_SHIFT; + + if (domain->giov && (domain->flags & PD_IOMMUV2_MASK)) + pte_root |= DTE_FLAG_GIOV; + pte_root |= DTE_FLAG_IR | DTE_FLAG_IW | DTE_FLAG_V | DTE_FLAG_TV; flags = amd_iommu_dev_table[devid].data[1]; -- 2.17.1