1 /* (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> */
2 /* (c) 2008, The V3VEE Project <http://www.v3vee.org> */
4 #include <palacios/vmm_io.h>
5 #include <palacios/vmm_string.h>
6 #include <palacios/vmm.h>
13 #define PrintDebug(fmt, args...)
17 static int default_write(ushort_t port, void *src, uint_t length, void * priv_data);
18 static int default_read(ushort_t port, void * dst, uint_t length, void * priv_data);
21 void init_vmm_io_map(struct guest_info * info) {
22 struct vmm_io_map * io_map = &(info->io_map);
23 io_map->num_ports = 0;
31 static int add_io_hook(struct vmm_io_map * io_map, struct vmm_io_hook * io_hook) {
33 if (!(io_map->head)) {
34 io_map->head = io_hook;
35 io_map->num_ports = 1;
37 } else if (io_map->head->port > io_hook->port) {
38 io_hook->next = io_map->head;
40 io_map->head->prev = io_hook;
41 io_map->head = io_hook;
46 struct vmm_io_hook * tmp_hook = io_map->head;
48 while ((tmp_hook->next) &&
49 (tmp_hook->next->port <= io_hook->port)) {
50 tmp_hook = tmp_hook->next;
53 if (tmp_hook->port == io_hook->port) {
54 //tmp_hook->read = io_hook->read;
55 //tmp_hook->write = io_hook->write;
59 io_hook->prev = tmp_hook;
60 io_hook->next = tmp_hook->next;
63 tmp_hook->next->prev = io_hook;
66 tmp_hook->next = io_hook;
75 static int remove_io_hook(struct vmm_io_map * io_map, struct vmm_io_hook * io_hook) {
76 if (io_map->head == io_hook) {
77 io_map->head = io_hook->next;
78 } else if (io_hook->prev) {
79 io_hook->prev->next = io_hook->next;
82 // data corruption failure
86 io_hook->next->prev = io_hook->prev;
98 int v3_hook_io_port(struct guest_info * info, uint_t port,
99 int (*read)(ushort_t port, void * dst, uint_t length, void * priv_data),
100 int (*write)(ushort_t port, void * src, uint_t length, void * priv_data),
102 struct vmm_io_map * io_map = &(info->io_map);
103 struct vmm_io_hook * io_hook = (struct vmm_io_hook *)V3_Malloc(sizeof(struct vmm_io_hook));
105 io_hook->port = port;
108 io_hook->read = &default_read;
110 io_hook->read = read;
114 io_hook->write = &default_write;
116 io_hook->write = write;
119 io_hook->next = NULL;
120 io_hook->prev = NULL;
122 io_hook->priv_data = priv_data;
124 if (add_io_hook(io_map, io_hook) != 0) {
132 int v3_unhook_io_port(struct guest_info * info, uint_t port) {
133 struct vmm_io_map * io_map = &(info->io_map);
134 struct vmm_io_hook * hook = v3_get_io_hook(io_map, port);
140 remove_io_hook(io_map, hook);
145 struct vmm_io_hook * v3_get_io_hook(struct vmm_io_map * io_map, uint_t port) {
146 struct vmm_io_hook * tmp_hook;
147 FOREACH_IO_HOOK(*io_map, tmp_hook) {
148 if (tmp_hook->port == port) {
157 void PrintDebugIOMap(struct vmm_io_map * io_map) {
158 struct vmm_io_hook * iter = io_map->head;
160 PrintDebug("VMM IO Map (Entries=%d)\n", io_map->num_ports);
163 PrintDebug("IO Port: %hu (Read=%x) (Write=%x)\n", iter->port, iter->read, iter->write);
170 * Write a byte to an I/O port.
172 void v3_outb(ushort_t port, uchar_t value) {
173 __asm__ __volatile__ (
176 : "a" (value), "Nd" (port)
181 * Read a byte from an I/O port.
183 uchar_t v3_inb(ushort_t port) {
186 __asm__ __volatile__ (
196 * Write a word to an I/O port.
198 void v3_outw(ushort_t port, ushort_t value) {
199 __asm__ __volatile__ (
202 : "a" (value), "Nd" (port)
207 * Read a word from an I/O port.
209 ushort_t v3_inw(ushort_t port) {
212 __asm__ __volatile__ (
222 * Write a double word to an I/O port.
224 void v3_outdw(ushort_t port, uint_t value) {
225 __asm__ __volatile__ (
228 : "a" (value), "Nd" (port)
233 * Read a double word from an I/O port.
235 uint_t v3_indw(ushort_t port) {
238 __asm__ __volatile__ (
251 static int default_write(ushort_t port, void *src, uint_t length, void * priv_data) {
255 __asm__ __volatile__ (
258 : "a" (*dst), "Nd" (port)
260 } else if (length == 2) {
261 __asm__ __volatile__ (
264 : "a" (*dst), "Nd" (port)
266 } else if (length == 4) {
267 __asm__ __volatile__ (
270 : "a" (*dst), "Nd" (port)
277 static int default_read(ushort_t port, void * dst, uint_t length, void * priv_data) {
282 __asm__ __volatile__ (