Message ID | 1520853173-7709-6-git-send-email-liran.alon@oracle.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
2018-03-12 13:12+0200, Liran Alon: > 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 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> > Signed-off-by: Krish Sadhukhan <krish.sadhukhan@oracle.com> > Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> > --- > diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c > @@ -6141,6 +6154,17 @@ static int handle_exception(struct kvm_vcpu *vcpu) > if (intr_info & INTR_INFO_DELIVER_CODE_MASK) > error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE); > > + if (!vmx->rmode.vm86_active && is_gp_fault(intr_info)) { Do we have some guarantees that the backdoor ports are never going to be used while vmx->rmode.vm86_active? Thanks. > + 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; > + } > + > /* > * The #PF with PFEC.RSVD = 1 indicates the guest is accessing > * MMIO, it is better to report an internal error. > -- > 1.9.1 >
On 16/03/2018 16:51, Radim Krčmář wrote: >> + if (!vmx->rmode.vm86_active && is_gp_fault(intr_info)) { > Do we have some guarantees that the backdoor ports are never going to be > used while vmx->rmode.vm86_active? While vmx->rmode.vm86_active, handle_rmode_exception simply runs the emulator whenever it sees a #GP, so that works too (except for not having EMULTYPE_NO_UD_ON_FAIL). Paolo > Thanks. > >> + 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; >> + }
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 051dab74e4e9..d6ad1feda9f9 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -1032,6 +1032,11 @@ static inline bool is_invalid_opcode(u32 intr_info) return is_exception_n(intr_info, UD_VECTOR); } +static inline bool is_gp_fault(u32 intr_info) +{ + return is_exception_n(intr_info, GP_VECTOR); +} + static inline bool is_external_interrupt(u32 intr_info) { return (intr_info & (INTR_INFO_INTR_TYPE_MASK | INTR_INFO_VALID_MASK)) @@ -1858,6 +1863,14 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu) eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR) | (1u << DB_VECTOR) | (1u << AC_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) + eb |= (1u << GP_VECTOR); if ((vcpu->guest_debug & (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) == (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) @@ -6141,6 +6154,17 @@ static int handle_exception(struct kvm_vcpu *vcpu) if (intr_info & INTR_INFO_DELIVER_CODE_MASK) error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE); + if (!vmx->rmode.vm86_active && is_gp_fault(intr_info)) { + 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; + } + /* * The #PF with PFEC.RSVD = 1 indicates the guest is accessing * MMIO, it is better to report an internal error.