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

[xen staging-4.20] x86/ept: batch PML p2m type-changes into single locked region



commit c7f876c99301152b470be5d39e8a0cef20681937
Author:     Roger Pau Monné <roger.pau@xxxxxxxxxx>
AuthorDate: Tue Jul 22 09:54:44 2025 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Tue Jul 22 09:54:44 2025 +0200

    x86/ept: batch PML p2m type-changes into single locked region
    
    The current p2m type-change loop in ept_vcpu_flush_pml_buffer() relies on
    each call to p2m_change_type_one() taking the p2m lock, doing the change
    and then dropping the lock and flushing the p2m.  Instead take the p2m lock
    outside of the loop, so that calls to gfn_{,un}lock() inside
    p2m_change_type_one() just take the p2m lock recursively, and more
    importantly, the flush is deferred until the p2m is unlocked in
    ept_vcpu_flush_pml_buffer().
    
    No functional change intended in the end result of
    ept_vcpu_flush_pml_buffer(), however a possibly noticeable performance
    improvement is expected.
    
    Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
    Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
    master commit: 060e9ab6e47bfe15dd1358332ea87e66c2d051f8
    master date: 2025-07-18 09:17:25 +0200
---
 xen/arch/x86/mm/p2m-ept.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/xen/arch/x86/mm/p2m-ept.c b/xen/arch/x86/mm/p2m-ept.c
index 015911ba6c..62fc8e5068 100644
--- a/xen/arch/x86/mm/p2m-ept.c
+++ b/xen/arch/x86/mm/p2m-ept.c
@@ -1375,6 +1375,8 @@ static void cf_check ept_flush_pml_buffers(struct 
p2m_domain *p2m)
 
 void ept_vcpu_flush_pml_buffer(struct vcpu *v)
 {
+    struct domain *d = v->domain;
+    struct p2m_domain *p2m = p2m_get_hostp2m(d);
     uint64_t *pml_buf;
     unsigned long pml_idx;
 
@@ -1401,6 +1403,12 @@ void ept_vcpu_flush_pml_buffer(struct vcpu *v)
     else
         pml_idx++;
 
+    /*
+     * Take the lock outside of the loop, so all the type changes are done
+     * inside of the same locked region and the EPT flush is deferred until the
+     * end of the loop.
+     */
+    p2m_lock(p2m);
     for ( ; pml_idx < NR_PML_ENTRIES; pml_idx++ )
     {
         unsigned long gfn = pml_buf[pml_idx] >> PAGE_SHIFT;
@@ -1413,11 +1421,12 @@ void ept_vcpu_flush_pml_buffer(struct vcpu *v)
          * are very rare, and additional cost is negligible, but a missing mark
          * is extremely difficult to debug.
          */
-        p2m_change_type_one(v->domain, gfn, p2m_ram_logdirty, p2m_ram_rw);
+        p2m_change_type_one(d, gfn, p2m_ram_logdirty, p2m_ram_rw);
 
         /* HVM guest: pfn == gfn */
-        paging_mark_pfn_dirty(v->domain, _pfn(gfn));
+        paging_mark_pfn_dirty(d, _pfn(gfn));
     }
+    p2m_unlock(p2m);
 
     unmap_domain_page(pml_buf);
 
--
generated by git-patchbot for /home/xen/git/xen.git#staging-4.20



 


Rackspace

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