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.


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