diff options
-rw-r--r-- | xen/arch/x86/hvm/vmx/intr.c | 4 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vmx/vvmx.c | 43 |
2 files changed, 44 insertions, 3 deletions
diff --git a/xen/arch/x86/hvm/vmx/intr.c b/xen/arch/x86/hvm/vmx/intr.c index 535248a6ac..c5c503ec2f 100644 --- a/xen/arch/x86/hvm/vmx/intr.c +++ b/xen/arch/x86/hvm/vmx/intr.c @@ -324,7 +324,9 @@ void vmx_intr_assist(void) } out: - if ( !cpu_has_vmx_virtual_intr_delivery && cpu_has_vmx_tpr_shadow ) + if ( !nestedhvm_vcpu_in_guestmode(v) && + !cpu_has_vmx_virtual_intr_delivery && + cpu_has_vmx_tpr_shadow ) __vmwrite(TPR_THRESHOLD, tpr_threshold); } diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c index b00581657a..7b27d2ddc7 100644 --- a/xen/arch/x86/hvm/vmx/vvmx.c +++ b/xen/arch/x86/hvm/vmx/vvmx.c @@ -471,8 +471,7 @@ void nvmx_update_exec_control(struct vcpu *v, u32 host_cntrl) shadow_cntrl = __n2_exec_control(v); pio_cntrl &= shadow_cntrl; /* Enforce the removed features */ - shadow_cntrl &= ~(CPU_BASED_TPR_SHADOW - | CPU_BASED_ACTIVATE_MSR_BITMAP + shadow_cntrl &= ~(CPU_BASED_ACTIVATE_MSR_BITMAP | CPU_BASED_ACTIVATE_IO_BITMAP | CPU_BASED_UNCOND_IO_EXITING); shadow_cntrl |= host_cntrl; @@ -570,6 +569,38 @@ static void nvmx_update_apic_access_address(struct vcpu *v) __vmwrite(APIC_ACCESS_ADDR, (apic_mfn << PAGE_SHIFT)); hvm_unmap_guest_frame(apic_va); } + else + __vmwrite(APIC_ACCESS_ADDR, 0); +} + +static void nvmx_update_virtual_apic_address(struct vcpu *v) +{ + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + u64 vapic_gpfn, vapic_mfn; + u32 ctrl; + void *vapic_va; + + ctrl = __n2_exec_control(v); + if ( ctrl & CPU_BASED_TPR_SHADOW ) + { + vapic_gpfn = __get_vvmcs(nvcpu->nv_vvmcx, VIRTUAL_APIC_PAGE_ADDR) >> PAGE_SHIFT; + vapic_va = hvm_map_guest_frame_ro(vapic_gpfn); + vapic_mfn = virt_to_mfn(vapic_va); + __vmwrite(VIRTUAL_APIC_PAGE_ADDR, (vapic_mfn << PAGE_SHIFT)); + hvm_unmap_guest_frame(vapic_va); + } + else + __vmwrite(VIRTUAL_APIC_PAGE_ADDR, 0); +} + +static void nvmx_update_tpr_threshold(struct vcpu *v) +{ + struct nestedvcpu *nvcpu = &vcpu_nestedhvm(v); + u32 ctrl = __n2_exec_control(v); + if ( ctrl & CPU_BASED_TPR_SHADOW ) + __vmwrite(TPR_THRESHOLD, __get_vvmcs(nvcpu->nv_vvmcx, TPR_THRESHOLD)); + else + __vmwrite(TPR_THRESHOLD, 0); } static void __clear_current_vvmcs(struct vcpu *v) @@ -780,6 +811,8 @@ static void load_shadow_control(struct vcpu *v) nvmx_update_entry_control(v); vmx_update_exception_bitmap(v); nvmx_update_apic_access_address(v); + nvmx_update_virtual_apic_address(v); + nvmx_update_tpr_threshold(v); } static void load_shadow_guest_state(struct vcpu *v) @@ -1371,6 +1404,7 @@ int nvmx_msr_read_intercept(unsigned int msr, u64 *msr_content) CPU_BASED_ACTIVATE_MSR_BITMAP | CPU_BASED_PAUSE_EXITING | CPU_BASED_RDPMC_EXITING | + CPU_BASED_TPR_SHADOW | CPU_BASED_ACTIVATE_SECONDARY_CONTROLS; data = gen_vmx_msr(data, VMX_PROCBASED_CTLS_DEFAULT1, host_data); break; @@ -1707,6 +1741,11 @@ int nvmx_n2_vmexit_handler(struct cpu_user_regs *regs, if ( ctrl & SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES ) nvcpu->nv_vmexit_pending = 1; break; + case EXIT_REASON_TPR_BELOW_THRESHOLD: + ctrl = __n2_exec_control(v); + if ( ctrl & CPU_BASED_TPR_SHADOW ) + nvcpu->nv_vmexit_pending = 1; + break; default: gdprintk(XENLOG_WARNING, "Unknown nested vmexit reason %x.\n", exit_reason); |