X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=linux-user%2Fsyscall.c;h=5eb5b3931ff2d27954f973b3049e3609fb7bd576;hb=c35734b2a6f9b028edacd5813ff271728ce2a9e3;hp=e95212894f048e9d10a0dbc10fb64235c542a23c;hpb=1be9e1dc569eb3817441baf60d26648c5dcef12d;p=qemu diff --git a/linux-user/syscall.c b/linux-user/syscall.c index e952128..5eb5b39 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -28,10 +28,13 @@ #include #include #include +#include +#include #include #include #include #include +#include #include #include #include @@ -42,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -139,6 +143,7 @@ type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \ #define __NR_sys_getdents __NR_getdents #define __NR_sys_getdents64 __NR_getdents64 #define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo +#define __NR_sys_syslog __NR_syslog #if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) #define __NR__llseek __NR_lseek @@ -158,9 +163,13 @@ _syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count); _syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, loff_t *, res, uint, wh); _syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo) +_syscall3(int,sys_syslog,int,type,char*,bufp,int,len) #ifdef __NR_exit_group _syscall1(int,exit_group,int,error_code) #endif +#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address) +_syscall1(int,set_tid_address,int *,tidptr) +#endif extern int personality(int); extern int flock(int, int); @@ -841,7 +850,7 @@ static long do_accept(int fd, target_ulong target_addr, target_ulong target_addrlen) { socklen_t addrlen = tget32(target_addrlen); - void *addr = alloca(target_addrlen); + void *addr = alloca(addrlen); long ret; ret = get_errno(accept(fd, addr, &addrlen)); @@ -856,7 +865,7 @@ static long do_getpeername(int fd, target_ulong target_addr, target_ulong target_addrlen) { socklen_t addrlen = tget32(target_addrlen); - void *addr = alloca(target_addrlen); + void *addr = alloca(addrlen); long ret; ret = get_errno(getpeername(fd, addr, &addrlen)); @@ -871,7 +880,7 @@ static long do_getsockname(int fd, target_ulong target_addr, target_ulong target_addrlen) { socklen_t addrlen = tget32(target_addrlen); - void *addr = alloca(target_addrlen); + void *addr = alloca(addrlen); long ret; ret = get_errno(getsockname(fd, addr, &addrlen)); @@ -1114,6 +1123,12 @@ static struct shm_region { uint32_t size; } shm_regions[N_SHM_REGIONS]; +union semun { + int val; + struct senid_ds *buf; + unsigned short *array; +}; + /* ??? This only works with linear mappings. */ static long do_ipc(long call, long first, long second, long third, long ptr, long fifth) @@ -1128,6 +1143,52 @@ static long do_ipc(long call, long first, long second, long third, call &= 0xffff; switch (call) { + case IPCOP_semop: + ret = get_errno(semop(first,(struct sembuf *) ptr, second)); + break; + + case IPCOP_semget: + ret = get_errno(semget(first, second, third)); + break; + + case IPCOP_semctl: + ret = get_errno(semctl(first, second, third, ((union semun*)ptr)->val)); + + break; + + case IPCOP_semtimedop: + gemu_log("Unsupported ipc call: %ld (version %d)\n", call, version); + ret = -ENOSYS; + break; + + case IPCOP_msgget: + ret = get_errno(msgget(first, second)); + break; + + case IPCOP_msgsnd: + ret = get_errno(msgsnd(first, (struct msgbuf *) ptr, second, third)); + break; + + case IPCOP_msgctl: + ret = get_errno(msgctl(first, second, (struct msqid_ds *) ptr)); + break; + + case IPCOP_msgrcv: + { + struct ipc_kludge + { + void *__unbounded msgp; + long int msgtyp; + }; + + struct ipc_kludge *foo = (struct ipc_kludge *) ptr; + struct msgbuf *msgp = (struct msgbuf *) foo->msgp; + + ret = get_errno(msgrcv(first, msgp, second, 0, third)); + + } + break; + case IPCOP_shmat: /* SHM_* flags are the same on all linux platforms */ ret = get_errno((long) shmat(first, (void *) ptr, second)); @@ -1664,8 +1725,7 @@ int do_fork(CPUState *env, unsigned int flags, unsigned long newsp) ts->next = first_task_state; first_task_state = ts; /* we create a new CPU instance. */ - new_env = cpu_init(); - memcpy(new_env, env, sizeof(CPUState)); + new_env = cpu_copy(env); #if defined(TARGET_I386) if (!newsp) newsp = env->regs[R_ESP]; @@ -1727,6 +1787,8 @@ static long do_fcntl(int fd, int cmd, target_ulong arg) { struct flock fl; struct target_flock *target_fl; + struct flock64 fl64; + struct target_flock64 *target_fl64; long ret; switch(cmd) { @@ -1756,10 +1818,27 @@ static long do_fcntl(int fd, int cmd, target_ulong arg) break; case TARGET_F_GETLK64: + ret = fcntl(fd, cmd >> 1, &fl64); + if (ret == 0) { + lock_user_struct(target_fl64, arg, 0); + target_fl64->l_type = tswap16(fl64.l_type) >> 1; + target_fl64->l_whence = tswap16(fl64.l_whence); + target_fl64->l_start = tswapl(fl64.l_start); + target_fl64->l_len = tswapl(fl64.l_len); + target_fl64->l_pid = tswapl(fl64.l_pid); + unlock_user_struct(target_fl64, arg, 1); + } + break; case TARGET_F_SETLK64: case TARGET_F_SETLKW64: - ret = -1; - errno = EINVAL; + lock_user_struct(target_fl64, arg, 1); + fl64.l_type = tswap16(target_fl64->l_type) >> 1; + fl64.l_whence = tswap16(target_fl64->l_whence); + fl64.l_start = tswapl(target_fl64->l_start); + fl64.l_len = tswapl(target_fl64->l_len); + fl64.l_pid = tswap16(target_fl64->l_pid); + unlock_user_struct(target_fl64, arg, 0); + ret = fcntl(fd, cmd >> 1, &fl64); break; case F_GETFL: @@ -2088,8 +2167,18 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, ret = get_errno(getpid()); break; case TARGET_NR_mount: - /* need to look at the data field */ - goto unimplemented; + { + /* need to look at the data field */ + void *p2, *p3; + p = lock_user_string(arg1); + p2 = lock_user_string(arg2); + p3 = lock_user_string(arg3); + ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, (const void *)arg5)); + unlock_user(p, arg1, 0); + unlock_user(p2, arg2, 0); + unlock_user(p3, arg3, 0); + break; + } case TARGET_NR_umount: p = lock_user_string(arg1); ret = get_errno(umount(p)); @@ -2673,7 +2762,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, break; #ifdef TARGET_NR_mmap2 case TARGET_NR_mmap2: -#if defined(TARGET_SPARC) +#if defined(TARGET_SPARC) || defined(TARGET_MIPS) #define MMAP_SHIFT 12 #else #define MMAP_SHIFT TARGET_PAGE_BITS @@ -2827,12 +2916,12 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, #endif #ifdef TARGET_NR_recv case TARGET_NR_recv: - ret = do_recvfrom(arg1, arg1, arg3, arg4, 0, 0); + ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0); break; #endif #ifdef TARGET_NR_recvfrom case TARGET_NR_recvfrom: - ret = do_recvfrom(arg1, arg1, arg3, arg4, arg5, arg6); + ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6); break; #endif #ifdef TARGET_NR_recvmsg @@ -2875,9 +2964,13 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5); break; #endif - + case TARGET_NR_syslog: - goto unimplemented; + p = lock_user_string(arg2); + ret = get_errno(sys_syslog((int)arg1, p, (int)arg3)); + unlock_user(p, arg2, 0); + break; + case TARGET_NR_setitimer: { struct itimerval value, ovalue, *pvalue; @@ -2933,7 +3026,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, lock_user_struct(target_st, arg2, 0); target_st->st_dev = tswap16(st.st_dev); target_st->st_ino = tswapl(st.st_ino); -#if defined(TARGET_PPC) +#if defined(TARGET_PPC) || defined(TARGET_MIPS) target_st->st_mode = tswapl(st.st_mode); /* XXX: check this */ target_st->st_uid = tswap32(st.st_uid); target_st->st_gid = tswap32(st.st_gid); @@ -3346,7 +3439,21 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, case TARGET_NR_nfsservctl: goto unimplemented; case TARGET_NR_prctl: - goto unimplemented; + switch (arg1) + { + case PR_GET_PDEATHSIG: + { + int deathsig; + ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5)); + if (!is_error(ret) && arg2) + tput32(arg2, deathsig); + } + break; + default: + ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5)); + break; + } + break; #ifdef TARGET_NR_pread case TARGET_NR_pread: page_unprotect_range(arg2, arg3); @@ -3829,6 +3936,12 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, break; } #endif +#ifdef TARGET_NR_cacheflush + case TARGET_NR_cacheflush: + /* self-modifying code is handled automatically, so nothing needed */ + ret = 0; + break; +#endif #ifdef TARGET_NR_security case TARGET_NR_security: goto unimplemented; @@ -3860,6 +3973,15 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, #endif #ifdef TARGET_NR_set_thread_area case TARGET_NR_set_thread_area: +#ifdef TARGET_MIPS + ((CPUMIPSState *) cpu_env)->tls_value = arg1; + ret = 0; + break; +#else + goto unimplemented_nowarn; +#endif +#endif +#ifdef TARGET_NR_get_thread_area case TARGET_NR_get_thread_area: goto unimplemented_nowarn; #endif @@ -3867,10 +3989,40 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, case TARGET_NR_getdomainname: goto unimplemented_nowarn; #endif + +#ifdef TARGET_NR_clock_gettime + case TARGET_NR_clock_gettime: + { + struct timespec ts; + ret = get_errno(clock_gettime(arg1, &ts)); + if (!is_error(ret)) { + host_to_target_timespec(arg2, &ts); + } + break; + } +#endif +#ifdef TARGET_NR_clock_getres + case TARGET_NR_clock_getres: + { + struct timespec ts; + ret = get_errno(clock_getres(arg1, &ts)); + if (!is_error(ret)) { + host_to_target_timespec(arg2, &ts); + } + break; + } +#endif + +#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address) + case TARGET_NR_set_tid_address: + ret = get_errno(set_tid_address((int *) arg1)); + break; +#endif + default: unimplemented: gemu_log("qemu: Unsupported syscall: %d\n", num); -#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_set_thread_area) || defined(TARGET_NR_getdomainname) +#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname) unimplemented_nowarn: #endif ret = -ENOSYS;