[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 2/4] x86emul: move stubs off the stack
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@xxxxxxxx> > > --- 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@xxxxxxx> > */ > > +#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. > > _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |