]> Pileus Git - ~andy/linux/blobdiff - arch/x86/kvm/vmx.c
Merge tag 'dm-3.11-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/agk...
[~andy/linux] / arch / x86 / kvm / vmx.c
index 260a9193955538b4fea743045b2f964b2736b24e..064d0be67ecc23734aa465541138d9b5be295277 100644 (file)
@@ -2096,6 +2096,8 @@ static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
                        (nested_cpu_has(vmcs12, CPU_BASED_USE_TSC_OFFSETING) ?
                         vmcs12->tsc_offset : 0));
        } else {
+               trace_kvm_write_tsc_offset(vcpu->vcpu_id,
+                                          vmcs_read64(TSC_OFFSET), offset);
                vmcs_write64(TSC_OFFSET, offset);
        }
 }
@@ -2103,11 +2105,14 @@ static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)
 static void vmx_adjust_tsc_offset(struct kvm_vcpu *vcpu, s64 adjustment, bool host)
 {
        u64 offset = vmcs_read64(TSC_OFFSET);
+
        vmcs_write64(TSC_OFFSET, offset + adjustment);
        if (is_guest_mode(vcpu)) {
                /* Even when running L2, the adjustment needs to apply to L1 */
                to_vmx(vcpu)->nested.vmcs01_tsc_offset += adjustment;
-       }
+       } else
+               trace_kvm_write_tsc_offset(vcpu->vcpu_id, offset,
+                                          offset + adjustment);
 }
 
 static u64 vmx_compute_tsc_offset(struct kvm_vcpu *vcpu, u64 target_tsc)
@@ -3399,15 +3404,22 @@ static void vmx_get_segment(struct kvm_vcpu *vcpu,
        var->limit = vmx_read_guest_seg_limit(vmx, seg);
        var->selector = vmx_read_guest_seg_selector(vmx, seg);
        ar = vmx_read_guest_seg_ar(vmx, seg);
+       var->unusable = (ar >> 16) & 1;
        var->type = ar & 15;
        var->s = (ar >> 4) & 1;
        var->dpl = (ar >> 5) & 3;
-       var->present = (ar >> 7) & 1;
+       /*
+        * Some userspaces do not preserve unusable property. Since usable
+        * segment has to be present according to VMX spec we can use present
+        * property to amend userspace bug by making unusable segment always
+        * nonpresent. vmx_segment_access_rights() already marks nonpresent
+        * segment as unusable.
+        */
+       var->present = !var->unusable;
        var->avl = (ar >> 12) & 1;
        var->l = (ar >> 13) & 1;
        var->db = (ar >> 14) & 1;
        var->g = (ar >> 15) & 1;
-       var->unusable = (ar >> 16) & 1;
 }
 
 static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg)
@@ -4176,10 +4188,10 @@ static void ept_set_mmio_spte_mask(void)
        /*
         * EPT Misconfigurations can be generated if the value of bits 2:0
         * of an EPT paging-structure entry is 110b (write/execute).
-        * Also, magic bits (0xffull << 49) is set to quickly identify mmio
+        * Also, magic bits (0x3ull << 62) is set to quickly identify mmio
         * spte.
         */
-       kvm_mmu_set_mmio_spte_mask(0xffull << 49 | 0x6ull);
+       kvm_mmu_set_mmio_spte_mask((0x3ull << 62) | 0x6ull);
 }
 
 /*
@@ -5366,10 +5378,14 @@ static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
        gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS);
 
        ret = handle_mmio_page_fault_common(vcpu, gpa, true);
-       if (likely(ret == 1))
+       if (likely(ret == RET_MMIO_PF_EMULATE))
                return x86_emulate_instruction(vcpu, gpa, 0, NULL, 0) ==
                                              EMULATE_DONE;
-       if (unlikely(!ret))
+
+       if (unlikely(ret == RET_MMIO_PF_INVALID))
+               return kvm_mmu_page_fault(vcpu, gpa, 0, NULL, 0);
+
+       if (unlikely(ret == RET_MMIO_PF_RETRY))
                return 1;
 
        /* It is the real ept misconfig */
@@ -7942,7 +7958,7 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
 
        kvm_register_write(vcpu, VCPU_REGS_RSP, vmcs12->host_rsp);
        kvm_register_write(vcpu, VCPU_REGS_RIP, vmcs12->host_rip);
-       vmx_set_rflags(vcpu, X86_EFLAGS_BIT1);
+       vmx_set_rflags(vcpu, X86_EFLAGS_FIXED);
        /*
         * Note that calling vmx_set_cr0 is important, even if cr0 hasn't
         * actually changed, because it depends on the current state of