ee47d2aa2492772880fc7f4a9a39d554250205f1
[akaros.git] / user / parlib / src / sparc / newlib_backend.c
1 /* See COPYRIGHT for copyright information. */
2 /* Andrew Waterman <waterman@eecs.bekeley.edu> */
3
4 #include <arch/arch.h>
5 #include <arch/frontend.h>
6 #include <parlib.h>
7 #include <sys/stat.h>
8 #include <sys/unistd.h>
9 #include <sys/times.h>
10 #include <sys/time.h>
11 #include <debug.h>
12 #include <hart.h>
13 #include <utime.h>
14 #include <dirent.h>
15 #include <assert.h>
16 #include <stdlib.h>
17
18 // should kernel do V->P translation on these args?
19 #define IN0  1
20 #define IN1  2
21 #define IN2  4
22 #define OUT0 8
23 #define OUT1 16
24 #define OUT2 32
25
26 #define fe(n,x,y,z,trans) syscall(SYS_frontend,RAMP_SYSCALL_ ## n,(int)(x),(int)(y),(int)(z),trans)
27
28 #define getbuf(name,len) \
29         assert(len <= PGSIZE); \
30         char name##_blah[2*PGSIZE] __attribute__((aligned(8))); \
31         char* name = (char*)(((uint32_t)name##_blah+PGSIZE)/PGSIZE*PGSIZE)
32         
33 #define copy_if_off_page(ptr,len) \
34         assert(len <= PGSIZE); \
35         char buf##ptr[2*PGSIZE] __attribute__((aligned(8))); \
36         if((uint32_t)ptr % sizeof(uint32_t) != 0 || ((uint32_t)ptr)/PGSIZE != ((uint32_t)ptr+len)/PGSIZE) \
37         { \
38                 char* buf2##ptr = (char*)(((uint32_t)buf##ptr+PGSIZE)/PGSIZE*PGSIZE); \
39                 memcpy(buf2##ptr,ptr,len); \
40                 ptr = buf2##ptr; \
41         }
42
43 #define buf_if_off_page(ptr,len) \
44         assert(len <= PGSIZE); \
45         char buf##ptr [2*PGSIZE]; \
46         char* buf2##ptr = (char*)(((uint32_t)buf##ptr+PGSIZE)/PGSIZE*PGSIZE); \
47         void* old##ptr = ptr; \
48         if((uint32_t)ptr % sizeof(uint32_t) != 0 || ((uint32_t)ptr)/PGSIZE != ((uint32_t)ptr+len)/PGSIZE) \
49         { \
50                 ptr = (typeof(ptr))(buf2##ptr); \
51         }
52
53 #define copyout_if_off_page(ptr,len) \
54         if((uint32_t)(old##ptr) % sizeof(uint32_t) != 0 || ((uint32_t)(old##ptr))/PGSIZE != ((uint32_t)ptr+len)/PGSIZE) \
55         { \
56                 memcpy(old##ptr,buf2##ptr,len); \
57         }
58
59 /* Return the vcoreid, which is set in entry.S right before calling libmain.
60  * This should only be used in libmain() and main(), before any code that might
61  * use a register.  It just returns eax. */
62 uint32_t newcore(void)
63 {
64         return hart_self();
65 }
66
67 mode_t
68 umask (mode_t mask)
69 {
70         assert(0);
71 }
72
73 int
74 chmod (const char *name, mode_t mode)
75 {
76         int len = strlen(name)+1;
77         if(len > RAMP_MAXPATH)
78                 return -1;
79
80         assert(0);
81 }
82
83 int
84 access (const char *name, int mode)
85 {
86         int len = strlen(name)+1;
87         if(len > RAMP_MAXPATH)
88                 return -1;
89
90         assert(0);
91 }
92
93 char *
94 getwd (char *pwd)
95 {
96         buf_if_off_page(pwd,RAMP_MAXPATH);
97         int32_t ret = fe(getcwd,pwd,RAMP_MAXPATH,0,OUT0);
98         copyout_if_off_page(pwd,RAMP_MAXPATH);
99         return (char*)ret;
100 }
101
102 long int
103 pathconf (const char *pathname, int name)
104 {
105         int len = strlen(pathname)+1;
106         if(len > RAMP_MAXPATH)
107                 return -1;
108
109         assert(0);
110 }
111
112 int
113 utime (const char *name, const struct utimbuf *buf)
114 {
115         int len = strlen(name)+1;
116         if(len > RAMP_MAXPATH)
117                 return -1;
118
119         assert(0);
120 }
121
122 int
123 chown (const char *name, uid_t owner, gid_t group)
124 {
125         int len = strlen(name)+1;
126         if(len > RAMP_MAXPATH)
127                 return -1;
128
129         assert(0);
130 }
131
132 int
133 mkdir (const char *name, mode_t mode)
134 {
135         int len = strlen(name)+1;
136         if(len > RAMP_MAXPATH)
137                 return -1;
138
139         assert(0);
140 }
141
142
143 int
144 rmdir (const char *name)
145 {
146         int len = strlen(name)+1;
147         if(len > RAMP_MAXPATH)
148                 return -1;
149
150         assert(0);
151 }
152
153 long int 
154 sysconf (int name)
155 {
156         assert(0);
157 }
158
159 typedef struct
160 {
161         int fd;
162         struct dirent ent;
163 } __dir;
164
165 DIR *opendir (const char *name)
166 {
167         __dir* dir = (__dir*)malloc(sizeof(__dir));
168         if(dir == NULL)
169                 return NULL;
170
171         int len = strlen(name)+1;
172         if(len > RAMP_MAXPATH)
173                 return NULL;
174
175         copy_if_off_page(name,len);
176         dir->fd = fe(opendir,name,0,0,IN0);
177         if(dir->fd < 0)
178         {
179                 free(dir);
180                 return NULL;
181         }
182
183         return (DIR*)((char*)dir+1); // make dereferencing fail loudly
184 }
185
186 struct dirent *readdir (DIR *d)
187 {
188         __dir* dir = (__dir*)((char*)d-1);
189         struct dirent* dep = &dir->ent;
190
191         buf_if_off_page(dep,sizeof(struct dirent));
192         int ret = fe(readdir,dir->fd,dep,0,OUT1);
193         copyout_if_off_page(dep,sizeof(struct dirent));
194
195         return ret == 0 ? dep : 0;
196 }
197
198 void rewinddir (DIR *d)
199 {
200         __dir* dir = (__dir*)((char*)d-1);
201         fe(rewinddir,dir->fd,0,0,0);
202 }
203
204 int closedir (DIR *d)
205 {
206         __dir* dir = (__dir*)((char*)d-1);
207         int ret = fe(closedir,dir->fd,0,0,0);
208         if(ret == 0)
209                 free(dir);
210         return ret;
211 }
212
213 int pipe (int __fildes[2])
214 {
215         assert(0);
216 }
217
218 int dup2 (int __fildes, int __fildes2)
219 {
220         return fe(dup2,__fildes,__fildes2,0,0);
221 }
222
223 unsigned sleep (unsigned int __seconds)
224 {
225         assert(0);
226 }
227
228 unsigned alarm(unsigned __secs)
229 {
230         assert(0);
231 }
232
233 int execvp(const char *__file, char * const __argv[])
234 {
235         assert(0);
236 }
237
238 int execv(const char *path, char *const argv[])
239 {
240         assert(0);
241 }
242
243 int fcntl (int fd, int cmd, ...) 
244 {
245         assert(0);
246 }
247
248 int chdir(const char *name)
249 {
250         size_t len = strlen(name)+1;
251         if(len > RAMP_MAXPATH)
252                 return -1;
253
254         copy_if_off_page(name,len);
255         return fe(chdir,name,0,0,IN0);
256 }
257
258 int
259 getpid(void)
260 {
261         return procinfo.pid;
262 }
263
264 void
265 _exit(int code)
266 {
267         sys_proc_destroy(getpid());
268         while(1);
269 }
270
271 int
272 isatty(int fd)
273 {
274         struct stat s;
275         int ret = fstat(fd,&s);
276         return ret < 0 ? -1 : ((s.st_mode & S_IFCHR) ? 1 : 0);
277 }
278
279 int
280 fork(void)
281 {
282         assert(0);
283 }
284
285 int
286 execve(const char* name, char* const argv[], char* const env[])
287 {
288         assert(0);
289 }
290
291 int
292 kill(int pid, int sig)
293 {
294         assert(0);
295 }
296
297 int
298 wait(int* status)
299 {
300         assert(0);
301 }
302
303 int
304 link(const char *old, const char *new)
305 {
306         int oldlen = strlen(old)+1, newlen = strlen(new)+1;
307         if(oldlen > RAMP_MAXPATH || newlen > RAMP_MAXPATH)
308                 return -1;
309
310         copy_if_off_page(old,oldlen);
311         copy_if_off_page(new,oldlen);
312         return fe(link,old,new,0,IN0 | IN1);
313 }
314
315 int
316 unlink(const char* name)
317 {
318         int len = strlen(name)+1;
319         if(len > RAMP_MAXPATH)
320                 return -1;
321
322         copy_if_off_page(name,len);
323         return fe(unlink,name,0,0,IN0);
324 }
325
326 int
327 fstat(int fd, struct stat* st)
328 {
329         buf_if_off_page(st,sizeof(*st));
330         int ret = fe(fstat,fd,st,0,OUT1);
331         copyout_if_off_page(st,sizeof(*st));
332         return ret;
333 }
334
335 int
336 lstat(const char* name, struct stat* st)
337 {
338         int len = strlen(name)+1;
339         if(len > RAMP_MAXPATH)
340                 return -1;
341
342         copy_if_off_page(name,len);
343         buf_if_off_page(st,sizeof(*st));
344         int ret = fe(lstat,name,st,0,IN0 | OUT1);
345         copyout_if_off_page(st,sizeof(*st));
346         return ret;
347 }
348
349 int
350 stat(const char* name, struct stat* st)
351 {
352         int len = strlen(name)+1;
353         if(len > RAMP_MAXPATH)
354                 return -1;
355
356         copy_if_off_page(name,len);
357         buf_if_off_page(st,sizeof(*st));
358         int ret = fe(stat,name,st,0,IN0 | OUT1);
359         copyout_if_off_page(st,sizeof(*st));
360         return ret;
361 }
362
363 off_t
364 lseek(int fd, off_t ptr, int dir)
365 {
366         return fe(lseek,fd,ptr,dir,0);
367 }
368
369 ssize_t
370 write(int fd, const void* ptr, size_t len)
371 {
372         len = MIN(PGSIZE,len);
373         copy_if_off_page(ptr,len);
374         return fe(write,fd,ptr,len,IN1);
375 }
376
377 ssize_t
378 read(int fd, void* ptr, size_t len)
379 {
380         len = MIN(PGSIZE,len);
381         buf_if_off_page(ptr,len);
382         int ret = fe(read,fd,ptr,len,OUT1);
383         copyout_if_off_page(ptr,len);
384         return ret;
385 }
386
387 int
388 open(char* name, int flags, int mode)
389 {
390         size_t len = strlen(name)+1;
391         if(len > RAMP_MAXPATH)
392                 return -1;
393
394         copy_if_off_page(name,len);
395         return fe(open,name,flags,mode,IN0);
396 }
397
398 int
399 close(int fd)
400 {
401         return fe(close,fd,0,0,0);
402 }
403
404 clock_t
405 times(struct tms* buf)
406 {
407         extern struct timeval timeval_start;
408         if(timeval_start.tv_sec == 0)
409                 return (clock_t)-1;
410
411         struct timeval tp;
412         if(gettimeofday(&tp,NULL))
413                 return (clock_t)-1;
414
415         long long utime = (tp.tv_sec - timeval_start.tv_sec)*1000000;
416         utime += tp.tv_usec-timeval_start.tv_usec;
417         buf->tms_utime = buf->tms_cutime = utime*CLK_TCK/1000000;
418         buf->tms_stime = buf->tms_cstime = 0;
419
420         return (clock_t)buf->tms_utime;
421 }
422
423 int
424 gettimeofday(struct timeval* tp, void* tzp)
425 {
426         static struct timeval tp0 __attribute__((aligned(sizeof(*tp))));
427         if(tp0.tv_sec == 0)
428         {
429                 int ret = fe(gettimeofday,&tp0,0,0,OUT0);
430                 if(ret)
431                         return ret;
432         }
433
434         long long dt = read_tsc();
435         tp->tv_sec = tp0.tv_sec + dt/procinfo.tsc_freq;
436         tp->tv_usec = (dt % procinfo.tsc_freq)*1000000/procinfo.tsc_freq;
437
438         return 0;
439 }
440