* cris/sim-main.h (struct _sim_cpu): New members last_syscall,
[deliverable/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
ed1f044a
HPN
667/* This one we treat specially, as it's used in the fcntl syscall. */
668#define TARGET_O_ACCMODE 3
669
f6bcefef
HPN
670static const CB_TARGET_DEFS_MAP open_map[] = {
671#ifdef O_ACCMODE
672 { O_ACCMODE, 0x3 },
673#endif
674#ifdef O_RDONLY
675 { O_RDONLY, 0x0 },
676#endif
677#ifdef O_WRONLY
678 { O_WRONLY, 0x1 },
679#endif
680#ifdef O_RDWR
681 { O_RDWR, 0x2 },
682#endif
683#ifdef O_CREAT
684 { O_CREAT, 0x40 },
685#endif
686#ifdef O_EXCL
687 { O_EXCL, 0x80 },
688#endif
689#ifdef O_NOCTTY
690 { O_NOCTTY, 0x100 },
691#endif
692#ifdef O_TRUNC
693 { O_TRUNC, 0x200 },
694#endif
695#ifdef O_APPEND
696 { O_APPEND, 0x400 },
697#endif
698#ifdef O_NONBLOCK
699 { O_NONBLOCK, 0x800 },
700#endif
701#ifdef O_NDELAY
702 { O_NDELAY, 0x0 },
703#endif
704#ifdef O_SYNC
705 { O_SYNC, 0x1000 },
706#endif
707#ifdef FASYNC
708 { FASYNC, 0x2000 },
709#endif
710#ifdef O_DIRECT
711 { O_DIRECT, 0x4000 },
712#endif
713#ifdef O_LARGEFILE
714 { O_LARGEFILE, 0x8000 },
715#endif
716#ifdef O_DIRECTORY
717 { O_DIRECTORY, 0x10000 },
718#endif
719#ifdef O_NOFOLLOW
720 { O_NOFOLLOW, 0x20000 },
721#endif
722 { -1, -1 }
723};
724
725/* Needed for the cris_pipe_nonempty and cris_pipe_empty syscalls. */
726static SIM_CPU *current_cpu_for_cb_callback;
727
728static int syscall_read_mem (host_callback *, struct cb_syscall *,
729 unsigned long, char *, int);
730static int syscall_write_mem (host_callback *, struct cb_syscall *,
731 unsigned long, const char *, int);
732static USI create_map (SIM_DESC, struct cris_sim_mmapped_page **,
733 USI addr, USI len);
734static USI unmap_pages (SIM_DESC, struct cris_sim_mmapped_page **,
735 USI addr, USI len);
736static USI is_mapped (SIM_DESC, struct cris_sim_mmapped_page **,
737 USI addr, USI len);
738static void dump_statistics (SIM_CPU *current_cpu);
739static void make_first_thread (SIM_CPU *current_cpu);
740
741/* Read/write functions for system call interface. */
742
743static int
744syscall_read_mem (host_callback *cb ATTRIBUTE_UNUSED,
745 struct cb_syscall *sc,
746 unsigned long taddr, char *buf, int bytes)
747{
748 SIM_DESC sd = (SIM_DESC) sc->p1;
749 SIM_CPU *cpu = (SIM_CPU *) sc->p2;
750
751 return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes);
752}
753
754static int
755syscall_write_mem (host_callback *cb ATTRIBUTE_UNUSED,
756 struct cb_syscall *sc,
757 unsigned long taddr, const char *buf, int bytes)
758{
759 SIM_DESC sd = (SIM_DESC) sc->p1;
760 SIM_CPU *cpu = (SIM_CPU *) sc->p2;
761
762 return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes);
763}
764
765/* When we risk running self-modified code (as in trampolines), this is
766 called from special-case insns. The silicon CRIS CPU:s have enough
767 cache snooping implemented making this a simulator-only issue. Tests:
768 gcc.c-torture/execute/931002-1.c execution, -O3 -g
769 gcc.c-torture/execute/931002-1.c execution, -O3 -fomit-frame-pointer. */
770
771void
772cris_flush_simulator_decode_cache (SIM_CPU *current_cpu,
773 USI pc ATTRIBUTE_UNUSED)
774{
775 SIM_DESC sd = CPU_STATE (current_cpu);
776
777#if WITH_SCACHE
778 if (USING_SCACHE_P (sd))
779 scache_flush_cpu (current_cpu);
780#endif
781}
782
783/* Output statistics at the end of a run. */
784static void
785dump_statistics (SIM_CPU *current_cpu)
786{
787 SIM_DESC sd = CPU_STATE (current_cpu);
788 CRIS_MISC_PROFILE *profp
789 = CPU_CRIS_MISC_PROFILE (current_cpu);
790 unsigned64 total = profp->basic_cycle_count;
791 const char *textmsg = "Basic clock cycles, total @: %llu\n";
792
793 /* The --cris-stats={basic|unaligned|schedulable|all} counts affect
794 what's included in the "total" count only. */
795 switch (CPU_CRIS_MISC_PROFILE (current_cpu)->flags
796 & FLAG_CRIS_MISC_PROFILE_ALL)
797 {
798 case FLAG_CRIS_MISC_PROFILE_SIMPLE:
799 break;
800
801 case (FLAG_CRIS_MISC_PROFILE_UNALIGNED | FLAG_CRIS_MISC_PROFILE_SIMPLE):
802 textmsg
803 = "Clock cycles including stall cycles for unaligned accesses @: %llu\n";
804 total += profp->unaligned_mem_dword_count;
805 break;
806
807 case (FLAG_CRIS_MISC_PROFILE_SCHEDULABLE | FLAG_CRIS_MISC_PROFILE_SIMPLE):
808 textmsg = "Schedulable clock cycles, total @: %llu\n";
809 total
810 += (profp->memsrc_stall_count
811 + profp->memraw_stall_count
812 + profp->movemsrc_stall_count
813 + profp->movemdst_stall_count
814 + profp->mulsrc_stall_count
815 + profp->jumpsrc_stall_count
816 + profp->unaligned_mem_dword_count);
817 break;
818
819 case FLAG_CRIS_MISC_PROFILE_ALL:
820 textmsg = "All accounted clock cycles, total @: %llu\n";
821 total
822 += (profp->memsrc_stall_count
823 + profp->memraw_stall_count
824 + profp->movemsrc_stall_count
825 + profp->movemdst_stall_count
826 + profp->movemaddr_stall_count
827 + profp->mulsrc_stall_count
828 + profp->jumpsrc_stall_count
829 + profp->branch_stall_count
830 + profp->jumptarget_stall_count
831 + profp->unaligned_mem_dword_count);
832 break;
833
834 default:
835 abort ();
836
837 sim_io_eprintf (sd,
838 "Internal inconsistency at %s:%d",
839 __FILE__, __LINE__);
840 sim_engine_halt (sd, current_cpu, NULL, 0,
841 sim_stopped, SIM_SIGILL);
842 }
843
844 /* Historically, these messages have gone to stderr, so we'll keep it
845 that way. It's also easier to then tell it from normal program
846 output. FIXME: Add redirect option like "run -e file". */
847 sim_io_eprintf (sd, textmsg, total);
848
849 /* For v32, unaligned_mem_dword_count should always be 0. For
850 v10, memsrc_stall_count should always be 0. */
851 sim_io_eprintf (sd, "Memory source stall cycles: %lld\n",
852 profp->memsrc_stall_count
853 + profp->unaligned_mem_dword_count);
854 sim_io_eprintf (sd, "Memory read-after-write stall cycles: %lld\n",
855 profp->memraw_stall_count);
856 sim_io_eprintf (sd, "Movem source stall cycles: %lld\n",
857 profp->movemsrc_stall_count);
858 sim_io_eprintf (sd, "Movem destination stall cycles: %lld\n",
859 profp->movemdst_stall_count);
860 sim_io_eprintf (sd, "Movem address stall cycles: %lld\n",
861 profp->movemaddr_stall_count);
862 sim_io_eprintf (sd, "Multiplication source stall cycles: %lld\n",
863 profp->mulsrc_stall_count);
864 sim_io_eprintf (sd, "Jump source stall cycles: %lld\n",
865 profp->jumpsrc_stall_count);
866 sim_io_eprintf (sd, "Branch misprediction stall cycles: %lld\n",
867 profp->branch_stall_count);
868 sim_io_eprintf (sd, "Jump target stall cycles: %lld\n",
869 profp->jumptarget_stall_count);
870}
871
872/* Check whether any part of [addr .. addr + len - 1] is already mapped.
873 Return 1 if a overlap detected, 0 otherwise. */
874
875static USI
876is_mapped (SIM_DESC sd ATTRIBUTE_UNUSED,
877 struct cris_sim_mmapped_page **rootp,
878 USI addr, USI len)
879{
880 struct cris_sim_mmapped_page *mapp;
881
882 if (len == 0 || (len & 8191))
883 abort ();
884
885 /* Iterate over the reverse-address sorted pages until we find a page in
886 or lower than the checked area. */
887 for (mapp = *rootp; mapp != NULL && mapp->addr >= addr; mapp = mapp->prev)
888 if (mapp->addr < addr + len && mapp->addr >= addr)
889 return 1;
890
891 return 0;
892}
893
894/* Create mmapped memory. */
895
896static USI
897create_map (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
898 USI len)
899{
900 struct cris_sim_mmapped_page *mapp;
901 struct cris_sim_mmapped_page **higher_prevp = rootp;
902 USI new_addr = 0x40000000;
903
904 if (addr != 0)
905 new_addr = addr;
906 else if (*rootp)
907 new_addr = rootp[0]->addr + 8192;
908
909 if (len != 8192)
910 {
911 USI page_addr;
912
913 if (len & 8191)
914 /* Which is better: return an error for this, or just round it up? */
915 abort ();
916
917 /* Do a recursive call for each page in the request. */
918 for (page_addr = new_addr; len != 0; page_addr += 8192, len -= 8192)
919 if (create_map (sd, rootp, page_addr, 8192) >= (USI) -8191)
920 abort ();
921
922 return new_addr;
923 }
924
925 for (mapp = *rootp;
926 mapp != NULL && mapp->addr > new_addr;
927 mapp = mapp->prev)
928 higher_prevp = &mapp->prev;
929
930 /* Allocate the new page, on the next higher page from the last one
931 allocated, and link in the new descriptor before previous ones. */
932 mapp = malloc (sizeof (*mapp));
933
934 if (mapp == NULL)
935 return (USI) -ENOMEM;
936
937 sim_core_attach (sd, NULL, 0, access_read_write_exec, 0,
938 new_addr, len,
939 0, NULL, NULL);
940
941 mapp->addr = new_addr;
942 mapp->prev = *higher_prevp;
943 *higher_prevp = mapp;
944
945 return new_addr;
946}
947
948/* Unmap one or more pages. */
949
950static USI
951unmap_pages (SIM_DESC sd, struct cris_sim_mmapped_page **rootp, USI addr,
952 USI len)
953{
954 struct cris_sim_mmapped_page *mapp;
955 struct cris_sim_mmapped_page **higher_prevp = rootp;
956
957 if (len != 8192)
958 {
959 USI page_addr;
960
961 if (len & 8191)
962 /* Which is better: return an error for this, or just round it up? */
963 abort ();
964
965 /* Loop backwards to make each call is O(1) over the number of pages
966 allocated, if we're unmapping from the high end of the pages. */
967 for (page_addr = addr + len - 8192;
968 page_addr >= addr;
969 page_addr -= 8192)
970 if (unmap_pages (sd, rootp, page_addr, 8192) != 0)
971 abort ();
972
973 return 0;
974 }
975
976 for (mapp = *rootp; mapp != NULL && mapp->addr > addr; mapp = mapp->prev)
977 higher_prevp = &mapp->prev;
978
979 if (mapp == NULL || mapp->addr != addr)
980 return EINVAL;
981
982 *higher_prevp = mapp->prev;
983 sim_core_detach (sd, NULL, 0, 0, addr);
984 free (mapp);
985 return 0;
986}
987
988/* The semantic code invokes this for illegal (unrecognized) instructions. */
989
990SEM_PC
991sim_engine_invalid_insn (SIM_CPU *current_cpu, IADDR cia, SEM_PC vpc)
992{
993 SIM_DESC sd = CPU_STATE (current_cpu);
994
995 sim_engine_halt (sd, current_cpu, NULL, cia, sim_stopped, SIM_SIGILL);
996 return vpc;
997}
998
999/* Handlers from the CGEN description that should not be called. */
1000
1001USI
1002cris_bmod_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
1003 UINT srcreg ATTRIBUTE_UNUSED,
1004 USI dstreg ATTRIBUTE_UNUSED)
1005{
1006 abort ();
1007}
1008
1009void
1010h_supr_set_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
1011 UINT index ATTRIBUTE_UNUSED,
1012 USI page ATTRIBUTE_UNUSED,
1013 USI newval ATTRIBUTE_UNUSED)
1014{
1015 abort ();
1016}
1017
1018USI
1019h_supr_get_handler (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
1020 UINT index ATTRIBUTE_UNUSED,
1021 USI page ATTRIBUTE_UNUSED)
1022{
1023 abort ();
1024}
1025
1026/* Swap one context for another. */
1027
1028static void
1029schedule (SIM_CPU *current_cpu, int next)
1030{
1031 /* Need to mark context-switches in the trace output. */
1032 if ((CPU_CRIS_MISC_PROFILE (current_cpu)->flags
1033 & FLAG_CRIS_MISC_PROFILE_XSIM_TRACE))
1034 cris_trace_printf (CPU_STATE (current_cpu), current_cpu,
1035 "\t#:%d\n", next);
1036
1037 /* Copy the current context (if there is one) to its slot. */
1038 if (current_cpu->thread_data[current_cpu->threadno].cpu_context)
1039 memcpy (current_cpu->thread_data[current_cpu->threadno].cpu_context,
1040 &current_cpu->cpu_data_placeholder,
1041 current_cpu->thread_cpu_data_size);
1042
1043 /* Copy the new context from its slot. */
1044 memcpy (&current_cpu->cpu_data_placeholder,
1045 current_cpu->thread_data[next].cpu_context,
1046 current_cpu->thread_cpu_data_size);
1047
1048 /* Update needed stuff to indicate the new context. */
1049 current_cpu->threadno = next;
1050
1051 /* Handle pending signals. */
1052 if (current_cpu->thread_data[next].sigpending
1053 /* We don't run nested signal handlers. This means that pause(2)
1054 and sigsuspend(2) do not work in sighandlers, but that
1055 shouldn't be too hard a restriction. It also greatly
1056 simplifies the code. */
1057 && current_cpu->thread_data[next].cpu_context_atsignal == NULL)
1058 {
1059 int sig;
1060
1061 /* See if there's really a pending, non-blocked handler. We don't
1062 queue signals, so just use the first one in ascending order. */
1063 for (sig = 0; sig < 64; sig++)
1064 if (current_cpu->thread_data[next].sigdata[sig].pending
1065 && !current_cpu->thread_data[next].sigdata[sig].blocked)
1066 {
1067 bfd_byte regbuf[4];
1068 USI sp;
1069 int i;
1070 USI blocked;
1071 USI pc = sim_pc_get (current_cpu);
1072
1073 /* It's simpler to save the CPU context inside the simulator
1074 than on the stack. */
1075 current_cpu->thread_data[next].cpu_context_atsignal
1076 = (*current_cpu
1077 ->make_thread_cpu_data) (current_cpu,
1078 current_cpu->thread_data[next]
1079 .cpu_context);
1080
1081 (*CPU_REG_FETCH (current_cpu)) (current_cpu, H_GR_SP, regbuf, 4);
1082 sp = bfd_getl32 (regbuf);
1083
1084 /* Make sure we have an aligned stack. */
1085 sp &= ~3;
1086
1087 /* Make room for the signal frame, aligned. FIXME: Check that
1088 the memory exists, map it in if absent. (BTW, should also
1089 implement on-access automatic stack allocation). */
1090 sp -= 20;
1091
1092 /* This isn't the same signal frame as the kernel uses, because
1093 we don't want to bother getting all registers on and off the
1094 stack. */
1095
1096 /* First, we store the currently blocked signals. */
1097 blocked = 0;
1098 for (i = 0; i < 32; i++)
1099 blocked
1100 |= current_cpu->thread_data[next].sigdata[i + 1].blocked << i;
1101 sim_core_write_aligned_4 (current_cpu, pc, 0, sp, blocked);
1102 blocked = 0;
1103 for (i = 0; i < 31; i++)
1104 blocked
1105 |= current_cpu->thread_data[next].sigdata[i + 33].blocked << i;
1106 sim_core_write_aligned_4 (current_cpu, pc, 0, sp + 4, blocked);
1107
1108 /* Then, the actual instructions. This is CPU-specific, but we
1109 use instructions from the common subset for v10 and v32 which
1110 should be safe for the time being but could be parametrized
1111 if need be. */
1112 /* MOVU.W [PC+],R9. */
1113 sim_core_write_aligned_2 (current_cpu, pc, 0, sp + 8, 0x9c5f);
1114 /* .WORD TARGET_SYS_sigreturn. */
1115 sim_core_write_aligned_2 (current_cpu, pc, 0, sp + 10,
1116 TARGET_SYS_sigreturn);
1117 /* BREAK 13. */
1118 sim_core_write_aligned_2 (current_cpu, pc, 0, sp + 12, 0xe93d);
1119
1120 /* NOP (on v32; it's SETF on v10, but is the correct compatible
1121 instruction. Still, it doesn't matter because v10 has no
1122 delay slot for BREAK so it will not be executed). */
1123 sim_core_write_aligned_2 (current_cpu, pc, 0, sp + 16, 0x05b0);
1124
1125 /* Modify registers to hold the right values for the sighandler
1126 context: updated stackpointer and return address pointing to
1127 the sigreturn stub. */
1128 bfd_putl32 (sp, regbuf);
1129 (*CPU_REG_STORE (current_cpu)) (current_cpu, H_GR_SP, regbuf, 4);
1130 bfd_putl32 (sp + 8, regbuf);
1131 (*CPU_REG_STORE (current_cpu)) (current_cpu, TARGET_SRP_REGNUM,
1132 regbuf, 4);
1133
1134 current_cpu->thread_data[next].sigdata[sig].pending = 0;
1135
1136 /* Block this signal (for the duration of the sighandler). */
1137 current_cpu->thread_data[next].sigdata[sig].blocked = 1;
1138
1139 sim_pc_set (current_cpu, current_cpu->sighandler[sig]);
1140 bfd_putl32 (sig, regbuf);
1141 (*CPU_REG_STORE (current_cpu)) (current_cpu, H_GR_R10,
1142 regbuf, 4);
1143
1144 /* We ignore a SA_SIGINFO flag in the sigaction call; the code I
1145 needed all this for, specifies a SA_SIGINFO call but treats it
1146 like an ordinary sighandler; only the signal number argument is
1147 inspected. To make future need to implement SA_SIGINFO
1148 correctly possible, we set the siginfo argument register to a
1149 magic (hopefully non-address) number. (NB: then, you should
1150 just need to pass the siginfo argument; it seems you probably
1151 don't need to implement the specific rt_sigreturn.) */
1152 bfd_putl32 (0xbad5161f, regbuf);
1153 (*CPU_REG_STORE (current_cpu)) (current_cpu, H_GR_R11,
1154 regbuf, 4);
1155
1156 /* The third argument is unused and the kernel sets it to 0. */
1157 bfd_putl32 (0, regbuf);
1158 (*CPU_REG_STORE (current_cpu)) (current_cpu, H_GR_R12,
1159 regbuf, 4);
1160 return;
1161 }
1162
1163 /* No, there actually was no pending signal for this thread. Reset
1164 this flag. */
1165 current_cpu->thread_data[next].sigpending = 0;
1166 }
1167}
1168
1169/* Reschedule the simplest possible way until something else is absolutely
1170 necessary:
1171 - A. Find the next process (round-robin) that doesn't have at_syscall
1172 set, schedule it.
1173 - B. If there is none, just run the next process, round-robin.
1174 - Clear at_syscall for the current process. */
1175
1176static void
1177reschedule (SIM_CPU *current_cpu)
1178{
1179 int i;
1180
1181 /* Iterate over all thread slots, because after a few thread creations
1182 and exits, we don't know where the live ones are. */
1183 for (i = (current_cpu->threadno + 1) % SIM_TARGET_MAX_THREADS;
1184 i != current_cpu->threadno;
1185 i = (i + 1) % SIM_TARGET_MAX_THREADS)
1186 if (current_cpu->thread_data[i].cpu_context
1187 && current_cpu->thread_data[i].at_syscall == 0)
1188 {
1189 schedule (current_cpu, i);
1190 return;
1191 }
1192
1193 /* Pick any next live thread. */
1194 for (i = (current_cpu->threadno + 1) % SIM_TARGET_MAX_THREADS;
1195 i != current_cpu->threadno;
1196 i = (i + 1) % SIM_TARGET_MAX_THREADS)
1197 if (current_cpu->thread_data[i].cpu_context)
1198 {
1199 schedule (current_cpu, i);
1200 return;
1201 }
1202
1203 /* More than one live thread, but we couldn't find the next one? */
1204 abort ();
1205}
1206
1207/* Set up everything to receive (or IGN) an incoming signal to the
1208 current context. */
1209
1210static int
1211deliver_signal (SIM_CPU *current_cpu, int sig, unsigned int pid)
1212{
1213 int i;
1214 USI pc = sim_pc_get (current_cpu);
1215
1216 /* Find the thread index of the pid. */
1217 for (i = 0; i < SIM_TARGET_MAX_THREADS; i++)
1218 /* Apparently it's ok to send signals to zombies (so a check for
1219 current_cpu->thread_data[i].cpu_context != NULL would be
1220 wrong). */
1221 if (current_cpu->thread_data[i].threadid == pid - TARGET_PID)
1222 {
1223 if (sig < 64)
1224 switch (current_cpu->sighandler[sig])
1225 {
1226 case TARGET_SIG_DFL:
1227 switch (sig)
1228 {
1229 /* The following according to the glibc
1230 documentation. (The kernel code has non-obvious
1231 execution paths.) */
1232 case TARGET_SIGFPE:
1233 case TARGET_SIGILL:
1234 case TARGET_SIGSEGV:
1235 case TARGET_SIGBUS:
1236 case TARGET_SIGABRT:
1237 case TARGET_SIGTRAP:
1238 case TARGET_SIGSYS:
1239
1240 case TARGET_SIGTERM:
1241 case TARGET_SIGINT:
1242 case TARGET_SIGQUIT:
1243 case TARGET_SIGKILL:
1244 case TARGET_SIGHUP:
1245
1246 case TARGET_SIGALRM:
1247 case TARGET_SIGVTALRM:
1248 case TARGET_SIGPROF:
1249 case TARGET_SIGSTOP:
1250
1251 case TARGET_SIGPIPE:
1252 case TARGET_SIGLOST:
1253 case TARGET_SIGXCPU:
1254 case TARGET_SIGXFSZ:
1255 case TARGET_SIGUSR1:
1256 case TARGET_SIGUSR2:
1257 sim_io_eprintf (CPU_STATE (current_cpu),
1258 "Exiting pid %d due to signal %d\n",
1259 pid, sig);
1260 sim_engine_halt (CPU_STATE (current_cpu), current_cpu,
1261 NULL, pc, sim_stopped,
1262 sig == TARGET_SIGABRT
1263 ? SIM_SIGABRT : SIM_SIGILL);
1264 return 0;
1265
1266 /* The default for all other signals is to be ignored. */
1267 default:
1268 return 0;
1269 }
1270
1271 case TARGET_SIG_IGN:
1272 switch (sig)
1273 {
1274 case TARGET_SIGKILL:
1275 case TARGET_SIGSTOP:
1276 /* Can't ignore these signals. */
1277 sim_io_eprintf (CPU_STATE (current_cpu),
1278 "Exiting pid %d due to signal %d\n",
1279 pid, sig);
1280 sim_engine_halt (CPU_STATE (current_cpu), current_cpu,
1281 NULL, pc, sim_stopped, SIM_SIGILL);
1282 return 0;
1283
1284 default:
1285 return 0;
1286 }
1287 break;
1288
1289 default:
1290 /* Mark the signal as pending, making schedule () check
1291 closer. The signal will be handled when the thread is
1292 scheduled and the signal is unblocked. */
1293 current_cpu->thread_data[i].sigdata[sig].pending = 1;
1294 current_cpu->thread_data[i].sigpending = 1;
1295 return 0;
1296 }
1297 else
1298 {
1299 sim_io_eprintf (CPU_STATE (current_cpu),
1300 "Unimplemented signal: %d\n", sig);
1301 sim_engine_halt (CPU_STATE (current_cpu), current_cpu, NULL, pc,
1302 sim_stopped, SIM_SIGILL);
1303 }
1304 }
1305
1306 return
1307 -cb_host_to_target_errno (STATE_CALLBACK (CPU_STATE (current_cpu)),
1308 ESRCH);
1309}
1310
1311/* Make the vector and the first item, the main thread. */
1312
1313static void
1314make_first_thread (SIM_CPU *current_cpu)
1315{
1316 current_cpu->thread_data
1317 = xcalloc (1,
1318 SIM_TARGET_MAX_THREADS
1319 * sizeof (current_cpu->thread_data[0]));
1320 current_cpu->thread_data[0].cpu_context
1321 = (*current_cpu->make_thread_cpu_data) (current_cpu,
1322 &current_cpu
1323 ->cpu_data_placeholder);
1324 current_cpu->thread_data[0].parent_threadid = -1;
1325
1326 /* For good measure. */
1327 if (TARGET_SIG_DFL != 0)
1328 abort ();
1329}
1330
1331/* Main function: the handler of the "break 13" syscall insn. */
1332
1333USI
1334cris_break_13_handler (SIM_CPU *current_cpu, USI callnum, USI arg1,
1335 USI arg2, USI arg3, USI arg4, USI arg5, USI arg6,
1336 USI pc)
1337{
1338 CB_SYSCALL s;
1339 SIM_DESC sd = CPU_STATE (current_cpu);
1340 host_callback *cb = STATE_CALLBACK (sd);
1341 int retval;
1342 int threadno = current_cpu->threadno;
1343
1344 current_cpu->syscalls++;
1345
1346 CB_SYSCALL_INIT (&s);
1347 s.func = callnum;
1348 s.arg1 = arg1;
1349 s.arg2 = arg2;
1350 s.arg3 = arg3;
1351
1352 if (callnum == TARGET_SYS_exit && current_cpu->m1threads == 0)
1353 {
1354 if (CPU_CRIS_MISC_PROFILE (current_cpu)->flags
1355 & FLAG_CRIS_MISC_PROFILE_ALL)
1356 dump_statistics (current_cpu);
1357 sim_engine_halt (sd, current_cpu, NULL, pc, sim_exited, arg1);
1358 }
1359
1360 s.p1 = (PTR) sd;
1361 s.p2 = (PTR) current_cpu;
1362 s.read_mem = syscall_read_mem;
1363 s.write_mem = syscall_write_mem;
1364
1365 current_cpu_for_cb_callback = current_cpu;
1366
1367 if (cb_syscall (cb, &s) != CB_RC_OK)
1368 {
1369 abort ();
1370 sim_io_eprintf (sd, "Break 13: invalid %d? Returned %ld\n", callnum,
1371 s.result);
1372 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGILL);
1373 }
1374
1375 retval = s.result == -1 ? -s.errcode : s.result;
1376
1377 if (s.errcode != 0 && s.errcode == cb_host_to_target_errno (cb, ENOSYS))
1378 {
1379 /* If the generic simulator call said ENOSYS, then let's try the
1380 ones we know ourselves.
1381
1382 The convention is to provide *very limited* functionality on an
1383 as-needed basis, only what's covered by the test-suite, tests
1384 added when functionality changes and abort with a descriptive
1385 message for *everything* else. Where there's no test-case, we
1386 just abort. */
1387 switch (callnum)
1388 {
1389 case 0:
1390 /* It's a pretty safe bet that the "old setup() system call"
1391 number will not be re-used; we can't say the same for higher
1392 numbers. We treat this simulator-generated call as "wait
1393 forever"; we re-run this insn. The wait is ended by a
1394 callback. Sanity check that this is the reason we got
1395 here. */
1396 if (current_cpu->thread_data == NULL
1397 || (current_cpu->thread_data[threadno].pipe_write_fd == 0))
1398 goto unimplemented_syscall;
1399
1400 sim_pc_set (current_cpu, pc);
1401 retval = arg1;
1402 break;
1403
1404 case TARGET_SYS_fcntl64:
1405 case TARGET_SYS_fcntl:
ed1f044a 1406 switch (arg2)
f6bcefef 1407 {
ed1f044a 1408 case 1:
f6bcefef
HPN
1409 /* F_GETFD.
1410 Glibc checks stdin, stdout and stderr fd:s for
1411 close-on-exec security sanity. We just need to provide a
1412 OK return value. If we really need to have a
1413 close-on-exec flag true, we could just do a real fcntl
1414 here. */
1415 retval = 0;
ed1f044a
HPN
1416 break;
1417
1418 case 2:
f6bcefef
HPN
1419 /* F_SETFD. Just ignore attempts to set the close-on-exec
1420 flag. */
1421 retval = 0;
ed1f044a
HPN
1422 break;
1423
1424 case 3:
1425 /* F_GETFL. Check for the special case for open+fdopen. */
1426 if (current_cpu->last_syscall == TARGET_SYS_open
1427 && arg1 == current_cpu->last_open_fd)
1428 {
1429 retval = current_cpu->last_open_flags & TARGET_O_ACCMODE;
1430 break;
1431 }
1432 /* FALLTHROUGH */
1433 /* Abort for all other cases. */
1434 default:
1435 sim_io_eprintf (sd, "Unimplemented %s syscall "
1436 "(fd: 0x%lx: cmd: 0x%lx arg: 0x%lx)\n",
1437 callnum == TARGET_SYS_fcntl
1438 ? "fcntl" : "fcntl64",
1439 (unsigned long) (USI) arg1,
1440 (unsigned long) (USI) arg2,
1441 (unsigned long) (USI) arg3);
1442 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
1443 SIM_SIGILL);
1444 break;
f6bcefef
HPN
1445 }
1446 break;
1447
1448 case TARGET_SYS_uname:
1449 {
1450 /* Fill in a few constants to appease glibc. */
1451 static const char sim_utsname[6][65] =
1452 {
1453 "Linux",
1454 "sim-target",
1455 "2.4.5",
1456 TARGET_UTSNAME,
1457 "cris",
1458 "localdomain"
1459 };
1460
1461 if ((s.write_mem) (cb, &s, arg1, (const char *) sim_utsname,
1462 sizeof (sim_utsname))
1463 != sizeof (sim_utsname))
1464 retval = -cb_host_to_target_errno (cb, EFAULT);
1465 else
1466 retval = 0;
1467 break;
1468 }
1469
1470 case TARGET_SYS_geteuid32:
1471 /* We tell the truth with these. Maybe we shouldn't, but it
1472 should match the "stat" information. */
1473 retval = geteuid ();
1474 break;
1475
1476 case TARGET_SYS_getuid32:
1477 retval = getuid ();
1478 break;
1479
1480 case TARGET_SYS_getegid32:
1481 retval = getegid ();
1482 break;
1483
1484 case TARGET_SYS_getgid32:
1485 retval = getgid ();
1486 break;
1487
1488 case TARGET_SYS_brk:
1489 /* Most often, we just return the argument, like the Linux
1490 kernel. */
1491 retval = arg1;
1492
1493 if (arg1 == 0)
1494 retval = current_cpu->endbrk;
1495 else if (arg1 <= current_cpu->endmem)
1496 current_cpu->endbrk = arg1;
1497 else
1498 {
1499 USI new_end = (arg1 + 8191) & ~8191;
1500
1501 /* If the simulator wants to brk more than a certain very
1502 large amount, something is wrong. FIXME: Return an error
1503 or abort? Have command-line selectable? */
1504 if (new_end - current_cpu->endmem > SIM_MAX_ALLOC_CHUNK)
1505 {
1506 current_cpu->endbrk = current_cpu->endmem;
1507 retval = current_cpu->endmem;
1508 break;
1509 }
1510
1511 sim_core_attach (sd, NULL, 0, access_read_write_exec, 0,
1512 current_cpu->endmem,
1513 new_end - current_cpu->endmem,
1514 0, NULL, NULL);
1515 current_cpu->endbrk = arg1;
1516 current_cpu->endmem = new_end;
1517 }
1518 break;
1519
1520 case TARGET_SYS_getpid:
1521 /* Correct until CLONE_THREAD is implemented. */
1522 retval = current_cpu->thread_data == NULL
1523 ? TARGET_PID
1524 : TARGET_PID + current_cpu->thread_data[threadno].threadid;
1525 break;
1526
1527 case TARGET_SYS_getppid:
1528 /* Correct until CLONE_THREAD is implemented. */
1529 retval = current_cpu->thread_data == NULL
1530 ? TARGET_PID - 1
1531 : (TARGET_PID
1532 + current_cpu->thread_data[threadno].parent_threadid);
1533 break;
1534
1535 case TARGET_SYS_mmap2:
1536 {
1537 USI addr = arg1;
1538 USI len = arg2;
1539 USI prot = arg3;
1540 USI flags = arg4;
1541 USI fd = arg5;
1542 USI pgoff = arg6;
1543
1544 /* If the simulator wants to mmap more than the very large
1545 limit, something is wrong. FIXME: Return an error or
1546 abort? Have command-line selectable? */
1547 if (len > SIM_MAX_ALLOC_CHUNK)
1548 {
1549 retval = -cb_host_to_target_errno (cb, ENOMEM);
1550 break;
1551 }
1552
1553 if ((prot != (TARGET_PROT_READ | TARGET_PROT_WRITE)
1554 && (prot
1555 != (TARGET_PROT_READ
1556 | TARGET_PROT_WRITE
1557 | TARGET_PROT_EXEC))
1558 && prot != TARGET_PROT_READ)
1559 || (flags != (TARGET_MAP_ANONYMOUS | TARGET_MAP_PRIVATE)
1560 && flags != TARGET_MAP_PRIVATE
1561 && flags != TARGET_MAP_SHARED)
1562 || (fd != (USI) -1 && prot != TARGET_PROT_READ)
69308976 1563 || pgoff != 0)
f6bcefef
HPN
1564 {
1565 sim_io_eprintf (sd, "Unimplemented mmap2 call "
1566 "(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
1567 (unsigned long) arg1,
1568 (unsigned long) arg2,
1569 (unsigned long) arg3,
1570 (unsigned long) arg4,
1571 (unsigned long) arg5,
1572 (unsigned long) arg6);
1573 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
1574 SIM_SIGILL);
1575 break;
1576 }
1577 else if (fd != (USI) -1)
1578 {
1579 /* Map a file. */
1580
1581 USI newaddr;
1582 USI pos;
1583
1584 /* A non-aligned argument is allowed for files. */
1585 USI newlen = (len + 8191) & ~8191;
1586
1587 /* We only support read, which we should already have
1588 checked. Check again anyway. */
1589 if (prot != TARGET_PROT_READ)
1590 abort ();
1591
1592 newaddr
1593 = create_map (sd, &current_cpu->highest_mmapped_page, addr,
1594 newlen);
1595
1596 if (newaddr >= (USI) -8191)
1597 {
1598 abort ();
1599 retval = -cb_host_to_target_errno (cb, -(SI) newaddr);
1600 break;
1601 }
1602
1603 /* Find the current position in the file. */
1604 s.func = TARGET_SYS_lseek;
1605 s.arg1 = fd;
1606 s.arg2 = 0;
1607 s.arg3 = SEEK_CUR;
1608 if (cb_syscall (cb, &s) != CB_RC_OK)
1609 abort ();
1610 pos = s.result;
1611
1612 if (s.result < 0)
1613 abort ();
1614
1615 /* Use the standard read callback to read in "len"
1616 bytes. */
1617 s.func = TARGET_SYS_read;
1618 s.arg1 = fd;
1619 s.arg2 = newaddr;
1620 s.arg3 = len;
1621 if (cb_syscall (cb, &s) != CB_RC_OK)
1622 abort ();
1623
1624 if ((USI) s.result != len)
1625 abort ();
1626
1627 /* After reading, we need to go back to the previous
1628 position in the file. */
1629 s.func = TARGET_SYS_lseek;
1630 s.arg1 = fd;
1631 s.arg2 = pos;
1632 s.arg3 = SEEK_SET;
1633 if (cb_syscall (cb, &s) != CB_RC_OK)
1634 abort ();
1635 if (pos != (USI) s.result)
1636 abort ();
1637
1638 retval = newaddr;
1639 }
1640 else
1641 {
1642 USI newaddr
69308976
HPN
1643 = create_map (sd, &current_cpu->highest_mmapped_page, addr,
1644 (len + 8191) & ~8191);
f6bcefef
HPN
1645
1646 if (newaddr >= (USI) -8191)
1647 retval = -cb_host_to_target_errno (cb, -(SI) newaddr);
1648 else
1649 retval = newaddr;
1650 }
1651 break;
1652 }
1653
1654 case TARGET_SYS_mprotect:
1655 {
1656 /* We only cover the case of linuxthreads mprotecting out its
1657 stack guard page. */
1658 USI addr = arg1;
1659 USI len = arg2;
1660 USI prot = arg3;
1661
1662 if ((addr & 8191) != 0
1663 || len != 8192
1664 || prot != TARGET_PROT_NONE
1665 || !is_mapped (sd, &current_cpu->highest_mmapped_page, addr,
1666 len))
1667 {
1668 sim_io_eprintf (sd, "Unimplemented mprotect call "
1669 "(0x%lx, 0x%lx, 0x%lx)\n",
1670 (unsigned long) arg1,
1671 (unsigned long) arg2,
1672 (unsigned long) arg3);
1673 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
1674 SIM_SIGILL);
1675 break;
1676 }
1677
1678 /* FIXME: We should account for pages like this that are
1679 "mprotected out". For now, we just tell the simulator
1680 core to remove that page from its map. */
1681 sim_core_detach (sd, NULL, 0, 0, addr);
1682 retval = 0;
1683 break;
1684 }
1685
1686 case TARGET_SYS_ioctl:
1687 {
1688 /* We support only a very limited functionality: checking
1689 stdout with TCGETS to perform the isatty function. The
1690 TCGETS ioctl isn't actually performed or the result used by
1691 an isatty () caller in a "hello, world" program; only the
1692 return value is then used. Maybe we shouldn't care about
1693 the environment of the simulator regarding isatty, but
1694 that's been working before, in the xsim simulator. */
1695 if (arg2 == TARGET_TCGETS && arg1 == 1)
1696 retval = isatty (1) ? 0 : cb_host_to_target_errno (cb, EINVAL);
1697 else
1698 retval = -cb_host_to_target_errno (cb, EINVAL);
1699 break;
1700 }
1701
1702 case TARGET_SYS_munmap:
1703 {
1704 USI addr = arg1;
1705 USI len = arg2;
1706 USI result
1707 = unmap_pages (sd, &current_cpu->highest_mmapped_page, addr,
1708 len);
1709 retval = result != 0 ? -cb_host_to_target_errno (cb, result) : 0;
1710 break;
1711 }
1712
1713 case TARGET_SYS_wait4:
1714 {
1715 int i;
1716 USI pid = arg1;
1717 USI saddr = arg2;
1718 USI options = arg3;
1719 USI rusagep = arg4;
1720
1721 /* FIXME: We're not properly implementing __WCLONE, and we
1722 don't really need the special casing so we might as well
1723 make this general. */
1724 if ((!(pid == (USI) -1
1725 && options == (TARGET___WCLONE | TARGET_WNOHANG)
1726 && saddr != 0)
1727 && !(pid > 0
1728 && (options == TARGET___WCLONE
1729 || options == TARGET___WALL)))
1730 || rusagep != 0
1731 || current_cpu->thread_data == NULL)
1732 {
1733 sim_io_eprintf (sd, "Unimplemented wait4 call "
1734 "(0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
1735 (unsigned long) arg1,
1736 (unsigned long) arg2,
1737 (unsigned long) arg3,
1738 (unsigned long) arg4);
1739 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
1740 SIM_SIGILL);
1741 break;
1742 }
1743
1744 if (pid == (USI) -1)
1745 for (i = 1; i < SIM_TARGET_MAX_THREADS; i++)
1746 {
1747 if (current_cpu->thread_data[threadno].threadid
1748 == current_cpu->thread_data[i].parent_threadid
1749 && current_cpu->thread_data[i].threadid != 0
1750 && current_cpu->thread_data[i].cpu_context == NULL)
1751 {
1752 /* A zombied child. Get the exit value and clear the
1753 zombied entry so it will be reused. */
1754 sim_core_write_unaligned_4 (current_cpu, pc, 0, saddr,
1755 current_cpu
1756 ->thread_data[i].exitval);
1757 retval
1758 = current_cpu->thread_data[i].threadid + TARGET_PID;
1759 memset (&current_cpu->thread_data[i], 0,
1760 sizeof (current_cpu->thread_data[i]));
1761 goto outer_break;
1762 }
1763 }
1764 else
1765 {
1766 /* We're waiting for a specific PID. If we don't find
1767 it zombied on this run, rerun the syscall. */
1768 for (i = 1; i < SIM_TARGET_MAX_THREADS; i++)
1769 if (pid == current_cpu->thread_data[i].threadid + TARGET_PID
1770 && current_cpu->thread_data[i].cpu_context == NULL)
1771 {
1772 if (saddr != 0)
1773 /* Get the exit value if the caller wants it. */
1774 sim_core_write_unaligned_4 (current_cpu, pc, 0,
1775 saddr,
1776 current_cpu
1777 ->thread_data[i]
1778 .exitval);
1779
1780 retval
1781 = current_cpu->thread_data[i].threadid + TARGET_PID;
1782 memset (&current_cpu->thread_data[i], 0,
1783 sizeof (current_cpu->thread_data[i]));
1784
1785 goto outer_break;
1786 }
1787
1788 sim_pc_set (current_cpu, pc);
1789 }
1790
1791 retval = -cb_host_to_target_errno (cb, ECHILD);
1792 outer_break:
1793 break;
1794 }
1795
1796 case TARGET_SYS_rt_sigaction:
1797 {
1798 USI signum = arg1;
1799 USI old_sa = arg3;
1800 USI new_sa = arg2;
1801
1802 /* The kernel says:
1803 struct sigaction {
1804 __sighandler_t sa_handler;
1805 unsigned long sa_flags;
1806 void (*sa_restorer)(void);
1807 sigset_t sa_mask;
1808 }; */
1809
1810 if (old_sa != 0)
1811 {
1812 sim_core_write_unaligned_4 (current_cpu, pc, 0, old_sa + 0,
1813 current_cpu->sighandler[signum]);
1814 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg3 + 4, 0);
1815 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg3 + 8, 0);
1816
1817 /* We'll assume _NSIG_WORDS is 2 for the kernel. */
1818 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg3 + 12, 0);
1819 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg3 + 16, 0);
1820 }
1821 if (new_sa != 0)
1822 {
2ecb8390 1823 USI target_sa_handler
f6bcefef 1824 = sim_core_read_unaligned_4 (current_cpu, pc, 0, new_sa);
2ecb8390 1825 USI target_sa_flags
f6bcefef 1826 = sim_core_read_unaligned_4 (current_cpu, pc, 0, new_sa + 4);
2ecb8390 1827 USI target_sa_restorer
f6bcefef 1828 = sim_core_read_unaligned_4 (current_cpu, pc, 0, new_sa + 8);
2ecb8390 1829 USI target_sa_mask_low
f6bcefef 1830 = sim_core_read_unaligned_4 (current_cpu, pc, 0, new_sa + 12);
2ecb8390 1831 USI target_sa_mask_high
f6bcefef
HPN
1832 = sim_core_read_unaligned_4 (current_cpu, pc, 0, new_sa + 16);
1833
1834 /* We won't interrupt a syscall so we won't restart it,
1835 but a signal(2) call ends up syscalling rt_sigaction
1836 with this flag, so we have to handle it. The
1837 sa_restorer field contains garbage when not
1838 TARGET_SA_RESTORER, so don't look at it. For the
1839 time being, we don't nest sighandlers, so we
1840 ignore the sa_mask, which simplifies things. */
2ecb8390
HPN
1841 if ((target_sa_flags != 0
1842 && target_sa_flags != TARGET_SA_RESTART
1843 && target_sa_flags != (TARGET_SA_RESTART|TARGET_SA_SIGINFO))
1844 || target_sa_handler == 0)
f6bcefef
HPN
1845 {
1846 sim_io_eprintf (sd, "Unimplemented rt_sigaction "
1847 "syscall (0x%lx, "
1848 "0x%lx: [0x%x, 0x%x, 0x%x, "
1849 "{0x%x, 0x%x}], "
1850 "0x%lx)\n",
1851 (unsigned long) arg1,
1852 (unsigned long) arg2,
2ecb8390
HPN
1853 target_sa_handler, target_sa_flags,
1854 target_sa_restorer,
1855 target_sa_mask_low, target_sa_mask_high,
f6bcefef
HPN
1856 (unsigned long) arg3);
1857 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
1858 SIM_SIGILL);
1859 }
1860
2ecb8390 1861 current_cpu->sighandler[signum] = target_sa_handler;
f6bcefef
HPN
1862
1863 /* Because we may have unblocked signals, one may now be
1864 pending, if there are threads, that is. */
1865 if (current_cpu->thread_data)
1866 current_cpu->thread_data[threadno].sigpending = 1;
1867 }
1868 retval = 0;
1869 break;
1870 }
1871
1872 case TARGET_SYS_mremap:
1873 {
1874 USI addr = arg1;
1875 USI old_len = arg2;
1876 USI new_len = arg3;
1877 USI flags = arg4;
1878 USI new_addr = arg5;
1879 USI mapped_addr;
1880
1881 if (new_len == old_len)
1882 /* The program and/or library is possibly confused but
1883 this is a valid call. Happens with ipps-1.40 on file
1884 svs_all. */
1885 retval = addr;
1886 else if (new_len < old_len)
1887 {
1888 /* Shrinking is easy. */
1889 if (unmap_pages (sd, &current_cpu->highest_mmapped_page,
1890 addr + new_len, old_len - new_len) != 0)
1891 retval = -cb_host_to_target_errno (cb, EINVAL);
1892 else
1893 retval = addr;
1894 }
1895 else if (! is_mapped (sd, &current_cpu->highest_mmapped_page,
1896 addr + old_len, new_len - old_len))
1897 {
1898 /* If the extension isn't mapped, we can just add it. */
1899 mapped_addr
1900 = create_map (sd, &current_cpu->highest_mmapped_page,
1901 addr + old_len, new_len - old_len);
1902
1903 if (mapped_addr > (USI) -8192)
1904 retval = -cb_host_to_target_errno (cb, -(SI) mapped_addr);
1905 else
1906 retval = addr;
1907 }
1908 else if (flags & TARGET_MREMAP_MAYMOVE)
1909 {
1910 /* Create a whole new map and copy the contents
1911 block-by-block there. We ignore the new_addr argument
1912 for now. */
1913 char buf[8192];
1914 USI prev_addr = addr;
1915 USI prev_len = old_len;
1916
1917 mapped_addr
1918 = create_map (sd, &current_cpu->highest_mmapped_page,
1919 0, new_len);
1920
1921 if (mapped_addr > (USI) -8192)
1922 {
1923 retval = -cb_host_to_target_errno (cb, -(SI) new_addr);
1924 break;
1925 }
1926
1927 retval = mapped_addr;
1928
1929 for (; old_len > 0;
1930 old_len -= 8192, mapped_addr += 8192, addr += 8192)
1931 {
1932 if (sim_core_read_buffer (sd, current_cpu, read_map, buf,
1933 addr, 8192) != 8192
1934 || sim_core_write_buffer (sd, current_cpu, 0, buf,
1935 mapped_addr, 8192) != 8192)
1936 abort ();
1937 }
1938
1939 if (unmap_pages (sd, &current_cpu->highest_mmapped_page,
1940 prev_addr, prev_len) != 0)
1941 abort ();
1942 }
1943 else
1944 retval = -cb_host_to_target_errno (cb, -ENOMEM);
1945 break;
1946 }
1947
1948 case TARGET_SYS_poll:
1949 {
1950 int npollfds = arg2;
1951 int timeout = arg3;
1952 SI ufds = arg1;
1953 SI fd = -1;
1954 HI events = -1;
1955 HI revents = 0;
1956 struct stat buf;
1957 int i;
1958
1959 /* The kernel says:
1960 struct pollfd {
1961 int fd;
1962 short events;
1963 short revents;
1964 }; */
1965
1966 /* Check that this is the expected poll call from
1967 linuxthreads/manager.c; we don't support anything else.
1968 Remember, fd == 0 isn't supported. */
1969 if (npollfds != 1
1970 || ((fd = sim_core_read_unaligned_4 (current_cpu, pc,
1971 0, ufds)) <= 0)
1972 || ((events = sim_core_read_unaligned_2 (current_cpu, pc,
1973 0, ufds + 4))
1974 != TARGET_POLLIN)
1975 || ((cb->fstat) (cb, fd, &buf) != 0
1976 || (buf.st_mode & S_IFIFO) == 0)
1977 || current_cpu->thread_data == NULL)
1978 {
1979 sim_io_eprintf (sd, "Unimplemented poll syscall "
1980 "(0x%lx: [0x%x, 0x%x, x], 0x%lx, 0x%lx)\n",
1981 (unsigned long) arg1, fd, events,
1982 (unsigned long) arg2, (unsigned long) arg3);
1983 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGILL);
1984 break;
1985 }
1986
1987 retval = 0;
1988
1989 /* Iterate over threads; find a marker that a writer is
1990 sleeping, waiting for a reader. */
1991 for (i = 0; i < SIM_TARGET_MAX_THREADS; i++)
1992 if (current_cpu->thread_data[i].cpu_context != NULL
1993 && current_cpu->thread_data[i].pipe_read_fd == fd)
1994 {
1995 revents = TARGET_POLLIN;
1996 retval = 1;
1997 break;
1998 }
1999
2000 /* Timeout decreases with whatever time passed between the
2001 last syscall and this. That's not exactly right for the
2002 first call, but it's close enough that it isn't
2003 worthwhile to complicate matters by making that a special
2004 case. */
2005 timeout
2006 -= (TARGET_TIME_MS (current_cpu)
2007 - (current_cpu->thread_data[threadno].last_execution));
2008
2009 /* Arrange to repeat this syscall until timeout or event,
2010 decreasing timeout at each iteration. */
2011 if (timeout > 0 && revents == 0)
2012 {
2013 bfd_byte timeout_buf[4];
2014
2015 bfd_putl32 (timeout, timeout_buf);
2016 (*CPU_REG_STORE (current_cpu)) (current_cpu,
2017 H_GR_R12, timeout_buf, 4);
2018 sim_pc_set (current_cpu, pc);
2019 retval = arg1;
2020 break;
2021 }
2022
2023 sim_core_write_unaligned_2 (current_cpu, pc, 0, ufds + 4 + 2,
2024 revents);
2025 break;
2026 }
2027
2028 case TARGET_SYS_gettimeofday:
2029 if (arg1 != 0)
2030 {
2031 USI ts = TARGET_TIME (current_cpu);
2032 USI tms = TARGET_TIME_MS (current_cpu);
2033
2034 /* First dword is seconds since TARGET_EPOCH. */
2035 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg1, ts);
2036
2037 /* Second dword is microseconds. */
2038 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg1 + 4,
2039 (tms % 1000) * 1000);
2040 }
2041 if (arg2 != 0)
2042 {
2043 /* Time-zone info is always cleared. */
2044 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg2, 0);
2045 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg2 + 4, 0);
2046 }
2047 retval = 0;
2048 break;
2049
2050 case TARGET_SYS_llseek:
2051 {
2052 /* If it fits, tweak parameters to fit the "generic" 32-bit
2053 lseek and use that. */
2054 SI fd = arg1;
2055 SI offs_hi = arg2;
2056 SI offs_lo = arg3;
2057 SI resultp = arg4;
2058 SI whence = arg5;
2059 retval = 0;
2060
2061 if (!((offs_hi == 0 && offs_lo >= 0)
2062 || (offs_hi == -1 && offs_lo < 0)))
2063 {
2064 sim_io_eprintf (sd,
2065 "Unimplemented llseek offset,"
2066 " fd %d: 0x%x:0x%x\n",
2067 fd, (unsigned) arg2, (unsigned) arg3);
2068 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2069 SIM_SIGILL);
2070 }
2071
2072 s.func = TARGET_SYS_lseek;
2073 s.arg2 = offs_lo;
2074 s.arg3 = whence;
2075 if (cb_syscall (cb, &s) != CB_RC_OK)
2076 {
2077 sim_io_eprintf (sd, "Break 13: invalid %d? Returned %ld\n", callnum,
2078 s.result);
2079 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped, SIM_SIGILL);
2080 }
2081 if (s.result < 0)
2082 retval = -s.errcode;
2083 else
2084 {
2085 sim_core_write_unaligned_4 (current_cpu, pc, 0, resultp,
2086 s.result);
2087 sim_core_write_unaligned_4 (current_cpu, pc, 0, resultp + 4,
2088 s.result < 0 ? -1 : 0);
2089 }
2090 break;
2091 }
2092
2093 /* This one does have a generic callback function, but at the time
2094 of this writing, cb_syscall does not have code for it, and we
2095 need target-specific code for the threads implementation
2096 anyway. */
2097 case TARGET_SYS_kill:
2098 {
2099 USI pid = arg1;
2100 USI sig = arg2;
2101
2102 retval = 0;
2103
2104 /* At kill(2), glibc sets signal masks such that the thread
2105 machinery is initialized. Still, there is and was only
2106 one thread. */
2107 if (current_cpu->max_threadid == 0)
2108 {
2109 if (pid != TARGET_PID)
2110 {
2111 retval = -cb_host_to_target_errno (cb, EPERM);
2112 break;
2113 }
2114
2115 /* FIXME: Signal infrastructure (target-to-sim mapping). */
2116 if (sig == TARGET_SIGABRT)
2117 /* A call "abort ()", i.e. "kill (getpid(), SIGABRT)" is
2118 the end-point for failing GCC test-cases. */
2119 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2120 SIM_SIGABRT);
2121 else
2122 {
2123 sim_io_eprintf (sd, "Unimplemented signal: %d\n", sig);
2124 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2125 SIM_SIGILL);
2126 }
2127
2128 /* This will not be reached. */
2129 abort ();
2130 }
2131 else
2132 retval = deliver_signal (current_cpu, sig, pid);
2133 break;
2134 }
2135
2136 case TARGET_SYS_rt_sigprocmask:
2137 {
2138 int i;
2139 USI how = arg1;
2140 USI newsetp = arg2;
2141 USI oldsetp = arg3;
2142
2143 if (how != TARGET_SIG_BLOCK
2144 && how != TARGET_SIG_SETMASK
2145 && how != TARGET_SIG_UNBLOCK)
2146 {
2147 sim_io_eprintf (sd, "Unimplemented rt_sigprocmask syscall "
2148 "(0x%x, 0x%x, 0x%x)\n", arg1, arg2, arg3);
2149 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2150 SIM_SIGILL);
2151 retval = 0;
2152 break;
2153 }
2154
2155 if (newsetp)
2156 {
2157 USI set_low
2158 = sim_core_read_unaligned_4 (current_cpu, pc, 0,
2159 newsetp);
2160 USI set_high
2161 = sim_core_read_unaligned_4 (current_cpu, pc, 0,
2162 newsetp + 4);
2163
2164 /* The sigmask is kept in the per-thread data, so we may
2165 need to create the first one. */
2166 if (current_cpu->thread_data == NULL)
2167 make_first_thread (current_cpu);
2168
2169 if (how == TARGET_SIG_SETMASK)
2170 for (i = 0; i < 64; i++)
2171 current_cpu->thread_data[threadno].sigdata[i].blocked = 0;
2172
2173 for (i = 0; i < 32; i++)
2174 if ((set_low & (1 << i)))
2175 current_cpu->thread_data[threadno].sigdata[i + 1].blocked
2176 = (how != TARGET_SIG_UNBLOCK);
2177
2178 for (i = 0; i < 31; i++)
2179 if ((set_high & (1 << i)))
2180 current_cpu->thread_data[threadno].sigdata[i + 33].blocked
2181 = (how != TARGET_SIG_UNBLOCK);
2182
2183 /* The mask changed, so a signal may be unblocked for
2184 execution. */
2185 current_cpu->thread_data[threadno].sigpending = 1;
2186 }
2187
2188 if (oldsetp != 0)
2189 {
2190 USI set_low = 0;
2191 USI set_high = 0;
2192
2193 for (i = 0; i < 32; i++)
2194 if (current_cpu->thread_data[threadno]
2195 .sigdata[i + 1].blocked)
2196 set_low |= 1 << i;
2197 for (i = 0; i < 31; i++)
2198 if (current_cpu->thread_data[threadno]
2199 .sigdata[i + 33].blocked)
2200 set_high |= 1 << i;
2201
2202 sim_core_write_unaligned_4 (current_cpu, pc, 0, oldsetp + 0, set_low);
2203 sim_core_write_unaligned_4 (current_cpu, pc, 0, oldsetp + 4, set_high);
2204 }
2205
2206 retval = 0;
2207 break;
2208 }
2209
2210 case TARGET_SYS_sigreturn:
2211 {
2212 int i;
2213 bfd_byte regbuf[4];
2214 int was_sigsuspended;
2215
2216 if (current_cpu->thread_data == NULL
2217 /* The CPU context is saved with the simulator data, not
2218 on the stack as in the real world. */
2219 || (current_cpu->thread_data[threadno].cpu_context_atsignal
2220 == NULL))
2221 {
2222 sim_io_eprintf (sd, "Invalid sigreturn syscall: no signal"
2223 " handler active "
2224 "(0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
2225 (unsigned long) arg1,
2226 (unsigned long) arg2,
2227 (unsigned long) arg3,
2228 (unsigned long) arg4,
2229 (unsigned long) arg5,
2230 (unsigned long) arg6);
2231 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2232 SIM_SIGILL);
2233 }
2234
2235 was_sigsuspended
2236 = current_cpu->thread_data[threadno].sigsuspended;
2237
2238 /* Restore the sigmask, either from the stack copy made when
2239 the sighandler was called, or from the saved state
2240 specifically for sigsuspend(2). */
2241 if (was_sigsuspended)
2242 {
2243 current_cpu->thread_data[threadno].sigsuspended = 0;
2244 for (i = 0; i < 64; i++)
2245 current_cpu->thread_data[threadno].sigdata[i].blocked
2246 = current_cpu->thread_data[threadno]
2247 .sigdata[i].blocked_suspendsave;
2248 }
2249 else
2250 {
2251 USI sp;
2252 USI set_low;
2253 USI set_high;
2254
2255 (*CPU_REG_FETCH (current_cpu)) (current_cpu,
2256 H_GR_SP, regbuf, 4);
2257 sp = bfd_getl32 (regbuf);
2258 set_low
2259 = sim_core_read_unaligned_4 (current_cpu, pc, 0, sp);
2260 set_high
2261 = sim_core_read_unaligned_4 (current_cpu, pc, 0, sp + 4);
2262
2263 for (i = 0; i < 32; i++)
2264 current_cpu->thread_data[threadno].sigdata[i + 1].blocked
2265 = (set_low & (1 << i)) != 0;
2266 for (i = 0; i < 31; i++)
2267 current_cpu->thread_data[threadno].sigdata[i + 33].blocked
2268 = (set_high & (1 << i)) != 0;
2269 }
2270
2271 /* The mask changed, so a signal may be unblocked for
2272 execution. */
2273 current_cpu->thread_data[threadno].sigpending = 1;
2274
2275 memcpy (&current_cpu->cpu_data_placeholder,
2276 current_cpu->thread_data[threadno].cpu_context_atsignal,
2277 current_cpu->thread_cpu_data_size);
2278 free (current_cpu->thread_data[threadno].cpu_context_atsignal);
2279 current_cpu->thread_data[threadno].cpu_context_atsignal = NULL;
2280
2281 /* The return value must come from the saved R10. */
2282 (*CPU_REG_FETCH (current_cpu)) (current_cpu, H_GR_R10, regbuf, 4);
2283 retval = bfd_getl32 (regbuf);
2284
2285 /* We must also break the "sigsuspension loop". */
2286 if (was_sigsuspended)
2287 sim_pc_set (current_cpu, sim_pc_get (current_cpu) + 2);
2288 break;
2289 }
2290
2291 case TARGET_SYS_rt_sigsuspend:
2292 {
2293 USI newsetp = arg1;
2294 USI setsize = arg2;
2295
2296 if (setsize != 8)
2297 {
2298 sim_io_eprintf (sd, "Unimplemented rt_sigsuspend syscall"
2299 " arguments (0x%lx, 0x%lx)\n",
2300 (unsigned long) arg1, (unsigned long) arg2);
2301 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2302 SIM_SIGILL);
2303 }
2304
2305 /* Don't change the signal mask if we're already in
2306 sigsuspend state (i.e. this syscall is a rerun). */
2307 else if (!current_cpu->thread_data[threadno].sigsuspended)
2308 {
2309 USI set_low
2310 = sim_core_read_unaligned_4 (current_cpu, pc, 0,
2311 newsetp);
2312 USI set_high
2313 = sim_core_read_unaligned_4 (current_cpu, pc, 0,
2314 newsetp + 4);
2315 int i;
2316
2317 /* Save the current sigmask and insert the user-supplied
2318 one. */
2319 for (i = 0; i < 32; i++)
2320 {
2321 current_cpu->thread_data[threadno]
2322 .sigdata[i + 1].blocked_suspendsave
2323 = current_cpu->thread_data[threadno]
2324 .sigdata[i + 1].blocked;
2325
2326 current_cpu->thread_data[threadno]
2327 .sigdata[i + 1].blocked = (set_low & (1 << i)) != 0;
2328 }
2329 for (i = 0; i < 31; i++)
2330 {
2331 current_cpu->thread_data[threadno]
2332 .sigdata[i + 33].blocked_suspendsave
2333 = current_cpu->thread_data[threadno]
2334 .sigdata[i + 33].blocked;
2335 current_cpu->thread_data[threadno]
2336 .sigdata[i + 33].blocked = (set_high & (1 << i)) != 0;
2337 }
2338
2339 current_cpu->thread_data[threadno].sigsuspended = 1;
2340
2341 /* The mask changed, so a signal may be unblocked for
2342 execution. */
2343 current_cpu->thread_data[threadno].sigpending = 1;
2344 }
2345
2346 /* Because we don't use arg1 (newsetp) when this syscall is
2347 rerun, it doesn't matter that we overwrite it with the
2348 (constant) return value. */
2349 retval = -cb_host_to_target_errno (cb, EINTR);
2350 sim_pc_set (current_cpu, pc);
2351 break;
2352 }
2353
2354 /* Add case labels here for other syscalls using the 32-bit
2355 "struct stat", provided they have a corresponding simulator
2356 function of course. */
5457266c 2357 case TARGET_SYS_stat:
f6bcefef
HPN
2358 case TARGET_SYS_fstat:
2359 {
2360 /* As long as the infrastructure doesn't cache anything
2361 related to the stat mapping, this trick gets us a dual
2362 "struct stat"-type mapping in the least error-prone way. */
2363 const char *saved_map = cb->stat_map;
2364 CB_TARGET_DEFS_MAP *saved_syscall_map = cb->syscall_map;
2365
2366 cb->syscall_map = (CB_TARGET_DEFS_MAP *) syscall_stat32_map;
2367 cb->stat_map = stat32_map;
2368
2369 if (cb_syscall (cb, &s) != CB_RC_OK)
2370 {
2371 abort ();
2372 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2373 SIM_SIGILL);
2374 }
2375 retval = s.result == -1 ? -s.errcode : s.result;
2376
2377 cb->stat_map = saved_map;
2378 cb->syscall_map = saved_syscall_map;
2379 break;
2380 }
2381
2382 case TARGET_SYS_getcwd:
2383 {
2384 USI buf = arg1;
2385 USI size = arg2;
2386
2387 char *cwd = xmalloc (MAXPATHLEN);
2388 if (cwd != getcwd (cwd, MAXPATHLEN))
2389 abort ();
2390
2391 /* FIXME: When and if we support chdir, we need something
2392 a bit more elaborate. */
2393 if (simulator_sysroot[0] != '\0')
2394 strcpy (cwd, "/");
2395
2396 retval = -cb_host_to_target_errno (cb, ERANGE);
2397 if (strlen (cwd) + 1 <= size)
2398 {
2399 retval = strlen (cwd) + 1;
2400 if (sim_core_write_buffer (sd, current_cpu, 0, cwd,
2401 buf, retval)
2402 != (unsigned int) retval)
2403 retval = -cb_host_to_target_errno (cb, EFAULT);
2404 }
2405 free (cwd);
2406 break;
2407 }
2408
2409 case TARGET_SYS_readlink:
2410 {
2411 SI path = arg1;
2412 SI buf = arg2;
2413 SI bufsiz = arg3;
2414 char *pbuf = xmalloc (MAXPATHLEN);
2415 char *lbuf = xmalloc (MAXPATHLEN);
2416 char *lbuf_alloc = lbuf;
2417 int nchars = -1;
2418 int i;
2419 int o = 0;
2420
2421 if (sim_core_read_unaligned_1 (current_cpu, pc, 0, path) == '/')
2422 {
2423 strcpy (pbuf, simulator_sysroot);
2424 o += strlen (simulator_sysroot);
2425 }
2426
2427 for (i = 0; i + o < MAXPATHLEN; i++)
2428 {
2429 pbuf[i + o]
2430 = sim_core_read_unaligned_1 (current_cpu, pc, 0, path + i);
2431 if (pbuf[i + o] == 0)
2432 break;
2433 }
2434
2435 if (i + o == MAXPATHLEN)
2436 {
2437 retval = -cb_host_to_target_errno (cb, ENAMETOOLONG);
2438 break;
2439 }
2440
2441 /* Intervene calls for certain files expected in the target
2442 proc file system. */
2443 if (strcmp (pbuf + strlen (simulator_sysroot),
2444 "/proc/" XSTRING (TARGET_PID) "/exe") == 0)
2445 {
2446 char *argv0
2447 = (STATE_PROG_ARGV (sd) != NULL
2448 ? *STATE_PROG_ARGV (sd) : NULL);
2449
2450 if (argv0 == NULL || *argv0 == '.')
2451 {
2452 sim_io_eprintf (sd, "Unimplemented readlink syscall "
2453 "(0x%lx: [\"%s\"], 0x%lx)\n",
2454 (unsigned long) arg1, pbuf,
2455 (unsigned long) arg2);
2456 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2457 SIM_SIGILL);
2458 break;
2459 }
2460 else if (*argv0 == '/')
2461 {
2462 if (strncmp (simulator_sysroot, argv0,
2463 strlen (simulator_sysroot)) == 0)
2464 argv0 += strlen (simulator_sysroot);
2465
2466 strcpy (lbuf, argv0);
2467 nchars = strlen (argv0) + 1;
2468 }
2469 else
2470 {
2471 if (getcwd (lbuf, MAXPATHLEN) != NULL
2472 && strlen (lbuf) + 2 + strlen (argv0) < MAXPATHLEN)
2473 {
2474 if (strncmp (simulator_sysroot, lbuf,
2475 strlen (simulator_sysroot)) == 0)
2476 lbuf += strlen (simulator_sysroot);
2477
2478 strcat (lbuf, "/");
2479 strcat (lbuf, argv0);
2480 nchars = strlen (lbuf) + 1;
2481 }
2482 else
2483 abort ();
2484 }
2485 }
2486 else
2487 nchars = readlink (pbuf, lbuf, MAXPATHLEN);
2488
2489 /* We trust that the readlink result returns a *relative*
2490 link, or one already adjusted for the file-path-prefix.
2491 (We can't generally tell the difference, so we go with
2492 the easiest decision; no adjustment.) */
2493
2494 if (nchars == -1)
2495 {
2496 retval = -cb_host_to_target_errno (cb, errno);
2497 break;
2498 }
2499
2500 if (bufsiz < nchars)
2501 nchars = bufsiz;
2502
2503 if (sim_core_write_buffer (sd, current_cpu, write_map, lbuf,
2504 buf, nchars) != (unsigned int) nchars)
2505 retval = -cb_host_to_target_errno (cb, EFAULT);
2506 else
2507 retval = nchars;
2508
2509 free (pbuf);
2510 free (lbuf_alloc);
2511 break;
2512 }
2513
2514 case TARGET_SYS_sched_getscheduler:
2515 {
2516 USI pid = arg1;
2517
2518 /* FIXME: Search (other) existing threads. */
2519 if (pid != 0 && pid != TARGET_PID)
2520 retval = -cb_host_to_target_errno (cb, ESRCH);
2521 else
2522 retval = TARGET_SCHED_OTHER;
2523 break;
2524 }
2525
2526 case TARGET_SYS_sched_getparam:
2527 {
2528 USI pid = arg1;
2529 USI paramp = arg2;
2530
2531 /* The kernel says:
2532 struct sched_param {
2533 int sched_priority;
2534 }; */
2535
2536 if (pid != 0 && pid != TARGET_PID)
2537 retval = -cb_host_to_target_errno (cb, ESRCH);
2538 else
2539 {
2540 /* FIXME: Save scheduler setting before threads are
2541 created too. */
2542 sim_core_write_unaligned_4 (current_cpu, pc, 0, paramp,
2543 current_cpu->thread_data != NULL
2544 ? (current_cpu
2545 ->thread_data[threadno]
2546 .priority)
2547 : 0);
2548 retval = 0;
2549 }
2550 break;
2551 }
2552
2553 case TARGET_SYS_sched_setparam:
2554 {
2555 USI pid = arg1;
2556 USI paramp = arg2;
2557
2558 if ((pid != 0 && pid != TARGET_PID)
2559 || sim_core_read_unaligned_4 (current_cpu, pc, 0,
2560 paramp) != 0)
2561 retval = -cb_host_to_target_errno (cb, EINVAL);
2562 else
2563 retval = 0;
2564 break;
2565 }
2566
2567 case TARGET_SYS_sched_setscheduler:
2568 {
2569 USI pid = arg1;
2570 USI policy = arg2;
2571 USI paramp = arg3;
2572
2573 if ((pid != 0 && pid != TARGET_PID)
2574 || policy != TARGET_SCHED_OTHER
2575 || sim_core_read_unaligned_4 (current_cpu, pc, 0,
2576 paramp) != 0)
2577 retval = -cb_host_to_target_errno (cb, EINVAL);
2578 else
2579 /* FIXME: Save scheduler setting to be read in later
2580 sched_getparam calls. */
2581 retval = 0;
2582 break;
2583 }
2584
2585 case TARGET_SYS_sched_yield:
2586 /* We reschedule to the next thread after a syscall anyway, so
2587 we don't have to do anything here than to set the return
2588 value. */
2589 retval = 0;
2590 break;
2591
2592 case TARGET_SYS_sched_get_priority_min:
2593 case TARGET_SYS_sched_get_priority_max:
2594 if (arg1 != 0)
2595 retval = -cb_host_to_target_errno (cb, EINVAL);
2596 else
2597 retval = 0;
2598 break;
2599
2600 case TARGET_SYS_ugetrlimit:
2601 {
2602 unsigned int curlim, maxlim;
2603 if (arg1 != TARGET_RLIMIT_STACK && arg1 != TARGET_RLIMIT_NOFILE)
2604 {
2605 retval = -cb_host_to_target_errno (cb, EINVAL);
2606 break;
2607 }
2608
2609 /* The kernel says:
2610 struct rlimit {
2611 unsigned long rlim_cur;
2612 unsigned long rlim_max;
2613 }; */
2614 if (arg1 == TARGET_RLIMIT_NOFILE)
2615 {
2616 /* Sadly a very low limit. Better not lie, though. */
2617 maxlim = curlim = MAX_CALLBACK_FDS;
2618 }
2619 else /* arg1 == TARGET_RLIMIT_STACK */
2620 {
2621 maxlim = 0xffffffff;
2622 curlim = 0x800000;
2623 }
2624 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg2, curlim);
2625 sim_core_write_unaligned_4 (current_cpu, pc, 0, arg2 + 4, maxlim);
2626 retval = 0;
2627 break;
2628 }
2629
2630 case TARGET_SYS_setrlimit:
2631 if (arg1 != TARGET_RLIMIT_STACK)
2632 {
2633 retval = -cb_host_to_target_errno (cb, EINVAL);
2634 break;
2635 }
2636 /* FIXME: Save values for future ugetrlimit calls. */
2637 retval = 0;
2638 break;
2639
2640 /* Provide a very limited subset of the sysctl functions, and
2641 abort for the rest. */
2642 case TARGET_SYS__sysctl:
2643 {
2644 /* The kernel says:
2645 struct __sysctl_args {
2646 int *name;
2647 int nlen;
2648 void *oldval;
2649 size_t *oldlenp;
2650 void *newval;
2651 size_t newlen;
2652 unsigned long __unused[4];
2653 }; */
2654 SI name = sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1);
2655 SI name0 = name == 0
2656 ? 0 : sim_core_read_unaligned_4 (current_cpu, pc, 0, name);
2657 SI name1 = name == 0
2658 ? 0 : sim_core_read_unaligned_4 (current_cpu, pc, 0, name + 4);
2659 SI nlen
2660 = sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1 + 4);
2661 SI oldval
2662 = sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1 + 8);
2663 SI oldlenp
2664 = sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1 + 12);
2665 SI oldlen = oldlenp == 0
2666 ? 0 : sim_core_read_unaligned_4 (current_cpu, pc, 0, oldlenp);
2667 SI newval
2668 = sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1 + 16);
2669 SI newlen
2670 = sim_core_read_unaligned_4 (current_cpu, pc, 0, arg1 + 20);
2671
2672 if (name0 == TARGET_CTL_KERN && name1 == TARGET_CTL_KERN_VERSION)
2673 {
2674 SI to_write = oldlen < (SI) sizeof (TARGET_UTSNAME)
2675 ? oldlen : (SI) sizeof (TARGET_UTSNAME);
2676
2677 sim_core_write_unaligned_4 (current_cpu, pc, 0, oldlenp,
2678 sizeof (TARGET_UTSNAME));
2679
2680 if (sim_core_write_buffer (sd, current_cpu, write_map,
2681 TARGET_UTSNAME, oldval,
2682 to_write)
2683 != (unsigned int) to_write)
2684 retval = -cb_host_to_target_errno (cb, EFAULT);
2685 else
2686 retval = 0;
2687 break;
2688 }
2689
2690 sim_io_eprintf (sd, "Unimplemented _sysctl syscall "
2691 "(0x%lx: [0x%lx, 0x%lx],"
2692 " 0x%lx, 0x%lx, 0x%lx, 0x%lx, 0x%lx)\n",
2693 (unsigned long) name,
2694 (unsigned long) name0,
2695 (unsigned long) name1,
2696 (unsigned long) nlen,
2697 (unsigned long) oldval,
2698 (unsigned long) oldlenp,
2699 (unsigned long) newval,
2700 (unsigned long) newlen);
2701 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2702 SIM_SIGILL);
2703 break;
2704 }
2705
2706 case TARGET_SYS_exit:
2707 {
2708 /* Here for all but the last thread. */
2709 int i;
2710 int pid
2711 = current_cpu->thread_data[threadno].threadid + TARGET_PID;
2712 int ppid
2713 = (current_cpu->thread_data[threadno].parent_threadid
2714 + TARGET_PID);
2715 int exitsig = current_cpu->thread_data[threadno].exitsig;
2716
2717 /* Any children are now all orphans. */
2718 for (i = 0; i < SIM_TARGET_MAX_THREADS; i++)
2719 if (current_cpu->thread_data[i].parent_threadid
2720 == current_cpu->thread_data[threadno].threadid)
2721 /* Make getppid(2) return 1 for them, poor little ones. */
2722 current_cpu->thread_data[i].parent_threadid = -TARGET_PID + 1;
2723
2724 /* Free the cpu context data. When the parent has received
2725 the exit status, we'll clear the entry too. */
2726 free (current_cpu->thread_data[threadno].cpu_context);
2727 current_cpu->thread_data[threadno].cpu_context = NULL;
2728 current_cpu->m1threads--;
2729 if (arg1 != 0)
2730 {
2731 sim_io_eprintf (sd, "Thread %d exited with status %d\n",
2732 pid, arg1);
2733 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2734 SIM_SIGILL);
2735 }
2736
2737 /* Still, we may want to support non-zero exit values. */
2738 current_cpu->thread_data[threadno].exitval = arg1 << 8;
2739
2740 if (exitsig)
2741 deliver_signal (current_cpu, exitsig, ppid);
2742 break;
2743 }
2744
2745 case TARGET_SYS_clone:
2746 {
2747 int nthreads = current_cpu->m1threads + 1;
2748 void *thread_cpu_data;
2749 bfd_byte old_sp_buf[4];
2750 bfd_byte sp_buf[4];
2751 const bfd_byte zeros[4] = { 0, 0, 0, 0 };
2752 int i;
2753
2754 /* That's right, the syscall clone arguments are reversed
2755 compared to sys_clone notes in clone(2) and compared to
2756 other Linux ports (i.e. it's the same order as in the
2757 clone(2) libcall). */
2758 USI flags = arg2;
2759 USI newsp = arg1;
2760
2761 if (nthreads == SIM_TARGET_MAX_THREADS)
2762 {
2763 retval = -cb_host_to_target_errno (cb, EAGAIN);
2764 break;
2765 }
2766
2767 /* FIXME: Implement the low byte. */
2768 if ((flags & ~TARGET_CSIGNAL) !=
2769 (TARGET_CLONE_VM
2770 | TARGET_CLONE_FS
2771 | TARGET_CLONE_FILES
2772 | TARGET_CLONE_SIGHAND)
2773 || newsp == 0)
2774 {
2775 sim_io_eprintf (sd,
2776 "Unimplemented clone syscall (0x%lx, 0x%lx)\n",
2777 (unsigned long) arg1, (unsigned long) arg2);
2778 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2779 SIM_SIGILL);
2780 }
2781
2782 if (current_cpu->thread_data == NULL)
2783 make_first_thread (current_cpu);
2784
2785 /* The created thread will get the new SP and a cleared R10.
2786 Since it's created out of a copy of the old thread and we
2787 don't have a set-register-function that just take the
2788 cpu_data as a parameter, we set the childs values first,
2789 and write back or overwrite them in the parent after the
2790 copy. */
2791 (*CPU_REG_FETCH (current_cpu)) (current_cpu,
2792 H_GR_SP, old_sp_buf, 4);
2793 bfd_putl32 (newsp, sp_buf);
2794 (*CPU_REG_STORE (current_cpu)) (current_cpu,
2795 H_GR_SP, sp_buf, 4);
2796 (*CPU_REG_STORE (current_cpu)) (current_cpu,
2797 H_GR_R10, (bfd_byte *) zeros, 4);
2798 thread_cpu_data
2799 = (*current_cpu
2800 ->make_thread_cpu_data) (current_cpu,
2801 &current_cpu->cpu_data_placeholder);
2802 (*CPU_REG_STORE (current_cpu)) (current_cpu,
2803 H_GR_SP, old_sp_buf, 4);
2804
2805 retval = ++current_cpu->max_threadid + TARGET_PID;
2806
2807 /* Find an unused slot. After a few threads have been created
2808 and exited, the array is expected to be a bit fragmented.
2809 We don't reuse the first entry, though, that of the
2810 original thread. */
2811 for (i = 1; i < SIM_TARGET_MAX_THREADS; i++)
2812 if (current_cpu->thread_data[i].cpu_context == NULL
2813 /* Don't reuse a zombied entry. */
2814 && current_cpu->thread_data[i].threadid == 0)
2815 break;
2816
2817 memcpy (&current_cpu->thread_data[i],
2818 &current_cpu->thread_data[threadno],
2819 sizeof (current_cpu->thread_data[i]));
2820 current_cpu->thread_data[i].cpu_context = thread_cpu_data;
2821 current_cpu->thread_data[i].cpu_context_atsignal = NULL;
2822 current_cpu->thread_data[i].threadid = current_cpu->max_threadid;
2823 current_cpu->thread_data[i].parent_threadid
2824 = current_cpu->thread_data[threadno].threadid;
2825 current_cpu->thread_data[i].pipe_read_fd = 0;
2826 current_cpu->thread_data[i].pipe_write_fd = 0;
2827 current_cpu->thread_data[i].at_syscall = 0;
2828 current_cpu->thread_data[i].sigpending = 0;
2829 current_cpu->thread_data[i].sigsuspended = 0;
2830 current_cpu->thread_data[i].exitsig = flags & TARGET_CSIGNAL;
2831 current_cpu->m1threads = nthreads;
2832 break;
2833 }
2834
2835 /* Better watch these in case they do something necessary. */
2836 case TARGET_SYS_socketcall:
2837 retval = -cb_host_to_target_errno (cb, ENOSYS);
2838 break;
2839
2840 unimplemented_syscall:
2841 default:
2842 sim_io_eprintf (sd, "Unimplemented syscall: %d "
2843 "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", callnum,
2844 arg1, arg2, arg3, arg4, arg5, arg6);
2845 sim_engine_halt (sd, current_cpu, NULL, pc, sim_stopped,
2846 SIM_SIGILL);
2847 }
2848 }
2849
ed1f044a
HPN
2850 /* Minimal support for fcntl F_GETFL as used in open+fdopen. */
2851 if (callnum == TARGET_SYS_open)
2852 {
2853 current_cpu->last_open_fd = retval;
2854 current_cpu->last_open_flags = arg2;
2855 }
2856 current_cpu->last_syscall = callnum;
2857
f6bcefef
HPN
2858 /* A system call is a rescheduling point. For the time being, we don't
2859 reschedule anywhere else. */
2860 if (current_cpu->m1threads != 0
2861 /* We need to schedule off from an exiting thread that is the
2862 second-last one. */
2863 || (current_cpu->thread_data != NULL
2864 && current_cpu->thread_data[threadno].cpu_context == NULL))
2865 {
2866 bfd_byte retval_buf[4];
2867
2868 current_cpu->thread_data[threadno].last_execution
2869 = TARGET_TIME_MS (current_cpu);
2870 bfd_putl32 (retval, retval_buf);
2871 (*CPU_REG_STORE (current_cpu)) (current_cpu, H_GR_R10, retval_buf, 4);
2872
2873 current_cpu->thread_data[threadno].at_syscall = 1;
2874 reschedule (current_cpu);
2875
2876 (*CPU_REG_FETCH (current_cpu)) (current_cpu, H_GR_R10, retval_buf, 4);
2877 retval = bfd_getl32 (retval_buf);
2878 }
2879
2880 return retval;
2881}
2882
2883/* Callback from simulator write saying that the pipe at (reader, writer)
2884 is now non-empty (so the writer should wait until the pipe is empty, at
2885 least not write to this or any other pipe). Simplest is to just wait
2886 until the pipe is empty. */
2887
2888static void
2889cris_pipe_nonempty (host_callback *cb ATTRIBUTE_UNUSED,
2890 int reader, int writer)
2891{
2892 SIM_CPU *cpu = current_cpu_for_cb_callback;
2893 const bfd_byte zeros[4] = { 0, 0, 0, 0 };
2894
2895 /* It's the current thread: we just have to re-run the current
2896 syscall instruction (presumably "break 13") and change the syscall
2897 to the special simulator-wait code. Oh, and set a marker that
2898 we're waiting, so we can disambiguate the special call from a
2899 program error.
2900
2901 This function may be called multiple times between cris_pipe_empty,
2902 but we must avoid e.g. decreasing PC every time. Check fd markers
2903 to tell. */
2904 if (cpu->thread_data == NULL)
2905 {
2906 sim_io_eprintf (CPU_STATE (cpu),
2907 "Terminating simulation due to writing pipe rd:wr %d:%d"
2908 " from one single thread\n", reader, writer);
2909 sim_engine_halt (CPU_STATE (cpu), cpu,
2910 NULL, sim_pc_get (cpu), sim_stopped, SIM_SIGILL);
2911 }
2912 else if (cpu->thread_data[cpu->threadno].pipe_write_fd == 0)
2913 {
2914 cpu->thread_data[cpu->threadno].pipe_write_fd = writer;
2915 cpu->thread_data[cpu->threadno].pipe_read_fd = reader;
2916 /* FIXME: We really shouldn't change registers other than R10 in
2917 syscalls (like R9), here or elsewhere. */
2918 (*CPU_REG_STORE (cpu)) (cpu, H_GR_R9, (bfd_byte *) zeros, 4);
2919 sim_pc_set (cpu, sim_pc_get (cpu) - 2);
2920 }
2921}
2922
2923/* Callback from simulator close or read call saying that the pipe at
2924 (reader, writer) is now empty (so the writer can write again, perhaps
2925 leave a waiting state). If there are bytes remaining, they couldn't be
2926 consumed (perhaps due to the pipe closing). */
2927
2928static void
2929cris_pipe_empty (host_callback *cb,
2930 int reader ATTRIBUTE_UNUSED,
2931 int writer)
2932{
2933 int i;
2934 SIM_CPU *cpu = current_cpu_for_cb_callback;
2935 bfd_byte r10_buf[4];
2936 int remaining = cb->pipe_buffer[writer].size;
2937
2938 /* We need to find the thread that waits for this pipe. */
2939 for (i = 0; i < SIM_TARGET_MAX_THREADS; i++)
2940 if (cpu->thread_data[i].cpu_context
2941 && cpu->thread_data[i].pipe_write_fd == writer)
2942 {
2943 int retval;
2944 /* Temporarily switch to this cpu context, so we can change the
2945 PC by ordinary calls. */
2946
2947 memcpy (cpu->thread_data[cpu->threadno].cpu_context,
2948 &cpu->cpu_data_placeholder,
2949 cpu->thread_cpu_data_size);
2950 memcpy (&cpu->cpu_data_placeholder,
2951 cpu->thread_data[i].cpu_context,
2952 cpu->thread_cpu_data_size);
2953
2954 /* The return value is supposed to contain the number of written
2955 bytes, which is the number of bytes requested and returned at
2956 the write call. We subtract the remaining bytes from that,
2957 but making sure we still get a positive number.
2958 The return value may also be a negative number; an error
2959 value. We cover this case by comparing against remaining,
2960 which is always >= 0. */
2961 (*CPU_REG_FETCH (cpu)) (cpu, H_GR_R10, r10_buf, 4);
2962 retval = (int) bfd_getl_signed_32 (r10_buf);
2963 if (retval >= remaining)
2964 bfd_putl32 (retval - remaining, r10_buf);
2965 (*CPU_REG_STORE (cpu)) (cpu, H_GR_R10, r10_buf, 4);
2966
2967 sim_pc_set (cpu, sim_pc_get (cpu) + 2);
2968 memcpy (cpu->thread_data[i].cpu_context,
2969 &cpu->cpu_data_placeholder,
2970 cpu->thread_cpu_data_size);
2971 memcpy (&cpu->cpu_data_placeholder,
2972 cpu->thread_data[cpu->threadno].cpu_context,
2973 cpu->thread_cpu_data_size);
2974 cpu->thread_data[i].pipe_read_fd = 0;
2975 cpu->thread_data[i].pipe_write_fd = 0;
2976 return;
2977 }
2978
2979 abort ();
2980}
2981
2982/* We have a simulator-specific notion of time. See TARGET_TIME. */
2983
2984static long
2985cris_time (host_callback *cb ATTRIBUTE_UNUSED, long *t)
2986{
2987 long retval = TARGET_TIME (current_cpu_for_cb_callback);
2988 if (t)
2989 *t = retval;
2990 return retval;
2991}
2992
2993/* Set target-specific callback data. */
2994
2995void
2996cris_set_callbacks (host_callback *cb)
2997{
2998 /* Yeargh, have to cast away constness to avoid warnings. */
2999 cb->syscall_map = (CB_TARGET_DEFS_MAP *) syscall_map;
3000 cb->errno_map = (CB_TARGET_DEFS_MAP *) errno_map;
3001
3002 /* The kernel stat64 layout. If we see a file > 2G, the "long"
3003 parameter to cb_store_target_endian will make st_size negative.
3004 Similarly for st_ino. FIXME: Find a 64-bit type, and use it
3005 *unsigned*, and/or add syntax for signed-ness. */
3006 cb->stat_map = stat_map;
3007 cb->open_map = (CB_TARGET_DEFS_MAP *) open_map;
3008 cb->pipe_nonempty = cris_pipe_nonempty;
3009 cb->pipe_empty = cris_pipe_empty;
3010 cb->time = cris_time;
3011}
3012
3013/* Process an address exception. */
3014
3015void
3016cris_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia,
3017 unsigned int map, int nr_bytes, address_word addr,
3018 transfer_type transfer, sim_core_signals sig)
3019{
3020 sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr,
3021 transfer, sig);
3022}
This page took 0.185631 seconds and 4 git commands to generate.