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.


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