Provisioning syscall and helper program (XCC)
[akaros.git] / user / parlib / syscall.c
1 // System call stubs.
2
3 #include <parlib.h>
4 #include <vcore.h>
5
6 int sys_proc_destroy(int pid, int exitcode)
7 {
8         return ros_syscall(SYS_proc_destroy, pid, exitcode, 0, 0, 0, 0);
9 }
10
11 int sys_getpid(void)
12 {
13          return ros_syscall(SYS_getpid, 0, 0, 0, 0, 0, 0);
14 }
15
16 size_t sys_getpcoreid(void)
17 {
18          return ros_syscall(SYS_getpcoreid, 0, 0, 0, 0, 0, 0);
19 }
20
21 ssize_t sys_cputs(const uint8_t *s, size_t len)
22 {
23     return ros_syscall(SYS_cputs, s,  len, 0, 0, 0, 0);
24 }
25
26 uint16_t sys_cgetc(void)
27 {
28     return ros_syscall(SYS_cgetc, 0, 0, 0, 0, 0, 0);
29 }
30
31 int sys_null(void)
32 {
33     return ros_syscall(SYS_null, 0, 0, 0, 0, 0, 0);
34 }
35
36 ssize_t sys_shared_page_alloc(void** addr, pid_t p2, 
37                               int p1_flags, int p2_flags
38                              ) 
39 {
40         return ros_syscall(SYS_shared_page_alloc, addr, 
41                        p2, p1_flags, p2_flags, 0, 0);
42 }
43
44 ssize_t sys_shared_page_free(void* addr, pid_t p2) 
45 {
46         return ros_syscall(SYS_shared_page_free, addr, p2, 0, 0, 0, 0);
47 }
48
49 //Write a buffer over the serial port
50 ssize_t sys_serial_write(void* buf, size_t len) 
51 {
52         return ros_syscall(SYS_serial_write, buf, len, 0, 0, 0, 0);
53 }
54
55 //Read a buffer over the serial port
56 ssize_t sys_serial_read(void* buf, size_t len) 
57 {
58         return ros_syscall(SYS_serial_read, buf, len, 0, 0, 0, 0);
59 }
60
61 //Write a buffer over ethernet
62 ssize_t sys_eth_write(void* buf, size_t len) 
63 {
64         if (len == 0)
65                 return 0;
66         
67         return ros_syscall(SYS_eth_write, buf, len, 0, 0, 0, 0);
68 }
69
70 //Read a buffer via ethernet
71 ssize_t sys_eth_read(void* buf, size_t len) 
72 {
73         if (len == 0)
74                 return 0;
75                 
76         return ros_syscall(SYS_eth_read, buf, len, 0, 0, 0, 0);
77 }
78
79 void sys_reboot(void)
80 {
81         ros_syscall(SYS_reboot, 0, 0, 0, 0, 0, 0);
82 }
83
84 void sys_yield(bool being_nice)
85 {
86         ros_syscall(SYS_yield, being_nice, 0, 0, 0, 0, 0);
87 }
88
89 int sys_proc_create(char *path, size_t path_l, char *argv[], char *envp[])
90 {
91         struct procinfo pi;
92         if (procinfo_pack_args(&pi, argv, envp)) {
93                 errno = ENOMEM;
94                 return -1;
95         }
96         return ros_syscall(SYS_proc_create, path, path_l, &pi, 0, 0, 0);
97 }
98
99 int sys_proc_run(int pid)
100 {
101         return ros_syscall(SYS_proc_run, pid, 0, 0, 0, 0, 0);
102 }
103
104 void *CT(length) sys_mmap(void *SNT addr, size_t length, int prot, int flags,
105                           int fd, size_t offset)
106 {
107         return (void*)ros_syscall(SYS_mmap, addr, length, prot, flags, fd, offset);
108 }
109
110 int sys_provision(int pid, unsigned int res_type, long res_val)
111 {
112         return ros_syscall(SYS_provision, pid, res_type, res_val, 0, 0, 0);
113 }
114
115 int sys_notify(int pid, unsigned int ev_type, struct event_msg *u_msg)
116 {
117         return ros_syscall(SYS_notify, pid, ev_type, u_msg, 0, 0, 0);
118 }
119
120 int sys_self_notify(uint32_t vcoreid, unsigned int ev_type,
121                     struct event_msg *u_msg, bool priv)
122 {
123         return ros_syscall(SYS_self_notify, vcoreid, ev_type, u_msg, priv, 0, 0);
124 }
125
126 int sys_halt_core(unsigned int usec)
127 {
128         return ros_syscall(SYS_halt_core, usec, 0, 0, 0, 0, 0);
129 }
130
131 void* sys_init_arsc()
132 {
133         return (void*)ros_syscall(SYS_init_arsc, 0, 0, 0, 0, 0, 0);
134 }
135
136 int sys_block(unsigned int usec)
137 {
138         return ros_syscall(SYS_block, usec, 0, 0, 0, 0, 0);
139 }
140
141 /* enable_my_notif tells the kernel whether or not it is okay to turn on notifs
142  * when our calling vcore 'yields'.  This controls whether or not the vcore will
143  * get started from vcore_entry() or not, and whether or not remote cores need
144  * to sys_change_vcore to preempt-recover the calling vcore.  Only set this to
145  * FALSE if you are unable to handle starting fresh at vcore_entry().  One
146  * example of this is in mcs_pdr_locks.
147  *
148  * Will return:
149  *              0 if we successfully changed to the target vcore.
150  *              -EBUSY if the target vcore is already mapped (a good kind of failure)
151  *              -EAGAIN if we failed for some other reason and need to try again.  For
152  *              example, the caller could be preempted, and we never even attempted to
153  *              change.
154  *              -EINVAL some userspace bug */
155 int sys_change_vcore(uint32_t vcoreid, bool enable_my_notif)
156 {
157         /* Since we might be asking to start up on a fresh stack (if
158          * enable_my_notif), we need to use some non-stack memory for the struct
159          * sysc.  Our vcore could get restarted before the syscall finishes (after
160          * unlocking the proc, before finish_sysc()), and the act of finishing would
161          * write onto our stack.  Thus we use the per-vcore struct. */
162         int flags;
163         /* Need to wait while a previous syscall is not done or locked.  Since this
164          * should only be called from VC ctx, we'll just spin.  Should be extremely
165          * rare.  Note flags is initialized to SC_DONE. */
166         do {
167                 cpu_relax();
168                 flags = atomic_read(&__vcore_one_sysc.flags);
169         } while (!(flags & SC_DONE) || flags & SC_K_LOCK);
170         __vcore_one_sysc.num = SYS_change_vcore;
171         __vcore_one_sysc.arg0 = vcoreid;
172         __vcore_one_sysc.arg1 = enable_my_notif;
173         /* keep in sync with glibc sysdeps/ros/syscall.c */
174         __ros_arch_syscall((long)&__vcore_one_sysc, 1);
175         /* If we returned, either we wanted to (!enable_my_notif) or we failed.
176          * Need to wait til the sysc is finished to find out why.  Again, its okay
177          * to just spin. */
178         do {
179                 cpu_relax();
180                 flags = atomic_read(&__vcore_one_sysc.flags);
181         } while (!(flags & SC_DONE) || flags & SC_K_LOCK);
182         return __vcore_one_sysc.retval;
183 }
184
185 int sys_change_to_m(void)
186 {
187         return ros_syscall(SYS_change_to_m, 0, 0, 0, 0, 0, 0);
188 }
189
190 int sys_poke_ksched(int res_type)
191 {
192         return ros_syscall(SYS_poke_ksched, res_type, 0, 0, 0, 0, 0);
193 }