Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Device File Virtualization Proof of Concept (Kernel+Preload)
[palacios.git] / gears / services / devfile / devfile_preload.c
diff --git a/gears/services/devfile/devfile_preload.c b/gears/services/devfile/devfile_preload.c
new file mode 100644 (file)
index 0000000..fea7a6e
--- /dev/null
@@ -0,0 +1,165 @@
+/* 
+   Device File Virtualization Guest Preload Library
+
+   (c) Akhil Guliani and William Gross, 2015
+     
+   Adapted from MPI module (c) 2012 Peter Dinda
+
+*/
+
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <errno.h>
+
+
+
+#include "devfile_hc.h"
+#include "devfile_guest_fd_tracker.h"
+
+static int __LocalFD = 0;
+static int __last_open_index = -1;
+
+
+unsigned long long syscall();
+
+int touch_ptr(volatile char* ptr, int size)
+{
+    int i;
+    for(i=0;i<size;i+=4096){
+        ptr[i] = ptr[i];
+    }
+    return 0;
+}
+
+int open(const char *path, int flags, mode_t mode)
+{
+
+    DEBUG_PRINT("path %s %d %d\n", path, flags, mode);
+    __last_open_index = check_name(path,dtrack);
+
+    if (__last_open_index>=0) {
+        DEBUG_PRINT("In our file, \n");
+        __LocalFD = dtrack[__last_open_index].devFD; 
+        if(__LocalFD >= 0) {
+            return __LocalFD;
+        } else {
+            // Execute open hypercall here
+            char buf[8192];
+            char* my_path;
+            int path_length = strlen(path)+1; 
+            //check if path is across a page boundary
+            //if so try to copy into a local buffer, that doesn't cross a page boundary
+            //if its greater than 4k, fail 
+            if (path_length > 4096){
+                DEBUG_PRINT("Path greater than 4k, failing open\n");
+                return -1;
+            }
+            //forcing path to be in a single page
+            my_path = (char*)((((unsigned long long)buf+4096)/4096)*4096);
+            strcpy(my_path,path); // my_path is touched via this
+           long long sys_errno;
+            int rcFD =  dev_file_syscall_hcall(SYS64_OPEN,(long long)my_path,flags,0 ,0,0,0,&sys_errno);
+            DEBUG_PRINT(" ReturnFD : %d; \n",  rcFD);
+            __LocalFD = rcFD;
+           // set global errno so caller can see
+           errno=sys_errno;
+            return rcFD;
+        }
+    } else {
+        DEBUG_PRINT("performing original open\n");
+        
+        return syscall(SYS64_OPEN, path, flags, mode);
+    }
+}
+
+size_t read(int fd, void *buf, size_t count)
+{
+    //does buf+count extend pass page boundary?
+    //if so, only do up to page boundary
+    // if( (buf%4096)+count <= 4096)
+    //     normal
+
+    if (fd == __LocalFD || (check_fd(fd,dtrack)>=0)){
+        long long sys_errno;
+        //Need to handle only up to a page boundary, can't handle contiguous pages right now
+        count = MIN(count,4096-((unsigned long long)buf%4096));
+       touch_ptr(buf,count);
+        int ret =  dev_file_syscall_hcall(SYS64_READ,fd,(long long)buf,count,0,0,0,&sys_errno);
+       DEBUG_PRINT("Read of %lu bytes returned %d (errno %lld)\n",count,ret,sys_errno);
+       errno = sys_errno;
+        return ret;
+    } else {
+        DEBUG_PRINT("performing original read\n");
+        return syscall(SYS64_READ,fd, buf, count);
+    }
+}
+
+ssize_t write(int fd, const void *buf, size_t count)
+{
+    if (fd == __LocalFD || (check_fd(fd,dtrack)>=0)) {
+        long long sys_errno;
+        //Need to handle only up to a page boundary, can't handle contiguous pages right now
+        count = MIN(count,4096-((unsigned long long)buf%4096));
+       touch_ptr((char*)buf,count);
+        int ret =  dev_file_syscall_hcall(SYS64_WRITE,fd, (long long)buf,count,0,0,0,&sys_errno);
+       DEBUG_PRINT("Write of %lu bytes returned %d (errno %lld)\n",count,ret,sys_errno);
+       errno=sys_errno;
+        return ret;
+    } else {
+        DEBUG_PRINT("performing original write\n");
+        return syscall(SYS64_WRITE,fd, buf, count);
+    }
+}
+
+int close(int fd)
+{
+    int index = check_fd(fd,dtrack); 
+    if (fd == __LocalFD || (index>=0)) {
+       long long sys_errno;
+        int ret =  dev_file_syscall_hcall(SYS64_CLOSE,fd,0,0,0,0,0,&sys_errno);
+        if (ret >=0) {
+            dtrack[index].devFD = -1;
+            __LocalFD = -1;
+        }
+       DEBUG_PRINT("Close returned %d (errno %lld)\n",ret, sys_errno);
+       errno=sys_errno;
+        return ret;
+    } else {
+        DEBUG_PRINT("performing original close\n");
+        return syscall(SYS64_CLOSE,fd);
+    }
+}
+
+
+int ioctl(int fd, int request, void* data) {
+    //int sign_post;
+    int index = check_fd(fd,dtrack);
+    
+    // this is where a careful, device-specific decode is needed
+    // to figure out whether the argument or anything it points
+    // is a pointer.  
+    if (fd == __LocalFD || (index>=0)) {
+       long long sys_errno=0;
+       int ret;
+       // First cut for just the data pointer:
+       //   if (data > &sign_post){
+       //probably on stack
+       //    }
+       // if (data < brk()
+       ret = dev_file_syscall_hcall(SYS64_IOCTL,fd,request,(unsigned long long)data,0,0,0,&sys_errno);
+
+       DEBUG_PRINT("ioctl(%d) returned %d (errno %lld)\n",request,ret, sys_errno);
+       errno=sys_errno;
+       return ret;
+    }
+    else{
+        return syscall(SYS64_IOCTL,fd,request,data);
+    }
+    return -1;
+
+}
+