[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH] x86/PV: avoid indirect call/thunk in I/O emulation



On 15/02/18 16:03, Jan Beulich wrote:
> The stub is within reach from the .text section, so there's no point
> using an indirect call here. This has the added benefit of there no
> longer being two sufficiently different approaches, breaking one of
> which people may not even notice.
>
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>

Wow - after all effort I've spent changing (and breaking) this, it
hadn't even occurred to me that a plain jmp was fine.

>
> --- a/xen/arch/x86/pv/emul-priv-op.c
> +++ b/xen/arch/x86/pv/emul-priv-op.c
> @@ -73,55 +73,42 @@ void (*pv_post_outb_hook)(unsigned int p
>  
>  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;
> +    signed long disp;

I'm not in favour of sprinkling 'signed' all over the code base.

long is already unambiguous, and a far more common construct to encounter. 

>      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 + 1 + 4);

The 1 in the middle here only aids clarity in the context above, where
it was part of a direct assignment to offset 11 in io_emul_stub[].

It is marginal, but in this case, I think stub_va + 5 would be slightly
clearer, as call opcode is obviously at 0, and the length of a call
instruction is 5.

~Andrew

> +    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;
>
>
>


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.