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.


Hook for thread creation split into create and start thread
[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_create_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     return thread;
478 }
479
480 void
481 palacios_start_thread(void * th){
482
483         struct task_struct * thread = (struct task_struct *)th;
484         wake_up_process(thread);
485
486 }
487 /**
488  * Rebind a kernel thread to the specified CPU
489  * The thread will be running on target CPU on return
490  * non-zero return means failure
491  */
492 int
493 palacios_move_thread_to_cpu(int new_cpu_id, 
494                             void * thread_ptr) {
495     struct task_struct * thread = (struct task_struct *)thread_ptr;
496
497     INFO("Moving thread (%p) to cpu %d\n", thread, new_cpu_id);
498
499     if (thread == NULL) {
500         thread = current;
501     }
502
503     /*
504      * Bind to the specified CPU.  When this call returns,
505      * the thread should be running on the target CPU.
506      */
507     return set_cpus_allowed_ptr(thread, cpumask_of(new_cpu_id));
508 }
509
510
511 /**
512  * Returns the CPU ID that the caller is running on.
513  */
514 unsigned int 
515 palacios_get_cpu(void) 
516 {
517
518     /* We want to call smp_processor_id()
519      * But this is not safe if kernel preemption is possible 
520      * We need to ensure that the palacios threads are bound to a give cpu
521      */
522
523     unsigned int cpu_id = get_cpu(); 
524     put_cpu();
525     return cpu_id;
526 }
527
528 /**
529  * Interrupts the physical CPU corresponding to the specified logical guest cpu.
530  *
531  * NOTE: 
532  * This is dependent on the implementation of xcall_reschedule().  Currently
533  * xcall_reschedule does not explicitly call schedule() on the destination CPU,
534  * but instead relies on the return to user space to handle it. Because
535  * palacios is a kernel thread schedule will not be called, which is correct.
536  * If it ever changes to induce side effects, we'll need to figure something
537  * else out...
538  */
539
540 #include <asm/apic.h>
541
542 static void
543 palacios_interrupt_cpu(
544         struct v3_vm_info *     vm, 
545         int                     cpu_id, 
546         int                     vector
547 )
548 {
549     if (vector == 0) {
550         smp_send_reschedule(cpu_id);
551     } else {
552         apic->send_IPI_mask(cpumask_of(cpu_id), vector);
553     }
554     return;
555 }
556
557 /**
558  * Dispatches an interrupt to Palacios for handling.
559  */
560 static void
561 palacios_dispatch_interrupt( int vector, void * dev, struct pt_regs * regs ) {
562     struct v3_interrupt intr = {
563         .irq            = vector,
564         .error          = regs->orig_ax,
565         .should_ack     = 1,
566     };
567     
568     if (irq_to_guest_map[vector]) {
569         v3_deliver_irq(irq_to_guest_map[vector], &intr);
570     }
571     
572 }
573
574 /**
575  * Instructs the kernel to forward the specified IRQ to Palacios.
576  */
577 static int
578 palacios_hook_interrupt(struct v3_vm_info *     vm,
579                         unsigned int            vector ) {
580     INFO("hooking vector %d\n", vector);        
581
582     if (irq_to_guest_map[vector]) {
583         WARNING(
584                "%s: Interrupt vector %u is already hooked.\n",
585                __func__, vector);
586         return -1;
587     }
588
589     DEBUG(
590            "%s: Hooking interrupt vector %u to vm %p.\n",
591            __func__, vector, vm);
592
593     irq_to_guest_map[vector] = vm;
594
595     /*
596      * NOTE: Normally PCI devices are supposed to be level sensitive,
597      *       but we need them to be edge sensitive so that they are
598      *       properly latched by Palacios.  Leaving them as level
599      *       sensitive would lead to an interrupt storm.
600      */
601     //ioapic_set_trigger_for_vector(vector, ioapic_edge_sensitive);
602     
603     //set_idtvec_handler(vector, palacios_dispatch_interrupt);
604     if (vector < 32) {
605         ERROR("unexpected vector for hooking\n");
606         return -1;
607     } else {
608         int device_id = 0;              
609         
610         int flag = 0;
611         int error;
612                 
613         DEBUG("hooking vector: %d\n", vector);          
614
615         if (vector == 32) {
616             flag = IRQF_TIMER;
617         } else {
618             flag = IRQF_SHARED;
619         }
620
621         error = request_irq((vector - 32),
622                             (void *)palacios_dispatch_interrupt,
623                             flag,
624                             "interrupt_for_palacios",
625                             &device_id);
626         
627         if (error) {
628             ERROR("error code for request_irq is %d\n", error);
629             ERROR("request vector %d failed", vector);
630             return -1;
631         }
632     }
633         
634     return 0;
635 }
636
637
638
639 /**
640  * Acknowledges an interrupt.
641  */
642 static int
643 palacios_ack_interrupt(
644         int                     vector
645
646 {
647   ack_APIC_irq(); 
648   DEBUG("Pretending to ack interrupt, vector=%d\n", vector);
649   return 0;
650 }
651   
652 /**
653  * Returns the CPU frequency in kilohertz.
654  */
655 unsigned int
656 palacios_get_cpu_khz(void) 
657 {
658     INFO("cpu_khz is %u\n", cpu_khz);
659
660     if (cpu_khz == 0) { 
661         INFO("faking cpu_khz to 1000000\n");
662         return 1000000;
663     } else {
664         return cpu_khz;
665     }
666   //return 1000000;
667 }
668
669 /**
670  * Yield the CPU so other host OS tasks can run.
671  * This will return immediately if there is no other thread that is runnable
672  * And there is no real bound on how long it will yield
673  */
674 void
675 palacios_yield_cpu(void)
676 {
677     schedule();
678     return;
679 }
680
681 /**
682  * Yield the CPU so other host OS tasks can run.
683  * Given now immediately if there is no other thread that is runnable
684  * And there is no real bound on how long it will yield
685  */
686 void palacios_sleep_cpu(unsigned int us)
687 {
688
689     set_current_state(TASK_INTERRUPTIBLE);
690     if (us) {
691         unsigned int uspj = 1000000U/HZ;
692         unsigned int jiffies = us/uspj + ((us%uspj) !=0);  // ceiling 
693         schedule_timeout(jiffies);
694     } else {
695         schedule();
696     }
697     return;
698 }
699
700 void palacios_wakeup_cpu(void *thread)
701 {
702     wake_up_process(thread);
703     return;
704 }
705
706 /**
707  * Allocates a mutex.
708  * Returns NULL on failure.
709  */
710 void *
711 palacios_mutex_alloc(void)
712 {
713     spinlock_t *lock = palacios_alloc(sizeof(spinlock_t));
714
715     if (lock) {
716         spin_lock_init(lock);
717         LOCKCHECK_ALLOC(lock);
718     } else {
719         ERROR("ALERT ALERT Unable to allocate lock\n");
720         return NULL;
721     }
722     
723     return lock;
724 }
725
726 void palacios_mutex_init(void *mutex)
727 {
728   spinlock_t *lock = (spinlock_t*)mutex;
729   
730   if (lock) {
731     spin_lock_init(lock);
732     LOCKCHECK_ALLOC(lock);
733   }
734 }
735
736 void palacios_mutex_deinit(void *mutex)
737 {
738   spinlock_t *lock = (spinlock_t*)mutex;
739   
740   if (lock) {
741     // no actual spin_lock_deinit on linux
742     // our purpose here is to drive the lock checker
743     LOCKCHECK_FREE(lock);
744   }
745 }
746
747
748 /**
749  * Frees a mutex.
750  */
751 void
752 palacios_mutex_free(void * mutex) {
753     palacios_free(mutex);
754     LOCKCHECK_FREE(mutex);
755 }
756
757 /**
758  * Locks a mutex.
759  */
760 void 
761 palacios_mutex_lock(void * mutex, int must_spin) {
762
763     LOCKCHECK_LOCK_PRE(mutex);
764     spin_lock((spinlock_t *)mutex);
765     LOCKCHECK_LOCK_POST(mutex);
766 }
767
768
769 /**
770  * Locks a mutex, disabling interrupts on this core
771  */
772 void *
773 palacios_mutex_lock_irqsave(void * mutex, int must_spin) {
774     
775     unsigned long flags; 
776     
777     LOCKCHECK_LOCK_IRQSAVE_PRE(mutex,flags);
778     spin_lock_irqsave((spinlock_t *)mutex,flags);
779     LOCKCHECK_LOCK_IRQSAVE_POST(mutex,flags);
780
781     return (void *)flags;
782 }
783
784
785 /**
786  * Unlocks a mutex.
787  */
788 void 
789 palacios_mutex_unlock(
790         void *                  mutex
791
792 {
793     LOCKCHECK_UNLOCK_PRE(mutex);
794     spin_unlock((spinlock_t *)mutex);
795     LOCKCHECK_UNLOCK_POST(mutex);
796 }
797
798
799 /**
800  * Unlocks a mutex and restores previous interrupt state on this core
801  */
802 void 
803 palacios_mutex_unlock_irqrestore(void *mutex, void *flags)
804 {
805     LOCKCHECK_UNLOCK_IRQRESTORE_PRE(mutex,(unsigned long)flags);
806     // This is correct, flags is opaque
807     spin_unlock_irqrestore((spinlock_t *)mutex,(unsigned long)flags);
808     LOCKCHECK_UNLOCK_IRQRESTORE_POST(mutex,(unsigned long)flags);
809 }
810
811 void palacios_used_fpu(void)
812 {
813    struct thread_info *cur = current_thread_info();
814
815    // We assume we are not preemptible here...
816    cur->status |= TS_USEDFPU;
817    clts(); 
818    // After this, FP Save should be handled by Linux if it
819    // switches to a different task and that task uses FPU
820 }
821
822 inline int ists(void)
823 {
824    return read_cr0() & X86_CR0_TS;
825
826 }
827 void palacios_need_fpu(void)
828 {
829     // We assume we are not preemptible here... 
830     if (ists()) { 
831       // we have been switched back to from somewhere else...
832       // Do a restore now - this will also do a clts()
833       math_state_restore();
834     }
835 }
836
837
838 /**
839  * Structure used by the Palacios hypervisor to interface with the host kernel.
840  */
841 static struct v3_os_hooks palacios_os_hooks = {
842         .print                  = palacios_print_scoped,
843         .allocate_pages         = palacios_allocate_pages,
844         .free_pages             = palacios_free_pages,
845         .malloc                 = palacios_alloc,
846         .free                   = palacios_free,
847         .vaddr_to_paddr         = palacios_vaddr_to_paddr,
848         .paddr_to_vaddr         = palacios_paddr_to_vaddr,
849         .hook_interrupt         = palacios_hook_interrupt,
850         .ack_irq                = palacios_ack_interrupt,
851         .get_cpu_khz            = palacios_get_cpu_khz,
852         .start_kernel_thread    = palacios_start_kernel_thread,
853         .yield_cpu              = palacios_yield_cpu,
854         .sleep_cpu              = palacios_sleep_cpu,
855         .wakeup_cpu             = palacios_wakeup_cpu,
856         .mutex_alloc            = palacios_mutex_alloc,
857         .mutex_free             = palacios_mutex_free,
858         .mutex_lock             = palacios_mutex_lock, 
859         .mutex_unlock           = palacios_mutex_unlock,
860         .mutex_lock_irqsave     = palacios_mutex_lock_irqsave, 
861         .mutex_unlock_irqrestore= palacios_mutex_unlock_irqrestore,
862         .get_cpu                = palacios_get_cpu,
863         .interrupt_cpu          = palacios_interrupt_cpu,
864         .call_on_cpu            = palacios_xcall,
865         .create_thread_on_cpu   = palacios_start_thread_on_cpu,
866         .start_thread           = palacios_start_thread,
867         .move_thread_to_cpu     = palacios_move_thread_to_cpu,
868 };
869
870
871 #ifdef V3_CONFIG_HOST_LAZY_FPU_SWITCH
872 // Note that this host interface is defined here since it's
873 // intertwined with thread creation... 
874 static struct v3_lazy_fpu_iface palacios_fpu_hooks = {
875         .used_fpu               = palacios_used_fpu,
876         .need_fpu               = palacios_need_fpu
877 };
878
879 #endif
880
881
882 int palacios_vmm_init( char *options )
883 {
884     int num_cpus = num_online_cpus();
885     char * cpu_mask = NULL;
886
887     if (cpu_list_len > 0) {
888         int major = 0;
889         int minor = 0;
890         int i = 0;
891
892         cpu_mask = palacios_alloc((num_cpus / 8) + 1);
893
894         if (!cpu_mask) { 
895             ERROR("Cannot allocate cpu mask\n");
896             return -1;
897         }
898
899         memset(cpu_mask, 0, (num_cpus / 8) + 1);
900         
901         for (i = 0; i < cpu_list_len; i++) {
902             if (cpu_list[i] >= num_cpus) {
903                 WARNING("CPU (%d) exceeds number of available CPUs. Ignoring...\n", cpu_list[i]);
904                 continue;
905             }
906
907             major = cpu_list[i] / 8;
908             minor = cpu_list[i] % 8;
909     
910             *(cpu_mask + major) |= (0x1 << minor);
911         }
912     }
913
914     memset(irq_to_guest_map, 0, sizeof(struct v3_vm_info *) * 256);
915
916     if (init_print_buffers()) {
917         ERROR("Cannot initialize print buffers\n");
918         palacios_free(cpu_mask);
919         return -1;
920     }
921
922     INFO("palacios_init starting - calling init_v3\n");
923
924     Init_V3(&palacios_os_hooks, cpu_mask, num_cpus, options);
925
926 #ifdef V3_CONFIG_HOST_LAZY_FPU_SWITCH
927     V3_Init_Lazy_FPU(&palacios_fpu_hooks);
928 #endif
929
930     return 0;
931
932 }
933
934
935 int palacios_vmm_exit( void ) {
936
937     Shutdown_V3();
938
939     INFO("palacios shutdown complete\n");
940
941     deinit_print_buffers();
942
943     return 0;
944 }