Signed-off-by: Mike Frysinger <vap...@gentoo.org> --- default-configs/bfin-linux-user.mak | 1 + linux-user/bfin/syscall.h | 59 ++++++ linux-user/bfin/syscall_nr.h | 389 ++++++++++++++++++++++++++++++++++++ linux-user/bfin/target_flat.h | 92 +++++++++ linux-user/bfin/target_sigcontext.h | 61 ++++++ linux-user/bfin/target_signal.h | 31 +++ linux-user/bfin/termbits.h | 227 +++++++++++++++++++++ linux-user/elfload.c | 47 +++++ linux-user/main.c | 160 +++++++++++++++ linux-user/qemu.h | 4 + linux-user/signal.c | 225 +++++++++++++++++++++ linux-user/syscall.c | 3 +- linux-user/syscall_defs.h | 65 +++++- linux-user/target_ucontext.h | 14 ++ 14 files changed, 1375 insertions(+), 3 deletions(-) create mode 100644 default-configs/bfin-linux-user.mak create mode 100644 linux-user/bfin/syscall.h create mode 100644 linux-user/bfin/syscall_nr.h create mode 100644 linux-user/bfin/target_flat.h create mode 100644 linux-user/bfin/target_sigcontext.h create mode 100644 linux-user/bfin/target_signal.h create mode 100644 linux-user/bfin/termbits.h create mode 100644 linux-user/target_ucontext.h
diff --git a/default-configs/bfin-linux-user.mak b/default-configs/bfin-linux-user.mak new file mode 100644 index 0000000..5f7aefb --- /dev/null +++ b/default-configs/bfin-linux-user.mak @@ -0,0 +1 @@ +# Default configuration for bfin-linux-user diff --git a/linux-user/bfin/syscall.h b/linux-user/bfin/syscall.h new file mode 100644 index 0000000..892ee75 --- /dev/null +++ b/linux-user/bfin/syscall.h @@ -0,0 +1,59 @@ +struct target_pt_regs { + abi_ulong orig_pc; + abi_ulong ipend; + abi_ulong seqstat; + abi_ulong rete; + abi_ulong retn; + abi_ulong retx; + abi_ulong pc; /* PC == RETI */ + abi_ulong rets; + abi_ulong reserved; /* Used as scratch during system calls */ + abi_ulong astat; + abi_ulong lb1; + abi_ulong lb0; + abi_ulong lt1; + abi_ulong lt0; + abi_ulong lc1; + abi_ulong lc0; + abi_ulong a1w; + abi_ulong a1x; + abi_ulong a0w; + abi_ulong a0x; + abi_ulong b3; + abi_ulong b2; + abi_ulong b1; + abi_ulong b0; + abi_ulong l3; + abi_ulong l2; + abi_ulong l1; + abi_ulong l0; + abi_ulong m3; + abi_ulong m2; + abi_ulong m1; + abi_ulong m0; + abi_ulong i3; + abi_ulong i2; + abi_ulong i1; + abi_ulong i0; + abi_ulong usp; + abi_ulong fp; + abi_ulong p5; + abi_ulong p4; + abi_ulong p3; + abi_ulong p2; + abi_ulong p1; + abi_ulong p0; + abi_ulong r7; + abi_ulong r6; + abi_ulong r5; + abi_ulong r4; + abi_ulong r3; + abi_ulong r2; + abi_ulong r1; + abi_ulong r0; + abi_ulong orig_r0; + abi_ulong orig_p0; + abi_ulong syscfg; +}; + +#define UNAME_MACHINE "blackfin" diff --git a/linux-user/bfin/syscall_nr.h b/linux-user/bfin/syscall_nr.h new file mode 100644 index 0000000..52ec628 --- /dev/null +++ b/linux-user/bfin/syscall_nr.h @@ -0,0 +1,389 @@ +/* + * 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 + /* 7 TARGET_NR_waitpid obsolete */ +#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 + /* 17 TARGET_NR_break obsolete */ + /* 18 TARGET_NR_oldstat obsolete */ +#define TARGET_NR_lseek 19 +#define TARGET_NR_getpid 20 +#define TARGET_NR_mount 21 + /* 22 TARGET_NR_umount obsolete */ +#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 TARGET_NR_oldfstat obsolete */ +#define TARGET_NR_pause 29 + /* 30 TARGET_NR_utime obsolete */ + /* 31 TARGET_NR_stty obsolete */ + /* 32 TARGET_NR_gtty obsolete */ +#define TARGET_NR_access 33 +#define TARGET_NR_nice 34 + /* 35 TARGET_NR_ftime obsolete */ +#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 + /* 44 TARGET_NR_prof obsolete */ +#define TARGET_NR_brk 45 +#define TARGET_NR_setgid 46 +#define TARGET_NR_getgid 47 + /* 48 TARGET_NR_signal obsolete */ +#define TARGET_NR_geteuid 49 +#define TARGET_NR_getegid 50 +#define TARGET_NR_acct 51 +#define TARGET_NR_umount2 52 + /* 53 TARGET_NR_lock obsolete */ +#define TARGET_NR_ioctl 54 +#define TARGET_NR_fcntl 55 + /* 56 TARGET_NR_mpx obsolete */ +#define TARGET_NR_setpgid 57 + /* 58 TARGET_NR_ulimit obsolete */ + /* 59 TARGET_NR_oldolduname obsolete */ +#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 + /* 67 TARGET_NR_sigaction obsolete */ +#define TARGET_NR_sgetmask 68 +#define TARGET_NR_ssetmask 69 +#define TARGET_NR_setreuid 70 +#define TARGET_NR_setregid 71 + /* 72 TARGET_NR_sigsuspend obsolete */ + /* 73 TARGET_NR_sigpending obsolete */ +#define TARGET_NR_sethostname 74 +#define TARGET_NR_setrlimit 75 + /* 76 TARGET_NR_old_getrlimit obsolete */ +#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 + /* 82 TARGET_NR_select obsolete */ +#define TARGET_NR_symlink 83 + /* 84 TARGET_NR_oldlstat obsolete */ +#define TARGET_NR_readlink 85 + /* 86 TARGET_NR_uselib obsolete */ + /* 87 TARGET_NR_swapon obsolete */ +#define TARGET_NR_reboot 88 + /* 89 TARGET_NR_readdir obsolete */ + /* 90 TARGET_NR_mmap obsolete */ +#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 + /* 98 TARGET_NR_profil obsolete */ +#define TARGET_NR_statfs 99 +#define TARGET_NR_fstatfs 100 + /* 101 TARGET_NR_ioperm */ + /* 102 TARGET_NR_socketcall obsolete */ +#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 TARGET_NR_olduname obsolete */ + /* 110 TARGET_NR_iopl obsolete */ +#define TARGET_NR_vhangup 111 + /* 112 TARGET_NR_idle obsolete */ + /* 113 TARGET_NR_vm86old */ +#define TARGET_NR_wait4 114 + /* 115 TARGET_NR_swapoff obsolete */ +#define TARGET_NR_sysinfo 116 + /* 117 TARGET_NR_ipc oboslete */ +#define TARGET_NR_fsync 118 + /* 119 TARGET_NR_sigreturn obsolete */ +#define TARGET_NR_clone 120 +#define TARGET_NR_setdomainname 121 +#define TARGET_NR_uname 122 + /* 123 TARGET_NR_modify_ldt obsolete */ +#define TARGET_NR_adjtimex 124 +#define TARGET_NR_mprotect 125 + /* 126 TARGET_NR_sigprocmask obsolete */ + /* 127 TARGET_NR_create_module obsolete */ +#define TARGET_NR_init_module 128 +#define TARGET_NR_delete_module 129 + /* 130 TARGET_NR_get_kernel_syms obsolete */ +#define TARGET_NR_quotactl 131 +#define TARGET_NR_getpgid 132 +#define TARGET_NR_fchdir 133 +#define TARGET_NR_bdflush 134 + /* 135 was sysfs */ +#define TARGET_NR_personality 136 + /* 137 TARGET_NR_afs_syscall */ +#define TARGET_NR_setfsuid 138 +#define TARGET_NR_setfsgid 139 +#define TARGET_NR__llseek 140 +#define TARGET_NR_getdents 141 + /* 142 TARGET_NR__newselect obsolete */ +#define TARGET_NR_flock 143 + /* 144 TARGET_NR_msync obsolete */ +#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 + /* 150 TARGET_NR_mlock */ + /* 151 TARGET_NR_munlock */ + /* 152 TARGET_NR_mlockall */ + /* 153 TARGET_NR_munlockall */ +#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 + /* 166 TARGET_NR_vm86 */ + /* 167 TARGET_NR_query_module */ + /* 168 TARGET_NR_poll */ +#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_pread 180 +#define TARGET_NR_pwrite 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 + /* 188 TARGET_NR_getpmsg */ + /* 189 TARGET_NR_putpmsg */ +#define TARGET_NR_vfork 190 +#define TARGET_NR_getrlimit 191 +#define TARGET_NR_mmap2 192 /* xxx: this is mmap2 !? */ +#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 + /* 218 TARGET_NR_mincore */ + /* 219 TARGET_NR_madvise */ +#define TARGET_NR_getdents64 220 +#define TARGET_NR_fcntl64 221 + /* 222 reserved for TUX */ + /* 223 reserved for TUX */ +#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 + /* 243 TARGET_NR_set_thread_area */ + /* 244 TARGET_NR_get_thread_area */ +#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 + /* 250 TARGET_NR_alloc_hugepages */ + /* 251 TARGET_NR_free_hugepages */ +#define TARGET_NR_exit_group 252 +#define TARGET_NR_lookup_dcookie 253 +#define TARGET_NR_bfin_spinlock 254 + +#define TARGET_NR_epoll_create 255 +#define TARGET_NR_epoll_ctl 256 +#define TARGET_NR_epoll_wait 257 + /* 258 TARGET_NR_remap_file_pages */ +#define TARGET_NR_set_tid_address 259 +#define TARGET_NR_timer_create 260 +#define TARGET_NR_timer_settime 261 +#define TARGET_NR_timer_gettime 262 +#define TARGET_NR_timer_getoverrun 263 +#define TARGET_NR_timer_delete 264 +#define TARGET_NR_clock_settime 265 +#define TARGET_NR_clock_gettime 266 +#define TARGET_NR_clock_getres 267 +#define TARGET_NR_clock_nanosleep 268 +#define TARGET_NR_statfs64 269 +#define TARGET_NR_fstatfs64 270 +#define TARGET_NR_tgkill 271 +#define TARGET_NR_utimes 272 +#define TARGET_NR_fadvise64_64 273 + /* 274 TARGET_NR_vserver */ + /* 275 TARGET_NR_mbind */ + /* 276 TARGET_NR_get_mempolicy */ + /* 277 TARGET_NR_set_mempolicy */ +#define TARGET_NR_mq_open 278 +#define TARGET_NR_mq_unlink 279 +#define TARGET_NR_mq_timedsend 280 +#define TARGET_NR_mq_timedreceive 281 +#define TARGET_NR_mq_notify 282 +#define TARGET_NR_mq_getsetattr 283 +#define TARGET_NR_kexec_load 284 +#define TARGET_NR_waitid 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 + /* 294 TARGET_NR_migrate_pages */ +#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 + +/* Blackfin private syscalls */ +#define TARGET_NR_sram_alloc 311 +#define TARGET_NR_sram_free 312 +#define TARGET_NR_dma_memcpy 313 + +/* socket syscalls */ +#define TARGET_NR_accept 314 +#define TARGET_NR_bind 315 +#define TARGET_NR_connect 316 +#define TARGET_NR_getpeername 317 +#define TARGET_NR_getsockname 318 +#define TARGET_NR_getsockopt 319 +#define TARGET_NR_listen 320 +#define TARGET_NR_recv 321 +#define TARGET_NR_recvfrom 322 +#define TARGET_NR_recvmsg 323 +#define TARGET_NR_send 324 +#define TARGET_NR_sendmsg 325 +#define TARGET_NR_sendto 326 +#define TARGET_NR_setsockopt 327 +#define TARGET_NR_shutdown 328 +#define TARGET_NR_socket 329 +#define TARGET_NR_socketpair 330 + +/* sysv ipc syscalls */ +#define TARGET_NR_semctl 331 +#define TARGET_NR_semget 332 +#define TARGET_NR_semop 333 +#define TARGET_NR_msgctl 334 +#define TARGET_NR_msgget 335 +#define TARGET_NR_msgrcv 336 +#define TARGET_NR_msgsnd 337 +#define TARGET_NR_shmat 338 +#define TARGET_NR_shmctl 339 +#define TARGET_NR_shmdt 340 +#define TARGET_NR_shmget 341 + +#define TARGET_NR_splice 342 +#define TARGET_NR_sync_file_range 343 +#define TARGET_NR_tee 344 +#define TARGET_NR_vmsplice 345 + +#define TARGET_NR_epoll_pwait 346 +#define TARGET_NR_utimensat 347 +#define TARGET_NR_signalfd 348 +#define TARGET_NR_timerfd_create 349 +#define TARGET_NR_eventfd 350 +#define TARGET_NR_pread64 351 +#define TARGET_NR_pwrite64 352 +#define TARGET_NR_fadvise64 353 +#define TARGET_NR_set_robust_list 354 +#define TARGET_NR_get_robust_list 355 +#define TARGET_NR_fallocate 356 +#define TARGET_NR_semtimedop 357 +#define TARGET_NR_timerfd_settime 358 +#define TARGET_NR_timerfd_gettime 359 +#define TARGET_NR_signalfd4 360 +#define TARGET_NR_eventfd2 361 +#define TARGET_NR_epoll_create1 362 +#define TARGET_NR_dup3 363 +#define TARGET_NR_pipe2 364 +#define TARGET_NR_inotify_init1 365 +#define TARGET_NR_preadv 366 +#define TARGET_NR_pwritev 367 +#define TARGET_NR_rt_tgsigqueueinfo 368 +#define TARGET_NR_perf_event_open 369 +#define TARGET_NR_recvmmsg 370 +#define TARGET_NR_fanotify_init 371 +#define TARGET_NR_fanotify_mark 372 +#define TARGET_NR_prlimit64 373 +#define TARGET_NR_cacheflush 374 + +#define TARGET_NR_syscall 375 diff --git a/linux-user/bfin/target_flat.h b/linux-user/bfin/target_flat.h new file mode 100644 index 0000000..c694a6a --- /dev/null +++ b/linux-user/bfin/target_flat.h @@ -0,0 +1,92 @@ +/* + * uClinux flat-format executables + * + * Copyright 2003-2011 Analog Devices Inc. + * + * Licensed under the GPL-2 + */ + +#define FLAT_BFIN_RELOC_TYPE_16_BIT 0 +#define FLAT_BFIN_RELOC_TYPE_16H_BIT 1 +#define FLAT_BFIN_RELOC_TYPE_32_BIT 2 + +#define flat_argvp_envp_on_stack() 0 +#define flat_reloc_valid(reloc, size) ((reloc) <= (size)) +#define flat_old_ram_flag(flag) (flag) +#define flat_get_relocate_addr(relval) ((relval) & 0x03ffffff) + +static inline int flat_set_persistent(abi_ulong relval, abi_ulong *persistent) +{ + int type = (relval >> 26) & 7; + if (type == 3) { + *persistent = relval << 16; + return 1; + } + return 0; +} + +static abi_ulong +flat_get_addr_from_rp(abi_ulong ul_ptr, abi_ulong relval, abi_ulong flags, abi_ulong *persistent) +{ + int type = (relval >> 26) & 7; + abi_ulong val; + +#ifdef DEBUG + printf("%s:%i: ptr:%8x relval:%8x type:%x flags:%x persistent:%x", + __func__, __LINE__, ul_ptr, relval, type, flags, *persistent); +#endif + + switch (type) { + case FLAT_BFIN_RELOC_TYPE_16_BIT: + case FLAT_BFIN_RELOC_TYPE_16H_BIT: + if (get_user_u16(val, ul_ptr)) { + fprintf(stderr, "BINFMT_FLAT: unable to read reloc at %#x\n", ul_ptr); + abort(); + } + val += *persistent; + break; + case FLAT_BFIN_RELOC_TYPE_32_BIT: + if (get_user_u32(val, ul_ptr)) { + fprintf(stderr, "BINFMT_FLAT: unable to read reloc at %#x\n", ul_ptr); + abort(); + } + break; + default: + fprintf(stderr, "BINFMT_FLAT: Unknown relocation type %x\n", type); + abort(); + break; + } +#ifdef DEBUG + printf(" val:%x\n", val); +#endif + + /* + * Stack-relative relocs contain the offset into the stack, we + * have to add the stack's start address here and return 1 from + * flat_addr_absolute to prevent the normal address calculations + */ + if (relval & (1 << 29)) { + fprintf(stderr, "BINFMT_FLAT: stack relocs not supported\n"); + abort(); + /*return val + current->mm->context.end_brk;*/ + } + + if ((flags & FLAT_FLAG_GOTPIC) == 0) + val = ntohl(val); + + return val; +} + +static int +flat_put_addr_at_rp(abi_ulong ptr, abi_ulong addr, abi_ulong relval) +{ + int type = (relval >> 26) & 7; + + switch (type) { + case FLAT_BFIN_RELOC_TYPE_16_BIT: return put_user_u16(addr, ptr); + case FLAT_BFIN_RELOC_TYPE_16H_BIT: return put_user_u16(addr >> 16, ptr); + case FLAT_BFIN_RELOC_TYPE_32_BIT: return put_user_u32(addr, ptr); + } + + abort(); +} diff --git a/linux-user/bfin/target_sigcontext.h b/linux-user/bfin/target_sigcontext.h new file mode 100644 index 0000000..10d61e2 --- /dev/null +++ b/linux-user/bfin/target_sigcontext.h @@ -0,0 +1,61 @@ +/* + * Copyright 2004-2008 Analog Devices Inc. + * + * Licensed under the GPL-2 or later. + */ + +#ifndef TARGET_SIGCONTEXT_H +#define TARGET_SIGCONTEXT_H + +/* Add new entries at the end of the structure only. */ +struct target_sigcontext { + abi_ulong sc_r0; + abi_ulong sc_r1; + abi_ulong sc_r2; + abi_ulong sc_r3; + abi_ulong sc_r4; + abi_ulong sc_r5; + abi_ulong sc_r6; + abi_ulong sc_r7; + abi_ulong sc_p0; + abi_ulong sc_p1; + abi_ulong sc_p2; + abi_ulong sc_p3; + abi_ulong sc_p4; + abi_ulong sc_p5; + abi_ulong sc_usp; + abi_ulong sc_a0w; + abi_ulong sc_a1w; + abi_ulong sc_a0x; + abi_ulong sc_a1x; + abi_ulong sc_astat; + abi_ulong sc_rets; + abi_ulong sc_pc; + abi_ulong sc_retx; + abi_ulong sc_fp; + abi_ulong sc_i0; + abi_ulong sc_i1; + abi_ulong sc_i2; + abi_ulong sc_i3; + abi_ulong sc_m0; + abi_ulong sc_m1; + abi_ulong sc_m2; + abi_ulong sc_m3; + abi_ulong sc_l0; + abi_ulong sc_l1; + abi_ulong sc_l2; + abi_ulong sc_l3; + abi_ulong sc_b0; + abi_ulong sc_b1; + abi_ulong sc_b2; + abi_ulong sc_b3; + abi_ulong sc_lc0; + abi_ulong sc_lc1; + abi_ulong sc_lt0; + abi_ulong sc_lt1; + abi_ulong sc_lb0; + abi_ulong sc_lb1; + abi_ulong sc_seqstat; +}; + +#endif diff --git a/linux-user/bfin/target_signal.h b/linux-user/bfin/target_signal.h new file mode 100644 index 0000000..7367c0a --- /dev/null +++ b/linux-user/bfin/target_signal.h @@ -0,0 +1,31 @@ +#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(CPUArchState *env) +{ + return env->spreg; +} + +#define TARGET_SIGRETURN_STUB 0x400 + +#endif /* TARGET_SIGNAL_H */ diff --git a/linux-user/bfin/termbits.h b/linux-user/bfin/termbits.h new file mode 100644 index 0000000..5c5fa01 --- /dev/null +++ b/linux-user/bfin/termbits.h @@ -0,0 +1,227 @@ +/* from asm/termbits.h */ +/* NOTE: exactly the same as i386 */ + +#define TARGET_NCCS 19 + +struct target_termios { + uint32_t c_iflag; /* input mode flags */ + uint32_t c_oflag; /* output mode flags */ + uint32_t c_cflag; /* control mode flags */ + uint32_t c_lflag; /* local mode flags */ + uint8_t c_line; /* line discipline */ + uint8_t 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, uint32_t) /* Get Pty Number (of pty-mux device) */ +#define TARGET_TIOCSPTLCK TARGET_IOW('T',0x31, int32_t) /* 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 index ddef23e..b09e33e 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -979,6 +979,48 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUM68KState *e #endif +#ifdef TARGET_BFIN + +#define ELF_START_MMAP 0x00000000 + +#define elf_check_arch(x) ( (x) == EM_BLACKFIN ) +#define elf_is_fdpic(e) ( (e)->e_flags & EF_BFIN_FDPIC ) + +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_BLACKFIN + +static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) +{ + if (infop->personality == PER_LINUX_FDPIC) { + if (infop->other_info) { + /* dynamic */ + regs->p0 = tswapl(infop->loadmap_addr); + regs->p1 = tswapl(infop->other_info->loadmap_addr); + regs->p2 = tswapl(infop->other_info->pt_dynamic_addr); + } else { + /* static */ + regs->p0 = tswapl(infop->loadmap_addr); + regs->p1 = 0; + regs->p2 = tswapl(infop->pt_dynamic_addr); + } + regs->r7 = 0; + } else if (infop->start_code == 0) { + /* Must be bare metal ELF ... */ + infop->personality = PER_MASK; + } + regs->pc = tswapl(infop->entry); + regs->usp = tswapl(infop->start_stack); +} + +#define ELF_EXEC_PAGESIZE 4096 + +/* See linux kernel: arch/blackfin/include/asm/elf.h. */ +#define ELF_NREG 40 +typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG]; + +#endif + #ifdef TARGET_ALPHA #define ELF_START_MMAP (0x30000000000ULL) @@ -1677,6 +1719,11 @@ static void load_elf_image(const char *image_name, int image_fd, address does not conflict with MMAP_MIN_ADDR or the QEMU application itself. */ probe_guest_base(image_name, loaddr, hiaddr); +#ifdef TARGET_BFIN + /* Make space for the fixed code region */ + if (elf_is_fdpic(ehdr) && load_addr < 0x1000) + load_addr += 0x1000; +#endif } load_bias = load_addr - loaddr; diff --git a/linux-user/main.c b/linux-user/main.c index b97b8cf..bb5d032 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -2795,6 +2795,115 @@ void cpu_loop(CPUM68KState *env) } #endif /* TARGET_M68K */ +#ifdef TARGET_BFIN + +#include "disas/disas.h" + +void cpu_loop(CPUArchState *env) +{ + CPUState *cs = ENV_GET_CPU(env); + int trapnr, gdbsig; + target_siginfo_t info; + + for (;;) { + cpu_exec_start(cs); + trapnr = cpu_exec(env); + cpu_exec_end(cs); + gdbsig = 0; + + switch (trapnr) { + case EXCP_SYSCALL: + env->pc += 2; + env->dreg[0] = do_syscall(env, + env->preg[0], + env->dreg[0], + env->dreg[1], + env->dreg[2], + env->dreg[3], + env->dreg[4], + env->dreg[5], 0, 0); + break; + case EXCP_INTERRUPT: + /* just indicate that signals should be handled asap */ + break; + case EXCP_DEBUG: + /* XXX: does this handle hwloops ? */ + /*env->pc += 2;*/ + /* EMUEXCPT signals debugger only if attached; NOP otherwise */ + gdbsig = TARGET_SIGTRAP; + break; + case EXCP_SOFT_BP: + { + int 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_HLT: + do_syscall(env, TARGET_NR_exit, 0, 0, 0, 0, 0, 0, 0, 0); + break; + case EXCP_ABORT: + do_syscall(env, TARGET_NR_exit, 1, 0, 0, 0, 0, 0, 0, 0); + break; + case EXCP_DBGA: + fprintf(stderr, "qemu: DBGA failed\n"); + cpu_dump_state(env, stderr, fprintf, 0); + gdbsig = TARGET_SIGABRT; + break; + case EXCP_UNDEF_INST: + fprintf(stderr, "qemu: unhandled insn @ %#x\n", env->pc); + log_target_disas(env, env->pc, 8, 0); + gdbsig = TARGET_SIGILL; + break; + case EXCP_DCPLB_VIOLATE: + fprintf(stderr, "qemu: memory violation @ %#x\n", env->pc); + log_target_disas(env, env->pc, 8, 0); + cpu_dump_state(env, stderr, fprintf, 0); + gdbsig = TARGET_SIGSEGV; + break; + case EXCP_ILL_SUPV: + fprintf(stderr, "qemu: supervisor mode required @ %#x\n", env->pc); + log_target_disas(env, env->pc, 8, 0); + gdbsig = TARGET_SIGILL; + break; + case EXCP_MISALIG_INST: + fprintf(stderr, "qemu: unaligned insn fetch @ %#x\n", env->pc); + log_target_disas(env, env->pc, 8, 0); + cpu_dump_state(env, stderr, fprintf, 0); + gdbsig = TARGET_SIGSEGV; + break; + case EXCP_DATA_MISALGIN: + fprintf(stderr, "qemu: unaligned data fetch @ %#x\n", env->pc); + log_target_disas(env, env->pc, 8, 0); + cpu_dump_state(env, stderr, fprintf, 0); + gdbsig = TARGET_SIGSEGV; + break; + default: + fprintf(stderr, "qemu: unhandled CPU exception %#x - aborting\n", + trapnr); + cpu_dump_state(env, stderr, fprintf, 0); + gdbsig = TARGET_SIGILL; + break; + } + + if (gdbsig) { + gdb_handlesig(env, gdbsig); + /* XXX: should we let people continue if gdb handles the signal ? */ + if (gdbsig != TARGET_SIGTRAP) { + exit(1); + } + } + + process_pending_signals(env); + } +} + +#endif + #ifdef TARGET_ALPHA static void do_store_exclusive(CPUAlphaState *env, int reg, int quad) { @@ -4013,6 +4122,57 @@ int main(int argc, char **argv, char **envp) } env->pc = regs->pc; } +#elif defined(TARGET_BFIN) + { + env->personality = info->personality; + env->dreg[0] = regs->r0; + env->dreg[1] = regs->r1; + env->dreg[2] = regs->r2; + env->dreg[3] = regs->r3; + env->dreg[4] = regs->r4; + env->dreg[5] = regs->r5; + env->dreg[6] = regs->r6; + env->dreg[7] = regs->r7; + env->preg[0] = regs->p0; + env->preg[1] = regs->p1; + env->preg[2] = regs->p2; + env->preg[3] = regs->p3; + env->preg[4] = regs->p4; + env->preg[5] = regs->p5; + env->spreg = regs->usp; + env->fpreg = regs->fp; + env->uspreg = regs->usp; + env->breg[0] = regs->b0; + env->breg[1] = regs->b1; + env->breg[2] = regs->b2; + env->breg[3] = regs->b3; + env->lreg[0] = regs->l0; + env->lreg[1] = regs->l1; + env->lreg[2] = regs->l2; + env->lreg[3] = regs->l3; + env->mreg[0] = regs->m0; + env->mreg[1] = regs->m1; + env->mreg[2] = regs->m2; + env->mreg[3] = regs->m3; + env->ireg[0] = regs->i0; + env->ireg[1] = regs->i1; + env->ireg[2] = regs->i2; + env->ireg[3] = regs->i3; + env->lcreg[0] = regs->lc0; + env->ltreg[0] = regs->lt0; + env->lbreg[0] = regs->lb0; + env->lcreg[1] = regs->lc1; + env->ltreg[1] = regs->lt1; + env->lbreg[1] = regs->lb1; + env->areg[0] = ((uint64_t)regs->a0x << 32) | regs->a0w; + env->areg[1] = ((uint64_t)regs->a1x << 32) | regs->a1w; + env->rets = regs->rets; + env->rete = regs->rete; + env->retn = regs->retn; + env->retx = regs->retx; + env->pc = regs->pc; + bfin_astat_write(env, regs->astat); + } #elif defined(TARGET_ALPHA) { int i; diff --git a/linux-user/qemu.h b/linux-user/qemu.h index b10e957..819f268 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -26,6 +26,10 @@ #define THREAD #endif +#ifdef TARGET_BFIN +#define CONFIG_USE_FDPIC +#endif + /* 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 diff --git a/linux-user/signal.c b/linux-user/signal.c index 5da8452..6e2d613 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -5353,6 +5353,231 @@ long do_rt_sigreturn(CPUAlphaState *env) force_sig(TARGET_SIGSEGV); } +#elif defined(TARGET_BFIN) + +#include "target_sigcontext.h" +#include "target_ucontext.h" + +struct target_rt_sigframe { + int32_t sig; + abi_ulong pinfo; + abi_ulong puc; + /* This is no longer needed by the kernel, but unfortunately userspace + * code expects it to be there. */ + char retcode[8]; + target_siginfo_t info; + struct target_ucontext uc; +}; + +struct fdpic_func_descriptor { + abi_ulong text; + abi_ulong GOT; +}; + +#define rreg dreg + +static inline int +target_rt_restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc, long *ret) +{ + uint32_t reg; + int err = 0; + +#define RESTORE2(e, x) err |= __get_user(env->e, &sc->sc_##x) +#define RESTOREA(r, i) RESTORE2(r##reg[i], r##i) +#define RESTORE(x) RESTORE2(x, x) + + /* restore passed registers */ + RESTOREA(r, 0); RESTOREA(r, 1); RESTOREA(r, 2); RESTOREA(r, 3); + RESTOREA(r, 4); RESTOREA(r, 5); RESTOREA(r, 6); RESTOREA(r, 7); + RESTOREA(p, 0); RESTOREA(p, 1); RESTOREA(p, 2); RESTOREA(p, 3); + RESTOREA(p, 4); RESTOREA(p, 5); + RESTORE2(spreg, usp); + err |= __get_user(reg, &sc->sc_a0x); + env->areg[0] = reg; + err |= __get_user(reg, &sc->sc_a0w); + env->areg[0] = (env->areg[0] << 32) | reg; + err |= __get_user(reg, &sc->sc_a1x); + env->areg[1] = reg; + err |= __get_user(reg, &sc->sc_a1w); + env->areg[1] = (env->areg[1] << 32) | reg; + err |= __get_user(reg, &sc->sc_astat); + bfin_astat_write(env, reg); + RESTORE(rets); + RESTORE(pc); + RESTORE(retx); + RESTORE2(fpreg, fp); + RESTOREA(i, 0); RESTOREA(i, 1); RESTOREA(i, 2); RESTOREA(i, 3); + RESTOREA(m, 0); RESTOREA(m, 1); RESTOREA(m, 2); RESTOREA(m, 3); + RESTOREA(l, 0); RESTOREA(l, 1); RESTOREA(l, 2); RESTOREA(l, 3); + RESTOREA(b, 0); RESTOREA(b, 1); RESTOREA(b, 2); RESTOREA(b, 3); + RESTOREA(lc, 0); RESTOREA(lc, 1); + RESTOREA(lt, 0); RESTOREA(lt, 1); + RESTOREA(lb, 0); RESTOREA(lb, 1); + RESTORE(seqstat); + + *ret = env->dreg[0]; + return err; +} + +static inline int +target_rt_setup_sigcontext(struct target_sigcontext *sc, CPUArchState *env) +{ + int err = 0; + +#define SETUP2(e, x) err |= __put_user(env->e, &sc->sc_##x) +#define SETUPA(r, i) SETUP2(r##reg[i], r##i) +#define SETUP(x) SETUP2(x, x) + + SETUPA(r, 0); SETUPA(r, 1); SETUPA(r, 2); SETUPA(r, 3); + SETUPA(r, 4); SETUPA(r, 5); SETUPA(r, 6); SETUPA(r, 7); + SETUPA(p, 0); SETUPA(p, 1); SETUPA(p, 2); SETUPA(p, 3); + SETUPA(p, 4); SETUPA(p, 5); + SETUP2(spreg, usp); + err |= __put_user((uint32_t)env->areg[0], &sc->sc_a0w); + err |= __put_user((uint32_t)env->areg[1], &sc->sc_a1w); + err |= __put_user((uint32_t)(env->areg[0] >> 32), &sc->sc_a0x); + err |= __put_user((uint32_t)(env->areg[1] >> 32), &sc->sc_a1x); + err |= __put_user(bfin_astat_read(env), &sc->sc_astat); + SETUP(rets); + SETUP(pc); + SETUP(retx); + SETUP2(fpreg, fp); + SETUPA(i, 0); SETUPA(i, 1); SETUPA(i, 2); SETUPA(i, 3); + SETUPA(m, 0); SETUPA(m, 1); SETUPA(m, 2); SETUPA(m, 3); + SETUPA(l, 0); SETUPA(l, 1); SETUPA(l, 2); SETUPA(l, 3); + SETUPA(b, 0); SETUPA(b, 1); SETUPA(b, 2); SETUPA(b, 3); + SETUPA(lc, 0); SETUPA(lc, 1); + SETUPA(lt, 0); SETUPA(lt, 1); + SETUPA(lb, 0); SETUPA(lb, 1); + SETUP(seqstat); + + return err; +} + +#undef rreg + +static inline abi_ulong +get_sigframe(struct target_sigaction *ka, CPUArchState *env, size_t frame_size) +{ + abi_ulong usp; + + /* Default to using normal stack. */ + usp = env->spreg; + + /* This is the X/Open sanctioned signal stack switching. */ + if ((ka->sa_flags & TARGET_SA_ONSTACK) && (sas_ss_flags(usp) == 0)) { + usp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size; + } + + return ((usp - frame_size) & -8UL); +} + +static void setup_rt_frame(int sig, struct target_sigaction *ka, + target_siginfo_t *info, + target_sigset_t *set, CPUArchState *env) +{ + struct target_rt_sigframe *frame; + abi_ulong frame_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; + + err |= __put_user(sig, &frame->sig); + + info_addr = frame_addr + offsetof(struct target_rt_sigframe, info); + err |= __put_user(info_addr, &frame->pinfo); + uc_addr = frame_addr + offsetof(struct target_rt_sigframe, uc); + err |= __put_user(uc_addr, &frame->puc); + err |= copy_siginfo_to_user(&frame->info, info); + + /* Create the ucontext. */ + err |= __put_user(0, &frame->uc.tuc_flags); + err |= __put_user(0, &frame->uc.tuc_link); + err |= __put_user(target_sigaltstack_used.ss_sp, &frame->uc.tuc_stack.ss_sp); + err |= __put_user(sas_ss_flags(env->spreg), &frame->uc.tuc_stack.ss_flags); + err |= __put_user(target_sigaltstack_used.ss_size, &frame->uc.tuc_stack.ss_size); + err |= target_rt_setup_sigcontext(&frame->uc.tuc_mcontext, env); + + for (i = 0; i < TARGET_NSIG_WORDS; i++) { + if (__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i])) + goto give_sigsegv; + } + + if (err) + goto give_sigsegv; + + /* Set up registers for signal handler */ + env->spreg = frame_addr; + if (env->personality & 0x0080000/*FDPIC_FUNCPTRS*/) { + struct fdpic_func_descriptor *funcptr; + if (!lock_user_struct(VERIFY_READ, funcptr, ka->_sa_handler, 1)) + goto give_sigsegv; + __get_user(env->pc, &funcptr->text); + __get_user(env->preg[3], &funcptr->GOT); + unlock_user_struct(funcptr, ka->_sa_handler, 0); + } else + env->pc = ka->_sa_handler; + env->rets = TARGET_SIGRETURN_STUB; + + env->dreg[0] = frame->sig; + env->dreg[1] = info_addr; + env->dreg[2] = uc_addr; + + unlock_user_struct(frame, frame_addr, 1); + return; + + give_sigsegv: + unlock_user_struct(frame, frame_addr, 1); + force_sig(TARGET_SIGSEGV); +} + +static void setup_frame(int sig, struct target_sigaction *ka, + target_sigset_t *set, CPUArchState *env) +{ + target_siginfo_t info; + setup_rt_frame(sig, ka, &info, set, env); +} + +long do_sigreturn(CPUArchState *env) +{ + fprintf(stderr, "do_sigreturn: not implemented\n"); + return -TARGET_ENOSYS; +} + +/* NB: This version should work for any arch ... */ +long do_rt_sigreturn(CPUArchState *env) +{ + long ret; + abi_ulong frame_addr = env->spreg; + struct target_rt_sigframe *frame; + sigset_t host_set; + + if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) + goto badframe; + + target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask); + sigprocmask(SIG_SETMASK, &host_set, NULL); + + if (target_rt_restore_sigcontext(env, &frame->uc.tuc_mcontext, &ret)) + 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 ret; + + badframe: + unlock_user_struct(frame, frame_addr, 0); + force_sig(TARGET_SIGSEGV); + return 0; +} + #else static void setup_frame(int sig, struct target_sigaction *ka, diff --git a/linux-user/syscall.c b/linux-user/syscall.c index cdd0c28..a9dce35 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -7444,7 +7444,8 @@ 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_S390X) || defined(TARGET_OPENRISC) + defined(TARGET_M68K) || defined(TARGET_S390X) || defined(TARGET_OPENRISC) || \ + defined(TARGET_BFIN) ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUArchState *)cpu_env)); break; #else diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 92c01a9..362cd2d 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -63,7 +63,7 @@ #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) + || defined(TARGET_S390X) || defined(TARGET_OPENRISC) || defined(TARGET_BFIN) #define TARGET_IOC_SIZEBITS 14 #define TARGET_IOC_DIRBITS 2 @@ -327,7 +327,7 @@ int do_sigaction(int sig, const struct target_sigaction *act, || 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) + || defined(TARGET_S390X) || defined(TARGET_OPENRISC) || defined(TARGET_BFIN) #if defined(TARGET_SPARC) #define TARGET_SA_NOCLDSTOP 8u @@ -1689,6 +1689,67 @@ struct target_stat64 { int64_t st_blocks; }; +#elif defined(TARGET_BFIN) + +struct target_stat { + uint16_t st_dev; + uint16_t __pad1; + abi_ulong st_ino; + uint16_t st_mode; + uint16_t st_nlink; + uint16_t st_uid; + uint16_t st_gid; + uint16_t st_rdev; + uint16_t __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; +} __attribute__((packed)); + +/* This matches struct stat64 in glibc2.1, hence the absolutely + * insane amounts of padding around dev_t's. + */ +struct target_stat64 { + uint64_t st_dev; + unsigned char __pad1[4]; + +#define STAT64_HAS_BROKEN_ST_INO 1 + abi_ulong __st_ino; + + uint32_t st_mode; + uint32_t st_nlink; + + abi_ulong st_uid; + abi_ulong st_gid; + + uint64_t st_rdev; + unsigned char __pad2[4]; + + int64_t st_size; + abi_ulong st_blksize; + + int64_t 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; + + uint64_t st_ino; +} __attribute__((packed)); + #elif defined(TARGET_ALPHA) struct target_stat { diff --git a/linux-user/target_ucontext.h b/linux-user/target_ucontext.h new file mode 100644 index 0000000..49706b4 --- /dev/null +++ b/linux-user/target_ucontext.h @@ -0,0 +1,14 @@ +/* This is the asm-generic/ucontext.h version */ + +#ifndef TARGET_UCONTEXT_H +#define TARGET_UCONTEXT_H + +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 */ +}; + +#endif -- 1.8.2.1