return 1;
 }
 
+enum vmcs_field_type {
+       VMCS_FIELD_TYPE_U16 = 0,
+       VMCS_FIELD_TYPE_U64 = 1,
+       VMCS_FIELD_TYPE_U32 = 2,
+       VMCS_FIELD_TYPE_NATURAL_WIDTH = 3
+};
+
+static inline int vmcs_field_type(unsigned long field)
+{
+       if (0x1 & field)        /* the *_HIGH fields are all 32 bit */
+               return VMCS_FIELD_TYPE_U32;
+       return (field >> 13) & 0x3 ;
+}
+
+static inline int vmcs_field_readonly(unsigned long field)
+{
+       return (((field >> 10) & 0x3) == 1);
+}
+
+/*
+ * Read a vmcs12 field. Since these can have varying lengths and we return
+ * one type, we chose the biggest type (u64) and zero-extend the return value
+ * to that size. Note that the caller, handle_vmread, might need to use only
+ * some of the bits we return here (e.g., on 32-bit guests, only 32 bits of
+ * 64-bit fields are to be returned).
+ */
+static inline bool vmcs12_read_any(struct kvm_vcpu *vcpu,
+                                       unsigned long field, u64 *ret)
+{
+       short offset = vmcs_field_to_offset(field);
+       char *p;
+
+       if (offset < 0)
+               return 0;
+
+       p = ((char *)(get_vmcs12(vcpu))) + offset;
+
+       switch (vmcs_field_type(field)) {
+       case VMCS_FIELD_TYPE_NATURAL_WIDTH:
+               *ret = *((natural_width *)p);
+               return 1;
+       case VMCS_FIELD_TYPE_U16:
+               *ret = *((u16 *)p);
+               return 1;
+       case VMCS_FIELD_TYPE_U32:
+               *ret = *((u32 *)p);
+               return 1;
+       case VMCS_FIELD_TYPE_U64:
+               *ret = *((u64 *)p);
+               return 1;
+       default:
+               return 0; /* can never happen. */
+       }
+}
+
+/*
+ * VMX instructions which assume a current vmcs12 (i.e., that VMPTRLD was
+ * used before) all generate the same failure when it is missing.
+ */
+static int nested_vmx_check_vmcs12(struct kvm_vcpu *vcpu)
+{
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+       if (vmx->nested.current_vmptr == -1ull) {
+               nested_vmx_failInvalid(vcpu);
+               skip_emulated_instruction(vcpu);
+               return 0;
+       }
+       return 1;
+}
+
+static int handle_vmread(struct kvm_vcpu *vcpu)
+{
+       unsigned long field;
+       u64 field_value;
+       unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+       u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
+       gva_t gva = 0;
+
+       if (!nested_vmx_check_permission(vcpu) ||
+           !nested_vmx_check_vmcs12(vcpu))
+               return 1;
+
+       /* Decode instruction info and find the field to read */
+       field = kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
+       /* Read the field, zero-extended to a u64 field_value */
+       if (!vmcs12_read_any(vcpu, field, &field_value)) {
+               nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT);
+               skip_emulated_instruction(vcpu);
+               return 1;
+       }
+       /*
+        * Now copy part of this value to register or memory, as requested.
+        * Note that the number of bits actually copied is 32 or 64 depending
+        * on the guest's mode (32 or 64 bit), not on the given field's length.
+        */
+       if (vmx_instruction_info & (1u << 10)) {
+               kvm_register_write(vcpu, (((vmx_instruction_info) >> 3) & 0xf),
+                       field_value);
+       } else {
+               if (get_vmx_mem_address(vcpu, exit_qualification,
+                               vmx_instruction_info, &gva))
+                       return 1;
+               /* _system ok, as nested_vmx_check_permission verified cpl=0 */
+               kvm_write_guest_virt_system(&vcpu->arch.emulate_ctxt, gva,
+                            &field_value, (is_long_mode(vcpu) ? 8 : 4), NULL);
+       }
+
+       nested_vmx_succeed(vcpu);
+       skip_emulated_instruction(vcpu);
+       return 1;
+}
+
+
+static int handle_vmwrite(struct kvm_vcpu *vcpu)
+{
+       unsigned long field;
+       gva_t gva;
+       unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+       u32 vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
+       char *p;
+       short offset;
+       /* The value to write might be 32 or 64 bits, depending on L1's long
+        * mode, and eventually we need to write that into a field of several
+        * possible lengths. The code below first zero-extends the value to 64
+        * bit (field_value), and then copies only the approriate number of
+        * bits into the vmcs12 field.
+        */
+       u64 field_value = 0;
+       struct x86_exception e;
+
+       if (!nested_vmx_check_permission(vcpu) ||
+           !nested_vmx_check_vmcs12(vcpu))
+               return 1;
+
+       if (vmx_instruction_info & (1u << 10))
+               field_value = kvm_register_read(vcpu,
+                       (((vmx_instruction_info) >> 3) & 0xf));
+       else {
+               if (get_vmx_mem_address(vcpu, exit_qualification,
+                               vmx_instruction_info, &gva))
+                       return 1;
+               if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva,
+                          &field_value, (is_long_mode(vcpu) ? 8 : 4), &e)) {
+                       kvm_inject_page_fault(vcpu, &e);
+                       return 1;
+               }
+       }
+
+
+       field = kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf));
+       if (vmcs_field_readonly(field)) {
+               nested_vmx_failValid(vcpu,
+                       VMXERR_VMWRITE_READ_ONLY_VMCS_COMPONENT);
+               skip_emulated_instruction(vcpu);
+               return 1;
+       }
+
+       offset = vmcs_field_to_offset(field);
+       if (offset < 0) {
+               nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT);
+               skip_emulated_instruction(vcpu);
+               return 1;
+       }
+       p = ((char *) get_vmcs12(vcpu)) + offset;
+
+       switch (vmcs_field_type(field)) {
+       case VMCS_FIELD_TYPE_U16:
+               *(u16 *)p = field_value;
+               break;
+       case VMCS_FIELD_TYPE_U32:
+               *(u32 *)p = field_value;
+               break;
+       case VMCS_FIELD_TYPE_U64:
+               *(u64 *)p = field_value;
+               break;
+       case VMCS_FIELD_TYPE_NATURAL_WIDTH:
+               *(natural_width *)p = field_value;
+               break;
+       default:
+               nested_vmx_failValid(vcpu, VMXERR_UNSUPPORTED_VMCS_COMPONENT);
+               skip_emulated_instruction(vcpu);
+               return 1;
+       }
+
+       nested_vmx_succeed(vcpu);
+       skip_emulated_instruction(vcpu);
+       return 1;
+}
+
 /* Emulate the VMPTRLD instruction */
 static int handle_vmptrld(struct kvm_vcpu *vcpu)
 {
        [EXIT_REASON_VMLAUNCH]                = handle_vmx_insn,
        [EXIT_REASON_VMPTRLD]                 = handle_vmptrld,
        [EXIT_REASON_VMPTRST]                 = handle_vmptrst,
-       [EXIT_REASON_VMREAD]                  = handle_vmx_insn,
+       [EXIT_REASON_VMREAD]                  = handle_vmread,
        [EXIT_REASON_VMRESUME]                = handle_vmx_insn,
-       [EXIT_REASON_VMWRITE]                 = handle_vmx_insn,
+       [EXIT_REASON_VMWRITE]                 = handle_vmwrite,
        [EXIT_REASON_VMOFF]                   = handle_vmoff,
        [EXIT_REASON_VMON]                    = handle_vmon,
        [EXIT_REASON_TPR_BELOW_THRESHOLD]     = handle_tpr_below_threshold,