From: Peter Dinda Date: Thu, 5 May 2011 18:14:38 +0000 (-0500) Subject: Ported user space support for host devices, user space host device example, and vnc... X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=5ac6ebe490fe6ebb948dd68736c693a3bb2f82dc Ported user space support for host devices, user space host device example, and vnc interface to graphics console from the monolithic version. Note: the addition of x0vncserver as a binary is by intent. Crufty to add as source right now --- diff --git a/linux_usr/Makefile b/linux_usr/Makefile index 2fc1ad8..c2a23aa 100644 --- a/linux_usr/Makefile +++ b/linux_usr/Makefile @@ -1,4 +1,5 @@ -all: v3_ctrl v3_stop v3_cons v3_mem v3_monitor v3_serial v3_net +all: v3_ctrl v3_stop v3_cons v3_mem v3_monitor v3_serial v3_net v3_user_host_dev_example + v3_ctrl : v3_ctrl.c v3_ctrl.h @@ -23,5 +24,8 @@ v3_monitor : v3_cons.c v3_ctrl.h v3_net : v3_net.c v3_ctrl.h gcc -static v3_net.c -o v3_net +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 + clean: rm -f v3_ctrl v3_cons v3_mem v3_monitor v3_serial v3_net diff --git a/linux_usr/v3_user_host_dev.c b/linux_usr/v3_user_host_dev.c new file mode 100644 index 0000000..8fe121a --- /dev/null +++ b/linux_usr/v3_user_host_dev.c @@ -0,0 +1,123 @@ +#include +#include +#include +#include + +#include "v3_user_host_dev.h" + + +int v3_user_host_dev_rendezvous(char *vmdev, char *url) +{ + int vmfd; + int devfd; + + if ((vmfd=open(vmdev,O_RDWR))<0) { + return -1; + } + + devfd = ioctl(vmfd,V3_VM_HOST_DEV_CONNECT,url); + + close(vmfd); + + return devfd; + +} +int v3_user_host_dev_depart(int devfd) +{ + return close(devfd); +} + + +int v3_user_host_dev_have_request(int devfd) +{ + uint64_t len; + + return ioctl(devfd,V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL,&len)==1; +} + +int v3_user_host_dev_pull_request(int devfd, struct palacios_host_dev_host_request_response **req) +{ + uint64_t len; + int rc; + + rc=ioctl(devfd,V3_HOST_DEV_HOST_REQUEST_SIZE_IOCTL,&len); + + if (rc<=0) { + return -1; + } else { + struct palacios_host_dev_host_request_response *r = malloc(len); + + rc=ioctl(devfd, V3_HOST_DEV_HOST_REQUEST_PULL_IOCTL,r); + + if (rc<=0) { + free(r); + return -1; + } else { + *req=r; + return 0; + } + } +} + + +int v3_user_host_dev_push_response(int devfd, struct palacios_host_dev_host_request_response *resp) +{ + int rc; + + rc=ioctl(devfd, V3_HOST_DEV_USER_RESPONSE_PUSH_IOCTL,resp); + + if (rc<=0) { + return -1; + } else { + return 0; + } +} + + + +static uint64_t do_user(int devfd, struct palacios_host_dev_user_op *op) +{ + return ioctl(devfd, V3_HOST_DEV_USER_REQUEST_PUSH_IOCTL,op); +} + +uint64_t v3_user_host_dev_read_guest_mem(int devfd, void *gpa, void *dest, uint64_t len) +{ + struct palacios_host_dev_user_op op; + + op.type= PALACIOS_HOST_DEV_USER_REQUEST_READ_GUEST; + op.gpa=gpa; + op.data=dest; + op.len=len; + op.irq=0; + + return do_user(devfd,&op); +} + +uint64_t v3_user_host_dev_write_guest_mem(int devfd, void *gpa, void *src, uint64_t len) +{ + struct palacios_host_dev_user_op op; + + op.type= PALACIOS_HOST_DEV_USER_REQUEST_WRITE_GUEST; + op.gpa=gpa; + op.data=src; + op.len=len; + op.irq=0; + + return do_user(devfd,&op); +} + +int v3_user_host_dev_inject_irq(int devfd, uint8_t irq) +{ + struct palacios_host_dev_user_op op; + + op.type= PALACIOS_HOST_DEV_USER_REQUEST_IRQ_GUEST; + op.gpa=0; + op.data=0; + op.len=0; + op.irq=irq; + + return do_user(devfd,&op); +} + + + diff --git a/linux_usr/v3_user_host_dev.h b/linux_usr/v3_user_host_dev.h new file mode 100644 index 0000000..523150f --- /dev/null +++ b/linux_usr/v3_user_host_dev.h @@ -0,0 +1,19 @@ +#ifndef _V3_USER_HOST_DEV_ +#define _V3_USER_HOST_DEV_ + +#include +#include "palacios-host-dev-user.h" + +int v3_user_host_dev_rendezvous(char *vmdev, char *url); // returns devfd for use in poll/select +int v3_user_host_dev_depart(int devfd); + +int v3_user_host_dev_have_request(int devfd); +int v3_user_host_dev_pull_request(int devfd, struct palacios_host_dev_host_request_response **req); +int v3_user_host_dev_push_response(int devfd, struct palacios_host_dev_host_request_response *resp); + +uint64_t v3_user_host_dev_read_guest_mem(int devfd, void *gpa, void *dest, uint64_t len); +uint64_t v3_user_host_dev_write_guest_mem(int devfd, void *gpa, void *src, uint64_t len); +int v3_user_host_dev_inject_guest_irq(int devfd, uint8_t irq); + +#endif + diff --git a/linux_usr/v3_user_host_dev_example.c b/linux_usr/v3_user_host_dev_example.c new file mode 100644 index 0000000..833f3c5 --- /dev/null +++ b/linux_usr/v3_user_host_dev_example.c @@ -0,0 +1,124 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "v3_user_host_dev.h" + +void usage() +{ + fprintf(stderr,"v3_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; + + // + // + // Process request here, perhaps calling these functions: + // + // uint64_t v3_user_host_dev_read_guest_mem(int devfd, void *gpa, void *dest, uint64_t len); + // uint64_t v3_user_host_dev_write_guest_mem(int devfd, void *gpa, void *src, uint64_t len); + // int v3_user_host_dev_inject_guest_irq(int devfd, uint8_t irq); + // + // determine datasize - # bytes to include in response + // + // now built a response + *resp = malloc(sizeof(struct palacios_host_dev_host_request_response) + datasize); + (*resp)->data_len = sizeof(struct palacios_host_dev_host_request_response) + datasize; + + // + // Fill out the fields of the response - notice that there are six kinds of things to response to: + // - read/write device port + // - read/write device mem + // - read/write device configuration space + + 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; + +} diff --git a/linux_usr/x0vncserver b/linux_usr/x0vncserver new file mode 100755 index 0000000..d173fe8 Binary files /dev/null and b/linux_usr/x0vncserver differ