|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 4/4] x86/vmx: Properly flush the TLB when an altp2m is modified
Modificaitons 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>
---
CC: Jan Beulich <JBeulich@xxxxxxxx>
CC: Wei Liu <wei.liu2@xxxxxxxxxx>
CC: Roger Pau Monné <roger.pau@xxxxxxxxxx>
CC: Razvan Cojocaru <rcojocaru@xxxxxxxxxxxxxxx>
CC: Tamas K Lengyel <tamas@xxxxxxxxxxxxx>
CC: Jun Nakajima <jun.nakajima@xxxxxxxxx>
CC: Kevin Tian <kevin.tian@xxxxxxxxx>
CC: Juergen Gross <jgross@xxxxxxxx>
---
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 395bccd..290175b 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -4273,6 +4273,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;
@@ -4319,17 +4320,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);
- else
- __invept(INVEPT_SINGLE_CONTEXT, ept->eptp);
+
+ /* Automatically invalidate all contexts if nested. */
+ inv += 1 + nestedhvm_enabled(currd);
+ single = ept;
+ }
+
+ if ( altp2m_active(curr->domain) )
+ {
+ 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);
}
out:
--
2.1.4
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |