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 new copyright and license
[palacios-OLD.git] / palacios / src / palacios / vmm_io.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 #include <palacios/vmm_io.h>
21 #include <palacios/vmm_string.h>
22 #include <palacios/vmm.h>
23
24
25
26
27 #ifndef DEBUG_IO
28 #undef PrintDebug
29 #define PrintDebug(fmt, args...)
30 #endif
31
32
33 void init_vmm_io_map(struct guest_info * info) {
34   struct vmm_io_map * io_map = &(info->io_map);
35   io_map->num_ports = 0;
36   io_map->head = NULL;
37 }
38
39
40
41
42
43 static int add_io_hook(struct vmm_io_map * io_map, struct vmm_io_hook * io_hook) {
44
45   if (!(io_map->head)) {
46     io_map->head = io_hook;
47     io_map->num_ports = 1;
48     return 0;
49   } else if (io_map->head->port > io_hook->port) {
50     io_hook->next = io_map->head;
51
52     io_map->head->prev = io_hook;
53     io_map->head = io_hook;
54     io_map->num_ports++;
55
56     return 0;
57   } else {
58     struct vmm_io_hook * tmp_hook = io_map->head;
59     
60     while ((tmp_hook->next)  && 
61            (tmp_hook->next->port <= io_hook->port)) {
62         tmp_hook = tmp_hook->next;
63     }
64     
65     if (tmp_hook->port == io_hook->port) {
66       //tmp_hook->read = io_hook->read;
67       //tmp_hook->write = io_hook->write;
68       //V3_Free(io_hook);
69       return -1;
70     } else {
71       io_hook->prev = tmp_hook;
72       io_hook->next = tmp_hook->next;
73
74       if (tmp_hook->next) {
75         tmp_hook->next->prev = io_hook;
76       }
77
78       tmp_hook->next = io_hook;
79
80       io_map->num_ports++;
81       return 0;
82     }
83   }
84   return -1;
85 }
86
87 static int remove_io_hook(struct vmm_io_map * io_map, struct vmm_io_hook * io_hook) {
88   if (io_map->head == io_hook) {
89     io_map->head = io_hook->next;
90   } else if (io_hook->prev) {
91     io_hook->prev->next = io_hook->next;
92   } else {
93     return -1;
94     // data corruption failure
95   }
96   
97   if (io_hook->next) {
98     io_hook->next->prev = io_hook->prev;
99   }
100
101   io_map->num_ports--;
102
103   return 0;
104 }
105
106
107
108 /* FIX ME */
109 static int default_write(ushort_t port, void *src, uint_t length, void * priv_data) {
110   /*
111     
112   if (length == 1) {
113   __asm__ __volatile__ (
114   "outb %b0, %w1"
115   :
116   : "a" (*dst), "Nd" (port)
117   );
118   } else if (length == 2) {
119   __asm__ __volatile__ (
120   "outw %b0, %w1"
121   :
122   : "a" (*dst), "Nd" (port)
123   );
124   } else if (length == 4) {
125   __asm__ __volatile__ (
126   "outw %b0, %w1"
127   :
128   : "a" (*dst), "Nd" (port)
129   );
130   }
131   */
132   return 0;
133 }
134
135 static int default_read(ushort_t port, void * dst, uint_t length, void * priv_data)
136 {
137
138   /*    
139         uchar_t value;
140
141     __asm__ __volatile__ (
142         "inb %w1, %b0"
143         : "=a" (value)
144         : "Nd" (port)
145     );
146
147     return value;
148   */
149
150   return 0;
151 }
152
153 int v3_hook_io_port(struct guest_info * info, uint_t port, 
154                     int (*read)(ushort_t port, void * dst, uint_t length, void * priv_data),
155                     int (*write)(ushort_t port, void * src, uint_t length, void * priv_data), 
156                     void * priv_data) {
157   struct vmm_io_map * io_map = &(info->io_map);
158   struct vmm_io_hook * io_hook = (struct vmm_io_hook *)V3_Malloc(sizeof(struct vmm_io_hook));
159
160   io_hook->port = port;
161
162   if (!read) {
163     io_hook->read = &default_read;
164   } else {
165     io_hook->read = read;
166   }
167
168   if (!write) {
169     io_hook->write = &default_write;
170   } else {
171     io_hook->write = write;
172   }
173
174   io_hook->next = NULL;
175   io_hook->prev = NULL;
176
177   io_hook->priv_data = priv_data;
178
179   if (add_io_hook(io_map, io_hook) != 0) {
180     V3_Free(io_hook);
181     return -1;
182   }
183
184   return 0;
185 }
186
187 int v3_unhook_io_port(struct guest_info * info, uint_t port) {
188   struct vmm_io_map * io_map = &(info->io_map);
189   struct vmm_io_hook * hook = v3_get_io_hook(io_map, port);
190
191   if (hook == NULL) {
192     return -1;
193   }
194
195   remove_io_hook(io_map, hook);
196   return 0;
197 }
198
199
200 struct vmm_io_hook * v3_get_io_hook(struct vmm_io_map * io_map, uint_t port) {
201   struct vmm_io_hook * tmp_hook;
202   FOREACH_IO_HOOK(*io_map, tmp_hook) {
203     if (tmp_hook->port == port) {
204       return tmp_hook;
205     }
206   }
207   return NULL;
208 }
209
210
211
212 void PrintDebugIOMap(struct vmm_io_map * io_map) {
213   struct vmm_io_hook * iter = io_map->head;
214
215   PrintDebug("VMM IO Map (Entries=%d)\n", io_map->num_ports);
216
217   while (iter) {
218     PrintDebug("IO Port: %hu (Read=%x) (Write=%x)\n", iter->port, iter->read, iter->write);
219   }
220 }