[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 09:23, Jan Beulich wrote:
>>>> 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?

Functionally, not, but I'm not convinced it would make anything better
either.

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

This ifdef is strictly required.  asm ("__x86.indirect_thunk.rcx");
doesn't exist when building with an incapable toolchain.

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

Again, these are strictly required, because of ind_thunk_rcx[].

> 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?

Ah yes - I will fold that in.

>
>> --- /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?

Degrades.

~Andrew

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