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

[Xen-changelog] [xen staging] x86/mm: add explicit preemption checks to L3 (un)validation



commit bac4567a67d5e8b916801ea5a04cf8b443dfb245
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Tue Mar 5 13:51:46 2019 +0100
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Tue Mar 5 13:51:46 2019 +0100

    x86/mm: add explicit preemption checks to L3 (un)validation
    
    When recursive page tables are used at the L3 level, unvalidation of a
    single L4 table may incur unvalidation of two levels of L3 tables, i.e.
    a maximum iteration count of 512^3 for unvalidating an L4 table. The
    preemption check in free_l2_table() as well as the one in
    _put_page_type() may never be reached, so explicit checking is needed in
    free_l3_table().
    
    When recursive page tables are used at the L4 level, the iteration count
    at L4 alone is capped at 512^2. As soon as a present L3 entry is hit
    which itself needs unvalidation (and hence requiring another nested loop
    with 512 iterations), the preemption checks added here kick in, so no
    further preemption checking is needed at L4 (until we decide to permit
    5-level paging for PV guests).
    
    The validation side additions are done just for symmetry.
    
    This is part of XSA-290.
    
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
 xen/arch/x86/mm.c | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index f970f509a5..90e082ed27 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -1604,6 +1604,13 @@ static int alloc_l3_table(struct page_info *page)
     {
         l3_pgentry_t l3e = pl3e[i];
 
+        if ( i > page->nr_validated_ptes && hypercall_preempt_check() )
+        {
+            page->nr_validated_ptes = i;
+            rc = -ERESTART;
+            break;
+        }
+
         if ( is_pv_32bit_domain(d) && (i == 3) )
         {
             if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) ||
@@ -1924,15 +1931,25 @@ static int free_l3_table(struct page_info *page)
 
     pl3e = map_domain_page(_mfn(pfn));
 
-    do {
+    for ( ; ; )
+    {
         rc = put_page_from_l3e(pl3e[i], pfn, partial, 0);
         if ( rc < 0 )
             break;
+
         partial = 0;
-        if ( rc > 0 )
-            continue;
-        pl3e[i] = unadjust_guest_l3e(pl3e[i], d);
-    } while ( i-- );
+        if ( rc == 0 )
+            pl3e[i] = unadjust_guest_l3e(pl3e[i], d);
+
+        if ( !i-- )
+            break;
+
+        if ( hypercall_preempt_check() )
+        {
+            rc = -EINTR;
+            break;
+        }
+    }
 
     unmap_domain_page(pl3e);
 
--
generated by git-patchbot for /home/xen/git/xen.git#staging

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

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