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.


fea7a6ef0c14e51ccf48b92d2107371499a2d52e
[palacios.git] / gears / services / devfile / devfile_preload.c
1 /* 
2    Device File Virtualization Guest Preload Library
3
4    (c) Akhil Guliani and William Gross, 2015
5      
6    Adapted from MPI module (c) 2012 Peter Dinda
7
8 */
9
10 #define _GNU_SOURCE
11
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <sys/types.h>
15 #include <errno.h>
16
17
18
19 #include "devfile_hc.h"
20 #include "devfile_guest_fd_tracker.h"
21
22 static int __LocalFD = 0;
23 static int __last_open_index = -1;
24
25
26 unsigned long long syscall();
27
28 int touch_ptr(volatile char* ptr, int size)
29 {
30     int i;
31     for(i=0;i<size;i+=4096){
32         ptr[i] = ptr[i];
33     }
34     return 0;
35 }
36
37 int open(const char *path, int flags, mode_t mode)
38 {
39
40     DEBUG_PRINT("path %s %d %d\n", path, flags, mode);
41  
42     __last_open_index = check_name(path,dtrack);
43
44     if (__last_open_index>=0) {
45         DEBUG_PRINT("In our file, \n");
46         __LocalFD = dtrack[__last_open_index].devFD; 
47         if(__LocalFD >= 0) {
48             return __LocalFD;
49         } else {
50             // Execute open hypercall here
51             char buf[8192];
52             char* my_path;
53             int path_length = strlen(path)+1; 
54             //check if path is across a page boundary
55             //if so try to copy into a local buffer, that doesn't cross a page boundary
56             //if its greater than 4k, fail 
57             if (path_length > 4096){
58                 DEBUG_PRINT("Path greater than 4k, failing open\n");
59                 return -1;
60             }
61             //forcing path to be in a single page
62             my_path = (char*)((((unsigned long long)buf+4096)/4096)*4096);
63             strcpy(my_path,path); // my_path is touched via this
64             long long sys_errno;
65             int rcFD =  dev_file_syscall_hcall(SYS64_OPEN,(long long)my_path,flags,0 ,0,0,0,&sys_errno);
66             DEBUG_PRINT(" ReturnFD : %d; \n",  rcFD);
67             __LocalFD = rcFD;
68             // set global errno so caller can see
69             errno=sys_errno;
70             return rcFD;
71         }
72     } else {
73         DEBUG_PRINT("performing original open\n");
74         
75         return syscall(SYS64_OPEN, path, flags, mode);
76     }
77 }
78
79 size_t read(int fd, void *buf, size_t count)
80 {
81     //does buf+count extend pass page boundary?
82     //if so, only do up to page boundary
83     // if( (buf%4096)+count <= 4096)
84     //     normal
85
86     if (fd == __LocalFD || (check_fd(fd,dtrack)>=0)){
87         long long sys_errno;
88         //Need to handle only up to a page boundary, can't handle contiguous pages right now
89         count = MIN(count,4096-((unsigned long long)buf%4096));
90         touch_ptr(buf,count);
91         int ret =  dev_file_syscall_hcall(SYS64_READ,fd,(long long)buf,count,0,0,0,&sys_errno);
92         DEBUG_PRINT("Read of %lu bytes returned %d (errno %lld)\n",count,ret,sys_errno);
93         errno = sys_errno;
94         return ret;
95     } else {
96         DEBUG_PRINT("performing original read\n");
97         return syscall(SYS64_READ,fd, buf, count);
98     }
99 }
100
101 ssize_t write(int fd, const void *buf, size_t count)
102 {
103     if (fd == __LocalFD || (check_fd(fd,dtrack)>=0)) {
104         long long sys_errno;
105         //Need to handle only up to a page boundary, can't handle contiguous pages right now
106         count = MIN(count,4096-((unsigned long long)buf%4096));
107         touch_ptr((char*)buf,count);
108         int ret =  dev_file_syscall_hcall(SYS64_WRITE,fd, (long long)buf,count,0,0,0,&sys_errno);
109         DEBUG_PRINT("Write of %lu bytes returned %d (errno %lld)\n",count,ret,sys_errno);
110         errno=sys_errno;
111         return ret;
112     } else {
113         DEBUG_PRINT("performing original write\n");
114         return syscall(SYS64_WRITE,fd, buf, count);
115     }
116 }
117
118 int close(int fd)
119 {
120     int index = check_fd(fd,dtrack); 
121     if (fd == __LocalFD || (index>=0)) {
122         long long sys_errno;
123         int ret =  dev_file_syscall_hcall(SYS64_CLOSE,fd,0,0,0,0,0,&sys_errno);
124         if (ret >=0) {
125             dtrack[index].devFD = -1;
126             __LocalFD = -1;
127         }
128         DEBUG_PRINT("Close returned %d (errno %lld)\n",ret, sys_errno);
129         errno=sys_errno;
130         return ret;
131     } else {
132         DEBUG_PRINT("performing original close\n");
133         return syscall(SYS64_CLOSE,fd);
134     }
135 }
136
137
138 int ioctl(int fd, int request, void* data) {
139     //int sign_post;
140     int index = check_fd(fd,dtrack);
141     
142     // this is where a careful, device-specific decode is needed
143     // to figure out whether the argument or anything it points
144     // is a pointer.  
145     if (fd == __LocalFD || (index>=0)) {
146         long long sys_errno=0;
147         int ret;
148         // First cut for just the data pointer:
149         //   if (data > &sign_post){
150         //probably on stack
151         //    }
152         // if (data < brk()
153         ret = dev_file_syscall_hcall(SYS64_IOCTL,fd,request,(unsigned long long)data,0,0,0,&sys_errno);
154
155         DEBUG_PRINT("ioctl(%d) returned %d (errno %lld)\n",request,ret, sys_errno);
156         errno=sys_errno;
157         return ret;
158     }
159     else{
160         return syscall(SYS64_IOCTL,fd,request,data);
161     }
162     return -1;
163
164 }
165