]> xenbits.xensource.com Git - xen.git/commitdiff
IOMMU: also pass p2m_access_t to p2m_get_iommu_flags()
authorJan Beulich <jbeulich@suse.com>
Wed, 25 Aug 2021 14:00:52 +0000 (16:00 +0200)
committerJan Beulich <jbeulich@suse.com>
Wed, 25 Aug 2021 14:00:52 +0000 (16:00 +0200)
A subsequent change will want to customize the IOMMU permissions based
on this.

This is part of XSA-378.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Paul Durrant <paul@xen.org>
master commit: d1bb6c97c31ef754fb29b29eb307c090414e8022
master date: 2021-08-25 14:15:32 +0200

xen/arch/x86/mm/p2m-ept.c
xen/arch/x86/mm/p2m-pt.c
xen/include/asm-x86/p2m.h

index e0fec73e3f5eb1028ceaf4f9cb2f74c55c3bc7e8..b4e8d91a94c73ae38d687ae35e0d5f203711226e 100644 (file)
@@ -711,7 +711,7 @@ ept_set_entry(struct p2m_domain *p2m, gfn_t gfn_, mfn_t mfn,
     uint8_t ipat = 0;
     bool_t need_modify_vtd_table = 1;
     bool_t vtd_pte_present = 0;
-    unsigned int iommu_flags = p2m_get_iommu_flags(p2mt, mfn);
+    unsigned int iommu_flags = p2m_get_iommu_flags(p2mt, p2ma, mfn);
     bool_t needs_sync = 1;
     ept_entry_t old_entry = { .epte = 0 };
     ept_entry_t new_entry = { .epte = 0 };
@@ -837,8 +837,8 @@ ept_set_entry(struct p2m_domain *p2m, gfn_t gfn_, mfn_t mfn,
 
         /* Safe to read-then-write because we hold the p2m lock */
         if ( ept_entry->mfn == new_entry.mfn &&
-             p2m_get_iommu_flags(ept_entry->sa_p2mt, _mfn(ept_entry->mfn)) ==
-             iommu_flags )
+             p2m_get_iommu_flags(ept_entry->sa_p2mt, ept_entry->access,
+                                 _mfn(ept_entry->mfn)) == iommu_flags )
             need_modify_vtd_table = 0;
 
         ept_p2m_type_to_flags(p2m, &new_entry, p2mt, p2ma);
index b8c5d2ed26eb5bd0102d613a1587ad66a2fb391c..0ea41a6ec5f89d06ca01528dc24603715b6cdef0 100644 (file)
@@ -471,6 +471,16 @@ int p2m_pt_handle_deferred_changes(uint64_t gpa)
     return rc;
 }
 
+/* Reconstruct a fake p2m_access_t from stored PTE flags. */
+static p2m_access_t p2m_flags_to_access(unsigned int flags)
+{
+    if ( flags & _PAGE_PRESENT )
+        return p2m_access_n;
+
+    /* No need to look at _PAGE_NX for now. */
+    return flags & _PAGE_RW ? p2m_access_rw : p2m_access_r;
+}
+
 /* Returns: 0 for success, -errno for failure */
 static int
 p2m_pt_set_entry(struct p2m_domain *p2m, gfn_t gfn_, mfn_t mfn,
@@ -487,7 +497,7 @@ p2m_pt_set_entry(struct p2m_domain *p2m, gfn_t gfn_, mfn_t mfn,
     l2_pgentry_t l2e_content;
     l3_pgentry_t l3e_content;
     int rc;
-    unsigned int iommu_pte_flags = p2m_get_iommu_flags(p2mt, mfn);
+    unsigned int iommu_pte_flags = p2m_get_iommu_flags(p2mt, p2ma, mfn);
     /*
      * old_mfn and iommu_old_flags control possible flush/update needs on the
      * IOMMU: We need to flush when MFN or flags (i.e. permissions) change.
@@ -556,6 +566,7 @@ p2m_pt_set_entry(struct p2m_domain *p2m, gfn_t gfn_, mfn_t mfn,
                 old_mfn = l1e_get_pfn(*p2m_entry);
                 iommu_old_flags =
                     p2m_get_iommu_flags(p2m_flags_to_type(flags),
+                                        p2m_flags_to_access(flags),
                                         _mfn(old_mfn));
             }
             else
@@ -602,9 +613,10 @@ p2m_pt_set_entry(struct p2m_domain *p2m, gfn_t gfn_, mfn_t mfn,
                                    0, L1_PAGETABLE_ENTRIES);
         ASSERT(p2m_entry);
         old_mfn = l1e_get_pfn(*p2m_entry);
+        flags = l1e_get_flags(*p2m_entry);
         iommu_old_flags =
-            p2m_get_iommu_flags(p2m_flags_to_type(l1e_get_flags(*p2m_entry)),
-                                _mfn(old_mfn));
+            p2m_get_iommu_flags(p2m_flags_to_type(flags),
+                                p2m_flags_to_access(flags), _mfn(old_mfn));
 
         if ( mfn_valid(mfn) || p2m_allows_invalid_mfn(p2mt) )
             entry_content = p2m_l1e_from_pfn(mfn_x(mfn),
@@ -648,6 +660,7 @@ p2m_pt_set_entry(struct p2m_domain *p2m, gfn_t gfn_, mfn_t mfn,
                 old_mfn = l1e_get_pfn(*p2m_entry);
                 iommu_old_flags =
                     p2m_get_iommu_flags(p2m_flags_to_type(flags),
+                                        p2m_flags_to_access(flags),
                                         _mfn(old_mfn));
             }
             else
index 3f41deaeea64124579ee0baa265353b43e128a09..ebba14a85c6745d35821b3e97e7dee1700cfdb54 100644 (file)
@@ -839,7 +839,8 @@ int p2m_altp2m_propagate_change(struct domain *d, gfn_t gfn,
 /*
  * p2m type to IOMMU flags
  */
-static inline unsigned int p2m_get_iommu_flags(p2m_type_t p2mt, mfn_t mfn)
+static inline unsigned int p2m_get_iommu_flags(p2m_type_t p2mt,
+                                               p2m_access_t p2ma, mfn_t mfn)
 {
     unsigned int flags;