typedef void io_emul_stub_t(struct cpu_user_regs *);
-void __x86_indirect_thunk_rcx(void);
-
static io_emul_stub_t *io_emul_stub_setup(struct priv_op_ctxt *ctxt, u8 opcode,
unsigned int port, unsigned int bytes)
{
struct stubs *this_stubs = &this_cpu(stubs);
unsigned long stub_va = this_stubs->addr + STUB_BUF_SIZE / 2;
+ long disp;
bool use_quirk_stub = false;
if ( !ctxt->io_emul_stub )
ctxt->io_emul_stub =
map_domain_page(_mfn(this_stubs->mfn)) + (stub_va & ~PAGE_MASK);
- /* movq $host_to_guest_gpr_switch,%rcx */
- ctxt->io_emul_stub[0] = 0x48;
- ctxt->io_emul_stub[1] = 0xb9;
- *(void **)&ctxt->io_emul_stub[2] = (void *)host_to_guest_gpr_switch;
-
-#ifdef CONFIG_INDIRECT_THUNK
- /* callq __x86_indirect_thunk_rcx */
- ctxt->io_emul_stub[10] = 0xe8;
- *(int32_t *)&ctxt->io_emul_stub[11] =
- (long)__x86_indirect_thunk_rcx - (stub_va + 11 + 4);
-#else
- /* callq *%rcx */
- ctxt->io_emul_stub[10] = 0xff;
- ctxt->io_emul_stub[11] = 0xd1;
- /* TODO: untangle ideal_nops from init/livepatch Kconfig options. */
- memcpy(&ctxt->io_emul_stub[12], "\x0f\x1f\x00", 3); /* P6_NOP3 */
-#endif
+ /* call host_to_guest_gpr_switch */
+ ctxt->io_emul_stub[0] = 0xe8;
+ disp = (long)host_to_guest_gpr_switch - (stub_va + 5);
+ BUG_ON((int32_t)disp != disp);
+ *(int32_t *)&ctxt->io_emul_stub[1] = disp;
if ( unlikely(ioemul_handle_quirk) )
- use_quirk_stub = ioemul_handle_quirk(opcode, &ctxt->io_emul_stub[15],
+ use_quirk_stub = ioemul_handle_quirk(opcode, &ctxt->io_emul_stub[5],
ctxt->ctxt.regs);
if ( !use_quirk_stub )
{
/* data16 or nop */
- ctxt->io_emul_stub[15] = (bytes != 2) ? 0x90 : 0x66;
+ ctxt->io_emul_stub[5] = (bytes != 2) ? 0x90 : 0x66;
/* <io-access opcode> */
- ctxt->io_emul_stub[16] = opcode;
+ ctxt->io_emul_stub[6] = opcode;
/* imm8 or nop */
- ctxt->io_emul_stub[17] = !(opcode & 8) ? port : 0x90;
+ ctxt->io_emul_stub[7] = !(opcode & 8) ? port : 0x90;
/* ret (jumps to guest_to_host_gpr_switch) */
- ctxt->io_emul_stub[18] = 0xc3;
+ ctxt->io_emul_stub[8] = 0xc3;
}
- BUILD_BUG_ON(STUB_BUF_SIZE / 2 < MAX(19, /* Default emul stub */
- 15 + IOEMUL_QUIRK_STUB_BYTES));
+ BUILD_BUG_ON(STUB_BUF_SIZE / 2 < MAX(9, /* Default emul stub */
+ 5 + IOEMUL_QUIRK_STUB_BYTES));
/* Handy function-typed pointer to the stub. */
return (void *)stub_va;