All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] KVM: MMU: Replace role.glevels with role.cr4_pae
@ 2010-04-14 16:20 Avi Kivity
  2010-04-14 16:32 ` Avi Kivity
  2010-04-15 16:58 ` Marcelo Tosatti
  0 siblings, 2 replies; 5+ messages in thread
From: Avi Kivity @ 2010-04-14 16:20 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: kvm

There is no real distinction between glevels=3 and glevels=4; both have
exactly the same format and the code is treated exactly the same way.  Drop
role.glevels and replace is with role.cr4_pae (which is meaningful).  This
simplifies the code a bit.

As a side effect, it allows sharing shadow page tables between pae and
longmode guest page tables at the same guest page.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 arch/x86/include/asm/kvm_host.h |    2 +-
 arch/x86/kvm/mmu.c              |   12 ++++++------
 arch/x86/kvm/mmutrace.h         |    5 +++--
 3 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 0c49c88..90530a6 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -171,8 +171,8 @@ struct kvm_pte_chain {
 union kvm_mmu_page_role {
 	unsigned word;
 	struct {
-		unsigned glevels:4;
 		unsigned level:4;
+		unsigned cr4_pae:1;
 		unsigned quadrant:2;
 		unsigned pad_for_nice_hex_output:6;
 		unsigned direct:1;
diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index b44380b..edfef80 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -1205,7 +1205,7 @@ static int kvm_mmu_zap_page(struct kvm *kvm, struct kvm_mmu_page *sp);
 
 static int kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 {
-	if (sp->role.glevels != vcpu->arch.mmu.root_level) {
+	if (sp->role.cr4_pae != !!is_pae(vcpu)) {
 		kvm_mmu_zap_page(vcpu->kvm, sp);
 		return 1;
 	}
@@ -1328,7 +1328,7 @@ static struct kvm_mmu_page *kvm_mmu_get_page(struct kvm_vcpu *vcpu,
 	role.level = level;
 	role.direct = direct;
 	if (role.direct)
-		role.glevels = 0;
+		role.cr4_pae = 0;
 	role.access = access;
 	if (vcpu->arch.mmu.root_level <= PT32_ROOT_LEVEL) {
 		quadrant = gaddr >> (PAGE_SHIFT + (PT64_PT_BITS * level));
@@ -2439,7 +2439,7 @@ static int init_kvm_softmmu(struct kvm_vcpu *vcpu)
 	else
 		r = paging32_init_context(vcpu);
 
-	vcpu->arch.mmu.base_role.glevels = vcpu->arch.mmu.root_level;
+	vcpu->arch.mmu.base_role.cr4_pae = !!is_pae(vcpu);
 
 	return r;
 }
@@ -2528,7 +2528,7 @@ static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu,
         }
 
 	++vcpu->kvm->stat.mmu_pte_updated;
-	if (sp->role.glevels == PT32_ROOT_LEVEL)
+	if (!sp->role.cr4_pae)
 		paging32_update_pte(vcpu, sp, spte, new);
 	else
 		paging64_update_pte(vcpu, sp, spte, new);
@@ -2677,7 +2677,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
 	hlist_for_each_entry_safe(sp, node, n, bucket, hash_link) {
 		if (sp->gfn != gfn || sp->role.direct || sp->role.invalid)
 			continue;
-		pte_size = sp->role.glevels == PT32_ROOT_LEVEL ? 4 : 8;
+		pte_size = sp->role.cr4_pae ? 8 : 4;
 		misaligned = (offset ^ (offset + bytes - 1)) & ~(pte_size - 1);
 		misaligned |= bytes < 4;
 		if (misaligned || flooded) {
@@ -2701,7 +2701,7 @@ void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
 		page_offset = offset;
 		level = sp->role.level;
 		npte = 1;
-		if (sp->role.glevels == PT32_ROOT_LEVEL) {
+		if (!sp->role.cr4_pae) {
 			page_offset <<= 1;	/* 32->64 */
 			/*
 			 * A 32-bit pde maps 4MB while the shadow pdes map
diff --git a/arch/x86/kvm/mmutrace.h b/arch/x86/kvm/mmutrace.h
index 1fe956a..3851f1f 100644
--- a/arch/x86/kvm/mmutrace.h
+++ b/arch/x86/kvm/mmutrace.h
@@ -28,9 +28,10 @@
 								        \
 	role.word = __entry->role;					\
 									\
-	trace_seq_printf(p, "sp gfn %llx %u/%u q%u%s %s%s %spge"	\
+	trace_seq_printf(p, "sp gfn %llx %u%s q%u%s %s%s %spge"		\
 			 " %snxe root %u %s%c",				\
-			 __entry->gfn, role.level, role.glevels,	\
+			 __entry->gfn, role.level,			\
+			 role.cr4_pae ? " pae" : "",			\
 			 role.quadrant,					\
 			 role.direct ? " direct" : "",			\
 			 access_str[role.access],			\
-- 
1.7.0.4


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

* Re: [PATCH] KVM: MMU: Replace role.glevels with role.cr4_pae
  2010-04-14 16:20 [PATCH] KVM: MMU: Replace role.glevels with role.cr4_pae Avi Kivity
@ 2010-04-14 16:32 ` Avi Kivity
  2010-04-14 18:29   ` Marcelo Tosatti
  2010-04-15 16:58 ` Marcelo Tosatti
  1 sibling, 1 reply; 5+ messages in thread
From: Avi Kivity @ 2010-04-14 16:32 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: kvm

On 04/14/2010 07:20 PM, Avi Kivity wrote:
> There is no real distinction between glevels=3 and glevels=4; both have
> exactly the same format and the code is treated exactly the same way.  Drop
> role.glevels and replace is with role.cr4_pae (which is meaningful).  This
> simplifies the code a bit.
>
> As a side effect, it allows sharing shadow page tables between pae and
> longmode guest page tables at the same guest page.
>    

>
>   static int kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
>   {
> -	if (sp->role.glevels != vcpu->arch.mmu.root_level) {
> +	if (sp->role.cr4_pae != !!is_pae(vcpu)) {
>   		kvm_mmu_zap_page(vcpu->kvm, sp);
>   		return 1;
>   	}
>    

This bit confuses me a little.  Why is it needed?  It will never hit 
from mmu_sync_children(), and as for kvm_mmu_get_page(), it will simply 
zap unrelated pages?

Is it related to the restriction that we can only unsync if we have just 
one shadow page for a gfn?  That's somewhat artificial (and hurts nonpae 
guests, and guests with linear page tables).

-- 
error compiling committee.c: too many arguments to function


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

* Re: [PATCH] KVM: MMU: Replace role.glevels with role.cr4_pae
  2010-04-14 16:32 ` Avi Kivity
@ 2010-04-14 18:29   ` Marcelo Tosatti
  2010-04-15  9:02     ` Avi Kivity
  0 siblings, 1 reply; 5+ messages in thread
From: Marcelo Tosatti @ 2010-04-14 18:29 UTC (permalink / raw)
  To: Avi Kivity; +Cc: kvm

On Wed, Apr 14, 2010 at 07:32:12PM +0300, Avi Kivity wrote:
> On 04/14/2010 07:20 PM, Avi Kivity wrote:
> >There is no real distinction between glevels=3 and glevels=4; both have
> >exactly the same format and the code is treated exactly the same way.  Drop
> >role.glevels and replace is with role.cr4_pae (which is meaningful).  This
> >simplifies the code a bit.
> >
> >As a side effect, it allows sharing shadow page tables between pae and
> >longmode guest page tables at the same guest page.
> 
> >
> >  static int kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
> >  {
> >-	if (sp->role.glevels != vcpu->arch.mmu.root_level) {
> >+	if (sp->role.cr4_pae != !!is_pae(vcpu)) {
> >  		kvm_mmu_zap_page(vcpu->kvm, sp);
> >  		return 1;
> >  	}
> 
> This bit confuses me a little.  Why is it needed?  It will never hit
> from mmu_sync_children(), and as for kvm_mmu_get_page(), it will
> simply zap unrelated pages?

kvm_mmu_get_page is write protecting a gfn. If there's shadow for a
different role, and its unsync, it needs to be synchronized.

Perhaps it could call the appropriate _sync_page version instead
of zapping, similar to mmu_pte_write_new_pte.

> Is it related to the restriction that we can only unsync if we have
> just one shadow page for a gfn?  That's somewhat artificial (and
> hurts nonpae guests, and guests with linear page tables).

If gfn is shadowed at PMD or higher level, you can't unsync the PTE 
shadow.

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

* Re: [PATCH] KVM: MMU: Replace role.glevels with role.cr4_pae
  2010-04-14 18:29   ` Marcelo Tosatti
@ 2010-04-15  9:02     ` Avi Kivity
  0 siblings, 0 replies; 5+ messages in thread
From: Avi Kivity @ 2010-04-15  9:02 UTC (permalink / raw)
  To: Marcelo Tosatti; +Cc: kvm

On 04/14/2010 09:29 PM, Marcelo Tosatti wrote:
> On Wed, Apr 14, 2010 at 07:32:12PM +0300, Avi Kivity wrote:
>    
>> On 04/14/2010 07:20 PM, Avi Kivity wrote:
>>      
>>> There is no real distinction between glevels=3 and glevels=4; both have
>>> exactly the same format and the code is treated exactly the same way.  Drop
>>> role.glevels and replace is with role.cr4_pae (which is meaningful).  This
>>> simplifies the code a bit.
>>>
>>> As a side effect, it allows sharing shadow page tables between pae and
>>> longmode guest page tables at the same guest page.
>>>        
>>      
>>>   static int kvm_sync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
>>>   {
>>> -	if (sp->role.glevels != vcpu->arch.mmu.root_level) {
>>> +	if (sp->role.cr4_pae != !!is_pae(vcpu)) {
>>>   		kvm_mmu_zap_page(vcpu->kvm, sp);
>>>   		return 1;
>>>   	}
>>>        
>> This bit confuses me a little.  Why is it needed?  It will never hit
>> from mmu_sync_children(), and as for kvm_mmu_get_page(), it will
>> simply zap unrelated pages?
>>      
> kvm_mmu_get_page is write protecting a gfn.

Took me a while to figure out why.

> If there's shadow for a
> differ	ent role, and its unsync, it needs to be synchronized.
>
>    

We could leave it unsync and write protected, though that destroys an 
invariant (sync==protected, unsync==unprotected), and all the calls to 
rmap_write_protect() become confused.

> Perhaps it could call the appropriate _sync_page version instead
> of zapping, similar to mmu_pte_write_new_pte.
>    

Probably better for nonpae.

>> Is it related to the restriction that we can only unsync if we have
>> just one shadow page for a gfn?  That's somewhat artificial (and
>> hurts nonpae guests, and guests with linear page tables).
>>      
> If gfn is shadowed at PMD or higher level, you can't unsync the PTE
> shadow.
>    

Yes.  Even if we could, invlpg is defined to drop all PDE caches (except 
large page PDEs), so we would have to resync all those pages on invlpg.

-- 
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.


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

* Re: [PATCH] KVM: MMU: Replace role.glevels with role.cr4_pae
  2010-04-14 16:20 [PATCH] KVM: MMU: Replace role.glevels with role.cr4_pae Avi Kivity
  2010-04-14 16:32 ` Avi Kivity
@ 2010-04-15 16:58 ` Marcelo Tosatti
  1 sibling, 0 replies; 5+ messages in thread
From: Marcelo Tosatti @ 2010-04-15 16:58 UTC (permalink / raw)
  To: Avi Kivity; +Cc: kvm

On Wed, Apr 14, 2010 at 07:20:03PM +0300, Avi Kivity wrote:
> There is no real distinction between glevels=3 and glevels=4; both have
> exactly the same format and the code is treated exactly the same way.  Drop
> role.glevels and replace is with role.cr4_pae (which is meaningful).  This
> simplifies the code a bit.
> 
> As a side effect, it allows sharing shadow page tables between pae and
> longmode guest page tables at the same guest page.
> 
> Signed-off-by: Avi Kivity <avi@redhat.com>

Applied, thanks.


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

end of thread, other threads:[~2010-04-15 17:23 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-04-14 16:20 [PATCH] KVM: MMU: Replace role.glevels with role.cr4_pae Avi Kivity
2010-04-14 16:32 ` Avi Kivity
2010-04-14 18:29   ` Marcelo Tosatti
2010-04-15  9:02     ` Avi Kivity
2010-04-15 16:58 ` Marcelo Tosatti

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.