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.


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