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.


Corrected timed yield
[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             kfree(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] = kmalloc(V3_PRINTK_BUF_SIZE,GFP_KERNEL);
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 - 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     pg_allocs += num_pages;
148
149     return pg_addr;
150 }
151
152
153 /**
154  * Frees a page previously allocated via palacios_allocate_page().
155  * Note that palacios_allocate_page() can allocate multiple pages with
156  * a single call while palacios_free_page() only frees a single page.
157  */
158
159 void palacios_free_pages(void * page_paddr, int num_pages) {
160     pg_frees += num_pages;
161     free_palacios_pgs((uintptr_t)page_paddr, num_pages);
162 }
163
164
165 /**
166  * Allocates 'size' bytes of kernel memory.
167  * Returns the kernel virtual address of the memory allocated.
168  */
169 void *
170 palacios_alloc(unsigned int size) {
171     void * addr = NULL;
172
173     if (irqs_disabled()) {
174         addr = kmalloc(size, GFP_ATOMIC);
175     } else {
176         addr = kmalloc(size, GFP_KERNEL);
177     }
178     
179     if (addr) { 
180         mallocs++;
181     }
182
183     return addr;
184 }
185
186 /**
187  * Frees memory that was previously allocated by palacios_alloc().
188  */
189 void
190 palacios_free(
191         void *                  addr
192 )
193 {
194     frees++;
195     kfree(addr);
196     return;
197 }
198
199 /**
200  * Converts a kernel virtual address to the corresponding physical address.
201  */
202 void *
203 palacios_vaddr_to_paddr(
204         void *                  vaddr
205 )
206 {
207     return (void*) __pa(vaddr);
208
209 }
210
211 /**
212  * Converts a physical address to the corresponding kernel virtual address.
213  */
214 void *
215 palacios_paddr_to_vaddr(
216         void *                  paddr
217 )
218 {
219   return __va(paddr);
220 }
221
222 /**
223  * Runs a function on the specified CPU.
224  */
225 static void 
226 palacios_xcall(
227         int                     cpu_id, 
228         void                    (*fn)(void *arg),
229         void *                  arg
230 )
231 {
232
233
234     // We set wait to 1, but I'm not sure this is necessary
235     smp_call_function_single(cpu_id, fn, arg, 1);
236     
237     return;
238 }
239
240 struct lnx_thread_arg {
241     int (*fn)(void * arg);
242     void * arg;
243     char * name;
244 };
245
246 static int lnx_thread_target(void * arg) {
247     struct lnx_thread_arg * thread_info = (struct lnx_thread_arg *)arg;
248     int ret = 0;
249     /*
250       INFO("Daemonizing new Palacios thread (name=%s)\n", thread_info->name);
251
252       daemonize(thread_info->name);
253       allow_signal(SIGKILL);
254     */
255
256
257     ret = thread_info->fn(thread_info->arg);
258
259
260     INFO("Palacios Thread (%s) EXITING\n", thread_info->name);
261
262     kfree(thread_info);
263     // handle cleanup 
264
265     do_exit(ret);
266     
267     return 0; // should not get here.
268 }
269
270 /**
271  * Creates a kernel thread.
272  */
273 void *
274 palacios_start_kernel_thread(
275         int (*fn)               (void * arg),
276         void *                  arg,
277         char *                  thread_name) {
278
279     struct lnx_thread_arg * thread_info = kmalloc(sizeof(struct lnx_thread_arg), GFP_KERNEL);
280
281     thread_info->fn = fn;
282     thread_info->arg = arg;
283     thread_info->name = thread_name;
284
285     return kthread_run( lnx_thread_target, thread_info, thread_name );
286 }
287
288
289 /**
290  * Starts a kernel thread on the specified CPU.
291  */
292 void * 
293 palacios_start_thread_on_cpu(int cpu_id, 
294                              int (*fn)(void * arg), 
295                              void * arg, 
296                              char * thread_name ) {
297     struct task_struct * thread = NULL;
298     struct lnx_thread_arg * thread_info = kmalloc(sizeof(struct lnx_thread_arg), GFP_KERNEL);
299
300     thread_info->fn = fn;
301     thread_info->arg = arg;
302     thread_info->name = thread_name;
303
304
305     thread = kthread_create( lnx_thread_target, thread_info, thread_name );
306
307     if (IS_ERR(thread)) {
308         WARNING("Palacios error creating thread: %s\n", thread_name);
309         return NULL;
310     }
311
312     if (set_cpus_allowed_ptr(thread, cpumask_of(cpu_id)) != 0) {
313         kthread_stop(thread);
314         return NULL;
315     }
316
317     wake_up_process(thread);
318
319     return thread;
320 }
321
322
323 /**
324  * Rebind a kernel thread to the specified CPU
325  * The thread will be running on target CPU on return
326  * non-zero return means failure
327  */
328 int
329 palacios_move_thread_to_cpu(int new_cpu_id, 
330                             void * thread_ptr) {
331     struct task_struct * thread = (struct task_struct *)thread_ptr;
332
333     INFO("Moving thread (%p) to cpu %d\n", thread, new_cpu_id);
334
335     if (thread == NULL) {
336         thread = current;
337     }
338
339     /*
340      * Bind to the specified CPU.  When this call returns,
341      * the thread should be running on the target CPU.
342      */
343     return set_cpus_allowed_ptr(thread, cpumask_of(new_cpu_id));
344 }
345
346
347 /**
348  * Returns the CPU ID that the caller is running on.
349  */
350 unsigned int 
351 palacios_get_cpu(void) 
352 {
353
354     /* We want to call smp_processor_id()
355      * But this is not safe if kernel preemption is possible 
356      * We need to ensure that the palacios threads are bound to a give cpu
357      */
358
359     unsigned int cpu_id = get_cpu(); 
360     put_cpu();
361     return cpu_id;
362 }
363
364 /**
365  * Interrupts the physical CPU corresponding to the specified logical guest cpu.
366  *
367  * NOTE: 
368  * This is dependent on the implementation of xcall_reschedule().  Currently
369  * xcall_reschedule does not explicitly call schedule() on the destination CPU,
370  * but instead relies on the return to user space to handle it. Because
371  * palacios is a kernel thread schedule will not be called, which is correct.
372  * If it ever changes to induce side effects, we'll need to figure something
373  * else out...
374  */
375
376 #include <asm/apic.h>
377
378 static void
379 palacios_interrupt_cpu(
380         struct v3_vm_info *     vm, 
381         int                     cpu_id, 
382         int                     vector
383 )
384 {
385     if (vector == 0) {
386         smp_send_reschedule(cpu_id);
387     } else {
388         apic->send_IPI_mask(cpumask_of(cpu_id), vector);
389     }
390     return;
391 }
392
393 /**
394  * Dispatches an interrupt to Palacios for handling.
395  */
396 static void
397 palacios_dispatch_interrupt( int vector, void * dev, struct pt_regs * regs ) {
398     struct v3_interrupt intr = {
399         .irq            = vector,
400         .error          = regs->orig_ax,
401         .should_ack     = 1,
402     };
403     
404     if (irq_to_guest_map[vector]) {
405         v3_deliver_irq(irq_to_guest_map[vector], &intr);
406     }
407     
408 }
409
410 /**
411  * Instructs the kernel to forward the specified IRQ to Palacios.
412  */
413 static int
414 palacios_hook_interrupt(struct v3_vm_info *     vm,
415                         unsigned int            vector ) {
416     INFO("hooking vector %d\n", vector);        
417
418     if (irq_to_guest_map[vector]) {
419         WARNING(
420                "%s: Interrupt vector %u is already hooked.\n",
421                __func__, vector);
422         return -1;
423     }
424
425     DEBUG(
426            "%s: Hooking interrupt vector %u to vm %p.\n",
427            __func__, vector, vm);
428
429     irq_to_guest_map[vector] = vm;
430
431     /*
432      * NOTE: Normally PCI devices are supposed to be level sensitive,
433      *       but we need them to be edge sensitive so that they are
434      *       properly latched by Palacios.  Leaving them as level
435      *       sensitive would lead to an interrupt storm.
436      */
437     //ioapic_set_trigger_for_vector(vector, ioapic_edge_sensitive);
438     
439     //set_idtvec_handler(vector, palacios_dispatch_interrupt);
440     if (vector < 32) {
441         panic("unexpected vector for hooking\n");
442     } else {
443         int device_id = 0;              
444         
445         int flag = 0;
446         int error;
447                 
448         DEBUG("hooking vector: %d\n", vector);          
449
450         if (vector == 32) {
451             flag = IRQF_TIMER;
452         } else {
453             flag = IRQF_SHARED;
454         }
455
456         error = request_irq((vector - 32),
457                             (void *)palacios_dispatch_interrupt,
458                             flag,
459                             "interrupt_for_palacios",
460                             &device_id);
461         
462         if (error) {
463             ERROR("error code for request_irq is %d\n", error);
464             panic("request vector %d failed", vector);
465         }
466     }
467         
468     return 0;
469 }
470
471
472
473 /**
474  * Acknowledges an interrupt.
475  */
476 static int
477 palacios_ack_interrupt(
478         int                     vector
479
480 {
481   ack_APIC_irq(); 
482   DEBUG("Pretending to ack interrupt, vector=%d\n", vector);
483   return 0;
484 }
485   
486 /**
487  * Returns the CPU frequency in kilohertz.
488  */
489 unsigned int
490 palacios_get_cpu_khz(void) 
491 {
492     INFO("cpu_khz is %u\n", cpu_khz);
493
494     if (cpu_khz == 0) { 
495         INFO("faking cpu_khz to 1000000\n");
496         return 1000000;
497     } else {
498         return cpu_khz;
499     }
500   //return 1000000;
501 }
502
503 /**
504  * Yield the CPU so other host OS tasks can run.
505  * This will return immediately if there is no other thread that is runnable
506  * And there is no real bound on how long it will yield
507  */
508 void
509 palacios_yield_cpu(void)
510 {
511     schedule();
512     return;
513 }
514
515 /**
516  * Yield the CPU so other host OS tasks can run.
517  * Given now immediately if there is no other thread that is runnable
518  * And there is no real bound on how long it will yield
519  */
520 void palacios_yield_cpu_timed(unsigned int us)
521 {
522
523     unsigned int uspj = 1000000U/HZ;
524    
525     unsigned int jiffies = us/uspj + ((us%uspj) !=0);  // ceiling 
526
527     set_current_state(TASK_INTERRUPTIBLE);
528     
529     schedule_timeout(jiffies);
530
531 }
532
533
534 /**
535  * Allocates a mutex.
536  * Returns NULL on failure.
537  */
538 void *
539 palacios_mutex_alloc(void)
540 {
541     spinlock_t *lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
542
543     if (lock) {
544         spin_lock_init(lock);
545     }
546     
547     return lock;
548 }
549
550 /**
551  * Frees a mutex.
552  */
553 void
554 palacios_mutex_free(void * mutex) {
555     kfree(mutex);
556 }
557
558 /**
559  * Locks a mutex.
560  */
561 void 
562 palacios_mutex_lock(void * mutex, int must_spin) {
563     spin_lock((spinlock_t *)mutex);
564 }
565
566
567 /**
568  * Locks a mutex, disabling interrupts on this core
569  */
570 void *
571 palacios_mutex_lock_irqsave(void * mutex, int must_spin) {
572     
573     unsigned long flags; 
574     
575     spin_lock_irqsave((spinlock_t *)mutex,flags);
576
577     return (void *)flags;
578 }
579
580
581 /**
582  * Unlocks a mutex.
583  */
584 void 
585 palacios_mutex_unlock(
586         void *                  mutex
587
588 {
589     spin_unlock((spinlock_t *)mutex);
590 }
591
592
593 /**
594  * Unlocks a mutex.
595  */
596 void 
597 palacios_mutex_unlock_irqrestore(void *mutex, void *flags)
598 {
599     // This is correct, flags is opaque
600     spin_unlock_irqrestore((spinlock_t *)mutex,(unsigned long)flags);
601 }
602
603 /**
604  * Structure used by the Palacios hypervisor to interface with the host kernel.
605  */
606 static struct v3_os_hooks palacios_os_hooks = {
607         .print                  = palacios_print,
608         .allocate_pages         = palacios_allocate_pages,
609         .free_pages             = palacios_free_pages,
610         .malloc                 = palacios_alloc,
611         .free                   = palacios_free,
612         .vaddr_to_paddr         = palacios_vaddr_to_paddr,
613         .paddr_to_vaddr         = palacios_paddr_to_vaddr,
614         .hook_interrupt         = palacios_hook_interrupt,
615         .ack_irq                = palacios_ack_interrupt,
616         .get_cpu_khz            = palacios_get_cpu_khz,
617         .start_kernel_thread    = palacios_start_kernel_thread,
618         .yield_cpu              = palacios_yield_cpu,
619         .yield_cpu_timed        = palacios_yield_cpu_timed,
620         .mutex_alloc            = palacios_mutex_alloc,
621         .mutex_free             = palacios_mutex_free,
622         .mutex_lock             = palacios_mutex_lock, 
623         .mutex_unlock           = palacios_mutex_unlock,
624         .mutex_lock_irqsave     = palacios_mutex_lock_irqsave, 
625         .mutex_unlock_irqrestore= palacios_mutex_unlock_irqrestore,
626         .get_cpu                = palacios_get_cpu,
627         .interrupt_cpu          = palacios_interrupt_cpu,
628         .call_on_cpu            = palacios_xcall,
629         .start_thread_on_cpu    = palacios_start_thread_on_cpu,
630         .move_thread_to_cpu     = palacios_move_thread_to_cpu,
631 };
632
633
634
635
636 int palacios_vmm_init( void )
637 {
638     int num_cpus = num_online_cpus();
639     char * cpu_mask = NULL;
640
641     if (cpu_list_len > 0) {
642         int major = 0;
643         int minor = 0;
644         int i = 0;
645
646         cpu_mask = kmalloc((num_cpus / 8) + 1, GFP_KERNEL);
647
648         if (!cpu_mask) { 
649             ERROR("Cannot allocate cpu mask\n");
650             return -1;
651         }
652
653         memset(cpu_mask, 0, (num_cpus / 8) + 1);
654         
655         for (i = 0; i < cpu_list_len; i++) {
656             if (cpu_list[i] >= num_cpus) {
657                 WARNING("CPU (%d) exceeds number of available CPUs. Ignoring...\n", cpu_list[i]);
658                 continue;
659             }
660
661             major = cpu_list[i] / 8;
662             minor = cpu_list[i] % 8;
663     
664             *(cpu_mask + major) |= (0x1 << minor);
665         }
666     }
667
668     memset(irq_to_guest_map, 0, sizeof(struct v3_vm_info *) * 256);
669
670     if (init_print_buffers()) {
671         ERROR("Cannot initialize print buffers\n");
672         kfree(cpu_mask);
673         return -1;
674     }
675
676     INFO("palacios_init starting - calling init_v3\n");
677
678     Init_V3(&palacios_os_hooks, cpu_mask, num_cpus);
679
680     return 0;
681
682 }
683
684
685 int palacios_vmm_exit( void ) {
686
687     Shutdown_V3();
688
689     INFO("palacios shutdown complete\n");
690
691     deinit_print_buffers();
692
693     return 0;
694 }