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>
022 028
023 #include <hwcore/cpu_context.h> 029 #include <hwcore/cpu_context.h>
024 #include <sos/uaccess.h> 030 #include <sos/uaccess.h>
025 #include "syscall.h" 031 #include "syscall.h"
026 032
027 033
028 034
029 035
030 036
031 sos_ret_t sos_do_syscall(int syscall_id, 037 sos_ret_t sos_do_syscall(int syscall_id,
032 const struct sos_cpu_ 038 const struct sos_cpu_state *user_ctxt)
033 { 039 {
034 sos_ret_t retval; 040 sos_ret_t retval;
035 041
036 switch(syscall_id) 042 switch(syscall_id)
037 { 043 {
038 case SOS_SYSCALL_ID_EXIT: 044 case SOS_SYSCALL_ID_EXIT:
039 { 045 {
040 unsigned int status; 046 unsigned int status;
041 retval = sos_syscall_get1arg(user_ctxt 047 retval = sos_syscall_get1arg(user_ctxt, & status);
042 if (SOS_OK != retval) 048 if (SOS_OK != retval)
043 break; 049 break;
044 sos_thread_exit(); 050 sos_thread_exit();
045 retval = -SOS_EFATAL; 051 retval = -SOS_EFATAL;
046 } 052 }
047 break; 053 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, TRUE);
>> 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_proc,
>> 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_uaddr;
>> 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->process) != 1)
>> 106 {
>> 107 retval = -SOS_EBUSY;
>> 108 break;
>> 109 }
>> 110
>> 111
>> 112 retval = sos_syscall_get2args(user_ctxt, & user_str, & len);
>> 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, user_str, len + 1);
>> 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(cur_thr->process);
>> 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_as, str);
>> 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 - SOS_DEFAULT_USER_STACK_SIZE)
>> 152 + 1;
>> 153 retval = sos_dev_zero_map(new_as, &ustack, SOS_DEFAULT_USER_STACK_SIZE,
>> 154 SOS_VM_MAP_PROT_READ | SOS_VM_MAP_PROT_WRITE,
>> 155 0);
>> 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_thr->process,
>> 166 start_uaddr,
>> 167 0, 0,
>> 168 ustack + SOS_DEFAULT_USER_STACK_SIZE
>> 169 - 4,
>> 170 SOS_SCHED_PRIO_TS_LOWEST);
>> 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, str);
>> 180
>> 181
>> 182 retval = sos_process_set_address_space(cur_thr->process,
>> 183 new_as);
>> 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_ctxt,
>> 213 (unsigned int*)& ptr_hint_uaddr,
>> 214 (unsigned int*)& length,
>> 215 (unsigned int*)& prot,
>> 216 (unsigned int*)& flags,
>> 217 (unsigned int*)& name_user,
>> 218 (unsigned int*)& offs64_hi,
>> 219 (unsigned int*)& offs64_lo);
>> 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_vaddr_t)& hint_uaddr,
>> 229 ptr_hint_uaddr,
>> 230 sizeof(hint_uaddr));
>> 231 if (sizeof(hint_uaddr) != retval)
>> 232 {
>> 233 retval = -SOS_EFAULT;
>> 234 break;
>> 235 }
>> 236
>> 237 retval = sos_strzcpy_from_user(name, name_user, sizeof(name));
>> 238 if (SOS_OK != retval)
>> 239 break;
>> 240
>> 241 my_as
>> 242 = sos_process_get_address_space(sos_thread_get_current()->process);
>> 243 if ( (0 == strncmp(name, "/dev/zero", sizeof(name)))
>> 244 || (0 == strncmp(name, "/dev/null", sizeof(name))) )
>> 245 retval = sos_dev_zero_map(my_as, & hint_uaddr, length, prot, flags);
>> 246 else if (0 == strncmp(name, "/dev/mem", sizeof(name)))
>> 247 retval = sos_dev_physmem_map(my_as, & hint_uaddr, length,
>> 248 offset_in_resource, prot, flags);
>> 249 else if (0 == strncmp(name, "/dev/kmem", sizeof(name)))
>> 250 retval = sos_dev_kmem_map(my_as, & hint_uaddr, length,
>> 251 offset_in_resource, prot, flags);
>> 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_uaddr,
>> 259 (sos_vaddr_t)& hint_uaddr,
>> 260 sizeof(hint_uaddr)))
>> 261 {
>> 262 sos_umem_vmm_unmap(my_as, hint_uaddr, length);
>> 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_thread_get_current()->process);
>> 278
>> 279 retval = sos_syscall_get2args(user_ctxt,
>> 280 (unsigned int*)& start_uaddr,
>> 281 (unsigned int*)& size);
>> 282 if (SOS_OK != retval)
>> 283 break;
>> 284
>> 285 retval = sos_umem_vmm_unmap(my_as, start_uaddr, size);
>> 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_thread_get_current()->process);
>> 298
>> 299 retval = sos_syscall_get3args(user_ctxt,
>> 300 (unsigned int*)& start_uaddr,
>> 301 (unsigned int*)& size,
>> 302 (unsigned int*)& new_access_rights);
>> 303 if (SOS_OK != retval)
>> 304 break;
>> 305
>> 306 retval = sos_thread_prepare_user_space_access(NULL, (sos_vaddr_t)NULL);
>> 307 if (SOS_OK != retval)
>> 308 break;
>> 309
>> 310 retval = sos_umem_vmm_chprot(my_as, start_uaddr, size,
>> 311 new_access_rights);
>> 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_thread_get_current()->process);
>> 329
>> 330 retval = sos_syscall_get5args(user_ctxt,
>> 331 (unsigned int*)& old_uaddr,
>> 332 (unsigned int*)& old_size,
>> 333 (unsigned int*)& uptr_new_uaddr,
>> 334 (unsigned int*)& new_size,
>> 335 (unsigned int*)& flags);
>> 336 if (SOS_OK != retval)
>> 337 break;
>> 338
>> 339 if (sizeof(new_uaddr) != sos_memcpy_from_user((sos_vaddr_t)& new_uaddr,
>> 340 (sos_uaddr_t)
>> 341 uptr_new_uaddr,
>> 342 sizeof(new_uaddr)))
>> 343 {
>> 344 retval = -SOS_EFAULT;
>> 345 break;
>> 346 }
>> 347
>> 348 retval = sos_thread_prepare_user_space_access(NULL, (sos_vaddr_t)NULL);
>> 349 if (SOS_OK != retval)
>> 350 break;
>> 351
>> 352 retval = sos_umem_vmm_resize(my_as, old_uaddr, old_size,
>> 353 & new_uaddr, new_size, flags);
>> 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)uptr_new_uaddr,
>> 360 (sos_vaddr_t)&new_uaddr,
>> 361 sizeof(new_uaddr)))
>> 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_thread_get_current()->process);
>> 381
>> 382 retval = sos_syscall_get4args(user_ctxt,
>> 383 (unsigned int*)& start_func,
>> 384 (unsigned int*)& start_arg1,
>> 385 (unsigned int*)& start_arg2,
>> 386 (unsigned int*)& stack_size);
>> 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_size);
>> 399 retval = sos_dev_zero_map(my_as, & stack_uaddr, stack_size,
>> 400 SOS_VM_MAP_PROT_READ | SOS_VM_MAP_PROT_WRITE,
>> 401 0);
>> 402 if (SOS_OK != retval)
>> 403 break;
>> 404
>> 405
>> 406 new_thr = sos_create_user_thread(NULL,
>> 407 sos_thread_get_current()->process,
>> 408 start_func,
>> 409 start_arg1,
>> 410 start_arg2,
>> 411 stack_uaddr + stack_size - 4,
>> 412 SOS_SCHED_PRIO_TS_LOWEST);
>> 413
>> 414 if (! new_thr)
>> 415 {
>> 416 sos_umem_vmm_unmap(my_as, stack_uaddr, stack_size);
>> 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_ctxt,
>> 428 (unsigned int*)& delay.sec,
>> 429 (unsigned int*)& delay.nanosec);
>> 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_thread_get_current()->process);
>> 444
>> 445 retval = sos_syscall_get1arg(user_ctxt,
>> 446 (unsigned int*)& new_top_heap);
>> 447 if (SOS_OK != retval)
>> 448 break;
>> 449
>> 450 retval = sos_thread_prepare_user_space_access(NULL, (sos_vaddr_t)NULL);
>> 451 if (SOS_OK != retval)
>> 452 break;
>> 453
>> 454 retval = sos_umem_vmm_brk(my_as, new_top_heap);
>> 455 sos_thread_end_user_space_access();
>> 456 }
>> 457 break;
>> 458
048 case SOS_SYSCALL_ID_BOCHS_WRITE: 459 case SOS_SYSCALL_ID_BOCHS_WRITE:
049 { 460 {
050 sos_uaddr_t user_str; 461 sos_uaddr_t user_str;
051 sos_size_t len; 462 sos_size_t len;
052 char * str; 463 char * str;
053 retval = sos_syscall_get2args(user_ctx 464 retval = sos_syscall_get2args(user_ctxt, & user_str, & len);
054 if (SOS_OK != retval) 465 if (SOS_OK != retval)
055 break; 466 break;
056 467
057 str = (char*)sos_kmalloc(len + 1, 0); 468 str = (char*)sos_kmalloc(len + 1, 0);
058 if (str) 469 if (str)
059 { 470 {
060 retval = sos_strzcpy_from_user(str 471 retval = sos_strzcpy_from_user(str, user_str, len+1);
061 str[len] = '\0'; 472 str[len] = '\0';
062 if (SOS_OK == retval) 473 if (SOS_OK == retval)
063 { 474 {
064 sos_bochs_printf("THR 0x%x: ", 475 sos_bochs_printf("THR 0x%x: ",
065 (unsigned)sos 476 (unsigned)sos_thread_get_current());
066 retval = sos_bochs_putstring(s 477 retval = sos_bochs_putstring(str);
067 retval = len; 478 retval = len;
068 } 479 }
069 sos_kfree((sos_vaddr_t)str); 480 sos_kfree((sos_vaddr_t)str);
070 } 481 }
071 else 482 else
072 retval = -SOS_ENOMEM; 483 retval = -SOS_ENOMEM;
073 } 484 }
074 break; 485 break;
075 486
076 487
077 488
078 489
079 490
080 491
081 492
082 493
083 494
084 495
085 496
086 case 4012: 497 case 4012:
087 { 498 {
088 sos_uaddr_t user_str; 499 sos_uaddr_t user_str;
089 unsigned int len; 500 unsigned int len;
090 unsigned char * str; 501 unsigned char * str;
091 502
092 retval = sos_syscall_get2args(user_ctx 503 retval = sos_syscall_get2args(user_ctxt, & user_str, & len);
093 if (SOS_OK != retval) 504 if (SOS_OK != retval)
094 break; 505 break;
095 506
096 str = (char*)sos_kmalloc(len + 1, 0); 507 str = (char*)sos_kmalloc(len + 1, 0);
097 if (str) 508 if (str)
098 { 509 {
099 int i; 510 int i;
100 sos_bochs_printf("Hexdump(0x%x, %d 511 sos_bochs_printf("Hexdump(0x%x, %d):\n", user_str, len);
101 retval = sos_memcpy_from_user((sos 512 retval = sos_memcpy_from_user((sos_vaddr_t) str, user_str, len);
102 sos_bochs_printf(" (Successfully 513 sos_bochs_printf(" (Successfully copied %d out of %d)\n",
103 retval, len); 514 retval, len);
104 515
105 for (i = 0 ; i < retval ; i++) 516 for (i = 0 ; i < retval ; i++)
106 { 517 {
107 if ((i % 32) == 0) 518 if ((i % 32) == 0)
108 sos_bochs_printf("%x:", i); 519 sos_bochs_printf("%x:", i);
109 sos_bochs_printf(" %x", str[i] 520 sos_bochs_printf(" %x", str[i]);
110 if (((i+1) % 32) == 0) 521 if (((i+1) % 32) == 0)
111 sos_bochs_printf("\n"); 522 sos_bochs_printf("\n");
112 } 523 }
113 if (i % 32) 524 if (i % 32)
114 sos_bochs_printf("\n"); 525 sos_bochs_printf("\n");
115 526
116 sos_kfree((sos_vaddr_t)str); 527 sos_kfree((sos_vaddr_t)str);
117 } 528 }
118 else 529 else
119 retval = -SOS_ENOMEM; 530 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, & ustr);
>> 546 if (SOS_OK != retval)
>> 547 break;
>> 548
>> 549 retval = sos_strndup_from_user(& kstr, ustr, 256, 0);
>> 550 if (SOS_OK != retval)
>> 551 break;
>> 552
>> 553 extern void sos_dump_as(const struct sos_umem_vmm_as *, const char *);
>> 554 my_as
>> 555 = sos_process_get_address_space(sos_thread_get_current()->process);
>> 556 sos_dump_as(my_as, kstr);
>> 557 sos_kfree((sos_vaddr_t)kstr);
120 } 558 }
121 break; 559 break;
122 560
123 561
124 562
125 563
126 564
127 565
128 case 4008: 566 case 4008:
129 { 567 {
130 extern void sos_process_dumplist(void) 568 extern void sos_process_dumplist(void);
131 sos_process_dumplist(); 569 sos_process_dumplist();
132 retval = SOS_OK; 570 retval = SOS_OK;
133 } 571 }
134 break; 572 break;
135 573
136 default: 574 default:
137 sos_bochs_printf("Syscall: UNKNOWN[%d]\n 575 sos_bochs_printf("Syscall: UNKNOWN[%d]\n", syscall_id);
138 retval = -SOS_ENOSUP; 576 retval = -SOS_ENOSUP;
139 } 577 }
140 578
141 return retval; 579 return retval;
142 } 580 }