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.


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