public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] KVM: More fixes for 2.6.21-rc3
@ 2007-03-11 10:07 Avi Kivity
       [not found] ` <11736076283998-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
  0 siblings, 1 reply; 5+ messages in thread
From: Avi Kivity @ 2007-03-11 10:07 UTC (permalink / raw)
  To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA

This patchset contains fixes I plan to submit pre 2.6.21: a fix for
large memory 32-bit hosts, and a fix for non-pae 32-bit guests.



-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH] KVM: MMU: Fix guest writes to nonpae pde
       [not found] ` <11736076283998-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
@ 2007-03-11 10:07   ` Avi Kivity
  2007-03-11 10:32     ` [kvm-devel] " Ingo Molnar
  2007-03-11 10:07   ` [PATCH] KVM: MMU: Fix host memory corruption on i386 with >= 4GB ram Avi Kivity
  1 sibling, 1 reply; 5+ messages in thread
From: Avi Kivity @ 2007-03-11 10:07 UTC (permalink / raw)
  To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA

KVM shadow page tables are always in pae mode, regardless of the guest
setting.  This means that a guest pde (mapping 4MB of memory) is mapped
to two shadow pdes (mapping 2MB each).

When the guest writes to a pte or pde, we intercept the write and emulate it.
We also remove any shadowed mappings corresponding to the write.  Since the
mmu did not account for the doubling in the number of pdes, it removed the
wrong entry, resulting in a mismatch between shadow page tables and guest
page tables, followed shortly by guest memory corruption.

This patch fixes the problem by detecting the special case of writing to
a non-pae pde and adjusting the address and number of shadow pdes zapped
accordingly.

Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
 drivers/kvm/mmu.c |   46 ++++++++++++++++++++++++++++++++++------------
 1 files changed, 34 insertions(+), 12 deletions(-)

diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index a1a9336..2cb4893 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -1093,22 +1093,40 @@ out:
 	return r;
 }
 
+static void mmu_pre_write_zap_pte(struct kvm_vcpu *vcpu,
+				  struct kvm_mmu_page *page,
+				  u64 *spte)
+{
+	u64 pte;
+	struct kvm_mmu_page *child;
+
+	pte = *spte;
+	if (is_present_pte(pte)) {
+		if (page->role.level == PT_PAGE_TABLE_LEVEL)
+			rmap_remove(vcpu, spte);
+		else {
+			child = page_header(pte & PT64_BASE_ADDR_MASK);
+			mmu_page_remove_parent_pte(vcpu, child, spte);
+		}
+	}
+	*spte = 0;
+}
+
 void kvm_mmu_pre_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes)
 {
 	gfn_t gfn = gpa >> PAGE_SHIFT;
 	struct kvm_mmu_page *page;
-	struct kvm_mmu_page *child;
 	struct hlist_node *node, *n;
 	struct hlist_head *bucket;
 	unsigned index;
 	u64 *spte;
-	u64 pte;
 	unsigned offset = offset_in_page(gpa);
 	unsigned pte_size;
 	unsigned page_offset;
 	unsigned misaligned;
 	int level;
 	int flooded = 0;
+	int npte;
 
 	pgprintk("%s: gpa %llx bytes %d\n", __FUNCTION__, gpa, bytes);
 	if (gfn == vcpu->last_pt_write_gfn) {
@@ -1144,22 +1162,26 @@ void kvm_mmu_pre_write(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes)
 		}
 		page_offset = offset;
 		level = page->role.level;
+		npte = 1;
 		if (page->role.glevels == PT32_ROOT_LEVEL) {
-			page_offset <<= 1;          /* 32->64 */
+			page_offset <<= 1;	/* 32->64 */
+			/*
+			 * A 32-bit pde maps 4MB while the shadow pdes map
+			 * only 2MB.  So we need to double the offset again
+			 * and zap two pdes instead of one.
+			 */
+			if (level == PT32_ROOT_LEVEL) {
+				page_offset <<= 1;
+				npte = 2;
+			}
 			page_offset &= ~PAGE_MASK;
 		}
 		spte = __va(page->page_hpa);
 		spte += page_offset / sizeof(*spte);
-		pte = *spte;
-		if (is_present_pte(pte)) {
-			if (level == PT_PAGE_TABLE_LEVEL)
-				rmap_remove(vcpu, spte);
-			else {
-				child = page_header(pte & PT64_BASE_ADDR_MASK);
-				mmu_page_remove_parent_pte(vcpu, child, spte);
-			}
+		while (npte--) {
+			mmu_pre_write_zap_pte(vcpu, page, spte);
+			++spte;
 		}
-		*spte = 0;
 	}
 }
 
-- 
1.5.0.2


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH] KVM: MMU: Fix host memory corruption on i386 with >= 4GB ram
       [not found] ` <11736076283998-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
  2007-03-11 10:07   ` [PATCH] KVM: MMU: Fix guest writes to nonpae pde Avi Kivity
@ 2007-03-11 10:07   ` Avi Kivity
  2007-03-11 10:33     ` [kvm-devel] " Ingo Molnar
  1 sibling, 1 reply; 5+ messages in thread
From: Avi Kivity @ 2007-03-11 10:07 UTC (permalink / raw)
  To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA

PAGE_MASK is an unsigned long, so using it to mask physical addresses on
i386 (which are 64-bit wide) leads to truncation.  This can result in
page->private of unrelated memory pages being modified, with disasterous
results.

Fix by not using PAGE_MASK for physical addresses; instead calculate
the correct value directly from PAGE_SIZE.  Also fix a similar BUG_ON().

Signed-off-by: Avi Kivity <avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
---
 drivers/kvm/mmu.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/kvm/mmu.c b/drivers/kvm/mmu.c
index 2cb4893..e85b4c7 100644
--- a/drivers/kvm/mmu.c
+++ b/drivers/kvm/mmu.c
@@ -131,7 +131,7 @@ static int dbg = 1;
 	(((address) >> PT32_LEVEL_SHIFT(level)) & ((1 << PT32_LEVEL_BITS) - 1))
 
 
-#define PT64_BASE_ADDR_MASK (((1ULL << 52) - 1) & PAGE_MASK)
+#define PT64_BASE_ADDR_MASK (((1ULL << 52) - 1) & ~(u64)(PAGE_SIZE-1))
 #define PT64_DIR_BASE_ADDR_MASK \
 	(PT64_BASE_ADDR_MASK & ~((1ULL << (PAGE_SHIFT + PT64_LEVEL_BITS)) - 1))
 
@@ -406,8 +406,8 @@ static void rmap_write_protect(struct kvm_vcpu *vcpu, u64 gfn)
 			spte = desc->shadow_ptes[0];
 		}
 		BUG_ON(!spte);
-		BUG_ON((*spte & PT64_BASE_ADDR_MASK) !=
-		       page_to_pfn(page) << PAGE_SHIFT);
+		BUG_ON((*spte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT
+		       != page_to_pfn(page));
 		BUG_ON(!(*spte & PT_PRESENT_MASK));
 		BUG_ON(!(*spte & PT_WRITABLE_MASK));
 		rmap_printk("rmap_write_protect: spte %p %llx\n", spte, *spte);
-- 
1.5.0.2


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [kvm-devel] [PATCH] KVM: MMU: Fix guest writes to nonpae pde
  2007-03-11 10:07   ` [PATCH] KVM: MMU: Fix guest writes to nonpae pde Avi Kivity
@ 2007-03-11 10:32     ` Ingo Molnar
  0 siblings, 0 replies; 5+ messages in thread
From: Ingo Molnar @ 2007-03-11 10:32 UTC (permalink / raw)
  To: Avi Kivity; +Cc: kvm-devel, linux-kernel


* Avi Kivity <avi@qumranet.com> wrote:

> KVM shadow page tables are always in pae mode, regardless of the guest 
> setting.  This means that a guest pde (mapping 4MB of memory) is 
> mapped to two shadow pdes (mapping 2MB each).
> 
> When the guest writes to a pte or pde, we intercept the write and 
> emulate it. We also remove any shadowed mappings corresponding to the 
> write.  Since the mmu did not account for the doubling in the number 
> of pdes, it removed the wrong entry, resulting in a mismatch between 
> shadow page tables and guest page tables, followed shortly by guest 
> memory corruption.
> 
> This patch fixes the problem by detecting the special case of writing 
> to a non-pae pde and adjusting the address and number of shadow pdes 
> zapped accordingly.
> 
> Signed-off-by: Avi Kivity <avi@qumranet.com>

tested this with both PAE and non-PAE Linux host and guest - works fine.

Acked-by: Ingo Molnar <mingo@elte.hu>

	Ingo

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [kvm-devel] [PATCH] KVM: MMU: Fix host memory corruption on i386 with >= 4GB ram
  2007-03-11 10:07   ` [PATCH] KVM: MMU: Fix host memory corruption on i386 with >= 4GB ram Avi Kivity
@ 2007-03-11 10:33     ` Ingo Molnar
  0 siblings, 0 replies; 5+ messages in thread
From: Ingo Molnar @ 2007-03-11 10:33 UTC (permalink / raw)
  To: Avi Kivity; +Cc: kvm-devel, linux-kernel


* Avi Kivity <avi@qumranet.com> wrote:

> PAGE_MASK is an unsigned long, so using it to mask physical addresses 
> on i386 (which are 64-bit wide) leads to truncation.  This can result 
> in page->private of unrelated memory pages being modified, with 
> disasterous results.
> 
> Fix by not using PAGE_MASK for physical addresses; instead calculate 
> the correct value directly from PAGE_SIZE.  Also fix a similar 
> BUG_ON().
> 
> Signed-off-by: Avi Kivity <avi@qumranet.com>

i have tested this, albeit with less than 4GB RAM.

Acked-by: Ingo Molnar <mingo@elte.hu>

	Ingo

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2007-03-11 10:33 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-03-11 10:07 [PATCH 0/2] KVM: More fixes for 2.6.21-rc3 Avi Kivity
     [not found] ` <11736076283998-git-send-email-avi-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-03-11 10:07   ` [PATCH] KVM: MMU: Fix guest writes to nonpae pde Avi Kivity
2007-03-11 10:32     ` [kvm-devel] " Ingo Molnar
2007-03-11 10:07   ` [PATCH] KVM: MMU: Fix host memory corruption on i386 with >= 4GB ram Avi Kivity
2007-03-11 10:33     ` [kvm-devel] " Ingo Molnar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox