2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2011, Lei Xia <lxia@northwestern.edu>
11 * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * This is free software. You are permitted to use, redistribute,
15 * and modify it under the terms of the GNU General Public License
16 * Version 2 (GPLv2). The accompanying COPYING file contains the
17 * full text of the license.
19 /* Palacios VNET Host Hooks Implementations */
21 #include <linux/kernel.h>
22 #include <linux/kthread.h>
23 #include <linux/spinlock.h>
24 #include <linux/gfp.h>
25 #include <linux/sched.h>
26 #include <linux/uaccess.h>
27 #include <linux/init.h>
28 #include <linux/smp_lock.h>
29 #include <asm/delay.h>
30 #include <linux/timer.h>
32 #include <vnet/vnet.h>
34 #include "palacios-vnet.h"
35 #include "linux-exts.h"
37 static void host_print(const char * fmt, ...) {
48 static void * host_allocate_pages(int num_pages, unsigned int alignment){
50 struct page * pgs = NULL;
51 int order = get_order(num_pages * PAGE_SIZE);
53 pgs = alloc_pages(GFP_KERNEL, order);
55 WARN(!pgs, "Could not allocate pages\n");
57 addr = page_to_pfn(pgs) << PAGE_SHIFT;
63 static void host_free_pages(void * page_paddr, int num_pages) {
64 uintptr_t pg_addr = (uintptr_t)page_paddr;
66 __free_pages(pfn_to_page(pg_addr >> PAGE_SHIFT), get_order(num_pages * PAGE_SIZE));
71 host_alloc(unsigned int size) {
73 addr = kmalloc(size, GFP_KERNEL);
88 host_vaddr_to_paddr(void * vaddr)
90 return (void*) __pa(vaddr);
95 host_paddr_to_vaddr(void * paddr)
102 host_start_kernel_thread(
103 int (*fn)(void * arg),
105 char * thread_name) {
106 struct task_struct * thread = NULL;
108 thread = kthread_run(fn, arg, thread_name );
113 static void host_kthread_sleep(long timeout){
114 set_current_state(TASK_INTERRUPTIBLE);
119 schedule_timeout(timeout);
125 static void host_kthread_wakeup(void * thread){
126 struct task_struct * kthread = (struct task_struct *)thread;
128 wake_up_process(kthread);
131 static void host_kthread_stop(void * thread){
132 struct task_struct * kthread = (struct task_struct *)thread;
134 kthread_stop(kthread);
137 static int host_kthread_should_stop(void){
138 return kthread_should_stop();
142 static void host_udelay(unsigned long usecs){
156 host_mutex_alloc(void)
158 spinlock_t * lock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
161 spin_lock_init(lock);
176 host_mutex_lock(void * mutex,
179 spin_lock((spinlock_t *)mutex);
183 host_mutex_unlock(void * mutex)
185 spin_unlock((spinlock_t *)mutex);
192 struct timer_list timer;
193 unsigned long interval;
196 void (* timer_fun)(void * private_data);
201 void timeout_fn(unsigned long arg){
202 struct host_timer * timer = (struct host_timer *)arg;
205 timer->timer_fun(timer->pri_data);
207 mod_timer(&(timer->timer), timer->interval);
212 host_create_timer(unsigned long interval,
213 void (* timer_fun)(void * priv_data),
215 struct host_timer * timer = (struct host_timer *)kmalloc(sizeof(struct host_timer), GFP_KERNEL);
217 timer->interval = interval;
218 timer->timer_fun = timer_fun;
219 timer->pri_data = data;
221 init_timer(&(timer->timer));
223 timer->timer.data = (unsigned long)timer;
224 timer->timer.function = timeout_fn;
225 timer->timer.expires = interval;
231 host_start_timer(void * vnet_timer){
232 struct host_timer * timer = (struct host_timer *)vnet_timer;
235 add_timer(&(timer->timer));
239 host_reset_timer(void * vnet_timer, unsigned long interval){
240 struct host_timer * timer = (struct host_timer *)timer;
242 timer->interval = interval;
246 host_stop_timer(void * vnet_timer){
247 struct host_timer * timer = (struct host_timer *)vnet_timer;
250 del_timer(&(timer->timer));
254 host_del_timer(void * vnet_timer){
255 struct host_timer * timer = (struct host_timer *)vnet_timer;
257 del_timer(&(timer->timer));
266 static struct vnet_host_hooks vnet_host_hooks = {
267 .timer_create = host_create_timer,
268 .timer_del = host_del_timer,
269 .timer_start = host_start_timer,
270 .timer_stop = host_stop_timer,
271 .timer_reset = host_reset_timer,
273 .thread_start = host_start_kernel_thread,
274 .thread_sleep = host_kthread_sleep,
275 .thread_wakeup = host_kthread_wakeup,
276 .thread_stop = host_kthread_stop,
277 .thread_should_stop = host_kthread_should_stop,
278 .udelay = host_udelay,
280 .yield_cpu = host_yield_cpu,
281 .mutex_alloc = host_mutex_alloc,
282 .mutex_free = host_mutex_free,
283 .mutex_lock = host_mutex_lock,
284 .mutex_unlock = host_mutex_unlock,
287 .allocate_pages = host_allocate_pages,
288 .free_pages = host_free_pages,
289 .malloc = host_alloc,
291 .vaddr_to_paddr = host_vaddr_to_paddr,
292 .paddr_to_vaddr = host_paddr_to_vaddr,
297 static int vnet_init( void ) {
298 init_vnet(&vnet_host_hooks);
303 printk("V3 VNET Inited\n");
309 static int vnet_deinit( void ) {
312 vnet_bridge_deinit();
315 printk("V3 VNET Deinited\n");
320 static struct linux_ext vnet_ext = {
323 .deinit = vnet_deinit,
328 register_extension(&vnet_ext);