Skip to content

Commit

Permalink
iommu/amd: Set the device table entry PPR bit for IOMMU V2 devices
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Gary R Hook authored and Alex Williamson committed Dec 20, 2017
1 parent f9fc049 commit ff18c4e
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 5 deletions.
20 changes: 15 additions & 5 deletions drivers/iommu/amd_iommu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1817,7 +1817,8 @@ static bool dma_ops_domain(struct protection_domain *domain)
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 flags = 0;
Expand All @@ -1834,6 +1835,13 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
if (ats)
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) {
u64 gcr3 = iommu_virt_to_phys(domain->gcr3_tbl);
u64 glx = domain->glx;
Expand Down Expand Up @@ -1896,9 +1904,9 @@ static void do_attach(struct iommu_dev_data *dev_data,
domain->dev_cnt += 1;

/* 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)
set_dte_entry(alias, domain, ats);
set_dte_entry(alias, domain, ats, dev_data->iommu_v2);

device_flush_dte(dev_data);
}
Expand Down Expand Up @@ -2277,13 +2285,15 @@ static void update_device_table(struct protection_domain *domain)
struct iommu_dev_data *dev_data;

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)
continue;

/* 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);
}
}

Expand Down
2 changes: 2 additions & 0 deletions drivers/iommu/amd_iommu_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
#define FEATURE_HE (1ULL<<8)
#define FEATURE_PC (1ULL<<9)
#define FEATURE_GAM_VAPIC (1ULL<<21)
#define FEATURE_EPHSUP (1ULL<<50)

#define FEATURE_PASID_SHIFT 32
#define FEATURE_PASID_MASK (0x1fULL << FEATURE_PASID_SHIFT)
Expand Down Expand Up @@ -192,6 +193,7 @@
/* macros and definitions for device table entries */
#define DEV_ENTRY_VALID 0x00
#define DEV_ENTRY_TRANSLATION 0x01
#define DEV_ENTRY_PPR 0x34
#define DEV_ENTRY_IR 0x3d
#define DEV_ENTRY_IW 0x3e
#define DEV_ENTRY_NO_PAGE_FAULT 0x62
Expand Down

0 comments on commit ff18c4e

Please sign in to comment.