[ltt-dev] [PATCH 1/2] Add the VIRT state
Julien Desfossez
julien.desfossez at polymtl.ca
Thu Sep 9 10:03:40 EDT 2010
The VIRT state is used to represent the CPU state of a machine when
there are virtual machines running. For now it only work with KVM but
could be extended to other virtualization technologies.
In the control flow view, a process entering in a virtual machine CPU
(vmentry) will be represented in red until a vmexit occurs.
Signed-off-by: Julien Desfossez <julien.desfossez at polymtl.ca>
---
lttv/lttv/state.c | 97 +++++++++++++++++++++++++++--
lttv/lttv/state.h | 13 +++-
lttv/modules/gui/controlflow/drawing.c | 17 +++++
lttv/modules/gui/controlflow/drawing.h | 1 +
lttv/modules/gui/controlflow/eventhooks.c | 2 +
5 files changed, 122 insertions(+), 8 deletions(-)
diff --git a/lttv/lttv/state.c b/lttv/lttv/state.c
index 871df9b..6987fa9 100644
--- a/lttv/lttv/state.c
+++ b/lttv/lttv/state.c
@@ -64,7 +64,8 @@ GQuark
LTT_CHANNEL_KERNEL,
LTT_CHANNEL_MM,
LTT_CHANNEL_USERSPACE,
- LTT_CHANNEL_BLOCK;
+ LTT_CHANNEL_BLOCK,
+ LTT_CHANNEL_KVM;
/* Events Quarks */
@@ -103,7 +104,9 @@ GQuark
LTT_EVENT_KPROBE,
LTT_EVENT_OPEN,
LTT_EVENT_READ,
- LTT_EVENT_POLL_EVENT;
+ LTT_EVENT_POLL_EVENT,
+ LTT_EVENT_VIRT_ENTRY,
+ LTT_EVENT_VIRT_EXIT;
/* Fields Quarks */
@@ -138,7 +141,8 @@ GQuark
LTT_FIELD_IP,
LTT_FIELD_FD,
LTT_FIELD_STATE,
- LTT_FIELD_CPU_ID;
+ LTT_FIELD_CPU_ID,
+ LTT_FIELD_VCPU_ID;
LttvExecutionMode
LTTV_STATE_MODE_UNKNOWN,
@@ -146,7 +150,8 @@ LttvExecutionMode
LTTV_STATE_SYSCALL,
LTTV_STATE_TRAP,
LTTV_STATE_IRQ,
- LTTV_STATE_SOFT_IRQ;
+ LTTV_STATE_SOFT_IRQ,
+ LTTV_STATE_VIRT;
LttvExecutionSubmode
LTTV_STATE_SUBMODE_UNKNOWN,
@@ -354,6 +359,20 @@ static void expand_syscall_table(LttvTraceState *ts, int id)
nt->nb_syscalls = new_nb;
}
+static void expand_virt_table(LttvTraceState *ts, int id)
+{
+ LttvNameTables *nt = ts->name_tables;
+ guint new_nb;
+
+ new_nb = check_expand(nt->nb_virt, id);
+ if(likely(new_nb == nt->nb_virt))
+ return;
+ expand_name_table(ts, &nt->virt_names, nt->nb_virt, new_nb);
+ fill_name_table(ts, nt->virt_names, nt->nb_virt, new_nb, "virt");
+ /* Update the table size */
+ nt->nb_virt = new_nb;
+}
+
static void expand_kprobe_table(LttvTraceState *ts, guint64 ip, char *symbol)
{
LttvNameTables *nt = ts->name_tables;
@@ -443,7 +462,7 @@ static void expand_soft_irq_table(LttvTraceState *ts, int id)
static void restore_init_state(LttvTraceState *self)
{
- guint i, nb_cpus, nb_irqs, nb_soft_irqs, nb_traps;
+ guint i, nb_cpus, nb_irqs, nb_soft_irqs, nb_traps, nb_virt;
//LttvTracefileState *tfcs;
@@ -471,6 +490,7 @@ static void restore_init_state(LttvTraceState *self)
nb_irqs = self->name_tables->nb_irqs;
nb_soft_irqs = self->name_tables->nb_soft_irqs;
nb_traps = self->name_tables->nb_traps;
+ nb_virt = self->name_tables->nb_virt;
/* Put the per cpu running_process to beginning state : process 0. */
for(i=0; i< nb_cpus; i++) {
@@ -2014,6 +2034,24 @@ static void create_name_tables(LttvTraceState *tcs)
lttv_trace_hook_remove_all(&hooks);
if(!lttv_trace_find_hook(tcs->parent.t,
+ LTT_CHANNEL_KVM,
+ LTT_EVENT_VIRT_ENTRY,
+ FIELD_ARRAY(LTT_FIELD_VCPU_ID),
+ NULL, NULL, &hooks)) {
+
+ name_tables->nb_virt = 256;
+ name_tables->virt_names = g_new(GQuark, 256);
+ for(i = 0 ; i < 256 ; i++) {
+ g_string_printf(fe_name, "vcpu %d", i);
+ name_tables->virt_names[i] = g_quark_from_string(fe_name->str);
+ }
+ } else {
+ name_tables->virt_names = NULL;
+ name_tables->nb_virt = 0;
+ }
+ lttv_trace_hook_remove_all(&hooks);
+
+ if(!lttv_trace_find_hook(tcs->parent.t,
LTT_CHANNEL_KERNEL,
LTT_EVENT_TRAP_ENTRY,
FIELD_ARRAY(LTT_FIELD_TRAP_ID),
@@ -2124,6 +2162,7 @@ static void free_name_tables(LttvTraceState *tcs)
// g_free(name_tables->eventtype_names);
if(name_tables->syscall_names) g_free(name_tables->syscall_names);
+ if(name_tables->virt_names) g_free(name_tables->virt_names);
if(name_tables->trap_names) g_free(name_tables->trap_names);
if(name_tables->irq_names) g_free(name_tables->irq_names);
if(name_tables->soft_irq_names) g_free(name_tables->soft_irq_names);
@@ -2548,6 +2587,37 @@ static gboolean syscall_exit(void *hook_data, void *call_data)
return FALSE;
}
+static gboolean kvm_entry(void *hook_data, void *call_data)
+{
+ LttvTracefileState *s = (LttvTracefileState *)call_data;
+ guint cpu = s->cpu;
+ LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
+ LttvProcessState *process = ts->running_process[cpu];
+ LttEvent *e = ltt_tracefile_get_event(s->parent.tf);
+ LttvTraceHook *th = (LttvTraceHook *)hook_data;
+ struct marker_field *f = lttv_trace_get_hook_field(th, 0);
+ LttvExecutionSubmode submode;
+ LttvNameTables *nt = ((LttvTraceState *)(s->parent.t_context))->name_tables;
+
+ guint vcpu = ltt_event_get_unsigned(e, f);
+ expand_virt_table(ts, vcpu);
+ submode = nt->virt_names[vcpu];
+ if(process->pid != 0)
+ push_state(s, LTTV_STATE_VIRT , submode);
+ return FALSE;
+}
+
+static gboolean kvm_exit(void *hook_data, void *call_data)
+{
+ LttvTracefileState *s = (LttvTracefileState *)call_data;
+ guint cpu = s->cpu;
+ LttvTraceState *ts = (LttvTraceState*)s->parent.t_context;
+ LttvProcessState *process = ts->running_process[cpu];
+
+ if(process->pid != 0)
+ pop_state(s, LTTV_STATE_VIRT);
+ return FALSE;
+}
static gboolean trap_entry(void *hook_data, void *call_data)
{
@@ -3619,6 +3689,18 @@ void lttv_state_add_event_hooks(LttvTracesetState *self)
syscall_exit, NULL, &hooks);
lttv_trace_find_hook(ts->parent.t,
+ LTT_CHANNEL_KVM,
+ LTT_EVENT_VIRT_ENTRY,
+ FIELD_ARRAY(LTT_FIELD_VCPU_ID),
+ kvm_entry, NULL, &hooks);
+
+ lttv_trace_find_hook(ts->parent.t,
+ LTT_CHANNEL_KVM,
+ LTT_EVENT_VIRT_EXIT,
+ NULL,
+ kvm_exit, NULL, &hooks);
+
+ lttv_trace_find_hook(ts->parent.t,
LTT_CHANNEL_KERNEL,
LTT_EVENT_TRAP_ENTRY,
FIELD_ARRAY(LTT_FIELD_TRAP_ID),
@@ -4417,6 +4499,7 @@ static void module_init()
LTTV_STATE_MODE_UNKNOWN = g_quark_from_string("MODE_UNKNOWN");
LTTV_STATE_USER_MODE = g_quark_from_string("USER_MODE");
LTTV_STATE_SYSCALL = g_quark_from_string("SYSCALL");
+ LTTV_STATE_VIRT = g_quark_from_string("VIRT");
LTTV_STATE_TRAP = g_quark_from_string("TRAP");
LTTV_STATE_IRQ = g_quark_from_string("IRQ");
LTTV_STATE_SOFT_IRQ = g_quark_from_string("SOFTIRQ");
@@ -4461,6 +4544,7 @@ static void module_init()
LTT_CHANNEL_TASK_STATE = g_quark_from_string("task_state");
LTT_CHANNEL_VM_STATE = g_quark_from_string("vm_state");
LTT_CHANNEL_KPROBE_STATE = g_quark_from_string("kprobe_state");
+ LTT_CHANNEL_KVM = g_quark_from_string("kvm");
LTT_CHANNEL_FS = g_quark_from_string("fs");
LTT_CHANNEL_KERNEL = g_quark_from_string("kernel");
LTT_CHANNEL_MM = g_quark_from_string("mm");
@@ -4469,6 +4553,8 @@ static void module_init()
LTT_EVENT_SYSCALL_ENTRY = g_quark_from_string("syscall_entry");
LTT_EVENT_SYSCALL_EXIT = g_quark_from_string("syscall_exit");
+ LTT_EVENT_VIRT_ENTRY = g_quark_from_string("kvm_entry");
+ LTT_EVENT_VIRT_EXIT = g_quark_from_string("kvm_exit");
LTT_EVENT_TRAP_ENTRY = g_quark_from_string("trap_entry");
LTT_EVENT_TRAP_EXIT = g_quark_from_string("trap_exit");
LTT_EVENT_PAGE_FAULT_ENTRY = g_quark_from_string("page_fault_entry");
@@ -4534,6 +4620,7 @@ static void module_init()
LTT_FIELD_FD = g_quark_from_string("fd");
LTT_FIELD_STATE = g_quark_from_string("state");
LTT_FIELD_CPU_ID = g_quark_from_string("cpu_id");
+ LTT_FIELD_VCPU_ID = g_quark_from_string("vcpu");
LTTV_CPU_UNKNOWN = g_quark_from_string("unknown");
LTTV_CPU_IDLE = g_quark_from_string("idle");
diff --git a/lttv/lttv/state.h b/lttv/lttv/state.h
index 1e6efb5..b6da6db 100644
--- a/lttv/lttv/state.h
+++ b/lttv/lttv/state.h
@@ -71,7 +71,8 @@ extern GQuark
LTT_CHANNEL_KERNEL,
LTT_CHANNEL_MM,
LTT_CHANNEL_USERSPACE,
- LTT_CHANNEL_BLOCK;
+ LTT_CHANNEL_BLOCK,
+ LTT_CHANNEL_KVM;
/* Events Quarks */
@@ -110,7 +111,9 @@ extern GQuark
LTT_EVENT_KPROBE,
LTT_EVENT_OPEN,
LTT_EVENT_READ,
- LTT_EVENT_POLL_EVENT;
+ LTT_EVENT_POLL_EVENT,
+ LTT_EVENT_VIRT_ENTRY,
+ LTT_EVENT_VIRT_EXIT;
/* Fields Quarks */
@@ -144,7 +147,8 @@ extern GQuark
LTT_FIELD_IP,
LTT_FIELD_FD,
LTT_FIELD_STATE,
- LTT_FIELD_CPU_ID;
+ LTT_FIELD_CPU_ID,
+ LTT_FIELD_VCPU_ID;
typedef struct _LttvTracesetState LttvTracesetState;
typedef struct _LttvTracesetStateClass LttvTracesetStateClass;
@@ -196,6 +200,7 @@ extern LttvExecutionMode
LTTV_STATE_TRAP,
LTTV_STATE_IRQ,
LTTV_STATE_SOFT_IRQ,
+ LTTV_STATE_VIRT,
LTTV_STATE_MODE_UNKNOWN;
@@ -372,6 +377,8 @@ typedef struct _LttvNameTables {
GQuark *soft_irq_names;
guint nb_soft_irqs;
GHashTable *kprobe_hash;
+ GQuark *virt_names;
+ guint nb_virt;
} LttvNameTables;
struct _LttvTraceState {
diff --git a/lttv/modules/gui/controlflow/drawing.c b/lttv/modules/gui/controlflow/drawing.c
index 10df57d..ecf2493 100644
--- a/lttv/modules/gui/controlflow/drawing.c
+++ b/lttv/modules/gui/controlflow/drawing.c
@@ -70,6 +70,7 @@ GdkColor drawing_colors[NUM_COLORS] =
{ 0, 0xFFFF, 0xFFFF, 0xFFFF }, /* COL_WHITE */
{ 0, 0x0000, 0xFF00, 0x0000 }, /* COL_RUN_USER_MODE : green */
{ 0, 0x0100, 0x9E00, 0xFFFF }, /* COL_RUN_SYSCALL : pale blue */
+ { 0, 0xFFFF, 0x0000, 0x0000 }, /* COL_RUN_VIRT : red */
{ 0, 0xFF00, 0xFF00, 0x0100 }, /* COL_RUN_TRAP : yellow */
{ 0, 0xFFFF, 0x5E00, 0x0000 }, /* COL_RUN_IRQ : orange */
{ 0, 0xFFFF, 0x9400, 0x9600 }, /* COL_RUN_SOFT_IRQ : pink */
@@ -246,6 +247,22 @@ void drawing_data_request(Drawing_t *drawing,
&hooks);
lttv_trace_find_hook(ts->parent.t,
+ LTT_CHANNEL_KVM,
+ LTT_EVENT_VIRT_ENTRY,
+ FIELD_ARRAY(LTT_FIELD_VCPU_ID),
+ before_execmode_hook,
+ events_request,
+ &hooks);
+
+ lttv_trace_find_hook(ts->parent.t,
+ LTT_CHANNEL_KVM,
+ LTT_EVENT_VIRT_EXIT,
+ NULL,
+ before_execmode_hook,
+ events_request,
+ &hooks);
+
+ lttv_trace_find_hook(ts->parent.t,
LTT_CHANNEL_KERNEL,
LTT_EVENT_TRAP_ENTRY,
FIELD_ARRAY(LTT_FIELD_TRAP_ID),
diff --git a/lttv/modules/gui/controlflow/drawing.h b/lttv/modules/gui/controlflow/drawing.h
index 3e4b3dc..f85e7c8 100644
--- a/lttv/modules/gui/controlflow/drawing.h
+++ b/lttv/modules/gui/controlflow/drawing.h
@@ -38,6 +38,7 @@ typedef enum _draw_color {
COL_WHITE,
COL_RUN_USER_MODE,/* green */
COL_RUN_SYSCALL, /* pale blue */
+ COL_RUN_VIRT, /* red */
COL_RUN_TRAP, /* yellow */
COL_RUN_IRQ, /* orange */
COL_RUN_SOFT_IRQ, /* red */
diff --git a/lttv/modules/gui/controlflow/eventhooks.c b/lttv/modules/gui/controlflow/eventhooks.c
index 516a4d2..314357d 100644
--- a/lttv/modules/gui/controlflow/eventhooks.c
+++ b/lttv/modules/gui/controlflow/eventhooks.c
@@ -241,6 +241,8 @@ static inline PropertiesLine prepare_s_e_line(LttvProcessState *process)
prop_line.color = drawing_colors[COL_RUN_USER_MODE];
else if(process->state->t == LTTV_STATE_SYSCALL)
prop_line.color = drawing_colors[COL_RUN_SYSCALL];
+ else if(process->state->t == LTTV_STATE_VIRT)
+ prop_line.color = drawing_colors[COL_RUN_VIRT];
else if(process->state->t == LTTV_STATE_TRAP)
prop_line.color = drawing_colors[COL_RUN_TRAP];
else if(process->state->t == LTTV_STATE_IRQ)
--
1.7.0.4
More information about the lttng-dev
mailing list