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.


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