Removed references to intptr_t
[akaros.git] / kern / src / frontend.c
1 #ifdef __SHARC__
2 #pragma nosharc
3 #endif
4
5 #ifdef __DEPUTY__
6 #pragma nodeputy
7 #endif
8
9 #include <atomic.h>
10 #include <process.h>
11 #include <kmalloc.h>
12 #include <pmap.h>
13 #include <frontend.h>
14 #include <syscall.h>
15 #include <smp.h>
16
17 volatile int magic_mem[10];
18
19 void
20 frontend_proc_init(struct proc *SAFE p)
21 {
22         pid_t parent_id = p->ppid, id = p->pid;
23         int32_t errno;
24         if(frontend_syscall(parent_id,APPSERVER_SYSCALL_proc_init,id,0,0,0,&errno))
25                 panic("Front-end server couldn't initialize new process!");
26 }
27
28 void
29 frontend_proc_free(struct proc *SAFE p)
30 {
31         int32_t errno;
32         if(frontend_syscall(0,APPSERVER_SYSCALL_proc_free,p->pid,0,0,0,&errno))
33                 panic("Front-end server couldn't free process!");
34 }
35
36 void* user_memdup(struct proc* p, const void* va, int len)
37 {
38         void* kva = NULL;
39         if(len < 0 || (kva = kmalloc(len,0)) == NULL)
40                 return ERR_PTR(-ENOMEM);
41         if(memcpy_from_user(p,kva,va,len))
42         {
43                 kfree(kva);
44                 return ERR_PTR(-EINVAL);
45         }
46
47         return kva;
48 }
49
50 void* user_memdup_errno(struct proc* p, const void* va, int len)
51 {
52         void* kva = user_memdup(p,va,len);
53         if(IS_ERR(kva))
54         {
55                 set_errno(current_tf,-PTR_ERR(kva));
56                 return NULL;
57         }
58         return kva;
59 }
60
61 void user_memdup_free(struct proc* p, void* va)
62 {
63         kfree(va);
64 }
65
66 char* user_strdup(struct proc* p, const char* va0, int max)
67 {
68         max++;
69         char* kbuf = (char*)kmalloc(PGSIZE,0);
70         if(kbuf == NULL)
71                 return ERR_PTR(-ENOMEM);
72
73         int pos = 0, len = 0;
74         const char* va = va0;
75         while(max > 0 && len == 0)
76         {
77                 int thislen = MIN(PGSIZE-(uintptr_t)va%PGSIZE,max);
78                 if(memcpy_from_user(p,kbuf,va,thislen))
79                 {
80                         kfree(kbuf);
81                         return ERR_PTR(-EINVAL);
82                 }
83
84                 const char* nullterm = memchr(kbuf,0,thislen);
85                 if(nullterm)
86                         len = pos+(nullterm-kbuf)+1;
87
88                 pos += thislen;
89                 va += thislen;
90                 max -= thislen;
91         }
92
93         kfree(kbuf);
94         return len ? user_memdup(p,va0,len) : ERR_PTR(-EINVAL);
95 }
96
97 char* user_strdup_errno(struct proc* p, const char* va, int max)
98 {
99         void* kva = user_strdup(p,va,max);
100         if(IS_ERR(kva))
101         {
102                 set_errno(current_tf,-PTR_ERR(kva));
103                 return NULL;
104         }
105         return kva;
106 }
107
108 int memcpy_to_user_errno(struct proc* p, void* dst, const void* src,
109                                 int len)
110 {
111         if(memcpy_to_user(p,dst,src,len))
112         {
113                 set_errno(current_tf,EINVAL);
114                 return -1;
115         }
116         return 0;
117 }
118
119 void* kmalloc_errno(int len)
120 {
121         void* kva = NULL;
122         if(len < 0 || (kva = kmalloc(len,0)) == NULL)
123                 set_errno(current_tf,ENOMEM);
124         return kva;
125 }
126
127 error_t read_page(struct proc* p, int fd, physaddr_t pa, int pgoff)
128 {
129         int errno;
130         int ret = frontend_syscall(p->pid,APPSERVER_SYSCALL_pread,fd,
131                                 pa,PGSIZE,pgoff*PGSIZE,&errno);
132
133         if(ret >= 0)
134                 memset(KADDR(pa)+ret,0,PGSIZE-ret);
135         return ret;
136 }
137
138 error_t open_file(struct proc* p, const char* path, int oflag, int mode)
139 {
140         int errno;
141         return frontend_syscall(p->pid,APPSERVER_SYSCALL_open,PADDR(path),
142                                 oflag,mode,0,&errno);
143 }
144
145 error_t close_file(struct proc* p, int fd)
146 {
147         int errno;
148         return frontend_syscall(p->pid,APPSERVER_SYSCALL_close,fd,0,0,0,&errno);
149 }
150
151 int user_frontend_syscall(struct proc* p, int n, int a0, int a1, int a2, int a3)
152 {
153         int errno, ret = frontend_syscall(p->pid,n,a0,a1,a2,a3,&errno);
154         if(errno && p)
155                 set_errno(current_tf,errno);
156         return ret;
157 }
158
159 int32_t frontend_syscall(pid_t pid, int32_t syscall_num, 
160                          uint32_t arg0, uint32_t arg1, 
161                          uint32_t arg2, uint32_t arg3, int32_t* errno)
162 {
163         static spinlock_t lock = SPINLOCK_INITIALIZER;
164         int32_t ret;
165
166         // only one frontend request at a time.
167         // interrupts could try to do frontend requests,
168         // which would deadlock, so disable them
169         spin_lock_irqsave(&lock);
170
171         // write syscall into magic memory
172         magic_mem[7] = 0;
173         magic_mem[1] = syscall_num;
174         magic_mem[2] = arg0;
175         magic_mem[3] = arg1;
176         magic_mem[4] = arg2;
177         magic_mem[5] = arg3;
178         magic_mem[6] = pid;
179         magic_mem[0] = 0x80;
180
181         // wait for front-end response
182         while(magic_mem[7] == 0)
183                 ;
184
185         ret = magic_mem[1];
186         *errno = magic_mem[2];
187
188         spin_unlock_irqsave(&lock);
189
190         return ret;
191 }
192
193 int32_t frontend_nbputch(char ch)
194 {
195         static spinlock_t putch_lock = SPINLOCK_INITIALIZER;
196         spin_lock_irqsave(&putch_lock);
197
198         int ret = -1;
199         if(magic_mem[8] == 0)
200         {
201                 magic_mem[8] = (unsigned int)(unsigned char)ch;
202                 ret = 0;
203         }
204
205         spin_unlock_irqsave(&putch_lock);
206         return ret;
207 }
208
209 int32_t frontend_nbgetch()
210 {
211         static spinlock_t getch_lock = SPINLOCK_INITIALIZER;
212         spin_lock_irqsave(&getch_lock);
213
214         int result = -1;
215         if(magic_mem[9]) 
216         {
217                 result = magic_mem[9];
218                 magic_mem[9] = 0;
219         }
220
221         spin_unlock_irqsave(&getch_lock);
222         return result;
223 }
224
225 void __diediedie(trapframe_t* tf, uint32_t srcid, uint32_t code, uint32_t a1, uint32_t a2)
226 {
227         int32_t errno;
228         frontend_syscall(0,APPSERVER_SYSCALL_exit,(int)code,0,0,0,&errno);
229         while(1);
230 }
231
232 void appserver_die(int code)
233 {
234         int i;
235         for(i = 0; i < num_cpus; i++)
236                 if(i != core_id())
237                         while(send_active_message(i,(amr_t)&__diediedie,(void*)code,0,0));
238
239         // just in case.
240         __diediedie(0,0,code,0,0);
241 }