Mirror of the lttng-dev mailing list
 help / color / mirror / Atom feed
* [ltt-dev] [PATCH 1/2] Add the VIRT state
@ 2010-09-09 14:03 Julien Desfossez
  2010-09-09 14:03 ` [ltt-dev] [PATCH 2/2] Display the VIRT state in resource view Julien Desfossez
  0 siblings, 1 reply; 2+ messages in thread
From: Julien Desfossez @ 2010-09-09 14:03 UTC (permalink / raw)


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




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

* [ltt-dev] [PATCH 2/2] Display the VIRT state in resource view
  2010-09-09 14:03 [ltt-dev] [PATCH 1/2] Add the VIRT state Julien Desfossez
@ 2010-09-09 14:03 ` Julien Desfossez
  0 siblings, 0 replies; 2+ messages in thread
From: Julien Desfossez @ 2010-09-09 14:03 UTC (permalink / raw)


Now when a physical CPU enters in a virtual machine (vmentry) its line
is colored in red until a vmexit occurs.
That way, we can see which physical CPU are used to run a VM.

Signed-off-by: Julien Desfossez <julien.desfossez at polymtl.ca>
---
 lttv/lttv/state.c                           |  102 +++++++++++++++++++++++++--
 lttv/lttv/state.h                           |    9 ++-
 lttv/modules/gui/resourceview/drawing.c     |   11 +++
 lttv/modules/gui/resourceview/drawing.h     |    9 +++
 lttv/modules/gui/resourceview/eventhooks.c  |   21 +++++-
 lttv/modules/gui/resourceview/eventhooks.h  |    3 +
 lttv/modules/gui/resourceview/processlist.c |   17 +++++
 lttv/modules/gui/resourceview/processlist.h |    4 +-
 8 files changed, 167 insertions(+), 9 deletions(-)

diff --git a/lttv/lttv/state.c b/lttv/lttv/state.c
index 6987fa9..353acca 100644
--- a/lttv/lttv/state.c
+++ b/lttv/lttv/state.c
@@ -180,7 +180,8 @@ LttvCPUMode
 	LTTV_CPU_BUSY,
 	LTTV_CPU_IRQ,
 	LTTV_CPU_SOFT_IRQ,
-	LTTV_CPU_TRAP;
+	LTTV_CPU_TRAP,
+	LTTV_CPU_VIRT;
 
 LttvIRQMode
 	LTTV_IRQ_UNKNOWN,
@@ -210,7 +211,8 @@ static GQuark
 	LTTV_STATE_RESOURCE_IRQS,
 	LTTV_STATE_RESOURCE_SOFT_IRQS,
 	LTTV_STATE_RESOURCE_TRAPS,
-	LTTV_STATE_RESOURCE_BLKDEVS;
+	LTTV_STATE_RESOURCE_BLKDEVS,
+	LTTV_STATE_RESOURCE_VIRT;
 
 static void create_max_time(LttvTraceState *tcs);
 
@@ -362,13 +364,23 @@ static void expand_syscall_table(LttvTraceState *ts, int id)
 static void expand_virt_table(LttvTraceState *ts, int id)
 {
 	LttvNameTables *nt = ts->name_tables;
-	guint new_nb;
+	LttvTrapState *old_table;
+	guint new_nb, i;
 
 	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");
+
+	old_table = ts->virt_states;
+	ts->virt_states = g_new(LttvVirtState, new_nb);
+	memcpy(ts->virt_states, old_table, nt->nb_virt * sizeof(LttvVirtState));
+	g_free(old_table);
+	for(i = nt->nb_virt; i < new_nb; i++)
+		ts->virt_states[i].running = 0;
+
 	/* Update the table size */
 	nt->nb_virt = new_nb;
 }
@@ -523,6 +535,9 @@ static void restore_init_state(LttvTraceState *self)
 			if(self->cpu_states[i].trap_stack->len)
 				g_array_remove_range(self->cpu_states[i].trap_stack, 0,
 						self->cpu_states[i].trap_stack->len);
+			if(self->cpu_states[i].virt_stack->len)
+				g_array_remove_range(self->cpu_states[i].virt_stack, 0,
+						self->cpu_states[i].virt_stack->len);
 		}
 	}
 
@@ -549,6 +564,12 @@ static void restore_init_state(LttvTraceState *self)
 	//g_hash_table_steal_all(self->bdev_states);
 	g_hash_table_foreach_steal(self->bdev_states, rettrue, NULL);
 
+	/* reset virt states */
+	for(i=0; i<nb_virt; i++) {
+		self->virt_states[i].running = 0;
+	}
+
+
 #if 0
 	nb_tracefile = self->parent.tracefiles->len;
 
@@ -704,6 +725,7 @@ static void init(LttvTracesetState *self, LttvTraceset *ts)
 			tcs->cpu_states[j].irq_stack = g_array_new(FALSE, FALSE, sizeof(gint));
 			tcs->cpu_states[j].softirq_stack = g_array_new(FALSE, FALSE, sizeof(gint));
 			tcs->cpu_states[j].trap_stack = g_array_new(FALSE, FALSE, sizeof(gint));
+			tcs->cpu_states[j].virt_stack = g_array_new(FALSE, FALSE, sizeof(gint));
 			g_assert(tcs->cpu_states[j].mode_stack != NULL);
 		}
 
@@ -724,6 +746,9 @@ static void init(LttvTracesetState *self, LttvTraceset *ts)
 		/* init bdev resource stuff */
 		tcs->bdev_states = g_hash_table_new(g_int_hash, g_int_equal);
 
+		/* init virt stuff */
+		tcs->virt_states = g_new(LttvVirtState, tcs->name_tables->nb_virt);
+
 		restore_init_state(tcs);
 		for(j = 0 ; j < nb_tracefile ; j++) {
 			tfcs =
@@ -1419,6 +1444,13 @@ static LttvCPUState *lttv_state_copy_cpu_states(LttvCPUState *states, guint n)
 			g_array_index(retval[i].mode_stack, GQuark, j) =
 					g_array_index(states[i].mode_stack, GQuark, j);
 		}
+
+		retval[i].virt_stack = g_array_new(FALSE, FALSE, sizeof(gint));
+		g_array_set_size(retval[i].virt_stack, states[i].virt_stack->len);
+		for(j=0; j<states[i].virt_stack->len; j++) {
+			g_array_index(retval[i].virt_stack, gint, j) =
+				g_array_index(states[i].virt_stack, gint, j);
+		}
 	}
 
 	return retval;
@@ -1433,6 +1465,7 @@ static void lttv_state_free_cpu_states(LttvCPUState *states, guint n)
 		g_array_free(states[i].irq_stack, TRUE);
 		g_array_free(states[i].softirq_stack, TRUE);
 		g_array_free(states[i].trap_stack, TRUE);
+		g_array_free(states[i].virt_stack, TRUE);
 	}
 
 	g_free(states);
@@ -1509,6 +1542,26 @@ static void lttv_state_free_trap_states(LttvTrapState *states, guint n)
 	g_free(states);
 }
 
+static LttvVirtState *
+lttv_state_copy_virt_states(LttvVirtState *states, guint n)
+{
+	guint i;
+	LttvVirtState *retval;
+
+	retval = g_new(LttvVirtState, n);
+
+	for(i=0; i<n; i++) {
+		retval[i].running = states[i].running;
+	}
+
+	return retval;
+}
+
+static void lttv_state_free_virt_states(LttvVirtState *states, guint n)
+{
+	g_free(states);
+}
+
 /* bdevstate stuff */
 
 static LttvBdevState *get_hashed_bdevstate(LttvTraceState *ts, guint16 devcode)
@@ -1601,7 +1654,7 @@ static void lttv_state_free_blkdev_hashtable(GHashTable *ht)
 
 static void state_save(LttvTraceState *self, LttvAttribute *container)
 {
-	guint i, nb_tracefile, nb_cpus, nb_irqs, nb_soft_irqs, nb_traps;
+	guint i, nb_tracefile, nb_cpus, nb_irqs, nb_soft_irqs, nb_traps, nb_virt;
 
 	LttvTracefileState *tfcs;
 
@@ -1709,12 +1762,21 @@ static void state_save(LttvTraceState *self, LttvAttribute *container)
 	value = lttv_attribute_add(container, LTTV_STATE_RESOURCE_BLKDEVS,
 				LTTV_POINTER);
 	*(value.v_pointer) = lttv_state_copy_blkdev_hashtable(self->bdev_states);
+
+	/* save the virt state */
+	nb_virt = self->name_tables->nb_virt;
+	{
+		value = lttv_attribute_add(container, LTTV_STATE_RESOURCE_VIRT,
+				LTTV_POINTER);
+		*(value.v_pointer) = lttv_state_copy_virt_states(self->virt_states, nb_virt);
+	}
+
 }
 
 
 static void state_restore(LttvTraceState *self, LttvAttribute *container)
 {
-	guint i, nb_tracefile, pid, nb_cpus, nb_irqs, nb_soft_irqs, nb_traps;
+	guint i, nb_tracefile, pid, nb_cpus, nb_irqs, nb_soft_irqs, nb_traps, nb_virt;
 
 	LttvTracefileState *tfcs;
 
@@ -1794,6 +1856,13 @@ static void state_restore(LttvTraceState *self, LttvAttribute *container)
 	lttv_state_free_blkdev_hashtable(self->bdev_states);
 	self->bdev_states = lttv_state_copy_blkdev_hashtable(*(value.v_pointer));
 
+	/* restore virt resource states */
+	nb_virt = self->name_tables->nb_virt;
+	type = lttv_attribute_get_by_name(container, LTTV_STATE_RESOURCE_VIRT, &value);
+	g_assert(type == LTTV_POINTER);
+	lttv_state_free_virt_states(self->virt_states, nb_virt);
+	self->virt_states = lttv_state_copy_virt_states(*(value.v_pointer), nb_virt);
+
 	for(i = 0 ; i < nb_tracefile ; i++) {
 		tfcs =
 				LTTV_TRACEFILE_STATE(g_array_index(self->parent.tracefiles,
@@ -2604,6 +2673,14 @@ static gboolean kvm_entry(void *hook_data, void *call_data)
 	submode = nt->virt_names[vcpu];
 	if(process->pid != 0)
 		push_state(s, LTTV_STATE_VIRT , submode);
+
+	/* update cpu status */
+	cpu_push_mode(s->cpu_state, LTTV_CPU_VIRT);
+
+	/* update trap status */
+	g_array_append_val(s->cpu_state->virt_stack, vcpu);
+	ts->virt_states[vcpu].running++;
+
 	return FALSE;
 }
 
@@ -2616,6 +2693,19 @@ static gboolean kvm_exit(void *hook_data, void *call_data)
 
 	if(process->pid != 0)
 		pop_state(s, LTTV_STATE_VIRT);
+
+	/* update cpu status */
+	cpu_pop_mode(s->cpu_state);
+
+	/* update virt status */
+	if (s->cpu_state->virt_stack->len > 0) {
+		gint last = g_array_index(s->cpu_state->virt_stack, gint,
+				s->cpu_state->virt_stack->len-1);
+		if(ts->virt_states[last].running)
+			ts->virt_states[last].running--;
+		g_array_remove_index(s->cpu_state->virt_stack,
+				s->cpu_state->virt_stack->len-1);
+	}
 	return FALSE;
 }
 
@@ -4532,6 +4622,7 @@ static void module_init()
 	LTTV_STATE_RESOURCE_SOFT_IRQS = g_quark_from_string("soft irq resource states");
 	LTTV_STATE_RESOURCE_TRAPS = g_quark_from_string("trap resource states");
 	LTTV_STATE_RESOURCE_BLKDEVS = g_quark_from_string("blkdevs resource states");
+	LTTV_STATE_RESOURCE_VIRT = g_quark_from_string("virt resource states");
 
 	LTT_CHANNEL_FD_STATE         = g_quark_from_string("fd_state");
 	LTT_CHANNEL_GLOBAL_STATE     = g_quark_from_string("global_state");
@@ -4628,6 +4719,7 @@ static void module_init()
 	LTTV_CPU_IRQ = g_quark_from_string("irq");
 	LTTV_CPU_SOFT_IRQ = g_quark_from_string("softirq");
 	LTTV_CPU_TRAP = g_quark_from_string("trap");
+	LTTV_CPU_VIRT = g_quark_from_string("virt");
 
 	LTTV_IRQ_UNKNOWN = g_quark_from_string("unknown");
 	LTTV_IRQ_IDLE = g_quark_from_string("idle");
diff --git a/lttv/lttv/state.h b/lttv/lttv/state.h
index b6da6db..2be86a6 100644
--- a/lttv/lttv/state.h
+++ b/lttv/lttv/state.h
@@ -248,7 +248,8 @@ extern LttvCPUMode
 	LTTV_CPU_BUSY,
 	LTTV_CPU_IRQ,
 	LTTV_CPU_SOFT_IRQ,
-	LTTV_CPU_TRAP;
+	LTTV_CPU_TRAP,
+	LTTV_CPU_VIRT;
 
 typedef GQuark LttvIRQMode;
 extern LttvIRQMode
@@ -348,6 +349,7 @@ typedef struct _LttvCPUState {
 	GArray *irq_stack;
 	GArray *softirq_stack;
 	GArray *trap_stack;
+	GArray *virt_stack;
 } LttvCPUState;
 
 typedef struct _LttvIRQState {
@@ -367,6 +369,10 @@ typedef struct _LttvBdevState {
 	GArray *mode_stack;
 } LttvBdevState;
 
+typedef struct _LttvVirtState {
+	guint running; /* number of times it is currently running (on different processors) */
+} LttvVirtState;
+
 typedef struct _LttvNameTables {
 	GQuark *syscall_names;
 	guint nb_syscalls;
@@ -406,6 +412,7 @@ struct _LttvTraceState {
 	/* FIXME should be a g_array to deal with resize and copy. */
 	LttvTrapState *trap_states; /* state of each trap */
 	GHashTable *bdev_states; /* state of the block devices */
+	LttvVirtState *virt_states; /* state of each trap */
 };
 
 struct _LttvTraceStateClass {
diff --git a/lttv/modules/gui/resourceview/drawing.c b/lttv/modules/gui/resourceview/drawing.c
index 033475a..8aef0fc 100644
--- a/lttv/modules/gui/resourceview/drawing.c
+++ b/lttv/modules/gui/resourceview/drawing.c
@@ -91,6 +91,7 @@ GdkColor drawing_colors_cpu[NUM_COLORS_CPU] =
   { 0, 0xFFFF, 0x5E00, 0x0000 }, /* COL_CPU_IRQ */
   { 0, 0xFFFF, 0x9400, 0x9600 }, /* COL_CPU_SOFT_IRQ */
   { 0, 0xFF00, 0xFF00, 0x0100 }, /* COL_CPU_TRAP */
+  { 0, 0xFFFF, 0x0000, 0x0000 }, /* COL_CPU_VIRT */
 };
 
 GdkColor drawing_colors_irq[NUM_COLORS_IRQ] =
@@ -123,6 +124,13 @@ GdkColor drawing_colors_bdev[NUM_COLORS_BDEV] =
   { 0, 0xFFFF, 0x0000, 0x0000 }, /* COL_BDEV_BUSY_WRITING */
 };
 
+GdkColor drawing_colors_virt[NUM_COLORS_VIRT] =
+{ /* Pixel, R, G, B */
+	{ 0, 0x0000, 0x0000, 0x0000 }, /* COL_VIRT_UNKNOWN */
+	{ 0, 0x0000, 0x0000, 0x0000 }, /* FIXME : COL_VIRT_IDLE */
+	{ 0, 0xFF00, 0xFF00, 0x0100 }, /* FIXME : COL_VIRT_BUSY */
+};
+
 /*****************************************************************************
  *                              drawing functions                            *
  *****************************************************************************/
@@ -1072,6 +1080,8 @@ Drawing_t *drawing_construct(ControlFlowData *control_flow_data)
                             TRUE, success);
   gdk_colormap_alloc_colors(colormap, drawing_colors_bdev, NUM_COLORS_BDEV, FALSE,
                             TRUE, success);
+  gdk_colormap_alloc_colors(colormap, drawing_colors_virt, NUM_COLORS_VIRT, FALSE,
+                            TRUE, success);
   
   drawing->gc =
     gdk_gc_new(GDK_DRAWABLE(main_window_get_widget(control_flow_data->tab)->window));
@@ -1133,6 +1143,7 @@ void drawing_destroy(Drawing_t *drawing)
   gdk_colormap_free_colors(colormap, drawing_colors_soft_irq, NUM_COLORS_IRQ);
   gdk_colormap_free_colors(colormap, drawing_colors_trap, NUM_COLORS_TRAP);
   gdk_colormap_free_colors(colormap, drawing_colors_bdev, NUM_COLORS_BDEV);
+  gdk_colormap_free_colors(colormap, drawing_colors_virt, NUM_COLORS_VIRT);
 
   // Do not unref here, Drawing_t destroyed by it's widget.
   //g_object_unref( G_OBJECT(drawing->drawing_area));
diff --git a/lttv/modules/gui/resourceview/drawing.h b/lttv/modules/gui/resourceview/drawing.h
index 8b0070b..fc0e7ec 100644
--- a/lttv/modules/gui/resourceview/drawing.h
+++ b/lttv/modules/gui/resourceview/drawing.h
@@ -57,6 +57,7 @@ typedef enum _draw_color_cpu {
                 COL_CPU_IRQ,
                 COL_CPU_SOFT_IRQ,
                 COL_CPU_TRAP,
+                COL_CPU_VIRT,
                 NUM_COLORS_CPU
 } draw_color_cpu; 
 
@@ -90,12 +91,20 @@ typedef enum _draw_color_bdev {
                 NUM_COLORS_BDEV
 } draw_color_bdev; 
 
+typedef enum _draw_color_virt {
+                COL_VIRT_UNKNOWN,
+                COL_VIRT_IDLE,
+                COL_VIRT_BUSY,
+                NUM_COLORS_VIRT
+} draw_color_virt;
+
 extern GdkColor drawing_colors[NUM_COLORS];
 extern GdkColor drawing_colors_cpu[NUM_COLORS_CPU];
 extern GdkColor drawing_colors_irq[NUM_COLORS_IRQ];
 extern GdkColor drawing_colors_soft_irq[NUM_COLORS_SOFT_IRQ];
 extern GdkColor drawing_colors_trap[NUM_COLORS_TRAP];
 extern GdkColor drawing_colors_bdev[NUM_COLORS_BDEV];
+extern GdkColor drawing_colors_virt[NUM_COLORS_VIRT];
 
 /* This part of the viewer does :
  * Draw horizontal lines, getting graphic context as arg.
diff --git a/lttv/modules/gui/resourceview/eventhooks.c b/lttv/modules/gui/resourceview/eventhooks.c
index 271e8d2..18e2c07 100644
--- a/lttv/modules/gui/resourceview/eventhooks.c
+++ b/lttv/modules/gui/resourceview/eventhooks.c
@@ -286,7 +286,11 @@ static void cpu_set_line_color(PropertiesLine *prop_line, LttvCPUState *s)
   }
   else if(present_state == LTTV_CPU_TRAP) {
     prop_line->color = drawing_colors_cpu[COL_CPU_TRAP];
-  } else {
+  }
+  else if(present_state == LTTV_CPU_VIRT) {
+    prop_line->color = drawing_colors_cpu[COL_CPU_VIRT];
+  }
+  else {
     prop_line->color = drawing_colors_cpu[COL_CPU_UNKNOWN];
   }
 }
@@ -352,6 +356,15 @@ static void bdev_set_line_color(PropertiesLine *prop_line, LttvBdevState *s)
   }
 }
 
+static void virt_set_line_color(PropertiesLine *prop_line, LttvVirtState *s)
+{
+  GQuark present_state;
+  if(s->running == 0)
+    prop_line->color = drawing_colors_virt[COL_VIRT_IDLE];
+  else
+    prop_line->color = drawing_colors_virt[COL_VIRT_BUSY];
+}
+
 /* before_schedchange_hook
  * 
  * This function basically draw lines and icons. Two types of lines are drawn :
@@ -624,6 +637,7 @@ int after_schedchange_hook(void *hook_data, void *call_data)
 int before_execmode_hook_irq(void *hook_data, void *call_data);
 int before_execmode_hook_soft_irq(void *hook_data, void *call_data);
 int before_execmode_hook_trap(void *hook_data, void *call_data);
+int before_execmode_hook_virt(void *hook_data, void *call_data);
 
 /* before_execmode_hook
  * 
@@ -661,6 +675,7 @@ int before_execmode_hook(void *hook_data, void *call_data)
   before_execmode_hook_irq(hook_data, call_data);
   before_execmode_hook_soft_irq(hook_data, call_data);
   before_execmode_hook_trap(hook_data, call_data);
+//  before_execmode_hook_virt(hook_data, call_data);
 
   /* we are in a execmode, before the state update. We must draw the
    * items corresponding to the state before it changes : now is the right
@@ -2026,7 +2041,9 @@ void draw_closure(gpointer key, gpointer value, gpointer user_data)
             // the lookup may return null; bdev_set_line_color must act appropriately
             bdev_set_line_color(&prop_line, bdev);
           }
-          
+          else if(hashed_process_data->type == RV_RESOURCE_VIRT) {
+              virt_set_line_color(&prop_line, &ts->virt_states[process_info->id]);
+          }
           draw_line((void*)&prop_line, (void*)&draw_context);
         }
 
diff --git a/lttv/modules/gui/resourceview/eventhooks.h b/lttv/modules/gui/resourceview/eventhooks.h
index 9ff63b3..e9bf8b6 100644
--- a/lttv/modules/gui/resourceview/eventhooks.h
+++ b/lttv/modules/gui/resourceview/eventhooks.h
@@ -137,4 +137,7 @@ HashedResourceData *resourcelist_obtain_trap(ControlFlowData *resourceview_data,
 HashedResourceData *resourcelist_obtain_bdev(ControlFlowData *resourceview_data,
   guint trace_num, guint id);
 
+HashedResourceData *resourcelist_obtain_virt(ControlFlowData *resourceview_data,
+		guint trace_num, guint id);
+
 #endif // _EVENT_HOOKS_H
diff --git a/lttv/modules/gui/resourceview/processlist.c b/lttv/modules/gui/resourceview/processlist.c
index ee24ba6..e317aff 100644
--- a/lttv/modules/gui/resourceview/processlist.c
+++ b/lttv/modules/gui/resourceview/processlist.c
@@ -446,6 +446,7 @@ ProcessList *processlist_construct(void)
   process_list->restypes[RV_RESOURCE_SOFT_IRQ].hash_table = g_hash_table_new(ru_numeric_hash_fct, ru_numeric_equ_fct);
   process_list->restypes[RV_RESOURCE_TRAP].hash_table = g_hash_table_new(ru_numeric_hash_fct, ru_numeric_equ_fct);
   process_list->restypes[RV_RESOURCE_BDEV].hash_table = g_hash_table_new(ru_numeric_hash_fct, ru_numeric_equ_fct);
+  process_list->restypes[RV_RESOURCE_VIRT].hash_table = g_hash_table_new(ru_numeric_hash_fct, ru_numeric_equ_fct);
   
   return process_list;
 }
@@ -578,6 +579,18 @@ GQuark make_bdev_name(ControlFlowData *resourceview_data, guint trace_num, guint
   return name;
 }
 
+GQuark make_virt_name(ControlFlowData *resourceview_data, guint trace_num, guint id)
+{
+	GQuark name;
+	gchar *str;
+
+	str = g_strdup_printf("Virt %u", id);
+	name = g_quark_from_string(str);
+	g_free(str);
+
+	return name;
+}
+
 HashedResourceData *resourcelist_obtain_machine(ControlFlowData *resourceview_data, guint trace_num, guint id)
 {
   ResourceUniqueNumeric *ru = g_new(ResourceUniqueNumeric, 1);
@@ -819,3 +832,7 @@ HashedResourceData *resourcelist_obtain_bdev(ControlFlowData *resourceview_data,
   return resourcelist_obtain_generic(resourceview_data, RV_RESOURCE_BDEV, trace_num, id, make_bdev_name);
 }
 
+HashedResourceData *resourcelist_obtain_virt(ControlFlowData *resourceview_data, guint trace_num, guint id)
+{
+	return resourcelist_obtain_generic(resourceview_data, RV_RESOURCE_VIRT, trace_num, id, make_virt_name);
+}
diff --git a/lttv/modules/gui/resourceview/processlist.h b/lttv/modules/gui/resourceview/processlist.h
index ce32e16..7126fc6 100644
--- a/lttv/modules/gui/resourceview/processlist.h
+++ b/lttv/modules/gui/resourceview/processlist.h
@@ -47,7 +47,8 @@
 #define RV_RESOURCE_SOFT_IRQ  3
 #define RV_RESOURCE_TRAP      4
 #define RV_RESOURCE_BDEV      5
-#define RV_RESOURCE_COUNT     6
+#define RV_RESOURCE_VIRT      6
+#define RV_RESOURCE_COUNT     7
 
 /* Enumeration of the columns */
 enum
@@ -304,5 +305,6 @@ HashedResourceData *resourcelist_obtain_irq(ControlFlowData *resourceview_data,
 HashedResourceData *resourcelist_obtain_soft_irq(ControlFlowData *resourceview_data, guint trace_num, guint id);
 HashedResourceData *resourcelist_obtain_trap(ControlFlowData *resourceview_data, guint trace_num, guint id);
 HashedResourceData *resourcelist_obtain_bdev(ControlFlowData *resourceview_data, guint trace_num, guint id);
+HashedResourceData *resourcelist_obtain_virt(ControlFlowData *resourceview_data, guint trace_num, guint id);
 
 #endif // _PROCESS_LIST_H
-- 
1.7.0.4





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

end of thread, other threads:[~2010-09-09 14:03 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-09-09 14:03 [ltt-dev] [PATCH 1/2] Add the VIRT state Julien Desfossez
2010-09-09 14:03 ` [ltt-dev] [PATCH 2/2] Display the VIRT state in resource view Julien Desfossez

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox