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 device checkpoint hooks
[palacios.git] / palacios / src / devices / os_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
22 #include <palacios/vmm.h>
23 #include <palacios/vmm_dev_mgr.h>
24 #include <palacios/vm_guest_mem.h>
25
26 #define BUF_SIZE 1024
27
28 #define DEBUG_PORT1 0xc0c0
29
30 struct debug_state {
31     char debug_buf[BUF_SIZE];
32     uint_t debug_offset;
33
34 };
35
36
37 static int handle_gen_write(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) {
38     struct debug_state * state = priv_data;
39
40     state->debug_buf[state->debug_offset++] = *(char*)src;
41
42     if ((*(char*)src == 0xa) ||  (state->debug_offset == (BUF_SIZE - 1))) {
43         PrintDebug("VM_CONSOLE>%s", state->debug_buf);
44         memset(state->debug_buf, 0, BUF_SIZE);
45         state->debug_offset = 0;
46     }
47
48     return length;
49 }
50
51 static int handle_hcall(struct guest_info * info, uint_t hcall_id, void * priv_data) {
52     struct debug_state * state = (struct debug_state *)priv_data;
53
54     int msg_len = info->vm_regs.rcx;
55     addr_t msg_gpa = info->vm_regs.rbx;
56     int buf_is_va = info->vm_regs.rdx;
57
58     if (msg_len >= BUF_SIZE) {
59         PrintError("Console message too large for buffer (len=%d)\n", msg_len);
60         return -1;
61     }
62
63     if (buf_is_va == 1) {
64         if (v3_read_gva_memory(info, msg_gpa, msg_len, (uchar_t *)state->debug_buf) != msg_len) {
65             PrintError("Could not read debug message\n");
66             return -1;
67         }
68     } else {
69         if (v3_read_gpa_memory(info, msg_gpa, msg_len, (uchar_t *)state->debug_buf) != msg_len) {
70             PrintError("Could not read debug message\n");
71             return -1;
72         }
73     }   
74
75     state->debug_buf[msg_len] = 0;
76
77     PrintDebug("VM_CONSOLE>%s\n", state->debug_buf);
78
79     return 0;
80 }
81
82
83
84 static int debug_free(struct debug_state * state) {
85
86     // unregister hypercall
87
88     V3_Free(state);
89     return 0;
90 };
91
92 #ifdef V3_CONFIG_CHECKPOINT
93 static int debug_save(struct v3_chkpt_ctx * ctx, void * private_data) {
94     struct debug_state * dbg = (struct debug_state *)private_data;
95     
96     V3_CHKPT_STD_SAVE(ctx, dbg->debug_buf);
97     V3_CHKPT_STD_SAVE(ctx, dbg->debug_offset);
98     
99     return 0;
100 }
101
102
103 static int debug_load(struct v3_chkpt_ctx * ctx, void * private_data) {
104     struct debug_state * dbg = (struct debug_state *)private_data;
105     
106     V3_CHKPT_STD_LOAD(ctx, dbg->debug_buf);
107     V3_CHKPT_STD_LOAD(ctx, dbg->debug_offset);
108     
109     return 0;
110 }
111
112 #endif
113
114
115
116 static struct v3_device_ops dev_ops = {
117     .free = (int (*)(void *))debug_free,
118 #ifdef V3_CONFIG_CHECKPOINT
119     .save = debug_save,
120     .load = debug_load
121 #endif 
122 };
123
124
125
126
127 static int debug_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
128     struct debug_state * state = NULL;
129     char * dev_id = v3_cfg_val(cfg, "ID");
130
131     state = (struct debug_state *)V3_Malloc(sizeof(struct debug_state));
132
133     PrintDebug("Creating OS Debug Device\n");
134
135     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, state);
136
137     if (dev == NULL) {
138         PrintError("Could not attach device %s\n", dev_id);
139         V3_Free(state);
140         return -1;
141     }
142
143     if (v3_dev_hook_io(dev, DEBUG_PORT1,  NULL, &handle_gen_write) == -1) {
144         PrintError("Error hooking OS debug IO port\n");
145         v3_remove_device(dev);
146         return -1;
147     }
148
149     v3_register_hypercall(vm, OS_DEBUG_HCALL, handle_hcall, state);
150
151     state->debug_offset = 0;
152     memset(state->debug_buf, 0, BUF_SIZE);
153   
154     return 0;
155 }
156
157
158 device_register("OS_DEBUG", debug_init)