Diff markup
001 001
002 002
003 003
004 004
005 005
006 006
007 007
008 008
009 009
010 010
011 011
012 012
013 013
014 014
015 015
016 016
017 017
018 #include <sos/thread.h> 018 #include <sos/thread.h>
019 #include <sos/kmalloc.h> 019 #include <sos/kmalloc.h>
020 #include <sos/klibc.h> 020 #include <sos/klibc.h>
021 #include <drivers/bochs.h> 021 #include <drivers/bochs.h>
022 #include <hwcore/paging.h> <<
023 #include <sos/physmem.h> <<
024 #include <sos/umem_vmm.h> <<
025 #include <drivers/zero.h> <<
026 #include <drivers/mem.h> <<
027 #include <sos/binfmt_elf32.h> <<
028 022
029 #include <hwcore/cpu_context.h> 023 #include <hwcore/cpu_context.h>
030 #include <sos/uaccess.h> 024 #include <sos/uaccess.h>
031 #include "syscall.h" 025 #include "syscall.h"
032 026
033 027
034 028
035 029
036 030
037 sos_ret_t sos_do_syscall(int syscall_id, 031 sos_ret_t sos_do_syscall(int syscall_id,
038 const struct sos_cpu_ 032 const struct sos_cpu_state *user_ctxt)
039 { 033 {
040 sos_ret_t retval; 034 sos_ret_t retval;
041 035
042 switch(syscall_id) 036 switch(syscall_id)
043 { 037 {
044 case SOS_SYSCALL_ID_EXIT: 038 case SOS_SYSCALL_ID_EXIT:
045 { 039 {
046 unsigned int status; 040 unsigned int status;
047 retval = sos_syscall_get1arg(user_ctxt 041 retval = sos_syscall_get1arg(user_ctxt, & status);
048 if (SOS_OK != retval) 042 if (SOS_OK != retval)
049 break; 043 break;
050 sos_thread_exit(); 044 sos_thread_exit();
051 retval = -SOS_EFATAL; 045 retval = -SOS_EFATAL;
052 } 046 }
053 break; 047 break;
054 <<
055 case SOS_SYSCALL_ID_FORK: <<
056 { <<
057 struct sos_thread *cur_thr, *new_thr; <<
058 struct sos_process *new_proc; <<
059 <<
060 cur_thr = sos_thread_get_current(); <<
061 <<
062 <<
063 new_proc = sos_process_create(NULL, TR <<
064 if (! new_proc) <<
065 { <<
066 retval = -SOS_ENOMEM; <<
067 break; <<
068 } <<
069 <<
070 <<
071 <<
072 <<
073 new_thr = <<
074 sos_duplicate_user_thread(NULL, new_ <<
075 cur_thr, <<
076 user_ctxt, <<
077 0); <<
078 if (! new_thr) <<
079 { <<
080 sos_process_unref(new_proc); <<
081 retval = -SOS_ENOMEM; <<
082 break; <<
083 } <<
084 <<
085 sos_process_unref(new_proc); <<
086 <<
087 <<
088 <<
089 <<
090 retval = (sos_ui32_t)new_proc; <<
091 } <<
092 break; <<
093 <<
094 case SOS_SYSCALL_ID_EXEC: <<
095 { <<
096 struct sos_thread *cur_thr, *new_thr; <<
097 struct sos_umem_vmm_as *new_as; <<
098 sos_uaddr_t user_str, ustack, start_ua <<
099 sos_size_t len; <<
100 char * str; <<
101 <<
102 cur_thr = sos_thread_get_current(); <<
103 <<
104 <<
105 if (sos_process_get_nb_threads(cur_thr <<
106 { <<
107 retval = -SOS_EBUSY; <<
108 break; <<
109 } <<
110 <<
111 <<
112 retval = sos_syscall_get2args(user_ctx <<
113 if (SOS_OK != retval) <<
114 break; <<
115 <<
116 <<
117 str = (char*)sos_kmalloc(len + 1, 0); <<
118 if (! str) <<
119 { <<
120 retval = -SOS_ENOMEM; <<
121 break; <<
122 } <<
123 retval = sos_strzcpy_from_user(str, us <<
124 if (retval < SOS_OK) <<
125 { <<
126 sos_kfree((sos_vaddr_t)str); <<
127 break; <<
128 } <<
129 <<
130 <<
131 new_as = sos_umem_vmm_create_empty_as( <<
132 if (! new_as) <<
133 { <<
134 sos_kfree((sos_vaddr_t)str); <<
135 retval = -SOS_ENOMEM; <<
136 break; <<
137 } <<
138 <<
139 <<
140 start_uaddr = sos_binfmt_elf32_map(new <<
141 if (start_uaddr == (sos_uaddr_t)NULL) <<
142 { <<
143 sos_umem_vmm_delete_as(new_as); <<
144 sos_kfree((sos_vaddr_t)str); <<
145 retval = -SOS_ENOENT; <<
146 break; <<
147 } <<
148 <<
149 <<
150 #define SOS_DEFAULT_USER_STACK_SIZE (8 << 20) <<
151 ustack = (SOS_PAGING_TOP_USER_ADDRESS <<
152 + 1; <<
153 retval = sos_dev_zero_map(new_as, &ust <<
154 SOS_VM_MAP_P <<
155 <<
156 if (SOS_OK != retval) <<
157 { <<
158 sos_umem_vmm_delete_as(new_as); <<
159 sos_kfree((sos_vaddr_t)str); <<
160 break; <<
161 } <<
162 <<
163 <<
164 new_thr = sos_create_user_thread(NULL, <<
165 cur_t <<
166 start <<
167 0, 0, <<
168 ustac <<
169 - 4 <<
170 SOS_S <<
171 if (! new_thr) <<
172 { <<
173 sos_umem_vmm_delete_as(new_as); <<
174 sos_kfree((sos_vaddr_t)str); <<
175 retval = -SOS_ENOMEM; <<
176 break; <<
177 } <<
178 <<
179 sos_process_set_name(cur_thr->process, <<
180 <<
181 <<
182 retval = sos_process_set_address_space <<
183 <<
184 if (SOS_OK != retval) <<
185 { <<
186 sos_umem_vmm_delete_as(new_as); <<
187 sos_kfree((sos_vaddr_t)str); <<
188 break; <<
189 } <<
190 <<
191 <<
192 sos_kfree((sos_vaddr_t)str); <<
193 sos_thread_exit(); <<
194 retval = -SOS_EFATAL; <<
195 } <<
196 break; <<
197 <<
198 case SOS_SYSCALL_ID_MMAP: <<
199 { <<
200 sos_uaddr_t ptr_hint_uaddr; <<
201 sos_uaddr_t hint_uaddr; <<
202 sos_size_t length; <<
203 sos_ui32_t prot; <<
204 sos_ui32_t flags; <<
205 sos_uaddr_t name_user; <<
206 sos_ui32_t offs64_hi; <<
207 sos_ui32_t offs64_lo; <<
208 sos_luoffset_t offset_in_resource; <<
209 char name[256]; <<
210 struct sos_umem_vmm_as * my_as; <<
211 <<
212 retval = sos_syscall_get7args(user_ctx <<
213 (unsigne <<
214 (unsigne <<
215 (unsigne <<
216 (unsigne <<
217 (unsigne <<
218 (unsigne <<
219 (unsigne <<
220 if (SOS_OK != retval) <<
221 break; <<
222 <<
223 <<
224 offset_in_resource = offs64_hi; <<
225 offset_in_resource <<= 32; <<
226 offset_in_resource |= offs64_lo; <<
227 <<
228 retval = sos_memcpy_from_user((sos_vad <<
229 ptr_hint <<
230 sizeof(h <<
231 if (sizeof(hint_uaddr) != retval) <<
232 { <<
233 retval = -SOS_EFAULT; <<
234 break; <<
235 } <<
236 <<
237 retval = sos_strzcpy_from_user(name, n <<
238 if (SOS_OK != retval) <<
239 break; <<
240 <<
241 my_as <<
242 = sos_process_get_address_space(sos_ <<
243 if ( (0 == strncmp(name, "/dev/zero", <<
244 || (0 == strncmp(name, "/dev/null <<
245 retval = sos_dev_zero_map(my_as, & h <<
246 else if (0 == strncmp(name, "/dev/mem" <<
247 retval = sos_dev_physmem_map(my_as, <<
248 offset_ <<
249 else if (0 == strncmp(name, "/dev/kmem <<
250 retval = sos_dev_kmem_map(my_as, & h <<
251 offset_in_ <<
252 else <<
253 retval = -SOS_ENOENT; <<
254 <<
255 if (SOS_OK == retval) <<
256 { <<
257 if (sizeof(hint_uaddr) <<
258 != sos_memcpy_to_user(ptr_hint <<
259 (sos_vad <<
260 sizeof(h <<
261 { <<
262 sos_umem_vmm_unmap(my_as, hint <<
263 retval = -SOS_EFAULT; <<
264 } <<
265 } <<
266 <<
267 } <<
268 break; <<
269 <<
270 case SOS_SYSCALL_ID_MUNMAP: <<
271 { <<
272 sos_uaddr_t start_uaddr; <<
273 sos_size_t size; <<
274 struct sos_umem_vmm_as * my_as; <<
275 <<
276 my_as <<
277 = sos_process_get_address_space(sos_ <<
278 <<
279 retval = sos_syscall_get2args(user_ctx <<
280 (unsigne <<
281 (unsigne <<
282 if (SOS_OK != retval) <<
283 break; <<
284 <<
285 retval = sos_umem_vmm_unmap(my_as, sta <<
286 } <<
287 break; <<
288 <<
289 case SOS_SYSCALL_ID_MPROTECT: <<
290 { <<
291 sos_uaddr_t start_uaddr; <<
292 sos_size_t size; <<
293 sos_ui32_t new_access_rights; <<
294 struct sos_umem_vmm_as * my_as; <<
295 <<
296 my_as <<
297 = sos_process_get_address_space(sos_ <<
298 <<
299 retval = sos_syscall_get3args(user_ctx <<
300 (unsigne <<
301 (unsigne <<
302 (unsigne <<
303 if (SOS_OK != retval) <<
304 break; <<
305 <<
306 retval = sos_thread_prepare_user_space <<
307 if (SOS_OK != retval) <<
308 break; <<
309 <<
310 retval = sos_umem_vmm_chprot(my_as, st <<
311 new_acces <<
312 <<
313 sos_thread_end_user_space_access(); <<
314 } <<
315 break; <<
316 <<
317 case SOS_SYSCALL_ID_MRESIZE: <<
318 { <<
319 sos_uaddr_t old_uaddr; <<
320 sos_size_t old_size; <<
321 sos_uaddr_t *uptr_new_uaddr; <<
322 sos_uaddr_t new_uaddr; <<
323 sos_size_t new_size; <<
324 sos_ui32_t flags; <<
325 struct sos_umem_vmm_as * my_as; <<
326 <<
327 my_as <<
328 = sos_process_get_address_space(sos_ <<
329 <<
330 retval = sos_syscall_get5args(user_ctx <<
331 (unsigne <<
332 (unsigne <<
333 (unsigne <<
334 (unsigne <<
335 (unsigne <<
336 if (SOS_OK != retval) <<
337 break; <<
338 <<
339 if (sizeof(new_uaddr) != sos_memcpy_fr <<
340 <<
341 <<
342 <<
343 { <<
344 retval = -SOS_EFAULT; <<
345 break; <<
346 } <<
347 <<
348 retval = sos_thread_prepare_user_space <<
349 if (SOS_OK != retval) <<
350 break; <<
351 <<
352 retval = sos_umem_vmm_resize(my_as, ol <<
353 & new_uad <<
354 sos_thread_end_user_space_access(); <<
355 if (SOS_OK != retval) <<
356 break; <<
357 <<
358 if (sizeof(new_uaddr) <<
359 == sos_memcpy_to_user((sos_uaddr_t <<
360 (sos_vaddr_t <<
361 sizeof(new_u <<
362 { <<
363 retval = -SOS_EFAULT; <<
364 break; <<
365 } <<
366 } <<
367 break; <<
368 <<
369 case SOS_SYSCALL_ID_NEW_THREAD: <<
370 { <<
371 sos_uaddr_t start_func; <<
372 sos_ui32_t start_arg1, start_arg2; <<
373 sos_size_t stack_size; <<
374 sos_uaddr_t stack_uaddr; <<
375 <<
376 struct sos_thread * new_thr; <<
377 struct sos_umem_vmm_as * my_as; <<
378 <<
379 my_as <<
380 = sos_process_get_address_space(sos_ <<
381 <<
382 retval = sos_syscall_get4args(user_ctx <<
383 (unsigne <<
384 (unsigne <<
385 (unsigne <<
386 (unsigne <<
387 if (SOS_OK != retval) <<
388 break; <<
389 <<
390 if (stack_size <= 0) <<
391 { <<
392 retval = -SOS_EINVAL; <<
393 break; <<
394 } <<
395 <<
396 <<
397 stack_uaddr = 0; <<
398 stack_size = SOS_PAGE_ALIGN_SUP(stack_ <<
399 retval = sos_dev_zero_map(my_as, & sta <<
400 SOS_VM_MAP_P <<
401 <<
402 if (SOS_OK != retval) <<
403 break; <<
404 <<
405 <<
406 new_thr = sos_create_user_thread(NULL, <<
407 sos_t <<
408 start <<
409 start <<
410 start <<
411 stack <<
412 SOS_S <<
413 <<
414 if (! new_thr) <<
415 { <<
416 sos_umem_vmm_unmap(my_as, stack_ua <<
417 retval = -SOS_ENOMEM; <<
418 break; <<
419 } <<
420 } <<
421 break; <<
422 <<
423 case SOS_SYSCALL_ID_NANOSLEEP: <<
424 { <<
425 struct sos_time delay; <<
426 <<
427 retval = sos_syscall_get2args(user_ctx <<
428 (unsigne <<
429 (unsigne <<
430 if (SOS_OK != retval) <<
431 break; <<
432 <<
433 retval = sos_thread_sleep(& delay); <<
434 } <<
435 break; <<
436 <<
437 case SOS_SYSCALL_ID_BRK: <<
438 { <<
439 sos_uaddr_t new_top_heap; <<
440 struct sos_umem_vmm_as * my_as; <<
441 <<
442 my_as <<
443 = sos_process_get_address_space(sos_ <<
444 <<
445 retval = sos_syscall_get1arg(user_ctxt <<
446 (unsigned <<
447 if (SOS_OK != retval) <<
448 break; <<
449 <<
450 retval = sos_thread_prepare_user_space <<
451 if (SOS_OK != retval) <<
452 break; <<
453 <<
454 retval = sos_umem_vmm_brk(my_as, new_t <<
455 sos_thread_end_user_space_access(); <<
456 } <<
457 break; <<
458 <<
459 case SOS_SYSCALL_ID_BOCHS_WRITE: 048 case SOS_SYSCALL_ID_BOCHS_WRITE:
460 { 049 {
461 sos_uaddr_t user_str; 050 sos_uaddr_t user_str;
462 sos_size_t len; 051 sos_size_t len;
463 char * str; 052 char * str;
464 retval = sos_syscall_get2args(user_ctx 053 retval = sos_syscall_get2args(user_ctxt, & user_str, & len);
465 if (SOS_OK != retval) 054 if (SOS_OK != retval)
466 break; 055 break;
467 056
468 str = (char*)sos_kmalloc(len + 1, 0); 057 str = (char*)sos_kmalloc(len + 1, 0);
469 if (str) 058 if (str)
470 { 059 {
471 retval = sos_strzcpy_from_user(str 060 retval = sos_strzcpy_from_user(str, user_str, len+1);
472 str[len] = '\0'; 061 str[len] = '\0';
473 if (SOS_OK == retval) 062 if (SOS_OK == retval)
474 { 063 {
475 sos_bochs_printf("THR 0x%x: ", 064 sos_bochs_printf("THR 0x%x: ",
476 (unsigned)sos 065 (unsigned)sos_thread_get_current());
477 retval = sos_bochs_putstring(s 066 retval = sos_bochs_putstring(str);
478 retval = len; 067 retval = len;
479 } 068 }
480 sos_kfree((sos_vaddr_t)str); 069 sos_kfree((sos_vaddr_t)str);
481 } 070 }
482 else 071 else
483 retval = -SOS_ENOMEM; 072 retval = -SOS_ENOMEM;
484 } 073 }
485 break; 074 break;
486 075
487 076
488 077
489 078
490 079
491 080
492 081
493 082
494 083
495 084
496 085
497 case 4012: 086 case 4012:
498 { 087 {
499 sos_uaddr_t user_str; 088 sos_uaddr_t user_str;
500 unsigned int len; 089 unsigned int len;
501 unsigned char * str; 090 unsigned char * str;
502 091
503 retval = sos_syscall_get2args(user_ctx 092 retval = sos_syscall_get2args(user_ctxt, & user_str, & len);
504 if (SOS_OK != retval) 093 if (SOS_OK != retval)
505 break; 094 break;
506 095
507 str = (char*)sos_kmalloc(len + 1, 0); 096 str = (char*)sos_kmalloc(len + 1, 0);
508 if (str) 097 if (str)
509 { 098 {
510 int i; 099 int i;
511 sos_bochs_printf("Hexdump(0x%x, %d 100 sos_bochs_printf("Hexdump(0x%x, %d):\n", user_str, len);
512 retval = sos_memcpy_from_user((sos 101 retval = sos_memcpy_from_user((sos_vaddr_t) str, user_str, len);
513 sos_bochs_printf(" (Successfully 102 sos_bochs_printf(" (Successfully copied %d out of %d)\n",
514 retval, len); 103 retval, len);
515 104
516 for (i = 0 ; i < retval ; i++) 105 for (i = 0 ; i < retval ; i++)
517 { 106 {
518 if ((i % 32) == 0) 107 if ((i % 32) == 0)
519 sos_bochs_printf("%x:", i); 108 sos_bochs_printf("%x:", i);
520 sos_bochs_printf(" %x", str[i] 109 sos_bochs_printf(" %x", str[i]);
521 if (((i+1) % 32) == 0) 110 if (((i+1) % 32) == 0)
522 sos_bochs_printf("\n"); 111 sos_bochs_printf("\n");
523 } 112 }
524 if (i % 32) 113 if (i % 32)
525 sos_bochs_printf("\n"); 114 sos_bochs_printf("\n");
526 115
527 sos_kfree((sos_vaddr_t)str); 116 sos_kfree((sos_vaddr_t)str);
528 } 117 }
529 else 118 else
530 retval = -SOS_ENOMEM; 119 retval = -SOS_ENOMEM;
531 } <<
532 break; <<
533 <<
534 <<
535 <<
536 <<
537 <<
538 <<
539 case 4004: <<
540 { <<
541 sos_uaddr_t ustr; <<
542 char * kstr; <<
543 struct sos_umem_vmm_as * my_as; <<
544 <<
545 retval = sos_syscall_get1arg(user_ctxt <<
546 if (SOS_OK != retval) <<
547 break; <<
548 <<
549 retval = sos_strndup_from_user(& kstr, <<
550 if (SOS_OK != retval) <<
551 break; <<
552 <<
553 extern void sos_dump_as(const struct s <<
554 my_as <<
555 = sos_process_get_address_space(sos_ <<
556 sos_dump_as(my_as, kstr); <<
557 sos_kfree((sos_vaddr_t)kstr); <<
558 } 120 }
559 break; 121 break;
560 122
561 123
562 124
563 125
564 126
565 127
566 case 4008: 128 case 4008:
567 { 129 {
568 extern void sos_process_dumplist(void) 130 extern void sos_process_dumplist(void);
569 sos_process_dumplist(); 131 sos_process_dumplist();
570 retval = SOS_OK; 132 retval = SOS_OK;
571 } 133 }
572 break; 134 break;
573 135
574 default: 136 default:
575 sos_bochs_printf("Syscall: UNKNOWN[%d]\n 137 sos_bochs_printf("Syscall: UNKNOWN[%d]\n", syscall_id);
576 retval = -SOS_ENOSUP; 138 retval = -SOS_ENOSUP;
577 } 139 }
578 140
579 return retval; 141 return retval;
580 } 142 }