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.


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