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

Reply via email to