[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen staging-4.10] x86/vmx: Properly flush the TLB when an altp2m is modified
commit 92fc0b635ca87459ef4582bb8f1663b14a097be4 Author: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> AuthorDate: Fri May 3 11:03:01 2019 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Fri May 3 11:03:01 2019 +0200 x86/vmx: Properly flush the TLB when an altp2m is modified Modifications to an altp2m mark the p2m as needing flushing, but this was never wired up in the return-to-guest path. As a result, stale TLB entries can remain after resuming the guest. In practice, this manifests as a missing EPT_VIOLATION or #VE exception when the guest subsequently accesses a page which has had its permissions reduced. vmx_vmenter_helper() now has 11 p2ms to potentially invalidate, but issuing 11 INVEPT instructions isn't clever. Instead, count how many contexts need invalidating, and use INVEPT_ALL_CONTEXT if two or more are in need of flushing. This doesn't have an XSA because altp2m is not yet a security-supported feature. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> Reviewed-by: Razvan Cojocaru <rcojocaru@xxxxxxxxxxxxxxx> Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx> Acked-by: Kevin Tian <kevin.tian@xxxxxxxxx> master commit: 69f7643df68ef8e994221a996e336a47cbb7bbc8 master date: 2019-02-28 11:16:27 +0000 --- xen/arch/x86/hvm/vmx/vmx.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index e28d7963b7..2896d272b1 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -4282,6 +4282,7 @@ static void lbr_fixup(void) bool vmx_vmenter_helper(const struct cpu_user_regs *regs) { struct vcpu *curr = current; + struct domain *currd = curr->domain; u32 new_asid, old_asid; struct hvm_vcpu_asid *p_asid; bool_t need_flush; @@ -4328,17 +4329,42 @@ bool vmx_vmenter_helper(const struct cpu_user_regs *regs) if ( paging_mode_hap(curr->domain) ) { - struct ept_data *ept = &p2m_get_hostp2m(curr->domain)->ept; + struct ept_data *ept = &p2m_get_hostp2m(currd)->ept; unsigned int cpu = smp_processor_id(); + unsigned int inv = 0; /* None => Single => All */ + struct ept_data *single = NULL; /* Single eptp, iff inv == 1 */ if ( cpumask_test_cpu(cpu, ept->invalidate) ) { cpumask_clear_cpu(cpu, ept->invalidate); - if ( nestedhvm_enabled(curr->domain) ) - __invept(INVEPT_ALL_CONTEXT, 0, 0); - else - __invept(INVEPT_SINGLE_CONTEXT, ept->eptp, 0); + + /* Automatically invalidate all contexts if nested. */ + inv += 1 + nestedhvm_enabled(currd); + single = ept; + } + + if ( altp2m_active(currd) ) + { + unsigned int i; + + for ( i = 0; i < MAX_ALTP2M; ++i ) + { + if ( currd->arch.altp2m_eptp[i] == mfn_x(INVALID_MFN) ) + continue; + + ept = &currd->arch.altp2m_p2m[i]->ept; + if ( cpumask_test_cpu(cpu, ept->invalidate) ) + { + cpumask_clear_cpu(cpu, ept->invalidate); + inv++; + single = ept; + } + } } + + if ( inv ) + __invept(inv == 1 ? INVEPT_SINGLE_CONTEXT : INVEPT_ALL_CONTEXT, + inv == 1 ? single->eptp : 0, 0); } out: -- generated by git-patchbot for /home/xen/git/xen.git#staging-4.10 _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |