]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/cris/traps.c
* sim/cris/c/clone5.c, sim/cris/c/mprotect1.c,
[thirdparty/binutils-gdb.git] / sim / cris / traps.c
CommitLineData
f6bcefef
HPN
1/* CRIS exception, interrupt, and trap (EIT) support
2 Copyright (C) 2004, 2005 Free Software Foundation, Inc.
3 Contributed by Axis Communications.
4
5This file is part of the GNU simulators.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License along
18with this program; if not, write to the Free Software Foundation, Inc.,
1959 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21#include "sim-main.h"
22#include "sim-options.h"
f6bcefef 23#include "bfd.h"
ed1f044a
HPN
24/* FIXME: get rid of targ-vals.h usage everywhere else. */
25
f6bcefef
HPN
26#ifdef HAVE_ERRNO_H
27#include <errno.h>
28#endif
29#ifdef HAVE_UNISTD_H
30#include <unistd.h>
31#endif
32#ifdef HAVE_FCNTL_H
33#include <fcntl.h>
34#endif
35#ifdef HAVE_SYS_PARAM_H
36#include <sys/param.h>
37#endif
38#ifdef HAVE_SYS_STAT_H
39#include <sys/stat.h>
40#endif
3ca4d560
HPN
41/* For PATH_MAX, originally. */
42#ifdef HAVE_LIMITS_H
43#include <limits.h>
44#endif
45
46/* From ld/sysdep.h. */
47#ifdef PATH_MAX
48# define SIM_PATHMAX PATH_MAX
49#else
50# ifdef MAXPATHLEN
51# define SIM_PATHMAX MAXPATHLEN
52# else
53# define SIM_PATHMAX 1024
54# endif
55#endif
f6bcefef
HPN
56
57/* The verbatim values are from asm-cris/unistd.h. */
58
59#define TARGET_SYS_exit 1
60#define TARGET_SYS_read 3
61#define TARGET_SYS_write 4
62#define TARGET_SYS_open 5
63#define TARGET_SYS_close 6
64#define TARGET_SYS_unlink 10
65#define TARGET_SYS_time 13
66#define TARGET_SYS_lseek 19
67#define TARGET_SYS_getpid 20
68#define TARGET_SYS_kill 37
69#define TARGET_SYS_rename 38
70#define TARGET_SYS_pipe 42
71#define TARGET_SYS_brk 45
72#define TARGET_SYS_ioctl 54
73#define TARGET_SYS_fcntl 55
74#define TARGET_SYS_getppid 64
75#define TARGET_SYS_setrlimit 75
76#define TARGET_SYS_gettimeofday 78
77#define TARGET_SYS_readlink 85
78#define TARGET_SYS_munmap 91
79#define TARGET_SYS_truncate 92
80#define TARGET_SYS_ftruncate 93
81#define TARGET_SYS_socketcall 102
5457266c 82#define TARGET_SYS_stat 106
f6bcefef
HPN
83#define TARGET_SYS_fstat 108
84#define TARGET_SYS_wait4 114
85#define TARGET_SYS_sigreturn 119
86#define TARGET_SYS_clone 120
87#define TARGET_SYS_uname 122
88#define TARGET_SYS_mprotect 125
89#define TARGET_SYS_llseek 140
90#define TARGET_SYS__sysctl 149
91#define TARGET_SYS_sched_setparam 154
92#define TARGET_SYS_sched_getparam 155
93#define TARGET_SYS_sched_setscheduler 156
94#define TARGET_SYS_sched_getscheduler 157
95#define TARGET_SYS_sched_yield 158
96#define TARGET_SYS_sched_get_priority_max 159
97#define TARGET_SYS_sched_get_priority_min 160
98#define TARGET_SYS_mremap 163
99#define TARGET_SYS_poll 168
100#define TARGET_SYS_rt_sigaction 174
101#define TARGET_SYS_rt_sigprocmask 175
102#define TARGET_SYS_rt_sigsuspend 179
103#define TARGET_SYS_getcwd 183
104#define TARGET_SYS_ugetrlimit 191
105#define TARGET_SYS_mmap2 192
106#define TARGET_SYS_stat64 195
107#define TARGET_SYS_lstat64 196
108#define TARGET_SYS_fstat64 197
109#define TARGET_SYS_geteuid32 201
110#define TARGET_SYS_getuid32 199
111#define TARGET_SYS_getegid32 202
112#define TARGET_SYS_getgid32 200
113#define TARGET_SYS_fcntl64 221
114
115#define TARGET_PROT_READ 0x1
116#define TARGET_PROT_WRITE 0x2
117#define TARGET_PROT_EXEC 0x4
118#define TARGET_PROT_NONE 0x0
119
120#define TARGET_MAP_SHARED 0x01
121#define TARGET_MAP_PRIVATE 0x02
122#define TARGET_MAP_TYPE 0x0f
123#define TARGET_MAP_FIXED 0x10
124#define TARGET_MAP_ANONYMOUS 0x20
125
126#define TARGET_CTL_KERN 1
127#define TARGET_CTL_VM 2
128#define TARGET_CTL_NET 3
129#define TARGET_CTL_PROC 4
130#define TARGET_CTL_FS 5
131#define TARGET_CTL_DEBUG 6
132#define TARGET_CTL_DEV 7
133#define TARGET_CTL_BUS 8
134#define TARGET_CTL_ABI 9
135
136#define TARGET_CTL_KERN_VERSION 4
137
138/* linux/mman.h */
139#define TARGET_MREMAP_MAYMOVE 1
140#define TARGET_MREMAP_FIXED 2
141
142#define TARGET_TCGETS 0x5401
143
144#define TARGET_UTSNAME "#38 Sun Apr 1 00:00:00 MET 2001"
145
146/* Seconds since the above date + 10 minutes. */
147#define TARGET_EPOCH 986080200
148
149/* Milliseconds since start of run. We use the number of syscalls to
150 avoid introducing noise in the execution time. */
151#define TARGET_TIME_MS(cpu) ((cpu)->syscalls)
152
153/* Seconds as in time(2). */
154#define TARGET_TIME(cpu) (TARGET_EPOCH + TARGET_TIME_MS (cpu) / 1000)
155
156#define TARGET_SCHED_OTHER 0
157
158#define TARGET_RLIMIT_STACK 3
159#define TARGET_RLIMIT_NOFILE 7
160
161#define SIM_TARGET_MAX_THREADS 64
162#define SIM_MAX_ALLOC_CHUNK (512*1024*1024)
163
164/* From linux/sched.h. */
165#define TARGET_CSIGNAL 0x000000ff
166#define TARGET_CLONE_VM 0x00000100
167#define TARGET_CLONE_FS 0x00000200
168#define TARGET_CLONE_FILES 0x00000400
169#define TARGET_CLONE_SIGHAND 0x00000800
170#define TARGET_CLONE_PID 0x00001000
171#define TARGET_CLONE_PTRACE 0x00002000
172#define TARGET_CLONE_VFORK 0x00004000
173#define TARGET_CLONE_PARENT 0x00008000
174#define TARGET_CLONE_THREAD 0x00010000
175#define TARGET_CLONE_SIGNAL (TARGET_CLONE_SIGHAND | TARGET_CLONE_THREAD)
176
177/* From asm-cris/poll.h. */
178#define TARGET_POLLIN 1
179
180/* From asm-cris/signal.h. */
181#define TARGET_SIG_BLOCK 0
182#define TARGET_SIG_UNBLOCK 1
183#define TARGET_SIG_SETMASK 2
184
185#define TARGET_SIG_DFL 0
186#define TARGET_SIG_IGN 1
187#define TARGET_SIG_ERR ((USI)-1)
188
189#define TARGET_SIGHUP 1
190#define TARGET_SIGINT 2
191#define TARGET_SIGQUIT 3
192#define TARGET_SIGILL 4
193#define TARGET_SIGTRAP 5
194#define TARGET_SIGABRT 6
195#define TARGET_SIGIOT 6
196#define TARGET_SIGBUS 7
197#define TARGET_SIGFPE 8
198#define TARGET_SIGKILL 9
199#define TARGET_SIGUSR1 10
200#define TARGET_SIGSEGV 11
201#define TARGET_SIGUSR2 12
202#define TARGET_SIGPIPE 13
203#define TARGET_SIGALRM 14
204#define TARGET_SIGTERM 15
205#define TARGET_SIGSTKFLT 16
206#define TARGET_SIGCHLD 17
207#define TARGET_SIGCONT 18
208#define TARGET_SIGSTOP 19
209#define TARGET_SIGTSTP 20
210#define TARGET_SIGTTIN 21
211#define TARGET_SIGTTOU 22
212#define TARGET_SIGURG 23
213#define TARGET_SIGXCPU 24
214#define TARGET_SIGXFSZ 25
215#define TARGET_SIGVTALRM 26
216#define TARGET_SIGPROF 27
217#define TARGET_SIGWINCH 28
218#define TARGET_SIGIO 29
219#define TARGET_SIGPOLL SIGIO
220/* Actually commented out in the kernel header. */
221#define TARGET_SIGLOST 29
222#define TARGET_SIGPWR 30
223#define TARGET_SIGSYS 31
224
225/* From include/asm-cris/signal.h. */
226#define TARGET_SA_NOCLDSTOP 0x00000001
227#define TARGET_SA_NOCLDWAIT 0x00000002 /* not supported yet */
228#define TARGET_SA_SIGINFO 0x00000004
229#define TARGET_SA_ONSTACK 0x08000000
230#define TARGET_SA_RESTART 0x10000000
231#define TARGET_SA_NODEFER 0x40000000
232#define TARGET_SA_RESETHAND 0x80000000
233#define TARGET_SA_INTERRUPT 0x20000000 /* dummy -- ignored */
234#define TARGET_SA_RESTORER 0x04000000
235
236/* From linux/wait.h. */
237#define TARGET_WNOHANG 1
238#define TARGET_WUNTRACED 2
239#define TARGET___WNOTHREAD 0x20000000
240#define TARGET___WALL 0x40000000
241#define TARGET___WCLONE 0x80000000
242
eccd787e
HPN
243/* From linux/limits.h. */
244#define TARGET_PIPE_BUF 4096
245
f6bcefef
HPN
246static const char stat_map[] =
247"st_dev,2:space,10:space,4:st_mode,4:st_nlink,4:st_uid,4"
248":st_gid,4:st_rdev,2:space,10:st_size,8:st_blksize,4:st_blocks,4"
249":space,4:st_atime,4:space,4:st_mtime,4:space,4:st_ctime,4:space,4"
250":st_ino,8";
251
252static const CB_TARGET_DEFS_MAP syscall_map[] =
253{
254 { CB_SYS_open, TARGET_SYS_open },
255 { CB_SYS_close, TARGET_SYS_close },
256 { CB_SYS_read, TARGET_SYS_read },
257 { CB_SYS_write, TARGET_SYS_write },
258 { CB_SYS_lseek, TARGET_SYS_lseek },
259 { CB_SYS_unlink, TARGET_SYS_unlink },
260 { CB_SYS_getpid, TARGET_SYS_getpid },
261 { CB_SYS_fstat, TARGET_SYS_fstat64 },
262 { CB_SYS_lstat, TARGET_SYS_lstat64 },
263 { CB_SYS_stat, TARGET_SYS_stat64 },
264 { CB_SYS_pipe, TARGET_SYS_pipe },
f6bcefef
HPN
265 { CB_SYS_rename, TARGET_SYS_rename },
266 { CB_SYS_truncate, TARGET_SYS_truncate },
267 { CB_SYS_ftruncate, TARGET_SYS_ftruncate },
268 { 0, -1 }
269};
270
271/* An older, 32-bit-only stat mapping. */
272static const char stat32_map[] =
273"st_dev,2:space,2:st_ino,4:st_mode,2:st_nlink,2:st_uid,2"
274":st_gid,2:st_rdev,2:space,2:st_size,4:st_blksize,4:st_blocks,4"
275":st_atime,4:space,4:st_mtime,4:space,4:st_ctime,4:space,12";
276
277/* Map for calls using the 32-bit struct stat. Primarily used by the
278 newlib Linux mapping. */
279static const CB_TARGET_DEFS_MAP syscall_stat32_map[] =
280{
281 { CB_SYS_fstat, TARGET_SYS_fstat },
5457266c 282 { CB_SYS_stat, TARGET_SYS_stat },
f6bcefef
HPN
283 { 0, -1 }
284};
285
286/* Giving the true value for the running sim process will lead to
287 non-time-invariant behavior. */
288#define TARGET_PID 42
289
290/* Unfortunately, we don't get this from cris.cpu at the moment, and if
291 we did, we'd still don't get a register number with the "16" offset. */
292#define TARGET_SRP_REGNUM (16+11)
293
294/* Extracted by applying
295 awk '/^#define/ { printf "#ifdef %s\n { %s, %s },\n#endif\n", $2, $2, $3;}'
296 on .../include/asm/errno.h in a GNU/Linux/CRIS installation and
297 adjusting the synonyms. */
298
299static const CB_TARGET_DEFS_MAP errno_map[] =
300{
301#ifdef EPERM
302 { EPERM, 1 },
303#endif
304#ifdef ENOENT
305 { ENOENT, 2 },
306#endif
307#ifdef ESRCH
308 { ESRCH, 3 },
309#endif
310#ifdef EINTR
311 { EINTR, 4 },
312#endif
313#ifdef EIO
314 { EIO, 5 },
315#endif
316#ifdef ENXIO
317 { ENXIO, 6 },
318#endif
319#ifdef E2BIG
320 { E2BIG, 7 },
321#endif
322#ifdef ENOEXEC
323 { ENOEXEC, 8 },
324#endif
325#ifdef EBADF
326 { EBADF, 9 },
327#endif
328#ifdef ECHILD
329 { ECHILD, 10 },
330#endif
331#ifdef EAGAIN
332 { EAGAIN, 11 },
333#endif
334#ifdef ENOMEM
335 { ENOMEM, 12 },
336#endif
337#ifdef EACCES
338 { EACCES, 13 },
339#endif
340#ifdef EFAULT
341 { EFAULT, 14 },
342#endif
343#ifdef ENOTBLK
344 { ENOTBLK, 15 },
345#endif
346#ifdef EBUSY
347 { EBUSY, 16 },
348#endif
349#ifdef EEXIST
350 { EEXIST, 17 },
351#endif
352#ifdef EXDEV
353 { EXDEV, 18 },
354#endif
355#ifdef ENODEV
356 { ENODEV, 19 },
357#endif
358#ifdef ENOTDIR
359 { ENOTDIR, 20 },
360#endif
361#ifdef EISDIR
362 { EISDIR, 21 },
363#endif
364#ifdef EINVAL
365 { EINVAL, 22 },
366#endif
367#ifdef ENFILE
368 { ENFILE, 23 },
369#endif
370#ifdef EMFILE
371 { EMFILE, 24 },
372#endif
373#ifdef ENOTTY
374 { ENOTTY, 25 },
375#endif
376#ifdef ETXTBSY
377 { ETXTBSY, 26 },
378#endif
379#ifdef EFBIG
380 { EFBIG, 27 },
381#endif
382#ifdef ENOSPC
383 { ENOSPC, 28 },
384#endif
385#ifdef ESPIPE
386 { ESPIPE, 29 },
387#endif
388#ifdef EROFS
389 { EROFS, 30 },
390#endif
391#ifdef EMLINK
392 { EMLINK, 31 },
393#endif
394#ifdef EPIPE
395 { EPIPE, 32 },
396#endif
397#ifdef EDOM
398 { EDOM, 33 },
399#endif
400#ifdef ERANGE
401 { ERANGE, 34 },
402#endif
403#ifdef EDEADLK
404 { EDEADLK, 35 },
405#endif
406#ifdef ENAMETOOLONG
407 { ENAMETOOLONG, 36 },
408#endif
409#ifdef ENOLCK
410 { ENOLCK, 37 },
411#endif
412#ifdef ENOSYS
413 { ENOSYS, 38 },
414#endif
415#ifdef ENOTEMPTY
416 { ENOTEMPTY, 39 },
417#endif
418#ifdef ELOOP
419 { ELOOP, 40 },
420#endif
421#ifdef EWOULDBLOCK
422 { EWOULDBLOCK, 11 },
423#endif
424#ifdef ENOMSG
425 { ENOMSG, 42 },
426#endif
427#ifdef EIDRM
428 { EIDRM, 43 },
429#endif
430#ifdef ECHRNG
431 { ECHRNG, 44 },
432#endif
433#ifdef EL2NSYNC
434 { EL2NSYNC, 45 },
435#endif
436#ifdef EL3HLT
437 { EL3HLT, 46 },
438#endif
439#ifdef EL3RST
440 { EL3RST, 47 },
441#endif
442#ifdef ELNRNG
443 { ELNRNG, 48 },
444#endif
445#ifdef EUNATCH
446 { EUNATCH, 49 },
447#endif
448#ifdef ENOCSI
449 { ENOCSI, 50 },
450#endif
451#ifdef EL2HLT
452 { EL2HLT, 51 },
453#endif
454#ifdef EBADE
455 { EBADE, 52 },
456#endif
457#ifdef EBADR
458 { EBADR, 53 },
459#endif
460#ifdef EXFULL
461 { EXFULL, 54 },
462#endif
463#ifdef ENOANO
464 { ENOANO, 55 },
465#endif
466#ifdef EBADRQC
467 { EBADRQC, 56 },
468#endif
469#ifdef EBADSLT
470 { EBADSLT, 57 },
471#endif
472#ifdef EDEADLOCK
473 { EDEADLOCK, 35 },
474#endif
475#ifdef EBFONT
476 { EBFONT, 59 },
477#endif
478#ifdef ENOSTR
479 { ENOSTR, 60 },
480#endif
481#ifdef ENODATA
482 { ENODATA, 61 },
483#endif
484#ifdef ETIME
485 { ETIME, 62 },
486#endif
487#ifdef ENOSR
488 { ENOSR, 63 },
489#endif
490#ifdef ENONET
491 { ENONET, 64 },
492#endif
493#ifdef ENOPKG
494 { ENOPKG, 65 },
495#endif
496#ifdef EREMOTE
497 { EREMOTE, 66 },
498#endif
499#ifdef ENOLINK
500 { ENOLINK, 67 },
501#endif
502#ifdef EADV
503 { EADV, 68 },
504#endif
505#ifdef ESRMNT
506 { ESRMNT, 69 },
507#endif
508#ifdef ECOMM
509 { ECOMM, 70 },
510#endif
511#ifdef EPROTO
512 { EPROTO, 71 },
513#endif
514#ifdef EMULTIHOP
515 { EMULTIHOP, 72 },
516#endif
517#ifdef EDOTDOT
518 { EDOTDOT, 73 },
519#endif
520#ifdef EBADMSG
521 { EBADMSG, 74 },
522#endif
523#ifdef EOVERFLOW
524 { EOVERFLOW, 75 },
525#endif
526#ifdef ENOTUNIQ
527 { ENOTUNIQ, 76 },
528#endif
529#ifdef EBADFD
530 { EBADFD, 77 },
531#endif
532#ifdef EREMCHG
533 { EREMCHG, 78 },
534#endif
535#ifdef ELIBACC
536 { ELIBACC, 79 },
537#endif
538#ifdef ELIBBAD
539 { ELIBBAD, 80 },
540#endif
541#ifdef ELIBSCN
542 { ELIBSCN, 81 },
543#endif
544#ifdef ELIBMAX
545 { ELIBMAX, 82 },
546#endif
547#ifdef ELIBEXEC
548 { ELIBEXEC, 83 },
549#endif
550#ifdef EILSEQ
551 { EILSEQ, 84 },
552#endif
553#ifdef ERESTART
554 { ERESTART, 85 },
555#endif
556#ifdef ESTRPIPE
557 { ESTRPIPE, 86 },
558#endif
559#ifdef EUSERS
560 { EUSERS, 87 },
561#endif
562#ifdef ENOTSOCK
563 { ENOTSOCK, 88 },
564#endif
565#ifdef EDESTADDRREQ
566 { EDESTADDRREQ, 89 },
567#endif
568#ifdef EMSGSIZE
569 { EMSGSIZE, 90 },
570#endif
571#ifdef EPROTOTYPE
572 { EPROTOTYPE, 91 },
573#endif
574#ifdef ENOPROTOOPT
575 { ENOPROTOOPT, 92 },
576#endif
577#ifdef EPROTONOSUPPORT
578 { EPROTONOSUPPORT, 93 },
579#endif
580#ifdef ESOCKTNOSUPPORT
581 { ESOCKTNOSUPPORT, 94 },
582#endif
583#ifdef EOPNOTSUPP
584 { EOPNOTSUPP, 95 },
585#endif
586#ifdef EPFNOSUPPORT
587 { EPFNOSUPPORT, 96 },
588#endif
589#ifdef EAFNOSUPPORT
590 { EAFNOSUPPORT, 97 },
591#endif
592#ifdef EADDRINUSE
593 { EADDRINUSE, 98 },
594#endif
595#ifdef EADDRNOTAVAIL
596 { EADDRNOTAVAIL, 99 },
597#endif
598#ifdef ENETDOWN
599 { ENETDOWN, 100 },
600#endif
601#ifdef ENETUNREACH
602 { ENETUNREACH, 101 },
603#endif
604#ifdef ENETRESET
605 { ENETRESET, 102 },
606#endif
607#ifdef ECONNABORTED
608 { ECONNABORTED, 103 },
609#endif
610#ifdef ECONNRESET
611 { ECONNRESET, 104 },
612#endif
613#ifdef ENOBUFS
614 { ENOBUFS, 105 },
615#endif
616#ifdef EISCONN
617 { EISCONN, 106 },
618#endif
619#ifdef ENOTCONN
620 { ENOTCONN, 107 },
621#endif
622#ifdef ESHUTDOWN
623 { ESHUTDOWN, 108 },
624#endif
625#ifdef ETOOMANYREFS
626 { ETOOMANYREFS, 109 },
627#endif
628#ifdef ETIMEDOUT
629 { ETIMEDOUT, 110 },
630#endif
631#ifdef ECONNREFUSED
632 { ECONNREFUSED, 111 },
633#endif
634#ifdef EHOSTDOWN
635 { EHOSTDOWN, 112 },
636#endif
637#ifdef EHOSTUNREACH
638 { EHOSTUNREACH, 113 },
639#endif
640#ifdef EALREADY
641 { EALREADY, 114 },
642#endif
643#ifdef EINPROGRESS
644 { EINPROGRESS, 115 },
645#endif
646#ifdef ESTALE
647 { ESTALE, 116 },
648#endif
649#ifdef EUCLEAN
650 { EUCLEAN, 117 },
651#endif
652#ifdef ENOTNAM
653 { ENOTNAM, 118 },
654#endif
655#ifdef ENAVAIL
656 { ENAVAIL, 119 },
657#endif
658#ifdef EISNAM
659 { EISNAM, 120 },
660#endif
661#ifdef EREMOTEIO
662 { EREMOTEIO, 121 },
663#endif
664#ifdef EDQUOT
665 { EDQUOT, 122 },
666#endif
667#ifdef ENOMEDIUM
668 { ENOMEDIUM, 123 },
669#endif
670#ifdef EMEDIUMTYPE
671 { EMEDIUMTYPE, 124 },
672#endif
673 { 0, -1 }
674};
675
676/* Extracted by applying
677 perl -ne 'if ($_ =~ /^#define/) { split;
678 printf "#ifdef $_[1]\n { %s, 0x%x },\n#endif\n",
679 $_[1], $_[2] =~ /^0/ ? oct($_[2]) : $_[2];}'
680 on pertinent parts of .../include/asm/fcntl.h in a GNU/Linux/CRIS
681 installation and removing synonyms and unnecessary items. Don't
682 forget the end-marker. */
683
8b9b39f4
HPN
684/* These we treat specially, as they're used in the fcntl F_GETFL
685 syscall. For consistency, open_map is also manually edited to use
686 these macros. */
687#define TARGET_O_ACCMODE 0x3
688#define TARGET_O_RDONLY 0x0
689#define TARGET_O_WRONLY 0x1
ed1f044a 690
f6bcefef
HPN
691static const CB_TARGET_DEFS_MAP open_map[] = {
692#ifdef O_ACCMODE
8b9b39f4 693 { O_ACCMODE, TARGET_O_ACCMODE },
f6bcefef
HPN
694#endif
695#ifdef O_RDONLY
8b9b39f4 696 { O_RDONLY, TARGET_O_RDONLY },
f6bcefef
HPN
697#endif
698#ifdef O_WRONLY
8b9b39f4 699 { O_WRONLY, TARGET_O_WRONLY },
f6bcefef
HPN
700#endif
701#ifdef O_RDWR
702 { O_RDWR, 0x2 },
703#endif
704#ifdef O_CREAT
705 { O_CREAT, 0x40 },
706#endif
707#ifdef O_EXCL
708 { O_EXCL, 0x80 },
709#endif
710#ifdef O_NOCTTY
711 { O_NOCTTY, 0x100 },
712#endif
713#ifdef O_TRUNC
714 { O_TRUNC, 0x200 },
715#endif
716#ifdef O_APPEND
717 { O_APPEND, 0x400 },
718#endif
719#ifdef O_NONBLOCK
720 { O_NONBLOCK, 0x800 },
721#endif
722#ifdef O_NDELAY
723 { O_NDELAY, 0x0 },
724#endif
725#ifdef O_SYNC
726 { O_SYNC, 0x1000 },
727#endif
728#ifdef FASYNC
729 { FASYNC, 0x2000 },
730#endif
731#ifdef O_DIRECT
732 { O_DIRECT, 0x4000 },
733#endif
734#ifdef O_LARGEFILE
735 { O_LARGEFILE, 0x8000 },
736#endif
737#ifdef O_DIRECTORY
738 { O_DIRECTORY, 0x10000 },
739#endif
740#ifdef O_NOFOLLOW
741 { O_NOFOLLOW, 0x20000 },
742#endif
743 { -1, -1 }
744};
745
746/* Needed for the cris_pipe_nonempty and cris_pipe_empty syscalls. */
747static SIM_CPU *current_cpu_for_cb_callback;
748
749static int syscall_read_mem (host_callback *, struct cb_syscall *,
750 unsigned long, char *, int);
751static int syscall_write_mem (host_callback *, struct cb_syscall *,
752 unsigned long, const char *, int);
753static USI create_map (SIM_DESC, struct cris_sim_mmapped_page **,
754 USI addr, USI len);
755static USI unmap_pages (SIM_DESC, struct cris_sim_mmapped_page **,
756 USI addr, USI len);
757static USI is_mapped (SIM_DESC, struct cris_sim_mmapped_page **,
758 USI addr, USI len);
759static void dump_statistics (SIM_CPU *current_cpu);
760static void make_first_thread (SIM_CPU *current_cpu);
761
762/* Read/write functions for system call interface. */
763
764static int
765syscall_read_mem (host_callback *cb ATTRIBUTE_UNUSED,
766 struct cb_syscall *sc,
767 unsigned long taddr, char *buf, int bytes)
768{
769 SIM_DESC sd = (SIM_DESC) sc->p1;
770 SIM_CPU *cpu = (SIM_CPU *) sc->p2;
771
772 return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes);
773}
774
775static int
776syscall_write_mem (host_callback *cb ATTRIBUTE_UNUSED,
777 struct cb_syscall *sc,
778 unsigned long taddr, const char *buf, int bytes)
779{
780 SIM_DESC sd = (SIM_DESC) sc->p1;
781 SIM_CPU *cpu = (SIM_CPU *) sc->p2;
782
783 return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes);
784}
785
786/* When we risk running self-modified code (as in trampolines), this is
787 called from special-case insns. The silicon CRIS CPU:s have enough
788 cache snooping implemented making this a simulator-only issue. Tests:
789 gcc.c-torture/execute/931002-1.c execution, -O3 -g
790 gcc.c-torture/execute/931002-1.c execution, -O3 -fomit-frame-pointer. */
791
792void
793cris_flush_simulator_decode_cache (SIM_CPU *current_cpu,
794 USI pc ATTRIBUTE_UNUSED)
795{
796 SIM_DESC sd = CPU_STATE (current_cpu);
797
798#if WITH_SCACHE
799 if (USING_SCACHE_P (sd))
800 scache_flush_cpu (current_cpu);
801#endif
802}
803
804/* Output statistics at the end of a run. */
805static void
806dump_statistics (SIM_CPU *current_cpu)
807{
808 SIM_DESC sd = CPU_STATE (current_cpu);
809 CRIS_MISC_PROFILE *profp
810 = CPU_CRIS_MISC_PROFILE (current_cpu);
811 unsigned64 total = profp->basic_cycle_count;
812 const char *textmsg = "Basic clock cycles, total @: %llu\n";
813
814 /* The --cris-stats={basic|unaligned|schedulable|all} counts affect
815 what's included in the "total" count only. */
816 switch (CPU_CRIS_MISC_PROFILE (current_cpu)->flags
817 & FLAG_CRIS_MISC_PROFILE_ALL)
818 {
819 case FLAG_CRIS_MISC_PROFILE_SIMPLE:
820 break;
821
822 case (FLAG_CRIS_MISC_PROFILE_UNALIGNED | FLAG_CRIS_MISC_PROFILE_SIMPLE):
823 textmsg
824 = "Clock cycles including stall cycles for unaligned accesses @: %llu\n";
825 total += profp->unaligned_mem_dword_count;
826 break;
827
828 case (FLAG_CRIS_MISC_PROFILE_SCHEDULABLE | FLAG_CRIS_MISC_PROFILE_SIMPLE):
829 textmsg = "Schedulable clock cycles, total @: %llu\n";
830 total
831 += (profp->memsrc_stall_count
832 + profp->memraw_stall_count
833 + profp->movemsrc_stall_count
834 + profp->movemdst_stall_count
835 + profp->mulsrc_stall_count
836 + profp->jumpsrc_stall_count
837 + profp->unaligned_mem_dword_count);
838 break;
839
840 case FLAG_CRIS_MISC_PROFILE_ALL:
841 textmsg = "All accounted clock cycles, total @: %llu\n";
842 total
843 += (profp->memsrc_stall_count
844 + profp->memraw_stall_count
845 + profp->movemsrc_stall_count
846 + profp->movemdst_stall_count
847 + profp->movemaddr_stall_count
848 + profp->mulsrc_stall_count
849 + profp->jumpsrc_stall_count
850 + profp->branch_stall_count
851 + profp->jumptarget_stall_count
852 + profp->unaligned_mem_dword_count);
853 break;
854
855 default:
856 abort ();
857
858 sim_io_eprintf (sd,
859 "Internal inconsistency at %s:%d",
860 __FILE__, __LINE__);
861 sim_engine_halt (sd, current_cpu, NULL, 0,
862 sim_stopped, SIM_SIGILL);
863 }
864
865 /* Historically, these messages have gone to stderr, so we'll keep it
866 that way. It's also easier to then tell it from normal program
867 output. FIXME: Add redirect option like "run -e file". */
868 sim_io_eprintf (sd, textmsg, total);
869
870 /* For v32, unaligned_mem_dword_count should always be 0. For
871 v10, memsrc_stall_count should always be 0. */
872 sim_io_eprintf (sd, "Memory source stall cycles: %lld\n",
873 profp->memsrc_stall_count
874 + profp->unaligned_mem_dword_count);
875 sim_io_eprintf (sd, "Memory read-after-write stall cycles: %lld\n",
876 profp->memraw_stall_count);
877 sim_io_eprintf (sd, "Movem source stall cycles: %lld\n",
878 profp->movemsrc_stall_count);
879 sim_io_eprintf (sd, "Movem destination stall cycles: %lld\n",
880 profp->movemdst_stall_count);
881 sim_io_eprintf (sd, "Movem address stall cycles: %lld\n",
882 profp->movemaddr_stall_count);
883 sim_io_eprintf (sd, "Multiplication source stall cycles: %lld\n",
884 profp->mulsrc_stall_count);
885 sim_io_eprintf (sd, "Jump source stall cycles: %lld\n",
886 profp->jumpsrc_stall_count);
887 sim_io_eprintf (sd, "Branch misprediction stall cycles: %lld\n",
888 profp->branch_stall_count);
889 sim_io_eprintf (sd, "Jump target stall cycles: %lld\n",
890 profp->jumptarget_stall_count);
891}
892
893/* Check whether any part of [addr .. addr + len - 1] is already mapped.
894 Return 1 if a overlap detected, 0 otherwise. */
895
896static USI
897is_mapped (SIM_DESC sd ATTRIBUTE_UNUSED,
898 struct cris_sim_mmapped_page **rootp,
899 USI addr, USI len)
900{
901 struct cris_sim_mmapped_page *mapp;
902
903 if (len == 0 || (len & 8191))
904 abort ();
905
906 /* Iterate over the reverse-address sorted pages until we find a page in
907 or lower than the checked area. */
908 for (mapp = *rootp; mapp != NULL && mapp->addr >= addr; mapp = mapp->prev)
909 if (mapp->addr < addr + len && mapp->addr >= addr)
910 return 1;
911
912 return 0;
913}
914
915/* Create mmapped memory. */
916
917static USI
918create_map (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
919 USI len)
920{
921 struct cris_sim_mmapped_page *mapp;
922 struct cris_sim_mmapped_page **higher_prevp = rootp;
923 USI new_addr = 0x40000000;
924
925 if (addr != 0)
926 new_addr = addr;
927 else if (*rootp)
928 new_addr = rootp[0]->addr + 8192;
929
930 if (len != 8192)
931 {
932 USI page_addr;
933
934 if (len & 8191)
935 /* Which is better: return an error for this, or just round it up? */
936 abort ();
937
938 /* Do a recursive call for each page in the request. */
939 for (page_addr = new_addr; len != 0; page_addr += 8192, len -= 8192)
940 if (create_map (sd, rootp, page_addr, 8192) >= (USI) -8191)
941 abort ();
942
943 return new_addr;
944 }
945
946 for (mapp = *rootp;
947 mapp != NULL && mapp->addr > new_addr;
948 mapp = mapp->prev)
949 higher_prevp = &mapp->prev;
950
951 /* Allocate the new page, on the next higher page from the last one
952 allocated, and link in the new descriptor before previous ones. */
953 mapp = malloc (sizeof (*mapp));
954
955 if (mapp == NULL)
956 return (USI) -ENOMEM;
957
958 sim_core_attach (sd, NULL, 0, access_read_write_exec, 0,
959 new_addr, len,
960 0, NULL, NULL);
961
962 mapp->addr = new_addr;
963 mapp->prev = *higher_prevp;
964 *higher_prevp = mapp;
965
966 return new_addr;
967}
968
969/* Unmap one or more pages. */
970
971static USI
972unmap_pages (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
973 USI len)
974{
975 struct cris_sim_mmapped_page *mapp;
976 struct cris_sim_mmapped_page **higher_prevp = rootp;
977
978 if (len != 8192)
979 {
980 USI page_addr;
981
982 if (len & 8191)
983 /* Which is better: return an error for this, or just round it up? */
984 abort ();
985
986 /* Loop backwards to make each call is O(1) over the number of pages
987 allocated, if we're unmapping from the high end of the pages. */
988 for (page_addr = addr + len - 8192;
989 page_addr >= addr;
990 page_addr -= 8192)
991 if (unmap_pages (sd, rootp, page_addr, 8192) != 0)
992 abort ();
993
994 return 0;
995 }
996
997 for (mapp = *rootp; mapp != NULL && mapp->addr > addr; mapp = mapp->prev)
998 higher_prevp = &mapp->prev;
999
1000 if (mapp == NULL || mapp->addr != addr)
1001 return EINVAL;
1002
1003 *higher_prevp = mapp->prev;
1004 sim_core_detach (sd, NULL, 0, 0, addr);
1005 free (mapp);
1006 return 0;
1007}
1008
1009/* The semantic code invokes this for illegal (unrecognized) instructions. */
1010
1011SEM_PC
1012sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc)
1013{
1014 SIM_DESC sd = CPU_STATE (current_cpu);
1015
1016 sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL);
1017 return vpc;
1018}
1019
1020/* Handlers from the CGEN description that should not be called. */
1021
1022USI
1023cris_bmod_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
1024 UINT srcreg ATTRIBUTE_UNUSED,
1025 USI dstreg ATTRIBUTE_UNUSED)
1026{
1027 abort ();
1028}
1029
1030void
1031h_supr_set_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
1032 UINT index ATTRIBUTE_UNUSED,
1033 USI page ATTRIBUTE_UNUSED,
1034 USI newval ATTRIBUTE_UNUSED)
1035{
1036 abort ();
1037}
1038
1039USI
1040h_supr_get_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
1041 UINT index ATTRIBUTE_UNUSED,
1042 USI page ATTRIBUTE_UNUSED)
1043{
1044 abort ();
1045}
1046
1047/* Swap one context for another. */
1048
1049static void
1050schedule (SIM_CPU *current_cpu, int next)
1051{
1052 /* Need to mark context-switches in the trace output. */
1053 if ((CPU_CRIS_MISC_PROFILE (current_cpu)->flags
1054 & FLAG_CRIS_MISC_PROFILE_XSIM_TRACE))
1055 cris_trace_printf (CPU_STATE (current_cpu), current_cpu,
1056 "\t#:%d\n", next);
1057
1058 /* Copy the current context (if there is one) to its slot. */
1059 if (current_cpu->thread_data[current_cpu->threadno].cpu_context)
1060 memcpy (current_cpu->thread_data[current_cpu->threadno].cpu_context,
1061 &current_cpu->cpu_data_placeholder,
1062 current_cpu->thread_cpu_data_size);
1063
1064 /* Copy the new context from its slot. */
1065 memcpy (&current_cpu->cpu_data_placeholder,
1066 current_cpu->thread_data[next].cpu_context,
1067 current_cpu->thread_cpu_data_size);
1068
1069 /* Update needed stuff to indicate the new context. */
1070 current_cpu->threadno = next;
1071
1072 /* Handle pending signals. */
1073 if (current_cpu->thread_data[next].sigpending
1074 /* We don't run nested signal handlers. This means that pause(2)
1075 and sigsuspend(2) do not work in sighandlers, but that
1076 shouldn't be too hard a restriction. It also greatly
1077 simplifies the code. */
1078 && current_cpu->thread_data[next].cpu_context_atsignal == NULL)
1079 {
1080 int sig;
1081
1082 /* See if there's really a pending, non-blocked handler. We don't
1083 queue signals, so just use the first one in ascending order. */
1084 for (sig = 0; sig < 64; sig++)
1085 if (current_cpu->thread_data[next].sigdata[sig].pending
1086 && !current_cpu->thread_data[next].sigdata[sig].blocked)
1087 {
1088 bfd_byte regbuf[4];
1089 USI sp;
1090 int i;
1091 USI blocked;
1092 USI pc = sim_pc_get (current_cpu);
1093
1094 /* It's simpler to save the CPU context inside the simulator
1095 than on the stack. */
1096 current_cpu->thread_data[next].cpu_context_atsignal
1097 = (*current_cpu
1098 ->make_thread_cpu_data) (current_cpu,
1099 current_cpu->thread_data[next]
1100 .cpu_context);
1101
1102 (*CPU_REG_FETCH (current_cpu)) (current_cpu, H_GR_SP, regbuf, 4);
1103 sp = bfd_getl32 (regbuf);
1104
1105 /* Make sure we have an aligned stack. */
1106 sp &= ~3;
1107
1108 /* Make room for the signal frame, aligned. FIXME: Check that
1109 the memory exists, map it in if absent. (BTW, should also
1110 implement on-access automatic stack allocation). */
1111 sp -= 20;
1112
1113 /* This isn't the same signal frame as the kernel uses, because
1114 we don't want to bother getting all registers on and off the
1115 stack. */
1116
1117 /* First, we store the currently blocked signals. */
1118 blocked = 0;
1119 for (i = 0; i < 32; i++)
1120 blocked
1121 |= current_cpu->thread_data[next].sigdata[i + 1].blocked << i;
1122 sim_core_write_aligned_4 (current_cpu, pc, 0, sp, blocked);
1123 blocked = 0;
1124 for (i = 0; i < 31; i++)
1125 blocked
1126 |= current_cpu->thread_data[next].sigdata[i + 33].blocked << i;
1127 sim_core_write_aligned_4 (current_cpu, pc, 0, sp + 4, blocked);
1128
1129 /* Then, the actual instructions. This is CPU-specific, but we
1130 use instructions from the common subset for v10 and v32 which
1131 should be safe for the time being but could be parametrized
1132 if need be. */
1133 /* MOVU.W [PC+],R9. */
1134 sim_core_write_aligned_2 (current_cpu, pc, 0, sp + 8, 0x9c5f);
1135 /* .WORD TARGET_SYS_sigreturn. */
1136 sim_core_write_aligned_2 (current_cpu, pc, 0, sp + 10,
1137 TARGET_SYS_sigreturn);
1138 /* BREAK 13. */
1139 sim_core_write_aligned_2 (current_cpu, pc, 0, sp + 12, 0xe93d);
1140
1141 /* NOP (on v32; it's SETF on v10, but is the correct compatible
1142 instruction. Still, it doesn't matter because v10 has no
1143 delay slot for BREAK so it will not be executed). */
1144 sim_core_write_aligned_2 (current_cpu, pc, 0, sp + 16, 0x05b0);
1145
1146 /* Modify registers to hold the right values for the sighandler
1147 context: updated stackpointer and return address pointing to
1148 the sigreturn stub. */
1149 bfd_putl32 (sp, regbuf);
1150 (*CPU_REG_STORE (current_cpu)) (current_cpu, H_GR_SP, regbuf, 4);
1151 bfd_putl32 (sp + 8, regbuf);
1152 (*CPU_REG_STORE (current_cpu)) (current_cpu, TARGET_SRP_REGNUM,
1153 regbuf, 4);
1154
1155 current_cpu->thread_data[next].sigdata[sig].pending = 0;
1156
1157 /* Block this signal (for the duration of the sighandler). */
1158 current_cpu->thread_data[next].sigdata[sig].blocked = 1;
1159
1160 sim_pc_set (current_cpu, current_cpu->sighandler[sig]);
1161 bfd_putl32 (sig, regbuf);
1162 (*CPU_REG_STORE (current_cpu)) (current_cpu, H_GR_R10,
1163 regbuf, 4);
1164
1165 /* We ignore a SA_SIGINFO flag in the sigaction call; the code I
1166 needed all this for, specifies a SA_SIGINFO call but treats it
1167 like an ordinary sighandler; only the signal number argument is
1168 inspected. To make future need to implement SA_SIGINFO
1169 correctly possible, we set the siginfo argument register to a
1170 magic (hopefully non-address) number. (NB: then, you should
1171 just need to pass the siginfo argument; it seems you probably
1172 don't need to implement the specific rt_sigreturn.) */
1173 bfd_putl32 (0xbad5161f, regbuf);
1174 (*CPU_REG_STORE (current_cpu)) (current_cpu, H_GR_R11,
1175 regbuf, 4);
1176
1177 /* The third argument is unused and the kernel sets it to 0. */
1178 bfd_putl32 (0, regbuf);
1179 (*CPU_REG_STORE (current_cpu)) (current_cpu, H_GR_R12,
1180 regbuf, 4);
1181 return;
1182 }
1183
1184 /* No, there actually was no pending signal for this thread. Reset
1185 this flag. */
1186 current_cpu->thread_data[next].sigpending = 0;
1187 }
1188}
1189
1190/* Reschedule the simplest possible way until something else is absolutely
1191 necessary:
1192 - A. Find the next process (round-robin) that doesn't have at_syscall
1193 set, schedule it.
1194 - B. If there is none, just run the next process, round-robin.
1195 - Clear at_syscall for the current process. */
1196
1197static void
1198reschedule (SIM_CPU *current_cpu)
1199{
1200 int i;
1201
1202 /* Iterate over all thread slots, because after a few thread creations
1203 and exits, we don't know where the live ones are. */
1204 for (i = (current_cpu->threadno + 1) % SIM_TARGET_MAX_THREADS;
1205 i != current_cpu->threadno;
1206 i = (i + 1) % SIM_TARGET_MAX_THREADS)
1207 if (current_cpu->thread_data[i].cpu_context
1208 && current_cpu->thread_data[i].at_syscall == 0)
1209 {
1210 schedule (current_cpu, i);
1211 return;
1212 }
1213
1214 /* Pick any next live thread. */
1215 for (i = (current_cpu->threadno + 1) % SIM_TARGET_MAX_THREADS;
1216 i != current_cpu->threadno;
1217 i = (i + 1) % SIM_TARGET_MAX_THREADS)
1218 if (current_cpu->thread_data[i].cpu_context)
1219 {
1220 schedule (current_cpu, i);
1221 return;
1222 }
1223
1224 /* More than one live thread, but we couldn't find the next one? */
1225 abort ();
1226}
1227
1228/* Set up everything to receive (or IGN) an incoming signal to the
1229 current context. */
1230
1231static int
1232deliver_signal (SIM_CPU *current_cpu, int sig, unsigned int pid)
1233{
1234 int i;
1235 USI pc = sim_pc_get (current_cpu);
1236
1237 /* Find the thread index of the pid. */
1238 for (i = 0; i < SIM_TARGET_MAX_THREADS; i++)
1239 /* Apparently it's ok to send signals to zombies (so a check for
1240 current_cpu->thread_data[i].cpu_context != NULL would be
1241 wrong). */
1242 if (current_cpu->thread_data[i].threadid == pid - TARGET_PID)
1243 {
1244 if (sig < 64)
1245 switch (current_cpu->sighandler[sig])
1246 {
1247 case TARGET_SIG_DFL:
1248 switch (sig)
1249 {
1250 /* The following according to the glibc
1251 documentation. (The kernel code has non-obvious
1252 execution paths.) */
1253 case TARGET_SIGFPE:
1254 case TARGET_SIGILL:
1255 case TARGET_SIGSEGV:
1256 case TARGET_SIGBUS:
1257 case TARGET_SIGABRT:
1258 case TARGET_SIGTRAP:
1259 case TARGET_SIGSYS:
1260
1261 case TARGET_SIGTERM:
1262 case TARGET_SIGINT:
1263 case TARGET_SIGQUIT:
1264 case TARGET_SIGKILL:
1265 case TARGET_SIGHUP:
1266
1267 case TARGET_SIGALRM:
1268 case TARGET_SIGVTALRM:
1269 case TARGET_SIGPROF:
1270 case TARGET_SIGSTOP:
1271
1272 case TARGET_SIGPIPE:
1273 case TARGET_SIGLOST:
1274 case TARGET_SIGXCPU:
1275 case TARGET_SIGXFSZ:
1276 case TARGET_SIGUSR1:
1277 case TARGET_SIGUSR2:
1278 sim_io_eprintf (CPU_STATE (current_cpu),
1279 "Exiting pid %d due to signal %d\n",
1280 pid, sig);
1281 sim_engine_halt (CPU_STATE (current_cpu), current_cpu,
1282 NULL, pc, sim_stopped,
1283 sig == TARGET_SIGABRT
1284 ? SIM_SIGABRT : SIM_SIGILL);
1285 return 0;
1286
1287 /* The default for all other signals is to be ignored. */
1288 default:
1289 return 0;
1290 }
1291
1292 case TARGET_SIG_IGN:
1293 switch (sig)
1294 {
1295 case TARGET_SIGKILL:
1296 case TARGET_SIGSTOP:
1297 /* Can't ignore these signals. */
1298 sim_io_eprintf (CPU_STATE (current_cpu),
1299 "Exiting pid %d due to signal %d\n",
1300 pid, sig);
1301 sim_engine_halt (CPU_STATE (current_cpu), current_cpu,
1302 NULL, pc, sim_stopped, SIM_SIGILL);
1303 return 0;
1304
1305 default:
1306 return 0;
1307 }
1308 break;
1309
1310 default:
1311 /* Mark the signal as pending, making schedule () check
1312 closer. The signal will be handled when the thread is
1313 scheduled and the signal is unblocked. */
1314 current_cpu->thread_data[i].sigdata[sig].pending = 1;
1315 current_cpu->thread_data[i].sigpending = 1;
1316 return 0;
1317 }
1318 else
1319 {
1320 sim_io_eprintf (CPU_STATE (current_cpu),
1321 "Unimplemented signal: %d\n", sig);
1322 sim_engine_halt (CPU_STATE (current_cpu), current_cpu, NULL, pc,
1323 sim_stopped, SIM_SIGILL);
1324 }
1325 }
1326
1327 return
1328 -cb_host_to_target_errno (STATE_CALLBACK (CPU_STATE (current_cpu)),
1329 ESRCH);
1330}
1331
1332/* Make the vector and the first item, the main thread. */
1333
1334static void
1335make_first_thread (SIM_CPU *current_cpu)
1336{
1337 current_cpu->thread_data
1338 = xcalloc (1,
1339 SIM_TARGET_MAX_THREADS
1340 * sizeof (current_cpu->thread_data[0]));
1341 current_cpu->thread_data[0].cpu_context
1342 = (*current_cpu->make_thread_cpu_data) (current_cpu,
1343 &current_cpu
1344 ->cpu_data_placeholder);
1345 current_cpu->thread_data[0].parent_threadid = -1;
1346
1347 /* For good measure. */
1348 if (TARGET_SIG_DFL != 0)
1349 abort ();
1350}
1351
1352/* Main function: the handler of the "break 13" syscall insn. */
1353
1354USI
1355cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
1356 USI arg2, USI arg3, USI arg4, USI arg5, USI arg6,
1357 USI pc)
1358{
1359 CB_SYSCALL s;
1360 SIM_DESC sd = CPU_STATE (current_cpu);
1361 host_callback *cb = STATE_CALLBACK (sd);
1362 int retval;
1363 int threadno = current_cpu->threadno;
1364
1365 current_cpu->syscalls++;
1366
1367 CB_SYSCALL_INIT (&s);
1368 s.func = callnum;
1369 s.arg1 = arg1;
1370 s.arg2 = arg2;
1371 s.arg3 = arg3;
1372
1373 if (callnum == TARGET_SYS_exit && current_cpu->m1threads == 0)
1374 {
1375 if (CPU_CRIS_MISC_PROFILE (current_cpu)->flags
1376 & FLAG_CRIS_MISC_PROFILE_ALL)
1377 dump_statistics (current_cpu);
1378 sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, arg1);
1379 }
1380
1381 s.p1 = (PTR) sd;
1382 s.p2 = (PTR) current_cpu;
1383 s.read_mem = syscall_read_mem;
1384 s.write_mem = syscall_write_mem;
1385
1386 current_cpu_for_cb_callback = current_cpu;
1387
1388 if (cb_syscall (cb, &s) != CB_RC_OK)
1389 {
1390 abort ();
1391 sim_io_eprintf (sd, "Break 13: invalid %d? Returned %ld\n", callnum,
1392 s.result);
1393 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGILL);
1394 }
1395
1396 retval = s.result == -1 ? -s.errcode : s.result;
1397
1398 if (s.errcode != 0 && s.errcode == cb_host_to_target_errno (cb, ENOSYS))
1399 {
1400 /* If the generic simulator call said ENOSYS, then let's try the
1401 ones we know ourselves.
1402
1403 The convention is to provide *very limited* functionality on an
1404 as-needed basis, only what's covered by the test-suite, tests
1405 added when functionality changes and abort with a descriptive
1406 message for *everything* else. Where there's no test-case, we
1407 just abort. */
1408 switch (callnum)
1409 {
1410 case 0:
1411 /* It's a pretty safe bet that the "old setup() system call"
1412 number will not be re-used; we can't say the same for higher
1413 numbers. We treat this simulator-generated call as "wait
1414 forever"; we re-run this insn. The wait is ended by a
1415 callback. Sanity check that this is the reason we got
1416 here. */
1417 if (current_cpu->thread_data == NULL
1418 || (current_cpu->thread_data[threadno].pipe_write_fd == 0))
1419 goto unimplemented_syscall;
1420
1421 sim_pc_set (current_cpu, pc);
1422 retval = arg1;
1423 break;
1424
1425 case TARGET_SYS_fcntl64:
1426 case TARGET_SYS_fcntl:
ed1f044a 1427 switch (arg2)
f6bcefef 1428 {
ed1f044a 1429 case 1:
f6bcefef
HPN
1430 /* F_GETFD.
1431 Glibc checks stdin, stdout and stderr fd:s for
1432 close-on-exec security sanity. We just need to provide a
1433 OK return value. If we really need to have a
1434 close-on-exec flag true, we could just do a real fcntl
1435 here. */
1436 retval = 0;
ed1f044a
HPN
1437 break;
1438
1439 case 2:
f6bcefef
HPN
1440 /* F_SETFD. Just ignore attempts to set the close-on-exec
1441 flag. */
1442 retval = 0;
ed1f044a
HPN
1443 break;
1444
1445 case 3:
1446 /* F_GETFL. Check for the special case for open+fdopen. */
1447 if (current_cpu->last_syscall == TARGET_SYS_open
1448 && arg1 == current_cpu->last_open_fd)
1449 {
1450 retval = current_cpu->last_open_flags & TARGET_O_ACCMODE;
1451 break;
1452 }
8b9b39f4
HPN
1453 else if (arg1 == 0)
1454 {
1455 /* Because we can't freopen fd:s 0, 1, 2 to mean
1456 something else than stdin, stdout and stderr
1457 (sim/common/syscall.c:cb_syscall special cases fd
1458 0, 1 and 2), we know what flags that we can
1459 sanely return for these fd:s. */
1460 retval = TARGET_O_RDONLY;
1461 break;
1462 }
1463 else if (arg1 == 1 || arg1 == 2)
1464 {
1465 retval = TARGET_O_WRONLY;
1466 break;
1467 }
ed1f044a 1468 /* FALLTHROUGH */
ed1f044a 1469 default:
8b9b39f4 1470 /* Abort for all other cases. */
ed1f044a
HPN
1471 sim_io_eprintf (sd, "Unimplemented %s syscall "
1472 "(fd: 0x%lx: cmd: 0x%lx arg: 0x%lx)\n",
1473 callnum == TARGET_SYS_fcntl
1474 ? "fcntl" : "fcntl64",
1475 (unsigned long) (USI) arg1,
1476 (unsigned long) (USI) arg2,
1477 (unsigned long) (USI) arg3);
1478 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
1479 SIM_SIGILL);
1480 break;
f6bcefef
HPN
1481 }
1482 break;
1483
1484 case TARGET_SYS_uname:
1485 {
1486 /* Fill in a few constants to appease glibc. */
1487 static const char sim_utsname[6][65] =
1488 {
1489 "Linux",
1490 "sim-target",
1491 "2.4.5",
1492 TARGET_UTSNAME,
1493 "cris",
1494 "localdomain"
1495 };
1496
1497 if ((s.write_mem) (cb, &s, arg1, (const char *) sim_utsname,
1498 sizeof (sim_utsname))
1499 != sizeof (sim_utsname))
1500 retval = -cb_host_to_target_errno (cb, EFAULT);
1501 else
1502 retval = 0;
1503 break;
1504 }
1505
1506 case TARGET_SYS_geteuid32:
1507 /* We tell the truth with these. Maybe we shouldn't, but it
1508 should match the "stat" information. */
1509 retval = geteuid ();
1510 break;
1511
1512 case TARGET_SYS_getuid32:
1513 retval = getuid ();
1514 break;
1515
1516 case TARGET_SYS_getegid32:
1517 retval = getegid ();
1518 break;
1519
1520 case TARGET_SYS_getgid32:
1521 retval = getgid ();
1522 break;
1523
1524 case TARGET_SYS_brk:
1525 /* Most often, we just return the argument, like the Linux
1526 kernel. */
1527 retval = arg1;
1528
1529 if (arg1 == 0)
1530 retval = current_cpu->endbrk;
1531 else if (arg1 <= current_cpu->endmem)
1532 current_cpu->endbrk = arg1;
1533 else
1534 {
1535 USI new_end = (arg1 + 8191) & ~8191;
1536
1537 /* If the simulator wants to brk more than a certain very
1538 large amount, something is wrong. FIXME: Return an error
1539 or abort? Have command-line selectable? */
1540 if (new_end - current_cpu->endmem > SIM_MAX_ALLOC_CHUNK)
1541 {
1542 current_cpu->endbrk = current_cpu->endmem;
1543 retval = current_cpu->endmem;
1544 break;
1545 }
1546
1547 sim_core_attach (sd, NULL, 0, access_read_write_exec, 0,
1548 current_cpu->endmem,
1549 new_end - current_cpu->endmem,
1550 0, NULL, NULL);
1551 current_cpu->endbrk = arg1;
1552 current_cpu->endmem = new_end;
1553 }
1554 break;
1555
1556 case TARGET_SYS_getpid:
1557 /* Correct until CLONE_THREAD is implemented. */
1558 retval = current_cpu->thread_data == NULL
1559 ? TARGET_PID
1560 : TARGET_PID + current_cpu->thread_data[threadno].threadid;
1561 break;
1562
1563 case TARGET_SYS_getppid:
1564 /* Correct until CLONE_THREAD is implemented. */
1565 retval = current_cpu->thread_data == NULL
1566 ? TARGET_PID - 1
1567 : (TARGET_PID
1568 + current_cpu->thread_data[threadno].parent_threadid);
1569 break;
1570
1571 case TARGET_SYS_mmap2:
1572 {
1573 USI addr = arg1;
1574 USI len = arg2;
1575 USI prot = arg3;
1576 USI flags = arg4;
1577 USI fd = arg5;
1578 USI pgoff = arg6;
1579
1580 /* If the simulator wants to mmap more than the very large
1581 limit, something is wrong. FIXME: Return an error or
1582 abort? Have command-line selectable? */
1583 if (len > SIM_MAX_ALLOC_CHUNK)
1584 {
1585 retval = -cb_host_to_target_errno (cb, ENOMEM);
1586 break;
1587 }
1588
1589 if ((prot != (TARGET_PROT_READ | TARGET_PROT_WRITE)
1590 && (prot
1591 != (TARGET_PROT_READ
1592 | TARGET_PROT_WRITE
1593 | TARGET_PROT_EXEC))
1594 && prot != TARGET_PROT_READ)
1595 || (flags != (TARGET_MAP_ANONYMOUS | TARGET_MAP_PRIVATE)
1596 && flags != TARGET_MAP_PRIVATE
1597 && flags != TARGET_MAP_SHARED)
1598 || (fd != (USI) -1 && prot != TARGET_PROT_READ)
69308976 1599 || pgoff != 0)
f6bcefef
HPN
1600 {
1601 sim_io_eprintf (sd, "Unimplemented mmap2 call "
1602 "(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
1603 (unsigned long) arg1,
1604 (unsigned long) arg2,
1605 (unsigned long) arg3,
1606 (unsigned long) arg4,
1607 (unsigned long) arg5,
1608 (unsigned long) arg6);
1609 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
1610 SIM_SIGILL);
1611 break;
1612 }
1613 else if (fd != (USI) -1)
1614 {
1615 /* Map a file. */
1616
1617 USI newaddr;
1618 USI pos;
1619
1620 /* A non-aligned argument is allowed for files. */
1621 USI newlen = (len + 8191) & ~8191;
1622
1623 /* We only support read, which we should already have
1624 checked. Check again anyway. */
1625 if (prot != TARGET_PROT_READ)
1626 abort ();
1627
1628 newaddr
1629 = create_map (sd, &current_cpu->highest_mmapped_page, addr,
1630 newlen);
1631
1632 if (newaddr >= (USI) -8191)
1633 {
1634 abort ();
1635 retval = -cb_host_to_target_errno (cb, -(SI) newaddr);
1636 break;
1637 }
1638
1639 /* Find the current position in the file. */
1640 s.func = TARGET_SYS_lseek;
1641 s.arg1 = fd;
1642 s.arg2 = 0;
1643 s.arg3 = SEEK_CUR;
1644 if (cb_syscall (cb, &s) != CB_RC_OK)
1645 abort ();
1646 pos = s.result;
1647
1648 if (s.result < 0)
1649 abort ();
1650
1651 /* Use the standard read callback to read in "len"
1652 bytes. */
1653 s.func = TARGET_SYS_read;
1654 s.arg1 = fd;
1655 s.arg2 = newaddr;
1656 s.arg3 = len;
1657 if (cb_syscall (cb, &s) != CB_RC_OK)
1658 abort ();
1659
1660 if ((USI) s.result != len)
1661 abort ();
1662
1663 /* After reading, we need to go back to the previous
1664 position in the file. */
1665 s.func = TARGET_SYS_lseek;
1666 s.arg1 = fd;
1667 s.arg2 = pos;
1668 s.arg3 = SEEK_SET;
1669 if (cb_syscall (cb, &s) != CB_RC_OK)
1670 abort ();
1671 if (pos != (USI) s.result)
1672 abort ();
1673
1674 retval = newaddr;
1675 }
1676 else
1677 {
1678 USI newaddr
69308976
HPN
1679 = create_map (sd, &current_cpu->highest_mmapped_page, addr,
1680 (len + 8191) & ~8191);
f6bcefef
HPN
1681
1682 if (newaddr >= (USI) -8191)
1683 retval = -cb_host_to_target_errno (cb, -(SI) newaddr);
1684 else
1685 retval = newaddr;
1686 }
1687 break;
1688 }
1689
1690 case TARGET_SYS_mprotect:
1691 {
1692 /* We only cover the case of linuxthreads mprotecting out its
1693 stack guard page. */
1694 USI addr = arg1;
1695 USI len = arg2;
1696 USI prot = arg3;
1697
1698 if ((addr & 8191) != 0
1699 || len != 8192
1700 || prot != TARGET_PROT_NONE
1701 || !is_mapped (sd, &current_cpu->highest_mmapped_page, addr,
1702 len))
1703 {
1704 sim_io_eprintf (sd, "Unimplemented mprotect call "
1705 "(0x%lx, 0x%lx, 0x%lx)\n",
1706 (unsigned long) arg1,
1707 (unsigned long) arg2,
1708 (unsigned long) arg3);
1709 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
1710 SIM_SIGILL);
1711 break;
1712 }
1713
1714 /* FIXME: We should account for pages like this that are
1715 "mprotected out". For now, we just tell the simulator
1716 core to remove that page from its map. */
1717 sim_core_detach (sd, NULL, 0, 0, addr);
1718 retval = 0;
1719 break;
1720 }
1721
1722 case TARGET_SYS_ioctl:
1723 {
1724 /* We support only a very limited functionality: checking
1725 stdout with TCGETS to perform the isatty function. The
1726 TCGETS ioctl isn't actually performed or the result used by
1727 an isatty () caller in a "hello, world" program; only the
1728 return value is then used. Maybe we shouldn't care about
1729 the environment of the simulator regarding isatty, but
1730 that's been working before, in the xsim simulator. */
1731 if (arg2 == TARGET_TCGETS && arg1 == 1)
1732 retval = isatty (1) ? 0 : cb_host_to_target_errno (cb, EINVAL);
1733 else
1734 retval = -cb_host_to_target_errno (cb, EINVAL);
1735 break;
1736 }
1737
1738 case TARGET_SYS_munmap:
1739 {
1740 USI addr = arg1;
1741 USI len = arg2;
1742 USI result
1743 = unmap_pages (sd, &current_cpu->highest_mmapped_page, addr,
1744 len);
1745 retval = result != 0 ? -cb_host_to_target_errno (cb, result) : 0;
1746 break;
1747 }
1748
1749 case TARGET_SYS_wait4:
1750 {
1751 int i;
1752 USI pid = arg1;
1753 USI saddr = arg2;
1754 USI options = arg3;
1755 USI rusagep = arg4;
1756
1757 /* FIXME: We're not properly implementing __WCLONE, and we
1758 don't really need the special casing so we might as well
1759 make this general. */
1760 if ((!(pid == (USI) -1
1761 && options == (TARGET___WCLONE | TARGET_WNOHANG)
1762 && saddr != 0)
1763 && !(pid > 0
1764 && (options == TARGET___WCLONE
1765 || options == TARGET___WALL)))
1766 || rusagep != 0
1767 || current_cpu->thread_data == NULL)
1768 {
1769 sim_io_eprintf (sd, "Unimplemented wait4 call "
1770 "(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
1771 (unsigned long) arg1,
1772 (unsigned long) arg2,
1773 (unsigned long) arg3,
1774 (unsigned long) arg4);
1775 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
1776 SIM_SIGILL);
1777 break;
1778 }
1779
1780 if (pid == (USI) -1)
1781 for (i = 1; i < SIM_TARGET_MAX_THREADS; i++)
1782 {
1783 if (current_cpu->thread_data[threadno].threadid
1784 == current_cpu->thread_data[i].parent_threadid
1785 && current_cpu->thread_data[i].threadid != 0
1786 && current_cpu->thread_data[i].cpu_context == NULL)
1787 {
1788 /* A zombied child. Get the exit value and clear the
1789 zombied entry so it will be reused. */
1790 sim_core_write_unaligned_4 (current_cpu, pc, 0, saddr,
1791 current_cpu
1792 ->thread_data[i].exitval);
1793 retval
1794 = current_cpu->thread_data[i].threadid + TARGET_PID;
1795 memset (&current_cpu->thread_data[i], 0,
1796 sizeof (current_cpu->thread_data[i]));
1797 goto outer_break;
1798 }
1799 }
1800 else
1801 {
1802 /* We're waiting for a specific PID. If we don't find
1803 it zombied on this run, rerun the syscall. */
1804 for (i = 1; i < SIM_TARGET_MAX_THREADS; i++)
1805 if (pid == current_cpu->thread_data[i].threadid + TARGET_PID
1806 && current_cpu->thread_data[i].cpu_context == NULL)
1807 {
1808 if (saddr != 0)
1809 /* Get the exit value if the caller wants it. */
1810 sim_core_write_unaligned_4 (current_cpu, pc, 0,
1811 saddr,
1812 current_cpu
1813 ->thread_data[i]
1814 .exitval);
1815
1816 retval
1817 = current_cpu->thread_data[i].threadid + TARGET_PID;
1818 memset (&current_cpu->thread_data[i], 0,
1819 sizeof (current_cpu->thread_data[i]));
1820
1821 goto outer_break;
1822 }
1823
1824 sim_pc_set (current_cpu, pc);
1825 }
1826
1827 retval = -cb_host_to_target_errno (cb, ECHILD);
1828 outer_break:
1829 break;
1830 }
1831
1832 case TARGET_SYS_rt_sigaction:
1833 {
1834 USI signum = arg1;
1835 USI old_sa = arg3;
1836 USI new_sa = arg2;
1837
1838 /* The kernel says:
1839 struct sigaction {
1840 __sighandler_t sa_handler;
1841 unsigned long sa_flags;
1842 void (*sa_restorer)(void);
1843 sigset_t sa_mask;
1844 }; */
1845
1846 if (old_sa != 0)
1847 {
1848 sim_core_write_unaligned_4 (current_cpu, pc, 0, old_sa + 0,
1849 current_cpu->sighandler[signum]);
1850 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg3 + 4, 0);
1851 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg3 + 8, 0);
1852
1853 /* We'll assume _NSIG_WORDS is 2 for the kernel. */
1854 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg3 + 12, 0);
1855 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg3 + 16, 0);
1856 }
1857 if (new_sa != 0)
1858 {
2ecb8390 1859 USI target_sa_handler
f6bcefef 1860 = sim_core_read_unaligned_4 (current_cpu, pc, 0, new_sa);
2ecb8390 1861 USI target_sa_flags
f6bcefef 1862 = sim_core_read_unaligned_4 (current_cpu, pc, 0, new_sa + 4);
2ecb8390 1863 USI target_sa_restorer
f6bcefef 1864 = sim_core_read_unaligned_4 (current_cpu, pc, 0, new_sa + 8);
2ecb8390 1865 USI target_sa_mask_low
f6bcefef 1866 = sim_core_read_unaligned_4 (current_cpu, pc, 0, new_sa + 12);
2ecb8390 1867 USI target_sa_mask_high
f6bcefef
HPN
1868 = sim_core_read_unaligned_4 (current_cpu, pc, 0, new_sa + 16);
1869
1870 /* We won't interrupt a syscall so we won't restart it,
1871 but a signal(2) call ends up syscalling rt_sigaction
1872 with this flag, so we have to handle it. The
1873 sa_restorer field contains garbage when not
1874 TARGET_SA_RESTORER, so don't look at it. For the
1875 time being, we don't nest sighandlers, so we
1876 ignore the sa_mask, which simplifies things. */
2ecb8390
HPN
1877 if ((target_sa_flags != 0
1878 && target_sa_flags != TARGET_SA_RESTART
1879 && target_sa_flags != (TARGET_SA_RESTART|TARGET_SA_SIGINFO))
1880 || target_sa_handler == 0)
f6bcefef
HPN
1881 {
1882 sim_io_eprintf (sd, "Unimplemented rt_sigaction "
1883 "syscall (0x%lx, "
1884 "0x%lx: [0x%x, 0x%x, 0x%x, "
1885 "{0x%x, 0x%x}], "
1886 "0x%lx)\n",
1887 (unsigned long) arg1,
1888 (unsigned long) arg2,
2ecb8390
HPN
1889 target_sa_handler, target_sa_flags,
1890 target_sa_restorer,
1891 target_sa_mask_low, target_sa_mask_high,
f6bcefef
HPN
1892 (unsigned long) arg3);
1893 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
1894 SIM_SIGILL);
1895 }
1896
2ecb8390 1897 current_cpu->sighandler[signum] = target_sa_handler;
f6bcefef
HPN
1898
1899 /* Because we may have unblocked signals, one may now be
1900 pending, if there are threads, that is. */
1901 if (current_cpu->thread_data)
1902 current_cpu->thread_data[threadno].sigpending = 1;
1903 }
1904 retval = 0;
1905 break;
1906 }
1907
1908 case TARGET_SYS_mremap:
1909 {
1910 USI addr = arg1;
1911 USI old_len = arg2;
1912 USI new_len = arg3;
1913 USI flags = arg4;
1914 USI new_addr = arg5;
1915 USI mapped_addr;
1916
1917 if (new_len == old_len)
1918 /* The program and/or library is possibly confused but
1919 this is a valid call. Happens with ipps-1.40 on file
1920 svs_all. */
1921 retval = addr;
1922 else if (new_len < old_len)
1923 {
1924 /* Shrinking is easy. */
1925 if (unmap_pages (sd, &current_cpu->highest_mmapped_page,
1926 addr + new_len, old_len - new_len) != 0)
1927 retval = -cb_host_to_target_errno (cb, EINVAL);
1928 else
1929 retval = addr;
1930 }
1931 else if (! is_mapped (sd, &current_cpu->highest_mmapped_page,
1932 addr + old_len, new_len - old_len))
1933 {
1934 /* If the extension isn't mapped, we can just add it. */
1935 mapped_addr
1936 = create_map (sd, &current_cpu->highest_mmapped_page,
1937 addr + old_len, new_len - old_len);
1938
1939 if (mapped_addr > (USI) -8192)
1940 retval = -cb_host_to_target_errno (cb, -(SI) mapped_addr);
1941 else
1942 retval = addr;
1943 }
1944 else if (flags & TARGET_MREMAP_MAYMOVE)
1945 {
1946 /* Create a whole new map and copy the contents
1947 block-by-block there. We ignore the new_addr argument
1948 for now. */
1949 char buf[8192];
1950 USI prev_addr = addr;
1951 USI prev_len = old_len;
1952
1953 mapped_addr
1954 = create_map (sd, &current_cpu->highest_mmapped_page,
1955 0, new_len);
1956
1957 if (mapped_addr > (USI) -8192)
1958 {
1959 retval = -cb_host_to_target_errno (cb, -(SI) new_addr);
1960 break;
1961 }
1962
1963 retval = mapped_addr;
1964
1965 for (; old_len > 0;
1966 old_len -= 8192, mapped_addr += 8192, addr += 8192)
1967 {
1968 if (sim_core_read_buffer (sd, current_cpu, read_map, buf,
1969 addr, 8192) != 8192
1970 || sim_core_write_buffer (sd, current_cpu, 0, buf,
1971 mapped_addr, 8192) != 8192)
1972 abort ();
1973 }
1974
1975 if (unmap_pages (sd, &current_cpu->highest_mmapped_page,
1976 prev_addr, prev_len) != 0)
1977 abort ();
1978 }
1979 else
1980 retval = -cb_host_to_target_errno (cb, -ENOMEM);
1981 break;
1982 }
1983
1984 case TARGET_SYS_poll:
1985 {
1986 int npollfds = arg2;
1987 int timeout = arg3;
1988 SI ufds = arg1;
1989 SI fd = -1;
1990 HI events = -1;
1991 HI revents = 0;
1992 struct stat buf;
1993 int i;
1994
1995 /* The kernel says:
1996 struct pollfd {
1997 int fd;
1998 short events;
1999 short revents;
2000 }; */
2001
2002 /* Check that this is the expected poll call from
2003 linuxthreads/manager.c; we don't support anything else.
2004 Remember, fd == 0 isn't supported. */
2005 if (npollfds != 1
2006 || ((fd = sim_core_read_unaligned_4 (current_cpu, pc,
2007 0, ufds)) <= 0)
2008 || ((events = sim_core_read_unaligned_2 (current_cpu, pc,
2009 0, ufds + 4))
2010 != TARGET_POLLIN)
2011 || ((cb->fstat) (cb, fd, &buf) != 0
2012 || (buf.st_mode & S_IFIFO) == 0)
2013 || current_cpu->thread_data == NULL)
2014 {
2015 sim_io_eprintf (sd, "Unimplemented poll syscall "
2016 "(0x%lx: [0x%x, 0x%x, x], 0x%lx, 0x%lx)\n",
2017 (unsigned long) arg1, fd, events,
2018 (unsigned long) arg2, (unsigned long) arg3);
2019 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGILL);
2020 break;
2021 }
2022
2023 retval = 0;
2024
2025 /* Iterate over threads; find a marker that a writer is
2026 sleeping, waiting for a reader. */
2027 for (i = 0; i < SIM_TARGET_MAX_THREADS; i++)
2028 if (current_cpu->thread_data[i].cpu_context != NULL
2029 && current_cpu->thread_data[i].pipe_read_fd == fd)
2030 {
2031 revents = TARGET_POLLIN;
2032 retval = 1;
2033 break;
2034 }
2035
2036 /* Timeout decreases with whatever time passed between the
2037 last syscall and this. That's not exactly right for the
2038 first call, but it's close enough that it isn't
2039 worthwhile to complicate matters by making that a special
2040 case. */
2041 timeout
2042 -= (TARGET_TIME_MS (current_cpu)
2043 - (current_cpu->thread_data[threadno].last_execution));
2044
2045 /* Arrange to repeat this syscall until timeout or event,
2046 decreasing timeout at each iteration. */
2047 if (timeout > 0 && revents == 0)
2048 {
2049 bfd_byte timeout_buf[4];
2050
2051 bfd_putl32 (timeout, timeout_buf);
2052 (*CPU_REG_STORE (current_cpu)) (current_cpu,
2053 H_GR_R12, timeout_buf, 4);
2054 sim_pc_set (current_cpu, pc);
2055 retval = arg1;
2056 break;
2057 }
2058
2059 sim_core_write_unaligned_2 (current_cpu, pc, 0, ufds + 4 + 2,
2060 revents);
2061 break;
2062 }
2063
d022998d
HPN
2064 case TARGET_SYS_time:
2065 {
2066 retval = (int) (*cb->time) (cb, 0L);
2067
2068 /* At time of this writing, CB_SYSCALL_time doesn't do the
2069 part of setting *arg1 to the return value. */
2070 if (arg1)
2071 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg1, retval);
2072 break;
2073 }
2074
f6bcefef
HPN
2075 case TARGET_SYS_gettimeofday:
2076 if (arg1 != 0)
2077 {
2078 USI ts = TARGET_TIME (current_cpu);
2079 USI tms = TARGET_TIME_MS (current_cpu);
2080
2081 /* First dword is seconds since TARGET_EPOCH. */
2082 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg1, ts);
2083
2084 /* Second dword is microseconds. */
2085 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg1 + 4,
2086 (tms % 1000) * 1000);
2087 }
2088 if (arg2 != 0)
2089 {
2090 /* Time-zone info is always cleared. */
2091 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg2, 0);
2092 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg2 + 4, 0);
2093 }
2094 retval = 0;
2095 break;
2096
2097 case TARGET_SYS_llseek:
2098 {
2099 /* If it fits, tweak parameters to fit the "generic" 32-bit
2100 lseek and use that. */
2101 SI fd = arg1;
2102 SI offs_hi = arg2;
2103 SI offs_lo = arg3;
2104 SI resultp = arg4;
2105 SI whence = arg5;
2106 retval = 0;
2107
2108 if (!((offs_hi == 0 && offs_lo >= 0)
2109 || (offs_hi == -1 && offs_lo < 0)))
2110 {
2111 sim_io_eprintf (sd,
2112 "Unimplemented llseek offset,"
2113 " fd %d: 0x%x:0x%x\n",
2114 fd, (unsigned) arg2, (unsigned) arg3);
2115 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2116 SIM_SIGILL);
2117 }
2118
2119 s.func = TARGET_SYS_lseek;
2120 s.arg2 = offs_lo;
2121 s.arg3 = whence;
2122 if (cb_syscall (cb, &s) != CB_RC_OK)
2123 {
2124 sim_io_eprintf (sd, "Break 13: invalid %d? Returned %ld\n", callnum,
2125 s.result);
2126 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGILL);
2127 }
2128 if (s.result < 0)
2129 retval = -s.errcode;
2130 else
2131 {
2132 sim_core_write_unaligned_4 (current_cpu, pc, 0, resultp,
2133 s.result);
2134 sim_core_write_unaligned_4 (current_cpu, pc, 0, resultp + 4,
2135 s.result < 0 ? -1 : 0);
2136 }
2137 break;
2138 }
2139
2140 /* This one does have a generic callback function, but at the time
2141 of this writing, cb_syscall does not have code for it, and we
2142 need target-specific code for the threads implementation
2143 anyway. */
2144 case TARGET_SYS_kill:
2145 {
2146 USI pid = arg1;
2147 USI sig = arg2;
2148
2149 retval = 0;
2150
2151 /* At kill(2), glibc sets signal masks such that the thread
2152 machinery is initialized. Still, there is and was only
2153 one thread. */
2154 if (current_cpu->max_threadid == 0)
2155 {
2156 if (pid != TARGET_PID)
2157 {
2158 retval = -cb_host_to_target_errno (cb, EPERM);
2159 break;
2160 }
2161
2162 /* FIXME: Signal infrastructure (target-to-sim mapping). */
2163 if (sig == TARGET_SIGABRT)
2164 /* A call "abort ()", i.e. "kill (getpid(), SIGABRT)" is
2165 the end-point for failing GCC test-cases. */
2166 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2167 SIM_SIGABRT);
2168 else
2169 {
2170 sim_io_eprintf (sd, "Unimplemented signal: %d\n", sig);
2171 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2172 SIM_SIGILL);
2173 }
2174
2175 /* This will not be reached. */
2176 abort ();
2177 }
2178 else
2179 retval = deliver_signal (current_cpu, sig, pid);
2180 break;
2181 }
2182
2183 case TARGET_SYS_rt_sigprocmask:
2184 {
2185 int i;
2186 USI how = arg1;
2187 USI newsetp = arg2;
2188 USI oldsetp = arg3;
2189
2190 if (how != TARGET_SIG_BLOCK
2191 && how != TARGET_SIG_SETMASK
2192 && how != TARGET_SIG_UNBLOCK)
2193 {
2194 sim_io_eprintf (sd, "Unimplemented rt_sigprocmask syscall "
2195 "(0x%x, 0x%x, 0x%x)\n", arg1, arg2, arg3);
2196 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2197 SIM_SIGILL);
2198 retval = 0;
2199 break;
2200 }
2201
2202 if (newsetp)
2203 {
2204 USI set_low
2205 = sim_core_read_unaligned_4 (current_cpu, pc, 0,
2206 newsetp);
2207 USI set_high
2208 = sim_core_read_unaligned_4 (current_cpu, pc, 0,
2209 newsetp + 4);
2210
2211 /* The sigmask is kept in the per-thread data, so we may
2212 need to create the first one. */
2213 if (current_cpu->thread_data == NULL)
2214 make_first_thread (current_cpu);
2215
2216 if (how == TARGET_SIG_SETMASK)
2217 for (i = 0; i < 64; i++)
2218 current_cpu->thread_data[threadno].sigdata[i].blocked = 0;
2219
2220 for (i = 0; i < 32; i++)
2221 if ((set_low & (1 << i)))
2222 current_cpu->thread_data[threadno].sigdata[i + 1].blocked
2223 = (how != TARGET_SIG_UNBLOCK);
2224
2225 for (i = 0; i < 31; i++)
2226 if ((set_high & (1 << i)))
2227 current_cpu->thread_data[threadno].sigdata[i + 33].blocked
2228 = (how != TARGET_SIG_UNBLOCK);
2229
2230 /* The mask changed, so a signal may be unblocked for
2231 execution. */
2232 current_cpu->thread_data[threadno].sigpending = 1;
2233 }
2234
2235 if (oldsetp != 0)
2236 {
2237 USI set_low = 0;
2238 USI set_high = 0;
2239
2240 for (i = 0; i < 32; i++)
2241 if (current_cpu->thread_data[threadno]
2242 .sigdata[i + 1].blocked)
2243 set_low |= 1 << i;
2244 for (i = 0; i < 31; i++)
2245 if (current_cpu->thread_data[threadno]
2246 .sigdata[i + 33].blocked)
2247 set_high |= 1 << i;
2248
2249 sim_core_write_unaligned_4 (current_cpu, pc, 0, oldsetp + 0, set_low);
2250 sim_core_write_unaligned_4 (current_cpu, pc, 0, oldsetp + 4, set_high);
2251 }
2252
2253 retval = 0;
2254 break;
2255 }
2256
2257 case TARGET_SYS_sigreturn:
2258 {
2259 int i;
2260 bfd_byte regbuf[4];
2261 int was_sigsuspended;
2262
2263 if (current_cpu->thread_data == NULL
2264 /* The CPU context is saved with the simulator data, not
2265 on the stack as in the real world. */
2266 || (current_cpu->thread_data[threadno].cpu_context_atsignal
2267 == NULL))
2268 {
2269 sim_io_eprintf (sd, "Invalid sigreturn syscall: no signal"
2270 " handler active "
2271 "(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
2272 (unsigned long) arg1,
2273 (unsigned long) arg2,
2274 (unsigned long) arg3,
2275 (unsigned long) arg4,
2276 (unsigned long) arg5,
2277 (unsigned long) arg6);
2278 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2279 SIM_SIGILL);
2280 }
2281
2282 was_sigsuspended
2283 = current_cpu->thread_data[threadno].sigsuspended;
2284
2285 /* Restore the sigmask, either from the stack copy made when
2286 the sighandler was called, or from the saved state
2287 specifically for sigsuspend(2). */
2288 if (was_sigsuspended)
2289 {
2290 current_cpu->thread_data[threadno].sigsuspended = 0;
2291 for (i = 0; i < 64; i++)
2292 current_cpu->thread_data[threadno].sigdata[i].blocked
2293 = current_cpu->thread_data[threadno]
2294 .sigdata[i].blocked_suspendsave;
2295 }
2296 else
2297 {
2298 USI sp;
2299 USI set_low;
2300 USI set_high;
2301
2302 (*CPU_REG_FETCH (current_cpu)) (current_cpu,
2303 H_GR_SP, regbuf, 4);
2304 sp = bfd_getl32 (regbuf);
2305 set_low
2306 = sim_core_read_unaligned_4 (current_cpu, pc, 0, sp);
2307 set_high
2308 = sim_core_read_unaligned_4 (current_cpu, pc, 0, sp + 4);
2309
2310 for (i = 0; i < 32; i++)
2311 current_cpu->thread_data[threadno].sigdata[i + 1].blocked
2312 = (set_low & (1 << i)) != 0;
2313 for (i = 0; i < 31; i++)
2314 current_cpu->thread_data[threadno].sigdata[i + 33].blocked
2315 = (set_high & (1 << i)) != 0;
2316 }
2317
2318 /* The mask changed, so a signal may be unblocked for
2319 execution. */
2320 current_cpu->thread_data[threadno].sigpending = 1;
2321
2322 memcpy (&current_cpu->cpu_data_placeholder,
2323 current_cpu->thread_data[threadno].cpu_context_atsignal,
2324 current_cpu->thread_cpu_data_size);
2325 free (current_cpu->thread_data[threadno].cpu_context_atsignal);
2326 current_cpu->thread_data[threadno].cpu_context_atsignal = NULL;
2327
2328 /* The return value must come from the saved R10. */
2329 (*CPU_REG_FETCH (current_cpu)) (current_cpu, H_GR_R10, regbuf, 4);
2330 retval = bfd_getl32 (regbuf);
2331
2332 /* We must also break the "sigsuspension loop". */
2333 if (was_sigsuspended)
2334 sim_pc_set (current_cpu, sim_pc_get (current_cpu) + 2);
2335 break;
2336 }
2337
2338 case TARGET_SYS_rt_sigsuspend:
2339 {
2340 USI newsetp = arg1;
2341 USI setsize = arg2;
2342
2343 if (setsize != 8)
2344 {
2345 sim_io_eprintf (sd, "Unimplemented rt_sigsuspend syscall"
2346 " arguments (0x%lx, 0x%lx)\n",
2347 (unsigned long) arg1, (unsigned long) arg2);
2348 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2349 SIM_SIGILL);
2350 }
2351
2352 /* Don't change the signal mask if we're already in
2353 sigsuspend state (i.e. this syscall is a rerun). */
2354 else if (!current_cpu->thread_data[threadno].sigsuspended)
2355 {
2356 USI set_low
2357 = sim_core_read_unaligned_4 (current_cpu, pc, 0,
2358 newsetp);
2359 USI set_high
2360 = sim_core_read_unaligned_4 (current_cpu, pc, 0,
2361 newsetp + 4);
2362 int i;
2363
2364 /* Save the current sigmask and insert the user-supplied
2365 one. */
2366 for (i = 0; i < 32; i++)
2367 {
2368 current_cpu->thread_data[threadno]
2369 .sigdata[i + 1].blocked_suspendsave
2370 = current_cpu->thread_data[threadno]
2371 .sigdata[i + 1].blocked;
2372
2373 current_cpu->thread_data[threadno]
2374 .sigdata[i + 1].blocked = (set_low & (1 << i)) != 0;
2375 }
2376 for (i = 0; i < 31; i++)
2377 {
2378 current_cpu->thread_data[threadno]
2379 .sigdata[i + 33].blocked_suspendsave
2380 = current_cpu->thread_data[threadno]
2381 .sigdata[i + 33].blocked;
2382 current_cpu->thread_data[threadno]
2383 .sigdata[i + 33].blocked = (set_high & (1 << i)) != 0;
2384 }
2385
2386 current_cpu->thread_data[threadno].sigsuspended = 1;
2387
2388 /* The mask changed, so a signal may be unblocked for
2389 execution. */
2390 current_cpu->thread_data[threadno].sigpending = 1;
2391 }
2392
2393 /* Because we don't use arg1 (newsetp) when this syscall is
2394 rerun, it doesn't matter that we overwrite it with the
2395 (constant) return value. */
2396 retval = -cb_host_to_target_errno (cb, EINTR);
2397 sim_pc_set (current_cpu, pc);
2398 break;
2399 }
2400
2401 /* Add case labels here for other syscalls using the 32-bit
2402 "struct stat", provided they have a corresponding simulator
2403 function of course. */
5457266c 2404 case TARGET_SYS_stat:
f6bcefef
HPN
2405 case TARGET_SYS_fstat:
2406 {
2407 /* As long as the infrastructure doesn't cache anything
2408 related to the stat mapping, this trick gets us a dual
2409 "struct stat"-type mapping in the least error-prone way. */
2410 const char *saved_map = cb->stat_map;
2411 CB_TARGET_DEFS_MAP *saved_syscall_map = cb->syscall_map;
2412
2413 cb->syscall_map = (CB_TARGET_DEFS_MAP *) syscall_stat32_map;
2414 cb->stat_map = stat32_map;
2415
2416 if (cb_syscall (cb, &s) != CB_RC_OK)
2417 {
2418 abort ();
2419 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2420 SIM_SIGILL);
2421 }
2422 retval = s.result == -1 ? -s.errcode : s.result;
2423
2424 cb->stat_map = saved_map;
2425 cb->syscall_map = saved_syscall_map;
2426 break;
2427 }
2428
2429 case TARGET_SYS_getcwd:
2430 {
2431 USI buf = arg1;
2432 USI size = arg2;
2433
3ca4d560
HPN
2434 char *cwd = xmalloc (SIM_PATHMAX);
2435 if (cwd != getcwd (cwd, SIM_PATHMAX))
f6bcefef
HPN
2436 abort ();
2437
2438 /* FIXME: When and if we support chdir, we need something
2439 a bit more elaborate. */
2440 if (simulator_sysroot[0] != '\0')
2441 strcpy (cwd, "/");
2442
2443 retval = -cb_host_to_target_errno (cb, ERANGE);
2444 if (strlen (cwd) + 1 <= size)
2445 {
2446 retval = strlen (cwd) + 1;
2447 if (sim_core_write_buffer (sd, current_cpu, 0, cwd,
2448 buf, retval)
2449 != (unsigned int) retval)
2450 retval = -cb_host_to_target_errno (cb, EFAULT);
2451 }
2452 free (cwd);
2453 break;
2454 }
2455
2456 case TARGET_SYS_readlink:
2457 {
2458 SI path = arg1;
2459 SI buf = arg2;
2460 SI bufsiz = arg3;
3ca4d560
HPN
2461 char *pbuf = xmalloc (SIM_PATHMAX);
2462 char *lbuf = xmalloc (SIM_PATHMAX);
f6bcefef
HPN
2463 char *lbuf_alloc = lbuf;
2464 int nchars = -1;
2465 int i;
2466 int o = 0;
2467
2468 if (sim_core_read_unaligned_1 (current_cpu, pc, 0, path) == '/')
2469 {
2470 strcpy (pbuf, simulator_sysroot);
2471 o += strlen (simulator_sysroot);
2472 }
2473
3ca4d560 2474 for (i = 0; i + o < SIM_PATHMAX; i++)
f6bcefef
HPN
2475 {
2476 pbuf[i + o]
2477 = sim_core_read_unaligned_1 (current_cpu, pc, 0, path + i);
2478 if (pbuf[i + o] == 0)
2479 break;
2480 }
2481
3ca4d560 2482 if (i + o == SIM_PATHMAX)
f6bcefef
HPN
2483 {
2484 retval = -cb_host_to_target_errno (cb, ENAMETOOLONG);
2485 break;
2486 }
2487
2488 /* Intervene calls for certain files expected in the target
2489 proc file system. */
2490 if (strcmp (pbuf + strlen (simulator_sysroot),
2491 "/proc/" XSTRING (TARGET_PID) "/exe") == 0)
2492 {
2493 char *argv0
2494 = (STATE_PROG_ARGV (sd) != NULL
2495 ? *STATE_PROG_ARGV (sd) : NULL);
2496
2497 if (argv0 == NULL || *argv0 == '.')
2498 {
2499 sim_io_eprintf (sd, "Unimplemented readlink syscall "
2500 "(0x%lx: [\"%s\"], 0x%lx)\n",
2501 (unsigned long) arg1, pbuf,
2502 (unsigned long) arg2);
2503 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2504 SIM_SIGILL);
2505 break;
2506 }
2507 else if (*argv0 == '/')
2508 {
2509 if (strncmp (simulator_sysroot, argv0,
2510 strlen (simulator_sysroot)) == 0)
2511 argv0 += strlen (simulator_sysroot);
2512
2513 strcpy (lbuf, argv0);
2514 nchars = strlen (argv0) + 1;
2515 }
2516 else
2517 {
3ca4d560
HPN
2518 if (getcwd (lbuf, SIM_PATHMAX) != NULL
2519 && strlen (lbuf) + 2 + strlen (argv0) < SIM_PATHMAX)
f6bcefef
HPN
2520 {
2521 if (strncmp (simulator_sysroot, lbuf,
2522 strlen (simulator_sysroot)) == 0)
2523 lbuf += strlen (simulator_sysroot);
2524
2525 strcat (lbuf, "/");
2526 strcat (lbuf, argv0);
2527 nchars = strlen (lbuf) + 1;
2528 }
2529 else
2530 abort ();
2531 }
2532 }
2533 else
3ca4d560 2534 nchars = readlink (pbuf, lbuf, SIM_PATHMAX);
f6bcefef
HPN
2535
2536 /* We trust that the readlink result returns a *relative*
2537 link, or one already adjusted for the file-path-prefix.
2538 (We can't generally tell the difference, so we go with
2539 the easiest decision; no adjustment.) */
2540
2541 if (nchars == -1)
2542 {
2543 retval = -cb_host_to_target_errno (cb, errno);
2544 break;
2545 }
2546
2547 if (bufsiz < nchars)
2548 nchars = bufsiz;
2549
2550 if (sim_core_write_buffer (sd, current_cpu, write_map, lbuf,
2551 buf, nchars) != (unsigned int) nchars)
2552 retval = -cb_host_to_target_errno (cb, EFAULT);
2553 else
2554 retval = nchars;
2555
2556 free (pbuf);
2557 free (lbuf_alloc);
2558 break;
2559 }
2560
2561 case TARGET_SYS_sched_getscheduler:
2562 {
2563 USI pid = arg1;
2564
2565 /* FIXME: Search (other) existing threads. */
2566 if (pid != 0 && pid != TARGET_PID)
2567 retval = -cb_host_to_target_errno (cb, ESRCH);
2568 else
2569 retval = TARGET_SCHED_OTHER;
2570 break;
2571 }
2572
2573 case TARGET_SYS_sched_getparam:
2574 {
2575 USI pid = arg1;
2576 USI paramp = arg2;
2577
2578 /* The kernel says:
2579 struct sched_param {
2580 int sched_priority;
2581 }; */
2582
2583 if (pid != 0 && pid != TARGET_PID)
2584 retval = -cb_host_to_target_errno (cb, ESRCH);
2585 else
2586 {
2587 /* FIXME: Save scheduler setting before threads are
2588 created too. */
2589 sim_core_write_unaligned_4 (current_cpu, pc, 0, paramp,
2590 current_cpu->thread_data != NULL
2591 ? (current_cpu
2592 ->thread_data[threadno]
2593 .priority)
2594 : 0);
2595 retval = 0;
2596 }
2597 break;
2598 }
2599
2600 case TARGET_SYS_sched_setparam:
2601 {
2602 USI pid = arg1;
2603 USI paramp = arg2;
2604
2605 if ((pid != 0 && pid != TARGET_PID)
2606 || sim_core_read_unaligned_4 (current_cpu, pc, 0,
2607 paramp) != 0)
2608 retval = -cb_host_to_target_errno (cb, EINVAL);
2609 else
2610 retval = 0;
2611 break;
2612 }
2613
2614 case TARGET_SYS_sched_setscheduler:
2615 {
2616 USI pid = arg1;
2617 USI policy = arg2;
2618 USI paramp = arg3;
2619
2620 if ((pid != 0 && pid != TARGET_PID)
2621 || policy != TARGET_SCHED_OTHER
2622 || sim_core_read_unaligned_4 (current_cpu, pc, 0,
2623 paramp) != 0)
2624 retval = -cb_host_to_target_errno (cb, EINVAL);
2625 else
2626 /* FIXME: Save scheduler setting to be read in later
2627 sched_getparam calls. */
2628 retval = 0;
2629 break;
2630 }
2631
2632 case TARGET_SYS_sched_yield:
2633 /* We reschedule to the next thread after a syscall anyway, so
2634 we don't have to do anything here than to set the return
2635 value. */
2636 retval = 0;
2637 break;
2638
2639 case TARGET_SYS_sched_get_priority_min:
2640 case TARGET_SYS_sched_get_priority_max:
2641 if (arg1 != 0)
2642 retval = -cb_host_to_target_errno (cb, EINVAL);
2643 else
2644 retval = 0;
2645 break;
2646
2647 case TARGET_SYS_ugetrlimit:
2648 {
2649 unsigned int curlim, maxlim;
2650 if (arg1 != TARGET_RLIMIT_STACK && arg1 != TARGET_RLIMIT_NOFILE)
2651 {
2652 retval = -cb_host_to_target_errno (cb, EINVAL);
2653 break;
2654 }
2655
2656 /* The kernel says:
2657 struct rlimit {
2658 unsigned long rlim_cur;
2659 unsigned long rlim_max;
2660 }; */
2661 if (arg1 == TARGET_RLIMIT_NOFILE)
2662 {
2663 /* Sadly a very low limit. Better not lie, though. */
2664 maxlim = curlim = MAX_CALLBACK_FDS;
2665 }
2666 else /* arg1 == TARGET_RLIMIT_STACK */
2667 {
2668 maxlim = 0xffffffff;
2669 curlim = 0x800000;
2670 }
2671 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg2, curlim);
2672 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg2 + 4, maxlim);
2673 retval = 0;
2674 break;
2675 }
2676
2677 case TARGET_SYS_setrlimit:
2678 if (arg1 != TARGET_RLIMIT_STACK)
2679 {
2680 retval = -cb_host_to_target_errno (cb, EINVAL);
2681 break;
2682 }
2683 /* FIXME: Save values for future ugetrlimit calls. */
2684 retval = 0;
2685 break;
2686
2687 /* Provide a very limited subset of the sysctl functions, and
2688 abort for the rest. */
2689 case TARGET_SYS__sysctl:
2690 {
2691 /* The kernel says:
2692 struct __sysctl_args {
2693 int *name;
2694 int nlen;
2695 void *oldval;
2696 size_t *oldlenp;
2697 void *newval;
2698 size_t newlen;
2699 unsigned long __unused[4];
2700 }; */
2701 SI name = sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1);
2702 SI name0 = name == 0
2703 ? 0 : sim_core_read_unaligned_4 (current_cpu, pc, 0, name);
2704 SI name1 = name == 0
2705 ? 0 : sim_core_read_unaligned_4 (current_cpu, pc, 0, name + 4);
2706 SI nlen
2707 = sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1 + 4);
2708 SI oldval
2709 = sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1 + 8);
2710 SI oldlenp
2711 = sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1 + 12);
2712 SI oldlen = oldlenp == 0
2713 ? 0 : sim_core_read_unaligned_4 (current_cpu, pc, 0, oldlenp);
2714 SI newval
2715 = sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1 + 16);
2716 SI newlen
2717 = sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1 + 20);
2718
2719 if (name0 == TARGET_CTL_KERN && name1 == TARGET_CTL_KERN_VERSION)
2720 {
2721 SI to_write = oldlen < (SI) sizeof (TARGET_UTSNAME)
2722 ? oldlen : (SI) sizeof (TARGET_UTSNAME);
2723
2724 sim_core_write_unaligned_4 (current_cpu, pc, 0, oldlenp,
2725 sizeof (TARGET_UTSNAME));
2726
2727 if (sim_core_write_buffer (sd, current_cpu, write_map,
2728 TARGET_UTSNAME, oldval,
2729 to_write)
2730 != (unsigned int) to_write)
2731 retval = -cb_host_to_target_errno (cb, EFAULT);
2732 else
2733 retval = 0;
2734 break;
2735 }
2736
2737 sim_io_eprintf (sd, "Unimplemented _sysctl syscall "
2738 "(0x%lx: [0x%lx, 0x%lx],"
2739 " 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
2740 (unsigned long) name,
2741 (unsigned long) name0,
2742 (unsigned long) name1,
2743 (unsigned long) nlen,
2744 (unsigned long) oldval,
2745 (unsigned long) oldlenp,
2746 (unsigned long) newval,
2747 (unsigned long) newlen);
2748 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2749 SIM_SIGILL);
2750 break;
2751 }
2752
2753 case TARGET_SYS_exit:
2754 {
2755 /* Here for all but the last thread. */
2756 int i;
2757 int pid
2758 = current_cpu->thread_data[threadno].threadid + TARGET_PID;
2759 int ppid
2760 = (current_cpu->thread_data[threadno].parent_threadid
2761 + TARGET_PID);
2762 int exitsig = current_cpu->thread_data[threadno].exitsig;
2763
2764 /* Any children are now all orphans. */
2765 for (i = 0; i < SIM_TARGET_MAX_THREADS; i++)
2766 if (current_cpu->thread_data[i].parent_threadid
2767 == current_cpu->thread_data[threadno].threadid)
2768 /* Make getppid(2) return 1 for them, poor little ones. */
2769 current_cpu->thread_data[i].parent_threadid = -TARGET_PID + 1;
2770
2771 /* Free the cpu context data. When the parent has received
2772 the exit status, we'll clear the entry too. */
2773 free (current_cpu->thread_data[threadno].cpu_context);
2774 current_cpu->thread_data[threadno].cpu_context = NULL;
2775 current_cpu->m1threads--;
2776 if (arg1 != 0)
2777 {
2778 sim_io_eprintf (sd, "Thread %d exited with status %d\n",
2779 pid, arg1);
2780 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2781 SIM_SIGILL);
2782 }
2783
2784 /* Still, we may want to support non-zero exit values. */
2785 current_cpu->thread_data[threadno].exitval = arg1 << 8;
2786
2787 if (exitsig)
2788 deliver_signal (current_cpu, exitsig, ppid);
2789 break;
2790 }
2791
2792 case TARGET_SYS_clone:
2793 {
2794 int nthreads = current_cpu->m1threads + 1;
2795 void *thread_cpu_data;
2796 bfd_byte old_sp_buf[4];
2797 bfd_byte sp_buf[4];
2798 const bfd_byte zeros[4] = { 0, 0, 0, 0 };
2799 int i;
2800
2801 /* That's right, the syscall clone arguments are reversed
2802 compared to sys_clone notes in clone(2) and compared to
2803 other Linux ports (i.e. it's the same order as in the
2804 clone(2) libcall). */
2805 USI flags = arg2;
2806 USI newsp = arg1;
2807
2808 if (nthreads == SIM_TARGET_MAX_THREADS)
2809 {
2810 retval = -cb_host_to_target_errno (cb, EAGAIN);
2811 break;
2812 }
2813
2814 /* FIXME: Implement the low byte. */
2815 if ((flags & ~TARGET_CSIGNAL) !=
2816 (TARGET_CLONE_VM
2817 | TARGET_CLONE_FS
2818 | TARGET_CLONE_FILES
2819 | TARGET_CLONE_SIGHAND)
2820 || newsp == 0)
2821 {
2822 sim_io_eprintf (sd,
2823 "Unimplemented clone syscall (0x%lx, 0x%lx)\n",
2824 (unsigned long) arg1, (unsigned long) arg2);
2825 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2826 SIM_SIGILL);
2827 }
2828
2829 if (current_cpu->thread_data == NULL)
2830 make_first_thread (current_cpu);
2831
2832 /* The created thread will get the new SP and a cleared R10.
2833 Since it's created out of a copy of the old thread and we
2834 don't have a set-register-function that just take the
2835 cpu_data as a parameter, we set the childs values first,
2836 and write back or overwrite them in the parent after the
2837 copy. */
2838 (*CPU_REG_FETCH (current_cpu)) (current_cpu,
2839 H_GR_SP, old_sp_buf, 4);
2840 bfd_putl32 (newsp, sp_buf);
2841 (*CPU_REG_STORE (current_cpu)) (current_cpu,
2842 H_GR_SP, sp_buf, 4);
2843 (*CPU_REG_STORE (current_cpu)) (current_cpu,
2844 H_GR_R10, (bfd_byte *) zeros, 4);
2845 thread_cpu_data
2846 = (*current_cpu
2847 ->make_thread_cpu_data) (current_cpu,
2848 &current_cpu->cpu_data_placeholder);
2849 (*CPU_REG_STORE (current_cpu)) (current_cpu,
2850 H_GR_SP, old_sp_buf, 4);
2851
2852 retval = ++current_cpu->max_threadid + TARGET_PID;
2853
2854 /* Find an unused slot. After a few threads have been created
2855 and exited, the array is expected to be a bit fragmented.
2856 We don't reuse the first entry, though, that of the
2857 original thread. */
2858 for (i = 1; i < SIM_TARGET_MAX_THREADS; i++)
2859 if (current_cpu->thread_data[i].cpu_context == NULL
2860 /* Don't reuse a zombied entry. */
2861 && current_cpu->thread_data[i].threadid == 0)
2862 break;
2863
2864 memcpy (&current_cpu->thread_data[i],
2865 &current_cpu->thread_data[threadno],
2866 sizeof (current_cpu->thread_data[i]));
2867 current_cpu->thread_data[i].cpu_context = thread_cpu_data;
2868 current_cpu->thread_data[i].cpu_context_atsignal = NULL;
2869 current_cpu->thread_data[i].threadid = current_cpu->max_threadid;
2870 current_cpu->thread_data[i].parent_threadid
2871 = current_cpu->thread_data[threadno].threadid;
2872 current_cpu->thread_data[i].pipe_read_fd = 0;
2873 current_cpu->thread_data[i].pipe_write_fd = 0;
2874 current_cpu->thread_data[i].at_syscall = 0;
2875 current_cpu->thread_data[i].sigpending = 0;
2876 current_cpu->thread_data[i].sigsuspended = 0;
2877 current_cpu->thread_data[i].exitsig = flags & TARGET_CSIGNAL;
2878 current_cpu->m1threads = nthreads;
2879 break;
2880 }
2881
2882 /* Better watch these in case they do something necessary. */
2883 case TARGET_SYS_socketcall:
2884 retval = -cb_host_to_target_errno (cb, ENOSYS);
2885 break;
2886
2887 unimplemented_syscall:
2888 default:
2889 sim_io_eprintf (sd, "Unimplemented syscall: %d "
2890 "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", callnum,
2891 arg1, arg2, arg3, arg4, arg5, arg6);
2892 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2893 SIM_SIGILL);
2894 }
2895 }
2896
ed1f044a
HPN
2897 /* Minimal support for fcntl F_GETFL as used in open+fdopen. */
2898 if (callnum == TARGET_SYS_open)
2899 {
2900 current_cpu->last_open_fd = retval;
2901 current_cpu->last_open_flags = arg2;
2902 }
2903 current_cpu->last_syscall = callnum;
2904
f6bcefef
HPN
2905 /* A system call is a rescheduling point. For the time being, we don't
2906 reschedule anywhere else. */
2907 if (current_cpu->m1threads != 0
2908 /* We need to schedule off from an exiting thread that is the
2909 second-last one. */
2910 || (current_cpu->thread_data != NULL
2911 && current_cpu->thread_data[threadno].cpu_context == NULL))
2912 {
2913 bfd_byte retval_buf[4];
2914
2915 current_cpu->thread_data[threadno].last_execution
2916 = TARGET_TIME_MS (current_cpu);
2917 bfd_putl32 (retval, retval_buf);
2918 (*CPU_REG_STORE (current_cpu)) (current_cpu, H_GR_R10, retval_buf, 4);
2919
2920 current_cpu->thread_data[threadno].at_syscall = 1;
2921 reschedule (current_cpu);
2922
2923 (*CPU_REG_FETCH (current_cpu)) (current_cpu, H_GR_R10, retval_buf, 4);
2924 retval = bfd_getl32 (retval_buf);
2925 }
2926
2927 return retval;
2928}
2929
2930/* Callback from simulator write saying that the pipe at (reader, writer)
2931 is now non-empty (so the writer should wait until the pipe is empty, at
2932 least not write to this or any other pipe). Simplest is to just wait
2933 until the pipe is empty. */
2934
2935static void
2936cris_pipe_nonempty (host_callback *cb ATTRIBUTE_UNUSED,
2937 int reader, int writer)
2938{
2939 SIM_CPU *cpu = current_cpu_for_cb_callback;
2940 const bfd_byte zeros[4] = { 0, 0, 0, 0 };
2941
2942 /* It's the current thread: we just have to re-run the current
2943 syscall instruction (presumably "break 13") and change the syscall
2944 to the special simulator-wait code. Oh, and set a marker that
2945 we're waiting, so we can disambiguate the special call from a
2946 program error.
2947
2948 This function may be called multiple times between cris_pipe_empty,
2949 but we must avoid e.g. decreasing PC every time. Check fd markers
2950 to tell. */
2951 if (cpu->thread_data == NULL)
2952 {
2953 sim_io_eprintf (CPU_STATE (cpu),
2954 "Terminating simulation due to writing pipe rd:wr %d:%d"
2955 " from one single thread\n", reader, writer);
2956 sim_engine_halt (CPU_STATE (cpu), cpu,
2957 NULL, sim_pc_get (cpu), sim_stopped, SIM_SIGILL);
2958 }
2959 else if (cpu->thread_data[cpu->threadno].pipe_write_fd == 0)
2960 {
2961 cpu->thread_data[cpu->threadno].pipe_write_fd = writer;
2962 cpu->thread_data[cpu->threadno].pipe_read_fd = reader;
2963 /* FIXME: We really shouldn't change registers other than R10 in
2964 syscalls (like R9), here or elsewhere. */
2965 (*CPU_REG_STORE (cpu)) (cpu, H_GR_R9, (bfd_byte *) zeros, 4);
2966 sim_pc_set (cpu, sim_pc_get (cpu) - 2);
2967 }
2968}
2969
2970/* Callback from simulator close or read call saying that the pipe at
2971 (reader, writer) is now empty (so the writer can write again, perhaps
2972 leave a waiting state). If there are bytes remaining, they couldn't be
2973 consumed (perhaps due to the pipe closing). */
2974
2975static void
2976cris_pipe_empty (host_callback *cb,
eccd787e 2977 int reader,
f6bcefef
HPN
2978 int writer)
2979{
2980 int i;
2981 SIM_CPU *cpu = current_cpu_for_cb_callback;
2982 bfd_byte r10_buf[4];
eccd787e
HPN
2983 int remaining
2984 = cb->pipe_buffer[writer].size - cb->pipe_buffer[reader].size;
f6bcefef
HPN
2985
2986 /* We need to find the thread that waits for this pipe. */
2987 for (i = 0; i < SIM_TARGET_MAX_THREADS; i++)
2988 if (cpu->thread_data[i].cpu_context
2989 && cpu->thread_data[i].pipe_write_fd == writer)
2990 {
2991 int retval;
eccd787e 2992
f6bcefef
HPN
2993 /* Temporarily switch to this cpu context, so we can change the
2994 PC by ordinary calls. */
2995
2996 memcpy (cpu->thread_data[cpu->threadno].cpu_context,
2997 &cpu->cpu_data_placeholder,
2998 cpu->thread_cpu_data_size);
2999 memcpy (&cpu->cpu_data_placeholder,
3000 cpu->thread_data[i].cpu_context,
3001 cpu->thread_cpu_data_size);
3002
eccd787e
HPN
3003 /* The return value is supposed to contain the number of
3004 written bytes, which is the number of bytes requested and
3005 returned at the write call. You might think the right
3006 thing is to adjust the return-value to be only the
3007 *consumed* number of bytes, but it isn't. We're only
3008 called if the pipe buffer is fully consumed or it is being
3009 closed, possibly with remaining bytes. For the latter
3010 case, the writer is still supposed to see success for
3011 PIPE_BUF bytes (a constant which we happen to know and is
3012 unlikely to change). The return value may also be a
3013 negative number; an error value. This case is covered
3014 because "remaining" is always >= 0. */
f6bcefef
HPN
3015 (*CPU_REG_FETCH (cpu)) (cpu, H_GR_R10, r10_buf, 4);
3016 retval = (int) bfd_getl_signed_32 (r10_buf);
eccd787e
HPN
3017 if (retval - remaining > TARGET_PIPE_BUF)
3018 {
3019 bfd_putl32 (retval - remaining, r10_buf);
3020 (*CPU_REG_STORE (cpu)) (cpu, H_GR_R10, r10_buf, 4);
3021 }
f6bcefef
HPN
3022 sim_pc_set (cpu, sim_pc_get (cpu) + 2);
3023 memcpy (cpu->thread_data[i].cpu_context,
3024 &cpu->cpu_data_placeholder,
3025 cpu->thread_cpu_data_size);
3026 memcpy (&cpu->cpu_data_placeholder,
3027 cpu->thread_data[cpu->threadno].cpu_context,
3028 cpu->thread_cpu_data_size);
3029 cpu->thread_data[i].pipe_read_fd = 0;
3030 cpu->thread_data[i].pipe_write_fd = 0;
3031 return;
3032 }
3033
3034 abort ();
3035}
3036
3037/* We have a simulator-specific notion of time. See TARGET_TIME. */
3038
3039static long
3040cris_time (host_callback *cb ATTRIBUTE_UNUSED, long *t)
3041{
3042 long retval = TARGET_TIME (current_cpu_for_cb_callback);
3043 if (t)
3044 *t = retval;
3045 return retval;
3046}
3047
3048/* Set target-specific callback data. */
3049
3050void
3051cris_set_callbacks (host_callback *cb)
3052{
3053 /* Yeargh, have to cast away constness to avoid warnings. */
3054 cb->syscall_map = (CB_TARGET_DEFS_MAP *) syscall_map;
3055 cb->errno_map = (CB_TARGET_DEFS_MAP *) errno_map;
3056
3057 /* The kernel stat64 layout. If we see a file > 2G, the "long"
3058 parameter to cb_store_target_endian will make st_size negative.
3059 Similarly for st_ino. FIXME: Find a 64-bit type, and use it
3060 *unsigned*, and/or add syntax for signed-ness. */
3061 cb->stat_map = stat_map;
3062 cb->open_map = (CB_TARGET_DEFS_MAP *) open_map;
3063 cb->pipe_nonempty = cris_pipe_nonempty;
3064 cb->pipe_empty = cris_pipe_empty;
3065 cb->time = cris_time;
3066}
3067
3068/* Process an address exception. */
3069
3070void
3071cris_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia,
3072 unsigned int map, int nr_bytes, address_word addr,
3073 transfer_type transfer, sim_core_signals sig)
3074{
3075 sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr,
3076 transfer, sig);
3077}