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.


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