struct palacios_graphics_console {
// descriptor for the data in the shared frame buffer
struct v3_frame_buffer_spec spec;
+
// the actual shared frame buffer
// Note that "shared" here means shared between palacios and us
// This data could of course also be shared with userland
- void *data;
+ void * data;
int cons_refcount;
int data_refcount;
gc->cons_refcount--;
gc->data_refcount--;
- if (gc->data_refcount<gc->cons_refcount) {
+ if (gc->data_refcount < gc->cons_refcount) {
printk("palacios: error! data refcount is less than console refcount for graphics console\n");
}
- if (gc->cons_refcount>0) {
+ if (gc->cons_refcount > 0) {
return;
} else {
- if (gc->cons_refcount<0) {
+ if (gc->cons_refcount < 0) {
printk("palacios: error! refcount for graphics console is negative on close!\n");
}
- if (gc->data_refcount>0) {
+ if (gc->data_refcount > 0) {
printk("palacios: error! refcount for graphics console data is positive on close - LEAKING MEMORY\n");
return;
}
static int fb_query(struct v3_guest * guest, unsigned int cmd, unsigned long arg,
void * priv_data) {
-
- struct v3_fb_query_response __user * u = (struct v3_fb_query_response __user *)arg;
+
struct palacios_graphics_console * cons = priv_data;
struct v3_fb_query_response q;
- if (copy_from_user(&q,(void __user *) u, sizeof(struct v3_fb_query_response))) {
+ if (copy_from_user(&q, (void __user *) arg, sizeof(struct v3_fb_query_response))) {
printk("palacios: copy from user in getting query in fb\n");
return -EFAULT;
}
printk("palacios: unable to copy fb content to user\n");
return -EFAULT;
}
- q.updated=1;
+ q.updated = 1;
}
break;
}
// now we'll copy back any changes we made to the query/response structure
- if (copy_to_user((void __user *) u, (void*)&q, sizeof(struct v3_fb_query_response))) {
+ if (copy_to_user((void __user *) arg, (void*)&q, sizeof(struct v3_fb_query_response))) {
printk("palacios: unable to copy fb response to user\n");
return -EFAULT;
}
unsigned long arg,
void * priv_data) {
- struct v3_fb_input __user * u = (struct v3_fb_input __user *)arg;
struct palacios_graphics_console * cons = priv_data;
struct v3_fb_input inp;
int rc = 0;
- if (copy_from_user(&inp,(void __user *) u, sizeof(struct v3_fb_input))) {
+ if (copy_from_user(&inp, (void __user *) arg, sizeof(struct v3_fb_input))) {
printk("palacios: copy from user in getting input in fb\n");
return -EFAULT;
}
#include <interfaces/vmm_host_dev.h>
#include "palacios.h"
-#include "palacios-host-dev.h"
#include "palacios-host-dev-user.h"
-
-
+#include "linux-exts.h"
+#include "palacios-vm.h"
/*
There are two things in this file:
*/
+struct palacios_host_dev {
+ spinlock_t lock;
+ struct list_head devs;
+};
+
+
#define MAX_URL 256
#define RENDEZVOUS_WAIT_SECS 60
-
-int connect_host_dev(struct v3_guest * guest, char *url)
+static int host_dev_connect(struct v3_guest * guest, unsigned int cmd, unsigned long arg, void * priv_data)
{
+ void __user * argp = (void __user *)arg;
+ char url[MAX_URL];
+ struct palacios_host_dev * host_dev = priv_data;
struct palacios_host_device_user *dev;
unsigned long f1, f2;
int i;
+
+
+ if (copy_from_user(url, argp, MAX_URL)) {
+ printk("copy from user error getting url for host device connect...\n");
+ return -EFAULT;
+ }
+
// currently only support user: types:
if (strncasecmp(url,"user:",5)) {
ERROR("palacios: do not currently support host devices of type in \"%s\"\n",url);
// URL. If we don't find it after a while, we give up
for (i=0;i<RENDEZVOUS_WAIT_SECS/RENDEZVOUS_RETRY_SECS;i++) {
- spin_lock_irqsave(&(guest->hostdev.lock),f1);
- list_for_each_entry(dev,&(guest->hostdev.devs), node) {
+ spin_lock_irqsave(&(host_dev->lock),f1);
+ list_for_each_entry(dev,&(host_dev->devs), node) {
if (!strncasecmp(url,dev->url,MAX_URL)) {
// found it
spin_lock_irqsave(&(dev->lock),f2);
if (dev->connected) {
ERROR("palacios: device for \"%s\" is already connected!\n",url);
spin_unlock_irqrestore(&(dev->lock),f2);
- spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+ spin_unlock_irqrestore(&(host_dev->lock),f1);
return -1;
} else {
dev->fd = anon_inode_getfd("v3-hostdev", &host_dev_fops, dev, 0);
if (dev->fd<0) {
ERROR("palacios: cannot create fd for device \"%s\"\n",url);
spin_unlock_irqrestore(&(dev->lock),f2);
- spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+ spin_unlock_irqrestore(&(host_dev->lock),f1);
return -1;
}
dev->connected=1;
}
INFO("palacios: connected fd for device \"%s\"\n",url);
spin_unlock_irqrestore(&(dev->lock),f2);
- spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+ spin_unlock_irqrestore(&(host_dev->lock),f1);
return dev->fd;
}
spin_unlock_irqrestore(&(dev->lock),f2);
}
}
- spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+ spin_unlock_irqrestore(&(host_dev->lock),f1);
ssleep(RENDEZVOUS_RETRY_SECS);
}
struct palacios_host_device_user *dev;
unsigned long f1,f2;
int i;
+ struct palacios_host_dev * host_dev = NULL;
/*
I will create the device in the list and then wait
for the user side to attach
*/
+ if (guest == NULL) {
+ return 0;
+ }
+
+
+ host_dev = get_vm_ext_data(guest, "HOST_DEV_INTERFACE");
+
+ if (host_dev == NULL) {
+ printk("Error locating vm host data for HOST_DEV_INTERFACE\n");
+ return 0;
+ }
+
if (strncasecmp(url,"user:",5)) {
ERROR("palacios: do not currently support devices of type in \"%s\"\n",url);
}
// Check to see if a device of this url already exists, which would be ugly
- spin_lock_irqsave(&(guest->hostdev.lock),f1);
- list_for_each_entry(dev,&(guest->hostdev.devs), node) {
+ spin_lock_irqsave(&(host_dev->lock),f1);
+ list_for_each_entry(dev,&(host_dev->devs), node) {
if (!strncasecmp(url,dev->url,MAX_URL)) {
// found it
- spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+ spin_unlock_irqrestore(&(host_dev->lock),f1);
ERROR("palacios: a host device with url \"%s\" already exists in the guest!\n",url);
return NULL;
}
}
- spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+ spin_unlock_irqrestore(&(host_dev->lock),f1);
INFO("palacios: creating host device \"%s\"\n",url);
INFO("palacios: attempting to rendezvous with user side of host device \"%s\"\n",url);
// Insert ourselves into the list
- spin_lock_irqsave(&(guest->hostdev.lock),f1);
- list_add(&(dev->node),&(guest->hostdev.devs));
- spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+ spin_lock_irqsave(&(host_dev->lock),f1);
+ list_add(&(dev->node),&(host_dev->devs));
+ spin_unlock_irqrestore(&(host_dev->lock),f1);
// Now wait until we are noticed!
ERROR("palacios: timeout waiting for user side to connect to host device \"%s\"",url);
// get us out of the list
- spin_lock_irqsave(&(guest->hostdev.lock),f1);
+ spin_lock_irqsave(&(host_dev->lock),f1);
list_del(&(dev->node));
- spin_unlock_irqrestore(&(guest->hostdev.lock),f1);
+ spin_unlock_irqrestore(&(host_dev->lock),f1);
palacios_host_dev_user_free(dev);
unsigned long f1, f2;
struct palacios_host_device_user *dev = (struct palacios_host_device_user *) hostdev;
-
+ struct palacios_host_dev * host_dev = NULL;
+
INFO("palacios: closing host device \"%s\"\n",dev->url);
- spin_lock_irqsave(&(dev->guest->hostdev.lock),f1);
+ if ((dev == NULL) || (dev->guest == NULL)) {
+ return -1;
+ }
+
+ host_dev = get_vm_ext_data(dev->guest, "HOST_DEV_INTERFACE");
+
+
+ if (host_dev == NULL) {
+ return -1;
+ }
+
+ spin_lock_irqsave(&(host_dev->lock),f1);
spin_lock_irqsave(&(dev->lock),f2);
list_del(&(dev->node));
spin_unlock_irqrestore(&(dev->lock),f2);
- spin_unlock_irqrestore(&(dev->guest->hostdev.lock),f1);
+ spin_unlock_irqrestore(&(host_dev->lock),f1);
palacios_host_dev_user_free(dev);
-int palacios_init_host_dev( void )
-{
+static int host_dev_init( void ) {
V3_Init_Host_Device_Support(&palacios_host_dev_hooks);
return 0;
}
+
+
+static int host_dev_guest_init(struct v3_guest * guest, void ** vm_data ) {
+ struct palacios_host_dev * host_dev = kmalloc(sizeof(struct palacios_host_dev), GFP_KERNEL);
+
+
+ INIT_LIST_HEAD(&(host_dev->devs));
+ spin_lock_init(&(host_dev->lock));
+
+ *vm_data = host_dev;
+
+
+ add_guest_ctrl(guest, V3_VM_HOST_DEV_CONNECT, host_dev_connect, host_dev);
+
+ return 0;
+}
+
+
+
+
+
+static struct linux_ext host_dev_ext = {
+ .name = "HOST_DEV_INTERFACE",
+ .init = host_dev_init,
+ .deinit = NULL,
+ .guest_init = host_dev_guest_init,
+ .guest_deinit = NULL
+};
+
+
+register_extension(&host_dev_ext);