On 29/09/17 14:53, Anaïs Gantet wrote: > > Hi, > > I would just like to underline a unusual behaviour I observed recently > with Xen. Indeed, a test with a Xen HVM x86-32bit guest pointed out the > x86_emulate function in xen/arch/x86/x86_emulate/x86_emulate.c seems to > only partially handle far-jmp instruction emulation. > > According to Intel documentation, when the processor is operating in > protected mode, there exists three types of far jumps: > * A far jump to a conforming or non-conforming code segment; > * A far jump through a call gate; > * A task switch - through a task gate or directly with a TSS segment. > > When x86_emulate function emulates a far jmp (case 0xea or 0xff/5), it > does not check what type of descriptor given as far-jmp parameter. When > performing segment loading (by calling load_seg function), type segment > parameter is always set to 'x86_seg_cs': > > xen/arch/x86/x86_emulate/x86_emulate.c: > 4665 far_jmp: > 4666 if ( (rc = load_seg(x86_seg_cs, imm2, 0, &cs, ctxt, ops)) || > 4667 (rc = commit_far_branch(&cs, imm1)) ) > 4668 goto done; > 4669 break; > > In protected mode load_seg calls protmode_load_seg. Before loading > segment, protmode_load_seg checks several properties, in particular the > consistency of the system flag S of 'x86_seg_cs' and of the descriptor > 'desc' referenced by 'imm2'. If imm2 references a call gate, a task gate > or a tss segment, flag S is clear and differs from x86_seg_cs flag. That > lead to a segmentation fault: > > xen/arch/x86/x86_emulate/x86_emulate.c: > 1434 /* User segments must have S flag == 1. */ > 1435 if ( is_x86_user_segment(seg) && !(desc.b & (1u << 12)) ) > 1436 goto raise_exn; > > In a nutshell, x86_emulate always generates a segmentation fault instead > of performing a legitim task swich or a legitim far jump through a call > gate. > Is it normal ? >
Unfortunately, (lack of) support for far calls/jumps to gates is a known limitation. It it wasn't explicitly identified before, it did come to light as part of c/s 653cae72 when trying to reduce the number of x86 instruction decoders in the hypervisor to just one. The current architecture of x86_emulate() makes it hard to fix. At the most recent Xen Dev Summit, I proposed an alteration in emulation architecture which will allow us to use one single implementation which works for PV and HVM guests. It will have the advantage of allowing us to harmonise the task switch logic as well, which currently only works when initiated from a VT-x/SVM TASK_SWITCH vmexit, rather than an emulation of `lcall $tss` In short, its known broken and there is a plan to try and resolve it. ~Andrew
_______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org https://lists.xen.org/xen-devel