*/
-#define V3_VM_HOST_DEV_CONNECT 512+1
+#define V3_VM_HOST_DEV_CONNECT (10244+1)
/* to detemine whether a host request is available, poll the fd for read */
/* make a request for reading/writing guest or injecting irq */
/* the arguemnt is a pointer to a palacios_host_dev_user_op struct */
/* return is negative on error, positive to indicate bytes read/written or irq injected*/
-#define V3_HOST_DEV_USER_REQUEST_PUSH_IOCTL 1
+#define V3_HOST_DEV_USER_REQUEST_PUSH_IOCTL (10244+2)
/* find out the size of the current host request, if one is pending */
/* you find out if one is pending by read poll/select on the fd */
/* the argument is a pointer to a uint64_t that will give the total size */
/* ioctl returns 1 if a request is ready, 0 if there is no request */
/* -EFAULT if there is a an error */
-#define V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL 2
+#define V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL (10244+3)
/* get the current host request, if one is available */
/* the argument is a pointer to a palacios_host_dev_host_request_response */
/* of the needed size */
/* ioctl returns 1 if a request is ready+copied, 0 if there is no request */
/* -EFAULT if there is a an error */
-#define V3_HOST_DEV_HOST_REQUEST_PULL_IOCTL 3
+#define V3_HOST_DEV_HOST_REQUEST_PULL_IOCTL (10244+4)
/* write back the response to the previously pulled host request */
/* the argument is a pointer to a palacios_host_dev_host_request_response */
-#define V3_HOST_DEV_USER_RESPONSE_PUSH_IOCTL 4
+#define V3_HOST_DEV_USER_RESPONSE_PUSH_IOCTL (10244+5)
#ifdef __KERNEL__
return 0;
}
+
static int host_dev_ioctl(struct inode *ip, struct file *fp, unsigned int val, unsigned long arg)
{
void __user *argp = (void __user *)arg;
struct palacios_host_device_user *dev = fp->private_data;
+
if (!dev->connected) {
return -EFAULT;
}
}
spin_unlock_irqrestore(&(dev->lock),f);
-
+
return 1; // have request for you
}
}
+
+
static struct file_operations host_dev_fops = {
.poll = host_dev_poll,
.release = host_dev_release,
spin_unlock_irqrestore(&(dev->lock),f);
return 0;
}
-
+
// resize request and response in case they will need it
palacios_resize_reqresp(&(dev->req),len,0); // make room for data
#define V3_VM_STREAM_CONNECT 21
#define V3_VM_STOP 22
-#define V3_VM_FB_INPUT 256+1
-#define V3_VM_FB_QUERY 256+2
+#define V3_VM_FB_INPUT (256+1)
+#define V3_VM_FB_QUERY (256+2)
-#define V3_VM_HOST_DEV_CONNECT 512+1
+#define V3_VM_HOST_DEV_CONNECT (10244+1)
struct v3_guest_img {
-all: v3_ctrl v3_stop v3_cons v3_mem v3_monitor v3_serial v3_net v3_user_host_dev_example
+all: v3_ctrl v3_stop v3_cons v3_mem v3_monitor v3_serial v3_net v3_user_host_dev_example v3_os_debug
v3_user_host_dev_example: v3_user_host_dev_example.c v3_user_host_dev.h v3_user_host_dev.c
gcc -static -I../linux_module v3_user_host_dev_example.c v3_user_host_dev.c -o v3_user_host_dev_example
+v3_os_debug: v3_os_debug.c v3_user_host_dev.h v3_user_host_dev.c
+ gcc -static -I../linux_module v3_os_debug.c v3_user_host_dev.c -o v3_os_debug
+
+
clean:
- rm -f v3_ctrl v3_cons v3_mem v3_monitor v3_serial v3_net
+ rm -f v3_ctrl v3_cons v3_mem v3_monitor v3_serial v3_net v3_user_host_dev_example v3_os_debug
--- /dev/null
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/select.h>
+#include <malloc.h>
+
+#include "v3_user_host_dev.h"
+
+void usage()
+{
+ fprintf(stderr,"v3_user_host_dev_example /dev/v3-vm0 user:mydev busywait|select\n");
+}
+
+
+int do_work(struct palacios_host_dev_host_request_response *req,
+ struct palacios_host_dev_host_request_response **resp)
+{
+ uint64_t datasize;
+
+ switch (req->type) {
+ case PALACIOS_HOST_DEV_HOST_REQUEST_WRITE_IO: {
+ if (req->port==0xc0c0) {
+ uint64_t i;
+ uint64_t numchars;
+ numchars = req->data_len - sizeof(struct palacios_host_dev_host_request_response);
+ for (i=0;i<numchars;i++) {
+ putchar(req->data[i]);
+ }
+ *resp = malloc(sizeof(struct palacios_host_dev_host_request_response));
+ **resp=*req;
+ (*resp)->len = (*resp)->data_len = sizeof(struct palacios_host_dev_host_request_response);
+ (*resp)->op_len = numchars;
+ } else {
+ printf("Huh? Unknown port %d\n",req->port);
+ }
+ }
+ break;
+
+ default:
+ printf("Huh? Unknown request %d\n", req->type);
+ }
+
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int devfd;
+ int mode=0;
+ char *vm, *url;
+
+ if (argc!=4) {
+ usage();
+ exit(-1);
+ }
+
+ vm=argv[1];
+ url=argv[2];
+ mode = argv[3][0]=='s';
+
+ fprintf(stderr,"Attempting to rendezvous with host device %s on vm %s\n", url, vm);
+
+ if ((devfd = v3_user_host_dev_rendezvous(vm,url))<0) {
+ perror("failed to rendezvous");
+ exit(-1);
+ }
+
+ fprintf(stderr,"Rendezvous succeeded, I will now operate in %s mode\n", mode==0 ? "busywait" : "select");
+
+ if (mode==0) {
+ //busywait
+
+ struct palacios_host_dev_host_request_response *req;
+ struct palacios_host_dev_host_request_response *resp;
+ uint64_t datasize;
+
+ while (1) {
+ while (!(v3_user_host_dev_have_request(devfd))) {
+ }
+ v3_user_host_dev_pull_request(devfd, &req);
+
+ do_work(req, &resp);
+
+ v3_user_host_dev_push_response(devfd, resp);
+
+ free(resp);
+ free(req);
+ }
+ } else {
+
+ struct palacios_host_dev_host_request_response *req;
+ struct palacios_host_dev_host_request_response *resp;
+ uint64_t datasize;
+ fd_set readset;
+ int rc;
+
+ // select-based operation so that you can wait for multiple things
+
+ while (1) {
+ FD_ZERO(&readset);
+ FD_SET(devfd,&readset);
+
+ rc = select(devfd+1, &readset, 0, 0, 0); // pick whatever you want to select on, just include devfd
+
+ if (rc>0) {
+ if (FD_ISSET(devfd,&readset)) {
+ // a request is read for us!
+ v3_user_host_dev_pull_request(devfd, &req);
+
+ do_work(req, &resp);
+
+ v3_user_host_dev_push_response(devfd, resp);
+
+ free(resp);
+ free(req);
+ }
+ }
+ }
+ }
+
+ v3_user_host_dev_depart(devfd);
+
+ return 0;
+
+}
#include <sys/stat.h>
#include <fcntl.h>
#include <malloc.h>
+#include <string.h>
+#include <stdio.h>
#include "v3_user_host_dev.h"
{
int vmfd;
int devfd;
+ char buf[256];
+
+
+ strcpy(buf,url);
+ buf[255]=0;
if ((vmfd=open(vmdev,O_RDWR))<0) {
return -1;
}
- devfd = ioctl(vmfd,V3_VM_HOST_DEV_CONNECT,url);
+ devfd = ioctl(vmfd,V3_VM_HOST_DEV_CONNECT,buf);
close(vmfd);
{
uint64_t len;
- return ioctl(devfd,V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL,&len)==1;
+ int rc=ioctl(devfd,V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL,&len);
+
+ return rc==1;
}
int v3_user_host_dev_pull_request(int devfd, struct palacios_host_dev_host_request_response **req)