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.


add v3vee copyright info
[palacios.git] / linux_module / palacios-vnet.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) 2011, Lei Xia <lxia@northwestern.edu>
11  * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
12  * All rights reserved.
13  *
14  * This is free software.  You are permitted to use, redistribute,
15  * and modify it under the terms of the GNU General Public License
16  * Version 2 (GPLv2).  The accompanying COPYING file contains the
17  * full text of the license.
18  */
19 /* Palacios VNET Host Hooks Implementations */
20
21 #include <linux/kernel.h>
22 #include <linux/kthread.h>
23 #include <linux/spinlock.h>
24 #include <linux/gfp.h>
25 #include <linux/sched.h>
26 #include <linux/uaccess.h>
27 #include <linux/init.h>
28 #include <linux/smp_lock.h>
29 #include <asm/delay.h>
30 #include <linux/timer.h>
31
32 #include <vnet/vnet.h>
33 #include "mm.h"
34 #include "palacios-vnet.h"
35 #include "linux-exts.h"
36
37 static void host_print(const char *     fmt, ...) {
38
39     va_list ap;
40     va_start(ap, fmt);
41     vprintk(fmt, ap);
42     va_end(ap);
43
44     return;
45 }
46
47
48 static void * host_allocate_pages(int num_pages, unsigned int alignment){
49     uintptr_t addr = 0; 
50     struct page * pgs = NULL;
51     int order = get_order(num_pages * PAGE_SIZE);
52          
53     pgs = alloc_pages(GFP_KERNEL, order);
54     
55     WARN(!pgs, "Could not allocate pages\n");
56        
57     addr = page_to_pfn(pgs) << PAGE_SHIFT; 
58    
59     return (void *)addr;
60 }
61
62
63 static void host_free_pages(void * page_paddr, int num_pages) {
64     uintptr_t pg_addr = (uintptr_t)page_paddr;
65         
66     __free_pages(pfn_to_page(pg_addr >> PAGE_SHIFT), get_order(num_pages * PAGE_SIZE));
67 }
68
69
70 static void *
71 host_alloc(unsigned int size) {
72     void * addr;
73     addr =  kmalloc(size, GFP_KERNEL);
74
75     return addr;
76 }
77
78 static void
79 host_free(
80         void *                  addr
81 )
82 {
83     kfree(addr);
84     return;
85 }
86
87 static void *
88 host_vaddr_to_paddr(void * vaddr)
89 {
90     return (void*) __pa(vaddr);
91
92 }
93
94 static void *
95 host_paddr_to_vaddr(void * paddr)
96 {
97     return __va(paddr);
98 }
99
100
101 static void *
102 host_start_kernel_thread(
103         int (*fn)(void * arg),
104         void * arg,
105         char * thread_name) {
106     struct task_struct * thread = NULL;
107
108     thread = kthread_run(fn, arg, thread_name );
109
110     return thread;
111 }
112
113 static void host_kthread_sleep(long timeout){
114     set_current_state(TASK_INTERRUPTIBLE);
115
116     if(timeout <= 0){
117         schedule();
118     }else {
119        schedule_timeout(timeout);
120     }
121
122     return;
123 }
124
125 static void host_kthread_wakeup(void * thread){
126     struct task_struct * kthread = (struct task_struct *)thread;
127         
128     wake_up_process(kthread);
129 }
130
131 static void host_kthread_stop(void * thread){
132     struct task_struct * kthread = (struct task_struct *)thread;
133
134     kthread_stop(kthread);
135 }
136
137 static int host_kthread_should_stop(void){
138     return kthread_should_stop();
139 }
140
141
142 static void host_udelay(unsigned long usecs){
143     udelay(usecs);
144 }
145
146
147
148 static void
149 host_yield_cpu(void)
150 {
151     schedule();
152     return;
153 }
154
155 static void *
156 host_mutex_alloc(void)
157 {
158     spinlock_t * lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
159
160     if (lock) {
161         spin_lock_init(lock);
162     }
163
164     return lock;
165 }
166
167 static void
168 host_mutex_free(
169         void * mutex
170
171 {
172     kfree(mutex);
173 }
174
175 static void 
176 host_mutex_lock(void * mutex, 
177                 int must_spin)
178 {
179     spin_lock((spinlock_t *)mutex);
180 }
181
182 static void 
183 host_mutex_unlock(void * mutex) 
184 {
185     spin_unlock((spinlock_t *)mutex);
186 }
187
188
189
190
191 struct host_timer {
192     struct timer_list timer;
193     unsigned long interval;
194
195     int active;
196     void (* timer_fun)(void * private_data);
197     void * pri_data;
198 };
199
200
201 void timeout_fn(unsigned long arg){
202     struct host_timer * timer = (struct host_timer *)arg;
203
204     if(timer->active){
205         timer->timer_fun(timer->pri_data);
206         
207         mod_timer(&(timer->timer), timer->interval);
208     }
209 }
210
211 static void *
212 host_create_timer(unsigned long interval, 
213                   void (* timer_fun)(void * priv_data), 
214                   void * data){
215     struct host_timer * timer = (struct host_timer *)kmalloc(sizeof(struct host_timer), GFP_KERNEL);
216
217     timer->interval = interval;
218     timer->timer_fun = timer_fun;
219     timer->pri_data = data;
220
221     init_timer(&(timer->timer));
222
223     timer->timer.data = (unsigned long)timer;
224     timer->timer.function = timeout_fn;
225     timer->timer.expires = interval;
226
227     return timer;
228 }
229
230 static void
231 host_start_timer(void * vnet_timer){
232     struct host_timer * timer = (struct host_timer *)vnet_timer;
233
234     timer->active = 1;
235     add_timer(&(timer->timer));
236 }
237
238 static void
239 host_reset_timer(void * vnet_timer, unsigned long interval){
240     struct host_timer * timer = (struct host_timer *)timer;
241
242     timer->interval = interval;
243 }
244
245 static void
246 host_stop_timer(void * vnet_timer){
247     struct host_timer * timer = (struct host_timer *)vnet_timer;
248
249     timer->active = 0;
250     del_timer(&(timer->timer));
251 }
252
253 static void
254 host_del_timer(void * vnet_timer){
255     struct host_timer * timer = (struct host_timer *)vnet_timer;
256
257     del_timer(&(timer->timer));
258
259     kfree(timer);
260 }
261
262
263
264
265
266 static struct vnet_host_hooks vnet_host_hooks = {
267     .timer_create       = host_create_timer,
268     .timer_del          = host_del_timer,
269     .timer_start                = host_start_timer,
270     .timer_stop         = host_stop_timer,
271     .timer_reset        = host_reset_timer,
272
273     .thread_start       = host_start_kernel_thread,
274     .thread_sleep       = host_kthread_sleep,
275     .thread_wakeup      = host_kthread_wakeup,
276     .thread_stop        = host_kthread_stop,
277     .thread_should_stop = host_kthread_should_stop,
278     .udelay     = host_udelay,
279
280     .yield_cpu          = host_yield_cpu,
281     .mutex_alloc        = host_mutex_alloc,
282     .mutex_free = host_mutex_free,
283     .mutex_lock = host_mutex_lock, 
284     .mutex_unlock       = host_mutex_unlock,
285
286     .print                      = host_print,
287     .allocate_pages     = host_allocate_pages,
288     .free_pages = host_free_pages,
289     .malloc             = host_alloc,
290     .free                       = host_free,
291     .vaddr_to_paddr             = host_vaddr_to_paddr,
292     .paddr_to_vaddr             = host_paddr_to_vaddr,
293 };
294
295
296
297 static int vnet_init( void ) {
298     init_vnet(&vnet_host_hooks);
299         
300     vnet_bridge_init();
301     vnet_ctrl_init();
302
303     printk("V3 VNET Inited\n");
304         
305     return 0;
306 }
307
308
309 static int vnet_deinit( void ) {
310     deinit_vnet();
311
312     vnet_bridge_deinit();
313     vnet_ctrl_deinit();
314
315     printk("V3 VNET Deinited\n");
316
317     return 0;
318 }
319
320 static struct linux_ext vnet_ext = {
321     .name = "VNET",
322     .init = vnet_init,
323     .deinit = vnet_deinit,
324     .guest_init = NULL,
325     .guest_deinit = NULL
326 };
327
328 register_extension(&vnet_ext);