From: Orit Wasserman <oritw@xxxxxxxxxx> --- arch/x86/kvm/vmx.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 65 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 71bd91a..411cbdb 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -61,15 +61,26 @@ module_param_named(unrestricted_guest, static int __read_mostly emulate_invalid_guest_state = 0; module_param(emulate_invalid_guest_state, bool, S_IRUGO); -struct vmcs { - u32 revision_id; - u32 abort; - char data[0]; +struct __attribute__ ((__packed__)) level_state { + /* Has the level1 guest done vmclear? */ + bool vmclear; }; struct nested_vmx { /* Has the level1 guest done vmxon? */ bool vmxon; + + /* + * Level 2 state : includes vmcs,registers and + * a copy of vmcs12 for vmread/vmwrite + */ + struct level_state *l2_state; +}; + +struct vmcs { + u32 revision_id; + u32 abort; + char data[0]; }; struct vcpu_vmx { @@ -186,6 +197,8 @@ static struct kvm_vmx_segment_field { static void ept_save_pdptrs(struct kvm_vcpu *vcpu); +static int create_l2_state(struct kvm_vcpu *vcpu); + /* * Keep MSR_K6_STAR at the end, as setup_msrs() will try to optimize it * away by decrementing the array size. @@ -1293,6 +1306,30 @@ static void vmclear_local_vcpus(void) __vcpu_clear(vmx); } +struct level_state *create_state(void) +{ + struct level_state *state = NULL; + + state = kzalloc(sizeof(struct level_state), GFP_KERNEL); + if (!state) { + printk(KERN_INFO "Error create level state\n"); + return NULL; + } + return state; +} + +int create_l2_state(struct kvm_vcpu *vcpu) +{ + struct vcpu_vmx *vmx = to_vmx(vcpu); + + if (!vmx->nested.l2_state) { + vmx->nested.l2_state = create_state(); + if (!vmx->nested.l2_state) + return -ENOMEM; + } + + return 0; +} /* Just like cpu_vmxoff(), but with the __kvm_handle_fault_on_reboot() * tricks. @@ -3261,6 +3298,27 @@ static int handle_vmx_insn(struct kvm_vcpu *vcpu) return 1; } +static void clear_rflags_cf_zf(struct kvm_vcpu *vcpu) +{ + unsigned long rflags; + rflags = vmx_get_rflags(vcpu); + rflags &= ~(X86_EFLAGS_CF | X86_EFLAGS_ZF); + vmx_set_rflags(vcpu, rflags); +} + +static int handle_vmclear(struct kvm_vcpu *vcpu) +{ + if (!nested_vmx_check_permission(vcpu)) + return 1; + + to_vmx(vcpu)->nested.l2_state->vmclear = 1; + + skip_emulated_instruction(vcpu); + clear_rflags_cf_zf(vcpu); + + return 1; +} + static int handle_vmoff(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx = to_vmx(vcpu); @@ -3310,6 +3368,8 @@ static int handle_vmon(struct kvm_vcpu *vcpu) vmx->nested.vmxon = 1; + create_l2_state(vcpu); + skip_emulated_instruction(vcpu); return 1; } @@ -3582,7 +3642,7 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = { [EXIT_REASON_HLT] = handle_halt, [EXIT_REASON_INVLPG] = handle_invlpg, [EXIT_REASON_VMCALL] = handle_vmcall, - [EXIT_REASON_VMCLEAR] = handle_vmx_insn, + [EXIT_REASON_VMCLEAR] = handle_vmclear, [EXIT_REASON_VMLAUNCH] = handle_vmx_insn, [EXIT_REASON_VMPTRLD] = handle_vmx_insn, [EXIT_REASON_VMPTRST] = handle_vmx_insn, -- 1.6.0.4 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html