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
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 401eb7c..b2fd336 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1285,8 +1285,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;
@@ -1295,9 +1294,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)
@@ -1336,8 +1335,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;
@@ -1346,6 +1345,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);
++vcpu->kvm->stat.mmu_pte_write;
@@ -1406,11 +1406,19 @@ 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(vcpu->kvm, gpa & ~(pte_size -
1),
+ gpte, pte_size);
+ if (r < 0)
+ continue;
+ } else
+ gpte = 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 56b88f7..4e4d859 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -240,20 +240,17 @@ 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;
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);
mmu_set_spte(vcpu, spte, page->role.access, pte_access, 0, 0,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h
tlb-clean3.patch
Description: tlb-clean3.patch
------------------------------------------------------------------------- SF.Net email is sponsored by: Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source. http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace
_______________________________________________ kvm-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/kvm-devel
