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