Commit cd9a491f authored by Liran Alon's avatar Liran Alon Committed by Radim Krčmář

KVM: nVMX: Emulate L1 individual-address invvpid by L0 individual-address invvpid

When vmcs12 uses VPID, all TLB entries populated by L2 are tagged with
vmx->nested.vpid02. Currently, INVVPID executed by L1 is emulated by L0
by using INVVPID single/global-context to flush all TLB entries
tagged with vmx->nested.vpid02 regardless of INVVPID type executed by
L1.

However, we can easily optimize the case of L1 INVVPID on an
individual-address. Just INVVPID given individual-address tagged with
vmx->nested.vpid02.
Reviewed-by: default avatarLiam Merwick <liam.merwick@oracle.com>
Signed-off-by: default avatarLiran Alon <liran.alon@oracle.com>
Reviewed-by: default avatarJim Mattson <jmattson@google.com>
[Squashed with a preparatory patch that added the !operand.vpid line.]
Signed-off-by: default avatarRadim Krčmář <rkrcmar@redhat.com>
parent 6f1e03bc
...@@ -1572,6 +1572,11 @@ static inline bool cpu_has_vmx_invept_global(void) ...@@ -1572,6 +1572,11 @@ static inline bool cpu_has_vmx_invept_global(void)
return vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT; return vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT;
} }
static inline bool cpu_has_vmx_invvpid_individual_addr(void)
{
return vmx_capability.vpid & VMX_VPID_EXTENT_INDIVIDUAL_ADDR_BIT;
}
static inline bool cpu_has_vmx_invvpid_single(void) static inline bool cpu_has_vmx_invvpid_single(void)
{ {
return vmx_capability.vpid & VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT; return vmx_capability.vpid & VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT;
...@@ -8513,12 +8518,19 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) ...@@ -8513,12 +8518,19 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
switch (type) { switch (type) {
case VMX_VPID_EXTENT_INDIVIDUAL_ADDR: case VMX_VPID_EXTENT_INDIVIDUAL_ADDR:
if (is_noncanonical_address(operand.gla, vcpu)) { if (!operand.vpid ||
is_noncanonical_address(operand.gla, vcpu)) {
nested_vmx_failValid(vcpu, nested_vmx_failValid(vcpu,
VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
return kvm_skip_emulated_instruction(vcpu); return kvm_skip_emulated_instruction(vcpu);
} }
/* fall through */ if (cpu_has_vmx_invvpid_individual_addr() &&
vmx->nested.vpid02) {
__invvpid(VMX_VPID_EXTENT_INDIVIDUAL_ADDR,
vmx->nested.vpid02, operand.gla);
} else
__vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
break;
case VMX_VPID_EXTENT_SINGLE_CONTEXT: case VMX_VPID_EXTENT_SINGLE_CONTEXT:
case VMX_VPID_EXTENT_SINGLE_NON_GLOBAL: case VMX_VPID_EXTENT_SINGLE_NON_GLOBAL:
if (!operand.vpid) { if (!operand.vpid) {
...@@ -8526,15 +8538,16 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) ...@@ -8526,15 +8538,16 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);
return kvm_skip_emulated_instruction(vcpu); return kvm_skip_emulated_instruction(vcpu);
} }
__vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
break; break;
case VMX_VPID_EXTENT_ALL_CONTEXT: case VMX_VPID_EXTENT_ALL_CONTEXT:
__vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
break; break;
default: default:
WARN_ON_ONCE(1); WARN_ON_ONCE(1);
return kvm_skip_emulated_instruction(vcpu); return kvm_skip_emulated_instruction(vcpu);
} }
__vmx_flush_tlb(vcpu, vmx->nested.vpid02, true);
nested_vmx_succeed(vcpu); nested_vmx_succeed(vcpu);
return kvm_skip_emulated_instruction(vcpu); return kvm_skip_emulated_instruction(vcpu);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment