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

Re: [Xen-devel] [PATCH 2/4] x86emul: centralize put_fpu() invocations



On 13/03/17 11:03, Jan Beulich wrote:
> ..., splitting parts of it into check_*() macros. This is in
> preparation of making ->put_fpu() do further adjustments to register
> state. (Some of the check_xmm() invocations could be avoided, as in
> some of the cases no insns handled there can actually raise #XM, but I
> think we're better off keeping them to avoid later additions of further
> insn patterns rendering the lack of the check a bug.)
>
> 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
> @@ -937,6 +937,7 @@ do {
>  
>  struct fpu_insn_ctxt {
>      uint8_t insn_bytes;
> +    uint8_t type;
>      int8_t exn_raised;
>  };
>  
> @@ -956,8 +957,6 @@ static int _get_fpu(
>  {
>      int rc;
>  
> -    fic->exn_raised = -1;
> -
>      fail_if(!ops->get_fpu);
>      rc = ops->get_fpu(fpu_handle_exception, fic, type, ctxt);
>  
> @@ -965,6 +964,8 @@ static int _get_fpu(
>      {
>          unsigned long cr0;
>  
> +        fic->type = type;
> +
>          fail_if(!ops->read_cr);
>          if ( type >= X86EMUL_FPU_xmm )
>          {
> @@ -1006,22 +1007,31 @@ do {
>      rc = _get_fpu(_type, _fic, ctxt, ops);                      \
>      if ( rc ) goto done;                                        \
>  } while (0)
> -#define _put_fpu()                                              \
> +
> +#define check_fpu(_fic)                                         \
>  do {                                                            \
> -    if ( ops->put_fpu != NULL )                                 \
> -        (ops->put_fpu)(ctxt);                                   \
> +    generate_exception_if((_fic)->exn_raised >= 0,              \
> +                          (_fic)->exn_raised);                  \
>  } while (0)
> -#define put_fpu(_fic)                                           \
> +
> +#define check_xmm(_fic)                                         \
>  do {                                                            \
> -    _put_fpu();                                                 \
>      if ( (_fic)->exn_raised == EXC_XM && ops->read_cr &&        \
>           ops->read_cr(4, &cr4, ctxt) == X86EMUL_OKAY &&         \
>           !(cr4 & X86_CR4_OSXMMEXCPT) )                               \
>          (_fic)->exn_raised = EXC_UD;                            \
> -    generate_exception_if((_fic)->exn_raised >= 0,              \
> -                          (_fic)->exn_raised);                  \
> +    check_fpu(_fic);                                            \
>  } while (0)

These two check macros seem like they should have an _exn() suffix to
make it clearer what they are actually doing.

>  
> +static void put_fpu(
> +    struct fpu_insn_ctxt *fic,
> +    struct x86_emulate_ctxt *ctxt,
> +    const struct x86_emulate_ops *ops)
> +{
> +    if ( fic->type != X86EMUL_FPU_none && ops->put_fpu )
> +        ops->put_fpu(ctxt);
> +}
> +
>  static inline bool fpu_check_write(void)
>  {
>      uint16_t fsw;
> @@ -7905,7 +7912,8 @@ x86_emulate(
>      ctxt->regs->eflags &= ~X86_EFLAGS_RF;
>  
>   done:
> -    _put_fpu();
> +    if ( rc != X86EMUL_OKAY )
> +        put_fpu(&fic, ctxt, ops);

Unless you assert at complete_insn that rc == X86EMUL_OKAY, you still
might call put_fpu() twice.

You can avoid the conditional here by setting fic->type to
X86EMUL_FPU_none at the end of put_fpu(), which looks like it is
compatible with your later modifications.

>      put_stub(stub);
>      return rc;
>  #undef state
> --- a/xen/arch/x86/x86_emulate/x86_emulate.h
> +++ b/xen/arch/x86/x86_emulate/x86_emulate.h
> @@ -161,7 +161,9 @@ enum x86_emulate_fpu_type {
>      X86EMUL_FPU_wait, /* WAIT/FWAIT instruction */
>      X86EMUL_FPU_mmx, /* MMX instruction set (%mm0-%mm7) */
>      X86EMUL_FPU_xmm, /* SSE instruction set (%xmm0-%xmm7/15) */
> -    X86EMUL_FPU_ymm  /* AVX/XOP instruction set (%ymm0-%ymm7/15) */
> +    X86EMUL_FPU_ymm, /* AVX/XOP instruction set (%ymm0-%ymm7/15) */
> +    /* This sentinel will never be passed to ->get_fpu(). */

Don't you mean ->put_fpu() here?  Either way, can we assert this fact?

~Andrew

> +    X86EMUL_FPU_none
>  };
>  
>  struct cpuid_leaf
>
>


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

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