KVM: nSVM: Fix IOIO size reported on emulation
PATCH 1/1 KVM: nSVM: Fix IOIO size reported on emulation
From: Jan Kiszka <[email protected]>
The access size of an in/ins is reported in dst_bytes, and that of out/outs in src_bytes.
---
I'm seeing one more issue now: on emulation of "in (%dx),%eax", we leave to user space several times and check interception also several times after returning. We use dx to calculate the port number for the interception check. But at some point, user space (QEMU) decides to update that register during vmport access - and now we check the wrong port in the bitmap (namely port 0). Ideas?
In general, the same interception checks are done multiple times. Once after the exit, then again during emulation. Can't we avoid this somehow?
arch/x86/kvm/svm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/x86/kvm/svm.c +2 -2
@@ -4261,9 +4261,9 @@ static int svm_check_intercept(struct kvm_vcpu *vcpu,if (info->intercept == x86_intercept_in || info->intercept == x86_intercept_ins) { exit_info |=SVM_IOIO_TYPE_MASK ; - bytes = info->src_bytes; - }else { bytes = info->dst_bytes; + }else { + bytes = info->src_bytes; } if (info->intercept == x86_intercept_outs ||
Signature · 1 line
1.8.4.5
nSVM: interception checks on emulation (was: [PATCH] KVM: nSVM: Fix IOIO size reported on emulation)
Quoted 2 lines · Jan Kiszka
I'm seeing one more issue now: on emulation of "in (%dx),%eax", we leave to user space several times and check interception also several times
Correction: we only leave once for user space.
Quoted 8 lines
after returning. We use dx to calculate the port number for the interception check. But at some point, user space (QEMU) decides to update that register during vmport access - and now we check the wrong port in the bitmap (namely port 0). Ideas?
In general, the same interception checks are done multiple times. Once after the exit, then again during emulation. Can't we avoid this somehow?
OK, we have different interception stages, but it seems we take multiple ones when we should only take a single:
qemu-system-x86-4455 [000] 38083.617545: kvm_exit: reason EXIT_IOIO rip 0x7fc6ead774e4 info 56580241 7fc6ead774e5 qemu-system-x86-4455 [000] 38083.617547: kvm_nested_vmexit: rip 7fc6ead774e4 reason EXIT_IOIO info1 56580241 info2 7fc6ead774e5 int_info 0 int_info_err 0 qemu-system-x86-4455 [000] 38083.617548: bprint: nested_svm_intercept: 5658 4 3c00bacb 0 1 f qemu-system-x86-4455 [000] 38083.617549: bprint: nested_svm_intercept: f0 qemu-system-x86-4455 [000] 38083.617553: kvm_emulate_insn: 0:7fc6ead774e4: ed qemu-system-x86-4455 [000] 38083.617555: bprint: svm_check_intercept: 5658 2 4 43 qemu-system-x86-4455 [000] 38083.617556: bprint: nested_svm_intercept: 5658 4 3c00bacb 0 1 f qemu-system-x86-4455 [000] 38083.617556: bprint: nested_svm_intercept: f0 qemu-system-x86-4455 [000] 38083.617559: kvm_userspace_exit: reason KVM_EXIT_IO (2) qemu-system-x86-4455 [000] 38083.617567: bprint: kvm_arch_vcpu_ioctl_get_regs: 5658 qemu-system-x86-4455 [000] 38083.617598: bprint: kvm_arch_vcpu_ioctl_set_regs: 0 qemu-system-x86-4455 [000] 38083.617628: bprint: svm_check_intercept: 0 2 4 43 qemu-system-x86-4455 [000] 38083.617629: bprint: nested_svm_intercept: 0 4 3c00b000 0 1 f qemu-system-x86-4455 [000] 38083.617630: bprint: nested_svm_intercept: ff qemu-system-x86-4455 [000] 38083.617631: kvm_nested_vmexit_inject: reason EXIT_IOIO info1 241 info2 7fc6ead774e4 int_info 0 int_info_err 0
And you can also see the rdx writing of user space here (rdx is printed in kvm_arch_vcpu_ioctl_*).
Jan
PATCH 1/1 KVM: nSVM: Set correct port for IOIO interception evaluation
From: Jan Kiszka <[email protected]>
Obtaining the port number from DX is bogus as a) there are immediate port accesses and b) user space may have changed the register content while processing the PIO access. Forward the correct value from the instruction emulator instead.
---
Valentine, I've a stable Jailhouse root cell under QEMU now :)
arch/x86/include/asm/kvm_emulate.h | 1 + arch/x86/kvm/emulate.c | 1 + arch/x86/kvm/svm.c | 6 +++--- 3 files changed, 5 insertions(+), 3 deletions(-)
arch/x86/include/asm/kvm_emulate.h +1 -0
@@ -37,6 +37,7 @@ struct x86_instruction_info {u8 modrm_reg;/* index of register used */ u8 modrm_rm;/* rm part of modrm */ u64 src_val;/* value of source operand */ +u64 dst_val;/* value of destination operand */ u8 src_bytes;/* size of source operand */ u8 dst_bytes;/* size of destination operand */ u8 ad_bytes;/* size of src/dst address */
arch/x86/kvm/emulate.c +1 -0
@@ -426,6 +426,7 @@ static int emulator_check_intercept(struct x86_emulate_ctxt *ctxt, .modrm_reg = ctxt->modrm_reg, .modrm_rm = ctxt->modrm_rm, .src_val = ctxt->src.val64, + .dst_val = ctxt->dst.val64, .src_bytes = ctxt->src.bytes, .dst_bytes = ctxt->dst.bytes, .ad_bytes = ctxt->ad_bytes,
arch/x86/kvm/svm.c +3 -3
@@ -4256,13 +4256,13 @@ static int svm_check_intercept(struct kvm_vcpu *vcpu,u64 exit_info;u32 bytes; - exit_info = (vcpu->arch.regs[VCPU_REGS_RDX ] &0xffff ) <<16 ; -if (info->intercept == x86_intercept_in || info->intercept == x86_intercept_ins) { - exit_info |=SVM_IOIO_TYPE_MASK ; + exit_info = ((info->src_val &0xffff ) <<16 ) | +SVM_IOIO_TYPE_MASK ; bytes = info->dst_bytes; }else { + exit_info = (info->dst_val &0xffff ) <<16 ; bytes = info->src_bytes; }
Signature · 1 line
1.8.4.5
Re: [PATCH] KVM: nSVM: Set correct port for IOIO interception evaluation
Quoted 8 lines · Jan Kiszka
From: Jan Kiszka <[email protected]>
Obtaining the port number from DX is bogus as a) there are immediate port accesses and b) user space may have changed the register content while processing the PIO access. Forward the correct value from the instruction emulator instead.
Signed-off-by Jan Kiszka <[email protected]>