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(¤t_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.
>
>
next prev parent 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).