Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


added dedicated debugging framework with associated interface
[palacios.git] / palacios / src / palacios / vmm_debug.c
1 /* 
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20
21 #include <palacios/vmm_debug.h>
22 #include <palacios/vmm.h>
23 #include <palacios/vmm_host_events.h>
24 #include <palacios/vm_guest.h>
25 #include <palacios/vmm_decoder.h>
26 #include <palacios/vm_guest_mem.h>
27
28 #define PRINT_TELEMETRY  1
29 #define PRINT_CORE_STATE 2
30 #define PRINT_ARCH_STATE 3
31 #define PRINT_STACK      4
32 #define PRINT_BACKTRACE  5
33
34
35 #define PRINT_ALL        100 // Absolutely everything
36 #define PRINT_STATE      101 // telemetry, core state, arch state
37
38
39
40
41 static int core_handler(struct guest_info * core, uint32_t cmd) {
42
43
44     switch (cmd) {
45         case PRINT_TELEMETRY: 
46             v3_print_core_telemetry(core);
47             break;
48         
49         case PRINT_CORE_STATE:
50             v3_raise_barrier(core->vm_info, NULL);
51
52             v3_print_guest_state(core);
53
54             v3_lower_barrier(core->vm_info);
55             break;
56         case PRINT_ARCH_STATE:
57             v3_raise_barrier(core->vm_info, NULL);
58
59             v3_print_arch_state(core);
60
61             v3_lower_barrier(core->vm_info);
62             break;
63         case PRINT_STACK:
64             v3_raise_barrier(core->vm_info, NULL);
65
66             v3_print_stack(core);
67
68             v3_lower_barrier(core->vm_info);
69             break;
70         case PRINT_BACKTRACE:
71             v3_raise_barrier(core->vm_info, NULL);
72
73             v3_print_backtrace(core);
74             
75             v3_lower_barrier(core->vm_info);
76             break;
77
78         case PRINT_STATE:
79             v3_raise_barrier(core->vm_info, NULL);
80
81             v3_print_core_telemetry(core);
82             v3_print_guest_state(core);
83             v3_print_arch_state(core);
84
85             v3_lower_barrier(core->vm_info);
86             break;
87
88     }
89
90     return 0;
91 }
92
93
94 static int evt_handler(struct v3_vm_info * vm, struct v3_debug_event * evt, void * priv_data) {
95
96     V3_Print("Debug Event Handler for core %d\n", evt->core_id);
97
98     if (evt->core_id == -1) {
99         int i = 0;
100         for (i = 0; i < vm->num_cores; i++) {
101             core_handler(&(vm->cores[i]), evt->cmd);
102         }
103     } else {
104         return core_handler(&vm->cores[evt->core_id], evt->cmd);
105     }
106
107     
108     return 0;
109 }
110
111
112 int v3_init_vm_debugging(struct v3_vm_info * vm) {
113     v3_hook_host_event(vm, HOST_DEBUG_EVT, 
114                        V3_HOST_EVENT_HANDLER(evt_handler), 
115                        NULL);
116
117
118     return 0;
119 }
120
121
122
123
124
125 void v3_print_segments(struct v3_segments * segs) {
126     int i = 0;
127     struct v3_segment * seg_ptr;
128
129     seg_ptr=(struct v3_segment *)segs;
130   
131     char *seg_names[] = {"CS", "DS" , "ES", "FS", "GS", "SS" , "LDTR", "GDTR", "IDTR", "TR", NULL};
132     V3_Print("Segments\n");
133
134     for (i = 0; seg_names[i] != NULL; i++) {
135
136         V3_Print("\t%s: Sel=%x, base=%p, limit=%x (long_mode=%d, db=%d)\n", seg_names[i], seg_ptr[i].selector, 
137                    (void *)(addr_t)seg_ptr[i].base, seg_ptr[i].limit,
138                    seg_ptr[i].long_mode, seg_ptr[i].db);
139
140     }
141 }
142
143
144
145 void v3_print_ctrl_regs(struct guest_info * core) {
146     struct v3_ctrl_regs * regs = &(core->ctrl_regs);
147     int i = 0;
148     v3_reg_t * reg_ptr;
149     char * reg_names[] = {"CR0", "CR2", "CR3", "CR4", "CR8", "FLAGS", "EFER", NULL};
150    
151
152     reg_ptr = (v3_reg_t *)regs;
153
154     V3_Print("Ctrl Regs:\n");
155
156     for (i = 0; reg_names[i] != NULL; i++) {
157         V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));  
158     }
159
160
161 }
162
163 #if 0
164 static int safe_gva_to_hva(struct guest_info * core, addr_t linear_addr, addr_t * host_addr) {
165     /* select the proper translation based on guest mode */
166     if (core->mem_mode == PHYSICAL_MEM) {
167         if (v3_gpa_to_hva(core, linear_addr, host_addr) == -1) return -1;
168     } else if (core->mem_mode == VIRTUAL_MEM) {
169         if (v3_gva_to_hva(core, linear_addr, host_addr) == -1) return -1;
170     }
171     return 0;
172 }
173
174 static int v3_print_disassembly(struct guest_info * core) {
175     int passed_rip = 0;
176     addr_t rip, rip_linear, rip_host;
177
178     /* we don't know where the instructions preceding RIP start, so we just take
179      * a guess and hope the instruction stream synced up with our disassembly
180      * some time before RIP; if it has not we correct RIP at that point
181      */
182
183     /* start disassembly 64 bytes before current RIP, continue 32 bytes after */
184     rip = (addr_t) core->rip - 64;
185     while ((int) (rip - core->rip) < 32) {
186         V3_Print("disassembly step\n");
187
188         /* always print RIP, even if the instructions before were bad */
189         if (!passed_rip && rip >= core->rip) {
190             if (rip != core->rip) {
191                 V3_Print("***** bad disassembly up to this point *****\n");
192                 rip = core->rip;
193             }
194             passed_rip = 1;
195         }
196
197         /* look up host virtual address for this instruction */
198         rip_linear = get_addr_linear(core, rip, &(core->segments.cs));
199         if (safe_gva_to_hva(core, rip_linear, &rip_host) < 0) {
200             rip++;
201             continue;
202         }
203
204         /* print disassembled instrcution (updates rip) */
205         if (v3_disasm(core, (void *) rip_host, &rip, rip == core->rip) < 0) {
206             rip++;
207             continue;
208         }
209
210     }
211
212     return 0;
213 }
214
215 #endif
216
217 void v3_print_guest_state(struct guest_info * core) {
218     addr_t linear_addr = 0; 
219
220     V3_Print("RIP: %p\n", (void *)(addr_t)(core->rip));
221     linear_addr = get_addr_linear(core, core->rip, &(core->segments.cs));
222     V3_Print("RIP Linear: %p\n", (void *)linear_addr);
223
224     V3_Print("NumExits: %u\n", (uint32_t)core->num_exits);
225
226     V3_Print("IRQ STATE: started=%d, pending=%d\n", 
227              core->intr_core_state.irq_started, 
228              core->intr_core_state.irq_pending);
229     V3_Print("EXCP STATE: err_code_valid=%d, err_code=%x\n", 
230              core->excp_state.excp_error_code_valid, 
231              core->excp_state.excp_error_code);
232
233
234     v3_print_segments(&(core->segments));
235     v3_print_ctrl_regs(core);
236
237     if (core->shdw_pg_mode == SHADOW_PAGING) {
238         V3_Print("Shadow Paging Guest Registers:\n");
239         V3_Print("\tGuest CR0=%p\n", (void *)(addr_t)(core->shdw_pg_state.guest_cr0));
240         V3_Print("\tGuest CR3=%p\n", (void *)(addr_t)(core->shdw_pg_state.guest_cr3));
241         V3_Print("\tGuest EFER=%p\n", (void *)(addr_t)(core->shdw_pg_state.guest_efer.value));
242         // CR4
243     }
244     v3_print_GPRs(core);
245
246     v3_print_mem_map(core->vm_info);
247
248     v3_print_stack(core);
249
250     //  v3_print_disassembly(core);
251 }
252
253
254 void v3_print_arch_state(struct guest_info * core) {
255
256
257 }
258
259
260 void v3_print_guest_state_all(struct v3_vm_info * vm) {
261     int i = 0;
262
263     V3_Print("VM Core states for %s\n", vm->name);
264
265     for (i = 0; i < 80; i++) {
266         V3_Print("-");
267     }
268
269     for (i = 0; i < vm->num_cores; i++) {
270         v3_print_guest_state(&vm->cores[i]);  
271     }
272     
273     for (i = 0; i < 80; i++) {
274         V3_Print("-");
275     }
276
277     V3_Print("\n");    
278 }
279
280
281
282 void v3_print_stack(struct guest_info * core) {
283     addr_t linear_addr = 0;
284     addr_t host_addr = 0;
285     int i = 0;
286     v3_cpu_mode_t cpu_mode = v3_get_vm_cpu_mode(core);
287
288     linear_addr = get_addr_linear(core, core->vm_regs.rsp, &(core->segments.ss));
289  
290     V3_Print("Stack at %p:\n", (void *)linear_addr);
291    
292     if (core->mem_mode == PHYSICAL_MEM) {
293         if (v3_gpa_to_hva(core, linear_addr, &host_addr) == -1) {
294             PrintError("Could not translate Stack address\n");
295             return;
296         }
297     } else if (core->mem_mode == VIRTUAL_MEM) {
298         if (v3_gva_to_hva(core, linear_addr, &host_addr) == -1) {
299             PrintError("Could not translate Virtual Stack address\n");
300             return;
301         }
302     }
303     
304     V3_Print("Host Address of rsp = 0x%p\n", (void *)host_addr);
305  
306     // We start i at one because the current stack pointer points to an unused stack element
307     for (i = 0; i <= 24; i++) {
308
309         if (cpu_mode == REAL) {
310             V3_Print("\t0x%.4x\n", *((uint16_t *)host_addr + (i * 2)));
311         } else if (cpu_mode == LONG) {
312             V3_Print("\t%p\n", (void *)*(addr_t *)(host_addr + (i * 8)));
313         } else {
314             // 32 bit stacks...
315             V3_Print("\t0x%.8x\n", *(uint32_t *)(host_addr + (i * 4)));
316         }
317     }
318
319 }    
320
321
322 void v3_print_backtrace(struct guest_info * core) {
323     addr_t gla_rbp = 0;
324     int i = 0;
325     v3_cpu_mode_t cpu_mode = v3_get_vm_cpu_mode(core);
326
327     V3_Print("Performing Backtrace for Core %d\n", core->vcpu_id);
328     V3_Print("\tRSP=%p, RBP=%p\n", (void *)core->vm_regs.rsp, (void *)core->vm_regs.rbp);
329
330     gla_rbp = get_addr_linear(core, core->vm_regs.rbp, &(core->segments.ss));
331
332     for (i = 0; i < 10; i++) {
333         addr_t hva_rbp = 0; 
334         addr_t hva_rip = 0; 
335
336         if (core->mem_mode == PHYSICAL_MEM) {
337             if (v3_gpa_to_hva(core, gla_rbp, &hva_rbp) == -1) {
338                 PrintError("Could not translate Stack address\n");
339                 return;
340             }
341         } else if (core->mem_mode == VIRTUAL_MEM) {
342             if (v3_gva_to_hva(core, gla_rbp, &hva_rbp) == -1) {
343                 PrintError("Could not translate Virtual Stack address\n");
344                 return;
345             }
346         }
347
348         hva_rip = hva_rbp + v3_get_addr_width(core);
349
350         
351         if (cpu_mode == REAL) {
352             V3_Print("Next RBP=0x%.4x, RIP=0x%.4x\n", *(uint16_t *)hva_rbp,*(uint16_t *)hva_rip);
353             gla_rbp = *(uint16_t *)hva_rbp;
354         } else if (cpu_mode == LONG) {
355             V3_Print("Next RBP=%p, RIP=%p\n", (void *)*(uint64_t *)hva_rbp, (void *)*(uint64_t *)hva_rip);
356             gla_rbp = *(uint64_t *)hva_rbp;
357         } else {
358             V3_Print("Next RBP=0x%.8x, RIP=0x%.8x\n", *(uint32_t *)hva_rbp, *(uint32_t *)hva_rip);
359             gla_rbp = *(uint32_t *)hva_rbp;
360         }
361     }
362 }
363
364
365 #ifdef __V3_32BIT__
366
367 void v3_print_GPRs(struct guest_info * core) {
368     struct v3_gprs * regs = &(core->vm_regs);
369     int i = 0;
370     v3_reg_t * reg_ptr;
371     char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", NULL};
372
373     reg_ptr = (v3_reg_t *)regs;
374
375     V3_Print("32 bit GPRs:\n");
376
377     for (i = 0; reg_names[i] != NULL; i++) {
378         V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));  
379     }
380 }
381
382 #elif __V3_64BIT__
383
384 void v3_print_GPRs(struct guest_info * core) {
385     struct v3_gprs * regs = &(core->vm_regs);
386     int i = 0;
387     v3_reg_t * reg_ptr;
388     char * reg_names[] = { "RDI", "RSI", "RBP", "RSP", "RBX", "RDX", "RCX", "RAX", \
389                            "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", NULL};
390
391     reg_ptr = (v3_reg_t *)regs;
392
393     V3_Print("64 bit GPRs:\n");
394
395     for (i = 0; reg_names[i] != NULL; i++) {
396         V3_Print("\t%s=0x%p (at %p)\n", reg_names[i], (void *)(addr_t)reg_ptr[i], &(reg_ptr[i]));  
397     }
398 }
399
400 #endif