16
16
17
17
QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION ;
18
18
19
- static uint64_t bb_count ;
20
- static uint64_t insn_count ;
19
+ typedef struct {
20
+ GMutex lock ;
21
+ int index ;
22
+ uint64_t bb_count ;
23
+ uint64_t insn_count ;
24
+ } CPUCount ;
25
+
26
+ /* Used by the inline & linux-user counts */
21
27
static bool do_inline ;
28
+ static CPUCount inline_count ;
29
+
30
+ /* Dump running CPU total on idle? */
31
+ static bool idle_report ;
32
+ static GPtrArray * counts ;
33
+ static int max_cpus ;
34
+
35
+ static void gen_one_cpu_report (CPUCount * count , GString * report )
36
+ {
37
+ if (count -> bb_count ) {
38
+ g_string_append_printf (report , "CPU%d: "
39
+ "bb's: %" PRIu64 ", insns: %" PRIu64 "\n" ,
40
+ count -> index ,
41
+ count -> bb_count , count -> insn_count );
42
+ }
43
+ }
22
44
23
45
static void plugin_exit (qemu_plugin_id_t id , void * p )
24
46
{
25
- g_autofree gchar * out = g_strdup_printf (
26
- "bb's: %" PRIu64 ", insns: %" PRIu64 "\n" ,
27
- bb_count , insn_count );
28
- qemu_plugin_outs (out );
47
+ g_autoptr (GString ) report = g_string_new ("" );
48
+
49
+ if (do_inline || !max_cpus ) {
50
+ g_string_printf (report , "bb's: %" PRIu64 ", insns: %" PRIu64 "\n" ,
51
+ inline_count .bb_count , inline_count .insn_count );
52
+ } else {
53
+ g_ptr_array_foreach (counts , (GFunc ) gen_one_cpu_report , report );
54
+ }
55
+ qemu_plugin_outs (report -> str );
56
+ }
57
+
58
+ static void vcpu_idle (qemu_plugin_id_t id , unsigned int cpu_index )
59
+ {
60
+ CPUCount * count = g_ptr_array_index (counts , cpu_index );
61
+ g_autoptr (GString ) report = g_string_new ("" );
62
+ gen_one_cpu_report (count , report );
63
+
64
+ if (report -> len > 0 ) {
65
+ g_string_prepend (report , "Idling " );
66
+ qemu_plugin_outs (report -> str );
67
+ }
29
68
}
30
69
31
70
static void vcpu_tb_exec (unsigned int cpu_index , void * udata )
32
71
{
33
- unsigned long n_insns = (unsigned long )udata ;
72
+ CPUCount * count = max_cpus ?
73
+ g_ptr_array_index (counts , cpu_index ) : & inline_count ;
34
74
35
- insn_count += n_insns ;
36
- bb_count ++ ;
75
+ unsigned long n_insns = (unsigned long )udata ;
76
+ g_mutex_lock (& count -> lock );
77
+ count -> insn_count += n_insns ;
78
+ count -> bb_count ++ ;
79
+ g_mutex_unlock (& count -> lock );
37
80
}
38
81
39
82
static void vcpu_tb_trans (qemu_plugin_id_t id , struct qemu_plugin_tb * tb )
@@ -42,9 +85,10 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
42
85
43
86
if (do_inline ) {
44
87
qemu_plugin_register_vcpu_tb_exec_inline (tb , QEMU_PLUGIN_INLINE_ADD_U64 ,
45
- & bb_count , 1 );
88
+ & inline_count . bb_count , 1 );
46
89
qemu_plugin_register_vcpu_tb_exec_inline (tb , QEMU_PLUGIN_INLINE_ADD_U64 ,
47
- & insn_count , n_insns );
90
+ & inline_count .insn_count ,
91
+ n_insns );
48
92
} else {
49
93
qemu_plugin_register_vcpu_tb_exec_cb (tb , vcpu_tb_exec ,
50
94
QEMU_PLUGIN_CB_NO_REGS ,
@@ -56,8 +100,35 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
56
100
const qemu_info_t * info ,
57
101
int argc , char * * argv )
58
102
{
59
- if (argc && strcmp (argv [0 ], "inline" ) == 0 ) {
60
- do_inline = true;
103
+ int i ;
104
+
105
+ for (i = 0 ; i < argc ; i ++ ) {
106
+ char * opt = argv [i ];
107
+ if (g_strcmp0 (opt , "inline" ) == 0 ) {
108
+ do_inline = true;
109
+ } else if (g_strcmp0 (opt , "idle" ) == 0 ) {
110
+ idle_report = true;
111
+ } else {
112
+ fprintf (stderr , "option parsing failed: %s\n" , opt );
113
+ return -1 ;
114
+ }
115
+ }
116
+
117
+ if (info -> system_emulation && !do_inline ) {
118
+ max_cpus = info -> system .max_vcpus ;
119
+ counts = g_ptr_array_new ();
120
+ for (i = 0 ; i < max_cpus ; i ++ ) {
121
+ CPUCount * count = g_new0 (CPUCount , 1 );
122
+ g_mutex_init (& count -> lock );
123
+ count -> index = i ;
124
+ g_ptr_array_add (counts , count );
125
+ }
126
+ } else if (!do_inline ) {
127
+ g_mutex_init (& inline_count .lock );
128
+ }
129
+
130
+ if (idle_report ) {
131
+ qemu_plugin_register_vcpu_idle_cb (id , vcpu_idle );
61
132
}
62
133
63
134
qemu_plugin_register_vcpu_tb_trans_cb (id , vcpu_tb_trans );
0 commit comments