Sergey Fedorov <sergey.fedo...@linaro.org> writes: > From: Sergey Fedorov <serge.f...@gmail.com> > > Ensure direct jump patching in TCI is atomic by: > * naturally aligning a location of direct jump address; > * using atomic_read()/atomic_set() to load/store the address. > > Signed-off-by: Sergey Fedorov <serge.f...@gmail.com> > Signed-off-by: Sergey Fedorov <sergey.fedo...@linaro.org> > --- > include/exec/exec-all.h | 2 +- > tcg/tci/tcg-target.inc.c | 2 ++ > tci.c | 5 ++++- > 3 files changed, 7 insertions(+), 2 deletions(-) > > diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h > index 736209505a68..59709c9dd5c9 100644 > --- a/include/exec/exec-all.h > +++ b/include/exec/exec-all.h > @@ -302,7 +302,7 @@ void tb_phys_invalidate(TranslationBlock *tb, > tb_page_addr_t page_addr); > static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr) > { > /* patch the branch destination */ > - *(uint32_t *)jmp_addr = addr - (jmp_addr + 4); > + atomic_set((int32_t *)jmp_addr, addr - (jmp_addr + 4)); > /* no need to flush icache explicitly */ > } > #elif defined(_ARCH_PPC) > diff --git a/tcg/tci/tcg-target.inc.c b/tcg/tci/tcg-target.inc.c > index 4afe4d7a8d59..7e6180e62898 100644 > --- a/tcg/tci/tcg-target.inc.c > +++ b/tcg/tci/tcg-target.inc.c > @@ -556,6 +556,8 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, > const TCGArg *args, > if (s->tb_jmp_offset) { > /* Direct jump method. */ > assert(args[0] < ARRAY_SIZE(s->tb_jmp_offset)); > + /* Align for atomic patching and thread safety */ > + s->code_ptr = (uint8_t *)(((uintptr_t)s->code_ptr + 3) & > ~3);
Seeing this pattern is being used over and over again I wonder if we should have some utility helper functions for this? Perhaps we should steal the kernels ALIGN macros? > s->tb_jmp_offset[args[0]] = tcg_current_code_size(s); > tcg_out32(s, 0); > } else { > diff --git a/tci.c b/tci.c > index 82705fe77295..531f5ebf2c2e 100644 > --- a/tci.c > +++ b/tci.c > @@ -1089,7 +1089,10 @@ uintptr_t tcg_qemu_tb_exec(CPUArchState *env, uint8_t > *tb_ptr) > goto exit; > break; > case INDEX_op_goto_tb: > - t0 = tci_read_i32(&tb_ptr); > + /* Jump address is aligned */ > + tb_ptr = (uint8_t *)(((uintptr_t)tb_ptr + 3) & ~3); > + t0 = atomic_read((int32_t *)tb_ptr); > + tb_ptr += sizeof(int32_t); > tci_assert(tb_ptr == old_code_ptr + op_size); > tb_ptr += (int32_t)t0; > continue; -- Alex Bennée