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 exit reporting to thread exit path
[palacios.git] / linux_module / palacios-stubs.c
1 #include <linux/kernel.h>
2 #include <linux/kthread.h>
3 #include <linux/spinlock.h>
4 #include <linux/gfp.h>
5 #include <linux/interrupt.h>
6 #include <linux/linkage.h>
7 #include <linux/sched.h>
8 #include <linux/uaccess.h>
9 #include <asm/irq_vectors.h>
10 #include <asm/io.h>
11
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <linux/kthread.h>
15 #include <asm/uaccess.h>
16 #include <linux/smp.h>
17
18 #include <palacios/vmm.h>
19 #include <palacios/vmm_host_events.h>
20 #include "palacios.h"
21
22
23
24
25 #include "mm.h"
26
27
28 u32 pg_allocs = 0;
29 u32 pg_frees = 0;
30 u32 mallocs = 0;
31 u32 frees = 0;
32
33
34 static struct v3_vm_info * irq_to_guest_map[256];
35
36
37 extern unsigned int cpu_khz;
38
39 extern int cpu_list[NR_CPUS];
40 extern int cpu_list_len;
41
42
43 /**
44  * Prints a message to the console.
45  */
46 static void palacios_print(const char * fmt, ...) {
47   va_list ap;
48   va_start(ap, fmt);
49   vprintk(fmt, ap);
50   va_end(ap);
51   
52   return;
53 }
54
55
56
57 /*
58  * Allocates a contiguous region of pages of the requested size.
59  * Returns the physical address of the first page in the region.
60  */
61 static void * palacios_allocate_pages(int num_pages, unsigned int alignment) {
62     void * pg_addr = NULL;
63
64     pg_addr = (void *)alloc_palacios_pgs(num_pages, alignment);
65     pg_allocs += num_pages;
66
67     return pg_addr;
68 }
69
70
71 /**
72  * Frees a page previously allocated via palacios_allocate_page().
73  * Note that palacios_allocate_page() can allocate multiple pages with
74  * a single call while palacios_free_page() only frees a single page.
75  */
76
77 static void palacios_free_pages(void * page_paddr, int num_pages) {
78     pg_frees += num_pages;
79     free_palacios_pgs((uintptr_t)page_paddr, num_pages);
80 }
81
82
83 /**
84  * Allocates 'size' bytes of kernel memory.
85  * Returns the kernel virtual address of the memory allocated.
86  */
87 static void *
88 palacios_alloc(unsigned int size) {
89     void * addr = NULL;
90
91     if (irqs_disabled()) {
92         addr = kmalloc(size, GFP_ATOMIC);
93     } else {
94         addr = kmalloc(size, GFP_KERNEL);
95     }
96     mallocs++;
97
98  
99     return addr;
100 }
101
102 /**
103  * Frees memory that was previously allocated by palacios_alloc().
104  */
105 static void
106 palacios_free(
107         void *                  addr
108 )
109 {
110     frees++;
111     kfree(addr);
112     return;
113 }
114
115 /**
116  * Converts a kernel virtual address to the corresponding physical address.
117  */
118 static void *
119 palacios_vaddr_to_paddr(
120         void *                  vaddr
121 )
122 {
123     return (void*) __pa(vaddr);
124
125 }
126
127 /**
128  * Converts a physical address to the corresponding kernel virtual address.
129  */
130 static void *
131 palacios_paddr_to_vaddr(
132         void *                  paddr
133 )
134 {
135   return __va(paddr);
136 }
137
138 /**
139  * Runs a function on the specified CPU.
140  */
141
142 // For now, do call only on local CPU 
143 static void 
144 palacios_xcall(
145         int                     cpu_id, 
146         void                    (*fn)(void *arg),
147         void *                  arg
148 )
149 {
150
151
152     // We set wait to 1, but I'm not sure this is necessary
153     smp_call_function_single(cpu_id, fn, arg, 1);
154     
155     return;
156 }
157
158 struct lnx_thread_arg {
159     int (*fn)(void * arg);
160     void * arg;
161     char * name;
162 };
163
164 static int lnx_thread_target(void * arg) {
165     struct lnx_thread_arg * thread_info = (struct lnx_thread_arg *)arg;
166     int ret = 0;
167     /*
168       printk("Daemonizing new Palacios thread (name=%s)\n", thread_info->name);
169
170       daemonize(thread_info->name);
171       allow_signal(SIGKILL);
172     */
173
174
175     ret = thread_info->fn(thread_info->arg);
176
177     kfree(thread_info);
178     // handle cleanup 
179
180     
181     printk("Palacios Thread (%s) EXITTING\n", thread_info->name);
182
183     do_exit(ret);
184     
185     return 0; // should not get here.
186 }
187
188 /**
189  * Creates a kernel thread.
190  */
191 static void *
192 palacios_start_kernel_thread(
193         int (*fn)               (void * arg),
194         void *                  arg,
195         char *                  thread_name) {
196
197     struct lnx_thread_arg * thread_info = kmalloc(sizeof(struct lnx_thread_arg), GFP_KERNEL);
198
199     thread_info->fn = fn;
200     thread_info->arg = arg;
201     thread_info->name = thread_name;
202
203     return kthread_run( lnx_thread_target, thread_info, thread_name );
204 }
205
206
207 /**
208  * Starts a kernel thread on the specified CPU.
209  */
210 static void * 
211 palacios_start_thread_on_cpu(int cpu_id, 
212                              int (*fn)(void * arg), 
213                              void * arg, 
214                              char * thread_name ) {
215     struct task_struct * thread = NULL;
216     struct lnx_thread_arg * thread_info = kmalloc(sizeof(struct lnx_thread_arg), GFP_KERNEL);
217
218     thread_info->fn = fn;
219     thread_info->arg = arg;
220     thread_info->name = thread_name;
221
222
223     thread = kthread_create( lnx_thread_target, thread_info, thread_name );
224
225     if (IS_ERR(thread)) {
226         printk("Palacios error creating thread: %s\n", thread_name);
227         return NULL;
228     }
229
230     if (set_cpus_allowed_ptr(thread, cpumask_of(cpu_id)) != 0) {
231         kthread_stop(thread);
232         return NULL;
233     }
234
235     wake_up_process(thread);
236
237     return thread;
238 }
239
240
241 /**
242  * Rebind a kernel thread to the specified CPU
243  * The thread will be running on target CPU on return
244  * non-zero return means failure
245  */
246 static int
247 palacios_move_thread_to_cpu(int new_cpu_id, 
248                             void * thread_ptr) {
249     struct task_struct * thread = (struct task_struct *)thread_ptr;
250
251     printk("Moving thread (%p) to cpu %d\n", thread, new_cpu_id);
252
253     if (thread == NULL) {
254         thread = current;
255     }
256
257     /*
258      * Bind to the specified CPU.  When this call returns,
259      * the thread should be running on the target CPU.
260      */
261     return set_cpus_allowed_ptr(thread, cpumask_of(new_cpu_id));
262 }
263
264
265 /**
266  * Returns the CPU ID that the caller is running on.
267  */
268 static unsigned int 
269 palacios_get_cpu(void) 
270 {
271
272     /* We want to call smp_processor_id()
273      * But this is not safe if kernel preemption is possible 
274      * We need to ensure that the palacios threads are bound to a give cpu
275      */
276
277     unsigned int cpu_id = get_cpu(); 
278     put_cpu();
279     return cpu_id;
280 }
281
282 /**
283  * Interrupts the physical CPU corresponding to the specified logical guest cpu.
284  *
285  * NOTE: 
286  * This is dependent on the implementation of xcall_reschedule().  Currently
287  * xcall_reschedule does not explicitly call schedule() on the destination CPU,
288  * but instead relies on the return to user space to handle it. Because
289  * palacios is a kernel thread schedule will not be called, which is correct.
290  * If it ever changes to induce side effects, we'll need to figure something
291  * else out...
292  */
293
294 #include <asm/apic.h>
295
296 static void
297 palacios_interrupt_cpu(
298         struct v3_vm_info *     vm, 
299         int                     cpu_id, 
300         int                     vector
301 )
302 {
303     if (vector == 0) {
304         smp_send_reschedule(cpu_id);
305     } else {
306         apic->send_IPI_mask(cpumask_of(cpu_id), vector);
307     }
308     return;
309 }
310
311 /**
312  * Dispatches an interrupt to Palacios for handling.
313  */
314 static void
315 palacios_dispatch_interrupt( int vector, void * dev, struct pt_regs * regs ) {
316     struct v3_interrupt intr = {
317         .irq            = vector,
318         .error          = regs->orig_ax,
319         .should_ack     = 1,
320     };
321     
322     if (irq_to_guest_map[vector]) {
323         v3_deliver_irq(irq_to_guest_map[vector], &intr);
324     }
325     
326 }
327
328 /**
329  * Instructs the kernel to forward the specified IRQ to Palacios.
330  */
331 static int
332 palacios_hook_interrupt(struct v3_vm_info *     vm,
333                         unsigned int            vector ) {
334     printk("hooking vector %d\n", vector);      
335
336     if (irq_to_guest_map[vector]) {
337         printk(KERN_WARNING
338                "%s: Interrupt vector %u is already hooked.\n",
339                __func__, vector);
340         return -1;
341     }
342
343     printk(KERN_DEBUG
344            "%s: Hooking interrupt vector %u to vm %p.\n",
345            __func__, vector, vm);
346
347     irq_to_guest_map[vector] = vm;
348
349     /*
350      * NOTE: Normally PCI devices are supposed to be level sensitive,
351      *       but we need them to be edge sensitive so that they are
352      *       properly latched by Palacios.  Leaving them as level
353      *       sensitive would lead to an interrupt storm.
354      */
355     //ioapic_set_trigger_for_vector(vector, ioapic_edge_sensitive);
356     
357     //set_idtvec_handler(vector, palacios_dispatch_interrupt);
358     if (vector < 32) {
359         panic("unexpected vector for hooking\n");
360     } else {
361         int device_id = 0;              
362         
363         int flag = 0;
364         int error;
365                 
366         printk("hooking vector: %d\n", vector);         
367
368         if (vector == 32) {
369             flag = IRQF_TIMER;
370         } else {
371             flag = IRQF_SHARED;
372         }
373
374         error = request_irq((vector - 32),
375                             (void *)palacios_dispatch_interrupt,
376                             flag,
377                             "interrupt_for_palacios",
378                             &device_id);
379         
380         if (error) {
381             printk("error code for request_irq is %d\n", error);
382             panic("request vector %d failed",vector);
383         }
384     }
385         
386     return 0;
387 }
388
389
390
391 /**
392  * Acknowledges an interrupt.
393  */
394 static int
395 palacios_ack_interrupt(
396         int                     vector
397
398 {
399   ack_APIC_irq(); 
400   printk("Pretending to ack interrupt, vector=%d\n",vector);
401   return 0;
402 }
403   
404 /**
405  * Returns the CPU frequency in kilohertz.
406  */
407 static unsigned int
408 palacios_get_cpu_khz(void) 
409 {
410     printk("cpu_khz is %u\n",cpu_khz);
411
412     if (cpu_khz == 0) { 
413         printk("faking cpu_khz to 1000000\n");
414         return 1000000;
415     } else {
416         return cpu_khz;
417     }
418   //return 1000000;
419 }
420
421 /**
422  * Yield the CPU so other host OS tasks can run.
423  */
424 static void
425 palacios_yield_cpu(void)
426 {
427     schedule();
428     return;
429 }
430
431
432
433 /**
434  * Allocates a mutex.
435  * Returns NULL on failure.
436  */
437 static void *
438 palacios_mutex_alloc(void)
439 {
440     spinlock_t *lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
441
442     if (lock) {
443         spin_lock_init(lock);
444     }
445     
446     return lock;
447 }
448
449 /**
450  * Frees a mutex.
451  */
452 static void
453 palacios_mutex_free(void * mutex) {
454     kfree(mutex);
455 }
456
457 /**
458  * Locks a mutex.
459  */
460 static void 
461 palacios_mutex_lock(void * mutex, int must_spin) {
462     spin_lock((spinlock_t *)mutex);
463 }
464
465 /**
466  * Unlocks a mutex.
467  */
468 static void 
469 palacios_mutex_unlock(
470         void *                  mutex
471
472 {
473     spin_unlock((spinlock_t *)mutex);
474 }
475
476 /**
477  * Structure used by the Palacios hypervisor to interface with the host kernel.
478  */
479 static struct v3_os_hooks palacios_os_hooks = {
480         .print                  = palacios_print,
481         .allocate_pages         = palacios_allocate_pages,
482         .free_pages             = palacios_free_pages,
483         .malloc                 = palacios_alloc,
484         .free                   = palacios_free,
485         .vaddr_to_paddr         = palacios_vaddr_to_paddr,
486         .paddr_to_vaddr         = palacios_paddr_to_vaddr,
487         .hook_interrupt         = palacios_hook_interrupt,
488         .ack_irq                = palacios_ack_interrupt,
489         .get_cpu_khz            = palacios_get_cpu_khz,
490         .start_kernel_thread    = palacios_start_kernel_thread,
491         .yield_cpu              = palacios_yield_cpu,
492         .mutex_alloc            = palacios_mutex_alloc,
493         .mutex_free             = palacios_mutex_free,
494         .mutex_lock             = palacios_mutex_lock, 
495         .mutex_unlock           = palacios_mutex_unlock,
496         .get_cpu                = palacios_get_cpu,
497         .interrupt_cpu          = palacios_interrupt_cpu,
498         .call_on_cpu            = palacios_xcall,
499         .start_thread_on_cpu    = palacios_start_thread_on_cpu,
500         .move_thread_to_cpu = palacios_move_thread_to_cpu,
501 };
502
503
504
505
506 int palacios_vmm_init( void )
507 {
508     int num_cpus = num_online_cpus();
509     char * cpu_mask = NULL;
510
511     if (cpu_list_len > 0) {
512         int major = 0;
513         int minor = 0;
514         int i = 0;
515
516         cpu_mask = kmalloc((num_cpus / 8) + 1, GFP_KERNEL);
517         memset(cpu_mask, 0, (num_cpus / 8) + 1);
518         
519         for (i = 0; i < cpu_list_len; i++) {
520             if (cpu_list[i] >= num_cpus) {
521                 printk("CPU (%d) exceeds number of available CPUs. Ignoring...\n", cpu_list[i]);
522                 continue;
523             }
524
525             major = cpu_list[i] / 8;
526             minor = cpu_list[i] % 8;
527     
528             *(cpu_mask + major) |= (0x1 << minor);
529         }
530     }
531
532     memset(irq_to_guest_map, 0, sizeof(struct v3_vm_info *) * 256);
533
534     printk("palacios_init starting - calling init_v3\n");
535     
536     Init_V3(&palacios_os_hooks, cpu_mask, num_cpus);
537
538     return 0;
539
540 }
541
542
543 int palacios_vmm_exit( void ) {
544
545     Shutdown_V3();
546
547     return 0;
548 }