From: Andrew Cooper Date: Tue, 9 Jan 2018 16:28:28 +0000 (+0000) Subject: x86/ioemul: Account for ioemul_handle_quirk() in stub length check X-Git-Tag: archive/raspbian/4.11.1-1+rpi1~1^2~66^2~846 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=b6c2c7f48ab8bd5566759cb404afd80fd0df2dfe;p=xen.git x86/ioemul: Account for ioemul_handle_quirk() in stub length check The opcode potentially written into ctxt->io_emul_stub[] in the case that ioemul_handle_quirk() is overriding the default logic isnt accounted for in the build-time check that the stubs are large enough. Introduce IOEMUL_QUIRK_STUB_BYTES and use for both the main and quirk stub cases. As a slim optimisation, avoid writing out the default stub when we know we are going to overwrite it. Signed-off-by: Andrew Cooper Reviewed-by: Jan Beulich --- diff --git a/xen/arch/x86/ioport_emulate.c b/xen/arch/x86/ioport_emulate.c index 58d2b53397..1f6f7948f2 100644 --- a/xen/arch/x86/ioport_emulate.c +++ b/xen/arch/x86/ioport_emulate.c @@ -35,6 +35,8 @@ static void ioemul_handle_proliant_quirk( io_emul_stub[8] = 0x9d; /* ret */ io_emul_stub[9] = 0xc3; + + BUILD_BUG_ON(IOEMUL_QUIRK_STUB_BYTES < 10); } static int __init proliant_quirk(struct dmi_system_id *d) diff --git a/xen/arch/x86/pv/emul-priv-op.c b/xen/arch/x86/pv/emul-priv-op.c index 1041a4cd2a..4087cf2ffb 100644 --- a/xen/arch/x86/pv/emul-priv-op.c +++ b/xen/arch/x86/pv/emul-priv-op.c @@ -89,19 +89,24 @@ static io_emul_stub_t *io_emul_stub_setup(struct priv_op_ctxt *ctxt, u8 opcode, /* callq *%rcx */ ctxt->io_emul_stub[10] = 0xff; ctxt->io_emul_stub[11] = 0xd1; - /* data16 or nop */ - ctxt->io_emul_stub[12] = (bytes != 2) ? 0x90 : 0x66; - /* */ - ctxt->io_emul_stub[13] = opcode; - /* imm8 or nop */ - ctxt->io_emul_stub[14] = !(opcode & 8) ? port : 0x90; - /* ret (jumps to guest_to_host_gpr_switch) */ - ctxt->io_emul_stub[15] = 0xc3; - BUILD_BUG_ON(STUB_BUF_SIZE / 2 < 16); - - if ( ioemul_handle_quirk ) + + if ( likely(!ioemul_handle_quirk) ) + { + /* data16 or nop */ + ctxt->io_emul_stub[12] = (bytes != 2) ? 0x90 : 0x66; + /* */ + ctxt->io_emul_stub[13] = opcode; + /* imm8 or nop */ + ctxt->io_emul_stub[14] = !(opcode & 8) ? port : 0x90; + /* ret (jumps to guest_to_host_gpr_switch) */ + ctxt->io_emul_stub[15] = 0xc3; + } + else ioemul_handle_quirk(opcode, &ctxt->io_emul_stub[12], ctxt->ctxt.regs); + BUILD_BUG_ON(STUB_BUF_SIZE / 2 < MAX(16, /* Regular stubs */ + 12 + IOEMUL_QUIRK_STUB_BYTES)); + /* Handy function-typed pointer to the stub. */ return (void *)(this_cpu(stubs.addr) + STUB_BUF_SIZE / 2); } diff --git a/xen/include/asm-x86/io.h b/xen/include/asm-x86/io.h index b156f4870b..e6bb20cb2f 100644 --- a/xen/include/asm-x86/io.h +++ b/xen/include/asm-x86/io.h @@ -51,6 +51,7 @@ __OUT(l,,int) extern void (*pv_post_outb_hook)(unsigned int port, u8 value); /* Function pointer used to handle platform specific I/O port emulation. */ +#define IOEMUL_QUIRK_STUB_BYTES 10 extern void (*ioemul_handle_quirk)( u8 opcode, char *io_emul_stub, struct cpu_user_regs *regs);