Signed-off-by: Lluís Vilanova <vilan...@ac.upc.edu> --- include/exec/cpu-all.h | 58 +++++++++++++++++++++-------------------- include/exec/exec-all.h | 3 ++ include/exec/softmmu_header.h | 17 ++++++++++++ tcg/tcg-op.h | 8 ++++++ tcg/tcg.c | 1 + trace-events | 15 +++++++++++ trace/tcg-op-internal.h | 55 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 129 insertions(+), 28 deletions(-) create mode 100644 trace/tcg-op-internal.h
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 4cb4b4a..4ecb486 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -250,21 +250,23 @@ extern unsigned long reserved_va; #if defined(CONFIG_USER_ONLY) +#include "trace.h" + /* if user mode, no other memory access functions */ -#define ldub(p) ldub_raw(p) -#define ldsb(p) ldsb_raw(p) -#define lduw(p) lduw_raw(p) -#define ldsw(p) ldsw_raw(p) -#define ldl(p) ldl_raw(p) -#define ldq(p) ldq_raw(p) -#define ldfl(p) ldfl_raw(p) -#define ldfq(p) ldfq_raw(p) -#define stb(p, v) stb_raw(p, v) -#define stw(p, v) stw_raw(p, v) -#define stl(p, v) stl_raw(p, v) -#define stq(p, v) stq_raw(p, v) -#define stfl(p, v) stfl_raw(p, v) -#define stfq(p, v) stfq_raw(p, v) +#define ldub(p) ({ trace_guest_vmem(p, 1, 0); ldub_raw(p); }) +#define ldsb(p) ({ trace_guest_vmem(p, 1, 0); ldsb_raw(p); }) +#define lduw(p) ({ trace_guest_vmem(p, 2, 0); lduw_raw(p); }) +#define ldsw(p) ({ trace_guest_vmem(p, 2, 0); ldsw_raw(p); }) +#define ldl(p) ({ trace_guest_vmem(p, 4, 0); ldl_raw(p); }) +#define ldq(p) ({ trace_guest_vmem(p, 8, 0); ldq_raw(p); }) +#define ldfl(p) ({ trace_guest_vmem(p, 4, 0); ldfl_raw(p); }) +#define ldfq(p) ({ trace_guest_vmem(p, 8, 0); ldfq_raw(p); }) +#define stb(p, v) ({ trace_guest_vmem(p, 1, 1); stb_raw(p, v); }) +#define stw(p, v) ({ trace_guest_vmem(p, 2, 1); stw_raw(p, v); }) +#define stl(p, v) ({ trace_guest_vmem(p, 4, 1); stl_raw(p, v); }) +#define stq(p, v) ({ trace_guest_vmem(p, 8, 1); stq_raw(p, v); }) +#define stfl(p, v) ({ trace_guest_vmem(p, 4, 1); stfl_raw(p, v); }) +#define stfq(p, v) ({ trace_guest_vmem(p, 8, 1); stfq_raw(p, v); }) #define cpu_ldub_code(env1, p) ldub_raw(p) #define cpu_ldsb_code(env1, p) ldsb_raw(p) @@ -295,20 +297,20 @@ extern unsigned long reserved_va; #define cpu_stl_kernel(env, addr, data) stl_raw(addr, data) #define cpu_stq_kernel(env, addr, data) stq_raw(addr, data) -#define ldub_kernel(p) ldub_raw(p) -#define ldsb_kernel(p) ldsb_raw(p) -#define lduw_kernel(p) lduw_raw(p) -#define ldsw_kernel(p) ldsw_raw(p) -#define ldl_kernel(p) ldl_raw(p) -#define ldq_kernel(p) ldq_raw(p) -#define ldfl_kernel(p) ldfl_raw(p) -#define ldfq_kernel(p) ldfq_raw(p) -#define stb_kernel(p, v) stb_raw(p, v) -#define stw_kernel(p, v) stw_raw(p, v) -#define stl_kernel(p, v) stl_raw(p, v) -#define stq_kernel(p, v) stq_raw(p, v) -#define stfl_kernel(p, v) stfl_raw(p, v) -#define stfq_kernel(p, vt) stfq_raw(p, v) +#define ldub_kernel(p) ({ trace_guest_vmem(p, 1, 0); ldub_raw(p); }) +#define ldsb_kernel(p) ({ trace_guest_vmem(p, 1, 0); ldsb_raw(p); }) +#define lduw_kernel(p) ({ trace_guest_vmem(p, 2, 0); lduw_raw(p); }) +#define ldsw_kernel(p) ({ trace_guest_vmem(p, 2, 0); ldsw_raw(p); }) +#define ldl_kernel(p) ({ trace_guest_vmem(p, 4, 0); ldl_raw(p); }) +#define ldq_kernel(p) ({ trace_guest_vmem(p, 8, 0); ldq_raw(p); }) +#define ldfl_kernel(p) ({ trace_guest_vmem(p, 4, 0); ldfl_raw(p); }) +#define ldfq_kernel(p) ({ trace_guest_vmem(p, 8, 0); ldfq_raw(p); }) +#define stb_kernel(p, v) ({ trace_guest_vmem(p, 1, 1); stb_raw(p, v); }) +#define stw_kernel(p, v) ({ trace_guest_vmem(p, 2, 1); stw_raw(p, v); }) +#define stl_kernel(p, v) ({ trace_guest_vmem(p, 4, 1); stl_raw(p, v); }) +#define stq_kernel(p, v) ({ trace_guest_vmem(p, 8, 1); stq_raw(p, v); }) +#define stfl_kernel(p, v) ({ trace_guest_vmem(p, 4, 1); stfl_raw(p, v); }) +#define stfq_kernel(p, vt) ({ trace_guest_vmem(p, 8, 1); stfq_raw(p, v); }) #define cpu_ldub_data(env, addr) ldub_raw(addr) #define cpu_lduw_data(env, addr) lduw_raw(addr) diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index ea90b64..f30cc4e 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -339,6 +339,8 @@ uint32_t helper_ldl_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); #define ACCESS_TYPE (NB_MMU_MODES + 1) +/* do not trace '*_code' accesses during instruction disassembly */ +#define TRACE_TCG_CODE_ACCESSOR 1 #define MEMSUFFIX _code #define DATA_SIZE 1 @@ -354,6 +356,7 @@ uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx); #include "exec/softmmu_header.h" #undef ACCESS_TYPE +#undef TRACE_TCG_CODE_ACCESSOR #undef MEMSUFFIX #endif diff --git a/include/exec/softmmu_header.h b/include/exec/softmmu_header.h index d8d9c81..ccd9cb1 100644 --- a/include/exec/softmmu_header.h +++ b/include/exec/softmmu_header.h @@ -25,6 +25,11 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see <http://www.gnu.org/licenses/>. */ + +#if !defined(TRACE_TCG_CODE_ACCESSOR) +#include "trace.h" +#endif + #if DATA_SIZE == 8 #define SUFFIX q #define USUFFIX q @@ -88,6 +93,10 @@ glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr) target_ulong addr; int mmu_idx; +#if !defined(TRACE_TCG_CODE_ACCESSOR) + trace_guest_vmem(ptr, DATA_SIZE, 0); +#endif + addr = ptr; page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); mmu_idx = CPU_MMU_INDEX; @@ -109,6 +118,10 @@ glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr) target_ulong addr; int mmu_idx; +#if !defined(TRACE_TCG_CODE_ACCESSOR) + trace_guest_vmem(ptr, DATA_SIZE, 0); +#endif + addr = ptr; page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); mmu_idx = CPU_MMU_INDEX; @@ -136,6 +149,10 @@ glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr, target_ulong addr; int mmu_idx; +#if !defined(TRACE_TCG_CODE_ACCESSOR) + trace_guest_vmem(ptr, DATA_SIZE, 1); +#endif + addr = ptr; page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); mmu_idx = CPU_MMU_INDEX; diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 7eabf22..0ce2f81 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -2888,3 +2888,11 @@ static inline void tcg_gen_qemu_st64(TCGv_i64 arg, TCGv addr, int mem_index) # define tcg_gen_ext_i32_ptr(R, A) \ tcg_gen_ext_i32_i64(TCGV_PTR_TO_NAT(R), (A)) #endif /* TCG_TARGET_REG_BITS == 32 */ + +#if !defined(TCG_OP_NOTRACE_GUEST_MEM) +/* To avoid a circular dependency with helper.h, overload tcg_gen_qemu_* + * routines with preprocessor macros to insert TCG virtual memory access + * tracing. + */ +#include "trace/tcg-op-internal.h" +#endif diff --git a/tcg/tcg.c b/tcg/tcg.c index acd02b9..7847277 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -47,6 +47,7 @@ #define NO_CPU_IO_DEFS #include "cpu.h" +#define TCG_OP_NOTRACE_GUEST_MEM #include "tcg-op.h" #if UINTPTR_MAX == UINT32_MAX diff --git a/trace-events b/trace-events index 1b668d1..3f5a55c 100644 --- a/trace-events +++ b/trace-events @@ -1186,3 +1186,18 @@ xen_pv_mmio_write(uint64_t addr) "WARNING: write to Xen PV Device MMIO space (ad # hw/pci/pci_host.c pci_cfg_read(const char *dev, unsigned devid, unsigned fnid, unsigned offs, unsigned val) "%s %02u:%u @0x%x -> 0x%x" pci_cfg_write(const char *dev, unsigned devid, unsigned fnid, unsigned offs, unsigned val) "%s %02u:%u @0x%x <- 0x%x" + + + +## Guest events, keep at bottom + +# @vaddr: Access' virtual address. +# @size : Access' size (bytes). +# @write: Whether the access is a write. +# +# Start virtual memory access (before any potential access violation). +# +# This event can be raised at execution time when running in 'user' mode. +# +# Targets: TCG(all) +disable tcg guest_vmem(TCGv vaddr, uint8_t size, uint8_t write) "vaddr=0x%016"PRIx64" size=%d write=%d" diff --git a/trace/tcg-op-internal.h b/trace/tcg-op-internal.h new file mode 100644 index 0000000..fea46fa --- /dev/null +++ b/trace/tcg-op-internal.h @@ -0,0 +1,55 @@ +/* -*- mode: c -*- + * Copyright (c) 2012-2014 Lluís Vilanova <vilan...@ac.upc.edu> + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +/** + * @file Capture TCG code generation for virtual memory accesses. + * + * Assumes that no other lower-level call will be performed by target + * architecture disassembly code on TCG instructions for accessing memory. + * + * Capturing calls to higher-level functions like @tcg_gen_qemu_ld8u would allow + * using constants for the access size (instead of computing it from the memory + * operand argument), but is harder to maintain. + */ + +#ifndef TRACE__TCG_OP_INTERNAL_H +#define TRACE__TCG_OP_INTERNAL_H + +static inline uint8_t _tcg_memop_size(TCGMemOp op) +{ + return 1 << (op & MO_SIZE); +} + +#define tcg_gen_qemu_ld_i32(val, addr, idx, memop) \ + do { \ + uint8_t _memop_size = _tcg_memop_size(memop); \ + trace_guest_vmem_tcg(addr, _memop_size, 0); \ + tcg_gen_qemu_ld_i32(val, addr, idx, memop); \ + } while (0) + +#define tcg_gen_qemu_st_i32(val, addr, idx, memop) \ + do { \ + uint8_t _memop_size = _tcg_memop_size(memop); \ + trace_guest_vmem_tcg(addr, _memop_size, 1); \ + tcg_gen_qemu_st_i32(val, addr, idx, memop); \ + } while (0) + +#define tcg_gen_qemu_ld_i64(val, addr, idx, memop) \ + do { \ + uint8_t _memop_size = _tcg_memop_size(memop); \ + trace_guest_vmem_tcg(addr, _memop_size, 0); \ + tcg_gen_qemu_ld_i64(val, addr, idx, memop); \ + } while (0) + +#define tcg_gen_qemu_st_i64(val, addr, idx, memop) \ + do { \ + uint8_t _memop_size = _tcg_memop_size(memop); \ + trace_guest_vmem_tcg(addr, _memop_size, 1); \ + tcg_gen_qemu_st_i64(val, addr, idx, memop); \ + } while (0) + +#endif /* TRACE__TCG_OP_INTERNAL_H */