Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1713905 > unrolled thread

[PATCH v2 2/5] KVM: MMU: check guest CR3 reserved bits based on its physical address width.

Started byYu Zhang <yu.c.zhang@linux.intel.com>
First post2017-08-17 14:10 +0200
Last post2017-08-17 14:50 +0200
Articles 3 — 2 participants

Back to article view | Back to linux.kernel

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  [PATCH v2 2/5] KVM: MMU: check guest CR3 reserved bits based on its physical address width. Yu Zhang <yu.c.zhang@linux.intel.com> - 2017-08-17 14:10 +0200
    Re: [PATCH v2 2/5] KVM: MMU: check guest CR3 reserved bits based on  its physical address width. Paolo Bonzini <pbonzini@redhat.com> - 2017-08-17 14:40 +0200
      Re: [PATCH v2 2/5] KVM: MMU: check guest CR3 reserved bits based on  its physical address width. Yu Zhang <yu.c.zhang@linux.intel.com> - 2017-08-17 14:50 +0200

#1713905 — [PATCH v2 2/5] KVM: MMU: check guest CR3 reserved bits based on its physical address width.

FromYu Zhang <yu.c.zhang@linux.intel.com>
Date2017-08-17 14:10 +0200
Subject[PATCH v2 2/5] KVM: MMU: check guest CR3 reserved bits based on its physical address width.
Message-ID<ufrMB-4Ff-17@gated-at.bofh.it>
Currently, KVM uses CR3_L_MODE_RESERVED_BITS to check the
reserved bits in CR3. Yet the length of reserved bits in
guest CR3 should be based on the physical address width
exposed to the VM. This patch changes CR3 check logic to
calculate the reserved bits at runtime.

Signed-off-by: Yu Zhang <yu.c.zhang@linux.intel.com>
---
 arch/x86/include/asm/kvm_host.h |  1 -
 arch/x86/kvm/emulate.c          | 13 +++++++++++--
 arch/x86/kvm/mmu.h              |  3 +++
 arch/x86/kvm/x86.c              |  8 ++++----
 4 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 9e4862e..018300e 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -79,7 +79,6 @@
 			  | X86_CR0_ET | X86_CR0_NE | X86_CR0_WP | X86_CR0_AM \
 			  | X86_CR0_NW | X86_CR0_CD | X86_CR0_PG))
 
-#define CR3_L_MODE_RESERVED_BITS 0xFFFFFF0000000000ULL
 #define CR3_PCID_INVD		 BIT_64(63)
 #define CR4_RESERVED_BITS                                               \
 	(~(unsigned long)(X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | X86_CR4_DE\
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 46daa37..f3e534d 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -29,6 +29,7 @@
 #include "x86.h"
 #include "tss.h"
 #include "cpuid.h"
+#include "mmu.h"
 
 /*
  * Operand types
@@ -4100,8 +4101,16 @@ static int check_cr_write(struct x86_emulate_ctxt *ctxt)
 		u64 rsvd = 0;
 
 		ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);
-		if (efer & EFER_LMA)
-			rsvd = CR3_L_MODE_RESERVED_BITS & ~CR3_PCID_INVD;
+		if (efer & EFER_LMA) {
+			u64 maxphyaddr;
+			u32 eax = 0x80000008;
+
+			if (ctxt->ops->get_cpuid(ctxt, &eax, NULL, NULL, NULL,
+						 NO_CHECK_LIMIT)) {
+				maxphyaddr = eax & 0xff;
+				rsvd = rsvd_bits(maxphyaddr, 62);
+			}
+		}
 
 		if (new_val & rsvd)
 			return emulate_gp(ctxt, 0);
diff --git a/arch/x86/kvm/mmu.h b/arch/x86/kvm/mmu.h
index d7d248a..1cd0fcb 100644
--- a/arch/x86/kvm/mmu.h
+++ b/arch/x86/kvm/mmu.h
@@ -48,6 +48,9 @@
 
 static inline u64 rsvd_bits(int s, int e)
 {
+	if (e < s)
+		return 0;
+
 	return ((1ULL << (e - s + 1)) - 1) << s;
 }
 
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index ee99fc1..fa3041f 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -813,10 +813,10 @@ int kvm_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 		return 0;
 	}
 
-	if (is_long_mode(vcpu)) {
-		if (cr3 & CR3_L_MODE_RESERVED_BITS)
-			return 1;
-	} else if (is_pae(vcpu) && is_paging(vcpu) &&
+	if (is_long_mode(vcpu) &&
+	    (cr3 & rsvd_bits(cpuid_maxphyaddr(vcpu), 62)))
+		return 1;
+	else if (is_pae(vcpu) && is_paging(vcpu) &&
 		   !load_pdptrs(vcpu, vcpu->arch.walk_mmu, cr3))
 		return 1;
 
-- 
2.5.0

[toc] | [next] | [standalone]


#1713958 — Re: [PATCH v2 2/5] KVM: MMU: check guest CR3 reserved bits based on its physical address width.

FromPaolo Bonzini <pbonzini@redhat.com>
Date2017-08-17 14:40 +0200
SubjectRe: [PATCH v2 2/5] KVM: MMU: check guest CR3 reserved bits based on its physical address width.
Message-ID<ufsfD-4R7-11@gated-at.bofh.it>
In reply to#1713905
On 17/08/2017 21:52, Yu Zhang wrote:
> +		if (efer & EFER_LMA) {
> +			u64 maxphyaddr;
> +			u32 eax = 0x80000008;
> +
> +			if (ctxt->ops->get_cpuid(ctxt, &eax, NULL, NULL, NULL,
> +						 NO_CHECK_LIMIT)) {
> +				maxphyaddr = eax & 0xff;
> +				rsvd = rsvd_bits(maxphyaddr, 62);
> +			}

You should use 36 here if ctxt->ops->get_cpuid returns false, for
consistency with cpuid_query_maxphyaddr.

Paolo

[toc] | [prev] | [next] | [standalone]


#1713978 — Re: [PATCH v2 2/5] KVM: MMU: check guest CR3 reserved bits based on its physical address width.

FromYu Zhang <yu.c.zhang@linux.intel.com>
Date2017-08-17 14:50 +0200
SubjectRe: [PATCH v2 2/5] KVM: MMU: check guest CR3 reserved bits based on its physical address width.
Message-ID<ufspk-4V5-27@gated-at.bofh.it>
In reply to#1713958

On 8/17/2017 8:31 PM, Paolo Bonzini wrote:
> On 17/08/2017 21:52, Yu Zhang wrote:
>> +		if (efer & EFER_LMA) {
>> +			u64 maxphyaddr;
>> +			u32 eax = 0x80000008;
>> +
>> +			if (ctxt->ops->get_cpuid(ctxt, &eax, NULL, NULL, NULL,
>> +						 NO_CHECK_LIMIT)) {
>> +				maxphyaddr = eax & 0xff;
>> +				rsvd = rsvd_bits(maxphyaddr, 62);
>> +			}
> You should use 36 here if ctxt->ops->get_cpuid returns false, for
> consistency with cpuid_query_maxphyaddr.

Oh, right. Thanks! :-)

Yu

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web