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) 2008, Jack Lange <jarusl@cs.northwestern.edu>
11 * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Jack Lange <jarusl@cs.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #include <palacios/vmm_dev_mgr.h>
21 #include <palacios/vm_guest.h>
22 #include <palacios/vmm.h>
23 #include <palacios/vmm_decoder.h>
28 #define PrintDebug(fmt, args...)
32 static struct hashtable * master_dev_table = NULL;
34 static uint_t dev_hash_fn(addr_t key) {
35 char * name = (char *)key;
36 return v3_hash_buffer((uchar_t *)name, strlen(name));
39 static int dev_eq_fn(addr_t key1, addr_t key2) {
40 char * name1 = (char *)key1;
41 char * name2 = (char *)key2;
43 return (strcmp(name1, name2) == 0);
47 int v3_init_devices() {
48 extern struct v3_device_info __start__v3_devices[];
49 extern struct v3_device_info __stop__v3_devices[];
50 struct v3_device_info * tmp_dev = __start__v3_devices;
51 int num_devices = (__stop__v3_devices - __start__v3_devices) / sizeof(struct v3_device_info);
55 PrintDebug("%d Virtual devices registered with Palacios\n", num_devices);
56 PrintDebug("Start addres=%p, Stop address=%p\n", __start__v3_devices, __stop__v3_devices);
58 master_dev_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn);
62 while (tmp_dev != __stop__v3_devices) {
63 PrintDebug("Device: %s\n", tmp_dev->name);
65 if (v3_htable_search(master_dev_table, (addr_t)(tmp_dev->name))) {
66 PrintError("Multiple instance of device (%s)\n", tmp_dev->name);
70 if (v3_htable_insert(master_dev_table,
71 (addr_t)(tmp_dev->name),
72 (addr_t)(tmp_dev->init)) == 0) {
73 PrintError("Could not add device %s to master list\n", tmp_dev->name);
77 tmp_dev = &(__start__v3_devices[++i]);
85 int v3_init_dev_mgr(struct guest_info * info) {
86 struct vmm_dev_mgr * mgr = &(info->dev_mgr);
88 INIT_LIST_HEAD(&(mgr->dev_list));
91 mgr->dev_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn);
97 int v3_dev_mgr_deinit(struct guest_info * info) {
98 struct vm_device * dev;
99 struct vmm_dev_mgr * mgr = &(info->dev_mgr);
100 struct vm_device * tmp;
102 list_for_each_entry_safe(dev, tmp, &(mgr->dev_list), dev_link) {
103 v3_detach_device(dev);
112 int v3_create_device(struct guest_info * info, const char * dev_name, void * cfg_data) {
113 int (*dev_init)(struct guest_info * info, void * cfg_data);
115 dev_init = (void *)v3_htable_search(master_dev_table, (addr_t)dev_name);
117 if (dev_init == NULL) {
118 PrintError("Could not find device %s in master device table\n", dev_name);
123 if (dev_init(info, cfg_data) == -1) {
124 PrintError("Could not initialize Device %s\n", dev_name);
132 void v3_free_device(struct vm_device * dev) {
138 struct vm_device * v3_find_dev(struct guest_info * info, const char * dev_name) {
139 struct vmm_dev_mgr * mgr = &(info->dev_mgr);
141 return (struct vm_device *)v3_htable_search(mgr->dev_table, (addr_t)dev_name);
145 /****************************************************************/
146 /* The remaining functions are called by the devices themselves */
147 /****************************************************************/
150 int v3_dev_hook_io(struct vm_device * dev, uint16_t port,
151 int (*read)(uint16_t port, void * dst, uint_t length, struct vm_device * dev),
152 int (*write)(uint16_t port, void * src, uint_t length, struct vm_device * dev)) {
153 return v3_hook_io_port(dev->vm, port,
154 (int (*)(ushort_t, void *, uint_t, void *))read,
155 (int (*)(ushort_t, void *, uint_t, void *))write,
160 int v3_dev_unhook_io(struct vm_device * dev, uint16_t port) {
161 return v3_unhook_io_port(dev->vm, port);
166 int v3_detach_device(struct vm_device * dev) {
167 struct vmm_dev_mgr * mgr = &(dev->vm->dev_mgr);
171 list_del(&(dev->dev_link));
180 struct vm_device * v3_allocate_device(char * name,
181 struct v3_device_ops * ops,
182 void * private_data) {
183 struct vm_device * dev = NULL;
185 dev = (struct vm_device*)V3_Malloc(sizeof(struct vm_device));
187 strncpy(dev->name, name, 32);
189 dev->private_data = private_data;
197 int v3_attach_device(struct guest_info * vm, struct vm_device * dev ) {
198 struct vmm_dev_mgr * mgr = &(vm->dev_mgr);
202 list_add(&(dev->dev_link), &(mgr->dev_list));
206 v3_htable_insert(mgr->dev_table, (addr_t)(dev->name), (addr_t)dev);
214 void PrintDebugDevMgr(struct guest_info * info) {
215 struct vmm_dev_mgr * mgr = &(info->dev_mgr);
216 struct vm_device * dev;
218 PrintDebug("%d devices registered with manager\n", mgr->num_devs);
220 list_for_each_entry(dev, &(mgr->dev_list), dev_link) {
222 PrintDebug("next..\n");
229 void PrintDebugDev(struct vm_device * dev) {
230 PrintDebug("Device: %s\n", dev->name);
237 void PrintDebugDevMgr(struct guest_info * info) {}
238 void PrintDebugDev(struct vm_device * dev) {}