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.


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