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.


Initial support for moving virtual cores among different physical CPUs
[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
40 /**
41  * Prints a message to the console.
42  */
43 static void palacios_print(const char * fmt, ...) {
44   va_list ap;
45   va_start(ap, fmt);
46   vprintk(fmt, ap);
47   va_end(ap);
48   
49   return;
50 }
51
52
53
54 /*
55  * Allocates a contiguous region of pages of the requested size.
56  * Returns the physical address of the first page in the region.
57  */
58 static void * palacios_allocate_pages(int num_pages, unsigned int alignment) {
59     void * pg_addr = NULL;
60
61     pg_addr = (void *)alloc_palacios_pgs(num_pages, alignment);
62     pg_allocs += num_pages;
63
64     return pg_addr;
65 }
66
67
68 /**
69  * Frees a page previously allocated via palacios_allocate_page().
70  * Note that palacios_allocate_page() can allocate multiple pages with
71  * a single call while palacios_free_page() only frees a single page.
72  */
73
74 static void palacios_free_pages(void * page_paddr, int num_pages) {
75     pg_frees += num_pages;
76     free_palacios_pgs((uintptr_t)page_paddr, num_pages);
77 }
78
79
80 /**
81  * Allocates 'size' bytes of kernel memory.
82  * Returns the kernel virtual address of the memory allocated.
83  */
84 static void *
85 palacios_alloc(unsigned int size) {
86     void * addr = NULL;
87
88     if (irqs_disabled()) {
89         addr = kmalloc(size, GFP_ATOMIC);
90     } else {
91         addr = kmalloc(size, GFP_KERNEL);
92     }
93     mallocs++;
94  
95     return addr;
96 }
97
98 /**
99  * Frees memory that was previously allocated by palacios_alloc().
100  */
101 static void
102 palacios_free(
103         void *                  addr
104 )
105 {
106     frees++;
107     kfree(addr);
108     return;
109 }
110
111 /**
112  * Converts a kernel virtual address to the corresponding physical address.
113  */
114 static void *
115 palacios_vaddr_to_paddr(
116         void *                  vaddr
117 )
118 {
119     return (void*) __pa(vaddr);
120
121 }
122
123 /**
124  * Converts a physical address to the corresponding kernel virtual address.
125  */
126 static void *
127 palacios_paddr_to_vaddr(
128         void *                  paddr
129 )
130 {
131   return __va(paddr);
132 }
133
134 /**
135  * Runs a function on the specified CPU.
136  */
137
138 // For now, do call only on local CPU 
139 static void 
140 palacios_xcall(
141         int                     cpu_id, 
142         void                    (*fn)(void *arg),
143         void *                  arg
144 )
145 {
146
147
148     // We set wait to 1, but I'm not sure this is necessary
149     smp_call_function_single(cpu_id, fn, arg, 1);
150     
151     return;
152 }
153
154 struct lnx_thread_arg {
155     int (*fn)(void * arg);
156     void * arg;
157     char * name;
158 };
159
160 static int lnx_thread_target(void * arg) {
161     struct lnx_thread_arg * thread_info = (struct lnx_thread_arg *)arg;
162
163     /*
164       printk("Daemonizing new Palacios thread (name=%s)\n", thread_info->name);
165
166       daemonize(thread_info->name);
167       allow_signal(SIGKILL);
168     */
169
170
171     thread_info->fn(thread_info->arg);
172
173     kfree(thread_info);
174     // handle cleanup 
175     
176     return 0;
177 }
178
179 /**
180  * Creates a kernel thread.
181  */
182 static void 
183 palacios_start_kernel_thread(
184         int (*fn)               (void * arg),
185         void *                  arg,
186         char *                  thread_name) {
187
188     struct lnx_thread_arg * thread_info = kmalloc(sizeof(struct lnx_thread_arg), GFP_KERNEL);
189
190     thread_info->fn = fn;
191     thread_info->arg = arg;
192     thread_info->name = thread_name;
193
194     kthread_run( lnx_thread_target, thread_info, thread_name );
195     return;
196 }
197
198
199 /**
200  * Starts a kernel thread on the specified CPU.
201  */
202 static void * 
203 palacios_start_thread_on_cpu(int cpu_id, 
204                              int (*fn)(void * arg), 
205                              void * arg, 
206                              char * thread_name ) {
207     struct task_struct * thread = NULL;
208     struct lnx_thread_arg * thread_info = kmalloc(sizeof(struct lnx_thread_arg), GFP_KERNEL);
209
210     thread_info->fn = fn;
211     thread_info->arg = arg;
212     thread_info->name = thread_name;
213
214
215     thread = kthread_create( lnx_thread_target, thread_info, thread_name );
216
217     if (IS_ERR(thread)) {
218         printk("Palacios error creating thread: %s\n", thread_name);
219         return NULL;
220     }
221
222     kthread_bind(thread, cpu_id);
223     wake_up_process(thread);
224
225     return thread;
226 }
227
228
229 /**
230  * Rebind a kernel thread to the specified CPU
231  * The thread will be running on target CPU on return
232  * non-zero return means failure
233  */
234 static int
235 palacios_move_thread_to_cpu(int new_cpu_id, 
236                              void * thread_ptr) {
237     struct task_struct * thread = (struct task_struct *)thread_ptr;
238
239     if(thread == NULL){
240         thread = current;
241     }
242
243     /*
244      * Bind to the specified CPU.  When this call returns,
245      * the thread should be running on the target CPU.
246      */
247     return set_cpus_allowed(thread, cpumask_of_cpu(new_cpu_id));
248 }
249
250
251 /**
252  * Returns the CPU ID that the caller is running on.
253  */
254 static unsigned int 
255 palacios_get_cpu(void) 
256 {
257
258     /* We want to call smp_processor_id()
259      * But this is not safe if kernel preemption is possible 
260      * We need to ensure that the palacios threads are bound to a give cpu
261      */
262
263     unsigned int cpu_id = get_cpu(); 
264     put_cpu();
265     return cpu_id;
266 }
267
268 /**
269  * Interrupts the physical CPU corresponding to the specified logical guest cpu.
270  *
271  * NOTE: 
272  * This is dependent on the implementation of xcall_reschedule().  Currently
273  * xcall_reschedule does not explicitly call schedule() on the destination CPU,
274  * but instead relies on the return to user space to handle it. Because
275  * palacios is a kernel thread schedule will not be called, which is correct.
276  * If it ever changes to induce side effects, we'll need to figure something
277  * else out...
278  */
279
280 #include <asm/apic.h>
281
282 static void
283 palacios_interrupt_cpu(
284         struct v3_vm_info *     vm, 
285         int                     cpu_id, 
286         int                     vector
287 )
288 {
289     if (vector == 0) {
290         smp_send_reschedule(cpu_id);
291     } else {
292         apic->send_IPI_mask(cpumask_of(cpu_id), vector);
293     }
294     return;
295 }
296
297 /**
298  * Dispatches an interrupt to Palacios for handling.
299  */
300 static void
301 palacios_dispatch_interrupt( int vector, void * dev, struct pt_regs * regs ) {
302     struct v3_interrupt intr = {
303         .irq            = vector,
304         .error          = regs->orig_ax,
305         .should_ack     = 1,
306     };
307     
308     if (irq_to_guest_map[vector]) {
309         v3_deliver_irq(irq_to_guest_map[vector], &intr);
310     }
311     
312 }
313
314 /**
315  * Instructs the kernel to forward the specified IRQ to Palacios.
316  */
317 static int
318 palacios_hook_interrupt(struct v3_vm_info *     vm,
319                         unsigned int            vector ) {
320     printk("hooking vector %d\n", vector);      
321
322     if (irq_to_guest_map[vector]) {
323         printk(KERN_WARNING
324                "%s: Interrupt vector %u is already hooked.\n",
325                __func__, vector);
326         return -1;
327     }
328
329     printk(KERN_DEBUG
330            "%s: Hooking interrupt vector %u to vm %p.\n",
331            __func__, vector, vm);
332
333     irq_to_guest_map[vector] = vm;
334
335     /*
336      * NOTE: Normally PCI devices are supposed to be level sensitive,
337      *       but we need them to be edge sensitive so that they are
338      *       properly latched by Palacios.  Leaving them as level
339      *       sensitive would lead to an interrupt storm.
340      */
341     //ioapic_set_trigger_for_vector(vector, ioapic_edge_sensitive);
342     
343     //set_idtvec_handler(vector, palacios_dispatch_interrupt);
344     if (vector < 32) {
345         panic("unexpected vector for hooking\n");
346     } else {
347         int device_id = 0;              
348         
349         int flag = 0;
350         int error;
351                 
352         printk("hooking vector: %d\n", vector);         
353
354         if (vector == 32) {
355             flag = IRQF_TIMER;
356         } else {
357             flag = IRQF_SHARED;
358         }
359
360         error = request_irq((vector - 32),
361                             (void *)palacios_dispatch_interrupt,
362                             flag,
363                             "interrupt_for_palacios",
364                             &device_id);
365         
366         if (error) {
367             printk("error code for request_irq is %d\n", error);
368             panic("request vector %d failed",vector);
369         }
370     }
371         
372     return 0;
373 }
374
375
376
377 /**
378  * Acknowledges an interrupt.
379  */
380 static int
381 palacios_ack_interrupt(
382         int                     vector
383
384 {
385   ack_APIC_irq(); 
386   printk("Pretending to ack interrupt, vector=%d\n",vector);
387   return 0;
388 }
389   
390 /**
391  * Returns the CPU frequency in kilohertz.
392  */
393 static unsigned int
394 palacios_get_cpu_khz(void) 
395 {
396     printk("cpu_khz is %u\n",cpu_khz);
397
398     if (cpu_khz == 0) { 
399         printk("faking cpu_khz to 1000000\n");
400         return 1000000;
401     } else {
402         return cpu_khz;
403     }
404   //return 1000000;
405 }
406
407 /**
408  * Yield the CPU so other host OS tasks can run.
409  */
410 static void
411 palacios_yield_cpu(void)
412 {
413     schedule();
414     return;
415 }
416
417
418
419 /**
420  * Allocates a mutex.
421  * Returns NULL on failure.
422  */
423 static void *
424 palacios_mutex_alloc(void)
425 {
426     spinlock_t *lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
427
428     if (lock) {
429         spin_lock_init(lock);
430     }
431     
432     return lock;
433 }
434
435 /**
436  * Frees a mutex.
437  */
438 static void
439 palacios_mutex_free(void * mutex) {
440     kfree(mutex);
441 }
442
443 /**
444  * Locks a mutex.
445  */
446 static void 
447 palacios_mutex_lock(void * mutex, int must_spin) {
448     spin_lock((spinlock_t *)mutex);
449 }
450
451 /**
452  * Unlocks a mutex.
453  */
454 static void 
455 palacios_mutex_unlock(
456         void *                  mutex
457
458 {
459     spin_unlock((spinlock_t *)mutex);
460 }
461
462 /**
463  * Structure used by the Palacios hypervisor to interface with the host kernel.
464  */
465 static struct v3_os_hooks palacios_os_hooks = {
466         .print                  = palacios_print,
467         .allocate_pages         = palacios_allocate_pages,
468         .free_pages             = palacios_free_pages,
469         .malloc                 = palacios_alloc,
470         .free                   = palacios_free,
471         .vaddr_to_paddr         = palacios_vaddr_to_paddr,
472         .paddr_to_vaddr         = palacios_paddr_to_vaddr,
473         .hook_interrupt         = palacios_hook_interrupt,
474         .ack_irq                = palacios_ack_interrupt,
475         .get_cpu_khz            = palacios_get_cpu_khz,
476         .start_kernel_thread    = palacios_start_kernel_thread,
477         .yield_cpu              = palacios_yield_cpu,
478         .mutex_alloc            = palacios_mutex_alloc,
479         .mutex_free             = palacios_mutex_free,
480         .mutex_lock             = palacios_mutex_lock, 
481         .mutex_unlock           = palacios_mutex_unlock,
482         .get_cpu                = palacios_get_cpu,
483         .interrupt_cpu          = palacios_interrupt_cpu,
484         .call_on_cpu            = palacios_xcall,
485         .start_thread_on_cpu    = palacios_start_thread_on_cpu,
486         .move_thread_to_cpu = palacios_move_thread_to_cpu,
487 };
488
489
490
491
492 int palacios_vmm_init( void )
493 {
494     
495     memset(irq_to_guest_map, 0, sizeof(struct v3_vm_info *) * 256);
496     
497     printk("palacios_init starting - calling init_v3\n");
498     
499     Init_V3(&palacios_os_hooks, nr_cpu_ids);
500
501     return 0;
502
503 }
504
505
506 int palacios_vmm_exit( void ) {
507
508     Shutdown_V3();
509
510     return 0;
511 }