Merge branch 'misc.namei' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[linux-2.6-microblaze.git] / arch / x86 / kvm / vmx / vmx.c
index d5d9fc5..0c2c0d5 100644 (file)
@@ -3812,21 +3812,6 @@ void vmx_enable_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr, int type)
                vmx_set_msr_bitmap_write(msr_bitmap, msr);
 }
 
-static u8 vmx_msr_bitmap_mode(struct kvm_vcpu *vcpu)
-{
-       u8 mode = 0;
-
-       if (cpu_has_secondary_exec_ctrls() &&
-           (secondary_exec_controls_get(to_vmx(vcpu)) &
-            SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE)) {
-               mode |= MSR_BITMAP_MODE_X2APIC;
-               if (enable_apicv && kvm_vcpu_apicv_active(vcpu))
-                       mode |= MSR_BITMAP_MODE_X2APIC_APICV;
-       }
-
-       return mode;
-}
-
 static void vmx_reset_x2apic_msrs(struct kvm_vcpu *vcpu, u8 mode)
 {
        unsigned long *msr_bitmap = to_vmx(vcpu)->vmcs01.msr_bitmap;
@@ -3844,11 +3829,29 @@ static void vmx_reset_x2apic_msrs(struct kvm_vcpu *vcpu, u8 mode)
        }
 }
 
-static void vmx_update_msr_bitmap_x2apic(struct kvm_vcpu *vcpu, u8 mode)
+static void vmx_update_msr_bitmap_x2apic(struct kvm_vcpu *vcpu)
 {
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+       u8 mode;
+
        if (!cpu_has_vmx_msr_bitmap())
                return;
 
+       if (cpu_has_secondary_exec_ctrls() &&
+           (secondary_exec_controls_get(vmx) &
+            SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE)) {
+               mode = MSR_BITMAP_MODE_X2APIC;
+               if (enable_apicv && kvm_vcpu_apicv_active(vcpu))
+                       mode |= MSR_BITMAP_MODE_X2APIC_APICV;
+       } else {
+               mode = 0;
+       }
+
+       if (mode == vmx->x2apic_msr_bitmap_mode)
+               return;
+
+       vmx->x2apic_msr_bitmap_mode = mode;
+
        vmx_reset_x2apic_msrs(vcpu, mode);
 
        /*
@@ -3865,21 +3868,6 @@ static void vmx_update_msr_bitmap_x2apic(struct kvm_vcpu *vcpu, u8 mode)
        }
 }
 
-void vmx_update_msr_bitmap(struct kvm_vcpu *vcpu)
-{
-       struct vcpu_vmx *vmx = to_vmx(vcpu);
-       u8 mode = vmx_msr_bitmap_mode(vcpu);
-       u8 changed = mode ^ vmx->msr_bitmap_mode;
-
-       if (!changed)
-               return;
-
-       if (changed & (MSR_BITMAP_MODE_X2APIC | MSR_BITMAP_MODE_X2APIC_APICV))
-               vmx_update_msr_bitmap_x2apic(vcpu, mode);
-
-       vmx->msr_bitmap_mode = mode;
-}
-
 void pt_update_intercept_for_msr(struct kvm_vcpu *vcpu)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -3936,7 +3924,6 @@ static void vmx_msr_filter_changed(struct kvm_vcpu *vcpu)
        }
 
        pt_update_intercept_for_msr(vcpu);
-       vmx_update_msr_bitmap_x2apic(vcpu, vmx_msr_bitmap_mode(vcpu));
 }
 
 static inline bool kvm_vcpu_trigger_posted_interrupt(struct kvm_vcpu *vcpu,
@@ -4108,7 +4095,7 @@ void set_cr4_guest_host_mask(struct vcpu_vmx *vmx)
        vmcs_writel(CR4_GUEST_HOST_MASK, ~vcpu->arch.cr4_guest_owned_bits);
 }
 
-u32 vmx_pin_based_exec_ctrl(struct vcpu_vmx *vmx)
+static u32 vmx_pin_based_exec_ctrl(struct vcpu_vmx *vmx)
 {
        u32 pin_based_exec_ctrl = vmcs_config.pin_based_exec_ctrl;
 
@@ -4124,6 +4111,30 @@ u32 vmx_pin_based_exec_ctrl(struct vcpu_vmx *vmx)
        return pin_based_exec_ctrl;
 }
 
+static u32 vmx_vmentry_ctrl(void)
+{
+       u32 vmentry_ctrl = vmcs_config.vmentry_ctrl;
+
+       if (vmx_pt_mode_is_system())
+               vmentry_ctrl &= ~(VM_ENTRY_PT_CONCEAL_PIP |
+                                 VM_ENTRY_LOAD_IA32_RTIT_CTL);
+       /* Loading of EFER and PERF_GLOBAL_CTRL are toggled dynamically */
+       return vmentry_ctrl &
+               ~(VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VM_ENTRY_LOAD_IA32_EFER);
+}
+
+static u32 vmx_vmexit_ctrl(void)
+{
+       u32 vmexit_ctrl = vmcs_config.vmexit_ctrl;
+
+       if (vmx_pt_mode_is_system())
+               vmexit_ctrl &= ~(VM_EXIT_PT_CONCEAL_PIP |
+                                VM_EXIT_CLEAR_IA32_RTIT_CTL);
+       /* Loading of EFER and PERF_GLOBAL_CTRL are toggled dynamically */
+       return vmexit_ctrl &
+               ~(VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | VM_EXIT_LOAD_IA32_EFER);
+}
+
 static void vmx_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -4140,11 +4151,10 @@ static void vmx_refresh_apicv_exec_ctrl(struct kvm_vcpu *vcpu)
                                        SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY);
        }
 
-       if (cpu_has_vmx_msr_bitmap())
-               vmx_update_msr_bitmap(vcpu);
+       vmx_update_msr_bitmap_x2apic(vcpu);
 }
 
-u32 vmx_exec_control(struct vcpu_vmx *vmx)
+static u32 vmx_exec_control(struct vcpu_vmx *vmx)
 {
        u32 exec_control = vmcs_config.cpu_based_exec_ctrl;
 
@@ -4226,7 +4236,7 @@ vmx_adjust_secondary_exec_control(struct vcpu_vmx *vmx, u32 *exec_control,
 #define vmx_adjust_sec_exec_exiting(vmx, exec_control, lname, uname) \
        vmx_adjust_sec_exec_control(vmx, exec_control, lname, uname, uname##_EXITING, true)
 
-static void vmx_compute_secondary_exec_control(struct vcpu_vmx *vmx)
+static u32 vmx_secondary_exec_control(struct vcpu_vmx *vmx)
 {
        struct kvm_vcpu *vcpu = &vmx->vcpu;
 
@@ -4312,7 +4322,7 @@ static void vmx_compute_secondary_exec_control(struct vcpu_vmx *vmx)
        if (!vcpu->kvm->arch.bus_lock_detection_enabled)
                exec_control &= ~SECONDARY_EXEC_BUS_LOCK_DETECTION;
 
-       vmx->secondary_exec_control = exec_control;
+       return exec_control;
 }
 
 #define VMX_XSS_EXIT_BITMAP 0
@@ -4336,10 +4346,8 @@ static void init_vmcs(struct vcpu_vmx *vmx)
 
        exec_controls_set(vmx, vmx_exec_control(vmx));
 
-       if (cpu_has_secondary_exec_ctrls()) {
-               vmx_compute_secondary_exec_control(vmx);
-               secondary_exec_controls_set(vmx, vmx->secondary_exec_control);
-       }
+       if (cpu_has_secondary_exec_ctrls())
+               secondary_exec_controls_set(vmx, vmx_secondary_exec_control(vmx));
 
        if (kvm_vcpu_apicv_active(&vmx->vcpu)) {
                vmcs_write64(EOI_EXIT_BITMAP0, 0);
@@ -4410,6 +4418,21 @@ static void init_vmcs(struct vcpu_vmx *vmx)
                vmx->pt_desc.guest.output_mask = 0x7F;
                vmcs_write64(GUEST_IA32_RTIT_CTL, 0);
        }
+
+       vmcs_write32(GUEST_SYSENTER_CS, 0);
+       vmcs_writel(GUEST_SYSENTER_ESP, 0);
+       vmcs_writel(GUEST_SYSENTER_EIP, 0);
+       vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
+
+       if (cpu_has_vmx_tpr_shadow()) {
+               vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, 0);
+               if (cpu_need_tpr_shadow(&vmx->vcpu))
+                       vmcs_write64(VIRTUAL_APIC_PAGE_ADDR,
+                                    __pa(vmx->vcpu.arch.apic->regs));
+               vmcs_write32(TPR_THRESHOLD, 0);
+       }
+
+       vmx_setup_uret_msrs(vmx);
 }
 
 static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
@@ -4446,16 +4469,6 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
        vmcs_write32(GUEST_LDTR_LIMIT, 0xffff);
        vmcs_write32(GUEST_LDTR_AR_BYTES, 0x00082);
 
-       if (!init_event) {
-               vmcs_write32(GUEST_SYSENTER_CS, 0);
-               vmcs_writel(GUEST_SYSENTER_ESP, 0);
-               vmcs_writel(GUEST_SYSENTER_EIP, 0);
-               vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
-       }
-
-       kvm_set_rflags(vcpu, X86_EFLAGS_FIXED);
-       kvm_rip_write(vcpu, 0xfff0);
-
        vmcs_writel(GUEST_GDTR_BASE, 0);
        vmcs_write32(GUEST_GDTR_LIMIT, 0xffff);
 
@@ -4468,32 +4481,11 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
        if (kvm_mpx_supported())
                vmcs_write64(GUEST_BNDCFGS, 0);
 
-       vmx_setup_uret_msrs(vmx);
-
-       if (cpu_has_vmx_msr_bitmap())
-               vmx_update_msr_bitmap(&vmx->vcpu);
-
        vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, 0);  /* 22.2.1 */
 
-       if (cpu_has_vmx_tpr_shadow() && !init_event) {
-               vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, 0);
-               if (cpu_need_tpr_shadow(vcpu))
-                       vmcs_write64(VIRTUAL_APIC_PAGE_ADDR,
-                                    __pa(vcpu->arch.apic->regs));
-               vmcs_write32(TPR_THRESHOLD, 0);
-       }
-
        kvm_make_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu);
 
-       vmx_set_cr0(vcpu, X86_CR0_NW | X86_CR0_CD | X86_CR0_ET);
-       vmx_set_cr4(vcpu, 0);
-       vmx_set_efer(vcpu, 0);
-
-       vmx_update_exception_bitmap(vcpu);
-
        vpid_sync_context(vmx->vpid);
-       if (init_event)
-               vmx_clear_hlt(vcpu);
 }
 
 static void vmx_enable_irq_window(struct kvm_vcpu *vcpu)
@@ -5140,6 +5132,12 @@ static void vmx_sync_dirty_debug_regs(struct kvm_vcpu *vcpu)
 
        vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_WONT_EXIT;
        exec_controls_setbit(to_vmx(vcpu), CPU_BASED_MOV_DR_EXITING);
+
+       /*
+        * exc_debug expects dr6 to be cleared after it runs, avoid that it sees
+        * a stale dr6 from the guest.
+        */
+       set_debugreg(DR6_RESERVED, 6);
 }
 
 static void vmx_set_dr7(struct kvm_vcpu *vcpu, unsigned long val)
@@ -6203,7 +6201,7 @@ void vmx_set_virtual_apic_mode(struct kvm_vcpu *vcpu)
        }
        secondary_exec_controls_set(vmx, sec_exec_control);
 
-       vmx_update_msr_bitmap(vcpu);
+       vmx_update_msr_bitmap_x2apic(vcpu);
 }
 
 static void vmx_set_apic_access_page_addr(struct kvm_vcpu *vcpu)
@@ -6384,6 +6382,9 @@ static void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
 
+       if (vmx->emulation_required)
+               return;
+
        if (vmx->exit_reason.basic == EXIT_REASON_EXTERNAL_INTERRUPT)
                handle_external_interrupt_irqoff(vcpu);
        else if (vmx->exit_reason.basic == EXIT_REASON_EXCEPTION_NMI)
@@ -6655,6 +6656,10 @@ static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu)
                vmx->loaded_vmcs->host_state.cr4 = cr4;
        }
 
+       /* When KVM_DEBUGREG_WONT_EXIT, dr6 is accessible in guest. */
+       if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT))
+               set_debugreg(vcpu->arch.dr6, 6);
+
        /* When single-stepping over STI and MOV SS, we must clear the
         * corresponding interruptibility bits in the guest state. Otherwise
         * vmentry fails as it then expects bit 14 (BS) in pending debug
@@ -6854,7 +6859,6 @@ static int vmx_create_vcpu(struct kvm_vcpu *vcpu)
                vmx_disable_intercept_for_msr(vcpu, MSR_CORE_C6_RESIDENCY, MSR_TYPE_R);
                vmx_disable_intercept_for_msr(vcpu, MSR_CORE_C7_RESIDENCY, MSR_TYPE_R);
        }
-       vmx->msr_bitmap_mode = 0;
 
        vmx->loaded_vmcs = &vmx->vmcs01;
        cpu = get_cpu();
@@ -7013,7 +7017,7 @@ exit:
        return (cache << VMX_EPT_MT_EPTE_SHIFT) | ipat;
 }
 
-static void vmcs_set_secondary_exec_control(struct vcpu_vmx *vmx)
+static void vmcs_set_secondary_exec_control(struct vcpu_vmx *vmx, u32 new_ctl)
 {
        /*
         * These bits in the secondary execution controls field
@@ -7027,7 +7031,6 @@ static void vmcs_set_secondary_exec_control(struct vcpu_vmx *vmx)
                SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES |
                SECONDARY_EXEC_DESC;
 
-       u32 new_ctl = vmx->secondary_exec_control;
        u32 cur_ctl = secondary_exec_controls_get(vmx);
 
        secondary_exec_controls_set(vmx, (new_ctl & ~mask) | (cur_ctl & mask));
@@ -7170,10 +7173,11 @@ static void vmx_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
        /* xsaves_enabled is recomputed in vmx_compute_secondary_exec_control(). */
        vcpu->arch.xsaves_enabled = false;
 
-       if (cpu_has_secondary_exec_ctrls()) {
-               vmx_compute_secondary_exec_control(vmx);
-               vmcs_set_secondary_exec_control(vmx);
-       }
+       vmx_setup_uret_msrs(vmx);
+
+       if (cpu_has_secondary_exec_ctrls())
+               vmcs_set_secondary_exec_control(vmx,
+                                               vmx_secondary_exec_control(vmx));
 
        if (nested_vmx_allowed(vcpu))
                to_vmx(vcpu)->msr_ia32_feature_control_valid_bits |=
@@ -7819,7 +7823,8 @@ static __init int hardware_setup(void)
                ept_lpage_level = PG_LEVEL_2M;
        else
                ept_lpage_level = PG_LEVEL_4K;
-       kvm_configure_mmu(enable_ept, vmx_get_max_tdp_level(), ept_lpage_level);
+       kvm_configure_mmu(enable_ept, 0, vmx_get_max_tdp_level(),
+                         ept_lpage_level);
 
        /*
         * Only enable PML when hardware supports PML feature, and both EPT