Skip to content
2 changes: 2 additions & 0 deletions qemu/aarch64.h
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,7 @@
#define helper_gvec_umax64 helper_gvec_umax64_aarch64
#define helper_gvec_bitsel helper_gvec_bitsel_aarch64
#define cpu_restore_state cpu_restore_state_aarch64
#define cpu_restore_pc_only cpu_restore_pc_only_aarch64
#define page_collection_lock page_collection_lock_aarch64
#define page_collection_unlock page_collection_unlock_aarch64
#define free_code_gen_buffer free_code_gen_buffer_aarch64
Expand Down Expand Up @@ -2770,6 +2771,7 @@
#define gen_sshl_i64 gen_sshl_i64_aarch64
#define gen_intermediate_code gen_intermediate_code_aarch64
#define restore_state_to_opc restore_state_to_opc_aarch64
#define restore_pc_to_opc restore_pc_to_opc_aarch64
#define disas_sve disas_sve_aarch64
#define helper_neon_qrdmlah_s16 helper_neon_qrdmlah_s16_aarch64
#define helper_gvec_qrdmlah_s16 helper_gvec_qrdmlah_s16_aarch64
Expand Down
24 changes: 15 additions & 9 deletions qemu/accel/tcg/cputlb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1033,6 +1033,9 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
cpu_io_recompile(cpu, retaddr);
}

/* Restore the guest CPU state to ensure the PC is synced */
cpu_restore_pc_only(uc->cpu, retaddr, false);

r = memory_region_dispatch_read(uc, mr, mr_offset, &val, op, iotlbentry->attrs);
if (r != MEMTX_OK) {
#if 0
Expand Down Expand Up @@ -1067,6 +1070,9 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
}
cpu->mem_io_pc = retaddr;

/* Restore the guest CPU state to ensure the PC is synced */
cpu_restore_pc_only(uc->cpu, retaddr, false);

r = memory_region_dispatch_write(uc, mr, mr_offset, val, op, iotlbentry->attrs);
if (r != MEMTX_OK) {
#if 0
Expand Down Expand Up @@ -1569,7 +1575,7 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
if (!HOOK_BOUND_CHECK(hook, paddr))
continue;
if (!synced && !uc->skip_sync_pc_on_exit && retaddr) {
cpu_restore_state(uc->cpu, retaddr, false);
cpu_restore_pc_only(uc->cpu, retaddr, false);
synced = true;
}
JIT_CALLBACK_GUARD_VAR(handled,
Expand All @@ -1590,7 +1596,7 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
if (!HOOK_BOUND_CHECK(hook, paddr))
continue;
if (!synced &&!uc->skip_sync_pc_on_exit && retaddr) {
cpu_restore_state(uc->cpu, retaddr, false);
cpu_restore_pc_only(uc->cpu, retaddr, false);
synced = true;
}
JIT_CALLBACK_GUARD_VAR(handled,
Expand Down Expand Up @@ -1658,7 +1664,7 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
if (!HOOK_BOUND_CHECK(hook, paddr))
continue;
if (!synced && !uc->skip_sync_pc_on_exit && retaddr) {
cpu_restore_state(uc->cpu, retaddr, false);
cpu_restore_pc_only(uc->cpu, retaddr, false);
synced = true;
}
JIT_CALLBACK_GUARD(((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ, paddr, size, 0, hook->user_data));
Expand Down Expand Up @@ -1690,7 +1696,7 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
if (!HOOK_BOUND_CHECK(hook, paddr))
continue;
if (!synced && !uc->skip_sync_pc_on_exit && retaddr) {
cpu_restore_state(uc->cpu, retaddr, false);
cpu_restore_pc_only(uc->cpu, retaddr, false);
synced = true;
}
JIT_CALLBACK_GUARD_VAR(handled,
Expand Down Expand Up @@ -1740,7 +1746,7 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
if (!HOOK_BOUND_CHECK(hook, paddr))
continue;
if (!synced && !uc->skip_sync_pc_on_exit && retaddr) {
cpu_restore_state(uc->cpu, retaddr, false);
cpu_restore_pc_only(uc->cpu, retaddr, false);
synced = true;
}
JIT_CALLBACK_GUARD_VAR(handled,
Expand Down Expand Up @@ -1854,7 +1860,7 @@ load_helper(CPUArchState *env, target_ulong addr, TCGMemOpIdx oi,
if (!HOOK_BOUND_CHECK(hook, paddr))
continue;
if (!synced && !uc->skip_sync_pc_on_exit && retaddr) {
cpu_restore_state(uc->cpu, retaddr, false);
cpu_restore_pc_only(uc->cpu, retaddr, false);
synced = true;
}
JIT_CALLBACK_GUARD(((uc_cb_hookmem_t)hook->callback)(env->uc, UC_MEM_READ_AFTER, paddr, size, res, hook->user_data));
Expand Down Expand Up @@ -2202,7 +2208,7 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
if (!HOOK_BOUND_CHECK(hook, paddr))
continue;
if (!synced && !uc->skip_sync_pc_on_exit && retaddr) {
cpu_restore_state(uc->cpu, retaddr, false);
cpu_restore_pc_only(uc->cpu, retaddr, false);
synced = true;
}
JIT_CALLBACK_GUARD(((uc_cb_hookmem_t)hook->callback)(uc, UC_MEM_WRITE, paddr, size, val, hook->user_data));
Expand All @@ -2221,7 +2227,7 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
if (!HOOK_BOUND_CHECK(hook, paddr))
continue;
if (!synced && !uc->skip_sync_pc_on_exit && retaddr) {
cpu_restore_state(uc->cpu, retaddr, false);
cpu_restore_pc_only(uc->cpu, retaddr, false);
synced = true;
}
JIT_CALLBACK_GUARD_VAR(handled,
Expand Down Expand Up @@ -2274,7 +2280,7 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val,
if (!HOOK_BOUND_CHECK(hook, paddr))
continue;
if (!synced && !uc->skip_sync_pc_on_exit && retaddr) {
cpu_restore_state(uc->cpu, retaddr, false);
cpu_restore_pc_only(uc->cpu, retaddr, false);
synced = true;
}
JIT_CALLBACK_GUARD_VAR(handled,
Expand Down
78 changes: 78 additions & 0 deletions qemu/accel/tcg/translate-all.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,84 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
return 0;
}

static int cpu_restore_pc_from_tb(CPUState *cpu, TranslationBlock *tb,
uintptr_t searched_pc, bool reset_icount)
{
target_ulong data[TARGET_INSN_START_WORDS] = { tb->pc };
uintptr_t host_pc = (uintptr_t)tb->tc.ptr;
CPUArchState *env = cpu->env_ptr;
uint8_t *p = (uint8_t *)tb->tc.ptr + tb->tc.size;
int i, j, num_insns = tb->icount;

searched_pc -= GETPC_ADJ;

if (searched_pc < host_pc) {
return -1;
}

/* Reconstruct the stored insn data while looking for the point at
which the end of the insn exceeds the searched_pc. */
for (i = 0; i < num_insns; ++i) {
for (j = 0; j < TARGET_INSN_START_WORDS; ++j) {
data[j] += decode_sleb128(&p);
}
host_pc += decode_sleb128(&p);
if (host_pc > searched_pc) {
goto found;
}
}
return -1;

found:
if (reset_icount && (tb_cflags(tb) & CF_USE_ICOUNT)) {
/* Reset the cycle counter to the start of the block
and shift if to the number of actually executed instructions */
cpu_neg(cpu)->icount_decr.u16.low += num_insns - i;
}
restore_pc_to_opc(env, tb, data);

return 0;
}

bool cpu_restore_pc_only(CPUState *cpu, uintptr_t host_pc, bool will_exit)
{
TCGContext *tcg_ctx = cpu->uc->tcg_ctx;
TranslationBlock *tb;
bool r = false;
uintptr_t check_offset;
struct uc_struct *uc = cpu->uc;

/* The host_pc has to be in the region of current code buffer. If
* it is not we will not be able to resolve it here. The two cases
* where host_pc will not be correct are:
*
* - fault during translation (instruction fetch)
* - fault from helper (not using GETPC() macro)
*
* Either way we need return early as we can't resolve it here.
*
* We are using unsigned arithmetic so if host_pc <
* tcg_init_ctx.code_gen_buffer check_offset will wrap to way
* above the code_gen_buffer_size
*/
check_offset = host_pc - (uintptr_t) uc->tcg_ctx->code_gen_buffer;

if (check_offset < uc->tcg_ctx->code_gen_buffer_size) {
tb = tcg_tb_lookup(tcg_ctx, host_pc);
if (tb) {
cpu_restore_pc_from_tb(cpu, tb, host_pc, will_exit);
if (tb_cflags(tb) & CF_NOCACHE) {
/* one-shot translation, invalidate it immediately */
tb_phys_invalidate(tcg_ctx, tb, -1);
tcg_tb_remove(tcg_ctx, tb);
}
r = true;
}
}

return r;
}

bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc, bool will_exit)
{
TCGContext *tcg_ctx = cpu->uc->tcg_ctx;
Expand Down
2 changes: 2 additions & 0 deletions qemu/arm.h
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,7 @@
#define helper_gvec_umax64 helper_gvec_umax64_arm
#define helper_gvec_bitsel helper_gvec_bitsel_arm
#define cpu_restore_state cpu_restore_state_arm
#define cpu_restore_pc_only cpu_restore_pc_only_arm
#define page_collection_lock page_collection_lock_arm
#define page_collection_unlock page_collection_unlock_arm
#define free_code_gen_buffer free_code_gen_buffer_arm
Expand Down Expand Up @@ -1789,6 +1790,7 @@
#define gen_sshl_i64 gen_sshl_i64_arm
#define gen_intermediate_code gen_intermediate_code_arm
#define restore_state_to_opc restore_state_to_opc_arm
#define restore_pc_to_opc restore_pc_to_opc_arm
#define helper_neon_qrdmlah_s16 helper_neon_qrdmlah_s16_arm
#define helper_gvec_qrdmlah_s16 helper_gvec_qrdmlah_s16_arm
#define helper_neon_qrdmlsh_s16 helper_neon_qrdmlsh_s16_arm
Expand Down
4 changes: 4 additions & 0 deletions qemu/include/exec/exec-all.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns);
void restore_state_to_opc(CPUArchState *env, TranslationBlock *tb,
target_ulong *data);

void restore_pc_to_opc(CPUArchState *env, TranslationBlock *tb,
target_ulong *data);
bool cpu_restore_pc_only(CPUState *cpu, uintptr_t host_pc, bool will_exit);

/**
* cpu_restore_state:
* @cpu: the vCPU state is to be restore to
Expand Down
2 changes: 2 additions & 0 deletions qemu/m68k.h
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,7 @@
#define helper_gvec_umax64 helper_gvec_umax64_m68k
#define helper_gvec_bitsel helper_gvec_bitsel_m68k
#define cpu_restore_state cpu_restore_state_m68k
#define cpu_restore_pc_only cpu_restore_pc_only_m68k
#define page_collection_lock page_collection_lock_m68k
#define page_collection_unlock page_collection_unlock_m68k
#define free_code_gen_buffer free_code_gen_buffer_m68k
Expand Down Expand Up @@ -1450,4 +1451,5 @@
#define register_m68k_insns register_m68k_insns_m68k
#define gen_intermediate_code gen_intermediate_code_m68k
#define restore_state_to_opc restore_state_to_opc_m68k
#define restore_pc_to_opc restore_pc_to_opc_m68k
#endif
2 changes: 2 additions & 0 deletions qemu/mips.h
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,7 @@
#define helper_gvec_umax64 helper_gvec_umax64_mips
#define helper_gvec_bitsel helper_gvec_bitsel_mips
#define cpu_restore_state cpu_restore_state_mips
#define cpu_restore_pc_only cpu_restore_pc_only_mips
#define page_collection_lock page_collection_lock_mips
#define page_collection_unlock page_collection_unlock_mips
#define free_code_gen_buffer free_code_gen_buffer_mips
Expand Down Expand Up @@ -2401,6 +2402,7 @@
#define cpu_mips_realize_env cpu_mips_realize_env_mips
#define cpu_state_reset cpu_state_reset_mips
#define restore_state_to_opc restore_state_to_opc_mips
#define restore_pc_to_opc restore_pc_to_opc_mips
#define ieee_rm ieee_rm_mips
#define mips_defs mips_defs_mips
#define mips_defs_number mips_defs_number_mips
Expand Down
2 changes: 2 additions & 0 deletions qemu/mips64.h
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,7 @@
#define helper_gvec_umax64 helper_gvec_umax64_mips64
#define helper_gvec_bitsel helper_gvec_bitsel_mips64
#define cpu_restore_state cpu_restore_state_mips64
#define cpu_restore_pc_only cpu_restore_pc_only_mips64
#define page_collection_lock page_collection_lock_mips64
#define page_collection_unlock page_collection_unlock_mips64
#define free_code_gen_buffer free_code_gen_buffer_mips64
Expand Down Expand Up @@ -2401,6 +2402,7 @@
#define cpu_mips_realize_env cpu_mips_realize_env_mips64
#define cpu_state_reset cpu_state_reset_mips64
#define restore_state_to_opc restore_state_to_opc_mips64
#define restore_pc_to_opc restore_pc_to_opc_mips64
#define ieee_rm ieee_rm_mips64
#define mips_defs mips_defs_mips64
#define mips_defs_number mips_defs_number_mips64
Expand Down
2 changes: 2 additions & 0 deletions qemu/mips64el.h
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,7 @@
#define helper_gvec_umax64 helper_gvec_umax64_mips64el
#define helper_gvec_bitsel helper_gvec_bitsel_mips64el
#define cpu_restore_state cpu_restore_state_mips64el
#define cpu_restore_pc_only cpu_restore_pc_only_mips64el
#define page_collection_lock page_collection_lock_mips64el
#define page_collection_unlock page_collection_unlock_mips64el
#define free_code_gen_buffer free_code_gen_buffer_mips64el
Expand Down Expand Up @@ -2401,6 +2402,7 @@
#define cpu_mips_realize_env cpu_mips_realize_env_mips64el
#define cpu_state_reset cpu_state_reset_mips64el
#define restore_state_to_opc restore_state_to_opc_mips64el
#define restore_pc_to_opc restore_pc_to_opc_mips64el
#define ieee_rm ieee_rm_mips64el
#define mips_defs mips_defs_mips64el
#define mips_defs_number mips_defs_number_mips64el
Expand Down
2 changes: 2 additions & 0 deletions qemu/mipsel.h
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,7 @@
#define helper_gvec_umax64 helper_gvec_umax64_mipsel
#define helper_gvec_bitsel helper_gvec_bitsel_mipsel
#define cpu_restore_state cpu_restore_state_mipsel
#define cpu_restore_pc_only cpu_restore_pc_only_mipsel
#define page_collection_lock page_collection_lock_mipsel
#define page_collection_unlock page_collection_unlock_mipsel
#define free_code_gen_buffer free_code_gen_buffer_mipsel
Expand Down Expand Up @@ -2401,6 +2402,7 @@
#define cpu_mips_realize_env cpu_mips_realize_env_mipsel
#define cpu_state_reset cpu_state_reset_mipsel
#define restore_state_to_opc restore_state_to_opc_mipsel
#define restore_pc_to_opc restore_pc_to_opc_mipsel
#define ieee_rm ieee_rm_mipsel
#define mips_defs mips_defs_mipsel
#define mips_defs_number mips_defs_number_mipsel
Expand Down
2 changes: 2 additions & 0 deletions qemu/ppc.h
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,7 @@
#define helper_gvec_umax64 helper_gvec_umax64_ppc
#define helper_gvec_bitsel helper_gvec_bitsel_ppc
#define cpu_restore_state cpu_restore_state_ppc
#define cpu_restore_pc_only cpu_restore_pc_only_ppc
#define page_collection_lock page_collection_lock_ppc
#define page_collection_unlock page_collection_unlock_ppc
#define free_code_gen_buffer free_code_gen_buffer_ppc
Expand Down Expand Up @@ -1680,6 +1681,7 @@
#define cpu_ppc_init cpu_ppc_init_ppc
#define gen_intermediate_code gen_intermediate_code_ppc
#define restore_state_to_opc restore_state_to_opc_ppc
#define restore_pc_to_opc restore_pc_to_opc_ppc
#define ppc_set_irq ppc_set_irq_ppc
#define ppc6xx_irq_init ppc6xx_irq_init_ppc
#define ppc40x_core_reset ppc40x_core_reset_ppc
Expand Down
2 changes: 2 additions & 0 deletions qemu/ppc64.h
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,7 @@
#define helper_gvec_umax64 helper_gvec_umax64_ppc64
#define helper_gvec_bitsel helper_gvec_bitsel_ppc64
#define cpu_restore_state cpu_restore_state_ppc64
#define cpu_restore_pc_only cpu_restore_pc_only_ppc64
#define page_collection_lock page_collection_lock_ppc64
#define page_collection_unlock page_collection_unlock_ppc64
#define free_code_gen_buffer free_code_gen_buffer_ppc64
Expand Down Expand Up @@ -1680,6 +1681,7 @@
#define cpu_ppc_init cpu_ppc_init_ppc64
#define gen_intermediate_code gen_intermediate_code_ppc64
#define restore_state_to_opc restore_state_to_opc_ppc64
#define restore_pc_to_opc restore_pc_to_opc_ppc64
#define ppc_set_irq ppc_set_irq_ppc64
#define ppc6xx_irq_init ppc6xx_irq_init_ppc64
#define ppc40x_core_reset ppc40x_core_reset_ppc64
Expand Down
2 changes: 2 additions & 0 deletions qemu/riscv32.h
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,7 @@
#define helper_gvec_umax64 helper_gvec_umax64_riscv32
#define helper_gvec_bitsel helper_gvec_bitsel_riscv32
#define cpu_restore_state cpu_restore_state_riscv32
#define cpu_restore_pc_only cpu_restore_pc_only_riscv32
#define page_collection_lock page_collection_lock_riscv32
#define page_collection_unlock page_collection_unlock_riscv32
#define free_code_gen_buffer free_code_gen_buffer_riscv32
Expand Down Expand Up @@ -1376,6 +1377,7 @@
#define gen_intermediate_code gen_intermediate_code_riscv32
#define riscv_translate_init riscv_translate_init_riscv32
#define restore_state_to_opc restore_state_to_opc_riscv32
#define restore_pc_to_opc restore_pc_to_opc_riscv32
#define cpu_riscv_init cpu_riscv_init_riscv32
#define helper_fcvt_l_s helper_fcvt_l_s_riscv32
#define helper_fcvt_lu_s helper_fcvt_lu_s_riscv32
Expand Down
2 changes: 2 additions & 0 deletions qemu/riscv64.h
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,7 @@
#define helper_gvec_umax64 helper_gvec_umax64_riscv64
#define helper_gvec_bitsel helper_gvec_bitsel_riscv64
#define cpu_restore_state cpu_restore_state_riscv64
#define cpu_restore_pc_only cpu_restore_pc_only_riscv64
#define page_collection_lock page_collection_lock_riscv64
#define page_collection_unlock page_collection_unlock_riscv64
#define free_code_gen_buffer free_code_gen_buffer_riscv64
Expand Down Expand Up @@ -1376,6 +1377,7 @@
#define gen_intermediate_code gen_intermediate_code_riscv64
#define riscv_translate_init riscv_translate_init_riscv64
#define restore_state_to_opc restore_state_to_opc_riscv64
#define restore_pc_to_opc restore_pc_to_opc_riscv64
#define cpu_riscv_init cpu_riscv_init_riscv64
#define helper_fcvt_l_s helper_fcvt_l_s_riscv64
#define helper_fcvt_lu_s helper_fcvt_lu_s_riscv64
Expand Down
1 change: 1 addition & 0 deletions qemu/s390x.h
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,7 @@
#define helper_gvec_umax64 helper_gvec_umax64_s390x
#define helper_gvec_bitsel helper_gvec_bitsel_s390x
#define cpu_restore_state cpu_restore_state_s390x
#define cpu_restore_pc_only cpu_restore_pc_only_s390x
#define page_collection_lock page_collection_lock_s390x
#define page_collection_unlock page_collection_unlock_s390x
#define free_code_gen_buffer free_code_gen_buffer_s390x
Expand Down
Loading
Loading