amd_iommu: Add helper function to extract the DTE
Extracting the DTE from a given AMDVIAddressSpace pointer structure is a common operation required for syncing the shadow page tables. Implement a helper to do it and check for common error conditions. Signed-off-by: Alejandro Jimenez <alejandro.j.jimenez@oracle.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20250919213515.917111-6-alejandro.j.jimenez@oracle.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
e8992fee66
commit
786d118530
1 changed files with 42 additions and 6 deletions
|
|
@ -77,6 +77,18 @@ typedef struct AMDVIIOTLBEntry {
|
|||
uint64_t page_mask; /* physical page size */
|
||||
} AMDVIIOTLBEntry;
|
||||
|
||||
/*
|
||||
* These 'fault' reasons have an overloaded meaning since they are not only
|
||||
* intended for describing reasons that generate an IO_PAGE_FAULT as per the AMD
|
||||
* IOMMU specification, but are also used to signal internal errors in the
|
||||
* emulation code.
|
||||
*/
|
||||
typedef enum AMDVIFaultReason {
|
||||
AMDVI_FR_DTE_RTR_ERR = 1, /* Failure to retrieve DTE */
|
||||
AMDVI_FR_DTE_V, /* DTE[V] = 0 */
|
||||
AMDVI_FR_DTE_TV, /* DTE[TV] = 0 */
|
||||
} AMDVIFaultReason;
|
||||
|
||||
uint64_t amdvi_extended_feature_register(AMDVIState *s)
|
||||
{
|
||||
uint64_t feature = AMDVI_DEFAULT_EXT_FEATURES;
|
||||
|
|
@ -524,6 +536,28 @@ static inline uint64_t amdvi_get_pte_entry(AMDVIState *s, uint64_t pte_addr,
|
|||
return pte;
|
||||
}
|
||||
|
||||
static int amdvi_as_to_dte(AMDVIAddressSpace *as, uint64_t *dte)
|
||||
{
|
||||
uint16_t devid = PCI_BUILD_BDF(as->bus_num, as->devfn);
|
||||
AMDVIState *s = as->iommu_state;
|
||||
|
||||
if (!amdvi_get_dte(s, devid, dte)) {
|
||||
/* Unable to retrieve DTE for devid */
|
||||
return -AMDVI_FR_DTE_RTR_ERR;
|
||||
}
|
||||
|
||||
if (!(dte[0] & AMDVI_DEV_VALID)) {
|
||||
/* DTE[V] not set, address is passed untranslated for devid */
|
||||
return -AMDVI_FR_DTE_V;
|
||||
}
|
||||
|
||||
if (!(dte[0] & AMDVI_DEV_TRANSLATION_VALID)) {
|
||||
/* DTE[TV] not set, host page table not valid for devid */
|
||||
return -AMDVI_FR_DTE_TV;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* log error without aborting since linux seems to be using reserved bits */
|
||||
static void amdvi_inval_devtab_entry(AMDVIState *s, uint64_t *cmd)
|
||||
{
|
||||
|
|
@ -1081,6 +1115,7 @@ static void amdvi_do_translate(AMDVIAddressSpace *as, hwaddr addr,
|
|||
uint16_t devid = PCI_BUILD_BDF(as->bus_num, as->devfn);
|
||||
AMDVIIOTLBEntry *iotlb_entry = amdvi_iotlb_lookup(s, addr, devid);
|
||||
uint64_t entry[4];
|
||||
int dte_ret;
|
||||
|
||||
if (iotlb_entry) {
|
||||
trace_amdvi_iotlb_hit(PCI_BUS_NUM(devid), PCI_SLOT(devid),
|
||||
|
|
@ -1092,13 +1127,14 @@ static void amdvi_do_translate(AMDVIAddressSpace *as, hwaddr addr,
|
|||
return;
|
||||
}
|
||||
|
||||
if (!amdvi_get_dte(s, devid, entry)) {
|
||||
return;
|
||||
}
|
||||
dte_ret = amdvi_as_to_dte(as, entry);
|
||||
|
||||
/* devices with V = 0 are not translated */
|
||||
if (!(entry[0] & AMDVI_DEV_VALID)) {
|
||||
goto out;
|
||||
if (dte_ret < 0) {
|
||||
if (dte_ret == -AMDVI_FR_DTE_V) {
|
||||
/* DTE[V]=0, address is passed untranslated */
|
||||
goto out;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
amdvi_page_walk(as, entry, ret,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue