|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH V1 8/8] x86/vmx: Fix nested VPID handling
From: Chunjie Zhu <chunjie.zhu@xxxxxxxxxx>
Some nested VPID problems:
* nept_get_ept_vpid_cap() ORed NVPID_CAP_BITS into the low half of
IA32_VMX_EPT_VPID_CAP. The VPID capability bits (INVVPID support
and types) live in bits 32 and up, so the low-half write advertised
unrelated EPT capabilities to L1 and never the intended INVVPID ones.
Shift them into place.
* virtual_vmentry() only tracked the L2 VPID when L1 enabled VPID.
When L1 does not use VPID, all of L2's linear mappings are tagged
with VPID 0 and must be invalidated on every virtual VM entry, so
flush the n2asid in that case as well.
* vmx_vmenter_helper() jumped over the whole ASID/EPT invalidation
block when the CPU lacks VPID, which also skipped the EPT
invalidation that has nothing to do with VPID. Skip only the VPID
part.
* Require VPID hardware support for nested virt. Without VPID, every
virtual VM entry/exit flushes the whole TLB, which makes nested VMX
too slow to be useful.
Signed-off-by: Chunjie Zhu <chunjie.zhu@xxxxxxxxxx>
---
xen/arch/x86/hvm/vmx/vmx.c | 4 ++--
xen/arch/x86/hvm/vmx/vvmx.c | 11 ++++++-----
xen/arch/x86/mm/hap/nested_ept.c | 2 +-
3 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index ed4ff56e7797..8b06a462602d 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -4943,7 +4943,7 @@ bool asmlinkage vmx_vmenter_helper(const struct
cpu_user_regs *regs)
vmx_pi_do_resume(curr);
if ( !cpu_has_vmx_vpid )
- goto out;
+ goto skip_vpid;
if ( nestedhvm_vcpu_in_guestmode(curr) )
p_asid = &vcpu_nestedhvm(curr).nv_n2asid;
else
@@ -4975,6 +4975,7 @@ bool asmlinkage vmx_vmenter_helper(const struct
cpu_user_regs *regs)
if ( unlikely(need_flush) )
vpid_sync_all();
+ skip_vpid:
if ( !paging_mode_shadow(curr->domain) )
{
struct ept_data *ept = &p2m_get_hostp2m(currd)->ept;
@@ -5017,7 +5018,6 @@ bool asmlinkage vmx_vmenter_helper(const struct
cpu_user_regs *regs)
inv == 1 ? single->eptp : 0);
}
- out:
if ( unlikely(curr->arch.hvm.vmx.lbr_flags & LBR_FIXUP_MASK) )
lbr_fixup();
diff --git a/xen/arch/x86/hvm/vmx/vvmx.c b/xen/arch/x86/hvm/vmx/vvmx.c
index d1bfc1f23612..6c2629f20742 100644
--- a/xen/arch/x86/hvm/vmx/vvmx.c
+++ b/xen/arch/x86/hvm/vmx/vvmx.c
@@ -1264,12 +1264,14 @@ static void virtual_vmentry(struct cpu_user_regs *regs)
__vmwrite(EPT_POINTER, get_host_eptp(v));
/* nested VPID support! */
- if ( cpu_has_vmx_vpid && nvmx_vpid_enabled(v) )
+ if ( cpu_has_vmx_vpid )
{
struct nestedvmx *nvmx = &vcpu_2_nvmx(v);
- uint32_t new_vpid = get_vvmcs(v, VIRTUAL_PROCESSOR_ID);
+ uint32_t new_vpid = nvmx_vpid_enabled(v) ?
+ get_vvmcs(v, VIRTUAL_PROCESSOR_ID) : 0;
- if ( nvmx->guest_vpid != new_vpid )
+ /* Without VPID, every virtual VM entry invalidates linear mappings. */
+ if ( !new_vpid || nvmx->guest_vpid != new_vpid )
{
hvm_asid_flush_vcpu_asid(&vcpu_nestedhvm(v).nv_n2asid);
nvmx->guest_vpid = new_vpid;
@@ -2909,9 +2911,8 @@ void nvmx_set_cr_read_shadow(struct vcpu *v, unsigned int
cr)
void __init start_nested_vmx(struct hvm_function_table *hvm_function_table)
{
- /* TODO: Require hardware support before enabling nested virt */
hvm_function_table->caps.nested_virt =
- hvm_function_table->caps.hap;
+ hvm_function_table->caps.hap && cpu_has_vmx_vpid;
}
/*
diff --git a/xen/arch/x86/mm/hap/nested_ept.c b/xen/arch/x86/mm/hap/nested_ept.c
index f8563156b6d0..18d5de870013 100644
--- a/xen/arch/x86/mm/hap/nested_ept.c
+++ b/xen/arch/x86/mm/hap/nested_ept.c
@@ -101,7 +101,7 @@ uint64_t nept_get_ept_vpid_cap(void)
if ( !cpu_has_vmx_ept_exec_only_supported )
caps &= ~VMX_EPT_EXEC_ONLY_SUPPORTED;
if ( cpu_has_vmx_vpid )
- caps |= NVPID_CAP_BITS;
+ caps |= (uint64_t)NVPID_CAP_BITS << 32;
return caps;
}
--
2.34.1
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |