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.


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