mirror of https://gitee.com/openkylin/linux.git
iommu/amd: Set the device table entry PPR bit for IOMMU V2 devices
The AMD IOMMU specification Rev 3.00 (December 2016) introduces a new Enhanced PPR Handling Support (EPHSup) bit in the MMIO register offset 0030h (IOMMU Extended Feature Register). When EPHSup=1, the IOMMU hardware requires the PPR bit of the device table entry (DTE) to be set in order to support PPR for a particular endpoint device. Please see https://support.amd.com/TechDocs/48882_IOMMU.pdf for this revision of the AMD IOMMU specification. Signed-off-by: Gary R Hook <gary.hook@amd.com> Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
This commit is contained in:
parent
f9fc049ef1
commit
ff18c4e598
|
@ -1817,7 +1817,8 @@ static bool dma_ops_domain(struct protection_domain *domain)
|
||||||
return domain->flags & PD_DMA_OPS_MASK;
|
return domain->flags & PD_DMA_OPS_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
|
static void set_dte_entry(u16 devid, struct protection_domain *domain,
|
||||||
|
bool ats, bool ppr)
|
||||||
{
|
{
|
||||||
u64 pte_root = 0;
|
u64 pte_root = 0;
|
||||||
u64 flags = 0;
|
u64 flags = 0;
|
||||||
|
@ -1834,6 +1835,13 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
|
||||||
if (ats)
|
if (ats)
|
||||||
flags |= DTE_FLAG_IOTLB;
|
flags |= DTE_FLAG_IOTLB;
|
||||||
|
|
||||||
|
if (ppr) {
|
||||||
|
struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
|
||||||
|
|
||||||
|
if (iommu_feature(iommu, FEATURE_EPHSUP))
|
||||||
|
pte_root |= 1ULL << DEV_ENTRY_PPR;
|
||||||
|
}
|
||||||
|
|
||||||
if (domain->flags & PD_IOMMUV2_MASK) {
|
if (domain->flags & PD_IOMMUV2_MASK) {
|
||||||
u64 gcr3 = iommu_virt_to_phys(domain->gcr3_tbl);
|
u64 gcr3 = iommu_virt_to_phys(domain->gcr3_tbl);
|
||||||
u64 glx = domain->glx;
|
u64 glx = domain->glx;
|
||||||
|
@ -1896,9 +1904,9 @@ static void do_attach(struct iommu_dev_data *dev_data,
|
||||||
domain->dev_cnt += 1;
|
domain->dev_cnt += 1;
|
||||||
|
|
||||||
/* Update device table */
|
/* Update device table */
|
||||||
set_dte_entry(dev_data->devid, domain, ats);
|
set_dte_entry(dev_data->devid, domain, ats, dev_data->iommu_v2);
|
||||||
if (alias != dev_data->devid)
|
if (alias != dev_data->devid)
|
||||||
set_dte_entry(alias, domain, ats);
|
set_dte_entry(alias, domain, ats, dev_data->iommu_v2);
|
||||||
|
|
||||||
device_flush_dte(dev_data);
|
device_flush_dte(dev_data);
|
||||||
}
|
}
|
||||||
|
@ -2277,13 +2285,15 @@ static void update_device_table(struct protection_domain *domain)
|
||||||
struct iommu_dev_data *dev_data;
|
struct iommu_dev_data *dev_data;
|
||||||
|
|
||||||
list_for_each_entry(dev_data, &domain->dev_list, list) {
|
list_for_each_entry(dev_data, &domain->dev_list, list) {
|
||||||
set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled);
|
set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled,
|
||||||
|
dev_data->iommu_v2);
|
||||||
|
|
||||||
if (dev_data->devid == dev_data->alias)
|
if (dev_data->devid == dev_data->alias)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* There is an alias, update device table entry for it */
|
/* There is an alias, update device table entry for it */
|
||||||
set_dte_entry(dev_data->alias, domain, dev_data->ats.enabled);
|
set_dte_entry(dev_data->alias, domain, dev_data->ats.enabled,
|
||||||
|
dev_data->iommu_v2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,6 +98,7 @@
|
||||||
#define FEATURE_HE (1ULL<<8)
|
#define FEATURE_HE (1ULL<<8)
|
||||||
#define FEATURE_PC (1ULL<<9)
|
#define FEATURE_PC (1ULL<<9)
|
||||||
#define FEATURE_GAM_VAPIC (1ULL<<21)
|
#define FEATURE_GAM_VAPIC (1ULL<<21)
|
||||||
|
#define FEATURE_EPHSUP (1ULL<<50)
|
||||||
|
|
||||||
#define FEATURE_PASID_SHIFT 32
|
#define FEATURE_PASID_SHIFT 32
|
||||||
#define FEATURE_PASID_MASK (0x1fULL << FEATURE_PASID_SHIFT)
|
#define FEATURE_PASID_MASK (0x1fULL << FEATURE_PASID_SHIFT)
|
||||||
|
@ -192,6 +193,7 @@
|
||||||
/* macros and definitions for device table entries */
|
/* macros and definitions for device table entries */
|
||||||
#define DEV_ENTRY_VALID 0x00
|
#define DEV_ENTRY_VALID 0x00
|
||||||
#define DEV_ENTRY_TRANSLATION 0x01
|
#define DEV_ENTRY_TRANSLATION 0x01
|
||||||
|
#define DEV_ENTRY_PPR 0x34
|
||||||
#define DEV_ENTRY_IR 0x3d
|
#define DEV_ENTRY_IR 0x3d
|
||||||
#define DEV_ENTRY_IW 0x3e
|
#define DEV_ENTRY_IW 0x3e
|
||||||
#define DEV_ENTRY_NO_PAGE_FAULT 0x62
|
#define DEV_ENTRY_NO_PAGE_FAULT 0x62
|
||||||
|
|
Loading…
Reference in New Issue