Notes about force_emulation_prefix in KVM
Notes about force_emulation_prefix in KVM.
1. Materials
commit id: 6c86eedc206dd1f9d37a2796faa8e6f2278215d2
https://lore.kernel.org/kvm/1522798129-14588-1-git-send-email-wanpengli@tencent.com/
2. Motivation
There is no easy way to force KVM to run an instruction through the emulator(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 be off by default.
The x86 emulator is the function: kvm_emulate_instruction
1 | kvm_emulate_instruction |
3. Example
- use
kvm.force_emulation_prefix=1
to enable
1 | /* Forced emulation prefix, used to invoke the emulator unconditionally. */ |
1 | static void record_no_fep(struct ex_regs *regs) |
- 在guest中不会因为执行
asm("nop")
而发生VM Exit. - 如果
kvm.force_emulation_prefix=1
,那么在kvm unit test中,执行asm(KVM_FEP "nop")
的结果就是执行asm("nop")
的结果,在guest中不会产生#UD. - 如果
kvm.force_emulation_prefix=0
,那么在kvm unit test中,执行asm(KVM_FEP "nop")
的结果就是在guest中产生#UD,那么#UD handler会被调用,全局变量fep_available
就会被设置为0.
Test cases:
1 | // https://gitlab.com/kvm-unit-tests/kvm-unit-tests/-/blob/master/x86/emulator.c#L1185-1190 |
目的是测试kvm_emulate_instruction是否正确模拟了nop
指令。
在guest中不会因为执行asm("nop")
而发生VM Exit,就无法测试kvm_emulate_instruction是否正确模拟了nop
指令。force_emulation_prefix
就帮上了忙,细节请参考下节的内容。
4. Source code
1 | //https://elixir.bootlin.com/linux/v5.15-rc5/source/arch/x86/kvm/x86.c#L6541 |
在上节的例子中,handle_ud
会执行kvm_rip_write(vcpu, kvm_rip_read(vcpu) + sizeof(sig))
,kvm_emulate_instruction
将模拟nop
指令。