diff mbox series

[RFC,01/10] amd-iommu: Cache PTE/DTE info in IOTLB

Message ID 20220428211351.3897-2-joao.m.martins@oracle.com (mailing list archive)
State New, archived
Headers show
Series hw/vfio, x86/iommu: IOMMUFD Dirty Tracking | expand

Commit Message

Joao Martins April 28, 2022, 9:13 p.m. UTC
On a successful translation, cache the PTE and DTE
flags set at the time of the translation i.e. the first 12bits
as well as the PTE storage. These bits contain read, write,
dirty and access for example. In theory the DTE lookup takes
precendence in the translation path, but in the interest of
performance extend the AMDVIIOTLBEntry to include that information.

This is a preparatory for AMD HDSup/HASup which requires updating
A/D bits off the PTE (even after its insertion in the IOTLB) based
on the fact that HAD bits (0x3 or 0x1) were set on the Device
Table Entry.

Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
---
 hw/i386/amd_iommu.c | 24 +++++++++++++++++++-----
 1 file changed, 19 insertions(+), 5 deletions(-)
diff mbox series

Patch

diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c
index ea8eaeb330b6..25b5c3be70ea 100644
--- a/hw/i386/amd_iommu.c
+++ b/hw/i386/amd_iommu.c
@@ -72,6 +72,9 @@  typedef struct AMDVIIOTLBEntry {
     uint64_t perms;             /* access permissions  */
     uint64_t translated_addr;   /* translated address  */
     uint64_t page_mask;         /* physical page size  */
+    uint16_t dte_flags;         /* device table entry flags */
+    uint64_t pte;               /* pte entry */
+    uint64_t pte_addr;          /* pte entry iova */
 } AMDVIIOTLBEntry;
 
 /* configure MMIO registers at startup/reset */
@@ -340,7 +343,8 @@  static void amdvi_iotlb_remove_page(AMDVIState *s, hwaddr addr,
 
 static void amdvi_update_iotlb(AMDVIState *s, uint16_t devid,
                                uint64_t gpa, IOMMUTLBEntry to_cache,
-                               uint16_t domid)
+                               uint16_t domid, uint16_t dte_flags,
+                               uint64_t pte, uint64_t pte_addr)
 {
     AMDVIIOTLBEntry *entry = g_new(AMDVIIOTLBEntry, 1);
     uint64_t *key = g_new(uint64_t, 1);
@@ -359,6 +363,9 @@  static void amdvi_update_iotlb(AMDVIState *s, uint16_t devid,
         entry->perms = to_cache.perm;
         entry->translated_addr = to_cache.translated_addr;
         entry->page_mask = to_cache.addr_mask;
+        entry->dte_flags = dte_flags;
+        entry->pte = pte;
+        entry->pte_addr = pte_addr;
         *key = gfn | ((uint64_t)(devid) << AMDVI_DEVID_SHIFT);
         g_hash_table_replace(s->iotlb, key, entry);
     }
@@ -896,7 +903,8 @@  static inline uint64_t amdvi_get_pte_entry(AMDVIState *s, uint64_t pte_addr,
 
 static void amdvi_page_walk(AMDVIAddressSpace *as, uint64_t *dte,
                             IOMMUTLBEntry *ret, unsigned perms,
-                            hwaddr addr)
+                            hwaddr addr, uint64_t *iotlb_pte,
+                            uint64_t *iotlb_pte_addr)
 {
     unsigned level, present, pte_perms, oldlevel;
     uint64_t pte = dte[0], pte_addr, page_mask;
@@ -945,6 +953,8 @@  static void amdvi_page_walk(AMDVIAddressSpace *as, uint64_t *dte,
         ret->translated_addr = (pte & AMDVI_DEV_PT_ROOT_MASK) & page_mask;
         ret->addr_mask = ~page_mask;
         ret->perm = amdvi_get_perms(pte);
+        *iotlb_pte = pte;
+        *iotlb_pte_addr = addr;
         return;
     }
 no_remap:
@@ -952,6 +962,8 @@  no_remap:
     ret->translated_addr = addr & AMDVI_PAGE_MASK_4K;
     ret->addr_mask = ~AMDVI_PAGE_MASK_4K;
     ret->perm = amdvi_get_perms(pte);
+    *iotlb_pte = pte;
+    *iotlb_pte_addr = addr;
 }
 
 static void amdvi_do_translate(AMDVIAddressSpace *as, hwaddr addr,
@@ -960,7 +972,7 @@  static void amdvi_do_translate(AMDVIAddressSpace *as, hwaddr addr,
     AMDVIState *s = as->iommu_state;
     uint16_t devid = PCI_BUILD_BDF(as->bus_num, as->devfn);
     AMDVIIOTLBEntry *iotlb_entry = amdvi_iotlb_lookup(s, addr, devid);
-    uint64_t entry[4];
+    uint64_t entry[4], pte, pte_addr;
 
     if (iotlb_entry) {
         trace_amdvi_iotlb_hit(PCI_BUS_NUM(devid), PCI_SLOT(devid),
@@ -982,10 +994,12 @@  static void amdvi_do_translate(AMDVIAddressSpace *as, hwaddr addr,
     }
 
     amdvi_page_walk(as, entry, ret,
-                    is_write ? AMDVI_PERM_WRITE : AMDVI_PERM_READ, addr);
+                    is_write ? AMDVI_PERM_WRITE : AMDVI_PERM_READ, addr,
+                    &pte, &pte_addr);
 
     amdvi_update_iotlb(s, devid, addr, *ret,
-                       entry[1] & AMDVI_DEV_DOMID_ID_MASK);
+                       entry[1] & AMDVI_DEV_DOMID_ID_MASK,
+                       entry[0] & ~AMDVI_DEV_PT_ROOT_MASK, pte, pte_addr);
     return;
 
 out: