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;
55 int num_devices = (__stop__v3_devices - __start__v3_devices) / sizeof(struct v3_device_info);
56 PrintDebug("%d Virtual devices registered with Palacios\n", num_devices);
60 PrintDebug("Start addres=%p, Stop address=%p\n", __start__v3_devices, __stop__v3_devices);
62 master_dev_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn);
66 while (tmp_dev != __stop__v3_devices) {
67 PrintDebug("Device: %s\n", tmp_dev->name);
69 if (v3_htable_search(master_dev_table, (addr_t)(tmp_dev->name))) {
70 PrintError("Multiple instance of device (%s)\n", tmp_dev->name);
74 if (v3_htable_insert(master_dev_table,
75 (addr_t)(tmp_dev->name),
76 (addr_t)(tmp_dev->init)) == 0) {
77 PrintError("Could not add device %s to master list\n", tmp_dev->name);
81 tmp_dev = &(__start__v3_devices[++i]);
89 int v3_init_dev_mgr(struct guest_info * info) {
90 struct vmm_dev_mgr * mgr = &(info->dev_mgr);
92 INIT_LIST_HEAD(&(mgr->dev_list));
95 mgr->dev_table = v3_create_htable(0, dev_hash_fn, dev_eq_fn);
101 int v3_dev_mgr_deinit(struct guest_info * info) {
102 struct vm_device * dev;
103 struct vmm_dev_mgr * mgr = &(info->dev_mgr);
104 struct vm_device * tmp;
106 list_for_each_entry_safe(dev, tmp, &(mgr->dev_list), dev_link) {
107 v3_detach_device(dev);
116 int v3_create_device(struct guest_info * info, const char * dev_name, void * cfg_data) {
117 int (*dev_init)(struct guest_info * info, void * cfg_data);
119 dev_init = (void *)v3_htable_search(master_dev_table, (addr_t)dev_name);
121 if (dev_init == NULL) {
122 PrintError("Could not find device %s in master device table\n", dev_name);
127 if (dev_init(info, cfg_data) == -1) {
128 PrintError("Could not initialize Device %s\n", dev_name);
136 void v3_free_device(struct vm_device * dev) {
142 struct vm_device * v3_find_dev(struct guest_info * info, const char * dev_name) {
143 struct vmm_dev_mgr * mgr = &(info->dev_mgr);
145 return (struct vm_device *)v3_htable_search(mgr->dev_table, (addr_t)dev_name);
149 /****************************************************************/
150 /* The remaining functions are called by the devices themselves */
151 /****************************************************************/
154 int v3_dev_hook_io(struct vm_device * dev, uint16_t port,
155 int (*read)(uint16_t port, void * dst, uint_t length, struct vm_device * dev),
156 int (*write)(uint16_t port, void * src, uint_t length, struct vm_device * dev)) {
157 return v3_hook_io_port(dev->vm, port,
158 (int (*)(ushort_t, void *, uint_t, void *))read,
159 (int (*)(ushort_t, void *, uint_t, void *))write,
164 int v3_dev_unhook_io(struct vm_device * dev, uint16_t port) {
165 return v3_unhook_io_port(dev->vm, port);
170 int v3_detach_device(struct vm_device * dev) {
171 struct vmm_dev_mgr * mgr = &(dev->vm->dev_mgr);
175 list_del(&(dev->dev_link));
184 struct vm_device * v3_allocate_device(char * name,
185 struct v3_device_ops * ops,
186 void * private_data) {
187 struct vm_device * dev = NULL;
189 dev = (struct vm_device*)V3_Malloc(sizeof(struct vm_device));
191 strncpy(dev->name, name, 32);
193 dev->private_data = private_data;
201 int v3_attach_device(struct guest_info * vm, struct vm_device * dev ) {
202 struct vmm_dev_mgr * mgr = &(vm->dev_mgr);
206 list_add(&(dev->dev_link), &(mgr->dev_list));
210 v3_htable_insert(mgr->dev_table, (addr_t)(dev->name), (addr_t)dev);
218 void PrintDebugDevMgr(struct guest_info * info) {
219 struct vmm_dev_mgr * mgr = &(info->dev_mgr);
220 struct vm_device * dev;
222 PrintDebug("%d devices registered with manager\n", mgr->num_devs);
224 list_for_each_entry(dev, &(mgr->dev_list), dev_link) {
226 PrintDebug("next..\n");
233 void PrintDebugDev(struct vm_device * dev) {
234 PrintDebug("Device: %s\n", dev->name);
241 void PrintDebugDevMgr(struct guest_info * info) {}
242 void PrintDebugDev(struct vm_device * dev) {}