Re: [PATCH v3 10/11] KVM: X86: Move handling of INVPCID types to x86

2020-07-29 Thread Jim Mattson
On Tue, Jul 28, 2020 at 4:38 PM Babu Moger  wrote:
>
> INVPCID instruction handling is mostly same across both VMX and
> SVM. So, move the code to common x86.c.
>
> Signed-off-by: Babu Moger 
Reviewed-by: Jim Mattson 


[PATCH v3 10/11] KVM: X86: Move handling of INVPCID types to x86

2020-07-28 Thread Babu Moger
INVPCID instruction handling is mostly same across both VMX and
SVM. So, move the code to common x86.c.

Signed-off-by: Babu Moger 
---
 arch/x86/kvm/vmx/vmx.c |   62 +--
 arch/x86/kvm/x86.c |   69 
 arch/x86/kvm/x86.h |3 +-
 3 files changed, 72 insertions(+), 62 deletions(-)

diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 13745f2a5ecd..eb988ebedd9e 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -5500,11 +5500,8 @@ static int handle_invpcid(struct kvm_vcpu *vcpu)
 {
u32 vmx_instruction_info;
unsigned long type;
-   bool pcid_enabled;
gva_t gva;
struct x86_exception e;
-   unsigned i;
-   unsigned long roots_to_free = 0;
struct {
u64 pcid;
u64 gla;
@@ -5536,64 +5533,7 @@ static int handle_invpcid(struct kvm_vcpu *vcpu)
if (r != X86EMUL_CONTINUE)
return vmx_handle_memory_failure(vcpu, r, );
 
-   if (operand.pcid >> 12 != 0) {
-   kvm_inject_gp(vcpu, 0);
-   return 1;
-   }
-
-   pcid_enabled = kvm_read_cr4_bits(vcpu, X86_CR4_PCIDE);
-
-   switch (type) {
-   case INVPCID_TYPE_INDIV_ADDR:
-   if ((!pcid_enabled && (operand.pcid != 0)) ||
-   is_noncanonical_address(operand.gla, vcpu)) {
-   kvm_inject_gp(vcpu, 0);
-   return 1;
-   }
-   kvm_mmu_invpcid_gva(vcpu, operand.gla, operand.pcid);
-   return kvm_skip_emulated_instruction(vcpu);
-
-   case INVPCID_TYPE_SINGLE_CTXT:
-   if (!pcid_enabled && (operand.pcid != 0)) {
-   kvm_inject_gp(vcpu, 0);
-   return 1;
-   }
-
-   if (kvm_get_active_pcid(vcpu) == operand.pcid) {
-   kvm_mmu_sync_roots(vcpu);
-   kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu);
-   }
-
-   for (i = 0; i < KVM_MMU_NUM_PREV_ROOTS; i++)
-   if (kvm_get_pcid(vcpu, 
vcpu->arch.mmu->prev_roots[i].pgd)
-   == operand.pcid)
-   roots_to_free |= KVM_MMU_ROOT_PREVIOUS(i);
-
-   kvm_mmu_free_roots(vcpu, vcpu->arch.mmu, roots_to_free);
-   /*
-* If neither the current cr3 nor any of the prev_roots use the
-* given PCID, then nothing needs to be done here because a
-* resync will happen anyway before switching to any other CR3.
-*/
-
-   return kvm_skip_emulated_instruction(vcpu);
-
-   case INVPCID_TYPE_ALL_NON_GLOBAL:
-   /*
-* Currently, KVM doesn't mark global entries in the shadow
-* page tables, so a non-global flush just degenerates to a
-* global flush. If needed, we could optimize this later by
-* keeping track of global entries in shadow page tables.
-*/
-
-   /* fall-through */
-   case INVPCID_TYPE_ALL_INCL_GLOBAL:
-   kvm_mmu_unload(vcpu);
-   return kvm_skip_emulated_instruction(vcpu);
-
-   default:
-   BUG(); /* We have already checked above that type <= 3 */
-   }
+   return kvm_handle_invpcid(vcpu, type, operand.pcid, operand.gla);
 }
 
 static int handle_pml_full(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 88c593f83b28..a3a3aa42b695 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -70,6 +70,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -10699,6 +10700,74 @@ u64 kvm_spec_ctrl_valid_bits(struct kvm_vcpu *vcpu)
 }
 EXPORT_SYMBOL_GPL(kvm_spec_ctrl_valid_bits);
 
+int kvm_handle_invpcid(struct kvm_vcpu *vcpu, unsigned long type,
+  u64 pcid, u64 gla)
+{
+   unsigned long roots_to_free = 0;
+   bool pcid_enabled;
+   unsigned int i;
+
+   if (pcid >> 12 != 0) {
+   kvm_inject_gp(vcpu, 0);
+   return 1;
+   }
+
+   pcid_enabled = kvm_read_cr4_bits(vcpu, X86_CR4_PCIDE);
+
+   switch (type) {
+   case INVPCID_TYPE_INDIV_ADDR:
+   if ((!pcid_enabled && (pcid != 0)) ||
+   is_noncanonical_address(gla, vcpu)) {
+   kvm_inject_gp(vcpu, 0);
+   return 1;
+   }
+   kvm_mmu_invpcid_gva(vcpu, gla, pcid);
+   return kvm_skip_emulated_instruction(vcpu);
+
+   case INVPCID_TYPE_SINGLE_CTXT:
+   if (!pcid_enabled && (pcid != 0)) {
+   kvm_inject_gp(vcpu, 0);
+   return 1;
+   }
+
+   if (kvm_get_active_pcid(vcpu) == pcid) {
+   kvm_mmu_sync_roots(vcpu);
+