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.


deallocation of devices
[palacios.git] / palacios / src / devices / generic.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, Peter Dinda <pdinda@northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Peter Dinda <pdinda@northwestern.edu>
15  * Contributor: 2008, Jack Lange <jarusl@cs.northwestern.edu>
16  *        
17  *
18  * This is free software.  You are permitted to use,
19  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20  */
21
22 #include <palacios/vmm.h>
23 #include <palacios/vmm_types.h>
24 #include <palacios/vmm_list.h>
25 #include <palacios/vmm_io.h>
26 #include <palacios/vmm_dev_mgr.h>
27
28 #ifndef CONFIG_DEBUG_GENERIC
29 #undef PrintDebug
30 #define PrintDebug(fmt, args...)
31 #endif
32
33
34 typedef enum {GENERIC_IGNORE, 
35               GENERIC_PASSTHROUGH, 
36               GENERIC_PRINT_AND_PASSTHROUGH, 
37               GENERIC_PRINT_AND_IGNORE} generic_mode_t;
38
39 struct generic_internal {
40 };
41
42
43 struct port_range {
44     uint_t start;
45     uint_t end;
46     generic_mode_t mode;
47     struct list_head range_link;
48 };
49
50
51
52
53
54 static int generic_write_port_passthrough(struct guest_info * core, uint16_t port, void * src, 
55                                           uint_t length, void * priv_data) {
56     uint_t i;
57
58     PrintDebug("generic: writing 0x");
59
60     for (i = 0; i < length; i++) { 
61         PrintDebug("%x", ((uint8_t *)src)[i]);
62     }
63   
64     PrintDebug(" to port 0x%x ... ", port);
65
66     switch (length) {
67         case 1:
68             v3_outb(port, ((uint8_t *)src)[0]);
69             break;
70         case 2:
71             v3_outw(port, ((uint16_t *)src)[0]);
72             break;
73         case 4:
74             v3_outdw(port, ((uint32_t *)src)[0]);
75             break;
76         default:
77             for (i = 0; i < length; i++) { 
78                 v3_outb(port, ((uint8_t *)src)[i]);
79             }
80     }
81
82     PrintDebug(" done\n");
83   
84     return length;
85 }
86
87 static int generic_read_port_passthrough(struct guest_info * core, uint16_t port, void * src, 
88                                          uint_t length, void * priv_data) {
89     uint_t i;
90
91     PrintDebug("generic: reading 0x%x bytes from port 0x%x ...", length, port);
92
93
94     switch (length) {
95         case 1:
96             ((uint8_t *)src)[0] = v3_inb(port);
97             break;
98         case 2:
99             ((uint16_t *)src)[0] = v3_inw(port);
100             break;
101         case 4:
102             ((uint32_t *)src)[0] = v3_indw(port);
103             break;
104         default:
105             for (i = 0; i < length; i++) { 
106                 ((uint8_t *)src)[i] = v3_inb(port);
107             }
108     }
109
110     PrintDebug(" done ... read 0x");
111
112     for (i = 0; i < length; i++) { 
113         PrintDebug("%x", ((uint8_t *)src)[i]);
114     }
115
116     PrintDebug("\n");
117
118     return length;
119 }
120
121 static int generic_write_port_ignore(struct guest_info * core, uint16_t port, void * src, 
122                                      uint_t length, void * priv_data) {
123     int i;
124
125     PrintDebug("generic: writing 0x");
126
127     for (i = 0; i < length; i++) { 
128         PrintDebug("%x", ((uint8_t *)src)[i]);
129     }
130   
131     PrintDebug(" to port 0x%x ... ignored\n", port);
132  
133     return length;
134 }
135
136 static int generic_read_port_ignore(struct guest_info * core, uint16_t port, void * src, 
137                                     uint_t length, void * priv_data) {
138
139     PrintDebug("generic: reading 0x%x bytes from port 0x%x ...", length, port);
140
141     memset((uint8_t *)src, 0, length);
142     PrintDebug(" ignored (return zeroed buffer)\n");
143
144     return length;
145 }
146
147
148
149
150
151 static int generic_free(struct generic_internal * state) {
152     PrintDebug("generic: deinit_device\n");
153
154     V3_Free(state);
155     return 0;
156 }
157
158
159
160
161
162 static struct v3_device_ops dev_ops = { 
163     .free = (int (*)(void *))generic_free, 
164 };
165
166
167
168
169 static int add_port_range(struct vm_device * dev, uint_t start, uint_t end, generic_mode_t mode) {
170     uint_t i = 0;
171
172     PrintDebug("generic: Adding Port Range: 0x%x to 0x%x as %s\n", 
173                start, end, 
174                (mode == GENERIC_PRINT_AND_PASSTHROUGH) ? "print-and-passthrough" : "print-and-ignore");
175     
176     for (i = start; i <= end; i++) { 
177         if (mode == GENERIC_PRINT_AND_PASSTHROUGH) { 
178             if (v3_dev_hook_io(dev, i, 
179                                 &generic_read_port_passthrough, 
180                                 &generic_write_port_passthrough) == -1) { 
181                 PrintError("generic: can't hook port 0x%x (already hooked?)\n", i);
182                 return -1;
183             }
184         } else if (mode == GENERIC_PRINT_AND_IGNORE) { 
185             if (v3_dev_hook_io(dev, i, 
186                                 &generic_read_port_ignore, 
187                                 &generic_write_port_ignore) == -1) { 
188                 PrintError("generic: can't hook port 0x%x (already hooked?)\n", i);
189                 return -1;
190             }
191         } 
192     }
193     
194     return 0;
195 }
196
197
198
199
200
201 static int generic_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) {
202     struct generic_internal * state = NULL;
203     char * dev_id = v3_cfg_val(cfg, "ID");
204     v3_cfg_tree_t * port_cfg = v3_cfg_subtree(cfg, "ports");
205
206
207     state = (struct generic_internal *)V3_Malloc(sizeof(struct generic_internal));
208
209     if (state == NULL) {
210         PrintError("Could not allocate generic state\n");
211         return -1;
212     }
213     
214     memset(state, 0, sizeof(struct generic_internal));
215     
216     struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, state);
217
218     if (dev == NULL) {
219         PrintError("Could not attach device %s\n", dev_id);
220         V3_Free(state);
221         return -1;
222     }
223
224     PrintDebug("generic: init_device\n");
225
226     // scan port list....
227     while (port_cfg) {
228         uint16_t start = atox(v3_cfg_val(port_cfg, "start"));
229         uint16_t end = atox(v3_cfg_val(port_cfg, "end"));
230         char * mode_str = v3_cfg_val(port_cfg, "mode");
231         generic_mode_t mode = GENERIC_IGNORE;
232
233         if (strcasecmp(mode_str, "print_and_ignore") == 0) {
234             mode = GENERIC_PRINT_AND_IGNORE;
235         } else if (strcasecmp(mode_str, "print_and_passthrough") == 0) {
236             mode = GENERIC_PRINT_AND_PASSTHROUGH;
237         } else {
238             PrintError("Invalid Mode %s\n", mode_str);
239             v3_remove_device(dev);
240             return -1;
241         }
242         
243         if (add_port_range(dev, start, end, mode) == -1) {
244             PrintError("Could not add port range %d-%d\n", start, end);
245             v3_remove_device(dev);
246             return -1;
247         }
248
249         port_cfg = v3_cfg_next_branch(port_cfg);
250     }
251
252
253     return 0;
254 }
255
256 device_register("GENERIC", generic_init)