All local system calls are asynchronous (XCC)
[akaros.git] / kern / src / syscall.c
1 /* See COPYRIGHT for copyright information. */
2
3 #ifdef __SHARC__
4 #pragma nosharc
5 #endif
6
7 #include <ros/common.h>
8 #include <ros/notification.h>
9 #include <arch/types.h>
10 #include <arch/arch.h>
11 #include <arch/mmu.h>
12 #include <arch/console.h>
13 #include <ros/timer.h>
14 #include <error.h>
15
16 #include <elf.h>
17 #include <string.h>
18 #include <assert.h>
19 #include <process.h>
20 #include <schedule.h>
21 #include <pmap.h>
22 #include <umem.h>
23 #include <mm.h>
24 #include <trap.h>
25 #include <syscall.h>
26 #include <kmalloc.h>
27 #include <stdio.h>
28 #include <resource.h>
29 #include <frontend.h>
30 #include <colored_caches.h>
31 #include <hashtable.h>
32 #include <arch/bitmask.h>
33 #include <vfs.h>
34 #include <devfs.h>
35 #include <smp.h>
36 #include <arsc_server.h>
37
38
39 #ifdef __CONFIG_NETWORKING__
40 #include <arch/nic_common.h>
41 extern int (*send_frame)(const char *CT(len) data, size_t len);
42 extern unsigned char device_mac[6];
43 #endif
44
45 /* Tracing Globals */
46 int systrace_flags = 0;
47 struct systrace_record *systrace_buffer = 0;
48 unsigned int systrace_bufidx = 0;
49 size_t systrace_bufsize = 0;
50 struct proc *systrace_procs[MAX_NUM_TRACED] = {0};
51 spinlock_t systrace_lock = SPINLOCK_INITIALIZER;
52
53 /* Not enforcing the packing of systrace_procs yet, but don't rely on that */
54 static bool proc_is_traced(struct proc *p)
55 {
56         for (int i = 0; i < MAX_NUM_TRACED; i++)
57                 if (systrace_procs[i] == p)
58                         return true;
59         return false;
60 }
61
62 /* Helper that "finishes" the current async syscall.  This should be used when
63  * we are calling a function in a syscall that might not return and won't be
64  * able to use the normal syscall return path, such as proc_yield() and
65  * resource_req().  Call this from within syscall.c (I don't want it global).
66  *
67  * It is possible for another user thread to see the syscall being done early -
68  * they just need to be careful with the weird proc management calls (as in,
69  * don't trust an async fork).
70  *
71  * *sysc is in user memory, and should be pinned (TODO: UMEM).  There may be
72  * issues with unpinning this if we never return.
73  *
74  * Note, this is currently tied to how cores execute syscall batches: pcpui
75  * telling them what to do *next*, which should be advanced one past the call we
76  * are currently working on.  If this sucks too much in the future, we can have
77  * two separate struct syscall *s. */
78 static void signal_current_sc(int retval)
79 {
80         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
81         struct syscall *sysc = pcpui->syscalls - 1;     /* it was already advanced */
82         sysc->retval = retval;
83         sysc->flags |= SC_DONE;
84 }
85
86 /* Callable by any function while executing a syscall (or otherwise, actually).
87  * Prep this by setting the errno_loc in advance. */
88 void set_errno(int errno)
89 {
90         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
91         if (pcpui->errno_loc)
92                 *(pcpui->errno_loc) = errno;
93 }
94
95 /************** Utility Syscalls **************/
96
97 static int sys_null(void)
98 {
99         return 0;
100 }
101
102 // Writes 'val' to 'num_writes' entries of the well-known array in the kernel
103 // address space.  It's just #defined to be some random 4MB chunk (which ought
104 // to be boot_alloced or something).  Meant to grab exclusive access to cache
105 // lines, to simulate doing something useful.
106 static int sys_cache_buster(struct proc *p, uint32_t num_writes,
107                              uint32_t num_pages, uint32_t flags)
108 { TRUSTEDBLOCK /* zra: this is not really part of the kernel */
109         #define BUSTER_ADDR             0xd0000000  // around 512 MB deep
110         #define MAX_WRITES              1048576*8
111         #define MAX_PAGES               32
112         #define INSERT_ADDR     (UINFO + 2*PGSIZE) // should be free for these tests
113         uint32_t* buster = (uint32_t*)BUSTER_ADDR;
114         static spinlock_t buster_lock = SPINLOCK_INITIALIZER;
115         uint64_t ticks = -1;
116         page_t* a_page[MAX_PAGES];
117
118         /* Strided Accesses or Not (adjust to step by cachelines) */
119         uint32_t stride = 1;
120         if (flags & BUSTER_STRIDED) {
121                 stride = 16;
122                 num_writes *= 16;
123         }
124
125         /* Shared Accesses or Not (adjust to use per-core regions)
126          * Careful, since this gives 8MB to each core, starting around 512MB.
127          * Also, doesn't separate memory for core 0 if it's an async call.
128          */
129         if (!(flags & BUSTER_SHARED))
130                 buster = (uint32_t*)(BUSTER_ADDR + core_id() * 0x00800000);
131
132         /* Start the timer, if we're asked to print this info*/
133         if (flags & BUSTER_PRINT_TICKS)
134                 ticks = start_timing();
135
136         /* Allocate num_pages (up to MAX_PAGES), to simulate doing some more
137          * realistic work.  Note we don't write to these pages, even if we pick
138          * unshared.  Mostly due to the inconvenience of having to match up the
139          * number of pages with the number of writes.  And it's unnecessary.
140          */
141         if (num_pages) {
142                 spin_lock(&buster_lock);
143                 for (int i = 0; i < MIN(num_pages, MAX_PAGES); i++) {
144                         upage_alloc(p, &a_page[i],1);
145                         page_insert(p->env_pgdir, a_page[i], (void*)INSERT_ADDR + PGSIZE*i,
146                                     PTE_USER_RW);
147                         page_decref(a_page[i]);
148                 }
149                 spin_unlock(&buster_lock);
150         }
151
152         if (flags & BUSTER_LOCKED)
153                 spin_lock(&buster_lock);
154         for (int i = 0; i < MIN(num_writes, MAX_WRITES); i=i+stride)
155                 buster[i] = 0xdeadbeef;
156         if (flags & BUSTER_LOCKED)
157                 spin_unlock(&buster_lock);
158
159         if (num_pages) {
160                 spin_lock(&buster_lock);
161                 for (int i = 0; i < MIN(num_pages, MAX_PAGES); i++) {
162                         page_remove(p->env_pgdir, (void*)(INSERT_ADDR + PGSIZE * i));
163                         page_decref(a_page[i]);
164                 }
165                 spin_unlock(&buster_lock);
166         }
167
168         /* Print info */
169         if (flags & BUSTER_PRINT_TICKS) {
170                 ticks = stop_timing(ticks);
171                 printk("%llu,", ticks);
172         }
173         return 0;
174 }
175
176 static int sys_cache_invalidate(void)
177 {
178         #ifdef __i386__
179                 wbinvd();
180         #endif
181         return 0;
182 }
183
184 /* sys_reboot(): called directly from dispatch table. */
185
186 /* Print a string to the system console. */
187 static ssize_t sys_cputs(struct proc *p, const char *DANGEROUS string,
188                          size_t strlen)
189 {
190         char *t_string;
191         t_string = user_strdup_errno(p, string, strlen);
192         if (!t_string)
193                 return -1;
194         printk("%.*s", strlen, t_string);
195         user_memdup_free(p, t_string);
196         return (ssize_t)strlen;
197 }
198
199 // Read a character from the system console.
200 // Returns the character.
201 static uint16_t sys_cgetc(struct proc *p)
202 {
203         uint16_t c;
204
205         // The cons_getc() primitive doesn't wait for a character,
206         // but the sys_cgetc() system call does.
207         while ((c = cons_getc()) == 0)
208                 cpu_relax();
209
210         return c;
211 }
212
213 /* Returns the id of the cpu this syscall is executed on. */
214 static uint32_t sys_getcpuid(void)
215 {
216         return core_id();
217 }
218
219 // TODO: Temporary hack until thread-local storage is implemented on i386 and
220 // this is removed from the user interface
221 static size_t sys_getvcoreid(struct proc *p)
222 {
223         return proc_get_vcoreid(p, core_id());
224 }
225
226 /************** Process management syscalls **************/
227
228 /* Returns the calling process's pid */
229 static pid_t sys_getpid(struct proc *p)
230 {
231         return p->pid;
232 }
233
234 /* Creates a process from the file 'path'.  The process is not runnable by
235  * default, so it needs it's status to be changed so that the next call to
236  * schedule() will try to run it.  TODO: take args/envs from userspace. */
237 static int sys_proc_create(struct proc *p, char *path, size_t path_l,
238                            struct procinfo *pi)
239 {
240         int pid = 0;
241         char *t_path;
242         struct file *program;
243         struct proc *new_p;
244
245         /* Copy in the path.  Consider putting an upper bound on path_l. */
246         t_path = user_strdup_errno(p, path, path_l);
247         if (!t_path)
248                 return -1;
249         program = do_file_open(t_path, 0, 0);
250         user_memdup_free(p, t_path);
251         if (!program)
252                 return -1;                      /* presumably, errno is already set */
253         /* TODO: need to split the proc creation, since you must load after setting
254          * args/env, since auxp gets set up there. */
255         //new_p = proc_create(program, 0, 0);
256         if (proc_alloc(&new_p, current))
257                 goto mid_error;
258         /* Set the argument stuff needed by glibc */
259         if (memcpy_from_user_errno(p, new_p->procinfo->argp, pi->argp,
260                                    sizeof(pi->argp)))
261                 goto late_error;
262         if (memcpy_from_user_errno(p, new_p->procinfo->argbuf, pi->argbuf,
263                                    sizeof(pi->argbuf)))
264                 goto late_error;
265         if (load_elf(new_p, program))
266                 goto late_error;
267         kref_put(&program->f_kref);
268         /* Connect to stdin, stdout, stderr (part of proc_create()) */
269         assert(insert_file(&new_p->open_files, dev_stdin,  0) == 0);
270         assert(insert_file(&new_p->open_files, dev_stdout, 0) == 1);
271         assert(insert_file(&new_p->open_files, dev_stderr, 0) == 2);
272         __proc_ready(new_p);
273         pid = new_p->pid;
274         kref_put(&new_p->kref); /* give up the reference created in proc_create() */
275         return pid;
276 late_error:
277         proc_destroy(new_p);
278 mid_error:
279         kref_put(&program->f_kref);
280         return -1;
281 }
282
283 /* Makes process PID runnable.  Consider moving the functionality to process.c */
284 static error_t sys_proc_run(struct proc *p, unsigned pid)
285 {
286         struct proc *target = pid2proc(pid);
287         error_t retval = 0;
288
289         if (!target)
290                 return -EBADPROC;
291         // note we can get interrupted here. it's not bad.
292         spin_lock(&p->proc_lock);
293         // make sure we have access and it's in the right state to be activated
294         if (!proc_controls(p, target)) {
295                 kref_put(&target->kref);
296                 retval = -EPERM;
297         } else if (target->state != PROC_CREATED) {
298                 kref_put(&target->kref);
299                 retval = -EINVAL;
300         } else {
301                 __proc_set_state(target, PROC_RUNNABLE_S);
302                 schedule_proc(target);
303         }
304         spin_unlock(&p->proc_lock);
305         kref_put(&target->kref);
306         return retval;
307 }
308
309 /* Destroy proc pid.  If this is called by the dying process, it will never
310  * return.  o/w it will return 0 on success, or an error.  Errors include:
311  * - EBADPROC: if there is no such process with pid
312  * - EPERM: if caller does not control pid */
313 static error_t sys_proc_destroy(struct proc *p, pid_t pid, int exitcode)
314 {
315         error_t r;
316         struct proc *p_to_die = pid2proc(pid);
317
318         if (!p_to_die) {
319                 set_errno(ESRCH);
320                 return -1;
321         }
322         if (!proc_controls(p, p_to_die)) {
323                 kref_put(&p_to_die->kref);
324                 set_errno(EPERM);
325                 return -1;
326         }
327         if (p_to_die == p) {
328                 // syscall code and pid2proc both have edible references, only need 1.
329                 p->exitcode = exitcode;
330                 kref_put(&p_to_die->kref);
331                 printd("[PID %d] proc exiting gracefully (code %d)\n", p->pid,exitcode);
332         } else {
333                 printd("[%d] destroying proc %d\n", p->pid, p_to_die->pid);
334         }
335         proc_destroy(p_to_die);
336         kref_put(&p_to_die->kref);
337         return ESUCCESS;
338 }
339
340 static int sys_proc_yield(struct proc *p, bool being_nice)
341 {
342         /* proc_yield() doesn't return - we need to set the syscall retval early */
343         signal_current_sc(0);
344         proc_yield(p, being_nice);
345         assert(0);
346 }
347
348 static ssize_t sys_fork(env_t* e)
349 {
350         // TODO: right now we only support fork for single-core processes
351         if (e->state != PROC_RUNNING_S) {
352                 set_errno(EINVAL);
353                 return -1;
354         }
355         /* Can't really fork if we don't have a current_tf to fork */
356         if (!current_tf) {
357                 set_errno(EINVAL);
358                 return -1;
359         }
360         env_t* env;
361         assert(!proc_alloc(&env, current));
362         assert(env != NULL);
363
364         env->heap_top = e->heap_top;
365         env->ppid = e->pid;
366         env->env_tf = *current_tf;
367
368         /* We need to speculatively say the syscall worked before copying the memory
369          * out, since the 'forked' process's call never actually goes through the
370          * syscall return path, and will never think it is done.  This violates a
371          * few things.  Just be careful with fork. */
372         signal_current_sc(0);
373
374         env->cache_colors_map = cache_colors_map_alloc();
375         for(int i=0; i < llc_cache->num_colors; i++)
376                 if(GET_BITMASK_BIT(e->cache_colors_map,i))
377                         cache_color_alloc(llc_cache, env->cache_colors_map);
378
379         duplicate_vmrs(e, env);
380
381         int copy_page(env_t* e, pte_t* pte, void* va, void* arg)
382         {
383                 env_t* env = (env_t*)arg;
384
385                 if(PAGE_PRESENT(*pte))
386                 {
387                         page_t* pp;
388                         if(upage_alloc(env,&pp,0))
389                                 return -1;
390                         if(page_insert(env->env_pgdir,pp,va,*pte & PTE_PERM))
391                         {
392                                 page_decref(pp);
393                                 return -1;
394                         }
395                         pagecopy(page2kva(pp),ppn2kva(PTE2PPN(*pte)));
396                         page_decref(pp);
397                 } else {
398                         assert(PAGE_PAGED_OUT(*pte));
399                         /* TODO: (SWAP) will need to either make a copy or CoW/refcnt the
400                          * backend store.  For now, this PTE will be the same as the
401                          * original PTE */
402                         panic("Swapping not supported!");
403                         pte_t* newpte = pgdir_walk(env->env_pgdir,va,1);
404                         if(!newpte)
405                                 return -1;
406                         *newpte = *pte;
407                 }
408                 return 0;
409         }
410
411         // TODO: (PC) this won't work.  Needs revisiting.
412         // copy procdata and procinfo
413         memcpy(env->procdata,e->procdata,sizeof(struct procdata));
414         memcpy(env->procinfo,e->procinfo,sizeof(struct procinfo));
415         env->procinfo->pid = env->pid;
416         env->procinfo->ppid = env->ppid;
417
418         /* for now, just copy the contents of every present page in the entire
419          * address space. */
420         if (env_user_mem_walk(e, 0, UMAPTOP, &copy_page, env)) {
421                 proc_destroy(env);      /* this is prob what you want, not decref by 2 */
422                 set_errno(ENOMEM);
423                 return -1;
424         }
425         clone_files(&e->open_files, &env->open_files);
426         __proc_ready(env);
427         __proc_set_state(env, PROC_RUNNABLE_S);
428         schedule_proc(env);
429
430         // don't decref the new process.
431         // that will happen when the parent waits for it.
432         // TODO: if the parent doesn't wait, we need to change the child's parent
433         // when the parent dies, or at least decref it
434
435         printd("[PID %d] fork PID %d\n",e->pid,env->pid);
436         return env->pid;
437 }
438
439 /* Load the binary "path" into the current process, and start executing it.
440  * argv and envp are magically bundled in procinfo for now.  Keep in sync with
441  * glibc's sysdeps/ros/execve.c */
442 static int sys_exec(struct proc *p, char *path, size_t path_l,
443                     struct procinfo *pi)
444 {
445         int ret = -1;
446         char *t_path;
447         struct file *program;
448         struct trapframe *old_cur_tf = current_tf;
449         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
450
451         /* We probably want it to never be allowed to exec if it ever was _M */
452         if (p->state != PROC_RUNNING_S) {
453                 set_errno(EINVAL);
454                 return -1;
455         }
456         /* Can't exec if we don't have a current_tf to restart (if we fail). */
457         if (!old_cur_tf) {
458                 set_errno(EINVAL);
459                 return -1;
460         }
461         /* Copy in the path.  Consider putting an upper bound on path_l. */
462         t_path = user_strdup_errno(p, path, path_l);
463         if (!t_path)
464                 return -1;
465         /* Clear the current_tf.  We won't be returning the 'normal' way.  Even if
466          * we want to return with an error, we need to go back differently in case
467          * we succeed.  This needs to be done before we could possibly block, but
468          * unfortunately happens before the point of no return. */
469         current_tf = 0;
470         /* This could block: */
471         program = do_file_open(t_path, 0, 0);
472         user_memdup_free(p, t_path);
473         if (!program)
474                 goto early_error;
475         /* Set the argument stuff needed by glibc */
476         if (memcpy_from_user_errno(p, p->procinfo->argp, pi->argp,
477                                    sizeof(pi->argp)))
478                 goto mid_error;
479         if (memcpy_from_user_errno(p, p->procinfo->argbuf, pi->argbuf,
480                                    sizeof(pi->argbuf)))
481                 goto mid_error;
482         /* This is the point of no return for the process. */
483         /* TODO: issues with this: Need to also assert there are no outstanding
484          * users of the sysrings.  the ldt page will get freed shortly, so that's
485          * okay.  Potentially issues with the nm and vcpd if we were in _M before
486          * and someone is trying to notify. */
487         memset(p->procdata, 0, sizeof(procdata_t));
488         destroy_vmrs(p);
489         close_all_files(&p->open_files, TRUE);
490         env_user_mem_free(p, 0, UMAPTOP);
491         if (load_elf(p, program)) {
492                 kref_put(&program->f_kref);
493                 proc_destroy(p);
494                 /* We don't want to do anything else - we just need to not accidentally
495                  * return to the user (hence the all_out) */
496                 goto all_out;
497         }
498         printd("[PID %d] exec %s\n", p->pid, file_name(program));
499         kref_put(&program->f_kref);
500         goto success;
501         /* These error and out paths are so we can handle the async interface, both
502          * for when we want to error/return to the proc, as well as when we succeed
503          * and want to start the newly exec'd _S */
504 mid_error:
505         /* These two error paths are for when we want to restart the process with an
506          * error value (errno is already set). */
507         kref_put(&program->f_kref);
508 early_error:
509         p->env_tf = *old_cur_tf;
510         signal_current_sc(-1);
511 success:
512         /* Here's how we'll restart the new (or old) process: */
513         spin_lock(&p->proc_lock);
514         __proc_set_state(p, PROC_RUNNABLE_S);
515         schedule_proc(p);
516         spin_unlock(&p->proc_lock);
517 all_out:
518         /* When we idle, we don't want to try executing other syscalls.  If exec
519          * succeeded (or the proc was destroyed) it'd just be wrong. */
520         pcpui->syscalls = 0;
521         pcpui->nr_calls = 0;
522         /* we can't return, since we'd write retvals to the old location of the
523          * sycall struct (which has been freed and is in the old userspace) (or has
524          * already been written to).*/
525         /* TODO: remove this when we remove the one in local_syscall() */
526         kref_put(&current->kref);
527         smp_idle();
528         assert(0);
529 }
530
531 static ssize_t sys_trywait(env_t* e, pid_t pid, int* status)
532 {
533         struct proc* p = pid2proc(pid);
534
535         // TODO: this syscall is racy, so we only support for single-core procs
536         if(e->state != PROC_RUNNING_S)
537                 return -1;
538
539         // TODO: need to use errno properly.  sadly, ROS error codes conflict..
540
541         if(p)
542         {
543                 ssize_t ret;
544
545                 if(current->pid == p->ppid)
546                 {
547                         if(p->state == PROC_DYING)
548                         {
549                                 memcpy_to_user(e,status,&p->exitcode,sizeof(int));
550                                 printd("[PID %d] waited for PID %d (code %d)\n",
551                                        e->pid,p->pid,p->exitcode);
552                                 ret = 0;
553                         }
554                         else // not dead yet
555                         {
556                                 set_errno(ESUCCESS);
557                                 ret = -1;
558                         }
559                 }
560                 else // not a child of the calling process
561                 {
562                         set_errno(EPERM);
563                         ret = -1;
564                 }
565
566                 // if the wait succeeded, decref twice
567                 if (ret == 0)
568                         kref_put(&p->kref);
569                 kref_put(&p->kref);
570                 return ret;
571         }
572
573         set_errno(EPERM);
574         return -1;
575 }
576
577 /************** Memory Management Syscalls **************/
578
579 static void *sys_mmap(struct proc *p, uintreg_t a1, uintreg_t a2, uintreg_t a3,
580                       uintreg_t *a456)
581 {
582         uintreg_t _a456[3];
583         if (memcpy_from_user(p, _a456, a456, 3 * sizeof(uintreg_t)))
584                 sys_proc_destroy(p, p->pid, -1);
585         return mmap(p, a1, a2, a3, _a456[0], _a456[1], _a456[2]);
586 }
587
588 static intreg_t sys_mprotect(struct proc *p, void *addr, size_t len, int prot)
589 {
590         return mprotect(p, (uintptr_t)addr, len, prot);
591 }
592
593 static intreg_t sys_munmap(struct proc *p, void *addr, size_t len)
594 {
595         return munmap(p, (uintptr_t)addr, len);
596 }
597
598 static ssize_t sys_shared_page_alloc(env_t* p1,
599                                      void**DANGEROUS _addr, pid_t p2_id,
600                                      int p1_flags, int p2_flags
601                                     )
602 {
603         printk("[kernel] shared page alloc is deprecated/unimplemented.\n");
604         return -1;
605 }
606
607 static int sys_shared_page_free(env_t* p1, void*DANGEROUS addr, pid_t p2)
608 {
609         return -1;
610 }
611
612
613 static int sys_resource_req(struct proc *p, int type, unsigned int amt_wanted,
614                             unsigned int amt_wanted_min, int flags)
615 {
616         signal_current_sc(0);
617         /* this might not return (if it's a _S -> _M transition) */
618         return resource_req(p, type, amt_wanted, amt_wanted_min, flags);
619 }
620
621 /* Will notify the target on the given vcore, if the caller controls the target.
622  * Will honor the target's wanted/vcoreid.  u_ne can be NULL. */
623 static int sys_notify(struct proc *p, int target_pid, unsigned int notif,
624                       struct notif_event *u_ne)
625 {
626         struct notif_event local_ne;
627         struct proc *target = pid2proc(target_pid);
628
629         if (!target) {
630                 set_errno(EBADPROC);
631                 return -1;
632         }
633         if (!proc_controls(p, target)) {
634                 kref_put(&target->kref);
635                 set_errno(EPERM);
636                 return -1;
637         }
638         /* if the user provided a notif_event, copy it in and use that */
639         if (u_ne) {
640                 if (memcpy_from_user(p, &local_ne, u_ne, sizeof(struct notif_event))) {
641                         kref_put(&target->kref);
642                         set_errno(EINVAL);
643                         return -1;
644                 }
645                 proc_notify(target, local_ne.ne_type, &local_ne);
646         } else {
647                 proc_notify(target, notif, 0);
648         }
649         kref_put(&target->kref);
650         return 0;
651 }
652
653 /* Will notify the calling process on the given vcore, independently of WANTED
654  * or advertised vcoreid.  If you change the parameters, change pop_ros_tf() */
655 static int sys_self_notify(struct proc *p, uint32_t vcoreid, unsigned int notif,
656                            struct notif_event *u_ne)
657 {
658         struct notif_event local_ne;
659
660         printd("[kernel] received self notify for vcoreid %d, notif %d, ne %08p\n",
661                vcoreid, notif, u_ne);
662         /* if the user provided a notif_event, copy it in and use that */
663         if (u_ne) {
664                 if (memcpy_from_user(p, &local_ne, u_ne, sizeof(struct notif_event))) {
665                         set_errno(EINVAL);
666                         return -1;
667                 }
668                 do_notify(p, vcoreid, local_ne.ne_type, &local_ne);
669         } else {
670                 do_notify(p, vcoreid, notif, 0);
671         }
672         return 0;
673 }
674
675 /* This will set a local timer for usec, then shut down the core */
676 static int sys_halt_core(struct proc *p, unsigned int usec)
677 {
678         /* TODO: ought to check and see if a timer was already active, etc, esp so
679          * userspace can't turn off timers.  also note we will also call whatever
680          * timer_interrupt() will do, though all we care about is just
681          * self_ipi/interrupting. */
682         set_core_timer(usec);
683         cpu_halt();
684         set_core_timer(0);              /* Disable the timer (we don't have a 0-shot yet) */
685
686         return 0;
687 }
688
689 /************** Platform Specific Syscalls **************/
690
691 //Read a buffer over the serial port
692 static ssize_t sys_serial_read(env_t* e, char *DANGEROUS _buf, size_t len)
693 {
694         printk("[kernel] serial reading is deprecated.\n");
695         if (len == 0)
696                 return 0;
697
698         #ifdef __CONFIG_SERIAL_IO__
699             char *COUNT(len) buf = user_mem_assert(e, _buf, len, PTE_USER_RO);
700                 size_t bytes_read = 0;
701                 int c;
702                 while((c = serial_read_byte()) != -1) {
703                         buf[bytes_read++] = (uint8_t)c;
704                         if(bytes_read == len) break;
705                 }
706                 return (ssize_t)bytes_read;
707         #else
708                 return -EINVAL;
709         #endif
710 }
711
712 //Write a buffer over the serial port
713 static ssize_t sys_serial_write(env_t* e, const char *DANGEROUS buf, size_t len)
714 {
715         printk("[kernel] serial writing is deprecated.\n");
716         if (len == 0)
717                 return 0;
718         #ifdef __CONFIG_SERIAL_IO__
719                 char *COUNT(len) _buf = user_mem_assert(e, buf, len, PTE_USER_RO);
720                 for(int i =0; i<len; i++)
721                         serial_send_byte(buf[i]);
722                 return (ssize_t)len;
723         #else
724                 return -EINVAL;
725         #endif
726 }
727
728 #ifdef __CONFIG_NETWORKING__
729 // This is not a syscall we want. Its hacky. Here just for syscall stuff until get a stack.
730 static ssize_t sys_eth_read(env_t* e, char *DANGEROUS buf)
731 {
732         if (eth_up) {
733
734                 uint32_t len;
735                 char *ptr;
736
737                 spin_lock(&packet_buffers_lock);
738
739                 if (num_packet_buffers == 0) {
740                         spin_unlock(&packet_buffers_lock);
741                         return 0;
742                 }
743
744                 ptr = packet_buffers[packet_buffers_head];
745                 len = packet_buffers_sizes[packet_buffers_head];
746
747                 num_packet_buffers--;
748                 packet_buffers_head = (packet_buffers_head + 1) % MAX_PACKET_BUFFERS;
749
750                 spin_unlock(&packet_buffers_lock);
751
752                 char* _buf = user_mem_assert(e, buf, len, PTE_U);
753
754                 memcpy(_buf, ptr, len);
755
756                 kfree(ptr);
757
758                 return len;
759         }
760         else
761                 return -EINVAL;
762 }
763
764 // This is not a syscall we want. Its hacky. Here just for syscall stuff until get a stack.
765 static ssize_t sys_eth_write(env_t* e, const char *DANGEROUS buf, size_t len)
766 {
767         if (eth_up) {
768
769                 if (len == 0)
770                         return 0;
771
772                 // HACK TO BYPASS HACK
773                 int just_sent = send_frame(buf, len);
774
775                 if (just_sent < 0) {
776                         printk("Packet send fail\n");
777                         return 0;
778                 }
779
780                 return just_sent;
781
782                 // END OF RECURSIVE HACK
783 /*
784                 char *COUNT(len) _buf = user_mem_assert(e, buf, len, PTE_U);
785                 int total_sent = 0;
786                 int just_sent = 0;
787                 int cur_packet_len = 0;
788                 while (total_sent != len) {
789                         cur_packet_len = ((len - total_sent) > MTU) ? MTU : (len - total_sent);
790                         char dest_mac[6] = APPSERVER_MAC_ADDRESS;
791                         char* wrap_buffer = eth_wrap(_buf + total_sent, cur_packet_len, device_mac, dest_mac, APPSERVER_PORT);
792                         just_sent = send_frame(wrap_buffer, cur_packet_len + sizeof(struct ETH_Header));
793
794                         if (just_sent < 0)
795                                 return 0; // This should be an error code of its own
796
797                         if (wrap_buffer)
798                                 kfree(wrap_buffer);
799
800                         total_sent += cur_packet_len;
801                 }
802
803                 return (ssize_t)len;
804 */
805         }
806         else
807                 return -EINVAL;
808 }
809
810 static ssize_t sys_eth_get_mac_addr(env_t* e, char *DANGEROUS buf) 
811 {
812         if (eth_up) {
813                 for (int i = 0; i < 6; i++)
814                         buf[i] = device_mac[i];
815                 return 0;
816         }
817         else
818                 return -EINVAL;
819 }
820
821 static int sys_eth_recv_check(env_t* e) 
822 {
823         if (num_packet_buffers != 0) 
824                 return 1;
825         else
826                 return 0;
827 }
828
829 #endif // Network
830
831 static intreg_t sys_read(struct proc *p, int fd, void *buf, int len)
832 {
833         ssize_t ret;
834         struct file *file = get_file_from_fd(&p->open_files, fd);
835         if (!file) {
836                 set_errno(EBADF);
837                 return -1;
838         }
839         if (!file->f_op->read) {
840                 kref_put(&file->f_kref);
841                 set_errno(EINVAL);
842                 return -1;
843         }
844         /* TODO: (UMEM) currently, read() handles user memcpy issues, but we
845          * probably should user_mem_check and pin the region here, so read doesn't
846          * worry about it */
847         ret = file->f_op->read(file, buf, len, &file->f_pos);
848         kref_put(&file->f_kref);
849         return ret;
850 }
851
852 static intreg_t sys_write(struct proc *p, int fd, const void *buf, int len)
853 {
854         ssize_t ret;
855         struct file *file = get_file_from_fd(&p->open_files, fd);
856         if (!file) {
857                 set_errno(EBADF);
858                 return -1;
859         }
860         if (!file->f_op->write) {
861                 kref_put(&file->f_kref);
862                 set_errno(EINVAL);
863                 return -1;
864         }
865         /* TODO: (UMEM) */
866         ret = file->f_op->write(file, buf, len, &file->f_pos);
867         kref_put(&file->f_kref);
868         return ret;
869 }
870
871 /* Checks args/reads in the path, opens the file, and inserts it into the
872  * process's open file list. 
873  *
874  * TODO: take the path length */
875 static intreg_t sys_open(struct proc *p, const char *path, size_t path_l,
876                          int oflag, int mode)
877 {
878         int fd = 0;
879         struct file *file;
880
881         printd("File %s Open attempt\n", path);
882         char *t_path = user_strdup_errno(p, path, path_l);
883         if (!t_path)
884                 return -1;
885         mode &= ~p->fs_env.umask;
886         file = do_file_open(t_path, oflag, mode);
887         user_memdup_free(p, t_path);
888         if (!file)
889                 return -1;
890         fd = insert_file(&p->open_files, file, 0);      /* stores the ref to file */
891         kref_put(&file->f_kref);
892         if (fd < 0) {
893                 warn("File insertion failed");
894                 return -1;
895         }
896         printd("File %s Open, res=%d\n", path, fd);
897         return fd;
898 }
899
900 static intreg_t sys_close(struct proc *p, int fd)
901 {
902         struct file *file = put_file_from_fd(&p->open_files, fd);
903         if (!file) {
904                 set_errno(EBADF);
905                 return -1;
906         }
907         return 0;
908 }
909
910 /* kept around til we remove the last ufe */
911 #define ufe(which,a0,a1,a2,a3) \
912         frontend_syscall_errno(p,APPSERVER_SYSCALL_##which,\
913                            (int)(a0),(int)(a1),(int)(a2),(int)(a3))
914
915 static intreg_t sys_fstat(struct proc *p, int fd, struct kstat *u_stat)
916 {
917         struct kstat *kbuf;
918         struct file *file = get_file_from_fd(&p->open_files, fd);
919         if (!file) {
920                 set_errno(EBADF);
921                 return -1;
922         }
923         kbuf = kmalloc(sizeof(struct kstat), 0);
924         if (!kbuf) {
925                 kref_put(&file->f_kref);
926                 set_errno(ENOMEM);
927                 return -1;
928         }
929         stat_inode(file->f_dentry->d_inode, kbuf);
930         kref_put(&file->f_kref);
931         /* TODO: UMEM: pin the memory, copy directly, and skip the kernel buffer */
932         if (memcpy_to_user_errno(p, u_stat, kbuf, sizeof(struct kstat))) {
933                 kfree(kbuf);
934                 set_errno(EINVAL);
935                 return -1;
936         }
937         kfree(kbuf);
938         return 0;
939 }
940
941 /* sys_stat() and sys_lstat() do nearly the same thing, differing in how they
942  * treat a symlink for the final item, which (probably) will be controlled by
943  * the lookup flags */
944 static intreg_t stat_helper(struct proc *p, const char *path, size_t path_l,
945                             struct kstat *u_stat, int flags)
946 {
947         struct kstat *kbuf;
948         struct dentry *path_d;
949         char *t_path = user_strdup_errno(p, path, path_l);
950         if (!t_path)
951                 return -1;
952         path_d = lookup_dentry(t_path, flags);
953         user_memdup_free(p, t_path);
954         if (!path_d)
955                 return -1;
956         kbuf = kmalloc(sizeof(struct kstat), 0);
957         if (!kbuf) {
958                 set_errno(ENOMEM);
959                 kref_put(&path_d->d_kref);
960                 return -1;
961         }
962         stat_inode(path_d->d_inode, kbuf);
963         kref_put(&path_d->d_kref);
964         /* TODO: UMEM: pin the memory, copy directly, and skip the kernel buffer */
965         if (memcpy_to_user_errno(p, u_stat, kbuf, sizeof(struct kstat))) {
966                 kfree(kbuf);
967                 set_errno(EINVAL);
968                 return -1;
969         }
970         kfree(kbuf);
971         return 0;
972 }
973
974 /* Follow a final symlink */
975 static intreg_t sys_stat(struct proc *p, const char *path, size_t path_l,
976                          struct kstat *u_stat)
977 {
978         return stat_helper(p, path, path_l, u_stat, LOOKUP_FOLLOW);
979 }
980
981 /* Don't follow a final symlink */
982 static intreg_t sys_lstat(struct proc *p, const char *path, size_t path_l,
983                           struct kstat *u_stat)
984 {
985         return stat_helper(p, path, path_l, u_stat, 0);
986 }
987
988 intreg_t sys_fcntl(struct proc *p, int fd, int cmd, int arg)
989 {
990         int retval = 0;
991         struct file *file = get_file_from_fd(&p->open_files, fd);
992         if (!file) {
993                 set_errno(EBADF);
994                 return -1;
995         }
996         switch (cmd) {
997                 case (F_DUPFD):
998                         retval = insert_file(&p->open_files, file, arg);
999                         if (retval < 0) {
1000                                 set_errno(-retval);
1001                                 retval = -1;
1002                         }
1003                         break;
1004                 case (F_GETFD):
1005                         retval = p->open_files.fd[fd].fd_flags;
1006                         break;
1007                 case (F_SETFD):
1008                         if (arg == FD_CLOEXEC)
1009                                 file->f_flags |= O_CLOEXEC;
1010                         break;
1011                 case (F_GETFL):
1012                         retval = file->f_flags;
1013                         break;
1014                 case (F_SETFL):
1015                         /* only allowed to set certain flags. */
1016                         arg &= O_FCNTL_FLAGS;
1017                         file->f_flags = (file->f_flags & ~O_FCNTL_FLAGS) | arg;
1018                         break;
1019                 default:
1020                         warn("Unsupported fcntl cmd %d\n", cmd);
1021         }
1022         kref_put(&file->f_kref);
1023         return retval;
1024 }
1025
1026 static intreg_t sys_access(struct proc *p, const char *path, size_t path_l,
1027                            int mode)
1028 {
1029         int retval;
1030         char *t_path = user_strdup_errno(p, path, path_l);
1031         if (!t_path)
1032                 return -1;
1033         retval = do_access(t_path, mode);
1034         user_memdup_free(p, t_path);
1035         printd("Access for path: %s retval: %d\n", path, retval);
1036         if (retval < 0) {
1037                 set_errno(-retval);
1038                 return -1;
1039         }
1040         return retval;
1041 }
1042
1043 intreg_t sys_umask(struct proc *p, int mask)
1044 {
1045         int old_mask = p->fs_env.umask;
1046         p->fs_env.umask = mask & S_PMASK;
1047         return old_mask;
1048 }
1049
1050 intreg_t sys_chmod(struct proc *p, const char *path, size_t path_l, int mode)
1051 {
1052         int retval;
1053         char *t_path = user_strdup_errno(p, path, path_l);
1054         if (!t_path)
1055                 return -1;
1056         retval = do_chmod(t_path, mode);
1057         user_memdup_free(p, t_path);
1058         if (retval < 0) {
1059                 set_errno(-retval);
1060                 return -1;
1061         }
1062         return retval;
1063 }
1064
1065 static intreg_t sys_lseek(struct proc *p, int fd, off_t offset, int whence)
1066 {
1067         off_t ret;
1068         struct file *file = get_file_from_fd(&p->open_files, fd);
1069         if (!file) {
1070                 set_errno(EBADF);
1071                 return -1;
1072         }
1073         ret = file->f_op->llseek(file, offset, whence);
1074         kref_put(&file->f_kref);
1075         return ret;
1076 }
1077
1078 intreg_t sys_link(struct proc *p, char *old_path, size_t old_l,
1079                   char *new_path, size_t new_l)
1080 {
1081         int ret;
1082         char *t_oldpath = user_strdup_errno(p, old_path, old_l);
1083         if (t_oldpath == NULL)
1084                 return -1;
1085         char *t_newpath = user_strdup_errno(p, new_path, new_l);
1086         if (t_newpath == NULL) {
1087                 user_memdup_free(p, t_oldpath);
1088                 return -1;
1089         }
1090         ret = do_link(t_oldpath, t_newpath);
1091         user_memdup_free(p, t_oldpath);
1092         user_memdup_free(p, t_newpath);
1093         return ret;
1094 }
1095
1096 intreg_t sys_unlink(struct proc *p, const char *path, size_t path_l)
1097 {
1098         int retval;
1099         char *t_path = user_strdup_errno(p, path, path_l);
1100         if (!t_path)
1101                 return -1;
1102         retval = do_unlink(t_path);
1103         user_memdup_free(p, t_path);
1104         return retval;
1105 }
1106
1107 intreg_t sys_symlink(struct proc *p, char *old_path, size_t old_l,
1108                      char *new_path, size_t new_l)
1109 {
1110         int ret;
1111         char *t_oldpath = user_strdup_errno(p, old_path, old_l);
1112         if (t_oldpath == NULL)
1113                 return -1;
1114         char *t_newpath = user_strdup_errno(p, new_path, new_l);
1115         if (t_newpath == NULL) {
1116                 user_memdup_free(p, t_oldpath);
1117                 return -1;
1118         }
1119         ret = do_symlink(new_path, old_path, S_IRWXU | S_IRWXG | S_IRWXO);
1120         user_memdup_free(p, t_oldpath);
1121         user_memdup_free(p, t_newpath);
1122         return ret;
1123 }
1124
1125 intreg_t sys_readlink(struct proc *p, char *path, size_t path_l,
1126                       char *u_buf, size_t buf_l)
1127 {
1128         char *symname;
1129         ssize_t copy_amt;
1130         struct dentry *path_d;
1131         char *t_path = user_strdup_errno(p, path, path_l);
1132         if (t_path == NULL)
1133                 return -1;
1134         path_d = lookup_dentry(t_path, 0);
1135         user_memdup_free(p, t_path);
1136         if (!path_d)
1137                 return -1;
1138         symname = path_d->d_inode->i_op->readlink(path_d);
1139         copy_amt = strnlen(symname, buf_l - 1) + 1;
1140         if (memcpy_to_user_errno(p, u_buf, symname, copy_amt)) {
1141                 kref_put(&path_d->d_kref);
1142                 set_errno(EINVAL);
1143                 return -1;
1144         }
1145         kref_put(&path_d->d_kref);
1146         printd("READLINK returning %s\n", u_buf);
1147         return copy_amt;
1148 }
1149
1150 intreg_t sys_chdir(struct proc *p, const char *path, size_t path_l)
1151 {
1152         int retval;
1153         char *t_path = user_strdup_errno(p, path, path_l);
1154         if (!t_path)
1155                 return -1;
1156         retval = do_chdir(&p->fs_env, t_path);
1157         user_memdup_free(p, t_path);
1158         if (retval) {
1159                 set_errno(-retval);
1160                 return -1;
1161         }
1162         return 0;
1163 }
1164
1165 /* Note cwd_l is not a strlen, it's an absolute size */
1166 intreg_t sys_getcwd(struct proc *p, char *u_cwd, size_t cwd_l)
1167 {
1168         int retval = 0;
1169         char *kfree_this;
1170         char *k_cwd = do_getcwd(&p->fs_env, &kfree_this, cwd_l);
1171         if (!k_cwd)
1172                 return -1;              /* errno set by do_getcwd */
1173         if (memcpy_to_user_errno(p, u_cwd, k_cwd, strnlen(k_cwd, cwd_l - 1) + 1))
1174                 retval = -1;
1175         kfree(kfree_this);
1176         return retval;
1177 }
1178
1179 intreg_t sys_mkdir(struct proc *p, const char *path, size_t path_l, int mode)
1180 {
1181         int retval;
1182         char *t_path = user_strdup_errno(p, path, path_l);
1183         if (!t_path)
1184                 return -1;
1185         mode &= ~p->fs_env.umask;
1186         retval = do_mkdir(t_path, mode);
1187         user_memdup_free(p, t_path);
1188         return retval;
1189 }
1190
1191 intreg_t sys_rmdir(struct proc *p, const char *path, size_t path_l)
1192 {
1193         int retval;
1194         char *t_path = user_strdup_errno(p, path, path_l);
1195         if (!t_path)
1196                 return -1;
1197         retval = do_rmdir(t_path);
1198         user_memdup_free(p, t_path);
1199         return retval;
1200 }
1201
1202 intreg_t sys_gettimeofday(struct proc *p, int *buf)
1203 {
1204         static spinlock_t gtod_lock = SPINLOCK_INITIALIZER;
1205         static int t0 = 0;
1206
1207         spin_lock(&gtod_lock);
1208         if(t0 == 0)
1209
1210 #if (defined __CONFIG_APPSERVER__)
1211         t0 = ufe(time,0,0,0,0);
1212 #else
1213         // Nanwan's birthday, bitches!!
1214         t0 = 1242129600;
1215 #endif 
1216         spin_unlock(&gtod_lock);
1217
1218         long long dt = read_tsc();
1219         int kbuf[2] = {t0+dt/system_timing.tsc_freq,
1220             (dt%system_timing.tsc_freq)*1000000/system_timing.tsc_freq};
1221
1222         return memcpy_to_user_errno(p,buf,kbuf,sizeof(kbuf));
1223 }
1224
1225 #define SIZEOF_STRUCT_TERMIOS 60
1226 intreg_t sys_tcgetattr(struct proc *p, int fd, void *termios_p)
1227 {
1228         int* kbuf = kmalloc(SIZEOF_STRUCT_TERMIOS,0);
1229         int ret = ufe(tcgetattr,fd,PADDR(kbuf),0,0);
1230         if(ret != -1 && memcpy_to_user_errno(p,termios_p,kbuf,SIZEOF_STRUCT_TERMIOS))
1231                 ret = -1;
1232         kfree(kbuf);
1233         return ret;
1234 }
1235
1236 intreg_t sys_tcsetattr(struct proc *p, int fd, int optional_actions,
1237                        const void *termios_p)
1238 {
1239         void* kbuf = user_memdup_errno(p,termios_p,SIZEOF_STRUCT_TERMIOS);
1240         if(kbuf == NULL)
1241                 return -1;
1242         int ret = ufe(tcsetattr,fd,optional_actions,PADDR(kbuf),0);
1243         user_memdup_free(p,kbuf);
1244         return ret;
1245 }
1246
1247 /* TODO: we don't have any notion of UIDs or GIDs yet, but don't let that stop a
1248  * process from thinking it can do these.  The other alternative is to have
1249  * glibc return 0 right away, though someone might want to do something with
1250  * these calls.  Someday. */
1251 intreg_t sys_setuid(struct proc *p, uid_t uid)
1252 {
1253         return 0;
1254 }
1255
1256 intreg_t sys_setgid(struct proc *p, gid_t gid)
1257 {
1258         return 0;
1259 }
1260
1261 /************** Syscall Invokation **************/
1262
1263 const static struct sys_table_entry syscall_table[] = {
1264         [SYS_null] = {(syscall_t)sys_null, "null"},
1265         [SYS_cache_buster] = {(syscall_t)sys_cache_buster, "buster"},
1266         [SYS_cache_invalidate] = {(syscall_t)sys_cache_invalidate, "wbinv"},
1267         [SYS_reboot] = {(syscall_t)reboot, "reboot!"},
1268         [SYS_cputs] = {(syscall_t)sys_cputs, "cputs"},
1269         [SYS_cgetc] = {(syscall_t)sys_cgetc, "cgetc"},
1270         [SYS_getcpuid] = {(syscall_t)sys_getcpuid, "getcpuid"},
1271         [SYS_getvcoreid] = {(syscall_t)sys_getvcoreid, "getvcoreid"},
1272         [SYS_getpid] = {(syscall_t)sys_getpid, "getpid"},
1273         [SYS_proc_create] = {(syscall_t)sys_proc_create, "proc_create"},
1274         [SYS_proc_run] = {(syscall_t)sys_proc_run, "proc_run"},
1275         [SYS_proc_destroy] = {(syscall_t)sys_proc_destroy, "proc_destroy"},
1276         [SYS_yield] = {(syscall_t)sys_proc_yield, "proc_yield"},
1277         [SYS_fork] = {(syscall_t)sys_fork, "fork"},
1278         [SYS_exec] = {(syscall_t)sys_exec, "exec"},
1279         [SYS_trywait] = {(syscall_t)sys_trywait, "trywait"},
1280         [SYS_mmap] = {(syscall_t)sys_mmap, "mmap"},
1281         [SYS_munmap] = {(syscall_t)sys_munmap, "munmap"},
1282         [SYS_mprotect] = {(syscall_t)sys_mprotect, "mprotect"},
1283         [SYS_shared_page_alloc] = {(syscall_t)sys_shared_page_alloc, "pa"},
1284         [SYS_shared_page_free] = {(syscall_t)sys_shared_page_free, "pf"},
1285         [SYS_resource_req] = {(syscall_t)sys_resource_req, "resource_req"},
1286         [SYS_notify] = {(syscall_t)sys_notify, "notify"},
1287         [SYS_self_notify] = {(syscall_t)sys_self_notify, "self_notify"},
1288         [SYS_halt_core] = {(syscall_t)sys_halt_core, "halt_core"},
1289 #ifdef __CONFIG_SERIAL_IO__
1290         [SYS_serial_read] = {(syscall_t)sys_serial_read, "ser_read"},
1291         [SYS_serial_write] = {(syscall_t)sys_serial_write, "ser_write"},
1292 #endif
1293 #ifdef __CONFIG_NETWORKING__
1294         [SYS_eth_read] = {(syscall_t)sys_eth_read, "eth_read"},
1295         [SYS_eth_write] = {(syscall_t)sys_eth_write, "eth_write"},
1296         [SYS_eth_get_mac_addr] = {(syscall_t)sys_eth_get_mac_addr, "get_mac"},
1297         [SYS_eth_recv_check] = {(syscall_t)sys_eth_recv_check, "recv_check"},
1298 #endif
1299 #ifdef __CONFIG_ARSC_SERVER__
1300         [SYS_init_arsc] = {(syscall_t)sys_init_arsc, "init_arsc"},
1301 #endif
1302         [SYS_read] = {(syscall_t)sys_read, "read"},
1303         [SYS_write] = {(syscall_t)sys_write, "write"},
1304         [SYS_open] = {(syscall_t)sys_open, "open"},
1305         [SYS_close] = {(syscall_t)sys_close, "close"},
1306         [SYS_fstat] = {(syscall_t)sys_fstat, "fstat"},
1307         [SYS_stat] = {(syscall_t)sys_stat, "stat"},
1308         [SYS_lstat] = {(syscall_t)sys_lstat, "lstat"},
1309         [SYS_fcntl] = {(syscall_t)sys_fcntl, "fcntl"},
1310         [SYS_access] = {(syscall_t)sys_access, "access"},
1311         [SYS_umask] = {(syscall_t)sys_umask, "umask"},
1312         [SYS_chmod] = {(syscall_t)sys_chmod, "chmod"},
1313         [SYS_lseek] = {(syscall_t)sys_lseek, "lseek"},
1314         [SYS_link] = {(syscall_t)sys_link, "link"},
1315         [SYS_unlink] = {(syscall_t)sys_unlink, "unlink"},
1316         [SYS_symlink] = {(syscall_t)sys_symlink, "symlink"},
1317         [SYS_readlink] = {(syscall_t)sys_readlink, "readlink"},
1318         [SYS_chdir] = {(syscall_t)sys_chdir, "chdir"},
1319         [SYS_getcwd] = {(syscall_t)sys_getcwd, "getcwd"},
1320         [SYS_mkdir] = {(syscall_t)sys_mkdir, "mkdri"},
1321         [SYS_rmdir] = {(syscall_t)sys_rmdir, "rmdir"},
1322         [SYS_gettimeofday] = {(syscall_t)sys_gettimeofday, "gettime"},
1323         [SYS_tcgetattr] = {(syscall_t)sys_tcgetattr, "tcgetattr"},
1324         [SYS_tcsetattr] = {(syscall_t)sys_tcsetattr, "tcsetattr"},
1325         [SYS_setuid] = {(syscall_t)sys_setuid, "setuid"},
1326         [SYS_setgid] = {(syscall_t)sys_setgid, "setgid"}
1327 };
1328
1329 /* Executes the given syscall.
1330  *
1331  * Note tf is passed in, which points to the tf of the context on the kernel
1332  * stack.  If any syscall needs to block, it needs to save this info, as well as
1333  * any silly state.
1334  * 
1335  * This syscall function is used by both local syscall and arsc, and should
1336  * remain oblivious of the caller. */
1337 intreg_t syscall(struct proc *p, uintreg_t syscallno, uintreg_t a1,
1338                  uintreg_t a2, uintreg_t a3, uintreg_t a4, uintreg_t a5)
1339 {
1340         const int max_syscall = sizeof(syscall_table)/sizeof(syscall_table[0]);
1341
1342         uint32_t coreid, vcoreid;
1343         if (systrace_flags & SYSTRACE_ON) {
1344                 if ((systrace_flags & SYSTRACE_ALLPROC) || (proc_is_traced(p))) {
1345                         coreid = core_id();
1346                         vcoreid = proc_get_vcoreid(p, coreid);
1347                         if (systrace_flags & SYSTRACE_LOUD) {
1348                                 printk("[%16llu] Syscall %3d (%12s):(%08p, %08p, %08p, %08p, "
1349                                        "%08p) proc: %d core: %d vcore: %d\n", read_tsc(),
1350                                        syscallno, syscall_table[syscallno].name, a1, a2, a3,
1351                                        a4, a5, p->pid, coreid, vcoreid);
1352                         } else {
1353                                 struct systrace_record *trace;
1354                                 unsigned int idx, new_idx;
1355                                 do {
1356                                         idx = systrace_bufidx;
1357                                         new_idx = (idx + 1) % systrace_bufsize;
1358                                 } while (!atomic_comp_swap(&systrace_bufidx, idx, new_idx));
1359                                 trace = &systrace_buffer[idx];
1360                                 trace->timestamp = read_tsc();
1361                                 trace->syscallno = syscallno;
1362                                 trace->arg1 = a1;
1363                                 trace->arg2 = a2;
1364                                 trace->arg3 = a3;
1365                                 trace->arg4 = a4;
1366                                 trace->arg5 = a5;
1367                                 trace->pid = p->pid;
1368                                 trace->coreid = coreid;
1369                                 trace->vcoreid = vcoreid;
1370                         }
1371                 }
1372         }
1373         //printk("Incoming syscall on core: %d number: %d\n    a1: %x\n   "
1374         //       " a2: %x\n    a3: %x\n    a4: %x\n    a5: %x\n", core_id(),
1375         //       syscallno, a1, a2, a3, a4, a5);
1376
1377         if (syscallno > max_syscall || syscall_table[syscallno].call == NULL)
1378                 panic("Invalid syscall number %d for proc %x!", syscallno, *p);
1379
1380         return syscall_table[syscallno].call(p, a1, a2, a3, a4, a5);
1381 }
1382
1383 /* A process can trap and call this function, which will set up the core to
1384  * handle all the syscalls.  a.k.a. "sys_debutante(needs, wants)" */
1385 void prep_syscalls(struct proc *p, struct syscall *sysc, unsigned int nr_calls)
1386 {
1387         int retval;
1388         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
1389         /* TODO: (UMEM) assert / pin the memory range sysc for nr_calls.  Not sure
1390          * how we'll know it is done to unpin it. (might need to handle it in
1391          * abandon_core() or smp_idle(). */
1392         user_mem_assert(p, sysc, nr_calls * sizeof(struct syscall), PTE_USER_RW);
1393         /* TEMP! */
1394         if (nr_calls != 1)
1395                 warn("Debutante calls: %d\n", nr_calls);
1396         /* Set up this core to process the local call */
1397         *pcpui->tf_retval_loc = 0;      /* current_tf's retval says how many are done */
1398         pcpui->syscalls = sysc;
1399         pcpui->nr_calls = nr_calls;
1400 }
1401
1402 /* This returns if there are no syscalls to do, o/w it always calls smp_idle()
1403  * afterwards. */
1404 void run_local_syscall(void)
1405 {
1406         struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
1407         struct syscall *sysc;
1408
1409         if (!pcpui->nr_calls) {
1410                 /* TODO: UMEM - stop pinning their memory.  Note, we may need to do this
1411                  * in other places.  This also will be tricky with exec, which doesn't
1412                  * have the same memory map anymore */
1413                 return;
1414         }
1415         sysc = pcpui->syscalls++;               /* get the next */
1416         pcpui->nr_calls--;                              /* one less to do */
1417         (*pcpui->tf_retval_loc)++;              /* one more started */
1418         pcpui->errno_loc = &sysc->err;
1419         // TODO: push this deeper into the syscalls */
1420         kref_get(&current->kref, 1);
1421         /* TODO: arg5 */
1422         sysc->retval = syscall(pcpui->cur_proc, sysc->num, sysc->arg0, sysc->arg1,
1423                                sysc->arg2, sysc->arg3, sysc->arg4);
1424         /* TODO: when we remove this, remove it from sys_exec() too */
1425         kref_put(&current->kref);
1426         sysc->flags |= SC_DONE;
1427         /* regardless of whether the call blocked or not, we smp_idle().  If it was
1428          * the last call, it'll return to the process.  If there are more, it will
1429          * do them. */
1430         smp_idle();
1431         assert(0);
1432 }
1433
1434 /* Syscall tracing */
1435 static void __init_systrace(void)
1436 {
1437         systrace_buffer = kmalloc(MAX_SYSTRACES*sizeof(struct systrace_record), 0);
1438         if (!systrace_buffer)
1439                 panic("Unable to alloc a trace buffer\n");
1440         systrace_bufidx = 0;
1441         systrace_bufsize = MAX_SYSTRACES;
1442         /* Note we never free the buffer - it's around forever.  Feel free to change
1443          * this if you want to change the size or something dynamically. */
1444 }
1445
1446 /* If you call this while it is running, it will change the mode */
1447 void systrace_start(bool silent)
1448 {
1449         static bool init = FALSE;
1450         spin_lock_irqsave(&systrace_lock);
1451         if (!init) {
1452                 __init_systrace();
1453                 init = TRUE;
1454         }
1455         systrace_flags = silent ? SYSTRACE_ON : SYSTRACE_ON | SYSTRACE_LOUD; 
1456         spin_unlock_irqsave(&systrace_lock);
1457 }
1458
1459 int systrace_reg(bool all, struct proc *p)
1460 {
1461         int retval = 0;
1462         spin_lock_irqsave(&systrace_lock);
1463         if (all) {
1464                 printk("Tracing syscalls for all processes\n");
1465                 systrace_flags |= SYSTRACE_ALLPROC;
1466                 retval = 0;
1467         } else {
1468                 for (int i = 0; i < MAX_NUM_TRACED; i++) {
1469                         if (!systrace_procs[i]) {
1470                                 printk("Tracing syscalls for process %d\n", p->pid);
1471                                 systrace_procs[i] = p;
1472                                 retval = 0;
1473                                 break;
1474                         }
1475                 }
1476         }
1477         spin_unlock_irqsave(&systrace_lock);
1478         return retval;
1479 }
1480
1481 void systrace_stop(void)
1482 {
1483         spin_lock_irqsave(&systrace_lock);
1484         systrace_flags = 0;
1485         for (int i = 0; i < MAX_NUM_TRACED; i++)
1486                 systrace_procs[i] = 0;
1487         spin_unlock_irqsave(&systrace_lock);
1488 }
1489
1490 /* If you registered a process specifically, then you need to dereg it
1491  * specifically.  Or just fully stop, which will do it for all. */
1492 int systrace_dereg(bool all, struct proc *p)
1493 {
1494         spin_lock_irqsave(&systrace_lock);
1495         if (all) {
1496                 printk("No longer tracing syscalls for all processes.\n");
1497                 systrace_flags &= ~SYSTRACE_ALLPROC;
1498         } else {
1499                 for (int i = 0; i < MAX_NUM_TRACED; i++) {
1500                         if (systrace_procs[i] == p) {
1501                                 systrace_procs[i] = 0;
1502                                 printk("No longer tracing syscalls for process %d\n", p->pid);
1503                         }
1504                 }
1505         }
1506         spin_unlock_irqsave(&systrace_lock);
1507         return 0;
1508 }
1509
1510 /* Regardless of locking, someone could be writing into the buffer */
1511 void systrace_print(bool all, struct proc *p)
1512 {
1513         spin_lock_irqsave(&systrace_lock);
1514         /* if you want to be clever, you could make this start from the earliest
1515          * timestamp and loop around.  Careful of concurrent writes. */
1516         for (int i = 0; i < systrace_bufsize; i++)
1517                 if (systrace_buffer[i].timestamp)
1518                         printk("[%16llu] Syscall %3d (%12s):(%08p, %08p, %08p, %08p, "
1519                                "%08p) proc: %d core: %d vcore: %d\n",
1520                                systrace_buffer[i].timestamp,
1521                                systrace_buffer[i].syscallno,
1522                                syscall_table[systrace_buffer[i].syscallno].name,
1523                                systrace_buffer[i].arg1,
1524                                systrace_buffer[i].arg2,
1525                                systrace_buffer[i].arg3,
1526                                systrace_buffer[i].arg4,
1527                                systrace_buffer[i].arg5,
1528                                systrace_buffer[i].pid,
1529                                systrace_buffer[i].coreid,
1530                                systrace_buffer[i].vcoreid);
1531         spin_unlock_irqsave(&systrace_lock);
1532 }
1533
1534 void systrace_clear_buffer(void)
1535 {
1536         spin_lock_irqsave(&systrace_lock);
1537         memset(systrace_buffer, 0, sizeof(struct systrace_record) * MAX_SYSTRACES);
1538         spin_unlock_irqsave(&systrace_lock);
1539 }