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.


Ignore frees of null in all cases (kfree, vfree, pagefree)
[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 #include <linux/vmalloc.h>
18
19 #include <asm/i387.h>
20
21 #include <palacios/vmm.h>
22 #include <palacios/vmm_host_events.h>
23
24 #ifdef V3_CONFIG_HOST_LAZY_FPU_SWITCH
25 #include <interfaces/vmm_lazy_fpu.h>
26 #endif
27
28 #include "palacios.h"
29
30 #include "mm.h"
31
32 #include "memcheck.h"
33 #include "lockcheck.h"
34
35
36
37 // The following can be used to track memory bugs
38 // zero memory after allocation (now applies to valloc and page alloc as well)
39 #define ALLOC_ZERO_MEM 1
40 // pad allocations by this many bytes on both ends of block (heap only)
41 #define ALLOC_PAD      0
42
43
44 u32 pg_allocs = 0;
45 u32 pg_frees = 0;
46 u32 mallocs = 0;
47 u32 frees = 0;
48 u32 vmallocs = 0;
49 u32 vfrees = 0;
50
51 static struct v3_vm_info * irq_to_guest_map[256];
52
53
54 extern unsigned int cpu_khz;
55
56 extern int cpu_list[NR_CPUS];
57 extern int cpu_list_len;
58
59
60 static char *print_buffer[NR_CPUS];
61
62 static void deinit_print_buffers(void)
63 {
64     int i;
65
66     for (i=0;i<NR_CPUS;i++) {
67         if (print_buffer[i]) { 
68             palacios_free(print_buffer[i]);
69             print_buffer[i]=0;
70         }
71     }
72 }
73
74 static int init_print_buffers(void)
75 {
76     int i;
77     
78     memset(print_buffer,0,sizeof(char*)*NR_CPUS);
79
80 #if !V3_PRINTK_OLD_STYLE_OUTPUT
81
82     for (i=0;i<NR_CPUS;i++) { 
83         print_buffer[i] = palacios_alloc(V3_PRINTK_BUF_SIZE);
84         if (!print_buffer[i]) { 
85             ERROR("Cannot allocate print buffer for cpu %d\n",i);
86             deinit_print_buffers();
87             return -1;
88         }
89         memset(print_buffer[i],0,V3_PRINTK_BUF_SIZE);
90     }
91
92 #endif
93     
94     return 0;
95
96 }
97  
98 /**
99  * Prints a message to the console.
100  */
101 void palacios_print_scoped(void * vm, int vcore, const char *fmt, ...) {
102
103 #if V3_PRINTK_OLD_STYLE_OUTPUT
104
105   va_list ap;
106
107   va_start(ap, fmt);
108   vprintk(fmt, ap);
109   va_end(ap);
110
111   return
112
113 #else 
114
115   va_list ap;
116   char *buf;
117   unsigned int cpu = palacios_get_cpu();
118   struct v3_guest *guest = (struct v3_guest *)vm;
119
120   buf = print_buffer[cpu];
121
122   if (!buf) { 
123       printk(KERN_INFO "palacios (pcore %u): output skipped - no allocated buffer\n",cpu);
124       return;
125   } 
126
127   va_start(ap, fmt);
128   vsnprintf(buf,V3_PRINTK_BUF_SIZE, fmt, ap);
129   va_end(ap);
130
131 #if V3_PRINTK_CHECK_7BIT
132   {
133       char c=0;
134       int i;
135       for (i=0;i<strlen(buf);i++) { 
136           if (buf[i] < 0) {
137               c=buf[i];
138               break;
139           }
140       }
141       if (c!=0) { 
142           printk(KERN_INFO "palacios (pcore %u): ALERT ALERT 8 BIT CHAR (c=%d) DETECTED\n", cpu,c);
143       }
144   }
145 #endif
146
147   if (guest) {
148     if (vcore>=0) { 
149       printk(KERN_INFO "palacios (pcore %u vm %s vcore %u): %s",
150              cpu,
151              guest->name,
152              vcore,
153              buf);
154     } else {
155        printk(KERN_INFO "palacios (pcore %u vm %s): %s",
156              cpu,
157              guest->name,
158              buf);
159     }
160   } else {
161     printk(KERN_INFO "palacios (pcore %u): %s",
162            cpu,
163            buf);
164   }
165     
166   return;
167
168 #endif
169
170 }
171
172
173 /*
174  * Allocates a contiguous region of pages of the requested size.
175  * Returns the physical address of the first page in the region.
176  */
177 void *palacios_allocate_pages(int num_pages, unsigned int alignment, int node_id, int constraints) {
178     void * pg_addr = NULL;
179
180     if (num_pages<=0) { 
181         ERROR("ALERT ALERT Attempt to allocate zero or fewer pages (%d pages, alignment %d, node %d, constraints 0x%x)\n",num_pages, alignment, node_id, constraints);
182       return NULL;
183     }
184
185     pg_addr = (void *)alloc_palacios_pgs(num_pages, alignment, node_id, constraints);
186
187     if (!pg_addr) { 
188         ERROR("ALERT ALERT  Page allocation has FAILED Warning (%d pages, alignment %d, node %d, constraints 0x%x)\n",num_pages, alignment, node_id, constraints);
189         return NULL;
190     }
191
192     pg_allocs += num_pages;
193
194 #if ALLOC_ZERO_MEM
195     memset(__va(pg_addr),0,num_pages*4096);
196 #endif
197
198     MEMCHECK_ALLOC_PAGES(pg_addr,num_pages*4096);
199
200     return pg_addr;
201 }
202
203
204 /**
205  * Frees a page previously allocated via palacios_allocate_page().
206  * Note that palacios_allocate_page() can allocate multiple pages with
207  * a single call while palacios_free_page() only frees a single page.
208  */
209
210 void palacios_free_pages(void * page_paddr, int num_pages) {
211     if (!page_paddr) { 
212         ERROR("Ignoring free pages: 0x%p (0x%lx)for %d pages\n", page_paddr, (uintptr_t)page_paddr, num_pages);
213         dump_stack();
214         return;
215     }
216     pg_frees += num_pages;
217     free_palacios_pgs((uintptr_t)page_paddr, num_pages);
218     MEMCHECK_FREE_PAGES(page_paddr,num_pages*4096);
219
220 }
221
222
223 void *
224 palacios_alloc_extended(unsigned int size, unsigned int flags, int node) {
225     void * addr = NULL;
226
227     if (size==0) { 
228       // note that modern kernels will respond to a zero byte
229       // kmalloc and return the address 0x10...  In Palacios, 
230       // we will simply not allow 0 byte allocs at all, of any kind
231       ERROR("ALERT ALERT attempt to kmalloc zero bytes rejected\n");
232       return NULL;
233     }
234
235     if (node==-1) { 
236         addr = kmalloc(size+2*ALLOC_PAD, flags);
237     } else {
238         addr = kmalloc_node(size+2*ALLOC_PAD, flags, node);
239     }
240
241     if (!addr || IS_ERR(addr)) { 
242        ERROR("ALERT ALERT  kmalloc has FAILED FAILED FAILED\n");
243        return NULL;
244     }   
245
246     mallocs++;
247
248 #if ALLOC_ZERO_MEM
249     memset(addr,0,size+2*ALLOC_PAD);
250 #endif
251
252     MEMCHECK_KMALLOC(addr,size+2*ALLOC_PAD);
253
254     return addr+ALLOC_PAD;
255 }
256
257 void *
258 palacios_valloc(unsigned int size)
259 {
260     void * addr = NULL;
261
262     if (size==0) { 
263       ERROR("ALERT ALERT attempt to vmalloc zero bytes rejected\n");
264       return NULL;
265     }
266
267     addr = vmalloc(size);
268
269     if (!addr || IS_ERR(addr)) { 
270        ERROR("ALERT ALERT  vmalloc has FAILED FAILED FAILED\n");
271        return NULL;
272     }   
273
274     vmallocs++;
275
276 #if ALLOC_ZERO_MEM
277     memset(addr,0,size);
278 #endif
279
280     MEMCHECK_VMALLOC(addr,size);
281
282     return addr;
283 }
284
285 void palacios_vfree(void *p)
286 {
287   if (!p) { 
288       ERROR("Ignoring vfree: 0x%p\n",p);
289       dump_stack();
290       return;
291   }
292   vfree(p);
293   vfrees++;
294   MEMCHECK_VFREE(p);
295 }
296
297 /**
298  * Allocates 'size' bytes of kernel memory.
299  * Returns the kernel virtual address of the memory allocated.
300  */
301 void *
302 palacios_alloc(unsigned int size) {
303
304     // It is very important that this test remains since 
305     // this function is used extensively throughout palacios and the linux
306     // module, both in places where interrupts are off and where they are on
307     // a GFP_KERNEL call, when done with interrupts off can lead to DEADLOCK
308     if (irqs_disabled()) {
309         return palacios_alloc_extended(size,GFP_ATOMIC,-1);
310     } else {
311         return palacios_alloc_extended(size,GFP_KERNEL,-1);
312     }
313
314 }
315
316 /**
317  * Frees memory that was previously allocated by palacios_alloc().
318  */
319 void
320 palacios_free(
321         void *                  addr
322 )
323 {
324     if (!addr) {
325         ERROR("Ignoring free : 0x%p\n", addr);
326         dump_stack();
327         return;
328     }
329     frees++;
330     kfree(addr-ALLOC_PAD);
331     MEMCHECK_KFREE(addr-ALLOC_PAD);
332 }
333
334 /**
335  * Converts a kernel virtual address to the corresponding physical address.
336  */
337 void *
338 palacios_vaddr_to_paddr(
339         void *                  vaddr
340 )
341 {
342     return (void*) __pa(vaddr);
343
344 }
345
346 /**
347  * Converts a physical address to the corresponding kernel virtual address.
348  */
349 void *
350 palacios_paddr_to_vaddr(
351         void *                  paddr
352 )
353 {
354   return __va(paddr);
355 }
356
357 /**
358  * Runs a function on the specified CPU.
359  */
360 static void 
361 palacios_xcall(
362         int                     cpu_id, 
363         void                    (*fn)(void *arg),
364         void *                  arg
365 )
366 {
367
368
369     // We set wait to 1, but I'm not sure this is necessary
370     smp_call_function_single(cpu_id, fn, arg, 1);
371     
372     return;
373 }
374
375
376 #define MAX_THREAD_NAME 32
377
378 struct lnx_thread_arg {
379     int (*fn)(void * arg);
380     void * arg;
381     char name[MAX_THREAD_NAME];
382 };
383
384 static int lnx_thread_target(void * arg) {
385     struct lnx_thread_arg * thread_info = (struct lnx_thread_arg *)arg;
386     int ret = 0;
387     /*
388       INFO("Daemonizing new Palacios thread (name=%s)\n", thread_info->name);
389
390       daemonize(thread_info->name);
391       allow_signal(SIGKILL);
392     */
393
394 #ifdef V3_CONFIG_HOST_LAZY_FPU_SWITCH
395     // We are a kernel thread that needs FPU save/restore state
396     // vcores definitely need this, all the other threads get it too, 
397     // but they just won't use it
398     fpu_alloc(&(current->thread.fpu));
399 #endif
400
401     ret = thread_info->fn(thread_info->arg);
402
403     INFO("Palacios Thread (%s) EXITING\n", thread_info->name);
404
405     palacios_free(thread_info);
406     // handle cleanup 
407
408     // We rely on do_exit to free the fpu data
409     // since we could get switched at any point until the thread is done... 
410
411     do_exit(ret);
412
413     return 0; // should not get here.
414 }
415
416 /**
417  * Creates a kernel thread.
418  */
419 void *
420 palacios_start_kernel_thread(
421         int (*fn)               (void * arg),
422         void *                  arg,
423         char *                  thread_name) {
424
425     struct lnx_thread_arg * thread_info = palacios_alloc(sizeof(struct lnx_thread_arg));
426
427     if (!thread_info) { 
428         ERROR("ALERT ALERT Unable to allocate thread\n");
429         return NULL;
430     }
431
432     thread_info->fn = fn;
433     thread_info->arg = arg;
434     strncpy(thread_info->name,thread_name,MAX_THREAD_NAME);
435     thread_info->name[MAX_THREAD_NAME-1] =0;
436
437     return kthread_run( lnx_thread_target, thread_info, thread_info->name );
438 }
439
440
441 /**
442  * Starts a kernel thread on the specified CPU.
443  */
444 void * 
445 palacios_start_thread_on_cpu(int cpu_id, 
446                              int (*fn)(void * arg), 
447                              void * arg, 
448                              char * thread_name ) {
449     struct task_struct * thread = NULL;
450     struct lnx_thread_arg * thread_info = palacios_alloc(sizeof(struct lnx_thread_arg));
451
452     if (!thread_info) { 
453         ERROR("ALERT ALERT Unable to allocate thread to start on cpu\n");
454         return NULL;
455     }
456
457     thread_info->fn = fn;
458     thread_info->arg = arg;
459     strncpy(thread_info->name,thread_name,MAX_THREAD_NAME);
460     thread_info->name[MAX_THREAD_NAME-1] =0;
461
462     thread = kthread_create( lnx_thread_target, thread_info, thread_info->name );
463
464     if (!thread || IS_ERR(thread)) {
465         WARNING("Palacios error creating thread: %s\n", thread_info->name);
466         palacios_free(thread_info);
467         return NULL;
468     }
469
470     if (set_cpus_allowed_ptr(thread, cpumask_of(cpu_id)) != 0) {
471         WARNING("Attempt to start thread on disallowed CPU\n");
472         kthread_stop(thread);
473         palacios_free(thread_info);
474         return NULL;
475     }
476
477     wake_up_process(thread);
478
479     return thread;
480 }
481
482
483 /**
484  * Rebind a kernel thread to the specified CPU
485  * The thread will be running on target CPU on return
486  * non-zero return means failure
487  */
488 int
489 palacios_move_thread_to_cpu(int new_cpu_id, 
490                             void * thread_ptr) {
491     struct task_struct * thread = (struct task_struct *)thread_ptr;
492
493     INFO("Moving thread (%p) to cpu %d\n", thread, new_cpu_id);
494
495     if (thread == NULL) {
496         thread = current;
497     }
498
499     /*
500      * Bind to the specified CPU.  When this call returns,
501      * the thread should be running on the target CPU.
502      */
503     return set_cpus_allowed_ptr(thread, cpumask_of(new_cpu_id));
504 }
505
506
507 /**
508  * Returns the CPU ID that the caller is running on.
509  */
510 unsigned int 
511 palacios_get_cpu(void) 
512 {
513
514     /* We want to call smp_processor_id()
515      * But this is not safe if kernel preemption is possible 
516      * We need to ensure that the palacios threads are bound to a give cpu
517      */
518
519     unsigned int cpu_id = get_cpu(); 
520     put_cpu();
521     return cpu_id;
522 }
523
524 /**
525  * Interrupts the physical CPU corresponding to the specified logical guest cpu.
526  *
527  * NOTE: 
528  * This is dependent on the implementation of xcall_reschedule().  Currently
529  * xcall_reschedule does not explicitly call schedule() on the destination CPU,
530  * but instead relies on the return to user space to handle it. Because
531  * palacios is a kernel thread schedule will not be called, which is correct.
532  * If it ever changes to induce side effects, we'll need to figure something
533  * else out...
534  */
535
536 #include <asm/apic.h>
537
538 static void
539 palacios_interrupt_cpu(
540         struct v3_vm_info *     vm, 
541         int                     cpu_id, 
542         int                     vector
543 )
544 {
545     if (vector == 0) {
546         smp_send_reschedule(cpu_id);
547     } else {
548         apic->send_IPI_mask(cpumask_of(cpu_id), vector);
549     }
550     return;
551 }
552
553 /**
554  * Dispatches an interrupt to Palacios for handling.
555  */
556 static void
557 palacios_dispatch_interrupt( int vector, void * dev, struct pt_regs * regs ) {
558     struct v3_interrupt intr = {
559         .irq            = vector,
560         .error          = regs->orig_ax,
561         .should_ack     = 1,
562     };
563     
564     if (irq_to_guest_map[vector]) {
565         v3_deliver_irq(irq_to_guest_map[vector], &intr);
566     }
567     
568 }
569
570 /**
571  * Instructs the kernel to forward the specified IRQ to Palacios.
572  */
573 static int
574 palacios_hook_interrupt(struct v3_vm_info *     vm,
575                         unsigned int            vector ) {
576     INFO("hooking vector %d\n", vector);        
577
578     if (irq_to_guest_map[vector]) {
579         WARNING(
580                "%s: Interrupt vector %u is already hooked.\n",
581                __func__, vector);
582         return -1;
583     }
584
585     DEBUG(
586            "%s: Hooking interrupt vector %u to vm %p.\n",
587            __func__, vector, vm);
588
589     irq_to_guest_map[vector] = vm;
590
591     /*
592      * NOTE: Normally PCI devices are supposed to be level sensitive,
593      *       but we need them to be edge sensitive so that they are
594      *       properly latched by Palacios.  Leaving them as level
595      *       sensitive would lead to an interrupt storm.
596      */
597     //ioapic_set_trigger_for_vector(vector, ioapic_edge_sensitive);
598     
599     //set_idtvec_handler(vector, palacios_dispatch_interrupt);
600     if (vector < 32) {
601         ERROR("unexpected vector for hooking\n");
602         return -1;
603     } else {
604         int device_id = 0;              
605         
606         int flag = 0;
607         int error;
608                 
609         DEBUG("hooking vector: %d\n", vector);          
610
611         if (vector == 32) {
612             flag = IRQF_TIMER;
613         } else {
614             flag = IRQF_SHARED;
615         }
616
617         error = request_irq((vector - 32),
618                             (void *)palacios_dispatch_interrupt,
619                             flag,
620                             "interrupt_for_palacios",
621                             &device_id);
622         
623         if (error) {
624             ERROR("error code for request_irq is %d\n", error);
625             ERROR("request vector %d failed", vector);
626             return -1;
627         }
628     }
629         
630     return 0;
631 }
632
633
634
635 /**
636  * Acknowledges an interrupt.
637  */
638 static int
639 palacios_ack_interrupt(
640         int                     vector
641
642 {
643   ack_APIC_irq(); 
644   DEBUG("Pretending to ack interrupt, vector=%d\n", vector);
645   return 0;
646 }
647   
648 /**
649  * Returns the CPU frequency in kilohertz.
650  */
651 unsigned int
652 palacios_get_cpu_khz(void) 
653 {
654     INFO("cpu_khz is %u\n", cpu_khz);
655
656     if (cpu_khz == 0) { 
657         INFO("faking cpu_khz to 1000000\n");
658         return 1000000;
659     } else {
660         return cpu_khz;
661     }
662   //return 1000000;
663 }
664
665 /**
666  * Yield the CPU so other host OS tasks can run.
667  * This will return immediately if there is no other thread that is runnable
668  * And there is no real bound on how long it will yield
669  */
670 void
671 palacios_yield_cpu(void)
672 {
673     schedule();
674     return;
675 }
676
677 /**
678  * Yield the CPU so other host OS tasks can run.
679  * Given now immediately if there is no other thread that is runnable
680  * And there is no real bound on how long it will yield
681  */
682 void palacios_sleep_cpu(unsigned int us)
683 {
684
685     set_current_state(TASK_INTERRUPTIBLE);
686     if (us) {
687         unsigned int uspj = 1000000U/HZ;
688         unsigned int jiffies = us/uspj + ((us%uspj) !=0);  // ceiling 
689         schedule_timeout(jiffies);
690     } else {
691         schedule();
692     }
693     return;
694 }
695
696 void palacios_wakeup_cpu(void *thread)
697 {
698     wake_up_process(thread);
699     return;
700 }
701
702 /**
703  * Allocates a mutex.
704  * Returns NULL on failure.
705  */
706 void *
707 palacios_mutex_alloc(void)
708 {
709     spinlock_t *lock = palacios_alloc(sizeof(spinlock_t));
710
711     if (lock) {
712         spin_lock_init(lock);
713         LOCKCHECK_ALLOC(lock);
714     } else {
715         ERROR("ALERT ALERT Unable to allocate lock\n");
716         return NULL;
717     }
718     
719     return lock;
720 }
721
722 void palacios_mutex_init(void *mutex)
723 {
724   spinlock_t *lock = (spinlock_t*)mutex;
725   
726   if (lock) {
727     spin_lock_init(lock);
728     LOCKCHECK_ALLOC(lock);
729   }
730 }
731
732 void palacios_mutex_deinit(void *mutex)
733 {
734   spinlock_t *lock = (spinlock_t*)mutex;
735   
736   if (lock) {
737     // no actual spin_lock_deinit on linux
738     // our purpose here is to drive the lock checker
739     LOCKCHECK_FREE(lock);
740   }
741 }
742
743
744 /**
745  * Frees a mutex.
746  */
747 void
748 palacios_mutex_free(void * mutex) {
749     palacios_free(mutex);
750     LOCKCHECK_FREE(mutex);
751 }
752
753 /**
754  * Locks a mutex.
755  */
756 void 
757 palacios_mutex_lock(void * mutex, int must_spin) {
758
759     LOCKCHECK_LOCK_PRE(mutex);
760     spin_lock((spinlock_t *)mutex);
761     LOCKCHECK_LOCK_POST(mutex);
762 }
763
764
765 /**
766  * Locks a mutex, disabling interrupts on this core
767  */
768 void *
769 palacios_mutex_lock_irqsave(void * mutex, int must_spin) {
770     
771     unsigned long flags; 
772     
773     LOCKCHECK_LOCK_IRQSAVE_PRE(mutex,flags);
774     spin_lock_irqsave((spinlock_t *)mutex,flags);
775     LOCKCHECK_LOCK_IRQSAVE_POST(mutex,flags);
776
777     return (void *)flags;
778 }
779
780
781 /**
782  * Unlocks a mutex.
783  */
784 void 
785 palacios_mutex_unlock(
786         void *                  mutex
787
788 {
789     LOCKCHECK_UNLOCK_PRE(mutex);
790     spin_unlock((spinlock_t *)mutex);
791     LOCKCHECK_UNLOCK_POST(mutex);
792 }
793
794
795 /**
796  * Unlocks a mutex and restores previous interrupt state on this core
797  */
798 void 
799 palacios_mutex_unlock_irqrestore(void *mutex, void *flags)
800 {
801     LOCKCHECK_UNLOCK_IRQRESTORE_PRE(mutex,(unsigned long)flags);
802     // This is correct, flags is opaque
803     spin_unlock_irqrestore((spinlock_t *)mutex,(unsigned long)flags);
804     LOCKCHECK_UNLOCK_IRQRESTORE_POST(mutex,(unsigned long)flags);
805 }
806
807 void palacios_used_fpu(void)
808 {
809    struct thread_info *cur = current_thread_info();
810
811    // We assume we are not preemptible here...
812    cur->status |= TS_USEDFPU;
813    clts(); 
814    // After this, FP Save should be handled by Linux if it
815    // switches to a different task and that task uses FPU
816 }
817
818 inline int ists(void)
819 {
820    return read_cr0() & X86_CR0_TS;
821
822 }
823 void palacios_need_fpu(void)
824 {
825     // We assume we are not preemptible here... 
826     if (ists()) { 
827       // we have been switched back to from somewhere else...
828       // Do a restore now - this will also do a clts()
829       math_state_restore();
830     }
831 }
832
833
834 /**
835  * Structure used by the Palacios hypervisor to interface with the host kernel.
836  */
837 static struct v3_os_hooks palacios_os_hooks = {
838         .print                  = palacios_print_scoped,
839         .allocate_pages         = palacios_allocate_pages,
840         .free_pages             = palacios_free_pages,
841         .malloc                 = palacios_alloc,
842         .free                   = palacios_free,
843         .vaddr_to_paddr         = palacios_vaddr_to_paddr,
844         .paddr_to_vaddr         = palacios_paddr_to_vaddr,
845         .hook_interrupt         = palacios_hook_interrupt,
846         .ack_irq                = palacios_ack_interrupt,
847         .get_cpu_khz            = palacios_get_cpu_khz,
848         .start_kernel_thread    = palacios_start_kernel_thread,
849         .yield_cpu              = palacios_yield_cpu,
850         .sleep_cpu              = palacios_sleep_cpu,
851         .wakeup_cpu             = palacios_wakeup_cpu,
852         .mutex_alloc            = palacios_mutex_alloc,
853         .mutex_free             = palacios_mutex_free,
854         .mutex_lock             = palacios_mutex_lock, 
855         .mutex_unlock           = palacios_mutex_unlock,
856         .mutex_lock_irqsave     = palacios_mutex_lock_irqsave, 
857         .mutex_unlock_irqrestore= palacios_mutex_unlock_irqrestore,
858         .get_cpu                = palacios_get_cpu,
859         .interrupt_cpu          = palacios_interrupt_cpu,
860         .call_on_cpu            = palacios_xcall,
861         .start_thread_on_cpu    = palacios_start_thread_on_cpu,
862         .move_thread_to_cpu     = palacios_move_thread_to_cpu,
863 };
864
865
866 #ifdef V3_CONFIG_HOST_LAZY_FPU_SWITCH
867 // Note that this host interface is defined here since it's
868 // intertwined with thread creation... 
869 static struct v3_lazy_fpu_iface palacios_fpu_hooks = {
870         .used_fpu               = palacios_used_fpu,
871         .need_fpu               = palacios_need_fpu
872 };
873
874 #endif
875
876
877 int palacios_vmm_init( char *options )
878 {
879     int num_cpus = num_online_cpus();
880     char * cpu_mask = NULL;
881
882     if (cpu_list_len > 0) {
883         int major = 0;
884         int minor = 0;
885         int i = 0;
886
887         cpu_mask = palacios_alloc((num_cpus / 8) + 1);
888
889         if (!cpu_mask) { 
890             ERROR("Cannot allocate cpu mask\n");
891             return -1;
892         }
893
894         memset(cpu_mask, 0, (num_cpus / 8) + 1);
895         
896         for (i = 0; i < cpu_list_len; i++) {
897             if (cpu_list[i] >= num_cpus) {
898                 WARNING("CPU (%d) exceeds number of available CPUs. Ignoring...\n", cpu_list[i]);
899                 continue;
900             }
901
902             major = cpu_list[i] / 8;
903             minor = cpu_list[i] % 8;
904     
905             *(cpu_mask + major) |= (0x1 << minor);
906         }
907     }
908
909     memset(irq_to_guest_map, 0, sizeof(struct v3_vm_info *) * 256);
910
911     if (init_print_buffers()) {
912         ERROR("Cannot initialize print buffers\n");
913         palacios_free(cpu_mask);
914         return -1;
915     }
916
917     INFO("palacios_init starting - calling init_v3\n");
918
919     Init_V3(&palacios_os_hooks, cpu_mask, num_cpus, options);
920
921 #ifdef V3_CONFIG_HOST_LAZY_FPU_SWITCH
922     V3_Init_Lazy_FPU(&palacios_fpu_hooks);
923 #endif
924
925     return 0;
926
927 }
928
929
930 int palacios_vmm_exit( void ) {
931
932     Shutdown_V3();
933
934     INFO("palacios shutdown complete\n");
935
936     deinit_print_buffers();
937
938     return 0;
939 }