diff options
Diffstat (limited to 'accel/tcg/user-exec.c')
-rw-r--r-- | accel/tcg/user-exec.c | 347 |
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. * |