All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2 00/10] trace: Per-vCPU tracing states
@ 2015-11-24 17:08 Lluís Vilanova
  2015-11-24 17:08 ` [Qemu-devel] [PATCH v2 01/10] trace: Add support for vCPU pointers in trace events Lluís Vilanova
                   ` (10 more replies)
  0 siblings, 11 replies; 20+ messages in thread
From: Lluís Vilanova @ 2015-11-24 17:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi, Eduardo Habkost

NOTE: This series completes the framework for guest code tracing. Next series
      will add actual events.

Provides per-vCPU dynamic controls of the tracing state of events tied to a
specific virtual CPU.

Events with the "vcpu" property are identified as being tied to a particular
virtual CPU, like executing an instruction. The state of such events can be
controlled idependently; this is specially useful to, for example, trace memory
access events of a process executing on a specific virtual CPU.

This event property plays in combination with the "tcg" property to avoid
generating a call to the execution-time event tracer when a vCPU is not actively
tracing such event (i.e., avoids adding tracing overheads).

Virtual CPUs tracing the same set of events use the same physical translation
cache, improving their reuse. The system has 2^N physical translation caches,
where "N" is the number of TCG events with the "vcpu" property. Every vCPU has a
bitmap with the states of these events, which can be controlled separately, and
uses it to select its physical translation cache. At translation time, QEMU
generates the code to trace an event at execution time only if the event is
enabled.

Changes in v2
=============

* Rebase on 5522a84.
* Improve patch descriptions.
* Refactor code generation into a separate patch.
* Fix forward declarations (Stefan Hajnoczi & Eduardo Habkost).
* Fix "since" tags in QAPI interface (Eric Blake).
* Unify QAPI/QMP interface with an optional 'vcpu' argument (Eric Blake).
* Fix QMP+GTK header workaround (Stefan Hajnoczi).


Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---

Lluís Vilanova (10):
      trace: Add support for vCPU pointers in trace events
      trace: Add 'vcpu' event property
      trace: [tcg] Identify events with the 'vcpu' property
      exec: [tcg] Refactor flush of per-CPU virtual TB cache
      exec: [ŧcg] Use multiple physical TB caches
      exec: [tcg] Track which vCPU is performing translation and execution
      [trivial] Track when QEMU has finished initialization
      disas: Remove unused macro '_'
      trace: [tcg] Add per-vCPU tracing states for events with the 'vcpu' property
      trace: [tcg] Generate TCG code to trace guest events on a per-vCPU basis


 Makefile.objs                            |    3 -
 bsd-user/main.c                          |    1 
 cpu-exec.c                               |   17 +++
 cputlb.c                                 |    2 
 disas/i386.c                             |    2 
 docs/tracing.txt                         |   40 ++++++++
 include/disas/bfd.h                      |    1 
 include/exec/exec-all.h                  |   16 +++
 include/qemu-common.h                    |    3 +
 include/qemu/typedefs.h                  |    1 
 include/qom/cpu.h                        |   10 ++
 linux-user/main.c                        |    1 
 monitor.c                                |    4 -
 qapi/trace.json                          |   16 ++-
 qemu-common.c                            |   14 +++
 qmp-commands.hx                          |   17 +++
 qom/cpu.c                                |   21 ++++
 scripts/tracetool/__init__.py            |   24 ++++-
 scripts/tracetool/format/events_c.py     |   11 ++
 scripts/tracetool/format/events_h.py     |   14 ++-
 scripts/tracetool/format/h.py            |    4 +
 scripts/tracetool/format/tcg_h.py        |   21 +++-
 scripts/tracetool/format/tcg_helper_c.py |   11 ++
 scripts/tracetool/format/ust_events_c.py |    3 -
 scripts/tracetool/transform.py           |    9 ++
 stubs/Makefile.objs                      |    1 
 stubs/qemu-common-stub.c                 |   21 ++++
 target-alpha/translate.c                 |    3 -
 target-arm/translate.c                   |    3 -
 target-arm/translate.h                   |    2 
 target-cris/translate.c                  |    3 -
 target-cris/translate_v10.c              |    1 
 target-i386/translate.c                  |    3 -
 target-lm32/translate.c                  |    3 -
 target-m68k/translate.c                  |    3 -
 target-microblaze/translate.c            |    3 -
 target-mips/translate.c                  |    3 -
 target-moxie/translate.c                 |    3 -
 target-openrisc/translate.c              |    3 -
 target-ppc/translate.c                   |    3 -
 target-s390x/translate.c                 |    3 -
 target-sh4/translate.c                   |    3 -
 target-sparc/translate.c                 |    6 +
 target-tilegx/translate.c                |    3 -
 target-tricore/translate.c               |    3 -
 target-unicore32/translate.c             |    3 -
 target-xtensa/translate.c                |    3 -
 tcg/tcg-op.h                             |    2 
 tcg/tcg.h                                |   10 ++
 trace/Makefile.objs                      |    2 
 trace/control-internal.h                 |   21 +++-
 trace/control-stub.c                     |   29 ++++++
 trace/control-target.c                   |   69 +++++++++++++
 trace/control.h                          |   64 ++++++++++++
 trace/event-internal.h                   |    6 +
 trace/qmp.c                              |  139 ++++++++++++++++++++++-----
 translate-all.c                          |  156 ++++++++++++++++++++++++++----
 translate-all.h                          |   49 +++++++++
 vl.c                                     |    2 
 59 files changed, 788 insertions(+), 109 deletions(-)
 create mode 100644 qemu-common.c
 create mode 100644 stubs/qemu-common-stub.c
 create mode 100644 trace/control-stub.c
 create mode 100644 trace/control-target.c


To: qemu-devel@nongnu.org
Cc: Stefan Hajnoczi <stefanha@gmail.com>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Cc: Eric Blake <eblake@redhat.com>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v2 01/10] trace: Add support for vCPU pointers in trace events
  2015-11-24 17:08 [Qemu-devel] [PATCH v2 00/10] trace: Per-vCPU tracing states Lluís Vilanova
@ 2015-11-24 17:08 ` Lluís Vilanova
  2015-11-24 17:08 ` [Qemu-devel] [PATCH v2 02/10] trace: Add 'vcpu' event property Lluís Vilanova
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 20+ messages in thread
From: Lluís Vilanova @ 2015-11-24 17:08 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Guan Xuetao, open list:ARM, Eduardo Habkost,
	Stefan Hajnoczi, Anthony Green, Mark Cave-Ayland, Jia Liu,
	Alexander Graf, Blue Swirl, Max Filippov, Michael Walle,
	Leon Alrae, open list:PowerPC, Stefan Hajnoczi, Paolo Bonzini,
	Edgar E. Iglesias, Bastian Koppelmann, Aurelien Jarno,
	Richard Henderson

The tracing infrastructure later needs to differentiate between regular
pointers and pointers to vCPUs.

Also changes all targets to use the new 'TCGv_cpu' type instead of the
generic 'TCGv_ptr'. As of now, the change is merely cosmetic ('TCGv_cpu'
translates into 'TCGv_ptr'), but that could change in the future to
enforce the difference.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 include/qemu/typedefs.h        |    1 +
 scripts/tracetool/transform.py |    9 ++++++++-
 target-alpha/translate.c       |    2 +-
 target-arm/translate.c         |    2 +-
 target-arm/translate.h         |    2 +-
 target-cris/translate.c        |    2 +-
 target-i386/translate.c        |    2 +-
 target-lm32/translate.c        |    2 +-
 target-m68k/translate.c        |    2 +-
 target-microblaze/translate.c  |    2 +-
 target-mips/translate.c        |    2 +-
 target-moxie/translate.c       |    2 +-
 target-openrisc/translate.c    |    2 +-
 target-ppc/translate.c         |    2 +-
 target-s390x/translate.c       |    2 +-
 target-sh4/translate.c         |    2 +-
 target-sparc/translate.c       |    5 +++--
 target-tilegx/translate.c      |    2 +-
 target-tricore/translate.c     |    2 +-
 target-unicore32/translate.c   |    2 +-
 target-xtensa/translate.c      |    2 +-
 tcg/tcg-op.h                   |    2 --
 tcg/tcg.h                      |    6 ++++++
 trace/control.h                |    3 ++-
 24 files changed, 38 insertions(+), 24 deletions(-)

diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
index 6b1093d..5f28c36 100644
--- a/include/qemu/typedefs.h
+++ b/include/qemu/typedefs.h
@@ -19,6 +19,7 @@ typedef struct BusState BusState;
 typedef struct CharDriverState CharDriverState;
 typedef struct CompatProperty CompatProperty;
 typedef struct CPUAddressSpace CPUAddressSpace;
+typedef struct CPUState CPUState;
 typedef struct DeviceState DeviceState;
 typedef struct DeviceListener DeviceListener;
 typedef struct DisplayChangeListener DisplayChangeListener;
diff --git a/scripts/tracetool/transform.py b/scripts/tracetool/transform.py
index fc5e679..db3ed54 100644
--- a/scripts/tracetool/transform.py
+++ b/scripts/tracetool/transform.py
@@ -6,7 +6,7 @@ Type-transformation rules.
 """
 
 __author__     = "Lluís Vilanova <vilanova@ac.upc.edu>"
-__copyright__  = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__  = "Copyright 2012-2015, Lluís Vilanova <vilanova@ac.upc.edu>"
 __license__    = "GPL version 2 or (at your option) any later version"
 
 __maintainer__ = "Stefan Hajnoczi"
@@ -74,6 +74,7 @@ TCG_2_HOST = {
     "TCGv_i32": "uint32_t",
     "TCGv_i64": "uint64_t",
     "TCGv_ptr": "void *",
+    "TCGv_cpu": "CPUState *",
     None: _tcg_2_host,
     }
 
@@ -98,6 +99,7 @@ HOST_2_TCG = {
     "uint32_t": "TCGv_i32",
     "uint64_t": "TCGv_i64",
     "void *"  : "TCGv_ptr",
+    "CPUState *": "TCGv_cpu",
     None: _host_2_tcg,
     }
 
@@ -115,6 +117,8 @@ TCG_2_TCG_HELPER_DEF = {
     "TCGv_i32": "uint32_t",
     "TCGv_i64": "uint64_t",
     "TCGv_ptr": "void *",
+    "TCGv_cpu": "void *",
+    "CPUState *": "void *",
     None: _tcg_2_helper_def,
     }
 
@@ -130,6 +134,7 @@ TCG_2_TCG_HELPER_DECL = {
     "TCGv_ptr": "ptr",
     "TCGv_i32": "i32",
     "TCGv_i64": "i64",
+    "TCGv_cpu": "ptr",
     None: _tcg_2_tcg_helper_decl_error,
     }
 
@@ -146,6 +151,7 @@ HOST_2_TCG_TMP_NEW = {
     "uint32_t": "tcg_const_i32",
     "uint64_t": "tcg_const_i64",
     "void *"  : "tcg_const_ptr",
+    "CPUState *": "tcg_const_ptr",
     None: _host_2_tcg_tmp_new,
     }
 
@@ -162,5 +168,6 @@ HOST_2_TCG_TMP_FREE = {
     "uint32_t": "tcg_temp_free_i32",
     "uint64_t": "tcg_temp_free_i64",
     "void *"  : "tcg_temp_free_ptr",
+    "CPUState *": "tcg_temp_free_ptr",
     None: _host_2_tcg_tmp_free,
     }
diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index 9909c70..d631f74 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -91,7 +91,7 @@ typedef enum {
 } ExitStatus;
 
 /* global register indexes */
-static TCGv_ptr cpu_env;
+static TCGv_cpu cpu_env;
 static TCGv cpu_std_ir[31];
 static TCGv cpu_fir[31];
 static TCGv cpu_pc;
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 5d22879..e672092 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -59,7 +59,7 @@
 #define IS_USER(s) (s->user)
 #endif
 
-TCGv_ptr cpu_env;
+TCGv_cpu cpu_env;
 /* We reuse the same 64-bit temporaries for efficiency.  */
 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
 static TCGv_i32 cpu_R[16];
diff --git a/target-arm/translate.h b/target-arm/translate.h
index 53ef971..6e8eb7d 100644
--- a/target-arm/translate.h
+++ b/target-arm/translate.h
@@ -70,7 +70,7 @@ typedef struct DisasCompare {
 } DisasCompare;
 
 /* Share the TCG temporaries common between 32 and 64 bit modes.  */
-extern TCGv_ptr cpu_env;
+extern TCGv_cpu cpu_env;
 extern TCGv_i32 cpu_NF, cpu_ZF, cpu_CF, cpu_VF;
 extern TCGv_i64 cpu_exclusive_addr;
 extern TCGv_i64 cpu_exclusive_val;
diff --git a/target-cris/translate.c b/target-cris/translate.c
index 2d710cc..fdcbfc6 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -58,7 +58,7 @@
 #define CC_MASK_NZVC 0xf
 #define CC_MASK_RNZV 0x10e
 
-static TCGv_ptr cpu_env;
+static TCGv_cpu cpu_env;
 static TCGv cpu_R[16];
 static TCGv cpu_PR[16];
 static TCGv cc_x;
diff --git a/target-i386/translate.c b/target-i386/translate.c
index a3dd167..53a09f8 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -62,7 +62,7 @@
 //#define MACRO_TEST   1
 
 /* global register indexes */
-static TCGv_ptr cpu_env;
+static TCGv_cpu cpu_env;
 static TCGv cpu_A0;
 static TCGv cpu_cc_dst, cpu_cc_src, cpu_cc_src2, cpu_cc_srcT;
 static TCGv_i32 cpu_cc_op;
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index fa5b0b9..a333fc6 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -42,7 +42,7 @@
 
 #define MEM_INDEX 0
 
-static TCGv_ptr cpu_env;
+static TCGv_cpu cpu_env;
 static TCGv cpu_R[32];
 static TCGv cpu_pc;
 static TCGv cpu_ie;
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 41ae2c6..d68d615 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -48,7 +48,7 @@
 static TCGv_i32 cpu_halted;
 static TCGv_i32 cpu_exception_index;
 
-static TCGv_ptr cpu_env;
+static TCGv_cpu cpu_env;
 
 static char cpu_reg_names[3*8*3 + 5*4];
 static TCGv cpu_dregs[8];
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 154b9d6..9f1586f 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -44,7 +44,7 @@
             (((src) >> start) & ((1 << (end - start + 1)) - 1))
 
 static TCGv env_debug;
-static TCGv_ptr cpu_env;
+static TCGv_cpu cpu_env;
 static TCGv cpu_R[32];
 static TCGv cpu_SR[18];
 static TCGv env_imm;
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 5626647..610ed7c 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1351,7 +1351,7 @@ enum {
 };
 
 /* global register indices */
-static TCGv_ptr cpu_env;
+static TCGv_cpu cpu_env;
 static TCGv cpu_gpr[32], cpu_PC;
 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
 static TCGv cpu_dspctrl, btarget, bcond;
diff --git a/target-moxie/translate.c b/target-moxie/translate.c
index 6dedcb7..ab8f6a7 100644
--- a/target-moxie/translate.c
+++ b/target-moxie/translate.c
@@ -59,7 +59,7 @@ enum {
 
 static TCGv cpu_pc;
 static TCGv cpu_gregs[16];
-static TCGv_ptr cpu_env;
+static TCGv_cpu cpu_env;
 static TCGv cc_a, cc_b;
 
 #include "exec/gen-icount.h"
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 606490a..3d29369 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -52,7 +52,7 @@ typedef struct DisasContext {
     uint32_t delayed_branch;
 } DisasContext;
 
-static TCGv_ptr cpu_env;
+static TCGv_cpu cpu_env;
 static TCGv cpu_sr;
 static TCGv cpu_R[32];
 static TCGv cpu_pc;
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 41a7258..17f732a 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -47,7 +47,7 @@
 /* Code translation helpers                                                  */
 
 /* global register indexes */
-static TCGv_ptr cpu_env;
+static TCGv_cpu cpu_env;
 static char cpu_reg_names[10*3 + 22*4 /* GPR */
     + 10*4 + 22*5 /* SPE GPRh */
     + 10*4 + 22*5 /* FPR */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index c79a2cb..262da89 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -36,7 +36,7 @@
 #include "exec/cpu_ldst.h"
 
 /* global register indexes */
-static TCGv_ptr cpu_env;
+static TCGv_cpu cpu_env;
 
 #include "exec/gen-icount.h"
 #include "exec/helper-proto.h"
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 7bc6216..c3a8fbd 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -59,7 +59,7 @@ enum {
 };
 
 /* global register indexes */
-static TCGv_ptr cpu_env;
+static TCGv_cpu cpu_env;
 static TCGv cpu_gregs[24];
 static TCGv cpu_sr, cpu_sr_m, cpu_sr_q, cpu_sr_t;
 static TCGv cpu_pc, cpu_ssr, cpu_spc, cpu_gbr;
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 41a3319..811519e 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -42,7 +42,8 @@
                          according to jump_pc[T2] */
 
 /* global register indexes */
-static TCGv_ptr cpu_env, cpu_regwptr;
+static TCGv_cpu cpu_env;
+static TCGv_ptr cpu_regwptr;
 static TCGv cpu_cc_src, cpu_cc_src2, cpu_cc_dst;
 static TCGv_i32 cpu_cc_op;
 static TCGv_i32 cpu_psr;
@@ -2294,7 +2295,7 @@ static void gen_fmovq(DisasContext *dc, DisasCompare *cmp, int rd, int rs)
 }
 
 #ifndef CONFIG_USER_ONLY
-static inline void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_ptr cpu_env)
+static inline void gen_load_trap_state_at_tl(TCGv_ptr r_tsptr, TCGv_cpu cpu_env)
 {
     TCGv_i32 r_tl = tcg_temp_new_i32();
 
diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c
index 354f25a..fb5413a 100644
--- a/target-tilegx/translate.c
+++ b/target-tilegx/translate.c
@@ -30,7 +30,7 @@
 
 #define FMT64X                          "%016" PRIx64
 
-static TCGv_ptr cpu_env;
+static TCGv_cpu cpu_env;
 static TCGv cpu_pc;
 static TCGv cpu_regs[TILEGX_R_COUNT];
 
diff --git a/target-tricore/translate.c b/target-tricore/translate.c
index 135c583..655db75 100644
--- a/target-tricore/translate.c
+++ b/target-tricore/translate.c
@@ -45,7 +45,7 @@ static TCGv cpu_PSW_SV;
 static TCGv cpu_PSW_AV;
 static TCGv cpu_PSW_SAV;
 /* CPU env */
-static TCGv_ptr cpu_env;
+static TCGv_cpu cpu_env;
 
 #include "exec/gen-icount.h"
 
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index d2f92f0..29c22f5 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -51,7 +51,7 @@ typedef struct DisasContext {
    conditional executions state has been updated.  */
 #define DISAS_SYSCALL 5
 
-static TCGv_ptr cpu_env;
+static TCGv_cpu cpu_env;
 static TCGv_i32 cpu_R[32];
 
 /* FIXME:  These should be removed.  */
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 06b0163..5ad1244 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -73,7 +73,7 @@ typedef struct DisasContext {
     unsigned cpenable;
 } DisasContext;
 
-static TCGv_ptr cpu_env;
+static TCGv_cpu cpu_env;
 static TCGv_i32 cpu_pc;
 static TCGv_i32 cpu_R[16];
 static TCGv_i32 cpu_FR[16];
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index 4e20dc1..c446d3d 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -756,7 +756,6 @@ static inline void tcg_gen_exit_tb(uintptr_t val)
 void tcg_gen_goto_tb(unsigned idx);
 
 #if TARGET_LONG_BITS == 32
-#define TCGv TCGv_i32
 #define tcg_temp_new() tcg_temp_new_i32()
 #define tcg_global_reg_new tcg_global_reg_new_i32
 #define tcg_global_mem_new tcg_global_mem_new_i32
@@ -768,7 +767,6 @@ void tcg_gen_goto_tb(unsigned idx);
 #define tcg_gen_qemu_ld_tl tcg_gen_qemu_ld_i32
 #define tcg_gen_qemu_st_tl tcg_gen_qemu_st_i32
 #else
-#define TCGv TCGv_i64
 #define tcg_temp_new() tcg_temp_new_i64()
 #define tcg_global_reg_new tcg_global_reg_new_i64
 #define tcg_global_mem_new tcg_global_mem_new_i64
diff --git a/tcg/tcg.h b/tcg/tcg.h
index a696922..1585551 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -308,6 +308,12 @@ typedef tcg_target_ulong TCGArg;
 typedef struct TCGv_i32_d *TCGv_i32;
 typedef struct TCGv_i64_d *TCGv_i64;
 typedef struct TCGv_ptr_d *TCGv_ptr;
+typedef TCGv_ptr TCGv_cpu;
+#if TARGET_LONG_BITS == 32
+typedef TCGv_i32 TCGv;
+#else  /* TARGET_LONG_BITS == 64 */
+typedef TCGv_i64 TCGv;
+#endif
 
 static inline TCGv_i32 QEMU_ARTIFICIAL MAKE_TCGV_I32(intptr_t i)
 {
diff --git a/trace/control.h b/trace/control.h
index da9bb6b..275a086 100644
--- a/trace/control.h
+++ b/trace/control.h
@@ -1,7 +1,7 @@
 /*
  * Interface for configuring and controlling the state of tracing events.
  *
- * Copyright (C) 2011-2014 Lluís Vilanova <vilanova@ac.upc.edu>
+ * Copyright (C) 2011-2015 Lluís Vilanova <vilanova@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.
@@ -11,6 +11,7 @@
 #define TRACE__CONTROL_H
 
 #include "qemu-common.h"
+#include "qemu/typedefs.h"
 #include "trace/generated-events.h"
 
 

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v2 02/10] trace: Add 'vcpu' event property
  2015-11-24 17:08 [Qemu-devel] [PATCH v2 00/10] trace: Per-vCPU tracing states Lluís Vilanova
  2015-11-24 17:08 ` [Qemu-devel] [PATCH v2 01/10] trace: Add support for vCPU pointers in trace events Lluís Vilanova
@ 2015-11-24 17:08 ` Lluís Vilanova
  2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 03/10] trace: [tcg] Identify events with the 'vcpu' property Lluís Vilanova
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 20+ messages in thread
From: Lluís Vilanova @ 2015-11-24 17:08 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi, Eduardo Habkost, Stefan Hajnoczi

This property identifies events that trace vCPU-specific information.

It adds a "CPUState*" argument to events with the property, identifying
the vCPU raising the event. TCG translation events also have a
"TCGv_cpu" implicit argument that is later used as the "CPUState*"
argument at execution time.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 docs/tracing.txt                         |   40 ++++++++++++++++++++++++++++++
 scripts/tracetool/__init__.py            |   24 +++++++++++++++++-
 scripts/tracetool/format/h.py            |    3 ++
 scripts/tracetool/format/tcg_h.py        |   13 ++++++++--
 scripts/tracetool/format/ust_events_c.py |    3 ++
 5 files changed, 76 insertions(+), 7 deletions(-)

diff --git a/docs/tracing.txt b/docs/tracing.txt
index 3853a6a..ade39e0 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -347,3 +347,43 @@ This will immediately call:
 and will generate the TCG code to call:
 
     void trace_foo(uint8_t a1, uint32_t a2);
+
+=== "vcpu" ===
+
+Identifies events that trace vCPU-specific information. The property adds a
+"CPUState*" argument that identifies the vCPU raising the event. If used
+together with the "tcg" property, it adds a second "TCGv_cpu" argument that
+identifies the vCPU when guest code is executed.
+
+The following example events:
+
+    foo(uint32_t a) "a=%x"
+    vcpu bar(uint32_t a) "cpu=%p a=%x"
+    tcg vcpu baz(uint32_t a) "cpu=%p a=%x", "cpu=%p a=%x"
+
+Can be used as:
+
+    #include "trace-tcg.h"
+    
+    CPUArchState *env;
+    TCGv_ptr cpu_env;
+    
+    void some_disassembly_func(...)
+    {
+        /* trace emitted at this point */
+        trace_foo(0xd1);
+        /* trace emitted at this point */
+        trace_bar(ENV_GET_CPU(env), 0xd2);
+        /* trace emitted at this point (env) and when guest code is executed (cpu_env) */
+        trace_baz_tcg(ENV_GET_CPU(env), cpu_env, 0xd3);
+    }
+
+If we assume code is translated by the vCPU with address 0xc1 and executed by
+the vCPU with address 0xc2, this would be an example output:
+
+    // at guest code translation
+    foo a=0xd1
+    bar cpu=0xc1 a=0xd2
+    baz_trans cpu=0xc1 a=0xd3
+    // at guest code execution
+    baz_exec cpu=0xc2 a=0xd3
diff --git a/scripts/tracetool/__init__.py b/scripts/tracetool/__init__.py
index 181675f..b75c66d 100644
--- a/scripts/tracetool/__init__.py
+++ b/scripts/tracetool/__init__.py
@@ -6,7 +6,7 @@ Machinery for generating tracing-related intermediate files.
 """
 
 __author__     = "Lluís Vilanova <vilanova@ac.upc.edu>"
-__copyright__  = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__  = "Copyright 2012-2015, Lluís Vilanova <vilanova@ac.upc.edu>"
 __license__    = "GPL version 2 or (at your option) any later version"
 
 __maintainer__ = "Stefan Hajnoczi"
@@ -146,7 +146,7 @@ class Event(object):
                       "(?:(?:(?P<fmt_trans>\".+),)?\s*(?P<fmt>\".+))?"
                       "\s*")
 
-    _VALID_PROPS = set(["disable", "tcg", "tcg-trans", "tcg-exec"])
+    _VALID_PROPS = set(["disable", "tcg", "tcg-trans", "tcg-exec", "vcpu"])
 
     def __init__(self, name, props, fmt, args, orig=None):
         """
@@ -215,6 +215,19 @@ class Event(object):
         if "tcg" in props and isinstance(fmt, str):
             raise ValueError("Events with 'tcg' property must have two formats")
 
+        # add implicit arguments when using the 'vcpu' property
+        if "vcpu" in props:
+            assert "tcg-trans" not in props and "tcg-exec" not in props
+            # events with 'tcg-trans' and 'tcg-exec' are auto-generated, they
+            # have already been transformed
+            if "tcg" in props:
+                types = ["TCGv_cpu"] + args.types()
+                names = ["_tcg_cpu"] + args.names()
+            else:
+                types = ["CPUState *"] + args.types()
+                names = ["_cpu"] + args.names()
+            args = Arguments(zip(types, names))
+
         return Event(name, props, fmt, args)
 
     def __repr__(self):
@@ -270,6 +283,7 @@ def _read_events(fobj):
             event_trans.name += "_trans"
             event_trans.properties += ["tcg-trans"]
             event_trans.fmt = event.fmt[0]
+            # ignore TCG arguments
             args_trans = []
             for atrans, aorig in zip(
                     event_trans.transform(tracetool.transform.TCG_2_HOST).args,
@@ -279,6 +293,12 @@ def _read_events(fobj):
             event_trans.args = Arguments(args_trans)
             event_trans = event_trans.copy()
 
+            # trace the vCPU performing the translation
+            if "vcpu" in event_trans.properties:
+                event_trans.args = Arguments(zip(
+                    ["CPUState *"] + list(event_trans.args.types()),
+                    ["_cpu"] + list(event_trans.args.names())))
+
             event_exec = event.copy()
             event_exec.name += "_exec"
             event_exec.properties += ["tcg-exec"]
diff --git a/scripts/tracetool/format/h.py b/scripts/tracetool/format/h.py
index 9b39430..01d8718 100644
--- a/scripts/tracetool/format/h.py
+++ b/scripts/tracetool/format/h.py
@@ -6,7 +6,7 @@ trace/generated-tracers.h
 """
 
 __author__     = "Lluís Vilanova <vilanova@ac.upc.edu>"
-__copyright__  = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__  = "Copyright 2012-2015, Lluís Vilanova <vilanova@ac.upc.edu>"
 __license__    = "GPL version 2 or (at your option) any later version"
 
 __maintainer__ = "Stefan Hajnoczi"
@@ -23,6 +23,7 @@ def generate(events, backend):
         '#define TRACE__GENERATED_TRACERS_H',
         '',
         '#include "qemu-common.h"',
+        '#include "qemu/typedefs.h"',
         '')
 
     backend.generate_begin(events)
diff --git a/scripts/tracetool/format/tcg_h.py b/scripts/tracetool/format/tcg_h.py
index f676b66..222002c 100644
--- a/scripts/tracetool/format/tcg_h.py
+++ b/scripts/tracetool/format/tcg_h.py
@@ -6,14 +6,14 @@ Generate .h file for TCG code generation.
 """
 
 __author__     = "Lluís Vilanova <vilanova@ac.upc.edu>"
-__copyright__  = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__  = "Copyright 2012-2015, Lluís Vilanova <vilanova@ac.upc.edu>"
 __license__    = "GPL version 2 or (at your option) any later version"
 
 __maintainer__ = "Stefan Hajnoczi"
 __email__      = "stefanha@linux.vnet.ibm.com"
 
 
-from tracetool import out
+from tracetool import out, Arguments
 
 
 def generate(events, backend):
@@ -38,10 +38,17 @@ def generate(events, backend):
         # get the original event definition
         e = e.original.original
 
+        if "vcpu" in e.properties:
+            args_api = Arguments(zip(
+                ["CPUState *"] + e.args.types(),
+                ["_cpu"] + e.args.names()))
+        else:
+            args_api = e.args
+
         out('static inline void %(name_tcg)s(%(args)s)',
             '{',
             name_tcg=e.api(e.QEMU_TRACE_TCG),
-            args=e.args)
+            args=args_api)
 
         if "disable" not in e.properties:
             out('    %(name_trans)s(%(argnames_trans)s);',
diff --git a/scripts/tracetool/format/ust_events_c.py b/scripts/tracetool/format/ust_events_c.py
index bc97093..5139840 100644
--- a/scripts/tracetool/format/ust_events_c.py
+++ b/scripts/tracetool/format/ust_events_c.py
@@ -6,7 +6,7 @@ trace/generated-ust.c
 """
 
 __author__     = "Mohamad Gebai <mohamad.gebai@polymtl.ca>"
-__copyright__  = "Copyright 2012, Mohamad Gebai <mohamad.gebai@polymtl.ca>"
+__copyright__  = "Copyright 2012, 2015, Mohamad Gebai <mohamad.gebai@polymtl.ca>"
 __license__    = "GPL version 2 or (at your option) any later version"
 
 __maintainer__ = "Stefan Hajnoczi"
@@ -30,4 +30,5 @@ def generate(events, backend):
         ' */',
         '#pragma GCC diagnostic ignored "-Wredundant-decls"',
         '',
+        '#include "qemu/typedefs.h"',
         '#include "generated-ust-provider.h"')

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v2 03/10] trace: [tcg] Identify events with the 'vcpu' property
  2015-11-24 17:08 [Qemu-devel] [PATCH v2 00/10] trace: Per-vCPU tracing states Lluís Vilanova
  2015-11-24 17:08 ` [Qemu-devel] [PATCH v2 01/10] trace: Add support for vCPU pointers in trace events Lluís Vilanova
  2015-11-24 17:08 ` [Qemu-devel] [PATCH v2 02/10] trace: Add 'vcpu' event property Lluís Vilanova
@ 2015-11-24 17:09 ` Lluís Vilanova
  2015-11-24 17:54   ` Eric Blake
  2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 04/10] exec: [tcg] Refactor flush of per-CPU virtual TB cache Lluís Vilanova
                   ` (7 subsequent siblings)
  10 siblings, 1 reply; 20+ messages in thread
From: Lluís Vilanova @ 2015-11-24 17:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Stefan Hajnoczi, Eduardo Habkost, Stefan Hajnoczi, Markus Armbruster

A separate ID space ('TRACE_CPU_*') is used in attribute 'cpu_id' that
only contains events with the 'vcpu' property.

These are later used to select the appropriate physical TB cache based
on what events are active.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 qapi/trace.json                      |    5 +++--
 scripts/tracetool/format/events_c.py |   11 +++++++++--
 scripts/tracetool/format/events_h.py |   14 ++++++++++++--
 trace/control-internal.h             |    8 +++++++-
 trace/control.h                      |    7 +++++++
 trace/event-internal.h               |    4 +++-
 trace/qmp.c                          |    3 ++-
 7 files changed, 43 insertions(+), 9 deletions(-)

diff --git a/qapi/trace.json b/qapi/trace.json
index 01b0a52..71cb96f 100644
--- a/qapi/trace.json
+++ b/qapi/trace.json
@@ -1,6 +1,6 @@
 # -*- mode: python -*-
 #
-# Copyright (C) 2011-2014 Lluís Vilanova <vilanova@ac.upc.edu>
+# Copyright (C) 2011-2015 Lluís Vilanova <vilanova@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.
@@ -29,11 +29,12 @@
 #
 # @name: Event name.
 # @state: Tracing state.
+# @vcpu: Whether this is a per-vCPU event (since 2.5).
 #
 # Since 2.2
 ##
 { 'struct': 'TraceEventInfo',
-  'data': {'name': 'str', 'state': 'TraceEventState'} }
+  'data': {'name': 'str', 'state': 'TraceEventState', 'vcpu': 'bool'} }
 
 ##
 # @trace-event-get-state:
diff --git a/scripts/tracetool/format/events_c.py b/scripts/tracetool/format/events_c.py
index 2d97fa3..e0ff73a 100644
--- a/scripts/tracetool/format/events_c.py
+++ b/scripts/tracetool/format/events_c.py
@@ -6,7 +6,7 @@ trace/generated-events.c
 """
 
 __author__     = "Lluís Vilanova <vilanova@ac.upc.edu>"
-__copyright__  = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__  = "Copyright 2012-2015, Lluís Vilanova <vilanova@ac.upc.edu>"
 __license__    = "GPL version 2 or (at your option) any later version"
 
 __maintainer__ = "Stefan Hajnoczi"
@@ -27,8 +27,15 @@ def generate(events, backend):
     out('TraceEvent trace_events[TRACE_EVENT_COUNT] = {')
 
     for e in events:
-        out('    { .id = %(id)s, .name = \"%(name)s\", .sstate = %(sstate)s, .dstate = 0 },',
+        if "vcpu" in e.properties and "tcg-exec" in e.properties:
+            vcpu_id = "TRACE_CPU_" + e.name.upper()
+        else:
+            vcpu_id = "TRACE_CPU_EVENT_COUNT"
+        out('    { .id = %(id)s, .cpu_id = %(vcpu_id)s,'
+            ' .name = \"%(name)s\",'
+            ' .sstate = %(sstate)s, .dstate = 0 },',
             id = "TRACE_" + e.name.upper(),
+            vcpu_id = vcpu_id,
             name = e.name,
             sstate = "TRACE_%s_ENABLED" % e.name.upper())
 
diff --git a/scripts/tracetool/format/events_h.py b/scripts/tracetool/format/events_h.py
index 9f114a3..f260090 100644
--- a/scripts/tracetool/format/events_h.py
+++ b/scripts/tracetool/format/events_h.py
@@ -6,7 +6,7 @@ trace/generated-events.h
 """
 
 __author__     = "Lluís Vilanova <vilanova@ac.upc.edu>"
-__copyright__  = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__  = "Copyright 2012-2015, Lluís Vilanova <vilanova@ac.upc.edu>"
 __license__    = "GPL version 2 or (at your option) any later version"
 
 __maintainer__ = "Stefan Hajnoczi"
@@ -34,13 +34,23 @@ def generate(events, backend):
     out('    TRACE_EVENT_COUNT',
         '} TraceEventID;')
 
+    # per-vCPU event identifiers
+    out('typedef enum {')
+
+    for e in events:
+        if "vcpu" in e.properties and "tcg-exec" in e.properties:
+            out('    TRACE_CPU_%s,' % e.name.upper())
+
+    out('    TRACE_CPU_EVENT_COUNT',
+        '} TraceEventCPUID;')
+
     # static state
     for e in events:
         if 'disable' in e.properties:
             enabled = 0
         else:
             enabled = 1
-        if "tcg-trans" in e.properties:
+        if "tcg-exec" in e.properties:
             # a single define for the two "sub-events"
             out('#define TRACE_%(name)s_ENABLED %(enabled)d',
                 name=e.original.original.name.upper(),
diff --git a/trace/control-internal.h b/trace/control-internal.h
index 5a8df28..70e55df 100644
--- a/trace/control-internal.h
+++ b/trace/control-internal.h
@@ -1,7 +1,7 @@
 /*
  * Interface for configuring and controlling the state of tracing events.
  *
- * Copyright (C) 2011-2014 Lluís Vilanova <vilanova@ac.upc.edu>
+ * Copyright (C) 2011-2015 Lluís Vilanova <vilanova@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.
@@ -39,6 +39,12 @@ static inline TraceEventID trace_event_get_id(TraceEvent *ev)
     return ev->id;
 }
 
+static inline TraceEventCPUID trace_event_get_cpu_id(TraceEvent *ev)
+{
+    assert(ev != NULL);
+    return ev->cpu_id;
+}
+
 static inline const char * trace_event_get_name(TraceEvent *ev)
 {
     assert(ev != NULL);
diff --git a/trace/control.h b/trace/control.h
index 275a086..a0bfd3e 100644
--- a/trace/control.h
+++ b/trace/control.h
@@ -87,6 +87,13 @@ static TraceEventID trace_event_count(void);
 static TraceEventID trace_event_get_id(TraceEvent *ev);
 
 /**
+ * trace_event_get_cpu_id:
+ *
+ * Get the per-vCPU identifier of an event.
+ */
+static TraceEventCPUID trace_event_get_cpu_id(TraceEvent *ev);
+
+/**
  * trace_event_get_name:
  *
  * Get the name of an event.
diff --git a/trace/event-internal.h b/trace/event-internal.h
index b2310d9..ae18b48 100644
--- a/trace/event-internal.h
+++ b/trace/event-internal.h
@@ -1,7 +1,7 @@
 /*
  * Interface for configuring and controlling the state of tracing events.
  *
- * Copyright (C) 2012 Lluís Vilanova <vilanova@ac.upc.edu>
+ * Copyright (C) 2012-2015 Lluís Vilanova <vilanova@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.
@@ -16,6 +16,7 @@
 /**
  * TraceEvent:
  * @id: Unique event identifier.
+ * @cpu_id: Unique per-vCPU event identifier.
  * @name: Event name.
  * @sstate: Static tracing state.
  * @dstate: Dynamic tracing state.
@@ -24,6 +25,7 @@
  */
 typedef struct TraceEvent {
     TraceEventID id;
+    TraceEventCPUID cpu_id;
     const char * name;
     const bool sstate;
     bool dstate;
diff --git a/trace/qmp.c b/trace/qmp.c
index 0b19489..b5a5020 100644
--- a/trace/qmp.c
+++ b/trace/qmp.c
@@ -1,7 +1,7 @@
 /*
  * QMP commands for tracing events.
  *
- * Copyright (C) 2014 Lluís Vilanova <vilanova@ac.upc.edu>
+ * Copyright (C) 2014-2015 Lluís Vilanova <vilanova@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.
@@ -22,6 +22,7 @@ TraceEventInfoList *qmp_trace_event_get_state(const char *name, Error **errp)
     while ((ev = trace_event_pattern(name, ev)) != NULL) {
         TraceEventInfoList *elem = g_new(TraceEventInfoList, 1);
         elem->value = g_new(TraceEventInfo, 1);
+        elem->value->vcpu = trace_event_get_cpu_id(ev) != TRACE_CPU_EVENT_COUNT;
         elem->value->name = g_strdup(trace_event_get_name(ev));
         if (!trace_event_get_state_static(ev)) {
             elem->value->state = TRACE_EVENT_STATE_UNAVAILABLE;

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v2 04/10] exec: [tcg] Refactor flush of per-CPU virtual TB cache
  2015-11-24 17:08 [Qemu-devel] [PATCH v2 00/10] trace: Per-vCPU tracing states Lluís Vilanova
                   ` (2 preceding siblings ...)
  2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 03/10] trace: [tcg] Identify events with the 'vcpu' property Lluís Vilanova
@ 2015-11-24 17:09 ` Lluís Vilanova
  2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 05/10] exec: [ŧcg] Use multiple physical TB caches Lluís Vilanova
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 20+ messages in thread
From: Lluís Vilanova @ 2015-11-24 17:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi, Eduardo Habkost

The function is reused in later patches.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 cputlb.c                |    2 +-
 include/exec/exec-all.h |    6 ++++++
 translate-all.c         |    7 ++++++-
 3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/cputlb.c b/cputlb.c
index bf1d50a..74bf989 100644
--- a/cputlb.c
+++ b/cputlb.c
@@ -61,7 +61,7 @@ void tlb_flush(CPUState *cpu, int flush_global)
 
     memset(env->tlb_table, -1, sizeof(env->tlb_table));
     memset(env->tlb_v_table, -1, sizeof(env->tlb_v_table));
-    memset(cpu->tb_jmp_cache, 0, sizeof(cpu->tb_jmp_cache));
+    tb_flush_jmp_cache_all(cpu);
 
     env->vtlb_index = 0;
     env->tlb_flush_addr = -1;
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index d900b0d..0859873 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -238,6 +238,12 @@ struct TBContext {
 };
 
 void tb_free(TranslationBlock *tb);
+/**
+ * tb_flush_jmp_cache_all:
+ *
+ * Flush the virtual translation block cache.
+ */
+void tb_flush_jmp_cache_all(CPUState *env);
 void tb_flush(CPUState *cpu);
 void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr);
 
diff --git a/translate-all.c b/translate-all.c
index a940bd2..ca4ea7f 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -846,7 +846,7 @@ void tb_flush(CPUState *cpu)
     tcg_ctx.tb_ctx.nb_tbs = 0;
 
     CPU_FOREACH(cpu) {
-        memset(cpu->tb_jmp_cache, 0, sizeof(cpu->tb_jmp_cache));
+        tb_flush_jmp_cache_all(cpu);
     }
 
     memset(tcg_ctx.tb_ctx.tb_phys_hash, 0, sizeof(tcg_ctx.tb_ctx.tb_phys_hash));
@@ -1586,6 +1586,11 @@ void tb_check_watchpoint(CPUState *cpu)
     }
 }
 
+void tb_flush_jmp_cache_all(CPUState *cpu)
+{
+    memset(cpu->tb_jmp_cache, 0, sizeof(cpu->tb_jmp_cache));
+}
+
 #ifndef CONFIG_USER_ONLY
 /* in deterministic execution mode, instructions doing device I/Os
    must be at the end of the TB */

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v2 05/10] exec: [ŧcg] Use multiple physical TB caches
  2015-11-24 17:08 [Qemu-devel] [PATCH v2 00/10] trace: Per-vCPU tracing states Lluís Vilanova
                   ` (3 preceding siblings ...)
  2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 04/10] exec: [tcg] Refactor flush of per-CPU virtual TB cache Lluís Vilanova
@ 2015-11-24 17:09 ` Lluís Vilanova
  2016-01-07  7:49   ` Stefan Hajnoczi
  2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 06/10] exec: [tcg] Track which vCPU is performing translation and execution Lluís Vilanova
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 20+ messages in thread
From: Lluís Vilanova @ 2015-11-24 17:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi, Eduardo Habkost, Andreas Färber

The physical translation block cache is split into as many caches as wanted, and
the virtual TB cache on each guest CPU uses a (potentially) different physical
TB cache.

This is later exploited to support different tracing event states on a per-vCPU
basis.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 cpu-exec.c              |   17 +++++
 include/exec/exec-all.h |   10 +++
 include/qom/cpu.h       |    5 ++
 qom/cpu.c               |    9 +++
 translate-all.c         |  146 +++++++++++++++++++++++++++++++++++++++++------
 translate-all.h         |   49 ++++++++++++++++
 6 files changed, 214 insertions(+), 22 deletions(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index c88d0ff..c258f16 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -27,6 +27,7 @@
 #include "exec/address-spaces.h"
 #include "qemu/rcu.h"
 #include "exec/tb-hash.h"
+#include "translate-all.h"
 #if defined(TARGET_I386) && !defined(CONFIG_USER_ONLY)
 #include "hw/i386/apic.h"
 #endif
@@ -224,7 +225,7 @@ static TranslationBlock *tb_find_physical(CPUState *cpu,
     phys_pc = get_page_addr_code(env, pc);
     phys_page1 = phys_pc & TARGET_PAGE_MASK;
     h = tb_phys_hash_func(phys_pc);
-    ptb1 = &tcg_ctx.tb_ctx.tb_phys_hash[h];
+    ptb1 = &tcg_ctx.tb_ctx.tb_phys_hash[cpu->tb_phys_idx][h];
     for(;;) {
         tb = *ptb1;
         if (!tb) {
@@ -253,8 +254,8 @@ static TranslationBlock *tb_find_physical(CPUState *cpu,
 
     /* Move the TB to the head of the list */
     *ptb1 = tb->phys_hash_next;
-    tb->phys_hash_next = tcg_ctx.tb_ctx.tb_phys_hash[h];
-    tcg_ctx.tb_ctx.tb_phys_hash[h] = tb;
+    tb->phys_hash_next = tcg_ctx.tb_ctx.tb_phys_hash[cpu->tb_phys_idx][h];
+    tcg_ctx.tb_ctx.tb_phys_hash[cpu->tb_phys_idx][h] = tb;
     return tb;
 }
 
@@ -488,6 +489,16 @@ int cpu_exec(CPUState *cpu)
                     cpu->exception_index = EXCP_INTERRUPT;
                     cpu_loop_exit(cpu);
                 }
+                if (unlikely(tcg_ctx.tb_ctx.tb_phys_hash_size_req !=
+                             tcg_ctx.tb_ctx.tb_phys_hash_size)) {
+                    if (tb_caches_apply() < 0) {
+                        next_tb = 0;
+                    }
+                }
+                if (unlikely(cpu->tb_phys_idx != cpu->tb_phys_idx_req)) {
+                    cpu_tb_cache_apply(cpu);
+                    next_tb = 0;
+                }
                 tb_lock();
                 tb = tb_find_fast(cpu);
                 /* Note: we do it here to avoid a gcc bug on Mac OS X when
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 0859873..ba8b15c 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -177,6 +177,10 @@ static inline void tlb_flush_by_mmuidx(CPUState *cpu, ...)
 #define USE_DIRECT_JUMP
 #endif
 
+/**
+ * TranslationBlock:
+ * @phys_idx: Index of physical TB cache where this TB has been allocated.
+ */
 struct TranslationBlock {
     target_ulong pc;   /* simulated PC corresponding to this block (EIP + CS base) */
     target_ulong cs_base; /* CS base for this block */
@@ -216,6 +220,8 @@ struct TranslationBlock {
        jmp_first */
     struct TranslationBlock *jmp_next[2];
     struct TranslationBlock *jmp_first;
+
+    unsigned int phys_idx;
 };
 
 #include "qemu/thread.h"
@@ -225,7 +231,9 @@ typedef struct TBContext TBContext;
 struct TBContext {
 
     TranslationBlock *tbs;
-    TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
+    TranslationBlock ***tb_phys_hash;
+    size_t tb_phys_hash_size;
+    size_t tb_phys_hash_size_req;
     int nb_tbs;
     /* any access to the tbs or the page table must use this lock */
     QemuMutex tb_lock;
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 51a1323..40962e0 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -250,6 +250,8 @@ struct kvm_run;
  * @kvm_fd: vCPU file descriptor for KVM.
  * @work_mutex: Lock to prevent multiple access to queued_work_*.
  * @queued_work_first: First asynchronous work pending.
+ * @tb_phys_idx: Index of current phsyical TB cache.
+ * @tb_phys_idx_req: Index of requested phsyical TB cache.
  *
  * State of one CPU core or thread.
  */
@@ -314,6 +316,9 @@ struct CPUState {
     struct KVMState *kvm_state;
     struct kvm_run *kvm_run;
 
+    unsigned int tb_phys_idx;
+    unsigned int tb_phys_idx_req;
+
     /* TODO Move common fields from CPUArchState here. */
     int cpu_index; /* used by alpha TCG */
     uint32_t halted; /* used by alpha, cris, ppc TCG */
diff --git a/qom/cpu.c b/qom/cpu.c
index fb80d13..bb7a618 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -363,6 +363,14 @@ static void cpu_class_init(ObjectClass *klass, void *data)
     dc->cannot_instantiate_with_device_add_yet = true;
 }
 
+static void cpu_init(Object *obj)
+{
+    CPUState *cpu = CPU(obj);
+
+    cpu->tb_phys_idx = 0;
+    cpu->tb_phys_idx_req = 0;
+}
+
 static const TypeInfo cpu_type_info = {
     .name = TYPE_CPU,
     .parent = TYPE_DEVICE,
@@ -372,6 +380,7 @@ static const TypeInfo cpu_type_info = {
     .abstract = true,
     .class_size = sizeof(CPUClass),
     .class_init = cpu_class_init,
+    .instance_init = cpu_init,
 };
 
 static void cpu_register_types(void)
diff --git a/translate-all.c b/translate-all.c
index ca4ea7f..9704efa 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -163,9 +163,22 @@ static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
                          tb_page_addr_t phys_page2);
 static TranslationBlock *tb_find_pc(uintptr_t tc_ptr);
 
+static void tb_phys_cache_alloc(unsigned int idx)
+{
+    size_t size = sizeof(tcg_ctx.tb_ctx.tb_phys_hash[0][0]) *
+        CODE_GEN_PHYS_HASH_SIZE;
+    tcg_ctx.tb_ctx.tb_phys_hash[idx] = malloc(size);
+    memset(tcg_ctx.tb_ctx.tb_phys_hash[idx], 0, size);
+}
+
 void cpu_gen_init(void)
 {
     tcg_context_init(&tcg_ctx); 
+
+    tcg_ctx.tb_ctx.tb_phys_hash_size = 0;
+    tcg_ctx.tb_ctx.tb_phys_hash_size_req = 1;
+    tcg_ctx.tb_ctx.tb_phys_hash = NULL;
+    tb_caches_apply();
 }
 
 /* Encode VAL as a signed leb128 sequence at P.
@@ -849,7 +862,12 @@ void tb_flush(CPUState *cpu)
         tb_flush_jmp_cache_all(cpu);
     }
 
-    memset(tcg_ctx.tb_ctx.tb_phys_hash, 0, sizeof(tcg_ctx.tb_ctx.tb_phys_hash));
+    unsigned int cache;
+    for (cache = 0; cache < tb_caches_get(); cache++) {
+        memset(tcg_ctx.tb_ctx.tb_phys_hash[cache], 0,
+               (sizeof(tcg_ctx.tb_ctx.tb_phys_hash[0][0]) *
+                CODE_GEN_PHYS_HASH_SIZE));
+    }
     page_flush_tb();
 
     tcg_ctx.code_gen_ptr = tcg_ctx.code_gen_buffer;
@@ -863,16 +881,21 @@ void tb_flush(CPUState *cpu)
 static void tb_invalidate_check(target_ulong address)
 {
     TranslationBlock *tb;
+    unsigned int cache;
     int i;
 
     address &= TARGET_PAGE_MASK;
-    for (i = 0; i < CODE_GEN_PHYS_HASH_SIZE; i++) {
-        for (tb = tb_ctx.tb_phys_hash[i]; tb != NULL; tb = tb->phys_hash_next) {
-            if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
-                  address >= tb->pc + tb->size)) {
-                printf("ERROR invalidate: address=" TARGET_FMT_lx
-                       " PC=%08lx size=%04x\n",
-                       address, (long)tb->pc, tb->size);
+    for (cache = 0; cache < tb_caches_get(); cache++) {
+        for (i = 0; i < CODE_GEN_PHYS_HASH_SIZE; i++) {
+            for (tb = tb_phys_hash[cache][i];
+                 tb != NULL;
+                 tb = tb->phys_hash_next) {
+                if (!(address + TARGET_PAGE_SIZE <= tb->pc ||
+                      address >= tb->pc + tb->size)) {
+                    printf("ERROR invalidate: address=" TARGET_FMT_lx
+                           " PC=%08lx size=%04x\n",
+                           address, (long)tb->pc, tb->size);
+                }
             }
         }
     }
@@ -882,16 +905,20 @@ static void tb_invalidate_check(target_ulong address)
 static void tb_page_check(void)
 {
     TranslationBlock *tb;
+    unsigned int cache;
     int i, flags1, flags2;
 
-    for (i = 0; i < CODE_GEN_PHYS_HASH_SIZE; i++) {
-        for (tb = tcg_ctx.tb_ctx.tb_phys_hash[i]; tb != NULL;
-                tb = tb->phys_hash_next) {
-            flags1 = page_get_flags(tb->pc);
-            flags2 = page_get_flags(tb->pc + tb->size - 1);
-            if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
-                printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
-                       (long)tb->pc, tb->size, flags1, flags2);
+    for (cache = 0; cache < tb_caches_get(); cache++) {
+        for (i = 0; i < CODE_GEN_PHYS_HASH_SIZE; i++) {
+            for (tb = tb_phys_hash[cache][i];
+                 tb != NULL;
+                 tb = tb->phys_hash_next) {
+                flags1 = page_get_flags(tb->pc);
+                flags2 = page_get_flags(tb->pc + tb->size - 1);
+                if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) {
+                    printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n",
+                           (long)tb->pc, tb->size, flags1, flags2);
+                }
             }
         }
     }
@@ -978,7 +1005,7 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr)
     /* remove the TB from the hash list */
     phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK);
     h = tb_phys_hash_func(phys_pc);
-    tb_hash_remove(&tcg_ctx.tb_ctx.tb_phys_hash[h], tb);
+    tb_hash_remove(&tcg_ctx.tb_ctx.tb_phys_hash[tb->phys_idx][h], tb);
 
     /* remove the TB from the page list */
     if (tb->page_addr[0] != page_addr) {
@@ -1053,6 +1080,86 @@ static void build_page_bitmap(PageDesc *p)
     }
 }
 
+size_t tb_caches_get(void)
+{
+    return tcg_ctx.tb_ctx.tb_phys_hash_size;
+}
+
+void tb_caches_set(size_t count)
+{
+    assert(count > 0);
+#ifndef NDEBUG
+    /* ensure no CPU is going to switch/stay in one of the removed caches */
+    CPUState *cpu;
+    CPU_FOREACH(cpu) {
+        assert(cpu->tb_phys_idx_req < count);
+    }
+#endif
+    tcg_ctx.tb_ctx.tb_phys_hash_size_req = count;
+}
+
+int tb_caches_apply(void)
+{
+    struct TBContext *tb_ctx = &tcg_ctx.tb_ctx;
+
+    if (likely(tb_ctx->tb_phys_hash_size_req == tb_ctx->tb_phys_hash_size)) {
+        return 0;
+    }
+
+    int res = tb_ctx->tb_phys_hash_size_req < tb_ctx->tb_phys_hash_size ?
+        -1 : 1;
+
+    if (res < 0) {
+        int i;
+        for (i = tb_ctx->tb_phys_hash_size_req;
+             i < tb_ctx->tb_phys_hash_size;
+             i++) {
+            free(tb_ctx->tb_phys_hash[i]);
+        }
+
+        CPUState *cpu;
+        CPU_FOREACH(cpu) {
+            if (cpu->tb_phys_idx >= tb_ctx->tb_phys_hash_size_req) {
+                fprintf(stderr,
+                        "CPU %d is using a deleted TB cache\n", cpu->cpu_index);
+                exit(1);
+            }
+        }
+    }
+
+    size_t size = sizeof(tb_ctx->tb_phys_hash[0]) *
+        tb_ctx->tb_phys_hash_size_req;
+    tb_ctx->tb_phys_hash = realloc(tb_ctx->tb_phys_hash, size);
+    int i;
+    for (i = tb_ctx->tb_phys_hash_size;
+         i < tb_ctx->tb_phys_hash_size_req;
+         i++) {
+        tb_phys_cache_alloc(i);
+    }
+
+    tb_ctx->tb_phys_hash_size = tb_ctx->tb_phys_hash_size_req;
+    return res;
+}
+
+unsigned int cpu_tb_cache_get(CPUState *cpu)
+{
+    return cpu->tb_phys_idx;
+}
+
+void cpu_tb_cache_set(CPUState *cpu, unsigned int index)
+{
+    assert(index < tcg_ctx.tb_ctx.tb_phys_hash_size_req);
+    cpu->tb_phys_idx_req = index;
+    cpu->tcg_exit_req = true;
+}
+
+void cpu_tb_cache_apply(CPUState *cpu)
+{
+    cpu->tb_phys_idx = cpu->tb_phys_idx_req;
+    tb_flush_jmp_cache_all(cpu);
+}
+
+
 /* Called with mmap_lock held for user mode emulation.  */
 TranslationBlock *tb_gen_code(CPUState *cpu,
                               target_ulong pc, target_ulong cs_base,
@@ -1090,6 +1197,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
     tb->cs_base = cs_base;
     tb->flags = flags;
     tb->cflags = cflags;
+    tb->phys_idx = ENV_GET_CPU(env)->tb_phys_idx;
 
 #ifdef CONFIG_PROFILER
     tcg_ctx.tb_count1++; /* includes aborted translations because of
@@ -1480,7 +1588,7 @@ static void tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
 
     /* add in the physical hash table */
     h = tb_phys_hash_func(phys_pc);
-    ptb = &tcg_ctx.tb_ctx.tb_phys_hash[h];
+    ptb = &tcg_ctx.tb_ctx.tb_phys_hash[tb->phys_idx][h];
     tb->phys_hash_next = *ptb;
     *ptb = tb;
 
@@ -1643,6 +1751,8 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
     pc = tb->pc;
     cs_base = tb->cs_base;
     flags = tb->flags;
+    /* XXX: It is OK to invalidate only this TB, as this is the one triggering
+     * the memory access */
     tb_phys_invalidate(tb, -1);
     if (tb->cflags & CF_NOCACHE) {
         if (tb->orig_tb) {
diff --git a/translate-all.h b/translate-all.h
index 0384640..d7ad063 100644
--- a/translate-all.h
+++ b/translate-all.h
@@ -19,6 +19,55 @@
 #ifndef TRANSLATE_ALL_H
 #define TRANSLATE_ALL_H
 
+
+/**
+ * tb_caches_get:
+ *
+ * Number of physical TB caches.
+ */
+size_t tb_caches_get(void);
+/**
+ * tb_caches_set:
+ *
+ * Request a new number of physical TB caches.
+ */
+void tb_caches_set(size_t count);
+/**
+ * tb_caches_apply:
+ *
+ * Apply the changes for a tb_caches_set() request.
+ *
+ * Returns: -1/1 if the number of caches has been shrinked/grown; 0 otherwise.
+ *
+ * Note: All TBs of eliminated caches are invalidated.
+ *
+ * Precondition: No vCPU uses any of the caches that will be removed (if any;
+ *               see cpu_tb_cache_set() and tb_caches_set()).
+ */
+int tb_caches_apply(void);
+/**
+ * cpu_tb_cache_get:
+ *
+ * Get the physical TB cache index for the given CPU.
+ */
+unsigned int cpu_tb_cache_get(CPUState *cpu);
+/**
+ * cpu_tb_cache_set:
+ *
+ * Set the physical TB cache index for the given CPU.
+ *
+ * Will have effect at the beginning of the next executed TB.
+ */
+void cpu_tb_cache_set(CPUState *cpu, unsigned int index);
+/**
+ * cpu_tb_cache_apply:
+ *
+ * Apply the changes for a cpu_tb_cache_set() request.
+ *
+ * Note: Invalidates the jump cache of the given CPU.
+ */
+void cpu_tb_cache_apply(CPUState *env);
+
 /* translate-all.c */
 void tb_invalidate_phys_page_fast(tb_page_addr_t start, int len);
 void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v2 06/10] exec: [tcg] Track which vCPU is performing translation and execution
  2015-11-24 17:08 [Qemu-devel] [PATCH v2 00/10] trace: Per-vCPU tracing states Lluís Vilanova
                   ` (4 preceding siblings ...)
  2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 05/10] exec: [ŧcg] Use multiple physical TB caches Lluís Vilanova
@ 2015-11-24 17:09 ` Lluís Vilanova
  2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 07/10] [trivial] Track when QEMU has finished initialization Lluís Vilanova
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 20+ messages in thread
From: Lluís Vilanova @ 2015-11-24 17:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Guan Xuetao, Eduardo Habkost, Stefan Hajnoczi,
	Anthony Green, Mark Cave-Ayland, Jia Liu, Alexander Graf,
	Blue Swirl, Max Filippov, Michael Walle, Leon Alrae,
	open list:PowerPC, open list:ARM, Paolo Bonzini,
	Edgar E. Iglesias, Bastian Koppelmann, Aurelien Jarno,
	Richard Henderson

Information is tracked inside the TCGContext structure, and later used
by tracing events with the 'tcg' and 'vcpu' properties.

The 'cpu' field is used to check tracing of translation-time
events ("*_trans"). The 'tcg_env' field is used to pass it to
execution-time events ("*_exec").

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 target-alpha/translate.c      |    1 +
 target-arm/translate.c        |    1 +
 target-cris/translate.c       |    1 +
 target-cris/translate_v10.c   |    1 +
 target-i386/translate.c       |    1 +
 target-lm32/translate.c       |    1 +
 target-m68k/translate.c       |    1 +
 target-microblaze/translate.c |    1 +
 target-mips/translate.c       |    1 +
 target-moxie/translate.c      |    1 +
 target-openrisc/translate.c   |    1 +
 target-ppc/translate.c        |    1 +
 target-s390x/translate.c      |    1 +
 target-sh4/translate.c        |    1 +
 target-sparc/translate.c      |    1 +
 target-tilegx/translate.c     |    1 +
 target-tricore/translate.c    |    1 +
 target-unicore32/translate.c  |    1 +
 target-xtensa/translate.c     |    1 +
 tcg/tcg.h                     |    4 ++++
 translate-all.c               |    2 ++
 21 files changed, 25 insertions(+)

diff --git a/target-alpha/translate.c b/target-alpha/translate.c
index d631f74..b5e2256 100644
--- a/target-alpha/translate.c
+++ b/target-alpha/translate.c
@@ -148,6 +148,7 @@ void alpha_translate_init(void)
     done_init = 1;
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    tcg_ctx.tcg_env = cpu_env;
 
     for (i = 0; i < 31; i++) {
         cpu_std_ir[i] = tcg_global_mem_new_i64(TCG_AREG0,
diff --git a/target-arm/translate.c b/target-arm/translate.c
index e672092..9828a84 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -87,6 +87,7 @@ void arm_translate_init(void)
     int i;
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    tcg_ctx.tcg_env = cpu_env;
 
     for (i = 0; i < 16; i++) {
         cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
diff --git a/target-cris/translate.c b/target-cris/translate.c
index fdcbfc6..e7e3f6c 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3360,6 +3360,7 @@ void cris_initialize_tcg(void)
     int i;
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    tcg_ctx.tcg_env = cpu_env;
     cc_x = tcg_global_mem_new(TCG_AREG0,
                               offsetof(CPUCRISState, cc_x), "cc_x");
     cc_src = tcg_global_mem_new(TCG_AREG0,
diff --git a/target-cris/translate_v10.c b/target-cris/translate_v10.c
index 3ab1c39..1ef8995 100644
--- a/target-cris/translate_v10.c
+++ b/target-cris/translate_v10.c
@@ -1249,6 +1249,7 @@ void cris_initialize_crisv10_tcg(void)
 	int i;
 
 	cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+        tcg_ctx.tcg_env = cpu_env;
 	cc_x = tcg_global_mem_new(TCG_AREG0,
 				  offsetof(CPUCRISState, cc_x), "cc_x");
 	cc_src = tcg_global_mem_new(TCG_AREG0,
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 53a09f8..fe5e155 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -7863,6 +7863,7 @@ void optimize_flags_init(void)
     int i;
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    tcg_ctx.tcg_env = cpu_env;
     cpu_cc_op = tcg_global_mem_new_i32(TCG_AREG0,
                                        offsetof(CPUX86State, cc_op), "cc_op");
     cpu_cc_dst = tcg_global_mem_new(TCG_AREG0, offsetof(CPUX86State, cc_dst),
diff --git a/target-lm32/translate.c b/target-lm32/translate.c
index a333fc6..7cb786f 100644
--- a/target-lm32/translate.c
+++ b/target-lm32/translate.c
@@ -1189,6 +1189,7 @@ void lm32_translate_init(void)
     int i;
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    tcg_ctx.tcg_env = cpu_env;
 
     for (i = 0; i < ARRAY_SIZE(cpu_R); i++) {
         cpu_R[i] = tcg_global_mem_new(TCG_AREG0,
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index d68d615..6280da0 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -91,6 +91,7 @@ void m68k_tcg_init(void)
                                                  "EXCEPTION");
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    tcg_ctx.tcg_env = cpu_env;
 
     p = cpu_reg_names;
     for (i = 0; i < 8; i++) {
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 9f1586f..d587e7e 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1867,6 +1867,7 @@ void mb_tcg_init(void)
     int i;
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    tcg_ctx.tcg_env = cpu_env;
 
     env_debug = tcg_global_mem_new(TCG_AREG0, 
                     offsetof(CPUMBState, debug),
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 610ed7c..c3cdc63 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -19818,6 +19818,7 @@ void mips_tcg_init(void)
         return;
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    tcg_ctx.tcg_env = cpu_env;
     TCGV_UNUSED(cpu_gpr[0]);
     for (i = 1; i < 32; i++)
         cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
diff --git a/target-moxie/translate.c b/target-moxie/translate.c
index ab8f6a7..11277e0 100644
--- a/target-moxie/translate.c
+++ b/target-moxie/translate.c
@@ -109,6 +109,7 @@ void moxie_translate_init(void)
         return;
     }
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    tcg_ctx.tcg_env = cpu_env;
     cpu_pc = tcg_global_mem_new_i32(TCG_AREG0,
                                     offsetof(CPUMoxieState, pc), "$pc");
     for (i = 0; i < 16; i++)
diff --git a/target-openrisc/translate.c b/target-openrisc/translate.c
index 3d29369..de2a541 100644
--- a/target-openrisc/translate.c
+++ b/target-openrisc/translate.c
@@ -77,6 +77,7 @@ void openrisc_translate_init(void)
     int i;
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    tcg_ctx.tcg_env = cpu_env;
     cpu_sr = tcg_global_mem_new(TCG_AREG0,
                                 offsetof(CPUOpenRISCState, sr), "sr");
     env_flags = tcg_global_mem_new_i32(TCG_AREG0,
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 17f732a..10f3a04 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -85,6 +85,7 @@ void ppc_translate_init(void)
         return;
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    tcg_ctx.tcg_env = cpu_env;
 
     p = cpu_reg_names;
     cpu_reg_names_size = sizeof(cpu_reg_names);
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 262da89..8df75db 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -166,6 +166,7 @@ void s390x_translate_init(void)
     int i;
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    tcg_ctx.tcg_env = cpu_env;
     psw_addr = tcg_global_mem_new_i64(TCG_AREG0,
                                       offsetof(CPUS390XState, psw.addr),
                                       "psw_addr");
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index c3a8fbd..58d1624 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -98,6 +98,7 @@ void sh4_translate_init(void)
         return;
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    tcg_ctx.tcg_env = cpu_env;
 
     for (i = 0; i < 24; i++)
         cpu_gregs[i] = tcg_global_mem_new_i32(TCG_AREG0,
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 811519e..9b9f50f 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -5344,6 +5344,7 @@ void gen_intermediate_code_init(CPUSPARCState *env)
         inited = 1;
 
         cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+        tcg_ctx.tcg_env = cpu_env;
         cpu_regwptr = tcg_global_mem_new_ptr(TCG_AREG0,
                                              offsetof(CPUSPARCState, regwptr),
                                              "regwptr");
diff --git a/target-tilegx/translate.c b/target-tilegx/translate.c
index fb5413a..9ae6d72 100644
--- a/target-tilegx/translate.c
+++ b/target-tilegx/translate.c
@@ -2440,6 +2440,7 @@ void tilegx_tcg_init(void)
     int i;
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    tcg_ctx.tcg_env = cpu_env;
     cpu_pc = tcg_global_mem_new_i64(TCG_AREG0, offsetof(CPUTLGState, pc), "pc");
     for (i = 0; i < TILEGX_R_COUNT; i++) {
         cpu_regs[i] = tcg_global_mem_new_i64(TCG_AREG0,
diff --git a/target-tricore/translate.c b/target-tricore/translate.c
index 655db75..a56bf2c 100644
--- a/target-tricore/translate.c
+++ b/target-tricore/translate.c
@@ -8366,6 +8366,7 @@ void tricore_tcg_init(void)
         return;
     }
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    tcg_ctx.tcg_env = cpu_env;
     /* reg init */
     for (i = 0 ; i < 16 ; i++) {
         cpu_gpr_a[i] = tcg_global_mem_new(TCG_AREG0,
diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c
index 29c22f5..1c66ab2 100644
--- a/target-unicore32/translate.c
+++ b/target-unicore32/translate.c
@@ -72,6 +72,7 @@ void uc32_translate_init(void)
     int i;
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    tcg_ctx.tcg_env = cpu_env;
 
     for (i = 0; i < 32; i++) {
         cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
diff --git a/target-xtensa/translate.c b/target-xtensa/translate.c
index 5ad1244..f5bde6b 100644
--- a/target-xtensa/translate.c
+++ b/target-xtensa/translate.c
@@ -217,6 +217,7 @@ void xtensa_translate_init(void)
     int i;
 
     cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
+    tcg_ctx.tcg_env = cpu_env;
     cpu_pc = tcg_global_mem_new_i32(TCG_AREG0,
             offsetof(CPUXtensaState, pc), "pc");
 
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 1585551..0f5986d 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -572,6 +572,10 @@ struct TCGContext {
 
     TBContext tb_ctx;
 
+    /* Track which vCPU triggers events */
+    CPUState *cpu;                      /* *_trans */
+    TCGv_cpu tcg_env;                   /* *_exec  */
+
     /* The TCGBackendData structure is private to tcg-target.c.  */
     struct TCGBackendData *be;
 
diff --git a/translate-all.c b/translate-all.c
index 9704efa..decaadf 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -1205,6 +1205,8 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
     ti = profile_getclock();
 #endif
 
+    tcg_ctx.cpu = ENV_GET_CPU(env);
+
     tcg_func_start(&tcg_ctx);
 
     gen_intermediate_code(env, tb);

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v2 07/10] [trivial] Track when QEMU has finished initialization
  2015-11-24 17:08 [Qemu-devel] [PATCH v2 00/10] trace: Per-vCPU tracing states Lluís Vilanova
                   ` (5 preceding siblings ...)
  2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 06/10] exec: [tcg] Track which vCPU is performing translation and execution Lluís Vilanova
@ 2015-11-24 17:09 ` Lluís Vilanova
  2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 08/10] disas: Remove unused macro '_' Lluís Vilanova
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 20+ messages in thread
From: Lluís Vilanova @ 2015-11-24 17:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Eduardo Habkost, Stefan Hajnoczi, Riku Voipio, Blue Swirl, Paolo Bonzini

Later used to synchronize per-vCPU state of events enabled from command
line.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 Makefile.objs            |    2 +-
 bsd-user/main.c          |    1 +
 include/qemu-common.h    |    3 +++
 linux-user/main.c        |    1 +
 qemu-common.c            |   14 ++++++++++++++
 stubs/Makefile.objs      |    1 +
 stubs/qemu-common-stub.c |   21 +++++++++++++++++++++
 vl.c                     |    2 ++
 8 files changed, 44 insertions(+), 1 deletion(-)
 create mode 100644 qemu-common.c
 create mode 100644 stubs/qemu-common-stub.c

diff --git a/Makefile.objs b/Makefile.objs
index 77be052..d161060 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -2,7 +2,7 @@
 # Common libraries for tools and emulators
 stub-obj-y = stubs/
 util-obj-y = util/ qobject/ qapi/
-util-obj-y += qmp-introspect.o qapi-types.o qapi-visit.o qapi-event.o
+util-obj-y += qmp-introspect.o qapi-types.o qapi-visit.o qapi-event.o qemu-common.o
 
 #######################################################################
 # block-obj-y is code used by both qemu system emulation and qemu-img
diff --git a/bsd-user/main.c b/bsd-user/main.c
index adf2de0..eff37e0 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -1121,6 +1121,7 @@ int main(int argc, char **argv)
         gdbserver_start (gdbstub_port);
         gdb_handlesig(cpu, 0);
     }
+    qemu_initialized = true;
     cpu_loop(env);
     /* never exits */
     return 0;
diff --git a/include/qemu-common.h b/include/qemu-common.h
index 405364f..dccc0ac 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -35,6 +35,9 @@
 # error Unknown pointer size
 #endif
 
+/* Whether the system has finished initializing */
+extern bool qemu_initialized;
+
 void cpu_ticks_init(void);
 
 /* icount */
diff --git a/linux-user/main.c b/linux-user/main.c
index 8acfe0f..f80a01e 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -4663,6 +4663,7 @@ int main(int argc, char **argv, char **envp)
         }
         gdb_handlesig(cpu, 0);
     }
+    qemu_initialized = true;
     cpu_loop(env);
     /* never exits */
     return 0;
diff --git a/qemu-common.c b/qemu-common.c
new file mode 100644
index 0000000..4b5ca1a
--- /dev/null
+++ b/qemu-common.c
@@ -0,0 +1,14 @@
+/*
+ * Common symbol definitions for all tools and targets.
+ *
+ * Copyright (C) 2011-2015 Lluís Vilanova <vilanova@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.
+*/
+
+#include "qemu-common.h"
+
+
+/* Whether QEMU has been initialized. */
+bool qemu_initialized;
diff --git a/stubs/Makefile.objs b/stubs/Makefile.objs
index d7898a0..670585a 100644
--- a/stubs/Makefile.objs
+++ b/stubs/Makefile.objs
@@ -38,3 +38,4 @@ stub-obj-y += qmp_pc_dimm_device_list.o
 stub-obj-y += target-monitor-defs.o
 stub-obj-y += target-get-monitor-def.o
 stub-obj-y += vhost.o
+stub-obj-y += qemu-common-stub.o
diff --git a/stubs/qemu-common-stub.c b/stubs/qemu-common-stub.c
new file mode 100644
index 0000000..f34f019
--- /dev/null
+++ b/stubs/qemu-common-stub.c
@@ -0,0 +1,21 @@
+/*
+ * Common symbol definitions for all tools and targets.
+ *
+ * Copyright (C) 2011-2015 Lluís Vilanova <vilanova@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.
+*/
+
+#include "qemu-common.h"
+#include <qemu/module.h>
+
+
+static void do_qemu_initialized_init(void)
+{
+    /* Tools always consider QEMU as inited */
+    qemu_initialized = true;
+}
+
+/* Block is always inited on both tools (and targets) */
+block_init(do_qemu_initialized_init);
diff --git a/vl.c b/vl.c
index 525929b..7c56159 100644
--- a/vl.c
+++ b/vl.c
@@ -4681,6 +4681,8 @@ int main(int argc, char **argv, char **envp)
         }
     }
 
+    qemu_initialized = true;
+
     main_loop();
     replay_disable_events();
 

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v2 08/10] disas: Remove unused macro '_'
  2015-11-24 17:08 [Qemu-devel] [PATCH v2 00/10] trace: Per-vCPU tracing states Lluís Vilanova
                   ` (6 preceding siblings ...)
  2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 07/10] [trivial] Track when QEMU has finished initialization Lluís Vilanova
@ 2015-11-24 17:09 ` Lluís Vilanova
  2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 09/10] trace: [tcg] Add per-vCPU tracing states for events with the 'vcpu' property Lluís Vilanova
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 20+ messages in thread
From: Lluís Vilanova @ 2015-11-24 17:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Stefan Hajnoczi, Richard Henderson, Eduardo Habkost, Paolo Bonzini

Eliminates a future compilation error when UI code includes the tracing
headers (indirectly pulling "disas/bfd.h" through "qom/cpu.h") and
GLib's i18n '_' macro.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 disas/i386.c        |    2 +-
 include/disas/bfd.h |    1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/disas/i386.c b/disas/i386.c
index c63d4a0..a343fbc 100644
--- a/disas/i386.c
+++ b/disas/i386.c
@@ -3406,7 +3406,7 @@ static const struct dis386 three_byte_table[][256] = {
   }
 };
 
-#define INTERNAL_DISASSEMBLER_ERROR _("<internal disassembler error>")
+#define INTERNAL_DISASSEMBLER_ERROR "<internal disassembler error>"
 
 static void
 ckprefix (void)
diff --git a/include/disas/bfd.h b/include/disas/bfd.h
index a112e9c..a761d5b 100644
--- a/include/disas/bfd.h
+++ b/include/disas/bfd.h
@@ -477,7 +477,6 @@ int generic_symbol_at_address(bfd_vma, struct disassemble_info *);
   (INFO).disassembler_options = NULL, \
   (INFO).insn_info_valid = 0
 
-#define _(x) x
 #define ATTRIBUTE_UNUSED __attribute__((unused))
 
 /* from libbfd */

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v2 09/10] trace: [tcg] Add per-vCPU tracing states for events with the 'vcpu' property
  2015-11-24 17:08 [Qemu-devel] [PATCH v2 00/10] trace: Per-vCPU tracing states Lluís Vilanova
                   ` (7 preceding siblings ...)
  2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 08/10] disas: Remove unused macro '_' Lluís Vilanova
@ 2015-11-24 17:09 ` Lluís Vilanova
  2015-11-24 17:57   ` Eric Blake
  2016-01-07  8:03   ` Stefan Hajnoczi
  2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 10/10] trace: [tcg] Generate TCG code to trace guest events on a per-vCPU basis Lluís Vilanova
  2016-01-07  8:05 ` [Qemu-devel] [PATCH v2 00/10] trace: Per-vCPU tracing states Stefan Hajnoczi
  10 siblings, 2 replies; 20+ messages in thread
From: Lluís Vilanova @ 2015-11-24 17:09 UTC (permalink / raw)
  To: qemu-devel
  Cc: Eduardo Habkost, Stefan Hajnoczi, Markus Armbruster,
	Luiz Capitulino, Stefan Hajnoczi, Andreas Färber

Each event with the 'vcpu' property gets a per-vCPU dynamic tracing state.

The set of enabled events with the 'vcpu' and 'tcg' properties is used
to select a per-vCPU physical TB cache.  The number of events with both
properties is used to select the number of physical TB caches, and a
bitmap of the identifiers of such enabled events is used to select a
physical TB cache.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 Makefile.objs                            |    1 
 include/qom/cpu.h                        |    5 +
 monitor.c                                |    4 -
 qapi/trace.json                          |   13 ++-
 qmp-commands.hx                          |   17 +++-
 qom/cpu.c                                |   12 +++
 scripts/tracetool/format/h.py            |    1 
 scripts/tracetool/format/tcg_helper_c.py |   11 ++
 trace/Makefile.objs                      |    2 
 trace/control-internal.h                 |   13 ++-
 trace/control-stub.c                     |   29 ++++++
 trace/control-target.c                   |   69 +++++++++++++++
 trace/control.h                          |   54 ++++++++++++
 trace/event-internal.h                   |    2 
 trace/qmp.c                              |  138 +++++++++++++++++++++++++-----
 translate-all.c                          |    1 
 16 files changed, 330 insertions(+), 42 deletions(-)
 create mode 100644 trace/control-stub.c
 create mode 100644 trace/control-target.c

diff --git a/Makefile.objs b/Makefile.objs
index d161060..6a6ccfd 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -98,6 +98,7 @@ version-lobj-$(CONFIG_WIN32) += $(BUILD_DIR)/version.lo
 # tracing
 util-obj-y +=  trace/
 target-obj-y += trace/
+stub-obj-y += trace/
 
 ######################################################################
 # guest agent
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 40962e0..8cde56e 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -29,6 +29,7 @@
 #include "qemu/queue.h"
 #include "qemu/thread.h"
 #include "qemu/typedefs.h"
+#include "trace/generated-events.h"
 
 typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size,
                                      void *opaque);
@@ -319,6 +320,10 @@ struct CPUState {
     unsigned int tb_phys_idx;
     unsigned int tb_phys_idx_req;
 
+    /* Ensure 'tb_phys_idx' can encode event states as a bitmask */
+    bool too_many_tcg_vcpu_events[
+        TRACE_CPU_EVENT_COUNT > sizeof(unsigned int)*8 ? -1 : 0];
+
     /* TODO Move common fields from CPUArchState here. */
     int cpu_index; /* used by alpha TCG */
     uint32_t halted; /* used by alpha, cris, ppc TCG */
diff --git a/monitor.c b/monitor.c
index e4cf34e..d161895 100644
--- a/monitor.c
+++ b/monitor.c
@@ -888,7 +888,7 @@ static void hmp_trace_event(Monitor *mon, const QDict *qdict)
     bool new_state = qdict_get_bool(qdict, "option");
     Error *local_err = NULL;
 
-    qmp_trace_event_set_state(tp_name, new_state, true, true, &local_err);
+    qmp_trace_event_set_state(tp_name, new_state, true, true, false, 0, &local_err);
     if (local_err) {
         error_report_err(local_err);
     }
@@ -1047,7 +1047,7 @@ static void hmp_info_cpustats(Monitor *mon, const QDict *qdict)
 
 static void hmp_info_trace_events(Monitor *mon, const QDict *qdict)
 {
-    TraceEventInfoList *events = qmp_trace_event_get_state("*", NULL);
+    TraceEventInfoList *events = qmp_trace_event_get_state("*", false, 0, NULL);
     TraceEventInfoList *elem;
 
     for (elem = events; elem != NULL; elem = elem->next) {
diff --git a/qapi/trace.json b/qapi/trace.json
index 71cb96f..fca70ee 100644
--- a/qapi/trace.json
+++ b/qapi/trace.json
@@ -29,7 +29,7 @@
 #
 # @name: Event name.
 # @state: Tracing state.
-# @vcpu: Whether this is a per-vCPU event (since 2.5).
+# @vcpu: #optional Whether this is a per-vCPU event (since 2.5).
 #
 # Since 2.2
 ##
@@ -42,13 +42,18 @@
 # Query the state of events.
 #
 # @name: Event name pattern (case-sensitive glob).
+# @vcpu: #optional The vCPU to check (any by default; since 2.5).
 #
 # Returns: a list of @TraceEventInfo for the matching events
 #
+# For any event without the "vcpu" property:
+# - If @name is a pattern and @vcpu is set, events are ignored.
+# - If @name is not a pattern and @vcpu is set, an error is raised.
+#
 # Since 2.2
 ##
 { 'command': 'trace-event-get-state',
-  'data': {'name': 'str'},
+  'data': {'name': 'str', '*vcpu': 'int'},
   'returns': ['TraceEventInfo'] }
 
 ##
@@ -59,8 +64,10 @@
 # @name: Event name pattern (case-sensitive glob).
 # @enable: Whether to enable tracing.
 # @ignore-unavailable: #optional Do not match unavailable events with @name.
+# @vcpu: The vCPU to act upon (all by default; since 2.5).
 #
 # Since 2.2
 ##
 { 'command': 'trace-event-set-state',
-  'data': {'name': 'str', 'enable': 'bool', '*ignore-unavailable': 'bool'} }
+  'data': {'name': 'str', 'enable': 'bool', '*ignore-unavailable': 'bool',
+           '*vcpu': 'int'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 9d8b42f..72368ca 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -4510,7 +4510,7 @@ EQMP
 
     {
         .name       = "trace-event-get-state",
-        .args_type  = "name:s",
+        .args_type  = "name:s,vcpu:i?",
         .mhandler.cmd_new = qmp_marshal_trace_event_get_state,
     },
 
@@ -4520,6 +4520,11 @@ trace-event-get-state
 
 Query the state of events.
 
+Arguments:
+
+- "name": Event name pattern (json-string).
+- "vcpu": Specific vCPU to query, any vCPU by default (json-int, optional).
+
 Example:
 
 -> { "execute": "trace-event-get-state", "arguments": { "name": "qemu_memalign" } }
@@ -4528,7 +4533,7 @@ EQMP
 
     {
         .name       = "trace-event-set-state",
-        .args_type  = "name:s,enable:b,ignore-unavailable:b?",
+        .args_type  = "name:s,enable:b,ignore-unavailable:b?,vcpu:i?",
         .mhandler.cmd_new = qmp_marshal_trace_event_set_state,
     },
 
@@ -4538,6 +4543,13 @@ trace-event-set-state
 
 Set the state of events.
 
+Arguments:
+
+- "name": Event name pattern (json-string).
+- "enable": Whether to enable or disable the event (json-bool).
+- "ignore-unavailable": Whether to ignore errors for events that cannot be changed (json-bool, optional).
+- "vcpu": Specific vCPU to set, all vCPUs by default (json-int, optional).
+
 Example:
 
 -> { "execute": "trace-event-set-state", "arguments": { "name": "qemu_memalign", "enable": "true" } }
@@ -4606,7 +4618,6 @@ Move mouse pointer to absolute coordinates (20000, 400).
                { "type": "abs", "data" : { "axis": "X", "value" : 20000 } },
                { "type": "abs", "data" : { "axis": "Y", "value" : 400 } } ] } }
 <- { "return": {} }
-
 EQMP
 
     {
diff --git a/qom/cpu.c b/qom/cpu.c
index bb7a618..bc27381 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -25,6 +25,7 @@
 #include "qemu/log.h"
 #include "qemu/error-report.h"
 #include "sysemu/sysemu.h"
+#include "trace/control.h"
 
 bool cpu_exists(int64_t id)
 {
@@ -227,6 +228,17 @@ void cpu_dump_statistics(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
 void cpu_reset(CPUState *cpu)
 {
     CPUClass *klass = CPU_GET_CLASS(cpu);
+    TraceEvent *ev = NULL;
+
+    if (!qemu_initialized) {
+        /* trace enabled events on all initial vCPUs */
+        while ((ev = trace_event_pattern("*", ev)) != NULL) {
+            if (trace_event_get_cpu_id(ev) != TRACE_CPU_EVENT_COUNT &&
+                trace_event_get_state_dynamic(ev)) {
+                trace_event_set_state_dynamic(ev, true);
+            }
+        }
+    }
 
     if (klass->reset != NULL) {
         (*klass->reset)(cpu);
diff --git a/scripts/tracetool/format/h.py b/scripts/tracetool/format/h.py
index 01d8718..440f656 100644
--- a/scripts/tracetool/format/h.py
+++ b/scripts/tracetool/format/h.py
@@ -36,6 +36,7 @@ def generate(events, backend):
             args=e.args)
 
         if "disable" not in e.properties:
+            # NOTE: See note on 'trace_event_set_cpu_state()'.
             backend.generate(e)
 
         out('}')
diff --git a/scripts/tracetool/format/tcg_helper_c.py b/scripts/tracetool/format/tcg_helper_c.py
index 96655a0..0cb7f45 100644
--- a/scripts/tracetool/format/tcg_helper_c.py
+++ b/scripts/tracetool/format/tcg_helper_c.py
@@ -6,7 +6,7 @@ Generate trace/generated-helpers.c.
 """
 
 __author__     = "Lluís Vilanova <vilanova@ac.upc.edu>"
-__copyright__  = "Copyright 2012-2014, Lluís Vilanova <vilanova@ac.upc.edu>"
+__copyright__  = "Copyright 2012-2015, Lluís Vilanova <vilanova@ac.upc.edu>"
 __license__    = "GPL version 2 or (at your option) any later version"
 
 __maintainer__ = "Stefan Hajnoczi"
@@ -36,8 +36,13 @@ def generate(events, backend):
         # tracetool.generate always transforms types to host
         e_args = e.original.args
 
-        values = ["(%s)%s" % (t, n)
-                  for t, n in e.args.transform(TCG_2_TCG_HELPER_DEF)]
+        values = []
+        for (t_old, n), (t_new, _) in zip(
+                e.args, e.args.transform(TCG_2_TCG_HELPER_DEF)):
+            if t_old == "CPUState *":
+                values.append("ENV_GET_CPU((CPUArchState*)%s)" % n)
+            else:
+                values.append("(%s)%s" % (t_new, n))
 
         out('void %(name_tcg)s(%(args)s)',
             '{',
diff --git a/trace/Makefile.objs b/trace/Makefile.objs
index 32f7a32..15896de 100644
--- a/trace/Makefile.objs
+++ b/trace/Makefile.objs
@@ -144,4 +144,6 @@ util-obj-$(CONFIG_TRACE_SIMPLE) += simple.o generated-tracers.o
 util-obj-$(CONFIG_TRACE_FTRACE) += ftrace.o
 util-obj-$(CONFIG_TRACE_UST) += generated-ust.o
 util-obj-y += control.o
+target-obj-y += control-target.o
+stub-obj-y += control-stub.o
 util-obj-y += qmp.o
diff --git a/trace/control-internal.h b/trace/control-internal.h
index 70e55df..d551adf 100644
--- a/trace/control-internal.h
+++ b/trace/control-internal.h
@@ -12,6 +12,9 @@
 
 #include <string.h>
 
+#include "qemu-common.h"
+#include "qom/cpu.h"
+
 
 extern TraceEvent trace_events[];
 
@@ -60,14 +63,16 @@ static inline bool trace_event_get_state_static(TraceEvent *ev)
 static inline bool trace_event_get_state_dynamic(TraceEvent *ev)
 {
     assert(ev != NULL);
-    return ev->dstate;
+    /* no need to iterate over vCPUs, since the global dynamic state is always set */
+    return ev->dstate > 0;
 }
 
-static inline void trace_event_set_state_dynamic(TraceEvent *ev, bool state)
+static inline bool trace_event_get_cpu_state_dynamic(CPUState *cpu,
+                                                     TraceEvent *ev)
 {
+    assert(cpu != NULL);
     assert(ev != NULL);
-    assert(trace_event_get_state_static(ev));
-    ev->dstate = state;
+    return cpu->tb_phys_idx & (((unsigned long)1) << ev->cpu_id);
 }
 
 #endif  /* TRACE__CONTROL_INTERNAL_H */
diff --git a/trace/control-stub.c b/trace/control-stub.c
new file mode 100644
index 0000000..dd62d3b
--- /dev/null
+++ b/trace/control-stub.c
@@ -0,0 +1,29 @@
+/*
+ * Interface for configuring and controlling the state of tracing events.
+ *
+ * Copyright (C) 2014-2015 Lluís Vilanova <vilanova@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.
+ */
+
+#include "trace/control.h"
+
+
+void trace_init_vcpu_tb_caches(void)
+{
+}
+
+void trace_event_set_state_dynamic(TraceEvent *ev, bool state)
+{
+    assert(ev != NULL);
+    assert(trace_event_get_state_static(ev));
+    ev->dstate = state;
+}
+
+void trace_event_set_cpu_state_dynamic(CPUState *cpu,
+                                       TraceEvent *ev, bool state)
+{
+    /* should never be called on non-target binaries */
+    abort();
+}
diff --git a/trace/control-target.c b/trace/control-target.c
new file mode 100644
index 0000000..b586b4d
--- /dev/null
+++ b/trace/control-target.c
@@ -0,0 +1,69 @@
+/*
+ * Interface for configuring and controlling the state of tracing events.
+ *
+ * Copyright (C) 2014-2015 Lluís Vilanova <vilanova@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.
+ */
+
+#include "trace/control.h"
+#include "cpu.h"
+#include "translate-all.h"
+
+
+void trace_init_vcpu_tb_caches(void)
+{
+    unsigned int events = 1;
+    TraceEvent *ev = NULL;
+    while ((ev = trace_event_pattern("*", ev)) != NULL) {
+        if (trace_event_get_cpu_id(ev) == TRACE_CPU_EVENT_COUNT) {
+            continue;
+        }
+        events <<= 1;
+    }
+    tb_caches_set(events);
+    tb_caches_apply();
+}
+
+void trace_event_set_state_dynamic(TraceEvent *ev, bool state)
+{
+    CPUState *cpu;
+    assert(ev != NULL);
+    assert(trace_event_get_state_static(ev));
+    if (trace_event_get_cpu_id(ev) != TRACE_CPU_EVENT_COUNT) {
+        CPU_FOREACH(cpu) {
+            trace_event_set_cpu_state_dynamic(cpu, ev, state);
+        }
+    } else {
+        ev->dstate = state;
+    }
+}
+
+void trace_event_set_cpu_state_dynamic(CPUState *cpu,
+                                       TraceEvent *ev, bool state)
+{
+    /*
+     * NOTE: Does not immediately apply changes on all affected vCPUs, so
+     *       "tcg-exec" events might be generated after being disabled (until
+     *       the vCPU finishes a BBL and checks for event state changes).
+     */
+    unsigned int bit;
+    bool state_pre;
+    assert(cpu != NULL);
+    assert(ev != NULL);
+    assert(trace_event_get_state_static(ev));
+    assert(trace_event_get_cpu_id(ev) != TRACE_CPU_EVENT_COUNT);
+    bit = ((unsigned long)1) << ev->cpu_id;
+    /* must use the requested TB index in case it's not yet synchronized */
+    state_pre = cpu->tb_phys_idx_req & bit;
+    if ((state_pre == 0) != (state == 0)) {
+        if (state) {
+            cpu_tb_cache_set(cpu, (cpu->tb_phys_idx_req & ~bit) | bit);
+            ev->dstate++;
+        } else {
+            cpu_tb_cache_set(cpu, (cpu->tb_phys_idx_req & ~bit));
+            ev->dstate--;
+        }
+    }
+}
diff --git a/trace/control.h b/trace/control.h
index a0bfd3e..80501cd 100644
--- a/trace/control.h
+++ b/trace/control.h
@@ -115,6 +115,22 @@ static const char * trace_event_get_name(TraceEvent *ev);
     ((id ##_ENABLED) && trace_event_get_state_dynamic(trace_event_id(id)))
 
 /**
+ * trace_event_get_cpu_state:
+ * @id: Event identifier.
+ *
+ * Get the tracing state of an event (both static and dynamic) for the given
+ * vCPU.
+ *
+ * If the event has the disabled property, the check will have no performance
+ * impact.
+ *
+ * As a down side, you must always use an immediate #TraceEventID value.
+ */
+#define trace_event_get_cpu_state(cpu, id)                              \
+    ((id ##_ENABLED) && trace_event_get_cpu_state_dynamic(cpu,          \
+                                                          trace_event_id(id)))
+
+/**
  * trace_event_get_state_static:
  * @id: Event identifier.
  *
@@ -129,10 +145,19 @@ static bool trace_event_get_state_static(TraceEvent *ev);
  * trace_event_get_state_dynamic:
  *
  * Get the dynamic tracing state of an event.
+ *
+ * If the event has the 'vcpu' property, gets the OR'ed state of all vCPUs.
  */
 static bool trace_event_get_state_dynamic(TraceEvent *ev);
 
 /**
+ * trace_event_get_cpu_state_dynamic:
+ *
+ * Get the dynamic tracing state of an event for the given vCPU.
+ */
+static bool trace_event_get_cpu_state_dynamic(CPUState *cpu, TraceEvent *ev);
+
+/**
  * trace_event_set_state:
  *
  * Set the tracing state of an event (only if possible).
@@ -146,13 +171,38 @@ static bool trace_event_get_state_dynamic(TraceEvent *ev);
     } while (0)
 
 /**
+ * trace_event_set_cpu_state:
+ *
+ * Set the tracing state of an event for the given vCPU (only if possible).
+ */
+#define trace_event_set_cpu_state(cpu, id, state)               \
+    do {                                                        \
+        if ((id ##_ENABLED)) {                                  \
+            TraceEvent *_e = trace_event_id(id);                \
+            trace_event_set_cpu_state_dynamic(cpu, _e, state);  \
+        }                                                       \
+    } while (0)
+
+/**
  * trace_event_set_state_dynamic:
  *
  * Set the dynamic tracing state of an event.
  *
+ * If the event has the 'vcpu' property, sets the state on all vCPUs.
+ *
  * Pre-condition: trace_event_get_state_static(ev) == true
  */
-static void trace_event_set_state_dynamic(TraceEvent *ev, bool state);
+void trace_event_set_state_dynamic(TraceEvent *ev, bool state);
+
+/**
+ * trace_event_set_cpu_state_dynamic:
+ *
+ * Set the dynamic tracing state of an event for the given vCPU.
+ *
+ * Pre-condition: trace_event_get_cpu_state_static(ev) == true
+ */
+void trace_event_set_cpu_state_dynamic(CPUState *cpu,
+                                       TraceEvent *ev, bool state);
 
 
 
@@ -169,6 +219,8 @@ static void trace_event_set_state_dynamic(TraceEvent *ev, bool state);
  */
 bool trace_init_backends(const char *events, const char *file);
 
+void trace_init_vcpu_tb_caches(void);
+
 
 #include "trace/control-internal.h"
 
diff --git a/trace/event-internal.h b/trace/event-internal.h
index ae18b48..1e89210 100644
--- a/trace/event-internal.h
+++ b/trace/event-internal.h
@@ -28,7 +28,7 @@ typedef struct TraceEvent {
     TraceEventCPUID cpu_id;
     const char * name;
     const bool sstate;
-    bool dstate;
+    size_t dstate;
 } TraceEvent;
 
 
diff --git a/trace/qmp.c b/trace/qmp.c
index b5a5020..2d3515a 100644
--- a/trace/qmp.c
+++ b/trace/qmp.c
@@ -12,64 +12,152 @@
 #include "trace/control.h"
 
 
-TraceEventInfoList *qmp_trace_event_get_state(const char *name, Error **errp)
+static bool get_cpu_state(bool has_index, int index, CPUState **cpu, Error **errp)
+{
+    if (has_index) {
+        *cpu = qemu_get_cpu(index);
+        if (*cpu == NULL) {
+            error_setg(errp, "invalid vCPU index %u", index);
+            return false;
+        }
+    } else {
+        *cpu = NULL;
+    }
+    return true;
+}
+
+TraceEventInfoList *qmp_trace_event_get_state(const char *name,
+                                              bool has_vcpu, int64_t vcpu,
+                                              Error **errp)
 {
     TraceEventInfoList *events = NULL;
-    bool found = false;
     TraceEvent *ev;
+    bool is_pattern = trace_event_is_pattern(name);
+    CPUState *cpu;
+
+    if (!get_cpu_state(has_vcpu, vcpu, &cpu, errp)) {
+        return NULL;
+    }
 
     ev = NULL;
     while ((ev = trace_event_pattern(name, ev)) != NULL) {
-        TraceEventInfoList *elem = g_new(TraceEventInfoList, 1);
+        TraceEventInfoList *elem;
+        bool is_vcpu = trace_event_get_cpu_id(ev) != TRACE_CPU_EVENT_COUNT;
+        if (has_vcpu && !is_vcpu) {
+            if (!is_pattern) {
+                error_setg(errp, "event \"%s\" is not vCPU-specific", name);
+            }
+            /* else: ignore */
+            continue;
+        }
+
+        elem = g_new(TraceEventInfoList, 1);
         elem->value = g_new(TraceEventInfo, 1);
-        elem->value->vcpu = trace_event_get_cpu_id(ev) != TRACE_CPU_EVENT_COUNT;
+        elem->value->vcpu = is_vcpu;
         elem->value->name = g_strdup(trace_event_get_name(ev));
+
         if (!trace_event_get_state_static(ev)) {
             elem->value->state = TRACE_EVENT_STATE_UNAVAILABLE;
-        } else if (!trace_event_get_state_dynamic(ev)) {
-            elem->value->state = TRACE_EVENT_STATE_DISABLED;
         } else {
-            elem->value->state = TRACE_EVENT_STATE_ENABLED;
+            if (has_vcpu) {
+                if (is_vcpu) {
+                    if (trace_event_get_cpu_state_dynamic(cpu, ev)) {
+                        elem->value->state = TRACE_EVENT_STATE_ENABLED;
+                    } else {
+                        elem->value->state = TRACE_EVENT_STATE_DISABLED;
+                    }
+                }
+                /* else: already handled above */
+            } else {
+                if (trace_event_get_state_dynamic(ev)) {
+                    elem->value->state = TRACE_EVENT_STATE_ENABLED;
+                } else {
+                    elem->value->state = TRACE_EVENT_STATE_DISABLED;
+                }
+            }
         }
         elem->next = events;
         events = elem;
-        found = true;
     }
 
-    if (!found && !trace_event_is_pattern(name)) {
+    if (events == NULL && !is_pattern) {
         error_setg(errp, "unknown event \"%s\"", name);
     }
 
     return events;
 }
 
+
+static void check_events_are_dynamic(const char *name, bool per_cpu,
+                                     bool *found, bool error_check,
+                                     bool *error_found, Error **errp)
+{
+    TraceEvent *ev = NULL;
+    *found = false;
+    *error_found = false;
+    while ((ev = trace_event_pattern(name, ev)) != NULL) {
+        if (per_cpu && trace_event_get_cpu_id(ev) == TRACE_CPU_EVENT_COUNT) {
+            if (error_check) {
+                Error *local_err = NULL;
+                error_setg(&local_err, "event \"%s\" is not vCPU-specific",
+                           trace_event_get_name(ev));
+                error_propagate(errp, local_err);
+                *error_found = true;
+            }
+            continue;
+        }
+        if (!trace_event_get_state_static(ev)) {
+            if (error_check) {
+                Error *local_err = NULL;
+                error_setg(&local_err, "cannot set dynamic tracing state for \"%s\"",
+                           trace_event_get_name(ev));
+                error_propagate(errp, local_err);
+                *error_found = true;
+            }
+            continue;
+        }
+        *found = true;
+    }
+}
+
 void qmp_trace_event_set_state(const char *name, bool enable,
-                               bool has_ignore_unavailable,
-                               bool ignore_unavailable, Error **errp)
+                               bool has_ignore_unavailable, bool ignore_unavailable,
+                               bool has_vcpu, int64_t vcpu,
+                               Error **errp)
 {
-    bool found = false;
-    TraceEvent *ev;
+    bool error, found;
+    TraceEvent *ev = NULL;
+    CPUState *cpu;
+
+    if (!get_cpu_state(has_vcpu, vcpu, &cpu, errp)) {
+        return;
+    }
 
     /* Check all selected events are dynamic */
-    ev = NULL;
-    while ((ev = trace_event_pattern(name, ev)) != NULL) {
-        found = true;
-        if (!(has_ignore_unavailable && ignore_unavailable) &&
-            !trace_event_get_state_static(ev)) {
-            error_setg(errp, "cannot set dynamic tracing state for \"%s\"",
-                       trace_event_get_name(ev));
-            return;
-        }
+    check_events_are_dynamic(name, has_vcpu, &found,
+                             !(has_ignore_unavailable && ignore_unavailable),
+                             &error, errp);
+    if (error) {
+        return;
     }
-    if (!found && !trace_event_is_pattern(name)) {
-        error_setg(errp, "unknown event \"%s\"", name);
+    if (!found) {
+        if (!trace_event_is_pattern(name)) {
+            error_setg(errp, "unknown event \"%s\"", name);
+        }
         return;
     }
 
     /* Apply changes */
     ev = NULL;
     while ((ev = trace_event_pattern(name, ev)) != NULL) {
-        if (trace_event_get_state_static(ev)) {
+        if (!trace_event_get_state_static(ev) ||
+            (has_vcpu && trace_event_get_cpu_id(ev) == TRACE_CPU_EVENT_COUNT)) {
+            /* if it were an error, it was catched by the check above */
+            continue;
+        }
+        if (has_vcpu) {
+            trace_event_set_cpu_state_dynamic(cpu, ev, enable);
+        } else {
             trace_event_set_state_dynamic(ev, enable);
         }
     }
diff --git a/translate-all.c b/translate-all.c
index decaadf..8eb966f 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -179,6 +179,7 @@ void cpu_gen_init(void)
     tcg_ctx.tb_ctx.tb_phys_hash_size_req = 1;
     tcg_ctx.tb_ctx.tb_phys_hash = NULL;
     tb_caches_apply();
+    trace_init_vcpu_tb_caches();
 }
 
 /* Encode VAL as a signed leb128 sequence at P.

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH v2 10/10] trace: [tcg] Generate TCG code to trace guest events on a per-vCPU basis
  2015-11-24 17:08 [Qemu-devel] [PATCH v2 00/10] trace: Per-vCPU tracing states Lluís Vilanova
                   ` (8 preceding siblings ...)
  2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 09/10] trace: [tcg] Add per-vCPU tracing states for events with the 'vcpu' property Lluís Vilanova
@ 2015-11-24 17:09 ` Lluís Vilanova
  2016-01-07  8:05 ` [Qemu-devel] [PATCH v2 00/10] trace: Per-vCPU tracing states Stefan Hajnoczi
  10 siblings, 0 replies; 20+ messages in thread
From: Lluís Vilanova @ 2015-11-24 17:09 UTC (permalink / raw)
  To: qemu-devel; +Cc: Stefan Hajnoczi, Eduardo Habkost, Stefan Hajnoczi

Events with the 'tcg' and 'vcpu' properties will:

* Trace the translation-time event ('*_trans').
* Generate TCG code to call a function that traces the execution-time
  event ('*_exec') iff the event is enabled for that vCPU.

Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
---
 scripts/tracetool/format/tcg_h.py |    8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/scripts/tracetool/format/tcg_h.py b/scripts/tracetool/format/tcg_h.py
index 222002c..2ecfc53 100644
--- a/scripts/tracetool/format/tcg_h.py
+++ b/scripts/tracetool/format/tcg_h.py
@@ -32,7 +32,7 @@ def generate(events, backend):
 
     for e in events:
         # just keep one of them
-        if "tcg-trans" not in e.properties:
+        if "tcg-exec" not in e.properties:
             continue
 
         # get the original event definition
@@ -52,7 +52,11 @@ def generate(events, backend):
 
         if "disable" not in e.properties:
             out('    %(name_trans)s(%(argnames_trans)s);',
-                '    gen_helper_%(name_exec)s(%(argnames_exec)s);',
+                '    if (%(cond)s) {',
+                '        gen_helper_%(name_exec)s(%(argnames_exec)s);',
+                '    }',
+                cond='trace_event_get_cpu_state(_cpu, TRACE_%s)' % e.event_exec.name.upper()
+                     if "vcpu" in e.properties else "true",
                 name_trans=e.event_trans.api(e.QEMU_TRACE),
                 name_exec=e.event_exec.api(e.QEMU_TRACE),
                 argnames_trans=", ".join(e.event_trans.args.names()),

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v2 03/10] trace: [tcg] Identify events with the 'vcpu' property
  2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 03/10] trace: [tcg] Identify events with the 'vcpu' property Lluís Vilanova
@ 2015-11-24 17:54   ` Eric Blake
  0 siblings, 0 replies; 20+ messages in thread
From: Eric Blake @ 2015-11-24 17:54 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Stefan Hajnoczi, Eduardo Habkost, Stefan Hajnoczi, Markus Armbruster

[-- Attachment #1: Type: text/plain, Size: 1185 bytes --]

On 11/24/2015 10:09 AM, Lluís Vilanova wrote:
> A separate ID space ('TRACE_CPU_*') is used in attribute 'cpu_id' that
> only contains events with the 'vcpu' property.
> 
> These are later used to select the appropriate physical TB cache based
> on what events are active.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> ---

> +++ b/qapi/trace.json
> @@ -1,6 +1,6 @@
>  # -*- mode: python -*-
>  #
> -# Copyright (C) 2011-2014 Lluís Vilanova <vilanova@ac.upc.edu>
> +# Copyright (C) 2011-2015 Lluís Vilanova <vilanova@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.
> @@ -29,11 +29,12 @@
>  #
>  # @name: Event name.
>  # @state: Tracing state.
> +# @vcpu: Whether this is a per-vCPU event (since 2.5).

You've missed 2.5 hard freeze; this will need to be 2.6.

Also, I note that patch 9/10 touches the same line again to make it
optional; why not just have it be optional in the beginning, to reduce
churn within the series?

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v2 09/10] trace: [tcg] Add per-vCPU tracing states for events with the 'vcpu' property
  2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 09/10] trace: [tcg] Add per-vCPU tracing states for events with the 'vcpu' property Lluís Vilanova
@ 2015-11-24 17:57   ` Eric Blake
  2015-11-24 18:31     ` Lluís Vilanova
  2016-01-07  8:03   ` Stefan Hajnoczi
  1 sibling, 1 reply; 20+ messages in thread
From: Eric Blake @ 2015-11-24 17:57 UTC (permalink / raw)
  To: Lluís Vilanova, qemu-devel
  Cc: Eduardo Habkost, Stefan Hajnoczi, Markus Armbruster,
	Luiz Capitulino, Stefan Hajnoczi, Andreas Färber

[-- Attachment #1: Type: text/plain, Size: 1960 bytes --]

On 11/24/2015 10:09 AM, Lluís Vilanova wrote:
> Each event with the 'vcpu' property gets a per-vCPU dynamic tracing state.
> 
> The set of enabled events with the 'vcpu' and 'tcg' properties is used
> to select a per-vCPU physical TB cache.  The number of events with both
> properties is used to select the number of physical TB caches, and a
> bitmap of the identifiers of such enabled events is used to select a
> physical TB cache.
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> ---

> +++ b/qapi/trace.json
> @@ -29,7 +29,7 @@
>  #
>  # @name: Event name.
>  # @state: Tracing state.
> -# @vcpu: Whether this is a per-vCPU event (since 2.5).
> +# @vcpu: #optional Whether this is a per-vCPU event (since 2.5).
>  #
>  # Since 2.2
>  ##

Spurious hunk? It looks like vcpu is always present on output, and that
it is only...

> @@ -42,13 +42,18 @@
>  # Query the state of events.
>  #
>  # @name: Event name pattern (case-sensitive glob).
> +# @vcpu: #optional The vCPU to check (any by default; since 2.5).

...the new input place where it is optional.

2.6.

>  #
>  # Returns: a list of @TraceEventInfo for the matching events
>  #
> +# For any event without the "vcpu" property:
> +# - If @name is a pattern and @vcpu is set, events are ignored.
> +# - If @name is not a pattern and @vcpu is set, an error is raised.
> +#
>  # Since 2.2
>  ##
>  { 'command': 'trace-event-get-state',
> -  'data': {'name': 'str'},
> +  'data': {'name': 'str', '*vcpu': 'int'},
>    'returns': ['TraceEventInfo'] }
>  
>  ##
> @@ -59,8 +64,10 @@
>  # @name: Event name pattern (case-sensitive glob).
>  # @enable: Whether to enable tracing.
>  # @ignore-unavailable: #optional Do not match unavailable events with @name.
> +# @vcpu: The vCPU to act upon (all by default; since 2.5).

2.6

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v2 09/10] trace: [tcg] Add per-vCPU tracing states for events with the 'vcpu' property
  2015-11-24 17:57   ` Eric Blake
@ 2015-11-24 18:31     ` Lluís Vilanova
  0 siblings, 0 replies; 20+ messages in thread
From: Lluís Vilanova @ 2015-11-24 18:31 UTC (permalink / raw)
  To: Eric Blake
  Cc: Eduardo Habkost, Stefan Hajnoczi, qemu-devel, Luiz Capitulino,
	Stefan Hajnoczi, Andreas Färber, Markus Armbruster

Eric Blake writes:

> On 11/24/2015 10:09 AM, Lluís Vilanova wrote:
>> Each event with the 'vcpu' property gets a per-vCPU dynamic tracing state.
>> 
>> The set of enabled events with the 'vcpu' and 'tcg' properties is used
>> to select a per-vCPU physical TB cache.  The number of events with both
>> properties is used to select the number of physical TB caches, and a
>> bitmap of the identifiers of such enabled events is used to select a
>> physical TB cache.
>> 
>> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
>> ---

>> +++ b/qapi/trace.json
>> @@ -29,7 +29,7 @@
>> #
>> # @name: Event name.
>> # @state: Tracing state.
>> -# @vcpu: Whether this is a per-vCPU event (since 2.5).
>> +# @vcpu: #optional Whether this is a per-vCPU event (since 2.5).
>> #
>> # Since 2.2
>> ##

> Spurious hunk? It looks like vcpu is always present on output, and that
> it is only...

>> @@ -42,13 +42,18 @@
>> # Query the state of events.
>> #
>> # @name: Event name pattern (case-sensitive glob).
>> +# @vcpu: #optional The vCPU to check (any by default; since 2.5).

> ...the new input place where it is optional.

Whoops! Misplaced tag, thanks.

> 2.6.

Done.


Thanks,
  Lluis

-- 
"And it's much the same thing with knowledge, for whenever you learn
something new, the whole world becomes that much richer."
-- The Princess of Pure Reason, as told by Norton Juster in The Phantom
Tollbooth

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v2 05/10] exec: [ŧcg] Use multiple physical TB caches
  2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 05/10] exec: [ŧcg] Use multiple physical TB caches Lluís Vilanova
@ 2016-01-07  7:49   ` Stefan Hajnoczi
  2016-01-07 17:56     ` Lluís Vilanova
  0 siblings, 1 reply; 20+ messages in thread
From: Stefan Hajnoczi @ 2016-01-07  7:49 UTC (permalink / raw)
  To: Lluís Vilanova; +Cc: qemu-devel, Andreas Färber, Eduardo Habkost

[-- Attachment #1: Type: text/plain, Size: 170 bytes --]

On Tue, Nov 24, 2015 at 06:09:14PM +0100, Lluís Vilanova wrote:

Commit message uses 'LATIN SMALL LETTER T WITH STROKE' (U+0167) instead
of regular 't' character :).

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v2 09/10] trace: [tcg] Add per-vCPU tracing states for events with the 'vcpu' property
  2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 09/10] trace: [tcg] Add per-vCPU tracing states for events with the 'vcpu' property Lluís Vilanova
  2015-11-24 17:57   ` Eric Blake
@ 2016-01-07  8:03   ` Stefan Hajnoczi
  2016-01-07 18:44     ` Lluís Vilanova
  1 sibling, 1 reply; 20+ messages in thread
From: Stefan Hajnoczi @ 2016-01-07  8:03 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: Eduardo Habkost, qemu-devel, Markus Armbruster, Luiz Capitulino,
	Stefan Hajnoczi, Andreas Färber

[-- Attachment #1: Type: text/plain, Size: 895 bytes --]

On Tue, Nov 24, 2015 at 06:09:36PM +0100, Lluís Vilanova wrote:
> +    /* Ensure 'tb_phys_idx' can encode event states as a bitmask */
> +    bool too_many_tcg_vcpu_events[
> +        TRACE_CPU_EVENT_COUNT > sizeof(unsigned int)*8 ? -1 : 0];

There is a limit of 32 vcpu tcg events?  That seems low but as long as
not too many users of this feature are merged it will work...

> @@ -227,6 +228,17 @@ void cpu_dump_statistics(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
>  void cpu_reset(CPUState *cpu)
>  {
>      CPUClass *klass = CPU_GET_CLASS(cpu);
> +    TraceEvent *ev = NULL;
> +
> +    if (!qemu_initialized) {

Is there a cleaner place to do this without introducing the
qemu_initialized global?

I guess the problem is that tracing itself is initialized before the
vcpus are set up.  Is qemu_add_machine_init_done_notifier() sufficient
for this purpose?

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v2 00/10] trace: Per-vCPU tracing states
  2015-11-24 17:08 [Qemu-devel] [PATCH v2 00/10] trace: Per-vCPU tracing states Lluís Vilanova
                   ` (9 preceding siblings ...)
  2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 10/10] trace: [tcg] Generate TCG code to trace guest events on a per-vCPU basis Lluís Vilanova
@ 2016-01-07  8:05 ` Stefan Hajnoczi
  10 siblings, 0 replies; 20+ messages in thread
From: Stefan Hajnoczi @ 2016-01-07  8:05 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: Peter Maydell, Richard Henderson, qemu-devel, Eduardo Habkost

[-- Attachment #1: Type: text/plain, Size: 6412 bytes --]

On Tue, Nov 24, 2015 at 06:08:47PM +0100, Lluís Vilanova wrote:
> NOTE: This series completes the framework for guest code tracing. Next series
>       will add actual events.
> 
> Provides per-vCPU dynamic controls of the tracing state of events tied to a
> specific virtual CPU.
> 
> Events with the "vcpu" property are identified as being tied to a particular
> virtual CPU, like executing an instruction. The state of such events can be
> controlled idependently; this is specially useful to, for example, trace memory
> access events of a process executing on a specific virtual CPU.
> 
> This event property plays in combination with the "tcg" property to avoid
> generating a call to the execution-time event tracer when a vCPU is not actively
> tracing such event (i.e., avoids adding tracing overheads).
> 
> Virtual CPUs tracing the same set of events use the same physical translation
> cache, improving their reuse. The system has 2^N physical translation caches,
> where "N" is the number of TCG events with the "vcpu" property. Every vCPU has a
> bitmap with the states of these events, which can be controlled separately, and
> uses it to select its physical translation cache. At translation time, QEMU
> generates the code to trace an event at execution time only if the event is
> enabled.
> 
> Changes in v2
> =============
> 
> * Rebase on 5522a84.
> * Improve patch descriptions.
> * Refactor code generation into a separate patch.
> * Fix forward declarations (Stefan Hajnoczi & Eduardo Habkost).
> * Fix "since" tags in QAPI interface (Eric Blake).
> * Unify QAPI/QMP interface with an optional 'vcpu' argument (Eric Blake).
> * Fix QMP+GTK header workaround (Stefan Hajnoczi).
> 
> 
> Signed-off-by: Lluís Vilanova <vilanova@ac.upc.edu>
> ---
> 
> Lluís Vilanova (10):
>       trace: Add support for vCPU pointers in trace events
>       trace: Add 'vcpu' event property
>       trace: [tcg] Identify events with the 'vcpu' property
>       exec: [tcg] Refactor flush of per-CPU virtual TB cache
>       exec: [ŧcg] Use multiple physical TB caches
>       exec: [tcg] Track which vCPU is performing translation and execution
>       [trivial] Track when QEMU has finished initialization
>       disas: Remove unused macro '_'
>       trace: [tcg] Add per-vCPU tracing states for events with the 'vcpu' property
>       trace: [tcg] Generate TCG code to trace guest events on a per-vCPU basis
> 
> 
>  Makefile.objs                            |    3 -
>  bsd-user/main.c                          |    1 
>  cpu-exec.c                               |   17 +++
>  cputlb.c                                 |    2 
>  disas/i386.c                             |    2 
>  docs/tracing.txt                         |   40 ++++++++
>  include/disas/bfd.h                      |    1 
>  include/exec/exec-all.h                  |   16 +++
>  include/qemu-common.h                    |    3 +
>  include/qemu/typedefs.h                  |    1 
>  include/qom/cpu.h                        |   10 ++
>  linux-user/main.c                        |    1 
>  monitor.c                                |    4 -
>  qapi/trace.json                          |   16 ++-
>  qemu-common.c                            |   14 +++
>  qmp-commands.hx                          |   17 +++
>  qom/cpu.c                                |   21 ++++
>  scripts/tracetool/__init__.py            |   24 ++++-
>  scripts/tracetool/format/events_c.py     |   11 ++
>  scripts/tracetool/format/events_h.py     |   14 ++-
>  scripts/tracetool/format/h.py            |    4 +
>  scripts/tracetool/format/tcg_h.py        |   21 +++-
>  scripts/tracetool/format/tcg_helper_c.py |   11 ++
>  scripts/tracetool/format/ust_events_c.py |    3 -
>  scripts/tracetool/transform.py           |    9 ++
>  stubs/Makefile.objs                      |    1 
>  stubs/qemu-common-stub.c                 |   21 ++++
>  target-alpha/translate.c                 |    3 -
>  target-arm/translate.c                   |    3 -
>  target-arm/translate.h                   |    2 
>  target-cris/translate.c                  |    3 -
>  target-cris/translate_v10.c              |    1 
>  target-i386/translate.c                  |    3 -
>  target-lm32/translate.c                  |    3 -
>  target-m68k/translate.c                  |    3 -
>  target-microblaze/translate.c            |    3 -
>  target-mips/translate.c                  |    3 -
>  target-moxie/translate.c                 |    3 -
>  target-openrisc/translate.c              |    3 -
>  target-ppc/translate.c                   |    3 -
>  target-s390x/translate.c                 |    3 -
>  target-sh4/translate.c                   |    3 -
>  target-sparc/translate.c                 |    6 +
>  target-tilegx/translate.c                |    3 -
>  target-tricore/translate.c               |    3 -
>  target-unicore32/translate.c             |    3 -
>  target-xtensa/translate.c                |    3 -
>  tcg/tcg-op.h                             |    2 
>  tcg/tcg.h                                |   10 ++
>  trace/Makefile.objs                      |    2 
>  trace/control-internal.h                 |   21 +++-
>  trace/control-stub.c                     |   29 ++++++
>  trace/control-target.c                   |   69 +++++++++++++
>  trace/control.h                          |   64 ++++++++++++
>  trace/event-internal.h                   |    6 +
>  trace/qmp.c                              |  139 ++++++++++++++++++++++-----
>  translate-all.c                          |  156 ++++++++++++++++++++++++++----
>  translate-all.h                          |   49 +++++++++
>  vl.c                                     |    2 
>  59 files changed, 788 insertions(+), 109 deletions(-)
>  create mode 100644 qemu-common.c
>  create mode 100644 stubs/qemu-common-stub.c
>  create mode 100644 trace/control-stub.c
>  create mode 100644 trace/control-target.c
> 
> 
> To: qemu-devel@nongnu.org
> Cc: Stefan Hajnoczi <stefanha@gmail.com>
> Cc: Eduardo Habkost <ehabkost@redhat.com>
> Cc: Eric Blake <eblake@redhat.com>

Acked-by: Stefan Hajnoczi <stefanha@redhat.com>

I left comments on individual patches.

There hasn't been any review from TCG folks yet.  I have CCed Peter
Maydell and Richard Henderson to review the TCG changes.

Stefan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v2 05/10] exec: [ŧcg]  Use multiple physical TB caches
  2016-01-07  7:49   ` Stefan Hajnoczi
@ 2016-01-07 17:56     ` Lluís Vilanova
  0 siblings, 0 replies; 20+ messages in thread
From: Lluís Vilanova @ 2016-01-07 17:56 UTC (permalink / raw)
  To: Stefan Hajnoczi; +Cc: qemu-devel, Andreas Färber, Eduardo Habkost

Stefan Hajnoczi writes:

> On Tue, Nov 24, 2015 at 06:09:14PM +0100, Lluís Vilanova wrote:
> Commit message uses 'LATIN SMALL LETTER T WITH STROKE' (U+0167) instead
> of regular 't' character :).

Woops! Thanks :)

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v2 09/10] trace: [tcg] Add per-vCPU tracing states for events with the 'vcpu' property
  2016-01-07  8:03   ` Stefan Hajnoczi
@ 2016-01-07 18:44     ` Lluís Vilanova
  2016-01-14 11:22       ` Stefan Hajnoczi
  0 siblings, 1 reply; 20+ messages in thread
From: Lluís Vilanova @ 2016-01-07 18:44 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: Eduardo Habkost, qemu-devel, Markus Armbruster, Luiz Capitulino,
	Stefan Hajnoczi, Andreas Färber

Stefan Hajnoczi writes:

> On Tue, Nov 24, 2015 at 06:09:36PM +0100, Lluís Vilanova wrote:
>> +    /* Ensure 'tb_phys_idx' can encode event states as a bitmask */
>> +    bool too_many_tcg_vcpu_events[
>> +        TRACE_CPU_EVENT_COUNT > sizeof(unsigned int)*8 ? -1 : 0];

> There is a limit of 32 vcpu tcg events?  That seems low but as long as
> not too many users of this feature are merged it will work...

Well, 'tb_phys_idx' and 'tb_phys_idx_req' (just above this line) are 'unsigned
int'. They could be changed to a 64-bit index if necessary, but more than that
would require a more complex physical TB cache selection.

Fortunately, this is going to be catched at compilation time, making it safe
against crashing QEMU because of too many events of this type.


>> @@ -227,6 +228,17 @@ void cpu_dump_statistics(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
>> void cpu_reset(CPUState *cpu)
>> {
>> CPUClass *klass = CPU_GET_CLASS(cpu);
>> +    TraceEvent *ev = NULL;
>> +
>> +    if (!qemu_initialized) {

> Is there a cleaner place to do this without introducing the
> qemu_initialized global?

> I guess the problem is that tracing itself is initialized before the
> vcpus are set up.  Is qemu_add_machine_init_done_notifier() sufficient
> for this purpose?

Right, tracing must be initialized early, while vCPUs do so much later. Also,
the hook I took for initialization is also called by regular vCPU resets and
hotplugs. The problem with machine_init is that it only works in full-system
(softmmu) mode, so it would require a separate initialization call for the user
mode variants (e.g., linux-user).

It would be much cleaner to add a trace post-initialization routine right before
main_loop/cpu_loop (doing the per-vCPU tracing state initialization). I'll
re-check the code to see if there was any other condition that made me take
'cpu_reset' instead.


Thanks,
  Lluis

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH v2 09/10] trace: [tcg] Add per-vCPU tracing states for events with the 'vcpu' property
  2016-01-07 18:44     ` Lluís Vilanova
@ 2016-01-14 11:22       ` Stefan Hajnoczi
  0 siblings, 0 replies; 20+ messages in thread
From: Stefan Hajnoczi @ 2016-01-14 11:22 UTC (permalink / raw)
  To: Lluís Vilanova
  Cc: Eduardo Habkost, qemu-devel, Stefan Hajnoczi, Markus Armbruster,
	Luiz Capitulino, Andreas Färber

[-- Attachment #1: Type: text/plain, Size: 1373 bytes --]

On Thu, Jan 07, 2016 at 07:44:13PM +0100, Lluís Vilanova wrote:
> Stefan Hajnoczi writes:
> 
> > On Tue, Nov 24, 2015 at 06:09:36PM +0100, Lluís Vilanova wrote:
> >> @@ -227,6 +228,17 @@ void cpu_dump_statistics(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
> >> void cpu_reset(CPUState *cpu)
> >> {
> >> CPUClass *klass = CPU_GET_CLASS(cpu);
> >> +    TraceEvent *ev = NULL;
> >> +
> >> +    if (!qemu_initialized) {
> 
> > Is there a cleaner place to do this without introducing the
> > qemu_initialized global?
> 
> > I guess the problem is that tracing itself is initialized before the
> > vcpus are set up.  Is qemu_add_machine_init_done_notifier() sufficient
> > for this purpose?
> 
> Right, tracing must be initialized early, while vCPUs do so much later. Also,
> the hook I took for initialization is also called by regular vCPU resets and
> hotplugs. The problem with machine_init is that it only works in full-system
> (softmmu) mode, so it would require a separate initialization call for the user
> mode variants (e.g., linux-user).
> 
> It would be much cleaner to add a trace post-initialization routine right before
> main_loop/cpu_loop (doing the per-vCPU tracing state initialization). I'll
> re-check the code to see if there was any other condition that made me take
> 'cpu_reset' instead.

Okay, great.

Stefan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2016-01-14 11:23 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-24 17:08 [Qemu-devel] [PATCH v2 00/10] trace: Per-vCPU tracing states Lluís Vilanova
2015-11-24 17:08 ` [Qemu-devel] [PATCH v2 01/10] trace: Add support for vCPU pointers in trace events Lluís Vilanova
2015-11-24 17:08 ` [Qemu-devel] [PATCH v2 02/10] trace: Add 'vcpu' event property Lluís Vilanova
2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 03/10] trace: [tcg] Identify events with the 'vcpu' property Lluís Vilanova
2015-11-24 17:54   ` Eric Blake
2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 04/10] exec: [tcg] Refactor flush of per-CPU virtual TB cache Lluís Vilanova
2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 05/10] exec: [ŧcg] Use multiple physical TB caches Lluís Vilanova
2016-01-07  7:49   ` Stefan Hajnoczi
2016-01-07 17:56     ` Lluís Vilanova
2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 06/10] exec: [tcg] Track which vCPU is performing translation and execution Lluís Vilanova
2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 07/10] [trivial] Track when QEMU has finished initialization Lluís Vilanova
2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 08/10] disas: Remove unused macro '_' Lluís Vilanova
2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 09/10] trace: [tcg] Add per-vCPU tracing states for events with the 'vcpu' property Lluís Vilanova
2015-11-24 17:57   ` Eric Blake
2015-11-24 18:31     ` Lluís Vilanova
2016-01-07  8:03   ` Stefan Hajnoczi
2016-01-07 18:44     ` Lluís Vilanova
2016-01-14 11:22       ` Stefan Hajnoczi
2015-11-24 17:09 ` [Qemu-devel] [PATCH v2 10/10] trace: [tcg] Generate TCG code to trace guest events on a per-vCPU basis Lluís Vilanova
2016-01-07  8:05 ` [Qemu-devel] [PATCH v2 00/10] trace: Per-vCPU tracing states Stefan Hajnoczi

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.