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.


Extensive, Pedantic Error Checking in Linux module, especially for memory
[palacios.git] / linux_module / palacios-stubs.c
1 #include <linux/kernel.h>
2 #include <linux/kthread.h>
3 #include <linux/spinlock.h>
4 #include <linux/gfp.h>
5 #include <linux/interrupt.h>
6 #include <linux/linkage.h>
7 #include <linux/sched.h>
8 #include <linux/uaccess.h>
9 #include <asm/irq_vectors.h>
10 #include <asm/io.h>
11
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <linux/kthread.h>
15 #include <asm/uaccess.h>
16 #include <linux/smp.h>
17
18 #include <palacios/vmm.h>
19 #include <palacios/vmm_host_events.h>
20 #include "palacios.h"
21
22
23
24
25 #include "mm.h"
26
27
28 u32 pg_allocs = 0;
29 u32 pg_frees = 0;
30 u32 mallocs = 0;
31 u32 frees = 0;
32
33
34 static struct v3_vm_info * irq_to_guest_map[256];
35
36
37 extern unsigned int cpu_khz;
38
39 extern int cpu_list[NR_CPUS];
40 extern int cpu_list_len;
41
42
43 static char *print_buffer[NR_CPUS];
44
45 static void deinit_print_buffers(void)
46 {
47     int i;
48
49     for (i=0;i<NR_CPUS;i++) {
50         if (print_buffer[i]) { 
51             palacios_free(print_buffer[i]);
52             print_buffer[i]=0;
53         }
54     }
55 }
56
57 static int init_print_buffers(void)
58 {
59     int i;
60     
61     memset(print_buffer,0,sizeof(char*)*NR_CPUS);
62
63 #if !V3_PRINTK_OLD_STYLE_OUTPUT
64
65     for (i=0;i<NR_CPUS;i++) { 
66         print_buffer[i] = palacios_alloc(V3_PRINTK_BUF_SIZE);
67         if (!print_buffer[i]) { 
68             ERROR("Cannot allocate print buffer for cpu %d\n",i);
69             deinit_print_buffers();
70             return -1;
71         }
72         memset(print_buffer[i],0,V3_PRINTK_BUF_SIZE);
73     }
74
75 #endif
76     
77     return 0;
78
79 }
80  
81 /**
82  * Prints a message to the console.
83  */
84 void palacios_print(const char *fmt, ...) {
85
86 #if V3_PRINTK_OLD_STYLE_OUTPUT
87
88   va_list ap;
89
90   va_start(ap, fmt);
91   vprintk(fmt, ap);
92   va_end(ap);
93
94   return
95
96 #else 
97
98   va_list ap;
99   char *buf;
100   unsigned int cpu = palacios_get_cpu();
101
102   buf = print_buffer[cpu];
103
104   if (!buf) { 
105       printk(KERN_INFO "palacios (pcore %u): output skipped - no allocated buffer\n",cpu);
106       return;
107   } 
108
109   va_start(ap, fmt);
110   vsnprintf(buf,V3_PRINTK_BUF_SIZE, fmt, ap);
111   va_end(ap);
112
113 #if V3_PRINTK_CHECK_7BIT
114   {
115       char c=0;
116       int i;
117       for (i=0;i<strlen(buf);i++) { 
118           if (buf[i] < 0) {
119               c=buf[i];
120               break;
121           }
122       }
123       if (c!=0) { 
124           printk(KERN_INFO "palacios (pcore %u): ALERT ALERT 8 BIT CHAR (c=%d) DETECTED\n", cpu,c);
125       }
126   }
127 #endif
128
129   printk(KERN_INFO "palacios (pcore %u): %s",cpu,buf);
130
131   return;
132
133 #endif
134
135 }
136
137
138
139 /*
140  * Allocates a contiguous region of pages of the requested size.
141  * Returns the physical address of the first page in the region.
142  */
143 void *palacios_allocate_pages(int num_pages, unsigned int alignment) {
144     void * pg_addr = NULL;
145
146     pg_addr = (void *)alloc_palacios_pgs(num_pages, alignment);
147
148     if (!pg_addr) { 
149         ERROR("ALERT ALERT  Page allocation has FAILED Warning\n");
150         return NULL;
151     }
152
153     pg_allocs += num_pages;
154
155     return pg_addr;
156 }
157
158
159 /**
160  * Frees a page previously allocated via palacios_allocate_page().
161  * Note that palacios_allocate_page() can allocate multiple pages with
162  * a single call while palacios_free_page() only frees a single page.
163  */
164
165 void palacios_free_pages(void * page_paddr, int num_pages) {
166     pg_frees += num_pages;
167     free_palacios_pgs((uintptr_t)page_paddr, num_pages);
168 }
169
170
171 /**
172  * Allocates 'size' bytes of kernel memory.
173  * Returns the kernel virtual address of the memory allocated.
174  */
175 void *
176 palacios_alloc(unsigned int size) {
177     void * addr = NULL;
178
179     // It is very important that this test remains since 
180     // this function is used extensively throughout palacios and the linux
181     // module, both in places where interrupts are off and where they are on
182     // a GFP_KERNEL call, when done with interrupts off can lead to DEADLOCK
183     if (irqs_disabled()) {
184         addr = kmalloc(size, GFP_ATOMIC);
185     } else {
186         addr = kmalloc(size, GFP_KERNEL);
187     }
188
189     if (!addr) { 
190        ERROR("ALERT ALERT  kmalloc has FAILED FAILED FAILED\n");
191        return NULL;
192     }   
193
194     mallocs++;
195
196     return addr;
197 }
198
199 /**
200  * Frees memory that was previously allocated by palacios_alloc().
201  */
202 void
203 palacios_free(
204         void *                  addr
205 )
206 {
207     frees++;
208     kfree(addr);
209     return;
210 }
211
212 /**
213  * Converts a kernel virtual address to the corresponding physical address.
214  */
215 void *
216 palacios_vaddr_to_paddr(
217         void *                  vaddr
218 )
219 {
220     return (void*) __pa(vaddr);
221
222 }
223
224 /**
225  * Converts a physical address to the corresponding kernel virtual address.
226  */
227 void *
228 palacios_paddr_to_vaddr(
229         void *                  paddr
230 )
231 {
232   return __va(paddr);
233 }
234
235 /**
236  * Runs a function on the specified CPU.
237  */
238 static void 
239 palacios_xcall(
240         int                     cpu_id, 
241         void                    (*fn)(void *arg),
242         void *                  arg
243 )
244 {
245
246
247     // We set wait to 1, but I'm not sure this is necessary
248     smp_call_function_single(cpu_id, fn, arg, 1);
249     
250     return;
251 }
252
253 struct lnx_thread_arg {
254     int (*fn)(void * arg);
255     void * arg;
256     char * name;
257 };
258
259 static int lnx_thread_target(void * arg) {
260     struct lnx_thread_arg * thread_info = (struct lnx_thread_arg *)arg;
261     int ret = 0;
262     /*
263       INFO("Daemonizing new Palacios thread (name=%s)\n", thread_info->name);
264
265       daemonize(thread_info->name);
266       allow_signal(SIGKILL);
267     */
268
269
270     ret = thread_info->fn(thread_info->arg);
271
272
273     INFO("Palacios Thread (%s) EXITING\n", thread_info->name);
274
275     palacios_free(thread_info);
276     // handle cleanup 
277
278     do_exit(ret);
279     
280     return 0; // should not get here.
281 }
282
283 /**
284  * Creates a kernel thread.
285  */
286 void *
287 palacios_start_kernel_thread(
288         int (*fn)               (void * arg),
289         void *                  arg,
290         char *                  thread_name) {
291
292     struct lnx_thread_arg * thread_info = palacios_alloc(sizeof(struct lnx_thread_arg));
293
294     if (!thread_info) { 
295         ERROR("ALERT ALERT Unable to allocate thread\n");
296         return NULL;
297     }
298
299     thread_info->fn = fn;
300     thread_info->arg = arg;
301     thread_info->name = thread_name;
302
303     return kthread_run( lnx_thread_target, thread_info, thread_name );
304 }
305
306
307 /**
308  * Starts a kernel thread on the specified CPU.
309  */
310 void * 
311 palacios_start_thread_on_cpu(int cpu_id, 
312                              int (*fn)(void * arg), 
313                              void * arg, 
314                              char * thread_name ) {
315     struct task_struct * thread = NULL;
316     struct lnx_thread_arg * thread_info = palacios_alloc(sizeof(struct lnx_thread_arg));
317
318     if (!thread_info) { 
319         ERROR("ALERT ALERT Unable to allocate thread to start on cpu\n");
320         return NULL;
321     }
322
323     thread_info->fn = fn;
324     thread_info->arg = arg;
325     thread_info->name = thread_name;
326
327
328     thread = kthread_create( lnx_thread_target, thread_info, thread_name );
329
330     if (IS_ERR(thread)) {
331         WARNING("Palacios error creating thread: %s\n", thread_name);
332         palacios_free(thread_info);
333         return NULL;
334     }
335
336     if (set_cpus_allowed_ptr(thread, cpumask_of(cpu_id)) != 0) {
337         WARNING("Attempt to start thread on disallowed CPU\n");
338         kthread_stop(thread);
339         palacios_free(thread_info);
340         return NULL;
341     }
342
343     wake_up_process(thread);
344
345     return thread;
346 }
347
348
349 /**
350  * Rebind a kernel thread to the specified CPU
351  * The thread will be running on target CPU on return
352  * non-zero return means failure
353  */
354 int
355 palacios_move_thread_to_cpu(int new_cpu_id, 
356                             void * thread_ptr) {
357     struct task_struct * thread = (struct task_struct *)thread_ptr;
358
359     INFO("Moving thread (%p) to cpu %d\n", thread, new_cpu_id);
360
361     if (thread == NULL) {
362         thread = current;
363     }
364
365     /*
366      * Bind to the specified CPU.  When this call returns,
367      * the thread should be running on the target CPU.
368      */
369     return set_cpus_allowed_ptr(thread, cpumask_of(new_cpu_id));
370 }
371
372
373 /**
374  * Returns the CPU ID that the caller is running on.
375  */
376 unsigned int 
377 palacios_get_cpu(void) 
378 {
379
380     /* We want to call smp_processor_id()
381      * But this is not safe if kernel preemption is possible 
382      * We need to ensure that the palacios threads are bound to a give cpu
383      */
384
385     unsigned int cpu_id = get_cpu(); 
386     put_cpu();
387     return cpu_id;
388 }
389
390 /**
391  * Interrupts the physical CPU corresponding to the specified logical guest cpu.
392  *
393  * NOTE: 
394  * This is dependent on the implementation of xcall_reschedule().  Currently
395  * xcall_reschedule does not explicitly call schedule() on the destination CPU,
396  * but instead relies on the return to user space to handle it. Because
397  * palacios is a kernel thread schedule will not be called, which is correct.
398  * If it ever changes to induce side effects, we'll need to figure something
399  * else out...
400  */
401
402 #include <asm/apic.h>
403
404 static void
405 palacios_interrupt_cpu(
406         struct v3_vm_info *     vm, 
407         int                     cpu_id, 
408         int                     vector
409 )
410 {
411     if (vector == 0) {
412         smp_send_reschedule(cpu_id);
413     } else {
414         apic->send_IPI_mask(cpumask_of(cpu_id), vector);
415     }
416     return;
417 }
418
419 /**
420  * Dispatches an interrupt to Palacios for handling.
421  */
422 static void
423 palacios_dispatch_interrupt( int vector, void * dev, struct pt_regs * regs ) {
424     struct v3_interrupt intr = {
425         .irq            = vector,
426         .error          = regs->orig_ax,
427         .should_ack     = 1,
428     };
429     
430     if (irq_to_guest_map[vector]) {
431         v3_deliver_irq(irq_to_guest_map[vector], &intr);
432     }
433     
434 }
435
436 /**
437  * Instructs the kernel to forward the specified IRQ to Palacios.
438  */
439 static int
440 palacios_hook_interrupt(struct v3_vm_info *     vm,
441                         unsigned int            vector ) {
442     INFO("hooking vector %d\n", vector);        
443
444     if (irq_to_guest_map[vector]) {
445         WARNING(
446                "%s: Interrupt vector %u is already hooked.\n",
447                __func__, vector);
448         return -1;
449     }
450
451     DEBUG(
452            "%s: Hooking interrupt vector %u to vm %p.\n",
453            __func__, vector, vm);
454
455     irq_to_guest_map[vector] = vm;
456
457     /*
458      * NOTE: Normally PCI devices are supposed to be level sensitive,
459      *       but we need them to be edge sensitive so that they are
460      *       properly latched by Palacios.  Leaving them as level
461      *       sensitive would lead to an interrupt storm.
462      */
463     //ioapic_set_trigger_for_vector(vector, ioapic_edge_sensitive);
464     
465     //set_idtvec_handler(vector, palacios_dispatch_interrupt);
466     if (vector < 32) {
467         ERROR("unexpected vector for hooking\n");
468         return -1;
469     } else {
470         int device_id = 0;              
471         
472         int flag = 0;
473         int error;
474                 
475         DEBUG("hooking vector: %d\n", vector);          
476
477         if (vector == 32) {
478             flag = IRQF_TIMER;
479         } else {
480             flag = IRQF_SHARED;
481         }
482
483         error = request_irq((vector - 32),
484                             (void *)palacios_dispatch_interrupt,
485                             flag,
486                             "interrupt_for_palacios",
487                             &device_id);
488         
489         if (error) {
490             ERROR("error code for request_irq is %d\n", error);
491             ERROR("request vector %d failed", vector);
492             return -1;
493         }
494     }
495         
496     return 0;
497 }
498
499
500
501 /**
502  * Acknowledges an interrupt.
503  */
504 static int
505 palacios_ack_interrupt(
506         int                     vector
507
508 {
509   ack_APIC_irq(); 
510   DEBUG("Pretending to ack interrupt, vector=%d\n", vector);
511   return 0;
512 }
513   
514 /**
515  * Returns the CPU frequency in kilohertz.
516  */
517 unsigned int
518 palacios_get_cpu_khz(void) 
519 {
520     INFO("cpu_khz is %u\n", cpu_khz);
521
522     if (cpu_khz == 0) { 
523         INFO("faking cpu_khz to 1000000\n");
524         return 1000000;
525     } else {
526         return cpu_khz;
527     }
528   //return 1000000;
529 }
530
531 /**
532  * Yield the CPU so other host OS tasks can run.
533  * This will return immediately if there is no other thread that is runnable
534  * And there is no real bound on how long it will yield
535  */
536 void
537 palacios_yield_cpu(void)
538 {
539     schedule();
540     return;
541 }
542
543 /**
544  * Yield the CPU so other host OS tasks can run.
545  * Given now immediately if there is no other thread that is runnable
546  * And there is no real bound on how long it will yield
547  */
548 void palacios_yield_cpu_timed(unsigned int us)
549 {
550
551     unsigned int uspj = 1000000U/HZ;
552    
553     unsigned int jiffies = us/uspj + ((us%uspj) !=0);  // ceiling 
554
555     set_current_state(TASK_INTERRUPTIBLE);
556     
557     schedule_timeout(jiffies);
558
559 }
560
561
562 /**
563  * Allocates a mutex.
564  * Returns NULL on failure.
565  */
566 void *
567 palacios_mutex_alloc(void)
568 {
569     spinlock_t *lock = palacios_alloc(sizeof(spinlock_t));
570
571     if (lock) {
572         spin_lock_init(lock);
573     } else {
574         ERROR("ALERT ALERT Unable to allocate lock\n");
575         return NULL;
576     }
577     
578     return lock;
579 }
580
581 /**
582  * Frees a mutex.
583  */
584 void
585 palacios_mutex_free(void * mutex) {
586     palacios_free(mutex);
587 }
588
589 /**
590  * Locks a mutex.
591  */
592 void 
593 palacios_mutex_lock(void * mutex, int must_spin) {
594     spin_lock((spinlock_t *)mutex);
595 }
596
597
598 /**
599  * Locks a mutex, disabling interrupts on this core
600  */
601 void *
602 palacios_mutex_lock_irqsave(void * mutex, int must_spin) {
603     
604     unsigned long flags; 
605     
606     spin_lock_irqsave((spinlock_t *)mutex,flags);
607
608     return (void *)flags;
609 }
610
611
612 /**
613  * Unlocks a mutex.
614  */
615 void 
616 palacios_mutex_unlock(
617         void *                  mutex
618
619 {
620     spin_unlock((spinlock_t *)mutex);
621 }
622
623
624 /**
625  * Unlocks a mutex and restores previous interrupt state on this core
626  */
627 void 
628 palacios_mutex_unlock_irqrestore(void *mutex, void *flags)
629 {
630     // This is correct, flags is opaque
631     spin_unlock_irqrestore((spinlock_t *)mutex,(unsigned long)flags);
632 }
633
634 /**
635  * Structure used by the Palacios hypervisor to interface with the host kernel.
636  */
637 static struct v3_os_hooks palacios_os_hooks = {
638         .print                  = palacios_print,
639         .allocate_pages         = palacios_allocate_pages,
640         .free_pages             = palacios_free_pages,
641         .malloc                 = palacios_alloc,
642         .free                   = palacios_free,
643         .vaddr_to_paddr         = palacios_vaddr_to_paddr,
644         .paddr_to_vaddr         = palacios_paddr_to_vaddr,
645         .hook_interrupt         = palacios_hook_interrupt,
646         .ack_irq                = palacios_ack_interrupt,
647         .get_cpu_khz            = palacios_get_cpu_khz,
648         .start_kernel_thread    = palacios_start_kernel_thread,
649         .yield_cpu              = palacios_yield_cpu,
650         .yield_cpu_timed        = palacios_yield_cpu_timed,
651         .mutex_alloc            = palacios_mutex_alloc,
652         .mutex_free             = palacios_mutex_free,
653         .mutex_lock             = palacios_mutex_lock, 
654         .mutex_unlock           = palacios_mutex_unlock,
655         .mutex_lock_irqsave     = palacios_mutex_lock_irqsave, 
656         .mutex_unlock_irqrestore= palacios_mutex_unlock_irqrestore,
657         .get_cpu                = palacios_get_cpu,
658         .interrupt_cpu          = palacios_interrupt_cpu,
659         .call_on_cpu            = palacios_xcall,
660         .start_thread_on_cpu    = palacios_start_thread_on_cpu,
661         .move_thread_to_cpu     = palacios_move_thread_to_cpu,
662 };
663
664
665
666
667 int palacios_vmm_init( void )
668 {
669     int num_cpus = num_online_cpus();
670     char * cpu_mask = NULL;
671
672     if (cpu_list_len > 0) {
673         int major = 0;
674         int minor = 0;
675         int i = 0;
676
677         cpu_mask = palacios_alloc((num_cpus / 8) + 1);
678
679         if (!cpu_mask) { 
680             ERROR("Cannot allocate cpu mask\n");
681             return -1;
682         }
683
684         memset(cpu_mask, 0, (num_cpus / 8) + 1);
685         
686         for (i = 0; i < cpu_list_len; i++) {
687             if (cpu_list[i] >= num_cpus) {
688                 WARNING("CPU (%d) exceeds number of available CPUs. Ignoring...\n", cpu_list[i]);
689                 continue;
690             }
691
692             major = cpu_list[i] / 8;
693             minor = cpu_list[i] % 8;
694     
695             *(cpu_mask + major) |= (0x1 << minor);
696         }
697     }
698
699     memset(irq_to_guest_map, 0, sizeof(struct v3_vm_info *) * 256);
700
701     if (init_print_buffers()) {
702         ERROR("Cannot initialize print buffers\n");
703         palacios_free(cpu_mask);
704         return -1;
705     }
706
707     INFO("palacios_init starting - calling init_v3\n");
708
709     Init_V3(&palacios_os_hooks, cpu_mask, num_cpus);
710
711     return 0;
712
713 }
714
715
716 int palacios_vmm_exit( void ) {
717
718     Shutdown_V3();
719
720     INFO("palacios shutdown complete\n");
721
722     deinit_print_buffers();
723
724     return 0;
725 }