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.


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