File:  [Qemu by Fabrice Bellard] / qemu / darwin-user / syscall.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:55:08 2018 UTC (3 years, 3 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0105, qemu0104, qemu0103, qemu0102, qemu0101, qemu0100, HEAD
qemu 0.10.0

    1: /*
    2:  *  Darwin syscalls
    3:  *
    4:  *  Copyright (c) 2003 Fabrice Bellard
    5:  *  Copyright (c) 2006 Pierre d'Herbemont
    6:  *
    7:  *  This program is free software; you can redistribute it and/or modify
    8:  *  it under the terms of the GNU General Public License as published by
    9:  *  the Free Software Foundation; either version 2 of the License, or
   10:  *  (at your option) any later version.
   11:  *
   12:  *  This program is distributed in the hope that it will be useful,
   13:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   14:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15:  *  GNU General Public License for more details.
   16:  *
   17:  *  You should have received a copy of the GNU General Public License
   18:  *  along with this program; if not, write to the Free Software
   19:  *  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
   20:  *  MA 02110-1301, USA.
   21:  */
   22: #include <fcntl.h>
   23: #include <stdio.h>
   24: #include <stdlib.h>
   25: #include <errno.h>
   26: 
   27: #include <mach/host_info.h>
   28: #include <mach/mach.h>
   29: #include <mach/mach_time.h>
   30: #include <mach/message.h>
   31: 
   32: #include <pthread.h>
   33: #include <dirent.h>
   34: 
   35: #include <sys/stat.h>
   36: #include <sys/syscall.h>
   37: #include <sys/sysctl.h>
   38: #include <sys/types.h>
   39: #include <unistd.h>
   40: #include <sys/ioctl.h>
   41: #include <sys/mman.h>
   42: #include <sys/types.h>
   43: #include <sys/dirent.h>
   44: #include <sys/uio.h>
   45: #include <sys/termios.h>
   46: #include <sys/ptrace.h>
   47: #include <net/if.h>
   48: 
   49: #include <sys/param.h>
   50: #include <sys/mount.h>
   51: 
   52: #include <sys/attr.h>
   53: 
   54: #include <mach/ndr.h>
   55: #include <mach/mig_errors.h>
   56: 
   57: #include <sys/xattr.h>
   58: 
   59: #include "qemu.h"
   60: 
   61: //#define DEBUG_SYSCALL
   62: 
   63: #ifdef DEBUG_SYSCALL
   64: # define DEBUG_FORCE_ENABLE_LOCAL() int __DEBUG_qemu_user_force_enable = 1
   65: # define DEBUG_BEGIN_ENABLE  __DEBUG_qemu_user_force_enable = 1;
   66: # define DEBUG_END_ENABLE  __DEBUG_qemu_user_force_enable = 0;
   67: 
   68: # define DEBUG_DISABLE_ALL() static int __DEBUG_qemu_user_force_enable = 0
   69: # define DEBUG_ENABLE_ALL()  static int __DEBUG_qemu_user_force_enable = 1
   70:     DEBUG_ENABLE_ALL();
   71: 
   72: # define DPRINTF(...) do { qemu_log(__VA_ARGS__); \
   73:                            if(__DEBUG_qemu_user_force_enable) fprintf(stderr, __VA_ARGS__); \
   74:                          } while(0)
   75: #else
   76: # define DEBUG_FORCE_ENABLE_LOCAL()
   77: # define DEBUG_BEGIN_ENABLE
   78: # define DEBUG_END_ENABLE
   79: 
   80: # define DPRINTF(...) do { qemu_log(__VA_ARGS__); } while(0)
   81: #endif
   82: 
   83: enum {
   84:     bswap_out = 0,
   85:     bswap_in = 1
   86: };
   87: 
   88: extern const char *interp_prefix;
   89: 
   90: static inline long get_errno(long ret)
   91: {
   92:     if (ret == -1)
   93:         return -errno;
   94:     else
   95:         return ret;
   96: }
   97: 
   98: static inline int is_error(long ret)
   99: {
  100:     return (unsigned long)ret >= (unsigned long)(-4096);
  101: }
  102: 
  103: /* ------------------------------------------------------------
  104:    Mach syscall handling
  105: */
  106: 
  107: void static inline print_description_msg_header(mach_msg_header_t *hdr)
  108: {
  109:     char *name = NULL;
  110:     int i;
  111:     struct { int number; char *name; } msg_name[] =
  112:     {
  113:         /* see http://fxr.watson.org/fxr/source/compat/mach/mach_namemap.c?v=NETBSD */
  114:         { 200,      "host_info" },
  115:         { 202,      "host_page_size" },
  116:         { 206,      "host_get_clock_service" },
  117:         { 206,      "host_get_clock_service" },
  118:         { 206,      "host_get_clock_service" },
  119:         { 306,      "host_get_clock_service" },
  120:         { 3204,     "mach_port_allocate" },
  121:         { 3206,     "mach_port_deallocate" },
  122:         { 3404,     "mach_ports_lookup" },
  123:         { 3409,     "mach_task_get_special_port" },
  124:         { 3414,     "mach_task_get_exception_ports" },
  125:         { 3418,     "mach_semaphore_create" },
  126:         { 3504,     "mach_semaphore_create" },
  127:         { 3509,     "mach_semaphore_create" },
  128:         { 3518,     "semaphore_create" },
  129:         { 3616,     "thread_policy" },
  130:         { 3801,     "vm_allocate" },
  131:         { 3802,     "vm_deallocate" },
  132:         { 3802,     "vm_deallocate" },
  133:         { 3803,     "vm_protect" },
  134:         { 3812,     "vm_map" },
  135:         { 4241776,  "lu_message_send_id" },  /* lookupd */
  136:         { 4241876,  "lu_message_reply_id" }, /* lookupd */
  137:     };
  138: 
  139:     for(i = 0; i < ARRAY_SIZE(msg_name); i++) {
  140:         if(msg_name[i].number == hdr->msgh_id)
  141:         {
  142:             name = msg_name[i].name;
  143:             break;
  144:         }
  145:     }
  146:     if(!name)
  147:         DPRINTF("unknown mach msg %d 0x%x\n", hdr->msgh_id, hdr->msgh_id);
  148:     else
  149:         DPRINTF("%s\n", name);
  150: #if 0
  151:     DPRINTF("Bits: %8x\n", hdr->msgh_bits);
  152:     DPRINTF("Size: %8x\n", hdr->msgh_size);
  153:     DPRINTF("Rmte: %8x\n", hdr->msgh_remote_port);
  154:     DPRINTF("Locl: %8x\n", hdr->msgh_local_port);
  155:     DPRINTF("Rsrv: %8x\n", hdr->msgh_reserved);
  156: 
  157:     DPRINTF("Id  : %8x\n", hdr->msgh_id);
  158: 
  159:     NDR_record_t *ndr = (NDR_record_t *)(hdr + 1);
  160:     DPRINTF("hdr = %p, sizeof(hdr) = %x, NDR = %p\n", hdr, (unsigned int)sizeof(mach_msg_header_t), ndr);
  161:     DPRINTF("%d %d %d %d %d %d %d %d\n",
  162:            ndr->mig_vers, ndr->if_vers, ndr->reserved1, ndr->mig_encoding,
  163:            ndr->int_rep, ndr->char_rep, ndr->float_rep, ndr->reserved2);
  164: #endif
  165: }
  166: 
  167: static inline void print_mach_msg_return(mach_msg_return_t ret)
  168: {
  169:     int i, found = 0;
  170: #define MACH_MSG_RET(msg) { msg, #msg }
  171:     struct { int code; char *name; } msg_name[] =
  172:     {
  173:         /* ref: http://darwinsource.opendarwin.org/10.4.2/xnu-792.2.4/osfmk/man/mach_msg.html */
  174:         /* send message */
  175:         MACH_MSG_RET(MACH_SEND_MSG_TOO_SMALL),
  176:         MACH_MSG_RET(MACH_SEND_NO_BUFFER),
  177:         MACH_MSG_RET(MACH_SEND_INVALID_DATA),
  178:         MACH_MSG_RET(MACH_SEND_INVALID_HEADER),
  179:         MACH_MSG_RET(MACH_SEND_INVALID_DEST),
  180:         MACH_MSG_RET(MACH_SEND_INVALID_NOTIFY),
  181:         MACH_MSG_RET(MACH_SEND_INVALID_REPLY),
  182:         MACH_MSG_RET(MACH_SEND_INVALID_TRAILER),
  183:         MACH_MSG_RET(MACH_SEND_INVALID_MEMORY),
  184:         MACH_MSG_RET(MACH_SEND_INVALID_RIGHT),
  185:         MACH_MSG_RET(MACH_SEND_INVALID_TYPE),
  186:         MACH_MSG_RET(MACH_SEND_INTERRUPTED),
  187:         MACH_MSG_RET(MACH_SEND_TIMED_OUT),
  188: 
  189:         MACH_MSG_RET(MACH_RCV_BODY_ERROR),
  190:         MACH_MSG_RET(MACH_RCV_HEADER_ERROR),
  191: 
  192:         MACH_MSG_RET(MACH_RCV_IN_SET),
  193:         MACH_MSG_RET(MACH_RCV_INTERRUPTED),
  194: 
  195:         MACH_MSG_RET(MACH_RCV_INVALID_DATA),
  196:         MACH_MSG_RET(MACH_RCV_INVALID_NAME),
  197:         MACH_MSG_RET(MACH_RCV_INVALID_NOTIFY),
  198:         MACH_MSG_RET(MACH_RCV_INVALID_TRAILER),
  199:         MACH_MSG_RET(MACH_RCV_INVALID_TYPE),
  200: 
  201:         MACH_MSG_RET(MACH_RCV_PORT_CHANGED),
  202:         MACH_MSG_RET(MACH_RCV_PORT_DIED),
  203: 
  204:         MACH_MSG_RET(MACH_RCV_SCATTER_SMALL),
  205:         MACH_MSG_RET(MACH_RCV_TIMED_OUT),
  206:         MACH_MSG_RET(MACH_RCV_TOO_LARGE)
  207:     };
  208: #undef MACH_MSG_RET
  209: 
  210:     if( ret == MACH_MSG_SUCCESS)
  211:         DPRINTF("MACH_MSG_SUCCESS\n");
  212:     else
  213:     {
  214:         for( i = 0; i < ARRAY_SIZE(msg_name); i++) {
  215:             if(msg_name[i].code == ret) {
  216:                 DPRINTF("%s\n", msg_name[i].name);
  217:                 found = 1;
  218:                 break;
  219:             }
  220:         }
  221:         if(!found)
  222:             qerror("unknow mach message ret code %d\n", ret);
  223:     }
  224: }
  225: 
  226: static inline void swap_mach_msg_header(mach_msg_header_t *hdr)
  227: {
  228:     hdr->msgh_bits = tswap32(hdr->msgh_bits);
  229:     hdr->msgh_size = tswap32(hdr->msgh_size);
  230:     hdr->msgh_remote_port = tswap32(hdr->msgh_remote_port);
  231:     hdr->msgh_local_port = tswap32(hdr->msgh_local_port);
  232:     hdr->msgh_reserved = tswap32(hdr->msgh_reserved);
  233:     hdr->msgh_id = tswap32(hdr->msgh_id);
  234: }
  235: 
  236: struct complex_msg {
  237:             mach_msg_header_t hdr;
  238:             mach_msg_body_t body;
  239: };
  240: 
  241: static inline void swap_mach_msg_body(struct complex_msg *complex_msg, int bswap)
  242: {
  243:     mach_msg_port_descriptor_t *descr = (mach_msg_port_descriptor_t *)(complex_msg+1);
  244:     int i,j;
  245: 
  246:     if(bswap == bswap_in)
  247:         tswap32s(&complex_msg->body.msgh_descriptor_count);
  248: 
  249:     DPRINTF("body.msgh_descriptor_count %d\n", complex_msg->body.msgh_descriptor_count);
  250: 
  251:     for(i = 0; i < complex_msg->body.msgh_descriptor_count; i++) {
  252:         switch(descr->type)
  253:         {
  254:             case MACH_MSG_PORT_DESCRIPTOR:
  255:                 tswap32s(&descr->name);
  256:                 descr++;
  257:                 break;
  258:             case MACH_MSG_OOL_DESCRIPTOR:
  259:             {
  260:                 mach_msg_ool_descriptor_t *ool = (void *)descr;
  261:                 tswap32s((uint32_t *)&ool->address);
  262:                 tswap32s(&ool->size);
  263: 
  264:                 descr = (mach_msg_port_descriptor_t *)(ool+1);
  265:                 break;
  266:             }
  267:             case MACH_MSG_OOL_PORTS_DESCRIPTOR:
  268:             {
  269:                 mach_msg_ool_ports_descriptor_t *ool_ports = (void *)descr;
  270:                 mach_port_name_t * port_names;
  271: 
  272:                 if(bswap == bswap_in)
  273:                 {
  274:                     tswap32s((uint32_t *)&ool_ports->address);
  275:                     tswap32s(&ool_ports->count);
  276:                 }
  277: 
  278:                 port_names = ool_ports->address;
  279: 
  280:                 for(j = 0; j < ool_ports->count; j++)
  281:                     tswap32s(&port_names[j]);
  282: 
  283:                 if(bswap == bswap_out)
  284:                 {
  285:                     tswap32s((uint32_t *)&ool_ports->address);
  286:                     tswap32s(&ool_ports->count);
  287:                 }
  288: 
  289:                 descr = (mach_msg_port_descriptor_t *)(ool_ports+1);
  290:                 break;
  291:             }
  292:             default: qerror("unknow mach msg descriptor type %x\n", descr->type);
  293:         }
  294:     }
  295:     if(bswap == bswap_out)
  296:         tswap32s(&complex_msg->body.msgh_descriptor_count);
  297: }
  298: 
  299: static inline void swap_mach_msg(mach_msg_header_t *hdr, int bswap)
  300: {
  301:     if (bswap == bswap_out && hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
  302:         swap_mach_msg_body((struct complex_msg *)hdr, bswap);
  303: 
  304:     swap_mach_msg_header(hdr);
  305: 
  306:     if (bswap == bswap_in && hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX)
  307:         swap_mach_msg_body((struct complex_msg *)hdr, bswap);
  308: }
  309: 
  310: static inline uint32_t target_mach_msg_trap(
  311:         mach_msg_header_t *hdr, uint32_t options, uint32_t send_size,
  312:         uint32_t rcv_size, uint32_t rcv_name, uint32_t time_out, uint32_t notify)
  313: {
  314:     extern int mach_msg_trap(mach_msg_header_t *, mach_msg_option_t,
  315:           mach_msg_size_t, mach_msg_size_t, mach_port_t,
  316:           mach_msg_timeout_t, mach_port_t);
  317:     mach_msg_audit_trailer_t *trailer;
  318:     mach_msg_id_t msg_id;
  319:     uint32_t ret = 0;
  320:     int i;
  321: 
  322:     swap_mach_msg(hdr, bswap_in);
  323: 
  324:     msg_id = hdr->msgh_id;
  325: 
  326:     print_description_msg_header(hdr);
  327: 
  328:     ret = mach_msg_trap(hdr, options, send_size, rcv_size, rcv_name, time_out, notify);
  329: 
  330:     print_mach_msg_return(ret);
  331: 
  332:     if( (options & MACH_RCV_MSG) && (REQUESTED_TRAILER_SIZE(options) > 0) )
  333:     {
  334:         /* XXX: the kernel always return the full trailer with MACH_SEND_MSG, so we should
  335:                 probably always bswap it  */
  336:         /* warning: according to Mac OS X Internals (the book) msg_size might be expressed in
  337:                     natural_t units but according to xnu/osfmk/mach/message.h: "The size of
  338:                     the message must be specified in bytes" */
  339:         trailer = (mach_msg_audit_trailer_t *)((uint8_t *)hdr + hdr->msgh_size);
  340:         /* XXX: Should probably do that based on the option asked by the sender, but dealing
  341:         with kernel answer seems more sound */
  342:         switch(trailer->msgh_trailer_size)
  343:         {
  344:             case sizeof(mach_msg_audit_trailer_t):
  345:                 for(i = 0; i < 8; i++)
  346:                     tswap32s(&trailer->msgh_audit.val[i]);
  347:                 /* Fall in mach_msg_security_trailer_t case */
  348:             case sizeof(mach_msg_security_trailer_t):
  349:                 tswap32s(&trailer->msgh_sender.val[0]);
  350:                 tswap32s(&trailer->msgh_sender.val[1]);
  351:                 /* Fall in mach_msg_seqno_trailer_t case */
  352:             case sizeof(mach_msg_seqno_trailer_t):
  353:                 tswap32s(&trailer->msgh_seqno);
  354:                 /* Fall in mach_msg_trailer_t case */
  355:             case sizeof(mach_msg_trailer_t):
  356:                 tswap32s(&trailer->msgh_trailer_type);
  357:                 tswap32s(&trailer->msgh_trailer_size);
  358:                 break;
  359:             case 0:
  360:                 /* Safer not to byteswap, but probably wrong */
  361:                 break;
  362:             default:
  363:                 qerror("unknow trailer type given its size %d\n", trailer->msgh_trailer_size);
  364:                 break;
  365:         }
  366:     }
  367: 
  368:     /* Special message handling */
  369:     switch (msg_id) {
  370:         case 200: /* host_info */
  371:         {
  372:             mig_reply_error_t *err = (mig_reply_error_t *)hdr;
  373:             struct {
  374:                 uint32_t unknow1;
  375:                 uint32_t max_cpus;
  376:                 uint32_t avail_cpus;
  377:                 uint32_t memory_size;
  378:                 uint32_t cpu_type;
  379:                 uint32_t cpu_subtype;
  380:             } *data = (void *)(err+1);
  381: 
  382:             DPRINTF("maxcpu = 0x%x\n",   data->max_cpus);
  383:             DPRINTF("numcpu = 0x%x\n",   data->avail_cpus);
  384:             DPRINTF("memsize = 0x%x\n",  data->memory_size);
  385: 
  386: #if defined(TARGET_I386)
  387:             data->cpu_type = CPU_TYPE_I386;
  388:             DPRINTF("cpu_type changed to 0x%x(i386)\n", data->cpu_type);
  389:             data->cpu_subtype = CPU_SUBTYPE_PENT;
  390:             DPRINTF("cpu_subtype changed to 0x%x(i386_pent)\n", data->cpu_subtype);
  391: #elif defined(TARGET_PPC)
  392:             data->cpu_type = CPU_TYPE_POWERPC;
  393:             DPRINTF("cpu_type changed to 0x%x(ppc)\n", data->cpu_type);
  394:             data->cpu_subtype = CPU_SUBTYPE_POWERPC_750;
  395:             DPRINTF("cpu_subtype changed to 0x%x(ppc_all)\n", data->cpu_subtype);
  396: #else
  397: # error target not supported
  398: #endif
  399:             break;
  400:         }
  401:         case 202: /* host_page_size */
  402:         {
  403:             mig_reply_error_t *err = (mig_reply_error_t *)hdr;
  404:             uint32_t *pagesize = (uint32_t *)(err+1);
  405: 
  406:             DPRINTF("pagesize = %d\n", *pagesize);
  407:             break;
  408:         }
  409:         default: break;
  410:     }
  411: 
  412:     swap_mach_msg(hdr, bswap_out);
  413: 
  414:     return ret;
  415: }
  416: 
  417: long do_mach_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
  418:                 uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
  419:                 uint32_t arg8)
  420: {
  421:     extern uint32_t mach_reply_port(void);
  422: 
  423:     long ret = 0;
  424: 
  425:     arg1 = tswap32(arg1);
  426:     arg2 = tswap32(arg2);
  427:     arg3 = tswap32(arg3);
  428:     arg4 = tswap32(arg4);
  429:     arg5 = tswap32(arg5);
  430:     arg6 = tswap32(arg6);
  431:     arg7 = tswap32(arg7);
  432:     arg8 = tswap32(arg8);
  433: 
  434:     DPRINTF("mach syscall %d : " , num);
  435: 
  436:     switch(num) {
  437:     /* see xnu/osfmk/mach/syscall_sw.h */
  438:     case -26:
  439:         DPRINTF("mach_reply_port()\n");
  440:         ret = mach_reply_port();
  441:         break;
  442:     case -27:
  443:         DPRINTF("mach_thread_self()\n");
  444:         ret = mach_thread_self();
  445:         break;
  446:     case -28:
  447:         DPRINTF("mach_task_self()\n");
  448:         ret = mach_task_self();
  449:         break;
  450:     case -29:
  451:         DPRINTF("mach_host_self()\n");
  452:         ret = mach_host_self();
  453:         break;
  454:     case -31:
  455:         DPRINTF("mach_msg_trap(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
  456:                 arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  457:         ret = target_mach_msg_trap((mach_msg_header_t *)arg1, arg2, arg3, arg4, arg5, arg6, arg7);
  458:         break;
  459: /* may need more translation if target arch is different from host */
  460: #if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
  461:     case -33:
  462:         DPRINTF("semaphore_signal_trap(0x%x)\n", arg1);
  463:         ret = semaphore_signal_trap(arg1);
  464:         break;
  465:     case -34:
  466:         DPRINTF("semaphore_signal_all_trap(0x%x)\n", arg1);
  467:         ret = semaphore_signal_all_trap(arg1);
  468:         break;
  469:     case -35:
  470:         DPRINTF("semaphore_signal_thread_trap(0x%x)\n", arg1, arg2);
  471:         ret = semaphore_signal_thread_trap(arg1,arg2);
  472:         break;
  473: #endif
  474:     case -36:
  475:         DPRINTF("semaphore_wait_trap(0x%x)\n", arg1);
  476:         extern int semaphore_wait_trap(int); // XXX: is there any header for that?
  477:         ret = semaphore_wait_trap(arg1);
  478:         break;
  479: /* may need more translation if target arch is different from host */
  480: #if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
  481:     case -37:
  482:         DPRINTF("semaphore_wait_signal_trap(0x%x, 0x%x)\n", arg1, arg2);
  483:         ret = semaphore_wait_signal_trap(arg1,arg2);
  484:         break;
  485: #endif
  486:     case -43:
  487:         DPRINTF("map_fd(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
  488:                 arg1, arg2, arg3, arg4, arg5);
  489:         ret = map_fd(arg1, arg2, (void*)arg3, arg4, arg5);
  490:         tswap32s((uint32_t*)arg3);
  491:         break;
  492: /* may need more translation if target arch is different from host */
  493: #if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__))
  494:     case -61:
  495:         DPRINTF("syscall_thread_switch(0x%x, 0x%x, 0x%x)\n",
  496:                 arg1, arg2, arg3);
  497:         ret = syscall_thread_switch(arg1, arg2, arg3);  // just a hint to the scheduler; can drop?
  498:         break;
  499: #endif
  500:     case -89:
  501:         DPRINTF("mach_timebase_info(0x%x)\n", arg1);
  502:         struct mach_timebase_info info;
  503:         ret = mach_timebase_info(&info);
  504:         if(!is_error(ret))
  505:         {
  506:             struct mach_timebase_info *outInfo = (void*)arg1;
  507:             outInfo->numer = tswap32(info.numer);
  508:             outInfo->denom = tswap32(info.denom);
  509:         }
  510:         break;
  511:     case -90:
  512:         DPRINTF("mach_wait_until()\n");
  513:         extern int mach_wait_until(uint64_t); // XXX: is there any header for that?
  514:         ret = mach_wait_until(((uint64_t)arg2<<32) | (uint64_t)arg1);
  515:         break;
  516:     case -91:
  517:         DPRINTF("mk_timer_create()\n");
  518:         extern int mk_timer_create(); // XXX: is there any header for that?
  519:         ret = mk_timer_create();
  520:         break;
  521:     case -92:
  522:         DPRINTF("mk_timer_destroy()\n");
  523:         extern int mk_timer_destroy(int); // XXX: is there any header for that?
  524:         ret = mk_timer_destroy(arg1);
  525:         break;
  526:     case -93:
  527:         DPRINTF("mk_timer_create()\n");
  528:         extern int mk_timer_arm(int, uint64_t); // XXX: is there any header for that?
  529:         ret = mk_timer_arm(arg1, ((uint64_t)arg3<<32) | (uint64_t)arg2);
  530:         break;
  531:     case -94:
  532:         DPRINTF("mk_timer_cancel()\n");
  533:         extern int mk_timer_cancel(int, uint64_t *); // XXX: is there any header for that?
  534:         ret = mk_timer_cancel(arg1, (uint64_t *)arg2);
  535:         if((!is_error(ret)) && arg2)
  536:             tswap64s((uint64_t *)arg2);
  537:         break;
  538:     default:
  539:         gemu_log("qemu: Unsupported mach syscall: %d(0x%x)\n", num, num);
  540:         gdb_handlesig (cpu_env, SIGTRAP);
  541:         exit(0);
  542:         break;
  543:     }
  544:     return ret;
  545: }
  546: 
  547: /* ------------------------------------------------------------
  548:    thread type syscall handling
  549: */
  550: long do_thread_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3,
  551:                 uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7,
  552:                 uint32_t arg8)
  553: {
  554:     extern uint32_t cthread_set_self(uint32_t);
  555:     extern uint32_t processor_facilities_used(void);
  556:     long ret = 0;
  557: 
  558:     arg1 = tswap32(arg1);
  559:     arg2 = tswap32(arg2);
  560:     arg3 = tswap32(arg3);
  561:     arg4 = tswap32(arg4);
  562:     arg5 = tswap32(arg5);
  563:     arg6 = tswap32(arg6);
  564:     arg7 = tswap32(arg7);
  565:     arg8 = tswap32(arg8);
  566: 
  567:     DPRINTF("thread syscall %d : " , num);
  568: 
  569:     switch(num) {
  570: #ifdef TARGET_I386
  571:     case 0x3:
  572: #endif
  573:     case 0x7FF1: /* cthread_set_self */
  574:         DPRINTF("cthread_set_self(0x%x)\n", (unsigned int)arg1);
  575:         ret = cthread_set_self(arg1);
  576: #ifdef TARGET_I386
  577:         /* we need to update the LDT with the address of the thread */
  578:         write_dt((void *)(((CPUX86State *) cpu_env)->ldt.base + (4 * sizeof(uint64_t))), arg1, 1,
  579:                  DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK |
  580:                  (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT));
  581:         /* New i386 convention, %gs should be set to our this LDT entry */
  582:         cpu_x86_load_seg(cpu_env, R_GS, 0x27);
  583:         /* Old i386 convention, the kernel returns the selector for the cthread (pre-10.4.8?)*/
  584:         ret = 0x27;
  585: #endif
  586:         break;
  587:     case 0x7FF2: /* Called the super-fast pthread_self handler by the apple guys */
  588:         DPRINTF("pthread_self()\n");
  589:         ret = (uint32_t)pthread_self();
  590:         break;
  591:     case 0x7FF3:
  592:         DPRINTF("processor_facilities_used()\n");
  593: #ifdef __i386__
  594:         qerror("processor_facilities_used: not implemented!\n");
  595: #else
  596:         ret = (uint32_t)processor_facilities_used();
  597: #endif
  598:         break;
  599:     default:
  600:         gemu_log("qemu: Unsupported thread syscall: %d(0x%x)\n", num, num);
  601:         gdb_handlesig (cpu_env, SIGTRAP);
  602:         exit(0);
  603:         break;
  604:     }
  605:     return ret;
  606: }
  607: 
  608: /* ------------------------------------------------------------
  609:    ioctl handling
  610: */
  611: static inline void byteswap_termios(struct termios *t)
  612: {
  613:     tswap32s((uint32_t*)&t->c_iflag);
  614:     tswap32s((uint32_t*)&t->c_oflag);
  615:     tswap32s((uint32_t*)&t->c_cflag);
  616:     tswap32s((uint32_t*)&t->c_lflag);
  617:     /* 20 (char) bytes then */
  618:     tswap32s((uint32_t*)&t->c_ispeed);
  619:     tswap32s((uint32_t*)&t->c_ospeed);
  620: }
  621: 
  622: static inline void byteswap_winsize(struct winsize *w)
  623: {
  624:     tswap16s(&w->ws_row);
  625:     tswap16s(&w->ws_col);
  626:     tswap16s(&w->ws_xpixel);
  627:     tswap16s(&w->ws_ypixel);
  628: }
  629: 
  630: #define STRUCT(name, list...) STRUCT_ ## name,
  631: #define STRUCT_SPECIAL(name) STRUCT_ ## name,
  632: enum {
  633: #include "ioctls_types.h"
  634: };
  635: #undef STRUCT
  636: #undef STRUCT_SPECIAL
  637: 
  638: #define STRUCT(name, list...) const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
  639: #define STRUCT_SPECIAL(name)
  640: #include "ioctls_types.h"
  641: #undef STRUCT
  642: #undef STRUCT_SPECIAL
  643: 
  644: typedef struct IOCTLEntry {
  645:     unsigned int target_cmd;
  646:     unsigned int host_cmd;
  647:     const char *name;
  648:     int access;
  649:     const argtype arg_type[5];
  650: } IOCTLEntry;
  651: 
  652: #define IOC_R 0x0001
  653: #define IOC_W 0x0002
  654: #define IOC_RW (IOC_R | IOC_W)
  655: 
  656: #define MAX_STRUCT_SIZE 4096
  657: 
  658: static IOCTLEntry ioctl_entries[] = {
  659: #define IOCTL(cmd, access, types...) \
  660:     { cmd, cmd, #cmd, access, { types } },
  661: #include "ioctls.h"
  662:     { 0, 0, },
  663: };
  664: 
  665: /* ??? Implement proper locking for ioctls.  */
  666: static long do_ioctl(long fd, long cmd, long arg)
  667: {
  668:     const IOCTLEntry *ie;
  669:     const argtype *arg_type;
  670:     int ret;
  671:     uint8_t buf_temp[MAX_STRUCT_SIZE];
  672:     int target_size;
  673:     void *argptr;
  674: 
  675:     ie = ioctl_entries;
  676:     for(;;) {
  677:         if (ie->target_cmd == 0) {
  678:             gemu_log("Unsupported ioctl: cmd=0x%04lx\n", cmd);
  679:             return -ENOSYS;
  680:         }
  681:         if (ie->target_cmd == cmd)
  682:             break;
  683:         ie++;
  684:     }
  685:     arg_type = ie->arg_type;
  686: #if defined(DEBUG)
  687:     gemu_log("ioctl: cmd=0x%04lx (%s)\n", cmd, ie->name);
  688: #endif
  689:     switch(arg_type[0]) {
  690:     case TYPE_NULL:
  691:         /* no argument */
  692:         ret = get_errno(ioctl(fd, ie->host_cmd));
  693:         break;
  694:     case TYPE_PTRVOID:
  695:     case TYPE_INT:
  696:         /* int argment */
  697:         ret = get_errno(ioctl(fd, ie->host_cmd, arg));
  698:         break;
  699:     case TYPE_PTR:
  700:         arg_type++;
  701:         target_size = thunk_type_size(arg_type, 0);
  702:         switch(ie->access) {
  703:         case IOC_R:
  704:             ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
  705:             if (!is_error(ret)) {
  706:                 argptr = lock_user(arg, target_size, 0);
  707:                 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
  708:                 unlock_user(argptr, arg, target_size);
  709:             }
  710:             break;
  711:         case IOC_W:
  712:             argptr = lock_user(arg, target_size, 1);
  713:             thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
  714:             unlock_user(argptr, arg, 0);
  715:             ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
  716:             break;
  717:         default:
  718:         case IOC_RW:
  719:             argptr = lock_user(arg, target_size, 1);
  720:             thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
  721:             unlock_user(argptr, arg, 0);
  722:             ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
  723:             if (!is_error(ret)) {
  724:                 argptr = lock_user(arg, target_size, 0);
  725:                 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
  726:                 unlock_user(argptr, arg, target_size);
  727:             }
  728:             break;
  729:         }
  730:         break;
  731:     default:
  732:         gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n", cmd, arg_type[0]);
  733:         ret = -ENOSYS;
  734:         break;
  735:     }
  736:     return ret;
  737: }
  738: 
  739: /* ------------------------------------------------------------
  740:    Unix syscall handling
  741: */
  742: 
  743: static inline void byteswap_attrlist(struct attrlist *a)
  744: {
  745:     tswap16s(&a->bitmapcount);
  746:     tswap16s(&a->reserved);
  747:     tswap32s(&a->commonattr);
  748:     tswap32s(&a->volattr);
  749:     tswap32s(&a->dirattr);
  750:     tswap32s(&a->fileattr);
  751:     tswap32s(&a->forkattr);
  752: }
  753: 
  754: struct attrbuf_header {
  755:     unsigned long length;
  756: };
  757: 
  758: static inline void byteswap_attrbuf(struct attrbuf_header *attrbuf, struct attrlist *attrlist)
  759: {
  760:     DPRINTF("attrBuf.lenght %lx\n", attrbuf->length);
  761: }
  762: 
  763: static inline void byteswap_statfs(struct statfs *s)
  764: {
  765:     tswap16s((uint16_t*)&s->f_otype);
  766:     tswap16s((uint16_t*)&s->f_oflags);
  767:     tswap32s((uint32_t*)&s->f_bsize);
  768:     tswap32s((uint32_t*)&s->f_iosize);
  769:     tswap32s((uint32_t*)&s->f_blocks);
  770:     tswap32s((uint32_t*)&s->f_bfree);
  771:     tswap32s((uint32_t*)&s->f_bavail);
  772:     tswap32s((uint32_t*)&s->f_files);
  773:     tswap32s((uint32_t*)&s->f_ffree);
  774:     tswap32s((uint32_t*)&s->f_fsid.val[0]);
  775:     tswap32s((uint32_t*)&s->f_fsid.val[1]);
  776:     tswap16s((uint16_t*)&s->f_reserved1);
  777:     tswap16s((uint16_t*)&s->f_type);
  778:     tswap32s((uint32_t*)&s->f_flags);
  779: }
  780: 
  781: static inline void byteswap_stat(struct stat *s)
  782: {
  783:     tswap32s((uint32_t*)&s->st_dev);
  784:     tswap32s(&s->st_ino);
  785:     tswap16s(&s->st_mode);
  786:     tswap16s(&s->st_nlink);
  787:     tswap32s(&s->st_uid);
  788:     tswap32s(&s->st_gid);
  789:     tswap32s((uint32_t*)&s->st_rdev);
  790:     tswap32s((uint32_t*)&s->st_atimespec.tv_sec);
  791:     tswap32s((uint32_t*)&s->st_atimespec.tv_nsec);
  792:     tswap32s((uint32_t*)&s->st_mtimespec.tv_sec);
  793:     tswap32s((uint32_t*)&s->st_mtimespec.tv_nsec);
  794:     tswap32s((uint32_t*)&s->st_ctimespec.tv_sec);
  795:     tswap32s((uint32_t*)&s->st_ctimespec.tv_nsec);
  796:     tswap64s((uint64_t*)&s->st_size);
  797:     tswap64s((uint64_t*)&s->st_blocks);
  798:     tswap32s((uint32_t*)&s->st_blksize);
  799:     tswap32s(&s->st_flags);
  800:     tswap32s(&s->st_gen);
  801: }
  802: 
  803: static inline void byteswap_dirents(struct dirent *d, int bytes)
  804: {
  805:     char *b;
  806:     for( b = (char*)d; (int)b < (int)d+bytes; )
  807:     {
  808:         unsigned short s = ((struct dirent *)b)->d_reclen;
  809:         tswap32s(&((struct dirent *)b)->d_ino);
  810:         tswap16s(&((struct dirent *)b)->d_reclen);
  811:         if(s<=0)
  812:             break;
  813:         b += s;
  814:     }
  815: }
  816: 
  817: static inline void byteswap_iovec(struct iovec *v, int n)
  818: {
  819:     int i;
  820:     for(i = 0; i < n; i++)
  821:     {
  822:         tswap32s((uint32_t*)&v[i].iov_base);
  823:         tswap32s((uint32_t*)&v[i].iov_len);
  824:     }
  825: }
  826: 
  827: static inline void byteswap_timeval(struct timeval *t)
  828: {
  829:     tswap32s((uint32_t*)&t->tv_sec);
  830:     tswap32s((uint32_t*)&t->tv_usec);
  831: }
  832: 
  833: long do_unix_syscall_indirect(void *cpu_env, int num);
  834: long do_sync(void);
  835: long do_exit(uint32_t arg1);
  836: long do_getlogin(char *out, uint32_t size);
  837: long do_open(char * arg1, uint32_t arg2, uint32_t arg3);
  838: long do_getfsstat(struct statfs * arg1, uint32_t arg2, uint32_t arg3);
  839: long do_sigprocmask(uint32_t arg1, uint32_t * arg2, uint32_t * arg3);
  840: long do_execve(char* arg1, char ** arg2, char ** arg3);
  841: long do_getgroups(uint32_t arg1, gid_t * arg2);
  842: long do_gettimeofday(struct timeval * arg1, void * arg2);
  843: long do_readv(uint32_t arg1, struct iovec * arg2, uint32_t arg3);
  844: long do_writev(uint32_t arg1, struct iovec * arg2, uint32_t arg3);
  845: long do_utimes(char * arg1, struct timeval * arg2);
  846: long do_futimes(uint32_t arg1, struct timeval * arg2);
  847: long do_statfs(char * arg1, struct statfs * arg2);
  848: long do_fstatfs(uint32_t arg1, struct statfs * arg2);
  849: long do_stat(char * arg1, struct stat * arg2);
  850: long do_fstat(uint32_t arg1, struct stat * arg2);
  851: long do_lstat(char * arg1, struct stat * arg2);
  852: long do_getdirentries(uint32_t arg1, void* arg2, uint32_t arg3, void* arg4);
  853: long do_lseek(void *cpu_env, int num);
  854: long do___sysctl(int * name, uint32_t namelen, void * oldp, size_t * oldlenp, void * newp, size_t newlen  /* ignored */);
  855: long do_getattrlist(void * arg1, void * arg2, void * arg3, uint32_t arg4, uint32_t arg5);
  856: long do_getdirentriesattr(uint32_t arg1, void * arg2, void * arg3, size_t arg4, void * arg5, void * arg6, void* arg7, uint32_t arg8);
  857: long do_fcntl(int fd, int cmd, int arg);
  858: 
  859: long no_syscall(void *cpu_env, int num);
  860: 
  861: long do_pread(uint32_t arg1, void * arg2, size_t arg3, off_t arg4)
  862: {
  863:     DPRINTF("0x%x, %p, 0x%lx, 0x%llx\n", arg1, arg2, arg3, arg4);
  864:     long ret = pread(arg1, arg2, arg3, arg4);
  865:     return ret;
  866: }
  867: 
  868: long do_read(int d, void *buf, size_t nbytes)
  869: {
  870:     DPRINTF("0x%x, %p, 0x%lx\n", d, buf, nbytes);
  871:     long ret = get_errno(read(d, buf, nbytes));
  872:     if(!is_error(ret))
  873:         DPRINTF("%x\n", *(uint32_t*)buf);
  874:     return ret;
  875: }
  876: 
  877: long unimpl_unix_syscall(void *cpu_env, int num);
  878: 
  879: typedef long (*syscall_function_t)(void *cpu_env, int num);
  880: 
  881: 
  882: /* define a table that will handle the syscall number->function association */
  883: #define VOID    void
  884: #define INT     (uint32_t)get_int_arg(&i, cpu_env)
  885: #define INT64   (uint64_t)get_int64_arg(&i, cpu_env)
  886: #define UINT    (unsigned int)INT
  887: #define PTR     (void*)INT
  888: 
  889: #define SIZE    INT
  890: #define OFFSET  INT64
  891: 
  892: #define WRAPPER_CALL_DIRECT_0(function, args) long __qemu_##function(void *cpu_env) {  return (long)function(); }
  893: #define WRAPPER_CALL_DIRECT_1(function, _arg1) long __qemu_##function(void *cpu_env) { int i = 0; typeof(_arg1) arg1 = _arg1;  return (long)function(arg1); }
  894: #define WRAPPER_CALL_DIRECT_2(function, _arg1, _arg2) long __qemu_##function(void *cpu_env) { int i = 0;  typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; return (long)function(arg1, arg2); }
  895: #define WRAPPER_CALL_DIRECT_3(function, _arg1, _arg2, _arg3) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; return (long)function(arg1, arg2, arg3); }
  896: #define WRAPPER_CALL_DIRECT_4(function, _arg1, _arg2, _arg3, _arg4) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; return (long)function(arg1, arg2, arg3, arg4); }
  897: #define WRAPPER_CALL_DIRECT_5(function, _arg1, _arg2, _arg3, _arg4, _arg5) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5;  return (long)function(arg1, arg2, arg3, arg4, arg5); }
  898: #define WRAPPER_CALL_DIRECT_6(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6;  return (long)function(arg1, arg2, arg3, arg4, arg5, arg6); }
  899: #define WRAPPER_CALL_DIRECT_7(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6; typeof(_arg7) arg7 = _arg7; return (long)function(arg1, arg2, arg3, arg4, arg5, arg6, arg7); }
  900: #define WRAPPER_CALL_DIRECT_8(function, _arg1, _arg2, _arg3, _arg4, _arg5, _arg6, _arg7, _arg8) long __qemu_##function(void *cpu_env) { int i = 0;   typeof(_arg1) arg1 = _arg1; typeof(_arg2) arg2 = _arg2; typeof(_arg3) arg3 = _arg3; typeof(_arg4) arg4 = _arg4; typeof(_arg5) arg5 = _arg5; typeof(_arg6) arg6 = _arg6; typeof(_arg7) arg7 = _arg7; typeof(_arg8) arg8 = _arg8;  return (long)function(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); }
  901: #define WRAPPER_CALL_DIRECT(function, nargs, args...) WRAPPER_CALL_DIRECT_##nargs(function, args)
  902: #define WRAPPER_CALL_NOERRNO(function, nargs, args...)  WRAPPER_CALL_DIRECT(function, nargs, args)
  903: #define WRAPPER_CALL_INDIRECT(function, nargs, args...)
  904: #define ENTRY(name, number, function, nargs, call_type, args...)  WRAPPER_##call_type(function, nargs, args)
  905: 
  906: #include "syscalls.h"
  907: 
  908: #undef ENTRY
  909: #undef WRAPPER_CALL_DIRECT
  910: #undef WRAPPER_CALL_NOERRNO
  911: #undef WRAPPER_CALL_INDIRECT
  912: #undef OFFSET
  913: #undef SIZE
  914: #undef INT
  915: #undef PTR
  916: #undef INT64
  917: 
  918: #define _ENTRY(name, number, function, nargs, call_type) [number] = {\
  919:         name, \
  920:         number, \
  921:         (syscall_function_t)function, \
  922:         nargs, \
  923:         call_type  \
  924:         },
  925: 
  926: #define ENTRY_CALL_DIRECT(name, number, function, nargs, call_type)  _ENTRY(name, number, __qemu_##function, nargs, call_type)
  927: #define ENTRY_CALL_NOERRNO(name, number, function, nargs, call_type) ENTRY_CALL_DIRECT(name, number, function, nargs, call_type)
  928: #define ENTRY_CALL_INDIRECT(name, number, function, nargs, call_type) _ENTRY(name, number, function, nargs, call_type)
  929: #define ENTRY(name, number, function, nargs, call_type, args...) ENTRY_##call_type(name, number, function, nargs, call_type)
  930: 
  931: #define CALL_DIRECT 1
  932: #define CALL_INDIRECT 2
  933: #define CALL_NOERRNO  (CALL_DIRECT | 4 /* = 5 */)
  934: 
  935: struct unix_syscall {
  936:     char * name;
  937:     int number;
  938:     syscall_function_t function;
  939:     int nargs;
  940:     int call_type;
  941: } unix_syscall_table[SYS_MAXSYSCALL] = {
  942: #include "syscalls.h"
  943: };
  944: 
  945: #undef ENTRY
  946: #undef _ENTRY
  947: #undef ENTRY_CALL_DIRECT
  948: #undef ENTRY_CALL_INDIRECT
  949: #undef ENTRY_CALL_NOERRNO
  950: 
  951: /* Actual syscalls implementation */
  952: 
  953: long do_unix_syscall_indirect(void *cpu_env, int num)
  954: {
  955:     long ret;
  956:     int new_num;
  957:     int i = 0;
  958: 
  959:     new_num = get_int_arg(&i, cpu_env);
  960: #ifdef TARGET_I386
  961:     ((CPUX86State*)cpu_env)->regs[R_ESP] += 4;
  962:     /* XXX: not necessary */
  963:     ((CPUX86State*)cpu_env)->regs[R_EAX] = new_num;
  964: #elif TARGET_PPC
  965:     {
  966:         int i;
  967:         uint32_t **regs = ((CPUPPCState*)cpu_env)->gpr;
  968:         for(i = 3; i < 11; i++)
  969:             *regs[i] = *regs[i+1];
  970:         /* XXX: not necessary */
  971:         *regs[0] = new_num;
  972:     }
  973: #endif
  974:     ret = do_unix_syscall(cpu_env, new_num);
  975: #ifdef TARGET_I386
  976:     ((CPUX86State*)cpu_env)->regs[R_ESP] -= 4;
  977:     /* XXX: not necessary */
  978:     ((CPUX86State*)cpu_env)->regs[R_EAX] = num;
  979: #elif TARGET_PPC
  980:     {
  981:         int i;
  982:         /* XXX: not really needed those regs are volatile accross calls */
  983:         uint32_t **regs = ((CPUPPCState*)cpu_env)->gpr;
  984:         for(i = 11; i > 3; i--)
  985:             *regs[i] = *regs[i-1];
  986:         regs[3] = new_num;
  987:         *regs[0] = num;
  988:     }
  989: #endif
  990:     return ret;
  991: }
  992: 
  993: long do_exit(uint32_t arg1)
  994: {
  995:     exit(arg1);
  996:     /* not reached */
  997:     return -1;
  998: }
  999: 
 1000: long do_sync(void)
 1001: {
 1002:     sync();
 1003:     return 0;
 1004: }
 1005: 
 1006: long do_getlogin(char *out, uint32_t size)
 1007: {
 1008:     char *login = getlogin();
 1009:     if(!login)
 1010:         return -1;
 1011:     memcpy(out, login, size);
 1012:     return 0;
 1013: }
 1014: long do_open(char * arg1, uint32_t arg2, uint32_t arg3)
 1015: {
 1016:     /* XXX: don't let the %s stay in there */
 1017:     DPRINTF("open(%s, 0x%x, 0x%x)\n", arg1, arg2, arg3);
 1018:     return get_errno(open(arg1, arg2, arg3));
 1019: }
 1020: 
 1021: long do_getfsstat(struct statfs * arg1, uint32_t arg2, uint32_t arg3)
 1022: {
 1023:     long ret;
 1024:     DPRINTF("getfsstat(%p, 0x%x, 0x%x)\n", arg1, arg2, arg3);
 1025:     ret = get_errno(getfsstat(arg1, arg2, arg3));
 1026:     if((!is_error(ret)) && arg1)
 1027:         byteswap_statfs(arg1);
 1028:     return ret;
 1029: }
 1030: 
 1031: long do_sigprocmask(uint32_t arg1, uint32_t * arg2, uint32_t * arg3)
 1032: {
 1033:     long ret;
 1034:     DPRINTF("sigprocmask(%d, %p, %p)\n", arg1, arg2, arg3);
 1035:     gemu_log("XXX: sigprocmask not tested (%d, %p, %p)\n", arg1, arg2, arg3);
 1036:     if(arg2)
 1037:         tswap32s(arg2);
 1038:     ret = get_errno(sigprocmask(arg1, (void *)arg2, (void *)arg3));
 1039:     if((!is_error(ret)) && arg3)
 1040:         tswap32s(arg3);
 1041:     if(arg2)
 1042:         tswap32s(arg2);
 1043:     return ret;
 1044: }
 1045: 
 1046: long do_execve(char* arg1, char ** arg2, char ** arg3)
 1047: {
 1048:     long ret;
 1049:     char **argv = arg2;
 1050:     char **envp = arg3;
 1051:     int argc;
 1052:     int envc;
 1053: 
 1054:     /* XXX: don't let the %s stay in here */
 1055:     DPRINTF("execve(%s, %p, %p)\n", arg1, arg2, arg3);
 1056: 
 1057:     for(argc = 0; argv[argc]; argc++);
 1058:     for(envc = 0; envp[envc]; envc++);
 1059: 
 1060:     argv = (char**)malloc(sizeof(char*)*argc);
 1061:     envp = (char**)malloc(sizeof(char*)*envc);
 1062: 
 1063:     for(; argc >= 0; argc--)
 1064:         argv[argc] = (char*)tswap32((uint32_t)(arg2)[argc]);
 1065: 
 1066:     for(; envc >= 0; envc--)
 1067:         envp[envc] = (char*)tswap32((uint32_t)(arg3)[envc]);
 1068: 
 1069:     ret = get_errno(execve(arg1, argv, envp));
 1070:     free(argv);
 1071:     free(envp);
 1072:     return ret;
 1073: }
 1074: 
 1075: long do_getgroups(uint32_t arg1, gid_t * arg2)
 1076: {
 1077:     long ret;
 1078:     int i;
 1079:     DPRINTF("getgroups(0x%x, %p)\n", arg1, arg2);
 1080:     ret = get_errno(getgroups(arg1, arg2));
 1081:     if(ret > 0)
 1082:         for(i = 0; i < arg1; i++)
 1083:             tswap32s(&arg2[i]);
 1084:     return ret;
 1085: }
 1086: 
 1087: long do_gettimeofday(struct timeval * arg1, void * arg2)
 1088: {
 1089:     long ret;
 1090:     DPRINTF("gettimeofday(%p, %p)\n",
 1091:             arg1, arg2);
 1092:     ret = get_errno(gettimeofday(arg1, arg2));
 1093:     if(!is_error(ret))
 1094:     {
 1095:         /* timezone no longer used according to the manpage, so don't bother with it */
 1096:         byteswap_timeval(arg1);
 1097:     }
 1098:     return ret;
 1099: }
 1100: 
 1101: long do_readv(uint32_t arg1, struct iovec * arg2, uint32_t arg3)
 1102: {
 1103:     long ret;
 1104:     DPRINTF("readv(0x%x, %p, 0x%x)\n", arg1, arg2, arg3);
 1105:     if(arg2)
 1106:         byteswap_iovec(arg2, arg3);
 1107:     ret = get_errno(readv(arg1, arg2, arg3));
 1108:     if((!is_error(ret)) && arg2)
 1109:         byteswap_iovec(arg2, arg3);
 1110:     return ret;
 1111: }
 1112: 
 1113: long do_writev(uint32_t arg1, struct iovec * arg2, uint32_t arg3)
 1114: {
 1115:     long ret;
 1116:     DPRINTF("writev(0x%x, %p, 0x%x)\n", arg1, arg2, arg3);
 1117:     if(arg2)
 1118:         byteswap_iovec(arg2, arg3);
 1119:     ret = get_errno(writev(arg1, arg2, arg3));
 1120:     if((!is_error(ret)) && arg2)
 1121:         byteswap_iovec(arg2, arg3);
 1122:     return ret;
 1123: }
 1124: 
 1125: long do_utimes(char * arg1, struct timeval * arg2)
 1126: {
 1127:     DPRINTF("utimes(%p, %p)\n", arg1, arg2);
 1128:     if(arg2)
 1129:     {
 1130:         byteswap_timeval(arg2);
 1131:         byteswap_timeval(arg2+1);
 1132:     }
 1133:     return get_errno(utimes(arg1, arg2));
 1134: }
 1135: 
 1136: long do_futimes(uint32_t arg1, struct timeval * arg2)
 1137: {
 1138:     DPRINTF("futimes(0x%x, %p)\n", arg1, arg2);
 1139:     if(arg2)
 1140:     {
 1141:         byteswap_timeval(arg2);
 1142:         byteswap_timeval(arg2+1);
 1143:     }
 1144:     return get_errno(futimes(arg1, arg2));
 1145: }
 1146: 
 1147: long do_statfs(char * arg1, struct statfs * arg2)
 1148: {
 1149:     long ret;
 1150:     DPRINTF("statfs(%p, %p)\n", arg1, arg2);
 1151:     ret = get_errno(statfs(arg1, arg2));
 1152:     if(!is_error(ret))
 1153:         byteswap_statfs(arg2);
 1154:     return ret;
 1155: }
 1156: 
 1157: long do_fstatfs(uint32_t arg1, struct statfs* arg2)
 1158: {
 1159:     long ret;
 1160:     DPRINTF("fstatfs(0x%x, %p)\n",
 1161:             arg1, arg2);
 1162:     ret = get_errno(fstatfs(arg1, arg2));
 1163:     if(!is_error(ret))
 1164:         byteswap_statfs(arg2);
 1165: 
 1166:     return ret;
 1167: }
 1168: 
 1169: long do_stat(char * arg1, struct stat * arg2)
 1170: {
 1171:     long ret;
 1172:     /* XXX: don't let the %s stay in there */
 1173:     DPRINTF("stat(%s, %p)\n", arg1, arg2);
 1174:     ret = get_errno(stat(arg1, arg2));
 1175:     if(!is_error(ret))
 1176:         byteswap_stat(arg2);
 1177:     return ret;
 1178: }
 1179: 
 1180: long do_fstat(uint32_t arg1, struct stat * arg2)
 1181: {
 1182:     long ret;
 1183:     DPRINTF("fstat(0x%x, %p)\n", arg1, arg2);
 1184:     ret = get_errno(fstat(arg1, arg2));
 1185:     if(!is_error(ret))
 1186:         byteswap_stat(arg2);
 1187:     return ret;
 1188: }
 1189: 
 1190: long do_lstat(char * arg1, struct stat * arg2)
 1191: {
 1192:     long ret;
 1193:     /* XXX: don't let the %s stay in there */
 1194:     DPRINTF("lstat(%s, %p)\n", (const char *)arg1, arg2);
 1195:     ret = get_errno(lstat(arg1, arg2));
 1196:     if(!is_error(ret))
 1197:         byteswap_stat(arg2);
 1198:     return ret;
 1199: }
 1200: 
 1201: long do_getdirentries(uint32_t arg1, void* arg2, uint32_t arg3, void* arg4)
 1202: {
 1203:     long ret;
 1204:     DPRINTF("getdirentries(0x%x, %p, 0x%x, %p)\n", arg1, arg2, arg3, arg4);
 1205:     if(arg4)
 1206:         tswap32s((uint32_t *)arg4);
 1207:     ret = get_errno(getdirentries(arg1, arg2, arg3, arg4));
 1208:     if(arg4)
 1209:         tswap32s((uint32_t *)arg4);
 1210:     if(!is_error(ret))
 1211:         byteswap_dirents(arg2, ret);
 1212:     return ret;
 1213: }
 1214: 
 1215: long do_lseek(void *cpu_env, int num)
 1216: {
 1217:     long ret;
 1218:     int i = 0;
 1219:     uint32_t arg1 = get_int_arg(&i, cpu_env);
 1220:     uint64_t offset = get_int64_arg(&i, cpu_env);
 1221:     uint32_t arg3 = get_int_arg(&i, cpu_env);
 1222:     uint64_t r = lseek(arg1, offset, arg3);
 1223: #ifdef TARGET_I386
 1224:     /* lowest word in eax, highest in edx */
 1225:     ret = r & 0xffffffff; /* will be set to eax after do_unix_syscall exit */
 1226:     ((CPUX86State *)cpu_env)->regs[R_EDX] = (uint32_t)((r >> 32) & 0xffffffff) ;
 1227: #elif defined TARGET_PPC
 1228:     ret = r & 0xffffffff; /* will be set to r3 after do_unix_syscall exit */
 1229:     ((CPUPPCState *)cpu_env)->gpr[4] = (uint32_t)((r >> 32) & 0xffffffff) ;
 1230: #else
 1231:     qerror("64 bit ret value on your arch?");
 1232: #endif
 1233:     return get_errno(ret);
 1234: }
 1235: 
 1236: void no_swap(void * oldp, int size)
 1237: {
 1238: }
 1239: 
 1240: void sysctl_tswap32s(void * oldp, int size)
 1241: {
 1242:     tswap32s(oldp);
 1243: }
 1244: 
 1245: void bswap_oid(uint32_t * oldp, int size)
 1246: {
 1247:     int count = size / sizeof(int);
 1248:     int i = 0;
 1249:     do { tswap32s(oldp + i); } while (++i < count);
 1250: }
 1251: 
 1252: void sysctl_usrstack(uint32_t * oldp, int size)
 1253: {
 1254:     DPRINTF("sysctl_usrstack: 0x%x\n", *oldp);
 1255:     tswap32s(oldp);
 1256: }
 1257: 
 1258: void sysctl_ncpu(uint32_t * ncpu, int size)
 1259: {
 1260:     *ncpu = 0x1;
 1261:     DPRINTF("sysctl_ncpu: 0x%x\n", *ncpu);
 1262:     tswap32s(ncpu);
 1263: }
 1264: 
 1265: void sysctl_exec(char * exec, int size)
 1266: {
 1267:     DPRINTF("sysctl_exec: %s\n", exec);
 1268: }
 1269: 
 1270: void sysctl_translate(char * exec, int size)
 1271: {
 1272:     DPRINTF("sysctl_translate: %s\n", exec);
 1273: }
 1274: 
 1275: struct sysctl_dir {
 1276:     int num;
 1277:     const char * name;
 1278:     void (*swap_func)(void *, int);
 1279:     struct sysctl_dir *childs;
 1280: };
 1281: 
 1282: #define ENTRYD(num, name, childs) { num, name, NULL, childs }
 1283: #define ENTRYE(num, name, func)   { num, name, (void (*)(void *, int))func, NULL  }
 1284: struct sysctl_dir sysctls_unspec[] = {
 1285:     ENTRYE(3,  "oip", bswap_oid),
 1286:     { 0, NULL, NULL, NULL }
 1287: };
 1288: 
 1289: struct sysctl_dir sysctls_kern[] = {
 1290:     ENTRYE(KERN_TRANSLATE,          "translate",    sysctl_translate), /* 44 */
 1291:     ENTRYE(KERN_EXEC,               "exec",         sysctl_exec), /* 45 */
 1292:     ENTRYE(KERN_USRSTACK32,          "KERN_USRSTACK32", sysctl_usrstack), /* 35 */
 1293:     ENTRYE(KERN_SHREG_PRIVATIZABLE,  "KERN_SHREG_PRIVATIZABLE", sysctl_tswap32s), /* 54 */
 1294:     { 0, NULL, NULL, NULL }
 1295: };
 1296: 
 1297: struct sysctl_dir sysctls_hw[] = {
 1298:     ENTRYE(HW_NCPU, "ncpud", sysctl_tswap32s),
 1299:     ENTRYE(104, "104", no_swap),
 1300:     ENTRYE(105, "105", no_swap),
 1301:     { 0, NULL, NULL, NULL }
 1302: };
 1303: 
 1304: struct sysctl_dir sysctls[] = {
 1305:     ENTRYD(CTL_UNSPEC, "unspec", sysctls_unspec),
 1306:     ENTRYD(CTL_KERN, "kern", sysctls_kern),
 1307:     ENTRYD(CTL_HW,   "hw",   sysctls_hw ),
 1308:     { 0, NULL, NULL, NULL }
 1309: };
 1310: 
 1311: #undef ENTRYE
 1312: #undef ENTRYD
 1313: 
 1314: static inline struct sysctl_dir * get_sysctl_entry_for_mib(int mib, struct sysctl_dir * sysctl_elmt)
 1315: {
 1316:     if(!sysctl_elmt)
 1317:         return NULL;
 1318:     for(; sysctl_elmt->name != NULL ; sysctl_elmt++) {
 1319:         if(sysctl_elmt->num == mib)
 1320:             return sysctl_elmt;
 1321:     }
 1322:     return NULL;
 1323: }
 1324: 
 1325: static inline long bswap_syctl(int * mib, int count, void *buf, int size)
 1326: {
 1327:     int i;
 1328:     struct sysctl_dir * sysctl = sysctls;
 1329:     struct sysctl_dir * ret = NULL;
 1330: 
 1331:     for(i = 0; i < count; i++) {
 1332: 
 1333:         if(!(ret = sysctl = get_sysctl_entry_for_mib(mib[i], sysctl))) {
 1334:             gemu_log("bswap_syctl: can't find mib %d\n", mib[i]);
 1335:             return -ENOTDIR;
 1336:         }
 1337:         if(!(sysctl = sysctl->childs))
 1338:             break;
 1339:     }
 1340: 
 1341:     if(ret->childs)
 1342:         qerror("we shouldn't have a directory element\n");
 1343: 
 1344:     ret->swap_func(buf, size);
 1345:     return 0;
 1346: }
 1347: 
 1348: static inline void print_syctl(int * mib, int count)
 1349: {
 1350:     int i;
 1351:     struct sysctl_dir * sysctl = sysctls;
 1352:     struct sysctl_dir * ret = NULL;
 1353: 
 1354:     for(i = 0; i < count; i++) {
 1355:         if(!(ret = sysctl = get_sysctl_entry_for_mib(mib[i], sysctl))){
 1356:             gemu_log("print_syctl: can't find mib %d\n", mib[i]);
 1357:             return;
 1358:         }
 1359:         DPRINTF("%s.", sysctl->name);
 1360:         if(!(sysctl = sysctl->childs))
 1361:             break;
 1362:     }
 1363:     DPRINTF("\n");
 1364: }
 1365: 
 1366: long do___sysctl(int * name, uint32_t namelen, void * oldp, size_t * oldlenp, void * newp, size_t newlen  /* ignored */)
 1367: {
 1368:     long ret = 0;
 1369:     int i;
 1370:     DPRINTF("sysctl(%p, 0x%x, %p, %p, %p, 0x%lx)\n",
 1371:             name, namelen, oldp, oldlenp, newp, newlen);
 1372:     if(name) {
 1373:         i = 0;
 1374:         do { tswap32s( name + i); } while (++i < namelen);
 1375:         print_syctl(name, namelen);
 1376:         //bswap_syctl(name, namelen, newp, newlen);
 1377:         tswap32s((uint32_t*)oldlenp);
 1378:     }
 1379: 
 1380:     if(name) /* Sometimes sysctl is called with no arg1, ignore */
 1381:         ret = get_errno(sysctl(name, namelen, oldp, oldlenp, newp, newlen));
 1382: 
 1383: #if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
 1384:     if (!is_error(ret) && bswap_syctl(name, namelen, oldp, *oldlenp) != 0) {
 1385:         return -ENOTDIR;
 1386:     }
 1387: #endif
 1388: 
 1389:     if(name) {
 1390:         //bswap_syctl(name, namelen, newp, newlen);
 1391:         tswap32s((uint32_t*)oldlenp);
 1392: 
 1393:         i = 0;
 1394:         do { tswap32s( name + i); } while (++i < namelen);
 1395:     }
 1396:     return ret;
 1397: }
 1398: 
 1399: long do_getattrlist(void * arg1, void * arg2, void * arg3, uint32_t arg4, uint32_t arg5)
 1400: {
 1401:     struct attrlist * attrlist = (void *)arg2;
 1402:     long ret;
 1403: 
 1404: #if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
 1405:     gemu_log("SYS_getdirentriesattr unimplemented\n");
 1406:     return -ENOTSUP;
 1407: #endif
 1408:     /* XXX: don't let the %s stay in there */
 1409:     DPRINTF("getattrlist(%s, %p, %p, 0x%x, 0x%x)\n",
 1410:             (char *)arg1, arg2, arg3, arg4, arg5);
 1411: 
 1412:     if(arg2) /* XXX: We should handle that in a copy especially
 1413:         if the structure is not writable */
 1414:         byteswap_attrlist(attrlist);
 1415: 
 1416:     ret = get_errno(getattrlist((const char* )arg1, attrlist, (void *)arg3, arg4, arg5));
 1417: 
 1418:     if(!is_error(ret))
 1419:     {
 1420:         byteswap_attrbuf((void *)arg3, attrlist);
 1421:         byteswap_attrlist(attrlist);
 1422:     }
 1423:     return ret;
 1424: }
 1425: 
 1426: long do_getdirentriesattr(uint32_t arg1, void * arg2, void * arg3, size_t arg4, void * arg5, void * arg6, void* arg7, uint32_t arg8)
 1427: {
 1428:     DPRINTF("getdirentriesattr(0x%x, %p, %p, 0x%lx, %p, %p, %p, 0x%x)\n",
 1429:             arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
 1430: #if defined(TARGET_I386) ^ defined(__i386__) || defined(TARGET_PPC) ^ defined(__ppc__)
 1431:     qerror("SYS_getdirentriesattr unimplemented\n");
 1432: #endif
 1433: 
 1434:     return get_errno(getdirentriesattr( arg1, (struct attrlist * )arg2, (void *)arg3, arg4,
 1435:                                        (unsigned long *)arg5, (unsigned long *)arg6,
 1436:                                        (unsigned long *)arg7, arg8));
 1437: }
 1438: 
 1439: static inline void bswap_flock(struct flock *f)
 1440: {
 1441:     tswap64s(&f->l_start);
 1442:     tswap64s(&f->l_len);
 1443:     tswap32s(&f->l_pid);
 1444:     tswap16s(&f->l_type);
 1445:     tswap16s(&f->l_whence);
 1446: }
 1447: 
 1448: static inline void bswap_fstore(struct fstore *f)
 1449: {
 1450:     tswap32s(&f->fst_flags);
 1451:     tswap32s(&f->fst_posmode);
 1452:     tswap64s(&f->fst_offset);
 1453:     tswap64s(&f->fst_length);
 1454:     tswap64s(&f->fst_bytesalloc);
 1455: }
 1456: 
 1457: static inline void bswap_radvisory(struct radvisory *f)
 1458: {
 1459:     tswap64s(&f->ra_offset);
 1460:     tswap32s(&f->ra_count);
 1461: }
 1462: 
 1463: static inline void bswap_fbootstraptransfer(struct fbootstraptransfer *f)
 1464: {
 1465:     tswap64s(&f->fbt_offset);
 1466:     tswap32s((uint32_t*)&f->fbt_length);
 1467:     tswap32s((uint32_t*)&f->fbt_buffer); /* XXX: this is a ptr */
 1468: }
 1469: 
 1470: static inline void bswap_log2phys(struct log2phys *f)
 1471: {
 1472:     tswap32s(&f->l2p_flags);
 1473:     tswap64s(&f->l2p_contigbytes);
 1474:     tswap64s(&f->l2p_devoffset);
 1475: }
 1476: 
 1477: static inline void bswap_fcntl_arg(int cmd, void * arg)
 1478: {
 1479:     switch(cmd)
 1480:     {
 1481:         case F_DUPFD:
 1482:         case F_GETFD:
 1483:         case F_SETFD:
 1484:         case F_GETFL:
 1485:         case F_SETFL:
 1486:         case F_GETOWN:
 1487:         case F_SETOWN:
 1488:         case F_SETSIZE:
 1489:         case F_RDAHEAD:
 1490:         case F_FULLFSYNC:
 1491:             break;
 1492:         case F_GETLK:
 1493:         case F_SETLK:
 1494:         case F_SETLKW:
 1495:             bswap_flock(arg);
 1496:             break;
 1497:         case F_PREALLOCATE:
 1498:             bswap_fstore(arg);
 1499:             break;
 1500:         case F_RDADVISE:
 1501:             bswap_radvisory(arg);
 1502:             break;
 1503:         case F_READBOOTSTRAP:
 1504:         case F_WRITEBOOTSTRAP:
 1505:             bswap_fbootstraptransfer(arg);
 1506:             break;
 1507:         case F_LOG2PHYS:
 1508:             bswap_log2phys(arg);
 1509:             break;
 1510:         default:
 1511:             gemu_log("unknow cmd in fcntl\n");
 1512:     }
 1513: }
 1514: 
 1515: long do_fcntl(int fd, int cmd, int arg)
 1516: {
 1517:     long ret;
 1518:     bswap_fcntl_arg(cmd, (void *)arg);
 1519:     ret = get_errno(fcntl(fd, cmd, arg));
 1520:     if(!is_error(ret))
 1521:         bswap_fcntl_arg(cmd, (void *)arg);
 1522:     return ret;
 1523: }
 1524: 
 1525: long no_syscall(void *cpu_env, int num)
 1526: {
 1527:     /* XXX: We should probably fordward it to the host kernel */
 1528:     qerror("no unix syscall %d\n", num);
 1529:     /* not reached */
 1530:     return -1;
 1531: }
 1532: 
 1533: long unimpl_unix_syscall(void *cpu_env, int num)
 1534: {
 1535:     if( (num < 0) || (num > SYS_MAXSYSCALL-1) )
 1536:         qerror("unix syscall %d is out of unix syscall bounds (0-%d) " , num, SYS_MAXSYSCALL-1);
 1537: 
 1538:     gemu_log("qemu: Unsupported unix syscall %s %d\n", unix_syscall_table[num].name , num);
 1539:     gdb_handlesig (cpu_env, SIGTRAP);
 1540:     exit(-1);
 1541: }
 1542: 
 1543: long do_unix_syscall(void *cpu_env, int num)
 1544: {
 1545:     long ret = 0;
 1546: 
 1547:     DPRINTF("unix syscall %d: " , num);
 1548: 
 1549:     if( (num < 0) || (num > SYS_MAXSYSCALL-1) )
 1550:         qerror("unix syscall %d is out of unix syscall bounds (0-%d) " , num, SYS_MAXSYSCALL-1);
 1551: 
 1552:     DPRINTF("%s [%s]", unix_syscall_table[num].name, unix_syscall_table[num].call_type & CALL_DIRECT ? "direct" : "indirect" );
 1553:     ret = unix_syscall_table[num].function(cpu_env, num);
 1554: 
 1555:     if(!(unix_syscall_table[num].call_type & CALL_NOERRNO))
 1556:         ret = get_errno(ret);
 1557: 
 1558:     DPRINTF("[returned 0x%x(%d)]\n", (int)ret, (int)ret);
 1559:     return ret;
 1560: }
 1561: 
 1562: /* ------------------------------------------------------------
 1563:    syscall_init
 1564: */
 1565: void syscall_init(void)
 1566: {
 1567:     /* Nothing yet */
 1568: }

unix.superglobalmegacorp.com