[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen staging] revert "x86/mm: re-implement get_page_light() using an atomic increment"



commit b819bd65f4fb25be582f66ba2e4134f61d86f459
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Tue Apr 30 08:37:19 2024 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Tue Apr 30 08:37:19 2024 +0200

    revert "x86/mm: re-implement get_page_light() using an atomic increment"
    
    This reverts commit c40bc0576dcc5acd4d7e22ef628eb4642f568533.
    
    That change aimed at eliminating an open-coded lock-like construct,
    which really isn't all that similar to, in particular, get_page(). The
    function always succeeds. Any remaining concern would want taking care
    of by placing block_lock_speculation() at the end of the function.
    Since the function is called only during page (de)validation, any
    possible performance concerns over such extra serialization could
    likely be addressed by pre-validating (e.g. via pinning) page tables.
    
    The fundamental issue with the change being reverted is that it detects
    bad state only after already having caused possible corruption. While
    the system is going to be halted in such an event, there is a time
    window during which the resulting incorrect state could be leveraged by
    a clever (in particular: fast enough) attacker.
    
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Acked-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
    Acked-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
---
 xen/arch/x86/mm.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 87529db7d1..d968bbbc73 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -2582,10 +2582,16 @@ bool get_page(struct page_info *page, const struct 
domain *domain)
  */
 static void get_page_light(struct page_info *page)
 {
-    unsigned long old_pgc = arch_fetch_and_add(&page->count_info, 1);
+    unsigned long x, nx, y = page->count_info;
 
-    BUG_ON(!(old_pgc & PGC_count_mask)); /* Not allocated? */
-    BUG_ON(!((old_pgc + 1) & PGC_count_mask)); /* Overflow? */
+    do {
+        x  = y;
+        nx = x + 1;
+        BUG_ON(!(x & PGC_count_mask)); /* Not allocated? */
+        BUG_ON(!(nx & PGC_count_mask)); /* Overflow? */
+        y = cmpxchg(&page->count_info, x, nx);
+    }
+    while ( unlikely(y != x) );
 }
 
 static int validate_page(struct page_info *page, unsigned long type,
--
generated by git-patchbot for /home/xen/git/xen.git#staging



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.