|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 1/5] x86emul: support UMIP
On 08/09/16 14:42, Jan Beulich wrote:
> To make this complete, also add support for SLDT and STR. Note that by
> just looking at the guest CR4 bit, this is independent of actually
> making available the UMIP feature to guests.
>
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
>
> --- a/xen/arch/x86/x86_emulate/x86_emulate.c
> +++ b/xen/arch/x86/x86_emulate/x86_emulate.c
> @@ -182,7 +182,7 @@ static const opcode_desc_t opcode_table[
>
> static const opcode_desc_t twobyte_table[256] = {
> /* 0x00 - 0x07 */
> - SrcMem16|ModRM, ImplicitOps|ModRM, ModRM, ModRM,
> + ModRM, ImplicitOps|ModRM, ModRM, ModRM,
> 0, ImplicitOps, ImplicitOps, ImplicitOps,
> /* 0x08 - 0x0F */
> ImplicitOps, ImplicitOps, 0, ImplicitOps,
> @@ -421,6 +421,7 @@ typedef union {
> /* Control register flags. */
> #define CR0_PE (1<<0)
> #define CR4_TSD (1<<2)
> +#define CR4_UMIP (1<<11)
>
> /* EFLAGS bit definitions. */
> #define EFLG_VIP (1<<20)
> @@ -1484,6 +1485,17 @@ static bool is_aligned(enum x86_segment
> return !((reg.base + offs) & (size - 1));
> }
>
> +static bool is_umip(struct x86_emulate_ctxt *ctxt,
> + const struct x86_emulate_ops *ops)
is_umip is an odd way of phrasing this. umip_enabled() or
is_umip_enabled() would be better.
> +{
> + unsigned long cr4;
> +
> + /* Intentionally not using mode_ring0() here to avoid its fail_if(). */
> + return get_cpl(ctxt, ops) > 0 &&
> + ops->read_cr && ops->read_cr(4, &cr4, ctxt) == X86EMUL_OKAY &&
> + (cr4 & CR4_UMIP);
> +}
> +
> /* Inject a software interrupt/exception, emulating if needed. */
> static int inject_swint(enum x86_swint_type type,
> uint8_t vector, uint8_t insn_len,
> @@ -2051,10 +2063,20 @@ x86_decode(
> break;
>
> case ext_0f:
> - case ext_0f3a:
> - case ext_8f08:
> - case ext_8f09:
> - case ext_8f0a:
> + switch ( b )
> + {
> + case 0x00: /* Grp6 */
> + switch ( modrm_reg & 6 )
> + {
> + case 0:
> + d |= DstMem | SrcImplicit | Mov;
> + break;
> + case 2: case 4:
> + d |= SrcMem16;
> + break;
> + }
> + break;
> + }
> break;
>
> case ext_0f38:
> @@ -2070,6 +2092,12 @@ x86_decode(
> }
> break;
>
> + case ext_0f3a:
> + case ext_8f08:
> + case ext_8f09:
> + case ext_8f0a:
> + break;
> +
> default:
> ASSERT_UNREACHABLE();
> }
> @@ -4177,14 +4205,31 @@ x86_emulate(
> }
> break;
>
> - case X86EMUL_OPC(0x0f, 0x00): /* Grp6 */
> - fail_if((modrm_reg & 6) != 2);
> + case X86EMUL_OPC(0x0f, 0x00): /* Grp6 */ {
Newline for {
> + enum x86_segment seg = (modrm_reg & 1) ? x86_seg_tr : x86_seg_ldtr;
> +
> + fail_if(modrm_reg & 4);
> generate_exception_if(!in_protmode(ctxt, ops), EXC_UD, -1);
> - generate_exception_if(!mode_ring0(), EXC_GP, 0);
> - if ( (rc = load_seg((modrm_reg & 1) ? x86_seg_tr : x86_seg_ldtr,
> - src.val, 0, NULL, ctxt, ops)) != 0 )
> - goto done;
> + if ( modrm_reg & 2 )
This needs to be (modrm_reg & 6) == 2. Otherwise, the /6 and /7
encodings will also raise #GP when they should raise #UD
Actually thinking about it, could we just have a full switch here like
other Grp $N decodes?
~Andrew
> + {
> + generate_exception_if(!mode_ring0(), EXC_GP, 0);
> + if ( (rc = load_seg(seg, src.val, 0, NULL, ctxt, ops)) != 0 )
> + goto done;
> + }
> + else
> + {
> + struct segment_register reg;
> +
> + generate_exception_if(is_umip(ctxt, ops), EXC_GP, 0);
> + fail_if(!ops->read_segment);
> + if ( (rc = ops->read_segment(seg, ®, ctxt)) != 0 )
> + goto done;
> + dst.val = reg.sel;
> + if ( dst.type == OP_MEM )
> + dst.bytes = 2;
> + }
> break;
> + }
>
> case X86EMUL_OPC(0x0f, 0x01): /* Grp7 */ {
> struct segment_register reg;
> @@ -4282,6 +4327,7 @@ x86_emulate(
> case 0: /* sgdt */
> case 1: /* sidt */
> generate_exception_if(ea.type != OP_MEM, EXC_UD, -1);
> + generate_exception_if(is_umip(ctxt, ops), EXC_GP, 0);
> fail_if(ops->read_segment == NULL);
> if ( (rc = ops->read_segment((modrm_reg & 1) ?
> x86_seg_idtr : x86_seg_gdtr,
> @@ -4316,6 +4362,7 @@ x86_emulate(
> goto done;
> break;
> case 4: /* smsw */
> + generate_exception_if(is_umip(ctxt, ops), EXC_GP, 0);
> ea.bytes = (ea.type == OP_MEM) ? 2 : op_bytes;
> dst = ea;
> fail_if(ops->read_cr == NULL);
>
>
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |