diff options
author | Sergey Fedorov <serge.fdrv@gmail.com> | 2016-04-22 19:08:48 +0300 |
---|---|---|
committer | Richard Henderson <rth@twiddle.net> | 2016-05-12 14:06:41 -1000 |
commit | ed3d51ecd7fe248d3959e469d53890ac9ffe0cd2 (patch) | |
tree | 2bb706344e30ab4fddf8a7c2ade4424f9afa1070 | |
parent | 0d07abf05e98903c7faf204a9a90f7d45b7554dc (diff) | |
download | qemu-ed3d51ecd7fe248d3959e469d53890ac9ffe0cd2.zip |
tcg/s390: Make direct jump patching thread-safe
Ensure direct jump patching in s390 is atomic by:
* naturally aligning a location of direct jump address;
* using atomic_read()/atomic_set() for code patching.
Signed-off-by: Sergey Fedorov <serge.fdrv@gmail.com>
Signed-off-by: Sergey Fedorov <sergey.fedorov@linaro.org>
Message-Id: <1461341333-19646-7-git-send-email-sergey.fedorov@linaro.org>
Signed-off-by: Richard Henderson <rth@twiddle.net>
-rw-r--r-- | include/exec/exec-all.h | 2 | ||||
-rw-r--r-- | tcg/s390/tcg-target.inc.c | 8 |
2 files changed, 9 insertions, 1 deletions
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 0ab7803259..6c095e8636 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -321,7 +321,7 @@ static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr) { /* patch the branch destination */ intptr_t disp = addr - (jmp_addr - 2); - stl_be_p((void*)jmp_addr, disp / 2); + atomic_set((int32_t *)jmp_addr, disp / 2); /* no need to flush icache explicitly */ } #elif defined(__aarch64__) diff --git a/tcg/s390/tcg-target.inc.c b/tcg/s390/tcg-target.inc.c index 5805532398..8e8064ce73 100644 --- a/tcg/s390/tcg-target.inc.c +++ b/tcg/s390/tcg-target.inc.c @@ -219,6 +219,8 @@ typedef enum S390Opcode { RX_ST = 0x50, RX_STC = 0x42, RX_STH = 0x40, + + NOP = 0x0707, } S390Opcode; #ifdef CONFIG_DEBUG_TCG @@ -1716,6 +1718,12 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, case INDEX_op_goto_tb: if (s->tb_jmp_offset) { + /* branch displacement must be aligned for atomic patching; + * see if we need to add extra nop before branch + */ + if (!QEMU_PTR_IS_ALIGNED(s->code_ptr + 1, 4)) { + tcg_out16(s, NOP); + } tcg_out16(s, RIL_BRCL | (S390_CC_ALWAYS << 4)); s->tb_jmp_offset[args[0]] = tcg_current_code_size(s); s->code_ptr += 2; |