From mboxrd@z Thu Jan 1 00:00:00 1970 From: Liran Alon Subject: Re: [PATCH v3 2/2] KVM: X86: Add Force Emulation Prefix for "emulate the next instruction" Date: Tue, 27 Mar 2018 23:55:32 -0700 (PDT) Message-ID: <490b19a2-3a40-4abb-b993-743c22ef43a5@default> Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Cc: , , , , , To: Return-path: Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-Id: kvm.vger.kernel.org ----- kernellwp@gmail.com wrote: > From: Wanpeng Li >=20 > There is no easy way to force KVM to run an instruction through the > emulator=20 > (by design as that will expose the x86 emulator as a significant > attack-surface). > However, we do wish to expose the x86 emulator in case we are testing > it > (e.g. via kvm-unit-tests). Therefore, this patch adds a "force > emulation prefix" > that is designed to raise #UD which KVM will trap and it's #UD > exit-handler will > match "force emulation prefix" to run instruction after prefix by the > x86 emulator. > To not expose the x86 emulator by default, we add a module parameter > that should=20 > be off by default. >=20 > A simple testcase here: >=20 > #include > #include > =20 > #define HYPERVISOR_INFO 0x40000000 > =20 > #define CPUID(idx, eax, ebx, ecx, edx) \ > asm volatile (\ > "ud2a; .ascii \"kvm\"; cpuid" \ > :"=3Db" (*ebx), "=3Da" (*eax), "=3Dc" (*ecx), "=3Dd" (*edx) \ > :"0"(idx) ); =20 > =20 > void main() =20 > { =20 > =09unsigned int eax, ebx, ecx, edx; =20 > =09char string[13]; =20 > =20 > =09CPUID(HYPERVISOR_INFO, &eax, &ebx, &ecx, &edx); =20 > =09*(unsigned int *)(string + 0) =3D ebx; =20 > =09*(unsigned int *)(string + 4) =3D ecx; =20 > =09*(unsigned int *)(string + 8) =3D edx; =20 > =20 > =09string[12] =3D 0; =20 > =09if (strncmp(string, "KVMKVMKVM\0\0\0", 12) =3D=3D 0) > =09=09printf("kvm guest\n"); =20 > =09else =20 > =09=09printf("bare hardware\n"); =20 > } >=20 > Suggested-by: Andrew Cooper > Cc: Paolo Bonzini > Cc: Radim Kr=C4=8Dm=C3=A1=C5=99 > Cc: Andrew Cooper > Cc: Konrad Rzeszutek Wilk > Cc: Liran Alon > Signed-off-by: Wanpeng Li > --- > arch/x86/kvm/x86.c | 18 +++++++++++++++++- > 1 file changed, 17 insertions(+), 1 deletion(-) >=20 > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index e3a60ab..40e2f78 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -146,6 +146,9 @@ bool __read_mostly enable_vmware_backdoor =3D > false; > module_param(enable_vmware_backdoor, bool, S_IRUGO); > EXPORT_SYMBOL_GPL(enable_vmware_backdoor); > =20 > +static bool __read_mostly force_emulation_prefix =3D false; > +module_param(force_emulation_prefix, bool, S_IRUGO); > + > #define KVM_NR_SHARED_MSRS 16 > =20 > struct kvm_shared_msrs_global { > @@ -4843,8 +4846,21 @@ > EXPORT_SYMBOL_GPL(kvm_write_guest_virt_system); > int handle_ud(struct kvm_vcpu *vcpu) > { > =09enum emulation_result er; > +=09int emulation_type =3D EMULTYPE_TRAP_UD; > + > +=09if (force_emulation_prefix) { > +=09=09char sig[5]; /* ud2; .ascii "kvm" */ > +=09=09struct x86_exception e; > + > +=09=09kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, > +=09=09=09=09kvm_get_linear_rip(vcpu), sig, sizeof(sig), &e); > +=09=09if (memcmp(sig, "\xf\xbkvm", sizeof(sig)) =3D=3D 0) { > +=09=09=09emulation_type =3D 0; > +=09=09=09kvm_rip_write(vcpu, kvm_rip_read(vcpu) + sizeof(sig)); > +=09=09} > +=09} > =20 > -=09er =3D emulate_instruction(vcpu, EMULTYPE_TRAP_UD); > +=09er =3D emulate_instruction(vcpu, emulation_type); > =09if (er =3D=3D EMULATE_USER_EXIT) > =09=09return 0; > =09if (er !=3D EMULATE_DONE) > --=20 > 2.7.4 Reviewed-by: Liran Alon