Not sure if it actually makes sense to send a patch with this as I have more problems to describe than lines that actually fix something - but well, this hack at least makes some hardware task switches into/out of VM86 work for me that failed before. So what I really intend is to get information on what I need to do to get this right (alternatively consider this a bug report and do the fix yourself): * I have disabled privilege checks for task gates (I need to switch out of VM86/ring 3 back into ring 0). This is wrong, they still need to be applied for software interrupts, but not for exceptions or IRQs (note that the check was wrong anyway, it should check the task gate DPL, not the TSS one). How do I find out what kind of interrupt caused the task switch? (Hm, I guess vmx->idt_vectoring_info could do it for Intel and I would have to pass this down into the emulator; for AMD see below) * May the emulator access the vcpu or should this go through a new x86_emulate_ops.set_rflags function pointer? * This works with VMX, but with SVM I have an additional problem: When trying to exit VM86 (usually by an exception) through a task gate in the IDT, the code runs into the reason = TASK_SWITCH_CALL path. I searched a bit in the documentation, but didn't find any obvious way to fix this. * Yes, I've yet to write a nice testcase for kvm-unittests Signed-off-by: Kevin Wolf <kwolf@xxxxxxxxxx> --- arch/x86/kvm/emulate.c | 13 ++++++++++++- 1 files changed, 12 insertions(+), 1 deletions(-) diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 05a562b..fdd3cca 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -1227,6 +1227,7 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt, seg_desc.type = 3; seg_desc.p = 1; seg_desc.s = 1; + seg_desc.dpl = 3; goto load; } @@ -2246,6 +2247,9 @@ static void save_state_to_tss32(struct x86_emulate_ctxt *ctxt, tss->ldt_selector = get_segment_selector(ctxt, VCPU_SREG_LDTR); } +#define emul_to_vcpu(ctxt) \ + container_of(ctxt, struct kvm_vcpu, arch.emulate_ctxt) + static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt, struct tss_segment_32 *tss) { @@ -2254,7 +2258,14 @@ static int load_state_from_tss32(struct x86_emulate_ctxt *ctxt, if (ctxt->ops->set_cr(ctxt, 3, tss->cr3)) return emulate_gp(ctxt, 0); ctxt->_eip = tss->eip; + ctxt->eflags = tss->eflags | 2; + if (ctxt->eflags & 0x20000) + ctxt->mode = X86EMUL_MODE_VM86; + else + ctxt->mode = X86EMUL_MODE_PROT32; + kvm_set_rflags(emul_to_vcpu(ctxt), ctxt->eflags); + ctxt->regs[VCPU_REGS_RAX] = tss->eax; ctxt->regs[VCPU_REGS_RCX] = tss->ecx; ctxt->regs[VCPU_REGS_RDX] = tss->edx; @@ -2372,7 +2383,7 @@ static int emulator_do_task_switch(struct x86_emulate_ctxt *ctxt, /* FIXME: check that next_tss_desc is tss */ - if (reason != TASK_SWITCH_IRET) { + if (reason != TASK_SWITCH_IRET && reason != TASK_SWITCH_GATE) { if ((tss_selector & 3) > next_tss_desc.dpl || ops->cpl(ctxt) > next_tss_desc.dpl) return emulate_gp(ctxt, 0); -- 1.7.6.5 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html