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.


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