Async syscall handling
[akaros.git] / lib / syscall.c
1 // System call stubs.
2
3 #include <inc/syscall.h>
4 #include <inc/lib.h>
5 #include <inc/x86.h>
6
7 static inline uint32_t
8 syscall(int num, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5)
9 {
10         uint32_t ret;
11
12         // Generic system call: pass system call number in AX,
13         // up to five parameters in DX, CX, BX, DI, SI.
14         // Interrupt kernel with T_SYSCALL.
15         //
16         // The "volatile" tells the assembler not to optimize
17         // this instruction away just because we don't use the
18         // return value.
19         // 
20         // The last clause tells the assembler that this can
21         // potentially change the condition codes and arbitrary
22         // memory locations.
23
24         asm volatile("int %1\n"
25                 : "=a" (ret)
26                 : "i" (T_SYSCALL),
27                   "a" (num),
28                   "d" (a1),
29                   "c" (a2),
30                   "b" (a3),
31                   "D" (a4),
32                   "S" (a5)
33                 : "cc", "memory");
34         
35         return ret;
36 }
37
38 static inline error_t async_syscall(syscall_req_t *syscall)
39 {
40         // spin til there is room for our request.  ring size is currently 64.
41         while (RING_FULL(&sysfrontring))
42                 cpu_relax();
43         // req_prod_pvt comes in as the previously produced item.  need to
44         // increment to the next available spot, which is the one we'll work on.
45         syscall_req_t* req = RING_GET_REQUEST(&sysfrontring, ++(sysfrontring.req_prod_pvt));
46         memcpy(req, syscall, sizeof(syscall_req_t));
47         // push our updates to sysfrontring.req_prod_pvt
48         RING_PUSH_REQUESTS(&sysfrontring);
49         //cprintf("DEBUG: sring->req_prod: %d, sring->rsp_prod: %d\n", \
50                 sysfrontring.sring->req_prod, sysfrontring.sring->rsp_prod);
51         return 0;
52         // at some point, we need to listen for the responses.  pass back a
53         // reference of some sort, probably via a parameter.
54 }
55
56 void sys_cputs_async(const char *s, size_t len)
57 {
58         // could just hardcode 4 0's, will eventually wrap this marshaller anyway
59         syscall_req_t syscall = {SYS_cputs, 0, {(uint32_t)s, len, [2 ... (NUM_SYS_ARGS-1)] 0} };
60         async_syscall(&syscall);
61 }
62
63 void sys_null()
64 {
65         syscall(SYS_null,0,0,0,0,0);
66 }
67
68 void
69 sys_cputs(const char *s, size_t len)
70 {
71         syscall(SYS_cputs, (uint32_t) s, len, 0, 0, 0);
72 }
73
74 int
75 sys_cgetc(void)
76 {
77         return syscall(SYS_cgetc, 0, 0, 0, 0, 0);
78 }
79
80 int
81 sys_env_destroy(envid_t envid)
82 {
83         return syscall(SYS_env_destroy, envid, 0, 0, 0, 0);
84 }
85
86 envid_t
87 sys_getenvid(void)
88 {
89          return syscall(SYS_getenvid, 0, 0, 0, 0, 0);
90 }
91
92