Avi Kivity wrote:
> Dong, Eddie wrote:
>> I observed 1-2 seconds faster in Windows XPSP2 ACPI bootup with
>> total of 23 seconds.
>> I can;t say it is exactly caused by this patch, but anyway it
>> simplifies the logic and code w/o any additional complexity.
>> thx,eddie 
>> 
>> 
>> 
> 
> Patch looks good, but will delay so that the guest scaling patch can
> be merged.  kvm_read_guest() will need to change to
> kvm_read_guest_inatomic(), since the mmu is becoming spinlocked.  

Rebased.
Thx, eddie

A guest non-aligned pte write or part of pte
update will leave shadow_trap_nonpresent_pte
in spte, which expects a new VM Exit at next
access time.

This patch fixed this by reading guest pte
in advance and thus be able to update spte
and reduce next VM Exit.

Signed-off-by: Yaozu (Eddie) Dong <[EMAIL PROTECTED]>

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index c478ee2..644254a 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1309,8 +1309,7 @@ static void mmu_pte_write_zap_pte(struct kvm_vcpu
*vcpu,
 static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu,
                                  struct kvm_mmu_page *sp,
                                  u64 *spte,
-                                 const void *new, int bytes,
-                                 int offset_in_pte)
+                                 const void *new)
 {
        if (sp->role.level != PT_PAGE_TABLE_LEVEL) {
                ++vcpu->kvm->stat.mmu_pde_zapped;
@@ -1319,9 +1318,9 @@ static void mmu_pte_write_new_pte(struct kvm_vcpu
*vcpu,
 
        ++vcpu->kvm->stat.mmu_pte_updated;
        if (sp->role.glevels == PT32_ROOT_LEVEL)
-               paging32_update_pte(vcpu, sp, spte, new, bytes,
offset_in_pte);
+               paging32_update_pte(vcpu, sp, spte, new);
        else
-               paging64_update_pte(vcpu, sp, spte, new, bytes,
offset_in_pte);
+               paging64_update_pte(vcpu, sp, spte, new);
 }
 
 static bool need_remote_flush(u64 old, u64 new)
@@ -1397,8 +1396,8 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu,
gpa_t gpa,
        struct hlist_node *node, *n;
        struct hlist_head *bucket;
        unsigned index;
-       u64 entry;
-       u64 *spte;
+       u64 entry, gentry;
+       u64 *spte, *gpte;
        unsigned offset = offset_in_page(gpa);
        unsigned pte_size;
        unsigned page_offset;
@@ -1407,6 +1406,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu,
gpa_t gpa,
        int level;
        int flooded = 0;
        int npte;
+       int r;
 
        pgprintk("%s: gpa %llx bytes %d\n", __FUNCTION__, gpa, bytes);
        mmu_guess_page_from_pte_write(vcpu, gpa, new, bytes);
@@ -1470,11 +1470,20 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu,
gpa_t gpa,
                                continue;
                }
                spte = &sp->spt[page_offset / sizeof(*spte)];
+               if ((gpa & (pte_size - 1)) || (bytes < pte_size)) {
+                       gentry = 0;
+                       gpte = &gentry;
+                       r = kvm_read_guest_atomic(vcpu->kvm,
+                                       gpa & ~(pte_size - 1),
+                                       gpte, pte_size);
+                       if (r < 0)
+                               continue;
+               } else
+                       gpte = (u64 *)new;
                while (npte--) {
                        entry = *spte;
                        mmu_pte_write_zap_pte(vcpu, sp, spte);
-                       mmu_pte_write_new_pte(vcpu, sp, spte, new,
bytes,
-                                             page_offset & (pte_size -
1));
+                       mmu_pte_write_new_pte(vcpu, sp, spte, gpte);
                        mmu_pte_write_flush_tlb(vcpu, entry, *spte);
                        ++spte;
                }
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index 03ba860..1678071 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -240,8 +240,7 @@ err:
 }
 
 static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct
kvm_mmu_page *page,
-                             u64 *spte, const void *pte, int bytes,
-                             int offset_in_pte)
+                             u64 *spte, const void *pte)
 {
        pt_element_t gpte;
        unsigned pte_access;
@@ -249,12 +248,10 @@ static void FNAME(update_pte)(struct kvm_vcpu
*vcpu, struct kvm_mmu_page *page,
 
        gpte = *(const pt_element_t *)pte;
        if (~gpte & (PT_PRESENT_MASK | PT_ACCESSED_MASK)) {
-               if (!offset_in_pte && !is_present_pte(gpte))
+               if (!is_present_pte(gpte))
                        set_shadow_pte(spte,
shadow_notrap_nonpresent_pte);
                return;
        }
-       if (bytes < sizeof(pt_element_t))
-               return;
        pgprintk("%s: gpte %llx spte %p\n", __FUNCTION__, (u64)gpte,
spte);
        pte_access = page->role.access & FNAME(gpte_access)(vcpu, gpte);
        if (gpte_to_gfn(gpte) != vcpu->arch.update_pte.gfn)

Attachment: tlb-prefetch.patch2
Description: tlb-prefetch.patch2

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
kvm-devel mailing list
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel

Reply via email to