aboutsummaryrefslogtreecommitdiff
path: root/accel/tcg/user-exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'accel/tcg/user-exec.c')
-rw-r--r--accel/tcg/user-exec.c347
1 files changed, 138 insertions, 209 deletions
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
index 65d3c9b286..e6bb29b42d 100644
--- a/accel/tcg/user-exec.c
+++ b/accel/tcg/user-exec.c
@@ -886,300 +886,227 @@ int cpu_signal_handler(int host_signum, void *pinfo,
/* The softmmu versions of these helpers are in cputlb.c. */
-uint32_t cpu_ldub_data(CPUArchState *env, abi_ptr ptr)
-{
- MemOpIdx oi = make_memop_idx(MO_UB, MMU_USER_IDX);
- uint32_t ret;
-
- trace_guest_ld_before_exec(env_cpu(env), ptr, oi);
- ret = ldub_p(g2h(env_cpu(env), ptr));
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_R);
- return ret;
-}
-
-int cpu_ldsb_data(CPUArchState *env, abi_ptr ptr)
-{
- return (int8_t)cpu_ldub_data(env, ptr);
-}
-
-uint32_t cpu_lduw_be_data(CPUArchState *env, abi_ptr ptr)
-{
- MemOpIdx oi = make_memop_idx(MO_BEUW, MMU_USER_IDX);
- uint32_t ret;
-
- trace_guest_ld_before_exec(env_cpu(env), ptr, oi);
- ret = lduw_be_p(g2h(env_cpu(env), ptr));
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_R);
- return ret;
-}
-
-int cpu_ldsw_be_data(CPUArchState *env, abi_ptr ptr)
-{
- return (int16_t)cpu_lduw_be_data(env, ptr);
-}
-
-uint32_t cpu_ldl_be_data(CPUArchState *env, abi_ptr ptr)
-{
- MemOpIdx oi = make_memop_idx(MO_BEUL, MMU_USER_IDX);
- uint32_t ret;
-
- trace_guest_ld_before_exec(env_cpu(env), ptr, oi);
- ret = ldl_be_p(g2h(env_cpu(env), ptr));
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_R);
- return ret;
-}
-
-uint64_t cpu_ldq_be_data(CPUArchState *env, abi_ptr ptr)
-{
- MemOpIdx oi = make_memop_idx(MO_BEQ, MMU_USER_IDX);
- uint64_t ret;
-
- trace_guest_ld_before_exec(env_cpu(env), ptr, oi);
- ret = ldq_be_p(g2h(env_cpu(env), ptr));
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_R);
- return ret;
-}
-
-uint32_t cpu_lduw_le_data(CPUArchState *env, abi_ptr ptr)
-{
- MemOpIdx oi = make_memop_idx(MO_LEUW, MMU_USER_IDX);
- uint32_t ret;
-
- trace_guest_ld_before_exec(env_cpu(env), ptr, oi);
- ret = lduw_le_p(g2h(env_cpu(env), ptr));
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_R);
- return ret;
-}
-
-int cpu_ldsw_le_data(CPUArchState *env, abi_ptr ptr)
+/*
+ * Verify that we have passed the correct MemOp to the correct function.
+ *
+ * We could present one function to target code, and dispatch based on
+ * the MemOp, but so far we have worked hard to avoid an indirect function
+ * call along the memory path.
+ */
+static void validate_memop(MemOpIdx oi, MemOp expected)
{
- return (int16_t)cpu_lduw_le_data(env, ptr);
+#ifdef CONFIG_DEBUG_TCG
+ MemOp have = get_memop(oi) & (MO_SIZE | MO_BSWAP);
+ assert(have == expected);
+#endif
}
-uint32_t cpu_ldl_le_data(CPUArchState *env, abi_ptr ptr)
+static void *cpu_mmu_lookup(CPUArchState *env, target_ulong addr,
+ MemOpIdx oi, uintptr_t ra, MMUAccessType type)
{
- MemOpIdx oi = make_memop_idx(MO_LEUL, MMU_USER_IDX);
- uint32_t ret;
-
- trace_guest_ld_before_exec(env_cpu(env), ptr, oi);
- ret = ldl_le_p(g2h(env_cpu(env), ptr));
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_R);
- return ret;
-}
+ void *ret;
-uint64_t cpu_ldq_le_data(CPUArchState *env, abi_ptr ptr)
-{
- MemOpIdx oi = make_memop_idx(MO_LEQ, MMU_USER_IDX);
- uint64_t ret;
+ /* TODO: Enforce guest required alignment. */
- trace_guest_ld_before_exec(env_cpu(env), ptr, oi);
- ret = ldq_le_p(g2h(env_cpu(env), ptr));
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_R);
+ ret = g2h(env_cpu(env), addr);
+ set_helper_retaddr(ra);
return ret;
}
-uint32_t cpu_ldub_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
+uint8_t cpu_ldb_mmu(CPUArchState *env, abi_ptr addr,
+ MemOpIdx oi, uintptr_t ra)
{
- uint32_t ret;
+ void *haddr;
+ uint8_t ret;
- set_helper_retaddr(retaddr);
- ret = cpu_ldub_data(env, ptr);
+ validate_memop(oi, MO_UB);
+ trace_guest_ld_before_exec(env_cpu(env), addr, oi);
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
+ ret = ldub_p(haddr);
clear_helper_retaddr();
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
return ret;
}
-int cpu_ldsb_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
-{
- return (int8_t)cpu_ldub_data_ra(env, ptr, retaddr);
-}
-
-uint32_t cpu_lduw_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
+uint16_t cpu_ldw_be_mmu(CPUArchState *env, abi_ptr addr,
+ MemOpIdx oi, uintptr_t ra)
{
- uint32_t ret;
+ void *haddr;
+ uint16_t ret;
- set_helper_retaddr(retaddr);
- ret = cpu_lduw_be_data(env, ptr);
+ validate_memop(oi, MO_BEUW);
+ trace_guest_ld_before_exec(env_cpu(env), addr, oi);
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
+ ret = lduw_be_p(haddr);
clear_helper_retaddr();
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
return ret;
}
-int cpu_ldsw_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
-{
- return (int16_t)cpu_lduw_be_data_ra(env, ptr, retaddr);
-}
-
-uint32_t cpu_ldl_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
+uint32_t cpu_ldl_be_mmu(CPUArchState *env, abi_ptr addr,
+ MemOpIdx oi, uintptr_t ra)
{
+ void *haddr;
uint32_t ret;
- set_helper_retaddr(retaddr);
- ret = cpu_ldl_be_data(env, ptr);
+ validate_memop(oi, MO_BEUL);
+ trace_guest_ld_before_exec(env_cpu(env), addr, oi);
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
+ ret = ldl_be_p(haddr);
clear_helper_retaddr();
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
return ret;
}
-uint64_t cpu_ldq_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
+uint64_t cpu_ldq_be_mmu(CPUArchState *env, abi_ptr addr,
+ MemOpIdx oi, uintptr_t ra)
{
+ void *haddr;
uint64_t ret;
- set_helper_retaddr(retaddr);
- ret = cpu_ldq_be_data(env, ptr);
+ validate_memop(oi, MO_BEQ);
+ trace_guest_ld_before_exec(env_cpu(env), addr, oi);
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
+ ret = ldq_be_p(haddr);
clear_helper_retaddr();
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
return ret;
}
-uint32_t cpu_lduw_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
+uint16_t cpu_ldw_le_mmu(CPUArchState *env, abi_ptr addr,
+ MemOpIdx oi, uintptr_t ra)
{
- uint32_t ret;
+ void *haddr;
+ uint16_t ret;
- set_helper_retaddr(retaddr);
- ret = cpu_lduw_le_data(env, ptr);
+ validate_memop(oi, MO_LEUW);
+ trace_guest_ld_before_exec(env_cpu(env), addr, oi);
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
+ ret = lduw_le_p(haddr);
clear_helper_retaddr();
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
return ret;
}
-int cpu_ldsw_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
-{
- return (int16_t)cpu_lduw_le_data_ra(env, ptr, retaddr);
-}
-
-uint32_t cpu_ldl_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
+uint32_t cpu_ldl_le_mmu(CPUArchState *env, abi_ptr addr,
+ MemOpIdx oi, uintptr_t ra)
{
+ void *haddr;
uint32_t ret;
- set_helper_retaddr(retaddr);
- ret = cpu_ldl_le_data(env, ptr);
+ validate_memop(oi, MO_LEUL);
+ trace_guest_ld_before_exec(env_cpu(env), addr, oi);
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
+ ret = ldl_le_p(haddr);
clear_helper_retaddr();
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
return ret;
}
-uint64_t cpu_ldq_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t retaddr)
+uint64_t cpu_ldq_le_mmu(CPUArchState *env, abi_ptr addr,
+ MemOpIdx oi, uintptr_t ra)
{
+ void *haddr;
uint64_t ret;
- set_helper_retaddr(retaddr);
- ret = cpu_ldq_le_data(env, ptr);
+ validate_memop(oi, MO_LEQ);
+ trace_guest_ld_before_exec(env_cpu(env), addr, oi);
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_LOAD);
+ ret = ldq_le_p(haddr);
clear_helper_retaddr();
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_R);
return ret;
}
-void cpu_stb_data(CPUArchState *env, abi_ptr ptr, uint32_t val)
-{
- MemOpIdx oi = make_memop_idx(MO_UB, MMU_USER_IDX);
-
- trace_guest_st_before_exec(env_cpu(env), ptr, oi);
- stb_p(g2h(env_cpu(env), ptr), val);
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_W);
-}
-
-void cpu_stw_be_data(CPUArchState *env, abi_ptr ptr, uint32_t val)
-{
- MemOpIdx oi = make_memop_idx(MO_BEUW, MMU_USER_IDX);
-
- trace_guest_st_before_exec(env_cpu(env), ptr, oi);
- stw_be_p(g2h(env_cpu(env), ptr), val);
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_W);
-}
-
-void cpu_stl_be_data(CPUArchState *env, abi_ptr ptr, uint32_t val)
-{
- MemOpIdx oi = make_memop_idx(MO_BEUL, MMU_USER_IDX);
-
- trace_guest_st_before_exec(env_cpu(env), ptr, oi);
- stl_be_p(g2h(env_cpu(env), ptr), val);
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_W);
-}
-
-void cpu_stq_be_data(CPUArchState *env, abi_ptr ptr, uint64_t val)
+void cpu_stb_mmu(CPUArchState *env, abi_ptr addr, uint8_t val,
+ MemOpIdx oi, uintptr_t ra)
{
- MemOpIdx oi = make_memop_idx(MO_BEQ, MMU_USER_IDX);
+ void *haddr;
- trace_guest_st_before_exec(env_cpu(env), ptr, oi);
- stq_be_p(g2h(env_cpu(env), ptr), val);
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_W);
+ validate_memop(oi, MO_UB);
+ trace_guest_st_before_exec(env_cpu(env), addr, oi);
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
+ stb_p(haddr, val);
+ clear_helper_retaddr();
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
}
-void cpu_stw_le_data(CPUArchState *env, abi_ptr ptr, uint32_t val)
+void cpu_stw_be_mmu(CPUArchState *env, abi_ptr addr, uint16_t val,
+ MemOpIdx oi, uintptr_t ra)
{
- MemOpIdx oi = make_memop_idx(MO_LEUW, MMU_USER_IDX);
+ void *haddr;
- trace_guest_st_before_exec(env_cpu(env), ptr, oi);
- stw_le_p(g2h(env_cpu(env), ptr), val);
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_W);
+ validate_memop(oi, MO_BEUW);
+ trace_guest_st_before_exec(env_cpu(env), addr, oi);
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
+ stw_be_p(haddr, val);
+ clear_helper_retaddr();
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
}
-void cpu_stl_le_data(CPUArchState *env, abi_ptr ptr, uint32_t val)
+void cpu_stl_be_mmu(CPUArchState *env, abi_ptr addr, uint32_t val,
+ MemOpIdx oi, uintptr_t ra)
{
- MemOpIdx oi = make_memop_idx(MO_LEUL, MMU_USER_IDX);
+ void *haddr;
- trace_guest_st_before_exec(env_cpu(env), ptr, oi);
- stl_le_p(g2h(env_cpu(env), ptr), val);
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_W);
+ validate_memop(oi, MO_BEUL);
+ trace_guest_st_before_exec(env_cpu(env), addr, oi);
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
+ stl_be_p(haddr, val);
+ clear_helper_retaddr();
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
}
-void cpu_stq_le_data(CPUArchState *env, abi_ptr ptr, uint64_t val)
+void cpu_stq_be_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
+ MemOpIdx oi, uintptr_t ra)
{
- MemOpIdx oi = make_memop_idx(MO_LEQ, MMU_USER_IDX);
-
- trace_guest_st_before_exec(env_cpu(env), ptr, oi);
- stq_le_p(g2h(env_cpu(env), ptr), val);
- qemu_plugin_vcpu_mem_cb(env_cpu(env), ptr, oi, QEMU_PLUGIN_MEM_W);
-}
+ void *haddr;
-void cpu_stb_data_ra(CPUArchState *env, abi_ptr ptr,
- uint32_t val, uintptr_t retaddr)
-{
- set_helper_retaddr(retaddr);
- cpu_stb_data(env, ptr, val);
+ validate_memop(oi, MO_BEQ);
+ trace_guest_st_before_exec(env_cpu(env), addr, oi);
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
+ stq_be_p(haddr, val);
clear_helper_retaddr();
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
}
-void cpu_stw_be_data_ra(CPUArchState *env, abi_ptr ptr,
- uint32_t val, uintptr_t retaddr)
+void cpu_stw_le_mmu(CPUArchState *env, abi_ptr addr, uint16_t val,
+ MemOpIdx oi, uintptr_t ra)
{
- set_helper_retaddr(retaddr);
- cpu_stw_be_data(env, ptr, val);
- clear_helper_retaddr();
-}
+ void *haddr;
-void cpu_stl_be_data_ra(CPUArchState *env, abi_ptr ptr,
- uint32_t val, uintptr_t retaddr)
-{
- set_helper_retaddr(retaddr);
- cpu_stl_be_data(env, ptr, val);
+ validate_memop(oi, MO_LEUW);
+ trace_guest_st_before_exec(env_cpu(env), addr, oi);
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
+ stw_le_p(haddr, val);
clear_helper_retaddr();
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
}
-void cpu_stq_be_data_ra(CPUArchState *env, abi_ptr ptr,
- uint64_t val, uintptr_t retaddr)
+void cpu_stl_le_mmu(CPUArchState *env, abi_ptr addr, uint32_t val,
+ MemOpIdx oi, uintptr_t ra)
{
- set_helper_retaddr(retaddr);
- cpu_stq_be_data(env, ptr, val);
- clear_helper_retaddr();
-}
+ void *haddr;
-void cpu_stw_le_data_ra(CPUArchState *env, abi_ptr ptr,
- uint32_t val, uintptr_t retaddr)
-{
- set_helper_retaddr(retaddr);
- cpu_stw_le_data(env, ptr, val);
+ validate_memop(oi, MO_LEUL);
+ trace_guest_st_before_exec(env_cpu(env), addr, oi);
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
+ stl_le_p(haddr, val);
clear_helper_retaddr();
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
}
-void cpu_stl_le_data_ra(CPUArchState *env, abi_ptr ptr,
- uint32_t val, uintptr_t retaddr)
+void cpu_stq_le_mmu(CPUArchState *env, abi_ptr addr, uint64_t val,
+ MemOpIdx oi, uintptr_t ra)
{
- set_helper_retaddr(retaddr);
- cpu_stl_le_data(env, ptr, val);
- clear_helper_retaddr();
-}
+ void *haddr;
-void cpu_stq_le_data_ra(CPUArchState *env, abi_ptr ptr,
- uint64_t val, uintptr_t retaddr)
-{
- set_helper_retaddr(retaddr);
- cpu_stq_le_data(env, ptr, val);
+ validate_memop(oi, MO_LEQ);
+ trace_guest_st_before_exec(env_cpu(env), addr, oi);
+ haddr = cpu_mmu_lookup(env, addr, oi, ra, MMU_DATA_STORE);
+ stq_le_p(haddr, val);
clear_helper_retaddr();
+ qemu_plugin_vcpu_mem_cb(env_cpu(env), addr, oi, QEMU_PLUGIN_MEM_W);
}
uint32_t cpu_ldub_code(CPUArchState *env, abi_ptr ptr)
@@ -1222,6 +1149,8 @@ uint64_t cpu_ldq_code(CPUArchState *env, abi_ptr ptr)
return ret;
}
+#include "ldst_common.c.inc"
+
/*
* Do not allow unaligned operations to proceed. Return the host address.
*