[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [BUG] x86_emulate function seems to partially handle far-jmp instruction emulation

On 29/09/17 14:53, Anaïs Gantet wrote:


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':

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:

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
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.

Xen-devel mailing list



Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.