tcg/aarch64: Support raising sigbus for user-only
Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
b1ee3c6725
commit
f85ab3d2e5
@ -10,6 +10,7 @@
|
|||||||
* See the COPYING file in the top-level directory for details.
|
* See the COPYING file in the top-level directory for details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "../tcg-ldst.c.inc"
|
||||||
#include "../tcg-pool.c.inc"
|
#include "../tcg-pool.c.inc"
|
||||||
#include "qemu/bitops.h"
|
#include "qemu/bitops.h"
|
||||||
|
|
||||||
@ -443,6 +444,7 @@ typedef enum {
|
|||||||
I3404_ANDI = 0x12000000,
|
I3404_ANDI = 0x12000000,
|
||||||
I3404_ORRI = 0x32000000,
|
I3404_ORRI = 0x32000000,
|
||||||
I3404_EORI = 0x52000000,
|
I3404_EORI = 0x52000000,
|
||||||
|
I3404_ANDSI = 0x72000000,
|
||||||
|
|
||||||
/* Move wide immediate instructions. */
|
/* Move wide immediate instructions. */
|
||||||
I3405_MOVN = 0x12800000,
|
I3405_MOVN = 0x12800000,
|
||||||
@ -1328,8 +1330,9 @@ static void tcg_out_goto_long(TCGContext *s, const tcg_insn_unit *target)
|
|||||||
if (offset == sextract64(offset, 0, 26)) {
|
if (offset == sextract64(offset, 0, 26)) {
|
||||||
tcg_out_insn(s, 3206, B, offset);
|
tcg_out_insn(s, 3206, B, offset);
|
||||||
} else {
|
} else {
|
||||||
tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, (intptr_t)target);
|
/* Choose X9 as a call-clobbered non-LR temporary. */
|
||||||
tcg_out_insn(s, 3207, BR, TCG_REG_TMP);
|
tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X9, (intptr_t)target);
|
||||||
|
tcg_out_insn(s, 3207, BR, TCG_REG_X9);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1541,9 +1544,14 @@ static void tcg_out_cltz(TCGContext *s, TCGType ext, TCGReg d,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_SOFTMMU
|
static void tcg_out_adr(TCGContext *s, TCGReg rd, const void *target)
|
||||||
#include "../tcg-ldst.c.inc"
|
{
|
||||||
|
ptrdiff_t offset = tcg_pcrel_diff(s, target);
|
||||||
|
tcg_debug_assert(offset == sextract64(offset, 0, 21));
|
||||||
|
tcg_out_insn(s, 3406, ADR, rd, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_SOFTMMU
|
||||||
/* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
|
/* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
|
||||||
* MemOpIdx oi, uintptr_t ra)
|
* MemOpIdx oi, uintptr_t ra)
|
||||||
*/
|
*/
|
||||||
@ -1577,13 +1585,6 @@ static void * const qemu_st_helpers[MO_SIZE + 1] = {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void tcg_out_adr(TCGContext *s, TCGReg rd, const void *target)
|
|
||||||
{
|
|
||||||
ptrdiff_t offset = tcg_pcrel_diff(s, target);
|
|
||||||
tcg_debug_assert(offset == sextract64(offset, 0, 21));
|
|
||||||
tcg_out_insn(s, 3406, ADR, rd, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
|
static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
|
||||||
{
|
{
|
||||||
MemOpIdx oi = lb->oi;
|
MemOpIdx oi = lb->oi;
|
||||||
@ -1714,15 +1715,58 @@ static void tcg_out_tlb_read(TCGContext *s, TCGReg addr_reg, MemOp opc,
|
|||||||
tcg_out_insn(s, 3202, B_C, TCG_COND_NE, 0);
|
tcg_out_insn(s, 3202, B_C, TCG_COND_NE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
static void tcg_out_test_alignment(TCGContext *s, bool is_ld, TCGReg addr_reg,
|
||||||
|
unsigned a_bits)
|
||||||
|
{
|
||||||
|
unsigned a_mask = (1 << a_bits) - 1;
|
||||||
|
TCGLabelQemuLdst *label = new_ldst_label(s);
|
||||||
|
|
||||||
|
label->is_ld = is_ld;
|
||||||
|
label->addrlo_reg = addr_reg;
|
||||||
|
|
||||||
|
/* tst addr, #mask */
|
||||||
|
tcg_out_logicali(s, I3404_ANDSI, 0, TCG_REG_XZR, addr_reg, a_mask);
|
||||||
|
|
||||||
|
label->label_ptr[0] = s->code_ptr;
|
||||||
|
|
||||||
|
/* b.ne slow_path */
|
||||||
|
tcg_out_insn(s, 3202, B_C, TCG_COND_NE, 0);
|
||||||
|
|
||||||
|
label->raddr = tcg_splitwx_to_rx(s->code_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tcg_out_fail_alignment(TCGContext *s, TCGLabelQemuLdst *l)
|
||||||
|
{
|
||||||
|
if (!reloc_pc19(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tcg_out_mov(s, TCG_TYPE_TL, TCG_REG_X1, l->addrlo_reg);
|
||||||
|
tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_X0, TCG_AREG0);
|
||||||
|
|
||||||
|
/* "Tail call" to the helper, with the return address back inline. */
|
||||||
|
tcg_out_adr(s, TCG_REG_LR, l->raddr);
|
||||||
|
tcg_out_goto_long(s, (const void *)(l->is_ld ? helper_unaligned_ld
|
||||||
|
: helper_unaligned_st));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
|
||||||
|
{
|
||||||
|
return tcg_out_fail_alignment(s, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
|
||||||
|
{
|
||||||
|
return tcg_out_fail_alignment(s, l);
|
||||||
|
}
|
||||||
#endif /* CONFIG_SOFTMMU */
|
#endif /* CONFIG_SOFTMMU */
|
||||||
|
|
||||||
static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp memop, TCGType ext,
|
static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp memop, TCGType ext,
|
||||||
TCGReg data_r, TCGReg addr_r,
|
TCGReg data_r, TCGReg addr_r,
|
||||||
TCGType otype, TCGReg off_r)
|
TCGType otype, TCGReg off_r)
|
||||||
{
|
{
|
||||||
/* Byte swapping is left to middle-end expansion. */
|
|
||||||
tcg_debug_assert((memop & MO_BSWAP) == 0);
|
|
||||||
|
|
||||||
switch (memop & MO_SSIZE) {
|
switch (memop & MO_SSIZE) {
|
||||||
case MO_UB:
|
case MO_UB:
|
||||||
tcg_out_ldst_r(s, I3312_LDRB, data_r, addr_r, otype, off_r);
|
tcg_out_ldst_r(s, I3312_LDRB, data_r, addr_r, otype, off_r);
|
||||||
@ -1756,9 +1800,6 @@ static void tcg_out_qemu_st_direct(TCGContext *s, MemOp memop,
|
|||||||
TCGReg data_r, TCGReg addr_r,
|
TCGReg data_r, TCGReg addr_r,
|
||||||
TCGType otype, TCGReg off_r)
|
TCGType otype, TCGReg off_r)
|
||||||
{
|
{
|
||||||
/* Byte swapping is left to middle-end expansion. */
|
|
||||||
tcg_debug_assert((memop & MO_BSWAP) == 0);
|
|
||||||
|
|
||||||
switch (memop & MO_SIZE) {
|
switch (memop & MO_SIZE) {
|
||||||
case MO_8:
|
case MO_8:
|
||||||
tcg_out_ldst_r(s, I3312_STRB, data_r, addr_r, otype, off_r);
|
tcg_out_ldst_r(s, I3312_STRB, data_r, addr_r, otype, off_r);
|
||||||
@ -1782,6 +1823,10 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
|
|||||||
{
|
{
|
||||||
MemOp memop = get_memop(oi);
|
MemOp memop = get_memop(oi);
|
||||||
const TCGType otype = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
|
const TCGType otype = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
|
||||||
|
|
||||||
|
/* Byte swapping is left to middle-end expansion. */
|
||||||
|
tcg_debug_assert((memop & MO_BSWAP) == 0);
|
||||||
|
|
||||||
#ifdef CONFIG_SOFTMMU
|
#ifdef CONFIG_SOFTMMU
|
||||||
unsigned mem_index = get_mmuidx(oi);
|
unsigned mem_index = get_mmuidx(oi);
|
||||||
tcg_insn_unit *label_ptr;
|
tcg_insn_unit *label_ptr;
|
||||||
@ -1792,6 +1837,10 @@ static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
|
|||||||
add_qemu_ldst_label(s, true, oi, ext, data_reg, addr_reg,
|
add_qemu_ldst_label(s, true, oi, ext, data_reg, addr_reg,
|
||||||
s->code_ptr, label_ptr);
|
s->code_ptr, label_ptr);
|
||||||
#else /* !CONFIG_SOFTMMU */
|
#else /* !CONFIG_SOFTMMU */
|
||||||
|
unsigned a_bits = get_alignment_bits(memop);
|
||||||
|
if (a_bits) {
|
||||||
|
tcg_out_test_alignment(s, true, addr_reg, a_bits);
|
||||||
|
}
|
||||||
if (USE_GUEST_BASE) {
|
if (USE_GUEST_BASE) {
|
||||||
tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
|
tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
|
||||||
TCG_REG_GUEST_BASE, otype, addr_reg);
|
TCG_REG_GUEST_BASE, otype, addr_reg);
|
||||||
@ -1807,6 +1856,10 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
|
|||||||
{
|
{
|
||||||
MemOp memop = get_memop(oi);
|
MemOp memop = get_memop(oi);
|
||||||
const TCGType otype = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
|
const TCGType otype = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
|
||||||
|
|
||||||
|
/* Byte swapping is left to middle-end expansion. */
|
||||||
|
tcg_debug_assert((memop & MO_BSWAP) == 0);
|
||||||
|
|
||||||
#ifdef CONFIG_SOFTMMU
|
#ifdef CONFIG_SOFTMMU
|
||||||
unsigned mem_index = get_mmuidx(oi);
|
unsigned mem_index = get_mmuidx(oi);
|
||||||
tcg_insn_unit *label_ptr;
|
tcg_insn_unit *label_ptr;
|
||||||
@ -1817,6 +1870,10 @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
|
|||||||
add_qemu_ldst_label(s, false, oi, (memop & MO_SIZE)== MO_64,
|
add_qemu_ldst_label(s, false, oi, (memop & MO_SIZE)== MO_64,
|
||||||
data_reg, addr_reg, s->code_ptr, label_ptr);
|
data_reg, addr_reg, s->code_ptr, label_ptr);
|
||||||
#else /* !CONFIG_SOFTMMU */
|
#else /* !CONFIG_SOFTMMU */
|
||||||
|
unsigned a_bits = get_alignment_bits(memop);
|
||||||
|
if (a_bits) {
|
||||||
|
tcg_out_test_alignment(s, false, addr_reg, a_bits);
|
||||||
|
}
|
||||||
if (USE_GUEST_BASE) {
|
if (USE_GUEST_BASE) {
|
||||||
tcg_out_qemu_st_direct(s, memop, data_reg,
|
tcg_out_qemu_st_direct(s, memop, data_reg,
|
||||||
TCG_REG_GUEST_BASE, otype, addr_reg);
|
TCG_REG_GUEST_BASE, otype, addr_reg);
|
||||||
|
@ -151,9 +151,7 @@ typedef enum {
|
|||||||
|
|
||||||
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
|
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
|
||||||
|
|
||||||
#ifdef CONFIG_SOFTMMU
|
|
||||||
#define TCG_TARGET_NEED_LDST_LABELS
|
#define TCG_TARGET_NEED_LDST_LABELS
|
||||||
#endif
|
|
||||||
#define TCG_TARGET_NEED_POOL_LABELS
|
#define TCG_TARGET_NEED_POOL_LABELS
|
||||||
|
|
||||||
#endif /* AARCH64_TCG_TARGET_H */
|
#endif /* AARCH64_TCG_TARGET_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user