On Mon, Apr 04, 2011 at 04:32:12PM +0200, Alexander Graf wrote: > From: Ulrich Hecht <u...@suse.de> > > This patch adds support for running s390x binaries in the linux-user emulation > code. > > Signed-off-by: Ulrich Hecht <u...@suse.de> > Signed-off-by: Alexander Graf <ag...@suse.de> > > --- > > v1 -> v2: > > - always set 64bit flag for s390x binaries in elf loader > - remove redundant EXECUTE_SVC > - advance psw.addr in syscall execution path > --- > linux-user/elfload.c | 19 ++ > linux-user/main.c | 83 +++++++++ > linux-user/s390x/syscall.h | 25 +++ > linux-user/s390x/syscall_nr.h | 349 > ++++++++++++++++++++++++++++++++++++++ > linux-user/s390x/target_signal.h | 26 +++ > linux-user/s390x/termbits.h | 283 ++++++++++++++++++++++++++++++ > linux-user/signal.c | 314 ++++++++++++++++++++++++++++++++++ > linux-user/syscall.c | 18 ++- > linux-user/syscall_defs.h | 56 ++++++- > s390x.ld | 194 +++++++++++++++++++++ > scripts/qemu-binfmt-conf.sh | 4 +- > 11 files changed, 1363 insertions(+), 8 deletions(-) > create mode 100644 linux-user/s390x/syscall.h > create mode 100644 linux-user/s390x/syscall_nr.h > create mode 100644 linux-user/s390x/target_signal.h > create mode 100644 linux-user/s390x/termbits.h > create mode 100644 s390x.ld > > diff --git a/linux-user/elfload.c b/linux-user/elfload.c > index fe5410e..489f839 100644 > --- a/linux-user/elfload.c > +++ b/linux-user/elfload.c > @@ -793,6 +793,25 @@ static inline void init_thread(struct target_pt_regs > *regs, > > #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 > diff --git a/linux-user/main.c b/linux-user/main.c > index e651bfd..362b8cb 100644 > --- a/linux-user/main.c > +++ b/linux-user/main.c > @@ -2624,6 +2624,80 @@ void cpu_loop (CPUState *env) > } > #endif /* TARGET_ALPHA */ > > +#ifdef TARGET_S390X > +void cpu_loop(CPUS390XState *env) > +{ > + int trapnr; > + target_siginfo_t info; > + > + while (1) { > + trapnr = cpu_s390x_exec (env); > + > + switch (trapnr) { > + case EXCP_INTERRUPT: > + /* just indicate that signals should be handled asap */ > + break; > + case EXCP_DEBUG: > + { > + int sig; > + > + sig = gdb_handlesig (env, 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_SVC: > + { > + int n = env->int_svc_code; > + if (!n) { > + /* syscalls > 255 */ > + n = env->regs[1]; > + } > + env->psw.addr += env->int_svc_ilc; > + 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]); > + } > + break; > + case EXCP_ADDR: > + { > + info.si_signo = SIGSEGV; > + info.si_errno = 0; > + /* XXX: check env->error_code */ > + info.si_code = TARGET_SEGV_MAPERR; > + info._sifields._sigfault._addr = env->__excp_addr; > + queue_signal(env, info.si_signo, &info); > + } > + break; > + case EXCP_SPEC: > + { > + fprintf(stderr,"specification exception insn 0x%08x%04x\n", > ldl(env->psw.addr), lduw(env->psw.addr + 4)); > + info.si_signo = SIGILL; > + info.si_errno = 0; > + info.si_code = TARGET_ILL_ILLOPC; > + info._sifields._sigfault._addr = env->__excp_addr; > + queue_signal(env, info.si_signo, &info); > + } > + break; > + default: > + printf ("Unhandled trap: 0x%x\n", trapnr); > + cpu_dump_state(env, stderr, fprintf, 0); > + exit (1); > + } > + process_pending_signals (env); > + } > +} > + > +#endif /* TARGET_S390X */ > + > static void version(void) > { > printf("qemu-" TARGET_ARCH " version " QEMU_VERSION QEMU_PKGVERSION > @@ -3363,6 +3437,15 @@ int main(int argc, char **argv, char **envp) > 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 > diff --git a/linux-user/s390x/syscall.h b/linux-user/s390x/syscall.h > new file mode 100644 > index 0000000..a3812a8 > --- /dev/null > +++ b/linux-user/s390x/syscall.h > @@ -0,0 +1,25 @@ > +/* 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 ilc; > + unsigned short trap; > +}; > + > +#define UNAME_MACHINE "s390x" > diff --git a/linux-user/s390x/syscall_nr.h b/linux-user/s390x/syscall_nr.h > new file mode 100644 > index 0000000..7cc6db2 > --- /dev/null > +++ b/linux-user/s390x/syscall_nr.h > @@ -0,0 +1,349 @@ > +/* > + * 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 > +#undef NR_syscalls > +#define NR_syscalls 328 > + > +/* > + * 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_signal.h > b/linux-user/s390x/target_signal.h > new file mode 100644 > index 0000000..b4816b0 > --- /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/termbits.h b/linux-user/s390x/termbits.h > new file mode 100644 > index 0000000..2a78a05 > --- /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/signal.c b/linux-user/signal.c > index ce033e9..8cdd22d 100644 > --- a/linux-user/signal.c > +++ b/linux-user/signal.c > @@ -3614,6 +3614,320 @@ long do_rt_sigreturn(CPUState *env) > return -TARGET_ENOSYS; > } > > +#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 uc_flags; > + struct target_ucontext *uc_link; > + target_stack_t uc_stack; > + target_sigregs uc_mcontext; > + target_sigset_t uc_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, CPUState *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(CPUState *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]); > + /*
CODING_STYLE there, and later in this file. It might be a good idea to run checkpatch.pl on this patch. > + * 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(env->fregs[i].ll, &sregs->fpregs.fprs[i]); > +} > + > +static void setup_frame(int sig, struct target_sigaction *ka, > + target_sigset_t *set, CPUState *env) > +{ > + sigframe *frame; > + abi_ulong frame_addr; > + > + frame_addr = get_sigframe(ka, env, sizeof *frame); > + qemu_log("%s: frame_addr 0x%lx\n", __FUNCTION__, frame_addr); > + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) > + goto give_sigsegv; > + > + qemu_log("%s: 1\n", __FUNCTION__); > + if (__put_user(set->sig[0], &frame->sc.oldmask[0])) > + goto give_sigsegv; > + > + save_sigregs(env, &frame->sregs); > + > + __put_user((abi_ulong)&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; > + if (__put_user(S390_SYSCALL_OPCODE | TARGET_NR_sigreturn, > + (uint16_t *)(frame->retcode))) > + goto give_sigsegv; > + } > + > + /* Set up backchain. */ > + if (__put_user(env->regs[15], (abi_ulong *) frame)) > + goto give_sigsegv; > + > + /* Set up registers for signal handler */ > + env->regs[15] = (target_ulong) frame; > + env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE; > + > + env->regs[2] = sig; //map_signal(sig); > + env->regs[3] = (target_ulong) &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. */ > + if (__put_user(env->regs[2], (int *) &frame->signo)) > + goto give_sigsegv; > + unlock_user_struct(frame, frame_addr, 1); > + return; > + > +give_sigsegv: > + qemu_log("%s: give_sigsegv\n", __FUNCTION__); > + 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, CPUState *env) > +{ > + int i; > + rt_sigframe *frame; > + abi_ulong frame_addr; > + > + frame_addr = get_sigframe(ka, env, sizeof *frame); > + qemu_log("%s: frame_addr 0x%lx\n", __FUNCTION__, frame_addr); > + if (!lock_user_struct(VERIFY_WRITE, frame, frame_addr, 0)) > + goto give_sigsegv; > + > + qemu_log("%s: 1\n", __FUNCTION__); > + if (copy_siginfo_to_user(&frame->info, info)) > + goto give_sigsegv; > + > + /* Create the ucontext. */ > + __put_user(0, &frame->uc.uc_flags); > + __put_user((abi_ulong)NULL, (abi_ulong*)&frame->uc.uc_link); > + __put_user(target_sigaltstack_used.ss_sp, &frame->uc.uc_stack.ss_sp); > + __put_user(sas_ss_flags(get_sp_from_cpustate(env)), > + &frame->uc.uc_stack.ss_flags); > + __put_user(target_sigaltstack_used.ss_size, &frame->uc.uc_stack.ss_size); > + save_sigregs(env, &frame->uc.uc_mcontext); > + for(i = 0; i < TARGET_NSIG_WORDS; i++) { > + __put_user((abi_ulong)set->sig[i], > (abi_ulong*)&frame->uc.uc_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; > + if (__put_user(S390_SYSCALL_OPCODE | TARGET_NR_rt_sigreturn, > + (uint16_t *)(frame->retcode))) > + goto give_sigsegv; > + } > + > + /* Set up backchain. */ > + if (__put_user(env->regs[15], (abi_ulong *) frame)) > + goto give_sigsegv; > + > + /* Set up registers for signal handler */ > + env->regs[15] = (target_ulong) frame; > + env->psw.addr = (target_ulong) ka->_sa_handler | PSW_ADDR_AMODE; > + > + env->regs[2] = sig; //map_signal(sig); > + env->regs[3] = (target_ulong) &frame->info; > + env->regs[4] = (target_ulong) &frame->uc; > + return; > + > +give_sigsegv: > + qemu_log("%s: give_sigsegv\n", __FUNCTION__); > + unlock_user_struct(frame, frame_addr, 1); > + force_sig(TARGET_SIGSEGV); > +} > + > +static int > +restore_sigregs(CPUState *env, target_sigregs *sc) > +{ > + int err = 0; > + int i; > + > + for (i = 0; i < 16; i++) { > + err |= __get_user(env->regs[i], &sc->regs.gprs[i]); > + } > + > + err |= __get_user(env->psw.mask, &sc->regs.psw.mask); > + qemu_log("%s: sc->regs.psw.addr 0x%lx env->psw.addr 0x%lx\n", > __FUNCTION__, sc->regs.psw.addr, env->psw.addr); > + err |= __get_user(env->psw.addr, &sc->regs.psw.addr); > + /* FIXME: 31-bit -> | PSW_ADDR_AMODE */ > + > + for (i = 0; i < 16; i++) { > + err |= __get_user(env->aregs[i], &sc->regs.acrs[i]); > + } > + for (i = 0; i < 16; i++) { > + err |= __get_user(env->fregs[i].ll, &sc->fpregs.fprs[i]); > + } > + > + return err; > +} > + > +long do_sigreturn(CPUState *env) > +{ > + sigframe *frame; > + abi_ulong frame_addr = env->regs[15]; > + qemu_log("%s: frame_addr 0x%lx\n", __FUNCTION__, frame_addr); > + target_sigset_t target_set; > + sigset_t set; > + > + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) > + goto badframe; > + if (__get_user(target_set.sig[0], &frame->sc.oldmask[0])) > + goto badframe; > + > + target_to_host_sigset_internal(&set, &target_set); > + 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: > + unlock_user_struct(frame, frame_addr, 0); > + force_sig(TARGET_SIGSEGV); > + return 0; > +} > + > +long do_rt_sigreturn(CPUState *env) > +{ > + rt_sigframe *frame; > + abi_ulong frame_addr = env->regs[15]; > + qemu_log("%s: frame_addr 0x%lx\n", __FUNCTION__, frame_addr); > + sigset_t set; > + > + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) > + goto badframe; > + target_to_host_sigset(&set, &frame->uc.uc_sigmask); > + > + sigprocmask(SIG_SETMASK, &set, NULL); /* ~_BLOCKABLE? */ > + > + if (restore_sigregs(env, &frame->uc.uc_mcontext)) > + goto badframe; > + > + if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.uc_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) && !defined(TARGET_PPC64) > > /* FIXME: Many of the structures are defined for both PPC and PPC64, but > diff --git a/linux-user/syscall.c b/linux-user/syscall.c > index bb0999d..fabe815 100644 > --- a/linux-user/syscall.c > +++ b/linux-user/syscall.c > @@ -196,7 +196,7 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 > arg4,type5 arg5, \ > #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__) > +#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) || > defined(__s390x__) > #define __NR__llseek __NR_lseek > #endif That's probably a correct change, but it should be done in a separate patch as it concerns host support. > @@ -5432,7 +5432,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long > arg1, > ret = get_errno(settimeofday(&tv, NULL)); > } > break; > -#ifdef TARGET_NR_select > +#if defined(TARGET_NR_select) && !defined(TARGET_S390X) && > !defined(TARGET_S390) > case TARGET_NR_select: > { > struct target_sel_arg_struct *sel; > @@ -5543,7 +5543,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long > arg1, > #endif > #ifdef TARGET_NR_mmap > case TARGET_NR_mmap: > -#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) > || defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) > +#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) > || \ > + defined(TARGET_M68K) || defined(TARGET_CRIS) || > defined(TARGET_MICROBLAZE) \ > + || defined(TARGET_S390X) > { > abi_ulong *v; > abi_ulong v1, v2, v3, v4, v5, v6; > @@ -6039,6 +6041,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long > arg1, > ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4)); > #elif defined(TARGET_CRIS) > ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5)); > +#elif defined(TARGET_S390X) > + ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4)); > #else > ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5)); > #endif > @@ -6247,8 +6251,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long > arg1, > } > break; > #endif /* TARGET_NR_getdents64 */ > -#ifdef TARGET_NR__newselect > +#if defined(TARGET_NR__newselect) || defined(TARGET_S390X) > +#ifdef TARGET_S390X > + case TARGET_NR_select: > +#else > case TARGET_NR__newselect: > +#endif > ret = do_select(arg1, arg2, arg3, arg4, arg5); > break; > #endif > @@ -6576,7 +6584,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long > arg1, > 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_M68K) || defined(TARGET_S390X) > ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState > *)cpu_env)); > break; > #else > diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h > index 702652c..7a870ac 100644 > --- a/linux-user/syscall_defs.h > +++ b/linux-user/syscall_defs.h > @@ -55,7 +55,7 @@ > #endif > > #if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SH4) \ > - || defined(TARGET_M68K) || defined(TARGET_CRIS) > + || defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_S390X) > > #define TARGET_IOC_SIZEBITS 14 > #define TARGET_IOC_DIRBITS 2 > @@ -315,7 +315,10 @@ 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) > +#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_S390X) > > #if defined(TARGET_SPARC) > #define TARGET_SA_NOCLDSTOP 8u > @@ -1678,6 +1681,27 @@ struct target_stat { > > 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]; > +}; > #else > #error unsupported CPU > #endif > @@ -1764,6 +1788,34 @@ struct target_statfs64 { > 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; > diff --git a/s390x.ld b/s390x.ld > new file mode 100644 > index 0000000..7d1f2b7 > --- /dev/null > +++ b/s390x.ld > @@ -0,0 +1,194 @@ > +/* Default linker script, for normal executables */ > +OUTPUT_FORMAT("elf64-s390", "elf64-s390", > + "elf64-s390") > +OUTPUT_ARCH(s390:64-bit) > +ENTRY(_start) > +SEARCH_DIR("/usr/s390x-suse-linux/lib64"); SEARCH_DIR("/usr/local/lib64"); > SEARCH_DIR("/lib64"); SEARCH_DIR("/usr/lib64"); > SEARCH_DIR("/usr/s390x-suse-linux/lib"); SEARCH_DIR("/usr/lib64"); > SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib"); > +SECTIONS > +{ > + /* Read-only sections, merged into text segment: */ > + PROVIDE (__executable_start = 0x60000000); . = 0x60000000 + SIZEOF_HEADERS; > + .interp : { *(.interp) } > + .note.gnu.build-id : { *(.note.gnu.build-id) } > + .hash : { *(.hash) } > + .gnu.hash : { *(.gnu.hash) } > + .dynsym : { *(.dynsym) } > + .dynstr : { *(.dynstr) } > + .gnu.version : { *(.gnu.version) } > + .gnu.version_d : { *(.gnu.version_d) } > + .gnu.version_r : { *(.gnu.version_r) } > + .rel.init : { *(.rel.init) } > + .rela.init : { *(.rela.init) } > + .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) } > + .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } > + .rel.fini : { *(.rel.fini) } > + .rela.fini : { *(.rela.fini) } > + .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) } > + .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } > + .rel.data.rel.ro : { *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) } > + .rela.data.rel.ro : { *(.rela.data.rel.ro* > .rela.gnu.linkonce.d.rel.ro.*) } > + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } > + .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } > + .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } > + .rela.tdata : { *(.rela.tdata .rela.tdata.* > .rela.gnu.linkonce.td.*) } > + .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } > + .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } > + .rel.ctors : { *(.rel.ctors) } > + .rela.ctors : { *(.rela.ctors) } > + .rel.dtors : { *(.rel.dtors) } > + .rela.dtors : { *(.rela.dtors) } > + .rel.got : { *(.rel.got) } > + .rela.got : { *(.rela.got) } > + .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } > + .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } > + .rel.plt : { *(.rel.plt) } > + .rela.plt : { *(.rela.plt) } > + .init : > + { > + KEEP (*(.init)) > + } =0x07070707 > + .plt : { *(.plt) } > + .text : > + { > + *(.text .stub .text.* .gnu.linkonce.t.*) > + /* .gnu.warning sections are handled specially by elf32.em. */ > + *(.gnu.warning) > + } =0x07070707 > + .fini : > + { > + KEEP (*(.fini)) > + } =0x07070707 > + PROVIDE (__etext = .); > + PROVIDE (_etext = .); > + PROVIDE (etext = .); > + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } > + .rodata1 : { *(.rodata1) } > + .eh_frame_hdr : { *(.eh_frame_hdr) } > + .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } > + .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table > .gcc_except_table.*) } > + /* Adjust the address for the data segment. We want to adjust up to > + the same address within the page on the next page up. */ > + . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & > (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT > (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); > + /* Exception handling */ > + .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } > + .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table > .gcc_except_table.*) } > + /* Thread Local Storage sections */ > + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } > + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } > + .preinit_array : > + { > + PROVIDE_HIDDEN (__preinit_array_start = .); > + KEEP (*(.preinit_array)) > + PROVIDE_HIDDEN (__preinit_array_end = .); > + } > + .init_array : > + { > + PROVIDE_HIDDEN (__init_array_start = .); > + KEEP (*(SORT(.init_array.*))) > + KEEP (*(.init_array)) > + PROVIDE_HIDDEN (__init_array_end = .); > + } > + .fini_array : > + { > + PROVIDE_HIDDEN (__fini_array_start = .); > + KEEP (*(.fini_array)) > + KEEP (*(SORT(.fini_array.*))) > + PROVIDE_HIDDEN (__fini_array_end = .); > + } > + .ctors : > + { > + /* gcc uses crtbegin.o to find the start of > + the constructors, so we make sure it is > + first. Because this is a wildcard, it > + doesn't matter if the user does not > + actually link against crtbegin.o; the > + linker won't look for a file to match a > + wildcard. The wildcard also means that it > + doesn't matter which directory crtbegin.o > + is in. */ > + KEEP (*crtbegin.o(.ctors)) > + KEEP (*crtbegin?.o(.ctors)) > + /* We don't want to include the .ctor section from > + the crtend.o file until after the sorted ctors. > + The .ctor section from the crtend file contains the > + end of ctors marker and it must be last */ > + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) > + KEEP (*(SORT(.ctors.*))) > + KEEP (*(.ctors)) > + } > + .dtors : > + { > + KEEP (*crtbegin.o(.dtors)) > + KEEP (*crtbegin?.o(.dtors)) > + KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) > + KEEP (*(SORT(.dtors.*))) > + KEEP (*(.dtors)) > + } > + .jcr : { KEEP (*(.jcr)) } > + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) > *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } > + .dynamic : { *(.dynamic) } > + . = DATA_SEGMENT_RELRO_END (0, .); > + .got : { *(.got.plt) *(.got) } > + .data : > + { > + *(.data .data.* .gnu.linkonce.d.*) > + SORT(CONSTRUCTORS) > + } > + .data1 : { *(.data1) } > + _edata = .; PROVIDE (edata = .); > + __bss_start = .; > + .bss : > + { > + *(.dynbss) > + *(.bss .bss.* .gnu.linkonce.b.*) > + *(COMMON) > + /* Align here to ensure that the .bss section occupies space up to > + _end. Align after .bss to ensure correct alignment even if the > + .bss section disappears because there are no input sections. > + FIXME: Why do we need it? When there is no .bss section, we don't > + pad the .data section. */ > + . = ALIGN(. != 0 ? 64 / 8 : 1); > + } > + . = ALIGN(64 / 8); > + . = ALIGN(64 / 8); > + _end = .; PROVIDE (end = .); > + . = DATA_SEGMENT_END (.); > + /* Stabs debugging sections. */ > + .stab 0 : { *(.stab) } > + .stabstr 0 : { *(.stabstr) } > + .stab.excl 0 : { *(.stab.excl) } > + .stab.exclstr 0 : { *(.stab.exclstr) } > + .stab.index 0 : { *(.stab.index) } > + .stab.indexstr 0 : { *(.stab.indexstr) } > + .comment 0 : { *(.comment) } > + /* DWARF debug sections. > + Symbols in the DWARF debugging sections are relative to the beginning > + of the section so we begin them at 0. */ > + /* DWARF 1 */ > + .debug 0 : { *(.debug) } > + .line 0 : { *(.line) } > + /* GNU DWARF 1 extensions */ > + .debug_srcinfo 0 : { *(.debug_srcinfo) } > + .debug_sfnames 0 : { *(.debug_sfnames) } > + /* DWARF 1.1 and DWARF 2 */ > + .debug_aranges 0 : { *(.debug_aranges) } > + .debug_pubnames 0 : { *(.debug_pubnames) } > + /* DWARF 2 */ > + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } > + .debug_abbrev 0 : { *(.debug_abbrev) } > + .debug_line 0 : { *(.debug_line) } > + .debug_frame 0 : { *(.debug_frame) } > + .debug_str 0 : { *(.debug_str) } > + .debug_loc 0 : { *(.debug_loc) } > + .debug_macinfo 0 : { *(.debug_macinfo) } > + /* SGI/MIPS DWARF 2 extensions */ > + .debug_weaknames 0 : { *(.debug_weaknames) } > + .debug_funcnames 0 : { *(.debug_funcnames) } > + .debug_typenames 0 : { *(.debug_typenames) } > + .debug_varnames 0 : { *(.debug_varnames) } > + /* DWARF 3 */ > + .debug_pubtypes 0 : { *(.debug_pubtypes) } > + .debug_ranges 0 : { *(.debug_ranges) } > + .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } > + /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) } > +} Is this file really related with *guest* support? > diff --git a/scripts/qemu-binfmt-conf.sh b/scripts/qemu-binfmt-conf.sh > index c50beb7..83a44d8 100644 > --- a/scripts/qemu-binfmt-conf.sh > +++ b/scripts/qemu-binfmt-conf.sh > @@ -1,5 +1,5 @@ > #!/bin/sh > -# enable automatic i386/ARM/M68K/MIPS/SPARC/PPC program execution by the > kernel > +# enable automatic i386/ARM/M68K/MIPS/SPARC/PPC/s390 program execution by > the kernel > > # load the binfmt_misc module > if [ ! -d /proc/sys/fs/binfmt_misc ]; then > @@ -63,4 +63,6 @@ fi > if [ $cpu != "sh" ] ; then > echo > ':sh4:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a\x00:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/local/bin/qemu-sh4:' > > /proc/sys/fs/binfmt_misc/register > echo > ':sh4eb:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x2a:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-sh4eb:' > > /proc/sys/fs/binfmt_misc/register > +if [ $cpu != "s390x" ] ; then > + echo > ':s390x:M::\x7fELF\x02\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x16:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff:/usr/local/bin/qemu-s390x:' > > /proc/sys/fs/binfmt_misc/register > fi Except coding style and a few minor issues, it looks fine. That said I don't know very well, and I would appreciate if someone with a good knowledge of linux-user can review it. Riku maybe (CC:ed)? -- Aurelien Jarno GPG: 1024D/F1BCDB73 aurel...@aurel32.net http://www.aurel32.net