diff mbox series

[RFC,v5,16/20] kvm: x86: hook the single-step events

Message ID 20181220182850.4579-17-alazar@bitdefender.com (mailing list archive)
State New, archived
Headers show
Series VM introspection | expand

Commit Message

Adalbert Lazăr Dec. 20, 2018, 6:28 p.m. UTC
From: Mihai DONTU <mdontu@bitdefender.com>

A previous patch has introduced support for single-stepping a guest
(currently only VMX is supported). This mechanism is used to cope with
instructions that cannot be handled by the x86 emulator during the
handling of a VMEXIT. In these situations, all other vCPU-s are kicked
and held, the EPT-based protection is removed and the guest is single
stepped by the vCPU that triggered the initial VMEXIT. Upon completion
the EPT-base protection is reinstalled and all vCPU-s all allowed to
return to the guest.

This is a rather slow workaround that kicks in occasionally. In the
future, the most frequently single-stepped instructions should be added
to the emulator (usually, stores to and from memory - SSE/AVX).

This patch adds the VMX-side of events meant to disable the single step
mechanism.

Signed-off-by: Nicușor Cîțu <ncitu@bitdefender.com>
Signed-off-by: Mihai Donțu <mdontu@bitdefender.com>
---
 arch/x86/kvm/vmx.c | 6 ++++++
 arch/x86/kvm/x86.c | 5 ++---
 2 files changed, 8 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index b976903c925c..48bbc35bd246 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -8142,6 +8142,7 @@  static int handle_invalid_op(struct kvm_vcpu *vcpu)
 
 static int handle_monitor_trap(struct kvm_vcpu *vcpu)
 {
+	kvmi_stop_ss(vcpu);
 	return 1;
 }
 
@@ -10681,6 +10682,11 @@  static int vmx_handle_exit(struct kvm_vcpu *vcpu)
 		}
 	}
 
+	if (kvmi_vcpu_enabled_ss(vcpu)
+			&& exit_reason != EXIT_REASON_EPT_VIOLATION
+			&& exit_reason != EXIT_REASON_MONITOR_TRAP_FLAG)
+		kvmi_stop_ss(vcpu);
+
 	if (exit_reason < kvm_vmx_max_exit_handlers
 	    && kvm_vmx_exit_handlers[exit_reason])
 		return kvm_vmx_exit_handlers[exit_reason](vcpu);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index b1cbcf44cf70..d163be11b2b5 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -7147,8 +7147,7 @@  static int inject_pending_event(struct kvm_vcpu *vcpu, bool req_int_win)
 	int r;
 
 	/* try to reinject previous events if any */
-
-	if (vcpu->arch.exception.injected)
+	if (vcpu->arch.exception.injected && !kvmi_vcpu_enabled_ss(vcpu))
 		kvm_x86_ops->queue_exception(vcpu);
 	/*
 	 * Do not inject an NMI or interrupt if there is a pending
@@ -7184,7 +7183,7 @@  static int inject_pending_event(struct kvm_vcpu *vcpu, bool req_int_win)
 	}
 
 	/* try to inject new event if pending */
-	if (vcpu->arch.exception.pending) {
+	if (vcpu->arch.exception.pending && !kvmi_vcpu_enabled_ss(vcpu)) {
 		WARN_ON_ONCE(vcpu->arch.exception.injected);
 		vcpu->arch.exception.pending = false;
 		vcpu->arch.exception.injected = true;