From: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
To: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>,
Gleb Natapov <gleb@redhat.com>,
LKML <linux-kernel@vger.kernel.org>, KVM <kvm@vger.kernel.org>
Subject: [PATCH v2 2/5] KVM: MMU: adjust page size early if gfn used as page table
Date: Mon, 10 Dec 2012 17:13:03 +0800 [thread overview]
Message-ID: <50C5A79F.3020805@linux.vnet.ibm.com> (raw)
In-Reply-To: <50C5A747.1020105@linux.vnet.ibm.com>
We have two issues in current code:
- if target gfn is used as its page table, guest will refault then kvm will use
small page size to map it. We need two #PF to fix its shadow page table
- sometimes, say a exception is triggered during vm-exit caused by #PF
(see handle_exception() in vmx.c), we remove all the shadow pages shadowed
by the target gfn before go into page fault path, it will cause infinite
loop:
delete shadow pages shadowed by the gfn -> try to use large page size to map
the gfn -> retry the access ->...
To fix these, We can adjust page size early if the target gfn is used as page
table
Signed-off-by: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
---
arch/x86/kvm/mmu.c | 13 ++++---------
arch/x86/kvm/paging_tmpl.h | 33 ++++++++++++++++++++++++++++++++-
2 files changed, 36 insertions(+), 10 deletions(-)
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index 2a3c890..54fc61e 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -2380,15 +2380,10 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep,
if (pte_access & ACC_WRITE_MASK) {
/*
- * There are two cases:
- * - the one is other vcpu creates new sp in the window
- * between mapping_level() and acquiring mmu-lock.
- * - the another case is the new sp is created by itself
- * (page-fault path) when guest uses the target gfn as
- * its page table.
- * Both of these cases can be fixed by allowing guest to
- * retry the access, it will refault, then we can establish
- * the mapping by using small page.
+ * Other vcpu creates new sp in the window between
+ * mapping_level() and acquiring mmu-lock. We can
+ * allow guest to retry the access, the mapping can
+ * be fixed if guest refault.
*/
if (level > PT_PAGE_TABLE_LEVEL &&
has_wrprotected_page(vcpu->kvm, gfn, level))
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index ec481e9..32d77ff 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -491,6 +491,36 @@ out_gpte_changed:
return 0;
}
+ /*
+ * To see whether the mapped gfn can write its page table in the current
+ * mapping.
+ *
+ * It is the helper function of FNAME(page_fault). When guest uses large page
+ * size to map the writable gfn which is used as current page table, we should
+ * force kvm to use small page size to map it because new shadow page will be
+ * created when kvm establishes shadow page table that stop kvm using large
+ * page size. Do it early can avoid unnecessary #PF and emulation.
+ *
+ * Note: the PDPT page table is not checked for PAE-32 bit guest. It is ok
+ * since the PDPT is always shadowed, that means, we can not use large page
+ * size to map the gfn which is used as PDPT.
+ */
+static bool
+FNAME(mapped_gfn_can_write_current_pagetable)(struct guest_walker *walker)
+{
+ int level;
+ gfn_t mask = ~(KVM_PAGES_PER_HPAGE(walker->level) - 1);
+
+ if (!(walker->pte_access & ACC_WRITE_MASK))
+ return false;
+
+ for (level = walker->level; level <= walker->max_level; level++)
+ if (!((walker->gfn ^ walker->table_gfn[level - 1]) & mask))
+ return true;
+
+ return false;
+}
+
/*
* Page fault handler. There are several causes for a page fault:
* - there is no shadow pte for the guest pte
@@ -560,7 +590,8 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, u32 error_code,
}
if (walker.level >= PT_DIRECTORY_LEVEL)
- force_pt_level = mapping_level_dirty_bitmap(vcpu, walker.gfn);
+ force_pt_level = mapping_level_dirty_bitmap(vcpu, walker.gfn)
+ || FNAME(mapped_gfn_can_write_current_pagetable)(&walker);
else
force_pt_level = 1;
if (!force_pt_level) {
--
1.7.7.6
next prev parent reply other threads:[~2012-12-10 9:13 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-12-10 9:11 [PATCH v2 0/5] KVM: x86: improve reexecute_instruction Xiao Guangrong
2012-12-10 9:12 ` [PATCH v2 1/5] KVM: MMU: move adjusting pte access for softmmu to FNAME(page_fault) Xiao Guangrong
2012-12-11 23:47 ` Marcelo Tosatti
2012-12-12 18:53 ` Xiao Guangrong
2012-12-10 9:13 ` Xiao Guangrong [this message]
2012-12-12 0:57 ` [PATCH v2 2/5] KVM: MMU: adjust page size early if gfn used as page table Marcelo Tosatti
2012-12-12 19:23 ` Xiao Guangrong
2012-12-13 22:37 ` Marcelo Tosatti
2012-12-10 9:13 ` [PATCH v2 3/5] KVM: x86: clean up reexecute_instruction Xiao Guangrong
2012-12-10 9:14 ` [PATCH v2 4/5] KVM: x86: let reexecute_instruction work for tdp Xiao Guangrong
2012-12-10 9:14 ` [PATCH v2 5/5] KVM: x86: improve reexecute_instruction Xiao Guangrong
2012-12-12 1:09 ` Marcelo Tosatti
2012-12-12 19:29 ` Xiao Guangrong
2012-12-13 23:02 ` Marcelo Tosatti
2012-12-14 3:40 ` Xiao Guangrong
2012-12-11 23:36 ` [PATCH v2 0/5] " Marcelo Tosatti
2012-12-12 20:05 ` Xiao Guangrong
2012-12-13 22:54 ` Marcelo Tosatti
2012-12-14 4:50 ` Xiao Guangrong
2012-12-15 1:05 ` Marcelo Tosatti
2012-12-23 11:46 ` Gleb Natapov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=50C5A79F.3020805@linux.vnet.ibm.com \
--to=xiaoguangrong@linux.vnet.ibm.com \
--cc=gleb@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mtosatti@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).