[PATCH 1/4] x86: extend update_intpte() to support atomic get-and-update

Kevin Lampis <[email protected]>
Newsgroups org.xenproject.lists.xen-devel
Message-ID <[email protected]>
The update_intpte() function now accepts a new use_cmpxchg flag and if set
returns the old pte value through the new *old pointer.

No functional change for existing callers.

Signed-off-by: Kevin Lampis <[email protected]>
---
 xen/arch/x86/pv/mm.h | 29 ++++++++++++++++++-----------
 1 file changed, 18 insertions(+), 11 deletions(-)

diff --git a/xen/arch/x86/pv/mm.h b/xen/arch/x86/pv/mm.h
index 4564cab9fc0f..8c42cf3b3f4d 100644
--- a/xen/arch/x86/pv/mm.h
+++ b/xen/arch/x86/pv/mm.h
@@ -66,13 +66,14 @@ static inline intpte_t paging_cmpxchg_guest_entry(
  * How to write an entry to the guest pagetables.
  * Returns false for failure (pointer not valid), true for success.
  */
-static inline bool update_intpte(intpte_t *p, intpte_t old, intpte_t new,
-                                 mfn_t mfn, struct vcpu *v, bool preserve_ad)
+static inline bool update_intpte(intpte_t *p, intpte_t *old, intpte_t new,
+                                 mfn_t mfn, struct vcpu *v, bool preserve_ad,
+                                 bool use_cmpxchg)
 {
     bool rv = true;
 
 #ifndef PTE_UPDATE_WITH_CMPXCHG
-    if ( !preserve_ad )
+    if ( !preserve_ad && !use_cmpxchg )
         paging_write_guest_entry(v, p, new, mfn);
     else
 #endif
@@ -82,30 +83,36 @@ static inline bool update_intpte(intpte_t *p, intpte_t old, intpte_t new,
             intpte_t _new = new, t;
 
             if ( preserve_ad )
-                _new |= old & (_PAGE_ACCESSED | _PAGE_DIRTY);
+                _new |= *old & (_PAGE_ACCESSED | _PAGE_DIRTY);
 
-            t = paging_cmpxchg_guest_entry(v, p, old, _new, mfn);
+            t = paging_cmpxchg_guest_entry(v, p, *old, _new, mfn);
 
-            if ( t == old )
+            if ( t == *old )
                 break;
 
             /* Allowed to change in Accessed/Dirty flags only. */
-            BUG_ON((t ^ old) & ~(intpte_t)(_PAGE_ACCESSED|_PAGE_DIRTY));
+            BUG_ON((t ^ *old) & ~(intpte_t)(_PAGE_ACCESSED|_PAGE_DIRTY));
 
-            old = t;
+            *old = t;
         }
     }
     return rv;
 }
 
+static inline bool _update_intpte(intpte_t *p, intpte_t old, intpte_t new,
+                                  mfn_t mfn, struct vcpu *v, bool preserve_ad)
+{
+    return update_intpte(p, &old, new, mfn, v, preserve_ad, false);
+}
+
 /*
  * Macro that wraps the appropriate type-changes around update_intpte().
  * Arguments are: type, ptr, old, new, mfn, vcpu
  */
 #define UPDATE_ENTRY(_t,_p,_o,_n,_m,_v,_ad)                         \
-    update_intpte(&_t ## e_get_intpte(*(_p)),                       \
-                  _t ## e_get_intpte(_o), _t ## e_get_intpte(_n),   \
-                  (_m), (_v), (_ad))
+    _update_intpte(&_t ## e_get_intpte(*(_p)),                      \
+                   _t ## e_get_intpte(_o), _t ## e_get_intpte(_n),  \
+                   (_m), (_v), (_ad))
 
 static always_inline l1_pgentry_t adjust_guest_l1e(l1_pgentry_t l1e,
                                                    const struct domain *d)
-- 
2.52.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.