xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Jan Beulich <JBeulich@suse.com>,
	xen-devel <xen-devel@lists.xenproject.org>
Cc: Keir Fraser <keir@xen.org>
Subject: Re: [PATCH 2/4] x86emul: move stubs off the stack
Date: Tue, 19 May 2015 18:33:54 +0100	[thread overview]
Message-ID: <555B7402.8070600@citrix.com> (raw)
In-Reply-To: <5559FB51020000780007B19A@mail.emea.novell.com>

On 18/05/15 13:46, Jan Beulich wrote:
> This is needed as stacks are going to become non-executable.
>
> Signed-off-by: Jan Beulich <jbeulich@suse.com>
>
> --- a/tools/tests/x86_emulator/x86_emulate.c
> +++ b/tools/tests/x86_emulator/x86_emulate.c
> @@ -17,4 +17,8 @@ typedef bool bool_t;
>  #define __packed __attribute__((packed))
>  
>  #include "x86_emulate/x86_emulate.h"
> +
> +#define get_stub(stb) ((void *)((stb).addr = (uintptr_t)(stb).buf))
> +#define put_stub(stb)
> +
>  #include "x86_emulate/x86_emulate.c"
> --- a/xen/arch/x86/x86_emulate.c
> +++ b/xen/arch/x86/x86_emulate.c
> @@ -9,6 +9,7 @@
>   *    Keir Fraser <keir@xen.org>
>   */
>  
> +#include <xen/domain_page.h>
>  #include <asm/x86_emulate.h>
>  #include <asm/asm_defns.h> /* mark_regs_dirty() */
>  #include <asm/processor.h> /* current_cpu_info */
> @@ -17,8 +18,22 @@
>  /* Avoid namespace pollution. */
>  #undef cmpxchg
>  #undef cpuid
> +#undef wbinvd
>  
>  #define cpu_has_amd_erratum(nr) \
>          cpu_has_amd_erratum(&current_cpu_data, AMD_ERRATUM_##nr)
>  
> +#define get_stub(stb) ({                                   \
> +    (stb).addr = this_cpu(stubs.addr) + STUB_BUF_SIZE / 2; \
> +    ((stb).ptr = map_domain_page(this_cpu(stubs.mfn))) +   \
> +        ((stb).addr & (PAGE_SIZE - 1));                    \
> +})
> +#define put_stub(stb) ({                                   \
> +    if ( (stb).ptr )                                       \
> +    {                                                      \
> +        unmap_domain_page((stb).ptr);                      \
> +        (stb).ptr = NULL;                                  \
> +    }                                                      \
> +})
> +

These don't need to be macros, and I suspect a compiler would choose to
out-of-line get_stub() if it could.

>  #include "x86_emulate/x86_emulate.c"
> --- a/xen/arch/x86/x86_emulate/x86_emulate.c
> +++ b/xen/arch/x86/x86_emulate/x86_emulate.c
> @@ -717,11 +717,14 @@ do{ struct fpu_insn_ctxt fic;           
>  } while (0)
>  
>  #define emulate_fpu_insn_stub(_bytes...)                                \
> -do{ uint8_t stub[] = { _bytes, 0xc3 };                                  \
> -    struct fpu_insn_ctxt fic = { .insn_bytes = sizeof(stub)-1 };        \
> +do{ uint8_t *buf = get_stub(stub);                                      \
> +    unsigned int _nr = sizeof((uint8_t[]){ _bytes });                   \
> +    struct fpu_insn_ctxt fic = { .insn_bytes = _nr };                    \

Alignment of backslashes.

> +    memcpy(buf, ((uint8_t[]){ _bytes, 0xc3 }), _nr + 1);                \
>      get_fpu(X86EMUL_FPU_fpu, &fic);                                     \
> -    (*(void(*)(void))stub)();                                           \
> +    stub.func();                                                        \
>      put_fpu(&fic);                                                      \
> +    put_stub(stub);                                                     \
>  } while (0)
>  
>  static unsigned long _get_rep_prefix(
> @@ -1458,6 +1461,7 @@ x86_emulate(
>      struct operand src = { .reg = REG_POISON };
>      struct operand dst = { .reg = REG_POISON };
>      enum x86_swint_type swint_type;
> +    struct x86_emulate_stub stub = {};
>      DECLARE_ALIGNED(mmval_t, mmval);
>      /*
>       * Data operand effective address (usually computed from ModRM).
> @@ -3792,6 +3796,7 @@ x86_emulate(
>  
>   done:
>      _put_fpu();
> +    put_stub(stub);
>      return rc;
>  
>   twobyte_insn:
> @@ -4007,9 +4012,15 @@ x86_emulate(
>                 /* {,v}movss xmm,xmm/m32 */
>                 /* {,v}movsd xmm,xmm/m64 */
>      {
> -        uint8_t stub[] = { 0x3e, 0x3e, 0x0f, b, modrm, 0xc3 };
> -        struct fpu_insn_ctxt fic = { .insn_bytes = sizeof(stub)-1 };
> +        uint8_t *buf = get_stub(stub);
> +        struct fpu_insn_ctxt fic = { .insn_bytes = 5 };
>  
> +        buf[0] = 0x3e;
> +        buf[1] = 0x3e;
> +        buf[2] = 0x0f;
> +        buf[3] = b;
> +        buf[4] = modrm;
> +        buf[5] = 0xc3;
>          if ( vex.opcx == vex_none )
>          {
>              if ( vex.pfx & VEX_PREFIX_DOUBLE_MASK )
> @@ -4017,7 +4028,7 @@ x86_emulate(
>              else
>                  vcpu_must_have_sse();
>              ea.bytes = 16;
> -            SET_SSE_PREFIX(stub[0], vex.pfx);
> +            SET_SSE_PREFIX(buf[0], vex.pfx);
>              get_fpu(X86EMUL_FPU_xmm, &fic);
>          }
>          else
> @@ -4044,15 +4055,16 @@ x86_emulate(
>              /* convert memory operand to (%rAX) */
>              rex_prefix &= ~REX_B;
>              vex.b = 1;
> -            stub[4] &= 0x38;
> +            buf[4] &= 0x38;
>          }
>          if ( !rc )
>          {
> -           copy_REX_VEX(stub, rex_prefix, vex);
> -           asm volatile ( "call *%0" : : "r" (stub), "a" (mmvalp)
> +           copy_REX_VEX(buf, rex_prefix, vex);
> +           asm volatile ( "call *%0" : : "r" (stub.func), "a" (mmvalp)
>                                       : "memory" );
>          }
>          put_fpu(&fic);
> +        put_stub(stub);
>          if ( !rc && (b & 1) && (ea.type == OP_MEM) )
>              rc = ops->write(ea.mem.seg, ea.mem.off, mmvalp,
>                              ea.bytes, ctxt);
> @@ -4242,9 +4254,15 @@ x86_emulate(
>                 /* {,v}movdq{a,u} xmm,xmm/m128 */
>                 /* vmovdq{a,u} ymm,ymm/m256 */
>      {
> -        uint8_t stub[] = { 0x3e, 0x3e, 0x0f, b, modrm, 0xc3 };
> -        struct fpu_insn_ctxt fic = { .insn_bytes = sizeof(stub)-1 };
> +        uint8_t *buf = get_stub(stub);
> +        struct fpu_insn_ctxt fic = { .insn_bytes = 5 };
>  
> +        buf[0] = 0x3e;
> +        buf[1] = 0x3e;
> +        buf[2] = 0x0f;
> +        buf[3] = b;
> +        buf[4] = modrm;
> +        buf[5] = 0xc3;
>          if ( vex.opcx == vex_none )
>          {
>              switch ( vex.pfx )
> @@ -4252,7 +4270,7 @@ x86_emulate(
>              case vex_66:
>              case vex_f3:
>                  vcpu_must_have_sse2();
> -                stub[0] = 0x66; /* movdqa */
> +                buf[0] = 0x66; /* movdqa */
>                  get_fpu(X86EMUL_FPU_xmm, &fic);
>                  ea.bytes = 16;
>                  break;
> @@ -4288,15 +4306,16 @@ x86_emulate(
>              /* convert memory operand to (%rAX) */
>              rex_prefix &= ~REX_B;
>              vex.b = 1;
> -            stub[4] &= 0x38;
> +            buf[4] &= 0x38;
>          }
>          if ( !rc )
>          {
> -           copy_REX_VEX(stub, rex_prefix, vex);
> -           asm volatile ( "call *%0" : : "r" (stub), "a" (mmvalp)
> +           copy_REX_VEX(buf, rex_prefix, vex);
> +           asm volatile ( "call *%0" : : "r" (stub.func), "a" (mmvalp)
>                                       : "memory" );
>          }
>          put_fpu(&fic);
> +        put_stub(stub);
>          if ( !rc && (b != 0x6f) && (ea.type == OP_MEM) )
>              rc = ops->write(ea.mem.seg, ea.mem.off, mmvalp,
>                              ea.bytes, ctxt);
> @@ -4638,5 +4657,6 @@ x86_emulate(
>  
>   cannot_emulate:
>      _put_fpu();
> +    put_stub(stub);
>      return X86EMUL_UNHANDLEABLE;
>  }
> --- a/xen/arch/x86/x86_emulate/x86_emulate.h
> +++ b/xen/arch/x86/x86_emulate/x86_emulate.h
> @@ -429,6 +429,18 @@ struct x86_emulate_ctxt
>      } retire;
>  };
>  
> +struct x86_emulate_stub {
> +    union {
> +        void (*func)(void);
> +        uintptr_t addr;
> +    };
> +#ifdef __XEN__
> +    void *ptr;
> +#else
> +    uint8_t buf[32];

16 is surely enough? The emulator will #GP if it attempts to fetch more
than 15 bytes, and only a 'ret' is needed after that.

~Andrew

> +#endif
> +};
> +
>  /*
>   * x86_emulate: Emulate an instruction.
>   * Returns -1 on failure, 0 on success.
>
>

  reply	other threads:[~2015-05-19 17:34 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-18 10:28 [PATCH 0/4] x86: don't default to executable mappings Jan Beulich
2015-05-18 12:46 ` [PATCH 1/4] x86: move syscall trampolines off the stack Jan Beulich
2015-05-18 18:39   ` Andrew Cooper
2015-05-19  6:41     ` Jan Beulich
2015-05-19  9:24       ` Andrew Cooper
2015-05-19 16:59   ` Andrew Cooper
2015-05-20  9:16     ` Jan Beulich
2015-05-20 13:37     ` Jan Beulich
2015-05-20 13:58       ` Andrew Cooper
2015-05-20 15:54     ` Jan Beulich
2015-05-18 12:46 ` [PATCH 2/4] x86emul: move stubs " Jan Beulich
2015-05-19 17:33   ` Andrew Cooper [this message]
2015-05-20  9:25     ` Jan Beulich
2015-05-18 12:47 ` [PATCH 3/4] x86: move I/O emulation " Jan Beulich
2015-05-19 17:48   ` Andrew Cooper
2015-05-20 13:57     ` Jan Beulich
2015-05-18 12:47 ` [PATCH 4/4] x86: switch default mapping attributes to non-executable Jan Beulich
2015-05-19 18:53   ` Andrew Cooper
2015-05-20  9:32     ` Jan Beulich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=555B7402.8070600@citrix.com \
    --to=andrew.cooper3@citrix.com \
    --cc=JBeulich@suse.com \
    --cc=keir@xen.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).