[RFC PATCH v1 19/34] KVM: introspection: clean non-default EPTs on unhook

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Ștefan Șicleru <ssicleru@xxxxxxxxxxxxxxx>

When a guest is unhooked, the VM is brought to default state and uses
default EPT view. Delete all shadow pages that belong to non-default EPT
views in order to free unused shadow pages. They are not used because
the guest cannot VMFUNC to any EPT view.

Signed-off-by: Ștefan Șicleru <ssicleru@xxxxxxxxxxxxxxx>
Signed-off-by: Adalbert Lazăr <alazar@xxxxxxxxxxxxxxx>
---
 arch/x86/include/asm/kvm_host.h |  2 ++
 arch/x86/kvm/kvmi.c             | 23 ++++++++++++++++++++++-
 virt/kvm/introspection/kvmi.c   |  3 +++
 3 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 519b8210b8ef..086b6e2a2314 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -1026,6 +1026,8 @@ struct kvm_arch {
 
 	struct kvm_pmu_event_filter *pmu_event_filter;
 	struct task_struct *nx_lpage_recovery_thread;
+
+	refcount_t kvmi_refcount;
 };
 
 struct kvm_vm_stat {
diff --git a/arch/x86/kvm/kvmi.c b/arch/x86/kvm/kvmi.c
index 52885b9e5b6e..27fd732cff29 100644
--- a/arch/x86/kvm/kvmi.c
+++ b/arch/x86/kvm/kvmi.c
@@ -640,6 +640,25 @@ static void kvmi_arch_restore_interception(struct kvm_vcpu *vcpu)
 	kvmi_arch_disable_msrw_intercept(vcpu, arch_vcpui->msrw.kvmi_mask.high);
 }
 
+void kvmi_arch_restore_ept_view(struct kvm_vcpu *vcpu)
+{
+	struct kvm *kvm = vcpu->kvm;
+	u16 view, default_view = 0;
+	bool visible = false;
+
+	if (kvm_get_ept_view(vcpu) != default_view)
+		kvmi_arch_cmd_set_ept_view(vcpu, default_view);
+
+	for (view = 0; view < KVM_MAX_EPT_VIEWS; view++)
+		kvmi_arch_cmd_control_ept_view(vcpu, view, visible);
+
+	if (refcount_dec_and_test(&kvm->arch.kvmi_refcount)) {
+		u16 zap_mask = ~(1 << default_view);
+
+		kvm_mmu_zap_all(vcpu->kvm, zap_mask);
+	}
+}
+
 bool kvmi_arch_clean_up_interception(struct kvm_vcpu *vcpu)
 {
 	struct kvmi_interception *arch_vcpui = vcpu->arch.kvmi;
@@ -647,8 +666,10 @@ bool kvmi_arch_clean_up_interception(struct kvm_vcpu *vcpu)
 	if (!arch_vcpui || !arch_vcpui->cleanup)
 		return false;
 
-	if (arch_vcpui->restore_interception)
+	if (arch_vcpui->restore_interception) {
 		kvmi_arch_restore_interception(vcpu);
+		kvmi_arch_restore_ept_view(vcpu);
+	}
 
 	return true;
 }
diff --git a/virt/kvm/introspection/kvmi.c b/virt/kvm/introspection/kvmi.c
index 44b0092e304f..f3bdef3c54e6 100644
--- a/virt/kvm/introspection/kvmi.c
+++ b/virt/kvm/introspection/kvmi.c
@@ -288,6 +288,9 @@ static void free_kvmi(struct kvm *kvm)
 
 	kvmi_clear_mem_access(kvm);
 
+	refcount_set(&kvm->arch.kvmi_refcount,
+			atomic_read(&kvm->online_vcpus));
+
 	kvm_for_each_vcpu(i, vcpu, kvm)
 		free_vcpui(vcpu, restore_interception);
 



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux