Commit 9718420e authored by Liran Alon's avatar Liran Alon Committed by Paolo Bonzini

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: default avatarLiran Alon <liran.alon@oracle.com>
Reviewed-by: default avatarNikita Leshenko <nikita.leshchenko@oracle.com>
Reviewed-by: default avatarKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Reviewed-by: default avatarRadim Krčmář <rkrcmar@redhat.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 9e869480
...@@ -1364,6 +1364,14 @@ static void init_vmcb(struct vcpu_svm *svm) ...@@ -1364,6 +1364,14 @@ static void init_vmcb(struct vcpu_svm *svm)
set_exception_intercept(svm, MC_VECTOR); set_exception_intercept(svm, MC_VECTOR);
set_exception_intercept(svm, AC_VECTOR); set_exception_intercept(svm, AC_VECTOR);
set_exception_intercept(svm, DB_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_INTR);
set_intercept(svm, INTERCEPT_NMI); set_intercept(svm, INTERCEPT_NMI);
...@@ -2552,6 +2560,23 @@ static int ac_interception(struct vcpu_svm *svm) ...@@ -2552,6 +2560,23 @@ static int ac_interception(struct vcpu_svm *svm)
return 1; 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) static bool is_erratum_383(void)
{ {
int err, i; int err, i;
...@@ -4551,6 +4576,7 @@ static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = { ...@@ -4551,6 +4576,7 @@ static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
[SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception, [SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception,
[SVM_EXIT_EXCP_BASE + MC_VECTOR] = mc_interception, [SVM_EXIT_EXCP_BASE + MC_VECTOR] = mc_interception,
[SVM_EXIT_EXCP_BASE + AC_VECTOR] = ac_interception, [SVM_EXIT_EXCP_BASE + AC_VECTOR] = ac_interception,
[SVM_EXIT_EXCP_BASE + GP_VECTOR] = gp_interception,
[SVM_EXIT_INTR] = intr_interception, [SVM_EXIT_INTR] = intr_interception,
[SVM_EXIT_NMI] = nmi_interception, [SVM_EXIT_NMI] = nmi_interception,
[SVM_EXIT_SMI] = nop_on_interception, [SVM_EXIT_SMI] = nop_on_interception,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment