From: Orit Wasserman <or...@il.ibm.com>

---
 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 majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to