[RHEL7,COMMIT] ms/KVM: x86: SVM: Intercept #GP to support access to VMware backdoor ports

Submitted by Konstantin Khorenko on May 8, 2018, 9:26 a.m.

Details

Message ID 201805080926.w489QPsG001555@finist_ce7.work
State New
Series "ms/KVM: x86: SVM: Intercept #GP to support access to VMware backdoor ports"
Headers show

Commit Message

Konstantin Khorenko May 8, 2018, 9:26 a.m.
The commit is pushed to "branch-rh7-3.10.0-693.21.1.vz7.47.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-693.21.1.vz7.47.5
------>
commit 0bbe620d3d91f005630fab92e493824c6d8c0c37
Author: Liran Alon <liran.alon@oracle.com>
Date:   Tue May 8 12:26:25 2018 +0300

    ms/KVM: x86: SVM: Intercept #GP to support access to VMware backdoor ports
    
    If KVM enable_vmware_backdoor module parameter is set,
    the commit change VMX to now intercept #GP instead of being directly
    deliviered from CPU to guest.
    
    It is done to support access to VMware Backdoor I/O ports
    even if TSS I/O permission denies it.
    In that case:
    1. A #GP will be raised and intercepted.
    2. #GP intercept handler will simulate I/O port access instruction.
    3. I/O port access instruction simulation will allow access to VMware
    backdoor ports specifically even if TSS I/O permission bitmap denies it.
    
    Note that the above change introduce slight performance hit as now #GPs
    are now not deliviered directly from CPU to guest but instead
    cause #VMExit and instruction emulation.
    However, this behavior is introduced only when enable_vmware_backdoor
    KVM module parameter is set.
    
    Signed-off-by: Liran Alon <liran.alon@oracle.com>
    Reviewed-by: Nikita Leshenko <nikita.leshchenko@oracle.com>
    Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
    Reviewed-by: Radim Krčmář <rkrcmar@redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
    
    (cherry picked from commit 9718420e9fd462ac6b7ea840f9e63eb6af7e1bda)
    Signed-off-by: Jan Dakinevich <jan.dakinevich@virtuozzo.com>
---
 arch/x86/kvm/svm.c | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

Patch hide | download patch | download mbox

diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index 09370ccc455d..d5f8aca82ce0 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1090,6 +1090,14 @@  static void init_vmcb(struct vcpu_svm *svm)
 	set_exception_intercept(svm, MC_VECTOR);
 	set_exception_intercept(svm, AC_VECTOR);
 	set_exception_intercept(svm, DB_VECTOR);
+	/*
+	 * Guest access to VMware backdoor ports could legitimately
+	 * trigger #GP because of TSS I/O permission bitmap.
+	 * We intercept those #GP and allow access to them anyway
+	 * as VMware does.
+	 */
+	if (enable_vmware_backdoor)
+		set_exception_intercept(svm, GP_VECTOR);
 
 	set_intercept(svm, INTERCEPT_INTR);
 	set_intercept(svm, INTERCEPT_NMI);
@@ -1999,6 +2007,23 @@  static int nm_interception(struct vcpu_svm *svm)
 	return 1;
 }
 
+static int gp_interception(struct vcpu_svm *svm)
+{
+	struct kvm_vcpu *vcpu = &svm->vcpu;
+	u32 error_code = svm->vmcb->control.exit_info_1;
+	int er;
+
+	WARN_ON_ONCE(!enable_vmware_backdoor);
+
+	er = emulate_instruction(vcpu,
+		EMULTYPE_VMWARE | EMULTYPE_NO_UD_ON_FAIL);
+	if (er == EMULATE_USER_EXIT)
+		return 0;
+	else if (er != EMULATE_DONE)
+		kvm_queue_exception_e(vcpu, GP_VECTOR, error_code);
+	return 1;
+}
+
 static bool is_erratum_383(void)
 {
 	int err, i;
@@ -3835,6 +3860,7 @@  static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
 	[SVM_EXIT_EXCP_BASE + NM_VECTOR]	= nm_interception,
 	[SVM_EXIT_EXCP_BASE + MC_VECTOR]	= mc_interception,
 	[SVM_EXIT_EXCP_BASE + AC_VECTOR]	= ac_interception,
+	[SVM_EXIT_EXCP_BASE + GP_VECTOR]	= gp_interception,
 	[SVM_EXIT_INTR]				= intr_interception,
 	[SVM_EXIT_NMI]				= nmi_interception,
 	[SVM_EXIT_SMI]				= nop_on_interception,