Skip to contentSkip to conversation

Enable Unrestricted Guest

PATCH Applied Nitin A Kamble 2 participants 5 messages Jun 4, 2009 – Jun 7, 2009

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover Enable Unrestricted Guest

Hi Avi,
I have modified the earlier patch as per you comments. I have prepared a
separate patch for renaming rmode.active to rmode.vm86_active. And 2nd patch enables the Unrestricted Guest feature in the KVM.
This patch will also work with unfixed (cpu reset state) qemu.
Please apply.

Thanks & Regards,
Nitin

Nitin A Kamble (2):
KVM: VMX: Rename rmode.active to rmode.vm86_active
KVM: VMX: Support Unrestricted Guest feature

 arch/x86/include/asm/kvm_host.h |   14 ++++---
 arch/x86/include/asm/vmx.h      |    1 +
 arch/x86/kvm/vmx.c              |   77 +++++++++++++++++++++++++++++----------
 3 files changed, 66 insertions(+), 26 deletions(-)
#1 lore raw

PATCH 1/2 KVM: VMX: Rename rmode.active to rmode.vm86_active

That way the interpretation of rmode.active becomes more clear with unrestricted guest code.

---
 arch/x86/include/asm/kvm_host.h |    2 +-
 arch/x86/kvm/vmx.c              |   28 ++++++++++++++--------------
 2 files changed, 15 insertions(+), 15 deletions(-)
arch/x86/include/asm/kvm_host.h +1 -1
index 1951d39..1cc901e 100644
@@ -339,7 +339,7 @@ struct kvm_vcpu_arch {
 	} interrupt;
 
 	struct {
-		int active;
+		int vm86_active;
 		u8 save_iopl;
 		struct kvm_save_segment {
 			u16 selector;
arch/x86/kvm/vmx.c +14 -14
index fd05fd2..d1ec8a9 100644
@@ -497,7 +497,7 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
 		if (vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP)
 			eb |= 1u << BP_VECTOR;
 	}
-	if (vcpu->arch.rmode.active)
+	if (vcpu->arch.rmode.vm86_active)
 		eb = ~0;
 	if (enable_ept)
 		eb &= ~(1u << PF_VECTOR); /* bypass_guest_pf = 0 */
@@ -733,7 +733,7 @@ static unsigned long vmx_get_rflags(struct kvm_vcpu *vcpu)
 
 static void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
 {
-	if (vcpu->arch.rmode.active)
+	if (vcpu->arch.rmode.vm86_active)
 		rflags |= X86_EFLAGS_IOPL | X86_EFLAGS_VM;
 	vmcs_writel(GUEST_RFLAGS, rflags);
 }
@@ -790,7 +790,7 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu, unsigned nr,
 		intr_info |= INTR_INFO_DELIVER_CODE_MASK;
 	}
 
-	if (vcpu->arch.rmode.active) {
+	if (vcpu->arch.rmode.vm86_active) {
 		vmx->rmode.irq.pending = true;
 		vmx->rmode.irq.vector = nr;
 		vmx->rmode.irq.rip = kvm_rip_read(vcpu);
@@ -1370,7 +1370,7 @@ static void enter_pmode(struct kvm_vcpu *vcpu)
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 
 	vmx->emulation_required = 1;
-	vcpu->arch.rmode.active = 0;
+	vcpu->arch.rmode.vm86_active = 0;
 
 	vmcs_writel(GUEST_TR_BASE, vcpu->arch.rmode.tr.base);
 	vmcs_write32(GUEST_TR_LIMIT, vcpu->arch.rmode.tr.limit);
@@ -1432,7 +1432,7 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 
 	vmx->emulation_required = 1;
-	vcpu->arch.rmode.active = 1;
+	vcpu->arch.rmode.vm86_active = 1;
 
 	vcpu->arch.rmode.tr.base = vmcs_readl(GUEST_TR_BASE);
 	vmcs_writel(GUEST_TR_BASE, rmode_tss_base(vcpu->kvm));
@@ -1616,10 +1616,10 @@ static void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 
 	vmx_fpu_deactivate(vcpu);
 
-	if (vcpu->arch.rmode.active && (cr0 & X86_CR0_PE))
+	if (vcpu->arch.rmode.vm86_active && (cr0 & X86_CR0_PE))
 		enter_pmode(vcpu);
 
-	if (!vcpu->arch.rmode.active && !(cr0 & X86_CR0_PE))
+	if (!vcpu->arch.rmode.vm86_active && !(cr0 & X86_CR0_PE))
 		enter_rmode(vcpu);
 
 #ifdef CONFIG_X86_64
@@ -1675,7 +1675,7 @@ static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
 
 static void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 {
-	unsigned long hw_cr4 = cr4 | (vcpu->arch.rmode.active ?
+	unsigned long hw_cr4 = cr4 | (vcpu->arch.rmode.vm86_active ?
 		    KVM_RMODE_VM_CR4_ALWAYS_ON : KVM_PMODE_VM_CR4_ALWAYS_ON);
 
 	vcpu->arch.cr4 = cr4;
@@ -1758,7 +1758,7 @@ static void vmx_set_segment(struct kvm_vcpu *vcpu,
 	struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
 	u32 ar;
 
-	if (vcpu->arch.rmode.active && seg == VCPU_SREG_TR) {
+	if (vcpu->arch.rmode.vm86_active && seg == VCPU_SREG_TR) {
 		vcpu->arch.rmode.tr.selector = var->selector;
 		vcpu->arch.rmode.tr.base = var->base;
 		vcpu->arch.rmode.tr.limit = var->limit;
@@ -1768,7 +1768,7 @@ static void vmx_set_segment(struct kvm_vcpu *vcpu,
 	vmcs_writel(sf->base, var->base);
 	vmcs_write32(sf->limit, var->limit);
 	vmcs_write16(sf->selector, var->selector);
-	if (vcpu->arch.rmode.active && var->s) {
+	if (vcpu->arch.rmode.vm86_active && var->s) {
 		/*
 		 * Hack real-mode segments into vm86 compatibility.
 		 */
@@ -2337,7 +2337,7 @@ static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
 		goto out;
 	}
 
-	vmx->vcpu.arch.rmode.active = 0;
+	vmx->vcpu.arch.rmode.vm86_active = 0;
 
 	vmx->soft_vnmi_blocked = 0;
 
@@ -2475,7 +2475,7 @@ static void vmx_inject_irq(struct kvm_vcpu *vcpu)
 	KVMTRACE_1D(INJ_VIRQ, vcpu, (u32)irq, handler);
 
 	++vcpu->stat.irq_injections;
-	if (vcpu->arch.rmode.active) {
+	if (vcpu->arch.rmode.vm86_active) {
 		vmx->rmode.irq.pending = true;
 		vmx->rmode.irq.vector = irq;
 		vmx->rmode.irq.rip = kvm_rip_read(vcpu);
@@ -2516,7 +2516,7 @@ static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
 	}
 
 	++vcpu->stat.nmi_injections;
-	if (vcpu->arch.rmode.active) {
+	if (vcpu->arch.rmode.vm86_active) {
 		vmx->rmode.irq.pending = true;
 		vmx->rmode.irq.vector = NMI_VECTOR;
 		vmx->rmode.irq.rip = kvm_rip_read(vcpu);
@@ -2652,7 +2652,7 @@ static int handle_exception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 		return kvm_mmu_page_fault(vcpu, cr2, error_code);
 	}
 
-	if (vcpu->arch.rmode.active &&
+	if (vcpu->arch.rmode.vm86_active &&
 	    handle_rmode_exception(vcpu, intr_info & INTR_INFO_VECTOR_MASK,
 								error_code)) {
 		if (vcpu->arch.halt_request) {
Signature · 1 line
1.6.0.6
#2 lore raw

PATCH 2/2 KVM: VMX: Support Unrestricted Guest feature

"Unrestricted Guest" feature is added in the VMX specification. Intel Westmere and onwards processors will support this feature.

It allows kvm guests to run real mode and unpaged mode
code natively in the VMX mode when EPT is turned on. With the unrestricted guest there is no need to emulate the guest real mode code in the vm86 container or in the emulator. Also the guest big real mode code works like native.

The attached patch enhances KVM to use the unrestricted guest feature
if available on the processor. It also adds a new kernel/module parameter to disable the unrestricted guest feature at the boot time.

---
 arch/x86/include/asm/kvm_host.h |   12 +++++----
 arch/x86/include/asm/vmx.h      |    1 +
 arch/x86/kvm/vmx.c              |   49 ++++++++++++++++++++++++++++++++++----
 3 files changed, 51 insertions(+), 11 deletions(-)
arch/x86/include/asm/kvm_host.h +7 -5
index 1cc901e..a1a96a5 100644
@@ -37,12 +37,14 @@
 #define CR3_L_MODE_RESERVED_BITS (CR3_NONPAE_RESERVED_BITS |	\
 				  0xFFFFFF0000000000ULL)
 
-#define KVM_GUEST_CR0_MASK				   \
-	(X86_CR0_PG | X86_CR0_PE | X86_CR0_WP | X86_CR0_NE \
-	 | X86_CR0_NW | X86_CR0_CD)
+#define KVM_GUEST_CR0_MASK_UNRESTRICTED_GUEST				\
+	(X86_CR0_WP | X86_CR0_NE | X86_CR0_NW | X86_CR0_CD)
+#define KVM_GUEST_CR0_MASK						\
+	(KVM_GUEST_CR0_MASK_UNRESTRICTED_GUEST | X86_CR0_PG | X86_CR0_PE)
+#define KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST				\
+	(X86_CR0_WP | X86_CR0_NE | X86_CR0_TS | X86_CR0_MP)
 #define KVM_VM_CR0_ALWAYS_ON						\
-	(X86_CR0_PG | X86_CR0_PE | X86_CR0_WP | X86_CR0_NE | X86_CR0_TS \
-	 | X86_CR0_MP)
+	(KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST | X86_CR0_PG | X86_CR0_PE)
 #define KVM_GUEST_CR4_MASK						\
 	(X86_CR4_VME | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_PGE | X86_CR4_VMXE)
 #define KVM_PMODE_VM_CR4_ALWAYS_ON (X86_CR4_PAE | X86_CR4_VMXE)
arch/x86/include/asm/vmx.h +1 -0
index 498f944..c73da02 100644
@@ -55,6 +55,7 @@
 #define SECONDARY_EXEC_ENABLE_EPT               0x00000002
 #define SECONDARY_EXEC_ENABLE_VPID              0x00000020
 #define SECONDARY_EXEC_WBINVD_EXITING		0x00000040
+#define SECONDARY_EXEC_UNRESTRICTED_GUEST	0x00000080
 
 
 #define PIN_BASED_EXT_INTR_MASK                 0x00000001
arch/x86/kvm/vmx.c +43 -6

114 lines not on this page · raw message

Signature · 1 line
1.6.0.6
#3 lore raw

Re: [PATCH KVM VMX 2/2] KVM: VMX: Support Unrestricted Guest feature

Quoted 15 lines · Nitin A Kamble

"Unrestricted Guest" feature is added in the VMX specification. Intel Westmere and onwards processors will support this feature.

It allows kvm guests to run real mode and unpaged mode
code natively in the VMX mode when EPT is turned on. With the unrestricted guest there is no need to emulate the guest real mode code in the vm86 container or in the emulator. Also the guest big real mode code works like native.

The attached patch enhances KVM to use the unrestricted guest feature
if available on the processor. It also adds a new kernel/module parameter to disable the unrestricted guest feature at the boot time.

arch/x86/kvm/vmx.c static void enter_rmode(struct kvm_vcpu *vcpu) · line 1453

Quoted 7 lines
arch/x86/kvm/vmx.c +3 -0
@@ -1431,6 +1447,9 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
 	unsigned long flags;
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 
+	if (enable_unrestricted_guest)
+		goto continue_rmode;
+
 

I think you should just return here. You don't need to reset the mmu context or run the init_rmode() code. Maybe you need to flush the tlb.

arch/x86/kvm/vmx.c static void vmx_set_segment(struct kvm_vcpu *vcpu, · line 1808

Quoted 7 lines
arch/x86/kvm/vmx.c +4 -0
+
+	if (enable_unrestricted_guest && (seg != VCPU_SREG_LDTR))
+		ar |= 0x1; /* Accessed */
+
 	vmcs_write32(sf->ar_bytes, ar);
 }

Please add a comment indicating it's for broken userspace that doesn't set the A bit.

Signature · 1 line
Do not meddle in the internals of kernels, for they are subtle and quick to panic.
Applied
#4 lore raw

Re: [PATCH KVM VMX 1/2] KVM: VMX: Rename rmode.active to rmode.vm86_active

In reply to Nitin A Kamble
Quoted 3 lines · Nitin A Kamble

That way the interpretation of rmode.active becomes more clear with unrestricted guest code.

Applied, thanks.

Signature · 1 line
Do not meddle in the internals of kernels, for they are subtle and quick to panic.