/* 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 #include #include #include #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=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; }