qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 12/12] trace: [all] Add "guest_vmem" event


From: Lluís Vilanova
Subject: [Qemu-devel] [PATCH 12/12] trace: [all] Add "guest_vmem" event
Date: Fri, 31 Jan 2014 17:10:08 +0100
User-agent: StGit/0.16

Signed-off-by: Lluís Vilanova <address@hidden>
---
 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 <address@hidden>
+ *
+ * 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 */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]