Message ID | 20190313124042.12855-6-pbonzini@redhat.com |
---|---|
State | New |
Headers | show |
Series | CET support | expand |
On 3/13/19 5:40 AM, Paolo Bonzini wrote: > Add endbr annotations before indirect branch targets. This lets QEMU enable > IBT even for TCG-enabled builds. > @@ -3514,6 +3526,7 @@ static void tcg_target_qemu_prologue(TCGContext *s) > CPU_TEMP_BUF_NLONGS * sizeof(long)); > > /* Save all callee saved registers. */ > + tcg_out_endbr(s); > for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { > tcg_out_push(s, tcg_target_callee_save_regs[i]); > } Nit: Keep the comment with the code to which it applies. I'll note that there's one latent but currently unused indirect branch: > } else { > /* indirect jump method */ > tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, -1, > (intptr_t)(s->tb_jmp_target_addr + a0)); > } > set_jmp_reset_offset(s, a0); We can probably just delete that condition, and assert it instead. Otherwise, Reviewed-by: Richard Henderson <richard.henderson@linaro.org> r~
On 3/13/19 5:40 AM, Paolo Bonzini wrote: > +static void tcg_out_endbr(TCGContext *s) > +{ > +#if defined __CET__ && (__CET__ & 1) > +#ifdef __x86_64__ > + tcg_out32(s, 0xfa1e0ff3); > +#else > + tcg_out32(s, 0xfb1e0ff3); > +#endif > +#endif > +} Normally we'd use a runtime test for the feature. Just because we compiled with CET does not mean we're running on CET-enabled hardware, since IIRC this is a nop otherwise. I assume there's a cpuid/xgetbv bit that indicates when IBT is present and/or active? r~
On 14/03/19 02:05, Richard Henderson wrote: > On 3/13/19 5:40 AM, Paolo Bonzini wrote: >> +static void tcg_out_endbr(TCGContext *s) >> +{ >> +#if defined __CET__ && (__CET__ & 1) >> +#ifdef __x86_64__ >> + tcg_out32(s, 0xfa1e0ff3); >> +#else >> + tcg_out32(s, 0xfb1e0ff3); >> +#endif >> +#endif >> +} > > Normally we'd use a runtime test for the feature. > > Just because we compiled with CET does not mean we're running on CET-enabled > hardware, since IIRC this is a nop otherwise. I assume there's a cpuid/xgetbv > bit that indicates when IBT is present and/or active? No, there is a way to deduce whether shadow stack is active, but IBT is only detectable by SIGSEGV'ing. It is enabled through an MSR which of course is not available from user space. There is a prctl to query the state, ARCH_X86_CET_STATUS, but I'm a bit wary of adding support for it before it hits the kernel; IBT only needs compiler support because the instructions/prefixes are a nop if disabled, unlike SHSTK which needs the "allocate shadow stack" prctl. It's a small fixed cost per TB, it seemed not a big deal to me. Paolo
On 3/14/19 3:50 AM, Paolo Bonzini wrote: > There is a prctl to query the state, ARCH_X86_CET_STATUS, but I'm a bit > wary of adding support for it before it hits the kernel; IBT only needs > compiler support because the instructions/prefixes are a nop if > disabled, unlike SHSTK which needs the "allocate shadow stack" prctl. > It's a small fixed cost per TB, it seemed not a big deal to me. There's a cpuid bit though, leaf 7, ebx bit 20. If that's not set... It's a small fixed cost, and it's possible that it's lost in the padding between TB's. But per 256k TB's it's 1MB "wasted", worst case. r~
On 14/03/19 16:15, Richard Henderson wrote:
> There's a cpuid bit though, leaf 7, ebx bit 20. If that's not set...
Yes, I can definitely test CPUID.
Paolo
On Wed, Mar 13, 2019 at 01:40:40PM +0100, Paolo Bonzini wrote: > +static void tcg_out_endbr(TCGContext *s) > +{ > +#if defined __CET__ && (__CET__ & 1) Please include a comment explaining why __CET__ & 1 is necessary. Is bit 0 of __CET__ the Indirect Branch Tracking feature flag?
diff --git a/Makefile.target b/Makefile.target index fa143d7b4b..df413c9b7f 100644 --- a/Makefile.target +++ b/Makefile.target @@ -114,8 +114,10 @@ obj-y += accel/ obj-$(CONFIG_TCG) += tcg/tcg.o tcg/tcg-op.o tcg/tcg-op-vec.o tcg/tcg-op-gvec.o obj-$(CONFIG_TCG) += tcg/tcg-common.o tcg/optimize.o ifeq ($(CONFIG_CET),y) +ifneq ($(CONFIG_CET_TCG),y) tcg/tcg.o-cflags := -fcf-protection=return endif +endif obj-$(CONFIG_TCG_INTERPRETER) += tcg/tci.o obj-$(CONFIG_TCG_INTERPRETER) += disas/tci.o obj-$(CONFIG_TCG) += fpu/softfloat.o diff --git a/configure b/configure index 4470fe8e74..4e553e521b 100755 --- a/configure +++ b/configure @@ -5096,6 +5096,11 @@ if test "$cet" = ""; then cet=yes QEMU_CFLAGS="-fcf-protection $QEMU_CFLAGS" fi +if test "$cpu" = "x86_64"; then + cet_tcg=yes +else + cet_tcg=no +fi ########################################## # check and set a backend for coroutine @@ -6290,6 +6295,7 @@ echo "TCG support $tcg" if test "$tcg" = "yes" ; then echo "TCG debug enabled $debug_tcg" echo "TCG interpreter $tcg_interpreter" + echo "TCG CET support $cet_tcg" fi echo "malloc trim support $malloc_trim" echo "RDMA support $rdma" @@ -6495,6 +6501,9 @@ fi if test "$cet" = "yes" ; then echo "CONFIG_CET=y" >> $config_host_mak fi +if test "$cet_tcg" = "yes" ; then + echo "CONFIG_CET_TCG=y" >> $config_host_mak +fi if test "$slirp" != "no"; then echo "CONFIG_SLIRP=y" >> $config_host_mak echo "CONFIG_SMBD_COMMAND=\"$smbd\"" >> $config_host_mak diff --git a/tcg/i386/tcg-target.inc.c b/tcg/i386/tcg-target.inc.c index 781b1faec2..4d1f80c1b2 100644 --- a/tcg/i386/tcg-target.inc.c +++ b/tcg/i386/tcg-target.inc.c @@ -808,6 +808,17 @@ static inline void tgen_arithr(TCGContext *s, int subop, int dest, int src) tcg_out_modrm(s, OPC_ARITH_GvEv + (subop << 3) + ext, dest, src); } +static void tcg_out_endbr(TCGContext *s) +{ +#if defined __CET__ && (__CET__ & 1) +#ifdef __x86_64__ + tcg_out32(s, 0xfa1e0ff3); +#else + tcg_out32(s, 0xfb1e0ff3); +#endif +#endif +} + static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) { int rexw = 0; @@ -3499,6 +3510,7 @@ static const int tcg_target_callee_save_regs[] = { static inline void tcg_out_start(TCGContext *s) { + tcg_out_endbr(s); } /* Generate global QEMU prologue and epilogue code */ @@ -3514,6 +3526,7 @@ static void tcg_target_qemu_prologue(TCGContext *s) CPU_TEMP_BUF_NLONGS * sizeof(long)); /* Save all callee saved registers. */ + tcg_out_endbr(s); for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) { tcg_out_push(s, tcg_target_callee_save_regs[i]); } @@ -3553,6 +3566,7 @@ static void tcg_target_qemu_prologue(TCGContext *s) * and fall through to the rest of the epilogue. */ s->code_gen_epilogue = s->code_ptr; + tcg_out_endbr(s); tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_EAX, 0); /* TB epilogue */
Add endbr annotations before indirect branch targets. This lets QEMU enable IBT even for TCG-enabled builds. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- Makefile.target | 2 ++ configure | 9 +++++++++ tcg/i386/tcg-target.inc.c | 14 ++++++++++++++ 3 files changed, 25 insertions(+)