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.


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