Use get_pcoreid() in proc management code
[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 <mm.h>
23 #include <trap.h>
24 #include <syscall.h>
25 #include <kmalloc.h>
26 #include <stdio.h>
27 #include <resource.h>
28 #include <frontend.h>
29 #include <colored_caches.h>
30 #include <arch/bitmask.h>
31 #include <kfs.h> // eventually replace this with vfs.h
32
33
34 #ifdef __CONFIG_NETWORKING__
35 #include <arch/nic_common.h>
36 extern int (*send_frame)(const char *CT(len) data, size_t len);
37 extern unsigned char device_mac[6];
38 #endif
39
40 /* Tracing Globals */
41 int systrace_flags = 0;
42 struct systrace_record *systrace_buffer = 0;
43 unsigned int systrace_bufidx = 0;
44 size_t systrace_bufsize = 0;
45 struct proc *systrace_procs[MAX_NUM_TRACED] = {0};
46 spinlock_t systrace_lock = SPINLOCK_INITIALIZER;
47
48 /* Not enforcing the packing of systrace_procs yet, but don't rely on that */
49 static bool proc_is_traced(struct proc *p)
50 {
51         for (int i = 0; i < MAX_NUM_TRACED; i++)
52                 if (systrace_procs[i] == p)
53                         return true;
54         return false;
55 }
56
57 /************** Utility Syscalls **************/
58
59 static int sys_null(void)
60 {
61         return 0;
62 }
63
64 // Writes 'val' to 'num_writes' entries of the well-known array in the kernel
65 // address space.  It's just #defined to be some random 4MB chunk (which ought
66 // to be boot_alloced or something).  Meant to grab exclusive access to cache
67 // lines, to simulate doing something useful.
68 static int sys_cache_buster(struct proc *p, uint32_t num_writes,
69                              uint32_t num_pages, uint32_t flags)
70 { TRUSTEDBLOCK /* zra: this is not really part of the kernel */
71         #define BUSTER_ADDR             0xd0000000  // around 512 MB deep
72         #define MAX_WRITES              1048576*8
73         #define MAX_PAGES               32
74         #define INSERT_ADDR     (UINFO + 2*PGSIZE) // should be free for these tests
75         uint32_t* buster = (uint32_t*)BUSTER_ADDR;
76         static spinlock_t buster_lock = SPINLOCK_INITIALIZER;
77         uint64_t ticks = -1;
78         page_t* a_page[MAX_PAGES];
79
80         /* Strided Accesses or Not (adjust to step by cachelines) */
81         uint32_t stride = 1;
82         if (flags & BUSTER_STRIDED) {
83                 stride = 16;
84                 num_writes *= 16;
85         }
86
87         /* Shared Accesses or Not (adjust to use per-core regions)
88          * Careful, since this gives 8MB to each core, starting around 512MB.
89          * Also, doesn't separate memory for core 0 if it's an async call.
90          */
91         if (!(flags & BUSTER_SHARED))
92                 buster = (uint32_t*)(BUSTER_ADDR + core_id() * 0x00800000);
93
94         /* Start the timer, if we're asked to print this info*/
95         if (flags & BUSTER_PRINT_TICKS)
96                 ticks = start_timing();
97
98         /* Allocate num_pages (up to MAX_PAGES), to simulate doing some more
99          * realistic work.  Note we don't write to these pages, even if we pick
100          * unshared.  Mostly due to the inconvenience of having to match up the
101          * number of pages with the number of writes.  And it's unnecessary.
102          */
103         if (num_pages) {
104                 spin_lock(&buster_lock);
105                 for (int i = 0; i < MIN(num_pages, MAX_PAGES); i++) {
106                         upage_alloc(p, &a_page[i],1);
107                         page_insert(p->env_pgdir, a_page[i], (void*)INSERT_ADDR + PGSIZE*i,
108                                     PTE_USER_RW);
109                 }
110                 spin_unlock(&buster_lock);
111         }
112
113         if (flags & BUSTER_LOCKED)
114                 spin_lock(&buster_lock);
115         for (int i = 0; i < MIN(num_writes, MAX_WRITES); i=i+stride)
116                 buster[i] = 0xdeadbeef;
117         if (flags & BUSTER_LOCKED)
118                 spin_unlock(&buster_lock);
119
120         if (num_pages) {
121                 spin_lock(&buster_lock);
122                 for (int i = 0; i < MIN(num_pages, MAX_PAGES); i++) {
123                         page_remove(p->env_pgdir, (void*)(INSERT_ADDR + PGSIZE * i));
124                         page_decref(a_page[i]);
125                 }
126                 spin_unlock(&buster_lock);
127         }
128
129         /* Print info */
130         if (flags & BUSTER_PRINT_TICKS) {
131                 ticks = stop_timing(ticks);
132                 printk("%llu,", ticks);
133         }
134         return 0;
135 }
136
137 static int sys_cache_invalidate(void)
138 {
139         #ifdef __i386__
140                 wbinvd();
141         #endif
142         return 0;
143 }
144
145 /* sys_reboot(): called directly from dispatch table. */
146
147 // Print a string to the system console.
148 // The string is exactly 'len' characters long.
149 // Destroys the environment on memory errors.
150 static ssize_t sys_cputs(env_t* e, const char *DANGEROUS s, size_t len)
151 {
152         // Check that the user has permission to read memory [s, s+len).
153         // Destroy the environment if not.
154         char *COUNT(len) _s = user_mem_assert(e, s, len, PTE_USER_RO);
155
156         // Print the string supplied by the user.
157         printk("%.*s", len, _s);
158         return (ssize_t)len;
159 }
160
161 // Read a character from the system console.
162 // Returns the character.
163 static uint16_t sys_cgetc(env_t* e)
164 {
165         uint16_t c;
166
167         // The cons_getc() primitive doesn't wait for a character,
168         // but the sys_cgetc() system call does.
169         while ((c = cons_getc()) == 0)
170                 cpu_relax();
171
172         return c;
173 }
174
175 /* Returns the id of the cpu this syscall is executed on. */
176 static uint32_t sys_getcpuid(void)
177 {
178         return core_id();
179 }
180
181 // TODO: Temporary hack until thread-local storage is implemented on i386 and
182 // this is removed from the user interface
183 static size_t sys_getvcoreid(struct proc *p)
184 {
185         return proc_get_vcoreid(p, core_id());
186 }
187
188 /************** Process management syscalls **************/
189
190 /* Returns the calling process's pid */
191 static pid_t sys_getpid(struct proc *p)
192 {
193         return p->pid;
194 }
195
196 /*
197  * Creates a process found at the user string 'path'.  Currently uses KFS.
198  * Not runnable by default, so it needs it's status to be changed so that the
199  * next call to schedule() will try to run it.
200  * TODO: once we have a decent VFS, consider splitting this up
201  * and once there's an mmap, can have most of this in process.c
202  */
203 static int sys_proc_create(struct proc *p, const char *DANGEROUS path)
204 {
205         int pid = 0;
206         char tpath[MAX_PATH_LEN];
207         /*
208          * There's a bunch of issues with reading in the path, which we'll
209          * need to sort properly in the VFS.  Main concerns are TOCTOU (copy-in),
210          * whether or not it's a big deal that the pointer could be into kernel
211          * space, and resolving both of these without knowing the length of the
212          * string. (TODO)
213          * Change this so that all syscalls with a pointer take a length.
214          *
215          * zra: I've added this user_mem_strlcpy, which I think eliminates the
216      * the TOCTOU issue. Adding a length arg to this call would allow a more
217          * efficient implementation, though, since only one call to user_mem_check
218          * would be required.
219          */
220         int ret = user_mem_strlcpy(p,tpath, path, MAX_PATH_LEN, PTE_USER_RO);
221         int kfs_inode = kfs_lookup_path(tpath);
222         if (kfs_inode < 0)
223                 return -EINVAL;
224         struct proc *new_p = kfs_proc_create(kfs_inode);
225         pid = new_p->pid;
226         proc_decref(new_p, 1); // let go of the reference created in proc_create()
227         return pid;
228 }
229
230 /* Makes process PID runnable.  Consider moving the functionality to process.c */
231 static error_t sys_proc_run(struct proc *p, unsigned pid)
232 {
233         struct proc *target = pid2proc(pid);
234         error_t retval = 0;
235
236         if (!target)
237                 return -EBADPROC;
238         // note we can get interrupted here. it's not bad.
239         spin_lock(&p->proc_lock);
240         // make sure we have access and it's in the right state to be activated
241         if (!proc_controls(p, target)) {
242                 proc_decref(target, 1);
243                 retval = -EPERM;
244         } else if (target->state != PROC_CREATED) {
245                 proc_decref(target, 1);
246                 retval = -EINVAL;
247         } else {
248                 __proc_set_state(target, PROC_RUNNABLE_S);
249                 schedule_proc(target);
250         }
251         spin_unlock(&p->proc_lock);
252         proc_decref(target, 1);
253         return retval;
254 }
255
256 /* Destroy proc pid.  If this is called by the dying process, it will never
257  * return.  o/w it will return 0 on success, or an error.  Errors include:
258  * - EBADPROC: if there is no such process with pid
259  * - EPERM: if caller does not control pid */
260 static error_t sys_proc_destroy(struct proc *p, pid_t pid, int exitcode)
261 {
262         error_t r;
263         struct proc *p_to_die = pid2proc(pid);
264
265         if (!p_to_die) {
266                 set_errno(current_tf, ESRCH);
267                 return -1;
268         }
269         if (!proc_controls(p, p_to_die)) {
270                 proc_decref(p_to_die, 1);
271                 set_errno(current_tf, EPERM);
272                 return -1;
273         }
274         if (p_to_die == p) {
275                 // syscall code and pid2proc both have edible references, only need 1.
276                 p->exitcode = exitcode;
277                 proc_decref(p, 1);
278                 printd("[PID %d] proc exiting gracefully (code %d)\n", p->pid,exitcode);
279         } else {
280                 printd("[%d] destroying proc %d\n", p->pid, p_to_die->pid);
281         }
282         proc_destroy(p_to_die);
283         proc_decref(p_to_die, 1);
284         return ESUCCESS;
285 }
286
287 static int sys_proc_yield(struct proc *p, bool being_nice)
288 {
289         proc_yield(p, being_nice);
290         return 0;
291 }
292
293 static ssize_t sys_run_binary(env_t* e, void *DANGEROUS binary_buf, size_t len,
294                               procinfo_t*DANGEROUS procinfo, size_t num_colors)
295 {
296         env_t* env = proc_create(NULL,0);
297         assert(env != NULL);
298
299         // let me know if you use this.  we need to sort process creation better.
300         printk("sys_run_binary() is deprecated.  Use at your own risk.");
301         if(memcpy_from_user(e,e->procinfo,procinfo,sizeof(*procinfo)))
302                 return -1;
303         proc_init_procinfo(e);
304
305         env_load_icode(env,e,binary_buf,len);
306         __proc_set_state(env, PROC_RUNNABLE_S);
307         schedule_proc(env);
308         if(num_colors > 0) {
309                 env->cache_colors_map = cache_colors_map_alloc();
310                 for(int i=0; i<num_colors; i++)
311                         cache_color_alloc(llc_cache, env->cache_colors_map);
312         }
313         proc_decref(env, 1);
314         proc_yield(e, 0);
315         return 0;
316 }
317
318 static ssize_t sys_fork(env_t* e)
319 {
320         // TODO: right now we only support fork for single-core processes
321         if(e->state != PROC_RUNNING_S)
322         {
323                 set_errno(current_tf,EINVAL);
324                 return -1;
325         }
326
327         env_t* env = proc_create(NULL,0);
328         assert(env != NULL);
329
330         env->heap_top = e->heap_top;
331         env->ppid = e->pid;
332         env->env_tf = *current_tf;
333
334         env->cache_colors_map = cache_colors_map_alloc();
335         for(int i=0; i < llc_cache->num_colors; i++)
336                 if(GET_BITMASK_BIT(e->cache_colors_map,i))
337                         cache_color_alloc(llc_cache, env->cache_colors_map);
338
339         int copy_page(env_t* e, pte_t* pte, void* va, void* arg)
340         {
341                 env_t* env = (env_t*)arg;
342
343                 if(PAGE_PRESENT(*pte))
344                 {
345                         page_t* pp;
346                         if(upage_alloc(env,&pp,0))
347                                 return -1;
348                         if(page_insert(env->env_pgdir,pp,va,*pte & PTE_PERM))
349                         {
350                                 page_decref(pp);
351                                 return -1;
352                         }
353
354                         pagecopy(page2kva(pp),ppn2kva(PTE2PPN(*pte)));
355                 }
356                 else // PAGE_PAGED_OUT(*pte)
357                 {
358                         pte_t* newpte = pgdir_walk(env->env_pgdir,va,1);
359                         if(!newpte)
360                                 return -1;
361
362                         struct file* file = PTE2PFAULT_INFO(*pte)->file;
363                         pfault_info_t* newpfi = pfault_info_alloc(file);
364                         if(!newpfi)
365                                 return -1;
366
367                         *newpfi = *PTE2PFAULT_INFO(*pte);
368                         *newpte = PFAULT_INFO2PTE(newpfi);
369                 }
370
371                 return 0;
372         }
373
374         // TODO: (PC) this won't work.  Needs revisiting.
375         // copy procdata and procinfo
376         memcpy(env->procdata,e->procdata,sizeof(struct procdata));
377         memcpy(env->procinfo,e->procinfo,sizeof(struct procinfo));
378         env->procinfo->pid = env->pid;
379         env->procinfo->ppid = env->ppid;
380
381         // copy all memory below procdata
382         if(env_user_mem_walk(e,0,UDATA,&copy_page,env))
383         {
384                 proc_decref(env,2);
385                 set_errno(current_tf,ENOMEM);
386                 return -1;
387         }
388
389         __proc_set_state(env, PROC_RUNNABLE_S);
390         schedule_proc(env);
391
392         // don't decref the new process.
393         // that will happen when the parent waits for it.
394
395         printd("[PID %d] fork PID %d\n",e->pid,env->pid);
396
397         return env->pid;
398 }
399
400 intreg_t sys_exec(struct proc* p, int fd, procinfo_t* pi)
401 {
402         if(p->state != PROC_RUNNING_S)
403                 return -1;
404
405         int ret = -1;
406         struct file* f = file_open_from_fd(p,fd);
407         if(f == NULL) {
408                 set_errno(current_tf, EBADF);
409                 goto out;
410         }
411
412         // Set the argument stuff needed by glibc
413         if(memcpy_from_user(p,p->procinfo->argp,pi->argp,sizeof(pi->argp))) {
414                 proc_destroy(p);
415                 goto out;
416         }
417         if(memcpy_from_user(p,p->procinfo->argbuf,pi->argbuf,sizeof(pi->argbuf))) {
418                 proc_destroy(p);
419                 goto out;
420         }
421
422         // TODO: don't do this either (PC)
423         memset(p->procdata, 0, sizeof(procdata_t));
424
425         env_user_mem_free(p,0,USTACKTOP);
426
427         if(load_elf(p,f))
428         {
429                 proc_destroy(p);
430                 goto out;
431         }
432         file_decref(f);
433         *current_tf = p->env_tf;
434         ret = 0;
435
436         printd("[PID %d] exec fd %d\n",p->pid,fd);
437
438 out:
439         return ret;
440 }
441
442 static ssize_t sys_trywait(env_t* e, pid_t pid, int* status)
443 {
444         struct proc* p = pid2proc(pid);
445
446         // TODO: this syscall is racy, so we only support for single-core procs
447         if(e->state != PROC_RUNNING_S)
448                 return -1;
449
450         // TODO: need to use errno properly.  sadly, ROS error codes conflict..
451
452         if(p)
453         {
454                 ssize_t ret;
455
456                 if(current->pid == p->ppid)
457                 {
458                         if(p->state == PROC_DYING)
459                         {
460                                 memcpy_to_user(e,status,&p->exitcode,sizeof(int));
461                                 printd("[PID %d] waited for PID %d (code %d)\n",
462                                        e->pid,p->pid,p->exitcode);
463                                 ret = 0;
464                         }
465                         else // not dead yet
466                         {
467                                 set_errno(current_tf,0);
468                                 ret = -1;
469                         }
470                 }
471                 else // not a child of the calling process
472                 {
473                         set_errno(current_tf,1);
474                         ret = -1;
475                 }
476
477                 // if the wait succeeded, decref twice
478                 proc_decref(p,1 + (ret == 0));
479                 return ret;
480         }
481
482         set_errno(current_tf,1);
483         return -1;
484 }
485
486 /************** Memory Management Syscalls **************/
487
488 static void *sys_mmap(struct proc* p, uintreg_t a1, uintreg_t a2, uintreg_t a3,
489                       uintreg_t* a456)
490 {
491         uintreg_t _a456[3];
492         if(memcpy_from_user(p,_a456,a456,3*sizeof(uintreg_t)))
493                 sys_proc_destroy(p,p->pid,-1);
494         return mmap(p,a1,a2,a3,_a456[0],_a456[1],_a456[2]);
495 }
496
497 static intreg_t sys_mprotect(struct proc* p, void* addr, size_t len, int prot)
498 {
499         return mprotect(p, addr, len, prot);
500 }
501
502 static intreg_t sys_munmap(struct proc* p, void* addr, size_t len)
503 {
504         return munmap(p, addr, len);
505 }
506
507 static void* sys_brk(struct proc *p, void* addr) {
508         ssize_t range;
509
510         // TODO: remove sys_brk
511         printk("[kernel] don't use brk, unsupported and will be removed soon.\n");
512
513         spin_lock(&p->proc_lock);
514
515         if((addr < p->procinfo->heap_bottom) || (addr >= (void*)BRK_END))
516                 goto out;
517
518         uintptr_t real_heap_top = ROUNDUP((uintptr_t)p->heap_top,PGSIZE);
519         uintptr_t real_new_heap_top = ROUNDUP((uintptr_t)addr,PGSIZE);
520         range = real_new_heap_top - real_heap_top;
521
522         if (range > 0) {
523                 if(__do_mmap(p, real_heap_top, range, PROT_READ | PROT_WRITE,
524                              MAP_FIXED | MAP_ANONYMOUS, NULL, 0) == MAP_FAILED)
525                         goto out;
526         }
527         else if (range < 0) {
528                 if(__munmap(p, (void*)real_new_heap_top, -range))
529                         goto out;
530         }
531         p->heap_top = addr;
532
533 out:
534         spin_unlock(&p->proc_lock);
535         return p->heap_top;
536 }
537
538 static ssize_t sys_shared_page_alloc(env_t* p1,
539                                      void**DANGEROUS _addr, pid_t p2_id,
540                                      int p1_flags, int p2_flags
541                                     )
542 {
543         //if (!VALID_USER_PERMS(p1_flags)) return -EPERM;
544         //if (!VALID_USER_PERMS(p2_flags)) return -EPERM;
545
546         void * COUNT(1) * COUNT(1) addr = user_mem_assert(p1, _addr, sizeof(void *),
547                                                       PTE_USER_RW);
548         struct proc *p2 = pid2proc(p2_id);
549         if (!p2)
550                 return -EBADPROC;
551
552         page_t* page;
553         error_t e = upage_alloc(p1, &page,1);
554         if (e < 0) {
555                 proc_decref(p2, 1);
556                 return e;
557         }
558
559         void* p2_addr = page_insert_in_range(p2->env_pgdir, page,
560                         (void*SNT)UTEXT, (void*SNT)UTOP, p2_flags);
561         if (p2_addr == NULL) {
562                 page_free(page);
563                 proc_decref(p2, 1);
564                 return -EFAIL;
565         }
566
567         void* p1_addr = page_insert_in_range(p1->env_pgdir, page,
568                         (void*SNT)UTEXT, (void*SNT)UTOP, p1_flags);
569         if(p1_addr == NULL) {
570                 page_remove(p2->env_pgdir, p2_addr);
571                 page_free(page);
572                 proc_decref(p2, 1);
573                 return -EFAIL;
574         }
575         *addr = p1_addr;
576         proc_decref(p2, 1);
577         return ESUCCESS;
578 }
579
580 static int sys_shared_page_free(env_t* p1, void*DANGEROUS addr, pid_t p2)
581 {
582         return -1;
583 }
584
585
586 /* sys_resource_req(): called directly from dispatch table. */
587
588 /* Will notify the target on the given vcore, if the caller controls the target.
589  * Will honor the target's wanted/vcoreid.  u_ne can be NULL. */
590 static int sys_notify(struct proc *p, int target_pid, unsigned int notif,
591                       struct notif_event *u_ne)
592 {
593         struct notif_event local_ne;
594         struct proc *target = pid2proc(target_pid);
595
596         if (!target) {
597                 set_errno(current_tf, EBADPROC);
598                 return -1;
599         }
600         if (!proc_controls(p, target)) {
601                 proc_decref(target, 1);
602                 set_errno(current_tf, EPERM);
603                 return -1;
604         }
605         /* if the user provided a notif_event, copy it in and use that */
606         if (u_ne) {
607                 if (memcpy_from_user(p, &local_ne, u_ne, sizeof(struct notif_event))) {
608                         proc_decref(target, 1);
609                         set_errno(current_tf, EINVAL);
610                         return -1;
611                 }
612                 proc_notify(target, local_ne.ne_type, &local_ne);
613         } else {
614                 proc_notify(target, notif, 0);
615         }
616         proc_decref(target, 1);
617         return 0;
618 }
619
620 /* Will notify the calling process on the given vcore, independently of WANTED
621  * or advertised vcoreid.  If you change the parameters, change pop_ros_tf() */
622 static int sys_self_notify(struct proc *p, uint32_t vcoreid, unsigned int notif,
623                            struct notif_event *u_ne)
624 {
625         struct notif_event local_ne;
626
627         printd("[kernel] received self notify for vcoreid %d, notif %d, ne %08p\n",
628                vcoreid, notif, u_ne);
629         /* if the user provided a notif_event, copy it in and use that */
630         if (u_ne) {
631                 if (memcpy_from_user(p, &local_ne, u_ne, sizeof(struct notif_event))) {
632                         set_errno(current_tf, EINVAL);
633                         return -1;
634                 }
635                 do_notify(p, vcoreid, local_ne.ne_type, &local_ne);
636         } else {
637                 do_notify(p, vcoreid, notif, 0);
638         }
639         return 0;
640 }
641
642 /* This will set a local timer for usec, then shut down the core */
643 static int sys_halt_core(struct proc *p, unsigned int usec)
644 {
645         /* TODO: ought to check and see if a timer was already active, etc, esp so
646          * userspace can't turn off timers.  also note we will also call whatever
647          * timer_interrupt() will do, though all we care about is just
648          * self_ipi/interrupting. */
649         set_core_timer(usec);
650         cpu_halt();
651
652         return 0;
653 }
654
655 /************** Platform Specific Syscalls **************/
656
657 //Read a buffer over the serial port
658 static ssize_t sys_serial_read(env_t* e, char *DANGEROUS _buf, size_t len)
659 {
660         if (len == 0)
661                 return 0;
662
663         #ifdef __CONFIG_SERIAL_IO__
664             char *COUNT(len) buf = user_mem_assert(e, _buf, len, PTE_USER_RO);
665                 size_t bytes_read = 0;
666                 int c;
667                 while((c = serial_read_byte()) != -1) {
668                         buf[bytes_read++] = (uint8_t)c;
669                         if(bytes_read == len) break;
670                 }
671                 return (ssize_t)bytes_read;
672         #else
673                 return -EINVAL;
674         #endif
675 }
676
677 //Write a buffer over the serial port
678 static ssize_t sys_serial_write(env_t* e, const char *DANGEROUS buf, size_t len)
679 {
680         if (len == 0)
681                 return 0;
682         #ifdef __CONFIG_SERIAL_IO__
683                 char *COUNT(len) _buf = user_mem_assert(e, buf, len, PTE_USER_RO);
684                 for(int i =0; i<len; i++)
685                         serial_send_byte(buf[i]);
686                 return (ssize_t)len;
687         #else
688                 return -EINVAL;
689         #endif
690 }
691
692 #ifdef __CONFIG_NETWORKING__
693 // This is not a syscall we want. Its hacky. Here just for syscall stuff until get a stack.
694 static ssize_t sys_eth_read(env_t* e, char *DANGEROUS buf)
695 {
696         if (eth_up) {
697
698                 uint32_t len;
699                 char *ptr;
700
701                 spin_lock(&packet_buffers_lock);
702
703                 if (num_packet_buffers == 0) {
704                         spin_unlock(&packet_buffers_lock);
705                         return 0;
706                 }
707
708                 ptr = packet_buffers[packet_buffers_head];
709                 len = packet_buffers_sizes[packet_buffers_head];
710
711                 num_packet_buffers--;
712                 packet_buffers_head = (packet_buffers_head + 1) % MAX_PACKET_BUFFERS;
713
714                 spin_unlock(&packet_buffers_lock);
715
716                 char* _buf = user_mem_assert(e, buf, len, PTE_U);
717
718                 memcpy(_buf, ptr, len);
719
720                 kfree(ptr);
721
722                 return len;
723         }
724         else
725                 return -EINVAL;
726 }
727
728 // This is not a syscall we want. Its hacky. Here just for syscall stuff until get a stack.
729 static ssize_t sys_eth_write(env_t* e, const char *DANGEROUS buf, size_t len)
730 {
731         if (eth_up) {
732
733                 if (len == 0)
734                         return 0;
735
736                 // HACK TO BYPASS HACK
737                 int just_sent = send_frame(buf, len);
738
739                 if (just_sent < 0) {
740                         printk("Packet send fail\n");
741                         return 0;
742                 }
743
744                 return just_sent;
745
746                 // END OF RECURSIVE HACK
747 /*
748                 char *COUNT(len) _buf = user_mem_assert(e, buf, len, PTE_U);
749                 int total_sent = 0;
750                 int just_sent = 0;
751                 int cur_packet_len = 0;
752                 while (total_sent != len) {
753                         cur_packet_len = ((len - total_sent) > MTU) ? MTU : (len - total_sent);
754                         char dest_mac[6] = APPSERVER_MAC_ADDRESS;
755                         char* wrap_buffer = eth_wrap(_buf + total_sent, cur_packet_len, device_mac, dest_mac, APPSERVER_PORT);
756                         just_sent = send_frame(wrap_buffer, cur_packet_len + sizeof(struct ETH_Header));
757
758                         if (just_sent < 0)
759                                 return 0; // This should be an error code of its own
760
761                         if (wrap_buffer)
762                                 kfree(wrap_buffer);
763
764                         total_sent += cur_packet_len;
765                 }
766
767                 return (ssize_t)len;
768 */
769         }
770         else
771                 return -EINVAL;
772 }
773
774 static ssize_t sys_eth_get_mac_addr(env_t* e, char *DANGEROUS buf) 
775 {
776         if (eth_up) {
777                 for (int i = 0; i < 6; i++)
778                         buf[i] = device_mac[i];
779                 return 0;
780         }
781         else
782                 return -EINVAL;
783 }
784
785 static int sys_eth_recv_check(env_t* e) 
786 {
787         if (num_packet_buffers != 0) 
788                 return 1;
789         else
790                 return 0;
791 }
792
793 #endif // Network
794
795 // Syscalls below here are serviced by the appserver for now.
796 #define ufe(which,a0,a1,a2,a3) \
797         frontend_syscall_errno(p,APPSERVER_SYSCALL_##which,\
798                            (int)(a0),(int)(a1),(int)(a2),(int)(a3))
799
800 intreg_t sys_write(struct proc* p, int fd, const void* buf, int len)
801 {
802         int ret = 0;
803         void* kbuf = user_memdup_errno(p,buf,len);
804         if(kbuf == NULL)
805                 return -1;
806 #ifndef __CONFIG_APPSERVER__
807         /* Catch a common usage of stderr */
808         if (fd == 2) {
809                 ((char*)kbuf)[len-1] = 0;
810                 printk("[stderr]: %s\n", kbuf);
811                 ret = len;
812         } else { // but warn/panic otherwise in ufe()
813                 ret = ufe(write, fd, PADDR(kbuf), len, 0);
814         }
815 #else
816         ret = ufe(write, fd, PADDR(kbuf), len, 0);
817 #endif
818         user_memdup_free(p,kbuf);
819         return ret;
820 }
821
822 intreg_t sys_read(struct proc* p, int fd, void* buf, int len)
823 {
824         void* kbuf = kmalloc_errno(len);
825         if(kbuf == NULL)
826                 return -1;
827         int ret = ufe(read,fd,PADDR(kbuf),len,0);
828         if(ret != -1 && memcpy_to_user_errno(p,buf,kbuf,len))
829                 ret = -1;
830         user_memdup_free(p,kbuf);
831         return ret;
832 }
833
834 intreg_t sys_pwrite(struct proc* p, int fd, const void* buf, int len, int offset)
835 {
836         void* kbuf = user_memdup_errno(p,buf,len);
837         if(kbuf == NULL)
838                 return -1;
839         int ret = ufe(pwrite,fd,PADDR(kbuf),len,offset);
840         user_memdup_free(p,kbuf);
841         return ret;
842 }
843
844 intreg_t sys_pread(struct proc* p, int fd, void* buf, int len, int offset)
845 {
846         void* kbuf = kmalloc_errno(len);
847         if(kbuf == NULL)
848                 return -1;
849         int ret = ufe(pread,fd,PADDR(kbuf),len,offset);
850         if(ret != -1 && memcpy_to_user_errno(p,buf,kbuf,len))
851                 ret = -1;
852         user_memdup_free(p,kbuf);
853         return ret;
854 }
855
856 intreg_t sys_open(struct proc* p, const char* path, int oflag, int mode)
857 {
858         printd("File Open, p: %p, path: %s, oflag: %d, mode: 0x%x\n", p, path, oflag, mode);
859         char* fn = user_strdup_errno(p,path,PGSIZE);
860         if(fn == NULL) {
861                 printd("File Open, user_strdup_errno failed\n");
862                 return -1;
863         }
864         printd("File Open, About to open\n");
865         int ret = ufe(open,PADDR(fn),oflag,mode,0);
866         printd("File Open, res=%d\n", ret);
867         user_memdup_free(p,fn);
868         return ret;
869 }
870 intreg_t sys_close(struct proc* p, int fd)
871 {
872         return ufe(close,fd,0,0,0);
873 }
874
875 #define NEWLIB_STAT_SIZE 64
876 intreg_t sys_fstat(struct proc* p, int fd, void* buf)
877 {
878         int *kbuf = kmalloc(NEWLIB_STAT_SIZE, 0);
879         int ret = ufe(fstat,fd,PADDR(kbuf),0,0);
880         if(ret != -1 && memcpy_to_user_errno(p,buf,kbuf,NEWLIB_STAT_SIZE))
881                 ret = -1;
882         kfree(kbuf);
883         return ret;
884 }
885
886 intreg_t sys_stat(struct proc* p, const char* path, void* buf)
887 {
888         char* fn = user_strdup_errno(p,path,PGSIZE);
889         if(fn == NULL)
890                 return -1;
891
892         int *kbuf = kmalloc(NEWLIB_STAT_SIZE, 0);
893         int ret = ufe(stat,PADDR(fn),PADDR(kbuf),0,0);
894         if(ret != -1 && memcpy_to_user_errno(p,buf,kbuf,NEWLIB_STAT_SIZE))
895                 ret = -1;
896
897         user_memdup_free(p,fn);
898         kfree(kbuf);
899         return ret;
900 }
901
902 intreg_t sys_lstat(struct proc* p, const char* path, void* buf)
903 {
904         char* fn = user_strdup_errno(p,path,PGSIZE);
905         if(fn == NULL)
906                 return -1;
907
908         int *kbuf = kmalloc(NEWLIB_STAT_SIZE, 0);
909         int ret = ufe(lstat,PADDR(fn),PADDR(kbuf),0,0);
910         if(ret != -1 && memcpy_to_user_errno(p,buf,kbuf,NEWLIB_STAT_SIZE))
911                 ret = -1;
912
913         user_memdup_free(p,fn);
914         kfree(kbuf);
915         return ret;
916 }
917
918 intreg_t sys_fcntl(struct proc* p, int fd, int cmd, int arg)
919 {
920         return ufe(fcntl,fd,cmd,arg,0);
921 }
922
923 intreg_t sys_access(struct proc* p, const char* path, int type)
924 {
925         char* fn = user_strdup_errno(p,path,PGSIZE);
926         if(fn == NULL)
927                 return -1;
928         int ret = ufe(access,PADDR(fn),type,0,0);
929         user_memdup_free(p,fn);
930         return ret;
931 }
932
933 intreg_t sys_umask(struct proc* p, int mask)
934 {
935         return ufe(umask,mask,0,0,0);
936 }
937
938 intreg_t sys_chmod(struct proc* p, const char* path, int mode)
939 {
940         char* fn = user_strdup_errno(p,path,PGSIZE);
941         if(fn == NULL)
942                 return -1;
943         int ret = ufe(chmod,PADDR(fn),mode,0,0);
944         user_memdup_free(p,fn);
945         return ret;
946 }
947
948 intreg_t sys_lseek(struct proc* p, int fd, int offset, int whence)
949 {
950         return ufe(lseek,fd,offset,whence,0);
951 }
952
953 intreg_t sys_link(struct proc* p, const char* _old, const char* _new)
954 {
955         char* oldpath = user_strdup_errno(p,_old,PGSIZE);
956         if(oldpath == NULL)
957                 return -1;
958
959         char* newpath = user_strdup_errno(p,_new,PGSIZE);
960         if(newpath == NULL)
961         {
962                 user_memdup_free(p,oldpath);
963                 return -1;
964         }
965
966         int ret = ufe(link,PADDR(oldpath),PADDR(newpath),0,0);
967         user_memdup_free(p,oldpath);
968         user_memdup_free(p,newpath);
969         return ret;
970 }
971
972 intreg_t sys_unlink(struct proc* p, const char* path)
973 {
974         char* fn = user_strdup_errno(p,path,PGSIZE);
975         if(fn == NULL)
976                 return -1;
977         int ret = ufe(unlink,PADDR(fn),0,0,0);
978         user_memdup_free(p,fn);
979         return ret;
980 }
981
982 intreg_t sys_chdir(struct proc* p, const char* path)
983 {
984         char* fn = user_strdup_errno(p,path,PGSIZE);
985         if(fn == NULL)
986                 return -1;
987         int ret = ufe(chdir,PADDR(fn),0,0,0);
988         user_memdup_free(p,fn);
989         return ret;
990 }
991
992 intreg_t sys_getcwd(struct proc* p, char* pwd, int size)
993 {
994         void* kbuf = kmalloc_errno(size);
995         if(kbuf == NULL)
996                 return -1;
997         int ret = ufe(read,PADDR(kbuf),size,0,0);
998         if(ret != -1 && memcpy_to_user_errno(p,pwd,kbuf,strnlen(kbuf,size)))
999                 ret = -1;
1000         user_memdup_free(p,kbuf);
1001         return ret;
1002 }
1003
1004 intreg_t sys_gettimeofday(struct proc* p, int* buf)
1005 {
1006         static spinlock_t gtod_lock = SPINLOCK_INITIALIZER;
1007         static int t0 = 0;
1008
1009         spin_lock(&gtod_lock);
1010         if(t0 == 0)
1011
1012 #if (defined __CONFIG_APPSERVER__)
1013         t0 = ufe(time,0,0,0,0);
1014 #else
1015         // Nanwan's birthday, bitches!!
1016         t0 = 1242129600;
1017 #endif 
1018         spin_unlock(&gtod_lock);
1019
1020         long long dt = read_tsc();
1021         int kbuf[2] = {t0+dt/system_timing.tsc_freq,
1022             (dt%system_timing.tsc_freq)*1000000/system_timing.tsc_freq};
1023
1024         return memcpy_to_user_errno(p,buf,kbuf,sizeof(kbuf));
1025 }
1026
1027 #define SIZEOF_STRUCT_TERMIOS 60
1028 intreg_t sys_tcgetattr(struct proc* p, int fd, void* termios_p)
1029 {
1030         int* kbuf = kmalloc(SIZEOF_STRUCT_TERMIOS,0);
1031         int ret = ufe(tcgetattr,fd,PADDR(kbuf),0,0);
1032         if(ret != -1 && memcpy_to_user_errno(p,termios_p,kbuf,SIZEOF_STRUCT_TERMIOS))
1033                 ret = -1;
1034         kfree(kbuf);
1035         return ret;
1036 }
1037
1038 intreg_t sys_tcsetattr(struct proc* p, int fd, int optional_actions, const void* termios_p)
1039 {
1040         void* kbuf = user_memdup_errno(p,termios_p,SIZEOF_STRUCT_TERMIOS);
1041         if(kbuf == NULL)
1042                 return -1;
1043         int ret = ufe(tcsetattr,fd,optional_actions,PADDR(kbuf),0);
1044         user_memdup_free(p,kbuf);
1045         return ret;
1046 }
1047
1048 /************** Syscall Invokation **************/
1049
1050 /* Executes the given syscall.
1051  *
1052  * Note tf is passed in, which points to the tf of the context on the kernel
1053  * stack.  If any syscall needs to block, it needs to save this info, as well as
1054  * any silly state.
1055  *
1056  * TODO: Build a dispatch table instead of switching on the syscallno
1057  * Dispatches to the correct kernel function, passing the arguments.
1058  */
1059 intreg_t syscall(struct proc *p, uintreg_t syscallno, uintreg_t a1,
1060                  uintreg_t a2, uintreg_t a3, uintreg_t a4, uintreg_t a5)
1061 {
1062         // Initialize the return value and error code returned to 0
1063         proc_set_syscall_retval(current_tf, 0);
1064         set_errno(current_tf,0);
1065
1066         typedef intreg_t (*syscall_t)(struct proc*,uintreg_t,uintreg_t,
1067                                       uintreg_t,uintreg_t,uintreg_t);
1068
1069         const static syscall_t syscall_table[] = {
1070                 [SYS_null] = (syscall_t)sys_null,
1071                 [SYS_cache_buster] = (syscall_t)sys_cache_buster,
1072                 [SYS_cache_invalidate] = (syscall_t)sys_cache_invalidate,
1073                 [SYS_reboot] = (syscall_t)reboot,
1074                 [SYS_cputs] = (syscall_t)sys_cputs,
1075                 [SYS_cgetc] = (syscall_t)sys_cgetc,
1076                 [SYS_getcpuid] = (syscall_t)sys_getcpuid,
1077                 [SYS_getvcoreid] = (syscall_t)sys_getvcoreid,
1078                 [SYS_getpid] = (syscall_t)sys_getpid,
1079                 [SYS_proc_create] = (syscall_t)sys_proc_create,
1080                 [SYS_proc_run] = (syscall_t)sys_proc_run,
1081                 [SYS_proc_destroy] = (syscall_t)sys_proc_destroy,
1082                 [SYS_yield] = (syscall_t)sys_proc_yield,
1083                 [SYS_run_binary] = (syscall_t)sys_run_binary,
1084                 [SYS_fork] = (syscall_t)sys_fork,
1085                 [SYS_exec] = (syscall_t)sys_exec,
1086                 [SYS_trywait] = (syscall_t)sys_trywait,
1087                 [SYS_mmap] = (syscall_t)sys_mmap,
1088                 [SYS_munmap] = (syscall_t)sys_munmap,
1089                 [SYS_mprotect] = (syscall_t)sys_mprotect,
1090                 [SYS_brk] = (syscall_t)sys_brk,
1091                 [SYS_shared_page_alloc] = (syscall_t)sys_shared_page_alloc,
1092                 [SYS_shared_page_free] = (syscall_t)sys_shared_page_free,
1093                 [SYS_resource_req] = (syscall_t)resource_req,
1094                 [SYS_notify] = (syscall_t)sys_notify,
1095                 [SYS_self_notify] = (syscall_t)sys_self_notify,
1096                 [SYS_halt_core] = (syscall_t)sys_halt_core,
1097         #ifdef __CONFIG_SERIAL_IO__
1098                 [SYS_serial_read] = (syscall_t)sys_serial_read,
1099                 [SYS_serial_write] = (syscall_t)sys_serial_write,
1100         #endif
1101         #ifdef __CONFIG_NETWORKING__
1102                 [SYS_eth_read] = (syscall_t)sys_eth_read,
1103                 [SYS_eth_write] = (syscall_t)sys_eth_write,
1104                 [SYS_eth_get_mac_addr] = (syscall_t)sys_eth_get_mac_addr,
1105                 [SYS_eth_recv_check] = (syscall_t)sys_eth_recv_check,
1106         #endif
1107                 // Syscalls serviced by the appserver for now.
1108                 [SYS_read] = (syscall_t)sys_read,
1109                 [SYS_write] = (syscall_t)sys_write,
1110                 [SYS_open] = (syscall_t)sys_open,
1111                 [SYS_close] = (syscall_t)sys_close,
1112                 [SYS_fstat] = (syscall_t)sys_fstat,
1113                 [SYS_stat] = (syscall_t)sys_stat,
1114                 [SYS_lstat] = (syscall_t)sys_lstat,
1115                 [SYS_fcntl] = (syscall_t)sys_fcntl,
1116                 [SYS_access] = (syscall_t)sys_access,
1117                 [SYS_umask] = (syscall_t)sys_umask,
1118                 [SYS_chmod] = (syscall_t)sys_chmod,
1119                 [SYS_lseek] = (syscall_t)sys_lseek,
1120                 [SYS_link] = (syscall_t)sys_link,
1121                 [SYS_unlink] = (syscall_t)sys_unlink,
1122                 [SYS_chdir] = (syscall_t)sys_chdir,
1123                 [SYS_getcwd] = (syscall_t)sys_getcwd,
1124                 [SYS_gettimeofday] = (syscall_t)sys_gettimeofday,
1125                 [SYS_tcgetattr] = (syscall_t)sys_tcgetattr,
1126                 [SYS_tcsetattr] = (syscall_t)sys_tcsetattr
1127         };
1128
1129         const int max_syscall = sizeof(syscall_table)/sizeof(syscall_table[0]);
1130
1131         uint32_t coreid, vcoreid;
1132         if (systrace_flags & SYSTRACE_ON) {
1133                 if ((systrace_flags & SYSTRACE_ALLPROC) || (proc_is_traced(p))) {
1134                         coreid = core_id();
1135                         vcoreid = proc_get_vcoreid(p, core_id());
1136                         if (systrace_flags & SYSTRACE_LOUD) {
1137                                 printk("[%16llu] Syscall %d for proc %d on core %d, vcore %d\n",
1138                                        read_tsc(), syscallno, p->pid, coreid, vcoreid);
1139                         } else {
1140                                 struct systrace_record *trace;
1141                                 unsigned int idx, new_idx;
1142                                 do {
1143                                         idx = systrace_bufidx;
1144                                         new_idx = (idx + 1) % systrace_bufsize;
1145                                 } while (!atomic_comp_swap(&systrace_bufidx, idx, new_idx));
1146                                 trace = &systrace_buffer[idx];
1147                                 trace->timestamp = read_tsc();
1148                                 trace->syscallno = syscallno;
1149                                 trace->pid = p->pid;
1150                                 trace->coreid = coreid;
1151                                 trace->vcoreid = vcoreid;
1152                         }
1153                 }
1154         }
1155         //printk("Incoming syscall on core: %d number: %d\n    a1: %x\n   "
1156         //       " a2: %x\n    a3: %x\n    a4: %x\n    a5: %x\n", core_id(),
1157         //       syscallno, a1, a2, a3, a4, a5);
1158
1159         if(syscallno > max_syscall || syscall_table[syscallno] == NULL)
1160                 panic("Invalid syscall number %d for proc %x!", syscallno, *p);
1161
1162         return syscall_table[syscallno](p,a1,a2,a3,a4,a5);
1163 }
1164
1165 intreg_t syscall_async(struct proc *p, syscall_req_t *call)
1166 {
1167         return syscall(p, call->num, call->args[0], call->args[1],
1168                        call->args[2], call->args[3], call->args[4]);
1169 }
1170
1171 /* You should already have a refcnt'd ref to p before calling this */
1172 intreg_t process_generic_syscalls(struct proc *p, size_t max)
1173 {
1174         size_t count = 0;
1175         syscall_back_ring_t* sysbr = &p->syscallbackring;
1176
1177         /* make sure the proc is still alive, and keep it from dying from under us
1178          * incref will return ESUCCESS on success.  This might need some thought
1179          * regarding when the incref should have happened (like by whoever passed us
1180          * the *p). */
1181         // TODO: ought to be unnecessary, if you called this right, kept here for
1182         // now in case anyone actually uses the ARSCs.
1183         proc_incref(p, 1);
1184
1185         // max is the most we'll process.  max = 0 means do as many as possible
1186         while (RING_HAS_UNCONSUMED_REQUESTS(sysbr) && ((!max)||(count < max)) ) {
1187                 if (!count) {
1188                         // ASSUME: one queue per process
1189                         // only switch cr3 for the very first request for this queue
1190                         // need to switch to the right context, so we can handle the user pointer
1191                         // that points to a data payload of the syscall
1192                         lcr3(p->env_cr3);
1193                 }
1194                 count++;
1195                 //printk("DEBUG PRE: sring->req_prod: %d, sring->rsp_prod: %d\n",
1196                 //         sysbr->sring->req_prod, sysbr->sring->rsp_prod);
1197                 // might want to think about 0-ing this out, if we aren't
1198                 // going to explicitly fill in all fields
1199                 syscall_rsp_t rsp;
1200                 // this assumes we get our answer immediately for the syscall.
1201                 syscall_req_t* req = RING_GET_REQUEST(sysbr, ++(sysbr->req_cons));
1202                 rsp.retval = syscall_async(p, req);
1203                 // write response into the slot it came from
1204                 memcpy(req, &rsp, sizeof(syscall_rsp_t));
1205                 // update our counter for what we've produced (assumes we went in order!)
1206                 (sysbr->rsp_prod_pvt)++;
1207                 RING_PUSH_RESPONSES(sysbr);
1208                 //printk("DEBUG POST: sring->req_prod: %d, sring->rsp_prod: %d\n",
1209                 //         sysbr->sring->req_prod, sysbr->sring->rsp_prod);
1210         }
1211         // load sane page tables (and don't rely on decref to do it for you).
1212         lcr3(boot_cr3);
1213         proc_decref(p, 1);
1214         return (intreg_t)count;
1215 }
1216
1217 /* Syscall tracing */
1218 static void __init_systrace(void)
1219 {
1220         systrace_buffer = kmalloc(MAX_SYSTRACES*sizeof(struct systrace_record), 0);
1221         if (!systrace_buffer)
1222                 panic("Unable to alloc a trace buffer\n");
1223         systrace_bufidx = 0;
1224         systrace_bufsize = MAX_SYSTRACES;
1225         /* Note we never free the buffer - it's around forever.  Feel free to change
1226          * this if you want to change the size or something dynamically. */
1227 }
1228
1229 /* If you call this while it is running, it will change the mode */
1230 void systrace_start(bool silent)
1231 {
1232         static bool init = FALSE;
1233         spin_lock_irqsave(&systrace_lock);
1234         if (!init) {
1235                 __init_systrace();
1236                 init = TRUE;
1237         }
1238         systrace_flags = silent ? SYSTRACE_ON : SYSTRACE_ON | SYSTRACE_LOUD; 
1239         spin_unlock_irqsave(&systrace_lock);
1240 }
1241
1242 int systrace_reg(bool all, struct proc *p)
1243 {
1244         int retval = 0;
1245         spin_lock_irqsave(&systrace_lock);
1246         if (all) {
1247                 printk("Tracing syscalls for all processes\n");
1248                 systrace_flags |= SYSTRACE_ALLPROC;
1249                 retval = 0;
1250         } else {
1251                 for (int i = 0; i < MAX_NUM_TRACED; i++) {
1252                         if (!systrace_procs[i]) {
1253                                 printk("Tracing syscalls for process %d\n", p->pid);
1254                                 systrace_procs[i] = p;
1255                                 retval = 0;
1256                                 break;
1257                         }
1258                 }
1259         }
1260         spin_unlock_irqsave(&systrace_lock);
1261         return retval;
1262 }
1263
1264 void systrace_stop(void)
1265 {
1266         spin_lock_irqsave(&systrace_lock);
1267         systrace_flags = 0;
1268         for (int i = 0; i < MAX_NUM_TRACED; i++)
1269                 systrace_procs[i] = 0;
1270         spin_unlock_irqsave(&systrace_lock);
1271 }
1272
1273 /* If you registered a process specifically, then you need to dereg it
1274  * specifically.  Or just fully stop, which will do it for all. */
1275 int systrace_dereg(bool all, struct proc *p)
1276 {
1277         spin_lock_irqsave(&systrace_lock);
1278         if (all) {
1279                 printk("No longer tracing syscalls for all processes.\n");
1280                 systrace_flags &= ~SYSTRACE_ALLPROC;
1281         } else {
1282                 for (int i = 0; i < MAX_NUM_TRACED; i++) {
1283                         if (systrace_procs[i] == p) {
1284                                 systrace_procs[i] = 0;
1285                                 printk("No longer tracing syscalls for process %d\n", p->pid);
1286                         }
1287                 }
1288         }
1289         spin_unlock_irqsave(&systrace_lock);
1290         return 0;
1291 }
1292
1293 /* Regardless of locking, someone could be writing into the buffer */
1294 void systrace_print(bool all, struct proc *p)
1295 {
1296         spin_lock_irqsave(&systrace_lock);
1297         /* if you want to be clever, you could make this start from the earliest
1298          * timestamp and loop around.  Careful of concurrent writes. */
1299         for (int i = 0; i < systrace_bufsize; i++)
1300                 if (systrace_buffer[i].timestamp)
1301                         printk("[%16llu] Syscall %d for proc %d on core %d, vcore %d\n",
1302                                systrace_buffer[i].timestamp,
1303                                systrace_buffer[i].syscallno,
1304                                systrace_buffer[i].pid,
1305                                systrace_buffer[i].coreid,
1306                                systrace_buffer[i].vcoreid);
1307         spin_unlock_irqsave(&systrace_lock);
1308 }
1309
1310 void systrace_clear_buffer(void)
1311 {
1312         spin_lock_irqsave(&systrace_lock);
1313         memset(systrace_buffer, 0, sizeof(struct systrace_record)*MAX_NUM_TRACED);
1314         spin_unlock_irqsave(&systrace_lock);
1315 }