diff options
| author | Liran Alon <liran.alon@oracle.com> | 2018-05-22 10:16:15 -0400 |
|---|---|---|
| committer | Radim Krčmář <rkrcmar@redhat.com> | 2018-05-24 13:45:45 -0400 |
| commit | cd9a491f6ef731cdee07dd0a2fe003389424a393 (patch) | |
| tree | 728c12364ae108f31672ba632cc5a4bbae026e8c | |
| parent | 6f1e03bcabcdbb199940dab0a60b1371cf95f6f9 (diff) | |
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: Liam Merwick <liam.merwick@oracle.com>
Signed-off-by: Liran Alon <liran.alon@oracle.com>
Reviewed-by: Jim Mattson <jmattson@google.com>
[Squashed with a preparatory patch that added the !operand.vpid line.]
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
| -rw-r--r-- | arch/x86/kvm/vmx.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 98f05e2b0ecc..e50beb76d846 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
| @@ -1572,6 +1572,11 @@ static inline bool cpu_has_vmx_invept_global(void) | |||
| 1572 | return vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT; | 1572 | return vmx_capability.ept & VMX_EPT_EXTENT_GLOBAL_BIT; |
| 1573 | } | 1573 | } |
| 1574 | 1574 | ||
| 1575 | static inline bool cpu_has_vmx_invvpid_individual_addr(void) | ||
| 1576 | { | ||
| 1577 | return vmx_capability.vpid & VMX_VPID_EXTENT_INDIVIDUAL_ADDR_BIT; | ||
| 1578 | } | ||
| 1579 | |||
| 1575 | static inline bool cpu_has_vmx_invvpid_single(void) | 1580 | static inline bool cpu_has_vmx_invvpid_single(void) |
| 1576 | { | 1581 | { |
| 1577 | return vmx_capability.vpid & VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT; | 1582 | return vmx_capability.vpid & VMX_VPID_EXTENT_SINGLE_CONTEXT_BIT; |
| @@ -8513,12 +8518,19 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) | |||
| 8513 | 8518 | ||
| 8514 | switch (type) { | 8519 | switch (type) { |
| 8515 | case VMX_VPID_EXTENT_INDIVIDUAL_ADDR: | 8520 | case VMX_VPID_EXTENT_INDIVIDUAL_ADDR: |
| 8516 | if (is_noncanonical_address(operand.gla, vcpu)) { | 8521 | if (!operand.vpid || |
| 8522 | is_noncanonical_address(operand.gla, vcpu)) { | ||
| 8517 | nested_vmx_failValid(vcpu, | 8523 | nested_vmx_failValid(vcpu, |
| 8518 | VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); | 8524 | VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); |
| 8519 | return kvm_skip_emulated_instruction(vcpu); | 8525 | return kvm_skip_emulated_instruction(vcpu); |
| 8520 | } | 8526 | } |
| 8521 | /* fall through */ | 8527 | if (cpu_has_vmx_invvpid_individual_addr() && |
| 8528 | vmx->nested.vpid02) { | ||
| 8529 | __invvpid(VMX_VPID_EXTENT_INDIVIDUAL_ADDR, | ||
| 8530 | vmx->nested.vpid02, operand.gla); | ||
| 8531 | } else | ||
| 8532 | __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true); | ||
| 8533 | break; | ||
| 8522 | case VMX_VPID_EXTENT_SINGLE_CONTEXT: | 8534 | case VMX_VPID_EXTENT_SINGLE_CONTEXT: |
| 8523 | case VMX_VPID_EXTENT_SINGLE_NON_GLOBAL: | 8535 | case VMX_VPID_EXTENT_SINGLE_NON_GLOBAL: |
| 8524 | if (!operand.vpid) { | 8536 | if (!operand.vpid) { |
| @@ -8526,15 +8538,16 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) | |||
| 8526 | VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); | 8538 | VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID); |
| 8527 | return kvm_skip_emulated_instruction(vcpu); | 8539 | return kvm_skip_emulated_instruction(vcpu); |
| 8528 | } | 8540 | } |
| 8541 | __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true); | ||
| 8529 | break; | 8542 | break; |
| 8530 | case VMX_VPID_EXTENT_ALL_CONTEXT: | 8543 | case VMX_VPID_EXTENT_ALL_CONTEXT: |
| 8544 | __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true); | ||
| 8531 | break; | 8545 | break; |
| 8532 | default: | 8546 | default: |
| 8533 | WARN_ON_ONCE(1); | 8547 | WARN_ON_ONCE(1); |
| 8534 | return kvm_skip_emulated_instruction(vcpu); | 8548 | return kvm_skip_emulated_instruction(vcpu); |
| 8535 | } | 8549 | } |
| 8536 | 8550 | ||
| 8537 | __vmx_flush_tlb(vcpu, vmx->nested.vpid02, true); | ||
| 8538 | nested_vmx_succeed(vcpu); | 8551 | nested_vmx_succeed(vcpu); |
| 8539 | 8552 | ||
| 8540 | return kvm_skip_emulated_instruction(vcpu); | 8553 | return kvm_skip_emulated_instruction(vcpu); |
