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

Re: [Xen-devel] [PATCH v6.5 11/26] x86: Support indirect thunks from assembly code



>>> On 04.01.18 at 01:15, <andrew.cooper3@xxxxxxxxxx> wrote:
> --- a/xen/arch/x86/boot/trampoline.S
> +++ b/xen/arch/x86/boot/trampoline.S
> @@ -153,8 +153,28 @@ trampoline_protmode_entry:
>          .code64
>  start64:
>          /* Jump to high mappings. */
> -        movabs  $__high_start,%rax
> -        jmpq    *%rax
> +        movabs  $__high_start, %rdi
> +
> +#ifdef CONFIG_INDIRECT_THUNK
> +        /*
> +         * If booting virtualised, or hot-onlining a CPU, sibling threads can
> +         * attempt Branch Target Injection against this jmp.
> +         *
> +         * We've got no usable stack so can't use a RETPOLINE thunk, and are
> +         * further than +- 2G from the high mappings so couldn't use 
> JUMP_THUNK
> +         * even if was a non-RETPOLINE thunk.  Futhermore, an LFENCE isn't
> +         * necesserily safe to use at this point.
> +         *
> +         * As this isn't a hotpath, use a fully serialising event to reduce
> +         * the speculation window as much as possible.  %ebx needs preserving
> +         * for __high_start.
> +         */
> +        mov     %ebx, %esi
> +        cpuid
> +        mov     %esi, %ebx
> +#endif
> +
> +        jmpq    *%rdi

Would there be anything wrong with omitting the #ifdef, slightly
improving readability?

> --- a/xen/arch/x86/pv/emul-priv-op.c
> +++ b/xen/arch/x86/pv/emul-priv-op.c
> @@ -73,37 +73,58 @@ void (*pv_post_outb_hook)(unsigned int port, u8 value);
>  
>  typedef void io_emul_stub_t(struct cpu_user_regs *);
>  
> +#ifdef CONFIG_INDIRECT_THUNK
> +extern char ind_thunk_rcx[] asm ("__x86.indirect_thunk.rcx");
> +#endif

Again I don't see the value of the #ifdef.

>  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;
> +
>      if ( !ctxt->io_emul_stub )
> -        ctxt->io_emul_stub = map_domain_page(_mfn(this_cpu(stubs.mfn))) +
> -                                             (this_cpu(stubs.addr) &
> -                                              ~PAGE_MASK) +
> -                                             STUB_BUF_SIZE / 2;
> +        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] =
> +        _p(ind_thunk_rcx) - _p(stub_va + 11 + 4);

Why two (hidden) casts when one (clearly visible one) would do:

    *(int32_t *)&ctxt->io_emul_stub[11] =
        (unsigned long)ind_thunk_rcx - (stub_va + 11 + 4);

?

> +#else
>      /* callq *%rcx */
>      ctxt->io_emul_stub[10] = 0xff;
>      ctxt->io_emul_stub[11] = 0xd1;
> +
> +    /*
> +     * 3 bytes of P6_NOPS.
> +     * TODO: untangle ideal_nops from init/livepatch Kconfig options.
> +     */
> +    memcpy(&ctxt->io_emul_stub[12], "\x0f\x1f\x00", 3);
> +#endif

Same here - rather than making everything more complicated to
read/understand, why don't we avoid conditionals in places where
performance is of no concern. In the end it may well be that we
wouldn't need CONFIG_INDIRECT_THUNK at all, unless it became
a user-selectable option (as suggested in reply to patch 9).

> --- a/xen/include/asm-x86/asm_defns.h
> +++ b/xen/include/asm-x86/asm_defns.h
> @@ -13,6 +13,14 @@
>  #include <asm/cpufeature.h>
>  #include <asm/alternative.h>
>  
> +#ifdef __ASSEMBLY__
> +# include <asm/indirect_thunk_asm.h>
> +#else
> +asm ( "\t.equ CONFIG_INDIRECT_THUNK, "
> +      __stringify(IS_ENABLED(CONFIG_INDIRECT_THUNK)) );
> +asm ( "\t.include \"asm/indirect_thunk_asm.h\"" );
> +#endif

For this to work with all compilers, aren't you still missing the
addition of -Wa,-I$(BASEDIR)/include on top of the other
compiler option additions done in patch 9?

> --- /dev/null
> +++ b/xen/include/asm-x86/indirect_thunk_asm.h
> @@ -0,0 +1,41 @@
> +/*
> + * Warning!  This file is included at an assembler level for .c files, 
> causing
> + * usual #ifdef'ary to turn into comments.
> + */
> +
> +.macro IND_THUNK insn:req arg:req
> +/*
> + * Create an indirect branch.  insn is one of call/jmp, arg is a single
> + * register.
> + *
> + * With no compiler support, this degrated into a plain indirect call/jmp.

"degrades" or "degenerates" or yet something else?

> + * With compiler support, dispatch to the correct __x86.indirect_thunk.*
> + */
> +    .if CONFIG_INDIRECT_THUNK == 1

If we really want/need to keep this config option, why not without
the "== 1"?

> +        $done = 0
> +        .irp reg, rax, rbx, rcx, rdx, rsi, rdi, rbp, r8, r9, r10, r11, r12, 
> r13, r14, r15

Same cosmetic remark as earlier regarding the ordering and the
possible omission of the r-s here.

Jan

_______________________________________________
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®.