Enable Unrestricted Guest
PATCH 1/2 KVM: VMX: Rename rmode.active to rmode.vm86_active
In reply to Nitin A KambleThat 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
@@ -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
@@ -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
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
@@ -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
@@ -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
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(-)
Avi Kivity
AppliedRe: [PATCH KVM VMX 1/2] KVM: VMX: Rename rmode.active to rmode.vm86_active
In reply to Nitin A KambleQuoted 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.
Re: [PATCH KVM VMX 2/2] KVM: VMX: Support Unrestricted Guest feature
In reply to Nitin A KambleQuoted 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.