From 54ce12e02e44feffa6de4f3a069b7d5c7262a966 Mon Sep 17 00:00:00 2001 From: Suravee Suthikulpanit Date: Wed, 23 Sep 2020 12:13:47 +0000 Subject: [PATCH] iommu/amd: Re-purpose Exclusion range registers to support SNP CWWB When the IOMMU SNP support bit is set in the IOMMU Extended Features register, hardware re-purposes the following registers: 1. IOMMU Exclusion Base register (MMIO offset 0020h) to Completion Wait Write-Back (CWWB) Base register 2. IOMMU Exclusion Range Limit (MMIO offset 0028h) to Completion Wait Write-Back (CWWB) Range Limit register and requires the IOMMU CWWB semaphore base and range to be programmed in the register offset 0020h and 0028h accordingly. Signed-off-by: Suravee Suthikulpanit Cc: Brijesh Singh Link: https://lore.kernel.org/r/20200923121347.25365-4-suravee.suthikulpanit@amd.com Signed-off-by: Joerg Roedel --- drivers/iommu/amd/amd_iommu_types.h | 1 + drivers/iommu/amd/init.c | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/amd_iommu_types.h index 1e7966c73707..f696ac7c5f89 100644 --- a/drivers/iommu/amd/amd_iommu_types.h +++ b/drivers/iommu/amd/amd_iommu_types.h @@ -93,6 +93,7 @@ #define FEATURE_PC (1ULL<<9) #define FEATURE_GAM_VAPIC (1ULL<<21) #define FEATURE_EPHSUP (1ULL<<50) +#define FEATURE_SNP (1ULL<<63) #define FEATURE_PASID_SHIFT 32 #define FEATURE_PASID_MASK (0x1fULL << FEATURE_PASID_SHIFT) diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 35f220704bef..662b01eaf0f2 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -359,6 +359,29 @@ static void iommu_set_exclusion_range(struct amd_iommu *iommu) &entry, sizeof(entry)); } +static void iommu_set_cwwb_range(struct amd_iommu *iommu) +{ + u64 start = iommu_virt_to_phys((void *)iommu->cmd_sem); + u64 entry = start & PM_ADDR_MASK; + + if (!iommu_feature(iommu, FEATURE_SNP)) + return; + + /* Note: + * Re-purpose Exclusion base/limit registers for Completion wait + * write-back base/limit. + */ + memcpy_toio(iommu->mmio_base + MMIO_EXCL_BASE_OFFSET, + &entry, sizeof(entry)); + + /* Note: + * Default to 4 Kbytes, which can be specified by setting base + * address equal to the limit address. + */ + memcpy_toio(iommu->mmio_base + MMIO_EXCL_LIMIT_OFFSET, + &entry, sizeof(entry)); +} + /* Programs the physical address of the device table into the IOMMU hardware */ static void iommu_set_device_table(struct amd_iommu *iommu) { @@ -1884,6 +1907,9 @@ static int __init amd_iommu_init_pci(void) ret = iommu_init_pci(iommu); if (ret) break; + + /* Need to setup range after PCI init */ + iommu_set_cwwb_range(iommu); } /* -- 2.20.1