diff options
Diffstat (limited to 'linux-user')
139 files changed, 49792 insertions, 0 deletions
diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs new file mode 100644 index 00000000..fd502178 --- /dev/null +++ b/linux-user/Makefile.objs @@ -0,0 +1,7 @@ +obj-y = main.o syscall.o strace.o mmap.o signal.o \ +	elfload.o linuxload.o uaccess.o uname.o + +obj-$(TARGET_HAS_BFLT) += flatload.o +obj-$(TARGET_I386) += vm86.o +obj-$(TARGET_ARM) += arm/nwfpe/ +obj-$(TARGET_M68K) += m68k-sim.o diff --git a/linux-user/aarch64/syscall.h b/linux-user/aarch64/syscall.h new file mode 100644 index 00000000..dc72a15c --- /dev/null +++ b/linux-user/aarch64/syscall.h @@ -0,0 +1,13 @@ +struct target_pt_regs { +    uint64_t        regs[31]; +    uint64_t        sp; +    uint64_t        pc; +    uint64_t        pstate; +}; + +#define UNAME_MACHINE "aarch64" +#define UNAME_MINIMUM_RELEASE "3.8.0" +#define TARGET_CLONE_BACKWARDS +#define TARGET_MINSIGSTKSZ       2048 +#define TARGET_MLOCKALL_MCL_CURRENT 1 +#define TARGET_MLOCKALL_MCL_FUTURE  2 diff --git a/linux-user/aarch64/syscall_nr.h b/linux-user/aarch64/syscall_nr.h new file mode 100644 index 00000000..743255db --- /dev/null +++ b/linux-user/aarch64/syscall_nr.h @@ -0,0 +1,323 @@ +/* + * This file contains the system call numbers. + */ + +#define TARGET_NR_io_setup 0 +#define TARGET_NR_io_destroy 1 +#define TARGET_NR_io_submit 2 +#define TARGET_NR_io_cancel 3 +#define TARGET_NR_io_getevents 4 +#define TARGET_NR_setxattr 5 +#define TARGET_NR_lsetxattr 6 +#define TARGET_NR_fsetxattr 7 +#define TARGET_NR_getxattr 8 +#define TARGET_NR_lgetxattr 9 +#define TARGET_NR_fgetxattr 10 +#define TARGET_NR_listxattr 11 +#define TARGET_NR_llistxattr 12 +#define TARGET_NR_flistxattr 13 +#define TARGET_NR_removexattr 14 +#define TARGET_NR_lremovexattr 15 +#define TARGET_NR_fremovexattr 16 +#define TARGET_NR_getcwd 17 +#define TARGET_NR_lookup_dcookie 18 +#define TARGET_NR_eventfd2 19 +#define TARGET_NR_epoll_create1 20 +#define TARGET_NR_epoll_ctl 21 +#define TARGET_NR_epoll_pwait 22 +#define TARGET_NR_dup 23 +#define TARGET_NR_dup3 24 +#define TARGET_NR_fcntl 25 +#define TARGET_NR_inotify_init1 26 +#define TARGET_NR_inotify_add_watch 27 +#define TARGET_NR_inotify_rm_watch 28 +#define TARGET_NR_ioctl 29 +#define TARGET_NR_ioprio_set 30 +#define TARGET_NR_ioprio_get 31 +#define TARGET_NR_flock 32 +#define TARGET_NR_mknodat 33 +#define TARGET_NR_mkdirat 34 +#define TARGET_NR_unlinkat 35 +#define TARGET_NR_symlinkat 36 +#define TARGET_NR_linkat 37 +#define TARGET_NR_renameat 38 +#define TARGET_NR_umount2 39 +#define TARGET_NR_mount 40 +#define TARGET_NR_pivot_root 41 +#define TARGET_NR_nfsservctl 42 +#define TARGET_NR_statfs 43 +#define TARGET_NR_fstatfs 44 +#define TARGET_NR_truncate 45 +#define TARGET_NR_ftruncate 46 +#define TARGET_NR_fallocate 47 +#define TARGET_NR_faccessat 48 +#define TARGET_NR_chdir 49 +#define TARGET_NR_fchdir 50 +#define TARGET_NR_chroot 51 +#define TARGET_NR_fchmod 52 +#define TARGET_NR_fchmodat 53 +#define TARGET_NR_fchownat 54 +#define TARGET_NR_fchown 55 +#define TARGET_NR_openat 56 +#define TARGET_NR_close 57 +#define TARGET_NR_vhangup 58 +#define TARGET_NR_pipe2 59 +#define TARGET_NR_quotactl 60 +#define TARGET_NR_getdents64 61 +#define TARGET_NR_lseek 62 +#define TARGET_NR_read 63 +#define TARGET_NR_write 64 +#define TARGET_NR_readv 65 +#define TARGET_NR_writev 66 +#define TARGET_NR_pread64 67 +#define TARGET_NR_pwrite64 68 +#define TARGET_NR_preadv 69 +#define TARGET_NR_pwritev 70 +#define TARGET_NR_sendfile 71 +#define TARGET_NR_pselect6 72 +#define TARGET_NR_ppoll 73 +#define TARGET_NR_signalfd4 74 +#define TARGET_NR_vmsplice 75 +#define TARGET_NR_splice 76 +#define TARGET_NR_tee 77 +#define TARGET_NR_readlinkat 78 +#define TARGET_NR_fstatat64 79 +#define TARGET_NR_fstat 80 +#define TARGET_NR_sync 81 +#define TARGET_NR_fsync 82 +#define TARGET_NR_fdatasync 83 +#define TARGET_NR_sync_file_range2 84 +/* #define TARGET_NR_sync_file_range 84 */ +#define TARGET_NR_timerfd_create 85 +#define TARGET_NR_timerfd_settime 86 +#define TARGET_NR_timerfd_gettime 87 +#define TARGET_NR_utimensat 88 +#define TARGET_NR_acct 89 +#define TARGET_NR_capget 90 +#define TARGET_NR_capset 91 +#define TARGET_NR_personality 92 +#define TARGET_NR_exit 93 +#define TARGET_NR_exit_group 94 +#define TARGET_NR_waitid 95 +#define TARGET_NR_set_tid_address 96 +#define TARGET_NR_unshare 97 +#define TARGET_NR_futex 98 +#define TARGET_NR_set_robust_list 99 +#define TARGET_NR_get_robust_list 100 +#define TARGET_NR_nanosleep 101 +#define TARGET_NR_getitimer 102 +#define TARGET_NR_setitimer 103 +#define TARGET_NR_kexec_load 104 +#define TARGET_NR_init_module 105 +#define TARGET_NR_delete_module 106 +#define TARGET_NR_timer_create 107 +#define TARGET_NR_timer_gettime 108 +#define TARGET_NR_timer_getoverrun 109 +#define TARGET_NR_timer_settime 110 +#define TARGET_NR_timer_delete 111 +#define TARGET_NR_clock_settime 112 +#define TARGET_NR_clock_gettime 113 +#define TARGET_NR_clock_getres 114 +#define TARGET_NR_clock_nanosleep 115 +#define TARGET_NR_syslog 116 +#define TARGET_NR_ptrace 117 +#define TARGET_NR_sched_setparam 118 +#define TARGET_NR_sched_setscheduler 119 +#define TARGET_NR_sched_getscheduler 120 +#define TARGET_NR_sched_getparam 121 +#define TARGET_NR_sched_setaffinity 122 +#define TARGET_NR_sched_getaffinity 123 +#define TARGET_NR_sched_yield 124 +#define TARGET_NR_sched_get_priority_max 125 +#define TARGET_NR_sched_get_priority_min 126 +#define TARGET_NR_sched_rr_get_interval 127 +#define TARGET_NR_restart_syscall 128 +#define TARGET_NR_kill 129 +#define TARGET_NR_tkill 130 +#define TARGET_NR_tgkill 131 +#define TARGET_NR_sigaltstack 132 +#define TARGET_NR_rt_sigsuspend 133 +#define TARGET_NR_rt_sigaction 134 +#define TARGET_NR_rt_sigprocmask 135 +#define TARGET_NR_rt_sigpending 136 +#define TARGET_NR_rt_sigtimedwait 137 +#define TARGET_NR_rt_sigqueueinfo 138 +#define TARGET_NR_rt_sigreturn 139 +#define TARGET_NR_setpriority 140 +#define TARGET_NR_getpriority 141 +#define TARGET_NR_reboot 142 +#define TARGET_NR_setregid 143 +#define TARGET_NR_setgid 144 +#define TARGET_NR_setreuid 145 +#define TARGET_NR_setuid 146 +#define TARGET_NR_setresuid 147 +#define TARGET_NR_getresuid 148 +#define TARGET_NR_setresgid 149 +#define TARGET_NR_getresgid 150 +#define TARGET_NR_setfsuid 151 +#define TARGET_NR_setfsgid 152 +#define TARGET_NR_times 153 +#define TARGET_NR_setpgid 154 +#define TARGET_NR_getpgid 155 +#define TARGET_NR_getsid 156 +#define TARGET_NR_setsid 157 +#define TARGET_NR_getgroups 158 +#define TARGET_NR_setgroups 159 +#define TARGET_NR_uname 160 +#define TARGET_NR_sethostname 161 +#define TARGET_NR_setdomainname 162 +#define TARGET_NR_getrlimit 163 +#define TARGET_NR_setrlimit 164 +#define TARGET_NR_getrusage 165 +#define TARGET_NR_umask 166 +#define TARGET_NR_prctl 167 +#define TARGET_NR_getcpu 168 +#define TARGET_NR_gettimeofday 169 +#define TARGET_NR_settimeofday 170 +#define TARGET_NR_adjtimex 171 +#define TARGET_NR_getpid 172 +#define TARGET_NR_getppid 173 +#define TARGET_NR_getuid 174 +#define TARGET_NR_geteuid 175 +#define TARGET_NR_getgid 176 +#define TARGET_NR_getegid 177 +#define TARGET_NR_gettid 178 +#define TARGET_NR_sysinfo 179 +#define TARGET_NR_mq_open 180 +#define TARGET_NR_mq_unlink 181 +#define TARGET_NR_mq_timedsend 182 +#define TARGET_NR_mq_timedreceive 183 +#define TARGET_NR_mq_notify 184 +#define TARGET_NR_mq_getsetattr 185 +#define TARGET_NR_msgget 186 +#define TARGET_NR_msgctl 187 +#define TARGET_NR_msgrcv 188 +#define TARGET_NR_msgsnd 189 +#define TARGET_NR_semget 190 +#define TARGET_NR_semctl 191 +#define TARGET_NR_semtimedop 192 +#define TARGET_NR_semop 193 +#define TARGET_NR_shmget 194 +#define TARGET_NR_shmctl 195 +#define TARGET_NR_shmat 196 +#define TARGET_NR_shmdt 197 +#define TARGET_NR_socket 198 +#define TARGET_NR_socketpair 199 +#define TARGET_NR_bind 200 +#define TARGET_NR_listen 201 +#define TARGET_NR_accept 202 +#define TARGET_NR_connect 203 +#define TARGET_NR_getsockname 204 +#define TARGET_NR_getpeername 205 +#define TARGET_NR_sendto 206 +#define TARGET_NR_recvfrom 207 +#define TARGET_NR_setsockopt 208 +#define TARGET_NR_getsockopt 209 +#define TARGET_NR_shutdown 210 +#define TARGET_NR_sendmsg 211 +#define TARGET_NR_recvmsg 212 +#define TARGET_NR_readahead 213 +#define TARGET_NR_brk 214 +#define TARGET_NR_munmap 215 +#define TARGET_NR_mremap 216 +#define TARGET_NR_add_key 217 +#define TARGET_NR_request_key 218 +#define TARGET_NR_keyctl 219 +#define TARGET_NR_clone 220 +#define TARGET_NR_execve 221 +#define TARGET_NR_mmap 222 +#define TARGET_NR_fadvise64 223 +#define TARGET_NR_swapon 224 +#define TARGET_NR_swapoff 225 +#define TARGET_NR_mprotect 226 +#define TARGET_NR_msync 227 +#define TARGET_NR_mlock 228 +#define TARGET_NR_munlock 229 +#define TARGET_NR_mlockall 230 +#define TARGET_NR_munlockall 231 +#define TARGET_NR_mincore 232 +#define TARGET_NR_madvise 233 +#define TARGET_NR_remap_file_pages 234 +#define TARGET_NR_mbind 235 +#define TARGET_NR_get_mempolicy 236 +#define TARGET_NR_set_mempolicy 237 +#define TARGET_NR_migrate_pages 238 +#define TARGET_NR_move_pages 239 +#define TARGET_NR_rt_tgsigqueueinfo 240 +#define TARGET_NR_perf_event_open 241 +#define TARGET_NR_accept4 242 +#define TARGET_NR_recvmmsg 243 +#define TARGET_NR_arch_specific_syscall 244 +#define TARGET_NR_wait4 260 +#define TARGET_NR_prlimit64 261 +#define TARGET_NR_fanotify_init 262 +#define TARGET_NR_fanotify_mark 263 +#define TARGET_NR_name_to_handle_at         264 +#define TARGET_NR_open_by_handle_at         265 +#define TARGET_NR_clock_adjtime 266 +#define TARGET_NR_syncfs 267 +#define TARGET_NR_setns 268 +#define TARGET_NR_sendmmsg 269 +#define TARGET_NR_process_vm_readv 270 +#define TARGET_NR_process_vm_writev 271 +#define TARGET_NR_kcmp 272 +#define TARGET_NR_finit_module 273 +#define TARGET_NR_open 1024 +#define TARGET_NR_link 1025 +#define TARGET_NR_unlink 1026 +#define TARGET_NR_mknod 1027 +#define TARGET_NR_chmod 1028 +#define TARGET_NR_chown 1029 +#define TARGET_NR_mkdir 1030 +#define TARGET_NR_rmdir 1031 +#define TARGET_NR_lchown 1032 +#define TARGET_NR_access 1033 +#define TARGET_NR_rename 1034 +#define TARGET_NR_readlink 1035 +#define TARGET_NR_symlink 1036 +#define TARGET_NR_utimes 1037 +#define TARGET_NR_stat 1038 +#define TARGET_NR_lstat 1039 +#define TARGET_NR_pipe 1040 +#define TARGET_NR_dup2 1041 +#define TARGET_NR_epoll_create 1042 +#define TARGET_NR_inotify_init 1043 +#define TARGET_NR_eventfd 1044 +#define TARGET_NR_signalfd 1045 +#define TARGET_NR_sendfile64 1046 +#define TARGET_NR_ftruncate64 1047 +#define TARGET_NR_truncate64 1048 +#define TARGET_NR_stat64 1049 +#define TARGET_NR_lstat64 1050 +#define TARGET_NR_fstat64 1051 +#define TARGET_NR_fcntl64 1052 +/* #define TARGET_NR_fadvise64 1053 */ +#define TARGET_NR_newfstatat 1054 +#define TARGET_NR_fstatfs64 1055 +#define TARGET_NR_statfs64 1056 +#define TARGET_NR_lseek64 1057 +#define TARGET_NR_mmap64 1058 +#define TARGET_NR_alarm 1059 +#define TARGET_NR_getpgrp 1060 +#define TARGET_NR_pause 1061 +#define TARGET_NR_time 1062 +#define TARGET_NR_utime 1063 +#define TARGET_NR_creat 1064 +#define TARGET_NR_getdents 1065 +#define TARGET_NR_futimesat 1066 +#define TARGET_NR_select 1067 +#define TARGET_NR_poll 1068 +#define TARGET_NR_epoll_wait 1069 +#define TARGET_NR_ustat 1070 +#define TARGET_NR_vfork 1071 +#define TARGET_NR_oldwait4 1072 +#define TARGET_NR_recv 1073 +#define TARGET_NR_send 1074 +#define TARGET_NR_bdflush 1075 +#define TARGET_NR_umount 1076 +#define TARGET_NR_uselib 1077 +#define TARGET_NR__sysctl 1078 +#define TARGET_NR_fork 1079 +#define TARGET_NR_syscalls (__NR_fork+1) + +#define TARGET_NR_sigreturn 1999 diff --git a/linux-user/aarch64/target_cpu.h b/linux-user/aarch64/target_cpu.h new file mode 100644 index 00000000..b5593dc5 --- /dev/null +++ b/linux-user/aarch64/target_cpu.h @@ -0,0 +1,38 @@ +/* + * ARM AArch64 specific CPU ABI and functions for linux-user + * + * Copyright (c) 2013 Alexander Graf <agraf@suse.de> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp) +{ +    if (newsp) { +        env->xregs[31] = newsp; +    } +    env->xregs[0] = 0; +} + +static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls) +{ +    /* Note that AArch64 Linux keeps the TLS pointer in TPIDR; this is +     * different from AArch32 Linux, which uses TPIDRRO. +     */ +    env->cp15.tpidr_el[0] = newtls; +} + +#endif diff --git a/linux-user/aarch64/target_signal.h b/linux-user/aarch64/target_signal.h new file mode 100644 index 00000000..e8c677de --- /dev/null +++ b/linux-user/aarch64/target_signal.h @@ -0,0 +1,29 @@ +#ifndef TARGET_SIGNAL_H +#define TARGET_SIGNAL_H + +#include "cpu.h" + +/* this struct defines a stack used during syscall handling */ + +typedef struct target_sigaltstack { +    abi_ulong ss_sp; +    abi_int ss_flags; +    abi_ulong ss_size; +} target_stack_t; + + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK 1 +#define TARGET_SS_DISABLE 2 + +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_SIGSTKSZ 8192 + +static inline abi_ulong get_sp_from_cpustate(CPUARMState *state) +{ +   return state->xregs[31]; +} + +#endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/aarch64/target_structs.h b/linux-user/aarch64/target_structs.h new file mode 100644 index 00000000..21c1f2c0 --- /dev/null +++ b/linux-user/aarch64/target_structs.h @@ -0,0 +1,58 @@ +/* + * ARM AArch64 specific structures for linux-user + * + * Copyright (c) 2013 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_STRUCTS_H +#define TARGET_STRUCTS_H + +struct target_ipc_perm { +    abi_int __key;                      /* Key.  */ +    abi_uint uid;                       /* Owner's user ID.  */ +    abi_uint gid;                       /* Owner's group ID.  */ +    abi_uint cuid;                      /* Creator's user ID.  */ +    abi_uint cgid;                      /* Creator's group ID.  */ +    abi_ushort mode;                    /* Read/write permission.  */ +    abi_ushort __pad1; +    abi_ushort __seq;                   /* Sequence number.  */ +    abi_ushort __pad2; +    abi_ulong __unused1; +    abi_ulong __unused2; +}; + +struct target_shmid_ds { +    struct target_ipc_perm shm_perm;    /* operation permission struct */ +    abi_long shm_segsz;                 /* size of segment in bytes */ +    abi_ulong shm_atime;                /* time of last shmat() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused1; +#endif +    abi_ulong shm_dtime;                /* time of last shmdt() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused2; +#endif +    abi_ulong shm_ctime;                /* time of last change by shmctl() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused3; +#endif +    abi_int shm_cpid;                   /* pid of creator */ +    abi_int shm_lpid;                   /* pid of last shmop */ +    abi_ulong shm_nattch;               /* number of current attaches */ +    abi_ulong __unused4; +    abi_ulong __unused5; +}; + +#endif diff --git a/linux-user/aarch64/termbits.h b/linux-user/aarch64/termbits.h new file mode 100644 index 00000000..b64ba974 --- /dev/null +++ b/linux-user/aarch64/termbits.h @@ -0,0 +1,220 @@ +/* from asm/termbits.h */ +/* NOTE: exactly the same as i386 */ + +#define TARGET_NCCS 19 + +struct target_termios { +    unsigned int c_iflag;               /* input mode flags */ +    unsigned int c_oflag;               /* output mode flags */ +    unsigned int c_cflag;               /* control mode flags */ +    unsigned int c_lflag;               /* local mode flags */ +    unsigned char c_line;                    /* line discipline */ +    unsigned char c_cc[TARGET_NCCS];                /* control characters */ +}; + +/* c_iflag bits */ +#define TARGET_IGNBRK  0000001 +#define TARGET_BRKINT  0000002 +#define TARGET_IGNPAR  0000004 +#define TARGET_PARMRK  0000010 +#define TARGET_INPCK   0000020 +#define TARGET_ISTRIP  0000040 +#define TARGET_INLCR   0000100 +#define TARGET_IGNCR   0000200 +#define TARGET_ICRNL   0000400 +#define TARGET_IUCLC   0001000 +#define TARGET_IXON    0002000 +#define TARGET_IXANY   0004000 +#define TARGET_IXOFF   0010000 +#define TARGET_IMAXBEL 0020000 +#define TARGET_IUTF8   0040000 + +/* c_oflag bits */ +#define TARGET_OPOST   0000001 +#define TARGET_OLCUC   0000002 +#define TARGET_ONLCR   0000004 +#define TARGET_OCRNL   0000010 +#define TARGET_ONOCR   0000020 +#define TARGET_ONLRET  0000040 +#define TARGET_OFILL   0000100 +#define TARGET_OFDEL   0000200 +#define TARGET_NLDLY   0000400 +#define   TARGET_NL0   0000000 +#define   TARGET_NL1   0000400 +#define TARGET_CRDLY   0003000 +#define   TARGET_CR0   0000000 +#define   TARGET_CR1   0001000 +#define   TARGET_CR2   0002000 +#define   TARGET_CR3   0003000 +#define TARGET_TABDLY  0014000 +#define   TARGET_TAB0  0000000 +#define   TARGET_TAB1  0004000 +#define   TARGET_TAB2  0010000 +#define   TARGET_TAB3  0014000 +#define   TARGET_XTABS 0014000 +#define TARGET_BSDLY   0020000 +#define   TARGET_BS0   0000000 +#define   TARGET_BS1   0020000 +#define TARGET_VTDLY   0040000 +#define   TARGET_VT0   0000000 +#define   TARGET_VT1   0040000 +#define TARGET_FFDLY   0100000 +#define   TARGET_FF0   0000000 +#define   TARGET_FF1   0100000 + +/* c_cflag bit meaning */ +#define TARGET_CBAUD   0010017 +#define  TARGET_B0     0000000         /* hang up */ +#define  TARGET_B50    0000001 +#define  TARGET_B75    0000002 +#define  TARGET_B110   0000003 +#define  TARGET_B134   0000004 +#define  TARGET_B150   0000005 +#define  TARGET_B200   0000006 +#define  TARGET_B300   0000007 +#define  TARGET_B600   0000010 +#define  TARGET_B1200  0000011 +#define  TARGET_B1800  0000012 +#define  TARGET_B2400  0000013 +#define  TARGET_B4800  0000014 +#define  TARGET_B9600  0000015 +#define  TARGET_B19200 0000016 +#define  TARGET_B38400 0000017 +#define TARGET_EXTA B19200 +#define TARGET_EXTB B38400 +#define TARGET_CSIZE   0000060 +#define   TARGET_CS5   0000000 +#define   TARGET_CS6   0000020 +#define   TARGET_CS7   0000040 +#define   TARGET_CS8   0000060 +#define TARGET_CSTOPB  0000100 +#define TARGET_CREAD   0000200 +#define TARGET_PARENB  0000400 +#define TARGET_PARODD  0001000 +#define TARGET_HUPCL   0002000 +#define TARGET_CLOCAL  0004000 +#define TARGET_CBAUDEX 0010000 +#define  TARGET_B57600  0010001 +#define  TARGET_B115200 0010002 +#define  TARGET_B230400 0010003 +#define  TARGET_B460800 0010004 +#define TARGET_CIBAUD    002003600000  /* input baud rate (not used) */ +#define TARGET_CMSPAR    010000000000  /* mark or space (stick) parity */ +#define TARGET_CRTSCTS   020000000000  /* flow control */ + +/* c_lflag bits */ +#define TARGET_ISIG    0000001 +#define TARGET_ICANON  0000002 +#define TARGET_XCASE   0000004 +#define TARGET_ECHO    0000010 +#define TARGET_ECHOE   0000020 +#define TARGET_ECHOK   0000040 +#define TARGET_ECHONL  0000100 +#define TARGET_NOFLSH  0000200 +#define TARGET_TOSTOP  0000400 +#define TARGET_ECHOCTL 0001000 +#define TARGET_ECHOPRT 0002000 +#define TARGET_ECHOKE  0004000 +#define TARGET_FLUSHO  0010000 +#define TARGET_PENDIN  0040000 +#define TARGET_IEXTEN  0100000 + +/* c_cc character offsets */ +#define TARGET_VINTR    0 +#define TARGET_VQUIT    1 +#define TARGET_VERASE   2 +#define TARGET_VKILL    3 +#define TARGET_VEOF     4 +#define TARGET_VTIME    5 +#define TARGET_VMIN     6 +#define TARGET_VSWTC    7 +#define TARGET_VSTART   8 +#define TARGET_VSTOP    9 +#define TARGET_VSUSP    10 +#define TARGET_VEOL     11 +#define TARGET_VREPRINT 12 +#define TARGET_VDISCARD 13 +#define TARGET_VWERASE  14 +#define TARGET_VLNEXT   15 +#define TARGET_VEOL2    16 + +/* ioctls */ + +#define TARGET_TCGETS           0x5401 +#define TARGET_TCSETS           0x5402 +#define TARGET_TCSETSW          0x5403 +#define TARGET_TCSETSF          0x5404 +#define TARGET_TCGETA           0x5405 +#define TARGET_TCSETA           0x5406 +#define TARGET_TCSETAW          0x5407 +#define TARGET_TCSETAF          0x5408 +#define TARGET_TCSBRK           0x5409 +#define TARGET_TCXONC           0x540A +#define TARGET_TCFLSH           0x540B + +#define TARGET_TIOCEXCL         0x540C +#define TARGET_TIOCNXCL         0x540D +#define TARGET_TIOCSCTTY        0x540E +#define TARGET_TIOCGPGRP        0x540F +#define TARGET_TIOCSPGRP        0x5410 +#define TARGET_TIOCOUTQ         0x5411 +#define TARGET_TIOCSTI          0x5412 +#define TARGET_TIOCGWINSZ       0x5413 +#define TARGET_TIOCSWINSZ       0x5414 +#define TARGET_TIOCMGET         0x5415 +#define TARGET_TIOCMBIS         0x5416 +#define TARGET_TIOCMBIC         0x5417 +#define TARGET_TIOCMSET         0x5418 +#define TARGET_TIOCGSOFTCAR     0x5419 +#define TARGET_TIOCSSOFTCAR     0x541A +#define TARGET_FIONREAD         0x541B +#define TARGET_TIOCINQ          TARGET_FIONREAD +#define TARGET_TIOCLINUX        0x541C +#define TARGET_TIOCCONS         0x541D +#define TARGET_TIOCGSERIAL      0x541E +#define TARGET_TIOCSSERIAL      0x541F +#define TARGET_TIOCPKT          0x5420 +#define TARGET_FIONBIO          0x5421 +#define TARGET_TIOCNOTTY        0x5422 +#define TARGET_TIOCSETD         0x5423 +#define TARGET_TIOCGETD         0x5424 +#define TARGET_TCSBRKP          0x5425 /* Needed for POSIX tcsendbreak() */ +#define TARGET_TIOCTTYGSTRUCT   0x5426 /* For debugging only */ +#define TARGET_TIOCSBRK         0x5427 /* BSD compatibility */ +#define TARGET_TIOCCBRK         0x5428 /* BSD compatibility */ +#define TARGET_TIOCGSID         0x5429 /* Return the session ID of FD */ +#define TARGET_TIOCGPTN         TARGET_IOR('T', 0x30, unsigned int) +        /* Get Pty Number (of pty-mux device) */ +#define TARGET_TIOCSPTLCK       TARGET_IOW('T', 0x31, int) +        /* Lock/unlock Pty */ + +#define TARGET_FIONCLEX         0x5450  /* these numbers need to be adjusted. */ +#define TARGET_FIOCLEX          0x5451 +#define TARGET_FIOASYNC         0x5452 +#define TARGET_TIOCSERCONFIG    0x5453 +#define TARGET_TIOCSERGWILD     0x5454 +#define TARGET_TIOCSERSWILD     0x5455 +#define TARGET_TIOCGLCKTRMIOS   0x5456 +#define TARGET_TIOCSLCKTRMIOS   0x5457 +#define TARGET_TIOCSERGSTRUCT   0x5458 /* For debugging only */ +#define TARGET_TIOCSERGETLSR    0x5459 /* Get line status register */ +#define TARGET_TIOCSERGETMULTI  0x545A /* Get multiport config  */ +#define TARGET_TIOCSERSETMULTI  0x545B /* Set multiport config */ + +#define TARGET_TIOCMIWAIT      0x545C +        /* wait for a change on serial input line(s) */ +#define TARGET_TIOCGICOUNT     0x545D +        /* read serial port inline interrupt counts */ +#define TARGET_TIOCGHAYESESP   0x545E  /* Get Hayes ESP configuration */ +#define TARGET_TIOCSHAYESESP   0x545F  /* Set Hayes ESP configuration */ + +/* Used for packet mode */ +#define TARGET_TIOCPKT_DATA              0 +#define TARGET_TIOCPKT_FLUSHREAD         1 +#define TARGET_TIOCPKT_FLUSHWRITE        2 +#define TARGET_TIOCPKT_STOP              4 +#define TARGET_TIOCPKT_START             8 +#define TARGET_TIOCPKT_NOSTOP           16 +#define TARGET_TIOCPKT_DOSTOP           32 + +#define TARGET_TIOCSER_TEMT    0x01 /* Transmitter physically empty */ diff --git a/linux-user/alpha/syscall.h b/linux-user/alpha/syscall.h new file mode 100644 index 00000000..245cff25 --- /dev/null +++ b/linux-user/alpha/syscall.h @@ -0,0 +1,257 @@ +/* default linux values for the selectors */ +#define __USER_DS	(1) + +struct target_pt_regs { +	abi_ulong r0; +	abi_ulong r1; +	abi_ulong r2; +	abi_ulong r3; +	abi_ulong r4; +	abi_ulong r5; +	abi_ulong r6; +	abi_ulong r7; +	abi_ulong r8; +	abi_ulong r19; +	abi_ulong r20; +	abi_ulong r21; +	abi_ulong r22; +	abi_ulong r23; +	abi_ulong r24; +	abi_ulong r25; +	abi_ulong r26; +	abi_ulong r27; +	abi_ulong r28; +	abi_ulong hae; +/* JRP - These are the values provided to a0-a2 by PALcode */ +	abi_ulong trap_a0; +	abi_ulong trap_a1; +	abi_ulong trap_a2; +/* These are saved by PAL-code: */ +	abi_ulong ps; +	abi_ulong pc; +	abi_ulong gp; +	abi_ulong r16; +	abi_ulong r17; +	abi_ulong r18; +/* Those is needed by qemu to temporary store the user stack pointer */ +        abi_ulong usp; +        abi_ulong unique; +}; + +#define UNAME_MACHINE "alpha" +#define UNAME_MINIMUM_RELEASE "2.6.32" + +#undef TARGET_EDEADLK +#define TARGET_EDEADLK		11 +#undef TARGET_EAGAIN +#define TARGET_EAGAIN		35 +#undef TARGET_EINPROGRESS +#define TARGET_EINPROGRESS	36 +#undef TARGET_EALREADY +#define TARGET_EALREADY		37 +#undef TARGET_ENOTSOCK +#define TARGET_ENOTSOCK		38 +#undef TARGET_EDESTADDRREQ +#define TARGET_EDESTADDRREQ	39 +#undef TARGET_EMSGSIZE +#define TARGET_EMSGSIZE		40 +#undef TARGET_EPROTOTYPE +#define TARGET_EPROTOTYPE	41 +#undef TARGET_ENOPROTOOPT +#define TARGET_ENOPROTOOPT	42 +#undef TARGET_EPROTONOSUPPORT +#define TARGET_EPROTONOSUPPORT	43 +#undef TARGET_ESOCKTNOSUPPORT +#define TARGET_ESOCKTNOSUPPORT	44 +#undef TARGET_EOPNOTSUPP +#define TARGET_EOPNOTSUPP	45 +#undef TARGET_EPFNOSUPPORT +#define TARGET_EPFNOSUPPORT	46 +#undef TARGET_EAFNOSUPPORT +#define TARGET_EAFNOSUPPORT	47 +#undef TARGET_EADDRINUSE +#define TARGET_EADDRINUSE	48 +#undef TARGET_EADDRNOTAVAIL +#define TARGET_EADDRNOTAVAIL	49 +#undef TARGET_ENETDOWN +#define TARGET_ENETDOWN		50 +#undef TARGET_ENETUNREACH +#define TARGET_ENETUNREACH	51 +#undef TARGET_ENETRESET +#define TARGET_ENETRESET	52 +#undef TARGET_ECONNABORTED +#define TARGET_ECONNABORTED	53 +#undef TARGET_ECONNRESET +#define TARGET_ECONNRESET	54 +#undef TARGET_ENOBUFS +#define TARGET_ENOBUFS		55 +#undef TARGET_EISCONN +#define TARGET_EISCONN		56 +#undef TARGET_ENOTCONN +#define TARGET_ENOTCONN		57 +#undef TARGET_ESHUTDOWN +#define TARGET_ESHUTDOWN	58 +#undef TARGET_ETOOMANYREFS +#define TARGET_ETOOMANYREFS	59 +#undef TARGET_ETIMEDOUT +#define TARGET_ETIMEDOUT	60 +#undef TARGET_ECONNREFUSED +#define TARGET_ECONNREFUSED	61 +#undef TARGET_ELOOP +#define TARGET_ELOOP		62 +#undef TARGET_ENAMETOOLONG +#define TARGET_ENAMETOOLONG	63 +#undef TARGET_EHOSTDOWN +#define TARGET_EHOSTDOWN	64 +#undef TARGET_EHOSTUNREACH +#define TARGET_EHOSTUNREACH	65 +#undef TARGET_ENOTEMPTY +#define TARGET_ENOTEMPTY	66 +// Unused			67 +#undef TARGET_EUSERS +#define TARGET_EUSERS		68 +#undef TARGET_EDQUOT +#define TARGET_EDQUOT		69 +#undef TARGET_ESTALE +#define TARGET_ESTALE		70 +#undef TARGET_EREMOTE +#define TARGET_EREMOTE		71 +// Unused			72-76 +#undef TARGET_ENOLCK +#define TARGET_ENOLCK		77 +#undef TARGET_ENOSYS +#define TARGET_ENOSYS		78 +// Unused			79 +#undef TARGET_ENOMSG +#define TARGET_ENOMSG		80 +#undef TARGET_EIDRM +#define TARGET_EIDRM		81 +#undef TARGET_ENOSR +#define TARGET_ENOSR		82 +#undef TARGET_ETIME +#define TARGET_ETIME		83 +#undef TARGET_EBADMSG +#define TARGET_EBADMSG		84 +#undef TARGET_EPROTO +#define TARGET_EPROTO		85 +#undef TARGET_ENODATA +#define TARGET_ENODATA		86 +#undef TARGET_ENOSTR +#define TARGET_ENOSTR		87 +#undef TARGET_ECHRNG +#define TARGET_ECHRNG		88 +#undef TARGET_EL2NSYNC +#define TARGET_EL2NSYNC		89 +#undef TARGET_EL3HLT +#define TARGET_EL3HLT		90 +#undef TARGET_EL3RST +#define TARGET_EL3RST		91 +#undef TARGET_ENOPKG +#define TARGET_ENOPKG		92 +#undef TARGET_ELNRNG +#define TARGET_ELNRNG		93 +#undef TARGET_EUNATCH +#define TARGET_EUNATCH		94 +#undef TARGET_ENOCSI +#define TARGET_ENOCSI		95 +#undef TARGET_EL2HLT +#define TARGET_EL2HLT		96 +#undef TARGET_EBADE +#define TARGET_EBADE		97 +#undef TARGET_EBADR +#define TARGET_EBADR		98 +#undef TARGET_EXFULL +#define TARGET_EXFULL		99 +#undef TARGET_ENOANO +#define TARGET_ENOANO		100 +#undef TARGET_EBADRQC +#define TARGET_EBADRQC		101 +#undef TARGET_EBADSLT +#define TARGET_EBADSLT		102 +// Unused			103 +#undef TARGET_EBFONT +#define TARGET_EBFONT		104 +#undef TARGET_ENONET +#define TARGET_ENONET		105 +#undef TARGET_ENOLINK +#define TARGET_ENOLINK		106 +#undef TARGET_EADV +#define TARGET_EADV		107 +#undef TARGET_ESRMNT +#define TARGET_ESRMNT		108 +#undef TARGET_ECOMM +#define TARGET_ECOMM		109 +#undef TARGET_EMULTIHOP +#define TARGET_EMULTIHOP	110 +#undef TARGET_EDOTDOT +#define TARGET_EDOTDOT		111 +#undef TARGET_EOVERFLOW +#define TARGET_EOVERFLOW	112 +#undef TARGET_ENOTUNIQ +#define TARGET_ENOTUNIQ		113 +#undef TARGET_EBADFD +#define TARGET_EBADFD		114 +#undef TARGET_EREMCHG +#define TARGET_EREMCHG		115 +#undef TARGET_EILSEQ +#define TARGET_EILSEQ		116 + +// Same as default		117-121 + +#undef TARGET_ELIBACC +#define TARGET_ELIBACC		122 +#undef TARGET_ELIBBAD +#define TARGET_ELIBBAD		123 +#undef TARGET_ELIBSCN +#define TARGET_ELIBSCN		124 +#undef TARGET_ELIBMAX +#define TARGET_ELIBMAX		125 +#undef TARGET_ELIBEXEC +#define TARGET_ELIBEXEC		126 +#undef TARGET_ERESTART +#define TARGET_ERESTART		127 +#undef TARGET_ESTRPIPE +#define TARGET_ESTRPIPE		128 +#undef TARGET_ENOMEDIUM +#define TARGET_ENOMEDIUM	129 +#undef TARGET_EMEDIUMTYPE +#define TARGET_EMEDIUMTYPE	130 +#undef TARGET_ECANCELED +#define TARGET_ECANCELED	131 +#undef TARGET_ENOKEY +#define TARGET_ENOKEY		132 +#undef TARGET_EKEYEXPIRED +#define TARGET_EKEYEXPIRED	133 +#undef TARGET_EKEYREVOKED +#define TARGET_EKEYREVOKED	134 +#undef TARGET_EKEYREJECTED +#define TARGET_EKEYREJECTED	135 +#undef TARGET_EOWNERDEAD +#define TARGET_EOWNERDEAD	136 +#undef TARGET_ENOTRECOVERABLE +#define TARGET_ENOTRECOVERABLE	137 +#undef TARGET_ERFKILL +#define TARGET_ERFKILL		138 + +// For sys_osf_getsysinfo +#define TARGET_GSI_UACPROC		8 +#define TARGET_GSI_IEEE_FP_CONTROL	45 +#define TARGET_GSI_IEEE_STATE_AT_SIGNAL	46 +#define TARGET_GSI_PROC_TYPE		60 +#define TARGET_GSI_GET_HWRPB		101 + +// For sys_ofs_setsysinfo +#define TARGET_SSI_NVPAIRS		1 +#define TARGET_SSI_IEEE_FP_CONTROL	14 +#define TARGET_SSI_IEEE_STATE_AT_SIGNAL	15 +#define TARGET_SSI_IEEE_IGNORE_STATE_AT_SIGNAL 16 +#define TARGET_SSI_IEEE_RAISE_EXCEPTION	1001 + +#define TARGET_SSIN_UACPROC		6 + +#define TARGET_UAC_NOPRINT		1 +#define TARGET_UAC_NOFIX		2 +#define TARGET_UAC_SIGBUS		4 +#define TARGET_MINSIGSTKSZ              4096 +#define TARGET_MLOCKALL_MCL_CURRENT     0x2000 +#define TARGET_MLOCKALL_MCL_FUTURE      0x4000 diff --git a/linux-user/alpha/syscall_nr.h b/linux-user/alpha/syscall_nr.h new file mode 100644 index 00000000..dde8d5c6 --- /dev/null +++ b/linux-user/alpha/syscall_nr.h @@ -0,0 +1,446 @@ +#define TARGET_NR_osf_syscall	  0	/* not implemented */ +#define TARGET_NR_exit		  1 +#define TARGET_NR_fork		  2 +#define TARGET_NR_read		  3 +#define TARGET_NR_write		  4 +#define TARGET_NR_osf_old_open	  5	/* not implemented */ +#define TARGET_NR_close		  6 +#define TARGET_NR_osf_wait4		  7 +#define TARGET_NR_osf_old_creat	  8	/* not implemented */ +#define TARGET_NR_link		  9 +#define TARGET_NR_unlink		 10 +#define TARGET_NR_osf_execve		 11	/* not implemented */ +#define TARGET_NR_chdir		 12 +#define TARGET_NR_fchdir		 13 +#define TARGET_NR_mknod		 14 +#define TARGET_NR_chmod		 15 +#define TARGET_NR_chown		 16 +#define TARGET_NR_brk		 17 +#define TARGET_NR_osf_getfsstat	 18	/* not implemented */ +#define TARGET_NR_lseek		 19 +#define TARGET_NR_getxpid		 20 +#define TARGET_NR_osf_mount		 21 +#define TARGET_NR_umount2		 22 +#define TARGET_NR_setuid		 23 +#define TARGET_NR_getxuid		 24 +#define TARGET_NR_exec_with_loader	 25	/* not implemented */ +#define TARGET_NR_ptrace		 26 +#define TARGET_NR_osf_nrecvmsg	 27	/* not implemented */ +#define TARGET_NR_osf_nsendmsg	 28	/* not implemented */ +#define TARGET_NR_osf_nrecvfrom	 29	/* not implemented */ +#define TARGET_NR_osf_naccept	 30	/* not implemented */ +#define TARGET_NR_osf_ngetpeername	 31	/* not implemented */ +#define TARGET_NR_osf_ngetsockname	 32	/* not implemented */ +#define TARGET_NR_access		 33 +#define TARGET_NR_osf_chflags	 34	/* not implemented */ +#define TARGET_NR_osf_fchflags	 35	/* not implemented */ +#define TARGET_NR_sync		 36 +#define TARGET_NR_kill		 37 +#define TARGET_NR_osf_old_stat	 38	/* not implemented */ +#define TARGET_NR_setpgid		 39 +#define TARGET_NR_osf_old_lstat	 40	/* not implemented */ +#define TARGET_NR_dup		 41 +#define TARGET_NR_pipe		 42 +#define TARGET_NR_osf_set_program_attributes	43 +#define TARGET_NR_osf_profil		 44	/* not implemented */ +#define TARGET_NR_open		 45 +#define TARGET_NR_osf_old_sigaction	 46	/* not implemented */ +#define TARGET_NR_getxgid		 47 +#define TARGET_NR_sigprocmask    48 +#define TARGET_NR_osf_getlogin	 49	/* not implemented */ +#define TARGET_NR_osf_setlogin	 50	/* not implemented */ +#define TARGET_NR_acct		 51 +#define TARGET_NR_sigpending		 52 + +#define TARGET_NR_ioctl		 54 +#define TARGET_NR_osf_reboot		 55	/* not implemented */ +#define TARGET_NR_osf_revoke		 56	/* not implemented */ +#define TARGET_NR_symlink		 57 +#define TARGET_NR_readlink		 58 +#define TARGET_NR_execve		 59 +#define TARGET_NR_umask		 60 +#define TARGET_NR_chroot		 61 +#define TARGET_NR_osf_old_fstat	 62	/* not implemented */ +#define TARGET_NR_getpgrp		 63 +#define TARGET_NR_getpagesize	 64 +#define TARGET_NR_osf_mremap		 65	/* not implemented */ +#define TARGET_NR_vfork		 66 +#define TARGET_NR_stat		 67 +#define TARGET_NR_lstat		 68 +#define TARGET_NR_osf_sbrk		 69	/* not implemented */ +#define TARGET_NR_osf_sstk		 70	/* not implemented */ +#define TARGET_NR_mmap		 71	/* OSF/1 mmap is superset of Linux */ +#define TARGET_NR_osf_old_vadvise	 72	/* not implemented */ +#define TARGET_NR_munmap		 73 +#define TARGET_NR_mprotect		 74 +#define TARGET_NR_madvise		 75 +#define TARGET_NR_vhangup		 76 +#define TARGET_NR_osf_kmodcall	 77	/* not implemented */ +#define TARGET_NR_osf_mincore	 78	/* not implemented */ +#define TARGET_NR_getgroups		 79 +#define TARGET_NR_setgroups		 80 +#define TARGET_NR_osf_old_getpgrp	 81	/* not implemented */ +#define TARGET_NR_setpgrp		 82	/* BSD alias for setpgid */ +#define TARGET_NR_osf_setitimer	 83 +#define TARGET_NR_osf_old_wait	 84	/* not implemented */ +#define TARGET_NR_osf_table		 85	/* not implemented */ +#define TARGET_NR_osf_getitimer	 86 +#define TARGET_NR_gethostname	 87 +#define TARGET_NR_sethostname	 88 +#define TARGET_NR_getdtablesize	 89 +#define TARGET_NR_dup2		 90 +#define TARGET_NR_fstat		 91 +#define TARGET_NR_fcntl		 92 +#define TARGET_NR_osf_select		 93 +#define TARGET_NR_poll		 94 +#define TARGET_NR_fsync		 95 +#define TARGET_NR_setpriority	 96 +#define TARGET_NR_socket		 97 +#define TARGET_NR_connect		 98 +#define TARGET_NR_accept		 99 +#define TARGET_NR_getpriority	100 +#define TARGET_NR_send		101 +#define TARGET_NR_recv		102 +#define TARGET_NR_sigreturn		103 +#define TARGET_NR_bind		104 +#define TARGET_NR_setsockopt		105 +#define TARGET_NR_listen		106 +#define TARGET_NR_osf_plock		107	/* not implemented */ +#define TARGET_NR_osf_old_sigvec	108	/* not implemented */ +#define TARGET_NR_osf_old_sigblock	109	/* not implemented */ +#define TARGET_NR_osf_old_sigsetmask	110	/* not implemented */ +#define TARGET_NR_sigsuspend		111 +#define TARGET_NR_osf_sigstack	112 +#define TARGET_NR_recvmsg		113 +#define TARGET_NR_sendmsg		114 +#define TARGET_NR_osf_old_vtrace	115	/* not implemented */ +#define TARGET_NR_osf_gettimeofday	116 +#define TARGET_NR_osf_getrusage	117 +#define TARGET_NR_getsockopt		118 + +#define TARGET_NR_readv		120 +#define TARGET_NR_writev		121 +#define TARGET_NR_osf_settimeofday	122 +#define TARGET_NR_fchown		123 +#define TARGET_NR_fchmod		124 +#define TARGET_NR_recvfrom		125 +#define TARGET_NR_setreuid		126 +#define TARGET_NR_setregid		127 +#define TARGET_NR_rename		128 +#define TARGET_NR_truncate		129 +#define TARGET_NR_ftruncate		130 +#define TARGET_NR_flock		131 +#define TARGET_NR_setgid		132 +#define TARGET_NR_sendto		133 +#define TARGET_NR_shutdown		134 +#define TARGET_NR_socketpair		135 +#define TARGET_NR_mkdir		136 +#define TARGET_NR_rmdir		137 +#define TARGET_NR_osf_utimes		138 +#define TARGET_NR_osf_old_sigreturn	139	/* not implemented */ +#define TARGET_NR_osf_adjtime	140	/* not implemented */ +#define TARGET_NR_getpeername	141 +#define TARGET_NR_osf_gethostid	142	/* not implemented */ +#define TARGET_NR_osf_sethostid	143	/* not implemented */ +#define TARGET_NR_getrlimit		144 +#define TARGET_NR_setrlimit		145 +#define TARGET_NR_osf_old_killpg	146	/* not implemented */ +#define TARGET_NR_setsid		147 +#define TARGET_NR_quotactl		148 +#define TARGET_NR_osf_oldquota	149	/* not implemented */ +#define TARGET_NR_getsockname	150 + +#define TARGET_NR_osf_pid_block	153	/* not implemented */ +#define TARGET_NR_osf_pid_unblock	154	/* not implemented */ + +#define TARGET_NR_sigaction		156 +#define TARGET_NR_osf_sigwaitprim	157	/* not implemented */ +#define TARGET_NR_osf_nfssvc		158	/* not implemented */ +#define TARGET_NR_osf_getdirentries	159 +#define TARGET_NR_osf_statfs		160 +#define TARGET_NR_osf_fstatfs	161 + +#define TARGET_NR_osf_asynch_daemon	163	/* not implemented */ +#define TARGET_NR_osf_getfh		164	/* not implemented */ +#define TARGET_NR_osf_getdomainname	165 +#define TARGET_NR_setdomainname	166 + +#define TARGET_NR_osf_exportfs	169	/* not implemented */ + +#define TARGET_NR_osf_alt_plock	181	/* not implemented */ + +#define TARGET_NR_osf_getmnt		184	/* not implemented */ + +#define TARGET_NR_osf_alt_sigpending	187	/* not implemented */ +#define TARGET_NR_osf_alt_setsid	188	/* not implemented */ + +#define TARGET_NR_osf_swapon		199 +#define TARGET_NR_msgctl		200 +#define TARGET_NR_msgget		201 +#define TARGET_NR_msgrcv		202 +#define TARGET_NR_msgsnd		203 +#define TARGET_NR_semctl		204 +#define TARGET_NR_semget		205 +#define TARGET_NR_semop		206 +#define TARGET_NR_osf_utsname	207 +#define TARGET_NR_lchown		208 +#define TARGET_NR_osf_shmat		209 +/* this has the usual shmat semantics so give it the name syscall.c expects + * so that our support for it is enabled. + */ +#define TARGET_NR_shmat TARGET_NR_osf_shmat +#define TARGET_NR_shmctl		210 +#define TARGET_NR_shmdt		211 +#define TARGET_NR_shmget		212 +#define TARGET_NR_osf_mvalid		213	/* not implemented */ +#define TARGET_NR_osf_getaddressconf	214	/* not implemented */ +#define TARGET_NR_osf_msleep		215	/* not implemented */ +#define TARGET_NR_osf_mwakeup	216	/* not implemented */ +#define TARGET_NR_msync		217 +#define TARGET_NR_osf_signal		218	/* not implemented */ +#define TARGET_NR_osf_utc_gettime	219	/* not implemented */ +#define TARGET_NR_osf_utc_adjtime	220	/* not implemented */ + +#define TARGET_NR_osf_security	222	/* not implemented */ +#define TARGET_NR_osf_kloadcall	223	/* not implemented */ + +#define TARGET_NR_getpgid		233 +#define TARGET_NR_getsid		234 +#define TARGET_NR_sigaltstack	235 +#define TARGET_NR_osf_waitid		236	/* not implemented */ +#define TARGET_NR_osf_priocntlset	237	/* not implemented */ +#define TARGET_NR_osf_sigsendset	238	/* not implemented */ +#define TARGET_NR_osf_set_speculative	239	/* not implemented */ +#define TARGET_NR_osf_msfs_syscall	240	/* not implemented */ +#define TARGET_NR_osf_sysinfo	241 +#define TARGET_NR_osf_uadmin		242	/* not implemented */ +#define TARGET_NR_osf_fuser		243	/* not implemented */ +#define TARGET_NR_osf_proplist_syscall    244 +#define TARGET_NR_osf_ntp_adjtime	245	/* not implemented */ +#define TARGET_NR_osf_ntp_gettime	246	/* not implemented */ +#define TARGET_NR_osf_pathconf	247	/* not implemented */ +#define TARGET_NR_osf_fpathconf	248	/* not implemented */ + +#define TARGET_NR_osf_uswitch	250	/* not implemented */ +#define TARGET_NR_osf_usleep_thread	251 +#define TARGET_NR_osf_audcntl	252	/* not implemented */ +#define TARGET_NR_osf_audgen		253	/* not implemented */ +#define TARGET_NR_sysfs		254 +#define TARGET_NR_osf_subsys_info	255	/* not implemented */ +#define TARGET_NR_osf_getsysinfo	256 +#define TARGET_NR_osf_setsysinfo	257 +#define TARGET_NR_osf_afs_syscall	258	/* not implemented */ +#define TARGET_NR_osf_swapctl	259	/* not implemented */ +#define TARGET_NR_osf_memcntl	260	/* not implemented */ +#define TARGET_NR_osf_fdatasync	261	/* not implemented */ + + +/* + * Linux-specific system calls begin at 300 + */ +#define TARGET_NR_bdflush		300 +#define TARGET_NR_sethae		301 +#define TARGET_NR_mount		302 +#define TARGET_NR_old_adjtimex	303 +#define TARGET_NR_swapoff		304 +#define TARGET_NR_getdents		305 +#define TARGET_NR_create_module	306 +#define TARGET_NR_init_module	307 +#define TARGET_NR_delete_module	308 +#define TARGET_NR_get_kernel_syms	309 +#define TARGET_NR_syslog		310 +#define TARGET_NR_reboot		311 +#define TARGET_NR_clone		312 +#define TARGET_NR_uselib		313 +#define TARGET_NR_mlock		314 +#define TARGET_NR_munlock		315 +#define TARGET_NR_mlockall		316 +#define TARGET_NR_munlockall		317 +#define TARGET_NR_sysinfo		318 +#define TARGET_NR__sysctl		319 +/* 320 was sys_idle.  */ +#define TARGET_NR_umount		321 +#define TARGET_NR_swapon		322 +#define TARGET_NR_times		323 +#define TARGET_NR_personality	324 +#define TARGET_NR_setfsuid		325 +#define TARGET_NR_setfsgid		326 +#define TARGET_NR_ustat		327 +#define TARGET_NR_statfs		328 +#define TARGET_NR_fstatfs		329 +#define TARGET_NR_sched_setparam		330 +#define TARGET_NR_sched_getparam		331 +#define TARGET_NR_sched_setscheduler		332 +#define TARGET_NR_sched_getscheduler		333 +#define TARGET_NR_sched_yield		334 +#define TARGET_NR_sched_get_priority_max	335 +#define TARGET_NR_sched_get_priority_min	336 +#define TARGET_NR_sched_rr_get_interval	337 +#define TARGET_NR_afs_syscall		338 +#define TARGET_NR_uname			339 +#define TARGET_NR_nanosleep			340 +#define TARGET_NR_mremap			341 +#define TARGET_NR_nfsservctl			342 +#define TARGET_NR_setresuid			343 +#define TARGET_NR_getresuid			344 +#define TARGET_NR_pciconfig_read		345 +#define TARGET_NR_pciconfig_write		346 +#define TARGET_NR_query_module		347 +#define TARGET_NR_prctl			348 +#define TARGET_NR_pread64			349 +#define TARGET_NR_pwrite64			350 +#define TARGET_NR_rt_sigreturn		351 +#define TARGET_NR_rt_sigaction		352 +#define TARGET_NR_rt_sigprocmask		353 +#define TARGET_NR_rt_sigpending		354 +#define TARGET_NR_rt_sigtimedwait		355 +#define TARGET_NR_rt_sigqueueinfo		356 +#define TARGET_NR_rt_sigsuspend		357 +#define TARGET_NR_select			358 +#define TARGET_NR_gettimeofday		359 +#define TARGET_NR_settimeofday		360 +#define TARGET_NR_getitimer			361 +#define TARGET_NR_setitimer			362 +#define TARGET_NR_utimes			363 +#define TARGET_NR_getrusage			364 +#define TARGET_NR_wait4			365 +#define TARGET_NR_adjtimex			366 +#define TARGET_NR_getcwd			367 +#define TARGET_NR_capget			368 +#define TARGET_NR_capset			369 +#define TARGET_NR_sendfile			370 +#define TARGET_NR_setresgid			371 +#define TARGET_NR_getresgid			372 +#define TARGET_NR_dipc			373 +#define TARGET_NR_pivot_root			374 +#define TARGET_NR_mincore			375 +#define TARGET_NR_pciconfig_iobase		376 +#define TARGET_NR_getdents64			377 +#define TARGET_NR_gettid			378 +#define TARGET_NR_readahead			379 +/* 380 is unused */ +#define TARGET_NR_tkill			381 +#define TARGET_NR_setxattr			382 +#define TARGET_NR_lsetxattr			383 +#define TARGET_NR_fsetxattr			384 +#define TARGET_NR_getxattr			385 +#define TARGET_NR_lgetxattr			386 +#define TARGET_NR_fgetxattr			387 +#define TARGET_NR_listxattr			388 +#define TARGET_NR_llistxattr			389 +#define TARGET_NR_flistxattr			390 +#define TARGET_NR_removexattr		391 +#define TARGET_NR_lremovexattr		392 +#define TARGET_NR_fremovexattr		393 +#define TARGET_NR_futex			394 +#define TARGET_NR_sched_setaffinity		395 +#define TARGET_NR_sched_getaffinity		396 +#define TARGET_NR_tuxcall			397 +#define TARGET_NR_io_setup			398 +#define TARGET_NR_io_destroy			399 +#define TARGET_NR_io_getevents		400 +#define TARGET_NR_io_submit			401 +#define TARGET_NR_io_cancel			402 +#define TARGET_NR_exit_group			405 +#define TARGET_NR_lookup_dcookie		406 +#define TARGET_NR_sys_epoll_create		407 +#define TARGET_NR_sys_epoll_ctl		408 +#define TARGET_NR_sys_epoll_wait		409 +#define TARGET_NR_remap_file_pages		410 +#define TARGET_NR_set_tid_address		411 +#define TARGET_NR_restart_syscall		412 +#define TARGET_NR_fadvise64			413 +#define TARGET_NR_timer_create		414 +#define TARGET_NR_timer_settime		415 +#define TARGET_NR_timer_gettime		416 +#define TARGET_NR_timer_getoverrun		417 +#define TARGET_NR_timer_delete		418 +#define TARGET_NR_clock_settime		419 +#define TARGET_NR_clock_gettime		420 +#define TARGET_NR_clock_getres		421 +#define TARGET_NR_clock_nanosleep		422 +#define TARGET_NR_semtimedop			423 +#define TARGET_NR_tgkill			424 +#define TARGET_NR_stat64			425 +#define TARGET_NR_lstat64			426 +#define TARGET_NR_fstat64			427 +#define TARGET_NR_vserver			428 +#define TARGET_NR_mbind			429 +#define TARGET_NR_get_mempolicy		430 +#define TARGET_NR_set_mempolicy		431 +#define TARGET_NR_mq_open			432 +#define TARGET_NR_mq_unlink			433 +#define TARGET_NR_mq_timedsend		434 +#define TARGET_NR_mq_timedreceive		435 +#define TARGET_NR_mq_notify			436 +#define TARGET_NR_mq_getsetattr		437 +#define TARGET_NR_waitid			438 +#define TARGET_NR_add_key			439 +#define TARGET_NR_request_key		440 +#define TARGET_NR_keyctl			441 +#define TARGET_NR_ioprio_set			442 +#define TARGET_NR_ioprio_get			443 +#define TARGET_NR_inotify_init		444 +#define TARGET_NR_inotify_add_watch		445 +#define TARGET_NR_inotify_rm_watch		446 +#define TARGET_NR_fdatasync			447 +#define TARGET_NR_kexec_load			448 +#define TARGET_NR_migrate_pages		449 +#define TARGET_NR_openat			450 +#define TARGET_NR_mkdirat			451 +#define TARGET_NR_mknodat			452 +#define TARGET_NR_fchownat			453 +#define TARGET_NR_futimesat			454 +#define TARGET_NR_fstatat64			455 +#define TARGET_NR_unlinkat			456 +#define TARGET_NR_renameat			457 +#define TARGET_NR_linkat			458 +#define TARGET_NR_symlinkat			459 +#define TARGET_NR_readlinkat			460 +#define TARGET_NR_fchmodat			461 +#define TARGET_NR_faccessat			462 +#define TARGET_NR_pselect6			463 +#define TARGET_NR_ppoll			464 +#define TARGET_NR_unshare			465 +#define TARGET_NR_set_robust_list		466 +#define TARGET_NR_get_robust_list		467 +#define TARGET_NR_splice			468 +#define TARGET_NR_sync_file_range		469 +#define TARGET_NR_tee			470 +#define TARGET_NR_vmsplice			471 +#define TARGET_NR_move_pages			472 +#define TARGET_NR_getcpu			473 +#define TARGET_NR_epoll_pwait		474 +#define TARGET_NR_utimensat			475 +#define TARGET_NR_signalfd			476 +#define TARGET_NR_timerfd			477 +#define TARGET_NR_eventfd			478 +#define TARGET_NR_recvmmsg                      479 +#define TARGET_NR_fallocate                     480 +#define TARGET_NR_timerfd_create                481 +#define TARGET_NR_timerfd_settime               482 +#define TARGET_NR_timerfd_gettime               483 +#define TARGET_NR_signalfd4                     484 +#define TARGET_NR_eventfd2                      485 +#define TARGET_NR_epoll_create1                 486 +#define TARGET_NR_dup3                          487 +#define TARGET_NR_pipe2                         488 +#define TARGET_NR_inotify_init1                 489 +#define TARGET_NR_preadv                        490 +#define TARGET_NR_pwritev                       491 +#define TARGET_NR_rt_tgsigqueueinfo             492 +#define TARGET_NR_perf_event_open               493 +#define TARGET_NR_fanotify_init                 494 +#define TARGET_NR_fanotify_mark                 495 +#define TARGET_NR_prlimit64                     496 +#define TARGET_NR_name_to_handle_at             497 +#define TARGET_NR_open_by_handle_at             498 +#define TARGET_NR_clock_adjtime                 499 +#define TARGET_NR_syncfs                        500 +#define TARGET_NR_setns                         501 +#define TARGET_NR_accept4                       502 +#define TARGET_NR_sendmmsg                      503 +#define TARGET_NR_process_vm_readv              504 +#define TARGET_NR_process_vm_writev             505 +#define TARGET_NR_kcmp                          506 +#define TARGET_NR_finit_module                  507 diff --git a/linux-user/alpha/target_cpu.h b/linux-user/alpha/target_cpu.h new file mode 100644 index 00000000..42562452 --- /dev/null +++ b/linux-user/alpha/target_cpu.h @@ -0,0 +1,36 @@ +/* + * Alpha specific CPU ABI and functions for linux-user + * + *  Copyright (c) 2007 Jocelyn Mayer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUAlphaState *env, target_ulong newsp) +{ +    if (newsp) { +        env->ir[IR_SP] = newsp; +    } +    env->ir[IR_V0] = 0; +    env->ir[IR_A3] = 0; +} + +static inline void cpu_set_tls(CPUAlphaState *env, target_ulong newtls) +{ +    env->unique = newtls; +} + +#endif diff --git a/linux-user/alpha/target_signal.h b/linux-user/alpha/target_signal.h new file mode 100644 index 00000000..d3822da6 --- /dev/null +++ b/linux-user/alpha/target_signal.h @@ -0,0 +1,57 @@ +#ifndef TARGET_SIGNAL_H +#define TARGET_SIGNAL_H + +#include "cpu.h" + +/* this struct defines a stack used during syscall handling */ + +typedef struct target_sigaltstack { +    abi_ulong ss_sp; +    int32_t ss_flags; +    int32_t dummy; +    abi_ulong ss_size; +} target_stack_t; + + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK	1 +#define TARGET_SS_DISABLE	2 + +#define TARGET_MINSIGSTKSZ	4096 +#define TARGET_SIGSTKSZ		16384 + +static inline abi_ulong get_sp_from_cpustate(CPUAlphaState *state) +{ +    return state->ir[IR_SP]; +} + +/* From <asm/gentrap.h>.  */ +#define TARGET_GEN_INTOVF      -1      /* integer overflow */ +#define TARGET_GEN_INTDIV      -2      /* integer division by zero */ +#define TARGET_GEN_FLTOVF      -3      /* fp overflow */ +#define TARGET_GEN_FLTDIV      -4      /* fp division by zero */ +#define TARGET_GEN_FLTUND      -5      /* fp underflow */ +#define TARGET_GEN_FLTINV      -6      /* invalid fp operand */ +#define TARGET_GEN_FLTINE      -7      /* inexact fp operand */ +#define TARGET_GEN_DECOVF      -8      /* decimal overflow (for COBOL??) */ +#define TARGET_GEN_DECDIV      -9      /* decimal division by zero */ +#define TARGET_GEN_DECINV      -10     /* invalid decimal operand */ +#define TARGET_GEN_ROPRAND     -11     /* reserved operand */ +#define TARGET_GEN_ASSERTERR   -12     /* assertion error */ +#define TARGET_GEN_NULPTRERR   -13     /* null pointer error */ +#define TARGET_GEN_STKOVF      -14     /* stack overflow */ +#define TARGET_GEN_STRLENERR   -15     /* string length error */ +#define TARGET_GEN_SUBSTRERR   -16     /* substring error */ +#define TARGET_GEN_RANGERR     -17     /* range error */ +#define TARGET_GEN_SUBRNG      -18 +#define TARGET_GEN_SUBRNG1     -19 +#define TARGET_GEN_SUBRNG2     -20 +#define TARGET_GEN_SUBRNG3     -21 +#define TARGET_GEN_SUBRNG4     -22 +#define TARGET_GEN_SUBRNG5     -23 +#define TARGET_GEN_SUBRNG6     -24 +#define TARGET_GEN_SUBRNG7     -25 + +#endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/alpha/target_structs.h b/linux-user/alpha/target_structs.h new file mode 100644 index 00000000..50e7708f --- /dev/null +++ b/linux-user/alpha/target_structs.h @@ -0,0 +1,48 @@ +/* + * Alpha specific structures for linux-user + * + * Copyright (c) 2013 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_STRUCTS_H +#define TARGET_STRUCTS_H + +struct target_ipc_perm { +    abi_int __key;                      /* Key.  */ +    abi_uint uid;                       /* Owner's user ID.  */ +    abi_uint gid;                       /* Owner's group ID.  */ +    abi_uint cuid;                      /* Creator's user ID.  */ +    abi_uint cgid;                      /* Creator's group ID.  */ +    abi_uint mode;                      /* Read/write permission.  */ +    abi_ushort __seq;                   /* Sequence number.  */ +    abi_ushort __pad1; +    abi_ulong __unused1; +    abi_ulong __unused2; +}; + +struct target_shmid_ds { +    struct target_ipc_perm shm_perm;    /* operation permission struct */ +    abi_long shm_segsz;                 /* size of segment in bytes */ +    abi_ulong shm_atime;                /* time of last shmat() */ +    abi_ulong shm_dtime;                /* time of last shmdt() */ +    abi_ulong shm_ctime;                /* time of last change by shmctl() */ +    abi_int shm_cpid;                   /* pid of creator */ +    abi_int shm_lpid;                   /* pid of last shmop */ +    abi_ulong shm_nattch;               /* number of current attaches */ +    abi_ulong __unused1; +    abi_ulong __unused2; +}; + +#endif diff --git a/linux-user/alpha/termbits.h b/linux-user/alpha/termbits.h new file mode 100644 index 00000000..6406b6a7 --- /dev/null +++ b/linux-user/alpha/termbits.h @@ -0,0 +1,264 @@ +typedef unsigned char	target_cc_t; +typedef unsigned int	target_speed_t; +typedef unsigned int	target_tcflag_t; + +#define TARGET_NCCS 19 +struct target_termios { +	target_tcflag_t c_iflag;		/* input mode flags */ +	target_tcflag_t c_oflag;		/* output mode flags */ +	target_tcflag_t c_cflag;		/* control mode flags */ +	target_tcflag_t c_lflag;		/* local mode flags */ +	target_cc_t c_cc[TARGET_NCCS];		/* control characters */ +	target_cc_t c_line;			/* line discipline (== c_cc[19]) */ +	target_speed_t c_ispeed;		/* input speed */ +	target_speed_t c_ospeed;		/* output speed */ +}; + +/* c_cc characters */ +#define TARGET_VEOF 0 +#define TARGET_VEOL 1 +#define TARGET_VEOL2 2 +#define TARGET_VERASE 3 +#define TARGET_VWERASE 4 +#define TARGET_VKILL 5 +#define TARGET_VREPRINT 6 +#define TARGET_VSWTC 7 +#define TARGET_VINTR 8 +#define TARGET_VQUIT 9 +#define TARGET_VSUSP 10 +#define TARGET_VSTART 12 +#define TARGET_VSTOP 13 +#define TARGET_VLNEXT 14 +#define TARGET_VDISCARD 15 +#define TARGET_VMIN 16 +#define TARGET_VTIME 17 + +/* c_iflag bits */ +#define TARGET_IGNBRK	0000001 +#define TARGET_BRKINT	0000002 +#define TARGET_IGNPAR	0000004 +#define TARGET_PARMRK	0000010 +#define TARGET_INPCK	0000020 +#define TARGET_ISTRIP	0000040 +#define TARGET_INLCR	0000100 +#define TARGET_IGNCR	0000200 +#define TARGET_ICRNL	0000400 +#define TARGET_IXON	0001000 +#define TARGET_IXOFF	0002000 +#define TARGET_IXANY	0004000 +#define TARGET_IUCLC	0010000 +#define TARGET_IMAXBEL	0020000 +#define TARGET_IUTF8	0040000 + +/* c_oflag bits */ +#define TARGET_OPOST	0000001 +#define TARGET_ONLCR	0000002 +#define TARGET_OLCUC	0000004 + +#define TARGET_OCRNL	0000010 +#define TARGET_ONOCR	0000020 +#define TARGET_ONLRET	0000040 + +#define TARGET_OFILL	00000100 +#define TARGET_OFDEL	00000200 +#define TARGET_NLDLY	00001400 +#define   TARGET_NL0	00000000 +#define   TARGET_NL1	00000400 +#define   TARGET_NL2	00001000 +#define   TARGET_NL3	00001400 +#define TARGET_TABDLY	00006000 +#define   TARGET_TAB0	00000000 +#define   TARGET_TAB1	00002000 +#define   TARGET_TAB2	00004000 +#define   TARGET_TAB3	00006000 +#define TARGET_CRDLY	00030000 +#define   TARGET_CR0	00000000 +#define   TARGET_CR1	00010000 +#define   TARGET_CR2	00020000 +#define   TARGET_CR3	00030000 +#define TARGET_FFDLY	00040000 +#define   TARGET_FF0	00000000 +#define   TARGET_FF1	00040000 +#define TARGET_BSDLY	00100000 +#define   TARGET_BS0	00000000 +#define   TARGET_BS1	00100000 +#define TARGET_VTDLY	00200000 +#define   TARGET_VT0	00000000 +#define   TARGET_VT1	00200000 +#define TARGET_XTABS	01000000 /* Hmm.. Linux/i386 considers this part of TABDLY.. */ + +/* c_cflag bit meaning */ +#define TARGET_CBAUD	0000037 +#define  TARGET_B0	0000000		/* hang up */ +#define  TARGET_B50	0000001 +#define  TARGET_B75	0000002 +#define  TARGET_B110	0000003 +#define  TARGET_B134	0000004 +#define  TARGET_B150	0000005 +#define  TARGET_B200	0000006 +#define  TARGET_B300	0000007 +#define  TARGET_B600	0000010 +#define  TARGET_B1200	0000011 +#define  TARGET_B1800	0000012 +#define  TARGET_B2400	0000013 +#define  TARGET_B4800	0000014 +#define  TARGET_B9600	0000015 +#define  TARGET_B19200	0000016 +#define  TARGET_B38400	0000017 +#define TARGET_EXTA B19200 +#define TARGET_EXTB B38400 +#define TARGET_CBAUDEX 0000000 +#define  TARGET_B57600   00020 +#define  TARGET_B115200  00021 +#define  TARGET_B230400  00022 +#define  TARGET_B460800  00023 +#define  TARGET_B500000  00024 +#define  TARGET_B576000  00025 +#define  TARGET_B921600  00026 +#define TARGET_B1000000  00027 +#define TARGET_B1152000  00030 +#define TARGET_B1500000  00031 +#define TARGET_B2000000  00032 +#define TARGET_B2500000  00033 +#define TARGET_B3000000  00034 +#define TARGET_B3500000  00035 +#define TARGET_B4000000  00036 + +#define TARGET_CSIZE	00001400 +#define   TARGET_CS5	00000000 +#define   TARGET_CS6	00000400 +#define   TARGET_CS7	00001000 +#define   TARGET_CS8	00001400 + +#define TARGET_CSTOPB	00002000 +#define TARGET_CREAD	00004000 +#define TARGET_PARENB	00010000 +#define TARGET_PARODD	00020000 +#define TARGET_HUPCL	00040000 + +#define TARGET_CLOCAL	00100000 +#define TARGET_CMSPAR	  010000000000		/* mark or space (stick) parity */ +#define TARGET_CRTSCTS	  020000000000		/* flow control */ + +/* c_lflag bits */ +#define TARGET_ISIG	0x00000080 +#define TARGET_ICANON	0x00000100 +#define TARGET_XCASE	0x00004000 +#define TARGET_ECHO	0x00000008 +#define TARGET_ECHOE	0x00000002 +#define TARGET_ECHOK	0x00000004 +#define TARGET_ECHONL	0x00000010 +#define TARGET_NOFLSH	0x80000000 +#define TARGET_TOSTOP	0x00400000 +#define TARGET_ECHOCTL	0x00000040 +#define TARGET_ECHOPRT	0x00000020 +#define TARGET_ECHOKE	0x00000001 +#define TARGET_FLUSHO	0x00800000 +#define TARGET_PENDIN	0x20000000 +#define TARGET_IEXTEN	0x00000400 + +#define TARGET_FIOCLEX		TARGET_IO('f', 1) +#define TARGET_FIONCLEX	TARGET_IO('f', 2) +#define TARGET_FIOASYNC	TARGET_IOW('f', 125, int) +#define TARGET_FIONBIO		TARGET_IOW('f', 126, int) +#define TARGET_FIONREAD	TARGET_IOR('f', 127, int) +#define TARGET_TIOCINQ		FIONREAD +#define TARGET_FIOQSIZE	TARGET_IOR('f', 128, loff_t) + +#define TARGET_TIOCGETP	TARGET_IOR('t', 8, struct target_sgttyb) +#define TARGET_TIOCSETP	TARGET_IOW('t', 9, struct target_sgttyb) +#define TARGET_TIOCSETN	TARGET_IOW('t', 10, struct target_sgttyb)	/* TIOCSETP wo flush */ + +#define TARGET_TIOCSETC	TARGET_IOW('t', 17, struct target_tchars) +#define TARGET_TIOCGETC	TARGET_IOR('t', 18, struct target_tchars) +#define TARGET_TCGETS		TARGET_IOR('t', 19, struct target_termios) +#define TARGET_TCSETS		TARGET_IOW('t', 20, struct target_termios) +#define TARGET_TCSETSW		TARGET_IOW('t', 21, struct target_termios) +#define TARGET_TCSETSF		TARGET_IOW('t', 22, struct target_termios) + +#define TARGET_TCGETA		TARGET_IOR('t', 23, struct target_termio) +#define TARGET_TCSETA		TARGET_IOW('t', 24, struct target_termio) +#define TARGET_TCSETAW		TARGET_IOW('t', 25, struct target_termio) +#define TARGET_TCSETAF		TARGET_IOW('t', 28, struct target_termio) + +#define TARGET_TCSBRK		TARGET_IO('t', 29) +#define TARGET_TCXONC		TARGET_IO('t', 30) +#define TARGET_TCFLSH		TARGET_IO('t', 31) + +#define TARGET_TIOCSWINSZ	TARGET_IOW('t', 103, struct target_winsize) +#define TARGET_TIOCGWINSZ	TARGET_IOR('t', 104, struct target_winsize) +#define	TARGET_TIOCSTART	TARGET_IO('t', 110)		/* start output, like ^Q */ +#define	TARGET_TIOCSTOP	TARGET_IO('t', 111)		/* stop output, like ^S */ +#define TARGET_TIOCOUTQ        TARGET_IOR('t', 115, int)     /* output queue size */ + +#define TARGET_TIOCGLTC	TARGET_IOR('t', 116, struct target_ltchars) +#define TARGET_TIOCSLTC	TARGET_IOW('t', 117, struct target_ltchars) +#define TARGET_TIOCSPGRP	TARGET_IOW('t', 118, int) +#define TARGET_TIOCGPGRP	TARGET_IOR('t', 119, int) + +#define TARGET_TIOCEXCL	0x540C +#define TARGET_TIOCNXCL	0x540D +#define TARGET_TIOCSCTTY	0x540E + +#define TARGET_TIOCSTI		0x5412 +#define TARGET_TIOCMGET	0x5415 +#define TARGET_TIOCMBIS	0x5416 +#define TARGET_TIOCMBIC	0x5417 +#define TARGET_TIOCMSET	0x5418 +# define TARGET_TIOCM_LE	0x001 +# define TARGET_TIOCM_DTR	0x002 +# define TARGET_TIOCM_RTS	0x004 +# define TARGET_TIOCM_ST	0x008 +# define TARGET_TIOCM_SR	0x010 +# define TARGET_TIOCM_CTS	0x020 +# define TARGET_TIOCM_CAR	0x040 +# define TARGET_TIOCM_RNG	0x080 +# define TARGET_TIOCM_DSR	0x100 +# define TARGET_TIOCM_CD	TIOCM_CAR +# define TARGET_TIOCM_RI	TIOCM_RNG +# define TARGET_TIOCM_OUT1	0x2000 +# define TARGET_TIOCM_OUT2	0x4000 +# define TARGET_TIOCM_LOOP	0x8000 + +#define TARGET_TIOCGSOFTCAR	0x5419 +#define TARGET_TIOCSSOFTCAR	0x541A +#define TARGET_TIOCLINUX	0x541C +#define TARGET_TIOCCONS	0x541D +#define TARGET_TIOCGSERIAL	0x541E +#define TARGET_TIOCSSERIAL	0x541F +#define TARGET_TIOCPKT		0x5420 +# define TARGET_TIOCPKT_DATA		 0 +# define TARGET_TIOCPKT_FLUSHREAD	 1 +# define TARGET_TIOCPKT_FLUSHWRITE	 2 +# define TARGET_TIOCPKT_STOP		 4 +# define TARGET_TIOCPKT_START		 8 +# define TARGET_TIOCPKT_NOSTOP		16 +# define TARGET_TIOCPKT_DOSTOP		32 + + +#define TARGET_TIOCNOTTY	0x5422 +#define TARGET_TIOCSETD	0x5423 +#define TARGET_TIOCGETD	0x5424 +#define TARGET_TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */ +#define TARGET_TIOCSBRK	0x5427  /* BSD compatibility */ +#define TARGET_TIOCCBRK	0x5428  /* BSD compatibility */ +#define TARGET_TIOCGSID	0x5429  /* Return the session ID of FD */ +#define TARGET_TIOCGPTN	TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define TARGET_TIOCSPTLCK	TARGET_IOW('T',0x31, int)  /* Lock/unlock Pty */ + +#define TARGET_TIOCSERCONFIG	0x5453 +#define TARGET_TIOCSERGWILD	0x5454 +#define TARGET_TIOCSERSWILD	0x5455 +#define TARGET_TIOCGLCKTRMIOS	0x5456 +#define TARGET_TIOCSLCKTRMIOS	0x5457 +#define TARGET_TIOCSERGSTRUCT	0x5458 /* For debugging only */ +#define TARGET_TIOCSERGETLSR   0x5459 /* Get line status register */ +  /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ +# define TARGET_TIOCSER_TEMT    0x01	/* Transmitter physically empty */ +#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config  */ +#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TARGET_TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */ +#define TARGET_TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */ +#define TARGET_TIOCGHAYESESP	0x545E  /* Get Hayes ESP configuration */ +#define TARGET_TIOCSHAYESESP	0x545F  /* Set Hayes ESP configuration */ diff --git a/linux-user/arm/nwfpe/Makefile.objs b/linux-user/arm/nwfpe/Makefile.objs new file mode 100644 index 00000000..51b0c32c --- /dev/null +++ b/linux-user/arm/nwfpe/Makefile.objs @@ -0,0 +1,2 @@ +obj-y = fpa11.o fpa11_cpdo.o fpa11_cpdt.o fpa11_cprt.o fpopcode.o +obj-y += single_cpdo.o double_cpdo.o extended_cpdo.o diff --git a/linux-user/arm/nwfpe/double_cpdo.c b/linux-user/arm/nwfpe/double_cpdo.c new file mode 100644 index 00000000..41c28f30 --- /dev/null +++ b/linux-user/arm/nwfpe/double_cpdo.c @@ -0,0 +1,295 @@ +/* +    NetWinder Floating Point Emulator +    (c) Rebel.COM, 1998,1999 + +    Direct questions, comments to Scott Bambrough <scottb@netwinder.org> + +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 2 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "fpa11.h" +#include "fpu/softfloat.h" +#include "fpopcode.h" + +float64 float64_exp(float64 Fm); +float64 float64_ln(float64 Fm); +float64 float64_sin(float64 rFm); +float64 float64_cos(float64 rFm); +float64 float64_arcsin(float64 rFm); +float64 float64_arctan(float64 rFm); +float64 float64_log(float64 rFm); +float64 float64_tan(float64 rFm); +float64 float64_arccos(float64 rFm); +float64 float64_pow(float64 rFn,float64 rFm); +float64 float64_pol(float64 rFn,float64 rFm); + +unsigned int DoubleCPDO(const unsigned int opcode) +{ +   FPA11 *fpa11 = GET_FPA11(); +   float64 rFm, rFn = float64_zero; +   unsigned int Fd, Fm, Fn, nRc = 1; + +   //printk("DoubleCPDO(0x%08x)\n",opcode); + +   Fm = getFm(opcode); +   if (CONSTANT_FM(opcode)) +   { +     rFm = getDoubleConstant(Fm); +   } +   else +   { +     switch (fpa11->fType[Fm]) +     { +        case typeSingle: +          rFm = float32_to_float64(fpa11->fpreg[Fm].fSingle, &fpa11->fp_status); +        break; + +        case typeDouble: +          rFm = fpa11->fpreg[Fm].fDouble; +          break; + +        case typeExtended: +            // !! patb +	    //printk("not implemented! why not?\n"); +            //!! ScottB +            // should never get here, if extended involved +            // then other operand should be promoted then +            // ExtendedCPDO called. +            break; + +        default: return 0; +     } +   } + +   if (!MONADIC_INSTRUCTION(opcode)) +   { +      Fn = getFn(opcode); +      switch (fpa11->fType[Fn]) +      { +        case typeSingle: +          rFn = float32_to_float64(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status); +        break; + +        case typeDouble: +          rFn = fpa11->fpreg[Fn].fDouble; +        break; + +        default: return 0; +      } +   } + +   Fd = getFd(opcode); +   /* !! this switch isn't optimized; better (opcode & MASK_ARITHMETIC_OPCODE)>>24, sort of */ +   switch (opcode & MASK_ARITHMETIC_OPCODE) +   { +      /* dyadic opcodes */ +      case ADF_CODE: +         fpa11->fpreg[Fd].fDouble = float64_add(rFn,rFm, &fpa11->fp_status); +      break; + +      case MUF_CODE: +      case FML_CODE: +         fpa11->fpreg[Fd].fDouble = float64_mul(rFn,rFm, &fpa11->fp_status); +      break; + +      case SUF_CODE: +         fpa11->fpreg[Fd].fDouble = float64_sub(rFn,rFm, &fpa11->fp_status); +      break; + +      case RSF_CODE: +         fpa11->fpreg[Fd].fDouble = float64_sub(rFm,rFn, &fpa11->fp_status); +      break; + +      case DVF_CODE: +      case FDV_CODE: +         fpa11->fpreg[Fd].fDouble = float64_div(rFn,rFm, &fpa11->fp_status); +      break; + +      case RDF_CODE: +      case FRD_CODE: +         fpa11->fpreg[Fd].fDouble = float64_div(rFm,rFn, &fpa11->fp_status); +      break; + +#if 0 +      case POW_CODE: +         fpa11->fpreg[Fd].fDouble = float64_pow(rFn,rFm); +      break; + +      case RPW_CODE: +         fpa11->fpreg[Fd].fDouble = float64_pow(rFm,rFn); +      break; +#endif + +      case RMF_CODE: +         fpa11->fpreg[Fd].fDouble = float64_rem(rFn,rFm, &fpa11->fp_status); +      break; + +#if 0 +      case POL_CODE: +         fpa11->fpreg[Fd].fDouble = float64_pol(rFn,rFm); +      break; +#endif + +      /* monadic opcodes */ +      case MVF_CODE: +         fpa11->fpreg[Fd].fDouble = rFm; +      break; + +      case MNF_CODE: +      { +         unsigned int *p = (unsigned int*)&rFm; +#ifdef HOST_WORDS_BIGENDIAN +         p[0] ^= 0x80000000; +#else +         p[1] ^= 0x80000000; +#endif +         fpa11->fpreg[Fd].fDouble = rFm; +      } +      break; + +      case ABS_CODE: +      { +         unsigned int *p = (unsigned int*)&rFm; +#ifdef HOST_WORDS_BIGENDIAN +         p[0] &= 0x7fffffff; +#else +         p[1] &= 0x7fffffff; +#endif +         fpa11->fpreg[Fd].fDouble = rFm; +      } +      break; + +      case RND_CODE: +      case URD_CODE: +         fpa11->fpreg[Fd].fDouble = float64_round_to_int(rFm, &fpa11->fp_status); +      break; + +      case SQT_CODE: +         fpa11->fpreg[Fd].fDouble = float64_sqrt(rFm, &fpa11->fp_status); +      break; + +#if 0 +      case LOG_CODE: +         fpa11->fpreg[Fd].fDouble = float64_log(rFm); +      break; + +      case LGN_CODE: +         fpa11->fpreg[Fd].fDouble = float64_ln(rFm); +      break; + +      case EXP_CODE: +         fpa11->fpreg[Fd].fDouble = float64_exp(rFm); +      break; + +      case SIN_CODE: +         fpa11->fpreg[Fd].fDouble = float64_sin(rFm); +      break; + +      case COS_CODE: +         fpa11->fpreg[Fd].fDouble = float64_cos(rFm); +      break; + +      case TAN_CODE: +         fpa11->fpreg[Fd].fDouble = float64_tan(rFm); +      break; + +      case ASN_CODE: +         fpa11->fpreg[Fd].fDouble = float64_arcsin(rFm); +      break; + +      case ACS_CODE: +         fpa11->fpreg[Fd].fDouble = float64_arccos(rFm); +      break; + +      case ATN_CODE: +         fpa11->fpreg[Fd].fDouble = float64_arctan(rFm); +      break; +#endif + +      case NRM_CODE: +      break; + +      default: +      { +        nRc = 0; +      } +   } + +   if (0 != nRc) fpa11->fType[Fd] = typeDouble; +   return nRc; +} + +#if 0 +float64 float64_exp(float64 rFm) +{ +  return rFm; +//series +} + +float64 float64_ln(float64 rFm) +{ +  return rFm; +//series +} + +float64 float64_sin(float64 rFm) +{ +  return rFm; +//series +} + +float64 float64_cos(float64 rFm) +{ +   return rFm; +   //series +} + +#if 0 +float64 float64_arcsin(float64 rFm) +{ +//series +} + +float64 float64_arctan(float64 rFm) +{ +  //series +} +#endif + +float64 float64_log(float64 rFm) +{ +  return float64_div(float64_ln(rFm),getDoubleConstant(7)); +} + +float64 float64_tan(float64 rFm) +{ +  return float64_div(float64_sin(rFm),float64_cos(rFm)); +} + +float64 float64_arccos(float64 rFm) +{ +return rFm; +   //return float64_sub(halfPi,float64_arcsin(rFm)); +} + +float64 float64_pow(float64 rFn,float64 rFm) +{ +  return float64_exp(float64_mul(rFm,float64_ln(rFn))); +} + +float64 float64_pol(float64 rFn,float64 rFm) +{ +  return float64_arctan(float64_div(rFn,rFm)); +} +#endif diff --git a/linux-user/arm/nwfpe/extended_cpdo.c b/linux-user/arm/nwfpe/extended_cpdo.c new file mode 100644 index 00000000..48eca3b4 --- /dev/null +++ b/linux-user/arm/nwfpe/extended_cpdo.c @@ -0,0 +1,272 @@ +/* +    NetWinder Floating Point Emulator +    (c) Rebel.COM, 1998,1999 + +    Direct questions, comments to Scott Bambrough <scottb@netwinder.org> + +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 2 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "fpa11.h" +#include "fpu/softfloat.h" +#include "fpopcode.h" + +floatx80 floatx80_exp(floatx80 Fm); +floatx80 floatx80_ln(floatx80 Fm); +floatx80 floatx80_sin(floatx80 rFm); +floatx80 floatx80_cos(floatx80 rFm); +floatx80 floatx80_arcsin(floatx80 rFm); +floatx80 floatx80_arctan(floatx80 rFm); +floatx80 floatx80_log(floatx80 rFm); +floatx80 floatx80_tan(floatx80 rFm); +floatx80 floatx80_arccos(floatx80 rFm); +floatx80 floatx80_pow(floatx80 rFn,floatx80 rFm); +floatx80 floatx80_pol(floatx80 rFn,floatx80 rFm); + +unsigned int ExtendedCPDO(const unsigned int opcode) +{ +   FPA11 *fpa11 = GET_FPA11(); +   floatx80 rFm, rFn; +   unsigned int Fd, Fm, Fn, nRc = 1; + +   //printk("ExtendedCPDO(0x%08x)\n",opcode); + +   Fm = getFm(opcode); +   if (CONSTANT_FM(opcode)) +   { +     rFm = getExtendedConstant(Fm); +   } +   else +   { +     switch (fpa11->fType[Fm]) +     { +        case typeSingle: +          rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle, &fpa11->fp_status); +        break; + +        case typeDouble: +          rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble, &fpa11->fp_status); +        break; + +        case typeExtended: +          rFm = fpa11->fpreg[Fm].fExtended; +        break; + +        default: return 0; +     } +   } + +   if (!MONADIC_INSTRUCTION(opcode)) +   { +      Fn = getFn(opcode); +      switch (fpa11->fType[Fn]) +      { +        case typeSingle: +          rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status); +        break; + +        case typeDouble: +          rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status); +        break; + +        case typeExtended: +          rFn = fpa11->fpreg[Fn].fExtended; +        break; + +        default: return 0; +      } +   } + +   Fd = getFd(opcode); +   switch (opcode & MASK_ARITHMETIC_OPCODE) +   { +      /* dyadic opcodes */ +      case ADF_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_add(rFn,rFm, &fpa11->fp_status); +      break; + +      case MUF_CODE: +      case FML_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_mul(rFn,rFm, &fpa11->fp_status); +      break; + +      case SUF_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_sub(rFn,rFm, &fpa11->fp_status); +      break; + +      case RSF_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_sub(rFm,rFn, &fpa11->fp_status); +      break; + +      case DVF_CODE: +      case FDV_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_div(rFn,rFm, &fpa11->fp_status); +      break; + +      case RDF_CODE: +      case FRD_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_div(rFm,rFn, &fpa11->fp_status); +      break; + +#if 0 +      case POW_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_pow(rFn,rFm); +      break; + +      case RPW_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_pow(rFm,rFn); +      break; +#endif + +      case RMF_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_rem(rFn,rFm, &fpa11->fp_status); +      break; + +#if 0 +      case POL_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_pol(rFn,rFm); +      break; +#endif + +      /* monadic opcodes */ +      case MVF_CODE: +         fpa11->fpreg[Fd].fExtended = rFm; +      break; + +      case MNF_CODE: +         rFm.high ^= 0x8000; +         fpa11->fpreg[Fd].fExtended = rFm; +      break; + +      case ABS_CODE: +         rFm.high &= 0x7fff; +         fpa11->fpreg[Fd].fExtended = rFm; +      break; + +      case RND_CODE: +      case URD_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_round_to_int(rFm, &fpa11->fp_status); +      break; + +      case SQT_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_sqrt(rFm, &fpa11->fp_status); +      break; + +#if 0 +      case LOG_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_log(rFm); +      break; + +      case LGN_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_ln(rFm); +      break; + +      case EXP_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_exp(rFm); +      break; + +      case SIN_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_sin(rFm); +      break; + +      case COS_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_cos(rFm); +      break; + +      case TAN_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_tan(rFm); +      break; + +      case ASN_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_arcsin(rFm); +      break; + +      case ACS_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_arccos(rFm); +      break; + +      case ATN_CODE: +         fpa11->fpreg[Fd].fExtended = floatx80_arctan(rFm); +      break; +#endif + +      case NRM_CODE: +      break; + +      default: +      { +        nRc = 0; +      } +   } + +   if (0 != nRc) fpa11->fType[Fd] = typeExtended; +   return nRc; +} + +#if 0 +floatx80 floatx80_exp(floatx80 Fm) +{ +//series +} + +floatx80 floatx80_ln(floatx80 Fm) +{ +//series +} + +floatx80 floatx80_sin(floatx80 rFm) +{ +//series +} + +floatx80 floatx80_cos(floatx80 rFm) +{ +//series +} + +floatx80 floatx80_arcsin(floatx80 rFm) +{ +//series +} + +floatx80 floatx80_arctan(floatx80 rFm) +{ +  //series +} + +floatx80 floatx80_log(floatx80 rFm) +{ +  return floatx80_div(floatx80_ln(rFm),getExtendedConstant(7)); +} + +floatx80 floatx80_tan(floatx80 rFm) +{ +  return floatx80_div(floatx80_sin(rFm),floatx80_cos(rFm)); +} + +floatx80 floatx80_arccos(floatx80 rFm) +{ +   //return floatx80_sub(halfPi,floatx80_arcsin(rFm)); +} + +floatx80 floatx80_pow(floatx80 rFn,floatx80 rFm) +{ +  return floatx80_exp(floatx80_mul(rFm,floatx80_ln(rFn))); +} + +floatx80 floatx80_pol(floatx80 rFn,floatx80 rFm) +{ +  return floatx80_arctan(floatx80_div(rFn,rFm)); +} +#endif diff --git a/linux-user/arm/nwfpe/fpa11.c b/linux-user/arm/nwfpe/fpa11.c new file mode 100644 index 00000000..eebd93fc --- /dev/null +++ b/linux-user/arm/nwfpe/fpa11.c @@ -0,0 +1,237 @@ +/* +    NetWinder Floating Point Emulator +    (c) Rebel.COM, 1998,1999 + +    Direct questions, comments to Scott Bambrough <scottb@netwinder.org> + +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 2 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "fpa11.h" + +#include "fpopcode.h" + +//#include "fpmodule.h" +//#include "fpmodule.inl" + +//#include <asm/system.h> + +#include <stdio.h> + +FPA11* qemufpa = NULL; +CPUARMState* user_registers; + +/* Reset the FPA11 chip.  Called to initialize and reset the emulator. */ +void resetFPA11(void) +{ +  int i; +  FPA11 *fpa11 = GET_FPA11(); + +  /* initialize the register type array */ +  for (i=0;i<=7;i++) +  { +    fpa11->fType[i] = typeNone; +  } + +  /* FPSR: set system id to FP_EMULATOR, set AC, clear all other bits */ +  fpa11->fpsr = FP_EMULATOR | BIT_AC; + +  /* FPCR: set SB, AB and DA bits, clear all others */ +#ifdef MAINTAIN_FPCR +  fpa11->fpcr = MASK_RESET; +#endif +} + +void SetRoundingMode(const unsigned int opcode) +{ +    int rounding_mode; +   FPA11 *fpa11 = GET_FPA11(); + +#ifdef MAINTAIN_FPCR +   fpa11->fpcr &= ~MASK_ROUNDING_MODE; +#endif +   switch (opcode & MASK_ROUNDING_MODE) +   { +      default: +      case ROUND_TO_NEAREST: +         rounding_mode = float_round_nearest_even; +#ifdef MAINTAIN_FPCR +         fpa11->fpcr |= ROUND_TO_NEAREST; +#endif +      break; + +      case ROUND_TO_PLUS_INFINITY: +         rounding_mode = float_round_up; +#ifdef MAINTAIN_FPCR +         fpa11->fpcr |= ROUND_TO_PLUS_INFINITY; +#endif +      break; + +      case ROUND_TO_MINUS_INFINITY: +         rounding_mode = float_round_down; +#ifdef MAINTAIN_FPCR +         fpa11->fpcr |= ROUND_TO_MINUS_INFINITY; +#endif +      break; + +      case ROUND_TO_ZERO: +         rounding_mode = float_round_to_zero; +#ifdef MAINTAIN_FPCR +         fpa11->fpcr |= ROUND_TO_ZERO; +#endif +      break; +  } +   set_float_rounding_mode(rounding_mode, &fpa11->fp_status); +} + +void SetRoundingPrecision(const unsigned int opcode) +{ +    int rounding_precision; +   FPA11 *fpa11 = GET_FPA11(); +#ifdef MAINTAIN_FPCR +   fpa11->fpcr &= ~MASK_ROUNDING_PRECISION; +#endif +   switch (opcode & MASK_ROUNDING_PRECISION) +   { +      case ROUND_SINGLE: +         rounding_precision = 32; +#ifdef MAINTAIN_FPCR +         fpa11->fpcr |= ROUND_SINGLE; +#endif +      break; + +      case ROUND_DOUBLE: +         rounding_precision = 64; +#ifdef MAINTAIN_FPCR +         fpa11->fpcr |= ROUND_DOUBLE; +#endif +      break; + +      case ROUND_EXTENDED: +         rounding_precision = 80; +#ifdef MAINTAIN_FPCR +         fpa11->fpcr |= ROUND_EXTENDED; +#endif +      break; + +      default: rounding_precision = 80; +  } +   set_floatx80_rounding_precision(rounding_precision, &fpa11->fp_status); +} + +/* Emulate the instruction in the opcode. */ +/* ??? This is not thread safe.  */ +unsigned int EmulateAll(unsigned int opcode, FPA11* qfpa, CPUARMState* qregs) +{ +  unsigned int nRc = 0; +//  unsigned long flags; +  FPA11 *fpa11; +//  save_flags(flags); sti(); + +  qemufpa=qfpa; +  user_registers=qregs; + +#if 0 +  fprintf(stderr,"emulating FP insn 0x%08x, PC=0x%08x\n", +          opcode, qregs[ARM_REG_PC]); +#endif +  fpa11 = GET_FPA11(); + +  if (fpa11->initflag == 0)		/* good place for __builtin_expect */ +  { +    resetFPA11(); +    SetRoundingMode(ROUND_TO_NEAREST); +    SetRoundingPrecision(ROUND_EXTENDED); +    fpa11->initflag = 1; +  } + +  set_float_exception_flags(0, &fpa11->fp_status); + +  if (TEST_OPCODE(opcode,MASK_CPRT)) +  { +    //fprintf(stderr,"emulating CPRT\n"); +    /* Emulate conversion opcodes. */ +    /* Emulate register transfer opcodes. */ +    /* Emulate comparison opcodes. */ +    nRc = EmulateCPRT(opcode); +  } +  else if (TEST_OPCODE(opcode,MASK_CPDO)) +  { +    //fprintf(stderr,"emulating CPDO\n"); +    /* Emulate monadic arithmetic opcodes. */ +    /* Emulate dyadic arithmetic opcodes. */ +    nRc = EmulateCPDO(opcode); +  } +  else if (TEST_OPCODE(opcode,MASK_CPDT)) +  { +    //fprintf(stderr,"emulating CPDT\n"); +    /* Emulate load/store opcodes. */ +    /* Emulate load/store multiple opcodes. */ +    nRc = EmulateCPDT(opcode); +  } +  else +  { +    /* Invalid instruction detected.  Return FALSE. */ +    nRc = 0; +  } + +//  restore_flags(flags); +  if(nRc == 1 && get_float_exception_flags(&fpa11->fp_status)) +  { +    //printf("fef 0x%x\n",float_exception_flags); +    nRc = -get_float_exception_flags(&fpa11->fp_status); +  } + +  //printf("returning %d\n",nRc); +  return(nRc); +} + +#if 0 +unsigned int EmulateAll1(unsigned int opcode) +{ +  switch ((opcode >> 24) & 0xf) +  { +     case 0xc: +     case 0xd: +       if ((opcode >> 20) & 0x1) +       { +          switch ((opcode >> 8) & 0xf) +          { +             case 0x1: return PerformLDF(opcode); break; +             case 0x2: return PerformLFM(opcode); break; +             default: return 0; +          } +       } +       else +       { +          switch ((opcode >> 8) & 0xf) +          { +             case 0x1: return PerformSTF(opcode); break; +             case 0x2: return PerformSFM(opcode); break; +             default: return 0; +          } +      } +     break; + +     case 0xe: +       if (opcode & 0x10) +         return EmulateCPDO(opcode); +       else +         return EmulateCPRT(opcode); +     break; + +     default: return 0; +  } +} +#endif diff --git a/linux-user/arm/nwfpe/fpa11.h b/linux-user/arm/nwfpe/fpa11.h new file mode 100644 index 00000000..bb9ac655 --- /dev/null +++ b/linux-user/arm/nwfpe/fpa11.h @@ -0,0 +1,130 @@ +/* +    NetWinder Floating Point Emulator +    (c) Rebel.com, 1998-1999 + +    Direct questions, comments to Scott Bambrough <scottb@netwinder.org> + +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 2 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __FPA11_H__ +#define __FPA11_H__ + +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> + +#include <cpu.h> + +#define GET_FPA11() (qemufpa) + +/* + * The processes registers are always at the very top of the 8K + * stack+task struct.  Use the same method as 'current' uses to + * reach them. + */ +extern CPUARMState *user_registers; + +#define GET_USERREG() (user_registers) + +/* Need task_struct */ +//#include <linux/sched.h> + +/* includes */ +#include "fpsr.h"		/* FP control and status register definitions */ +#include "fpu/softfloat.h" + +#define		typeNone		0x00 +#define		typeSingle		0x01 +#define		typeDouble		0x02 +#define		typeExtended		0x03 + +/* + * This must be no more and no less than 12 bytes. + */ +typedef union tagFPREG { +   floatx80 fExtended; +   float64  fDouble; +   float32  fSingle; +} FPREG; + +/* + * FPA11 device model. + * + * This structure is exported to user space.  Do not re-order. + * Only add new stuff to the end, and do not change the size of + * any element.  Elements of this structure are used by user + * space, and must match struct user_fp in include/asm-arm/user.h. + * We include the byte offsets below for documentation purposes. + * + * The size of this structure and FPREG are checked by fpmodule.c + * on initialisation.  If the rules have been broken, NWFPE will + * not initialise. + */ +typedef struct tagFPA11 { +/*   0 */  FPREG fpreg[8];		/* 8 floating point registers */ +/*  96 */  FPSR fpsr;			/* floating point status register */ +/* 100 */  FPCR fpcr;			/* floating point control register */ +/* 104 */  unsigned char fType[8];	/* type of floating point value held in +					   floating point registers.  One of none +					   single, double or extended. */ +/* 112 */  int initflag;		/* this is special.  The kernel guarantees +					   to set it to 0 when a thread is launched, +					   so we can use it to detect whether this +					   instance of the emulator needs to be +					   initialised. */ +    float_status fp_status;      /* QEMU float emulator status */ +} FPA11; + +extern FPA11* qemufpa; + +void resetFPA11(void); +void SetRoundingMode(const unsigned int); +void SetRoundingPrecision(const unsigned int); + +static inline unsigned int readRegister(unsigned int reg) +{ +    return (user_registers->regs[(reg)]); +} + +static inline void writeRegister(unsigned int x, unsigned int y) +{ +#if 0 +	printf("writing %d to r%d\n",y,x); +#endif +        user_registers->regs[(x)]=(y); +} + +static inline void writeConditionCodes(unsigned int x) +{ +        cpsr_write(user_registers,x,CPSR_NZCV); +} + +#define ARM_REG_PC 15 + +unsigned int EmulateAll(unsigned int opcode, FPA11* qfpa, CPUARMState* qregs); + +unsigned int EmulateCPDO(const unsigned int); +unsigned int EmulateCPDT(const unsigned int); +unsigned int EmulateCPRT(const unsigned int); + +unsigned int SingleCPDO(const unsigned int opcode); +unsigned int DoubleCPDO(const unsigned int opcode); +unsigned int ExtendedCPDO(const unsigned int opcode); + + +/* included only for get_user/put_user macros */ +#include "qemu.h" + +#endif diff --git a/linux-user/arm/nwfpe/fpa11.inl b/linux-user/arm/nwfpe/fpa11.inl new file mode 100644 index 00000000..6c6f380d --- /dev/null +++ b/linux-user/arm/nwfpe/fpa11.inl @@ -0,0 +1,50 @@ +/* +    NetWinder Floating Point Emulator +    (c) Rebel.COM, 1998,1999 + +    Direct questions, comments to Scott Bambrough <scottb@netwinder.org> + +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 2 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "fpa11.h" + +/* Read and write floating point status register */ +static inline unsigned int readFPSR(void) +{ +  FPA11 *fpa11 = GET_FPA11(); +  return(fpa11->fpsr); +} + +static inline void writeFPSR(FPSR reg) +{ +  FPA11 *fpa11 = GET_FPA11(); +  /* the sysid byte in the status register is readonly */ +  fpa11->fpsr = (fpa11->fpsr & MASK_SYSID) | (reg & ~MASK_SYSID); +} + +/* Read and write floating point control register */ +static inline FPCR readFPCR(void) +{ +  FPA11 *fpa11 = GET_FPA11(); +  /* clear SB, AB and DA bits before returning FPCR */ +  return(fpa11->fpcr & ~MASK_RFC); +} + +static inline void writeFPCR(FPCR reg) +{ +  FPA11 *fpa11 = GET_FPA11(); +  fpa11->fpcr &= ~MASK_WFC;		/* clear SB, AB and DA bits */ +  fpa11->fpcr |= (reg & MASK_WFC);	/* write SB, AB and DA bits */ +} diff --git a/linux-user/arm/nwfpe/fpa11_cpdo.c b/linux-user/arm/nwfpe/fpa11_cpdo.c new file mode 100644 index 00000000..5f4a6a41 --- /dev/null +++ b/linux-user/arm/nwfpe/fpa11_cpdo.c @@ -0,0 +1,112 @@ +/* +    NetWinder Floating Point Emulator +    (c) Rebel.COM, 1998,1999 + +    Direct questions, comments to Scott Bambrough <scottb@netwinder.org> + +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 2 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "fpa11.h" +#include "fpopcode.h" + +unsigned int EmulateCPDO(const unsigned int opcode) +{ +   FPA11 *fpa11 = GET_FPA11(); +   unsigned int Fd, nType, nDest, nRc = 1; + +   //printk("EmulateCPDO(0x%08x)\n",opcode); + +   /* Get the destination size.  If not valid let Linux perform +      an invalid instruction trap. */ +   nDest = getDestinationSize(opcode); +   if (typeNone == nDest) return 0; + +   SetRoundingMode(opcode); + +   /* Compare the size of the operands in Fn and Fm. +      Choose the largest size and perform operations in that size, +      in order to make use of all the precision of the operands. +      If Fm is a constant, we just grab a constant of a size +      matching the size of the operand in Fn. */ +   if (MONADIC_INSTRUCTION(opcode)) +     nType = nDest; +   else +     nType = fpa11->fType[getFn(opcode)]; + +   if (!CONSTANT_FM(opcode)) +   { +     register unsigned int Fm = getFm(opcode); +     if (nType < fpa11->fType[Fm]) +     { +        nType = fpa11->fType[Fm]; +     } +   } + +   switch (nType) +   { +      case typeSingle   : nRc = SingleCPDO(opcode);   break; +      case typeDouble   : nRc = DoubleCPDO(opcode);   break; +      case typeExtended : nRc = ExtendedCPDO(opcode); break; +      default           : nRc = 0; +   } + +   /* If the operation succeeded, check to see if the result in the +      destination register is the correct size.  If not force it +      to be. */ +   Fd = getFd(opcode); +   nType = fpa11->fType[Fd]; +   if ((0 != nRc) && (nDest != nType)) +   { +     switch (nDest) +     { +       case typeSingle: +       { +         if (typeDouble == nType) +           fpa11->fpreg[Fd].fSingle = +              float64_to_float32(fpa11->fpreg[Fd].fDouble, &fpa11->fp_status); +         else +           fpa11->fpreg[Fd].fSingle = +              floatx80_to_float32(fpa11->fpreg[Fd].fExtended, &fpa11->fp_status); +       } +       break; + +       case typeDouble: +       { +         if (typeSingle == nType) +           fpa11->fpreg[Fd].fDouble = +              float32_to_float64(fpa11->fpreg[Fd].fSingle, &fpa11->fp_status); +         else +           fpa11->fpreg[Fd].fDouble = +              floatx80_to_float64(fpa11->fpreg[Fd].fExtended, &fpa11->fp_status); +       } +       break; + +       case typeExtended: +       { +         if (typeSingle == nType) +           fpa11->fpreg[Fd].fExtended = +              float32_to_floatx80(fpa11->fpreg[Fd].fSingle, &fpa11->fp_status); +         else +           fpa11->fpreg[Fd].fExtended = +              float64_to_floatx80(fpa11->fpreg[Fd].fDouble, &fpa11->fp_status); +       } +       break; +     } + +     fpa11->fType[Fd] = nDest; +   } + +   return nRc; +} diff --git a/linux-user/arm/nwfpe/fpa11_cpdt.c b/linux-user/arm/nwfpe/fpa11_cpdt.c new file mode 100644 index 00000000..007a3d65 --- /dev/null +++ b/linux-user/arm/nwfpe/fpa11_cpdt.c @@ -0,0 +1,381 @@ +/* +    NetWinder Floating Point Emulator +    (c) Rebel.com, 1998-1999 +    (c) Philip Blundell, 1998 + +    Direct questions, comments to Scott Bambrough <scottb@netwinder.org> + +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 2 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "fpa11.h" +#include "fpu/softfloat.h" +#include "fpopcode.h" +//#include "fpmodule.h" +//#include "fpmodule.inl" + +//#include <asm/uaccess.h> + +static inline +void loadSingle(const unsigned int Fn, target_ulong addr) +{ +   FPA11 *fpa11 = GET_FPA11(); +   fpa11->fType[Fn] = typeSingle; +   /* FIXME - handle failure of get_user() */ +   get_user_u32(float32_val(fpa11->fpreg[Fn].fSingle), addr); +} + +static inline +void loadDouble(const unsigned int Fn, target_ulong addr) +{ +   FPA11 *fpa11 = GET_FPA11(); +   unsigned int *p; +   p = (unsigned int*)&fpa11->fpreg[Fn].fDouble; +   fpa11->fType[Fn] = typeDouble; +#ifdef HOST_WORDS_BIGENDIAN +   /* FIXME - handle failure of get_user() */ +   get_user_u32(p[0], addr); /* sign & exponent */ +   get_user_u32(p[1], addr + 4); +#else +   /* FIXME - handle failure of get_user() */ +   get_user_u32(p[0], addr + 4); +   get_user_u32(p[1], addr); /* sign & exponent */ +#endif +} + +static inline +void loadExtended(const unsigned int Fn, target_ulong addr) +{ +   FPA11 *fpa11 = GET_FPA11(); +   unsigned int *p; +   p = (unsigned int*)&fpa11->fpreg[Fn].fExtended; +   fpa11->fType[Fn] = typeExtended; +   /* FIXME - handle failure of get_user() */ +   get_user_u32(p[0], addr);  /* sign & exponent */ +   get_user_u32(p[1], addr + 8);  /* ls bits */ +   get_user_u32(p[2], addr + 4);  /* ms bits */ +} + +static inline +void loadMultiple(const unsigned int Fn, target_ulong addr) +{ +   FPA11 *fpa11 = GET_FPA11(); +   register unsigned int *p; +   unsigned long x; + +   p = (unsigned int*)&(fpa11->fpreg[Fn]); +   /* FIXME - handle failure of get_user() */ +   get_user_u32(x, addr); +   fpa11->fType[Fn] = (x >> 14) & 0x00000003; + +   switch (fpa11->fType[Fn]) +   { +      case typeSingle: +      case typeDouble: +      { +         /* FIXME - handle failure of get_user() */ +         get_user_u32(p[0], addr + 8);  /* Single */ +         get_user_u32(p[1], addr + 4);  /* double msw */ +         p[2] = 0;        /* empty */ +      } +      break; + +      case typeExtended: +      { +         /* FIXME - handle failure of get_user() */ +         get_user_u32(p[1], addr + 8); +         get_user_u32(p[2], addr + 4);  /* msw */ +         p[0] = (x & 0x80003fff); +      } +      break; +   } +} + +static inline +void storeSingle(const unsigned int Fn, target_ulong addr) +{ +   FPA11 *fpa11 = GET_FPA11(); +   float32 val; +   register unsigned int *p = (unsigned int*)&val; + +   switch (fpa11->fType[Fn]) +   { +      case typeDouble: +         val = float64_to_float32(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status); +      break; + +      case typeExtended: +         val = floatx80_to_float32(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status); +      break; + +      default: val = fpa11->fpreg[Fn].fSingle; +   } + +   /* FIXME - handle put_user() failures */ +   put_user_u32(p[0], addr); +} + +static inline +void storeDouble(const unsigned int Fn, target_ulong addr) +{ +   FPA11 *fpa11 = GET_FPA11(); +   float64 val; +   register unsigned int *p = (unsigned int*)&val; + +   switch (fpa11->fType[Fn]) +   { +      case typeSingle: +         val = float32_to_float64(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status); +      break; + +      case typeExtended: +         val = floatx80_to_float64(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status); +      break; + +      default: val = fpa11->fpreg[Fn].fDouble; +   } +   /* FIXME - handle put_user() failures */ +#ifdef HOST_WORDS_BIGENDIAN +   put_user_u32(p[0], addr);	/* msw */ +   put_user_u32(p[1], addr + 4);	/* lsw */ +#else +   put_user_u32(p[1], addr);	/* msw */ +   put_user_u32(p[0], addr + 4);	/* lsw */ +#endif +} + +static inline +void storeExtended(const unsigned int Fn, target_ulong addr) +{ +   FPA11 *fpa11 = GET_FPA11(); +   floatx80 val; +   register unsigned int *p = (unsigned int*)&val; + +   switch (fpa11->fType[Fn]) +   { +      case typeSingle: +         val = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status); +      break; + +      case typeDouble: +         val = float64_to_floatx80(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status); +      break; + +      default: val = fpa11->fpreg[Fn].fExtended; +   } + +   /* FIXME - handle put_user() failures */ +   put_user_u32(p[0], addr); /* sign & exp */ +   put_user_u32(p[1], addr + 8); +   put_user_u32(p[2], addr + 4); /* msw */ +} + +static inline +void storeMultiple(const unsigned int Fn, target_ulong addr) +{ +   FPA11 *fpa11 = GET_FPA11(); +   register unsigned int nType, *p; + +   p = (unsigned int*)&(fpa11->fpreg[Fn]); +   nType = fpa11->fType[Fn]; + +   switch (nType) +   { +      case typeSingle: +      case typeDouble: +      { +         put_user_u32(p[0], addr + 8); /* single */ +	 put_user_u32(p[1], addr + 4); /* double msw */ +	 put_user_u32(nType << 14, addr); +      } +      break; + +      case typeExtended: +      { +         put_user_u32(p[2], addr + 4); /* msw */ +	 put_user_u32(p[1], addr + 8); +	 put_user_u32((p[0] & 0x80003fff) | (nType << 14), addr); +      } +      break; +   } +} + +static unsigned int PerformLDF(const unsigned int opcode) +{ +    target_ulong pBase, pAddress, pFinal; +    unsigned int nRc = 1, +     write_back = WRITE_BACK(opcode); + +   //printk("PerformLDF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode)); + +   pBase = readRegister(getRn(opcode)); +   if (ARM_REG_PC == getRn(opcode)) +   { +     pBase += 8; +     write_back = 0; +   } + +   pFinal = pBase; +   if (BIT_UP_SET(opcode)) +     pFinal += getOffset(opcode) * 4; +   else +     pFinal -= getOffset(opcode) * 4; + +   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase; + +   switch (opcode & MASK_TRANSFER_LENGTH) +   { +      case TRANSFER_SINGLE  : loadSingle(getFd(opcode),pAddress);   break; +      case TRANSFER_DOUBLE  : loadDouble(getFd(opcode),pAddress);   break; +      case TRANSFER_EXTENDED: loadExtended(getFd(opcode),pAddress); break; +      default: nRc = 0; +   } + +   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal); +   return nRc; +} + +static unsigned int PerformSTF(const unsigned int opcode) +{ +   target_ulong pBase, pAddress, pFinal; +   unsigned int nRc = 1, +     write_back = WRITE_BACK(opcode); + +   //printk("PerformSTF(0x%08x), Fd = 0x%08x\n",opcode,getFd(opcode)); +   SetRoundingMode(ROUND_TO_NEAREST); + +   pBase = readRegister(getRn(opcode)); +   if (ARM_REG_PC == getRn(opcode)) +   { +     pBase += 8; +     write_back = 0; +   } + +   pFinal = pBase; +   if (BIT_UP_SET(opcode)) +     pFinal += getOffset(opcode) * 4; +   else +     pFinal -= getOffset(opcode) * 4; + +   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase; + +   switch (opcode & MASK_TRANSFER_LENGTH) +   { +      case TRANSFER_SINGLE  : storeSingle(getFd(opcode),pAddress);   break; +      case TRANSFER_DOUBLE  : storeDouble(getFd(opcode),pAddress);   break; +      case TRANSFER_EXTENDED: storeExtended(getFd(opcode),pAddress); break; +      default: nRc = 0; +   } + +   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal); +   return nRc; +} + +static unsigned int PerformLFM(const unsigned int opcode) +{ +   unsigned int i, Fd, +     write_back = WRITE_BACK(opcode); +   target_ulong pBase, pAddress, pFinal; + +   pBase = readRegister(getRn(opcode)); +   if (ARM_REG_PC == getRn(opcode)) +   { +     pBase += 8; +     write_back = 0; +   } + +   pFinal = pBase; +   if (BIT_UP_SET(opcode)) +     pFinal += getOffset(opcode) * 4; +   else +     pFinal -= getOffset(opcode) * 4; + +   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase; + +   Fd = getFd(opcode); +   for (i=getRegisterCount(opcode);i>0;i--) +   { +     loadMultiple(Fd,pAddress); +     pAddress += 12; Fd++; +     if (Fd == 8) Fd = 0; +   } + +   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal); +   return 1; +} + +static unsigned int PerformSFM(const unsigned int opcode) +{ +   unsigned int i, Fd, +     write_back = WRITE_BACK(opcode); +   target_ulong pBase, pAddress, pFinal; + +   pBase = readRegister(getRn(opcode)); +   if (ARM_REG_PC == getRn(opcode)) +   { +     pBase += 8; +     write_back = 0; +   } + +   pFinal = pBase; +   if (BIT_UP_SET(opcode)) +     pFinal += getOffset(opcode) * 4; +   else +     pFinal -= getOffset(opcode) * 4; + +   if (PREINDEXED(opcode)) pAddress = pFinal; else pAddress = pBase; + +   Fd = getFd(opcode); +   for (i=getRegisterCount(opcode);i>0;i--) +   { +     storeMultiple(Fd,pAddress); +     pAddress += 12; Fd++; +     if (Fd == 8) Fd = 0; +   } + +   if (write_back) writeRegister(getRn(opcode),(unsigned int)pFinal); +   return 1; +} + +#if 1 +unsigned int EmulateCPDT(const unsigned int opcode) +{ +  unsigned int nRc = 0; + +  //printk("EmulateCPDT(0x%08x)\n",opcode); + +  if (LDF_OP(opcode)) +  { +    nRc = PerformLDF(opcode); +  } +  else if (LFM_OP(opcode)) +  { +    nRc = PerformLFM(opcode); +  } +  else if (STF_OP(opcode)) +  { +    nRc = PerformSTF(opcode); +  } +  else if (SFM_OP(opcode)) +  { +    nRc = PerformSFM(opcode); +  } +  else +  { +    nRc = 0; +  } + +  return nRc; +} +#endif diff --git a/linux-user/arm/nwfpe/fpa11_cprt.c b/linux-user/arm/nwfpe/fpa11_cprt.c new file mode 100644 index 00000000..7be93fa5 --- /dev/null +++ b/linux-user/arm/nwfpe/fpa11_cprt.c @@ -0,0 +1,283 @@ +/* +    NetWinder Floating Point Emulator +    (c) Rebel.COM, 1998,1999 +    (c) Philip Blundell, 1999 + +    Direct questions, comments to Scott Bambrough <scottb@netwinder.org> + +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 2 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "fpa11.h" +#include "fpu/softfloat.h" +#include "fpopcode.h" +#include "fpa11.inl" +//#include "fpmodule.h" +//#include "fpmodule.inl" + +unsigned int PerformFLT(const unsigned int opcode); +unsigned int PerformFIX(const unsigned int opcode); + +static unsigned int +PerformComparison(const unsigned int opcode); + +unsigned int EmulateCPRT(const unsigned int opcode) +{ +  unsigned int nRc = 1; + +  //printk("EmulateCPRT(0x%08x)\n",opcode); + +  if (opcode & 0x800000) +  { +     /* This is some variant of a comparison (PerformComparison will +	sort out which one).  Since most of the other CPRT +	instructions are oddball cases of some sort or other it makes +	sense to pull this out into a fast path.  */ +     return PerformComparison(opcode); +  } + +  /* Hint to GCC that we'd like a jump table rather than a load of CMPs */ +  switch ((opcode & 0x700000) >> 20) +  { +    case  FLT_CODE >> 20: nRc = PerformFLT(opcode); break; +    case  FIX_CODE >> 20: nRc = PerformFIX(opcode); break; + +    case  WFS_CODE >> 20: writeFPSR(readRegister(getRd(opcode))); break; +    case  RFS_CODE >> 20: writeRegister(getRd(opcode),readFPSR()); break; + +#if 0    /* We currently have no use for the FPCR, so there's no point +	    in emulating it. */ +    case  WFC_CODE >> 20: writeFPCR(readRegister(getRd(opcode))); +    case  RFC_CODE >> 20: writeRegister(getRd(opcode),readFPCR()); break; +#endif + +    default: nRc = 0; +  } + +  return nRc; +} + +unsigned int PerformFLT(const unsigned int opcode) +{ +   FPA11 *fpa11 = GET_FPA11(); + +   unsigned int nRc = 1; +   SetRoundingMode(opcode); + +   switch (opcode & MASK_ROUNDING_PRECISION) +   { +      case ROUND_SINGLE: +      { +        fpa11->fType[getFn(opcode)] = typeSingle; +        fpa11->fpreg[getFn(opcode)].fSingle = +	   int32_to_float32(readRegister(getRd(opcode)), &fpa11->fp_status); +      } +      break; + +      case ROUND_DOUBLE: +      { +        fpa11->fType[getFn(opcode)] = typeDouble; +        fpa11->fpreg[getFn(opcode)].fDouble = +            int32_to_float64(readRegister(getRd(opcode)), &fpa11->fp_status); +      } +      break; + +      case ROUND_EXTENDED: +      { +        fpa11->fType[getFn(opcode)] = typeExtended; +        fpa11->fpreg[getFn(opcode)].fExtended = +	   int32_to_floatx80(readRegister(getRd(opcode)), &fpa11->fp_status); +      } +      break; + +      default: nRc = 0; +  } + +  return nRc; +} + +unsigned int PerformFIX(const unsigned int opcode) +{ +   FPA11 *fpa11 = GET_FPA11(); +   unsigned int nRc = 1; +   unsigned int Fn = getFm(opcode); + +   SetRoundingMode(opcode); + +   switch (fpa11->fType[Fn]) +   { +      case typeSingle: +      { +         writeRegister(getRd(opcode), +	               float32_to_int32(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status)); +      } +      break; + +      case typeDouble: +      { +         //printf("F%d is 0x%" PRIx64 "\n",Fn,fpa11->fpreg[Fn].fDouble); +         writeRegister(getRd(opcode), +	               float64_to_int32(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status)); +      } +      break; + +      case typeExtended: +      { +         writeRegister(getRd(opcode), +	               floatx80_to_int32(fpa11->fpreg[Fn].fExtended, &fpa11->fp_status)); +      } +      break; + +      default: nRc = 0; +  } + +  return nRc; +} + + +static __inline unsigned int +PerformComparisonOperation(floatx80 Fn, floatx80 Fm) +{ +   FPA11 *fpa11 = GET_FPA11(); +   unsigned int flags = 0; + +   /* test for less than condition */ +   if (floatx80_lt(Fn,Fm, &fpa11->fp_status)) +   { +      flags |= CC_NEGATIVE; +   } + +   /* test for equal condition */ +   if (floatx80_eq_quiet(Fn,Fm, &fpa11->fp_status)) +   { +      flags |= CC_ZERO; +   } + +   /* test for greater than or equal condition */ +   if (floatx80_lt(Fm,Fn, &fpa11->fp_status)) +   { +      flags |= CC_CARRY; +   } + +   writeConditionCodes(flags); +   return 1; +} + +/* This instruction sets the flags N, Z, C, V in the FPSR. */ + +static unsigned int PerformComparison(const unsigned int opcode) +{ +   FPA11 *fpa11 = GET_FPA11(); +   unsigned int Fn, Fm; +   floatx80 rFn, rFm; +   int e_flag = opcode & 0x400000;	/* 1 if CxFE */ +   int n_flag = opcode & 0x200000;	/* 1 if CNxx */ +   unsigned int flags = 0; + +   //printk("PerformComparison(0x%08x)\n",opcode); + +   Fn = getFn(opcode); +   Fm = getFm(opcode); + +   /* Check for unordered condition and convert all operands to 80-bit +      format. +      ?? Might be some mileage in avoiding this conversion if possible. +      Eg, if both operands are 32-bit, detect this and do a 32-bit +      comparison (cheaper than an 80-bit one).  */ +   switch (fpa11->fType[Fn]) +   { +      case typeSingle: +        //printk("single.\n"); +	if (float32_is_any_nan(fpa11->fpreg[Fn].fSingle)) +	   goto unordered; +        rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status); +      break; + +      case typeDouble: +        //printk("double.\n"); +	if (float64_is_any_nan(fpa11->fpreg[Fn].fDouble)) +	   goto unordered; +        rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status); +      break; + +      case typeExtended: +        //printk("extended.\n"); +	if (floatx80_is_any_nan(fpa11->fpreg[Fn].fExtended)) +	   goto unordered; +        rFn = fpa11->fpreg[Fn].fExtended; +      break; + +      default: return 0; +   } + +   if (CONSTANT_FM(opcode)) +   { +     //printk("Fm is a constant: #%d.\n",Fm); +     rFm = getExtendedConstant(Fm); +     if (floatx80_is_any_nan(rFm)) +        goto unordered; +   } +   else +   { +     //printk("Fm = r%d which contains a ",Fm); +      switch (fpa11->fType[Fm]) +      { +         case typeSingle: +           //printk("single.\n"); +	   if (float32_is_any_nan(fpa11->fpreg[Fm].fSingle)) +	      goto unordered; +           rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle, &fpa11->fp_status); +         break; + +         case typeDouble: +           //printk("double.\n"); +	   if (float64_is_any_nan(fpa11->fpreg[Fm].fDouble)) +	      goto unordered; +           rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble, &fpa11->fp_status); +         break; + +         case typeExtended: +           //printk("extended.\n"); +	   if (floatx80_is_any_nan(fpa11->fpreg[Fm].fExtended)) +	      goto unordered; +           rFm = fpa11->fpreg[Fm].fExtended; +         break; + +         default: return 0; +      } +   } + +   if (n_flag) +   { +      rFm.high ^= 0x8000; +   } + +   return PerformComparisonOperation(rFn,rFm); + + unordered: +   /* ?? The FPA data sheet is pretty vague about this, in particular +      about whether the non-E comparisons can ever raise exceptions. +      This implementation is based on a combination of what it says in +      the data sheet, observation of how the Acorn emulator actually +      behaves (and how programs expect it to) and guesswork.  */ +   flags |= CC_OVERFLOW; +   flags &= ~(CC_ZERO | CC_NEGATIVE); + +   if (BIT_AC & readFPSR()) flags |= CC_CARRY; + +   if (e_flag) float_raise(float_flag_invalid, &fpa11->fp_status); + +   writeConditionCodes(flags); +   return 1; +} diff --git a/linux-user/arm/nwfpe/fpopcode.c b/linux-user/arm/nwfpe/fpopcode.c new file mode 100644 index 00000000..0ada30c6 --- /dev/null +++ b/linux-user/arm/nwfpe/fpopcode.c @@ -0,0 +1,90 @@ +/* +    NetWinder Floating Point Emulator +    (c) Rebel.COM, 1998,1999 + +    Direct questions, comments to Scott Bambrough <scottb@netwinder.org> + +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 2 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "fpa11.h" +#include "fpu/softfloat.h" +#include "fpopcode.h" +#include "fpsr.h" +//#include "fpmodule.h" +//#include "fpmodule.inl" + +const floatx80 floatx80Constant[] = { +  { 0x0000000000000000ULL, 0x0000},	/* extended 0.0 */ +  { 0x8000000000000000ULL, 0x3fff},	/* extended 1.0 */ +  { 0x8000000000000000ULL, 0x4000},	/* extended 2.0 */ +  { 0xc000000000000000ULL, 0x4000},	/* extended 3.0 */ +  { 0x8000000000000000ULL, 0x4001},	/* extended 4.0 */ +  { 0xa000000000000000ULL, 0x4001},	/* extended 5.0 */ +  { 0x8000000000000000ULL, 0x3ffe},	/* extended 0.5 */ +  { 0xa000000000000000ULL, 0x4002}	/* extended 10.0 */ +}; + +const float64 float64Constant[] = { +  const_float64(0x0000000000000000ULL),		/* double 0.0 */ +  const_float64(0x3ff0000000000000ULL),		/* double 1.0 */ +  const_float64(0x4000000000000000ULL),		/* double 2.0 */ +  const_float64(0x4008000000000000ULL),		/* double 3.0 */ +  const_float64(0x4010000000000000ULL),		/* double 4.0 */ +  const_float64(0x4014000000000000ULL),		/* double 5.0 */ +  const_float64(0x3fe0000000000000ULL),		/* double 0.5 */ +  const_float64(0x4024000000000000ULL)			/* double 10.0 */ +}; + +const float32 float32Constant[] = { +  const_float32(0x00000000),				/* single 0.0 */ +  const_float32(0x3f800000),				/* single 1.0 */ +  const_float32(0x40000000),				/* single 2.0 */ +  const_float32(0x40400000),				/* single 3.0 */ +  const_float32(0x40800000),				/* single 4.0 */ +  const_float32(0x40a00000),				/* single 5.0 */ +  const_float32(0x3f000000),				/* single 0.5 */ +  const_float32(0x41200000)				/* single 10.0 */ +}; + +unsigned int getRegisterCount(const unsigned int opcode) +{ +  unsigned int nRc; + +  switch (opcode & MASK_REGISTER_COUNT) +  { +    case 0x00000000: nRc = 4; break; +    case 0x00008000: nRc = 1; break; +    case 0x00400000: nRc = 2; break; +    case 0x00408000: nRc = 3; break; +    default: nRc = 0; +  } + +  return(nRc); +} + +unsigned int getDestinationSize(const unsigned int opcode) +{ +  unsigned int nRc; + +  switch (opcode & MASK_DESTINATION_SIZE) +  { +    case 0x00000000: nRc = typeSingle; break; +    case 0x00000080: nRc = typeDouble; break; +    case 0x00080000: nRc = typeExtended; break; +    default: nRc = typeNone; +  } + +  return(nRc); +} diff --git a/linux-user/arm/nwfpe/fpopcode.h b/linux-user/arm/nwfpe/fpopcode.h new file mode 100644 index 00000000..1b1137f3 --- /dev/null +++ b/linux-user/arm/nwfpe/fpopcode.h @@ -0,0 +1,390 @@ +/* +    NetWinder Floating Point Emulator +    (c) Rebel.COM, 1998,1999 + +    Direct questions, comments to Scott Bambrough <scottb@netwinder.org> + +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 2 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __FPOPCODE_H__ +#define __FPOPCODE_H__ + +/* +ARM Floating Point Instruction Classes +| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +|c o n d|1 1 0 P|U|u|W|L|   Rn  |v|  Fd |0|0|0|1|  o f f s e t  | CPDT +|c o n d|1 1 0 P|U|w|W|L|   Rn  |x|  Fd |0|0|0|1|  o f f s e t  | CPDT +| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | +|c o n d|1 1 1 0|a|b|c|d|e|  Fn |j|  Fd |0|0|0|1|f|g|h|0|i|  Fm | CPDO +|c o n d|1 1 1 0|a|b|c|L|e|  Fn |   Rd  |0|0|0|1|f|g|h|1|i|  Fm | CPRT +|c o n d|1 1 1 0|a|b|c|1|e|  Fn |1|1|1|1|0|0|0|1|f|g|h|1|i|  Fm | comparisons +| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | + +CPDT		data transfer instructions +		LDF, STF, LFM, SFM + +CPDO		dyadic arithmetic instructions +		ADF, MUF, SUF, RSF, DVF, RDF, +		POW, RPW, RMF, FML, FDV, FRD, POL + +CPDO		monadic arithmetic instructions +		MVF, MNF, ABS, RND, SQT, LOG, LGN, EXP, +		SIN, COS, TAN, ASN, ACS, ATN, URD, NRM + +CPRT		joint arithmetic/data transfer instructions +		FIX (arithmetic followed by load/store) +		FLT (load/store followed by arithmetic) +		CMF, CNF CMFE, CNFE (comparisons) +		WFS, RFS (write/read floating point status register) +		WFC, RFC (write/read floating point control register) + +cond		condition codes +P		pre/post index bit: 0 = postindex, 1 = preindex +U		up/down bit: 0 = stack grows down, 1 = stack grows up +W		write back bit: 1 = update base register (Rn) +L		load/store bit: 0 = store, 1 = load +Rn		base register +Rd		destination/source register +Fd		floating point destination register +Fn		floating point source register +Fm		floating point source register or floating point constant + +uv		transfer length (TABLE 1) +wx		register count (TABLE 2) +abcd		arithmetic opcode (TABLES 3 & 4) +ef		destination size (rounding precision) (TABLE 5) +gh		rounding mode (TABLE 6) +j		dyadic/monadic bit: 0 = dyadic, 1 = monadic +i 		constant bit: 1 = constant (TABLE 6) +*/ + +/* +TABLE 1 ++-------------------------+---+---+---------+---------+ +|  Precision              | u | v | FPSR.EP | length  | ++-------------------------+---+---+---------+---------+ +| Single                  | 0 | 0 |    x    | 1 words | +| Double                  | 1 | 1 |    x    | 2 words | +| Extended                | 1 | 1 |    x    | 3 words | +| Packed decimal          | 1 | 1 |    0    | 3 words | +| Expanded packed decimal | 1 | 1 |    1    | 4 words | ++-------------------------+---+---+---------+---------+ +Note: x = don't care +*/ + +/* +TABLE 2 ++---+---+---------------------------------+ +| w | x | Number of registers to transfer | ++---+---+---------------------------------+ +| 0 | 1 |  1                              | +| 1 | 0 |  2                              | +| 1 | 1 |  3                              | +| 0 | 0 |  4                              | ++---+---+---------------------------------+ +*/ + +/* +TABLE 3: Dyadic Floating Point Opcodes ++---+---+---+---+----------+-----------------------+-----------------------+ +| a | b | c | d | Mnemonic | Description           | Operation             | ++---+---+---+---+----------+-----------------------+-----------------------+ +| 0 | 0 | 0 | 0 | ADF      | Add                   | Fd := Fn + Fm         | +| 0 | 0 | 0 | 1 | MUF      | Multiply              | Fd := Fn * Fm         | +| 0 | 0 | 1 | 0 | SUF      | Subtract              | Fd := Fn - Fm         | +| 0 | 0 | 1 | 1 | RSF      | Reverse subtract      | Fd := Fm - Fn         | +| 0 | 1 | 0 | 0 | DVF      | Divide                | Fd := Fn / Fm         | +| 0 | 1 | 0 | 1 | RDF      | Reverse divide        | Fd := Fm / Fn         | +| 0 | 1 | 1 | 0 | POW      | Power                 | Fd := Fn ^ Fm         | +| 0 | 1 | 1 | 1 | RPW      | Reverse power         | Fd := Fm ^ Fn         | +| 1 | 0 | 0 | 0 | RMF      | Remainder             | Fd := IEEE rem(Fn/Fm) | +| 1 | 0 | 0 | 1 | FML      | Fast Multiply         | Fd := Fn * Fm         | +| 1 | 0 | 1 | 0 | FDV      | Fast Divide           | Fd := Fn / Fm         | +| 1 | 0 | 1 | 1 | FRD      | Fast reverse divide   | Fd := Fm / Fn         | +| 1 | 1 | 0 | 0 | POL      | Polar angle (ArcTan2) | Fd := arctan2(Fn,Fm)  | +| 1 | 1 | 0 | 1 |          | undefined instruction | trap                  | +| 1 | 1 | 1 | 0 |          | undefined instruction | trap                  | +| 1 | 1 | 1 | 1 |          | undefined instruction | trap                  | ++---+---+---+---+----------+-----------------------+-----------------------+ +Note: POW, RPW, POL are deprecated, and are available for backwards +      compatibility only. +*/ + +/* +TABLE 4: Monadic Floating Point Opcodes ++---+---+---+---+----------+-----------------------+-----------------------+ +| a | b | c | d | Mnemonic | Description           | Operation             | ++---+---+---+---+----------+-----------------------+-----------------------+ +| 0 | 0 | 0 | 0 | MVF      | Move                  | Fd := Fm              | +| 0 | 0 | 0 | 1 | MNF      | Move negated          | Fd := - Fm            | +| 0 | 0 | 1 | 0 | ABS      | Absolute value        | Fd := abs(Fm)         | +| 0 | 0 | 1 | 1 | RND      | Round to integer      | Fd := int(Fm)         | +| 0 | 1 | 0 | 0 | SQT      | Square root           | Fd := sqrt(Fm)        | +| 0 | 1 | 0 | 1 | LOG      | Log base 10           | Fd := log10(Fm)       | +| 0 | 1 | 1 | 0 | LGN      | Log base e            | Fd := ln(Fm)          | +| 0 | 1 | 1 | 1 | EXP      | Exponent              | Fd := e ^ Fm          | +| 1 | 0 | 0 | 0 | SIN      | Sine                  | Fd := sin(Fm)         | +| 1 | 0 | 0 | 1 | COS      | Cosine                | Fd := cos(Fm)         | +| 1 | 0 | 1 | 0 | TAN      | Tangent               | Fd := tan(Fm)         | +| 1 | 0 | 1 | 1 | ASN      | Arc Sine              | Fd := arcsin(Fm)      | +| 1 | 1 | 0 | 0 | ACS      | Arc Cosine            | Fd := arccos(Fm)      | +| 1 | 1 | 0 | 1 | ATN      | Arc Tangent           | Fd := arctan(Fm)      | +| 1 | 1 | 1 | 0 | URD      | Unnormalized round    | Fd := int(Fm)         | +| 1 | 1 | 1 | 1 | NRM      | Normalize             | Fd := norm(Fm)        | ++---+---+---+---+----------+-----------------------+-----------------------+ +Note: LOG, LGN, EXP, SIN, COS, TAN, ASN, ACS, ATN are deprecated, and are +      available for backwards compatibility only. +*/ + +/* +TABLE 5 ++-------------------------+---+---+ +|  Rounding Precision     | e | f | ++-------------------------+---+---+ +| IEEE Single precision   | 0 | 0 | +| IEEE Double precision   | 0 | 1 | +| IEEE Extended precision | 1 | 0 | +| undefined (trap)        | 1 | 1 | ++-------------------------+---+---+ +*/ + +/* +TABLE 5 ++---------------------------------+---+---+ +|  Rounding Mode                  | g | h | ++---------------------------------+---+---+ +| Round to nearest (default)      | 0 | 0 | +| Round toward plus infinity      | 0 | 1 | +| Round toward negative infinity  | 1 | 0 | +| Round toward zero               | 1 | 1 | ++---------------------------------+---+---+ +*/ + +/* +=== +=== Definitions for load and store instructions +=== +*/ + +/* bit masks */ +#define BIT_PREINDEX	0x01000000 +#define BIT_UP		0x00800000 +#define BIT_WRITE_BACK	0x00200000 +#define BIT_LOAD	0x00100000 + +/* masks for load/store */ +#define MASK_CPDT		0x0c000000  /* data processing opcode */ +#define MASK_OFFSET		0x000000ff +#define MASK_TRANSFER_LENGTH	0x00408000 +#define MASK_REGISTER_COUNT	MASK_TRANSFER_LENGTH +#define MASK_COPROCESSOR	0x00000f00 + +/* Tests for transfer length */ +#define TRANSFER_SINGLE		0x00000000 +#define TRANSFER_DOUBLE		0x00008000 +#define TRANSFER_EXTENDED	0x00400000 +#define TRANSFER_PACKED		MASK_TRANSFER_LENGTH + +/* Get the coprocessor number from the opcode. */ +#define getCoprocessorNumber(opcode)	((opcode & MASK_COPROCESSOR) >> 8) + +/* Get the offset from the opcode. */ +#define getOffset(opcode)		(opcode & MASK_OFFSET) + +/* Tests for specific data transfer load/store opcodes. */ +#define TEST_OPCODE(opcode,mask)	(((opcode) & (mask)) == (mask)) + +#define LOAD_OP(opcode)   TEST_OPCODE((opcode),MASK_CPDT | BIT_LOAD) +#define STORE_OP(opcode)  ((opcode & (MASK_CPDT | BIT_LOAD)) == MASK_CPDT) + +#define LDF_OP(opcode)	(LOAD_OP(opcode) && (getCoprocessorNumber(opcode) == 1)) +#define LFM_OP(opcode)	(LOAD_OP(opcode) && (getCoprocessorNumber(opcode) == 2)) +#define STF_OP(opcode)	(STORE_OP(opcode) && (getCoprocessorNumber(opcode) == 1)) +#define SFM_OP(opcode)	(STORE_OP(opcode) && (getCoprocessorNumber(opcode) == 2)) + +#define PREINDEXED(opcode)		((opcode & BIT_PREINDEX) != 0) +#define POSTINDEXED(opcode)		((opcode & BIT_PREINDEX) == 0) +#define BIT_UP_SET(opcode)		((opcode & BIT_UP) != 0) +#define BIT_UP_CLEAR(opcode)		((opcode & BIT_DOWN) == 0) +#define WRITE_BACK(opcode)		((opcode & BIT_WRITE_BACK) != 0) +#define LOAD(opcode)			((opcode & BIT_LOAD) != 0) +#define STORE(opcode)			((opcode & BIT_LOAD) == 0) + +/* +=== +=== Definitions for arithmetic instructions +=== +*/ +/* bit masks */ +#define BIT_MONADIC	0x00008000 +#define BIT_CONSTANT	0x00000008 + +#define CONSTANT_FM(opcode)		((opcode & BIT_CONSTANT) != 0) +#define MONADIC_INSTRUCTION(opcode)	((opcode & BIT_MONADIC) != 0) + +/* instruction identification masks */ +#define MASK_CPDO		0x0e000000  /* arithmetic opcode */ +#define MASK_ARITHMETIC_OPCODE	0x00f08000 +#define MASK_DESTINATION_SIZE	0x00080080 + +/* dyadic arithmetic opcodes. */ +#define ADF_CODE	0x00000000 +#define MUF_CODE	0x00100000 +#define SUF_CODE	0x00200000 +#define RSF_CODE	0x00300000 +#define DVF_CODE	0x00400000 +#define RDF_CODE	0x00500000 +#define POW_CODE	0x00600000 +#define RPW_CODE	0x00700000 +#define RMF_CODE	0x00800000 +#define FML_CODE	0x00900000 +#define FDV_CODE	0x00a00000 +#define FRD_CODE	0x00b00000 +#define POL_CODE	0x00c00000 +/* 0x00d00000 is an invalid dyadic arithmetic opcode */ +/* 0x00e00000 is an invalid dyadic arithmetic opcode */ +/* 0x00f00000 is an invalid dyadic arithmetic opcode */ + +/* monadic arithmetic opcodes. */ +#define MVF_CODE	0x00008000 +#define MNF_CODE	0x00108000 +#define ABS_CODE	0x00208000 +#define RND_CODE	0x00308000 +#define SQT_CODE	0x00408000 +#define LOG_CODE	0x00508000 +#define LGN_CODE	0x00608000 +#define EXP_CODE	0x00708000 +#define SIN_CODE	0x00808000 +#define COS_CODE	0x00908000 +#define TAN_CODE	0x00a08000 +#define ASN_CODE	0x00b08000 +#define ACS_CODE	0x00c08000 +#define ATN_CODE	0x00d08000 +#define URD_CODE	0x00e08000 +#define NRM_CODE	0x00f08000 + +/* +=== +=== Definitions for register transfer and comparison instructions +=== +*/ + +#define MASK_CPRT		0x0e000010  /* register transfer opcode */ +#define MASK_CPRT_CODE		0x00f00000 +#define FLT_CODE		0x00000000 +#define FIX_CODE		0x00100000 +#define WFS_CODE		0x00200000 +#define RFS_CODE		0x00300000 +#define WFC_CODE		0x00400000 +#define RFC_CODE		0x00500000 +#define CMF_CODE		0x00900000 +#define CNF_CODE		0x00b00000 +#define CMFE_CODE		0x00d00000 +#define CNFE_CODE		0x00f00000 + +/* +=== +=== Common definitions +=== +*/ + +/* register masks */ +#define MASK_Rd		0x0000f000 +#define MASK_Rn		0x000f0000 +#define MASK_Fd		0x00007000 +#define MASK_Fm		0x00000007 +#define MASK_Fn		0x00070000 + +/* condition code masks */ +#define CC_MASK		0xf0000000 +#define CC_NEGATIVE	0x80000000 +#define CC_ZERO		0x40000000 +#define CC_CARRY	0x20000000 +#define CC_OVERFLOW	0x10000000 +#define CC_EQ		0x00000000 +#define CC_NE		0x10000000 +#define CC_CS		0x20000000 +#define CC_HS		CC_CS +#define CC_CC		0x30000000 +#define CC_LO		CC_CC +#define CC_MI		0x40000000 +#define CC_PL		0x50000000 +#define CC_VS		0x60000000 +#define CC_VC		0x70000000 +#define CC_HI		0x80000000 +#define CC_LS		0x90000000 +#define CC_GE		0xa0000000 +#define CC_LT		0xb0000000 +#define CC_GT		0xc0000000 +#define CC_LE		0xd0000000 +#define CC_AL		0xe0000000 +#define CC_NV		0xf0000000 + +/* rounding masks/values */ +#define MASK_ROUNDING_MODE	0x00000060 +#define ROUND_TO_NEAREST	0x00000000 +#define ROUND_TO_PLUS_INFINITY	0x00000020 +#define ROUND_TO_MINUS_INFINITY	0x00000040 +#define ROUND_TO_ZERO		0x00000060 + +#define MASK_ROUNDING_PRECISION	0x00080080 +#define ROUND_SINGLE		0x00000000 +#define ROUND_DOUBLE		0x00000080 +#define ROUND_EXTENDED		0x00080000 + +/* Get the condition code from the opcode. */ +#define getCondition(opcode)		(opcode >> 28) + +/* Get the source register from the opcode. */ +#define getRn(opcode)			((opcode & MASK_Rn) >> 16) + +/* Get the destination floating point register from the opcode. */ +#define getFd(opcode)			((opcode & MASK_Fd) >> 12) + +/* Get the first source floating point register from the opcode. */ +#define getFn(opcode)		((opcode & MASK_Fn) >> 16) + +/* Get the second source floating point register from the opcode. */ +#define getFm(opcode)		(opcode & MASK_Fm) + +/* Get the destination register from the opcode. */ +#define getRd(opcode)		((opcode & MASK_Rd) >> 12) + +/* Get the rounding mode from the opcode. */ +#define getRoundingMode(opcode)		((opcode & MASK_ROUNDING_MODE) >> 5) + +extern const floatx80 floatx80Constant[]; +extern const float64 float64Constant[]; +extern const float32 float32Constant[]; + +static inline floatx80 getExtendedConstant(const unsigned int nIndex) +{ +   return floatx80Constant[nIndex]; +} + +static inline float64 getDoubleConstant(const unsigned int nIndex) +{ +   return float64Constant[nIndex]; +} + +static inline float32 getSingleConstant(const unsigned int nIndex) +{ +   return float32Constant[nIndex]; +} + +unsigned int getRegisterCount(const unsigned int opcode); +unsigned int getDestinationSize(const unsigned int opcode); + +#endif diff --git a/linux-user/arm/nwfpe/fpsr.h b/linux-user/arm/nwfpe/fpsr.h new file mode 100644 index 00000000..859dcd58 --- /dev/null +++ b/linux-user/arm/nwfpe/fpsr.h @@ -0,0 +1,107 @@ +/* +    NetWinder Floating Point Emulator +    (c) Rebel.com, 1998-1999 + +    Direct questions, comments to Scott Bambrough <scottb@netwinder.org> + +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 2 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef __FPSR_H__ +#define __FPSR_H__ + +/* +The FPSR is a 32 bit register consisting of 4 parts, each exactly +one byte. + +	SYSTEM ID +	EXCEPTION TRAP ENABLE BYTE +	SYSTEM CONTROL BYTE +	CUMULATIVE EXCEPTION FLAGS BYTE + +The FPCR is a 32 bit register consisting of bit flags. +*/ + +/* SYSTEM ID +------------ +Note: the system id byte is read only  */ + +typedef unsigned int FPSR;  /* type for floating point status register */ +typedef unsigned int FPCR;  /* type for floating point control register */ + +#define MASK_SYSID		0xff000000 +#define BIT_HARDWARE		0x80000000 +#define FP_EMULATOR		0x01000000	/* System ID for emulator */ +#define FP_ACCELERATOR		0x81000000	/* System ID for FPA11 */ + +/* EXCEPTION TRAP ENABLE BYTE +----------------------------- */ + +#define MASK_TRAP_ENABLE	0x00ff0000 +#define MASK_TRAP_ENABLE_STRICT	0x001f0000 +#define BIT_IXE		0x00100000   /* inexact exception enable */ +#define BIT_UFE		0x00080000   /* underflow exception enable */ +#define BIT_OFE		0x00040000   /* overflow exception enable */ +#define BIT_DZE		0x00020000   /* divide by zero exception enable */ +#define BIT_IOE		0x00010000   /* invalid operation exception enable */ + +/* SYSTEM CONTROL BYTE +---------------------- */ + +#define MASK_SYSTEM_CONTROL	0x0000ff00 +#define MASK_TRAP_STRICT	0x00001f00 + +#define BIT_AC	0x00001000	/* use alternative C-flag definition +				   for compares */ +#define BIT_EP	0x00000800	/* use expanded packed decimal format */ +#define BIT_SO	0x00000400	/* select synchronous operation of FPA */ +#define BIT_NE	0x00000200	/* NaN exception bit */ +#define BIT_ND	0x00000100	/* no denormalized numbers bit */ + +/* CUMULATIVE EXCEPTION FLAGS BYTE +---------------------------------- */ + +#define MASK_EXCEPTION_FLAGS		0x000000ff +#define MASK_EXCEPTION_FLAGS_STRICT	0x0000001f + +#define BIT_IXC		0x00000010	/* inexact exception flag */ +#define BIT_UFC		0x00000008	/* underflow exception flag */ +#define BIT_OFC		0x00000004	/* overfloat exception flag */ +#define BIT_DZC		0x00000002	/* divide by zero exception flag */ +#define BIT_IOC		0x00000001	/* invalid operation exception flag */ + +/* Floating Point Control Register +----------------------------------*/ + +#define BIT_RU		0x80000000	/* rounded up bit */ +#define BIT_IE		0x10000000	/* inexact bit */ +#define BIT_MO		0x08000000	/* mantissa overflow bit */ +#define BIT_EO		0x04000000	/* exponent overflow bit */ +#define BIT_SB		0x00000800	/* store bounce */ +#define BIT_AB		0x00000400	/* arithmetic bounce */ +#define BIT_RE		0x00000200	/* rounding exception */ +#define BIT_DA		0x00000100	/* disable FPA */ + +#define MASK_OP		0x00f08010	/* AU operation code */ +#define MASK_PR		0x00080080	/* AU precision */ +#define MASK_S1		0x00070000	/* AU source register 1 */ +#define MASK_S2		0x00000007	/* AU source register 2 */ +#define MASK_DS		0x00007000	/* AU destination register */ +#define MASK_RM		0x00000060	/* AU rounding mode */ +#define MASK_ALU	0x9cfff2ff	/* only ALU can write these bits */ +#define MASK_RESET	0x00000d00	/* bits set on reset, all others cleared */ +#define MASK_WFC	MASK_RESET +#define MASK_RFC	~MASK_RESET + +#endif diff --git a/linux-user/arm/nwfpe/single_cpdo.c b/linux-user/arm/nwfpe/single_cpdo.c new file mode 100644 index 00000000..2bfb359e --- /dev/null +++ b/linux-user/arm/nwfpe/single_cpdo.c @@ -0,0 +1,252 @@ +/* +    NetWinder Floating Point Emulator +    (c) Rebel.COM, 1998,1999 + +    Direct questions, comments to Scott Bambrough <scottb@netwinder.org> + +    This program is free software; you can redistribute it and/or modify +    it under the terms of the GNU General Public License as published by +    the Free Software Foundation; either version 2 of the License, or +    (at your option) any later version. + +    This program is distributed in the hope that it will be useful, +    but WITHOUT ANY WARRANTY; without even the implied warranty of +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +    GNU General Public License for more details. + +    You should have received a copy of the GNU General Public License +    along with this program; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "fpa11.h" +#include "fpu/softfloat.h" +#include "fpopcode.h" + +float32 float32_exp(float32 Fm); +float32 float32_ln(float32 Fm); +float32 float32_sin(float32 rFm); +float32 float32_cos(float32 rFm); +float32 float32_arcsin(float32 rFm); +float32 float32_arctan(float32 rFm); +float32 float32_log(float32 rFm); +float32 float32_tan(float32 rFm); +float32 float32_arccos(float32 rFm); +float32 float32_pow(float32 rFn,float32 rFm); +float32 float32_pol(float32 rFn,float32 rFm); + +unsigned int SingleCPDO(const unsigned int opcode) +{ +   FPA11 *fpa11 = GET_FPA11(); +   float32 rFm, rFn = float32_zero; +   unsigned int Fd, Fm, Fn, nRc = 1; + +   Fm = getFm(opcode); +   if (CONSTANT_FM(opcode)) +   { +     rFm = getSingleConstant(Fm); +   } +   else +   { +     switch (fpa11->fType[Fm]) +     { +        case typeSingle: +          rFm = fpa11->fpreg[Fm].fSingle; +        break; + +        default: return 0; +     } +   } + +   if (!MONADIC_INSTRUCTION(opcode)) +   { +      Fn = getFn(opcode); +      switch (fpa11->fType[Fn]) +      { +        case typeSingle: +          rFn = fpa11->fpreg[Fn].fSingle; +        break; + +        default: return 0; +      } +   } + +   Fd = getFd(opcode); +   switch (opcode & MASK_ARITHMETIC_OPCODE) +   { +      /* dyadic opcodes */ +      case ADF_CODE: +         fpa11->fpreg[Fd].fSingle = float32_add(rFn,rFm, &fpa11->fp_status); +      break; + +      case MUF_CODE: +      case FML_CODE: +        fpa11->fpreg[Fd].fSingle = float32_mul(rFn,rFm, &fpa11->fp_status); +      break; + +      case SUF_CODE: +         fpa11->fpreg[Fd].fSingle = float32_sub(rFn,rFm, &fpa11->fp_status); +      break; + +      case RSF_CODE: +         fpa11->fpreg[Fd].fSingle = float32_sub(rFm,rFn, &fpa11->fp_status); +      break; + +      case DVF_CODE: +      case FDV_CODE: +         fpa11->fpreg[Fd].fSingle = float32_div(rFn,rFm, &fpa11->fp_status); +      break; + +      case RDF_CODE: +      case FRD_CODE: +         fpa11->fpreg[Fd].fSingle = float32_div(rFm,rFn, &fpa11->fp_status); +      break; + +#if 0 +      case POW_CODE: +         fpa11->fpreg[Fd].fSingle = float32_pow(rFn,rFm); +      break; + +      case RPW_CODE: +         fpa11->fpreg[Fd].fSingle = float32_pow(rFm,rFn); +      break; +#endif + +      case RMF_CODE: +         fpa11->fpreg[Fd].fSingle = float32_rem(rFn,rFm, &fpa11->fp_status); +      break; + +#if 0 +      case POL_CODE: +         fpa11->fpreg[Fd].fSingle = float32_pol(rFn,rFm); +      break; +#endif + +      /* monadic opcodes */ +      case MVF_CODE: +         fpa11->fpreg[Fd].fSingle = rFm; +      break; + +      case MNF_CODE: +         fpa11->fpreg[Fd].fSingle = float32_chs(rFm); +      break; + +      case ABS_CODE: +         fpa11->fpreg[Fd].fSingle = float32_abs(rFm); +      break; + +      case RND_CODE: +      case URD_CODE: +         fpa11->fpreg[Fd].fSingle = float32_round_to_int(rFm, &fpa11->fp_status); +      break; + +      case SQT_CODE: +         fpa11->fpreg[Fd].fSingle = float32_sqrt(rFm, &fpa11->fp_status); +      break; + +#if 0 +      case LOG_CODE: +         fpa11->fpreg[Fd].fSingle = float32_log(rFm); +      break; + +      case LGN_CODE: +         fpa11->fpreg[Fd].fSingle = float32_ln(rFm); +      break; + +      case EXP_CODE: +         fpa11->fpreg[Fd].fSingle = float32_exp(rFm); +      break; + +      case SIN_CODE: +         fpa11->fpreg[Fd].fSingle = float32_sin(rFm); +      break; + +      case COS_CODE: +         fpa11->fpreg[Fd].fSingle = float32_cos(rFm); +      break; + +      case TAN_CODE: +         fpa11->fpreg[Fd].fSingle = float32_tan(rFm); +      break; + +      case ASN_CODE: +         fpa11->fpreg[Fd].fSingle = float32_arcsin(rFm); +      break; + +      case ACS_CODE: +         fpa11->fpreg[Fd].fSingle = float32_arccos(rFm); +      break; + +      case ATN_CODE: +         fpa11->fpreg[Fd].fSingle = float32_arctan(rFm); +      break; +#endif + +      case NRM_CODE: +      break; + +      default: +      { +        nRc = 0; +      } +   } + +   if (0 != nRc) fpa11->fType[Fd] = typeSingle; +   return nRc; +} + +#if 0 +float32 float32_exp(float32 Fm) +{ +//series +} + +float32 float32_ln(float32 Fm) +{ +//series +} + +float32 float32_sin(float32 rFm) +{ +//series +} + +float32 float32_cos(float32 rFm) +{ +//series +} + +float32 float32_arcsin(float32 rFm) +{ +//series +} + +float32 float32_arctan(float32 rFm) +{ +  //series +} + +float32 float32_arccos(float32 rFm) +{ +   //return float32_sub(halfPi,float32_arcsin(rFm)); +} + +float32 float32_log(float32 rFm) +{ +  return float32_div(float32_ln(rFm),getSingleConstant(7)); +} + +float32 float32_tan(float32 rFm) +{ +  return float32_div(float32_sin(rFm),float32_cos(rFm)); +} + +float32 float32_pow(float32 rFn,float32 rFm) +{ +  return float32_exp(float32_mul(rFm,float32_ln(rFn))); +} + +float32 float32_pol(float32 rFn,float32 rFm) +{ +  return float32_arctan(float32_div(rFn,rFm)); +} +#endif diff --git a/linux-user/arm/syscall.h b/linux-user/arm/syscall.h new file mode 100644 index 00000000..3844a961 --- /dev/null +++ b/linux-user/arm/syscall.h @@ -0,0 +1,50 @@ + +/* this struct defines the way the registers are stored on the +   stack during a system call. */ + +struct target_pt_regs { +    abi_long uregs[18]; +}; + +#define ARM_cpsr	uregs[16] +#define ARM_pc		uregs[15] +#define ARM_lr		uregs[14] +#define ARM_sp		uregs[13] +#define ARM_ip		uregs[12] +#define ARM_fp		uregs[11] +#define ARM_r10		uregs[10] +#define ARM_r9		uregs[9] +#define ARM_r8		uregs[8] +#define ARM_r7		uregs[7] +#define ARM_r6		uregs[6] +#define ARM_r5		uregs[5] +#define ARM_r4		uregs[4] +#define ARM_r3		uregs[3] +#define ARM_r2		uregs[2] +#define ARM_r1		uregs[1] +#define ARM_r0		uregs[0] +#define ARM_ORIG_r0	uregs[17] + +#define ARM_SYSCALL_BASE	0x900000 +#define ARM_THUMB_SYSCALL	0 + +#define ARM_NR_BASE	  0xf0000 +#define ARM_NR_breakpoint (ARM_NR_BASE + 1) +#define ARM_NR_cacheflush (ARM_NR_BASE + 2) +#define ARM_NR_set_tls	  (ARM_NR_BASE + 5) + +#define ARM_NR_semihosting	  0x123456 +#define ARM_NR_thumb_semihosting  0xAB + +#if defined(TARGET_WORDS_BIGENDIAN) +#define UNAME_MACHINE "armv5teb" +#else +#define UNAME_MACHINE "armv5tel" +#endif +#define UNAME_MINIMUM_RELEASE "2.6.32" + +#define TARGET_CLONE_BACKWARDS + +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_MLOCKALL_MCL_CURRENT 1 +#define TARGET_MLOCKALL_MCL_FUTURE  2 diff --git a/linux-user/arm/syscall_nr.h b/linux-user/arm/syscall_nr.h new file mode 100644 index 00000000..53552bea --- /dev/null +++ b/linux-user/arm/syscall_nr.h @@ -0,0 +1,386 @@ +/* + * This file contains the system call numbers. + */ + +#define TARGET_NR_restart_syscall		(  0) +#define TARGET_NR_exit			(  1) +#define TARGET_NR_fork			(  2) +#define TARGET_NR_read			(  3) +#define TARGET_NR_write			(  4) +#define TARGET_NR_open			(  5) +#define TARGET_NR_close			(  6) +#define TARGET_NR_waitpid			(  7)	/* removed */ +#define TARGET_NR_creat			(  8) +#define TARGET_NR_link			(  9) +#define TARGET_NR_unlink			( 10) +#define TARGET_NR_execve			( 11) +#define TARGET_NR_chdir			( 12) +#define TARGET_NR_time			( 13) +#define TARGET_NR_mknod			( 14) +#define TARGET_NR_chmod			( 15) +#define TARGET_NR_lchown			( 16) +#define TARGET_NR_break			( 17)	/* removed */ +					/* 18 was sys_stat */ +#define TARGET_NR_lseek			( 19) +#define TARGET_NR_getpid			( 20) +#define TARGET_NR_mount			( 21) +#define TARGET_NR_umount			( 22) +#define TARGET_NR_setuid			( 23) +#define TARGET_NR_getuid			( 24) +#define TARGET_NR_stime			( 25) +#define TARGET_NR_ptrace			( 26) +#define TARGET_NR_alarm			( 27) + +#define TARGET_NR_pause			( 29) +#define TARGET_NR_utime			( 30) +#define TARGET_NR_stty			( 31)	/* removed */ +#define TARGET_NR_gtty			( 32)	/* removed */ +#define TARGET_NR_access			( 33) +#define TARGET_NR_nice			( 34) +#define TARGET_NR_ftime			( 35)	/* removed */ +#define TARGET_NR_sync			( 36) +#define TARGET_NR_kill			( 37) +#define TARGET_NR_rename			( 38) +#define TARGET_NR_mkdir			( 39) +#define TARGET_NR_rmdir			( 40) +#define TARGET_NR_dup			( 41) +#define TARGET_NR_pipe			( 42) +#define TARGET_NR_times			( 43) +#define TARGET_NR_prof			( 44)	/* removed */ +#define TARGET_NR_brk			( 45) +#define TARGET_NR_setgid			( 46) +#define TARGET_NR_getgid			( 47) +#define TARGET_NR_signal			( 48)	/* removed */ +#define TARGET_NR_geteuid			( 49) +#define TARGET_NR_getegid			( 50) +#define TARGET_NR_acct			( 51) +#define TARGET_NR_umount2			( 52) +#define TARGET_NR_lock			( 53)	/* removed */ +#define TARGET_NR_ioctl			( 54) +#define TARGET_NR_fcntl			( 55) +#define TARGET_NR_mpx			( 56)	/* removed */ +#define TARGET_NR_setpgid			( 57) +#define TARGET_NR_ulimit			( 58)	/* removed */ +					/* 59 was sys_olduname */ +#define TARGET_NR_umask			( 60) +#define TARGET_NR_chroot			( 61) +#define TARGET_NR_ustat			( 62) +#define TARGET_NR_dup2			( 63) +#define TARGET_NR_getppid			( 64) +#define TARGET_NR_getpgrp			( 65) +#define TARGET_NR_setsid			( 66) +#define TARGET_NR_sigaction			( 67) +#define TARGET_NR_sgetmask			( 68)	/* removed */ +#define TARGET_NR_ssetmask			( 69)	/* removed */ +#define TARGET_NR_setreuid			( 70) +#define TARGET_NR_setregid			( 71) +#define TARGET_NR_sigsuspend			( 72) +#define TARGET_NR_sigpending			( 73) +#define TARGET_NR_sethostname		( 74) +#define TARGET_NR_setrlimit			( 75) +#define TARGET_NR_getrlimit			( 76)	/* Back compat 2GB limited rlimit */ +#define TARGET_NR_getrusage			( 77) +#define TARGET_NR_gettimeofday		( 78) +#define TARGET_NR_settimeofday		( 79) +#define TARGET_NR_getgroups			( 80) +#define TARGET_NR_setgroups			( 81) +#define TARGET_NR_select			( 82) +#define TARGET_NR_symlink			( 83) +					/* 84 was sys_lstat */ +#define TARGET_NR_readlink			( 85) +#define TARGET_NR_uselib			( 86) +#define TARGET_NR_swapon			( 87) +#define TARGET_NR_reboot			( 88) +#define TARGET_NR_readdir			( 89) +#define TARGET_NR_mmap			( 90) +#define TARGET_NR_munmap			( 91) +#define TARGET_NR_truncate			( 92) +#define TARGET_NR_ftruncate			( 93) +#define TARGET_NR_fchmod			( 94) +#define TARGET_NR_fchown			( 95) +#define TARGET_NR_getpriority		( 96) +#define TARGET_NR_setpriority		( 97) +#define TARGET_NR_profil			( 98)	/* removed */ +#define TARGET_NR_statfs			( 99) +#define TARGET_NR_fstatfs			(100) +#define TARGET_NR_ioperm			(101) +#define TARGET_NR_socketcall			(102) +#define TARGET_NR_syslog			(103) +#define TARGET_NR_setitimer			(104) +#define TARGET_NR_getitimer			(105) +#define TARGET_NR_stat			(106) +#define TARGET_NR_lstat			(107) +#define TARGET_NR_fstat			(108) +					/* 109 was sys_uname */ +					/* 110 was sys_iopl */ +#define TARGET_NR_vhangup			(111) +#define TARGET_NR_idle			(112) +#define TARGET_NR_syscall			(113) /* syscall to call a syscall! */ +#define TARGET_NR_wait4			(114) +#define TARGET_NR_swapoff			(115) +#define TARGET_NR_sysinfo			(116) +#define TARGET_NR_ipc			(117) +#define TARGET_NR_fsync			(118) +#define TARGET_NR_sigreturn			(119) +#define TARGET_NR_clone			(120) +#define TARGET_NR_setdomainname		(121) +#define TARGET_NR_uname			(122) +#define TARGET_NR_modify_ldt			(123) +#define TARGET_NR_adjtimex			(124) +#define TARGET_NR_mprotect			(125) +#define TARGET_NR_sigprocmask		(126) +#define TARGET_NR_create_module		(127)	/* removed */ +#define TARGET_NR_init_module		(128) +#define TARGET_NR_delete_module		(129) +#define TARGET_NR_get_kernel_syms		(130)	/* removed */ +#define TARGET_NR_quotactl			(131) +#define TARGET_NR_getpgid			(132) +#define TARGET_NR_fchdir			(133) +#define TARGET_NR_bdflush			(134) +#define TARGET_NR_sysfs			(135) +#define TARGET_NR_personality		(136) +#define TARGET_NR_afs_syscall		(137) /* Syscall for Andrew File System */ +#define TARGET_NR_setfsuid			(138) +#define TARGET_NR_setfsgid			(139) +#define TARGET_NR__llseek			(140) +#define TARGET_NR_getdents			(141) +#define TARGET_NR__newselect			(142) +#define TARGET_NR_flock			(143) +#define TARGET_NR_msync			(144) +#define TARGET_NR_readv			(145) +#define TARGET_NR_writev			(146) +#define TARGET_NR_getsid			(147) +#define TARGET_NR_fdatasync			(148) +#define TARGET_NR__sysctl			(149) +#define TARGET_NR_mlock			(150) +#define TARGET_NR_munlock			(151) +#define TARGET_NR_mlockall			(152) +#define TARGET_NR_munlockall			(153) +#define TARGET_NR_sched_setparam		(154) +#define TARGET_NR_sched_getparam		(155) +#define TARGET_NR_sched_setscheduler		(156) +#define TARGET_NR_sched_getscheduler		(157) +#define TARGET_NR_sched_yield		(158) +#define TARGET_NR_sched_get_priority_max	(159) +#define TARGET_NR_sched_get_priority_min	(160) +#define TARGET_NR_sched_rr_get_interval	(161) +#define TARGET_NR_nanosleep			(162) +#define TARGET_NR_mremap			(163) +#define TARGET_NR_setresuid			(164) +#define TARGET_NR_getresuid			(165) +#define TARGET_NR_vm86			(166)	/* removed */ +#define TARGET_NR_query_module		(167)	/* removed */ +#define TARGET_NR_poll			(168) +#define TARGET_NR_nfsservctl			(169) +#define TARGET_NR_setresgid			(170) +#define TARGET_NR_getresgid			(171) +#define TARGET_NR_prctl			(172) +#define TARGET_NR_rt_sigreturn		(173) +#define TARGET_NR_rt_sigaction		(174) +#define TARGET_NR_rt_sigprocmask		(175) +#define TARGET_NR_rt_sigpending		(176) +#define TARGET_NR_rt_sigtimedwait		(177) +#define TARGET_NR_rt_sigqueueinfo		(178) +#define TARGET_NR_rt_sigsuspend		(179) +#define TARGET_NR_pread64                       (180) +#define TARGET_NR_pwrite64                      (181) +#define TARGET_NR_chown			(182) +#define TARGET_NR_getcwd			(183) +#define TARGET_NR_capget			(184) +#define TARGET_NR_capset			(185) +#define TARGET_NR_sigaltstack		(186) +#define TARGET_NR_sendfile			(187) +					/* 188 reserved */ +					/* 189 reserved */ +#define TARGET_NR_vfork			(190) +#define TARGET_NR_ugetrlimit			(191)	/* SuS compliant getrlimit */ +#define TARGET_NR_mmap2			(192) +#define TARGET_NR_truncate64			(193) +#define TARGET_NR_ftruncate64		(194) +#define TARGET_NR_stat64			(195) +#define TARGET_NR_lstat64			(196) +#define TARGET_NR_fstat64			(197) +#define TARGET_NR_lchown32			(198) +#define TARGET_NR_getuid32			(199) +#define TARGET_NR_getgid32			(200) +#define TARGET_NR_geteuid32			(201) +#define TARGET_NR_getegid32			(202) +#define TARGET_NR_setreuid32			(203) +#define TARGET_NR_setregid32			(204) +#define TARGET_NR_getgroups32		(205) +#define TARGET_NR_setgroups32		(206) +#define TARGET_NR_fchown32			(207) +#define TARGET_NR_setresuid32		(208) +#define TARGET_NR_getresuid32		(209) +#define TARGET_NR_setresgid32		(210) +#define TARGET_NR_getresgid32		(211) +#define TARGET_NR_chown32			(212) +#define TARGET_NR_setuid32			(213) +#define TARGET_NR_setgid32			(214) +#define TARGET_NR_setfsuid32			(215) +#define TARGET_NR_setfsgid32			(216) +#define TARGET_NR_getdents64			(217) +#define TARGET_NR_pivot_root			(218) +#define TARGET_NR_mincore			(219) +#define TARGET_NR_madvise			(220) +#define TARGET_NR_fcntl64			(221) +					/* 222 for tux */ +					/* 223 is unused */ +#define TARGET_NR_gettid			(224) +#define TARGET_NR_readahead			(225) +#define TARGET_NR_setxattr			(226) +#define TARGET_NR_lsetxattr			(227) +#define TARGET_NR_fsetxattr			(228) +#define TARGET_NR_getxattr			(229) +#define TARGET_NR_lgetxattr			(230) +#define TARGET_NR_fgetxattr			(231) +#define TARGET_NR_listxattr			(232) +#define TARGET_NR_llistxattr			(233) +#define TARGET_NR_flistxattr			(234) +#define TARGET_NR_removexattr		(235) +#define TARGET_NR_lremovexattr		(236) +#define TARGET_NR_fremovexattr		(237) +#define TARGET_NR_tkill			(238) +#define TARGET_NR_sendfile64			(239) +#define TARGET_NR_futex			(240) +#define TARGET_NR_sched_setaffinity		(241) +#define TARGET_NR_sched_getaffinity		(242) +#define TARGET_NR_io_setup			(243) +#define TARGET_NR_io_destroy			(244) +#define TARGET_NR_io_getevents		(245) +#define TARGET_NR_io_submit			(246) +#define TARGET_NR_io_cancel			(247) +#define TARGET_NR_exit_group			(248) +#define TARGET_NR_lookup_dcookie		(249) +#define TARGET_NR_epoll_create		(250) +#define TARGET_NR_epoll_ctl			(251) +#define TARGET_NR_epoll_wait			(252) +#define TARGET_NR_remap_file_pages		(253) +					/* 254 for set_thread_area */ +					/* 255 for get_thread_area */ +					/* 256 for set_tid_address */ +#define TARGET_NR_set_tid_address		256 +#define TARGET_NR_timer_create		257 +#define TARGET_NR_timer_settime		258 +#define TARGET_NR_timer_gettime		259 +#define TARGET_NR_timer_getoverrun		260 +#define TARGET_NR_timer_delete		261 +#define TARGET_NR_clock_settime		262 +#define TARGET_NR_clock_gettime		263 +#define TARGET_NR_clock_getres		264 +#define TARGET_NR_clock_nanosleep		265 +#define TARGET_NR_statfs64			266 +#define TARGET_NR_fstatfs64			267 +#define TARGET_NR_tgkill			268 +#define TARGET_NR_utimes			269 +#define TARGET_NR_arm_fadvise64_64		270 +#define TARGET_NR_pciconfig_iobase		271 +#define TARGET_NR_pciconfig_read		272 +#define TARGET_NR_pciconfig_write		273 +#define TARGET_NR_mq_open			274 +#define TARGET_NR_mq_unlink			275 +#define TARGET_NR_mq_timedsend		276 +#define TARGET_NR_mq_timedreceive		277 +#define TARGET_NR_mq_notify			278 +#define TARGET_NR_mq_getsetattr		279 +#define TARGET_NR_waitid			280 +#define TARGET_NR_socket			281 +#define TARGET_NR_bind			282 +#define TARGET_NR_connect			283 +#define TARGET_NR_listen			284 +#define TARGET_NR_accept			285 +#define TARGET_NR_getsockname		286 +#define TARGET_NR_getpeername		287 +#define TARGET_NR_socketpair			288 +#define TARGET_NR_send			289 +#define TARGET_NR_sendto			290 +#define TARGET_NR_recv			291 +#define TARGET_NR_recvfrom			292 +#define TARGET_NR_shutdown			293 +#define TARGET_NR_setsockopt			294 +#define TARGET_NR_getsockopt			295 +#define TARGET_NR_sendmsg			296 +#define TARGET_NR_recvmsg			297 +#define TARGET_NR_semop			298 +#define TARGET_NR_semget			299 +#define TARGET_NR_semctl			300 +#define TARGET_NR_msgsnd			301 +#define TARGET_NR_msgrcv			302 +#define TARGET_NR_msgget			303 +#define TARGET_NR_msgctl			304 +#define TARGET_NR_shmat			305 +#define TARGET_NR_shmdt			306 +#define TARGET_NR_shmget			307 +#define TARGET_NR_shmctl			308 +#define TARGET_NR_add_key			309 +#define TARGET_NR_request_key		310 +#define TARGET_NR_keyctl			311 +#define TARGET_NR_semtimedop			312 +#define TARGET_NR_vserver			313 +#define TARGET_NR_ioprio_set			314 +#define TARGET_NR_ioprio_get			315 +#define TARGET_NR_inotify_init		316 +#define TARGET_NR_inotify_add_watch		317 +#define TARGET_NR_inotify_rm_watch		318 +#define TARGET_NR_mbind			319 +#define TARGET_NR_get_mempolicy		320 +#define TARGET_NR_set_mempolicy		321 +#define TARGET_NR_openat			(322) +#define TARGET_NR_mkdirat			(323) +#define TARGET_NR_mknodat			(324) +#define TARGET_NR_fchownat			(325) +#define TARGET_NR_futimesat			(326) +#define TARGET_NR_fstatat64			(327) +#define TARGET_NR_unlinkat			(328) +#define TARGET_NR_renameat			(329) +#define TARGET_NR_linkat			(330) +#define TARGET_NR_symlinkat			(331) +#define TARGET_NR_readlinkat			(332) +#define TARGET_NR_fchmodat			(333) +#define TARGET_NR_faccessat			(334) +#define TARGET_NR_pselect6			(335) +#define TARGET_NR_ppoll                         (336) +#define TARGET_NR_unshare			(337) +#define TARGET_NR_set_robust_list		(338) +#define TARGET_NR_get_robust_list		(339) +#define TARGET_NR_splice			(340) +#define TARGET_NR_arm_sync_file_range	(341) +#define TARGET_NR_sync_file_range2		TARGET_NR_arm_sync_file_range +#define TARGET_NR_tee			(342) +#define TARGET_NR_vmsplice			(343) +#define TARGET_NR_move_pages			(344) +#define TARGET_NR_getcpu			(345) +#define TARGET_NR_epoll_pwait                   (346) +#define TARGET_NR_kexec_load			(347) +#define TARGET_NR_utimensat			(348) +#define TARGET_NR_signalfd			(349) +#define TARGET_NR_timerfd_create		(350) +#define TARGET_NR_eventfd			(351) +#define TARGET_NR_fallocate			(352) +#define TARGET_NR_timerfd_settime		(353) +#define TARGET_NR_timerfd_gettime		(354) +#define TARGET_NR_signalfd4			(355) +#define TARGET_NR_eventfd2			(356) +#define TARGET_NR_epoll_create1		(357) +#define TARGET_NR_dup3				(358) +#define TARGET_NR_pipe2			(359) +#define TARGET_NR_inotify_init1		(360) +#define TARGET_NR_preadv                       (361) +#define TARGET_NR_pwritev                      (362) +#define TARGET_NR_rt_tgsigqueueinfo            (363) +#define TARGET_NR_perf_event_open              (364) +#define TARGET_NR_recvmmsg                     (365) +#define TARGET_NR_accept4                      (366) +#define TARGET_NR_fanotify_init                (367) +#define TARGET_NR_fanotify_mark                (368) +#define TARGET_NR_prlimit64                    (369) +#define TARGET_NR_name_to_handle_at            (370) +#define TARGET_NR_open_by_handle_at            (371) +#define TARGET_NR_clock_adjtime                (372) +#define TARGET_NR_syncfs                       (373) +#define TARGET_NR_sendmmsg                     (374) +#define TARGET_NR_setns                        (375) +#define TARGET_NR_process_vm_readv             (376) +#define TARGET_NR_process_vm_writev            (377) +#define TARGET_NR_kcmp                         (378) +#define TARGET_NR_finit_module                 (379) diff --git a/linux-user/arm/target_cpu.h b/linux-user/arm/target_cpu.h new file mode 100644 index 00000000..6832262e --- /dev/null +++ b/linux-user/arm/target_cpu.h @@ -0,0 +1,48 @@ +/* + * ARM specific CPU ABI and functions for linux-user + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUARMState *env, target_ulong newsp) +{ +    if (newsp) { +        env->regs[13] = newsp; +    } +    env->regs[0] = 0; +} + +static inline void cpu_set_tls(CPUARMState *env, target_ulong newtls) +{ +    if (access_secure_reg(env)) { +        env->cp15.tpidruro_s = newtls; +    } else { +        env->cp15.tpidrro_el[0] = newtls; +    } +} + +static inline target_ulong cpu_get_tls(CPUARMState *env) +{ +    if (access_secure_reg(env)) { +        return env->cp15.tpidruro_s; +    } else { +        return env->cp15.tpidrro_el[0]; +    } +} + +#endif diff --git a/linux-user/arm/target_signal.h b/linux-user/arm/target_signal.h new file mode 100644 index 00000000..2b328131 --- /dev/null +++ b/linux-user/arm/target_signal.h @@ -0,0 +1,29 @@ +#ifndef TARGET_SIGNAL_H +#define TARGET_SIGNAL_H + +#include "cpu.h" + +/* this struct defines a stack used during syscall handling */ + +typedef struct target_sigaltstack { +	abi_ulong ss_sp; +	abi_long ss_flags; +	abi_ulong ss_size; +} target_stack_t; + + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK	1 +#define TARGET_SS_DISABLE	2 + +#define TARGET_MINSIGSTKSZ	2048 +#define TARGET_SIGSTKSZ		8192 + +static inline abi_ulong get_sp_from_cpustate(CPUARMState *state) +{ +   return state->regs[13]; +} + +#endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/arm/target_structs.h b/linux-user/arm/target_structs.h new file mode 100644 index 00000000..f3c85d4e --- /dev/null +++ b/linux-user/arm/target_structs.h @@ -0,0 +1,52 @@ +/* + * ARM specific structures for linux-user + * + * Copyright (c) 2013 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_STRUCTS_H +#define TARGET_STRUCTS_H + +struct target_ipc_perm { +    abi_int __key;                      /* Key.  */ +    abi_uint uid;                       /* Owner's user ID.  */ +    abi_uint gid;                       /* Owner's group ID.  */ +    abi_uint cuid;                      /* Creator's user ID.  */ +    abi_uint cgid;                      /* Creator's group ID.  */ +    abi_ushort mode;                    /* Read/write permission.  */ +    abi_ushort __pad1; +    abi_ushort __seq;                   /* Sequence number.  */ +    abi_ushort __pad2; +    abi_ulong __unused1; +    abi_ulong __unused2; +}; + +struct target_shmid_ds { +    struct target_ipc_perm shm_perm;    /* operation permission struct */ +    abi_long shm_segsz;                 /* size of segment in bytes */ +    abi_ulong shm_atime;                /* time of last shmat() */ +    abi_ulong __unused1; +    abi_ulong shm_dtime;                /* time of last shmdt() */ +    abi_ulong __unused2; +    abi_ulong shm_ctime;                /* time of last change by shmctl() */ +    abi_ulong __unused3; +    abi_int shm_cpid;                   /* pid of creator */ +    abi_int shm_lpid;                   /* pid of last shmop */ +    abi_ulong shm_nattch;               /* number of current attaches */ +    abi_ulong __unused4; +    abi_ulong __unused5; +}; + +#endif diff --git a/linux-user/arm/termbits.h b/linux-user/arm/termbits.h new file mode 100644 index 00000000..7772df17 --- /dev/null +++ b/linux-user/arm/termbits.h @@ -0,0 +1,216 @@ +/* from asm/termbits.h */ +/* NOTE: exactly the same as i386 */ + +#define TARGET_NCCS 19 + +struct target_termios { +    unsigned int c_iflag;               /* input mode flags */ +    unsigned int c_oflag;               /* output mode flags */ +    unsigned int c_cflag;               /* control mode flags */ +    unsigned int c_lflag;               /* local mode flags */ +    unsigned char c_line;                    /* line discipline */ +    unsigned char c_cc[TARGET_NCCS];                /* control characters */ +}; + +/* c_iflag bits */ +#define TARGET_IGNBRK  0000001 +#define TARGET_BRKINT  0000002 +#define TARGET_IGNPAR  0000004 +#define TARGET_PARMRK  0000010 +#define TARGET_INPCK   0000020 +#define TARGET_ISTRIP  0000040 +#define TARGET_INLCR   0000100 +#define TARGET_IGNCR   0000200 +#define TARGET_ICRNL   0000400 +#define TARGET_IUCLC   0001000 +#define TARGET_IXON    0002000 +#define TARGET_IXANY   0004000 +#define TARGET_IXOFF   0010000 +#define TARGET_IMAXBEL 0020000 +#define TARGET_IUTF8   0040000 + +/* c_oflag bits */ +#define TARGET_OPOST   0000001 +#define TARGET_OLCUC   0000002 +#define TARGET_ONLCR   0000004 +#define TARGET_OCRNL   0000010 +#define TARGET_ONOCR   0000020 +#define TARGET_ONLRET  0000040 +#define TARGET_OFILL   0000100 +#define TARGET_OFDEL   0000200 +#define TARGET_NLDLY   0000400 +#define   TARGET_NL0   0000000 +#define   TARGET_NL1   0000400 +#define TARGET_CRDLY   0003000 +#define   TARGET_CR0   0000000 +#define   TARGET_CR1   0001000 +#define   TARGET_CR2   0002000 +#define   TARGET_CR3   0003000 +#define TARGET_TABDLY  0014000 +#define   TARGET_TAB0  0000000 +#define   TARGET_TAB1  0004000 +#define   TARGET_TAB2  0010000 +#define   TARGET_TAB3  0014000 +#define   TARGET_XTABS 0014000 +#define TARGET_BSDLY   0020000 +#define   TARGET_BS0   0000000 +#define   TARGET_BS1   0020000 +#define TARGET_VTDLY   0040000 +#define   TARGET_VT0   0000000 +#define   TARGET_VT1   0040000 +#define TARGET_FFDLY   0100000 +#define   TARGET_FF0   0000000 +#define   TARGET_FF1   0100000 + +/* c_cflag bit meaning */ +#define TARGET_CBAUD   0010017 +#define  TARGET_B0     0000000         /* hang up */ +#define  TARGET_B50    0000001 +#define  TARGET_B75    0000002 +#define  TARGET_B110   0000003 +#define  TARGET_B134   0000004 +#define  TARGET_B150   0000005 +#define  TARGET_B200   0000006 +#define  TARGET_B300   0000007 +#define  TARGET_B600   0000010 +#define  TARGET_B1200  0000011 +#define  TARGET_B1800  0000012 +#define  TARGET_B2400  0000013 +#define  TARGET_B4800  0000014 +#define  TARGET_B9600  0000015 +#define  TARGET_B19200 0000016 +#define  TARGET_B38400 0000017 +#define TARGET_EXTA B19200 +#define TARGET_EXTB B38400 +#define TARGET_CSIZE   0000060 +#define   TARGET_CS5   0000000 +#define   TARGET_CS6   0000020 +#define   TARGET_CS7   0000040 +#define   TARGET_CS8   0000060 +#define TARGET_CSTOPB  0000100 +#define TARGET_CREAD   0000200 +#define TARGET_PARENB  0000400 +#define TARGET_PARODD  0001000 +#define TARGET_HUPCL   0002000 +#define TARGET_CLOCAL  0004000 +#define TARGET_CBAUDEX 0010000 +#define  TARGET_B57600  0010001 +#define  TARGET_B115200 0010002 +#define  TARGET_B230400 0010003 +#define  TARGET_B460800 0010004 +#define TARGET_CIBAUD    002003600000  /* input baud rate (not used) */ +#define TARGET_CMSPAR    010000000000  /* mark or space (stick) parity */ +#define TARGET_CRTSCTS   020000000000  /* flow control */ + +/* c_lflag bits */ +#define TARGET_ISIG    0000001 +#define TARGET_ICANON  0000002 +#define TARGET_XCASE   0000004 +#define TARGET_ECHO    0000010 +#define TARGET_ECHOE   0000020 +#define TARGET_ECHOK   0000040 +#define TARGET_ECHONL  0000100 +#define TARGET_NOFLSH  0000200 +#define TARGET_TOSTOP  0000400 +#define TARGET_ECHOCTL 0001000 +#define TARGET_ECHOPRT 0002000 +#define TARGET_ECHOKE  0004000 +#define TARGET_FLUSHO  0010000 +#define TARGET_PENDIN  0040000 +#define TARGET_IEXTEN  0100000 + +/* c_cc character offsets */ +#define TARGET_VINTR	0 +#define TARGET_VQUIT	1 +#define TARGET_VERASE	2 +#define TARGET_VKILL	3 +#define TARGET_VEOF	4 +#define TARGET_VTIME	5 +#define TARGET_VMIN	6 +#define TARGET_VSWTC	7 +#define TARGET_VSTART	8 +#define TARGET_VSTOP	9 +#define TARGET_VSUSP	10 +#define TARGET_VEOL	11 +#define TARGET_VREPRINT	12 +#define TARGET_VDISCARD	13 +#define TARGET_VWERASE	14 +#define TARGET_VLNEXT	15 +#define TARGET_VEOL2	16 + +/* ioctls */ + +#define TARGET_TCGETS		0x5401 +#define TARGET_TCSETS		0x5402 +#define TARGET_TCSETSW		0x5403 +#define TARGET_TCSETSF		0x5404 +#define TARGET_TCGETA		0x5405 +#define TARGET_TCSETA		0x5406 +#define TARGET_TCSETAW		0x5407 +#define TARGET_TCSETAF		0x5408 +#define TARGET_TCSBRK		0x5409 +#define TARGET_TCXONC		0x540A +#define TARGET_TCFLSH		0x540B + +#define TARGET_TIOCEXCL	0x540C +#define TARGET_TIOCNXCL	0x540D +#define TARGET_TIOCSCTTY	0x540E +#define TARGET_TIOCGPGRP	0x540F +#define TARGET_TIOCSPGRP	0x5410 +#define TARGET_TIOCOUTQ	0x5411 +#define TARGET_TIOCSTI		0x5412 +#define TARGET_TIOCGWINSZ	0x5413 +#define TARGET_TIOCSWINSZ	0x5414 +#define TARGET_TIOCMGET	0x5415 +#define TARGET_TIOCMBIS	0x5416 +#define TARGET_TIOCMBIC	0x5417 +#define TARGET_TIOCMSET	0x5418 +#define TARGET_TIOCGSOFTCAR	0x5419 +#define TARGET_TIOCSSOFTCAR	0x541A +#define TARGET_FIONREAD	0x541B +#define TARGET_TIOCINQ		TARGET_FIONREAD +#define TARGET_TIOCLINUX	0x541C +#define TARGET_TIOCCONS	0x541D +#define TARGET_TIOCGSERIAL	0x541E +#define TARGET_TIOCSSERIAL	0x541F +#define TARGET_TIOCPKT		0x5420 +#define TARGET_FIONBIO		0x5421 +#define TARGET_TIOCNOTTY	0x5422 +#define TARGET_TIOCSETD	0x5423 +#define TARGET_TIOCGETD	0x5424 +#define TARGET_TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */ +#define TARGET_TIOCTTYGSTRUCT	0x5426  /* For debugging only */ +#define TARGET_TIOCSBRK	0x5427  /* BSD compatibility */ +#define TARGET_TIOCCBRK	0x5428  /* BSD compatibility */ +#define TARGET_TIOCGSID	0x5429  /* Return the session ID of FD */ +#define TARGET_TIOCGPTN	TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define TARGET_TIOCSPTLCK	TARGET_IOW('T',0x31, int)  /* Lock/unlock Pty */ + +#define TARGET_FIONCLEX	0x5450  /* these numbers need to be adjusted. */ +#define TARGET_FIOCLEX		0x5451 +#define TARGET_FIOASYNC	0x5452 +#define TARGET_TIOCSERCONFIG	0x5453 +#define TARGET_TIOCSERGWILD	0x5454 +#define TARGET_TIOCSERSWILD	0x5455 +#define TARGET_TIOCGLCKTRMIOS	0x5456 +#define TARGET_TIOCSLCKTRMIOS	0x5457 +#define TARGET_TIOCSERGSTRUCT	0x5458 /* For debugging only */ +#define TARGET_TIOCSERGETLSR   0x5459 /* Get line status register */ +#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config  */ +#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TARGET_TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */ +#define TARGET_TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */ +#define TARGET_TIOCGHAYESESP   0x545E  /* Get Hayes ESP configuration */ +#define TARGET_TIOCSHAYESESP   0x545F  /* Set Hayes ESP configuration */ + +/* Used for packet mode */ +#define TARGET_TIOCPKT_DATA		 0 +#define TARGET_TIOCPKT_FLUSHREAD	 1 +#define TARGET_TIOCPKT_FLUSHWRITE	 2 +#define TARGET_TIOCPKT_STOP		 4 +#define TARGET_TIOCPKT_START		 8 +#define TARGET_TIOCPKT_NOSTOP		16 +#define TARGET_TIOCPKT_DOSTOP		32 + +#define TARGET_TIOCSER_TEMT    0x01	/* Transmitter physically empty */ diff --git a/linux-user/cris/syscall.h b/linux-user/cris/syscall.h new file mode 100644 index 00000000..2957b0d6 --- /dev/null +++ b/linux-user/cris/syscall.h @@ -0,0 +1,46 @@ +#ifndef CRIS_SYSCALL_H +#define CRIS_SYSCALL_H 1 + +#define UNAME_MACHINE "cris" +#define UNAME_MINIMUM_RELEASE "2.6.32" + +/* pt_regs not only specifices the format in the user-struct during + * ptrace but is also the frame format used in the kernel prologue/epilogues + * themselves + */ + +struct target_pt_regs { +        unsigned long orig_r10; +        /* pushed by movem r13, [sp] in SAVE_ALL. */ +        unsigned long r0; +        unsigned long r1; +        unsigned long r2; +        unsigned long r3; +        unsigned long r4; +        unsigned long r5; +        unsigned long r6; +        unsigned long r7; +        unsigned long r8; +        unsigned long r9; +        unsigned long r10; +        unsigned long r11; +        unsigned long r12; +        unsigned long r13; +        unsigned long acr; +        unsigned long srs; +        unsigned long mof; +        unsigned long spc; +        unsigned long ccs; +        unsigned long srp; +        unsigned long erp; /* This is actually the debugged process' PC */ +        /* For debugging purposes; saved only when needed. */ +        unsigned long exs; +        unsigned long eda; +}; + +#define TARGET_CLONE_BACKWARDS2 +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_MLOCKALL_MCL_CURRENT 1 +#define TARGET_MLOCKALL_MCL_FUTURE  2 + +#endif diff --git a/linux-user/cris/syscall_nr.h b/linux-user/cris/syscall_nr.h new file mode 100644 index 00000000..694bd02f --- /dev/null +++ b/linux-user/cris/syscall_nr.h @@ -0,0 +1,338 @@ +/* + * This file contains the system call numbers, and stub macros for libc. + */ + +#define TARGET_NR_restart_syscall      0 +#define TARGET_NR_exit		  1 +#define TARGET_NR_fork		  2 +#define TARGET_NR_read		  3 +#define TARGET_NR_write		  4 +#define TARGET_NR_open		  5 +#define TARGET_NR_close		  6 +#define TARGET_NR_waitpid		  7 +#define TARGET_NR_creat		  8 +#define TARGET_NR_link		  9 +#define TARGET_NR_unlink		 10 +#define TARGET_NR_execve		 11 +#define TARGET_NR_chdir		 12 +#define TARGET_NR_time		 13 +#define TARGET_NR_mknod		 14 +#define TARGET_NR_chmod		 15 +#define TARGET_NR_lchown		 16 +#define TARGET_NR_break		 17 +#define TARGET_NR_oldstat		 18 +#define TARGET_NR_lseek		 19 +#define TARGET_NR_getpid		 20 +#define TARGET_NR_mount		 21 +#define TARGET_NR_umount		 22 +#define TARGET_NR_setuid		 23 +#define TARGET_NR_getuid		 24 +#define TARGET_NR_stime		 25 +#define TARGET_NR_ptrace		 26 +#define TARGET_NR_alarm		 27 +#define TARGET_NR_oldfstat		 28 +#define TARGET_NR_pause		 29 +#define TARGET_NR_utime		 30 +#define TARGET_NR_stty		 31 +#define TARGET_NR_gtty		 32 +#define TARGET_NR_access		 33 +#define TARGET_NR_nice		 34 +#define TARGET_NR_ftime		 35 +#define TARGET_NR_sync		 36 +#define TARGET_NR_kill		 37 +#define TARGET_NR_rename		 38 +#define TARGET_NR_mkdir		 39 +#define TARGET_NR_rmdir		 40 +#define TARGET_NR_dup		 41 +#define TARGET_NR_pipe		 42 +#define TARGET_NR_times		 43 +#define TARGET_NR_prof		 44 +#define TARGET_NR_brk		 45 +#define TARGET_NR_setgid		 46 +#define TARGET_NR_getgid		 47 +#define TARGET_NR_signal		 48 +#define TARGET_NR_geteuid		 49 +#define TARGET_NR_getegid		 50 +#define TARGET_NR_acct		 51 +#define TARGET_NR_umount2		 52 +#define TARGET_NR_lock		 53 +#define TARGET_NR_ioctl		 54 +#define TARGET_NR_fcntl		 55 +#define TARGET_NR_mpx		 56 +#define TARGET_NR_setpgid		 57 +#define TARGET_NR_ulimit		 58 +#define TARGET_NR_oldolduname	 59 +#define TARGET_NR_umask		 60 +#define TARGET_NR_chroot		 61 +#define TARGET_NR_ustat		 62 +#define TARGET_NR_dup2		 63 +#define TARGET_NR_getppid		 64 +#define TARGET_NR_getpgrp		 65 +#define TARGET_NR_setsid		 66 +#define TARGET_NR_sigaction		 67 +#define TARGET_NR_sgetmask		 68 +#define TARGET_NR_ssetmask		 69 +#define TARGET_NR_setreuid		 70 +#define TARGET_NR_setregid		 71 +#define TARGET_NR_sigsuspend		 72 +#define TARGET_NR_sigpending		 73 +#define TARGET_NR_sethostname	 74 +#define TARGET_NR_setrlimit		 75 +#define TARGET_NR_getrlimit		 76 +#define TARGET_NR_getrusage		 77 +#define TARGET_NR_gettimeofday	 78 +#define TARGET_NR_settimeofday	 79 +#define TARGET_NR_getgroups		 80 +#define TARGET_NR_setgroups		 81 +#define TARGET_NR_select		 82 +#define TARGET_NR_symlink		 83 +#define TARGET_NR_oldlstat		 84 +#define TARGET_NR_readlink		 85 +#define TARGET_NR_uselib		 86 +#define TARGET_NR_swapon		 87 +#define TARGET_NR_reboot		 88 +#define TARGET_NR_readdir		 89 +#define TARGET_NR_mmap		 90 +#define TARGET_NR_munmap		 91 +#define TARGET_NR_truncate		 92 +#define TARGET_NR_ftruncate		 93 +#define TARGET_NR_fchmod		 94 +#define TARGET_NR_fchown		 95 +#define TARGET_NR_getpriority	 96 +#define TARGET_NR_setpriority	 97 +#define TARGET_NR_profil		 98 +#define TARGET_NR_statfs		 99 +#define TARGET_NR_fstatfs		100 +#define TARGET_NR_ioperm		101 +#define TARGET_NR_socketcall		102 +#define TARGET_NR_syslog		103 +#define TARGET_NR_setitimer		104 +#define TARGET_NR_getitimer		105 +#define TARGET_NR_stat		106 +#define TARGET_NR_lstat		107 +#define TARGET_NR_fstat		108 +#define TARGET_NR_olduname		109 +#define TARGET_NR_iopl		110 +#define TARGET_NR_vhangup		111 +#define TARGET_NR_idle		112 +#define TARGET_NR_vm86		113 +#define TARGET_NR_wait4		114 +#define TARGET_NR_swapoff		115 +#define TARGET_NR_sysinfo		116 +#define TARGET_NR_ipc		117 +#define TARGET_NR_fsync		118 +#define TARGET_NR_sigreturn		119 +#define TARGET_NR_clone		120 +#define TARGET_NR_setdomainname	121 +#define TARGET_NR_uname		122 +#define TARGET_NR_modify_ldt		123 +#define TARGET_NR_adjtimex		124 +#define TARGET_NR_mprotect		125 +#define TARGET_NR_sigprocmask	126 +#define TARGET_NR_create_module	127 +#define TARGET_NR_init_module	128 +#define TARGET_NR_delete_module	129 +#define TARGET_NR_get_kernel_syms	130 +#define TARGET_NR_quotactl		131 +#define TARGET_NR_getpgid		132 +#define TARGET_NR_fchdir		133 +#define TARGET_NR_bdflush		134 +#define TARGET_NR_sysfs		135 +#define TARGET_NR_personality	136 +#define TARGET_NR_afs_syscall	137 /* Syscall for Andrew File System */ +#define TARGET_NR_setfsuid		138 +#define TARGET_NR_setfsgid		139 +#define TARGET_NR__llseek		140 +#define TARGET_NR_getdents		141 +#define TARGET_NR__newselect		142 +#define TARGET_NR_flock		143 +#define TARGET_NR_msync		144 +#define TARGET_NR_readv		145 +#define TARGET_NR_writev		146 +#define TARGET_NR_getsid		147 +#define TARGET_NR_fdatasync		148 +#define TARGET_NR__sysctl		149 +#define TARGET_NR_mlock		150 +#define TARGET_NR_munlock		151 +#define TARGET_NR_mlockall		152 +#define TARGET_NR_munlockall		153 +#define TARGET_NR_sched_setparam		154 +#define TARGET_NR_sched_getparam		155 +#define TARGET_NR_sched_setscheduler		156 +#define TARGET_NR_sched_getscheduler		157 +#define TARGET_NR_sched_yield		158 +#define TARGET_NR_sched_get_priority_max	159 +#define TARGET_NR_sched_get_priority_min	160 +#define TARGET_NR_sched_rr_get_interval	161 +#define TARGET_NR_nanosleep		162 +#define TARGET_NR_mremap		163 +#define TARGET_NR_setresuid		164 +#define TARGET_NR_getresuid		165 + +#define TARGET_NR_query_module	167 +#define TARGET_NR_poll		168 +#define TARGET_NR_nfsservctl		169 +#define TARGET_NR_setresgid		170 +#define TARGET_NR_getresgid		171 +#define TARGET_NR_prctl              172 +#define TARGET_NR_rt_sigreturn	173 +#define TARGET_NR_rt_sigaction	174 +#define TARGET_NR_rt_sigprocmask	175 +#define TARGET_NR_rt_sigpending	176 +#define TARGET_NR_rt_sigtimedwait	177 +#define TARGET_NR_rt_sigqueueinfo	178 +#define TARGET_NR_rt_sigsuspend	179 +#define TARGET_NR_pread64		180 +#define TARGET_NR_pwrite64		181 +#define TARGET_NR_chown		182 +#define TARGET_NR_getcwd		183 +#define TARGET_NR_capget		184 +#define TARGET_NR_capset		185 +#define TARGET_NR_sigaltstack	186 +#define TARGET_NR_sendfile		187 +#define TARGET_NR_getpmsg		188	/* some people actually want streams */ +#define TARGET_NR_putpmsg		189	/* some people actually want streams */ +#define TARGET_NR_vfork		190 +#define TARGET_NR_ugetrlimit		191	/* SuS compliant getrlimit */ +#define TARGET_NR_mmap2		192 +#define TARGET_NR_truncate64		193 +#define TARGET_NR_ftruncate64	194 +#define TARGET_NR_stat64		195 +#define TARGET_NR_lstat64		196 +#define TARGET_NR_fstat64		197 +#define TARGET_NR_lchown32		198 +#define TARGET_NR_getuid32		199 +#define TARGET_NR_getgid32		200 +#define TARGET_NR_geteuid32		201 +#define TARGET_NR_getegid32		202 +#define TARGET_NR_setreuid32		203 +#define TARGET_NR_setregid32		204 +#define TARGET_NR_getgroups32	205 +#define TARGET_NR_setgroups32	206 +#define TARGET_NR_fchown32		207 +#define TARGET_NR_setresuid32	208 +#define TARGET_NR_getresuid32	209 +#define TARGET_NR_setresgid32	210 +#define TARGET_NR_getresgid32	211 +#define TARGET_NR_chown32		212 +#define TARGET_NR_setuid32		213 +#define TARGET_NR_setgid32		214 +#define TARGET_NR_setfsuid32		215 +#define TARGET_NR_setfsgid32		216 +#define TARGET_NR_pivot_root		217 +#define TARGET_NR_mincore		218 +#define TARGET_NR_madvise		219 +#define TARGET_NR_getdents64		220 +#define TARGET_NR_fcntl64		221 +/* 223 is unused */ +#define TARGET_NR_gettid             224 +#define TARGET_NR_readahead          225 +#define TARGET_NR_setxattr		226 +#define TARGET_NR_lsetxattr		227 +#define TARGET_NR_fsetxattr		228 +#define TARGET_NR_getxattr		229 +#define TARGET_NR_lgetxattr		230 +#define TARGET_NR_fgetxattr		231 +#define TARGET_NR_listxattr		232 +#define TARGET_NR_llistxattr		233 +#define TARGET_NR_flistxattr		234 +#define TARGET_NR_removexattr	235 +#define TARGET_NR_lremovexattr	236 +#define TARGET_NR_fremovexattr	237 +#define TARGET_NR_tkill		238 +#define TARGET_NR_sendfile64		239 +#define TARGET_NR_futex		240 +#define TARGET_NR_sched_setaffinity	241 +#define TARGET_NR_sched_getaffinity	242 +#define TARGET_NR_set_thread_area	243 +#define TARGET_NR_get_thread_area	244 +#define TARGET_NR_io_setup		245 +#define TARGET_NR_io_destroy		246 +#define TARGET_NR_io_getevents	247 +#define TARGET_NR_io_submit		248 +#define TARGET_NR_io_cancel		249 +#define TARGET_NR_fadvise64		250 +#define TARGET_NR_exit_group		252 +#define TARGET_NR_lookup_dcookie	253 +#define TARGET_NR_epoll_create	254 +#define TARGET_NR_epoll_ctl		255 +#define TARGET_NR_epoll_wait		256 +#define TARGET_NR_remap_file_pages	257 +#define TARGET_NR_set_tid_address	258 +#define TARGET_NR_timer_create	259 +#define TARGET_NR_timer_settime	(TARGET_NR_timer_create+1) +#define TARGET_NR_timer_gettime	(TARGET_NR_timer_create+2) +#define TARGET_NR_timer_getoverrun	(TARGET_NR_timer_create+3) +#define TARGET_NR_timer_delete	(TARGET_NR_timer_create+4) +#define TARGET_NR_clock_settime	(TARGET_NR_timer_create+5) +#define TARGET_NR_clock_gettime	(TARGET_NR_timer_create+6) +#define TARGET_NR_clock_getres	(TARGET_NR_timer_create+7) +#define TARGET_NR_clock_nanosleep	(TARGET_NR_timer_create+8) +#define TARGET_NR_statfs64		268 +#define TARGET_NR_fstatfs64		269 +#define TARGET_NR_tgkill		270 +#define TARGET_NR_utimes		271 +#define TARGET_NR_fadvise64_64	272 +#define TARGET_NR_vserver		273 +#define TARGET_NR_mbind		274 +#define TARGET_NR_get_mempolicy	275 +#define TARGET_NR_set_mempolicy	276 +#define TARGET_NR_mq_open 		277 +#define TARGET_NR_mq_unlink		(TARGET_NR_mq_open+1) +#define TARGET_NR_mq_timedsend	(TARGET_NR_mq_open+2) +#define TARGET_NR_mq_timedreceive	(TARGET_NR_mq_open+3) +#define TARGET_NR_mq_notify		(TARGET_NR_mq_open+4) +#define TARGET_NR_mq_getsetattr	(TARGET_NR_mq_open+5) +#define TARGET_NR_kexec_load		283 +#define TARGET_NR_waitid		284 +/* #define TARGET_NR_sys_setaltroot	285 */ +#define TARGET_NR_add_key		286 +#define TARGET_NR_request_key	287 +#define TARGET_NR_keyctl		288 +#define TARGET_NR_ioprio_set         289 +#define TARGET_NR_ioprio_get         290 +#define TARGET_NR_inotify_init       291 +#define TARGET_NR_inotify_add_watch  292 +#define TARGET_NR_inotify_rm_watch   293 +#define TARGET_NR_migrate_pages      294 +#define TARGET_NR_openat             295 +#define TARGET_NR_mkdirat            296 +#define TARGET_NR_mknodat            297 +#define TARGET_NR_fchownat           298 +#define TARGET_NR_futimesat          299 +#define TARGET_NR_fstatat64          300 +#define TARGET_NR_unlinkat           301 +#define TARGET_NR_renameat           302 +#define TARGET_NR_linkat             303 +#define TARGET_NR_symlinkat          304 +#define TARGET_NR_readlinkat         305 +#define TARGET_NR_fchmodat           306 +#define TARGET_NR_faccessat          307 +#define TARGET_NR_pselect6           308 +#define TARGET_NR_ppoll              309 +#define TARGET_NR_unshare            310 +#define TARGET_NR_set_robust_list    311 +#define TARGET_NR_get_robust_list    312 +#define TARGET_NR_splice             313 +#define TARGET_NR_sync_file_range    314 +#define TARGET_NR_tee                315 +#define TARGET_NR_vmsplice           316 +#define TARGET_NR_move_pages         317 +#define TARGET_NR_getcpu             318 +#define TARGET_NR_epoll_pwait        319 +#define TARGET_NR_utimensat          320 +#define TARGET_NR_signalfd           321 +#define TARGET_NR_timerfd_create     322 +#define TARGET_NR_eventfd            323 +#define TARGET_NR_fallocate          324 +#define TARGET_NR_timerfd_settime    325 +#define TARGET_NR_timerfd_gettime    326 +#define TARGET_NR_signalfd4          327 +#define TARGET_NR_eventfd2           328 +#define TARGET_NR_epoll_create1      329 +#define TARGET_NR_dup3               330 +#define TARGET_NR_pipe2              331 +#define TARGET_NR_inotify_init1      332 +#define TARGET_NR_preadv             333 +#define TARGET_NR_pwritev            334 +#define TARGET_NR_setns              335 diff --git a/linux-user/cris/target_cpu.h b/linux-user/cris/target_cpu.h new file mode 100644 index 00000000..4d787e5f --- /dev/null +++ b/linux-user/cris/target_cpu.h @@ -0,0 +1,36 @@ +/* + * CRIS specific CPU ABI and functions for linux-user + * + * Copyright (c) 2007 AXIS Communications AB + * Written by Edgar E. Iglesias + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUCRISState *env, target_ulong newsp) +{ +    if (newsp) { +        env->regs[14] = newsp; +    } +    env->regs[10] = 0; +} + +static inline void cpu_set_tls(CPUCRISState *env, target_ulong newtls) +{ +    env->pregs[PR_PID] = (env->pregs[PR_PID] & 0xff) | newtls; +} + +#endif diff --git a/linux-user/cris/target_signal.h b/linux-user/cris/target_signal.h new file mode 100644 index 00000000..5611840f --- /dev/null +++ b/linux-user/cris/target_signal.h @@ -0,0 +1,29 @@ +#ifndef TARGET_SIGNAL_H +#define TARGET_SIGNAL_H + +#include "cpu.h" + +/* this struct defines a stack used during syscall handling */ + +typedef struct target_sigaltstack { +	abi_ulong ss_sp; +	abi_ulong ss_size; +	abi_long ss_flags; +} target_stack_t; + + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK     1 +#define TARGET_SS_DISABLE     2 + +#define TARGET_MINSIGSTKSZ    2048 +#define TARGET_SIGSTKSZ       8192 + +static inline abi_ulong get_sp_from_cpustate(CPUCRISState *state) +{ +    return state->regs[14]; +} + +#endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/cris/target_structs.h b/linux-user/cris/target_structs.h new file mode 100644 index 00000000..e4a1ffb3 --- /dev/null +++ b/linux-user/cris/target_structs.h @@ -0,0 +1,58 @@ +/* + * CRIS specific structures for linux-user + * + * Copyright (c) 2013 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_STRUCTS_H +#define TARGET_STRUCTS_H + +struct target_ipc_perm { +    abi_int __key;                      /* Key.  */ +    abi_uint uid;                       /* Owner's user ID.  */ +    abi_uint gid;                       /* Owner's group ID.  */ +    abi_uint cuid;                      /* Creator's user ID.  */ +    abi_uint cgid;                      /* Creator's group ID.  */ +    abi_ushort mode;                    /* Read/write permission.  */ +    abi_ushort __pad1; +    abi_ushort __seq;                   /* Sequence number.  */ +    abi_ushort __pad2; +    abi_ulong __unused1; +    abi_ulong __unused2; +}; + +struct target_shmid_ds { +    struct target_ipc_perm shm_perm;    /* operation permission struct */ +    abi_long shm_segsz;                 /* size of segment in bytes */ +    abi_ulong shm_atime;                /* time of last shmat() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused1; +#endif +    abi_ulong shm_dtime;                /* time of last shmdt() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused2; +#endif +    abi_ulong shm_ctime;                /* time of last change by shmctl() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused3; +#endif +    abi_int shm_cpid;                   /* pid of creator */ +    abi_int shm_lpid;                   /* pid of last shmop */ +    abi_ulong shm_nattch;               /* number of current attaches */ +    abi_ulong __unused4; +    abi_ulong __unused5; +}; + +#endif diff --git a/linux-user/cris/termbits.h b/linux-user/cris/termbits.h new file mode 100644 index 00000000..fc82ca08 --- /dev/null +++ b/linux-user/cris/termbits.h @@ -0,0 +1,213 @@ +/* from asm/termbits.h */ + +#define TARGET_NCCS 19 + +struct target_termios { +    unsigned int c_iflag;               /* input mode flags */ +    unsigned int c_oflag;               /* output mode flags */ +    unsigned int c_cflag;               /* control mode flags */ +    unsigned int c_lflag;               /* local mode flags */ +    unsigned char c_line;                    /* line discipline */ +    unsigned char c_cc[TARGET_NCCS];                /* control characters */ +}; + +/* c_iflag bits */ +#define TARGET_IGNBRK  0000001 +#define TARGET_BRKINT  0000002 +#define TARGET_IGNPAR  0000004 +#define TARGET_PARMRK  0000010 +#define TARGET_INPCK   0000020 +#define TARGET_ISTRIP  0000040 +#define TARGET_INLCR   0000100 +#define TARGET_IGNCR   0000200 +#define TARGET_ICRNL   0000400 +#define TARGET_IUCLC   0001000 +#define TARGET_IXON    0002000 +#define TARGET_IXANY   0004000 +#define TARGET_IXOFF   0010000 +#define TARGET_IMAXBEL 0020000 + +/* c_oflag bits */ +#define TARGET_OPOST   0000001 +#define TARGET_OLCUC   0000002 +#define TARGET_ONLCR   0000004 +#define TARGET_OCRNL   0000010 +#define TARGET_ONOCR   0000020 +#define TARGET_ONLRET  0000040 +#define TARGET_OFILL   0000100 +#define TARGET_OFDEL   0000200 +#define TARGET_NLDLY   0000400 +#define   TARGET_NL0   0000000 +#define   TARGET_NL1   0000400 +#define TARGET_CRDLY   0003000 +#define   TARGET_CR0   0000000 +#define   TARGET_CR1   0001000 +#define   TARGET_CR2   0002000 +#define   TARGET_CR3   0003000 +#define TARGET_TABDLY  0014000 +#define   TARGET_TAB0  0000000 +#define   TARGET_TAB1  0004000 +#define   TARGET_TAB2  0010000 +#define   TARGET_TAB3  0014000 +#define   TARGET_XTABS 0014000 +#define TARGET_BSDLY   0020000 +#define   TARGET_BS0   0000000 +#define   TARGET_BS1   0020000 +#define TARGET_VTDLY   0040000 +#define   TARGET_VT0   0000000 +#define   TARGET_VT1   0040000 +#define TARGET_FFDLY   0100000 +#define   TARGET_FF0   0000000 +#define   TARGET_FF1   0100000 + +/* c_cflag bit meaning */ +#define TARGET_CBAUD   0010017 +#define  TARGET_B0     0000000         /* hang up */ +#define  TARGET_B50    0000001 +#define  TARGET_B75    0000002 +#define  TARGET_B110   0000003 +#define  TARGET_B134   0000004 +#define  TARGET_B150   0000005 +#define  TARGET_B200   0000006 +#define  TARGET_B300   0000007 +#define  TARGET_B600   0000010 +#define  TARGET_B1200  0000011 +#define  TARGET_B1800  0000012 +#define  TARGET_B2400  0000013 +#define  TARGET_B4800  0000014 +#define  TARGET_B9600  0000015 +#define  TARGET_B19200 0000016 +#define  TARGET_B38400 0000017 +#define TARGET_EXTA B19200 +#define TARGET_EXTB B38400 +#define TARGET_CSIZE   0000060 +#define   TARGET_CS5   0000000 +#define   TARGET_CS6   0000020 +#define   TARGET_CS7   0000040 +#define   TARGET_CS8   0000060 +#define TARGET_CSTOPB  0000100 +#define TARGET_CREAD   0000200 +#define TARGET_PARENB  0000400 +#define TARGET_PARODD  0001000 +#define TARGET_HUPCL   0002000 +#define TARGET_CLOCAL  0004000 +#define TARGET_CBAUDEX 0010000 +#define  TARGET_B57600  0010001 +#define  TARGET_B115200 0010002 +#define  TARGET_B230400 0010003 +#define  TARGET_B460800 0010004 +#define TARGET_CIBAUD    002003600000  /* input baud rate (not used) */ +#define TARGET_CRTSCTS   020000000000          /* flow control */ + +/* c_lflag bits */ +#define TARGET_ISIG    0000001 +#define TARGET_ICANON  0000002 +#define TARGET_XCASE   0000004 +#define TARGET_ECHO    0000010 +#define TARGET_ECHOE   0000020 +#define TARGET_ECHOK   0000040 +#define TARGET_ECHONL  0000100 +#define TARGET_NOFLSH  0000200 +#define TARGET_TOSTOP  0000400 +#define TARGET_ECHOCTL 0001000 +#define TARGET_ECHOPRT 0002000 +#define TARGET_ECHOKE  0004000 +#define TARGET_FLUSHO  0010000 +#define TARGET_PENDIN  0040000 +#define TARGET_IEXTEN  0100000 + +/* c_cc character offsets */ +#define TARGET_VINTR	0 +#define TARGET_VQUIT	1 +#define TARGET_VERASE	2 +#define TARGET_VKILL	3 +#define TARGET_VEOF	4 +#define TARGET_VTIME	5 +#define TARGET_VMIN	6 +#define TARGET_VSWTC	7 +#define TARGET_VSTART	8 +#define TARGET_VSTOP	9 +#define TARGET_VSUSP	10 +#define TARGET_VEOL	11 +#define TARGET_VREPRINT	12 +#define TARGET_VDISCARD	13 +#define TARGET_VWERASE	14 +#define TARGET_VLNEXT	15 +#define TARGET_VEOL2	16 + +/* ioctls */ + +#define TARGET_TCGETS		0x5401 +#define TARGET_TCSETS		0x5402 +#define TARGET_TCSETSW		0x5403 +#define TARGET_TCSETSF		0x5404 +#define TARGET_TCGETA		0x5405 +#define TARGET_TCSETA		0x5406 +#define TARGET_TCSETAW		0x5407 +#define TARGET_TCSETAF		0x5408 +#define TARGET_TCSBRK		0x5409 +#define TARGET_TCXONC		0x540A +#define TARGET_TCFLSH		0x540B + +#define TARGET_TIOCEXCL	0x540C +#define TARGET_TIOCNXCL	0x540D +#define TARGET_TIOCSCTTY	0x540E +#define TARGET_TIOCGPGRP	0x540F +#define TARGET_TIOCSPGRP	0x5410 +#define TARGET_TIOCOUTQ	0x5411 +#define TARGET_TIOCSTI		0x5412 +#define TARGET_TIOCGWINSZ	0x5413 +#define TARGET_TIOCSWINSZ	0x5414 +#define TARGET_TIOCMGET	0x5415 +#define TARGET_TIOCMBIS	0x5416 +#define TARGET_TIOCMBIC	0x5417 +#define TARGET_TIOCMSET	0x5418 +#define TARGET_TIOCGSOFTCAR	0x5419 +#define TARGET_TIOCSSOFTCAR	0x541A +#define TARGET_FIONREAD	0x541B +#define TARGET_TIOCINQ		TARGET_FIONREAD +#define TARGET_TIOCLINUX	0x541C +#define TARGET_TIOCCONS	0x541D +#define TARGET_TIOCGSERIAL	0x541E +#define TARGET_TIOCSSERIAL	0x541F +#define TARGET_TIOCPKT		0x5420 +#define TARGET_FIONBIO		0x5421 +#define TARGET_TIOCNOTTY	0x5422 +#define TARGET_TIOCSETD	0x5423 +#define TARGET_TIOCGETD	0x5424 +#define TARGET_TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */ +#define TARGET_TIOCTTYGSTRUCT	0x5426  /* For debugging only */ +#define TARGET_TIOCSBRK	0x5427  /* BSD compatibility */ +#define TARGET_TIOCCBRK	0x5428  /* BSD compatibility */ +#define TARGET_TIOCGSID	0x5429  /* Return the session ID of FD */ +#define TARGET_TIOCGPTN	TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define TARGET_TIOCSPTLCK	TARGET_IOW('T',0x31, int)  /* Lock/unlock Pty */ + +#define TARGET_FIONCLEX	0x5450  /* these numbers need to be adjusted. */ +#define TARGET_FIOCLEX		0x5451 +#define TARGET_FIOASYNC	0x5452 +#define TARGET_TIOCSERCONFIG	0x5453 +#define TARGET_TIOCSERGWILD	0x5454 +#define TARGET_TIOCSERSWILD	0x5455 +#define TARGET_TIOCGLCKTRMIOS	0x5456 +#define TARGET_TIOCSLCKTRMIOS	0x5457 +#define TARGET_TIOCSERGSTRUCT	0x5458 /* For debugging only */ +#define TARGET_TIOCSERGETLSR   0x5459 /* Get line status register */ +#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config  */ +#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TARGET_TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */ +#define TARGET_TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */ +#define TARGET_TIOCGHAYESESP   0x545E  /* Get Hayes ESP configuration */ +#define TARGET_TIOCSHAYESESP   0x545F  /* Set Hayes ESP configuration */ + +/* Used for packet mode */ +#define TARGET_TIOCPKT_DATA		 0 +#define TARGET_TIOCPKT_FLUSHREAD	 1 +#define TARGET_TIOCPKT_FLUSHWRITE	 2 +#define TARGET_TIOCPKT_STOP		 4 +#define TARGET_TIOCPKT_START		 8 +#define TARGET_TIOCPKT_NOSTOP		16 +#define TARGET_TIOCPKT_DOSTOP		32 + +#define TARGET_TIOCSER_TEMT    0x01	/* Transmitter physically empty */ diff --git a/linux-user/elfload.c b/linux-user/elfload.c new file mode 100644 index 00000000..17883686 --- /dev/null +++ b/linux-user/elfload.c @@ -0,0 +1,3120 @@ +/* This is the Linux kernel elf-loading code, ported into user space */ +#include <sys/time.h> +#include <sys/param.h> + +#include <stdio.h> +#include <sys/types.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/resource.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#include "qemu.h" +#include "disas/disas.h" + +#ifdef _ARCH_PPC64 +#undef ARCH_DLINFO +#undef ELF_PLATFORM +#undef ELF_HWCAP +#undef ELF_HWCAP2 +#undef ELF_CLASS +#undef ELF_DATA +#undef ELF_ARCH +#endif + +#define ELF_OSABI   ELFOSABI_SYSV + +/* from personality.h */ + +/* + * Flags for bug emulation. + * + * These occupy the top three bytes. + */ +enum { +    ADDR_NO_RANDOMIZE = 0x0040000,      /* disable randomization of VA space */ +    FDPIC_FUNCPTRS =    0x0080000,      /* userspace function ptrs point to +                                           descriptors (signal handling) */ +    MMAP_PAGE_ZERO =    0x0100000, +    ADDR_COMPAT_LAYOUT = 0x0200000, +    READ_IMPLIES_EXEC = 0x0400000, +    ADDR_LIMIT_32BIT =  0x0800000, +    SHORT_INODE =       0x1000000, +    WHOLE_SECONDS =     0x2000000, +    STICKY_TIMEOUTS =   0x4000000, +    ADDR_LIMIT_3GB =    0x8000000, +}; + +/* + * Personality types. + * + * These go in the low byte.  Avoid using the top bit, it will + * conflict with error returns. + */ +enum { +    PER_LINUX =         0x0000, +    PER_LINUX_32BIT =   0x0000 | ADDR_LIMIT_32BIT, +    PER_LINUX_FDPIC =   0x0000 | FDPIC_FUNCPTRS, +    PER_SVR4 =          0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO, +    PER_SVR3 =          0x0002 | STICKY_TIMEOUTS | SHORT_INODE, +    PER_SCOSVR3 =       0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS | SHORT_INODE, +    PER_OSR5 =          0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS, +    PER_WYSEV386 =      0x0004 | STICKY_TIMEOUTS | SHORT_INODE, +    PER_ISCR4 =         0x0005 | STICKY_TIMEOUTS, +    PER_BSD =           0x0006, +    PER_SUNOS =         0x0006 | STICKY_TIMEOUTS, +    PER_XENIX =         0x0007 | STICKY_TIMEOUTS | SHORT_INODE, +    PER_LINUX32 =       0x0008, +    PER_LINUX32_3GB =   0x0008 | ADDR_LIMIT_3GB, +    PER_IRIX32 =        0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */ +    PER_IRIXN32 =       0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */ +    PER_IRIX64 =        0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */ +    PER_RISCOS =        0x000c, +    PER_SOLARIS =       0x000d | STICKY_TIMEOUTS, +    PER_UW7 =           0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO, +    PER_OSF4 =          0x000f,                  /* OSF/1 v4 */ +    PER_HPUX =          0x0010, +    PER_MASK =          0x00ff, +}; + +/* + * Return the base personality without flags. + */ +#define personality(pers)       (pers & PER_MASK) + +/* this flag is uneffective under linux too, should be deleted */ +#ifndef MAP_DENYWRITE +#define MAP_DENYWRITE 0 +#endif + +/* should probably go in elf.h */ +#ifndef ELIBBAD +#define ELIBBAD 80 +#endif + +#ifdef TARGET_WORDS_BIGENDIAN +#define ELF_DATA        ELFDATA2MSB +#else +#define ELF_DATA        ELFDATA2LSB +#endif + +#ifdef TARGET_ABI_MIPSN32 +typedef abi_ullong      target_elf_greg_t; +#define tswapreg(ptr)   tswap64(ptr) +#else +typedef abi_ulong       target_elf_greg_t; +#define tswapreg(ptr)   tswapal(ptr) +#endif + +#ifdef USE_UID16 +typedef abi_ushort      target_uid_t; +typedef abi_ushort      target_gid_t; +#else +typedef abi_uint        target_uid_t; +typedef abi_uint        target_gid_t; +#endif +typedef abi_int         target_pid_t; + +#ifdef TARGET_I386 + +#define ELF_PLATFORM get_elf_platform() + +static const char *get_elf_platform(void) +{ +    static char elf_platform[] = "i386"; +    int family = object_property_get_int(OBJECT(thread_cpu), "family", NULL); +    if (family > 6) +        family = 6; +    if (family >= 3) +        elf_platform[1] = '0' + family; +    return elf_platform; +} + +#define ELF_HWCAP get_elf_hwcap() + +static uint32_t get_elf_hwcap(void) +{ +    X86CPU *cpu = X86_CPU(thread_cpu); + +    return cpu->env.features[FEAT_1_EDX]; +} + +#ifdef TARGET_X86_64 +#define ELF_START_MMAP 0x2aaaaab000ULL +#define elf_check_arch(x) ( ((x) == ELF_ARCH) ) + +#define ELF_CLASS      ELFCLASS64 +#define ELF_ARCH       EM_X86_64 + +static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) +{ +    regs->rax = 0; +    regs->rsp = infop->start_stack; +    regs->rip = infop->entry; +} + +#define ELF_NREG    27 +typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG]; + +/* + * Note that ELF_NREG should be 29 as there should be place for + * TRAPNO and ERR "registers" as well but linux doesn't dump + * those. + * + * See linux kernel: arch/x86/include/asm/elf.h + */ +static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env) +{ +    (*regs)[0] = env->regs[15]; +    (*regs)[1] = env->regs[14]; +    (*regs)[2] = env->regs[13]; +    (*regs)[3] = env->regs[12]; +    (*regs)[4] = env->regs[R_EBP]; +    (*regs)[5] = env->regs[R_EBX]; +    (*regs)[6] = env->regs[11]; +    (*regs)[7] = env->regs[10]; +    (*regs)[8] = env->regs[9]; +    (*regs)[9] = env->regs[8]; +    (*regs)[10] = env->regs[R_EAX]; +    (*regs)[11] = env->regs[R_ECX]; +    (*regs)[12] = env->regs[R_EDX]; +    (*regs)[13] = env->regs[R_ESI]; +    (*regs)[14] = env->regs[R_EDI]; +    (*regs)[15] = env->regs[R_EAX]; /* XXX */ +    (*regs)[16] = env->eip; +    (*regs)[17] = env->segs[R_CS].selector & 0xffff; +    (*regs)[18] = env->eflags; +    (*regs)[19] = env->regs[R_ESP]; +    (*regs)[20] = env->segs[R_SS].selector & 0xffff; +    (*regs)[21] = env->segs[R_FS].selector & 0xffff; +    (*regs)[22] = env->segs[R_GS].selector & 0xffff; +    (*regs)[23] = env->segs[R_DS].selector & 0xffff; +    (*regs)[24] = env->segs[R_ES].selector & 0xffff; +    (*regs)[25] = env->segs[R_FS].selector & 0xffff; +    (*regs)[26] = env->segs[R_GS].selector & 0xffff; +} + +#else + +#define ELF_START_MMAP 0x80000000 + +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) ) + +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS       ELFCLASS32 +#define ELF_ARCH        EM_386 + +static inline void init_thread(struct target_pt_regs *regs, +                               struct image_info *infop) +{ +    regs->esp = infop->start_stack; +    regs->eip = infop->entry; + +    /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program +       starts %edx contains a pointer to a function which might be +       registered using `atexit'.  This provides a mean for the +       dynamic linker to call DT_FINI functions for shared libraries +       that have been loaded before the code runs. + +       A value of 0 tells we have no such handler.  */ +    regs->edx = 0; +} + +#define ELF_NREG    17 +typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG]; + +/* + * Note that ELF_NREG should be 19 as there should be place for + * TRAPNO and ERR "registers" as well but linux doesn't dump + * those. + * + * See linux kernel: arch/x86/include/asm/elf.h + */ +static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *env) +{ +    (*regs)[0] = env->regs[R_EBX]; +    (*regs)[1] = env->regs[R_ECX]; +    (*regs)[2] = env->regs[R_EDX]; +    (*regs)[3] = env->regs[R_ESI]; +    (*regs)[4] = env->regs[R_EDI]; +    (*regs)[5] = env->regs[R_EBP]; +    (*regs)[6] = env->regs[R_EAX]; +    (*regs)[7] = env->segs[R_DS].selector & 0xffff; +    (*regs)[8] = env->segs[R_ES].selector & 0xffff; +    (*regs)[9] = env->segs[R_FS].selector & 0xffff; +    (*regs)[10] = env->segs[R_GS].selector & 0xffff; +    (*regs)[11] = env->regs[R_EAX]; /* XXX */ +    (*regs)[12] = env->eip; +    (*regs)[13] = env->segs[R_CS].selector & 0xffff; +    (*regs)[14] = env->eflags; +    (*regs)[15] = env->regs[R_ESP]; +    (*regs)[16] = env->segs[R_SS].selector & 0xffff; +} +#endif + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE       4096 + +#endif + +#ifdef TARGET_ARM + +#ifndef TARGET_AARCH64 +/* 32 bit ARM definitions */ + +#define ELF_START_MMAP 0x80000000 + +#define elf_check_arch(x) ((x) == ELF_MACHINE) + +#define ELF_ARCH        ELF_MACHINE +#define ELF_CLASS       ELFCLASS32 + +static inline void init_thread(struct target_pt_regs *regs, +                               struct image_info *infop) +{ +    abi_long stack = infop->start_stack; +    memset(regs, 0, sizeof(*regs)); + +    regs->ARM_cpsr = 0x10; +    if (infop->entry & 1) +        regs->ARM_cpsr |= CPSR_T; +    regs->ARM_pc = infop->entry & 0xfffffffe; +    regs->ARM_sp = infop->start_stack; +    /* FIXME - what to for failure of get_user()? */ +    get_user_ual(regs->ARM_r2, stack + 8); /* envp */ +    get_user_ual(regs->ARM_r1, stack + 4); /* envp */ +    /* XXX: it seems that r0 is zeroed after ! */ +    regs->ARM_r0 = 0; +    /* For uClinux PIC binaries.  */ +    /* XXX: Linux does this only on ARM with no MMU (do we care ?) */ +    regs->ARM_r10 = infop->start_data; +} + +#define ELF_NREG    18 +typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG]; + +static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUARMState *env) +{ +    (*regs)[0] = tswapreg(env->regs[0]); +    (*regs)[1] = tswapreg(env->regs[1]); +    (*regs)[2] = tswapreg(env->regs[2]); +    (*regs)[3] = tswapreg(env->regs[3]); +    (*regs)[4] = tswapreg(env->regs[4]); +    (*regs)[5] = tswapreg(env->regs[5]); +    (*regs)[6] = tswapreg(env->regs[6]); +    (*regs)[7] = tswapreg(env->regs[7]); +    (*regs)[8] = tswapreg(env->regs[8]); +    (*regs)[9] = tswapreg(env->regs[9]); +    (*regs)[10] = tswapreg(env->regs[10]); +    (*regs)[11] = tswapreg(env->regs[11]); +    (*regs)[12] = tswapreg(env->regs[12]); +    (*regs)[13] = tswapreg(env->regs[13]); +    (*regs)[14] = tswapreg(env->regs[14]); +    (*regs)[15] = tswapreg(env->regs[15]); + +    (*regs)[16] = tswapreg(cpsr_read((CPUARMState *)env)); +    (*regs)[17] = tswapreg(env->regs[0]); /* XXX */ +} + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE       4096 + +enum +{ +    ARM_HWCAP_ARM_SWP       = 1 << 0, +    ARM_HWCAP_ARM_HALF      = 1 << 1, +    ARM_HWCAP_ARM_THUMB     = 1 << 2, +    ARM_HWCAP_ARM_26BIT     = 1 << 3, +    ARM_HWCAP_ARM_FAST_MULT = 1 << 4, +    ARM_HWCAP_ARM_FPA       = 1 << 5, +    ARM_HWCAP_ARM_VFP       = 1 << 6, +    ARM_HWCAP_ARM_EDSP      = 1 << 7, +    ARM_HWCAP_ARM_JAVA      = 1 << 8, +    ARM_HWCAP_ARM_IWMMXT    = 1 << 9, +    ARM_HWCAP_ARM_CRUNCH    = 1 << 10, +    ARM_HWCAP_ARM_THUMBEE   = 1 << 11, +    ARM_HWCAP_ARM_NEON      = 1 << 12, +    ARM_HWCAP_ARM_VFPv3     = 1 << 13, +    ARM_HWCAP_ARM_VFPv3D16  = 1 << 14, +    ARM_HWCAP_ARM_TLS       = 1 << 15, +    ARM_HWCAP_ARM_VFPv4     = 1 << 16, +    ARM_HWCAP_ARM_IDIVA     = 1 << 17, +    ARM_HWCAP_ARM_IDIVT     = 1 << 18, +    ARM_HWCAP_ARM_VFPD32    = 1 << 19, +    ARM_HWCAP_ARM_LPAE      = 1 << 20, +    ARM_HWCAP_ARM_EVTSTRM   = 1 << 21, +}; + +enum { +    ARM_HWCAP2_ARM_AES      = 1 << 0, +    ARM_HWCAP2_ARM_PMULL    = 1 << 1, +    ARM_HWCAP2_ARM_SHA1     = 1 << 2, +    ARM_HWCAP2_ARM_SHA2     = 1 << 3, +    ARM_HWCAP2_ARM_CRC32    = 1 << 4, +}; + +/* The commpage only exists for 32 bit kernels */ + +#define TARGET_HAS_VALIDATE_GUEST_SPACE +/* Return 1 if the proposed guest space is suitable for the guest. + * Return 0 if the proposed guest space isn't suitable, but another + * address space should be tried. + * Return -1 if there is no way the proposed guest space can be + * valid regardless of the base. + * The guest code may leave a page mapped and populate it if the + * address is suitable. + */ +static int validate_guest_space(unsigned long guest_base, +                                unsigned long guest_size) +{ +    unsigned long real_start, test_page_addr; + +    /* We need to check that we can force a fault on access to the +     * commpage at 0xffff0fxx +     */ +    test_page_addr = guest_base + (0xffff0f00 & qemu_host_page_mask); + +    /* If the commpage lies within the already allocated guest space, +     * then there is no way we can allocate it. +     */ +    if (test_page_addr >= guest_base +        && test_page_addr <= (guest_base + guest_size)) { +        return -1; +    } + +    /* Note it needs to be writeable to let us initialise it */ +    real_start = (unsigned long) +                 mmap((void *)test_page_addr, qemu_host_page_size, +                     PROT_READ | PROT_WRITE, +                     MAP_ANONYMOUS | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + +    /* If we can't map it then try another address */ +    if (real_start == -1ul) { +        return 0; +    } + +    if (real_start != test_page_addr) { +        /* OS didn't put the page where we asked - unmap and reject */ +        munmap((void *)real_start, qemu_host_page_size); +        return 0; +    } + +    /* Leave the page mapped +     * Populate it (mmap should have left it all 0'd) +     */ + +    /* Kernel helper versions */ +    __put_user(5, (uint32_t *)g2h(0xffff0ffcul)); + +    /* Now it's populated make it RO */ +    if (mprotect((void *)test_page_addr, qemu_host_page_size, PROT_READ)) { +        perror("Protecting guest commpage"); +        exit(-1); +    } + +    return 1; /* All good */ +} + +#define ELF_HWCAP get_elf_hwcap() +#define ELF_HWCAP2 get_elf_hwcap2() + +static uint32_t get_elf_hwcap(void) +{ +    ARMCPU *cpu = ARM_CPU(thread_cpu); +    uint32_t hwcaps = 0; + +    hwcaps |= ARM_HWCAP_ARM_SWP; +    hwcaps |= ARM_HWCAP_ARM_HALF; +    hwcaps |= ARM_HWCAP_ARM_THUMB; +    hwcaps |= ARM_HWCAP_ARM_FAST_MULT; + +    /* probe for the extra features */ +#define GET_FEATURE(feat, hwcap) \ +    do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0) +    /* EDSP is in v5TE and above, but all our v5 CPUs are v5TE */ +    GET_FEATURE(ARM_FEATURE_V5, ARM_HWCAP_ARM_EDSP); +    GET_FEATURE(ARM_FEATURE_VFP, ARM_HWCAP_ARM_VFP); +    GET_FEATURE(ARM_FEATURE_IWMMXT, ARM_HWCAP_ARM_IWMMXT); +    GET_FEATURE(ARM_FEATURE_THUMB2EE, ARM_HWCAP_ARM_THUMBEE); +    GET_FEATURE(ARM_FEATURE_NEON, ARM_HWCAP_ARM_NEON); +    GET_FEATURE(ARM_FEATURE_VFP3, ARM_HWCAP_ARM_VFPv3); +    GET_FEATURE(ARM_FEATURE_V6K, ARM_HWCAP_ARM_TLS); +    GET_FEATURE(ARM_FEATURE_VFP4, ARM_HWCAP_ARM_VFPv4); +    GET_FEATURE(ARM_FEATURE_ARM_DIV, ARM_HWCAP_ARM_IDIVA); +    GET_FEATURE(ARM_FEATURE_THUMB_DIV, ARM_HWCAP_ARM_IDIVT); +    /* All QEMU's VFPv3 CPUs have 32 registers, see VFP_DREG in translate.c. +     * Note that the ARM_HWCAP_ARM_VFPv3D16 bit is always the inverse of +     * ARM_HWCAP_ARM_VFPD32 (and so always clear for QEMU); it is unrelated +     * to our VFP_FP16 feature bit. +     */ +    GET_FEATURE(ARM_FEATURE_VFP3, ARM_HWCAP_ARM_VFPD32); +    GET_FEATURE(ARM_FEATURE_LPAE, ARM_HWCAP_ARM_LPAE); + +    return hwcaps; +} + +static uint32_t get_elf_hwcap2(void) +{ +    ARMCPU *cpu = ARM_CPU(thread_cpu); +    uint32_t hwcaps = 0; + +    GET_FEATURE(ARM_FEATURE_V8_AES, ARM_HWCAP2_ARM_AES); +    GET_FEATURE(ARM_FEATURE_V8_PMULL, ARM_HWCAP2_ARM_PMULL); +    GET_FEATURE(ARM_FEATURE_V8_SHA1, ARM_HWCAP2_ARM_SHA1); +    GET_FEATURE(ARM_FEATURE_V8_SHA256, ARM_HWCAP2_ARM_SHA2); +    GET_FEATURE(ARM_FEATURE_CRC, ARM_HWCAP2_ARM_CRC32); +    return hwcaps; +} + +#undef GET_FEATURE + +#else +/* 64 bit ARM definitions */ +#define ELF_START_MMAP 0x80000000 + +#define elf_check_arch(x) ((x) == ELF_MACHINE) + +#define ELF_ARCH        ELF_MACHINE +#define ELF_CLASS       ELFCLASS64 +#define ELF_PLATFORM    "aarch64" + +static inline void init_thread(struct target_pt_regs *regs, +                               struct image_info *infop) +{ +    abi_long stack = infop->start_stack; +    memset(regs, 0, sizeof(*regs)); + +    regs->pc = infop->entry & ~0x3ULL; +    regs->sp = stack; +} + +#define ELF_NREG    34 +typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG]; + +static void elf_core_copy_regs(target_elf_gregset_t *regs, +                               const CPUARMState *env) +{ +    int i; + +    for (i = 0; i < 32; i++) { +        (*regs)[i] = tswapreg(env->xregs[i]); +    } +    (*regs)[32] = tswapreg(env->pc); +    (*regs)[33] = tswapreg(pstate_read((CPUARMState *)env)); +} + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE       4096 + +enum { +    ARM_HWCAP_A64_FP            = 1 << 0, +    ARM_HWCAP_A64_ASIMD         = 1 << 1, +    ARM_HWCAP_A64_EVTSTRM       = 1 << 2, +    ARM_HWCAP_A64_AES           = 1 << 3, +    ARM_HWCAP_A64_PMULL         = 1 << 4, +    ARM_HWCAP_A64_SHA1          = 1 << 5, +    ARM_HWCAP_A64_SHA2          = 1 << 6, +    ARM_HWCAP_A64_CRC32         = 1 << 7, +}; + +#define ELF_HWCAP get_elf_hwcap() + +static uint32_t get_elf_hwcap(void) +{ +    ARMCPU *cpu = ARM_CPU(thread_cpu); +    uint32_t hwcaps = 0; + +    hwcaps |= ARM_HWCAP_A64_FP; +    hwcaps |= ARM_HWCAP_A64_ASIMD; + +    /* probe for the extra features */ +#define GET_FEATURE(feat, hwcap) \ +    do { if (arm_feature(&cpu->env, feat)) { hwcaps |= hwcap; } } while (0) +    GET_FEATURE(ARM_FEATURE_V8_AES, ARM_HWCAP_A64_AES); +    GET_FEATURE(ARM_FEATURE_V8_PMULL, ARM_HWCAP_A64_PMULL); +    GET_FEATURE(ARM_FEATURE_V8_SHA1, ARM_HWCAP_A64_SHA1); +    GET_FEATURE(ARM_FEATURE_V8_SHA256, ARM_HWCAP_A64_SHA2); +    GET_FEATURE(ARM_FEATURE_CRC, ARM_HWCAP_A64_CRC32); +#undef GET_FEATURE + +    return hwcaps; +} + +#endif /* not TARGET_AARCH64 */ +#endif /* TARGET_ARM */ + +#ifdef TARGET_UNICORE32 + +#define ELF_START_MMAP          0x80000000 + +#define elf_check_arch(x)       ((x) == EM_UNICORE32) + +#define ELF_CLASS               ELFCLASS32 +#define ELF_DATA                ELFDATA2LSB +#define ELF_ARCH                EM_UNICORE32 + +static inline void init_thread(struct target_pt_regs *regs, +        struct image_info *infop) +{ +    abi_long stack = infop->start_stack; +    memset(regs, 0, sizeof(*regs)); +    regs->UC32_REG_asr = 0x10; +    regs->UC32_REG_pc = infop->entry & 0xfffffffe; +    regs->UC32_REG_sp = infop->start_stack; +    /* FIXME - what to for failure of get_user()? */ +    get_user_ual(regs->UC32_REG_02, stack + 8); /* envp */ +    get_user_ual(regs->UC32_REG_01, stack + 4); /* envp */ +    /* XXX: it seems that r0 is zeroed after ! */ +    regs->UC32_REG_00 = 0; +} + +#define ELF_NREG    34 +typedef target_elf_greg_t  target_elf_gregset_t[ELF_NREG]; + +static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUUniCore32State *env) +{ +    (*regs)[0] = env->regs[0]; +    (*regs)[1] = env->regs[1]; +    (*regs)[2] = env->regs[2]; +    (*regs)[3] = env->regs[3]; +    (*regs)[4] = env->regs[4]; +    (*regs)[5] = env->regs[5]; +    (*regs)[6] = env->regs[6]; +    (*regs)[7] = env->regs[7]; +    (*regs)[8] = env->regs[8]; +    (*regs)[9] = env->regs[9]; +    (*regs)[10] = env->regs[10]; +    (*regs)[11] = env->regs[11]; +    (*regs)[12] = env->regs[12]; +    (*regs)[13] = env->regs[13]; +    (*regs)[14] = env->regs[14]; +    (*regs)[15] = env->regs[15]; +    (*regs)[16] = env->regs[16]; +    (*regs)[17] = env->regs[17]; +    (*regs)[18] = env->regs[18]; +    (*regs)[19] = env->regs[19]; +    (*regs)[20] = env->regs[20]; +    (*regs)[21] = env->regs[21]; +    (*regs)[22] = env->regs[22]; +    (*regs)[23] = env->regs[23]; +    (*regs)[24] = env->regs[24]; +    (*regs)[25] = env->regs[25]; +    (*regs)[26] = env->regs[26]; +    (*regs)[27] = env->regs[27]; +    (*regs)[28] = env->regs[28]; +    (*regs)[29] = env->regs[29]; +    (*regs)[30] = env->regs[30]; +    (*regs)[31] = env->regs[31]; + +    (*regs)[32] = cpu_asr_read((CPUUniCore32State *)env); +    (*regs)[33] = env->regs[0]; /* XXX */ +} + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE               4096 + +#define ELF_HWCAP                       (UC32_HWCAP_CMOV | UC32_HWCAP_UCF64) + +#endif + +#ifdef TARGET_SPARC +#ifdef TARGET_SPARC64 + +#define ELF_START_MMAP 0x80000000 +#define ELF_HWCAP  (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \ +                    | HWCAP_SPARC_MULDIV | HWCAP_SPARC_V9) +#ifndef TARGET_ABI32 +#define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS ) +#else +#define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC ) +#endif + +#define ELF_CLASS   ELFCLASS64 +#define ELF_ARCH    EM_SPARCV9 + +#define STACK_BIAS              2047 + +static inline void init_thread(struct target_pt_regs *regs, +                               struct image_info *infop) +{ +#ifndef TARGET_ABI32 +    regs->tstate = 0; +#endif +    regs->pc = infop->entry; +    regs->npc = regs->pc + 4; +    regs->y = 0; +#ifdef TARGET_ABI32 +    regs->u_regs[14] = infop->start_stack - 16 * 4; +#else +    if (personality(infop->personality) == PER_LINUX32) +        regs->u_regs[14] = infop->start_stack - 16 * 4; +    else +        regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS; +#endif +} + +#else +#define ELF_START_MMAP 0x80000000 +#define ELF_HWCAP  (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | HWCAP_SPARC_SWAP \ +                    | HWCAP_SPARC_MULDIV) +#define elf_check_arch(x) ( (x) == EM_SPARC ) + +#define ELF_CLASS   ELFCLASS32 +#define ELF_ARCH    EM_SPARC + +static inline void init_thread(struct target_pt_regs *regs, +                               struct image_info *infop) +{ +    regs->psr = 0; +    regs->pc = infop->entry; +    regs->npc = regs->pc + 4; +    regs->y = 0; +    regs->u_regs[14] = infop->start_stack - 16 * 4; +} + +#endif +#endif + +#ifdef TARGET_PPC + +#define ELF_START_MMAP 0x80000000 + +#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) + +#define elf_check_arch(x) ( (x) == EM_PPC64 ) + +#define ELF_CLASS       ELFCLASS64 + +#else + +#define elf_check_arch(x) ( (x) == EM_PPC ) + +#define ELF_CLASS       ELFCLASS32 + +#endif + +#define ELF_ARCH        EM_PPC + +/* Feature masks for the Aux Vector Hardware Capabilities (AT_HWCAP). +   See arch/powerpc/include/asm/cputable.h.  */ +enum { +    QEMU_PPC_FEATURE_32 = 0x80000000, +    QEMU_PPC_FEATURE_64 = 0x40000000, +    QEMU_PPC_FEATURE_601_INSTR = 0x20000000, +    QEMU_PPC_FEATURE_HAS_ALTIVEC = 0x10000000, +    QEMU_PPC_FEATURE_HAS_FPU = 0x08000000, +    QEMU_PPC_FEATURE_HAS_MMU = 0x04000000, +    QEMU_PPC_FEATURE_HAS_4xxMAC = 0x02000000, +    QEMU_PPC_FEATURE_UNIFIED_CACHE = 0x01000000, +    QEMU_PPC_FEATURE_HAS_SPE = 0x00800000, +    QEMU_PPC_FEATURE_HAS_EFP_SINGLE = 0x00400000, +    QEMU_PPC_FEATURE_HAS_EFP_DOUBLE = 0x00200000, +    QEMU_PPC_FEATURE_NO_TB = 0x00100000, +    QEMU_PPC_FEATURE_POWER4 = 0x00080000, +    QEMU_PPC_FEATURE_POWER5 = 0x00040000, +    QEMU_PPC_FEATURE_POWER5_PLUS = 0x00020000, +    QEMU_PPC_FEATURE_CELL = 0x00010000, +    QEMU_PPC_FEATURE_BOOKE = 0x00008000, +    QEMU_PPC_FEATURE_SMT = 0x00004000, +    QEMU_PPC_FEATURE_ICACHE_SNOOP = 0x00002000, +    QEMU_PPC_FEATURE_ARCH_2_05 = 0x00001000, +    QEMU_PPC_FEATURE_PA6T = 0x00000800, +    QEMU_PPC_FEATURE_HAS_DFP = 0x00000400, +    QEMU_PPC_FEATURE_POWER6_EXT = 0x00000200, +    QEMU_PPC_FEATURE_ARCH_2_06 = 0x00000100, +    QEMU_PPC_FEATURE_HAS_VSX = 0x00000080, +    QEMU_PPC_FEATURE_PSERIES_PERFMON_COMPAT = 0x00000040, + +    QEMU_PPC_FEATURE_TRUE_LE = 0x00000002, +    QEMU_PPC_FEATURE_PPC_LE = 0x00000001, + +    /* Feature definitions in AT_HWCAP2.  */ +    QEMU_PPC_FEATURE2_ARCH_2_07 = 0x80000000, /* ISA 2.07 */ +    QEMU_PPC_FEATURE2_HAS_HTM = 0x40000000, /* Hardware Transactional Memory */ +    QEMU_PPC_FEATURE2_HAS_DSCR = 0x20000000, /* Data Stream Control Register */ +    QEMU_PPC_FEATURE2_HAS_EBB = 0x10000000, /* Event Base Branching */ +    QEMU_PPC_FEATURE2_HAS_ISEL = 0x08000000, /* Integer Select */ +    QEMU_PPC_FEATURE2_HAS_TAR = 0x04000000, /* Target Address Register */ +}; + +#define ELF_HWCAP get_elf_hwcap() + +static uint32_t get_elf_hwcap(void) +{ +    PowerPCCPU *cpu = POWERPC_CPU(thread_cpu); +    uint32_t features = 0; + +    /* We don't have to be terribly complete here; the high points are +       Altivec/FP/SPE support.  Anything else is just a bonus.  */ +#define GET_FEATURE(flag, feature)                                      \ +    do { if (cpu->env.insns_flags & flag) { features |= feature; } } while (0) +#define GET_FEATURE2(flag, feature)                                      \ +    do { if (cpu->env.insns_flags2 & flag) { features |= feature; } } while (0) +    GET_FEATURE(PPC_64B, QEMU_PPC_FEATURE_64); +    GET_FEATURE(PPC_FLOAT, QEMU_PPC_FEATURE_HAS_FPU); +    GET_FEATURE(PPC_ALTIVEC, QEMU_PPC_FEATURE_HAS_ALTIVEC); +    GET_FEATURE(PPC_SPE, QEMU_PPC_FEATURE_HAS_SPE); +    GET_FEATURE(PPC_SPE_SINGLE, QEMU_PPC_FEATURE_HAS_EFP_SINGLE); +    GET_FEATURE(PPC_SPE_DOUBLE, QEMU_PPC_FEATURE_HAS_EFP_DOUBLE); +    GET_FEATURE(PPC_BOOKE, QEMU_PPC_FEATURE_BOOKE); +    GET_FEATURE(PPC_405_MAC, QEMU_PPC_FEATURE_HAS_4xxMAC); +    GET_FEATURE2(PPC2_DFP, QEMU_PPC_FEATURE_HAS_DFP); +    GET_FEATURE2(PPC2_VSX, QEMU_PPC_FEATURE_HAS_VSX); +    GET_FEATURE2((PPC2_PERM_ISA206 | PPC2_DIVE_ISA206 | PPC2_ATOMIC_ISA206 | +                  PPC2_FP_CVT_ISA206 | PPC2_FP_TST_ISA206), +                  QEMU_PPC_FEATURE_ARCH_2_06); +#undef GET_FEATURE +#undef GET_FEATURE2 + +    return features; +} + +#define ELF_HWCAP2 get_elf_hwcap2() + +static uint32_t get_elf_hwcap2(void) +{ +    PowerPCCPU *cpu = POWERPC_CPU(thread_cpu); +    uint32_t features = 0; + +#define GET_FEATURE(flag, feature)                                      \ +    do { if (cpu->env.insns_flags & flag) { features |= feature; } } while (0) +#define GET_FEATURE2(flag, feature)                                      \ +    do { if (cpu->env.insns_flags2 & flag) { features |= feature; } } while (0) + +    GET_FEATURE(PPC_ISEL, QEMU_PPC_FEATURE2_HAS_ISEL); +    GET_FEATURE2(PPC2_BCTAR_ISA207, QEMU_PPC_FEATURE2_HAS_TAR); +    GET_FEATURE2((PPC2_BCTAR_ISA207 | PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 | +                  PPC2_ISA207S), QEMU_PPC_FEATURE2_ARCH_2_07); + +#undef GET_FEATURE +#undef GET_FEATURE2 + +    return features; +} + +/* + * The requirements here are: + * - keep the final alignment of sp (sp & 0xf) + * - make sure the 32-bit value at the first 16 byte aligned position of + *   AUXV is greater than 16 for glibc compatibility. + *   AT_IGNOREPPC is used for that. + * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC, + *   even if DLINFO_ARCH_ITEMS goes to zero or is undefined. + */ +#define DLINFO_ARCH_ITEMS       5 +#define ARCH_DLINFO                                     \ +    do {                                                \ +        PowerPCCPU *cpu = POWERPC_CPU(thread_cpu);              \ +        NEW_AUX_ENT(AT_DCACHEBSIZE, cpu->env.dcache_line_size); \ +        NEW_AUX_ENT(AT_ICACHEBSIZE, cpu->env.icache_line_size); \ +        NEW_AUX_ENT(AT_UCACHEBSIZE, 0);                 \ +        /*                                              \ +         * Now handle glibc compatibility.              \ +         */                                             \ +        NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);        \ +        NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);        \ +    } while (0) + +static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop) +{ +    _regs->gpr[1] = infop->start_stack; +#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) +    if (get_ppc64_abi(infop) < 2) { +        uint64_t val; +        get_user_u64(val, infop->entry + 8); +        _regs->gpr[2] = val + infop->load_bias; +        get_user_u64(val, infop->entry); +        infop->entry = val + infop->load_bias; +    } else { +        _regs->gpr[12] = infop->entry;  /* r12 set to global entry address */ +    } +#endif +    _regs->nip = infop->entry; +} + +/* See linux kernel: arch/powerpc/include/asm/elf.h.  */ +#define ELF_NREG 48 +typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; + +static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *env) +{ +    int i; +    target_ulong ccr = 0; + +    for (i = 0; i < ARRAY_SIZE(env->gpr); i++) { +        (*regs)[i] = tswapreg(env->gpr[i]); +    } + +    (*regs)[32] = tswapreg(env->nip); +    (*regs)[33] = tswapreg(env->msr); +    (*regs)[35] = tswapreg(env->ctr); +    (*regs)[36] = tswapreg(env->lr); +    (*regs)[37] = tswapreg(env->xer); + +    for (i = 0; i < ARRAY_SIZE(env->crf); i++) { +        ccr |= env->crf[i] << (32 - ((i + 1) * 4)); +    } +    (*regs)[38] = tswapreg(ccr); +} + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE       4096 + +#endif + +#ifdef TARGET_MIPS + +#define ELF_START_MMAP 0x80000000 + +#define elf_check_arch(x) ( (x) == EM_MIPS ) + +#ifdef TARGET_MIPS64 +#define ELF_CLASS   ELFCLASS64 +#else +#define ELF_CLASS   ELFCLASS32 +#endif +#define ELF_ARCH    EM_MIPS + +static inline void init_thread(struct target_pt_regs *regs, +                               struct image_info *infop) +{ +    regs->cp0_status = 2 << CP0St_KSU; +    regs->cp0_epc = infop->entry; +    regs->regs[29] = infop->start_stack; +} + +/* See linux kernel: arch/mips/include/asm/elf.h.  */ +#define ELF_NREG 45 +typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; + +/* See linux kernel: arch/mips/include/asm/reg.h.  */ +enum { +#ifdef TARGET_MIPS64 +    TARGET_EF_R0 = 0, +#else +    TARGET_EF_R0 = 6, +#endif +    TARGET_EF_R26 = TARGET_EF_R0 + 26, +    TARGET_EF_R27 = TARGET_EF_R0 + 27, +    TARGET_EF_LO = TARGET_EF_R0 + 32, +    TARGET_EF_HI = TARGET_EF_R0 + 33, +    TARGET_EF_CP0_EPC = TARGET_EF_R0 + 34, +    TARGET_EF_CP0_BADVADDR = TARGET_EF_R0 + 35, +    TARGET_EF_CP0_STATUS = TARGET_EF_R0 + 36, +    TARGET_EF_CP0_CAUSE = TARGET_EF_R0 + 37 +}; + +/* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs.  */ +static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMIPSState *env) +{ +    int i; + +    for (i = 0; i < TARGET_EF_R0; i++) { +        (*regs)[i] = 0; +    } +    (*regs)[TARGET_EF_R0] = 0; + +    for (i = 1; i < ARRAY_SIZE(env->active_tc.gpr); i++) { +        (*regs)[TARGET_EF_R0 + i] = tswapreg(env->active_tc.gpr[i]); +    } + +    (*regs)[TARGET_EF_R26] = 0; +    (*regs)[TARGET_EF_R27] = 0; +    (*regs)[TARGET_EF_LO] = tswapreg(env->active_tc.LO[0]); +    (*regs)[TARGET_EF_HI] = tswapreg(env->active_tc.HI[0]); +    (*regs)[TARGET_EF_CP0_EPC] = tswapreg(env->active_tc.PC); +    (*regs)[TARGET_EF_CP0_BADVADDR] = tswapreg(env->CP0_BadVAddr); +    (*regs)[TARGET_EF_CP0_STATUS] = tswapreg(env->CP0_Status); +    (*regs)[TARGET_EF_CP0_CAUSE] = tswapreg(env->CP0_Cause); +} + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE        4096 + +#endif /* TARGET_MIPS */ + +#ifdef TARGET_MICROBLAZE + +#define ELF_START_MMAP 0x80000000 + +#define elf_check_arch(x) ( (x) == EM_MICROBLAZE || (x) == EM_MICROBLAZE_OLD) + +#define ELF_CLASS   ELFCLASS32 +#define ELF_ARCH    EM_MICROBLAZE + +static inline void init_thread(struct target_pt_regs *regs, +                               struct image_info *infop) +{ +    regs->pc = infop->entry; +    regs->r1 = infop->start_stack; + +} + +#define ELF_EXEC_PAGESIZE        4096 + +#define USE_ELF_CORE_DUMP +#define ELF_NREG 38 +typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; + +/* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs.  */ +static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUMBState *env) +{ +    int i, pos = 0; + +    for (i = 0; i < 32; i++) { +        (*regs)[pos++] = tswapreg(env->regs[i]); +    } + +    for (i = 0; i < 6; i++) { +        (*regs)[pos++] = tswapreg(env->sregs[i]); +    } +} + +#endif /* TARGET_MICROBLAZE */ + +#ifdef TARGET_OPENRISC + +#define ELF_START_MMAP 0x08000000 + +#define elf_check_arch(x) ((x) == EM_OPENRISC) + +#define ELF_ARCH EM_OPENRISC +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA  ELFDATA2MSB + +static inline void init_thread(struct target_pt_regs *regs, +                               struct image_info *infop) +{ +    regs->pc = infop->entry; +    regs->gpr[1] = infop->start_stack; +} + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE 8192 + +/* See linux kernel arch/openrisc/include/asm/elf.h.  */ +#define ELF_NREG 34 /* gprs and pc, sr */ +typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; + +static void elf_core_copy_regs(target_elf_gregset_t *regs, +                               const CPUOpenRISCState *env) +{ +    int i; + +    for (i = 0; i < 32; i++) { +        (*regs)[i] = tswapreg(env->gpr[i]); +    } + +    (*regs)[32] = tswapreg(env->pc); +    (*regs)[33] = tswapreg(env->sr); +} +#define ELF_HWCAP 0 +#define ELF_PLATFORM NULL + +#endif /* TARGET_OPENRISC */ + +#ifdef TARGET_SH4 + +#define ELF_START_MMAP 0x80000000 + +#define elf_check_arch(x) ( (x) == EM_SH ) + +#define ELF_CLASS ELFCLASS32 +#define ELF_ARCH  EM_SH + +static inline void init_thread(struct target_pt_regs *regs, +                               struct image_info *infop) +{ +    /* Check other registers XXXXX */ +    regs->pc = infop->entry; +    regs->regs[15] = infop->start_stack; +} + +/* See linux kernel: arch/sh/include/asm/elf.h.  */ +#define ELF_NREG 23 +typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; + +/* See linux kernel: arch/sh/include/asm/ptrace.h.  */ +enum { +    TARGET_REG_PC = 16, +    TARGET_REG_PR = 17, +    TARGET_REG_SR = 18, +    TARGET_REG_GBR = 19, +    TARGET_REG_MACH = 20, +    TARGET_REG_MACL = 21, +    TARGET_REG_SYSCALL = 22 +}; + +static inline void elf_core_copy_regs(target_elf_gregset_t *regs, +                                      const CPUSH4State *env) +{ +    int i; + +    for (i = 0; i < 16; i++) { +        (*regs[i]) = tswapreg(env->gregs[i]); +    } + +    (*regs)[TARGET_REG_PC] = tswapreg(env->pc); +    (*regs)[TARGET_REG_PR] = tswapreg(env->pr); +    (*regs)[TARGET_REG_SR] = tswapreg(env->sr); +    (*regs)[TARGET_REG_GBR] = tswapreg(env->gbr); +    (*regs)[TARGET_REG_MACH] = tswapreg(env->mach); +    (*regs)[TARGET_REG_MACL] = tswapreg(env->macl); +    (*regs)[TARGET_REG_SYSCALL] = 0; /* FIXME */ +} + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE        4096 + +enum { +    SH_CPU_HAS_FPU            = 0x0001, /* Hardware FPU support */ +    SH_CPU_HAS_P2_FLUSH_BUG   = 0x0002, /* Need to flush the cache in P2 area */ +    SH_CPU_HAS_MMU_PAGE_ASSOC = 0x0004, /* SH3: TLB way selection bit support */ +    SH_CPU_HAS_DSP            = 0x0008, /* SH-DSP: DSP support */ +    SH_CPU_HAS_PERF_COUNTER   = 0x0010, /* Hardware performance counters */ +    SH_CPU_HAS_PTEA           = 0x0020, /* PTEA register */ +    SH_CPU_HAS_LLSC           = 0x0040, /* movli.l/movco.l */ +    SH_CPU_HAS_L2_CACHE       = 0x0080, /* Secondary cache / URAM */ +    SH_CPU_HAS_OP32           = 0x0100, /* 32-bit instruction support */ +    SH_CPU_HAS_PTEAEX         = 0x0200, /* PTE ASID Extension support */ +}; + +#define ELF_HWCAP get_elf_hwcap() + +static uint32_t get_elf_hwcap(void) +{ +    SuperHCPU *cpu = SUPERH_CPU(thread_cpu); +    uint32_t hwcap = 0; + +    hwcap |= SH_CPU_HAS_FPU; + +    if (cpu->env.features & SH_FEATURE_SH4A) { +        hwcap |= SH_CPU_HAS_LLSC; +    } + +    return hwcap; +} + +#endif + +#ifdef TARGET_CRIS + +#define ELF_START_MMAP 0x80000000 + +#define elf_check_arch(x) ( (x) == EM_CRIS ) + +#define ELF_CLASS ELFCLASS32 +#define ELF_ARCH  EM_CRIS + +static inline void init_thread(struct target_pt_regs *regs, +                               struct image_info *infop) +{ +    regs->erp = infop->entry; +} + +#define ELF_EXEC_PAGESIZE        8192 + +#endif + +#ifdef TARGET_M68K + +#define ELF_START_MMAP 0x80000000 + +#define elf_check_arch(x) ( (x) == EM_68K ) + +#define ELF_CLASS       ELFCLASS32 +#define ELF_ARCH        EM_68K + +/* ??? Does this need to do anything? +   #define ELF_PLAT_INIT(_r) */ + +static inline void init_thread(struct target_pt_regs *regs, +                               struct image_info *infop) +{ +    regs->usp = infop->start_stack; +    regs->sr = 0; +    regs->pc = infop->entry; +} + +/* See linux kernel: arch/m68k/include/asm/elf.h.  */ +#define ELF_NREG 20 +typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; + +static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUM68KState *env) +{ +    (*regs)[0] = tswapreg(env->dregs[1]); +    (*regs)[1] = tswapreg(env->dregs[2]); +    (*regs)[2] = tswapreg(env->dregs[3]); +    (*regs)[3] = tswapreg(env->dregs[4]); +    (*regs)[4] = tswapreg(env->dregs[5]); +    (*regs)[5] = tswapreg(env->dregs[6]); +    (*regs)[6] = tswapreg(env->dregs[7]); +    (*regs)[7] = tswapreg(env->aregs[0]); +    (*regs)[8] = tswapreg(env->aregs[1]); +    (*regs)[9] = tswapreg(env->aregs[2]); +    (*regs)[10] = tswapreg(env->aregs[3]); +    (*regs)[11] = tswapreg(env->aregs[4]); +    (*regs)[12] = tswapreg(env->aregs[5]); +    (*regs)[13] = tswapreg(env->aregs[6]); +    (*regs)[14] = tswapreg(env->dregs[0]); +    (*regs)[15] = tswapreg(env->aregs[7]); +    (*regs)[16] = tswapreg(env->dregs[0]); /* FIXME: orig_d0 */ +    (*regs)[17] = tswapreg(env->sr); +    (*regs)[18] = tswapreg(env->pc); +    (*regs)[19] = 0;  /* FIXME: regs->format | regs->vector */ +} + +#define USE_ELF_CORE_DUMP +#define ELF_EXEC_PAGESIZE       8192 + +#endif + +#ifdef TARGET_ALPHA + +#define ELF_START_MMAP (0x30000000000ULL) + +#define elf_check_arch(x) ( (x) == ELF_ARCH ) + +#define ELF_CLASS      ELFCLASS64 +#define ELF_ARCH       EM_ALPHA + +static inline void init_thread(struct target_pt_regs *regs, +                               struct image_info *infop) +{ +    regs->pc = infop->entry; +    regs->ps = 8; +    regs->usp = infop->start_stack; +} + +#define ELF_EXEC_PAGESIZE        8192 + +#endif /* TARGET_ALPHA */ + +#ifdef TARGET_S390X + +#define ELF_START_MMAP (0x20000000000ULL) + +#define elf_check_arch(x) ( (x) == ELF_ARCH ) + +#define ELF_CLASS	ELFCLASS64 +#define ELF_DATA	ELFDATA2MSB +#define ELF_ARCH	EM_S390 + +static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) +{ +    regs->psw.addr = infop->entry; +    regs->psw.mask = PSW_MASK_64 | PSW_MASK_32; +    regs->gprs[15] = infop->start_stack; +} + +#endif /* TARGET_S390X */ + +#ifndef ELF_PLATFORM +#define ELF_PLATFORM (NULL) +#endif + +#ifndef ELF_HWCAP +#define ELF_HWCAP 0 +#endif + +#ifdef TARGET_ABI32 +#undef ELF_CLASS +#define ELF_CLASS ELFCLASS32 +#undef bswaptls +#define bswaptls(ptr) bswap32s(ptr) +#endif + +#include "elf.h" + +struct exec +{ +    unsigned int a_info;   /* Use macros N_MAGIC, etc for access */ +    unsigned int a_text;   /* length of text, in bytes */ +    unsigned int a_data;   /* length of data, in bytes */ +    unsigned int a_bss;    /* length of uninitialized data area, in bytes */ +    unsigned int a_syms;   /* length of symbol table data in file, in bytes */ +    unsigned int a_entry;  /* start address */ +    unsigned int a_trsize; /* length of relocation info for text, in bytes */ +    unsigned int a_drsize; /* length of relocation info for data, in bytes */ +}; + + +#define N_MAGIC(exec) ((exec).a_info & 0xffff) +#define OMAGIC 0407 +#define NMAGIC 0410 +#define ZMAGIC 0413 +#define QMAGIC 0314 + +/* Necessary parameters */ +#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE +#define TARGET_ELF_PAGESTART(_v) ((_v) & \ +                                 ~(abi_ulong)(TARGET_ELF_EXEC_PAGESIZE-1)) +#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1)) + +#define DLINFO_ITEMS 14 + +static inline void memcpy_fromfs(void * to, const void * from, unsigned long n) +{ +    memcpy(to, from, n); +} + +#ifdef BSWAP_NEEDED +static void bswap_ehdr(struct elfhdr *ehdr) +{ +    bswap16s(&ehdr->e_type);            /* Object file type */ +    bswap16s(&ehdr->e_machine);         /* Architecture */ +    bswap32s(&ehdr->e_version);         /* Object file version */ +    bswaptls(&ehdr->e_entry);           /* Entry point virtual address */ +    bswaptls(&ehdr->e_phoff);           /* Program header table file offset */ +    bswaptls(&ehdr->e_shoff);           /* Section header table file offset */ +    bswap32s(&ehdr->e_flags);           /* Processor-specific flags */ +    bswap16s(&ehdr->e_ehsize);          /* ELF header size in bytes */ +    bswap16s(&ehdr->e_phentsize);       /* Program header table entry size */ +    bswap16s(&ehdr->e_phnum);           /* Program header table entry count */ +    bswap16s(&ehdr->e_shentsize);       /* Section header table entry size */ +    bswap16s(&ehdr->e_shnum);           /* Section header table entry count */ +    bswap16s(&ehdr->e_shstrndx);        /* Section header string table index */ +} + +static void bswap_phdr(struct elf_phdr *phdr, int phnum) +{ +    int i; +    for (i = 0; i < phnum; ++i, ++phdr) { +        bswap32s(&phdr->p_type);        /* Segment type */ +        bswap32s(&phdr->p_flags);       /* Segment flags */ +        bswaptls(&phdr->p_offset);      /* Segment file offset */ +        bswaptls(&phdr->p_vaddr);       /* Segment virtual address */ +        bswaptls(&phdr->p_paddr);       /* Segment physical address */ +        bswaptls(&phdr->p_filesz);      /* Segment size in file */ +        bswaptls(&phdr->p_memsz);       /* Segment size in memory */ +        bswaptls(&phdr->p_align);       /* Segment alignment */ +    } +} + +static void bswap_shdr(struct elf_shdr *shdr, int shnum) +{ +    int i; +    for (i = 0; i < shnum; ++i, ++shdr) { +        bswap32s(&shdr->sh_name); +        bswap32s(&shdr->sh_type); +        bswaptls(&shdr->sh_flags); +        bswaptls(&shdr->sh_addr); +        bswaptls(&shdr->sh_offset); +        bswaptls(&shdr->sh_size); +        bswap32s(&shdr->sh_link); +        bswap32s(&shdr->sh_info); +        bswaptls(&shdr->sh_addralign); +        bswaptls(&shdr->sh_entsize); +    } +} + +static void bswap_sym(struct elf_sym *sym) +{ +    bswap32s(&sym->st_name); +    bswaptls(&sym->st_value); +    bswaptls(&sym->st_size); +    bswap16s(&sym->st_shndx); +} +#else +static inline void bswap_ehdr(struct elfhdr *ehdr) { } +static inline void bswap_phdr(struct elf_phdr *phdr, int phnum) { } +static inline void bswap_shdr(struct elf_shdr *shdr, int shnum) { } +static inline void bswap_sym(struct elf_sym *sym) { } +#endif + +#ifdef USE_ELF_CORE_DUMP +static int elf_core_dump(int, const CPUArchState *); +#endif /* USE_ELF_CORE_DUMP */ +static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias); + +/* Verify the portions of EHDR within E_IDENT for the target. +   This can be performed before bswapping the entire header.  */ +static bool elf_check_ident(struct elfhdr *ehdr) +{ +    return (ehdr->e_ident[EI_MAG0] == ELFMAG0 +            && ehdr->e_ident[EI_MAG1] == ELFMAG1 +            && ehdr->e_ident[EI_MAG2] == ELFMAG2 +            && ehdr->e_ident[EI_MAG3] == ELFMAG3 +            && ehdr->e_ident[EI_CLASS] == ELF_CLASS +            && ehdr->e_ident[EI_DATA] == ELF_DATA +            && ehdr->e_ident[EI_VERSION] == EV_CURRENT); +} + +/* Verify the portions of EHDR outside of E_IDENT for the target. +   This has to wait until after bswapping the header.  */ +static bool elf_check_ehdr(struct elfhdr *ehdr) +{ +    return (elf_check_arch(ehdr->e_machine) +            && ehdr->e_ehsize == sizeof(struct elfhdr) +            && ehdr->e_phentsize == sizeof(struct elf_phdr) +            && (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)); +} + +/* + * 'copy_elf_strings()' copies argument/envelope strings from user + * memory to free pages in kernel mem. These are in a format ready + * to be put directly into the top of new user memory. + * + */ +static abi_ulong copy_elf_strings(int argc,char ** argv, void **page, +                                  abi_ulong p) +{ +    char *tmp, *tmp1, *pag = NULL; +    int len, offset = 0; + +    if (!p) { +        return 0;       /* bullet-proofing */ +    } +    while (argc-- > 0) { +        tmp = argv[argc]; +        if (!tmp) { +            fprintf(stderr, "VFS: argc is wrong"); +            exit(-1); +        } +        tmp1 = tmp; +        while (*tmp++); +        len = tmp - tmp1; +        if (p < len) {  /* this shouldn't happen - 128kB */ +            return 0; +        } +        while (len) { +            --p; --tmp; --len; +            if (--offset < 0) { +                offset = p % TARGET_PAGE_SIZE; +                pag = (char *)page[p/TARGET_PAGE_SIZE]; +                if (!pag) { +                    pag = g_try_malloc0(TARGET_PAGE_SIZE); +                    page[p/TARGET_PAGE_SIZE] = pag; +                    if (!pag) +                        return 0; +                } +            } +            if (len == 0 || offset == 0) { +                *(pag + offset) = *tmp; +            } +            else { +                int bytes_to_copy = (len > offset) ? offset : len; +                tmp -= bytes_to_copy; +                p -= bytes_to_copy; +                offset -= bytes_to_copy; +                len -= bytes_to_copy; +                memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1); +            } +        } +    } +    return p; +} + +static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm, +                                 struct image_info *info) +{ +    abi_ulong stack_base, size, error, guard; +    int i; + +    /* Create enough stack to hold everything.  If we don't use +       it for args, we'll use it for something else.  */ +    size = guest_stack_size; +    if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE) { +        size = MAX_ARG_PAGES*TARGET_PAGE_SIZE; +    } +    guard = TARGET_PAGE_SIZE; +    if (guard < qemu_real_host_page_size) { +        guard = qemu_real_host_page_size; +    } + +    error = target_mmap(0, size + guard, PROT_READ | PROT_WRITE, +                        MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +    if (error == -1) { +        perror("mmap stack"); +        exit(-1); +    } + +    /* We reserve one extra page at the top of the stack as guard.  */ +    target_mprotect(error, guard, PROT_NONE); + +    info->stack_limit = error + guard; +    stack_base = info->stack_limit + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE; +    p += stack_base; + +    for (i = 0 ; i < MAX_ARG_PAGES ; i++) { +        if (bprm->page[i]) { +            info->rss++; +            /* FIXME - check return value of memcpy_to_target() for failure */ +            memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE); +            g_free(bprm->page[i]); +        } +        stack_base += TARGET_PAGE_SIZE; +    } +    return p; +} + +/* Map and zero the bss.  We need to explicitly zero any fractional pages +   after the data section (i.e. bss).  */ +static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot) +{ +    uintptr_t host_start, host_map_start, host_end; + +    last_bss = TARGET_PAGE_ALIGN(last_bss); + +    /* ??? There is confusion between qemu_real_host_page_size and +       qemu_host_page_size here and elsewhere in target_mmap, which +       may lead to the end of the data section mapping from the file +       not being mapped.  At least there was an explicit test and +       comment for that here, suggesting that "the file size must +       be known".  The comment probably pre-dates the introduction +       of the fstat system call in target_mmap which does in fact +       find out the size.  What isn't clear is if the workaround +       here is still actually needed.  For now, continue with it, +       but merge it with the "normal" mmap that would allocate the bss.  */ + +    host_start = (uintptr_t) g2h(elf_bss); +    host_end = (uintptr_t) g2h(last_bss); +    host_map_start = (host_start + qemu_real_host_page_size - 1); +    host_map_start &= -qemu_real_host_page_size; + +    if (host_map_start < host_end) { +        void *p = mmap((void *)host_map_start, host_end - host_map_start, +                       prot, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +        if (p == MAP_FAILED) { +            perror("cannot mmap brk"); +            exit(-1); +        } +    } + +    /* Ensure that the bss page(s) are valid */ +    if ((page_get_flags(last_bss-1) & prot) != prot) { +        page_set_flags(elf_bss & TARGET_PAGE_MASK, last_bss, prot | PAGE_VALID); +    } + +    if (host_start < host_map_start) { +        memset((void *)host_start, 0, host_map_start - host_start); +    } +} + +#ifdef CONFIG_USE_FDPIC +static abi_ulong loader_build_fdpic_loadmap(struct image_info *info, abi_ulong sp) +{ +    uint16_t n; +    struct elf32_fdpic_loadseg *loadsegs = info->loadsegs; + +    /* elf32_fdpic_loadseg */ +    n = info->nsegs; +    while (n--) { +        sp -= 12; +        put_user_u32(loadsegs[n].addr, sp+0); +        put_user_u32(loadsegs[n].p_vaddr, sp+4); +        put_user_u32(loadsegs[n].p_memsz, sp+8); +    } + +    /* elf32_fdpic_loadmap */ +    sp -= 4; +    put_user_u16(0, sp+0); /* version */ +    put_user_u16(info->nsegs, sp+2); /* nsegs */ + +    info->personality = PER_LINUX_FDPIC; +    info->loadmap_addr = sp; + +    return sp; +} +#endif + +static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, +                                   struct elfhdr *exec, +                                   struct image_info *info, +                                   struct image_info *interp_info) +{ +    abi_ulong sp; +    abi_ulong sp_auxv; +    int size; +    int i; +    abi_ulong u_rand_bytes; +    uint8_t k_rand_bytes[16]; +    abi_ulong u_platform; +    const char *k_platform; +    const int n = sizeof(elf_addr_t); + +    sp = p; + +#ifdef CONFIG_USE_FDPIC +    /* Needs to be before we load the env/argc/... */ +    if (elf_is_fdpic(exec)) { +        /* Need 4 byte alignment for these structs */ +        sp &= ~3; +        sp = loader_build_fdpic_loadmap(info, sp); +        info->other_info = interp_info; +        if (interp_info) { +            interp_info->other_info = info; +            sp = loader_build_fdpic_loadmap(interp_info, sp); +        } +    } +#endif + +    u_platform = 0; +    k_platform = ELF_PLATFORM; +    if (k_platform) { +        size_t len = strlen(k_platform) + 1; +        sp -= (len + n - 1) & ~(n - 1); +        u_platform = sp; +        /* FIXME - check return value of memcpy_to_target() for failure */ +        memcpy_to_target(sp, k_platform, len); +    } + +    /* +     * Generate 16 random bytes for userspace PRNG seeding (not +     * cryptically secure but it's not the aim of QEMU). +     */ +    for (i = 0; i < 16; i++) { +        k_rand_bytes[i] = rand(); +    } +    sp -= 16; +    u_rand_bytes = sp; +    /* FIXME - check return value of memcpy_to_target() for failure */ +    memcpy_to_target(sp, k_rand_bytes, 16); + +    /* +     * Force 16 byte _final_ alignment here for generality. +     */ +    sp = sp &~ (abi_ulong)15; +    size = (DLINFO_ITEMS + 1) * 2; +    if (k_platform) +        size += 2; +#ifdef DLINFO_ARCH_ITEMS +    size += DLINFO_ARCH_ITEMS * 2; +#endif +#ifdef ELF_HWCAP2 +    size += 2; +#endif +    size += envc + argc + 2; +    size += 1;  /* argc itself */ +    size *= n; +    if (size & 15) +        sp -= 16 - (size & 15); + +    /* This is correct because Linux defines +     * elf_addr_t as Elf32_Off / Elf64_Off +     */ +#define NEW_AUX_ENT(id, val) do {               \ +        sp -= n; put_user_ual(val, sp);         \ +        sp -= n; put_user_ual(id, sp);          \ +    } while(0) + +    sp_auxv = sp; +    NEW_AUX_ENT (AT_NULL, 0); + +    /* There must be exactly DLINFO_ITEMS entries here.  */ +    NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff)); +    NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr))); +    NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum)); +    NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(MAX(TARGET_PAGE_SIZE, getpagesize()))); +    NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_info ? interp_info->load_addr : 0)); +    NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0); +    NEW_AUX_ENT(AT_ENTRY, info->entry); +    NEW_AUX_ENT(AT_UID, (abi_ulong) getuid()); +    NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid()); +    NEW_AUX_ENT(AT_GID, (abi_ulong) getgid()); +    NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid()); +    NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP); +    NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK)); +    NEW_AUX_ENT(AT_RANDOM, (abi_ulong) u_rand_bytes); + +#ifdef ELF_HWCAP2 +    NEW_AUX_ENT(AT_HWCAP2, (abi_ulong) ELF_HWCAP2); +#endif + +    if (k_platform) +        NEW_AUX_ENT(AT_PLATFORM, u_platform); +#ifdef ARCH_DLINFO +    /* +     * ARCH_DLINFO must come last so platform specific code can enforce +     * special alignment requirements on the AUXV if necessary (eg. PPC). +     */ +    ARCH_DLINFO; +#endif +#undef NEW_AUX_ENT + +    info->saved_auxv = sp; +    info->auxv_len = sp_auxv - sp; + +    sp = loader_build_argptr(envc, argc, sp, p, 0); +    /* Check the right amount of stack was allocated for auxvec, envp & argv. */ +    assert(sp_auxv - sp == size); +    return sp; +} + +#ifndef TARGET_HAS_VALIDATE_GUEST_SPACE +/* If the guest doesn't have a validation function just agree */ +static int validate_guest_space(unsigned long guest_base, +                                unsigned long guest_size) +{ +    return 1; +} +#endif + +unsigned long init_guest_space(unsigned long host_start, +                               unsigned long host_size, +                               unsigned long guest_start, +                               bool fixed) +{ +    unsigned long current_start, real_start; +    int flags; + +    assert(host_start || host_size); + +    /* If just a starting address is given, then just verify that +     * address.  */ +    if (host_start && !host_size) { +        if (validate_guest_space(host_start, host_size) == 1) { +            return host_start; +        } else { +            return (unsigned long)-1; +        } +    } + +    /* Setup the initial flags and start address.  */ +    current_start = host_start & qemu_host_page_mask; +    flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE; +    if (fixed) { +        flags |= MAP_FIXED; +    } + +    /* Otherwise, a non-zero size region of memory needs to be mapped +     * and validated.  */ +    while (1) { +        unsigned long real_size = host_size; + +        /* Do not use mmap_find_vma here because that is limited to the +         * guest address space.  We are going to make the +         * guest address space fit whatever we're given. +         */ +        real_start = (unsigned long) +            mmap((void *)current_start, host_size, PROT_NONE, flags, -1, 0); +        if (real_start == (unsigned long)-1) { +            return (unsigned long)-1; +        } + +        /* Ensure the address is properly aligned.  */ +        if (real_start & ~qemu_host_page_mask) { +            munmap((void *)real_start, host_size); +            real_size = host_size + qemu_host_page_size; +            real_start = (unsigned long) +                mmap((void *)real_start, real_size, PROT_NONE, flags, -1, 0); +            if (real_start == (unsigned long)-1) { +                return (unsigned long)-1; +            } +            real_start = HOST_PAGE_ALIGN(real_start); +        } + +        /* Check to see if the address is valid.  */ +        if (!host_start || real_start == current_start) { +            int valid = validate_guest_space(real_start - guest_start, +                                             real_size); +            if (valid == 1) { +                break; +            } else if (valid == -1) { +                return (unsigned long)-1; +            } +            /* valid == 0, so try again. */ +        } + +        /* That address didn't work.  Unmap and try a different one. +         * The address the host picked because is typically right at +         * the top of the host address space and leaves the guest with +         * no usable address space.  Resort to a linear search.  We +         * already compensated for mmap_min_addr, so this should not +         * happen often.  Probably means we got unlucky and host +         * address space randomization put a shared library somewhere +         * inconvenient. +         */ +        munmap((void *)real_start, host_size); +        current_start += qemu_host_page_size; +        if (host_start == current_start) { +            /* Theoretically possible if host doesn't have any suitably +             * aligned areas.  Normally the first mmap will fail. +             */ +            return (unsigned long)-1; +        } +    } + +    qemu_log("Reserved 0x%lx bytes of guest address space\n", host_size); + +    return real_start; +} + +static void probe_guest_base(const char *image_name, +                             abi_ulong loaddr, abi_ulong hiaddr) +{ +    /* Probe for a suitable guest base address, if the user has not set +     * it explicitly, and set guest_base appropriately. +     * In case of error we will print a suitable message and exit. +     */ +#if defined(CONFIG_USE_GUEST_BASE) +    const char *errmsg; +    if (!have_guest_base && !reserved_va) { +        unsigned long host_start, real_start, host_size; + +        /* Round addresses to page boundaries.  */ +        loaddr &= qemu_host_page_mask; +        hiaddr = HOST_PAGE_ALIGN(hiaddr); + +        if (loaddr < mmap_min_addr) { +            host_start = HOST_PAGE_ALIGN(mmap_min_addr); +        } else { +            host_start = loaddr; +            if (host_start != loaddr) { +                errmsg = "Address overflow loading ELF binary"; +                goto exit_errmsg; +            } +        } +        host_size = hiaddr - loaddr; + +        /* Setup the initial guest memory space with ranges gleaned from +         * the ELF image that is being loaded. +         */ +        real_start = init_guest_space(host_start, host_size, loaddr, false); +        if (real_start == (unsigned long)-1) { +            errmsg = "Unable to find space for application"; +            goto exit_errmsg; +        } +        guest_base = real_start - loaddr; + +        qemu_log("Relocating guest address space from 0x" +                 TARGET_ABI_FMT_lx " to 0x%lx\n", +                 loaddr, real_start); +    } +    return; + +exit_errmsg: +    fprintf(stderr, "%s: %s\n", image_name, errmsg); +    exit(-1); +#endif +} + + +/* Load an ELF image into the address space. + +   IMAGE_NAME is the filename of the image, to use in error messages. +   IMAGE_FD is the open file descriptor for the image. + +   BPRM_BUF is a copy of the beginning of the file; this of course +   contains the elf file header at offset 0.  It is assumed that this +   buffer is sufficiently aligned to present no problems to the host +   in accessing data at aligned offsets within the buffer. + +   On return: INFO values will be filled in, as necessary or available.  */ + +static void load_elf_image(const char *image_name, int image_fd, +                           struct image_info *info, char **pinterp_name, +                           char bprm_buf[BPRM_BUF_SIZE]) +{ +    struct elfhdr *ehdr = (struct elfhdr *)bprm_buf; +    struct elf_phdr *phdr; +    abi_ulong load_addr, load_bias, loaddr, hiaddr, error; +    int i, retval; +    const char *errmsg; + +    /* First of all, some simple consistency checks */ +    errmsg = "Invalid ELF image for this architecture"; +    if (!elf_check_ident(ehdr)) { +        goto exit_errmsg; +    } +    bswap_ehdr(ehdr); +    if (!elf_check_ehdr(ehdr)) { +        goto exit_errmsg; +    } + +    i = ehdr->e_phnum * sizeof(struct elf_phdr); +    if (ehdr->e_phoff + i <= BPRM_BUF_SIZE) { +        phdr = (struct elf_phdr *)(bprm_buf + ehdr->e_phoff); +    } else { +        phdr = (struct elf_phdr *) alloca(i); +        retval = pread(image_fd, phdr, i, ehdr->e_phoff); +        if (retval != i) { +            goto exit_read; +        } +    } +    bswap_phdr(phdr, ehdr->e_phnum); + +#ifdef CONFIG_USE_FDPIC +    info->nsegs = 0; +    info->pt_dynamic_addr = 0; +#endif + +    /* Find the maximum size of the image and allocate an appropriate +       amount of memory to handle that.  */ +    loaddr = -1, hiaddr = 0; +    for (i = 0; i < ehdr->e_phnum; ++i) { +        if (phdr[i].p_type == PT_LOAD) { +            abi_ulong a = phdr[i].p_vaddr - phdr[i].p_offset; +            if (a < loaddr) { +                loaddr = a; +            } +            a = phdr[i].p_vaddr + phdr[i].p_memsz; +            if (a > hiaddr) { +                hiaddr = a; +            } +#ifdef CONFIG_USE_FDPIC +            ++info->nsegs; +#endif +        } +    } + +    load_addr = loaddr; +    if (ehdr->e_type == ET_DYN) { +        /* The image indicates that it can be loaded anywhere.  Find a +           location that can hold the memory space required.  If the +           image is pre-linked, LOADDR will be non-zero.  Since we do +           not supply MAP_FIXED here we'll use that address if and +           only if it remains available.  */ +        load_addr = target_mmap(loaddr, hiaddr - loaddr, PROT_NONE, +                                MAP_PRIVATE | MAP_ANON | MAP_NORESERVE, +                                -1, 0); +        if (load_addr == -1) { +            goto exit_perror; +        } +    } else if (pinterp_name != NULL) { +        /* This is the main executable.  Make sure that the low +           address does not conflict with MMAP_MIN_ADDR or the +           QEMU application itself.  */ +        probe_guest_base(image_name, loaddr, hiaddr); +    } +    load_bias = load_addr - loaddr; + +#ifdef CONFIG_USE_FDPIC +    { +        struct elf32_fdpic_loadseg *loadsegs = info->loadsegs = +            g_malloc(sizeof(*loadsegs) * info->nsegs); + +        for (i = 0; i < ehdr->e_phnum; ++i) { +            switch (phdr[i].p_type) { +            case PT_DYNAMIC: +                info->pt_dynamic_addr = phdr[i].p_vaddr + load_bias; +                break; +            case PT_LOAD: +                loadsegs->addr = phdr[i].p_vaddr + load_bias; +                loadsegs->p_vaddr = phdr[i].p_vaddr; +                loadsegs->p_memsz = phdr[i].p_memsz; +                ++loadsegs; +                break; +            } +        } +    } +#endif + +    info->load_bias = load_bias; +    info->load_addr = load_addr; +    info->entry = ehdr->e_entry + load_bias; +    info->start_code = -1; +    info->end_code = 0; +    info->start_data = -1; +    info->end_data = 0; +    info->brk = 0; +    info->elf_flags = ehdr->e_flags; + +    for (i = 0; i < ehdr->e_phnum; i++) { +        struct elf_phdr *eppnt = phdr + i; +        if (eppnt->p_type == PT_LOAD) { +            abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em; +            int elf_prot = 0; + +            if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ; +            if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; +            if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; + +            vaddr = load_bias + eppnt->p_vaddr; +            vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr); +            vaddr_ps = TARGET_ELF_PAGESTART(vaddr); + +            error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po, +                                elf_prot, MAP_PRIVATE | MAP_FIXED, +                                image_fd, eppnt->p_offset - vaddr_po); +            if (error == -1) { +                goto exit_perror; +            } + +            vaddr_ef = vaddr + eppnt->p_filesz; +            vaddr_em = vaddr + eppnt->p_memsz; + +            /* If the load segment requests extra zeros (e.g. bss), map it.  */ +            if (vaddr_ef < vaddr_em) { +                zero_bss(vaddr_ef, vaddr_em, elf_prot); +            } + +            /* Find the full program boundaries.  */ +            if (elf_prot & PROT_EXEC) { +                if (vaddr < info->start_code) { +                    info->start_code = vaddr; +                } +                if (vaddr_ef > info->end_code) { +                    info->end_code = vaddr_ef; +                } +            } +            if (elf_prot & PROT_WRITE) { +                if (vaddr < info->start_data) { +                    info->start_data = vaddr; +                } +                if (vaddr_ef > info->end_data) { +                    info->end_data = vaddr_ef; +                } +                if (vaddr_em > info->brk) { +                    info->brk = vaddr_em; +                } +            } +        } else if (eppnt->p_type == PT_INTERP && pinterp_name) { +            char *interp_name; + +            if (*pinterp_name) { +                errmsg = "Multiple PT_INTERP entries"; +                goto exit_errmsg; +            } +            interp_name = malloc(eppnt->p_filesz); +            if (!interp_name) { +                goto exit_perror; +            } + +            if (eppnt->p_offset + eppnt->p_filesz <= BPRM_BUF_SIZE) { +                memcpy(interp_name, bprm_buf + eppnt->p_offset, +                       eppnt->p_filesz); +            } else { +                retval = pread(image_fd, interp_name, eppnt->p_filesz, +                               eppnt->p_offset); +                if (retval != eppnt->p_filesz) { +                    goto exit_perror; +                } +            } +            if (interp_name[eppnt->p_filesz - 1] != 0) { +                errmsg = "Invalid PT_INTERP entry"; +                goto exit_errmsg; +            } +            *pinterp_name = interp_name; +        } +    } + +    if (info->end_data == 0) { +        info->start_data = info->end_code; +        info->end_data = info->end_code; +        info->brk = info->end_code; +    } + +    if (qemu_log_enabled()) { +        load_symbols(ehdr, image_fd, load_bias); +    } + +    close(image_fd); +    return; + + exit_read: +    if (retval >= 0) { +        errmsg = "Incomplete read of file header"; +        goto exit_errmsg; +    } + exit_perror: +    errmsg = strerror(errno); + exit_errmsg: +    fprintf(stderr, "%s: %s\n", image_name, errmsg); +    exit(-1); +} + +static void load_elf_interp(const char *filename, struct image_info *info, +                            char bprm_buf[BPRM_BUF_SIZE]) +{ +    int fd, retval; + +    fd = open(path(filename), O_RDONLY); +    if (fd < 0) { +        goto exit_perror; +    } + +    retval = read(fd, bprm_buf, BPRM_BUF_SIZE); +    if (retval < 0) { +        goto exit_perror; +    } +    if (retval < BPRM_BUF_SIZE) { +        memset(bprm_buf + retval, 0, BPRM_BUF_SIZE - retval); +    } + +    load_elf_image(filename, fd, info, NULL, bprm_buf); +    return; + + exit_perror: +    fprintf(stderr, "%s: %s\n", filename, strerror(errno)); +    exit(-1); +} + +static int symfind(const void *s0, const void *s1) +{ +    target_ulong addr = *(target_ulong *)s0; +    struct elf_sym *sym = (struct elf_sym *)s1; +    int result = 0; +    if (addr < sym->st_value) { +        result = -1; +    } else if (addr >= sym->st_value + sym->st_size) { +        result = 1; +    } +    return result; +} + +static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr) +{ +#if ELF_CLASS == ELFCLASS32 +    struct elf_sym *syms = s->disas_symtab.elf32; +#else +    struct elf_sym *syms = s->disas_symtab.elf64; +#endif + +    // binary search +    struct elf_sym *sym; + +    sym = bsearch(&orig_addr, syms, s->disas_num_syms, sizeof(*syms), symfind); +    if (sym != NULL) { +        return s->disas_strtab + sym->st_name; +    } + +    return ""; +} + +/* FIXME: This should use elf_ops.h  */ +static int symcmp(const void *s0, const void *s1) +{ +    struct elf_sym *sym0 = (struct elf_sym *)s0; +    struct elf_sym *sym1 = (struct elf_sym *)s1; +    return (sym0->st_value < sym1->st_value) +        ? -1 +        : ((sym0->st_value > sym1->st_value) ? 1 : 0); +} + +/* Best attempt to load symbols from this ELF object. */ +static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias) +{ +    int i, shnum, nsyms, sym_idx = 0, str_idx = 0; +    struct elf_shdr *shdr; +    char *strings = NULL; +    struct syminfo *s = NULL; +    struct elf_sym *new_syms, *syms = NULL; + +    shnum = hdr->e_shnum; +    i = shnum * sizeof(struct elf_shdr); +    shdr = (struct elf_shdr *)alloca(i); +    if (pread(fd, shdr, i, hdr->e_shoff) != i) { +        return; +    } + +    bswap_shdr(shdr, shnum); +    for (i = 0; i < shnum; ++i) { +        if (shdr[i].sh_type == SHT_SYMTAB) { +            sym_idx = i; +            str_idx = shdr[i].sh_link; +            goto found; +        } +    } + +    /* There will be no symbol table if the file was stripped.  */ +    return; + + found: +    /* Now know where the strtab and symtab are.  Snarf them.  */ +    s = malloc(sizeof(*s)); +    if (!s) { +        goto give_up; +    } + +    i = shdr[str_idx].sh_size; +    s->disas_strtab = strings = malloc(i); +    if (!strings || pread(fd, strings, i, shdr[str_idx].sh_offset) != i) { +        goto give_up; +    } + +    i = shdr[sym_idx].sh_size; +    syms = malloc(i); +    if (!syms || pread(fd, syms, i, shdr[sym_idx].sh_offset) != i) { +        goto give_up; +    } + +    nsyms = i / sizeof(struct elf_sym); +    for (i = 0; i < nsyms; ) { +        bswap_sym(syms + i); +        /* Throw away entries which we do not need.  */ +        if (syms[i].st_shndx == SHN_UNDEF +            || syms[i].st_shndx >= SHN_LORESERVE +            || ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) { +            if (i < --nsyms) { +                syms[i] = syms[nsyms]; +            } +        } else { +#if defined(TARGET_ARM) || defined (TARGET_MIPS) +            /* The bottom address bit marks a Thumb or MIPS16 symbol.  */ +            syms[i].st_value &= ~(target_ulong)1; +#endif +            syms[i].st_value += load_bias; +            i++; +        } +    } + +    /* No "useful" symbol.  */ +    if (nsyms == 0) { +        goto give_up; +    } + +    /* Attempt to free the storage associated with the local symbols +       that we threw away.  Whether or not this has any effect on the +       memory allocation depends on the malloc implementation and how +       many symbols we managed to discard.  */ +    new_syms = realloc(syms, nsyms * sizeof(*syms)); +    if (new_syms == NULL) { +        goto give_up; +    } +    syms = new_syms; + +    qsort(syms, nsyms, sizeof(*syms), symcmp); + +    s->disas_num_syms = nsyms; +#if ELF_CLASS == ELFCLASS32 +    s->disas_symtab.elf32 = syms; +#else +    s->disas_symtab.elf64 = syms; +#endif +    s->lookup_symbol = lookup_symbolxx; +    s->next = syminfos; +    syminfos = s; + +    return; + +give_up: +    free(s); +    free(strings); +    free(syms); +} + +int load_elf_binary(struct linux_binprm *bprm, struct image_info *info) +{ +    struct image_info interp_info; +    struct elfhdr elf_ex; +    char *elf_interpreter = NULL; + +    info->start_mmap = (abi_ulong)ELF_START_MMAP; +    info->mmap = 0; +    info->rss = 0; + +    load_elf_image(bprm->filename, bprm->fd, info, +                   &elf_interpreter, bprm->buf); + +    /* ??? We need a copy of the elf header for passing to create_elf_tables. +       If we do nothing, we'll have overwritten this when we re-use bprm->buf +       when we load the interpreter.  */ +    elf_ex = *(struct elfhdr *)bprm->buf; + +    bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p); +    bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p); +    bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p); +    if (!bprm->p) { +        fprintf(stderr, "%s: %s\n", bprm->filename, strerror(E2BIG)); +        exit(-1); +    } + +    /* Do this so that we can load the interpreter, if need be.  We will +       change some of these later */ +    bprm->p = setup_arg_pages(bprm->p, bprm, info); + +    if (elf_interpreter) { +        load_elf_interp(elf_interpreter, &interp_info, bprm->buf); + +        /* If the program interpreter is one of these two, then assume +           an iBCS2 image.  Otherwise assume a native linux image.  */ + +        if (strcmp(elf_interpreter, "/usr/lib/libc.so.1") == 0 +            || strcmp(elf_interpreter, "/usr/lib/ld.so.1") == 0) { +            info->personality = PER_SVR4; + +            /* Why this, you ask???  Well SVr4 maps page 0 as read-only, +               and some applications "depend" upon this behavior.  Since +               we do not have the power to recompile these, we emulate +               the SVr4 behavior.  Sigh.  */ +            target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC, +                        MAP_FIXED | MAP_PRIVATE, -1, 0); +        } +    } + +    bprm->p = create_elf_tables(bprm->p, bprm->argc, bprm->envc, &elf_ex, +                                info, (elf_interpreter ? &interp_info : NULL)); +    info->start_stack = bprm->p; + +    /* If we have an interpreter, set that as the program's entry point. +       Copy the load_bias as well, to help PPC64 interpret the entry +       point as a function descriptor.  Do this after creating elf tables +       so that we copy the original program entry point into the AUXV.  */ +    if (elf_interpreter) { +        info->load_bias = interp_info.load_bias; +        info->entry = interp_info.entry; +        free(elf_interpreter); +    } + +#ifdef USE_ELF_CORE_DUMP +    bprm->core_dump = &elf_core_dump; +#endif + +    return 0; +} + +#ifdef USE_ELF_CORE_DUMP +/* + * Definitions to generate Intel SVR4-like core files. + * These mostly have the same names as the SVR4 types with "target_elf_" + * tacked on the front to prevent clashes with linux definitions, + * and the typedef forms have been avoided.  This is mostly like + * the SVR4 structure, but more Linuxy, with things that Linux does + * not support and which gdb doesn't really use excluded. + * + * Fields we don't dump (their contents is zero) in linux-user qemu + * are marked with XXX. + * + * Core dump code is copied from linux kernel (fs/binfmt_elf.c). + * + * Porting ELF coredump for target is (quite) simple process.  First you + * define USE_ELF_CORE_DUMP in target ELF code (where init_thread() for + * the target resides): + * + * #define USE_ELF_CORE_DUMP + * + * Next you define type of register set used for dumping.  ELF specification + * says that it needs to be array of elf_greg_t that has size of ELF_NREG. + * + * typedef <target_regtype> target_elf_greg_t; + * #define ELF_NREG <number of registers> + * typedef taret_elf_greg_t target_elf_gregset_t[ELF_NREG]; + * + * Last step is to implement target specific function that copies registers + * from given cpu into just specified register set.  Prototype is: + * + * static void elf_core_copy_regs(taret_elf_gregset_t *regs, + *                                const CPUArchState *env); + * + * Parameters: + *     regs - copy register values into here (allocated and zeroed by caller) + *     env - copy registers from here + * + * Example for ARM target is provided in this file. + */ + +/* An ELF note in memory */ +struct memelfnote { +    const char *name; +    size_t     namesz; +    size_t     namesz_rounded; +    int        type; +    size_t     datasz; +    size_t     datasz_rounded; +    void       *data; +    size_t     notesz; +}; + +struct target_elf_siginfo { +    abi_int    si_signo; /* signal number */ +    abi_int    si_code;  /* extra code */ +    abi_int    si_errno; /* errno */ +}; + +struct target_elf_prstatus { +    struct target_elf_siginfo pr_info;      /* Info associated with signal */ +    abi_short          pr_cursig;    /* Current signal */ +    abi_ulong          pr_sigpend;   /* XXX */ +    abi_ulong          pr_sighold;   /* XXX */ +    target_pid_t       pr_pid; +    target_pid_t       pr_ppid; +    target_pid_t       pr_pgrp; +    target_pid_t       pr_sid; +    struct target_timeval pr_utime;  /* XXX User time */ +    struct target_timeval pr_stime;  /* XXX System time */ +    struct target_timeval pr_cutime; /* XXX Cumulative user time */ +    struct target_timeval pr_cstime; /* XXX Cumulative system time */ +    target_elf_gregset_t      pr_reg;       /* GP registers */ +    abi_int            pr_fpvalid;   /* XXX */ +}; + +#define ELF_PRARGSZ     (80) /* Number of chars for args */ + +struct target_elf_prpsinfo { +    char         pr_state;       /* numeric process state */ +    char         pr_sname;       /* char for pr_state */ +    char         pr_zomb;        /* zombie */ +    char         pr_nice;        /* nice val */ +    abi_ulong    pr_flag;        /* flags */ +    target_uid_t pr_uid; +    target_gid_t pr_gid; +    target_pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid; +    /* Lots missing */ +    char    pr_fname[16];           /* filename of executable */ +    char    pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ +}; + +/* Here is the structure in which status of each thread is captured. */ +struct elf_thread_status { +    QTAILQ_ENTRY(elf_thread_status)  ets_link; +    struct target_elf_prstatus prstatus;   /* NT_PRSTATUS */ +#if 0 +    elf_fpregset_t fpu;             /* NT_PRFPREG */ +    struct task_struct *thread; +    elf_fpxregset_t xfpu;           /* ELF_CORE_XFPREG_TYPE */ +#endif +    struct memelfnote notes[1]; +    int num_notes; +}; + +struct elf_note_info { +    struct memelfnote   *notes; +    struct target_elf_prstatus *prstatus;  /* NT_PRSTATUS */ +    struct target_elf_prpsinfo *psinfo;    /* NT_PRPSINFO */ + +    QTAILQ_HEAD(thread_list_head, elf_thread_status) thread_list; +#if 0 +    /* +     * Current version of ELF coredump doesn't support +     * dumping fp regs etc. +     */ +    elf_fpregset_t *fpu; +    elf_fpxregset_t *xfpu; +    int thread_status_size; +#endif +    int notes_size; +    int numnote; +}; + +struct vm_area_struct { +    target_ulong   vma_start;  /* start vaddr of memory region */ +    target_ulong   vma_end;    /* end vaddr of memory region */ +    abi_ulong      vma_flags;  /* protection etc. flags for the region */ +    QTAILQ_ENTRY(vm_area_struct) vma_link; +}; + +struct mm_struct { +    QTAILQ_HEAD(, vm_area_struct) mm_mmap; +    int mm_count;           /* number of mappings */ +}; + +static struct mm_struct *vma_init(void); +static void vma_delete(struct mm_struct *); +static int vma_add_mapping(struct mm_struct *, target_ulong, +                           target_ulong, abi_ulong); +static int vma_get_mapping_count(const struct mm_struct *); +static struct vm_area_struct *vma_first(const struct mm_struct *); +static struct vm_area_struct *vma_next(struct vm_area_struct *); +static abi_ulong vma_dump_size(const struct vm_area_struct *); +static int vma_walker(void *priv, target_ulong start, target_ulong end, +                      unsigned long flags); + +static void fill_elf_header(struct elfhdr *, int, uint16_t, uint32_t); +static void fill_note(struct memelfnote *, const char *, int, +                      unsigned int, void *); +static void fill_prstatus(struct target_elf_prstatus *, const TaskState *, int); +static int fill_psinfo(struct target_elf_prpsinfo *, const TaskState *); +static void fill_auxv_note(struct memelfnote *, const TaskState *); +static void fill_elf_note_phdr(struct elf_phdr *, int, off_t); +static size_t note_size(const struct memelfnote *); +static void free_note_info(struct elf_note_info *); +static int fill_note_info(struct elf_note_info *, long, const CPUArchState *); +static void fill_thread_info(struct elf_note_info *, const CPUArchState *); +static int core_dump_filename(const TaskState *, char *, size_t); + +static int dump_write(int, const void *, size_t); +static int write_note(struct memelfnote *, int); +static int write_note_info(struct elf_note_info *, int); + +#ifdef BSWAP_NEEDED +static void bswap_prstatus(struct target_elf_prstatus *prstatus) +{ +    prstatus->pr_info.si_signo = tswap32(prstatus->pr_info.si_signo); +    prstatus->pr_info.si_code = tswap32(prstatus->pr_info.si_code); +    prstatus->pr_info.si_errno = tswap32(prstatus->pr_info.si_errno); +    prstatus->pr_cursig = tswap16(prstatus->pr_cursig); +    prstatus->pr_sigpend = tswapal(prstatus->pr_sigpend); +    prstatus->pr_sighold = tswapal(prstatus->pr_sighold); +    prstatus->pr_pid = tswap32(prstatus->pr_pid); +    prstatus->pr_ppid = tswap32(prstatus->pr_ppid); +    prstatus->pr_pgrp = tswap32(prstatus->pr_pgrp); +    prstatus->pr_sid = tswap32(prstatus->pr_sid); +    /* cpu times are not filled, so we skip them */ +    /* regs should be in correct format already */ +    prstatus->pr_fpvalid = tswap32(prstatus->pr_fpvalid); +} + +static void bswap_psinfo(struct target_elf_prpsinfo *psinfo) +{ +    psinfo->pr_flag = tswapal(psinfo->pr_flag); +    psinfo->pr_uid = tswap16(psinfo->pr_uid); +    psinfo->pr_gid = tswap16(psinfo->pr_gid); +    psinfo->pr_pid = tswap32(psinfo->pr_pid); +    psinfo->pr_ppid = tswap32(psinfo->pr_ppid); +    psinfo->pr_pgrp = tswap32(psinfo->pr_pgrp); +    psinfo->pr_sid = tswap32(psinfo->pr_sid); +} + +static void bswap_note(struct elf_note *en) +{ +    bswap32s(&en->n_namesz); +    bswap32s(&en->n_descsz); +    bswap32s(&en->n_type); +} +#else +static inline void bswap_prstatus(struct target_elf_prstatus *p) { } +static inline void bswap_psinfo(struct target_elf_prpsinfo *p) {} +static inline void bswap_note(struct elf_note *en) { } +#endif /* BSWAP_NEEDED */ + +/* + * Minimal support for linux memory regions.  These are needed + * when we are finding out what memory exactly belongs to + * emulated process.  No locks needed here, as long as + * thread that received the signal is stopped. + */ + +static struct mm_struct *vma_init(void) +{ +    struct mm_struct *mm; + +    if ((mm = g_malloc(sizeof (*mm))) == NULL) +        return (NULL); + +    mm->mm_count = 0; +    QTAILQ_INIT(&mm->mm_mmap); + +    return (mm); +} + +static void vma_delete(struct mm_struct *mm) +{ +    struct vm_area_struct *vma; + +    while ((vma = vma_first(mm)) != NULL) { +        QTAILQ_REMOVE(&mm->mm_mmap, vma, vma_link); +        g_free(vma); +    } +    g_free(mm); +} + +static int vma_add_mapping(struct mm_struct *mm, target_ulong start, +                           target_ulong end, abi_ulong flags) +{ +    struct vm_area_struct *vma; + +    if ((vma = g_malloc0(sizeof (*vma))) == NULL) +        return (-1); + +    vma->vma_start = start; +    vma->vma_end = end; +    vma->vma_flags = flags; + +    QTAILQ_INSERT_TAIL(&mm->mm_mmap, vma, vma_link); +    mm->mm_count++; + +    return (0); +} + +static struct vm_area_struct *vma_first(const struct mm_struct *mm) +{ +    return (QTAILQ_FIRST(&mm->mm_mmap)); +} + +static struct vm_area_struct *vma_next(struct vm_area_struct *vma) +{ +    return (QTAILQ_NEXT(vma, vma_link)); +} + +static int vma_get_mapping_count(const struct mm_struct *mm) +{ +    return (mm->mm_count); +} + +/* + * Calculate file (dump) size of given memory region. + */ +static abi_ulong vma_dump_size(const struct vm_area_struct *vma) +{ +    /* if we cannot even read the first page, skip it */ +    if (!access_ok(VERIFY_READ, vma->vma_start, TARGET_PAGE_SIZE)) +        return (0); + +    /* +     * Usually we don't dump executable pages as they contain +     * non-writable code that debugger can read directly from +     * target library etc.  However, thread stacks are marked +     * also executable so we read in first page of given region +     * and check whether it contains elf header.  If there is +     * no elf header, we dump it. +     */ +    if (vma->vma_flags & PROT_EXEC) { +        char page[TARGET_PAGE_SIZE]; + +        copy_from_user(page, vma->vma_start, sizeof (page)); +        if ((page[EI_MAG0] == ELFMAG0) && +            (page[EI_MAG1] == ELFMAG1) && +            (page[EI_MAG2] == ELFMAG2) && +            (page[EI_MAG3] == ELFMAG3)) { +            /* +             * Mappings are possibly from ELF binary.  Don't dump +             * them. +             */ +            return (0); +        } +    } + +    return (vma->vma_end - vma->vma_start); +} + +static int vma_walker(void *priv, target_ulong start, target_ulong end, +                      unsigned long flags) +{ +    struct mm_struct *mm = (struct mm_struct *)priv; + +    vma_add_mapping(mm, start, end, flags); +    return (0); +} + +static void fill_note(struct memelfnote *note, const char *name, int type, +                      unsigned int sz, void *data) +{ +    unsigned int namesz; + +    namesz = strlen(name) + 1; +    note->name = name; +    note->namesz = namesz; +    note->namesz_rounded = roundup(namesz, sizeof (int32_t)); +    note->type = type; +    note->datasz = sz; +    note->datasz_rounded = roundup(sz, sizeof (int32_t)); + +    note->data = data; + +    /* +     * We calculate rounded up note size here as specified by +     * ELF document. +     */ +    note->notesz = sizeof (struct elf_note) + +        note->namesz_rounded + note->datasz_rounded; +} + +static void fill_elf_header(struct elfhdr *elf, int segs, uint16_t machine, +                            uint32_t flags) +{ +    (void) memset(elf, 0, sizeof(*elf)); + +    (void) memcpy(elf->e_ident, ELFMAG, SELFMAG); +    elf->e_ident[EI_CLASS] = ELF_CLASS; +    elf->e_ident[EI_DATA] = ELF_DATA; +    elf->e_ident[EI_VERSION] = EV_CURRENT; +    elf->e_ident[EI_OSABI] = ELF_OSABI; + +    elf->e_type = ET_CORE; +    elf->e_machine = machine; +    elf->e_version = EV_CURRENT; +    elf->e_phoff = sizeof(struct elfhdr); +    elf->e_flags = flags; +    elf->e_ehsize = sizeof(struct elfhdr); +    elf->e_phentsize = sizeof(struct elf_phdr); +    elf->e_phnum = segs; + +    bswap_ehdr(elf); +} + +static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, off_t offset) +{ +    phdr->p_type = PT_NOTE; +    phdr->p_offset = offset; +    phdr->p_vaddr = 0; +    phdr->p_paddr = 0; +    phdr->p_filesz = sz; +    phdr->p_memsz = 0; +    phdr->p_flags = 0; +    phdr->p_align = 0; + +    bswap_phdr(phdr, 1); +} + +static size_t note_size(const struct memelfnote *note) +{ +    return (note->notesz); +} + +static void fill_prstatus(struct target_elf_prstatus *prstatus, +                          const TaskState *ts, int signr) +{ +    (void) memset(prstatus, 0, sizeof (*prstatus)); +    prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; +    prstatus->pr_pid = ts->ts_tid; +    prstatus->pr_ppid = getppid(); +    prstatus->pr_pgrp = getpgrp(); +    prstatus->pr_sid = getsid(0); + +    bswap_prstatus(prstatus); +} + +static int fill_psinfo(struct target_elf_prpsinfo *psinfo, const TaskState *ts) +{ +    char *base_filename; +    unsigned int i, len; + +    (void) memset(psinfo, 0, sizeof (*psinfo)); + +    len = ts->info->arg_end - ts->info->arg_start; +    if (len >= ELF_PRARGSZ) +        len = ELF_PRARGSZ - 1; +    if (copy_from_user(&psinfo->pr_psargs, ts->info->arg_start, len)) +        return -EFAULT; +    for (i = 0; i < len; i++) +        if (psinfo->pr_psargs[i] == 0) +            psinfo->pr_psargs[i] = ' '; +    psinfo->pr_psargs[len] = 0; + +    psinfo->pr_pid = getpid(); +    psinfo->pr_ppid = getppid(); +    psinfo->pr_pgrp = getpgrp(); +    psinfo->pr_sid = getsid(0); +    psinfo->pr_uid = getuid(); +    psinfo->pr_gid = getgid(); + +    base_filename = g_path_get_basename(ts->bprm->filename); +    /* +     * Using strncpy here is fine: at max-length, +     * this field is not NUL-terminated. +     */ +    (void) strncpy(psinfo->pr_fname, base_filename, +                   sizeof(psinfo->pr_fname)); + +    g_free(base_filename); +    bswap_psinfo(psinfo); +    return (0); +} + +static void fill_auxv_note(struct memelfnote *note, const TaskState *ts) +{ +    elf_addr_t auxv = (elf_addr_t)ts->info->saved_auxv; +    elf_addr_t orig_auxv = auxv; +    void *ptr; +    int len = ts->info->auxv_len; + +    /* +     * Auxiliary vector is stored in target process stack.  It contains +     * {type, value} pairs that we need to dump into note.  This is not +     * strictly necessary but we do it here for sake of completeness. +     */ + +    /* read in whole auxv vector and copy it to memelfnote */ +    ptr = lock_user(VERIFY_READ, orig_auxv, len, 0); +    if (ptr != NULL) { +        fill_note(note, "CORE", NT_AUXV, len, ptr); +        unlock_user(ptr, auxv, len); +    } +} + +/* + * Constructs name of coredump file.  We have following convention + * for the name: + *     qemu_<basename-of-target-binary>_<date>-<time>_<pid>.core + * + * Returns 0 in case of success, -1 otherwise (errno is set). + */ +static int core_dump_filename(const TaskState *ts, char *buf, +                              size_t bufsize) +{ +    char timestamp[64]; +    char *filename = NULL; +    char *base_filename = NULL; +    struct timeval tv; +    struct tm tm; + +    assert(bufsize >= PATH_MAX); + +    if (gettimeofday(&tv, NULL) < 0) { +        (void) fprintf(stderr, "unable to get current timestamp: %s", +                       strerror(errno)); +        return (-1); +    } + +    filename = strdup(ts->bprm->filename); +    base_filename = strdup(basename(filename)); +    (void) strftime(timestamp, sizeof (timestamp), "%Y%m%d-%H%M%S", +                    localtime_r(&tv.tv_sec, &tm)); +    (void) snprintf(buf, bufsize, "qemu_%s_%s_%d.core", +                    base_filename, timestamp, (int)getpid()); +    free(base_filename); +    free(filename); + +    return (0); +} + +static int dump_write(int fd, const void *ptr, size_t size) +{ +    const char *bufp = (const char *)ptr; +    ssize_t bytes_written, bytes_left; +    struct rlimit dumpsize; +    off_t pos; + +    bytes_written = 0; +    getrlimit(RLIMIT_CORE, &dumpsize); +    if ((pos = lseek(fd, 0, SEEK_CUR))==-1) { +        if (errno == ESPIPE) { /* not a seekable stream */ +            bytes_left = size; +        } else { +            return pos; +        } +    } else { +        if (dumpsize.rlim_cur <= pos) { +            return -1; +        } else if (dumpsize.rlim_cur == RLIM_INFINITY) { +            bytes_left = size; +        } else { +            size_t limit_left=dumpsize.rlim_cur - pos; +            bytes_left = limit_left >= size ? size : limit_left ; +        } +    } + +    /* +     * In normal conditions, single write(2) should do but +     * in case of socket etc. this mechanism is more portable. +     */ +    do { +        bytes_written = write(fd, bufp, bytes_left); +        if (bytes_written < 0) { +            if (errno == EINTR) +                continue; +            return (-1); +        } else if (bytes_written == 0) { /* eof */ +            return (-1); +        } +        bufp += bytes_written; +        bytes_left -= bytes_written; +    } while (bytes_left > 0); + +    return (0); +} + +static int write_note(struct memelfnote *men, int fd) +{ +    struct elf_note en; + +    en.n_namesz = men->namesz; +    en.n_type = men->type; +    en.n_descsz = men->datasz; + +    bswap_note(&en); + +    if (dump_write(fd, &en, sizeof(en)) != 0) +        return (-1); +    if (dump_write(fd, men->name, men->namesz_rounded) != 0) +        return (-1); +    if (dump_write(fd, men->data, men->datasz_rounded) != 0) +        return (-1); + +    return (0); +} + +static void fill_thread_info(struct elf_note_info *info, const CPUArchState *env) +{ +    CPUState *cpu = ENV_GET_CPU((CPUArchState *)env); +    TaskState *ts = (TaskState *)cpu->opaque; +    struct elf_thread_status *ets; + +    ets = g_malloc0(sizeof (*ets)); +    ets->num_notes = 1; /* only prstatus is dumped */ +    fill_prstatus(&ets->prstatus, ts, 0); +    elf_core_copy_regs(&ets->prstatus.pr_reg, env); +    fill_note(&ets->notes[0], "CORE", NT_PRSTATUS, sizeof (ets->prstatus), +              &ets->prstatus); + +    QTAILQ_INSERT_TAIL(&info->thread_list, ets, ets_link); + +    info->notes_size += note_size(&ets->notes[0]); +} + +static void init_note_info(struct elf_note_info *info) +{ +    /* Initialize the elf_note_info structure so that it is at +     * least safe to call free_note_info() on it. Must be +     * called before calling fill_note_info(). +     */ +    memset(info, 0, sizeof (*info)); +    QTAILQ_INIT(&info->thread_list); +} + +static int fill_note_info(struct elf_note_info *info, +                          long signr, const CPUArchState *env) +{ +#define NUMNOTES 3 +    CPUState *cpu = ENV_GET_CPU((CPUArchState *)env); +    TaskState *ts = (TaskState *)cpu->opaque; +    int i; + +    info->notes = g_malloc0(NUMNOTES * sizeof (struct memelfnote)); +    if (info->notes == NULL) +        return (-ENOMEM); +    info->prstatus = g_malloc0(sizeof (*info->prstatus)); +    if (info->prstatus == NULL) +        return (-ENOMEM); +    info->psinfo = g_malloc0(sizeof (*info->psinfo)); +    if (info->prstatus == NULL) +        return (-ENOMEM); + +    /* +     * First fill in status (and registers) of current thread +     * including process info & aux vector. +     */ +    fill_prstatus(info->prstatus, ts, signr); +    elf_core_copy_regs(&info->prstatus->pr_reg, env); +    fill_note(&info->notes[0], "CORE", NT_PRSTATUS, +              sizeof (*info->prstatus), info->prstatus); +    fill_psinfo(info->psinfo, ts); +    fill_note(&info->notes[1], "CORE", NT_PRPSINFO, +              sizeof (*info->psinfo), info->psinfo); +    fill_auxv_note(&info->notes[2], ts); +    info->numnote = 3; + +    info->notes_size = 0; +    for (i = 0; i < info->numnote; i++) +        info->notes_size += note_size(&info->notes[i]); + +    /* read and fill status of all threads */ +    cpu_list_lock(); +    CPU_FOREACH(cpu) { +        if (cpu == thread_cpu) { +            continue; +        } +        fill_thread_info(info, (CPUArchState *)cpu->env_ptr); +    } +    cpu_list_unlock(); + +    return (0); +} + +static void free_note_info(struct elf_note_info *info) +{ +    struct elf_thread_status *ets; + +    while (!QTAILQ_EMPTY(&info->thread_list)) { +        ets = QTAILQ_FIRST(&info->thread_list); +        QTAILQ_REMOVE(&info->thread_list, ets, ets_link); +        g_free(ets); +    } + +    g_free(info->prstatus); +    g_free(info->psinfo); +    g_free(info->notes); +} + +static int write_note_info(struct elf_note_info *info, int fd) +{ +    struct elf_thread_status *ets; +    int i, error = 0; + +    /* write prstatus, psinfo and auxv for current thread */ +    for (i = 0; i < info->numnote; i++) +        if ((error = write_note(&info->notes[i], fd)) != 0) +            return (error); + +    /* write prstatus for each thread */ +    QTAILQ_FOREACH(ets, &info->thread_list, ets_link) { +        if ((error = write_note(&ets->notes[0], fd)) != 0) +            return (error); +    } + +    return (0); +} + +/* + * Write out ELF coredump. + * + * See documentation of ELF object file format in: + * http://www.caldera.com/developers/devspecs/gabi41.pdf + * + * Coredump format in linux is following: + * + * 0   +----------------------+         \ + *     | ELF header           | ET_CORE  | + *     +----------------------+          | + *     | ELF program headers  |          |--- headers + *     | - NOTE section       |          | + *     | - PT_LOAD sections   |          | + *     +----------------------+         / + *     | NOTEs:               | + *     | - NT_PRSTATUS        | + *     | - NT_PRSINFO         | + *     | - NT_AUXV            | + *     +----------------------+ <-- aligned to target page + *     | Process memory dump  | + *     :                      : + *     .                      . + *     :                      : + *     |                      | + *     +----------------------+ + * + * NT_PRSTATUS -> struct elf_prstatus (per thread) + * NT_PRSINFO  -> struct elf_prpsinfo + * NT_AUXV is array of { type, value } pairs (see fill_auxv_note()). + * + * Format follows System V format as close as possible.  Current + * version limitations are as follows: + *     - no floating point registers are dumped + * + * Function returns 0 in case of success, negative errno otherwise. + * + * TODO: make this work also during runtime: it should be + * possible to force coredump from running process and then + * continue processing.  For example qemu could set up SIGUSR2 + * handler (provided that target process haven't registered + * handler for that) that does the dump when signal is received. + */ +static int elf_core_dump(int signr, const CPUArchState *env) +{ +    const CPUState *cpu = ENV_GET_CPU((CPUArchState *)env); +    const TaskState *ts = (const TaskState *)cpu->opaque; +    struct vm_area_struct *vma = NULL; +    char corefile[PATH_MAX]; +    struct elf_note_info info; +    struct elfhdr elf; +    struct elf_phdr phdr; +    struct rlimit dumpsize; +    struct mm_struct *mm = NULL; +    off_t offset = 0, data_offset = 0; +    int segs = 0; +    int fd = -1; + +    init_note_info(&info); + +    errno = 0; +    getrlimit(RLIMIT_CORE, &dumpsize); +    if (dumpsize.rlim_cur == 0) +        return 0; + +    if (core_dump_filename(ts, corefile, sizeof (corefile)) < 0) +        return (-errno); + +    if ((fd = open(corefile, O_WRONLY | O_CREAT, +                   S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) +        return (-errno); + +    /* +     * Walk through target process memory mappings and +     * set up structure containing this information.  After +     * this point vma_xxx functions can be used. +     */ +    if ((mm = vma_init()) == NULL) +        goto out; + +    walk_memory_regions(mm, vma_walker); +    segs = vma_get_mapping_count(mm); + +    /* +     * Construct valid coredump ELF header.  We also +     * add one more segment for notes. +     */ +    fill_elf_header(&elf, segs + 1, ELF_MACHINE, 0); +    if (dump_write(fd, &elf, sizeof (elf)) != 0) +        goto out; + +    /* fill in in-memory version of notes */ +    if (fill_note_info(&info, signr, env) < 0) +        goto out; + +    offset += sizeof (elf);                             /* elf header */ +    offset += (segs + 1) * sizeof (struct elf_phdr);    /* program headers */ + +    /* write out notes program header */ +    fill_elf_note_phdr(&phdr, info.notes_size, offset); + +    offset += info.notes_size; +    if (dump_write(fd, &phdr, sizeof (phdr)) != 0) +        goto out; + +    /* +     * ELF specification wants data to start at page boundary so +     * we align it here. +     */ +    data_offset = offset = roundup(offset, ELF_EXEC_PAGESIZE); + +    /* +     * Write program headers for memory regions mapped in +     * the target process. +     */ +    for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) { +        (void) memset(&phdr, 0, sizeof (phdr)); + +        phdr.p_type = PT_LOAD; +        phdr.p_offset = offset; +        phdr.p_vaddr = vma->vma_start; +        phdr.p_paddr = 0; +        phdr.p_filesz = vma_dump_size(vma); +        offset += phdr.p_filesz; +        phdr.p_memsz = vma->vma_end - vma->vma_start; +        phdr.p_flags = vma->vma_flags & PROT_READ ? PF_R : 0; +        if (vma->vma_flags & PROT_WRITE) +            phdr.p_flags |= PF_W; +        if (vma->vma_flags & PROT_EXEC) +            phdr.p_flags |= PF_X; +        phdr.p_align = ELF_EXEC_PAGESIZE; + +        bswap_phdr(&phdr, 1); +        dump_write(fd, &phdr, sizeof (phdr)); +    } + +    /* +     * Next we write notes just after program headers.  No +     * alignment needed here. +     */ +    if (write_note_info(&info, fd) < 0) +        goto out; + +    /* align data to page boundary */ +    if (lseek(fd, data_offset, SEEK_SET) != data_offset) +        goto out; + +    /* +     * Finally we can dump process memory into corefile as well. +     */ +    for (vma = vma_first(mm); vma != NULL; vma = vma_next(vma)) { +        abi_ulong addr; +        abi_ulong end; + +        end = vma->vma_start + vma_dump_size(vma); + +        for (addr = vma->vma_start; addr < end; +             addr += TARGET_PAGE_SIZE) { +            char page[TARGET_PAGE_SIZE]; +            int error; + +            /* +             *  Read in page from target process memory and +             *  write it to coredump file. +             */ +            error = copy_from_user(page, addr, sizeof (page)); +            if (error != 0) { +                (void) fprintf(stderr, "unable to dump " TARGET_ABI_FMT_lx "\n", +                               addr); +                errno = -error; +                goto out; +            } +            if (dump_write(fd, page, TARGET_PAGE_SIZE) < 0) +                goto out; +        } +    } + + out: +    free_note_info(&info); +    if (mm != NULL) +        vma_delete(mm); +    (void) close(fd); + +    if (errno != 0) +        return (-errno); +    return (0); +} +#endif /* USE_ELF_CORE_DUMP */ + +void do_init_thread(struct target_pt_regs *regs, struct image_info *infop) +{ +    init_thread(regs, infop); +} diff --git a/linux-user/errno_defs.h b/linux-user/errno_defs.h new file mode 100644 index 00000000..8a1cf76c --- /dev/null +++ b/linux-user/errno_defs.h @@ -0,0 +1,141 @@ +/* + * Target definitions of errnos. These may be overridden by an + * architecture specific header if needed. + * + * Taken from asm-generic/errno-base.h and asm-generic/errno.h + */ +#define TARGET_EPERM            1      /* Operation not permitted */ +#define TARGET_ENOENT           2      /* No such file or directory */ +#define TARGET_ESRCH            3      /* No such process */ +#define TARGET_EINTR            4      /* Interrupted system call */ +#define TARGET_EIO              5      /* I/O error */ +#define TARGET_ENXIO            6      /* No such device or address */ +#define TARGET_E2BIG            7      /* Argument list too long */ +#define TARGET_ENOEXEC          8      /* TARGET_Exec format error */ +#define TARGET_EBADF            9      /* Bad file number */ +#define TARGET_ECHILD          10      /* No child processes */ +#define TARGET_EAGAIN          11      /* Try again */ +#define TARGET_ENOMEM          12      /* Out of memory */ +#define TARGET_EACCES          13      /* Permission denied */ +#define TARGET_EFAULT          14      /* Bad address */ +#define TARGET_ENOTBLK         15      /* Block device required */ +#define TARGET_EBUSY           16      /* Device or resource busy */ +#define TARGET_EEXIST          17      /* File exists */ +#define TARGET_EXDEV           18      /* Cross-device link */ +#define TARGET_ENODEV          19      /* No such device */ +#define TARGET_ENOTDIR         20      /* Not a directory */ +#define TARGET_EISDIR          21      /* Is a directory */ +#define TARGET_EINVAL          22      /* Invalid argument */ +#define TARGET_ENFILE          23      /* File table overflow */ +#define TARGET_EMFILE          24      /* Too many open files */ +#define TARGET_ENOTTY          25      /* Not a typewriter */ +#define TARGET_ETXTBSY         26      /* Text file busy */ +#define TARGET_EFBIG           27      /* File too large */ +#define TARGET_ENOSPC          28      /* No space left on device */ +#define TARGET_ESPIPE          29      /* Illegal seek */ +#define TARGET_EROFS           30      /* Read-only file system */ +#define TARGET_EMLINK          31      /* Too many links */ +#define TARGET_EPIPE           32      /* Broken pipe */ +#define TARGET_EDOM            33      /* Math argument out of domain of func */ +#define TARGET_ERANGE          34      /* Math result not representable */ + +#define TARGET_EDEADLK         35      /* Resource deadlock would occur */ +#define TARGET_ENAMETOOLONG    36      /* File name too long */ +#define TARGET_ENOLCK          37      /* No record locks available */ +#define TARGET_ENOSYS          38      /* Function not implemented */ +#define TARGET_ENOTEMPTY       39      /* Directory not empty */ +#define TARGET_ELOOP           40      /* Too many symbolic links encountered */ + +#define TARGET_ENOMSG          42      /* No message of desired type */ +#define TARGET_EIDRM           43      /* Identifier removed */ +#define TARGET_ECHRNG          44      /* Channel number out of range */ +#define TARGET_EL2NSYNC        45      /* Level 2 not synchronized */ +#define TARGET_EL3HLT          46      /* Level 3 halted */ +#define TARGET_EL3RST          47      /* Level 3 reset */ +#define TARGET_ELNRNG          48      /* Link number out of range */ +#define TARGET_EUNATCH         49      /* Protocol driver not attached */ +#define TARGET_ENOCSI          50      /* No CSI structure available */ +#define TARGET_EL2HLT          51      /* Level 2 halted */ +#define TARGET_EBADE           52      /* Invalid exchange */ +#define TARGET_EBADR           53      /* Invalid request descriptor */ +#define TARGET_EXFULL          54      /* TARGET_Exchange full */ +#define TARGET_ENOANO          55      /* No anode */ +#define TARGET_EBADRQC         56      /* Invalid request code */ +#define TARGET_EBADSLT         57      /* Invalid slot */ + +#define TARGET_EBFONT          59      /* Bad font file format */ +#define TARGET_ENOSTR          60      /* Device not a stream */ +#define TARGET_ENODATA         61      /* No data available */ +#define TARGET_ETIME           62      /* Timer expired */ +#define TARGET_ENOSR           63      /* Out of streams resources */ +#define TARGET_ENONET          64      /* Machine is not on the network */ +#define TARGET_ENOPKG          65      /* Package not installed */ +#define TARGET_EREMOTE         66      /* Object is remote */ +#define TARGET_ENOLINK         67      /* Link has been severed */ +#define TARGET_EADV            68      /* Advertise error */ +#define TARGET_ESRMNT          69      /* Srmount error */ +#define TARGET_ECOMM           70      /* Communication error on send */ +#define TARGET_EPROTO          71      /* Protocol error */ +#define TARGET_EMULTIHOP       72      /* Multihop attempted */ +#define TARGET_EDOTDOT         73      /* RFS specific error */ +#define TARGET_EBADMSG         74      /* Not a data message */ +#define TARGET_EOVERFLOW       75      /* Value too large for defined data type */ +#define TARGET_ENOTUNIQ        76      /* Name not unique on network */ +#define TARGET_EBADFD          77      /* File descriptor in bad state */ +#define TARGET_EREMCHG         78      /* Remote address changed */ +#define TARGET_ELIBACC         79      /* Can not access a needed shared library */ +#define TARGET_ELIBBAD         80      /* Accessing a corrupted shared library */ +#define TARGET_ELIBSCN         81      /* .lib section in a.out corrupted */ +#define TARGET_ELIBMAX         82      /* Attempting to link in too many shared libraries */ +#define TARGET_ELIBEXEC        83      /* Cannot exec a shared library directly */ +#define TARGET_EILSEQ          84      /* Illegal byte sequence */ +#define TARGET_ERESTART        85      /* Interrupted system call should be restarted */ +#define TARGET_ESTRPIPE        86      /* Streams pipe error */ +#define TARGET_EUSERS          87      /* Too many users */ +#define TARGET_ENOTSOCK        88      /* Socket operation on non-socket */ +#define TARGET_EDESTADDRREQ    89      /* Destination address required */ +#define TARGET_EMSGSIZE        90      /* Message too long */ +#define TARGET_EPROTOTYPE      91      /* Protocol wrong type for socket */ +#define TARGET_ENOPROTOOPT     92      /* Protocol not available */ +#define TARGET_EPROTONOSUPPORT 93      /* Protocol not supported */ +#define TARGET_ESOCKTNOSUPPORT 94      /* Socket type not supported */ +#define TARGET_EOPNOTSUPP      95      /* Operation not supported on transport endpoint */ +#define TARGET_EPFNOSUPPORT    96      /* Protocol family not supported */ +#define TARGET_EAFNOSUPPORT    97      /* Address family not supported by protocol */ +#define TARGET_EADDRINUSE      98      /* Address already in use */ +#define TARGET_EADDRNOTAVAIL   99      /* Cannot assign requested address */ +#define TARGET_ENETDOWN        100     /* Network is down */ +#define TARGET_ENETUNREACH     101     /* Network is unreachable */ +#define TARGET_ENETRESET       102     /* Network dropped connection because of reset */ +#define TARGET_ECONNABORTED    103     /* Software caused connection abort */ +#define TARGET_ECONNRESET      104     /* Connection reset by peer */ +#define TARGET_ENOBUFS         105     /* No buffer space available */ +#define TARGET_EISCONN         106     /* Transport endpoint is already connected */ +#define TARGET_ENOTCONN        107     /* Transport endpoint is not connected */ +#define TARGET_ESHUTDOWN       108     /* Cannot send after transport endpoint shutdown */ +#define TARGET_ETOOMANYREFS    109     /* Too many references: cannot splice */ +#define TARGET_ETIMEDOUT       110     /* Connection timed out */ +#define TARGET_ECONNREFUSED    111     /* Connection refused */ +#define TARGET_EHOSTDOWN       112     /* Host is down */ +#define TARGET_EHOSTUNREACH    113     /* No route to host */ +#define TARGET_EALREADY        114     /* Operation already in progress */ +#define TARGET_EINPROGRESS     115     /* Operation now in progress */ +#define TARGET_ESTALE          116     /* Stale NFS file handle */ +#define TARGET_EUCLEAN         117     /* Structure needs cleaning */ +#define TARGET_ENOTNAM         118     /* Not a XENIX named type file */ +#define TARGET_ENAVAIL         119     /* No XENIX semaphores available */ +#define TARGET_EISNAM          120     /* Is a named type file */ +#define TARGET_EREMOTEIO       121     /* Remote I/O error */ +#define TARGET_EDQUOT          122     /* Quota exceeded */ + +#define TARGET_ENOMEDIUM       123     /* No medium found */ +#define TARGET_EMEDIUMTYPE     124     /* Wrong medium type */ +#define TARGET_ECANCELED       125     /* Operation Canceled */ +#define TARGET_ENOKEY          126     /* Required key not available */ +#define TARGET_EKEYEXPIRED     127     /* Key has expired */ +#define TARGET_EKEYREVOKED     128     /* Key has been revoked */ +#define TARGET_EKEYREJECTED    129     /* Key was rejected by service */ + +/* for robust mutexes */ +#define TARGET_EOWNERDEAD      130     /* Owner died */ +#define TARGET_ENOTRECOVERABLE 131     /* State not recoverable */ diff --git a/linux-user/flat.h b/linux-user/flat.h new file mode 100644 index 00000000..6f2d0c4b --- /dev/null +++ b/linux-user/flat.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2002-2003  David McCullough <davidm@snapgear.com> + * Copyright (C) 1998       Kenneth Albanowski <kjahds@kjahds.com> + *                          The Silver Hammer Group, Ltd. + * + * This file provides the definitions and structures needed to + * support uClinux flat-format executables. + */ + +#define	FLAT_VERSION			0x00000004L + +#ifdef CONFIG_BINFMT_SHARED_FLAT +#define	MAX_SHARED_LIBS			(4) +#else +#define	MAX_SHARED_LIBS			(1) +#endif + +/* + * To make everything easier to port and manage cross platform + * development,  all fields are in network byte order. + */ + +struct flat_hdr { +	char magic[4]; +	abi_ulong rev;          /* version (as above) */ +	abi_ulong entry;        /* Offset of first executable instruction +                                   with text segment from beginning of file */ +	abi_ulong data_start;   /* Offset of data segment from beginning of +                                   file */ +	abi_ulong data_end;     /* Offset of end of data segment +                                   from beginning of file */ +	abi_ulong bss_end;      /* Offset of end of bss segment from beginning +                                   of file */ + +	/* (It is assumed that data_end through bss_end forms the bss segment.) */ + +	abi_ulong stack_size;   /* Size of stack, in bytes */ +	abi_ulong reloc_start;  /* Offset of relocation records from +                                   beginning of file */ +	abi_ulong reloc_count;  /* Number of relocation records */ +	abi_ulong flags; +	abi_ulong build_date;   /* When the program/library was built */ +	abi_ulong filler[5];    /* Reservered, set to zero */ +}; + +#define FLAT_FLAG_RAM    0x0001 /* load program entirely into RAM */ +#define FLAT_FLAG_GOTPIC 0x0002 /* program is PIC with GOT */ +#define FLAT_FLAG_GZIP   0x0004 /* all but the header is compressed */ +#define FLAT_FLAG_GZDATA 0x0008 /* only data/relocs are compressed (for XIP) */ +#define FLAT_FLAG_KTRACE 0x0010 /* output useful kernel trace for debugging */ + + +/* + * While it would be nice to keep this header clean,  users of older + * tools still need this support in the kernel.  So this section is + * purely for compatibility with old tool chains. + * + * DO NOT make changes or enhancements to the old format please,  just work + *        with the format above,  except to fix bugs with old format support. + */ + +#define	OLD_FLAT_VERSION			0x00000002L +#define OLD_FLAT_RELOC_TYPE_TEXT	0 +#define OLD_FLAT_RELOC_TYPE_DATA	1 +#define OLD_FLAT_RELOC_TYPE_BSS		2 + +#   	define OLD_FLAT_FLAG_RAM    0x1 /* load program entirely into RAM */ diff --git a/linux-user/flatload.c b/linux-user/flatload.c new file mode 100644 index 00000000..566a7a87 --- /dev/null +++ b/linux-user/flatload.c @@ -0,0 +1,812 @@ +/****************************************************************************/ +/* + *  QEMU bFLT binary loader.  Based on linux/fs/binfmt_flat.c + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, see <http://www.gnu.org/licenses/>. + * + *      Copyright (C) 2006 CodeSourcery. + *	Copyright (C) 2000-2003 David McCullough <davidm@snapgear.com> + *	Copyright (C) 2002 Greg Ungerer <gerg@snapgear.com> + *	Copyright (C) 2002 SnapGear, by Paul Dale <pauli@snapgear.com> + *	Copyright (C) 2000, 2001 Lineo, by David McCullough <davidm@lineo.com> + *  based heavily on: + * + *  linux/fs/binfmt_aout.c: + *      Copyright (C) 1991, 1992, 1996  Linus Torvalds + *  linux/fs/binfmt_flat.c for 2.0 kernel + *	    Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com> + *	JAN/99 -- coded full program relocation (gerg@snapgear.com) + */ + +/* ??? ZFLAT and shared library support is currently disabled.  */ + +/****************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <sys/mman.h> +#include <unistd.h> + +#include "qemu.h" +#include "flat.h" +#define ntohl(x) be32_to_cpu(x) +#include <target_flat.h> + +//#define DEBUG + +#ifdef DEBUG +#define	DBG_FLT(...)	printf(__VA_ARGS__) +#else +#define	DBG_FLT(...) +#endif + +#define RELOC_FAILED 0xff00ff01		/* Relocation incorrect somewhere */ +#define UNLOADED_LIB 0x7ff000ff		/* Placeholder for unused library */ + +struct lib_info { +    abi_ulong start_code;       /* Start of text segment */ +    abi_ulong start_data;       /* Start of data segment */ +    abi_ulong end_data;         /* Start of bss section */ +    abi_ulong start_brk;        /* End of data segment */ +    abi_ulong text_len;	        /* Length of text segment */ +    abi_ulong entry;	        /* Start address for this module */ +    abi_ulong build_date;       /* When this one was compiled */ +    short loaded;		/* Has this library been loaded? */ +}; + +#ifdef CONFIG_BINFMT_SHARED_FLAT +static int load_flat_shared_library(int id, struct lib_info *p); +#endif + +struct linux_binprm; + +/****************************************************************************/ +/* + * create_flat_tables() parses the env- and arg-strings in new user + * memory and creates the pointer tables from them, and puts their + * addresses on the "stack", returning the new stack pointer value. + */ + +/* Push a block of strings onto the guest stack.  */ +static abi_ulong copy_strings(abi_ulong p, int n, char **s) +{ +    int len; + +    while (n-- > 0) { +        len = strlen(s[n]) + 1; +        p -= len; +        memcpy_to_target(p, s[n], len); +    } + +    return p; +} + +static int target_pread(int fd, abi_ulong ptr, abi_ulong len, +                        abi_ulong offset) +{ +    void *buf; +    int ret; + +    buf = lock_user(VERIFY_WRITE, ptr, len, 0); +    ret = pread(fd, buf, len, offset); +    unlock_user(buf, ptr, len); +    return ret; +} +/****************************************************************************/ + +#ifdef CONFIG_BINFMT_ZFLAT + +#include <linux/zlib.h> + +#define LBUFSIZE	4000 + +/* gzip flag byte */ +#define ASCII_FLAG   0x01 /* bit 0 set: file probably ASCII text */ +#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ +#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME    0x08 /* bit 3 set: original file name present */ +#define COMMENT      0x10 /* bit 4 set: file comment present */ +#define ENCRYPTED    0x20 /* bit 5 set: file is encrypted */ +#define RESERVED     0xC0 /* bit 6,7:   reserved */ + +static int decompress_exec( +	struct linux_binprm *bprm, +	unsigned long offset, +	char *dst, +	long len, +	int fd) +{ +	unsigned char *buf; +	z_stream strm; +	loff_t fpos; +	int ret, retval; + +	DBG_FLT("decompress_exec(offset=%x,buf=%x,len=%x)\n",(int)offset, (int)dst, (int)len); + +	memset(&strm, 0, sizeof(strm)); +	strm.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL); +	if (strm.workspace == NULL) { +		DBG_FLT("binfmt_flat: no memory for decompress workspace\n"); +		return -ENOMEM; +	} +	buf = kmalloc(LBUFSIZE, GFP_KERNEL); +	if (buf == NULL) { +		DBG_FLT("binfmt_flat: no memory for read buffer\n"); +		retval = -ENOMEM; +		goto out_free; +	} + +	/* Read in first chunk of data and parse gzip header. */ +	fpos = offset; +	ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos); + +	strm.next_in = buf; +	strm.avail_in = ret; +	strm.total_in = 0; + +	retval = -ENOEXEC; + +	/* Check minimum size -- gzip header */ +	if (ret < 10) { +		DBG_FLT("binfmt_flat: file too small?\n"); +		goto out_free_buf; +	} + +	/* Check gzip magic number */ +	if ((buf[0] != 037) || ((buf[1] != 0213) && (buf[1] != 0236))) { +		DBG_FLT("binfmt_flat: unknown compression magic?\n"); +		goto out_free_buf; +	} + +	/* Check gzip method */ +	if (buf[2] != 8) { +		DBG_FLT("binfmt_flat: unknown compression method?\n"); +		goto out_free_buf; +	} +	/* Check gzip flags */ +	if ((buf[3] & ENCRYPTED) || (buf[3] & CONTINUATION) || +	    (buf[3] & RESERVED)) { +		DBG_FLT("binfmt_flat: unknown flags?\n"); +		goto out_free_buf; +	} + +	ret = 10; +	if (buf[3] & EXTRA_FIELD) { +		ret += 2 + buf[10] + (buf[11] << 8); +		if (unlikely(LBUFSIZE == ret)) { +			DBG_FLT("binfmt_flat: buffer overflow (EXTRA)?\n"); +			goto out_free_buf; +		} +	} +	if (buf[3] & ORIG_NAME) { +		for (; ret < LBUFSIZE && (buf[ret] != 0); ret++) +			; +		if (unlikely(LBUFSIZE == ret)) { +			DBG_FLT("binfmt_flat: buffer overflow (ORIG_NAME)?\n"); +			goto out_free_buf; +		} +	} +	if (buf[3] & COMMENT) { +		for (;  ret < LBUFSIZE && (buf[ret] != 0); ret++) +			; +		if (unlikely(LBUFSIZE == ret)) { +			DBG_FLT("binfmt_flat: buffer overflow (COMMENT)?\n"); +			goto out_free_buf; +		} +	} + +	strm.next_in += ret; +	strm.avail_in -= ret; + +	strm.next_out = dst; +	strm.avail_out = len; +	strm.total_out = 0; + +	if (zlib_inflateInit2(&strm, -MAX_WBITS) != Z_OK) { +		DBG_FLT("binfmt_flat: zlib init failed?\n"); +		goto out_free_buf; +	} + +	while ((ret = zlib_inflate(&strm, Z_NO_FLUSH)) == Z_OK) { +		ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos); +		if (ret <= 0) +			break; +		if (ret >= (unsigned long) -4096) +			break; +		len -= ret; + +		strm.next_in = buf; +		strm.avail_in = ret; +		strm.total_in = 0; +	} + +	if (ret < 0) { +		DBG_FLT("binfmt_flat: decompression failed (%d), %s\n", +			ret, strm.msg); +		goto out_zlib; +	} + +	retval = 0; +out_zlib: +	zlib_inflateEnd(&strm); +out_free_buf: +	kfree(buf); +out_free: +	kfree(strm.workspace); +out: +	return retval; +} + +#endif /* CONFIG_BINFMT_ZFLAT */ + +/****************************************************************************/ + +static abi_ulong +calc_reloc(abi_ulong r, struct lib_info *p, int curid, int internalp) +{ +    abi_ulong addr; +    int id; +    abi_ulong start_brk; +    abi_ulong start_data; +    abi_ulong text_len; +    abi_ulong start_code; + +#ifdef CONFIG_BINFMT_SHARED_FLAT +#error needs checking +    if (r == 0) +        id = curid;	/* Relocs of 0 are always self referring */ +    else { +        id = (r >> 24) & 0xff;	/* Find ID for this reloc */ +        r &= 0x00ffffff;	/* Trim ID off here */ +    } +    if (id >= MAX_SHARED_LIBS) { +        fprintf(stderr, "BINFMT_FLAT: reference 0x%x to shared library %d\n", +                (unsigned) r, id); +        goto failed; +    } +    if (curid != id) { +        if (internalp) { +            fprintf(stderr, "BINFMT_FLAT: reloc address 0x%x not " +                    "in same module (%d != %d)\n", +                    (unsigned) r, curid, id); +            goto failed; +        } else if ( ! p[id].loaded && +                    load_flat_shared_library(id, p) > (unsigned long) -4096) { +            fprintf(stderr, "BINFMT_FLAT: failed to load library %d\n", id); +            goto failed; +        } +        /* Check versioning information (i.e. time stamps) */ +        if (p[id].build_date && p[curid].build_date +            && p[curid].build_date < p[id].build_date) { +            fprintf(stderr, "BINFMT_FLAT: library %d is younger than %d\n", +                    id, curid); +            goto failed; +        } +    } +#else +    id = 0; +#endif + +    start_brk = p[id].start_brk; +    start_data = p[id].start_data; +    start_code = p[id].start_code; +    text_len = p[id].text_len; + +    if (!flat_reloc_valid(r, start_brk - start_data + text_len)) { +        fprintf(stderr, "BINFMT_FLAT: reloc outside program 0x%x " +                "(0 - 0x%x/0x%x)\n", +               (int) r,(int)(start_brk-start_code),(int)text_len); +        goto failed; +    } + +    if (r < text_len)			/* In text segment */ +        addr = r + start_code; +    else					/* In data segment */ +        addr = r - text_len + start_data; + +    /* Range checked already above so doing the range tests is redundant...*/ +    return(addr); + +failed: +    abort(); +    return RELOC_FAILED; +} + +/****************************************************************************/ + +/* ??? This does not handle endianness correctly.  */ +static void old_reloc(struct lib_info *libinfo, uint32_t rl) +{ +#ifdef DEBUG +	const char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" }; +#endif +	uint32_t *ptr; +        uint32_t offset; +        int reloc_type; + +        offset = rl & 0x3fffffff; +        reloc_type = rl >> 30; +        /* ??? How to handle this?  */ +#if defined(CONFIG_COLDFIRE) +	ptr = (uint32_t *) ((unsigned long) libinfo->start_code + offset); +#else +	ptr = (uint32_t *) ((unsigned long) libinfo->start_data + offset); +#endif + +#ifdef DEBUG +	fprintf(stderr, "Relocation of variable at DATASEG+%x " +		"(address %p, currently %x) into segment %s\n", +		offset, ptr, (int)*ptr, segment[reloc_type]); +#endif + +	switch (reloc_type) { +	case OLD_FLAT_RELOC_TYPE_TEXT: +		*ptr += libinfo->start_code; +		break; +	case OLD_FLAT_RELOC_TYPE_DATA: +		*ptr += libinfo->start_data; +		break; +	case OLD_FLAT_RELOC_TYPE_BSS: +		*ptr += libinfo->end_data; +		break; +	default: +		fprintf(stderr, "BINFMT_FLAT: Unknown relocation type=%x\n", +                        reloc_type); +		break; +	} +	DBG_FLT("Relocation became %x\n", (int)*ptr); +} + +/****************************************************************************/ + +static int load_flat_file(struct linux_binprm * bprm, +		struct lib_info *libinfo, int id, abi_ulong *extra_stack) +{ +    struct flat_hdr * hdr; +    abi_ulong textpos = 0, datapos = 0; +    abi_long result; +    abi_ulong realdatastart = 0; +    abi_ulong text_len, data_len, bss_len, stack_len, flags; +    abi_ulong extra; +    abi_ulong reloc = 0, rp; +    int i, rev, relocs = 0; +    abi_ulong fpos; +    abi_ulong start_code; +    abi_ulong indx_len; + +    hdr = ((struct flat_hdr *) bprm->buf);		/* exec-header */ + +    text_len  = ntohl(hdr->data_start); +    data_len  = ntohl(hdr->data_end) - ntohl(hdr->data_start); +    bss_len   = ntohl(hdr->bss_end) - ntohl(hdr->data_end); +    stack_len = ntohl(hdr->stack_size); +    if (extra_stack) { +        stack_len += *extra_stack; +        *extra_stack = stack_len; +    } +    relocs    = ntohl(hdr->reloc_count); +    flags     = ntohl(hdr->flags); +    rev       = ntohl(hdr->rev); + +    DBG_FLT("BINFMT_FLAT: Loading file: %s\n", bprm->filename); + +    if (rev != FLAT_VERSION && rev != OLD_FLAT_VERSION) { +        fprintf(stderr, "BINFMT_FLAT: bad magic/rev (0x%x, need 0x%x)\n", +                rev, (int) FLAT_VERSION); +        return -ENOEXEC; +    } + +    /* Don't allow old format executables to use shared libraries */ +    if (rev == OLD_FLAT_VERSION && id != 0) { +        fprintf(stderr, "BINFMT_FLAT: shared libraries are not available\n"); +        return -ENOEXEC; +    } + +    /* +     * fix up the flags for the older format,  there were all kinds +     * of endian hacks,  this only works for the simple cases +     */ +    if (rev == OLD_FLAT_VERSION && flat_old_ram_flag(flags)) +        flags = FLAT_FLAG_RAM; + +#ifndef CONFIG_BINFMT_ZFLAT +    if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) { +        fprintf(stderr, "Support for ZFLAT executables is not enabled\n"); +        return -ENOEXEC; +    } +#endif + +    /* +     * calculate the extra space we need to map in +     */ +    extra = relocs * sizeof(abi_ulong); +    if (extra < bss_len + stack_len) +        extra = bss_len + stack_len; + +    /* Add space for library base pointers.  Make sure this does not +       misalign the  doesn't misalign the data segment.  */ +    indx_len = MAX_SHARED_LIBS * sizeof(abi_ulong); +    indx_len = (indx_len + 15) & ~(abi_ulong)15; + +    /* +     * there are a couple of cases here,  the separate code/data +     * case,  and then the fully copied to RAM case which lumps +     * it all together. +     */ +    if ((flags & (FLAT_FLAG_RAM|FLAT_FLAG_GZIP)) == 0) { +        /* +         * this should give us a ROM ptr,  but if it doesn't we don't +         * really care +         */ +        DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); + +        textpos = target_mmap(0, text_len, PROT_READ|PROT_EXEC, +                              MAP_PRIVATE, bprm->fd, 0); +        if (textpos == -1) { +            fprintf(stderr, "Unable to mmap process text\n"); +            return -1; +        } + +        realdatastart = target_mmap(0, data_len + extra + indx_len, +                                    PROT_READ|PROT_WRITE|PROT_EXEC, +                                    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + +        if (realdatastart == -1) { +            fprintf(stderr, "Unable to allocate RAM for process data\n"); +            return realdatastart; +        } +        datapos = realdatastart + indx_len; + +        DBG_FLT("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n", +                        (int)(data_len + bss_len + stack_len), (int)datapos); + +        fpos = ntohl(hdr->data_start); +#ifdef CONFIG_BINFMT_ZFLAT +        if (flags & FLAT_FLAG_GZDATA) { +            result = decompress_exec(bprm, fpos, (char *) datapos, +                                     data_len + (relocs * sizeof(abi_ulong))) +        } else +#endif +        { +            result = target_pread(bprm->fd, datapos, +                                  data_len + (relocs * sizeof(abi_ulong)), +                                  fpos); +        } +        if (result < 0) { +            fprintf(stderr, "Unable to read data+bss\n"); +            return result; +        } + +        reloc = datapos + (ntohl(hdr->reloc_start) - text_len); + +    } else { + +        textpos = target_mmap(0, text_len + data_len + extra + indx_len, +                              PROT_READ | PROT_EXEC | PROT_WRITE, +                              MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +        if (textpos == -1 ) { +            fprintf(stderr, "Unable to allocate RAM for process text/data\n"); +            return -1; +        } + +        realdatastart = textpos + ntohl(hdr->data_start); +        datapos = realdatastart + indx_len; +        reloc = (textpos + ntohl(hdr->reloc_start) + indx_len); + +#ifdef CONFIG_BINFMT_ZFLAT +#error code needs checking +        /* +         * load it all in and treat it like a RAM load from now on +         */ +        if (flags & FLAT_FLAG_GZIP) { +                result = decompress_exec(bprm, sizeof (struct flat_hdr), +                                 (((char *) textpos) + sizeof (struct flat_hdr)), +                                 (text_len + data_len + (relocs * sizeof(unsigned long)) +                                          - sizeof (struct flat_hdr)), +                                 0); +                memmove((void *) datapos, (void *) realdatastart, +                                data_len + (relocs * sizeof(unsigned long))); +        } else if (flags & FLAT_FLAG_GZDATA) { +                fpos = 0; +                result = bprm->file->f_op->read(bprm->file, +                                (char *) textpos, text_len, &fpos); +                if (result < (unsigned long) -4096) +                        result = decompress_exec(bprm, text_len, (char *) datapos, +                                         data_len + (relocs * sizeof(unsigned long)), 0); +        } +        else +#endif +        { +            result = target_pread(bprm->fd, textpos, +                                  text_len, 0); +            if (result >= 0) { +                result = target_pread(bprm->fd, datapos, +                    data_len + (relocs * sizeof(abi_ulong)), +                    ntohl(hdr->data_start)); +            } +        } +        if (result < 0) { +            fprintf(stderr, "Unable to read code+data+bss\n"); +            return result; +        } +    } + +    DBG_FLT("Mapping is 0x%x, Entry point is 0x%x, data_start is 0x%x\n", +            (int)textpos, 0x00ffffff&ntohl(hdr->entry), +            ntohl(hdr->data_start)); + +    /* The main program needs a little extra setup in the task structure */ +    start_code = textpos + sizeof (struct flat_hdr); + +    DBG_FLT("%s %s: TEXT=%x-%x DATA=%x-%x BSS=%x-%x\n", +            id ? "Lib" : "Load", bprm->filename, +            (int) start_code, (int) (textpos + text_len), +            (int) datapos, +            (int) (datapos + data_len), +            (int) (datapos + data_len), +            (int) (((datapos + data_len + bss_len) + 3) & ~3)); + +    text_len -= sizeof(struct flat_hdr); /* the real code len */ + +    /* Store the current module values into the global library structure */ +    libinfo[id].start_code = start_code; +    libinfo[id].start_data = datapos; +    libinfo[id].end_data = datapos + data_len; +    libinfo[id].start_brk = datapos + data_len + bss_len; +    libinfo[id].text_len = text_len; +    libinfo[id].loaded = 1; +    libinfo[id].entry = (0x00ffffff & ntohl(hdr->entry)) + textpos; +    libinfo[id].build_date = ntohl(hdr->build_date); + +    /* +     * We just load the allocations into some temporary memory to +     * help simplify all this mumbo jumbo +     * +     * We've got two different sections of relocation entries. +     * The first is the GOT which resides at the beginning of the data segment +     * and is terminated with a -1.  This one can be relocated in place. +     * The second is the extra relocation entries tacked after the image's +     * data segment. These require a little more processing as the entry is +     * really an offset into the image which contains an offset into the +     * image. +     */ +    if (flags & FLAT_FLAG_GOTPIC) { +        rp = datapos; +        while (1) { +            abi_ulong addr; +            if (get_user_ual(addr, rp)) +                return -EFAULT; +            if (addr == -1) +                break; +            if (addr) { +                addr = calc_reloc(addr, libinfo, id, 0); +                if (addr == RELOC_FAILED) +                    return -ENOEXEC; +                if (put_user_ual(addr, rp)) +                    return -EFAULT; +            } +            rp += sizeof(abi_ulong); +        } +    } + +    /* +     * Now run through the relocation entries. +     * We've got to be careful here as C++ produces relocatable zero +     * entries in the constructor and destructor tables which are then +     * tested for being not zero (which will always occur unless we're +     * based from address zero).  This causes an endless loop as __start +     * is at zero.  The solution used is to not relocate zero addresses. +     * This has the negative side effect of not allowing a global data +     * reference to be statically initialised to _stext (I've moved +     * __start to address 4 so that is okay). +     */ +    if (rev > OLD_FLAT_VERSION) { +        abi_ulong persistent = 0; +        for (i = 0; i < relocs; i++) { +            abi_ulong addr, relval; + +            /* Get the address of the pointer to be +               relocated (of course, the address has to be +               relocated first).  */ +            if (get_user_ual(relval, reloc + i * sizeof(abi_ulong))) +                return -EFAULT; +            relval = ntohl(relval); +            if (flat_set_persistent(relval, &persistent)) +                continue; +            addr = flat_get_relocate_addr(relval); +            rp = calc_reloc(addr, libinfo, id, 1); +            if (rp == RELOC_FAILED) +                return -ENOEXEC; + +            /* Get the pointer's value.  */ +            if (get_user_ual(addr, rp)) +                return -EFAULT; +            addr = flat_get_addr_from_rp(addr, relval, flags, &persistent); +            if (addr != 0) { +                /* +                 * Do the relocation.  PIC relocs in the data section are +                 * already in target order +                 */ +                if ((flags & FLAT_FLAG_GOTPIC) == 0) +                    addr = ntohl(addr); +                addr = calc_reloc(addr, libinfo, id, 0); +                if (addr == RELOC_FAILED) +                    return -ENOEXEC; + +                /* Write back the relocated pointer.  */ +                if (flat_put_addr_at_rp(rp, addr, relval)) +                    return -EFAULT; +            } +        } +    } else { +        for (i = 0; i < relocs; i++) { +            abi_ulong relval; +            if (get_user_ual(relval, reloc + i * sizeof(abi_ulong))) +                return -EFAULT; +            old_reloc(&libinfo[0], relval); +        } +    } + +    /* zero the BSS.  */ +    memset(g2h(datapos + data_len), 0, bss_len); + +    return 0; +} + + +/****************************************************************************/ +#ifdef CONFIG_BINFMT_SHARED_FLAT + +/* + * Load a shared library into memory.  The library gets its own data + * segment (including bss) but not argv/argc/environ. + */ + +static int load_flat_shared_library(int id, struct lib_info *libs) +{ +	struct linux_binprm bprm; +	int res; +	char buf[16]; + +	/* Create the file name */ +	sprintf(buf, "/lib/lib%d.so", id); + +	/* Open the file up */ +	bprm.filename = buf; +	bprm.file = open_exec(bprm.filename); +	res = PTR_ERR(bprm.file); +	if (IS_ERR(bprm.file)) +		return res; + +	res = prepare_binprm(&bprm); + +	if (res <= (unsigned long)-4096) +		res = load_flat_file(&bprm, libs, id, NULL); +	if (bprm.file) { +		allow_write_access(bprm.file); +		fput(bprm.file); +		bprm.file = NULL; +	} +	return(res); +} + +#endif /* CONFIG_BINFMT_SHARED_FLAT */ + +int load_flt_binary(struct linux_binprm *bprm, struct image_info *info) +{ +    struct lib_info libinfo[MAX_SHARED_LIBS]; +    abi_ulong p = bprm->p; +    abi_ulong stack_len; +    abi_ulong start_addr; +    abi_ulong sp; +    int res; +    int i, j; + +    memset(libinfo, 0, sizeof(libinfo)); +    /* +     * We have to add the size of our arguments to our stack size +     * otherwise it's too easy for users to create stack overflows +     * by passing in a huge argument list.  And yes,  we have to be +     * pedantic and include space for the argv/envp array as it may have +     * a lot of entries. +     */ +    stack_len = 0; +    for (i = 0; i < bprm->argc; ++i) { +        /* the argv strings */ +        stack_len += strlen(bprm->argv[i]); +    } +    for (i = 0; i < bprm->envc; ++i) { +        /* the envp strings */ +        stack_len += strlen(bprm->envp[i]); +    } +    stack_len += (bprm->argc + 1) * 4; /* the argv array */ +    stack_len += (bprm->envc + 1) * 4; /* the envp array */ + + +    res = load_flat_file(bprm, libinfo, 0, &stack_len); +    if (res > (unsigned long)-4096) +            return res; + +    /* Update data segment pointers for all libraries */ +    for (i=0; i<MAX_SHARED_LIBS; i++) { +        if (libinfo[i].loaded) { +            abi_ulong p; +            p = libinfo[i].start_data; +            for (j=0; j<MAX_SHARED_LIBS; j++) { +                p -= 4; +                /* FIXME - handle put_user() failures */ +                if (put_user_ual(libinfo[j].loaded +                                 ? libinfo[j].start_data +                                 : UNLOADED_LIB, +                                 p)) +                    return -EFAULT; +            } +        } +    } + +    p = ((libinfo[0].start_brk + stack_len + 3) & ~3) - 4; +    DBG_FLT("p=%x\n", (int)p); + +    /* Copy argv/envp.  */ +    p = copy_strings(p, bprm->envc, bprm->envp); +    p = copy_strings(p, bprm->argc, bprm->argv); +    /* Align stack.  */ +    sp = p & ~(abi_ulong)(sizeof(abi_ulong) - 1); +    /* Enforce final stack alignment of 16 bytes.  This is sufficient +       for all current targets, and excess alignment is harmless.  */ +    stack_len = bprm->envc + bprm->argc + 2; +    stack_len += 3;	/* argc, arvg, argp */ +    stack_len *= sizeof(abi_ulong); +    if ((sp + stack_len) & 15) +        sp -= 16 - ((sp + stack_len) & 15); +    sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p, +                             flat_argvp_envp_on_stack()); + +    /* Fake some return addresses to ensure the call chain will +     * initialise library in order for us.  We are required to call +     * lib 1 first, then 2, ... and finally the main program (id 0). +     */ +    start_addr = libinfo[0].entry; + +#ifdef CONFIG_BINFMT_SHARED_FLAT +#error here +    for (i = MAX_SHARED_LIBS-1; i>0; i--) { +            if (libinfo[i].loaded) { +                    /* Push previos first to call address */ +                    --sp; +                    if (put_user_ual(start_addr, sp)) +                        return -EFAULT; +                    start_addr = libinfo[i].entry; +            } +    } +#endif + +    /* Stash our initial stack pointer into the mm structure */ +    info->start_code = libinfo[0].start_code; +    info->end_code = libinfo[0].start_code = libinfo[0].text_len; +    info->start_data = libinfo[0].start_data; +    info->end_data = libinfo[0].end_data; +    info->start_brk = libinfo[0].start_brk; +    info->start_stack = sp; +    info->stack_limit = libinfo[0].start_brk; +    info->entry = start_addr; +    info->code_offset = info->start_code; +    info->data_offset = info->start_data - libinfo[0].text_len; + +    DBG_FLT("start_thread(entry=0x%x, start_stack=0x%x)\n", +            (int)info->entry, (int)info->start_stack); + +    return 0; +} diff --git a/linux-user/i386/syscall.h b/linux-user/i386/syscall.h new file mode 100644 index 00000000..906aaac0 --- /dev/null +++ b/linux-user/i386/syscall.h @@ -0,0 +1,152 @@ +/* default linux values for the selectors */ +#define __USER_CS	(0x23) +#define __USER_DS	(0x2B) + +struct target_pt_regs { +	long ebx; +	long ecx; +	long edx; +	long esi; +	long edi; +	long ebp; +	long eax; +	int  xds; +	int  xes; +	long orig_eax; +	long eip; +	int  xcs; +	long eflags; +	long esp; +	int  xss; +}; + +/* ioctls */ + +#define TARGET_LDT_ENTRIES      8192 +#define TARGET_LDT_ENTRY_SIZE	8 + +#define TARGET_GDT_ENTRIES             9 +#define TARGET_GDT_ENTRY_TLS_ENTRIES   3 +#define TARGET_GDT_ENTRY_TLS_MIN       6 +#define TARGET_GDT_ENTRY_TLS_MAX       (TARGET_GDT_ENTRY_TLS_MIN + TARGET_GDT_ENTRY_TLS_ENTRIES - 1) + +struct target_modify_ldt_ldt_s { +    unsigned int  entry_number; +    abi_ulong base_addr; +    unsigned int limit; +    unsigned int flags; +}; + +/* vm86 defines */ + +#define TARGET_BIOSSEG		0x0f000 + +#define TARGET_CPU_086		0 +#define TARGET_CPU_186		1 +#define TARGET_CPU_286		2 +#define TARGET_CPU_386		3 +#define TARGET_CPU_486		4 +#define TARGET_CPU_586		5 + +#define TARGET_VM86_SIGNAL	0	/* return due to signal */ +#define TARGET_VM86_UNKNOWN	1	/* unhandled GP fault - IO-instruction or similar */ +#define TARGET_VM86_INTx	2	/* int3/int x instruction (ARG = x) */ +#define TARGET_VM86_STI	3	/* sti/popf/iret instruction enabled virtual interrupts */ + +/* + * Additional return values when invoking new vm86() + */ +#define TARGET_VM86_PICRETURN	4	/* return due to pending PIC request */ +#define TARGET_VM86_TRAP	6	/* return due to DOS-debugger request */ + +/* + * function codes when invoking new vm86() + */ +#define TARGET_VM86_PLUS_INSTALL_CHECK	0 +#define TARGET_VM86_ENTER		1 +#define TARGET_VM86_ENTER_NO_BYPASS	2 +#define	TARGET_VM86_REQUEST_IRQ	3 +#define TARGET_VM86_FREE_IRQ		4 +#define TARGET_VM86_GET_IRQ_BITS	5 +#define TARGET_VM86_GET_AND_RESET_IRQ	6 + +/* + * This is the stack-layout seen by the user space program when we have + * done a translation of "SAVE_ALL" from vm86 mode. The real kernel layout + * is 'kernel_vm86_regs' (see below). + */ + +struct target_vm86_regs { +/* + * normal regs, with special meaning for the segment descriptors.. + */ +	abi_long ebx; +	abi_long ecx; +	abi_long edx; +	abi_long esi; +	abi_long edi; +	abi_long ebp; +	abi_long eax; +	abi_long __null_ds; +	abi_long __null_es; +	abi_long __null_fs; +	abi_long __null_gs; +	abi_long orig_eax; +	abi_long eip; +	unsigned short cs, __csh; +	abi_long eflags; +	abi_long esp; +	unsigned short ss, __ssh; +/* + * these are specific to v86 mode: + */ +	unsigned short es, __esh; +	unsigned short ds, __dsh; +	unsigned short fs, __fsh; +	unsigned short gs, __gsh; +}; + +struct target_revectored_struct { +	abi_ulong __map[8];			/* 256 bits */ +}; + +struct target_vm86_struct { +	struct target_vm86_regs regs; +	abi_ulong flags; +	abi_ulong screen_bitmap; +	abi_ulong cpu_type; +	struct target_revectored_struct int_revectored; +	struct target_revectored_struct int21_revectored; +}; + +/* + * flags masks + */ +#define TARGET_VM86_SCREEN_BITMAP	0x0001 + +struct target_vm86plus_info_struct { +        abi_ulong flags; +#define TARGET_force_return_for_pic (1 << 0) +#define TARGET_vm86dbg_active       (1 << 1)  /* for debugger */ +#define TARGET_vm86dbg_TFpendig     (1 << 2)  /* for debugger */ +#define TARGET_is_vm86pus           (1 << 31) /* for vm86 internal use */ +	unsigned char vm86dbg_intxxtab[32];   /* for debugger */ +}; + +struct target_vm86plus_struct { +	struct target_vm86_regs regs; +	abi_ulong flags; +	abi_ulong screen_bitmap; +	abi_ulong cpu_type; +	struct target_revectored_struct int_revectored; +	struct target_revectored_struct int21_revectored; +	struct target_vm86plus_info_struct vm86plus; +}; + +#define UNAME_MACHINE "i686" +#define UNAME_MINIMUM_RELEASE "2.6.32" + +#define TARGET_CLONE_BACKWARDS +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_MLOCKALL_MCL_CURRENT 1 +#define TARGET_MLOCKALL_MCL_FUTURE  2 diff --git a/linux-user/i386/syscall_nr.h b/linux-user/i386/syscall_nr.h new file mode 100644 index 00000000..c8f73021 --- /dev/null +++ b/linux-user/i386/syscall_nr.h @@ -0,0 +1,355 @@ +/* + * This file contains the system call numbers. + */ + +#define TARGET_NR_restart_syscall      0 +#define TARGET_NR_exit		  1 +#define TARGET_NR_fork		  2 +#define TARGET_NR_read		  3 +#define TARGET_NR_write		  4 +#define TARGET_NR_open		  5 +#define TARGET_NR_close		  6 +#define TARGET_NR_waitpid		  7 +#define TARGET_NR_creat		  8 +#define TARGET_NR_link		  9 +#define TARGET_NR_unlink		 10 +#define TARGET_NR_execve		 11 +#define TARGET_NR_chdir		 12 +#define TARGET_NR_time		 13 +#define TARGET_NR_mknod		 14 +#define TARGET_NR_chmod		 15 +#define TARGET_NR_lchown		 16 +#define TARGET_NR_break		 17 +#define TARGET_NR_oldstat		 18 +#define TARGET_NR_lseek		 19 +#define TARGET_NR_getpid		 20 +#define TARGET_NR_mount		 21 +#define TARGET_NR_umount		 22 +#define TARGET_NR_setuid		 23 +#define TARGET_NR_getuid		 24 +#define TARGET_NR_stime		 25 +#define TARGET_NR_ptrace		 26 +#define TARGET_NR_alarm		 27 +#define TARGET_NR_oldfstat		 28 +#define TARGET_NR_pause		 29 +#define TARGET_NR_utime		 30 +#define TARGET_NR_stty		 31 +#define TARGET_NR_gtty		 32 +#define TARGET_NR_access		 33 +#define TARGET_NR_nice		 34 +#define TARGET_NR_ftime		 35 +#define TARGET_NR_sync		 36 +#define TARGET_NR_kill		 37 +#define TARGET_NR_rename		 38 +#define TARGET_NR_mkdir		 39 +#define TARGET_NR_rmdir		 40 +#define TARGET_NR_dup		 41 +#define TARGET_NR_pipe		 42 +#define TARGET_NR_times		 43 +#define TARGET_NR_prof		 44 +#define TARGET_NR_brk		 45 +#define TARGET_NR_setgid		 46 +#define TARGET_NR_getgid		 47 +#define TARGET_NR_signal		 48 +#define TARGET_NR_geteuid		 49 +#define TARGET_NR_getegid		 50 +#define TARGET_NR_acct		 51 +#define TARGET_NR_umount2		 52 +#define TARGET_NR_lock		 53 +#define TARGET_NR_ioctl		 54 +#define TARGET_NR_fcntl		 55 +#define TARGET_NR_mpx		 56 +#define TARGET_NR_setpgid		 57 +#define TARGET_NR_ulimit		 58 +#define TARGET_NR_oldolduname	 59 +#define TARGET_NR_umask		 60 +#define TARGET_NR_chroot		 61 +#define TARGET_NR_ustat		 62 +#define TARGET_NR_dup2		 63 +#define TARGET_NR_getppid		 64 +#define TARGET_NR_getpgrp		 65 +#define TARGET_NR_setsid		 66 +#define TARGET_NR_sigaction		 67 +#define TARGET_NR_sgetmask		 68 +#define TARGET_NR_ssetmask		 69 +#define TARGET_NR_setreuid		 70 +#define TARGET_NR_setregid		 71 +#define TARGET_NR_sigsuspend		 72 +#define TARGET_NR_sigpending		 73 +#define TARGET_NR_sethostname	 74 +#define TARGET_NR_setrlimit		 75 +#define TARGET_NR_getrlimit		 76	/* Back compatible 2Gig limited rlimit */ +#define TARGET_NR_getrusage		 77 +#define TARGET_NR_gettimeofday	 78 +#define TARGET_NR_settimeofday	 79 +#define TARGET_NR_getgroups		 80 +#define TARGET_NR_setgroups		 81 +#define TARGET_NR_select		 82 +#define TARGET_NR_symlink		 83 +#define TARGET_NR_oldlstat		 84 +#define TARGET_NR_readlink		 85 +#define TARGET_NR_uselib		 86 +#define TARGET_NR_swapon		 87 +#define TARGET_NR_reboot		 88 +#define TARGET_NR_readdir		 89 +#define TARGET_NR_mmap		 90 +#define TARGET_NR_munmap		 91 +#define TARGET_NR_truncate		 92 +#define TARGET_NR_ftruncate		 93 +#define TARGET_NR_fchmod		 94 +#define TARGET_NR_fchown		 95 +#define TARGET_NR_getpriority	 96 +#define TARGET_NR_setpriority	 97 +#define TARGET_NR_profil		 98 +#define TARGET_NR_statfs		 99 +#define TARGET_NR_fstatfs		100 +#define TARGET_NR_ioperm		101 +#define TARGET_NR_socketcall		102 +#define TARGET_NR_syslog		103 +#define TARGET_NR_setitimer		104 +#define TARGET_NR_getitimer		105 +#define TARGET_NR_stat		106 +#define TARGET_NR_lstat		107 +#define TARGET_NR_fstat		108 +#define TARGET_NR_olduname		109 +#define TARGET_NR_iopl		110 +#define TARGET_NR_vhangup		111 +#define TARGET_NR_idle		112 +#define TARGET_NR_vm86old		113 +#define TARGET_NR_wait4		114 +#define TARGET_NR_swapoff		115 +#define TARGET_NR_sysinfo		116 +#define TARGET_NR_ipc		117 +#define TARGET_NR_fsync		118 +#define TARGET_NR_sigreturn		119 +#define TARGET_NR_clone		120 +#define TARGET_NR_setdomainname	121 +#define TARGET_NR_uname		122 +#define TARGET_NR_modify_ldt		123 +#define TARGET_NR_adjtimex		124 +#define TARGET_NR_mprotect		125 +#define TARGET_NR_sigprocmask	126 +#define TARGET_NR_create_module	127 +#define TARGET_NR_init_module	128 +#define TARGET_NR_delete_module	129 +#define TARGET_NR_get_kernel_syms	130 +#define TARGET_NR_quotactl		131 +#define TARGET_NR_getpgid		132 +#define TARGET_NR_fchdir		133 +#define TARGET_NR_bdflush		134 +#define TARGET_NR_sysfs		135 +#define TARGET_NR_personality	136 +#define TARGET_NR_afs_syscall	137 /* Syscall for Andrew File System */ +#define TARGET_NR_setfsuid		138 +#define TARGET_NR_setfsgid		139 +#define TARGET_NR__llseek		140 +#define TARGET_NR_getdents		141 +#define TARGET_NR__newselect		142 +#define TARGET_NR_flock		143 +#define TARGET_NR_msync		144 +#define TARGET_NR_readv		145 +#define TARGET_NR_writev		146 +#define TARGET_NR_getsid		147 +#define TARGET_NR_fdatasync		148 +#define TARGET_NR__sysctl		149 +#define TARGET_NR_mlock		150 +#define TARGET_NR_munlock		151 +#define TARGET_NR_mlockall		152 +#define TARGET_NR_munlockall		153 +#define TARGET_NR_sched_setparam		154 +#define TARGET_NR_sched_getparam		155 +#define TARGET_NR_sched_setscheduler		156 +#define TARGET_NR_sched_getscheduler		157 +#define TARGET_NR_sched_yield		158 +#define TARGET_NR_sched_get_priority_max	159 +#define TARGET_NR_sched_get_priority_min	160 +#define TARGET_NR_sched_rr_get_interval	161 +#define TARGET_NR_nanosleep		162 +#define TARGET_NR_mremap		163 +#define TARGET_NR_setresuid		164 +#define TARGET_NR_getresuid		165 +#define TARGET_NR_vm86		166 +#define TARGET_NR_query_module	167 +#define TARGET_NR_poll		168 +#define TARGET_NR_nfsservctl		169 +#define TARGET_NR_setresgid		170 +#define TARGET_NR_getresgid		171 +#define TARGET_NR_prctl              172 +#define TARGET_NR_rt_sigreturn	173 +#define TARGET_NR_rt_sigaction	174 +#define TARGET_NR_rt_sigprocmask	175 +#define TARGET_NR_rt_sigpending	176 +#define TARGET_NR_rt_sigtimedwait	177 +#define TARGET_NR_rt_sigqueueinfo	178 +#define TARGET_NR_rt_sigsuspend	179 +#define TARGET_NR_pread64               180 +#define TARGET_NR_pwrite64              181 +#define TARGET_NR_chown		182 +#define TARGET_NR_getcwd		183 +#define TARGET_NR_capget		184 +#define TARGET_NR_capset		185 +#define TARGET_NR_sigaltstack	186 +#define TARGET_NR_sendfile		187 +#define TARGET_NR_getpmsg		188	/* some people actually want streams */ +#define TARGET_NR_putpmsg		189	/* some people actually want streams */ +#define TARGET_NR_vfork		190 +#define TARGET_NR_ugetrlimit		191	/* SuS compliant getrlimit */ +#define TARGET_NR_mmap2		192 +#define TARGET_NR_truncate64		193 +#define TARGET_NR_ftruncate64	194 +#define TARGET_NR_stat64		195 +#define TARGET_NR_lstat64		196 +#define TARGET_NR_fstat64		197 +#define TARGET_NR_lchown32		198 +#define TARGET_NR_getuid32		199 +#define TARGET_NR_getgid32		200 +#define TARGET_NR_geteuid32		201 +#define TARGET_NR_getegid32		202 +#define TARGET_NR_setreuid32		203 +#define TARGET_NR_setregid32		204 +#define TARGET_NR_getgroups32	205 +#define TARGET_NR_setgroups32	206 +#define TARGET_NR_fchown32		207 +#define TARGET_NR_setresuid32	208 +#define TARGET_NR_getresuid32	209 +#define TARGET_NR_setresgid32	210 +#define TARGET_NR_getresgid32	211 +#define TARGET_NR_chown32		212 +#define TARGET_NR_setuid32		213 +#define TARGET_NR_setgid32		214 +#define TARGET_NR_setfsuid32		215 +#define TARGET_NR_setfsgid32		216 +#define TARGET_NR_pivot_root		217 +#define TARGET_NR_mincore		218 +#define TARGET_NR_madvise		219 +#define TARGET_NR_madvise1		219	/* delete when C lib stub is removed */ +#define TARGET_NR_getdents64		220 +#define TARGET_NR_fcntl64		221 +/* 223 is unused */ +#define TARGET_NR_gettid		224 +#define TARGET_NR_readahead		225 +#define TARGET_NR_setxattr		226 +#define TARGET_NR_lsetxattr		227 +#define TARGET_NR_fsetxattr		228 +#define TARGET_NR_getxattr		229 +#define TARGET_NR_lgetxattr		230 +#define TARGET_NR_fgetxattr		231 +#define TARGET_NR_listxattr		232 +#define TARGET_NR_llistxattr		233 +#define TARGET_NR_flistxattr		234 +#define TARGET_NR_removexattr	235 +#define TARGET_NR_lremovexattr	236 +#define TARGET_NR_fremovexattr	237 +#define TARGET_NR_tkill		238 +#define TARGET_NR_sendfile64		239 +#define TARGET_NR_futex		240 +#define TARGET_NR_sched_setaffinity	241 +#define TARGET_NR_sched_getaffinity	242 +#define TARGET_NR_set_thread_area	243 +#define TARGET_NR_get_thread_area	244 +#define TARGET_NR_io_setup		245 +#define TARGET_NR_io_destroy		246 +#define TARGET_NR_io_getevents	247 +#define TARGET_NR_io_submit		248 +#define TARGET_NR_io_cancel		249 +#define TARGET_NR_fadvise64		250 +/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */ +#define TARGET_NR_exit_group		252 +#define TARGET_NR_lookup_dcookie	253 +#define TARGET_NR_epoll_create	254 +#define TARGET_NR_epoll_ctl		255 +#define TARGET_NR_epoll_wait		256 +#define TARGET_NR_remap_file_pages	257 +#define TARGET_NR_set_tid_address	258 +#define TARGET_NR_timer_create	259 +#define TARGET_NR_timer_settime	(TARGET_NR_timer_create+1) +#define TARGET_NR_timer_gettime	(TARGET_NR_timer_create+2) +#define TARGET_NR_timer_getoverrun	(TARGET_NR_timer_create+3) +#define TARGET_NR_timer_delete	(TARGET_NR_timer_create+4) +#define TARGET_NR_clock_settime	(TARGET_NR_timer_create+5) +#define TARGET_NR_clock_gettime	(TARGET_NR_timer_create+6) +#define TARGET_NR_clock_getres	(TARGET_NR_timer_create+7) +#define TARGET_NR_clock_nanosleep	(TARGET_NR_timer_create+8) +#define TARGET_NR_statfs64		268 +#define TARGET_NR_fstatfs64		269 +#define TARGET_NR_tgkill		270 +#define TARGET_NR_utimes		271 +#define TARGET_NR_fadvise64_64	272 +#define TARGET_NR_vserver		273 +#define TARGET_NR_mbind		274 +#define TARGET_NR_get_mempolicy	275 +#define TARGET_NR_set_mempolicy	276 +#define TARGET_NR_mq_open 		277 +#define TARGET_NR_mq_unlink		(TARGET_NR_mq_open+1) +#define TARGET_NR_mq_timedsend	(TARGET_NR_mq_open+2) +#define TARGET_NR_mq_timedreceive	(TARGET_NR_mq_open+3) +#define TARGET_NR_mq_notify		(TARGET_NR_mq_open+4) +#define TARGET_NR_mq_getsetattr	(TARGET_NR_mq_open+5) +#define TARGET_NR_kexec_load		283 +#define TARGET_NR_waitid		284 +/* #define TARGET_NR_sys_setaltroot	285 */ +#define TARGET_NR_add_key		286 +#define TARGET_NR_request_key	287 +#define TARGET_NR_keyctl		288 +#define TARGET_NR_ioprio_set		289 +#define TARGET_NR_ioprio_get		290 +#define TARGET_NR_inotify_init	291 +#define TARGET_NR_inotify_add_watch	292 +#define TARGET_NR_inotify_rm_watch	293 +#define TARGET_NR_migrate_pages	294 +#define TARGET_NR_openat		295 +#define TARGET_NR_mkdirat		296 +#define TARGET_NR_mknodat		297 +#define TARGET_NR_fchownat		298 +#define TARGET_NR_futimesat		299 +#define TARGET_NR_fstatat64		300 +#define TARGET_NR_unlinkat		301 +#define TARGET_NR_renameat		302 +#define TARGET_NR_linkat		303 +#define TARGET_NR_symlinkat		304 +#define TARGET_NR_readlinkat		305 +#define TARGET_NR_fchmodat		306 +#define TARGET_NR_faccessat		307 +#define TARGET_NR_pselect6		308 +#define TARGET_NR_ppoll		309 +#define TARGET_NR_unshare		310 +#define TARGET_NR_set_robust_list	311 +#define TARGET_NR_get_robust_list	312 +#define TARGET_NR_splice		313 +#define TARGET_NR_sync_file_range	314 +#define TARGET_NR_tee		315 +#define TARGET_NR_vmsplice		316 +#define TARGET_NR_move_pages		317 +#define TARGET_NR_getcpu		318 +#define TARGET_NR_epoll_pwait	319 +#define TARGET_NR_utimensat		320 +#define TARGET_NR_signalfd		321 +#define TARGET_NR_timerfd		322 +#define TARGET_NR_eventfd		323 +#define TARGET_NR_fallocate		324 +#define TARGET_NR_timerfd_settime	325 +#define TARGET_NR_timerfd_gettime	326 +#define TARGET_NR_signalfd4		327 +#define TARGET_NR_eventfd2		328 +#define TARGET_NR_epoll_create1	329 +#define TARGET_NR_dup3			330 +#define TARGET_NR_pipe2		331 +#define TARGET_NR_inotify_init1	332 +#define TARGET_NR_preadv                333 +#define TARGET_NR_pwritev               334 +#define TARGET_NR_rt_tgsigqueueinfo     335 +#define TARGET_NR_perf_event_open       336 +#define TARGET_NR_recvmmsg              337 +#define TARGET_NR_fanotify_init         338 +#define TARGET_NR_fanotify_mark         339 +#define TARGET_NR_prlimit64             340 +#define TARGET_NR_name_to_handle_at     341 +#define TARGET_NR_open_by_handle_at     342 +#define TARGET_NR_clock_adjtime         343 +#define TARGET_NR_syncfs                344 +#define TARGET_NR_sendmmsg              345 +#define TARGET_NR_setns                 346 +#define TARGET_NR_process_vm_readv      347 +#define TARGET_NR_process_vm_writev     348 +#define TARGET_NR_kcmp                  349 +#define TARGET_NR_finit_module          350 diff --git a/linux-user/i386/target_cpu.h b/linux-user/i386/target_cpu.h new file mode 100644 index 00000000..58f86454 --- /dev/null +++ b/linux-user/i386/target_cpu.h @@ -0,0 +1,48 @@ +/* + * i386 specific CPU ABI and functions for linux-user + * + *  Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUX86State *env, target_ulong newsp) +{ +    if (newsp) { +        env->regs[R_ESP] = newsp; +    } +    env->regs[R_EAX] = 0; +} + +#if defined(TARGET_ABI32) +abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr); + +static inline void cpu_set_tls(CPUX86State *env, target_ulong newtls) +{ +    do_set_thread_area(env, newtls); +    cpu_x86_load_seg(env, R_GS, env->segs[R_GS].selector); +} +#else +abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr); + +static inline void cpu_set_tls(CPUX86State *env, target_ulong newtls) +{ +    do_arch_prctl(env, TARGET_ARCH_SET_FS, newtls); +} +#endif /* defined(TARGET_ABI32) */ + +#endif /* !defined(TARGET_CPU_H) */ diff --git a/linux-user/i386/target_signal.h b/linux-user/i386/target_signal.h new file mode 100644 index 00000000..9baf7fbe --- /dev/null +++ b/linux-user/i386/target_signal.h @@ -0,0 +1,29 @@ +#ifndef TARGET_SIGNAL_H +#define TARGET_SIGNAL_H + +#include "cpu.h" + +/* this struct defines a stack used during syscall handling */ + +typedef struct target_sigaltstack { +	abi_ulong ss_sp; +	abi_long ss_flags; +	abi_ulong ss_size; +} target_stack_t; + + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK	1 +#define TARGET_SS_DISABLE	2 + +#define TARGET_MINSIGSTKSZ	2048 +#define TARGET_SIGSTKSZ		8192 + +static inline abi_ulong get_sp_from_cpustate(CPUX86State *state) +{ +    return state->regs[R_ESP]; +} + +#endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/i386/target_structs.h b/linux-user/i386/target_structs.h new file mode 100644 index 00000000..65f535e1 --- /dev/null +++ b/linux-user/i386/target_structs.h @@ -0,0 +1,58 @@ +/* + * i386 specific structures for linux-user + * + * Copyright (c) 2013 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_STRUCTS_H +#define TARGET_STRUCTS_H + +struct target_ipc_perm { +    abi_int __key;                      /* Key.  */ +    abi_uint uid;                       /* Owner's user ID.  */ +    abi_uint gid;                       /* Owner's group ID.  */ +    abi_uint cuid;                      /* Creator's user ID.  */ +    abi_uint cgid;                      /* Creator's group ID.  */ +    abi_ushort mode;                    /* Read/write permission.  */ +    abi_ushort __pad1; +    abi_ushort __seq;                   /* Sequence number.  */ +    abi_ushort __pad2; +    abi_ulong __unused1; +    abi_ulong __unused2; +}; + +struct target_shmid_ds { +    struct target_ipc_perm shm_perm;    /* operation permission struct */ +    abi_long shm_segsz;                 /* size of segment in bytes */ +    abi_ulong shm_atime;                /* time of last shmat() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused1; +#endif +    abi_ulong shm_dtime;                /* time of last shmdt() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused2; +#endif +    abi_ulong shm_ctime;                /* time of last change by shmctl() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused3; +#endif +    abi_int shm_cpid;                   /* pid of creator */ +    abi_int shm_lpid;                   /* pid of last shmop */ +    abi_ulong shm_nattch;               /* number of current attaches */ +    abi_ulong __unused4; +    abi_ulong __unused5; +}; + +#endif diff --git a/linux-user/i386/termbits.h b/linux-user/i386/termbits.h new file mode 100644 index 00000000..e051a3af --- /dev/null +++ b/linux-user/i386/termbits.h @@ -0,0 +1,226 @@ +/* from asm/termbits.h */ + +#define TARGET_NCCS 19 + +struct target_termios { +    unsigned int c_iflag;               /* input mode flags */ +    unsigned int c_oflag;               /* output mode flags */ +    unsigned int c_cflag;               /* control mode flags */ +    unsigned int c_lflag;               /* local mode flags */ +    unsigned char c_line;                    /* line discipline */ +    unsigned char c_cc[TARGET_NCCS];                /* control characters */ +}; + +/* c_iflag bits */ +#define TARGET_IGNBRK  0000001 +#define TARGET_BRKINT  0000002 +#define TARGET_IGNPAR  0000004 +#define TARGET_PARMRK  0000010 +#define TARGET_INPCK   0000020 +#define TARGET_ISTRIP  0000040 +#define TARGET_INLCR   0000100 +#define TARGET_IGNCR   0000200 +#define TARGET_ICRNL   0000400 +#define TARGET_IUCLC   0001000 +#define TARGET_IXON    0002000 +#define TARGET_IXANY   0004000 +#define TARGET_IXOFF   0010000 +#define TARGET_IMAXBEL 0020000 +#define TARGET_IUTF8   0040000 + +/* c_oflag bits */ +#define TARGET_OPOST   0000001 +#define TARGET_OLCUC   0000002 +#define TARGET_ONLCR   0000004 +#define TARGET_OCRNL   0000010 +#define TARGET_ONOCR   0000020 +#define TARGET_ONLRET  0000040 +#define TARGET_OFILL   0000100 +#define TARGET_OFDEL   0000200 +#define TARGET_NLDLY   0000400 +#define   TARGET_NL0   0000000 +#define   TARGET_NL1   0000400 +#define TARGET_CRDLY   0003000 +#define   TARGET_CR0   0000000 +#define   TARGET_CR1   0001000 +#define   TARGET_CR2   0002000 +#define   TARGET_CR3   0003000 +#define TARGET_TABDLY  0014000 +#define   TARGET_TAB0  0000000 +#define   TARGET_TAB1  0004000 +#define   TARGET_TAB2  0010000 +#define   TARGET_TAB3  0014000 +#define   TARGET_XTABS 0014000 +#define TARGET_BSDLY   0020000 +#define   TARGET_BS0   0000000 +#define   TARGET_BS1   0020000 +#define TARGET_VTDLY   0040000 +#define   TARGET_VT0   0000000 +#define   TARGET_VT1   0040000 +#define TARGET_FFDLY   0100000 +#define   TARGET_FF0   0000000 +#define   TARGET_FF1   0100000 + +/* c_cflag bit meaning */ +#define TARGET_CBAUD   0010017 +#define  TARGET_B0     0000000         /* hang up */ +#define  TARGET_B50    0000001 +#define  TARGET_B75    0000002 +#define  TARGET_B110   0000003 +#define  TARGET_B134   0000004 +#define  TARGET_B150   0000005 +#define  TARGET_B200   0000006 +#define  TARGET_B300   0000007 +#define  TARGET_B600   0000010 +#define  TARGET_B1200  0000011 +#define  TARGET_B1800  0000012 +#define  TARGET_B2400  0000013 +#define  TARGET_B4800  0000014 +#define  TARGET_B9600  0000015 +#define  TARGET_B19200 0000016 +#define  TARGET_B38400 0000017 +#define TARGET_EXTA B19200 +#define TARGET_EXTB B38400 +#define TARGET_CSIZE   0000060 +#define   TARGET_CS5   0000000 +#define   TARGET_CS6   0000020 +#define   TARGET_CS7   0000040 +#define   TARGET_CS8   0000060 +#define TARGET_CSTOPB  0000100 +#define TARGET_CREAD   0000200 +#define TARGET_PARENB  0000400 +#define TARGET_PARODD  0001000 +#define TARGET_HUPCL   0002000 +#define TARGET_CLOCAL  0004000 +#define TARGET_CBAUDEX 0010000 +#define  TARGET_B57600  0010001 +#define  TARGET_B115200 0010002 +#define  TARGET_B230400 0010003 +#define  TARGET_B460800 0010004 +#define  TARGET_B500000 0010005 +#define  TARGET_B576000 0010006 +#define  TARGET_B921600 0010007 +#define  TARGET_B1000000 0010010 +#define  TARGET_B1152000 0010011 +#define  TARGET_B1500000 0010012 +#define  TARGET_B2000000 0010013 +#define  TARGET_B2500000 0010014 +#define  TARGET_B3000000 0010015 +#define  TARGET_B3500000 0010016 +#define  TARGET_B4000000 0010017 +#define TARGET_CIBAUD    002003600000  /* input baud rate (not used) */ +#define TARGET_CMSPAR    010000000000  /* mark or space (stick) parity */ +#define TARGET_CRTSCTS   020000000000  /* flow control */ + +/* c_lflag bits */ +#define TARGET_ISIG    0000001 +#define TARGET_ICANON  0000002 +#define TARGET_XCASE   0000004 +#define TARGET_ECHO    0000010 +#define TARGET_ECHOE   0000020 +#define TARGET_ECHOK   0000040 +#define TARGET_ECHONL  0000100 +#define TARGET_NOFLSH  0000200 +#define TARGET_TOSTOP  0000400 +#define TARGET_ECHOCTL 0001000 +#define TARGET_ECHOPRT 0002000 +#define TARGET_ECHOKE  0004000 +#define TARGET_FLUSHO  0010000 +#define TARGET_PENDIN  0040000 +#define TARGET_IEXTEN  0100000 + +/* c_cc character offsets */ +#define TARGET_VINTR	0 +#define TARGET_VQUIT	1 +#define TARGET_VERASE	2 +#define TARGET_VKILL	3 +#define TARGET_VEOF	4 +#define TARGET_VTIME	5 +#define TARGET_VMIN	6 +#define TARGET_VSWTC	7 +#define TARGET_VSTART	8 +#define TARGET_VSTOP	9 +#define TARGET_VSUSP	10 +#define TARGET_VEOL	11 +#define TARGET_VREPRINT	12 +#define TARGET_VDISCARD	13 +#define TARGET_VWERASE	14 +#define TARGET_VLNEXT	15 +#define TARGET_VEOL2	16 + +/* ioctls */ + +#define TARGET_TCGETS		0x5401 +#define TARGET_TCSETS		0x5402 +#define TARGET_TCSETSW		0x5403 +#define TARGET_TCSETSF		0x5404 +#define TARGET_TCGETA		0x5405 +#define TARGET_TCSETA		0x5406 +#define TARGET_TCSETAW		0x5407 +#define TARGET_TCSETAF		0x5408 +#define TARGET_TCSBRK		0x5409 +#define TARGET_TCXONC		0x540A +#define TARGET_TCFLSH		0x540B + +#define TARGET_TIOCEXCL	0x540C +#define TARGET_TIOCNXCL	0x540D +#define TARGET_TIOCSCTTY	0x540E +#define TARGET_TIOCGPGRP	0x540F +#define TARGET_TIOCSPGRP	0x5410 +#define TARGET_TIOCOUTQ	0x5411 +#define TARGET_TIOCSTI		0x5412 +#define TARGET_TIOCGWINSZ	0x5413 +#define TARGET_TIOCSWINSZ	0x5414 +#define TARGET_TIOCMGET	0x5415 +#define TARGET_TIOCMBIS	0x5416 +#define TARGET_TIOCMBIC	0x5417 +#define TARGET_TIOCMSET	0x5418 +#define TARGET_TIOCGSOFTCAR	0x5419 +#define TARGET_TIOCSSOFTCAR	0x541A +#define TARGET_FIONREAD	0x541B +#define TARGET_TIOCINQ		TARGET_FIONREAD +#define TARGET_TIOCLINUX	0x541C +#define TARGET_TIOCCONS	0x541D +#define TARGET_TIOCGSERIAL	0x541E +#define TARGET_TIOCSSERIAL	0x541F +#define TARGET_TIOCPKT		0x5420 +#define TARGET_FIONBIO		0x5421 +#define TARGET_TIOCNOTTY	0x5422 +#define TARGET_TIOCSETD	0x5423 +#define TARGET_TIOCGETD	0x5424 +#define TARGET_TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */ +#define TARGET_TIOCTTYGSTRUCT	0x5426  /* For debugging only */ +#define TARGET_TIOCSBRK	0x5427  /* BSD compatibility */ +#define TARGET_TIOCCBRK	0x5428  /* BSD compatibility */ +#define TARGET_TIOCGSID	0x5429  /* Return the session ID of FD */ +#define TARGET_TIOCGPTN	TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define TARGET_TIOCSPTLCK	TARGET_IOW('T',0x31, int)  /* Lock/unlock Pty */ + +#define TARGET_FIONCLEX	0x5450  /* these numbers need to be adjusted. */ +#define TARGET_FIOCLEX		0x5451 +#define TARGET_FIOASYNC	0x5452 +#define TARGET_TIOCSERCONFIG	0x5453 +#define TARGET_TIOCSERGWILD	0x5454 +#define TARGET_TIOCSERSWILD	0x5455 +#define TARGET_TIOCGLCKTRMIOS	0x5456 +#define TARGET_TIOCSLCKTRMIOS	0x5457 +#define TARGET_TIOCSERGSTRUCT	0x5458 /* For debugging only */ +#define TARGET_TIOCSERGETLSR   0x5459 /* Get line status register */ +#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config  */ +#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TARGET_TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */ +#define TARGET_TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */ +#define TARGET_TIOCGHAYESESP   0x545E  /* Get Hayes ESP configuration */ +#define TARGET_TIOCSHAYESESP   0x545F  /* Set Hayes ESP configuration */ + +/* Used for packet mode */ +#define TARGET_TIOCPKT_DATA		 0 +#define TARGET_TIOCPKT_FLUSHREAD	 1 +#define TARGET_TIOCPKT_FLUSHWRITE	 2 +#define TARGET_TIOCPKT_STOP		 4 +#define TARGET_TIOCPKT_START		 8 +#define TARGET_TIOCPKT_NOSTOP		16 +#define TARGET_TIOCPKT_DOSTOP		32 + +#define TARGET_TIOCSER_TEMT    0x01	/* Transmitter physically empty */ diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h new file mode 100644 index 00000000..e6726551 --- /dev/null +++ b/linux-user/ioctls.h @@ -0,0 +1,388 @@ +     /* emulated ioctl list */ + +     IOCTL(TCGETS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios))) +     IOCTL(TCSETS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios))) +     IOCTL(TCSETSF, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios))) +     IOCTL(TCSETSW, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios))) +     IOCTL(TIOCGWINSZ, IOC_R, MK_PTR(MK_STRUCT(STRUCT_winsize))) +     IOCTL(TIOCSWINSZ, IOC_W, MK_PTR(MK_STRUCT(STRUCT_winsize))) +     IOCTL(FIONREAD, IOC_R, MK_PTR(TYPE_INT)) +     IOCTL(TCGETA, IOC_R, MK_PTR(TYPE_INT)) +     IOCTL(TCSETA, IOC_W, MK_PTR(TYPE_INT)) +     IOCTL(TCSETAW, IOC_W, MK_PTR(TYPE_INT)) +     IOCTL(TCSETAF, IOC_W, MK_PTR(TYPE_INT)) +     IOCTL(TCSBRK, 0, TYPE_INT) +     IOCTL(TCSBRKP, 0, TYPE_INT) +     IOCTL(TCXONC, 0, TYPE_INT) +     IOCTL(TCFLSH, 0, TYPE_INT) +     IOCTL(TIOCEXCL, 0, TYPE_NULL) +     IOCTL(TIOCNXCL, 0, TYPE_NULL) +     IOCTL(TIOCSCTTY, 0, TYPE_INT) +     IOCTL(TIOCGPGRP, IOC_R, MK_PTR(TYPE_INT)) +     IOCTL(TIOCSPGRP, IOC_W, MK_PTR(TYPE_INT)) +     IOCTL(TIOCGSID, IOC_W, MK_PTR(TYPE_INT)) +     IOCTL(TIOCOUTQ, IOC_R, MK_PTR(TYPE_INT)) +     IOCTL(TIOCSTI, IOC_W, MK_PTR(TYPE_INT)) +     IOCTL(TIOCMGET, IOC_R, MK_PTR(TYPE_INT)) +     IOCTL(TIOCMBIS, IOC_W, MK_PTR(TYPE_INT)) +     IOCTL(TIOCMBIC, IOC_W, MK_PTR(TYPE_INT)) +     IOCTL(TIOCMSET, IOC_W, MK_PTR(TYPE_INT)) +     IOCTL(TIOCGSOFTCAR, IOC_R, MK_PTR(TYPE_INT)) +     IOCTL(TIOCSSOFTCAR, IOC_W, MK_PTR(TYPE_INT)) +     IOCTL(TIOCLINUX, IOC_R | IOC_W, MK_PTR(TYPE_INT)) +     IOCTL(TIOCCONS, 0, TYPE_NULL) +     IOCTL(TIOCGSERIAL, IOC_R, MK_PTR(TYPE_INT)) +     IOCTL(TIOCSSERIAL, IOC_W, MK_PTR(TYPE_INT)) +     IOCTL(TIOCPKT, IOC_W, MK_PTR(TYPE_INT)) +     IOCTL(FIONBIO, IOC_W, MK_PTR(TYPE_INT)) +     IOCTL(TIOCNOTTY, 0, TYPE_NULL) +     IOCTL(TIOCGETD, IOC_R, MK_PTR(TYPE_INT)) +     IOCTL(TIOCSETD, IOC_W, MK_PTR(TYPE_INT)) +     IOCTL(TIOCGPTN, IOC_R, MK_PTR(TYPE_INT)) +     IOCTL(TIOCSPTLCK, IOC_W, MK_PTR(TYPE_INT)) +     IOCTL(FIOCLEX, 0, TYPE_NULL) +     IOCTL(FIONCLEX, 0, TYPE_NULL) +     IOCTL(FIOASYNC, IOC_W, MK_PTR(TYPE_INT)) +     IOCTL(TIOCGLCKTRMIOS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios))) +     IOCTL(TIOCSLCKTRMIOS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios))) +     IOCTL(TIOCSERCONFIG, 0, TYPE_NULL) +     IOCTL(TIOCSERGETLSR, IOC_R, MK_PTR(TYPE_INT)) +     IOCTL(TIOCSERGETMULTI, IOC_R, MK_PTR(MK_STRUCT(STRUCT_serial_multiport_struct))) +     IOCTL(TIOCSERSETMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_serial_multiport_struct))) +     IOCTL(TIOCMIWAIT, 0, TYPE_INT) +     IOCTL(TIOCGICOUNT, IOC_R, MK_PTR(MK_STRUCT(STRUCT_serial_icounter_struct))) + +     IOCTL(KIOCSOUND, 0, TYPE_INT) +     IOCTL(KDMKTONE, 0, TYPE_INT) +     IOCTL(KDSETMODE, 0, TYPE_INT) +     IOCTL(KDGKBTYPE, IOC_R, MK_PTR(TYPE_CHAR)) +     IOCTL(KDGKBMODE, IOC_R, MK_PTR(TYPE_INT)) +     IOCTL(KDSKBMODE, 0, TYPE_INT) +     IOCTL(KDGKBENT, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_kbentry))) +     IOCTL(KDGKBSENT, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_kbsentry))) +     IOCTL(KDGKBLED, 0, TYPE_INT) +     IOCTL(KDSKBLED, 0, TYPE_INT) +     IOCTL(KDGETLED, 0, TYPE_INT) +     IOCTL(KDSETLED, 0, TYPE_INT) +     IOCTL_SPECIAL(KDSIGACCEPT, 0, do_ioctl_kdsigaccept, TYPE_INT) + +     IOCTL(BLKROSET, IOC_W, MK_PTR(TYPE_INT)) +     IOCTL(BLKROGET, IOC_R, MK_PTR(TYPE_INT)) +     IOCTL(BLKRRPART, 0, TYPE_NULL) +     IOCTL(BLKGETSIZE, IOC_R, MK_PTR(TYPE_ULONG)) +#ifdef BLKGETSIZE64 +     IOCTL(BLKGETSIZE64, IOC_R, MK_PTR(TYPE_ULONGLONG)) +#endif +     IOCTL(BLKFLSBUF, 0, TYPE_NULL) +     IOCTL(BLKRASET, 0, TYPE_INT) +     IOCTL(BLKRAGET, IOC_R, MK_PTR(TYPE_LONG)) +     IOCTL(BLKSSZGET, IOC_R, MK_PTR(TYPE_LONG)) +     IOCTL(BLKBSZGET, IOC_R, MK_PTR(TYPE_INT)) +     IOCTL_SPECIAL(BLKPG, IOC_W, do_ioctl_blkpg, +                   MK_PTR(MK_STRUCT(STRUCT_blkpg_ioctl_arg))) +#ifdef FIBMAP +     IOCTL(FIBMAP, IOC_W | IOC_R, MK_PTR(TYPE_LONG)) +#endif +#ifdef FIGETBSZ +     IOCTL(FIGETBSZ, IOC_R, MK_PTR(TYPE_LONG)) +#endif +#ifdef CONFIG_FIEMAP +     IOCTL_SPECIAL(FS_IOC_FIEMAP, IOC_W | IOC_R, do_ioctl_fs_ioc_fiemap, +                   MK_PTR(MK_STRUCT(STRUCT_fiemap))) +#endif + +  IOCTL(SIOCATMARK, 0, TYPE_NULL) +  IOCTL(SIOCGIFNAME, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SIOCGIFFLAGS, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq))) +  IOCTL(SIOCSIFFLAGS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_short_ifreq))) +  IOCTL(SIOCGIFADDR, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq))) +  IOCTL(SIOCSIFADDR, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq))) +  IOCTL(SIOCGIFBRDADDR, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq))) +  IOCTL(SIOCSIFBRDADDR, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq))) +  IOCTL(SIOCGIFDSTADDR, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq))) +  IOCTL(SIOCSIFDSTADDR, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq))) +  IOCTL(SIOCGIFNETMASK, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq))) +  IOCTL(SIOCSIFNETMASK, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq))) +  IOCTL(SIOCGIFHWADDR, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq))) +  IOCTL(SIOCSIFHWADDR, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq))) +  IOCTL(SIOCGIFTXQLEN, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq))) +  IOCTL(SIOCSIFTXQLEN, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq))) +  IOCTL(SIOCGIFMETRIC, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_int_ifreq))) +  IOCTL(SIOCSIFMETRIC, IOC_W, MK_PTR(MK_STRUCT(STRUCT_int_ifreq))) +  IOCTL(SIOCGIFMTU, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_int_ifreq))) +  IOCTL(SIOCSIFMTU, IOC_W, MK_PTR(MK_STRUCT(STRUCT_int_ifreq))) +  IOCTL(SIOCGIFMAP, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_ifmap_ifreq))) +  IOCTL(SIOCSIFMAP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_ifmap_ifreq))) +  IOCTL(SIOCGIFSLAVE, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_char_ifreq))) +  IOCTL(SIOCSIFSLAVE, IOC_W, MK_PTR(MK_STRUCT(STRUCT_char_ifreq))) +  IOCTL(SIOCGIFMEM, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_ptr_ifreq))) +  IOCTL(SIOCSIFMEM, IOC_W, MK_PTR(MK_STRUCT(STRUCT_ptr_ifreq))) +  IOCTL(SIOCADDMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq))) +  IOCTL(SIOCDELMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq))) +  IOCTL(SIOCGIFINDEX, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_int_ifreq))) +  IOCTL(SIOCSIFLINK, 0, TYPE_NULL) +  IOCTL_SPECIAL(SIOCGIFCONF, IOC_W | IOC_R, do_ioctl_ifconf, +                MK_PTR(MK_STRUCT(STRUCT_ifconf))) +  IOCTL(SIOCGIFENCAP, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SIOCSIFENCAP, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SIOCDARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq))) +  IOCTL(SIOCSARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq))) +  IOCTL(SIOCGARP, IOC_R, MK_PTR(MK_STRUCT(STRUCT_arpreq))) +  IOCTL(SIOCDRARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq))) +  IOCTL(SIOCSRARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq))) +  IOCTL(SIOCGRARP, IOC_R, MK_PTR(MK_STRUCT(STRUCT_arpreq))) +  IOCTL(SIOCGIWNAME, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_char_ifreq))) + +  IOCTL(CDROMPAUSE, 0, TYPE_NULL) +  IOCTL(CDROMSTART, 0, TYPE_NULL) +  IOCTL(CDROMSTOP, 0, TYPE_NULL) +  IOCTL(CDROMRESUME, 0, TYPE_NULL) +  IOCTL(CDROMEJECT, 0, TYPE_NULL) +  IOCTL(CDROMEJECT_SW, 0, TYPE_INT) +  IOCTL(CDROMCLOSETRAY, 0, TYPE_NULL) +  IOCTL(CDROMRESET, 0, TYPE_NULL) +  IOCTL(CDROMPLAYMSF, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(CDROMPLAYTRKIND, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(CDROMREADTOCHDR, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(CDROMREADTOCENTRY, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(CDROMVOLCTRL, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(CDROMSUBCHNL, IOC_RW, MK_PTR(TYPE_INT)) +  /* XXX: incorrect (need specific handling) */ +  IOCTL(CDROMREADAUDIO, IOC_W, MK_PTR(MK_STRUCT(STRUCT_cdrom_read_audio))) +  IOCTL(CDROMREADCOOKED, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(CDROMREADRAW, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(CDROMREADMODE1, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(CDROMREADMODE2, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(CDROMREADALL, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(CDROMMULTISESSION, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(CDROM_GET_UPC, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(CDROMVOLREAD, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(CDROMSEEK, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(CDROMPLAYBLK, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(CDROM_MEDIA_CHANGED, 0, TYPE_NULL) +  IOCTL(CDROM_SET_OPTIONS, 0, TYPE_INT) +  IOCTL(CDROM_CLEAR_OPTIONS, 0, TYPE_INT) +  IOCTL(CDROM_SELECT_SPEED, 0, TYPE_INT) +  IOCTL(CDROM_SELECT_DISC, 0, TYPE_INT) +  IOCTL(CDROM_DRIVE_STATUS, 0, TYPE_NULL) +  IOCTL(CDROM_DISC_STATUS, 0, TYPE_NULL) +  IOCTL(CDROMAUDIOBUFSIZ, 0, TYPE_INT) + +#if 0 +  IOCTL(SNDCTL_COPR_HALT, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_COPR_LOAD, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_COPR_RCODE, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_COPR_RCVMSG, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_COPR_RDATA, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_COPR_RESET, 0, TYPE_NULL) +  IOCTL(SNDCTL_COPR_RUN, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_COPR_SENDMSG, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_COPR_WCODE, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_COPR_WDATA, IOC_W, MK_PTR(TYPE_INT)) +#endif +  IOCTL(SNDCTL_DSP_CHANNELS, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_DSP_GETBLKSIZE, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_DSP_GETCAPS, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_DSP_GETFMTS, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_DSP_GETIPTR, IOC_R, MK_PTR(MK_STRUCT(STRUCT_count_info))) +  IOCTL(SNDCTL_DSP_GETOPTR, IOC_R, MK_PTR(MK_STRUCT(STRUCT_count_info))) +  IOCTL(SNDCTL_DSP_GETISPACE, IOC_R, MK_PTR(MK_STRUCT(STRUCT_audio_buf_info))) +  IOCTL(SNDCTL_DSP_GETOSPACE, IOC_R, MK_PTR(MK_STRUCT(STRUCT_audio_buf_info))) +  IOCTL(SNDCTL_DSP_GETTRIGGER, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_DSP_MAPINBUF, IOC_R, MK_PTR(MK_STRUCT(STRUCT_buffmem_desc))) +  IOCTL(SNDCTL_DSP_MAPOUTBUF, IOC_R, MK_PTR(MK_STRUCT(STRUCT_buffmem_desc))) +  IOCTL(SNDCTL_DSP_NONBLOCK, 0, TYPE_NULL) +  IOCTL(SNDCTL_DSP_POST, 0, TYPE_NULL) +  IOCTL(SNDCTL_DSP_RESET, 0, TYPE_NULL) +  IOCTL(SNDCTL_DSP_SETDUPLEX, 0, TYPE_NULL) +  IOCTL(SNDCTL_DSP_SETFMT, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_DSP_SETFRAGMENT, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_DSP_SETSYNCRO, 0, TYPE_NULL) +  IOCTL(SNDCTL_DSP_SETTRIGGER, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_DSP_SPEED, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_DSP_STEREO, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_DSP_SUBDIVIDE, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_DSP_SYNC, 0, TYPE_NULL) +#if 0 +  IOCTL(SNDCTL_FM_4OP_ENABLE, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_FM_LOAD_INSTR, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_MIDI_INFO, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_MIDI_MPUCMD, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_MIDI_MPUMODE, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_MIDI_PRETIME, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_SEQ_CTRLRATE, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_SEQ_GETINCOUNT, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_SEQ_GETOUTCOUNT, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_SEQ_NRMIDIS, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_SEQ_NRSYNTHS, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_SEQ_OUTOFBAND, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_SEQ_PANIC, 0, TYPE_NULL) +  IOCTL(SNDCTL_SEQ_PERCMODE, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_SEQ_RESET, 0, TYPE_NULL) +  IOCTL(SNDCTL_SEQ_RESETSAMPLES, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_SEQ_SYNC, 0, TYPE_NULL) +  IOCTL(SNDCTL_SEQ_TESTMIDI, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_SEQ_THRESHOLD, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_SYNTH_INFO, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_SYNTH_MEMAVL, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_TMR_CONTINUE, 0, TYPE_NULL) +  IOCTL(SNDCTL_TMR_METRONOME, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_TMR_SELECT, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_TMR_SOURCE, IOC_RW, MK_PTR(TYPE_INT)) +#if 0 +     /* we invalidate these defines because they have a same number as +        termios ioctls */ +  IOCTL(SNDCTL_TMR_START, 0, TYPE_NULL) +  IOCTL(SNDCTL_TMR_STOP, 0, TYPE_NULL) +#endif +  IOCTL(SNDCTL_TMR_TEMPO, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SNDCTL_TMR_TIMEBASE, IOC_RW, MK_PTR(TYPE_INT)) + +  IOCTL(SOUND_PCM_WRITE_FILTER, IOC_W | IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_PCM_READ_RATE, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_PCM_READ_CHANNELS, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_PCM_READ_BITS, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_PCM_READ_FILTER, IOC_R, MK_PTR(TYPE_INT)) +#endif +  IOCTL(SOUND_MIXER_INFO, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_ACCESS, 0, TYPE_PTRVOID) +  IOCTL(SOUND_MIXER_PRIVATE1, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_PRIVATE2, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_PRIVATE3, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_PRIVATE4, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_PRIVATE5, IOC_RW, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_VOLUME, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_BASS, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_TREBLE, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_SYNTH, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_PCM, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_SPEAKER, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_LINE, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_MIC, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_CD, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_IMIX, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_ALTPCM, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_RECLEV, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_IGAIN, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_OGAIN, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_LINE1, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_LINE2, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_LINE3, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_MUTE, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_ENHANCE, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_LOUD, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_RECSRC, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_DEVMASK, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_RECMASK, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_STEREODEVS, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_READ_CAPS, IOC_R, MK_PTR(TYPE_INT)) + +  IOCTL(SOUND_MIXER_WRITE_VOLUME, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_WRITE_BASS, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_WRITE_TREBLE, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_WRITE_SYNTH, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_WRITE_PCM, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_WRITE_SPEAKER, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_WRITE_LINE, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_WRITE_MIC, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_WRITE_CD, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_WRITE_IMIX, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_WRITE_ALTPCM, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_WRITE_RECLEV, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_WRITE_IGAIN, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_WRITE_OGAIN, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_WRITE_LINE1, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_WRITE_LINE2, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_WRITE_LINE3, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_WRITE_MUTE, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_WRITE_ENHANCE, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_WRITE_LOUD, IOC_W, MK_PTR(TYPE_INT)) +  IOCTL(SOUND_MIXER_WRITE_RECSRC, IOC_W, MK_PTR(TYPE_INT)) + +  IOCTL(HDIO_GETGEO, IOC_R, MK_PTR(MK_STRUCT(STRUCT_hd_geometry))) +  IOCTL(HDIO_GET_UNMASKINTR, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(HDIO_GET_MULTCOUNT, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(HDIO_GET_IDENTITY, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(HDIO_GET_KEEPSETTINGS, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(HDIO_GET_NOWERR, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(HDIO_GET_DMA, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(HDIO_GET_32BIT, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(HDIO_DRIVE_CMD, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(HDIO_SET_UNMASKINTR, 0, TYPE_INT) +  IOCTL(HDIO_SET_MULTCOUNT, 0, TYPE_INT) +  IOCTL(HDIO_SET_KEEPSETTINGS, 0, TYPE_INT) +  IOCTL(HDIO_SET_NOWERR, 0, TYPE_INT) +  IOCTL(HDIO_SET_DMA, 0, TYPE_INT) +  IOCTL(HDIO_SET_32BIT, 0, TYPE_INT) +  IOCTL(HDIO_SET_PIO_MODE, 0, TYPE_INT) + +  IOCTL(VFAT_IOCTL_READDIR_BOTH, IOC_R, MK_PTR(MK_ARRAY(MK_STRUCT(STRUCT_dirent), 2))) +  IOCTL(VFAT_IOCTL_READDIR_SHORT, IOC_R, MK_PTR(MK_ARRAY(MK_STRUCT(STRUCT_dirent), 2))) + +  IOCTL(LOOP_SET_FD, 0, TYPE_INT) +  IOCTL(LOOP_CLR_FD, 0, TYPE_INT) +  IOCTL(LOOP_SET_STATUS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info))) +  IOCTL(LOOP_GET_STATUS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info))) +  IOCTL(LOOP_SET_STATUS64, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info64))) +  IOCTL(LOOP_GET_STATUS64, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info64))) +  IOCTL(LOOP_CHANGE_FD, 0, TYPE_INT) + +  IOCTL(MTIOCTOP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_mtop))) +  IOCTL(MTIOCGET, IOC_R, MK_PTR(MK_STRUCT(STRUCT_mtget))) +  IOCTL(MTIOCPOS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_mtpos))) + +  IOCTL(FBIOGET_FSCREENINFO, IOC_R, MK_PTR(MK_STRUCT(STRUCT_fb_fix_screeninfo))) +  IOCTL(FBIOGET_VSCREENINFO, IOC_R, MK_PTR(MK_STRUCT(STRUCT_fb_var_screeninfo))) +  IOCTL(FBIOPUT_VSCREENINFO, IOC_W, MK_PTR(MK_STRUCT(STRUCT_fb_var_screeninfo))) +  IOCTL(FBIOGETCMAP,        IOC_RW, MK_PTR(MK_STRUCT(STRUCT_fb_cmap))) +  IOCTL(FBIOPUTCMAP,        IOC_RW, MK_PTR(MK_STRUCT(STRUCT_fb_cmap))) +  IOCTL(FBIOPAN_DISPLAY,    IOC_RW, MK_PTR(MK_STRUCT(STRUCT_fb_var_screeninfo))) +  IOCTL(FBIOGET_CON2FBMAP,  IOC_RW, MK_PTR(MK_STRUCT(STRUCT_fb_con2fbmap))) +  IOCTL(FBIOPUT_CON2FBMAP,  IOC_RW, MK_PTR(MK_STRUCT(STRUCT_fb_con2fbmap))) + +  IOCTL(VT_OPENQRY, IOC_R, MK_PTR(TYPE_INT)) +  IOCTL(VT_GETSTATE, IOC_R, MK_PTR(MK_STRUCT(STRUCT_vt_stat))) +  IOCTL(VT_ACTIVATE, 0, TYPE_INT) +  IOCTL(VT_WAITACTIVE, 0, TYPE_INT) +  IOCTL(VT_LOCKSWITCH, 0, TYPE_INT) +  IOCTL(VT_UNLOCKSWITCH, 0, TYPE_INT) +  IOCTL(VT_GETMODE, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_vt_mode))) +  IOCTL(VT_SETMODE, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_vt_mode))) +  IOCTL(VT_RELDISP, 0, TYPE_INT) +  IOCTL(VT_DISALLOCATE, 0, TYPE_INT) + +  IOCTL(DM_VERSION, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_dm_ioctl))) +  IOCTL_SPECIAL(DM_REMOVE_ALL,   IOC_RW, do_ioctl_dm, +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl))) +  IOCTL_SPECIAL(DM_LIST_DEVICES, IOC_RW, do_ioctl_dm, +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl))) +  IOCTL_SPECIAL(DM_DEV_CREATE,   IOC_RW, do_ioctl_dm, +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl))) +  IOCTL_SPECIAL(DM_DEV_REMOVE,   IOC_RW, do_ioctl_dm, +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl))) +  IOCTL_SPECIAL(DM_DEV_RENAME,   IOC_RW, do_ioctl_dm, +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl))) +  IOCTL_SPECIAL(DM_DEV_SUSPEND,  IOC_RW, do_ioctl_dm, +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl))) +  IOCTL_SPECIAL(DM_DEV_STATUS,   IOC_RW, do_ioctl_dm, +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl))) +  IOCTL_SPECIAL(DM_DEV_WAIT,     IOC_RW, do_ioctl_dm, +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl))) +  IOCTL_SPECIAL(DM_TABLE_LOAD,   IOC_RW, do_ioctl_dm, +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl))) +  IOCTL_SPECIAL(DM_TABLE_CLEAR,  IOC_RW, do_ioctl_dm, +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl))) +  IOCTL_SPECIAL(DM_TABLE_DEPS,   IOC_RW, do_ioctl_dm, +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl))) +  IOCTL_SPECIAL(DM_TABLE_STATUS, IOC_RW, do_ioctl_dm, +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl))) +  IOCTL_SPECIAL(DM_LIST_VERSIONS,IOC_RW, do_ioctl_dm, +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl))) +  IOCTL_SPECIAL(DM_TARGET_MSG,   IOC_RW, do_ioctl_dm, +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl))) +  IOCTL_SPECIAL(DM_DEV_SET_GEOMETRY, IOC_RW, do_ioctl_dm, +                MK_PTR(MK_STRUCT(STRUCT_dm_ioctl))) +  IOCTL_SPECIAL(SIOCADDRT, IOC_W, do_ioctl_rt, +                MK_PTR(MK_STRUCT(STRUCT_rtentry))) +  IOCTL_SPECIAL(SIOCDELRT, IOC_W, do_ioctl_rt, +                MK_PTR(MK_STRUCT(STRUCT_rtentry))) diff --git a/linux-user/linux_loop.h b/linux-user/linux_loop.h new file mode 100644 index 00000000..8974caa9 --- /dev/null +++ b/linux-user/linux_loop.h @@ -0,0 +1,95 @@ +/* Copied from 2.6.25 kernel headers to avoid problems on older hosts.  */ +#ifndef _LINUX_LOOP_H +#define _LINUX_LOOP_H + +/* + * include/linux/loop.h + * + * Written by Theodore Ts'o, 3/29/93. + * + * Copyright 1993 by Theodore Ts'o.  Redistribution of this file is + * permitted under the GNU General Public License. + */ + +#define LO_NAME_SIZE	64 +#define LO_KEY_SIZE	32 + + +/* + * Loop flags + */ +enum { +	LO_FLAGS_READ_ONLY	= 1, +	LO_FLAGS_USE_AOPS	= 2, +	LO_FLAGS_AUTOCLEAR	= 4, +}; + +#include <linux/version.h> +#include <asm/posix_types.h>	/* for __kernel_old_dev_t */ +#include <asm/types.h>		/* for __u64 */ + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) /* This is a guess.  */ +#define __kernel_old_dev_t __kernel_dev_t +#endif + +/* Backwards compatibility version */ +struct loop_info { +	int		   lo_number;		/* ioctl r/o */ +	__kernel_old_dev_t lo_device; 		/* ioctl r/o */ +	unsigned long	   lo_inode; 		/* ioctl r/o */ +	__kernel_old_dev_t lo_rdevice; 		/* ioctl r/o */ +	int		   lo_offset; +	int		   lo_encrypt_type; +	int		   lo_encrypt_key_size; 	/* ioctl w/o */ +	int		   lo_flags;			/* ioctl r/o */ +	char		   lo_name[LO_NAME_SIZE]; +	unsigned char	   lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ +	unsigned long	   lo_init[2]; +	char		   reserved[4]; +}; + +struct loop_info64 { +	__u64		   lo_device;			/* ioctl r/o */ +	__u64		   lo_inode;			/* ioctl r/o */ +	__u64		   lo_rdevice;			/* ioctl r/o */ +	__u64		   lo_offset; +	__u64		   lo_sizelimit;/* bytes, 0 == max available */ +	__u32		   lo_number;			/* ioctl r/o */ +	__u32		   lo_encrypt_type; +	__u32		   lo_encrypt_key_size;		/* ioctl w/o */ +	__u32		   lo_flags;			/* ioctl r/o */ +	__u8		   lo_file_name[LO_NAME_SIZE]; +	__u8		   lo_crypt_name[LO_NAME_SIZE]; +	__u8		   lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ +	__u64		   lo_init[2]; +}; + +/* + * Loop filter types + */ + +#define LO_CRYPT_NONE		0 +#define LO_CRYPT_XOR		1 +#define LO_CRYPT_DES		2 +#define LO_CRYPT_FISH2		3    /* Twofish encryption */ +#define LO_CRYPT_BLOW		4 +#define LO_CRYPT_CAST128	5 +#define LO_CRYPT_IDEA		6 +#define LO_CRYPT_DUMMY		9 +#define LO_CRYPT_SKIPJACK	10 +#define LO_CRYPT_CRYPTOAPI	18 +#define MAX_LO_CRYPT		20 + +/* + * IOCTL commands --- we will commandeer 0x4C ('L') + */ + +#define LOOP_SET_FD		0x4C00 +#define LOOP_CLR_FD		0x4C01 +#define LOOP_SET_STATUS		0x4C02 +#define LOOP_GET_STATUS		0x4C03 +#define LOOP_SET_STATUS64	0x4C04 +#define LOOP_GET_STATUS64	0x4C05 +#define LOOP_CHANGE_FD		0x4C06 + +#endif diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c new file mode 100644 index 00000000..506e837a --- /dev/null +++ b/linux-user/linuxload.c @@ -0,0 +1,180 @@ +/* Code for loading Linux executables.  Mostly linux kernel code.  */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> + +#include "qemu.h" + +#define NGROUPS 32 + +/* ??? This should really be somewhere else.  */ +abi_long memcpy_to_target(abi_ulong dest, const void *src, +                          unsigned long len) +{ +    void *host_ptr; + +    host_ptr = lock_user(VERIFY_WRITE, dest, len, 0); +    if (!host_ptr) +        return -TARGET_EFAULT; +    memcpy(host_ptr, src, len); +    unlock_user(host_ptr, dest, 1); +    return 0; +} + +static int count(char ** vec) +{ +    int		i; + +    for(i = 0; *vec; i++) { +        vec++; +    } + +    return(i); +} + +static int prepare_binprm(struct linux_binprm *bprm) +{ +    struct stat		st; +    int mode; +    int retval; + +    if(fstat(bprm->fd, &st) < 0) { +	return(-errno); +    } + +    mode = st.st_mode; +    if(!S_ISREG(mode)) {	/* Must be regular file */ +	return(-EACCES); +    } +    if(!(mode & 0111)) {	/* Must have at least one execute bit set */ +	return(-EACCES); +    } + +    bprm->e_uid = geteuid(); +    bprm->e_gid = getegid(); + +    /* Set-uid? */ +    if(mode & S_ISUID) { +    	bprm->e_uid = st.st_uid; +    } + +    /* Set-gid? */ +    /* +     * If setgid is set but no group execute bit then this +     * is a candidate for mandatory locking, not a setgid +     * executable. +     */ +    if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) { +	bprm->e_gid = st.st_gid; +    } + +    retval = read(bprm->fd, bprm->buf, BPRM_BUF_SIZE); +    if (retval < 0) { +	perror("prepare_binprm"); +	exit(-1); +    } +    if (retval < BPRM_BUF_SIZE) { +        /* Make sure the rest of the loader won't read garbage.  */ +        memset(bprm->buf + retval, 0, BPRM_BUF_SIZE - retval); +    } +    return retval; +} + +/* Construct the envp and argv tables on the target stack.  */ +abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp, +                              abi_ulong stringp, int push_ptr) +{ +    TaskState *ts = (TaskState *)thread_cpu->opaque; +    int n = sizeof(abi_ulong); +    abi_ulong envp; +    abi_ulong argv; + +    sp -= (envc + 1) * n; +    envp = sp; +    sp -= (argc + 1) * n; +    argv = sp; +    if (push_ptr) { +        /* FIXME - handle put_user() failures */ +        sp -= n; +        put_user_ual(envp, sp); +        sp -= n; +        put_user_ual(argv, sp); +    } +    sp -= n; +    /* FIXME - handle put_user() failures */ +    put_user_ual(argc, sp); +    ts->info->arg_start = stringp; +    while (argc-- > 0) { +        /* FIXME - handle put_user() failures */ +        put_user_ual(stringp, argv); +        argv += n; +        stringp += target_strlen(stringp) + 1; +    } +    ts->info->arg_end = stringp; +    /* FIXME - handle put_user() failures */ +    put_user_ual(0, argv); +    while (envc-- > 0) { +        /* FIXME - handle put_user() failures */ +        put_user_ual(stringp, envp); +        envp += n; +        stringp += target_strlen(stringp) + 1; +    } +    /* FIXME - handle put_user() failures */ +    put_user_ual(0, envp); + +    return sp; +} + +int loader_exec(int fdexec, const char *filename, char **argv, char **envp, +             struct target_pt_regs * regs, struct image_info *infop, +             struct linux_binprm *bprm) +{ +    int retval; +    int i; + +    bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int); +    memset(bprm->page, 0, sizeof(bprm->page)); +    bprm->fd = fdexec; +    bprm->filename = (char *)filename; +    bprm->argc = count(argv); +    bprm->argv = argv; +    bprm->envc = count(envp); +    bprm->envp = envp; + +    retval = prepare_binprm(bprm); + +    if(retval>=0) { +        if (bprm->buf[0] == 0x7f +                && bprm->buf[1] == 'E' +                && bprm->buf[2] == 'L' +                && bprm->buf[3] == 'F') { +            retval = load_elf_binary(bprm, infop); +#if defined(TARGET_HAS_BFLT) +        } else if (bprm->buf[0] == 'b' +                && bprm->buf[1] == 'F' +                && bprm->buf[2] == 'L' +                && bprm->buf[3] == 'T') { +            retval = load_flt_binary(bprm, infop); +#endif +        } else { +            return -ENOEXEC; +        } +    } + +    if(retval>=0) { +        /* success.  Initialize important registers */ +        do_init_thread(regs, infop); +        return retval; +    } + +    /* Something went wrong, return the inode and free the argument pages*/ +    for (i=0 ; i<MAX_ARG_PAGES ; i++) { +        g_free(bprm->page[i]); +    } +    return(retval); +} diff --git a/linux-user/m68k-sim.c b/linux-user/m68k-sim.c new file mode 100644 index 00000000..1994e400 --- /dev/null +++ b/linux-user/m68k-sim.c @@ -0,0 +1,171 @@ +/* + *  m68k simulator syscall interface + * + *  Copyright (c) 2005 CodeSourcery, LLC. Written by Paul Brook. + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <time.h> + +#include "qemu.h" + +#define SYS_EXIT        1 +#define SYS_READ        3 +#define SYS_WRITE       4 +#define SYS_OPEN        5 +#define SYS_CLOSE       6 +#define SYS_BRK         17 +#define SYS_FSTAT       28 +#define SYS_ISATTY      29 +#define SYS_LSEEK       199 + +struct m68k_sim_stat { +    uint16_t sim_st_dev; +    uint16_t sim_st_ino; +    uint32_t sim_st_mode; +    uint16_t sim_st_nlink; +    uint16_t sim_st_uid; +    uint16_t sim_st_gid; +    uint16_t sim_st_rdev; +    uint32_t sim_st_size; +    uint32_t sim_st_atime; +    uint32_t sim_st_mtime; +    uint32_t sim_st_ctime; +    uint32_t sim_st_blksize; +    uint32_t sim_st_blocks; +}; + +static inline uint32_t check_err(CPUM68KState *env, uint32_t code) +{ +  env->dregs[0] = code; +  if (code == (uint32_t)-1) { +      env->dregs[1] = errno; +  } else { +      env->dregs[1] = 0; +  } +  return code; +} + +#define SIM_O_APPEND    0x0008 +#define SIM_O_CREAT     0x0200 +#define SIM_O_TRUNC     0x0400 +#define SIM_O_EXCL      0x0800 +#define SIM_O_NONBLOCK  0x4000 +#define SIM_O_NOCTTY    0x8000 +#define SIM_O_SYNC      0x2000 + +static int translate_openflags(int flags) +{ +    int hf; + +    switch (flags & 3) { +    case 0: hf = O_RDONLY; break; +    case 1: hf = O_WRONLY; break; +    case 2: hf = O_RDWR; break; +    default: hf = O_RDWR; break; +    } + +    if (flags & SIM_O_APPEND) hf |= O_APPEND; +    if (flags & SIM_O_CREAT) hf |= O_CREAT; +    if (flags & SIM_O_TRUNC) hf |= O_TRUNC; +    if (flags & SIM_O_EXCL) hf |= O_EXCL; +    if (flags & SIM_O_NONBLOCK) hf |= O_NONBLOCK; +    if (flags & SIM_O_NOCTTY) hf |= O_NOCTTY; +    if (flags & SIM_O_SYNC) hf |= O_SYNC; + +    return hf; +} + +#define ARG(x) tswap32(args[x]) +void do_m68k_simcall(CPUM68KState *env, int nr) +{ +    M68kCPU *cpu = m68k_env_get_cpu(env); +    uint32_t *args; + +    args = (uint32_t *)(unsigned long)(env->aregs[7] + 4); +    switch (nr) { +    case SYS_EXIT: +        exit(ARG(0)); +    case SYS_READ: +        check_err(env, read(ARG(0), (void *)(unsigned long)ARG(1), ARG(2))); +        break; +    case SYS_WRITE: +        check_err(env, write(ARG(0), (void *)(unsigned long)ARG(1), ARG(2))); +        break; +    case SYS_OPEN: +        check_err(env, open((char *)(unsigned long)ARG(0), +                            translate_openflags(ARG(1)), ARG(2))); +        break; +    case SYS_CLOSE: +        { +            /* Ignore attempts to close stdin/out/err.  */ +            int fd = ARG(0); +            if (fd > 2) +              check_err(env, close(fd)); +            else +              check_err(env, 0); +            break; +        } +    case SYS_BRK: +        { +            int32_t ret; + +            ret = do_brk((abi_ulong)ARG(0)); +            if (ret == -ENOMEM) +                ret = -1; +            check_err(env, ret); +        } +        break; +    case SYS_FSTAT: +        { +            struct stat s; +            int rc; +            struct m68k_sim_stat *p; +            rc = check_err(env, fstat(ARG(0), &s)); +            if (rc == 0) { +                p = (struct m68k_sim_stat *)(unsigned long)ARG(1); +                p->sim_st_dev = tswap16(s.st_dev); +                p->sim_st_ino = tswap16(s.st_ino); +                p->sim_st_mode = tswap32(s.st_mode); +                p->sim_st_nlink = tswap16(s.st_nlink); +                p->sim_st_uid = tswap16(s.st_uid); +                p->sim_st_gid = tswap16(s.st_gid); +                p->sim_st_rdev = tswap16(s.st_rdev); +                p->sim_st_size = tswap32(s.st_size); +                p->sim_st_atime = tswap32(s.st_atime); +                p->sim_st_mtime = tswap32(s.st_mtime); +                p->sim_st_ctime = tswap32(s.st_ctime); +                p->sim_st_blksize = tswap32(s.st_blksize); +                p->sim_st_blocks = tswap32(s.st_blocks); +            } +        } +        break; +    case SYS_ISATTY: +        check_err(env, isatty(ARG(0))); +        break; +    case SYS_LSEEK: +        check_err(env, lseek(ARG(0), (int32_t)ARG(1), ARG(2))); +        break; +    default: +        cpu_abort(CPU(cpu), "Unsupported m68k sim syscall %d\n", nr); +    } +} diff --git a/linux-user/m68k/syscall.h b/linux-user/m68k/syscall.h new file mode 100644 index 00000000..9218493a --- /dev/null +++ b/linux-user/m68k/syscall.h @@ -0,0 +1,25 @@ + +/* this struct defines the way the registers are stored on the +   stack during a system call. */ + +struct target_pt_regs { +    abi_long d1, d2, d3, d4, d5, d6, d7; +    abi_long a0, a1, a2, a3, a4, a5, a6; +    abi_ulong d0; +    abi_ulong usp; +    abi_ulong orig_d0; +    int16_t stkadj; +    uint16_t sr; +    abi_ulong pc; +    uint16_t fntvex; +    uint16_t __fill; +}; + +#define UNAME_MACHINE "m68k" +#define UNAME_MINIMUM_RELEASE "2.6.32" + +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_MLOCKALL_MCL_CURRENT 1 +#define TARGET_MLOCKALL_MCL_FUTURE  2 + +void do_m68k_simcall(CPUM68KState *, int); diff --git a/linux-user/m68k/syscall_nr.h b/linux-user/m68k/syscall_nr.h new file mode 100644 index 00000000..25f8521e --- /dev/null +++ b/linux-user/m68k/syscall_nr.h @@ -0,0 +1,351 @@ +/* + * This file contains the system call numbers. + */ + +#define TARGET_NR_exit                 1 +#define TARGET_NR_fork                 2 +#define TARGET_NR_read                 3 +#define TARGET_NR_write                4 +#define TARGET_NR_open                 5 +#define TARGET_NR_close                6 +#define TARGET_NR_waitpid              7 +#define TARGET_NR_creat                8 +#define TARGET_NR_link                 9 +#define TARGET_NR_unlink              10 +#define TARGET_NR_execve              11 +#define TARGET_NR_chdir               12 +#define TARGET_NR_time                13 +#define TARGET_NR_mknod               14 +#define TARGET_NR_chmod               15 +#define TARGET_NR_chown               16 +#define TARGET_NR_break               17 +#define TARGET_NR_oldstat             18 +#define TARGET_NR_lseek               19 +#define TARGET_NR_getpid              20 +#define TARGET_NR_mount               21 +#define TARGET_NR_umount              22 +#define TARGET_NR_setuid              23 +#define TARGET_NR_getuid              24 +#define TARGET_NR_stime               25 +#define TARGET_NR_ptrace              26 +#define TARGET_NR_alarm               27 +#define TARGET_NR_oldfstat            28 +#define TARGET_NR_pause               29 +#define TARGET_NR_utime               30 +#define TARGET_NR_stty                31 +#define TARGET_NR_gtty                32 +#define TARGET_NR_access              33 +#define TARGET_NR_nice                34 +#define TARGET_NR_ftime               35 +#define TARGET_NR_sync                36 +#define TARGET_NR_kill                37 +#define TARGET_NR_rename              38 +#define TARGET_NR_mkdir               39 +#define TARGET_NR_rmdir               40 +#define TARGET_NR_dup                 41 +#define TARGET_NR_pipe                42 +#define TARGET_NR_times               43 +#define TARGET_NR_prof                44 +#define TARGET_NR_brk                 45 +#define TARGET_NR_setgid              46 +#define TARGET_NR_getgid              47 +#define TARGET_NR_signal              48 +#define TARGET_NR_geteuid             49 +#define TARGET_NR_getegid             50 +#define TARGET_NR_acct                51 +#define TARGET_NR_umount2             52 +#define TARGET_NR_lock                53 +#define TARGET_NR_ioctl               54 +#define TARGET_NR_fcntl               55 +#define TARGET_NR_mpx                 56 +#define TARGET_NR_setpgid             57 +#define TARGET_NR_ulimit              58 +#define TARGET_NR_oldolduname         59 +#define TARGET_NR_umask               60 +#define TARGET_NR_chroot              61 +#define TARGET_NR_ustat               62 +#define TARGET_NR_dup2                63 +#define TARGET_NR_getppid             64 +#define TARGET_NR_getpgrp             65 +#define TARGET_NR_setsid              66 +#define TARGET_NR_sigaction           67 +#define TARGET_NR_sgetmask            68 +#define TARGET_NR_ssetmask            69 +#define TARGET_NR_setreuid            70 +#define TARGET_NR_setregid            71 +#define TARGET_NR_sigsuspend          72 +#define TARGET_NR_sigpending          73 +#define TARGET_NR_sethostname         74 +#define TARGET_NR_setrlimit           75 +#define TARGET_NR_getrlimit           76 +#define TARGET_NR_getrusage           77 +#define TARGET_NR_gettimeofday        78 +#define TARGET_NR_settimeofday        79 +#define TARGET_NR_getgroups           80 +#define TARGET_NR_setgroups           81 +#define TARGET_NR_select              82 +#define TARGET_NR_symlink             83 +#define TARGET_NR_oldlstat            84 +#define TARGET_NR_readlink            85 +#define TARGET_NR_uselib              86 +#define TARGET_NR_swapon              87 +#define TARGET_NR_reboot              88 +#define TARGET_NR_readdir             89 +#define TARGET_NR_mmap                90 +#define TARGET_NR_munmap              91 +#define TARGET_NR_truncate            92 +#define TARGET_NR_ftruncate           93 +#define TARGET_NR_fchmod              94 +#define TARGET_NR_fchown              95 +#define TARGET_NR_getpriority         96 +#define TARGET_NR_setpriority         97 +#define TARGET_NR_profil              98 +#define TARGET_NR_statfs              99 +#define TARGET_NR_fstatfs            100 +#define TARGET_NR_ioperm             101 +#define TARGET_NR_socketcall         102 +#define TARGET_NR_syslog             103 +#define TARGET_NR_setitimer          104 +#define TARGET_NR_getitimer          105 +#define TARGET_NR_stat               106 +#define TARGET_NR_lstat              107 +#define TARGET_NR_fstat              108 +#define TARGET_NR_olduname           109 +//#define TARGET_NR_iopl               /* 110 */ not supported +#define TARGET_NR_vhangup            111 +//#define TARGET_NR_idle               /* 112 */ Obsolete +//#define TARGET_NR_vm86               /* 113 */ not supported +#define TARGET_NR_wait4              114 +#define TARGET_NR_swapoff            115 +#define TARGET_NR_sysinfo            116 +#define TARGET_NR_ipc                117 +#define TARGET_NR_fsync              118 +#define TARGET_NR_sigreturn          119 +#define TARGET_NR_clone              120 +#define TARGET_NR_setdomainname      121 +#define TARGET_NR_uname              122 +#define TARGET_NR_cacheflush         123 +#define TARGET_NR_adjtimex           124 +#define TARGET_NR_mprotect           125 +#define TARGET_NR_sigprocmask        126 +#define TARGET_NR_create_module      127 +#define TARGET_NR_init_module        128 +#define TARGET_NR_delete_module      129 +#define TARGET_NR_get_kernel_syms    130 +#define TARGET_NR_quotactl           131 +#define TARGET_NR_getpgid            132 +#define TARGET_NR_fchdir             133 +#define TARGET_NR_bdflush            134 +#define TARGET_NR_sysfs              135 +#define TARGET_NR_personality        136 +#define TARGET_NR_afs_syscall        137 /* Syscall for Andrew File System */ +#define TARGET_NR_setfsuid           138 +#define TARGET_NR_setfsgid           139 +#define TARGET_NR__llseek            140 +#define TARGET_NR_getdents           141 +#define TARGET_NR__newselect         142 +#define TARGET_NR_flock              143 +#define TARGET_NR_msync              144 +#define TARGET_NR_readv              145 +#define TARGET_NR_writev             146 +#define TARGET_NR_getsid             147 +#define TARGET_NR_fdatasync          148 +#define TARGET_NR__sysctl            149 +#define TARGET_NR_mlock              150 +#define TARGET_NR_munlock            151 +#define TARGET_NR_mlockall           152 +#define TARGET_NR_munlockall         153 +#define TARGET_NR_sched_setparam             154 +#define TARGET_NR_sched_getparam             155 +#define TARGET_NR_sched_setscheduler         156 +#define TARGET_NR_sched_getscheduler         157 +#define TARGET_NR_sched_yield                158 +#define TARGET_NR_sched_get_priority_max     159 +#define TARGET_NR_sched_get_priority_min     160 +#define TARGET_NR_sched_rr_get_interval      161 +#define TARGET_NR_nanosleep          162 +#define TARGET_NR_mremap             163 +#define TARGET_NR_setresuid          164 +#define TARGET_NR_getresuid          165 +#define TARGET_NR_getpagesize        166 +#define TARGET_NR_query_module       167 +#define TARGET_NR_poll               168 +#define TARGET_NR_nfsservctl         169 +#define TARGET_NR_setresgid          170 +#define TARGET_NR_getresgid          171 +#define TARGET_NR_prctl              172 +#define TARGET_NR_rt_sigreturn       173 +#define TARGET_NR_rt_sigaction       174 +#define TARGET_NR_rt_sigprocmask     175 +#define TARGET_NR_rt_sigpending      176 +#define TARGET_NR_rt_sigtimedwait    177 +#define TARGET_NR_rt_sigqueueinfo    178 +#define TARGET_NR_rt_sigsuspend      179 +#define TARGET_NR_pread64            180 +#define TARGET_NR_pwrite64           181 +#define TARGET_NR_lchown             182 +#define TARGET_NR_getcwd             183 +#define TARGET_NR_capget             184 +#define TARGET_NR_capset             185 +#define TARGET_NR_sigaltstack        186 +#define TARGET_NR_sendfile           187 +#define TARGET_NR_getpmsg            188     /* some people actually want streams */ +#define TARGET_NR_putpmsg            189     /* some people actually want streams */ +#define TARGET_NR_vfork              190 +#define TARGET_NR_ugetrlimit         191 +#define TARGET_NR_mmap2              192 +#define TARGET_NR_truncate64         193 +#define TARGET_NR_ftruncate64        194 +#define TARGET_NR_stat64             195 +#define TARGET_NR_lstat64            196 +#define TARGET_NR_fstat64            197 +#define TARGET_NR_chown32            198 +#define TARGET_NR_getuid32           199 +#define TARGET_NR_getgid32           200 +#define TARGET_NR_geteuid32          201 +#define TARGET_NR_getegid32          202 +#define TARGET_NR_setreuid32         203 +#define TARGET_NR_setregid32         204 +#define TARGET_NR_getgroups32        205 +#define TARGET_NR_setgroups32        206 +#define TARGET_NR_fchown32           207 +#define TARGET_NR_setresuid32        208 +#define TARGET_NR_getresuid32        209 +#define TARGET_NR_setresgid32        210 +#define TARGET_NR_getresgid32        211 +#define TARGET_NR_lchown32           212 +#define TARGET_NR_setuid32           213 +#define TARGET_NR_setgid32           214 +#define TARGET_NR_setfsuid32         215 +#define TARGET_NR_setfsgid32         216 +#define TARGET_NR_pivot_root         217 +#define TARGET_NR_getdents64         220 +#define TARGET_NR_gettid             221 +#define TARGET_NR_tkill              222 +#define TARGET_NR_setxattr           223 +#define TARGET_NR_lsetxattr          224 +#define TARGET_NR_fsetxattr          225 +#define TARGET_NR_getxattr           226 +#define TARGET_NR_lgetxattr          227 +#define TARGET_NR_fgetxattr          228 +#define TARGET_NR_listxattr          229 +#define TARGET_NR_llistxattr         230 +#define TARGET_NR_flistxattr         231 +#define TARGET_NR_removexattr        232 +#define TARGET_NR_lremovexattr       233 +#define TARGET_NR_fremovexattr       234 +#define TARGET_NR_futex              235 +#define TARGET_NR_sendfile64         236 +#define TARGET_NR_mincore            237 +#define TARGET_NR_madvise            238 +#define TARGET_NR_fcntl64            239 +#define TARGET_NR_readahead          240 +#define TARGET_NR_io_setup           241 +#define TARGET_NR_io_destroy         242 +#define TARGET_NR_io_getevents       243 +#define TARGET_NR_io_submit          244 +#define TARGET_NR_io_cancel          245 +#define TARGET_NR_fadvise64          246 +#define TARGET_NR_exit_group         247 +#define TARGET_NR_lookup_dcookie     248 +#define TARGET_NR_epoll_create       249 +#define TARGET_NR_epoll_ctl          250 +#define TARGET_NR_epoll_wait         251 +#define TARGET_NR_remap_file_pages   252 +#define TARGET_NR_set_tid_address    253 +#define TARGET_NR_timer_create       254 +#define TARGET_NR_timer_settime      255 +#define TARGET_NR_timer_gettime      256 +#define TARGET_NR_timer_getoverrun   257 +#define TARGET_NR_timer_delete       258 +#define TARGET_NR_clock_settime      259 +#define TARGET_NR_clock_gettime      260 +#define TARGET_NR_clock_getres       261 +#define TARGET_NR_clock_nanosleep    262 +#define TARGET_NR_statfs64           263 +#define TARGET_NR_fstatfs64          264 +#define TARGET_NR_tgkill             265 +#define TARGET_NR_utimes             266 +#define TARGET_NR_fadvise64_64       267 +#define TARGET_NR_mbind              268 +#define TARGET_NR_get_mempolicy      269 +#define TARGET_NR_set_mempolicy      270 +#define TARGET_NR_mq_open            271 +#define TARGET_NR_mq_unlink          272 +#define TARGET_NR_mq_timedsend       273 +#define TARGET_NR_mq_timedreceive    274 +#define TARGET_NR_mq_notify          275 +#define TARGET_NR_mq_getsetattr      276 +#define TARGET_NR_waitid             277 +#define TARGET_NR_vserver            278 +#define TARGET_NR_add_key            279 +#define TARGET_NR_request_key        280 +#define TARGET_NR_keyctl             281 +#define TARGET_NR_ioprio_set		282 +#define TARGET_NR_ioprio_get		283 +#define TARGET_NR_inotify_init	284 +#define TARGET_NR_inotify_add_watch	285 +#define TARGET_NR_inotify_rm_watch	286 +#define TARGET_NR_migrate_pages	287 +#define TARGET_NR_openat		288 +#define TARGET_NR_mkdirat		289 +#define TARGET_NR_mknodat		290 +#define TARGET_NR_fchownat		291 +#define TARGET_NR_futimesat		292 +#define TARGET_NR_fstatat64		293 +#define TARGET_NR_unlinkat		294 +#define TARGET_NR_renameat		295 +#define TARGET_NR_linkat		296 +#define TARGET_NR_symlinkat		297 +#define TARGET_NR_readlinkat		298 +#define TARGET_NR_fchmodat		299 +#define TARGET_NR_faccessat		300 +#define TARGET_NR_pselect6		301 +#define TARGET_NR_ppoll		302 +#define TARGET_NR_unshare		303 +#define TARGET_NR_set_robust_list	304 +#define TARGET_NR_get_robust_list	305 +#define TARGET_NR_splice		306 +#define TARGET_NR_sync_file_range	307 +#define TARGET_NR_tee		308 +#define TARGET_NR_vmsplice		309 +#define TARGET_NR_move_pages		310 +#define TARGET_NR_sched_setaffinity	311 +#define TARGET_NR_sched_getaffinity	312 +#define TARGET_NR_kexec_load		313 +#define TARGET_NR_getcpu		314 +#define TARGET_NR_epoll_pwait	315 +#define TARGET_NR_utimensat		316 +#define TARGET_NR_signalfd		317 +#define TARGET_NR_timerfd		318 +#define TARGET_NR_eventfd		319 +#define TARGET_NR_fallocate		320 +#define TARGET_NR_timerfd_settime	321 +#define TARGET_NR_timerfd_gettime	322 +#define TARGET_NR_signalfd4		323 +#define TARGET_NR_eventfd2		324 +#define TARGET_NR_epoll_create1	325 +#define TARGET_NR_dup3			326 +#define TARGET_NR_pipe2		327 +#define TARGET_NR_inotify_init1	328 +#define TARGET_NR_inotify_init1         328 +#define TARGET_NR_preadv                329 +#define TARGET_NR_pwritev               330 +#define TARGET_NR_rt_tgsigqueueinfo     331 +#define TARGET_NR_perf_event_open       332 +#define TARGET_NR_get_thread_area       333 +#define TARGET_NR_set_thread_area       334 +#define TARGET_NR_atomic_cmpxchg_32     335 +#define TARGET_NR_atomic_barrier        336 +#define TARGET_NR_fanotify_init         337 +#define TARGET_NR_fanotify_mark         338 +#define TARGET_NR_prlimit64             339 +#define TARGET_NR_name_to_handle_at     340 +#define TARGET_NR_open_by_handle_at     341 +#define TARGET_NR_clock_adjtime         342 +#define TARGET_NR_syncfs                343 +#define TARGET_NR_setns                 344 +#define TARGET_NR_process_vm_readv      345 +#define TARGET_NR_process_vm_writev     346 +#define TARGET_NR_kcmp                  347 +#define TARGET_NR_finit_module          348 diff --git a/linux-user/m68k/target_cpu.h b/linux-user/m68k/target_cpu.h new file mode 100644 index 00000000..bb4d3fab --- /dev/null +++ b/linux-user/m68k/target_cpu.h @@ -0,0 +1,40 @@ +/* + * m68k specific CPU ABI and functions for linux-user + * + * Copyright (c) 2005-2007 CodeSourcery + * Written by Paul Brook + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUM68KState *env, target_ulong newsp) +{ +    if (newsp) { +        env->aregs[7] = newsp; +    } +    env->dregs[0] = 0; +} + +static inline void cpu_set_tls(CPUM68KState *env, target_ulong newtls) +{ +    CPUState *cs = CPU(m68k_env_get_cpu(env)); +    TaskState *ts = cs->opaque; + +    ts->tp_value = newtls; +} + +#endif diff --git a/linux-user/m68k/target_signal.h b/linux-user/m68k/target_signal.h new file mode 100644 index 00000000..479758a4 --- /dev/null +++ b/linux-user/m68k/target_signal.h @@ -0,0 +1,29 @@ +#ifndef TARGET_SIGNAL_H +#define TARGET_SIGNAL_H + +#include "cpu.h" + +/* this struct defines a stack used during syscall handling */ + +typedef struct target_sigaltstack { +	abi_ulong ss_sp; +	abi_long ss_flags; +	abi_ulong ss_size; +} target_stack_t; + + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK	1 +#define TARGET_SS_DISABLE	2 + +#define TARGET_MINSIGSTKSZ	2048 +#define TARGET_SIGSTKSZ	8192 + +static inline abi_ulong get_sp_from_cpustate(CPUM68KState *state) +{ +    return state->aregs[7]; +} + +#endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/m68k/target_structs.h b/linux-user/m68k/target_structs.h new file mode 100644 index 00000000..de257c97 --- /dev/null +++ b/linux-user/m68k/target_structs.h @@ -0,0 +1,58 @@ +/* + * m68k specific structures for linux-user + * + * Copyright (c) 2013 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_STRUCTS_H +#define TARGET_STRUCTS_H + +struct target_ipc_perm { +    abi_int __key;                      /* Key.  */ +    abi_uint uid;                       /* Owner's user ID.  */ +    abi_uint gid;                       /* Owner's group ID.  */ +    abi_uint cuid;                      /* Creator's user ID.  */ +    abi_uint cgid;                      /* Creator's group ID.  */ +    abi_ushort mode;                    /* Read/write permission.  */ +    abi_ushort __pad1; +    abi_ushort __seq;                   /* Sequence number.  */ +    abi_ushort __pad2; +    abi_ulong __unused1; +    abi_ulong __unused2; +}; + +struct target_shmid_ds { +    struct target_ipc_perm shm_perm;    /* operation permission struct */ +    abi_long shm_segsz;                 /* size of segment in bytes */ +    abi_ulong shm_atime;                /* time of last shmat() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused1; +#endif +    abi_ulong shm_dtime;                /* time of last shmdt() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused2; +#endif +    abi_ulong shm_ctime;                /* time of last change by shmctl() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused3; +#endif +    abi_int shm_cpid;                   /* pid of creator */ +    abi_int shm_lpid;                   /* pid of last shmop */ +    abi_ulong shm_nattch;               /* number of current attaches */ +    abi_ulong __unused4; +    abi_ulong __unused5; +}; + +#endif diff --git a/linux-user/m68k/termbits.h b/linux-user/m68k/termbits.h new file mode 100644 index 00000000..f7982fb6 --- /dev/null +++ b/linux-user/m68k/termbits.h @@ -0,0 +1,227 @@ +/* from asm/termbits.h */ +/* NOTE: exactly the same as i386 */ + +#define TARGET_NCCS 19 + +struct target_termios { +    unsigned int c_iflag;               /* input mode flags */ +    unsigned int c_oflag;               /* output mode flags */ +    unsigned int c_cflag;               /* control mode flags */ +    unsigned int c_lflag;               /* local mode flags */ +    unsigned char c_line;                    /* line discipline */ +    unsigned char c_cc[TARGET_NCCS];                /* control characters */ +}; + +/* c_iflag bits */ +#define TARGET_IGNBRK  0000001 +#define TARGET_BRKINT  0000002 +#define TARGET_IGNPAR  0000004 +#define TARGET_PARMRK  0000010 +#define TARGET_INPCK   0000020 +#define TARGET_ISTRIP  0000040 +#define TARGET_INLCR   0000100 +#define TARGET_IGNCR   0000200 +#define TARGET_ICRNL   0000400 +#define TARGET_IUCLC   0001000 +#define TARGET_IXON    0002000 +#define TARGET_IXANY   0004000 +#define TARGET_IXOFF   0010000 +#define TARGET_IMAXBEL 0020000 +#define TARGET_IUTF8   0040000 + +/* c_oflag bits */ +#define TARGET_OPOST   0000001 +#define TARGET_OLCUC   0000002 +#define TARGET_ONLCR   0000004 +#define TARGET_OCRNL   0000010 +#define TARGET_ONOCR   0000020 +#define TARGET_ONLRET  0000040 +#define TARGET_OFILL   0000100 +#define TARGET_OFDEL   0000200 +#define TARGET_NLDLY   0000400 +#define   TARGET_NL0   0000000 +#define   TARGET_NL1   0000400 +#define TARGET_CRDLY   0003000 +#define   TARGET_CR0   0000000 +#define   TARGET_CR1   0001000 +#define   TARGET_CR2   0002000 +#define   TARGET_CR3   0003000 +#define TARGET_TABDLY  0014000 +#define   TARGET_TAB0  0000000 +#define   TARGET_TAB1  0004000 +#define   TARGET_TAB2  0010000 +#define   TARGET_TAB3  0014000 +#define   TARGET_XTABS 0014000 +#define TARGET_BSDLY   0020000 +#define   TARGET_BS0   0000000 +#define   TARGET_BS1   0020000 +#define TARGET_VTDLY   0040000 +#define   TARGET_VT0   0000000 +#define   TARGET_VT1   0040000 +#define TARGET_FFDLY   0100000 +#define   TARGET_FF0   0000000 +#define   TARGET_FF1   0100000 + +/* c_cflag bit meaning */ +#define TARGET_CBAUD   0010017 +#define  TARGET_B0     0000000         /* hang up */ +#define  TARGET_B50    0000001 +#define  TARGET_B75    0000002 +#define  TARGET_B110   0000003 +#define  TARGET_B134   0000004 +#define  TARGET_B150   0000005 +#define  TARGET_B200   0000006 +#define  TARGET_B300   0000007 +#define  TARGET_B600   0000010 +#define  TARGET_B1200  0000011 +#define  TARGET_B1800  0000012 +#define  TARGET_B2400  0000013 +#define  TARGET_B4800  0000014 +#define  TARGET_B9600  0000015 +#define  TARGET_B19200 0000016 +#define  TARGET_B38400 0000017 +#define TARGET_EXTA B19200 +#define TARGET_EXTB B38400 +#define TARGET_CSIZE   0000060 +#define   TARGET_CS5   0000000 +#define   TARGET_CS6   0000020 +#define   TARGET_CS7   0000040 +#define   TARGET_CS8   0000060 +#define TARGET_CSTOPB  0000100 +#define TARGET_CREAD   0000200 +#define TARGET_PARENB  0000400 +#define TARGET_PARODD  0001000 +#define TARGET_HUPCL   0002000 +#define TARGET_CLOCAL  0004000 +#define TARGET_CBAUDEX 0010000 +#define  TARGET_B57600  0010001 +#define  TARGET_B115200 0010002 +#define  TARGET_B230400 0010003 +#define  TARGET_B460800 0010004 +#define  TARGET_B500000 0010005 +#define  TARGET_B576000 0010006 +#define  TARGET_B921600 0010007 +#define  TARGET_B1000000 0010010 +#define  TARGET_B1152000 0010011 +#define  TARGET_B1500000 0010012 +#define  TARGET_B2000000 0010013 +#define  TARGET_B2500000 0010014 +#define  TARGET_B3000000 0010015 +#define  TARGET_B3500000 0010016 +#define  TARGET_B4000000 0010017 +#define TARGET_CIBAUD    002003600000  /* input baud rate (not used) */ +#define TARGET_CMSPAR    010000000000  /* mark or space (stick) parity */ +#define TARGET_CRTSCTS   020000000000  /* flow control */ + +/* c_lflag bits */ +#define TARGET_ISIG    0000001 +#define TARGET_ICANON  0000002 +#define TARGET_XCASE   0000004 +#define TARGET_ECHO    0000010 +#define TARGET_ECHOE   0000020 +#define TARGET_ECHOK   0000040 +#define TARGET_ECHONL  0000100 +#define TARGET_NOFLSH  0000200 +#define TARGET_TOSTOP  0000400 +#define TARGET_ECHOCTL 0001000 +#define TARGET_ECHOPRT 0002000 +#define TARGET_ECHOKE  0004000 +#define TARGET_FLUSHO  0010000 +#define TARGET_PENDIN  0040000 +#define TARGET_IEXTEN  0100000 + +/* c_cc character offsets */ +#define TARGET_VINTR	0 +#define TARGET_VQUIT	1 +#define TARGET_VERASE	2 +#define TARGET_VKILL	3 +#define TARGET_VEOF	4 +#define TARGET_VTIME	5 +#define TARGET_VMIN	6 +#define TARGET_VSWTC	7 +#define TARGET_VSTART	8 +#define TARGET_VSTOP	9 +#define TARGET_VSUSP	10 +#define TARGET_VEOL	11 +#define TARGET_VREPRINT	12 +#define TARGET_VDISCARD	13 +#define TARGET_VWERASE	14 +#define TARGET_VLNEXT	15 +#define TARGET_VEOL2	16 + +/* ioctls */ + +#define TARGET_TCGETS		0x5401 +#define TARGET_TCSETS		0x5402 +#define TARGET_TCSETSW		0x5403 +#define TARGET_TCSETSF		0x5404 +#define TARGET_TCGETA		0x5405 +#define TARGET_TCSETA		0x5406 +#define TARGET_TCSETAW		0x5407 +#define TARGET_TCSETAF		0x5408 +#define TARGET_TCSBRK		0x5409 +#define TARGET_TCXONC		0x540A +#define TARGET_TCFLSH		0x540B + +#define TARGET_TIOCEXCL	0x540C +#define TARGET_TIOCNXCL	0x540D +#define TARGET_TIOCSCTTY	0x540E +#define TARGET_TIOCGPGRP	0x540F +#define TARGET_TIOCSPGRP	0x5410 +#define TARGET_TIOCOUTQ	0x5411 +#define TARGET_TIOCSTI		0x5412 +#define TARGET_TIOCGWINSZ	0x5413 +#define TARGET_TIOCSWINSZ	0x5414 +#define TARGET_TIOCMGET	0x5415 +#define TARGET_TIOCMBIS	0x5416 +#define TARGET_TIOCMBIC	0x5417 +#define TARGET_TIOCMSET	0x5418 +#define TARGET_TIOCGSOFTCAR	0x5419 +#define TARGET_TIOCSSOFTCAR	0x541A +#define TARGET_FIONREAD	0x541B +#define TARGET_TIOCINQ		TARGET_FIONREAD +#define TARGET_TIOCLINUX	0x541C +#define TARGET_TIOCCONS	0x541D +#define TARGET_TIOCGSERIAL	0x541E +#define TARGET_TIOCSSERIAL	0x541F +#define TARGET_TIOCPKT		0x5420 +#define TARGET_FIONBIO		0x5421 +#define TARGET_TIOCNOTTY	0x5422 +#define TARGET_TIOCSETD	0x5423 +#define TARGET_TIOCGETD	0x5424 +#define TARGET_TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */ +#define TARGET_TIOCTTYGSTRUCT	0x5426  /* For debugging only */ +#define TARGET_TIOCSBRK	0x5427  /* BSD compatibility */ +#define TARGET_TIOCCBRK	0x5428  /* BSD compatibility */ +#define TARGET_TIOCGSID	0x5429  /* Return the session ID of FD */ +#define TARGET_TIOCGPTN	TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define TARGET_TIOCSPTLCK	TARGET_IOW('T',0x31, int)  /* Lock/unlock Pty */ + +#define TARGET_FIONCLEX	0x5450  /* these numbers need to be adjusted. */ +#define TARGET_FIOCLEX		0x5451 +#define TARGET_FIOASYNC	0x5452 +#define TARGET_TIOCSERCONFIG	0x5453 +#define TARGET_TIOCSERGWILD	0x5454 +#define TARGET_TIOCSERSWILD	0x5455 +#define TARGET_TIOCGLCKTRMIOS	0x5456 +#define TARGET_TIOCSLCKTRMIOS	0x5457 +#define TARGET_TIOCSERGSTRUCT	0x5458 /* For debugging only */ +#define TARGET_TIOCSERGETLSR   0x5459 /* Get line status register */ +#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config  */ +#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TARGET_TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */ +#define TARGET_TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */ +#define TARGET_TIOCGHAYESESP   0x545E  /* Get Hayes ESP configuration */ +#define TARGET_TIOCSHAYESESP   0x545F  /* Set Hayes ESP configuration */ + +/* Used for packet mode */ +#define TARGET_TIOCPKT_DATA		 0 +#define TARGET_TIOCPKT_FLUSHREAD	 1 +#define TARGET_TIOCPKT_FLUSHWRITE	 2 +#define TARGET_TIOCPKT_STOP		 4 +#define TARGET_TIOCPKT_START		 8 +#define TARGET_TIOCPKT_NOSTOP		16 +#define TARGET_TIOCPKT_DOSTOP		32 + +#define TARGET_TIOCSER_TEMT    0x01	/* Transmitter physically empty */ diff --git a/linux-user/main.c b/linux-user/main.c new file mode 100644 index 00000000..fdee9813 --- /dev/null +++ b/linux-user/main.c @@ -0,0 +1,4411 @@ +/* + *  qemu user main + * + *  Copyright (c) 2003-2008 Fabrice Bellard + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, see <http://www.gnu.org/licenses/>. + */ +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/mman.h> +#include <sys/syscall.h> +#include <sys/resource.h> + +#include "qemu.h" +#include "qemu-common.h" +#include "cpu.h" +#include "tcg.h" +#include "qemu/timer.h" +#include "qemu/envlist.h" +#include "elf.h" + +char *exec_path; + +int singlestep; +const char *filename; +const char *argv0; +int gdbstub_port; +envlist_t *envlist; +static const char *cpu_model; +unsigned long mmap_min_addr; +#if defined(CONFIG_USE_GUEST_BASE) +unsigned long guest_base; +int have_guest_base; +#if (TARGET_LONG_BITS == 32) && (HOST_LONG_BITS == 64) +/* + * When running 32-on-64 we should make sure we can fit all of the possible + * guest address space into a contiguous chunk of virtual host memory. + * + * This way we will never overlap with our own libraries or binaries or stack + * or anything else that QEMU maps. + */ +# ifdef TARGET_MIPS +/* MIPS only supports 31 bits of virtual address space for user space */ +unsigned long reserved_va = 0x77000000; +# else +unsigned long reserved_va = 0xf7000000; +# endif +#else +unsigned long reserved_va; +#endif +#endif + +static void usage(void); + +static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX; +const char *qemu_uname_release; + +/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so +   we allocate a bigger stack. Need a better solution, for example +   by remapping the process stack directly at the right place */ +unsigned long guest_stack_size = 8 * 1024 * 1024UL; + +void gemu_log(const char *fmt, ...) +{ +    va_list ap; + +    va_start(ap, fmt); +    vfprintf(stderr, fmt, ap); +    va_end(ap); +} + +#if defined(TARGET_I386) +int cpu_get_pic_interrupt(CPUX86State *env) +{ +    return -1; +} +#endif + +/***********************************************************/ +/* Helper routines for implementing atomic operations.  */ + +/* To implement exclusive operations we force all cpus to syncronise. +   We don't require a full sync, only that no cpus are executing guest code. +   The alternative is to map target atomic ops onto host equivalents, +   which requires quite a lot of per host/target work.  */ +static pthread_mutex_t cpu_list_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t exclusive_lock = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t exclusive_cond = PTHREAD_COND_INITIALIZER; +static pthread_cond_t exclusive_resume = PTHREAD_COND_INITIALIZER; +static int pending_cpus; + +/* Make sure everything is in a consistent state for calling fork().  */ +void fork_start(void) +{ +    pthread_mutex_lock(&tcg_ctx.tb_ctx.tb_lock); +    pthread_mutex_lock(&exclusive_lock); +    mmap_fork_start(); +} + +void fork_end(int child) +{ +    mmap_fork_end(child); +    if (child) { +        CPUState *cpu, *next_cpu; +        /* Child processes created by fork() only have a single thread. +           Discard information about the parent threads.  */ +        CPU_FOREACH_SAFE(cpu, next_cpu) { +            if (cpu != thread_cpu) { +                QTAILQ_REMOVE(&cpus, thread_cpu, node); +            } +        } +        pending_cpus = 0; +        pthread_mutex_init(&exclusive_lock, NULL); +        pthread_mutex_init(&cpu_list_mutex, NULL); +        pthread_cond_init(&exclusive_cond, NULL); +        pthread_cond_init(&exclusive_resume, NULL); +        pthread_mutex_init(&tcg_ctx.tb_ctx.tb_lock, NULL); +        gdbserver_fork(thread_cpu); +    } else { +        pthread_mutex_unlock(&exclusive_lock); +        pthread_mutex_unlock(&tcg_ctx.tb_ctx.tb_lock); +    } +} + +/* Wait for pending exclusive operations to complete.  The exclusive lock +   must be held.  */ +static inline void exclusive_idle(void) +{ +    while (pending_cpus) { +        pthread_cond_wait(&exclusive_resume, &exclusive_lock); +    } +} + +/* Start an exclusive operation. +   Must only be called from outside cpu_arm_exec.   */ +static inline void start_exclusive(void) +{ +    CPUState *other_cpu; + +    pthread_mutex_lock(&exclusive_lock); +    exclusive_idle(); + +    pending_cpus = 1; +    /* Make all other cpus stop executing.  */ +    CPU_FOREACH(other_cpu) { +        if (other_cpu->running) { +            pending_cpus++; +            cpu_exit(other_cpu); +        } +    } +    if (pending_cpus > 1) { +        pthread_cond_wait(&exclusive_cond, &exclusive_lock); +    } +} + +/* Finish an exclusive operation.  */ +static inline void __attribute__((unused)) end_exclusive(void) +{ +    pending_cpus = 0; +    pthread_cond_broadcast(&exclusive_resume); +    pthread_mutex_unlock(&exclusive_lock); +} + +/* Wait for exclusive ops to finish, and begin cpu execution.  */ +static inline void cpu_exec_start(CPUState *cpu) +{ +    pthread_mutex_lock(&exclusive_lock); +    exclusive_idle(); +    cpu->running = true; +    pthread_mutex_unlock(&exclusive_lock); +} + +/* Mark cpu as not executing, and release pending exclusive ops.  */ +static inline void cpu_exec_end(CPUState *cpu) +{ +    pthread_mutex_lock(&exclusive_lock); +    cpu->running = false; +    if (pending_cpus > 1) { +        pending_cpus--; +        if (pending_cpus == 1) { +            pthread_cond_signal(&exclusive_cond); +        } +    } +    exclusive_idle(); +    pthread_mutex_unlock(&exclusive_lock); +} + +void cpu_list_lock(void) +{ +    pthread_mutex_lock(&cpu_list_mutex); +} + +void cpu_list_unlock(void) +{ +    pthread_mutex_unlock(&cpu_list_mutex); +} + + +#ifdef TARGET_I386 +/***********************************************************/ +/* CPUX86 core interface */ + +uint64_t cpu_get_tsc(CPUX86State *env) +{ +    return cpu_get_real_ticks(); +} + +static void write_dt(void *ptr, unsigned long addr, unsigned long limit, +                     int flags) +{ +    unsigned int e1, e2; +    uint32_t *p; +    e1 = (addr << 16) | (limit & 0xffff); +    e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000); +    e2 |= flags; +    p = ptr; +    p[0] = tswap32(e1); +    p[1] = tswap32(e2); +} + +static uint64_t *idt_table; +#ifdef TARGET_X86_64 +static void set_gate64(void *ptr, unsigned int type, unsigned int dpl, +                       uint64_t addr, unsigned int sel) +{ +    uint32_t *p, e1, e2; +    e1 = (addr & 0xffff) | (sel << 16); +    e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8); +    p = ptr; +    p[0] = tswap32(e1); +    p[1] = tswap32(e2); +    p[2] = tswap32(addr >> 32); +    p[3] = 0; +} +/* only dpl matters as we do only user space emulation */ +static void set_idt(int n, unsigned int dpl) +{ +    set_gate64(idt_table + n * 2, 0, dpl, 0, 0); +} +#else +static void set_gate(void *ptr, unsigned int type, unsigned int dpl, +                     uint32_t addr, unsigned int sel) +{ +    uint32_t *p, e1, e2; +    e1 = (addr & 0xffff) | (sel << 16); +    e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8); +    p = ptr; +    p[0] = tswap32(e1); +    p[1] = tswap32(e2); +} + +/* only dpl matters as we do only user space emulation */ +static void set_idt(int n, unsigned int dpl) +{ +    set_gate(idt_table + n, 0, dpl, 0, 0); +} +#endif + +void cpu_loop(CPUX86State *env) +{ +    CPUState *cs = CPU(x86_env_get_cpu(env)); +    int trapnr; +    abi_ulong pc; +    target_siginfo_t info; + +    for(;;) { +        cpu_exec_start(cs); +        trapnr = cpu_x86_exec(cs); +        cpu_exec_end(cs); +        switch(trapnr) { +        case 0x80: +            /* linux syscall from int $0x80 */ +            env->regs[R_EAX] = do_syscall(env, +                                          env->regs[R_EAX], +                                          env->regs[R_EBX], +                                          env->regs[R_ECX], +                                          env->regs[R_EDX], +                                          env->regs[R_ESI], +                                          env->regs[R_EDI], +                                          env->regs[R_EBP], +                                          0, 0); +            break; +#ifndef TARGET_ABI32 +        case EXCP_SYSCALL: +            /* linux syscall from syscall instruction */ +            env->regs[R_EAX] = do_syscall(env, +                                          env->regs[R_EAX], +                                          env->regs[R_EDI], +                                          env->regs[R_ESI], +                                          env->regs[R_EDX], +                                          env->regs[10], +                                          env->regs[8], +                                          env->regs[9], +                                          0, 0); +            break; +#endif +        case EXCP0B_NOSEG: +        case EXCP0C_STACK: +            info.si_signo = TARGET_SIGBUS; +            info.si_errno = 0; +            info.si_code = TARGET_SI_KERNEL; +            info._sifields._sigfault._addr = 0; +            queue_signal(env, info.si_signo, &info); +            break; +        case EXCP0D_GPF: +            /* XXX: potential problem if ABI32 */ +#ifndef TARGET_X86_64 +            if (env->eflags & VM_MASK) { +                handle_vm86_fault(env); +            } else +#endif +            { +                info.si_signo = TARGET_SIGSEGV; +                info.si_errno = 0; +                info.si_code = TARGET_SI_KERNEL; +                info._sifields._sigfault._addr = 0; +                queue_signal(env, info.si_signo, &info); +            } +            break; +        case EXCP0E_PAGE: +            info.si_signo = TARGET_SIGSEGV; +            info.si_errno = 0; +            if (!(env->error_code & 1)) +                info.si_code = TARGET_SEGV_MAPERR; +            else +                info.si_code = TARGET_SEGV_ACCERR; +            info._sifields._sigfault._addr = env->cr[2]; +            queue_signal(env, info.si_signo, &info); +            break; +        case EXCP00_DIVZ: +#ifndef TARGET_X86_64 +            if (env->eflags & VM_MASK) { +                handle_vm86_trap(env, trapnr); +            } else +#endif +            { +                /* division by zero */ +                info.si_signo = TARGET_SIGFPE; +                info.si_errno = 0; +                info.si_code = TARGET_FPE_INTDIV; +                info._sifields._sigfault._addr = env->eip; +                queue_signal(env, info.si_signo, &info); +            } +            break; +        case EXCP01_DB: +        case EXCP03_INT3: +#ifndef TARGET_X86_64 +            if (env->eflags & VM_MASK) { +                handle_vm86_trap(env, trapnr); +            } else +#endif +            { +                info.si_signo = TARGET_SIGTRAP; +                info.si_errno = 0; +                if (trapnr == EXCP01_DB) { +                    info.si_code = TARGET_TRAP_BRKPT; +                    info._sifields._sigfault._addr = env->eip; +                } else { +                    info.si_code = TARGET_SI_KERNEL; +                    info._sifields._sigfault._addr = 0; +                } +                queue_signal(env, info.si_signo, &info); +            } +            break; +        case EXCP04_INTO: +        case EXCP05_BOUND: +#ifndef TARGET_X86_64 +            if (env->eflags & VM_MASK) { +                handle_vm86_trap(env, trapnr); +            } else +#endif +            { +                info.si_signo = TARGET_SIGSEGV; +                info.si_errno = 0; +                info.si_code = TARGET_SI_KERNEL; +                info._sifields._sigfault._addr = 0; +                queue_signal(env, info.si_signo, &info); +            } +            break; +        case EXCP06_ILLOP: +            info.si_signo = TARGET_SIGILL; +            info.si_errno = 0; +            info.si_code = TARGET_ILL_ILLOPN; +            info._sifields._sigfault._addr = env->eip; +            queue_signal(env, info.si_signo, &info); +            break; +        case EXCP_INTERRUPT: +            /* just indicate that signals should be handled asap */ +            break; +        case EXCP_DEBUG: +            { +                int sig; + +                sig = gdb_handlesig(cs, TARGET_SIGTRAP); +                if (sig) +                  { +                    info.si_signo = sig; +                    info.si_errno = 0; +                    info.si_code = TARGET_TRAP_BRKPT; +                    queue_signal(env, info.si_signo, &info); +                  } +            } +            break; +        default: +            pc = env->segs[R_CS].base + env->eip; +            fprintf(stderr, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n", +                    (long)pc, trapnr); +            abort(); +        } +        process_pending_signals(env); +    } +} +#endif + +#ifdef TARGET_ARM + +#define get_user_code_u32(x, gaddr, doswap)             \ +    ({ abi_long __r = get_user_u32((x), (gaddr));       \ +        if (!__r && (doswap)) {                         \ +            (x) = bswap32(x);                           \ +        }                                               \ +        __r;                                            \ +    }) + +#define get_user_code_u16(x, gaddr, doswap)             \ +    ({ abi_long __r = get_user_u16((x), (gaddr));       \ +        if (!__r && (doswap)) {                         \ +            (x) = bswap16(x);                           \ +        }                                               \ +        __r;                                            \ +    }) + +#ifdef TARGET_ABI32 +/* Commpage handling -- there is no commpage for AArch64 */ + +/* + * See the Linux kernel's Documentation/arm/kernel_user_helpers.txt + * Input: + * r0 = pointer to oldval + * r1 = pointer to newval + * r2 = pointer to target value + * + * Output: + * r0 = 0 if *ptr was changed, non-0 if no exchange happened + * C set if *ptr was changed, clear if no exchange happened + * + * Note segv's in kernel helpers are a bit tricky, we can set the + * data address sensibly but the PC address is just the entry point. + */ +static void arm_kernel_cmpxchg64_helper(CPUARMState *env) +{ +    uint64_t oldval, newval, val; +    uint32_t addr, cpsr; +    target_siginfo_t info; + +    /* Based on the 32 bit code in do_kernel_trap */ + +    /* XXX: This only works between threads, not between processes. +       It's probably possible to implement this with native host +       operations. However things like ldrex/strex are much harder so +       there's not much point trying.  */ +    start_exclusive(); +    cpsr = cpsr_read(env); +    addr = env->regs[2]; + +    if (get_user_u64(oldval, env->regs[0])) { +        env->exception.vaddress = env->regs[0]; +        goto segv; +    }; + +    if (get_user_u64(newval, env->regs[1])) { +        env->exception.vaddress = env->regs[1]; +        goto segv; +    }; + +    if (get_user_u64(val, addr)) { +        env->exception.vaddress = addr; +        goto segv; +    } + +    if (val == oldval) { +        val = newval; + +        if (put_user_u64(val, addr)) { +            env->exception.vaddress = addr; +            goto segv; +        }; + +        env->regs[0] = 0; +        cpsr |= CPSR_C; +    } else { +        env->regs[0] = -1; +        cpsr &= ~CPSR_C; +    } +    cpsr_write(env, cpsr, CPSR_C); +    end_exclusive(); +    return; + +segv: +    end_exclusive(); +    /* We get the PC of the entry address - which is as good as anything, +       on a real kernel what you get depends on which mode it uses. */ +    info.si_signo = TARGET_SIGSEGV; +    info.si_errno = 0; +    /* XXX: check env->error_code */ +    info.si_code = TARGET_SEGV_MAPERR; +    info._sifields._sigfault._addr = env->exception.vaddress; +    queue_signal(env, info.si_signo, &info); +} + +/* Handle a jump to the kernel code page.  */ +static int +do_kernel_trap(CPUARMState *env) +{ +    uint32_t addr; +    uint32_t cpsr; +    uint32_t val; + +    switch (env->regs[15]) { +    case 0xffff0fa0: /* __kernel_memory_barrier */ +        /* ??? No-op. Will need to do better for SMP.  */ +        break; +    case 0xffff0fc0: /* __kernel_cmpxchg */ +         /* XXX: This only works between threads, not between processes. +            It's probably possible to implement this with native host +            operations. However things like ldrex/strex are much harder so +            there's not much point trying.  */ +        start_exclusive(); +        cpsr = cpsr_read(env); +        addr = env->regs[2]; +        /* FIXME: This should SEGV if the access fails.  */ +        if (get_user_u32(val, addr)) +            val = ~env->regs[0]; +        if (val == env->regs[0]) { +            val = env->regs[1]; +            /* FIXME: Check for segfaults.  */ +            put_user_u32(val, addr); +            env->regs[0] = 0; +            cpsr |= CPSR_C; +        } else { +            env->regs[0] = -1; +            cpsr &= ~CPSR_C; +        } +        cpsr_write(env, cpsr, CPSR_C); +        end_exclusive(); +        break; +    case 0xffff0fe0: /* __kernel_get_tls */ +        env->regs[0] = cpu_get_tls(env); +        break; +    case 0xffff0f60: /* __kernel_cmpxchg64 */ +        arm_kernel_cmpxchg64_helper(env); +        break; + +    default: +        return 1; +    } +    /* Jump back to the caller.  */ +    addr = env->regs[14]; +    if (addr & 1) { +        env->thumb = 1; +        addr &= ~1; +    } +    env->regs[15] = addr; + +    return 0; +} + +/* Store exclusive handling for AArch32 */ +static int do_strex(CPUARMState *env) +{ +    uint64_t val; +    int size; +    int rc = 1; +    int segv = 0; +    uint32_t addr; +    start_exclusive(); +    if (env->exclusive_addr != env->exclusive_test) { +        goto fail; +    } +    /* We know we're always AArch32 so the address is in uint32_t range +     * unless it was the -1 exclusive-monitor-lost value (which won't +     * match exclusive_test above). +     */ +    assert(extract64(env->exclusive_addr, 32, 32) == 0); +    addr = env->exclusive_addr; +    size = env->exclusive_info & 0xf; +    switch (size) { +    case 0: +        segv = get_user_u8(val, addr); +        break; +    case 1: +        segv = get_user_u16(val, addr); +        break; +    case 2: +    case 3: +        segv = get_user_u32(val, addr); +        break; +    default: +        abort(); +    } +    if (segv) { +        env->exception.vaddress = addr; +        goto done; +    } +    if (size == 3) { +        uint32_t valhi; +        segv = get_user_u32(valhi, addr + 4); +        if (segv) { +            env->exception.vaddress = addr + 4; +            goto done; +        } +        val = deposit64(val, 32, 32, valhi); +    } +    if (val != env->exclusive_val) { +        goto fail; +    } + +    val = env->regs[(env->exclusive_info >> 8) & 0xf]; +    switch (size) { +    case 0: +        segv = put_user_u8(val, addr); +        break; +    case 1: +        segv = put_user_u16(val, addr); +        break; +    case 2: +    case 3: +        segv = put_user_u32(val, addr); +        break; +    } +    if (segv) { +        env->exception.vaddress = addr; +        goto done; +    } +    if (size == 3) { +        val = env->regs[(env->exclusive_info >> 12) & 0xf]; +        segv = put_user_u32(val, addr + 4); +        if (segv) { +            env->exception.vaddress = addr + 4; +            goto done; +        } +    } +    rc = 0; +fail: +    env->regs[15] += 4; +    env->regs[(env->exclusive_info >> 4) & 0xf] = rc; +done: +    end_exclusive(); +    return segv; +} + +void cpu_loop(CPUARMState *env) +{ +    CPUState *cs = CPU(arm_env_get_cpu(env)); +    int trapnr; +    unsigned int n, insn; +    target_siginfo_t info; +    uint32_t addr; + +    for(;;) { +        cpu_exec_start(cs); +        trapnr = cpu_arm_exec(cs); +        cpu_exec_end(cs); +        switch(trapnr) { +        case EXCP_UDEF: +            { +                TaskState *ts = cs->opaque; +                uint32_t opcode; +                int rc; + +                /* we handle the FPU emulation here, as Linux */ +                /* we get the opcode */ +                /* FIXME - what to do if get_user() fails? */ +                get_user_code_u32(opcode, env->regs[15], env->bswap_code); + +                rc = EmulateAll(opcode, &ts->fpa, env); +                if (rc == 0) { /* illegal instruction */ +                    info.si_signo = TARGET_SIGILL; +                    info.si_errno = 0; +                    info.si_code = TARGET_ILL_ILLOPN; +                    info._sifields._sigfault._addr = env->regs[15]; +                    queue_signal(env, info.si_signo, &info); +                } else if (rc < 0) { /* FP exception */ +                    int arm_fpe=0; + +                    /* translate softfloat flags to FPSR flags */ +                    if (-rc & float_flag_invalid) +                      arm_fpe |= BIT_IOC; +                    if (-rc & float_flag_divbyzero) +                      arm_fpe |= BIT_DZC; +                    if (-rc & float_flag_overflow) +                      arm_fpe |= BIT_OFC; +                    if (-rc & float_flag_underflow) +                      arm_fpe |= BIT_UFC; +                    if (-rc & float_flag_inexact) +                      arm_fpe |= BIT_IXC; + +                    FPSR fpsr = ts->fpa.fpsr; +                    //printf("fpsr 0x%x, arm_fpe 0x%x\n",fpsr,arm_fpe); + +                    if (fpsr & (arm_fpe << 16)) { /* exception enabled? */ +                      info.si_signo = TARGET_SIGFPE; +                      info.si_errno = 0; + +                      /* ordered by priority, least first */ +                      if (arm_fpe & BIT_IXC) info.si_code = TARGET_FPE_FLTRES; +                      if (arm_fpe & BIT_UFC) info.si_code = TARGET_FPE_FLTUND; +                      if (arm_fpe & BIT_OFC) info.si_code = TARGET_FPE_FLTOVF; +                      if (arm_fpe & BIT_DZC) info.si_code = TARGET_FPE_FLTDIV; +                      if (arm_fpe & BIT_IOC) info.si_code = TARGET_FPE_FLTINV; + +                      info._sifields._sigfault._addr = env->regs[15]; +                      queue_signal(env, info.si_signo, &info); +                    } else { +                      env->regs[15] += 4; +                    } + +                    /* accumulate unenabled exceptions */ +                    if ((!(fpsr & BIT_IXE)) && (arm_fpe & BIT_IXC)) +                      fpsr |= BIT_IXC; +                    if ((!(fpsr & BIT_UFE)) && (arm_fpe & BIT_UFC)) +                      fpsr |= BIT_UFC; +                    if ((!(fpsr & BIT_OFE)) && (arm_fpe & BIT_OFC)) +                      fpsr |= BIT_OFC; +                    if ((!(fpsr & BIT_DZE)) && (arm_fpe & BIT_DZC)) +                      fpsr |= BIT_DZC; +                    if ((!(fpsr & BIT_IOE)) && (arm_fpe & BIT_IOC)) +                      fpsr |= BIT_IOC; +                    ts->fpa.fpsr=fpsr; +                } else { /* everything OK */ +                    /* increment PC */ +                    env->regs[15] += 4; +                } +            } +            break; +        case EXCP_SWI: +        case EXCP_BKPT: +            { +                env->eabi = 1; +                /* system call */ +                if (trapnr == EXCP_BKPT) { +                    if (env->thumb) { +                        /* FIXME - what to do if get_user() fails? */ +                        get_user_code_u16(insn, env->regs[15], env->bswap_code); +                        n = insn & 0xff; +                        env->regs[15] += 2; +                    } else { +                        /* FIXME - what to do if get_user() fails? */ +                        get_user_code_u32(insn, env->regs[15], env->bswap_code); +                        n = (insn & 0xf) | ((insn >> 4) & 0xff0); +                        env->regs[15] += 4; +                    } +                } else { +                    if (env->thumb) { +                        /* FIXME - what to do if get_user() fails? */ +                        get_user_code_u16(insn, env->regs[15] - 2, +                                          env->bswap_code); +                        n = insn & 0xff; +                    } else { +                        /* FIXME - what to do if get_user() fails? */ +                        get_user_code_u32(insn, env->regs[15] - 4, +                                          env->bswap_code); +                        n = insn & 0xffffff; +                    } +                } + +                if (n == ARM_NR_cacheflush) { +                    /* nop */ +                } else if (n == ARM_NR_semihosting +                           || n == ARM_NR_thumb_semihosting) { +                    env->regs[0] = do_arm_semihosting (env); +                } else if (n == 0 || n >= ARM_SYSCALL_BASE || env->thumb) { +                    /* linux syscall */ +                    if (env->thumb || n == 0) { +                        n = env->regs[7]; +                    } else { +                        n -= ARM_SYSCALL_BASE; +                        env->eabi = 0; +                    } +                    if ( n > ARM_NR_BASE) { +                        switch (n) { +                        case ARM_NR_cacheflush: +                            /* nop */ +                            break; +                        case ARM_NR_set_tls: +                            cpu_set_tls(env, env->regs[0]); +                            env->regs[0] = 0; +                            break; +                        case ARM_NR_breakpoint: +                            env->regs[15] -= env->thumb ? 2 : 4; +                            goto excp_debug; +                        default: +                            gemu_log("qemu: Unsupported ARM syscall: 0x%x\n", +                                     n); +                            env->regs[0] = -TARGET_ENOSYS; +                            break; +                        } +                    } else { +                        env->regs[0] = do_syscall(env, +                                                  n, +                                                  env->regs[0], +                                                  env->regs[1], +                                                  env->regs[2], +                                                  env->regs[3], +                                                  env->regs[4], +                                                  env->regs[5], +                                                  0, 0); +                    } +                } else { +                    goto error; +                } +            } +            break; +        case EXCP_INTERRUPT: +            /* just indicate that signals should be handled asap */ +            break; +        case EXCP_STREX: +            if (!do_strex(env)) { +                break; +            } +            /* fall through for segv */ +        case EXCP_PREFETCH_ABORT: +        case EXCP_DATA_ABORT: +            addr = env->exception.vaddress; +            { +                info.si_signo = TARGET_SIGSEGV; +                info.si_errno = 0; +                /* XXX: check env->error_code */ +                info.si_code = TARGET_SEGV_MAPERR; +                info._sifields._sigfault._addr = addr; +                queue_signal(env, info.si_signo, &info); +            } +            break; +        case EXCP_DEBUG: +        excp_debug: +            { +                int sig; + +                sig = gdb_handlesig(cs, TARGET_SIGTRAP); +                if (sig) +                  { +                    info.si_signo = sig; +                    info.si_errno = 0; +                    info.si_code = TARGET_TRAP_BRKPT; +                    queue_signal(env, info.si_signo, &info); +                  } +            } +            break; +        case EXCP_KERNEL_TRAP: +            if (do_kernel_trap(env)) +              goto error; +            break; +        default: +        error: +            fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", +                    trapnr); +            cpu_dump_state(cs, stderr, fprintf, 0); +            abort(); +        } +        process_pending_signals(env); +    } +} + +#else + +/* + * Handle AArch64 store-release exclusive + * + * rs = gets the status result of store exclusive + * rt = is the register that is stored + * rt2 = is the second register store (in STP) + * + */ +static int do_strex_a64(CPUARMState *env) +{ +    uint64_t val; +    int size; +    bool is_pair; +    int rc = 1; +    int segv = 0; +    uint64_t addr; +    int rs, rt, rt2; + +    start_exclusive(); +    /* size | is_pair << 2 | (rs << 4) | (rt << 9) | (rt2 << 14)); */ +    size = extract32(env->exclusive_info, 0, 2); +    is_pair = extract32(env->exclusive_info, 2, 1); +    rs = extract32(env->exclusive_info, 4, 5); +    rt = extract32(env->exclusive_info, 9, 5); +    rt2 = extract32(env->exclusive_info, 14, 5); + +    addr = env->exclusive_addr; + +    if (addr != env->exclusive_test) { +        goto finish; +    } + +    switch (size) { +    case 0: +        segv = get_user_u8(val, addr); +        break; +    case 1: +        segv = get_user_u16(val, addr); +        break; +    case 2: +        segv = get_user_u32(val, addr); +        break; +    case 3: +        segv = get_user_u64(val, addr); +        break; +    default: +        abort(); +    } +    if (segv) { +        env->exception.vaddress = addr; +        goto error; +    } +    if (val != env->exclusive_val) { +        goto finish; +    } +    if (is_pair) { +        if (size == 2) { +            segv = get_user_u32(val, addr + 4); +        } else { +            segv = get_user_u64(val, addr + 8); +        } +        if (segv) { +            env->exception.vaddress = addr + (size == 2 ? 4 : 8); +            goto error; +        } +        if (val != env->exclusive_high) { +            goto finish; +        } +    } +    /* handle the zero register */ +    val = rt == 31 ? 0 : env->xregs[rt]; +    switch (size) { +    case 0: +        segv = put_user_u8(val, addr); +        break; +    case 1: +        segv = put_user_u16(val, addr); +        break; +    case 2: +        segv = put_user_u32(val, addr); +        break; +    case 3: +        segv = put_user_u64(val, addr); +        break; +    } +    if (segv) { +        goto error; +    } +    if (is_pair) { +        /* handle the zero register */ +        val = rt2 == 31 ? 0 : env->xregs[rt2]; +        if (size == 2) { +            segv = put_user_u32(val, addr + 4); +        } else { +            segv = put_user_u64(val, addr + 8); +        } +        if (segv) { +            env->exception.vaddress = addr + (size == 2 ? 4 : 8); +            goto error; +        } +    } +    rc = 0; +finish: +    env->pc += 4; +    /* rs == 31 encodes a write to the ZR, thus throwing away +     * the status return. This is rather silly but valid. +     */ +    if (rs < 31) { +        env->xregs[rs] = rc; +    } +error: +    /* instruction faulted, PC does not advance */ +    /* either way a strex releases any exclusive lock we have */ +    env->exclusive_addr = -1; +    end_exclusive(); +    return segv; +} + +/* AArch64 main loop */ +void cpu_loop(CPUARMState *env) +{ +    CPUState *cs = CPU(arm_env_get_cpu(env)); +    int trapnr, sig; +    target_siginfo_t info; + +    for (;;) { +        cpu_exec_start(cs); +        trapnr = cpu_arm_exec(cs); +        cpu_exec_end(cs); + +        switch (trapnr) { +        case EXCP_SWI: +            env->xregs[0] = do_syscall(env, +                                       env->xregs[8], +                                       env->xregs[0], +                                       env->xregs[1], +                                       env->xregs[2], +                                       env->xregs[3], +                                       env->xregs[4], +                                       env->xregs[5], +                                       0, 0); +            break; +        case EXCP_INTERRUPT: +            /* just indicate that signals should be handled asap */ +            break; +        case EXCP_UDEF: +            info.si_signo = TARGET_SIGILL; +            info.si_errno = 0; +            info.si_code = TARGET_ILL_ILLOPN; +            info._sifields._sigfault._addr = env->pc; +            queue_signal(env, info.si_signo, &info); +            break; +        case EXCP_STREX: +            if (!do_strex_a64(env)) { +                break; +            } +            /* fall through for segv */ +        case EXCP_PREFETCH_ABORT: +        case EXCP_DATA_ABORT: +            info.si_signo = TARGET_SIGSEGV; +            info.si_errno = 0; +            /* XXX: check env->error_code */ +            info.si_code = TARGET_SEGV_MAPERR; +            info._sifields._sigfault._addr = env->exception.vaddress; +            queue_signal(env, info.si_signo, &info); +            break; +        case EXCP_DEBUG: +        case EXCP_BKPT: +            sig = gdb_handlesig(cs, TARGET_SIGTRAP); +            if (sig) { +                info.si_signo = sig; +                info.si_errno = 0; +                info.si_code = TARGET_TRAP_BRKPT; +                queue_signal(env, info.si_signo, &info); +            } +            break; +        default: +            fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", +                    trapnr); +            cpu_dump_state(cs, stderr, fprintf, 0); +            abort(); +        } +        process_pending_signals(env); +        /* Exception return on AArch64 always clears the exclusive monitor, +         * so any return to running guest code implies this. +         * A strex (successful or otherwise) also clears the monitor, so +         * we don't need to specialcase EXCP_STREX. +         */ +        env->exclusive_addr = -1; +    } +} +#endif /* ndef TARGET_ABI32 */ + +#endif + +#ifdef TARGET_UNICORE32 + +void cpu_loop(CPUUniCore32State *env) +{ +    CPUState *cs = CPU(uc32_env_get_cpu(env)); +    int trapnr; +    unsigned int n, insn; +    target_siginfo_t info; + +    for (;;) { +        cpu_exec_start(cs); +        trapnr = uc32_cpu_exec(cs); +        cpu_exec_end(cs); +        switch (trapnr) { +        case UC32_EXCP_PRIV: +            { +                /* system call */ +                get_user_u32(insn, env->regs[31] - 4); +                n = insn & 0xffffff; + +                if (n >= UC32_SYSCALL_BASE) { +                    /* linux syscall */ +                    n -= UC32_SYSCALL_BASE; +                    if (n == UC32_SYSCALL_NR_set_tls) { +                            cpu_set_tls(env, env->regs[0]); +                            env->regs[0] = 0; +                    } else { +                        env->regs[0] = do_syscall(env, +                                                  n, +                                                  env->regs[0], +                                                  env->regs[1], +                                                  env->regs[2], +                                                  env->regs[3], +                                                  env->regs[4], +                                                  env->regs[5], +                                                  0, 0); +                    } +                } else { +                    goto error; +                } +            } +            break; +        case UC32_EXCP_DTRAP: +        case UC32_EXCP_ITRAP: +            info.si_signo = TARGET_SIGSEGV; +            info.si_errno = 0; +            /* XXX: check env->error_code */ +            info.si_code = TARGET_SEGV_MAPERR; +            info._sifields._sigfault._addr = env->cp0.c4_faultaddr; +            queue_signal(env, info.si_signo, &info); +            break; +        case EXCP_INTERRUPT: +            /* just indicate that signals should be handled asap */ +            break; +        case EXCP_DEBUG: +            { +                int sig; + +                sig = gdb_handlesig(cs, TARGET_SIGTRAP); +                if (sig) { +                    info.si_signo = sig; +                    info.si_errno = 0; +                    info.si_code = TARGET_TRAP_BRKPT; +                    queue_signal(env, info.si_signo, &info); +                } +            } +            break; +        default: +            goto error; +        } +        process_pending_signals(env); +    } + +error: +    fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); +    cpu_dump_state(cs, stderr, fprintf, 0); +    abort(); +} +#endif + +#ifdef TARGET_SPARC +#define SPARC64_STACK_BIAS 2047 + +//#define DEBUG_WIN + +/* WARNING: dealing with register windows _is_ complicated. More info +   can be found at http://www.sics.se/~psm/sparcstack.html */ +static inline int get_reg_index(CPUSPARCState *env, int cwp, int index) +{ +    index = (index + cwp * 16) % (16 * env->nwindows); +    /* wrap handling : if cwp is on the last window, then we use the +       registers 'after' the end */ +    if (index < 8 && env->cwp == env->nwindows - 1) +        index += 16 * env->nwindows; +    return index; +} + +/* save the register window 'cwp1' */ +static inline void save_window_offset(CPUSPARCState *env, int cwp1) +{ +    unsigned int i; +    abi_ulong sp_ptr; + +    sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; +#ifdef TARGET_SPARC64 +    if (sp_ptr & 3) +        sp_ptr += SPARC64_STACK_BIAS; +#endif +#if defined(DEBUG_WIN) +    printf("win_overflow: sp_ptr=0x" TARGET_ABI_FMT_lx " save_cwp=%d\n", +           sp_ptr, cwp1); +#endif +    for(i = 0; i < 16; i++) { +        /* FIXME - what to do if put_user() fails? */ +        put_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr); +        sp_ptr += sizeof(abi_ulong); +    } +} + +static void save_window(CPUSPARCState *env) +{ +#ifndef TARGET_SPARC64 +    unsigned int new_wim; +    new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) & +        ((1LL << env->nwindows) - 1); +    save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); +    env->wim = new_wim; +#else +    save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2)); +    env->cansave++; +    env->canrestore--; +#endif +} + +static void restore_window(CPUSPARCState *env) +{ +#ifndef TARGET_SPARC64 +    unsigned int new_wim; +#endif +    unsigned int i, cwp1; +    abi_ulong sp_ptr; + +#ifndef TARGET_SPARC64 +    new_wim = ((env->wim << 1) | (env->wim >> (env->nwindows - 1))) & +        ((1LL << env->nwindows) - 1); +#endif + +    /* restore the invalid window */ +    cwp1 = cpu_cwp_inc(env, env->cwp + 1); +    sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; +#ifdef TARGET_SPARC64 +    if (sp_ptr & 3) +        sp_ptr += SPARC64_STACK_BIAS; +#endif +#if defined(DEBUG_WIN) +    printf("win_underflow: sp_ptr=0x" TARGET_ABI_FMT_lx " load_cwp=%d\n", +           sp_ptr, cwp1); +#endif +    for(i = 0; i < 16; i++) { +        /* FIXME - what to do if get_user() fails? */ +        get_user_ual(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr); +        sp_ptr += sizeof(abi_ulong); +    } +#ifdef TARGET_SPARC64 +    env->canrestore++; +    if (env->cleanwin < env->nwindows - 1) +        env->cleanwin++; +    env->cansave--; +#else +    env->wim = new_wim; +#endif +} + +static void flush_windows(CPUSPARCState *env) +{ +    int offset, cwp1; + +    offset = 1; +    for(;;) { +        /* if restore would invoke restore_window(), then we can stop */ +        cwp1 = cpu_cwp_inc(env, env->cwp + offset); +#ifndef TARGET_SPARC64 +        if (env->wim & (1 << cwp1)) +            break; +#else +        if (env->canrestore == 0) +            break; +        env->cansave++; +        env->canrestore--; +#endif +        save_window_offset(env, cwp1); +        offset++; +    } +    cwp1 = cpu_cwp_inc(env, env->cwp + 1); +#ifndef TARGET_SPARC64 +    /* set wim so that restore will reload the registers */ +    env->wim = 1 << cwp1; +#endif +#if defined(DEBUG_WIN) +    printf("flush_windows: nb=%d\n", offset - 1); +#endif +} + +void cpu_loop (CPUSPARCState *env) +{ +    CPUState *cs = CPU(sparc_env_get_cpu(env)); +    int trapnr; +    abi_long ret; +    target_siginfo_t info; + +    while (1) { +        cpu_exec_start(cs); +        trapnr = cpu_sparc_exec(cs); +        cpu_exec_end(cs); + +        /* Compute PSR before exposing state.  */ +        if (env->cc_op != CC_OP_FLAGS) { +            cpu_get_psr(env); +        } + +        switch (trapnr) { +#ifndef TARGET_SPARC64 +        case 0x88: +        case 0x90: +#else +        case 0x110: +        case 0x16d: +#endif +            ret = do_syscall (env, env->gregs[1], +                              env->regwptr[0], env->regwptr[1], +                              env->regwptr[2], env->regwptr[3], +                              env->regwptr[4], env->regwptr[5], +                              0, 0); +            if ((abi_ulong)ret >= (abi_ulong)(-515)) { +#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) +                env->xcc |= PSR_CARRY; +#else +                env->psr |= PSR_CARRY; +#endif +                ret = -ret; +            } else { +#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) +                env->xcc &= ~PSR_CARRY; +#else +                env->psr &= ~PSR_CARRY; +#endif +            } +            env->regwptr[0] = ret; +            /* next instruction */ +            env->pc = env->npc; +            env->npc = env->npc + 4; +            break; +        case 0x83: /* flush windows */ +#ifdef TARGET_ABI32 +        case 0x103: +#endif +            flush_windows(env); +            /* next instruction */ +            env->pc = env->npc; +            env->npc = env->npc + 4; +            break; +#ifndef TARGET_SPARC64 +        case TT_WIN_OVF: /* window overflow */ +            save_window(env); +            break; +        case TT_WIN_UNF: /* window underflow */ +            restore_window(env); +            break; +        case TT_TFAULT: +        case TT_DFAULT: +            { +                info.si_signo = TARGET_SIGSEGV; +                info.si_errno = 0; +                /* XXX: check env->error_code */ +                info.si_code = TARGET_SEGV_MAPERR; +                info._sifields._sigfault._addr = env->mmuregs[4]; +                queue_signal(env, info.si_signo, &info); +            } +            break; +#else +        case TT_SPILL: /* window overflow */ +            save_window(env); +            break; +        case TT_FILL: /* window underflow */ +            restore_window(env); +            break; +        case TT_TFAULT: +        case TT_DFAULT: +            { +                info.si_signo = TARGET_SIGSEGV; +                info.si_errno = 0; +                /* XXX: check env->error_code */ +                info.si_code = TARGET_SEGV_MAPERR; +                if (trapnr == TT_DFAULT) +                    info._sifields._sigfault._addr = env->dmmuregs[4]; +                else +                    info._sifields._sigfault._addr = cpu_tsptr(env)->tpc; +                queue_signal(env, info.si_signo, &info); +            } +            break; +#ifndef TARGET_ABI32 +        case 0x16e: +            flush_windows(env); +            sparc64_get_context(env); +            break; +        case 0x16f: +            flush_windows(env); +            sparc64_set_context(env); +            break; +#endif +#endif +        case EXCP_INTERRUPT: +            /* just indicate that signals should be handled asap */ +            break; +        case TT_ILL_INSN: +            { +                info.si_signo = TARGET_SIGILL; +                info.si_errno = 0; +                info.si_code = TARGET_ILL_ILLOPC; +                info._sifields._sigfault._addr = env->pc; +                queue_signal(env, info.si_signo, &info); +            } +            break; +        case EXCP_DEBUG: +            { +                int sig; + +                sig = gdb_handlesig(cs, TARGET_SIGTRAP); +                if (sig) +                  { +                    info.si_signo = sig; +                    info.si_errno = 0; +                    info.si_code = TARGET_TRAP_BRKPT; +                    queue_signal(env, info.si_signo, &info); +                  } +            } +            break; +        default: +            printf ("Unhandled trap: 0x%x\n", trapnr); +            cpu_dump_state(cs, stderr, fprintf, 0); +            exit (1); +        } +        process_pending_signals (env); +    } +} + +#endif + +#ifdef TARGET_PPC +static inline uint64_t cpu_ppc_get_tb(CPUPPCState *env) +{ +    return cpu_get_real_ticks(); +} + +uint64_t cpu_ppc_load_tbl(CPUPPCState *env) +{ +    return cpu_ppc_get_tb(env); +} + +uint32_t cpu_ppc_load_tbu(CPUPPCState *env) +{ +    return cpu_ppc_get_tb(env) >> 32; +} + +uint64_t cpu_ppc_load_atbl(CPUPPCState *env) +{ +    return cpu_ppc_get_tb(env); +} + +uint32_t cpu_ppc_load_atbu(CPUPPCState *env) +{ +    return cpu_ppc_get_tb(env) >> 32; +} + +uint32_t cpu_ppc601_load_rtcu(CPUPPCState *env) +__attribute__ (( alias ("cpu_ppc_load_tbu") )); + +uint32_t cpu_ppc601_load_rtcl(CPUPPCState *env) +{ +    return cpu_ppc_load_tbl(env) & 0x3FFFFF80; +} + +/* XXX: to be fixed */ +int ppc_dcr_read (ppc_dcr_t *dcr_env, int dcrn, uint32_t *valp) +{ +    return -1; +} + +int ppc_dcr_write (ppc_dcr_t *dcr_env, int dcrn, uint32_t val) +{ +    return -1; +} + +#define EXCP_DUMP(env, fmt, ...)                                        \ +do {                                                                    \ +    CPUState *cs = ENV_GET_CPU(env);                                    \ +    fprintf(stderr, fmt , ## __VA_ARGS__);                              \ +    cpu_dump_state(cs, stderr, fprintf, 0);                             \ +    qemu_log(fmt, ## __VA_ARGS__);                                      \ +    if (qemu_log_enabled()) {                                           \ +        log_cpu_state(cs, 0);                                           \ +    }                                                                   \ +} while (0) + +static int do_store_exclusive(CPUPPCState *env) +{ +    target_ulong addr; +    target_ulong page_addr; +    target_ulong val, val2 __attribute__((unused)) = 0; +    int flags; +    int segv = 0; + +    addr = env->reserve_ea; +    page_addr = addr & TARGET_PAGE_MASK; +    start_exclusive(); +    mmap_lock(); +    flags = page_get_flags(page_addr); +    if ((flags & PAGE_READ) == 0) { +        segv = 1; +    } else { +        int reg = env->reserve_info & 0x1f; +        int size = env->reserve_info >> 5; +        int stored = 0; + +        if (addr == env->reserve_addr) { +            switch (size) { +            case 1: segv = get_user_u8(val, addr); break; +            case 2: segv = get_user_u16(val, addr); break; +            case 4: segv = get_user_u32(val, addr); break; +#if defined(TARGET_PPC64) +            case 8: segv = get_user_u64(val, addr); break; +            case 16: { +                segv = get_user_u64(val, addr); +                if (!segv) { +                    segv = get_user_u64(val2, addr + 8); +                } +                break; +            } +#endif +            default: abort(); +            } +            if (!segv && val == env->reserve_val) { +                val = env->gpr[reg]; +                switch (size) { +                case 1: segv = put_user_u8(val, addr); break; +                case 2: segv = put_user_u16(val, addr); break; +                case 4: segv = put_user_u32(val, addr); break; +#if defined(TARGET_PPC64) +                case 8: segv = put_user_u64(val, addr); break; +                case 16: { +                    if (val2 == env->reserve_val2) { +                        if (msr_le) { +                            val2 = val; +                            val = env->gpr[reg+1]; +                        } else { +                            val2 = env->gpr[reg+1]; +                        } +                        segv = put_user_u64(val, addr); +                        if (!segv) { +                            segv = put_user_u64(val2, addr + 8); +                        } +                    } +                    break; +                } +#endif +                default: abort(); +                } +                if (!segv) { +                    stored = 1; +                } +            } +        } +        env->crf[0] = (stored << 1) | xer_so; +        env->reserve_addr = (target_ulong)-1; +    } +    if (!segv) { +        env->nip += 4; +    } +    mmap_unlock(); +    end_exclusive(); +    return segv; +} + +void cpu_loop(CPUPPCState *env) +{ +    CPUState *cs = CPU(ppc_env_get_cpu(env)); +    target_siginfo_t info; +    int trapnr; +    target_ulong ret; + +    for(;;) { +        cpu_exec_start(cs); +        trapnr = cpu_ppc_exec(cs); +        cpu_exec_end(cs); +        switch(trapnr) { +        case POWERPC_EXCP_NONE: +            /* Just go on */ +            break; +        case POWERPC_EXCP_CRITICAL: /* Critical input                        */ +            cpu_abort(cs, "Critical interrupt while in user mode. " +                      "Aborting\n"); +            break; +        case POWERPC_EXCP_MCHECK:   /* Machine check exception               */ +            cpu_abort(cs, "Machine check exception while in user mode. " +                      "Aborting\n"); +            break; +        case POWERPC_EXCP_DSI:      /* Data storage exception                */ +            EXCP_DUMP(env, "Invalid data memory access: 0x" TARGET_FMT_lx "\n", +                      env->spr[SPR_DAR]); +            /* XXX: check this. Seems bugged */ +            switch (env->error_code & 0xFF000000) { +            case 0x40000000: +                info.si_signo = TARGET_SIGSEGV; +                info.si_errno = 0; +                info.si_code = TARGET_SEGV_MAPERR; +                break; +            case 0x04000000: +                info.si_signo = TARGET_SIGILL; +                info.si_errno = 0; +                info.si_code = TARGET_ILL_ILLADR; +                break; +            case 0x08000000: +                info.si_signo = TARGET_SIGSEGV; +                info.si_errno = 0; +                info.si_code = TARGET_SEGV_ACCERR; +                break; +            default: +                /* Let's send a regular segfault... */ +                EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", +                          env->error_code); +                info.si_signo = TARGET_SIGSEGV; +                info.si_errno = 0; +                info.si_code = TARGET_SEGV_MAPERR; +                break; +            } +            info._sifields._sigfault._addr = env->nip; +            queue_signal(env, info.si_signo, &info); +            break; +        case POWERPC_EXCP_ISI:      /* Instruction storage exception         */ +            EXCP_DUMP(env, "Invalid instruction fetch: 0x\n" TARGET_FMT_lx +                      "\n", env->spr[SPR_SRR0]); +            /* XXX: check this */ +            switch (env->error_code & 0xFF000000) { +            case 0x40000000: +                info.si_signo = TARGET_SIGSEGV; +            info.si_errno = 0; +                info.si_code = TARGET_SEGV_MAPERR; +                break; +            case 0x10000000: +            case 0x08000000: +                info.si_signo = TARGET_SIGSEGV; +                info.si_errno = 0; +                info.si_code = TARGET_SEGV_ACCERR; +                break; +            default: +                /* Let's send a regular segfault... */ +                EXCP_DUMP(env, "Invalid segfault errno (%02x)\n", +                          env->error_code); +                info.si_signo = TARGET_SIGSEGV; +                info.si_errno = 0; +                info.si_code = TARGET_SEGV_MAPERR; +                break; +            } +            info._sifields._sigfault._addr = env->nip - 4; +            queue_signal(env, info.si_signo, &info); +            break; +        case POWERPC_EXCP_EXTERNAL: /* External input                        */ +            cpu_abort(cs, "External interrupt while in user mode. " +                      "Aborting\n"); +            break; +        case POWERPC_EXCP_ALIGN:    /* Alignment exception                   */ +            EXCP_DUMP(env, "Unaligned memory access\n"); +            /* XXX: check this */ +            info.si_signo = TARGET_SIGBUS; +            info.si_errno = 0; +            info.si_code = TARGET_BUS_ADRALN; +            info._sifields._sigfault._addr = env->nip - 4; +            queue_signal(env, info.si_signo, &info); +            break; +        case POWERPC_EXCP_PROGRAM:  /* Program exception                     */ +            /* XXX: check this */ +            switch (env->error_code & ~0xF) { +            case POWERPC_EXCP_FP: +                EXCP_DUMP(env, "Floating point program exception\n"); +                info.si_signo = TARGET_SIGFPE; +                info.si_errno = 0; +                switch (env->error_code & 0xF) { +                case POWERPC_EXCP_FP_OX: +                    info.si_code = TARGET_FPE_FLTOVF; +                    break; +                case POWERPC_EXCP_FP_UX: +                    info.si_code = TARGET_FPE_FLTUND; +                    break; +                case POWERPC_EXCP_FP_ZX: +                case POWERPC_EXCP_FP_VXZDZ: +                    info.si_code = TARGET_FPE_FLTDIV; +                    break; +                case POWERPC_EXCP_FP_XX: +                    info.si_code = TARGET_FPE_FLTRES; +                    break; +                case POWERPC_EXCP_FP_VXSOFT: +                    info.si_code = TARGET_FPE_FLTINV; +                    break; +                case POWERPC_EXCP_FP_VXSNAN: +                case POWERPC_EXCP_FP_VXISI: +                case POWERPC_EXCP_FP_VXIDI: +                case POWERPC_EXCP_FP_VXIMZ: +                case POWERPC_EXCP_FP_VXVC: +                case POWERPC_EXCP_FP_VXSQRT: +                case POWERPC_EXCP_FP_VXCVI: +                    info.si_code = TARGET_FPE_FLTSUB; +                    break; +                default: +                    EXCP_DUMP(env, "Unknown floating point exception (%02x)\n", +                              env->error_code); +                    break; +                } +                break; +            case POWERPC_EXCP_INVAL: +                EXCP_DUMP(env, "Invalid instruction\n"); +                info.si_signo = TARGET_SIGILL; +                info.si_errno = 0; +                switch (env->error_code & 0xF) { +                case POWERPC_EXCP_INVAL_INVAL: +                    info.si_code = TARGET_ILL_ILLOPC; +                    break; +                case POWERPC_EXCP_INVAL_LSWX: +                    info.si_code = TARGET_ILL_ILLOPN; +                    break; +                case POWERPC_EXCP_INVAL_SPR: +                    info.si_code = TARGET_ILL_PRVREG; +                    break; +                case POWERPC_EXCP_INVAL_FP: +                    info.si_code = TARGET_ILL_COPROC; +                    break; +                default: +                    EXCP_DUMP(env, "Unknown invalid operation (%02x)\n", +                              env->error_code & 0xF); +                    info.si_code = TARGET_ILL_ILLADR; +                    break; +                } +                break; +            case POWERPC_EXCP_PRIV: +                EXCP_DUMP(env, "Privilege violation\n"); +                info.si_signo = TARGET_SIGILL; +                info.si_errno = 0; +                switch (env->error_code & 0xF) { +                case POWERPC_EXCP_PRIV_OPC: +                    info.si_code = TARGET_ILL_PRVOPC; +                    break; +                case POWERPC_EXCP_PRIV_REG: +                    info.si_code = TARGET_ILL_PRVREG; +                    break; +                default: +                    EXCP_DUMP(env, "Unknown privilege violation (%02x)\n", +                              env->error_code & 0xF); +                    info.si_code = TARGET_ILL_PRVOPC; +                    break; +                } +                break; +            case POWERPC_EXCP_TRAP: +                cpu_abort(cs, "Tried to call a TRAP\n"); +                break; +            default: +                /* Should not happen ! */ +                cpu_abort(cs, "Unknown program exception (%02x)\n", +                          env->error_code); +                break; +            } +            info._sifields._sigfault._addr = env->nip - 4; +            queue_signal(env, info.si_signo, &info); +            break; +        case POWERPC_EXCP_FPU:      /* Floating-point unavailable exception  */ +            EXCP_DUMP(env, "No floating point allowed\n"); +            info.si_signo = TARGET_SIGILL; +            info.si_errno = 0; +            info.si_code = TARGET_ILL_COPROC; +            info._sifields._sigfault._addr = env->nip - 4; +            queue_signal(env, info.si_signo, &info); +            break; +        case POWERPC_EXCP_SYSCALL:  /* System call exception                 */ +            cpu_abort(cs, "Syscall exception while in user mode. " +                      "Aborting\n"); +            break; +        case POWERPC_EXCP_APU:      /* Auxiliary processor unavailable       */ +            EXCP_DUMP(env, "No APU instruction allowed\n"); +            info.si_signo = TARGET_SIGILL; +            info.si_errno = 0; +            info.si_code = TARGET_ILL_COPROC; +            info._sifields._sigfault._addr = env->nip - 4; +            queue_signal(env, info.si_signo, &info); +            break; +        case POWERPC_EXCP_DECR:     /* Decrementer exception                 */ +            cpu_abort(cs, "Decrementer interrupt while in user mode. " +                      "Aborting\n"); +            break; +        case POWERPC_EXCP_FIT:      /* Fixed-interval timer interrupt        */ +            cpu_abort(cs, "Fix interval timer interrupt while in user mode. " +                      "Aborting\n"); +            break; +        case POWERPC_EXCP_WDT:      /* Watchdog timer interrupt              */ +            cpu_abort(cs, "Watchdog timer interrupt while in user mode. " +                      "Aborting\n"); +            break; +        case POWERPC_EXCP_DTLB:     /* Data TLB error                        */ +            cpu_abort(cs, "Data TLB exception while in user mode. " +                      "Aborting\n"); +            break; +        case POWERPC_EXCP_ITLB:     /* Instruction TLB error                 */ +            cpu_abort(cs, "Instruction TLB exception while in user mode. " +                      "Aborting\n"); +            break; +        case POWERPC_EXCP_SPEU:     /* SPE/embedded floating-point unavail.  */ +            EXCP_DUMP(env, "No SPE/floating-point instruction allowed\n"); +            info.si_signo = TARGET_SIGILL; +            info.si_errno = 0; +            info.si_code = TARGET_ILL_COPROC; +            info._sifields._sigfault._addr = env->nip - 4; +            queue_signal(env, info.si_signo, &info); +            break; +        case POWERPC_EXCP_EFPDI:    /* Embedded floating-point data IRQ      */ +            cpu_abort(cs, "Embedded floating-point data IRQ not handled\n"); +            break; +        case POWERPC_EXCP_EFPRI:    /* Embedded floating-point round IRQ     */ +            cpu_abort(cs, "Embedded floating-point round IRQ not handled\n"); +            break; +        case POWERPC_EXCP_EPERFM:   /* Embedded performance monitor IRQ      */ +            cpu_abort(cs, "Performance monitor exception not handled\n"); +            break; +        case POWERPC_EXCP_DOORI:    /* Embedded doorbell interrupt           */ +            cpu_abort(cs, "Doorbell interrupt while in user mode. " +                       "Aborting\n"); +            break; +        case POWERPC_EXCP_DOORCI:   /* Embedded doorbell critical interrupt  */ +            cpu_abort(cs, "Doorbell critical interrupt while in user mode. " +                      "Aborting\n"); +            break; +        case POWERPC_EXCP_RESET:    /* System reset exception                */ +            cpu_abort(cs, "Reset interrupt while in user mode. " +                      "Aborting\n"); +            break; +        case POWERPC_EXCP_DSEG:     /* Data segment exception                */ +            cpu_abort(cs, "Data segment exception while in user mode. " +                      "Aborting\n"); +            break; +        case POWERPC_EXCP_ISEG:     /* Instruction segment exception         */ +            cpu_abort(cs, "Instruction segment exception " +                      "while in user mode. Aborting\n"); +            break; +        /* PowerPC 64 with hypervisor mode support */ +        case POWERPC_EXCP_HDECR:    /* Hypervisor decrementer exception      */ +            cpu_abort(cs, "Hypervisor decrementer interrupt " +                      "while in user mode. Aborting\n"); +            break; +        case POWERPC_EXCP_TRACE:    /* Trace exception                       */ +            /* Nothing to do: +             * we use this exception to emulate step-by-step execution mode. +             */ +            break; +        /* PowerPC 64 with hypervisor mode support */ +        case POWERPC_EXCP_HDSI:     /* Hypervisor data storage exception     */ +            cpu_abort(cs, "Hypervisor data storage exception " +                      "while in user mode. Aborting\n"); +            break; +        case POWERPC_EXCP_HISI:     /* Hypervisor instruction storage excp   */ +            cpu_abort(cs, "Hypervisor instruction storage exception " +                      "while in user mode. Aborting\n"); +            break; +        case POWERPC_EXCP_HDSEG:    /* Hypervisor data segment exception     */ +            cpu_abort(cs, "Hypervisor data segment exception " +                      "while in user mode. Aborting\n"); +            break; +        case POWERPC_EXCP_HISEG:    /* Hypervisor instruction segment excp   */ +            cpu_abort(cs, "Hypervisor instruction segment exception " +                      "while in user mode. Aborting\n"); +            break; +        case POWERPC_EXCP_VPU:      /* Vector unavailable exception          */ +            EXCP_DUMP(env, "No Altivec instructions allowed\n"); +            info.si_signo = TARGET_SIGILL; +            info.si_errno = 0; +            info.si_code = TARGET_ILL_COPROC; +            info._sifields._sigfault._addr = env->nip - 4; +            queue_signal(env, info.si_signo, &info); +            break; +        case POWERPC_EXCP_PIT:      /* Programmable interval timer IRQ       */ +            cpu_abort(cs, "Programmable interval timer interrupt " +                      "while in user mode. Aborting\n"); +            break; +        case POWERPC_EXCP_IO:       /* IO error exception                    */ +            cpu_abort(cs, "IO error exception while in user mode. " +                      "Aborting\n"); +            break; +        case POWERPC_EXCP_RUNM:     /* Run mode exception                    */ +            cpu_abort(cs, "Run mode exception while in user mode. " +                      "Aborting\n"); +            break; +        case POWERPC_EXCP_EMUL:     /* Emulation trap exception              */ +            cpu_abort(cs, "Emulation trap exception not handled\n"); +            break; +        case POWERPC_EXCP_IFTLB:    /* Instruction fetch TLB error           */ +            cpu_abort(cs, "Instruction fetch TLB exception " +                      "while in user-mode. Aborting"); +            break; +        case POWERPC_EXCP_DLTLB:    /* Data load TLB miss                    */ +            cpu_abort(cs, "Data load TLB exception while in user-mode. " +                      "Aborting"); +            break; +        case POWERPC_EXCP_DSTLB:    /* Data store TLB miss                   */ +            cpu_abort(cs, "Data store TLB exception while in user-mode. " +                      "Aborting"); +            break; +        case POWERPC_EXCP_FPA:      /* Floating-point assist exception       */ +            cpu_abort(cs, "Floating-point assist exception not handled\n"); +            break; +        case POWERPC_EXCP_IABR:     /* Instruction address breakpoint        */ +            cpu_abort(cs, "Instruction address breakpoint exception " +                      "not handled\n"); +            break; +        case POWERPC_EXCP_SMI:      /* System management interrupt           */ +            cpu_abort(cs, "System management interrupt while in user mode. " +                      "Aborting\n"); +            break; +        case POWERPC_EXCP_THERM:    /* Thermal interrupt                     */ +            cpu_abort(cs, "Thermal interrupt interrupt while in user mode. " +                      "Aborting\n"); +            break; +        case POWERPC_EXCP_PERFM:   /* Embedded performance monitor IRQ      */ +            cpu_abort(cs, "Performance monitor exception not handled\n"); +            break; +        case POWERPC_EXCP_VPUA:     /* Vector assist exception               */ +            cpu_abort(cs, "Vector assist exception not handled\n"); +            break; +        case POWERPC_EXCP_SOFTP:    /* Soft patch exception                  */ +            cpu_abort(cs, "Soft patch exception not handled\n"); +            break; +        case POWERPC_EXCP_MAINT:    /* Maintenance exception                 */ +            cpu_abort(cs, "Maintenance exception while in user mode. " +                      "Aborting\n"); +            break; +        case POWERPC_EXCP_STOP:     /* stop translation                      */ +            /* We did invalidate the instruction cache. Go on */ +            break; +        case POWERPC_EXCP_BRANCH:   /* branch instruction:                   */ +            /* We just stopped because of a branch. Go on */ +            break; +        case POWERPC_EXCP_SYSCALL_USER: +            /* system call in user-mode emulation */ +            /* WARNING: +             * PPC ABI uses overflow flag in cr0 to signal an error +             * in syscalls. +             */ +            env->crf[0] &= ~0x1; +            ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4], +                             env->gpr[5], env->gpr[6], env->gpr[7], +                             env->gpr[8], 0, 0); +            if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) { +                /* Returning from a successful sigreturn syscall. +                   Avoid corrupting register state.  */ +                break; +            } +            if (ret > (target_ulong)(-515)) { +                env->crf[0] |= 0x1; +                ret = -ret; +            } +            env->gpr[3] = ret; +            break; +        case POWERPC_EXCP_STCX: +            if (do_store_exclusive(env)) { +                info.si_signo = TARGET_SIGSEGV; +                info.si_errno = 0; +                info.si_code = TARGET_SEGV_MAPERR; +                info._sifields._sigfault._addr = env->nip; +                queue_signal(env, info.si_signo, &info); +            } +            break; +        case EXCP_DEBUG: +            { +                int sig; + +                sig = gdb_handlesig(cs, TARGET_SIGTRAP); +                if (sig) { +                    info.si_signo = sig; +                    info.si_errno = 0; +                    info.si_code = TARGET_TRAP_BRKPT; +                    queue_signal(env, info.si_signo, &info); +                  } +            } +            break; +        case EXCP_INTERRUPT: +            /* just indicate that signals should be handled asap */ +            break; +        default: +            cpu_abort(cs, "Unknown exception 0x%d. Aborting\n", trapnr); +            break; +        } +        process_pending_signals(env); +    } +} +#endif + +#ifdef TARGET_MIPS + +# ifdef TARGET_ABI_MIPSO32 +#  define MIPS_SYS(name, args) args, +static const uint8_t mips_syscall_args[] = { +	MIPS_SYS(sys_syscall	, 8)	/* 4000 */ +	MIPS_SYS(sys_exit	, 1) +	MIPS_SYS(sys_fork	, 0) +	MIPS_SYS(sys_read	, 3) +	MIPS_SYS(sys_write	, 3) +	MIPS_SYS(sys_open	, 3)	/* 4005 */ +	MIPS_SYS(sys_close	, 1) +	MIPS_SYS(sys_waitpid	, 3) +	MIPS_SYS(sys_creat	, 2) +	MIPS_SYS(sys_link	, 2) +	MIPS_SYS(sys_unlink	, 1)	/* 4010 */ +	MIPS_SYS(sys_execve	, 0) +	MIPS_SYS(sys_chdir	, 1) +	MIPS_SYS(sys_time	, 1) +	MIPS_SYS(sys_mknod	, 3) +	MIPS_SYS(sys_chmod	, 2)	/* 4015 */ +	MIPS_SYS(sys_lchown	, 3) +	MIPS_SYS(sys_ni_syscall	, 0) +	MIPS_SYS(sys_ni_syscall	, 0)	/* was sys_stat */ +	MIPS_SYS(sys_lseek	, 3) +	MIPS_SYS(sys_getpid	, 0)	/* 4020 */ +	MIPS_SYS(sys_mount	, 5) +	MIPS_SYS(sys_umount	, 1) +	MIPS_SYS(sys_setuid	, 1) +	MIPS_SYS(sys_getuid	, 0) +	MIPS_SYS(sys_stime	, 1)	/* 4025 */ +	MIPS_SYS(sys_ptrace	, 4) +	MIPS_SYS(sys_alarm	, 1) +	MIPS_SYS(sys_ni_syscall	, 0)	/* was sys_fstat */ +	MIPS_SYS(sys_pause	, 0) +	MIPS_SYS(sys_utime	, 2)	/* 4030 */ +	MIPS_SYS(sys_ni_syscall	, 0) +	MIPS_SYS(sys_ni_syscall	, 0) +	MIPS_SYS(sys_access	, 2) +	MIPS_SYS(sys_nice	, 1) +	MIPS_SYS(sys_ni_syscall	, 0)	/* 4035 */ +	MIPS_SYS(sys_sync	, 0) +	MIPS_SYS(sys_kill	, 2) +	MIPS_SYS(sys_rename	, 2) +	MIPS_SYS(sys_mkdir	, 2) +	MIPS_SYS(sys_rmdir	, 1)	/* 4040 */ +	MIPS_SYS(sys_dup		, 1) +	MIPS_SYS(sys_pipe	, 0) +	MIPS_SYS(sys_times	, 1) +	MIPS_SYS(sys_ni_syscall	, 0) +	MIPS_SYS(sys_brk		, 1)	/* 4045 */ +	MIPS_SYS(sys_setgid	, 1) +	MIPS_SYS(sys_getgid	, 0) +	MIPS_SYS(sys_ni_syscall	, 0)	/* was signal(2) */ +	MIPS_SYS(sys_geteuid	, 0) +	MIPS_SYS(sys_getegid	, 0)	/* 4050 */ +	MIPS_SYS(sys_acct	, 0) +	MIPS_SYS(sys_umount2	, 2) +	MIPS_SYS(sys_ni_syscall	, 0) +	MIPS_SYS(sys_ioctl	, 3) +	MIPS_SYS(sys_fcntl	, 3)	/* 4055 */ +	MIPS_SYS(sys_ni_syscall	, 2) +	MIPS_SYS(sys_setpgid	, 2) +	MIPS_SYS(sys_ni_syscall	, 0) +	MIPS_SYS(sys_olduname	, 1) +	MIPS_SYS(sys_umask	, 1)	/* 4060 */ +	MIPS_SYS(sys_chroot	, 1) +	MIPS_SYS(sys_ustat	, 2) +	MIPS_SYS(sys_dup2	, 2) +	MIPS_SYS(sys_getppid	, 0) +	MIPS_SYS(sys_getpgrp	, 0)	/* 4065 */ +	MIPS_SYS(sys_setsid	, 0) +	MIPS_SYS(sys_sigaction	, 3) +	MIPS_SYS(sys_sgetmask	, 0) +	MIPS_SYS(sys_ssetmask	, 1) +	MIPS_SYS(sys_setreuid	, 2)	/* 4070 */ +	MIPS_SYS(sys_setregid	, 2) +	MIPS_SYS(sys_sigsuspend	, 0) +	MIPS_SYS(sys_sigpending	, 1) +	MIPS_SYS(sys_sethostname	, 2) +	MIPS_SYS(sys_setrlimit	, 2)	/* 4075 */ +	MIPS_SYS(sys_getrlimit	, 2) +	MIPS_SYS(sys_getrusage	, 2) +	MIPS_SYS(sys_gettimeofday, 2) +	MIPS_SYS(sys_settimeofday, 2) +	MIPS_SYS(sys_getgroups	, 2)	/* 4080 */ +	MIPS_SYS(sys_setgroups	, 2) +	MIPS_SYS(sys_ni_syscall	, 0)	/* old_select */ +	MIPS_SYS(sys_symlink	, 2) +	MIPS_SYS(sys_ni_syscall	, 0)	/* was sys_lstat */ +	MIPS_SYS(sys_readlink	, 3)	/* 4085 */ +	MIPS_SYS(sys_uselib	, 1) +	MIPS_SYS(sys_swapon	, 2) +	MIPS_SYS(sys_reboot	, 3) +	MIPS_SYS(old_readdir	, 3) +	MIPS_SYS(old_mmap	, 6)	/* 4090 */ +	MIPS_SYS(sys_munmap	, 2) +	MIPS_SYS(sys_truncate	, 2) +	MIPS_SYS(sys_ftruncate	, 2) +	MIPS_SYS(sys_fchmod	, 2) +	MIPS_SYS(sys_fchown	, 3)	/* 4095 */ +	MIPS_SYS(sys_getpriority	, 2) +	MIPS_SYS(sys_setpriority	, 3) +	MIPS_SYS(sys_ni_syscall	, 0) +	MIPS_SYS(sys_statfs	, 2) +	MIPS_SYS(sys_fstatfs	, 2)	/* 4100 */ +	MIPS_SYS(sys_ni_syscall	, 0)	/* was ioperm(2) */ +	MIPS_SYS(sys_socketcall	, 2) +	MIPS_SYS(sys_syslog	, 3) +	MIPS_SYS(sys_setitimer	, 3) +	MIPS_SYS(sys_getitimer	, 2)	/* 4105 */ +	MIPS_SYS(sys_newstat	, 2) +	MIPS_SYS(sys_newlstat	, 2) +	MIPS_SYS(sys_newfstat	, 2) +	MIPS_SYS(sys_uname	, 1) +	MIPS_SYS(sys_ni_syscall	, 0)	/* 4110 was iopl(2) */ +	MIPS_SYS(sys_vhangup	, 0) +	MIPS_SYS(sys_ni_syscall	, 0)	/* was sys_idle() */ +	MIPS_SYS(sys_ni_syscall	, 0)	/* was sys_vm86 */ +	MIPS_SYS(sys_wait4	, 4) +	MIPS_SYS(sys_swapoff	, 1)	/* 4115 */ +	MIPS_SYS(sys_sysinfo	, 1) +	MIPS_SYS(sys_ipc		, 6) +	MIPS_SYS(sys_fsync	, 1) +	MIPS_SYS(sys_sigreturn	, 0) +	MIPS_SYS(sys_clone	, 6)	/* 4120 */ +	MIPS_SYS(sys_setdomainname, 2) +	MIPS_SYS(sys_newuname	, 1) +	MIPS_SYS(sys_ni_syscall	, 0)	/* sys_modify_ldt */ +	MIPS_SYS(sys_adjtimex	, 1) +	MIPS_SYS(sys_mprotect	, 3)	/* 4125 */ +	MIPS_SYS(sys_sigprocmask	, 3) +	MIPS_SYS(sys_ni_syscall	, 0)	/* was create_module */ +	MIPS_SYS(sys_init_module	, 5) +	MIPS_SYS(sys_delete_module, 1) +	MIPS_SYS(sys_ni_syscall	, 0)	/* 4130	was get_kernel_syms */ +	MIPS_SYS(sys_quotactl	, 0) +	MIPS_SYS(sys_getpgid	, 1) +	MIPS_SYS(sys_fchdir	, 1) +	MIPS_SYS(sys_bdflush	, 2) +	MIPS_SYS(sys_sysfs	, 3)	/* 4135 */ +	MIPS_SYS(sys_personality	, 1) +	MIPS_SYS(sys_ni_syscall	, 0)	/* for afs_syscall */ +	MIPS_SYS(sys_setfsuid	, 1) +	MIPS_SYS(sys_setfsgid	, 1) +	MIPS_SYS(sys_llseek	, 5)	/* 4140 */ +	MIPS_SYS(sys_getdents	, 3) +	MIPS_SYS(sys_select	, 5) +	MIPS_SYS(sys_flock	, 2) +	MIPS_SYS(sys_msync	, 3) +	MIPS_SYS(sys_readv	, 3)	/* 4145 */ +	MIPS_SYS(sys_writev	, 3) +	MIPS_SYS(sys_cacheflush	, 3) +	MIPS_SYS(sys_cachectl	, 3) +	MIPS_SYS(sys_sysmips	, 4) +	MIPS_SYS(sys_ni_syscall	, 0)	/* 4150 */ +	MIPS_SYS(sys_getsid	, 1) +	MIPS_SYS(sys_fdatasync	, 0) +	MIPS_SYS(sys_sysctl	, 1) +	MIPS_SYS(sys_mlock	, 2) +	MIPS_SYS(sys_munlock	, 2)	/* 4155 */ +	MIPS_SYS(sys_mlockall	, 1) +	MIPS_SYS(sys_munlockall	, 0) +	MIPS_SYS(sys_sched_setparam, 2) +	MIPS_SYS(sys_sched_getparam, 2) +	MIPS_SYS(sys_sched_setscheduler, 3)	/* 4160 */ +	MIPS_SYS(sys_sched_getscheduler, 1) +	MIPS_SYS(sys_sched_yield	, 0) +	MIPS_SYS(sys_sched_get_priority_max, 1) +	MIPS_SYS(sys_sched_get_priority_min, 1) +	MIPS_SYS(sys_sched_rr_get_interval, 2)	/* 4165 */ +	MIPS_SYS(sys_nanosleep,	2) +	MIPS_SYS(sys_mremap	, 5) +	MIPS_SYS(sys_accept	, 3) +	MIPS_SYS(sys_bind	, 3) +	MIPS_SYS(sys_connect	, 3)	/* 4170 */ +	MIPS_SYS(sys_getpeername	, 3) +	MIPS_SYS(sys_getsockname	, 3) +	MIPS_SYS(sys_getsockopt	, 5) +	MIPS_SYS(sys_listen	, 2) +	MIPS_SYS(sys_recv	, 4)	/* 4175 */ +	MIPS_SYS(sys_recvfrom	, 6) +	MIPS_SYS(sys_recvmsg	, 3) +	MIPS_SYS(sys_send	, 4) +	MIPS_SYS(sys_sendmsg	, 3) +	MIPS_SYS(sys_sendto	, 6)	/* 4180 */ +	MIPS_SYS(sys_setsockopt	, 5) +	MIPS_SYS(sys_shutdown	, 2) +	MIPS_SYS(sys_socket	, 3) +	MIPS_SYS(sys_socketpair	, 4) +	MIPS_SYS(sys_setresuid	, 3)	/* 4185 */ +	MIPS_SYS(sys_getresuid	, 3) +	MIPS_SYS(sys_ni_syscall	, 0)	/* was sys_query_module */ +	MIPS_SYS(sys_poll	, 3) +	MIPS_SYS(sys_nfsservctl	, 3) +	MIPS_SYS(sys_setresgid	, 3)	/* 4190 */ +	MIPS_SYS(sys_getresgid	, 3) +	MIPS_SYS(sys_prctl	, 5) +	MIPS_SYS(sys_rt_sigreturn, 0) +	MIPS_SYS(sys_rt_sigaction, 4) +	MIPS_SYS(sys_rt_sigprocmask, 4)	/* 4195 */ +	MIPS_SYS(sys_rt_sigpending, 2) +	MIPS_SYS(sys_rt_sigtimedwait, 4) +	MIPS_SYS(sys_rt_sigqueueinfo, 3) +	MIPS_SYS(sys_rt_sigsuspend, 0) +	MIPS_SYS(sys_pread64	, 6)	/* 4200 */ +	MIPS_SYS(sys_pwrite64	, 6) +	MIPS_SYS(sys_chown	, 3) +	MIPS_SYS(sys_getcwd	, 2) +	MIPS_SYS(sys_capget	, 2) +	MIPS_SYS(sys_capset	, 2)	/* 4205 */ +	MIPS_SYS(sys_sigaltstack	, 2) +	MIPS_SYS(sys_sendfile	, 4) +	MIPS_SYS(sys_ni_syscall	, 0) +	MIPS_SYS(sys_ni_syscall	, 0) +	MIPS_SYS(sys_mmap2	, 6)	/* 4210 */ +	MIPS_SYS(sys_truncate64	, 4) +	MIPS_SYS(sys_ftruncate64	, 4) +	MIPS_SYS(sys_stat64	, 2) +	MIPS_SYS(sys_lstat64	, 2) +	MIPS_SYS(sys_fstat64	, 2)	/* 4215 */ +	MIPS_SYS(sys_pivot_root	, 2) +	MIPS_SYS(sys_mincore	, 3) +	MIPS_SYS(sys_madvise	, 3) +	MIPS_SYS(sys_getdents64	, 3) +	MIPS_SYS(sys_fcntl64	, 3)	/* 4220 */ +	MIPS_SYS(sys_ni_syscall	, 0) +	MIPS_SYS(sys_gettid	, 0) +	MIPS_SYS(sys_readahead	, 5) +	MIPS_SYS(sys_setxattr	, 5) +	MIPS_SYS(sys_lsetxattr	, 5)	/* 4225 */ +	MIPS_SYS(sys_fsetxattr	, 5) +	MIPS_SYS(sys_getxattr	, 4) +	MIPS_SYS(sys_lgetxattr	, 4) +	MIPS_SYS(sys_fgetxattr	, 4) +	MIPS_SYS(sys_listxattr	, 3)	/* 4230 */ +	MIPS_SYS(sys_llistxattr	, 3) +	MIPS_SYS(sys_flistxattr	, 3) +	MIPS_SYS(sys_removexattr	, 2) +	MIPS_SYS(sys_lremovexattr, 2) +	MIPS_SYS(sys_fremovexattr, 2)	/* 4235 */ +	MIPS_SYS(sys_tkill	, 2) +	MIPS_SYS(sys_sendfile64	, 5) +	MIPS_SYS(sys_futex	, 6) +	MIPS_SYS(sys_sched_setaffinity, 3) +	MIPS_SYS(sys_sched_getaffinity, 3)	/* 4240 */ +	MIPS_SYS(sys_io_setup	, 2) +	MIPS_SYS(sys_io_destroy	, 1) +	MIPS_SYS(sys_io_getevents, 5) +	MIPS_SYS(sys_io_submit	, 3) +	MIPS_SYS(sys_io_cancel	, 3)	/* 4245 */ +	MIPS_SYS(sys_exit_group	, 1) +	MIPS_SYS(sys_lookup_dcookie, 3) +	MIPS_SYS(sys_epoll_create, 1) +	MIPS_SYS(sys_epoll_ctl	, 4) +	MIPS_SYS(sys_epoll_wait	, 3)	/* 4250 */ +	MIPS_SYS(sys_remap_file_pages, 5) +	MIPS_SYS(sys_set_tid_address, 1) +	MIPS_SYS(sys_restart_syscall, 0) +	MIPS_SYS(sys_fadvise64_64, 7) +	MIPS_SYS(sys_statfs64	, 3)	/* 4255 */ +	MIPS_SYS(sys_fstatfs64	, 2) +	MIPS_SYS(sys_timer_create, 3) +	MIPS_SYS(sys_timer_settime, 4) +	MIPS_SYS(sys_timer_gettime, 2) +	MIPS_SYS(sys_timer_getoverrun, 1)	/* 4260 */ +	MIPS_SYS(sys_timer_delete, 1) +	MIPS_SYS(sys_clock_settime, 2) +	MIPS_SYS(sys_clock_gettime, 2) +	MIPS_SYS(sys_clock_getres, 2) +	MIPS_SYS(sys_clock_nanosleep, 4)	/* 4265 */ +	MIPS_SYS(sys_tgkill	, 3) +	MIPS_SYS(sys_utimes	, 2) +	MIPS_SYS(sys_mbind	, 4) +	MIPS_SYS(sys_ni_syscall	, 0)	/* sys_get_mempolicy */ +	MIPS_SYS(sys_ni_syscall	, 0)	/* 4270 sys_set_mempolicy */ +	MIPS_SYS(sys_mq_open	, 4) +	MIPS_SYS(sys_mq_unlink	, 1) +	MIPS_SYS(sys_mq_timedsend, 5) +	MIPS_SYS(sys_mq_timedreceive, 5) +	MIPS_SYS(sys_mq_notify	, 2)	/* 4275 */ +	MIPS_SYS(sys_mq_getsetattr, 3) +	MIPS_SYS(sys_ni_syscall	, 0)	/* sys_vserver */ +	MIPS_SYS(sys_waitid	, 4) +	MIPS_SYS(sys_ni_syscall	, 0)	/* available, was setaltroot */ +	MIPS_SYS(sys_add_key	, 5) +	MIPS_SYS(sys_request_key, 4) +	MIPS_SYS(sys_keyctl	, 5) +	MIPS_SYS(sys_set_thread_area, 1) +	MIPS_SYS(sys_inotify_init, 0) +	MIPS_SYS(sys_inotify_add_watch, 3) /* 4285 */ +	MIPS_SYS(sys_inotify_rm_watch, 2) +	MIPS_SYS(sys_migrate_pages, 4) +	MIPS_SYS(sys_openat, 4) +	MIPS_SYS(sys_mkdirat, 3) +	MIPS_SYS(sys_mknodat, 4)	/* 4290 */ +	MIPS_SYS(sys_fchownat, 5) +	MIPS_SYS(sys_futimesat, 3) +	MIPS_SYS(sys_fstatat64, 4) +	MIPS_SYS(sys_unlinkat, 3) +	MIPS_SYS(sys_renameat, 4)	/* 4295 */ +	MIPS_SYS(sys_linkat, 5) +	MIPS_SYS(sys_symlinkat, 3) +	MIPS_SYS(sys_readlinkat, 4) +	MIPS_SYS(sys_fchmodat, 3) +	MIPS_SYS(sys_faccessat, 3)	/* 4300 */ +	MIPS_SYS(sys_pselect6, 6) +	MIPS_SYS(sys_ppoll, 5) +	MIPS_SYS(sys_unshare, 1) +	MIPS_SYS(sys_splice, 6) +	MIPS_SYS(sys_sync_file_range, 7) /* 4305 */ +	MIPS_SYS(sys_tee, 4) +	MIPS_SYS(sys_vmsplice, 4) +	MIPS_SYS(sys_move_pages, 6) +	MIPS_SYS(sys_set_robust_list, 2) +	MIPS_SYS(sys_get_robust_list, 3) /* 4310 */ +	MIPS_SYS(sys_kexec_load, 4) +	MIPS_SYS(sys_getcpu, 3) +	MIPS_SYS(sys_epoll_pwait, 6) +	MIPS_SYS(sys_ioprio_set, 3) +	MIPS_SYS(sys_ioprio_get, 2) +        MIPS_SYS(sys_utimensat, 4) +        MIPS_SYS(sys_signalfd, 3) +        MIPS_SYS(sys_ni_syscall, 0)     /* was timerfd */ +        MIPS_SYS(sys_eventfd, 1) +        MIPS_SYS(sys_fallocate, 6)      /* 4320 */ +        MIPS_SYS(sys_timerfd_create, 2) +        MIPS_SYS(sys_timerfd_gettime, 2) +        MIPS_SYS(sys_timerfd_settime, 4) +        MIPS_SYS(sys_signalfd4, 4) +        MIPS_SYS(sys_eventfd2, 2)       /* 4325 */ +        MIPS_SYS(sys_epoll_create1, 1) +        MIPS_SYS(sys_dup3, 3) +        MIPS_SYS(sys_pipe2, 2) +        MIPS_SYS(sys_inotify_init1, 1) +        MIPS_SYS(sys_preadv, 6)         /* 4330 */ +        MIPS_SYS(sys_pwritev, 6) +        MIPS_SYS(sys_rt_tgsigqueueinfo, 4) +        MIPS_SYS(sys_perf_event_open, 5) +        MIPS_SYS(sys_accept4, 4) +        MIPS_SYS(sys_recvmmsg, 5)       /* 4335 */ +        MIPS_SYS(sys_fanotify_init, 2) +        MIPS_SYS(sys_fanotify_mark, 6) +        MIPS_SYS(sys_prlimit64, 4) +        MIPS_SYS(sys_name_to_handle_at, 5) +        MIPS_SYS(sys_open_by_handle_at, 3) /* 4340 */ +        MIPS_SYS(sys_clock_adjtime, 2) +        MIPS_SYS(sys_syncfs, 1) +}; +#  undef MIPS_SYS +# endif /* O32 */ + +static int do_store_exclusive(CPUMIPSState *env) +{ +    target_ulong addr; +    target_ulong page_addr; +    target_ulong val; +    int flags; +    int segv = 0; +    int reg; +    int d; + +    addr = env->lladdr; +    page_addr = addr & TARGET_PAGE_MASK; +    start_exclusive(); +    mmap_lock(); +    flags = page_get_flags(page_addr); +    if ((flags & PAGE_READ) == 0) { +        segv = 1; +    } else { +        reg = env->llreg & 0x1f; +        d = (env->llreg & 0x20) != 0; +        if (d) { +            segv = get_user_s64(val, addr); +        } else { +            segv = get_user_s32(val, addr); +        } +        if (!segv) { +            if (val != env->llval) { +                env->active_tc.gpr[reg] = 0; +            } else { +                if (d) { +                    segv = put_user_u64(env->llnewval, addr); +                } else { +                    segv = put_user_u32(env->llnewval, addr); +                } +                if (!segv) { +                    env->active_tc.gpr[reg] = 1; +                } +            } +        } +    } +    env->lladdr = -1; +    if (!segv) { +        env->active_tc.PC += 4; +    } +    mmap_unlock(); +    end_exclusive(); +    return segv; +} + +/* Break codes */ +enum { +    BRK_OVERFLOW = 6, +    BRK_DIVZERO = 7 +}; + +static int do_break(CPUMIPSState *env, target_siginfo_t *info, +                    unsigned int code) +{ +    int ret = -1; + +    switch (code) { +    case BRK_OVERFLOW: +    case BRK_DIVZERO: +        info->si_signo = TARGET_SIGFPE; +        info->si_errno = 0; +        info->si_code = (code == BRK_OVERFLOW) ? FPE_INTOVF : FPE_INTDIV; +        queue_signal(env, info->si_signo, &*info); +        ret = 0; +        break; +    default: +        info->si_signo = TARGET_SIGTRAP; +        info->si_errno = 0; +        queue_signal(env, info->si_signo, &*info); +        ret = 0; +        break; +    } + +    return ret; +} + +void cpu_loop(CPUMIPSState *env) +{ +    CPUState *cs = CPU(mips_env_get_cpu(env)); +    target_siginfo_t info; +    int trapnr; +    abi_long ret; +# ifdef TARGET_ABI_MIPSO32 +    unsigned int syscall_num; +# endif + +    for(;;) { +        cpu_exec_start(cs); +        trapnr = cpu_mips_exec(cs); +        cpu_exec_end(cs); +        switch(trapnr) { +        case EXCP_SYSCALL: +            env->active_tc.PC += 4; +# ifdef TARGET_ABI_MIPSO32 +            syscall_num = env->active_tc.gpr[2] - 4000; +            if (syscall_num >= sizeof(mips_syscall_args)) { +                ret = -TARGET_ENOSYS; +            } else { +                int nb_args; +                abi_ulong sp_reg; +                abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0; + +                nb_args = mips_syscall_args[syscall_num]; +                sp_reg = env->active_tc.gpr[29]; +                switch (nb_args) { +                /* these arguments are taken from the stack */ +                case 8: +                    if ((ret = get_user_ual(arg8, sp_reg + 28)) != 0) { +                        goto done_syscall; +                    } +                case 7: +                    if ((ret = get_user_ual(arg7, sp_reg + 24)) != 0) { +                        goto done_syscall; +                    } +                case 6: +                    if ((ret = get_user_ual(arg6, sp_reg + 20)) != 0) { +                        goto done_syscall; +                    } +                case 5: +                    if ((ret = get_user_ual(arg5, sp_reg + 16)) != 0) { +                        goto done_syscall; +                    } +                default: +                    break; +                } +                ret = do_syscall(env, env->active_tc.gpr[2], +                                 env->active_tc.gpr[4], +                                 env->active_tc.gpr[5], +                                 env->active_tc.gpr[6], +                                 env->active_tc.gpr[7], +                                 arg5, arg6, arg7, arg8); +            } +done_syscall: +# else +            ret = do_syscall(env, env->active_tc.gpr[2], +                             env->active_tc.gpr[4], env->active_tc.gpr[5], +                             env->active_tc.gpr[6], env->active_tc.gpr[7], +                             env->active_tc.gpr[8], env->active_tc.gpr[9], +                             env->active_tc.gpr[10], env->active_tc.gpr[11]); +# endif /* O32 */ +            if (ret == -TARGET_QEMU_ESIGRETURN) { +                /* Returning from a successful sigreturn syscall. +                   Avoid clobbering register state.  */ +                break; +            } +            if ((abi_ulong)ret >= (abi_ulong)-1133) { +                env->active_tc.gpr[7] = 1; /* error flag */ +                ret = -ret; +            } else { +                env->active_tc.gpr[7] = 0; /* error flag */ +            } +            env->active_tc.gpr[2] = ret; +            break; +        case EXCP_TLBL: +        case EXCP_TLBS: +        case EXCP_AdEL: +        case EXCP_AdES: +            info.si_signo = TARGET_SIGSEGV; +            info.si_errno = 0; +            /* XXX: check env->error_code */ +            info.si_code = TARGET_SEGV_MAPERR; +            info._sifields._sigfault._addr = env->CP0_BadVAddr; +            queue_signal(env, info.si_signo, &info); +            break; +        case EXCP_CpU: +        case EXCP_RI: +            info.si_signo = TARGET_SIGILL; +            info.si_errno = 0; +            info.si_code = 0; +            queue_signal(env, info.si_signo, &info); +            break; +        case EXCP_INTERRUPT: +            /* just indicate that signals should be handled asap */ +            break; +        case EXCP_DEBUG: +            { +                int sig; + +                sig = gdb_handlesig(cs, TARGET_SIGTRAP); +                if (sig) +                  { +                    info.si_signo = sig; +                    info.si_errno = 0; +                    info.si_code = TARGET_TRAP_BRKPT; +                    queue_signal(env, info.si_signo, &info); +                  } +            } +            break; +        case EXCP_SC: +            if (do_store_exclusive(env)) { +                info.si_signo = TARGET_SIGSEGV; +                info.si_errno = 0; +                info.si_code = TARGET_SEGV_MAPERR; +                info._sifields._sigfault._addr = env->active_tc.PC; +                queue_signal(env, info.si_signo, &info); +            } +            break; +        case EXCP_DSPDIS: +            info.si_signo = TARGET_SIGILL; +            info.si_errno = 0; +            info.si_code = TARGET_ILL_ILLOPC; +            queue_signal(env, info.si_signo, &info); +            break; +        /* The code below was inspired by the MIPS Linux kernel trap +         * handling code in arch/mips/kernel/traps.c. +         */ +        case EXCP_BREAK: +            { +                abi_ulong trap_instr; +                unsigned int code; + +                if (env->hflags & MIPS_HFLAG_M16) { +                    if (env->insn_flags & ASE_MICROMIPS) { +                        /* microMIPS mode */ +                        ret = get_user_u16(trap_instr, env->active_tc.PC); +                        if (ret != 0) { +                            goto error; +                        } + +                        if ((trap_instr >> 10) == 0x11) { +                            /* 16-bit instruction */ +                            code = trap_instr & 0xf; +                        } else { +                            /* 32-bit instruction */ +                            abi_ulong instr_lo; + +                            ret = get_user_u16(instr_lo, +                                               env->active_tc.PC + 2); +                            if (ret != 0) { +                                goto error; +                            } +                            trap_instr = (trap_instr << 16) | instr_lo; +                            code = ((trap_instr >> 6) & ((1 << 20) - 1)); +                            /* Unfortunately, microMIPS also suffers from +                               the old assembler bug...  */ +                            if (code >= (1 << 10)) { +                                code >>= 10; +                            } +                        } +                    } else { +                        /* MIPS16e mode */ +                        ret = get_user_u16(trap_instr, env->active_tc.PC); +                        if (ret != 0) { +                            goto error; +                        } +                        code = (trap_instr >> 6) & 0x3f; +                    } +                } else { +                    ret = get_user_u32(trap_instr, env->active_tc.PC); +                    if (ret != 0) { +                        goto error; +                    } + +                    /* As described in the original Linux kernel code, the +                     * below checks on 'code' are to work around an old +                     * assembly bug. +                     */ +                    code = ((trap_instr >> 6) & ((1 << 20) - 1)); +                    if (code >= (1 << 10)) { +                        code >>= 10; +                    } +                } + +                if (do_break(env, &info, code) != 0) { +                    goto error; +                } +            } +            break; +        case EXCP_TRAP: +            { +                abi_ulong trap_instr; +                unsigned int code = 0; + +                if (env->hflags & MIPS_HFLAG_M16) { +                    /* microMIPS mode */ +                    abi_ulong instr[2]; + +                    ret = get_user_u16(instr[0], env->active_tc.PC) || +                          get_user_u16(instr[1], env->active_tc.PC + 2); + +                    trap_instr = (instr[0] << 16) | instr[1]; +                } else { +                    ret = get_user_u32(trap_instr, env->active_tc.PC); +                } + +                if (ret != 0) { +                    goto error; +                } + +                /* The immediate versions don't provide a code.  */ +                if (!(trap_instr & 0xFC000000)) { +                    if (env->hflags & MIPS_HFLAG_M16) { +                        /* microMIPS mode */ +                        code = ((trap_instr >> 12) & ((1 << 4) - 1)); +                    } else { +                        code = ((trap_instr >> 6) & ((1 << 10) - 1)); +                    } +                } + +                if (do_break(env, &info, code) != 0) { +                    goto error; +                } +            } +            break; +        default: +error: +            fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", +                    trapnr); +            cpu_dump_state(cs, stderr, fprintf, 0); +            abort(); +        } +        process_pending_signals(env); +    } +} +#endif + +#ifdef TARGET_OPENRISC + +void cpu_loop(CPUOpenRISCState *env) +{ +    CPUState *cs = CPU(openrisc_env_get_cpu(env)); +    int trapnr, gdbsig; + +    for (;;) { +        cpu_exec_start(cs); +        trapnr = cpu_openrisc_exec(cs); +        cpu_exec_end(cs); +        gdbsig = 0; + +        switch (trapnr) { +        case EXCP_RESET: +            qemu_log("\nReset request, exit, pc is %#x\n", env->pc); +            exit(1); +            break; +        case EXCP_BUSERR: +            qemu_log("\nBus error, exit, pc is %#x\n", env->pc); +            gdbsig = TARGET_SIGBUS; +            break; +        case EXCP_DPF: +        case EXCP_IPF: +            cpu_dump_state(cs, stderr, fprintf, 0); +            gdbsig = TARGET_SIGSEGV; +            break; +        case EXCP_TICK: +            qemu_log("\nTick time interrupt pc is %#x\n", env->pc); +            break; +        case EXCP_ALIGN: +            qemu_log("\nAlignment pc is %#x\n", env->pc); +            gdbsig = TARGET_SIGBUS; +            break; +        case EXCP_ILLEGAL: +            qemu_log("\nIllegal instructionpc is %#x\n", env->pc); +            gdbsig = TARGET_SIGILL; +            break; +        case EXCP_INT: +            qemu_log("\nExternal interruptpc is %#x\n", env->pc); +            break; +        case EXCP_DTLBMISS: +        case EXCP_ITLBMISS: +            qemu_log("\nTLB miss\n"); +            break; +        case EXCP_RANGE: +            qemu_log("\nRange\n"); +            gdbsig = TARGET_SIGSEGV; +            break; +        case EXCP_SYSCALL: +            env->pc += 4;   /* 0xc00; */ +            env->gpr[11] = do_syscall(env, +                                      env->gpr[11], /* return value       */ +                                      env->gpr[3],  /* r3 - r7 are params */ +                                      env->gpr[4], +                                      env->gpr[5], +                                      env->gpr[6], +                                      env->gpr[7], +                                      env->gpr[8], 0, 0); +            break; +        case EXCP_FPE: +            qemu_log("\nFloating point error\n"); +            break; +        case EXCP_TRAP: +            qemu_log("\nTrap\n"); +            gdbsig = TARGET_SIGTRAP; +            break; +        case EXCP_NR: +            qemu_log("\nNR\n"); +            break; +        default: +            qemu_log("\nqemu: unhandled CPU exception %#x - aborting\n", +                     trapnr); +            cpu_dump_state(cs, stderr, fprintf, 0); +            gdbsig = TARGET_SIGILL; +            break; +        } +        if (gdbsig) { +            gdb_handlesig(cs, gdbsig); +            if (gdbsig != TARGET_SIGTRAP) { +                exit(1); +            } +        } + +        process_pending_signals(env); +    } +} + +#endif /* TARGET_OPENRISC */ + +#ifdef TARGET_SH4 +void cpu_loop(CPUSH4State *env) +{ +    CPUState *cs = CPU(sh_env_get_cpu(env)); +    int trapnr, ret; +    target_siginfo_t info; + +    while (1) { +        cpu_exec_start(cs); +        trapnr = cpu_sh4_exec(cs); +        cpu_exec_end(cs); + +        switch (trapnr) { +        case 0x160: +            env->pc += 2; +            ret = do_syscall(env, +                             env->gregs[3], +                             env->gregs[4], +                             env->gregs[5], +                             env->gregs[6], +                             env->gregs[7], +                             env->gregs[0], +                             env->gregs[1], +                             0, 0); +            env->gregs[0] = ret; +            break; +        case EXCP_INTERRUPT: +            /* just indicate that signals should be handled asap */ +            break; +        case EXCP_DEBUG: +            { +                int sig; + +                sig = gdb_handlesig(cs, TARGET_SIGTRAP); +                if (sig) +                  { +                    info.si_signo = sig; +                    info.si_errno = 0; +                    info.si_code = TARGET_TRAP_BRKPT; +                    queue_signal(env, info.si_signo, &info); +                  } +            } +            break; +	case 0xa0: +	case 0xc0: +            info.si_signo = TARGET_SIGSEGV; +            info.si_errno = 0; +            info.si_code = TARGET_SEGV_MAPERR; +            info._sifields._sigfault._addr = env->tea; +            queue_signal(env, info.si_signo, &info); +	    break; + +        default: +            printf ("Unhandled trap: 0x%x\n", trapnr); +            cpu_dump_state(cs, stderr, fprintf, 0); +            exit (1); +        } +        process_pending_signals (env); +    } +} +#endif + +#ifdef TARGET_CRIS +void cpu_loop(CPUCRISState *env) +{ +    CPUState *cs = CPU(cris_env_get_cpu(env)); +    int trapnr, ret; +    target_siginfo_t info; +     +    while (1) { +        cpu_exec_start(cs); +        trapnr = cpu_cris_exec(cs); +        cpu_exec_end(cs); +        switch (trapnr) { +        case 0xaa: +            { +                info.si_signo = TARGET_SIGSEGV; +                info.si_errno = 0; +                /* XXX: check env->error_code */ +                info.si_code = TARGET_SEGV_MAPERR; +                info._sifields._sigfault._addr = env->pregs[PR_EDA]; +                queue_signal(env, info.si_signo, &info); +            } +            break; +	case EXCP_INTERRUPT: +	  /* just indicate that signals should be handled asap */ +	  break; +        case EXCP_BREAK: +            ret = do_syscall(env,  +                             env->regs[9],  +                             env->regs[10],  +                             env->regs[11],  +                             env->regs[12],  +                             env->regs[13],  +                             env->pregs[7],  +                             env->pregs[11], +                             0, 0); +            env->regs[10] = ret; +            break; +        case EXCP_DEBUG: +            { +                int sig; + +                sig = gdb_handlesig(cs, TARGET_SIGTRAP); +                if (sig) +                  { +                    info.si_signo = sig; +                    info.si_errno = 0; +                    info.si_code = TARGET_TRAP_BRKPT; +                    queue_signal(env, info.si_signo, &info); +                  } +            } +            break; +        default: +            printf ("Unhandled trap: 0x%x\n", trapnr); +            cpu_dump_state(cs, stderr, fprintf, 0); +            exit (1); +        } +        process_pending_signals (env); +    } +} +#endif + +#ifdef TARGET_MICROBLAZE +void cpu_loop(CPUMBState *env) +{ +    CPUState *cs = CPU(mb_env_get_cpu(env)); +    int trapnr, ret; +    target_siginfo_t info; +     +    while (1) { +        cpu_exec_start(cs); +        trapnr = cpu_mb_exec(cs); +        cpu_exec_end(cs); +        switch (trapnr) { +        case 0xaa: +            { +                info.si_signo = TARGET_SIGSEGV; +                info.si_errno = 0; +                /* XXX: check env->error_code */ +                info.si_code = TARGET_SEGV_MAPERR; +                info._sifields._sigfault._addr = 0; +                queue_signal(env, info.si_signo, &info); +            } +            break; +	case EXCP_INTERRUPT: +	  /* just indicate that signals should be handled asap */ +	  break; +        case EXCP_BREAK: +            /* Return address is 4 bytes after the call.  */ +            env->regs[14] += 4; +            env->sregs[SR_PC] = env->regs[14]; +            ret = do_syscall(env,  +                             env->regs[12],  +                             env->regs[5],  +                             env->regs[6],  +                             env->regs[7],  +                             env->regs[8],  +                             env->regs[9],  +                             env->regs[10], +                             0, 0); +            env->regs[3] = ret; +            break; +        case EXCP_HW_EXCP: +            env->regs[17] = env->sregs[SR_PC] + 4; +            if (env->iflags & D_FLAG) { +                env->sregs[SR_ESR] |= 1 << 12; +                env->sregs[SR_PC] -= 4; +                /* FIXME: if branch was immed, replay the imm as well.  */ +            } + +            env->iflags &= ~(IMM_FLAG | D_FLAG); + +            switch (env->sregs[SR_ESR] & 31) { +                case ESR_EC_DIVZERO: +                    info.si_signo = TARGET_SIGFPE; +                    info.si_errno = 0; +                    info.si_code = TARGET_FPE_FLTDIV; +                    info._sifields._sigfault._addr = 0; +                    queue_signal(env, info.si_signo, &info); +                    break; +                case ESR_EC_FPU: +                    info.si_signo = TARGET_SIGFPE; +                    info.si_errno = 0; +                    if (env->sregs[SR_FSR] & FSR_IO) { +                        info.si_code = TARGET_FPE_FLTINV; +                    } +                    if (env->sregs[SR_FSR] & FSR_DZ) { +                        info.si_code = TARGET_FPE_FLTDIV; +                    } +                    info._sifields._sigfault._addr = 0; +                    queue_signal(env, info.si_signo, &info); +                    break; +                default: +                    printf ("Unhandled hw-exception: 0x%x\n", +                            env->sregs[SR_ESR] & ESR_EC_MASK); +                    cpu_dump_state(cs, stderr, fprintf, 0); +                    exit (1); +                    break; +            } +            break; +        case EXCP_DEBUG: +            { +                int sig; + +                sig = gdb_handlesig(cs, TARGET_SIGTRAP); +                if (sig) +                  { +                    info.si_signo = sig; +                    info.si_errno = 0; +                    info.si_code = TARGET_TRAP_BRKPT; +                    queue_signal(env, info.si_signo, &info); +                  } +            } +            break; +        default: +            printf ("Unhandled trap: 0x%x\n", trapnr); +            cpu_dump_state(cs, stderr, fprintf, 0); +            exit (1); +        } +        process_pending_signals (env); +    } +} +#endif + +#ifdef TARGET_M68K + +void cpu_loop(CPUM68KState *env) +{ +    CPUState *cs = CPU(m68k_env_get_cpu(env)); +    int trapnr; +    unsigned int n; +    target_siginfo_t info; +    TaskState *ts = cs->opaque; + +    for(;;) { +        cpu_exec_start(cs); +        trapnr = cpu_m68k_exec(cs); +        cpu_exec_end(cs); +        switch(trapnr) { +        case EXCP_ILLEGAL: +            { +                if (ts->sim_syscalls) { +                    uint16_t nr; +                    get_user_u16(nr, env->pc + 2); +                    env->pc += 4; +                    do_m68k_simcall(env, nr); +                } else { +                    goto do_sigill; +                } +            } +            break; +        case EXCP_HALT_INSN: +            /* Semihosing syscall.  */ +            env->pc += 4; +            do_m68k_semihosting(env, env->dregs[0]); +            break; +        case EXCP_LINEA: +        case EXCP_LINEF: +        case EXCP_UNSUPPORTED: +        do_sigill: +            info.si_signo = TARGET_SIGILL; +            info.si_errno = 0; +            info.si_code = TARGET_ILL_ILLOPN; +            info._sifields._sigfault._addr = env->pc; +            queue_signal(env, info.si_signo, &info); +            break; +        case EXCP_TRAP0: +            { +                ts->sim_syscalls = 0; +                n = env->dregs[0]; +                env->pc += 2; +                env->dregs[0] = do_syscall(env, +                                          n, +                                          env->dregs[1], +                                          env->dregs[2], +                                          env->dregs[3], +                                          env->dregs[4], +                                          env->dregs[5], +                                          env->aregs[0], +                                          0, 0); +            } +            break; +        case EXCP_INTERRUPT: +            /* just indicate that signals should be handled asap */ +            break; +        case EXCP_ACCESS: +            { +                info.si_signo = TARGET_SIGSEGV; +                info.si_errno = 0; +                /* XXX: check env->error_code */ +                info.si_code = TARGET_SEGV_MAPERR; +                info._sifields._sigfault._addr = env->mmu.ar; +                queue_signal(env, info.si_signo, &info); +            } +            break; +        case EXCP_DEBUG: +            { +                int sig; + +                sig = gdb_handlesig(cs, TARGET_SIGTRAP); +                if (sig) +                  { +                    info.si_signo = sig; +                    info.si_errno = 0; +                    info.si_code = TARGET_TRAP_BRKPT; +                    queue_signal(env, info.si_signo, &info); +                  } +            } +            break; +        default: +            fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", +                    trapnr); +            cpu_dump_state(cs, stderr, fprintf, 0); +            abort(); +        } +        process_pending_signals(env); +    } +} +#endif /* TARGET_M68K */ + +#ifdef TARGET_ALPHA +static void do_store_exclusive(CPUAlphaState *env, int reg, int quad) +{ +    target_ulong addr, val, tmp; +    target_siginfo_t info; +    int ret = 0; + +    addr = env->lock_addr; +    tmp = env->lock_st_addr; +    env->lock_addr = -1; +    env->lock_st_addr = 0; + +    start_exclusive(); +    mmap_lock(); + +    if (addr == tmp) { +        if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) { +            goto do_sigsegv; +        } + +        if (val == env->lock_value) { +            tmp = env->ir[reg]; +            if (quad ? put_user_u64(tmp, addr) : put_user_u32(tmp, addr)) { +                goto do_sigsegv; +            } +            ret = 1; +        } +    } +    env->ir[reg] = ret; +    env->pc += 4; + +    mmap_unlock(); +    end_exclusive(); +    return; + + do_sigsegv: +    mmap_unlock(); +    end_exclusive(); + +    info.si_signo = TARGET_SIGSEGV; +    info.si_errno = 0; +    info.si_code = TARGET_SEGV_MAPERR; +    info._sifields._sigfault._addr = addr; +    queue_signal(env, TARGET_SIGSEGV, &info); +} + +void cpu_loop(CPUAlphaState *env) +{ +    CPUState *cs = CPU(alpha_env_get_cpu(env)); +    int trapnr; +    target_siginfo_t info; +    abi_long sysret; + +    while (1) { +        cpu_exec_start(cs); +        trapnr = cpu_alpha_exec(cs); +        cpu_exec_end(cs); + +        /* All of the traps imply a transition through PALcode, which +           implies an REI instruction has been executed.  Which means +           that the intr_flag should be cleared.  */ +        env->intr_flag = 0; + +        switch (trapnr) { +        case EXCP_RESET: +            fprintf(stderr, "Reset requested. Exit\n"); +            exit(1); +            break; +        case EXCP_MCHK: +            fprintf(stderr, "Machine check exception. Exit\n"); +            exit(1); +            break; +        case EXCP_SMP_INTERRUPT: +        case EXCP_CLK_INTERRUPT: +        case EXCP_DEV_INTERRUPT: +            fprintf(stderr, "External interrupt. Exit\n"); +            exit(1); +            break; +        case EXCP_MMFAULT: +            env->lock_addr = -1; +            info.si_signo = TARGET_SIGSEGV; +            info.si_errno = 0; +            info.si_code = (page_get_flags(env->trap_arg0) & PAGE_VALID +                            ? TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR); +            info._sifields._sigfault._addr = env->trap_arg0; +            queue_signal(env, info.si_signo, &info); +            break; +        case EXCP_UNALIGN: +            env->lock_addr = -1; +            info.si_signo = TARGET_SIGBUS; +            info.si_errno = 0; +            info.si_code = TARGET_BUS_ADRALN; +            info._sifields._sigfault._addr = env->trap_arg0; +            queue_signal(env, info.si_signo, &info); +            break; +        case EXCP_OPCDEC: +        do_sigill: +            env->lock_addr = -1; +            info.si_signo = TARGET_SIGILL; +            info.si_errno = 0; +            info.si_code = TARGET_ILL_ILLOPC; +            info._sifields._sigfault._addr = env->pc; +            queue_signal(env, info.si_signo, &info); +            break; +        case EXCP_ARITH: +            env->lock_addr = -1; +            info.si_signo = TARGET_SIGFPE; +            info.si_errno = 0; +            info.si_code = TARGET_FPE_FLTINV; +            info._sifields._sigfault._addr = env->pc; +            queue_signal(env, info.si_signo, &info); +            break; +        case EXCP_FEN: +            /* No-op.  Linux simply re-enables the FPU.  */ +            break; +        case EXCP_CALL_PAL: +            env->lock_addr = -1; +            switch (env->error_code) { +            case 0x80: +                /* BPT */ +                info.si_signo = TARGET_SIGTRAP; +                info.si_errno = 0; +                info.si_code = TARGET_TRAP_BRKPT; +                info._sifields._sigfault._addr = env->pc; +                queue_signal(env, info.si_signo, &info); +                break; +            case 0x81: +                /* BUGCHK */ +                info.si_signo = TARGET_SIGTRAP; +                info.si_errno = 0; +                info.si_code = 0; +                info._sifields._sigfault._addr = env->pc; +                queue_signal(env, info.si_signo, &info); +                break; +            case 0x83: +                /* CALLSYS */ +                trapnr = env->ir[IR_V0]; +                sysret = do_syscall(env, trapnr, +                                    env->ir[IR_A0], env->ir[IR_A1], +                                    env->ir[IR_A2], env->ir[IR_A3], +                                    env->ir[IR_A4], env->ir[IR_A5], +                                    0, 0); +                if (trapnr == TARGET_NR_sigreturn +                    || trapnr == TARGET_NR_rt_sigreturn) { +                    break; +                } +                /* Syscall writes 0 to V0 to bypass error check, similar +                   to how this is handled internal to Linux kernel. +                   (Ab)use trapnr temporarily as boolean indicating error.  */ +                trapnr = (env->ir[IR_V0] != 0 && sysret < 0); +                env->ir[IR_V0] = (trapnr ? -sysret : sysret); +                env->ir[IR_A3] = trapnr; +                break; +            case 0x86: +                /* IMB */ +                /* ??? We can probably elide the code using page_unprotect +                   that is checking for self-modifying code.  Instead we +                   could simply call tb_flush here.  Until we work out the +                   changes required to turn off the extra write protection, +                   this can be a no-op.  */ +                break; +            case 0x9E: +                /* RDUNIQUE */ +                /* Handled in the translator for usermode.  */ +                abort(); +            case 0x9F: +                /* WRUNIQUE */ +                /* Handled in the translator for usermode.  */ +                abort(); +            case 0xAA: +                /* GENTRAP */ +                info.si_signo = TARGET_SIGFPE; +                switch (env->ir[IR_A0]) { +                case TARGET_GEN_INTOVF: +                    info.si_code = TARGET_FPE_INTOVF; +                    break; +                case TARGET_GEN_INTDIV: +                    info.si_code = TARGET_FPE_INTDIV; +                    break; +                case TARGET_GEN_FLTOVF: +                    info.si_code = TARGET_FPE_FLTOVF; +                    break; +                case TARGET_GEN_FLTUND: +                    info.si_code = TARGET_FPE_FLTUND; +                    break; +                case TARGET_GEN_FLTINV: +                    info.si_code = TARGET_FPE_FLTINV; +                    break; +                case TARGET_GEN_FLTINE: +                    info.si_code = TARGET_FPE_FLTRES; +                    break; +                case TARGET_GEN_ROPRAND: +                    info.si_code = 0; +                    break; +                default: +                    info.si_signo = TARGET_SIGTRAP; +                    info.si_code = 0; +                    break; +                } +                info.si_errno = 0; +                info._sifields._sigfault._addr = env->pc; +                queue_signal(env, info.si_signo, &info); +                break; +            default: +                goto do_sigill; +            } +            break; +        case EXCP_DEBUG: +            info.si_signo = gdb_handlesig(cs, TARGET_SIGTRAP); +            if (info.si_signo) { +                env->lock_addr = -1; +                info.si_errno = 0; +                info.si_code = TARGET_TRAP_BRKPT; +                queue_signal(env, info.si_signo, &info); +            } +            break; +        case EXCP_STL_C: +        case EXCP_STQ_C: +            do_store_exclusive(env, env->error_code, trapnr - EXCP_STL_C); +            break; +        case EXCP_INTERRUPT: +            /* Just indicate that signals should be handled asap.  */ +            break; +        default: +            printf ("Unhandled trap: 0x%x\n", trapnr); +            cpu_dump_state(cs, stderr, fprintf, 0); +            exit (1); +        } +        process_pending_signals (env); +    } +} +#endif /* TARGET_ALPHA */ + +#ifdef TARGET_S390X +void cpu_loop(CPUS390XState *env) +{ +    CPUState *cs = CPU(s390_env_get_cpu(env)); +    int trapnr, n, sig; +    target_siginfo_t info; +    target_ulong addr; + +    while (1) { +        cpu_exec_start(cs); +        trapnr = cpu_s390x_exec(cs); +        cpu_exec_end(cs); +        switch (trapnr) { +        case EXCP_INTERRUPT: +            /* Just indicate that signals should be handled asap.  */ +            break; + +        case EXCP_SVC: +            n = env->int_svc_code; +            if (!n) { +                /* syscalls > 255 */ +                n = env->regs[1]; +            } +            env->psw.addr += env->int_svc_ilen; +            env->regs[2] = do_syscall(env, n, env->regs[2], env->regs[3], +                                      env->regs[4], env->regs[5], +                                      env->regs[6], env->regs[7], 0, 0); +            break; + +        case EXCP_DEBUG: +            sig = gdb_handlesig(cs, TARGET_SIGTRAP); +            if (sig) { +                n = TARGET_TRAP_BRKPT; +                goto do_signal_pc; +            } +            break; +        case EXCP_PGM: +            n = env->int_pgm_code; +            switch (n) { +            case PGM_OPERATION: +            case PGM_PRIVILEGED: +                sig = TARGET_SIGILL; +                n = TARGET_ILL_ILLOPC; +                goto do_signal_pc; +            case PGM_PROTECTION: +            case PGM_ADDRESSING: +                sig = TARGET_SIGSEGV; +                /* XXX: check env->error_code */ +                n = TARGET_SEGV_MAPERR; +                addr = env->__excp_addr; +                goto do_signal; +            case PGM_EXECUTE: +            case PGM_SPECIFICATION: +            case PGM_SPECIAL_OP: +            case PGM_OPERAND: +            do_sigill_opn: +                sig = TARGET_SIGILL; +                n = TARGET_ILL_ILLOPN; +                goto do_signal_pc; + +            case PGM_FIXPT_OVERFLOW: +                sig = TARGET_SIGFPE; +                n = TARGET_FPE_INTOVF; +                goto do_signal_pc; +            case PGM_FIXPT_DIVIDE: +                sig = TARGET_SIGFPE; +                n = TARGET_FPE_INTDIV; +                goto do_signal_pc; + +            case PGM_DATA: +                n = (env->fpc >> 8) & 0xff; +                if (n == 0xff) { +                    /* compare-and-trap */ +                    goto do_sigill_opn; +                } else { +                    /* An IEEE exception, simulated or otherwise.  */ +                    if (n & 0x80) { +                        n = TARGET_FPE_FLTINV; +                    } else if (n & 0x40) { +                        n = TARGET_FPE_FLTDIV; +                    } else if (n & 0x20) { +                        n = TARGET_FPE_FLTOVF; +                    } else if (n & 0x10) { +                        n = TARGET_FPE_FLTUND; +                    } else if (n & 0x08) { +                        n = TARGET_FPE_FLTRES; +                    } else { +                        /* ??? Quantum exception; BFP, DFP error.  */ +                        goto do_sigill_opn; +                    } +                    sig = TARGET_SIGFPE; +                    goto do_signal_pc; +                } + +            default: +                fprintf(stderr, "Unhandled program exception: %#x\n", n); +                cpu_dump_state(cs, stderr, fprintf, 0); +                exit(1); +            } +            break; + +        do_signal_pc: +            addr = env->psw.addr; +        do_signal: +            info.si_signo = sig; +            info.si_errno = 0; +            info.si_code = n; +            info._sifields._sigfault._addr = addr; +            queue_signal(env, info.si_signo, &info); +            break; + +        default: +            fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr); +            cpu_dump_state(cs, stderr, fprintf, 0); +            exit(1); +        } +        process_pending_signals (env); +    } +} + +#endif /* TARGET_S390X */ + +THREAD CPUState *thread_cpu; + +void task_settid(TaskState *ts) +{ +    if (ts->ts_tid == 0) { +        ts->ts_tid = (pid_t)syscall(SYS_gettid); +    } +} + +void stop_all_tasks(void) +{ +    /* +     * We trust that when using NPTL, start_exclusive() +     * handles thread stopping correctly. +     */ +    start_exclusive(); +} + +/* Assumes contents are already zeroed.  */ +void init_task_state(TaskState *ts) +{ +    int i; +  +    ts->used = 1; +    ts->first_free = ts->sigqueue_table; +    for (i = 0; i < MAX_SIGQUEUE_SIZE - 1; i++) { +        ts->sigqueue_table[i].next = &ts->sigqueue_table[i + 1]; +    } +    ts->sigqueue_table[i].next = NULL; +} + +CPUArchState *cpu_copy(CPUArchState *env) +{ +    CPUState *cpu = ENV_GET_CPU(env); +    CPUState *new_cpu = cpu_init(cpu_model); +    CPUArchState *new_env = new_cpu->env_ptr; +    CPUBreakpoint *bp; +    CPUWatchpoint *wp; + +    /* Reset non arch specific state */ +    cpu_reset(new_cpu); + +    memcpy(new_env, env, sizeof(CPUArchState)); + +    /* Clone all break/watchpoints. +       Note: Once we support ptrace with hw-debug register access, make sure +       BP_CPU break/watchpoints are handled correctly on clone. */ +    QTAILQ_INIT(&new_cpu->breakpoints); +    QTAILQ_INIT(&new_cpu->watchpoints); +    QTAILQ_FOREACH(bp, &cpu->breakpoints, entry) { +        cpu_breakpoint_insert(new_cpu, bp->pc, bp->flags, NULL); +    } +    QTAILQ_FOREACH(wp, &cpu->watchpoints, entry) { +        cpu_watchpoint_insert(new_cpu, wp->vaddr, wp->len, wp->flags, NULL); +    } + +    return new_env; +} + +static void handle_arg_help(const char *arg) +{ +    usage(); +} + +static void handle_arg_log(const char *arg) +{ +    int mask; + +    mask = qemu_str_to_log_mask(arg); +    if (!mask) { +        qemu_print_log_usage(stdout); +        exit(1); +    } +    qemu_set_log(mask); +} + +static void handle_arg_log_filename(const char *arg) +{ +    qemu_set_log_filename(arg); +} + +static void handle_arg_set_env(const char *arg) +{ +    char *r, *p, *token; +    r = p = strdup(arg); +    while ((token = strsep(&p, ",")) != NULL) { +        if (envlist_setenv(envlist, token) != 0) { +            usage(); +        } +    } +    free(r); +} + +static void handle_arg_unset_env(const char *arg) +{ +    char *r, *p, *token; +    r = p = strdup(arg); +    while ((token = strsep(&p, ",")) != NULL) { +        if (envlist_unsetenv(envlist, token) != 0) { +            usage(); +        } +    } +    free(r); +} + +static void handle_arg_argv0(const char *arg) +{ +    argv0 = strdup(arg); +} + +static void handle_arg_stack_size(const char *arg) +{ +    char *p; +    guest_stack_size = strtoul(arg, &p, 0); +    if (guest_stack_size == 0) { +        usage(); +    } + +    if (*p == 'M') { +        guest_stack_size *= 1024 * 1024; +    } else if (*p == 'k' || *p == 'K') { +        guest_stack_size *= 1024; +    } +} + +static void handle_arg_ld_prefix(const char *arg) +{ +    interp_prefix = strdup(arg); +} + +static void handle_arg_pagesize(const char *arg) +{ +    qemu_host_page_size = atoi(arg); +    if (qemu_host_page_size == 0 || +        (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) { +        fprintf(stderr, "page size must be a power of two\n"); +        exit(1); +    } +} + +static void handle_arg_randseed(const char *arg) +{ +    unsigned long long seed; + +    if (parse_uint_full(arg, &seed, 0) != 0 || seed > UINT_MAX) { +        fprintf(stderr, "Invalid seed number: %s\n", arg); +        exit(1); +    } +    srand(seed); +} + +static void handle_arg_gdb(const char *arg) +{ +    gdbstub_port = atoi(arg); +} + +static void handle_arg_uname(const char *arg) +{ +    qemu_uname_release = strdup(arg); +} + +static void handle_arg_cpu(const char *arg) +{ +    cpu_model = strdup(arg); +    if (cpu_model == NULL || is_help_option(cpu_model)) { +        /* XXX: implement xxx_cpu_list for targets that still miss it */ +#if defined(cpu_list) +        cpu_list(stdout, &fprintf); +#endif +        exit(1); +    } +} + +#if defined(CONFIG_USE_GUEST_BASE) +static void handle_arg_guest_base(const char *arg) +{ +    guest_base = strtol(arg, NULL, 0); +    have_guest_base = 1; +} + +static void handle_arg_reserved_va(const char *arg) +{ +    char *p; +    int shift = 0; +    reserved_va = strtoul(arg, &p, 0); +    switch (*p) { +    case 'k': +    case 'K': +        shift = 10; +        break; +    case 'M': +        shift = 20; +        break; +    case 'G': +        shift = 30; +        break; +    } +    if (shift) { +        unsigned long unshifted = reserved_va; +        p++; +        reserved_va <<= shift; +        if (((reserved_va >> shift) != unshifted) +#if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS +            || (reserved_va > (1ul << TARGET_VIRT_ADDR_SPACE_BITS)) +#endif +            ) { +            fprintf(stderr, "Reserved virtual address too big\n"); +            exit(1); +        } +    } +    if (*p) { +        fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p); +        exit(1); +    } +} +#endif + +static void handle_arg_singlestep(const char *arg) +{ +    singlestep = 1; +} + +static void handle_arg_strace(const char *arg) +{ +    do_strace = 1; +} + +static void handle_arg_version(const char *arg) +{ +    printf("qemu-" TARGET_NAME " version " QEMU_VERSION QEMU_PKGVERSION +           ", Copyright (c) 2003-2008 Fabrice Bellard\n"); +    exit(0); +} + +struct qemu_argument { +    const char *argv; +    const char *env; +    bool has_arg; +    void (*handle_opt)(const char *arg); +    const char *example; +    const char *help; +}; + +static const struct qemu_argument arg_table[] = { +    {"h",          "",                 false, handle_arg_help, +     "",           "print this help"}, +    {"g",          "QEMU_GDB",         true,  handle_arg_gdb, +     "port",       "wait gdb connection to 'port'"}, +    {"L",          "QEMU_LD_PREFIX",   true,  handle_arg_ld_prefix, +     "path",       "set the elf interpreter prefix to 'path'"}, +    {"s",          "QEMU_STACK_SIZE",  true,  handle_arg_stack_size, +     "size",       "set the stack size to 'size' bytes"}, +    {"cpu",        "QEMU_CPU",         true,  handle_arg_cpu, +     "model",      "select CPU (-cpu help for list)"}, +    {"E",          "QEMU_SET_ENV",     true,  handle_arg_set_env, +     "var=value",  "sets targets environment variable (see below)"}, +    {"U",          "QEMU_UNSET_ENV",   true,  handle_arg_unset_env, +     "var",        "unsets targets environment variable (see below)"}, +    {"0",          "QEMU_ARGV0",       true,  handle_arg_argv0, +     "argv0",      "forces target process argv[0] to be 'argv0'"}, +    {"r",          "QEMU_UNAME",       true,  handle_arg_uname, +     "uname",      "set qemu uname release string to 'uname'"}, +#if defined(CONFIG_USE_GUEST_BASE) +    {"B",          "QEMU_GUEST_BASE",  true,  handle_arg_guest_base, +     "address",    "set guest_base address to 'address'"}, +    {"R",          "QEMU_RESERVED_VA", true,  handle_arg_reserved_va, +     "size",       "reserve 'size' bytes for guest virtual address space"}, +#endif +    {"d",          "QEMU_LOG",         true,  handle_arg_log, +     "item[,...]", "enable logging of specified items " +     "(use '-d help' for a list of items)"}, +    {"D",          "QEMU_LOG_FILENAME", true, handle_arg_log_filename, +     "logfile",     "write logs to 'logfile' (default stderr)"}, +    {"p",          "QEMU_PAGESIZE",    true,  handle_arg_pagesize, +     "pagesize",   "set the host page size to 'pagesize'"}, +    {"singlestep", "QEMU_SINGLESTEP",  false, handle_arg_singlestep, +     "",           "run in singlestep mode"}, +    {"strace",     "QEMU_STRACE",      false, handle_arg_strace, +     "",           "log system calls"}, +    {"seed",       "QEMU_RAND_SEED",   true,  handle_arg_randseed, +     "",           "Seed for pseudo-random number generator"}, +    {"version",    "QEMU_VERSION",     false, handle_arg_version, +     "",           "display version information and exit"}, +    {NULL, NULL, false, NULL, NULL, NULL} +}; + +static void usage(void) +{ +    const struct qemu_argument *arginfo; +    int maxarglen; +    int maxenvlen; + +    printf("usage: qemu-" TARGET_NAME " [options] program [arguments...]\n" +           "Linux CPU emulator (compiled for " TARGET_NAME " emulation)\n" +           "\n" +           "Options and associated environment variables:\n" +           "\n"); + +    /* Calculate column widths. We must always have at least enough space +     * for the column header. +     */ +    maxarglen = strlen("Argument"); +    maxenvlen = strlen("Env-variable"); + +    for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { +        int arglen = strlen(arginfo->argv); +        if (arginfo->has_arg) { +            arglen += strlen(arginfo->example) + 1; +        } +        if (strlen(arginfo->env) > maxenvlen) { +            maxenvlen = strlen(arginfo->env); +        } +        if (arglen > maxarglen) { +            maxarglen = arglen; +        } +    } + +    printf("%-*s %-*s Description\n", maxarglen+1, "Argument", +            maxenvlen, "Env-variable"); + +    for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { +        if (arginfo->has_arg) { +            printf("-%s %-*s %-*s %s\n", arginfo->argv, +                   (int)(maxarglen - strlen(arginfo->argv) - 1), +                   arginfo->example, maxenvlen, arginfo->env, arginfo->help); +        } else { +            printf("-%-*s %-*s %s\n", maxarglen, arginfo->argv, +                    maxenvlen, arginfo->env, +                    arginfo->help); +        } +    } + +    printf("\n" +           "Defaults:\n" +           "QEMU_LD_PREFIX  = %s\n" +           "QEMU_STACK_SIZE = %ld byte\n", +           interp_prefix, +           guest_stack_size); + +    printf("\n" +           "You can use -E and -U options or the QEMU_SET_ENV and\n" +           "QEMU_UNSET_ENV environment variables to set and unset\n" +           "environment variables for the target process.\n" +           "It is possible to provide several variables by separating them\n" +           "by commas in getsubopt(3) style. Additionally it is possible to\n" +           "provide the -E and -U options multiple times.\n" +           "The following lines are equivalent:\n" +           "    -E var1=val2 -E var2=val2 -U LD_PRELOAD -U LD_DEBUG\n" +           "    -E var1=val2,var2=val2 -U LD_PRELOAD,LD_DEBUG\n" +           "    QEMU_SET_ENV=var1=val2,var2=val2 QEMU_UNSET_ENV=LD_PRELOAD,LD_DEBUG\n" +           "Note that if you provide several changes to a single variable\n" +           "the last change will stay in effect.\n"); + +    exit(1); +} + +static int parse_args(int argc, char **argv) +{ +    const char *r; +    int optind; +    const struct qemu_argument *arginfo; + +    for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { +        if (arginfo->env == NULL) { +            continue; +        } + +        r = getenv(arginfo->env); +        if (r != NULL) { +            arginfo->handle_opt(r); +        } +    } + +    optind = 1; +    for (;;) { +        if (optind >= argc) { +            break; +        } +        r = argv[optind]; +        if (r[0] != '-') { +            break; +        } +        optind++; +        r++; +        if (!strcmp(r, "-")) { +            break; +        } + +        for (arginfo = arg_table; arginfo->handle_opt != NULL; arginfo++) { +            if (!strcmp(r, arginfo->argv)) { +                if (arginfo->has_arg) { +                    if (optind >= argc) { +                        usage(); +                    } +                    arginfo->handle_opt(argv[optind]); +                    optind++; +                } else { +                    arginfo->handle_opt(NULL); +                } +                break; +            } +        } + +        /* no option matched the current argv */ +        if (arginfo->handle_opt == NULL) { +            usage(); +        } +    } + +    if (optind >= argc) { +        usage(); +    } + +    filename = argv[optind]; +    exec_path = argv[optind]; + +    return optind; +} + +int main(int argc, char **argv, char **envp) +{ +    struct target_pt_regs regs1, *regs = ®s1; +    struct image_info info1, *info = &info1; +    struct linux_binprm bprm; +    TaskState *ts; +    CPUArchState *env; +    CPUState *cpu; +    int optind; +    char **target_environ, **wrk; +    char **target_argv; +    int target_argc; +    int i; +    int ret; +    int execfd; + +    module_call_init(MODULE_INIT_QOM); + +    if ((envlist = envlist_create()) == NULL) { +        (void) fprintf(stderr, "Unable to allocate envlist\n"); +        exit(1); +    } + +    /* add current environment into the list */ +    for (wrk = environ; *wrk != NULL; wrk++) { +        (void) envlist_setenv(envlist, *wrk); +    } + +    /* Read the stack limit from the kernel.  If it's "unlimited", +       then we can do little else besides use the default.  */ +    { +        struct rlimit lim; +        if (getrlimit(RLIMIT_STACK, &lim) == 0 +            && lim.rlim_cur != RLIM_INFINITY +            && lim.rlim_cur == (target_long)lim.rlim_cur) { +            guest_stack_size = lim.rlim_cur; +        } +    } + +    cpu_model = NULL; +#if defined(cpudef_setup) +    cpudef_setup(); /* parse cpu definitions in target config file (TBD) */ +#endif + +    srand(time(NULL)); + +    optind = parse_args(argc, argv); + +    /* Zero out regs */ +    memset(regs, 0, sizeof(struct target_pt_regs)); + +    /* Zero out image_info */ +    memset(info, 0, sizeof(struct image_info)); + +    memset(&bprm, 0, sizeof (bprm)); + +    /* Scan interp_prefix dir for replacement files. */ +    init_paths(interp_prefix); + +    init_qemu_uname_release(); + +    if (cpu_model == NULL) { +#if defined(TARGET_I386) +#ifdef TARGET_X86_64 +        cpu_model = "qemu64"; +#else +        cpu_model = "qemu32"; +#endif +#elif defined(TARGET_ARM) +        cpu_model = "any"; +#elif defined(TARGET_UNICORE32) +        cpu_model = "any"; +#elif defined(TARGET_M68K) +        cpu_model = "any"; +#elif defined(TARGET_SPARC) +#ifdef TARGET_SPARC64 +        cpu_model = "TI UltraSparc II"; +#else +        cpu_model = "Fujitsu MB86904"; +#endif +#elif defined(TARGET_MIPS) +#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) +        cpu_model = "5KEf"; +#else +        cpu_model = "24Kf"; +#endif +#elif defined TARGET_OPENRISC +        cpu_model = "or1200"; +#elif defined(TARGET_PPC) +# ifdef TARGET_PPC64 +        cpu_model = "POWER7"; +# else +        cpu_model = "750"; +# endif +#elif defined TARGET_SH4 +        cpu_model = TYPE_SH7785_CPU; +#else +        cpu_model = "any"; +#endif +    } +    tcg_exec_init(0); +    /* NOTE: we need to init the CPU at this stage to get +       qemu_host_page_size */ +    cpu = cpu_init(cpu_model); +    if (!cpu) { +        fprintf(stderr, "Unable to find CPU definition\n"); +        exit(1); +    } +    env = cpu->env_ptr; +    cpu_reset(cpu); + +    thread_cpu = cpu; + +    if (getenv("QEMU_STRACE")) { +        do_strace = 1; +    } + +    if (getenv("QEMU_RAND_SEED")) { +        handle_arg_randseed(getenv("QEMU_RAND_SEED")); +    } + +    target_environ = envlist_to_environ(envlist, NULL); +    envlist_free(envlist); + +#if defined(CONFIG_USE_GUEST_BASE) +    /* +     * Now that page sizes are configured in cpu_init() we can do +     * proper page alignment for guest_base. +     */ +    guest_base = HOST_PAGE_ALIGN(guest_base); + +    if (reserved_va || have_guest_base) { +        guest_base = init_guest_space(guest_base, reserved_va, 0, +                                      have_guest_base); +        if (guest_base == (unsigned long)-1) { +            fprintf(stderr, "Unable to reserve 0x%lx bytes of virtual address " +                    "space for use as guest address space (check your virtual " +                    "memory ulimit setting or reserve less using -R option)\n", +                    reserved_va); +            exit(1); +        } + +        if (reserved_va) { +            mmap_next_start = reserved_va; +        } +    } +#endif /* CONFIG_USE_GUEST_BASE */ + +    /* +     * Read in mmap_min_addr kernel parameter.  This value is used +     * When loading the ELF image to determine whether guest_base +     * is needed.  It is also used in mmap_find_vma. +     */ +    { +        FILE *fp; + +        if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) { +            unsigned long tmp; +            if (fscanf(fp, "%lu", &tmp) == 1) { +                mmap_min_addr = tmp; +                qemu_log("host mmap_min_addr=0x%lx\n", mmap_min_addr); +            } +            fclose(fp); +        } +    } + +    /* +     * Prepare copy of argv vector for target. +     */ +    target_argc = argc - optind; +    target_argv = calloc(target_argc + 1, sizeof (char *)); +    if (target_argv == NULL) { +	(void) fprintf(stderr, "Unable to allocate memory for target_argv\n"); +	exit(1); +    } + +    /* +     * If argv0 is specified (using '-0' switch) we replace +     * argv[0] pointer with the given one. +     */ +    i = 0; +    if (argv0 != NULL) { +        target_argv[i++] = strdup(argv0); +    } +    for (; i < target_argc; i++) { +        target_argv[i] = strdup(argv[optind + i]); +    } +    target_argv[target_argc] = NULL; + +    ts = g_malloc0 (sizeof(TaskState)); +    init_task_state(ts); +    /* build Task State */ +    ts->info = info; +    ts->bprm = &bprm; +    cpu->opaque = ts; +    task_settid(ts); + +    execfd = qemu_getauxval(AT_EXECFD); +    if (execfd == 0) { +        execfd = open(filename, O_RDONLY); +        if (execfd < 0) { +            printf("Error while loading %s: %s\n", filename, strerror(errno)); +            _exit(1); +        } +    } + +    ret = loader_exec(execfd, filename, target_argv, target_environ, regs, +        info, &bprm); +    if (ret != 0) { +        printf("Error while loading %s: %s\n", filename, strerror(-ret)); +        _exit(1); +    } + +    for (wrk = target_environ; *wrk; wrk++) { +        free(*wrk); +    } + +    free(target_environ); + +    if (qemu_log_enabled()) { +#if defined(CONFIG_USE_GUEST_BASE) +        qemu_log("guest_base  0x%lx\n", guest_base); +#endif +        log_page_dump(); + +        qemu_log("start_brk   0x" TARGET_ABI_FMT_lx "\n", info->start_brk); +        qemu_log("end_code    0x" TARGET_ABI_FMT_lx "\n", info->end_code); +        qemu_log("start_code  0x" TARGET_ABI_FMT_lx "\n", +                 info->start_code); +        qemu_log("start_data  0x" TARGET_ABI_FMT_lx "\n", +                 info->start_data); +        qemu_log("end_data    0x" TARGET_ABI_FMT_lx "\n", info->end_data); +        qemu_log("start_stack 0x" TARGET_ABI_FMT_lx "\n", +                 info->start_stack); +        qemu_log("brk         0x" TARGET_ABI_FMT_lx "\n", info->brk); +        qemu_log("entry       0x" TARGET_ABI_FMT_lx "\n", info->entry); +    } + +    target_set_brk(info->brk); +    syscall_init(); +    signal_init(); + +#if defined(CONFIG_USE_GUEST_BASE) +    /* Now that we've loaded the binary, GUEST_BASE is fixed.  Delay +       generating the prologue until now so that the prologue can take +       the real value of GUEST_BASE into account.  */ +    tcg_prologue_init(&tcg_ctx); +#endif + +#if defined(TARGET_I386) +    env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK; +    env->hflags |= HF_PE_MASK | HF_CPL_MASK; +    if (env->features[FEAT_1_EDX] & CPUID_SSE) { +        env->cr[4] |= CR4_OSFXSR_MASK; +        env->hflags |= HF_OSFXSR_MASK; +    } +#ifndef TARGET_ABI32 +    /* enable 64 bit mode if possible */ +    if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM)) { +        fprintf(stderr, "The selected x86 CPU does not support 64 bit mode\n"); +        exit(1); +    } +    env->cr[4] |= CR4_PAE_MASK; +    env->efer |= MSR_EFER_LMA | MSR_EFER_LME; +    env->hflags |= HF_LMA_MASK; +#endif + +    /* flags setup : we activate the IRQs by default as in user mode */ +    env->eflags |= IF_MASK; + +    /* linux register setup */ +#ifndef TARGET_ABI32 +    env->regs[R_EAX] = regs->rax; +    env->regs[R_EBX] = regs->rbx; +    env->regs[R_ECX] = regs->rcx; +    env->regs[R_EDX] = regs->rdx; +    env->regs[R_ESI] = regs->rsi; +    env->regs[R_EDI] = regs->rdi; +    env->regs[R_EBP] = regs->rbp; +    env->regs[R_ESP] = regs->rsp; +    env->eip = regs->rip; +#else +    env->regs[R_EAX] = regs->eax; +    env->regs[R_EBX] = regs->ebx; +    env->regs[R_ECX] = regs->ecx; +    env->regs[R_EDX] = regs->edx; +    env->regs[R_ESI] = regs->esi; +    env->regs[R_EDI] = regs->edi; +    env->regs[R_EBP] = regs->ebp; +    env->regs[R_ESP] = regs->esp; +    env->eip = regs->eip; +#endif + +    /* linux interrupt setup */ +#ifndef TARGET_ABI32 +    env->idt.limit = 511; +#else +    env->idt.limit = 255; +#endif +    env->idt.base = target_mmap(0, sizeof(uint64_t) * (env->idt.limit + 1), +                                PROT_READ|PROT_WRITE, +                                MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); +    idt_table = g2h(env->idt.base); +    set_idt(0, 0); +    set_idt(1, 0); +    set_idt(2, 0); +    set_idt(3, 3); +    set_idt(4, 3); +    set_idt(5, 0); +    set_idt(6, 0); +    set_idt(7, 0); +    set_idt(8, 0); +    set_idt(9, 0); +    set_idt(10, 0); +    set_idt(11, 0); +    set_idt(12, 0); +    set_idt(13, 0); +    set_idt(14, 0); +    set_idt(15, 0); +    set_idt(16, 0); +    set_idt(17, 0); +    set_idt(18, 0); +    set_idt(19, 0); +    set_idt(0x80, 3); + +    /* linux segment setup */ +    { +        uint64_t *gdt_table; +        env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES, +                                    PROT_READ|PROT_WRITE, +                                    MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); +        env->gdt.limit = sizeof(uint64_t) * TARGET_GDT_ENTRIES - 1; +        gdt_table = g2h(env->gdt.base); +#ifdef TARGET_ABI32 +        write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff, +                 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | +                 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT)); +#else +        /* 64 bit code segment */ +        write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff, +                 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | +                 DESC_L_MASK | +                 (3 << DESC_DPL_SHIFT) | (0xa << DESC_TYPE_SHIFT)); +#endif +        write_dt(&gdt_table[__USER_DS >> 3], 0, 0xfffff, +                 DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | +                 (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT)); +    } +    cpu_x86_load_seg(env, R_CS, __USER_CS); +    cpu_x86_load_seg(env, R_SS, __USER_DS); +#ifdef TARGET_ABI32 +    cpu_x86_load_seg(env, R_DS, __USER_DS); +    cpu_x86_load_seg(env, R_ES, __USER_DS); +    cpu_x86_load_seg(env, R_FS, __USER_DS); +    cpu_x86_load_seg(env, R_GS, __USER_DS); +    /* This hack makes Wine work... */ +    env->segs[R_FS].selector = 0; +#else +    cpu_x86_load_seg(env, R_DS, 0); +    cpu_x86_load_seg(env, R_ES, 0); +    cpu_x86_load_seg(env, R_FS, 0); +    cpu_x86_load_seg(env, R_GS, 0); +#endif +#elif defined(TARGET_AARCH64) +    { +        int i; + +        if (!(arm_feature(env, ARM_FEATURE_AARCH64))) { +            fprintf(stderr, +                    "The selected ARM CPU does not support 64 bit mode\n"); +            exit(1); +        } + +        for (i = 0; i < 31; i++) { +            env->xregs[i] = regs->regs[i]; +        } +        env->pc = regs->pc; +        env->xregs[31] = regs->sp; +    } +#elif defined(TARGET_ARM) +    { +        int i; +        cpsr_write(env, regs->uregs[16], 0xffffffff); +        for(i = 0; i < 16; i++) { +            env->regs[i] = regs->uregs[i]; +        } +        /* Enable BE8.  */ +        if (EF_ARM_EABI_VERSION(info->elf_flags) >= EF_ARM_EABI_VER4 +            && (info->elf_flags & EF_ARM_BE8)) { +            env->bswap_code = 1; +        } +    } +#elif defined(TARGET_UNICORE32) +    { +        int i; +        cpu_asr_write(env, regs->uregs[32], 0xffffffff); +        for (i = 0; i < 32; i++) { +            env->regs[i] = regs->uregs[i]; +        } +    } +#elif defined(TARGET_SPARC) +    { +        int i; +	env->pc = regs->pc; +	env->npc = regs->npc; +        env->y = regs->y; +        for(i = 0; i < 8; i++) +            env->gregs[i] = regs->u_regs[i]; +        for(i = 0; i < 8; i++) +            env->regwptr[i] = regs->u_regs[i + 8]; +    } +#elif defined(TARGET_PPC) +    { +        int i; + +#if defined(TARGET_PPC64) +#if defined(TARGET_ABI32) +        env->msr &= ~((target_ulong)1 << MSR_SF); +#else +        env->msr |= (target_ulong)1 << MSR_SF; +#endif +#endif +        env->nip = regs->nip; +        for(i = 0; i < 32; i++) { +            env->gpr[i] = regs->gpr[i]; +        } +    } +#elif defined(TARGET_M68K) +    { +        env->pc = regs->pc; +        env->dregs[0] = regs->d0; +        env->dregs[1] = regs->d1; +        env->dregs[2] = regs->d2; +        env->dregs[3] = regs->d3; +        env->dregs[4] = regs->d4; +        env->dregs[5] = regs->d5; +        env->dregs[6] = regs->d6; +        env->dregs[7] = regs->d7; +        env->aregs[0] = regs->a0; +        env->aregs[1] = regs->a1; +        env->aregs[2] = regs->a2; +        env->aregs[3] = regs->a3; +        env->aregs[4] = regs->a4; +        env->aregs[5] = regs->a5; +        env->aregs[6] = regs->a6; +        env->aregs[7] = regs->usp; +        env->sr = regs->sr; +        ts->sim_syscalls = 1; +    } +#elif defined(TARGET_MICROBLAZE) +    { +        env->regs[0] = regs->r0; +        env->regs[1] = regs->r1; +        env->regs[2] = regs->r2; +        env->regs[3] = regs->r3; +        env->regs[4] = regs->r4; +        env->regs[5] = regs->r5; +        env->regs[6] = regs->r6; +        env->regs[7] = regs->r7; +        env->regs[8] = regs->r8; +        env->regs[9] = regs->r9; +        env->regs[10] = regs->r10; +        env->regs[11] = regs->r11; +        env->regs[12] = regs->r12; +        env->regs[13] = regs->r13; +        env->regs[14] = regs->r14; +        env->regs[15] = regs->r15;	     +        env->regs[16] = regs->r16;	     +        env->regs[17] = regs->r17;	     +        env->regs[18] = regs->r18;	     +        env->regs[19] = regs->r19;	     +        env->regs[20] = regs->r20;	     +        env->regs[21] = regs->r21;	     +        env->regs[22] = regs->r22;	     +        env->regs[23] = regs->r23;	     +        env->regs[24] = regs->r24;	     +        env->regs[25] = regs->r25;	     +        env->regs[26] = regs->r26;	     +        env->regs[27] = regs->r27;	     +        env->regs[28] = regs->r28;	     +        env->regs[29] = regs->r29;	     +        env->regs[30] = regs->r30;	     +        env->regs[31] = regs->r31;	     +        env->sregs[SR_PC] = regs->pc; +    } +#elif defined(TARGET_MIPS) +    { +        int i; + +        for(i = 0; i < 32; i++) { +            env->active_tc.gpr[i] = regs->regs[i]; +        } +        env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1; +        if (regs->cp0_epc & 1) { +            env->hflags |= MIPS_HFLAG_M16; +        } +    } +#elif defined(TARGET_OPENRISC) +    { +        int i; + +        for (i = 0; i < 32; i++) { +            env->gpr[i] = regs->gpr[i]; +        } + +        env->sr = regs->sr; +        env->pc = regs->pc; +    } +#elif defined(TARGET_SH4) +    { +        int i; + +        for(i = 0; i < 16; i++) { +            env->gregs[i] = regs->regs[i]; +        } +        env->pc = regs->pc; +    } +#elif defined(TARGET_ALPHA) +    { +        int i; + +        for(i = 0; i < 28; i++) { +            env->ir[i] = ((abi_ulong *)regs)[i]; +        } +        env->ir[IR_SP] = regs->usp; +        env->pc = regs->pc; +    } +#elif defined(TARGET_CRIS) +    { +	    env->regs[0] = regs->r0; +	    env->regs[1] = regs->r1; +	    env->regs[2] = regs->r2; +	    env->regs[3] = regs->r3; +	    env->regs[4] = regs->r4; +	    env->regs[5] = regs->r5; +	    env->regs[6] = regs->r6; +	    env->regs[7] = regs->r7; +	    env->regs[8] = regs->r8; +	    env->regs[9] = regs->r9; +	    env->regs[10] = regs->r10; +	    env->regs[11] = regs->r11; +	    env->regs[12] = regs->r12; +	    env->regs[13] = regs->r13; +	    env->regs[14] = info->start_stack; +	    env->regs[15] = regs->acr;	     +	    env->pc = regs->erp; +    } +#elif defined(TARGET_S390X) +    { +            int i; +            for (i = 0; i < 16; i++) { +                env->regs[i] = regs->gprs[i]; +            } +            env->psw.mask = regs->psw.mask; +            env->psw.addr = regs->psw.addr; +    } +#else +#error unsupported target CPU +#endif + +#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32) +    ts->stack_base = info->start_stack; +    ts->heap_base = info->brk; +    /* This will be filled in on the first SYS_HEAPINFO call.  */ +    ts->heap_limit = 0; +#endif + +    if (gdbstub_port) { +        if (gdbserver_start(gdbstub_port) < 0) { +            fprintf(stderr, "qemu: could not open gdbserver on port %d\n", +                    gdbstub_port); +            exit(1); +        } +        gdb_handlesig(cpu, 0); +    } +    cpu_loop(env); +    /* never exits */ +    return 0; +} diff --git a/linux-user/microblaze/syscall.h b/linux-user/microblaze/syscall.h new file mode 100644 index 00000000..3c1ed27c --- /dev/null +++ b/linux-user/microblaze/syscall.h @@ -0,0 +1,56 @@ +#ifndef MICROBLAZE_SYSCALLS_H +#define MICROBLAZE_SYSCALLS_H 1 + +#define UNAME_MACHINE "microblaze" +#define UNAME_MINIMUM_RELEASE "2.6.32" + +/* We use microblaze_reg_t to keep things similar to the kernel sources.  */ +typedef uint32_t microblaze_reg_t; + +struct target_pt_regs { +        microblaze_reg_t r0; +        microblaze_reg_t r1; +        microblaze_reg_t r2; +        microblaze_reg_t r3; +        microblaze_reg_t r4; +        microblaze_reg_t r5; +        microblaze_reg_t r6; +        microblaze_reg_t r7; +        microblaze_reg_t r8; +        microblaze_reg_t r9; +        microblaze_reg_t r10; +        microblaze_reg_t r11; +        microblaze_reg_t r12; +        microblaze_reg_t r13; +        microblaze_reg_t r14; +        microblaze_reg_t r15; +        microblaze_reg_t r16; +        microblaze_reg_t r17; +        microblaze_reg_t r18; +        microblaze_reg_t r19; +        microblaze_reg_t r20; +        microblaze_reg_t r21; +        microblaze_reg_t r22; +        microblaze_reg_t r23; +        microblaze_reg_t r24; +        microblaze_reg_t r25; +        microblaze_reg_t r26; +        microblaze_reg_t r27; +        microblaze_reg_t r28; +        microblaze_reg_t r29; +        microblaze_reg_t r30; +        microblaze_reg_t r31; +        microblaze_reg_t pc; +        microblaze_reg_t msr; +        microblaze_reg_t ear; +        microblaze_reg_t esr; +        microblaze_reg_t fsr; +        uint32_t kernel_mode; +}; + +#define TARGET_CLONE_BACKWARDS +#define TARGET_MINSIGSTKSZ      2048 +#define TARGET_MLOCKALL_MCL_CURRENT 1 +#define TARGET_MLOCKALL_MCL_FUTURE  2 + +#endif diff --git a/linux-user/microblaze/syscall_nr.h b/linux-user/microblaze/syscall_nr.h new file mode 100644 index 00000000..6f530f9d --- /dev/null +++ b/linux-user/microblaze/syscall_nr.h @@ -0,0 +1,384 @@ +#define TARGET_NR_restart_syscall	0 /* ok */ +#define TARGET_NR_exit		1 /* ok */ +#define TARGET_NR_fork		2 /* not for no MMU - weird */ +#define TARGET_NR_read		3 /* ok */ +#define TARGET_NR_write		4 /* ok */ +#define TARGET_NR_open		5 /* openat */ +#define TARGET_NR_close		6 /* ok */ +#define TARGET_NR_waitpid		7 /* waitid */ +#define TARGET_NR_creat		8 /* openat */ +#define TARGET_NR_link		9 /* linkat */ +#define TARGET_NR_unlink		10 /* unlinkat */ +#define TARGET_NR_execve		11 /* ok */ +#define TARGET_NR_chdir		12 /* ok */ +#define TARGET_NR_time		13 /* obsolete -> sys_gettimeofday */ +#define TARGET_NR_mknod		14 /* mknodat */ +#define TARGET_NR_chmod		15 /* fchmodat */ +#define TARGET_NR_lchown		16 /* ok */ +#define TARGET_NR_break		17 /* don't know */ +#define TARGET_NR_oldstat		18 /* remove */ +#define TARGET_NR_lseek		19 /* ok */ +#define TARGET_NR_getpid		20 /* ok */ +#define TARGET_NR_mount		21 /* ok */ +#define TARGET_NR_umount		22 /* ok */  /* use only umount2 */ +#define TARGET_NR_setuid		23 /* ok */ +#define TARGET_NR_getuid		24 /* ok */ +#define TARGET_NR_stime		25 /* obsolete -> sys_settimeofday */ +#define TARGET_NR_ptrace		26 /* ok */ +#define TARGET_NR_alarm		27 /* obsolete -> sys_setitimer */ +#define TARGET_NR_oldfstat		28 /* remove */ +#define TARGET_NR_pause		29 /* obsolete -> sys_rt_sigtimedwait */ +#define TARGET_NR_utime		30 /* obsolete -> sys_utimesat */ +#define TARGET_NR_stty		31 /* remove */ +#define TARGET_NR_gtty		32 /* remove */ +#define TARGET_NR_access		33 /* faccessat */ +#define TARGET_NR_nice		34 /* can be implemented by sys_setpriority */ +#define TARGET_NR_ftime		35 /* remove */ +#define TARGET_NR_sync		36 /* ok */ +#define TARGET_NR_kill		37 /* ok */ +#define TARGET_NR_rename		38 /* renameat */ +#define TARGET_NR_mkdir		39 /* mkdirat */ +#define TARGET_NR_rmdir		40 /* unlinkat */ +#define TARGET_NR_dup		41 /* ok */ +#define TARGET_NR_pipe		42 /* ok */ +#define TARGET_NR_times		43 /* ok */ +#define TARGET_NR_prof		44 /* remove */ +#define TARGET_NR_brk		45 /* ok -mmu, nommu specific */ +#define TARGET_NR_setgid		46 /* ok */ +#define TARGET_NR_getgid		47 /* ok */ +#define TARGET_NR_signal		48 /* obsolete -> sys_rt_sigaction */ +#define TARGET_NR_geteuid		49 /* ok */ +#define TARGET_NR_getegid		50 /* ok */ +#define TARGET_NR_acct		51 /* add it and then I can disable it */ +#define TARGET_NR_umount2		52 /* remove */ +#define TARGET_NR_lock		53 /* remove */ +#define TARGET_NR_ioctl		54 /* ok */ +#define TARGET_NR_fcntl		55 /* ok -> 64bit version*/ +#define TARGET_NR_mpx		56 /* remove */ +#define TARGET_NR_setpgid		57 /* ok */ +#define TARGET_NR_ulimit		58 /* remove */ +#define TARGET_NR_oldolduname	59 /* remove */ +#define TARGET_NR_umask		60 /* ok */ +#define TARGET_NR_chroot		61 /* ok */ +#define TARGET_NR_ustat		62 /* obsolete -> statfs64 */ +#define TARGET_NR_dup2		63 /* ok */ +#define TARGET_NR_getppid		64 /* ok */ +#define TARGET_NR_getpgrp		65 /* obsolete -> sys_getpgid */ +#define TARGET_NR_setsid		66 /* ok */ +#define TARGET_NR_sigaction		67 /* obsolete -> rt_sigaction */ +#define TARGET_NR_sgetmask		68 /* obsolete -> sys_rt_sigprocmask */ +#define TARGET_NR_ssetmask		69 /* obsolete ->sys_rt_sigprocmask */ +#define TARGET_NR_setreuid		70 /* ok */ +#define TARGET_NR_setregid		71 /* ok */ +#define TARGET_NR_sigsuspend		72 /* obsolete -> rt_sigsuspend */ +#define TARGET_NR_sigpending		73 /* obsolete -> sys_rt_sigpending */ +#define TARGET_NR_sethostname	74 /* ok */ +#define TARGET_NR_setrlimit		75 /* ok */ +#define TARGET_NR_getrlimit		76 /* ok Back compatible 2Gig limited rlimit */ +#define TARGET_NR_getrusage		77 /* ok */ +#define TARGET_NR_gettimeofday	78 /* ok */ +#define TARGET_NR_settimeofday	79 /* ok */ +#define TARGET_NR_getgroups		80 /* ok */ +#define TARGET_NR_setgroups		81 /* ok */ +#define TARGET_NR_select		82 /* obsolete -> sys_pselect7 */ +#define TARGET_NR_symlink		83 /* symlinkat */ +#define TARGET_NR_oldlstat		84 /* remove */ +#define TARGET_NR_readlink		85 /* obsolete -> sys_readlinkat */ +#define TARGET_NR_uselib		86 /* remove */ +#define TARGET_NR_swapon		87 /* ok */ +#define TARGET_NR_reboot		88 /* ok */ +#define TARGET_NR_readdir		89 /* remove ? */ +#define TARGET_NR_mmap		90 /* obsolete -> sys_mmap2 */ +#define TARGET_NR_munmap		91 /* ok - mmu and nommu */ +#define TARGET_NR_truncate		92 /* ok or truncate64 */ +#define TARGET_NR_ftruncate		93 /* ok or ftruncate64 */ +#define TARGET_NR_fchmod		94 /* ok */ +#define TARGET_NR_fchown		95 /* ok */ +#define TARGET_NR_getpriority	96 /* ok */ +#define TARGET_NR_setpriority	97 /* ok */ +#define TARGET_NR_profil		98 /* remove */ +#define TARGET_NR_statfs		99 /* ok or statfs64 */ +#define TARGET_NR_fstatfs		100  /* ok or fstatfs64 */ +#define TARGET_NR_ioperm		101 /* remove */ +#define TARGET_NR_socketcall		102 /* remove */ +#define TARGET_NR_syslog		103 /* ok */ +#define TARGET_NR_setitimer		104 /* ok */ +#define TARGET_NR_getitimer		105 /* ok */ +#define TARGET_NR_stat		106 /* remove */ +#define TARGET_NR_lstat		107 /* remove */ +#define TARGET_NR_fstat		108 /* remove */ +#define TARGET_NR_olduname		109 /* remove */ +#define TARGET_NR_iopl		110 /* remove */ +#define TARGET_NR_vhangup		111 /* ok */ +#define TARGET_NR_idle		112 /* remove */ +#define TARGET_NR_vm86old		113 /* remove */ +#define TARGET_NR_wait4		114 /* obsolete -> waitid */ +#define TARGET_NR_swapoff		115 /* ok */ +#define TARGET_NR_sysinfo		116 /* ok */ +#define TARGET_NR_ipc		117 /* remove - direct call */ +#define TARGET_NR_fsync		118 /* ok */ +#define TARGET_NR_sigreturn		119 /* obsolete -> sys_rt_sigreturn */ +#define TARGET_NR_clone		120 /* ok */ +#define TARGET_NR_setdomainname	121 /* ok */ +#define TARGET_NR_uname		122 /* remove */ +#define TARGET_NR_modify_ldt		123 /* remove */ +#define TARGET_NR_adjtimex		124 /* ok */ +#define TARGET_NR_mprotect		125 /* remove */ +#define TARGET_NR_sigprocmask	126 /* obsolete -> sys_rt_sigprocmask */ +#define TARGET_NR_create_module	127 /* remove */ +#define TARGET_NR_init_module	128 /* ok */ +#define TARGET_NR_delete_module	129 /* ok */ +#define TARGET_NR_get_kernel_syms	130 /* remove */ +#define TARGET_NR_quotactl		131 /* ok */ +#define TARGET_NR_getpgid		132 /* ok */ +#define TARGET_NR_fchdir		133 /* ok */ +#define TARGET_NR_bdflush		134 /* remove */ +#define TARGET_NR_sysfs		135 /* needed for busybox */ +#define TARGET_NR_personality	136 /* ok */ +#define TARGET_NR_afs_syscall	137 /* Syscall for Andrew File System */ +#define TARGET_NR_setfsuid		138 /* ok */ +#define TARGET_NR_setfsgid		139 /* ok */ +#define TARGET_NR__llseek		140 /* remove only lseek */ +#define TARGET_NR_getdents		141 /* ok or getdents64 */ +#define TARGET_NR__newselect		142 /* remove */ +#define TARGET_NR_flock		143 /* ok */ +#define TARGET_NR_msync		144 /* remove */ +#define TARGET_NR_readv		145 /* ok */ +#define TARGET_NR_writev		146 /* ok */ +#define TARGET_NR_getsid		147 /* ok */ +#define TARGET_NR_fdatasync		148 /* ok */ +#define TARGET_NR__sysctl		149 /* remove */ +#define TARGET_NR_mlock		150 /* ok - nommu or mmu */ +#define TARGET_NR_munlock		151 /* ok - nommu or mmu */ +#define TARGET_NR_mlockall		152 /* ok - nommu or mmu */ +#define TARGET_NR_munlockall		153 /* ok - nommu or mmu */ +#define TARGET_NR_sched_setparam		154 /* ok */ +#define TARGET_NR_sched_getparam		155 /* ok */ +#define TARGET_NR_sched_setscheduler		156 /* ok */ +#define TARGET_NR_sched_getscheduler		157 /* ok */ +#define TARGET_NR_sched_yield		158 /* ok */ +#define TARGET_NR_sched_get_priority_max	159 /* ok */ +#define TARGET_NR_sched_get_priority_min	160 /* ok */ +#define TARGET_NR_sched_rr_get_interval	161 /* ok */ +#define TARGET_NR_nanosleep		162 /* ok */ +#define TARGET_NR_mremap		163 /* ok - nommu or mmu */ +#define TARGET_NR_setresuid		164 /* ok */ +#define TARGET_NR_getresuid		165 /* ok */ +#define TARGET_NR_vm86		166 /* remove */ +#define TARGET_NR_query_module	167 /* ok */ +#define TARGET_NR_poll		168 /* obsolete -> sys_ppoll */ +#define TARGET_NR_nfsservctl		169 /* ok */ +#define TARGET_NR_setresgid		170 /* ok */ +#define TARGET_NR_getresgid		171 /* ok */ +#define TARGET_NR_prctl		172 /* ok */ +#define TARGET_NR_rt_sigreturn	173 /* ok */ +#define TARGET_NR_rt_sigaction	174 /* ok */ +#define TARGET_NR_rt_sigprocmask	175 /* ok */ +#define TARGET_NR_rt_sigpending	176 /* ok */ +#define TARGET_NR_rt_sigtimedwait	177 /* ok */ +#define TARGET_NR_rt_sigqueueinfo	178 /* ok */ +#define TARGET_NR_rt_sigsuspend	179 /* ok */ +#define TARGET_NR_pread64		180 /* ok */ +#define TARGET_NR_pwrite64		181 /* ok */ +#define TARGET_NR_chown		182 /* obsolete -> fchownat */ +#define TARGET_NR_getcwd		183 /* ok */ +#define TARGET_NR_capget		184 /* ok */ +#define TARGET_NR_capset		185 /* ok */ +#define TARGET_NR_sigaltstack	186 /* remove */ +#define TARGET_NR_sendfile		187 /* ok -> exist 64bit version*/ +#define TARGET_NR_getpmsg		188 /* remove - some people actually want streams */ +#define TARGET_NR_putpmsg		189 /* remove - some people actually want streams */ +#define TARGET_NR_vfork		190 /* for noMMU - group with clone -> maybe remove */ +#define TARGET_NR_ugetrlimit		191 /* remove - SuS compliant getrlimit */ +#define TARGET_NR_mmap2		192 /* ok */ +#define TARGET_NR_truncate64		193 /* ok */ +#define TARGET_NR_ftruncate64	194 /* ok */ +#define TARGET_NR_stat64		195 /* remove _ARCH_WANT_STAT64 */ +#define TARGET_NR_lstat64		196 /* remove _ARCH_WANT_STAT64 */ +#define TARGET_NR_fstat64		197 /* remove _ARCH_WANT_STAT64 */ +#define TARGET_NR_lchown32		198 /* ok - without 32 */ +#define TARGET_NR_getuid32		199 /* ok - without 32 */ +#define TARGET_NR_getgid32		200 /* ok - without 32 */ +#define TARGET_NR_geteuid32		201 /* ok - without 32 */ +#define TARGET_NR_getegid32		202 /* ok - without 32 */ +#define TARGET_NR_setreuid32		203 /* ok - without 32 */ +#define TARGET_NR_setregid32		204 /* ok - without 32 */ +#define TARGET_NR_getgroups32	205 /* ok - without 32 */ +#define TARGET_NR_setgroups32	206 /* ok - without 32 */ +#define TARGET_NR_fchown32		207 /* ok - without 32 */ +#define TARGET_NR_setresuid32	208 /* ok - without 32 */ +#define TARGET_NR_getresuid32	209 /* ok - without 32 */ +#define TARGET_NR_setresgid32	210 /* ok - without 32 */ +#define TARGET_NR_getresgid32	211 /* ok - without 32 */ +#define TARGET_NR_chown32		212 /* ok - without 32 -obsolete -> fchownat */ +#define TARGET_NR_setuid32		213 /* ok - without 32 */ +#define TARGET_NR_setgid32		214 /* ok - without 32 */ +#define TARGET_NR_setfsuid32		215 /* ok - without 32 */ +#define TARGET_NR_setfsgid32		216 /* ok - without 32 */ +#define TARGET_NR_pivot_root		217 /* ok */ +#define TARGET_NR_mincore		218 /* ok */ +#define TARGET_NR_madvise		219 /* ok */ +//#define TARGET_NR_madvise1		219 /* remove delete when C lib stub is removed */ +#define TARGET_NR_getdents64		220 /* ok */ +#define TARGET_NR_fcntl64		221 /* ok */ +/* 223 is unused */ +#define TARGET_NR_gettid		224 /* ok */ +#define TARGET_NR_readahead		225 /* ok */ +#define TARGET_NR_setxattr		226 /* ok */ +#define TARGET_NR_lsetxattr		227 /* ok */ +#define TARGET_NR_fsetxattr		228 /* ok */ +#define TARGET_NR_getxattr		229 /* ok */ +#define TARGET_NR_lgetxattr		230 /* ok */ +#define TARGET_NR_fgetxattr		231 /* ok */ +#define TARGET_NR_listxattr		232 /* ok */ +#define TARGET_NR_llistxattr		233 /* ok */ +#define TARGET_NR_flistxattr		234 /* ok */ +#define TARGET_NR_removexattr	235 /* ok */ +#define TARGET_NR_lremovexattr	236 /* ok */ +#define TARGET_NR_fremovexattr	237 /* ok */ +#define TARGET_NR_tkill		238 /* ok */ +#define TARGET_NR_sendfile64		239 /* ok */ +#define TARGET_NR_futex		240 /* ok */ +#define TARGET_NR_sched_setaffinity	241 /* ok */ +#define TARGET_NR_sched_getaffinity	242 /* ok */ +#define TARGET_NR_set_thread_area	243 /* remove */ +#define TARGET_NR_get_thread_area	244 /* remove */ +#define TARGET_NR_io_setup		245 /* ok */ +#define TARGET_NR_io_destroy		246 /* ok */ +#define TARGET_NR_io_getevents	247 /* ok */ +#define TARGET_NR_io_submit		248 /* ok */ +#define TARGET_NR_io_cancel		249 /* ok */ +#define TARGET_NR_fadvise64		250 /* remove -> sys_fadvise64_64 */ +/* 251 is available for reuse (was briefly sys_set_zone_reclaim) */ +#define TARGET_NR_exit_group		252 /* ok */ +#define TARGET_NR_lookup_dcookie	253 /* ok */ +#define TARGET_NR_epoll_create	254 /* ok */ +#define TARGET_NR_epoll_ctl		255 /* ok */ +#define TARGET_NR_epoll_wait		256 /* obsolete -> sys_epoll_pwait */ +#define TARGET_NR_remap_file_pages	257 /* only for mmu */ +#define TARGET_NR_set_tid_address	258 /* ok */ +#define TARGET_NR_timer_create	259 /* ok */ +#define TARGET_NR_timer_settime	(TARGET_NR_timer_create+1) /* 260 */ /* ok */ +#define TARGET_NR_timer_gettime	(TARGET_NR_timer_create+2) /* 261 */ /* ok */ +#define TARGET_NR_timer_getoverrun	(TARGET_NR_timer_create+3) /* 262 */ /* ok */ +#define TARGET_NR_timer_delete	(TARGET_NR_timer_create+4) /* 263 */ /* ok */ +#define TARGET_NR_clock_settime	(TARGET_NR_timer_create+5) /* 264 */ /* ok */ +#define TARGET_NR_clock_gettime	(TARGET_NR_timer_create+6) /* 265 */ /* ok */ +#define TARGET_NR_clock_getres	(TARGET_NR_timer_create+7) /* 266 */ /* ok */ +#define TARGET_NR_clock_nanosleep	(TARGET_NR_timer_create+8) /* 267 */ /* ok */ +#define TARGET_NR_statfs64		268 /* ok */ +#define TARGET_NR_fstatfs64		269 /* ok */ +#define TARGET_NR_tgkill		270 /* ok */ +#define TARGET_NR_utimes		271 /* obsolete -> sys_futimesat */ +#define TARGET_NR_fadvise64_64	272 /* ok */ +#define TARGET_NR_vserver		273 /* ok */ +#define TARGET_NR_mbind		274 /* only for mmu */ +#define TARGET_NR_get_mempolicy	275 /* only for mmu */ +#define TARGET_NR_set_mempolicy	276 /* only for mmu */ +#define TARGET_NR_mq_open		277 /* ok */ +#define TARGET_NR_mq_unlink		(TARGET_NR_mq_open+1) /* 278 */ /* ok */ +#define TARGET_NR_mq_timedsend	(TARGET_NR_mq_open+2) /* 279 */ /* ok */ +#define TARGET_NR_mq_timedreceive	(TARGET_NR_mq_open+3) /* 280 */ /* ok */ +#define TARGET_NR_mq_notify		(TARGET_NR_mq_open+4) /* 281 */ /* ok */ +#define TARGET_NR_mq_getsetattr	(TARGET_NR_mq_open+5) /* 282 */ /* ok */ +#define TARGET_NR_kexec_load		283 /* ok */ +#define TARGET_NR_waitid		284 /* ok */ +/* #define TARGET_NR_sys_setaltroot	285 */ +#define TARGET_NR_add_key		286 /* ok */ +#define TARGET_NR_request_key	287 /* ok */ +#define TARGET_NR_keyctl		288 /* ok */ +#define TARGET_NR_ioprio_set		289 /* ok */ +#define TARGET_NR_ioprio_get		290 /* ok */ +#define TARGET_NR_inotify_init	291 /* ok */ +#define TARGET_NR_inotify_add_watch	292 /* ok */ +#define TARGET_NR_inotify_rm_watch	293 /* ok */ +#define TARGET_NR_migrate_pages	294 /* mmu */ +#define TARGET_NR_openat		295 /* ok */ +#define TARGET_NR_mkdirat		296 /* ok */ +#define TARGET_NR_mknodat		297 /* ok */ +#define TARGET_NR_fchownat		298 /* ok */ +#define TARGET_NR_futimesat		299 /* obsolete -> sys_utimesat */ +#define TARGET_NR_fstatat64		300 /* stat64 */ +#define TARGET_NR_unlinkat		301 /* ok */ +#define TARGET_NR_renameat		302 /* ok */ +#define TARGET_NR_linkat		303 /* ok */ +#define TARGET_NR_symlinkat		304 /* ok */ +#define TARGET_NR_readlinkat		305 /* ok */ +#define TARGET_NR_fchmodat		306 /* ok */ +#define TARGET_NR_faccessat		307 /* ok */ +#define TARGET_NR_pselect6		308 /* obsolete -> sys_pselect7 */ +#define TARGET_NR_ppoll		309 /* ok */ +#define TARGET_NR_unshare		310 /* ok */ +#define TARGET_NR_set_robust_list	311 /* ok */ +#define TARGET_NR_get_robust_list	312 /* ok */ +#define TARGET_NR_splice		313 /* ok */ +#define TARGET_NR_sync_file_range	314 /* ok */ +#define TARGET_NR_tee		315 /* ok */ +#define TARGET_NR_vmsplice		316 /* ok */ +#define TARGET_NR_move_pages		317 /* mmu */ +#define TARGET_NR_getcpu		318 /* ok */ +#define TARGET_NR_epoll_pwait	319 /* ok */ +#define TARGET_NR_utimensat		320 /* ok */ +#define TARGET_NR_signalfd		321 /* ok */ +#define TARGET_NR_timerfd_create	322 /* ok */ +#define TARGET_NR_eventfd		323 /* ok */ +#define TARGET_NR_fallocate		324 /* ok */ +#define TARGET_NR_semtimedop		325 /* ok - semaphore group */ +#define TARGET_NR_timerfd_settime	326 /* ok */ +#define TARGET_NR_timerfd_gettime	327 /* ok */ +/* sysv ipc syscalls */ +#define TARGET_NR_semctl		328 /* ok */ +#define TARGET_NR_semget		329 /* ok */ +#define TARGET_NR_semop		330 /* ok */ +#define TARGET_NR_msgctl		331 /* ok */ +#define TARGET_NR_msgget		332 /* ok */ +#define TARGET_NR_msgrcv		333 /* ok */ +#define TARGET_NR_msgsnd		334 /* ok */ +#define TARGET_NR_shmat		335 /* ok */ +#define TARGET_NR_shmctl		336 /* ok */ +#define TARGET_NR_shmdt		337 /* ok */ +#define TARGET_NR_shmget		338 /* ok */ + + +#define TARGET_NR_signalfd4		339 /* new */ +#define TARGET_NR_eventfd2		340 /* new */ +#define TARGET_NR_epoll_create1	341 /* new */ +#define TARGET_NR_dup3		342 /* new */ +#define TARGET_NR_pipe2		343 /* new */ +#define TARGET_NR_inotify_init1	344 /* new */ +#define TARGET_NR_socket		345 /* new */ +#define TARGET_NR_socketpair		346 /* new */ +#define TARGET_NR_bind		347 /* new */ +#define TARGET_NR_listen		348 /* new */ +#define TARGET_NR_accept		349 /* new */ +#define TARGET_NR_connect		350 /* new */ +#define TARGET_NR_getsockname	351 /* new */ +#define TARGET_NR_getpeername	352 /* new */ +#define TARGET_NR_sendto		353 /* new */ +#define TARGET_NR_send		354 /* new */ +#define TARGET_NR_recvfrom		355 /* new */ +#define TARGET_NR_recv		356 /* new */ +#define TARGET_NR_setsockopt		357 /* new */ +#define TARGET_NR_getsockopt		358 /* new */ +#define TARGET_NR_shutdown		359 /* new */ +#define TARGET_NR_sendmsg		360 /* new */ +#define TARGET_NR_recvmsg		361 /* new */ +#define TARGET_NR_accept04		362 /* new */ +#define TARGET_NR_preadv                363 /* new */ +#define TARGET_NR_pwritev               364 /* new */ +#define TARGET_NR_rt_tgsigqueueinfo     365 /* new */ +#define TARGET_NR_perf_event_open       366 /* new */ +#define TARGET_NR_recvmmsg              367 /* new */ +#define TARGET_NR_fanotify_init         368 +#define TARGET_NR_fanotify_mark         369 +#define TARGET_NR_prlimit64             370 +#define TARGET_NR_name_to_handle_at     371 +#define TARGET_NR_open_by_handle_at     372 +#define TARGET_NR_clock_adjtime         373 +#define TARGET_NR_syncfs                374 +#define TARGET_NR_setns                 375 +#define TARGET_NR_sendmmsg              376 +#define TARGET_NR_process_vm_readv      377 +#define TARGET_NR_process_vm_writev     378 +#define TARGET_NR_kcmp                  379 +#define TARGET_NR_finit_module          380 diff --git a/linux-user/microblaze/target_cpu.h b/linux-user/microblaze/target_cpu.h new file mode 100644 index 00000000..c6386ea9 --- /dev/null +++ b/linux-user/microblaze/target_cpu.h @@ -0,0 +1,35 @@ +/* + * MicroBlaze specific CPU ABI and functions for linux-user + * + * Copyright (c) 2009 Edgar E. Iglesias + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUMBState *env, target_ulong newsp) +{ +    if (newsp) { +        env->regs[R_SP] = newsp; +    } +    env->regs[3] = 0; +} + +static inline void cpu_set_tls(CPUMBState *env, target_ulong newtls) +{ +    env->regs[21] = newtls; +} + +#endif diff --git a/linux-user/microblaze/target_signal.h b/linux-user/microblaze/target_signal.h new file mode 100644 index 00000000..3d1f7a72 --- /dev/null +++ b/linux-user/microblaze/target_signal.h @@ -0,0 +1,29 @@ +#ifndef TARGET_SIGNAL_H +#define TARGET_SIGNAL_H + +#include "cpu.h" + +/* this struct defines a stack used during syscall handling */ + +typedef struct target_sigaltstack { +	abi_ulong ss_sp; +	abi_ulong ss_size; +	abi_long ss_flags; +} target_stack_t; + + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK     1 +#define TARGET_SS_DISABLE     2 + +#define TARGET_MINSIGSTKSZ    2048 +#define TARGET_SIGSTKSZ       8192 + +static inline abi_ulong get_sp_from_cpustate(CPUMBState *state) +{ +    return state->regs[14]; +} + +#endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/microblaze/target_structs.h b/linux-user/microblaze/target_structs.h new file mode 100644 index 00000000..325e2f6d --- /dev/null +++ b/linux-user/microblaze/target_structs.h @@ -0,0 +1,58 @@ +/* + * MicroBlaze specific structures for linux-user + * + * Copyright (c) 2013 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_STRUCTS_H +#define TARGET_STRUCTS_H + +struct target_ipc_perm { +    abi_int __key;                      /* Key.  */ +    abi_uint uid;                       /* Owner's user ID.  */ +    abi_uint gid;                       /* Owner's group ID.  */ +    abi_uint cuid;                      /* Creator's user ID.  */ +    abi_uint cgid;                      /* Creator's group ID.  */ +    abi_ushort mode;                    /* Read/write permission.  */ +    abi_ushort __pad1; +    abi_ushort __seq;                   /* Sequence number.  */ +    abi_ushort __pad2; +    abi_ulong __unused1; +    abi_ulong __unused2; +}; + +struct target_shmid_ds { +    struct target_ipc_perm shm_perm;    /* operation permission struct */ +    abi_long shm_segsz;                 /* size of segment in bytes */ +    abi_ulong shm_atime;                /* time of last shmat() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused1; +#endif +    abi_ulong shm_dtime;                /* time of last shmdt() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused2; +#endif +    abi_ulong shm_ctime;                /* time of last change by shmctl() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused3; +#endif +    abi_int shm_cpid;                   /* pid of creator */ +    abi_int shm_lpid;                   /* pid of last shmop */ +    abi_ulong shm_nattch;               /* number of current attaches */ +    abi_ulong __unused4; +    abi_ulong __unused5; +}; + +#endif diff --git a/linux-user/microblaze/termbits.h b/linux-user/microblaze/termbits.h new file mode 100644 index 00000000..fc82ca08 --- /dev/null +++ b/linux-user/microblaze/termbits.h @@ -0,0 +1,213 @@ +/* from asm/termbits.h */ + +#define TARGET_NCCS 19 + +struct target_termios { +    unsigned int c_iflag;               /* input mode flags */ +    unsigned int c_oflag;               /* output mode flags */ +    unsigned int c_cflag;               /* control mode flags */ +    unsigned int c_lflag;               /* local mode flags */ +    unsigned char c_line;                    /* line discipline */ +    unsigned char c_cc[TARGET_NCCS];                /* control characters */ +}; + +/* c_iflag bits */ +#define TARGET_IGNBRK  0000001 +#define TARGET_BRKINT  0000002 +#define TARGET_IGNPAR  0000004 +#define TARGET_PARMRK  0000010 +#define TARGET_INPCK   0000020 +#define TARGET_ISTRIP  0000040 +#define TARGET_INLCR   0000100 +#define TARGET_IGNCR   0000200 +#define TARGET_ICRNL   0000400 +#define TARGET_IUCLC   0001000 +#define TARGET_IXON    0002000 +#define TARGET_IXANY   0004000 +#define TARGET_IXOFF   0010000 +#define TARGET_IMAXBEL 0020000 + +/* c_oflag bits */ +#define TARGET_OPOST   0000001 +#define TARGET_OLCUC   0000002 +#define TARGET_ONLCR   0000004 +#define TARGET_OCRNL   0000010 +#define TARGET_ONOCR   0000020 +#define TARGET_ONLRET  0000040 +#define TARGET_OFILL   0000100 +#define TARGET_OFDEL   0000200 +#define TARGET_NLDLY   0000400 +#define   TARGET_NL0   0000000 +#define   TARGET_NL1   0000400 +#define TARGET_CRDLY   0003000 +#define   TARGET_CR0   0000000 +#define   TARGET_CR1   0001000 +#define   TARGET_CR2   0002000 +#define   TARGET_CR3   0003000 +#define TARGET_TABDLY  0014000 +#define   TARGET_TAB0  0000000 +#define   TARGET_TAB1  0004000 +#define   TARGET_TAB2  0010000 +#define   TARGET_TAB3  0014000 +#define   TARGET_XTABS 0014000 +#define TARGET_BSDLY   0020000 +#define   TARGET_BS0   0000000 +#define   TARGET_BS1   0020000 +#define TARGET_VTDLY   0040000 +#define   TARGET_VT0   0000000 +#define   TARGET_VT1   0040000 +#define TARGET_FFDLY   0100000 +#define   TARGET_FF0   0000000 +#define   TARGET_FF1   0100000 + +/* c_cflag bit meaning */ +#define TARGET_CBAUD   0010017 +#define  TARGET_B0     0000000         /* hang up */ +#define  TARGET_B50    0000001 +#define  TARGET_B75    0000002 +#define  TARGET_B110   0000003 +#define  TARGET_B134   0000004 +#define  TARGET_B150   0000005 +#define  TARGET_B200   0000006 +#define  TARGET_B300   0000007 +#define  TARGET_B600   0000010 +#define  TARGET_B1200  0000011 +#define  TARGET_B1800  0000012 +#define  TARGET_B2400  0000013 +#define  TARGET_B4800  0000014 +#define  TARGET_B9600  0000015 +#define  TARGET_B19200 0000016 +#define  TARGET_B38400 0000017 +#define TARGET_EXTA B19200 +#define TARGET_EXTB B38400 +#define TARGET_CSIZE   0000060 +#define   TARGET_CS5   0000000 +#define   TARGET_CS6   0000020 +#define   TARGET_CS7   0000040 +#define   TARGET_CS8   0000060 +#define TARGET_CSTOPB  0000100 +#define TARGET_CREAD   0000200 +#define TARGET_PARENB  0000400 +#define TARGET_PARODD  0001000 +#define TARGET_HUPCL   0002000 +#define TARGET_CLOCAL  0004000 +#define TARGET_CBAUDEX 0010000 +#define  TARGET_B57600  0010001 +#define  TARGET_B115200 0010002 +#define  TARGET_B230400 0010003 +#define  TARGET_B460800 0010004 +#define TARGET_CIBAUD    002003600000  /* input baud rate (not used) */ +#define TARGET_CRTSCTS   020000000000          /* flow control */ + +/* c_lflag bits */ +#define TARGET_ISIG    0000001 +#define TARGET_ICANON  0000002 +#define TARGET_XCASE   0000004 +#define TARGET_ECHO    0000010 +#define TARGET_ECHOE   0000020 +#define TARGET_ECHOK   0000040 +#define TARGET_ECHONL  0000100 +#define TARGET_NOFLSH  0000200 +#define TARGET_TOSTOP  0000400 +#define TARGET_ECHOCTL 0001000 +#define TARGET_ECHOPRT 0002000 +#define TARGET_ECHOKE  0004000 +#define TARGET_FLUSHO  0010000 +#define TARGET_PENDIN  0040000 +#define TARGET_IEXTEN  0100000 + +/* c_cc character offsets */ +#define TARGET_VINTR	0 +#define TARGET_VQUIT	1 +#define TARGET_VERASE	2 +#define TARGET_VKILL	3 +#define TARGET_VEOF	4 +#define TARGET_VTIME	5 +#define TARGET_VMIN	6 +#define TARGET_VSWTC	7 +#define TARGET_VSTART	8 +#define TARGET_VSTOP	9 +#define TARGET_VSUSP	10 +#define TARGET_VEOL	11 +#define TARGET_VREPRINT	12 +#define TARGET_VDISCARD	13 +#define TARGET_VWERASE	14 +#define TARGET_VLNEXT	15 +#define TARGET_VEOL2	16 + +/* ioctls */ + +#define TARGET_TCGETS		0x5401 +#define TARGET_TCSETS		0x5402 +#define TARGET_TCSETSW		0x5403 +#define TARGET_TCSETSF		0x5404 +#define TARGET_TCGETA		0x5405 +#define TARGET_TCSETA		0x5406 +#define TARGET_TCSETAW		0x5407 +#define TARGET_TCSETAF		0x5408 +#define TARGET_TCSBRK		0x5409 +#define TARGET_TCXONC		0x540A +#define TARGET_TCFLSH		0x540B + +#define TARGET_TIOCEXCL	0x540C +#define TARGET_TIOCNXCL	0x540D +#define TARGET_TIOCSCTTY	0x540E +#define TARGET_TIOCGPGRP	0x540F +#define TARGET_TIOCSPGRP	0x5410 +#define TARGET_TIOCOUTQ	0x5411 +#define TARGET_TIOCSTI		0x5412 +#define TARGET_TIOCGWINSZ	0x5413 +#define TARGET_TIOCSWINSZ	0x5414 +#define TARGET_TIOCMGET	0x5415 +#define TARGET_TIOCMBIS	0x5416 +#define TARGET_TIOCMBIC	0x5417 +#define TARGET_TIOCMSET	0x5418 +#define TARGET_TIOCGSOFTCAR	0x5419 +#define TARGET_TIOCSSOFTCAR	0x541A +#define TARGET_FIONREAD	0x541B +#define TARGET_TIOCINQ		TARGET_FIONREAD +#define TARGET_TIOCLINUX	0x541C +#define TARGET_TIOCCONS	0x541D +#define TARGET_TIOCGSERIAL	0x541E +#define TARGET_TIOCSSERIAL	0x541F +#define TARGET_TIOCPKT		0x5420 +#define TARGET_FIONBIO		0x5421 +#define TARGET_TIOCNOTTY	0x5422 +#define TARGET_TIOCSETD	0x5423 +#define TARGET_TIOCGETD	0x5424 +#define TARGET_TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */ +#define TARGET_TIOCTTYGSTRUCT	0x5426  /* For debugging only */ +#define TARGET_TIOCSBRK	0x5427  /* BSD compatibility */ +#define TARGET_TIOCCBRK	0x5428  /* BSD compatibility */ +#define TARGET_TIOCGSID	0x5429  /* Return the session ID of FD */ +#define TARGET_TIOCGPTN	TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define TARGET_TIOCSPTLCK	TARGET_IOW('T',0x31, int)  /* Lock/unlock Pty */ + +#define TARGET_FIONCLEX	0x5450  /* these numbers need to be adjusted. */ +#define TARGET_FIOCLEX		0x5451 +#define TARGET_FIOASYNC	0x5452 +#define TARGET_TIOCSERCONFIG	0x5453 +#define TARGET_TIOCSERGWILD	0x5454 +#define TARGET_TIOCSERSWILD	0x5455 +#define TARGET_TIOCGLCKTRMIOS	0x5456 +#define TARGET_TIOCSLCKTRMIOS	0x5457 +#define TARGET_TIOCSERGSTRUCT	0x5458 /* For debugging only */ +#define TARGET_TIOCSERGETLSR   0x5459 /* Get line status register */ +#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config  */ +#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TARGET_TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */ +#define TARGET_TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */ +#define TARGET_TIOCGHAYESESP   0x545E  /* Get Hayes ESP configuration */ +#define TARGET_TIOCSHAYESESP   0x545F  /* Set Hayes ESP configuration */ + +/* Used for packet mode */ +#define TARGET_TIOCPKT_DATA		 0 +#define TARGET_TIOCPKT_FLUSHREAD	 1 +#define TARGET_TIOCPKT_FLUSHWRITE	 2 +#define TARGET_TIOCPKT_STOP		 4 +#define TARGET_TIOCPKT_START		 8 +#define TARGET_TIOCPKT_NOSTOP		16 +#define TARGET_TIOCPKT_DOSTOP		32 + +#define TARGET_TIOCSER_TEMT    0x01	/* Transmitter physically empty */ diff --git a/linux-user/mips/syscall.h b/linux-user/mips/syscall.h new file mode 100644 index 00000000..35ca23b1 --- /dev/null +++ b/linux-user/mips/syscall.h @@ -0,0 +1,233 @@ + +/* this struct defines the way the registers are stored on the +   stack during a system call. */ + +struct target_pt_regs { +	/* Pad bytes for argument save space on the stack. */ +	abi_ulong pad0[6]; + +	/* Saved main processor registers. */ +	abi_ulong regs[32]; + +	/* Saved special registers. */ +	abi_ulong cp0_status; +	abi_ulong lo; +	abi_ulong hi; +	abi_ulong cp0_badvaddr; +	abi_ulong cp0_cause; +	abi_ulong cp0_epc; +}; + +/* Target errno definitions taken from asm-mips/errno.h */ +#undef TARGET_ENOMSG +#define TARGET_ENOMSG          35      /* Identifier removed */ +#undef TARGET_EIDRM +#define TARGET_EIDRM           36      /* Identifier removed */ +#undef TARGET_ECHRNG +#define TARGET_ECHRNG          37      /* Channel number out of range */ +#undef TARGET_EL2NSYNC +#define TARGET_EL2NSYNC        38      /* Level 2 not synchronized */ +#undef TARGET_EL3HLT +#define TARGET_EL3HLT          39      /* Level 3 halted */ +#undef TARGET_EL3RST +#define TARGET_EL3RST          40      /* Level 3 reset */ +#undef TARGET_ELNRNG +#define TARGET_ELNRNG          41      /* Link number out of range */ +#undef TARGET_EUNATCH +#define TARGET_EUNATCH         42      /* Protocol driver not attached */ +#undef TARGET_ENOCSI +#define TARGET_ENOCSI          43      /* No CSI structure available */ +#undef TARGET_EL2HLT +#define TARGET_EL2HLT          44      /* Level 2 halted */ +#undef TARGET_EDEADLK +#define TARGET_EDEADLK         45      /* Resource deadlock would occur */ +#undef TARGET_ENOLCK +#define TARGET_ENOLCK          46      /* No record locks available */ +#undef TARGET_EBADE +#define TARGET_EBADE           50      /* Invalid exchange */ +#undef TARGET_EBADR +#define TARGET_EBADR           51      /* Invalid request descriptor */ +#undef TARGET_EXFULL +#define TARGET_EXFULL          52      /* TARGET_Exchange full */ +#undef TARGET_ENOANO +#define TARGET_ENOANO          53      /* No anode */ +#undef TARGET_EBADRQC +#define TARGET_EBADRQC         54      /* Invalid request code */ +#undef TARGET_EBADSLT +#define TARGET_EBADSLT         55      /* Invalid slot */ +#undef TARGET_EDEADLOCK +#define TARGET_EDEADLOCK       56      /* File locking deadlock error */ +#undef TARGET_EBFONT +#define TARGET_EBFONT          59      /* Bad font file format */ +#undef TARGET_ENOSTR +#define TARGET_ENOSTR          60      /* Device not a stream */ +#undef TARGET_ENODATA +#define TARGET_ENODATA         61      /* No data available */ +#undef TARGET_ETIME +#define TARGET_ETIME           62      /* Timer expired */ +#undef TARGET_ENOSR +#define TARGET_ENOSR           63      /* Out of streams resources */ +#undef TARGET_ENONET +#define TARGET_ENONET          64      /* Machine is not on the network */ +#undef TARGET_ENOPKG +#define TARGET_ENOPKG          65      /* Package not installed */ +#undef TARGET_EREMOTE +#define TARGET_EREMOTE         66      /* Object is remote */ +#undef TARGET_ENOLINK +#define TARGET_ENOLINK         67      /* Link has been severed */ +#undef TARGET_EADV +#define TARGET_EADV            68      /* Advertise error */ +#undef TARGET_ESRMNT +#define TARGET_ESRMNT          69      /* Srmount error */ +#undef TARGET_ECOMM +#define TARGET_ECOMM           70      /* Communication error on send */ +#undef TARGET_EPROTO +#define TARGET_EPROTO          71      /* Protocol error */ +#undef TARGET_EDOTDOT +#define TARGET_EDOTDOT         73      /* RFS specific error */ +#undef TARGET_EMULTIHOP +#define TARGET_EMULTIHOP       74      /* Multihop attempted */ +#undef TARGET_EBADMSG +#define TARGET_EBADMSG         77      /* Not a data message */ +#undef TARGET_ENAMETOOLONG +#define TARGET_ENAMETOOLONG    78      /* File name too long */ +#undef TARGET_EOVERFLOW +#define TARGET_EOVERFLOW       79      /* Value too large for defined data type */ +#undef TARGET_ENOTUNIQ +#define TARGET_ENOTUNIQ        80      /* Name not unique on network */ +#undef TARGET_EBADFD +#define TARGET_EBADFD          81      /* File descriptor in bad state */ +#undef TARGET_EREMCHG +#define TARGET_EREMCHG         82      /* Remote address changed */ +#undef TARGET_ELIBACC +#define TARGET_ELIBACC         83      /* Can not access a needed shared library */ +#undef TARGET_ELIBBAD +#define TARGET_ELIBBAD         84      /* Accessing a corrupted shared library */ +#undef TARGET_ELIBSCN +#define TARGET_ELIBSCN         85      /* .lib section in a.out corrupted */ +#undef TARGET_ELIBMAX +#define TARGET_ELIBMAX         86      /* Attempting to link in too many shared libraries */ +#undef TARGET_ELIBEXEC +#define TARGET_ELIBEXEC        87      /* Cannot exec a shared library directly */ +#undef TARGET_EILSEQ +#define TARGET_EILSEQ          88      /* Illegal byte sequence */ +#undef TARGET_ENOSYS +#define TARGET_ENOSYS          89      /* Function not implemented */ +#undef TARGET_ELOOP +#define TARGET_ELOOP           90      /* Too many symbolic links encountered */ +#undef TARGET_ERESTART +#define TARGET_ERESTART        91      /* Interrupted system call should be restarted */ +#undef TARGET_ESTRPIPE +#define TARGET_ESTRPIPE        92      /* Streams pipe error */ +#undef TARGET_ENOTEMPTY +#define TARGET_ENOTEMPTY       93      /* Directory not empty */ +#undef TARGET_EUSERS +#define TARGET_EUSERS          94      /* Too many users */ +#undef TARGET_ENOTSOCK +#define TARGET_ENOTSOCK        95      /* Socket operation on non-socket */ +#undef TARGET_EDESTADDRREQ +#define TARGET_EDESTADDRREQ    96      /* Destination address required */ +#undef TARGET_EMSGSIZE +#define TARGET_EMSGSIZE        97      /* Message too long */ +#undef TARGET_EPROTOTYPE +#define TARGET_EPROTOTYPE      98      /* Protocol wrong type for socket */ +#undef TARGET_ENOPROTOOPT +#define TARGET_ENOPROTOOPT     99      /* Protocol not available */ +#undef TARGET_EPROTONOSUPPORT +#define TARGET_EPROTONOSUPPORT 120     /* Protocol not supported */ +#undef TARGET_ESOCKTNOSUPPORT +#define TARGET_ESOCKTNOSUPPORT 121     /* Socket type not supported */ +#undef TARGET_EOPNOTSUPP +#define TARGET_EOPNOTSUPP      122     /* Operation not supported on transport endpoint */ +#undef TARGET_EPFNOSUPPORT +#define TARGET_EPFNOSUPPORT    123     /* Protocol family not supported */ +#undef TARGET_EAFNOSUPPORT +#define TARGET_EAFNOSUPPORT    124     /* Address family not supported by protocol */ +#undef TARGET_EADDRINUSE +#define TARGET_EADDRINUSE      125     /* Address already in use */ +#undef TARGET_EADDRNOTAVAIL +#define TARGET_EADDRNOTAVAIL   126     /* Cannot assign requested address */ +#undef TARGET_ENETDOWN +#define TARGET_ENETDOWN        127     /* Network is down */ +#undef TARGET_ENETUNREACH +#define TARGET_ENETUNREACH     128     /* Network is unreachable */ +#undef TARGET_ENETRESET +#define TARGET_ENETRESET       129     /* Network dropped connection because of reset */ +#undef TARGET_ECONNABORTED +#define TARGET_ECONNABORTED    130     /* Software caused connection abort */ +#undef TARGET_ECONNRESET +#define TARGET_ECONNRESET      131     /* Connection reset by peer */ +#undef TARGET_ENOBUFS +#define TARGET_ENOBUFS         132     /* No buffer space available */ +#undef TARGET_EISCONN +#define TARGET_EISCONN         133     /* Transport endpoint is already connected */ +#undef TARGET_ENOTCONN +#define TARGET_ENOTCONN        134     /* Transport endpoint is not connected */ +#undef TARGET_EUCLEAN +#define TARGET_EUCLEAN         135     /* Structure needs cleaning */ +#undef TARGET_ENOTNAM +#define TARGET_ENOTNAM         137     /* Not a XENIX named type file */ +#undef TARGET_ENAVAIL +#define TARGET_ENAVAIL         138     /* No XENIX semaphores available */ +#undef TARGET_EISNAM +#define TARGET_EISNAM          139     /* Is a named type file */ +#undef TARGET_EREMOTEIO +#define TARGET_EREMOTEIO       140     /* Remote I/O error */ +#undef TARGET_EINIT +#define TARGET_EINIT           141     /* Reserved */ +#undef TARGET_EREMDEV +#define TARGET_EREMDEV         142     /* TARGET_Error 142 */ +#undef TARGET_ESHUTDOWN +#define TARGET_ESHUTDOWN       143     /* Cannot send after transport endpoint shutdown */ +#undef TARGET_ETOOMANYREFS +#define TARGET_ETOOMANYREFS    144     /* Too many references: cannot splice */ +#undef TARGET_ETIMEDOUT +#define TARGET_ETIMEDOUT       145     /* Connection timed out */ +#undef TARGET_ECONNREFUSED +#define TARGET_ECONNREFUSED    146     /* Connection refused */ +#undef TARGET_EHOSTDOWN +#define TARGET_EHOSTDOWN       147     /* Host is down */ +#undef TARGET_EHOSTUNREACH +#define TARGET_EHOSTUNREACH    148     /* No route to host */ +#undef TARGET_EALREADY +#define TARGET_EALREADY        149     /* Operation already in progress */ +#undef TARGET_EINPROGRESS +#define TARGET_EINPROGRESS     150     /* Operation now in progress */ +#undef TARGET_ESTALE +#define TARGET_ESTALE          151     /* Stale NFS file handle */ +#undef TARGET_ECANCELED +#define TARGET_ECANCELED       158     /* AIO operation canceled */ +/* + * These error are Linux extensions. + */ +#undef TARGET_ENOMEDIUM +#define TARGET_ENOMEDIUM       159     /* No medium found */ +#undef TARGET_EMEDIUMTYPE +#define TARGET_EMEDIUMTYPE     160     /* Wrong medium type */ +#undef TARGET_ENOKEY +#define TARGET_ENOKEY          161     /* Required key not available */ +#undef TARGET_EKEYEXPIRED +#define TARGET_EKEYEXPIRED     162     /* Key has expired */ +#undef TARGET_EKEYREVOKED +#define TARGET_EKEYREVOKED     163     /* Key has been revoked */ +#undef TARGET_EKEYREJECTED +#define TARGET_EKEYREJECTED    164     /* Key was rejected by service */ + +/* for robust mutexes */ +#undef TARGET_EOWNERDEAD +#define TARGET_EOWNERDEAD      165     /* Owner died */ +#undef TARGET_ENOTRECOVERABLE +#define TARGET_ENOTRECOVERABLE 166     /* State not recoverable */ + + + +/* Nasty hack: define a fake errno value for use by sigreturn.  */ +#define TARGET_QEMU_ESIGRETURN 255 + +#define UNAME_MACHINE "mips" +#define UNAME_MINIMUM_RELEASE "2.6.32" + +#define TARGET_CLONE_BACKWARDS +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_MLOCKALL_MCL_CURRENT 1 +#define TARGET_MLOCKALL_MCL_FUTURE  2 diff --git a/linux-user/mips/syscall_nr.h b/linux-user/mips/syscall_nr.h new file mode 100644 index 00000000..2d1a13ee --- /dev/null +++ b/linux-user/mips/syscall_nr.h @@ -0,0 +1,353 @@ +/* + * Linux o32 style syscalls are in the range from 4000 to 4999. + */ +#define TARGET_NR_Linux			4000 +#define TARGET_NR_syscall		(TARGET_NR_Linux +   0) +#define TARGET_NR_exit			(TARGET_NR_Linux +   1) +#define TARGET_NR_fork			(TARGET_NR_Linux +   2) +#define TARGET_NR_read			(TARGET_NR_Linux +   3) +#define TARGET_NR_write			(TARGET_NR_Linux +   4) +#define TARGET_NR_open			(TARGET_NR_Linux +   5) +#define TARGET_NR_close			(TARGET_NR_Linux +   6) +#define TARGET_NR_waitpid		(TARGET_NR_Linux +   7) +#define TARGET_NR_creat			(TARGET_NR_Linux +   8) +#define TARGET_NR_link			(TARGET_NR_Linux +   9) +#define TARGET_NR_unlink		(TARGET_NR_Linux +  10) +#define TARGET_NR_execve		(TARGET_NR_Linux +  11) +#define TARGET_NR_chdir			(TARGET_NR_Linux +  12) +#define TARGET_NR_time			(TARGET_NR_Linux +  13) +#define TARGET_NR_mknod			(TARGET_NR_Linux +  14) +#define TARGET_NR_chmod			(TARGET_NR_Linux +  15) +#define TARGET_NR_lchown		(TARGET_NR_Linux +  16) +#define TARGET_NR_break			(TARGET_NR_Linux +  17) +#define TARGET_NR_unused18		(TARGET_NR_Linux +  18) +#define TARGET_NR_lseek			(TARGET_NR_Linux +  19) +#define TARGET_NR_getpid		(TARGET_NR_Linux +  20) +#define TARGET_NR_mount			(TARGET_NR_Linux +  21) +#define TARGET_NR_umount		(TARGET_NR_Linux +  22) +#define TARGET_NR_setuid		(TARGET_NR_Linux +  23) +#define TARGET_NR_getuid		(TARGET_NR_Linux +  24) +#define TARGET_NR_stime			(TARGET_NR_Linux +  25) +#define TARGET_NR_ptrace		(TARGET_NR_Linux +  26) +#define TARGET_NR_alarm			(TARGET_NR_Linux +  27) +#define TARGET_NR_unused28		(TARGET_NR_Linux +  28) +#define TARGET_NR_pause			(TARGET_NR_Linux +  29) +#define TARGET_NR_utime			(TARGET_NR_Linux +  30) +#define TARGET_NR_stty			(TARGET_NR_Linux +  31) +#define TARGET_NR_gtty			(TARGET_NR_Linux +  32) +#define TARGET_NR_access		(TARGET_NR_Linux +  33) +#define TARGET_NR_nice			(TARGET_NR_Linux +  34) +#define TARGET_NR_ftime			(TARGET_NR_Linux +  35) +#define TARGET_NR_sync			(TARGET_NR_Linux +  36) +#define TARGET_NR_kill			(TARGET_NR_Linux +  37) +#define TARGET_NR_rename		(TARGET_NR_Linux +  38) +#define TARGET_NR_mkdir			(TARGET_NR_Linux +  39) +#define TARGET_NR_rmdir			(TARGET_NR_Linux +  40) +#define TARGET_NR_dup			(TARGET_NR_Linux +  41) +#define TARGET_NR_pipe			(TARGET_NR_Linux +  42) +#define TARGET_NR_times			(TARGET_NR_Linux +  43) +#define TARGET_NR_prof			(TARGET_NR_Linux +  44) +#define TARGET_NR_brk			(TARGET_NR_Linux +  45) +#define TARGET_NR_setgid		(TARGET_NR_Linux +  46) +#define TARGET_NR_getgid		(TARGET_NR_Linux +  47) +#define TARGET_NR_signal		(TARGET_NR_Linux +  48) +#define TARGET_NR_geteuid		(TARGET_NR_Linux +  49) +#define TARGET_NR_getegid		(TARGET_NR_Linux +  50) +#define TARGET_NR_acct			(TARGET_NR_Linux +  51) +#define TARGET_NR_umount2		(TARGET_NR_Linux +  52) +#define TARGET_NR_lock			(TARGET_NR_Linux +  53) +#define TARGET_NR_ioctl			(TARGET_NR_Linux +  54) +#define TARGET_NR_fcntl			(TARGET_NR_Linux +  55) +#define TARGET_NR_mpx			(TARGET_NR_Linux +  56) +#define TARGET_NR_setpgid		(TARGET_NR_Linux +  57) +#define TARGET_NR_ulimit		(TARGET_NR_Linux +  58) +#define TARGET_NR_unused59		(TARGET_NR_Linux +  59) +#define TARGET_NR_umask			(TARGET_NR_Linux +  60) +#define TARGET_NR_chroot		(TARGET_NR_Linux +  61) +#define TARGET_NR_ustat			(TARGET_NR_Linux +  62) +#define TARGET_NR_dup2			(TARGET_NR_Linux +  63) +#define TARGET_NR_getppid		(TARGET_NR_Linux +  64) +#define TARGET_NR_getpgrp		(TARGET_NR_Linux +  65) +#define TARGET_NR_setsid		(TARGET_NR_Linux +  66) +#define TARGET_NR_sigaction		(TARGET_NR_Linux +  67) +#define TARGET_NR_sgetmask		(TARGET_NR_Linux +  68) +#define TARGET_NR_ssetmask		(TARGET_NR_Linux +  69) +#define TARGET_NR_setreuid		(TARGET_NR_Linux +  70) +#define TARGET_NR_setregid		(TARGET_NR_Linux +  71) +#define TARGET_NR_sigsuspend		(TARGET_NR_Linux +  72) +#define TARGET_NR_sigpending		(TARGET_NR_Linux +  73) +#define TARGET_NR_sethostname		(TARGET_NR_Linux +  74) +#define TARGET_NR_setrlimit		(TARGET_NR_Linux +  75) +#define TARGET_NR_getrlimit		(TARGET_NR_Linux +  76) +#define TARGET_NR_getrusage		(TARGET_NR_Linux +  77) +#define TARGET_NR_gettimeofday		(TARGET_NR_Linux +  78) +#define TARGET_NR_settimeofday		(TARGET_NR_Linux +  79) +#define TARGET_NR_getgroups		(TARGET_NR_Linux +  80) +#define TARGET_NR_setgroups		(TARGET_NR_Linux +  81) +#define TARGET_NR_reserved82		(TARGET_NR_Linux +  82) +#define TARGET_NR_symlink		(TARGET_NR_Linux +  83) +#define TARGET_NR_unused84		(TARGET_NR_Linux +  84) +#define TARGET_NR_readlink		(TARGET_NR_Linux +  85) +#define TARGET_NR_uselib		(TARGET_NR_Linux +  86) +#define TARGET_NR_swapon		(TARGET_NR_Linux +  87) +#define TARGET_NR_reboot		(TARGET_NR_Linux +  88) +#define TARGET_NR_readdir		(TARGET_NR_Linux +  89) +#define TARGET_NR_mmap			(TARGET_NR_Linux +  90) +#define TARGET_NR_munmap		(TARGET_NR_Linux +  91) +#define TARGET_NR_truncate		(TARGET_NR_Linux +  92) +#define TARGET_NR_ftruncate		(TARGET_NR_Linux +  93) +#define TARGET_NR_fchmod		(TARGET_NR_Linux +  94) +#define TARGET_NR_fchown		(TARGET_NR_Linux +  95) +#define TARGET_NR_getpriority		(TARGET_NR_Linux +  96) +#define TARGET_NR_setpriority		(TARGET_NR_Linux +  97) +#define TARGET_NR_profil		(TARGET_NR_Linux +  98) +#define TARGET_NR_statfs		(TARGET_NR_Linux +  99) +#define TARGET_NR_fstatfs		(TARGET_NR_Linux + 100) +#define TARGET_NR_ioperm		(TARGET_NR_Linux + 101) +#define TARGET_NR_socketcall		(TARGET_NR_Linux + 102) +#define TARGET_NR_syslog		(TARGET_NR_Linux + 103) +#define TARGET_NR_setitimer		(TARGET_NR_Linux + 104) +#define TARGET_NR_getitimer		(TARGET_NR_Linux + 105) +#define TARGET_NR_stat			(TARGET_NR_Linux + 106) +#define TARGET_NR_lstat			(TARGET_NR_Linux + 107) +#define TARGET_NR_fstat			(TARGET_NR_Linux + 108) +#define TARGET_NR_unused109		(TARGET_NR_Linux + 109) +#define TARGET_NR_iopl			(TARGET_NR_Linux + 110) +#define TARGET_NR_vhangup		(TARGET_NR_Linux + 111) +#define TARGET_NR_idle			(TARGET_NR_Linux + 112) +#define TARGET_NR_vm86			(TARGET_NR_Linux + 113) +#define TARGET_NR_wait4			(TARGET_NR_Linux + 114) +#define TARGET_NR_swapoff		(TARGET_NR_Linux + 115) +#define TARGET_NR_sysinfo		(TARGET_NR_Linux + 116) +#define TARGET_NR_ipc			(TARGET_NR_Linux + 117) +#define TARGET_NR_fsync			(TARGET_NR_Linux + 118) +#define TARGET_NR_sigreturn		(TARGET_NR_Linux + 119) +#define TARGET_NR_clone			(TARGET_NR_Linux + 120) +#define TARGET_NR_setdomainname		(TARGET_NR_Linux + 121) +#define TARGET_NR_uname			(TARGET_NR_Linux + 122) +#define TARGET_NR_modify_ldt		(TARGET_NR_Linux + 123) +#define TARGET_NR_adjtimex		(TARGET_NR_Linux + 124) +#define TARGET_NR_mprotect		(TARGET_NR_Linux + 125) +#define TARGET_NR_sigprocmask		(TARGET_NR_Linux + 126) +#define TARGET_NR_create_module		(TARGET_NR_Linux + 127) +#define TARGET_NR_init_module		(TARGET_NR_Linux + 128) +#define TARGET_NR_delete_module		(TARGET_NR_Linux + 129) +#define TARGET_NR_get_kernel_syms	(TARGET_NR_Linux + 130) +#define TARGET_NR_quotactl		(TARGET_NR_Linux + 131) +#define TARGET_NR_getpgid		(TARGET_NR_Linux + 132) +#define TARGET_NR_fchdir		(TARGET_NR_Linux + 133) +#define TARGET_NR_bdflush		(TARGET_NR_Linux + 134) +#define TARGET_NR_sysfs			(TARGET_NR_Linux + 135) +#define TARGET_NR_personality		(TARGET_NR_Linux + 136) +#define TARGET_NR_afs_syscall		(TARGET_NR_Linux + 137) /* Syscall for Andrew File System */ +#define TARGET_NR_setfsuid		(TARGET_NR_Linux + 138) +#define TARGET_NR_setfsgid		(TARGET_NR_Linux + 139) +#define TARGET_NR__llseek		(TARGET_NR_Linux + 140) +#define TARGET_NR_getdents		(TARGET_NR_Linux + 141) +#define TARGET_NR__newselect		(TARGET_NR_Linux + 142) +#define TARGET_NR_flock			(TARGET_NR_Linux + 143) +#define TARGET_NR_msync			(TARGET_NR_Linux + 144) +#define TARGET_NR_readv			(TARGET_NR_Linux + 145) +#define TARGET_NR_writev		(TARGET_NR_Linux + 146) +#define TARGET_NR_cacheflush		(TARGET_NR_Linux + 147) +#define TARGET_NR_cachectl		(TARGET_NR_Linux + 148) +#define TARGET_NR_sysmips		(TARGET_NR_Linux + 149) +#define TARGET_NR_unused150		(TARGET_NR_Linux + 150) +#define TARGET_NR_getsid		(TARGET_NR_Linux + 151) +#define TARGET_NR_fdatasync		(TARGET_NR_Linux + 152) +#define TARGET_NR__sysctl		(TARGET_NR_Linux + 153) +#define TARGET_NR_mlock			(TARGET_NR_Linux + 154) +#define TARGET_NR_munlock		(TARGET_NR_Linux + 155) +#define TARGET_NR_mlockall		(TARGET_NR_Linux + 156) +#define TARGET_NR_munlockall		(TARGET_NR_Linux + 157) +#define TARGET_NR_sched_setparam	(TARGET_NR_Linux + 158) +#define TARGET_NR_sched_getparam	(TARGET_NR_Linux + 159) +#define TARGET_NR_sched_setscheduler	(TARGET_NR_Linux + 160) +#define TARGET_NR_sched_getscheduler	(TARGET_NR_Linux + 161) +#define TARGET_NR_sched_yield		(TARGET_NR_Linux + 162) +#define TARGET_NR_sched_get_priority_max	(TARGET_NR_Linux + 163) +#define TARGET_NR_sched_get_priority_min	(TARGET_NR_Linux + 164) +#define TARGET_NR_sched_rr_get_interval	(TARGET_NR_Linux + 165) +#define TARGET_NR_nanosleep		(TARGET_NR_Linux + 166) +#define TARGET_NR_mremap		(TARGET_NR_Linux + 167) +#define TARGET_NR_accept		(TARGET_NR_Linux + 168) +#define TARGET_NR_bind			(TARGET_NR_Linux + 169) +#define TARGET_NR_connect		(TARGET_NR_Linux + 170) +#define TARGET_NR_getpeername		(TARGET_NR_Linux + 171) +#define TARGET_NR_getsockname		(TARGET_NR_Linux + 172) +#define TARGET_NR_getsockopt		(TARGET_NR_Linux + 173) +#define TARGET_NR_listen		(TARGET_NR_Linux + 174) +#define TARGET_NR_recv			(TARGET_NR_Linux + 175) +#define TARGET_NR_recvfrom		(TARGET_NR_Linux + 176) +#define TARGET_NR_recvmsg		(TARGET_NR_Linux + 177) +#define TARGET_NR_send			(TARGET_NR_Linux + 178) +#define TARGET_NR_sendmsg		(TARGET_NR_Linux + 179) +#define TARGET_NR_sendto		(TARGET_NR_Linux + 180) +#define TARGET_NR_setsockopt		(TARGET_NR_Linux + 181) +#define TARGET_NR_shutdown		(TARGET_NR_Linux + 182) +#define TARGET_NR_socket		(TARGET_NR_Linux + 183) +#define TARGET_NR_socketpair		(TARGET_NR_Linux + 184) +#define TARGET_NR_setresuid		(TARGET_NR_Linux + 185) +#define TARGET_NR_getresuid		(TARGET_NR_Linux + 186) +#define TARGET_NR_query_module		(TARGET_NR_Linux + 187) +#define TARGET_NR_poll			(TARGET_NR_Linux + 188) +#define TARGET_NR_nfsservctl		(TARGET_NR_Linux + 189) +#define TARGET_NR_setresgid		(TARGET_NR_Linux + 190) +#define TARGET_NR_getresgid		(TARGET_NR_Linux + 191) +#define TARGET_NR_prctl			(TARGET_NR_Linux + 192) +#define TARGET_NR_rt_sigreturn		(TARGET_NR_Linux + 193) +#define TARGET_NR_rt_sigaction		(TARGET_NR_Linux + 194) +#define TARGET_NR_rt_sigprocmask	(TARGET_NR_Linux + 195) +#define TARGET_NR_rt_sigpending		(TARGET_NR_Linux + 196) +#define TARGET_NR_rt_sigtimedwait	(TARGET_NR_Linux + 197) +#define TARGET_NR_rt_sigqueueinfo	(TARGET_NR_Linux + 198) +#define TARGET_NR_rt_sigsuspend		(TARGET_NR_Linux + 199) +#define TARGET_NR_pread64		(TARGET_NR_Linux + 200) +#define TARGET_NR_pwrite64		(TARGET_NR_Linux + 201) +#define TARGET_NR_chown 		(TARGET_NR_Linux + 202) +#define TARGET_NR_getcwd		(TARGET_NR_Linux + 203) +#define TARGET_NR_capget		(TARGET_NR_Linux + 204) +#define TARGET_NR_capset		(TARGET_NR_Linux + 205) +#define TARGET_NR_sigaltstack		(TARGET_NR_Linux + 206) +#define TARGET_NR_sendfile		(TARGET_NR_Linux + 207) +#define TARGET_NR_getpmsg		(TARGET_NR_Linux + 208) +#define TARGET_NR_putpmsg		(TARGET_NR_Linux + 209) +#define TARGET_NR_mmap2			(TARGET_NR_Linux + 210) +#define TARGET_NR_truncate64		(TARGET_NR_Linux + 211) +#define TARGET_NR_ftruncate64		(TARGET_NR_Linux + 212) +#define TARGET_NR_stat64		(TARGET_NR_Linux + 213) +#define TARGET_NR_lstat64		(TARGET_NR_Linux + 214) +#define TARGET_NR_fstat64		(TARGET_NR_Linux + 215) +#define TARGET_NR_pivot_root		(TARGET_NR_Linux + 216) +#define TARGET_NR_mincore		(TARGET_NR_Linux + 217) +#define TARGET_NR_madvise		(TARGET_NR_Linux + 218) +#define TARGET_NR_getdents64		(TARGET_NR_Linux + 219) +#define TARGET_NR_fcntl64		(TARGET_NR_Linux + 220) +#define TARGET_NR_reserved221		(TARGET_NR_Linux + 221) +#define TARGET_NR_gettid		(TARGET_NR_Linux + 222) +#define TARGET_NR_readahead		(TARGET_NR_Linux + 223) +#define TARGET_NR_setxattr		(TARGET_NR_Linux + 224) +#define TARGET_NR_lsetxattr		(TARGET_NR_Linux + 225) +#define TARGET_NR_fsetxattr		(TARGET_NR_Linux + 226) +#define TARGET_NR_getxattr		(TARGET_NR_Linux + 227) +#define TARGET_NR_lgetxattr		(TARGET_NR_Linux + 228) +#define TARGET_NR_fgetxattr		(TARGET_NR_Linux + 229) +#define TARGET_NR_listxattr		(TARGET_NR_Linux + 230) +#define TARGET_NR_llistxattr		(TARGET_NR_Linux + 231) +#define TARGET_NR_flistxattr		(TARGET_NR_Linux + 232) +#define TARGET_NR_removexattr		(TARGET_NR_Linux + 233) +#define TARGET_NR_lremovexattr		(TARGET_NR_Linux + 234) +#define TARGET_NR_fremovexattr		(TARGET_NR_Linux + 235) +#define TARGET_NR_tkill			(TARGET_NR_Linux + 236) +#define TARGET_NR_sendfile64		(TARGET_NR_Linux + 237) +#define TARGET_NR_futex			(TARGET_NR_Linux + 238) +#define TARGET_NR_sched_setaffinity	(TARGET_NR_Linux + 239) +#define TARGET_NR_sched_getaffinity	(TARGET_NR_Linux + 240) +#define TARGET_NR_io_setup		(TARGET_NR_Linux + 241) +#define TARGET_NR_io_destroy		(TARGET_NR_Linux + 242) +#define TARGET_NR_io_getevents		(TARGET_NR_Linux + 243) +#define TARGET_NR_io_submit		(TARGET_NR_Linux + 244) +#define TARGET_NR_io_cancel		(TARGET_NR_Linux + 245) +#define TARGET_NR_exit_group		(TARGET_NR_Linux + 246) +#define TARGET_NR_lookup_dcookie	(TARGET_NR_Linux + 247) +#define TARGET_NR_epoll_create		(TARGET_NR_Linux + 248) +#define TARGET_NR_epoll_ctl		(TARGET_NR_Linux + 249) +#define TARGET_NR_epoll_wait		(TARGET_NR_Linux + 250) +#define TARGET_NR_remap_file_pages	(TARGET_NR_Linux + 251) +#define TARGET_NR_set_tid_address	(TARGET_NR_Linux + 252) +#define TARGET_NR_restart_syscall	(TARGET_NR_Linux + 253) +#define TARGET_NR_fadvise64		(TARGET_NR_Linux + 254) +#define TARGET_NR_statfs64		(TARGET_NR_Linux + 255) +#define TARGET_NR_fstatfs64		(TARGET_NR_Linux + 256) +#define TARGET_NR_timer_create		(TARGET_NR_Linux + 257) +#define TARGET_NR_timer_settime		(TARGET_NR_Linux + 258) +#define TARGET_NR_timer_gettime		(TARGET_NR_Linux + 259) +#define TARGET_NR_timer_getoverrun	(TARGET_NR_Linux + 260) +#define TARGET_NR_timer_delete		(TARGET_NR_Linux + 261) +#define TARGET_NR_clock_settime		(TARGET_NR_Linux + 262) +#define TARGET_NR_clock_gettime		(TARGET_NR_Linux + 263) +#define TARGET_NR_clock_getres		(TARGET_NR_Linux + 264) +#define TARGET_NR_clock_nanosleep	(TARGET_NR_Linux + 265) +#define TARGET_NR_tgkill		(TARGET_NR_Linux + 266) +#define TARGET_NR_utimes		(TARGET_NR_Linux + 267) +#define TARGET_NR_mbind			(TARGET_NR_Linux + 268) +#define TARGET_NR_get_mempolicy		(TARGET_NR_Linux + 269) +#define TARGET_NR_set_mempolicy		(TARGET_NR_Linux + 270) +#define TARGET_NR_mq_open		(TARGET_NR_Linux + 271) +#define TARGET_NR_mq_unlink		(TARGET_NR_Linux + 272) +#define TARGET_NR_mq_timedsend		(TARGET_NR_Linux + 273) +#define TARGET_NR_mq_timedreceive	(TARGET_NR_Linux + 274) +#define TARGET_NR_mq_notify		(TARGET_NR_Linux + 275) +#define TARGET_NR_mq_getsetattr		(TARGET_NR_Linux + 276) +#define TARGET_NR_vserver		(TARGET_NR_Linux + 277) +#define TARGET_NR_waitid		(TARGET_NR_Linux + 278) +/* #define TARGET_NR_sys_setaltroot	(TARGET_NR_Linux + 279) */ +#define TARGET_NR_add_key		(TARGET_NR_Linux + 280) +#define TARGET_NR_request_key		(TARGET_NR_Linux + 281) +#define TARGET_NR_keyctl		(TARGET_NR_Linux + 282) +#define TARGET_NR_set_thread_area	(TARGET_NR_Linux + 283) +#define TARGET_NR_inotify_init		(TARGET_NR_Linux + 284) +#define TARGET_NR_inotify_add_watch	(TARGET_NR_Linux + 285) +#define TARGET_NR_inotify_rm_watch	(TARGET_NR_Linux + 286) +#define TARGET_NR_migrate_pages		(TARGET_NR_Linux + 287) +#define TARGET_NR_openat		(TARGET_NR_Linux + 288) +#define TARGET_NR_mkdirat		(TARGET_NR_Linux + 289) +#define TARGET_NR_mknodat		(TARGET_NR_Linux + 290) +#define TARGET_NR_fchownat		(TARGET_NR_Linux + 291) +#define TARGET_NR_futimesat		(TARGET_NR_Linux + 292) +#define TARGET_NR_fstatat64		(TARGET_NR_Linux + 293) +#define TARGET_NR_unlinkat		(TARGET_NR_Linux + 294) +#define TARGET_NR_renameat		(TARGET_NR_Linux + 295) +#define TARGET_NR_linkat		(TARGET_NR_Linux + 296) +#define TARGET_NR_symlinkat		(TARGET_NR_Linux + 297) +#define TARGET_NR_readlinkat		(TARGET_NR_Linux + 298) +#define TARGET_NR_fchmodat		(TARGET_NR_Linux + 299) +#define TARGET_NR_faccessat		(TARGET_NR_Linux + 300) +#define TARGET_NR_pselect6		(TARGET_NR_Linux + 301) +#define TARGET_NR_ppoll			(TARGET_NR_Linux + 302) +#define TARGET_NR_unshare		(TARGET_NR_Linux + 303) +#define TARGET_NR_splice		(TARGET_NR_Linux + 304) +#define TARGET_NR_sync_file_range	(TARGET_NR_Linux + 305) +#define TARGET_NR_tee			(TARGET_NR_Linux + 306) +#define TARGET_NR_vmsplice		(TARGET_NR_Linux + 307) +#define TARGET_NR_move_pages		(TARGET_NR_Linux + 308) +#define TARGET_NR_set_robust_list	(TARGET_NR_Linux + 309) +#define TARGET_NR_get_robust_list	(TARGET_NR_Linux + 310) +#define TARGET_NR_kexec_load		(TARGET_NR_Linux + 311) +#define TARGET_NR_getcpu		(TARGET_NR_Linux + 312) +#define TARGET_NR_epoll_pwait		(TARGET_NR_Linux + 313) +#define TARGET_NR_ioprio_set		(TARGET_NR_Linux + 314) +#define TARGET_NR_ioprio_get		(TARGET_NR_Linux + 315) +#define TARGET_NR_utimensat		(TARGET_NR_Linux + 316) +#define TARGET_NR_signalfd		(TARGET_NR_Linux + 317) +#define TARGET_NR_timerfd		(TARGET_NR_Linux + 318) +#define TARGET_NR_eventfd		(TARGET_NR_Linux + 319) +#define TARGET_NR_fallocate		(TARGET_NR_Linux + 320) +#define TARGET_NR_timerfd_create	(TARGET_NR_Linux + 321) +#define TARGET_NR_timerfd_gettime	(TARGET_NR_Linux + 322) +#define TARGET_NR_timerfd_settime	(TARGET_NR_Linux + 323) +#define TARGET_NR_signalfd4		(TARGET_NR_Linux + 324) +#define TARGET_NR_eventfd2		(TARGET_NR_Linux + 325) +#define TARGET_NR_epoll_create1	(TARGET_NR_Linux + 326) +#define TARGET_NR_dup3			(TARGET_NR_Linux + 327) +#define TARGET_NR_pipe2		(TARGET_NR_Linux + 328) +#define TARGET_NR_inotify_init1	(TARGET_NR_Linux + 329) +#define TARGET_NR_preadv                (TARGET_NR_Linux + 330) +#define TARGET_NR_pwritev               (TARGET_NR_Linux + 331) +#define TARGET_NR_rt_tgsigqueueinfo     (TARGET_NR_Linux + 332) +#define TARGET_NR_perf_event_open       (TARGET_NR_Linux + 333) +#define TARGET_NR_accept4               (TARGET_NR_Linux + 334) +#define TARGET_NR_recvmmsg              (TARGET_NR_Linux + 335) +#define TARGET_NR_fanotify_init         (TARGET_NR_Linux + 336) +#define TARGET_NR_fanotify_mark         (TARGET_NR_Linux + 337) +#define TARGET_NR_prlimit64             (TARGET_NR_Linux + 338) +#define TARGET_NR_name_to_handle_at     (TARGET_NR_Linux + 339) +#define TARGET_NR_open_by_handle_at     (TARGET_NR_Linux + 340) +#define TARGET_NR_clock_adjtime         (TARGET_NR_Linux + 341) +#define TARGET_NR_syncfs                (TARGET_NR_Linux + 342) +#define TARGET_NR_sendmmsg              (TARGET_NR_Linux + 343) +#define TARGET_NR_setns                 (TARGET_NR_Linux + 344) +#define TARGET_NR_process_vm_readv      (TARGET_NR_Linux + 345) +#define TARGET_NR_process_vm_writev     (TARGET_NR_Linux + 346) +#define TARGET_NR_kcmp                  (TARGET_NR_Linux + 347) +#define TARGET_NR_finit_module          (TARGET_NR_Linux + 348) diff --git a/linux-user/mips/target_cpu.h b/linux-user/mips/target_cpu.h new file mode 100644 index 00000000..19b88550 --- /dev/null +++ b/linux-user/mips/target_cpu.h @@ -0,0 +1,36 @@ +/* + * MIPS specific CPU ABI and functions for linux-user + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUMIPSState *env, target_ulong newsp) +{ +    if (newsp) { +        env->active_tc.gpr[29] = newsp; +    } +    env->active_tc.gpr[7] = 0; +    env->active_tc.gpr[2] = 0; +} + +static inline void cpu_set_tls(CPUMIPSState *env, target_ulong newtls) +{ +    env->active_tc.CP0_UserLocal = newtls; +} + +#endif diff --git a/linux-user/mips/target_signal.h b/linux-user/mips/target_signal.h new file mode 100644 index 00000000..6e1dc8b6 --- /dev/null +++ b/linux-user/mips/target_signal.h @@ -0,0 +1,29 @@ +#ifndef TARGET_SIGNAL_H +#define TARGET_SIGNAL_H + +#include "cpu.h" + +/* this struct defines a stack used during syscall handling */ + +typedef struct target_sigaltstack { +	abi_long ss_sp; +	abi_ulong ss_size; +	abi_long ss_flags; +} target_stack_t; + + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK     1 +#define TARGET_SS_DISABLE     2 + +#define TARGET_MINSIGSTKSZ    2048 +#define TARGET_SIGSTKSZ       8192 + +static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state) +{ +    return state->active_tc.gpr[29]; +} + +#endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/mips/target_structs.h b/linux-user/mips/target_structs.h new file mode 100644 index 00000000..16021e8a --- /dev/null +++ b/linux-user/mips/target_structs.h @@ -0,0 +1,48 @@ +/* + * MIPS specific structures for linux-user + * + * Copyright (c) 2013 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_STRUCTS_H +#define TARGET_STRUCTS_H + +struct target_ipc_perm { +    abi_int __key;                      /* Key.  */ +    abi_uint uid;                       /* Owner's user ID.  */ +    abi_uint gid;                       /* Owner's group ID.  */ +    abi_uint cuid;                      /* Creator's user ID.  */ +    abi_uint cgid;                      /* Creator's group ID.  */ +    abi_uint mode;                      /* Read/write permission.  */ +    abi_ushort __seq;                   /* Sequence number.  */ +    abi_ushort __pad1; +    abi_ulong __unused1; +    abi_ulong __unused2; +}; + +struct target_shmid_ds { +    struct target_ipc_perm shm_perm;    /* operation permission struct */ +    abi_long shm_segsz;                 /* size of segment in bytes */ +    abi_ulong shm_atime;                /* time of last shmat() */ +    abi_ulong shm_dtime;                /* time of last shmdt() */ +    abi_ulong shm_ctime;                /* time of last change by shmctl() */ +    abi_int shm_cpid;                   /* pid of creator */ +    abi_int shm_lpid;                   /* pid of last shmop */ +    abi_ulong shm_nattch;               /* number of current attaches */ +    abi_ulong __unused1; +    abi_ulong __unused2; +}; + +#endif diff --git a/linux-user/mips/termbits.h b/linux-user/mips/termbits.h new file mode 100644 index 00000000..d3a6cf8f --- /dev/null +++ b/linux-user/mips/termbits.h @@ -0,0 +1,245 @@ +/* from asm/termbits.h */ + +#define TARGET_NCCS 23 + +struct target_termios { +    unsigned int c_iflag;               /* input mode flags */ +    unsigned int c_oflag;               /* output mode flags */ +    unsigned int c_cflag;               /* control mode flags */ +    unsigned int c_lflag;               /* local mode flags */ +    unsigned char c_line;                    /* line discipline */ +    unsigned char c_cc[TARGET_NCCS];                /* control characters */ +}; + +/* c_iflag bits */ +#define TARGET_IGNBRK  0000001 +#define TARGET_BRKINT  0000002 +#define TARGET_IGNPAR  0000004 +#define TARGET_PARMRK  0000010 +#define TARGET_INPCK   0000020 +#define TARGET_ISTRIP  0000040 +#define TARGET_INLCR   0000100 +#define TARGET_IGNCR   0000200 +#define TARGET_ICRNL   0000400 +#define TARGET_IUCLC   0001000 +#define TARGET_IXON    0002000 +#define TARGET_IXANY   0004000 +#define TARGET_IXOFF   0010000 +#define TARGET_IMAXBEL 0020000 +#define TARGET_IUTF8   0040000 + +/* c_oflag bits */ +#define TARGET_OPOST   0000001 +#define TARGET_OLCUC   0000002 +#define TARGET_ONLCR   0000004 +#define TARGET_OCRNL   0000010 +#define TARGET_ONOCR   0000020 +#define TARGET_ONLRET  0000040 +#define TARGET_OFILL   0000100 +#define TARGET_OFDEL   0000200 +#define TARGET_NLDLY   0000400 +#define   TARGET_NL0   0000000 +#define   TARGET_NL1   0000400 +#define TARGET_CRDLY   0003000 +#define   TARGET_CR0   0000000 +#define   TARGET_CR1   0001000 +#define   TARGET_CR2   0002000 +#define   TARGET_CR3   0003000 +#define TARGET_TABDLY  0014000 +#define   TARGET_TAB0  0000000 +#define   TARGET_TAB1  0004000 +#define   TARGET_TAB2  0010000 +#define   TARGET_TAB3  0014000 +#define   TARGET_XTABS 0014000 +#define TARGET_BSDLY   0020000 +#define   TARGET_BS0   0000000 +#define   TARGET_BS1   0020000 +#define TARGET_VTDLY   0040000 +#define   TARGET_VT0   0000000 +#define   TARGET_VT1   0040000 +#define TARGET_FFDLY   0100000 +#define   TARGET_FF0   0000000 +#define   TARGET_FF1   0100000 + +/* c_cflag bit meaning */ +#define TARGET_CBAUD   0010017 +#define  TARGET_B0     0000000         /* hang up */ +#define  TARGET_B50    0000001 +#define  TARGET_B75    0000002 +#define  TARGET_B110   0000003 +#define  TARGET_B134   0000004 +#define  TARGET_B150   0000005 +#define  TARGET_B200   0000006 +#define  TARGET_B300   0000007 +#define  TARGET_B600   0000010 +#define  TARGET_B1200  0000011 +#define  TARGET_B1800  0000012 +#define  TARGET_B2400  0000013 +#define  TARGET_B4800  0000014 +#define  TARGET_B9600  0000015 +#define  TARGET_B19200 0000016 +#define  TARGET_B38400 0000017 +#define TARGET_EXTA B19200 +#define TARGET_EXTB B38400 +#define TARGET_CSIZE   0000060 +#define   TARGET_CS5   0000000 +#define   TARGET_CS6   0000020 +#define   TARGET_CS7   0000040 +#define   TARGET_CS8   0000060 +#define TARGET_CSTOPB  0000100 +#define TARGET_CREAD   0000200 +#define TARGET_PARENB  0000400 +#define TARGET_PARODD  0001000 +#define TARGET_HUPCL   0002000 +#define TARGET_CLOCAL  0004000 +#define TARGET_CBAUDEX 0010000 +#define  TARGET_BOTHER   0010000 +#define  TARGET_B57600   0010001 +#define  TARGET_B115200  0010002 +#define  TARGET_B230400  0010003 +#define  TARGET_B460800  0010004 +#define  TARGET_B500000  0010005 +#define  TARGET_B576000  0010006 +#define  TARGET_B921600  0010007 +#define  TARGET_B1000000 0010010 +#define  TARGET_B1152000 0010011 +#define  TARGET_B1500000 0010012 +#define  TARGET_B2000000 0010013 +#define  TARGET_B2500000 0010014 +#define  TARGET_B3000000 0010015 +#define  TARGET_B3500000 0010016 +#define  TARGET_B4000000 0010017 +#define TARGET_CIBAUD    002003600000  /* input baud rate (not used) */ +#define TARGET_CMSPAR    010000000000  /* mark or space (stick) parity */ +#define TARGET_CRTSCTS   020000000000  /* flow control */ + +/* c_lflag bits */ +#define TARGET_ISIG    0000001 +#define TARGET_ICANON  0000002 +#define TARGET_XCASE   0000004 +#define TARGET_ECHO    0000010 +#define TARGET_ECHOE   0000020 +#define TARGET_ECHOK   0000040 +#define TARGET_ECHONL  0000100 +#define TARGET_NOFLSH  0000200 +#define TARGET_IEXTEN  0000400 +#define TARGET_ECHOCTL 0001000 +#define TARGET_ECHOPRT 0002000 +#define TARGET_ECHOKE  0004000 +#define TARGET_FLUSHO  0010000 +#define TARGET_PENDIN  0040000 +#define TARGET_TOSTOP  0100000 +#define TARGET_ITOSTOP TARGET_TOSTOP + +/* c_cc character offsets */ +#define TARGET_VINTR	0 +#define TARGET_VQUIT	1 +#define TARGET_VERASE	2 +#define TARGET_VKILL	3 +#define TARGET_VMIN	4 +#define TARGET_VTIME	5 +#define TARGET_VEOL2	6 +#define TARGET_VSWTC	7 +#define TARGET_VSTART	8 +#define TARGET_VSTOP	9 +#define TARGET_VSUSP	10 +/* VDSUSP not supported */ +#define TARGET_VREPRINT	12 +#define TARGET_VDISCARD	13 +#define TARGET_VWERASE	14 +#define TARGET_VLNEXT	15 +#define TARGET_VEOF	16 +#define TARGET_VEOL	17 + +/* ioctls */ + +#define TARGET_TCGETA		0x5401 +#define TARGET_TCSETA		0x5402	/* Clashes with SNDCTL_TMR_START sound ioctl */ +#define TARGET_TCSETAW		0x5403 +#define TARGET_TCSETAF		0x5404 + +#define TARGET_TCSBRK		0x5405 +#define TARGET_TCXONC		0x5406 +#define TARGET_TCFLSH		0x5407 + +#define TARGET_TCGETS		0x540d +#define TARGET_TCSETS		0x540e +#define TARGET_TCSETSW		0x540f +#define TARGET_TCSETSF		0x5410 + +#define TARGET_TIOCEXCL	0x740d		/* set exclusive use of tty */ +#define TARGET_TIOCNXCL	0x740e		/* reset exclusive use of tty */ +#define TARGET_TIOCOUTQ	0x7472		/* output queue size */ +#define TARGET_TIOCSTI	0x5472		/* simulate terminal input */ +#define TARGET_TIOCMGET	0x741d		/* get all modem bits */ +#define TARGET_TIOCMBIS	0x741b		/* bis modem bits */ +#define TARGET_TIOCMBIC	0x741c		/* bic modem bits */ +#define TARGET_TIOCMSET	0x741a		/* set all modem bits */ +#define TARGET_TIOCPKT		0x5470		/* pty: set/clear packet mode */ +#define	 TARGET_TIOCPKT_DATA		0x00	/* data packet */ +#define	 TARGET_TIOCPKT_FLUSHREAD	0x01	/* flush packet */ +#define	 TARGET_TIOCPKT_FLUSHWRITE	0x02	/* flush packet */ +#define	 TARGET_TIOCPKT_STOP		0x04	/* stop output */ +#define	 TARGET_TIOCPKT_START		0x08	/* start output */ +#define	 TARGET_TIOCPKT_NOSTOP		0x10	/* no more ^S, ^Q */ +#define	 TARGET_TIOCPKT_DOSTOP		0x20	/* now do ^S ^Q */ +/* #define  TIOCPKT_IOCTL		0x40	state change of pty driver */ +#define TARGET_TIOCSWINSZ	TARGET_IOW('t', 103, struct winsize)	/* set window size */ +#define TARGET_TIOCGWINSZ	TARGET_IOR('t', 104, struct winsize)	/* get window size */ +#define TARGET_TIOCNOTTY	0x5471		/* void tty association */ +#define TARGET_TIOCSETD	0x7401 +#define TARGET_TIOCGETD	0x7400 + +#define TARGET_FIOCLEX		0x6601 +#define TARGET_FIONCLEX	0x6602 +#define TARGET_FIOASYNC	0x667d +#define TARGET_FIONBIO		0x667e +#define TARGET_FIOQSIZE	0x667f + +#define TARGET_TIOCGLTC	0x7474			/* get special local chars */ +#define TARGET_TIOCSLTC	0x7475			/* set special local chars */ +#define TARGET_TIOCSPGRP	TARGET_IOW('t', 118, int)	/* set pgrp of tty */ +#define TARGET_TIOCGPGRP	TARGET_IOR('t', 119, int)	/* get pgrp of tty */ +#define TARGET_TIOCCONS	TARGET_IOW('t', 120, int)	/* become virtual console */ + +#define TARGET_FIONREAD	0x467f +#define TARGET_TIOCINQ		TARGET_FIONREAD + +#define TARGET_TIOCGETP        0x7408 +#define TARGET_TIOCSETP        0x7409 +#define TARGET_TIOCSETN        0x740a			/* TIOCSETP wo flush */ + +/* #define TARGET_TIOCSETA	TARGET_IOW('t', 20, struct termios) set termios struct */ +/* #define TARGET_TIOCSETAW	TARGET_IOW('t', 21, struct termios) drain output, set */ +/* #define TARGET_TIOCSETAF	TARGET_IOW('t', 22, struct termios) drn out, fls in, set */ +/* #define TARGET_TIOCGETD	TARGET_IOR('t', 26, int)	get line discipline */ +/* #define TARGET_TIOCSETD	TARGET_IOW('t', 27, int)	set line discipline */ +						/* 127-124 compat */ + +#define TARGET_TIOCSBRK	0x5427  /* BSD compatibility */ +#define TARGET_TIOCCBRK	0x5428  /* BSD compatibility */ +#define TARGET_TIOCGSID	0x7416  /* Return the session ID of FD */ +#define TARGET_TIOCGPTN	TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define TARGET_TIOCSPTLCK	TARGET_IOW('T',0x31, int)  /* Lock/unlock Pty */ + +/* I hope the range from 0x5480 on is free ... */ +#define TARGET_TIOCSCTTY	0x5480		/* become controlling tty */ +#define TARGET_TIOCGSOFTCAR	0x5481 +#define TARGET_TIOCSSOFTCAR	0x5482 +#define TARGET_TIOCLINUX	0x5483 +#define TARGET_TIOCGSERIAL	0x5484 +#define TARGET_TIOCSSERIAL	0x5485 +#define TARGET_TCSBRKP		0x5486	/* Needed for POSIX tcsendbreak() */ +#define TARGET_TIOCSERCONFIG	0x5488 +#define TARGET_TIOCSERGWILD	0x5489 +#define TARGET_TIOCSERSWILD	0x548a +#define TARGET_TIOCGLCKTRMIOS	0x548b +#define TARGET_TIOCSLCKTRMIOS	0x548c +#define TARGET_TIOCSERGSTRUCT	0x548d /* For debugging only */ +#define TARGET_TIOCSERGETLSR   0x548e /* Get line status register */ +#define TARGET_TIOCSERGETMULTI 0x548f /* Get multiport config  */ +#define TARGET_TIOCSERSETMULTI 0x5490 /* Set multiport config */ +#define TARGET_TIOCMIWAIT      0x5491 /* wait for a change on serial input line(s) */ +#define TARGET_TIOCGICOUNT     0x5492 /* read serial port inline interrupt counts */ +#define TARGET_TIOCGHAYESESP	0x5493 /* Get Hayes ESP configuration */ +#define TARGET_TIOCSHAYESESP	0x5494 /* Set Hayes ESP configuration */ diff --git a/linux-user/mips64/syscall.h b/linux-user/mips64/syscall.h new file mode 100644 index 00000000..6733107d --- /dev/null +++ b/linux-user/mips64/syscall.h @@ -0,0 +1,230 @@ + +/* this struct defines the way the registers are stored on the +   stack during a system call. */ + +struct target_pt_regs { +        /* Saved main processor registers. */ +        target_ulong regs[32]; + +        /* Saved special registers. */ +        target_ulong cp0_status; +        target_ulong lo; +        target_ulong hi; +        target_ulong cp0_badvaddr; +        target_ulong cp0_cause; +        target_ulong cp0_epc; +}; + +/* Target errno definitions taken from asm-mips/errno.h */ +#undef TARGET_ENOMSG +#define TARGET_ENOMSG          35      /* Identifier removed */ +#undef TARGET_EIDRM +#define TARGET_EIDRM           36      /* Identifier removed */ +#undef TARGET_ECHRNG +#define TARGET_ECHRNG          37      /* Channel number out of range */ +#undef TARGET_EL2NSYNC +#define TARGET_EL2NSYNC        38      /* Level 2 not synchronized */ +#undef TARGET_EL3HLT +#define TARGET_EL3HLT          39      /* Level 3 halted */ +#undef TARGET_EL3RST +#define TARGET_EL3RST          40      /* Level 3 reset */ +#undef TARGET_ELNRNG +#define TARGET_ELNRNG          41      /* Link number out of range */ +#undef TARGET_EUNATCH +#define TARGET_EUNATCH         42      /* Protocol driver not attached */ +#undef TARGET_ENOCSI +#define TARGET_ENOCSI          43      /* No CSI structure available */ +#undef TARGET_EL2HLT +#define TARGET_EL2HLT          44      /* Level 2 halted */ +#undef TARGET_EDEADLK +#define TARGET_EDEADLK         45      /* Resource deadlock would occur */ +#undef TARGET_ENOLCK +#define TARGET_ENOLCK          46      /* No record locks available */ +#undef TARGET_EBADE +#define TARGET_EBADE           50      /* Invalid exchange */ +#undef TARGET_EBADR +#define TARGET_EBADR           51      /* Invalid request descriptor */ +#undef TARGET_EXFULL +#define TARGET_EXFULL          52      /* TARGET_Exchange full */ +#undef TARGET_ENOANO +#define TARGET_ENOANO          53      /* No anode */ +#undef TARGET_EBADRQC +#define TARGET_EBADRQC         54      /* Invalid request code */ +#undef TARGET_EBADSLT +#define TARGET_EBADSLT         55      /* Invalid slot */ +#undef TARGET_EDEADLOCK +#define TARGET_EDEADLOCK       56      /* File locking deadlock error */ +#undef TARGET_EBFONT +#define TARGET_EBFONT          59      /* Bad font file format */ +#undef TARGET_ENOSTR +#define TARGET_ENOSTR          60      /* Device not a stream */ +#undef TARGET_ENODATA +#define TARGET_ENODATA         61      /* No data available */ +#undef TARGET_ETIME +#define TARGET_ETIME           62      /* Timer expired */ +#undef TARGET_ENOSR +#define TARGET_ENOSR           63      /* Out of streams resources */ +#undef TARGET_ENONET +#define TARGET_ENONET          64      /* Machine is not on the network */ +#undef TARGET_ENOPKG +#define TARGET_ENOPKG          65      /* Package not installed */ +#undef TARGET_EREMOTE +#define TARGET_EREMOTE         66      /* Object is remote */ +#undef TARGET_ENOLINK +#define TARGET_ENOLINK         67      /* Link has been severed */ +#undef TARGET_EADV +#define TARGET_EADV            68      /* Advertise error */ +#undef TARGET_ESRMNT +#define TARGET_ESRMNT          69      /* Srmount error */ +#undef TARGET_ECOMM +#define TARGET_ECOMM           70      /* Communication error on send */ +#undef TARGET_EPROTO +#define TARGET_EPROTO          71      /* Protocol error */ +#undef TARGET_EDOTDOT +#define TARGET_EDOTDOT         73      /* RFS specific error */ +#undef TARGET_EMULTIHOP +#define TARGET_EMULTIHOP       74      /* Multihop attempted */ +#undef TARGET_EBADMSG +#define TARGET_EBADMSG         77      /* Not a data message */ +#undef TARGET_ENAMETOOLONG +#define TARGET_ENAMETOOLONG    78      /* File name too long */ +#undef TARGET_EOVERFLOW +#define TARGET_EOVERFLOW       79      /* Value too large for defined data type */ +#undef TARGET_ENOTUNIQ +#define TARGET_ENOTUNIQ        80      /* Name not unique on network */ +#undef TARGET_EBADFD +#define TARGET_EBADFD          81      /* File descriptor in bad state */ +#undef TARGET_EREMCHG +#define TARGET_EREMCHG         82      /* Remote address changed */ +#undef TARGET_ELIBACC +#define TARGET_ELIBACC         83      /* Can not access a needed shared library */ +#undef TARGET_ELIBBAD +#define TARGET_ELIBBAD         84      /* Accessing a corrupted shared library */ +#undef TARGET_ELIBSCN +#define TARGET_ELIBSCN         85      /* .lib section in a.out corrupted */ +#undef TARGET_ELIBMAX +#define TARGET_ELIBMAX         86      /* Attempting to link in too many shared libraries */ +#undef TARGET_ELIBEXEC +#define TARGET_ELIBEXEC        87      /* Cannot exec a shared library directly */ +#undef TARGET_EILSEQ +#define TARGET_EILSEQ          88      /* Illegal byte sequence */ +#undef TARGET_ENOSYS +#define TARGET_ENOSYS          89      /* Function not implemented */ +#undef TARGET_ELOOP +#define TARGET_ELOOP           90      /* Too many symbolic links encountered */ +#undef TARGET_ERESTART +#define TARGET_ERESTART        91      /* Interrupted system call should be restarted */ +#undef TARGET_ESTRPIPE +#define TARGET_ESTRPIPE        92      /* Streams pipe error */ +#undef TARGET_ENOTEMPTY +#define TARGET_ENOTEMPTY       93      /* Directory not empty */ +#undef TARGET_EUSERS +#define TARGET_EUSERS          94      /* Too many users */ +#undef TARGET_ENOTSOCK +#define TARGET_ENOTSOCK        95      /* Socket operation on non-socket */ +#undef TARGET_EDESTADDRREQ +#define TARGET_EDESTADDRREQ    96      /* Destination address required */ +#undef TARGET_EMSGSIZE +#define TARGET_EMSGSIZE        97      /* Message too long */ +#undef TARGET_EPROTOTYPE +#define TARGET_EPROTOTYPE      98      /* Protocol wrong type for socket */ +#undef TARGET_ENOPROTOOPT +#define TARGET_ENOPROTOOPT     99      /* Protocol not available */ +#undef TARGET_EPROTONOSUPPORT +#define TARGET_EPROTONOSUPPORT 120     /* Protocol not supported */ +#undef TARGET_ESOCKTNOSUPPORT +#define TARGET_ESOCKTNOSUPPORT 121     /* Socket type not supported */ +#undef TARGET_EOPNOTSUPP +#define TARGET_EOPNOTSUPP      122     /* Operation not supported on transport endpoint */ +#undef TARGET_EPFNOSUPPORT +#define TARGET_EPFNOSUPPORT    123     /* Protocol family not supported */ +#undef TARGET_EAFNOSUPPORT +#define TARGET_EAFNOSUPPORT    124     /* Address family not supported by protocol */ +#undef TARGET_EADDRINUSE +#define TARGET_EADDRINUSE      125     /* Address already in use */ +#undef TARGET_EADDRNOTAVAIL +#define TARGET_EADDRNOTAVAIL   126     /* Cannot assign requested address */ +#undef TARGET_ENETDOWN +#define TARGET_ENETDOWN        127     /* Network is down */ +#undef TARGET_ENETUNREACH +#define TARGET_ENETUNREACH     128     /* Network is unreachable */ +#undef TARGET_ENETRESET +#define TARGET_ENETRESET       129     /* Network dropped connection because of reset */ +#undef TARGET_ECONNABORTED +#define TARGET_ECONNABORTED    130     /* Software caused connection abort */ +#undef TARGET_ECONNRESET +#define TARGET_ECONNRESET      131     /* Connection reset by peer */ +#undef TARGET_ENOBUFS +#define TARGET_ENOBUFS         132     /* No buffer space available */ +#undef TARGET_EISCONN +#define TARGET_EISCONN         133     /* Transport endpoint is already connected */ +#undef TARGET_ENOTCONN +#define TARGET_ENOTCONN        134     /* Transport endpoint is not connected */ +#undef TARGET_EUCLEAN +#define TARGET_EUCLEAN         135     /* Structure needs cleaning */ +#undef TARGET_ENOTNAM +#define TARGET_ENOTNAM         137     /* Not a XENIX named type file */ +#undef TARGET_ENAVAIL +#define TARGET_ENAVAIL         138     /* No XENIX semaphores available */ +#undef TARGET_EISNAM +#define TARGET_EISNAM          139     /* Is a named type file */ +#undef TARGET_EREMOTEIO +#define TARGET_EREMOTEIO       140     /* Remote I/O error */ +#undef TARGET_EINIT +#define TARGET_EINIT           141     /* Reserved */ +#undef TARGET_EREMDEV +#define TARGET_EREMDEV         142     /* TARGET_Error 142 */ +#undef TARGET_ESHUTDOWN +#define TARGET_ESHUTDOWN       143     /* Cannot send after transport endpoint shutdown */ +#undef TARGET_ETOOMANYREFS +#define TARGET_ETOOMANYREFS    144     /* Too many references: cannot splice */ +#undef TARGET_ETIMEDOUT +#define TARGET_ETIMEDOUT       145     /* Connection timed out */ +#undef TARGET_ECONNREFUSED +#define TARGET_ECONNREFUSED    146     /* Connection refused */ +#undef TARGET_EHOSTDOWN +#define TARGET_EHOSTDOWN       147     /* Host is down */ +#undef TARGET_EHOSTUNREACH +#define TARGET_EHOSTUNREACH    148     /* No route to host */ +#undef TARGET_EALREADY +#define TARGET_EALREADY        149     /* Operation already in progress */ +#undef TARGET_EINPROGRESS +#define TARGET_EINPROGRESS     150     /* Operation now in progress */ +#undef TARGET_ESTALE +#define TARGET_ESTALE          151     /* Stale NFS file handle */ +#undef TARGET_ECANCELED +#define TARGET_ECANCELED       158     /* AIO operation canceled */ +/* + * These error are Linux extensions. + */ +#undef TARGET_ENOMEDIUM +#define TARGET_ENOMEDIUM       159     /* No medium found */ +#undef TARGET_EMEDIUMTYPE +#define TARGET_EMEDIUMTYPE     160     /* Wrong medium type */ +#undef TARGET_ENOKEY +#define TARGET_ENOKEY          161     /* Required key not available */ +#undef TARGET_EKEYEXPIRED +#define TARGET_EKEYEXPIRED     162     /* Key has expired */ +#undef TARGET_EKEYREVOKED +#define TARGET_EKEYREVOKED     163     /* Key has been revoked */ +#undef TARGET_EKEYREJECTED +#define TARGET_EKEYREJECTED    164     /* Key was rejected by service */ + +/* for robust mutexes */ +#undef TARGET_EOWNERDEAD +#define TARGET_EOWNERDEAD      165     /* Owner died */ +#undef TARGET_ENOTRECOVERABLE +#define TARGET_ENOTRECOVERABLE 166     /* State not recoverable */ + + + +/* Nasty hack: define a fake errno value for use by sigreturn. */ +#define TARGET_QEMU_ESIGRETURN 255 + +#define UNAME_MACHINE "mips64" +#define UNAME_MINIMUM_RELEASE "2.6.32" + +#define TARGET_CLONE_BACKWARDS +#define TARGET_MINSIGSTKSZ      2048 +#define TARGET_MLOCKALL_MCL_CURRENT 1 +#define TARGET_MLOCKALL_MCL_FUTURE  2 diff --git a/linux-user/mips64/syscall_nr.h b/linux-user/mips64/syscall_nr.h new file mode 100644 index 00000000..004232a8 --- /dev/null +++ b/linux-user/mips64/syscall_nr.h @@ -0,0 +1,633 @@ +#ifdef TARGET_ABI32 +/* + * Linux N32 syscalls are in the range from 6000 to 6999. + */ +#define TARGET_NR_Linux                 6000 +#define TARGET_NR_read                  (TARGET_NR_Linux +   0) +#define TARGET_NR_write                 (TARGET_NR_Linux +   1) +#define TARGET_NR_open                  (TARGET_NR_Linux +   2) +#define TARGET_NR_close                 (TARGET_NR_Linux +   3) +#define TARGET_NR_stat                  (TARGET_NR_Linux +   4) +#define TARGET_NR_fstat                 (TARGET_NR_Linux +   5) +#define TARGET_NR_lstat                 (TARGET_NR_Linux +   6) +#define TARGET_NR_poll                  (TARGET_NR_Linux +   7) +#define TARGET_NR_lseek                 (TARGET_NR_Linux +   8) +#define TARGET_NR_mmap                  (TARGET_NR_Linux +   9) +#define TARGET_NR_mprotect              (TARGET_NR_Linux +  10) +#define TARGET_NR_munmap                (TARGET_NR_Linux +  11) +#define TARGET_NR_brk                   (TARGET_NR_Linux +  12) +#define TARGET_NR_rt_sigaction          (TARGET_NR_Linux +  13) +#define TARGET_NR_rt_sigprocmask        (TARGET_NR_Linux +  14) +#define TARGET_NR_ioctl                 (TARGET_NR_Linux +  15) +#define TARGET_NR_pread64               (TARGET_NR_Linux +  16) +#define TARGET_NR_pwrite64              (TARGET_NR_Linux +  17) +#define TARGET_NR_readv                 (TARGET_NR_Linux +  18) +#define TARGET_NR_writev                (TARGET_NR_Linux +  19) +#define TARGET_NR_access                (TARGET_NR_Linux +  20) +#define TARGET_NR_pipe                  (TARGET_NR_Linux +  21) +#define TARGET_NR__newselect            (TARGET_NR_Linux +  22) +#define TARGET_NR_sched_yield           (TARGET_NR_Linux +  23) +#define TARGET_NR_mremap                (TARGET_NR_Linux +  24) +#define TARGET_NR_msync                 (TARGET_NR_Linux +  25) +#define TARGET_NR_mincore               (TARGET_NR_Linux +  26) +#define TARGET_NR_madvise               (TARGET_NR_Linux +  27) +#define TARGET_NR_shmget                (TARGET_NR_Linux +  28) +#define TARGET_NR_shmat                 (TARGET_NR_Linux +  29) +#define TARGET_NR_shmctl                (TARGET_NR_Linux +  30) +#define TARGET_NR_dup                   (TARGET_NR_Linux +  31) +#define TARGET_NR_dup2                  (TARGET_NR_Linux +  32) +#define TARGET_NR_pause                 (TARGET_NR_Linux +  33) +#define TARGET_NR_nanosleep             (TARGET_NR_Linux +  34) +#define TARGET_NR_getitimer             (TARGET_NR_Linux +  35) +#define TARGET_NR_setitimer             (TARGET_NR_Linux +  36) +#define TARGET_NR_alarm                 (TARGET_NR_Linux +  37) +#define TARGET_NR_getpid                (TARGET_NR_Linux +  38) +#define TARGET_NR_sendfile              (TARGET_NR_Linux +  39) +#define TARGET_NR_socket                (TARGET_NR_Linux +  40) +#define TARGET_NR_connect               (TARGET_NR_Linux +  41) +#define TARGET_NR_accept                (TARGET_NR_Linux +  42) +#define TARGET_NR_sendto                (TARGET_NR_Linux +  43) +#define TARGET_NR_recvfrom              (TARGET_NR_Linux +  44) +#define TARGET_NR_sendmsg               (TARGET_NR_Linux +  45) +#define TARGET_NR_recvmsg               (TARGET_NR_Linux +  46) +#define TARGET_NR_shutdown              (TARGET_NR_Linux +  47) +#define TARGET_NR_bind                  (TARGET_NR_Linux +  48) +#define TARGET_NR_listen                (TARGET_NR_Linux +  49) +#define TARGET_NR_getsockname           (TARGET_NR_Linux +  50) +#define TARGET_NR_getpeername           (TARGET_NR_Linux +  51) +#define TARGET_NR_socketpair            (TARGET_NR_Linux +  52) +#define TARGET_NR_setsockopt            (TARGET_NR_Linux +  53) +#define TARGET_NR_getsockopt            (TARGET_NR_Linux +  54) +#define TARGET_NR_clone                 (TARGET_NR_Linux +  55) +#define TARGET_NR_fork                  (TARGET_NR_Linux +  56) +#define TARGET_NR_execve                (TARGET_NR_Linux +  57) +#define TARGET_NR_exit                  (TARGET_NR_Linux +  58) +#define TARGET_NR_wait4                 (TARGET_NR_Linux +  59) +#define TARGET_NR_kill                  (TARGET_NR_Linux +  60) +#define TARGET_NR_uname                 (TARGET_NR_Linux +  61) +#define TARGET_NR_semget                (TARGET_NR_Linux +  62) +#define TARGET_NR_semop                 (TARGET_NR_Linux +  63) +#define TARGET_NR_semctl                (TARGET_NR_Linux +  64) +#define TARGET_NR_shmdt                 (TARGET_NR_Linux +  65) +#define TARGET_NR_msgget                (TARGET_NR_Linux +  66) +#define TARGET_NR_msgsnd                (TARGET_NR_Linux +  67) +#define TARGET_NR_msgrcv                (TARGET_NR_Linux +  68) +#define TARGET_NR_msgctl                (TARGET_NR_Linux +  69) +#define TARGET_NR_fcntl                 (TARGET_NR_Linux +  70) +#define TARGET_NR_flock                 (TARGET_NR_Linux +  71) +#define TARGET_NR_fsync                 (TARGET_NR_Linux +  72) +#define TARGET_NR_fdatasync             (TARGET_NR_Linux +  73) +#define TARGET_NR_truncate              (TARGET_NR_Linux +  74) +#define TARGET_NR_ftruncate             (TARGET_NR_Linux +  75) +#define TARGET_NR_getdents              (TARGET_NR_Linux +  76) +#define TARGET_NR_getcwd                (TARGET_NR_Linux +  77) +#define TARGET_NR_chdir                 (TARGET_NR_Linux +  78) +#define TARGET_NR_fchdir                (TARGET_NR_Linux +  79) +#define TARGET_NR_rename                (TARGET_NR_Linux +  80) +#define TARGET_NR_mkdir                 (TARGET_NR_Linux +  81) +#define TARGET_NR_rmdir                 (TARGET_NR_Linux +  82) +#define TARGET_NR_creat                 (TARGET_NR_Linux +  83) +#define TARGET_NR_link                  (TARGET_NR_Linux +  84) +#define TARGET_NR_unlink                (TARGET_NR_Linux +  85) +#define TARGET_NR_symlink               (TARGET_NR_Linux +  86) +#define TARGET_NR_readlink              (TARGET_NR_Linux +  87) +#define TARGET_NR_chmod                 (TARGET_NR_Linux +  88) +#define TARGET_NR_fchmod                (TARGET_NR_Linux +  89) +#define TARGET_NR_chown                 (TARGET_NR_Linux +  90) +#define TARGET_NR_fchown                (TARGET_NR_Linux +  91) +#define TARGET_NR_lchown                (TARGET_NR_Linux +  92) +#define TARGET_NR_umask                 (TARGET_NR_Linux +  93) +#define TARGET_NR_gettimeofday          (TARGET_NR_Linux +  94) +#define TARGET_NR_getrlimit             (TARGET_NR_Linux +  95) +#define TARGET_NR_getrusage             (TARGET_NR_Linux +  96) +#define TARGET_NR_sysinfo               (TARGET_NR_Linux +  97) +#define TARGET_NR_times                 (TARGET_NR_Linux +  98) +#define TARGET_NR_ptrace                (TARGET_NR_Linux +  99) +#define TARGET_NR_getuid                (TARGET_NR_Linux + 100) +#define TARGET_NR_syslog                (TARGET_NR_Linux + 101) +#define TARGET_NR_getgid                (TARGET_NR_Linux + 102) +#define TARGET_NR_setuid                (TARGET_NR_Linux + 103) +#define TARGET_NR_setgid                (TARGET_NR_Linux + 104) +#define TARGET_NR_geteuid               (TARGET_NR_Linux + 105) +#define TARGET_NR_getegid               (TARGET_NR_Linux + 106) +#define TARGET_NR_setpgid               (TARGET_NR_Linux + 107) +#define TARGET_NR_getppid               (TARGET_NR_Linux + 108) +#define TARGET_NR_getpgrp               (TARGET_NR_Linux + 109) +#define TARGET_NR_setsid                (TARGET_NR_Linux + 110) +#define TARGET_NR_setreuid              (TARGET_NR_Linux + 111) +#define TARGET_NR_setregid              (TARGET_NR_Linux + 112) +#define TARGET_NR_getgroups             (TARGET_NR_Linux + 113) +#define TARGET_NR_setgroups             (TARGET_NR_Linux + 114) +#define TARGET_NR_setresuid             (TARGET_NR_Linux + 115) +#define TARGET_NR_getresuid             (TARGET_NR_Linux + 116) +#define TARGET_NR_setresgid             (TARGET_NR_Linux + 117) +#define TARGET_NR_getresgid             (TARGET_NR_Linux + 118) +#define TARGET_NR_getpgid               (TARGET_NR_Linux + 119) +#define TARGET_NR_setfsuid              (TARGET_NR_Linux + 120) +#define TARGET_NR_setfsgid              (TARGET_NR_Linux + 121) +#define TARGET_NR_getsid                (TARGET_NR_Linux + 122) +#define TARGET_NR_capget                (TARGET_NR_Linux + 123) +#define TARGET_NR_capset                (TARGET_NR_Linux + 124) +#define TARGET_NR_rt_sigpending         (TARGET_NR_Linux + 125) +#define TARGET_NR_rt_sigtimedwait       (TARGET_NR_Linux + 126) +#define TARGET_NR_rt_sigqueueinfo       (TARGET_NR_Linux + 127) +#define TARGET_NR_rt_sigsuspend         (TARGET_NR_Linux + 128) +#define TARGET_NR_sigaltstack           (TARGET_NR_Linux + 129) +#define TARGET_NR_utime                 (TARGET_NR_Linux + 130) +#define TARGET_NR_mknod                 (TARGET_NR_Linux + 131) +#define TARGET_NR_personality           (TARGET_NR_Linux + 132) +#define TARGET_NR_ustat                 (TARGET_NR_Linux + 133) +#define TARGET_NR_statfs                (TARGET_NR_Linux + 134) +#define TARGET_NR_fstatfs               (TARGET_NR_Linux + 135) +#define TARGET_NR_sysfs                 (TARGET_NR_Linux + 136) +#define TARGET_NR_getpriority           (TARGET_NR_Linux + 137) +#define TARGET_NR_setpriority           (TARGET_NR_Linux + 138) +#define TARGET_NR_sched_setparam        (TARGET_NR_Linux + 139) +#define TARGET_NR_sched_getparam        (TARGET_NR_Linux + 140) +#define TARGET_NR_sched_setscheduler    (TARGET_NR_Linux + 141) +#define TARGET_NR_sched_getscheduler    (TARGET_NR_Linux + 142) +#define TARGET_NR_sched_get_priority_max        (TARGET_NR_Linux + 143) +#define TARGET_NR_sched_get_priority_min        (TARGET_NR_Linux + 144) +#define TARGET_NR_sched_rr_get_interval (TARGET_NR_Linux + 145) +#define TARGET_NR_mlock                 (TARGET_NR_Linux + 146) +#define TARGET_NR_munlock               (TARGET_NR_Linux + 147) +#define TARGET_NR_mlockall              (TARGET_NR_Linux + 148) +#define TARGET_NR_munlockall            (TARGET_NR_Linux + 149) +#define TARGET_NR_vhangup               (TARGET_NR_Linux + 150) +#define TARGET_NR_pivot_root            (TARGET_NR_Linux + 151) +#define TARGET_NR__sysctl               (TARGET_NR_Linux + 152) +#define TARGET_NR_prctl                 (TARGET_NR_Linux + 153) +#define TARGET_NR_adjtimex              (TARGET_NR_Linux + 154) +#define TARGET_NR_setrlimit             (TARGET_NR_Linux + 155) +#define TARGET_NR_chroot                (TARGET_NR_Linux + 156) +#define TARGET_NR_sync                  (TARGET_NR_Linux + 157) +#define TARGET_NR_acct                  (TARGET_NR_Linux + 158) +#define TARGET_NR_settimeofday          (TARGET_NR_Linux + 159) +#define TARGET_NR_mount                 (TARGET_NR_Linux + 160) +#define TARGET_NR_umount2               (TARGET_NR_Linux + 161) +#define TARGET_NR_swapon                (TARGET_NR_Linux + 162) +#define TARGET_NR_swapoff               (TARGET_NR_Linux + 163) +#define TARGET_NR_reboot                (TARGET_NR_Linux + 164) +#define TARGET_NR_sethostname           (TARGET_NR_Linux + 165) +#define TARGET_NR_setdomainname         (TARGET_NR_Linux + 166) +#define TARGET_NR_create_module         (TARGET_NR_Linux + 167) +#define TARGET_NR_init_module           (TARGET_NR_Linux + 168) +#define TARGET_NR_delete_module         (TARGET_NR_Linux + 169) +#define TARGET_NR_get_kernel_syms       (TARGET_NR_Linux + 170) +#define TARGET_NR_query_module          (TARGET_NR_Linux + 171) +#define TARGET_NR_quotactl              (TARGET_NR_Linux + 172) +#define TARGET_NR_nfsservctl            (TARGET_NR_Linux + 173) +#define TARGET_NR_getpmsg               (TARGET_NR_Linux + 174) +#define TARGET_NR_putpmsg               (TARGET_NR_Linux + 175) +#define TARGET_NR_afs_syscall           (TARGET_NR_Linux + 176) +#define TARGET_NR_reserved177           (TARGET_NR_Linux + 177) +#define TARGET_NR_gettid                (TARGET_NR_Linux + 178) +#define TARGET_NR_readahead             (TARGET_NR_Linux + 179) +#define TARGET_NR_setxattr              (TARGET_NR_Linux + 180) +#define TARGET_NR_lsetxattr             (TARGET_NR_Linux + 181) +#define TARGET_NR_fsetxattr             (TARGET_NR_Linux + 182) +#define TARGET_NR_getxattr              (TARGET_NR_Linux + 183) +#define TARGET_NR_lgetxattr             (TARGET_NR_Linux + 184) +#define TARGET_NR_fgetxattr             (TARGET_NR_Linux + 185) +#define TARGET_NR_listxattr             (TARGET_NR_Linux + 186) +#define TARGET_NR_llistxattr            (TARGET_NR_Linux + 187) +#define TARGET_NR_flistxattr            (TARGET_NR_Linux + 188) +#define TARGET_NR_removexattr           (TARGET_NR_Linux + 189) +#define TARGET_NR_lremovexattr          (TARGET_NR_Linux + 190) +#define TARGET_NR_fremovexattr          (TARGET_NR_Linux + 191) +#define TARGET_NR_tkill                 (TARGET_NR_Linux + 192) +#define TARGET_NR_reserved193           (TARGET_NR_Linux + 193) +#define TARGET_NR_futex                 (TARGET_NR_Linux + 194) +#define TARGET_NR_sched_setaffinity     (TARGET_NR_Linux + 195) +#define TARGET_NR_sched_getaffinity     (TARGET_NR_Linux + 196) +#define TARGET_NR_cacheflush            (TARGET_NR_Linux + 197) +#define TARGET_NR_cachectl              (TARGET_NR_Linux + 198) +#define TARGET_NR_sysmips               (TARGET_NR_Linux + 199) +#define TARGET_NR_io_setup              (TARGET_NR_Linux + 200) +#define TARGET_NR_io_destroy            (TARGET_NR_Linux + 201) +#define TARGET_NR_io_getevents          (TARGET_NR_Linux + 202) +#define TARGET_NR_io_submit             (TARGET_NR_Linux + 203) +#define TARGET_NR_io_cancel             (TARGET_NR_Linux + 204) +#define TARGET_NR_exit_group            (TARGET_NR_Linux + 205) +#define TARGET_NR_lookup_dcookie        (TARGET_NR_Linux + 206) +#define TARGET_NR_epoll_create          (TARGET_NR_Linux + 207) +#define TARGET_NR_epoll_ctl             (TARGET_NR_Linux + 208) +#define TARGET_NR_epoll_wait            (TARGET_NR_Linux + 209) +#define TARGET_NR_remap_file_pages      (TARGET_NR_Linux + 210) +#define TARGET_NR_rt_sigreturn          (TARGET_NR_Linux + 211) +#define TARGET_NR_fcntl64               (TARGET_NR_Linux + 212) +#define TARGET_NR_set_tid_address       (TARGET_NR_Linux + 213) +#define TARGET_NR_restart_syscall       (TARGET_NR_Linux + 214) +#define TARGET_NR_semtimedop            (TARGET_NR_Linux + 215) +#define TARGET_NR_fadvise64             (TARGET_NR_Linux + 216) +#define TARGET_NR_statfs64              (TARGET_NR_Linux + 217) +#define TARGET_NR_fstatfs64             (TARGET_NR_Linux + 218) +#define TARGET_NR_sendfile64            (TARGET_NR_Linux + 219) +#define TARGET_NR_timer_create          (TARGET_NR_Linux + 220) +#define TARGET_NR_timer_settime         (TARGET_NR_Linux + 221) +#define TARGET_NR_timer_gettime         (TARGET_NR_Linux + 222) +#define TARGET_NR_timer_getoverrun      (TARGET_NR_Linux + 223) +#define TARGET_NR_timer_delete          (TARGET_NR_Linux + 224) +#define TARGET_NR_clock_settime         (TARGET_NR_Linux + 225) +#define TARGET_NR_clock_gettime         (TARGET_NR_Linux + 226) +#define TARGET_NR_clock_getres          (TARGET_NR_Linux + 227) +#define TARGET_NR_clock_nanosleep       (TARGET_NR_Linux + 228) +#define TARGET_NR_tgkill                (TARGET_NR_Linux + 229) +#define TARGET_NR_utimes                (TARGET_NR_Linux + 230) +#define TARGET_NR_mbind                 (TARGET_NR_Linux + 231) +#define TARGET_NR_get_mempolicy         (TARGET_NR_Linux + 232) +#define TARGET_NR_set_mempolicy         (TARGET_NR_Linux + 233) +#define TARGET_NR_mq_open               (TARGET_NR_Linux + 234) +#define TARGET_NR_mq_unlink             (TARGET_NR_Linux + 235) +#define TARGET_NR_mq_timedsend          (TARGET_NR_Linux + 236) +#define TARGET_NR_mq_timedreceive       (TARGET_NR_Linux + 237) +#define TARGET_NR_mq_notify             (TARGET_NR_Linux + 238) +#define TARGET_NR_mq_getsetattr         (TARGET_NR_Linux + 239) +#define TARGET_NR_vserver               (TARGET_NR_Linux + 240) +#define TARGET_NR_waitid                (TARGET_NR_Linux + 241) +/* #define TARGET_NR_sys_setaltroot     (TARGET_NR_Linux + 242) */ +#define TARGET_NR_add_key               (TARGET_NR_Linux + 243) +#define TARGET_NR_request_key           (TARGET_NR_Linux + 244) +#define TARGET_NR_keyctl                (TARGET_NR_Linux + 245) +#define TARGET_NR_set_thread_area       (TARGET_NR_Linux + 246) +#define TARGET_NR_inotify_init          (TARGET_NR_Linux + 247) +#define TARGET_NR_inotify_add_watch     (TARGET_NR_Linux + 248) +#define TARGET_NR_inotify_rm_watch      (TARGET_NR_Linux + 249) +#define TARGET_NR_migrate_pages         (TARGET_NR_Linux + 250) +#define TARGET_NR_openat                (TARGET_NR_Linux + 251) +#define TARGET_NR_mkdirat               (TARGET_NR_Linux + 252) +#define TARGET_NR_mknodat               (TARGET_NR_Linux + 253) +#define TARGET_NR_fchownat              (TARGET_NR_Linux + 254) +#define TARGET_NR_futimesat             (TARGET_NR_Linux + 255) +#define TARGET_NR_newfstatat            (TARGET_NR_Linux + 256) +#define TARGET_NR_unlinkat              (TARGET_NR_Linux + 257) +#define TARGET_NR_renameat              (TARGET_NR_Linux + 258) +#define TARGET_NR_linkat                (TARGET_NR_Linux + 259) +#define TARGET_NR_symlinkat             (TARGET_NR_Linux + 260) +#define TARGET_NR_readlinkat            (TARGET_NR_Linux + 261) +#define TARGET_NR_fchmodat              (TARGET_NR_Linux + 262) +#define TARGET_NR_faccessat             (TARGET_NR_Linux + 263) +#define TARGET_NR_pselect6              (TARGET_NR_Linux + 264) +#define TARGET_NR_ppoll                 (TARGET_NR_Linux + 265) +#define TARGET_NR_unshare               (TARGET_NR_Linux + 266) +#define TARGET_NR_splice                (TARGET_NR_Linux + 267) +#define TARGET_NR_sync_file_range       (TARGET_NR_Linux + 268) +#define TARGET_NR_tee                   (TARGET_NR_Linux + 269) +#define TARGET_NR_vmsplice              (TARGET_NR_Linux + 270) +#define TARGET_NR_move_pages            (TARGET_NR_Linux + 271) +#define TARGET_NR_set_robust_list       (TARGET_NR_Linux + 272) +#define TARGET_NR_get_robust_list       (TARGET_NR_Linux + 273) +#define TARGET_NR_kexec_load            (TARGET_NR_Linux + 274) +#define TARGET_NR_getcpu                (TARGET_NR_Linux + 275) +#define TARGET_NR_epoll_pwait           (TARGET_NR_Linux + 276) +#define TARGET_NR_ioprio_set            (TARGET_NR_Linux + 277) +#define TARGET_NR_ioprio_get            (TARGET_NR_Linux + 278) +#define TARGET_NR_utimensat             (TARGET_NR_Linux + 279) +#define TARGET_NR_signalfd              (TARGET_NR_Linux + 280) +#define TARGET_NR_timerfd               (TARGET_NR_Linux + 281) +#define TARGET_NR_eventfd               (TARGET_NR_Linux + 282) +#define TARGET_NR_fallocate             (TARGET_NR_Linux + 283) +#define TARGET_NR_timerfd_create        (TARGET_NR_Linux + 284) +#define TARGET_NR_timerfd_gettime       (TARGET_NR_Linux + 285) +#define TARGET_NR_timerfd_settime       (TARGET_NR_Linux + 286) +#define TARGET_NR_signalfd4             (TARGET_NR_Linux + 287) +#define TARGET_NR_eventfd2              (TARGET_NR_Linux + 288) +#define TARGET_NR_epoll_create1         (TARGET_NR_Linux + 289) +#define TARGET_NR_dup3                  (TARGET_NR_Linux + 290) +#define TARGET_NR_pipe2                 (TARGET_NR_Linux + 291) +#define TARGET_NR_inotify_init1         (TARGET_NR_Linux + 292) +#define TARGET_NR_preadv                (TARGET_NR_Linux + 293) +#define TARGET_NR_pwritev               (TARGET_NR_Linux + 294) +#define TARGET_NR_rt_tgsigqueueinfo     (TARGET_NR_Linux + 295) +#define TARGET_NR_perf_event_open       (TARGET_NR_Linux + 296) +#define TARGET_NR_accept4               (TARGET_NR_Linux + 297) +#define TARGET_NR_recvmmsg              (TARGET_NR_Linux + 298) +#define TARGET_NR_getdents64            (TARGET_NR_Linux + 299) +#define TARGET_NR_fanotify_init         (TARGET_NR_Linux + 300) +#define TARGET_NR_fanotify_mark         (TARGET_NR_Linux + 301) +#define TARGET_NR_prlimit64             (TARGET_NR_Linux + 302) +#define TARGET_NR_name_to_handle_at     (TARGET_NR_Linux + 303) +#define TARGET_NR_open_by_handle_at     (TARGET_NR_Linux + 304) +#define TARGET_NR_clock_adjtime         (TARGET_NR_Linux + 305) +#define TARGET_NR_syncfs                (TARGET_NR_Linux + 306) +#define TARGET_NR_sendmmsg              (TARGET_NR_Linux + 307) +#define TARGET_NR_setns                 (TARGET_NR_Linux + 308) +#define TARGET_NR_process_vm_readv      (TARGET_NR_Linux + 309) +#define TARGET_NR_process_vm_writev     (TARGET_NR_Linux + 310) +#define TARGET_NR_kcmp                  (TARGET_NR_Linux + 311) +#define TARGET_NR_finit_module          (TARGET_NR_Linux + 312) +#else +/* + * Linux 64-bit syscalls are in the range from 5000 to 5999. + */ +#define TARGET_NR_Linux                 5000 +#define TARGET_NR_read                  (TARGET_NR_Linux +   0) +#define TARGET_NR_write                 (TARGET_NR_Linux +   1) +#define TARGET_NR_open                  (TARGET_NR_Linux +   2) +#define TARGET_NR_close                 (TARGET_NR_Linux +   3) +#define TARGET_NR_stat                  (TARGET_NR_Linux +   4) +#define TARGET_NR_fstat                 (TARGET_NR_Linux +   5) +#define TARGET_NR_lstat                 (TARGET_NR_Linux +   6) +#define TARGET_NR_poll                  (TARGET_NR_Linux +   7) +#define TARGET_NR_lseek                 (TARGET_NR_Linux +   8) +#define TARGET_NR_mmap                  (TARGET_NR_Linux +   9) +#define TARGET_NR_mprotect              (TARGET_NR_Linux +  10) +#define TARGET_NR_munmap                (TARGET_NR_Linux +  11) +#define TARGET_NR_brk                   (TARGET_NR_Linux +  12) +#define TARGET_NR_rt_sigaction          (TARGET_NR_Linux +  13) +#define TARGET_NR_rt_sigprocmask        (TARGET_NR_Linux +  14) +#define TARGET_NR_ioctl                 (TARGET_NR_Linux +  15) +#define TARGET_NR_pread64               (TARGET_NR_Linux +  16) +#define TARGET_NR_pwrite64              (TARGET_NR_Linux +  17) +#define TARGET_NR_readv                 (TARGET_NR_Linux +  18) +#define TARGET_NR_writev                (TARGET_NR_Linux +  19) +#define TARGET_NR_access                (TARGET_NR_Linux +  20) +#define TARGET_NR_pipe                  (TARGET_NR_Linux +  21) +#define TARGET_NR__newselect            (TARGET_NR_Linux +  22) +#define TARGET_NR_sched_yield           (TARGET_NR_Linux +  23) +#define TARGET_NR_mremap                (TARGET_NR_Linux +  24) +#define TARGET_NR_msync                 (TARGET_NR_Linux +  25) +#define TARGET_NR_mincore               (TARGET_NR_Linux +  26) +#define TARGET_NR_madvise               (TARGET_NR_Linux +  27) +#define TARGET_NR_shmget                (TARGET_NR_Linux +  28) +#define TARGET_NR_shmat                 (TARGET_NR_Linux +  29) +#define TARGET_NR_shmctl                (TARGET_NR_Linux +  30) +#define TARGET_NR_dup                   (TARGET_NR_Linux +  31) +#define TARGET_NR_dup2                  (TARGET_NR_Linux +  32) +#define TARGET_NR_pause                 (TARGET_NR_Linux +  33) +#define TARGET_NR_nanosleep             (TARGET_NR_Linux +  34) +#define TARGET_NR_getitimer             (TARGET_NR_Linux +  35) +#define TARGET_NR_setitimer             (TARGET_NR_Linux +  36) +#define TARGET_NR_alarm                 (TARGET_NR_Linux +  37) +#define TARGET_NR_getpid                (TARGET_NR_Linux +  38) +#define TARGET_NR_sendfile              (TARGET_NR_Linux +  39) +#define TARGET_NR_socket                (TARGET_NR_Linux +  40) +#define TARGET_NR_connect               (TARGET_NR_Linux +  41) +#define TARGET_NR_accept                (TARGET_NR_Linux +  42) +#define TARGET_NR_sendto                (TARGET_NR_Linux +  43) +#define TARGET_NR_recvfrom              (TARGET_NR_Linux +  44) +#define TARGET_NR_sendmsg               (TARGET_NR_Linux +  45) +#define TARGET_NR_recvmsg               (TARGET_NR_Linux +  46) +#define TARGET_NR_shutdown              (TARGET_NR_Linux +  47) +#define TARGET_NR_bind                  (TARGET_NR_Linux +  48) +#define TARGET_NR_listen                (TARGET_NR_Linux +  49) +#define TARGET_NR_getsockname           (TARGET_NR_Linux +  50) +#define TARGET_NR_getpeername           (TARGET_NR_Linux +  51) +#define TARGET_NR_socketpair            (TARGET_NR_Linux +  52) +#define TARGET_NR_setsockopt            (TARGET_NR_Linux +  53) +#define TARGET_NR_getsockopt            (TARGET_NR_Linux +  54) +#define TARGET_NR_clone                 (TARGET_NR_Linux +  55) +#define TARGET_NR_fork                  (TARGET_NR_Linux +  56) +#define TARGET_NR_execve                (TARGET_NR_Linux +  57) +#define TARGET_NR_exit                  (TARGET_NR_Linux +  58) +#define TARGET_NR_wait4                 (TARGET_NR_Linux +  59) +#define TARGET_NR_kill                  (TARGET_NR_Linux +  60) +#define TARGET_NR_uname                 (TARGET_NR_Linux +  61) +#define TARGET_NR_semget                (TARGET_NR_Linux +  62) +#define TARGET_NR_semop                 (TARGET_NR_Linux +  63) +#define TARGET_NR_semctl                (TARGET_NR_Linux +  64) +#define TARGET_NR_shmdt                 (TARGET_NR_Linux +  65) +#define TARGET_NR_msgget                (TARGET_NR_Linux +  66) +#define TARGET_NR_msgsnd                (TARGET_NR_Linux +  67) +#define TARGET_NR_msgrcv                (TARGET_NR_Linux +  68) +#define TARGET_NR_msgctl                (TARGET_NR_Linux +  69) +#define TARGET_NR_fcntl                 (TARGET_NR_Linux +  70) +#define TARGET_NR_flock                 (TARGET_NR_Linux +  71) +#define TARGET_NR_fsync                 (TARGET_NR_Linux +  72) +#define TARGET_NR_fdatasync             (TARGET_NR_Linux +  73) +#define TARGET_NR_truncate              (TARGET_NR_Linux +  74) +#define TARGET_NR_ftruncate             (TARGET_NR_Linux +  75) +#define TARGET_NR_getdents              (TARGET_NR_Linux +  76) +#define TARGET_NR_getcwd                (TARGET_NR_Linux +  77) +#define TARGET_NR_chdir                 (TARGET_NR_Linux +  78) +#define TARGET_NR_fchdir                (TARGET_NR_Linux +  79) +#define TARGET_NR_rename                (TARGET_NR_Linux +  80) +#define TARGET_NR_mkdir                 (TARGET_NR_Linux +  81) +#define TARGET_NR_rmdir                 (TARGET_NR_Linux +  82) +#define TARGET_NR_creat                 (TARGET_NR_Linux +  83) +#define TARGET_NR_link                  (TARGET_NR_Linux +  84) +#define TARGET_NR_unlink                (TARGET_NR_Linux +  85) +#define TARGET_NR_symlink               (TARGET_NR_Linux +  86) +#define TARGET_NR_readlink              (TARGET_NR_Linux +  87) +#define TARGET_NR_chmod                 (TARGET_NR_Linux +  88) +#define TARGET_NR_fchmod                (TARGET_NR_Linux +  89) +#define TARGET_NR_chown                 (TARGET_NR_Linux +  90) +#define TARGET_NR_fchown                (TARGET_NR_Linux +  91) +#define TARGET_NR_lchown                (TARGET_NR_Linux +  92) +#define TARGET_NR_umask                 (TARGET_NR_Linux +  93) +#define TARGET_NR_gettimeofday          (TARGET_NR_Linux +  94) +#define TARGET_NR_getrlimit             (TARGET_NR_Linux +  95) +#define TARGET_NR_getrusage             (TARGET_NR_Linux +  96) +#define TARGET_NR_sysinfo               (TARGET_NR_Linux +  97) +#define TARGET_NR_times                 (TARGET_NR_Linux +  98) +#define TARGET_NR_ptrace                (TARGET_NR_Linux +  99) +#define TARGET_NR_getuid                (TARGET_NR_Linux + 100) +#define TARGET_NR_syslog                (TARGET_NR_Linux + 101) +#define TARGET_NR_getgid                (TARGET_NR_Linux + 102) +#define TARGET_NR_setuid                (TARGET_NR_Linux + 103) +#define TARGET_NR_setgid                (TARGET_NR_Linux + 104) +#define TARGET_NR_geteuid               (TARGET_NR_Linux + 105) +#define TARGET_NR_getegid               (TARGET_NR_Linux + 106) +#define TARGET_NR_setpgid               (TARGET_NR_Linux + 107) +#define TARGET_NR_getppid               (TARGET_NR_Linux + 108) +#define TARGET_NR_getpgrp               (TARGET_NR_Linux + 109) +#define TARGET_NR_setsid                (TARGET_NR_Linux + 110) +#define TARGET_NR_setreuid              (TARGET_NR_Linux + 111) +#define TARGET_NR_setregid              (TARGET_NR_Linux + 112) +#define TARGET_NR_getgroups             (TARGET_NR_Linux + 113) +#define TARGET_NR_setgroups             (TARGET_NR_Linux + 114) +#define TARGET_NR_setresuid             (TARGET_NR_Linux + 115) +#define TARGET_NR_getresuid             (TARGET_NR_Linux + 116) +#define TARGET_NR_setresgid             (TARGET_NR_Linux + 117) +#define TARGET_NR_getresgid             (TARGET_NR_Linux + 118) +#define TARGET_NR_getpgid               (TARGET_NR_Linux + 119) +#define TARGET_NR_setfsuid              (TARGET_NR_Linux + 120) +#define TARGET_NR_setfsgid              (TARGET_NR_Linux + 121) +#define TARGET_NR_getsid                (TARGET_NR_Linux + 122) +#define TARGET_NR_capget                (TARGET_NR_Linux + 123) +#define TARGET_NR_capset                (TARGET_NR_Linux + 124) +#define TARGET_NR_rt_sigpending         (TARGET_NR_Linux + 125) +#define TARGET_NR_rt_sigtimedwait       (TARGET_NR_Linux + 126) +#define TARGET_NR_rt_sigqueueinfo       (TARGET_NR_Linux + 127) +#define TARGET_NR_rt_sigsuspend         (TARGET_NR_Linux + 128) +#define TARGET_NR_sigaltstack           (TARGET_NR_Linux + 129) +#define TARGET_NR_utime                 (TARGET_NR_Linux + 130) +#define TARGET_NR_mknod                 (TARGET_NR_Linux + 131) +#define TARGET_NR_personality           (TARGET_NR_Linux + 132) +#define TARGET_NR_ustat                 (TARGET_NR_Linux + 133) +#define TARGET_NR_statfs                (TARGET_NR_Linux + 134) +#define TARGET_NR_fstatfs               (TARGET_NR_Linux + 135) +#define TARGET_NR_sysfs                 (TARGET_NR_Linux + 136) +#define TARGET_NR_getpriority           (TARGET_NR_Linux + 137) +#define TARGET_NR_setpriority           (TARGET_NR_Linux + 138) +#define TARGET_NR_sched_setparam        (TARGET_NR_Linux + 139) +#define TARGET_NR_sched_getparam        (TARGET_NR_Linux + 140) +#define TARGET_NR_sched_setscheduler    (TARGET_NR_Linux + 141) +#define TARGET_NR_sched_getscheduler    (TARGET_NR_Linux + 142) +#define TARGET_NR_sched_get_priority_max        (TARGET_NR_Linux + 143) +#define TARGET_NR_sched_get_priority_min        (TARGET_NR_Linux + 144) +#define TARGET_NR_sched_rr_get_interval (TARGET_NR_Linux + 145) +#define TARGET_NR_mlock                 (TARGET_NR_Linux + 146) +#define TARGET_NR_munlock               (TARGET_NR_Linux + 147) +#define TARGET_NR_mlockall              (TARGET_NR_Linux + 148) +#define TARGET_NR_munlockall            (TARGET_NR_Linux + 149) +#define TARGET_NR_vhangup               (TARGET_NR_Linux + 150) +#define TARGET_NR_pivot_root            (TARGET_NR_Linux + 151) +#define TARGET_NR__sysctl               (TARGET_NR_Linux + 152) +#define TARGET_NR_prctl                 (TARGET_NR_Linux + 153) +#define TARGET_NR_adjtimex              (TARGET_NR_Linux + 154) +#define TARGET_NR_setrlimit             (TARGET_NR_Linux + 155) +#define TARGET_NR_chroot                (TARGET_NR_Linux + 156) +#define TARGET_NR_sync                  (TARGET_NR_Linux + 157) +#define TARGET_NR_acct                  (TARGET_NR_Linux + 158) +#define TARGET_NR_settimeofday          (TARGET_NR_Linux + 159) +#define TARGET_NR_mount                 (TARGET_NR_Linux + 160) +#define TARGET_NR_umount2               (TARGET_NR_Linux + 161) +#define TARGET_NR_swapon                (TARGET_NR_Linux + 162) +#define TARGET_NR_swapoff               (TARGET_NR_Linux + 163) +#define TARGET_NR_reboot                (TARGET_NR_Linux + 164) +#define TARGET_NR_sethostname           (TARGET_NR_Linux + 165) +#define TARGET_NR_setdomainname         (TARGET_NR_Linux + 166) +#define TARGET_NR_create_module         (TARGET_NR_Linux + 167) +#define TARGET_NR_init_module           (TARGET_NR_Linux + 168) +#define TARGET_NR_delete_module         (TARGET_NR_Linux + 169) +#define TARGET_NR_get_kernel_syms       (TARGET_NR_Linux + 170) +#define TARGET_NR_query_module          (TARGET_NR_Linux + 171) +#define TARGET_NR_quotactl              (TARGET_NR_Linux + 172) +#define TARGET_NR_nfsservctl            (TARGET_NR_Linux + 173) +#define TARGET_NR_getpmsg               (TARGET_NR_Linux + 174) +#define TARGET_NR_putpmsg               (TARGET_NR_Linux + 175) +#define TARGET_NR_afs_syscall           (TARGET_NR_Linux + 176) +#define TARGET_NR_reserved177           (TARGET_NR_Linux + 177) +#define TARGET_NR_gettid                (TARGET_NR_Linux + 178) +#define TARGET_NR_readahead             (TARGET_NR_Linux + 179) +#define TARGET_NR_setxattr              (TARGET_NR_Linux + 180) +#define TARGET_NR_lsetxattr             (TARGET_NR_Linux + 181) +#define TARGET_NR_fsetxattr             (TARGET_NR_Linux + 182) +#define TARGET_NR_getxattr              (TARGET_NR_Linux + 183) +#define TARGET_NR_lgetxattr             (TARGET_NR_Linux + 184) +#define TARGET_NR_fgetxattr             (TARGET_NR_Linux + 185) +#define TARGET_NR_listxattr             (TARGET_NR_Linux + 186) +#define TARGET_NR_llistxattr            (TARGET_NR_Linux + 187) +#define TARGET_NR_flistxattr            (TARGET_NR_Linux + 188) +#define TARGET_NR_removexattr           (TARGET_NR_Linux + 189) +#define TARGET_NR_lremovexattr          (TARGET_NR_Linux + 190) +#define TARGET_NR_fremovexattr          (TARGET_NR_Linux + 191) +#define TARGET_NR_tkill                 (TARGET_NR_Linux + 192) +#define TARGET_NR_reserved193           (TARGET_NR_Linux + 193) +#define TARGET_NR_futex                 (TARGET_NR_Linux + 194) +#define TARGET_NR_sched_setaffinity     (TARGET_NR_Linux + 195) +#define TARGET_NR_sched_getaffinity     (TARGET_NR_Linux + 196) +#define TARGET_NR_cacheflush            (TARGET_NR_Linux + 197) +#define TARGET_NR_cachectl              (TARGET_NR_Linux + 198) +#define TARGET_NR_sysmips               (TARGET_NR_Linux + 199) +#define TARGET_NR_io_setup              (TARGET_NR_Linux + 200) +#define TARGET_NR_io_destroy            (TARGET_NR_Linux + 201) +#define TARGET_NR_io_getevents          (TARGET_NR_Linux + 202) +#define TARGET_NR_io_submit             (TARGET_NR_Linux + 203) +#define TARGET_NR_io_cancel             (TARGET_NR_Linux + 204) +#define TARGET_NR_exit_group            (TARGET_NR_Linux + 205) +#define TARGET_NR_lookup_dcookie        (TARGET_NR_Linux + 206) +#define TARGET_NR_epoll_create          (TARGET_NR_Linux + 207) +#define TARGET_NR_epoll_ctl             (TARGET_NR_Linux + 208) +#define TARGET_NR_epoll_wait            (TARGET_NR_Linux + 209) +#define TARGET_NR_remap_file_pages      (TARGET_NR_Linux + 210) +#define TARGET_NR_rt_sigreturn          (TARGET_NR_Linux + 211) +#define TARGET_NR_set_tid_address       (TARGET_NR_Linux + 212) +#define TARGET_NR_restart_syscall       (TARGET_NR_Linux + 213) +#define TARGET_NR_semtimedop            (TARGET_NR_Linux + 214) +#define TARGET_NR_fadvise64             (TARGET_NR_Linux + 215) +#define TARGET_NR_timer_create          (TARGET_NR_Linux + 216) +#define TARGET_NR_timer_settime         (TARGET_NR_Linux + 217) +#define TARGET_NR_timer_gettime         (TARGET_NR_Linux + 218) +#define TARGET_NR_timer_getoverrun      (TARGET_NR_Linux + 219) +#define TARGET_NR_timer_delete          (TARGET_NR_Linux + 220) +#define TARGET_NR_clock_settime         (TARGET_NR_Linux + 221) +#define TARGET_NR_clock_gettime         (TARGET_NR_Linux + 222) +#define TARGET_NR_clock_getres          (TARGET_NR_Linux + 223) +#define TARGET_NR_clock_nanosleep       (TARGET_NR_Linux + 224) +#define TARGET_NR_tgkill                (TARGET_NR_Linux + 225) +#define TARGET_NR_utimes                (TARGET_NR_Linux + 226) +#define TARGET_NR_mbind                 (TARGET_NR_Linux + 227) +#define TARGET_NR_get_mempolicy         (TARGET_NR_Linux + 228) +#define TARGET_NR_set_mempolicy         (TARGET_NR_Linux + 229) +#define TARGET_NR_mq_open               (TARGET_NR_Linux + 230) +#define TARGET_NR_mq_unlink             (TARGET_NR_Linux + 231) +#define TARGET_NR_mq_timedsend          (TARGET_NR_Linux + 232) +#define TARGET_NR_mq_timedreceive       (TARGET_NR_Linux + 233) +#define TARGET_NR_mq_notify             (TARGET_NR_Linux + 234) +#define TARGET_NR_mq_getsetattr         (TARGET_NR_Linux + 235) +#define TARGET_NR_vserver               (TARGET_NR_Linux + 236) +#define TARGET_NR_waitid                (TARGET_NR_Linux + 237) +/* #define TARGET_NR_sys_setaltroot     (TARGET_NR_Linux + 238) */ +#define TARGET_NR_add_key               (TARGET_NR_Linux + 239) +#define TARGET_NR_request_key           (TARGET_NR_Linux + 240) +#define TARGET_NR_keyctl                (TARGET_NR_Linux + 241) +#define TARGET_NR_set_thread_area       (TARGET_NR_Linux + 242) +#define TARGET_NR_inotify_init          (TARGET_NR_Linux + 243) +#define TARGET_NR_inotify_add_watch     (TARGET_NR_Linux + 244) +#define TARGET_NR_inotify_rm_watch      (TARGET_NR_Linux + 245) +#define TARGET_NR_migrate_pages         (TARGET_NR_Linux + 246) +#define TARGET_NR_openat                (TARGET_NR_Linux + 247) +#define TARGET_NR_mkdirat               (TARGET_NR_Linux + 248) +#define TARGET_NR_mknodat               (TARGET_NR_Linux + 249) +#define TARGET_NR_fchownat              (TARGET_NR_Linux + 250) +#define TARGET_NR_futimesat             (TARGET_NR_Linux + 251) +#define TARGET_NR_newfstatat            (TARGET_NR_Linux + 252) +#define TARGET_NR_unlinkat              (TARGET_NR_Linux + 253) +#define TARGET_NR_renameat              (TARGET_NR_Linux + 254) +#define TARGET_NR_linkat                (TARGET_NR_Linux + 255) +#define TARGET_NR_symlinkat             (TARGET_NR_Linux + 256) +#define TARGET_NR_readlinkat            (TARGET_NR_Linux + 257) +#define TARGET_NR_fchmodat              (TARGET_NR_Linux + 258) +#define TARGET_NR_faccessat             (TARGET_NR_Linux + 259) +#define TARGET_NR_pselect6              (TARGET_NR_Linux + 260) +#define TARGET_NR_ppoll                 (TARGET_NR_Linux + 261) +#define TARGET_NR_unshare               (TARGET_NR_Linux + 262) +#define TARGET_NR_splice                (TARGET_NR_Linux + 263) +#define TARGET_NR_sync_file_range       (TARGET_NR_Linux + 264) +#define TARGET_NR_tee                   (TARGET_NR_Linux + 265) +#define TARGET_NR_vmsplice              (TARGET_NR_Linux + 266) +#define TARGET_NR_move_pages            (TARGET_NR_Linux + 267) +#define TARGET_NR_set_robust_list       (TARGET_NR_Linux + 268) +#define TARGET_NR_get_robust_list       (TARGET_NR_Linux + 269) +#define TARGET_NR_kexec_load            (TARGET_NR_Linux + 270) +#define TARGET_NR_getcpu                (TARGET_NR_Linux + 271) +#define TARGET_NR_epoll_pwait           (TARGET_NR_Linux + 272) +#define TARGET_NR_ioprio_set            (TARGET_NR_Linux + 273) +#define TARGET_NR_ioprio_get            (TARGET_NR_Linux + 274) +#define TARGET_NR_utimensat             (TARGET_NR_Linux + 275) +#define TARGET_NR_signalfd              (TARGET_NR_Linux + 276) +#define TARGET_NR_timerfd               (TARGET_NR_Linux + 277) +#define TARGET_NR_eventfd               (TARGET_NR_Linux + 278) +#define TARGET_NR_fallocate             (TARGET_NR_Linux + 279) +#define TARGET_NR_timerfd_create        (TARGET_NR_Linux + 280) +#define TARGET_NR_timerfd_gettime       (TARGET_NR_Linux + 281) +#define TARGET_NR_timerfd_settime       (TARGET_NR_Linux + 282) +#define TARGET_NR_signalfd4             (TARGET_NR_Linux + 283) +#define TARGET_NR_eventfd2              (TARGET_NR_Linux + 284) +#define TARGET_NR_epoll_create1         (TARGET_NR_Linux + 285) +#define TARGET_NR_dup3                  (TARGET_NR_Linux + 286) +#define TARGET_NR_pipe2                 (TARGET_NR_Linux + 287) +#define TARGET_NR_inotify_init1         (TARGET_NR_Linux + 288) +#define TARGET_NR_preadv                (TARGET_NR_Linux + 289) +#define TARGET_NR_pwritev               (TARGET_NR_Linux + 290) +#define TARGET_NR_rt_tgsigqueueinfo     (TARGET_NR_Linux + 291) +#define TARGET_NR_perf_event_open       (TARGET_NR_Linux + 292) +#define TARGET_NR_accept4               (TARGET_NR_Linux + 293) +#define TARGET_NR_recvmmsg              (TARGET_NR_Linux + 294) +#define TARGET_NR_fanotify_init         (TARGET_NR_Linux + 295) +#define TARGET_NR_fanotify_mark         (TARGET_NR_Linux + 296) +#define TARGET_NR_prlimit64             (TARGET_NR_Linux + 297) +#define TARGET_NR_name_to_handle_at     (TARGET_NR_Linux + 298) +#define TARGET_NR_open_by_handle_at     (TARGET_NR_Linux + 299) +#define TARGET_NR_clock_adjtime         (TARGET_NR_Linux + 300) +#define TARGET_NR_syncfs                (TARGET_NR_Linux + 301) +#define TARGET_NR_sendmmsg              (TARGET_NR_Linux + 302) +#define TARGET_NR_setns                 (TARGET_NR_Linux + 303) +#define TARGET_NR_process_vm_readv      (TARGET_NR_Linux + 304) +#define TARGET_NR_process_vm_writev     (TARGET_NR_Linux + 305) +#define TARGET_NR_kcmp                  (TARGET_NR_Linux + 306) +#define TARGET_NR_finit_module          (TARGET_NR_Linux + 307) +#define TARGET_NR_getdents64            (TARGET_NR_Linux + 308) +#endif diff --git a/linux-user/mips64/target_cpu.h b/linux-user/mips64/target_cpu.h new file mode 100644 index 00000000..f16991b4 --- /dev/null +++ b/linux-user/mips64/target_cpu.h @@ -0,0 +1,19 @@ +/* + * MIPS64 specific structures for linux-user + * + * Copyright (c) 2013 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#include "../mips/target_cpu.h" diff --git a/linux-user/mips64/target_signal.h b/linux-user/mips64/target_signal.h new file mode 100644 index 00000000..5fb6a2cc --- /dev/null +++ b/linux-user/mips64/target_signal.h @@ -0,0 +1,29 @@ +#ifndef TARGET_SIGNAL_H +#define TARGET_SIGNAL_H + +#include "cpu.h" + +/* this struct defines a stack used during syscall handling */ + +typedef struct target_sigaltstack { +	abi_long ss_sp; +	abi_ulong ss_size; +	abi_int ss_flags; +} target_stack_t; + + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK     1 +#define TARGET_SS_DISABLE     2 + +#define TARGET_MINSIGSTKSZ    2048 +#define TARGET_SIGSTKSZ       8192 + +static inline abi_ulong get_sp_from_cpustate(CPUMIPSState *state) +{ +    return state->active_tc.gpr[29]; +} + +#endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/mips64/target_structs.h b/linux-user/mips64/target_structs.h new file mode 100644 index 00000000..a4f619e7 --- /dev/null +++ b/linux-user/mips64/target_structs.h @@ -0,0 +1,2 @@ +#include "../mips/target_structs.h" + diff --git a/linux-user/mips64/termbits.h b/linux-user/mips64/termbits.h new file mode 100644 index 00000000..d3a6cf8f --- /dev/null +++ b/linux-user/mips64/termbits.h @@ -0,0 +1,245 @@ +/* from asm/termbits.h */ + +#define TARGET_NCCS 23 + +struct target_termios { +    unsigned int c_iflag;               /* input mode flags */ +    unsigned int c_oflag;               /* output mode flags */ +    unsigned int c_cflag;               /* control mode flags */ +    unsigned int c_lflag;               /* local mode flags */ +    unsigned char c_line;                    /* line discipline */ +    unsigned char c_cc[TARGET_NCCS];                /* control characters */ +}; + +/* c_iflag bits */ +#define TARGET_IGNBRK  0000001 +#define TARGET_BRKINT  0000002 +#define TARGET_IGNPAR  0000004 +#define TARGET_PARMRK  0000010 +#define TARGET_INPCK   0000020 +#define TARGET_ISTRIP  0000040 +#define TARGET_INLCR   0000100 +#define TARGET_IGNCR   0000200 +#define TARGET_ICRNL   0000400 +#define TARGET_IUCLC   0001000 +#define TARGET_IXON    0002000 +#define TARGET_IXANY   0004000 +#define TARGET_IXOFF   0010000 +#define TARGET_IMAXBEL 0020000 +#define TARGET_IUTF8   0040000 + +/* c_oflag bits */ +#define TARGET_OPOST   0000001 +#define TARGET_OLCUC   0000002 +#define TARGET_ONLCR   0000004 +#define TARGET_OCRNL   0000010 +#define TARGET_ONOCR   0000020 +#define TARGET_ONLRET  0000040 +#define TARGET_OFILL   0000100 +#define TARGET_OFDEL   0000200 +#define TARGET_NLDLY   0000400 +#define   TARGET_NL0   0000000 +#define   TARGET_NL1   0000400 +#define TARGET_CRDLY   0003000 +#define   TARGET_CR0   0000000 +#define   TARGET_CR1   0001000 +#define   TARGET_CR2   0002000 +#define   TARGET_CR3   0003000 +#define TARGET_TABDLY  0014000 +#define   TARGET_TAB0  0000000 +#define   TARGET_TAB1  0004000 +#define   TARGET_TAB2  0010000 +#define   TARGET_TAB3  0014000 +#define   TARGET_XTABS 0014000 +#define TARGET_BSDLY   0020000 +#define   TARGET_BS0   0000000 +#define   TARGET_BS1   0020000 +#define TARGET_VTDLY   0040000 +#define   TARGET_VT0   0000000 +#define   TARGET_VT1   0040000 +#define TARGET_FFDLY   0100000 +#define   TARGET_FF0   0000000 +#define   TARGET_FF1   0100000 + +/* c_cflag bit meaning */ +#define TARGET_CBAUD   0010017 +#define  TARGET_B0     0000000         /* hang up */ +#define  TARGET_B50    0000001 +#define  TARGET_B75    0000002 +#define  TARGET_B110   0000003 +#define  TARGET_B134   0000004 +#define  TARGET_B150   0000005 +#define  TARGET_B200   0000006 +#define  TARGET_B300   0000007 +#define  TARGET_B600   0000010 +#define  TARGET_B1200  0000011 +#define  TARGET_B1800  0000012 +#define  TARGET_B2400  0000013 +#define  TARGET_B4800  0000014 +#define  TARGET_B9600  0000015 +#define  TARGET_B19200 0000016 +#define  TARGET_B38400 0000017 +#define TARGET_EXTA B19200 +#define TARGET_EXTB B38400 +#define TARGET_CSIZE   0000060 +#define   TARGET_CS5   0000000 +#define   TARGET_CS6   0000020 +#define   TARGET_CS7   0000040 +#define   TARGET_CS8   0000060 +#define TARGET_CSTOPB  0000100 +#define TARGET_CREAD   0000200 +#define TARGET_PARENB  0000400 +#define TARGET_PARODD  0001000 +#define TARGET_HUPCL   0002000 +#define TARGET_CLOCAL  0004000 +#define TARGET_CBAUDEX 0010000 +#define  TARGET_BOTHER   0010000 +#define  TARGET_B57600   0010001 +#define  TARGET_B115200  0010002 +#define  TARGET_B230400  0010003 +#define  TARGET_B460800  0010004 +#define  TARGET_B500000  0010005 +#define  TARGET_B576000  0010006 +#define  TARGET_B921600  0010007 +#define  TARGET_B1000000 0010010 +#define  TARGET_B1152000 0010011 +#define  TARGET_B1500000 0010012 +#define  TARGET_B2000000 0010013 +#define  TARGET_B2500000 0010014 +#define  TARGET_B3000000 0010015 +#define  TARGET_B3500000 0010016 +#define  TARGET_B4000000 0010017 +#define TARGET_CIBAUD    002003600000  /* input baud rate (not used) */ +#define TARGET_CMSPAR    010000000000  /* mark or space (stick) parity */ +#define TARGET_CRTSCTS   020000000000  /* flow control */ + +/* c_lflag bits */ +#define TARGET_ISIG    0000001 +#define TARGET_ICANON  0000002 +#define TARGET_XCASE   0000004 +#define TARGET_ECHO    0000010 +#define TARGET_ECHOE   0000020 +#define TARGET_ECHOK   0000040 +#define TARGET_ECHONL  0000100 +#define TARGET_NOFLSH  0000200 +#define TARGET_IEXTEN  0000400 +#define TARGET_ECHOCTL 0001000 +#define TARGET_ECHOPRT 0002000 +#define TARGET_ECHOKE  0004000 +#define TARGET_FLUSHO  0010000 +#define TARGET_PENDIN  0040000 +#define TARGET_TOSTOP  0100000 +#define TARGET_ITOSTOP TARGET_TOSTOP + +/* c_cc character offsets */ +#define TARGET_VINTR	0 +#define TARGET_VQUIT	1 +#define TARGET_VERASE	2 +#define TARGET_VKILL	3 +#define TARGET_VMIN	4 +#define TARGET_VTIME	5 +#define TARGET_VEOL2	6 +#define TARGET_VSWTC	7 +#define TARGET_VSTART	8 +#define TARGET_VSTOP	9 +#define TARGET_VSUSP	10 +/* VDSUSP not supported */ +#define TARGET_VREPRINT	12 +#define TARGET_VDISCARD	13 +#define TARGET_VWERASE	14 +#define TARGET_VLNEXT	15 +#define TARGET_VEOF	16 +#define TARGET_VEOL	17 + +/* ioctls */ + +#define TARGET_TCGETA		0x5401 +#define TARGET_TCSETA		0x5402	/* Clashes with SNDCTL_TMR_START sound ioctl */ +#define TARGET_TCSETAW		0x5403 +#define TARGET_TCSETAF		0x5404 + +#define TARGET_TCSBRK		0x5405 +#define TARGET_TCXONC		0x5406 +#define TARGET_TCFLSH		0x5407 + +#define TARGET_TCGETS		0x540d +#define TARGET_TCSETS		0x540e +#define TARGET_TCSETSW		0x540f +#define TARGET_TCSETSF		0x5410 + +#define TARGET_TIOCEXCL	0x740d		/* set exclusive use of tty */ +#define TARGET_TIOCNXCL	0x740e		/* reset exclusive use of tty */ +#define TARGET_TIOCOUTQ	0x7472		/* output queue size */ +#define TARGET_TIOCSTI	0x5472		/* simulate terminal input */ +#define TARGET_TIOCMGET	0x741d		/* get all modem bits */ +#define TARGET_TIOCMBIS	0x741b		/* bis modem bits */ +#define TARGET_TIOCMBIC	0x741c		/* bic modem bits */ +#define TARGET_TIOCMSET	0x741a		/* set all modem bits */ +#define TARGET_TIOCPKT		0x5470		/* pty: set/clear packet mode */ +#define	 TARGET_TIOCPKT_DATA		0x00	/* data packet */ +#define	 TARGET_TIOCPKT_FLUSHREAD	0x01	/* flush packet */ +#define	 TARGET_TIOCPKT_FLUSHWRITE	0x02	/* flush packet */ +#define	 TARGET_TIOCPKT_STOP		0x04	/* stop output */ +#define	 TARGET_TIOCPKT_START		0x08	/* start output */ +#define	 TARGET_TIOCPKT_NOSTOP		0x10	/* no more ^S, ^Q */ +#define	 TARGET_TIOCPKT_DOSTOP		0x20	/* now do ^S ^Q */ +/* #define  TIOCPKT_IOCTL		0x40	state change of pty driver */ +#define TARGET_TIOCSWINSZ	TARGET_IOW('t', 103, struct winsize)	/* set window size */ +#define TARGET_TIOCGWINSZ	TARGET_IOR('t', 104, struct winsize)	/* get window size */ +#define TARGET_TIOCNOTTY	0x5471		/* void tty association */ +#define TARGET_TIOCSETD	0x7401 +#define TARGET_TIOCGETD	0x7400 + +#define TARGET_FIOCLEX		0x6601 +#define TARGET_FIONCLEX	0x6602 +#define TARGET_FIOASYNC	0x667d +#define TARGET_FIONBIO		0x667e +#define TARGET_FIOQSIZE	0x667f + +#define TARGET_TIOCGLTC	0x7474			/* get special local chars */ +#define TARGET_TIOCSLTC	0x7475			/* set special local chars */ +#define TARGET_TIOCSPGRP	TARGET_IOW('t', 118, int)	/* set pgrp of tty */ +#define TARGET_TIOCGPGRP	TARGET_IOR('t', 119, int)	/* get pgrp of tty */ +#define TARGET_TIOCCONS	TARGET_IOW('t', 120, int)	/* become virtual console */ + +#define TARGET_FIONREAD	0x467f +#define TARGET_TIOCINQ		TARGET_FIONREAD + +#define TARGET_TIOCGETP        0x7408 +#define TARGET_TIOCSETP        0x7409 +#define TARGET_TIOCSETN        0x740a			/* TIOCSETP wo flush */ + +/* #define TARGET_TIOCSETA	TARGET_IOW('t', 20, struct termios) set termios struct */ +/* #define TARGET_TIOCSETAW	TARGET_IOW('t', 21, struct termios) drain output, set */ +/* #define TARGET_TIOCSETAF	TARGET_IOW('t', 22, struct termios) drn out, fls in, set */ +/* #define TARGET_TIOCGETD	TARGET_IOR('t', 26, int)	get line discipline */ +/* #define TARGET_TIOCSETD	TARGET_IOW('t', 27, int)	set line discipline */ +						/* 127-124 compat */ + +#define TARGET_TIOCSBRK	0x5427  /* BSD compatibility */ +#define TARGET_TIOCCBRK	0x5428  /* BSD compatibility */ +#define TARGET_TIOCGSID	0x7416  /* Return the session ID of FD */ +#define TARGET_TIOCGPTN	TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define TARGET_TIOCSPTLCK	TARGET_IOW('T',0x31, int)  /* Lock/unlock Pty */ + +/* I hope the range from 0x5480 on is free ... */ +#define TARGET_TIOCSCTTY	0x5480		/* become controlling tty */ +#define TARGET_TIOCGSOFTCAR	0x5481 +#define TARGET_TIOCSSOFTCAR	0x5482 +#define TARGET_TIOCLINUX	0x5483 +#define TARGET_TIOCGSERIAL	0x5484 +#define TARGET_TIOCSSERIAL	0x5485 +#define TARGET_TCSBRKP		0x5486	/* Needed for POSIX tcsendbreak() */ +#define TARGET_TIOCSERCONFIG	0x5488 +#define TARGET_TIOCSERGWILD	0x5489 +#define TARGET_TIOCSERSWILD	0x548a +#define TARGET_TIOCGLCKTRMIOS	0x548b +#define TARGET_TIOCSLCKTRMIOS	0x548c +#define TARGET_TIOCSERGSTRUCT	0x548d /* For debugging only */ +#define TARGET_TIOCSERGETLSR   0x548e /* Get line status register */ +#define TARGET_TIOCSERGETMULTI 0x548f /* Get multiport config  */ +#define TARGET_TIOCSERSETMULTI 0x5490 /* Set multiport config */ +#define TARGET_TIOCMIWAIT      0x5491 /* wait for a change on serial input line(s) */ +#define TARGET_TIOCGICOUNT     0x5492 /* read serial port inline interrupt counts */ +#define TARGET_TIOCGHAYESESP	0x5493 /* Get Hayes ESP configuration */ +#define TARGET_TIOCSHAYESESP	0x5494 /* Set Hayes ESP configuration */ diff --git a/linux-user/mmap.c b/linux-user/mmap.c new file mode 100644 index 00000000..78e1b2df --- /dev/null +++ b/linux-user/mmap.c @@ -0,0 +1,782 @@ +/* + *  mmap support for qemu + * + *  Copyright (c) 2003 Fabrice Bellard + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, see <http://www.gnu.org/licenses/>. + */ +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <linux/mman.h> +#include <linux/unistd.h> + +#include "qemu.h" +#include "qemu-common.h" +#include "translate-all.h" + +//#define DEBUG_MMAP + +static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER; +static __thread int mmap_lock_count; + +void mmap_lock(void) +{ +    if (mmap_lock_count++ == 0) { +        pthread_mutex_lock(&mmap_mutex); +    } +} + +void mmap_unlock(void) +{ +    if (--mmap_lock_count == 0) { +        pthread_mutex_unlock(&mmap_mutex); +    } +} + +/* Grab lock to make sure things are in a consistent state after fork().  */ +void mmap_fork_start(void) +{ +    if (mmap_lock_count) +        abort(); +    pthread_mutex_lock(&mmap_mutex); +} + +void mmap_fork_end(int child) +{ +    if (child) +        pthread_mutex_init(&mmap_mutex, NULL); +    else +        pthread_mutex_unlock(&mmap_mutex); +} + +/* NOTE: all the constants are the HOST ones, but addresses are target. */ +int target_mprotect(abi_ulong start, abi_ulong len, int prot) +{ +    abi_ulong end, host_start, host_end, addr; +    int prot1, ret; + +#ifdef DEBUG_MMAP +    printf("mprotect: start=0x" TARGET_ABI_FMT_lx +           "len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c\n", start, len, +           prot & PROT_READ ? 'r' : '-', +           prot & PROT_WRITE ? 'w' : '-', +           prot & PROT_EXEC ? 'x' : '-'); +#endif + +    if ((start & ~TARGET_PAGE_MASK) != 0) +        return -EINVAL; +    len = TARGET_PAGE_ALIGN(len); +    end = start + len; +    if (end < start) +        return -EINVAL; +    prot &= PROT_READ | PROT_WRITE | PROT_EXEC; +    if (len == 0) +        return 0; + +    mmap_lock(); +    host_start = start & qemu_host_page_mask; +    host_end = HOST_PAGE_ALIGN(end); +    if (start > host_start) { +        /* handle host page containing start */ +        prot1 = prot; +        for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) { +            prot1 |= page_get_flags(addr); +        } +        if (host_end == host_start + qemu_host_page_size) { +            for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) { +                prot1 |= page_get_flags(addr); +            } +            end = host_end; +        } +        ret = mprotect(g2h(host_start), qemu_host_page_size, prot1 & PAGE_BITS); +        if (ret != 0) +            goto error; +        host_start += qemu_host_page_size; +    } +    if (end < host_end) { +        prot1 = prot; +        for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) { +            prot1 |= page_get_flags(addr); +        } +        ret = mprotect(g2h(host_end - qemu_host_page_size), qemu_host_page_size, +                       prot1 & PAGE_BITS); +        if (ret != 0) +            goto error; +        host_end -= qemu_host_page_size; +    } + +    /* handle the pages in the middle */ +    if (host_start < host_end) { +        ret = mprotect(g2h(host_start), host_end - host_start, prot); +        if (ret != 0) +            goto error; +    } +    page_set_flags(start, start + len, prot | PAGE_VALID); +    mmap_unlock(); +    return 0; +error: +    mmap_unlock(); +    return ret; +} + +/* map an incomplete host page */ +static int mmap_frag(abi_ulong real_start, +                     abi_ulong start, abi_ulong end, +                     int prot, int flags, int fd, abi_ulong offset) +{ +    abi_ulong real_end, addr; +    void *host_start; +    int prot1, prot_new; + +    real_end = real_start + qemu_host_page_size; +    host_start = g2h(real_start); + +    /* get the protection of the target pages outside the mapping */ +    prot1 = 0; +    for(addr = real_start; addr < real_end; addr++) { +        if (addr < start || addr >= end) +            prot1 |= page_get_flags(addr); +    } + +    if (prot1 == 0) { +        /* no page was there, so we allocate one */ +        void *p = mmap(host_start, qemu_host_page_size, prot, +                       flags | MAP_ANONYMOUS, -1, 0); +        if (p == MAP_FAILED) +            return -1; +        prot1 = prot; +    } +    prot1 &= PAGE_BITS; + +    prot_new = prot | prot1; +    if (!(flags & MAP_ANONYMOUS)) { +        /* msync() won't work here, so we return an error if write is +           possible while it is a shared mapping */ +        if ((flags & MAP_TYPE) == MAP_SHARED && +            (prot & PROT_WRITE)) +            return -1; + +        /* adjust protection to be able to read */ +        if (!(prot1 & PROT_WRITE)) +            mprotect(host_start, qemu_host_page_size, prot1 | PROT_WRITE); + +        /* read the corresponding file data */ +        if (pread(fd, g2h(start), end - start, offset) == -1) +            return -1; + +        /* put final protection */ +        if (prot_new != (prot1 | PROT_WRITE)) +            mprotect(host_start, qemu_host_page_size, prot_new); +    } else { +        /* just update the protection */ +        if (prot_new != prot1) { +            mprotect(host_start, qemu_host_page_size, prot_new); +        } +    } +    return 0; +} + +#if HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64 +# define TASK_UNMAPPED_BASE  (1ul << 38) +#elif defined(__CYGWIN__) +/* Cygwin doesn't have a whole lot of address space.  */ +# define TASK_UNMAPPED_BASE  0x18000000 +#else +# define TASK_UNMAPPED_BASE  0x40000000 +#endif +abi_ulong mmap_next_start = TASK_UNMAPPED_BASE; + +unsigned long last_brk; + +#ifdef CONFIG_USE_GUEST_BASE +/* Subroutine of mmap_find_vma, used when we have pre-allocated a chunk +   of guest address space.  */ +static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size) +{ +    abi_ulong addr; +    abi_ulong end_addr; +    int prot; +    int looped = 0; + +    if (size > RESERVED_VA) { +        return (abi_ulong)-1; +    } + +    size = HOST_PAGE_ALIGN(size); +    end_addr = start + size; +    if (end_addr > RESERVED_VA) { +        end_addr = RESERVED_VA; +    } +    addr = end_addr - qemu_host_page_size; + +    while (1) { +        if (addr > end_addr) { +            if (looped) { +                return (abi_ulong)-1; +            } +            end_addr = RESERVED_VA; +            addr = end_addr - qemu_host_page_size; +            looped = 1; +            continue; +        } +        prot = page_get_flags(addr); +        if (prot) { +            end_addr = addr; +        } +        if (addr + size == end_addr) { +            break; +        } +        addr -= qemu_host_page_size; +    } + +    if (start == mmap_next_start) { +        mmap_next_start = addr; +    } + +    return addr; +} +#endif + +/* + * Find and reserve a free memory area of size 'size'. The search + * starts at 'start'. + * It must be called with mmap_lock() held. + * Return -1 if error. + */ +abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size) +{ +    void *ptr, *prev; +    abi_ulong addr; +    int wrapped, repeat; + +    /* If 'start' == 0, then a default start address is used. */ +    if (start == 0) { +        start = mmap_next_start; +    } else { +        start &= qemu_host_page_mask; +    } + +    size = HOST_PAGE_ALIGN(size); + +#ifdef CONFIG_USE_GUEST_BASE +    if (RESERVED_VA) { +        return mmap_find_vma_reserved(start, size); +    } +#endif + +    addr = start; +    wrapped = repeat = 0; +    prev = 0; + +    for (;; prev = ptr) { +        /* +         * Reserve needed memory area to avoid a race. +         * It should be discarded using: +         *  - mmap() with MAP_FIXED flag +         *  - mremap() with MREMAP_FIXED flag +         *  - shmat() with SHM_REMAP flag +         */ +        ptr = mmap(g2h(addr), size, PROT_NONE, +                   MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE, -1, 0); + +        /* ENOMEM, if host address space has no memory */ +        if (ptr == MAP_FAILED) { +            return (abi_ulong)-1; +        } + +        /* Count the number of sequential returns of the same address. +           This is used to modify the search algorithm below.  */ +        repeat = (ptr == prev ? repeat + 1 : 0); + +        if (h2g_valid(ptr + size - 1)) { +            addr = h2g(ptr); + +            if ((addr & ~TARGET_PAGE_MASK) == 0) { +                /* Success.  */ +                if (start == mmap_next_start && addr >= TASK_UNMAPPED_BASE) { +                    mmap_next_start = addr + size; +                } +                return addr; +            } + +            /* The address is not properly aligned for the target.  */ +            switch (repeat) { +            case 0: +                /* Assume the result that the kernel gave us is the +                   first with enough free space, so start again at the +                   next higher target page.  */ +                addr = TARGET_PAGE_ALIGN(addr); +                break; +            case 1: +                /* Sometimes the kernel decides to perform the allocation +                   at the top end of memory instead.  */ +                addr &= TARGET_PAGE_MASK; +                break; +            case 2: +                /* Start over at low memory.  */ +                addr = 0; +                break; +            default: +                /* Fail.  This unaligned block must the last.  */ +                addr = -1; +                break; +            } +        } else { +            /* Since the result the kernel gave didn't fit, start +               again at low memory.  If any repetition, fail.  */ +            addr = (repeat ? -1 : 0); +        } + +        /* Unmap and try again.  */ +        munmap(ptr, size); + +        /* ENOMEM if we checked the whole of the target address space.  */ +        if (addr == (abi_ulong)-1) { +            return (abi_ulong)-1; +        } else if (addr == 0) { +            if (wrapped) { +                return (abi_ulong)-1; +            } +            wrapped = 1; +            /* Don't actually use 0 when wrapping, instead indicate +               that we'd truly like an allocation in low memory.  */ +            addr = (mmap_min_addr > TARGET_PAGE_SIZE +                     ? TARGET_PAGE_ALIGN(mmap_min_addr) +                     : TARGET_PAGE_SIZE); +        } else if (wrapped && addr >= start) { +            return (abi_ulong)-1; +        } +    } +} + +/* NOTE: all the constants are the HOST ones */ +abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, +                     int flags, int fd, abi_ulong offset) +{ +    abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len; + +    mmap_lock(); +#ifdef DEBUG_MMAP +    { +        printf("mmap: start=0x" TARGET_ABI_FMT_lx +               " len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c flags=", +               start, len, +               prot & PROT_READ ? 'r' : '-', +               prot & PROT_WRITE ? 'w' : '-', +               prot & PROT_EXEC ? 'x' : '-'); +        if (flags & MAP_FIXED) +            printf("MAP_FIXED "); +        if (flags & MAP_ANONYMOUS) +            printf("MAP_ANON "); +        switch(flags & MAP_TYPE) { +        case MAP_PRIVATE: +            printf("MAP_PRIVATE "); +            break; +        case MAP_SHARED: +            printf("MAP_SHARED "); +            break; +        default: +            printf("[MAP_TYPE=0x%x] ", flags & MAP_TYPE); +            break; +        } +        printf("fd=%d offset=" TARGET_ABI_FMT_lx "\n", fd, offset); +    } +#endif + +    if (offset & ~TARGET_PAGE_MASK) { +        errno = EINVAL; +        goto fail; +    } + +    len = TARGET_PAGE_ALIGN(len); +    if (len == 0) +        goto the_end; +    real_start = start & qemu_host_page_mask; +    host_offset = offset & qemu_host_page_mask; + +    /* If the user is asking for the kernel to find a location, do that +       before we truncate the length for mapping files below.  */ +    if (!(flags & MAP_FIXED)) { +        host_len = len + offset - host_offset; +        host_len = HOST_PAGE_ALIGN(host_len); +        start = mmap_find_vma(real_start, host_len); +        if (start == (abi_ulong)-1) { +            errno = ENOMEM; +            goto fail; +        } +    } + +    /* When mapping files into a memory area larger than the file, accesses +       to pages beyond the file size will cause a SIGBUS.  + +       For example, if mmaping a file of 100 bytes on a host with 4K pages +       emulating a target with 8K pages, the target expects to be able to +       access the first 8K. But the host will trap us on any access beyond +       4K.   + +       When emulating a target with a larger page-size than the hosts, we +       may need to truncate file maps at EOF and add extra anonymous pages +       up to the targets page boundary.  */ + +    if ((qemu_real_host_page_size < TARGET_PAGE_SIZE) +        && !(flags & MAP_ANONYMOUS)) { +       struct stat sb; + +       if (fstat (fd, &sb) == -1) +           goto fail; + +       /* Are we trying to create a map beyond EOF?.  */ +       if (offset + len > sb.st_size) { +           /* If so, truncate the file map at eof aligned with  +              the hosts real pagesize. Additional anonymous maps +              will be created beyond EOF.  */ +           len = (sb.st_size - offset); +           len += qemu_real_host_page_size - 1; +           len &= ~(qemu_real_host_page_size - 1); +       } +    } + +    if (!(flags & MAP_FIXED)) { +        unsigned long host_start; +        void *p; + +        host_len = len + offset - host_offset; +        host_len = HOST_PAGE_ALIGN(host_len); + +        /* Note: we prefer to control the mapping address. It is +           especially important if qemu_host_page_size > +           qemu_real_host_page_size */ +        p = mmap(g2h(start), host_len, prot, +                 flags | MAP_FIXED | MAP_ANONYMOUS, -1, 0); +        if (p == MAP_FAILED) +            goto fail; +        /* update start so that it points to the file position at 'offset' */ +        host_start = (unsigned long)p; +        if (!(flags & MAP_ANONYMOUS)) { +            p = mmap(g2h(start), len, prot, +                     flags | MAP_FIXED, fd, host_offset); +            if (p == MAP_FAILED) { +                munmap(g2h(start), host_len); +                goto fail; +            } +            host_start += offset - host_offset; +        } +        start = h2g(host_start); +    } else { +        if (start & ~TARGET_PAGE_MASK) { +            errno = EINVAL; +            goto fail; +        } +        end = start + len; +        real_end = HOST_PAGE_ALIGN(end); + +	/* +	 * Test if requested memory area fits target address space +	 * It can fail only on 64-bit host with 32-bit target. +	 * On any other target/host host mmap() handles this error correctly. +	 */ +        if ((unsigned long)start + len - 1 > (abi_ulong) -1) { +            errno = EINVAL; +            goto fail; +        } + +        /* worst case: we cannot map the file because the offset is not +           aligned, so we read it */ +        if (!(flags & MAP_ANONYMOUS) && +            (offset & ~qemu_host_page_mask) != (start & ~qemu_host_page_mask)) { +            /* msync() won't work here, so we return an error if write is +               possible while it is a shared mapping */ +            if ((flags & MAP_TYPE) == MAP_SHARED && +                (prot & PROT_WRITE)) { +                errno = EINVAL; +                goto fail; +            } +            retaddr = target_mmap(start, len, prot | PROT_WRITE, +                                  MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, +                                  -1, 0); +            if (retaddr == -1) +                goto fail; +            if (pread(fd, g2h(start), len, offset) == -1) +                goto fail; +            if (!(prot & PROT_WRITE)) { +                ret = target_mprotect(start, len, prot); +                if (ret != 0) { +                    start = ret; +                    goto the_end; +                } +            } +            goto the_end; +        } +         +        /* handle the start of the mapping */ +        if (start > real_start) { +            if (real_end == real_start + qemu_host_page_size) { +                /* one single host page */ +                ret = mmap_frag(real_start, start, end, +                                prot, flags, fd, offset); +                if (ret == -1) +                    goto fail; +                goto the_end1; +            } +            ret = mmap_frag(real_start, start, real_start + qemu_host_page_size, +                            prot, flags, fd, offset); +            if (ret == -1) +                goto fail; +            real_start += qemu_host_page_size; +        } +        /* handle the end of the mapping */ +        if (end < real_end) { +            ret = mmap_frag(real_end - qemu_host_page_size, +                            real_end - qemu_host_page_size, real_end, +                            prot, flags, fd, +                            offset + real_end - qemu_host_page_size - start); +            if (ret == -1) +                goto fail; +            real_end -= qemu_host_page_size; +        } + +        /* map the middle (easier) */ +        if (real_start < real_end) { +            void *p; +            unsigned long offset1; +            if (flags & MAP_ANONYMOUS) +                offset1 = 0; +            else +                offset1 = offset + real_start - start; +            p = mmap(g2h(real_start), real_end - real_start, +                     prot, flags, fd, offset1); +            if (p == MAP_FAILED) +                goto fail; +        } +    } + the_end1: +    page_set_flags(start, start + len, prot | PAGE_VALID); + the_end: +#ifdef DEBUG_MMAP +    printf("ret=0x" TARGET_ABI_FMT_lx "\n", start); +    page_dump(stdout); +    printf("\n"); +#endif +    tb_invalidate_phys_range(start, start + len); +    mmap_unlock(); +    return start; +fail: +    mmap_unlock(); +    return -1; +} + +static void mmap_reserve(abi_ulong start, abi_ulong size) +{ +    abi_ulong real_start; +    abi_ulong real_end; +    abi_ulong addr; +    abi_ulong end; +    int prot; + +    real_start = start & qemu_host_page_mask; +    real_end = HOST_PAGE_ALIGN(start + size); +    end = start + size; +    if (start > real_start) { +        /* handle host page containing start */ +        prot = 0; +        for (addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) { +            prot |= page_get_flags(addr); +        } +        if (real_end == real_start + qemu_host_page_size) { +            for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) { +                prot |= page_get_flags(addr); +            } +            end = real_end; +        } +        if (prot != 0) +            real_start += qemu_host_page_size; +    } +    if (end < real_end) { +        prot = 0; +        for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) { +            prot |= page_get_flags(addr); +        } +        if (prot != 0) +            real_end -= qemu_host_page_size; +    } +    if (real_start != real_end) { +        mmap(g2h(real_start), real_end - real_start, PROT_NONE, +                 MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, +                 -1, 0); +    } +} + +int target_munmap(abi_ulong start, abi_ulong len) +{ +    abi_ulong end, real_start, real_end, addr; +    int prot, ret; + +#ifdef DEBUG_MMAP +    printf("munmap: start=0x" TARGET_ABI_FMT_lx " len=0x" +           TARGET_ABI_FMT_lx "\n", +           start, len); +#endif +    if (start & ~TARGET_PAGE_MASK) +        return -EINVAL; +    len = TARGET_PAGE_ALIGN(len); +    if (len == 0) +        return -EINVAL; +    mmap_lock(); +    end = start + len; +    real_start = start & qemu_host_page_mask; +    real_end = HOST_PAGE_ALIGN(end); + +    if (start > real_start) { +        /* handle host page containing start */ +        prot = 0; +        for(addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) { +            prot |= page_get_flags(addr); +        } +        if (real_end == real_start + qemu_host_page_size) { +            for(addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) { +                prot |= page_get_flags(addr); +            } +            end = real_end; +        } +        if (prot != 0) +            real_start += qemu_host_page_size; +    } +    if (end < real_end) { +        prot = 0; +        for(addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) { +            prot |= page_get_flags(addr); +        } +        if (prot != 0) +            real_end -= qemu_host_page_size; +    } + +    ret = 0; +    /* unmap what we can */ +    if (real_start < real_end) { +        if (RESERVED_VA) { +            mmap_reserve(real_start, real_end - real_start); +        } else { +            ret = munmap(g2h(real_start), real_end - real_start); +        } +    } + +    if (ret == 0) { +        page_set_flags(start, start + len, 0); +        tb_invalidate_phys_range(start, start + len); +    } +    mmap_unlock(); +    return ret; +} + +abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size, +                       abi_ulong new_size, unsigned long flags, +                       abi_ulong new_addr) +{ +    int prot; +    void *host_addr; + +    mmap_lock(); + +    if (flags & MREMAP_FIXED) { +        host_addr = (void *) syscall(__NR_mremap, g2h(old_addr), +                                     old_size, new_size, +                                     flags, +                                     g2h(new_addr)); + +        if (RESERVED_VA && host_addr != MAP_FAILED) { +            /* If new and old addresses overlap then the above mremap will +               already have failed with EINVAL.  */ +            mmap_reserve(old_addr, old_size); +        } +    } else if (flags & MREMAP_MAYMOVE) { +        abi_ulong mmap_start; + +        mmap_start = mmap_find_vma(0, new_size); + +        if (mmap_start == -1) { +            errno = ENOMEM; +            host_addr = MAP_FAILED; +        } else { +            host_addr = (void *) syscall(__NR_mremap, g2h(old_addr), +                                         old_size, new_size, +                                         flags | MREMAP_FIXED, +                                         g2h(mmap_start)); +            if ( RESERVED_VA ) { +                mmap_reserve(old_addr, old_size); +            } +        } +    } else { +        int prot = 0; +        if (RESERVED_VA && old_size < new_size) { +            abi_ulong addr; +            for (addr = old_addr + old_size; +                 addr < old_addr + new_size; +                 addr++) { +                prot |= page_get_flags(addr); +            } +        } +        if (prot == 0) { +            host_addr = mremap(g2h(old_addr), old_size, new_size, flags); +            if (host_addr != MAP_FAILED && RESERVED_VA && old_size > new_size) { +                mmap_reserve(old_addr + old_size, new_size - old_size); +            } +        } else { +            errno = ENOMEM; +            host_addr = MAP_FAILED; +        } +        /* Check if address fits target address space */ +        if ((unsigned long)host_addr + new_size > (abi_ulong)-1) { +            /* Revert mremap() changes */ +            host_addr = mremap(g2h(old_addr), new_size, old_size, flags); +            errno = ENOMEM; +            host_addr = MAP_FAILED; +        } +    } + +    if (host_addr == MAP_FAILED) { +        new_addr = -1; +    } else { +        new_addr = h2g(host_addr); +        prot = page_get_flags(old_addr); +        page_set_flags(old_addr, old_addr + old_size, 0); +        page_set_flags(new_addr, new_addr + new_size, prot | PAGE_VALID); +    } +    tb_invalidate_phys_range(new_addr, new_addr + new_size); +    mmap_unlock(); +    return new_addr; +} + +int target_msync(abi_ulong start, abi_ulong len, int flags) +{ +    abi_ulong end; + +    if (start & ~TARGET_PAGE_MASK) +        return -EINVAL; +    len = TARGET_PAGE_ALIGN(len); +    end = start + len; +    if (end < start) +        return -EINVAL; +    if (end == start) +        return 0; + +    start &= qemu_host_page_mask; +    return msync(g2h(start), end - start, flags); +} diff --git a/linux-user/openrisc/syscall.h b/linux-user/openrisc/syscall.h new file mode 100644 index 00000000..8ac03656 --- /dev/null +++ b/linux-user/openrisc/syscall.h @@ -0,0 +1,29 @@ +struct target_pt_regs { +    union { +        struct { +            /* Named registers */ +            uint32_t sr;       /* Stored in place of r0 */ +            target_ulong sp;   /* r1 */ +        }; +        struct { +            /* Old style */ +            target_ulong offset[2]; +            target_ulong gprs[30]; +        }; +        struct { +            /* New style */ +            target_ulong gpr[32]; +        }; +    }; +    target_ulong pc; +    target_ulong orig_gpr11;   /* For restarting system calls */ +    uint32_t syscallno;        /* Syscall number (used by strace) */ +    target_ulong dummy;     /* Cheap alignment fix */ +}; + +#define UNAME_MACHINE "openrisc" +#define UNAME_MINIMUM_RELEASE "2.6.32" + +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_MLOCKALL_MCL_CURRENT 1 +#define TARGET_MLOCKALL_MCL_FUTURE  2 diff --git a/linux-user/openrisc/syscall_nr.h b/linux-user/openrisc/syscall_nr.h new file mode 100644 index 00000000..4c386eae --- /dev/null +++ b/linux-user/openrisc/syscall_nr.h @@ -0,0 +1,510 @@ +#define TARGET_NR_io_setup 0 +#define TARGET_NR_io_destroy 1 +#define TARGET_NR_io_submit 2 +#define TARGET_NR_io_cancel 3 +#define TARGET_NR_io_getevents 4 + +/* fs/xattr.c */ +#define TARGET_NR_setxattr 5 +#define TARGET_NR_lsetxattr 6 +#define TARGET_NR_fsetxattr 7 +#define TARGET_NR_getxattr 8 +#define TARGET_NR_lgetxattr 9 +#define TARGET_NR_fgetxattr 10 +#define TARGET_NR_listxattr 11 +#define TARGET_NR_llistxattr 12 +#define TARGET_NR_flistxattr 13 +#define TARGET_NR_removexattr 14 +#define TARGET_NR_lremovexattr 15 +#define TARGET_NR_fremovexattr 16 + +/* fs/dcache.c */ +#define TARGET_NR_getcwd 17 + +/* fs/cookies.c */ +#define TARGET_NR_lookup_dcookie 18 + +/* fs/eventfd.c */ +#define TARGET_NR_eventfd2 19 + +/* fs/eventpoll.c */ +#define TARGET_NR_epoll_create1 20 +#define TARGET_NR_epoll_ctl 21 +#define TARGET_NR_epoll_pwait 22 + +/* fs/fcntl.c */ +#define TARGET_NR_dup 23 +#define TARGET_NR_dup3 24 +#define TARGET_NR_3264_fcntl 25 + +/* fs/inotify_user.c */ +#define TARGET_NR_inotify_init1 26 +#define TARGET_NR_inotify_add_watch 27 +#define TARGET_NR_inotify_rm_watch 28 + +/* fs/ioctl.c */ +#define TARGET_NR_ioctl 29 + +/* fs/ioprio.c */ +#define TARGET_NR_ioprio_set 30 +#define TARGET_NR_ioprio_get 31 + +/* fs/locks.c */ +#define TARGET_NR_flock 32 + +/* fs/namei.c */ +#define TARGET_NR_mknodat 33 +#define TARGET_NR_mkdirat 34 +#define TARGET_NR_unlinkat 35 +#define TARGET_NR_symlinkat 36 +#define TARGET_NR_linkat 37 +#define TARGET_NR_renameat 38 + +/* fs/namespace.c */ +#define TARGET_NR_umount2 39 +#define TARGET_NR_mount 40 +#define TARGET_NR_pivot_root 41 + +/* fs/nfsctl.c */ +#define TARGET_NR_nfsservctl 42 + +/* fs/open.c */ +#define TARGET_NR_3264_statfs 43 +#define TARGET_NR_3264_fstatfs 44 +#define TARGET_NR_3264_truncate 45 +#define TARGET_NR_3264_ftruncate 46 + +#define TARGET_NR_fallocate 47 +#define TARGET_NR_faccessat 48 +#define TARGET_NR_chdir 49 +#define TARGET_NR_fchdir 50 +#define TARGET_NR_chroot 51 +#define TARGET_NR_fchmod 52 +#define TARGET_NR_fchmodat 53 +#define TARGET_NR_fchownat 54 +#define TARGET_NR_fchown 55 +#define TARGET_NR_openat 56 +#define TARGET_NR_close 57 +#define TARGET_NR_vhangup 58 + +/* fs/pipe.c */ +#define TARGET_NR_pipe2 59 + +/* fs/quota.c */ +#define TARGET_NR_quotactl 60 + +/* fs/readdir.c */ +#define TARGET_NR_getdents64 61 + +/* fs/read_write.c */ +#define TARGET_NR_3264_lseek 62 +#define TARGET_NR_read 63 +#define TARGET_NR_write 64 +#define TARGET_NR_readv 65 +#define TARGET_NR_writev 66 +#define TARGET_NR_pread64 67 +#define TARGET_NR_pwrite64 68 +#define TARGET_NR_preadv 69 +#define TARGET_NR_pwritev 70 + +/* fs/sendfile.c */ +#define TARGET_NR_3264_sendfile 71 + +/* fs/select.c */ +#define TARGET_NR_pselect6 72 +#define TARGET_NR_ppoll 73 + +/* fs/signalfd.c */ +#define TARGET_NR_signalfd4 74 + +/* fs/splice.c */ +#define TARGET_NR_vmsplice 75 +#define TARGET_NR_splice 76 +#define TARGET_NR_tee 77 + +/* fs/stat.c */ +#define TARGET_NR_readlinkat 78 +#define TARGET_NR_3264_fstatat 79 +#define TARGET_NR_3264_fstat 80 + +/* fs/sync.c */ +#define TARGET_NR_sync 81 +#define TARGET_NR_fsync 82 +#define TARGET_NR_fdatasync 83 + +#ifdef __ARCH_WANT_SYNC_FILE_RANGE2 +#define TARGET_NR_sync_file_range2 84 +#else +#define TARGET_NR_sync_file_range 84 +#endif + +/* fs/timerfd.c */ +#define TARGET_NR_timerfd_create 85 +#define TARGET_NR_timerfd_settime 86 +#define TARGET_NR_timerfd_gettime 87 + +/* fs/utimes.c */ +#define TARGET_NR_utimensat 88 + +/* kernel/acct.c */ +#define TARGET_NR_acct 89 + +/* kernel/capability.c */ +#define TARGET_NR_capget 90 +#define TARGET_NR_capset 91 + +/* kernel/exec_domain.c */ +#define TARGET_NR_personality 92 + +/* kernel/exit.c */ +#define TARGET_NR_exit 93 +#define TARGET_NR_exit_group 94 +#define TARGET_NR_waitid 95 + +/* kernel/fork.c */ +#define TARGET_NR_set_tid_address 96 +#define TARGET_NR_unshare 97 + +/* kernel/futex.c */ +#define TARGET_NR_futex 98 +#define TARGET_NR_set_robust_list 99 +#define TARGET_NR_get_robust_list 100 + +/* kernel/hrtimer.c */ +#define TARGET_NR_nanosleep 101 + +/* kernel/itimer.c */ +#define TARGET_NR_getitimer 102 +#define TARGET_NR_setitimer 103 + +/* kernel/kexec.c */ +#define TARGET_NR_kexec_load 104 + +/* kernel/module.c */ +#define TARGET_NR_init_module 105 +#define TARGET_NR_delete_module 106 + +/* kernel/posix-timers.c */ +#define TARGET_NR_timer_create 107 +#define TARGET_NR_timer_gettime 108 +#define TARGET_NR_timer_getoverrun 109 +#define TARGET_NR_timer_settime 110 +#define TARGET_NR_timer_delete 111 +#define TARGET_NR_clock_settime 112 +#define TARGET_NR_clock_gettime 113 +#define TARGET_NR_clock_getres 114 +#define TARGET_NR_clock_nanosleep 115 + +/* kernel/printk.c */ +#define TARGET_NR_syslog 116 + +/* kernel/ptrace.c */ +#define TARGET_NR_ptrace 117 + +/* kernel/sched.c */ +#define TARGET_NR_sched_setparam 118 +#define TARGET_NR_sched_setscheduler 119 +#define TARGET_NR_sched_getscheduler 120 +#define TARGET_NR_sched_getparam 121 +#define TARGET_NR_sched_setaffinity 122 +#define TARGET_NR_sched_getaffinity 123 +#define TARGET_NR_sched_yield 124 +#define TARGET_NR_sched_get_priority_max 125 +#define TARGET_NR_sched_get_priority_min 126 +#define TARGET_NR_sched_rr_get_interval 127 + +/* kernel/signal.c */ +#define TARGET_NR_restart_syscall 128 +#define TARGET_NR_kill 129 +#define TARGET_NR_tkill 130 +#define TARGET_NR_tgkill 131 +#define TARGET_NR_sigaltstack 132 +#define TARGET_NR_rt_sigsuspend 133 +#define TARGET_NR_rt_sigaction 134 +#define TARGET_NR_rt_sigprocmask 135 +#define TARGET_NR_rt_sigpending 136 +#define TARGET_NR_rt_sigtimedwait 137 +#define TARGET_NR_rt_sigqueueinfo 138 +#define TARGET_NR_rt_sigreturn 139 + +/* kernel/sys.c */ +#define TARGET_NR_setpriority 140 +#define TARGET_NR_getpriority 141 +#define TARGET_NR_reboot 142 +#define TARGET_NR_setregid 143 +#define TARGET_NR_setgid 144 +#define TARGET_NR_setreuid 145 +#define TARGET_NR_setuid 146 +#define TARGET_NR_setresuid 147 +#define TARGET_NR_getresuid 148 +#define TARGET_NR_setresgid 149 +#define TARGET_NR_getresgid 150 +#define TARGET_NR_setfsuid 151 +#define TARGET_NR_setfsgid 152 +#define TARGET_NR_times 153 +#define TARGET_NR_setpgid 154 +#define TARGET_NR_getpgid 155 +#define TARGET_NR_getsid 156 +#define TARGET_NR_setsid 157 +#define TARGET_NR_getgroups 158 +#define TARGET_NR_setgroups 159 +#define TARGET_NR_uname 160 +#define TARGET_NR_sethostname 161 +#define TARGET_NR_setdomainname 162 +#define TARGET_NR_getrlimit 163 +#define TARGET_NR_setrlimit 164 +#define TARGET_NR_getrusage 165 +#define TARGET_NR_umask 166 +#define TARGET_NR_prctl 167 +#define TARGET_NR_getcpu 168 + +/* kernel/time.c */ +#define TARGET_NR_gettimeofday 169 +#define TARGET_NR_settimeofday 170 +#define TARGET_NR_adjtimex 171 + +/* kernel/timer.c */ +#define TARGET_NR_getpid 172 +#define TARGET_NR_getppid 173 +#define TARGET_NR_getuid 174 +#define TARGET_NR_geteuid 175 +#define TARGET_NR_getgid 176 +#define TARGET_NR_getegid 177 +#define TARGET_NR_gettid 178 +#define TARGET_NR_sysinfo 179 + +/* ipc/mqueue.c */ +#define TARGET_NR_mq_open 180 +#define TARGET_NR_mq_unlink 181 +#define TARGET_NR_mq_timedsend 182 +#define TARGET_NR_mq_timedreceive 183 +#define TARGET_NR_mq_notify 184 +#define TARGET_NR_mq_getsetattr 185 + +/* ipc/msg.c */ +#define TARGET_NR_msgget 186 +#define TARGET_NR_msgctl 187 +#define TARGET_NR_msgrcv 188 +#define TARGET_NR_msgsnd 189 + +/* ipc/sem.c */ +#define TARGET_NR_semget 190 +#define TARGET_NR_semctl 191 +#define TARGET_NR_semtimedop 192 +#define TARGET_NR_semop 193 + +/* ipc/shm.c */ +#define TARGET_NR_shmget 194 +#define TARGET_NR_shmctl 195 +#define TARGET_NR_shmat 196 +#define TARGET_NR_shmdt 197 + +/* net/socket.c */ +#define TARGET_NR_socket 198 +#define TARGET_NR_socketpair 199 +#define TARGET_NR_bind 200 +#define TARGET_NR_listen 201 +#define TARGET_NR_accept 202 +#define TARGET_NR_connect 203 +#define TARGET_NR_getsockname 204 +#define TARGET_NR_getpeername 205 +#define TARGET_NR_sendto 206 +#define TARGET_NR_recvfrom 207 +#define TARGET_NR_setsockopt 208 +#define TARGET_NR_getsockopt 209 +#define TARGET_NR_shutdown 210 +#define TARGET_NR_sendmsg 211 +#define TARGET_NR_recvmsg 212 + +/* mm/filemap.c */ +#define TARGET_NR_readahead 213 + +/* mm/nommu.c, also with MMU */ +#define TARGET_NR_brk 214 +#define TARGET_NR_munmap 215 +#define TARGET_NR_mremap 216 + +/* security/keys/keyctl.c */ +#define TARGET_NR_add_key 217 +#define TARGET_NR_request_key 218 +#define TARGET_NR_keyctl 219 + +/* arch/example/kernel/sys_example.c */ +#define TARGET_NR_clone 220 +#define TARGET_NR_execve 221 + +#define TARGET_NR_3264_mmap 222 +/* mm/fadvise.c */ +#define TARGET_NR_3264_fadvise64 223 + +/* mm/, CONFIG_MMU only */ +#ifndef __ARCH_NOMMU +#define TARGET_NR_swapon 224 +#define TARGET_NR_swapoff 225 +#define TARGET_NR_mprotect 226 +#define TARGET_NR_msync 227 +#define TARGET_NR_mlock 228 +#define TARGET_NR_munlock 229 +#define TARGET_NR_mlockall 230 +#define TARGET_NR_munlockall 231 +#define TARGET_NR_mincore 232 +#define TARGET_NR_madvise 233 +#define TARGET_NR_remap_file_pages 234 +#define TARGET_NR_mbind 235 +#define TARGET_NR_get_mempolicy 236 +#define TARGET_NR_set_mempolicy 237 +#define TARGET_NR_migrate_pages 238 +#define TARGET_NR_move_pages 239 +#endif + +#define TARGET_NR_rt_tgsigqueueinfo 240 +#define TARGET_NR_perf_event_open 241 +#define TARGET_NR_accept4 242 +#define TARGET_NR_recvmmsg 243 + +/* + * Architectures may provide up to 16 syscalls of their own + * starting with this value. + */ +#define TARGET_NR_arch_specific_syscall 244 + +#define TARGET_NR_wait4 260 +#define TARGET_NR_prlimit64 261 +#define TARGET_NR_fanotify_init 262 +#define TARGET_NR_fanotify_mark 263 +#define TARGET_NR_name_to_handle_at         264 +#define TARGET_NR_open_by_handle_at         265 +#define TARGET_NR_clock_adjtime 266 +#define TARGET_NR_syncfs 267 +#define TARGET_NR_setns 268 +#define TARGET_NR_sendmmsg 269 +#define TARGET_NR_process_vm_readv 270 +#define TARGET_NR_process_vm_writev 271 +#define TARGET_NR_kcmp 272 +#define TARGET_NR_finit_module 273 + +#undef TARGET_NR_syscalls +#define TARGET_NR_syscalls 274 + +/* + * All syscalls below here should go away really, + * these are provided for both review and as a porting + * help for the C library version. +* + * Last chance: are any of these important enough to + * enable by default? + */ +#define TARGET_NR_open 1024 +#define TARGET_NR_link 1025 +#define TARGET_NR_unlink 1026 +#define TARGET_NR_mknod 1027 +#define TARGET_NR_chmod 1028 +#define TARGET_NR_chown 1029 +#define TARGET_NR_mkdir 1030 +#define TARGET_NR_rmdir 1031 +#define TARGET_NR_lchown 1032 +#define TARGET_NR_access 1033 +#define TARGET_NR_rename 1034 +#define TARGET_NR_readlink 1035 +#define TARGET_NR_symlink 1036 +#define TARGET_NR_utimes 1037 +#define TARGET_NR_3264_stat 1038 +#define TARGET_NR_3264_lstat 1039 + +#undef TARGET_NR_syscalls +#define TARGET_NR_syscalls (TARGET_NR_3264_lstat+1) + +#define TARGET_NR_pipe 1040 +#define TARGET_NR_dup2 1041 +#define TARGET_NR_epoll_create 1042 +#define TARGET_NR_inotify_init 1043 +#define TARGET_NR_eventfd 1044 +#define TARGET_NR_signalfd 1045 + +#undef TARGET_NR_syscalls +#define TARGET_NR_syscalls (TARGET_NR_signalfd+1) + + +#define TARGET_NR_sendfile 1046 +#define TARGET_NR_ftruncate 1047 +#define TARGET_NR_truncate 1048 +#define TARGET_NR_stat 1049 +#define TARGET_NR_lstat 1050 +#define TARGET_NR_fstat 1051 +#define TARGET_NR_fcntl 1052 +#define TARGET_NR_fadvise64 1053 +#define __ARCH_WANT_SYS_FADVISE64 +#define TARGET_NR_newfstatat 1054 +#define __ARCH_WANT_SYS_NEWFSTATAT +#define TARGET_NR_fstatfs 1055 +#define TARGET_NR_statfs 1056 +#define TARGET_NR_lseek 1057 +#define TARGET_NR_mmap 1058 + +#undef TARGET_NR_syscalls +#define TARGET_NR_syscalls (TARGET_NR_mmap+1) + +#define TARGET_NR_alarm 1059 +#define __ARCH_WANT_SYS_ALARM +#define TARGET_NR_getpgrp 1060 +#define __ARCH_WANT_SYS_GETPGRP +#define TARGET_NR_pause 1061 +#define __ARCH_WANT_SYS_PAUSE +#define TARGET_NR_time 1062 +#define __ARCH_WANT_SYS_TIME +#define __ARCH_WANT_COMPAT_SYS_TIME +#define TARGET_NR_utime 1063 +#define __ARCH_WANT_SYS_UTIME + +#define TARGET_NR_creat 1064 +#define TARGET_NR_getdents 1065 +#define __ARCH_WANT_SYS_GETDENTS +#define TARGET_NR_futimesat 1066 +#define TARGET_NR_select 1067 +#define __ARCH_WANT_SYS_SELECT +#define TARGET_NR_poll 1068 +#define TARGET_NR_epoll_wait 1069 +#define TARGET_NR_ustat 1070 +#define TARGET_NR_vfork 1071 +#define TARGET_NR_oldwait4 1072 +#define TARGET_NR_recv 1073 +#define TARGET_NR_send 1074 +#define TARGET_NR_bdflush 1075 +#define TARGET_NR_umount 1076 +#define __ARCH_WANT_SYS_OLDUMOUNT +#define TARGET_NR_uselib 1077 +#define TARGET_NR__sysctl 1078 + +#define TARGET_NR_fork 1079 + +#undef TARGET_NR_syscalls +#define TARGET_NR_syscalls (TARGET_NR_fork+1) + + +/* + * 32 bit systems traditionally used different + * syscalls for off_t and loff_t arguments, while + * 64 bit systems only need the off_t version. + * For new 32 bit platforms, there is no need to + * implement the old 32 bit off_t syscalls, so + * they take different names. + * Here we map the numbers so that both versions + * use the same syscall table layout. + */ + +#define TARGET_NR_fcntl64 TARGET_NR_3264_fcntl +#define TARGET_NR_statfs64 TARGET_NR_3264_statfs +#define TARGET_NR_fstatfs64 TARGET_NR_3264_fstatfs +#define TARGET_NR_truncate64 TARGET_NR_3264_truncate +#define TARGET_NR_ftruncate64 TARGET_NR_3264_ftruncate +#define TARGET_NR_llseek TARGET_NR_3264_lseek +#define TARGET_NR_sendfile64 TARGET_NR_3264_sendfile +#define TARGET_NR_fstatat64 TARGET_NR_3264_fstatat +#define TARGET_NR_fstat64 TARGET_NR_3264_fstat +#define TARGET_NR_mmap2 TARGET_NR_3264_mmap +#define TARGET_NR_fadvise64_64 TARGET_NR_3264_fadvise64 + +#ifdef TARGET_NR_3264_stat +#define TARGET_NR_stat64 TARGET_NR_3264_stat +#define TARGET_NR_lstat64 TARGET_NR_3264_lstat +#endif diff --git a/linux-user/openrisc/target_cpu.h b/linux-user/openrisc/target_cpu.h new file mode 100644 index 00000000..32a46ac8 --- /dev/null +++ b/linux-user/openrisc/target_cpu.h @@ -0,0 +1,38 @@ +/* + * OpenRISC specific CPU ABI and functions for linux-user + * + * Copyright (c) 2011-2012 Jia Liu <proljc@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUOpenRISCState *env, target_ulong newsp) +{ +    if (newsp) { +        env->gpr[1] = newsp; +    } +    env->gpr[11] = 0; +} + +static inline void cpu_set_tls(CPUOpenRISCState *env, target_ulong newtls) +{ +    /* Linux kernel 3.10 does not pay any attention to CLONE_SETTLS +     * in copy_thread(), so QEMU need not do so either. +     */ +} + +#endif diff --git a/linux-user/openrisc/target_signal.h b/linux-user/openrisc/target_signal.h new file mode 100644 index 00000000..964aed69 --- /dev/null +++ b/linux-user/openrisc/target_signal.h @@ -0,0 +1,26 @@ +#ifndef TARGET_SIGNAL_H +#define TARGET_SIGNAL_H + +#include "cpu.h" + +/* this struct defines a stack used during syscall handling */ + +typedef struct target_sigaltstack { +    abi_long ss_sp; +    abi_ulong ss_size; +    abi_long ss_flags; +} target_stack_t; + +/* sigaltstack controls  */ +#define TARGET_SS_ONSTACK     1 +#define TARGET_SS_DISABLE     2 + +#define TARGET_MINSIGSTKSZ    2048 +#define TARGET_SIGSTKSZ       8192 + +static inline abi_ulong get_sp_from_cpustate(CPUOpenRISCState *state) +{ +    return state->gpr[1]; +} + +#endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/openrisc/target_structs.h b/linux-user/openrisc/target_structs.h new file mode 100644 index 00000000..f4d560f5 --- /dev/null +++ b/linux-user/openrisc/target_structs.h @@ -0,0 +1,58 @@ +/* + * OpenRISC specific structures for linux-user + * + * Copyright (c) 2013 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_STRUCTS_H +#define TARGET_STRUCTS_H + +struct target_ipc_perm { +    abi_int __key;                      /* Key.  */ +    abi_uint uid;                       /* Owner's user ID.  */ +    abi_uint gid;                       /* Owner's group ID.  */ +    abi_uint cuid;                      /* Creator's user ID.  */ +    abi_uint cgid;                      /* Creator's group ID.  */ +    abi_ushort mode;                    /* Read/write permission.  */ +    abi_ushort __pad1; +    abi_ushort __seq;                   /* Sequence number.  */ +    abi_ushort __pad2; +    abi_ulong __unused1; +    abi_ulong __unused2; +}; + +struct target_shmid_ds { +    struct target_ipc_perm shm_perm;    /* operation permission struct */ +    abi_long shm_segsz;                 /* size of segment in bytes */ +    abi_ulong shm_atime;                /* time of last shmat() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused1; +#endif +    abi_ulong shm_dtime;                /* time of last shmdt() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused2; +#endif +    abi_ulong shm_ctime;                /* time of last change by shmctl() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused3; +#endif +    abi_int shm_cpid;                   /* pid of creator */ +    abi_int shm_lpid;                   /* pid of last shmop */ +    abi_ulong shm_nattch;               /* number of current attaches */ +    abi_ulong __unused4; +    abi_ulong __unused5; +}; + +#endif diff --git a/linux-user/openrisc/termbits.h b/linux-user/openrisc/termbits.h new file mode 100644 index 00000000..373af772 --- /dev/null +++ b/linux-user/openrisc/termbits.h @@ -0,0 +1,294 @@ +typedef unsigned char   target_openrisc_cc;        /*cc_t*/ +typedef unsigned int    target_openrisc_speed;     /*speed_t*/ +typedef unsigned int    target_openrisc_tcflag;    /*tcflag_t*/ + +#define TARGET_NCCS 19 +struct target_termios { +    target_openrisc_tcflag c_iflag;               /* input mode flags */ +    target_openrisc_tcflag c_oflag;               /* output mode flags */ +    target_openrisc_tcflag c_cflag;               /* control mode flags */ +    target_openrisc_tcflag c_lflag;               /* local mode flags */ +    target_openrisc_cc c_line;                    /* line discipline */ +    target_openrisc_cc c_cc[TARGET_NCCS];         /* control characters */ +}; + +struct target_termios2 { +    target_openrisc_tcflag c_iflag;               /* input mode flags */ +    target_openrisc_tcflag c_oflag;               /* output mode flags */ +    target_openrisc_tcflag c_cflag;               /* control mode flags */ +    target_openrisc_tcflag c_lflag;               /* local mode flags */ +    target_openrisc_cc c_line;                    /* line discipline */ +    target_openrisc_cc c_cc[TARGET_NCCS];         /* control characters */ +    target_openrisc_speed c_ispeed;               /* input speed */ +    target_openrisc_speed c_ospeed;               /* output speed */ +}; + +struct target_termios3 { +    target_openrisc_tcflag c_iflag;               /* input mode flags */ +    target_openrisc_tcflag c_oflag;               /* output mode flags */ +    target_openrisc_tcflag c_cflag;               /* control mode flags */ +    target_openrisc_tcflag c_lflag;               /* local mode flags */ +    target_openrisc_cc c_line;                    /* line discipline */ +    target_openrisc_cc c_cc[TARGET_NCCS];         /* control characters */ +    target_openrisc_speed c_ispeed;               /* input speed */ +    target_openrisc_speed c_ospeed;               /* output speed */ +}; + +/* c_cc characters */ +#define TARGET_VINTR 0 +#define TARGET_VQUIT 1 +#define TARGET_VERASE 2 +#define TARGET_VKILL 3 +#define TARGET_VEOF 4 +#define TARGET_VTIME 5 +#define TARGET_VMIN 6 +#define TARGET_VSWTC 7 +#define TARGET_VSTART 8 +#define TARGET_VSTOP 9 +#define TARGET_VSUSP 10 +#define TARGET_VEOL 11 +#define TARGET_VREPRINT 12 +#define TARGET_VDISCARD 13 +#define TARGET_VWERASE 14 +#define TARGET_VLNEXT 15 +#define TARGET_VEOL2 16 + +/* c_iflag bits */ +#define TARGET_IGNBRK  0000001 +#define TARGET_BRKINT  0000002 +#define TARGET_IGNPAR  0000004 +#define TARGET_PARMRK  0000010 +#define TARGET_INPCK   0000020 +#define TARGET_ISTRIP  0000040 +#define TARGET_INLCR   0000100 +#define TARGET_IGNCR   0000200 +#define TARGET_ICRNL   0000400 +#define TARGET_IUCLC   0001000 +#define TARGET_IXON    0002000 +#define TARGET_IXANY   0004000 +#define TARGET_IXOFF   0010000 +#define TARGET_IMAXBEL 0020000 +#define TARGET_IUTF8   0040000 + +/* c_oflag bits */ +#define TARGET_OPOST   0000001 +#define TARGET_OLCUC   0000002 +#define TARGET_ONLCR   0000004 +#define TARGET_OCRNL   0000010 +#define TARGET_ONOCR   0000020 +#define TARGET_ONLRET  0000040 +#define TARGET_OFILL   0000100 +#define TARGET_OFDEL   0000200 +#define TARGET_NLDLY   0000400 +#define TARGET_NL0     0000000 +#define TARGET_NL1     0000400 +#define TARGET_CRDLY   0003000 +#define TARGET_CR0     0000000 +#define TARGET_CR1     0001000 +#define TARGET_CR2     0002000 +#define TARGET_CR3     0003000 +#define TARGET_TABDLY  0014000 +#define TARGET_TAB0    0000000 +#define TARGET_TAB1    0004000 +#define TARGET_TAB2    0010000 +#define TARGET_TAB3    0014000 +#define TARGET_XTABS   0014000 +#define TARGET_BSDLY   0020000 +#define TARGET_BS0     0000000 +#define TARGET_BS1     0020000 +#define TARGET_VTDLY   0040000 +#define TARGET_VT0     0000000 +#define TARGET_VT1     0040000 +#define TARGET_FFDLY   0100000 +#define TARGET_FF0     0000000 +#define TARGET_FF1     0100000 + +/* c_cflag bit meaning */ +#define TARGET_CBAUD    0010017 +#define TARGET_B0       0000000                /* hang up */ +#define TARGET_B50      0000001 +#define TARGET_B75      0000002 +#define TARGET_B110     0000003 +#define TARGET_B134     0000004 +#define TARGET_B150     0000005 +#define TARGET_B200     0000006 +#define TARGET_B300     0000007 +#define TARGET_B600     0000010 +#define TARGET_B1200    0000011 +#define TARGET_B1800    0000012 +#define TARGET_B2400    0000013 +#define TARGET_B4800    0000014 +#define TARGET_B9600    0000015 +#define TARGET_B19200   0000016 +#define TARGET_B38400   0000017 +#define TARGET_EXTA     B19200 +#define TARGET_EXTB     B38400 +#define TARGET_CSIZE    0000060 +#define TARGET_CS5      0000000 +#define TARGET_CS6      0000020 +#define TARGET_CS7      0000040 +#define TARGET_CS8      0000060 +#define TARGET_CSTOPB   0000100 +#define TARGET_CREAD    0000200 +#define TARGET_PARENB   0000400 +#define TARGET_PARODD   0001000 +#define TARGET_HUPCL    0002000 +#define TARGET_CLOCAL   0004000 +#define TARGET_CBAUDEX  0010000 +#define TARGET_BOTHER   0010000 +#define TARGET_B57600   0010001 +#define TARGET_B115200  0010002 +#define TARGET_B230400  0010003 +#define TARGET_B460800  0010004 +#define TARGET_B500000  0010005 +#define TARGET_B576000  0010006 +#define TARGET_B921600  0010007 +#define TARGET_B1000000 0010010 +#define TARGET_B1152000 0010011 +#define TARGET_B1500000 0010012 +#define TARGET_B2000000 0010013 +#define TARGET_B2500000 0010014 +#define TARGET_B3000000 0010015 +#define TARGET_B3500000 0010016 +#define TARGET_B4000000 0010017 +#define TARGET_CIBAUD   002003600000   /* input baud rate */ +#define TARGET_CMSPAR   010000000000   /* mark or space (stick) parity */ +#define TARGET_CRTSCTS  020000000000   /* flow control */ + +#define TARGET_IBSHIFT   16            /* Shift from CBAUD to CIBAUD */ + +/* c_lflag bits */ +#define TARGET_ISIG    0000001 +#define TARGET_ICANON  0000002 +#define TARGET_XCASE   0000004 +#define TARGET_ECHO    0000010 +#define TARGET_ECHOE   0000020 +#define TARGET_ECHOK   0000040 +#define TARGET_ECHONL  0000100 +#define TARGET_NOFLSH  0000200 +#define TARGET_TOSTOP  0000400 +#define TARGET_ECHOCTL 0001000 +#define TARGET_ECHOPRT 0002000 +#define TARGET_ECHOKE  0004000 +#define TARGET_FLUSHO  0010000 +#define TARGET_PENDIN  0040000 +#define TARGET_IEXTEN  0100000 +#define TARGET_EXTPROC 0200000 + +/* tcflow() and TCXONC use these */ +#define TARGET_TCOOFF          0 +#define TARGET_TCOON           1 +#define TARGET_TCIOFF          2 +#define TARGET_TCION           3 + +/* tcflush() and TCFLSH use these */ +#define TARGET_TCIFLUSH        0 +#define TARGET_TCOFLUSH        1 +#define TARGET_TCIOFLUSH       2 + +/* tcsetattr uses these */ +#define TARGET_TCSANOW         0 +#define TARGET_TCSADRAIN       1 +#define TARGET_TCSAFLUSH       2 + +/* ioctls */ +#define TARGET_TCGETS          0x5401 +#define TARGET_TCSETS          0x5402 +#define TARGET_TCSETSW         0x5403 +#define TARGET_TCSETSF         0x5404 +#define TARGET_TCGETA          0x5405 +#define TARGET_TCSETA          0x5406 +#define TARGET_TCSETAW         0x5407 +#define TARGET_TCSETAF         0x5408 +#define TARGET_TCSBRK          0x5409 +#define TARGET_TCXONC          0x540A +#define TARGET_TCFLSH          0x540B +#define TARGET_TIOCEXCL        0x540C +#define TARGET_TIOCNXCL        0x540D +#define TARGET_TIOCSCTTY       0x540E +#define TARGET_TIOCGPGRP       0x540F +#define TARGET_TIOCSPGRP       0x5410 +#define TARGET_TIOCOUTQ        0x5411 +#define TARGET_TIOCSTI         0x5412 +#define TARGET_TIOCGWINSZ      0x5413 +#define TARGET_TIOCSWINSZ      0x5414 +#define TARGET_TIOCMGET        0x5415 +#define TARGET_TIOCMBIS        0x5416 +#define TARGET_TIOCMBIC        0x5417 +#define TARGET_TIOCMSET        0x5418 +#define TARGET_TIOCGSOFTCAR    0x5419 +#define TARGET_TIOCSSOFTCAR    0x541A +#define TARGET_FIONREAD        0x541B +#define TARGET_TIOCINQ         FIONREAD +#define TARGET_TIOCLINUX       0x541C +#define TARGET_TIOCCONS        0x541D +#define TARGET_TIOCGSERIAL     0x541E +#define TARGET_TIOCSSERIAL     0x541F +#define TARGET_TIOCPKT         0x5420 +#define TARGET_FIONBIO         0x5421 +#define TARGET_TIOCNOTTY       0x5422 +#define TARGET_TIOCSETD        0x5423 +#define TARGET_TIOCGETD        0x5424 +#define TARGET_TCSBRKP         0x5425  /* Needed for POSIX tcsendbreak() */ +#define TARGET_TIOCSBRK        0x5427  /* BSD compatibility */ +#define TARGET_TIOCCBRK        0x5428  /* BSD compatibility */ +#define TARGET_TIOCGSID        0x5429  /* Return the session ID of FD */ +#define TARGET_TCGETS2         TARGET_IOR('T', 0x2A, struct termios2) +#define TARGET_TCSETS2         TARGET_IOW('T', 0x2B, struct termios2) +#define TARGET_TCSETSW2        TARGET_IOW('T', 0x2C, struct termios2) +#define TARGET_TCSETSF2        TARGET_IOW('T', 0x2D, struct termios2) +#define TARGET_TIOCGRS485      0x542E +#ifndef TARGET_TIOCSRS485 +#define TARGET_TIOCSRS485      0x542F +#endif +/* Get Pty Number (of pty-mux device) */ +#define TARGET_TIOCGPTN        TARGET_IOR('T', 0x30, unsigned int) +/* Lock/unlock Pty */ +#define TARGET_TIOCSPTLCK      TARGET_IOW('T', 0x31, int) +/* Get primary device node of /dev/console */ +#define TARGET_TIOCGDEV        TARGET_IOR('T', 0x32, unsigned int) +#define TARGET_TCGETX          0x5432 /* SYS5 TCGETX compatibility */ +#define TARGET_TCSETX          0x5433 +#define TARGET_TCSETXF         0x5434 +#define TARGET_TCSETXW         0x5435 +/* pty: generate signal */ +#define TARGET_TIOCSIG         TARGET_IOW('T', 0x36, int) +#define TARGET_TIOCVHANGUP     0x5437 + +#define TARGET_FIONCLEX        0x5450 +#define TARGET_FIOCLEX         0x5451 +#define TARGET_FIOASYNC        0x5452 +#define TARGET_TIOCSERCONFIG   0x5453 +#define TARGET_TIOCSERGWILD    0x5454 +#define TARGET_TIOCSERSWILD    0x5455 +#define TARGET_TIOCGLCKTRMIOS  0x5456 +#define TARGET_TIOCSLCKTRMIOS  0x5457 +#define TARGET_TIOCSERGSTRUCT  0x5458 /* For debugging only */ +#define TARGET_TIOCSERGETLSR   0x5459 /* Get line status register */ +#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config  */ +#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ + +/* wait for a change on serial input line(s) */ +#define TARGET_TIOCMIWAIT      0x545C +/* read serial port inline interrupt counts */ +#define TARGET_TIOCGICOUNT     0x545D + +/* + * Some arches already define TARGET_FIOQSIZE due to a historical + * conflict with a Hayes modem-specific ioctl value. + */ +#ifndef TARGET_FIOQSIZE +#define TARGET_FIOQSIZE        0x5460 +#endif + +/* Used for packet mode */ +#define TARGET_TIOCPKT_DATA             0 +#define TARGET_TIOCPKT_FLUSHREAD        1 +#define TARGET_TIOCPKT_FLUSHWRITE       2 +#define TARGET_TIOCPKT_STOP             4 +#define TARGET_TIOCPKT_START            8 +#define TARGET_TIOCPKT_NOSTOP          16 +#define TARGET_TIOCPKT_DOSTOP          32 +#define TARGET_TIOCPKT_IOCTL           64 + +#define TARGET_TIOCSER_TEMT    0x01    /* Transmitter physically empty */ diff --git a/linux-user/ppc/syscall.h b/linux-user/ppc/syscall.h new file mode 100644 index 00000000..0daf5cd2 --- /dev/null +++ b/linux-user/ppc/syscall.h @@ -0,0 +1,75 @@ +/* + *  PPC emulation for qemu: syscall definitions. + * + *  Copyright (c) 2003 Jocelyn Mayer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +/* XXX: ABSOLUTELY BUGGY: + * for now, this is quite just a cut-and-paste from i386 target... + */ + +/* default linux values for the selectors */ +#define __USER_DS	(1) + +struct target_pt_regs { +	abi_ulong gpr[32]; +	abi_ulong nip; +	abi_ulong msr; +	abi_ulong orig_gpr3;	/* Used for restarting system calls */ +	abi_ulong ctr; +	abi_ulong link; +	abi_ulong xer; +	abi_ulong ccr; +#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) +        abi_ulong softe; +#else +	abi_ulong mq;		/* 601 only (not used at present) */ +#endif +					/* Used on APUS to hold IPL value. */ +	abi_ulong trap;		/* Reason for being here */ +	abi_ulong dar;		/* Fault registers */ +	abi_ulong dsisr; +	abi_ulong result; 		/* Result of a system call */ +}; + +/* ioctls */ +struct target_revectored_struct { +	abi_ulong __map[8];			/* 256 bits */ +}; + +/* Nasty hack: define a fake errno value for use by sigreturn.  */ +#define TARGET_QEMU_ESIGRETURN 255 + +/* + * flags masks + */ + +#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) +#ifdef TARGET_WORDS_BIGENDIAN +#define UNAME_MACHINE "ppc64" +#else +#define UNAME_MACHINE "ppc64le" +#endif +#else +#define UNAME_MACHINE "ppc" +#endif +#define UNAME_MINIMUM_RELEASE "2.6.32" + +#define TARGET_CLONE_BACKWARDS + +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_MLOCKALL_MCL_CURRENT 0x2000 +#define TARGET_MLOCKALL_MCL_FUTURE  0x4000 diff --git a/linux-user/ppc/syscall_nr.h b/linux-user/ppc/syscall_nr.h new file mode 100644 index 00000000..1e1736e1 --- /dev/null +++ b/linux-user/ppc/syscall_nr.h @@ -0,0 +1,370 @@ +/* + * This file contains the system call numbers. + */ +#define TARGET_NR_restart_syscall          0 +#define TARGET_NR_exit                     1 +#define TARGET_NR_fork                     2 +#define TARGET_NR_read                     3 +#define TARGET_NR_write                    4 +#define TARGET_NR_open                     5 +#define TARGET_NR_close                    6 +#define TARGET_NR_waitpid                  7 +#define TARGET_NR_creat                    8 +#define TARGET_NR_link                     9 +#define TARGET_NR_unlink                  10 +#define TARGET_NR_execve                  11 +#define TARGET_NR_chdir                   12 +#define TARGET_NR_time                    13 +#define TARGET_NR_mknod                   14 +#define TARGET_NR_chmod                   15 +#define TARGET_NR_lchown                  16 +#define TARGET_NR_break                   17 +#define TARGET_NR_oldstat                 18 +#define TARGET_NR_lseek                   19 +#define TARGET_NR_getpid                  20 +#define TARGET_NR_mount                   21 +#define TARGET_NR_umount                  22 +#define TARGET_NR_setuid                  23 +#define TARGET_NR_getuid                  24 +#define TARGET_NR_stime                   25 +#define TARGET_NR_ptrace                  26 +#define TARGET_NR_alarm                   27 +#define TARGET_NR_oldfstat                28 +#define TARGET_NR_pause                   29 +#define TARGET_NR_utime                   30 +#define TARGET_NR_stty                    31 +#define TARGET_NR_gtty                    32 +#define TARGET_NR_access                  33 +#define TARGET_NR_nice                    34 +#define TARGET_NR_ftime                   35 +#define TARGET_NR_sync                    36 +#define TARGET_NR_kill                    37 +#define TARGET_NR_rename                  38 +#define TARGET_NR_mkdir                   39 +#define TARGET_NR_rmdir                   40 +#define TARGET_NR_dup                     41 +#define TARGET_NR_pipe                    42 +#define TARGET_NR_times                   43 +#define TARGET_NR_prof                    44 +#define TARGET_NR_brk                     45 +#define TARGET_NR_setgid                  46 +#define TARGET_NR_getgid                  47 +#define TARGET_NR_signal                  48 +#define TARGET_NR_geteuid                 49 +#define TARGET_NR_getegid                 50 +#define TARGET_NR_acct                    51 +#define TARGET_NR_umount2                 52 +#define TARGET_NR_lock                    53 +#define TARGET_NR_ioctl                   54 +#define TARGET_NR_fcntl                   55 +#define TARGET_NR_mpx                     56 +#define TARGET_NR_setpgid                 57 +#define TARGET_NR_ulimit                  58 +#define TARGET_NR_oldolduname             59 +#define TARGET_NR_umask                   60 +#define TARGET_NR_chroot                  61 +#define TARGET_NR_ustat                   62 +#define TARGET_NR_dup2                    63 +#define TARGET_NR_getppid                 64 +#define TARGET_NR_getpgrp                 65 +#define TARGET_NR_setsid                  66 +#define TARGET_NR_sigaction               67 +#define TARGET_NR_sgetmask                68 +#define TARGET_NR_ssetmask                69 +#define TARGET_NR_setreuid                70 +#define TARGET_NR_setregid                71 +#define TARGET_NR_sigsuspend              72 +#define TARGET_NR_sigpending              73 +#define TARGET_NR_sethostname             74 +#define TARGET_NR_setrlimit               75 +#define TARGET_NR_getrlimit               76 +#define TARGET_NR_getrusage               77 +#define TARGET_NR_gettimeofday            78 +#define TARGET_NR_settimeofday            79 +#define TARGET_NR_getgroups               80 +#define TARGET_NR_setgroups               81 +#define TARGET_NR_select                  82 +#define TARGET_NR_symlink                 83 +#define TARGET_NR_oldlstat                84 +#define TARGET_NR_readlink                85 +#define TARGET_NR_uselib                  86 +#define TARGET_NR_swapon                  87 +#define TARGET_NR_reboot                  88 +#define TARGET_NR_readdir                 89 +#define TARGET_NR_mmap                    90 +#define TARGET_NR_munmap                  91 +#define TARGET_NR_truncate                92 +#define TARGET_NR_ftruncate               93 +#define TARGET_NR_fchmod                  94 +#define TARGET_NR_fchown                  95 +#define TARGET_NR_getpriority             96 +#define TARGET_NR_setpriority             97 +#define TARGET_NR_profil                  98 +#define TARGET_NR_statfs                  99 +#define TARGET_NR_fstatfs                100 +#define TARGET_NR_ioperm                 101 +#define TARGET_NR_socketcall             102 +#define TARGET_NR_syslog                 103 +#define TARGET_NR_setitimer              104 +#define TARGET_NR_getitimer              105 +#define TARGET_NR_stat                   106 +#define TARGET_NR_lstat                  107 +#define TARGET_NR_fstat                  108 +#define TARGET_NR_olduname               109 +#define TARGET_NR_iopl                   110 +#define TARGET_NR_vhangup                111 +#define TARGET_NR_idle                   112 +#define TARGET_NR_vm86                   113 +#define TARGET_NR_wait4                  114 +#define TARGET_NR_swapoff                115 +#define TARGET_NR_sysinfo                116 +#define TARGET_NR_ipc                    117 +#define TARGET_NR_fsync                  118 +#define TARGET_NR_sigreturn              119 +#define TARGET_NR_clone                  120 +#define TARGET_NR_setdomainname          121 +#define TARGET_NR_uname                  122 +#define TARGET_NR_modify_ldt             123 +#define TARGET_NR_adjtimex               124 +#define TARGET_NR_mprotect               125 +#define TARGET_NR_sigprocmask            126 +#define TARGET_NR_create_module          127 +#define TARGET_NR_init_module            128 +#define TARGET_NR_delete_module          129 +#define TARGET_NR_get_kernel_syms        130 +#define TARGET_NR_quotactl               131 +#define TARGET_NR_getpgid                132 +#define TARGET_NR_fchdir                 133 +#define TARGET_NR_bdflush                134 +#define TARGET_NR_sysfs                  135 +#define TARGET_NR_personality            136 +#define TARGET_NR_afs_syscall            137 /* Syscall for Andrew File System */ +#define TARGET_NR_setfsuid               138 +#define TARGET_NR_setfsgid               139 +#define TARGET_NR__llseek                140 +#define TARGET_NR_getdents               141 +#define TARGET_NR__newselect             142 +#define TARGET_NR_flock                  143 +#define TARGET_NR_msync                  144 +#define TARGET_NR_readv                  145 +#define TARGET_NR_writev                 146 +#define TARGET_NR_getsid                 147 +#define TARGET_NR_fdatasync              148 +#define TARGET_NR__sysctl                149 +#define TARGET_NR_mlock                  150 +#define TARGET_NR_munlock                151 +#define TARGET_NR_mlockall               152 +#define TARGET_NR_munlockall             153 +#define TARGET_NR_sched_setparam         154 +#define TARGET_NR_sched_getparam         155 +#define TARGET_NR_sched_setscheduler     156 +#define TARGET_NR_sched_getscheduler     157 +#define TARGET_NR_sched_yield            158 +#define TARGET_NR_sched_get_priority_max 159 +#define TARGET_NR_sched_get_priority_min 160 +#define TARGET_NR_sched_rr_get_interval  161 +#define TARGET_NR_nanosleep              162 +#define TARGET_NR_mremap                 163 +#define TARGET_NR_setresuid32            164 +#define TARGET_NR_getresuid32            165 +#define TARGET_NR_query_module           166 +#define TARGET_NR_poll                   167 +#define TARGET_NR_nfsservctl             168 +#define TARGET_NR_setresgid32            169 +#define TARGET_NR_getresgid32            170 +#define TARGET_NR_prctl                  171 +#define TARGET_NR_rt_sigreturn           172 +#define TARGET_NR_rt_sigaction           173 +#define TARGET_NR_rt_sigprocmask         174 +#define TARGET_NR_rt_sigpending          175 +#define TARGET_NR_rt_sigtimedwait        176 +#define TARGET_NR_rt_sigqueueinfo        177 +#define TARGET_NR_rt_sigsuspend          178 +#define TARGET_NR_pread64                179 +#define TARGET_NR_pwrite64               180 +#define TARGET_NR_chown                  181 +#define TARGET_NR_getcwd                 182 +#define TARGET_NR_capget                 183 +#define TARGET_NR_capset                 184 +#define TARGET_NR_sigaltstack            185 +#define TARGET_NR_sendfile               186 +#define TARGET_NR_getpmsg                187     /* some people actually want streams */ +#define TARGET_NR_putpmsg                188     /* some people actually want streams */ +#define TARGET_NR_vfork                  189 +#define TARGET_NR_ugetrlimit             190     /* SuS compliant getrlimit */ +#define TARGET_NR_readahead              191 +#if !defined(TARGET_PPC64) || defined(TARGET_ABI32) +#define TARGET_NR_mmap2                  192 +#define TARGET_NR_truncate64             193 +#define TARGET_NR_ftruncate64            194 +#define TARGET_NR_stat64                 195 +#define TARGET_NR_lstat64                196 +#define TARGET_NR_fstat64                197 +#endif +#define TARGET_NR_pciconfig_read         198 +#define TARGET_NR_pciconfig_write        199 +#define TARGET_NR_pciconfig_iobase       200 +#define TARGET_NR_multiplexer            201 +#define TARGET_NR_getdents64             202 +#define TARGET_NR_pivot_root             203 +#if !defined(TARGET_PPC64) || defined(TARGET_ABI32) +#define TARGET_NR_fcntl64                204 +#endif +#define TARGET_NR_madvise                205 +#define TARGET_NR_mincore                206 +#define TARGET_NR_gettid                 207 +#define TARGET_NR_tkill                  208 +#define TARGET_NR_setxattr               209 +#define TARGET_NR_lsetxattr              210 +#define TARGET_NR_fsetxattr              211 +#define TARGET_NR_getxattr               212 +#define TARGET_NR_lgetxattr              213 +#define TARGET_NR_fgetxattr              214 +#define TARGET_NR_listxattr              215 +#define TARGET_NR_llistxattr             216 +#define TARGET_NR_flistxattr             217 +#define TARGET_NR_removexattr            218 +#define TARGET_NR_lremovexattr           219 +#define TARGET_NR_fremovexattr           220 +#define TARGET_NR_futex                  221 +#define TARGET_NR_sched_setaffinity      222 +#define TARGET_NR_sched_getaffinity      223 +/* 224 currently unused */ +#define TARGET_NR_tuxcall                225 +#if !defined(TARGET_PPC64) || defined(TARGET_ABI32) +#define TARGET_NR_sendfile64             226 +#endif +#define TARGET_NR_io_setup               227 +#define TARGET_NR_io_destroy             228 +#define TARGET_NR_io_getevents           229 +#define TARGET_NR_io_submit              230 +#define TARGET_NR_io_cancel              231 +#define TARGET_NR_set_tid_address        232 +#define TARGET_NR_fadvise64              233 +#define TARGET_NR_exit_group             234 +#define TARGET_NR_lookup_dcookie         235 +#define TARGET_NR_epoll_create           236 +#define TARGET_NR_epoll_ctl              237 +#define TARGET_NR_epoll_wait             238 +#define TARGET_NR_remap_file_pages       239 +#define TARGET_NR_timer_create           240 +#define TARGET_NR_timer_settime          241 +#define TARGET_NR_timer_gettime          242 +#define TARGET_NR_timer_getoverrun       243 +#define TARGET_NR_timer_delete           244 +#define TARGET_NR_clock_settime          245 +#define TARGET_NR_clock_gettime          246 +#define TARGET_NR_clock_getres           247 +#define TARGET_NR_clock_nanosleep        248 +#define TARGET_NR_swapcontext            249 +#define TARGET_NR_tgkill                 250 +#define TARGET_NR_utimes                 251 +#define TARGET_NR_statfs64               252 +#define TARGET_NR_fstatfs64              253 +#if !defined(TARGET_PPC64) || defined(TARGET_ABI32) +#define TARGET_NR_fadvise64_64           254 +#endif +#define TARGET_NR_rtas		255 +#define TARGET_NR_sys_debug_setcontext 256 +/* Number 257 is reserved for vserver */ +#define TARGET_NR_migrate_pages	258 +#define TARGET_NR_mbind		259 +#define TARGET_NR_get_mempolicy	260 +#define TARGET_NR_set_mempolicy	261 +#define TARGET_NR_mq_open		262 +#define TARGET_NR_mq_unlink		263 +#define TARGET_NR_mq_timedsend	264 +#define TARGET_NR_mq_timedreceive	265 +#define TARGET_NR_mq_notify		266 +#define TARGET_NR_mq_getsetattr	267 +#define TARGET_NR_kexec_load		268 +#define TARGET_NR_add_key		269 +#define TARGET_NR_request_key	270 +#define TARGET_NR_keyctl		271 +#define TARGET_NR_waitid		272 +#define TARGET_NR_ioprio_set		273 +#define TARGET_NR_ioprio_get		274 +#define TARGET_NR_inotify_init	275 +#define TARGET_NR_inotify_add_watch	276 +#define TARGET_NR_inotify_rm_watch	277 +#define TARGET_NR_spu_run		278 +#define TARGET_NR_spu_create		279 +#define TARGET_NR_pselect6		280 +#define TARGET_NR_ppoll		281 +#define TARGET_NR_unshare		282 +#define TARGET_NR_splice		283 +#define TARGET_NR_tee		284 +#define TARGET_NR_vmsplice		285 +#define TARGET_NR_openat		286 +#define TARGET_NR_mkdirat		287 +#define TARGET_NR_mknodat		288 +#define TARGET_NR_fchownat		289 +#define TARGET_NR_futimesat		290 +#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) +#define TARGET_NR_newfstatat		291 +#else +#define TARGET_NR_fstatat64		291 +#endif +#define TARGET_NR_unlinkat		292 +#define TARGET_NR_renameat		293 +#define TARGET_NR_linkat		294 +#define TARGET_NR_symlinkat		295 +#define TARGET_NR_readlinkat		296 +#define TARGET_NR_fchmodat		297 +#define TARGET_NR_faccessat		298 +#define TARGET_NR_get_robust_list	299 +#define TARGET_NR_set_robust_list	300 +#define TARGET_NR_move_pages		301 +#define TARGET_NR_getcpu		302 +#define TARGET_NR_epoll_pwait	303 +#define TARGET_NR_utimensat		304 +#define TARGET_NR_signalfd		305 +#define TARGET_NR_timerfd		306 +#define TARGET_NR_eventfd		307 +#define TARGET_NR_sync_file_range2	308 +#define TARGET_NR_fallocate		309 +#define TARGET_NR_subpage_prot		310 +#define TARGET_NR_timerfd_settime	311 +#define TARGET_NR_timerfd_gettime	312 +#define TARGET_NR_signalfd4		313 +#define TARGET_NR_eventfd2		314 +#define TARGET_NR_epoll_create1	315 +#define TARGET_NR_dup3			316 +#define TARGET_NR_pipe2		317 +#define TARGET_NR_inotify_init1	318 +#define TARGET_NR_perf_event_open       319 +#define TARGET_NR_preadv                320 +#define TARGET_NR_pwritev               321 +#define TARGET_NR_rt_tgsigqueueinfo     322 +#define TARGET_NR_fanotify_init         323 +#define TARGET_NR_fanotify_mark         324 +#define TARGET_NR_prlimit64             325 +#define TARGET_NR_socket                326 +#define TARGET_NR_bind                  327 +#define TARGET_NR_connect               328 +#define TARGET_NR_listen                329 +#define TARGET_NR_accept                330 +#define TARGET_NR_getsockname           331 +#define TARGET_NR_getpeername           332 +#define TARGET_NR_socketpair            333 +#define TARGET_NR_send                  334 +#define TARGET_NR_sendto                335 +#define TARGET_NR_recv                  336 +#define TARGET_NR_recvfrom              337 +#define TARGET_NR_shutdown              338 +#define TARGET_NR_setsockopt            339 +#define TARGET_NR_getsockopt            340 +#define TARGET_NR_sendmsg               341 +#define TARGET_NR_recvmsg               342 +#define TARGET_NR_recvmmsg              343 +#define TARGET_NR_accept4               344 +#define TARGET_NR_name_to_handle_at     345 +#define TARGET_NR_open_by_handle_at     346 +#define TARGET_NR_clock_adjtime         347 +#define TARGET_NR_syncfs                348 +#define TARGET_NR_sendmmsg              349 +#define TARGET_NR_setns                 350 +#define TARGET_NR_process_vm_readv      351 +#define TARGET_NR_process_vm_writev     352 +#define TARGET_NR_finit_module          353 +#define TARGET_NR_kcmp                  354 diff --git a/linux-user/ppc/target_cpu.h b/linux-user/ppc/target_cpu.h new file mode 100644 index 00000000..26f4ba29 --- /dev/null +++ b/linux-user/ppc/target_cpu.h @@ -0,0 +1,51 @@ +/* + * PowerPC specific CPU ABI and functions for linux-user + * + * Copyright (c) 2003-2007 Jocelyn Mayer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUPPCState *env, target_ulong newsp) +{ +    if (newsp) { +        env->gpr[1] = newsp; +    } +    env->gpr[3] = 0; +} + +static inline void cpu_set_tls(CPUPPCState *env, target_ulong newtls) +{ +#if defined(TARGET_PPC64) +    /* The kernel checks TIF_32BIT here; we don't support loading 32-bit +       binaries on PPC64 yet. */ +    env->gpr[13] = newtls; +#else +    env->gpr[2] = newtls; +#endif +} + +#ifndef EF_PPC64_ABI +#define EF_PPC64_ABI           0x3 +#endif + +static inline uint32_t get_ppc64_abi(struct image_info *infop) +{ +  return infop->elf_flags & EF_PPC64_ABI; +} + + +#endif diff --git a/linux-user/ppc/target_signal.h b/linux-user/ppc/target_signal.h new file mode 100644 index 00000000..a93b5cf1 --- /dev/null +++ b/linux-user/ppc/target_signal.h @@ -0,0 +1,29 @@ +#ifndef TARGET_SIGNAL_H +#define TARGET_SIGNAL_H + +#include "cpu.h" + +/* this struct defines a stack used during syscall handling */ + +typedef struct target_sigaltstack { +	abi_ulong ss_sp; +	int ss_flags; +	abi_ulong ss_size; +} target_stack_t; + + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK     1 +#define TARGET_SS_DISABLE     2 + +#define TARGET_MINSIGSTKSZ    2048 +#define TARGET_SIGSTKSZ       8192 + +static inline abi_ulong get_sp_from_cpustate(CPUPPCState *state) +{ +    return state->gpr[1]; +} + +#endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/ppc/target_structs.h b/linux-user/ppc/target_structs.h new file mode 100644 index 00000000..2b876131 --- /dev/null +++ b/linux-user/ppc/target_structs.h @@ -0,0 +1,60 @@ +/* + * PowerPC specific structures for linux-user + * + * Copyright (c) 2013 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_STRUCTS_H +#define TARGET_STRUCTS_H + +struct target_ipc_perm { +    abi_int __key;                      /* Key.  */ +    abi_uint uid;                       /* Owner's user ID.  */ +    abi_uint gid;                       /* Owner's group ID.  */ +    abi_uint cuid;                      /* Creator's user ID.  */ +    abi_uint cgid;                      /* Creator's group ID.  */ +    abi_uint mode;                      /* Read/write permission.  */ +    uint32_t __seq;                     /* Sequence number.  */ +    uint32_t __pad1; +    uint64_t __unused1; +    uint64_t __unused2; +}; + +struct target_shmid_ds { +    struct target_ipc_perm shm_perm;    /* operation permission struct */ +#if TARGET_ABI_BITS == 32 +    abi_uint __unused1; +#endif +    abi_ulong shm_atime;                /* time of last shmat() */ +#if TARGET_ABI_BITS == 32 +    abi_uint __unused2; +#endif +    abi_ulong shm_dtime;                /* time of last shmdt() */ +#if TARGET_ABI_BITS == 32 +    abi_uint __unused3; +#endif +    abi_ulong shm_ctime;                /* time of last change by shmctl() */ +#if TARGET_ABI_BITS == 32 +    abi_uint __unused4; +#endif +    abi_long shm_segsz;                 /* size of segment in bytes */ +    abi_int shm_cpid;                   /* pid of creator */ +    abi_int shm_lpid;                   /* pid of last shmop */ +    abi_ulong shm_nattch;               /* number of current attaches */ +    abi_ulong __unused5; +    abi_ulong __unused6; +}; + +#endif diff --git a/linux-user/ppc/termbits.h b/linux-user/ppc/termbits.h new file mode 100644 index 00000000..73e71517 --- /dev/null +++ b/linux-user/ppc/termbits.h @@ -0,0 +1,236 @@ +/* from asm/termbits.h */ + +#define TARGET_NCCS 19 + +struct target_termios { +    unsigned int c_iflag;               /* input mode flags */ +    unsigned int c_oflag;               /* output mode flags */ +    unsigned int c_cflag;               /* control mode flags */ +    unsigned int c_lflag;               /* local mode flags */ +    unsigned char c_cc[TARGET_NCCS];                /* control characters */ +    unsigned char c_line;                    /* line discipline */ +    unsigned int c_ispeed;		/* input speed */ +    unsigned int c_ospeed;		/* output speed */ +}; + +/* c_cc character offsets */ +#define TARGET_VINTR 	0 +#define TARGET_VQUIT 	1 +#define TARGET_VERASE 	2 +#define TARGET_VKILL	3 +#define TARGET_VEOF	4 +#define TARGET_VMIN	5 +#define TARGET_VEOL	6 +#define TARGET_VTIME	7 +#define TARGET_VEOL2	8 +#define TARGET_VSWTC	9 + +#define TARGET_VWERASE 	10 +#define TARGET_VREPRINT	11 +#define TARGET_VSUSP 		12 +#define TARGET_VSTART		13 +#define TARGET_VSTOP		14 +#define TARGET_VLNEXT		15 +#define TARGET_VDISCARD	16 + +#define TARGET_IGNBRK	0000001 +#define TARGET_BRKINT	0000002 +#define TARGET_IGNPAR	0000004 +#define TARGET_PARMRK	0000010 +#define TARGET_INPCK	0000020 +#define TARGET_ISTRIP	0000040 +#define TARGET_INLCR	0000100 +#define TARGET_IGNCR	0000200 +#define TARGET_ICRNL	0000400 +#define TARGET_IXON	0001000 +#define TARGET_IXOFF	0002000 +#define TARGET_IXANY	0004000 +#define TARGET_IUCLC	0010000 +#define TARGET_IMAXBEL	0020000 +#define	TARGET_IUTF8	0040000 + +/* c_oflag bits */ +#define TARGET_OPOST	0000001 +#define TARGET_ONLCR	0000002 +#define TARGET_OLCUC	0000004 + +#define TARGET_OCRNL	0000010 +#define TARGET_ONOCR	0000020 +#define TARGET_ONLRET	0000040 + +#define TARGET_OFILL	00000100 +#define TARGET_OFDEL	00000200 +#define TARGET_NLDLY	00001400 +#define   TARGET_NL0	00000000 +#define   TARGET_NL1	00000400 +#define   TARGET_NL2	00001000 +#define   TARGET_NL3	00001400 +#define TARGET_TABDLY	00006000 +#define   TARGET_TAB0	00000000 +#define   TARGET_TAB1	00002000 +#define   TARGET_TAB2	00004000 +#define   TARGET_TAB3	00006000 +#define   TARGET_XTABS	00006000	/* required by POSIX to == TAB3 */ +#define TARGET_CRDLY	00030000 +#define   TARGET_CR0	00000000 +#define   TARGET_CR1	00010000 +#define   TARGET_CR2	00020000 +#define   TARGET_CR3	00030000 +#define TARGET_FFDLY	00040000 +#define   TARGET_FF0	00000000 +#define   TARGET_FF1	00040000 +#define TARGET_BSDLY	00100000 +#define   TARGET_BS0	00000000 +#define   TARGET_BS1	00100000 +#define TARGET_VTDLY	00200000 +#define   TARGET_VT0	00000000 +#define   TARGET_VT1	00200000 + +/* c_cflag bit meaning */ +#define TARGET_CBAUD	0000377 +#define  TARGET_B0	0000000		/* hang up */ +#define  TARGET_B50	0000001 +#define  TARGET_B75	0000002 +#define  TARGET_B110	0000003 +#define  TARGET_B134	0000004 +#define  TARGET_B150	0000005 +#define  TARGET_B200	0000006 +#define  TARGET_B300	0000007 +#define  TARGET_B600	0000010 +#define  TARGET_B1200	0000011 +#define  TARGET_B1800	0000012 +#define  TARGET_B2400	0000013 +#define  TARGET_B4800	0000014 +#define  TARGET_B9600	0000015 +#define  TARGET_B19200	0000016 +#define  TARGET_B38400	0000017 +#define TARGET_EXTA B19200 +#define TARGET_EXTB B38400 +#define TARGET_CBAUDEX 0000000 +#define  TARGET_B57600   00020 +#define  TARGET_B115200  00021 +#define  TARGET_B230400  00022 +#define  TARGET_B460800  00023 +#define  TARGET_B500000  00024 +#define  TARGET_B576000  00025 +#define  TARGET_B921600  00026 +#define TARGET_B1000000  00027 +#define TARGET_B1152000  00030 +#define TARGET_B1500000  00031 +#define TARGET_B2000000  00032 +#define TARGET_B2500000  00033 +#define TARGET_B3000000  00034 +#define TARGET_B3500000  00035 +#define TARGET_B4000000  00036 + +#define TARGET_CSIZE	00001400 +#define   TARGET_CS5	00000000 +#define   TARGET_CS6	00000400 +#define   TARGET_CS7	00001000 +#define   TARGET_CS8	00001400 + +#define TARGET_CSTOPB	00002000 +#define TARGET_CREAD	00004000 +#define TARGET_PARENB	00010000 +#define TARGET_PARODD	00020000 +#define TARGET_HUPCL	00040000 + +#define TARGET_CLOCAL	00100000 +#define TARGET_CMSPAR	010000000000		/* mark or space (stick) parity */ +#define TARGET_CRTSCTS	020000000000		/* flow control */ + +/* c_lflag bits */ +#define TARGET_ISIG	0x00000080 +#define TARGET_ICANON	0x00000100 +#define TARGET_XCASE	0x00004000 +#define TARGET_ECHO	0x00000008 +#define TARGET_ECHOE	0x00000002 +#define TARGET_ECHOK	0x00000004 +#define TARGET_ECHONL	0x00000010 +#define TARGET_NOFLSH	0x80000000 +#define TARGET_TOSTOP	0x00400000 +#define TARGET_ECHOCTL	0x00000040 +#define TARGET_ECHOPRT	0x00000020 +#define TARGET_ECHOKE	0x00000001 +#define TARGET_FLUSHO	0x00800000 +#define TARGET_PENDIN	0x20000000 +#define TARGET_IEXTEN	0x00000400 + +/* ioctls */ + +#define TARGET_FIOCLEX		TARGET_IO('f', 1) +#define TARGET_FIONCLEX	        TARGET_IO('f', 2) +#define TARGET_FIOASYNC	        TARGET_IOW('f', 125, int) +#define TARGET_FIONBIO		TARGET_IOW('f', 126, int) +#define TARGET_FIONREAD	        TARGET_IOR('f', 127, int) +#define TARGET_TIOCINQ		TARGET_FIONREAD +//#define TARGET_FIOQSIZE	        TARGET_IOR('f', 128, loff_t) + +#define TARGET_TCGETS		TARGET_IOR('t', 19, struct target_termios) +#define TARGET_TCSETS		TARGET_IOW('t', 20, struct target_termios) +#define TARGET_TCSETSW		TARGET_IOW('t', 21, struct target_termios) +#define TARGET_TCSETSF		TARGET_IOW('t', 22, struct target_termios) + +#define TARGET_TCGETA		TARGET_IOR('t', 23, struct target_termio) +#define TARGET_TCSETA		TARGET_IOW('t', 24, struct target_termio) +#define TARGET_TCSETAW		TARGET_IOW('t', 25, struct target_termio) +#define TARGET_TCSETAF		TARGET_IOW('t', 28, struct target_termio) + +#define TARGET_TCSBRK		TARGET_IO('t', 29) +#define TARGET_TCXONC		TARGET_IO('t', 30) +#define TARGET_TCFLSH		TARGET_IO('t', 31) + +#define TARGET_TIOCSWINSZ	TARGET_IOW('t', 103, struct target_winsize) +#define TARGET_TIOCGWINSZ	TARGET_IOR('t', 104, struct target_winsize) +#define	TARGET_TIOCSTART	TARGET_IO('t', 110)		/* start output, like ^Q */ +#define	TARGET_TIOCSTOP	TARGET_IO('t', 111)		/* stop output, like ^S */ +#define TARGET_TIOCOUTQ        TARGET_IOR('t', 115, int)     /* output queue size */ + +#define TARGET_TIOCGLTC	TARGET_IOR('t', 116, struct target_ltchars) +#define TARGET_TIOCSLTC	TARGET_IOW('t', 117, struct target_ltchars) +#define TARGET_TIOCSPGRP	TARGET_IOW('t', 118, int) +#define TARGET_TIOCGPGRP	TARGET_IOR('t', 119, int) + +#define TARGET_TIOCEXCL	0x540C +#define TARGET_TIOCNXCL	0x540D +#define TARGET_TIOCSCTTY	0x540E + +#define TARGET_TIOCSTI		0x5412 +#define TARGET_TIOCMGET	0x5415 +#define TARGET_TIOCMBIS	0x5416 +#define TARGET_TIOCMBIC	0x5417 +#define TARGET_TIOCMSET	0x5418 + +#define TARGET_TIOCGSOFTCAR	0x5419 +#define TARGET_TIOCSSOFTCAR	0x541A +#define TARGET_TIOCLINUX	0x541C +#define TARGET_TIOCCONS	0x541D +#define TARGET_TIOCGSERIAL	0x541E +#define TARGET_TIOCSSERIAL	0x541F +#define TARGET_TIOCPKT		0x5420 + +#define TARGET_TIOCNOTTY	0x5422 +#define TARGET_TIOCSETD	0x5423 +#define TARGET_TIOCGETD	0x5424 +#define TARGET_TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */ +#define TARGET_TIOCTTYGSTRUCT	0x5426  /* For debugging only */ +#define TARGET_TIOCSBRK	0x5427  /* BSD compatibility */ +#define TARGET_TIOCCBRK	0x5428  /* BSD compatibility */ +#define TARGET_TIOCGSID	0x5429  /* Return the session ID of FD */ +#define TARGET_TIOCGPTN	TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define TARGET_TIOCSPTLCK	TARGET_IOW('T',0x31, int)  /* Lock/unlock Pty */ + +#define TARGET_TIOCSERCONFIG	0x5453 +#define TARGET_TIOCSERGWILD	0x5454 +#define TARGET_TIOCSERSWILD	0x5455 +#define TARGET_TIOCGLCKTRMIOS	0x5456 +#define TARGET_TIOCSLCKTRMIOS	0x5457 +#define TARGET_TIOCSERGSTRUCT	0x5458 /* For debugging only */ +#define TARGET_TIOCSERGETLSR   0x5459 /* Get line status register */ +  /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ +# define TARGET_TIOCSER_TEMT    0x01	/* Transmitter physically empty */ +#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config  */ +#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TARGET_TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */ +#define TARGET_TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */ diff --git a/linux-user/qemu.h b/linux-user/qemu.h new file mode 100644 index 00000000..8012cc2f --- /dev/null +++ b/linux-user/qemu.h @@ -0,0 +1,458 @@ +#ifndef QEMU_H +#define QEMU_H + +#include <signal.h> +#include <string.h> + +#include "cpu.h" +#include "exec/cpu_ldst.h" + +#undef DEBUG_REMAP +#ifdef DEBUG_REMAP +#include <stdlib.h> +#endif /* DEBUG_REMAP */ + +#include "exec/user/abitypes.h" + +#include "exec/user/thunk.h" +#include "syscall_defs.h" +#include "syscall.h" +#include "exec/gdbstub.h" +#include "qemu/queue.h" + +#define THREAD __thread + +/* This struct is used to hold certain information about the image. + * Basically, it replicates in user space what would be certain + * task_struct fields in the kernel + */ +struct image_info { +        abi_ulong       load_bias; +        abi_ulong       load_addr; +        abi_ulong       start_code; +        abi_ulong       end_code; +        abi_ulong       start_data; +        abi_ulong       end_data; +        abi_ulong       start_brk; +        abi_ulong       brk; +        abi_ulong       start_mmap; +        abi_ulong       mmap; +        abi_ulong       rss; +        abi_ulong       start_stack; +        abi_ulong       stack_limit; +        abi_ulong       entry; +        abi_ulong       code_offset; +        abi_ulong       data_offset; +        abi_ulong       saved_auxv; +        abi_ulong       auxv_len; +        abi_ulong       arg_start; +        abi_ulong       arg_end; +        uint32_t        elf_flags; +	int		personality; +#ifdef CONFIG_USE_FDPIC +        abi_ulong       loadmap_addr; +        uint16_t        nsegs; +        void           *loadsegs; +        abi_ulong       pt_dynamic_addr; +        struct image_info *other_info; +#endif +}; + +#ifdef TARGET_I386 +/* Information about the current linux thread */ +struct vm86_saved_state { +    uint32_t eax; /* return code */ +    uint32_t ebx; +    uint32_t ecx; +    uint32_t edx; +    uint32_t esi; +    uint32_t edi; +    uint32_t ebp; +    uint32_t esp; +    uint32_t eflags; +    uint32_t eip; +    uint16_t cs, ss, ds, es, fs, gs; +}; +#endif + +#if defined(TARGET_ARM) && defined(TARGET_ABI32) +/* FPU emulator */ +#include "nwfpe/fpa11.h" +#endif + +#define MAX_SIGQUEUE_SIZE 1024 + +struct sigqueue { +    struct sigqueue *next; +    target_siginfo_t info; +}; + +struct emulated_sigtable { +    int pending; /* true if signal is pending */ +    struct sigqueue *first; +    struct sigqueue info; /* in order to always have memory for the +                             first signal, we put it here */ +}; + +/* NOTE: we force a big alignment so that the stack stored after is +   aligned too */ +typedef struct TaskState { +    pid_t ts_tid;     /* tid (or pid) of this task */ +#ifdef TARGET_ARM +# ifdef TARGET_ABI32 +    /* FPA state */ +    FPA11 fpa; +# endif +    int swi_errno; +#endif +#ifdef TARGET_UNICORE32 +    int swi_errno; +#endif +#if defined(TARGET_I386) && !defined(TARGET_X86_64) +    abi_ulong target_v86; +    struct vm86_saved_state vm86_saved_regs; +    struct target_vm86plus_struct vm86plus; +    uint32_t v86flags; +    uint32_t v86mask; +#endif +    abi_ulong child_tidptr; +#ifdef TARGET_M68K +    int sim_syscalls; +    abi_ulong tp_value; +#endif +#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32) +    /* Extra fields for semihosted binaries.  */ +    uint32_t heap_base; +    uint32_t heap_limit; +#endif +    uint32_t stack_base; +    int used; /* non zero if used */ +    bool sigsegv_blocked; /* SIGSEGV blocked by guest */ +    struct image_info *info; +    struct linux_binprm *bprm; + +    struct emulated_sigtable sigtab[TARGET_NSIG]; +    struct sigqueue sigqueue_table[MAX_SIGQUEUE_SIZE]; /* siginfo queue */ +    struct sigqueue *first_free; /* first free siginfo queue entry */ +    int signal_pending; /* non zero if a signal may be pending */ +} __attribute__((aligned(16))) TaskState; + +extern char *exec_path; +void init_task_state(TaskState *ts); +void task_settid(TaskState *); +void stop_all_tasks(void); +extern const char *qemu_uname_release; +extern unsigned long mmap_min_addr; + +/* ??? See if we can avoid exposing so much of the loader internals.  */ +/* + * MAX_ARG_PAGES defines the number of pages allocated for arguments + * and envelope for the new program. 32 should suffice, this gives + * a maximum env+arg of 128kB w/4KB pages! + */ +#define MAX_ARG_PAGES 33 + +/* Read a good amount of data initially, to hopefully get all the +   program headers loaded.  */ +#define BPRM_BUF_SIZE  1024 + +/* + * This structure is used to hold the arguments that are + * used when loading binaries. + */ +struct linux_binprm { +        char buf[BPRM_BUF_SIZE] __attribute__((aligned)); +        void *page[MAX_ARG_PAGES]; +        abi_ulong p; +	int fd; +        int e_uid, e_gid; +        int argc, envc; +        char **argv; +        char **envp; +        char * filename;        /* Name of binary */ +        int (*core_dump)(int, const CPUArchState *); /* coredump routine */ +}; + +void do_init_thread(struct target_pt_regs *regs, struct image_info *infop); +abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp, +                              abi_ulong stringp, int push_ptr); +int loader_exec(int fdexec, const char *filename, char **argv, char **envp, +             struct target_pt_regs * regs, struct image_info *infop, +             struct linux_binprm *); + +int load_elf_binary(struct linux_binprm *bprm, struct image_info *info); +int load_flt_binary(struct linux_binprm *bprm, struct image_info *info); + +abi_long memcpy_to_target(abi_ulong dest, const void *src, +                          unsigned long len); +void target_set_brk(abi_ulong new_brk); +abi_long do_brk(abi_ulong new_brk); +void syscall_init(void); +abi_long do_syscall(void *cpu_env, int num, abi_long arg1, +                    abi_long arg2, abi_long arg3, abi_long arg4, +                    abi_long arg5, abi_long arg6, abi_long arg7, +                    abi_long arg8); +void gemu_log(const char *fmt, ...) GCC_FMT_ATTR(1, 2); +extern THREAD CPUState *thread_cpu; +void cpu_loop(CPUArchState *env); +char *target_strerror(int err); +int get_osversion(void); +void init_qemu_uname_release(void); +void fork_start(void); +void fork_end(int child); + +/* Creates the initial guest address space in the host memory space using + * the given host start address hint and size.  The guest_start parameter + * specifies the start address of the guest space.  guest_base will be the + * difference between the host start address computed by this function and + * guest_start.  If fixed is specified, then the mapped address space must + * start at host_start.  The real start address of the mapped memory space is + * returned or -1 if there was an error. + */ +unsigned long init_guest_space(unsigned long host_start, +                               unsigned long host_size, +                               unsigned long guest_start, +                               bool fixed); + +#include "qemu/log.h" + +/* syscall.c */ +int host_to_target_waitstatus(int status); + +/* strace.c */ +void print_syscall(int num, +                   abi_long arg1, abi_long arg2, abi_long arg3, +                   abi_long arg4, abi_long arg5, abi_long arg6); +void print_syscall_ret(int num, abi_long arg1); +extern int do_strace; + +/* signal.c */ +void process_pending_signals(CPUArchState *cpu_env); +void signal_init(void); +int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info); +void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info); +void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo); +int target_to_host_signal(int sig); +int host_to_target_signal(int sig); +long do_sigreturn(CPUArchState *env); +long do_rt_sigreturn(CPUArchState *env); +abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp); +int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset); + +#ifdef TARGET_I386 +/* vm86.c */ +void save_v86_state(CPUX86State *env); +void handle_vm86_trap(CPUX86State *env, int trapno); +void handle_vm86_fault(CPUX86State *env); +int do_vm86(CPUX86State *env, long subfunction, abi_ulong v86_addr); +#elif defined(TARGET_SPARC64) +void sparc64_set_context(CPUSPARCState *env); +void sparc64_get_context(CPUSPARCState *env); +#endif + +/* mmap.c */ +int target_mprotect(abi_ulong start, abi_ulong len, int prot); +abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, +                     int flags, int fd, abi_ulong offset); +int target_munmap(abi_ulong start, abi_ulong len); +abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size, +                       abi_ulong new_size, unsigned long flags, +                       abi_ulong new_addr); +int target_msync(abi_ulong start, abi_ulong len, int flags); +extern unsigned long last_brk; +extern abi_ulong mmap_next_start; +void mmap_lock(void); +void mmap_unlock(void); +abi_ulong mmap_find_vma(abi_ulong, abi_ulong); +void cpu_list_lock(void); +void cpu_list_unlock(void); +void mmap_fork_start(void); +void mmap_fork_end(int child); + +/* main.c */ +extern unsigned long guest_stack_size; + +/* user access */ + +#define VERIFY_READ 0 +#define VERIFY_WRITE 1 /* implies read access */ + +static inline int access_ok(int type, abi_ulong addr, abi_ulong size) +{ +    return page_check_range((target_ulong)addr, size, +                            (type == VERIFY_READ) ? PAGE_READ : (PAGE_READ | PAGE_WRITE)) == 0; +} + +/* NOTE __get_user and __put_user use host pointers and don't check access. +   These are usually used to access struct data members once the struct has +   been locked - usually with lock_user_struct.  */ + +/* Tricky points: +   - Use __builtin_choose_expr to avoid type promotion from ?:, +   - Invalid sizes result in a compile time error stemming from +     the fact that abort has no parameters. +   - It's easier to use the endian-specific unaligned load/store +     functions than host-endian unaligned load/store plus tswapN.  */ + +#define __put_user_e(x, hptr, e)                                        \ +  (__builtin_choose_expr(sizeof(*(hptr)) == 1, stb_p,                   \ +   __builtin_choose_expr(sizeof(*(hptr)) == 2, stw_##e##_p,             \ +   __builtin_choose_expr(sizeof(*(hptr)) == 4, stl_##e##_p,             \ +   __builtin_choose_expr(sizeof(*(hptr)) == 8, stq_##e##_p, abort))))   \ +     ((hptr), (x)), (void)0) + +#define __get_user_e(x, hptr, e)                                        \ +  ((x) = (typeof(*hptr))(                                               \ +   __builtin_choose_expr(sizeof(*(hptr)) == 1, ldub_p,                  \ +   __builtin_choose_expr(sizeof(*(hptr)) == 2, lduw_##e##_p,            \ +   __builtin_choose_expr(sizeof(*(hptr)) == 4, ldl_##e##_p,             \ +   __builtin_choose_expr(sizeof(*(hptr)) == 8, ldq_##e##_p, abort))))   \ +     (hptr)), (void)0) + +#ifdef TARGET_WORDS_BIGENDIAN +# define __put_user(x, hptr)  __put_user_e(x, hptr, be) +# define __get_user(x, hptr)  __get_user_e(x, hptr, be) +#else +# define __put_user(x, hptr)  __put_user_e(x, hptr, le) +# define __get_user(x, hptr)  __get_user_e(x, hptr, le) +#endif + +/* put_user()/get_user() take a guest address and check access */ +/* These are usually used to access an atomic data type, such as an int, + * that has been passed by address.  These internally perform locking + * and unlocking on the data type. + */ +#define put_user(x, gaddr, target_type)					\ +({									\ +    abi_ulong __gaddr = (gaddr);					\ +    target_type *__hptr;						\ +    abi_long __ret = 0;							\ +    if ((__hptr = lock_user(VERIFY_WRITE, __gaddr, sizeof(target_type), 0))) { \ +        __put_user((x), __hptr);				\ +        unlock_user(__hptr, __gaddr, sizeof(target_type));		\ +    } else								\ +        __ret = -TARGET_EFAULT;						\ +    __ret;								\ +}) + +#define get_user(x, gaddr, target_type)					\ +({									\ +    abi_ulong __gaddr = (gaddr);					\ +    target_type *__hptr;						\ +    abi_long __ret = 0;							\ +    if ((__hptr = lock_user(VERIFY_READ, __gaddr, sizeof(target_type), 1))) { \ +        __get_user((x), __hptr);				\ +        unlock_user(__hptr, __gaddr, 0);				\ +    } else {								\ +        /* avoid warning */						\ +        (x) = 0;							\ +        __ret = -TARGET_EFAULT;						\ +    }									\ +    __ret;								\ +}) + +#define put_user_ual(x, gaddr) put_user((x), (gaddr), abi_ulong) +#define put_user_sal(x, gaddr) put_user((x), (gaddr), abi_long) +#define put_user_u64(x, gaddr) put_user((x), (gaddr), uint64_t) +#define put_user_s64(x, gaddr) put_user((x), (gaddr), int64_t) +#define put_user_u32(x, gaddr) put_user((x), (gaddr), uint32_t) +#define put_user_s32(x, gaddr) put_user((x), (gaddr), int32_t) +#define put_user_u16(x, gaddr) put_user((x), (gaddr), uint16_t) +#define put_user_s16(x, gaddr) put_user((x), (gaddr), int16_t) +#define put_user_u8(x, gaddr)  put_user((x), (gaddr), uint8_t) +#define put_user_s8(x, gaddr)  put_user((x), (gaddr), int8_t) + +#define get_user_ual(x, gaddr) get_user((x), (gaddr), abi_ulong) +#define get_user_sal(x, gaddr) get_user((x), (gaddr), abi_long) +#define get_user_u64(x, gaddr) get_user((x), (gaddr), uint64_t) +#define get_user_s64(x, gaddr) get_user((x), (gaddr), int64_t) +#define get_user_u32(x, gaddr) get_user((x), (gaddr), uint32_t) +#define get_user_s32(x, gaddr) get_user((x), (gaddr), int32_t) +#define get_user_u16(x, gaddr) get_user((x), (gaddr), uint16_t) +#define get_user_s16(x, gaddr) get_user((x), (gaddr), int16_t) +#define get_user_u8(x, gaddr)  get_user((x), (gaddr), uint8_t) +#define get_user_s8(x, gaddr)  get_user((x), (gaddr), int8_t) + +/* copy_from_user() and copy_to_user() are usually used to copy data + * buffers between the target and host.  These internally perform + * locking/unlocking of the memory. + */ +abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len); +abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len); + +/* Functions for accessing guest memory.  The tget and tput functions +   read/write single values, byteswapping as necessary.  The lock_user function +   gets a pointer to a contiguous area of guest memory, but does not perform +   any byteswapping.  lock_user may return either a pointer to the guest +   memory, or a temporary buffer.  */ + +/* Lock an area of guest memory into the host.  If copy is true then the +   host area will have the same contents as the guest.  */ +static inline void *lock_user(int type, abi_ulong guest_addr, long len, int copy) +{ +    if (!access_ok(type, guest_addr, len)) +        return NULL; +#ifdef DEBUG_REMAP +    { +        void *addr; +        addr = malloc(len); +        if (copy) +            memcpy(addr, g2h(guest_addr), len); +        else +            memset(addr, 0, len); +        return addr; +    } +#else +    return g2h(guest_addr); +#endif +} + +/* Unlock an area of guest memory.  The first LEN bytes must be +   flushed back to guest memory. host_ptr = NULL is explicitly +   allowed and does nothing. */ +static inline void unlock_user(void *host_ptr, abi_ulong guest_addr, +                               long len) +{ + +#ifdef DEBUG_REMAP +    if (!host_ptr) +        return; +    if (host_ptr == g2h(guest_addr)) +        return; +    if (len > 0) +        memcpy(g2h(guest_addr), host_ptr, len); +    free(host_ptr); +#endif +} + +/* Return the length of a string in target memory or -TARGET_EFAULT if +   access error. */ +abi_long target_strlen(abi_ulong gaddr); + +/* Like lock_user but for null terminated strings.  */ +static inline void *lock_user_string(abi_ulong guest_addr) +{ +    abi_long len; +    len = target_strlen(guest_addr); +    if (len < 0) +        return NULL; +    return lock_user(VERIFY_READ, guest_addr, (long)(len + 1), 1); +} + +/* Helper macros for locking/unlocking a target struct.  */ +#define lock_user_struct(type, host_ptr, guest_addr, copy)	\ +    (host_ptr = lock_user(type, guest_addr, sizeof(*host_ptr), copy)) +#define unlock_user_struct(host_ptr, guest_addr, copy)		\ +    unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0) + +#include <pthread.h> + +/* Include target-specific struct and function definitions; + * they may need access to the target-independent structures + * above, so include them last. + */ +#include "target_cpu.h" +#include "target_signal.h" +#include "target_structs.h" + +#endif /* QEMU_H */ diff --git a/linux-user/s390x/syscall.h b/linux-user/s390x/syscall.h new file mode 100644 index 00000000..35f170af --- /dev/null +++ b/linux-user/s390x/syscall.h @@ -0,0 +1,29 @@ +/* this typedef defines how a Program Status Word looks like */ +typedef struct { +    abi_ulong mask; +    abi_ulong addr; +} __attribute__ ((aligned(8))) target_psw_t; + +/* + * The pt_regs struct defines the way the registers are stored on + * the stack during a system call. + */ + +#define TARGET_NUM_GPRS        16 + +struct target_pt_regs { +    abi_ulong args[1]; +    target_psw_t psw; +    abi_ulong gprs[TARGET_NUM_GPRS]; +    abi_ulong orig_gpr2; +    unsigned short ilen; +    unsigned short trap; +}; + +#define UNAME_MACHINE "s390x" +#define UNAME_MINIMUM_RELEASE "2.6.32" + +#define TARGET_CLONE_BACKWARDS2 +#define TARGET_MINSIGSTKSZ        2048 +#define TARGET_MLOCKALL_MCL_CURRENT 1 +#define TARGET_MLOCKALL_MCL_FUTURE  2 diff --git a/linux-user/s390x/syscall_nr.h b/linux-user/s390x/syscall_nr.h new file mode 100644 index 00000000..7c0b8b2e --- /dev/null +++ b/linux-user/s390x/syscall_nr.h @@ -0,0 +1,363 @@ +/* + * This file contains the system call numbers. + */ + +#define TARGET_NR_exit                 1 +#define TARGET_NR_fork                 2 +#define TARGET_NR_read                 3 +#define TARGET_NR_write                4 +#define TARGET_NR_open                 5 +#define TARGET_NR_close                6 +#define TARGET_NR_restart_syscall	  7 +#define TARGET_NR_creat                8 +#define TARGET_NR_link                 9 +#define TARGET_NR_unlink              10 +#define TARGET_NR_execve              11 +#define TARGET_NR_chdir               12 +#define TARGET_NR_mknod               14 +#define TARGET_NR_chmod               15 +#define TARGET_NR_lseek               19 +#define TARGET_NR_getpid              20 +#define TARGET_NR_mount               21 +#define TARGET_NR_umount              22 +#define TARGET_NR_ptrace              26 +#define TARGET_NR_alarm               27 +#define TARGET_NR_pause               29 +#define TARGET_NR_utime               30 +#define TARGET_NR_access              33 +#define TARGET_NR_nice                34 +#define TARGET_NR_sync                36 +#define TARGET_NR_kill                37 +#define TARGET_NR_rename              38 +#define TARGET_NR_mkdir               39 +#define TARGET_NR_rmdir               40 +#define TARGET_NR_dup                 41 +#define TARGET_NR_pipe                42 +#define TARGET_NR_times               43 +#define TARGET_NR_brk                 45 +#define TARGET_NR_signal              48 +#define TARGET_NR_acct                51 +#define TARGET_NR_umount2             52 +#define TARGET_NR_ioctl               54 +#define TARGET_NR_fcntl               55 +#define TARGET_NR_setpgid             57 +#define TARGET_NR_umask               60 +#define TARGET_NR_chroot              61 +#define TARGET_NR_ustat               62 +#define TARGET_NR_dup2                63 +#define TARGET_NR_getppid             64 +#define TARGET_NR_getpgrp             65 +#define TARGET_NR_setsid              66 +#define TARGET_NR_sigaction           67 +#define TARGET_NR_sigsuspend          72 +#define TARGET_NR_sigpending          73 +#define TARGET_NR_sethostname         74 +#define TARGET_NR_setrlimit           75 +#define TARGET_NR_getrusage           77 +#define TARGET_NR_gettimeofday        78 +#define TARGET_NR_settimeofday        79 +#define TARGET_NR_symlink             83 +#define TARGET_NR_readlink            85 +#define TARGET_NR_uselib              86 +#define TARGET_NR_swapon              87 +#define TARGET_NR_reboot              88 +#define TARGET_NR_readdir             89 +#define TARGET_NR_mmap                90 +#define TARGET_NR_munmap              91 +#define TARGET_NR_truncate            92 +#define TARGET_NR_ftruncate           93 +#define TARGET_NR_fchmod              94 +#define TARGET_NR_getpriority         96 +#define TARGET_NR_setpriority         97 +#define TARGET_NR_statfs              99 +#define TARGET_NR_fstatfs            100 +#define TARGET_NR_socketcall         102 +#define TARGET_NR_syslog             103 +#define TARGET_NR_setitimer          104 +#define TARGET_NR_getitimer          105 +#define TARGET_NR_stat               106 +#define TARGET_NR_lstat              107 +#define TARGET_NR_fstat              108 +#define TARGET_NR_lookup_dcookie     110 +#define TARGET_NR_vhangup            111 +#define TARGET_NR_idle               112 +#define TARGET_NR_wait4              114 +#define TARGET_NR_swapoff            115 +#define TARGET_NR_sysinfo            116 +#define TARGET_NR_ipc                117 +#define TARGET_NR_fsync              118 +#define TARGET_NR_sigreturn          119 +#define TARGET_NR_clone              120 +#define TARGET_NR_setdomainname      121 +#define TARGET_NR_uname              122 +#define TARGET_NR_adjtimex           124 +#define TARGET_NR_mprotect           125 +#define TARGET_NR_sigprocmask        126 +#define TARGET_NR_create_module      127 +#define TARGET_NR_init_module        128 +#define TARGET_NR_delete_module      129 +#define TARGET_NR_get_kernel_syms    130 +#define TARGET_NR_quotactl           131 +#define TARGET_NR_getpgid            132 +#define TARGET_NR_fchdir             133 +#define TARGET_NR_bdflush            134 +#define TARGET_NR_sysfs              135 +#define TARGET_NR_personality        136 +#define TARGET_NR_afs_syscall        137 /* Syscall for Andrew File System */ +#define TARGET_NR_getdents           141 +#define TARGET_NR_flock              143 +#define TARGET_NR_msync              144 +#define TARGET_NR_readv              145 +#define TARGET_NR_writev             146 +#define TARGET_NR_getsid             147 +#define TARGET_NR_fdatasync          148 +#define TARGET_NR__sysctl            149 +#define TARGET_NR_mlock              150 +#define TARGET_NR_munlock            151 +#define TARGET_NR_mlockall           152 +#define TARGET_NR_munlockall         153 +#define TARGET_NR_sched_setparam             154 +#define TARGET_NR_sched_getparam             155 +#define TARGET_NR_sched_setscheduler         156 +#define TARGET_NR_sched_getscheduler         157 +#define TARGET_NR_sched_yield                158 +#define TARGET_NR_sched_get_priority_max     159 +#define TARGET_NR_sched_get_priority_min     160 +#define TARGET_NR_sched_rr_get_interval      161 +#define TARGET_NR_nanosleep          162 +#define TARGET_NR_mremap             163 +#define TARGET_NR_query_module       167 +#define TARGET_NR_poll               168 +#define TARGET_NR_nfsservctl         169 +#define TARGET_NR_prctl              172 +#define TARGET_NR_rt_sigreturn       173 +#define TARGET_NR_rt_sigaction       174 +#define TARGET_NR_rt_sigprocmask     175 +#define TARGET_NR_rt_sigpending      176 +#define TARGET_NR_rt_sigtimedwait    177 +#define TARGET_NR_rt_sigqueueinfo    178 +#define TARGET_NR_rt_sigsuspend      179 +#define TARGET_NR_pread64            180 +#define TARGET_NR_pwrite64           181 +#define TARGET_NR_getcwd             183 +#define TARGET_NR_capget             184 +#define TARGET_NR_capset             185 +#define TARGET_NR_sigaltstack        186 +#define TARGET_NR_sendfile           187 +#define TARGET_NR_getpmsg		188 +#define TARGET_NR_putpmsg		189 +#define TARGET_NR_vfork		190 +#define TARGET_NR_pivot_root         217 +#define TARGET_NR_mincore            218 +#define TARGET_NR_madvise            219 +#define TARGET_NR_getdents64		220 +#define TARGET_NR_readahead		222 +#define TARGET_NR_setxattr		224 +#define TARGET_NR_lsetxattr		225 +#define TARGET_NR_fsetxattr		226 +#define TARGET_NR_getxattr		227 +#define TARGET_NR_lgetxattr		228 +#define TARGET_NR_fgetxattr		229 +#define TARGET_NR_listxattr		230 +#define TARGET_NR_llistxattr		231 +#define TARGET_NR_flistxattr		232 +#define TARGET_NR_removexattr	233 +#define TARGET_NR_lremovexattr	234 +#define TARGET_NR_fremovexattr	235 +#define TARGET_NR_gettid		236 +#define TARGET_NR_tkill		237 +#define TARGET_NR_futex		238 +#define TARGET_NR_sched_setaffinity	239 +#define TARGET_NR_sched_getaffinity	240 +#define TARGET_NR_tgkill		241 +/* Number 242 is reserved for tux */ +#define TARGET_NR_io_setup		243 +#define TARGET_NR_io_destroy		244 +#define TARGET_NR_io_getevents	245 +#define TARGET_NR_io_submit		246 +#define TARGET_NR_io_cancel		247 +#define TARGET_NR_exit_group		248 +#define TARGET_NR_epoll_create	249 +#define TARGET_NR_epoll_ctl		250 +#define TARGET_NR_epoll_wait		251 +#define TARGET_NR_set_tid_address	252 +#define TARGET_NR_fadvise64		253 +#define TARGET_NR_timer_create	254 +#define TARGET_NR_timer_settime	(TARGET_NR_timer_create+1) +#define TARGET_NR_timer_gettime	(TARGET_NR_timer_create+2) +#define TARGET_NR_timer_getoverrun	(TARGET_NR_timer_create+3) +#define TARGET_NR_timer_delete	(TARGET_NR_timer_create+4) +#define TARGET_NR_clock_settime	(TARGET_NR_timer_create+5) +#define TARGET_NR_clock_gettime	(TARGET_NR_timer_create+6) +#define TARGET_NR_clock_getres	(TARGET_NR_timer_create+7) +#define TARGET_NR_clock_nanosleep	(TARGET_NR_timer_create+8) +/* Number 263 is reserved for vserver */ +#define TARGET_NR_statfs64		265 +#define TARGET_NR_fstatfs64		266 +#define TARGET_NR_remap_file_pages	267 +/* Number 268 is reserved for new sys_mbind */ +/* Number 269 is reserved for new sys_get_mempolicy */ +/* Number 270 is reserved for new sys_set_mempolicy */ +#define TARGET_NR_mq_open		271 +#define TARGET_NR_mq_unlink		272 +#define TARGET_NR_mq_timedsend	273 +#define TARGET_NR_mq_timedreceive	274 +#define TARGET_NR_mq_notify		275 +#define TARGET_NR_mq_getsetattr	276 +#define TARGET_NR_kexec_load		277 +#define TARGET_NR_add_key		278 +#define TARGET_NR_request_key	279 +#define TARGET_NR_keyctl		280 +#define TARGET_NR_waitid		281 +#define TARGET_NR_ioprio_set		282 +#define TARGET_NR_ioprio_get		283 +#define TARGET_NR_inotify_init	284 +#define TARGET_NR_inotify_add_watch	285 +#define TARGET_NR_inotify_rm_watch	286 +/* Number 287 is reserved for new sys_migrate_pages */ +#define TARGET_NR_openat		288 +#define TARGET_NR_mkdirat		289 +#define TARGET_NR_mknodat		290 +#define TARGET_NR_fchownat		291 +#define TARGET_NR_futimesat		292 +#define TARGET_NR_unlinkat		294 +#define TARGET_NR_renameat		295 +#define TARGET_NR_linkat		296 +#define TARGET_NR_symlinkat		297 +#define TARGET_NR_readlinkat		298 +#define TARGET_NR_fchmodat		299 +#define TARGET_NR_faccessat		300 +#define TARGET_NR_pselect6		301 +#define TARGET_NR_ppoll		302 +#define TARGET_NR_unshare		303 +#define TARGET_NR_set_robust_list	304 +#define TARGET_NR_get_robust_list	305 +#define TARGET_NR_splice		306 +#define TARGET_NR_sync_file_range	307 +#define TARGET_NR_tee		308 +#define TARGET_NR_vmsplice		309 +/* Number 310 is reserved for new sys_move_pages */ +#define TARGET_NR_getcpu		311 +#define TARGET_NR_epoll_pwait	312 +#define TARGET_NR_utimes		313 +#define TARGET_NR_fallocate		314 +#define TARGET_NR_utimensat		315 +#define TARGET_NR_signalfd		316 +#define TARGET_NR_timerfd		317 +#define TARGET_NR_eventfd		318 +#define TARGET_NR_timerfd_create	319 +#define TARGET_NR_timerfd_settime	320 +#define TARGET_NR_timerfd_gettime	321 +#define TARGET_NR_signalfd4		322 +#define TARGET_NR_eventfd2		323 +#define TARGET_NR_inotify_init1	324 +#define TARGET_NR_pipe2		325 +#define TARGET_NR_dup3		326 +#define TARGET_NR_epoll_create1	327 +#define TARGET_NR_preadv                328 +#define TARGET_NR_pwritev               329 +#define TARGET_NR_rt_tgsigqueueinfo     330 +#define TARGET_NR_perf_event_open       331 +#define TARGET_NR_fanotify_init         332 +#define TARGET_NR_fanotify_mark         333 +#define TARGET_NR_prlimit64             334 +#define TARGET_NR_name_to_handle_at     335 +#define TARGET_NR_open_by_handle_at     336 +#define TARGET_NR_clock_adjtime         337 +#define TARGET_NR_syncfs                338 +#define TARGET_NR_setns                 339 +#define TARGET_NR_process_vm_readv      340 +#define TARGET_NR_process_vm_writev     341 +#define TARGET_NR_s390_runtime_instr    342 +#define TARGET_NR_kcmp                  343 +#define TARGET_NR_finit_module          344 + +/* + * There are some system calls that are not present on 64 bit, some + * have a different name although they do the same (e.g. TARGET_NR_chown32 + * is TARGET_NR_chown on 64 bit). + */ +#ifndef TARGET_S390X + +#define TARGET_NR_time		 13 +#define TARGET_NR_lchown		 16 +#define TARGET_NR_setuid		 23 +#define TARGET_NR_getuid		 24 +#define TARGET_NR_stime		 25 +#define TARGET_NR_setgid		 46 +#define TARGET_NR_getgid		 47 +#define TARGET_NR_geteuid		 49 +#define TARGET_NR_getegid		 50 +#define TARGET_NR_setreuid		 70 +#define TARGET_NR_setregid		 71 +#define TARGET_NR_getrlimit		 76 +#define TARGET_NR_getgroups		 80 +#define TARGET_NR_setgroups		 81 +#define TARGET_NR_fchown		 95 +#define TARGET_NR_ioperm		101 +#define TARGET_NR_setfsuid		138 +#define TARGET_NR_setfsgid		139 +#define TARGET_NR__llseek		140 +#define TARGET_NR__newselect 	142 +#define TARGET_NR_setresuid		164 +#define TARGET_NR_getresuid		165 +#define TARGET_NR_setresgid		170 +#define TARGET_NR_getresgid		171 +#define TARGET_NR_chown		182 +#define TARGET_NR_ugetrlimit		191	/* SuS compliant getrlimit */ +#define TARGET_NR_mmap2		192 +#define TARGET_NR_truncate64		193 +#define TARGET_NR_ftruncate64	194 +#define TARGET_NR_stat64		195 +#define TARGET_NR_lstat64		196 +#define TARGET_NR_fstat64		197 +#define TARGET_NR_lchown32		198 +#define TARGET_NR_getuid32		199 +#define TARGET_NR_getgid32		200 +#define TARGET_NR_geteuid32		201 +#define TARGET_NR_getegid32		202 +#define TARGET_NR_setreuid32		203 +#define TARGET_NR_setregid32		204 +#define TARGET_NR_getgroups32	205 +#define TARGET_NR_setgroups32	206 +#define TARGET_NR_fchown32		207 +#define TARGET_NR_setresuid32	208 +#define TARGET_NR_getresuid32	209 +#define TARGET_NR_setresgid32	210 +#define TARGET_NR_getresgid32	211 +#define TARGET_NR_chown32		212 +#define TARGET_NR_setuid32		213 +#define TARGET_NR_setgid32		214 +#define TARGET_NR_setfsuid32		215 +#define TARGET_NR_setfsgid32		216 +#define TARGET_NR_fcntl64		221 +#define TARGET_NR_sendfile64		223 +#define TARGET_NR_fadvise64_64	264 +#define TARGET_NR_fstatat64		293 + +#else + +#define TARGET_NR_select		142 +#define TARGET_NR_getrlimit		191	/* SuS compliant getrlimit */ +#define TARGET_NR_lchown  		198 +#define TARGET_NR_getuid  		199 +#define TARGET_NR_getgid  		200 +#define TARGET_NR_geteuid  		201 +#define TARGET_NR_getegid  		202 +#define TARGET_NR_setreuid  		203 +#define TARGET_NR_setregid  		204 +#define TARGET_NR_getgroups  	205 +#define TARGET_NR_setgroups  	206 +#define TARGET_NR_fchown  		207 +#define TARGET_NR_setresuid  	208 +#define TARGET_NR_getresuid  	209 +#define TARGET_NR_setresgid  	210 +#define TARGET_NR_getresgid  	211 +#define TARGET_NR_chown  		212 +#define TARGET_NR_setuid  		213 +#define TARGET_NR_setgid  		214 +#define TARGET_NR_setfsuid  		215 +#define TARGET_NR_setfsgid  		216 +#define TARGET_NR_newfstatat		293 + +#endif diff --git a/linux-user/s390x/target_cpu.h b/linux-user/s390x/target_cpu.h new file mode 100644 index 00000000..f10abe8e --- /dev/null +++ b/linux-user/s390x/target_cpu.h @@ -0,0 +1,39 @@ +/* + * S/390 specific CPU ABI and functions for linux-user + * + * Copyright (c) 2009 Ulrich Hecht + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * Contributions after 2012-10-29 are licensed under the terms of the + * GNU GPL, version 2 or (at your option) any later version. + * + * You should have received a copy of the GNU (Lesser) General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUS390XState *env, target_ulong newsp) +{ +    if (newsp) { +        env->regs[15] = newsp; +    } +    env->regs[2] = 0; +} + +static inline void cpu_set_tls(CPUS390XState *env, target_ulong newtls) +{ +    env->aregs[0] = newtls >> 32; +    env->aregs[1] = newtls & 0xffffffffULL; +} + +#endif diff --git a/linux-user/s390x/target_signal.h b/linux-user/s390x/target_signal.h new file mode 100644 index 00000000..b4816b04 --- /dev/null +++ b/linux-user/s390x/target_signal.h @@ -0,0 +1,26 @@ +#ifndef TARGET_SIGNAL_H +#define TARGET_SIGNAL_H + +#include "cpu.h" + +typedef struct target_sigaltstack { +    abi_ulong ss_sp; +    int ss_flags; +    abi_ulong ss_size; +} target_stack_t; + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK      1 +#define TARGET_SS_DISABLE      2 + +#define TARGET_MINSIGSTKSZ     2048 +#define TARGET_SIGSTKSZ        8192 + +static inline abi_ulong get_sp_from_cpustate(CPUS390XState *state) +{ +   return state->regs[15]; +} + +#endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/s390x/target_structs.h b/linux-user/s390x/target_structs.h new file mode 100644 index 00000000..6b6f5b52 --- /dev/null +++ b/linux-user/s390x/target_structs.h @@ -0,0 +1,63 @@ +/* + * S/390 specific structures for linux-user + * + * Copyright (c) 2013 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_STRUCTS_H +#define TARGET_STRUCTS_H + + +struct target_ipc_perm { +    abi_int __key;                       /* Key.  */ +    abi_uint uid;                        /* Owner's user ID.  */ +    abi_uint gid;                        /* Owner's group ID.  */ +    abi_uint cuid;                       /* Creator's user ID.  */ +    abi_uint cgid;                       /* Creator's group ID.  */ +#if TARGET_ABI_BITS == 64 +    abi_uint mode;                       /* Read/write permission.  */ +#else +    abi_ushort mode;                     /* Read/write permission.  */ +    abi_ushort __pad1; +#endif +    abi_ushort __seq;                    /* Sequence number.  */ +    abi_ushort __pad2; +    abi_ulong __unused1; +    abi_ulong __unused2; +}; + +struct target_shmid_ds { +    struct target_ipc_perm shm_perm;    /* operation permission struct */ +    abi_long shm_segsz;                 /* size of segment in bytes */ +    abi_ulong shm_atime;                /* time of last shmat() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused1; +#endif +    abi_ulong shm_dtime;                /* time of last shmdt() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused2; +#endif +    abi_ulong shm_ctime;                /* time of last change by shmctl() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused3; +#endif +    abi_int shm_cpid;                   /* pid of creator */ +    abi_int shm_lpid;                   /* pid of last shmop */ +    abi_ulong shm_nattch;               /* number of current attaches */ +    abi_ulong __unused4; +    abi_ulong __unused5; +}; + +#endif diff --git a/linux-user/s390x/termbits.h b/linux-user/s390x/termbits.h new file mode 100644 index 00000000..2a78a055 --- /dev/null +++ b/linux-user/s390x/termbits.h @@ -0,0 +1,283 @@ +/* + *  include/asm-s390/termbits.h + * + *  S390 version + * + *  Derived from "include/asm-i386/termbits.h" + */ + +#define TARGET_NCCS 19 +struct target_termios { +    unsigned int c_iflag;		/* input mode flags */ +    unsigned int c_oflag;		/* output mode flags */ +    unsigned int c_cflag;		/* control mode flags */ +    unsigned int c_lflag;		/* local mode flags */ +    unsigned char c_line;			/* line discipline */ +    unsigned char c_cc[TARGET_NCCS];		/* control characters */ +}; + +struct target_termios2 { +    unsigned int c_iflag;		/* input mode flags */ +    unsigned int c_oflag;		/* output mode flags */ +    unsigned int c_cflag;		/* control mode flags */ +    unsigned int c_lflag;		/* local mode flags */ +    unsigned char c_line;			/* line discipline */ +    unsigned char c_cc[TARGET_NCCS];		/* control characters */ +    unsigned int c_ispeed;		/* input speed */ +    unsigned int c_ospeed;		/* output speed */ +}; + +struct target_ktermios { +    unsigned int c_iflag;		/* input mode flags */ +    unsigned int c_oflag;		/* output mode flags */ +    unsigned int c_cflag;		/* control mode flags */ +    unsigned int c_lflag;		/* local mode flags */ +    unsigned char c_line;			/* line discipline */ +    unsigned char c_cc[TARGET_NCCS];		/* control characters */ +    unsigned int c_ispeed;		/* input speed */ +    unsigned int c_ospeed;		/* output speed */ +}; + +/* c_cc characters */ +#define TARGET_VINTR 0 +#define TARGET_VQUIT 1 +#define TARGET_VERASE 2 +#define TARGET_VKILL 3 +#define TARGET_VEOF 4 +#define TARGET_VTIME 5 +#define TARGET_VMIN 6 +#define TARGET_VSWTC 7 +#define TARGET_VSTART 8 +#define TARGET_VSTOP 9 +#define TARGET_VSUSP 10 +#define TARGET_VEOL 11 +#define TARGET_VREPRINT 12 +#define TARGET_VDISCARD 13 +#define TARGET_VWERASE 14 +#define TARGET_VLNEXT 15 +#define TARGET_VEOL2 16 + +/* c_iflag bits */ +#define TARGET_IGNBRK	0000001 +#define TARGET_BRKINT	0000002 +#define TARGET_IGNPAR	0000004 +#define TARGET_PARMRK	0000010 +#define TARGET_INPCK	0000020 +#define TARGET_ISTRIP	0000040 +#define TARGET_INLCR	0000100 +#define TARGET_IGNCR	0000200 +#define TARGET_ICRNL	0000400 +#define TARGET_IUCLC	0001000 +#define TARGET_IXON	0002000 +#define TARGET_IXANY	0004000 +#define TARGET_IXOFF	0010000 +#define TARGET_IMAXBEL	0020000 +#define TARGET_IUTF8	0040000 + +/* c_oflag bits */ +#define TARGET_OPOST	0000001 +#define TARGET_OLCUC	0000002 +#define TARGET_ONLCR	0000004 +#define TARGET_OCRNL	0000010 +#define TARGET_ONOCR	0000020 +#define TARGET_ONLRET	0000040 +#define TARGET_OFILL	0000100 +#define TARGET_OFDEL	0000200 +#define TARGET_NLDLY	0000400 +#define TARGET_NL0	0000000 +#define TARGET_NL1	0000400 +#define TARGET_CRDLY	0003000 +#define TARGET_CR0	0000000 +#define TARGET_CR1	0001000 +#define TARGET_CR2	0002000 +#define TARGET_CR3	0003000 +#define TARGET_TABDLY	0014000 +#define TARGET_TAB0	0000000 +#define TARGET_TAB1	0004000 +#define TARGET_TAB2	0010000 +#define TARGET_TAB3	0014000 +#define TARGET_XTABS	0014000 +#define TARGET_BSDLY	0020000 +#define TARGET_BS0	0000000 +#define TARGET_BS1	0020000 +#define TARGET_VTDLY	0040000 +#define TARGET_VT0	0000000 +#define TARGET_VT1	0040000 +#define TARGET_FFDLY	0100000 +#define TARGET_FF0	0000000 +#define TARGET_FF1	0100000 + +/* c_cflag bit meaning */ +#define TARGET_CBAUD	0010017 +#define TARGET_B0	0000000		/* hang up */ +#define TARGET_B50	0000001 +#define TARGET_B75	0000002 +#define TARGET_B110	0000003 +#define TARGET_B134	0000004 +#define TARGET_B150	0000005 +#define TARGET_B200	0000006 +#define TARGET_B300	0000007 +#define TARGET_B600	0000010 +#define TARGET_B1200	0000011 +#define TARGET_B1800	0000012 +#define TARGET_B2400	0000013 +#define TARGET_B4800	0000014 +#define TARGET_B9600	0000015 +#define TARGET_B19200	0000016 +#define TARGET_B38400	0000017 +#define TARGET_EXTA B19200 +#define TARGET_EXTB B38400 +#define TARGET_CSIZE	0000060 +#define TARGET_CS5	0000000 +#define TARGET_CS6	0000020 +#define TARGET_CS7	0000040 +#define TARGET_CS8	0000060 +#define TARGET_CSTOPB	0000100 +#define TARGET_CREAD	0000200 +#define TARGET_PARENB	0000400 +#define TARGET_PARODD	0001000 +#define TARGET_HUPCL	0002000 +#define TARGET_CLOCAL	0004000 +#define TARGET_CBAUDEX 0010000 +#define TARGET_BOTHER  0010000 +#define TARGET_B57600  0010001 +#define TARGET_B115200 0010002 +#define TARGET_B230400 0010003 +#define TARGET_B460800 0010004 +#define TARGET_B500000 0010005 +#define TARGET_B576000 0010006 +#define TARGET_B921600 0010007 +#define TARGET_B1000000 0010010 +#define TARGET_B1152000 0010011 +#define TARGET_B1500000 0010012 +#define TARGET_B2000000 0010013 +#define TARGET_B2500000 0010014 +#define TARGET_B3000000 0010015 +#define TARGET_B3500000 0010016 +#define TARGET_B4000000 0010017 +#define TARGET_CIBAUD	  002003600000	/* input baud rate */ +#define TARGET_CMSPAR	  010000000000		/* mark or space (stick) parity */ +#define TARGET_CRTSCTS	  020000000000		/* flow control */ + +#define TARGET_IBSHIFT	  16		/* Shift from CBAUD to CIBAUD */ + +/* c_lflag bits */ +#define TARGET_ISIG	0000001 +#define TARGET_ICANON	0000002 +#define TARGET_XCASE	0000004 +#define TARGET_ECHO	0000010 +#define TARGET_ECHOE	0000020 +#define TARGET_ECHOK	0000040 +#define TARGET_ECHONL	0000100 +#define TARGET_NOFLSH	0000200 +#define TARGET_TOSTOP	0000400 +#define TARGET_ECHOCTL	0001000 +#define TARGET_ECHOPRT	0002000 +#define TARGET_ECHOKE	0004000 +#define TARGET_FLUSHO	0010000 +#define TARGET_PENDIN	0040000 +#define TARGET_IEXTEN	0100000 + +/* tcflow() and TCXONC use these */ +#define	TARGET_TCOOFF		0 +#define	TARGET_TCOON		1 +#define	TARGET_TCIOFF		2 +#define	TARGET_TCION		3 + +/* tcflush() and TCFLSH use these */ +#define	TARGET_TCIFLUSH	0 +#define	TARGET_TCOFLUSH	1 +#define	TARGET_TCIOFLUSH	2 + +/* tcsetattr uses these */ +#define	TARGET_TCSANOW		0 +#define	TARGET_TCSADRAIN	1 +#define	TARGET_TCSAFLUSH	2 + +/* + *  include/asm-s390/ioctls.h + * + *  S390 version + * + *  Derived from "include/asm-i386/ioctls.h" + */ + +/* 0x54 is just a magic number to make these relatively unique ('T') */ + +#define TARGET_TCGETS		0x5401 +#define TARGET_TCSETS		0x5402 +#define TARGET_TCSETSW		0x5403 +#define TARGET_TCSETSF		0x5404 +#define TARGET_TCGETA		0x5405 +#define TARGET_TCSETA		0x5406 +#define TARGET_TCSETAW		0x5407 +#define TARGET_TCSETAF		0x5408 +#define TARGET_TCSBRK		0x5409 +#define TARGET_TCXONC		0x540A +#define TARGET_TCFLSH		0x540B +#define TARGET_TIOCEXCL	0x540C +#define TARGET_TIOCNXCL	0x540D +#define TARGET_TIOCSCTTY	0x540E +#define TARGET_TIOCGPGRP	0x540F +#define TARGET_TIOCSPGRP	0x5410 +#define TARGET_TIOCOUTQ	0x5411 +#define TARGET_TIOCSTI		0x5412 +#define TARGET_TIOCGWINSZ	0x5413 +#define TARGET_TIOCSWINSZ	0x5414 +#define TARGET_TIOCMGET	0x5415 +#define TARGET_TIOCMBIS	0x5416 +#define TARGET_TIOCMBIC	0x5417 +#define TARGET_TIOCMSET	0x5418 +#define TARGET_TIOCGSOFTCAR	0x5419 +#define TARGET_TIOCSSOFTCAR	0x541A +#define TARGET_FIONREAD	0x541B +#define TARGET_TIOCINQ		FIONREAD +#define TARGET_TIOCLINUX	0x541C +#define TARGET_TIOCCONS	0x541D +#define TARGET_TIOCGSERIAL	0x541E +#define TARGET_TIOCSSERIAL	0x541F +#define TARGET_TIOCPKT		0x5420 +#define TARGET_FIONBIO		0x5421 +#define TARGET_TIOCNOTTY	0x5422 +#define TARGET_TIOCSETD	0x5423 +#define TARGET_TIOCGETD	0x5424 +#define TARGET_TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */ +#define TARGET_TIOCSBRK	0x5427  /* BSD compatibility */ +#define TARGET_TIOCCBRK	0x5428  /* BSD compatibility */ +#define TARGET_TIOCGSID	0x5429  /* Return the session ID of FD */ +#define TARGET_TCGETS2		_IOR('T',0x2A, struct termios2) +#define TARGET_TCSETS2		_IOW('T',0x2B, struct termios2) +#define TARGET_TCSETSW2	_IOW('T',0x2C, struct termios2) +#define TARGET_TCSETSF2	_IOW('T',0x2D, struct termios2) +#define TARGET_TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define TARGET_TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */ +#define TARGET_TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get real dev no below /dev/console */ + +#define TARGET_FIONCLEX	0x5450  /* these numbers need to be adjusted. */ +#define TARGET_FIOCLEX		0x5451 +#define TARGET_FIOASYNC	0x5452 +#define TARGET_TIOCSERCONFIG	0x5453 +#define TARGET_TIOCSERGWILD	0x5454 +#define TARGET_TIOCSERSWILD	0x5455 +#define TARGET_TIOCGLCKTRMIOS	0x5456 +#define TARGET_TIOCSLCKTRMIOS	0x5457 +#define TARGET_TIOCSERGSTRUCT	0x5458 /* For debugging only */ +#define TARGET_TIOCSERGETLSR   0x5459 /* Get line status register */ +#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config  */ +#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TARGET_TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */ +#define TARGET_TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */ +#define TARGET_FIOQSIZE	0x545E + +/* Used for packet mode */ +#define TARGET_TIOCPKT_DATA		 0 +#define TARGET_TIOCPKT_FLUSHREAD	 1 +#define TARGET_TIOCPKT_FLUSHWRITE	 2 +#define TARGET_TIOCPKT_STOP		 4 +#define TARGET_TIOCPKT_START		 8 +#define TARGET_TIOCPKT_NOSTOP		16 +#define TARGET_TIOCPKT_DOSTOP		32 + +#define TARGET_TIOCSER_TEMT    0x01	/* Transmitter physically empty */ + diff --git a/linux-user/sh4/syscall.h b/linux-user/sh4/syscall.h new file mode 100644 index 00000000..7aa4f239 --- /dev/null +++ b/linux-user/sh4/syscall.h @@ -0,0 +1,17 @@ +struct target_pt_regs { +        unsigned long regs[16]; +        unsigned long pc; +        unsigned long pr; +        unsigned long sr; +        unsigned long gbr; +        unsigned long mach; +        unsigned long macl; +        long tra; +}; + +#define UNAME_MACHINE "sh4" +#define UNAME_MINIMUM_RELEASE "2.6.32" + +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_MLOCKALL_MCL_CURRENT 1 +#define TARGET_MLOCKALL_MCL_FUTURE  2 diff --git a/linux-user/sh4/syscall_nr.h b/linux-user/sh4/syscall_nr.h new file mode 100644 index 00000000..bdf8742c --- /dev/null +++ b/linux-user/sh4/syscall_nr.h @@ -0,0 +1,374 @@ +/* + * This file contains the system call numbers. + */ + +#define TARGET_NR_restart_syscall	  0 +#define TARGET_NR_exit		  1 +#define TARGET_NR_fork		  2 +#define TARGET_NR_read		  3 +#define TARGET_NR_write		  4 +#define TARGET_NR_open		  5 +#define TARGET_NR_close		  6 +#define TARGET_NR_waitpid		  7 +#define TARGET_NR_creat		  8 +#define TARGET_NR_link		  9 +#define TARGET_NR_unlink		 10 +#define TARGET_NR_execve		 11 +#define TARGET_NR_chdir		 12 +#define TARGET_NR_time		 13 +#define TARGET_NR_mknod		 14 +#define TARGET_NR_chmod		 15 +#define TARGET_NR_lchown		 16 +#define TARGET_NR_break		 17 +#define TARGET_NR_oldstat		 18 +#define TARGET_NR_lseek		 19 +#define TARGET_NR_getpid		 20 +#define TARGET_NR_mount		 21 +#define TARGET_NR_umount		 22 +#define TARGET_NR_setuid		 23 +#define TARGET_NR_getuid		 24 +#define TARGET_NR_stime		 25 +#define TARGET_NR_ptrace		 26 +#define TARGET_NR_alarm		 27 +#define TARGET_NR_oldfstat		 28 +#define TARGET_NR_pause		 29 +#define TARGET_NR_utime		 30 +#define TARGET_NR_stty		 31 +#define TARGET_NR_gtty		 32 +#define TARGET_NR_access		 33 +#define TARGET_NR_nice		 34 +#define TARGET_NR_ftime		 35 +#define TARGET_NR_sync		 36 +#define TARGET_NR_kill		 37 +#define TARGET_NR_rename		 38 +#define TARGET_NR_mkdir		 39 +#define TARGET_NR_rmdir		 40 +#define TARGET_NR_dup		 41 +#define TARGET_NR_pipe		 42 +#define TARGET_NR_times		 43 +#define TARGET_NR_prof		 44 +#define TARGET_NR_brk		 45 +#define TARGET_NR_setgid		 46 +#define TARGET_NR_getgid		 47 +#define TARGET_NR_signal		 48 +#define TARGET_NR_geteuid		 49 +#define TARGET_NR_getegid		 50 +#define TARGET_NR_acct		 51 +#define TARGET_NR_umount2		 52 +#define TARGET_NR_lock		 53 +#define TARGET_NR_ioctl		 54 +#define TARGET_NR_fcntl		 55 +#define TARGET_NR_mpx		 56 +#define TARGET_NR_setpgid		 57 +#define TARGET_NR_ulimit		 58 +#define TARGET_NR_oldolduname	 59 +#define TARGET_NR_umask		 60 +#define TARGET_NR_chroot		 61 +#define TARGET_NR_ustat		 62 +#define TARGET_NR_dup2		 63 +#define TARGET_NR_getppid		 64 +#define TARGET_NR_getpgrp		 65 +#define TARGET_NR_setsid		 66 +#define TARGET_NR_sigaction		 67 +#define TARGET_NR_sgetmask		 68 +#define TARGET_NR_ssetmask		 69 +#define TARGET_NR_setreuid		 70 +#define TARGET_NR_setregid		 71 +#define TARGET_NR_sigsuspend		 72 +#define TARGET_NR_sigpending		 73 +#define TARGET_NR_sethostname	 74 +#define TARGET_NR_setrlimit		 75 +#define TARGET_NR_getrlimit	 	 76	/* Back compatible 2Gig limited rlimit */ +#define TARGET_NR_getrusage		 77 +#define TARGET_NR_gettimeofday	 78 +#define TARGET_NR_settimeofday	 79 +#define TARGET_NR_getgroups		 80 +#define TARGET_NR_setgroups		 81 +#define TARGET_NR_select		 82 +#define TARGET_NR_symlink		 83 +#define TARGET_NR_oldlstat		 84 +#define TARGET_NR_readlink		 85 +#define TARGET_NR_uselib		 86 +#define TARGET_NR_swapon		 87 +#define TARGET_NR_reboot		 88 +#define TARGET_NR_readdir		 89 +#define TARGET_NR_mmap		 90 +#define TARGET_NR_munmap		 91 +#define TARGET_NR_truncate		 92 +#define TARGET_NR_ftruncate		 93 +#define TARGET_NR_fchmod		 94 +#define TARGET_NR_fchown		 95 +#define TARGET_NR_getpriority	 96 +#define TARGET_NR_setpriority	 97 +#define TARGET_NR_profil		 98 +#define TARGET_NR_statfs		 99 +#define TARGET_NR_fstatfs		100 +#define TARGET_NR_ioperm		101 +#define TARGET_NR_socketcall		102 +#define TARGET_NR_syslog		103 +#define TARGET_NR_setitimer		104 +#define TARGET_NR_getitimer		105 +#define TARGET_NR_stat		106 +#define TARGET_NR_lstat		107 +#define TARGET_NR_fstat		108 +#define TARGET_NR_olduname		109 +#define TARGET_NR_iopl		110 +#define TARGET_NR_vhangup		111 +#define TARGET_NR_idle		112 +#define TARGET_NR_vm86old		113 +#define TARGET_NR_wait4		114 +#define TARGET_NR_swapoff		115 +#define TARGET_NR_sysinfo		116 +#define TARGET_NR_ipc		117 +#define TARGET_NR_fsync		118 +#define TARGET_NR_sigreturn		119 +#define TARGET_NR_clone		120 +#define TARGET_NR_setdomainname	121 +#define TARGET_NR_uname		122 +#define TARGET_NR_cacheflush		123 +#define TARGET_NR_adjtimex		124 +#define TARGET_NR_mprotect		125 +#define TARGET_NR_sigprocmask	126 +#define TARGET_NR_create_module	127 +#define TARGET_NR_init_module	128 +#define TARGET_NR_delete_module	129 +#define TARGET_NR_get_kernel_syms	130 +#define TARGET_NR_quotactl		131 +#define TARGET_NR_getpgid		132 +#define TARGET_NR_fchdir		133 +#define TARGET_NR_bdflush		134 +#define TARGET_NR_sysfs		135 +#define TARGET_NR_personality	136 +#define TARGET_NR_afs_syscall	137 /* Syscall for Andrew File System */ +#define TARGET_NR_setfsuid		138 +#define TARGET_NR_setfsgid		139 +#define TARGET_NR__llseek		140 +#define TARGET_NR_getdents		141 +#define TARGET_NR__newselect		142 +#define TARGET_NR_flock		143 +#define TARGET_NR_msync		144 +#define TARGET_NR_readv		145 +#define TARGET_NR_writev		146 +#define TARGET_NR_getsid		147 +#define TARGET_NR_fdatasync		148 +#define TARGET_NR__sysctl		149 +#define TARGET_NR_mlock		150 +#define TARGET_NR_munlock		151 +#define TARGET_NR_mlockall		152 +#define TARGET_NR_munlockall		153 +#define TARGET_NR_sched_setparam		154 +#define TARGET_NR_sched_getparam		155 +#define TARGET_NR_sched_setscheduler		156 +#define TARGET_NR_sched_getscheduler		157 +#define TARGET_NR_sched_yield		158 +#define TARGET_NR_sched_get_priority_max	159 +#define TARGET_NR_sched_get_priority_min	160 +#define TARGET_NR_sched_rr_get_interval	161 +#define TARGET_NR_nanosleep		162 +#define TARGET_NR_mremap		163 +#define TARGET_NR_setresuid		164 +#define TARGET_NR_getresuid		165 +#define TARGET_NR_vm86		166 +#define TARGET_NR_query_module	167 +#define TARGET_NR_poll		168 +#define TARGET_NR_nfsservctl		169 +#define TARGET_NR_setresgid		170 +#define TARGET_NR_getresgid		171 +#define TARGET_NR_prctl              172 +#define TARGET_NR_rt_sigreturn	173 +#define TARGET_NR_rt_sigaction	174 +#define TARGET_NR_rt_sigprocmask	175 +#define TARGET_NR_rt_sigpending	176 +#define TARGET_NR_rt_sigtimedwait	177 +#define TARGET_NR_rt_sigqueueinfo	178 +#define TARGET_NR_rt_sigsuspend	179 +#define TARGET_NR_pread64		180 +#define TARGET_NR_pwrite64		181 +#define TARGET_NR_chown		182 +#define TARGET_NR_getcwd		183 +#define TARGET_NR_capget		184 +#define TARGET_NR_capset		185 +#define TARGET_NR_sigaltstack	186 +#define TARGET_NR_sendfile		187 +#define TARGET_NR_streams1		188	/* some people actually want it */ +#define TARGET_NR_streams2		189	/* some people actually want it */ +#define TARGET_NR_vfork		190 +#define TARGET_NR_ugetrlimit		191	/* SuS compliant getrlimit */ +#define TARGET_NR_mmap2		192 +#define TARGET_NR_truncate64		193 +#define TARGET_NR_ftruncate64	194 +#define TARGET_NR_stat64		195 +#define TARGET_NR_lstat64		196 +#define TARGET_NR_fstat64		197 +#define TARGET_NR_lchown32		198 +#define TARGET_NR_getuid32		199 +#define TARGET_NR_getgid32		200 +#define TARGET_NR_geteuid32		201 +#define TARGET_NR_getegid32		202 +#define TARGET_NR_setreuid32		203 +#define TARGET_NR_setregid32		204 +#define TARGET_NR_getgroups32	205 +#define TARGET_NR_setgroups32	206 +#define TARGET_NR_fchown32		207 +#define TARGET_NR_setresuid32	208 +#define TARGET_NR_getresuid32	209 +#define TARGET_NR_setresgid32	210 +#define TARGET_NR_getresgid32	211 +#define TARGET_NR_chown32		212 +#define TARGET_NR_setuid32		213 +#define TARGET_NR_setgid32		214 +#define TARGET_NR_setfsuid32		215 +#define TARGET_NR_setfsgid32		216 +#define TARGET_NR_pivot_root		217 +#define TARGET_NR_mincore		218 +#define TARGET_NR_madvise		219 +#define TARGET_NR_getdents64		220 +#define TARGET_NR_fcntl64		221 +/* 223 is unused */ +#define TARGET_NR_gettid		224 +#define TARGET_NR_readahead		225 +#define TARGET_NR_setxattr		226 +#define TARGET_NR_lsetxattr		227 +#define TARGET_NR_fsetxattr		228 +#define TARGET_NR_getxattr		229 +#define TARGET_NR_lgetxattr		230 +#define TARGET_NR_fgetxattr		231 +#define TARGET_NR_listxattr		232 +#define TARGET_NR_llistxattr		233 +#define TARGET_NR_flistxattr		234 +#define TARGET_NR_removexattr	235 +#define TARGET_NR_lremovexattr	236 +#define TARGET_NR_fremovexattr	237 +#define TARGET_NR_tkill		238 +#define TARGET_NR_sendfile64		239 +#define TARGET_NR_futex		240 +#define TARGET_NR_sched_setaffinity	241 +#define TARGET_NR_sched_getaffinity	242 +#define TARGET_NR_set_thread_area	243 +#define TARGET_NR_get_thread_area	244 +#define TARGET_NR_io_setup		245 +#define TARGET_NR_io_destroy		246 +#define TARGET_NR_io_getevents	247 +#define TARGET_NR_io_submit		248 +#define TARGET_NR_io_cancel		249 +#define TARGET_NR_fadvise64		250 + +#define TARGET_NR_exit_group		252 +#define TARGET_NR_lookup_dcookie	253 +#define TARGET_NR_epoll_create	254 +#define TARGET_NR_epoll_ctl		255 +#define TARGET_NR_epoll_wait		256 +#define TARGET_NR_remap_file_pages	257 +#define TARGET_NR_set_tid_address	258 +#define TARGET_NR_timer_create	259 +#define TARGET_NR_timer_settime	(TARGET_NR_timer_create+1) +#define TARGET_NR_timer_gettime	(TARGET_NR_timer_create+2) +#define TARGET_NR_timer_getoverrun	(TARGET_NR_timer_create+3) +#define TARGET_NR_timer_delete	(TARGET_NR_timer_create+4) +#define TARGET_NR_clock_settime	(TARGET_NR_timer_create+5) +#define TARGET_NR_clock_gettime	(TARGET_NR_timer_create+6) +#define TARGET_NR_clock_getres	(TARGET_NR_timer_create+7) +#define TARGET_NR_clock_nanosleep	(TARGET_NR_timer_create+8) +#define TARGET_NR_statfs64		268 +#define TARGET_NR_fstatfs64		269 +#define TARGET_NR_tgkill		270 +#define TARGET_NR_utimes		271 +#define TARGET_NR_fadvise64_64	272 +#define TARGET_NR_vserver		273 +#define TARGET_NR_mbind              274 +#define TARGET_NR_get_mempolicy      275 +#define TARGET_NR_set_mempolicy      276 +#define TARGET_NR_mq_open            277 +#define TARGET_NR_mq_unlink          (TARGET_NR_mq_open+1) +#define TARGET_NR_mq_timedsend       (TARGET_NR_mq_open+2) +#define TARGET_NR_mq_timedreceive    (TARGET_NR_mq_open+3) +#define TARGET_NR_mq_notify          (TARGET_NR_mq_open+4) +#define TARGET_NR_mq_getsetattr      (TARGET_NR_mq_open+5) +#define TARGET_NR_sys_kexec_load	283 +#define TARGET_NR_waitid		284 +#define TARGET_NR_add_key		285 +#define TARGET_NR_request_key	286 +#define TARGET_NR_keyctl		287 +#define TARGET_NR_ioprio_set		288 +#define TARGET_NR_ioprio_get		289 +#define TARGET_NR_inotify_init	290 +#define TARGET_NR_inotify_add_watch	291 +#define TARGET_NR_inotify_rm_watch	292 +/* 293 is unused */ +#define TARGET_NR_migrate_pages	294 +#define TARGET_NR_openat		295 +#define TARGET_NR_mkdirat		296 +#define TARGET_NR_mknodat		297 +#define TARGET_NR_fchownat		298 +#define TARGET_NR_futimesat		299 +#define TARGET_NR_fstatat64		300 +#define TARGET_NR_unlinkat		301 +#define TARGET_NR_renameat		302 +#define TARGET_NR_linkat		303 +#define TARGET_NR_symlinkat		304 +#define TARGET_NR_readlinkat		305 +#define TARGET_NR_fchmodat		306 +#define TARGET_NR_faccessat		307 +#define TARGET_NR_pselect6		308 +#define TARGET_NR_ppoll		309 +#define TARGET_NR_unshare		310 +#define TARGET_NR_set_robust_list	311 +#define TARGET_NR_get_robust_list	312 +#define TARGET_NR_splice		313 +#define TARGET_NR_sync_file_range	314 +#define TARGET_NR_tee		315 +#define TARGET_NR_vmsplice		316 +#define TARGET_NR_move_pages		317 +#define TARGET_NR_getcpu		318 +#define TARGET_NR_epoll_pwait	319 +#define TARGET_NR_utimensat		320 +#define TARGET_NR_signalfd		321 +#define TARGET_NR_timerfd		322 +#define TARGET_NR_eventfd		323 +#define TARGET_NR_fallocate		324 +#define TARGET_NR_timerfd_settime	325 +#define TARGET_NR_timerfd_gettime	326 +#define TARGET_NR_signalfd4		327 +#define TARGET_NR_eventfd2		328 +#define TARGET_NR_epoll_create1	329 +#define TARGET_NR_dup3			330 +#define TARGET_NR_pipe2		331 +#define TARGET_NR_inotify_init1	332 +#define TARGET_NR_preadv                333 +#define TARGET_NR_pwritev               334 +#define TARGET_NR_rt_tgsigqueueinfo     335 +#define TARGET_NR_perf_event_open       336 +#define TARGET_NR_fanotify_init         337 +#define TARGET_NR_fanotify_mark         338 +#define TARGET_NR_prlimit64             339 + +/* Non-multiplexed socket family */ +#define TARGET_NR_socket                340 +#define TARGET_NR_bind                  341 +#define TARGET_NR_connect               342 +#define TARGET_NR_listen                343 +#define TARGET_NR_accept                344 +#define TARGET_NR_getsockname           345 +#define TARGET_NR_getpeername           346 +#define TARGET_NR_socketpair            347 +#define TARGET_NR_send                  348 +#define TARGET_NR_sendto                349 +#define TARGET_NR_recv                  350 +#define TARGET_NR_recvfrom              351 +#define TARGET_NR_shutdown              352 +#define TARGET_NR_setsockopt            353 +#define TARGET_NR_getsockopt            354 +#define TARGET_NR_sendmsg               355 +#define TARGET_NR_recvmsg               356 +#define TARGET_NR_recvmmsg              357 +#define TARGET_NR_accept4               358 +#define TARGET_NR_name_to_handle_at     359 +#define TARGET_NR_open_by_handle_at     360 +#define TARGET_NR_clock_adjtime         361 +#define TARGET_NR_syncfs                362 +#define TARGET_NR_sendmmsg              363 +#define TARGET_NR_setns                 364 +#define TARGET_NR_process_vm_readv      365 +#define TARGET_NR_process_vm_writev     366 +#define TARGET_NR_kcmp                  367 +#define TARGET_NR_finit_module          368 diff --git a/linux-user/sh4/target_cpu.h b/linux-user/sh4/target_cpu.h new file mode 100644 index 00000000..141856f8 --- /dev/null +++ b/linux-user/sh4/target_cpu.h @@ -0,0 +1,35 @@ +/* + * SH4 specific CPU ABI and functions for linux-user + * + * Copyright (c) 2005 Samuel Tardieu + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUSH4State *env, target_ulong newsp) +{ +    if (newsp) { +        env->gregs[15] = newsp; +    } +    env->gregs[0] = 0; +} + +static inline void cpu_set_tls(CPUSH4State *env, target_ulong newtls) +{ +  env->gbr = newtls; +} + +#endif diff --git a/linux-user/sh4/target_signal.h b/linux-user/sh4/target_signal.h new file mode 100644 index 00000000..e148da09 --- /dev/null +++ b/linux-user/sh4/target_signal.h @@ -0,0 +1,29 @@ +#ifndef TARGET_SIGNAL_H +#define TARGET_SIGNAL_H + +#include "cpu.h" + +/* this struct defines a stack used during syscall handling */ + +typedef struct target_sigaltstack { +	abi_ulong ss_sp; +	abi_long ss_flags; +	abi_ulong ss_size; +} target_stack_t; + + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK     1 +#define TARGET_SS_DISABLE     2 + +#define TARGET_MINSIGSTKSZ    2048 +#define TARGET_SIGSTKSZ       8192 + +static inline abi_ulong get_sp_from_cpustate(CPUSH4State *state) +{ +    return state->gregs[15]; +} + +#endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/sh4/target_structs.h b/linux-user/sh4/target_structs.h new file mode 100644 index 00000000..32b235e0 --- /dev/null +++ b/linux-user/sh4/target_structs.h @@ -0,0 +1,58 @@ +/* + * SH4 specific structures for linux-user + * + * Copyright (c) 2013 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_STRUCTS_H +#define TARGET_STRUCTS_H + +struct target_ipc_perm { +    abi_int __key;                      /* Key.  */ +    abi_uint uid;                       /* Owner's user ID.  */ +    abi_uint gid;                       /* Owner's group ID.  */ +    abi_uint cuid;                      /* Creator's user ID.  */ +    abi_uint cgid;                      /* Creator's group ID.  */ +    abi_ushort mode;                    /* Read/write permission.  */ +    abi_ushort __pad1; +    abi_ushort __seq;                   /* Sequence number.  */ +    abi_ushort __pad2; +    abi_ulong __unused1; +    abi_ulong __unused2; +}; + +struct target_shmid_ds { +    struct target_ipc_perm shm_perm;    /* operation permission struct */ +    abi_long shm_segsz;                 /* size of segment in bytes */ +    abi_ulong shm_atime;                /* time of last shmat() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused1; +#endif +    abi_ulong shm_dtime;                /* time of last shmdt() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused2; +#endif +    abi_ulong shm_ctime;                /* time of last change by shmctl() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused3; +#endif +    abi_int shm_cpid;                   /* pid of creator */ +    abi_int shm_lpid;                   /* pid of last shmop */ +    abi_ulong shm_nattch;               /* number of current attaches */ +    abi_ulong __unused4; +    abi_ulong __unused5; +}; + +#endif diff --git a/linux-user/sh4/termbits.h b/linux-user/sh4/termbits.h new file mode 100644 index 00000000..2ff774f6 --- /dev/null +++ b/linux-user/sh4/termbits.h @@ -0,0 +1,274 @@ +/* from asm/termbits.h */ + +#define TARGET_NCCS 19 + +struct target_termios { +	unsigned int c_iflag;			/* input mode flags */ +	unsigned int c_oflag;			/* output mode flags */ +	unsigned int c_cflag;			/* control mode flags */ +	unsigned int c_lflag;			/* local mode flags */ +	unsigned char c_line;			/* line discipline */ +	unsigned char c_cc[TARGET_NCCS];	/* control characters */ +}; + +/* c_cc characters */ +#define TARGET_VINTR 0 +#define TARGET_VQUIT 1 +#define TARGET_VERASE 2 +#define TARGET_VKILL 3 +#define TARGET_VEOF 4 +#define TARGET_VTIME 5 +#define TARGET_VMIN 6 +#define TARGET_VSWTC 7 +#define TARGET_VSTART 8 +#define TARGET_VSTOP 9 +#define TARGET_VSUSP 10 +#define TARGET_VEOL 11 +#define TARGET_VREPRINT 12 +#define TARGET_VDISCARD 13 +#define TARGET_VWERASE 14 +#define TARGET_VLNEXT 15 +#define TARGET_VEOL2 16 + +/* c_iflag bits */ +#define TARGET_IGNBRK	0000001 +#define TARGET_BRKINT	0000002 +#define TARGET_IGNPAR	0000004 +#define TARGET_PARMRK	0000010 +#define TARGET_INPCK	0000020 +#define TARGET_ISTRIP	0000040 +#define TARGET_INLCR	0000100 +#define TARGET_IGNCR	0000200 +#define TARGET_ICRNL	0000400 +#define TARGET_IUCLC	0001000 +#define TARGET_IXON	0002000 +#define TARGET_IXANY	0004000 +#define TARGET_IXOFF	0010000 +#define TARGET_IMAXBEL	0020000 +#define TARGET_IUTF8	0040000 + +/* c_oflag bits */ +#define TARGET_OPOST	0000001 +#define TARGET_OLCUC	0000002 +#define TARGET_ONLCR	0000004 +#define TARGET_OCRNL	0000010 +#define TARGET_ONOCR	0000020 +#define TARGET_ONLRET	0000040 +#define TARGET_OFILL	0000100 +#define TARGET_OFDEL	0000200 +#define TARGET_NLDLY	0000400 +#define TARGET_NL0	0000000 +#define TARGET_NL1	0000400 +#define TARGET_CRDLY	0003000 +#define TARGET_CR0	0000000 +#define TARGET_CR1	0001000 +#define TARGET_CR2	0002000 +#define TARGET_CR3	0003000 +#define TARGET_TABDLY	0014000 +#define TARGET_TAB0	0000000 +#define TARGET_TAB1	0004000 +#define TARGET_TAB2	0010000 +#define TARGET_TAB3	0014000 +#define TARGET_XTABS	0014000 +#define TARGET_BSDLY	0020000 +#define TARGET_BS0	0000000 +#define TARGET_BS1	0020000 +#define TARGET_VTDLY	0040000 +#define TARGET_VT0	0000000 +#define TARGET_VT1	0040000 +#define TARGET_FFDLY	0100000 +#define TARGET_FF0	0000000 +#define TARGET_FF1	0100000 + +/* c_cflag bit meaning */ +#define TARGET_CBAUD	0010017 +#define TARGET_B0	0000000		/* hang up */ +#define TARGET_B50	0000001 +#define TARGET_B75	0000002 +#define TARGET_B110	0000003 +#define TARGET_B134	0000004 +#define TARGET_B150	0000005 +#define TARGET_B200	0000006 +#define TARGET_B300	0000007 +#define TARGET_B600	0000010 +#define TARGET_B1200	0000011 +#define TARGET_B1800	0000012 +#define TARGET_B2400	0000013 +#define TARGET_B4800	0000014 +#define TARGET_B9600	0000015 +#define TARGET_B19200	0000016 +#define TARGET_B38400	0000017 +#define TARGET_EXTA B19200 +#define TARGET_EXTB B38400 +#define TARGET_CSIZE	0000060 +#define TARGET_CS5	0000000 +#define TARGET_CS6	0000020 +#define TARGET_CS7	0000040 +#define TARGET_CS8	0000060 +#define TARGET_CSTOPB	0000100 +#define TARGET_CREAD	0000200 +#define TARGET_PARENB	0000400 +#define TARGET_PARODD	0001000 +#define TARGET_HUPCL	0002000 +#define TARGET_CLOCAL	0004000 +#define TARGET_CBAUDEX 0010000 +#define TARGET_B57600 0010001 +#define TARGET_B115200 0010002 +#define TARGET_B230400 0010003 +#define TARGET_B460800 0010004 +#define TARGET_B500000 0010005 +#define TARGET_B576000 0010006 +#define TARGET_B921600 0010007 +#define TARGET_B1000000 0010010 +#define TARGET_B1152000 0010011 +#define TARGET_B1500000 0010012 +#define TARGET_B2000000 0010013 +#define TARGET_B2500000 0010014 +#define TARGET_B3000000 0010015 +#define TARGET_B3500000 0010016 +#define TARGET_B4000000 0010017 +#define TARGET_CIBAUD	  002003600000	/* input baud rate (not used) */ +#define TARGET_CMSPAR	  010000000000		/* mark or space (stick) parity */ +#define TARGET_CRTSCTS	  020000000000		/* flow control */ + +/* c_lflag bits */ +#define TARGET_ISIG	0000001 +#define TARGET_ICANON	0000002 +#define TARGET_XCASE	0000004 +#define TARGET_ECHO	0000010 +#define TARGET_ECHOE	0000020 +#define TARGET_ECHOK	0000040 +#define TARGET_ECHONL	0000100 +#define TARGET_NOFLSH	0000200 +#define TARGET_TOSTOP	0000400 +#define TARGET_ECHOCTL	0001000 +#define TARGET_ECHOPRT	0002000 +#define TARGET_ECHOKE	0004000 +#define TARGET_FLUSHO	0010000 +#define TARGET_PENDIN	0040000 +#define TARGET_IEXTEN	0100000 + +/* tcflow() and TCXONC use these */ +#define TARGET_TCOOFF		0 +#define TARGET_TCOON		1 +#define TARGET_TCIOFF		2 +#define TARGET_TCION		3 + +/* tcflush() and TCFLSH use these */ +#define TARGET_TCIFLUSH	0 +#define TARGET_TCOFLUSH	1 +#define TARGET_TCIOFLUSH	2 + +/* tcsetattr uses these */ +#define TARGET_TCSANOW		0 +#define TARGET_TCSADRAIN	1 +#define TARGET_TARGET_TCSAFLUSH	2 + +/* ioctl */ +#define TARGET_FIOCLEX         TARGET_IO('f', 1) +#define TARGET_FIONCLEX        TARGET_IO('f', 2) +#define TARGET_FIOASYNC        TARGET_IOW('f', 125, int) +#define TARGET_FIONBIO         TARGET_IOW('f', 126, int) +#define TARGET_FIONREAD        TARGET_IOR('f', 127, int) +#define TARGET_TIOCINQ         TARGET_FIONREAD +#define TARGET_FIOQSIZE        TARGET_IOR('f', 128, loff_t) +#define TARGET_TCGETS          0x5401 +#define TARGET_TCSETS          0x5402 +#define TARGET_TCSETSW         0x5403 +#define TARGET_TCSETSF         0x5404 +#define TARGET_TCGETA          TARGET_IOR('t', 23, struct termio) +#define TARGET_TIOCSWINSZ      TARGET_IOW('t', 103, struct winsize) +#define TARGET_TIOCGWINSZ      TARGET_IOR('t', 104, struct winsize) +#define TARGET_TIOCSTART       TARGET_IO('t', 110)           /* start output, like ^Q */ +#define TARGET_TIOCSTOP        TARGET_IO('t', 111)           /* stop output, like ^S */ +#define TARGET_TIOCOUTQ        TARGET_IOR('t', 115, int)     /* output queue size */ + +#define TARGET_TIOCSPGRP       TARGET_IOW('t', 118, int) +#define TARGET_TIOCGPGRP       TARGET_IOR('t', 119, int) + +#define TARGET_TCSETA          TARGET_IOW('t', 24, struct termio) +#define TARGET_TCSETAW         TARGET_IOW('t', 25, struct termio) +#define TARGET_TCSETAF         TARGET_IOW('t', 28, struct termio) +#define TARGET_TCSBRK          TARGET_IO('t', 29) +#define TARGET_TCXONC          TARGET_IO('t', 30) +#define TARGET_TCFLSH          TARGET_IO('t', 31) + +#define TARGET_TIOCSWINSZ      TARGET_IOW('t', 103, struct winsize) +#define TARGET_TIOCGWINSZ      TARGET_IOR('t', 104, struct winsize) +#define TARGET_TIOCSTART       TARGET_IO('t', 110)           /* start output, like ^Q */ +#define TARGET_TIOCSTOP        TARGET_IO('t', 111)           /* stop output, like ^S */ +#define TARGET_TIOCOUTQ        TARGET_IOR('t', 115, int)     /* output queue size */ + +#define TARGET_TIOCSPGRP       TARGET_IOW('t', 118, int) +#define TARGET_TIOCGPGRP       TARGET_IOR('t', 119, int) +#define TARGET_TIOCEXCL        TARGET_IO('T', 12) /* 0x540C */ +#define TARGET_TIOCNXCL        TARGET_IO('T', 13) /* 0x540D */ +#define TARGET_TIOCSCTTY       TARGET_IO('T', 14) /* 0x540E */ + +#define TARGET_TIOCSTI         TARGET_IOW('T', 18, char) /* 0x5412 */ +#define TARGET_TIOCMGET        TARGET_IOR('T', 21, unsigned int) /* 0x5415 */ +#define TARGET_TIOCMBIS        TARGET_IOW('T', 22, unsigned int) /* 0x5416 */ +#define TARGET_TIOCMBIC        TARGET_IOW('T', 23, unsigned int) /* 0x5417 */ +#define TARGET_TIOCMSET        TARGET_IOW('T', 24, unsigned int) /* 0x5418 */ +#define TARGET_TIOCM_LE       0x001 +#define TARGET_TIOCM_DTR      0x002 +#define TARGET_TIOCM_RTS      0x004 +#define TARGET_TIOCM_ST       0x008 +#define TARGET_TIOCM_SR       0x010 +#define TARGET_TIOCM_CTS      0x020 +#define TARGET_TIOCM_CAR      0x040 +#define TARGET_TIOCM_RNG      0x080 +#define TARGET_TIOCM_DSR      0x100 +#define TARGET_TIOCM_CD       TARGET_TIOCM_CAR +#define TARGET_TIOCM_RI       TARGET_TIOCM_RNG + +#define TARGET_TIOCGSOFTCAR    TARGET_IOR('T', 25, unsigned int) /* 0x5419 */ +#define TARGET_TIOCSSOFTCAR    TARGET_IOW('T', 26, unsigned int) /* 0x541A */ +#define TARGET_TIOCLINUX       TARGET_IOW('T', 28, char) /* 0x541C */ +#define TARGET_TIOCCONS        TARGET_IO('T', 29) /* 0x541D */ +#define TARGET_TIOCGSERIAL     TARGET_IOR('T', 30, int) /* 0x541E */ +#define TARGET_TIOCSSERIAL     TARGET_IOW('T', 31, int) /* 0x541F */ +#define TARGET_TIOCPKT         TARGET_IOW('T', 32, int) /* 0x5420 */ +#define TARGET_TIOCPKT_DATA            0 +#define TARGET_TIOCPKT_FLUSHREAD       1 +#define TARGET_TIOCPKT_FLUSHWRITE      2 +#define TARGET_TIOCPKT_STOP            4 +#define TARGET_TIOCPKT_START           8 +#define TARGET_TIOCPKT_NOSTOP         16 +#define TARGET_TIOCPKT_DOSTOP         32 + + +#define TARGET_TIOCNOTTY       TARGET_IO('T', 34) /* 0x5422 */ +#define TARGET_TIOCSETD        TARGET_IOW('T', 35, int) /* 0x5423 */ +#define TARGET_TIOCGETD        TARGET_IOR('T', 36, int) /* 0x5424 */ +#define TARGET_TCSBRKP         TARGET_IOW('T', 37, int) /* 0x5425 */ /* Needed for POSIX tcse +ndbreak() */ +#define TARGET_TIOCSBRK        TARGET_IO('T', 39) /* 0x5427 */ /* BSD compatibility */ +#define TARGET_TIOCCBRK        TARGET_IO('T', 40) /* 0x5428 */ /* BSD compatibility */ +#define TARGET_TIOCGSID        TARGET_IOR('T', 41, pid_t) /* 0x5429 */ /* Return the session +ID of FD */ +#define TARGET_TIOCGPTN        TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-m +ux device) */ +#define TARGET_TIOCSPTLCK      TARGET_IOW('T',0x31, int)  /* Lock/unlock Pty */ + + +#define TARGET_TIOCSERCONFIG   TARGET_IO('T', 83) /* 0x5453 */ +#define TARGET_TIOCSERGWILD    TARGET_IOR('T', 84,  int) /* 0x5454 */ +#define TARGET_TIOCSERSWILD    TARGET_IOW('T', 85,  int) /* 0x5455 */ +#define TARGET_TIOCGLCKTRMIOS  0x5456 +#define TARGET_TIOCSLCKTRMIOS  0x5457 +#define TARGET_TIOCSERGSTRUCT  TARGET_IOR('T', 88, int) /* 0x5458 */ /* For d +ebugging only */ +#define TARGET_TIOCSERGETLSR   TARGET_IOR('T', 89, unsigned int) /* 0x5459 */ /* Get line sta +tus register */ +  /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ +# define TIOCSER_TEMT    0x01   /* Transmitter physically empty */ +#define TARGET_TIOCSERGETMULTI TARGET_IOR('T', 90, int) /* 0x545A +*/ /* Get multiport config  */ +#define TARGET_TIOCSERSETMULTI TARGET_IOW('T', 91, int) /* 0x545B +*/ /* Set multiport config */ + +#define TARGET_TIOCMIWAIT      TARGET_IO('T', 92) /* 0x545C */       /* wait for a change on +serial input line(s) */ +#define TARGET_TIOCGICOUNT     TARGET_IOR('T', 93, int) /* 0x545D */ /* read +serial port inline interrupt counts */ diff --git a/linux-user/signal.c b/linux-user/signal.c new file mode 100644 index 00000000..9d4cef40 --- /dev/null +++ b/linux-user/signal.c @@ -0,0 +1,5680 @@ +/* + *  Emulation of Linux signals + * + *  Copyright (c) 2003 Fabrice Bellard + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, see <http://www.gnu.org/licenses/>. + */ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdarg.h> +#include <unistd.h> +#include <errno.h> +#include <assert.h> +#include <sys/ucontext.h> +#include <sys/resource.h> + +#include "qemu.h" +#include "qemu-common.h" +#include "target_signal.h" + +//#define DEBUG_SIGNAL + +static struct target_sigaltstack target_sigaltstack_used = { +    .ss_sp = 0, +    .ss_size = 0, +    .ss_flags = TARGET_SS_DISABLE, +}; + +static struct target_sigaction sigact_table[TARGET_NSIG]; + +static void host_signal_handler(int host_signum, siginfo_t *info, +                                void *puc); + +static uint8_t host_to_target_signal_table[_NSIG] = { +    [SIGHUP] = TARGET_SIGHUP, +    [SIGINT] = TARGET_SIGINT, +    [SIGQUIT] = TARGET_SIGQUIT, +    [SIGILL] = TARGET_SIGILL, +    [SIGTRAP] = TARGET_SIGTRAP, +    [SIGABRT] = TARGET_SIGABRT, +/*    [SIGIOT] = TARGET_SIGIOT,*/ +    [SIGBUS] = TARGET_SIGBUS, +    [SIGFPE] = TARGET_SIGFPE, +    [SIGKILL] = TARGET_SIGKILL, +    [SIGUSR1] = TARGET_SIGUSR1, +    [SIGSEGV] = TARGET_SIGSEGV, +    [SIGUSR2] = TARGET_SIGUSR2, +    [SIGPIPE] = TARGET_SIGPIPE, +    [SIGALRM] = TARGET_SIGALRM, +    [SIGTERM] = TARGET_SIGTERM, +#ifdef SIGSTKFLT +    [SIGSTKFLT] = TARGET_SIGSTKFLT, +#endif +    [SIGCHLD] = TARGET_SIGCHLD, +    [SIGCONT] = TARGET_SIGCONT, +    [SIGSTOP] = TARGET_SIGSTOP, +    [SIGTSTP] = TARGET_SIGTSTP, +    [SIGTTIN] = TARGET_SIGTTIN, +    [SIGTTOU] = TARGET_SIGTTOU, +    [SIGURG] = TARGET_SIGURG, +    [SIGXCPU] = TARGET_SIGXCPU, +    [SIGXFSZ] = TARGET_SIGXFSZ, +    [SIGVTALRM] = TARGET_SIGVTALRM, +    [SIGPROF] = TARGET_SIGPROF, +    [SIGWINCH] = TARGET_SIGWINCH, +    [SIGIO] = TARGET_SIGIO, +    [SIGPWR] = TARGET_SIGPWR, +    [SIGSYS] = TARGET_SIGSYS, +    /* next signals stay the same */ +    /* Nasty hack: Reverse SIGRTMIN and SIGRTMAX to avoid overlap with +       host libpthread signals.  This assumes no one actually uses SIGRTMAX :-/ +       To fix this properly we need to do manual signal delivery multiplexed +       over a single host signal.  */ +    [__SIGRTMIN] = __SIGRTMAX, +    [__SIGRTMAX] = __SIGRTMIN, +}; +static uint8_t target_to_host_signal_table[_NSIG]; + +static inline int on_sig_stack(unsigned long sp) +{ +    return (sp - target_sigaltstack_used.ss_sp +            < target_sigaltstack_used.ss_size); +} + +static inline int sas_ss_flags(unsigned long sp) +{ +    return (target_sigaltstack_used.ss_size == 0 ? SS_DISABLE +            : on_sig_stack(sp) ? SS_ONSTACK : 0); +} + +int host_to_target_signal(int sig) +{ +    if (sig < 0 || sig >= _NSIG) +        return sig; +    return host_to_target_signal_table[sig]; +} + +int target_to_host_signal(int sig) +{ +    if (sig < 0 || sig >= _NSIG) +        return sig; +    return target_to_host_signal_table[sig]; +} + +static inline void target_sigemptyset(target_sigset_t *set) +{ +    memset(set, 0, sizeof(*set)); +} + +static inline void target_sigaddset(target_sigset_t *set, int signum) +{ +    signum--; +    abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW); +    set->sig[signum / TARGET_NSIG_BPW] |= mask; +} + +static inline int target_sigismember(const target_sigset_t *set, int signum) +{ +    signum--; +    abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW); +    return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0); +} + +static void host_to_target_sigset_internal(target_sigset_t *d, +                                           const sigset_t *s) +{ +    int i; +    target_sigemptyset(d); +    for (i = 1; i <= TARGET_NSIG; i++) { +        if (sigismember(s, i)) { +            target_sigaddset(d, host_to_target_signal(i)); +        } +    } +} + +void host_to_target_sigset(target_sigset_t *d, const sigset_t *s) +{ +    target_sigset_t d1; +    int i; + +    host_to_target_sigset_internal(&d1, s); +    for(i = 0;i < TARGET_NSIG_WORDS; i++) +        d->sig[i] = tswapal(d1.sig[i]); +} + +static void target_to_host_sigset_internal(sigset_t *d, +                                           const target_sigset_t *s) +{ +    int i; +    sigemptyset(d); +    for (i = 1; i <= TARGET_NSIG; i++) { +        if (target_sigismember(s, i)) { +            sigaddset(d, target_to_host_signal(i)); +        } +     } +} + +void target_to_host_sigset(sigset_t *d, const target_sigset_t *s) +{ +    target_sigset_t s1; +    int i; + +    for(i = 0;i < TARGET_NSIG_WORDS; i++) +        s1.sig[i] = tswapal(s->sig[i]); +    target_to_host_sigset_internal(d, &s1); +} + +void host_to_target_old_sigset(abi_ulong *old_sigset, +                               const sigset_t *sigset) +{ +    target_sigset_t d; +    host_to_target_sigset(&d, sigset); +    *old_sigset = d.sig[0]; +} + +void target_to_host_old_sigset(sigset_t *sigset, +                               const abi_ulong *old_sigset) +{ +    target_sigset_t d; +    int i; + +    d.sig[0] = *old_sigset; +    for(i = 1;i < TARGET_NSIG_WORDS; i++) +        d.sig[i] = 0; +    target_to_host_sigset(sigset, &d); +} + +/* Wrapper for sigprocmask function + * Emulates a sigprocmask in a safe way for the guest. Note that set and oldset + * are host signal set, not guest ones. This wraps the sigprocmask host calls + * that should be protected (calls originated from guest) + */ +int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset) +{ +    int ret; +    sigset_t val; +    sigset_t *temp = NULL; +    CPUState *cpu = thread_cpu; +    TaskState *ts = (TaskState *)cpu->opaque; +    bool segv_was_blocked = ts->sigsegv_blocked; + +    if (set) { +        bool has_sigsegv = sigismember(set, SIGSEGV); +        val = *set; +        temp = &val; + +        sigdelset(temp, SIGSEGV); + +        switch (how) { +        case SIG_BLOCK: +            if (has_sigsegv) { +                ts->sigsegv_blocked = true; +            } +            break; +        case SIG_UNBLOCK: +            if (has_sigsegv) { +                ts->sigsegv_blocked = false; +            } +            break; +        case SIG_SETMASK: +            ts->sigsegv_blocked = has_sigsegv; +            break; +        default: +            g_assert_not_reached(); +        } +    } + +    ret = sigprocmask(how, temp, oldset); + +    if (oldset && segv_was_blocked) { +        sigaddset(oldset, SIGSEGV); +    } + +    return ret; +} + +/* siginfo conversion */ + +static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo, +                                                 const siginfo_t *info) +{ +    int sig = host_to_target_signal(info->si_signo); +    tinfo->si_signo = sig; +    tinfo->si_errno = 0; +    tinfo->si_code = info->si_code; + +    if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV +        || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) { +        /* Should never come here, but who knows. The information for +           the target is irrelevant.  */ +        tinfo->_sifields._sigfault._addr = 0; +    } else if (sig == TARGET_SIGIO) { +        tinfo->_sifields._sigpoll._band = info->si_band; +	tinfo->_sifields._sigpoll._fd = info->si_fd; +    } else if (sig == TARGET_SIGCHLD) { +        tinfo->_sifields._sigchld._pid = info->si_pid; +        tinfo->_sifields._sigchld._uid = info->si_uid; +        tinfo->_sifields._sigchld._status +            = host_to_target_waitstatus(info->si_status); +        tinfo->_sifields._sigchld._utime = info->si_utime; +        tinfo->_sifields._sigchld._stime = info->si_stime; +    } else if (sig >= TARGET_SIGRTMIN) { +        tinfo->_sifields._rt._pid = info->si_pid; +        tinfo->_sifields._rt._uid = info->si_uid; +        /* XXX: potential problem if 64 bit */ +        tinfo->_sifields._rt._sigval.sival_ptr +            = (abi_ulong)(unsigned long)info->si_value.sival_ptr; +    } +} + +static void tswap_siginfo(target_siginfo_t *tinfo, +                          const target_siginfo_t *info) +{ +    int sig = info->si_signo; +    tinfo->si_signo = tswap32(sig); +    tinfo->si_errno = tswap32(info->si_errno); +    tinfo->si_code = tswap32(info->si_code); + +    if (sig == TARGET_SIGILL || sig == TARGET_SIGFPE || sig == TARGET_SIGSEGV +        || sig == TARGET_SIGBUS || sig == TARGET_SIGTRAP) { +        tinfo->_sifields._sigfault._addr +            = tswapal(info->_sifields._sigfault._addr); +    } else if (sig == TARGET_SIGIO) { +        tinfo->_sifields._sigpoll._band +            = tswap32(info->_sifields._sigpoll._band); +        tinfo->_sifields._sigpoll._fd = tswap32(info->_sifields._sigpoll._fd); +    } else if (sig == TARGET_SIGCHLD) { +        tinfo->_sifields._sigchld._pid +            = tswap32(info->_sifields._sigchld._pid); +        tinfo->_sifields._sigchld._uid +            = tswap32(info->_sifields._sigchld._uid); +        tinfo->_sifields._sigchld._status +            = tswap32(info->_sifields._sigchld._status); +        tinfo->_sifields._sigchld._utime +            = tswapal(info->_sifields._sigchld._utime); +        tinfo->_sifields._sigchld._stime +            = tswapal(info->_sifields._sigchld._stime); +    } else if (sig >= TARGET_SIGRTMIN) { +        tinfo->_sifields._rt._pid = tswap32(info->_sifields._rt._pid); +        tinfo->_sifields._rt._uid = tswap32(info->_sifields._rt._uid); +        tinfo->_sifields._rt._sigval.sival_ptr +            = tswapal(info->_sifields._rt._sigval.sival_ptr); +    } +} + + +void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info) +{ +    host_to_target_siginfo_noswap(tinfo, info); +    tswap_siginfo(tinfo, tinfo); +} + +/* XXX: we support only POSIX RT signals are used. */ +/* XXX: find a solution for 64 bit (additional malloced data is needed) */ +void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo) +{ +    info->si_signo = tswap32(tinfo->si_signo); +    info->si_errno = tswap32(tinfo->si_errno); +    info->si_code = tswap32(tinfo->si_code); +    info->si_pid = tswap32(tinfo->_sifields._rt._pid); +    info->si_uid = tswap32(tinfo->_sifields._rt._uid); +    info->si_value.sival_ptr = +            (void *)(long)tswapal(tinfo->_sifields._rt._sigval.sival_ptr); +} + +static int fatal_signal (int sig) +{ +    switch (sig) { +    case TARGET_SIGCHLD: +    case TARGET_SIGURG: +    case TARGET_SIGWINCH: +        /* Ignored by default.  */ +        return 0; +    case TARGET_SIGCONT: +    case TARGET_SIGSTOP: +    case TARGET_SIGTSTP: +    case TARGET_SIGTTIN: +    case TARGET_SIGTTOU: +        /* Job control signals.  */ +        return 0; +    default: +        return 1; +    } +} + +/* returns 1 if given signal should dump core if not handled */ +static int core_dump_signal(int sig) +{ +    switch (sig) { +    case TARGET_SIGABRT: +    case TARGET_SIGFPE: +    case TARGET_SIGILL: +    case TARGET_SIGQUIT: +    case TARGET_SIGSEGV: +    case TARGET_SIGTRAP: +    case TARGET_SIGBUS: +        return (1); +    default: +        return (0); +    } +} + +void signal_init(void) +{ +    struct sigaction act; +    struct sigaction oact; +    int i, j; +    int host_sig; + +    /* generate signal conversion tables */ +    for(i = 1; i < _NSIG; i++) { +        if (host_to_target_signal_table[i] == 0) +            host_to_target_signal_table[i] = i; +    } +    for(i = 1; i < _NSIG; i++) { +        j = host_to_target_signal_table[i]; +        target_to_host_signal_table[j] = i; +    } + +    /* set all host signal handlers. ALL signals are blocked during +       the handlers to serialize them. */ +    memset(sigact_table, 0, sizeof(sigact_table)); + +    sigfillset(&act.sa_mask); +    act.sa_flags = SA_SIGINFO; +    act.sa_sigaction = host_signal_handler; +    for(i = 1; i <= TARGET_NSIG; i++) { +        host_sig = target_to_host_signal(i); +        sigaction(host_sig, NULL, &oact); +        if (oact.sa_sigaction == (void *)SIG_IGN) { +            sigact_table[i - 1]._sa_handler = TARGET_SIG_IGN; +        } else if (oact.sa_sigaction == (void *)SIG_DFL) { +            sigact_table[i - 1]._sa_handler = TARGET_SIG_DFL; +        } +        /* If there's already a handler installed then something has +           gone horribly wrong, so don't even try to handle that case.  */ +        /* Install some handlers for our own use.  We need at least +           SIGSEGV and SIGBUS, to detect exceptions.  We can not just +           trap all signals because it affects syscall interrupt +           behavior.  But do trap all default-fatal signals.  */ +        if (fatal_signal (i)) +            sigaction(host_sig, &act, NULL); +    } +} + +/* signal queue handling */ + +static inline struct sigqueue *alloc_sigqueue(CPUArchState *env) +{ +    CPUState *cpu = ENV_GET_CPU(env); +    TaskState *ts = cpu->opaque; +    struct sigqueue *q = ts->first_free; +    if (!q) +        return NULL; +    ts->first_free = q->next; +    return q; +} + +static inline void free_sigqueue(CPUArchState *env, struct sigqueue *q) +{ +    CPUState *cpu = ENV_GET_CPU(env); +    TaskState *ts = cpu->opaque; + +    q->next = ts->first_free; +    ts->first_free = q; +} + +/* abort execution with signal */ +static void QEMU_NORETURN force_sig(int target_sig) +{ +    CPUState *cpu = thread_cpu; +    CPUArchState *env = cpu->env_ptr; +    TaskState *ts = (TaskState *)cpu->opaque; +    int host_sig, core_dumped = 0; +    struct sigaction act; +    host_sig = target_to_host_signal(target_sig); +    gdb_signalled(env, target_sig); + +    /* dump core if supported by target binary format */ +    if (core_dump_signal(target_sig) && (ts->bprm->core_dump != NULL)) { +        stop_all_tasks(); +        core_dumped = +            ((*ts->bprm->core_dump)(target_sig, env) == 0); +    } +    if (core_dumped) { +        /* we already dumped the core of target process, we don't want +         * a coredump of qemu itself */ +        struct rlimit nodump; +        getrlimit(RLIMIT_CORE, &nodump); +        nodump.rlim_cur=0; +        setrlimit(RLIMIT_CORE, &nodump); +        (void) fprintf(stderr, "qemu: uncaught target signal %d (%s) - %s\n", +            target_sig, strsignal(host_sig), "core dumped" ); +    } + +    /* The proper exit code for dying from an uncaught signal is +     * -<signal>.  The kernel doesn't allow exit() or _exit() to pass +     * a negative value.  To get the proper exit code we need to +     * actually die from an uncaught signal.  Here the default signal +     * handler is installed, we send ourself a signal and we wait for +     * it to arrive. */ +    sigfillset(&act.sa_mask); +    act.sa_handler = SIG_DFL; +    act.sa_flags = 0; +    sigaction(host_sig, &act, NULL); + +    /* For some reason raise(host_sig) doesn't send the signal when +     * statically linked on x86-64. */ +    kill(getpid(), host_sig); + +    /* Make sure the signal isn't masked (just reuse the mask inside +    of act) */ +    sigdelset(&act.sa_mask, host_sig); +    sigsuspend(&act.sa_mask); + +    /* unreachable */ +    abort(); +} + +/* queue a signal so that it will be send to the virtual CPU as soon +   as possible */ +int queue_signal(CPUArchState *env, int sig, target_siginfo_t *info) +{ +    CPUState *cpu = ENV_GET_CPU(env); +    TaskState *ts = cpu->opaque; +    struct emulated_sigtable *k; +    struct sigqueue *q, **pq; +    abi_ulong handler; +    int queue; + +#if defined(DEBUG_SIGNAL) +    fprintf(stderr, "queue_signal: sig=%d\n", +            sig); +#endif +    k = &ts->sigtab[sig - 1]; +    queue = gdb_queuesig (); +    handler = sigact_table[sig - 1]._sa_handler; + +    if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) { +        /* Guest has blocked SIGSEGV but we got one anyway. Assume this +         * is a forced SIGSEGV (ie one the kernel handles via force_sig_info +         * because it got a real MMU fault). A blocked SIGSEGV in that +         * situation is treated as if using the default handler. This is +         * not correct if some other process has randomly sent us a SIGSEGV +         * via kill(), but that is not easy to distinguish at this point, +         * so we assume it doesn't happen. +         */ +        handler = TARGET_SIG_DFL; +    } + +    if (!queue && handler == TARGET_SIG_DFL) { +        if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) { +            kill(getpid(),SIGSTOP); +            return 0; +        } else +        /* default handler : ignore some signal. The other are fatal */ +        if (sig != TARGET_SIGCHLD && +            sig != TARGET_SIGURG && +            sig != TARGET_SIGWINCH && +            sig != TARGET_SIGCONT) { +            force_sig(sig); +        } else { +            return 0; /* indicate ignored */ +        } +    } else if (!queue && handler == TARGET_SIG_IGN) { +        /* ignore signal */ +        return 0; +    } else if (!queue && handler == TARGET_SIG_ERR) { +        force_sig(sig); +    } else { +        pq = &k->first; +        if (sig < TARGET_SIGRTMIN) { +            /* if non real time signal, we queue exactly one signal */ +            if (!k->pending) +                q = &k->info; +            else +                return 0; +        } else { +            if (!k->pending) { +                /* first signal */ +                q = &k->info; +            } else { +                q = alloc_sigqueue(env); +                if (!q) +                    return -EAGAIN; +                while (*pq != NULL) +                    pq = &(*pq)->next; +            } +        } +        *pq = q; +        q->info = *info; +        q->next = NULL; +        k->pending = 1; +        /* signal that a new signal is pending */ +        ts->signal_pending = 1; +        return 1; /* indicates that the signal was queued */ +    } +} + +static void host_signal_handler(int host_signum, siginfo_t *info, +                                void *puc) +{ +    CPUArchState *env = thread_cpu->env_ptr; +    int sig; +    target_siginfo_t tinfo; + +    /* the CPU emulator uses some host signals to detect exceptions, +       we forward to it some signals */ +    if ((host_signum == SIGSEGV || host_signum == SIGBUS) +        && info->si_code > 0) { +        if (cpu_signal_handler(host_signum, info, puc)) +            return; +    } + +    /* get target signal number */ +    sig = host_to_target_signal(host_signum); +    if (sig < 1 || sig > TARGET_NSIG) +        return; +#if defined(DEBUG_SIGNAL) +    fprintf(stderr, "qemu: got signal %d\n", sig); +#endif +    host_to_target_siginfo_noswap(&tinfo, info); +    if (queue_signal(env, sig, &tinfo) == 1) { +        /* interrupt the virtual CPU as soon as possible */ +        cpu_exit(thread_cpu); +    } +} + +/* do_sigaltstack() returns target values and errnos. */ +/* compare linux/kernel/signal.c:do_sigaltstack() */ +abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp) +{ +    int ret; +    struct target_sigaltstack oss; + +    /* XXX: test errors */ +    if(uoss_addr) +    { +        __put_user(target_sigaltstack_used.ss_sp, &oss.ss_sp); +        __put_user(target_sigaltstack_used.ss_size, &oss.ss_size); +        __put_user(sas_ss_flags(sp), &oss.ss_flags); +    } + +    if(uss_addr) +    { +        struct target_sigaltstack *uss; +        struct target_sigaltstack ss; +        size_t minstacksize = TARGET_MINSIGSTKSZ; + +#if defined(TARGET_PPC64) +        /* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */ +        struct image_info *image = ((TaskState *)thread_cpu->opaque)->info; +        if (get_ppc64_abi(image) > 1) { +            minstacksize = 4096; +        } +#endif + +	ret = -TARGET_EFAULT; +        if (!lock_user_struct(VERIFY_READ, uss, uss_addr, 1)) { +            goto out; +        } +        __get_user(ss.ss_sp, &uss->ss_sp); +        __get_user(ss.ss_size, &uss->ss_size); +        __get_user(ss.ss_flags, &uss->ss_flags); +        unlock_user_struct(uss, uss_addr, 0); + +	ret = -TARGET_EPERM; +	if (on_sig_stack(sp)) +            goto out; + +	ret = -TARGET_EINVAL; +	if (ss.ss_flags != TARGET_SS_DISABLE +            && ss.ss_flags != TARGET_SS_ONSTACK +            && ss.ss_flags != 0) +            goto out; + +	if (ss.ss_flags == TARGET_SS_DISABLE) { +            ss.ss_size = 0; +            ss.ss_sp = 0; +	} else { +            ret = -TARGET_ENOMEM; +            if (ss.ss_size < minstacksize) { +                goto out; +            } +	} + +        target_sigaltstack_used.ss_sp = ss.ss_sp; +        target_sigaltstack_used.ss_size = ss.ss_size; +    } + +    if (uoss_addr) { +        ret = -TARGET_EFAULT; +        if (copy_to_user(uoss_addr, &oss, sizeof(oss))) +            goto out; +    } + +    ret = 0; +out: +    return ret; +} + +/* do_sigaction() return host values and errnos */ +int do_sigaction(int sig, const struct target_sigaction *act, +                 struct target_sigaction *oact) +{ +    struct target_sigaction *k; +    struct sigaction act1; +    int host_sig; +    int ret = 0; + +    if (sig < 1 || sig > TARGET_NSIG || sig == TARGET_SIGKILL || sig == TARGET_SIGSTOP) +        return -EINVAL; +    k = &sigact_table[sig - 1]; +#if defined(DEBUG_SIGNAL) +    fprintf(stderr, "sigaction sig=%d act=0x%p, oact=0x%p\n", +            sig, act, oact); +#endif +    if (oact) { +        __put_user(k->_sa_handler, &oact->_sa_handler); +        __put_user(k->sa_flags, &oact->sa_flags); +#if !defined(TARGET_MIPS) +        __put_user(k->sa_restorer, &oact->sa_restorer); +#endif +        /* Not swapped.  */ +        oact->sa_mask = k->sa_mask; +    } +    if (act) { +        /* FIXME: This is not threadsafe.  */ +        __get_user(k->_sa_handler, &act->_sa_handler); +        __get_user(k->sa_flags, &act->sa_flags); +#if !defined(TARGET_MIPS) +        __get_user(k->sa_restorer, &act->sa_restorer); +#endif +        /* To be swapped in target_to_host_sigset.  */ +        k->sa_mask = act->sa_mask; + +        /* we update the host linux signal state */ +        host_sig = target_to_host_signal(sig); +        if (host_sig != SIGSEGV && host_sig != SIGBUS) { +            sigfillset(&act1.sa_mask); +            act1.sa_flags = SA_SIGINFO; +            if (k->sa_flags & TARGET_SA_RESTART) +                act1.sa_flags |= SA_RESTART; +            /* NOTE: it is important to update the host kernel signal +               ignore state to avoid getting unexpected interrupted +               syscalls */ +            if (k->_sa_handler == TARGET_SIG_IGN) { +                act1.sa_sigaction = (void *)SIG_IGN; +            } else if (k->_sa_handler == TARGET_SIG_DFL) { +                if (fatal_signal (sig)) +                    act1.sa_sigaction = host_signal_handler; +                else +                    act1.sa_sigaction = (void *)SIG_DFL; +            } else { +                act1.sa_sigaction = host_signal_handler; +            } +            ret = sigaction(host_sig, &act1, NULL); +        } +    } +    return ret; +} + +#if defined(TARGET_I386) && TARGET_ABI_BITS == 32 + +/* from the Linux kernel */ + +struct target_fpreg { +	uint16_t significand[4]; +	uint16_t exponent; +}; + +struct target_fpxreg { +	uint16_t significand[4]; +	uint16_t exponent; +	uint16_t padding[3]; +}; + +struct target_xmmreg { +	abi_ulong element[4]; +}; + +struct target_fpstate { +	/* Regular FPU environment */ +        abi_ulong       cw; +        abi_ulong       sw; +        abi_ulong       tag; +        abi_ulong       ipoff; +        abi_ulong       cssel; +        abi_ulong       dataoff; +        abi_ulong       datasel; +	struct target_fpreg	_st[8]; +	uint16_t	status; +	uint16_t	magic;		/* 0xffff = regular FPU data only */ + +	/* FXSR FPU environment */ +        abi_ulong       _fxsr_env[6];   /* FXSR FPU env is ignored */ +        abi_ulong       mxcsr; +        abi_ulong       reserved; +	struct target_fpxreg	_fxsr_st[8];	/* FXSR FPU reg data is ignored */ +	struct target_xmmreg	_xmm[8]; +        abi_ulong       padding[56]; +}; + +#define X86_FXSR_MAGIC		0x0000 + +struct target_sigcontext { +	uint16_t gs, __gsh; +	uint16_t fs, __fsh; +	uint16_t es, __esh; +	uint16_t ds, __dsh; +        abi_ulong edi; +        abi_ulong esi; +        abi_ulong ebp; +        abi_ulong esp; +        abi_ulong ebx; +        abi_ulong edx; +        abi_ulong ecx; +        abi_ulong eax; +        abi_ulong trapno; +        abi_ulong err; +        abi_ulong eip; +	uint16_t cs, __csh; +        abi_ulong eflags; +        abi_ulong esp_at_signal; +	uint16_t ss, __ssh; +        abi_ulong fpstate; /* pointer */ +        abi_ulong oldmask; +        abi_ulong cr2; +}; + +struct target_ucontext { +        abi_ulong         tuc_flags; +        abi_ulong         tuc_link; +	target_stack_t	  tuc_stack; +	struct target_sigcontext tuc_mcontext; +	target_sigset_t	  tuc_sigmask;	/* mask last for extensibility */ +}; + +struct sigframe +{ +    abi_ulong pretcode; +    int sig; +    struct target_sigcontext sc; +    struct target_fpstate fpstate; +    abi_ulong extramask[TARGET_NSIG_WORDS-1]; +    char retcode[8]; +}; + +struct rt_sigframe +{ +    abi_ulong pretcode; +    int sig; +    abi_ulong pinfo; +    abi_ulong puc; +    struct target_siginfo info; +    struct target_ucontext uc; +    struct target_fpstate fpstate; +    char retcode[8]; +}; + +/* + * Set up a signal frame. + */ + +/* XXX: save x87 state */ +static void setup_sigcontext(struct target_sigcontext *sc, +        struct target_fpstate *fpstate, CPUX86State *env, abi_ulong mask, +        abi_ulong fpstate_addr) +{ +    CPUState *cs = CPU(x86_env_get_cpu(env)); +    uint16_t magic; + +	/* already locked in setup_frame() */ +    __put_user(env->segs[R_GS].selector, (unsigned int *)&sc->gs); +    __put_user(env->segs[R_FS].selector, (unsigned int *)&sc->fs); +    __put_user(env->segs[R_ES].selector, (unsigned int *)&sc->es); +    __put_user(env->segs[R_DS].selector, (unsigned int *)&sc->ds); +    __put_user(env->regs[R_EDI], &sc->edi); +    __put_user(env->regs[R_ESI], &sc->esi); +    __put_user(env->regs[R_EBP], &sc->ebp); +    __put_user(env->regs[R_ESP], &sc->esp); +    __put_user(env->regs[R_EBX], &sc->ebx); +    __put_user(env->regs[R_EDX], &sc->edx); +    __put_user(env->regs[R_ECX], &sc->ecx); +    __put_user(env->regs[R_EAX], &sc->eax); +    __put_user(cs->exception_index, &sc->trapno); +    __put_user(env->error_code, &sc->err); +    __put_user(env->eip, &sc->eip); +    __put_user(env->segs[R_CS].selector, (unsigned int *)&sc->cs); +    __put_user(env->eflags, &sc->eflags); +    __put_user(env->regs[R_ESP], &sc->esp_at_signal); +    __put_user(env->segs[R_SS].selector, (unsigned int *)&sc->ss); + +        cpu_x86_fsave(env, fpstate_addr, 1); +        fpstate->status = fpstate->sw; +        magic = 0xffff; +    __put_user(magic, &fpstate->magic); +    __put_user(fpstate_addr, &sc->fpstate); + +	/* non-iBCS2 extensions.. */ +    __put_user(mask, &sc->oldmask); +    __put_user(env->cr[2], &sc->cr2); +} + +/* + * Determine which stack to use.. + */ + +static inline abi_ulong +get_sigframe(struct target_sigaction *ka, CPUX86State *env, size_t frame_size) +{ +	unsigned long esp; + +	/* Default to using normal stack */ +	esp = env->regs[R_ESP]; +	/* This is the X/Open sanctioned signal stack switching.  */ +        if (ka->sa_flags & TARGET_SA_ONSTACK) { +            if (sas_ss_flags(esp) == 0) +                esp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; +        } + +	/* This is the legacy signal stack switching. */ +	else +        if ((env->segs[R_SS].selector & 0xffff) != __USER_DS && +            !(ka->sa_flags & TARGET_SA_RESTORER) && +            ka->sa_restorer) { +            esp = (unsigned long) ka->sa_restorer; +	} +        return (esp - frame_size) & -8ul; +} + +/* compare linux/arch/i386/kernel/signal.c:setup_frame() */ +static void setup_frame(int sig, struct target_sigaction *ka, +			target_sigset_t *set, CPUX86State *env) +{ +	abi_ulong frame_addr; +	struct sigframe *frame; +	int i; + +	frame_addr = get_sigframe(ka, env, sizeof(*frame)); + +	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) +		goto give_sigsegv; + +    __put_user(sig, &frame->sig); + +	setup_sigcontext(&frame->sc, &frame->fpstate, env, set->sig[0], +                         frame_addr + offsetof(struct sigframe, fpstate)); + +    for(i = 1; i < TARGET_NSIG_WORDS; i++) { +        __put_user(set->sig[i], &frame->extramask[i - 1]); +    } + +	/* Set up to return from userspace.  If provided, use a stub +	   already in userspace.  */ +	if (ka->sa_flags & TARGET_SA_RESTORER) { +        __put_user(ka->sa_restorer, &frame->pretcode); +	} else { +                uint16_t val16; +                abi_ulong retcode_addr; +                retcode_addr = frame_addr + offsetof(struct sigframe, retcode); +        __put_user(retcode_addr, &frame->pretcode); +		/* This is popl %eax ; movl $,%eax ; int $0x80 */ +                val16 = 0xb858; +        __put_user(val16, (uint16_t *)(frame->retcode+0)); +        __put_user(TARGET_NR_sigreturn, (int *)(frame->retcode+2)); +                val16 = 0x80cd; +        __put_user(val16, (uint16_t *)(frame->retcode+6)); +	} + + +	/* Set up registers for signal handler */ +	env->regs[R_ESP] = frame_addr; +	env->eip = ka->_sa_handler; + +        cpu_x86_load_seg(env, R_DS, __USER_DS); +        cpu_x86_load_seg(env, R_ES, __USER_DS); +        cpu_x86_load_seg(env, R_SS, __USER_DS); +        cpu_x86_load_seg(env, R_CS, __USER_CS); +	env->eflags &= ~TF_MASK; + +	unlock_user_struct(frame, frame_addr, 1); + +	return; + +give_sigsegv: +	if (sig == TARGET_SIGSEGV) +		ka->_sa_handler = TARGET_SIG_DFL; +	force_sig(TARGET_SIGSEGV /* , current */); +} + +/* compare linux/arch/i386/kernel/signal.c:setup_rt_frame() */ +static void setup_rt_frame(int sig, struct target_sigaction *ka, +                           target_siginfo_t *info, +			   target_sigset_t *set, CPUX86State *env) +{ +        abi_ulong frame_addr, addr; +	struct rt_sigframe *frame; +	int i; + +	frame_addr = get_sigframe(ka, env, sizeof(*frame)); + +	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) +		goto give_sigsegv; + +    __put_user(sig, &frame->sig); +        addr = frame_addr + offsetof(struct rt_sigframe, info); +    __put_user(addr, &frame->pinfo); +        addr = frame_addr + offsetof(struct rt_sigframe, uc); +    __put_user(addr, &frame->puc); +    tswap_siginfo(&frame->info, info); + +	/* Create the ucontext.  */ +    __put_user(0, &frame->uc.tuc_flags); +    __put_user(0, &frame->uc.tuc_link); +    __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp); +    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), +               &frame->uc.tuc_stack.ss_flags); +    __put_user(target_sigaltstack_used.ss_size, +               &frame->uc.tuc_stack.ss_size); +    setup_sigcontext(&frame->uc.tuc_mcontext, &frame->fpstate, env, +            set->sig[0], frame_addr + offsetof(struct rt_sigframe, fpstate)); + +    for(i = 0; i < TARGET_NSIG_WORDS; i++) { +        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]); +    } + +	/* Set up to return from userspace.  If provided, use a stub +	   already in userspace.  */ +	if (ka->sa_flags & TARGET_SA_RESTORER) { +        __put_user(ka->sa_restorer, &frame->pretcode); +	} else { +                uint16_t val16; +                addr = frame_addr + offsetof(struct rt_sigframe, retcode); +        __put_user(addr, &frame->pretcode); +		/* This is movl $,%eax ; int $0x80 */ +        __put_user(0xb8, (char *)(frame->retcode+0)); +        __put_user(TARGET_NR_rt_sigreturn, (int *)(frame->retcode+1)); +                val16 = 0x80cd; +        __put_user(val16, (uint16_t *)(frame->retcode+5)); +	} + +	/* Set up registers for signal handler */ +	env->regs[R_ESP] = frame_addr; +	env->eip = ka->_sa_handler; + +        cpu_x86_load_seg(env, R_DS, __USER_DS); +        cpu_x86_load_seg(env, R_ES, __USER_DS); +        cpu_x86_load_seg(env, R_SS, __USER_DS); +        cpu_x86_load_seg(env, R_CS, __USER_CS); +	env->eflags &= ~TF_MASK; + +	unlock_user_struct(frame, frame_addr, 1); + +	return; + +give_sigsegv: +	if (sig == TARGET_SIGSEGV) +		ka->_sa_handler = TARGET_SIG_DFL; +	force_sig(TARGET_SIGSEGV /* , current */); +} + +static int +restore_sigcontext(CPUX86State *env, struct target_sigcontext *sc, int *peax) +{ +	unsigned int err = 0; +        abi_ulong fpstate_addr; +        unsigned int tmpflags; + +        cpu_x86_load_seg(env, R_GS, tswap16(sc->gs)); +        cpu_x86_load_seg(env, R_FS, tswap16(sc->fs)); +        cpu_x86_load_seg(env, R_ES, tswap16(sc->es)); +        cpu_x86_load_seg(env, R_DS, tswap16(sc->ds)); + +        env->regs[R_EDI] = tswapl(sc->edi); +        env->regs[R_ESI] = tswapl(sc->esi); +        env->regs[R_EBP] = tswapl(sc->ebp); +        env->regs[R_ESP] = tswapl(sc->esp); +        env->regs[R_EBX] = tswapl(sc->ebx); +        env->regs[R_EDX] = tswapl(sc->edx); +        env->regs[R_ECX] = tswapl(sc->ecx); +        env->eip = tswapl(sc->eip); + +        cpu_x86_load_seg(env, R_CS, lduw_p(&sc->cs) | 3); +        cpu_x86_load_seg(env, R_SS, lduw_p(&sc->ss) | 3); + +        tmpflags = tswapl(sc->eflags); +        env->eflags = (env->eflags & ~0x40DD5) | (tmpflags & 0x40DD5); +        //		regs->orig_eax = -1;		/* disable syscall checks */ + +        fpstate_addr = tswapl(sc->fpstate); +	if (fpstate_addr != 0) { +                if (!access_ok(VERIFY_READ, fpstate_addr,  +                               sizeof(struct target_fpstate))) +                        goto badframe; +                cpu_x86_frstor(env, fpstate_addr, 1); +	} + +        *peax = tswapl(sc->eax); +	return err; +badframe: +	return 1; +} + +long do_sigreturn(CPUX86State *env) +{ +    struct sigframe *frame; +    abi_ulong frame_addr = env->regs[R_ESP] - 8; +    target_sigset_t target_set; +    sigset_t set; +    int eax, i; + +#if defined(DEBUG_SIGNAL) +    fprintf(stderr, "do_sigreturn\n"); +#endif +    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) +        goto badframe; +    /* set blocked signals */ +    __get_user(target_set.sig[0], &frame->sc.oldmask); +    for(i = 1; i < TARGET_NSIG_WORDS; i++) { +        __get_user(target_set.sig[i], &frame->extramask[i - 1]); +    } + +    target_to_host_sigset_internal(&set, &target_set); +    do_sigprocmask(SIG_SETMASK, &set, NULL); + +    /* restore registers */ +    if (restore_sigcontext(env, &frame->sc, &eax)) +        goto badframe; +    unlock_user_struct(frame, frame_addr, 0); +    return eax; + +badframe: +    unlock_user_struct(frame, frame_addr, 0); +    force_sig(TARGET_SIGSEGV); +    return 0; +} + +long do_rt_sigreturn(CPUX86State *env) +{ +        abi_ulong frame_addr; +	struct rt_sigframe *frame; +        sigset_t set; +	int eax; + +        frame_addr = env->regs[R_ESP] - 4; +        if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) +                goto badframe; +        target_to_host_sigset(&set, &frame->uc.tuc_sigmask); +        do_sigprocmask(SIG_SETMASK, &set, NULL); + +	if (restore_sigcontext(env, &frame->uc.tuc_mcontext, &eax)) +		goto badframe; + +	if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,  +                           get_sp_from_cpustate(env)) == -EFAULT) +		goto badframe; + +        unlock_user_struct(frame, frame_addr, 0); +	return eax; + +badframe: +        unlock_user_struct(frame, frame_addr, 0); +        force_sig(TARGET_SIGSEGV); +	return 0; +} + +#elif defined(TARGET_AARCH64) + +struct target_sigcontext { +    uint64_t fault_address; +    /* AArch64 registers */ +    uint64_t regs[31]; +    uint64_t sp; +    uint64_t pc; +    uint64_t pstate; +    /* 4K reserved for FP/SIMD state and future expansion */ +    char __reserved[4096] __attribute__((__aligned__(16))); +}; + +struct target_ucontext { +    abi_ulong tuc_flags; +    abi_ulong tuc_link; +    target_stack_t tuc_stack; +    target_sigset_t tuc_sigmask; +    /* glibc uses a 1024-bit sigset_t */ +    char __unused[1024 / 8 - sizeof(target_sigset_t)]; +    /* last for future expansion */ +    struct target_sigcontext tuc_mcontext; +}; + +/* + * Header to be used at the beginning of structures extending the user + * context. Such structures must be placed after the rt_sigframe on the stack + * and be 16-byte aligned. The last structure must be a dummy one with the + * magic and size set to 0. + */ +struct target_aarch64_ctx { +    uint32_t magic; +    uint32_t size; +}; + +#define TARGET_FPSIMD_MAGIC 0x46508001 + +struct target_fpsimd_context { +    struct target_aarch64_ctx head; +    uint32_t fpsr; +    uint32_t fpcr; +    uint64_t vregs[32 * 2]; /* really uint128_t vregs[32] */ +}; + +/* + * Auxiliary context saved in the sigcontext.__reserved array. Not exported to + * user space as it will change with the addition of new context. User space + * should check the magic/size information. + */ +struct target_aux_context { +    struct target_fpsimd_context fpsimd; +    /* additional context to be added before "end" */ +    struct target_aarch64_ctx end; +}; + +struct target_rt_sigframe { +    struct target_siginfo info; +    struct target_ucontext uc; +    uint64_t fp; +    uint64_t lr; +    uint32_t tramp[2]; +}; + +static int target_setup_sigframe(struct target_rt_sigframe *sf, +                                 CPUARMState *env, target_sigset_t *set) +{ +    int i; +    struct target_aux_context *aux = +        (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved; + +    /* set up the stack frame for unwinding */ +    __put_user(env->xregs[29], &sf->fp); +    __put_user(env->xregs[30], &sf->lr); + +    for (i = 0; i < 31; i++) { +        __put_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]); +    } +    __put_user(env->xregs[31], &sf->uc.tuc_mcontext.sp); +    __put_user(env->pc, &sf->uc.tuc_mcontext.pc); +    __put_user(pstate_read(env), &sf->uc.tuc_mcontext.pstate); + +    __put_user(env->exception.vaddress, &sf->uc.tuc_mcontext.fault_address); + +    for (i = 0; i < TARGET_NSIG_WORDS; i++) { +        __put_user(set->sig[i], &sf->uc.tuc_sigmask.sig[i]); +    } + +    for (i = 0; i < 32; i++) { +#ifdef TARGET_WORDS_BIGENDIAN +        __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]); +        __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]); +#else +        __put_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]); +        __put_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]); +#endif +    } +    __put_user(vfp_get_fpsr(env), &aux->fpsimd.fpsr); +    __put_user(vfp_get_fpcr(env), &aux->fpsimd.fpcr); +    __put_user(TARGET_FPSIMD_MAGIC, &aux->fpsimd.head.magic); +    __put_user(sizeof(struct target_fpsimd_context), +            &aux->fpsimd.head.size); + +    /* set the "end" magic */ +    __put_user(0, &aux->end.magic); +    __put_user(0, &aux->end.size); + +    return 0; +} + +static int target_restore_sigframe(CPUARMState *env, +                                   struct target_rt_sigframe *sf) +{ +    sigset_t set; +    int i; +    struct target_aux_context *aux = +        (struct target_aux_context *)sf->uc.tuc_mcontext.__reserved; +    uint32_t magic, size, fpsr, fpcr; +    uint64_t pstate; + +    target_to_host_sigset(&set, &sf->uc.tuc_sigmask); +    do_sigprocmask(SIG_SETMASK, &set, NULL); + +    for (i = 0; i < 31; i++) { +        __get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]); +    } + +    __get_user(env->xregs[31], &sf->uc.tuc_mcontext.sp); +    __get_user(env->pc, &sf->uc.tuc_mcontext.pc); +    __get_user(pstate, &sf->uc.tuc_mcontext.pstate); +    pstate_write(env, pstate); + +    __get_user(magic, &aux->fpsimd.head.magic); +    __get_user(size, &aux->fpsimd.head.size); + +    if (magic != TARGET_FPSIMD_MAGIC +        || size != sizeof(struct target_fpsimd_context)) { +        return 1; +    } + +    for (i = 0; i < 32; i++) { +#ifdef TARGET_WORDS_BIGENDIAN +        __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2 + 1]); +        __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2]); +#else +        __get_user(env->vfp.regs[i * 2], &aux->fpsimd.vregs[i * 2]); +        __get_user(env->vfp.regs[i * 2 + 1], &aux->fpsimd.vregs[i * 2 + 1]); +#endif +    } +    __get_user(fpsr, &aux->fpsimd.fpsr); +    vfp_set_fpsr(env, fpsr); +    __get_user(fpcr, &aux->fpsimd.fpcr); +    vfp_set_fpcr(env, fpcr); + +    return 0; +} + +static abi_ulong get_sigframe(struct target_sigaction *ka, CPUARMState *env) +{ +    abi_ulong sp; + +    sp = env->xregs[31]; + +    /* +     * This is the X/Open sanctioned signal stack switching. +     */ +    if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) { +        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; +    } + +    sp = (sp - sizeof(struct target_rt_sigframe)) & ~15; + +    return sp; +} + +static void target_setup_frame(int usig, struct target_sigaction *ka, +                               target_siginfo_t *info, target_sigset_t *set, +                               CPUARMState *env) +{ +    struct target_rt_sigframe *frame; +    abi_ulong frame_addr, return_addr; + +    frame_addr = get_sigframe(ka, env); +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { +        goto give_sigsegv; +    } + +    __put_user(0, &frame->uc.tuc_flags); +    __put_user(0, &frame->uc.tuc_link); + +    __put_user(target_sigaltstack_used.ss_sp, +                      &frame->uc.tuc_stack.ss_sp); +    __put_user(sas_ss_flags(env->xregs[31]), +                      &frame->uc.tuc_stack.ss_flags); +    __put_user(target_sigaltstack_used.ss_size, +                      &frame->uc.tuc_stack.ss_size); +    target_setup_sigframe(frame, env, set); +    if (ka->sa_flags & TARGET_SA_RESTORER) { +        return_addr = ka->sa_restorer; +    } else { +        /* mov x8,#__NR_rt_sigreturn; svc #0 */ +        __put_user(0xd2801168, &frame->tramp[0]); +        __put_user(0xd4000001, &frame->tramp[1]); +        return_addr = frame_addr + offsetof(struct target_rt_sigframe, tramp); +    } +    env->xregs[0] = usig; +    env->xregs[31] = frame_addr; +    env->xregs[29] = env->xregs[31] + offsetof(struct target_rt_sigframe, fp); +    env->pc = ka->_sa_handler; +    env->xregs[30] = return_addr; +    if (info) { +        tswap_siginfo(&frame->info, info); +        env->xregs[1] = frame_addr + offsetof(struct target_rt_sigframe, info); +        env->xregs[2] = frame_addr + offsetof(struct target_rt_sigframe, uc); +    } + +    unlock_user_struct(frame, frame_addr, 1); +    return; + + give_sigsegv: +    unlock_user_struct(frame, frame_addr, 1); +    force_sig(TARGET_SIGSEGV); +} + +static void setup_rt_frame(int sig, struct target_sigaction *ka, +                           target_siginfo_t *info, target_sigset_t *set, +                           CPUARMState *env) +{ +    target_setup_frame(sig, ka, info, set, env); +} + +static void setup_frame(int sig, struct target_sigaction *ka, +                        target_sigset_t *set, CPUARMState *env) +{ +    target_setup_frame(sig, ka, 0, set, env); +} + +long do_rt_sigreturn(CPUARMState *env) +{ +    struct target_rt_sigframe *frame = NULL; +    abi_ulong frame_addr = env->xregs[31]; + +    if (frame_addr & 15) { +        goto badframe; +    } + +    if  (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { +        goto badframe; +    } + +    if (target_restore_sigframe(env, frame)) { +        goto badframe; +    } + +    if (do_sigaltstack(frame_addr + +            offsetof(struct target_rt_sigframe, uc.tuc_stack), +            0, get_sp_from_cpustate(env)) == -EFAULT) { +        goto badframe; +    } + +    unlock_user_struct(frame, frame_addr, 0); +    return env->xregs[0]; + + badframe: +    unlock_user_struct(frame, frame_addr, 0); +    force_sig(TARGET_SIGSEGV); +    return 0; +} + +long do_sigreturn(CPUARMState *env) +{ +    return do_rt_sigreturn(env); +} + +#elif defined(TARGET_ARM) + +struct target_sigcontext { +	abi_ulong trap_no; +	abi_ulong error_code; +	abi_ulong oldmask; +	abi_ulong arm_r0; +	abi_ulong arm_r1; +	abi_ulong arm_r2; +	abi_ulong arm_r3; +	abi_ulong arm_r4; +	abi_ulong arm_r5; +	abi_ulong arm_r6; +	abi_ulong arm_r7; +	abi_ulong arm_r8; +	abi_ulong arm_r9; +	abi_ulong arm_r10; +	abi_ulong arm_fp; +	abi_ulong arm_ip; +	abi_ulong arm_sp; +	abi_ulong arm_lr; +	abi_ulong arm_pc; +	abi_ulong arm_cpsr; +	abi_ulong fault_address; +}; + +struct target_ucontext_v1 { +    abi_ulong tuc_flags; +    abi_ulong tuc_link; +    target_stack_t tuc_stack; +    struct target_sigcontext tuc_mcontext; +    target_sigset_t  tuc_sigmask;	/* mask last for extensibility */ +}; + +struct target_ucontext_v2 { +    abi_ulong tuc_flags; +    abi_ulong tuc_link; +    target_stack_t tuc_stack; +    struct target_sigcontext tuc_mcontext; +    target_sigset_t  tuc_sigmask;	/* mask last for extensibility */ +    char __unused[128 - sizeof(target_sigset_t)]; +    abi_ulong tuc_regspace[128] __attribute__((__aligned__(8))); +}; + +struct target_user_vfp { +    uint64_t fpregs[32]; +    abi_ulong fpscr; +}; + +struct target_user_vfp_exc { +    abi_ulong fpexc; +    abi_ulong fpinst; +    abi_ulong fpinst2; +}; + +struct target_vfp_sigframe { +    abi_ulong magic; +    abi_ulong size; +    struct target_user_vfp ufp; +    struct target_user_vfp_exc ufp_exc; +} __attribute__((__aligned__(8))); + +struct target_iwmmxt_sigframe { +    abi_ulong magic; +    abi_ulong size; +    uint64_t regs[16]; +    /* Note that not all the coprocessor control registers are stored here */ +    uint32_t wcssf; +    uint32_t wcasf; +    uint32_t wcgr0; +    uint32_t wcgr1; +    uint32_t wcgr2; +    uint32_t wcgr3; +} __attribute__((__aligned__(8))); + +#define TARGET_VFP_MAGIC 0x56465001 +#define TARGET_IWMMXT_MAGIC 0x12ef842a + +struct sigframe_v1 +{ +    struct target_sigcontext sc; +    abi_ulong extramask[TARGET_NSIG_WORDS-1]; +    abi_ulong retcode; +}; + +struct sigframe_v2 +{ +    struct target_ucontext_v2 uc; +    abi_ulong retcode; +}; + +struct rt_sigframe_v1 +{ +    abi_ulong pinfo; +    abi_ulong puc; +    struct target_siginfo info; +    struct target_ucontext_v1 uc; +    abi_ulong retcode; +}; + +struct rt_sigframe_v2 +{ +    struct target_siginfo info; +    struct target_ucontext_v2 uc; +    abi_ulong retcode; +}; + +#define TARGET_CONFIG_CPU_32 1 + +/* + * For ARM syscalls, we encode the syscall number into the instruction. + */ +#define SWI_SYS_SIGRETURN	(0xef000000|(TARGET_NR_sigreturn + ARM_SYSCALL_BASE)) +#define SWI_SYS_RT_SIGRETURN	(0xef000000|(TARGET_NR_rt_sigreturn + ARM_SYSCALL_BASE)) + +/* + * For Thumb syscalls, we pass the syscall number via r7.  We therefore + * need two 16-bit instructions. + */ +#define SWI_THUMB_SIGRETURN	(0xdf00 << 16 | 0x2700 | (TARGET_NR_sigreturn)) +#define SWI_THUMB_RT_SIGRETURN	(0xdf00 << 16 | 0x2700 | (TARGET_NR_rt_sigreturn)) + +static const abi_ulong retcodes[4] = { +	SWI_SYS_SIGRETURN,	SWI_THUMB_SIGRETURN, +	SWI_SYS_RT_SIGRETURN,	SWI_THUMB_RT_SIGRETURN +}; + + +static inline int valid_user_regs(CPUARMState *regs) +{ +    return 1; +} + +static void +setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/ +                 CPUARMState *env, abi_ulong mask) +{ +	__put_user(env->regs[0], &sc->arm_r0); +	__put_user(env->regs[1], &sc->arm_r1); +	__put_user(env->regs[2], &sc->arm_r2); +	__put_user(env->regs[3], &sc->arm_r3); +	__put_user(env->regs[4], &sc->arm_r4); +	__put_user(env->regs[5], &sc->arm_r5); +	__put_user(env->regs[6], &sc->arm_r6); +	__put_user(env->regs[7], &sc->arm_r7); +	__put_user(env->regs[8], &sc->arm_r8); +	__put_user(env->regs[9], &sc->arm_r9); +	__put_user(env->regs[10], &sc->arm_r10); +	__put_user(env->regs[11], &sc->arm_fp); +	__put_user(env->regs[12], &sc->arm_ip); +	__put_user(env->regs[13], &sc->arm_sp); +	__put_user(env->regs[14], &sc->arm_lr); +	__put_user(env->regs[15], &sc->arm_pc); +#ifdef TARGET_CONFIG_CPU_32 +	__put_user(cpsr_read(env), &sc->arm_cpsr); +#endif + +	__put_user(/* current->thread.trap_no */ 0, &sc->trap_no); +	__put_user(/* current->thread.error_code */ 0, &sc->error_code); +	__put_user(/* current->thread.address */ 0, &sc->fault_address); +	__put_user(mask, &sc->oldmask); +} + +static inline abi_ulong +get_sigframe(struct target_sigaction *ka, CPUARMState *regs, int framesize) +{ +	unsigned long sp = regs->regs[13]; + +	/* +	 * This is the X/Open sanctioned signal stack switching. +	 */ +	if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) +            sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; +	/* +	 * ATPCS B01 mandates 8-byte alignment +	 */ +	return (sp - framesize) & ~7; +} + +static void +setup_return(CPUARMState *env, struct target_sigaction *ka, +	     abi_ulong *rc, abi_ulong frame_addr, int usig, abi_ulong rc_addr) +{ +	abi_ulong handler = ka->_sa_handler; +	abi_ulong retcode; +	int thumb = handler & 1; +	uint32_t cpsr = cpsr_read(env); + +	cpsr &= ~CPSR_IT; +	if (thumb) { +		cpsr |= CPSR_T; +	} else { +		cpsr &= ~CPSR_T; +	} + +	if (ka->sa_flags & TARGET_SA_RESTORER) { +		retcode = ka->sa_restorer; +	} else { +		unsigned int idx = thumb; + +		if (ka->sa_flags & TARGET_SA_SIGINFO) +			idx += 2; + +        __put_user(retcodes[idx], rc); + +		retcode = rc_addr + thumb; +	} + +	env->regs[0] = usig; +	env->regs[13] = frame_addr; +	env->regs[14] = retcode; +	env->regs[15] = handler & (thumb ? ~1 : ~3); +	cpsr_write(env, cpsr, 0xffffffff); +} + +static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUARMState *env) +{ +    int i; +    struct target_vfp_sigframe *vfpframe; +    vfpframe = (struct target_vfp_sigframe *)regspace; +    __put_user(TARGET_VFP_MAGIC, &vfpframe->magic); +    __put_user(sizeof(*vfpframe), &vfpframe->size); +    for (i = 0; i < 32; i++) { +        __put_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]); +    } +    __put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr); +    __put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc); +    __put_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst); +    __put_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2); +    return (abi_ulong*)(vfpframe+1); +} + +static abi_ulong *setup_sigframe_v2_iwmmxt(abi_ulong *regspace, +                                           CPUARMState *env) +{ +    int i; +    struct target_iwmmxt_sigframe *iwmmxtframe; +    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace; +    __put_user(TARGET_IWMMXT_MAGIC, &iwmmxtframe->magic); +    __put_user(sizeof(*iwmmxtframe), &iwmmxtframe->size); +    for (i = 0; i < 16; i++) { +        __put_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]); +    } +    __put_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf); +    __put_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf); +    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0); +    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1); +    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2); +    __put_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3); +    return (abi_ulong*)(iwmmxtframe+1); +} + +static void setup_sigframe_v2(struct target_ucontext_v2 *uc, +                              target_sigset_t *set, CPUARMState *env) +{ +    struct target_sigaltstack stack; +    int i; +    abi_ulong *regspace; + +    /* Clear all the bits of the ucontext we don't use.  */ +    memset(uc, 0, offsetof(struct target_ucontext_v2, tuc_mcontext)); + +    memset(&stack, 0, sizeof(stack)); +    __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp); +    __put_user(target_sigaltstack_used.ss_size, &stack.ss_size); +    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags); +    memcpy(&uc->tuc_stack, &stack, sizeof(stack)); + +    setup_sigcontext(&uc->tuc_mcontext, env, set->sig[0]); +    /* Save coprocessor signal frame.  */ +    regspace = uc->tuc_regspace; +    if (arm_feature(env, ARM_FEATURE_VFP)) { +        regspace = setup_sigframe_v2_vfp(regspace, env); +    } +    if (arm_feature(env, ARM_FEATURE_IWMMXT)) { +        regspace = setup_sigframe_v2_iwmmxt(regspace, env); +    } + +    /* Write terminating magic word */ +    __put_user(0, regspace); + +    for(i = 0; i < TARGET_NSIG_WORDS; i++) { +        __put_user(set->sig[i], &uc->tuc_sigmask.sig[i]); +    } +} + +/* compare linux/arch/arm/kernel/signal.c:setup_frame() */ +static void setup_frame_v1(int usig, struct target_sigaction *ka, +                           target_sigset_t *set, CPUARMState *regs) +{ +	struct sigframe_v1 *frame; +	abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame)); +	int i; + +	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) +		return; + +	setup_sigcontext(&frame->sc, regs, set->sig[0]); + +    for(i = 1; i < TARGET_NSIG_WORDS; i++) { +        __put_user(set->sig[i], &frame->extramask[i - 1]); +    } + +        setup_return(regs, ka, &frame->retcode, frame_addr, usig, +                     frame_addr + offsetof(struct sigframe_v1, retcode)); + +	unlock_user_struct(frame, frame_addr, 1); +} + +static void setup_frame_v2(int usig, struct target_sigaction *ka, +                           target_sigset_t *set, CPUARMState *regs) +{ +	struct sigframe_v2 *frame; +	abi_ulong frame_addr = get_sigframe(ka, regs, sizeof(*frame)); + +	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) +		return; + +        setup_sigframe_v2(&frame->uc, set, regs); + +        setup_return(regs, ka, &frame->retcode, frame_addr, usig, +                     frame_addr + offsetof(struct sigframe_v2, retcode)); + +	unlock_user_struct(frame, frame_addr, 1); +} + +static void setup_frame(int usig, struct target_sigaction *ka, +                        target_sigset_t *set, CPUARMState *regs) +{ +    if (get_osversion() >= 0x020612) { +        setup_frame_v2(usig, ka, set, regs); +    } else { +        setup_frame_v1(usig, ka, set, regs); +    } +} + +/* compare linux/arch/arm/kernel/signal.c:setup_rt_frame() */ +static void setup_rt_frame_v1(int usig, struct target_sigaction *ka, +                              target_siginfo_t *info, +                              target_sigset_t *set, CPUARMState *env) +{ +	struct rt_sigframe_v1 *frame; +	abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame)); +	struct target_sigaltstack stack; +	int i; +        abi_ulong info_addr, uc_addr; + +	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) +            return /* 1 */; + +        info_addr = frame_addr + offsetof(struct rt_sigframe_v1, info); +	__put_user(info_addr, &frame->pinfo); +        uc_addr = frame_addr + offsetof(struct rt_sigframe_v1, uc); +	__put_user(uc_addr, &frame->puc); +        tswap_siginfo(&frame->info, info); + +	/* Clear all the bits of the ucontext we don't use.  */ +	memset(&frame->uc, 0, offsetof(struct target_ucontext_v1, tuc_mcontext)); + +        memset(&stack, 0, sizeof(stack)); +        __put_user(target_sigaltstack_used.ss_sp, &stack.ss_sp); +        __put_user(target_sigaltstack_used.ss_size, &stack.ss_size); +        __put_user(sas_ss_flags(get_sp_from_cpustate(env)), &stack.ss_flags); +        memcpy(&frame->uc.tuc_stack, &stack, sizeof(stack)); + +	setup_sigcontext(&frame->uc.tuc_mcontext, env, set->sig[0]); +        for(i = 0; i < TARGET_NSIG_WORDS; i++) { +            __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]); +        } + +        setup_return(env, ka, &frame->retcode, frame_addr, usig, +                     frame_addr + offsetof(struct rt_sigframe_v1, retcode)); + +        env->regs[1] = info_addr; +        env->regs[2] = uc_addr; + +	unlock_user_struct(frame, frame_addr, 1); +} + +static void setup_rt_frame_v2(int usig, struct target_sigaction *ka, +                              target_siginfo_t *info, +                              target_sigset_t *set, CPUARMState *env) +{ +	struct rt_sigframe_v2 *frame; +	abi_ulong frame_addr = get_sigframe(ka, env, sizeof(*frame)); +        abi_ulong info_addr, uc_addr; + +	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) +            return /* 1 */; + +        info_addr = frame_addr + offsetof(struct rt_sigframe_v2, info); +        uc_addr = frame_addr + offsetof(struct rt_sigframe_v2, uc); +        tswap_siginfo(&frame->info, info); + +        setup_sigframe_v2(&frame->uc, set, env); + +        setup_return(env, ka, &frame->retcode, frame_addr, usig, +                     frame_addr + offsetof(struct rt_sigframe_v2, retcode)); + +        env->regs[1] = info_addr; +        env->regs[2] = uc_addr; + +	unlock_user_struct(frame, frame_addr, 1); +} + +static void setup_rt_frame(int usig, struct target_sigaction *ka, +                           target_siginfo_t *info, +                           target_sigset_t *set, CPUARMState *env) +{ +    if (get_osversion() >= 0x020612) { +        setup_rt_frame_v2(usig, ka, info, set, env); +    } else { +        setup_rt_frame_v1(usig, ka, info, set, env); +    } +} + +static int +restore_sigcontext(CPUARMState *env, struct target_sigcontext *sc) +{ +	int err = 0; +        uint32_t cpsr; + +    __get_user(env->regs[0], &sc->arm_r0); +    __get_user(env->regs[1], &sc->arm_r1); +    __get_user(env->regs[2], &sc->arm_r2); +    __get_user(env->regs[3], &sc->arm_r3); +    __get_user(env->regs[4], &sc->arm_r4); +    __get_user(env->regs[5], &sc->arm_r5); +    __get_user(env->regs[6], &sc->arm_r6); +    __get_user(env->regs[7], &sc->arm_r7); +    __get_user(env->regs[8], &sc->arm_r8); +    __get_user(env->regs[9], &sc->arm_r9); +    __get_user(env->regs[10], &sc->arm_r10); +    __get_user(env->regs[11], &sc->arm_fp); +    __get_user(env->regs[12], &sc->arm_ip); +    __get_user(env->regs[13], &sc->arm_sp); +    __get_user(env->regs[14], &sc->arm_lr); +    __get_user(env->regs[15], &sc->arm_pc); +#ifdef TARGET_CONFIG_CPU_32 +    __get_user(cpsr, &sc->arm_cpsr); +        cpsr_write(env, cpsr, CPSR_USER | CPSR_EXEC); +#endif + +	err |= !valid_user_regs(env); + +	return err; +} + +static long do_sigreturn_v1(CPUARMState *env) +{ +        abi_ulong frame_addr; +        struct sigframe_v1 *frame = NULL; +	target_sigset_t set; +        sigset_t host_set; +        int i; + +	/* +	 * Since we stacked the signal on a 64-bit boundary, +	 * then 'sp' should be word aligned here.  If it's +	 * not, then the user is trying to mess with us. +	 */ +        frame_addr = env->regs[13]; +        if (frame_addr & 7) { +            goto badframe; +        } + +	if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) +                goto badframe; + +    __get_user(set.sig[0], &frame->sc.oldmask); +    for(i = 1; i < TARGET_NSIG_WORDS; i++) { +        __get_user(set.sig[i], &frame->extramask[i - 1]); +    } + +        target_to_host_sigset_internal(&host_set, &set); +        do_sigprocmask(SIG_SETMASK, &host_set, NULL); + +	if (restore_sigcontext(env, &frame->sc)) +		goto badframe; + +#if 0 +	/* Send SIGTRAP if we're single-stepping */ +	if (ptrace_cancel_bpt(current)) +		send_sig(SIGTRAP, current, 1); +#endif +	unlock_user_struct(frame, frame_addr, 0); +        return env->regs[0]; + +badframe: +        force_sig(TARGET_SIGSEGV /* , current */); +	return 0; +} + +static abi_ulong *restore_sigframe_v2_vfp(CPUARMState *env, abi_ulong *regspace) +{ +    int i; +    abi_ulong magic, sz; +    uint32_t fpscr, fpexc; +    struct target_vfp_sigframe *vfpframe; +    vfpframe = (struct target_vfp_sigframe *)regspace; + +    __get_user(magic, &vfpframe->magic); +    __get_user(sz, &vfpframe->size); +    if (magic != TARGET_VFP_MAGIC || sz != sizeof(*vfpframe)) { +        return 0; +    } +    for (i = 0; i < 32; i++) { +        __get_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]); +    } +    __get_user(fpscr, &vfpframe->ufp.fpscr); +    vfp_set_fpscr(env, fpscr); +    __get_user(fpexc, &vfpframe->ufp_exc.fpexc); +    /* Sanitise FPEXC: ensure VFP is enabled, FPINST2 is invalid +     * and the exception flag is cleared +     */ +    fpexc |= (1 << 30); +    fpexc &= ~((1 << 31) | (1 << 28)); +    env->vfp.xregs[ARM_VFP_FPEXC] = fpexc; +    __get_user(env->vfp.xregs[ARM_VFP_FPINST], &vfpframe->ufp_exc.fpinst); +    __get_user(env->vfp.xregs[ARM_VFP_FPINST2], &vfpframe->ufp_exc.fpinst2); +    return (abi_ulong*)(vfpframe + 1); +} + +static abi_ulong *restore_sigframe_v2_iwmmxt(CPUARMState *env, +                                             abi_ulong *regspace) +{ +    int i; +    abi_ulong magic, sz; +    struct target_iwmmxt_sigframe *iwmmxtframe; +    iwmmxtframe = (struct target_iwmmxt_sigframe *)regspace; + +    __get_user(magic, &iwmmxtframe->magic); +    __get_user(sz, &iwmmxtframe->size); +    if (magic != TARGET_IWMMXT_MAGIC || sz != sizeof(*iwmmxtframe)) { +        return 0; +    } +    for (i = 0; i < 16; i++) { +        __get_user(env->iwmmxt.regs[i], &iwmmxtframe->regs[i]); +    } +    __get_user(env->vfp.xregs[ARM_IWMMXT_wCSSF], &iwmmxtframe->wcssf); +    __get_user(env->vfp.xregs[ARM_IWMMXT_wCASF], &iwmmxtframe->wcssf); +    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR0], &iwmmxtframe->wcgr0); +    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR1], &iwmmxtframe->wcgr1); +    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR2], &iwmmxtframe->wcgr2); +    __get_user(env->vfp.xregs[ARM_IWMMXT_wCGR3], &iwmmxtframe->wcgr3); +    return (abi_ulong*)(iwmmxtframe + 1); +} + +static int do_sigframe_return_v2(CPUARMState *env, target_ulong frame_addr, +                                 struct target_ucontext_v2 *uc) +{ +    sigset_t host_set; +    abi_ulong *regspace; + +    target_to_host_sigset(&host_set, &uc->tuc_sigmask); +    do_sigprocmask(SIG_SETMASK, &host_set, NULL); + +    if (restore_sigcontext(env, &uc->tuc_mcontext)) +        return 1; + +    /* Restore coprocessor signal frame */ +    regspace = uc->tuc_regspace; +    if (arm_feature(env, ARM_FEATURE_VFP)) { +        regspace = restore_sigframe_v2_vfp(env, regspace); +        if (!regspace) { +            return 1; +        } +    } +    if (arm_feature(env, ARM_FEATURE_IWMMXT)) { +        regspace = restore_sigframe_v2_iwmmxt(env, regspace); +        if (!regspace) { +            return 1; +        } +    } + +    if (do_sigaltstack(frame_addr + offsetof(struct target_ucontext_v2, tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) +        return 1; + +#if 0 +    /* Send SIGTRAP if we're single-stepping */ +    if (ptrace_cancel_bpt(current)) +            send_sig(SIGTRAP, current, 1); +#endif + +    return 0; +} + +static long do_sigreturn_v2(CPUARMState *env) +{ +        abi_ulong frame_addr; +        struct sigframe_v2 *frame = NULL; + +	/* +	 * Since we stacked the signal on a 64-bit boundary, +	 * then 'sp' should be word aligned here.  If it's +	 * not, then the user is trying to mess with us. +	 */ +        frame_addr = env->regs[13]; +        if (frame_addr & 7) { +            goto badframe; +        } + +	if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) +                goto badframe; + +        if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) +                goto badframe; + +	unlock_user_struct(frame, frame_addr, 0); +	return env->regs[0]; + +badframe: +	unlock_user_struct(frame, frame_addr, 0); +        force_sig(TARGET_SIGSEGV /* , current */); +	return 0; +} + +long do_sigreturn(CPUARMState *env) +{ +    if (get_osversion() >= 0x020612) { +        return do_sigreturn_v2(env); +    } else { +        return do_sigreturn_v1(env); +    } +} + +static long do_rt_sigreturn_v1(CPUARMState *env) +{ +        abi_ulong frame_addr; +        struct rt_sigframe_v1 *frame = NULL; +        sigset_t host_set; + +	/* +	 * Since we stacked the signal on a 64-bit boundary, +	 * then 'sp' should be word aligned here.  If it's +	 * not, then the user is trying to mess with us. +	 */ +        frame_addr = env->regs[13]; +        if (frame_addr & 7) { +            goto badframe; +        } + +	if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) +                goto badframe; + +        target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask); +        do_sigprocmask(SIG_SETMASK, &host_set, NULL); + +	if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) +		goto badframe; + +	if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) +		goto badframe; + +#if 0 +	/* Send SIGTRAP if we're single-stepping */ +	if (ptrace_cancel_bpt(current)) +		send_sig(SIGTRAP, current, 1); +#endif +	unlock_user_struct(frame, frame_addr, 0); +	return env->regs[0]; + +badframe: +	unlock_user_struct(frame, frame_addr, 0); +        force_sig(TARGET_SIGSEGV /* , current */); +	return 0; +} + +static long do_rt_sigreturn_v2(CPUARMState *env) +{ +        abi_ulong frame_addr; +        struct rt_sigframe_v2 *frame = NULL; + +	/* +	 * Since we stacked the signal on a 64-bit boundary, +	 * then 'sp' should be word aligned here.  If it's +	 * not, then the user is trying to mess with us. +	 */ +        frame_addr = env->regs[13]; +        if (frame_addr & 7) { +            goto badframe; +        } + +	if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) +                goto badframe; + +        if (do_sigframe_return_v2(env, frame_addr, &frame->uc)) +                goto badframe; + +	unlock_user_struct(frame, frame_addr, 0); +	return env->regs[0]; + +badframe: +	unlock_user_struct(frame, frame_addr, 0); +        force_sig(TARGET_SIGSEGV /* , current */); +	return 0; +} + +long do_rt_sigreturn(CPUARMState *env) +{ +    if (get_osversion() >= 0x020612) { +        return do_rt_sigreturn_v2(env); +    } else { +        return do_rt_sigreturn_v1(env); +    } +} + +#elif defined(TARGET_SPARC) + +#define __SUNOS_MAXWIN   31 + +/* This is what SunOS does, so shall I. */ +struct target_sigcontext { +        abi_ulong sigc_onstack;      /* state to restore */ + +        abi_ulong sigc_mask;         /* sigmask to restore */ +        abi_ulong sigc_sp;           /* stack pointer */ +        abi_ulong sigc_pc;           /* program counter */ +        abi_ulong sigc_npc;          /* next program counter */ +        abi_ulong sigc_psr;          /* for condition codes etc */ +        abi_ulong sigc_g1;           /* User uses these two registers */ +        abi_ulong sigc_o0;           /* within the trampoline code. */ + +        /* Now comes information regarding the users window set +         * at the time of the signal. +         */ +        abi_ulong sigc_oswins;       /* outstanding windows */ + +        /* stack ptrs for each regwin buf */ +        char *sigc_spbuf[__SUNOS_MAXWIN]; + +        /* Windows to restore after signal */ +        struct { +                abi_ulong locals[8]; +                abi_ulong ins[8]; +        } sigc_wbuf[__SUNOS_MAXWIN]; +}; +/* A Sparc stack frame */ +struct sparc_stackf { +        abi_ulong locals[8]; +        abi_ulong ins[8]; +        /* It's simpler to treat fp and callers_pc as elements of ins[] +         * since we never need to access them ourselves. +         */ +        char *structptr; +        abi_ulong xargs[6]; +        abi_ulong xxargs[1]; +}; + +typedef struct { +        struct { +                abi_ulong psr; +                abi_ulong pc; +                abi_ulong npc; +                abi_ulong y; +                abi_ulong u_regs[16]; /* globals and ins */ +        }               si_regs; +        int             si_mask; +} __siginfo_t; + +typedef struct { +        abi_ulong       si_float_regs[32]; +        unsigned   long si_fsr; +        unsigned   long si_fpqdepth; +        struct { +                unsigned long *insn_addr; +                unsigned long insn; +        } si_fpqueue [16]; +} qemu_siginfo_fpu_t; + + +struct target_signal_frame { +	struct sparc_stackf	ss; +	__siginfo_t		info; +	abi_ulong               fpu_save; +	abi_ulong		insns[2] __attribute__ ((aligned (8))); +	abi_ulong		extramask[TARGET_NSIG_WORDS - 1]; +	abi_ulong		extra_size; /* Should be 0 */ +	qemu_siginfo_fpu_t	fpu_state; +}; +struct target_rt_signal_frame { +	struct sparc_stackf	ss; +	siginfo_t		info; +	abi_ulong		regs[20]; +	sigset_t		mask; +	abi_ulong               fpu_save; +	unsigned int		insns[2]; +	stack_t			stack; +	unsigned int		extra_size; /* Should be 0 */ +	qemu_siginfo_fpu_t	fpu_state; +}; + +#define UREG_O0        16 +#define UREG_O6        22 +#define UREG_I0        0 +#define UREG_I1        1 +#define UREG_I2        2 +#define UREG_I3        3 +#define UREG_I4        4 +#define UREG_I5        5 +#define UREG_I6        6 +#define UREG_I7        7 +#define UREG_L0	       8 +#define UREG_FP        UREG_I6 +#define UREG_SP        UREG_O6 + +static inline abi_ulong get_sigframe(struct target_sigaction *sa,  +                                     CPUSPARCState *env, +                                     unsigned long framesize) +{ +	abi_ulong sp; + +	sp = env->regwptr[UREG_FP]; + +	/* This is the X/Open sanctioned signal stack switching.  */ +	if (sa->sa_flags & TARGET_SA_ONSTACK) { +            if (!on_sig_stack(sp) +                && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7)) +                sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; +	} +	return sp - framesize; +} + +static int +setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask) +{ +	int err = 0, i; + +    __put_user(env->psr, &si->si_regs.psr); +    __put_user(env->pc, &si->si_regs.pc); +    __put_user(env->npc, &si->si_regs.npc); +    __put_user(env->y, &si->si_regs.y); +	for (i=0; i < 8; i++) { +        __put_user(env->gregs[i], &si->si_regs.u_regs[i]); +	} +	for (i=0; i < 8; i++) { +        __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]); +	} +    __put_user(mask, &si->si_mask); +	return err; +} + +#if 0 +static int +setup_sigcontext(struct target_sigcontext *sc, /*struct _fpstate *fpstate,*/ +                 CPUSPARCState *env, unsigned long mask) +{ +	int err = 0; + +    __put_user(mask, &sc->sigc_mask); +    __put_user(env->regwptr[UREG_SP], &sc->sigc_sp); +    __put_user(env->pc, &sc->sigc_pc); +    __put_user(env->npc, &sc->sigc_npc); +    __put_user(env->psr, &sc->sigc_psr); +    __put_user(env->gregs[1], &sc->sigc_g1); +    __put_user(env->regwptr[UREG_O0], &sc->sigc_o0); + +	return err; +} +#endif +#define NF_ALIGNEDSZ  (((sizeof(struct target_signal_frame) + 7) & (~7))) + +static void setup_frame(int sig, struct target_sigaction *ka, +                        target_sigset_t *set, CPUSPARCState *env) +{ +        abi_ulong sf_addr; +	struct target_signal_frame *sf; +	int sigframe_size, err, i; + +	/* 1. Make sure everything is clean */ +	//synchronize_user_stack(); + +        sigframe_size = NF_ALIGNEDSZ; +	sf_addr = get_sigframe(ka, env, sigframe_size); + +        sf = lock_user(VERIFY_WRITE, sf_addr,  +                       sizeof(struct target_signal_frame), 0); +        if (!sf) +		goto sigsegv; +                 +	//fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]); +#if 0 +	if (invalid_frame_pointer(sf, sigframe_size)) +		goto sigill_and_return; +#endif +	/* 2. Save the current process state */ +	err = setup___siginfo(&sf->info, env, set->sig[0]); +    __put_user(0, &sf->extra_size); + +	//save_fpu_state(regs, &sf->fpu_state); +	//__put_user(&sf->fpu_state, &sf->fpu_save); + +    __put_user(set->sig[0], &sf->info.si_mask); +	for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) { +        __put_user(set->sig[i + 1], &sf->extramask[i]); +	} + +	for (i = 0; i < 8; i++) { +        __put_user(env->regwptr[i + UREG_L0], &sf->ss.locals[i]); +	} +	for (i = 0; i < 8; i++) { +        __put_user(env->regwptr[i + UREG_I0], &sf->ss.ins[i]); +	} +	if (err) +		goto sigsegv; + +	/* 3. signal handler back-trampoline and parameters */ +	env->regwptr[UREG_FP] = sf_addr; +	env->regwptr[UREG_I0] = sig; +	env->regwptr[UREG_I1] = sf_addr +  +                offsetof(struct target_signal_frame, info); +	env->regwptr[UREG_I2] = sf_addr +  +                offsetof(struct target_signal_frame, info); + +	/* 4. signal handler */ +	env->pc = ka->_sa_handler; +	env->npc = (env->pc + 4); +	/* 5. return to kernel instructions */ +	if (ka->sa_restorer) +		env->regwptr[UREG_I7] = ka->sa_restorer; +	else { +                uint32_t val32; + +		env->regwptr[UREG_I7] = sf_addr +  +                        offsetof(struct target_signal_frame, insns) - 2 * 4; + +		/* mov __NR_sigreturn, %g1 */ +                val32 = 0x821020d8; +        __put_user(val32, &sf->insns[0]); + +		/* t 0x10 */ +                val32 = 0x91d02010; +        __put_user(val32, &sf->insns[1]); +		if (err) +			goto sigsegv; + +		/* Flush instruction space. */ +		//flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); +                //		tb_flush(CPU(sparc_env_get_cpu(env))); +	} +        unlock_user(sf, sf_addr, sizeof(struct target_signal_frame)); +	return; +#if 0 +sigill_and_return: +	force_sig(TARGET_SIGILL); +#endif +sigsegv: +	//fprintf(stderr, "force_sig\n"); +        unlock_user(sf, sf_addr, sizeof(struct target_signal_frame)); +	force_sig(TARGET_SIGSEGV); +} + +static void setup_rt_frame(int sig, struct target_sigaction *ka, +                           target_siginfo_t *info, +                           target_sigset_t *set, CPUSPARCState *env) +{ +    fprintf(stderr, "setup_rt_frame: not implemented\n"); +} + +long do_sigreturn(CPUSPARCState *env) +{ +        abi_ulong sf_addr; +        struct target_signal_frame *sf; +        uint32_t up_psr, pc, npc; +        target_sigset_t set; +        sigset_t host_set; +        int err=0, i; + +        sf_addr = env->regwptr[UREG_FP]; +        if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) +                goto segv_and_exit; +#if 0 +	fprintf(stderr, "sigreturn\n"); +	fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]); +#endif +	//cpu_dump_state(env, stderr, fprintf, 0); + +        /* 1. Make sure we are not getting garbage from the user */ + +        if (sf_addr & 3) +                goto segv_and_exit; + +        __get_user(pc,  &sf->info.si_regs.pc); +        __get_user(npc, &sf->info.si_regs.npc); + +        if ((pc | npc) & 3) +                goto segv_and_exit; + +        /* 2. Restore the state */ +        __get_user(up_psr, &sf->info.si_regs.psr); + +        /* User can only change condition codes and FPU enabling in %psr. */ +        env->psr = (up_psr & (PSR_ICC /* | PSR_EF */)) +                  | (env->psr & ~(PSR_ICC /* | PSR_EF */)); + +	env->pc = pc; +	env->npc = npc; +        __get_user(env->y, &sf->info.si_regs.y); +	for (i=0; i < 8; i++) { +		__get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]); +	} +	for (i=0; i < 8; i++) { +		__get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]); +	} + +        /* FIXME: implement FPU save/restore: +         * __get_user(fpu_save, &sf->fpu_save); +         * if (fpu_save) +         *        err |= restore_fpu_state(env, fpu_save); +         */ + +        /* This is pretty much atomic, no amount locking would prevent +         * the races which exist anyways. +         */ +        __get_user(set.sig[0], &sf->info.si_mask); +        for(i = 1; i < TARGET_NSIG_WORDS; i++) { +            __get_user(set.sig[i], &sf->extramask[i - 1]); +        } + +        target_to_host_sigset_internal(&host_set, &set); +        do_sigprocmask(SIG_SETMASK, &host_set, NULL); + +        if (err) +                goto segv_and_exit; +        unlock_user_struct(sf, sf_addr, 0); +        return env->regwptr[0]; + +segv_and_exit: +        unlock_user_struct(sf, sf_addr, 0); +	force_sig(TARGET_SIGSEGV); +} + +long do_rt_sigreturn(CPUSPARCState *env) +{ +    fprintf(stderr, "do_rt_sigreturn: not implemented\n"); +    return -TARGET_ENOSYS; +} + +#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) +#define MC_TSTATE 0 +#define MC_PC 1 +#define MC_NPC 2 +#define MC_Y 3 +#define MC_G1 4 +#define MC_G2 5 +#define MC_G3 6 +#define MC_G4 7 +#define MC_G5 8 +#define MC_G6 9 +#define MC_G7 10 +#define MC_O0 11 +#define MC_O1 12 +#define MC_O2 13 +#define MC_O3 14 +#define MC_O4 15 +#define MC_O5 16 +#define MC_O6 17 +#define MC_O7 18 +#define MC_NGREG 19 + +typedef abi_ulong target_mc_greg_t; +typedef target_mc_greg_t target_mc_gregset_t[MC_NGREG]; + +struct target_mc_fq { +    abi_ulong *mcfq_addr; +    uint32_t mcfq_insn; +}; + +struct target_mc_fpu { +    union { +        uint32_t sregs[32]; +        uint64_t dregs[32]; +        //uint128_t qregs[16]; +    } mcfpu_fregs; +    abi_ulong mcfpu_fsr; +    abi_ulong mcfpu_fprs; +    abi_ulong mcfpu_gsr; +    struct target_mc_fq *mcfpu_fq; +    unsigned char mcfpu_qcnt; +    unsigned char mcfpu_qentsz; +    unsigned char mcfpu_enab; +}; +typedef struct target_mc_fpu target_mc_fpu_t; + +typedef struct { +    target_mc_gregset_t mc_gregs; +    target_mc_greg_t mc_fp; +    target_mc_greg_t mc_i7; +    target_mc_fpu_t mc_fpregs; +} target_mcontext_t; + +struct target_ucontext { +    struct target_ucontext *tuc_link; +    abi_ulong tuc_flags; +    target_sigset_t tuc_sigmask; +    target_mcontext_t tuc_mcontext; +}; + +/* A V9 register window */ +struct target_reg_window { +    abi_ulong locals[8]; +    abi_ulong ins[8]; +}; + +#define TARGET_STACK_BIAS 2047 + +/* {set, get}context() needed for 64-bit SparcLinux userland. */ +void sparc64_set_context(CPUSPARCState *env) +{ +    abi_ulong ucp_addr; +    struct target_ucontext *ucp; +    target_mc_gregset_t *grp; +    abi_ulong pc, npc, tstate; +    abi_ulong fp, i7, w_addr; +    unsigned int i; + +    ucp_addr = env->regwptr[UREG_I0]; +    if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) +        goto do_sigsegv; +    grp  = &ucp->tuc_mcontext.mc_gregs; +    __get_user(pc, &((*grp)[MC_PC])); +    __get_user(npc, &((*grp)[MC_NPC])); +    if ((pc | npc) & 3) +        goto do_sigsegv; +    if (env->regwptr[UREG_I1]) { +        target_sigset_t target_set; +        sigset_t set; + +        if (TARGET_NSIG_WORDS == 1) { +            __get_user(target_set.sig[0], &ucp->tuc_sigmask.sig[0]); +        } else { +            abi_ulong *src, *dst; +            src = ucp->tuc_sigmask.sig; +            dst = target_set.sig; +            for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) { +                __get_user(*dst, src); +            } +        } +        target_to_host_sigset_internal(&set, &target_set); +        do_sigprocmask(SIG_SETMASK, &set, NULL); +    } +    env->pc = pc; +    env->npc = npc; +    __get_user(env->y, &((*grp)[MC_Y])); +    __get_user(tstate, &((*grp)[MC_TSTATE])); +    env->asi = (tstate >> 24) & 0xff; +    cpu_put_ccr(env, tstate >> 32); +    cpu_put_cwp64(env, tstate & 0x1f); +    __get_user(env->gregs[1], (&(*grp)[MC_G1])); +    __get_user(env->gregs[2], (&(*grp)[MC_G2])); +    __get_user(env->gregs[3], (&(*grp)[MC_G3])); +    __get_user(env->gregs[4], (&(*grp)[MC_G4])); +    __get_user(env->gregs[5], (&(*grp)[MC_G5])); +    __get_user(env->gregs[6], (&(*grp)[MC_G6])); +    __get_user(env->gregs[7], (&(*grp)[MC_G7])); +    __get_user(env->regwptr[UREG_I0], (&(*grp)[MC_O0])); +    __get_user(env->regwptr[UREG_I1], (&(*grp)[MC_O1])); +    __get_user(env->regwptr[UREG_I2], (&(*grp)[MC_O2])); +    __get_user(env->regwptr[UREG_I3], (&(*grp)[MC_O3])); +    __get_user(env->regwptr[UREG_I4], (&(*grp)[MC_O4])); +    __get_user(env->regwptr[UREG_I5], (&(*grp)[MC_O5])); +    __get_user(env->regwptr[UREG_I6], (&(*grp)[MC_O6])); +    __get_user(env->regwptr[UREG_I7], (&(*grp)[MC_O7])); + +    __get_user(fp, &(ucp->tuc_mcontext.mc_fp)); +    __get_user(i7, &(ucp->tuc_mcontext.mc_i7)); + +    w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6]; +    if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),  +                 abi_ulong) != 0) +        goto do_sigsegv; +    if (put_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),  +                 abi_ulong) != 0) +        goto do_sigsegv; +    /* FIXME this does not match how the kernel handles the FPU in +     * its sparc64_set_context implementation. In particular the FPU +     * is only restored if fenab is non-zero in: +     *   __get_user(fenab, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_enab)); +     */ +    __get_user(env->fprs, &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fprs)); +    { +        uint32_t *src = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs; +        for (i = 0; i < 64; i++, src++) { +            if (i & 1) { +                __get_user(env->fpr[i/2].l.lower, src); +            } else { +                __get_user(env->fpr[i/2].l.upper, src); +            } +        } +    } +    __get_user(env->fsr, +               &(ucp->tuc_mcontext.mc_fpregs.mcfpu_fsr)); +    __get_user(env->gsr, +               &(ucp->tuc_mcontext.mc_fpregs.mcfpu_gsr)); +    unlock_user_struct(ucp, ucp_addr, 0); +    return; + do_sigsegv: +    unlock_user_struct(ucp, ucp_addr, 0); +    force_sig(TARGET_SIGSEGV); +} + +void sparc64_get_context(CPUSPARCState *env) +{ +    abi_ulong ucp_addr; +    struct target_ucontext *ucp; +    target_mc_gregset_t *grp; +    target_mcontext_t *mcp; +    abi_ulong fp, i7, w_addr; +    int err; +    unsigned int i; +    target_sigset_t target_set; +    sigset_t set; + +    ucp_addr = env->regwptr[UREG_I0]; +    if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) +        goto do_sigsegv; +     +    mcp = &ucp->tuc_mcontext; +    grp = &mcp->mc_gregs; + +    /* Skip over the trap instruction, first. */ +    env->pc = env->npc; +    env->npc += 4; + +    err = 0; + +    do_sigprocmask(0, NULL, &set); +    host_to_target_sigset_internal(&target_set, &set); +    if (TARGET_NSIG_WORDS == 1) { +        __put_user(target_set.sig[0], +                   (abi_ulong *)&ucp->tuc_sigmask); +    } else { +        abi_ulong *src, *dst; +        src = target_set.sig; +        dst = ucp->tuc_sigmask.sig; +        for (i = 0; i < TARGET_NSIG_WORDS; i++, dst++, src++) { +            __put_user(*src, dst); +        } +        if (err) +            goto do_sigsegv; +    } + +    /* XXX: tstate must be saved properly */ +    //    __put_user(env->tstate, &((*grp)[MC_TSTATE])); +    __put_user(env->pc, &((*grp)[MC_PC])); +    __put_user(env->npc, &((*grp)[MC_NPC])); +    __put_user(env->y, &((*grp)[MC_Y])); +    __put_user(env->gregs[1], &((*grp)[MC_G1])); +    __put_user(env->gregs[2], &((*grp)[MC_G2])); +    __put_user(env->gregs[3], &((*grp)[MC_G3])); +    __put_user(env->gregs[4], &((*grp)[MC_G4])); +    __put_user(env->gregs[5], &((*grp)[MC_G5])); +    __put_user(env->gregs[6], &((*grp)[MC_G6])); +    __put_user(env->gregs[7], &((*grp)[MC_G7])); +    __put_user(env->regwptr[UREG_I0], &((*grp)[MC_O0])); +    __put_user(env->regwptr[UREG_I1], &((*grp)[MC_O1])); +    __put_user(env->regwptr[UREG_I2], &((*grp)[MC_O2])); +    __put_user(env->regwptr[UREG_I3], &((*grp)[MC_O3])); +    __put_user(env->regwptr[UREG_I4], &((*grp)[MC_O4])); +    __put_user(env->regwptr[UREG_I5], &((*grp)[MC_O5])); +    __put_user(env->regwptr[UREG_I6], &((*grp)[MC_O6])); +    __put_user(env->regwptr[UREG_I7], &((*grp)[MC_O7])); + +    w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6]; +    fp = i7 = 0; +    if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),  +                 abi_ulong) != 0) +        goto do_sigsegv; +    if (get_user(i7, w_addr + offsetof(struct target_reg_window, ins[7]),  +                 abi_ulong) != 0) +        goto do_sigsegv; +    __put_user(fp, &(mcp->mc_fp)); +    __put_user(i7, &(mcp->mc_i7)); + +    { +        uint32_t *dst = ucp->tuc_mcontext.mc_fpregs.mcfpu_fregs.sregs; +        for (i = 0; i < 64; i++, dst++) { +            if (i & 1) { +                __put_user(env->fpr[i/2].l.lower, dst); +            } else { +                __put_user(env->fpr[i/2].l.upper, dst); +            } +        } +    } +    __put_user(env->fsr, &(mcp->mc_fpregs.mcfpu_fsr)); +    __put_user(env->gsr, &(mcp->mc_fpregs.mcfpu_gsr)); +    __put_user(env->fprs, &(mcp->mc_fpregs.mcfpu_fprs)); + +    if (err) +        goto do_sigsegv; +    unlock_user_struct(ucp, ucp_addr, 1); +    return; + do_sigsegv: +    unlock_user_struct(ucp, ucp_addr, 1); +    force_sig(TARGET_SIGSEGV); +} +#endif +#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64) + +# if defined(TARGET_ABI_MIPSO32) +struct target_sigcontext { +    uint32_t   sc_regmask;     /* Unused */ +    uint32_t   sc_status; +    uint64_t   sc_pc; +    uint64_t   sc_regs[32]; +    uint64_t   sc_fpregs[32]; +    uint32_t   sc_ownedfp;     /* Unused */ +    uint32_t   sc_fpc_csr; +    uint32_t   sc_fpc_eir;     /* Unused */ +    uint32_t   sc_used_math; +    uint32_t   sc_dsp;         /* dsp status, was sc_ssflags */ +    uint32_t   pad0; +    uint64_t   sc_mdhi; +    uint64_t   sc_mdlo; +    target_ulong   sc_hi1;         /* Was sc_cause */ +    target_ulong   sc_lo1;         /* Was sc_badvaddr */ +    target_ulong   sc_hi2;         /* Was sc_sigset[4] */ +    target_ulong   sc_lo2; +    target_ulong   sc_hi3; +    target_ulong   sc_lo3; +}; +# else /* N32 || N64 */ +struct target_sigcontext { +    uint64_t sc_regs[32]; +    uint64_t sc_fpregs[32]; +    uint64_t sc_mdhi; +    uint64_t sc_hi1; +    uint64_t sc_hi2; +    uint64_t sc_hi3; +    uint64_t sc_mdlo; +    uint64_t sc_lo1; +    uint64_t sc_lo2; +    uint64_t sc_lo3; +    uint64_t sc_pc; +    uint32_t sc_fpc_csr; +    uint32_t sc_used_math; +    uint32_t sc_dsp; +    uint32_t sc_reserved; +}; +# endif /* O32 */ + +struct sigframe { +    uint32_t sf_ass[4];			/* argument save space for o32 */ +    uint32_t sf_code[2];			/* signal trampoline */ +    struct target_sigcontext sf_sc; +    target_sigset_t sf_mask; +}; + +struct target_ucontext { +    target_ulong tuc_flags; +    target_ulong tuc_link; +    target_stack_t tuc_stack; +    target_ulong pad0; +    struct target_sigcontext tuc_mcontext; +    target_sigset_t tuc_sigmask; +}; + +struct target_rt_sigframe { +    uint32_t rs_ass[4];               /* argument save space for o32 */ +    uint32_t rs_code[2];              /* signal trampoline */ +    struct target_siginfo rs_info; +    struct target_ucontext rs_uc; +}; + +/* Install trampoline to jump back from signal handler */ +static inline int install_sigtramp(unsigned int *tramp,   unsigned int syscall) +{ +    int err = 0; + +    /* +     * Set up the return code ... +     * +     *         li      v0, __NR__foo_sigreturn +     *         syscall +     */ + +    __put_user(0x24020000 + syscall, tramp + 0); +    __put_user(0x0000000c          , tramp + 1); +    return err; +} + +static inline void setup_sigcontext(CPUMIPSState *regs, +        struct target_sigcontext *sc) +{ +    int i; + +    __put_user(exception_resume_pc(regs), &sc->sc_pc); +    regs->hflags &= ~MIPS_HFLAG_BMASK; + +    __put_user(0, &sc->sc_regs[0]); +    for (i = 1; i < 32; ++i) { +        __put_user(regs->active_tc.gpr[i], &sc->sc_regs[i]); +    } + +    __put_user(regs->active_tc.HI[0], &sc->sc_mdhi); +    __put_user(regs->active_tc.LO[0], &sc->sc_mdlo); + +    /* Rather than checking for dsp existence, always copy.  The storage +       would just be garbage otherwise.  */ +    __put_user(regs->active_tc.HI[1], &sc->sc_hi1); +    __put_user(regs->active_tc.HI[2], &sc->sc_hi2); +    __put_user(regs->active_tc.HI[3], &sc->sc_hi3); +    __put_user(regs->active_tc.LO[1], &sc->sc_lo1); +    __put_user(regs->active_tc.LO[2], &sc->sc_lo2); +    __put_user(regs->active_tc.LO[3], &sc->sc_lo3); +    { +        uint32_t dsp = cpu_rddsp(0x3ff, regs); +        __put_user(dsp, &sc->sc_dsp); +    } + +    __put_user(1, &sc->sc_used_math); + +    for (i = 0; i < 32; ++i) { +        __put_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]); +    } +} + +static inline void +restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc) +{ +    int i; + +    __get_user(regs->CP0_EPC, &sc->sc_pc); + +    __get_user(regs->active_tc.HI[0], &sc->sc_mdhi); +    __get_user(regs->active_tc.LO[0], &sc->sc_mdlo); + +    for (i = 1; i < 32; ++i) { +        __get_user(regs->active_tc.gpr[i], &sc->sc_regs[i]); +    } + +    __get_user(regs->active_tc.HI[1], &sc->sc_hi1); +    __get_user(regs->active_tc.HI[2], &sc->sc_hi2); +    __get_user(regs->active_tc.HI[3], &sc->sc_hi3); +    __get_user(regs->active_tc.LO[1], &sc->sc_lo1); +    __get_user(regs->active_tc.LO[2], &sc->sc_lo2); +    __get_user(regs->active_tc.LO[3], &sc->sc_lo3); +    { +        uint32_t dsp; +        __get_user(dsp, &sc->sc_dsp); +        cpu_wrdsp(dsp, 0x3ff, regs); +    } + +    for (i = 0; i < 32; ++i) { +        __get_user(regs->active_fpu.fpr[i].d, &sc->sc_fpregs[i]); +    } +} + +/* + * Determine which stack to use.. + */ +static inline abi_ulong +get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size) +{ +    unsigned long sp; + +    /* Default to using normal stack */ +    sp = regs->active_tc.gpr[29]; + +    /* +     * FPU emulator may have its own trampoline active just +     * above the user stack, 16-bytes before the next lowest +     * 16 byte boundary.  Try to avoid trashing it. +     */ +    sp -= 32; + +    /* This is the X/Open sanctioned signal stack switching.  */ +    if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) { +        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; +    } + +    return (sp - frame_size) & ~7; +} + +static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env) +{ +    if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) { +        env->hflags &= ~MIPS_HFLAG_M16; +        env->hflags |= (env->active_tc.PC & 1) << MIPS_HFLAG_M16_SHIFT; +        env->active_tc.PC &= ~(target_ulong) 1; +    } +} + +# if defined(TARGET_ABI_MIPSO32) +/* compare linux/arch/mips/kernel/signal.c:setup_frame() */ +static void setup_frame(int sig, struct target_sigaction * ka, +                        target_sigset_t *set, CPUMIPSState *regs) +{ +    struct sigframe *frame; +    abi_ulong frame_addr; +    int i; + +    frame_addr = get_sigframe(ka, regs, sizeof(*frame)); +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) +	goto give_sigsegv; + +    install_sigtramp(frame->sf_code, TARGET_NR_sigreturn); + +    setup_sigcontext(regs, &frame->sf_sc); + +    for(i = 0; i < TARGET_NSIG_WORDS; i++) { +        __put_user(set->sig[i], &frame->sf_mask.sig[i]); +    } + +    /* +    * Arguments to signal handler: +    * +    *   a0 = signal number +    *   a1 = 0 (should be cause) +    *   a2 = pointer to struct sigcontext +    * +    * $25 and PC point to the signal handler, $29 points to the +    * struct sigframe. +    */ +    regs->active_tc.gpr[ 4] = sig; +    regs->active_tc.gpr[ 5] = 0; +    regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc); +    regs->active_tc.gpr[29] = frame_addr; +    regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code); +    /* The original kernel code sets CP0_EPC to the handler +    * since it returns to userland using eret +    * we cannot do this here, and we must set PC directly */ +    regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler; +    mips_set_hflags_isa_mode_from_pc(regs); +    unlock_user_struct(frame, frame_addr, 1); +    return; + +give_sigsegv: +    force_sig(TARGET_SIGSEGV/*, current*/); +} + +long do_sigreturn(CPUMIPSState *regs) +{ +    struct sigframe *frame; +    abi_ulong frame_addr; +    sigset_t blocked; +    target_sigset_t target_set; +    int i; + +#if defined(DEBUG_SIGNAL) +    fprintf(stderr, "do_sigreturn\n"); +#endif +    frame_addr = regs->active_tc.gpr[29]; +    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) +   	goto badframe; + +    for(i = 0; i < TARGET_NSIG_WORDS; i++) { +        __get_user(target_set.sig[i], &frame->sf_mask.sig[i]); +    } + +    target_to_host_sigset_internal(&blocked, &target_set); +    do_sigprocmask(SIG_SETMASK, &blocked, NULL); + +    restore_sigcontext(regs, &frame->sf_sc); + +#if 0 +    /* +     * Don't let your children do this ... +     */ +    __asm__ __volatile__( +   	"move\t$29, %0\n\t" +   	"j\tsyscall_exit" +   	:/* no outputs */ +   	:"r" (®s)); +    /* Unreached */ +#endif + +    regs->active_tc.PC = regs->CP0_EPC; +    mips_set_hflags_isa_mode_from_pc(regs); +    /* I am not sure this is right, but it seems to work +    * maybe a problem with nested signals ? */ +    regs->CP0_EPC = 0; +    return -TARGET_QEMU_ESIGRETURN; + +badframe: +    force_sig(TARGET_SIGSEGV/*, current*/); +    return 0; +} +# endif /* O32 */ + +static void setup_rt_frame(int sig, struct target_sigaction *ka, +                           target_siginfo_t *info, +                           target_sigset_t *set, CPUMIPSState *env) +{ +    struct target_rt_sigframe *frame; +    abi_ulong frame_addr; +    int i; + +    frame_addr = get_sigframe(ka, env, sizeof(*frame)); +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) +	goto give_sigsegv; + +    install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn); + +    tswap_siginfo(&frame->rs_info, info); + +    __put_user(0, &frame->rs_uc.tuc_flags); +    __put_user(0, &frame->rs_uc.tuc_link); +    __put_user(target_sigaltstack_used.ss_sp, &frame->rs_uc.tuc_stack.ss_sp); +    __put_user(target_sigaltstack_used.ss_size, &frame->rs_uc.tuc_stack.ss_size); +    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), +               &frame->rs_uc.tuc_stack.ss_flags); + +    setup_sigcontext(env, &frame->rs_uc.tuc_mcontext); + +    for(i = 0; i < TARGET_NSIG_WORDS; i++) { +        __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]); +    } + +    /* +    * Arguments to signal handler: +    * +    *   a0 = signal number +    *   a1 = pointer to siginfo_t +    *   a2 = pointer to struct ucontext +    * +    * $25 and PC point to the signal handler, $29 points to the +    * struct sigframe. +    */ +    env->active_tc.gpr[ 4] = sig; +    env->active_tc.gpr[ 5] = frame_addr +                             + offsetof(struct target_rt_sigframe, rs_info); +    env->active_tc.gpr[ 6] = frame_addr +                             + offsetof(struct target_rt_sigframe, rs_uc); +    env->active_tc.gpr[29] = frame_addr; +    env->active_tc.gpr[31] = frame_addr +                             + offsetof(struct target_rt_sigframe, rs_code); +    /* The original kernel code sets CP0_EPC to the handler +    * since it returns to userland using eret +    * we cannot do this here, and we must set PC directly */ +    env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler; +    mips_set_hflags_isa_mode_from_pc(env); +    unlock_user_struct(frame, frame_addr, 1); +    return; + +give_sigsegv: +    unlock_user_struct(frame, frame_addr, 1); +    force_sig(TARGET_SIGSEGV/*, current*/); +} + +long do_rt_sigreturn(CPUMIPSState *env) +{ +    struct target_rt_sigframe *frame; +    abi_ulong frame_addr; +    sigset_t blocked; + +#if defined(DEBUG_SIGNAL) +    fprintf(stderr, "do_rt_sigreturn\n"); +#endif +    frame_addr = env->active_tc.gpr[29]; +    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) +   	goto badframe; + +    target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask); +    do_sigprocmask(SIG_SETMASK, &blocked, NULL); + +    restore_sigcontext(env, &frame->rs_uc.tuc_mcontext); + +    if (do_sigaltstack(frame_addr + +		       offsetof(struct target_rt_sigframe, rs_uc.tuc_stack), +		       0, get_sp_from_cpustate(env)) == -EFAULT) +        goto badframe; + +    env->active_tc.PC = env->CP0_EPC; +    mips_set_hflags_isa_mode_from_pc(env); +    /* I am not sure this is right, but it seems to work +    * maybe a problem with nested signals ? */ +    env->CP0_EPC = 0; +    return -TARGET_QEMU_ESIGRETURN; + +badframe: +    force_sig(TARGET_SIGSEGV/*, current*/); +    return 0; +} + +#elif defined(TARGET_SH4) + +/* + * code and data structures from linux kernel: + * include/asm-sh/sigcontext.h + * arch/sh/kernel/signal.c + */ + +struct target_sigcontext { +    target_ulong  oldmask; + +    /* CPU registers */ +    target_ulong  sc_gregs[16]; +    target_ulong  sc_pc; +    target_ulong  sc_pr; +    target_ulong  sc_sr; +    target_ulong  sc_gbr; +    target_ulong  sc_mach; +    target_ulong  sc_macl; + +    /* FPU registers */ +    target_ulong  sc_fpregs[16]; +    target_ulong  sc_xfpregs[16]; +    unsigned int sc_fpscr; +    unsigned int sc_fpul; +    unsigned int sc_ownedfp; +}; + +struct target_sigframe +{ +    struct target_sigcontext sc; +    target_ulong extramask[TARGET_NSIG_WORDS-1]; +    uint16_t retcode[3]; +}; + + +struct target_ucontext { +    target_ulong tuc_flags; +    struct target_ucontext *tuc_link; +    target_stack_t tuc_stack; +    struct target_sigcontext tuc_mcontext; +    target_sigset_t tuc_sigmask;	/* mask last for extensibility */ +}; + +struct target_rt_sigframe +{ +    struct target_siginfo info; +    struct target_ucontext uc; +    uint16_t retcode[3]; +}; + + +#define MOVW(n)  (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */ +#define TRAP_NOARG 0xc310         /* Syscall w/no args (NR in R3) SH3/4 */ + +static abi_ulong get_sigframe(struct target_sigaction *ka, +                         unsigned long sp, size_t frame_size) +{ +    if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(sp) == 0)) { +        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; +    } + +    return (sp - frame_size) & -8ul; +} + +static void setup_sigcontext(struct target_sigcontext *sc, +                            CPUSH4State *regs, unsigned long mask) +{ +    int i; + +#define COPY(x)         __put_user(regs->x, &sc->sc_##x) +    COPY(gregs[0]); COPY(gregs[1]); +    COPY(gregs[2]); COPY(gregs[3]); +    COPY(gregs[4]); COPY(gregs[5]); +    COPY(gregs[6]); COPY(gregs[7]); +    COPY(gregs[8]); COPY(gregs[9]); +    COPY(gregs[10]); COPY(gregs[11]); +    COPY(gregs[12]); COPY(gregs[13]); +    COPY(gregs[14]); COPY(gregs[15]); +    COPY(gbr); COPY(mach); +    COPY(macl); COPY(pr); +    COPY(sr); COPY(pc); +#undef COPY + +    for (i=0; i<16; i++) { +        __put_user(regs->fregs[i], &sc->sc_fpregs[i]); +    } +    __put_user(regs->fpscr, &sc->sc_fpscr); +    __put_user(regs->fpul, &sc->sc_fpul); + +    /* non-iBCS2 extensions.. */ +    __put_user(mask, &sc->oldmask); +} + +static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc, +                              target_ulong *r0_p) +{ +    int i; + +#define COPY(x)         __get_user(regs->x, &sc->sc_##x) +    COPY(gregs[1]); +    COPY(gregs[2]); COPY(gregs[3]); +    COPY(gregs[4]); COPY(gregs[5]); +    COPY(gregs[6]); COPY(gregs[7]); +    COPY(gregs[8]); COPY(gregs[9]); +    COPY(gregs[10]); COPY(gregs[11]); +    COPY(gregs[12]); COPY(gregs[13]); +    COPY(gregs[14]); COPY(gregs[15]); +    COPY(gbr); COPY(mach); +    COPY(macl); COPY(pr); +    COPY(sr); COPY(pc); +#undef COPY + +    for (i=0; i<16; i++) { +        __get_user(regs->fregs[i], &sc->sc_fpregs[i]); +    } +    __get_user(regs->fpscr, &sc->sc_fpscr); +    __get_user(regs->fpul, &sc->sc_fpul); + +    regs->tra = -1;         /* disable syscall checks */ +    __get_user(*r0_p, &sc->sc_gregs[0]); +} + +static void setup_frame(int sig, struct target_sigaction *ka, +                        target_sigset_t *set, CPUSH4State *regs) +{ +    struct target_sigframe *frame; +    abi_ulong frame_addr; +    int i; +    int err = 0; + +    frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame)); +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) +	goto give_sigsegv; + +    setup_sigcontext(&frame->sc, regs, set->sig[0]); + +    for (i = 0; i < TARGET_NSIG_WORDS - 1; i++) { +        __put_user(set->sig[i + 1], &frame->extramask[i]); +    } + +    /* Set up to return from userspace.  If provided, use a stub +       already in userspace.  */ +    if (ka->sa_flags & TARGET_SA_RESTORER) { +        regs->pr = (unsigned long) ka->sa_restorer; +    } else { +        /* Generate return code (system call to sigreturn) */ +        __put_user(MOVW(2), &frame->retcode[0]); +        __put_user(TRAP_NOARG, &frame->retcode[1]); +        __put_user((TARGET_NR_sigreturn), &frame->retcode[2]); +        regs->pr = (unsigned long) frame->retcode; +    } + +    if (err) +        goto give_sigsegv; + +    /* Set up registers for signal handler */ +    regs->gregs[15] = frame_addr; +    regs->gregs[4] = sig; /* Arg for signal handler */ +    regs->gregs[5] = 0; +    regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc); +    regs->pc = (unsigned long) ka->_sa_handler; + +    unlock_user_struct(frame, frame_addr, 1); +    return; + +give_sigsegv: +    unlock_user_struct(frame, frame_addr, 1); +    force_sig(TARGET_SIGSEGV); +} + +static void setup_rt_frame(int sig, struct target_sigaction *ka, +                           target_siginfo_t *info, +                           target_sigset_t *set, CPUSH4State *regs) +{ +    struct target_rt_sigframe *frame; +    abi_ulong frame_addr; +    int i; +    int err = 0; + +    frame_addr = get_sigframe(ka, regs->gregs[15], sizeof(*frame)); +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) +	goto give_sigsegv; + +    tswap_siginfo(&frame->info, info); + +    /* Create the ucontext.  */ +    __put_user(0, &frame->uc.tuc_flags); +    __put_user(0, (unsigned long *)&frame->uc.tuc_link); +    __put_user((unsigned long)target_sigaltstack_used.ss_sp, +               &frame->uc.tuc_stack.ss_sp); +    __put_user(sas_ss_flags(regs->gregs[15]), +               &frame->uc.tuc_stack.ss_flags); +    __put_user(target_sigaltstack_used.ss_size, +               &frame->uc.tuc_stack.ss_size); +    setup_sigcontext(&frame->uc.tuc_mcontext, +			    regs, set->sig[0]); +    for(i = 0; i < TARGET_NSIG_WORDS; i++) { +        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]); +    } + +    /* Set up to return from userspace.  If provided, use a stub +       already in userspace.  */ +    if (ka->sa_flags & TARGET_SA_RESTORER) { +        regs->pr = (unsigned long) ka->sa_restorer; +    } else { +        /* Generate return code (system call to sigreturn) */ +        __put_user(MOVW(2), &frame->retcode[0]); +        __put_user(TRAP_NOARG, &frame->retcode[1]); +        __put_user((TARGET_NR_rt_sigreturn), &frame->retcode[2]); +        regs->pr = (unsigned long) frame->retcode; +    } + +    if (err) +        goto give_sigsegv; + +    /* Set up registers for signal handler */ +    regs->gregs[15] = frame_addr; +    regs->gregs[4] = sig; /* Arg for signal handler */ +    regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info); +    regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc); +    regs->pc = (unsigned long) ka->_sa_handler; + +    unlock_user_struct(frame, frame_addr, 1); +    return; + +give_sigsegv: +    unlock_user_struct(frame, frame_addr, 1); +    force_sig(TARGET_SIGSEGV); +} + +long do_sigreturn(CPUSH4State *regs) +{ +    struct target_sigframe *frame; +    abi_ulong frame_addr; +    sigset_t blocked; +    target_sigset_t target_set; +    target_ulong r0; +    int i; +    int err = 0; + +#if defined(DEBUG_SIGNAL) +    fprintf(stderr, "do_sigreturn\n"); +#endif +    frame_addr = regs->gregs[15]; +    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) +   	goto badframe; + +    __get_user(target_set.sig[0], &frame->sc.oldmask); +    for(i = 1; i < TARGET_NSIG_WORDS; i++) { +        __get_user(target_set.sig[i], &frame->extramask[i - 1]); +    } + +    if (err) +        goto badframe; + +    target_to_host_sigset_internal(&blocked, &target_set); +    do_sigprocmask(SIG_SETMASK, &blocked, NULL); + +    restore_sigcontext(regs, &frame->sc, &r0); + +    unlock_user_struct(frame, frame_addr, 0); +    return r0; + +badframe: +    unlock_user_struct(frame, frame_addr, 0); +    force_sig(TARGET_SIGSEGV); +    return 0; +} + +long do_rt_sigreturn(CPUSH4State *regs) +{ +    struct target_rt_sigframe *frame; +    abi_ulong frame_addr; +    sigset_t blocked; +    target_ulong r0; + +#if defined(DEBUG_SIGNAL) +    fprintf(stderr, "do_rt_sigreturn\n"); +#endif +    frame_addr = regs->gregs[15]; +    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) +   	goto badframe; + +    target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask); +    do_sigprocmask(SIG_SETMASK, &blocked, NULL); + +    restore_sigcontext(regs, &frame->uc.tuc_mcontext, &r0); + +    if (do_sigaltstack(frame_addr + +		       offsetof(struct target_rt_sigframe, uc.tuc_stack), +		       0, get_sp_from_cpustate(regs)) == -EFAULT) +        goto badframe; + +    unlock_user_struct(frame, frame_addr, 0); +    return r0; + +badframe: +    unlock_user_struct(frame, frame_addr, 0); +    force_sig(TARGET_SIGSEGV); +    return 0; +} +#elif defined(TARGET_MICROBLAZE) + +struct target_sigcontext { +    struct target_pt_regs regs;  /* needs to be first */ +    uint32_t oldmask; +}; + +struct target_stack_t { +    abi_ulong ss_sp; +    int ss_flags; +    unsigned int ss_size; +}; + +struct target_ucontext { +    abi_ulong tuc_flags; +    abi_ulong tuc_link; +    struct target_stack_t tuc_stack; +    struct target_sigcontext tuc_mcontext; +    uint32_t tuc_extramask[TARGET_NSIG_WORDS - 1]; +}; + +/* Signal frames. */ +struct target_signal_frame { +    struct target_ucontext uc; +    uint32_t extramask[TARGET_NSIG_WORDS - 1]; +    uint32_t tramp[2]; +}; + +struct rt_signal_frame { +    siginfo_t info; +    struct ucontext uc; +    uint32_t tramp[2]; +}; + +static void setup_sigcontext(struct target_sigcontext *sc, CPUMBState *env) +{ +    __put_user(env->regs[0], &sc->regs.r0); +    __put_user(env->regs[1], &sc->regs.r1); +    __put_user(env->regs[2], &sc->regs.r2); +    __put_user(env->regs[3], &sc->regs.r3); +    __put_user(env->regs[4], &sc->regs.r4); +    __put_user(env->regs[5], &sc->regs.r5); +    __put_user(env->regs[6], &sc->regs.r6); +    __put_user(env->regs[7], &sc->regs.r7); +    __put_user(env->regs[8], &sc->regs.r8); +    __put_user(env->regs[9], &sc->regs.r9); +    __put_user(env->regs[10], &sc->regs.r10); +    __put_user(env->regs[11], &sc->regs.r11); +    __put_user(env->regs[12], &sc->regs.r12); +    __put_user(env->regs[13], &sc->regs.r13); +    __put_user(env->regs[14], &sc->regs.r14); +    __put_user(env->regs[15], &sc->regs.r15); +    __put_user(env->regs[16], &sc->regs.r16); +    __put_user(env->regs[17], &sc->regs.r17); +    __put_user(env->regs[18], &sc->regs.r18); +    __put_user(env->regs[19], &sc->regs.r19); +    __put_user(env->regs[20], &sc->regs.r20); +    __put_user(env->regs[21], &sc->regs.r21); +    __put_user(env->regs[22], &sc->regs.r22); +    __put_user(env->regs[23], &sc->regs.r23); +    __put_user(env->regs[24], &sc->regs.r24); +    __put_user(env->regs[25], &sc->regs.r25); +    __put_user(env->regs[26], &sc->regs.r26); +    __put_user(env->regs[27], &sc->regs.r27); +    __put_user(env->regs[28], &sc->regs.r28); +    __put_user(env->regs[29], &sc->regs.r29); +    __put_user(env->regs[30], &sc->regs.r30); +    __put_user(env->regs[31], &sc->regs.r31); +    __put_user(env->sregs[SR_PC], &sc->regs.pc); +} + +static void restore_sigcontext(struct target_sigcontext *sc, CPUMBState *env) +{ +    __get_user(env->regs[0], &sc->regs.r0); +    __get_user(env->regs[1], &sc->regs.r1); +    __get_user(env->regs[2], &sc->regs.r2); +    __get_user(env->regs[3], &sc->regs.r3); +    __get_user(env->regs[4], &sc->regs.r4); +    __get_user(env->regs[5], &sc->regs.r5); +    __get_user(env->regs[6], &sc->regs.r6); +    __get_user(env->regs[7], &sc->regs.r7); +    __get_user(env->regs[8], &sc->regs.r8); +    __get_user(env->regs[9], &sc->regs.r9); +    __get_user(env->regs[10], &sc->regs.r10); +    __get_user(env->regs[11], &sc->regs.r11); +    __get_user(env->regs[12], &sc->regs.r12); +    __get_user(env->regs[13], &sc->regs.r13); +    __get_user(env->regs[14], &sc->regs.r14); +    __get_user(env->regs[15], &sc->regs.r15); +    __get_user(env->regs[16], &sc->regs.r16); +    __get_user(env->regs[17], &sc->regs.r17); +    __get_user(env->regs[18], &sc->regs.r18); +    __get_user(env->regs[19], &sc->regs.r19); +    __get_user(env->regs[20], &sc->regs.r20); +    __get_user(env->regs[21], &sc->regs.r21); +    __get_user(env->regs[22], &sc->regs.r22); +    __get_user(env->regs[23], &sc->regs.r23); +    __get_user(env->regs[24], &sc->regs.r24); +    __get_user(env->regs[25], &sc->regs.r25); +    __get_user(env->regs[26], &sc->regs.r26); +    __get_user(env->regs[27], &sc->regs.r27); +    __get_user(env->regs[28], &sc->regs.r28); +    __get_user(env->regs[29], &sc->regs.r29); +    __get_user(env->regs[30], &sc->regs.r30); +    __get_user(env->regs[31], &sc->regs.r31); +    __get_user(env->sregs[SR_PC], &sc->regs.pc); +} + +static abi_ulong get_sigframe(struct target_sigaction *ka, +                              CPUMBState *env, int frame_size) +{ +    abi_ulong sp = env->regs[1]; + +    if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !on_sig_stack(sp)) { +        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; +    } + +    return ((sp - frame_size) & -8UL); +} + +static void setup_frame(int sig, struct target_sigaction *ka, +                        target_sigset_t *set, CPUMBState *env) +{ +    struct target_signal_frame *frame; +    abi_ulong frame_addr; +    int i; + +    frame_addr = get_sigframe(ka, env, sizeof *frame); +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) +        goto badframe; + +    /* Save the mask.  */ +    __put_user(set->sig[0], &frame->uc.tuc_mcontext.oldmask); + +    for(i = 1; i < TARGET_NSIG_WORDS; i++) { +        __put_user(set->sig[i], &frame->extramask[i - 1]); +    } + +    setup_sigcontext(&frame->uc.tuc_mcontext, env); + +    /* Set up to return from userspace. If provided, use a stub +       already in userspace. */ +    /* minus 8 is offset to cater for "rtsd r15,8" offset */ +    if (ka->sa_flags & TARGET_SA_RESTORER) { +        env->regs[15] = ((unsigned long)ka->sa_restorer)-8; +    } else { +        uint32_t t; +        /* Note, these encodings are _big endian_! */ +        /* addi r12, r0, __NR_sigreturn */ +        t = 0x31800000UL | TARGET_NR_sigreturn; +        __put_user(t, frame->tramp + 0); +        /* brki r14, 0x8 */ +        t = 0xb9cc0008UL; +        __put_user(t, frame->tramp + 1); + +        /* Return from sighandler will jump to the tramp. +           Negative 8 offset because return is rtsd r15, 8 */ +        env->regs[15] = ((unsigned long)frame->tramp) - 8; +    } + +    /* Set up registers for signal handler */ +    env->regs[1] = frame_addr; +    /* Signal handler args: */ +    env->regs[5] = sig; /* Arg 0: signum */ +    env->regs[6] = 0; +    /* arg 1: sigcontext */ +    env->regs[7] = frame_addr += offsetof(typeof(*frame), uc); + +    /* Offset of 4 to handle microblaze rtid r14, 0 */ +    env->sregs[SR_PC] = (unsigned long)ka->_sa_handler; + +    unlock_user_struct(frame, frame_addr, 1); +    return; +  badframe: +    force_sig(TARGET_SIGSEGV); +} + +static void setup_rt_frame(int sig, struct target_sigaction *ka, +                           target_siginfo_t *info, +                           target_sigset_t *set, CPUMBState *env) +{ +    fprintf(stderr, "Microblaze setup_rt_frame: not implemented\n"); +} + +long do_sigreturn(CPUMBState *env) +{ +    struct target_signal_frame *frame; +    abi_ulong frame_addr; +    target_sigset_t target_set; +    sigset_t set; +    int i; + +    frame_addr = env->regs[R_SP]; +    /* Make sure the guest isn't playing games.  */ +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) +        goto badframe; + +    /* Restore blocked signals */ +    __get_user(target_set.sig[0], &frame->uc.tuc_mcontext.oldmask); +    for(i = 1; i < TARGET_NSIG_WORDS; i++) { +       __get_user(target_set.sig[i], &frame->extramask[i - 1]); +    } +    target_to_host_sigset_internal(&set, &target_set); +    do_sigprocmask(SIG_SETMASK, &set, NULL); + +    restore_sigcontext(&frame->uc.tuc_mcontext, env); +    /* We got here through a sigreturn syscall, our path back is via an +       rtb insn so setup r14 for that.  */ +    env->regs[14] = env->sregs[SR_PC]; +  +    unlock_user_struct(frame, frame_addr, 0); +    return env->regs[10]; +  badframe: +    force_sig(TARGET_SIGSEGV); +} + +long do_rt_sigreturn(CPUMBState *env) +{ +    fprintf(stderr, "Microblaze do_rt_sigreturn: not implemented\n"); +    return -TARGET_ENOSYS; +} + +#elif defined(TARGET_CRIS) + +struct target_sigcontext { +        struct target_pt_regs regs;  /* needs to be first */ +        uint32_t oldmask; +        uint32_t usp;    /* usp before stacking this gunk on it */ +}; + +/* Signal frames. */ +struct target_signal_frame { +        struct target_sigcontext sc; +        uint32_t extramask[TARGET_NSIG_WORDS - 1]; +        uint16_t retcode[4];      /* Trampoline code. */ +}; + +struct rt_signal_frame { +        siginfo_t *pinfo; +        void *puc; +        siginfo_t info; +        struct ucontext uc; +        uint16_t retcode[4];      /* Trampoline code. */ +}; + +static void setup_sigcontext(struct target_sigcontext *sc, CPUCRISState *env) +{ +	__put_user(env->regs[0], &sc->regs.r0); +	__put_user(env->regs[1], &sc->regs.r1); +	__put_user(env->regs[2], &sc->regs.r2); +	__put_user(env->regs[3], &sc->regs.r3); +	__put_user(env->regs[4], &sc->regs.r4); +	__put_user(env->regs[5], &sc->regs.r5); +	__put_user(env->regs[6], &sc->regs.r6); +	__put_user(env->regs[7], &sc->regs.r7); +	__put_user(env->regs[8], &sc->regs.r8); +	__put_user(env->regs[9], &sc->regs.r9); +	__put_user(env->regs[10], &sc->regs.r10); +	__put_user(env->regs[11], &sc->regs.r11); +	__put_user(env->regs[12], &sc->regs.r12); +	__put_user(env->regs[13], &sc->regs.r13); +	__put_user(env->regs[14], &sc->usp); +	__put_user(env->regs[15], &sc->regs.acr); +	__put_user(env->pregs[PR_MOF], &sc->regs.mof); +	__put_user(env->pregs[PR_SRP], &sc->regs.srp); +	__put_user(env->pc, &sc->regs.erp); +} + +static void restore_sigcontext(struct target_sigcontext *sc, CPUCRISState *env) +{ +	__get_user(env->regs[0], &sc->regs.r0); +	__get_user(env->regs[1], &sc->regs.r1); +	__get_user(env->regs[2], &sc->regs.r2); +	__get_user(env->regs[3], &sc->regs.r3); +	__get_user(env->regs[4], &sc->regs.r4); +	__get_user(env->regs[5], &sc->regs.r5); +	__get_user(env->regs[6], &sc->regs.r6); +	__get_user(env->regs[7], &sc->regs.r7); +	__get_user(env->regs[8], &sc->regs.r8); +	__get_user(env->regs[9], &sc->regs.r9); +	__get_user(env->regs[10], &sc->regs.r10); +	__get_user(env->regs[11], &sc->regs.r11); +	__get_user(env->regs[12], &sc->regs.r12); +	__get_user(env->regs[13], &sc->regs.r13); +	__get_user(env->regs[14], &sc->usp); +	__get_user(env->regs[15], &sc->regs.acr); +	__get_user(env->pregs[PR_MOF], &sc->regs.mof); +	__get_user(env->pregs[PR_SRP], &sc->regs.srp); +	__get_user(env->pc, &sc->regs.erp); +} + +static abi_ulong get_sigframe(CPUCRISState *env, int framesize) +{ +	abi_ulong sp; +	/* Align the stack downwards to 4.  */ +	sp = (env->regs[R_SP] & ~3); +	return sp - framesize; +} + +static void setup_frame(int sig, struct target_sigaction *ka, +                        target_sigset_t *set, CPUCRISState *env) +{ +	struct target_signal_frame *frame; +	abi_ulong frame_addr; +	int i; + +	frame_addr = get_sigframe(env, sizeof *frame); +	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) +		goto badframe; + +	/* +	 * The CRIS signal return trampoline. A real linux/CRIS kernel doesn't +	 * use this trampoline anymore but it sets it up for GDB. +	 * In QEMU, using the trampoline simplifies things a bit so we use it. +	 * +	 * This is movu.w __NR_sigreturn, r9; break 13; +	 */ +    __put_user(0x9c5f, frame->retcode+0); +    __put_user(TARGET_NR_sigreturn, +               frame->retcode + 1); +    __put_user(0xe93d, frame->retcode + 2); + +	/* Save the mask.  */ +    __put_user(set->sig[0], &frame->sc.oldmask); + +    for(i = 1; i < TARGET_NSIG_WORDS; i++) { +        __put_user(set->sig[i], &frame->extramask[i - 1]); +    } + +	setup_sigcontext(&frame->sc, env); + +	/* Move the stack and setup the arguments for the handler.  */ +	env->regs[R_SP] = frame_addr; +	env->regs[10] = sig; +	env->pc = (unsigned long) ka->_sa_handler; +	/* Link SRP so the guest returns through the trampoline.  */ +	env->pregs[PR_SRP] = frame_addr + offsetof(typeof(*frame), retcode); + +	unlock_user_struct(frame, frame_addr, 1); +	return; +  badframe: +	force_sig(TARGET_SIGSEGV); +} + +static void setup_rt_frame(int sig, struct target_sigaction *ka, +                           target_siginfo_t *info, +                           target_sigset_t *set, CPUCRISState *env) +{ +    fprintf(stderr, "CRIS setup_rt_frame: not implemented\n"); +} + +long do_sigreturn(CPUCRISState *env) +{ +	struct target_signal_frame *frame; +	abi_ulong frame_addr; +	target_sigset_t target_set; +	sigset_t set; +	int i; + +	frame_addr = env->regs[R_SP]; +	/* Make sure the guest isn't playing games.  */ +	if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) +		goto badframe; + +	/* Restore blocked signals */ +    __get_user(target_set.sig[0], &frame->sc.oldmask); +	for(i = 1; i < TARGET_NSIG_WORDS; i++) { +        __get_user(target_set.sig[i], &frame->extramask[i - 1]); +	} +	target_to_host_sigset_internal(&set, &target_set); +        do_sigprocmask(SIG_SETMASK, &set, NULL); + +	restore_sigcontext(&frame->sc, env); +	unlock_user_struct(frame, frame_addr, 0); +	return env->regs[10]; +  badframe: +	force_sig(TARGET_SIGSEGV); +} + +long do_rt_sigreturn(CPUCRISState *env) +{ +    fprintf(stderr, "CRIS do_rt_sigreturn: not implemented\n"); +    return -TARGET_ENOSYS; +} + +#elif defined(TARGET_OPENRISC) + +struct target_sigcontext { +    struct target_pt_regs regs; +    abi_ulong oldmask; +    abi_ulong usp; +}; + +struct target_ucontext { +    abi_ulong tuc_flags; +    abi_ulong tuc_link; +    target_stack_t tuc_stack; +    struct target_sigcontext tuc_mcontext; +    target_sigset_t tuc_sigmask;   /* mask last for extensibility */ +}; + +struct target_rt_sigframe { +    abi_ulong pinfo; +    uint64_t puc; +    struct target_siginfo info; +    struct target_sigcontext sc; +    struct target_ucontext uc; +    unsigned char retcode[16];  /* trampoline code */ +}; + +/* This is the asm-generic/ucontext.h version */ +#if 0 +static int restore_sigcontext(CPUOpenRISCState *regs, +                              struct target_sigcontext *sc) +{ +    unsigned int err = 0; +    unsigned long old_usp; + +    /* Alwys make any pending restarted system call return -EINTR */ +    current_thread_info()->restart_block.fn = do_no_restart_syscall; + +    /* restore the regs from &sc->regs (same as sc, since regs is first) +     * (sc is already checked for VERIFY_READ since the sigframe was +     *  checked in sys_sigreturn previously) +     */ + +    if (copy_from_user(regs, &sc, sizeof(struct target_pt_regs))) { +        goto badframe; +    } + +    /* make sure the U-flag is set so user-mode cannot fool us */ + +    regs->sr &= ~SR_SM; + +    /* restore the old USP as it was before we stacked the sc etc. +     * (we cannot just pop the sigcontext since we aligned the sp and +     *  stuff after pushing it) +     */ + +    __get_user(old_usp, &sc->usp); +    phx_signal("old_usp 0x%lx", old_usp); + +    __PHX__ REALLY           /* ??? */ +    wrusp(old_usp); +    regs->gpr[1] = old_usp; + +    /* TODO: the other ports use regs->orig_XX to disable syscall checks +     * after this completes, but we don't use that mechanism. maybe we can +     * use it now ? +     */ + +    return err; + +badframe: +    return 1; +} +#endif + +/* Set up a signal frame.  */ + +static void setup_sigcontext(struct target_sigcontext *sc, +                            CPUOpenRISCState *regs, +                            unsigned long mask) +{ +    unsigned long usp = regs->gpr[1]; + +    /* copy the regs. they are first in sc so we can use sc directly */ + +    /*copy_to_user(&sc, regs, sizeof(struct target_pt_regs));*/ + +    /* Set the frametype to CRIS_FRAME_NORMAL for the execution of +       the signal handler. The frametype will be restored to its previous +       value in restore_sigcontext. */ +    /*regs->frametype = CRIS_FRAME_NORMAL;*/ + +    /* then some other stuff */ +    __put_user(mask, &sc->oldmask); +    __put_user(usp, &sc->usp); +} + +static inline unsigned long align_sigframe(unsigned long sp) +{ +    unsigned long i; +    i = sp & ~3UL; +    return i; +} + +static inline abi_ulong get_sigframe(struct target_sigaction *ka, +                                     CPUOpenRISCState *regs, +                                     size_t frame_size) +{ +    unsigned long sp = regs->gpr[1]; +    int onsigstack = on_sig_stack(sp); + +    /* redzone */ +    /* This is the X/Open sanctioned signal stack switching.  */ +    if ((ka->sa_flags & TARGET_SA_ONSTACK) != 0 && !onsigstack) { +        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; +    } + +    sp = align_sigframe(sp - frame_size); + +    /* +     * If we are on the alternate signal stack and would overflow it, don't. +     * Return an always-bogus address instead so we will die with SIGSEGV. +     */ + +    if (onsigstack && !likely(on_sig_stack(sp))) { +        return -1L; +    } + +    return sp; +} + +static void setup_frame(int sig, struct target_sigaction *ka, +                        target_sigset_t *set, CPUOpenRISCState *env) +{ +    qemu_log("Not implement.\n"); +} + +static void setup_rt_frame(int sig, struct target_sigaction *ka, +                           target_siginfo_t *info, +                           target_sigset_t *set, CPUOpenRISCState *env) +{ +    int err = 0; +    abi_ulong frame_addr; +    unsigned long return_ip; +    struct target_rt_sigframe *frame; +    abi_ulong info_addr, uc_addr; + +    frame_addr = get_sigframe(ka, env, sizeof(*frame)); +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { +        goto give_sigsegv; +    } + +    info_addr = frame_addr + offsetof(struct target_rt_sigframe, info); +    __put_user(info_addr, &frame->pinfo); +    uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc); +    __put_user(uc_addr, &frame->puc); + +    if (ka->sa_flags & SA_SIGINFO) { +        tswap_siginfo(&frame->info, info); +    } + +    /*err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));*/ +    __put_user(0, &frame->uc.tuc_flags); +    __put_user(0, &frame->uc.tuc_link); +    __put_user(target_sigaltstack_used.ss_sp, +               &frame->uc.tuc_stack.ss_sp); +    __put_user(sas_ss_flags(env->gpr[1]), &frame->uc.tuc_stack.ss_flags); +    __put_user(target_sigaltstack_used.ss_size, +               &frame->uc.tuc_stack.ss_size); +    setup_sigcontext(&frame->sc, env, set->sig[0]); + +    /*err |= copy_to_user(frame->uc.tuc_sigmask, set, sizeof(*set));*/ + +    /* trampoline - the desired return ip is the retcode itself */ +    return_ip = (unsigned long)&frame->retcode; +    /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */ +    __put_user(0xa960, (short *)(frame->retcode + 0)); +    __put_user(TARGET_NR_rt_sigreturn, (short *)(frame->retcode + 2)); +    __put_user(0x20000001, (unsigned long *)(frame->retcode + 4)); +    __put_user(0x15000000, (unsigned long *)(frame->retcode + 8)); + +    if (err) { +        goto give_sigsegv; +    } + +    /* TODO what is the current->exec_domain stuff and invmap ? */ + +    /* Set up registers for signal handler */ +    env->pc = (unsigned long)ka->_sa_handler; /* what we enter NOW */ +    env->gpr[9] = (unsigned long)return_ip;     /* what we enter LATER */ +    env->gpr[3] = (unsigned long)sig;           /* arg 1: signo */ +    env->gpr[4] = (unsigned long)&frame->info;  /* arg 2: (siginfo_t*) */ +    env->gpr[5] = (unsigned long)&frame->uc;    /* arg 3: ucontext */ + +    /* actually move the usp to reflect the stacked frame */ +    env->gpr[1] = (unsigned long)frame; + +    return; + +give_sigsegv: +    unlock_user_struct(frame, frame_addr, 1); +    if (sig == TARGET_SIGSEGV) { +        ka->_sa_handler = TARGET_SIG_DFL; +    } +    force_sig(TARGET_SIGSEGV); +} + +long do_sigreturn(CPUOpenRISCState *env) +{ + +    qemu_log("do_sigreturn: not implemented\n"); +    return -TARGET_ENOSYS; +} + +long do_rt_sigreturn(CPUOpenRISCState *env) +{ +    qemu_log("do_rt_sigreturn: not implemented\n"); +    return -TARGET_ENOSYS; +} +/* TARGET_OPENRISC */ + +#elif defined(TARGET_S390X) + +#define __NUM_GPRS 16 +#define __NUM_FPRS 16 +#define __NUM_ACRS 16 + +#define S390_SYSCALL_SIZE   2 +#define __SIGNAL_FRAMESIZE      160 /* FIXME: 31-bit mode -> 96 */ + +#define _SIGCONTEXT_NSIG        64 +#define _SIGCONTEXT_NSIG_BPW    64 /* FIXME: 31-bit mode -> 32 */ +#define _SIGCONTEXT_NSIG_WORDS  (_SIGCONTEXT_NSIG / _SIGCONTEXT_NSIG_BPW) +#define _SIGMASK_COPY_SIZE    (sizeof(unsigned long)*_SIGCONTEXT_NSIG_WORDS) +#define PSW_ADDR_AMODE            0x0000000000000000UL /* 0x80000000UL for 31-bit */ +#define S390_SYSCALL_OPCODE ((uint16_t)0x0a00) + +typedef struct { +    target_psw_t psw; +    target_ulong gprs[__NUM_GPRS]; +    unsigned int acrs[__NUM_ACRS]; +} target_s390_regs_common; + +typedef struct { +    unsigned int fpc; +    double   fprs[__NUM_FPRS]; +} target_s390_fp_regs; + +typedef struct { +    target_s390_regs_common regs; +    target_s390_fp_regs     fpregs; +} target_sigregs; + +struct target_sigcontext { +    target_ulong   oldmask[_SIGCONTEXT_NSIG_WORDS]; +    target_sigregs *sregs; +}; + +typedef struct { +    uint8_t callee_used_stack[__SIGNAL_FRAMESIZE]; +    struct target_sigcontext sc; +    target_sigregs sregs; +    int signo; +    uint8_t retcode[S390_SYSCALL_SIZE]; +} sigframe; + +struct target_ucontext { +    target_ulong tuc_flags; +    struct target_ucontext *tuc_link; +    target_stack_t tuc_stack; +    target_sigregs tuc_mcontext; +    target_sigset_t tuc_sigmask;   /* mask last for extensibility */ +}; + +typedef struct { +    uint8_t callee_used_stack[__SIGNAL_FRAMESIZE]; +    uint8_t retcode[S390_SYSCALL_SIZE]; +    struct target_siginfo info; +    struct target_ucontext uc; +} rt_sigframe; + +static inline abi_ulong +get_sigframe(struct target_sigaction *ka, CPUS390XState *env, size_t frame_size) +{ +    abi_ulong sp; + +    /* Default to using normal stack */ +    sp = env->regs[15]; + +    /* This is the X/Open sanctioned signal stack switching.  */ +    if (ka->sa_flags & TARGET_SA_ONSTACK) { +        if (!sas_ss_flags(sp)) { +            sp = target_sigaltstack_used.ss_sp + +                 target_sigaltstack_used.ss_size; +        } +    } + +    /* This is the legacy signal stack switching. */ +    else if (/* FIXME !user_mode(regs) */ 0 && +             !(ka->sa_flags & TARGET_SA_RESTORER) && +             ka->sa_restorer) { +        sp = (abi_ulong) ka->sa_restorer; +    } + +    return (sp - frame_size) & -8ul; +} + +static void save_sigregs(CPUS390XState *env, target_sigregs *sregs) +{ +    int i; +    //save_access_regs(current->thread.acrs); FIXME + +    /* Copy a 'clean' PSW mask to the user to avoid leaking +       information about whether PER is currently on.  */ +    __put_user(env->psw.mask, &sregs->regs.psw.mask); +    __put_user(env->psw.addr, &sregs->regs.psw.addr); +    for (i = 0; i < 16; i++) { +        __put_user(env->regs[i], &sregs->regs.gprs[i]); +    } +    for (i = 0; i < 16; i++) { +        __put_user(env->aregs[i], &sregs->regs.acrs[i]); +    } +    /* +     * We have to store the fp registers to current->thread.fp_regs +     * to merge them with the emulated registers. +     */ +    //save_fp_regs(¤t->thread.fp_regs); FIXME +    for (i = 0; i < 16; i++) { +        __put_user(get_freg(env, i)->ll, &sregs->fpregs.fprs[i]); +    } +} + +static void setup_frame(int sig, struct target_sigaction *ka, +                        target_sigset_t *set, CPUS390XState *env) +{ +    sigframe *frame; +    abi_ulong frame_addr; + +    frame_addr = get_sigframe(ka, env, sizeof(*frame)); +    qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__, +             (unsigned long long)frame_addr); +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { +            goto give_sigsegv; +    } + +    qemu_log("%s: 1\n", __FUNCTION__); +    __put_user(set->sig[0], &frame->sc.oldmask[0]); + +    save_sigregs(env, &frame->sregs); + +    __put_user((abi_ulong)(unsigned long)&frame->sregs, +               (abi_ulong *)&frame->sc.sregs); + +    /* Set up to return from userspace.  If provided, use a stub +       already in userspace.  */ +    if (ka->sa_flags & TARGET_SA_RESTORER) { +            env->regs[14] = (unsigned long) +                    ka->sa_restorer | PSW_ADDR_AMODE; +    } else { +            env->regs[14] = (unsigned long) +                    frame->retcode | PSW_ADDR_AMODE; +            __put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn, +                       (uint16_t *)(frame->retcode)); +    } + +    /* Set up backchain. */ +    __put_user(env->regs[15], (abi_ulong *) frame); + +    /* Set up registers for signal handler */ +    env->regs[15] = frame_addr; +    env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE; + +    env->regs[2] = sig; //map_signal(sig); +    env->regs[3] = frame_addr += offsetof(typeof(*frame), sc); + +    /* We forgot to include these in the sigcontext. +       To avoid breaking binary compatibility, they are passed as args. */ +    env->regs[4] = 0; // FIXME: no clue... current->thread.trap_no; +    env->regs[5] = 0; // FIXME: no clue... current->thread.prot_addr; + +    /* Place signal number on stack to allow backtrace from handler.  */ +    __put_user(env->regs[2], (int *) &frame->signo); +    unlock_user_struct(frame, frame_addr, 1); +    return; + +give_sigsegv: +    qemu_log("%s: give_sigsegv\n", __FUNCTION__); +    force_sig(TARGET_SIGSEGV); +} + +static void setup_rt_frame(int sig, struct target_sigaction *ka, +                           target_siginfo_t *info, +                           target_sigset_t *set, CPUS390XState *env) +{ +    int i; +    rt_sigframe *frame; +    abi_ulong frame_addr; + +    frame_addr = get_sigframe(ka, env, sizeof *frame); +    qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__, +             (unsigned long long)frame_addr); +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { +        goto give_sigsegv; +    } + +    qemu_log("%s: 1\n", __FUNCTION__); +    tswap_siginfo(&frame->info, info); + +    /* Create the ucontext.  */ +    __put_user(0, &frame->uc.tuc_flags); +    __put_user((abi_ulong)0, (abi_ulong *)&frame->uc.tuc_link); +    __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp); +    __put_user(sas_ss_flags(get_sp_from_cpustate(env)), +                      &frame->uc.tuc_stack.ss_flags); +    __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size); +    save_sigregs(env, &frame->uc.tuc_mcontext); +    for (i = 0; i < TARGET_NSIG_WORDS; i++) { +        __put_user((abi_ulong)set->sig[i], +        (abi_ulong *)&frame->uc.tuc_sigmask.sig[i]); +    } + +    /* Set up to return from userspace.  If provided, use a stub +       already in userspace.  */ +    if (ka->sa_flags & TARGET_SA_RESTORER) { +        env->regs[14] = (unsigned long) ka->sa_restorer | PSW_ADDR_AMODE; +    } else { +        env->regs[14] = (unsigned long) frame->retcode | PSW_ADDR_AMODE; +        __put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn, +                   (uint16_t *)(frame->retcode)); +    } + +    /* Set up backchain. */ +    __put_user(env->regs[15], (abi_ulong *) frame); + +    /* Set up registers for signal handler */ +    env->regs[15] = frame_addr; +    env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE; + +    env->regs[2] = sig; //map_signal(sig); +    env->regs[3] = frame_addr + offsetof(typeof(*frame), info); +    env->regs[4] = frame_addr + offsetof(typeof(*frame), uc); +    return; + +give_sigsegv: +    qemu_log("%s: give_sigsegv\n", __FUNCTION__); +    force_sig(TARGET_SIGSEGV); +} + +static int +restore_sigregs(CPUS390XState *env, target_sigregs *sc) +{ +    int err = 0; +    int i; + +    for (i = 0; i < 16; i++) { +        __get_user(env->regs[i], &sc->regs.gprs[i]); +    } + +    __get_user(env->psw.mask, &sc->regs.psw.mask); +    qemu_log("%s: sc->regs.psw.addr 0x%llx env->psw.addr 0x%llx\n", +             __FUNCTION__, (unsigned long long)sc->regs.psw.addr, +             (unsigned long long)env->psw.addr); +    __get_user(env->psw.addr, &sc->regs.psw.addr); +    /* FIXME: 31-bit -> | PSW_ADDR_AMODE */ + +    for (i = 0; i < 16; i++) { +        __get_user(env->aregs[i], &sc->regs.acrs[i]); +    } +    for (i = 0; i < 16; i++) { +        __get_user(get_freg(env, i)->ll, &sc->fpregs.fprs[i]); +    } + +    return err; +} + +long do_sigreturn(CPUS390XState *env) +{ +    sigframe *frame; +    abi_ulong frame_addr = env->regs[15]; +    qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__, +             (unsigned long long)frame_addr); +    target_sigset_t target_set; +    sigset_t set; + +    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { +        goto badframe; +    } +    __get_user(target_set.sig[0], &frame->sc.oldmask[0]); + +    target_to_host_sigset_internal(&set, &target_set); +    do_sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */ + +    if (restore_sigregs(env, &frame->sregs)) { +        goto badframe; +    } + +    unlock_user_struct(frame, frame_addr, 0); +    return env->regs[2]; + +badframe: +    force_sig(TARGET_SIGSEGV); +    return 0; +} + +long do_rt_sigreturn(CPUS390XState *env) +{ +    rt_sigframe *frame; +    abi_ulong frame_addr = env->regs[15]; +    qemu_log("%s: frame_addr 0x%llx\n", __FUNCTION__, +             (unsigned long long)frame_addr); +    sigset_t set; + +    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { +        goto badframe; +    } +    target_to_host_sigset(&set, &frame->uc.tuc_sigmask); + +    do_sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */ + +    if (restore_sigregs(env, &frame->uc.tuc_mcontext)) { +        goto badframe; +    } + +    if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0, +                       get_sp_from_cpustate(env)) == -EFAULT) { +        goto badframe; +    } +    unlock_user_struct(frame, frame_addr, 0); +    return env->regs[2]; + +badframe: +    unlock_user_struct(frame, frame_addr, 0); +    force_sig(TARGET_SIGSEGV); +    return 0; +} + +#elif defined(TARGET_PPC) + +/* Size of dummy stack frame allocated when calling signal handler. +   See arch/powerpc/include/asm/ptrace.h.  */ +#if defined(TARGET_PPC64) +#define SIGNAL_FRAMESIZE 128 +#else +#define SIGNAL_FRAMESIZE 64 +#endif + +/* See arch/powerpc/include/asm/ucontext.h.  Only used for 32-bit PPC; +   on 64-bit PPC, sigcontext and mcontext are one and the same.  */ +struct target_mcontext { +    target_ulong mc_gregs[48]; +    /* Includes fpscr.  */ +    uint64_t mc_fregs[33]; +    target_ulong mc_pad[2]; +    /* We need to handle Altivec and SPE at the same time, which no +       kernel needs to do.  Fortunately, the kernel defines this bit to +       be Altivec-register-large all the time, rather than trying to +       twiddle it based on the specific platform.  */ +    union { +        /* SPE vector registers.  One extra for SPEFSCR.  */ +        uint32_t spe[33]; +        /* Altivec vector registers.  The packing of VSCR and VRSAVE +           varies depending on whether we're PPC64 or not: PPC64 splits +           them apart; PPC32 stuffs them together.  */ +#if defined(TARGET_PPC64) +#define QEMU_NVRREG 34 +#else +#define QEMU_NVRREG 33 +#endif +        ppc_avr_t altivec[QEMU_NVRREG]; +#undef QEMU_NVRREG +    } mc_vregs __attribute__((__aligned__(16))); +}; + +/* See arch/powerpc/include/asm/sigcontext.h.  */ +struct target_sigcontext { +    target_ulong _unused[4]; +    int32_t signal; +#if defined(TARGET_PPC64) +    int32_t pad0; +#endif +    target_ulong handler; +    target_ulong oldmask; +    target_ulong regs;      /* struct pt_regs __user * */ +#if defined(TARGET_PPC64) +    struct target_mcontext mcontext; +#endif +}; + +/* Indices for target_mcontext.mc_gregs, below. +   See arch/powerpc/include/asm/ptrace.h for details.  */ +enum { +    TARGET_PT_R0 = 0, +    TARGET_PT_R1 = 1, +    TARGET_PT_R2 = 2, +    TARGET_PT_R3 = 3, +    TARGET_PT_R4 = 4, +    TARGET_PT_R5 = 5, +    TARGET_PT_R6 = 6, +    TARGET_PT_R7 = 7, +    TARGET_PT_R8 = 8, +    TARGET_PT_R9 = 9, +    TARGET_PT_R10 = 10, +    TARGET_PT_R11 = 11, +    TARGET_PT_R12 = 12, +    TARGET_PT_R13 = 13, +    TARGET_PT_R14 = 14, +    TARGET_PT_R15 = 15, +    TARGET_PT_R16 = 16, +    TARGET_PT_R17 = 17, +    TARGET_PT_R18 = 18, +    TARGET_PT_R19 = 19, +    TARGET_PT_R20 = 20, +    TARGET_PT_R21 = 21, +    TARGET_PT_R22 = 22, +    TARGET_PT_R23 = 23, +    TARGET_PT_R24 = 24, +    TARGET_PT_R25 = 25, +    TARGET_PT_R26 = 26, +    TARGET_PT_R27 = 27, +    TARGET_PT_R28 = 28, +    TARGET_PT_R29 = 29, +    TARGET_PT_R30 = 30, +    TARGET_PT_R31 = 31, +    TARGET_PT_NIP = 32, +    TARGET_PT_MSR = 33, +    TARGET_PT_ORIG_R3 = 34, +    TARGET_PT_CTR = 35, +    TARGET_PT_LNK = 36, +    TARGET_PT_XER = 37, +    TARGET_PT_CCR = 38, +    /* Yes, there are two registers with #39.  One is 64-bit only.  */ +    TARGET_PT_MQ = 39, +    TARGET_PT_SOFTE = 39, +    TARGET_PT_TRAP = 40, +    TARGET_PT_DAR = 41, +    TARGET_PT_DSISR = 42, +    TARGET_PT_RESULT = 43, +    TARGET_PT_REGS_COUNT = 44 +}; + + +struct target_ucontext { +    target_ulong tuc_flags; +    target_ulong tuc_link;    /* struct ucontext __user * */ +    struct target_sigaltstack tuc_stack; +#if !defined(TARGET_PPC64) +    int32_t tuc_pad[7]; +    target_ulong tuc_regs;    /* struct mcontext __user * +                                points to uc_mcontext field */ +#endif +    target_sigset_t tuc_sigmask; +#if defined(TARGET_PPC64) +    target_sigset_t unused[15]; /* Allow for uc_sigmask growth */ +    struct target_sigcontext tuc_sigcontext; +#else +    int32_t tuc_maskext[30]; +    int32_t tuc_pad2[3]; +    struct target_mcontext tuc_mcontext; +#endif +}; + +/* See arch/powerpc/kernel/signal_32.c.  */ +struct target_sigframe { +    struct target_sigcontext sctx; +    struct target_mcontext mctx; +    int32_t abigap[56]; +}; + +#if defined(TARGET_PPC64) + +#define TARGET_TRAMP_SIZE 6 + +struct target_rt_sigframe { +        /* sys_rt_sigreturn requires the ucontext be the first field */ +        struct target_ucontext uc; +        target_ulong  _unused[2]; +        uint32_t trampoline[TARGET_TRAMP_SIZE]; +        target_ulong pinfo; /* struct siginfo __user * */ +        target_ulong puc; /* void __user * */ +        struct target_siginfo info; +        /* 64 bit ABI allows for 288 bytes below sp before decrementing it. */ +        char abigap[288]; +} __attribute__((aligned(16))); + +#else + +struct target_rt_sigframe { +    struct target_siginfo info; +    struct target_ucontext uc; +    int32_t abigap[56]; +}; + +#endif + +#if defined(TARGET_PPC64) + +struct target_func_ptr { +    target_ulong entry; +    target_ulong toc; +}; + +#endif + +/* We use the mc_pad field for the signal return trampoline.  */ +#define tramp mc_pad + +/* See arch/powerpc/kernel/signal.c.  */ +static target_ulong get_sigframe(struct target_sigaction *ka, +                                 CPUPPCState *env, +                                 int frame_size) +{ +    target_ulong oldsp, newsp; + +    oldsp = env->gpr[1]; + +    if ((ka->sa_flags & TARGET_SA_ONSTACK) && +        (sas_ss_flags(oldsp) == 0)) { +        oldsp = (target_sigaltstack_used.ss_sp +                 + target_sigaltstack_used.ss_size); +    } + +    newsp = (oldsp - frame_size) & ~0xFUL; + +    return newsp; +} + +static void save_user_regs(CPUPPCState *env, struct target_mcontext *frame) +{ +    target_ulong msr = env->msr; +    int i; +    target_ulong ccr = 0; + +    /* In general, the kernel attempts to be intelligent about what it +       needs to save for Altivec/FP/SPE registers.  We don't care that +       much, so we just go ahead and save everything.  */ + +    /* Save general registers.  */ +    for (i = 0; i < ARRAY_SIZE(env->gpr); i++) { +       __put_user(env->gpr[i], &frame->mc_gregs[i]); +    } +    __put_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]); +    __put_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]); +    __put_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]); +    __put_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]); + +    for (i = 0; i < ARRAY_SIZE(env->crf); i++) { +        ccr |= env->crf[i] << (32 - ((i + 1) * 4)); +    } +    __put_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]); + +    /* Save Altivec registers if necessary.  */ +    if (env->insns_flags & PPC_ALTIVEC) { +        for (i = 0; i < ARRAY_SIZE(env->avr); i++) { +            ppc_avr_t *avr = &env->avr[i]; +            ppc_avr_t *vreg = &frame->mc_vregs.altivec[i]; + +            __put_user(avr->u64[0], &vreg->u64[0]); +            __put_user(avr->u64[1], &vreg->u64[1]); +        } +        /* Set MSR_VR in the saved MSR value to indicate that +           frame->mc_vregs contains valid data.  */ +        msr |= MSR_VR; +        __put_user((uint32_t)env->spr[SPR_VRSAVE], +                   &frame->mc_vregs.altivec[32].u32[3]); +    } + +    /* Save floating point registers.  */ +    if (env->insns_flags & PPC_FLOAT) { +        for (i = 0; i < ARRAY_SIZE(env->fpr); i++) { +            __put_user(env->fpr[i], &frame->mc_fregs[i]); +        } +        __put_user((uint64_t) env->fpscr, &frame->mc_fregs[32]); +    } + +    /* Save SPE registers.  The kernel only saves the high half.  */ +    if (env->insns_flags & PPC_SPE) { +#if defined(TARGET_PPC64) +        for (i = 0; i < ARRAY_SIZE(env->gpr); i++) { +            __put_user(env->gpr[i] >> 32, &frame->mc_vregs.spe[i]); +        } +#else +        for (i = 0; i < ARRAY_SIZE(env->gprh); i++) { +            __put_user(env->gprh[i], &frame->mc_vregs.spe[i]); +        } +#endif +        /* Set MSR_SPE in the saved MSR value to indicate that +           frame->mc_vregs contains valid data.  */ +        msr |= MSR_SPE; +        __put_user(env->spe_fscr, &frame->mc_vregs.spe[32]); +    } + +    /* Store MSR.  */ +    __put_user(msr, &frame->mc_gregs[TARGET_PT_MSR]); +} + +static void encode_trampoline(int sigret, uint32_t *tramp) +{ +    /* Set up the sigreturn trampoline: li r0,sigret; sc.  */ +    if (sigret) { +        __put_user(0x38000000 | sigret, &tramp[0]); +        __put_user(0x44000002, &tramp[1]); +    } +} + +static void restore_user_regs(CPUPPCState *env, +                              struct target_mcontext *frame, int sig) +{ +    target_ulong save_r2 = 0; +    target_ulong msr; +    target_ulong ccr; + +    int i; + +    if (!sig) { +        save_r2 = env->gpr[2]; +    } + +    /* Restore general registers.  */ +    for (i = 0; i < ARRAY_SIZE(env->gpr); i++) { +        __get_user(env->gpr[i], &frame->mc_gregs[i]); +    } +    __get_user(env->nip, &frame->mc_gregs[TARGET_PT_NIP]); +    __get_user(env->ctr, &frame->mc_gregs[TARGET_PT_CTR]); +    __get_user(env->lr, &frame->mc_gregs[TARGET_PT_LNK]); +    __get_user(env->xer, &frame->mc_gregs[TARGET_PT_XER]); +    __get_user(ccr, &frame->mc_gregs[TARGET_PT_CCR]); + +    for (i = 0; i < ARRAY_SIZE(env->crf); i++) { +        env->crf[i] = (ccr >> (32 - ((i + 1) * 4))) & 0xf; +    } + +    if (!sig) { +        env->gpr[2] = save_r2; +    } +    /* Restore MSR.  */ +    __get_user(msr, &frame->mc_gregs[TARGET_PT_MSR]); + +    /* If doing signal return, restore the previous little-endian mode.  */ +    if (sig) +        env->msr = (env->msr & ~MSR_LE) | (msr & MSR_LE); + +    /* Restore Altivec registers if necessary.  */ +    if (env->insns_flags & PPC_ALTIVEC) { +        for (i = 0; i < ARRAY_SIZE(env->avr); i++) { +            ppc_avr_t *avr = &env->avr[i]; +            ppc_avr_t *vreg = &frame->mc_vregs.altivec[i]; + +            __get_user(avr->u64[0], &vreg->u64[0]); +            __get_user(avr->u64[1], &vreg->u64[1]); +        } +        /* Set MSR_VEC in the saved MSR value to indicate that +           frame->mc_vregs contains valid data.  */ +        __get_user(env->spr[SPR_VRSAVE], +                   (target_ulong *)(&frame->mc_vregs.altivec[32].u32[3])); +    } + +    /* Restore floating point registers.  */ +    if (env->insns_flags & PPC_FLOAT) { +        uint64_t fpscr; +        for (i = 0; i < ARRAY_SIZE(env->fpr); i++) { +            __get_user(env->fpr[i], &frame->mc_fregs[i]); +        } +        __get_user(fpscr, &frame->mc_fregs[32]); +        env->fpscr = (uint32_t) fpscr; +    } + +    /* Save SPE registers.  The kernel only saves the high half.  */ +    if (env->insns_flags & PPC_SPE) { +#if defined(TARGET_PPC64) +        for (i = 0; i < ARRAY_SIZE(env->gpr); i++) { +            uint32_t hi; + +            __get_user(hi, &frame->mc_vregs.spe[i]); +            env->gpr[i] = ((uint64_t)hi << 32) | ((uint32_t) env->gpr[i]); +        } +#else +        for (i = 0; i < ARRAY_SIZE(env->gprh); i++) { +            __get_user(env->gprh[i], &frame->mc_vregs.spe[i]); +        } +#endif +        __get_user(env->spe_fscr, &frame->mc_vregs.spe[32]); +    } +} + +static void setup_frame(int sig, struct target_sigaction *ka, +                        target_sigset_t *set, CPUPPCState *env) +{ +    struct target_sigframe *frame; +    struct target_sigcontext *sc; +    target_ulong frame_addr, newsp; +    int err = 0; +#if defined(TARGET_PPC64) +    struct image_info *image = ((TaskState *)thread_cpu->opaque)->info; +#endif + +    frame_addr = get_sigframe(ka, env, sizeof(*frame)); +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 1)) +        goto sigsegv; +    sc = &frame->sctx; + +    __put_user(ka->_sa_handler, &sc->handler); +    __put_user(set->sig[0], &sc->oldmask); +#if TARGET_ABI_BITS == 64 +    __put_user(set->sig[0] >> 32, &sc->_unused[3]); +#else +    __put_user(set->sig[1], &sc->_unused[3]); +#endif +    __put_user(h2g(&frame->mctx), &sc->regs); +    __put_user(sig, &sc->signal); + +    /* Save user regs.  */ +    save_user_regs(env, &frame->mctx); + +    /* Construct the trampoline code on the stack. */ +    encode_trampoline(TARGET_NR_sigreturn, (uint32_t *)&frame->mctx.tramp); + +    /* The kernel checks for the presence of a VDSO here.  We don't +       emulate a vdso, so use a sigreturn system call.  */ +    env->lr = (target_ulong) h2g(frame->mctx.tramp); + +    /* Turn off all fp exceptions.  */ +    env->fpscr = 0; + +    /* Create a stack frame for the caller of the handler.  */ +    newsp = frame_addr - SIGNAL_FRAMESIZE; +    err |= put_user(env->gpr[1], newsp, target_ulong); + +    if (err) +        goto sigsegv; + +    /* Set up registers for signal handler.  */ +    env->gpr[1] = newsp; +    env->gpr[3] = sig; +    env->gpr[4] = frame_addr + offsetof(struct target_sigframe, sctx); + +#if defined(TARGET_PPC64) +    if (get_ppc64_abi(image) < 2) { +        /* ELFv1 PPC64 function pointers are pointers to OPD entries. */ +        struct target_func_ptr *handler = +            (struct target_func_ptr *)g2h(ka->_sa_handler); +        env->nip = tswapl(handler->entry); +        env->gpr[2] = tswapl(handler->toc); +    } else { +        /* ELFv2 PPC64 function pointers are entry points, but R12 +         * must also be set */ +        env->nip = tswapl((target_ulong) ka->_sa_handler); +        env->gpr[12] = env->nip; +    } +#else +    env->nip = (target_ulong) ka->_sa_handler; +#endif + +    /* Signal handlers are entered in big-endian mode.  */ +    env->msr &= ~MSR_LE; + +    unlock_user_struct(frame, frame_addr, 1); +    return; + +sigsegv: +    unlock_user_struct(frame, frame_addr, 1); +    qemu_log("segfaulting from setup_frame\n"); +    force_sig(TARGET_SIGSEGV); +} + +static void setup_rt_frame(int sig, struct target_sigaction *ka, +                           target_siginfo_t *info, +                           target_sigset_t *set, CPUPPCState *env) +{ +    struct target_rt_sigframe *rt_sf; +    uint32_t *trampptr = 0; +    struct target_mcontext *mctx = 0; +    target_ulong rt_sf_addr, newsp = 0; +    int i, err = 0; +#if defined(TARGET_PPC64) +    struct image_info *image = ((TaskState *)thread_cpu->opaque)->info; +#endif + +    rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf)); +    if (!lock_user_struct(VERIFY_WRITE, rt_sf, rt_sf_addr, 1)) +        goto sigsegv; + +    tswap_siginfo(&rt_sf->info, info); + +    __put_user(0, &rt_sf->uc.tuc_flags); +    __put_user(0, &rt_sf->uc.tuc_link); +    __put_user((target_ulong)target_sigaltstack_used.ss_sp, +               &rt_sf->uc.tuc_stack.ss_sp); +    __put_user(sas_ss_flags(env->gpr[1]), +               &rt_sf->uc.tuc_stack.ss_flags); +    __put_user(target_sigaltstack_used.ss_size, +               &rt_sf->uc.tuc_stack.ss_size); +#if !defined(TARGET_PPC64) +    __put_user(h2g (&rt_sf->uc.tuc_mcontext), +               &rt_sf->uc.tuc_regs); +#endif +    for(i = 0; i < TARGET_NSIG_WORDS; i++) { +        __put_user(set->sig[i], &rt_sf->uc.tuc_sigmask.sig[i]); +    } + +#if defined(TARGET_PPC64) +    mctx = &rt_sf->uc.tuc_sigcontext.mcontext; +    trampptr = &rt_sf->trampoline[0]; +#else +    mctx = &rt_sf->uc.tuc_mcontext; +    trampptr = (uint32_t *)&rt_sf->uc.tuc_mcontext.tramp; +#endif + +    save_user_regs(env, mctx); +    encode_trampoline(TARGET_NR_rt_sigreturn, trampptr); + +    /* The kernel checks for the presence of a VDSO here.  We don't +       emulate a vdso, so use a sigreturn system call.  */ +    env->lr = (target_ulong) h2g(trampptr); + +    /* Turn off all fp exceptions.  */ +    env->fpscr = 0; + +    /* Create a stack frame for the caller of the handler.  */ +    newsp = rt_sf_addr - (SIGNAL_FRAMESIZE + 16); +    err |= put_user(env->gpr[1], newsp, target_ulong); + +    if (err) +        goto sigsegv; + +    /* Set up registers for signal handler.  */ +    env->gpr[1] = newsp; +    env->gpr[3] = (target_ulong) sig; +    env->gpr[4] = (target_ulong) h2g(&rt_sf->info); +    env->gpr[5] = (target_ulong) h2g(&rt_sf->uc); +    env->gpr[6] = (target_ulong) h2g(rt_sf); + +#if defined(TARGET_PPC64) +    if (get_ppc64_abi(image) < 2) { +        /* ELFv1 PPC64 function pointers are pointers to OPD entries. */ +        struct target_func_ptr *handler = +            (struct target_func_ptr *)g2h(ka->_sa_handler); +        env->nip = tswapl(handler->entry); +        env->gpr[2] = tswapl(handler->toc); +    } else { +        /* ELFv2 PPC64 function pointers are entry points, but R12 +         * must also be set */ +        env->nip = tswapl((target_ulong) ka->_sa_handler); +        env->gpr[12] = env->nip; +    } +#else +    env->nip = (target_ulong) ka->_sa_handler; +#endif + +    /* Signal handlers are entered in big-endian mode.  */ +    env->msr &= ~MSR_LE; + +    unlock_user_struct(rt_sf, rt_sf_addr, 1); +    return; + +sigsegv: +    unlock_user_struct(rt_sf, rt_sf_addr, 1); +    qemu_log("segfaulting from setup_rt_frame\n"); +    force_sig(TARGET_SIGSEGV); + +} + +long do_sigreturn(CPUPPCState *env) +{ +    struct target_sigcontext *sc = NULL; +    struct target_mcontext *sr = NULL; +    target_ulong sr_addr = 0, sc_addr; +    sigset_t blocked; +    target_sigset_t set; + +    sc_addr = env->gpr[1] + SIGNAL_FRAMESIZE; +    if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) +        goto sigsegv; + +#if defined(TARGET_PPC64) +    set.sig[0] = sc->oldmask + ((uint64_t)(sc->_unused[3]) << 32); +#else +    __get_user(set.sig[0], &sc->oldmask); +    __get_user(set.sig[1], &sc->_unused[3]); +#endif +    target_to_host_sigset_internal(&blocked, &set); +    do_sigprocmask(SIG_SETMASK, &blocked, NULL); + +    __get_user(sr_addr, &sc->regs); +    if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1)) +        goto sigsegv; +    restore_user_regs(env, sr, 1); + +    unlock_user_struct(sr, sr_addr, 1); +    unlock_user_struct(sc, sc_addr, 1); +    return -TARGET_QEMU_ESIGRETURN; + +sigsegv: +    unlock_user_struct(sr, sr_addr, 1); +    unlock_user_struct(sc, sc_addr, 1); +    qemu_log("segfaulting from do_sigreturn\n"); +    force_sig(TARGET_SIGSEGV); +    return 0; +} + +/* See arch/powerpc/kernel/signal_32.c.  */ +static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig) +{ +    struct target_mcontext *mcp; +    target_ulong mcp_addr; +    sigset_t blocked; +    target_sigset_t set; + +    if (copy_from_user(&set, h2g(ucp) + offsetof(struct target_ucontext, tuc_sigmask), +                       sizeof (set))) +        return 1; + +#if defined(TARGET_PPC64) +    mcp_addr = h2g(ucp) + +        offsetof(struct target_ucontext, tuc_sigcontext.mcontext); +#else +    __get_user(mcp_addr, &ucp->tuc_regs); +#endif + +    if (!lock_user_struct(VERIFY_READ, mcp, mcp_addr, 1)) +        return 1; + +    target_to_host_sigset_internal(&blocked, &set); +    do_sigprocmask(SIG_SETMASK, &blocked, NULL); +    restore_user_regs(env, mcp, sig); + +    unlock_user_struct(mcp, mcp_addr, 1); +    return 0; +} + +long do_rt_sigreturn(CPUPPCState *env) +{ +    struct target_rt_sigframe *rt_sf = NULL; +    target_ulong rt_sf_addr; + +    rt_sf_addr = env->gpr[1] + SIGNAL_FRAMESIZE + 16; +    if (!lock_user_struct(VERIFY_READ, rt_sf, rt_sf_addr, 1)) +        goto sigsegv; + +    if (do_setcontext(&rt_sf->uc, env, 1)) +        goto sigsegv; + +    do_sigaltstack(rt_sf_addr +                   + offsetof(struct target_rt_sigframe, uc.tuc_stack), +                   0, env->gpr[1]); + +    unlock_user_struct(rt_sf, rt_sf_addr, 1); +    return -TARGET_QEMU_ESIGRETURN; + +sigsegv: +    unlock_user_struct(rt_sf, rt_sf_addr, 1); +    qemu_log("segfaulting from do_rt_sigreturn\n"); +    force_sig(TARGET_SIGSEGV); +    return 0; +} + +#elif defined(TARGET_M68K) + +struct target_sigcontext { +    abi_ulong  sc_mask; +    abi_ulong  sc_usp; +    abi_ulong  sc_d0; +    abi_ulong  sc_d1; +    abi_ulong  sc_a0; +    abi_ulong  sc_a1; +    unsigned short sc_sr; +    abi_ulong  sc_pc; +}; + +struct target_sigframe +{ +    abi_ulong pretcode; +    int sig; +    int code; +    abi_ulong psc; +    char retcode[8]; +    abi_ulong extramask[TARGET_NSIG_WORDS-1]; +    struct target_sigcontext sc; +}; +  +typedef int target_greg_t; +#define TARGET_NGREG 18 +typedef target_greg_t target_gregset_t[TARGET_NGREG]; + +typedef struct target_fpregset { +    int f_fpcntl[3]; +    int f_fpregs[8*3]; +} target_fpregset_t; + +struct target_mcontext { +    int version; +    target_gregset_t gregs; +    target_fpregset_t fpregs; +}; + +#define TARGET_MCONTEXT_VERSION 2 + +struct target_ucontext { +    abi_ulong tuc_flags; +    abi_ulong tuc_link; +    target_stack_t tuc_stack; +    struct target_mcontext tuc_mcontext; +    abi_long tuc_filler[80]; +    target_sigset_t tuc_sigmask; +}; + +struct target_rt_sigframe +{ +    abi_ulong pretcode; +    int sig; +    abi_ulong pinfo; +    abi_ulong puc; +    char retcode[8]; +    struct target_siginfo info; +    struct target_ucontext uc; +}; + +static void setup_sigcontext(struct target_sigcontext *sc, CPUM68KState *env, +        abi_ulong mask) +{ +    __put_user(mask, &sc->sc_mask); +    __put_user(env->aregs[7], &sc->sc_usp); +    __put_user(env->dregs[0], &sc->sc_d0); +    __put_user(env->dregs[1], &sc->sc_d1); +    __put_user(env->aregs[0], &sc->sc_a0); +    __put_user(env->aregs[1], &sc->sc_a1); +    __put_user(env->sr, &sc->sc_sr); +    __put_user(env->pc, &sc->sc_pc); +} + +static void +restore_sigcontext(CPUM68KState *env, struct target_sigcontext *sc, int *pd0) +{ +    int temp; + +    __get_user(env->aregs[7], &sc->sc_usp); +    __get_user(env->dregs[1], &sc->sc_d1); +    __get_user(env->aregs[0], &sc->sc_a0); +    __get_user(env->aregs[1], &sc->sc_a1); +    __get_user(env->pc, &sc->sc_pc); +    __get_user(temp, &sc->sc_sr); +    env->sr = (env->sr & 0xff00) | (temp & 0xff); + +    *pd0 = tswapl(sc->sc_d0); +} + +/* + * Determine which stack to use.. + */ +static inline abi_ulong +get_sigframe(struct target_sigaction *ka, CPUM68KState *regs, +             size_t frame_size) +{ +    unsigned long sp; + +    sp = regs->aregs[7]; + +    /* This is the X/Open sanctioned signal stack switching.  */ +    if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags (sp) == 0)) { +        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; +    } + +    return ((sp - frame_size) & -8UL); +} + +static void setup_frame(int sig, struct target_sigaction *ka, +                        target_sigset_t *set, CPUM68KState *env) +{ +    struct target_sigframe *frame; +    abi_ulong frame_addr; +    abi_ulong retcode_addr; +    abi_ulong sc_addr; +    int i; + +    frame_addr = get_sigframe(ka, env, sizeof *frame); +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) +	goto give_sigsegv; + +    __put_user(sig, &frame->sig); + +    sc_addr = frame_addr + offsetof(struct target_sigframe, sc); +    __put_user(sc_addr, &frame->psc); + +    setup_sigcontext(&frame->sc, env, set->sig[0]); + +    for(i = 1; i < TARGET_NSIG_WORDS; i++) { +        __put_user(set->sig[i], &frame->extramask[i - 1]); +    } + +    /* Set up to return from userspace.  */ + +    retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode); +    __put_user(retcode_addr, &frame->pretcode); + +    /* moveq #,d0; trap #0 */ + +    __put_user(0x70004e40 + (TARGET_NR_sigreturn << 16), +                      (uint32_t *)(frame->retcode)); + +    /* Set up to return from userspace */ + +    env->aregs[7] = frame_addr; +    env->pc = ka->_sa_handler; + +    unlock_user_struct(frame, frame_addr, 1); +    return; + +give_sigsegv: +    force_sig(TARGET_SIGSEGV); +} + +static inline int target_rt_setup_ucontext(struct target_ucontext *uc, +                                           CPUM68KState *env) +{ +    target_greg_t *gregs = uc->tuc_mcontext.gregs; + +    __put_user(TARGET_MCONTEXT_VERSION, &uc->tuc_mcontext.version); +    __put_user(env->dregs[0], &gregs[0]); +    __put_user(env->dregs[1], &gregs[1]); +    __put_user(env->dregs[2], &gregs[2]); +    __put_user(env->dregs[3], &gregs[3]); +    __put_user(env->dregs[4], &gregs[4]); +    __put_user(env->dregs[5], &gregs[5]); +    __put_user(env->dregs[6], &gregs[6]); +    __put_user(env->dregs[7], &gregs[7]); +    __put_user(env->aregs[0], &gregs[8]); +    __put_user(env->aregs[1], &gregs[9]); +    __put_user(env->aregs[2], &gregs[10]); +    __put_user(env->aregs[3], &gregs[11]); +    __put_user(env->aregs[4], &gregs[12]); +    __put_user(env->aregs[5], &gregs[13]); +    __put_user(env->aregs[6], &gregs[14]); +    __put_user(env->aregs[7], &gregs[15]); +    __put_user(env->pc, &gregs[16]); +    __put_user(env->sr, &gregs[17]); + +    return 0; +} +  +static inline int target_rt_restore_ucontext(CPUM68KState *env, +                                             struct target_ucontext *uc, +                                             int *pd0) +{ +    int temp; +    target_greg_t *gregs = uc->tuc_mcontext.gregs; +     +    __get_user(temp, &uc->tuc_mcontext.version); +    if (temp != TARGET_MCONTEXT_VERSION) +        goto badframe; + +    /* restore passed registers */ +    __get_user(env->dregs[0], &gregs[0]); +    __get_user(env->dregs[1], &gregs[1]); +    __get_user(env->dregs[2], &gregs[2]); +    __get_user(env->dregs[3], &gregs[3]); +    __get_user(env->dregs[4], &gregs[4]); +    __get_user(env->dregs[5], &gregs[5]); +    __get_user(env->dregs[6], &gregs[6]); +    __get_user(env->dregs[7], &gregs[7]); +    __get_user(env->aregs[0], &gregs[8]); +    __get_user(env->aregs[1], &gregs[9]); +    __get_user(env->aregs[2], &gregs[10]); +    __get_user(env->aregs[3], &gregs[11]); +    __get_user(env->aregs[4], &gregs[12]); +    __get_user(env->aregs[5], &gregs[13]); +    __get_user(env->aregs[6], &gregs[14]); +    __get_user(env->aregs[7], &gregs[15]); +    __get_user(env->pc, &gregs[16]); +    __get_user(temp, &gregs[17]); +    env->sr = (env->sr & 0xff00) | (temp & 0xff); + +    *pd0 = env->dregs[0]; +    return 0; + +badframe: +    return 1; +} + +static void setup_rt_frame(int sig, struct target_sigaction *ka, +                           target_siginfo_t *info, +                           target_sigset_t *set, CPUM68KState *env) +{ +    struct target_rt_sigframe *frame; +    abi_ulong frame_addr; +    abi_ulong retcode_addr; +    abi_ulong info_addr; +    abi_ulong uc_addr; +    int err = 0; +    int i; + +    frame_addr = get_sigframe(ka, env, sizeof *frame); +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) +	goto give_sigsegv; + +    __put_user(sig, &frame->sig); + +    info_addr = frame_addr + offsetof(struct target_rt_sigframe, info); +    __put_user(info_addr, &frame->pinfo); + +    uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc); +    __put_user(uc_addr, &frame->puc); + +    tswap_siginfo(&frame->info, info); + +    /* Create the ucontext */ + +    __put_user(0, &frame->uc.tuc_flags); +    __put_user(0, &frame->uc.tuc_link); +    __put_user(target_sigaltstack_used.ss_sp, +               &frame->uc.tuc_stack.ss_sp); +    __put_user(sas_ss_flags(env->aregs[7]), +               &frame->uc.tuc_stack.ss_flags); +    __put_user(target_sigaltstack_used.ss_size, +               &frame->uc.tuc_stack.ss_size); +    err |= target_rt_setup_ucontext(&frame->uc, env); + +    if (err) +            goto give_sigsegv; + +    for(i = 0; i < TARGET_NSIG_WORDS; i++) { +        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]); +    } + +    /* Set up to return from userspace.  */ + +    retcode_addr = frame_addr + offsetof(struct target_sigframe, retcode); +    __put_user(retcode_addr, &frame->pretcode); + +    /* moveq #,d0; notb d0; trap #0 */ + +    __put_user(0x70004600 + ((TARGET_NR_rt_sigreturn ^ 0xff) << 16), +               (uint32_t *)(frame->retcode + 0)); +    __put_user(0x4e40, (uint16_t *)(frame->retcode + 4)); + +    if (err) +        goto give_sigsegv; + +    /* Set up to return from userspace */ + +    env->aregs[7] = frame_addr; +    env->pc = ka->_sa_handler; + +    unlock_user_struct(frame, frame_addr, 1); +    return; + +give_sigsegv: +    unlock_user_struct(frame, frame_addr, 1); +    force_sig(TARGET_SIGSEGV); +} + +long do_sigreturn(CPUM68KState *env) +{ +    struct target_sigframe *frame; +    abi_ulong frame_addr = env->aregs[7] - 4; +    target_sigset_t target_set; +    sigset_t set; +    int d0, i; + +    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) +        goto badframe; + +    /* set blocked signals */ + +    __get_user(target_set.sig[0], &frame->sc.sc_mask); + +    for(i = 1; i < TARGET_NSIG_WORDS; i++) { +        __get_user(target_set.sig[i], &frame->extramask[i - 1]); +    } + +    target_to_host_sigset_internal(&set, &target_set); +    do_sigprocmask(SIG_SETMASK, &set, NULL); + +    /* restore registers */ + +    restore_sigcontext(env, &frame->sc, &d0); + +    unlock_user_struct(frame, frame_addr, 0); +    return d0; + +badframe: +    force_sig(TARGET_SIGSEGV); +    return 0; +} + +long do_rt_sigreturn(CPUM68KState *env) +{ +    struct target_rt_sigframe *frame; +    abi_ulong frame_addr = env->aregs[7] - 4; +    target_sigset_t target_set; +    sigset_t set; +    int d0; + +    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) +        goto badframe; + +    target_to_host_sigset_internal(&set, &target_set); +    do_sigprocmask(SIG_SETMASK, &set, NULL); + +    /* restore registers */ + +    if (target_rt_restore_ucontext(env, &frame->uc, &d0)) +        goto badframe; + +    if (do_sigaltstack(frame_addr + +                       offsetof(struct target_rt_sigframe, uc.tuc_stack), +                       0, get_sp_from_cpustate(env)) == -EFAULT) +        goto badframe; + +    unlock_user_struct(frame, frame_addr, 0); +    return d0; + +badframe: +    unlock_user_struct(frame, frame_addr, 0); +    force_sig(TARGET_SIGSEGV); +    return 0; +} + +#elif defined(TARGET_ALPHA) + +struct target_sigcontext { +    abi_long sc_onstack; +    abi_long sc_mask; +    abi_long sc_pc; +    abi_long sc_ps; +    abi_long sc_regs[32]; +    abi_long sc_ownedfp; +    abi_long sc_fpregs[32]; +    abi_ulong sc_fpcr; +    abi_ulong sc_fp_control; +    abi_ulong sc_reserved1; +    abi_ulong sc_reserved2; +    abi_ulong sc_ssize; +    abi_ulong sc_sbase; +    abi_ulong sc_traparg_a0; +    abi_ulong sc_traparg_a1; +    abi_ulong sc_traparg_a2; +    abi_ulong sc_fp_trap_pc; +    abi_ulong sc_fp_trigger_sum; +    abi_ulong sc_fp_trigger_inst; +}; + +struct target_ucontext { +    abi_ulong tuc_flags; +    abi_ulong tuc_link; +    abi_ulong tuc_osf_sigmask; +    target_stack_t tuc_stack; +    struct target_sigcontext tuc_mcontext; +    target_sigset_t tuc_sigmask; +}; + +struct target_sigframe { +    struct target_sigcontext sc; +    unsigned int retcode[3]; +}; + +struct target_rt_sigframe { +    target_siginfo_t info; +    struct target_ucontext uc; +    unsigned int retcode[3]; +}; + +#define INSN_MOV_R30_R16        0x47fe0410 +#define INSN_LDI_R0             0x201f0000 +#define INSN_CALLSYS            0x00000083 + +static void setup_sigcontext(struct target_sigcontext *sc, CPUAlphaState *env, +                            abi_ulong frame_addr, target_sigset_t *set) +{ +    int i; + +    __put_user(on_sig_stack(frame_addr), &sc->sc_onstack); +    __put_user(set->sig[0], &sc->sc_mask); +    __put_user(env->pc, &sc->sc_pc); +    __put_user(8, &sc->sc_ps); + +    for (i = 0; i < 31; ++i) { +        __put_user(env->ir[i], &sc->sc_regs[i]); +    } +    __put_user(0, &sc->sc_regs[31]); + +    for (i = 0; i < 31; ++i) { +        __put_user(env->fir[i], &sc->sc_fpregs[i]); +    } +    __put_user(0, &sc->sc_fpregs[31]); +    __put_user(cpu_alpha_load_fpcr(env), &sc->sc_fpcr); + +    __put_user(0, &sc->sc_traparg_a0); /* FIXME */ +    __put_user(0, &sc->sc_traparg_a1); /* FIXME */ +    __put_user(0, &sc->sc_traparg_a2); /* FIXME */ +} + +static void restore_sigcontext(CPUAlphaState *env, +                              struct target_sigcontext *sc) +{ +    uint64_t fpcr; +    int i; + +    __get_user(env->pc, &sc->sc_pc); + +    for (i = 0; i < 31; ++i) { +        __get_user(env->ir[i], &sc->sc_regs[i]); +    } +    for (i = 0; i < 31; ++i) { +        __get_user(env->fir[i], &sc->sc_fpregs[i]); +    } + +    __get_user(fpcr, &sc->sc_fpcr); +    cpu_alpha_store_fpcr(env, fpcr); +} + +static inline abi_ulong get_sigframe(struct target_sigaction *sa, +                                     CPUAlphaState *env, +                                     unsigned long framesize) +{ +    abi_ulong sp = env->ir[IR_SP]; + +    /* This is the X/Open sanctioned signal stack switching.  */ +    if ((sa->sa_flags & TARGET_SA_ONSTACK) != 0 && !sas_ss_flags(sp)) { +        sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; +    } +    return (sp - framesize) & -32; +} + +static void setup_frame(int sig, struct target_sigaction *ka, +                        target_sigset_t *set, CPUAlphaState *env) +{ +    abi_ulong frame_addr, r26; +    struct target_sigframe *frame; +    int err = 0; + +    frame_addr = get_sigframe(ka, env, sizeof(*frame)); +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { +        goto give_sigsegv; +    } + +    setup_sigcontext(&frame->sc, env, frame_addr, set); + +    if (ka->sa_restorer) { +        r26 = ka->sa_restorer; +    } else { +        __put_user(INSN_MOV_R30_R16, &frame->retcode[0]); +        __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn, +                   &frame->retcode[1]); +        __put_user(INSN_CALLSYS, &frame->retcode[2]); +        /* imb() */ +        r26 = frame_addr; +    } + +    unlock_user_struct(frame, frame_addr, 1); + +    if (err) { +    give_sigsegv: +        if (sig == TARGET_SIGSEGV) { +            ka->_sa_handler = TARGET_SIG_DFL; +        } +        force_sig(TARGET_SIGSEGV); +    } + +    env->ir[IR_RA] = r26; +    env->ir[IR_PV] = env->pc = ka->_sa_handler; +    env->ir[IR_A0] = sig; +    env->ir[IR_A1] = 0; +    env->ir[IR_A2] = frame_addr + offsetof(struct target_sigframe, sc); +    env->ir[IR_SP] = frame_addr; +} + +static void setup_rt_frame(int sig, struct target_sigaction *ka, +                           target_siginfo_t *info, +                           target_sigset_t *set, CPUAlphaState *env) +{ +    abi_ulong frame_addr, r26; +    struct target_rt_sigframe *frame; +    int i, err = 0; + +    frame_addr = get_sigframe(ka, env, sizeof(*frame)); +    if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) { +        goto give_sigsegv; +    } + +    tswap_siginfo(&frame->info, info); + +    __put_user(0, &frame->uc.tuc_flags); +    __put_user(0, &frame->uc.tuc_link); +    __put_user(set->sig[0], &frame->uc.tuc_osf_sigmask); +    __put_user(target_sigaltstack_used.ss_sp, +               &frame->uc.tuc_stack.ss_sp); +    __put_user(sas_ss_flags(env->ir[IR_SP]), +               &frame->uc.tuc_stack.ss_flags); +    __put_user(target_sigaltstack_used.ss_size, +               &frame->uc.tuc_stack.ss_size); +    setup_sigcontext(&frame->uc.tuc_mcontext, env, frame_addr, set); +    for (i = 0; i < TARGET_NSIG_WORDS; ++i) { +        __put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]); +    } + +    if (ka->sa_restorer) { +        r26 = ka->sa_restorer; +    } else { +        __put_user(INSN_MOV_R30_R16, &frame->retcode[0]); +        __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn, +                   &frame->retcode[1]); +        __put_user(INSN_CALLSYS, &frame->retcode[2]); +        /* imb(); */ +        r26 = frame_addr; +    } + +    if (err) { +    give_sigsegv: +       if (sig == TARGET_SIGSEGV) { +            ka->_sa_handler = TARGET_SIG_DFL; +        } +        force_sig(TARGET_SIGSEGV); +    } + +    env->ir[IR_RA] = r26; +    env->ir[IR_PV] = env->pc = ka->_sa_handler; +    env->ir[IR_A0] = sig; +    env->ir[IR_A1] = frame_addr + offsetof(struct target_rt_sigframe, info); +    env->ir[IR_A2] = frame_addr + offsetof(struct target_rt_sigframe, uc); +    env->ir[IR_SP] = frame_addr; +} + +long do_sigreturn(CPUAlphaState *env) +{ +    struct target_sigcontext *sc; +    abi_ulong sc_addr = env->ir[IR_A0]; +    target_sigset_t target_set; +    sigset_t set; + +    if (!lock_user_struct(VERIFY_READ, sc, sc_addr, 1)) { +        goto badframe; +    } + +    target_sigemptyset(&target_set); +    __get_user(target_set.sig[0], &sc->sc_mask); + +    target_to_host_sigset_internal(&set, &target_set); +    do_sigprocmask(SIG_SETMASK, &set, NULL); + +    restore_sigcontext(env, sc); +    unlock_user_struct(sc, sc_addr, 0); +    return env->ir[IR_V0]; + + badframe: +    force_sig(TARGET_SIGSEGV); +} + +long do_rt_sigreturn(CPUAlphaState *env) +{ +    abi_ulong frame_addr = env->ir[IR_A0]; +    struct target_rt_sigframe *frame; +    sigset_t set; + +    if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) { +        goto badframe; +    } +    target_to_host_sigset(&set, &frame->uc.tuc_sigmask); +    do_sigprocmask(SIG_SETMASK, &set, NULL); + +    restore_sigcontext(env, &frame->uc.tuc_mcontext); +    if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe, +                                             uc.tuc_stack), +                       0, env->ir[IR_SP]) == -EFAULT) { +        goto badframe; +    } + +    unlock_user_struct(frame, frame_addr, 0); +    return env->ir[IR_V0]; + + + badframe: +    unlock_user_struct(frame, frame_addr, 0); +    force_sig(TARGET_SIGSEGV); +} + +#else + +static void setup_frame(int sig, struct target_sigaction *ka, +			target_sigset_t *set, CPUArchState *env) +{ +    fprintf(stderr, "setup_frame: not implemented\n"); +} + +static void setup_rt_frame(int sig, struct target_sigaction *ka, +                           target_siginfo_t *info, +			   target_sigset_t *set, CPUArchState *env) +{ +    fprintf(stderr, "setup_rt_frame: not implemented\n"); +} + +long do_sigreturn(CPUArchState *env) +{ +    fprintf(stderr, "do_sigreturn: not implemented\n"); +    return -TARGET_ENOSYS; +} + +long do_rt_sigreturn(CPUArchState *env) +{ +    fprintf(stderr, "do_rt_sigreturn: not implemented\n"); +    return -TARGET_ENOSYS; +} + +#endif + +void process_pending_signals(CPUArchState *cpu_env) +{ +    CPUState *cpu = ENV_GET_CPU(cpu_env); +    int sig; +    abi_ulong handler; +    sigset_t set, old_set; +    target_sigset_t target_old_set; +    struct emulated_sigtable *k; +    struct target_sigaction *sa; +    struct sigqueue *q; +    TaskState *ts = cpu->opaque; + +    if (!ts->signal_pending) +        return; + +    /* FIXME: This is not threadsafe.  */ +    k = ts->sigtab; +    for(sig = 1; sig <= TARGET_NSIG; sig++) { +        if (k->pending) +            goto handle_signal; +        k++; +    } +    /* if no signal is pending, just return */ +    ts->signal_pending = 0; +    return; + + handle_signal: +#ifdef DEBUG_SIGNAL +    fprintf(stderr, "qemu: process signal %d\n", sig); +#endif +    /* dequeue signal */ +    q = k->first; +    k->first = q->next; +    if (!k->first) +        k->pending = 0; + +    sig = gdb_handlesig(cpu, sig); +    if (!sig) { +        sa = NULL; +        handler = TARGET_SIG_IGN; +    } else { +        sa = &sigact_table[sig - 1]; +        handler = sa->_sa_handler; +    } + +    if (ts->sigsegv_blocked && sig == TARGET_SIGSEGV) { +        /* Guest has blocked SIGSEGV but we got one anyway. Assume this +         * is a forced SIGSEGV (ie one the kernel handles via force_sig_info +         * because it got a real MMU fault), and treat as if default handler. +         */ +        handler = TARGET_SIG_DFL; +    } + +    if (handler == TARGET_SIG_DFL) { +        /* default handler : ignore some signal. The other are job control or fatal */ +        if (sig == TARGET_SIGTSTP || sig == TARGET_SIGTTIN || sig == TARGET_SIGTTOU) { +            kill(getpid(),SIGSTOP); +        } else if (sig != TARGET_SIGCHLD && +                   sig != TARGET_SIGURG && +                   sig != TARGET_SIGWINCH && +                   sig != TARGET_SIGCONT) { +            force_sig(sig); +        } +    } else if (handler == TARGET_SIG_IGN) { +        /* ignore sig */ +    } else if (handler == TARGET_SIG_ERR) { +        force_sig(sig); +    } else { +        /* compute the blocked signals during the handler execution */ +        target_to_host_sigset(&set, &sa->sa_mask); +        /* SA_NODEFER indicates that the current signal should not be +           blocked during the handler */ +        if (!(sa->sa_flags & TARGET_SA_NODEFER)) +            sigaddset(&set, target_to_host_signal(sig)); + +        /* block signals in the handler using Linux */ +        do_sigprocmask(SIG_BLOCK, &set, &old_set); +        /* save the previous blocked signal state to restore it at the +           end of the signal execution (see do_sigreturn) */ +        host_to_target_sigset_internal(&target_old_set, &old_set); + +        /* if the CPU is in VM86 mode, we restore the 32 bit values */ +#if defined(TARGET_I386) && !defined(TARGET_X86_64) +        { +            CPUX86State *env = cpu_env; +            if (env->eflags & VM_MASK) +                save_v86_state(env); +        } +#endif +        /* prepare the stack frame of the virtual CPU */ +#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) +        /* These targets do not have traditional signals.  */ +        setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env); +#else +        if (sa->sa_flags & TARGET_SA_SIGINFO) +            setup_rt_frame(sig, sa, &q->info, &target_old_set, cpu_env); +        else +            setup_frame(sig, sa, &target_old_set, cpu_env); +#endif +	if (sa->sa_flags & TARGET_SA_RESETHAND) +            sa->_sa_handler = TARGET_SIG_DFL; +    } +    if (q != &k->info) +        free_sigqueue(cpu_env, q); +} diff --git a/linux-user/socket.h b/linux-user/socket.h new file mode 100644 index 00000000..4dacae61 --- /dev/null +++ b/linux-user/socket.h @@ -0,0 +1,340 @@ + +#if defined(TARGET_MIPS) +    /* MIPS special values for constants */ + +    /* +     * For setsockopt(2) +     * +     * This defines are ABI conformant as far as Linux supports these ... +     */ +    #define TARGET_SOL_SOCKET      0xffff + +    #define TARGET_SO_DEBUG        0x0001  /* Record debugging information. */ +    #define TARGET_SO_REUSEADDR    0x0004  /* Allow reuse of local addresses. */ +    #define TARGET_SO_KEEPALIVE    0x0008  /* Keep connections alive and send +                                              SIGPIPE when they die. */ +    #define TARGET_SO_DONTROUTE    0x0010  /* Don't do local routing. */ +    #define TARGET_SO_BROADCAST    0x0020  /* Allow transmission of +                                              broadcast messages. */ +    #define TARGET_SO_LINGER       0x0080  /* Block on close of a reliable +                                            * socket to transmit pending data. +                                            */ +    #define TARGET_SO_OOBINLINE 0x0100     /* Receive out-of-band data in-band. +                                            */ +    #if 0 +    /* To add: Allow local address and port reuse. */ +    #define TARGET_SO_REUSEPORT 0x0200 +    #endif + +    #define TARGET_SO_TYPE         0x1008  /* Compatible name for SO_STYLE. */ +    #define TARGET_SO_STYLE        SO_TYPE /* Synonym */ +    #define TARGET_SO_ERROR        0x1007  /* get error status and clear */ +    #define TARGET_SO_SNDBUF       0x1001  /* Send buffer size. */ +    #define TARGET_SO_RCVBUF       0x1002  /* Receive buffer. */ +    #define TARGET_SO_SNDLOWAT     0x1003  /* send low-water mark */ +    #define TARGET_SO_RCVLOWAT     0x1004  /* receive low-water mark */ +    #define TARGET_SO_SNDTIMEO     0x1005  /* send timeout */ +    #define TARGET_SO_RCVTIMEO     0x1006  /* receive timeout */ +    #define TARGET_SO_ACCEPTCONN   0x1009 + +    /* linux-specific, might as well be the same as on i386 */ +    #define TARGET_SO_NO_CHECK     11 +    #define TARGET_SO_PRIORITY     12 +    #define TARGET_SO_BSDCOMPAT    14 + +    #define TARGET_SO_PASSCRED     17 +    #define TARGET_SO_PEERCRED     18 + +    /* Security levels - as per NRL IPv6 - don't actually do anything */ +    #define TARGET_SO_SECURITY_AUTHENTICATION              22 +    #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT        23 +    #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK          24 + +    #define TARGET_SO_BINDTODEVICE         25 + +    /* Socket filtering */ +    #define TARGET_SO_ATTACH_FILTER        26 +    #define TARGET_SO_DETACH_FILTER        27 + +    #define TARGET_SO_PEERNAME             28 +    #define TARGET_SO_TIMESTAMP            29 +    #define SCM_TIMESTAMP          SO_TIMESTAMP + +    #define TARGET_SO_PEERSEC              30 +    #define TARGET_SO_SNDBUFFORCE          31 +    #define TARGET_SO_RCVBUFFORCE          33 +    #define TARGET_SO_PASSSEC              34 + +    /** sock_type - Socket types +     * +     * Please notice that for binary compat reasons MIPS has to +     * override the enum sock_type in include/linux/net.h, so +     * we define ARCH_HAS_SOCKET_TYPES here. +     * +     * @SOCK_DGRAM - datagram (conn.less) socket +     * @SOCK_STREAM - stream (connection) socket +     * @SOCK_RAW - raw socket +     * @SOCK_RDM - reliably-delivered message +     * @SOCK_SEQPACKET - sequential packet socket +     * @SOCK_DCCP - Datagram Congestion Control Protocol socket +     * @SOCK_PACKET - linux specific way of getting packets at the dev level. +     *                For writing rarp and other similar things on the user +     *                level. +     * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag. +     * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag. +     */ + +    #define ARCH_HAS_SOCKET_TYPES          1 + +    enum sock_type { +           TARGET_SOCK_DGRAM       = 1, +           TARGET_SOCK_STREAM      = 2, +           TARGET_SOCK_RAW         = 3, +           TARGET_SOCK_RDM         = 4, +           TARGET_SOCK_SEQPACKET   = 5, +           TARGET_SOCK_DCCP        = 6, +           TARGET_SOCK_PACKET      = 10, +           TARGET_SOCK_CLOEXEC     = 02000000, +           TARGET_SOCK_NONBLOCK    = 0200, +    }; + +    #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1) +    #define TARGET_SOCK_TYPE_MASK    0xf  /* Covers up to TARGET_SOCK_MAX-1. */ + +#elif defined(TARGET_ALPHA) + +    /* For setsockopt(2) */ +    #define TARGET_SOL_SOCKET   0xffff + +    #define TARGET_SO_DEBUG 0x0001 +    #define TARGET_SO_REUSEADDR 0x0004 +    #define TARGET_SO_KEEPALIVE 0x0008 +    #define TARGET_SO_DONTROUTE 0x0010 +    #define TARGET_SO_BROADCAST 0x0020 +    #define TARGET_SO_LINGER    0x0080 +    #define TARGET_SO_OOBINLINE 0x0100 +    /* To add :#define TARGET_SO_REUSEPORT 0x0200 */ + +    #define TARGET_SO_TYPE      0x1008 +    #define TARGET_SO_ERROR 0x1007 +    #define TARGET_SO_SNDBUF    0x1001 +    #define TARGET_SO_RCVBUF    0x1002 +    #define TARGET_SO_SNDBUFFORCE   0x100a +    #define TARGET_SO_RCVBUFFORCE   0x100b +    #define TARGET_SO_RCVLOWAT  0x1010 +    #define TARGET_SO_SNDLOWAT  0x1011 +    #define TARGET_SO_RCVTIMEO  0x1012 +    #define TARGET_SO_SNDTIMEO  0x1013 +    #define TARGET_SO_ACCEPTCONN    0x1014 +    #define TARGET_SO_PROTOCOL  0x1028 +    #define TARGET_SO_DOMAIN    0x1029 + +    /* linux-specific, might as well be the same as on i386 */ +    #define TARGET_SO_NO_CHECK  11 +    #define TARGET_SO_PRIORITY  12 +    #define TARGET_SO_BSDCOMPAT 14 + +    #define TARGET_SO_PASSCRED  17 +    #define TARGET_SO_PEERCRED  18 +    #define TARGET_SO_BINDTODEVICE 25 + +    /* Socket filtering */ +    #define TARGET_SO_ATTACH_FILTER        26 +    #define TARGET_SO_DETACH_FILTER        27 + +    #define TARGET_SO_PEERNAME      28 +    #define TARGET_SO_TIMESTAMP     29 +    #define TARGET_SCM_TIMESTAMP        TARGET_SO_TIMESTAMP + +    #define TARGET_SO_PEERSEC       30 +    #define TARGET_SO_PASSSEC       34 +    #define TARGET_SO_TIMESTAMPNS       35 +    #define TARGET_SCM_TIMESTAMPNS      TARGET_SO_TIMESTAMPNS + +    /* Security levels - as per NRL IPv6 - don't actually do anything */ +    #define TARGET_SO_SECURITY_AUTHENTICATION       19 +    #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT 20 +    #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK       21 + +    #define TARGET_SO_MARK          36 + +    #define TARGET_SO_TIMESTAMPING      37 +    #define TARGET_SCM_TIMESTAMPING TARGET_SO_TIMESTAMPING + +    #define TARGET_SO_RXQ_OVFL             40 + +    #define TARGET_SO_WIFI_STATUS       41 +    #define TARGET_SCM_WIFI_STATUS      TARGET_SO_WIFI_STATUS +    #define TARGET_SO_PEEK_OFF      42 + +    /* Instruct lower device to use last 4-bytes of skb data as FCS */ +    #define TARGET_SO_NOFCS     43 + +    /** sock_type - Socket types +     * +     * Please notice that for binary compat reasons ALPHA has to +     * override the enum sock_type in include/linux/net.h, so +     * we define ARCH_HAS_SOCKET_TYPES here. +     * +     * @SOCK_DGRAM - datagram (conn.less) socket +     * @SOCK_STREAM - stream (connection) socket +     * @SOCK_RAW - raw socket +     * @SOCK_RDM - reliably-delivered message +     * @SOCK_SEQPACKET - sequential packet socket +     * @SOCK_DCCP - Datagram Congestion Control Protocol socket +     * @SOCK_PACKET - linux specific way of getting packets at the dev level. +     *                For writing rarp and other similar things on the user +     *                level. +     * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag. +     * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag. +     */ + +    #define ARCH_HAS_SOCKET_TYPES          1 + +    enum sock_type { +           TARGET_SOCK_STREAM      = 1, +           TARGET_SOCK_DGRAM       = 2, +           TARGET_SOCK_RAW         = 3, +           TARGET_SOCK_RDM         = 4, +           TARGET_SOCK_SEQPACKET   = 5, +           TARGET_SOCK_DCCP        = 6, +           TARGET_SOCK_PACKET      = 10, +           TARGET_SOCK_CLOEXEC     = 010000000, +           TARGET_SOCK_NONBLOCK    = 010000000000, +    }; + +    #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1) +    #define TARGET_SOCK_TYPE_MASK    0xf  /* Covers up to TARGET_SOCK_MAX-1. */ +#else + +#if defined(TARGET_SPARC) +    /** sock_type - Socket types +     * +     * Please notice that for binary compat reasons SPARC has to +     * override the enum sock_type in include/linux/net.h, so +     * we define ARCH_HAS_SOCKET_TYPES here. +     * +     * @SOCK_DGRAM - datagram (conn.less) socket +     * @SOCK_STREAM - stream (connection) socket +     * @SOCK_RAW - raw socket +     * @SOCK_RDM - reliably-delivered message +     * @SOCK_SEQPACKET - sequential packet socket +     * @SOCK_DCCP - Datagram Congestion Control Protocol socket +     * @SOCK_PACKET - linux specific way of getting packets at the dev level. +     *                For writing rarp and other similar things on the user +     *                level. +     * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag. +     * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag. +     */ + +    #define ARCH_HAS_SOCKET_TYPES          1 + +    enum sock_type { +           TARGET_SOCK_STREAM      = 1, +           TARGET_SOCK_DGRAM       = 2, +           TARGET_SOCK_RAW         = 3, +           TARGET_SOCK_RDM         = 4, +           TARGET_SOCK_SEQPACKET   = 5, +           TARGET_SOCK_DCCP        = 6, +           TARGET_SOCK_PACKET      = 10, +           TARGET_SOCK_CLOEXEC     = 020000000, +           TARGET_SOCK_NONBLOCK    = 040000, +    }; + +    #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1) +    #define TARGET_SOCK_TYPE_MASK    0xf  /* Covers up to TARGET_SOCK_MAX-1. */ + +    #define TARGET_SO_PASSSEC        31 +#else +    #define TARGET_SO_PASSSEC        34 +#endif + +    /* For setsockopt(2) */ +    #define TARGET_SOL_SOCKET      1 + +    #define TARGET_SO_DEBUG        1 +    #define TARGET_SO_REUSEADDR    2 +    #define TARGET_SO_TYPE         3 +    #define TARGET_SO_ERROR        4 +    #define TARGET_SO_DONTROUTE    5 +    #define TARGET_SO_BROADCAST    6 +    #define TARGET_SO_SNDBUF       7 +    #define TARGET_SO_RCVBUF       8 +    #define TARGET_SO_SNDBUFFORCE  32 +    #define TARGET_SO_RCVBUFFORCE  33 +    #define TARGET_SO_KEEPALIVE    9 +    #define TARGET_SO_OOBINLINE    10 +    #define TARGET_SO_NO_CHECK     11 +    #define TARGET_SO_PRIORITY     12 +    #define TARGET_SO_LINGER       13 +    #define TARGET_SO_BSDCOMPAT    14 +    /* To add :#define TARGET_SO_REUSEPORT 15 */ +#if defined(TARGET_PPC) +    #define TARGET_SO_RCVLOWAT     16 +    #define TARGET_SO_SNDLOWAT     17 +    #define TARGET_SO_RCVTIMEO     18 +    #define TARGET_SO_SNDTIMEO     19 +    #define TARGET_SO_PASSCRED     20 +    #define TARGET_SO_PEERCRED     21 +#else +    #define TARGET_SO_PASSCRED     16 +    #define TARGET_SO_PEERCRED     17 +    #define TARGET_SO_RCVLOWAT     18 +    #define TARGET_SO_SNDLOWAT     19 +    #define TARGET_SO_RCVTIMEO     20 +    #define TARGET_SO_SNDTIMEO     21 +#endif + +    /* Security levels - as per NRL IPv6 - don't actually do anything */ +    #define TARGET_SO_SECURITY_AUTHENTICATION              22 +    #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT        23 +    #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK          24 + +    #define TARGET_SO_BINDTODEVICE 25 + +    /* Socket filtering */ +    #define TARGET_SO_ATTACH_FILTER        26 +    #define TARGET_SO_DETACH_FILTER        27 + +    #define TARGET_SO_PEERNAME             28 +    #define TARGET_SO_TIMESTAMP            29 +    #define TARGET_SCM_TIMESTAMP           TARGET_SO_TIMESTAMP + +    #define TARGET_SO_ACCEPTCONN           30 + +    #define TARGET_SO_PEERSEC              31 + +#endif + +#ifndef ARCH_HAS_SOCKET_TYPES +    /** sock_type - Socket types - default values +     * +     * +     * @SOCK_STREAM - stream (connection) socket +     * @SOCK_DGRAM - datagram (conn.less) socket +     * @SOCK_RAW - raw socket +     * @SOCK_RDM - reliably-delivered message +     * @SOCK_SEQPACKET - sequential packet socket +     * @SOCK_DCCP - Datagram Congestion Control Protocol socket +     * @SOCK_PACKET - linux specific way of getting packets at the dev level. +     *                For writing rarp and other similar things on the user +     *                level. +     * @SOCK_CLOEXEC - sets the close-on-exec (FD_CLOEXEC) flag. +     * @SOCK_NONBLOCK - sets the O_NONBLOCK file status flag. +     */ +    enum sock_type { +           TARGET_SOCK_STREAM      = 1, +           TARGET_SOCK_DGRAM       = 2, +           TARGET_SOCK_RAW         = 3, +           TARGET_SOCK_RDM         = 4, +           TARGET_SOCK_SEQPACKET   = 5, +           TARGET_SOCK_DCCP        = 6, +           TARGET_SOCK_PACKET      = 10, +           TARGET_SOCK_CLOEXEC     = 02000000, +           TARGET_SOCK_NONBLOCK    = 04000, +    }; + +    #define TARGET_SOCK_MAX (TARGET_SOCK_PACKET + 1) +    #define TARGET_SOCK_TYPE_MASK    0xf  /* Covers up to TARGET_SOCK_MAX-1. */ + +#endif diff --git a/linux-user/sparc/syscall.h b/linux-user/sparc/syscall.h new file mode 100644 index 00000000..58573b92 --- /dev/null +++ b/linux-user/sparc/syscall.h @@ -0,0 +1,20 @@ +struct target_pt_regs { +	abi_ulong psr; +	abi_ulong pc; +	abi_ulong npc; +	abi_ulong y; +	abi_ulong u_regs[16]; +}; + +#define UNAME_MACHINE "sun4" +#define UNAME_MINIMUM_RELEASE "2.6.32" + +/* SPARC kernels don't define this in their Kconfig, but they have the + * same ABI as if they did, implemented by sparc-specific code which fishes + * directly in the u_regs() struct for half the parameters in sparc_do_fork() + * and copy_thread(). + */ +#define TARGET_CLONE_BACKWARDS +#define TARGET_MINSIGSTKSZ      4096 +#define TARGET_MLOCKALL_MCL_CURRENT 0x2000 +#define TARGET_MLOCKALL_MCL_FUTURE  0x4000 diff --git a/linux-user/sparc/syscall_nr.h b/linux-user/sparc/syscall_nr.h new file mode 100644 index 00000000..181cd326 --- /dev/null +++ b/linux-user/sparc/syscall_nr.h @@ -0,0 +1,311 @@ +#define TARGET_NR_exit                 1 /* Common                                      */ +#define TARGET_NR_fork                 2 /* Common                                      */ +#define TARGET_NR_read                 3 /* Common                                      */ +#define TARGET_NR_write                4 /* Common                                      */ +#define TARGET_NR_open                 5 /* Common                                      */ +#define TARGET_NR_close                6 /* Common                                      */ +#define TARGET_NR_wait4                7 /* Common                                      */ +#define TARGET_NR_creat                8 /* Common                                      */ +#define TARGET_NR_link                 9 /* Common                                      */ +#define TARGET_NR_unlink              10 /* Common                                      */ +#define TARGET_NR_execv               11 /* SunOS Specific                              */ +#define TARGET_NR_chdir               12 /* Common                                      */ +#define TARGET_NR_chown		 13 /* Common					   */ +#define TARGET_NR_mknod               14 /* Common                                      */ +#define TARGET_NR_chmod               15 /* Common                                      */ +#define TARGET_NR_lchown              16 /* Common                                      */ +#define TARGET_NR_brk                 17 /* Common                                      */ +#define TARGET_NR_perfctr             18 /* Performance counter operations              */ +#define TARGET_NR_lseek               19 /* Common                                      */ +#define TARGET_NR_getpid              20 /* Common                                      */ +#define TARGET_NR_capget		 21 /* Linux Specific				   */ +#define TARGET_NR_capset		 22 /* Linux Specific				   */ +#define TARGET_NR_setuid              23 /* Implemented via setreuid in SunOS           */ +#define TARGET_NR_getuid              24 /* Common                                      */ +#define TARGET_NR_ptrace              26 /* Common                                      */ +#define TARGET_NR_alarm               27 /* Implemented via setitimer in SunOS          */ +#define TARGET_NR_sigaltstack	 28 /* Common					   */ +#define TARGET_NR_pause               29 /* Is sigblock(0)->sigpause() in SunOS         */ +#define TARGET_NR_utime               30 /* Implemented via utimes() under SunOS        */ +#define TARGET_NR_lchown32            31 /* Linux sparc32 specific                      */ +#define TARGET_NR_fchown32            32 /* Linux sparc32 specific                      */ +#define TARGET_NR_access              33 /* Common                                      */ +#define TARGET_NR_nice                34 /* Implemented via get/setpriority() in SunOS  */ +#define TARGET_NR_chown32             35 /* Linux sparc32 specific                      */ +#define TARGET_NR_sync                36 /* Common                                      */ +#define TARGET_NR_kill                37 /* Common                                      */ +#define TARGET_NR_stat                38 /* Common                                      */ +#define TARGET_NR_sendfile		 39 /* Linux Specific				   */ +#define TARGET_NR_lstat               40 /* Common                                      */ +#define TARGET_NR_dup                 41 /* Common                                      */ +#define TARGET_NR_pipe                42 /* Common                                      */ +#define TARGET_NR_times               43 /* Implemented via getrusage() in SunOS        */ +#define TARGET_NR_getuid32            44 /* Linux sparc32 specific                      */ +#define TARGET_NR_umount2             45 /* Linux Specific                              */ +#define TARGET_NR_setgid              46 /* Implemented via setregid() in SunOS         */ +#define TARGET_NR_getgid              47 /* Common                                      */ +#define TARGET_NR_signal              48 /* Implemented via sigvec() in SunOS           */ +#define TARGET_NR_geteuid             49 /* SunOS calls getuid()                        */ +#define TARGET_NR_getegid             50 /* SunOS calls getgid()                        */ +#define TARGET_NR_acct                51 /* Common                                      */ +#define TARGET_NR_getgid32            53 /* Linux sparc32 specific                      */ +#define TARGET_NR_ioctl               54 /* Common                                      */ +#define TARGET_NR_reboot              55 /* Common                                      */ +#define TARGET_NR_mmap2		 56 /* Linux sparc32 Specific			   */ +#define TARGET_NR_symlink             57 /* Common                                      */ +#define TARGET_NR_readlink            58 /* Common                                      */ +#define TARGET_NR_execve              59 /* Common                                      */ +#define TARGET_NR_umask               60 /* Common                                      */ +#define TARGET_NR_chroot              61 /* Common                                      */ +#define TARGET_NR_fstat               62 /* Common                                      */ +#define TARGET_NR_fstat64		 63 /* Linux sparc32 Specific			   */ +#define TARGET_NR_getpagesize         64 /* Common                                      */ +#define TARGET_NR_msync               65 /* Common in newer 1.3.x revs...               */ +#define TARGET_NR_vfork               66 /* Common                                      */ +#define TARGET_NR_pread64             67 /* Linux Specific */ +#define TARGET_NR_pwrite64            68 /* Linux Specific */ +#define TARGET_NR_geteuid32           69 /* Linux sparc32, sbrk under SunOS             */ +#define TARGET_NR_getegid32           70 /* Linux sparc32, sstk under SunOS             */ +#define TARGET_NR_mmap                71 /* Common                                      */ +#define TARGET_NR_setreuid32          72 /* Linux sparc32, vadvise under SunOS          */ +#define TARGET_NR_munmap              73 /* Common                                      */ +#define TARGET_NR_mprotect            74 /* Common                                      */ +#define TARGET_NR_madvise             75 /* Common                                      */ +#define TARGET_NR_vhangup             76 /* Common                                      */ +#define TARGET_NR_truncate64		 77 /* Linux sparc32 Specific			   */ +#define TARGET_NR_mincore             78 /* Common                                      */ +#define TARGET_NR_getgroups           79 /* Common                                      */ +#define TARGET_NR_setgroups           80 /* Common                                      */ +#define TARGET_NR_getpgrp             81 /* Common                                      */ +#define TARGET_NR_setgroups32         82 /* Linux sparc32, setpgrp under SunOS          */ +#define TARGET_NR_setitimer           83 /* Common                                      */ +#define TARGET_NR_ftruncate64	 84 /* Linux sparc32 Specific			   */ +#define TARGET_NR_swapon              85 /* Common                                      */ +#define TARGET_NR_getitimer           86 /* Common                                      */ +#define TARGET_NR_setuid32            87 /* Linux sparc32, gethostname under SunOS      */ +#define TARGET_NR_sethostname         88 /* Common                                      */ +#define TARGET_NR_setgid32            89 /* Linux sparc32, getdtablesize under SunOS    */ +#define TARGET_NR_dup2                90 /* Common                                      */ +#define TARGET_NR_setfsuid32          91 /* Linux sparc32, getdopt under SunOS          */ +#define TARGET_NR_fcntl               92 /* Common                                      */ +#define TARGET_NR_select              93 /* Common                                      */ +#define TARGET_NR_setfsgid32          94 /* Linux sparc32, setdopt under SunOS          */ +#define TARGET_NR_fsync               95 /* Common                                      */ +#define TARGET_NR_setpriority         96 /* Common                                      */ +#define TARGET_NR_socket              97 /* Common                                      */ +#define TARGET_NR_connect             98 /* Common                                      */ +#define TARGET_NR_accept              99 /* Common                                      */ +#define TARGET_NR_getpriority        100 /* Common                                      */ +#define TARGET_NR_rt_sigreturn       101 /* Linux Specific                              */ +#define TARGET_NR_rt_sigaction       102 /* Linux Specific                              */ +#define TARGET_NR_rt_sigprocmask     103 /* Linux Specific                              */ +#define TARGET_NR_rt_sigpending      104 /* Linux Specific                              */ +#define TARGET_NR_rt_sigtimedwait    105 /* Linux Specific                              */ +#define TARGET_NR_rt_sigqueueinfo    106 /* Linux Specific                              */ +#define TARGET_NR_rt_sigsuspend      107 /* Linux Specific                              */ +#define TARGET_NR_setresuid32        108 /* Linux Specific, sigvec under SunOS	   */ +#define TARGET_NR_getresuid32        109 /* Linux Specific, sigblock under SunOS	   */ +#define TARGET_NR_setresgid32        110 /* Linux Specific, sigsetmask under SunOS	   */ +#define TARGET_NR_getresgid32        111 /* Linux Specific, sigpause under SunOS	   */ +#define TARGET_NR_setregid32         112 /* Linux sparc32, sigstack under SunOS         */ +#define TARGET_NR_recvmsg            113 /* Common                                      */ +#define TARGET_NR_sendmsg            114 /* Common                                      */ +#define TARGET_NR_getgroups32        115 /* Linux sparc32, vtrace under SunOS           */ +#define TARGET_NR_gettimeofday       116 /* Common                                      */ +#define TARGET_NR_getrusage          117 /* Common                                      */ +#define TARGET_NR_getsockopt         118 /* Common                                      */ +#define TARGET_NR_getcwd		119 /* Linux Specific				   */ +#define TARGET_NR_readv              120 /* Common                                      */ +#define TARGET_NR_writev             121 /* Common                                      */ +#define TARGET_NR_settimeofday       122 /* Common                                      */ +#define TARGET_NR_fchown             123 /* Common                                      */ +#define TARGET_NR_fchmod             124 /* Common                                      */ +#define TARGET_NR_recvfrom           125 /* Common                                      */ +#define TARGET_NR_setreuid           126 /* Common                                      */ +#define TARGET_NR_setregid           127 /* Common                                      */ +#define TARGET_NR_rename             128 /* Common                                      */ +#define TARGET_NR_truncate           129 /* Common                                      */ +#define TARGET_NR_ftruncate          130 /* Common                                      */ +#define TARGET_NR_flock              131 /* Common                                      */ +#define TARGET_NR_lstat64		132 /* Linux sparc32 Specific			   */ +#define TARGET_NR_sendto             133 /* Common                                      */ +#define TARGET_NR_shutdown           134 /* Common                                      */ +#define TARGET_NR_socketpair         135 /* Common                                      */ +#define TARGET_NR_mkdir              136 /* Common                                      */ +#define TARGET_NR_rmdir              137 /* Common                                      */ +#define TARGET_NR_utimes             138 /* SunOS Specific                              */ +#define TARGET_NR_stat64		139 /* Linux sparc32 Specific			   */ +#define TARGET_NR_getpeername        141 /* Common                                      */ +#define TARGET_NR_futex              142 /* gethostid under SunOS                       */ +#define TARGET_NR_gettid             143 /* ENOSYS under SunOS                          */ +#define TARGET_NR_getrlimit          144 /* Common                                      */ +#define TARGET_NR_setrlimit          145 /* Common                                      */ +#define TARGET_NR_pivot_root		146 /* Linux Specific, killpg under SunOS          */ +#define TARGET_NR_prctl		147 /* ENOSYS under SunOS                          */ +#define TARGET_NR_pciconfig_read	148 /* ENOSYS under SunOS                          */ +#define TARGET_NR_pciconfig_write	149 /* ENOSYS under SunOS                          */ +#define TARGET_NR_getsockname        150 /* Common                                      */ +#define TARGET_NR_poll               153 /* Common                                      */ +#define TARGET_NR_getdents64		154 /* Linux specific				   */ +#define TARGET_NR_fcntl64		155 /* Linux sparc32 Specific                      */ +#define TARGET_NR_statfs             157 /* Common                                      */ +#define TARGET_NR_fstatfs            158 /* Common                                      */ +#define TARGET_NR_umount             159 /* Common                                      */ +#define TARGET_NR_getdomainname      162 /* SunOS Specific                              */ +#define TARGET_NR_setdomainname      163 /* Common                                      */ +#define TARGET_NR_quotactl           165 /* Common                                      */ +#define TARGET_NR_set_tid_address    166 /* Linux specific, exportfs under SunOS        */ +#define TARGET_NR_mount              167 /* Common                                      */ +#define TARGET_NR_ustat              168 /* Common                                      */ +#define TARGET_NR_getdents           174 /* Common                                      */ +#define TARGET_NR_setsid             175 /* Common                                      */ +#define TARGET_NR_fchdir             176 /* Common                                      */ +#define TARGET_NR_sigpending         183 /* Common                                      */ +#define TARGET_NR_query_module	184 /* Linux Specific				   */ +#define TARGET_NR_setpgid            185 /* Common                                      */ +#define TARGET_NR_tkill              187 /* SunOS: fpathconf                            */ +#define TARGET_NR_exit_group	     188 /* Linux specific, sysconf undef SunOS         */ +#define TARGET_NR_uname              189 /* Linux Specific                              */ +#define TARGET_NR_init_module        190 /* Linux Specific                              */ +#define TARGET_NR_personality        191 /* Linux Specific                              */ +#define TARGET_NR_getppid            197 /* Linux Specific                              */ +#define TARGET_NR_sigaction          198 /* Linux Specific                              */ +#define TARGET_NR_sgetmask           199 /* Linux Specific                              */ +#define TARGET_NR_ssetmask           200 /* Linux Specific                              */ +#define TARGET_NR_sigsuspend         201 /* Linux Specific                              */ +#define TARGET_NR_oldlstat           202 /* Linux Specific                              */ +#define TARGET_NR_uselib             203 /* Linux Specific                              */ +#define TARGET_NR_readdir            204 /* Linux Specific                              */ +#define TARGET_NR_readahead          205 /* Linux Specific                              */ +#define TARGET_NR_socketcall         206 /* Linux Specific                              */ +#define TARGET_NR_syslog             207 /* Linux Specific                              */ +#define TARGET_NR_tgkill             211 /* Linux Specific                              */ +#define TARGET_NR_waitpid            212 /* Linux Specific                              */ +#define TARGET_NR_swapoff            213 /* Linux Specific                              */ +#define TARGET_NR_sysinfo            214 /* Linux Specific                              */ +#define TARGET_NR_ipc                215 /* Linux Specific                              */ +#define TARGET_NR_sigreturn          216 /* Linux Specific                              */ +#define TARGET_NR_clone              217 /* Linux Specific                              */ +#define TARGET_NR_adjtimex           219 /* Linux Specific                              */ +#define TARGET_NR_sigprocmask        220 /* Linux Specific                              */ +#define TARGET_NR_create_module      221 /* Linux Specific                              */ +#define TARGET_NR_delete_module      222 /* Linux Specific                              */ +#define TARGET_NR_get_kernel_syms    223 /* Linux Specific                              */ +#define TARGET_NR_getpgid            224 /* Linux Specific                              */ +#define TARGET_NR_bdflush            225 /* Linux Specific                              */ +#define TARGET_NR_sysfs              226 /* Linux Specific                              */ +#define TARGET_NR_afs_syscall        227 /* Linux Specific                              */ +#define TARGET_NR_setfsuid           228 /* Linux Specific                              */ +#define TARGET_NR_setfsgid           229 /* Linux Specific                              */ +#define TARGET_NR__newselect         230 /* Linux Specific                              */ +#define TARGET_NR_time               231 /* Linux Specific                              */ +#define TARGET_NR_stime              233 /* Linux Specific                              */ +#define TARGET_NR_statfs64           234 /* Linux Specific                              */ +#define TARGET_NR_fstatfs64          235 /* Linux Specific                              */ +#define TARGET_NR__llseek            236 /* Linux Specific                              */ +#define TARGET_NR_mlock              237 +#define TARGET_NR_munlock            238 +#define TARGET_NR_mlockall           239 +#define TARGET_NR_munlockall         240 +#define TARGET_NR_sched_setparam     241 +#define TARGET_NR_sched_getparam     242 +#define TARGET_NR_sched_setscheduler 243 +#define TARGET_NR_sched_getscheduler 244 +#define TARGET_NR_sched_yield        245 +#define TARGET_NR_sched_get_priority_max 246 +#define TARGET_NR_sched_get_priority_min 247 +#define TARGET_NR_sched_rr_get_interval  248 +#define TARGET_NR_nanosleep          249 +#define TARGET_NR_mremap             250 +#define TARGET_NR__sysctl            251 +#define TARGET_NR_getsid             252 +#define TARGET_NR_fdatasync          253 +#define TARGET_NR_nfsservctl         254 +#define TARGET_NR_aplib              255 +#define TARGET_NR_clock_settime	256 +#define TARGET_NR_clock_gettime	257 +#define TARGET_NR_clock_getres	258 +#define TARGET_NR_clock_nanosleep	259 +#define TARGET_NR_sched_getaffinity	260 +#define TARGET_NR_sched_setaffinity	261 +#define TARGET_NR_timer_settime	262 +#define TARGET_NR_timer_gettime	263 +#define TARGET_NR_timer_getoverrun	264 +#define TARGET_NR_timer_delete	265 +#define TARGET_NR_timer_create	266 +/* #define TARGET_NR_vserver		267 Reserved for VSERVER */ +#define TARGET_NR_io_setup		268 +#define TARGET_NR_io_destroy		269 +#define TARGET_NR_io_submit		270 +#define TARGET_NR_io_cancel		271 +#define TARGET_NR_io_getevents	272 +#define TARGET_NR_mq_open		273 +#define TARGET_NR_mq_unlink		274 +#define TARGET_NR_mq_timedsend	275 +#define TARGET_NR_mq_timedreceive	276 +#define TARGET_NR_mq_notify		277 +#define TARGET_NR_mq_getsetattr	278 +#define TARGET_NR_waitid		279 +#define TARGET_NR_tee		280 +#define TARGET_NR_add_key		281 +#define TARGET_NR_request_key	282 +#define TARGET_NR_keyctl		283 +#define TARGET_NR_openat		284 +#define TARGET_NR_mkdirat		285 +#define TARGET_NR_mknodat		286 +#define TARGET_NR_fchownat		287 +#define TARGET_NR_futimesat		288 +#define TARGET_NR_fstatat64		289 +#define TARGET_NR_unlinkat		290 +#define TARGET_NR_renameat		291 +#define TARGET_NR_linkat		292 +#define TARGET_NR_symlinkat		293 +#define TARGET_NR_readlinkat		294 +#define TARGET_NR_fchmodat		295 +#define TARGET_NR_faccessat		296 +#define TARGET_NR_pselect6		297 +#define TARGET_NR_ppoll		298 +#define TARGET_NR_unshare		299 +#define TARGET_NR_set_robust_list	300 +#define TARGET_NR_get_robust_list	301 +#define TARGET_NR_migrate_pages	302 +#define TARGET_NR_mbind		303 +#define TARGET_NR_get_mempolicy	304 +#define TARGET_NR_set_mempolicy	305 +#define TARGET_NR_kexec_load		306 +#define TARGET_NR_move_pages		307 +#define TARGET_NR_getcpu		308 +#define TARGET_NR_epoll_pwait	309 +#define TARGET_NR_utimensat		310 +#define TARGET_NR_signalfd		311 +#define TARGET_NR_timerfd		312 +#define TARGET_NR_eventfd		313 +#define TARGET_NR_fallocate		314 +#define TARGET_NR_timerfd_settime	315 +#define TARGET_NR_timerfd_gettime	316 +#define TARGET_NR_signalfd4		317 +#define TARGET_NR_eventfd2		318 +#define TARGET_NR_epoll_create1	319 +#define TARGET_NR_dup3			320 +#define TARGET_NR_pipe2		321 +#define TARGET_NR_inotify_init1	322 +#define TARGET_NR_accept4		323 +#define TARGET_NR_preadv                324 +#define TARGET_NR_pwritev               325 +#define TARGET_NR_rt_tgsigqueueinfo     326 +#define TARGET_NR_perf_event_open       327 +#define TARGET_NR_recvmmsg              328 +#define TARGET_NR_fanotify_init         329 +#define TARGET_NR_fanotify_mark         330 +#define TARGET_NR_prlimit64             331 +#define TARGET_NR_name_to_handle_at     332 +#define TARGET_NR_open_by_handle_at     333 +#define TARGET_NR_clock_adjtime         334 +#define TARGET_NR_syncfs                335 +#define TARGET_NR_sendmmsg              336 +#define TARGET_NR_setns                 337 +#define TARGET_NR_process_vm_readv      338 +#define TARGET_NR_process_vm_writev     339 +#define TARGET_NR_kern_features         340 +#define TARGET_NR_kcmp                  341 +#define TARGET_NR_finit_module          342 diff --git a/linux-user/sparc/target_cpu.h b/linux-user/sparc/target_cpu.h new file mode 100644 index 00000000..4944d465 --- /dev/null +++ b/linux-user/sparc/target_cpu.h @@ -0,0 +1,44 @@ +/* + * SPARC specific CPU ABI and functions for linux-user + * + * Copyright (C) 2003 Thomas M. Ogrisegg <tom@fnord.at> + * Copyright (C) 2003-2005 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUSPARCState *env, target_ulong newsp) +{ +    if (newsp) { +        env->regwptr[22] = newsp; +    } +    /* syscall return for clone child: 0, and clear CF since +     * this counts as a success return value. +     */ +    env->regwptr[0] = 0; +#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) +    env->xcc &= ~PSR_CARRY; +#else +    env->psr &= ~PSR_CARRY; +#endif +} + +static inline void cpu_set_tls(CPUSPARCState *env, target_ulong newtls) +{ +    env->gregs[7] = newtls; +} + +#endif diff --git a/linux-user/sparc/target_signal.h b/linux-user/sparc/target_signal.h new file mode 100644 index 00000000..c7de300c --- /dev/null +++ b/linux-user/sparc/target_signal.h @@ -0,0 +1,36 @@ +#ifndef TARGET_SIGNAL_H +#define TARGET_SIGNAL_H + +#include "cpu.h" + +/* this struct defines a stack used during syscall handling */ + +typedef struct target_sigaltstack { +	abi_ulong ss_sp; +	abi_long ss_flags; +	abi_ulong ss_size; +} target_stack_t; + + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK	1 +#define TARGET_SS_DISABLE	2 + +#define TARGET_MINSIGSTKSZ	4096 +#define TARGET_SIGSTKSZ		16384 + +#ifndef UREG_I6 +#define UREG_I6        6 +#endif +#ifndef UREG_FP +#define UREG_FP        UREG_I6 +#endif + +static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state) +{ +    return state->regwptr[UREG_FP]; +} + +#endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/sparc/target_structs.h b/linux-user/sparc/target_structs.h new file mode 100644 index 00000000..c139e09a --- /dev/null +++ b/linux-user/sparc/target_structs.h @@ -0,0 +1,63 @@ +/* + * SPARC specific structures for linux-user + * + * Copyright (c) 2013 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_STRUCTS_H +#define TARGET_STRUCTS_H + +struct target_ipc_perm { +    abi_int __key;                      /* Key.  */ +    abi_uint uid;                       /* Owner's user ID.  */ +    abi_uint gid;                       /* Owner's group ID.  */ +    abi_uint cuid;                      /* Creator's user ID.  */ +    abi_uint cgid;                      /* Creator's group ID.  */ +#if TARGET_ABI_BITS == 32 +    abi_ushort __pad1; +    abi_ushort mode;                    /* Read/write permission.  */ +    abi_ushort __pad2; +#else +    abi_ushort mode; +    abi_ushort __pad1; +#endif +    abi_ushort __seq;                   /* Sequence number.  */ +    uint64_t __unused1; +    uint64_t __unused2; +}; + +struct target_shmid_ds { +    struct target_ipc_perm shm_perm;    /* operation permission struct */ +#if TARGET_ABI_BITS == 32 +    abi_uint __pad1; +#endif +    abi_ulong shm_atime;                /* time of last shmat() */ +#if TARGET_ABI_BITS == 32 +    abi_uint __pad2; +#endif +    abi_ulong shm_dtime;                /* time of last shmdt() */ +#if TARGET_ABI_BITS == 32 +    abi_uint __pad3; +#endif +    abi_ulong shm_ctime;                /* time of last change by shmctl() */ +    abi_long shm_segsz;                 /* size of segment in bytes */ +    abi_ulong shm_cpid;                 /* pid of creator */ +    abi_ulong shm_lpid;                 /* pid of last shmop */ +    abi_long shm_nattch;                /* number of current attaches */ +    abi_ulong __unused1; +    abi_ulong __unused2; +}; + +#endif diff --git a/linux-user/sparc/termbits.h b/linux-user/sparc/termbits.h new file mode 100644 index 00000000..691600d2 --- /dev/null +++ b/linux-user/sparc/termbits.h @@ -0,0 +1,279 @@ +/* from asm/termbits.h */ + +#define TARGET_NCCS 19 + +struct target_termios { +    unsigned int c_iflag;               /* input mode flags */ +    unsigned int c_oflag;               /* output mode flags */ +    unsigned int c_cflag;               /* control mode flags */ +    unsigned int c_lflag;               /* local mode flags */ +    unsigned char c_line;                    /* line discipline */ +    unsigned char c_cc[TARGET_NCCS];                /* control characters */ +}; + +/* c_cc characters */ +#define TARGET_VINTR    0 +#define TARGET_VQUIT    1 +#define TARGET_VERASE   2 +#define TARGET_VKILL    3 +#define TARGET_VEOF     4 +#define TARGET_VEOL     5 +#define TARGET_VEOL2    6 +#define TARGET_VSWTC    7 +#define TARGET_VSTART   8 +#define TARGET_VSTOP    9 + +#define TARGET_VSUSP    10 +#define TARGET_VDSUSP   11  /* SunOS POSIX nicety I do believe... */ +#define TARGET_VREPRINT 12 +#define TARGET_VDISCARD 13 +#define TARGET_VWERASE  14 +#define TARGET_VLNEXT   15 + +/* Kernel keeps vmin/vtime separated, user apps assume vmin/vtime is + * shared with eof/eol + */ +#define TARGET_VMIN     TARGET_VEOF +#define TARGET_VTIME    TARGET_VEOL + +/* c_iflag bits */ +#define TARGET_IGNBRK	0x00000001 +#define TARGET_BRKINT	0x00000002 +#define TARGET_IGNPAR	0x00000004 +#define TARGET_PARMRK	0x00000008 +#define TARGET_INPCK	0x00000010 +#define TARGET_ISTRIP	0x00000020 +#define TARGET_INLCR	0x00000040 +#define TARGET_IGNCR	0x00000080 +#define TARGET_ICRNL	0x00000100 +#define TARGET_IUCLC	0x00000200 +#define TARGET_IXON	0x00000400 +#define TARGET_IXANY	0x00000800 +#define TARGET_IXOFF	0x00001000 +#define TARGET_IMAXBEL	0x00002000 +#define TARGET_IUTF8	0x00004000 + +/* c_oflag bits */ +#define TARGET_OPOST	0x00000001 +#define TARGET_OLCUC	0x00000002 +#define TARGET_ONLCR	0x00000004 +#define TARGET_OCRNL	0x00000008 +#define TARGET_ONOCR	0x00000010 +#define TARGET_ONLRET	0x00000020 +#define TARGET_OFILL	0x00000040 +#define TARGET_OFDEL	0x00000080 +#define TARGET_NLDLY	0x00000100 +#define   TARGET_NL0	0x00000000 +#define   TARGET_NL1	0x00000100 +#define TARGET_CRDLY	0x00000600 +#define   TARGET_CR0	0x00000000 +#define   TARGET_CR1	0x00000200 +#define   TARGET_CR2	0x00000400 +#define   TARGET_CR3	0x00000600 +#define TARGET_TABDLY	0x00001800 +#define   TARGET_TAB0	0x00000000 +#define   TARGET_TAB1	0x00000800 +#define   TARGET_TAB2	0x00001000 +#define   TARGET_TAB3	0x00001800 +#define   TARGET_XTABS	0x00001800 +#define TARGET_BSDLY	0x00002000 +#define   TARGET_BS0	0x00000000 +#define   TARGET_BS1	0x00002000 +#define TARGET_VTDLY	0x00004000 +#define   TARGET_VT0	0x00000000 +#define   TARGET_VT1	0x00004000 +#define TARGET_FFDLY	0x00008000 +#define   TARGET_FF0	0x00000000 +#define   TARGET_FF1	0x00008000 +#define TARGET_PAGEOUT 0x00010000  /* SUNOS specific */ +#define TARGET_WRAP    0x00020000  /* SUNOS specific */ + +/* c_cflag bit meaning */ +#define TARGET_CBAUD	  0x0000100f +#define  TARGET_B0	  0x00000000   /* hang up */ +#define  TARGET_B50	  0x00000001 +#define  TARGET_B75	  0x00000002 +#define  TARGET_B110	  0x00000003 +#define  TARGET_B134	  0x00000004 +#define  TARGET_B150	  0x00000005 +#define  TARGET_B200	  0x00000006 +#define  TARGET_B300	  0x00000007 +#define  TARGET_B600	  0x00000008 +#define  TARGET_B1200	  0x00000009 +#define  TARGET_B1800	  0x0000000a +#define  TARGET_B2400	  0x0000000b +#define  TARGET_B4800	  0x0000000c +#define  TARGET_B9600	  0x0000000d +#define  TARGET_B19200	  0x0000000e +#define  TARGET_B38400	  0x0000000f +#define TARGET_EXTA      B19200 +#define TARGET_EXTB      B38400 +#define  TARGET_CSIZE    0x00000030 +#define   TARGET_CS5	  0x00000000 +#define   TARGET_CS6	  0x00000010 +#define   TARGET_CS7	  0x00000020 +#define   TARGET_CS8	  0x00000030 +#define TARGET_CSTOPB	  0x00000040 +#define TARGET_CREAD	  0x00000080 +#define TARGET_PARENB	  0x00000100 +#define TARGET_PARODD	  0x00000200 +#define TARGET_HUPCL	  0x00000400 +#define TARGET_CLOCAL	  0x00000800 +#define TARGET_CBAUDEX   0x00001000 +/* We'll never see these speeds with the Zilogs, but for completeness... */ +#define  TARGET_B57600   0x00001001 +#define  TARGET_B115200  0x00001002 +#define  TARGET_B230400  0x00001003 +#define  TARGET_B460800  0x00001004 +/* This is what we can do with the Zilogs. */ +#define  TARGET_B76800   0x00001005 +/* This is what we can do with the SAB82532. */ +#define  TARGET_B153600  0x00001006 +#define  TARGET_B307200  0x00001007 +#define  TARGET_B614400  0x00001008 +#define  TARGET_B921600  0x00001009 +/* And these are the rest... */ +#define  TARGET_B500000  0x0000100a +#define  TARGET_B576000  0x0000100b +#define TARGET_B1000000  0x0000100c +#define TARGET_B1152000  0x0000100d +#define TARGET_B1500000  0x0000100e +#define TARGET_B2000000  0x0000100f +/* These have totally bogus values and nobody uses them +   so far. Later on we'd have to use say 0x10000x and +   adjust CBAUD constant and drivers accordingly. +#define B2500000  0x00001010 +#define B3000000  0x00001011 +#define B3500000  0x00001012 +#define B4000000  0x00001013  */ +#define TARGET_CIBAUD	  0x100f0000  /* input baud rate (not used) */ +#define TARGET_CMSPAR	  0x40000000  /* mark or space (stick) parity */ +#define TARGET_CRTSCTS	  0x80000000  /* flow control */ + +/* c_lflag bits */ +#define TARGET_ISIG	0x00000001 +#define TARGET_ICANON	0x00000002 +#define TARGET_XCASE	0x00000004 +#define TARGET_ECHO	0x00000008 +#define TARGET_ECHOE	0x00000010 +#define TARGET_ECHOK	0x00000020 +#define TARGET_ECHONL	0x00000040 +#define TARGET_NOFLSH	0x00000080 +#define TARGET_TOSTOP	0x00000100 +#define TARGET_ECHOCTL	0x00000200 +#define TARGET_ECHOPRT	0x00000400 +#define TARGET_ECHOKE	0x00000800 +#define TARGET_DEFECHO  0x00001000  /* SUNOS thing, what is it? */ +#define TARGET_FLUSHO	0x00002000 +#define TARGET_PENDIN	0x00004000 +#define TARGET_IEXTEN	0x00008000 + +/* ioctls */ + +/* Big T */ +#define TARGET_TCGETA		TARGET_IOR('T', 1, struct target_termio) +#define TARGET_TCSETA		TARGET_IOW('T', 2, struct target_termio) +#define TARGET_TCSETAW		TARGET_IOW('T', 3, struct target_termio) +#define TARGET_TCSETAF		TARGET_IOW('T', 4, struct target_termio) +#define TARGET_TCSBRK		TARGET_IO('T', 5) +#define TARGET_TCXONC		TARGET_IO('T', 6) +#define TARGET_TCFLSH		TARGET_IO('T', 7) +#define TARGET_TCGETS		TARGET_IOR('T', 8, struct target_termios) +#define TARGET_TCSETS		TARGET_IOW('T', 9, struct target_termios) +#define TARGET_TCSETSW		TARGET_IOW('T', 10, struct target_termios) +#define TARGET_TCSETSF		TARGET_IOW('T', 11, struct target_termios) + +/* Note that all the ioctls that are not available in Linux have a + * double underscore on the front to: a) avoid some programs to + * thing we support some ioctls under Linux (autoconfiguration stuff) + */ +/* Little t */ +#define TARGET_TIOCGETD	TARGET_IOR('t', 0, int) +#define TARGET_TIOCSETD	TARGET_IOW('t', 1, int) +//#define __TIOCHPCL        _IO('t', 2) /* SunOS Specific */ +//#define __TIOCMODG        _IOR('t', 3, int) /* SunOS Specific */ +//#define __TIOCMODS        _IOW('t', 4, int) /* SunOS Specific */ +//#define __TIOCGETP        _IOR('t', 8, struct sgttyb) /* SunOS Specific */ +//#define __TIOCSETP        _IOW('t', 9, struct sgttyb) /* SunOS Specific */ +//#define __TIOCSETN        _IOW('t', 10, struct sgttyb) /* SunOS Specific */ +#define TARGET_TIOCEXCL	TARGET_IO('t', 13) +#define TARGET_TIOCNXCL	TARGET_IO('t', 14) +//#define __TIOCFLUSH       _IOW('t', 16, int) /* SunOS Specific */ +//#define __TIOCSETC        _IOW('t', 17, struct tchars) /* SunOS Specific */ +//#define __TIOCGETC        _IOR('t', 18, struct tchars) /* SunOS Specific */ +//#define __TIOCTCNTL       _IOW('t', 32, int) /* SunOS Specific */ +//#define __TIOCSIGNAL      _IOW('t', 33, int) /* SunOS Specific */ +//#define __TIOCSETX        _IOW('t', 34, int) /* SunOS Specific */ +//#define __TIOCGETX        _IOR('t', 35, int) /* SunOS Specific */ +#define TARGET_TIOCCONS	TARGET_IO('t', 36) +//#define __TIOCSSIZE     _IOW('t', 37, struct sunos_ttysize) /* SunOS Specific */ +//#define __TIOCGSIZE     _IOR('t', 38, struct sunos_ttysize) /* SunOS Specific */ +#define TARGET_TIOCGSOFTCAR	TARGET_IOR('t', 100, int) +#define TARGET_TIOCSSOFTCAR	TARGET_IOW('t', 101, int) +//#define __TIOCUCNTL       _IOW('t', 102, int) /* SunOS Specific */ +#define TARGET_TIOCSWINSZ	TARGET_IOW('t', 103, struct winsize) +#define TARGET_TIOCGWINSZ	TARGET_IOR('t', 104, struct winsize) +//#define __TIOCREMOTE      _IOW('t', 105, int) /* SunOS Specific */ +#define TARGET_TIOCMGET	TARGET_IOR('t', 106, int) +#define TARGET_TIOCMBIC	TARGET_IOW('t', 107, int) +#define TARGET_TIOCMBIS	TARGET_IOW('t', 108, int) +#define TARGET_TIOCMSET	TARGET_IOW('t', 109, int) +#define TARGET_TIOCSTART       TARGET_IO('t', 110) +#define TARGET_TIOCSTOP        TARGET_IO('t', 111) +#define TARGET_TIOCPKT		TARGET_IOW('t', 112, int) +#define TARGET_TIOCNOTTY	TARGET_IO('t', 113) +#define TARGET_TIOCSTI		TARGET_IOW('t', 114, char) +#define TARGET_TIOCOUTQ	TARGET_IOR('t', 115, int) +//#define __TIOCGLTC        _IOR('t', 116, struct ltchars) /* SunOS Specific */ +//#define __TIOCSLTC        _IOW('t', 117, struct ltchars) /* SunOS Specific */ +/* 118 is the non-posix setpgrp tty ioctl */ +/* 119 is the non-posix getpgrp tty ioctl */ +//#define __TIOCCDTR        TARGET_IO('t', 120) /* SunOS Specific */ +//#define __TIOCSDTR        TARGET_IO('t', 121) /* SunOS Specific */ +#define TARGET_TIOCCBRK        TARGET_IO('t', 122) +#define TARGET_TIOCSBRK        TARGET_IO('t', 123) +//#define __TIOCLGET        TARGET_IOW('t', 124, int) /* SunOS Specific */ +//#define __TIOCLSET        TARGET_IOW('t', 125, int) /* SunOS Specific */ +//#define __TIOCLBIC        TARGET_IOW('t', 126, int) /* SunOS Specific */ +//#define __TIOCLBIS        TARGET_IOW('t', 127, int) /* SunOS Specific */ +//#define __TIOCISPACE      TARGET_IOR('t', 128, int) /* SunOS Specific */ +//#define __TIOCISIZE       TARGET_IOR('t', 129, int) /* SunOS Specific */ +#define TARGET_TIOCSPGRP	TARGET_IOW('t', 130, int) +#define TARGET_TIOCGPGRP	TARGET_IOR('t', 131, int) +#define TARGET_TIOCSCTTY	TARGET_IO('t', 132) +#define TARGET_TIOCGSID	TARGET_IOR('t', 133, int) +/* Get minor device of a pty master's FD -- Solaris equiv is ISPTM */ +#define TARGET_TIOCGPTN	TARGET_IOR('t', 134, unsigned int) /* Get Pty Number */ +#define TARGET_TIOCSPTLCK	TARGET_IOW('t', 135, int) /* Lock/unlock PTY */ + +/* Little f */ +#define TARGET_FIOCLEX		TARGET_IO('f', 1) +#define TARGET_FIONCLEX	TARGET_IO('f', 2) +#define TARGET_FIOASYNC	TARGET_IOW('f', 125, int) +#define TARGET_FIONBIO		TARGET_IOW('f', 126, int) +#define TARGET_FIONREAD	TARGET_IOR('f', 127, int) +#define TARGET_TIOCINQ		TARGET_FIONREAD + +/* SCARY Rutgers local SunOS kernel hackery, perhaps I will support it + * someday.  This is completely bogus, I know... + */ +//#define __TCGETSTAT       TARGET_IO('T', 200) /* Rutgers specific */ +//#define __TCSETSTAT       TARGET_IO('T', 201) /* Rutgers specific */ + +/* Linux specific, no SunOS equivalent. */ +#define TARGET_TIOCLINUX	0x541C +#define TARGET_TIOCGSERIAL	0x541E +#define TARGET_TIOCSSERIAL	0x541F +#define TARGET_TCSBRKP		0x5425 +#define TARGET_TIOCTTYGSTRUCT	0x5426 +#define TARGET_TIOCSERCONFIG	0x5453 +#define TARGET_TIOCSERGWILD	0x5454 +#define TARGET_TIOCSERSWILD	0x5455 +#define TARGET_TIOCGLCKTRMIOS	0x5456 +#define TARGET_TIOCSLCKTRMIOS	0x5457 +#define TARGET_TIOCSERGSTRUCT	0x5458 /* For debugging only */ +#define TARGET_TIOCSERGETLSR   0x5459 /* Get line status register */ +#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config  */ +#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ +#define TARGET_TIOCMIWAIT	0x545C /* Wait input */ +#define TARGET_TIOCGICOUNT	0x545D /* Read serial port inline interrupt counts */ diff --git a/linux-user/sparc64/syscall.h b/linux-user/sparc64/syscall.h new file mode 100644 index 00000000..8398d3f4 --- /dev/null +++ b/linux-user/sparc64/syscall.h @@ -0,0 +1,21 @@ +struct target_pt_regs { +	abi_ulong u_regs[16]; +	abi_ulong tstate; +	abi_ulong pc; +	abi_ulong npc; +	abi_ulong y; +	abi_ulong fprs; +}; + +#define UNAME_MACHINE "sun4u" +#define UNAME_MINIMUM_RELEASE "2.6.32" + +/* SPARC kernels don't define this in their Kconfig, but they have the + * same ABI as if they did, implemented by sparc-specific code which fishes + * directly in the u_regs() struct for half the parameters in sparc_do_fork() + * and copy_thread(). + */ +#define TARGET_CLONE_BACKWARDS +#define TARGET_MINSIGSTKSZ      4096 +#define TARGET_MLOCKALL_MCL_CURRENT 0x2000 +#define TARGET_MLOCKALL_MCL_FUTURE  0x4000 diff --git a/linux-user/sparc64/syscall_nr.h b/linux-user/sparc64/syscall_nr.h new file mode 100644 index 00000000..34a984cc --- /dev/null +++ b/linux-user/sparc64/syscall_nr.h @@ -0,0 +1,343 @@ +#define TARGET_NR_restart_syscall      0 /* Linux Specific				   */ +#define TARGET_NR_exit                 1 /* Common                                      */ +#define TARGET_NR_fork                 2 /* Common                                      */ +#define TARGET_NR_read                 3 /* Common                                      */ +#define TARGET_NR_write                4 /* Common                                      */ +#define TARGET_NR_open                 5 /* Common                                      */ +#define TARGET_NR_close                6 /* Common                                      */ +#define TARGET_NR_wait4                7 /* Common                                      */ +#define TARGET_NR_creat                8 /* Common                                      */ +#define TARGET_NR_link                 9 /* Common                                      */ +#define TARGET_NR_unlink              10 /* Common                                      */ +#define TARGET_NR_execv               11 /* SunOS Specific                              */ +#define TARGET_NR_chdir               12 /* Common                                      */ +#define TARGET_NR_chown		 13 /* Common					   */ +#define TARGET_NR_mknod               14 /* Common                                      */ +#define TARGET_NR_chmod               15 /* Common                                      */ +#define TARGET_NR_lchown              16 /* Common                                      */ +#define TARGET_NR_brk                 17 /* Common                                      */ +#define TARGET_NR_perfctr             18 /* Performance counter operations              */ +#define TARGET_NR_lseek               19 /* Common                                      */ +#define TARGET_NR_getpid              20 /* Common                                      */ +#define TARGET_NR_capget		 21 /* Linux Specific				   */ +#define TARGET_NR_capset		 22 /* Linux Specific				   */ +#define TARGET_NR_setuid              23 /* Implemented via setreuid in SunOS           */ +#define TARGET_NR_getuid              24 /* Common                                      */ +/* #define TARGET_NR_time alias	 25    ENOSYS under SunOS			   */ +#define TARGET_NR_ptrace              26 /* Common                                      */ +#define TARGET_NR_alarm               27 /* Implemented via setitimer in SunOS          */ +#define TARGET_NR_sigaltstack	 28 /* Common					   */ +#define TARGET_NR_pause               29 /* Is sigblock(0)->sigpause() in SunOS         */ +#define TARGET_NR_utime               30 /* Implemented via utimes() under SunOS        */ +#define TARGET_NR_lchown32            31 /* Linux sparc32 specific                      */ +#define TARGET_NR_fchown32            32 /* Linux sparc32 specific                      */ +#define TARGET_NR_access              33 /* Common                                      */ +#define TARGET_NR_nice                34 /* Implemented via get/setpriority() in SunOS  */ +#define TARGET_NR_chown32             35 /*  Linux sparc32 specific                     */ +#define TARGET_NR_sync                36 /* Common                                      */ +#define TARGET_NR_kill                37 /* Common                                      */ +#define TARGET_NR_stat                38 /* Common                                      */ +#define TARGET_NR_sendfile		 39 /* Linux Specific				   */ +#define TARGET_NR_lstat               40 /* Common                                      */ +#define TARGET_NR_dup                 41 /* Common                                      */ +#define TARGET_NR_pipe                42 /* Common                                      */ +#define TARGET_NR_times               43 /* Implemented via getrusage() in SunOS        */ +#define TARGET_NR_getuid32            44 /* Linux sparc32 specific                      */ +#define TARGET_NR_umount2             45 /* Linux Specific                              */ +#define TARGET_NR_setgid              46 /* Implemented via setregid() in SunOS         */ +#define TARGET_NR_getgid              47 /* Common                                      */ +#define TARGET_NR_signal              48 /* Implemented via sigvec() in SunOS           */ +#define TARGET_NR_geteuid             49 /* SunOS calls getuid()                        */ +#define TARGET_NR_getegid             50 /* SunOS calls getgid()                        */ +#define TARGET_NR_acct                51 /* Common                                      */ +#define TARGET_NR_memory_ordering	 52 /* Linux Specific				   */ +#define TARGET_NR_getgid32            53 /* Linux sparc32 specific                      */ +#define TARGET_NR_ioctl               54 /* Common                                      */ +#define TARGET_NR_reboot              55 /* Common                                      */ +#define TARGET_NR_mmap2		      56 /* Linux sparc32 Specific                      */ +#define TARGET_NR_symlink             57 /* Common                                      */ +#define TARGET_NR_readlink            58 /* Common                                      */ +#define TARGET_NR_execve              59 /* Common                                      */ +#define TARGET_NR_umask               60 /* Common                                      */ +#define TARGET_NR_chroot              61 /* Common                                      */ +#define TARGET_NR_fstat               62 /* Common                                      */ +#define TARGET_NR_fstat64             63 /* Linux sparc32 Specific                      */ +#define TARGET_NR_getpagesize         64 /* Common                                      */ +#define TARGET_NR_msync               65 /* Common in newer 1.3.x revs...               */ +#define TARGET_NR_vfork               66 /* Common                                      */ +#define TARGET_NR_pread64             67 /* Linux Specific                              */ +#define TARGET_NR_pwrite64            68 /* Linux Specific                              */ +#define TARGET_NR_geteuid32           69 /* Linux sparc32, sbrk under SunOS             */ +#define TARGET_NR_getegid32           70 /* Linux sparc32, sstk under SunOS             */ +#define TARGET_NR_mmap                71 /* Common                                      */ +#define TARGET_NR_setreuid32          72 /* Linux sparc32, vadvise under SunOS          */ +#define TARGET_NR_munmap              73 /* Common                                      */ +#define TARGET_NR_mprotect            74 /* Common                                      */ +#define TARGET_NR_madvise             75 /* Common                                      */ +#define TARGET_NR_vhangup             76 /* Common                                      */ +#define TARGET_NR_truncate64          77 /* Linux sparc32 Specific			*/ +#define TARGET_NR_mincore             78 /* Common                                      */ +#define TARGET_NR_getgroups           79 /* Common                                      */ +#define TARGET_NR_setgroups           80 /* Common                                      */ +#define TARGET_NR_getpgrp             81 /* Common                                      */ +#define TARGET_NR_setgroups32         82 /* Linux sparc32, setpgrp under SunOS          */ +#define TARGET_NR_setitimer           83 /* Common                                      */ +#define TARGET_NR_ftruncate64         84 /* Linux sparc32 Specific                      */ +#define TARGET_NR_swapon              85 /* Common                                      */ +#define TARGET_NR_getitimer           86 /* Common                                      */ +#define TARGET_NR_setuid32            87 /* Linux sparc32, gethostname under SunOS      */ +#define TARGET_NR_sethostname         88 /* Common                                      */ +#define TARGET_NR_setgid32            89 /* Linux sparc32, getdtablesize under SunOS    */ +#define TARGET_NR_dup2                90 /* Common                                      */ +#define TARGET_NR_setfsuid32          91 /* Linux sparc32, getdopt under SunOS          */ +#define TARGET_NR_fcntl               92 /* Common                                      */ +#define TARGET_NR_select              93 /* Common                                      */ +#define TARGET_NR_setfsgid32          94 /* Linux sparc32, setdopt under SunOS          */ +#define TARGET_NR_fsync               95 /* Common                                      */ +#define TARGET_NR_setpriority         96 /* Common                                      */ +#define TARGET_NR_socket              97 /* Common                                      */ +#define TARGET_NR_connect             98 /* Common                                      */ +#define TARGET_NR_accept              99 /* Common                                      */ +#define TARGET_NR_getpriority        100 /* Common                                      */ +#define TARGET_NR_rt_sigreturn       101 /* Linux Specific                              */ +#define TARGET_NR_rt_sigaction       102 /* Linux Specific                              */ +#define TARGET_NR_rt_sigprocmask     103 /* Linux Specific                              */ +#define TARGET_NR_rt_sigpending      104 /* Linux Specific                              */ +#define TARGET_NR_rt_sigtimedwait    105 /* Linux Specific                              */ +#define TARGET_NR_rt_sigqueueinfo    106 /* Linux Specific                              */ +#define TARGET_NR_rt_sigsuspend      107 /* Linux Specific                              */ +#define TARGET_NR_setresuid          108 /* Linux Specific, sigvec under SunOS	   */ +#define TARGET_NR_getresuid          109 /* Linux Specific, sigblock under SunOS	   */ +#define TARGET_NR_setresgid          110 /* Linux Specific, sigsetmask under SunOS	   */ +#define TARGET_NR_getresgid          111 /* Linux Specific, sigpause under SunOS	   */ +/* #define TARGET_NR_setregid32          75  Linux sparc32, sigstack under SunOS         */ +#define TARGET_NR_recvmsg            113 /* Common                                      */ +#define TARGET_NR_sendmsg            114 /* Common                                      */ +#define TARGET_NR_getgroups32        115 /* Linux sparc32, vtrace under SunOS           */ +#define TARGET_NR_gettimeofday       116 /* Common                                      */ +#define TARGET_NR_getrusage          117 /* Common                                      */ +#define TARGET_NR_getsockopt         118 /* Common                                      */ +#define TARGET_NR_getcwd		119 /* Linux Specific				   */ +#define TARGET_NR_readv              120 /* Common                                      */ +#define TARGET_NR_writev             121 /* Common                                      */ +#define TARGET_NR_settimeofday       122 /* Common                                      */ +#define TARGET_NR_fchown             123 /* Common                                      */ +#define TARGET_NR_fchmod             124 /* Common                                      */ +#define TARGET_NR_recvfrom           125 /* Common                                      */ +#define TARGET_NR_setreuid           126 /* Common                                      */ +#define TARGET_NR_setregid           127 /* Common                                      */ +#define TARGET_NR_rename             128 /* Common                                      */ +#define TARGET_NR_truncate           129 /* Common                                      */ +#define TARGET_NR_ftruncate          130 /* Common                                      */ +#define TARGET_NR_flock              131 /* Common                                      */ +#define TARGET_NR_lstat64	     132 /* Linux sparc32 Specific                      */ +#define TARGET_NR_sendto             133 /* Common                                      */ +#define TARGET_NR_shutdown           134 /* Common                                      */ +#define TARGET_NR_socketpair         135 /* Common                                      */ +#define TARGET_NR_mkdir              136 /* Common                                      */ +#define TARGET_NR_rmdir              137 /* Common                                      */ +#define TARGET_NR_utimes             138 /* SunOS Specific                              */ +#define TARGET_NR_stat64	     139 /* Linux sparc32 Specific			   */ +#define TARGET_NR_sendfile64         140 /* adjtime under SunOS                         */ +#define TARGET_NR_getpeername        141 /* Common                                      */ +#define TARGET_NR_futex              142 /* gethostid under SunOS                       */ +#define TARGET_NR_gettid             143 /* ENOSYS under SunOS                          */ +#define TARGET_NR_getrlimit		144 /* Common                                      */ +#define TARGET_NR_setrlimit          145 /* Common                                      */ +#define TARGET_NR_pivot_root		146 /* Linux Specific, killpg under SunOS          */ +#define TARGET_NR_prctl		147 /* ENOSYS under SunOS                          */ +#define TARGET_NR_pciconfig_read	148 /* ENOSYS under SunOS                          */ +#define TARGET_NR_pciconfig_write	149 /* ENOSYS under SunOS                          */ +#define TARGET_NR_getsockname        150 /* Common                                      */ +/* #define TARGET_NR_getmsg          151    SunOS Specific                              */ +/* #define TARGET_NR_putmsg          152    SunOS Specific                              */ +#define TARGET_NR_poll               153 /* Common                                      */ +#define TARGET_NR_getdents64		154 /* Linux specific				   */ +#define TARGET_NR_fcntl64            155 /* Linux sparc32 Specific                      */ +/* #define TARGET_NR_getdirentries   156    SunOS Specific                              */ +#define TARGET_NR_statfs             157 /* Common                                      */ +#define TARGET_NR_fstatfs            158 /* Common                                      */ +#define TARGET_NR_umount             159 /* Common                                      */ +#define TARGET_NR_sched_set_affinity 160 /* Linux specific, async_daemon under SunOS    */ +#define TARGET_NR_sched_get_affinity 161 /* Linux specific, getfh under SunOS           */ +#define TARGET_NR_getdomainname      162 /* SunOS Specific                              */ +#define TARGET_NR_setdomainname      163 /* Common                                      */ +#define TARGET_NR_utrap_install	164 /* SYSV ABI/v9 required			   */ +#define TARGET_NR_quotactl           165 /* Common                                      */ +#define TARGET_NR_set_tid_address    166 /* Linux specific, exportfs under SunOS        */ +#define TARGET_NR_mount              167 /* Common                                      */ +#define TARGET_NR_ustat              168 /* Common                                      */ +#define TARGET_NR_setxattr           169 /* SunOS: semsys                               */ +#define TARGET_NR_lsetxattr          170 /* SunOS: msgsys                               */ +#define TARGET_NR_fsetxattr          171 /* SunOS: shmsys                               */ +#define TARGET_NR_getxattr           172 /* SunOS: auditsys                             */ +#define TARGET_NR_lgetxattr          173 /* SunOS: rfssys                               */ +#define TARGET_NR_getdents           174 /* Common                                      */ +#define TARGET_NR_setsid             175 /* Common                                      */ +#define TARGET_NR_fchdir             176 /* Common                                      */ +#define TARGET_NR_fgetxattr          177 /* SunOS: fchroot                              */ +#define TARGET_NR_listxattr          178 /* SunOS: vpixsys                              */ +#define TARGET_NR_llistxattr         179 /* SunOS: aioread                              */ +#define TARGET_NR_flistxattr         180 /* SunOS: aiowrite                             */ +#define TARGET_NR_removexattr        181 /* SunOS: aiowait                              */ +#define TARGET_NR_lremovexattr       182 /* SunOS: aiocancel                            */ +#define TARGET_NR_sigpending         183 /* Common                                      */ +#define TARGET_NR_query_module	184 /* Linux Specific				   */ +#define TARGET_NR_setpgid            185 /* Common                                      */ +#define TARGET_NR_fremovexattr       186 /* SunOS: pathconf                             */ +#define TARGET_NR_tkill              187 /* SunOS: fpathconf                            */ +#define TARGET_NR_exit_group		188 /* Linux specific, sysconf undef SunOS         */ +#define TARGET_NR_uname              189 /* Linux Specific                              */ +#define TARGET_NR_init_module        190 /* Linux Specific                              */ +#define TARGET_NR_personality        191 /* Linux Specific                              */ +#define TARGET_NR_remap_file_pages   192 /* Linux Specific                              */ +#define TARGET_NR_epoll_create       193 /* Linux Specific                              */ +#define TARGET_NR_epoll_ctl          194 /* Linux Specific                              */ +#define TARGET_NR_epoll_wait         195 /* Linux Specific                              */ +/* #define TARGET_NR_ulimit          196    Linux Specific                              */ +#define TARGET_NR_getppid            197 /* Linux Specific                              */ +#define TARGET_NR_sigaction          198 /* Linux Specific                              */ +#define TARGET_NR_sgetmask           199 /* Linux Specific                              */ +#define TARGET_NR_ssetmask           200 /* Linux Specific                              */ +#define TARGET_NR_sigsuspend         201 /* Linux Specific                              */ +#define TARGET_NR_oldlstat           202 /* Linux Specific                              */ +#define TARGET_NR_uselib             203 /* Linux Specific                              */ +#define TARGET_NR_readdir            204 /* Linux Specific                              */ +#define TARGET_NR_readahead          205 /* Linux Specific                              */ +#define TARGET_NR_socketcall         206 /* Linux Specific                              */ +#define TARGET_NR_syslog             207 /* Linux Specific                              */ +#define TARGET_NR_lookup_dcookie     208 /* Linux Specific                              */ +#define TARGET_NR_fadvise64          209 /* Linux Specific                              */ +#define TARGET_NR_fadvise64_64       210 /* Linux Specific                              */ +#define TARGET_NR_tgkill             211 /* Linux Specific                              */ +#define TARGET_NR_waitpid            212 /* Linux Specific                              */ +#define TARGET_NR_swapoff            213 /* Linux Specific                              */ +#define TARGET_NR_sysinfo            214 /* Linux Specific                              */ +#define TARGET_NR_ipc                215 /* Linux Specific                              */ +#define TARGET_NR_sigreturn          216 /* Linux Specific                              */ +#define TARGET_NR_clone              217 /* Linux Specific                              */ +/* #define TARGET_NR_modify_ldt      218    Linux Specific - i386 specific, unused      */ +#define TARGET_NR_adjtimex           219 /* Linux Specific                              */ +#define TARGET_NR_sigprocmask        220 /* Linux Specific                              */ +#define TARGET_NR_create_module      221 /* Linux Specific                              */ +#define TARGET_NR_delete_module      222 /* Linux Specific                              */ +#define TARGET_NR_get_kernel_syms    223 /* Linux Specific                              */ +#define TARGET_NR_getpgid            224 /* Linux Specific                              */ +#define TARGET_NR_bdflush            225 /* Linux Specific                              */ +#define TARGET_NR_sysfs              226 /* Linux Specific                              */ +#define TARGET_NR_afs_syscall        227 /* Linux Specific                              */ +#define TARGET_NR_setfsuid           228 /* Linux Specific                              */ +#define TARGET_NR_setfsgid           229 /* Linux Specific                              */ +#define TARGET_NR__newselect         230 /* Linux Specific                              */ +#define TARGET_NR_time               231 /* Linux sparc32                               */ +/* #define TARGET_NR_oldstat         232    Linux Specific                              */ +#define TARGET_NR_stime              233 /* Linux Specific                              */ +#define TARGET_NR_statfs64           234 /* Linux Specific                              */ +#define TARGET_NR_fstatfs64          235 /* Linux Specific                              */ +#define TARGET_NR__llseek            236 /* Linux Specific                              */ +#define TARGET_NR_mlock              237 +#define TARGET_NR_munlock            238 +#define TARGET_NR_mlockall           239 +#define TARGET_NR_munlockall         240 +#define TARGET_NR_sched_setparam     241 +#define TARGET_NR_sched_getparam     242 +#define TARGET_NR_sched_setscheduler 243 +#define TARGET_NR_sched_getscheduler 244 +#define TARGET_NR_sched_yield        245 +#define TARGET_NR_sched_get_priority_max 246 +#define TARGET_NR_sched_get_priority_min 247 +#define TARGET_NR_sched_rr_get_interval  248 +#define TARGET_NR_nanosleep          249 +#define TARGET_NR_mremap             250 +#define TARGET_NR__sysctl            251 +#define TARGET_NR_getsid             252 +#define TARGET_NR_fdatasync          253 +#define TARGET_NR_nfsservctl         254 +#define TARGET_NR_aplib              255 +#define TARGET_NR_clock_settime	256 +#define TARGET_NR_clock_gettime	257 +#define TARGET_NR_clock_getres	258 +#define TARGET_NR_clock_nanosleep	259 +#define TARGET_NR_sched_getaffinity	260 +#define TARGET_NR_sched_setaffinity	261 +#define TARGET_NR_timer_settime	262 +#define TARGET_NR_timer_gettime	263 +#define TARGET_NR_timer_getoverrun	264 +#define TARGET_NR_timer_delete	265 +#define TARGET_NR_timer_create	266 +/* #define TARGET_NR_vserver		267 Reserved for VSERVER */ +#define TARGET_NR_io_setup		268 +#define TARGET_NR_io_destroy		269 +#define TARGET_NR_io_submit		270 +#define TARGET_NR_io_cancel		271 +#define TARGET_NR_io_getevents	272 +#define TARGET_NR_mq_open		273 +#define TARGET_NR_mq_unlink		274 +#define TARGET_NR_mq_timedsend	275 +#define TARGET_NR_mq_timedreceive	276 +#define TARGET_NR_mq_notify		277 +#define TARGET_NR_mq_getsetattr	278 +#define TARGET_NR_waitid		279 +/*#define TARGET_NR_sys_setaltroot	280 available (was setaltroot) */ +#define TARGET_NR_add_key		281 +#define TARGET_NR_request_key	282 +#define TARGET_NR_keyctl		283 +#define TARGET_NR_openat		284 +#define TARGET_NR_mkdirat		285 +#define TARGET_NR_mknodat		286 +#define TARGET_NR_fchownat		287 +#define TARGET_NR_futimesat		288 +#define TARGET_NR_fstatat64		289 +#define TARGET_NR_unlinkat		290 +#define TARGET_NR_renameat		291 +#define TARGET_NR_linkat		292 +#define TARGET_NR_symlinkat		293 +#define TARGET_NR_readlinkat		294 +#define TARGET_NR_fchmodat		295 +#define TARGET_NR_faccessat		296 +#define TARGET_NR_pselect6		297 +#define TARGET_NR_ppoll		298 +#define TARGET_NR_unshare		299 +#define TARGET_NR_set_robust_list	300 +#define TARGET_NR_get_robust_list	301 +#define TARGET_NR_migrate_pages	302 +#define TARGET_NR_mbind		303 +#define TARGET_NR_get_mempolicy	304 +#define TARGET_NR_set_mempolicy	305 +#define TARGET_NR_kexec_load		306 +#define TARGET_NR_move_pages		307 +#define TARGET_NR_getcpu		308 +#define TARGET_NR_epoll_pwait	309 +#define TARGET_NR_utimensat		310 +#define TARGET_NR_signalfd		311 +#define TARGET_NR_timerfd		312 +#define TARGET_NR_eventfd		313 +#define TARGET_NR_fallocate		314 +#define TARGET_NR_timerfd_settime	315 +#define TARGET_NR_timerfd_gettime	316 +#define TARGET_NR_signalfd4		317 +#define TARGET_NR_eventfd2		318 +#define TARGET_NR_epoll_create1	319 +#define TARGET_NR_dup3			320 +#define TARGET_NR_pipe2		321 +#define TARGET_NR_inotify_init1	322 +#define TARGET_NR_accept4		323 +#define TARGET_NR_preadv                324 +#define TARGET_NR_pwritev               325 +#define TARGET_NR_rt_tgsigqueueinfo     326 +#define TARGET_NR_perf_event_open       327 +#define TARGET_NR_recvmmsg              328 +#define TARGET_NR_fanotify_init         329 +#define TARGET_NR_fanotify_mark         330 +#define TARGET_NR_prlimit64             331 +#define TARGET_NR_name_to_handle_at     332 +#define TARGET_NR_open_by_handle_at     333 +#define TARGET_NR_clock_adjtime         334 +#define TARGET_NR_syncfs                335 +#define TARGET_NR_sendmmsg              336 +#define TARGET_NR_setns                 337 +#define TARGET_NR_process_vm_readv      338 +#define TARGET_NR_process_vm_writev     339 +#define TARGET_NR_kern_features         340 +#define TARGET_NR_kcmp                  341 +#define TARGET_NR_finit_module          342 diff --git a/linux-user/sparc64/target_cpu.h b/linux-user/sparc64/target_cpu.h new file mode 100644 index 00000000..b22263d2 --- /dev/null +++ b/linux-user/sparc64/target_cpu.h @@ -0,0 +1 @@ +#include "../sparc/target_cpu.h" diff --git a/linux-user/sparc64/target_signal.h b/linux-user/sparc64/target_signal.h new file mode 100644 index 00000000..c7de300c --- /dev/null +++ b/linux-user/sparc64/target_signal.h @@ -0,0 +1,36 @@ +#ifndef TARGET_SIGNAL_H +#define TARGET_SIGNAL_H + +#include "cpu.h" + +/* this struct defines a stack used during syscall handling */ + +typedef struct target_sigaltstack { +	abi_ulong ss_sp; +	abi_long ss_flags; +	abi_ulong ss_size; +} target_stack_t; + + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK	1 +#define TARGET_SS_DISABLE	2 + +#define TARGET_MINSIGSTKSZ	4096 +#define TARGET_SIGSTKSZ		16384 + +#ifndef UREG_I6 +#define UREG_I6        6 +#endif +#ifndef UREG_FP +#define UREG_FP        UREG_I6 +#endif + +static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state) +{ +    return state->regwptr[UREG_FP]; +} + +#endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/sparc64/target_structs.h b/linux-user/sparc64/target_structs.h new file mode 100644 index 00000000..fc172900 --- /dev/null +++ b/linux-user/sparc64/target_structs.h @@ -0,0 +1,58 @@ +/* + * SPARC64 specific structures for linux-user + * + * Copyright (c) 2013 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_STRUCTS_H +#define TARGET_STRUCTS_H + +struct target_ipc_perm { +    abi_int __key;                      /* Key.  */ +    abi_uint uid;                       /* Owner's user ID.  */ +    abi_uint gid;                       /* Owner's group ID.  */ +    abi_uint cuid;                      /* Creator's user ID.  */ +    abi_uint cgid;                      /* Creator's group ID.  */ +    abi_ushort mode;                    /* Read/write permission.  */ +    abi_ushort __pad1; +    abi_ushort __seq;                   /* Sequence number.  */ +    abi_ushort __pad2; +    abi_ulong __unused1; +    abi_ulong __unused2; +}; + +struct target_shmid_ds { +    struct target_ipc_perm shm_perm;    /* operation permission struct */ +    abi_long shm_segsz;                 /* size of segment in bytes */ +    abi_ulong shm_atime;                /* time of last shmat() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused1; +#endif +    abi_ulong shm_dtime;                /* time of last shmdt() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused2; +#endif +    abi_ulong shm_ctime;                /* time of last change by shmctl() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused3; +#endif +    abi_int shm_cpid;                   /* pid of creator */ +    abi_int shm_lpid;                   /* pid of last shmop */ +    abi_ulong shm_nattch;               /* number of current attaches */ +    abi_ulong __unused4; +    abi_ulong __unused5; +}; + +#endif diff --git a/linux-user/sparc64/termbits.h b/linux-user/sparc64/termbits.h new file mode 100644 index 00000000..691600d2 --- /dev/null +++ b/linux-user/sparc64/termbits.h @@ -0,0 +1,279 @@ +/* from asm/termbits.h */ + +#define TARGET_NCCS 19 + +struct target_termios { +    unsigned int c_iflag;               /* input mode flags */ +    unsigned int c_oflag;               /* output mode flags */ +    unsigned int c_cflag;               /* control mode flags */ +    unsigned int c_lflag;               /* local mode flags */ +    unsigned char c_line;                    /* line discipline */ +    unsigned char c_cc[TARGET_NCCS];                /* control characters */ +}; + +/* c_cc characters */ +#define TARGET_VINTR    0 +#define TARGET_VQUIT    1 +#define TARGET_VERASE   2 +#define TARGET_VKILL    3 +#define TARGET_VEOF     4 +#define TARGET_VEOL     5 +#define TARGET_VEOL2    6 +#define TARGET_VSWTC    7 +#define TARGET_VSTART   8 +#define TARGET_VSTOP    9 + +#define TARGET_VSUSP    10 +#define TARGET_VDSUSP   11  /* SunOS POSIX nicety I do believe... */ +#define TARGET_VREPRINT 12 +#define TARGET_VDISCARD 13 +#define TARGET_VWERASE  14 +#define TARGET_VLNEXT   15 + +/* Kernel keeps vmin/vtime separated, user apps assume vmin/vtime is + * shared with eof/eol + */ +#define TARGET_VMIN     TARGET_VEOF +#define TARGET_VTIME    TARGET_VEOL + +/* c_iflag bits */ +#define TARGET_IGNBRK	0x00000001 +#define TARGET_BRKINT	0x00000002 +#define TARGET_IGNPAR	0x00000004 +#define TARGET_PARMRK	0x00000008 +#define TARGET_INPCK	0x00000010 +#define TARGET_ISTRIP	0x00000020 +#define TARGET_INLCR	0x00000040 +#define TARGET_IGNCR	0x00000080 +#define TARGET_ICRNL	0x00000100 +#define TARGET_IUCLC	0x00000200 +#define TARGET_IXON	0x00000400 +#define TARGET_IXANY	0x00000800 +#define TARGET_IXOFF	0x00001000 +#define TARGET_IMAXBEL	0x00002000 +#define TARGET_IUTF8	0x00004000 + +/* c_oflag bits */ +#define TARGET_OPOST	0x00000001 +#define TARGET_OLCUC	0x00000002 +#define TARGET_ONLCR	0x00000004 +#define TARGET_OCRNL	0x00000008 +#define TARGET_ONOCR	0x00000010 +#define TARGET_ONLRET	0x00000020 +#define TARGET_OFILL	0x00000040 +#define TARGET_OFDEL	0x00000080 +#define TARGET_NLDLY	0x00000100 +#define   TARGET_NL0	0x00000000 +#define   TARGET_NL1	0x00000100 +#define TARGET_CRDLY	0x00000600 +#define   TARGET_CR0	0x00000000 +#define   TARGET_CR1	0x00000200 +#define   TARGET_CR2	0x00000400 +#define   TARGET_CR3	0x00000600 +#define TARGET_TABDLY	0x00001800 +#define   TARGET_TAB0	0x00000000 +#define   TARGET_TAB1	0x00000800 +#define   TARGET_TAB2	0x00001000 +#define   TARGET_TAB3	0x00001800 +#define   TARGET_XTABS	0x00001800 +#define TARGET_BSDLY	0x00002000 +#define   TARGET_BS0	0x00000000 +#define   TARGET_BS1	0x00002000 +#define TARGET_VTDLY	0x00004000 +#define   TARGET_VT0	0x00000000 +#define   TARGET_VT1	0x00004000 +#define TARGET_FFDLY	0x00008000 +#define   TARGET_FF0	0x00000000 +#define   TARGET_FF1	0x00008000 +#define TARGET_PAGEOUT 0x00010000  /* SUNOS specific */ +#define TARGET_WRAP    0x00020000  /* SUNOS specific */ + +/* c_cflag bit meaning */ +#define TARGET_CBAUD	  0x0000100f +#define  TARGET_B0	  0x00000000   /* hang up */ +#define  TARGET_B50	  0x00000001 +#define  TARGET_B75	  0x00000002 +#define  TARGET_B110	  0x00000003 +#define  TARGET_B134	  0x00000004 +#define  TARGET_B150	  0x00000005 +#define  TARGET_B200	  0x00000006 +#define  TARGET_B300	  0x00000007 +#define  TARGET_B600	  0x00000008 +#define  TARGET_B1200	  0x00000009 +#define  TARGET_B1800	  0x0000000a +#define  TARGET_B2400	  0x0000000b +#define  TARGET_B4800	  0x0000000c +#define  TARGET_B9600	  0x0000000d +#define  TARGET_B19200	  0x0000000e +#define  TARGET_B38400	  0x0000000f +#define TARGET_EXTA      B19200 +#define TARGET_EXTB      B38400 +#define  TARGET_CSIZE    0x00000030 +#define   TARGET_CS5	  0x00000000 +#define   TARGET_CS6	  0x00000010 +#define   TARGET_CS7	  0x00000020 +#define   TARGET_CS8	  0x00000030 +#define TARGET_CSTOPB	  0x00000040 +#define TARGET_CREAD	  0x00000080 +#define TARGET_PARENB	  0x00000100 +#define TARGET_PARODD	  0x00000200 +#define TARGET_HUPCL	  0x00000400 +#define TARGET_CLOCAL	  0x00000800 +#define TARGET_CBAUDEX   0x00001000 +/* We'll never see these speeds with the Zilogs, but for completeness... */ +#define  TARGET_B57600   0x00001001 +#define  TARGET_B115200  0x00001002 +#define  TARGET_B230400  0x00001003 +#define  TARGET_B460800  0x00001004 +/* This is what we can do with the Zilogs. */ +#define  TARGET_B76800   0x00001005 +/* This is what we can do with the SAB82532. */ +#define  TARGET_B153600  0x00001006 +#define  TARGET_B307200  0x00001007 +#define  TARGET_B614400  0x00001008 +#define  TARGET_B921600  0x00001009 +/* And these are the rest... */ +#define  TARGET_B500000  0x0000100a +#define  TARGET_B576000  0x0000100b +#define TARGET_B1000000  0x0000100c +#define TARGET_B1152000  0x0000100d +#define TARGET_B1500000  0x0000100e +#define TARGET_B2000000  0x0000100f +/* These have totally bogus values and nobody uses them +   so far. Later on we'd have to use say 0x10000x and +   adjust CBAUD constant and drivers accordingly. +#define B2500000  0x00001010 +#define B3000000  0x00001011 +#define B3500000  0x00001012 +#define B4000000  0x00001013  */ +#define TARGET_CIBAUD	  0x100f0000  /* input baud rate (not used) */ +#define TARGET_CMSPAR	  0x40000000  /* mark or space (stick) parity */ +#define TARGET_CRTSCTS	  0x80000000  /* flow control */ + +/* c_lflag bits */ +#define TARGET_ISIG	0x00000001 +#define TARGET_ICANON	0x00000002 +#define TARGET_XCASE	0x00000004 +#define TARGET_ECHO	0x00000008 +#define TARGET_ECHOE	0x00000010 +#define TARGET_ECHOK	0x00000020 +#define TARGET_ECHONL	0x00000040 +#define TARGET_NOFLSH	0x00000080 +#define TARGET_TOSTOP	0x00000100 +#define TARGET_ECHOCTL	0x00000200 +#define TARGET_ECHOPRT	0x00000400 +#define TARGET_ECHOKE	0x00000800 +#define TARGET_DEFECHO  0x00001000  /* SUNOS thing, what is it? */ +#define TARGET_FLUSHO	0x00002000 +#define TARGET_PENDIN	0x00004000 +#define TARGET_IEXTEN	0x00008000 + +/* ioctls */ + +/* Big T */ +#define TARGET_TCGETA		TARGET_IOR('T', 1, struct target_termio) +#define TARGET_TCSETA		TARGET_IOW('T', 2, struct target_termio) +#define TARGET_TCSETAW		TARGET_IOW('T', 3, struct target_termio) +#define TARGET_TCSETAF		TARGET_IOW('T', 4, struct target_termio) +#define TARGET_TCSBRK		TARGET_IO('T', 5) +#define TARGET_TCXONC		TARGET_IO('T', 6) +#define TARGET_TCFLSH		TARGET_IO('T', 7) +#define TARGET_TCGETS		TARGET_IOR('T', 8, struct target_termios) +#define TARGET_TCSETS		TARGET_IOW('T', 9, struct target_termios) +#define TARGET_TCSETSW		TARGET_IOW('T', 10, struct target_termios) +#define TARGET_TCSETSF		TARGET_IOW('T', 11, struct target_termios) + +/* Note that all the ioctls that are not available in Linux have a + * double underscore on the front to: a) avoid some programs to + * thing we support some ioctls under Linux (autoconfiguration stuff) + */ +/* Little t */ +#define TARGET_TIOCGETD	TARGET_IOR('t', 0, int) +#define TARGET_TIOCSETD	TARGET_IOW('t', 1, int) +//#define __TIOCHPCL        _IO('t', 2) /* SunOS Specific */ +//#define __TIOCMODG        _IOR('t', 3, int) /* SunOS Specific */ +//#define __TIOCMODS        _IOW('t', 4, int) /* SunOS Specific */ +//#define __TIOCGETP        _IOR('t', 8, struct sgttyb) /* SunOS Specific */ +//#define __TIOCSETP        _IOW('t', 9, struct sgttyb) /* SunOS Specific */ +//#define __TIOCSETN        _IOW('t', 10, struct sgttyb) /* SunOS Specific */ +#define TARGET_TIOCEXCL	TARGET_IO('t', 13) +#define TARGET_TIOCNXCL	TARGET_IO('t', 14) +//#define __TIOCFLUSH       _IOW('t', 16, int) /* SunOS Specific */ +//#define __TIOCSETC        _IOW('t', 17, struct tchars) /* SunOS Specific */ +//#define __TIOCGETC        _IOR('t', 18, struct tchars) /* SunOS Specific */ +//#define __TIOCTCNTL       _IOW('t', 32, int) /* SunOS Specific */ +//#define __TIOCSIGNAL      _IOW('t', 33, int) /* SunOS Specific */ +//#define __TIOCSETX        _IOW('t', 34, int) /* SunOS Specific */ +//#define __TIOCGETX        _IOR('t', 35, int) /* SunOS Specific */ +#define TARGET_TIOCCONS	TARGET_IO('t', 36) +//#define __TIOCSSIZE     _IOW('t', 37, struct sunos_ttysize) /* SunOS Specific */ +//#define __TIOCGSIZE     _IOR('t', 38, struct sunos_ttysize) /* SunOS Specific */ +#define TARGET_TIOCGSOFTCAR	TARGET_IOR('t', 100, int) +#define TARGET_TIOCSSOFTCAR	TARGET_IOW('t', 101, int) +//#define __TIOCUCNTL       _IOW('t', 102, int) /* SunOS Specific */ +#define TARGET_TIOCSWINSZ	TARGET_IOW('t', 103, struct winsize) +#define TARGET_TIOCGWINSZ	TARGET_IOR('t', 104, struct winsize) +//#define __TIOCREMOTE      _IOW('t', 105, int) /* SunOS Specific */ +#define TARGET_TIOCMGET	TARGET_IOR('t', 106, int) +#define TARGET_TIOCMBIC	TARGET_IOW('t', 107, int) +#define TARGET_TIOCMBIS	TARGET_IOW('t', 108, int) +#define TARGET_TIOCMSET	TARGET_IOW('t', 109, int) +#define TARGET_TIOCSTART       TARGET_IO('t', 110) +#define TARGET_TIOCSTOP        TARGET_IO('t', 111) +#define TARGET_TIOCPKT		TARGET_IOW('t', 112, int) +#define TARGET_TIOCNOTTY	TARGET_IO('t', 113) +#define TARGET_TIOCSTI		TARGET_IOW('t', 114, char) +#define TARGET_TIOCOUTQ	TARGET_IOR('t', 115, int) +//#define __TIOCGLTC        _IOR('t', 116, struct ltchars) /* SunOS Specific */ +//#define __TIOCSLTC        _IOW('t', 117, struct ltchars) /* SunOS Specific */ +/* 118 is the non-posix setpgrp tty ioctl */ +/* 119 is the non-posix getpgrp tty ioctl */ +//#define __TIOCCDTR        TARGET_IO('t', 120) /* SunOS Specific */ +//#define __TIOCSDTR        TARGET_IO('t', 121) /* SunOS Specific */ +#define TARGET_TIOCCBRK        TARGET_IO('t', 122) +#define TARGET_TIOCSBRK        TARGET_IO('t', 123) +//#define __TIOCLGET        TARGET_IOW('t', 124, int) /* SunOS Specific */ +//#define __TIOCLSET        TARGET_IOW('t', 125, int) /* SunOS Specific */ +//#define __TIOCLBIC        TARGET_IOW('t', 126, int) /* SunOS Specific */ +//#define __TIOCLBIS        TARGET_IOW('t', 127, int) /* SunOS Specific */ +//#define __TIOCISPACE      TARGET_IOR('t', 128, int) /* SunOS Specific */ +//#define __TIOCISIZE       TARGET_IOR('t', 129, int) /* SunOS Specific */ +#define TARGET_TIOCSPGRP	TARGET_IOW('t', 130, int) +#define TARGET_TIOCGPGRP	TARGET_IOR('t', 131, int) +#define TARGET_TIOCSCTTY	TARGET_IO('t', 132) +#define TARGET_TIOCGSID	TARGET_IOR('t', 133, int) +/* Get minor device of a pty master's FD -- Solaris equiv is ISPTM */ +#define TARGET_TIOCGPTN	TARGET_IOR('t', 134, unsigned int) /* Get Pty Number */ +#define TARGET_TIOCSPTLCK	TARGET_IOW('t', 135, int) /* Lock/unlock PTY */ + +/* Little f */ +#define TARGET_FIOCLEX		TARGET_IO('f', 1) +#define TARGET_FIONCLEX	TARGET_IO('f', 2) +#define TARGET_FIOASYNC	TARGET_IOW('f', 125, int) +#define TARGET_FIONBIO		TARGET_IOW('f', 126, int) +#define TARGET_FIONREAD	TARGET_IOR('f', 127, int) +#define TARGET_TIOCINQ		TARGET_FIONREAD + +/* SCARY Rutgers local SunOS kernel hackery, perhaps I will support it + * someday.  This is completely bogus, I know... + */ +//#define __TCGETSTAT       TARGET_IO('T', 200) /* Rutgers specific */ +//#define __TCSETSTAT       TARGET_IO('T', 201) /* Rutgers specific */ + +/* Linux specific, no SunOS equivalent. */ +#define TARGET_TIOCLINUX	0x541C +#define TARGET_TIOCGSERIAL	0x541E +#define TARGET_TIOCSSERIAL	0x541F +#define TARGET_TCSBRKP		0x5425 +#define TARGET_TIOCTTYGSTRUCT	0x5426 +#define TARGET_TIOCSERCONFIG	0x5453 +#define TARGET_TIOCSERGWILD	0x5454 +#define TARGET_TIOCSERSWILD	0x5455 +#define TARGET_TIOCGLCKTRMIOS	0x5456 +#define TARGET_TIOCSLCKTRMIOS	0x5457 +#define TARGET_TIOCSERGSTRUCT	0x5458 /* For debugging only */ +#define TARGET_TIOCSERGETLSR   0x5459 /* Get line status register */ +#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config  */ +#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ +#define TARGET_TIOCMIWAIT	0x545C /* Wait input */ +#define TARGET_TIOCGICOUNT	0x545D /* Read serial port inline interrupt counts */ diff --git a/linux-user/strace.c b/linux-user/strace.c new file mode 100644 index 00000000..ea6c1d24 --- /dev/null +++ b/linux-user/strace.c @@ -0,0 +1,1618 @@ +#include <stdio.h> +#include <sys/ipc.h> +#include <sys/msg.h> +#include <sys/sem.h> +#include <sys/shm.h> +#include <sys/select.h> +#include <sys/types.h> +#include <sys/mount.h> +#include <sys/mman.h> +#include <unistd.h> +#include <sched.h> +#include "qemu.h" + +int do_strace=0; + +struct syscallname { +    int nr; +    const char *name; +    const char *format; +    void (*call)(const struct syscallname *, +                 abi_long, abi_long, abi_long, +                 abi_long, abi_long, abi_long); +    void (*result)(const struct syscallname *, abi_long); +}; + +#ifdef __GNUC__ +/* + * It is possible that target doesn't have syscall that uses + * following flags but we don't want the compiler to warn + * us about them being unused.  Same applies to utility print + * functions.  It is ok to keep them while not used. + */ +#define UNUSED __attribute__ ((unused)) +#else +#define UNUSED +#endif + +/* + * Structure used to translate flag values into strings.  This is + * similar that is in the actual strace tool. + */ +struct flags { +    abi_long    f_value;  /* flag */ +    const char  *f_string; /* stringified flag */ +}; + +/* common flags for all architectures */ +#define FLAG_GENERIC(name) { name, #name } +/* target specific flags (syscall_defs.h has TARGET_<flag>) */ +#define FLAG_TARGET(name)  { TARGET_ ## name, #name } +/* end of flags array */ +#define FLAG_END           { 0, NULL } + +UNUSED static const char *get_comma(int); +UNUSED static void print_pointer(abi_long, int); +UNUSED static void print_flags(const struct flags *, abi_long, int); +UNUSED static void print_at_dirfd(abi_long, int); +UNUSED static void print_file_mode(abi_long, int); +UNUSED static void print_open_flags(abi_long, int); +UNUSED static void print_syscall_prologue(const struct syscallname *); +UNUSED static void print_syscall_epilogue(const struct syscallname *); +UNUSED static void print_string(abi_long, int); +UNUSED static void print_raw_param(const char *, abi_long, int); +UNUSED static void print_timeval(abi_ulong, int); +UNUSED static void print_number(abi_long, int); +UNUSED static void print_signal(abi_ulong, int); + +/* + * Utility functions + */ +static void +print_ipc_cmd(int cmd) +{ +#define output_cmd(val) \ +if( cmd == val ) { \ +    gemu_log(#val); \ +    return; \ +} + +    cmd &= 0xff; + +    /* General IPC commands */ +    output_cmd( IPC_RMID ); +    output_cmd( IPC_SET ); +    output_cmd( IPC_STAT ); +    output_cmd( IPC_INFO ); +    /* msgctl() commands */ +    #ifdef __USER_MISC +    output_cmd( MSG_STAT ); +    output_cmd( MSG_INFO ); +    #endif +    /* shmctl() commands */ +    output_cmd( SHM_LOCK ); +    output_cmd( SHM_UNLOCK ); +    output_cmd( SHM_STAT ); +    output_cmd( SHM_INFO ); +    /* semctl() commands */ +    output_cmd( GETPID ); +    output_cmd( GETVAL ); +    output_cmd( GETALL ); +    output_cmd( GETNCNT ); +    output_cmd( GETZCNT ); +    output_cmd( SETVAL ); +    output_cmd( SETALL ); +    output_cmd( SEM_STAT ); +    output_cmd( SEM_INFO ); +    output_cmd( IPC_RMID ); +    output_cmd( IPC_RMID ); +    output_cmd( IPC_RMID ); +    output_cmd( IPC_RMID ); +    output_cmd( IPC_RMID ); +    output_cmd( IPC_RMID ); +    output_cmd( IPC_RMID ); +    output_cmd( IPC_RMID ); +    output_cmd( IPC_RMID ); + +    /* Some value we don't recognize */ +    gemu_log("%d",cmd); +} + +static void +print_signal(abi_ulong arg, int last) +{ +    const char *signal_name = NULL; +    switch(arg) { +    case TARGET_SIGHUP: signal_name = "SIGHUP"; break; +    case TARGET_SIGINT: signal_name = "SIGINT"; break; +    case TARGET_SIGQUIT: signal_name = "SIGQUIT"; break; +    case TARGET_SIGILL: signal_name = "SIGILL"; break; +    case TARGET_SIGABRT: signal_name = "SIGABRT"; break; +    case TARGET_SIGFPE: signal_name = "SIGFPE"; break; +    case TARGET_SIGKILL: signal_name = "SIGKILL"; break; +    case TARGET_SIGSEGV: signal_name = "SIGSEGV"; break; +    case TARGET_SIGPIPE: signal_name = "SIGPIPE"; break; +    case TARGET_SIGALRM: signal_name = "SIGALRM"; break; +    case TARGET_SIGTERM: signal_name = "SIGTERM"; break; +    case TARGET_SIGUSR1: signal_name = "SIGUSR1"; break; +    case TARGET_SIGUSR2: signal_name = "SIGUSR2"; break; +    case TARGET_SIGCHLD: signal_name = "SIGCHLD"; break; +    case TARGET_SIGCONT: signal_name = "SIGCONT"; break; +    case TARGET_SIGSTOP: signal_name = "SIGSTOP"; break; +    case TARGET_SIGTTIN: signal_name = "SIGTTIN"; break; +    case TARGET_SIGTTOU: signal_name = "SIGTTOU"; break; +    } +    if (signal_name == NULL) { +        print_raw_param("%ld", arg, last); +        return; +    } +    gemu_log("%s%s", signal_name, get_comma(last)); +} + +#ifdef TARGET_NR__newselect +static void +print_fdset(int n, abi_ulong target_fds_addr) +{ +    int i; + +    gemu_log("["); +    if( target_fds_addr ) { +        abi_long *target_fds; + +        target_fds = lock_user(VERIFY_READ, +                               target_fds_addr, +                               sizeof(*target_fds)*(n / TARGET_ABI_BITS + 1), +                               1); + +        if (!target_fds) +            return; + +        for (i=n; i>=0; i--) { +            if ((tswapal(target_fds[i / TARGET_ABI_BITS]) >> (i & (TARGET_ABI_BITS - 1))) & 1) +                gemu_log("%d,", i ); +            } +        unlock_user(target_fds, target_fds_addr, 0); +    } +    gemu_log("]"); +} +#endif + +/* + * Sysycall specific output functions + */ + +/* select */ +#ifdef TARGET_NR__newselect +static long newselect_arg1 = 0; +static long newselect_arg2 = 0; +static long newselect_arg3 = 0; +static long newselect_arg4 = 0; +static long newselect_arg5 = 0; + +static void +print_newselect(const struct syscallname *name, +                abi_long arg1, abi_long arg2, abi_long arg3, +                abi_long arg4, abi_long arg5, abi_long arg6) +{ +    gemu_log("%s(" TARGET_ABI_FMT_ld ",", name->name, arg1); +    print_fdset(arg1, arg2); +    gemu_log(","); +    print_fdset(arg1, arg3); +    gemu_log(","); +    print_fdset(arg1, arg4); +    gemu_log(","); +    print_timeval(arg5, 1); +    gemu_log(")"); + +    /* save for use in the return output function below */ +    newselect_arg1=arg1; +    newselect_arg2=arg2; +    newselect_arg3=arg3; +    newselect_arg4=arg4; +    newselect_arg5=arg5; +} +#endif + +#ifdef TARGET_NR_semctl +static void +print_semctl(const struct syscallname *name, +             abi_long arg1, abi_long arg2, abi_long arg3, +             abi_long arg4, abi_long arg5, abi_long arg6) +{ +    gemu_log("%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ",", name->name, arg1, arg2); +    print_ipc_cmd(arg3); +    gemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4); +} +#endif + +static void +print_execve(const struct syscallname *name, +             abi_long arg1, abi_long arg2, abi_long arg3, +             abi_long arg4, abi_long arg5, abi_long arg6) +{ +    abi_ulong arg_ptr_addr; +    char *s; + +    if (!(s = lock_user_string(arg1))) +        return; +    gemu_log("%s(\"%s\",{", name->name, s); +    unlock_user(s, arg1, 0); + +    for (arg_ptr_addr = arg2; ; arg_ptr_addr += sizeof(abi_ulong)) { +        abi_ulong *arg_ptr, arg_addr; + +	arg_ptr = lock_user(VERIFY_READ, arg_ptr_addr, sizeof(abi_ulong), 1); +        if (!arg_ptr) +            return; +    arg_addr = tswapal(*arg_ptr); +	unlock_user(arg_ptr, arg_ptr_addr, 0); +        if (!arg_addr) +            break; +        if ((s = lock_user_string(arg_addr))) { +            gemu_log("\"%s\",", s); +            unlock_user(s, arg_addr, 0); +        } +    } + +    gemu_log("NULL})"); +} + +#ifdef TARGET_NR_ipc +static void +print_ipc(const struct syscallname *name, +          abi_long arg1, abi_long arg2, abi_long arg3, +          abi_long arg4, abi_long arg5, abi_long arg6) +{ +    switch(arg1) { +    case IPCOP_semctl: +        gemu_log("semctl(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ",", arg1, arg2); +        print_ipc_cmd(arg3); +        gemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4); +        break; +    default: +        gemu_log("%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ")", +                 name->name, arg1, arg2, arg3, arg4); +    } +} +#endif + +/* + * Variants for the return value output function + */ + +static void +print_syscall_ret_addr(const struct syscallname *name, abi_long ret) +{ +    char *errstr = NULL; + +    if (ret < 0) { +        errstr = target_strerror(-ret); +    } +    if (errstr) { +        gemu_log(" = -1 errno=%d (%s)\n", (int)-ret, errstr); +    } else { +        gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret); +    } +} + +#if 0 /* currently unused */ +static void +print_syscall_ret_raw(struct syscallname *name, abi_long ret) +{ +        gemu_log(" = 0x" TARGET_ABI_FMT_lx "\n", ret); +} +#endif + +#ifdef TARGET_NR__newselect +static void +print_syscall_ret_newselect(const struct syscallname *name, abi_long ret) +{ +    gemu_log(" = 0x" TARGET_ABI_FMT_lx " (", ret); +    print_fdset(newselect_arg1,newselect_arg2); +    gemu_log(","); +    print_fdset(newselect_arg1,newselect_arg3); +    gemu_log(","); +    print_fdset(newselect_arg1,newselect_arg4); +    gemu_log(","); +    print_timeval(newselect_arg5, 1); +    gemu_log(")\n"); +} +#endif + +UNUSED static struct flags access_flags[] = { +    FLAG_GENERIC(F_OK), +    FLAG_GENERIC(R_OK), +    FLAG_GENERIC(W_OK), +    FLAG_GENERIC(X_OK), +    FLAG_END, +}; + +UNUSED static struct flags at_file_flags[] = { +#ifdef AT_EACCESS +    FLAG_GENERIC(AT_EACCESS), +#endif +#ifdef AT_SYMLINK_NOFOLLOW +    FLAG_GENERIC(AT_SYMLINK_NOFOLLOW), +#endif +    FLAG_END, +}; + +UNUSED static struct flags unlinkat_flags[] = { +#ifdef AT_REMOVEDIR +    FLAG_GENERIC(AT_REMOVEDIR), +#endif +    FLAG_END, +}; + +UNUSED static struct flags mode_flags[] = { +    FLAG_GENERIC(S_IFSOCK), +    FLAG_GENERIC(S_IFLNK), +    FLAG_GENERIC(S_IFREG), +    FLAG_GENERIC(S_IFBLK), +    FLAG_GENERIC(S_IFDIR), +    FLAG_GENERIC(S_IFCHR), +    FLAG_GENERIC(S_IFIFO), +    FLAG_END, +}; + +UNUSED static struct flags open_access_flags[] = { +    FLAG_TARGET(O_RDONLY), +    FLAG_TARGET(O_WRONLY), +    FLAG_TARGET(O_RDWR), +    FLAG_END, +}; + +UNUSED static struct flags open_flags[] = { +    FLAG_TARGET(O_APPEND), +    FLAG_TARGET(O_CREAT), +    FLAG_TARGET(O_DIRECTORY), +    FLAG_TARGET(O_EXCL), +    FLAG_TARGET(O_LARGEFILE), +    FLAG_TARGET(O_NOCTTY), +    FLAG_TARGET(O_NOFOLLOW), +    FLAG_TARGET(O_NONBLOCK),      /* also O_NDELAY */ +    FLAG_TARGET(O_DSYNC), +    FLAG_TARGET(__O_SYNC), +    FLAG_TARGET(O_TRUNC), +#ifdef O_DIRECT +    FLAG_TARGET(O_DIRECT), +#endif +#ifdef O_NOATIME +    FLAG_TARGET(O_NOATIME), +#endif +#ifdef O_CLOEXEC +    FLAG_TARGET(O_CLOEXEC), +#endif +#ifdef O_PATH +    FLAG_TARGET(O_PATH), +#endif +    FLAG_END, +}; + +UNUSED static struct flags mount_flags[] = { +#ifdef MS_BIND +    FLAG_GENERIC(MS_BIND), +#endif +#ifdef MS_DIRSYNC +    FLAG_GENERIC(MS_DIRSYNC), +#endif +    FLAG_GENERIC(MS_MANDLOCK), +#ifdef MS_MOVE +    FLAG_GENERIC(MS_MOVE), +#endif +    FLAG_GENERIC(MS_NOATIME), +    FLAG_GENERIC(MS_NODEV), +    FLAG_GENERIC(MS_NODIRATIME), +    FLAG_GENERIC(MS_NOEXEC), +    FLAG_GENERIC(MS_NOSUID), +    FLAG_GENERIC(MS_RDONLY), +#ifdef MS_RELATIME +    FLAG_GENERIC(MS_RELATIME), +#endif +    FLAG_GENERIC(MS_REMOUNT), +    FLAG_GENERIC(MS_SYNCHRONOUS), +    FLAG_END, +}; + +UNUSED static struct flags umount2_flags[] = { +#ifdef MNT_FORCE +    FLAG_GENERIC(MNT_FORCE), +#endif +#ifdef MNT_DETACH +    FLAG_GENERIC(MNT_DETACH), +#endif +#ifdef MNT_EXPIRE +    FLAG_GENERIC(MNT_EXPIRE), +#endif +    FLAG_END, +}; + +UNUSED static struct flags mmap_prot_flags[] = { +    FLAG_GENERIC(PROT_NONE), +    FLAG_GENERIC(PROT_EXEC), +    FLAG_GENERIC(PROT_READ), +    FLAG_GENERIC(PROT_WRITE), +    FLAG_TARGET(PROT_SEM), +    FLAG_GENERIC(PROT_GROWSDOWN), +    FLAG_GENERIC(PROT_GROWSUP), +    FLAG_END, +}; + +UNUSED static struct flags mmap_flags[] = { +    FLAG_TARGET(MAP_SHARED), +    FLAG_TARGET(MAP_PRIVATE), +    FLAG_TARGET(MAP_ANONYMOUS), +    FLAG_TARGET(MAP_DENYWRITE), +    FLAG_TARGET(MAP_FIXED), +    FLAG_TARGET(MAP_GROWSDOWN), +    FLAG_TARGET(MAP_EXECUTABLE), +#ifdef MAP_LOCKED +    FLAG_TARGET(MAP_LOCKED), +#endif +#ifdef MAP_NONBLOCK +    FLAG_TARGET(MAP_NONBLOCK), +#endif +    FLAG_TARGET(MAP_NORESERVE), +#ifdef MAP_POPULATE +    FLAG_TARGET(MAP_POPULATE), +#endif +#ifdef TARGET_MAP_UNINITIALIZED +    FLAG_TARGET(MAP_UNINITIALIZED), +#endif +    FLAG_END, +}; + +UNUSED static struct flags clone_flags[] = { +    FLAG_GENERIC(CLONE_VM), +    FLAG_GENERIC(CLONE_FS), +    FLAG_GENERIC(CLONE_FILES), +    FLAG_GENERIC(CLONE_SIGHAND), +    FLAG_GENERIC(CLONE_PTRACE), +    FLAG_GENERIC(CLONE_VFORK), +    FLAG_GENERIC(CLONE_PARENT), +    FLAG_GENERIC(CLONE_THREAD), +    FLAG_GENERIC(CLONE_NEWNS), +    FLAG_GENERIC(CLONE_SYSVSEM), +    FLAG_GENERIC(CLONE_SETTLS), +    FLAG_GENERIC(CLONE_PARENT_SETTID), +    FLAG_GENERIC(CLONE_CHILD_CLEARTID), +    FLAG_GENERIC(CLONE_DETACHED), +    FLAG_GENERIC(CLONE_UNTRACED), +    FLAG_GENERIC(CLONE_CHILD_SETTID), +#if defined(CLONE_NEWUTS) +    FLAG_GENERIC(CLONE_NEWUTS), +#endif +#if defined(CLONE_NEWIPC) +    FLAG_GENERIC(CLONE_NEWIPC), +#endif +#if defined(CLONE_NEWUSER) +    FLAG_GENERIC(CLONE_NEWUSER), +#endif +#if defined(CLONE_NEWPID) +    FLAG_GENERIC(CLONE_NEWPID), +#endif +#if defined(CLONE_NEWNET) +    FLAG_GENERIC(CLONE_NEWNET), +#endif +#if defined(CLONE_IO) +    FLAG_GENERIC(CLONE_IO), +#endif +    FLAG_END, +}; + +/* + * print_xxx utility functions.  These are used to print syscall + * parameters in certain format.  All of these have parameter + * named 'last'.  This parameter is used to add comma to output + * when last == 0. + */ + +static const char * +get_comma(int last) +{ +    return ((last) ? "" : ","); +} + +static void +print_flags(const struct flags *f, abi_long flags, int last) +{ +    const char *sep = ""; +    int n; + +    if ((flags == 0) && (f->f_value == 0)) { +        gemu_log("%s%s", f->f_string, get_comma(last)); +        return; +    } +    for (n = 0; f->f_string != NULL; f++) { +        if ((f->f_value != 0) && ((flags & f->f_value) == f->f_value)) { +            gemu_log("%s%s", sep, f->f_string); +            flags &= ~f->f_value; +            sep = "|"; +            n++; +        } +    } + +    if (n > 0) { +        /* print rest of the flags as numeric */ +        if (flags != 0) { +            gemu_log("%s%#x%s", sep, (unsigned int)flags, get_comma(last)); +        } else { +            gemu_log("%s", get_comma(last)); +        } +    } else { +        /* no string version of flags found, print them in hex then */ +        gemu_log("%#x%s", (unsigned int)flags, get_comma(last)); +    } +} + +static void +print_at_dirfd(abi_long dirfd, int last) +{ +#ifdef AT_FDCWD +    if (dirfd == AT_FDCWD) { +        gemu_log("AT_FDCWD%s", get_comma(last)); +        return; +    } +#endif +    gemu_log("%d%s", (int)dirfd, get_comma(last)); +} + +static void +print_file_mode(abi_long mode, int last) +{ +    const char *sep = ""; +    const struct flags *m; + +    for (m = &mode_flags[0]; m->f_string != NULL; m++) { +        if ((m->f_value & mode) == m->f_value) { +            gemu_log("%s%s", m->f_string, sep); +            sep = "|"; +            mode &= ~m->f_value; +            break; +        } +    } + +    mode &= ~S_IFMT; +    /* print rest of the mode as octal */ +    if (mode != 0) +        gemu_log("%s%#o", sep, (unsigned int)mode); + +    gemu_log("%s", get_comma(last)); +} + +static void +print_open_flags(abi_long flags, int last) +{ +    print_flags(open_access_flags, flags & TARGET_O_ACCMODE, 1); +    flags &= ~TARGET_O_ACCMODE; +    if (flags == 0) { +        gemu_log("%s", get_comma(last)); +        return; +    } +    gemu_log("|"); +    print_flags(open_flags, flags, last); +} + +static void +print_syscall_prologue(const struct syscallname *sc) +{ +    gemu_log("%s(", sc->name); +} + +/*ARGSUSED*/ +static void +print_syscall_epilogue(const struct syscallname *sc) +{ +    (void)sc; +    gemu_log(")"); +} + +static void +print_string(abi_long addr, int last) +{ +    char *s; + +    if ((s = lock_user_string(addr)) != NULL) { +        gemu_log("\"%s\"%s", s, get_comma(last)); +        unlock_user(s, addr, 0); +    } else { +        /* can't get string out of it, so print it as pointer */ +        print_pointer(addr, last); +    } +} + +/* + * Prints out raw parameter using given format.  Caller needs + * to do byte swapping if needed. + */ +static void +print_raw_param(const char *fmt, abi_long param, int last) +{ +    char format[64]; + +    (void) snprintf(format, sizeof (format), "%s%s", fmt, get_comma(last)); +    gemu_log(format, param); +} + +static void +print_pointer(abi_long p, int last) +{ +    if (p == 0) +        gemu_log("NULL%s", get_comma(last)); +    else +        gemu_log("0x" TARGET_ABI_FMT_lx "%s", p, get_comma(last)); +} + +/* + * Reads 32-bit (int) number from guest address space from + * address 'addr' and prints it. + */ +static void +print_number(abi_long addr, int last) +{ +    if (addr == 0) { +        gemu_log("NULL%s", get_comma(last)); +    } else { +        int num; + +        get_user_s32(num, addr); +        gemu_log("[%d]%s", num, get_comma(last)); +    } +} + +static void +print_timeval(abi_ulong tv_addr, int last) +{ +    if( tv_addr ) { +        struct target_timeval *tv; + +        tv = lock_user(VERIFY_READ, tv_addr, sizeof(*tv), 1); +        if (!tv) +            return; +        gemu_log("{" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "}%s", +            tswapal(tv->tv_sec), tswapal(tv->tv_usec), get_comma(last)); +        unlock_user(tv, tv_addr, 0); +    } else +        gemu_log("NULL%s", get_comma(last)); +} + +#undef UNUSED + +#ifdef TARGET_NR_accept +static void +print_accept(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_raw_param("%d", arg0, 0); +    print_pointer(arg1, 0); +    print_number(arg2, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_access +static void +print_access(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 0); +    print_flags(access_flags, arg1, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_brk +static void +print_brk(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_pointer(arg0, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_chdir +static void +print_chdir(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_chmod +static void +print_chmod(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 0); +    print_file_mode(arg1, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_clone +static void +print_clone(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +#if defined(TARGET_M68K) +    print_flags(clone_flags, arg0, 0); +    print_raw_param("newsp=0x" TARGET_ABI_FMT_lx, arg1, 1); +#elif defined(TARGET_SH4) || defined(TARGET_ALPHA) +    print_flags(clone_flags, arg0, 0); +    print_raw_param("child_stack=0x" TARGET_ABI_FMT_lx, arg1, 0); +    print_raw_param("parent_tidptr=0x" TARGET_ABI_FMT_lx, arg2, 0); +    print_raw_param("child_tidptr=0x" TARGET_ABI_FMT_lx, arg3, 0); +    print_raw_param("tls=0x" TARGET_ABI_FMT_lx, arg4, 1); +#elif defined(TARGET_CRIS) +    print_raw_param("child_stack=0x" TARGET_ABI_FMT_lx, arg0, 0); +    print_flags(clone_flags, arg1, 0); +    print_raw_param("parent_tidptr=0x" TARGET_ABI_FMT_lx, arg2, 0); +    print_raw_param("tls=0x" TARGET_ABI_FMT_lx, arg3, 0); +    print_raw_param("child_tidptr=0x" TARGET_ABI_FMT_lx, arg4, 1); +#else +    print_flags(clone_flags, arg0, 0); +    print_raw_param("child_stack=0x" TARGET_ABI_FMT_lx, arg1, 0); +    print_raw_param("parent_tidptr=0x" TARGET_ABI_FMT_lx, arg2, 0); +    print_raw_param("tls=0x" TARGET_ABI_FMT_lx, arg3, 0); +    print_raw_param("child_tidptr=0x" TARGET_ABI_FMT_lx, arg4, 1); +#endif +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_creat +static void +print_creat(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 0); +    print_file_mode(arg1, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_execv +static void +print_execv(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 0); +    print_raw_param("0x" TARGET_ABI_FMT_lx, arg1, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_faccessat +static void +print_faccessat(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_at_dirfd(arg0, 0); +    print_string(arg1, 0); +    print_flags(access_flags, arg2, 0); +    print_flags(at_file_flags, arg3, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_fchmodat +static void +print_fchmodat(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_at_dirfd(arg0, 0); +    print_string(arg1, 0); +    print_file_mode(arg2, 0); +    print_flags(at_file_flags, arg3, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_fchownat +static void +print_fchownat(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_at_dirfd(arg0, 0); +    print_string(arg1, 0); +    print_raw_param("%d", arg2, 0); +    print_raw_param("%d", arg3, 0); +    print_flags(at_file_flags, arg4, 1); +    print_syscall_epilogue(name); +} +#endif + +#if defined(TARGET_NR_fcntl) || defined(TARGET_NR_fcntl64) +static void +print_fcntl(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_raw_param("%d", arg0, 0); +    switch(arg1) { +    case TARGET_F_DUPFD: +        gemu_log("F_DUPFD,"); +        print_raw_param(TARGET_ABI_FMT_ld, arg2, 1); +        break; +    case TARGET_F_GETFD: +        gemu_log("F_GETFD"); +        break; +    case TARGET_F_SETFD: +        gemu_log("F_SETFD,"); +        print_raw_param(TARGET_ABI_FMT_ld, arg2, 1); +        break; +    case TARGET_F_GETFL: +        gemu_log("F_GETFL"); +        break; +    case TARGET_F_SETFL: +        gemu_log("F_SETFL,"); +        print_open_flags(arg2, 1); +        break; +    case TARGET_F_GETLK: +        gemu_log("F_GETLK,"); +        print_pointer(arg2, 1); +        break; +    case TARGET_F_SETLK: +        gemu_log("F_SETLK,"); +        print_pointer(arg2, 1); +        break; +    case TARGET_F_SETLKW: +        gemu_log("F_SETLKW,"); +        print_pointer(arg2, 1); +        break; +    case TARGET_F_GETOWN: +        gemu_log("F_GETOWN"); +        break; +    case TARGET_F_SETOWN: +        gemu_log("F_SETOWN,"); +        print_raw_param(TARGET_ABI_FMT_ld, arg2, 0); +        break; +    case TARGET_F_GETSIG: +        gemu_log("F_GETSIG"); +        break; +    case TARGET_F_SETSIG: +        gemu_log("F_SETSIG,"); +        print_raw_param(TARGET_ABI_FMT_ld, arg2, 0); +        break; +#if TARGET_ABI_BITS == 32 +    case TARGET_F_GETLK64: +        gemu_log("F_GETLK64,"); +        print_pointer(arg2, 1); +        break; +    case TARGET_F_SETLK64: +        gemu_log("F_SETLK64,"); +        print_pointer(arg2, 1); +        break; +    case TARGET_F_SETLKW64: +        gemu_log("F_SETLKW64,"); +        print_pointer(arg2, 1); +        break; +#endif +    case TARGET_F_SETLEASE: +        gemu_log("F_SETLEASE,"); +        print_raw_param(TARGET_ABI_FMT_ld, arg2, 0); +        break; +    case TARGET_F_GETLEASE: +        gemu_log("F_GETLEASE"); +        break; +    case TARGET_F_DUPFD_CLOEXEC: +        gemu_log("F_DUPFD_CLOEXEC,"); +        print_raw_param(TARGET_ABI_FMT_ld, arg2, 1); +        break; +    case TARGET_F_NOTIFY: +        gemu_log("F_NOTIFY,"); +        print_raw_param(TARGET_ABI_FMT_ld, arg2, 0); +        break; +    default: +        print_raw_param(TARGET_ABI_FMT_ld, arg1, 0); +        print_pointer(arg2, 1); +        break; +    } +    print_syscall_epilogue(name); +} +#define print_fcntl64   print_fcntl +#endif + + +#ifdef TARGET_NR_futimesat +static void +print_futimesat(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_at_dirfd(arg0, 0); +    print_string(arg1, 0); +    print_timeval(arg2, 0); +    print_timeval(arg2 + sizeof (struct target_timeval), 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_link +static void +print_link(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 0); +    print_string(arg1, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_linkat +static void +print_linkat(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_at_dirfd(arg0, 0); +    print_string(arg1, 0); +    print_at_dirfd(arg2, 0); +    print_string(arg3, 0); +    print_flags(at_file_flags, arg4, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR__llseek +static void +print__llseek(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    const char *whence = "UNKNOWN"; +    print_syscall_prologue(name); +    print_raw_param("%d", arg0, 0); +    print_raw_param("%ld", arg1, 0); +    print_raw_param("%ld", arg2, 0); +    print_pointer(arg3, 0); +    switch(arg4) { +    case SEEK_SET: whence = "SEEK_SET"; break; +    case SEEK_CUR: whence = "SEEK_CUR"; break; +    case SEEK_END: whence = "SEEK_END"; break; +    } +    gemu_log("%s",whence); +    print_syscall_epilogue(name); +} +#endif + +#if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) || \ +    defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) +static void +print_stat(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 0); +    print_pointer(arg1, 1); +    print_syscall_epilogue(name); +} +#define print_lstat     print_stat +#define print_stat64	print_stat +#define print_lstat64   print_stat +#endif + +#if defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) +static void +print_fstat(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_raw_param("%d", arg0, 0); +    print_pointer(arg1, 1); +    print_syscall_epilogue(name); +} +#define print_fstat64     print_fstat +#endif + +#ifdef TARGET_NR_mkdir +static void +print_mkdir(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 0); +    print_file_mode(arg1, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_mkdirat +static void +print_mkdirat(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_at_dirfd(arg0, 0); +    print_string(arg1, 0); +    print_file_mode(arg2, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_rmdir +static void +print_rmdir(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 0); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_rt_sigaction +static void +print_rt_sigaction(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_signal(arg0, 0); +    print_pointer(arg1, 0); +    print_pointer(arg2, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_rt_sigprocmask +static void +print_rt_sigprocmask(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    const char *how = "UNKNOWN"; +    print_syscall_prologue(name); +    switch(arg0) { +    case TARGET_SIG_BLOCK: how = "SIG_BLOCK"; break; +    case TARGET_SIG_UNBLOCK: how = "SIG_UNBLOCK"; break; +    case TARGET_SIG_SETMASK: how = "SIG_SETMASK"; break; +    } +    gemu_log("%s,",how); +    print_pointer(arg1, 0); +    print_pointer(arg2, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_mknod +static void +print_mknod(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    int hasdev = (arg1 & (S_IFCHR|S_IFBLK)); + +    print_syscall_prologue(name); +    print_string(arg0, 0); +    print_file_mode(arg1, (hasdev == 0)); +    if (hasdev) { +        print_raw_param("makedev(%d", major(arg2), 0); +        print_raw_param("%d)", minor(arg2), 1); +    } +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_mknodat +static void +print_mknodat(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    int hasdev = (arg2 & (S_IFCHR|S_IFBLK)); + +    print_syscall_prologue(name); +    print_at_dirfd(arg0, 0); +    print_string(arg1, 0); +    print_file_mode(arg2, (hasdev == 0)); +    if (hasdev) { +        print_raw_param("makedev(%d", major(arg3), 0); +        print_raw_param("%d)", minor(arg3), 1); +    } +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_mq_open +static void +print_mq_open(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    int is_creat = (arg1 & TARGET_O_CREAT); + +    print_syscall_prologue(name); +    print_string(arg0, 0); +    print_open_flags(arg1, (is_creat == 0)); +    if (is_creat) { +        print_file_mode(arg2, 0); +        print_pointer(arg3, 1); +    } +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_open +static void +print_open(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    int is_creat = (arg1 & TARGET_O_CREAT); + +    print_syscall_prologue(name); +    print_string(arg0, 0); +    print_open_flags(arg1, (is_creat == 0)); +    if (is_creat) +        print_file_mode(arg2, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_openat +static void +print_openat(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    int is_creat = (arg2 & TARGET_O_CREAT); + +    print_syscall_prologue(name); +    print_at_dirfd(arg0, 0); +    print_string(arg1, 0); +    print_open_flags(arg2, (is_creat == 0)); +    if (is_creat) +        print_file_mode(arg3, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_mq_unlink +static void +print_mq_unlink(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 1); +    print_syscall_epilogue(name); +} +#endif + +#if defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat) +static void +print_fstatat64(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_at_dirfd(arg0, 0); +    print_string(arg1, 0); +    print_pointer(arg2, 0); +    print_flags(at_file_flags, arg3, 1); +    print_syscall_epilogue(name); +} +#define print_newfstatat    print_fstatat64 +#endif + +#ifdef TARGET_NR_readlink +static void +print_readlink(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 0); +    print_pointer(arg1, 0); +    print_raw_param("%u", arg2, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_readlinkat +static void +print_readlinkat(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_at_dirfd(arg0, 0); +    print_string(arg1, 0); +    print_pointer(arg2, 0); +    print_raw_param("%u", arg3, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_rename +static void +print_rename(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 0); +    print_string(arg1, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_renameat +static void +print_renameat(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_at_dirfd(arg0, 0); +    print_string(arg1, 0); +    print_at_dirfd(arg2, 0); +    print_string(arg3, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_statfs +static void +print_statfs(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 0); +    print_pointer(arg1, 1); +    print_syscall_epilogue(name); +} +#define print_statfs64  print_statfs +#endif + +#ifdef TARGET_NR_symlink +static void +print_symlink(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 0); +    print_string(arg1, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_symlinkat +static void +print_symlinkat(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 0); +    print_at_dirfd(arg1, 0); +    print_string(arg2, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_mount +static void +print_mount(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 0); +    print_string(arg1, 0); +    print_string(arg2, 0); +    print_flags(mount_flags, arg3, 0); +    print_pointer(arg4, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_umount +static void +print_umount(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_umount2 +static void +print_umount2(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 0); +    print_flags(umount2_flags, arg1, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_unlink +static void +print_unlink(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_unlinkat +static void +print_unlinkat(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_at_dirfd(arg0, 0); +    print_string(arg1, 0); +    print_flags(unlinkat_flags, arg2, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_utime +static void +print_utime(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 0); +    print_pointer(arg1, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_utimes +static void +print_utimes(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_string(arg0, 0); +    print_pointer(arg1, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_utimensat +static void +print_utimensat(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_at_dirfd(arg0, 0); +    print_string(arg1, 0); +    print_pointer(arg2, 0); +    print_flags(at_file_flags, arg3, 1); +    print_syscall_epilogue(name); +} +#endif + +#if defined(TARGET_NR_mmap) || defined(TARGET_NR_mmap2) +static void +print_mmap(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_pointer(arg0, 0); +    print_raw_param("%d", arg1, 0); +    print_flags(mmap_prot_flags, arg2, 0); +    print_flags(mmap_flags, arg3, 0); +    print_raw_param("%d", arg4, 0); +    print_raw_param("%#x", arg5, 1); +    print_syscall_epilogue(name); +} +#define print_mmap2     print_mmap +#endif + +#ifdef TARGET_NR_mprotect +static void +print_mprotect(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_pointer(arg0, 0); +    print_raw_param("%d", arg1, 0); +    print_flags(mmap_prot_flags, arg2, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_munmap +static void +print_munmap(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_pointer(arg0, 0); +    print_raw_param("%d", arg1, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_futex +static void print_futex_op(abi_long tflag, int last) +{ +#define print_op(val) \ +if( cmd == val ) { \ +    gemu_log(#val); \ +    return; \ +} + +    int cmd = (int)tflag; +#ifdef FUTEX_PRIVATE_FLAG +    if (cmd & FUTEX_PRIVATE_FLAG) { +        gemu_log("FUTEX_PRIVATE_FLAG|"); +        cmd &= ~FUTEX_PRIVATE_FLAG; +    } +#endif +#ifdef FUTEX_CLOCK_REALTIME +    if (cmd & FUTEX_CLOCK_REALTIME) { +        gemu_log("FUTEX_CLOCK_REALTIME|"); +        cmd &= ~FUTEX_CLOCK_REALTIME; +    } +#endif +    print_op(FUTEX_WAIT) +    print_op(FUTEX_WAKE) +    print_op(FUTEX_FD) +    print_op(FUTEX_REQUEUE) +    print_op(FUTEX_CMP_REQUEUE) +    print_op(FUTEX_WAKE_OP) +    print_op(FUTEX_LOCK_PI) +    print_op(FUTEX_UNLOCK_PI) +    print_op(FUTEX_TRYLOCK_PI) +#ifdef FUTEX_WAIT_BITSET +    print_op(FUTEX_WAIT_BITSET) +#endif +#ifdef FUTEX_WAKE_BITSET +    print_op(FUTEX_WAKE_BITSET) +#endif +    /* unknown values */ +    gemu_log("%d",cmd); +} + +static void +print_futex(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_pointer(arg0, 0); +    print_futex_op(arg1, 0); +    print_raw_param(",%d", arg2, 0); +    print_pointer(arg3, 0); /* struct timespec */ +    print_pointer(arg4, 0); +    print_raw_param("%d", arg4, 1); +    print_syscall_epilogue(name); +} +#endif + +#ifdef TARGET_NR_kill +static void +print_kill(const struct syscallname *name, +    abi_long arg0, abi_long arg1, abi_long arg2, +    abi_long arg3, abi_long arg4, abi_long arg5) +{ +    print_syscall_prologue(name); +    print_raw_param("%d", arg0, 0); +    print_signal(arg1, 1); +    print_syscall_epilogue(name); +} +#endif + +/* + * An array of all of the syscalls we know about + */ + +static const struct syscallname scnames[] = { +#include "strace.list" +}; + +static int nsyscalls = ARRAY_SIZE(scnames); + +/* + * The public interface to this module. + */ +void +print_syscall(int num, +              abi_long arg1, abi_long arg2, abi_long arg3, +              abi_long arg4, abi_long arg5, abi_long arg6) +{ +    int i; +    const char *format="%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ")"; + +    gemu_log("%d ", getpid() ); + +    for(i=0;i<nsyscalls;i++) +        if( scnames[i].nr == num ) { +            if( scnames[i].call != NULL ) { +                scnames[i].call(&scnames[i],arg1,arg2,arg3,arg4,arg5,arg6); +            } else { +                /* XXX: this format system is broken because it uses +                   host types and host pointers for strings */ +                if( scnames[i].format != NULL ) +                    format = scnames[i].format; +                gemu_log(format,scnames[i].name, arg1,arg2,arg3,arg4,arg5,arg6); +            } +            return; +        } +    gemu_log("Unknown syscall %d\n", num); +} + + +void +print_syscall_ret(int num, abi_long ret) +{ +    int i; +    char *errstr = NULL; + +    for(i=0;i<nsyscalls;i++) +        if( scnames[i].nr == num ) { +            if( scnames[i].result != NULL ) { +                scnames[i].result(&scnames[i],ret); +            } else { +                if (ret < 0) { +                    errstr = target_strerror(-ret); +                } +                if (errstr) { +                    gemu_log(" = -1 errno=" TARGET_ABI_FMT_ld " (%s)\n", +                             -ret, errstr); +                } else { +                    gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret); +                } +            } +            break; +        } +} diff --git a/linux-user/strace.list b/linux-user/strace.list new file mode 100644 index 00000000..aa0cd735 --- /dev/null +++ b/linux-user/strace.list @@ -0,0 +1,1544 @@ +/* + * Note that if you change format strings in these, check also + * that corresponding print functions are able to handle string + * locking correctly (see strace.c). + */ +#ifdef TARGET_NR_accept +{ TARGET_NR_accept, "accept" , NULL, print_accept, NULL }, +#endif +#ifdef TARGET_NR_access +{ TARGET_NR_access, "access" , NULL, print_access, NULL }, +#endif +#ifdef TARGET_NR_acct +{ TARGET_NR_acct, "acct" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_add_key +{ TARGET_NR_add_key, "add_key" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_adjtimex +{ TARGET_NR_adjtimex, "adjtimex" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_afs_syscall +{ TARGET_NR_afs_syscall, "afs_syscall" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_alarm +{ TARGET_NR_alarm, "alarm" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_aplib +{ TARGET_NR_aplib, "aplib" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_arch_prctl +{ TARGET_NR_arch_prctl, "arch_prctl" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_arm_fadvise64_64 +{ TARGET_NR_arm_fadvise64_64, "arm_fadvise64_64" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_bdflush +{ TARGET_NR_bdflush, "bdflush" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_bind +{ TARGET_NR_bind, "bind" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_break +{ TARGET_NR_break, "break" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_brk +{ TARGET_NR_brk, "brk" , NULL, print_brk, print_syscall_ret_addr }, +#endif +#ifdef TARGET_NR_cachectl +{ TARGET_NR_cachectl, "cachectl" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_cacheflush +{ TARGET_NR_cacheflush, "cacheflush" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_capget +{ TARGET_NR_capget, "capget" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_capset +{ TARGET_NR_capset, "capset" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_chdir +{ TARGET_NR_chdir, "chdir" , NULL, print_chdir, NULL }, +#endif +#ifdef TARGET_NR_chmod +{ TARGET_NR_chmod, "chmod" , NULL, print_chmod, NULL }, +#endif +#ifdef TARGET_NR_chown +{ TARGET_NR_chown, "chown" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_chown32 +{ TARGET_NR_chown32, "chown32" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_chroot +{ TARGET_NR_chroot, "chroot" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_clock_getres +{ TARGET_NR_clock_getres, "clock_getres" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_clock_gettime +{ TARGET_NR_clock_gettime, "clock_gettime" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_clock_nanosleep +{ TARGET_NR_clock_nanosleep, "clock_nanosleep" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_clock_settime +{ TARGET_NR_clock_settime, "clock_settime" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_clone +{ TARGET_NR_clone, "clone" , NULL, print_clone, NULL }, +#endif +#ifdef TARGET_NR_close +{ TARGET_NR_close, "close" , "%s(%d)", NULL, NULL }, +#endif +#ifdef TARGET_NR_connect +{ TARGET_NR_connect, "connect" , "%s(%d,%#x,%d)", NULL, NULL }, +#endif +#ifdef TARGET_NR_creat +{ TARGET_NR_creat, "creat" , NULL, print_creat, NULL }, +#endif +#ifdef TARGET_NR_create_module +{ TARGET_NR_create_module, "create_module" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_delete_module +{ TARGET_NR_delete_module, "delete_module" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_dipc +{ TARGET_NR_dipc, "dipc" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_dup +{ TARGET_NR_dup, "dup" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_dup2 +{ TARGET_NR_dup2, "dup2" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_epoll_create +{ TARGET_NR_epoll_create, "epoll_create" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_epoll_create1 +{ TARGET_NR_epoll_create1, "epoll_create1" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_epoll_ctl +{ TARGET_NR_epoll_ctl, "epoll_ctl" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_epoll_ctl_old +{ TARGET_NR_epoll_ctl_old, "epoll_ctl_old" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_epoll_wait +{ TARGET_NR_epoll_wait, "epoll_wait" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_epoll_wait_old +{ TARGET_NR_epoll_wait_old, "epoll_wait_old" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_execv +{ TARGET_NR_execv, "execv" , NULL, print_execv, NULL }, +#endif +#ifdef TARGET_NR_execve +{ TARGET_NR_execve, "execve" , NULL, print_execve, NULL }, +#endif +#ifdef TARGET_NR_exec_with_loader +{ TARGET_NR_exec_with_loader, "exec_with_loader" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_exit +{ TARGET_NR_exit, "exit" , "%s(%d)\n", NULL, NULL }, +#endif +#ifdef TARGET_NR__exit +{ TARGET_NR__exit, "_exit" , "%s(%d)\n", NULL, NULL }, +#endif +#ifdef TARGET_NR_exit_group +{ TARGET_NR_exit_group, "exit_group" , "%s(%d)\n", NULL, NULL }, +#endif +#ifdef TARGET_NR_faccessat +{ TARGET_NR_faccessat, "faccessat" , NULL, print_faccessat, NULL }, +#endif +#ifdef TARGET_NR_fadvise64 +{ TARGET_NR_fadvise64, "fadvise64" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_fadvise64_64 +{ TARGET_NR_fadvise64_64, "fadvise64_64" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_fchdir +{ TARGET_NR_fchdir, "fchdir" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_fchmod +{ TARGET_NR_fchmod, "fchmod" , "%s(%d,%#o)", NULL, NULL }, +#endif +#ifdef TARGET_NR_fchmodat +{ TARGET_NR_fchmodat, "fchmodat" , NULL, print_fchmodat, NULL }, +#endif +#ifdef TARGET_NR_fchown +{ TARGET_NR_fchown, "fchown" , "%s(%d,%d,%d)", NULL, NULL }, +#endif +#ifdef TARGET_NR_fchown32 +{ TARGET_NR_fchown32, "fchown32" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_fchownat +{ TARGET_NR_fchownat, "fchownat" , NULL, print_fchownat, NULL }, +#endif +#ifdef TARGET_NR_fcntl +{ TARGET_NR_fcntl, "fcntl" , NULL, print_fcntl, NULL }, +#endif +#ifdef TARGET_NR_fcntl64 +{ TARGET_NR_fcntl64, "fcntl64" , NULL, print_fcntl64, NULL }, +#endif +#ifdef TARGET_NR_fdatasync +{ TARGET_NR_fdatasync, "fdatasync" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_fgetxattr +{ TARGET_NR_fgetxattr, "fgetxattr" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_flistxattr +{ TARGET_NR_flistxattr, "flistxattr" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_flock +{ TARGET_NR_flock, "flock" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_fork +{ TARGET_NR_fork, "fork" , "%s()", NULL, NULL }, +#endif +#ifdef TARGET_NR_fremovexattr +{ TARGET_NR_fremovexattr, "fremovexattr" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_fsetxattr +{ TARGET_NR_fsetxattr, "fsetxattr" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_fstat +{ TARGET_NR_fstat, "fstat" , NULL, print_fstat, NULL }, +#endif +#ifdef TARGET_NR_fstat64 +{ TARGET_NR_fstat64, "fstat64" , NULL, print_fstat64, NULL }, +#endif +#ifdef TARGET_NR_fstatfs +{ TARGET_NR_fstatfs, "fstatfs" , "%s(%d,%p)", NULL, NULL }, +#endif +#ifdef TARGET_NR_fstatfs64 +{ TARGET_NR_fstatfs64, "fstatfs64" , "%s(%d,%p)", NULL, NULL }, +#endif +#ifdef TARGET_NR_fsync +{ TARGET_NR_fsync, "fsync" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_ftime +{ TARGET_NR_ftime, "ftime" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_ftruncate +{ TARGET_NR_ftruncate, "ftruncate" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_ftruncate64 +{ TARGET_NR_ftruncate64, "ftruncate64" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_futex +{ TARGET_NR_futex, "futex" , NULL, print_futex, NULL }, +#endif +#ifdef TARGET_NR_futimesat +{ TARGET_NR_futimesat, "futimesat" , NULL, print_futimesat, NULL }, +#endif +#ifdef TARGET_NR_getcwd +{ TARGET_NR_getcwd, "getcwd" , "%s(%p,%d)", NULL, NULL }, +#endif +#ifdef TARGET_NR_getdents +{ TARGET_NR_getdents, "getdents" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getdents64 +{ TARGET_NR_getdents64, "getdents64" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getdomainname +{ TARGET_NR_getdomainname, "getdomainname" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getdtablesize +{ TARGET_NR_getdtablesize, "getdtablesize" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getegid +{ TARGET_NR_getegid, "getegid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getegid32 +{ TARGET_NR_getegid32, "getegid32" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_geteuid +{ TARGET_NR_geteuid, "geteuid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_geteuid32 +{ TARGET_NR_geteuid32, "geteuid32" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getgid +{ TARGET_NR_getgid, "getgid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getgid32 +{ TARGET_NR_getgid32, "getgid32" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getgroups +{ TARGET_NR_getgroups, "getgroups" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getgroups32 +{ TARGET_NR_getgroups32, "getgroups32" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_gethostname +{ TARGET_NR_gethostname, "gethostname" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getitimer +{ TARGET_NR_getitimer, "getitimer" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_get_kernel_syms +{ TARGET_NR_get_kernel_syms, "get_kernel_syms" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_get_mempolicy +{ TARGET_NR_get_mempolicy, "get_mempolicy" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getpagesize +{ TARGET_NR_getpagesize, "getpagesize" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getpeername +{ TARGET_NR_getpeername, "getpeername" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getpgid +{ TARGET_NR_getpgid, "getpgid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getpgrp +{ TARGET_NR_getpgrp, "getpgrp" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getpid +{ TARGET_NR_getpid, "getpid" , "%s()", NULL, NULL }, +#endif +#ifdef TARGET_NR_getpmsg +{ TARGET_NR_getpmsg, "getpmsg" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getppid +{ TARGET_NR_getppid, "getppid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getpriority +{ TARGET_NR_getpriority, "getpriority", "%s(%#x,%#x)", NULL, NULL }, +#endif +#ifdef TARGET_NR_getresgid +{ TARGET_NR_getresgid, "getresgid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getresgid32 +{ TARGET_NR_getresgid32, "getresgid32" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getresuid +{ TARGET_NR_getresuid, "getresuid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getresuid32 +{ TARGET_NR_getresuid32, "getresuid32" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getrlimit +{ TARGET_NR_getrlimit, "getrlimit" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_get_robust_list +{ TARGET_NR_get_robust_list, "get_robust_list" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getrusage +{ TARGET_NR_getrusage, "getrusage" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getsid +{ TARGET_NR_getsid, "getsid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getsockname +{ TARGET_NR_getsockname, "getsockname" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getsockopt +{ TARGET_NR_getsockopt, "getsockopt" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_get_thread_area +{ TARGET_NR_get_thread_area, "get_thread_area" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_gettid +{ TARGET_NR_gettid, "gettid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_gettimeofday +{ TARGET_NR_gettimeofday, "gettimeofday" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getuid +{ TARGET_NR_getuid, "getuid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getuid32 +{ TARGET_NR_getuid32, "getuid32" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getxattr +{ TARGET_NR_getxattr, "getxattr" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getxgid +{ TARGET_NR_getxgid, "getxgid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getxpid +{ TARGET_NR_getxpid, "getxpid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_getxuid +{ TARGET_NR_getxuid, "getxuid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_gtty +{ TARGET_NR_gtty, "gtty" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_idle +{ TARGET_NR_idle, "idle" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_init_module +{ TARGET_NR_init_module, "init_module" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_inotify_add_watch +{ TARGET_NR_inotify_add_watch, "inotify_add_watch" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_inotify_init +{ TARGET_NR_inotify_init, "inotify_init" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_inotify_rm_watch +{ TARGET_NR_inotify_rm_watch, "inotify_rm_watch" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_io_cancel +{ TARGET_NR_io_cancel, "io_cancel" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_ioctl +{ TARGET_NR_ioctl, "ioctl" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_io_destroy +{ TARGET_NR_io_destroy, "io_destroy" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_io_getevents +{ TARGET_NR_io_getevents, "io_getevents" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_ioperm +{ TARGET_NR_ioperm, "ioperm" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_iopl +{ TARGET_NR_iopl, "iopl" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_ioprio_get +{ TARGET_NR_ioprio_get, "ioprio_get" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_ioprio_set +{ TARGET_NR_ioprio_set, "ioprio_set" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_io_setup +{ TARGET_NR_io_setup, "io_setup" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_io_submit +{ TARGET_NR_io_submit, "io_submit" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_ipc +{ TARGET_NR_ipc, "ipc" , NULL, print_ipc, NULL }, +#endif +#ifdef TARGET_NR_kexec_load +{ TARGET_NR_kexec_load, "kexec_load" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_keyctl +{ TARGET_NR_keyctl, "keyctl" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_kill +{ TARGET_NR_kill, "kill", NULL, print_kill, NULL }, +#endif +#ifdef TARGET_NR_lchown +{ TARGET_NR_lchown, "lchown" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_lchown32 +{ TARGET_NR_lchown32, "lchown32" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_lgetxattr +{ TARGET_NR_lgetxattr, "lgetxattr" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_link +{ TARGET_NR_link, "link" , NULL, print_link, NULL }, +#endif +#ifdef TARGET_NR_linkat +{ TARGET_NR_linkat, "linkat" , NULL, print_linkat, NULL }, +#endif +#ifdef TARGET_NR_Linux +{ TARGET_NR_Linux, "Linux" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_listen +{ TARGET_NR_listen, "listen" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_listxattr +{ TARGET_NR_listxattr, "listxattr" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_llistxattr +{ TARGET_NR_llistxattr, "llistxattr" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR__llseek +{ TARGET_NR__llseek, "_llseek" , NULL, print__llseek, NULL }, +#endif +#ifdef TARGET_NR_lock +{ TARGET_NR_lock, "lock" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_lookup_dcookie +{ TARGET_NR_lookup_dcookie, "lookup_dcookie" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_lremovexattr +{ TARGET_NR_lremovexattr, "lremovexattr" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_lseek +{ TARGET_NR_lseek, "lseek" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_lsetxattr +{ TARGET_NR_lsetxattr, "lsetxattr" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_lstat +{ TARGET_NR_lstat, "lstat" , NULL, print_lstat, NULL }, +#endif +#ifdef TARGET_NR_lstat64 +{ TARGET_NR_lstat64, "lstat64" , NULL, print_lstat64, NULL }, +#endif +#ifdef TARGET_NR_madvise +{ TARGET_NR_madvise, "madvise" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_madvise1 +{ TARGET_NR_madvise1, "madvise1" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_mbind +{ TARGET_NR_mbind, "mbind" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_memory_ordering +{ TARGET_NR_memory_ordering, "memory_ordering" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_migrate_pages +{ TARGET_NR_migrate_pages, "migrate_pages" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_mincore +{ TARGET_NR_mincore, "mincore" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_mkdir +{ TARGET_NR_mkdir, "mkdir" , NULL, print_mkdir, NULL }, +#endif +#ifdef TARGET_NR_mkdirat +{ TARGET_NR_mkdirat, "mkdirat" , NULL, print_mkdirat, NULL }, +#endif +#ifdef TARGET_NR_rmdir +{ TARGET_NR_rmdir, "rmdir" , NULL, print_rmdir, NULL }, +#endif +#ifdef TARGET_NR_mknod +{ TARGET_NR_mknod, "mknod" , NULL, print_mknod, NULL }, +#endif +#ifdef TARGET_NR_mknodat +{ TARGET_NR_mknodat, "mknodat" , NULL, print_mknodat, NULL }, +#endif +#ifdef TARGET_NR_mlock +{ TARGET_NR_mlock, "mlock" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_mlockall +{ TARGET_NR_mlockall, "mlockall" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_mmap +{ TARGET_NR_mmap, "mmap" , NULL, print_mmap, print_syscall_ret_addr }, +#endif +#ifdef TARGET_NR_mmap2 +{ TARGET_NR_mmap2, "mmap2" , NULL, print_mmap2, print_syscall_ret_addr }, +#endif +#ifdef TARGET_NR_modify_ldt +{ TARGET_NR_modify_ldt, "modify_ldt" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_mount +{ TARGET_NR_mount, "mount" , NULL, print_mount, NULL }, +#endif +#ifdef TARGET_NR_move_pages +{ TARGET_NR_move_pages, "move_pages" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_mprotect +{ TARGET_NR_mprotect, "mprotect" , NULL, print_mprotect, NULL }, +#endif +#ifdef TARGET_NR_mpx +{ TARGET_NR_mpx, "mpx" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_mq_getsetattr +{ TARGET_NR_mq_getsetattr, "mq_getsetattr" , "%s(%d,%p,%p)", NULL, NULL }, +#endif +#ifdef TARGET_NR_mq_notify +{ TARGET_NR_mq_notify, "mq_notify" , "%s(%d,%p)", NULL, NULL }, +#endif +#ifdef TARGET_NR_mq_open +{ TARGET_NR_mq_open, "mq_open" , NULL, print_mq_open, NULL }, +#endif +#ifdef TARGET_NR_mq_timedreceive +{ TARGET_NR_mq_timedreceive, "mq_timedreceive" , "%s(%d,%p,%d,%u,%p)", NULL, NULL }, +#endif +#ifdef TARGET_NR_mq_timedsend +{ TARGET_NR_mq_timedsend, "mq_timedsend" , "%s(%d,%p,%d,%u,%p)", NULL, NULL }, +#endif +#ifdef TARGET_NR_mq_unlink +{ TARGET_NR_mq_unlink, "mq_unlink" , NULL, print_mq_unlink, NULL }, +#endif +#ifdef TARGET_NR_mremap +{ TARGET_NR_mremap, "mremap" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_msgctl +{ TARGET_NR_msgctl, "msgctl" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_msgget +{ TARGET_NR_msgget, "msgget" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_msgrcv +{ TARGET_NR_msgrcv, "msgrcv" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_msgsnd +{ TARGET_NR_msgsnd, "msgsnd" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_msync +{ TARGET_NR_msync, "msync" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_multiplexer +{ TARGET_NR_multiplexer, "multiplexer" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_munlock +{ TARGET_NR_munlock, "munlock" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_munlockall +{ TARGET_NR_munlockall, "munlockall" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_munmap +{ TARGET_NR_munmap, "munmap" , NULL, print_munmap, NULL }, +#endif +#ifdef TARGET_NR_nanosleep +{ TARGET_NR_nanosleep, "nanosleep" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_fstatat64 +{ TARGET_NR_fstatat64, "fstatat64" , NULL, print_fstatat64, NULL }, +#endif +#ifdef TARGET_NR_newfstatat +{ TARGET_NR_newfstatat, "newfstatat" , NULL, print_newfstatat, NULL }, +#endif +#ifdef TARGET_NR__newselect +{ TARGET_NR__newselect, "_newselect" , NULL, print_newselect, print_syscall_ret_newselect }, +#endif +#ifdef TARGET_NR_nfsservctl +{ TARGET_NR_nfsservctl, "nfsservctl" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_nice +{ TARGET_NR_nice, "nice" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_old_adjtimex +{ TARGET_NR_old_adjtimex, "old_adjtimex" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_oldfstat +{ TARGET_NR_oldfstat, "oldfstat" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_oldlstat +{ TARGET_NR_oldlstat, "oldlstat" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_oldolduname +{ TARGET_NR_oldolduname, "oldolduname" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_oldstat +{ TARGET_NR_oldstat, "oldstat" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_olduname +{ TARGET_NR_olduname, "olduname" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_open +{ TARGET_NR_open, "open" , NULL, print_open, NULL }, +#endif +#ifdef TARGET_NR_openat +{ TARGET_NR_openat, "openat" , NULL, print_openat, NULL }, +#endif +#ifdef TARGET_NR_osf_adjtime +{ TARGET_NR_osf_adjtime, "osf_adjtime" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_afs_syscall +{ TARGET_NR_osf_afs_syscall, "osf_afs_syscall" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_alt_plock +{ TARGET_NR_osf_alt_plock, "osf_alt_plock" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_alt_setsid +{ TARGET_NR_osf_alt_setsid, "osf_alt_setsid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_alt_sigpending +{ TARGET_NR_osf_alt_sigpending, "osf_alt_sigpending" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_asynch_daemon +{ TARGET_NR_osf_asynch_daemon, "osf_asynch_daemon" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_audcntl +{ TARGET_NR_osf_audcntl, "osf_audcntl" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_audgen +{ TARGET_NR_osf_audgen, "osf_audgen" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_chflags +{ TARGET_NR_osf_chflags, "osf_chflags" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_execve +{ TARGET_NR_osf_execve, "osf_execve" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_exportfs +{ TARGET_NR_osf_exportfs, "osf_exportfs" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_fchflags +{ TARGET_NR_osf_fchflags, "osf_fchflags" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_fdatasync +{ TARGET_NR_osf_fdatasync, "osf_fdatasync" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_fpathconf +{ TARGET_NR_osf_fpathconf, "osf_fpathconf" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_fstatfs +{ TARGET_NR_osf_fstatfs, "osf_fstatfs" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_fuser +{ TARGET_NR_osf_fuser, "osf_fuser" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_getaddressconf +{ TARGET_NR_osf_getaddressconf, "osf_getaddressconf" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_getdirentries +{ TARGET_NR_osf_getdirentries, "osf_getdirentries" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_getdomainname +{ TARGET_NR_osf_getdomainname, "osf_getdomainname" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_getfh +{ TARGET_NR_osf_getfh, "osf_getfh" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_getfsstat +{ TARGET_NR_osf_getfsstat, "osf_getfsstat" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_gethostid +{ TARGET_NR_osf_gethostid, "osf_gethostid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_getitimer +{ TARGET_NR_osf_getitimer, "osf_getitimer" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_getlogin +{ TARGET_NR_osf_getlogin, "osf_getlogin" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_getmnt +{ TARGET_NR_osf_getmnt, "osf_getmnt" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_getrusage +{ TARGET_NR_osf_getrusage, "osf_getrusage" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_getsysinfo +{ TARGET_NR_osf_getsysinfo, "osf_getsysinfo" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_gettimeofday +{ TARGET_NR_osf_gettimeofday, "osf_gettimeofday" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_kloadcall +{ TARGET_NR_osf_kloadcall, "osf_kloadcall" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_kmodcall +{ TARGET_NR_osf_kmodcall, "osf_kmodcall" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_memcntl +{ TARGET_NR_osf_memcntl, "osf_memcntl" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_mincore +{ TARGET_NR_osf_mincore, "osf_mincore" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_mount +{ TARGET_NR_osf_mount, "osf_mount" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_mremap +{ TARGET_NR_osf_mremap, "osf_mremap" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_msfs_syscall +{ TARGET_NR_osf_msfs_syscall, "osf_msfs_syscall" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_msleep +{ TARGET_NR_osf_msleep, "osf_msleep" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_mvalid +{ TARGET_NR_osf_mvalid, "osf_mvalid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_mwakeup +{ TARGET_NR_osf_mwakeup, "osf_mwakeup" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_naccept +{ TARGET_NR_osf_naccept, "osf_naccept" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_nfssvc +{ TARGET_NR_osf_nfssvc, "osf_nfssvc" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_ngetpeername +{ TARGET_NR_osf_ngetpeername, "osf_ngetpeername" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_ngetsockname +{ TARGET_NR_osf_ngetsockname, "osf_ngetsockname" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_nrecvfrom +{ TARGET_NR_osf_nrecvfrom, "osf_nrecvfrom" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_nrecvmsg +{ TARGET_NR_osf_nrecvmsg, "osf_nrecvmsg" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_nsendmsg +{ TARGET_NR_osf_nsendmsg, "osf_nsendmsg" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_ntp_adjtime +{ TARGET_NR_osf_ntp_adjtime, "osf_ntp_adjtime" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_ntp_gettime +{ TARGET_NR_osf_ntp_gettime, "osf_ntp_gettime" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_old_creat +{ TARGET_NR_osf_old_creat, "osf_old_creat" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_old_fstat +{ TARGET_NR_osf_old_fstat, "osf_old_fstat" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_old_getpgrp +{ TARGET_NR_osf_old_getpgrp, "osf_old_getpgrp" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_old_killpg +{ TARGET_NR_osf_old_killpg, "osf_old_killpg" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_old_lstat +{ TARGET_NR_osf_old_lstat, "osf_old_lstat" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_old_open +{ TARGET_NR_osf_old_open, "osf_old_open" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_oldquota +{ TARGET_NR_osf_oldquota, "osf_oldquota" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_old_sigaction +{ TARGET_NR_osf_old_sigaction, "osf_old_sigaction" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_old_sigblock +{ TARGET_NR_osf_old_sigblock, "osf_old_sigblock" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_old_sigreturn +{ TARGET_NR_osf_old_sigreturn, "osf_old_sigreturn" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_old_sigsetmask +{ TARGET_NR_osf_old_sigsetmask, "osf_old_sigsetmask" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_old_sigvec +{ TARGET_NR_osf_old_sigvec, "osf_old_sigvec" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_old_stat +{ TARGET_NR_osf_old_stat, "osf_old_stat" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_old_vadvise +{ TARGET_NR_osf_old_vadvise, "osf_old_vadvise" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_old_vtrace +{ TARGET_NR_osf_old_vtrace, "osf_old_vtrace" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_old_wait +{ TARGET_NR_osf_old_wait, "osf_old_wait" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_pathconf +{ TARGET_NR_osf_pathconf, "osf_pathconf" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_pid_block +{ TARGET_NR_osf_pid_block, "osf_pid_block" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_pid_unblock +{ TARGET_NR_osf_pid_unblock, "osf_pid_unblock" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_plock +{ TARGET_NR_osf_plock, "osf_plock" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_priocntlset +{ TARGET_NR_osf_priocntlset, "osf_priocntlset" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_profil +{ TARGET_NR_osf_profil, "osf_profil" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_proplist_syscall +{ TARGET_NR_osf_proplist_syscall, "osf_proplist_syscall" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_reboot +{ TARGET_NR_osf_reboot, "osf_reboot" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_revoke +{ TARGET_NR_osf_revoke, "osf_revoke" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_sbrk +{ TARGET_NR_osf_sbrk, "osf_sbrk" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_security +{ TARGET_NR_osf_security, "osf_security" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_select +{ TARGET_NR_osf_select, "osf_select" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_sethostid +{ TARGET_NR_osf_sethostid, "osf_sethostid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_setitimer +{ TARGET_NR_osf_setitimer, "osf_setitimer" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_setlogin +{ TARGET_NR_osf_setlogin, "osf_setlogin" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_set_program_attributes +{ TARGET_NR_osf_set_program_attributes, "osf_set_program_attributes" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_set_speculative +{ TARGET_NR_osf_set_speculative, "osf_set_speculative" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_setsysinfo +{ TARGET_NR_osf_setsysinfo, "osf_setsysinfo" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_settimeofday +{ TARGET_NR_osf_settimeofday, "osf_settimeofday" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_shmat +{ TARGET_NR_osf_shmat, "osf_shmat" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_signal +{ TARGET_NR_osf_signal, "osf_signal" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_sigprocmask +{ TARGET_NR_osf_sigprocmask, "osf_sigprocmask" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_sigsendset +{ TARGET_NR_osf_sigsendset, "osf_sigsendset" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_sigstack +{ TARGET_NR_osf_sigstack, "osf_sigstack" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_sigwaitprim +{ TARGET_NR_osf_sigwaitprim, "osf_sigwaitprim" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_sstk +{ TARGET_NR_osf_sstk, "osf_sstk" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_statfs +{ TARGET_NR_osf_statfs, "osf_statfs" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_subsys_info +{ TARGET_NR_osf_subsys_info, "osf_subsys_info" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_swapctl +{ TARGET_NR_osf_swapctl, "osf_swapctl" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_swapon +{ TARGET_NR_osf_swapon, "osf_swapon" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_syscall +{ TARGET_NR_osf_syscall, "osf_syscall" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_sysinfo +{ TARGET_NR_osf_sysinfo, "osf_sysinfo" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_table +{ TARGET_NR_osf_table, "osf_table" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_uadmin +{ TARGET_NR_osf_uadmin, "osf_uadmin" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_usleep_thread +{ TARGET_NR_osf_usleep_thread, "osf_usleep_thread" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_uswitch +{ TARGET_NR_osf_uswitch, "osf_uswitch" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_utc_adjtime +{ TARGET_NR_osf_utc_adjtime, "osf_utc_adjtime" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_utc_gettime +{ TARGET_NR_osf_utc_gettime, "osf_utc_gettime" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_utimes +{ TARGET_NR_osf_utimes, "osf_utimes" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_utsname +{ TARGET_NR_osf_utsname, "osf_utsname" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_wait4 +{ TARGET_NR_osf_wait4, "osf_wait4" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_osf_waitid +{ TARGET_NR_osf_waitid, "osf_waitid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_pause +{ TARGET_NR_pause, "pause" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_pciconfig_iobase +{ TARGET_NR_pciconfig_iobase, "pciconfig_iobase" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_pciconfig_read +{ TARGET_NR_pciconfig_read, "pciconfig_read" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_pciconfig_write +{ TARGET_NR_pciconfig_write, "pciconfig_write" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_perfctr +{ TARGET_NR_perfctr, "perfctr" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_personality +{ TARGET_NR_personality, "personality" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_pipe +{ TARGET_NR_pipe, "pipe" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_pivot_root +{ TARGET_NR_pivot_root, "pivot_root" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_poll +{ TARGET_NR_poll, "poll" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_ppoll +{ TARGET_NR_ppoll, "ppoll" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_prctl +{ TARGET_NR_prctl, "prctl" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_pread64 +{ TARGET_NR_pread64, "pread64" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_prof +{ TARGET_NR_prof, "prof" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_profil +{ TARGET_NR_profil, "profil" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_pselect6 +{ TARGET_NR_pselect6, "pselect6" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_ptrace +{ TARGET_NR_ptrace, "ptrace" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_putpmsg +{ TARGET_NR_putpmsg, "putpmsg" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_pwrite64 +{ TARGET_NR_pwrite64, "pwrite64" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_query_module +{ TARGET_NR_query_module, "query_module" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_quotactl +{ TARGET_NR_quotactl, "quotactl" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_read +{ TARGET_NR_read, "read" , "%s(%d,%#x,%d)", NULL, NULL }, +#endif +#ifdef TARGET_NR_readahead +{ TARGET_NR_readahead, "readahead" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_readdir +{ TARGET_NR_readdir, "readdir" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_readlink +{ TARGET_NR_readlink, "readlink" , NULL, print_readlink, NULL }, +#endif +#ifdef TARGET_NR_readlinkat +{ TARGET_NR_readlinkat, "readlinkat" , NULL, print_readlinkat, NULL }, +#endif +#ifdef TARGET_NR_readv +{ TARGET_NR_readv, "readv" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_reboot +{ TARGET_NR_reboot, "reboot" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_recv +{ TARGET_NR_recv, "recv" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_recvfrom +{ TARGET_NR_recvfrom, "recvfrom" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_recvmsg +{ TARGET_NR_recvmsg, "recvmsg" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_remap_file_pages +{ TARGET_NR_remap_file_pages, "remap_file_pages" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_removexattr +{ TARGET_NR_removexattr, "removexattr" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_rename +{ TARGET_NR_rename, "rename" , NULL, print_rename, NULL }, +#endif +#ifdef TARGET_NR_renameat +{ TARGET_NR_renameat, "renameat" , NULL, print_renameat, NULL }, +#endif +#ifdef TARGET_NR_request_key +{ TARGET_NR_request_key, "request_key" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_reserved221 +{ TARGET_NR_reserved221, "reserved221" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_reserved82 +{ TARGET_NR_reserved82, "reserved82" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_restart_syscall +{ TARGET_NR_restart_syscall, "restart_syscall" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_rmdir +{ TARGET_NR_rmdir, "rmdir" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_rt_sigaction +{ TARGET_NR_rt_sigaction, "rt_sigaction" , NULL, print_rt_sigaction, NULL }, +#endif +#ifdef TARGET_NR_rt_sigpending +{ TARGET_NR_rt_sigpending, "rt_sigpending" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_rt_sigprocmask +{ TARGET_NR_rt_sigprocmask, "rt_sigprocmask" , NULL, print_rt_sigprocmask, NULL }, +#endif +#ifdef TARGET_NR_rt_sigqueueinfo +{ TARGET_NR_rt_sigqueueinfo, "rt_sigqueueinfo" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_rt_sigreturn +{ TARGET_NR_rt_sigreturn, "rt_sigreturn" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_rt_sigsuspend +{ TARGET_NR_rt_sigsuspend, "rt_sigsuspend" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_rt_sigtimedwait +{ TARGET_NR_rt_sigtimedwait, "rt_sigtimedwait" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sched_getaffinity +{ TARGET_NR_sched_getaffinity, "sched_getaffinity" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sched_get_affinity +{ TARGET_NR_sched_get_affinity, "sched_get_affinity" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sched_getparam +{ TARGET_NR_sched_getparam, "sched_getparam" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sched_get_priority_max +{ TARGET_NR_sched_get_priority_max, "sched_get_priority_max" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sched_get_priority_min +{ TARGET_NR_sched_get_priority_min, "sched_get_priority_min" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sched_getscheduler +{ TARGET_NR_sched_getscheduler, "sched_getscheduler" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sched_rr_get_interval +{ TARGET_NR_sched_rr_get_interval, "sched_rr_get_interval" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sched_setaffinity +{ TARGET_NR_sched_setaffinity, "sched_setaffinity" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sched_set_affinity +{ TARGET_NR_sched_set_affinity, "sched_set_affinity" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sched_setparam +{ TARGET_NR_sched_setparam, "sched_setparam" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sched_setscheduler +{ TARGET_NR_sched_setscheduler, "sched_setscheduler" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sched_yield +{ TARGET_NR_sched_yield, "sched_yield" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_security +{ TARGET_NR_security, "security" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_select +{ TARGET_NR_select, "select" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_semctl +{ TARGET_NR_semctl, "semctl" , NULL, print_semctl, NULL }, +#endif +#ifdef TARGET_NR_semget +{ TARGET_NR_semget, "semget" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_semop +{ TARGET_NR_semop, "semop" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_semtimedop +{ TARGET_NR_semtimedop, "semtimedop" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_send +{ TARGET_NR_send, "send" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sendfile +{ TARGET_NR_sendfile, "sendfile" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sendfile64 +{ TARGET_NR_sendfile64, "sendfile64" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sendmsg +{ TARGET_NR_sendmsg, "sendmsg" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sendto +{ TARGET_NR_sendto, "sendto" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setdomainname +{ TARGET_NR_setdomainname, "setdomainname" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setfsgid +{ TARGET_NR_setfsgid, "setfsgid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setfsgid32 +{ TARGET_NR_setfsgid32, "setfsgid32" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setfsuid +{ TARGET_NR_setfsuid, "setfsuid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setfsuid32 +{ TARGET_NR_setfsuid32, "setfsuid32" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setgid +{ TARGET_NR_setgid, "setgid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setgid32 +{ TARGET_NR_setgid32, "setgid32" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setgroups +{ TARGET_NR_setgroups, "setgroups" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setgroups32 +{ TARGET_NR_setgroups32, "setgroups32" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sethae +{ TARGET_NR_sethae, "sethae" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sethostname +{ TARGET_NR_sethostname, "sethostname" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setitimer +{ TARGET_NR_setitimer, "setitimer" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_set_mempolicy +{ TARGET_NR_set_mempolicy, "set_mempolicy" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setns +{ TARGET_NR_setns, "setns" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setpgid +{ TARGET_NR_setpgid, "setpgid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setpgrp +{ TARGET_NR_setpgrp, "setpgrp" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setpriority +{ TARGET_NR_setpriority, "setpriority" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setregid +{ TARGET_NR_setregid, "setregid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setregid32 +{ TARGET_NR_setregid32, "setregid32" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setresgid +{ TARGET_NR_setresgid, "setresgid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setresgid32 +{ TARGET_NR_setresgid32, "setresgid32" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setresuid +{ TARGET_NR_setresuid, "setresuid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setresuid32 +{ TARGET_NR_setresuid32, "setresuid32" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setreuid +{ TARGET_NR_setreuid, "setreuid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setreuid32 +{ TARGET_NR_setreuid32, "setreuid32" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setrlimit +{ TARGET_NR_setrlimit, "setrlimit" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_set_robust_list +{ TARGET_NR_set_robust_list, "set_robust_list" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setsid +{ TARGET_NR_setsid, "setsid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setsockopt +{ TARGET_NR_setsockopt, "setsockopt" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_set_thread_area +{ TARGET_NR_set_thread_area, "set_thread_area" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_set_tid_address +{ TARGET_NR_set_tid_address, "set_tid_address" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_settimeofday +{ TARGET_NR_settimeofday, "settimeofday" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setuid +{ TARGET_NR_setuid, "setuid" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setuid32 +{ TARGET_NR_setuid32, "setuid32" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_setxattr +{ TARGET_NR_setxattr, "setxattr" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sgetmask +{ TARGET_NR_sgetmask, "sgetmask" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_shmat +{ TARGET_NR_shmat, "shmat" , NULL, NULL, print_syscall_ret_addr }, +#endif +#ifdef TARGET_NR_shmctl +{ TARGET_NR_shmctl, "shmctl" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_shmdt +{ TARGET_NR_shmdt, "shmdt" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_shmget +{ TARGET_NR_shmget, "shmget" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_shutdown +{ TARGET_NR_shutdown, "shutdown" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sigaction +{ TARGET_NR_sigaction, "sigaction" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sigaltstack +{ TARGET_NR_sigaltstack, "sigaltstack" , "%s(%p,%p)", NULL, NULL }, +#endif +#ifdef TARGET_NR_signal +{ TARGET_NR_signal, "signal" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sigpending +{ TARGET_NR_sigpending, "sigpending" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sigprocmask +{ TARGET_NR_sigprocmask, "sigprocmask" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sigreturn +{ TARGET_NR_sigreturn, "sigreturn" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sigsuspend +{ TARGET_NR_sigsuspend, "sigsuspend" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_socket +{ TARGET_NR_socket, "socket" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_socketcall +{ TARGET_NR_socketcall, "socketcall" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_socketpair +{ TARGET_NR_socketpair, "socketpair" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_splice +{ TARGET_NR_splice, "splice" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_ssetmask +{ TARGET_NR_ssetmask, "ssetmask" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_stat +{ TARGET_NR_stat, "stat" , NULL, print_stat, NULL }, +#endif +#ifdef TARGET_NR_stat64 +{ TARGET_NR_stat64, "stat64" , NULL, print_stat64, NULL }, +#endif +#ifdef TARGET_NR_statfs +{ TARGET_NR_statfs, "statfs" , NULL, print_statfs, NULL }, +#endif +#ifdef TARGET_NR_statfs64 +{ TARGET_NR_statfs64, "statfs64" , NULL, print_statfs64, NULL }, +#endif +#ifdef TARGET_NR_stime +{ TARGET_NR_stime, "stime" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_streams1 +{ TARGET_NR_streams1, "streams1" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_streams2 +{ TARGET_NR_streams2, "streams2" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_stty +{ TARGET_NR_stty, "stty" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_swapcontext +{ TARGET_NR_swapcontext, "swapcontext" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_swapoff +{ TARGET_NR_swapoff, "swapoff" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_swapon +{ TARGET_NR_swapon, "swapon" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_symlink +{ TARGET_NR_symlink, "symlink" , NULL, print_symlink, NULL }, +#endif +#ifdef TARGET_NR_symlinkat +{ TARGET_NR_symlinkat, "symlinkat", NULL, print_symlinkat, NULL }, +#endif +#ifdef TARGET_NR_sync +{ TARGET_NR_sync, "sync" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sync_file_range +{ TARGET_NR_sync_file_range, "sync_file_range" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_syscall +{ TARGET_NR_syscall, "syscall" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR__sysctl +{ TARGET_NR__sysctl, "_sysctl" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sys_epoll_create +{ TARGET_NR_sys_epoll_create, "sys_epoll_create" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sys_epoll_ctl +{ TARGET_NR_sys_epoll_ctl, "sys_epoll_ctl" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sys_epoll_wait +{ TARGET_NR_sys_epoll_wait, "sys_epoll_wait" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sysfs +{ TARGET_NR_sysfs, "sysfs" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sysinfo +{ TARGET_NR_sysinfo, "sysinfo" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sys_kexec_load +{ TARGET_NR_sys_kexec_load, "sys_kexec_load" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_syslog +{ TARGET_NR_syslog, "syslog" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sysmips +{ TARGET_NR_sysmips, "sysmips" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sys_setaltroot +{ TARGET_NR_sys_setaltroot, "sys_setaltroot" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_tee +{ TARGET_NR_tee, "tee" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_tgkill +{ TARGET_NR_tgkill, "tgkill" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_time +{ TARGET_NR_time, "time" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_timer_create +{ TARGET_NR_timer_create, "timer_create" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_timer_delete +{ TARGET_NR_timer_delete, "timer_delete" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_timer_getoverrun +{ TARGET_NR_timer_getoverrun, "timer_getoverrun" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_timer_gettime +{ TARGET_NR_timer_gettime, "timer_gettime" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_timer_settime +{ TARGET_NR_timer_settime, "timer_settime" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_timerfd_create +{ TARGET_NR_timerfd_create, "timerfd_create" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_timerfd_gettime +{ TARGET_NR_timerfd_gettime, "timerfd_gettime" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_timerfd_settime +{ TARGET_NR_timerfd_settime, "timerfd_settime" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_times +{ TARGET_NR_times, "times" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_tkill +{ TARGET_NR_tkill, "tkill" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_truncate +{ TARGET_NR_truncate, "truncate" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_truncate64 +{ TARGET_NR_truncate64, "truncate64" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_tuxcall +{ TARGET_NR_tuxcall, "tuxcall" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_ugetrlimit +{ TARGET_NR_ugetrlimit, "ugetrlimit" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_ulimit +{ TARGET_NR_ulimit, "ulimit" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_umask +{ TARGET_NR_umask, "umask" , "%s(%#o)", NULL, NULL }, +#endif +#ifdef TARGET_NR_umount +{ TARGET_NR_umount, "umount" , NULL, print_umount, NULL }, +#endif +#ifdef TARGET_NR_umount2 +{ TARGET_NR_umount2, "umount2" , NULL, print_umount2, NULL }, +#endif +#ifdef TARGET_NR_uname +{ TARGET_NR_uname, "uname" , "%s(%p)", NULL, NULL }, +#endif +#ifdef TARGET_NR_unlink +{ TARGET_NR_unlink, "unlink" , NULL, print_unlink, NULL }, +#endif +#ifdef TARGET_NR_unlinkat +{ TARGET_NR_unlinkat, "unlinkat" , NULL, print_unlinkat, NULL }, +#endif +#ifdef TARGET_NR_unshare +{ TARGET_NR_unshare, "unshare" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_unused109 +{ TARGET_NR_unused109, "unused109" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_unused150 +{ TARGET_NR_unused150, "unused150" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_unused18 +{ TARGET_NR_unused18, "unused18" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_unused28 +{ TARGET_NR_unused28, "unused28" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_unused59 +{ TARGET_NR_unused59, "unused59" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_unused84 +{ TARGET_NR_unused84, "unused84" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_uselib +{ TARGET_NR_uselib, "uselib" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_ustat +{ TARGET_NR_ustat, "ustat" , "%s(%#x,%p)", NULL, NULL }, +#endif +#ifdef TARGET_NR_utime +{ TARGET_NR_utime, "utime" , NULL, print_utime, NULL }, +#endif +#ifdef TARGET_NR_utimes +{ TARGET_NR_utimes, "utimes" , NULL, print_utimes, NULL }, +#endif +#ifdef TARGET_NR_utrap_install +{ TARGET_NR_utrap_install, "utrap_install" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_vfork +{ TARGET_NR_vfork, "vfork" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_vhangup +{ TARGET_NR_vhangup, "vhangup" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_vm86 +{ TARGET_NR_vm86, "vm86" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_vm86old +{ TARGET_NR_vm86old, "vm86old" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_vmsplice +{ TARGET_NR_vmsplice, "vmsplice" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_vserver +{ TARGET_NR_vserver, "vserver" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_wait4 +{ TARGET_NR_wait4, "wait4" , NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_waitid +{ TARGET_NR_waitid, "waitid" , "%s(%#x,%d,%p,%#x)", NULL, NULL }, +#endif +#ifdef TARGET_NR_waitpid +{ TARGET_NR_waitpid, "waitpid" , "%s(%d,%p,%#x)", NULL, NULL }, +#endif +#ifdef TARGET_NR_write +{ TARGET_NR_write, "write" , "%s(%d,%#x,%d)", NULL, NULL }, +#endif +#ifdef TARGET_NR_writev +{ TARGET_NR_writev, "writev" , "%s(%d,%p,%#x)", NULL, NULL }, +#endif +#ifdef TARGET_NR_utimensat +{ TARGET_NR_utimensat, "utimensat", NULL, print_utimensat, NULL }, +#endif +#ifdef TARGET_NR_sync_file_range +{ TARGET_NR_sync_file_range, "sync_file_range", NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_sync_file_range2 +{ TARGET_NR_sync_file_range2, "sync_file_range2", NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_pipe2 +{ TARGET_NR_pipe2, "pipe2", NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_atomic_cmpxchg_32 +{ TARGET_NR_atomic_cmpxchg_32, "atomic_cmpxchg_32", NULL, NULL, NULL }, +#endif +#ifdef TARGET_NR_atomic_barrier +{ TARGET_NR_atomic_barrier, "atomic_barrier", NULL, NULL, NULL }, +#endif diff --git a/linux-user/syscall.c b/linux-user/syscall.c new file mode 100644 index 00000000..f62c6989 --- /dev/null +++ b/linux-user/syscall.c @@ -0,0 +1,9890 @@ +/* + *  Linux syscalls + * + *  Copyright (c) 2003 Fabrice Bellard + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, see <http://www.gnu.org/licenses/>. + */ +#define _ATFILE_SOURCE +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <elf.h> +#include <endian.h> +#include <errno.h> +#include <unistd.h> +#include <fcntl.h> +#include <time.h> +#include <limits.h> +#include <grp.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/msg.h> +#include <sys/wait.h> +#include <sys/time.h> +#include <sys/stat.h> +#include <sys/mount.h> +#include <sys/file.h> +#include <sys/fsuid.h> +#include <sys/personality.h> +#include <sys/prctl.h> +#include <sys/resource.h> +#include <sys/mman.h> +#include <sys/swap.h> +#include <linux/capability.h> +#include <signal.h> +#include <sched.h> +#ifdef __ia64__ +int __clone2(int (*fn)(void *), void *child_stack_base, +             size_t stack_size, int flags, void *arg, ...); +#endif +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/uio.h> +#include <sys/poll.h> +#include <sys/times.h> +#include <sys/shm.h> +#include <sys/sem.h> +#include <sys/statfs.h> +#include <utime.h> +#include <sys/sysinfo.h> +//#include <sys/user.h> +#include <netinet/ip.h> +#include <netinet/tcp.h> +#include <linux/wireless.h> +#include <linux/icmp.h> +#include "qemu-common.h" +#ifdef CONFIG_TIMERFD +#include <sys/timerfd.h> +#endif +#ifdef TARGET_GPROF +#include <sys/gmon.h> +#endif +#ifdef CONFIG_EVENTFD +#include <sys/eventfd.h> +#endif +#ifdef CONFIG_EPOLL +#include <sys/epoll.h> +#endif +#ifdef CONFIG_ATTR +#include "qemu/xattr.h" +#endif +#ifdef CONFIG_SENDFILE +#include <sys/sendfile.h> +#endif + +#define termios host_termios +#define winsize host_winsize +#define termio host_termio +#define sgttyb host_sgttyb /* same as target */ +#define tchars host_tchars /* same as target */ +#define ltchars host_ltchars /* same as target */ + +#include <linux/termios.h> +#include <linux/unistd.h> +#include <linux/cdrom.h> +#include <linux/hdreg.h> +#include <linux/soundcard.h> +#include <linux/kd.h> +#include <linux/mtio.h> +#include <linux/fs.h> +#if defined(CONFIG_FIEMAP) +#include <linux/fiemap.h> +#endif +#include <linux/fb.h> +#include <linux/vt.h> +#include <linux/dm-ioctl.h> +#include <linux/reboot.h> +#include <linux/route.h> +#include <linux/filter.h> +#include <linux/blkpg.h> +#include "linux_loop.h" +#include "uname.h" + +#include "qemu.h" + +#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \ +    CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID) + +//#define DEBUG + +//#include <linux/msdos_fs.h> +#define	VFAT_IOCTL_READDIR_BOTH		_IOR('r', 1, struct linux_dirent [2]) +#define	VFAT_IOCTL_READDIR_SHORT	_IOR('r', 2, struct linux_dirent [2]) + + +#undef _syscall0 +#undef _syscall1 +#undef _syscall2 +#undef _syscall3 +#undef _syscall4 +#undef _syscall5 +#undef _syscall6 + +#define _syscall0(type,name)		\ +static type name (void)			\ +{					\ +	return syscall(__NR_##name);	\ +} + +#define _syscall1(type,name,type1,arg1)		\ +static type name (type1 arg1)			\ +{						\ +	return syscall(__NR_##name, arg1);	\ +} + +#define _syscall2(type,name,type1,arg1,type2,arg2)	\ +static type name (type1 arg1,type2 arg2)		\ +{							\ +	return syscall(__NR_##name, arg1, arg2);	\ +} + +#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3)	\ +static type name (type1 arg1,type2 arg2,type3 arg3)		\ +{								\ +	return syscall(__NR_##name, arg1, arg2, arg3);		\ +} + +#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4)	\ +static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4)			\ +{										\ +	return syscall(__NR_##name, arg1, arg2, arg3, arg4);			\ +} + +#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,	\ +		  type5,arg5)							\ +static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5)	\ +{										\ +	return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5);		\ +} + + +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,	\ +		  type5,arg5,type6,arg6)					\ +static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,	\ +                  type6 arg6)							\ +{										\ +	return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6);	\ +} + + +#define __NR_sys_uname __NR_uname +#define __NR_sys_getcwd1 __NR_getcwd +#define __NR_sys_getdents __NR_getdents +#define __NR_sys_getdents64 __NR_getdents64 +#define __NR_sys_getpriority __NR_getpriority +#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo +#define __NR_sys_syslog __NR_syslog +#define __NR_sys_tgkill __NR_tgkill +#define __NR_sys_tkill __NR_tkill +#define __NR_sys_futex __NR_futex +#define __NR_sys_inotify_init __NR_inotify_init +#define __NR_sys_inotify_add_watch __NR_inotify_add_watch +#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch + +#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) || \ +    defined(__s390x__) +#define __NR__llseek __NR_lseek +#endif + +/* Newer kernel ports have llseek() instead of _llseek() */ +#if defined(TARGET_NR_llseek) && !defined(TARGET_NR__llseek) +#define TARGET_NR__llseek TARGET_NR_llseek +#endif + +#ifdef __NR_gettid +_syscall0(int, gettid) +#else +/* This is a replacement for the host gettid() and must return a host +   errno. */ +static int gettid(void) { +    return -ENOSYS; +} +#endif +#ifdef __NR_getdents +_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count); +#endif +#if !defined(__NR_getdents) || \ +    (defined(TARGET_NR_getdents64) && defined(__NR_getdents64)) +_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count); +#endif +#if defined(TARGET_NR__llseek) && defined(__NR_llseek) +_syscall5(int, _llseek,  uint,  fd, ulong, hi, ulong, lo, +          loff_t *, res, uint, wh); +#endif +_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo) +_syscall3(int,sys_syslog,int,type,char*,bufp,int,len) +#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill) +_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig) +#endif +#if defined(TARGET_NR_tkill) && defined(__NR_tkill) +_syscall2(int,sys_tkill,int,tid,int,sig) +#endif +#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 +#if defined(TARGET_NR_futex) && defined(__NR_futex) +_syscall6(int,sys_futex,int *,uaddr,int,op,int,val, +          const struct timespec *,timeout,int *,uaddr2,int,val3) +#endif +#define __NR_sys_sched_getaffinity __NR_sched_getaffinity +_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len, +          unsigned long *, user_mask_ptr); +#define __NR_sys_sched_setaffinity __NR_sched_setaffinity +_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len, +          unsigned long *, user_mask_ptr); +_syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd, +          void *, arg); +_syscall2(int, capget, struct __user_cap_header_struct *, header, +          struct __user_cap_data_struct *, data); +_syscall2(int, capset, struct __user_cap_header_struct *, header, +          struct __user_cap_data_struct *, data); +#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get) +_syscall2(int, ioprio_get, int, which, int, who) +#endif +#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set) +_syscall3(int, ioprio_set, int, which, int, who, int, ioprio) +#endif + +static bitmask_transtbl fcntl_flags_tbl[] = { +  { TARGET_O_ACCMODE,   TARGET_O_WRONLY,    O_ACCMODE,   O_WRONLY,    }, +  { TARGET_O_ACCMODE,   TARGET_O_RDWR,      O_ACCMODE,   O_RDWR,      }, +  { TARGET_O_CREAT,     TARGET_O_CREAT,     O_CREAT,     O_CREAT,     }, +  { TARGET_O_EXCL,      TARGET_O_EXCL,      O_EXCL,      O_EXCL,      }, +  { TARGET_O_NOCTTY,    TARGET_O_NOCTTY,    O_NOCTTY,    O_NOCTTY,    }, +  { TARGET_O_TRUNC,     TARGET_O_TRUNC,     O_TRUNC,     O_TRUNC,     }, +  { TARGET_O_APPEND,    TARGET_O_APPEND,    O_APPEND,    O_APPEND,    }, +  { TARGET_O_NONBLOCK,  TARGET_O_NONBLOCK,  O_NONBLOCK,  O_NONBLOCK,  }, +  { TARGET_O_SYNC,      TARGET_O_DSYNC,     O_SYNC,      O_DSYNC,     }, +  { TARGET_O_SYNC,      TARGET_O_SYNC,      O_SYNC,      O_SYNC,      }, +  { TARGET_FASYNC,      TARGET_FASYNC,      FASYNC,      FASYNC,      }, +  { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, }, +  { TARGET_O_NOFOLLOW,  TARGET_O_NOFOLLOW,  O_NOFOLLOW,  O_NOFOLLOW,  }, +#if defined(O_DIRECT) +  { TARGET_O_DIRECT,    TARGET_O_DIRECT,    O_DIRECT,    O_DIRECT,    }, +#endif +#if defined(O_NOATIME) +  { TARGET_O_NOATIME,   TARGET_O_NOATIME,   O_NOATIME,   O_NOATIME    }, +#endif +#if defined(O_CLOEXEC) +  { TARGET_O_CLOEXEC,   TARGET_O_CLOEXEC,   O_CLOEXEC,   O_CLOEXEC    }, +#endif +#if defined(O_PATH) +  { TARGET_O_PATH,      TARGET_O_PATH,      O_PATH,      O_PATH       }, +#endif +  /* Don't terminate the list prematurely on 64-bit host+guest.  */ +#if TARGET_O_LARGEFILE != 0 || O_LARGEFILE != 0 +  { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, }, +#endif +  { 0, 0, 0, 0 } +}; + +static int sys_getcwd1(char *buf, size_t size) +{ +  if (getcwd(buf, size) == NULL) { +      /* getcwd() sets errno */ +      return (-1); +  } +  return strlen(buf)+1; +} + +static int sys_openat(int dirfd, const char *pathname, int flags, mode_t mode) +{ +  /* +   * open(2) has extra parameter 'mode' when called with +   * flag O_CREAT. +   */ +  if ((flags & O_CREAT) != 0) { +      return (openat(dirfd, pathname, flags, mode)); +  } +  return (openat(dirfd, pathname, flags)); +} + +#ifdef TARGET_NR_utimensat +#ifdef CONFIG_UTIMENSAT +static int sys_utimensat(int dirfd, const char *pathname, +    const struct timespec times[2], int flags) +{ +    if (pathname == NULL) +        return futimens(dirfd, times); +    else +        return utimensat(dirfd, pathname, times, flags); +} +#elif defined(__NR_utimensat) +#define __NR_sys_utimensat __NR_utimensat +_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname, +          const struct timespec *,tsp,int,flags) +#else +static int sys_utimensat(int dirfd, const char *pathname, +                         const struct timespec times[2], int flags) +{ +    errno = ENOSYS; +    return -1; +} +#endif +#endif /* TARGET_NR_utimensat */ + +#ifdef CONFIG_INOTIFY +#include <sys/inotify.h> + +#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init) +static int sys_inotify_init(void) +{ +  return (inotify_init()); +} +#endif +#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch) +static int sys_inotify_add_watch(int fd,const char *pathname, int32_t mask) +{ +  return (inotify_add_watch(fd, pathname, mask)); +} +#endif +#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch) +static int sys_inotify_rm_watch(int fd, int32_t wd) +{ +  return (inotify_rm_watch(fd, wd)); +} +#endif +#ifdef CONFIG_INOTIFY1 +#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1) +static int sys_inotify_init1(int flags) +{ +  return (inotify_init1(flags)); +} +#endif +#endif +#else +/* Userspace can usually survive runtime without inotify */ +#undef TARGET_NR_inotify_init +#undef TARGET_NR_inotify_init1 +#undef TARGET_NR_inotify_add_watch +#undef TARGET_NR_inotify_rm_watch +#endif /* CONFIG_INOTIFY  */ + +#if defined(TARGET_NR_ppoll) +#ifndef __NR_ppoll +# define __NR_ppoll -1 +#endif +#define __NR_sys_ppoll __NR_ppoll +_syscall5(int, sys_ppoll, struct pollfd *, fds, nfds_t, nfds, +          struct timespec *, timeout, const sigset_t *, sigmask, +          size_t, sigsetsize) +#endif + +#if defined(TARGET_NR_pselect6) +#ifndef __NR_pselect6 +# define __NR_pselect6 -1 +#endif +#define __NR_sys_pselect6 __NR_pselect6 +_syscall6(int, sys_pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, +          fd_set *, exceptfds, struct timespec *, timeout, void *, sig); +#endif + +#if defined(TARGET_NR_prlimit64) +#ifndef __NR_prlimit64 +# define __NR_prlimit64 -1 +#endif +#define __NR_sys_prlimit64 __NR_prlimit64 +/* The glibc rlimit structure may not be that used by the underlying syscall */ +struct host_rlimit64 { +    uint64_t rlim_cur; +    uint64_t rlim_max; +}; +_syscall4(int, sys_prlimit64, pid_t, pid, int, resource, +          const struct host_rlimit64 *, new_limit, +          struct host_rlimit64 *, old_limit) +#endif + + +#if defined(TARGET_NR_timer_create) +/* Maxiumum of 32 active POSIX timers allowed at any one time. */ +static timer_t g_posix_timers[32] = { 0, } ; + +static inline int next_free_host_timer(void) +{ +    int k ; +    /* FIXME: Does finding the next free slot require a lock? */ +    for (k = 0; k < ARRAY_SIZE(g_posix_timers); k++) { +        if (g_posix_timers[k] == 0) { +            g_posix_timers[k] = (timer_t) 1; +            return k; +        } +    } +    return -1; +} +#endif + +/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */ +#ifdef TARGET_ARM +static inline int regpairs_aligned(void *cpu_env) { +    return ((((CPUARMState *)cpu_env)->eabi) == 1) ; +} +#elif defined(TARGET_MIPS) +static inline int regpairs_aligned(void *cpu_env) { return 1; } +#elif defined(TARGET_PPC) && !defined(TARGET_PPC64) +/* SysV AVI for PPC32 expects 64bit parameters to be passed on odd/even pairs + * of registers which translates to the same as ARM/MIPS, because we start with + * r3 as arg1 */ +static inline int regpairs_aligned(void *cpu_env) { return 1; } +#else +static inline int regpairs_aligned(void *cpu_env) { return 0; } +#endif + +#define ERRNO_TABLE_SIZE 1200 + +/* target_to_host_errno_table[] is initialized from + * host_to_target_errno_table[] in syscall_init(). */ +static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = { +}; + +/* + * This list is the union of errno values overridden in asm-<arch>/errno.h + * minus the errnos that are not actually generic to all archs. + */ +static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = { +    [EIDRM]		= TARGET_EIDRM, +    [ECHRNG]		= TARGET_ECHRNG, +    [EL2NSYNC]		= TARGET_EL2NSYNC, +    [EL3HLT]		= TARGET_EL3HLT, +    [EL3RST]		= TARGET_EL3RST, +    [ELNRNG]		= TARGET_ELNRNG, +    [EUNATCH]		= TARGET_EUNATCH, +    [ENOCSI]		= TARGET_ENOCSI, +    [EL2HLT]		= TARGET_EL2HLT, +    [EDEADLK]		= TARGET_EDEADLK, +    [ENOLCK]		= TARGET_ENOLCK, +    [EBADE]		= TARGET_EBADE, +    [EBADR]		= TARGET_EBADR, +    [EXFULL]		= TARGET_EXFULL, +    [ENOANO]		= TARGET_ENOANO, +    [EBADRQC]		= TARGET_EBADRQC, +    [EBADSLT]		= TARGET_EBADSLT, +    [EBFONT]		= TARGET_EBFONT, +    [ENOSTR]		= TARGET_ENOSTR, +    [ENODATA]		= TARGET_ENODATA, +    [ETIME]		= TARGET_ETIME, +    [ENOSR]		= TARGET_ENOSR, +    [ENONET]		= TARGET_ENONET, +    [ENOPKG]		= TARGET_ENOPKG, +    [EREMOTE]		= TARGET_EREMOTE, +    [ENOLINK]		= TARGET_ENOLINK, +    [EADV]		= TARGET_EADV, +    [ESRMNT]		= TARGET_ESRMNT, +    [ECOMM]		= TARGET_ECOMM, +    [EPROTO]		= TARGET_EPROTO, +    [EDOTDOT]		= TARGET_EDOTDOT, +    [EMULTIHOP]		= TARGET_EMULTIHOP, +    [EBADMSG]		= TARGET_EBADMSG, +    [ENAMETOOLONG]	= TARGET_ENAMETOOLONG, +    [EOVERFLOW]		= TARGET_EOVERFLOW, +    [ENOTUNIQ]		= TARGET_ENOTUNIQ, +    [EBADFD]		= TARGET_EBADFD, +    [EREMCHG]		= TARGET_EREMCHG, +    [ELIBACC]		= TARGET_ELIBACC, +    [ELIBBAD]		= TARGET_ELIBBAD, +    [ELIBSCN]		= TARGET_ELIBSCN, +    [ELIBMAX]		= TARGET_ELIBMAX, +    [ELIBEXEC]		= TARGET_ELIBEXEC, +    [EILSEQ]		= TARGET_EILSEQ, +    [ENOSYS]		= TARGET_ENOSYS, +    [ELOOP]		= TARGET_ELOOP, +    [ERESTART]		= TARGET_ERESTART, +    [ESTRPIPE]		= TARGET_ESTRPIPE, +    [ENOTEMPTY]		= TARGET_ENOTEMPTY, +    [EUSERS]		= TARGET_EUSERS, +    [ENOTSOCK]		= TARGET_ENOTSOCK, +    [EDESTADDRREQ]	= TARGET_EDESTADDRREQ, +    [EMSGSIZE]		= TARGET_EMSGSIZE, +    [EPROTOTYPE]	= TARGET_EPROTOTYPE, +    [ENOPROTOOPT]	= TARGET_ENOPROTOOPT, +    [EPROTONOSUPPORT]	= TARGET_EPROTONOSUPPORT, +    [ESOCKTNOSUPPORT]	= TARGET_ESOCKTNOSUPPORT, +    [EOPNOTSUPP]	= TARGET_EOPNOTSUPP, +    [EPFNOSUPPORT]	= TARGET_EPFNOSUPPORT, +    [EAFNOSUPPORT]	= TARGET_EAFNOSUPPORT, +    [EADDRINUSE]	= TARGET_EADDRINUSE, +    [EADDRNOTAVAIL]	= TARGET_EADDRNOTAVAIL, +    [ENETDOWN]		= TARGET_ENETDOWN, +    [ENETUNREACH]	= TARGET_ENETUNREACH, +    [ENETRESET]		= TARGET_ENETRESET, +    [ECONNABORTED]	= TARGET_ECONNABORTED, +    [ECONNRESET]	= TARGET_ECONNRESET, +    [ENOBUFS]		= TARGET_ENOBUFS, +    [EISCONN]		= TARGET_EISCONN, +    [ENOTCONN]		= TARGET_ENOTCONN, +    [EUCLEAN]		= TARGET_EUCLEAN, +    [ENOTNAM]		= TARGET_ENOTNAM, +    [ENAVAIL]		= TARGET_ENAVAIL, +    [EISNAM]		= TARGET_EISNAM, +    [EREMOTEIO]		= TARGET_EREMOTEIO, +    [ESHUTDOWN]		= TARGET_ESHUTDOWN, +    [ETOOMANYREFS]	= TARGET_ETOOMANYREFS, +    [ETIMEDOUT]		= TARGET_ETIMEDOUT, +    [ECONNREFUSED]	= TARGET_ECONNREFUSED, +    [EHOSTDOWN]		= TARGET_EHOSTDOWN, +    [EHOSTUNREACH]	= TARGET_EHOSTUNREACH, +    [EALREADY]		= TARGET_EALREADY, +    [EINPROGRESS]	= TARGET_EINPROGRESS, +    [ESTALE]		= TARGET_ESTALE, +    [ECANCELED]		= TARGET_ECANCELED, +    [ENOMEDIUM]		= TARGET_ENOMEDIUM, +    [EMEDIUMTYPE]	= TARGET_EMEDIUMTYPE, +#ifdef ENOKEY +    [ENOKEY]		= TARGET_ENOKEY, +#endif +#ifdef EKEYEXPIRED +    [EKEYEXPIRED]	= TARGET_EKEYEXPIRED, +#endif +#ifdef EKEYREVOKED +    [EKEYREVOKED]	= TARGET_EKEYREVOKED, +#endif +#ifdef EKEYREJECTED +    [EKEYREJECTED]	= TARGET_EKEYREJECTED, +#endif +#ifdef EOWNERDEAD +    [EOWNERDEAD]	= TARGET_EOWNERDEAD, +#endif +#ifdef ENOTRECOVERABLE +    [ENOTRECOVERABLE]	= TARGET_ENOTRECOVERABLE, +#endif +}; + +static inline int host_to_target_errno(int err) +{ +    if(host_to_target_errno_table[err]) +        return host_to_target_errno_table[err]; +    return err; +} + +static inline int target_to_host_errno(int err) +{ +    if (target_to_host_errno_table[err]) +        return target_to_host_errno_table[err]; +    return err; +} + +static inline abi_long get_errno(abi_long ret) +{ +    if (ret == -1) +        return -host_to_target_errno(errno); +    else +        return ret; +} + +static inline int is_error(abi_long ret) +{ +    return (abi_ulong)ret >= (abi_ulong)(-4096); +} + +char *target_strerror(int err) +{ +    if ((err >= ERRNO_TABLE_SIZE) || (err < 0)) { +        return NULL; +    } +    return strerror(target_to_host_errno(err)); +} + +static inline int host_to_target_sock_type(int host_type) +{ +    int target_type; + +    switch (host_type & 0xf /* SOCK_TYPE_MASK */) { +    case SOCK_DGRAM: +        target_type = TARGET_SOCK_DGRAM; +        break; +    case SOCK_STREAM: +        target_type = TARGET_SOCK_STREAM; +        break; +    default: +        target_type = host_type & 0xf /* SOCK_TYPE_MASK */; +        break; +    } + +#if defined(SOCK_CLOEXEC) +    if (host_type & SOCK_CLOEXEC) { +        target_type |= TARGET_SOCK_CLOEXEC; +    } +#endif + +#if defined(SOCK_NONBLOCK) +    if (host_type & SOCK_NONBLOCK) { +        target_type |= TARGET_SOCK_NONBLOCK; +    } +#endif + +    return target_type; +} + +static abi_ulong target_brk; +static abi_ulong target_original_brk; +static abi_ulong brk_page; + +void target_set_brk(abi_ulong new_brk) +{ +    target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk); +    brk_page = HOST_PAGE_ALIGN(target_brk); +} + +//#define DEBUGF_BRK(message, args...) do { fprintf(stderr, (message), ## args); } while (0) +#define DEBUGF_BRK(message, args...) + +/* do_brk() must return target values and target errnos. */ +abi_long do_brk(abi_ulong new_brk) +{ +    abi_long mapped_addr; +    int	new_alloc_size; + +    DEBUGF_BRK("do_brk(" TARGET_ABI_FMT_lx ") -> ", new_brk); + +    if (!new_brk) { +        DEBUGF_BRK(TARGET_ABI_FMT_lx " (!new_brk)\n", target_brk); +        return target_brk; +    } +    if (new_brk < target_original_brk) { +        DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk < target_original_brk)\n", +                   target_brk); +        return target_brk; +    } + +    /* If the new brk is less than the highest page reserved to the +     * target heap allocation, set it and we're almost done...  */ +    if (new_brk <= brk_page) { +        /* Heap contents are initialized to zero, as for anonymous +         * mapped pages.  */ +        if (new_brk > target_brk) { +            memset(g2h(target_brk), 0, new_brk - target_brk); +        } +	target_brk = new_brk; +        DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk <= brk_page)\n", target_brk); +    	return target_brk; +    } + +    /* We need to allocate more memory after the brk... Note that +     * we don't use MAP_FIXED because that will map over the top of +     * any existing mapping (like the one with the host libc or qemu +     * itself); instead we treat "mapped but at wrong address" as +     * a failure and unmap again. +     */ +    new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page); +    mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size, +                                        PROT_READ|PROT_WRITE, +                                        MAP_ANON|MAP_PRIVATE, 0, 0)); + +    if (mapped_addr == brk_page) { +        /* Heap contents are initialized to zero, as for anonymous +         * mapped pages.  Technically the new pages are already +         * initialized to zero since they *are* anonymous mapped +         * pages, however we have to take care with the contents that +         * come from the remaining part of the previous page: it may +         * contains garbage data due to a previous heap usage (grown +         * then shrunken).  */ +        memset(g2h(target_brk), 0, brk_page - target_brk); + +        target_brk = new_brk; +        brk_page = HOST_PAGE_ALIGN(target_brk); +        DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr == brk_page)\n", +            target_brk); +        return target_brk; +    } else if (mapped_addr != -1) { +        /* Mapped but at wrong address, meaning there wasn't actually +         * enough space for this brk. +         */ +        target_munmap(mapped_addr, new_alloc_size); +        mapped_addr = -1; +        DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr != -1)\n", target_brk); +    } +    else { +        DEBUGF_BRK(TARGET_ABI_FMT_lx " (otherwise)\n", target_brk); +    } + +#if defined(TARGET_ALPHA) +    /* We (partially) emulate OSF/1 on Alpha, which requires we +       return a proper errno, not an unchanged brk value.  */ +    return -TARGET_ENOMEM; +#endif +    /* For everything else, return the previous break. */ +    return target_brk; +} + +static inline abi_long copy_from_user_fdset(fd_set *fds, +                                            abi_ulong target_fds_addr, +                                            int n) +{ +    int i, nw, j, k; +    abi_ulong b, *target_fds; + +    nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS; +    if (!(target_fds = lock_user(VERIFY_READ, +                                 target_fds_addr, +                                 sizeof(abi_ulong) * nw, +                                 1))) +        return -TARGET_EFAULT; + +    FD_ZERO(fds); +    k = 0; +    for (i = 0; i < nw; i++) { +        /* grab the abi_ulong */ +        __get_user(b, &target_fds[i]); +        for (j = 0; j < TARGET_ABI_BITS; j++) { +            /* check the bit inside the abi_ulong */ +            if ((b >> j) & 1) +                FD_SET(k, fds); +            k++; +        } +    } + +    unlock_user(target_fds, target_fds_addr, 0); + +    return 0; +} + +static inline abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr, +                                                 abi_ulong target_fds_addr, +                                                 int n) +{ +    if (target_fds_addr) { +        if (copy_from_user_fdset(fds, target_fds_addr, n)) +            return -TARGET_EFAULT; +        *fds_ptr = fds; +    } else { +        *fds_ptr = NULL; +    } +    return 0; +} + +static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr, +                                          const fd_set *fds, +                                          int n) +{ +    int i, nw, j, k; +    abi_long v; +    abi_ulong *target_fds; + +    nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS; +    if (!(target_fds = lock_user(VERIFY_WRITE, +                                 target_fds_addr, +                                 sizeof(abi_ulong) * nw, +                                 0))) +        return -TARGET_EFAULT; + +    k = 0; +    for (i = 0; i < nw; i++) { +        v = 0; +        for (j = 0; j < TARGET_ABI_BITS; j++) { +            v |= ((abi_ulong)(FD_ISSET(k, fds) != 0) << j); +            k++; +        } +        __put_user(v, &target_fds[i]); +    } + +    unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw); + +    return 0; +} + +#if defined(__alpha__) +#define HOST_HZ 1024 +#else +#define HOST_HZ 100 +#endif + +static inline abi_long host_to_target_clock_t(long ticks) +{ +#if HOST_HZ == TARGET_HZ +    return ticks; +#else +    return ((int64_t)ticks * TARGET_HZ) / HOST_HZ; +#endif +} + +static inline abi_long host_to_target_rusage(abi_ulong target_addr, +                                             const struct rusage *rusage) +{ +    struct target_rusage *target_rusage; + +    if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0)) +        return -TARGET_EFAULT; +    target_rusage->ru_utime.tv_sec = tswapal(rusage->ru_utime.tv_sec); +    target_rusage->ru_utime.tv_usec = tswapal(rusage->ru_utime.tv_usec); +    target_rusage->ru_stime.tv_sec = tswapal(rusage->ru_stime.tv_sec); +    target_rusage->ru_stime.tv_usec = tswapal(rusage->ru_stime.tv_usec); +    target_rusage->ru_maxrss = tswapal(rusage->ru_maxrss); +    target_rusage->ru_ixrss = tswapal(rusage->ru_ixrss); +    target_rusage->ru_idrss = tswapal(rusage->ru_idrss); +    target_rusage->ru_isrss = tswapal(rusage->ru_isrss); +    target_rusage->ru_minflt = tswapal(rusage->ru_minflt); +    target_rusage->ru_majflt = tswapal(rusage->ru_majflt); +    target_rusage->ru_nswap = tswapal(rusage->ru_nswap); +    target_rusage->ru_inblock = tswapal(rusage->ru_inblock); +    target_rusage->ru_oublock = tswapal(rusage->ru_oublock); +    target_rusage->ru_msgsnd = tswapal(rusage->ru_msgsnd); +    target_rusage->ru_msgrcv = tswapal(rusage->ru_msgrcv); +    target_rusage->ru_nsignals = tswapal(rusage->ru_nsignals); +    target_rusage->ru_nvcsw = tswapal(rusage->ru_nvcsw); +    target_rusage->ru_nivcsw = tswapal(rusage->ru_nivcsw); +    unlock_user_struct(target_rusage, target_addr, 1); + +    return 0; +} + +static inline rlim_t target_to_host_rlim(abi_ulong target_rlim) +{ +    abi_ulong target_rlim_swap; +    rlim_t result; +     +    target_rlim_swap = tswapal(target_rlim); +    if (target_rlim_swap == TARGET_RLIM_INFINITY) +        return RLIM_INFINITY; + +    result = target_rlim_swap; +    if (target_rlim_swap != (rlim_t)result) +        return RLIM_INFINITY; +     +    return result; +} + +static inline abi_ulong host_to_target_rlim(rlim_t rlim) +{ +    abi_ulong target_rlim_swap; +    abi_ulong result; +     +    if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim) +        target_rlim_swap = TARGET_RLIM_INFINITY; +    else +        target_rlim_swap = rlim; +    result = tswapal(target_rlim_swap); +     +    return result; +} + +static inline int target_to_host_resource(int code) +{ +    switch (code) { +    case TARGET_RLIMIT_AS: +        return RLIMIT_AS; +    case TARGET_RLIMIT_CORE: +        return RLIMIT_CORE; +    case TARGET_RLIMIT_CPU: +        return RLIMIT_CPU; +    case TARGET_RLIMIT_DATA: +        return RLIMIT_DATA; +    case TARGET_RLIMIT_FSIZE: +        return RLIMIT_FSIZE; +    case TARGET_RLIMIT_LOCKS: +        return RLIMIT_LOCKS; +    case TARGET_RLIMIT_MEMLOCK: +        return RLIMIT_MEMLOCK; +    case TARGET_RLIMIT_MSGQUEUE: +        return RLIMIT_MSGQUEUE; +    case TARGET_RLIMIT_NICE: +        return RLIMIT_NICE; +    case TARGET_RLIMIT_NOFILE: +        return RLIMIT_NOFILE; +    case TARGET_RLIMIT_NPROC: +        return RLIMIT_NPROC; +    case TARGET_RLIMIT_RSS: +        return RLIMIT_RSS; +    case TARGET_RLIMIT_RTPRIO: +        return RLIMIT_RTPRIO; +    case TARGET_RLIMIT_SIGPENDING: +        return RLIMIT_SIGPENDING; +    case TARGET_RLIMIT_STACK: +        return RLIMIT_STACK; +    default: +        return code; +    } +} + +static inline abi_long copy_from_user_timeval(struct timeval *tv, +                                              abi_ulong target_tv_addr) +{ +    struct target_timeval *target_tv; + +    if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) +        return -TARGET_EFAULT; + +    __get_user(tv->tv_sec, &target_tv->tv_sec); +    __get_user(tv->tv_usec, &target_tv->tv_usec); + +    unlock_user_struct(target_tv, target_tv_addr, 0); + +    return 0; +} + +static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr, +                                            const struct timeval *tv) +{ +    struct target_timeval *target_tv; + +    if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) +        return -TARGET_EFAULT; + +    __put_user(tv->tv_sec, &target_tv->tv_sec); +    __put_user(tv->tv_usec, &target_tv->tv_usec); + +    unlock_user_struct(target_tv, target_tv_addr, 1); + +    return 0; +} + +static inline abi_long copy_from_user_timezone(struct timezone *tz, +                                               abi_ulong target_tz_addr) +{ +    struct target_timezone *target_tz; + +    if (!lock_user_struct(VERIFY_READ, target_tz, target_tz_addr, 1)) { +        return -TARGET_EFAULT; +    } + +    __get_user(tz->tz_minuteswest, &target_tz->tz_minuteswest); +    __get_user(tz->tz_dsttime, &target_tz->tz_dsttime); + +    unlock_user_struct(target_tz, target_tz_addr, 0); + +    return 0; +} + +#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open) +#include <mqueue.h> + +static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr, +                                              abi_ulong target_mq_attr_addr) +{ +    struct target_mq_attr *target_mq_attr; + +    if (!lock_user_struct(VERIFY_READ, target_mq_attr, +                          target_mq_attr_addr, 1)) +        return -TARGET_EFAULT; + +    __get_user(attr->mq_flags, &target_mq_attr->mq_flags); +    __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg); +    __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize); +    __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs); + +    unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0); + +    return 0; +} + +static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr, +                                            const struct mq_attr *attr) +{ +    struct target_mq_attr *target_mq_attr; + +    if (!lock_user_struct(VERIFY_WRITE, target_mq_attr, +                          target_mq_attr_addr, 0)) +        return -TARGET_EFAULT; + +    __put_user(attr->mq_flags, &target_mq_attr->mq_flags); +    __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg); +    __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize); +    __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs); + +    unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1); + +    return 0; +} +#endif + +#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) +/* do_select() must return target values and target errnos. */ +static abi_long do_select(int n, +                          abi_ulong rfd_addr, abi_ulong wfd_addr, +                          abi_ulong efd_addr, abi_ulong target_tv_addr) +{ +    fd_set rfds, wfds, efds; +    fd_set *rfds_ptr, *wfds_ptr, *efds_ptr; +    struct timeval tv, *tv_ptr; +    abi_long ret; + +    ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n); +    if (ret) { +        return ret; +    } +    ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n); +    if (ret) { +        return ret; +    } +    ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n); +    if (ret) { +        return ret; +    } + +    if (target_tv_addr) { +        if (copy_from_user_timeval(&tv, target_tv_addr)) +            return -TARGET_EFAULT; +        tv_ptr = &tv; +    } else { +        tv_ptr = NULL; +    } + +    ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr)); + +    if (!is_error(ret)) { +        if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) +            return -TARGET_EFAULT; +        if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n)) +            return -TARGET_EFAULT; +        if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n)) +            return -TARGET_EFAULT; + +        if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv)) +            return -TARGET_EFAULT; +    } + +    return ret; +} +#endif + +static abi_long do_pipe2(int host_pipe[], int flags) +{ +#ifdef CONFIG_PIPE2 +    return pipe2(host_pipe, flags); +#else +    return -ENOSYS; +#endif +} + +static abi_long do_pipe(void *cpu_env, abi_ulong pipedes, +                        int flags, int is_pipe2) +{ +    int host_pipe[2]; +    abi_long ret; +    ret = flags ? do_pipe2(host_pipe, flags) : pipe(host_pipe); + +    if (is_error(ret)) +        return get_errno(ret); + +    /* Several targets have special calling conventions for the original +       pipe syscall, but didn't replicate this into the pipe2 syscall.  */ +    if (!is_pipe2) { +#if defined(TARGET_ALPHA) +        ((CPUAlphaState *)cpu_env)->ir[IR_A4] = host_pipe[1]; +        return host_pipe[0]; +#elif defined(TARGET_MIPS) +        ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1]; +        return host_pipe[0]; +#elif defined(TARGET_SH4) +        ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1]; +        return host_pipe[0]; +#elif defined(TARGET_SPARC) +        ((CPUSPARCState*)cpu_env)->regwptr[1] = host_pipe[1]; +        return host_pipe[0]; +#endif +    } + +    if (put_user_s32(host_pipe[0], pipedes) +        || put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0]))) +        return -TARGET_EFAULT; +    return get_errno(ret); +} + +static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn, +                                              abi_ulong target_addr, +                                              socklen_t len) +{ +    struct target_ip_mreqn *target_smreqn; + +    target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1); +    if (!target_smreqn) +        return -TARGET_EFAULT; +    mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr; +    mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr; +    if (len == sizeof(struct target_ip_mreqn)) +        mreqn->imr_ifindex = tswapal(target_smreqn->imr_ifindex); +    unlock_user(target_smreqn, target_addr, 0); + +    return 0; +} + +static inline abi_long target_to_host_sockaddr(struct sockaddr *addr, +                                               abi_ulong target_addr, +                                               socklen_t len) +{ +    const socklen_t unix_maxlen = sizeof (struct sockaddr_un); +    sa_family_t sa_family; +    struct target_sockaddr *target_saddr; + +    target_saddr = lock_user(VERIFY_READ, target_addr, len, 1); +    if (!target_saddr) +        return -TARGET_EFAULT; + +    sa_family = tswap16(target_saddr->sa_family); + +    /* Oops. The caller might send a incomplete sun_path; sun_path +     * must be terminated by \0 (see the manual page), but +     * unfortunately it is quite common to specify sockaddr_un +     * length as "strlen(x->sun_path)" while it should be +     * "strlen(...) + 1". We'll fix that here if needed. +     * Linux kernel has a similar feature. +     */ + +    if (sa_family == AF_UNIX) { +        if (len < unix_maxlen && len > 0) { +            char *cp = (char*)target_saddr; + +            if ( cp[len-1] && !cp[len] ) +                len++; +        } +        if (len > unix_maxlen) +            len = unix_maxlen; +    } + +    memcpy(addr, target_saddr, len); +    addr->sa_family = sa_family; +    if (sa_family == AF_PACKET) { +	struct target_sockaddr_ll *lladdr; + +	lladdr = (struct target_sockaddr_ll *)addr; +	lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex); +	lladdr->sll_hatype = tswap16(lladdr->sll_hatype); +    } +    unlock_user(target_saddr, target_addr, 0); + +    return 0; +} + +static inline abi_long host_to_target_sockaddr(abi_ulong target_addr, +                                               struct sockaddr *addr, +                                               socklen_t len) +{ +    struct target_sockaddr *target_saddr; + +    target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0); +    if (!target_saddr) +        return -TARGET_EFAULT; +    memcpy(target_saddr, addr, len); +    target_saddr->sa_family = tswap16(addr->sa_family); +    unlock_user(target_saddr, target_addr, len); + +    return 0; +} + +static inline abi_long target_to_host_cmsg(struct msghdr *msgh, +                                           struct target_msghdr *target_msgh) +{ +    struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh); +    abi_long msg_controllen; +    abi_ulong target_cmsg_addr; +    struct target_cmsghdr *target_cmsg; +    socklen_t space = 0; +     +    msg_controllen = tswapal(target_msgh->msg_controllen); +    if (msg_controllen < sizeof (struct target_cmsghdr))  +        goto the_end; +    target_cmsg_addr = tswapal(target_msgh->msg_control); +    target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1); +    if (!target_cmsg) +        return -TARGET_EFAULT; + +    while (cmsg && target_cmsg) { +        void *data = CMSG_DATA(cmsg); +        void *target_data = TARGET_CMSG_DATA(target_cmsg); + +        int len = tswapal(target_cmsg->cmsg_len) +                  - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr)); + +        space += CMSG_SPACE(len); +        if (space > msgh->msg_controllen) { +            space -= CMSG_SPACE(len); +            /* This is a QEMU bug, since we allocated the payload +             * area ourselves (unlike overflow in host-to-target +             * conversion, which is just the guest giving us a buffer +             * that's too small). It can't happen for the payload types +             * we currently support; if it becomes an issue in future +             * we would need to improve our allocation strategy to +             * something more intelligent than "twice the size of the +             * target buffer we're reading from". +             */ +            gemu_log("Host cmsg overflow\n"); +            break; +        } + +        if (tswap32(target_cmsg->cmsg_level) == TARGET_SOL_SOCKET) { +            cmsg->cmsg_level = SOL_SOCKET; +        } else { +            cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level); +        } +        cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type); +        cmsg->cmsg_len = CMSG_LEN(len); + +        if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { +            int *fd = (int *)data; +            int *target_fd = (int *)target_data; +            int i, numfds = len / sizeof(int); + +            for (i = 0; i < numfds; i++) { +                __get_user(fd[i], target_fd + i); +            } +        } else if (cmsg->cmsg_level == SOL_SOCKET +               &&  cmsg->cmsg_type == SCM_CREDENTIALS) { +            struct ucred *cred = (struct ucred *)data; +            struct target_ucred *target_cred = +                (struct target_ucred *)target_data; + +            __get_user(cred->pid, &target_cred->pid); +            __get_user(cred->uid, &target_cred->uid); +            __get_user(cred->gid, &target_cred->gid); +        } else { +            gemu_log("Unsupported ancillary data: %d/%d\n", +                                        cmsg->cmsg_level, cmsg->cmsg_type); +            memcpy(data, target_data, len); +        } + +        cmsg = CMSG_NXTHDR(msgh, cmsg); +        target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg); +    } +    unlock_user(target_cmsg, target_cmsg_addr, 0); + the_end: +    msgh->msg_controllen = space; +    return 0; +} + +static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh, +                                           struct msghdr *msgh) +{ +    struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh); +    abi_long msg_controllen; +    abi_ulong target_cmsg_addr; +    struct target_cmsghdr *target_cmsg; +    socklen_t space = 0; + +    msg_controllen = tswapal(target_msgh->msg_controllen); +    if (msg_controllen < sizeof (struct target_cmsghdr))  +        goto the_end; +    target_cmsg_addr = tswapal(target_msgh->msg_control); +    target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0); +    if (!target_cmsg) +        return -TARGET_EFAULT; + +    while (cmsg && target_cmsg) { +        void *data = CMSG_DATA(cmsg); +        void *target_data = TARGET_CMSG_DATA(target_cmsg); + +        int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr)); +        int tgt_len, tgt_space; + +        /* We never copy a half-header but may copy half-data; +         * this is Linux's behaviour in put_cmsg(). Note that +         * truncation here is a guest problem (which we report +         * to the guest via the CTRUNC bit), unlike truncation +         * in target_to_host_cmsg, which is a QEMU bug. +         */ +        if (msg_controllen < sizeof(struct cmsghdr)) { +            target_msgh->msg_flags |= tswap32(MSG_CTRUNC); +            break; +        } + +        if (cmsg->cmsg_level == SOL_SOCKET) { +            target_cmsg->cmsg_level = tswap32(TARGET_SOL_SOCKET); +        } else { +            target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level); +        } +        target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type); + +        tgt_len = TARGET_CMSG_LEN(len); + +        /* Payload types which need a different size of payload on +         * the target must adjust tgt_len here. +         */ +        switch (cmsg->cmsg_level) { +        case SOL_SOCKET: +            switch (cmsg->cmsg_type) { +            case SO_TIMESTAMP: +                tgt_len = sizeof(struct target_timeval); +                break; +            default: +                break; +            } +        default: +            break; +        } + +        if (msg_controllen < tgt_len) { +            target_msgh->msg_flags |= tswap32(MSG_CTRUNC); +            tgt_len = msg_controllen; +        } + +        /* We must now copy-and-convert len bytes of payload +         * into tgt_len bytes of destination space. Bear in mind +         * that in both source and destination we may be dealing +         * with a truncated value! +         */ +        switch (cmsg->cmsg_level) { +        case SOL_SOCKET: +            switch (cmsg->cmsg_type) { +            case SCM_RIGHTS: +            { +                int *fd = (int *)data; +                int *target_fd = (int *)target_data; +                int i, numfds = tgt_len / sizeof(int); + +                for (i = 0; i < numfds; i++) { +                    __put_user(fd[i], target_fd + i); +                } +                break; +            } +            case SO_TIMESTAMP: +            { +                struct timeval *tv = (struct timeval *)data; +                struct target_timeval *target_tv = +                    (struct target_timeval *)target_data; + +                if (len != sizeof(struct timeval) || +                    tgt_len != sizeof(struct target_timeval)) { +                    goto unimplemented; +                } + +                /* copy struct timeval to target */ +                __put_user(tv->tv_sec, &target_tv->tv_sec); +                __put_user(tv->tv_usec, &target_tv->tv_usec); +                break; +            } +            case SCM_CREDENTIALS: +            { +                struct ucred *cred = (struct ucred *)data; +                struct target_ucred *target_cred = +                    (struct target_ucred *)target_data; + +                __put_user(cred->pid, &target_cred->pid); +                __put_user(cred->uid, &target_cred->uid); +                __put_user(cred->gid, &target_cred->gid); +                break; +            } +            default: +                goto unimplemented; +            } +            break; + +        default: +        unimplemented: +            gemu_log("Unsupported ancillary data: %d/%d\n", +                                        cmsg->cmsg_level, cmsg->cmsg_type); +            memcpy(target_data, data, MIN(len, tgt_len)); +            if (tgt_len > len) { +                memset(target_data + len, 0, tgt_len - len); +            } +        } + +        target_cmsg->cmsg_len = tswapal(tgt_len); +        tgt_space = TARGET_CMSG_SPACE(tgt_len); +        if (msg_controllen < tgt_space) { +            tgt_space = msg_controllen; +        } +        msg_controllen -= tgt_space; +        space += tgt_space; +        cmsg = CMSG_NXTHDR(msgh, cmsg); +        target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg); +    } +    unlock_user(target_cmsg, target_cmsg_addr, space); + the_end: +    target_msgh->msg_controllen = tswapal(space); +    return 0; +} + +/* do_setsockopt() Must return target values and target errnos. */ +static abi_long do_setsockopt(int sockfd, int level, int optname, +                              abi_ulong optval_addr, socklen_t optlen) +{ +    abi_long ret; +    int val; +    struct ip_mreqn *ip_mreq; +    struct ip_mreq_source *ip_mreq_source; + +    switch(level) { +    case SOL_TCP: +        /* TCP options all take an 'int' value.  */ +        if (optlen < sizeof(uint32_t)) +            return -TARGET_EINVAL; + +        if (get_user_u32(val, optval_addr)) +            return -TARGET_EFAULT; +        ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); +        break; +    case SOL_IP: +        switch(optname) { +        case IP_TOS: +        case IP_TTL: +        case IP_HDRINCL: +        case IP_ROUTER_ALERT: +        case IP_RECVOPTS: +        case IP_RETOPTS: +        case IP_PKTINFO: +        case IP_MTU_DISCOVER: +        case IP_RECVERR: +        case IP_RECVTOS: +#ifdef IP_FREEBIND +        case IP_FREEBIND: +#endif +        case IP_MULTICAST_TTL: +        case IP_MULTICAST_LOOP: +            val = 0; +            if (optlen >= sizeof(uint32_t)) { +                if (get_user_u32(val, optval_addr)) +                    return -TARGET_EFAULT; +            } else if (optlen >= 1) { +                if (get_user_u8(val, optval_addr)) +                    return -TARGET_EFAULT; +            } +            ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); +            break; +        case IP_ADD_MEMBERSHIP: +        case IP_DROP_MEMBERSHIP: +            if (optlen < sizeof (struct target_ip_mreq) || +                optlen > sizeof (struct target_ip_mreqn)) +                return -TARGET_EINVAL; + +            ip_mreq = (struct ip_mreqn *) alloca(optlen); +            target_to_host_ip_mreq(ip_mreq, optval_addr, optlen); +            ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen)); +            break; + +        case IP_BLOCK_SOURCE: +        case IP_UNBLOCK_SOURCE: +        case IP_ADD_SOURCE_MEMBERSHIP: +        case IP_DROP_SOURCE_MEMBERSHIP: +            if (optlen != sizeof (struct target_ip_mreq_source)) +                return -TARGET_EINVAL; + +            ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1); +            ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen)); +            unlock_user (ip_mreq_source, optval_addr, 0); +            break; + +        default: +            goto unimplemented; +        } +        break; +    case SOL_IPV6: +        switch (optname) { +        case IPV6_MTU_DISCOVER: +        case IPV6_MTU: +        case IPV6_V6ONLY: +        case IPV6_RECVPKTINFO: +            val = 0; +            if (optlen < sizeof(uint32_t)) { +                return -TARGET_EINVAL; +            } +            if (get_user_u32(val, optval_addr)) { +                return -TARGET_EFAULT; +            } +            ret = get_errno(setsockopt(sockfd, level, optname, +                                       &val, sizeof(val))); +            break; +        default: +            goto unimplemented; +        } +        break; +    case SOL_RAW: +        switch (optname) { +        case ICMP_FILTER: +            /* struct icmp_filter takes an u32 value */ +            if (optlen < sizeof(uint32_t)) { +                return -TARGET_EINVAL; +            } + +            if (get_user_u32(val, optval_addr)) { +                return -TARGET_EFAULT; +            } +            ret = get_errno(setsockopt(sockfd, level, optname, +                                       &val, sizeof(val))); +            break; + +        default: +            goto unimplemented; +        } +        break; +    case TARGET_SOL_SOCKET: +        switch (optname) { +        case TARGET_SO_RCVTIMEO: +        { +                struct timeval tv; + +                optname = SO_RCVTIMEO; + +set_timeout: +                if (optlen != sizeof(struct target_timeval)) { +                    return -TARGET_EINVAL; +                } + +                if (copy_from_user_timeval(&tv, optval_addr)) { +                    return -TARGET_EFAULT; +                } + +                ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, +                                &tv, sizeof(tv))); +                return ret; +        } +        case TARGET_SO_SNDTIMEO: +                optname = SO_SNDTIMEO; +                goto set_timeout; +        case TARGET_SO_ATTACH_FILTER: +        { +                struct target_sock_fprog *tfprog; +                struct target_sock_filter *tfilter; +                struct sock_fprog fprog; +                struct sock_filter *filter; +                int i; + +                if (optlen != sizeof(*tfprog)) { +                    return -TARGET_EINVAL; +                } +                if (!lock_user_struct(VERIFY_READ, tfprog, optval_addr, 0)) { +                    return -TARGET_EFAULT; +                } +                if (!lock_user_struct(VERIFY_READ, tfilter, +                                      tswapal(tfprog->filter), 0)) { +                    unlock_user_struct(tfprog, optval_addr, 1); +                    return -TARGET_EFAULT; +                } + +                fprog.len = tswap16(tfprog->len); +                filter = malloc(fprog.len * sizeof(*filter)); +                if (filter == NULL) { +                    unlock_user_struct(tfilter, tfprog->filter, 1); +                    unlock_user_struct(tfprog, optval_addr, 1); +                    return -TARGET_ENOMEM; +                } +                for (i = 0; i < fprog.len; i++) { +                    filter[i].code = tswap16(tfilter[i].code); +                    filter[i].jt = tfilter[i].jt; +                    filter[i].jf = tfilter[i].jf; +                    filter[i].k = tswap32(tfilter[i].k); +                } +                fprog.filter = filter; + +                ret = get_errno(setsockopt(sockfd, SOL_SOCKET, +                                SO_ATTACH_FILTER, &fprog, sizeof(fprog))); +                free(filter); + +                unlock_user_struct(tfilter, tfprog->filter, 1); +                unlock_user_struct(tfprog, optval_addr, 1); +                return ret; +        } +	case TARGET_SO_BINDTODEVICE: +	{ +		char *dev_ifname, *addr_ifname; + +		if (optlen > IFNAMSIZ - 1) { +		    optlen = IFNAMSIZ - 1; +		} +		dev_ifname = lock_user(VERIFY_READ, optval_addr, optlen, 1); +		if (!dev_ifname) { +		    return -TARGET_EFAULT; +		} +		optname = SO_BINDTODEVICE; +		addr_ifname = alloca(IFNAMSIZ); +		memcpy(addr_ifname, dev_ifname, optlen); +		addr_ifname[optlen] = 0; +		ret = get_errno(setsockopt(sockfd, level, optname, addr_ifname, optlen)); +		unlock_user (dev_ifname, optval_addr, 0); +		return ret; +	} +            /* Options with 'int' argument.  */ +        case TARGET_SO_DEBUG: +		optname = SO_DEBUG; +		break; +        case TARGET_SO_REUSEADDR: +		optname = SO_REUSEADDR; +		break; +        case TARGET_SO_TYPE: +		optname = SO_TYPE; +		break; +        case TARGET_SO_ERROR: +		optname = SO_ERROR; +		break; +        case TARGET_SO_DONTROUTE: +		optname = SO_DONTROUTE; +		break; +        case TARGET_SO_BROADCAST: +		optname = SO_BROADCAST; +		break; +        case TARGET_SO_SNDBUF: +		optname = SO_SNDBUF; +		break; +        case TARGET_SO_SNDBUFFORCE: +                optname = SO_SNDBUFFORCE; +                break; +        case TARGET_SO_RCVBUF: +		optname = SO_RCVBUF; +		break; +        case TARGET_SO_RCVBUFFORCE: +                optname = SO_RCVBUFFORCE; +                break; +        case TARGET_SO_KEEPALIVE: +		optname = SO_KEEPALIVE; +		break; +        case TARGET_SO_OOBINLINE: +		optname = SO_OOBINLINE; +		break; +        case TARGET_SO_NO_CHECK: +		optname = SO_NO_CHECK; +		break; +        case TARGET_SO_PRIORITY: +		optname = SO_PRIORITY; +		break; +#ifdef SO_BSDCOMPAT +        case TARGET_SO_BSDCOMPAT: +		optname = SO_BSDCOMPAT; +		break; +#endif +        case TARGET_SO_PASSCRED: +		optname = SO_PASSCRED; +		break; +        case TARGET_SO_PASSSEC: +                optname = SO_PASSSEC; +                break; +        case TARGET_SO_TIMESTAMP: +		optname = SO_TIMESTAMP; +		break; +        case TARGET_SO_RCVLOWAT: +		optname = SO_RCVLOWAT; +		break; +            break; +        default: +            goto unimplemented; +        } +	if (optlen < sizeof(uint32_t)) +            return -TARGET_EINVAL; + +	if (get_user_u32(val, optval_addr)) +            return -TARGET_EFAULT; +	ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val))); +        break; +    default: +    unimplemented: +        gemu_log("Unsupported setsockopt level=%d optname=%d\n", level, optname); +        ret = -TARGET_ENOPROTOOPT; +    } +    return ret; +} + +/* do_getsockopt() Must return target values and target errnos. */ +static abi_long do_getsockopt(int sockfd, int level, int optname, +                              abi_ulong optval_addr, abi_ulong optlen) +{ +    abi_long ret; +    int len, val; +    socklen_t lv; + +    switch(level) { +    case TARGET_SOL_SOCKET: +        level = SOL_SOCKET; +        switch (optname) { +        /* These don't just return a single integer */ +        case TARGET_SO_LINGER: +        case TARGET_SO_RCVTIMEO: +        case TARGET_SO_SNDTIMEO: +        case TARGET_SO_PEERNAME: +            goto unimplemented; +        case TARGET_SO_PEERCRED: { +            struct ucred cr; +            socklen_t crlen; +            struct target_ucred *tcr; + +            if (get_user_u32(len, optlen)) { +                return -TARGET_EFAULT; +            } +            if (len < 0) { +                return -TARGET_EINVAL; +            } + +            crlen = sizeof(cr); +            ret = get_errno(getsockopt(sockfd, level, SO_PEERCRED, +                                       &cr, &crlen)); +            if (ret < 0) { +                return ret; +            } +            if (len > crlen) { +                len = crlen; +            } +            if (!lock_user_struct(VERIFY_WRITE, tcr, optval_addr, 0)) { +                return -TARGET_EFAULT; +            } +            __put_user(cr.pid, &tcr->pid); +            __put_user(cr.uid, &tcr->uid); +            __put_user(cr.gid, &tcr->gid); +            unlock_user_struct(tcr, optval_addr, 1); +            if (put_user_u32(len, optlen)) { +                return -TARGET_EFAULT; +            } +            break; +        } +        /* Options with 'int' argument.  */ +        case TARGET_SO_DEBUG: +            optname = SO_DEBUG; +            goto int_case; +        case TARGET_SO_REUSEADDR: +            optname = SO_REUSEADDR; +            goto int_case; +        case TARGET_SO_TYPE: +            optname = SO_TYPE; +            goto int_case; +        case TARGET_SO_ERROR: +            optname = SO_ERROR; +            goto int_case; +        case TARGET_SO_DONTROUTE: +            optname = SO_DONTROUTE; +            goto int_case; +        case TARGET_SO_BROADCAST: +            optname = SO_BROADCAST; +            goto int_case; +        case TARGET_SO_SNDBUF: +            optname = SO_SNDBUF; +            goto int_case; +        case TARGET_SO_RCVBUF: +            optname = SO_RCVBUF; +            goto int_case; +        case TARGET_SO_KEEPALIVE: +            optname = SO_KEEPALIVE; +            goto int_case; +        case TARGET_SO_OOBINLINE: +            optname = SO_OOBINLINE; +            goto int_case; +        case TARGET_SO_NO_CHECK: +            optname = SO_NO_CHECK; +            goto int_case; +        case TARGET_SO_PRIORITY: +            optname = SO_PRIORITY; +            goto int_case; +#ifdef SO_BSDCOMPAT +        case TARGET_SO_BSDCOMPAT: +            optname = SO_BSDCOMPAT; +            goto int_case; +#endif +        case TARGET_SO_PASSCRED: +            optname = SO_PASSCRED; +            goto int_case; +        case TARGET_SO_TIMESTAMP: +            optname = SO_TIMESTAMP; +            goto int_case; +        case TARGET_SO_RCVLOWAT: +            optname = SO_RCVLOWAT; +            goto int_case; +        case TARGET_SO_ACCEPTCONN: +            optname = SO_ACCEPTCONN; +            goto int_case; +        default: +            goto int_case; +        } +        break; +    case SOL_TCP: +        /* TCP options all take an 'int' value.  */ +    int_case: +        if (get_user_u32(len, optlen)) +            return -TARGET_EFAULT; +        if (len < 0) +            return -TARGET_EINVAL; +        lv = sizeof(lv); +        ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv)); +        if (ret < 0) +            return ret; +        if (optname == SO_TYPE) { +            val = host_to_target_sock_type(val); +        } +        if (len > lv) +            len = lv; +        if (len == 4) { +            if (put_user_u32(val, optval_addr)) +                return -TARGET_EFAULT; +        } else { +            if (put_user_u8(val, optval_addr)) +                return -TARGET_EFAULT; +        } +        if (put_user_u32(len, optlen)) +            return -TARGET_EFAULT; +        break; +    case SOL_IP: +        switch(optname) { +        case IP_TOS: +        case IP_TTL: +        case IP_HDRINCL: +        case IP_ROUTER_ALERT: +        case IP_RECVOPTS: +        case IP_RETOPTS: +        case IP_PKTINFO: +        case IP_MTU_DISCOVER: +        case IP_RECVERR: +        case IP_RECVTOS: +#ifdef IP_FREEBIND +        case IP_FREEBIND: +#endif +        case IP_MULTICAST_TTL: +        case IP_MULTICAST_LOOP: +            if (get_user_u32(len, optlen)) +                return -TARGET_EFAULT; +            if (len < 0) +                return -TARGET_EINVAL; +            lv = sizeof(lv); +            ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv)); +            if (ret < 0) +                return ret; +            if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) { +                len = 1; +                if (put_user_u32(len, optlen) +                    || put_user_u8(val, optval_addr)) +                    return -TARGET_EFAULT; +            } else { +                if (len > sizeof(int)) +                    len = sizeof(int); +                if (put_user_u32(len, optlen) +                    || put_user_u32(val, optval_addr)) +                    return -TARGET_EFAULT; +            } +            break; +        default: +            ret = -TARGET_ENOPROTOOPT; +            break; +        } +        break; +    default: +    unimplemented: +        gemu_log("getsockopt level=%d optname=%d not yet supported\n", +                 level, optname); +        ret = -TARGET_EOPNOTSUPP; +        break; +    } +    return ret; +} + +static struct iovec *lock_iovec(int type, abi_ulong target_addr, +                                int count, int copy) +{ +    struct target_iovec *target_vec; +    struct iovec *vec; +    abi_ulong total_len, max_len; +    int i; +    int err = 0; +    bool bad_address = false; + +    if (count == 0) { +        errno = 0; +        return NULL; +    } +    if (count < 0 || count > IOV_MAX) { +        errno = EINVAL; +        return NULL; +    } + +    vec = calloc(count, sizeof(struct iovec)); +    if (vec == NULL) { +        errno = ENOMEM; +        return NULL; +    } + +    target_vec = lock_user(VERIFY_READ, target_addr, +                           count * sizeof(struct target_iovec), 1); +    if (target_vec == NULL) { +        err = EFAULT; +        goto fail2; +    } + +    /* ??? If host page size > target page size, this will result in a +       value larger than what we can actually support.  */ +    max_len = 0x7fffffff & TARGET_PAGE_MASK; +    total_len = 0; + +    for (i = 0; i < count; i++) { +        abi_ulong base = tswapal(target_vec[i].iov_base); +        abi_long len = tswapal(target_vec[i].iov_len); + +        if (len < 0) { +            err = EINVAL; +            goto fail; +        } else if (len == 0) { +            /* Zero length pointer is ignored.  */ +            vec[i].iov_base = 0; +        } else { +            vec[i].iov_base = lock_user(type, base, len, copy); +            /* If the first buffer pointer is bad, this is a fault.  But +             * subsequent bad buffers will result in a partial write; this +             * is realized by filling the vector with null pointers and +             * zero lengths. */ +            if (!vec[i].iov_base) { +                if (i == 0) { +                    err = EFAULT; +                    goto fail; +                } else { +                    bad_address = true; +                } +            } +            if (bad_address) { +                len = 0; +            } +            if (len > max_len - total_len) { +                len = max_len - total_len; +            } +        } +        vec[i].iov_len = len; +        total_len += len; +    } + +    unlock_user(target_vec, target_addr, 0); +    return vec; + + fail: +    while (--i >= 0) { +        if (tswapal(target_vec[i].iov_len) > 0) { +            unlock_user(vec[i].iov_base, tswapal(target_vec[i].iov_base), 0); +        } +    } +    unlock_user(target_vec, target_addr, 0); + fail2: +    free(vec); +    errno = err; +    return NULL; +} + +static void unlock_iovec(struct iovec *vec, abi_ulong target_addr, +                         int count, int copy) +{ +    struct target_iovec *target_vec; +    int i; + +    target_vec = lock_user(VERIFY_READ, target_addr, +                           count * sizeof(struct target_iovec), 1); +    if (target_vec) { +        for (i = 0; i < count; i++) { +            abi_ulong base = tswapal(target_vec[i].iov_base); +            abi_long len = tswapal(target_vec[i].iov_len); +            if (len < 0) { +                break; +            } +            unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0); +        } +        unlock_user(target_vec, target_addr, 0); +    } + +    free(vec); +} + +static inline int target_to_host_sock_type(int *type) +{ +    int host_type = 0; +    int target_type = *type; + +    switch (target_type & TARGET_SOCK_TYPE_MASK) { +    case TARGET_SOCK_DGRAM: +        host_type = SOCK_DGRAM; +        break; +    case TARGET_SOCK_STREAM: +        host_type = SOCK_STREAM; +        break; +    default: +        host_type = target_type & TARGET_SOCK_TYPE_MASK; +        break; +    } +    if (target_type & TARGET_SOCK_CLOEXEC) { +#if defined(SOCK_CLOEXEC) +        host_type |= SOCK_CLOEXEC; +#else +        return -TARGET_EINVAL; +#endif +    } +    if (target_type & TARGET_SOCK_NONBLOCK) { +#if defined(SOCK_NONBLOCK) +        host_type |= SOCK_NONBLOCK; +#elif !defined(O_NONBLOCK) +        return -TARGET_EINVAL; +#endif +    } +    *type = host_type; +    return 0; +} + +/* Try to emulate socket type flags after socket creation.  */ +static int sock_flags_fixup(int fd, int target_type) +{ +#if !defined(SOCK_NONBLOCK) && defined(O_NONBLOCK) +    if (target_type & TARGET_SOCK_NONBLOCK) { +        int flags = fcntl(fd, F_GETFL); +        if (fcntl(fd, F_SETFL, O_NONBLOCK | flags) == -1) { +            close(fd); +            return -TARGET_EINVAL; +        } +    } +#endif +    return fd; +} + +/* do_socket() Must return target values and target errnos. */ +static abi_long do_socket(int domain, int type, int protocol) +{ +    int target_type = type; +    int ret; + +    ret = target_to_host_sock_type(&type); +    if (ret) { +        return ret; +    } + +    if (domain == PF_NETLINK) +        return -TARGET_EAFNOSUPPORT; +    ret = get_errno(socket(domain, type, protocol)); +    if (ret >= 0) { +        ret = sock_flags_fixup(ret, target_type); +    } +    return ret; +} + +/* do_bind() Must return target values and target errnos. */ +static abi_long do_bind(int sockfd, abi_ulong target_addr, +                        socklen_t addrlen) +{ +    void *addr; +    abi_long ret; + +    if ((int)addrlen < 0) { +        return -TARGET_EINVAL; +    } + +    addr = alloca(addrlen+1); + +    ret = target_to_host_sockaddr(addr, target_addr, addrlen); +    if (ret) +        return ret; + +    return get_errno(bind(sockfd, addr, addrlen)); +} + +/* do_connect() Must return target values and target errnos. */ +static abi_long do_connect(int sockfd, abi_ulong target_addr, +                           socklen_t addrlen) +{ +    void *addr; +    abi_long ret; + +    if ((int)addrlen < 0) { +        return -TARGET_EINVAL; +    } + +    addr = alloca(addrlen+1); + +    ret = target_to_host_sockaddr(addr, target_addr, addrlen); +    if (ret) +        return ret; + +    return get_errno(connect(sockfd, addr, addrlen)); +} + +/* do_sendrecvmsg_locked() Must return target values and target errnos. */ +static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp, +                                      int flags, int send) +{ +    abi_long ret, len; +    struct msghdr msg; +    int count; +    struct iovec *vec; +    abi_ulong target_vec; + +    if (msgp->msg_name) { +        msg.msg_namelen = tswap32(msgp->msg_namelen); +        msg.msg_name = alloca(msg.msg_namelen+1); +        ret = target_to_host_sockaddr(msg.msg_name, tswapal(msgp->msg_name), +                                msg.msg_namelen); +        if (ret) { +            goto out2; +        } +    } else { +        msg.msg_name = NULL; +        msg.msg_namelen = 0; +    } +    msg.msg_controllen = 2 * tswapal(msgp->msg_controllen); +    msg.msg_control = alloca(msg.msg_controllen); +    msg.msg_flags = tswap32(msgp->msg_flags); + +    count = tswapal(msgp->msg_iovlen); +    target_vec = tswapal(msgp->msg_iov); +    vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, +                     target_vec, count, send); +    if (vec == NULL) { +        ret = -host_to_target_errno(errno); +        goto out2; +    } +    msg.msg_iovlen = count; +    msg.msg_iov = vec; + +    if (send) { +        ret = target_to_host_cmsg(&msg, msgp); +        if (ret == 0) +            ret = get_errno(sendmsg(fd, &msg, flags)); +    } else { +        ret = get_errno(recvmsg(fd, &msg, flags)); +        if (!is_error(ret)) { +            len = ret; +            ret = host_to_target_cmsg(msgp, &msg); +            if (!is_error(ret)) { +                msgp->msg_namelen = tswap32(msg.msg_namelen); +                if (msg.msg_name != NULL) { +                    ret = host_to_target_sockaddr(tswapal(msgp->msg_name), +                                    msg.msg_name, msg.msg_namelen); +                    if (ret) { +                        goto out; +                    } +                } + +                ret = len; +            } +        } +    } + +out: +    unlock_iovec(vec, target_vec, count, !send); +out2: +    return ret; +} + +static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg, +                               int flags, int send) +{ +    abi_long ret; +    struct target_msghdr *msgp; + +    if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE, +                          msgp, +                          target_msg, +                          send ? 1 : 0)) { +        return -TARGET_EFAULT; +    } +    ret = do_sendrecvmsg_locked(fd, msgp, flags, send); +    unlock_user_struct(msgp, target_msg, send ? 0 : 1); +    return ret; +} + +#ifdef TARGET_NR_sendmmsg +/* We don't rely on the C library to have sendmmsg/recvmmsg support, + * so it might not have this *mmsg-specific flag either. + */ +#ifndef MSG_WAITFORONE +#define MSG_WAITFORONE 0x10000 +#endif + +static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec, +                                unsigned int vlen, unsigned int flags, +                                int send) +{ +    struct target_mmsghdr *mmsgp; +    abi_long ret = 0; +    int i; + +    if (vlen > UIO_MAXIOV) { +        vlen = UIO_MAXIOV; +    } + +    mmsgp = lock_user(VERIFY_WRITE, target_msgvec, sizeof(*mmsgp) * vlen, 1); +    if (!mmsgp) { +        return -TARGET_EFAULT; +    } + +    for (i = 0; i < vlen; i++) { +        ret = do_sendrecvmsg_locked(fd, &mmsgp[i].msg_hdr, flags, send); +        if (is_error(ret)) { +            break; +        } +        mmsgp[i].msg_len = tswap32(ret); +        /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */ +        if (flags & MSG_WAITFORONE) { +            flags |= MSG_DONTWAIT; +        } +    } + +    unlock_user(mmsgp, target_msgvec, sizeof(*mmsgp) * i); + +    /* Return number of datagrams sent if we sent any at all; +     * otherwise return the error. +     */ +    if (i) { +        return i; +    } +    return ret; +} +#endif + +/* If we don't have a system accept4() then just call accept. + * The callsites to do_accept4() will ensure that they don't + * pass a non-zero flags argument in this config. + */ +#ifndef CONFIG_ACCEPT4 +static inline int accept4(int sockfd, struct sockaddr *addr, +                          socklen_t *addrlen, int flags) +{ +    assert(flags == 0); +    return accept(sockfd, addr, addrlen); +} +#endif + +/* do_accept4() Must return target values and target errnos. */ +static abi_long do_accept4(int fd, abi_ulong target_addr, +                           abi_ulong target_addrlen_addr, int flags) +{ +    socklen_t addrlen; +    void *addr; +    abi_long ret; +    int host_flags; + +    host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl); + +    if (target_addr == 0) { +        return get_errno(accept4(fd, NULL, NULL, host_flags)); +    } + +    /* linux returns EINVAL if addrlen pointer is invalid */ +    if (get_user_u32(addrlen, target_addrlen_addr)) +        return -TARGET_EINVAL; + +    if ((int)addrlen < 0) { +        return -TARGET_EINVAL; +    } + +    if (!access_ok(VERIFY_WRITE, target_addr, addrlen)) +        return -TARGET_EINVAL; + +    addr = alloca(addrlen); + +    ret = get_errno(accept4(fd, addr, &addrlen, host_flags)); +    if (!is_error(ret)) { +        host_to_target_sockaddr(target_addr, addr, addrlen); +        if (put_user_u32(addrlen, target_addrlen_addr)) +            ret = -TARGET_EFAULT; +    } +    return ret; +} + +/* do_getpeername() Must return target values and target errnos. */ +static abi_long do_getpeername(int fd, abi_ulong target_addr, +                               abi_ulong target_addrlen_addr) +{ +    socklen_t addrlen; +    void *addr; +    abi_long ret; + +    if (get_user_u32(addrlen, target_addrlen_addr)) +        return -TARGET_EFAULT; + +    if ((int)addrlen < 0) { +        return -TARGET_EINVAL; +    } + +    if (!access_ok(VERIFY_WRITE, target_addr, addrlen)) +        return -TARGET_EFAULT; + +    addr = alloca(addrlen); + +    ret = get_errno(getpeername(fd, addr, &addrlen)); +    if (!is_error(ret)) { +        host_to_target_sockaddr(target_addr, addr, addrlen); +        if (put_user_u32(addrlen, target_addrlen_addr)) +            ret = -TARGET_EFAULT; +    } +    return ret; +} + +/* do_getsockname() Must return target values and target errnos. */ +static abi_long do_getsockname(int fd, abi_ulong target_addr, +                               abi_ulong target_addrlen_addr) +{ +    socklen_t addrlen; +    void *addr; +    abi_long ret; + +    if (get_user_u32(addrlen, target_addrlen_addr)) +        return -TARGET_EFAULT; + +    if ((int)addrlen < 0) { +        return -TARGET_EINVAL; +    } + +    if (!access_ok(VERIFY_WRITE, target_addr, addrlen)) +        return -TARGET_EFAULT; + +    addr = alloca(addrlen); + +    ret = get_errno(getsockname(fd, addr, &addrlen)); +    if (!is_error(ret)) { +        host_to_target_sockaddr(target_addr, addr, addrlen); +        if (put_user_u32(addrlen, target_addrlen_addr)) +            ret = -TARGET_EFAULT; +    } +    return ret; +} + +/* do_socketpair() Must return target values and target errnos. */ +static abi_long do_socketpair(int domain, int type, int protocol, +                              abi_ulong target_tab_addr) +{ +    int tab[2]; +    abi_long ret; + +    target_to_host_sock_type(&type); + +    ret = get_errno(socketpair(domain, type, protocol, tab)); +    if (!is_error(ret)) { +        if (put_user_s32(tab[0], target_tab_addr) +            || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0]))) +            ret = -TARGET_EFAULT; +    } +    return ret; +} + +/* do_sendto() Must return target values and target errnos. */ +static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags, +                          abi_ulong target_addr, socklen_t addrlen) +{ +    void *addr; +    void *host_msg; +    abi_long ret; + +    if ((int)addrlen < 0) { +        return -TARGET_EINVAL; +    } + +    host_msg = lock_user(VERIFY_READ, msg, len, 1); +    if (!host_msg) +        return -TARGET_EFAULT; +    if (target_addr) { +        addr = alloca(addrlen+1); +        ret = target_to_host_sockaddr(addr, target_addr, addrlen); +        if (ret) { +            unlock_user(host_msg, msg, 0); +            return ret; +        } +        ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen)); +    } else { +        ret = get_errno(send(fd, host_msg, len, flags)); +    } +    unlock_user(host_msg, msg, 0); +    return ret; +} + +/* do_recvfrom() Must return target values and target errnos. */ +static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags, +                            abi_ulong target_addr, +                            abi_ulong target_addrlen) +{ +    socklen_t addrlen; +    void *addr; +    void *host_msg; +    abi_long ret; + +    host_msg = lock_user(VERIFY_WRITE, msg, len, 0); +    if (!host_msg) +        return -TARGET_EFAULT; +    if (target_addr) { +        if (get_user_u32(addrlen, target_addrlen)) { +            ret = -TARGET_EFAULT; +            goto fail; +        } +        if ((int)addrlen < 0) { +            ret = -TARGET_EINVAL; +            goto fail; +        } +        addr = alloca(addrlen); +        ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen)); +    } else { +        addr = NULL; /* To keep compiler quiet.  */ +        ret = get_errno(qemu_recv(fd, host_msg, len, flags)); +    } +    if (!is_error(ret)) { +        if (target_addr) { +            host_to_target_sockaddr(target_addr, addr, addrlen); +            if (put_user_u32(addrlen, target_addrlen)) { +                ret = -TARGET_EFAULT; +                goto fail; +            } +        } +        unlock_user(host_msg, msg, len); +    } else { +fail: +        unlock_user(host_msg, msg, 0); +    } +    return ret; +} + +#ifdef TARGET_NR_socketcall +/* do_socketcall() Must return target values and target errnos. */ +static abi_long do_socketcall(int num, abi_ulong vptr) +{ +    static const unsigned ac[] = { /* number of arguments per call */ +        [SOCKOP_socket] = 3,      /* domain, type, protocol */ +        [SOCKOP_bind] = 3,        /* sockfd, addr, addrlen */ +        [SOCKOP_connect] = 3,     /* sockfd, addr, addrlen */ +        [SOCKOP_listen] = 2,      /* sockfd, backlog */ +        [SOCKOP_accept] = 3,      /* sockfd, addr, addrlen */ +        [SOCKOP_accept4] = 4,     /* sockfd, addr, addrlen, flags */ +        [SOCKOP_getsockname] = 3, /* sockfd, addr, addrlen */ +        [SOCKOP_getpeername] = 3, /* sockfd, addr, addrlen */ +        [SOCKOP_socketpair] = 4,  /* domain, type, protocol, tab */ +        [SOCKOP_send] = 4,        /* sockfd, msg, len, flags */ +        [SOCKOP_recv] = 4,        /* sockfd, msg, len, flags */ +        [SOCKOP_sendto] = 6,      /* sockfd, msg, len, flags, addr, addrlen */ +        [SOCKOP_recvfrom] = 6,    /* sockfd, msg, len, flags, addr, addrlen */ +        [SOCKOP_shutdown] = 2,    /* sockfd, how */ +        [SOCKOP_sendmsg] = 3,     /* sockfd, msg, flags */ +        [SOCKOP_recvmsg] = 3,     /* sockfd, msg, flags */ +        [SOCKOP_setsockopt] = 5,  /* sockfd, level, optname, optval, optlen */ +        [SOCKOP_getsockopt] = 5,  /* sockfd, level, optname, optval, optlen */ +    }; +    abi_long a[6]; /* max 6 args */ + +    /* first, collect the arguments in a[] according to ac[] */ +    if (num >= 0 && num < ARRAY_SIZE(ac)) { +        unsigned i; +        assert(ARRAY_SIZE(a) >= ac[num]); /* ensure we have space for args */ +        for (i = 0; i < ac[num]; ++i) { +            if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) { +                return -TARGET_EFAULT; +            } +        } +    } + +    /* now when we have the args, actually handle the call */ +    switch (num) { +    case SOCKOP_socket: /* domain, type, protocol */ +        return do_socket(a[0], a[1], a[2]); +    case SOCKOP_bind: /* sockfd, addr, addrlen */ +        return do_bind(a[0], a[1], a[2]); +    case SOCKOP_connect: /* sockfd, addr, addrlen */ +        return do_connect(a[0], a[1], a[2]); +    case SOCKOP_listen: /* sockfd, backlog */ +        return get_errno(listen(a[0], a[1])); +    case SOCKOP_accept: /* sockfd, addr, addrlen */ +        return do_accept4(a[0], a[1], a[2], 0); +    case SOCKOP_accept4: /* sockfd, addr, addrlen, flags */ +        return do_accept4(a[0], a[1], a[2], a[3]); +    case SOCKOP_getsockname: /* sockfd, addr, addrlen */ +        return do_getsockname(a[0], a[1], a[2]); +    case SOCKOP_getpeername: /* sockfd, addr, addrlen */ +        return do_getpeername(a[0], a[1], a[2]); +    case SOCKOP_socketpair: /* domain, type, protocol, tab */ +        return do_socketpair(a[0], a[1], a[2], a[3]); +    case SOCKOP_send: /* sockfd, msg, len, flags */ +        return do_sendto(a[0], a[1], a[2], a[3], 0, 0); +    case SOCKOP_recv: /* sockfd, msg, len, flags */ +        return do_recvfrom(a[0], a[1], a[2], a[3], 0, 0); +    case SOCKOP_sendto: /* sockfd, msg, len, flags, addr, addrlen */ +        return do_sendto(a[0], a[1], a[2], a[3], a[4], a[5]); +    case SOCKOP_recvfrom: /* sockfd, msg, len, flags, addr, addrlen */ +        return do_recvfrom(a[0], a[1], a[2], a[3], a[4], a[5]); +    case SOCKOP_shutdown: /* sockfd, how */ +        return get_errno(shutdown(a[0], a[1])); +    case SOCKOP_sendmsg: /* sockfd, msg, flags */ +        return do_sendrecvmsg(a[0], a[1], a[2], 1); +    case SOCKOP_recvmsg: /* sockfd, msg, flags */ +        return do_sendrecvmsg(a[0], a[1], a[2], 0); +    case SOCKOP_setsockopt: /* sockfd, level, optname, optval, optlen */ +        return do_setsockopt(a[0], a[1], a[2], a[3], a[4]); +    case SOCKOP_getsockopt: /* sockfd, level, optname, optval, optlen */ +        return do_getsockopt(a[0], a[1], a[2], a[3], a[4]); +    default: +        gemu_log("Unsupported socketcall: %d\n", num); +        return -TARGET_ENOSYS; +    } +} +#endif + +#define N_SHM_REGIONS	32 + +static struct shm_region { +    abi_ulong	start; +    abi_ulong	size; +} shm_regions[N_SHM_REGIONS]; + +struct target_semid_ds +{ +  struct target_ipc_perm sem_perm; +  abi_ulong sem_otime; +#if !defined(TARGET_PPC64) +  abi_ulong __unused1; +#endif +  abi_ulong sem_ctime; +#if !defined(TARGET_PPC64) +  abi_ulong __unused2; +#endif +  abi_ulong sem_nsems; +  abi_ulong __unused3; +  abi_ulong __unused4; +}; + +static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip, +                                               abi_ulong target_addr) +{ +    struct target_ipc_perm *target_ip; +    struct target_semid_ds *target_sd; + +    if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) +        return -TARGET_EFAULT; +    target_ip = &(target_sd->sem_perm); +    host_ip->__key = tswap32(target_ip->__key); +    host_ip->uid = tswap32(target_ip->uid); +    host_ip->gid = tswap32(target_ip->gid); +    host_ip->cuid = tswap32(target_ip->cuid); +    host_ip->cgid = tswap32(target_ip->cgid); +#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC) +    host_ip->mode = tswap32(target_ip->mode); +#else +    host_ip->mode = tswap16(target_ip->mode); +#endif +#if defined(TARGET_PPC) +    host_ip->__seq = tswap32(target_ip->__seq); +#else +    host_ip->__seq = tswap16(target_ip->__seq); +#endif +    unlock_user_struct(target_sd, target_addr, 0); +    return 0; +} + +static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr, +                                               struct ipc_perm *host_ip) +{ +    struct target_ipc_perm *target_ip; +    struct target_semid_ds *target_sd; + +    if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) +        return -TARGET_EFAULT; +    target_ip = &(target_sd->sem_perm); +    target_ip->__key = tswap32(host_ip->__key); +    target_ip->uid = tswap32(host_ip->uid); +    target_ip->gid = tswap32(host_ip->gid); +    target_ip->cuid = tswap32(host_ip->cuid); +    target_ip->cgid = tswap32(host_ip->cgid); +#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC) +    target_ip->mode = tswap32(host_ip->mode); +#else +    target_ip->mode = tswap16(host_ip->mode); +#endif +#if defined(TARGET_PPC) +    target_ip->__seq = tswap32(host_ip->__seq); +#else +    target_ip->__seq = tswap16(host_ip->__seq); +#endif +    unlock_user_struct(target_sd, target_addr, 1); +    return 0; +} + +static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd, +                                               abi_ulong target_addr) +{ +    struct target_semid_ds *target_sd; + +    if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) +        return -TARGET_EFAULT; +    if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr)) +        return -TARGET_EFAULT; +    host_sd->sem_nsems = tswapal(target_sd->sem_nsems); +    host_sd->sem_otime = tswapal(target_sd->sem_otime); +    host_sd->sem_ctime = tswapal(target_sd->sem_ctime); +    unlock_user_struct(target_sd, target_addr, 0); +    return 0; +} + +static inline abi_long host_to_target_semid_ds(abi_ulong target_addr, +                                               struct semid_ds *host_sd) +{ +    struct target_semid_ds *target_sd; + +    if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) +        return -TARGET_EFAULT; +    if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm))) +        return -TARGET_EFAULT; +    target_sd->sem_nsems = tswapal(host_sd->sem_nsems); +    target_sd->sem_otime = tswapal(host_sd->sem_otime); +    target_sd->sem_ctime = tswapal(host_sd->sem_ctime); +    unlock_user_struct(target_sd, target_addr, 1); +    return 0; +} + +struct target_seminfo { +    int semmap; +    int semmni; +    int semmns; +    int semmnu; +    int semmsl; +    int semopm; +    int semume; +    int semusz; +    int semvmx; +    int semaem; +}; + +static inline abi_long host_to_target_seminfo(abi_ulong target_addr, +                                              struct seminfo *host_seminfo) +{ +    struct target_seminfo *target_seminfo; +    if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0)) +        return -TARGET_EFAULT; +    __put_user(host_seminfo->semmap, &target_seminfo->semmap); +    __put_user(host_seminfo->semmni, &target_seminfo->semmni); +    __put_user(host_seminfo->semmns, &target_seminfo->semmns); +    __put_user(host_seminfo->semmnu, &target_seminfo->semmnu); +    __put_user(host_seminfo->semmsl, &target_seminfo->semmsl); +    __put_user(host_seminfo->semopm, &target_seminfo->semopm); +    __put_user(host_seminfo->semume, &target_seminfo->semume); +    __put_user(host_seminfo->semusz, &target_seminfo->semusz); +    __put_user(host_seminfo->semvmx, &target_seminfo->semvmx); +    __put_user(host_seminfo->semaem, &target_seminfo->semaem); +    unlock_user_struct(target_seminfo, target_addr, 1); +    return 0; +} + +union semun { +	int val; +	struct semid_ds *buf; +	unsigned short *array; +	struct seminfo *__buf; +}; + +union target_semun { +	int val; +	abi_ulong buf; +	abi_ulong array; +	abi_ulong __buf; +}; + +static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array, +                                               abi_ulong target_addr) +{ +    int nsems; +    unsigned short *array; +    union semun semun; +    struct semid_ds semid_ds; +    int i, ret; + +    semun.buf = &semid_ds; + +    ret = semctl(semid, 0, IPC_STAT, semun); +    if (ret == -1) +        return get_errno(ret); + +    nsems = semid_ds.sem_nsems; + +    *host_array = malloc(nsems*sizeof(unsigned short)); +    if (!*host_array) { +        return -TARGET_ENOMEM; +    } +    array = lock_user(VERIFY_READ, target_addr, +                      nsems*sizeof(unsigned short), 1); +    if (!array) { +        free(*host_array); +        return -TARGET_EFAULT; +    } + +    for(i=0; i<nsems; i++) { +        __get_user((*host_array)[i], &array[i]); +    } +    unlock_user(array, target_addr, 0); + +    return 0; +} + +static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr, +                                               unsigned short **host_array) +{ +    int nsems; +    unsigned short *array; +    union semun semun; +    struct semid_ds semid_ds; +    int i, ret; + +    semun.buf = &semid_ds; + +    ret = semctl(semid, 0, IPC_STAT, semun); +    if (ret == -1) +        return get_errno(ret); + +    nsems = semid_ds.sem_nsems; + +    array = lock_user(VERIFY_WRITE, target_addr, +                      nsems*sizeof(unsigned short), 0); +    if (!array) +        return -TARGET_EFAULT; + +    for(i=0; i<nsems; i++) { +        __put_user((*host_array)[i], &array[i]); +    } +    free(*host_array); +    unlock_user(array, target_addr, 1); + +    return 0; +} + +static inline abi_long do_semctl(int semid, int semnum, int cmd, +                                 union target_semun target_su) +{ +    union semun arg; +    struct semid_ds dsarg; +    unsigned short *array = NULL; +    struct seminfo seminfo; +    abi_long ret = -TARGET_EINVAL; +    abi_long err; +    cmd &= 0xff; + +    switch( cmd ) { +	case GETVAL: +	case SETVAL: +            /* In 64 bit cross-endian situations, we will erroneously pick up +             * the wrong half of the union for the "val" element.  To rectify +             * this, the entire 8-byte structure is byteswapped, followed by +	     * a swap of the 4 byte val field. In other cases, the data is +	     * already in proper host byte order. */ +	    if (sizeof(target_su.val) != (sizeof(target_su.buf))) { +		target_su.buf = tswapal(target_su.buf); +		arg.val = tswap32(target_su.val); +	    } else { +		arg.val = target_su.val; +	    } +            ret = get_errno(semctl(semid, semnum, cmd, arg)); +            break; +	case GETALL: +	case SETALL: +            err = target_to_host_semarray(semid, &array, target_su.array); +            if (err) +                return err; +            arg.array = array; +            ret = get_errno(semctl(semid, semnum, cmd, arg)); +            err = host_to_target_semarray(semid, target_su.array, &array); +            if (err) +                return err; +            break; +	case IPC_STAT: +	case IPC_SET: +	case SEM_STAT: +            err = target_to_host_semid_ds(&dsarg, target_su.buf); +            if (err) +                return err; +            arg.buf = &dsarg; +            ret = get_errno(semctl(semid, semnum, cmd, arg)); +            err = host_to_target_semid_ds(target_su.buf, &dsarg); +            if (err) +                return err; +            break; +	case IPC_INFO: +	case SEM_INFO: +            arg.__buf = &seminfo; +            ret = get_errno(semctl(semid, semnum, cmd, arg)); +            err = host_to_target_seminfo(target_su.__buf, &seminfo); +            if (err) +                return err; +            break; +	case IPC_RMID: +	case GETPID: +	case GETNCNT: +	case GETZCNT: +            ret = get_errno(semctl(semid, semnum, cmd, NULL)); +            break; +    } + +    return ret; +} + +struct target_sembuf { +    unsigned short sem_num; +    short sem_op; +    short sem_flg; +}; + +static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf, +                                             abi_ulong target_addr, +                                             unsigned nsops) +{ +    struct target_sembuf *target_sembuf; +    int i; + +    target_sembuf = lock_user(VERIFY_READ, target_addr, +                              nsops*sizeof(struct target_sembuf), 1); +    if (!target_sembuf) +        return -TARGET_EFAULT; + +    for(i=0; i<nsops; i++) { +        __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num); +        __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op); +        __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg); +    } + +    unlock_user(target_sembuf, target_addr, 0); + +    return 0; +} + +static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops) +{ +    struct sembuf sops[nsops]; + +    if (target_to_host_sembuf(sops, ptr, nsops)) +        return -TARGET_EFAULT; + +    return get_errno(semop(semid, sops, nsops)); +} + +struct target_msqid_ds +{ +    struct target_ipc_perm msg_perm; +    abi_ulong msg_stime; +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused1; +#endif +    abi_ulong msg_rtime; +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused2; +#endif +    abi_ulong msg_ctime; +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused3; +#endif +    abi_ulong __msg_cbytes; +    abi_ulong msg_qnum; +    abi_ulong msg_qbytes; +    abi_ulong msg_lspid; +    abi_ulong msg_lrpid; +    abi_ulong __unused4; +    abi_ulong __unused5; +}; + +static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md, +                                               abi_ulong target_addr) +{ +    struct target_msqid_ds *target_md; + +    if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1)) +        return -TARGET_EFAULT; +    if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr)) +        return -TARGET_EFAULT; +    host_md->msg_stime = tswapal(target_md->msg_stime); +    host_md->msg_rtime = tswapal(target_md->msg_rtime); +    host_md->msg_ctime = tswapal(target_md->msg_ctime); +    host_md->__msg_cbytes = tswapal(target_md->__msg_cbytes); +    host_md->msg_qnum = tswapal(target_md->msg_qnum); +    host_md->msg_qbytes = tswapal(target_md->msg_qbytes); +    host_md->msg_lspid = tswapal(target_md->msg_lspid); +    host_md->msg_lrpid = tswapal(target_md->msg_lrpid); +    unlock_user_struct(target_md, target_addr, 0); +    return 0; +} + +static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr, +                                               struct msqid_ds *host_md) +{ +    struct target_msqid_ds *target_md; + +    if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0)) +        return -TARGET_EFAULT; +    if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm))) +        return -TARGET_EFAULT; +    target_md->msg_stime = tswapal(host_md->msg_stime); +    target_md->msg_rtime = tswapal(host_md->msg_rtime); +    target_md->msg_ctime = tswapal(host_md->msg_ctime); +    target_md->__msg_cbytes = tswapal(host_md->__msg_cbytes); +    target_md->msg_qnum = tswapal(host_md->msg_qnum); +    target_md->msg_qbytes = tswapal(host_md->msg_qbytes); +    target_md->msg_lspid = tswapal(host_md->msg_lspid); +    target_md->msg_lrpid = tswapal(host_md->msg_lrpid); +    unlock_user_struct(target_md, target_addr, 1); +    return 0; +} + +struct target_msginfo { +    int msgpool; +    int msgmap; +    int msgmax; +    int msgmnb; +    int msgmni; +    int msgssz; +    int msgtql; +    unsigned short int msgseg; +}; + +static inline abi_long host_to_target_msginfo(abi_ulong target_addr, +                                              struct msginfo *host_msginfo) +{ +    struct target_msginfo *target_msginfo; +    if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0)) +        return -TARGET_EFAULT; +    __put_user(host_msginfo->msgpool, &target_msginfo->msgpool); +    __put_user(host_msginfo->msgmap, &target_msginfo->msgmap); +    __put_user(host_msginfo->msgmax, &target_msginfo->msgmax); +    __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb); +    __put_user(host_msginfo->msgmni, &target_msginfo->msgmni); +    __put_user(host_msginfo->msgssz, &target_msginfo->msgssz); +    __put_user(host_msginfo->msgtql, &target_msginfo->msgtql); +    __put_user(host_msginfo->msgseg, &target_msginfo->msgseg); +    unlock_user_struct(target_msginfo, target_addr, 1); +    return 0; +} + +static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr) +{ +    struct msqid_ds dsarg; +    struct msginfo msginfo; +    abi_long ret = -TARGET_EINVAL; + +    cmd &= 0xff; + +    switch (cmd) { +    case IPC_STAT: +    case IPC_SET: +    case MSG_STAT: +        if (target_to_host_msqid_ds(&dsarg,ptr)) +            return -TARGET_EFAULT; +        ret = get_errno(msgctl(msgid, cmd, &dsarg)); +        if (host_to_target_msqid_ds(ptr,&dsarg)) +            return -TARGET_EFAULT; +        break; +    case IPC_RMID: +        ret = get_errno(msgctl(msgid, cmd, NULL)); +        break; +    case IPC_INFO: +    case MSG_INFO: +        ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo)); +        if (host_to_target_msginfo(ptr, &msginfo)) +            return -TARGET_EFAULT; +        break; +    } + +    return ret; +} + +struct target_msgbuf { +    abi_long mtype; +    char	mtext[1]; +}; + +static inline abi_long do_msgsnd(int msqid, abi_long msgp, +                                 ssize_t msgsz, int msgflg) +{ +    struct target_msgbuf *target_mb; +    struct msgbuf *host_mb; +    abi_long ret = 0; + +    if (msgsz < 0) { +        return -TARGET_EINVAL; +    } + +    if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0)) +        return -TARGET_EFAULT; +    host_mb = malloc(msgsz+sizeof(long)); +    if (!host_mb) { +        unlock_user_struct(target_mb, msgp, 0); +        return -TARGET_ENOMEM; +    } +    host_mb->mtype = (abi_long) tswapal(target_mb->mtype); +    memcpy(host_mb->mtext, target_mb->mtext, msgsz); +    ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg)); +    free(host_mb); +    unlock_user_struct(target_mb, msgp, 0); + +    return ret; +} + +static inline abi_long do_msgrcv(int msqid, abi_long msgp, +                                 unsigned int msgsz, abi_long msgtyp, +                                 int msgflg) +{ +    struct target_msgbuf *target_mb; +    char *target_mtext; +    struct msgbuf *host_mb; +    abi_long ret = 0; + +    if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0)) +        return -TARGET_EFAULT; + +    host_mb = g_malloc(msgsz+sizeof(long)); +    ret = get_errno(msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg)); + +    if (ret > 0) { +        abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong); +        target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0); +        if (!target_mtext) { +            ret = -TARGET_EFAULT; +            goto end; +        } +        memcpy(target_mb->mtext, host_mb->mtext, ret); +        unlock_user(target_mtext, target_mtext_addr, ret); +    } + +    target_mb->mtype = tswapal(host_mb->mtype); + +end: +    if (target_mb) +        unlock_user_struct(target_mb, msgp, 1); +    g_free(host_mb); +    return ret; +} + +static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd, +                                               abi_ulong target_addr) +{ +    struct target_shmid_ds *target_sd; + +    if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) +        return -TARGET_EFAULT; +    if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr)) +        return -TARGET_EFAULT; +    __get_user(host_sd->shm_segsz, &target_sd->shm_segsz); +    __get_user(host_sd->shm_atime, &target_sd->shm_atime); +    __get_user(host_sd->shm_dtime, &target_sd->shm_dtime); +    __get_user(host_sd->shm_ctime, &target_sd->shm_ctime); +    __get_user(host_sd->shm_cpid, &target_sd->shm_cpid); +    __get_user(host_sd->shm_lpid, &target_sd->shm_lpid); +    __get_user(host_sd->shm_nattch, &target_sd->shm_nattch); +    unlock_user_struct(target_sd, target_addr, 0); +    return 0; +} + +static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr, +                                               struct shmid_ds *host_sd) +{ +    struct target_shmid_ds *target_sd; + +    if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) +        return -TARGET_EFAULT; +    if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm))) +        return -TARGET_EFAULT; +    __put_user(host_sd->shm_segsz, &target_sd->shm_segsz); +    __put_user(host_sd->shm_atime, &target_sd->shm_atime); +    __put_user(host_sd->shm_dtime, &target_sd->shm_dtime); +    __put_user(host_sd->shm_ctime, &target_sd->shm_ctime); +    __put_user(host_sd->shm_cpid, &target_sd->shm_cpid); +    __put_user(host_sd->shm_lpid, &target_sd->shm_lpid); +    __put_user(host_sd->shm_nattch, &target_sd->shm_nattch); +    unlock_user_struct(target_sd, target_addr, 1); +    return 0; +} + +struct  target_shminfo { +    abi_ulong shmmax; +    abi_ulong shmmin; +    abi_ulong shmmni; +    abi_ulong shmseg; +    abi_ulong shmall; +}; + +static inline abi_long host_to_target_shminfo(abi_ulong target_addr, +                                              struct shminfo *host_shminfo) +{ +    struct target_shminfo *target_shminfo; +    if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0)) +        return -TARGET_EFAULT; +    __put_user(host_shminfo->shmmax, &target_shminfo->shmmax); +    __put_user(host_shminfo->shmmin, &target_shminfo->shmmin); +    __put_user(host_shminfo->shmmni, &target_shminfo->shmmni); +    __put_user(host_shminfo->shmseg, &target_shminfo->shmseg); +    __put_user(host_shminfo->shmall, &target_shminfo->shmall); +    unlock_user_struct(target_shminfo, target_addr, 1); +    return 0; +} + +struct target_shm_info { +    int used_ids; +    abi_ulong shm_tot; +    abi_ulong shm_rss; +    abi_ulong shm_swp; +    abi_ulong swap_attempts; +    abi_ulong swap_successes; +}; + +static inline abi_long host_to_target_shm_info(abi_ulong target_addr, +                                               struct shm_info *host_shm_info) +{ +    struct target_shm_info *target_shm_info; +    if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0)) +        return -TARGET_EFAULT; +    __put_user(host_shm_info->used_ids, &target_shm_info->used_ids); +    __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot); +    __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss); +    __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp); +    __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts); +    __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes); +    unlock_user_struct(target_shm_info, target_addr, 1); +    return 0; +} + +static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf) +{ +    struct shmid_ds dsarg; +    struct shminfo shminfo; +    struct shm_info shm_info; +    abi_long ret = -TARGET_EINVAL; + +    cmd &= 0xff; + +    switch(cmd) { +    case IPC_STAT: +    case IPC_SET: +    case SHM_STAT: +        if (target_to_host_shmid_ds(&dsarg, buf)) +            return -TARGET_EFAULT; +        ret = get_errno(shmctl(shmid, cmd, &dsarg)); +        if (host_to_target_shmid_ds(buf, &dsarg)) +            return -TARGET_EFAULT; +        break; +    case IPC_INFO: +        ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo)); +        if (host_to_target_shminfo(buf, &shminfo)) +            return -TARGET_EFAULT; +        break; +    case SHM_INFO: +        ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info)); +        if (host_to_target_shm_info(buf, &shm_info)) +            return -TARGET_EFAULT; +        break; +    case IPC_RMID: +    case SHM_LOCK: +    case SHM_UNLOCK: +        ret = get_errno(shmctl(shmid, cmd, NULL)); +        break; +    } + +    return ret; +} + +static inline abi_ulong do_shmat(int shmid, abi_ulong shmaddr, int shmflg) +{ +    abi_long raddr; +    void *host_raddr; +    struct shmid_ds shm_info; +    int i,ret; + +    /* find out the length of the shared memory segment */ +    ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info)); +    if (is_error(ret)) { +        /* can't get length, bail out */ +        return ret; +    } + +    mmap_lock(); + +    if (shmaddr) +        host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg); +    else { +        abi_ulong mmap_start; + +        mmap_start = mmap_find_vma(0, shm_info.shm_segsz); + +        if (mmap_start == -1) { +            errno = ENOMEM; +            host_raddr = (void *)-1; +        } else +            host_raddr = shmat(shmid, g2h(mmap_start), shmflg | SHM_REMAP); +    } + +    if (host_raddr == (void *)-1) { +        mmap_unlock(); +        return get_errno((long)host_raddr); +    } +    raddr=h2g((unsigned long)host_raddr); + +    page_set_flags(raddr, raddr + shm_info.shm_segsz, +                   PAGE_VALID | PAGE_READ | +                   ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE)); + +    for (i = 0; i < N_SHM_REGIONS; i++) { +        if (shm_regions[i].start == 0) { +            shm_regions[i].start = raddr; +            shm_regions[i].size = shm_info.shm_segsz; +            break; +        } +    } + +    mmap_unlock(); +    return raddr; + +} + +static inline abi_long do_shmdt(abi_ulong shmaddr) +{ +    int i; + +    for (i = 0; i < N_SHM_REGIONS; ++i) { +        if (shm_regions[i].start == shmaddr) { +            shm_regions[i].start = 0; +            page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0); +            break; +        } +    } + +    return get_errno(shmdt(g2h(shmaddr))); +} + +#ifdef TARGET_NR_ipc +/* ??? This only works with linear mappings.  */ +/* do_ipc() must return target values and target errnos. */ +static abi_long do_ipc(unsigned int call, abi_long first, +                       abi_long second, abi_long third, +                       abi_long ptr, abi_long fifth) +{ +    int version; +    abi_long ret = 0; + +    version = call >> 16; +    call &= 0xffff; + +    switch (call) { +    case IPCOP_semop: +        ret = do_semop(first, ptr, second); +        break; + +    case IPCOP_semget: +        ret = get_errno(semget(first, second, third)); +        break; + +    case IPCOP_semctl: { +        /* The semun argument to semctl is passed by value, so dereference the +         * ptr argument. */ +        abi_ulong atptr; +        get_user_ual(atptr, ptr); +        ret = do_semctl(first, second, third, +                (union target_semun) atptr); +        break; +    } + +    case IPCOP_msgget: +        ret = get_errno(msgget(first, second)); +        break; + +    case IPCOP_msgsnd: +        ret = do_msgsnd(first, ptr, second, third); +        break; + +    case IPCOP_msgctl: +        ret = do_msgctl(first, second, ptr); +        break; + +    case IPCOP_msgrcv: +        switch (version) { +        case 0: +            { +                struct target_ipc_kludge { +                    abi_long msgp; +                    abi_long msgtyp; +                } *tmp; + +                if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) { +                    ret = -TARGET_EFAULT; +                    break; +                } + +                ret = do_msgrcv(first, tswapal(tmp->msgp), second, tswapal(tmp->msgtyp), third); + +                unlock_user_struct(tmp, ptr, 0); +                break; +            } +        default: +            ret = do_msgrcv(first, ptr, second, fifth, third); +        } +        break; + +    case IPCOP_shmat: +        switch (version) { +        default: +        { +            abi_ulong raddr; +            raddr = do_shmat(first, ptr, second); +            if (is_error(raddr)) +                return get_errno(raddr); +            if (put_user_ual(raddr, third)) +                return -TARGET_EFAULT; +            break; +        } +        case 1: +            ret = -TARGET_EINVAL; +            break; +        } +	break; +    case IPCOP_shmdt: +        ret = do_shmdt(ptr); +	break; + +    case IPCOP_shmget: +	/* IPC_* flag values are the same on all linux platforms */ +	ret = get_errno(shmget(first, second, third)); +	break; + +	/* IPC_* and SHM_* command values are the same on all linux platforms */ +    case IPCOP_shmctl: +        ret = do_shmctl(first, second, ptr); +        break; +    default: +	gemu_log("Unsupported ipc call: %d (version %d)\n", call, version); +	ret = -TARGET_ENOSYS; +	break; +    } +    return ret; +} +#endif + +/* kernel structure types definitions */ + +#define STRUCT(name, ...) STRUCT_ ## name, +#define STRUCT_SPECIAL(name) STRUCT_ ## name, +enum { +#include "syscall_types.h" +STRUCT_MAX +}; +#undef STRUCT +#undef STRUCT_SPECIAL + +#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = {  __VA_ARGS__, TYPE_NULL }; +#define STRUCT_SPECIAL(name) +#include "syscall_types.h" +#undef STRUCT +#undef STRUCT_SPECIAL + +typedef struct IOCTLEntry IOCTLEntry; + +typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp, +                             int fd, int cmd, abi_long arg); + +struct IOCTLEntry { +    int target_cmd; +    unsigned int host_cmd; +    const char *name; +    int access; +    do_ioctl_fn *do_ioctl; +    const argtype arg_type[5]; +}; + +#define IOC_R 0x0001 +#define IOC_W 0x0002 +#define IOC_RW (IOC_R | IOC_W) + +#define MAX_STRUCT_SIZE 4096 + +#ifdef CONFIG_FIEMAP +/* So fiemap access checks don't overflow on 32 bit systems. + * This is very slightly smaller than the limit imposed by + * the underlying kernel. + */ +#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap))  \ +                            / sizeof(struct fiemap_extent)) + +static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp, +                                       int fd, int cmd, abi_long arg) +{ +    /* The parameter for this ioctl is a struct fiemap followed +     * by an array of struct fiemap_extent whose size is set +     * in fiemap->fm_extent_count. The array is filled in by the +     * ioctl. +     */ +    int target_size_in, target_size_out; +    struct fiemap *fm; +    const argtype *arg_type = ie->arg_type; +    const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) }; +    void *argptr, *p; +    abi_long ret; +    int i, extent_size = thunk_type_size(extent_arg_type, 0); +    uint32_t outbufsz; +    int free_fm = 0; + +    assert(arg_type[0] == TYPE_PTR); +    assert(ie->access == IOC_RW); +    arg_type++; +    target_size_in = thunk_type_size(arg_type, 0); +    argptr = lock_user(VERIFY_READ, arg, target_size_in, 1); +    if (!argptr) { +        return -TARGET_EFAULT; +    } +    thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); +    unlock_user(argptr, arg, 0); +    fm = (struct fiemap *)buf_temp; +    if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) { +        return -TARGET_EINVAL; +    } + +    outbufsz = sizeof (*fm) + +        (sizeof(struct fiemap_extent) * fm->fm_extent_count); + +    if (outbufsz > MAX_STRUCT_SIZE) { +        /* We can't fit all the extents into the fixed size buffer. +         * Allocate one that is large enough and use it instead. +         */ +        fm = malloc(outbufsz); +        if (!fm) { +            return -TARGET_ENOMEM; +        } +        memcpy(fm, buf_temp, sizeof(struct fiemap)); +        free_fm = 1; +    } +    ret = get_errno(ioctl(fd, ie->host_cmd, fm)); +    if (!is_error(ret)) { +        target_size_out = target_size_in; +        /* An extent_count of 0 means we were only counting the extents +         * so there are no structs to copy +         */ +        if (fm->fm_extent_count != 0) { +            target_size_out += fm->fm_mapped_extents * extent_size; +        } +        argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0); +        if (!argptr) { +            ret = -TARGET_EFAULT; +        } else { +            /* Convert the struct fiemap */ +            thunk_convert(argptr, fm, arg_type, THUNK_TARGET); +            if (fm->fm_extent_count != 0) { +                p = argptr + target_size_in; +                /* ...and then all the struct fiemap_extents */ +                for (i = 0; i < fm->fm_mapped_extents; i++) { +                    thunk_convert(p, &fm->fm_extents[i], extent_arg_type, +                                  THUNK_TARGET); +                    p += extent_size; +                } +            } +            unlock_user(argptr, arg, target_size_out); +        } +    } +    if (free_fm) { +        free(fm); +    } +    return ret; +} +#endif + +static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp, +                                int fd, int cmd, abi_long arg) +{ +    const argtype *arg_type = ie->arg_type; +    int target_size; +    void *argptr; +    int ret; +    struct ifconf *host_ifconf; +    uint32_t outbufsz; +    const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) }; +    int target_ifreq_size; +    int nb_ifreq; +    int free_buf = 0; +    int i; +    int target_ifc_len; +    abi_long target_ifc_buf; +    int host_ifc_len; +    char *host_ifc_buf; + +    assert(arg_type[0] == TYPE_PTR); +    assert(ie->access == IOC_RW); + +    arg_type++; +    target_size = thunk_type_size(arg_type, 0); + +    argptr = lock_user(VERIFY_READ, arg, target_size, 1); +    if (!argptr) +        return -TARGET_EFAULT; +    thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); +    unlock_user(argptr, arg, 0); + +    host_ifconf = (struct ifconf *)(unsigned long)buf_temp; +    target_ifc_len = host_ifconf->ifc_len; +    target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf; + +    target_ifreq_size = thunk_type_size(ifreq_arg_type, 0); +    nb_ifreq = target_ifc_len / target_ifreq_size; +    host_ifc_len = nb_ifreq * sizeof(struct ifreq); + +    outbufsz = sizeof(*host_ifconf) + host_ifc_len; +    if (outbufsz > MAX_STRUCT_SIZE) { +        /* We can't fit all the extents into the fixed size buffer. +         * Allocate one that is large enough and use it instead. +         */ +        host_ifconf = malloc(outbufsz); +        if (!host_ifconf) { +            return -TARGET_ENOMEM; +        } +        memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf)); +        free_buf = 1; +    } +    host_ifc_buf = (char*)host_ifconf + sizeof(*host_ifconf); + +    host_ifconf->ifc_len = host_ifc_len; +    host_ifconf->ifc_buf = host_ifc_buf; + +    ret = get_errno(ioctl(fd, ie->host_cmd, host_ifconf)); +    if (!is_error(ret)) { +	/* convert host ifc_len to target ifc_len */ + +        nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq); +        target_ifc_len = nb_ifreq * target_ifreq_size; +        host_ifconf->ifc_len = target_ifc_len; + +	/* restore target ifc_buf */ + +        host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf; + +	/* copy struct ifconf to target user */ + +        argptr = lock_user(VERIFY_WRITE, arg, target_size, 0); +        if (!argptr) +            return -TARGET_EFAULT; +        thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET); +        unlock_user(argptr, arg, target_size); + +	/* copy ifreq[] to target user */ + +        argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0); +        for (i = 0; i < nb_ifreq ; i++) { +            thunk_convert(argptr + i * target_ifreq_size, +                          host_ifc_buf + i * sizeof(struct ifreq), +                          ifreq_arg_type, THUNK_TARGET); +        } +        unlock_user(argptr, target_ifc_buf, target_ifc_len); +    } + +    if (free_buf) { +        free(host_ifconf); +    } + +    return ret; +} + +static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd, +                            int cmd, abi_long arg) +{ +    void *argptr; +    struct dm_ioctl *host_dm; +    abi_long guest_data; +    uint32_t guest_data_size; +    int target_size; +    const argtype *arg_type = ie->arg_type; +    abi_long ret; +    void *big_buf = NULL; +    char *host_data; + +    arg_type++; +    target_size = thunk_type_size(arg_type, 0); +    argptr = lock_user(VERIFY_READ, arg, target_size, 1); +    if (!argptr) { +        ret = -TARGET_EFAULT; +        goto out; +    } +    thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); +    unlock_user(argptr, arg, 0); + +    /* buf_temp is too small, so fetch things into a bigger buffer */ +    big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2); +    memcpy(big_buf, buf_temp, target_size); +    buf_temp = big_buf; +    host_dm = big_buf; + +    guest_data = arg + host_dm->data_start; +    if ((guest_data - arg) < 0) { +        ret = -EINVAL; +        goto out; +    } +    guest_data_size = host_dm->data_size - host_dm->data_start; +    host_data = (char*)host_dm + host_dm->data_start; + +    argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1); +    switch (ie->host_cmd) { +    case DM_REMOVE_ALL: +    case DM_LIST_DEVICES: +    case DM_DEV_CREATE: +    case DM_DEV_REMOVE: +    case DM_DEV_SUSPEND: +    case DM_DEV_STATUS: +    case DM_DEV_WAIT: +    case DM_TABLE_STATUS: +    case DM_TABLE_CLEAR: +    case DM_TABLE_DEPS: +    case DM_LIST_VERSIONS: +        /* no input data */ +        break; +    case DM_DEV_RENAME: +    case DM_DEV_SET_GEOMETRY: +        /* data contains only strings */ +        memcpy(host_data, argptr, guest_data_size); +        break; +    case DM_TARGET_MSG: +        memcpy(host_data, argptr, guest_data_size); +        *(uint64_t*)host_data = tswap64(*(uint64_t*)argptr); +        break; +    case DM_TABLE_LOAD: +    { +        void *gspec = argptr; +        void *cur_data = host_data; +        const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) }; +        int spec_size = thunk_type_size(arg_type, 0); +        int i; + +        for (i = 0; i < host_dm->target_count; i++) { +            struct dm_target_spec *spec = cur_data; +            uint32_t next; +            int slen; + +            thunk_convert(spec, gspec, arg_type, THUNK_HOST); +            slen = strlen((char*)gspec + spec_size) + 1; +            next = spec->next; +            spec->next = sizeof(*spec) + slen; +            strcpy((char*)&spec[1], gspec + spec_size); +            gspec += next; +            cur_data += spec->next; +        } +        break; +    } +    default: +        ret = -TARGET_EINVAL; +        unlock_user(argptr, guest_data, 0); +        goto out; +    } +    unlock_user(argptr, guest_data, 0); + +    ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); +    if (!is_error(ret)) { +        guest_data = arg + host_dm->data_start; +        guest_data_size = host_dm->data_size - host_dm->data_start; +        argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0); +        switch (ie->host_cmd) { +        case DM_REMOVE_ALL: +        case DM_DEV_CREATE: +        case DM_DEV_REMOVE: +        case DM_DEV_RENAME: +        case DM_DEV_SUSPEND: +        case DM_DEV_STATUS: +        case DM_TABLE_LOAD: +        case DM_TABLE_CLEAR: +        case DM_TARGET_MSG: +        case DM_DEV_SET_GEOMETRY: +            /* no return data */ +            break; +        case DM_LIST_DEVICES: +        { +            struct dm_name_list *nl = (void*)host_dm + host_dm->data_start; +            uint32_t remaining_data = guest_data_size; +            void *cur_data = argptr; +            const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) }; +            int nl_size = 12; /* can't use thunk_size due to alignment */ + +            while (1) { +                uint32_t next = nl->next; +                if (next) { +                    nl->next = nl_size + (strlen(nl->name) + 1); +                } +                if (remaining_data < nl->next) { +                    host_dm->flags |= DM_BUFFER_FULL_FLAG; +                    break; +                } +                thunk_convert(cur_data, nl, arg_type, THUNK_TARGET); +                strcpy(cur_data + nl_size, nl->name); +                cur_data += nl->next; +                remaining_data -= nl->next; +                if (!next) { +                    break; +                } +                nl = (void*)nl + next; +            } +            break; +        } +        case DM_DEV_WAIT: +        case DM_TABLE_STATUS: +        { +            struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start; +            void *cur_data = argptr; +            const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) }; +            int spec_size = thunk_type_size(arg_type, 0); +            int i; + +            for (i = 0; i < host_dm->target_count; i++) { +                uint32_t next = spec->next; +                int slen = strlen((char*)&spec[1]) + 1; +                spec->next = (cur_data - argptr) + spec_size + slen; +                if (guest_data_size < spec->next) { +                    host_dm->flags |= DM_BUFFER_FULL_FLAG; +                    break; +                } +                thunk_convert(cur_data, spec, arg_type, THUNK_TARGET); +                strcpy(cur_data + spec_size, (char*)&spec[1]); +                cur_data = argptr + spec->next; +                spec = (void*)host_dm + host_dm->data_start + next; +            } +            break; +        } +        case DM_TABLE_DEPS: +        { +            void *hdata = (void*)host_dm + host_dm->data_start; +            int count = *(uint32_t*)hdata; +            uint64_t *hdev = hdata + 8; +            uint64_t *gdev = argptr + 8; +            int i; + +            *(uint32_t*)argptr = tswap32(count); +            for (i = 0; i < count; i++) { +                *gdev = tswap64(*hdev); +                gdev++; +                hdev++; +            } +            break; +        } +        case DM_LIST_VERSIONS: +        { +            struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start; +            uint32_t remaining_data = guest_data_size; +            void *cur_data = argptr; +            const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) }; +            int vers_size = thunk_type_size(arg_type, 0); + +            while (1) { +                uint32_t next = vers->next; +                if (next) { +                    vers->next = vers_size + (strlen(vers->name) + 1); +                } +                if (remaining_data < vers->next) { +                    host_dm->flags |= DM_BUFFER_FULL_FLAG; +                    break; +                } +                thunk_convert(cur_data, vers, arg_type, THUNK_TARGET); +                strcpy(cur_data + vers_size, vers->name); +                cur_data += vers->next; +                remaining_data -= vers->next; +                if (!next) { +                    break; +                } +                vers = (void*)vers + next; +            } +            break; +        } +        default: +            unlock_user(argptr, guest_data, 0); +            ret = -TARGET_EINVAL; +            goto out; +        } +        unlock_user(argptr, guest_data, guest_data_size); + +        argptr = lock_user(VERIFY_WRITE, arg, target_size, 0); +        if (!argptr) { +            ret = -TARGET_EFAULT; +            goto out; +        } +        thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); +        unlock_user(argptr, arg, target_size); +    } +out: +    g_free(big_buf); +    return ret; +} + +static abi_long do_ioctl_blkpg(const IOCTLEntry *ie, uint8_t *buf_temp, int fd, +                               int cmd, abi_long arg) +{ +    void *argptr; +    int target_size; +    const argtype *arg_type = ie->arg_type; +    const argtype part_arg_type[] = { MK_STRUCT(STRUCT_blkpg_partition) }; +    abi_long ret; + +    struct blkpg_ioctl_arg *host_blkpg = (void*)buf_temp; +    struct blkpg_partition host_part; + +    /* Read and convert blkpg */ +    arg_type++; +    target_size = thunk_type_size(arg_type, 0); +    argptr = lock_user(VERIFY_READ, arg, target_size, 1); +    if (!argptr) { +        ret = -TARGET_EFAULT; +        goto out; +    } +    thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); +    unlock_user(argptr, arg, 0); + +    switch (host_blkpg->op) { +    case BLKPG_ADD_PARTITION: +    case BLKPG_DEL_PARTITION: +        /* payload is struct blkpg_partition */ +        break; +    default: +        /* Unknown opcode */ +        ret = -TARGET_EINVAL; +        goto out; +    } + +    /* Read and convert blkpg->data */ +    arg = (abi_long)(uintptr_t)host_blkpg->data; +    target_size = thunk_type_size(part_arg_type, 0); +    argptr = lock_user(VERIFY_READ, arg, target_size, 1); +    if (!argptr) { +        ret = -TARGET_EFAULT; +        goto out; +    } +    thunk_convert(&host_part, argptr, part_arg_type, THUNK_HOST); +    unlock_user(argptr, arg, 0); + +    /* Swizzle the data pointer to our local copy and call! */ +    host_blkpg->data = &host_part; +    ret = get_errno(ioctl(fd, ie->host_cmd, host_blkpg)); + +out: +    return ret; +} + +static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp, +                                int fd, int cmd, abi_long arg) +{ +    const argtype *arg_type = ie->arg_type; +    const StructEntry *se; +    const argtype *field_types; +    const int *dst_offsets, *src_offsets; +    int target_size; +    void *argptr; +    abi_ulong *target_rt_dev_ptr; +    unsigned long *host_rt_dev_ptr; +    abi_long ret; +    int i; + +    assert(ie->access == IOC_W); +    assert(*arg_type == TYPE_PTR); +    arg_type++; +    assert(*arg_type == TYPE_STRUCT); +    target_size = thunk_type_size(arg_type, 0); +    argptr = lock_user(VERIFY_READ, arg, target_size, 1); +    if (!argptr) { +        return -TARGET_EFAULT; +    } +    arg_type++; +    assert(*arg_type == (int)STRUCT_rtentry); +    se = struct_entries + *arg_type++; +    assert(se->convert[0] == NULL); +    /* convert struct here to be able to catch rt_dev string */ +    field_types = se->field_types; +    dst_offsets = se->field_offsets[THUNK_HOST]; +    src_offsets = se->field_offsets[THUNK_TARGET]; +    for (i = 0; i < se->nb_fields; i++) { +        if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) { +            assert(*field_types == TYPE_PTRVOID); +            target_rt_dev_ptr = (abi_ulong *)(argptr + src_offsets[i]); +            host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]); +            if (*target_rt_dev_ptr != 0) { +                *host_rt_dev_ptr = (unsigned long)lock_user_string( +                                                  tswapal(*target_rt_dev_ptr)); +                if (!*host_rt_dev_ptr) { +                    unlock_user(argptr, arg, 0); +                    return -TARGET_EFAULT; +                } +            } else { +                *host_rt_dev_ptr = 0; +            } +            field_types++; +            continue; +        } +        field_types = thunk_convert(buf_temp + dst_offsets[i], +                                    argptr + src_offsets[i], +                                    field_types, THUNK_HOST); +    } +    unlock_user(argptr, arg, 0); + +    ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); +    if (*host_rt_dev_ptr != 0) { +        unlock_user((void *)*host_rt_dev_ptr, +                    *target_rt_dev_ptr, 0); +    } +    return ret; +} + +static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp, +                                     int fd, int cmd, abi_long arg) +{ +    int sig = target_to_host_signal(arg); +    return get_errno(ioctl(fd, ie->host_cmd, sig)); +} + +static IOCTLEntry ioctl_entries[] = { +#define IOCTL(cmd, access, ...) \ +    { TARGET_ ## cmd, cmd, #cmd, access, 0, {  __VA_ARGS__ } }, +#define IOCTL_SPECIAL(cmd, access, dofn, ...)                      \ +    { TARGET_ ## cmd, cmd, #cmd, access, dofn, {  __VA_ARGS__ } }, +#include "ioctls.h" +    { 0, 0, }, +}; + +/* ??? Implement proper locking for ioctls.  */ +/* do_ioctl() Must return target values and target errnos. */ +static abi_long do_ioctl(int fd, int cmd, abi_long arg) +{ +    const IOCTLEntry *ie; +    const argtype *arg_type; +    abi_long ret; +    uint8_t buf_temp[MAX_STRUCT_SIZE]; +    int target_size; +    void *argptr; + +    ie = ioctl_entries; +    for(;;) { +        if (ie->target_cmd == 0) { +            gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd); +            return -TARGET_ENOSYS; +        } +        if (ie->target_cmd == cmd) +            break; +        ie++; +    } +    arg_type = ie->arg_type; +#if defined(DEBUG) +    gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name); +#endif +    if (ie->do_ioctl) { +        return ie->do_ioctl(ie, buf_temp, fd, cmd, arg); +    } + +    switch(arg_type[0]) { +    case TYPE_NULL: +        /* no argument */ +        ret = get_errno(ioctl(fd, ie->host_cmd)); +        break; +    case TYPE_PTRVOID: +    case TYPE_INT: +        /* int argment */ +        ret = get_errno(ioctl(fd, ie->host_cmd, arg)); +        break; +    case TYPE_PTR: +        arg_type++; +        target_size = thunk_type_size(arg_type, 0); +        switch(ie->access) { +        case IOC_R: +            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); +            if (!is_error(ret)) { +                argptr = lock_user(VERIFY_WRITE, arg, target_size, 0); +                if (!argptr) +                    return -TARGET_EFAULT; +                thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); +                unlock_user(argptr, arg, target_size); +            } +            break; +        case IOC_W: +            argptr = lock_user(VERIFY_READ, arg, target_size, 1); +            if (!argptr) +                return -TARGET_EFAULT; +            thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); +            unlock_user(argptr, arg, 0); +            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); +            break; +        default: +        case IOC_RW: +            argptr = lock_user(VERIFY_READ, arg, target_size, 1); +            if (!argptr) +                return -TARGET_EFAULT; +            thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); +            unlock_user(argptr, arg, 0); +            ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); +            if (!is_error(ret)) { +                argptr = lock_user(VERIFY_WRITE, arg, target_size, 0); +                if (!argptr) +                    return -TARGET_EFAULT; +                thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); +                unlock_user(argptr, arg, target_size); +            } +            break; +        } +        break; +    default: +        gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n", +                 (long)cmd, arg_type[0]); +        ret = -TARGET_ENOSYS; +        break; +    } +    return ret; +} + +static const bitmask_transtbl iflag_tbl[] = { +        { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK }, +        { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT }, +        { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR }, +        { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK }, +        { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK }, +        { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP }, +        { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR }, +        { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR }, +        { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL }, +        { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC }, +        { TARGET_IXON, TARGET_IXON, IXON, IXON }, +        { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY }, +        { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF }, +        { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL }, +        { 0, 0, 0, 0 } +}; + +static const bitmask_transtbl oflag_tbl[] = { +	{ TARGET_OPOST, TARGET_OPOST, OPOST, OPOST }, +	{ TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC }, +	{ TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR }, +	{ TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL }, +	{ TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR }, +	{ TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET }, +	{ TARGET_OFILL, TARGET_OFILL, OFILL, OFILL }, +	{ TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL }, +	{ TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 }, +	{ TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 }, +	{ TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 }, +	{ TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 }, +	{ TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 }, +	{ TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 }, +	{ TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 }, +	{ TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 }, +	{ TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 }, +	{ TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 }, +	{ TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 }, +	{ TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 }, +	{ TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 }, +	{ TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 }, +	{ TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 }, +	{ TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 }, +	{ 0, 0, 0, 0 } +}; + +static const bitmask_transtbl cflag_tbl[] = { +	{ TARGET_CBAUD, TARGET_B0, CBAUD, B0 }, +	{ TARGET_CBAUD, TARGET_B50, CBAUD, B50 }, +	{ TARGET_CBAUD, TARGET_B75, CBAUD, B75 }, +	{ TARGET_CBAUD, TARGET_B110, CBAUD, B110 }, +	{ TARGET_CBAUD, TARGET_B134, CBAUD, B134 }, +	{ TARGET_CBAUD, TARGET_B150, CBAUD, B150 }, +	{ TARGET_CBAUD, TARGET_B200, CBAUD, B200 }, +	{ TARGET_CBAUD, TARGET_B300, CBAUD, B300 }, +	{ TARGET_CBAUD, TARGET_B600, CBAUD, B600 }, +	{ TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 }, +	{ TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 }, +	{ TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 }, +	{ TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 }, +	{ TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 }, +	{ TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 }, +	{ TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 }, +	{ TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 }, +	{ TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 }, +	{ TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 }, +	{ TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 }, +	{ TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 }, +	{ TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 }, +	{ TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 }, +	{ TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 }, +	{ TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB }, +	{ TARGET_CREAD, TARGET_CREAD, CREAD, CREAD }, +	{ TARGET_PARENB, TARGET_PARENB, PARENB, PARENB }, +	{ TARGET_PARODD, TARGET_PARODD, PARODD, PARODD }, +	{ TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL }, +	{ TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL }, +	{ TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS }, +	{ 0, 0, 0, 0 } +}; + +static const bitmask_transtbl lflag_tbl[] = { +	{ TARGET_ISIG, TARGET_ISIG, ISIG, ISIG }, +	{ TARGET_ICANON, TARGET_ICANON, ICANON, ICANON }, +	{ TARGET_XCASE, TARGET_XCASE, XCASE, XCASE }, +	{ TARGET_ECHO, TARGET_ECHO, ECHO, ECHO }, +	{ TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE }, +	{ TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK }, +	{ TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL }, +	{ TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH }, +	{ TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP }, +	{ TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL }, +	{ TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT }, +	{ TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE }, +	{ TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO }, +	{ TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN }, +	{ TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN }, +	{ 0, 0, 0, 0 } +}; + +static void target_to_host_termios (void *dst, const void *src) +{ +    struct host_termios *host = dst; +    const struct target_termios *target = src; + +    host->c_iflag = +        target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl); +    host->c_oflag = +        target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl); +    host->c_cflag = +        target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl); +    host->c_lflag = +        target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl); +    host->c_line = target->c_line; + +    memset(host->c_cc, 0, sizeof(host->c_cc)); +    host->c_cc[VINTR] = target->c_cc[TARGET_VINTR]; +    host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT]; +    host->c_cc[VERASE] = target->c_cc[TARGET_VERASE]; +    host->c_cc[VKILL] = target->c_cc[TARGET_VKILL]; +    host->c_cc[VEOF] = target->c_cc[TARGET_VEOF]; +    host->c_cc[VTIME] = target->c_cc[TARGET_VTIME]; +    host->c_cc[VMIN] = target->c_cc[TARGET_VMIN]; +    host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC]; +    host->c_cc[VSTART] = target->c_cc[TARGET_VSTART]; +    host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP]; +    host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP]; +    host->c_cc[VEOL] = target->c_cc[TARGET_VEOL]; +    host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT]; +    host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD]; +    host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE]; +    host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT]; +    host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2]; +} + +static void host_to_target_termios (void *dst, const void *src) +{ +    struct target_termios *target = dst; +    const struct host_termios *host = src; + +    target->c_iflag = +        tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl)); +    target->c_oflag = +        tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl)); +    target->c_cflag = +        tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl)); +    target->c_lflag = +        tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl)); +    target->c_line = host->c_line; + +    memset(target->c_cc, 0, sizeof(target->c_cc)); +    target->c_cc[TARGET_VINTR] = host->c_cc[VINTR]; +    target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT]; +    target->c_cc[TARGET_VERASE] = host->c_cc[VERASE]; +    target->c_cc[TARGET_VKILL] = host->c_cc[VKILL]; +    target->c_cc[TARGET_VEOF] = host->c_cc[VEOF]; +    target->c_cc[TARGET_VTIME] = host->c_cc[VTIME]; +    target->c_cc[TARGET_VMIN] = host->c_cc[VMIN]; +    target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC]; +    target->c_cc[TARGET_VSTART] = host->c_cc[VSTART]; +    target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP]; +    target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP]; +    target->c_cc[TARGET_VEOL] = host->c_cc[VEOL]; +    target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT]; +    target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD]; +    target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE]; +    target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT]; +    target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2]; +} + +static const StructEntry struct_termios_def = { +    .convert = { host_to_target_termios, target_to_host_termios }, +    .size = { sizeof(struct target_termios), sizeof(struct host_termios) }, +    .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) }, +}; + +static bitmask_transtbl mmap_flags_tbl[] = { +	{ TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED }, +	{ TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE }, +	{ TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED }, +	{ TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS }, +	{ TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN }, +	{ TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE }, +	{ TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE }, +	{ TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED }, +        { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE, MAP_NORESERVE, +          MAP_NORESERVE }, +	{ 0, 0, 0, 0 } +}; + +#if defined(TARGET_I386) + +/* NOTE: there is really one LDT for all the threads */ +static uint8_t *ldt_table; + +static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount) +{ +    int size; +    void *p; + +    if (!ldt_table) +        return 0; +    size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE; +    if (size > bytecount) +        size = bytecount; +    p = lock_user(VERIFY_WRITE, ptr, size, 0); +    if (!p) +        return -TARGET_EFAULT; +    /* ??? Should this by byteswapped?  */ +    memcpy(p, ldt_table, size); +    unlock_user(p, ptr, size); +    return size; +} + +/* XXX: add locking support */ +static abi_long write_ldt(CPUX86State *env, +                          abi_ulong ptr, unsigned long bytecount, int oldmode) +{ +    struct target_modify_ldt_ldt_s ldt_info; +    struct target_modify_ldt_ldt_s *target_ldt_info; +    int seg_32bit, contents, read_exec_only, limit_in_pages; +    int seg_not_present, useable, lm; +    uint32_t *lp, entry_1, entry_2; + +    if (bytecount != sizeof(ldt_info)) +        return -TARGET_EINVAL; +    if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1)) +        return -TARGET_EFAULT; +    ldt_info.entry_number = tswap32(target_ldt_info->entry_number); +    ldt_info.base_addr = tswapal(target_ldt_info->base_addr); +    ldt_info.limit = tswap32(target_ldt_info->limit); +    ldt_info.flags = tswap32(target_ldt_info->flags); +    unlock_user_struct(target_ldt_info, ptr, 0); + +    if (ldt_info.entry_number >= TARGET_LDT_ENTRIES) +        return -TARGET_EINVAL; +    seg_32bit = ldt_info.flags & 1; +    contents = (ldt_info.flags >> 1) & 3; +    read_exec_only = (ldt_info.flags >> 3) & 1; +    limit_in_pages = (ldt_info.flags >> 4) & 1; +    seg_not_present = (ldt_info.flags >> 5) & 1; +    useable = (ldt_info.flags >> 6) & 1; +#ifdef TARGET_ABI32 +    lm = 0; +#else +    lm = (ldt_info.flags >> 7) & 1; +#endif +    if (contents == 3) { +        if (oldmode) +            return -TARGET_EINVAL; +        if (seg_not_present == 0) +            return -TARGET_EINVAL; +    } +    /* allocate the LDT */ +    if (!ldt_table) { +        env->ldt.base = target_mmap(0, +                                    TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE, +                                    PROT_READ|PROT_WRITE, +                                    MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); +        if (env->ldt.base == -1) +            return -TARGET_ENOMEM; +        memset(g2h(env->ldt.base), 0, +               TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE); +        env->ldt.limit = 0xffff; +        ldt_table = g2h(env->ldt.base); +    } + +    /* NOTE: same code as Linux kernel */ +    /* Allow LDTs to be cleared by the user. */ +    if (ldt_info.base_addr == 0 && ldt_info.limit == 0) { +        if (oldmode || +            (contents == 0		&& +             read_exec_only == 1	&& +             seg_32bit == 0		&& +             limit_in_pages == 0	&& +             seg_not_present == 1	&& +             useable == 0 )) { +            entry_1 = 0; +            entry_2 = 0; +            goto install; +        } +    } + +    entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) | +        (ldt_info.limit & 0x0ffff); +    entry_2 = (ldt_info.base_addr & 0xff000000) | +        ((ldt_info.base_addr & 0x00ff0000) >> 16) | +        (ldt_info.limit & 0xf0000) | +        ((read_exec_only ^ 1) << 9) | +        (contents << 10) | +        ((seg_not_present ^ 1) << 15) | +        (seg_32bit << 22) | +        (limit_in_pages << 23) | +        (lm << 21) | +        0x7000; +    if (!oldmode) +        entry_2 |= (useable << 20); + +    /* Install the new entry ...  */ +install: +    lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3)); +    lp[0] = tswap32(entry_1); +    lp[1] = tswap32(entry_2); +    return 0; +} + +/* specific and weird i386 syscalls */ +static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr, +                              unsigned long bytecount) +{ +    abi_long ret; + +    switch (func) { +    case 0: +        ret = read_ldt(ptr, bytecount); +        break; +    case 1: +        ret = write_ldt(env, ptr, bytecount, 1); +        break; +    case 0x11: +        ret = write_ldt(env, ptr, bytecount, 0); +        break; +    default: +        ret = -TARGET_ENOSYS; +        break; +    } +    return ret; +} + +#if defined(TARGET_I386) && defined(TARGET_ABI32) +abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr) +{ +    uint64_t *gdt_table = g2h(env->gdt.base); +    struct target_modify_ldt_ldt_s ldt_info; +    struct target_modify_ldt_ldt_s *target_ldt_info; +    int seg_32bit, contents, read_exec_only, limit_in_pages; +    int seg_not_present, useable, lm; +    uint32_t *lp, entry_1, entry_2; +    int i; + +    lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1); +    if (!target_ldt_info) +        return -TARGET_EFAULT; +    ldt_info.entry_number = tswap32(target_ldt_info->entry_number); +    ldt_info.base_addr = tswapal(target_ldt_info->base_addr); +    ldt_info.limit = tswap32(target_ldt_info->limit); +    ldt_info.flags = tswap32(target_ldt_info->flags); +    if (ldt_info.entry_number == -1) { +        for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) { +            if (gdt_table[i] == 0) { +                ldt_info.entry_number = i; +                target_ldt_info->entry_number = tswap32(i); +                break; +            } +        } +    } +    unlock_user_struct(target_ldt_info, ptr, 1); + +    if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||  +        ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX) +           return -TARGET_EINVAL; +    seg_32bit = ldt_info.flags & 1; +    contents = (ldt_info.flags >> 1) & 3; +    read_exec_only = (ldt_info.flags >> 3) & 1; +    limit_in_pages = (ldt_info.flags >> 4) & 1; +    seg_not_present = (ldt_info.flags >> 5) & 1; +    useable = (ldt_info.flags >> 6) & 1; +#ifdef TARGET_ABI32 +    lm = 0; +#else +    lm = (ldt_info.flags >> 7) & 1; +#endif + +    if (contents == 3) { +        if (seg_not_present == 0) +            return -TARGET_EINVAL; +    } + +    /* NOTE: same code as Linux kernel */ +    /* Allow LDTs to be cleared by the user. */ +    if (ldt_info.base_addr == 0 && ldt_info.limit == 0) { +        if ((contents == 0             && +             read_exec_only == 1       && +             seg_32bit == 0            && +             limit_in_pages == 0       && +             seg_not_present == 1      && +             useable == 0 )) { +            entry_1 = 0; +            entry_2 = 0; +            goto install; +        } +    } + +    entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) | +        (ldt_info.limit & 0x0ffff); +    entry_2 = (ldt_info.base_addr & 0xff000000) | +        ((ldt_info.base_addr & 0x00ff0000) >> 16) | +        (ldt_info.limit & 0xf0000) | +        ((read_exec_only ^ 1) << 9) | +        (contents << 10) | +        ((seg_not_present ^ 1) << 15) | +        (seg_32bit << 22) | +        (limit_in_pages << 23) | +        (useable << 20) | +        (lm << 21) | +        0x7000; + +    /* Install the new entry ...  */ +install: +    lp = (uint32_t *)(gdt_table + ldt_info.entry_number); +    lp[0] = tswap32(entry_1); +    lp[1] = tswap32(entry_2); +    return 0; +} + +static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr) +{ +    struct target_modify_ldt_ldt_s *target_ldt_info; +    uint64_t *gdt_table = g2h(env->gdt.base); +    uint32_t base_addr, limit, flags; +    int seg_32bit, contents, read_exec_only, limit_in_pages, idx; +    int seg_not_present, useable, lm; +    uint32_t *lp, entry_1, entry_2; + +    lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1); +    if (!target_ldt_info) +        return -TARGET_EFAULT; +    idx = tswap32(target_ldt_info->entry_number); +    if (idx < TARGET_GDT_ENTRY_TLS_MIN || +        idx > TARGET_GDT_ENTRY_TLS_MAX) { +        unlock_user_struct(target_ldt_info, ptr, 1); +        return -TARGET_EINVAL; +    } +    lp = (uint32_t *)(gdt_table + idx); +    entry_1 = tswap32(lp[0]); +    entry_2 = tswap32(lp[1]); +     +    read_exec_only = ((entry_2 >> 9) & 1) ^ 1; +    contents = (entry_2 >> 10) & 3; +    seg_not_present = ((entry_2 >> 15) & 1) ^ 1; +    seg_32bit = (entry_2 >> 22) & 1; +    limit_in_pages = (entry_2 >> 23) & 1; +    useable = (entry_2 >> 20) & 1; +#ifdef TARGET_ABI32 +    lm = 0; +#else +    lm = (entry_2 >> 21) & 1; +#endif +    flags = (seg_32bit << 0) | (contents << 1) | +        (read_exec_only << 3) | (limit_in_pages << 4) | +        (seg_not_present << 5) | (useable << 6) | (lm << 7); +    limit = (entry_1 & 0xffff) | (entry_2  & 0xf0000); +    base_addr = (entry_1 >> 16) |  +        (entry_2 & 0xff000000) |  +        ((entry_2 & 0xff) << 16); +    target_ldt_info->base_addr = tswapal(base_addr); +    target_ldt_info->limit = tswap32(limit); +    target_ldt_info->flags = tswap32(flags); +    unlock_user_struct(target_ldt_info, ptr, 1); +    return 0; +} +#endif /* TARGET_I386 && TARGET_ABI32 */ + +#ifndef TARGET_ABI32 +abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr) +{ +    abi_long ret = 0; +    abi_ulong val; +    int idx; + +    switch(code) { +    case TARGET_ARCH_SET_GS: +    case TARGET_ARCH_SET_FS: +        if (code == TARGET_ARCH_SET_GS) +            idx = R_GS; +        else +            idx = R_FS; +        cpu_x86_load_seg(env, idx, 0); +        env->segs[idx].base = addr; +        break; +    case TARGET_ARCH_GET_GS: +    case TARGET_ARCH_GET_FS: +        if (code == TARGET_ARCH_GET_GS) +            idx = R_GS; +        else +            idx = R_FS; +        val = env->segs[idx].base; +        if (put_user(val, addr, abi_ulong)) +            ret = -TARGET_EFAULT; +        break; +    default: +        ret = -TARGET_EINVAL; +        break; +    } +    return ret; +} +#endif + +#endif /* defined(TARGET_I386) */ + +#define NEW_STACK_SIZE 0x40000 + + +static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER; +typedef struct { +    CPUArchState *env; +    pthread_mutex_t mutex; +    pthread_cond_t cond; +    pthread_t thread; +    uint32_t tid; +    abi_ulong child_tidptr; +    abi_ulong parent_tidptr; +    sigset_t sigmask; +} new_thread_info; + +static void *clone_func(void *arg) +{ +    new_thread_info *info = arg; +    CPUArchState *env; +    CPUState *cpu; +    TaskState *ts; + +    env = info->env; +    cpu = ENV_GET_CPU(env); +    thread_cpu = cpu; +    ts = (TaskState *)cpu->opaque; +    info->tid = gettid(); +    cpu->host_tid = info->tid; +    task_settid(ts); +    if (info->child_tidptr) +        put_user_u32(info->tid, info->child_tidptr); +    if (info->parent_tidptr) +        put_user_u32(info->tid, info->parent_tidptr); +    /* Enable signals.  */ +    sigprocmask(SIG_SETMASK, &info->sigmask, NULL); +    /* Signal to the parent that we're ready.  */ +    pthread_mutex_lock(&info->mutex); +    pthread_cond_broadcast(&info->cond); +    pthread_mutex_unlock(&info->mutex); +    /* Wait until the parent has finshed initializing the tls state.  */ +    pthread_mutex_lock(&clone_lock); +    pthread_mutex_unlock(&clone_lock); +    cpu_loop(env); +    /* never exits */ +    return NULL; +} + +/* do_fork() Must return host values and target errnos (unlike most +   do_*() functions). */ +static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp, +                   abi_ulong parent_tidptr, target_ulong newtls, +                   abi_ulong child_tidptr) +{ +    CPUState *cpu = ENV_GET_CPU(env); +    int ret; +    TaskState *ts; +    CPUState *new_cpu; +    CPUArchState *new_env; +    unsigned int nptl_flags; +    sigset_t sigmask; + +    /* Emulate vfork() with fork() */ +    if (flags & CLONE_VFORK) +        flags &= ~(CLONE_VFORK | CLONE_VM); + +    if (flags & CLONE_VM) { +        TaskState *parent_ts = (TaskState *)cpu->opaque; +        new_thread_info info; +        pthread_attr_t attr; + +        ts = g_malloc0(sizeof(TaskState)); +        init_task_state(ts); +        /* we create a new CPU instance. */ +        new_env = cpu_copy(env); +        /* Init regs that differ from the parent.  */ +        cpu_clone_regs(new_env, newsp); +        new_cpu = ENV_GET_CPU(new_env); +        new_cpu->opaque = ts; +        ts->bprm = parent_ts->bprm; +        ts->info = parent_ts->info; +        nptl_flags = flags; +        flags &= ~CLONE_NPTL_FLAGS2; + +        if (nptl_flags & CLONE_CHILD_CLEARTID) { +            ts->child_tidptr = child_tidptr; +        } + +        if (nptl_flags & CLONE_SETTLS) +            cpu_set_tls (new_env, newtls); + +        /* Grab a mutex so that thread setup appears atomic.  */ +        pthread_mutex_lock(&clone_lock); + +        memset(&info, 0, sizeof(info)); +        pthread_mutex_init(&info.mutex, NULL); +        pthread_mutex_lock(&info.mutex); +        pthread_cond_init(&info.cond, NULL); +        info.env = new_env; +        if (nptl_flags & CLONE_CHILD_SETTID) +            info.child_tidptr = child_tidptr; +        if (nptl_flags & CLONE_PARENT_SETTID) +            info.parent_tidptr = parent_tidptr; + +        ret = pthread_attr_init(&attr); +        ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE); +        ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); +        /* It is not safe to deliver signals until the child has finished +           initializing, so temporarily block all signals.  */ +        sigfillset(&sigmask); +        sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask); + +        ret = pthread_create(&info.thread, &attr, clone_func, &info); +        /* TODO: Free new CPU state if thread creation failed.  */ + +        sigprocmask(SIG_SETMASK, &info.sigmask, NULL); +        pthread_attr_destroy(&attr); +        if (ret == 0) { +            /* Wait for the child to initialize.  */ +            pthread_cond_wait(&info.cond, &info.mutex); +            ret = info.tid; +            if (flags & CLONE_PARENT_SETTID) +                put_user_u32(ret, parent_tidptr); +        } else { +            ret = -1; +        } +        pthread_mutex_unlock(&info.mutex); +        pthread_cond_destroy(&info.cond); +        pthread_mutex_destroy(&info.mutex); +        pthread_mutex_unlock(&clone_lock); +    } else { +        /* if no CLONE_VM, we consider it is a fork */ +        if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0) +            return -EINVAL; +        fork_start(); +        ret = fork(); +        if (ret == 0) { +            /* Child Process.  */ +            rcu_after_fork(); +            cpu_clone_regs(env, newsp); +            fork_end(1); +            /* There is a race condition here.  The parent process could +               theoretically read the TID in the child process before the child +               tid is set.  This would require using either ptrace +               (not implemented) or having *_tidptr to point at a shared memory +               mapping.  We can't repeat the spinlock hack used above because +               the child process gets its own copy of the lock.  */ +            if (flags & CLONE_CHILD_SETTID) +                put_user_u32(gettid(), child_tidptr); +            if (flags & CLONE_PARENT_SETTID) +                put_user_u32(gettid(), parent_tidptr); +            ts = (TaskState *)cpu->opaque; +            if (flags & CLONE_SETTLS) +                cpu_set_tls (env, newtls); +            if (flags & CLONE_CHILD_CLEARTID) +                ts->child_tidptr = child_tidptr; +        } else { +            fork_end(0); +        } +    } +    return ret; +} + +/* warning : doesn't handle linux specific flags... */ +static int target_to_host_fcntl_cmd(int cmd) +{ +    switch(cmd) { +	case TARGET_F_DUPFD: +	case TARGET_F_GETFD: +	case TARGET_F_SETFD: +	case TARGET_F_GETFL: +	case TARGET_F_SETFL: +            return cmd; +        case TARGET_F_GETLK: +	    return F_GETLK; +	case TARGET_F_SETLK: +	    return F_SETLK; +	case TARGET_F_SETLKW: +	    return F_SETLKW; +	case TARGET_F_GETOWN: +	    return F_GETOWN; +	case TARGET_F_SETOWN: +	    return F_SETOWN; +	case TARGET_F_GETSIG: +	    return F_GETSIG; +	case TARGET_F_SETSIG: +	    return F_SETSIG; +#if TARGET_ABI_BITS == 32 +        case TARGET_F_GETLK64: +	    return F_GETLK64; +	case TARGET_F_SETLK64: +	    return F_SETLK64; +	case TARGET_F_SETLKW64: +	    return F_SETLKW64; +#endif +        case TARGET_F_SETLEASE: +            return F_SETLEASE; +        case TARGET_F_GETLEASE: +            return F_GETLEASE; +#ifdef F_DUPFD_CLOEXEC +        case TARGET_F_DUPFD_CLOEXEC: +            return F_DUPFD_CLOEXEC; +#endif +        case TARGET_F_NOTIFY: +            return F_NOTIFY; +#ifdef F_GETOWN_EX +	case TARGET_F_GETOWN_EX: +	    return F_GETOWN_EX; +#endif +#ifdef F_SETOWN_EX +	case TARGET_F_SETOWN_EX: +	    return F_SETOWN_EX; +#endif +	default: +            return -TARGET_EINVAL; +    } +    return -TARGET_EINVAL; +} + +#define TRANSTBL_CONVERT(a) { -1, TARGET_##a, -1, a } +static const bitmask_transtbl flock_tbl[] = { +    TRANSTBL_CONVERT(F_RDLCK), +    TRANSTBL_CONVERT(F_WRLCK), +    TRANSTBL_CONVERT(F_UNLCK), +    TRANSTBL_CONVERT(F_EXLCK), +    TRANSTBL_CONVERT(F_SHLCK), +    { 0, 0, 0, 0 } +}; + +static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) +{ +    struct flock fl; +    struct target_flock *target_fl; +    struct flock64 fl64; +    struct target_flock64 *target_fl64; +#ifdef F_GETOWN_EX +    struct f_owner_ex fox; +    struct target_f_owner_ex *target_fox; +#endif +    abi_long ret; +    int host_cmd = target_to_host_fcntl_cmd(cmd); + +    if (host_cmd == -TARGET_EINVAL) +	    return host_cmd; + +    switch(cmd) { +    case TARGET_F_GETLK: +        if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1)) +            return -TARGET_EFAULT; +        fl.l_type = +                  target_to_host_bitmask(tswap16(target_fl->l_type), flock_tbl); +        fl.l_whence = tswap16(target_fl->l_whence); +        fl.l_start = tswapal(target_fl->l_start); +        fl.l_len = tswapal(target_fl->l_len); +        fl.l_pid = tswap32(target_fl->l_pid); +        unlock_user_struct(target_fl, arg, 0); +        ret = get_errno(fcntl(fd, host_cmd, &fl)); +        if (ret == 0) { +            if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0)) +                return -TARGET_EFAULT; +            target_fl->l_type = +                          host_to_target_bitmask(tswap16(fl.l_type), flock_tbl); +            target_fl->l_whence = tswap16(fl.l_whence); +            target_fl->l_start = tswapal(fl.l_start); +            target_fl->l_len = tswapal(fl.l_len); +            target_fl->l_pid = tswap32(fl.l_pid); +            unlock_user_struct(target_fl, arg, 1); +        } +        break; + +    case TARGET_F_SETLK: +    case TARGET_F_SETLKW: +        if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1)) +            return -TARGET_EFAULT; +        fl.l_type = +                  target_to_host_bitmask(tswap16(target_fl->l_type), flock_tbl); +        fl.l_whence = tswap16(target_fl->l_whence); +        fl.l_start = tswapal(target_fl->l_start); +        fl.l_len = tswapal(target_fl->l_len); +        fl.l_pid = tswap32(target_fl->l_pid); +        unlock_user_struct(target_fl, arg, 0); +        ret = get_errno(fcntl(fd, host_cmd, &fl)); +        break; + +    case TARGET_F_GETLK64: +        if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1)) +            return -TARGET_EFAULT; +        fl64.l_type = +           target_to_host_bitmask(tswap16(target_fl64->l_type), flock_tbl) >> 1; +        fl64.l_whence = tswap16(target_fl64->l_whence); +        fl64.l_start = tswap64(target_fl64->l_start); +        fl64.l_len = tswap64(target_fl64->l_len); +        fl64.l_pid = tswap32(target_fl64->l_pid); +        unlock_user_struct(target_fl64, arg, 0); +        ret = get_errno(fcntl(fd, host_cmd, &fl64)); +        if (ret == 0) { +            if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0)) +                return -TARGET_EFAULT; +            target_fl64->l_type = +                   host_to_target_bitmask(tswap16(fl64.l_type), flock_tbl) >> 1; +            target_fl64->l_whence = tswap16(fl64.l_whence); +            target_fl64->l_start = tswap64(fl64.l_start); +            target_fl64->l_len = tswap64(fl64.l_len); +            target_fl64->l_pid = tswap32(fl64.l_pid); +            unlock_user_struct(target_fl64, arg, 1); +        } +        break; +    case TARGET_F_SETLK64: +    case TARGET_F_SETLKW64: +        if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1)) +            return -TARGET_EFAULT; +        fl64.l_type = +           target_to_host_bitmask(tswap16(target_fl64->l_type), flock_tbl) >> 1; +        fl64.l_whence = tswap16(target_fl64->l_whence); +        fl64.l_start = tswap64(target_fl64->l_start); +        fl64.l_len = tswap64(target_fl64->l_len); +        fl64.l_pid = tswap32(target_fl64->l_pid); +        unlock_user_struct(target_fl64, arg, 0); +        ret = get_errno(fcntl(fd, host_cmd, &fl64)); +        break; + +    case TARGET_F_GETFL: +        ret = get_errno(fcntl(fd, host_cmd, arg)); +        if (ret >= 0) { +            ret = host_to_target_bitmask(ret, fcntl_flags_tbl); +        } +        break; + +    case TARGET_F_SETFL: +        ret = get_errno(fcntl(fd, host_cmd, target_to_host_bitmask(arg, fcntl_flags_tbl))); +        break; + +#ifdef F_GETOWN_EX +    case TARGET_F_GETOWN_EX: +        ret = get_errno(fcntl(fd, host_cmd, &fox)); +        if (ret >= 0) { +            if (!lock_user_struct(VERIFY_WRITE, target_fox, arg, 0)) +                return -TARGET_EFAULT; +            target_fox->type = tswap32(fox.type); +            target_fox->pid = tswap32(fox.pid); +            unlock_user_struct(target_fox, arg, 1); +        } +        break; +#endif + +#ifdef F_SETOWN_EX +    case TARGET_F_SETOWN_EX: +        if (!lock_user_struct(VERIFY_READ, target_fox, arg, 1)) +            return -TARGET_EFAULT; +        fox.type = tswap32(target_fox->type); +        fox.pid = tswap32(target_fox->pid); +        unlock_user_struct(target_fox, arg, 0); +        ret = get_errno(fcntl(fd, host_cmd, &fox)); +        break; +#endif + +    case TARGET_F_SETOWN: +    case TARGET_F_GETOWN: +    case TARGET_F_SETSIG: +    case TARGET_F_GETSIG: +    case TARGET_F_SETLEASE: +    case TARGET_F_GETLEASE: +        ret = get_errno(fcntl(fd, host_cmd, arg)); +        break; + +    default: +        ret = get_errno(fcntl(fd, cmd, arg)); +        break; +    } +    return ret; +} + +#ifdef USE_UID16 + +static inline int high2lowuid(int uid) +{ +    if (uid > 65535) +        return 65534; +    else +        return uid; +} + +static inline int high2lowgid(int gid) +{ +    if (gid > 65535) +        return 65534; +    else +        return gid; +} + +static inline int low2highuid(int uid) +{ +    if ((int16_t)uid == -1) +        return -1; +    else +        return uid; +} + +static inline int low2highgid(int gid) +{ +    if ((int16_t)gid == -1) +        return -1; +    else +        return gid; +} +static inline int tswapid(int id) +{ +    return tswap16(id); +} + +#define put_user_id(x, gaddr) put_user_u16(x, gaddr) + +#else /* !USE_UID16 */ +static inline int high2lowuid(int uid) +{ +    return uid; +} +static inline int high2lowgid(int gid) +{ +    return gid; +} +static inline int low2highuid(int uid) +{ +    return uid; +} +static inline int low2highgid(int gid) +{ +    return gid; +} +static inline int tswapid(int id) +{ +    return tswap32(id); +} + +#define put_user_id(x, gaddr) put_user_u32(x, gaddr) + +#endif /* USE_UID16 */ + +void syscall_init(void) +{ +    IOCTLEntry *ie; +    const argtype *arg_type; +    int size; +    int i; + +    thunk_init(STRUCT_MAX); + +#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def); +#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def); +#include "syscall_types.h" +#undef STRUCT +#undef STRUCT_SPECIAL + +    /* Build target_to_host_errno_table[] table from +     * host_to_target_errno_table[]. */ +    for (i = 0; i < ERRNO_TABLE_SIZE; i++) { +        target_to_host_errno_table[host_to_target_errno_table[i]] = i; +    } + +    /* we patch the ioctl size if necessary. We rely on the fact that +       no ioctl has all the bits at '1' in the size field */ +    ie = ioctl_entries; +    while (ie->target_cmd != 0) { +        if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) == +            TARGET_IOC_SIZEMASK) { +            arg_type = ie->arg_type; +            if (arg_type[0] != TYPE_PTR) { +                fprintf(stderr, "cannot patch size for ioctl 0x%x\n", +                        ie->target_cmd); +                exit(1); +            } +            arg_type++; +            size = thunk_type_size(arg_type, 0); +            ie->target_cmd = (ie->target_cmd & +                              ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) | +                (size << TARGET_IOC_SIZESHIFT); +        } + +        /* automatic consistency check if same arch */ +#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \ +    (defined(__x86_64__) && defined(TARGET_X86_64)) +        if (unlikely(ie->target_cmd != ie->host_cmd)) { +            fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n", +                    ie->name, ie->target_cmd, ie->host_cmd); +        } +#endif +        ie++; +    } +} + +#if TARGET_ABI_BITS == 32 +static inline uint64_t target_offset64(uint32_t word0, uint32_t word1) +{ +#ifdef TARGET_WORDS_BIGENDIAN +    return ((uint64_t)word0 << 32) | word1; +#else +    return ((uint64_t)word1 << 32) | word0; +#endif +} +#else /* TARGET_ABI_BITS == 32 */ +static inline uint64_t target_offset64(uint64_t word0, uint64_t word1) +{ +    return word0; +} +#endif /* TARGET_ABI_BITS != 32 */ + +#ifdef TARGET_NR_truncate64 +static inline abi_long target_truncate64(void *cpu_env, const char *arg1, +                                         abi_long arg2, +                                         abi_long arg3, +                                         abi_long arg4) +{ +    if (regpairs_aligned(cpu_env)) { +        arg2 = arg3; +        arg3 = arg4; +    } +    return get_errno(truncate64(arg1, target_offset64(arg2, arg3))); +} +#endif + +#ifdef TARGET_NR_ftruncate64 +static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1, +                                          abi_long arg2, +                                          abi_long arg3, +                                          abi_long arg4) +{ +    if (regpairs_aligned(cpu_env)) { +        arg2 = arg3; +        arg3 = arg4; +    } +    return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3))); +} +#endif + +static inline abi_long target_to_host_timespec(struct timespec *host_ts, +                                               abi_ulong target_addr) +{ +    struct target_timespec *target_ts; + +    if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) +        return -TARGET_EFAULT; +    host_ts->tv_sec = tswapal(target_ts->tv_sec); +    host_ts->tv_nsec = tswapal(target_ts->tv_nsec); +    unlock_user_struct(target_ts, target_addr, 0); +    return 0; +} + +static inline abi_long host_to_target_timespec(abi_ulong target_addr, +                                               struct timespec *host_ts) +{ +    struct target_timespec *target_ts; + +    if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) +        return -TARGET_EFAULT; +    target_ts->tv_sec = tswapal(host_ts->tv_sec); +    target_ts->tv_nsec = tswapal(host_ts->tv_nsec); +    unlock_user_struct(target_ts, target_addr, 1); +    return 0; +} + +static inline abi_long target_to_host_itimerspec(struct itimerspec *host_itspec, +                                                 abi_ulong target_addr) +{ +    struct target_itimerspec *target_itspec; + +    if (!lock_user_struct(VERIFY_READ, target_itspec, target_addr, 1)) { +        return -TARGET_EFAULT; +    } + +    host_itspec->it_interval.tv_sec = +                            tswapal(target_itspec->it_interval.tv_sec); +    host_itspec->it_interval.tv_nsec = +                            tswapal(target_itspec->it_interval.tv_nsec); +    host_itspec->it_value.tv_sec = tswapal(target_itspec->it_value.tv_sec); +    host_itspec->it_value.tv_nsec = tswapal(target_itspec->it_value.tv_nsec); + +    unlock_user_struct(target_itspec, target_addr, 1); +    return 0; +} + +static inline abi_long host_to_target_itimerspec(abi_ulong target_addr, +                                               struct itimerspec *host_its) +{ +    struct target_itimerspec *target_itspec; + +    if (!lock_user_struct(VERIFY_WRITE, target_itspec, target_addr, 0)) { +        return -TARGET_EFAULT; +    } + +    target_itspec->it_interval.tv_sec = tswapal(host_its->it_interval.tv_sec); +    target_itspec->it_interval.tv_nsec = tswapal(host_its->it_interval.tv_nsec); + +    target_itspec->it_value.tv_sec = tswapal(host_its->it_value.tv_sec); +    target_itspec->it_value.tv_nsec = tswapal(host_its->it_value.tv_nsec); + +    unlock_user_struct(target_itspec, target_addr, 0); +    return 0; +} + +static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp, +                                               abi_ulong target_addr) +{ +    struct target_sigevent *target_sevp; + +    if (!lock_user_struct(VERIFY_READ, target_sevp, target_addr, 1)) { +        return -TARGET_EFAULT; +    } + +    /* This union is awkward on 64 bit systems because it has a 32 bit +     * integer and a pointer in it; we follow the conversion approach +     * used for handling sigval types in signal.c so the guest should get +     * the correct value back even if we did a 64 bit byteswap and it's +     * using the 32 bit integer. +     */ +    host_sevp->sigev_value.sival_ptr = +        (void *)(uintptr_t)tswapal(target_sevp->sigev_value.sival_ptr); +    host_sevp->sigev_signo = +        target_to_host_signal(tswap32(target_sevp->sigev_signo)); +    host_sevp->sigev_notify = tswap32(target_sevp->sigev_notify); +    host_sevp->_sigev_un._tid = tswap32(target_sevp->_sigev_un._tid); + +    unlock_user_struct(target_sevp, target_addr, 1); +    return 0; +} + +#if defined(TARGET_NR_mlockall) +static inline int target_to_host_mlockall_arg(int arg) +{ +    int result = 0; + +    if (arg & TARGET_MLOCKALL_MCL_CURRENT) { +        result |= MCL_CURRENT; +    } +    if (arg & TARGET_MLOCKALL_MCL_FUTURE) { +        result |= MCL_FUTURE; +    } +    return result; +} +#endif + +#if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat) +static inline abi_long host_to_target_stat64(void *cpu_env, +                                             abi_ulong target_addr, +                                             struct stat *host_st) +{ +#if defined(TARGET_ARM) && defined(TARGET_ABI32) +    if (((CPUARMState *)cpu_env)->eabi) { +        struct target_eabi_stat64 *target_st; + +        if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0)) +            return -TARGET_EFAULT; +        memset(target_st, 0, sizeof(struct target_eabi_stat64)); +        __put_user(host_st->st_dev, &target_st->st_dev); +        __put_user(host_st->st_ino, &target_st->st_ino); +#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO +        __put_user(host_st->st_ino, &target_st->__st_ino); +#endif +        __put_user(host_st->st_mode, &target_st->st_mode); +        __put_user(host_st->st_nlink, &target_st->st_nlink); +        __put_user(host_st->st_uid, &target_st->st_uid); +        __put_user(host_st->st_gid, &target_st->st_gid); +        __put_user(host_st->st_rdev, &target_st->st_rdev); +        __put_user(host_st->st_size, &target_st->st_size); +        __put_user(host_st->st_blksize, &target_st->st_blksize); +        __put_user(host_st->st_blocks, &target_st->st_blocks); +        __put_user(host_st->st_atime, &target_st->target_st_atime); +        __put_user(host_st->st_mtime, &target_st->target_st_mtime); +        __put_user(host_st->st_ctime, &target_st->target_st_ctime); +        unlock_user_struct(target_st, target_addr, 1); +    } else +#endif +    { +#if defined(TARGET_HAS_STRUCT_STAT64) +        struct target_stat64 *target_st; +#else +        struct target_stat *target_st; +#endif + +        if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0)) +            return -TARGET_EFAULT; +        memset(target_st, 0, sizeof(*target_st)); +        __put_user(host_st->st_dev, &target_st->st_dev); +        __put_user(host_st->st_ino, &target_st->st_ino); +#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO +        __put_user(host_st->st_ino, &target_st->__st_ino); +#endif +        __put_user(host_st->st_mode, &target_st->st_mode); +        __put_user(host_st->st_nlink, &target_st->st_nlink); +        __put_user(host_st->st_uid, &target_st->st_uid); +        __put_user(host_st->st_gid, &target_st->st_gid); +        __put_user(host_st->st_rdev, &target_st->st_rdev); +        /* XXX: better use of kernel struct */ +        __put_user(host_st->st_size, &target_st->st_size); +        __put_user(host_st->st_blksize, &target_st->st_blksize); +        __put_user(host_st->st_blocks, &target_st->st_blocks); +        __put_user(host_st->st_atime, &target_st->target_st_atime); +        __put_user(host_st->st_mtime, &target_st->target_st_mtime); +        __put_user(host_st->st_ctime, &target_st->target_st_ctime); +        unlock_user_struct(target_st, target_addr, 1); +    } + +    return 0; +} +#endif + +/* ??? Using host futex calls even when target atomic operations +   are not really atomic probably breaks things.  However implementing +   futexes locally would make futexes shared between multiple processes +   tricky.  However they're probably useless because guest atomic +   operations won't work either.  */ +static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout, +                    target_ulong uaddr2, int val3) +{ +    struct timespec ts, *pts; +    int base_op; + +    /* ??? We assume FUTEX_* constants are the same on both host +       and target.  */ +#ifdef FUTEX_CMD_MASK +    base_op = op & FUTEX_CMD_MASK; +#else +    base_op = op; +#endif +    switch (base_op) { +    case FUTEX_WAIT: +    case FUTEX_WAIT_BITSET: +        if (timeout) { +            pts = &ts; +            target_to_host_timespec(pts, timeout); +        } else { +            pts = NULL; +        } +        return get_errno(sys_futex(g2h(uaddr), op, tswap32(val), +                         pts, NULL, val3)); +    case FUTEX_WAKE: +        return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0)); +    case FUTEX_FD: +        return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0)); +    case FUTEX_REQUEUE: +    case FUTEX_CMP_REQUEUE: +    case FUTEX_WAKE_OP: +        /* For FUTEX_REQUEUE, FUTEX_CMP_REQUEUE, and FUTEX_WAKE_OP, the +           TIMEOUT parameter is interpreted as a uint32_t by the kernel. +           But the prototype takes a `struct timespec *'; insert casts +           to satisfy the compiler.  We do not need to tswap TIMEOUT +           since it's not compared to guest memory.  */ +        pts = (struct timespec *)(uintptr_t) timeout; +        return get_errno(sys_futex(g2h(uaddr), op, val, pts, +                                   g2h(uaddr2), +                                   (base_op == FUTEX_CMP_REQUEUE +                                    ? tswap32(val3) +                                    : val3))); +    default: +        return -TARGET_ENOSYS; +    } +} + +/* Map host to target signal numbers for the wait family of syscalls. +   Assume all other status bits are the same.  */ +int host_to_target_waitstatus(int status) +{ +    if (WIFSIGNALED(status)) { +        return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f); +    } +    if (WIFSTOPPED(status)) { +        return (host_to_target_signal(WSTOPSIG(status)) << 8) +               | (status & 0xff); +    } +    return status; +} + +static int open_self_cmdline(void *cpu_env, int fd) +{ +    int fd_orig = -1; +    bool word_skipped = false; + +    fd_orig = open("/proc/self/cmdline", O_RDONLY); +    if (fd_orig < 0) { +        return fd_orig; +    } + +    while (true) { +        ssize_t nb_read; +        char buf[128]; +        char *cp_buf = buf; + +        nb_read = read(fd_orig, buf, sizeof(buf)); +        if (nb_read < 0) { +            fd_orig = close(fd_orig); +            return -1; +        } else if (nb_read == 0) { +            break; +        } + +        if (!word_skipped) { +            /* Skip the first string, which is the path to qemu-*-static +               instead of the actual command. */ +            cp_buf = memchr(buf, 0, sizeof(buf)); +            if (cp_buf) { +                /* Null byte found, skip one string */ +                cp_buf++; +                nb_read -= cp_buf - buf; +                word_skipped = true; +            } +        } + +        if (word_skipped) { +            if (write(fd, cp_buf, nb_read) != nb_read) { +                close(fd_orig); +                return -1; +            } +        } +    } + +    return close(fd_orig); +} + +static int open_self_maps(void *cpu_env, int fd) +{ +    CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env); +    TaskState *ts = cpu->opaque; +    FILE *fp; +    char *line = NULL; +    size_t len = 0; +    ssize_t read; + +    fp = fopen("/proc/self/maps", "r"); +    if (fp == NULL) { +        return -EACCES; +    } + +    while ((read = getline(&line, &len, fp)) != -1) { +        int fields, dev_maj, dev_min, inode; +        uint64_t min, max, offset; +        char flag_r, flag_w, flag_x, flag_p; +        char path[512] = ""; +        fields = sscanf(line, "%"PRIx64"-%"PRIx64" %c%c%c%c %"PRIx64" %x:%x %d" +                        " %512s", &min, &max, &flag_r, &flag_w, &flag_x, +                        &flag_p, &offset, &dev_maj, &dev_min, &inode, path); + +        if ((fields < 10) || (fields > 11)) { +            continue; +        } +        if (h2g_valid(min)) { +            int flags = page_get_flags(h2g(min)); +            max = h2g_valid(max - 1) ? max : (uintptr_t)g2h(GUEST_ADDR_MAX); +            if (page_check_range(h2g(min), max - min, flags) == -1) { +                continue; +            } +            if (h2g(min) == ts->info->stack_limit) { +                pstrcpy(path, sizeof(path), "      [stack]"); +            } +            dprintf(fd, TARGET_ABI_FMT_lx "-" TARGET_ABI_FMT_lx +                    " %c%c%c%c %08" PRIx64 " %02x:%02x %d %s%s\n", +                    h2g(min), h2g(max - 1) + 1, flag_r, flag_w, +                    flag_x, flag_p, offset, dev_maj, dev_min, inode, +                    path[0] ? "         " : "", path); +        } +    } + +    free(line); +    fclose(fp); + +    return 0; +} + +static int open_self_stat(void *cpu_env, int fd) +{ +    CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env); +    TaskState *ts = cpu->opaque; +    abi_ulong start_stack = ts->info->start_stack; +    int i; + +    for (i = 0; i < 44; i++) { +      char buf[128]; +      int len; +      uint64_t val = 0; + +      if (i == 0) { +        /* pid */ +        val = getpid(); +        snprintf(buf, sizeof(buf), "%"PRId64 " ", val); +      } else if (i == 1) { +        /* app name */ +        snprintf(buf, sizeof(buf), "(%s) ", ts->bprm->argv[0]); +      } else if (i == 27) { +        /* stack bottom */ +        val = start_stack; +        snprintf(buf, sizeof(buf), "%"PRId64 " ", val); +      } else { +        /* for the rest, there is MasterCard */ +        snprintf(buf, sizeof(buf), "0%c", i == 43 ? '\n' : ' '); +      } + +      len = strlen(buf); +      if (write(fd, buf, len) != len) { +          return -1; +      } +    } + +    return 0; +} + +static int open_self_auxv(void *cpu_env, int fd) +{ +    CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env); +    TaskState *ts = cpu->opaque; +    abi_ulong auxv = ts->info->saved_auxv; +    abi_ulong len = ts->info->auxv_len; +    char *ptr; + +    /* +     * Auxiliary vector is stored in target process stack. +     * read in whole auxv vector and copy it to file +     */ +    ptr = lock_user(VERIFY_READ, auxv, len, 0); +    if (ptr != NULL) { +        while (len > 0) { +            ssize_t r; +            r = write(fd, ptr, len); +            if (r <= 0) { +                break; +            } +            len -= r; +            ptr += r; +        } +        lseek(fd, 0, SEEK_SET); +        unlock_user(ptr, auxv, len); +    } + +    return 0; +} + +static int is_proc_myself(const char *filename, const char *entry) +{ +    if (!strncmp(filename, "/proc/", strlen("/proc/"))) { +        filename += strlen("/proc/"); +        if (!strncmp(filename, "self/", strlen("self/"))) { +            filename += strlen("self/"); +        } else if (*filename >= '1' && *filename <= '9') { +            char myself[80]; +            snprintf(myself, sizeof(myself), "%d/", getpid()); +            if (!strncmp(filename, myself, strlen(myself))) { +                filename += strlen(myself); +            } else { +                return 0; +            } +        } else { +            return 0; +        } +        if (!strcmp(filename, entry)) { +            return 1; +        } +    } +    return 0; +} + +#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) +static int is_proc(const char *filename, const char *entry) +{ +    return strcmp(filename, entry) == 0; +} + +static int open_net_route(void *cpu_env, int fd) +{ +    FILE *fp; +    char *line = NULL; +    size_t len = 0; +    ssize_t read; + +    fp = fopen("/proc/net/route", "r"); +    if (fp == NULL) { +        return -EACCES; +    } + +    /* read header */ + +    read = getline(&line, &len, fp); +    dprintf(fd, "%s", line); + +    /* read routes */ + +    while ((read = getline(&line, &len, fp)) != -1) { +        char iface[16]; +        uint32_t dest, gw, mask; +        unsigned int flags, refcnt, use, metric, mtu, window, irtt; +        sscanf(line, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n", +                     iface, &dest, &gw, &flags, &refcnt, &use, &metric, +                     &mask, &mtu, &window, &irtt); +        dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n", +                iface, tswap32(dest), tswap32(gw), flags, refcnt, use, +                metric, tswap32(mask), mtu, window, irtt); +    } + +    free(line); +    fclose(fp); + +    return 0; +} +#endif + +static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode) +{ +    struct fake_open { +        const char *filename; +        int (*fill)(void *cpu_env, int fd); +        int (*cmp)(const char *s1, const char *s2); +    }; +    const struct fake_open *fake_open; +    static const struct fake_open fakes[] = { +        { "maps", open_self_maps, is_proc_myself }, +        { "stat", open_self_stat, is_proc_myself }, +        { "auxv", open_self_auxv, is_proc_myself }, +        { "cmdline", open_self_cmdline, is_proc_myself }, +#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) +        { "/proc/net/route", open_net_route, is_proc }, +#endif +        { NULL, NULL, NULL } +    }; + +    if (is_proc_myself(pathname, "exe")) { +        int execfd = qemu_getauxval(AT_EXECFD); +        return execfd ? execfd : get_errno(sys_openat(dirfd, exec_path, flags, mode)); +    } + +    for (fake_open = fakes; fake_open->filename; fake_open++) { +        if (fake_open->cmp(pathname, fake_open->filename)) { +            break; +        } +    } + +    if (fake_open->filename) { +        const char *tmpdir; +        char filename[PATH_MAX]; +        int fd, r; + +        /* create temporary file to map stat to */ +        tmpdir = getenv("TMPDIR"); +        if (!tmpdir) +            tmpdir = "/tmp"; +        snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir); +        fd = mkstemp(filename); +        if (fd < 0) { +            return fd; +        } +        unlink(filename); + +        if ((r = fake_open->fill(cpu_env, fd))) { +            close(fd); +            return r; +        } +        lseek(fd, 0, SEEK_SET); + +        return fd; +    } + +    return get_errno(sys_openat(dirfd, path(pathname), flags, mode)); +} + +#define TIMER_MAGIC 0x0caf0000 +#define TIMER_MAGIC_MASK 0xffff0000 + +/* Convert QEMU provided timer ID back to internal 16bit index format */ +static target_timer_t get_timer_id(abi_long arg) +{ +    target_timer_t timerid = arg; + +    if ((timerid & TIMER_MAGIC_MASK) != TIMER_MAGIC) { +        return -TARGET_EINVAL; +    } + +    timerid &= 0xffff; + +    if (timerid >= ARRAY_SIZE(g_posix_timers)) { +        return -TARGET_EINVAL; +    } + +    return timerid; +} + +/* do_syscall() should always have a single exit point at the end so +   that actions, such as logging of syscall results, can be performed. +   All errnos that do_syscall() returns must be -TARGET_<errcode>. */ +abi_long do_syscall(void *cpu_env, int num, abi_long arg1, +                    abi_long arg2, abi_long arg3, abi_long arg4, +                    abi_long arg5, abi_long arg6, abi_long arg7, +                    abi_long arg8) +{ +    CPUState *cpu = ENV_GET_CPU(cpu_env); +    abi_long ret; +    struct stat st; +    struct statfs stfs; +    void *p; + +#ifdef DEBUG +    gemu_log("syscall %d", num); +#endif +    if(do_strace) +        print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6); + +    switch(num) { +    case TARGET_NR_exit: +        /* In old applications this may be used to implement _exit(2). +           However in threaded applictions it is used for thread termination, +           and _exit_group is used for application termination. +           Do thread termination if we have more then one thread.  */ +        /* FIXME: This probably breaks if a signal arrives.  We should probably +           be disabling signals.  */ +        if (CPU_NEXT(first_cpu)) { +            TaskState *ts; + +            cpu_list_lock(); +            /* Remove the CPU from the list.  */ +            QTAILQ_REMOVE(&cpus, cpu, node); +            cpu_list_unlock(); +            ts = cpu->opaque; +            if (ts->child_tidptr) { +                put_user_u32(0, ts->child_tidptr); +                sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX, +                          NULL, NULL, 0); +            } +            thread_cpu = NULL; +            object_unref(OBJECT(cpu)); +            g_free(ts); +            pthread_exit(NULL); +        } +#ifdef TARGET_GPROF +        _mcleanup(); +#endif +        gdb_exit(cpu_env, arg1); +        _exit(arg1); +        ret = 0; /* avoid warning */ +        break; +    case TARGET_NR_read: +        if (arg3 == 0) +            ret = 0; +        else { +            if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) +                goto efault; +            ret = get_errno(read(arg1, p, arg3)); +            unlock_user(p, arg2, ret); +        } +        break; +    case TARGET_NR_write: +        if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) +            goto efault; +        ret = get_errno(write(arg1, p, arg3)); +        unlock_user(p, arg2, 0); +        break; +    case TARGET_NR_open: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(do_openat(cpu_env, AT_FDCWD, p, +                                  target_to_host_bitmask(arg2, fcntl_flags_tbl), +                                  arg3)); +        unlock_user(p, arg1, 0); +        break; +    case TARGET_NR_openat: +        if (!(p = lock_user_string(arg2))) +            goto efault; +        ret = get_errno(do_openat(cpu_env, arg1, p, +                                  target_to_host_bitmask(arg3, fcntl_flags_tbl), +                                  arg4)); +        unlock_user(p, arg2, 0); +        break; +    case TARGET_NR_close: +        ret = get_errno(close(arg1)); +        break; +    case TARGET_NR_brk: +        ret = do_brk(arg1); +        break; +    case TARGET_NR_fork: +        ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0)); +        break; +#ifdef TARGET_NR_waitpid +    case TARGET_NR_waitpid: +        { +            int status; +            ret = get_errno(waitpid(arg1, &status, arg3)); +            if (!is_error(ret) && arg2 && ret +                && put_user_s32(host_to_target_waitstatus(status), arg2)) +                goto efault; +        } +        break; +#endif +#ifdef TARGET_NR_waitid +    case TARGET_NR_waitid: +        { +            siginfo_t info; +            info.si_pid = 0; +            ret = get_errno(waitid(arg1, arg2, &info, arg4)); +            if (!is_error(ret) && arg3 && info.si_pid != 0) { +                if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0))) +                    goto efault; +                host_to_target_siginfo(p, &info); +                unlock_user(p, arg3, sizeof(target_siginfo_t)); +            } +        } +        break; +#endif +#ifdef TARGET_NR_creat /* not on alpha */ +    case TARGET_NR_creat: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(creat(p, arg2)); +        unlock_user(p, arg1, 0); +        break; +#endif +    case TARGET_NR_link: +        { +            void * p2; +            p = lock_user_string(arg1); +            p2 = lock_user_string(arg2); +            if (!p || !p2) +                ret = -TARGET_EFAULT; +            else +                ret = get_errno(link(p, p2)); +            unlock_user(p2, arg2, 0); +            unlock_user(p, arg1, 0); +        } +        break; +#if defined(TARGET_NR_linkat) +    case TARGET_NR_linkat: +        { +            void * p2 = NULL; +            if (!arg2 || !arg4) +                goto efault; +            p  = lock_user_string(arg2); +            p2 = lock_user_string(arg4); +            if (!p || !p2) +                ret = -TARGET_EFAULT; +            else +                ret = get_errno(linkat(arg1, p, arg3, p2, arg5)); +            unlock_user(p, arg2, 0); +            unlock_user(p2, arg4, 0); +        } +        break; +#endif +    case TARGET_NR_unlink: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(unlink(p)); +        unlock_user(p, arg1, 0); +        break; +#if defined(TARGET_NR_unlinkat) +    case TARGET_NR_unlinkat: +        if (!(p = lock_user_string(arg2))) +            goto efault; +        ret = get_errno(unlinkat(arg1, p, arg3)); +        unlock_user(p, arg2, 0); +        break; +#endif +    case TARGET_NR_execve: +        { +            char **argp, **envp; +            int argc, envc; +            abi_ulong gp; +            abi_ulong guest_argp; +            abi_ulong guest_envp; +            abi_ulong addr; +            char **q; +            int total_size = 0; + +            argc = 0; +            guest_argp = arg2; +            for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) { +                if (get_user_ual(addr, gp)) +                    goto efault; +                if (!addr) +                    break; +                argc++; +            } +            envc = 0; +            guest_envp = arg3; +            for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) { +                if (get_user_ual(addr, gp)) +                    goto efault; +                if (!addr) +                    break; +                envc++; +            } + +            argp = alloca((argc + 1) * sizeof(void *)); +            envp = alloca((envc + 1) * sizeof(void *)); + +            for (gp = guest_argp, q = argp; gp; +                  gp += sizeof(abi_ulong), q++) { +                if (get_user_ual(addr, gp)) +                    goto execve_efault; +                if (!addr) +                    break; +                if (!(*q = lock_user_string(addr))) +                    goto execve_efault; +                total_size += strlen(*q) + 1; +            } +            *q = NULL; + +            for (gp = guest_envp, q = envp; gp; +                  gp += sizeof(abi_ulong), q++) { +                if (get_user_ual(addr, gp)) +                    goto execve_efault; +                if (!addr) +                    break; +                if (!(*q = lock_user_string(addr))) +                    goto execve_efault; +                total_size += strlen(*q) + 1; +            } +            *q = NULL; + +            /* This case will not be caught by the host's execve() if its +               page size is bigger than the target's. */ +            if (total_size > MAX_ARG_PAGES * TARGET_PAGE_SIZE) { +                ret = -TARGET_E2BIG; +                goto execve_end; +            } +            if (!(p = lock_user_string(arg1))) +                goto execve_efault; +            ret = get_errno(execve(p, argp, envp)); +            unlock_user(p, arg1, 0); + +            goto execve_end; + +        execve_efault: +            ret = -TARGET_EFAULT; + +        execve_end: +            for (gp = guest_argp, q = argp; *q; +                  gp += sizeof(abi_ulong), q++) { +                if (get_user_ual(addr, gp) +                    || !addr) +                    break; +                unlock_user(*q, addr, 0); +            } +            for (gp = guest_envp, q = envp; *q; +                  gp += sizeof(abi_ulong), q++) { +                if (get_user_ual(addr, gp) +                    || !addr) +                    break; +                unlock_user(*q, addr, 0); +            } +        } +        break; +    case TARGET_NR_chdir: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(chdir(p)); +        unlock_user(p, arg1, 0); +        break; +#ifdef TARGET_NR_time +    case TARGET_NR_time: +        { +            time_t host_time; +            ret = get_errno(time(&host_time)); +            if (!is_error(ret) +                && arg1 +                && put_user_sal(host_time, arg1)) +                goto efault; +        } +        break; +#endif +    case TARGET_NR_mknod: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(mknod(p, arg2, arg3)); +        unlock_user(p, arg1, 0); +        break; +#if defined(TARGET_NR_mknodat) +    case TARGET_NR_mknodat: +        if (!(p = lock_user_string(arg2))) +            goto efault; +        ret = get_errno(mknodat(arg1, p, arg3, arg4)); +        unlock_user(p, arg2, 0); +        break; +#endif +    case TARGET_NR_chmod: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(chmod(p, arg2)); +        unlock_user(p, arg1, 0); +        break; +#ifdef TARGET_NR_break +    case TARGET_NR_break: +        goto unimplemented; +#endif +#ifdef TARGET_NR_oldstat +    case TARGET_NR_oldstat: +        goto unimplemented; +#endif +    case TARGET_NR_lseek: +        ret = get_errno(lseek(arg1, arg2, arg3)); +        break; +#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA) +    /* Alpha specific */ +    case TARGET_NR_getxpid: +        ((CPUAlphaState *)cpu_env)->ir[IR_A4] = getppid(); +        ret = get_errno(getpid()); +        break; +#endif +#ifdef TARGET_NR_getpid +    case TARGET_NR_getpid: +        ret = get_errno(getpid()); +        break; +#endif +    case TARGET_NR_mount: +        { +            /* need to look at the data field */ +            void *p2, *p3; + +            if (arg1) { +                p = lock_user_string(arg1); +                if (!p) { +                    goto efault; +                } +            } else { +                p = NULL; +            } + +            p2 = lock_user_string(arg2); +            if (!p2) { +                if (arg1) { +                    unlock_user(p, arg1, 0); +                } +                goto efault; +            } + +            if (arg3) { +                p3 = lock_user_string(arg3); +                if (!p3) { +                    if (arg1) { +                        unlock_user(p, arg1, 0); +                    } +                    unlock_user(p2, arg2, 0); +                    goto efault; +                } +            } else { +                p3 = NULL; +            } + +            /* FIXME - arg5 should be locked, but it isn't clear how to +             * do that since it's not guaranteed to be a NULL-terminated +             * string. +             */ +            if (!arg5) { +                ret = mount(p, p2, p3, (unsigned long)arg4, NULL); +            } else { +                ret = mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)); +            } +            ret = get_errno(ret); + +            if (arg1) { +                unlock_user(p, arg1, 0); +            } +            unlock_user(p2, arg2, 0); +            if (arg3) { +                unlock_user(p3, arg3, 0); +            } +        } +        break; +#ifdef TARGET_NR_umount +    case TARGET_NR_umount: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(umount(p)); +        unlock_user(p, arg1, 0); +        break; +#endif +#ifdef TARGET_NR_stime /* not on alpha */ +    case TARGET_NR_stime: +        { +            time_t host_time; +            if (get_user_sal(host_time, arg1)) +                goto efault; +            ret = get_errno(stime(&host_time)); +        } +        break; +#endif +    case TARGET_NR_ptrace: +        goto unimplemented; +#ifdef TARGET_NR_alarm /* not on alpha */ +    case TARGET_NR_alarm: +        ret = alarm(arg1); +        break; +#endif +#ifdef TARGET_NR_oldfstat +    case TARGET_NR_oldfstat: +        goto unimplemented; +#endif +#ifdef TARGET_NR_pause /* not on alpha */ +    case TARGET_NR_pause: +        ret = get_errno(pause()); +        break; +#endif +#ifdef TARGET_NR_utime +    case TARGET_NR_utime: +        { +            struct utimbuf tbuf, *host_tbuf; +            struct target_utimbuf *target_tbuf; +            if (arg2) { +                if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1)) +                    goto efault; +                tbuf.actime = tswapal(target_tbuf->actime); +                tbuf.modtime = tswapal(target_tbuf->modtime); +                unlock_user_struct(target_tbuf, arg2, 0); +                host_tbuf = &tbuf; +            } else { +                host_tbuf = NULL; +            } +            if (!(p = lock_user_string(arg1))) +                goto efault; +            ret = get_errno(utime(p, host_tbuf)); +            unlock_user(p, arg1, 0); +        } +        break; +#endif +    case TARGET_NR_utimes: +        { +            struct timeval *tvp, tv[2]; +            if (arg2) { +                if (copy_from_user_timeval(&tv[0], arg2) +                    || copy_from_user_timeval(&tv[1], +                                              arg2 + sizeof(struct target_timeval))) +                    goto efault; +                tvp = tv; +            } else { +                tvp = NULL; +            } +            if (!(p = lock_user_string(arg1))) +                goto efault; +            ret = get_errno(utimes(p, tvp)); +            unlock_user(p, arg1, 0); +        } +        break; +#if defined(TARGET_NR_futimesat) +    case TARGET_NR_futimesat: +        { +            struct timeval *tvp, tv[2]; +            if (arg3) { +                if (copy_from_user_timeval(&tv[0], arg3) +                    || copy_from_user_timeval(&tv[1], +                                              arg3 + sizeof(struct target_timeval))) +                    goto efault; +                tvp = tv; +            } else { +                tvp = NULL; +            } +            if (!(p = lock_user_string(arg2))) +                goto efault; +            ret = get_errno(futimesat(arg1, path(p), tvp)); +            unlock_user(p, arg2, 0); +        } +        break; +#endif +#ifdef TARGET_NR_stty +    case TARGET_NR_stty: +        goto unimplemented; +#endif +#ifdef TARGET_NR_gtty +    case TARGET_NR_gtty: +        goto unimplemented; +#endif +    case TARGET_NR_access: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(access(path(p), arg2)); +        unlock_user(p, arg1, 0); +        break; +#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat) +    case TARGET_NR_faccessat: +        if (!(p = lock_user_string(arg2))) +            goto efault; +        ret = get_errno(faccessat(arg1, p, arg3, 0)); +        unlock_user(p, arg2, 0); +        break; +#endif +#ifdef TARGET_NR_nice /* not on alpha */ +    case TARGET_NR_nice: +        ret = get_errno(nice(arg1)); +        break; +#endif +#ifdef TARGET_NR_ftime +    case TARGET_NR_ftime: +        goto unimplemented; +#endif +    case TARGET_NR_sync: +        sync(); +        ret = 0; +        break; +    case TARGET_NR_kill: +        ret = get_errno(kill(arg1, target_to_host_signal(arg2))); +        break; +    case TARGET_NR_rename: +        { +            void *p2; +            p = lock_user_string(arg1); +            p2 = lock_user_string(arg2); +            if (!p || !p2) +                ret = -TARGET_EFAULT; +            else +                ret = get_errno(rename(p, p2)); +            unlock_user(p2, arg2, 0); +            unlock_user(p, arg1, 0); +        } +        break; +#if defined(TARGET_NR_renameat) +    case TARGET_NR_renameat: +        { +            void *p2; +            p  = lock_user_string(arg2); +            p2 = lock_user_string(arg4); +            if (!p || !p2) +                ret = -TARGET_EFAULT; +            else +                ret = get_errno(renameat(arg1, p, arg3, p2)); +            unlock_user(p2, arg4, 0); +            unlock_user(p, arg2, 0); +        } +        break; +#endif +    case TARGET_NR_mkdir: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(mkdir(p, arg2)); +        unlock_user(p, arg1, 0); +        break; +#if defined(TARGET_NR_mkdirat) +    case TARGET_NR_mkdirat: +        if (!(p = lock_user_string(arg2))) +            goto efault; +        ret = get_errno(mkdirat(arg1, p, arg3)); +        unlock_user(p, arg2, 0); +        break; +#endif +    case TARGET_NR_rmdir: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(rmdir(p)); +        unlock_user(p, arg1, 0); +        break; +    case TARGET_NR_dup: +        ret = get_errno(dup(arg1)); +        break; +    case TARGET_NR_pipe: +        ret = do_pipe(cpu_env, arg1, 0, 0); +        break; +#ifdef TARGET_NR_pipe2 +    case TARGET_NR_pipe2: +        ret = do_pipe(cpu_env, arg1, +                      target_to_host_bitmask(arg2, fcntl_flags_tbl), 1); +        break; +#endif +    case TARGET_NR_times: +        { +            struct target_tms *tmsp; +            struct tms tms; +            ret = get_errno(times(&tms)); +            if (arg1) { +                tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0); +                if (!tmsp) +                    goto efault; +                tmsp->tms_utime = tswapal(host_to_target_clock_t(tms.tms_utime)); +                tmsp->tms_stime = tswapal(host_to_target_clock_t(tms.tms_stime)); +                tmsp->tms_cutime = tswapal(host_to_target_clock_t(tms.tms_cutime)); +                tmsp->tms_cstime = tswapal(host_to_target_clock_t(tms.tms_cstime)); +            } +            if (!is_error(ret)) +                ret = host_to_target_clock_t(ret); +        } +        break; +#ifdef TARGET_NR_prof +    case TARGET_NR_prof: +        goto unimplemented; +#endif +#ifdef TARGET_NR_signal +    case TARGET_NR_signal: +        goto unimplemented; +#endif +    case TARGET_NR_acct: +        if (arg1 == 0) { +            ret = get_errno(acct(NULL)); +        } else { +            if (!(p = lock_user_string(arg1))) +                goto efault; +            ret = get_errno(acct(path(p))); +            unlock_user(p, arg1, 0); +        } +        break; +#ifdef TARGET_NR_umount2 +    case TARGET_NR_umount2: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(umount2(p, arg2)); +        unlock_user(p, arg1, 0); +        break; +#endif +#ifdef TARGET_NR_lock +    case TARGET_NR_lock: +        goto unimplemented; +#endif +    case TARGET_NR_ioctl: +        ret = do_ioctl(arg1, arg2, arg3); +        break; +    case TARGET_NR_fcntl: +        ret = do_fcntl(arg1, arg2, arg3); +        break; +#ifdef TARGET_NR_mpx +    case TARGET_NR_mpx: +        goto unimplemented; +#endif +    case TARGET_NR_setpgid: +        ret = get_errno(setpgid(arg1, arg2)); +        break; +#ifdef TARGET_NR_ulimit +    case TARGET_NR_ulimit: +        goto unimplemented; +#endif +#ifdef TARGET_NR_oldolduname +    case TARGET_NR_oldolduname: +        goto unimplemented; +#endif +    case TARGET_NR_umask: +        ret = get_errno(umask(arg1)); +        break; +    case TARGET_NR_chroot: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(chroot(p)); +        unlock_user(p, arg1, 0); +        break; +    case TARGET_NR_ustat: +        goto unimplemented; +    case TARGET_NR_dup2: +        ret = get_errno(dup2(arg1, arg2)); +        break; +#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3) +    case TARGET_NR_dup3: +        ret = get_errno(dup3(arg1, arg2, arg3)); +        break; +#endif +#ifdef TARGET_NR_getppid /* not on alpha */ +    case TARGET_NR_getppid: +        ret = get_errno(getppid()); +        break; +#endif +    case TARGET_NR_getpgrp: +        ret = get_errno(getpgrp()); +        break; +    case TARGET_NR_setsid: +        ret = get_errno(setsid()); +        break; +#ifdef TARGET_NR_sigaction +    case TARGET_NR_sigaction: +        { +#if defined(TARGET_ALPHA) +            struct target_sigaction act, oact, *pact = 0; +            struct target_old_sigaction *old_act; +            if (arg2) { +                if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1)) +                    goto efault; +                act._sa_handler = old_act->_sa_handler; +                target_siginitset(&act.sa_mask, old_act->sa_mask); +                act.sa_flags = old_act->sa_flags; +                act.sa_restorer = 0; +                unlock_user_struct(old_act, arg2, 0); +                pact = &act; +            } +            ret = get_errno(do_sigaction(arg1, pact, &oact)); +            if (!is_error(ret) && arg3) { +                if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0)) +                    goto efault; +                old_act->_sa_handler = oact._sa_handler; +                old_act->sa_mask = oact.sa_mask.sig[0]; +                old_act->sa_flags = oact.sa_flags; +                unlock_user_struct(old_act, arg3, 1); +            } +#elif defined(TARGET_MIPS) +	    struct target_sigaction act, oact, *pact, *old_act; + +	    if (arg2) { +                if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1)) +                    goto efault; +		act._sa_handler = old_act->_sa_handler; +		target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]); +		act.sa_flags = old_act->sa_flags; +		unlock_user_struct(old_act, arg2, 0); +		pact = &act; +	    } else { +		pact = NULL; +	    } + +	    ret = get_errno(do_sigaction(arg1, pact, &oact)); + +	    if (!is_error(ret) && arg3) { +                if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0)) +                    goto efault; +		old_act->_sa_handler = oact._sa_handler; +		old_act->sa_flags = oact.sa_flags; +		old_act->sa_mask.sig[0] = oact.sa_mask.sig[0]; +		old_act->sa_mask.sig[1] = 0; +		old_act->sa_mask.sig[2] = 0; +		old_act->sa_mask.sig[3] = 0; +		unlock_user_struct(old_act, arg3, 1); +	    } +#else +            struct target_old_sigaction *old_act; +            struct target_sigaction act, oact, *pact; +            if (arg2) { +                if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1)) +                    goto efault; +                act._sa_handler = old_act->_sa_handler; +                target_siginitset(&act.sa_mask, old_act->sa_mask); +                act.sa_flags = old_act->sa_flags; +                act.sa_restorer = old_act->sa_restorer; +                unlock_user_struct(old_act, arg2, 0); +                pact = &act; +            } else { +                pact = NULL; +            } +            ret = get_errno(do_sigaction(arg1, pact, &oact)); +            if (!is_error(ret) && arg3) { +                if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0)) +                    goto efault; +                old_act->_sa_handler = oact._sa_handler; +                old_act->sa_mask = oact.sa_mask.sig[0]; +                old_act->sa_flags = oact.sa_flags; +                old_act->sa_restorer = oact.sa_restorer; +                unlock_user_struct(old_act, arg3, 1); +            } +#endif +        } +        break; +#endif +    case TARGET_NR_rt_sigaction: +        { +#if defined(TARGET_ALPHA) +            struct target_sigaction act, oact, *pact = 0; +            struct target_rt_sigaction *rt_act; +            /* ??? arg4 == sizeof(sigset_t).  */ +            if (arg2) { +                if (!lock_user_struct(VERIFY_READ, rt_act, arg2, 1)) +                    goto efault; +                act._sa_handler = rt_act->_sa_handler; +                act.sa_mask = rt_act->sa_mask; +                act.sa_flags = rt_act->sa_flags; +                act.sa_restorer = arg5; +                unlock_user_struct(rt_act, arg2, 0); +                pact = &act; +            } +            ret = get_errno(do_sigaction(arg1, pact, &oact)); +            if (!is_error(ret) && arg3) { +                if (!lock_user_struct(VERIFY_WRITE, rt_act, arg3, 0)) +                    goto efault; +                rt_act->_sa_handler = oact._sa_handler; +                rt_act->sa_mask = oact.sa_mask; +                rt_act->sa_flags = oact.sa_flags; +                unlock_user_struct(rt_act, arg3, 1); +            } +#else +            struct target_sigaction *act; +            struct target_sigaction *oact; + +            if (arg2) { +                if (!lock_user_struct(VERIFY_READ, act, arg2, 1)) +                    goto efault; +            } else +                act = NULL; +            if (arg3) { +                if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) { +                    ret = -TARGET_EFAULT; +                    goto rt_sigaction_fail; +                } +            } else +                oact = NULL; +            ret = get_errno(do_sigaction(arg1, act, oact)); +	rt_sigaction_fail: +            if (act) +                unlock_user_struct(act, arg2, 0); +            if (oact) +                unlock_user_struct(oact, arg3, 1); +#endif +        } +        break; +#ifdef TARGET_NR_sgetmask /* not on alpha */ +    case TARGET_NR_sgetmask: +        { +            sigset_t cur_set; +            abi_ulong target_set; +            do_sigprocmask(0, NULL, &cur_set); +            host_to_target_old_sigset(&target_set, &cur_set); +            ret = target_set; +        } +        break; +#endif +#ifdef TARGET_NR_ssetmask /* not on alpha */ +    case TARGET_NR_ssetmask: +        { +            sigset_t set, oset, cur_set; +            abi_ulong target_set = arg1; +            do_sigprocmask(0, NULL, &cur_set); +            target_to_host_old_sigset(&set, &target_set); +            sigorset(&set, &set, &cur_set); +            do_sigprocmask(SIG_SETMASK, &set, &oset); +            host_to_target_old_sigset(&target_set, &oset); +            ret = target_set; +        } +        break; +#endif +#ifdef TARGET_NR_sigprocmask +    case TARGET_NR_sigprocmask: +        { +#if defined(TARGET_ALPHA) +            sigset_t set, oldset; +            abi_ulong mask; +            int how; + +            switch (arg1) { +            case TARGET_SIG_BLOCK: +                how = SIG_BLOCK; +                break; +            case TARGET_SIG_UNBLOCK: +                how = SIG_UNBLOCK; +                break; +            case TARGET_SIG_SETMASK: +                how = SIG_SETMASK; +                break; +            default: +                ret = -TARGET_EINVAL; +                goto fail; +            } +            mask = arg2; +            target_to_host_old_sigset(&set, &mask); + +            ret = get_errno(do_sigprocmask(how, &set, &oldset)); +            if (!is_error(ret)) { +                host_to_target_old_sigset(&mask, &oldset); +                ret = mask; +                ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0; /* force no error */ +            } +#else +            sigset_t set, oldset, *set_ptr; +            int how; + +            if (arg2) { +                switch (arg1) { +                case TARGET_SIG_BLOCK: +                    how = SIG_BLOCK; +                    break; +                case TARGET_SIG_UNBLOCK: +                    how = SIG_UNBLOCK; +                    break; +                case TARGET_SIG_SETMASK: +                    how = SIG_SETMASK; +                    break; +                default: +                    ret = -TARGET_EINVAL; +                    goto fail; +                } +                if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1))) +                    goto efault; +                target_to_host_old_sigset(&set, p); +                unlock_user(p, arg2, 0); +                set_ptr = &set; +            } else { +                how = 0; +                set_ptr = NULL; +            } +            ret = get_errno(do_sigprocmask(how, set_ptr, &oldset)); +            if (!is_error(ret) && arg3) { +                if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0))) +                    goto efault; +                host_to_target_old_sigset(p, &oldset); +                unlock_user(p, arg3, sizeof(target_sigset_t)); +            } +#endif +        } +        break; +#endif +    case TARGET_NR_rt_sigprocmask: +        { +            int how = arg1; +            sigset_t set, oldset, *set_ptr; + +            if (arg2) { +                switch(how) { +                case TARGET_SIG_BLOCK: +                    how = SIG_BLOCK; +                    break; +                case TARGET_SIG_UNBLOCK: +                    how = SIG_UNBLOCK; +                    break; +                case TARGET_SIG_SETMASK: +                    how = SIG_SETMASK; +                    break; +                default: +                    ret = -TARGET_EINVAL; +                    goto fail; +                } +                if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1))) +                    goto efault; +                target_to_host_sigset(&set, p); +                unlock_user(p, arg2, 0); +                set_ptr = &set; +            } else { +                how = 0; +                set_ptr = NULL; +            } +            ret = get_errno(do_sigprocmask(how, set_ptr, &oldset)); +            if (!is_error(ret) && arg3) { +                if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0))) +                    goto efault; +                host_to_target_sigset(p, &oldset); +                unlock_user(p, arg3, sizeof(target_sigset_t)); +            } +        } +        break; +#ifdef TARGET_NR_sigpending +    case TARGET_NR_sigpending: +        { +            sigset_t set; +            ret = get_errno(sigpending(&set)); +            if (!is_error(ret)) { +                if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0))) +                    goto efault; +                host_to_target_old_sigset(p, &set); +                unlock_user(p, arg1, sizeof(target_sigset_t)); +            } +        } +        break; +#endif +    case TARGET_NR_rt_sigpending: +        { +            sigset_t set; +            ret = get_errno(sigpending(&set)); +            if (!is_error(ret)) { +                if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0))) +                    goto efault; +                host_to_target_sigset(p, &set); +                unlock_user(p, arg1, sizeof(target_sigset_t)); +            } +        } +        break; +#ifdef TARGET_NR_sigsuspend +    case TARGET_NR_sigsuspend: +        { +            sigset_t set; +#if defined(TARGET_ALPHA) +            abi_ulong mask = arg1; +            target_to_host_old_sigset(&set, &mask); +#else +            if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1))) +                goto efault; +            target_to_host_old_sigset(&set, p); +            unlock_user(p, arg1, 0); +#endif +            ret = get_errno(sigsuspend(&set)); +        } +        break; +#endif +    case TARGET_NR_rt_sigsuspend: +        { +            sigset_t set; +            if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1))) +                goto efault; +            target_to_host_sigset(&set, p); +            unlock_user(p, arg1, 0); +            ret = get_errno(sigsuspend(&set)); +        } +        break; +    case TARGET_NR_rt_sigtimedwait: +        { +            sigset_t set; +            struct timespec uts, *puts; +            siginfo_t uinfo; + +            if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1))) +                goto efault; +            target_to_host_sigset(&set, p); +            unlock_user(p, arg1, 0); +            if (arg3) { +                puts = &uts; +                target_to_host_timespec(puts, arg3); +            } else { +                puts = NULL; +            } +            ret = get_errno(sigtimedwait(&set, &uinfo, puts)); +            if (!is_error(ret)) { +                if (arg2) { +                    p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), +                                  0); +                    if (!p) { +                        goto efault; +                    } +                    host_to_target_siginfo(p, &uinfo); +                    unlock_user(p, arg2, sizeof(target_siginfo_t)); +                } +                ret = host_to_target_signal(ret); +            } +        } +        break; +    case TARGET_NR_rt_sigqueueinfo: +        { +            siginfo_t uinfo; +            if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1))) +                goto efault; +            target_to_host_siginfo(&uinfo, p); +            unlock_user(p, arg1, 0); +            ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo)); +        } +        break; +#ifdef TARGET_NR_sigreturn +    case TARGET_NR_sigreturn: +        /* NOTE: ret is eax, so not transcoding must be done */ +        ret = do_sigreturn(cpu_env); +        break; +#endif +    case TARGET_NR_rt_sigreturn: +        /* NOTE: ret is eax, so not transcoding must be done */ +        ret = do_rt_sigreturn(cpu_env); +        break; +    case TARGET_NR_sethostname: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(sethostname(p, arg2)); +        unlock_user(p, arg1, 0); +        break; +    case TARGET_NR_setrlimit: +        { +            int resource = target_to_host_resource(arg1); +            struct target_rlimit *target_rlim; +            struct rlimit rlim; +            if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1)) +                goto efault; +            rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur); +            rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max); +            unlock_user_struct(target_rlim, arg2, 0); +            ret = get_errno(setrlimit(resource, &rlim)); +        } +        break; +    case TARGET_NR_getrlimit: +        { +            int resource = target_to_host_resource(arg1); +            struct target_rlimit *target_rlim; +            struct rlimit rlim; + +            ret = get_errno(getrlimit(resource, &rlim)); +            if (!is_error(ret)) { +                if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0)) +                    goto efault; +                target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur); +                target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max); +                unlock_user_struct(target_rlim, arg2, 1); +            } +        } +        break; +    case TARGET_NR_getrusage: +        { +            struct rusage rusage; +            ret = get_errno(getrusage(arg1, &rusage)); +            if (!is_error(ret)) { +                ret = host_to_target_rusage(arg2, &rusage); +            } +        } +        break; +    case TARGET_NR_gettimeofday: +        { +            struct timeval tv; +            ret = get_errno(gettimeofday(&tv, NULL)); +            if (!is_error(ret)) { +                if (copy_to_user_timeval(arg1, &tv)) +                    goto efault; +            } +        } +        break; +    case TARGET_NR_settimeofday: +        { +            struct timeval tv, *ptv = NULL; +            struct timezone tz, *ptz = NULL; + +            if (arg1) { +                if (copy_from_user_timeval(&tv, arg1)) { +                    goto efault; +                } +                ptv = &tv; +            } + +            if (arg2) { +                if (copy_from_user_timezone(&tz, arg2)) { +                    goto efault; +                } +                ptz = &tz; +            } + +            ret = get_errno(settimeofday(ptv, ptz)); +        } +        break; +#if defined(TARGET_NR_select) +    case TARGET_NR_select: +#if defined(TARGET_S390X) || defined(TARGET_ALPHA) +        ret = do_select(arg1, arg2, arg3, arg4, arg5); +#else +        { +            struct target_sel_arg_struct *sel; +            abi_ulong inp, outp, exp, tvp; +            long nsel; + +            if (!lock_user_struct(VERIFY_READ, sel, arg1, 1)) +                goto efault; +            nsel = tswapal(sel->n); +            inp = tswapal(sel->inp); +            outp = tswapal(sel->outp); +            exp = tswapal(sel->exp); +            tvp = tswapal(sel->tvp); +            unlock_user_struct(sel, arg1, 0); +            ret = do_select(nsel, inp, outp, exp, tvp); +        } +#endif +        break; +#endif +#ifdef TARGET_NR_pselect6 +    case TARGET_NR_pselect6: +        { +            abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr; +            fd_set rfds, wfds, efds; +            fd_set *rfds_ptr, *wfds_ptr, *efds_ptr; +            struct timespec ts, *ts_ptr; + +            /* +             * The 6th arg is actually two args smashed together, +             * so we cannot use the C library. +             */ +            sigset_t set; +            struct { +                sigset_t *set; +                size_t size; +            } sig, *sig_ptr; + +            abi_ulong arg_sigset, arg_sigsize, *arg7; +            target_sigset_t *target_sigset; + +            n = arg1; +            rfd_addr = arg2; +            wfd_addr = arg3; +            efd_addr = arg4; +            ts_addr = arg5; + +            ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n); +            if (ret) { +                goto fail; +            } +            ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n); +            if (ret) { +                goto fail; +            } +            ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n); +            if (ret) { +                goto fail; +            } + +            /* +             * This takes a timespec, and not a timeval, so we cannot +             * use the do_select() helper ... +             */ +            if (ts_addr) { +                if (target_to_host_timespec(&ts, ts_addr)) { +                    goto efault; +                } +                ts_ptr = &ts; +            } else { +                ts_ptr = NULL; +            } + +            /* Extract the two packed args for the sigset */ +            if (arg6) { +                sig_ptr = &sig; +                sig.size = _NSIG / 8; + +                arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1); +                if (!arg7) { +                    goto efault; +                } +                arg_sigset = tswapal(arg7[0]); +                arg_sigsize = tswapal(arg7[1]); +                unlock_user(arg7, arg6, 0); + +                if (arg_sigset) { +                    sig.set = &set; +                    if (arg_sigsize != sizeof(*target_sigset)) { +                        /* Like the kernel, we enforce correct size sigsets */ +                        ret = -TARGET_EINVAL; +                        goto fail; +                    } +                    target_sigset = lock_user(VERIFY_READ, arg_sigset, +                                              sizeof(*target_sigset), 1); +                    if (!target_sigset) { +                        goto efault; +                    } +                    target_to_host_sigset(&set, target_sigset); +                    unlock_user(target_sigset, arg_sigset, 0); +                } else { +                    sig.set = NULL; +                } +            } else { +                sig_ptr = NULL; +            } + +            ret = get_errno(sys_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr, +                                         ts_ptr, sig_ptr)); + +            if (!is_error(ret)) { +                if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) +                    goto efault; +                if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n)) +                    goto efault; +                if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n)) +                    goto efault; + +                if (ts_addr && host_to_target_timespec(ts_addr, &ts)) +                    goto efault; +            } +        } +        break; +#endif +    case TARGET_NR_symlink: +        { +            void *p2; +            p = lock_user_string(arg1); +            p2 = lock_user_string(arg2); +            if (!p || !p2) +                ret = -TARGET_EFAULT; +            else +                ret = get_errno(symlink(p, p2)); +            unlock_user(p2, arg2, 0); +            unlock_user(p, arg1, 0); +        } +        break; +#if defined(TARGET_NR_symlinkat) +    case TARGET_NR_symlinkat: +        { +            void *p2; +            p  = lock_user_string(arg1); +            p2 = lock_user_string(arg3); +            if (!p || !p2) +                ret = -TARGET_EFAULT; +            else +                ret = get_errno(symlinkat(p, arg2, p2)); +            unlock_user(p2, arg3, 0); +            unlock_user(p, arg1, 0); +        } +        break; +#endif +#ifdef TARGET_NR_oldlstat +    case TARGET_NR_oldlstat: +        goto unimplemented; +#endif +    case TARGET_NR_readlink: +        { +            void *p2; +            p = lock_user_string(arg1); +            p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0); +            if (!p || !p2) { +                ret = -TARGET_EFAULT; +            } else if (!arg3) { +                /* Short circuit this for the magic exe check. */ +                ret = -TARGET_EINVAL; +            } else if (is_proc_myself((const char *)p, "exe")) { +                char real[PATH_MAX], *temp; +                temp = realpath(exec_path, real); +                /* Return value is # of bytes that we wrote to the buffer. */ +                if (temp == NULL) { +                    ret = get_errno(-1); +                } else { +                    /* Don't worry about sign mismatch as earlier mapping +                     * logic would have thrown a bad address error. */ +                    ret = MIN(strlen(real), arg3); +                    /* We cannot NUL terminate the string. */ +                    memcpy(p2, real, ret); +                } +            } else { +                ret = get_errno(readlink(path(p), p2, arg3)); +            } +            unlock_user(p2, arg2, ret); +            unlock_user(p, arg1, 0); +        } +        break; +#if defined(TARGET_NR_readlinkat) +    case TARGET_NR_readlinkat: +        { +            void *p2; +            p  = lock_user_string(arg2); +            p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0); +            if (!p || !p2) { +                ret = -TARGET_EFAULT; +            } else if (is_proc_myself((const char *)p, "exe")) { +                char real[PATH_MAX], *temp; +                temp = realpath(exec_path, real); +                ret = temp == NULL ? get_errno(-1) : strlen(real) ; +                snprintf((char *)p2, arg4, "%s", real); +            } else { +                ret = get_errno(readlinkat(arg1, path(p), p2, arg4)); +            } +            unlock_user(p2, arg3, ret); +            unlock_user(p, arg2, 0); +        } +        break; +#endif +#ifdef TARGET_NR_uselib +    case TARGET_NR_uselib: +        goto unimplemented; +#endif +#ifdef TARGET_NR_swapon +    case TARGET_NR_swapon: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(swapon(p, arg2)); +        unlock_user(p, arg1, 0); +        break; +#endif +    case TARGET_NR_reboot: +        if (arg3 == LINUX_REBOOT_CMD_RESTART2) { +           /* arg4 must be ignored in all other cases */ +           p = lock_user_string(arg4); +           if (!p) { +              goto efault; +           } +           ret = get_errno(reboot(arg1, arg2, arg3, p)); +           unlock_user(p, arg4, 0); +        } else { +           ret = get_errno(reboot(arg1, arg2, arg3, NULL)); +        } +        break; +#ifdef TARGET_NR_readdir +    case TARGET_NR_readdir: +        goto unimplemented; +#endif +#ifdef TARGET_NR_mmap +    case TARGET_NR_mmap: +#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \ +    (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \ +    defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \ +    || defined(TARGET_S390X) +        { +            abi_ulong *v; +            abi_ulong v1, v2, v3, v4, v5, v6; +            if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1))) +                goto efault; +            v1 = tswapal(v[0]); +            v2 = tswapal(v[1]); +            v3 = tswapal(v[2]); +            v4 = tswapal(v[3]); +            v5 = tswapal(v[4]); +            v6 = tswapal(v[5]); +            unlock_user(v, arg1, 0); +            ret = get_errno(target_mmap(v1, v2, v3, +                                        target_to_host_bitmask(v4, mmap_flags_tbl), +                                        v5, v6)); +        } +#else +        ret = get_errno(target_mmap(arg1, arg2, arg3, +                                    target_to_host_bitmask(arg4, mmap_flags_tbl), +                                    arg5, +                                    arg6)); +#endif +        break; +#endif +#ifdef TARGET_NR_mmap2 +    case TARGET_NR_mmap2: +#ifndef MMAP_SHIFT +#define MMAP_SHIFT 12 +#endif +        ret = get_errno(target_mmap(arg1, arg2, arg3, +                                    target_to_host_bitmask(arg4, mmap_flags_tbl), +                                    arg5, +                                    arg6 << MMAP_SHIFT)); +        break; +#endif +    case TARGET_NR_munmap: +        ret = get_errno(target_munmap(arg1, arg2)); +        break; +    case TARGET_NR_mprotect: +        { +            TaskState *ts = cpu->opaque; +            /* Special hack to detect libc making the stack executable.  */ +            if ((arg3 & PROT_GROWSDOWN) +                && arg1 >= ts->info->stack_limit +                && arg1 <= ts->info->start_stack) { +                arg3 &= ~PROT_GROWSDOWN; +                arg2 = arg2 + arg1 - ts->info->stack_limit; +                arg1 = ts->info->stack_limit; +            } +        } +        ret = get_errno(target_mprotect(arg1, arg2, arg3)); +        break; +#ifdef TARGET_NR_mremap +    case TARGET_NR_mremap: +        ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5)); +        break; +#endif +        /* ??? msync/mlock/munlock are broken for softmmu.  */ +#ifdef TARGET_NR_msync +    case TARGET_NR_msync: +        ret = get_errno(msync(g2h(arg1), arg2, arg3)); +        break; +#endif +#ifdef TARGET_NR_mlock +    case TARGET_NR_mlock: +        ret = get_errno(mlock(g2h(arg1), arg2)); +        break; +#endif +#ifdef TARGET_NR_munlock +    case TARGET_NR_munlock: +        ret = get_errno(munlock(g2h(arg1), arg2)); +        break; +#endif +#ifdef TARGET_NR_mlockall +    case TARGET_NR_mlockall: +        ret = get_errno(mlockall(target_to_host_mlockall_arg(arg1))); +        break; +#endif +#ifdef TARGET_NR_munlockall +    case TARGET_NR_munlockall: +        ret = get_errno(munlockall()); +        break; +#endif +    case TARGET_NR_truncate: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(truncate(p, arg2)); +        unlock_user(p, arg1, 0); +        break; +    case TARGET_NR_ftruncate: +        ret = get_errno(ftruncate(arg1, arg2)); +        break; +    case TARGET_NR_fchmod: +        ret = get_errno(fchmod(arg1, arg2)); +        break; +#if defined(TARGET_NR_fchmodat) +    case TARGET_NR_fchmodat: +        if (!(p = lock_user_string(arg2))) +            goto efault; +        ret = get_errno(fchmodat(arg1, p, arg3, 0)); +        unlock_user(p, arg2, 0); +        break; +#endif +    case TARGET_NR_getpriority: +        /* Note that negative values are valid for getpriority, so we must +           differentiate based on errno settings.  */ +        errno = 0; +        ret = getpriority(arg1, arg2); +        if (ret == -1 && errno != 0) { +            ret = -host_to_target_errno(errno); +            break; +        } +#ifdef TARGET_ALPHA +        /* Return value is the unbiased priority.  Signal no error.  */ +        ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0; +#else +        /* Return value is a biased priority to avoid negative numbers.  */ +        ret = 20 - ret; +#endif +        break; +    case TARGET_NR_setpriority: +        ret = get_errno(setpriority(arg1, arg2, arg3)); +        break; +#ifdef TARGET_NR_profil +    case TARGET_NR_profil: +        goto unimplemented; +#endif +    case TARGET_NR_statfs: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(statfs(path(p), &stfs)); +        unlock_user(p, arg1, 0); +    convert_statfs: +        if (!is_error(ret)) { +            struct target_statfs *target_stfs; + +            if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0)) +                goto efault; +            __put_user(stfs.f_type, &target_stfs->f_type); +            __put_user(stfs.f_bsize, &target_stfs->f_bsize); +            __put_user(stfs.f_blocks, &target_stfs->f_blocks); +            __put_user(stfs.f_bfree, &target_stfs->f_bfree); +            __put_user(stfs.f_bavail, &target_stfs->f_bavail); +            __put_user(stfs.f_files, &target_stfs->f_files); +            __put_user(stfs.f_ffree, &target_stfs->f_ffree); +            __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]); +            __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]); +            __put_user(stfs.f_namelen, &target_stfs->f_namelen); +            __put_user(stfs.f_frsize, &target_stfs->f_frsize); +            memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare)); +            unlock_user_struct(target_stfs, arg2, 1); +        } +        break; +    case TARGET_NR_fstatfs: +        ret = get_errno(fstatfs(arg1, &stfs)); +        goto convert_statfs; +#ifdef TARGET_NR_statfs64 +    case TARGET_NR_statfs64: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(statfs(path(p), &stfs)); +        unlock_user(p, arg1, 0); +    convert_statfs64: +        if (!is_error(ret)) { +            struct target_statfs64 *target_stfs; + +            if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0)) +                goto efault; +            __put_user(stfs.f_type, &target_stfs->f_type); +            __put_user(stfs.f_bsize, &target_stfs->f_bsize); +            __put_user(stfs.f_blocks, &target_stfs->f_blocks); +            __put_user(stfs.f_bfree, &target_stfs->f_bfree); +            __put_user(stfs.f_bavail, &target_stfs->f_bavail); +            __put_user(stfs.f_files, &target_stfs->f_files); +            __put_user(stfs.f_ffree, &target_stfs->f_ffree); +            __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]); +            __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]); +            __put_user(stfs.f_namelen, &target_stfs->f_namelen); +            __put_user(stfs.f_frsize, &target_stfs->f_frsize); +            memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare)); +            unlock_user_struct(target_stfs, arg3, 1); +        } +        break; +    case TARGET_NR_fstatfs64: +        ret = get_errno(fstatfs(arg1, &stfs)); +        goto convert_statfs64; +#endif +#ifdef TARGET_NR_ioperm +    case TARGET_NR_ioperm: +        goto unimplemented; +#endif +#ifdef TARGET_NR_socketcall +    case TARGET_NR_socketcall: +        ret = do_socketcall(arg1, arg2); +        break; +#endif +#ifdef TARGET_NR_accept +    case TARGET_NR_accept: +        ret = do_accept4(arg1, arg2, arg3, 0); +        break; +#endif +#ifdef TARGET_NR_accept4 +    case TARGET_NR_accept4: +#ifdef CONFIG_ACCEPT4 +        ret = do_accept4(arg1, arg2, arg3, arg4); +#else +        goto unimplemented; +#endif +        break; +#endif +#ifdef TARGET_NR_bind +    case TARGET_NR_bind: +        ret = do_bind(arg1, arg2, arg3); +        break; +#endif +#ifdef TARGET_NR_connect +    case TARGET_NR_connect: +        ret = do_connect(arg1, arg2, arg3); +        break; +#endif +#ifdef TARGET_NR_getpeername +    case TARGET_NR_getpeername: +        ret = do_getpeername(arg1, arg2, arg3); +        break; +#endif +#ifdef TARGET_NR_getsockname +    case TARGET_NR_getsockname: +        ret = do_getsockname(arg1, arg2, arg3); +        break; +#endif +#ifdef TARGET_NR_getsockopt +    case TARGET_NR_getsockopt: +        ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5); +        break; +#endif +#ifdef TARGET_NR_listen +    case TARGET_NR_listen: +        ret = get_errno(listen(arg1, arg2)); +        break; +#endif +#ifdef TARGET_NR_recv +    case TARGET_NR_recv: +        ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0); +        break; +#endif +#ifdef TARGET_NR_recvfrom +    case TARGET_NR_recvfrom: +        ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6); +        break; +#endif +#ifdef TARGET_NR_recvmsg +    case TARGET_NR_recvmsg: +        ret = do_sendrecvmsg(arg1, arg2, arg3, 0); +        break; +#endif +#ifdef TARGET_NR_send +    case TARGET_NR_send: +        ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0); +        break; +#endif +#ifdef TARGET_NR_sendmsg +    case TARGET_NR_sendmsg: +        ret = do_sendrecvmsg(arg1, arg2, arg3, 1); +        break; +#endif +#ifdef TARGET_NR_sendmmsg +    case TARGET_NR_sendmmsg: +        ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1); +        break; +    case TARGET_NR_recvmmsg: +        ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0); +        break; +#endif +#ifdef TARGET_NR_sendto +    case TARGET_NR_sendto: +        ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6); +        break; +#endif +#ifdef TARGET_NR_shutdown +    case TARGET_NR_shutdown: +        ret = get_errno(shutdown(arg1, arg2)); +        break; +#endif +#ifdef TARGET_NR_socket +    case TARGET_NR_socket: +        ret = do_socket(arg1, arg2, arg3); +        break; +#endif +#ifdef TARGET_NR_socketpair +    case TARGET_NR_socketpair: +        ret = do_socketpair(arg1, arg2, arg3, arg4); +        break; +#endif +#ifdef TARGET_NR_setsockopt +    case TARGET_NR_setsockopt: +        ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5); +        break; +#endif + +    case TARGET_NR_syslog: +        if (!(p = lock_user_string(arg2))) +            goto efault; +        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; + +            if (arg2) { +                pvalue = &value; +                if (copy_from_user_timeval(&pvalue->it_interval, arg2) +                    || copy_from_user_timeval(&pvalue->it_value, +                                              arg2 + sizeof(struct target_timeval))) +                    goto efault; +            } else { +                pvalue = NULL; +            } +            ret = get_errno(setitimer(arg1, pvalue, &ovalue)); +            if (!is_error(ret) && arg3) { +                if (copy_to_user_timeval(arg3, +                                         &ovalue.it_interval) +                    || copy_to_user_timeval(arg3 + sizeof(struct target_timeval), +                                            &ovalue.it_value)) +                    goto efault; +            } +        } +        break; +    case TARGET_NR_getitimer: +        { +            struct itimerval value; + +            ret = get_errno(getitimer(arg1, &value)); +            if (!is_error(ret) && arg2) { +                if (copy_to_user_timeval(arg2, +                                         &value.it_interval) +                    || copy_to_user_timeval(arg2 + sizeof(struct target_timeval), +                                            &value.it_value)) +                    goto efault; +            } +        } +        break; +    case TARGET_NR_stat: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(stat(path(p), &st)); +        unlock_user(p, arg1, 0); +        goto do_stat; +    case TARGET_NR_lstat: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(lstat(path(p), &st)); +        unlock_user(p, arg1, 0); +        goto do_stat; +    case TARGET_NR_fstat: +        { +            ret = get_errno(fstat(arg1, &st)); +        do_stat: +            if (!is_error(ret)) { +                struct target_stat *target_st; + +                if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0)) +                    goto efault; +                memset(target_st, 0, sizeof(*target_st)); +                __put_user(st.st_dev, &target_st->st_dev); +                __put_user(st.st_ino, &target_st->st_ino); +                __put_user(st.st_mode, &target_st->st_mode); +                __put_user(st.st_uid, &target_st->st_uid); +                __put_user(st.st_gid, &target_st->st_gid); +                __put_user(st.st_nlink, &target_st->st_nlink); +                __put_user(st.st_rdev, &target_st->st_rdev); +                __put_user(st.st_size, &target_st->st_size); +                __put_user(st.st_blksize, &target_st->st_blksize); +                __put_user(st.st_blocks, &target_st->st_blocks); +                __put_user(st.st_atime, &target_st->target_st_atime); +                __put_user(st.st_mtime, &target_st->target_st_mtime); +                __put_user(st.st_ctime, &target_st->target_st_ctime); +                unlock_user_struct(target_st, arg2, 1); +            } +        } +        break; +#ifdef TARGET_NR_olduname +    case TARGET_NR_olduname: +        goto unimplemented; +#endif +#ifdef TARGET_NR_iopl +    case TARGET_NR_iopl: +        goto unimplemented; +#endif +    case TARGET_NR_vhangup: +        ret = get_errno(vhangup()); +        break; +#ifdef TARGET_NR_idle +    case TARGET_NR_idle: +        goto unimplemented; +#endif +#ifdef TARGET_NR_syscall +    case TARGET_NR_syscall: +        ret = do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5, +                         arg6, arg7, arg8, 0); +        break; +#endif +    case TARGET_NR_wait4: +        { +            int status; +            abi_long status_ptr = arg2; +            struct rusage rusage, *rusage_ptr; +            abi_ulong target_rusage = arg4; +            abi_long rusage_err; +            if (target_rusage) +                rusage_ptr = &rusage; +            else +                rusage_ptr = NULL; +            ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr)); +            if (!is_error(ret)) { +                if (status_ptr && ret) { +                    status = host_to_target_waitstatus(status); +                    if (put_user_s32(status, status_ptr)) +                        goto efault; +                } +                if (target_rusage) { +                    rusage_err = host_to_target_rusage(target_rusage, &rusage); +                    if (rusage_err) { +                        ret = rusage_err; +                    } +                } +            } +        } +        break; +#ifdef TARGET_NR_swapoff +    case TARGET_NR_swapoff: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(swapoff(p)); +        unlock_user(p, arg1, 0); +        break; +#endif +    case TARGET_NR_sysinfo: +        { +            struct target_sysinfo *target_value; +            struct sysinfo value; +            ret = get_errno(sysinfo(&value)); +            if (!is_error(ret) && arg1) +            { +                if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0)) +                    goto efault; +                __put_user(value.uptime, &target_value->uptime); +                __put_user(value.loads[0], &target_value->loads[0]); +                __put_user(value.loads[1], &target_value->loads[1]); +                __put_user(value.loads[2], &target_value->loads[2]); +                __put_user(value.totalram, &target_value->totalram); +                __put_user(value.freeram, &target_value->freeram); +                __put_user(value.sharedram, &target_value->sharedram); +                __put_user(value.bufferram, &target_value->bufferram); +                __put_user(value.totalswap, &target_value->totalswap); +                __put_user(value.freeswap, &target_value->freeswap); +                __put_user(value.procs, &target_value->procs); +                __put_user(value.totalhigh, &target_value->totalhigh); +                __put_user(value.freehigh, &target_value->freehigh); +                __put_user(value.mem_unit, &target_value->mem_unit); +                unlock_user_struct(target_value, arg1, 1); +            } +        } +        break; +#ifdef TARGET_NR_ipc +    case TARGET_NR_ipc: +	ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6); +	break; +#endif +#ifdef TARGET_NR_semget +    case TARGET_NR_semget: +        ret = get_errno(semget(arg1, arg2, arg3)); +        break; +#endif +#ifdef TARGET_NR_semop +    case TARGET_NR_semop: +        ret = do_semop(arg1, arg2, arg3); +        break; +#endif +#ifdef TARGET_NR_semctl +    case TARGET_NR_semctl: +        ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4); +        break; +#endif +#ifdef TARGET_NR_msgctl +    case TARGET_NR_msgctl: +        ret = do_msgctl(arg1, arg2, arg3); +        break; +#endif +#ifdef TARGET_NR_msgget +    case TARGET_NR_msgget: +        ret = get_errno(msgget(arg1, arg2)); +        break; +#endif +#ifdef TARGET_NR_msgrcv +    case TARGET_NR_msgrcv: +        ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5); +        break; +#endif +#ifdef TARGET_NR_msgsnd +    case TARGET_NR_msgsnd: +        ret = do_msgsnd(arg1, arg2, arg3, arg4); +        break; +#endif +#ifdef TARGET_NR_shmget +    case TARGET_NR_shmget: +        ret = get_errno(shmget(arg1, arg2, arg3)); +        break; +#endif +#ifdef TARGET_NR_shmctl +    case TARGET_NR_shmctl: +        ret = do_shmctl(arg1, arg2, arg3); +        break; +#endif +#ifdef TARGET_NR_shmat +    case TARGET_NR_shmat: +        ret = do_shmat(arg1, arg2, arg3); +        break; +#endif +#ifdef TARGET_NR_shmdt +    case TARGET_NR_shmdt: +        ret = do_shmdt(arg1); +        break; +#endif +    case TARGET_NR_fsync: +        ret = get_errno(fsync(arg1)); +        break; +    case TARGET_NR_clone: +        /* Linux manages to have three different orderings for its +         * arguments to clone(); the BACKWARDS and BACKWARDS2 defines +         * match the kernel's CONFIG_CLONE_* settings. +         * Microblaze is further special in that it uses a sixth +         * implicit argument to clone for the TLS pointer. +         */ +#if defined(TARGET_MICROBLAZE) +        ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5)); +#elif defined(TARGET_CLONE_BACKWARDS) +        ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5)); +#elif defined(TARGET_CLONE_BACKWARDS2) +        ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4)); +#else +        ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4)); +#endif +        break; +#ifdef __NR_exit_group +        /* new thread calls */ +    case TARGET_NR_exit_group: +#ifdef TARGET_GPROF +        _mcleanup(); +#endif +        gdb_exit(cpu_env, arg1); +        ret = get_errno(exit_group(arg1)); +        break; +#endif +    case TARGET_NR_setdomainname: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(setdomainname(p, arg2)); +        unlock_user(p, arg1, 0); +        break; +    case TARGET_NR_uname: +        /* no need to transcode because we use the linux syscall */ +        { +            struct new_utsname * buf; + +            if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0)) +                goto efault; +            ret = get_errno(sys_uname(buf)); +            if (!is_error(ret)) { +                /* Overrite the native machine name with whatever is being +                   emulated. */ +                strcpy (buf->machine, cpu_to_uname_machine(cpu_env)); +                /* Allow the user to override the reported release.  */ +                if (qemu_uname_release && *qemu_uname_release) +                  strcpy (buf->release, qemu_uname_release); +            } +            unlock_user_struct(buf, arg1, 1); +        } +        break; +#ifdef TARGET_I386 +    case TARGET_NR_modify_ldt: +        ret = do_modify_ldt(cpu_env, arg1, arg2, arg3); +        break; +#if !defined(TARGET_X86_64) +    case TARGET_NR_vm86old: +        goto unimplemented; +    case TARGET_NR_vm86: +        ret = do_vm86(cpu_env, arg1, arg2); +        break; +#endif +#endif +    case TARGET_NR_adjtimex: +        goto unimplemented; +#ifdef TARGET_NR_create_module +    case TARGET_NR_create_module: +#endif +    case TARGET_NR_init_module: +    case TARGET_NR_delete_module: +#ifdef TARGET_NR_get_kernel_syms +    case TARGET_NR_get_kernel_syms: +#endif +        goto unimplemented; +    case TARGET_NR_quotactl: +        goto unimplemented; +    case TARGET_NR_getpgid: +        ret = get_errno(getpgid(arg1)); +        break; +    case TARGET_NR_fchdir: +        ret = get_errno(fchdir(arg1)); +        break; +#ifdef TARGET_NR_bdflush /* not on x86_64 */ +    case TARGET_NR_bdflush: +        goto unimplemented; +#endif +#ifdef TARGET_NR_sysfs +    case TARGET_NR_sysfs: +        goto unimplemented; +#endif +    case TARGET_NR_personality: +        ret = get_errno(personality(arg1)); +        break; +#ifdef TARGET_NR_afs_syscall +    case TARGET_NR_afs_syscall: +        goto unimplemented; +#endif +#ifdef TARGET_NR__llseek /* Not on alpha */ +    case TARGET_NR__llseek: +        { +            int64_t res; +#if !defined(__NR_llseek) +            res = lseek(arg1, ((uint64_t)arg2 << 32) | arg3, arg5); +            if (res == -1) { +                ret = get_errno(res); +            } else { +                ret = 0; +            } +#else +            ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5)); +#endif +            if ((ret == 0) && put_user_s64(res, arg4)) { +                goto efault; +            } +        } +        break; +#endif +    case TARGET_NR_getdents: +#ifdef __NR_getdents +#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64 +        { +            struct target_dirent *target_dirp; +            struct linux_dirent *dirp; +            abi_long count = arg3; + +	    dirp = malloc(count); +	    if (!dirp) { +                ret = -TARGET_ENOMEM; +                goto fail; +            } + +            ret = get_errno(sys_getdents(arg1, dirp, count)); +            if (!is_error(ret)) { +                struct linux_dirent *de; +		struct target_dirent *tde; +                int len = ret; +                int reclen, treclen; +		int count1, tnamelen; + +		count1 = 0; +                de = dirp; +                if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0))) +                    goto efault; +		tde = target_dirp; +                while (len > 0) { +                    reclen = de->d_reclen; +                    tnamelen = reclen - offsetof(struct linux_dirent, d_name); +                    assert(tnamelen >= 0); +                    treclen = tnamelen + offsetof(struct target_dirent, d_name); +                    assert(count1 + treclen <= count); +                    tde->d_reclen = tswap16(treclen); +                    tde->d_ino = tswapal(de->d_ino); +                    tde->d_off = tswapal(de->d_off); +                    memcpy(tde->d_name, de->d_name, tnamelen); +                    de = (struct linux_dirent *)((char *)de + reclen); +                    len -= reclen; +                    tde = (struct target_dirent *)((char *)tde + treclen); +		    count1 += treclen; +                } +		ret = count1; +                unlock_user(target_dirp, arg2, ret); +            } +	    free(dirp); +        } +#else +        { +            struct linux_dirent *dirp; +            abi_long count = arg3; + +            if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0))) +                goto efault; +            ret = get_errno(sys_getdents(arg1, dirp, count)); +            if (!is_error(ret)) { +                struct linux_dirent *de; +                int len = ret; +                int reclen; +                de = dirp; +                while (len > 0) { +                    reclen = de->d_reclen; +                    if (reclen > len) +                        break; +                    de->d_reclen = tswap16(reclen); +                    tswapls(&de->d_ino); +                    tswapls(&de->d_off); +                    de = (struct linux_dirent *)((char *)de + reclen); +                    len -= reclen; +                } +            } +            unlock_user(dirp, arg2, ret); +        } +#endif +#else +        /* Implement getdents in terms of getdents64 */ +        { +            struct linux_dirent64 *dirp; +            abi_long count = arg3; + +            dirp = lock_user(VERIFY_WRITE, arg2, count, 0); +            if (!dirp) { +                goto efault; +            } +            ret = get_errno(sys_getdents64(arg1, dirp, count)); +            if (!is_error(ret)) { +                /* Convert the dirent64 structs to target dirent.  We do this +                 * in-place, since we can guarantee that a target_dirent is no +                 * larger than a dirent64; however this means we have to be +                 * careful to read everything before writing in the new format. +                 */ +                struct linux_dirent64 *de; +                struct target_dirent *tde; +                int len = ret; +                int tlen = 0; + +                de = dirp; +                tde = (struct target_dirent *)dirp; +                while (len > 0) { +                    int namelen, treclen; +                    int reclen = de->d_reclen; +                    uint64_t ino = de->d_ino; +                    int64_t off = de->d_off; +                    uint8_t type = de->d_type; + +                    namelen = strlen(de->d_name); +                    treclen = offsetof(struct target_dirent, d_name) +                        + namelen + 2; +                    treclen = QEMU_ALIGN_UP(treclen, sizeof(abi_long)); + +                    memmove(tde->d_name, de->d_name, namelen + 1); +                    tde->d_ino = tswapal(ino); +                    tde->d_off = tswapal(off); +                    tde->d_reclen = tswap16(treclen); +                    /* The target_dirent type is in what was formerly a padding +                     * byte at the end of the structure: +                     */ +                    *(((char *)tde) + treclen - 1) = type; + +                    de = (struct linux_dirent64 *)((char *)de + reclen); +                    tde = (struct target_dirent *)((char *)tde + treclen); +                    len -= reclen; +                    tlen += treclen; +                } +                ret = tlen; +            } +            unlock_user(dirp, arg2, ret); +        } +#endif +        break; +#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64) +    case TARGET_NR_getdents64: +        { +            struct linux_dirent64 *dirp; +            abi_long count = arg3; +            if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0))) +                goto efault; +            ret = get_errno(sys_getdents64(arg1, dirp, count)); +            if (!is_error(ret)) { +                struct linux_dirent64 *de; +                int len = ret; +                int reclen; +                de = dirp; +                while (len > 0) { +                    reclen = de->d_reclen; +                    if (reclen > len) +                        break; +                    de->d_reclen = tswap16(reclen); +                    tswap64s((uint64_t *)&de->d_ino); +                    tswap64s((uint64_t *)&de->d_off); +                    de = (struct linux_dirent64 *)((char *)de + reclen); +                    len -= reclen; +                } +            } +            unlock_user(dirp, arg2, ret); +        } +        break; +#endif /* TARGET_NR_getdents64 */ +#if defined(TARGET_NR__newselect) +    case TARGET_NR__newselect: +        ret = do_select(arg1, arg2, arg3, arg4, arg5); +        break; +#endif +#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll) +# ifdef TARGET_NR_poll +    case TARGET_NR_poll: +# endif +# ifdef TARGET_NR_ppoll +    case TARGET_NR_ppoll: +# endif +        { +            struct target_pollfd *target_pfd; +            unsigned int nfds = arg2; +            int timeout = arg3; +            struct pollfd *pfd; +            unsigned int i; + +            target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1); +            if (!target_pfd) +                goto efault; + +            pfd = alloca(sizeof(struct pollfd) * nfds); +            for(i = 0; i < nfds; i++) { +                pfd[i].fd = tswap32(target_pfd[i].fd); +                pfd[i].events = tswap16(target_pfd[i].events); +            } + +# ifdef TARGET_NR_ppoll +            if (num == TARGET_NR_ppoll) { +                struct timespec _timeout_ts, *timeout_ts = &_timeout_ts; +                target_sigset_t *target_set; +                sigset_t _set, *set = &_set; + +                if (arg3) { +                    if (target_to_host_timespec(timeout_ts, arg3)) { +                        unlock_user(target_pfd, arg1, 0); +                        goto efault; +                    } +                } else { +                    timeout_ts = NULL; +                } + +                if (arg4) { +                    target_set = lock_user(VERIFY_READ, arg4, sizeof(target_sigset_t), 1); +                    if (!target_set) { +                        unlock_user(target_pfd, arg1, 0); +                        goto efault; +                    } +                    target_to_host_sigset(set, target_set); +                } else { +                    set = NULL; +                } + +                ret = get_errno(sys_ppoll(pfd, nfds, timeout_ts, set, _NSIG/8)); + +                if (!is_error(ret) && arg3) { +                    host_to_target_timespec(arg3, timeout_ts); +                } +                if (arg4) { +                    unlock_user(target_set, arg4, 0); +                } +            } else +# endif +                ret = get_errno(poll(pfd, nfds, timeout)); + +            if (!is_error(ret)) { +                for(i = 0; i < nfds; i++) { +                    target_pfd[i].revents = tswap16(pfd[i].revents); +                } +            } +            unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds); +        } +        break; +#endif +    case TARGET_NR_flock: +        /* NOTE: the flock constant seems to be the same for every +           Linux platform */ +        ret = get_errno(flock(arg1, arg2)); +        break; +    case TARGET_NR_readv: +        { +            struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0); +            if (vec != NULL) { +                ret = get_errno(readv(arg1, vec, arg3)); +                unlock_iovec(vec, arg2, arg3, 1); +            } else { +                ret = -host_to_target_errno(errno); +            } +        } +        break; +    case TARGET_NR_writev: +        { +            struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); +            if (vec != NULL) { +                ret = get_errno(writev(arg1, vec, arg3)); +                unlock_iovec(vec, arg2, arg3, 0); +            } else { +                ret = -host_to_target_errno(errno); +            } +        } +        break; +    case TARGET_NR_getsid: +        ret = get_errno(getsid(arg1)); +        break; +#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */ +    case TARGET_NR_fdatasync: +        ret = get_errno(fdatasync(arg1)); +        break; +#endif +    case TARGET_NR__sysctl: +        /* We don't implement this, but ENOTDIR is always a safe +           return value. */ +        ret = -TARGET_ENOTDIR; +        break; +    case TARGET_NR_sched_getaffinity: +        { +            unsigned int mask_size; +            unsigned long *mask; + +            /* +             * sched_getaffinity needs multiples of ulong, so need to take +             * care of mismatches between target ulong and host ulong sizes. +             */ +            if (arg2 & (sizeof(abi_ulong) - 1)) { +                ret = -TARGET_EINVAL; +                break; +            } +            mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1); + +            mask = alloca(mask_size); +            ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask)); + +            if (!is_error(ret)) { +                if (ret > arg2) { +                    /* More data returned than the caller's buffer will fit. +                     * This only happens if sizeof(abi_long) < sizeof(long) +                     * and the caller passed us a buffer holding an odd number +                     * of abi_longs. If the host kernel is actually using the +                     * extra 4 bytes then fail EINVAL; otherwise we can just +                     * ignore them and only copy the interesting part. +                     */ +                    int numcpus = sysconf(_SC_NPROCESSORS_CONF); +                    if (numcpus > arg2 * 8) { +                        ret = -TARGET_EINVAL; +                        break; +                    } +                    ret = arg2; +                } + +                if (copy_to_user(arg3, mask, ret)) { +                    goto efault; +                } +            } +        } +        break; +    case TARGET_NR_sched_setaffinity: +        { +            unsigned int mask_size; +            unsigned long *mask; + +            /* +             * sched_setaffinity needs multiples of ulong, so need to take +             * care of mismatches between target ulong and host ulong sizes. +             */ +            if (arg2 & (sizeof(abi_ulong) - 1)) { +                ret = -TARGET_EINVAL; +                break; +            } +            mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1); + +            mask = alloca(mask_size); +            if (!lock_user_struct(VERIFY_READ, p, arg3, 1)) { +                goto efault; +            } +            memcpy(mask, p, arg2); +            unlock_user_struct(p, arg2, 0); + +            ret = get_errno(sys_sched_setaffinity(arg1, mask_size, mask)); +        } +        break; +    case TARGET_NR_sched_setparam: +        { +            struct sched_param *target_schp; +            struct sched_param schp; + +            if (arg2 == 0) { +                return -TARGET_EINVAL; +            } +            if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1)) +                goto efault; +            schp.sched_priority = tswap32(target_schp->sched_priority); +            unlock_user_struct(target_schp, arg2, 0); +            ret = get_errno(sched_setparam(arg1, &schp)); +        } +        break; +    case TARGET_NR_sched_getparam: +        { +            struct sched_param *target_schp; +            struct sched_param schp; + +            if (arg2 == 0) { +                return -TARGET_EINVAL; +            } +            ret = get_errno(sched_getparam(arg1, &schp)); +            if (!is_error(ret)) { +                if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0)) +                    goto efault; +                target_schp->sched_priority = tswap32(schp.sched_priority); +                unlock_user_struct(target_schp, arg2, 1); +            } +        } +        break; +    case TARGET_NR_sched_setscheduler: +        { +            struct sched_param *target_schp; +            struct sched_param schp; +            if (arg3 == 0) { +                return -TARGET_EINVAL; +            } +            if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1)) +                goto efault; +            schp.sched_priority = tswap32(target_schp->sched_priority); +            unlock_user_struct(target_schp, arg3, 0); +            ret = get_errno(sched_setscheduler(arg1, arg2, &schp)); +        } +        break; +    case TARGET_NR_sched_getscheduler: +        ret = get_errno(sched_getscheduler(arg1)); +        break; +    case TARGET_NR_sched_yield: +        ret = get_errno(sched_yield()); +        break; +    case TARGET_NR_sched_get_priority_max: +        ret = get_errno(sched_get_priority_max(arg1)); +        break; +    case TARGET_NR_sched_get_priority_min: +        ret = get_errno(sched_get_priority_min(arg1)); +        break; +    case TARGET_NR_sched_rr_get_interval: +        { +            struct timespec ts; +            ret = get_errno(sched_rr_get_interval(arg1, &ts)); +            if (!is_error(ret)) { +                ret = host_to_target_timespec(arg2, &ts); +            } +        } +        break; +    case TARGET_NR_nanosleep: +        { +            struct timespec req, rem; +            target_to_host_timespec(&req, arg1); +            ret = get_errno(nanosleep(&req, &rem)); +            if (is_error(ret) && arg2) { +                host_to_target_timespec(arg2, &rem); +            } +        } +        break; +#ifdef TARGET_NR_query_module +    case TARGET_NR_query_module: +        goto unimplemented; +#endif +#ifdef TARGET_NR_nfsservctl +    case TARGET_NR_nfsservctl: +        goto unimplemented; +#endif +    case TARGET_NR_prctl: +        switch (arg1) { +        case PR_GET_PDEATHSIG: +        { +            int deathsig; +            ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5)); +            if (!is_error(ret) && arg2 +                && put_user_ual(deathsig, arg2)) { +                goto efault; +            } +            break; +        } +#ifdef PR_GET_NAME +        case PR_GET_NAME: +        { +            void *name = lock_user(VERIFY_WRITE, arg2, 16, 1); +            if (!name) { +                goto efault; +            } +            ret = get_errno(prctl(arg1, (unsigned long)name, +                                  arg3, arg4, arg5)); +            unlock_user(name, arg2, 16); +            break; +        } +        case PR_SET_NAME: +        { +            void *name = lock_user(VERIFY_READ, arg2, 16, 1); +            if (!name) { +                goto efault; +            } +            ret = get_errno(prctl(arg1, (unsigned long)name, +                                  arg3, arg4, arg5)); +            unlock_user(name, arg2, 0); +            break; +        } +#endif +        default: +            /* Most prctl options have no pointer arguments */ +            ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5)); +            break; +        } +        break; +#ifdef TARGET_NR_arch_prctl +    case TARGET_NR_arch_prctl: +#if defined(TARGET_I386) && !defined(TARGET_ABI32) +        ret = do_arch_prctl(cpu_env, arg1, arg2); +        break; +#else +        goto unimplemented; +#endif +#endif +#ifdef TARGET_NR_pread64 +    case TARGET_NR_pread64: +        if (regpairs_aligned(cpu_env)) { +            arg4 = arg5; +            arg5 = arg6; +        } +        if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) +            goto efault; +        ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5))); +        unlock_user(p, arg2, ret); +        break; +    case TARGET_NR_pwrite64: +        if (regpairs_aligned(cpu_env)) { +            arg4 = arg5; +            arg5 = arg6; +        } +        if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) +            goto efault; +        ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5))); +        unlock_user(p, arg2, 0); +        break; +#endif +    case TARGET_NR_getcwd: +        if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0))) +            goto efault; +        ret = get_errno(sys_getcwd1(p, arg2)); +        unlock_user(p, arg1, ret); +        break; +    case TARGET_NR_capget: +    case TARGET_NR_capset: +    { +        struct target_user_cap_header *target_header; +        struct target_user_cap_data *target_data = NULL; +        struct __user_cap_header_struct header; +        struct __user_cap_data_struct data[2]; +        struct __user_cap_data_struct *dataptr = NULL; +        int i, target_datalen; +        int data_items = 1; + +        if (!lock_user_struct(VERIFY_WRITE, target_header, arg1, 1)) { +            goto efault; +        } +        header.version = tswap32(target_header->version); +        header.pid = tswap32(target_header->pid); + +        if (header.version != _LINUX_CAPABILITY_VERSION) { +            /* Version 2 and up takes pointer to two user_data structs */ +            data_items = 2; +        } + +        target_datalen = sizeof(*target_data) * data_items; + +        if (arg2) { +            if (num == TARGET_NR_capget) { +                target_data = lock_user(VERIFY_WRITE, arg2, target_datalen, 0); +            } else { +                target_data = lock_user(VERIFY_READ, arg2, target_datalen, 1); +            } +            if (!target_data) { +                unlock_user_struct(target_header, arg1, 0); +                goto efault; +            } + +            if (num == TARGET_NR_capset) { +                for (i = 0; i < data_items; i++) { +                    data[i].effective = tswap32(target_data[i].effective); +                    data[i].permitted = tswap32(target_data[i].permitted); +                    data[i].inheritable = tswap32(target_data[i].inheritable); +                } +            } + +            dataptr = data; +        } + +        if (num == TARGET_NR_capget) { +            ret = get_errno(capget(&header, dataptr)); +        } else { +            ret = get_errno(capset(&header, dataptr)); +        } + +        /* The kernel always updates version for both capget and capset */ +        target_header->version = tswap32(header.version); +        unlock_user_struct(target_header, arg1, 1); + +        if (arg2) { +            if (num == TARGET_NR_capget) { +                for (i = 0; i < data_items; i++) { +                    target_data[i].effective = tswap32(data[i].effective); +                    target_data[i].permitted = tswap32(data[i].permitted); +                    target_data[i].inheritable = tswap32(data[i].inheritable); +                } +                unlock_user(target_data, arg2, target_datalen); +            } else { +                unlock_user(target_data, arg2, 0); +            } +        } +        break; +    } +    case TARGET_NR_sigaltstack: +#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \ +    defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA) || \ +    defined(TARGET_M68K) || defined(TARGET_S390X) || defined(TARGET_OPENRISC) +        ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUArchState *)cpu_env)); +        break; +#else +        goto unimplemented; +#endif + +#ifdef CONFIG_SENDFILE +    case TARGET_NR_sendfile: +    { +        off_t *offp = NULL; +        off_t off; +        if (arg3) { +            ret = get_user_sal(off, arg3); +            if (is_error(ret)) { +                break; +            } +            offp = &off; +        } +        ret = get_errno(sendfile(arg1, arg2, offp, arg4)); +        if (!is_error(ret) && arg3) { +            abi_long ret2 = put_user_sal(off, arg3); +            if (is_error(ret2)) { +                ret = ret2; +            } +        } +        break; +    } +#ifdef TARGET_NR_sendfile64 +    case TARGET_NR_sendfile64: +    { +        off_t *offp = NULL; +        off_t off; +        if (arg3) { +            ret = get_user_s64(off, arg3); +            if (is_error(ret)) { +                break; +            } +            offp = &off; +        } +        ret = get_errno(sendfile(arg1, arg2, offp, arg4)); +        if (!is_error(ret) && arg3) { +            abi_long ret2 = put_user_s64(off, arg3); +            if (is_error(ret2)) { +                ret = ret2; +            } +        } +        break; +    } +#endif +#else +    case TARGET_NR_sendfile: +#ifdef TARGET_NR_sendfile64 +    case TARGET_NR_sendfile64: +#endif +        goto unimplemented; +#endif + +#ifdef TARGET_NR_getpmsg +    case TARGET_NR_getpmsg: +        goto unimplemented; +#endif +#ifdef TARGET_NR_putpmsg +    case TARGET_NR_putpmsg: +        goto unimplemented; +#endif +#ifdef TARGET_NR_vfork +    case TARGET_NR_vfork: +        ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD, +                        0, 0, 0, 0)); +        break; +#endif +#ifdef TARGET_NR_ugetrlimit +    case TARGET_NR_ugetrlimit: +    { +	struct rlimit rlim; +	int resource = target_to_host_resource(arg1); +	ret = get_errno(getrlimit(resource, &rlim)); +	if (!is_error(ret)) { +	    struct target_rlimit *target_rlim; +            if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0)) +                goto efault; +	    target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur); +	    target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max); +            unlock_user_struct(target_rlim, arg2, 1); +	} +	break; +    } +#endif +#ifdef TARGET_NR_truncate64 +    case TARGET_NR_truncate64: +        if (!(p = lock_user_string(arg1))) +            goto efault; +	ret = target_truncate64(cpu_env, p, arg2, arg3, arg4); +        unlock_user(p, arg1, 0); +	break; +#endif +#ifdef TARGET_NR_ftruncate64 +    case TARGET_NR_ftruncate64: +	ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4); +	break; +#endif +#ifdef TARGET_NR_stat64 +    case TARGET_NR_stat64: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(stat(path(p), &st)); +        unlock_user(p, arg1, 0); +        if (!is_error(ret)) +            ret = host_to_target_stat64(cpu_env, arg2, &st); +        break; +#endif +#ifdef TARGET_NR_lstat64 +    case TARGET_NR_lstat64: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(lstat(path(p), &st)); +        unlock_user(p, arg1, 0); +        if (!is_error(ret)) +            ret = host_to_target_stat64(cpu_env, arg2, &st); +        break; +#endif +#ifdef TARGET_NR_fstat64 +    case TARGET_NR_fstat64: +        ret = get_errno(fstat(arg1, &st)); +        if (!is_error(ret)) +            ret = host_to_target_stat64(cpu_env, arg2, &st); +        break; +#endif +#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) +#ifdef TARGET_NR_fstatat64 +    case TARGET_NR_fstatat64: +#endif +#ifdef TARGET_NR_newfstatat +    case TARGET_NR_newfstatat: +#endif +        if (!(p = lock_user_string(arg2))) +            goto efault; +        ret = get_errno(fstatat(arg1, path(p), &st, arg4)); +        if (!is_error(ret)) +            ret = host_to_target_stat64(cpu_env, arg3, &st); +        break; +#endif +    case TARGET_NR_lchown: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3))); +        unlock_user(p, arg1, 0); +        break; +#ifdef TARGET_NR_getuid +    case TARGET_NR_getuid: +        ret = get_errno(high2lowuid(getuid())); +        break; +#endif +#ifdef TARGET_NR_getgid +    case TARGET_NR_getgid: +        ret = get_errno(high2lowgid(getgid())); +        break; +#endif +#ifdef TARGET_NR_geteuid +    case TARGET_NR_geteuid: +        ret = get_errno(high2lowuid(geteuid())); +        break; +#endif +#ifdef TARGET_NR_getegid +    case TARGET_NR_getegid: +        ret = get_errno(high2lowgid(getegid())); +        break; +#endif +    case TARGET_NR_setreuid: +        ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2))); +        break; +    case TARGET_NR_setregid: +        ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2))); +        break; +    case TARGET_NR_getgroups: +        { +            int gidsetsize = arg1; +            target_id *target_grouplist; +            gid_t *grouplist; +            int i; + +            grouplist = alloca(gidsetsize * sizeof(gid_t)); +            ret = get_errno(getgroups(gidsetsize, grouplist)); +            if (gidsetsize == 0) +                break; +            if (!is_error(ret)) { +                target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * sizeof(target_id), 0); +                if (!target_grouplist) +                    goto efault; +                for(i = 0;i < ret; i++) +                    target_grouplist[i] = tswapid(high2lowgid(grouplist[i])); +                unlock_user(target_grouplist, arg2, gidsetsize * sizeof(target_id)); +            } +        } +        break; +    case TARGET_NR_setgroups: +        { +            int gidsetsize = arg1; +            target_id *target_grouplist; +            gid_t *grouplist = NULL; +            int i; +            if (gidsetsize) { +                grouplist = alloca(gidsetsize * sizeof(gid_t)); +                target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * sizeof(target_id), 1); +                if (!target_grouplist) { +                    ret = -TARGET_EFAULT; +                    goto fail; +                } +                for (i = 0; i < gidsetsize; i++) { +                    grouplist[i] = low2highgid(tswapid(target_grouplist[i])); +                } +                unlock_user(target_grouplist, arg2, 0); +            } +            ret = get_errno(setgroups(gidsetsize, grouplist)); +        } +        break; +    case TARGET_NR_fchown: +        ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3))); +        break; +#if defined(TARGET_NR_fchownat) +    case TARGET_NR_fchownat: +        if (!(p = lock_user_string(arg2)))  +            goto efault; +        ret = get_errno(fchownat(arg1, p, low2highuid(arg3), +                                 low2highgid(arg4), arg5)); +        unlock_user(p, arg2, 0); +        break; +#endif +#ifdef TARGET_NR_setresuid +    case TARGET_NR_setresuid: +        ret = get_errno(setresuid(low2highuid(arg1), +                                  low2highuid(arg2), +                                  low2highuid(arg3))); +        break; +#endif +#ifdef TARGET_NR_getresuid +    case TARGET_NR_getresuid: +        { +            uid_t ruid, euid, suid; +            ret = get_errno(getresuid(&ruid, &euid, &suid)); +            if (!is_error(ret)) { +                if (put_user_id(high2lowuid(ruid), arg1) +                    || put_user_id(high2lowuid(euid), arg2) +                    || put_user_id(high2lowuid(suid), arg3)) +                    goto efault; +            } +        } +        break; +#endif +#ifdef TARGET_NR_getresgid +    case TARGET_NR_setresgid: +        ret = get_errno(setresgid(low2highgid(arg1), +                                  low2highgid(arg2), +                                  low2highgid(arg3))); +        break; +#endif +#ifdef TARGET_NR_getresgid +    case TARGET_NR_getresgid: +        { +            gid_t rgid, egid, sgid; +            ret = get_errno(getresgid(&rgid, &egid, &sgid)); +            if (!is_error(ret)) { +                if (put_user_id(high2lowgid(rgid), arg1) +                    || put_user_id(high2lowgid(egid), arg2) +                    || put_user_id(high2lowgid(sgid), arg3)) +                    goto efault; +            } +        } +        break; +#endif +    case TARGET_NR_chown: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3))); +        unlock_user(p, arg1, 0); +        break; +    case TARGET_NR_setuid: +        ret = get_errno(setuid(low2highuid(arg1))); +        break; +    case TARGET_NR_setgid: +        ret = get_errno(setgid(low2highgid(arg1))); +        break; +    case TARGET_NR_setfsuid: +        ret = get_errno(setfsuid(arg1)); +        break; +    case TARGET_NR_setfsgid: +        ret = get_errno(setfsgid(arg1)); +        break; + +#ifdef TARGET_NR_lchown32 +    case TARGET_NR_lchown32: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(lchown(p, arg2, arg3)); +        unlock_user(p, arg1, 0); +        break; +#endif +#ifdef TARGET_NR_getuid32 +    case TARGET_NR_getuid32: +        ret = get_errno(getuid()); +        break; +#endif + +#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA) +   /* Alpha specific */ +    case TARGET_NR_getxuid: +         { +            uid_t euid; +            euid=geteuid(); +            ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid; +         } +        ret = get_errno(getuid()); +        break; +#endif +#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA) +   /* Alpha specific */ +    case TARGET_NR_getxgid: +         { +            uid_t egid; +            egid=getegid(); +            ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid; +         } +        ret = get_errno(getgid()); +        break; +#endif +#if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA) +    /* Alpha specific */ +    case TARGET_NR_osf_getsysinfo: +        ret = -TARGET_EOPNOTSUPP; +        switch (arg1) { +          case TARGET_GSI_IEEE_FP_CONTROL: +            { +                uint64_t swcr, fpcr = cpu_alpha_load_fpcr (cpu_env); + +                /* Copied from linux ieee_fpcr_to_swcr.  */ +                swcr = (fpcr >> 35) & SWCR_STATUS_MASK; +                swcr |= (fpcr >> 36) & SWCR_MAP_DMZ; +                swcr |= (~fpcr >> 48) & (SWCR_TRAP_ENABLE_INV +                                        | SWCR_TRAP_ENABLE_DZE +                                        | SWCR_TRAP_ENABLE_OVF); +                swcr |= (~fpcr >> 57) & (SWCR_TRAP_ENABLE_UNF +                                        | SWCR_TRAP_ENABLE_INE); +                swcr |= (fpcr >> 47) & SWCR_MAP_UMZ; +                swcr |= (~fpcr >> 41) & SWCR_TRAP_ENABLE_DNO; + +                if (put_user_u64 (swcr, arg2)) +                        goto efault; +                ret = 0; +            } +            break; + +          /* case GSI_IEEE_STATE_AT_SIGNAL: +             -- Not implemented in linux kernel. +             case GSI_UACPROC: +             -- Retrieves current unaligned access state; not much used. +             case GSI_PROC_TYPE: +             -- Retrieves implver information; surely not used. +             case GSI_GET_HWRPB: +             -- Grabs a copy of the HWRPB; surely not used. +          */ +        } +        break; +#endif +#if defined(TARGET_NR_osf_setsysinfo) && defined(TARGET_ALPHA) +    /* Alpha specific */ +    case TARGET_NR_osf_setsysinfo: +        ret = -TARGET_EOPNOTSUPP; +        switch (arg1) { +          case TARGET_SSI_IEEE_FP_CONTROL: +            { +                uint64_t swcr, fpcr, orig_fpcr; + +                if (get_user_u64 (swcr, arg2)) { +                    goto efault; +                } +                orig_fpcr = cpu_alpha_load_fpcr(cpu_env); +                fpcr = orig_fpcr & FPCR_DYN_MASK; + +                /* Copied from linux ieee_swcr_to_fpcr.  */ +                fpcr |= (swcr & SWCR_STATUS_MASK) << 35; +                fpcr |= (swcr & SWCR_MAP_DMZ) << 36; +                fpcr |= (~swcr & (SWCR_TRAP_ENABLE_INV +                                  | SWCR_TRAP_ENABLE_DZE +                                  | SWCR_TRAP_ENABLE_OVF)) << 48; +                fpcr |= (~swcr & (SWCR_TRAP_ENABLE_UNF +                                  | SWCR_TRAP_ENABLE_INE)) << 57; +                fpcr |= (swcr & SWCR_MAP_UMZ ? FPCR_UNDZ | FPCR_UNFD : 0); +                fpcr |= (~swcr & SWCR_TRAP_ENABLE_DNO) << 41; + +                cpu_alpha_store_fpcr(cpu_env, fpcr); +                ret = 0; +            } +            break; + +          case TARGET_SSI_IEEE_RAISE_EXCEPTION: +            { +                uint64_t exc, fpcr, orig_fpcr; +                int si_code; + +                if (get_user_u64(exc, arg2)) { +                    goto efault; +                } + +                orig_fpcr = cpu_alpha_load_fpcr(cpu_env); + +                /* We only add to the exception status here.  */ +                fpcr = orig_fpcr | ((exc & SWCR_STATUS_MASK) << 35); + +                cpu_alpha_store_fpcr(cpu_env, fpcr); +                ret = 0; + +                /* Old exceptions are not signaled.  */ +                fpcr &= ~(orig_fpcr & FPCR_STATUS_MASK); + +                /* If any exceptions set by this call, +                   and are unmasked, send a signal.  */ +                si_code = 0; +                if ((fpcr & (FPCR_INE | FPCR_INED)) == FPCR_INE) { +                    si_code = TARGET_FPE_FLTRES; +                } +                if ((fpcr & (FPCR_UNF | FPCR_UNFD)) == FPCR_UNF) { +                    si_code = TARGET_FPE_FLTUND; +                } +                if ((fpcr & (FPCR_OVF | FPCR_OVFD)) == FPCR_OVF) { +                    si_code = TARGET_FPE_FLTOVF; +                } +                if ((fpcr & (FPCR_DZE | FPCR_DZED)) == FPCR_DZE) { +                    si_code = TARGET_FPE_FLTDIV; +                } +                if ((fpcr & (FPCR_INV | FPCR_INVD)) == FPCR_INV) { +                    si_code = TARGET_FPE_FLTINV; +                } +                if (si_code != 0) { +                    target_siginfo_t info; +                    info.si_signo = SIGFPE; +                    info.si_errno = 0; +                    info.si_code = si_code; +                    info._sifields._sigfault._addr +                        = ((CPUArchState *)cpu_env)->pc; +                    queue_signal((CPUArchState *)cpu_env, info.si_signo, &info); +                } +            } +            break; + +          /* case SSI_NVPAIRS: +             -- Used with SSIN_UACPROC to enable unaligned accesses. +             case SSI_IEEE_STATE_AT_SIGNAL: +             case SSI_IEEE_IGNORE_STATE_AT_SIGNAL: +             -- Not implemented in linux kernel +          */ +        } +        break; +#endif +#ifdef TARGET_NR_osf_sigprocmask +    /* Alpha specific.  */ +    case TARGET_NR_osf_sigprocmask: +        { +            abi_ulong mask; +            int how; +            sigset_t set, oldset; + +            switch(arg1) { +            case TARGET_SIG_BLOCK: +                how = SIG_BLOCK; +                break; +            case TARGET_SIG_UNBLOCK: +                how = SIG_UNBLOCK; +                break; +            case TARGET_SIG_SETMASK: +                how = SIG_SETMASK; +                break; +            default: +                ret = -TARGET_EINVAL; +                goto fail; +            } +            mask = arg2; +            target_to_host_old_sigset(&set, &mask); +            do_sigprocmask(how, &set, &oldset); +            host_to_target_old_sigset(&mask, &oldset); +            ret = mask; +        } +        break; +#endif + +#ifdef TARGET_NR_getgid32 +    case TARGET_NR_getgid32: +        ret = get_errno(getgid()); +        break; +#endif +#ifdef TARGET_NR_geteuid32 +    case TARGET_NR_geteuid32: +        ret = get_errno(geteuid()); +        break; +#endif +#ifdef TARGET_NR_getegid32 +    case TARGET_NR_getegid32: +        ret = get_errno(getegid()); +        break; +#endif +#ifdef TARGET_NR_setreuid32 +    case TARGET_NR_setreuid32: +        ret = get_errno(setreuid(arg1, arg2)); +        break; +#endif +#ifdef TARGET_NR_setregid32 +    case TARGET_NR_setregid32: +        ret = get_errno(setregid(arg1, arg2)); +        break; +#endif +#ifdef TARGET_NR_getgroups32 +    case TARGET_NR_getgroups32: +        { +            int gidsetsize = arg1; +            uint32_t *target_grouplist; +            gid_t *grouplist; +            int i; + +            grouplist = alloca(gidsetsize * sizeof(gid_t)); +            ret = get_errno(getgroups(gidsetsize, grouplist)); +            if (gidsetsize == 0) +                break; +            if (!is_error(ret)) { +                target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0); +                if (!target_grouplist) { +                    ret = -TARGET_EFAULT; +                    goto fail; +                } +                for(i = 0;i < ret; i++) +                    target_grouplist[i] = tswap32(grouplist[i]); +                unlock_user(target_grouplist, arg2, gidsetsize * 4); +            } +        } +        break; +#endif +#ifdef TARGET_NR_setgroups32 +    case TARGET_NR_setgroups32: +        { +            int gidsetsize = arg1; +            uint32_t *target_grouplist; +            gid_t *grouplist; +            int i; + +            grouplist = alloca(gidsetsize * sizeof(gid_t)); +            target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1); +            if (!target_grouplist) { +                ret = -TARGET_EFAULT; +                goto fail; +            } +            for(i = 0;i < gidsetsize; i++) +                grouplist[i] = tswap32(target_grouplist[i]); +            unlock_user(target_grouplist, arg2, 0); +            ret = get_errno(setgroups(gidsetsize, grouplist)); +        } +        break; +#endif +#ifdef TARGET_NR_fchown32 +    case TARGET_NR_fchown32: +        ret = get_errno(fchown(arg1, arg2, arg3)); +        break; +#endif +#ifdef TARGET_NR_setresuid32 +    case TARGET_NR_setresuid32: +        ret = get_errno(setresuid(arg1, arg2, arg3)); +        break; +#endif +#ifdef TARGET_NR_getresuid32 +    case TARGET_NR_getresuid32: +        { +            uid_t ruid, euid, suid; +            ret = get_errno(getresuid(&ruid, &euid, &suid)); +            if (!is_error(ret)) { +                if (put_user_u32(ruid, arg1) +                    || put_user_u32(euid, arg2) +                    || put_user_u32(suid, arg3)) +                    goto efault; +            } +        } +        break; +#endif +#ifdef TARGET_NR_setresgid32 +    case TARGET_NR_setresgid32: +        ret = get_errno(setresgid(arg1, arg2, arg3)); +        break; +#endif +#ifdef TARGET_NR_getresgid32 +    case TARGET_NR_getresgid32: +        { +            gid_t rgid, egid, sgid; +            ret = get_errno(getresgid(&rgid, &egid, &sgid)); +            if (!is_error(ret)) { +                if (put_user_u32(rgid, arg1) +                    || put_user_u32(egid, arg2) +                    || put_user_u32(sgid, arg3)) +                    goto efault; +            } +        } +        break; +#endif +#ifdef TARGET_NR_chown32 +    case TARGET_NR_chown32: +        if (!(p = lock_user_string(arg1))) +            goto efault; +        ret = get_errno(chown(p, arg2, arg3)); +        unlock_user(p, arg1, 0); +        break; +#endif +#ifdef TARGET_NR_setuid32 +    case TARGET_NR_setuid32: +        ret = get_errno(setuid(arg1)); +        break; +#endif +#ifdef TARGET_NR_setgid32 +    case TARGET_NR_setgid32: +        ret = get_errno(setgid(arg1)); +        break; +#endif +#ifdef TARGET_NR_setfsuid32 +    case TARGET_NR_setfsuid32: +        ret = get_errno(setfsuid(arg1)); +        break; +#endif +#ifdef TARGET_NR_setfsgid32 +    case TARGET_NR_setfsgid32: +        ret = get_errno(setfsgid(arg1)); +        break; +#endif + +    case TARGET_NR_pivot_root: +        goto unimplemented; +#ifdef TARGET_NR_mincore +    case TARGET_NR_mincore: +        { +            void *a; +            ret = -TARGET_EFAULT; +            if (!(a = lock_user(VERIFY_READ, arg1,arg2, 0))) +                goto efault; +            if (!(p = lock_user_string(arg3))) +                goto mincore_fail; +            ret = get_errno(mincore(a, arg2, p)); +            unlock_user(p, arg3, ret); +            mincore_fail: +            unlock_user(a, arg1, 0); +        } +        break; +#endif +#ifdef TARGET_NR_arm_fadvise64_64 +    case TARGET_NR_arm_fadvise64_64: +	{ +		/* +		 * arm_fadvise64_64 looks like fadvise64_64 but +		 * with different argument order +		 */ +		abi_long temp; +		temp = arg3; +		arg3 = arg4; +		arg4 = temp; +	} +#endif +#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64) || defined(TARGET_NR_fadvise64) +#ifdef TARGET_NR_fadvise64_64 +    case TARGET_NR_fadvise64_64: +#endif +#ifdef TARGET_NR_fadvise64 +    case TARGET_NR_fadvise64: +#endif +#ifdef TARGET_S390X +        switch (arg4) { +        case 4: arg4 = POSIX_FADV_NOREUSE + 1; break; /* make sure it's an invalid value */ +        case 5: arg4 = POSIX_FADV_NOREUSE + 2; break; /* ditto */ +        case 6: arg4 = POSIX_FADV_DONTNEED; break; +        case 7: arg4 = POSIX_FADV_NOREUSE; break; +        default: break; +        } +#endif +        ret = -posix_fadvise(arg1, arg2, arg3, arg4); +	break; +#endif +#ifdef TARGET_NR_madvise +    case TARGET_NR_madvise: +        /* A straight passthrough may not be safe because qemu sometimes +           turns private file-backed mappings into anonymous mappings. +           This will break MADV_DONTNEED. +           This is a hint, so ignoring and returning success is ok.  */ +        ret = get_errno(0); +        break; +#endif +#if TARGET_ABI_BITS == 32 +    case TARGET_NR_fcntl64: +    { +	int cmd; +	struct flock64 fl; +	struct target_flock64 *target_fl; +#ifdef TARGET_ARM +	struct target_eabi_flock64 *target_efl; +#endif + +	cmd = target_to_host_fcntl_cmd(arg2); +        if (cmd == -TARGET_EINVAL) { +            ret = cmd; +            break; +        } + +        switch(arg2) { +        case TARGET_F_GETLK64: +#ifdef TARGET_ARM +            if (((CPUARMState *)cpu_env)->eabi) { +                if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))  +                    goto efault; +                fl.l_type = tswap16(target_efl->l_type); +                fl.l_whence = tswap16(target_efl->l_whence); +                fl.l_start = tswap64(target_efl->l_start); +                fl.l_len = tswap64(target_efl->l_len); +                fl.l_pid = tswap32(target_efl->l_pid); +                unlock_user_struct(target_efl, arg3, 0); +            } else +#endif +            { +                if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))  +                    goto efault; +                fl.l_type = tswap16(target_fl->l_type); +                fl.l_whence = tswap16(target_fl->l_whence); +                fl.l_start = tswap64(target_fl->l_start); +                fl.l_len = tswap64(target_fl->l_len); +                fl.l_pid = tswap32(target_fl->l_pid); +                unlock_user_struct(target_fl, arg3, 0); +            } +            ret = get_errno(fcntl(arg1, cmd, &fl)); +	    if (ret == 0) { +#ifdef TARGET_ARM +                if (((CPUARMState *)cpu_env)->eabi) { +                    if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))  +                        goto efault; +                    target_efl->l_type = tswap16(fl.l_type); +                    target_efl->l_whence = tswap16(fl.l_whence); +                    target_efl->l_start = tswap64(fl.l_start); +                    target_efl->l_len = tswap64(fl.l_len); +                    target_efl->l_pid = tswap32(fl.l_pid); +                    unlock_user_struct(target_efl, arg3, 1); +                } else +#endif +                { +                    if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))  +                        goto efault; +                    target_fl->l_type = tswap16(fl.l_type); +                    target_fl->l_whence = tswap16(fl.l_whence); +                    target_fl->l_start = tswap64(fl.l_start); +                    target_fl->l_len = tswap64(fl.l_len); +                    target_fl->l_pid = tswap32(fl.l_pid); +                    unlock_user_struct(target_fl, arg3, 1); +                } +	    } +	    break; + +        case TARGET_F_SETLK64: +        case TARGET_F_SETLKW64: +#ifdef TARGET_ARM +            if (((CPUARMState *)cpu_env)->eabi) { +                if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))  +                    goto efault; +                fl.l_type = tswap16(target_efl->l_type); +                fl.l_whence = tswap16(target_efl->l_whence); +                fl.l_start = tswap64(target_efl->l_start); +                fl.l_len = tswap64(target_efl->l_len); +                fl.l_pid = tswap32(target_efl->l_pid); +                unlock_user_struct(target_efl, arg3, 0); +            } else +#endif +            { +                if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))  +                    goto efault; +                fl.l_type = tswap16(target_fl->l_type); +                fl.l_whence = tswap16(target_fl->l_whence); +                fl.l_start = tswap64(target_fl->l_start); +                fl.l_len = tswap64(target_fl->l_len); +                fl.l_pid = tswap32(target_fl->l_pid); +                unlock_user_struct(target_fl, arg3, 0); +            } +            ret = get_errno(fcntl(arg1, cmd, &fl)); +	    break; +        default: +            ret = do_fcntl(arg1, arg2, arg3); +            break; +        } +	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; +#endif +#ifdef TARGET_NR_getpagesize +    case TARGET_NR_getpagesize: +        ret = TARGET_PAGE_SIZE; +        break; +#endif +    case TARGET_NR_gettid: +        ret = get_errno(gettid()); +        break; +#ifdef TARGET_NR_readahead +    case TARGET_NR_readahead: +#if TARGET_ABI_BITS == 32 +        if (regpairs_aligned(cpu_env)) { +            arg2 = arg3; +            arg3 = arg4; +            arg4 = arg5; +        } +        ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4)); +#else +        ret = get_errno(readahead(arg1, arg2, arg3)); +#endif +        break; +#endif +#ifdef CONFIG_ATTR +#ifdef TARGET_NR_setxattr +    case TARGET_NR_listxattr: +    case TARGET_NR_llistxattr: +    { +        void *p, *b = 0; +        if (arg2) { +            b = lock_user(VERIFY_WRITE, arg2, arg3, 0); +            if (!b) { +                ret = -TARGET_EFAULT; +                break; +            } +        } +        p = lock_user_string(arg1); +        if (p) { +            if (num == TARGET_NR_listxattr) { +                ret = get_errno(listxattr(p, b, arg3)); +            } else { +                ret = get_errno(llistxattr(p, b, arg3)); +            } +        } else { +            ret = -TARGET_EFAULT; +        } +        unlock_user(p, arg1, 0); +        unlock_user(b, arg2, arg3); +        break; +    } +    case TARGET_NR_flistxattr: +    { +        void *b = 0; +        if (arg2) { +            b = lock_user(VERIFY_WRITE, arg2, arg3, 0); +            if (!b) { +                ret = -TARGET_EFAULT; +                break; +            } +        } +        ret = get_errno(flistxattr(arg1, b, arg3)); +        unlock_user(b, arg2, arg3); +        break; +    } +    case TARGET_NR_setxattr: +    case TARGET_NR_lsetxattr: +        { +            void *p, *n, *v = 0; +            if (arg3) { +                v = lock_user(VERIFY_READ, arg3, arg4, 1); +                if (!v) { +                    ret = -TARGET_EFAULT; +                    break; +                } +            } +            p = lock_user_string(arg1); +            n = lock_user_string(arg2); +            if (p && n) { +                if (num == TARGET_NR_setxattr) { +                    ret = get_errno(setxattr(p, n, v, arg4, arg5)); +                } else { +                    ret = get_errno(lsetxattr(p, n, v, arg4, arg5)); +                } +            } else { +                ret = -TARGET_EFAULT; +            } +            unlock_user(p, arg1, 0); +            unlock_user(n, arg2, 0); +            unlock_user(v, arg3, 0); +        } +        break; +    case TARGET_NR_fsetxattr: +        { +            void *n, *v = 0; +            if (arg3) { +                v = lock_user(VERIFY_READ, arg3, arg4, 1); +                if (!v) { +                    ret = -TARGET_EFAULT; +                    break; +                } +            } +            n = lock_user_string(arg2); +            if (n) { +                ret = get_errno(fsetxattr(arg1, n, v, arg4, arg5)); +            } else { +                ret = -TARGET_EFAULT; +            } +            unlock_user(n, arg2, 0); +            unlock_user(v, arg3, 0); +        } +        break; +    case TARGET_NR_getxattr: +    case TARGET_NR_lgetxattr: +        { +            void *p, *n, *v = 0; +            if (arg3) { +                v = lock_user(VERIFY_WRITE, arg3, arg4, 0); +                if (!v) { +                    ret = -TARGET_EFAULT; +                    break; +                } +            } +            p = lock_user_string(arg1); +            n = lock_user_string(arg2); +            if (p && n) { +                if (num == TARGET_NR_getxattr) { +                    ret = get_errno(getxattr(p, n, v, arg4)); +                } else { +                    ret = get_errno(lgetxattr(p, n, v, arg4)); +                } +            } else { +                ret = -TARGET_EFAULT; +            } +            unlock_user(p, arg1, 0); +            unlock_user(n, arg2, 0); +            unlock_user(v, arg3, arg4); +        } +        break; +    case TARGET_NR_fgetxattr: +        { +            void *n, *v = 0; +            if (arg3) { +                v = lock_user(VERIFY_WRITE, arg3, arg4, 0); +                if (!v) { +                    ret = -TARGET_EFAULT; +                    break; +                } +            } +            n = lock_user_string(arg2); +            if (n) { +                ret = get_errno(fgetxattr(arg1, n, v, arg4)); +            } else { +                ret = -TARGET_EFAULT; +            } +            unlock_user(n, arg2, 0); +            unlock_user(v, arg3, arg4); +        } +        break; +    case TARGET_NR_removexattr: +    case TARGET_NR_lremovexattr: +        { +            void *p, *n; +            p = lock_user_string(arg1); +            n = lock_user_string(arg2); +            if (p && n) { +                if (num == TARGET_NR_removexattr) { +                    ret = get_errno(removexattr(p, n)); +                } else { +                    ret = get_errno(lremovexattr(p, n)); +                } +            } else { +                ret = -TARGET_EFAULT; +            } +            unlock_user(p, arg1, 0); +            unlock_user(n, arg2, 0); +        } +        break; +    case TARGET_NR_fremovexattr: +        { +            void *n; +            n = lock_user_string(arg2); +            if (n) { +                ret = get_errno(fremovexattr(arg1, n)); +            } else { +                ret = -TARGET_EFAULT; +            } +            unlock_user(n, arg2, 0); +        } +        break; +#endif +#endif /* CONFIG_ATTR */ +#ifdef TARGET_NR_set_thread_area +    case TARGET_NR_set_thread_area: +#if defined(TARGET_MIPS) +      ((CPUMIPSState *) cpu_env)->active_tc.CP0_UserLocal = arg1; +      ret = 0; +      break; +#elif defined(TARGET_CRIS) +      if (arg1 & 0xff) +          ret = -TARGET_EINVAL; +      else { +          ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1; +          ret = 0; +      } +      break; +#elif defined(TARGET_I386) && defined(TARGET_ABI32) +      ret = do_set_thread_area(cpu_env, arg1); +      break; +#elif defined(TARGET_M68K) +      { +          TaskState *ts = cpu->opaque; +          ts->tp_value = arg1; +          ret = 0; +          break; +      } +#else +      goto unimplemented_nowarn; +#endif +#endif +#ifdef TARGET_NR_get_thread_area +    case TARGET_NR_get_thread_area: +#if defined(TARGET_I386) && defined(TARGET_ABI32) +        ret = do_get_thread_area(cpu_env, arg1); +        break; +#elif defined(TARGET_M68K) +        { +            TaskState *ts = cpu->opaque; +            ret = ts->tp_value; +            break; +        } +#else +        goto unimplemented_nowarn; +#endif +#endif +#ifdef TARGET_NR_getdomainname +    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 +#ifdef TARGET_NR_clock_nanosleep +    case TARGET_NR_clock_nanosleep: +    { +        struct timespec ts; +        target_to_host_timespec(&ts, arg3); +        ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL)); +        if (arg4) +            host_to_target_timespec(arg4, &ts); + +#if defined(TARGET_PPC) +        /* clock_nanosleep is odd in that it returns positive errno values. +         * On PPC, CR0 bit 3 should be set in such a situation. */ +        if (ret) { +            ((CPUPPCState *)cpu_env)->crf[0] |= 1; +        } +#endif +        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 *)g2h(arg1))); +        break; +#endif + +#if defined(TARGET_NR_tkill) && defined(__NR_tkill) +    case TARGET_NR_tkill: +        ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2))); +        break; +#endif + +#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill) +    case TARGET_NR_tgkill: +	ret = get_errno(sys_tgkill((int)arg1, (int)arg2, +                        target_to_host_signal(arg3))); +	break; +#endif + +#ifdef TARGET_NR_set_robust_list +    case TARGET_NR_set_robust_list: +    case TARGET_NR_get_robust_list: +        /* The ABI for supporting robust futexes has userspace pass +         * the kernel a pointer to a linked list which is updated by +         * userspace after the syscall; the list is walked by the kernel +         * when the thread exits. Since the linked list in QEMU guest +         * memory isn't a valid linked list for the host and we have +         * no way to reliably intercept the thread-death event, we can't +         * support these. Silently return ENOSYS so that guest userspace +         * falls back to a non-robust futex implementation (which should +         * be OK except in the corner case of the guest crashing while +         * holding a mutex that is shared with another process via +         * shared memory). +         */ +        goto unimplemented_nowarn; +#endif + +#if defined(TARGET_NR_utimensat) +    case TARGET_NR_utimensat: +        { +            struct timespec *tsp, ts[2]; +            if (!arg3) { +                tsp = NULL; +            } else { +                target_to_host_timespec(ts, arg3); +                target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec)); +                tsp = ts; +            } +            if (!arg2) +                ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4)); +            else { +                if (!(p = lock_user_string(arg2))) { +                    ret = -TARGET_EFAULT; +                    goto fail; +                } +                ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4)); +                unlock_user(p, arg2, 0); +            } +        } +	break; +#endif +    case TARGET_NR_futex: +        ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6); +        break; +#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init) +    case TARGET_NR_inotify_init: +        ret = get_errno(sys_inotify_init()); +        break; +#endif +#ifdef CONFIG_INOTIFY1 +#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1) +    case TARGET_NR_inotify_init1: +        ret = get_errno(sys_inotify_init1(arg1)); +        break; +#endif +#endif +#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch) +    case TARGET_NR_inotify_add_watch: +        p = lock_user_string(arg2); +        ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3)); +        unlock_user(p, arg2, 0); +        break; +#endif +#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch) +    case TARGET_NR_inotify_rm_watch: +        ret = get_errno(sys_inotify_rm_watch(arg1, arg2)); +        break; +#endif + +#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open) +    case TARGET_NR_mq_open: +        { +            struct mq_attr posix_mq_attr, *attrp; + +            p = lock_user_string(arg1 - 1); +            if (arg4 != 0) { +                copy_from_user_mq_attr (&posix_mq_attr, arg4); +                attrp = &posix_mq_attr; +            } else { +                attrp = 0; +            } +            ret = get_errno(mq_open(p, arg2, arg3, attrp)); +            unlock_user (p, arg1, 0); +        } +        break; + +    case TARGET_NR_mq_unlink: +        p = lock_user_string(arg1 - 1); +        ret = get_errno(mq_unlink(p)); +        unlock_user (p, arg1, 0); +        break; + +    case TARGET_NR_mq_timedsend: +        { +            struct timespec ts; + +            p = lock_user (VERIFY_READ, arg2, arg3, 1); +            if (arg5 != 0) { +                target_to_host_timespec(&ts, arg5); +                ret = get_errno(mq_timedsend(arg1, p, arg3, arg4, &ts)); +                host_to_target_timespec(arg5, &ts); +            } +            else +                ret = get_errno(mq_send(arg1, p, arg3, arg4)); +            unlock_user (p, arg2, arg3); +        } +        break; + +    case TARGET_NR_mq_timedreceive: +        { +            struct timespec ts; +            unsigned int prio; + +            p = lock_user (VERIFY_READ, arg2, arg3, 1); +            if (arg5 != 0) { +                target_to_host_timespec(&ts, arg5); +                ret = get_errno(mq_timedreceive(arg1, p, arg3, &prio, &ts)); +                host_to_target_timespec(arg5, &ts); +            } +            else +                ret = get_errno(mq_receive(arg1, p, arg3, &prio)); +            unlock_user (p, arg2, arg3); +            if (arg4 != 0) +                put_user_u32(prio, arg4); +        } +        break; + +    /* Not implemented for now... */ +/*     case TARGET_NR_mq_notify: */ +/*         break; */ + +    case TARGET_NR_mq_getsetattr: +        { +            struct mq_attr posix_mq_attr_in, posix_mq_attr_out; +            ret = 0; +            if (arg3 != 0) { +                ret = mq_getattr(arg1, &posix_mq_attr_out); +                copy_to_user_mq_attr(arg3, &posix_mq_attr_out); +            } +            if (arg2 != 0) { +                copy_from_user_mq_attr(&posix_mq_attr_in, arg2); +                ret |= mq_setattr(arg1, &posix_mq_attr_in, &posix_mq_attr_out); +            } + +        } +        break; +#endif + +#ifdef CONFIG_SPLICE +#ifdef TARGET_NR_tee +    case TARGET_NR_tee: +        { +            ret = get_errno(tee(arg1,arg2,arg3,arg4)); +        } +        break; +#endif +#ifdef TARGET_NR_splice +    case TARGET_NR_splice: +        { +            loff_t loff_in, loff_out; +            loff_t *ploff_in = NULL, *ploff_out = NULL; +            if (arg2) { +                if (get_user_u64(loff_in, arg2)) { +                    goto efault; +                } +                ploff_in = &loff_in; +            } +            if (arg4) { +                if (get_user_u64(loff_out, arg4)) { +                    goto efault; +                } +                ploff_out = &loff_out; +            } +            ret = get_errno(splice(arg1, ploff_in, arg3, ploff_out, arg5, arg6)); +            if (arg2) { +                if (put_user_u64(loff_in, arg2)) { +                    goto efault; +                } +            } +            if (arg4) { +                if (put_user_u64(loff_out, arg4)) { +                    goto efault; +                } +            } +        } +        break; +#endif +#ifdef TARGET_NR_vmsplice +	case TARGET_NR_vmsplice: +        { +            struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); +            if (vec != NULL) { +                ret = get_errno(vmsplice(arg1, vec, arg3, arg4)); +                unlock_iovec(vec, arg2, arg3, 0); +            } else { +                ret = -host_to_target_errno(errno); +            } +        } +        break; +#endif +#endif /* CONFIG_SPLICE */ +#ifdef CONFIG_EVENTFD +#if defined(TARGET_NR_eventfd) +    case TARGET_NR_eventfd: +        ret = get_errno(eventfd(arg1, 0)); +        break; +#endif +#if defined(TARGET_NR_eventfd2) +    case TARGET_NR_eventfd2: +    { +        int host_flags = arg2 & (~(TARGET_O_NONBLOCK | TARGET_O_CLOEXEC)); +        if (arg2 & TARGET_O_NONBLOCK) { +            host_flags |= O_NONBLOCK; +        } +        if (arg2 & TARGET_O_CLOEXEC) { +            host_flags |= O_CLOEXEC; +        } +        ret = get_errno(eventfd(arg1, host_flags)); +        break; +    } +#endif +#endif /* CONFIG_EVENTFD  */ +#if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate) +    case TARGET_NR_fallocate: +#if TARGET_ABI_BITS == 32 +        ret = get_errno(fallocate(arg1, arg2, target_offset64(arg3, arg4), +                                  target_offset64(arg5, arg6))); +#else +        ret = get_errno(fallocate(arg1, arg2, arg3, arg4)); +#endif +        break; +#endif +#if defined(CONFIG_SYNC_FILE_RANGE) +#if defined(TARGET_NR_sync_file_range) +    case TARGET_NR_sync_file_range: +#if TARGET_ABI_BITS == 32 +#if defined(TARGET_MIPS) +        ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4), +                                        target_offset64(arg5, arg6), arg7)); +#else +        ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3), +                                        target_offset64(arg4, arg5), arg6)); +#endif /* !TARGET_MIPS */ +#else +        ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4)); +#endif +        break; +#endif +#if defined(TARGET_NR_sync_file_range2) +    case TARGET_NR_sync_file_range2: +        /* This is like sync_file_range but the arguments are reordered */ +#if TARGET_ABI_BITS == 32 +        ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4), +                                        target_offset64(arg5, arg6), arg2)); +#else +        ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2)); +#endif +        break; +#endif +#endif +#if defined(CONFIG_EPOLL) +#if defined(TARGET_NR_epoll_create) +    case TARGET_NR_epoll_create: +        ret = get_errno(epoll_create(arg1)); +        break; +#endif +#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1) +    case TARGET_NR_epoll_create1: +        ret = get_errno(epoll_create1(arg1)); +        break; +#endif +#if defined(TARGET_NR_epoll_ctl) +    case TARGET_NR_epoll_ctl: +    { +        struct epoll_event ep; +        struct epoll_event *epp = 0; +        if (arg4) { +            struct target_epoll_event *target_ep; +            if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) { +                goto efault; +            } +            ep.events = tswap32(target_ep->events); +            /* The epoll_data_t union is just opaque data to the kernel, +             * so we transfer all 64 bits across and need not worry what +             * actual data type it is. +             */ +            ep.data.u64 = tswap64(target_ep->data.u64); +            unlock_user_struct(target_ep, arg4, 0); +            epp = &ep; +        } +        ret = get_errno(epoll_ctl(arg1, arg2, arg3, epp)); +        break; +    } +#endif + +#if defined(TARGET_NR_epoll_pwait) && defined(CONFIG_EPOLL_PWAIT) +#define IMPLEMENT_EPOLL_PWAIT +#endif +#if defined(TARGET_NR_epoll_wait) || defined(IMPLEMENT_EPOLL_PWAIT) +#if defined(TARGET_NR_epoll_wait) +    case TARGET_NR_epoll_wait: +#endif +#if defined(IMPLEMENT_EPOLL_PWAIT) +    case TARGET_NR_epoll_pwait: +#endif +    { +        struct target_epoll_event *target_ep; +        struct epoll_event *ep; +        int epfd = arg1; +        int maxevents = arg3; +        int timeout = arg4; + +        target_ep = lock_user(VERIFY_WRITE, arg2, +                              maxevents * sizeof(struct target_epoll_event), 1); +        if (!target_ep) { +            goto efault; +        } + +        ep = alloca(maxevents * sizeof(struct epoll_event)); + +        switch (num) { +#if defined(IMPLEMENT_EPOLL_PWAIT) +        case TARGET_NR_epoll_pwait: +        { +            target_sigset_t *target_set; +            sigset_t _set, *set = &_set; + +            if (arg5) { +                target_set = lock_user(VERIFY_READ, arg5, +                                       sizeof(target_sigset_t), 1); +                if (!target_set) { +                    unlock_user(target_ep, arg2, 0); +                    goto efault; +                } +                target_to_host_sigset(set, target_set); +                unlock_user(target_set, arg5, 0); +            } else { +                set = NULL; +            } + +            ret = get_errno(epoll_pwait(epfd, ep, maxevents, timeout, set)); +            break; +        } +#endif +#if defined(TARGET_NR_epoll_wait) +        case TARGET_NR_epoll_wait: +            ret = get_errno(epoll_wait(epfd, ep, maxevents, timeout)); +            break; +#endif +        default: +            ret = -TARGET_ENOSYS; +        } +        if (!is_error(ret)) { +            int i; +            for (i = 0; i < ret; i++) { +                target_ep[i].events = tswap32(ep[i].events); +                target_ep[i].data.u64 = tswap64(ep[i].data.u64); +            } +        } +        unlock_user(target_ep, arg2, ret * sizeof(struct target_epoll_event)); +        break; +    } +#endif +#endif +#ifdef TARGET_NR_prlimit64 +    case TARGET_NR_prlimit64: +    { +        /* args: pid, resource number, ptr to new rlimit, ptr to old rlimit */ +        struct target_rlimit64 *target_rnew, *target_rold; +        struct host_rlimit64 rnew, rold, *rnewp = 0; +        int resource = target_to_host_resource(arg2); +        if (arg3) { +            if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) { +                goto efault; +            } +            rnew.rlim_cur = tswap64(target_rnew->rlim_cur); +            rnew.rlim_max = tswap64(target_rnew->rlim_max); +            unlock_user_struct(target_rnew, arg3, 0); +            rnewp = &rnew; +        } + +        ret = get_errno(sys_prlimit64(arg1, resource, rnewp, arg4 ? &rold : 0)); +        if (!is_error(ret) && arg4) { +            if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) { +                goto efault; +            } +            target_rold->rlim_cur = tswap64(rold.rlim_cur); +            target_rold->rlim_max = tswap64(rold.rlim_max); +            unlock_user_struct(target_rold, arg4, 1); +        } +        break; +    } +#endif +#ifdef TARGET_NR_gethostname +    case TARGET_NR_gethostname: +    { +        char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0); +        if (name) { +            ret = get_errno(gethostname(name, arg2)); +            unlock_user(name, arg1, arg2); +        } else { +            ret = -TARGET_EFAULT; +        } +        break; +    } +#endif +#ifdef TARGET_NR_atomic_cmpxchg_32 +    case TARGET_NR_atomic_cmpxchg_32: +    { +        /* should use start_exclusive from main.c */ +        abi_ulong mem_value; +        if (get_user_u32(mem_value, arg6)) { +            target_siginfo_t info; +            info.si_signo = SIGSEGV; +            info.si_errno = 0; +            info.si_code = TARGET_SEGV_MAPERR; +            info._sifields._sigfault._addr = arg6; +            queue_signal((CPUArchState *)cpu_env, info.si_signo, &info); +            ret = 0xdeadbeef; + +        } +        if (mem_value == arg2) +            put_user_u32(arg1, arg6); +        ret = mem_value; +        break; +    } +#endif +#ifdef TARGET_NR_atomic_barrier +    case TARGET_NR_atomic_barrier: +    { +        /* Like the kernel implementation and the qemu arm barrier, no-op this? */ +        ret = 0; +        break; +    } +#endif + +#ifdef TARGET_NR_timer_create +    case TARGET_NR_timer_create: +    { +        /* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */ + +        struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL; + +        int clkid = arg1; +        int timer_index = next_free_host_timer(); + +        if (timer_index < 0) { +            ret = -TARGET_EAGAIN; +        } else { +            timer_t *phtimer = g_posix_timers  + timer_index; + +            if (arg2) { +                phost_sevp = &host_sevp; +                ret = target_to_host_sigevent(phost_sevp, arg2); +                if (ret != 0) { +                    break; +                } +            } + +            ret = get_errno(timer_create(clkid, phost_sevp, phtimer)); +            if (ret) { +                phtimer = NULL; +            } else { +                if (put_user(TIMER_MAGIC | timer_index, arg3, target_timer_t)) { +                    goto efault; +                } +            } +        } +        break; +    } +#endif + +#ifdef TARGET_NR_timer_settime +    case TARGET_NR_timer_settime: +    { +        /* args: timer_t timerid, int flags, const struct itimerspec *new_value, +         * struct itimerspec * old_value */ +        target_timer_t timerid = get_timer_id(arg1); + +        if (timerid < 0) { +            ret = timerid; +        } else if (arg3 == 0) { +            ret = -TARGET_EINVAL; +        } else { +            timer_t htimer = g_posix_timers[timerid]; +            struct itimerspec hspec_new = {{0},}, hspec_old = {{0},}; + +            target_to_host_itimerspec(&hspec_new, arg3); +            ret = get_errno( +                          timer_settime(htimer, arg2, &hspec_new, &hspec_old)); +            host_to_target_itimerspec(arg2, &hspec_old); +        } +        break; +    } +#endif + +#ifdef TARGET_NR_timer_gettime +    case TARGET_NR_timer_gettime: +    { +        /* args: timer_t timerid, struct itimerspec *curr_value */ +        target_timer_t timerid = get_timer_id(arg1); + +        if (timerid < 0) { +            ret = timerid; +        } else if (!arg2) { +            ret = -TARGET_EFAULT; +        } else { +            timer_t htimer = g_posix_timers[timerid]; +            struct itimerspec hspec; +            ret = get_errno(timer_gettime(htimer, &hspec)); + +            if (host_to_target_itimerspec(arg2, &hspec)) { +                ret = -TARGET_EFAULT; +            } +        } +        break; +    } +#endif + +#ifdef TARGET_NR_timer_getoverrun +    case TARGET_NR_timer_getoverrun: +    { +        /* args: timer_t timerid */ +        target_timer_t timerid = get_timer_id(arg1); + +        if (timerid < 0) { +            ret = timerid; +        } else { +            timer_t htimer = g_posix_timers[timerid]; +            ret = get_errno(timer_getoverrun(htimer)); +        } +        break; +    } +#endif + +#ifdef TARGET_NR_timer_delete +    case TARGET_NR_timer_delete: +    { +        /* args: timer_t timerid */ +        target_timer_t timerid = get_timer_id(arg1); + +        if (timerid < 0) { +            ret = timerid; +        } else { +            timer_t htimer = g_posix_timers[timerid]; +            ret = get_errno(timer_delete(htimer)); +            g_posix_timers[timerid] = 0; +        } +        break; +    } +#endif + +#if defined(TARGET_NR_timerfd_create) && defined(CONFIG_TIMERFD) +    case TARGET_NR_timerfd_create: +        ret = get_errno(timerfd_create(arg1, +                target_to_host_bitmask(arg2, fcntl_flags_tbl))); +        break; +#endif + +#if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD) +    case TARGET_NR_timerfd_gettime: +        { +            struct itimerspec its_curr; + +            ret = get_errno(timerfd_gettime(arg1, &its_curr)); + +            if (arg2 && host_to_target_itimerspec(arg2, &its_curr)) { +                goto efault; +            } +        } +        break; +#endif + +#if defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD) +    case TARGET_NR_timerfd_settime: +        { +            struct itimerspec its_new, its_old, *p_new; + +            if (arg3) { +                if (target_to_host_itimerspec(&its_new, arg3)) { +                    goto efault; +                } +                p_new = &its_new; +            } else { +                p_new = NULL; +            } + +            ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old)); + +            if (arg4 && host_to_target_itimerspec(arg4, &its_old)) { +                goto efault; +            } +        } +        break; +#endif + +#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get) +    case TARGET_NR_ioprio_get: +        ret = get_errno(ioprio_get(arg1, arg2)); +        break; +#endif + +#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set) +    case TARGET_NR_ioprio_set: +        ret = get_errno(ioprio_set(arg1, arg2, arg3)); +        break; +#endif + +#if defined(TARGET_NR_setns) && defined(CONFIG_SETNS) +    case TARGET_NR_setns: +        ret = get_errno(setns(arg1, arg2)); +        break; +#endif +#if defined(TARGET_NR_unshare) && defined(CONFIG_SETNS) +    case TARGET_NR_unshare: +        ret = get_errno(unshare(arg1)); +        break; +#endif + +    default: +    unimplemented: +        gemu_log("qemu: Unsupported syscall: %d\n", num); +#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname) || defined(TARGET_NR_set_robust_list) +    unimplemented_nowarn: +#endif +        ret = -TARGET_ENOSYS; +        break; +    } +fail: +#ifdef DEBUG +    gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret); +#endif +    if(do_strace) +        print_syscall_ret(num, ret); +    return ret; +efault: +    ret = -TARGET_EFAULT; +    goto fail; +} diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h new file mode 100644 index 00000000..edd5f3c8 --- /dev/null +++ b/linux-user/syscall_defs.h @@ -0,0 +1,2566 @@ +/* common syscall defines for all architectures */ + +/* Note: although the syscall numbers change between architectures, +   most of them stay the same, so we handle it by putting ifdefs if +   necessary */ + +#ifndef SYSCALL_DEFS_H +#define SYSCALL_DEFS_H 1 + + +#include "syscall_nr.h" + +#define SOCKOP_socket           1 +#define SOCKOP_bind             2 +#define SOCKOP_connect          3 +#define SOCKOP_listen           4 +#define SOCKOP_accept           5 +#define SOCKOP_getsockname      6 +#define SOCKOP_getpeername      7 +#define SOCKOP_socketpair       8 +#define SOCKOP_send             9 +#define SOCKOP_recv             10 +#define SOCKOP_sendto           11 +#define SOCKOP_recvfrom         12 +#define SOCKOP_shutdown         13 +#define SOCKOP_setsockopt       14 +#define SOCKOP_getsockopt       15 +#define SOCKOP_sendmsg          16 +#define SOCKOP_recvmsg          17 +#define SOCKOP_accept4          18 + +#define IPCOP_semop		1 +#define IPCOP_semget		2 +#define IPCOP_semctl		3 +#define IPCOP_semtimedop	4 +#define IPCOP_msgsnd		11 +#define IPCOP_msgrcv		12 +#define IPCOP_msgget		13 +#define IPCOP_msgctl		14 +#define IPCOP_shmat		21 +#define IPCOP_shmdt		22 +#define IPCOP_shmget		23 +#define IPCOP_shmctl		24 + +/* + * The following is for compatibility across the various Linux + * platforms.  The i386 ioctl numbering scheme doesn't really enforce + * a type field.  De facto, however, the top 8 bits of the lower 16 + * bits are indeed used as a type field, so we might just as well make + * this explicit here.  Please be sure to use the decoding macros + * below from now on. + */ +#define TARGET_IOC_NRBITS	8 +#define TARGET_IOC_TYPEBITS	8 + +#if defined(TARGET_I386) || (defined(TARGET_ARM) && defined(TARGET_ABI32)) \ +    || defined(TARGET_SPARC) \ +    || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS) +    /* 16 bit uid wrappers emulation */ +#define USE_UID16 +#define target_id uint16_t +#else +#define target_id uint32_t +#endif + +#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \ +    || defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_UNICORE32) \ +    || defined(TARGET_S390X) || defined(TARGET_OPENRISC) + +#define TARGET_IOC_SIZEBITS	14 +#define TARGET_IOC_DIRBITS	2 + +#define TARGET_IOC_NONE	  0U +#define TARGET_IOC_WRITE  1U +#define TARGET_IOC_READ	  2U + +#elif defined(TARGET_PPC) || defined(TARGET_ALPHA) || \ +      defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE) || \ +      defined(TARGET_MIPS) + +#define TARGET_IOC_SIZEBITS	13 +#define TARGET_IOC_DIRBITS	3 + +#define TARGET_IOC_NONE	  1U +#define TARGET_IOC_READ	  2U +#define TARGET_IOC_WRITE  4U + +#else +#error unsupported CPU +#endif + +#define TARGET_IOC_NRMASK	((1 << TARGET_IOC_NRBITS)-1) +#define TARGET_IOC_TYPEMASK	((1 << TARGET_IOC_TYPEBITS)-1) +#define TARGET_IOC_SIZEMASK	((1 << TARGET_IOC_SIZEBITS)-1) +#define TARGET_IOC_DIRMASK	((1 << TARGET_IOC_DIRBITS)-1) + +#define TARGET_IOC_NRSHIFT	0 +#define TARGET_IOC_TYPESHIFT	(TARGET_IOC_NRSHIFT+TARGET_IOC_NRBITS) +#define TARGET_IOC_SIZESHIFT	(TARGET_IOC_TYPESHIFT+TARGET_IOC_TYPEBITS) +#define TARGET_IOC_DIRSHIFT	(TARGET_IOC_SIZESHIFT+TARGET_IOC_SIZEBITS) + +#define TARGET_IOC(dir,type,nr,size) \ +	(((dir)  << TARGET_IOC_DIRSHIFT) | \ +	 ((type) << TARGET_IOC_TYPESHIFT) | \ +	 ((nr)   << TARGET_IOC_NRSHIFT) | \ +	 ((size) << TARGET_IOC_SIZESHIFT)) + +/* used to create numbers */ +#define TARGET_IO(type,nr)		TARGET_IOC(TARGET_IOC_NONE,(type),(nr),0) +#define TARGET_IOR(type,nr,size)	TARGET_IOC(TARGET_IOC_READ,(type),(nr),sizeof(size)) +#define TARGET_IOW(type,nr,size)	TARGET_IOC(TARGET_IOC_WRITE,(type),(nr),sizeof(size)) +#define TARGET_IOWR(type,nr,size)	TARGET_IOC(TARGET_IOC_READ|TARGET_IOC_WRITE,(type),(nr),sizeof(size)) + +/* the size is automatically computed for these defines */ +#define TARGET_IORU(type,nr)	TARGET_IOC(TARGET_IOC_READ,(type),(nr),TARGET_IOC_SIZEMASK) +#define TARGET_IOWU(type,nr)	TARGET_IOC(TARGET_IOC_WRITE,(type),(nr),TARGET_IOC_SIZEMASK) +#define TARGET_IOWRU(type,nr)	TARGET_IOC(TARGET_IOC_READ|TARGET_IOC_WRITE,(type),(nr),TARGET_IOC_SIZEMASK) + +struct target_sockaddr { +    uint16_t sa_family; +    uint8_t sa_data[14]; +}; + +struct target_sockaddr_ll { +    uint16_t sll_family;   /* Always AF_PACKET */ +    uint16_t sll_protocol; /* Physical layer protocol */ +    int      sll_ifindex;  /* Interface number */ +    uint16_t sll_hatype;   /* ARP hardware type */ +    uint8_t  sll_pkttype;  /* Packet type */ +    uint8_t  sll_halen;    /* Length of address */ +    uint8_t  sll_addr[8];  /* Physical layer address */ +}; + +struct target_sock_filter { +    abi_ushort code; +    uint8_t jt; +    uint8_t jf; +    abi_uint k; +}; + +struct target_sock_fprog { +    abi_ushort len; +    abi_ulong filter; +}; + +struct target_in_addr { +    uint32_t s_addr; /* big endian */ +}; + +struct target_ip_mreq { +    struct target_in_addr imr_multiaddr; +    struct target_in_addr imr_address; +}; + +struct target_ip_mreqn { +    struct target_in_addr imr_multiaddr; +    struct target_in_addr imr_address; +    abi_long imr_ifindex; +}; + +struct target_ip_mreq_source { +    /* big endian */ +    uint32_t imr_multiaddr; +    uint32_t imr_interface; +    uint32_t imr_sourceaddr; +}; + +struct target_timeval { +    abi_long tv_sec; +    abi_long tv_usec; +}; + +struct target_timespec { +    abi_long tv_sec; +    abi_long tv_nsec; +}; + +struct target_timezone { +    abi_int tz_minuteswest; +    abi_int tz_dsttime; +}; + +struct target_itimerval { +    struct target_timeval it_interval; +    struct target_timeval it_value; +}; + +struct target_itimerspec { +    struct target_timespec it_interval; +    struct target_timespec it_value; +}; + +typedef abi_long target_clock_t; + +#define TARGET_HZ 100 + +struct target_tms { +    target_clock_t tms_utime; +    target_clock_t tms_stime; +    target_clock_t tms_cutime; +    target_clock_t tms_cstime; +}; + +struct target_utimbuf { +    abi_long actime; +    abi_long modtime; +}; + +struct target_sel_arg_struct { +    abi_long n; +    abi_long inp, outp, exp; +    abi_long tvp; +}; + +struct target_iovec { +    abi_long iov_base;   /* Starting address */ +    abi_long iov_len;   /* Number of bytes */ +}; + +struct target_msghdr { +    abi_long	 msg_name;	 /* Socket name			*/ +    int		 msg_namelen;	 /* Length of name		*/ +    abi_long	 msg_iov;	 /* Data blocks			*/ +    abi_long	 msg_iovlen;	 /* Number of blocks		*/ +    abi_long     msg_control;	 /* Per protocol magic (eg BSD file descriptor passing) */ +    abi_long	 msg_controllen; /* Length of cmsg list */ +    unsigned int msg_flags; +}; + +struct target_cmsghdr { +    abi_long     cmsg_len; +    int          cmsg_level; +    int          cmsg_type; +}; + +#define TARGET_CMSG_DATA(cmsg) ((unsigned char *) ((struct target_cmsghdr *) (cmsg) + 1)) +#define TARGET_CMSG_NXTHDR(mhdr, cmsg) __target_cmsg_nxthdr (mhdr, cmsg) +#define TARGET_CMSG_ALIGN(len) (((len) + sizeof (abi_long) - 1) \ +                               & (size_t) ~(sizeof (abi_long) - 1)) +#define TARGET_CMSG_SPACE(len) (TARGET_CMSG_ALIGN (len) \ +                               + TARGET_CMSG_ALIGN (sizeof (struct target_cmsghdr))) +#define TARGET_CMSG_LEN(len)   (TARGET_CMSG_ALIGN (sizeof (struct target_cmsghdr)) + (len)) + +static __inline__ struct target_cmsghdr * +__target_cmsg_nxthdr (struct target_msghdr *__mhdr, struct target_cmsghdr *__cmsg) +{ +  struct target_cmsghdr *__ptr; + +  __ptr = (struct target_cmsghdr *)((unsigned char *) __cmsg +                                    + TARGET_CMSG_ALIGN (tswapal(__cmsg->cmsg_len))); +  if ((unsigned long)((char *)(__ptr+1) - (char *)(size_t)tswapal(__mhdr->msg_control)) +      > tswapal(__mhdr->msg_controllen)) +    /* No more entries.  */ +    return (struct target_cmsghdr *)0; +  return __cmsg; +} + +struct target_mmsghdr { +    struct target_msghdr msg_hdr;              /* Message header */ +    unsigned int         msg_len;              /* Number of bytes transmitted */ +}; + +struct  target_rusage { +        struct target_timeval ru_utime;        /* user time used */ +        struct target_timeval ru_stime;        /* system time used */ +        abi_long    ru_maxrss;                 /* maximum resident set size */ +        abi_long    ru_ixrss;                  /* integral shared memory size */ +        abi_long    ru_idrss;                  /* integral unshared data size */ +        abi_long    ru_isrss;                  /* integral unshared stack size */ +        abi_long    ru_minflt;                 /* page reclaims */ +        abi_long    ru_majflt;                 /* page faults */ +        abi_long    ru_nswap;                  /* swaps */ +        abi_long    ru_inblock;                /* block input operations */ +        abi_long    ru_oublock;                /* block output operations */ +        abi_long    ru_msgsnd;                 /* messages sent */ +        abi_long    ru_msgrcv;                 /* messages received */ +        abi_long    ru_nsignals;               /* signals received */ +        abi_long    ru_nvcsw;                  /* voluntary context switches */ +        abi_long    ru_nivcsw;                 /* involuntary " */ +}; + +typedef struct { +        int     val[2]; +} kernel_fsid_t; + +struct kernel_statfs { +	int f_type; +	int f_bsize; +	int f_blocks; +	int f_bfree; +	int f_bavail; +	int f_files; +	int f_ffree; +        kernel_fsid_t f_fsid; +	int f_namelen; +	int f_spare[6]; +}; + +struct target_dirent { +        abi_long        d_ino; +        abi_long        d_off; +        unsigned short  d_reclen; +        char            d_name[]; +}; + +struct target_dirent64 { +	uint64_t	d_ino; +	int64_t		d_off; +	unsigned short	d_reclen; +	unsigned char	d_type; +	char		d_name[256]; +}; + + +/* mostly generic signal stuff */ +#define TARGET_SIG_DFL	((abi_long)0)	/* default signal handling */ +#define TARGET_SIG_IGN	((abi_long)1)	/* ignore signal */ +#define TARGET_SIG_ERR	((abi_long)-1)	/* error return from signal */ + +#ifdef TARGET_MIPS +#define TARGET_NSIG	   128 +#else +#define TARGET_NSIG	   64 +#endif +#define TARGET_NSIG_BPW	   TARGET_ABI_BITS +#define TARGET_NSIG_WORDS  (TARGET_NSIG / TARGET_NSIG_BPW) + +typedef struct { +    abi_ulong sig[TARGET_NSIG_WORDS]; +} target_sigset_t; + +#ifdef BSWAP_NEEDED +static inline void tswap_sigset(target_sigset_t *d, const target_sigset_t *s) +{ +    int i; +    for(i = 0;i < TARGET_NSIG_WORDS; i++) +        d->sig[i] = tswapal(s->sig[i]); +} +#else +static inline void tswap_sigset(target_sigset_t *d, const target_sigset_t *s) +{ +    *d = *s; +} +#endif + +static inline void target_siginitset(target_sigset_t *d, abi_ulong set) +{ +    int i; +    d->sig[0] = set; +    for(i = 1;i < TARGET_NSIG_WORDS; i++) +        d->sig[i] = 0; +} + +void host_to_target_sigset(target_sigset_t *d, const sigset_t *s); +void target_to_host_sigset(sigset_t *d, const target_sigset_t *s); +void host_to_target_old_sigset(abi_ulong *old_sigset, +                               const sigset_t *sigset); +void target_to_host_old_sigset(sigset_t *sigset, +                               const abi_ulong *old_sigset); +struct target_sigaction; +int do_sigaction(int sig, const struct target_sigaction *act, +                 struct target_sigaction *oact); + +#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \ +    || defined(TARGET_PPC) || defined(TARGET_MIPS) || defined(TARGET_SH4) \ +    || defined(TARGET_M68K) || defined(TARGET_ALPHA) || defined(TARGET_CRIS) \ +    || defined(TARGET_MICROBLAZE) || defined(TARGET_UNICORE32) \ +    || defined(TARGET_S390X) || defined(TARGET_OPENRISC) + +#if defined(TARGET_SPARC) +#define TARGET_SA_NOCLDSTOP    8u +#define TARGET_SA_NOCLDWAIT    0x100u +#define TARGET_SA_SIGINFO      0x200u +#define TARGET_SA_ONSTACK      1u +#define TARGET_SA_RESTART      2u +#define TARGET_SA_NODEFER      0x20u +#define TARGET_SA_RESETHAND    4u +#elif defined(TARGET_MIPS) +#define TARGET_SA_NOCLDSTOP	0x00000001 +#define TARGET_SA_NOCLDWAIT	0x00010000 +#define TARGET_SA_SIGINFO	0x00000008 +#define TARGET_SA_ONSTACK	0x08000000 +#define TARGET_SA_NODEFER	0x40000000 +#define TARGET_SA_RESTART	0x10000000 +#define TARGET_SA_RESETHAND	0x80000000 +#if !defined(TARGET_ABI_MIPSN32) && !defined(TARGET_ABI_MIPSN64) +#define TARGET_SA_RESTORER	0x04000000	/* Only for O32 */ +#endif +#elif defined(TARGET_OPENRISC) +#define TARGET_SA_NOCLDSTOP    0x00000001 +#define TARGET_SA_NOCLDWAIT    0x00000002 +#define TARGET_SA_SIGINFO      0x00000004 +#define TARGET_SA_ONSTACK      0x08000000 +#define TARGET_SA_RESTART      0x10000000 +#define TARGET_SA_NODEFER      0x40000000 +#define TARGET_SA_RESETHAND    0x80000000 +#elif defined(TARGET_ALPHA) +#define TARGET_SA_ONSTACK	0x00000001 +#define TARGET_SA_RESTART	0x00000002 +#define TARGET_SA_NOCLDSTOP	0x00000004 +#define TARGET_SA_NODEFER	0x00000008 +#define TARGET_SA_RESETHAND	0x00000010 +#define TARGET_SA_NOCLDWAIT	0x00000020 /* not supported yet */ +#define TARGET_SA_SIGINFO	0x00000040 +#else +#define TARGET_SA_NOCLDSTOP	0x00000001 +#define TARGET_SA_NOCLDWAIT	0x00000002 /* not supported yet */ +#define TARGET_SA_SIGINFO	0x00000004 +#define TARGET_SA_ONSTACK	0x08000000 +#define TARGET_SA_RESTART	0x10000000 +#define TARGET_SA_NODEFER	0x40000000 +#define TARGET_SA_RESETHAND	0x80000000 +#define TARGET_SA_RESTORER	0x04000000 +#endif + +#if defined(TARGET_ALPHA) + +#define TARGET_SIGHUP            1 +#define TARGET_SIGINT            2 +#define TARGET_SIGQUIT           3 +#define TARGET_SIGILL            4 +#define TARGET_SIGTRAP           5 +#define TARGET_SIGABRT           6 +#define TARGET_SIGSTKFLT         7 /* actually SIGEMT */ +#define TARGET_SIGFPE            8 +#define TARGET_SIGKILL           9 +#define TARGET_SIGBUS           10 +#define TARGET_SIGSEGV          11 +#define TARGET_SIGSYS           12 +#define TARGET_SIGPIPE          13 +#define TARGET_SIGALRM          14 +#define TARGET_SIGTERM          15 +#define TARGET_SIGURG           16 +#define TARGET_SIGSTOP          17 +#define TARGET_SIGTSTP          18 +#define TARGET_SIGCONT          19 +#define TARGET_SIGCHLD          20 +#define TARGET_SIGTTIN          21 +#define TARGET_SIGTTOU          22 +#define TARGET_SIGIO            23 +#define TARGET_SIGXCPU          24 +#define TARGET_SIGXFSZ          25 +#define TARGET_SIGVTALRM        26 +#define TARGET_SIGPROF          27 +#define TARGET_SIGWINCH         28 +#define TARGET_SIGPWR           29 /* actually SIGINFO */ +#define TARGET_SIGUSR1          30 +#define TARGET_SIGUSR2          31 +#define TARGET_SIGRTMIN         32 + +#define TARGET_SIG_BLOCK         1 +#define TARGET_SIG_UNBLOCK       2 +#define TARGET_SIG_SETMASK       3 + +#elif defined(TARGET_SPARC) + +#define TARGET_SIGHUP		 1 +#define TARGET_SIGINT		 2 +#define TARGET_SIGQUIT		 3 +#define TARGET_SIGILL		 4 +#define TARGET_SIGTRAP		 5 +#define TARGET_SIGABRT		 6 +#define TARGET_SIGIOT		 6 +#define TARGET_SIGSTKFLT	 7 /* actually EMT */ +#define TARGET_SIGFPE		 8 +#define TARGET_SIGKILL		 9 +#define TARGET_SIGBUS		10 +#define TARGET_SIGSEGV		11 +#define TARGET_SIGSYS		12 +#define TARGET_SIGPIPE		13 +#define TARGET_SIGALRM		14 +#define TARGET_SIGTERM		15 +#define TARGET_SIGURG		16 +#define TARGET_SIGSTOP		17 +#define TARGET_SIGTSTP		18 +#define TARGET_SIGCONT		19 +#define TARGET_SIGCHLD		20 +#define TARGET_SIGTTIN		21 +#define TARGET_SIGTTOU		22 +#define TARGET_SIGIO		23 +#define TARGET_SIGXCPU		24 +#define TARGET_SIGXFSZ		25 +#define TARGET_SIGVTALRM	26 +#define TARGET_SIGPROF		27 +#define TARGET_SIGWINCH	        28 +#define TARGET_SIGPWR		29 +#define TARGET_SIGUSR1		30 +#define TARGET_SIGUSR2		31 +#define TARGET_SIGRTMIN         32 + +#define TARGET_SIG_BLOCK          0x01 /* for blocking signals */ +#define TARGET_SIG_UNBLOCK        0x02 /* for unblocking signals */ +#define TARGET_SIG_SETMASK        0x04 /* for setting the signal mask */ + +#elif defined(TARGET_MIPS) + +#define TARGET_SIGHUP		 1	/* Hangup (POSIX).  */ +#define TARGET_SIGINT		 2	/* Interrupt (ANSI).  */ +#define TARGET_SIGQUIT		 3	/* Quit (POSIX).  */ +#define TARGET_SIGILL		 4	/* Illegal instruction (ANSI).  */ +#define TARGET_SIGTRAP		 5	/* Trace trap (POSIX).  */ +#define TARGET_SIGIOT		 6	/* IOT trap (4.2 BSD).  */ +#define TARGET_SIGABRT		 TARGET_SIGIOT	/* Abort (ANSI).  */ +#define TARGET_SIGEMT		 7 +#define TARGET_SIGSTKFLT	 7 /* XXX: incorrect */ +#define TARGET_SIGFPE		 8	/* Floating-point exception (ANSI).  */ +#define TARGET_SIGKILL		 9	/* Kill, unblockable (POSIX).  */ +#define TARGET_SIGBUS		10	/* BUS error (4.2 BSD).  */ +#define TARGET_SIGSEGV		11	/* Segmentation violation (ANSI).  */ +#define TARGET_SIGSYS		12 +#define TARGET_SIGPIPE		13	/* Broken pipe (POSIX).  */ +#define TARGET_SIGALRM		14	/* Alarm clock (POSIX).  */ +#define TARGET_SIGTERM		15	/* Termination (ANSI).  */ +#define TARGET_SIGUSR1		16	/* User-defined signal 1 (POSIX).  */ +#define TARGET_SIGUSR2		17	/* User-defined signal 2 (POSIX).  */ +#define TARGET_SIGCHLD		18	/* Child status has changed (POSIX).  */ +#define TARGET_SIGCLD		TARGET_SIGCHLD	/* Same as TARGET_SIGCHLD (System V).  */ +#define TARGET_SIGPWR		19	/* Power failure restart (System V).  */ +#define TARGET_SIGWINCH	20	/* Window size change (4.3 BSD, Sun).  */ +#define TARGET_SIGURG		21	/* Urgent condition on socket (4.2 BSD).  */ +#define TARGET_SIGIO		22	/* I/O now possible (4.2 BSD).  */ +#define TARGET_SIGPOLL		TARGET_SIGIO	/* Pollable event occurred (System V).  */ +#define TARGET_SIGSTOP		23	/* Stop, unblockable (POSIX).  */ +#define TARGET_SIGTSTP		24	/* Keyboard stop (POSIX).  */ +#define TARGET_SIGCONT		25	/* Continue (POSIX).  */ +#define TARGET_SIGTTIN		26	/* Background read from tty (POSIX).  */ +#define TARGET_SIGTTOU		27	/* Background write to tty (POSIX).  */ +#define TARGET_SIGVTALRM	28	/* Virtual alarm clock (4.2 BSD).  */ +#define TARGET_SIGPROF		29	/* Profiling alarm clock (4.2 BSD).  */ +#define TARGET_SIGXCPU		30	/* CPU limit exceeded (4.2 BSD).  */ +#define TARGET_SIGXFSZ		31	/* File size limit exceeded (4.2 BSD).  */ +#define TARGET_SIGRTMIN         32 + +#define TARGET_SIG_BLOCK	1	/* for blocking signals */ +#define TARGET_SIG_UNBLOCK	2	/* for unblocking signals */ +#define TARGET_SIG_SETMASK	3	/* for setting the signal mask */ + +#else + +/* OpenRISC Using the general signals */ +#define TARGET_SIGHUP		 1 +#define TARGET_SIGINT		 2 +#define TARGET_SIGQUIT		 3 +#define TARGET_SIGILL		 4 +#define TARGET_SIGTRAP		 5 +#define TARGET_SIGABRT		 6 +#define TARGET_SIGIOT		 6 +#define TARGET_SIGBUS		 7 +#define TARGET_SIGFPE		 8 +#define TARGET_SIGKILL		 9 +#define TARGET_SIGUSR1		10 +#define TARGET_SIGSEGV		11 +#define TARGET_SIGUSR2		12 +#define TARGET_SIGPIPE		13 +#define TARGET_SIGALRM		14 +#define TARGET_SIGTERM		15 +#define TARGET_SIGSTKFLT	16 +#define TARGET_SIGCHLD		17 +#define TARGET_SIGCONT		18 +#define TARGET_SIGSTOP		19 +#define TARGET_SIGTSTP		20 +#define TARGET_SIGTTIN		21 +#define TARGET_SIGTTOU		22 +#define TARGET_SIGURG		23 +#define TARGET_SIGXCPU		24 +#define TARGET_SIGXFSZ		25 +#define TARGET_SIGVTALRM	26 +#define TARGET_SIGPROF		27 +#define TARGET_SIGWINCH	        28 +#define TARGET_SIGIO		29 +#define TARGET_SIGPWR		30 +#define TARGET_SIGSYS		31 +#define TARGET_SIGRTMIN         32 + +#define TARGET_SIG_BLOCK          0    /* for blocking signals */ +#define TARGET_SIG_UNBLOCK        1    /* for unblocking signals */ +#define TARGET_SIG_SETMASK        2    /* for setting the signal mask */ + +#endif + +#if defined(TARGET_ALPHA) +struct target_old_sigaction { +    abi_ulong _sa_handler; +    abi_ulong sa_mask; +    int32_t sa_flags; +}; + +struct target_rt_sigaction { +    abi_ulong _sa_handler; +    abi_ulong sa_flags; +    target_sigset_t sa_mask; +}; + +/* This is the struct used inside the kernel.  The ka_restorer +   field comes from the 5th argument to sys_rt_sigaction.  */ +struct target_sigaction { +    abi_ulong _sa_handler; +    abi_ulong sa_flags; +    target_sigset_t sa_mask; +    abi_ulong sa_restorer; +}; +#elif defined(TARGET_MIPS) +struct target_sigaction { +	uint32_t	sa_flags; +#if defined(TARGET_ABI_MIPSN32) +	uint32_t	_sa_handler; +#else +	abi_ulong	_sa_handler; +#endif +	target_sigset_t	sa_mask; +}; +#else +struct target_old_sigaction { +        abi_ulong _sa_handler; +        abi_ulong sa_mask; +        abi_ulong sa_flags; +        abi_ulong sa_restorer; +}; + +struct target_sigaction { +        abi_ulong _sa_handler; +        abi_ulong sa_flags; +        abi_ulong sa_restorer; +        target_sigset_t sa_mask; +}; +#endif + +typedef union target_sigval { +	int sival_int; +        abi_ulong sival_ptr; +} target_sigval_t; +#if 0 +#if defined (TARGET_SPARC) +typedef struct { +	struct { +		abi_ulong psr; +		abi_ulong pc; +		abi_ulong npc; +		abi_ulong y; +		abi_ulong u_regs[16]; /* globals and ins */ +	}		si_regs; +	int		si_mask; +} __siginfo_t; + +typedef struct { +	unsigned   long si_float_regs [32]; +	unsigned   long si_fsr; +	unsigned   long si_fpqdepth; +	struct { +		unsigned long *insn_addr; +		unsigned long insn; +	} si_fpqueue [16]; +} __siginfo_fpu_t; +#endif +#endif + +#define TARGET_SI_MAX_SIZE	128 + +#if TARGET_ABI_BITS == 32 +#define TARGET_SI_PREAMBLE_SIZE (3 * sizeof(int)) +#else +#define TARGET_SI_PREAMBLE_SIZE (4 * sizeof(int)) +#endif + +#define TARGET_SI_PAD_SIZE ((TARGET_SI_MAX_SIZE - TARGET_SI_PREAMBLE_SIZE) / sizeof(int)) + +typedef struct target_siginfo { +#ifdef TARGET_MIPS +	int si_signo; +	int si_code; +	int si_errno; +#else +	int si_signo; +	int si_errno; +	int si_code; +#endif + +	union { +		int _pad[TARGET_SI_PAD_SIZE]; + +		/* kill() */ +		struct { +			pid_t _pid;		/* sender's pid */ +			uid_t _uid;		/* sender's uid */ +		} _kill; + +		/* POSIX.1b timers */ +		struct { +			unsigned int _timer1; +			unsigned int _timer2; +		} _timer; + +		/* POSIX.1b signals */ +		struct { +			pid_t _pid;		/* sender's pid */ +			uid_t _uid;		/* sender's uid */ +			target_sigval_t _sigval; +		} _rt; + +		/* SIGCHLD */ +		struct { +			pid_t _pid;		/* which child */ +			uid_t _uid;		/* sender's uid */ +			int _status;		/* exit code */ +			target_clock_t _utime; +                        target_clock_t _stime; +		} _sigchld; + +		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */ +		struct { +			abi_ulong _addr; /* faulting insn/memory ref. */ +		} _sigfault; + +		/* SIGPOLL */ +		struct { +			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */ +			int _fd; +		} _sigpoll; +	} _sifields; +} target_siginfo_t; + +/* + * si_code values + * Digital reserves positive values for kernel-generated signals. + */ +#define TARGET_SI_USER		0	/* sent by kill, sigsend, raise */ +#define TARGET_SI_KERNEL	0x80	/* sent by the kernel from somewhere */ +#define TARGET_SI_QUEUE	-1		/* sent by sigqueue */ +#define TARGET_SI_TIMER -2              /* sent by timer expiration */ +#define TARGET_SI_MESGQ	-3		/* sent by real time mesq state change */ +#define TARGET_SI_ASYNCIO	-4	/* sent by AIO completion */ +#define TARGET_SI_SIGIO	-5		/* sent by queued SIGIO */ + +/* + * SIGILL si_codes + */ +#define TARGET_ILL_ILLOPC	(1)	/* illegal opcode */ +#define TARGET_ILL_ILLOPN	(2)	/* illegal operand */ +#define TARGET_ILL_ILLADR	(3)	/* illegal addressing mode */ +#define TARGET_ILL_ILLTRP	(4)	/* illegal trap */ +#define TARGET_ILL_PRVOPC	(5)	/* privileged opcode */ +#define TARGET_ILL_PRVREG	(6)	/* privileged register */ +#define TARGET_ILL_COPROC	(7)	/* coprocessor error */ +#define TARGET_ILL_BADSTK	(8)	/* internal stack error */ + +/* + * SIGFPE si_codes + */ +#define TARGET_FPE_INTDIV      (1)  /* integer divide by zero */ +#define TARGET_FPE_INTOVF      (2)  /* integer overflow */ +#define TARGET_FPE_FLTDIV      (3)  /* floating point divide by zero */ +#define TARGET_FPE_FLTOVF      (4)  /* floating point overflow */ +#define TARGET_FPE_FLTUND      (5)  /* floating point underflow */ +#define TARGET_FPE_FLTRES      (6)  /* floating point inexact result */ +#define TARGET_FPE_FLTINV      (7)  /* floating point invalid operation */ +#define TARGET_FPE_FLTSUB      (8)  /* subscript out of range */ +#define TARGET_NSIGFPE         8 + +/* + * SIGSEGV si_codes + */ +#define TARGET_SEGV_MAPERR     (1)  /* address not mapped to object */ +#define TARGET_SEGV_ACCERR     (2)  /* invalid permissions for mapped object */ + +/* + * SIGBUS si_codes + */ +#define TARGET_BUS_ADRALN       (1)	/* invalid address alignment */ +#define TARGET_BUS_ADRERR       (2)	/* non-existent physical address */ +#define TARGET_BUS_OBJERR       (3)	/* object specific hardware error */ + +/* + * SIGTRAP si_codes + */ +#define TARGET_TRAP_BRKPT	(1)	/* process breakpoint */ +#define TARGET_TRAP_TRACE	(2)	/* process trace trap */ + +#endif /* defined(TARGET_I386) || defined(TARGET_ARM) */ + +struct target_rlimit { +        abi_ulong   rlim_cur; +        abi_ulong   rlim_max; +}; + +#if defined(TARGET_ALPHA) +#define TARGET_RLIM_INFINITY	0x7fffffffffffffffull +#elif defined(TARGET_MIPS) || (defined(TARGET_SPARC) && TARGET_ABI_BITS == 32) +#define TARGET_RLIM_INFINITY	0x7fffffffUL +#else +#define TARGET_RLIM_INFINITY	((abi_ulong)-1) +#endif + +#if defined(TARGET_MIPS) +#define TARGET_RLIMIT_CPU		0 +#define TARGET_RLIMIT_FSIZE		1 +#define TARGET_RLIMIT_DATA		2 +#define TARGET_RLIMIT_STACK		3 +#define TARGET_RLIMIT_CORE		4 +#define TARGET_RLIMIT_RSS		7 +#define TARGET_RLIMIT_NPROC		8 +#define TARGET_RLIMIT_NOFILE		5 +#define TARGET_RLIMIT_MEMLOCK		9 +#define TARGET_RLIMIT_AS		6 +#define TARGET_RLIMIT_LOCKS		10 +#define TARGET_RLIMIT_SIGPENDING	11 +#define TARGET_RLIMIT_MSGQUEUE		12 +#define TARGET_RLIMIT_NICE		13 +#define TARGET_RLIMIT_RTPRIO		14 +#else +#define TARGET_RLIMIT_CPU		0 +#define TARGET_RLIMIT_FSIZE		1 +#define TARGET_RLIMIT_DATA		2 +#define TARGET_RLIMIT_STACK		3 +#define TARGET_RLIMIT_CORE		4 +#define TARGET_RLIMIT_RSS		5 +#if defined(TARGET_SPARC) +#define TARGET_RLIMIT_NOFILE		6 +#define TARGET_RLIMIT_NPROC		7 +#else +#define TARGET_RLIMIT_NPROC		6 +#define TARGET_RLIMIT_NOFILE		7 +#endif +#define TARGET_RLIMIT_MEMLOCK		8 +#define TARGET_RLIMIT_AS		9 +#define TARGET_RLIMIT_LOCKS		10 +#define TARGET_RLIMIT_SIGPENDING	11 +#define TARGET_RLIMIT_MSGQUEUE		12 +#define TARGET_RLIMIT_NICE		13 +#define TARGET_RLIMIT_RTPRIO		14 +#endif + +struct target_pollfd { +    int fd;           /* file descriptor */ +    short events;     /* requested events */ +    short revents;    /* returned events */ +}; + +/* virtual terminal ioctls */ +#define TARGET_KIOCSOUND       0x4B2F	/* start sound generation (0 for off) */ +#define TARGET_KDMKTONE	       0x4B30	/* generate tone */ +#define TARGET_KDGKBTYPE       0x4b33 +#define TARGET_KDSETMODE       0x4b3a +#define TARGET_KDGKBMODE       0x4b44 +#define TARGET_KDSKBMODE       0x4b45 +#define TARGET_KDGKBENT	       0x4B46	/* gets one entry in translation table */ +#define TARGET_KDGKBSENT       0x4B48	/* gets one function key string entry */ +#define TARGET_KDGKBLED        0x4B64	/* get led flags (not lights) */ +#define TARGET_KDSKBLED        0x4B65	/* set led flags (not lights) */ +#define TARGET_KDGETLED        0x4B31	/* return current led state */ +#define TARGET_KDSETLED        0x4B32	/* set led state [lights, not flags] */ +#define TARGET_KDSIGACCEPT     0x4B4E + +#define TARGET_SIOCATMARK      0x8905 + +/* Networking ioctls */ +#define TARGET_SIOCADDRT       0x890B          /* add routing table entry */ +#define TARGET_SIOCDELRT       0x890C          /* delete routing table entry */ +#define TARGET_SIOCGIFNAME     0x8910          /* get iface name               */ +#define TARGET_SIOCSIFLINK     0x8911          /* set iface channel            */ +#define TARGET_SIOCGIFCONF     0x8912          /* get iface list               */ +#define TARGET_SIOCGIFFLAGS    0x8913          /* get flags                    */ +#define TARGET_SIOCSIFFLAGS    0x8914          /* set flags                    */ +#define TARGET_SIOCGIFADDR     0x8915          /* get PA address               */ +#define TARGET_SIOCSIFADDR     0x8916          /* set PA address               */ +#define TARGET_SIOCGIFDSTADDR  0x8917          /* get remote PA address        */ +#define TARGET_SIOCSIFDSTADDR  0x8918          /* set remote PA address        */ +#define TARGET_SIOCGIFBRDADDR  0x8919          /* get broadcast PA address     */ +#define TARGET_SIOCSIFBRDADDR  0x891a          /* set broadcast PA address     */ +#define TARGET_SIOCGIFNETMASK  0x891b          /* get network PA mask          */ +#define TARGET_SIOCSIFNETMASK  0x891c          /* set network PA mask          */ +#define TARGET_SIOCGIFMETRIC   0x891d          /* get metric                   */ +#define TARGET_SIOCSIFMETRIC   0x891e          /* set metric                   */ +#define TARGET_SIOCGIFMEM      0x891f          /* get memory address (BSD)     */ +#define TARGET_SIOCSIFMEM      0x8920          /* set memory address (BSD)     */ +#define TARGET_SIOCGIFMTU      0x8921          /* get MTU size                 */ +#define TARGET_SIOCSIFMTU      0x8922          /* set MTU size                 */ +#define TARGET_SIOCSIFHWADDR   0x8924          /* set hardware address (NI)    */ +#define TARGET_SIOCGIFENCAP    0x8925          /* get/set slip encapsulation   */ +#define TARGET_SIOCSIFENCAP    0x8926 +#define TARGET_SIOCGIFHWADDR   0x8927          /* Get hardware address         */ +#define TARGET_SIOCGIFSLAVE    0x8929          /* Driver slaving support       */ +#define TARGET_SIOCSIFSLAVE    0x8930 +#define TARGET_SIOCADDMULTI    0x8931          /* Multicast address lists      */ +#define TARGET_SIOCDELMULTI    0x8932 +#define TARGET_SIOCGIFINDEX    0x8933 + +/* Bridging control calls */ +#define TARGET_SIOCGIFBR       0x8940          /* Bridging support             */ +#define TARGET_SIOCSIFBR       0x8941          /* Set bridging options         */ + +#define TARGET_SIOCGIFTXQLEN   0x8942          /* Get the tx queue length      */ +#define TARGET_SIOCSIFTXQLEN   0x8943          /* Set the tx queue length      */ + +/* ARP cache control calls. */ +#define TARGET_OLD_SIOCDARP    0x8950          /* old delete ARP table entry   */ +#define TARGET_OLD_SIOCGARP    0x8951          /* old get ARP table entry      */ +#define TARGET_OLD_SIOCSARP    0x8952          /* old set ARP table entry      */ +#define TARGET_SIOCDARP        0x8953          /* delete ARP table entry       */ +#define TARGET_SIOCGARP        0x8954          /* get ARP table entry          */ +#define TARGET_SIOCSARP        0x8955          /* set ARP table entry          */ + +/* RARP cache control calls. */ +#define TARGET_SIOCDRARP       0x8960          /* delete RARP table entry      */ +#define TARGET_SIOCGRARP       0x8961          /* get RARP table entry         */ +#define TARGET_SIOCSRARP       0x8962          /* set RARP table entry         */ + +/* Driver configuration calls */ +#define TARGET_SIOCGIFMAP      0x8970          /* Get device parameters        */ +#define TARGET_SIOCSIFMAP      0x8971          /* Set device parameters        */ + +/* DLCI configuration calls */ +#define TARGET_SIOCADDDLCI     0x8980          /* Create new DLCI device       */ +#define TARGET_SIOCDELDLCI     0x8981          /* Delete DLCI device           */ + +/* From <linux/wireless.h> */ + +#define TARGET_SIOCGIWNAME     0x8B01          /* get name == wireless protocol */ + +/* From <linux/fs.h> */ + +#define TARGET_BLKROSET   TARGET_IO(0x12,93) /* set device read-only (0 = read-write) */ +#define TARGET_BLKROGET   TARGET_IO(0x12,94) /* get read-only status (0 = read_write) */ +#define TARGET_BLKRRPART  TARGET_IO(0x12,95) /* re-read partition table */ +#define TARGET_BLKGETSIZE TARGET_IO(0x12,96) /* return device size /512 (long *arg) */ +#define TARGET_BLKFLSBUF  TARGET_IO(0x12,97) /* flush buffer cache */ +#define TARGET_BLKRASET   TARGET_IO(0x12,98) /* Set read ahead for block device */ +#define TARGET_BLKRAGET   TARGET_IO(0x12,99) /* get current read ahead setting */ +#define TARGET_BLKFRASET  TARGET_IO(0x12,100)/* set filesystem (mm/filemap.c) read-ahead */ +#define TARGET_BLKFRAGET  TARGET_IO(0x12,101)/* get filesystem (mm/filemap.c) read-ahead */ +#define TARGET_BLKSECTSET TARGET_IO(0x12,102)/* set max sectors per request (ll_rw_blk.c) */ +#define TARGET_BLKSECTGET TARGET_IO(0x12,103)/* get max sectors per request (ll_rw_blk.c) */ +#define TARGET_BLKSSZGET  TARGET_IO(0x12,104)/* get block device sector size */ +#define TARGET_BLKPG      TARGET_IO(0x12,105)/* Partition table and disk geometry handling */ +/* A jump here: 108-111 have been used for various private purposes. */ +#define TARGET_BLKBSZGET  TARGET_IOR(0x12, 112, abi_ulong) +#define TARGET_BLKBSZSET  TARGET_IOW(0x12, 113, abi_ulong) +#define TARGET_BLKGETSIZE64 TARGET_IOR(0x12,114,abi_ulong) +                                             /* return device size in bytes +                                                (u64 *arg) */ +#define TARGET_FIBMAP     TARGET_IO(0x00,1)  /* bmap access */ +#define TARGET_FIGETBSZ   TARGET_IO(0x00,2)  /* get the block size used for bmap */ +#define TARGET_FS_IOC_FIEMAP TARGET_IOWR('f',11,struct fiemap) + +/* cdrom commands */ +#define TARGET_CDROMPAUSE		0x5301 /* Pause Audio Operation */ +#define TARGET_CDROMRESUME		0x5302 /* Resume paused Audio Operation */ +#define TARGET_CDROMPLAYMSF		0x5303 /* Play Audio MSF (struct cdrom_msf) */ +#define TARGET_CDROMPLAYTRKIND		0x5304 /* Play Audio Track/index +                                           (struct cdrom_ti) */ +#define TARGET_CDROMREADTOCHDR		0x5305 /* Read TOC header +                                           (struct cdrom_tochdr) */ +#define TARGET_CDROMREADTOCENTRY	0x5306 /* Read TOC entry +                                           (struct cdrom_tocentry) */ +#define TARGET_CDROMSTOP		0x5307 /* Stop the cdrom drive */ +#define TARGET_CDROMSTART		0x5308 /* Start the cdrom drive */ +#define TARGET_CDROMEJECT		0x5309 /* Ejects the cdrom media */ +#define TARGET_CDROMVOLCTRL		0x530a /* Control output volume +                                           (struct cdrom_volctrl) */ +#define TARGET_CDROMSUBCHNL		0x530b /* Read subchannel data +                                           (struct cdrom_subchnl) */ +#define TARGET_CDROMREADMODE2		0x530c /* Read TARGET_CDROM mode 2 data (2336 Bytes) +                                           (struct cdrom_read) */ +#define TARGET_CDROMREADMODE1		0x530d /* Read TARGET_CDROM mode 1 data (2048 Bytes) +                                           (struct cdrom_read) */ +#define TARGET_CDROMREADAUDIO		0x530e /* (struct cdrom_read_audio) */ +#define TARGET_CDROMEJECT_SW		0x530f /* enable(1)/disable(0) auto-ejecting */ +#define TARGET_CDROMMULTISESSION	0x5310 /* Obtain the start-of-last-session +                                           address of multi session disks +                                           (struct cdrom_multisession) */ +#define TARGET_CDROM_GET_MCN		0x5311 /* Obtain the "Universal Product Code" +                                           if available (struct cdrom_mcn) */ +#define TARGET_CDROM_GET_UPC		TARGET_CDROM_GET_MCN  /* This one is depricated, +                                          but here anyway for compatibility */ +#define TARGET_CDROMRESET		0x5312 /* hard-reset the drive */ +#define TARGET_CDROMVOLREAD		0x5313 /* Get the drive's volume setting +                                          (struct cdrom_volctrl) */ +#define TARGET_CDROMREADRAW		0x5314	/* read data in raw mode (2352 Bytes) +                                           (struct cdrom_read) */ +/* + * These ioctls are used only used in aztcd.c and optcd.c + */ +#define TARGET_CDROMREADCOOKED		0x5315	/* read data in cooked mode */ +#define TARGET_CDROMSEEK		0x5316  /* seek msf address */ + +/* + * This ioctl is only used by the scsi-cd driver. +   It is for playing audio in logical block addressing mode. + */ +#define TARGET_CDROMPLAYBLK		0x5317	/* (struct cdrom_blk) */ + +/* + * These ioctls are only used in optcd.c + */ +#define TARGET_CDROMREADALL		0x5318	/* read all 2646 bytes */ + +/* + * These ioctls are (now) only in ide-cd.c for controlling + * drive spindown time.  They should be implemented in the + * Uniform driver, via generic packet commands, GPCMD_MODE_SELECT_10, + * GPCMD_MODE_SENSE_10 and the GPMODE_POWER_PAGE... + *  -Erik + */ +#define TARGET_CDROMGETSPINDOWN        0x531d +#define TARGET_CDROMSETSPINDOWN        0x531e + +/* + * These ioctls are implemented through the uniform CD-ROM driver + * They _will_ be adopted by all CD-ROM drivers, when all the CD-ROM + * drivers are eventually ported to the uniform CD-ROM driver interface. + */ +#define TARGET_CDROMCLOSETRAY		0x5319	/* pendant of CDROMEJECT */ +#define TARGET_CDROM_SET_OPTIONS	0x5320  /* Set behavior options */ +#define TARGET_CDROM_CLEAR_OPTIONS	0x5321  /* Clear behavior options */ +#define TARGET_CDROM_SELECT_SPEED	0x5322  /* Set the CD-ROM speed */ +#define TARGET_CDROM_SELECT_DISC	0x5323  /* Select disc (for juke-boxes) */ +#define TARGET_CDROM_MEDIA_CHANGED	0x5325  /* Check is media changed  */ +#define TARGET_CDROM_DRIVE_STATUS	0x5326  /* Get tray position, etc. */ +#define TARGET_CDROM_DISC_STATUS	0x5327  /* Get disc type, etc. */ +#define TARGET_CDROM_CHANGER_NSLOTS    0x5328  /* Get number of slots */ +#define TARGET_CDROM_LOCKDOOR		0x5329  /* lock or unlock door */ +#define TARGET_CDROM_DEBUG		0x5330	/* Turn debug messages on/off */ +#define TARGET_CDROM_GET_CAPABILITY	0x5331	/* get capabilities */ + +/* Note that scsi/scsi_ioctl.h also uses 0x5382 - 0x5386. + * Future CDROM ioctls should be kept below 0x537F + */ + +/* This ioctl is only used by sbpcd at the moment */ +#define TARGET_CDROMAUDIOBUFSIZ        0x5382	/* set the audio buffer size */ +					/* conflict with SCSI_IOCTL_GET_IDLUN */ + +/* DVD-ROM Specific ioctls */ +#define TARGET_DVD_READ_STRUCT		0x5390  /* Read structure */ +#define TARGET_DVD_WRITE_STRUCT	0x5391  /* Write structure */ +#define TARGET_DVD_AUTH		0x5392  /* Authentication */ + +#define TARGET_CDROM_SEND_PACKET	0x5393	/* send a packet to the drive */ +#define TARGET_CDROM_NEXT_WRITABLE	0x5394	/* get next writable block */ +#define TARGET_CDROM_LAST_WRITTEN	0x5395	/* get last block written on disc */ + +/* HD commands */ + +/* hd/ide ctl's that pass (arg) ptrs to user space are numbered 0x030n/0x031n */ +#define TARGET_HDIO_GETGEO            0x0301  /* get device geometry */ +#define TARGET_HDIO_GET_UNMASKINTR    0x0302  /* get current unmask setting */ +#define TARGET_HDIO_GET_MULTCOUNT     0x0304  /* get current IDE blockmode setting */ +#define TARGET_HDIO_GET_KEEPSETTINGS  0x0308  /* get keep-settings-on-reset flag */ +#define TARGET_HDIO_GET_32BIT         0x0309  /* get current io_32bit setting */ +#define TARGET_HDIO_GET_NOWERR        0x030a  /* get ignore-write-error flag */ +#define TARGET_HDIO_GET_DMA           0x030b  /* get use-dma flag */ +#define TARGET_HDIO_GET_IDENTITY      0x030d  /* get IDE identification info */ +#define TARGET_HDIO_DRIVE_CMD         0x031f  /* execute a special drive command */ + +/* hd/ide ctl's that pass (arg) non-ptr values are numbered 0x032n/0x033n */ +#define TARGET_HDIO_SET_MULTCOUNT     0x0321  /* change IDE blockmode */ +#define TARGET_HDIO_SET_UNMASKINTR    0x0322  /* permit other irqs during I/O */ +#define TARGET_HDIO_SET_KEEPSETTINGS  0x0323  /* keep ioctl settings on reset */ +#define TARGET_HDIO_SET_32BIT         0x0324  /* change io_32bit flags */ +#define TARGET_HDIO_SET_NOWERR        0x0325  /* change ignore-write-error flag */ +#define TARGET_HDIO_SET_DMA           0x0326  /* change use-dma flag */ +#define TARGET_HDIO_SET_PIO_MODE      0x0327  /* reconfig interface to new speed */ + +/* loop ioctls */ +#define TARGET_LOOP_SET_FD            0x4C00 +#define TARGET_LOOP_CLR_FD            0x4C01 +#define TARGET_LOOP_SET_STATUS        0x4C02 +#define TARGET_LOOP_GET_STATUS        0x4C03 +#define TARGET_LOOP_SET_STATUS64      0x4C04 +#define TARGET_LOOP_GET_STATUS64      0x4C05 +#define TARGET_LOOP_CHANGE_FD         0x4C06 + +/* fb ioctls */ +#define TARGET_FBIOGET_VSCREENINFO    0x4600 +#define TARGET_FBIOPUT_VSCREENINFO    0x4601 +#define TARGET_FBIOGET_FSCREENINFO    0x4602 +#define TARGET_FBIOGETCMAP            0x4604 +#define TARGET_FBIOPUTCMAP            0x4605 +#define TARGET_FBIOPAN_DISPLAY        0x4606 +#define TARGET_FBIOGET_CON2FBMAP      0x460F +#define TARGET_FBIOPUT_CON2FBMAP      0x4610 + +/* vt ioctls */ +#define TARGET_VT_OPENQRY             0x5600 +#define TARGET_VT_GETSTATE            0x5603 +#define TARGET_VT_ACTIVATE            0x5606 +#define TARGET_VT_WAITACTIVE          0x5607 +#define TARGET_VT_LOCKSWITCH          0x560b +#define TARGET_VT_UNLOCKSWITCH        0x560c +#define TARGET_VT_GETMODE             0x5601 +#define TARGET_VT_SETMODE             0x5602 +#define TARGET_VT_RELDISP             0x5605 +#define TARGET_VT_DISALLOCATE         0x5608 + +/* device mapper */ +#define TARGET_DM_VERSION             TARGET_IOWRU(0xfd, 0x00) +#define TARGET_DM_REMOVE_ALL          TARGET_IOWRU(0xfd, 0x01) +#define TARGET_DM_LIST_DEVICES        TARGET_IOWRU(0xfd, 0x02) +#define TARGET_DM_DEV_CREATE          TARGET_IOWRU(0xfd, 0x03) +#define TARGET_DM_DEV_REMOVE          TARGET_IOWRU(0xfd, 0x04) +#define TARGET_DM_DEV_RENAME          TARGET_IOWRU(0xfd, 0x05) +#define TARGET_DM_DEV_SUSPEND         TARGET_IOWRU(0xfd, 0x06) +#define TARGET_DM_DEV_STATUS          TARGET_IOWRU(0xfd, 0x07) +#define TARGET_DM_DEV_WAIT            TARGET_IOWRU(0xfd, 0x08) +#define TARGET_DM_TABLE_LOAD          TARGET_IOWRU(0xfd, 0x09) +#define TARGET_DM_TABLE_CLEAR         TARGET_IOWRU(0xfd, 0x0a) +#define TARGET_DM_TABLE_DEPS          TARGET_IOWRU(0xfd, 0x0b) +#define TARGET_DM_TABLE_STATUS        TARGET_IOWRU(0xfd, 0x0c) +#define TARGET_DM_LIST_VERSIONS       TARGET_IOWRU(0xfd, 0x0d) +#define TARGET_DM_TARGET_MSG          TARGET_IOWRU(0xfd, 0x0e) +#define TARGET_DM_DEV_SET_GEOMETRY    TARGET_IOWRU(0xfd, 0x0f) + +/* from asm/termbits.h */ + +#define TARGET_NCC 8 +struct target_termio { +	unsigned short c_iflag;		/* input mode flags */ +	unsigned short c_oflag;		/* output mode flags */ +	unsigned short c_cflag;		/* control mode flags */ +	unsigned short c_lflag;		/* local mode flags */ +	unsigned char c_line;		/* line discipline */ +	unsigned char c_cc[TARGET_NCC];	/* control characters */ +}; + +struct target_winsize { +	unsigned short ws_row; +	unsigned short ws_col; +	unsigned short ws_xpixel; +	unsigned short ws_ypixel; +}; + +#include "termbits.h" + +#if defined(TARGET_MIPS) +#define TARGET_PROT_SEM         0x10 +#else +#define TARGET_PROT_SEM         0x08 +#endif + +/* Common */ +#define TARGET_MAP_SHARED	0x01		/* Share changes */ +#define TARGET_MAP_PRIVATE	0x02		/* Changes are private */ +#define TARGET_MAP_TYPE		0x0f		/* Mask for type of mapping */ + +/* Target specific */ +#if defined(TARGET_MIPS) +#define TARGET_MAP_FIXED	0x10		/* Interpret addr exactly */ +#define TARGET_MAP_ANONYMOUS	0x0800		/* don't use a file */ +#define TARGET_MAP_GROWSDOWN	0x1000		/* stack-like segment */ +#define TARGET_MAP_DENYWRITE	0x2000		/* ETXTBSY */ +#define TARGET_MAP_EXECUTABLE	0x4000		/* mark it as an executable */ +#define TARGET_MAP_LOCKED	0x8000		/* pages are locked */ +#define TARGET_MAP_NORESERVE	0x0400		/* don't check for reservations */ +#define TARGET_MAP_POPULATE	0x10000		/* populate (prefault) pagetables */ +#define TARGET_MAP_NONBLOCK	0x20000		/* do not block on IO */ +#elif defined(TARGET_PPC) +#define TARGET_MAP_FIXED	0x10		/* Interpret addr exactly */ +#define TARGET_MAP_ANONYMOUS	0x20		/* don't use a file */ +#define TARGET_MAP_GROWSDOWN	0x0100		/* stack-like segment */ +#define TARGET_MAP_DENYWRITE	0x0800		/* ETXTBSY */ +#define TARGET_MAP_EXECUTABLE	0x1000		/* mark it as an executable */ +#define TARGET_MAP_LOCKED	0x0080		/* pages are locked */ +#define TARGET_MAP_NORESERVE	0x0040		/* don't check for reservations */ +#define TARGET_MAP_POPULATE	0x8000		/* populate (prefault) pagetables */ +#define TARGET_MAP_NONBLOCK	0x10000		/* do not block on IO */ +#elif defined(TARGET_ALPHA) +#define TARGET_MAP_ANONYMOUS	0x10		/* don't use a file */ +#define TARGET_MAP_FIXED	0x100		/* Interpret addr exactly */ +#define TARGET_MAP_GROWSDOWN	0x01000		/* stack-like segment */ +#define TARGET_MAP_DENYWRITE	0x02000		/* ETXTBSY */ +#define TARGET_MAP_EXECUTABLE	0x04000		/* mark it as an executable */ +#define TARGET_MAP_LOCKED	0x08000		/* lock the mapping */ +#define TARGET_MAP_NORESERVE	0x10000		/* no check for reservations */ +#define TARGET_MAP_POPULATE	0x20000		/* pop (prefault) pagetables */ +#define TARGET_MAP_NONBLOCK	0x40000		/* do not block on IO */ +#else +#define TARGET_MAP_FIXED	0x10		/* Interpret addr exactly */ +#define TARGET_MAP_ANONYMOUS	0x20		/* don't use a file */ +#define TARGET_MAP_GROWSDOWN	0x0100		/* stack-like segment */ +#define TARGET_MAP_DENYWRITE	0x0800		/* ETXTBSY */ +#define TARGET_MAP_EXECUTABLE	0x1000		/* mark it as an executable */ +#define TARGET_MAP_LOCKED	0x2000		/* pages are locked */ +#define TARGET_MAP_NORESERVE	0x4000		/* don't check for reservations */ +#define TARGET_MAP_POPULATE	0x8000		/* populate (prefault) pagetables */ +#define TARGET_MAP_NONBLOCK	0x10000		/* do not block on IO */ +#define TARGET_MAP_UNINITIALIZED 0x4000000	/* for anonymous mmap, memory could be uninitialized */ +#endif + +#if (defined(TARGET_I386) && defined(TARGET_ABI32)) \ +    || (defined(TARGET_ARM) && defined(TARGET_ABI32)) \ +    || defined(TARGET_CRIS) || defined(TARGET_UNICORE32) +struct target_stat { +	unsigned short st_dev; +	unsigned short __pad1; +	abi_ulong st_ino; +	unsigned short st_mode; +	unsigned short st_nlink; +	unsigned short st_uid; +	unsigned short st_gid; +	unsigned short st_rdev; +	unsigned short __pad2; +	abi_ulong  st_size; +	abi_ulong  st_blksize; +	abi_ulong  st_blocks; +	abi_ulong  target_st_atime; +	abi_ulong  __unused1; +	abi_ulong  target_st_mtime; +	abi_ulong  __unused2; +	abi_ulong  target_st_ctime; +	abi_ulong  __unused3; +	abi_ulong  __unused4; +	abi_ulong  __unused5; +}; + +/* This matches struct stat64 in glibc2.1, hence the absolutely + * insane amounts of padding around dev_t's. + */ +#define TARGET_HAS_STRUCT_STAT64 +struct target_stat64 { +	unsigned short	st_dev; +	unsigned char	__pad0[10]; + +#define TARGET_STAT64_HAS_BROKEN_ST_INO	1 +	abi_ulong	__st_ino; + +	unsigned int	st_mode; +	unsigned int	st_nlink; + +	abi_ulong	st_uid; +	abi_ulong	st_gid; + +	unsigned short	st_rdev; +	unsigned char	__pad3[10]; + +	long long	st_size; +	abi_ulong	st_blksize; + +	abi_ulong	st_blocks;	/* Number 512-byte blocks allocated. */ +	abi_ulong	__pad4;		/* future possible st_blocks high bits */ + +	abi_ulong	target_st_atime; +	abi_ulong	__pad5; + +	abi_ulong	target_st_mtime; +	abi_ulong	__pad6; + +	abi_ulong	target_st_ctime; +	abi_ulong	__pad7;		/* will be high 32 bits of ctime someday */ + +	unsigned long long	st_ino; +} QEMU_PACKED; + +#ifdef TARGET_ARM +#define TARGET_HAS_STRUCT_STAT64 +struct target_eabi_stat64 { +        unsigned long long st_dev; +        unsigned int    __pad1; +        abi_ulong    __st_ino; +        unsigned int    st_mode; +        unsigned int    st_nlink; + +        abi_ulong    st_uid; +        abi_ulong    st_gid; + +        unsigned long long st_rdev; +        unsigned int    __pad2[2]; + +        long long       st_size; +        abi_ulong    st_blksize; +        unsigned int    __pad3; +        unsigned long long st_blocks; + +        abi_ulong    target_st_atime; +        abi_ulong    target_st_atime_nsec; + +        abi_ulong    target_st_mtime; +        abi_ulong    target_st_mtime_nsec; + +        abi_ulong    target_st_ctime; +        abi_ulong    target_st_ctime_nsec; + +        unsigned long long st_ino; +} QEMU_PACKED; +#endif + +#elif defined(TARGET_SPARC64) && !defined(TARGET_ABI32) +struct target_stat { +	unsigned int	st_dev; +	abi_ulong	st_ino; +	unsigned int	st_mode; +	unsigned int	st_nlink; +	unsigned int	st_uid; +	unsigned int	st_gid; +	unsigned int	st_rdev; +	abi_long	st_size; +	abi_long	target_st_atime; +	abi_long	target_st_mtime; +	abi_long	target_st_ctime; +	abi_long	st_blksize; +	abi_long	st_blocks; +	abi_ulong	__unused4[2]; +}; + +#define TARGET_HAS_STRUCT_STAT64 +struct target_stat64 { +	unsigned char	__pad0[6]; +	unsigned short	st_dev; + +	uint64_t	st_ino; +	uint64_t	st_nlink; + +	unsigned int	st_mode; + +	unsigned int	st_uid; +	unsigned int	st_gid; + +	unsigned char	__pad2[6]; +	unsigned short	st_rdev; + +        int64_t		st_size; +	int64_t		st_blksize; + +	unsigned char	__pad4[4]; +	unsigned int	st_blocks; + +	abi_ulong	target_st_atime; +	abi_ulong	__unused1; + +	abi_ulong	target_st_mtime; +	abi_ulong	__unused2; + +	abi_ulong	target_st_ctime; +	abi_ulong	__unused3; + +	abi_ulong	__unused4[3]; +}; + +#elif defined(TARGET_SPARC) + +struct target_stat { +	unsigned short	st_dev; +	abi_ulong	st_ino; +	unsigned short	st_mode; +	short		st_nlink; +	unsigned short	st_uid; +	unsigned short	st_gid; +	unsigned short	st_rdev; +	abi_long	st_size; +	abi_long	target_st_atime; +	abi_ulong	__unused1; +	abi_long	target_st_mtime; +	abi_ulong	__unused2; +	abi_long	target_st_ctime; +	abi_ulong	__unused3; +	abi_long	st_blksize; +	abi_long	st_blocks; +	abi_ulong	__unused4[2]; +}; + +#define TARGET_HAS_STRUCT_STAT64 +struct target_stat64 { +	unsigned char	__pad0[6]; +	unsigned short	st_dev; + +	uint64_t st_ino; + +	unsigned int	st_mode; +	unsigned int	st_nlink; + +	unsigned int	st_uid; +	unsigned int	st_gid; + +	unsigned char	__pad2[6]; +	unsigned short	st_rdev; + +	unsigned char	__pad3[8]; + +        int64_t	st_size; +	unsigned int	st_blksize; + +	unsigned char	__pad4[8]; +	unsigned int	st_blocks; + +	unsigned int	target_st_atime; +	unsigned int	__unused1; + +	unsigned int	target_st_mtime; +	unsigned int	__unused2; + +	unsigned int	target_st_ctime; +	unsigned int	__unused3; + +	unsigned int	__unused4; +	unsigned int	__unused5; +}; + +#elif defined(TARGET_PPC) + +struct target_stat { +	abi_ulong st_dev; +	abi_ulong st_ino; +#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) +	abi_ulong st_nlink; +	unsigned int st_mode; +#else +	unsigned int st_mode; +	unsigned short st_nlink; +#endif +	unsigned int st_uid; +	unsigned int st_gid; +	abi_ulong  st_rdev; +	abi_ulong  st_size; +	abi_ulong  st_blksize; +	abi_ulong  st_blocks; +	abi_ulong  target_st_atime; +	abi_ulong  target_st_atime_nsec; +	abi_ulong  target_st_mtime; +	abi_ulong  target_st_mtime_nsec; +	abi_ulong  target_st_ctime; +	abi_ulong  target_st_ctime_nsec; +	abi_ulong  __unused4; +	abi_ulong  __unused5; +#if defined(TARGET_PPC64) && !defined(TARGET_ABI32) +	abi_ulong  __unused6; +#endif +}; + +#if !defined(TARGET_PPC64) || defined(TARGET_ABI32) +#define TARGET_HAS_STRUCT_STAT64 +struct QEMU_PACKED target_stat64 { +	unsigned long long st_dev; +        unsigned long long st_ino; +	unsigned int st_mode; +	unsigned int st_nlink; +	unsigned int st_uid; +	unsigned int st_gid; +	unsigned long long st_rdev; +	unsigned long long __pad0; +	long long      st_size; +	int	       st_blksize; +	unsigned int   __pad1; +	long long      st_blocks;	/* Number 512-byte blocks allocated. */ +	int	       target_st_atime; +        unsigned int   target_st_atime_nsec; +	int	       target_st_mtime; +        unsigned int   target_st_mtime_nsec; +	int            target_st_ctime; +        unsigned int   target_st_ctime_nsec; +        unsigned int   __unused4; +        unsigned int   __unused5; +}; +#endif + +#elif defined(TARGET_MICROBLAZE) + +struct target_stat { +	abi_ulong st_dev; +	abi_ulong st_ino; +	unsigned int st_mode; +	unsigned short st_nlink; +	unsigned int st_uid; +	unsigned int st_gid; +	abi_ulong  st_rdev; +	abi_ulong  st_size; +	abi_ulong  st_blksize; +	abi_ulong  st_blocks; +	abi_ulong  target_st_atime; +	abi_ulong  target_st_atime_nsec; +	abi_ulong  target_st_mtime; +	abi_ulong  target_st_mtime_nsec; +	abi_ulong  target_st_ctime; +	abi_ulong  target_st_ctime_nsec; +	abi_ulong  __unused4; +	abi_ulong  __unused5; +}; + +/* FIXME: Microblaze no-mmu user-space has a difference stat64 layout...  */ +#define TARGET_HAS_STRUCT_STAT64 +struct QEMU_PACKED target_stat64 { +	uint64_t st_dev; +#define TARGET_STAT64_HAS_BROKEN_ST_INO 1 +	uint32_t pad0; +	uint32_t __st_ino; + +	uint32_t st_mode; +	uint32_t st_nlink; +	uint32_t st_uid; +	uint32_t st_gid; +	uint64_t st_rdev; +	uint64_t __pad1; + +	int64_t  st_size; +	int32_t  st_blksize; +	uint32_t __pad2; +	int64_t st_blocks;	/* Number 512-byte blocks allocated. */ + +	int	       target_st_atime; +	unsigned int   target_st_atime_nsec; +	int	       target_st_mtime; +	unsigned int   target_st_mtime_nsec; +	int            target_st_ctime; +	unsigned int   target_st_ctime_nsec; +	uint64_t st_ino; +}; + +#elif defined(TARGET_M68K) + +struct target_stat { +	unsigned short st_dev; +	unsigned short __pad1; +	abi_ulong st_ino; +	unsigned short st_mode; +	unsigned short st_nlink; +	unsigned short st_uid; +	unsigned short st_gid; +	unsigned short st_rdev; +	unsigned short __pad2; +	abi_ulong  st_size; +	abi_ulong  st_blksize; +	abi_ulong  st_blocks; +	abi_ulong  target_st_atime; +	abi_ulong  __unused1; +	abi_ulong  target_st_mtime; +	abi_ulong  __unused2; +	abi_ulong  target_st_ctime; +	abi_ulong  __unused3; +	abi_ulong  __unused4; +	abi_ulong  __unused5; +}; + +/* This matches struct stat64 in glibc2.1, hence the absolutely + * insane amounts of padding around dev_t's. + */ +#define TARGET_HAS_STRUCT_STAT64 +struct target_stat64 { +	unsigned long long	st_dev; +	unsigned char	__pad1[2]; + +#define TARGET_STAT64_HAS_BROKEN_ST_INO	1 +	abi_ulong	__st_ino; + +	unsigned int	st_mode; +	unsigned int	st_nlink; + +	abi_ulong	st_uid; +	abi_ulong	st_gid; + +	unsigned long long	st_rdev; +	unsigned char	__pad3[2]; + +	long long	st_size; +	abi_ulong	st_blksize; + +	abi_ulong	__pad4;		/* future possible st_blocks high bits */ +	abi_ulong	st_blocks;	/* Number 512-byte blocks allocated. */ + +	abi_ulong	target_st_atime; +	abi_ulong	target_st_atime_nsec; + +	abi_ulong	target_st_mtime; +	abi_ulong	target_st_mtime_nsec; + +	abi_ulong	target_st_ctime; +	abi_ulong	target_st_ctime_nsec; + +	unsigned long long	st_ino; +} QEMU_PACKED; + +#elif defined(TARGET_ABI_MIPSN64) + +/* The memory layout is the same as of struct stat64 of the 32-bit kernel.  */ +struct target_stat { +	unsigned int		st_dev; +	unsigned int		st_pad0[3]; /* Reserved for st_dev expansion */ + +	abi_ulong		st_ino; + +	unsigned int		st_mode; +	unsigned int		st_nlink; + +	int			st_uid; +	int			st_gid; + +	unsigned int		st_rdev; +	unsigned int		st_pad1[3]; /* Reserved for st_rdev expansion */ + +	abi_ulong		st_size; + +	/* +	 * Actually this should be timestruc_t st_atime, st_mtime and st_ctime +	 * but we don't have it under Linux. +	 */ +	unsigned int		target_st_atime; +	unsigned int		target_st_atime_nsec; + +	unsigned int		target_st_mtime; +	unsigned int		target_st_mtime_nsec; + +	unsigned int		target_st_ctime; +	unsigned int		target_st_ctime_nsec; + +	unsigned int		st_blksize; +	unsigned int		st_pad2; + +	abi_ulong		st_blocks; +}; + +#elif defined(TARGET_ABI_MIPSN32) + +struct target_stat { +        abi_ulong    st_dev; +        abi_ulong    st_pad0[3]; /* Reserved for st_dev expansion */ +        uint64_t     st_ino; +        unsigned int st_mode; +        unsigned int st_nlink; +        int          st_uid; +        int          st_gid; +        abi_ulong    st_rdev; +        abi_ulong    st_pad1[3]; /* Reserved for st_rdev expansion */ +        int64_t      st_size; +        abi_long     target_st_atime; +        abi_ulong    target_st_atime_nsec; /* Reserved for st_atime expansion */ +        abi_long     target_st_mtime; +        abi_ulong    target_st_mtime_nsec; /* Reserved for st_mtime expansion */ +        abi_long     target_st_ctime; +        abi_ulong    target_st_ctime_nsec; /* Reserved for st_ctime expansion */ +        abi_ulong    st_blksize; +        abi_ulong    st_pad2; +        int64_t      st_blocks; +}; + +#elif defined(TARGET_ABI_MIPSO32) + +struct target_stat { +	unsigned	st_dev; +	abi_long	st_pad1[3];		/* Reserved for network id */ +	abi_ulong	st_ino; +	unsigned int	st_mode; +	unsigned int	st_nlink; +	int		st_uid; +	int		st_gid; +	unsigned 	st_rdev; +	abi_long	st_pad2[2]; +	abi_long	st_size; +	abi_long	st_pad3; +	/* +	 * Actually this should be timestruc_t st_atime, st_mtime and st_ctime +	 * but we don't have it under Linux. +	 */ +	abi_long		target_st_atime; +	abi_long		target_st_atime_nsec; +	abi_long		target_st_mtime; +	abi_long		target_st_mtime_nsec; +	abi_long		target_st_ctime; +	abi_long		target_st_ctime_nsec; +	abi_long		st_blksize; +	abi_long		st_blocks; +	abi_long		st_pad4[14]; +}; + +/* + * This matches struct stat64 in glibc2.1, hence the absolutely insane + * amounts of padding around dev_t's.  The memory layout is the same as of + * struct stat of the 64-bit kernel. + */ + +#define TARGET_HAS_STRUCT_STAT64 +struct target_stat64 { +	abi_ulong	st_dev; +	abi_ulong	st_pad0[3];	/* Reserved for st_dev expansion  */ + +	uint64_t	st_ino; + +        unsigned int	st_mode; +        unsigned int	st_nlink; + +	int		st_uid; +	int		st_gid; + +	abi_ulong	st_rdev; +	abi_ulong	st_pad1[3];	/* Reserved for st_rdev expansion  */ + +	int64_t 	st_size; + +	/* +	 * Actually this should be timestruc_t st_atime, st_mtime and st_ctime +	 * but we don't have it under Linux. +	 */ +	abi_long	target_st_atime; +	abi_ulong	target_st_atime_nsec;	/* Reserved for st_atime expansion  */ + +	abi_long	target_st_mtime; +	abi_ulong	target_st_mtime_nsec;	/* Reserved for st_mtime expansion  */ + +	abi_long	target_st_ctime; +	abi_ulong	target_st_ctime_nsec;	/* Reserved for st_ctime expansion  */ + +	abi_ulong	st_blksize; +	abi_ulong	st_pad2; + +	int64_t  	st_blocks; +}; + +#elif defined(TARGET_ALPHA) + +struct target_stat { +       unsigned int    st_dev; +       unsigned int    st_ino; +       unsigned int    st_mode; +       unsigned int    st_nlink; +       unsigned int    st_uid; +       unsigned int    st_gid; +       unsigned int    st_rdev; +       abi_long     st_size; +       abi_ulong    target_st_atime; +       abi_ulong    target_st_mtime; +       abi_ulong    target_st_ctime; +       unsigned int    st_blksize; +       unsigned int    st_blocks; +       unsigned int    st_flags; +       unsigned int    st_gen; +}; + +#define TARGET_HAS_STRUCT_STAT64 +struct target_stat64 { +       abi_ulong    st_dev; +       abi_ulong    st_ino; +       abi_ulong    st_rdev; +       abi_long     st_size; +       abi_ulong    st_blocks; + +       unsigned int    st_mode; +       unsigned int    st_uid; +       unsigned int    st_gid; +       unsigned int    st_blksize; +       unsigned int    st_nlink; +       unsigned int    __pad0; + +       abi_ulong    target_st_atime; +       abi_ulong    target_st_atime_nsec; +       abi_ulong    target_st_mtime; +       abi_ulong    target_st_mtime_nsec; +       abi_ulong    target_st_ctime; +       abi_ulong    target_st_ctime_nsec; +       abi_long     __unused[3]; +}; + +#elif defined(TARGET_SH4) + +struct target_stat { +	abi_ulong  st_dev; +	abi_ulong  st_ino; +	unsigned short st_mode; +	unsigned short st_nlink; +	unsigned short st_uid; +	unsigned short st_gid; +	abi_ulong  st_rdev; +	abi_ulong  st_size; +	abi_ulong  st_blksize; +	abi_ulong  st_blocks; +	abi_ulong  target_st_atime; +	abi_ulong  target_st_atime_nsec; +	abi_ulong  target_st_mtime; +	abi_ulong  target_st_mtime_nsec; +	abi_ulong  target_st_ctime; +	abi_ulong  target_st_ctime_nsec; +	abi_ulong  __unused4; +	abi_ulong  __unused5; +}; + +/* This matches struct stat64 in glibc2.1, hence the absolutely + * insane amounts of padding around dev_t's. + */ +#define TARGET_HAS_STRUCT_STAT64 +struct QEMU_PACKED target_stat64 { +	unsigned long long	st_dev; +	unsigned char	__pad0[4]; + +#define TARGET_STAT64_HAS_BROKEN_ST_INO	1 +	abi_ulong	__st_ino; + +	unsigned int	st_mode; +	unsigned int	st_nlink; + +	abi_ulong	st_uid; +	abi_ulong	st_gid; + +	unsigned long long	st_rdev; +	unsigned char	__pad3[4]; + +	long long	st_size; +	abi_ulong	st_blksize; + +	unsigned long long	st_blocks;	/* Number 512-byte blocks allocated. */ + +	abi_ulong	target_st_atime; +	abi_ulong	target_st_atime_nsec; + +	abi_ulong	target_st_mtime; +	abi_ulong	target_st_mtime_nsec; + +	abi_ulong	target_st_ctime; +	abi_ulong	target_st_ctime_nsec; + +	unsigned long long	st_ino; +}; + +#elif defined(TARGET_I386) && !defined(TARGET_ABI32) +struct target_stat { +	abi_ulong	st_dev; +	abi_ulong	st_ino; +	abi_ulong	st_nlink; + +	unsigned int	st_mode; +	unsigned int	st_uid; +	unsigned int	st_gid; +	unsigned int	__pad0; +	abi_ulong	st_rdev; +	abi_long	st_size; +	abi_long	st_blksize; +    	abi_long	st_blocks;	/* Number 512-byte blocks allocated. */ + +	abi_ulong	target_st_atime; +	abi_ulong 	target_st_atime_nsec;  +	abi_ulong	target_st_mtime; +	abi_ulong	target_st_mtime_nsec; +	abi_ulong	target_st_ctime; +	abi_ulong       target_st_ctime_nsec; + +  	abi_long	__unused[3]; +}; +#elif defined(TARGET_S390X) +struct target_stat { +    abi_ulong  st_dev; +    abi_ulong  st_ino; +    abi_ulong  st_nlink; +    unsigned int   st_mode; +    unsigned int   st_uid; +    unsigned int   st_gid; +    unsigned int   __pad1; +    abi_ulong  st_rdev; +    abi_ulong  st_size; +    abi_ulong  target_st_atime; +    abi_ulong  target_st_atime_nsec; +    abi_ulong  target_st_mtime; +    abi_ulong  target_st_mtime_nsec; +    abi_ulong  target_st_ctime; +    abi_ulong  target_st_ctime_nsec; +    abi_ulong  st_blksize; +    abi_long       st_blocks; +    abi_ulong  __unused[3]; +}; +#elif defined(TARGET_AARCH64) +struct target_stat { +    abi_ulong  st_dev; +    abi_ulong  st_ino; +    unsigned int st_mode; +    unsigned int st_nlink; +    unsigned int   st_uid; +    unsigned int   st_gid; +    abi_ulong  st_rdev; +    abi_ulong  _pad1; +    abi_long  st_size; +    int        st_blksize; +    int        __pad2; +    abi_long   st_blocks; +    abi_long  target_st_atime; +    abi_ulong  target_st_atime_nsec; +    abi_long  target_st_mtime; +    abi_ulong  target_st_mtime_nsec; +    abi_long  target_st_ctime; +    abi_ulong  target_st_ctime_nsec; +    unsigned int __unused[2]; +}; +#elif defined(TARGET_OPENRISC) + +/* These are the asm-generic versions of the stat and stat64 structures */ + +struct target_stat { +    abi_ulong st_dev; +    abi_ulong st_ino; +    unsigned int st_mode; +    unsigned int st_nlink; +    unsigned int st_uid; +    unsigned int st_gid; +    abi_ulong st_rdev; +    abi_ulong __pad1; +    abi_long st_size; +    int st_blksize; +    int __pad2; +    abi_long st_blocks; +    abi_long target_st_atime; +    abi_ulong target_st_atime_nsec; +    abi_long target_st_mtime; +    abi_ulong target_st_mtime_nsec; +    abi_long target_st_ctime; +    abi_ulong target_st_ctime_nsec; +    unsigned int __unused4; +    unsigned int __unused5; +}; + +#define TARGET_HAS_STRUCT_STAT64 +struct target_stat64 { +    uint64_t st_dev; +    uint64_t st_ino; +    unsigned int st_mode; +    unsigned int st_nlink; +    unsigned int st_uid; +    unsigned int st_gid; +    uint64_t st_rdev; +    uint64_t __pad1; +    int64_t st_size; +    int st_blksize; +    int __pad2; +    int64_t st_blocks; +    int target_st_atime; +    unsigned int target_st_atime_nsec; +    int target_st_mtime; +    unsigned int target_st_mtime_nsec; +    int target_st_ctime; +    unsigned int target_st_ctime_nsec; +    unsigned int __unused4; +    unsigned int __unused5; +}; + +#else +#error unsupported CPU +#endif + +typedef struct { +        int     val[2]; +} target_fsid_t; + +#ifdef TARGET_MIPS +#ifdef TARGET_ABI_MIPSN32 +struct target_statfs { +	int32_t			f_type; +	int32_t			f_bsize; +	int32_t			f_frsize;	/* Fragment size - unsupported */ +	int32_t			f_blocks; +	int32_t			f_bfree; +	int32_t			f_files; +	int32_t			f_ffree; +	int32_t			f_bavail; + +	/* Linux specials */ +	target_fsid_t		f_fsid; +	int32_t			f_namelen; +	int32_t			f_spare[6]; +}; +#else +struct target_statfs { +	abi_long		f_type; +	abi_long		f_bsize; +	abi_long		f_frsize;	/* Fragment size - unsupported */ +	abi_long		f_blocks; +	abi_long		f_bfree; +	abi_long		f_files; +	abi_long		f_ffree; +	abi_long		f_bavail; + +	/* Linux specials */ +	target_fsid_t		f_fsid; +	abi_long		f_namelen; +	abi_long		f_spare[6]; +}; +#endif + +struct target_statfs64 { +	uint32_t	f_type; +	uint32_t	f_bsize; +	uint32_t	f_frsize;	/* Fragment size - unsupported */ +	uint32_t	__pad; +	uint64_t	f_blocks; +	uint64_t	f_bfree; +	uint64_t	f_files; +	uint64_t	f_ffree; +	uint64_t	f_bavail; +	target_fsid_t	f_fsid; +	uint32_t	f_namelen; +	uint32_t	f_spare[6]; +}; +#elif (defined(TARGET_PPC64) || defined(TARGET_X86_64) || \ +       defined(TARGET_SPARC64) || defined(TARGET_AARCH64)) && \ +       !defined(TARGET_ABI32) +struct target_statfs { +	abi_long f_type; +	abi_long f_bsize; +	abi_long f_blocks; +	abi_long f_bfree; +	abi_long f_bavail; +	abi_long f_files; +	abi_long f_ffree; +	target_fsid_t f_fsid; +	abi_long f_namelen; +	abi_long f_frsize; +	abi_long f_spare[5]; +}; + +struct target_statfs64 { +	abi_long f_type; +	abi_long f_bsize; +	abi_long f_blocks; +	abi_long f_bfree; +	abi_long f_bavail; +	abi_long f_files; +	abi_long f_ffree; +	target_fsid_t f_fsid; +	abi_long f_namelen; +	abi_long f_frsize; +	abi_long f_spare[5]; +}; +#elif defined(TARGET_S390X) +struct target_statfs { +    int32_t  f_type; +    int32_t  f_bsize; +    abi_long f_blocks; +    abi_long f_bfree; +    abi_long f_bavail; +    abi_long f_files; +    abi_long f_ffree; +    kernel_fsid_t f_fsid; +    int32_t  f_namelen; +    int32_t  f_frsize; +    int32_t  f_spare[5]; +}; + +struct target_statfs64 { +    int32_t  f_type; +    int32_t  f_bsize; +    abi_long f_blocks; +    abi_long f_bfree; +    abi_long f_bavail; +    abi_long f_files; +    abi_long f_ffree; +    kernel_fsid_t f_fsid; +    int32_t  f_namelen; +    int32_t  f_frsize; +    int32_t  f_spare[5]; +}; +#else +struct target_statfs { +	uint32_t f_type; +	uint32_t f_bsize; +	uint32_t f_blocks; +	uint32_t f_bfree; +	uint32_t f_bavail; +	uint32_t f_files; +	uint32_t f_ffree; +	target_fsid_t f_fsid; +	uint32_t f_namelen; +	uint32_t f_frsize; +	uint32_t f_spare[5]; +}; + +struct target_statfs64 { +	uint32_t f_type; +	uint32_t f_bsize; +	uint64_t f_blocks; +	uint64_t f_bfree; +	uint64_t f_bavail; +	uint64_t f_files; +	uint64_t f_ffree; +	target_fsid_t f_fsid; +        uint32_t f_namelen; +	uint32_t f_frsize; +	uint32_t f_spare[5]; +}; +#endif + + +#define TARGET_F_DUPFD         0       /* dup */ +#define TARGET_F_GETFD         1       /* get close_on_exec */ +#define TARGET_F_SETFD         2       /* set/clear close_on_exec */ +#define TARGET_F_GETFL         3       /* get file->f_flags */ +#define TARGET_F_SETFL         4       /* set file->f_flags */ + +#if defined(TARGET_ALPHA) +#define TARGET_F_GETLK         7 +#define TARGET_F_SETLK         8 +#define TARGET_F_SETLKW        9 +#define TARGET_F_SETOWN        5       /*  for sockets. */ +#define TARGET_F_GETOWN        6       /*  for sockets. */ + +#define TARGET_F_RDLCK         1 +#define TARGET_F_WRLCK         2 +#define TARGET_F_UNLCK         8 +#define TARGET_F_EXLCK         16 +#define TARGET_F_SHLCK         32 +#elif defined(TARGET_MIPS) +#define TARGET_F_GETLK         14 +#define TARGET_F_SETLK         6 +#define TARGET_F_SETLKW        7 +#define TARGET_F_SETOWN        24       /*  for sockets. */ +#define TARGET_F_GETOWN        25       /*  for sockets. */ +#else +#define TARGET_F_GETLK         5 +#define TARGET_F_SETLK         6 +#define TARGET_F_SETLKW        7 +#define TARGET_F_SETOWN        8       /*  for sockets. */ +#define TARGET_F_GETOWN        9       /*  for sockets. */ +#endif +#define TARGET_F_SETOWN_EX     15 +#define TARGET_F_GETOWN_EX     16 + +#ifndef TARGET_F_RDLCK +#define TARGET_F_RDLCK         0 +#define TARGET_F_WRLCK         1 +#define TARGET_F_UNLCK         2 +#endif + +#ifndef TARGET_F_EXLCK +#define TARGET_F_EXLCK         4 +#define TARGET_F_SHLCK         8 +#endif + + +#define TARGET_F_SETSIG        10      /*  for sockets. */ +#define TARGET_F_GETSIG        11      /*  for sockets. */ + +#if defined(TARGET_MIPS) +#define TARGET_F_GETLK64       33      /*  using 'struct flock64' */ +#define TARGET_F_SETLK64       34 +#define TARGET_F_SETLKW64      35 +#else +#define TARGET_F_GETLK64       12      /*  using 'struct flock64' */ +#define TARGET_F_SETLK64       13 +#define TARGET_F_SETLKW64      14 +#endif + +#define TARGET_F_LINUX_SPECIFIC_BASE 1024 +#define TARGET_F_SETLEASE (TARGET_F_LINUX_SPECIFIC_BASE + 0) +#define TARGET_F_GETLEASE (TARGET_F_LINUX_SPECIFIC_BASE + 1) +#define TARGET_F_DUPFD_CLOEXEC (TARGET_F_LINUX_SPECIFIC_BASE + 6) +#define TARGET_F_NOTIFY  (TARGET_F_LINUX_SPECIFIC_BASE+2) + +#if defined(TARGET_ALPHA) +#define TARGET_O_NONBLOCK           04 +#define TARGET_O_APPEND            010 +#define TARGET_O_CREAT           01000 /* not fcntl */ +#define TARGET_O_TRUNC           02000 /* not fcntl */ +#define TARGET_O_EXCL            04000 /* not fcntl */ +#define TARGET_O_NOCTTY         010000 /* not fcntl */ +#define TARGET_O_DSYNC          040000 +#define TARGET_O_LARGEFILE           0 /* not necessary, always 64-bit */ +#define TARGET_O_DIRECTORY     0100000 /* must be a directory */ +#define TARGET_O_NOFOLLOW      0200000 /* don't follow links */ +#define TARGET_O_DIRECT       02000000 /* direct disk access hint */ +#define TARGET_O_NOATIME      04000000 +#define TARGET_O_CLOEXEC     010000000 +#define TARGET___O_SYNC      020000000 +#define TARGET_O_PATH        040000000 +#elif defined(TARGET_ARM) || defined(TARGET_M68K) +#define TARGET_O_DIRECTORY      040000 /* must be a directory */ +#define TARGET_O_NOFOLLOW      0100000 /* don't follow links */ +#define TARGET_O_DIRECT        0200000 /* direct disk access hint */ +#define TARGET_O_LARGEFILE     0400000 +#elif defined(TARGET_MIPS) +#define TARGET_O_APPEND         0x0008 +#define TARGET_O_DSYNC          0x0010 +#define TARGET_O_NONBLOCK       0x0080 +#define TARGET_O_CREAT          0x0100  /* not fcntl */ +#define TARGET_O_TRUNC          0x0200  /* not fcntl */ +#define TARGET_O_EXCL           0x0400  /* not fcntl */ +#define TARGET_O_NOCTTY         0x0800  /* not fcntl */ +#define TARGET_FASYNC           0x1000  /* fcntl, for BSD compatibility */ +#define TARGET_O_LARGEFILE      0x2000  /* allow large file opens */ +#define TARGET___O_SYNC         0x4000 +#define TARGET_O_DIRECT         0x8000  /* direct disk access hint */ +#elif defined (TARGET_PPC) +#define TARGET_O_DIRECTORY      040000 /* must be a directory */ +#define TARGET_O_NOFOLLOW      0100000 /* don't follow links */ +#define TARGET_O_LARGEFILE     0200000 +#define TARGET_O_DIRECT        0400000 /* direct disk access hint */ +#elif defined (TARGET_SPARC) +#define TARGET_O_APPEND         0x0008 +#define TARGET_FASYNC           0x0040  /* fcntl, for BSD compatibility */ +#define TARGET_O_CREAT          0x0200  /* not fcntl */ +#define TARGET_O_TRUNC          0x0400  /* not fcntl */ +#define TARGET_O_EXCL           0x0800  /* not fcntl */ +#define TARGET_O_DSYNC          0x2000 +#define TARGET_O_NONBLOCK       0x4000 +# ifdef TARGET_SPARC64 +#  define TARGET_O_NDELAY       0x0004 +# else +#  define TARGET_O_NDELAY       (0x0004 | TARGET_O_NONBLOCK) +# endif +#define TARGET_O_NOCTTY         0x8000  /* not fcntl */ +#define TARGET_O_LARGEFILE     0x40000 +#define TARGET_O_DIRECT       0x100000  /* direct disk access hint */ +#define TARGET_O_NOATIME      0x200000 +#define TARGET_O_CLOEXEC      0x400000 +#define TARGET___O_SYNC       0x800000 +#define TARGET_O_PATH        0x1000000 +#endif + +/* <asm-generic/fcntl.h> values follow.  */ +#define TARGET_O_ACCMODE          0003 +#define TARGET_O_RDONLY             00 +#define TARGET_O_WRONLY             01 +#define TARGET_O_RDWR               02 +#ifndef TARGET_O_CREAT +#define TARGET_O_CREAT            0100 /* not fcntl */ +#endif +#ifndef TARGET_O_EXCL +#define TARGET_O_EXCL             0200 /* not fcntl */ +#endif +#ifndef TARGET_O_NOCTTY +#define TARGET_O_NOCTTY           0400 /* not fcntl */ +#endif +#ifndef TARGET_O_TRUNC +#define TARGET_O_TRUNC           01000 /* not fcntl */ +#endif +#ifndef TARGET_O_APPEND +#define TARGET_O_APPEND          02000 +#endif +#ifndef TARGET_O_NONBLOCK +#define TARGET_O_NONBLOCK        04000 +#endif +#ifndef TARGET_O_DSYNC +#define TARGET_O_DSYNC          010000 +#endif +#ifndef TARGET_FASYNC +#define TARGET_FASYNC           020000 /* fcntl, for BSD compatibility */ +#endif +#ifndef TARGET_O_DIRECT +#define TARGET_O_DIRECT         040000 /* direct disk access hint */ +#endif +#ifndef TARGET_O_LARGEFILE +#define TARGET_O_LARGEFILE     0100000 +#endif +#ifndef TARGET_O_DIRECTORY +#define TARGET_O_DIRECTORY     0200000 /* must be a directory */ +#endif +#ifndef TARGET_O_NOFOLLOW +#define TARGET_O_NOFOLLOW      0400000 /* don't follow links */ +#endif +#ifndef TARGET_O_NOATIME +#define TARGET_O_NOATIME      01000000 +#endif +#ifndef TARGET_O_CLOEXEC +#define TARGET_O_CLOEXEC      02000000 +#endif +#ifndef TARGET___O_SYNC +#define TARGET___O_SYNC       04000000 +#endif +#ifndef TARGET_O_PATH +#define TARGET_O_PATH        010000000 +#endif +#ifndef TARGET_O_NDELAY +#define TARGET_O_NDELAY  TARGET_O_NONBLOCK +#endif +#ifndef TARGET_O_SYNC +#define TARGET_O_SYNC    (TARGET___O_SYNC | TARGET_O_DSYNC) +#endif + +struct target_flock { +	short l_type; +	short l_whence; +	abi_ulong l_start; +	abi_ulong l_len; +	int l_pid; +}; + +struct target_flock64 { +	short  l_type; +	short  l_whence; +#if defined(TARGET_PPC) || defined(TARGET_X86_64) || defined(TARGET_MIPS) || defined(TARGET_SPARC) || defined(TARGET_HPPA) || defined (TARGET_MICROBLAZE) +        int __pad; +#endif +	unsigned long long l_start; +	unsigned long long l_len; +	int  l_pid; +} QEMU_PACKED; + +#ifdef TARGET_ARM +struct target_eabi_flock64 { +	short  l_type; +	short  l_whence; +        int __pad; +	unsigned long long l_start; +	unsigned long long l_len; +	int  l_pid; +} QEMU_PACKED; +#endif + +struct target_f_owner_ex { +        int type;	/* Owner type of ID.  */ +        int pid;	/* ID of owner.  */ +}; + +/* soundcard defines */ +/* XXX: convert them all to arch indepedent entries */ +#define TARGET_SNDCTL_COPR_HALT           TARGET_IOWR('C',  7, int); +#define TARGET_SNDCTL_COPR_LOAD           0xcfb04301 +#define TARGET_SNDCTL_COPR_RCODE          0xc0144303 +#define TARGET_SNDCTL_COPR_RCVMSG         0x8fa44309 +#define TARGET_SNDCTL_COPR_RDATA          0xc0144302 +#define TARGET_SNDCTL_COPR_RESET          0x00004300 +#define TARGET_SNDCTL_COPR_RUN            0xc0144306 +#define TARGET_SNDCTL_COPR_SENDMSG        0xcfa44308 +#define TARGET_SNDCTL_COPR_WCODE          0x40144305 +#define TARGET_SNDCTL_COPR_WDATA          0x40144304 +#define TARGET_SNDCTL_DSP_RESET           TARGET_IO('P', 0) +#define TARGET_SNDCTL_DSP_SYNC            TARGET_IO('P', 1) +#define TARGET_SNDCTL_DSP_SPEED           TARGET_IOWR('P', 2, int) +#define TARGET_SNDCTL_DSP_STEREO          TARGET_IOWR('P', 3, int) +#define TARGET_SNDCTL_DSP_GETBLKSIZE      TARGET_IOWR('P', 4, int) +#define TARGET_SNDCTL_DSP_SETFMT          TARGET_IOWR('P', 5, int) +#define TARGET_SNDCTL_DSP_CHANNELS        TARGET_IOWR('P', 6, int) +#define TARGET_SOUND_PCM_WRITE_FILTER     TARGET_IOWR('P', 7, int) +#define TARGET_SNDCTL_DSP_POST            TARGET_IO('P', 8) +#define TARGET_SNDCTL_DSP_SUBDIVIDE       TARGET_IOWR('P', 9, int) +#define TARGET_SNDCTL_DSP_SETFRAGMENT     TARGET_IOWR('P',10, int) +#define TARGET_SNDCTL_DSP_GETFMTS         TARGET_IOR('P', 11, int) +#define TARGET_SNDCTL_DSP_GETOSPACE       TARGET_IORU('P',12) +#define TARGET_SNDCTL_DSP_GETISPACE       TARGET_IORU('P',13) +#define TARGET_SNDCTL_DSP_GETCAPS         TARGET_IOR('P', 15, int) +#define TARGET_SNDCTL_DSP_GETTRIGGER      TARGET_IOR('P',16, int) +#define TARGET_SNDCTL_DSP_GETIPTR         TARGET_IORU('P',17) +#define TARGET_SNDCTL_DSP_GETOPTR         TARGET_IORU('P',18) +#define TARGET_SNDCTL_DSP_MAPINBUF        TARGET_IORU('P', 19) +#define TARGET_SNDCTL_DSP_MAPOUTBUF       TARGET_IORU('P', 20) +#define TARGET_SNDCTL_DSP_NONBLOCK        0x0000500e +#define TARGET_SNDCTL_DSP_SAMPLESIZE      0xc0045005 +#define TARGET_SNDCTL_DSP_SETDUPLEX       0x00005016 +#define TARGET_SNDCTL_DSP_SETSYNCRO       0x00005015 +#define TARGET_SNDCTL_DSP_SETTRIGGER      0x40045010 +#define TARGET_SNDCTL_FM_4OP_ENABLE       0x4004510f +#define TARGET_SNDCTL_FM_LOAD_INSTR       0x40285107 +#define TARGET_SNDCTL_MIDI_INFO           0xc074510c +#define TARGET_SNDCTL_MIDI_MPUCMD         0xc0216d02 +#define TARGET_SNDCTL_MIDI_MPUMODE        0xc0046d01 +#define TARGET_SNDCTL_MIDI_PRETIME        0xc0046d00 +#define TARGET_SNDCTL_PMGR_ACCESS         0xcfb85110 +#define TARGET_SNDCTL_PMGR_IFACE          0xcfb85001 +#define TARGET_SNDCTL_SEQ_CTRLRATE        0xc0045103 +#define TARGET_SNDCTL_SEQ_GETINCOUNT      0x80045105 +#define TARGET_SNDCTL_SEQ_GETOUTCOUNT     0x80045104 +#define TARGET_SNDCTL_SEQ_NRMIDIS         0x8004510b +#define TARGET_SNDCTL_SEQ_NRSYNTHS        0x8004510a +#define TARGET_SNDCTL_SEQ_OUTOFBAND       0x40085112 +#define TARGET_SNDCTL_SEQ_PANIC           0x00005111 +#define TARGET_SNDCTL_SEQ_PERCMODE        0x40045106 +#define TARGET_SNDCTL_SEQ_RESET           0x00005100 +#define TARGET_SNDCTL_SEQ_RESETSAMPLES    0x40045109 +#define TARGET_SNDCTL_SEQ_SYNC            0x00005101 +#define TARGET_SNDCTL_SEQ_TESTMIDI        0x40045108 +#define TARGET_SNDCTL_SEQ_THRESHOLD       0x4004510d +#define TARGET_SNDCTL_SEQ_TRESHOLD        0x4004510d +#define TARGET_SNDCTL_SYNTH_INFO          0xc08c5102 +#define TARGET_SNDCTL_SYNTH_MEMAVL        0xc004510e +#define TARGET_SNDCTL_TMR_CONTINUE        0x00005404 +#define TARGET_SNDCTL_TMR_METRONOME       0x40045407 +#define TARGET_SNDCTL_TMR_SELECT          0x40045408 +#define TARGET_SNDCTL_TMR_SOURCE          0xc0045406 +#define TARGET_SNDCTL_TMR_START           0x00005402 +#define TARGET_SNDCTL_TMR_STOP            0x00005403 +#define TARGET_SNDCTL_TMR_TEMPO           0xc0045405 +#define TARGET_SNDCTL_TMR_TIMEBASE        0xc0045401 +#define TARGET_SOUND_PCM_READ_RATE        0x80045002 +#define TARGET_SOUND_PCM_READ_CHANNELS    0x80045006 +#define TARGET_SOUND_PCM_READ_BITS        0x80045005 +#define TARGET_SOUND_PCM_READ_FILTER      0x80045007 +#define TARGET_SOUND_MIXER_INFO           TARGET_IOR ('M', 101, mixer_info) +#define TARGET_SOUND_MIXER_ACCESS         0xc0804d66 +#define TARGET_SOUND_MIXER_PRIVATE1       TARGET_IOWR('M', 111, int) +#define TARGET_SOUND_MIXER_PRIVATE2       TARGET_IOWR('M', 112, int) +#define TARGET_SOUND_MIXER_PRIVATE3       TARGET_IOWR('M', 113, int) +#define TARGET_SOUND_MIXER_PRIVATE4       TARGET_IOWR('M', 114, int) +#define TARGET_SOUND_MIXER_PRIVATE5       TARGET_IOWR('M', 115, int) + +#define TARGET_MIXER_READ(dev)	TARGET_IOR('M', dev, int) + +#define TARGET_SOUND_MIXER_READ_VOLUME		TARGET_MIXER_READ(SOUND_MIXER_VOLUME) +#define TARGET_SOUND_MIXER_READ_BASS		TARGET_MIXER_READ(SOUND_MIXER_BASS) +#define TARGET_SOUND_MIXER_READ_TREBLE		TARGET_MIXER_READ(SOUND_MIXER_TREBLE) +#define TARGET_SOUND_MIXER_READ_SYNTH		TARGET_MIXER_READ(SOUND_MIXER_SYNTH) +#define TARGET_SOUND_MIXER_READ_PCM		TARGET_MIXER_READ(SOUND_MIXER_PCM) +#define TARGET_SOUND_MIXER_READ_SPEAKER	        TARGET_MIXER_READ(SOUND_MIXER_SPEAKER) +#define TARGET_SOUND_MIXER_READ_LINE		TARGET_MIXER_READ(SOUND_MIXER_LINE) +#define TARGET_SOUND_MIXER_READ_MIC		TARGET_MIXER_READ(SOUND_MIXER_MIC) +#define TARGET_SOUND_MIXER_READ_CD		TARGET_MIXER_READ(SOUND_MIXER_CD) +#define TARGET_SOUND_MIXER_READ_IMIX		TARGET_MIXER_READ(SOUND_MIXER_IMIX) +#define TARGET_SOUND_MIXER_READ_ALTPCM		TARGET_MIXER_READ(SOUND_MIXER_ALTPCM) +#define TARGET_SOUND_MIXER_READ_RECLEV		TARGET_MIXER_READ(SOUND_MIXER_RECLEV) +#define TARGET_SOUND_MIXER_READ_IGAIN		TARGET_MIXER_READ(SOUND_MIXER_IGAIN) +#define TARGET_SOUND_MIXER_READ_OGAIN		TARGET_MIXER_READ(SOUND_MIXER_OGAIN) +#define TARGET_SOUND_MIXER_READ_LINE1		TARGET_MIXER_READ(SOUND_MIXER_LINE1) +#define TARGET_SOUND_MIXER_READ_LINE2		TARGET_MIXER_READ(SOUND_MIXER_LINE2) +#define TARGET_SOUND_MIXER_READ_LINE3		TARGET_MIXER_READ(SOUND_MIXER_LINE3) + +/* Obsolete macros */ +#define TARGET_SOUND_MIXER_READ_MUTE		TARGET_MIXER_READ(SOUND_MIXER_MUTE) +#define TARGET_SOUND_MIXER_READ_ENHANCE	        TARGET_MIXER_READ(SOUND_MIXER_ENHANCE) +#define TARGET_SOUND_MIXER_READ_LOUD		TARGET_MIXER_READ(SOUND_MIXER_LOUD) + +#define TARGET_SOUND_MIXER_READ_RECSRC		TARGET_MIXER_READ(SOUND_MIXER_RECSRC) +#define TARGET_SOUND_MIXER_READ_DEVMASK	        TARGET_MIXER_READ(SOUND_MIXER_DEVMASK) +#define TARGET_SOUND_MIXER_READ_RECMASK	        TARGET_MIXER_READ(SOUND_MIXER_RECMASK) +#define TARGET_SOUND_MIXER_READ_STEREODEVS	TARGET_MIXER_READ(SOUND_MIXER_STEREODEVS) +#define TARGET_SOUND_MIXER_READ_CAPS		TARGET_MIXER_READ(SOUND_MIXER_CAPS) + +#define TARGET_MIXER_WRITE(dev)		TARGET_IOWR('M', dev, int) + +#define TARGET_SOUND_MIXER_WRITE_VOLUME	TARGET_MIXER_WRITE(SOUND_MIXER_VOLUME) +#define TARGET_SOUND_MIXER_WRITE_BASS		TARGET_MIXER_WRITE(SOUND_MIXER_BASS) +#define TARGET_SOUND_MIXER_WRITE_TREBLE	TARGET_MIXER_WRITE(SOUND_MIXER_TREBLE) +#define TARGET_SOUND_MIXER_WRITE_SYNTH		TARGET_MIXER_WRITE(SOUND_MIXER_SYNTH) +#define TARGET_SOUND_MIXER_WRITE_PCM		TARGET_MIXER_WRITE(SOUND_MIXER_PCM) +#define TARGET_SOUND_MIXER_WRITE_SPEAKER	TARGET_MIXER_WRITE(SOUND_MIXER_SPEAKER) +#define TARGET_SOUND_MIXER_WRITE_LINE		TARGET_MIXER_WRITE(SOUND_MIXER_LINE) +#define TARGET_SOUND_MIXER_WRITE_MIC		TARGET_MIXER_WRITE(SOUND_MIXER_MIC) +#define TARGET_SOUND_MIXER_WRITE_CD		TARGET_MIXER_WRITE(SOUND_MIXER_CD) +#define TARGET_SOUND_MIXER_WRITE_IMIX		TARGET_MIXER_WRITE(SOUND_MIXER_IMIX) +#define TARGET_SOUND_MIXER_WRITE_ALTPCM	TARGET_MIXER_WRITE(SOUND_MIXER_ALTPCM) +#define TARGET_SOUND_MIXER_WRITE_RECLEV	TARGET_MIXER_WRITE(SOUND_MIXER_RECLEV) +#define TARGET_SOUND_MIXER_WRITE_IGAIN		TARGET_MIXER_WRITE(SOUND_MIXER_IGAIN) +#define TARGET_SOUND_MIXER_WRITE_OGAIN		TARGET_MIXER_WRITE(SOUND_MIXER_OGAIN) +#define TARGET_SOUND_MIXER_WRITE_LINE1		TARGET_MIXER_WRITE(SOUND_MIXER_LINE1) +#define TARGET_SOUND_MIXER_WRITE_LINE2		TARGET_MIXER_WRITE(SOUND_MIXER_LINE2) +#define TARGET_SOUND_MIXER_WRITE_LINE3		TARGET_MIXER_WRITE(SOUND_MIXER_LINE3) + +/* Obsolete macros */ +#define TARGET_SOUND_MIXER_WRITE_MUTE		TARGET_MIXER_WRITE(SOUND_MIXER_MUTE) +#define TARGET_SOUND_MIXER_WRITE_ENHANCE	TARGET_MIXER_WRITE(SOUND_MIXER_ENHANCE) +#define TARGET_SOUND_MIXER_WRITE_LOUD		TARGET_MIXER_WRITE(SOUND_MIXER_LOUD) + +#define TARGET_SOUND_MIXER_WRITE_RECSRC	TARGET_MIXER_WRITE(SOUND_MIXER_RECSRC) + +/* vfat ioctls */ +#define TARGET_VFAT_IOCTL_READDIR_BOTH    TARGET_IORU('r', 1) +#define TARGET_VFAT_IOCTL_READDIR_SHORT   TARGET_IORU('r', 2) + +#define TARGET_MTIOCTOP        TARGET_IOW('m', 1, struct mtop) +#define TARGET_MTIOCGET        TARGET_IOR('m', 2, struct mtget) +#define TARGET_MTIOCPOS        TARGET_IOR('m', 3, struct mtpos) + +struct target_sysinfo { +    abi_long uptime;                /* Seconds since boot */ +    abi_ulong loads[3];             /* 1, 5, and 15 minute load averages */ +    abi_ulong totalram;             /* Total usable main memory size */ +    abi_ulong freeram;              /* Available memory size */ +    abi_ulong sharedram;            /* Amount of shared memory */ +    abi_ulong bufferram;            /* Memory used by buffers */ +    abi_ulong totalswap;            /* Total swap space size */ +    abi_ulong freeswap;             /* swap space still available */ +    unsigned short procs;           /* Number of current processes */ +    unsigned short pad;             /* explicit padding for m68k */ +    abi_ulong totalhigh;            /* Total high memory size */ +    abi_ulong freehigh;             /* Available high memory size */ +    unsigned int mem_unit;          /* Memory unit size in bytes */ +    char _f[20-2*sizeof(abi_long)-sizeof(int)]; /* Padding: libc5 uses this.. */ +}; + +struct linux_dirent { +    long            d_ino; +    unsigned long   d_off; +    unsigned short  d_reclen; +    char            d_name[256]; /* We must not include limits.h! */ +}; + +struct linux_dirent64 { +    uint64_t        d_ino; +    int64_t         d_off; +    unsigned short  d_reclen; +    unsigned char   d_type; +    char            d_name[256]; +}; + +struct target_mq_attr { +    abi_long mq_flags; +    abi_long mq_maxmsg; +    abi_long mq_msgsize; +    abi_long mq_curmsgs; +}; + +#include "socket.h" + +#include "errno_defs.h" + +#define FUTEX_WAIT              0 +#define FUTEX_WAKE              1 +#define FUTEX_FD                2 +#define FUTEX_REQUEUE           3 +#define FUTEX_CMP_REQUEUE       4 +#define FUTEX_WAKE_OP           5 +#define FUTEX_LOCK_PI           6 +#define FUTEX_UNLOCK_PI         7 +#define FUTEX_TRYLOCK_PI        8 +#define FUTEX_WAIT_BITSET       9 +#define FUTEX_WAKE_BITSET       10 + +#define FUTEX_PRIVATE_FLAG      128 +#define FUTEX_CLOCK_REALTIME    256 +#define FUTEX_CMD_MASK          ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME) + +#ifdef CONFIG_EPOLL +typedef union target_epoll_data { +    abi_ulong ptr; +    abi_ulong fd; +    uint32_t u32; +    uint64_t u64; +} target_epoll_data_t; + +struct target_epoll_event { +    uint32_t events; +#if defined(TARGET_ARM) || defined(TARGET_MIPS) || defined(TARGET_MIPS64) +    uint32_t __pad; +#endif +    target_epoll_data_t data; +} QEMU_PACKED; +#endif +struct target_rlimit64 { +    uint64_t rlim_cur; +    uint64_t rlim_max; +}; + +struct target_ucred { +    uint32_t pid; +    uint32_t uid; +    uint32_t gid; +}; + +#endif + +typedef int32_t target_timer_t; + +#define TARGET_SIGEV_MAX_SIZE 64 + +/* This is architecture-specific but most architectures use the default */ +#ifdef TARGET_MIPS +#define TARGET_SIGEV_PREAMBLE_SIZE (sizeof(int32_t) * 2 + sizeof(abi_long)) +#else +#define TARGET_SIGEV_PREAMBLE_SIZE (sizeof(int32_t) * 2 \ +                                    + sizeof(target_sigval_t)) +#endif + +#define TARGET_SIGEV_PAD_SIZE ((TARGET_SIGEV_MAX_SIZE \ +                                - TARGET_SIGEV_PREAMBLE_SIZE) \ +                               / sizeof(int32_t)) + +struct target_sigevent { +    target_sigval_t sigev_value; +    int32_t sigev_signo; +    int32_t sigev_notify; +    union { +        int32_t _pad[TARGET_SIGEV_PAD_SIZE]; +        int32_t _tid; + +        struct { +            void (*_function)(sigval_t); +            void *_attribute; +        } _sigev_thread; +    } _sigev_un; +}; + +struct target_user_cap_header { +    uint32_t version; +    int pid; +}; + +struct target_user_cap_data { +    uint32_t effective; +    uint32_t permitted; +    uint32_t inheritable; +}; diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h new file mode 100644 index 00000000..1fd4ee0b --- /dev/null +++ b/linux-user/syscall_types.h @@ -0,0 +1,255 @@ +STRUCT_SPECIAL(termios) + +STRUCT(winsize, +       TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT) + +STRUCT(serial_multiport_struct, +       TYPE_INT, TYPE_INT, TYPE_CHAR, TYPE_CHAR, TYPE_INT, TYPE_CHAR, TYPE_CHAR, +       TYPE_INT, TYPE_CHAR, TYPE_CHAR, TYPE_INT, TYPE_CHAR, TYPE_CHAR, TYPE_INT, +       MK_ARRAY(TYPE_INT, 32)) + +STRUCT(serial_icounter_struct, +       TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, MK_ARRAY(TYPE_INT, 16)) + +STRUCT(sockaddr, +       TYPE_SHORT, MK_ARRAY(TYPE_CHAR, 14)) + +STRUCT(rtentry, +       TYPE_ULONG, MK_STRUCT(STRUCT_sockaddr), MK_STRUCT(STRUCT_sockaddr), MK_STRUCT(STRUCT_sockaddr), +       TYPE_SHORT, TYPE_SHORT, TYPE_ULONG, TYPE_PTRVOID, TYPE_SHORT, TYPE_PTRVOID, +       TYPE_ULONG, TYPE_ULONG, TYPE_SHORT) + +STRUCT(ifmap, +       TYPE_ULONG, TYPE_ULONG, TYPE_SHORT, TYPE_CHAR, TYPE_CHAR, TYPE_CHAR, +       /* Spare 3 bytes */ +       TYPE_CHAR, TYPE_CHAR, TYPE_CHAR) + +/* The *_ifreq_list arrays deal with the fact that struct ifreq has unions */ + +STRUCT(sockaddr_ifreq, +       MK_ARRAY(TYPE_CHAR, IFNAMSIZ), MK_STRUCT(STRUCT_sockaddr)) + +STRUCT(short_ifreq, +       MK_ARRAY(TYPE_CHAR, IFNAMSIZ), TYPE_SHORT) + +STRUCT(int_ifreq, +       MK_ARRAY(TYPE_CHAR, IFNAMSIZ), TYPE_INT) + +STRUCT(ifmap_ifreq, +       MK_ARRAY(TYPE_CHAR, IFNAMSIZ), MK_STRUCT(STRUCT_ifmap)) + +STRUCT(char_ifreq, +       MK_ARRAY(TYPE_CHAR, IFNAMSIZ), +       MK_ARRAY(TYPE_CHAR, IFNAMSIZ)) + +STRUCT(ptr_ifreq, +       MK_ARRAY(TYPE_CHAR, IFNAMSIZ), TYPE_PTRVOID) + +STRUCT(ifconf, +       TYPE_INT, TYPE_PTRVOID) + +STRUCT(arpreq, +       MK_STRUCT(STRUCT_sockaddr), MK_STRUCT(STRUCT_sockaddr), TYPE_INT, MK_STRUCT(STRUCT_sockaddr), +       MK_ARRAY(TYPE_CHAR, 16)) + +STRUCT(arpreq_old, +       MK_STRUCT(STRUCT_sockaddr), MK_STRUCT(STRUCT_sockaddr), TYPE_INT, MK_STRUCT(STRUCT_sockaddr)) + +STRUCT(cdrom_read_audio, +       TYPE_CHAR, TYPE_CHAR, TYPE_CHAR, TYPE_CHAR, TYPE_CHAR, TYPE_INT, TYPE_PTRVOID, +       TYPE_NULL) + +STRUCT(hd_geometry, +       TYPE_CHAR, TYPE_CHAR, TYPE_SHORT, TYPE_ULONG) + +STRUCT(dirent, +       TYPE_LONG, TYPE_LONG, TYPE_SHORT, MK_ARRAY(TYPE_CHAR, 256)) + +STRUCT(kbentry, +       TYPE_CHAR, TYPE_CHAR, TYPE_SHORT) + +STRUCT(kbsentry, +       TYPE_CHAR, MK_ARRAY(TYPE_CHAR, 512)) + +STRUCT(audio_buf_info, +       TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT) + +STRUCT(count_info, +       TYPE_INT, TYPE_INT, TYPE_INT) + +STRUCT(buffmem_desc, +       TYPE_PTRVOID, TYPE_INT) + +STRUCT(mixer_info, +       MK_ARRAY(TYPE_CHAR, 16), MK_ARRAY(TYPE_CHAR, 32), TYPE_INT, MK_ARRAY(TYPE_INT, 10)) + +/* loop device ioctls */ +STRUCT(loop_info, +       TYPE_INT,                 /* lo_number */ +       TYPE_OLDDEVT,             /* lo_device */ +       TYPE_ULONG,               /* lo_inode */ +       TYPE_OLDDEVT,             /* lo_rdevice */ +       TYPE_INT,                 /* lo_offset */ +       TYPE_INT,                 /* lo_encrypt_type */ +       TYPE_INT,                 /* lo_encrypt_key_size */ +       TYPE_INT,                 /* lo_flags */ +       MK_ARRAY(TYPE_CHAR, 64),  /* lo_name */ +       MK_ARRAY(TYPE_CHAR, 32),  /* lo_encrypt_key */ +       MK_ARRAY(TYPE_ULONG, 2),  /* lo_init */ +       MK_ARRAY(TYPE_CHAR, 4))   /* reserved */ + +STRUCT(loop_info64, +       TYPE_ULONGLONG,           /* lo_device */ +       TYPE_ULONGLONG,           /* lo_inode */ +       TYPE_ULONGLONG,           /* lo_rdevice */ +       TYPE_ULONGLONG,           /* lo_offset */ +       TYPE_ULONG,               /* lo_number */ +       TYPE_ULONG,               /* lo_encrypt_type */ +       TYPE_ULONG,               /* lo_encrypt_key_size */ +       TYPE_ULONG,               /* lo_flags */ +       MK_ARRAY(TYPE_CHAR, 64),  /* lo_name */ +       MK_ARRAY(TYPE_CHAR, 64),  /* lo_crypt_name */ +       MK_ARRAY(TYPE_CHAR, 32),  /* lo_encrypt_key */ +       MK_ARRAY(TYPE_ULONGLONG, 2))  /* lo_init */ + +/* mag tape ioctls */ +STRUCT(mtop, TYPE_SHORT, TYPE_INT) +STRUCT(mtget, TYPE_LONG, TYPE_LONG, TYPE_LONG, TYPE_LONG, TYPE_LONG, +       TYPE_INT, TYPE_INT) +STRUCT(mtpos, TYPE_LONG) + +STRUCT(fb_fix_screeninfo, +       MK_ARRAY(TYPE_CHAR, 16), /* id */ +       TYPE_ULONG, /* smem_start */ +       TYPE_INT, /* smem_len */ +       TYPE_INT, /* type */ +       TYPE_INT, /* type_aux */ +       TYPE_INT, /* visual */ +       TYPE_SHORT, /* xpanstep */ +       TYPE_SHORT, /* ypanstep */ +       TYPE_SHORT, /* ywrapstep */ +       TYPE_INT, /* line_length */ +       TYPE_ULONG, /* mmio_start */ +       TYPE_INT, /* mmio_len */ +       TYPE_INT, /* accel */ +       MK_ARRAY(TYPE_CHAR, 3)) /* reserved */ + +STRUCT(fb_var_screeninfo, +       TYPE_INT, /* xres */ +       TYPE_INT, /* yres */ +       TYPE_INT, /* xres_virtual */ +       TYPE_INT, /* yres_virtual */ +       TYPE_INT, /* xoffset */ +       TYPE_INT, /* yoffset */ +       TYPE_INT, /* bits_per_pixel */ +       TYPE_INT, /* grayscale */ +       MK_ARRAY(TYPE_INT, 3), /* red */ +       MK_ARRAY(TYPE_INT, 3), /* green */ +       MK_ARRAY(TYPE_INT, 3), /* blue */ +       MK_ARRAY(TYPE_INT, 3), /* transp */ +       TYPE_INT, /* nonstd */ +       TYPE_INT, /* activate */ +       TYPE_INT, /* height */ +       TYPE_INT, /* width */ +       TYPE_INT, /* accel_flags */ +       TYPE_INT, /* pixclock */ +       TYPE_INT, /* left_margin */ +       TYPE_INT, /* right_margin */ +       TYPE_INT, /* upper_margin */ +       TYPE_INT, /* lower_margin */ +       TYPE_INT, /* hsync_len */ +       TYPE_INT, /* vsync_len */ +       TYPE_INT, /* sync */ +       TYPE_INT, /* vmode */ +       TYPE_INT, /* rotate */ +       MK_ARRAY(TYPE_INT, 5)) /* reserved */ + +STRUCT(fb_cmap, +       TYPE_INT, /* start  */ +       TYPE_INT, /* len    */ +       TYPE_PTRVOID, /* red    */ +       TYPE_PTRVOID, /* green  */ +       TYPE_PTRVOID, /* blue   */ +       TYPE_PTRVOID) /* transp */ + +STRUCT(fb_con2fbmap, +       TYPE_INT, /* console     */ +       TYPE_INT) /* framebuffer */ + + +STRUCT(vt_stat, +       TYPE_SHORT, /* v_active */ +       TYPE_SHORT, /* v_signal */ +       TYPE_SHORT) /* v_state */ + +STRUCT(vt_mode, +       TYPE_CHAR,  /* mode   */ +       TYPE_CHAR,  /* waitv  */ +       TYPE_SHORT, /* relsig */ +       TYPE_SHORT, /* acqsig */ +       TYPE_SHORT) /* frsig  */ + +STRUCT(dm_ioctl, +       MK_ARRAY(TYPE_INT, 3), /* version */ +       TYPE_INT, /* data_size */ +       TYPE_INT, /* data_start */ +       TYPE_INT, /* target_count*/ +       TYPE_INT, /* open_count */ +       TYPE_INT, /* flags */ +       TYPE_INT, /* event_nr */ +       TYPE_INT, /* padding */ +       TYPE_ULONGLONG, /* dev */ +       MK_ARRAY(TYPE_CHAR, 128), /* name */ +       MK_ARRAY(TYPE_CHAR, 129), /* uuid */ +       MK_ARRAY(TYPE_CHAR, 7)) /* data */ + +STRUCT(dm_target_spec, +       TYPE_ULONGLONG, /* sector_start */ +       TYPE_ULONGLONG, /* length */ +       TYPE_INT, /* status */ +       TYPE_INT, /* next */ +       MK_ARRAY(TYPE_CHAR, 16)) /* target_type */ + +STRUCT(dm_target_deps, +       TYPE_INT, /* count */ +       TYPE_INT) /* padding */ + +STRUCT(dm_name_list, +       TYPE_ULONGLONG, /* dev */ +       TYPE_INT) /* next */ + +STRUCT(dm_target_versions, +       TYPE_INT, /* next */ +       MK_ARRAY(TYPE_INT, 3)) /* version*/ + +STRUCT(dm_target_msg, +       TYPE_ULONGLONG) /* sector */ + +STRUCT(fiemap_extent, +       TYPE_ULONGLONG, /* fe_logical */ +       TYPE_ULONGLONG, /* fe_physical */ +       TYPE_ULONGLONG, /* fe_length */ +       MK_ARRAY(TYPE_ULONGLONG, 2), /* fe_reserved64[2] */ +       TYPE_INT, /* fe_flags */ +       MK_ARRAY(TYPE_INT, 3)) /* fe_reserved[3] */ + +STRUCT(fiemap, +       TYPE_ULONGLONG, /* fm_start */ +       TYPE_ULONGLONG, /* fm_length */ +       TYPE_INT, /* fm_flags */ +       TYPE_INT, /* fm_mapped_extents */ +       TYPE_INT, /* fm_extent_count */ +       TYPE_INT) /* fm_reserved */ + +STRUCT(blkpg_partition, +       TYPE_LONGLONG, /* start */ +       TYPE_LONGLONG, /* length */ +       TYPE_INT, /* pno */ +       MK_ARRAY(TYPE_CHAR, BLKPG_DEVNAMELTH), /* devname */ +       MK_ARRAY(TYPE_CHAR, BLKPG_VOLNAMELTH)) /* volname */ + +STRUCT(blkpg_ioctl_arg, +       TYPE_INT, /* op */ +       TYPE_INT, /* flags */ +       TYPE_INT, /* datalen */ +       TYPE_PTRVOID) /* data */ diff --git a/linux-user/target_flat.h b/linux-user/target_flat.h new file mode 100644 index 00000000..0ba6bdd1 --- /dev/null +++ b/linux-user/target_flat.h @@ -0,0 +1,10 @@ +/* If your arch needs to do custom stuff, create your own target_flat.h + * header file in linux-user/<your arch>/ + */ +#define flat_argvp_envp_on_stack()                           1 +#define flat_reloc_valid(reloc, size)                        ((reloc) <= (size)) +#define flat_old_ram_flag(flag)                              (flag) +#define flat_get_relocate_addr(relval)                       (relval) +#define flat_get_addr_from_rp(rp, relval, flags, persistent) (rp) +#define flat_set_persistent(relval, persistent)              (*persistent) +#define flat_put_addr_at_rp(rp, addr, relval)                put_user_ual(addr, rp) diff --git a/linux-user/uaccess.c b/linux-user/uaccess.c new file mode 100644 index 00000000..a4d108c2 --- /dev/null +++ b/linux-user/uaccess.c @@ -0,0 +1,65 @@ +/* User memory access */ +#include <stdio.h> +#include <string.h> + +#include "qemu.h" + +/* copy_from_user() and copy_to_user() are usually used to copy data + * buffers between the target and host.  These internally perform + * locking/unlocking of the memory. + */ +abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len) +{ +    abi_long ret = 0; +    void *ghptr; + +    if ((ghptr = lock_user(VERIFY_READ, gaddr, len, 1))) { +        memcpy(hptr, ghptr, len); +        unlock_user(ghptr, gaddr, 0); +    } else +        ret = -TARGET_EFAULT; + +    return ret; +} + + +abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len) +{ +    abi_long ret = 0; +    void *ghptr; + +    if ((ghptr = lock_user(VERIFY_WRITE, gaddr, len, 0))) { +        memcpy(ghptr, hptr, len); +	unlock_user(ghptr, gaddr, len); +    } else +        ret = -TARGET_EFAULT; + +    return ret; +} + +/* Return the length of a string in target memory or -TARGET_EFAULT if +   access error  */ +abi_long target_strlen(abi_ulong guest_addr1) +{ +    uint8_t *ptr; +    abi_ulong guest_addr; +    int max_len, len; + +    guest_addr = guest_addr1; +    for(;;) { +        max_len = TARGET_PAGE_SIZE - (guest_addr & ~TARGET_PAGE_MASK); +        ptr = lock_user(VERIFY_READ, guest_addr, max_len, 1); +        if (!ptr) +            return -TARGET_EFAULT; +        len = qemu_strnlen((const char *)ptr, max_len); +        unlock_user(ptr, guest_addr, 0); +        guest_addr += len; +        /* we don't allow wrapping or integer overflow */ +        if (guest_addr == 0 ||  +            (guest_addr - guest_addr1) > 0x7fffffff) +            return -TARGET_EFAULT; +        if (len != max_len) +            break; +    } +    return guest_addr - guest_addr1; +} diff --git a/linux-user/uname.c b/linux-user/uname.c new file mode 100644 index 00000000..1e6560d7 --- /dev/null +++ b/linux-user/uname.c @@ -0,0 +1,169 @@ +/* + *  cpu to uname machine name map + * + *  Copyright (c) 2009 Loïc Minier + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> + +#include "qemu.h" +//#include "qemu-common.h" +#include "uname.h" + +/* return highest utsname machine name for emulated instruction set + * + * NB: the default emulated CPU ("any") might not match any existing CPU, e.g. + * on ARM it has all features turned on, so there is no perfect arch string to + * return here */ +const char *cpu_to_uname_machine(void *cpu_env) +{ +#if defined(TARGET_ARM) && !defined(TARGET_AARCH64) + +    /* utsname machine name on linux arm is CPU arch name + endianness, e.g. +     * armv7l; to get a list of CPU arch names from the linux source, use: +     *     grep arch_name: -A1 linux/arch/arm/mm/proc-*.S +     * see arch/arm/kernel/setup.c: setup_processor() +     */ + +    /* in theory, endianness is configurable on some ARM CPUs, but this isn't +     * used in user mode emulation */ +#ifdef TARGET_WORDS_BIGENDIAN +#define utsname_suffix "b" +#else +#define utsname_suffix "l" +#endif +    if (arm_feature(cpu_env, ARM_FEATURE_V7)) +        return "armv7" utsname_suffix; +    if (arm_feature(cpu_env, ARM_FEATURE_V6)) +        return "armv6" utsname_suffix; +    /* earliest emulated CPU is ARMv5TE; qemu can emulate the 1026, but not its +     * Jazelle support */ +    return "armv5te" utsname_suffix; +#elif defined(TARGET_I386) && !defined(TARGET_X86_64) +    /* see arch/x86/kernel/cpu/bugs.c: check_bugs(), 386, 486, 586, 686 */ +    CPUState *cpu = ENV_GET_CPU((CPUX86State *)cpu_env); +    int family = object_property_get_int(OBJECT(cpu), "family", NULL); +    if (family == 4) { +        return "i486"; +    } +    if (family == 5) { +        return "i586"; +    } +    return "i686"; +#else +    /* default is #define-d in each arch/ subdir */ +    return UNAME_MACHINE; +#endif +} + + +#define COPY_UTSNAME_FIELD(dest, src) \ +  do { \ +      /* __NEW_UTS_LEN doesn't include terminating null */ \ +      (void) strncpy((dest), (src), __NEW_UTS_LEN); \ +      (dest)[__NEW_UTS_LEN] = '\0'; \ +  } while (0) + +int sys_uname(struct new_utsname *buf) +{ +  struct utsname uts_buf; + +  if (uname(&uts_buf) < 0) +      return (-1); + +  /* +   * Just in case these have some differences, we +   * translate utsname to new_utsname (which is the +   * struct linux kernel uses). +   */ + +  memset(buf, 0, sizeof(*buf)); +  COPY_UTSNAME_FIELD(buf->sysname, uts_buf.sysname); +  COPY_UTSNAME_FIELD(buf->nodename, uts_buf.nodename); +  COPY_UTSNAME_FIELD(buf->release, uts_buf.release); +  COPY_UTSNAME_FIELD(buf->version, uts_buf.version); +  COPY_UTSNAME_FIELD(buf->machine, uts_buf.machine); +#ifdef _GNU_SOURCE +  COPY_UTSNAME_FIELD(buf->domainname, uts_buf.domainname); +#endif +  return (0); + +#undef COPY_UTSNAME_FIELD +} + +static int relstr_to_int(const char *s) +{ +    /* Convert a uname release string like "2.6.18" to an integer +     * of the form 0x020612. (Beware that 0x020612 is *not* 2.6.12.) +     */ +    int i, n, tmp; + +    tmp = 0; +    for (i = 0; i < 3; i++) { +        n = 0; +        while (*s >= '0' && *s <= '9') { +            n *= 10; +            n += *s - '0'; +            s++; +        } +        tmp = (tmp << 8) + n; +        if (*s == '.') { +            s++; +        } +    } +    return tmp; +} + +int get_osversion(void) +{ +    static int osversion; +    struct new_utsname buf; +    const char *s; + +    if (osversion) +        return osversion; +    if (qemu_uname_release && *qemu_uname_release) { +        s = qemu_uname_release; +    } else { +        if (sys_uname(&buf)) +            return 0; +        s = buf.release; +    } +    osversion = relstr_to_int(s); +    return osversion; +} + +void init_qemu_uname_release(void) +{ +    /* Initialize qemu_uname_release for later use. +     * If the host kernel is too old and the user hasn't asked for +     * a specific fake version number, we might want to fake a minimum +     * target kernel version. +     */ +    struct new_utsname buf; + +    if (qemu_uname_release && *qemu_uname_release) { +        return; +    } + +    if (sys_uname(&buf)) { +        return; +    } + +    if (relstr_to_int(buf.release) < relstr_to_int(UNAME_MINIMUM_RELEASE)) { +        qemu_uname_release = UNAME_MINIMUM_RELEASE; +    } +} diff --git a/linux-user/uname.h b/linux-user/uname.h new file mode 100644 index 00000000..cc62e76c --- /dev/null +++ b/linux-user/uname.h @@ -0,0 +1,10 @@ +#ifndef UNAME_H +#define UNAME_H 1 + +#include <sys/utsname.h> +#include <linux/utsname.h> + +const char *cpu_to_uname_machine(void *cpu_env); +int sys_uname(struct new_utsname *buf); + +#endif /* UNAME _H */ diff --git a/linux-user/unicore32/syscall.h b/linux-user/unicore32/syscall.h new file mode 100644 index 00000000..385a9756 --- /dev/null +++ b/linux-user/unicore32/syscall.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2010-2011 GUAN Xue-tao + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __UC32_SYSCALL_H__ +#define __UC32_SYSCALL_H__ +struct target_pt_regs { +    abi_ulong uregs[34]; +}; + +#define UC32_REG_pc             uregs[31] +#define UC32_REG_lr             uregs[30] +#define UC32_REG_sp             uregs[29] +#define UC32_REG_ip             uregs[28] +#define UC32_REG_fp             uregs[27] +#define UC32_REG_26             uregs[26] +#define UC32_REG_25             uregs[25] +#define UC32_REG_24             uregs[24] +#define UC32_REG_23             uregs[23] +#define UC32_REG_22             uregs[22] +#define UC32_REG_21             uregs[21] +#define UC32_REG_20             uregs[20] +#define UC32_REG_19             uregs[19] +#define UC32_REG_18             uregs[18] +#define UC32_REG_17             uregs[17] +#define UC32_REG_16             uregs[16] +#define UC32_REG_15             uregs[15] +#define UC32_REG_14             uregs[14] +#define UC32_REG_13             uregs[13] +#define UC32_REG_12             uregs[12] +#define UC32_REG_11             uregs[11] +#define UC32_REG_10             uregs[10] +#define UC32_REG_09             uregs[9] +#define UC32_REG_08             uregs[8] +#define UC32_REG_07             uregs[7] +#define UC32_REG_06             uregs[6] +#define UC32_REG_05             uregs[5] +#define UC32_REG_04             uregs[4] +#define UC32_REG_03             uregs[3] +#define UC32_REG_02             uregs[2] +#define UC32_REG_01             uregs[1] +#define UC32_REG_00             uregs[0] +#define UC32_REG_asr            uregs[32] +#define UC32_REG_ORIG_00        uregs[33] + +#define UC32_SYSCALL_BASE               0x900000 +#define UC32_SYSCALL_ARCH_BASE          0xf0000 +#define UC32_SYSCALL_NR_set_tls         (UC32_SYSCALL_ARCH_BASE + 5) + +#define UNAME_MACHINE "UniCore-II" +#define UNAME_MINIMUM_RELEASE "2.6.32" + +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_MLOCKALL_MCL_CURRENT 1 +#define TARGET_MLOCKALL_MCL_FUTURE  2 + +#endif /* __UC32_SYSCALL_H__ */ diff --git a/linux-user/unicore32/syscall_nr.h b/linux-user/unicore32/syscall_nr.h new file mode 100644 index 00000000..486b8c45 --- /dev/null +++ b/linux-user/unicore32/syscall_nr.h @@ -0,0 +1,371 @@ +/* + * This file contains the system call numbers for UniCore32 oldabi. + * + * Copyright (C) 2010-2011 GUAN Xue-tao + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#define TARGET_NR_restart_syscall               0 +#define TARGET_NR_exit                          1 +#define TARGET_NR_fork                          2 +#define TARGET_NR_read                          3 +#define TARGET_NR_write                         4 +#define TARGET_NR_open                          5 +#define TARGET_NR_close                         6 +#define TARGET_NR_waitpid                       7 +#define TARGET_NR_creat                         8 +#define TARGET_NR_link                          9 +#define TARGET_NR_unlink                        10 +#define TARGET_NR_execve                        11 +#define TARGET_NR_chdir                         12 +#define TARGET_NR_time                          13 +#define TARGET_NR_mknod                         14 +#define TARGET_NR_chmod                         15 +#define TARGET_NR_lchown                        16 +#define TARGET_NR_break                         17 +                                                /* 18 */ +#define TARGET_NR_lseek                         19 +#define TARGET_NR_getpid                        20 +#define TARGET_NR_mount                         21 +#define TARGET_NR_umount                        22 +#define TARGET_NR_setuid                        23 +#define TARGET_NR_getuid                        24 +#define TARGET_NR_stime                         25 +#define TARGET_NR_ptrace                        26 +#define TARGET_NR_alarm                         27 +                                                /* 28 */ +#define TARGET_NR_pause                         29 +#define TARGET_NR_utime                         30 +#define TARGET_NR_stty                          31 +#define TARGET_NR_gtty                          32 +#define TARGET_NR_access                        33 +#define TARGET_NR_nice                          34 +#define TARGET_NR_ftime                         35 +#define TARGET_NR_sync                          36 +#define TARGET_NR_kill                          37 +#define TARGET_NR_rename                        38 +#define TARGET_NR_mkdir                         39 +#define TARGET_NR_rmdir                         40 +#define TARGET_NR_dup                           41 +#define TARGET_NR_pipe                          42 +#define TARGET_NR_times                         43 +#define TARGET_NR_prof                          44 +#define TARGET_NR_brk                           45 +#define TARGET_NR_setgid                        46 +#define TARGET_NR_getgid                        47 +#define TARGET_NR_signal                        48 +#define TARGET_NR_geteuid                       49 +#define TARGET_NR_getegid                       50 +#define TARGET_NR_acct                          51 +#define TARGET_NR_umount2                       52 +#define TARGET_NR_lock                          53 +#define TARGET_NR_ioctl                         54 +#define TARGET_NR_fcntl                         55 +#define TARGET_NR_mpx                           56 +#define TARGET_NR_setpgid                       57 +#define TARGET_NR_ulimit                        58 +                                                /* 59 */ +#define TARGET_NR_umask                         60 +#define TARGET_NR_chroot                        61 +#define TARGET_NR_ustat                         62 +#define TARGET_NR_dup2                          63 +#define TARGET_NR_getppid                       64 +#define TARGET_NR_getpgrp                       65 +#define TARGET_NR_setsid                        66 +#define TARGET_NR_sigaction                     67 +#define TARGET_NR_sgetmask                      68 +#define TARGET_NR_ssetmask                      69 +#define TARGET_NR_setreuid                      70 +#define TARGET_NR_setregid                      71 +#define TARGET_NR_sigsuspend                    72 +#define TARGET_NR_sigpending                    73 +#define TARGET_NR_sethostname                   74 +#define TARGET_NR_setrlimit                     75 +#define TARGET_NR_getrlimit                     76 +#define TARGET_NR_getrusage                     77 +#define TARGET_NR_gettimeofday                  78 +#define TARGET_NR_settimeofday                  79 +#define TARGET_NR_getgroups                     80 +#define TARGET_NR_setgroups                     81 +#define TARGET_NR_select                        82 +#define TARGET_NR_symlink                       83 +                                                /* 84 */ +#define TARGET_NR_readlink                      85 +#define TARGET_NR_uselib                        86 +#define TARGET_NR_swapon                        87 +#define TARGET_NR_reboot                        88 +#define TARGET_NR_readdir                       89 +#define TARGET_NR_mmap                          90 +#define TARGET_NR_munmap                        91 +#define TARGET_NR_truncate                      92 +#define TARGET_NR_ftruncate                     93 +#define TARGET_NR_fchmod                        94 +#define TARGET_NR_fchown                        95 +#define TARGET_NR_getpriority                   96 +#define TARGET_NR_setpriority                   97 +#define TARGET_NR_profil                        98 +#define TARGET_NR_statfs                        99 +#define TARGET_NR_fstatfs                       100 +#define TARGET_NR_ioperm                        101 +#define TARGET_NR_socketcall                    102 +#define TARGET_NR_syslog                        103 +#define TARGET_NR_setitimer                     104 +#define TARGET_NR_getitimer                     105 +#define TARGET_NR_stat                          106 +#define TARGET_NR_lstat                         107 +#define TARGET_NR_fstat                         108 +                                                /* 109 */ +                                                /* 110 */ +#define TARGET_NR_vhangup                       111 +#define TARGET_NR_idle                          112 +#define TARGET_NR_syscall                       113 +#define TARGET_NR_wait4                         114 +#define TARGET_NR_swapoff                       115 +#define TARGET_NR_sysinfo                       116 +#define TARGET_NR_ipc                           117 +#define TARGET_NR_fsync                         118 +#define TARGET_NR_sigreturn                     119 +#define TARGET_NR_clone                         120 +#define TARGET_NR_setdomainname                 121 +#define TARGET_NR_uname                         122 +#define TARGET_NR_modify_ldt                    123 +#define TARGET_NR_adjtimex                      124 +#define TARGET_NR_mprotect                      125 +#define TARGET_NR_sigprocmask                   126 +#define TARGET_NR_create_module                 127 +#define TARGET_NR_init_module                   128 +#define TARGET_NR_delete_module                 129 +#define TARGET_NR_get_kernel_syms               130 +#define TARGET_NR_quotactl                      131 +#define TARGET_NR_getpgid                       132 +#define TARGET_NR_fchdir                        133 +#define TARGET_NR_bdflush                       134 +#define TARGET_NR_sysfs                         135 +#define TARGET_NR_personality                   136 +#define TARGET_NR_afs_syscall                   137 +#define TARGET_NR_setfsuid                      138 +#define TARGET_NR_setfsgid                      139 +#define TARGET_NR__llseek                       140 +#define TARGET_NR_getdents                      141 +#define TARGET_NR__newselect                    142 +#define TARGET_NR_flock                         143 +#define TARGET_NR_msync                         144 +#define TARGET_NR_readv                         145 +#define TARGET_NR_writev                        146 +#define TARGET_NR_getsid                        147 +#define TARGET_NR_fdatasync                     148 +#define TARGET_NR__sysctl                       149 +#define TARGET_NR_mlock                         150 +#define TARGET_NR_munlock                       151 +#define TARGET_NR_mlockall                      152 +#define TARGET_NR_munlockall                    153 +#define TARGET_NR_sched_setparam                154 +#define TARGET_NR_sched_getparam                155 +#define TARGET_NR_sched_setscheduler            156 +#define TARGET_NR_sched_getscheduler            157 +#define TARGET_NR_sched_yield                   158 +#define TARGET_NR_sched_get_priority_max        159 +#define TARGET_NR_sched_get_priority_min        160 +#define TARGET_NR_sched_rr_get_interval         161 +#define TARGET_NR_nanosleep                     162 +#define TARGET_NR_mremap                        163 +#define TARGET_NR_setresuid                     164 +#define TARGET_NR_getresuid                     165 +#define TARGET_NR_vm86                          166 +#define TARGET_NR_query_module                  167 +#define TARGET_NR_poll                          168 +#define TARGET_NR_nfsservctl                    169 +#define TARGET_NR_setresgid                     170 +#define TARGET_NR_getresgid                     171 +#define TARGET_NR_prctl                         172 +#define TARGET_NR_rt_sigreturn                  173 +#define TARGET_NR_rt_sigaction                  174 +#define TARGET_NR_rt_sigprocmask                175 +#define TARGET_NR_rt_sigpending                 176 +#define TARGET_NR_rt_sigtimedwait               177 +#define TARGET_NR_rt_sigqueueinfo               178 +#define TARGET_NR_rt_sigsuspend                 179 +#define TARGET_NR_pread64                       180 +#define TARGET_NR_pwrite64                      181 +#define TARGET_NR_chown                         182 +#define TARGET_NR_getcwd                        183 +#define TARGET_NR_capget                        184 +#define TARGET_NR_capset                        185 +#define TARGET_NR_sigaltstack                   186 +#define TARGET_NR_sendfile                      187 +                                                /* 188 */ +                                                /* 189 */ +#define TARGET_NR_vfork                         190 +#define TARGET_NR_ugetrlimit                    191 +#define TARGET_NR_mmap2                         192 +#define TARGET_NR_truncate64                    193 +#define TARGET_NR_ftruncate64                   194 +#define TARGET_NR_stat64                        195 +#define TARGET_NR_lstat64                       196 +#define TARGET_NR_fstat64                       197 +#define TARGET_NR_lchown32                      198 +#define TARGET_NR_getuid32                      199 +#define TARGET_NR_getgid32                      200 +#define TARGET_NR_geteuid32                     201 +#define TARGET_NR_getegid32                     202 +#define TARGET_NR_setreuid32                    203 +#define TARGET_NR_setregid32                    204 +#define TARGET_NR_getgroups32                   205 +#define TARGET_NR_setgroups32                   206 +#define TARGET_NR_fchown32                      207 +#define TARGET_NR_setresuid32                   208 +#define TARGET_NR_getresuid32                   209 +#define TARGET_NR_setresgid32                   210 +#define TARGET_NR_getresgid32                   211 +#define TARGET_NR_chown32                       212 +#define TARGET_NR_setuid32                      213 +#define TARGET_NR_setgid32                      214 +#define TARGET_NR_setfsuid32                    215 +#define TARGET_NR_setfsgid32                    216 +#define TARGET_NR_getdents64                    217 +#define TARGET_NR_pivot_root                    218 +#define TARGET_NR_mincore                       219 +#define TARGET_NR_madvise                       220 +#define TARGET_NR_fcntl64                       221 +                                                /* 222 */ +                                                /* 223 */ +#define TARGET_NR_gettid                        224 +#define TARGET_NR_readahead                     225 +#define TARGET_NR_setxattr                      226 +#define TARGET_NR_lsetxattr                     227 +#define TARGET_NR_fsetxattr                     228 +#define TARGET_NR_getxattr                      229 +#define TARGET_NR_lgetxattr                     230 +#define TARGET_NR_fgetxattr                     231 +#define TARGET_NR_listxattr                     232 +#define TARGET_NR_llistxattr                    233 +#define TARGET_NR_flistxattr                    234 +#define TARGET_NR_removexattr                   235 +#define TARGET_NR_lremovexattr                  236 +#define TARGET_NR_fremovexattr                  237 +#define TARGET_NR_tkill                         238 +#define TARGET_NR_sendfile64                    239 +#define TARGET_NR_futex                         240 +#define TARGET_NR_sched_setaffinity             241 +#define TARGET_NR_sched_getaffinity             242 +#define TARGET_NR_io_setup                      243 +#define TARGET_NR_io_destroy                    244 +#define TARGET_NR_io_getevents                  245 +#define TARGET_NR_io_submit                     246 +#define TARGET_NR_io_cancel                     247 +#define TARGET_NR_exit_group                    248 +#define TARGET_NR_lookup_dcookie                249 +#define TARGET_NR_epoll_create                  250 +#define TARGET_NR_epoll_ctl                     251 +#define TARGET_NR_epoll_wait                    252 +#define TARGET_NR_remap_file_pages              253 +                                                /* 254 */ +                                                /* 255 */ +                                                /* 256 */ +#define TARGET_NR_set_tid_address               256 +#define TARGET_NR_timer_create                  257 +#define TARGET_NR_timer_settime                 258 +#define TARGET_NR_timer_gettime                 259 +#define TARGET_NR_timer_getoverrun              260 +#define TARGET_NR_timer_delete                  261 +#define TARGET_NR_clock_settime                 262 +#define TARGET_NR_clock_gettime                 263 +#define TARGET_NR_clock_getres                  264 +#define TARGET_NR_clock_nanosleep               265 +#define TARGET_NR_statfs64                      266 +#define TARGET_NR_fstatfs64                     267 +#define TARGET_NR_tgkill                        268 +#define TARGET_NR_utimes                        269 +#define TARGET_NR_fadvise64_64                  270 +#define TARGET_NR_pciconfig_iobase              271 +#define TARGET_NR_pciconfig_read                272 +#define TARGET_NR_pciconfig_write               273 +#define TARGET_NR_mq_open                       274 +#define TARGET_NR_mq_unlink                     275 +#define TARGET_NR_mq_timedsend                  276 +#define TARGET_NR_mq_timedreceive               277 +#define TARGET_NR_mq_notify                     278 +#define TARGET_NR_mq_getsetattr                 279 +#define TARGET_NR_waitid                        280 +#define TARGET_NR_socket                        281 +#define TARGET_NR_bind                          282 +#define TARGET_NR_connect                       283 +#define TARGET_NR_listen                        284 +#define TARGET_NR_accept                        285 +#define TARGET_NR_getsockname                   286 +#define TARGET_NR_getpeername                   287 +#define TARGET_NR_socketpair                    288 +#define TARGET_NR_send                          289 +#define TARGET_NR_sendto                        290 +#define TARGET_NR_recv                          291 +#define TARGET_NR_recvfrom                      292 +#define TARGET_NR_shutdown                      293 +#define TARGET_NR_setsockopt                    294 +#define TARGET_NR_getsockopt                    295 +#define TARGET_NR_sendmsg                       296 +#define TARGET_NR_recvmsg                       297 +#define TARGET_NR_semop                         298 +#define TARGET_NR_semget                        299 +#define TARGET_NR_semctl                        300 +#define TARGET_NR_msgsnd                        301 +#define TARGET_NR_msgrcv                        302 +#define TARGET_NR_msgget                        303 +#define TARGET_NR_msgctl                        304 +#define TARGET_NR_shmat                         305 +#define TARGET_NR_shmdt                         306 +#define TARGET_NR_shmget                        307 +#define TARGET_NR_shmctl                        308 +#define TARGET_NR_add_key                       309 +#define TARGET_NR_request_key                   310 +#define TARGET_NR_keyctl                        311 +#define TARGET_NR_semtimedop                    312 +#define TARGET_NR_vserver                       313 +#define TARGET_NR_ioprio_set                    314 +#define TARGET_NR_ioprio_get                    315 +#define TARGET_NR_inotify_init                  316 +#define TARGET_NR_inotify_add_watch             317 +#define TARGET_NR_inotify_rm_watch              318 +#define TARGET_NR_mbind                         319 +#define TARGET_NR_get_mempolicy                 320 +#define TARGET_NR_set_mempolicy                 321 +#define TARGET_NR_openat                        322 +#define TARGET_NR_mkdirat                       323 +#define TARGET_NR_mknodat                       324 +#define TARGET_NR_fchownat                      325 +#define TARGET_NR_futimesat                     326 +#define TARGET_NR_fstatat64                     327 +#define TARGET_NR_unlinkat                      328 +#define TARGET_NR_renameat                      329 +#define TARGET_NR_linkat                        330 +#define TARGET_NR_symlinkat                     331 +#define TARGET_NR_readlinkat                    332 +#define TARGET_NR_fchmodat                      333 +#define TARGET_NR_faccessat                     334 +                                                /* 335 */ +                                                /* 336 */ +#define TARGET_NR_unshare                       337 +#define TARGET_NR_set_robust_list               338 +#define TARGET_NR_get_robust_list               339 +#define TARGET_NR_splice                        340 +#define TARGET_NR_sync_file_range2              341 +#define TARGET_NR_tee                           342 +#define TARGET_NR_vmsplice                      343 +#define TARGET_NR_move_pages                    344 +#define TARGET_NR_getcpu                        345 +                                                /* 346 */ +#define TARGET_NR_kexec_load                    347 +#define TARGET_NR_utimensat                     348 +#define TARGET_NR_signalfd                      349 +#define TARGET_NR_timerfd                       350 +#define TARGET_NR_eventfd                       351 +#define TARGET_NR_fallocate                     352 +#define TARGET_NR_timerfd_settime               353 +#define TARGET_NR_timerfd_gettime               354 +#define TARGET_NR_signalfd4                     355 +#define TARGET_NR_eventfd2                      356 +#define TARGET_NR_epoll_create1                 357 +#define TARGET_NR_dup3                          358 +#define TARGET_NR_pipe2                         359 +#define TARGET_NR_inotify_init1                 360 diff --git a/linux-user/unicore32/target_cpu.h b/linux-user/unicore32/target_cpu.h new file mode 100644 index 00000000..fb790871 --- /dev/null +++ b/linux-user/unicore32/target_cpu.h @@ -0,0 +1,27 @@ +/* + * UniCore32 specific CPU ABI and functions for linux-user + * + * Copyright (C) 2010-2012 Guan Xuetao + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation, or (at your option) any + * later version. See the COPYING file in the top-level directory. + */ +#ifndef TARGET_CPU_H +#define TARGET_CPU_H + +static inline void cpu_clone_regs(CPUUniCore32State *env, target_ulong newsp) +{ +    if (newsp) { +        env->regs[29] = newsp; +    } +    env->regs[0] = 0; +} + +static inline void cpu_set_tls(CPUUniCore32State *env, target_ulong newtls) +{ +    env->regs[16] = newtls; +} + +#endif diff --git a/linux-user/unicore32/target_signal.h b/linux-user/unicore32/target_signal.h new file mode 100644 index 00000000..8b255c45 --- /dev/null +++ b/linux-user/unicore32/target_signal.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2010-2011 GUAN Xue-tao + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef TARGET_SIGNAL_H +#define TARGET_SIGNAL_H + +/* this struct defines a stack used during syscall handling */ +typedef struct target_sigaltstack { +    abi_ulong ss_sp; +    abi_ulong ss_flags; +    abi_ulong ss_size; +} target_stack_t; + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK               1 +#define TARGET_SS_DISABLE               2 + +#define get_sp_from_cpustate(cpustate)  (cpustate->regs[29]) + +#endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/unicore32/target_structs.h b/linux-user/unicore32/target_structs.h new file mode 100644 index 00000000..78936950 --- /dev/null +++ b/linux-user/unicore32/target_structs.h @@ -0,0 +1,58 @@ +/* + * UniCore32 specific structures for linux-user + * + * Copyright (c) 2013 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_STRUCTS_H +#define TARGET_STRUCTS_H + +struct target_ipc_perm { +    abi_int __key;                      /* Key.  */ +    abi_uint uid;                       /* Owner's user ID.  */ +    abi_uint gid;                       /* Owner's group ID.  */ +    abi_uint cuid;                      /* Creator's user ID.  */ +    abi_uint cgid;                      /* Creator's group ID.  */ +    abi_ushort mode;                    /* Read/write permission.  */ +    abi_ushort __pad1; +    abi_ushort __seq;                   /* Sequence number.  */ +    abi_ushort __pad2; +    abi_ulong __unused1; +    abi_ulong __unused2; +}; + +struct target_shmid_ds { +    struct target_ipc_perm shm_perm;    /* operation permission struct */ +    abi_long shm_segsz;                 /* size of segment in bytes */ +    abi_ulong shm_atime;                /* time of last shmat() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused1; +#endif +    abi_ulong shm_dtime;                /* time of last shmdt() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused2; +#endif +    abi_ulong shm_ctime;                /* time of last change by shmctl() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused3; +#endif +    abi_int shm_cpid;                   /* pid of creator */ +    abi_int shm_lpid;                   /* pid of last shmop */ +    abi_ulong shm_nattch;               /* number of current attaches */ +    abi_ulong __unused4; +    abi_ulong __unused5; +}; + +#endif diff --git a/linux-user/unicore32/termbits.h b/linux-user/unicore32/termbits.h new file mode 100644 index 00000000..a5fcd64a --- /dev/null +++ b/linux-user/unicore32/termbits.h @@ -0,0 +1,2 @@ +/* NOTE: exactly the same as i386 */ +#include "../i386/termbits.h" diff --git a/linux-user/vm86.c b/linux-user/vm86.c new file mode 100644 index 00000000..22a4eb96 --- /dev/null +++ b/linux-user/vm86.c @@ -0,0 +1,495 @@ +/* + *  vm86 linux syscall support + * + *  Copyright (c) 2003 Fabrice Bellard + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, see <http://www.gnu.org/licenses/>. + */ +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> + +#include "qemu.h" + +//#define DEBUG_VM86 + +#ifdef DEBUG_VM86 +#  define LOG_VM86(...) qemu_log(__VA_ARGS__); +#else +#  define LOG_VM86(...) do { } while (0) +#endif + + +#define set_flags(X,new,mask) \ +((X) = ((X) & ~(mask)) | ((new) & (mask))) + +#define SAFE_MASK	(0xDD5) +#define RETURN_MASK	(0xDFF) + +static inline int is_revectored(int nr, struct target_revectored_struct *bitmap) +{ +    return (((uint8_t *)bitmap)[nr >> 3] >> (nr & 7)) & 1; +} + +static inline void vm_putw(CPUX86State *env, uint32_t segptr, +                           unsigned int reg16, unsigned int val) +{ +    cpu_stw_data(env, segptr + (reg16 & 0xffff), val); +} + +static inline void vm_putl(CPUX86State *env, uint32_t segptr, +                           unsigned int reg16, unsigned int val) +{ +    cpu_stl_data(env, segptr + (reg16 & 0xffff), val); +} + +static inline unsigned int vm_getb(CPUX86State *env, +                                   uint32_t segptr, unsigned int reg16) +{ +    return cpu_ldub_data(env, segptr + (reg16 & 0xffff)); +} + +static inline unsigned int vm_getw(CPUX86State *env, +                                   uint32_t segptr, unsigned int reg16) +{ +    return cpu_lduw_data(env, segptr + (reg16 & 0xffff)); +} + +static inline unsigned int vm_getl(CPUX86State *env, +                                   uint32_t segptr, unsigned int reg16) +{ +    return cpu_ldl_data(env, segptr + (reg16 & 0xffff)); +} + +void save_v86_state(CPUX86State *env) +{ +    CPUState *cs = CPU(x86_env_get_cpu(env)); +    TaskState *ts = cs->opaque; +    struct target_vm86plus_struct * target_v86; + +    if (!lock_user_struct(VERIFY_WRITE, target_v86, ts->target_v86, 0)) +        /* FIXME - should return an error */ +        return; +    /* put the VM86 registers in the userspace register structure */ +    target_v86->regs.eax = tswap32(env->regs[R_EAX]); +    target_v86->regs.ebx = tswap32(env->regs[R_EBX]); +    target_v86->regs.ecx = tswap32(env->regs[R_ECX]); +    target_v86->regs.edx = tswap32(env->regs[R_EDX]); +    target_v86->regs.esi = tswap32(env->regs[R_ESI]); +    target_v86->regs.edi = tswap32(env->regs[R_EDI]); +    target_v86->regs.ebp = tswap32(env->regs[R_EBP]); +    target_v86->regs.esp = tswap32(env->regs[R_ESP]); +    target_v86->regs.eip = tswap32(env->eip); +    target_v86->regs.cs = tswap16(env->segs[R_CS].selector); +    target_v86->regs.ss = tswap16(env->segs[R_SS].selector); +    target_v86->regs.ds = tswap16(env->segs[R_DS].selector); +    target_v86->regs.es = tswap16(env->segs[R_ES].selector); +    target_v86->regs.fs = tswap16(env->segs[R_FS].selector); +    target_v86->regs.gs = tswap16(env->segs[R_GS].selector); +    set_flags(env->eflags, ts->v86flags, VIF_MASK | ts->v86mask); +    target_v86->regs.eflags = tswap32(env->eflags); +    unlock_user_struct(target_v86, ts->target_v86, 1); +    LOG_VM86("save_v86_state: eflags=%08x cs:ip=%04x:%04x\n", +             env->eflags, env->segs[R_CS].selector, env->eip); + +    /* restore 32 bit registers */ +    env->regs[R_EAX] = ts->vm86_saved_regs.eax; +    env->regs[R_EBX] = ts->vm86_saved_regs.ebx; +    env->regs[R_ECX] = ts->vm86_saved_regs.ecx; +    env->regs[R_EDX] = ts->vm86_saved_regs.edx; +    env->regs[R_ESI] = ts->vm86_saved_regs.esi; +    env->regs[R_EDI] = ts->vm86_saved_regs.edi; +    env->regs[R_EBP] = ts->vm86_saved_regs.ebp; +    env->regs[R_ESP] = ts->vm86_saved_regs.esp; +    env->eflags = ts->vm86_saved_regs.eflags; +    env->eip = ts->vm86_saved_regs.eip; + +    cpu_x86_load_seg(env, R_CS, ts->vm86_saved_regs.cs); +    cpu_x86_load_seg(env, R_SS, ts->vm86_saved_regs.ss); +    cpu_x86_load_seg(env, R_DS, ts->vm86_saved_regs.ds); +    cpu_x86_load_seg(env, R_ES, ts->vm86_saved_regs.es); +    cpu_x86_load_seg(env, R_FS, ts->vm86_saved_regs.fs); +    cpu_x86_load_seg(env, R_GS, ts->vm86_saved_regs.gs); +} + +/* return from vm86 mode to 32 bit. The vm86() syscall will return +   'retval' */ +static inline void return_to_32bit(CPUX86State *env, int retval) +{ +    LOG_VM86("return_to_32bit: ret=0x%x\n", retval); +    save_v86_state(env); +    env->regs[R_EAX] = retval; +} + +static inline int set_IF(CPUX86State *env) +{ +    CPUState *cs = CPU(x86_env_get_cpu(env)); +    TaskState *ts = cs->opaque; + +    ts->v86flags |= VIF_MASK; +    if (ts->v86flags & VIP_MASK) { +        return_to_32bit(env, TARGET_VM86_STI); +        return 1; +    } +    return 0; +} + +static inline void clear_IF(CPUX86State *env) +{ +    CPUState *cs = CPU(x86_env_get_cpu(env)); +    TaskState *ts = cs->opaque; + +    ts->v86flags &= ~VIF_MASK; +} + +static inline void clear_TF(CPUX86State *env) +{ +    env->eflags &= ~TF_MASK; +} + +static inline void clear_AC(CPUX86State *env) +{ +    env->eflags &= ~AC_MASK; +} + +static inline int set_vflags_long(unsigned long eflags, CPUX86State *env) +{ +    CPUState *cs = CPU(x86_env_get_cpu(env)); +    TaskState *ts = cs->opaque; + +    set_flags(ts->v86flags, eflags, ts->v86mask); +    set_flags(env->eflags, eflags, SAFE_MASK); +    if (eflags & IF_MASK) +        return set_IF(env); +    else +        clear_IF(env); +    return 0; +} + +static inline int set_vflags_short(unsigned short flags, CPUX86State *env) +{ +    CPUState *cs = CPU(x86_env_get_cpu(env)); +    TaskState *ts = cs->opaque; + +    set_flags(ts->v86flags, flags, ts->v86mask & 0xffff); +    set_flags(env->eflags, flags, SAFE_MASK); +    if (flags & IF_MASK) +        return set_IF(env); +    else +        clear_IF(env); +    return 0; +} + +static inline unsigned int get_vflags(CPUX86State *env) +{ +    CPUState *cs = CPU(x86_env_get_cpu(env)); +    TaskState *ts = cs->opaque; +    unsigned int flags; + +    flags = env->eflags & RETURN_MASK; +    if (ts->v86flags & VIF_MASK) +        flags |= IF_MASK; +    flags |= IOPL_MASK; +    return flags | (ts->v86flags & ts->v86mask); +} + +#define ADD16(reg, val) reg = (reg & ~0xffff) | ((reg + (val)) & 0xffff) + +/* handle VM86 interrupt (NOTE: the CPU core currently does not +   support TSS interrupt revectoring, so this code is always executed) */ +static void do_int(CPUX86State *env, int intno) +{ +    CPUState *cs = CPU(x86_env_get_cpu(env)); +    TaskState *ts = cs->opaque; +    uint32_t int_addr, segoffs, ssp; +    unsigned int sp; + +    if (env->segs[R_CS].selector == TARGET_BIOSSEG) +        goto cannot_handle; +    if (is_revectored(intno, &ts->vm86plus.int_revectored)) +        goto cannot_handle; +    if (intno == 0x21 && is_revectored((env->regs[R_EAX] >> 8) & 0xff, +                                       &ts->vm86plus.int21_revectored)) +        goto cannot_handle; +    int_addr = (intno << 2); +    segoffs = cpu_ldl_data(env, int_addr); +    if ((segoffs >> 16) == TARGET_BIOSSEG) +        goto cannot_handle; +    LOG_VM86("VM86: emulating int 0x%x. CS:IP=%04x:%04x\n", +             intno, segoffs >> 16, segoffs & 0xffff); +    /* save old state */ +    ssp = env->segs[R_SS].selector << 4; +    sp = env->regs[R_ESP] & 0xffff; +    vm_putw(env, ssp, sp - 2, get_vflags(env)); +    vm_putw(env, ssp, sp - 4, env->segs[R_CS].selector); +    vm_putw(env, ssp, sp - 6, env->eip); +    ADD16(env->regs[R_ESP], -6); +    /* goto interrupt handler */ +    env->eip = segoffs & 0xffff; +    cpu_x86_load_seg(env, R_CS, segoffs >> 16); +    clear_TF(env); +    clear_IF(env); +    clear_AC(env); +    return; + cannot_handle: +    LOG_VM86("VM86: return to 32 bits int 0x%x\n", intno); +    return_to_32bit(env, TARGET_VM86_INTx | (intno << 8)); +} + +void handle_vm86_trap(CPUX86State *env, int trapno) +{ +    if (trapno == 1 || trapno == 3) { +        return_to_32bit(env, TARGET_VM86_TRAP + (trapno << 8)); +    } else { +        do_int(env, trapno); +    } +} + +#define CHECK_IF_IN_TRAP() \ +      if ((ts->vm86plus.vm86plus.flags & TARGET_vm86dbg_active) && \ +          (ts->vm86plus.vm86plus.flags & TARGET_vm86dbg_TFpendig)) \ +		newflags |= TF_MASK + +#define VM86_FAULT_RETURN \ +        if ((ts->vm86plus.vm86plus.flags & TARGET_force_return_for_pic) && \ +            (ts->v86flags & (IF_MASK | VIF_MASK))) \ +            return_to_32bit(env, TARGET_VM86_PICRETURN); \ +        return + +void handle_vm86_fault(CPUX86State *env) +{ +    CPUState *cs = CPU(x86_env_get_cpu(env)); +    TaskState *ts = cs->opaque; +    uint32_t csp, ssp; +    unsigned int ip, sp, newflags, newip, newcs, opcode, intno; +    int data32, pref_done; + +    csp = env->segs[R_CS].selector << 4; +    ip = env->eip & 0xffff; + +    ssp = env->segs[R_SS].selector << 4; +    sp = env->regs[R_ESP] & 0xffff; + +    LOG_VM86("VM86 exception %04x:%08x\n", +             env->segs[R_CS].selector, env->eip); + +    data32 = 0; +    pref_done = 0; +    do { +        opcode = vm_getb(env, csp, ip); +        ADD16(ip, 1); +        switch (opcode) { +        case 0x66:      /* 32-bit data */     data32=1; break; +        case 0x67:      /* 32-bit address */  break; +        case 0x2e:      /* CS */              break; +        case 0x3e:      /* DS */              break; +        case 0x26:      /* ES */              break; +        case 0x36:      /* SS */              break; +        case 0x65:      /* GS */              break; +        case 0x64:      /* FS */              break; +        case 0xf2:      /* repnz */	      break; +        case 0xf3:      /* rep */             break; +        default: pref_done = 1; +        } +    } while (!pref_done); + +    /* VM86 mode */ +    switch(opcode) { +    case 0x9c: /* pushf */ +        if (data32) { +            vm_putl(env, ssp, sp - 4, get_vflags(env)); +            ADD16(env->regs[R_ESP], -4); +        } else { +            vm_putw(env, ssp, sp - 2, get_vflags(env)); +            ADD16(env->regs[R_ESP], -2); +        } +        env->eip = ip; +        VM86_FAULT_RETURN; + +    case 0x9d: /* popf */ +        if (data32) { +            newflags = vm_getl(env, ssp, sp); +            ADD16(env->regs[R_ESP], 4); +        } else { +            newflags = vm_getw(env, ssp, sp); +            ADD16(env->regs[R_ESP], 2); +        } +        env->eip = ip; +        CHECK_IF_IN_TRAP(); +        if (data32) { +            if (set_vflags_long(newflags, env)) +                return; +        } else { +            if (set_vflags_short(newflags, env)) +                return; +        } +        VM86_FAULT_RETURN; + +    case 0xcd: /* int */ +        intno = vm_getb(env, csp, ip); +        ADD16(ip, 1); +        env->eip = ip; +        if (ts->vm86plus.vm86plus.flags & TARGET_vm86dbg_active) { +            if ( (ts->vm86plus.vm86plus.vm86dbg_intxxtab[intno >> 3] >> +                  (intno &7)) & 1) { +                return_to_32bit(env, TARGET_VM86_INTx + (intno << 8)); +                return; +            } +        } +        do_int(env, intno); +        break; + +    case 0xcf: /* iret */ +        if (data32) { +            newip = vm_getl(env, ssp, sp) & 0xffff; +            newcs = vm_getl(env, ssp, sp + 4) & 0xffff; +            newflags = vm_getl(env, ssp, sp + 8); +            ADD16(env->regs[R_ESP], 12); +        } else { +            newip = vm_getw(env, ssp, sp); +            newcs = vm_getw(env, ssp, sp + 2); +            newflags = vm_getw(env, ssp, sp + 4); +            ADD16(env->regs[R_ESP], 6); +        } +        env->eip = newip; +        cpu_x86_load_seg(env, R_CS, newcs); +        CHECK_IF_IN_TRAP(); +        if (data32) { +            if (set_vflags_long(newflags, env)) +                return; +        } else { +            if (set_vflags_short(newflags, env)) +                return; +        } +        VM86_FAULT_RETURN; + +    case 0xfa: /* cli */ +        env->eip = ip; +        clear_IF(env); +        VM86_FAULT_RETURN; + +    case 0xfb: /* sti */ +        env->eip = ip; +        if (set_IF(env)) +            return; +        VM86_FAULT_RETURN; + +    default: +        /* real VM86 GPF exception */ +        return_to_32bit(env, TARGET_VM86_UNKNOWN); +        break; +    } +} + +int do_vm86(CPUX86State *env, long subfunction, abi_ulong vm86_addr) +{ +    CPUState *cs = CPU(x86_env_get_cpu(env)); +    TaskState *ts = cs->opaque; +    struct target_vm86plus_struct * target_v86; +    int ret; + +    switch (subfunction) { +    case TARGET_VM86_REQUEST_IRQ: +    case TARGET_VM86_FREE_IRQ: +    case TARGET_VM86_GET_IRQ_BITS: +    case TARGET_VM86_GET_AND_RESET_IRQ: +        gemu_log("qemu: unsupported vm86 subfunction (%ld)\n", subfunction); +        ret = -TARGET_EINVAL; +        goto out; +    case TARGET_VM86_PLUS_INSTALL_CHECK: +        /* NOTE: on old vm86 stuff this will return the error +           from verify_area(), because the subfunction is +           interpreted as (invalid) address to vm86_struct. +           So the installation check works. +            */ +        ret = 0; +        goto out; +    } + +    /* save current CPU regs */ +    ts->vm86_saved_regs.eax = 0; /* default vm86 syscall return code */ +    ts->vm86_saved_regs.ebx = env->regs[R_EBX]; +    ts->vm86_saved_regs.ecx = env->regs[R_ECX]; +    ts->vm86_saved_regs.edx = env->regs[R_EDX]; +    ts->vm86_saved_regs.esi = env->regs[R_ESI]; +    ts->vm86_saved_regs.edi = env->regs[R_EDI]; +    ts->vm86_saved_regs.ebp = env->regs[R_EBP]; +    ts->vm86_saved_regs.esp = env->regs[R_ESP]; +    ts->vm86_saved_regs.eflags = env->eflags; +    ts->vm86_saved_regs.eip  = env->eip; +    ts->vm86_saved_regs.cs = env->segs[R_CS].selector; +    ts->vm86_saved_regs.ss = env->segs[R_SS].selector; +    ts->vm86_saved_regs.ds = env->segs[R_DS].selector; +    ts->vm86_saved_regs.es = env->segs[R_ES].selector; +    ts->vm86_saved_regs.fs = env->segs[R_FS].selector; +    ts->vm86_saved_regs.gs = env->segs[R_GS].selector; + +    ts->target_v86 = vm86_addr; +    if (!lock_user_struct(VERIFY_READ, target_v86, vm86_addr, 1)) +        return -TARGET_EFAULT; +    /* build vm86 CPU state */ +    ts->v86flags = tswap32(target_v86->regs.eflags); +    env->eflags = (env->eflags & ~SAFE_MASK) | +        (tswap32(target_v86->regs.eflags) & SAFE_MASK) | VM_MASK; + +    ts->vm86plus.cpu_type = tswapal(target_v86->cpu_type); +    switch (ts->vm86plus.cpu_type) { +    case TARGET_CPU_286: +        ts->v86mask = 0; +        break; +    case TARGET_CPU_386: +        ts->v86mask = NT_MASK | IOPL_MASK; +        break; +    case TARGET_CPU_486: +        ts->v86mask = AC_MASK | NT_MASK | IOPL_MASK; +        break; +    default: +        ts->v86mask = ID_MASK | AC_MASK | NT_MASK | IOPL_MASK; +        break; +    } + +    env->regs[R_EBX] = tswap32(target_v86->regs.ebx); +    env->regs[R_ECX] = tswap32(target_v86->regs.ecx); +    env->regs[R_EDX] = tswap32(target_v86->regs.edx); +    env->regs[R_ESI] = tswap32(target_v86->regs.esi); +    env->regs[R_EDI] = tswap32(target_v86->regs.edi); +    env->regs[R_EBP] = tswap32(target_v86->regs.ebp); +    env->regs[R_ESP] = tswap32(target_v86->regs.esp); +    env->eip = tswap32(target_v86->regs.eip); +    cpu_x86_load_seg(env, R_CS, tswap16(target_v86->regs.cs)); +    cpu_x86_load_seg(env, R_SS, tswap16(target_v86->regs.ss)); +    cpu_x86_load_seg(env, R_DS, tswap16(target_v86->regs.ds)); +    cpu_x86_load_seg(env, R_ES, tswap16(target_v86->regs.es)); +    cpu_x86_load_seg(env, R_FS, tswap16(target_v86->regs.fs)); +    cpu_x86_load_seg(env, R_GS, tswap16(target_v86->regs.gs)); +    ret = tswap32(target_v86->regs.eax); /* eax will be restored at +                                            the end of the syscall */ +    memcpy(&ts->vm86plus.int_revectored, +           &target_v86->int_revectored, 32); +    memcpy(&ts->vm86plus.int21_revectored, +           &target_v86->int21_revectored, 32); +    ts->vm86plus.vm86plus.flags = tswapal(target_v86->vm86plus.flags); +    memcpy(&ts->vm86plus.vm86plus.vm86dbg_intxxtab, +           target_v86->vm86plus.vm86dbg_intxxtab, 32); +    unlock_user_struct(target_v86, vm86_addr, 0); + +    LOG_VM86("do_vm86: cs:ip=%04x:%04x\n", +             env->segs[R_CS].selector, env->eip); +    /* now the virtual CPU is ready for vm86 execution ! */ + out: +    return ret; +} diff --git a/linux-user/x86_64/syscall.h b/linux-user/x86_64/syscall.h new file mode 100644 index 00000000..88b3c3fe --- /dev/null +++ b/linux-user/x86_64/syscall.h @@ -0,0 +1,102 @@ +#define __USER_CS	(0x33) +#define __USER_DS	(0x2B) + +struct target_pt_regs { +	abi_ulong r15; +	abi_ulong r14; +	abi_ulong r13; +	abi_ulong r12; +	abi_ulong rbp; +	abi_ulong rbx; +/* arguments: non interrupts/non tracing syscalls only save up to here */ + 	abi_ulong r11; +	abi_ulong r10; +	abi_ulong r9; +	abi_ulong r8; +	abi_ulong rax; +	abi_ulong rcx; +	abi_ulong rdx; +	abi_ulong rsi; +	abi_ulong rdi; +	abi_ulong orig_rax; +/* end of arguments */ +/* cpu exception frame or undefined */ +	abi_ulong rip; +	abi_ulong cs; +	abi_ulong eflags; +	abi_ulong rsp; +	abi_ulong ss; +/* top of stack page */ +}; + +/* Maximum number of LDT entries supported. */ +#define TARGET_LDT_ENTRIES	8192 +/* The size of each LDT entry. */ +#define TARGET_LDT_ENTRY_SIZE	8 + +#define TARGET_GDT_ENTRIES 16 +#define TARGET_GDT_ENTRY_TLS_ENTRIES 3 +#define TARGET_GDT_ENTRY_TLS_MIN 12 +#define TARGET_GDT_ENTRY_TLS_MAX 14 + +#if 0 // Redefine this +struct target_modify_ldt_ldt_s { +	unsigned int  entry_number; +        abi_ulong     base_addr; +	unsigned int  limit; +	unsigned int  seg_32bit:1; +	unsigned int  contents:2; +	unsigned int  read_exec_only:1; +	unsigned int  limit_in_pages:1; +	unsigned int  seg_not_present:1; +	unsigned int  useable:1; +	unsigned int  lm:1; +}; +#else +struct target_modify_ldt_ldt_s { +	unsigned int  entry_number; +        abi_ulong     base_addr; +	unsigned int  limit; +        unsigned int flags; +}; +#endif + +struct target_ipc64_perm +{ +	int		key; +	uint32_t	uid; +	uint32_t	gid; +	uint32_t	cuid; +	uint32_t	cgid; +	unsigned short		mode; +	unsigned short		__pad1; +	unsigned short		seq; +	unsigned short		__pad2; +	abi_ulong		__unused1; +	abi_ulong		__unused2; +}; + +struct target_msqid64_ds { +	struct target_ipc64_perm msg_perm; +	unsigned int msg_stime;	/* last msgsnd time */ +	unsigned int msg_rtime;	/* last msgrcv time */ +	unsigned int msg_ctime;	/* last change time */ +	abi_ulong  msg_cbytes;	/* current number of bytes on queue */ +	abi_ulong  msg_qnum;	/* number of messages in queue */ +	abi_ulong  msg_qbytes;	/* max number of bytes on queue */ +	unsigned int msg_lspid;	/* pid of last msgsnd */ +	unsigned int msg_lrpid;	/* last receive pid */ +	abi_ulong  __unused4; +	abi_ulong  __unused5; +}; + +#define UNAME_MACHINE "x86_64" +#define UNAME_MINIMUM_RELEASE "2.6.32" + +#define TARGET_ARCH_SET_GS 0x1001 +#define TARGET_ARCH_SET_FS 0x1002 +#define TARGET_ARCH_GET_FS 0x1003 +#define TARGET_ARCH_GET_GS 0x1004 +#define TARGET_MINSIGSTKSZ 2048 +#define TARGET_MLOCKALL_MCL_CURRENT 1 +#define TARGET_MLOCKALL_MCL_FUTURE  2 diff --git a/linux-user/x86_64/syscall_nr.h b/linux-user/x86_64/syscall_nr.h new file mode 100644 index 00000000..7c59e3a0 --- /dev/null +++ b/linux-user/x86_64/syscall_nr.h @@ -0,0 +1,314 @@ +#define TARGET_NR_read                                0 +#define TARGET_NR_write                               1 +#define TARGET_NR_open                                2 +#define TARGET_NR_close                               3 +#define TARGET_NR_stat                                4 +#define TARGET_NR_fstat                               5 +#define TARGET_NR_lstat                               6 +#define TARGET_NR_poll                                7 +#define TARGET_NR_lseek                               8 +#define TARGET_NR_mmap                                9 +#define TARGET_NR_mprotect                           10 +#define TARGET_NR_munmap                             11 +#define TARGET_NR_brk                                12 +#define TARGET_NR_rt_sigaction                       13 +#define TARGET_NR_rt_sigprocmask                     14 +#define TARGET_NR_rt_sigreturn                       15 +#define TARGET_NR_ioctl                              16 +#define TARGET_NR_pread64                            17 +#define TARGET_NR_pwrite64                           18 +#define TARGET_NR_readv                              19 +#define TARGET_NR_writev                             20 +#define TARGET_NR_access                             21 +#define TARGET_NR_pipe                               22 +#define TARGET_NR_select                             23 +#define TARGET_NR_sched_yield                        24 +#define TARGET_NR_mremap                             25 +#define TARGET_NR_msync                              26 +#define TARGET_NR_mincore                            27 +#define TARGET_NR_madvise                            28 +#define TARGET_NR_shmget                             29 +#define TARGET_NR_shmat                              30 +#define TARGET_NR_shmctl                             31 +#define TARGET_NR_dup                                32 +#define TARGET_NR_dup2                               33 +#define TARGET_NR_pause                              34 +#define TARGET_NR_nanosleep                          35 +#define TARGET_NR_getitimer                          36 +#define TARGET_NR_alarm                              37 +#define TARGET_NR_setitimer                          38 +#define TARGET_NR_getpid                             39 +#define TARGET_NR_sendfile                           40 +#define TARGET_NR_socket                             41 +#define TARGET_NR_connect                            42 +#define TARGET_NR_accept                             43 +#define TARGET_NR_sendto                             44 +#define TARGET_NR_recvfrom                           45 +#define TARGET_NR_sendmsg                            46 +#define TARGET_NR_recvmsg                            47 +#define TARGET_NR_shutdown                           48 +#define TARGET_NR_bind                               49 +#define TARGET_NR_listen                             50 +#define TARGET_NR_getsockname                        51 +#define TARGET_NR_getpeername                        52 +#define TARGET_NR_socketpair                         53 +#define TARGET_NR_setsockopt                         54 +#define TARGET_NR_getsockopt                         55 +#define TARGET_NR_clone                              56 +#define TARGET_NR_fork                               57 +#define TARGET_NR_vfork                              58 +#define TARGET_NR_execve                             59 +#define TARGET_NR_exit                               60 +#define TARGET_NR_wait4                              61 +#define TARGET_NR_kill                               62 +#define TARGET_NR_uname                              63 +#define TARGET_NR_semget                             64 +#define TARGET_NR_semop                              65 +#define TARGET_NR_semctl                             66 +#define TARGET_NR_shmdt                              67 +#define TARGET_NR_msgget                             68 +#define TARGET_NR_msgsnd                             69 +#define TARGET_NR_msgrcv                             70 +#define TARGET_NR_msgctl                             71 +#define TARGET_NR_fcntl                              72 +#define TARGET_NR_flock                              73 +#define TARGET_NR_fsync                              74 +#define TARGET_NR_fdatasync                          75 +#define TARGET_NR_truncate                           76 +#define TARGET_NR_ftruncate                          77 +#define TARGET_NR_getdents                           78 +#define TARGET_NR_getcwd                             79 +#define TARGET_NR_chdir                              80 +#define TARGET_NR_fchdir                             81 +#define TARGET_NR_rename                             82 +#define TARGET_NR_mkdir                              83 +#define TARGET_NR_rmdir                              84 +#define TARGET_NR_creat                              85 +#define TARGET_NR_link                               86 +#define TARGET_NR_unlink                             87 +#define TARGET_NR_symlink                            88 +#define TARGET_NR_readlink                           89 +#define TARGET_NR_chmod                              90 +#define TARGET_NR_fchmod                             91 +#define TARGET_NR_chown                              92 +#define TARGET_NR_fchown                             93 +#define TARGET_NR_lchown                             94 +#define TARGET_NR_umask                              95 +#define TARGET_NR_gettimeofday                       96 +#define TARGET_NR_getrlimit                          97 +#define TARGET_NR_getrusage                          98 +#define TARGET_NR_sysinfo                            99 +#define TARGET_NR_times                             100 +#define TARGET_NR_ptrace                            101 +#define TARGET_NR_getuid                            102 +#define TARGET_NR_syslog                            103 +#define TARGET_NR_getgid                            104 +#define TARGET_NR_setuid                            105 +#define TARGET_NR_setgid                            106 +#define TARGET_NR_geteuid                           107 +#define TARGET_NR_getegid                           108 +#define TARGET_NR_setpgid                           109 +#define TARGET_NR_getppid                           110 +#define TARGET_NR_getpgrp                           111 +#define TARGET_NR_setsid                            112 +#define TARGET_NR_setreuid                          113 +#define TARGET_NR_setregid                          114 +#define TARGET_NR_getgroups                         115 +#define TARGET_NR_setgroups                         116 +#define TARGET_NR_setresuid                         117 +#define TARGET_NR_getresuid                         118 +#define TARGET_NR_setresgid                         119 +#define TARGET_NR_getresgid                         120 +#define TARGET_NR_getpgid                           121 +#define TARGET_NR_setfsuid                          122 +#define TARGET_NR_setfsgid                          123 +#define TARGET_NR_getsid                            124 +#define TARGET_NR_capget                            125 +#define TARGET_NR_capset                            126 +#define TARGET_NR_rt_sigpending                     127 +#define TARGET_NR_rt_sigtimedwait                   128 +#define TARGET_NR_rt_sigqueueinfo                   129 +#define TARGET_NR_rt_sigsuspend                     130 +#define TARGET_NR_sigaltstack                       131 +#define TARGET_NR_utime                             132 +#define TARGET_NR_mknod                             133 +#define TARGET_NR_uselib                            134 +#define TARGET_NR_personality                       135 +#define TARGET_NR_ustat                             136 +#define TARGET_NR_statfs                            137 +#define TARGET_NR_fstatfs                           138 +#define TARGET_NR_sysfs                             139 +#define TARGET_NR_getpriority                       140 +#define TARGET_NR_setpriority                       141 +#define TARGET_NR_sched_setparam                    142 +#define TARGET_NR_sched_getparam                    143 +#define TARGET_NR_sched_setscheduler                144 +#define TARGET_NR_sched_getscheduler                145 +#define TARGET_NR_sched_get_priority_max            146 +#define TARGET_NR_sched_get_priority_min            147 +#define TARGET_NR_sched_rr_get_interval             148 +#define TARGET_NR_mlock                             149 +#define TARGET_NR_munlock                           150 +#define TARGET_NR_mlockall                          151 +#define TARGET_NR_munlockall                        152 +#define TARGET_NR_vhangup                           153 +#define TARGET_NR_modify_ldt                        154 +#define TARGET_NR_pivot_root                        155 +#define TARGET_NR__sysctl                           156 +#define TARGET_NR_prctl                             157 +#define TARGET_NR_arch_prctl                        158 +#define TARGET_NR_adjtimex                          159 +#define TARGET_NR_setrlimit                         160 +#define TARGET_NR_chroot                            161 +#define TARGET_NR_sync                              162 +#define TARGET_NR_acct                              163 +#define TARGET_NR_settimeofday                      164 +#define TARGET_NR_mount                             165 +#define TARGET_NR_umount2                           166 +#define TARGET_NR_swapon                            167 +#define TARGET_NR_swapoff                           168 +#define TARGET_NR_reboot                            169 +#define TARGET_NR_sethostname                       170 +#define TARGET_NR_setdomainname                     171 +#define TARGET_NR_iopl                              172 +#define TARGET_NR_ioperm                            173 +#define TARGET_NR_create_module                     174 +#define TARGET_NR_init_module                       175 +#define TARGET_NR_delete_module                     176 +#define TARGET_NR_get_kernel_syms                   177 +#define TARGET_NR_query_module                      178 +#define TARGET_NR_quotactl                          179 +#define TARGET_NR_nfsservctl                        180 +#define TARGET_NR_getpmsg                           181	/* reserved for LiS/STREAMS */ +#define TARGET_NR_putpmsg                           182	/* reserved for LiS/STREAMS */ +#define TARGET_NR_afs_syscall                       183	/* reserved for AFS */ +#define TARGET_NR_tuxcall      		184 /* reserved for tux */ +#define TARGET_NR_security			185 +#define TARGET_NR_gettid		186 +#define TARGET_NR_readahead		187 +#define TARGET_NR_setxattr		188 +#define TARGET_NR_lsetxattr		189 +#define TARGET_NR_fsetxattr		190 +#define TARGET_NR_getxattr		191 +#define TARGET_NR_lgetxattr		192 +#define TARGET_NR_fgetxattr		193 +#define TARGET_NR_listxattr		194 +#define TARGET_NR_llistxattr		195 +#define TARGET_NR_flistxattr		196 +#define TARGET_NR_removexattr	197 +#define TARGET_NR_lremovexattr	198 +#define TARGET_NR_fremovexattr	199 +#define TARGET_NR_tkill	200 +#define TARGET_NR_time      201 +#define TARGET_NR_futex     202 +#define TARGET_NR_sched_setaffinity    203 +#define TARGET_NR_sched_getaffinity     204 +#define TARGET_NR_set_thread_area	205 +#define TARGET_NR_io_setup	206 +#define TARGET_NR_io_destroy	207 +#define TARGET_NR_io_getevents	208 +#define TARGET_NR_io_submit	209 +#define TARGET_NR_io_cancel	210 +#define TARGET_NR_get_thread_area	211 +#define TARGET_NR_lookup_dcookie	212 +#define TARGET_NR_epoll_create	213 +#define TARGET_NR_epoll_ctl_old	214 +#define TARGET_NR_epoll_wait_old	215 +#define TARGET_NR_remap_file_pages	216 +#define TARGET_NR_getdents64	217 +#define TARGET_NR_set_tid_address	218 +#define TARGET_NR_restart_syscall	219 +#define TARGET_NR_semtimedop		220 +#define TARGET_NR_fadvise64		221 +#define TARGET_NR_timer_create		222 +#define TARGET_NR_timer_settime		223 +#define TARGET_NR_timer_gettime		224 +#define TARGET_NR_timer_getoverrun		225 +#define TARGET_NR_timer_delete	226 +#define TARGET_NR_clock_settime	227 +#define TARGET_NR_clock_gettime	228 +#define TARGET_NR_clock_getres	229 +#define TARGET_NR_clock_nanosleep	230 +#define TARGET_NR_exit_group		231 +#define TARGET_NR_epoll_wait		232 +#define TARGET_NR_epoll_ctl		233 +#define TARGET_NR_tgkill		234 +#define TARGET_NR_utimes		235 +#define TARGET_NR_vserver		236 +#define TARGET_NR_mbind 		237 +#define TARGET_NR_set_mempolicy 	238 +#define TARGET_NR_get_mempolicy 	239 +#define TARGET_NR_mq_open 		240 +#define TARGET_NR_mq_unlink 		241 +#define TARGET_NR_mq_timedsend 	242 +#define TARGET_NR_mq_timedreceive	243 +#define TARGET_NR_mq_notify 		244 +#define TARGET_NR_mq_getsetattr 	245 +#define TARGET_NR_kexec_load 	246 +#define TARGET_NR_waitid		247 +#define TARGET_NR_add_key		248 +#define TARGET_NR_request_key	249 +#define TARGET_NR_keyctl		250 +#define TARGET_NR_ioprio_set		251 +#define TARGET_NR_ioprio_get		252 +#define TARGET_NR_inotify_init	253 +#define TARGET_NR_inotify_add_watch	254 +#define TARGET_NR_inotify_rm_watch	255 +#define TARGET_NR_migrate_pages	256 +#define TARGET_NR_openat		257 +#define TARGET_NR_mkdirat		258 +#define TARGET_NR_mknodat		259 +#define TARGET_NR_fchownat		260 +#define TARGET_NR_futimesat		261 +#define TARGET_NR_newfstatat		262 +#define TARGET_NR_unlinkat		263 +#define TARGET_NR_renameat		264 +#define TARGET_NR_linkat		265 +#define TARGET_NR_symlinkat		266 +#define TARGET_NR_readlinkat		267 +#define TARGET_NR_fchmodat		268 +#define TARGET_NR_faccessat		269 +#define TARGET_NR_pselect6		270 +#define TARGET_NR_ppoll		271 +#define TARGET_NR_unshare		272 +#define TARGET_NR_set_robust_list	273 +#define TARGET_NR_get_robust_list	274 +#define TARGET_NR_splice		275 +#define TARGET_NR_tee		276 +#define TARGET_NR_sync_file_range	277 +#define TARGET_NR_vmsplice		278 +#define TARGET_NR_move_pages		279 +#define TARGET_NR_utimensat		280 +#define TARGET_NR_epoll_pwait	281 +#define TARGET_NR_signalfd		282 +#define TARGET_NR_timerfd		283 +#define TARGET_NR_eventfd		284 +#define TARGET_NR_fallocate		285 +#define TARGET_NR_timerfd_settime	286 +#define TARGET_NR_timerfd_gettime	287 +#define TARGET_NR_accept4		288 +#define TARGET_NR_signalfd4		289 +#define TARGET_NR_eventfd2		290 +#define TARGET_NR_epoll_create1	291 +#define TARGET_NR_dup3			292 +#define TARGET_NR_pipe2		293 +#define TARGET_NR_inotify_init1	294 +#define TARGET_NR_preadv                295 +#define TARGET_NR_pwritev               296 +#define TARGET_NR_rt_tgsigqueueinfo     297 +#define TARGET_NR_perf_event_open       298 +#define TARGET_NR_recvmmsg              299 +#define TARGET_NR_fanotify_init         300 +#define TARGET_NR_fanotify_mark         301 +#define TARGET_NR_prlimit64             302 +#define TARGET_NR_name_to_handle_at     303 +#define TARGET_NR_open_by_handle_at     304 +#define TARGET_NR_clock_adjtime         305 +#define TARGET_NR_syncfs                306 +#define TARGET_NR_sendmmsg              307 +#define TARGET_NR_setns                 308 +#define TARGET_NR_getcpu                309 +#define TARGET_NR_process_vm_readv      310 +#define TARGET_NR_process_vm_writev     311 +#define TARGET_NR_kcmp                  312 +#define TARGET_NR_finit_module          313 diff --git a/linux-user/x86_64/target_cpu.h b/linux-user/x86_64/target_cpu.h new file mode 100644 index 00000000..9ec7cbb7 --- /dev/null +++ b/linux-user/x86_64/target_cpu.h @@ -0,0 +1 @@ +#include "../i386/target_cpu.h" diff --git a/linux-user/x86_64/target_signal.h b/linux-user/x86_64/target_signal.h new file mode 100644 index 00000000..9baf7fbe --- /dev/null +++ b/linux-user/x86_64/target_signal.h @@ -0,0 +1,29 @@ +#ifndef TARGET_SIGNAL_H +#define TARGET_SIGNAL_H + +#include "cpu.h" + +/* this struct defines a stack used during syscall handling */ + +typedef struct target_sigaltstack { +	abi_ulong ss_sp; +	abi_long ss_flags; +	abi_ulong ss_size; +} target_stack_t; + + +/* + * sigaltstack controls + */ +#define TARGET_SS_ONSTACK	1 +#define TARGET_SS_DISABLE	2 + +#define TARGET_MINSIGSTKSZ	2048 +#define TARGET_SIGSTKSZ		8192 + +static inline abi_ulong get_sp_from_cpustate(CPUX86State *state) +{ +    return state->regs[R_ESP]; +} + +#endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/x86_64/target_structs.h b/linux-user/x86_64/target_structs.h new file mode 100644 index 00000000..d9340561 --- /dev/null +++ b/linux-user/x86_64/target_structs.h @@ -0,0 +1,58 @@ +/* + * X86-64 specific structures for linux-user + * + * Copyright (c) 2013 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ +#ifndef TARGET_STRUCTS_H +#define TARGET_STRUCTS_H + +struct target_ipc_perm { +    abi_int __key;                      /* Key.  */ +    abi_uint uid;                       /* Owner's user ID.  */ +    abi_uint gid;                       /* Owner's group ID.  */ +    abi_uint cuid;                      /* Creator's user ID.  */ +    abi_uint cgid;                      /* Creator's group ID.  */ +    abi_ushort mode;                    /* Read/write permission.  */ +    abi_ushort __pad1; +    abi_ushort __seq;                   /* Sequence number.  */ +    abi_ushort __pad2; +    abi_ulong __unused1; +    abi_ulong __unused2; +}; + +struct target_shmid_ds { +    struct target_ipc_perm shm_perm;    /* operation permission struct */ +    abi_long shm_segsz;                 /* size of segment in bytes */ +    abi_ulong shm_atime;                /* time of last shmat() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused1; +#endif +    abi_ulong shm_dtime;                /* time of last shmdt() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused2; +#endif +    abi_ulong shm_ctime;                /* time of last change by shmctl() */ +#if TARGET_ABI_BITS == 32 +    abi_ulong __unused3; +#endif +    abi_int shm_cpid;                   /* pid of creator */ +    abi_int shm_lpid;                   /* pid of last shmop */ +    abi_ulong shm_nattch;               /* number of current attaches */ +    abi_ulong __unused4; +    abi_ulong __unused5; +}; + +#endif diff --git a/linux-user/x86_64/termbits.h b/linux-user/x86_64/termbits.h new file mode 100644 index 00000000..1c3445c6 --- /dev/null +++ b/linux-user/x86_64/termbits.h @@ -0,0 +1,247 @@ +#define TARGET_NCCS 19 + +typedef unsigned char	target_cc_t; +typedef unsigned int	target_speed_t; +typedef unsigned int	target_tcflag_t; +struct target_termios { +	target_tcflag_t c_iflag;		/* input mode flags */ +	target_tcflag_t c_oflag;		/* output mode flags */ +	target_tcflag_t c_cflag;		/* control mode flags */ +	target_tcflag_t c_lflag;		/* local mode flags */ +	target_cc_t c_line;			/* line discipline */ +	target_cc_t c_cc[TARGET_NCCS];		/* control characters */ +}; + +/* c_cc characters */ +#define TARGET_VINTR 0 +#define TARGET_VQUIT 1 +#define TARGET_VERASE 2 +#define TARGET_VKILL 3 +#define TARGET_VEOF 4 +#define TARGET_VTIME 5 +#define TARGET_VMIN 6 +#define TARGET_VSWTC 7 +#define TARGET_VSTART 8 +#define TARGET_VSTOP 9 +#define TARGET_VSUSP 10 +#define TARGET_VEOL 11 +#define TARGET_VREPRINT 12 +#define TARGET_VDISCARD 13 +#define TARGET_VWERASE 14 +#define TARGET_VLNEXT 15 +#define TARGET_VEOL2 16 + +/* c_iflag bits */ +#define TARGET_IGNBRK	0000001 +#define TARGET_BRKINT	0000002 +#define TARGET_IGNPAR	0000004 +#define TARGET_PARMRK	0000010 +#define TARGET_INPCK	0000020 +#define TARGET_ISTRIP	0000040 +#define TARGET_INLCR	0000100 +#define TARGET_IGNCR	0000200 +#define TARGET_ICRNL	0000400 +#define TARGET_IUCLC	0001000 +#define TARGET_IXON	0002000 +#define TARGET_IXANY	0004000 +#define TARGET_IXOFF	0010000 +#define TARGET_IMAXBEL	0020000 +#define TARGET_IUTF8	0040000 + +/* c_oflag bits */ +#define TARGET_OPOST	0000001 +#define TARGET_OLCUC	0000002 +#define TARGET_ONLCR	0000004 +#define TARGET_OCRNL	0000010 +#define TARGET_ONOCR	0000020 +#define TARGET_ONLRET	0000040 +#define TARGET_OFILL	0000100 +#define TARGET_OFDEL	0000200 +#define TARGET_NLDLY	0000400 +#define   TARGET_NL0	0000000 +#define   TARGET_NL1	0000400 +#define TARGET_CRDLY	0003000 +#define   TARGET_CR0	0000000 +#define   TARGET_CR1	0001000 +#define   TARGET_CR2	0002000 +#define   TARGET_CR3	0003000 +#define TARGET_TABDLY	0014000 +#define   TARGET_TAB0	0000000 +#define   TARGET_TAB1	0004000 +#define   TARGET_TAB2	0010000 +#define   TARGET_TAB3	0014000 +#define   TARGET_XTABS	0014000 +#define TARGET_BSDLY	0020000 +#define   TARGET_BS0	0000000 +#define   TARGET_BS1	0020000 +#define TARGET_VTDLY	0040000 +#define   TARGET_VT0	0000000 +#define   TARGET_VT1	0040000 +#define TARGET_FFDLY	0100000 +#define   TARGET_FF0	0000000 +#define   TARGET_FF1	0100000 + +/* c_cflag bit meaning */ +#define TARGET_CBAUD	0010017 +#define  TARGET_B0	0000000		/* hang up */ +#define  TARGET_B50	0000001 +#define  TARGET_B75	0000002 +#define  TARGET_B110	0000003 +#define  TARGET_B134	0000004 +#define  TARGET_B150	0000005 +#define  TARGET_B200	0000006 +#define  TARGET_B300	0000007 +#define  TARGET_B600	0000010 +#define  TARGET_B1200	0000011 +#define  TARGET_B1800	0000012 +#define  TARGET_B2400	0000013 +#define  TARGET_B4800	0000014 +#define  TARGET_B9600	0000015 +#define  TARGET_B19200	0000016 +#define  TARGET_B38400	0000017 +#define TARGET_EXTA B19200 +#define TARGET_EXTB B38400 +#define TARGET_CSIZE	0000060 +#define   TARGET_CS5	0000000 +#define   TARGET_CS6	0000020 +#define   TARGET_CS7	0000040 +#define   TARGET_CS8	0000060 +#define TARGET_CSTOPB	0000100 +#define TARGET_CREAD	0000200 +#define TARGET_PARENB	0000400 +#define TARGET_PARODD	0001000 +#define TARGET_HUPCL	0002000 +#define TARGET_CLOCAL	0004000 +#define TARGET_CBAUDEX 0010000 +#define	   TARGET_BOTHER 0010000		/* non standard rate */ +#define    TARGET_B57600 0010001 +#define   TARGET_B115200 0010002 +#define   TARGET_B230400 0010003 +#define   TARGET_B460800 0010004 +#define   TARGET_B500000 0010005 +#define   TARGET_B576000 0010006 +#define   TARGET_B921600 0010007 +#define  TARGET_B1000000 0010010 +#define  TARGET_B1152000 0010011 +#define  TARGET_B1500000 0010012 +#define  TARGET_B2000000 0010013 +#define  TARGET_B2500000 0010014 +#define  TARGET_B3000000 0010015 +#define  TARGET_B3500000 0010016 +#define  TARGET_B4000000 0010017 +#define TARGET_CIBAUD	  002003600000	/* input baud rate */ +#define TARGET_CMSPAR	  010000000000		/* mark or space (stick) parity */ +#define TARGET_CRTSCTS	  020000000000		/* flow control */ + +#define TARGET_IBSHIFT	  8		/* Shift from CBAUD to CIBAUD */ + +/* c_lflag bits */ +#define TARGET_ISIG	0000001 +#define TARGET_ICANON	0000002 +#define TARGET_XCASE	0000004 +#define TARGET_ECHO	0000010 +#define TARGET_ECHOE	0000020 +#define TARGET_ECHOK	0000040 +#define TARGET_ECHONL	0000100 +#define TARGET_NOFLSH	0000200 +#define TARGET_TOSTOP	0000400 +#define TARGET_ECHOCTL	0001000 +#define TARGET_ECHOPRT	0002000 +#define TARGET_ECHOKE	0004000 +#define TARGET_FLUSHO	0010000 +#define TARGET_PENDIN	0040000 +#define TARGET_IEXTEN	0100000 + +/* tcflow() and TCXONC use these */ +#define	TARGET_TCOOFF		0 +#define	TARGET_TCOON		1 +#define	TARGET_TCIOFF		2 +#define	TARGET_TCION		3 + +/* tcflush() and TCFLSH use these */ +#define	TARGET_TCIFLUSH	0 +#define	TARGET_TCOFLUSH	1 +#define	TARGET_TCIOFLUSH	2 + +/* tcsetattr uses these */ +#define	TARGET_TCSANOW		0 +#define	TARGET_TCSADRAIN	1 +#define	TARGET_TCSAFLUSH	2 + +#define TARGET_TCGETS		0x5401 +#define TARGET_TCSETS		0x5402 +#define TARGET_TCSETSW		0x5403 +#define TARGET_TCSETSF		0x5404 +#define TARGET_TCGETA		0x5405 +#define TARGET_TCSETA		0x5406 +#define TARGET_TCSETAW		0x5407 +#define TARGET_TCSETAF		0x5408 +#define TARGET_TCSBRK		0x5409 +#define TARGET_TCXONC		0x540A +#define TARGET_TCFLSH		0x540B +#define TARGET_TIOCEXCL	0x540C +#define TARGET_TIOCNXCL	0x540D +#define TARGET_TIOCSCTTY	0x540E +#define TARGET_TIOCGPGRP	0x540F +#define TARGET_TIOCSPGRP	0x5410 +#define TARGET_TIOCOUTQ	0x5411 +#define TARGET_TIOCSTI		0x5412 +#define TARGET_TIOCGWINSZ	0x5413 +#define TARGET_TIOCSWINSZ	0x5414 +#define TARGET_TIOCMGET	0x5415 +#define TARGET_TIOCMBIS	0x5416 +#define TARGET_TIOCMBIC	0x5417 +#define TARGET_TIOCMSET	0x5418 +#define TARGET_TIOCGSOFTCAR	0x5419 +#define TARGET_TIOCSSOFTCAR	0x541A +#define TARGET_FIONREAD	0x541B +#define TARGET_TIOCINQ		FIONREAD +#define TARGET_TIOCLINUX	0x541C +#define TARGET_TIOCCONS	0x541D +#define TARGET_TIOCGSERIAL	0x541E +#define TARGET_TIOCSSERIAL	0x541F +#define TARGET_TIOCPKT		0x5420 +#define TARGET_FIONBIO		0x5421 +#define TARGET_TIOCNOTTY	0x5422 +#define TARGET_TIOCSETD	0x5423 +#define TARGET_TIOCGETD	0x5424 +#define TARGET_TCSBRKP		0x5425	/* Needed for POSIX tcsendbreak() */ +#define TARGET_TIOCSBRK	0x5427  /* BSD compatibility */ +#define TARGET_TIOCCBRK	0x5428  /* BSD compatibility */ +#define TARGET_TIOCGSID	0x5429  /* Return the session ID of FD */ +#define TARGET_TCGETS2		_IOR('T',0x2A, struct termios2) +#define TARGET_TCSETS2		_IOW('T',0x2B, struct termios2) +#define TARGET_TCSETSW2	_IOW('T',0x2C, struct termios2) +#define TARGET_TCSETSF2	_IOW('T',0x2D, struct termios2) +#define TARGET_TIOCGPTN	_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ +#define TARGET_TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */ + +#define TARGET_FIONCLEX	0x5450  /* these numbers need to be adjusted. */ +#define TARGET_FIOCLEX		0x5451 +#define TARGET_FIOASYNC	0x5452 +#define TARGET_TIOCSERCONFIG	0x5453 +#define TARGET_TIOCSERGWILD	0x5454 +#define TARGET_TIOCSERSWILD	0x5455 +#define TARGET_TIOCGLCKTRMIOS	0x5456 +#define TARGET_TIOCSLCKTRMIOS	0x5457 +#define TARGET_TIOCSERGSTRUCT	0x5458 /* For debugging only */ +#define TARGET_TIOCSERGETLSR   0x5459 /* Get line status register */ +#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config  */ +#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */ + +#define TARGET_TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */ +#define TARGET_TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */ +#define TARGET_TIOCGHAYESESP   0x545E  /* Get Hayes ESP configuration */ +#define TARGET_TIOCSHAYESESP   0x545F  /* Set Hayes ESP configuration */ +#define TARGET_FIOQSIZE       0x5460 + +/* Used for packet mode */ +#define TARGET_TIOCPKT_DATA		 0 +#define TARGET_TIOCPKT_FLUSHREAD	 1 +#define TARGET_TIOCPKT_FLUSHWRITE	 2 +#define TARGET_TIOCPKT_STOP		 4 +#define TARGET_TIOCPKT_START		 8 +#define TARGET_TIOCPKT_NOSTOP		16 +#define TARGET_TIOCPKT_DOSTOP		32 + +#define TARGET_TIOCSER_TEMT    0x01	/* Transmitter physically empty */  | 
