diff --git a/configure b/configure
index f74e1f3b7c..c1be5f3508 100755
--- a/configure
+++ b/configure
@@ -6669,7 +6669,7 @@ target_name=$(echo $target | cut -d '-' -f 1)
target_bigendian="no"
case "$target_name" in
- armeb|aarch64_be|hppa|lm32|m68k|microblaze|mips|mipsn32|mips64|moxie|or1k|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|sparc|sparc64|sparc32plus|xtensaeb)
+ armeb|aarch64_be|hppa|lm32|m68k|microblaze|irix|irixn32|irix64|mips|mipsn32|mips64|moxie|or1k|ppc|ppcemb|ppc64|ppc64abi32|s390x|sh4eb|solaris|solaris64|sparc|sparc64|sparc32plus|xtensaeb)
target_bigendian=yes
;;
esac
@@ -6746,6 +6746,28 @@ case "$target_name" in
TARGET_ARCH=microblaze
bflt="yes"
;;
+ irix)
+ TARGET_ARCH=mips
+ TARGET_ABI_DIR=irix
+ TARGET_BASE_ARCH=mips
+ echo "TARGET_ABI_MIPSO32=y" >> $config_target_mak
+ echo "TARGET_ABI_IRIX=y" >> $config_target_mak
+ ;;
+ irixn32)
+ TARGET_ARCH=mips64
+ TARGET_ABI_DIR=irix
+ TARGET_BASE_ARCH=mips
+ echo "TARGET_ABI_MIPSN32=y" >> $config_target_mak
+ echo "TARGET_ABI32=y" >> $config_target_mak
+ echo "TARGET_ABI_IRIX=y" >> $config_target_mak
+ ;;
+ irix64)
+ TARGET_ARCH=mips64
+ TARGET_ABI_DIR=irix
+ TARGET_BASE_ARCH=mips
+ echo "TARGET_ABI_MIPSN64=y" >> $config_target_mak
+ echo "TARGET_ABI_IRIX=y" >> $config_target_mak
+ ;;
mips|mipsel)
TARGET_ARCH=mips
echo "TARGET_ABI_MIPSO32=y" >> $config_target_mak
@@ -6811,6 +6833,17 @@ case "$target_name" in
TARGET_ARCH=sh4
bflt="yes"
;;
+ solaris)
+ TARGET_ARCH=sparc
+ TARGET_ABI_DIR=solaris
+ echo "TARGET_ABI_SOLARIS=y" >> $config_target_mak
+ ;;
+ solaris64)
+ TARGET_ARCH=sparc64
+ TARGET_ABI_DIR=solaris
+ TARGET_BASE_ARCH=sparc
+ echo "TARGET_ABI_SOLARIS=y" >> $config_target_mak
+ ;;
sparc)
;;
sparc64)
@@ -6961,7 +6994,7 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
microblaze*)
disas_config "MICROBLAZE"
;;
- mips*)
+ irix*|mips*)
disas_config "MIPS"
;;
moxie*)
@@ -6985,7 +7018,7 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
sh4)
disas_config "SH4"
;;
- sparc*)
+ solaris*|sparc*)
disas_config "SPARC"
;;
xtensa*)
diff --git a/default-configs/irix-linux-user.mak b/default-configs/irix-linux-user.mak
new file mode 100644
index 0000000000..31df57021e
--- /dev/null
+++ b/default-configs/irix-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for mips-linux-user
diff --git a/default-configs/irix64-linux-user.mak b/default-configs/irix64-linux-user.mak
new file mode 100644
index 0000000000..1598bfcf7d
--- /dev/null
+++ b/default-configs/irix64-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for mips64-linux-user
diff --git a/default-configs/irixn32-linux-user.mak b/default-configs/irixn32-linux-user.mak
new file mode 100644
index 0000000000..5b97919794
--- /dev/null
+++ b/default-configs/irixn32-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for mipsn32-linux-user
diff --git a/default-configs/solaris-linux-user.mak b/default-configs/solaris-linux-user.mak
new file mode 100644
index 0000000000..9c716d1f92
--- /dev/null
+++ b/default-configs/solaris-linux-user.mak
@@ -0,0 +1 @@
+# Default configuration for sparc-linux-user
diff --git a/include/elf.h b/include/elf.h
index c0dc9bb5fd..96bb8206e3 100644
--- a/include/elf.h
+++ b/include/elf.h
@@ -281,6 +281,8 @@ typedef int64_t Elf64_Sxword;
#define AT_L2_CACHESHAPE 36 /* bits 4-7: log2 of line size. */
#define AT_L3_CACHESHAPE 37 /* val&~255: cache size. */
+#define AT_SUN_LDDATA 2016 /* Solaris specific, rld data segment */
+
typedef struct dynamic{
Elf32_Sword d_tag;
union{
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 5fc130cc20..a8b3962f06 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -690,6 +690,15 @@ static inline void init_thread(struct target_pt_regs *regs,
}
#endif
+
+#ifdef TARGET_ABI_SOLARIS
+#define DLINFO_ARCH_ITEMS 1
+#define ARCH_DLINFO \
+ do { \
+ NEW_AUX_ENT(AT_SUN_LDDATA, (abi_ulong)(interp_info ? interp_info->start_data : 0)); \
+ } while (0)
+#endif
+
#endif
#ifdef TARGET_PPC
@@ -1606,8 +1615,13 @@ static abi_ulong setup_arg_pages(struct linux_binprm *bprm,
guard = qemu_real_host_page_size;
}
+#ifdef TARGET_ABI_IRIX
+ error = target_mmap(0x7fff8000 - size - guard, size + guard, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+#else
error = target_mmap(0, size + guard, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+#endif
if (error == -1) {
perror("mmap stack");
exit(-1);
@@ -1799,6 +1813,12 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
info->arg_start = u_argv;
info->arg_end = u_argv + argc * n;
+#ifdef TARGET_ABI_IRIX
+#define NEW_AUX_ENT(id, val) do { \
+ put_user_u32(id, u_auxv); u_auxv += n; \
+ put_user_ual(val, u_auxv); u_auxv += n; \
+ } while(0)
+#else
/* This is correct because Linux defines
* elf_addr_t as Elf32_Off / Elf64_Off
*/
@@ -1806,6 +1826,7 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
put_user_ual(id, u_auxv); u_auxv += n; \
put_user_ual(val, u_auxv); u_auxv += n; \
} while(0)
+#endif
#ifdef ARCH_DLINFO
/*
@@ -1817,7 +1838,11 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
/* There must be exactly DLINFO_ITEMS entries here, or the assert
* on info->auxv_len will trigger.
*/
+#ifdef TARGET_ABI_IRIX
+ NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_bias + info->phdr_offset));
+#else
NEW_AUX_ENT(AT_PHDR, (abi_ulong)(info->load_addr + exec->e_phoff));
+#endif
NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(MAX(TARGET_PAGE_SIZE, getpagesize())));
@@ -2016,6 +2041,87 @@ exit_errmsg:
}
+#ifdef TARGET_ABI_IRIX
+/* SGI_ELFMAP: Map ELF sections into the address space.
+ IMAGE_FD is the open file descriptor for the image.
+*/
+abi_ulong sgi_map_elf_image(int image_fd, struct elf_phdr *phdr, int phnum)
+{
+ abi_ulong load_addr, load_bias, loaddr, hiaddr, error;
+ int i;
+ const char *errmsg;
+
+ /* Find the maximum size of the image and allocate an appropriate
+ amount of memory to handle that. */
+ loaddr = -1, hiaddr = 0;
+ for (i = 0; i < phnum; ++i) {
+ if (phdr[i].p_type == PT_LOAD) {
+ abi_ulong a = phdr[i].p_vaddr;
+ if (a < loaddr) {
+ loaddr = a;
+ }
+ a += phdr[i].p_memsz;
+ if (a > hiaddr) {
+ hiaddr = a;
+ }
+ }
+ }
+
+ /* The image indicates that it can be loaded anywhere. Find a
+ location that can hold the memory space required. If the
+ image is pre-linked, LOADDR will be non-zero. Since we do
+ not supply MAP_FIXED here we'll use that address if and
+ only if it remains available. */
+ load_addr = target_mmap(loaddr, hiaddr - loaddr, PROT_NONE,
+ MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
+ -1, 0);
+ if (load_addr == -1) {
+ goto exit_perror;
+ }
+ /* unmap to avoid failure if objects would be loaded into a hole */
+ target_munmap(load_addr, hiaddr - loaddr);
+ load_bias = load_addr - loaddr;
+
+ for (i = 0; i < phnum; i++) {
+ struct elf_phdr *eppnt = phdr + i;
+ if (eppnt->p_type == PT_LOAD) {
+ abi_ulong vaddr, vaddr_po, vaddr_ps, vaddr_ef, vaddr_em;
+ int elf_prot = 0;
+
+ if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
+ if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
+ if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
+
+ vaddr = load_bias + eppnt->p_vaddr;
+ vaddr_po = TARGET_ELF_PAGEOFFSET(vaddr);
+ vaddr_ps = TARGET_ELF_PAGESTART(vaddr);
+
+ error = target_mmap(vaddr_ps, eppnt->p_filesz + vaddr_po,
+ elf_prot, MAP_PRIVATE | MAP_FIXED,
+ image_fd, eppnt->p_offset - vaddr_po);
+ if (error == -1) {
+ goto exit_perror;
+ }
+
+ vaddr_ef = vaddr + eppnt->p_filesz;
+ vaddr_em = vaddr + eppnt->p_memsz;
+
+ /* If the load segment requests extra zeros (e.g. bss), map it. */
+ if (vaddr_ef < vaddr_em) {
+ zero_bss(vaddr_ef, vaddr_em, elf_prot);
+ }
+ }
+ }
+
+ return load_bias + phdr[0].p_vaddr;
+
+ exit_perror:
+ errmsg = strerror(errno);
+ fprintf(stderr, "error in syssgi elfmap: %s\n", errmsg);
+ return -ENOEXEC;
+}
+#endif
+
/* Load an ELF image into the address space.
IMAGE_NAME is the filename of the image, to use in error messages.
@@ -2099,6 +2205,8 @@ static void load_elf_image(const char *image_name, int image_fd,
if (load_addr == -1) {
goto exit_perror;
}
+ /* unmap to avoid failure if objects would be loaded into a hole */
+ target_munmap(load_addr, hiaddr - loaddr);
} else if (pinterp_name != NULL) {
/* This is the main executable. Make sure that the low
address does not conflict with MMAP_MIN_ADDR or the
@@ -2215,6 +2323,11 @@ static void load_elf_image(const char *image_name, int image_fd,
}
*pinterp_name = interp_name;
}
+#ifdef TARGET_ABI_IRIX
+ else if (eppnt->p_type == PT_PHDR) {
+ info->phdr_offset = eppnt->p_vaddr;
+ }
+#endif
}
if (info->end_data == 0) {
@@ -2230,6 +2343,17 @@ static void load_elf_image(const char *image_name, int image_fd,
mmap_unlock();
close(image_fd);
+#ifdef TARGET_ABI_IRIX
+ /* PRDA hack */
+ error = target_mmap(0x200000, TARGET_PAGE_SIZE, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,
+ -1, 0);
+ if (error == -1) {
+ goto exit_perror;
+ }
+ put_user(getpid(), 0x200e00, target_pid_t);
+ put_user(getpid(), 0x200e40, target_pid_t);
+#endif
return;
exit_read:
@@ -2463,6 +2587,7 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
struct elfhdr elf_ex;
char *elf_interpreter = NULL;
char *scratch;
+ abi_ulong top;
info->start_mmap = (abi_ulong)ELF_START_MMAP;
@@ -2476,7 +2601,7 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
/* Do this so that we can load the interpreter, if need be. We will
change some of these later */
- bprm->p = setup_arg_pages(bprm, info);
+ bprm->p = top = setup_arg_pages(bprm, info);
scratch = g_new0(char, TARGET_PAGE_SIZE);
if (STACK_GROWS_DOWN) {
@@ -2507,6 +2632,26 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
fprintf(stderr, "%s: %s\n", bprm->filename, strerror(E2BIG));
exit(-1);
}
+#ifdef TARGET_ABI_IRIX
+ /* page alignment */
+ if (bprm->p % TARGET_PAGE_SIZE) {
+ int o = bprm->p % TARGET_PAGE_SIZE;
+ int l = top - bprm->p;
+ int p = bprm->p - o;
+ char *ptr = lock_user(VERIFY_WRITE, p, l+o, 0);
+ if (!ptr) {
+ fprintf(stderr, "%s: %s\n", bprm->filename, strerror(EFAULT));
+ exit(-1);
+ }
+ memmove(ptr, ptr+o, l);
+ unlock_user(ptr, p, 1);
+ /* adjust pointers by alignment offset */
+ bprm->p -= o;
+ info->file_string -= o;
+ info->arg_strings -= o;
+ info->env_strings -= o;
+ }
+#endif
if (elf_interpreter) {
load_elf_interp(elf_interpreter, &interp_info, bprm->buf);
diff --git a/linux-user/errno_defs.h b/linux-user/errno_defs.h
index 55fbebda51..e15566c9e1 100644
--- a/linux-user/errno_defs.h
+++ b/linux-user/errno_defs.h
@@ -4,6 +4,158 @@
*
* Taken from asm-generic/errno-base.h and asm-generic/errno.h
*/
+#if defined TARGET_ABI_IRIX || defined TARGET_ABI_SOLARIS
+#define TARGET_EPERM 1 /* Operation not permitted */
+#define TARGET_ENOENT 2 /* No such file or directory */
+#define TARGET_ESRCH 3 /* No such process */
+#define TARGET_EINTR 4 /* Interrupted function call */
+#define TARGET_EIO 5 /* I/O error */
+#define TARGET_ENXIO 6 /* No such device or address */
+#define TARGET_E2BIG 7 /* Arg list too long */
+#define TARGET_ENOEXEC 8 /* Exec format error */
+#define TARGET_EBADF 9 /* Bad file number */
+#define TARGET_ECHILD 10 /* No child processes */
+#define TARGET_EAGAIN 11 /* Resource temporarily unavailable */
+#define TARGET_ENOMEM 12 /* Not enough space */
+#define TARGET_EACCES 13 /* Permission denied */
+#define TARGET_EFAULT 14 /* Bad address */
+#define TARGET_ENOTBLK 15 /* Block device required */
+#define TARGET_EBUSY 16 /* Resource busy */
+#define TARGET_EEXIST 17 /* File exists */
+#define TARGET_EXDEV 18 /* Improper link */
+#define TARGET_ENODEV 19 /* No such device */
+#define TARGET_ENOTDIR 20 /* Not a directory */
+#define TARGET_EISDIR 21 /* Is a directory */
+#define TARGET_EINVAL 22 /* Invalid argument */
+#define TARGET_ENFILE 23 /* File table overflow */
+#define TARGET_EMFILE 24 /* Too many open files */
+#define TARGET_ENOTTY 25 /* Inappropriate I/O control operation */
+#define TARGET_ETXTBSY 26 /* Text file busy */
+#define TARGET_EFBIG 27 /* File too large */
+#define TARGET_ENOSPC 28 /* No space left on device */
+#define TARGET_ESPIPE 29 /* Illegal seek */
+#define TARGET_EROFS 30 /* Read only file system */
+#define TARGET_EMLINK 31 /* Too many links */
+#define TARGET_EPIPE 32 /* Broken pipe */
+#define TARGET_EDOM 33 /* Domain error */
+#define TARGET_ERANGE 34 /* Result too large */
+#define TARGET_ENOMSG 35 /* No message of desired type */
+#define TARGET_EIDRM 36 /* Identifier removed */
+#define TARGET_ECHRNG 37 /* Channel number out of range */
+#define TARGET_EL2NSYNC 38 /* Level 2 not synchronized */
+#define TARGET_EL3HLT 39 /* Level 3 halted */
+#define TARGET_EL3RST 40 /* Level 3 reset */
+#define TARGET_ELNRNG 41 /* Link number out of range */
+#define TARGET_EUNATCH 42 /* Protocol driver not attached */
+#define TARGET_ENOCSI 43 /* No CSI structure available */
+#define TARGET_EL2HLT 44 /* Level 2 halted */
+#define TARGET_EDEADLK 45 /* Resource deadlock avoided */
+#define TARGET_ENOLCK 46 /* No locks available */
+#define TARGET_ECKPT 47 /* POSIX checkpoint/restart error */
+
+/* Convergent Error Returns */
+#define TARGET_EBADE 50 /* invalid exchange */
+#define TARGET_EBADR 51 /* invalid request descriptor */
+#define TARGET_EXFULL 52 /* exchange full */
+#define TARGET_ENOANO 53 /* no anode */
+#define TARGET_EBADRQC 54 /* invalid request code */
+#define TARGET_EBADSLT 55 /* invalid slot */
+#define TARGET_EDEADLOCK 56 /* file locking deadlock error */
+
+#define TARGET_EBFONT 57 /* bad font file fmt */
+
+/* stream problems */
+#define TARGET_ENOSTR 60 /* Device not a stream */
+#define TARGET_ENODATA 61 /* no data (for no delay io) */
+#define TARGET_ETIME 62 /* timer expired */
+#define TARGET_ENOSR 63 /* out of streams resources */
+
+#define TARGET_ENONET 64 /* Machine is not on the network */
+#define TARGET_ENOPKG 65 /* Package not installed */
+#define TARGET_EREMOTE 66 /* The object is remote */
+#define TARGET_ENOLINK 67 /* the link has been severed */
+#define TARGET_EADV 68 /* advertise error */
+#define TARGET_ESRMNT 69 /* srmount error */
+
+#define TARGET_ECOMM 70 /* Communication error on send */
+#define TARGET_EPROTO 71 /* Protocol error */
+#define TARGET_EMULTIHOP 74 /* multihop attempted */
+#define TARGET_EBADMSG 77 /* Bad message */
+#define TARGET_ENAMETOOLONG 78 /* Filename too long */
+#define TARGET_EOVERFLOW 79 /* value too large to be stored in data type */
+#define TARGET_ENOTUNIQ 80 /* given log. name not unique */
+#define TARGET_EBADFD 81 /* f.d. invalid for this operation */
+#define TARGET_EREMCHG 82 /* Remote address changed */
+
+/* shared library problems */
+#define TARGET_ELIBACC 83 /* Can't access a needed shared lib. */
+#define TARGET_ELIBBAD 84 /* Accessing a corrupted shared lib. */
+#define TARGET_ELIBSCN 85 /* .lib section in a.out corrupted. */
+#define TARGET_ELIBMAX 86 /* Attempting to link in too many libs. */
+#define TARGET_ELIBEXEC 87 /* Attempting to exec a shared library. */
+#define TARGET_EILSEQ 88 /* Illegal byte sequence. */
+#define TARGET_ENOSYS 89 /* Function not implemented */
+#define TARGET_ELOOP 90 /* Symbolic link loop */
+#define TARGET_ERESTART 91 /* Restartable system call */
+#define TARGET_ESTRPIPE 92 /* if pipe/FIFO, don't sleep in stream head */
+
+#define TARGET_ENOTEMPTY 93 /* Directory not empty */
+
+#define TARGET_EUSERS 94 /* Too many users (for UFS) */
+
+/* BSD Networking Software */
+ /* argument errors */
+#define TARGET_ENOTSOCK 95 /* Socket operation on non-socket */
+#define TARGET_EDESTADDRREQ 96 /* Destination address required */
+#define TARGET_EMSGSIZE 97 /* Inappropriate message buffer length */
+#define TARGET_EPROTOTYPE 98 /* Protocol wrong type for socket */
+#define TARGET_ENOPROTOOPT 99 /* Protocol not available */
+#define TARGET_EPROTONOSUPPORT 120 /* Protocol not supported */
+#define TARGET_ESOCKTNOSUPPORT 121 /* Socket type not supported */
+#define TARGET_EOPNOTSUPP 122 /* Operation not supported on socket */
+#define TARGET_EPFNOSUPPORT 123 /* Protocol family not supported */
+#define TARGET_EAFNOSUPPORT 124 /* Address family not supported by
+ protocol family */
+#define TARGET_EADDRINUSE 125 /* Address already in use */
+#define TARGET_EADDRNOTAVAIL 126 /* Can't assign requested address */
+
+/* operational errors */
+#define TARGET_ENETDOWN 127 /* Network is down */
+#define TARGET_ENETUNREACH 128 /* Network is unreachable */
+#define TARGET_ENETRESET 129 /* Network dropped connection because
+ of reset */
+#define TARGET_ECONNABORTED 130 /* Software caused connection abort */
+#define TARGET_ECONNRESET 131 /* Connection reset by peer */
+#define TARGET_ENOBUFS 132 /* No buffer space available */
+#define TARGET_EISCONN 133 /* Socket is already connected */
+#define TARGET_ENOTCONN 134 /* Socket is not connected */
+
+/* XENIX has 135 - 142 */
+#define TARGET_ESHUTDOWN 143 /* Can't send after socket shutdown */
+#define TARGET_ETOOMANYREFS 144 /* Too many references: can't splice */
+#define TARGET_ETIMEDOUT 145 /* Connection timed out */
+#define TARGET_ECONNREFUSED 146 /* Connection refused */
+#define TARGET_EHOSTDOWN 147 /* Host is down */
+#define TARGET_EHOSTUNREACH 148 /* No route to host */
+
+#define TARGET_EWOULDBLOCK TARGET_EAGAIN
+
+#define TARGET_EALREADY 149 /* operation already in progress */
+#define TARGET_EINPROGRESS 150 /* operation now in progress */
+/* SUN Network File System */
+#define TARGET_ESTALE 151 /* Stale NFS file handle */
+
+/* XENIX error numbers */
+#define TARGET_EUCLEAN 135 /* Structure needs cleaning */
+#define TARGET_ENOTNAM 137 /* Not a XENIX named type file */
+#define TARGET_ENAVAIL 138 /* No XENIX semaphores available */
+#define TARGET_EISNAM 139 /* Is a named type file */
+#define TARGET_EREMOTEIO 140 /* Remote I/O error */
+#define TARGET_EINIT 141 /* Reserved for future */
+#define TARGET_EREMDEV 142 /* Error 142 */
+#define TARGET_ECANCELED 158 /* AIO operation canceled */
+
+#else
#define TARGET_EPERM 1 /* Operation not permitted */
#define TARGET_ENOENT 2 /* No such file or directory */
#define TARGET_ESRCH 3 /* No such process */
@@ -142,6 +294,7 @@
#define TARGET_ERFKILL 132 /* Operation not possible due to RF-kill */
#define TARGET_EHWPOISON 133 /* Memory page has hardware error */
+#endif
/* QEMU internal, not visible to the guest. This is returned when a
* system call should be restarted, to tell the main loop that it
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index 586c794639..7dea36d8ee 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -1,5 +1,12 @@
/* emulated ioctl list */
+#ifdef TARGET_ABI_IRIX
+ IOCTL_MAP(TCNGETS, TCGETS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
+ IOCTL_MAP(TCNSETS, TCSETS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
+ IOCTL_MAP(TCNSETSF, TCSETSF, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
+ IOCTL_MAP(TCNSETSW, TCSETSW, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
+#endif
+
IOCTL(TCGETS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
IOCTL(TCSETS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
IOCTL(TCSETSF, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
@@ -55,6 +62,7 @@
IOCTL(TIOCMIWAIT, 0, TYPE_INT)
IOCTL(TIOCGICOUNT, IOC_R, MK_PTR(MK_STRUCT(STRUCT_serial_icounter_struct)))
+#if !defined(TARGET_ABI_IRIX) && !defined(TARGET_ABI_SOLARIS)
IOCTL(KIOCSOUND, 0, TYPE_INT)
IOCTL(KDMKTONE, 0, TYPE_INT)
IOCTL(KDSETMODE, 0, TYPE_INT)
@@ -126,6 +134,7 @@
#ifdef CONFIG_FIEMAP
IOCTL_SPECIAL(FS_IOC_FIEMAP, IOC_W | IOC_R, do_ioctl_fs_ioc_fiemap,
MK_PTR(MK_STRUCT(STRUCT_fiemap)))
+#endif
#endif
IOCTL(FS_IOC_GETFLAGS, IOC_R, MK_PTR(TYPE_INT))
@@ -175,7 +184,11 @@
IOCTL(SIOCGPGRP, IOC_R, MK_PTR(TYPE_INT)) /* pid_t */
IOCTL(SIOCGSTAMP, IOC_R, MK_PTR(MK_STRUCT(STRUCT_timeval)))
IOCTL(SIOCGSTAMPNS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_timespec)))
+#ifdef TARGET_ABI_IRIX
+ IOCTL_MAP(SIOCNREAD, FIONREAD, IOC_R, MK_PTR(TYPE_INT))
+#endif
+#if !defined TARGET_ABI_IRIX && !defined TARGET_ABI_SOLARIS
IOCTL(RNDGETENTCNT, IOC_R, MK_PTR(TYPE_INT))
IOCTL(RNDADDTOENTCNT, IOC_W, MK_PTR(TYPE_INT))
IOCTL(RNDZAPENTCNT, 0, TYPE_NULL)
@@ -438,6 +451,7 @@
MK_PTR(MK_STRUCT(STRUCT_rtentry)))
IOCTL_SPECIAL(SIOCDELRT, IOC_W, do_ioctl_rt,
MK_PTR(MK_STRUCT(STRUCT_rtentry)))
+#endif
#ifdef TARGET_TIOCSTART
IOCTL_IGNORE(TIOCSTART)
diff --git a/linux-user/irix/syscall_nr.h b/linux-user/irix/syscall_nr.h
new file mode 100644
index 0000000000..76eb3fed9b
--- /dev/null
+++ b/linux-user/irix/syscall_nr.h
@@ -0,0 +1,355 @@
+/*
+ * IRIX syscalls are in the range from 1000 to 1999.
+ */
+#define TARGET_NR_Linux 1000
+
+/* syscalls as per IRIX /usr/include/sys.s */
+#define TARGET_NR_syscall (0+TARGET_NR_Linux)
+#define TARGET_NR_exit (1+TARGET_NR_Linux)
+#define TARGET_NR_fork (2+TARGET_NR_Linux)
+#define TARGET_NR_read (3+TARGET_NR_Linux)
+#define TARGET_NR_write (4+TARGET_NR_Linux)
+#define TARGET_NR_open (5+TARGET_NR_Linux)
+#define TARGET_NR_close (6+TARGET_NR_Linux)
+#define TARGET_NR_creat (8+TARGET_NR_Linux)
+#define TARGET_NR_link (9+TARGET_NR_Linux)
+#define TARGET_NR_unlink (10+TARGET_NR_Linux)
+#define TARGET_NR_execv (11+TARGET_NR_Linux)
+#define TARGET_NR_chdir (12+TARGET_NR_Linux)
+#define TARGET_NR_time (13+TARGET_NR_Linux)
+#define TARGET_NR_chmod (15+TARGET_NR_Linux)
+#define TARGET_NR_chown (16+TARGET_NR_Linux)
+#define TARGET_NR_brk (17+TARGET_NR_Linux)
+#define TARGET_NR_stat (18+TARGET_NR_Linux)
+#define TARGET_NR_lseek (19+TARGET_NR_Linux)
+#define TARGET_NR_getpid (20+TARGET_NR_Linux)
+#define TARGET_NR_mount (21+TARGET_NR_Linux)
+#define TARGET_NR_umount (22+TARGET_NR_Linux)
+#define TARGET_NR_setuid (23+TARGET_NR_Linux)
+#define TARGET_NR_getuid (24+TARGET_NR_Linux)
+#define TARGET_NR_stime (25+TARGET_NR_Linux)
+#define TARGET_NR_ptrace (26+TARGET_NR_Linux)
+#define TARGET_NR_alarm (27+TARGET_NR_Linux)
+#define TARGET_NR_pause (29+TARGET_NR_Linux)
+#define TARGET_NR_utime (30+TARGET_NR_Linux)
+#define TARGET_NR_access (33+TARGET_NR_Linux)
+#define TARGET_NR_nice (34+TARGET_NR_Linux)
+#define TARGET_NR_statfs (35+TARGET_NR_Linux)
+#define TARGET_NR_sync (36+TARGET_NR_Linux)
+#define TARGET_NR_kill (37+TARGET_NR_Linux)
+#define TARGET_NR_fstatfs (38+TARGET_NR_Linux)
+#define TARGET_NR_pgrpsys (39+TARGET_NR_Linux)
+#define TARGET_NR_syssgi (40+TARGET_NR_Linux)
+#define TARGET_NR_dup (41+TARGET_NR_Linux)
+#define TARGET_NR_pipe (42+TARGET_NR_Linux)
+#define TARGET_NR_times (43+TARGET_NR_Linux)
+#define TARGET_NR_profil (44+TARGET_NR_Linux)
+#define TARGET_NR_plock (45+TARGET_NR_Linux)
+#define TARGET_NR_setgid (46+TARGET_NR_Linux)
+#define TARGET_NR_getgid (47+TARGET_NR_Linux)
+#define TARGET_NR_msgsys (49+TARGET_NR_Linux)
+#define TARGET_NR_sysmips (50+TARGET_NR_Linux)
+#define TARGET_NR_acct (51+TARGET_NR_Linux)
+#define TARGET_NR_shmsys (52+TARGET_NR_Linux)
+#define TARGET_NR_semsys (53+TARGET_NR_Linux)
+#define TARGET_NR_ioctl (54+TARGET_NR_Linux)
+#define TARGET_NR_uadmin (55+TARGET_NR_Linux)
+#define TARGET_NR_sysmp (56+TARGET_NR_Linux)
+#define TARGET_NR_utssyssgi (57+TARGET_NR_Linux)
+#define TARGET_NR_execve (59+TARGET_NR_Linux)
+#define TARGET_NR_umask (60+TARGET_NR_Linux)
+#define TARGET_NR_chroot (61+TARGET_NR_Linux)
+#define TARGET_NR_fcntl (62+TARGET_NR_Linux)
+#define TARGET_NR_ulimit (63+TARGET_NR_Linux)
+#define TARGET_NR_getrlimit64 (75+TARGET_NR_Linux)
+#define TARGET_NR_setrlimit64 (76+TARGET_NR_Linux)
+#define TARGET_NR_nanosleep (77+TARGET_NR_Linux)
+#define TARGET_NR_lseek64 (78+TARGET_NR_Linux)
+#define TARGET_NR_rmdir (79+TARGET_NR_Linux)
+#define TARGET_NR_mkdir (80+TARGET_NR_Linux)
+#define TARGET_NR_getdents (81+TARGET_NR_Linux)
+#define TARGET_NR_sginap (82+TARGET_NR_Linux)
+#define TARGET_NR_sgikopt (83+TARGET_NR_Linux)
+#define TARGET_NR_sysfs (84+TARGET_NR_Linux)
+#define TARGET_NR_getmsg (85+TARGET_NR_Linux)
+#define TARGET_NR_putmsg (86+TARGET_NR_Linux)
+#define TARGET_NR_poll (87+TARGET_NR_Linux)
+#define TARGET_NR_sigreturn (88+TARGET_NR_Linux)
+#define TARGET_NR_accept (89+TARGET_NR_Linux)
+#define TARGET_NR_bind (90+TARGET_NR_Linux)
+#define TARGET_NR_connect (91+TARGET_NR_Linux)
+#define TARGET_NR_gethostid (92+TARGET_NR_Linux)
+#define TARGET_NR_getpeername (93+TARGET_NR_Linux)
+#define TARGET_NR_getsockname (94+TARGET_NR_Linux)
+#define TARGET_NR_getsockopt (95+TARGET_NR_Linux)
+#define TARGET_NR_listen (96+TARGET_NR_Linux)
+#define TARGET_NR_recv (97+TARGET_NR_Linux)
+#define TARGET_NR_recvfrom (98+TARGET_NR_Linux)
+#define TARGET_NR_recvmsg (99+TARGET_NR_Linux)
+#define TARGET_NR_select (100+TARGET_NR_Linux)
+#define TARGET_NR_send (101+TARGET_NR_Linux)
+#define TARGET_NR_sendmsg (102+TARGET_NR_Linux)
+#define TARGET_NR_sendto (103+TARGET_NR_Linux)
+#define TARGET_NR_sethostid (104+TARGET_NR_Linux)
+#define TARGET_NR_setsockopt (105+TARGET_NR_Linux)
+#define TARGET_NR_shutdown (106+TARGET_NR_Linux)
+#define TARGET_NR_socket (107+TARGET_NR_Linux)
+#define TARGET_NR_gethostname (108+TARGET_NR_Linux)
+#define TARGET_NR_sethostname (109+TARGET_NR_Linux)
+#define TARGET_NR_getdomainname (110+TARGET_NR_Linux)
+#define TARGET_NR_setdomainname (111+TARGET_NR_Linux)
+#define TARGET_NR_truncate (112+TARGET_NR_Linux)
+#define TARGET_NR_ftruncate (113+TARGET_NR_Linux)
+#define TARGET_NR_rename (114+TARGET_NR_Linux)
+#define TARGET_NR_symlink (115+TARGET_NR_Linux)
+#define TARGET_NR_readlink (116+TARGET_NR_Linux)
+#define TARGET_NR_nfssvc (119+TARGET_NR_Linux)
+#define TARGET_NR_getfh (120+TARGET_NR_Linux)
+#define TARGET_NR_async_daemons (121+TARGET_NR_Linux)
+#define TARGET_NR_exportfs (122+TARGET_NR_Linux)
+#define TARGET_NR_setregid (123+TARGET_NR_Linux)
+#define TARGET_NR_setreuid (124+TARGET_NR_Linux)
+#define TARGET_NR_getitimer (125+TARGET_NR_Linux)
+#define TARGET_NR_setitimer (126+TARGET_NR_Linux)
+#define TARGET_NR_adjtime (127+TARGET_NR_Linux)
+#define TARGET_NR_gettimeofday (128+TARGET_NR_Linux)
+#define TARGET_NR_sproc (129+TARGET_NR_Linux)
+#define TARGET_NR_sgiprctl (130+TARGET_NR_Linux)
+#define TARGET_NR_procblk (131+TARGET_NR_Linux)
+#define TARGET_NR_sprocsp (132+TARGET_NR_Linux)
+#define TARGET_NR_mmap (134+TARGET_NR_Linux)
+#define TARGET_NR_munmap (135+TARGET_NR_Linux)
+#define TARGET_NR_mprotect (136+TARGET_NR_Linux)
+#define TARGET_NR_msync (137+TARGET_NR_Linux)
+#define TARGET_NR_madvise (138+TARGET_NR_Linux)
+#define TARGET_NR_pagelock (139+TARGET_NR_Linux)
+#define TARGET_NR_getpagesize (140+TARGET_NR_Linux)
+#define TARGET_NR_quotactl (141+TARGET_NR_Linux)
+#define TARGET_NR_getpgid (143+TARGET_NR_Linux)
+#define TARGET_NR_setpgid (144+TARGET_NR_Linux)
+#define TARGET_NR_vhangup (145+TARGET_NR_Linux)
+#define TARGET_NR_fsync (146+TARGET_NR_Linux)
+#define TARGET_NR_fchdir (147+TARGET_NR_Linux)
+#define TARGET_NR_getrlimit (148+TARGET_NR_Linux)
+#define TARGET_NR_setrlimit (149+TARGET_NR_Linux)
+#define TARGET_NR_cacheflush (150+TARGET_NR_Linux)
+#define TARGET_NR_cachectl (151+TARGET_NR_Linux)
+#define TARGET_NR_fchown (152+TARGET_NR_Linux)
+#define TARGET_NR_fchmod (153+TARGET_NR_Linux)
+#define TARGET_NR_socketpair (155+TARGET_NR_Linux)
+#define TARGET_NR_sysinfosgi (156+TARGET_NR_Linux)
+#define TARGET_NR_uname (157+TARGET_NR_Linux)
+#define TARGET_NR_xstat (158+TARGET_NR_Linux)
+#define TARGET_NR_lxstat (159+TARGET_NR_Linux)
+#define TARGET_NR_fxstat (160+TARGET_NR_Linux)
+#define TARGET_NR_xmknod (161+TARGET_NR_Linux)
+#define TARGET_NR_sigaction (162+TARGET_NR_Linux)
+#define TARGET_NR_sigpending (163+TARGET_NR_Linux)
+#define TARGET_NR_sigprocmask (164+TARGET_NR_Linux)
+#define TARGET_NR_sigsuspend (165+TARGET_NR_Linux)
+#define TARGET_NR_sigpoll (166+TARGET_NR_Linux)
+#define TARGET_NR_swapctl (167+TARGET_NR_Linux)
+#define TARGET_NR_getcontext (168+TARGET_NR_Linux)
+#define TARGET_NR_setcontext (169+TARGET_NR_Linux)
+#define TARGET_NR_waitid (170+TARGET_NR_Linux)
+#define TARGET_NR_sigstack (171+TARGET_NR_Linux)
+#define TARGET_NR_sigaltstack (172+TARGET_NR_Linux)
+#define TARGET_NR_sigsendset (173+TARGET_NR_Linux)
+#define TARGET_NR_statvfs (174+TARGET_NR_Linux)
+#define TARGET_NR_fstatvfs (175+TARGET_NR_Linux)
+#define TARGET_NR_getpmsg (176+TARGET_NR_Linux)
+#define TARGET_NR_putpmsg (177+TARGET_NR_Linux)
+#define TARGET_NR_lchown (178+TARGET_NR_Linux)
+#define TARGET_NR_priocntl (179+TARGET_NR_Linux)
+#define TARGET_NR_ksigqueue (180+TARGET_NR_Linux)
+#define TARGET_NR_readv (181+TARGET_NR_Linux)
+#define TARGET_NR_writev (182+TARGET_NR_Linux)
+#define TARGET_NR_truncate64 (183+TARGET_NR_Linux)
+#define TARGET_NR_ftruncate64 (184+TARGET_NR_Linux)
+#define TARGET_NR_mmap64 (185+TARGET_NR_Linux)
+#define TARGET_NR_dmi (186+TARGET_NR_Linux)
+#define TARGET_NR_pread64 (187+TARGET_NR_Linux)
+#define TARGET_NR_pwrite64 (188+TARGET_NR_Linux)
+#define TARGET_NR_fdatasync (189+TARGET_NR_Linux)
+#define TARGET_NR_sgifastpath (190+TARGET_NR_Linux)
+#define TARGET_NR_attr_get (191+TARGET_NR_Linux)
+#define TARGET_NR_attr_getf (192+TARGET_NR_Linux)
+#define TARGET_NR_attr_set (193+TARGET_NR_Linux)
+#define TARGET_NR_attr_setf (194+TARGET_NR_Linux)
+#define TARGET_NR_attr_remove (195+TARGET_NR_Linux)
+#define TARGET_NR_attr_removef (196+TARGET_NR_Linux)
+#define TARGET_NR_attr_list (197+TARGET_NR_Linux)
+#define TARGET_NR_attr_listf (198+TARGET_NR_Linux)
+#define TARGET_NR_attr_multi (199+TARGET_NR_Linux)
+#define TARGET_NR_attr_multif (200+TARGET_NR_Linux)
+#define TARGET_NR_statvfs64 (201+TARGET_NR_Linux)
+#define TARGET_NR_fstatvfs64 (202+TARGET_NR_Linux)
+#define TARGET_NR_getmountid (203+TARGET_NR_Linux)
+#define TARGET_NR_nsproc (204+TARGET_NR_Linux)
+#define TARGET_NR_getdents64 (205+TARGET_NR_Linux)
+#define TARGET_NR_afs_syscall (206+TARGET_NR_Linux)
+#define TARGET_NR_ngetdents (207+TARGET_NR_Linux)
+#define TARGET_NR_ngetdents64 (208+TARGET_NR_Linux)
+#define TARGET_NR_sgi_sesmgr (209+TARGET_NR_Linux)
+#define TARGET_NR_pidsprocsp (210+TARGET_NR_Linux)
+#define TARGET_NR_rexec (211+TARGET_NR_Linux)
+#define TARGET_NR_timer_create (212+TARGET_NR_Linux)
+#define TARGET_NR_timer_delete (213+TARGET_NR_Linux)
+#define TARGET_NR_timer_settime (214+TARGET_NR_Linux)
+#define TARGET_NR_timer_gettime (215+TARGET_NR_Linux)
+#define TARGET_NR_timer_getoverrun (216+TARGET_NR_Linux)
+#define TARGET_NR_sched_rr_get_interval (217+TARGET_NR_Linux)
+#define TARGET_NR_sched_yield (218+TARGET_NR_Linux)
+#define TARGET_NR_sched_getscheduler (219+TARGET_NR_Linux)
+#define TARGET_NR_sched_setscheduler (220+TARGET_NR_Linux)
+#define TARGET_NR_sched_getparam (221+TARGET_NR_Linux)
+#define TARGET_NR_sched_setparam (222+TARGET_NR_Linux)
+#define TARGET_NR_usync_cntl (223+TARGET_NR_Linux)
+#define TARGET_NR_psema_cntl (224+TARGET_NR_Linux)
+#define TARGET_NR_restartreturn (225+TARGET_NR_Linux)
+#define TARGET_NR_sysget (226+TARGET_NR_Linux)
+#define TARGET_NR_xpg4_recvmsg (227+TARGET_NR_Linux)
+#define TARGET_NR_umfscall (228+TARGET_NR_Linux)
+#define TARGET_NR_nsproctid (229+TARGET_NR_Linux)
+#define TARGET_NR_rexec_complete (230+TARGET_NR_Linux)
+#define TARGET_NR_xpg4_sigaltstack (231+TARGET_NR_Linux)
+#define TARGET_NR_xpg4_select (232+TARGET_NR_Linux)
+#define TARGET_NR_xpg4_setregid (233+TARGET_NR_Linux)
+#define TARGET_NR_linkfollow (234+TARGET_NR_Linux)
+
+
+/* msgsys(cmd, ...), same as solaris... */
+#define TARGET_NR_msgsys_msgget 0
+#define TARGET_NR_msgsys_msgctl 1
+#define TARGET_NR_msgsys_msgrcv 2
+#define TARGET_NR_msgsys_msgsnd 3
+
+
+/* shmsys(cmd, ...), same as solaris... */
+#define TARGET_NR_shmsys_shmat 0
+#define TARGET_NR_shmsys_shmctl 1
+#define TARGET_NR_shmsys_shmdt 2
+#define TARGET_NR_shmsys_shmget 3
+
+
+/* semsys(cmd, ...), same as solaris... */
+#define TARGET_NR_semsys_semctl 0
+#define TARGET_NR_semsys_semget 1
+#define TARGET_NR_semsys_semop 2
+
+
+/* pgrpsys(cmd), same as solaris... */
+#define TARGET_NR_pgrpsys_getpgrp 0
+#define TARGET_NR_pgrpsys_setpgrp 1
+
+
+/* syssgi(cmd, ...) */
+#define TARGET_NR_syssgi_setsid (20)
+#define TARGET_NR_syssgi_setpgid (21)
+#define TARGET_NR_syssgi_sysconf (22)
+#define TARGET_NR_syssgi_pathconf (23)
+#define TARGET_NR_syssgi_setgroups (40)
+#define TARGET_NR_syssgi_getgroups (41)
+#define TARGET_NR_syssgi_settimeofday (52)
+#define TARGET_NR_syssgi_rusage (56)
+#define TARGET_NR_syssgi_sigaltstack (60)
+#define TARGET_NR_syssgi_getpgid (64)
+#define TARGET_NR_syssgi_getsid (65)
+/* SGI specific syssgi calls */
+#define TARGET_NR_syssgi_sysid (1)
+#define TARGET_NR_syssgi_elfmap (68)
+#define TARGET_NR_syssgi_rldenv (92)
+#define TARGET_NR_syssgi_tosstsave (108)
+#define TARGET_NR_syssgi_fdhi (109)
+#define TARGET_NR_syssgi_fpbcopy (129)
+#define TARGET_NR_syssgi_getust (130)
+
+
+/* syssgi(sysconf, cmd, ...) */
+#define TARGET_NR_sysconf_childmax (2)
+#define TARGET_NR_sysconf_clktick (3)
+#define TARGET_NR_sysconf_openmax (5)
+#define TARGET_NR_sysconf_pagesize (11)
+#define TARGET_NR_sysconf_nprocs (14)
+#define TARGET_NR_sysconf_acl (25)
+#define TARGET_NR_sysconf_mac (28)
+#define TARGET_NR_sysconf_cap (29)
+
+
+/* sysmp(cmd, ...) */
+#define TARGET_NR_sysmp_nprocs (1)
+#define TARGET_NR_sysmp_naprocs (2)
+#define TARGET_NR_sysmp_pgsize (14)
+
+
+/* prctl(cmd, ...) */
+#define TARGET_NR_prctl_isblocked (2)
+#define TARGET_NR_prctl_maxpprocs (5)
+#define TARGET_NR_prctl_unblkonexec (6)
+#define TARGET_NR_prctl_setexitsig (8)
+#define TARGET_NR_prctl_termchild (12)
+#define TARGET_NR_prctl_getnshare (14)
+#define TARGET_NR_prctl_initthreads (20)
+#define TARGET_NR_prctl_threadctl (21)
+#define TARGET_NR_prctl_lastshexit (22)
+
+
+/* prctl(TARGET_NR_prctl_threadctl, cmd, ...) */
+#define TARGET_NR_prctl_thread_exit (1)
+#define TARGET_NR_prctl_thread_block (2)
+#define TARGET_NR_prctl_thread_unblock (3)
+#define TARGET_NR_prctl_thread_kill (4)
+#define TARGET_NR_prctl_thread_sched (5)
+
+
+/* procblk(cmd, ...) */
+#define TARGET_NR_procblk_block (0)
+#define TARGET_NR_procblk_unblock (1)
+#define TARGET_NR_procblk_count (2)
+
+
+/* usync_cntl(cmd, ...), list from netbsd 5.2 */
+#define TARGET_NR_usync_block (1)
+#define TARGET_NR_usync_intr_block (2)
+#define TARGET_NR_usync_unblock_all (3)
+#define TARGET_NR_usync_unblock (4)
+#define TARGET_NR_usync_notify_register (5)
+#define TARGET_NR_usync_notify (6)
+#define TARGET_NR_usync_notify_delete (7)
+#define TARGET_NR_usync_notify_clear (8)
+#define TARGET_NR_usync_get_state (11)
+#define TARGET_NR_usync_handoff (12)
+
+
+/* psema_cntl(cmd, ...), list from /usr/sbin/par */
+#define TARGET_NR_psema_open (1)
+#define TARGET_NR_psema_close (2)
+#define TARGET_NR_psema_unlink (3)
+#define TARGET_NR_psema_post (4)
+#define TARGET_NR_psema_wait (5)
+#define TARGET_NR_psema_trywait (6)
+#define TARGET_NR_psema_getvalue (7)
+#define TARGET_NR_psema_wait2 (9)
+
+
+/* swapctl(cmd, arg) */
+#define TARGET_NR_swapctl_getfree (103)
+
+
+/* sysinfosgi(cmd, buf, size) */
+#define TARGET_NR_sysinfo_gethostname 2
+#define TARGET_NR_sysinfo_sethostname 258
+#define TARGET_NR_sysinfo_getsrpcdomain 9
+#define TARGET_NR_sysinfo_setsrpcdomain 265
+#define TARGET_NR_sysinfo_sysname 1
+#define TARGET_NR_sysinfo_release 3
+#define TARGET_NR_sysinfo_version 4
+#define TARGET_NR_sysinfo_machine 5
+#define TARGET_NR_sysinfo_cpuarch 6
+#define TARGET_NR_sysinfo_hwserial 7
+#define TARGET_NR_sysinfo_hwproducer 8
+#define TARGET_NR_sysinfo_processors 109
+
+
+/* utssyssgi(obuf, ibuf, cmd) */
+#define TARGET_NR_utssys_uname (0)
diff --git a/linux-user/irix/target_cpu.h b/linux-user/irix/target_cpu.h
new file mode 100644
index 0000000000..51b9fecd26
--- /dev/null
+++ b/linux-user/irix/target_cpu.h
@@ -0,0 +1,36 @@
+/*
+ * MIPS specific CPU ABI and functions for linux-user
+ *
+ * Copyright (c) 2004-2005 Jocelyn Mayer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+#ifndef IRIX_TARGET_CPU_H
+#define IRIX_TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUMIPSState *env, target_ulong newsp)
+{
+ if (newsp) {
+ env->active_tc.gpr[29] = newsp;
+ }
+ env->active_tc.gpr[7] = 0;
+ env->active_tc.gpr[2] = 0;
+}
+
+static inline void cpu_set_tls(CPUMIPSState *env, target_ulong newtls)
+{
+ env->active_tc.CP0_UserLocal = newtls;
+}
+
+#endif
diff --git a/linux-user/irix/target_elf.h b/linux-user/irix/target_elf.h
new file mode 100644
index 0000000000..fa3de8de03
--- /dev/null
+++ b/linux-user/irix/target_elf.h
@@ -0,0 +1,20 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation, or (at your option) any
+ * later version. See the COPYING file in the top-level directory.
+ */
+
+#ifndef MIPS_TARGET_ELF_H
+#define MIPS_TARGET_ELF_H
+static inline const char *cpu_get_model(uint32_t eflags)
+{
+ /* O32 is MIPS I and MIPS II ISA, N32/N64 is MIPS III and MIPS IV ISA */
+ if ((eflags & EF_MIPS_ARCH) == EF_MIPS_ARCH_1 ||
+ (eflags & EF_MIPS_ARCH) == EF_MIPS_ARCH_2) {
+ return "24Kf"; // MIPS32
+// return "R4000";
+ }
+ return "5Kf"; // MIPS64
+}
+#endif
diff --git a/linux-user/irix/target_signal.h b/linux-user/irix/target_signal.h
new file mode 100644
index 0000000000..01e461d2b4
--- /dev/null
+++ b/linux-user/irix/target_signal.h
@@ -0,0 +1,66 @@
+#ifndef IRIX_TARGET_SIGNAL_H
+#define IRIX_TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+#ifdef TARGET_ABI32
+ abi_uint ss_sp;
+#else
+ abi_ulong ss_sp;
+#endif
+ uint32_t ss_size;
+ abi_int ss_flags;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK 1
+#define TARGET_SS_DISABLE 2
+
+#define TARGET_MINSIGSTKSZ 2048
+#define TARGET_SIGSTKSZ 8192
+
+static inline target_ulong get_sp_from_cpustate(CPUMIPSState *state)
+{
+ return state->active_tc.gpr[29];
+}
+
+struct target_mcontext32 {
+ uint32_t gregs[36];
+ double fregs[16];
+ uint32_t fpcsr;
+};
+
+struct target_mcontext64 {
+ uint64_t gregs[37];
+ double fregs[32];
+ uint32_t fpcsr;
+};
+
+struct target_mcontext {
+ union {
+ struct target_mcontext32 _32;
+ struct target_mcontext64 _64;
+ } mc;
+};
+
+struct target_ucontext {
+ abi_ulong tuc_flags;
+#ifdef TARGET_ABI32
+ abi_uint tuc_link;
+#else
+ abi_ulong tuc_link;
+#endif
+ target_sigset_t tuc_sigmask;
+ struct target_sigaltstack tuc_stack;
+ struct target_mcontext tuc_mcontext;
+};
+
+int save_context(CPUMIPSState *regs, struct target_mcontext *sc, int setret);
+int restore_context(CPUMIPSState *regs, struct target_mcontext *sc);
+#endif /* TARGET_SIGNAL_H */
diff --git a/linux-user/irix/target_structs.h b/linux-user/irix/target_structs.h
new file mode 100644
index 0000000000..021f67db40
--- /dev/null
+++ b/linux-user/irix/target_structs.h
@@ -0,0 +1,55 @@
+/*
+ * MIPS specific structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+#ifndef IRIX_TARGET_STRUCTS_H
+#define IRIX_TARGET_STRUCTS_H
+
+struct target_ipc_perm {
+ abi_uint uid; /* Owner's user ID. */
+ abi_uint gid; /* Owner's group ID. */
+ abi_uint cuid; /* Creator's user ID. */
+ abi_uint cgid; /* Creator's group ID. */
+ abi_uint mode; /* Read/write permission. */
+ abi_ulong __seq; /* Sequence number. */
+ abi_int __key; /* Key. */
+ abi_ulong __pad1[4];
+};
+
+struct target_shmid_ds {
+ struct target_ipc_perm shm_perm; /* operation permission struct */
+#ifdef TARGET_ABI32
+ abi_int shm_segsz; /* size of segment in bytes */
+ abi_ulong shm_amp;
+ short shm_lkcnt;
+ short __pad0;
+#else
+ abi_int shm_osegsz;
+ abi_long shm_segsz; /* size of segment in bytes */
+ abi_int __pad0;
+#endif
+ abi_int shm_lpid; /* pid of last shmop */
+ abi_int shm_cpid; /* pid of creator */
+ abi_ulong shm_nattch; /* number of current attaches */
+ abi_ulong shm_cnattch; /* number of current attaches */
+ abi_ulong shm_atime; /* time of last shmat() */
+ abi_ulong shm_dtime; /* time of last shmdt() */
+ abi_ulong shm_ctime; /* time of last change by shmctl() */
+ abi_ulong __pad1[4];
+};
+
+#endif
diff --git a/linux-user/irix/target_syscall.h b/linux-user/irix/target_syscall.h
new file mode 100644
index 0000000000..581d8bc829
--- /dev/null
+++ b/linux-user/irix/target_syscall.h
@@ -0,0 +1,30 @@
+#ifndef IRIX_TARGET_SYSCALL_H
+#define IRIX_TARGET_SYSCALL_H
+
+/* this struct defines the way the registers are stored on the
+ stack during a system call. */
+
+struct target_pt_regs {
+ /* Saved main processor registers. */
+ target_ulong regs[32];
+
+ /* Saved special registers. */
+ target_ulong cp0_status;
+ target_ulong lo;
+ target_ulong hi;
+ target_ulong cp0_badvaddr;
+ target_ulong cp0_cause;
+ target_ulong cp0_epc;
+};
+
+#define UNAME_MACHINE "irix"
+#define UNAME_MINIMUM_RELEASE "2.6.32"
+
+#define TARGET_FORCE_SHMLBA
+
+static inline abi_ulong target_shmlba(CPUMIPSState *env)
+{
+ return 0x40000;
+}
+
+#endif
diff --git a/linux-user/irix/termbits.h b/linux-user/irix/termbits.h
new file mode 100644
index 0000000000..4bcd45cb48
--- /dev/null
+++ b/linux-user/irix/termbits.h
@@ -0,0 +1,260 @@
+/* from asm/termbits.h */
+
+#define TARGET_NCCS 23
+
+struct target_termios {
+ unsigned int c_iflag; /* input mode flags */
+ unsigned int c_oflag; /* output mode flags */
+ unsigned int c_cflag; /* control mode flags */
+ unsigned int c_lflag; /* local mode flags */
+#ifdef IRIX_NEW_TERMIO
+ unsigned int c_ospeed;
+ unsigned int c_ispeed;
+#endif
+ unsigned char c_cc[TARGET_NCCS]; /* control characters */
+};
+
+/* c_iflag bits */
+#define TARGET_IGNBRK 0000001
+#define TARGET_BRKINT 0000002
+#define TARGET_IGNPAR 0000004
+#define TARGET_PARMRK 0000010
+#define TARGET_INPCK 0000020
+#define TARGET_ISTRIP 0000040
+#define TARGET_INLCR 0000100
+#define TARGET_IGNCR 0000200
+#define TARGET_ICRNL 0000400
+#define TARGET_IUCLC 0001000
+#define TARGET_IXON 0002000
+#define TARGET_IXANY 0004000
+#define TARGET_IXOFF 0010000
+#define TARGET_IMAXBEL 0020000
+#define TARGET_IUTF8 0040000
+
+/* c_oflag bits */
+#define TARGET_OPOST 0000001
+#define TARGET_OLCUC 0000002
+#define TARGET_ONLCR 0000004
+#define TARGET_OCRNL 0000010
+#define TARGET_ONOCR 0000020
+#define TARGET_ONLRET 0000040
+#define TARGET_OFILL 0000100
+#define TARGET_OFDEL 0000200
+#define TARGET_NLDLY 0000400
+#define TARGET_NL0 0000000
+#define TARGET_NL1 0000400
+#define TARGET_CRDLY 0003000
+#define TARGET_CR0 0000000
+#define TARGET_CR1 0001000
+#define TARGET_CR2 0002000
+#define TARGET_CR3 0003000
+#define TARGET_TABDLY 0014000
+#define TARGET_TAB0 0000000
+#define TARGET_TAB1 0004000
+#define TARGET_TAB2 0010000
+#define TARGET_TAB3 0014000
+#define TARGET_XTABS 0014000
+#define TARGET_BSDLY 0020000
+#define TARGET_BS0 0000000
+#define TARGET_BS1 0020000
+#define TARGET_VTDLY 0040000
+#define TARGET_VT0 0000000
+#define TARGET_VT1 0040000
+#define TARGET_FFDLY 0100000
+#define TARGET_FF0 0000000
+#define TARGET_FF1 0100000
+
+/* c_cflag bit meaning */
+#define TARGET_CBAUD 0010017
+#define TARGET_B0 0000000 /* hang up */
+#define TARGET_B50 0000001
+#define TARGET_B75 0000002
+#define TARGET_B110 0000003
+#define TARGET_B134 0000004
+#define TARGET_B150 0000005
+#define TARGET_B200 0000006
+#define TARGET_B300 0000007
+#define TARGET_B600 0000010
+#define TARGET_B1200 0000011
+#define TARGET_B1800 0000012
+#define TARGET_B2400 0000013
+#define TARGET_B4800 0000014
+#define TARGET_B9600 0000015
+#define TARGET_B19200 0000016
+#define TARGET_B38400 0000017
+#define TARGET_EXTA B19200
+#define TARGET_EXTB B38400
+#define TARGET_CSIZE 0000060
+#define TARGET_CS5 0000000
+#define TARGET_CS6 0000020
+#define TARGET_CS7 0000040
+#define TARGET_CS8 0000060
+#define TARGET_CSTOPB 0000100
+#define TARGET_CREAD 0000200
+#define TARGET_PARENB 0000400
+#define TARGET_PARODD 0001000
+#define TARGET_HUPCL 0002000
+#define TARGET_CLOCAL 0004000
+#define TARGET_CBAUDEX 0010000
+#define TARGET_BOTHER 0010000
+#define TARGET_B57600 0010001
+#define TARGET_B115200 0010002
+#define TARGET_B230400 0010003
+#define TARGET_B460800 0010004
+#define TARGET_B500000 0010005
+#define TARGET_B576000 0010006
+#define TARGET_B921600 0010007
+#define TARGET_B1000000 0010010
+#define TARGET_B1152000 0010011
+#define TARGET_B1500000 0010012
+#define TARGET_B2000000 0010013
+#define TARGET_B2500000 0010014
+#define TARGET_B3000000 0010015
+#define TARGET_B3500000 0010016
+#define TARGET_B4000000 0010017
+#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */
+#define TARGET_CMSPAR 010000000000 /* mark or space (stick) parity */
+#define TARGET_CRTSCTS 020000000000 /* flow control */
+
+/* c_lflag bits */
+#define TARGET_ISIG 0000001
+#define TARGET_ICANON 0000002
+#define TARGET_XCASE 0000004
+#define TARGET_ECHO 0000010
+#define TARGET_ECHOE 0000020
+#define TARGET_ECHOK 0000040
+#define TARGET_ECHONL 0000100
+#define TARGET_NOFLSH 0000200
+#define TARGET_IEXTEN 0000400
+#define TARGET_ECHOCTL 0001000
+#define TARGET_ECHOPRT 0002000
+#define TARGET_ECHOKE 0004000
+#define TARGET_FLUSHO 0010000
+#define TARGET_PENDIN 0040000
+#define TARGET_TOSTOP 0100000
+#define TARGET_ITOSTOP TARGET_TOSTOP
+
+/* c_cc character offsets */
+#define TARGET_VINTR 0
+#define TARGET_VQUIT 1
+#define TARGET_VERASE 2
+#define TARGET_VKILL 3
+#define TARGET_VMIN 4
+#define TARGET_VTIME 5
+#define TARGET_VEOL2 6
+#define TARGET_VSWTC 7
+#define TARGET_VSTART 8
+#define TARGET_VSTOP 9
+#define TARGET_VSUSP 10
+/* VDSUSP not supported */
+#define TARGET_VREPRINT 12
+#define TARGET_VDISCARD 13
+#define TARGET_VWERASE 14
+#define TARGET_VLNEXT 15
+#define TARGET_VEOF 16
+#define TARGET_VEOL 17
+
+/* ioctls */
+
+#ifdef IRIX_NEW_TERMIO
+#define TARGET_TCGETA 0x54c9
+#define TARGET_TCSETA 0x54ca
+#define TARGET_TCSETAW 0x54cb
+#define TARGET_TCSETAF 0x54cc
+#else
+#define TARGET_TCGETA 0x5401
+#define TARGET_TCSETA 0x5402
+#define TARGET_TCSETAW 0x5403
+#define TARGET_TCSETAF 0x5404
+#endif
+
+#define TARGET_TCSBRK 0x5405
+#define TARGET_TCXONC 0x5406
+#define TARGET_TCFLSH 0x5407
+
+#define TARGET_TCGETS 0x540d
+#define TARGET_TCSETS 0x540e
+#define TARGET_TCSETSW 0x540f
+#define TARGET_TCSETSF 0x5410
+
+#define TARGET_TCNGETS 0x54d5
+#define TARGET_TCNSETS 0x54d6
+#define TARGET_TCNSETSW 0x54d7
+#define TARGET_TCNSETSF 0x54d8
+
+#define TARGET_TIOCEXCL 0x740d /* set exclusive use of tty */
+#define TARGET_TIOCNXCL 0x740e /* reset exclusive use of tty */
+#define TARGET_TIOCOUTQ 0x7472 /* output queue size */
+#define TARGET_TIOCSTI 0x5472 /* simulate terminal input */
+#define TARGET_TIOCMGET 0x741d /* get all modem bits */
+#define TARGET_TIOCMBIS 0x741b /* bis modem bits */
+#define TARGET_TIOCMBIC 0x741c /* bic modem bits */
+#define TARGET_TIOCMSET 0x741a /* set all modem bits */
+#define TARGET_TIOCPKT 0x5470 /* pty: set/clear packet mode */
+#define TARGET_TIOCPKT_DATA 0x00 /* data packet */
+#define TARGET_TIOCPKT_FLUSHREAD 0x01 /* flush packet */
+#define TARGET_TIOCPKT_FLUSHWRITE 0x02 /* flush packet */
+#define TARGET_TIOCPKT_STOP 0x04 /* stop output */
+#define TARGET_TIOCPKT_START 0x08 /* start output */
+#define TARGET_TIOCPKT_NOSTOP 0x10 /* no more ^S, ^Q */
+#define TARGET_TIOCPKT_DOSTOP 0x20 /* now do ^S ^Q */
+/* #define TIOCPKT_IOCTL 0x40 state change of pty driver */
+#define TARGET_TIOCSWINSZ TARGET_IOW('t', 103, struct winsize) /* set window size */
+#define TARGET_TIOCGWINSZ TARGET_IOR('t', 104, struct winsize) /* get window size */
+#define TARGET_TIOCNOTTY 0x5471 /* void tty association */
+#define TARGET_TIOCSETD 0x7401
+#define TARGET_TIOCGETD 0x7400
+
+#define TARGET_FIOCLEX 0x6601
+#define TARGET_FIONCLEX 0x6602
+#define TARGET_FIOASYNC 0x667d
+#define TARGET_FIONBIO 0x667e
+#define TARGET_FIOQSIZE 0x667f
+
+#define TARGET_TIOCGLTC 0x7474 /* get special local chars */
+#define TARGET_TIOCSLTC 0x7475 /* set special local chars */
+#define TARGET_TIOCSPGRP TARGET_IOW('t', 118, int) /* set pgrp of tty */
+#define TARGET_TIOCGPGRP TARGET_IOR('t', 119, int) /* get pgrp of tty */
+#define TARGET_TIOCCONS TARGET_IOW('t', 120, int) /* become virtual console */
+
+#define TARGET_FIONREAD 0x467f
+#define TARGET_TIOCINQ TARGET_FIONREAD
+
+#define TARGET_TIOCGETP 0x7408
+#define TARGET_TIOCSETP 0x7409
+#define TARGET_TIOCSETN 0x740a /* TIOCSETP wo flush */
+
+/* #define TARGET_TIOCSETA TARGET_IOW('t', 20, struct termios) set termios struct */
+/* #define TARGET_TIOCSETAW TARGET_IOW('t', 21, struct termios) drain output, set */
+/* #define TARGET_TIOCSETAF TARGET_IOW('t', 22, struct termios) drn out, fls in, set */
+/* #define TARGET_TIOCGETD TARGET_IOR('t', 26, int) get line discipline */
+/* #define TARGET_TIOCSETD TARGET_IOW('t', 27, int) set line discipline */
+ /* 127-124 compat */
+
+#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */
+#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */
+#define TARGET_TIOCGSID 0x7416 /* Return the session ID of FD */
+#define TARGET_TIOCGPTN TARGET_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define TARGET_TIOCSPTLCK TARGET_IOW('T',0x31, int) /* Lock/unlock Pty */
+
+/* I hope the range from 0x5480 on is free ... */
+#define TARGET_TIOCSCTTY 0x5480 /* become controlling tty */
+#define TARGET_TIOCGSOFTCAR 0x5481
+#define TARGET_TIOCSSOFTCAR 0x5482
+#define TARGET_TIOCLINUX 0x5483
+#define TARGET_TIOCGSERIAL 0x5484
+#define TARGET_TIOCSSERIAL 0x5485
+#define TARGET_TCSBRKP 0x5486 /* Needed for POSIX tcsendbreak() */
+#define TARGET_TIOCSERCONFIG 0x5488
+#define TARGET_TIOCSERGWILD 0x5489
+#define TARGET_TIOCSERSWILD 0x548a
+#define TARGET_TIOCGLCKTRMIOS 0x548b
+#define TARGET_TIOCSLCKTRMIOS 0x548c
+#define TARGET_TIOCSERGSTRUCT 0x548d /* For debugging only */
+#define TARGET_TIOCSERGETLSR 0x548e /* Get line status register */
+#define TARGET_TIOCSERGETMULTI 0x548f /* Get multiport config */
+#define TARGET_TIOCSERSETMULTI 0x5490 /* Set multiport config */
+#define TARGET_TIOCMIWAIT 0x5491 /* wait for a change on serial input line(s) */
+#define TARGET_TIOCGICOUNT 0x5492 /* read serial port inline interrupt counts */
+#define TARGET_TIOCGHAYESESP 0x5493 /* Get Hayes ESP configuration */
+#define TARGET_TIOCSHAYESESP 0x5494 /* Set Hayes ESP configuration */
diff --git a/linux-user/main.c b/linux-user/main.c
index 7bc9bc79b0..8f6475bb99 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -126,7 +126,7 @@ int cpu_get_pic_interrupt(CPUX86State *env)
/* Helper routines for implementing atomic operations. */
/* Make sure everything is in a consistent state for calling fork(). */
-void fork_start(void)
+void fork_start(CPUArchState *env)
{
start_exclusive();
mmap_fork_start();
@@ -134,21 +134,21 @@ void fork_start(void)
cpu_list_lock();
}
-void fork_end(int child)
+void fork_end(CPUArchState *env, int child)
{
mmap_fork_end(child);
if (child) {
- CPUState *cpu, *next_cpu;
+ CPUState *cpu, *next_cpu, *cur_cpu = ENV_GET_CPU(env);
/* Child processes created by fork() only have a single thread.
Discard information about the parent threads. */
CPU_FOREACH_SAFE(cpu, next_cpu) {
- if (cpu != thread_cpu) {
+ if (cpu != cur_cpu) {
QTAILQ_REMOVE(&cpus, cpu, node);
}
}
qemu_mutex_init(&tb_ctx.tb_lock);
qemu_init_cpu_list();
- gdbserver_fork(thread_cpu);
+ gdbserver_fork(cur_cpu);
/* qemu_init_cpu_list() takes care of reinitializing the
* exclusive state, so we don't need to end_exclusive() here.
*/
@@ -1066,7 +1066,7 @@ static void restore_window(CPUSPARCState *env)
#endif
}
-static void flush_windows(CPUSPARCState *env)
+void flush_windows(CPUSPARCState *env)
{
int offset, cwp1;
@@ -1158,6 +1158,38 @@ void cpu_loop (CPUSPARCState *env)
env->pc = env->npc;
env->npc = env->npc + 4;
break;
+#ifdef TARGET_ABI_SOLARIS
+ case 0xa4: /* gethrtime() */
+ {
+ struct timespec ts;
+ unsigned long long tm;
+ clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
+
+ tm = ts.tv_sec * 1000000000LL + ts.tv_nsec;
+ env->regwptr[0] = (uint32_t)(tm >> 32);
+ env->regwptr[1] = (uint32_t)(tm);
+ if (do_strace)
+ gemu_log("%d gethrtime() = %llu\n", getpid(), tm);
+ }
+ /* next instruction */
+ env->pc = env->npc;
+ env->npc = env->npc + 4;
+ break;
+ case 0xa7: /* gethrestime() */
+ {
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+
+ env->regwptr[0] = ts.tv_sec;
+ env->regwptr[1] = ts.tv_nsec;
+ if (do_strace)
+ gemu_log("%d gethrestime() = %lu\n", getpid(), ts.tv_sec);
+ }
+ /* next instruction */
+ env->pc = env->npc;
+ env->npc = env->npc + 4;
+ break;
+#endif
#ifndef TARGET_SPARC64
case TT_WIN_OVF: /* window overflow */
save_window(env);
@@ -1791,8 +1823,273 @@ void cpu_loop(CPUPPCState *env)
#ifdef TARGET_MIPS
-# ifdef TARGET_ABI_MIPSO32
-# define MIPS_SYS(name, args) args,
+# if defined(TARGET_ABI_IRIX)
+/* emulating the PRDA is expensive, since for every memory access the address
+ * has to be examined. Do this only if the user requires it.
+ */
+int irix_emulate_prda;
+
+/*
+ * The N32 ABI takes 64 bit args and return values in a 64 bit register, while
+ * the O32 ABI splits these in two 32 bit registers.
+ * Map 64 bit args to 32 bits here to avoid dealing with it in the syscall code.
+ * Also, a 64 bit return code in 2 32 bit registers must be recombined for N32.
+ *
+ * N32 uses the 64 bit syscall version if one is available (e.g. getdents64)
+ * Map 32 bit system calls to the 64 bit version here as well.
+ *
+ * Structure/union argument passing is left aligned. In N32, an object of 32 bit
+ * is in that case shifted to the upper half of the 64 bit register.
+ * Thus, in the special case of semsys(SEMCTL...), the 5th argument must be
+ * dealt with like a 64 bit argument in N32 for the correct value to be passed.
+ */
+# define SYSCALL_ARGS(n,a64,r64,s) ((n)|(a64)<<4|((r64)<<8)|((s)<<16))
+# define SYSCALL_NARGS(v) ((v)&0xf) /* #registers, incl. padding */
+# define SYSCALL_ARG64(v) (((v)>>4)&0xf) /* position of 64bit arg */
+# define SYSCALL_RET64(v) (((v)>>8)&0x1) /* returns a 64bit value */
+# define SYSCALL_MAP(v) ((v)>>16) /* N32 32bit syscall to 64bit */
+# define _ 0 /* for a better overview */
+# define X 8 /* place holder for "don't know" for proprietary syscalls */
+static const uint32_t mips_syscall_args[] = { /* see IRIX:/usr/include/sys.s */
+ SYSCALL_ARGS(8, _, _, _), /* 0: syscall */
+ SYSCALL_ARGS(1, _, _, _), /* 1: exit */
+ SYSCALL_ARGS(0, _, _, _), /* 2: fork */
+ SYSCALL_ARGS(3, _, _, _), /* 3: read */
+ SYSCALL_ARGS(3, _, _, _), /* 4: write */
+ SYSCALL_ARGS(3, _, _, _), /* 5: open */
+ SYSCALL_ARGS(1, _, _, _), /* 6: close */
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(2, _, _, _), /* 8: creat */
+ SYSCALL_ARGS(2, _, _, _), /* 9: link */
+ SYSCALL_ARGS(1, _, _, _), /* 10: unlink */
+ SYSCALL_ARGS(2, _, _, _), /* 11: execv */
+ SYSCALL_ARGS(1, _, _, _), /* 12: chdir */
+ SYSCALL_ARGS(0, _, _, _), /* 13: time */
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(2, _, _, _), /* 15: chmod */
+ SYSCALL_ARGS(3, _, _, _), /* 16: chown */
+ SYSCALL_ARGS(1, _, _, _), /* 17: brk */
+ SYSCALL_ARGS(2, _, _, _), /* 18: stat */
+ SYSCALL_ARGS(3, _, _, TARGET_NR_lseek64), /* 19: lseek */
+ SYSCALL_ARGS(0, _, _, _), /* 20: getpid */
+ SYSCALL_ARGS(6, _, _, _), /* 21: mount */
+ SYSCALL_ARGS(1, _, _, _), /* 22: umount */
+ SYSCALL_ARGS(1, _, _, _), /* 23: setuid */
+ SYSCALL_ARGS(0, _, _, _), /* 24: getuid */
+ SYSCALL_ARGS(1, _, _, _), /* 25: stime */
+ SYSCALL_ARGS(4, _, _, _), /* 26: ptrace */
+ SYSCALL_ARGS(1, _, _, _), /* 27: alarm */
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(0, _, _, _), /* 29: pause */
+ SYSCALL_ARGS(2, _, _, _), /* 30: utime */
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(2, _, _, _), /* 33: access */
+ SYSCALL_ARGS(1, _, _, _), /* 34: nice */
+ SYSCALL_ARGS(4, _, _, _), /* 35: statfs */
+ SYSCALL_ARGS(0, _, _, _), /* 36: sync */
+ SYSCALL_ARGS(2, _, _, _), /* 37: kill */
+ SYSCALL_ARGS(4, _, _, _), /* 38: fstatfs */
+ SYSCALL_ARGS(1, _, _, _), /* 39: pgrpsys */
+ SYSCALL_ARGS(X, _, _, _), /* 40: syssgi */
+ SYSCALL_ARGS(1, _, _, _), /* 41: dup */
+ SYSCALL_ARGS(0, _, _, _), /* 42: pipe */
+ SYSCALL_ARGS(1, _, _, _), /* 43: times */
+ SYSCALL_ARGS(4, _, _, _), /* 44: profil */
+ SYSCALL_ARGS(1, _, _, _), /* 45: plock */
+ SYSCALL_ARGS(1, _, _, _), /* 46: setgid */
+ SYSCALL_ARGS(0, _, _, _), /* 47: getgid */
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(6, _, _, _), /* 49: msgsys */
+ SYSCALL_ARGS(4, _, _, _), /* 50: sysmips */
+ SYSCALL_ARGS(1, _, _, _), /* 51: acct */
+ SYSCALL_ARGS(5, _, _, _), /* 52: shmsys */
+ SYSCALL_ARGS(5, 5, _, _), /* 53: semsys */
+ SYSCALL_ARGS(3, _, _, _), /* 54: ioctl */
+ SYSCALL_ARGS(3, _, _, _), /* 55: uadmin */
+ SYSCALL_ARGS(X, _, _, _), /* 56: sysmp */
+ SYSCALL_ARGS(3, _, _, _), /* 57: utssys */
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(3, _, _, _), /* 59: execve */
+ SYSCALL_ARGS(1, _, _, _), /* 60: umask */
+ SYSCALL_ARGS(1, _, _, _), /* 61: chroot */
+ SYSCALL_ARGS(3, _, _, _), /* 62: fcntl */
+ SYSCALL_ARGS(2, _, _, _), /* 63: ulimit */
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(2, _, _, _), /* 75: getrlimit64 */
+ SYSCALL_ARGS(2, _, _, _), /* 76: setrlimit64 */
+ SYSCALL_ARGS(2, _, _, _), /* 77: nanosleep */
+ SYSCALL_ARGS(5, 2, 1, _), /* 78: lseek64 */
+ SYSCALL_ARGS(1, _, _, _), /* 79: rmdir */
+ SYSCALL_ARGS(2, _, _, _), /* 80: mkdir */
+ SYSCALL_ARGS(3, _, _, TARGET_NR_getdents64),/* 81: getdents */
+ SYSCALL_ARGS(1, _, _, _), /* 82: sginap */
+ SYSCALL_ARGS(3, _, _, _), /* 83: sgikopt */
+ SYSCALL_ARGS(3, _, _, _), /* 84: sysfs */
+ SYSCALL_ARGS(4, _, _, _), /* 85: getmsg */
+ SYSCALL_ARGS(4, _, _, _), /* 86: putmsg */
+ SYSCALL_ARGS(3, _, _, _), /* 87: poll */
+ SYSCALL_ARGS(3, _, _, _), /* 88: sigreturn */
+ SYSCALL_ARGS(3, _, _, _), /* 89: accept */
+ SYSCALL_ARGS(3, _, _, _), /* 90: bind */
+ SYSCALL_ARGS(3, _, _, _), /* 91: connect */
+ SYSCALL_ARGS(0, _, _, _), /* 92: gethostid */
+ SYSCALL_ARGS(3, _, _, _), /* 93: getpeername */
+ SYSCALL_ARGS(3, _, _, _), /* 94: getsockname */
+ SYSCALL_ARGS(5, _, _, _), /* 95: getsockopt */
+ SYSCALL_ARGS(2, _, _, _), /* 96: listen */
+ SYSCALL_ARGS(4, _, _, _), /* 97: recv */
+ SYSCALL_ARGS(6, _, _, _), /* 98: recvfrom */
+ SYSCALL_ARGS(3, _, _, _), /* 99: recvmsg */
+ SYSCALL_ARGS(5, _, _, _), /* 100: select */
+ SYSCALL_ARGS(4, _, _, _), /* 101: send */
+ SYSCALL_ARGS(3, _, _, _), /* 102: sendmsg */
+ SYSCALL_ARGS(6, _, _, _), /* 103: sendto */
+ SYSCALL_ARGS(1, _, _, _), /* 104: sethostid */
+ SYSCALL_ARGS(5, _, _, _), /* 105: setsockopt */
+ SYSCALL_ARGS(2, _, _, _), /* 106: shutdown */
+ SYSCALL_ARGS(3, _, _, _), /* 107: socket */
+ SYSCALL_ARGS(2, _, _, _), /* 108: gethostname */
+ SYSCALL_ARGS(2, _, _, _), /* 109: sethostname */
+ SYSCALL_ARGS(2, _, _, _), /* 110: getdomainname */
+ SYSCALL_ARGS(2, _, _, _), /* 111: setdomainname */
+ SYSCALL_ARGS(2, _, _, TARGET_NR_truncate64),/* 112: truncate */
+ SYSCALL_ARGS(2, _, _, TARGET_NR_ftruncate64),/* 113: ftruncate */
+ SYSCALL_ARGS(2, _, _, _), /* 114: rename */
+ SYSCALL_ARGS(2, _, _, _), /* 115: symlink */
+ SYSCALL_ARGS(3, _, _, _), /* 116: readlink */
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(X, _, _, _), /* 119: nfssvc */
+ SYSCALL_ARGS(X, _, _, _), /* 120: getfh */
+ SYSCALL_ARGS(X, _, _, _), /* 121: async_daemon */
+ SYSCALL_ARGS(X, _, _, _), /* 122: exportfs */
+ SYSCALL_ARGS(2, _, _, _), /* 123: setregid */
+ SYSCALL_ARGS(2, _, _, _), /* 123: setreuid */
+ SYSCALL_ARGS(2, _, _, _), /* 125: getitimer */
+ SYSCALL_ARGS(3, _, _, _), /* 126: setitimer */
+ SYSCALL_ARGS(2, _, _, _), /* 127: adjtime */
+ SYSCALL_ARGS(1, _, _, _), /* 128: gettimeofday */
+ SYSCALL_ARGS(3, _, _, _), /* 129: sproc */
+ SYSCALL_ARGS(3, _, _, _), /* 130: prctl */
+ SYSCALL_ARGS(3, _, _, _), /* 131: procblk */
+ SYSCALL_ARGS(5, _, _, _), /* 132: sprocsp */
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(6, _, _, TARGET_NR_mmap64), /* 134: mmap */
+ SYSCALL_ARGS(2, _, _, _), /* 135: munmap */
+ SYSCALL_ARGS(3, _, _, _), /* 136: mprotect */
+ SYSCALL_ARGS(3, _, _, _), /* 137: msync */
+ SYSCALL_ARGS(3, _, _, _), /* 138: madvise */
+ SYSCALL_ARGS(3, _, _, _), /* 139: pagelock */
+ SYSCALL_ARGS(0, _, _, _), /* 140: getpagesize */
+ SYSCALL_ARGS(4, _, _, _), /* 141: quotactl */
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(1, _, _, _), /* 143: getpgid */
+ SYSCALL_ARGS(2, _, _, _), /* 144: setpgid */
+ SYSCALL_ARGS(0, _, _, _), /* 145: vhangup */
+ SYSCALL_ARGS(1, _, _, _), /* 146: fsync */
+ SYSCALL_ARGS(1, _, _, _), /* 147: fchdir */
+ SYSCALL_ARGS(2, _, _, TARGET_NR_getrlimit64),/* 148: getrlimit */
+ SYSCALL_ARGS(2, _, _, TARGET_NR_setrlimit64),/* 149: setrlimit */
+ SYSCALL_ARGS(3, _, _, _), /* 150: cacheflush */
+ SYSCALL_ARGS(3, _, _, _), /* 151: cachectl */
+ SYSCALL_ARGS(3, _, _, _), /* 152: fchown */
+ SYSCALL_ARGS(2, _, _, _), /* 153: fchmod */
+ SYSCALL_ARGS(_, _, _, _),
+ SYSCALL_ARGS(4, _, _, _), /* 155: socketpair */
+ SYSCALL_ARGS(3, _, _, _), /* 156: sysinfo */
+ SYSCALL_ARGS(1, _, _, _), /* 157: uname */
+ SYSCALL_ARGS(3, _, _, _), /* 158: xstat */
+ SYSCALL_ARGS(3, _, _, _), /* 159: lxstat */
+ SYSCALL_ARGS(3, _, _, _), /* 160: fxstat */
+ SYSCALL_ARGS(4, _, _, _), /* 161: xmknod */
+ SYSCALL_ARGS(4, _, _, _), /* 162: sigaction */
+ SYSCALL_ARGS(1, _, _, _), /* 163: sigpending */
+ SYSCALL_ARGS(3, _, _, _), /* 164: sigprocmask */
+ SYSCALL_ARGS(1, _, _, _), /* 165: sigsuspend */
+ SYSCALL_ARGS(3, _, _, _), /* 166: sigpoll */
+ SYSCALL_ARGS(2, _, _, _), /* 167: swapctl */
+ SYSCALL_ARGS(1, _, _, _), /* 168: getcontext */
+ SYSCALL_ARGS(1, _, _, _), /* 169: setcontext */
+ SYSCALL_ARGS(5, _, _, _), /* 170: waitsys */
+ SYSCALL_ARGS(2, _, _, _), /* 171: sigstack */
+ SYSCALL_ARGS(2, _, _, _), /* 172: sigaltstack */
+ SYSCALL_ARGS(2, _, _, _), /* 173: sigsendset */
+ SYSCALL_ARGS(2, _, _, TARGET_NR_statvfs64), /* 174: statvfs */
+ SYSCALL_ARGS(2, _, _, TARGET_NR_fstatvfs64),/* 175: fstatvfs */
+ SYSCALL_ARGS(5, _, _, _), /* 176: getpmsg */
+ SYSCALL_ARGS(5, _, _, _), /* 177: putpmsg */
+ SYSCALL_ARGS(3, _, _, _), /* 178: lchown */
+ SYSCALL_ARGS(0, _, _, _), /* 179: priocntl */
+ SYSCALL_ARGS(X, _, _, _), /* 180: ksigqueue */
+ SYSCALL_ARGS(3, _, _, _), /* 181: readv */
+ SYSCALL_ARGS(3, _, _, _), /* 182: writev */
+ SYSCALL_ARGS(4, 2, _, _), /* 183: truncate64 */
+ SYSCALL_ARGS(4, 2, _, _), /* 184: ftruncate64 */
+ SYSCALL_ARGS(8, 6, _, _), /* 185: mmap64 */
+ SYSCALL_ARGS(X, _, _, _), /* 186: dmi */
+ SYSCALL_ARGS(6, 4, _, _), /* 187: pread64 */
+ SYSCALL_ARGS(6, 4, _, _), /* 188: pwrite64 */
+ SYSCALL_ARGS(1, _, _, _), /* 189: fdatasync */
+ SYSCALL_ARGS(X, _, _, _), /* 190: sgifastpath */
+ SYSCALL_ARGS(5, _, _, _), /* 191: attr_get */
+ SYSCALL_ARGS(5, _, _, _), /* 192: attr_getf */
+ SYSCALL_ARGS(5, _, _, _), /* 193: attr_set */
+ SYSCALL_ARGS(5, _, _, _), /* 194: attr_setf */
+ SYSCALL_ARGS(3, _, _, _), /* 195: attr_remove */
+ SYSCALL_ARGS(3, _, _, _), /* 196: attr_removef */
+ SYSCALL_ARGS(5, _, _, _), /* 197: attr_list */
+ SYSCALL_ARGS(5, _, _, _), /* 198: attr_listf */
+ SYSCALL_ARGS(4, _, _, _), /* 199: attr_multi */
+ SYSCALL_ARGS(4, _, _, _), /* 200: attr_multif */
+ SYSCALL_ARGS(2, _, _, _), /* 201: statvfs64 */
+ SYSCALL_ARGS(2, _, _, _), /* 202: fstatvfs64 */
+ SYSCALL_ARGS(2, _, _, _), /* 203: getmountid */
+ SYSCALL_ARGS(5, _, _, _), /* 204: nsproc */
+ SYSCALL_ARGS(3, _, _, _), /* 205: getdents64 */
+ SYSCALL_ARGS(X, _, _, _), /* 206: afs_syscall */
+ SYSCALL_ARGS(4, _, _, TARGET_NR_ngetdents64),/* 207: ngetdents */
+ SYSCALL_ARGS(4, _, _, _), /* 208: ngetdents64 */
+ SYSCALL_ARGS(X, _, _, _), /* 209: sgi_sesmgr */
+ SYSCALL_ARGS(X, _, _, _), /* 210: pidsprocsp */
+ SYSCALL_ARGS(X, _, _, _), /* 211: rexec */
+ SYSCALL_ARGS(3, _, _, _), /* 212: timer_create */
+ SYSCALL_ARGS(1, _, _, _), /* 213: timer_delete */
+ SYSCALL_ARGS(4, _, _, _), /* 214: timer_settime */
+ SYSCALL_ARGS(2, _, _, _), /* 215: timer_gettime */
+ SYSCALL_ARGS(1, _, _, _), /* 216: timer_getoverrun */
+ SYSCALL_ARGS(2, _, _, _), /* 217: sched_rr_get_interval */
+ SYSCALL_ARGS(0, _, _, _), /* 218: sched_yield */
+ SYSCALL_ARGS(1, _, _, _), /* 219: sched_getscheduler */
+ SYSCALL_ARGS(3, _, _, _), /* 220: sched_setscheduler */
+ SYSCALL_ARGS(2, _, _, _), /* 221: sched_getparam */
+ SYSCALL_ARGS(2, _, _, _), /* 222: sched_setparam */
+ SYSCALL_ARGS(2, _, _, _), /* 223: usync_cntl */
+ SYSCALL_ARGS(5, _, _, _), /* 224: psema_cntl */
+ SYSCALL_ARGS(X, _, _, _), /* 225: restartreturn */
+ SYSCALL_ARGS(5, _, _, _), /* 226: sysget */
+ SYSCALL_ARGS(3, _, _, _), /* 227: xpg4_recvmsg */
+ SYSCALL_ARGS(X, _, _, _), /* 228: umfscall */
+ SYSCALL_ARGS(X, _, _, _), /* 229: nsproctid */
+ SYSCALL_ARGS(X, _, _, _), /* 230: rexec_complete */
+ SYSCALL_ARGS(2, _, _, _), /* 231: xpg4_sigaltstack */
+ SYSCALL_ARGS(5, _, _, _), /* 232: xpg4_select */
+ SYSCALL_ARGS(2, _, _, _), /* 233: xpg4_setregid */
+ SYSCALL_ARGS(2, _, _, _), /* 234: linkfollow */
+};
+# else
+# define MIPS_SYS(name, args) args,
+# define SYSCALL_NARGS(v) (v)
static const uint8_t mips_syscall_args[] = {
MIPS_SYS(sys_syscall , 8) /* 4000 */
MIPS_SYS(sys_exit , 1)
@@ -2160,6 +2457,7 @@ static const uint8_t mips_syscall_args[] = {
};
# undef MIPS_SYS
# endif /* O32 */
+#define NUM_SYSCALLS (sizeof(mips_syscall_args) / sizeof(*mips_syscall_args))
static int do_store_exclusive(CPUMIPSState *env)
{
@@ -2241,14 +2539,45 @@ static int do_break(CPUMIPSState *env, target_siginfo_t *info,
return ret;
}
+#if defined(TARGET_ABI_IRIX) && defined(TARGET_ABI_MIPSN32)
+/* split the arg64'th arg, which is a 64 bit arg in a 64 bit register, into an
+ * even/odd 32 bit register pair, moving the other args up as necessary. This is
+ * needed because the syscall ABI for TARGET_ABI32 only knows about 32 bit args.
+ */
+static void get_args_n32(target_ulong *regs, int arg64, int num, abi_ulong args[8])
+{
+ int i, j;
+
+ /* what a nuisance, and all this just for a few of the syscalls :-( */
+ if (arg64) {
+ for (i = 0; i < arg64-1; i++)
+ args[i] = regs[i];
+ args[i] = 0; i += (i & 1); /* align to even register */
+ args[i++] = regs[arg64-1] >> 32;
+ args[i++] = regs[arg64-1];
+ /* at most registers are needed for the expanded args */
+ for (j = arg64; i < num; j++)
+ args[i++] = regs[j];
+ } else {
+ for (i = 0; i < num; i++)
+ args[i] = regs[i];
+ }
+}
+#endif
+
void cpu_loop(CPUMIPSState *env)
{
CPUState *cs = CPU(mips_env_get_cpu(env));
target_siginfo_t info;
int trapnr;
abi_long ret;
-# ifdef TARGET_ABI_MIPSO32
unsigned int syscall_num;
+ int offset = 0;
+# ifdef TARGET_ABI_IRIX
+ TaskState *ts = cs->opaque;
+
+ __put_user(ts->ts_tid, (abi_int *)&ts->prda[0xe00]);
+ __put_user(ts->ts_tid, (abi_int *)&ts->prda[0xe40]);
# endif
for(;;) {
@@ -2260,17 +2589,23 @@ void cpu_loop(CPUMIPSState *env)
switch(trapnr) {
case EXCP_SYSCALL:
env->active_tc.PC += 4;
-# ifdef TARGET_ABI_MIPSO32
- syscall_num = env->active_tc.gpr[2] - 4000;
+ syscall_num = env->active_tc.gpr[2] - TARGET_NR_Linux;
+# ifdef TARGET_ABI_IRIX
+ /* handle indirect syscalls here, else N32 64 bit args are passed incorrectly */
+ offset = (syscall_num == TARGET_NR_syscall - TARGET_NR_Linux);
+ if (offset)
+ syscall_num = env->active_tc.gpr[4] - TARGET_NR_Linux;
+# endif
if (syscall_num >= sizeof(mips_syscall_args)) {
ret = -TARGET_ENOSYS;
} else {
+# ifdef TARGET_ABI_MIPSO32
int nb_args;
abi_ulong sp_reg;
- abi_ulong arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
+ abi_ulong arg4 = 0, arg5 = 0, arg6 = 0, arg7 = 0, arg8 = 0;
- nb_args = mips_syscall_args[syscall_num];
- sp_reg = env->active_tc.gpr[29];
+ nb_args = SYSCALL_NARGS(mips_syscall_args[syscall_num]);
+ sp_reg = env->active_tc.gpr[29] + 4*offset;
switch (nb_args) {
/* these arguments are taken from the stack */
case 8:
@@ -2289,24 +2624,41 @@ void cpu_loop(CPUMIPSState *env)
if ((ret = get_user_ual(arg5, sp_reg + 16)) != 0) {
goto done_syscall;
}
+ case 4:
+ if (offset && (ret = get_user_ual(arg4, sp_reg + 12)) != 0) {
+ goto done_syscall;
+ }
default:
break;
}
- ret = do_syscall(env, env->active_tc.gpr[2],
- env->active_tc.gpr[4],
- env->active_tc.gpr[5],
- env->active_tc.gpr[6],
- env->active_tc.gpr[7],
+ ret = do_syscall(env, syscall_num + TARGET_NR_Linux,
+ env->active_tc.gpr[4+offset],
+ env->active_tc.gpr[5+offset],
+ env->active_tc.gpr[6+offset],
+ offset ? arg4 : env->active_tc.gpr[7],
arg5, arg6, arg7, arg8);
- }
-done_syscall:
+done_syscall: ;
# else
- ret = do_syscall(env, env->active_tc.gpr[2],
- env->active_tc.gpr[4], env->active_tc.gpr[5],
- env->active_tc.gpr[6], env->active_tc.gpr[7],
- env->active_tc.gpr[8], env->active_tc.gpr[9],
- env->active_tc.gpr[10], env->active_tc.gpr[11]);
+# if defined TARGET_ABI_IRIX && defined TARGET_ABI_MIPSN32
+ /* split 64 bit args into 2 32 bit args for N32 */
+ int nb_args;
+ int arg64;
+ abi_ulong args[8];
+
+ /* map certain syscalls to their 64 bit version */
+ if (SYSCALL_MAP(mips_syscall_args[syscall_num]))
+ syscall_num = SYSCALL_MAP(mips_syscall_args[syscall_num]) - TARGET_NR_Linux;
+ nb_args = SYSCALL_NARGS(mips_syscall_args[syscall_num]);
+ arg64 = SYSCALL_ARG64(mips_syscall_args[syscall_num]);
+ get_args_n32(&env->active_tc.gpr[4+offset], arg64, nb_args, args);
+# else
+ target_ulong *args = &env->active_tc.gpr[4+offset];
+# endif
+ ret = do_syscall(env, syscall_num + TARGET_NR_Linux,
+ args[0], args[1], args[2], args[3],
+ args[4], args[5], args[6], args[7]);
# endif /* O32 */
+ }
if (ret == -TARGET_ERESTARTSYS) {
env->active_tc.PC -= 4;
break;
@@ -2316,13 +2668,29 @@ done_syscall:
Avoid clobbering register state. */
break;
}
+ /* on return: gpr7 = error flag, gpr2/3 = value(s) or error code */
+# if defined TARGET_ABI_IRIX
+# if defined TARGET_ABI_MIPSN32
+ /* restore a 64 bit retval for N32 */
+ if (SYSCALL_RET64(mips_syscall_args[syscall_num])) {
+ target_ulong tret = ((target_ulong)ret << 32) | env->active_tc.gpr[3];
+ env->active_tc.gpr[7] = (tret >= (target_ulong)-1700);
+ env->active_tc.gpr[2] = (env->active_tc.gpr[7] ? -tret : tret);
+ } else
+# endif
+ {
+ env->active_tc.gpr[7] = (ret >= (abi_ulong)-1700);
+ env->active_tc.gpr[2] = (env->active_tc.gpr[7] ? -ret : ret);
+ }
+# else
if ((abi_ulong)ret >= (abi_ulong)-1133) {
env->active_tc.gpr[7] = 1; /* error flag */
- ret = -ret;
+ env->active_tc.gpr[2] = -ret;
} else {
env->active_tc.gpr[7] = 0; /* error flag */
+ env->active_tc.gpr[2] = ret;
}
- env->active_tc.gpr[2] = ret;
+# endif
break;
case EXCP_TLBL:
case EXCP_TLBS:
@@ -2342,6 +2710,14 @@ done_syscall:
info.si_code = 0;
queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
break;
+#ifdef TARGET_ABI_IRIX
+ case EXCP_FPE:
+ info.si_signo = TARGET_SIGFPE;
+ info.si_errno = 0;
+ info.si_code = 0;
+ queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
+ break;
+#endif
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
break;
@@ -3944,9 +4320,7 @@ void qemu_cpu_kick(CPUState *cpu)
void task_settid(TaskState *ts)
{
- if (ts->ts_tid == 0) {
- ts->ts_tid = (pid_t)syscall(SYS_gettid);
- }
+ ts->ts_tid = (pid_t)syscall(SYS_gettid);
}
void stop_all_tasks(void)
@@ -3962,6 +4336,39 @@ void stop_all_tasks(void)
void init_task_state(TaskState *ts)
{
ts->used = 1;
+
+#ifdef TARGET_ABI_IRIX
+ pthread_mutex_init(&ts->procblk_mutex, NULL);
+ pthread_cond_init(&ts->procblk_cond, NULL);
+#endif
+}
+
+TaskState *find_task_state(pid_t tid)
+{
+ CPUState *cpu;
+ TaskState *ts = NULL;
+
+ for (cpu = first_cpu; cpu; cpu = CPU_NEXT(cpu)) {
+ ts = cpu->opaque;
+ if (ts->ts_tid == tid)
+ break;
+ }
+
+ return ts;
+}
+
+CPUState *find_cpu_state(pid_t tid)
+{
+ CPUState *cpu;
+ TaskState *ts;
+
+ for (cpu = first_cpu; cpu; cpu = CPU_NEXT(cpu)) {
+ ts = cpu->opaque;
+ if (ts->ts_tid == tid)
+ break;
+ }
+
+ return cpu;
}
CPUArchState *cpu_copy(CPUArchState *env)
@@ -4574,7 +4981,7 @@ int main(int argc, char **argv, char **envp)
target_set_brk(info->brk);
syscall_init();
- signal_init();
+ signal_init(env);
/* Now that we've loaded the binary, GUEST_BASE is fixed. Delay
generating the prologue until now so that the prologue can take
@@ -4856,6 +5263,17 @@ int main(int argc, char **argv, char **envp)
}
restore_snan_bit_mode(env);
}
+# if defined TARGET_ABI_IRIX && !defined TARGET_ABI_MIPSO32
+ /* TODO: is this OK? */
+ if ((info->elf_flags & EF_MIPS_ARCH) == EF_MIPS_ARCH_4) {
+ /* enable MIPS IV COP1X instructions for N32 and N64 */
+ env->CP0_Status |= (1 << CP0St_CU3);
+ env->hflags |= MIPS_HFLAG_COP1X;
+ }
+ /* check if PRDA emulation is requested */
+ if (getenv("QEMU_IRIXPRDA"))
+ irix_emulate_prda = 1;
+# endif
}
#elif defined(TARGET_NIOS2)
{
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index f4b4ca72ad..029bf0f188 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -58,6 +58,9 @@ struct image_info {
abi_ulong pt_dynamic_addr;
struct image_info *other_info;
#endif
+#ifdef TARGET_ABI_IRIX
+ abi_ulong phdr_offset;
+#endif
};
#ifdef TARGET_I386
@@ -119,6 +122,22 @@ typedef struct TaskState {
/* Extra fields for semihosted binaries. */
abi_ulong heap_base;
abi_ulong heap_limit;
+#endif
+#if defined(TARGET_ABI_IRIX)
+ struct TaskState *parent_task;
+ abi_ulong ctx_link;
+ abi_ulong sigtramp;
+ unsigned char prda[TARGET_PAGE_SIZE];
+ int procblk_count;
+ pthread_mutex_t procblk_mutex;
+ pthread_cond_t procblk_cond;
+ int is_pthread;
+ int is_blocked;
+ int termchild_sig;
+ int exit_sig;
+#endif
+#if defined(TARGET_ABI_SOLARIS)
+ abi_ulong ctx_link;
#endif
abi_ulong stack_base;
int used; /* non zero if used */
@@ -152,6 +171,8 @@ typedef struct TaskState {
extern char *exec_path;
void init_task_state(TaskState *ts);
+TaskState *find_task_state(pid_t tid);
+CPUState *find_cpu_state(pid_t tid);
void task_settid(TaskState *);
void stop_all_tasks(void);
extern const char *qemu_uname_release;
@@ -189,6 +210,15 @@ int loader_exec(int fdexec, const char *filename, char **argv, char **envp,
uint32_t get_elf_eflags(int fd);
int load_elf_binary(struct linux_binprm *bprm, struct image_info *info);
int load_flt_binary(struct linux_binprm *bprm, struct image_info *info);
+#ifdef TARGET_ABI_IRIX
+#ifdef TARGET_ABI_MIPSN64
+struct elf64_phdr;
+abi_ulong sgi_map_elf_image(int image_fd, struct elf64_phdr *phdr, int phnum);
+#else
+struct elf32_phdr;
+abi_ulong sgi_map_elf_image(int image_fd, struct elf32_phdr *phdr, int phnum);
+#endif
+#endif
abi_long memcpy_to_target(abi_ulong dest, const void *src,
unsigned long len);
@@ -205,8 +235,8 @@ void cpu_loop(CPUArchState *env);
const char *target_strerror(int err);
int get_osversion(void);
void init_qemu_uname_release(void);
-void fork_start(void);
-void fork_end(int child);
+void fork_start(CPUArchState *env);
+void fork_end(CPUArchState *env, int child);
/* Creates the initial guest address space in the host memory space using
* the given host start address hint and size. The guest_start parameter
@@ -378,7 +408,7 @@ extern int do_strace;
/* signal.c */
void process_pending_signals(CPUArchState *cpu_env);
-void signal_init(void);
+void signal_init(CPUArchState *env);
int queue_signal(CPUArchState *env, int sig, int si_type,
target_siginfo_t *info);
void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
@@ -387,8 +417,8 @@ int target_to_host_signal(int sig);
int host_to_target_signal(int sig);
long do_sigreturn(CPUArchState *env);
long do_rt_sigreturn(CPUArchState *env);
-abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
-int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
+abi_long do_sigaltstack(CPUArchState *env, abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp);
+int do_sigprocmask(CPUArchState *env, int how, const sigset_t *set, sigset_t *oldset);
/**
* block_signals: block all signals while handling this guest syscall
*
@@ -407,7 +437,7 @@ int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
*
* Return value: non-zero if there was a pending signal, zero if not.
*/
-int block_signals(void); /* Returns non zero if signal pending */
+int block_signals(CPUArchState *env); /* Returns non zero if signal pending */
#ifdef TARGET_I386
/* vm86.c */
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 4d3f244612..827180e969 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -20,6 +20,7 @@
#include "qemu/bitops.h"
#include
#include
+#include
#include "qemu.h"
#include "qemu-common.h"
@@ -80,7 +81,7 @@ static uint8_t host_to_target_signal_table[_NSIG] = {
[__SIGRTMIN] = __SIGRTMAX,
[__SIGRTMAX] = __SIGRTMIN,
};
-static uint8_t target_to_host_signal_table[_NSIG];
+static uint8_t target_to_host_signal_table[TARGET_NSIG];
static inline int on_sig_stack(unsigned long sp)
{
@@ -103,7 +104,7 @@ int host_to_target_signal(int sig)
int target_to_host_signal(int sig)
{
- if (sig < 0 || sig >= _NSIG)
+ if (sig < 0 || sig >= TARGET_NSIG)
return sig;
return target_to_host_signal_table[sig];
}
@@ -117,14 +118,18 @@ static inline void target_sigaddset(target_sigset_t *set, int signum)
{
signum--;
abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
- set->sig[signum / TARGET_NSIG_BPW] |= mask;
+ if (signum < TARGET_NSIG_BPW * TARGET_NSIG_WORDS)
+ set->sig[signum / TARGET_NSIG_BPW] |= mask;
}
static inline int target_sigismember(const target_sigset_t *set, int signum)
{
signum--;
abi_ulong mask = (abi_ulong)1 << (signum % TARGET_NSIG_BPW);
- return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
+ if (signum < TARGET_NSIG_BPW * TARGET_NSIG_WORDS)
+ return ((set->sig[signum / TARGET_NSIG_BPW] & mask) != 0);
+ else
+ return 0;
}
static void host_to_target_sigset_internal(target_sigset_t *d,
@@ -132,7 +137,7 @@ static void host_to_target_sigset_internal(target_sigset_t *d,
{
int i;
target_sigemptyset(d);
- for (i = 1; i <= TARGET_NSIG; i++) {
+ for (i = 1; i <= _NSIG; i++) {
if (sigismember(s, i)) {
target_sigaddset(d, host_to_target_signal(i));
}
@@ -146,7 +151,7 @@ void host_to_target_sigset(target_sigset_t *d, const sigset_t *s)
host_to_target_sigset_internal(&d1, s);
for(i = 0;i < TARGET_NSIG_WORDS; i++)
- d->sig[i] = tswapal(d1.sig[i]);
+ __put_user(d1.sig[i], &d->sig[i]);
}
static void target_to_host_sigset_internal(sigset_t *d,
@@ -154,7 +159,7 @@ static void target_to_host_sigset_internal(sigset_t *d,
{
int i;
sigemptyset(d);
- for (i = 1; i <= TARGET_NSIG; i++) {
+ for (i = 1; i <= TARGET_NSIG_BPW * TARGET_NSIG_WORDS; i++) {
if (target_sigismember(s, i)) {
sigaddset(d, target_to_host_signal(i));
}
@@ -167,7 +172,7 @@ void target_to_host_sigset(sigset_t *d, const target_sigset_t *s)
int i;
for(i = 0;i < TARGET_NSIG_WORDS; i++)
- s1.sig[i] = tswapal(s->sig[i]);
+ __get_user(s1.sig[i], &s->sig[i]);
target_to_host_sigset_internal(d, &s1);
}
@@ -176,7 +181,11 @@ void host_to_target_old_sigset(abi_ulong *old_sigset,
{
target_sigset_t d;
host_to_target_sigset(&d, sigset);
+#if defined TARGET_ABI_IRIX || defined TARGET_ABI_SOLARIS
+ *(abi_uint *)old_sigset = d.sig[0];
+#else
*old_sigset = d.sig[0];
+#endif
}
void target_to_host_old_sigset(sigset_t *sigset,
@@ -185,15 +194,20 @@ void target_to_host_old_sigset(sigset_t *sigset,
target_sigset_t d;
int i;
+#if defined TARGET_ABI_IRIX || defined TARGET_ABI_SOLARIS
+ d.sig[0] = *(abi_uint *)old_sigset;
+#else
d.sig[0] = *old_sigset;
+#endif
for(i = 1;i < TARGET_NSIG_WORDS; i++)
d.sig[i] = 0;
target_to_host_sigset(sigset, &d);
}
-int block_signals(void)
+int block_signals(CPUArchState *env)
{
- TaskState *ts = (TaskState *)thread_cpu->opaque;
+ CPUState *cpu = ENV_GET_CPU(env);
+ TaskState *ts = (TaskState *)cpu->opaque;
sigset_t set;
/* It's OK to block everything including SIGSEGV, because we won't
@@ -213,9 +227,10 @@ int block_signals(void)
* 0 on success.
* If set is NULL, this is guaranteed not to fail.
*/
-int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
+int do_sigprocmask(CPUArchState *env, int how, const sigset_t *set, sigset_t *oldset)
{
- TaskState *ts = (TaskState *)thread_cpu->opaque;
+ CPUState *cpu = ENV_GET_CPU(env);
+ TaskState *ts = (TaskState *)cpu->opaque;
if (oldset) {
*oldset = ts->signal_mask;
@@ -224,7 +239,7 @@ int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
if (set) {
int i;
- if (block_signals()) {
+ if (block_signals(env)) {
return -TARGET_ERESTARTSYS;
}
@@ -254,13 +269,14 @@ int do_sigprocmask(int how, const sigset_t *set, sigset_t *oldset)
}
#if !defined(TARGET_OPENRISC) && !defined(TARGET_UNICORE32) && \
- !defined(TARGET_NIOS2)
+ !defined(TARGET_NIOS2) && !defined(TARGET_ABI_SOLARIS)
/* Just set the guest's signal mask to the specified value; the
* caller is assumed to have called block_signals() already.
*/
-static void set_sigmask(const sigset_t *set)
+static void set_sigmask(CPUArchState *env, const sigset_t *set)
{
- TaskState *ts = (TaskState *)thread_cpu->opaque;
+ CPUState *cpu = ENV_GET_CPU(env);
+ TaskState *ts = (TaskState *)cpu->opaque;
ts->signal_mask = *set;
}
@@ -317,7 +333,9 @@ static inline void host_to_target_siginfo_noswap(target_siginfo_t *tinfo,
switch (sig) {
case TARGET_SIGCHLD:
tinfo->_sifields._sigchld._pid = info->si_pid;
+#if !defined TARGET_ABI_IRIX && !defined TARGET_ABI_SOLARIS
tinfo->_sifields._sigchld._uid = info->si_uid;
+#endif
tinfo->_sifields._sigchld._status
= host_to_target_waitstatus(info->si_status);
tinfo->_sifields._sigchld._utime = info->si_utime;
@@ -383,8 +401,10 @@ static void tswap_siginfo(target_siginfo_t *tinfo,
case QEMU_SI_CHLD:
__put_user(info->_sifields._sigchld._pid,
&tinfo->_sifields._sigchld._pid);
+#if !defined TARGET_ABI_IRIX && !defined TARGET_ABI_SOLARIS
__put_user(info->_sifields._sigchld._uid,
&tinfo->_sifields._sigchld._uid);
+#endif
__put_user(info->_sifields._sigchld._status,
&tinfo->_sifields._sigchld._status);
__put_user(info->_sifields._sigchld._utime,
@@ -465,9 +485,10 @@ static int core_dump_signal(int sig)
}
}
-void signal_init(void)
+void signal_init(CPUArchState *env)
{
- TaskState *ts = (TaskState *)thread_cpu->opaque;
+ CPUState *cpu = ENV_GET_CPU(env);
+ TaskState *ts = (TaskState *)cpu->opaque;
struct sigaction act;
struct sigaction oact;
int i, j;
@@ -480,7 +501,8 @@ void signal_init(void)
}
for(i = 1; i < _NSIG; i++) {
j = host_to_target_signal_table[i];
- target_to_host_signal_table[j] = i;
+ if (j < TARGET_NSIG)
+ target_to_host_signal_table[j] = i;
}
/* Set the signal mask from the host mask. */
@@ -517,10 +539,8 @@ void signal_init(void)
* also forces the signal to "not blocked, not ignored", but for QEMU
* that work is done in process_pending_signals().
*/
-static void force_sig(int sig)
+static void force_sig(CPUArchState *env, int sig)
{
- CPUState *cpu = thread_cpu;
- CPUArchState *env = cpu->env_ptr;
target_siginfo_t info;
info.si_signo = sig;
@@ -536,7 +556,7 @@ static void force_sig(int sig)
* at the point of failure.
*/
#if !defined(TARGET_RISCV)
-static void force_sigsegv(int oldsig)
+static void force_sigsegv(CPUArchState *env, int oldsig)
{
if (oldsig == SIGSEGV) {
/* Make sure we don't try to deliver the signal again; this will
@@ -544,17 +564,16 @@ static void force_sigsegv(int oldsig)
*/
sigact_table[oldsig - 1]._sa_handler = TARGET_SIG_DFL;
}
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
}
#endif
#endif
/* abort execution with signal */
-static void QEMU_NORETURN dump_core_and_abort(int target_sig)
+static void QEMU_NORETURN dump_core_and_abort(CPUArchState *env, int target_sig)
{
- CPUState *cpu = thread_cpu;
- CPUArchState *env = cpu->env_ptr;
+ CPUState *cpu = ENV_GET_CPU(env);
TaskState *ts = (TaskState *)cpu->opaque;
int host_sig, core_dumped = 0;
struct sigaction act;
@@ -633,8 +652,8 @@ static inline void rewind_if_in_safe_syscall(void *puc)
static void host_signal_handler(int host_signum, siginfo_t *info,
void *puc)
{
- CPUArchState *env = thread_cpu->env_ptr;
- CPUState *cpu = ENV_GET_CPU(env);
+ CPUState *cpu = thread_cpu;
+ CPUArchState *env = cpu->env_ptr;
TaskState *ts = cpu->opaque;
int sig;
@@ -683,12 +702,12 @@ static void host_signal_handler(int host_signum, siginfo_t *info,
sigdelset(&uc->uc_sigmask, SIGBUS);
/* interrupt the virtual CPU as soon as possible */
- cpu_exit(thread_cpu);
+ cpu_exit(cpu);
}
/* do_sigaltstack() returns target values and errnos. */
/* compare linux/kernel/signal.c:do_sigaltstack() */
-abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
+abi_long do_sigaltstack(CPUArchState *env, abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
{
int ret;
struct target_sigaltstack oss;
@@ -709,7 +728,8 @@ abi_long do_sigaltstack(abi_ulong uss_addr, abi_ulong uoss_addr, abi_ulong sp)
#if defined(TARGET_PPC64)
/* ELF V2 for PPC64 has a 4K minimum stack size for signal handlers */
- struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
+ CPUState *cpu = ENV_GET_CPU(env);
+ struct image_info *image = ((TaskState *)cpu->opaque)->info;
if (get_ppc64_abi(image) > 1) {
minstacksize = 4096;
}
@@ -760,7 +780,7 @@ out:
}
/* do_sigaction() return target values and host errnos */
-int do_sigaction(int sig, const struct target_sigaction *act,
+int do_sigaction(CPUArchState *env, int sig, const struct target_sigaction *act,
struct target_sigaction *oact)
{
struct target_sigaction *k;
@@ -772,7 +792,7 @@ int do_sigaction(int sig, const struct target_sigaction *act,
return -TARGET_EINVAL;
}
- if (block_signals()) {
+ if (block_signals(env)) {
return -TARGET_ERESTARTSYS;
}
@@ -1168,7 +1188,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
return;
give_sigsegv:
- force_sigsegv(sig);
+ force_sigsegv(env, sig);
}
#endif
@@ -1264,7 +1284,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
return;
give_sigsegv:
- force_sigsegv(sig);
+ force_sigsegv(env, sig);
}
static int
@@ -1356,7 +1376,7 @@ long do_sigreturn(CPUX86State *env)
}
target_to_host_sigset_internal(&set, &target_set);
- set_sigmask(&set);
+ set_sigmask(env, &set);
/* restore registers */
if (restore_sigcontext(env, &frame->sc))
@@ -1366,7 +1386,7 @@ long do_sigreturn(CPUX86State *env)
badframe:
unlock_user_struct(frame, frame_addr, 0);
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
#endif
@@ -1382,13 +1402,13 @@ long do_rt_sigreturn(CPUX86State *env)
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
goto badframe;
target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
- set_sigmask(&set);
+ set_sigmask(env, &set);
if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
goto badframe;
}
- if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
+ if (do_sigaltstack(env, frame_addr + offsetof(struct rt_sigframe, uc.tuc_stack), 0,
get_sp_from_cpustate(env)) == -EFAULT) {
goto badframe;
}
@@ -1398,7 +1418,7 @@ long do_rt_sigreturn(CPUX86State *env)
badframe:
unlock_user_struct(frame, frame_addr, 0);
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -1523,7 +1543,7 @@ static int target_restore_sigframe(CPUARMState *env,
uint64_t pstate;
target_to_host_sigset(&set, &sf->uc.tuc_sigmask);
- set_sigmask(&set);
+ set_sigmask(env, &set);
for (i = 0; i < 31; i++) {
__get_user(env->xregs[i], &sf->uc.tuc_mcontext.regs[i]);
@@ -1629,7 +1649,7 @@ static void target_setup_frame(int usig, struct target_sigaction *ka,
give_sigsegv:
unlock_user_struct(frame, frame_addr, 1);
- force_sigsegv(usig);
+ force_sigsegv(env, usig);
}
static void setup_rt_frame(int sig, struct target_sigaction *ka,
@@ -1663,7 +1683,7 @@ long do_rt_sigreturn(CPUARMState *env)
goto badframe;
}
- if (do_sigaltstack(frame_addr +
+ if (do_sigaltstack(env, frame_addr +
offsetof(struct target_rt_sigframe, uc.tuc_stack),
0, get_sp_from_cpustate(env)) == -EFAULT) {
goto badframe;
@@ -1674,7 +1694,7 @@ long do_rt_sigreturn(CPUARMState *env)
badframe:
unlock_user_struct(frame, frame_addr, 0);
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -1996,7 +2016,7 @@ static void setup_frame_v1(int usig, struct target_sigaction *ka,
unlock_user_struct(frame, frame_addr, 1);
return;
sigsegv:
- force_sigsegv(usig);
+ force_sigsegv(regs, usig);
}
static void setup_frame_v2(int usig, struct target_sigaction *ka,
@@ -2018,7 +2038,7 @@ static void setup_frame_v2(int usig, struct target_sigaction *ka,
unlock_user_struct(frame, frame_addr, 1);
return;
sigsegv:
- force_sigsegv(usig);
+ force_sigsegv(regs, usig);
}
static void setup_frame(int usig, struct target_sigaction *ka,
@@ -2076,7 +2096,7 @@ static void setup_rt_frame_v1(int usig, struct target_sigaction *ka,
unlock_user_struct(frame, frame_addr, 1);
return;
sigsegv:
- force_sigsegv(usig);
+ force_sigsegv(env, usig);
}
static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
@@ -2107,7 +2127,7 @@ static void setup_rt_frame_v2(int usig, struct target_sigaction *ka,
unlock_user_struct(frame, frame_addr, 1);
return;
sigsegv:
- force_sigsegv(usig);
+ force_sigsegv(env, usig);
}
static void setup_rt_frame(int usig, struct target_sigaction *ka,
@@ -2182,7 +2202,7 @@ static long do_sigreturn_v1(CPUARMState *env)
}
target_to_host_sigset_internal(&host_set, &set);
- set_sigmask(&host_set);
+ set_sigmask(env, &host_set);
if (restore_sigcontext(env, &frame->sc)) {
goto badframe;
@@ -2197,7 +2217,7 @@ static long do_sigreturn_v1(CPUARMState *env)
return -TARGET_QEMU_ESIGRETURN;
badframe:
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -2264,7 +2284,7 @@ static int do_sigframe_return_v2(CPUARMState *env,
abi_ulong *regspace;
target_to_host_sigset(&host_set, &uc->tuc_sigmask);
- set_sigmask(&host_set);
+ set_sigmask(env, &host_set);
if (restore_sigcontext(env, &uc->tuc_mcontext))
return 1;
@@ -2284,7 +2304,7 @@ static int do_sigframe_return_v2(CPUARMState *env,
}
}
- if (do_sigaltstack(context_addr
+ if (do_sigaltstack(env, context_addr
+ offsetof(struct target_ucontext_v2, tuc_stack),
0, get_sp_from_cpustate(env)) == -EFAULT) {
return 1;
@@ -2331,7 +2351,7 @@ static long do_sigreturn_v2(CPUARMState *env)
badframe:
unlock_user_struct(frame, frame_addr, 0);
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -2366,13 +2386,13 @@ static long do_rt_sigreturn_v1(CPUARMState *env)
}
target_to_host_sigset(&host_set, &frame->uc.tuc_sigmask);
- set_sigmask(&host_set);
+ set_sigmask(env, &host_set);
if (restore_sigcontext(env, &frame->uc.tuc_mcontext)) {
goto badframe;
}
- if (do_sigaltstack(frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
+ if (do_sigaltstack(env, frame_addr + offsetof(struct rt_sigframe_v1, uc.tuc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT)
goto badframe;
#if 0
@@ -2385,7 +2405,7 @@ static long do_rt_sigreturn_v1(CPUARMState *env)
badframe:
unlock_user_struct(frame, frame_addr, 0);
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -2421,7 +2441,7 @@ static long do_rt_sigreturn_v2(CPUARMState *env)
badframe:
unlock_user_struct(frame, frame_addr, 0);
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -2434,6 +2454,208 @@ long do_rt_sigreturn(CPUARMState *env)
}
}
+#elif defined(TARGET_ABI_SOLARIS)
+
+/* for an explanation of the stack frame layout see http://icps.u-strasbg.fr/
+ * people/loechner/public_html/enseignement/SPARC/sparcstack.html
+ */
+
+/* NOTE: Solaris uses setcontext instead of sigreturn */
+/* TODO: 64 bit version of this */
+
+/* the signal handling is modelled after the Illuminos source (Solaris 10?) */
+struct target_signal_frame {
+ int fr_locals[8]; /* saved %l0-7 */
+ int fr_ins[8]; /* saved %i0-7 */
+ uint32_t fr_stret; /* struct return addr */
+ int fr_args[7]; /* arg dump [0-5], more args if any */
+ struct target_ucontext fr_uc;
+};
+
+#define UREG_I0 16
+#define UREG_O0 0
+#define UREG_O1 1
+#define UREG_O2 2
+#define UREG_L0 8
+#define UREG_FP UREG_I6
+#define UREG_SP UREG_O6
+
+#define NF_ALIGNEDSZ (((sizeof(struct target_signal_frame) + 7) & (~7)))
+
+static inline abi_ulong get_sigframe(struct target_sigaction *sa,
+ CPUSPARCState *env,
+ unsigned long framesize)
+{
+ abi_ulong sp;
+
+ sp = env->regwptr[UREG_SP];
+
+ /* This is the X/Open sanctioned signal stack switching. */
+ if (sa->sa_flags & TARGET_SA_ONSTACK) {
+ if (!on_sig_stack(sp)
+ && !((target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size) & 7))
+ sp = target_sigaltstack_used.ss_sp + target_sigaltstack_used.ss_size;
+ }
+ return sp - framesize;
+}
+
+int save_context(CPUSPARCState *env, struct target_mcontext *sc, int setret)
+{
+ struct target_mcontext32 *mc32 = &sc->_32;
+ abi_ulong *sp;
+ int i;
+
+ /* flush all but the current window to the stack (saves %l0-7/%i0-7) */
+ flush_windows(env);
+
+ /* the stack always points to 64 bytes for the current %l0-7/%i0-7 */
+ if (!(sp = lock_user(VERIFY_WRITE, env->regwptr[UREG_SP], 16*4, 0)))
+ return -1;
+ for (i = 0; i < 16; i++)
+ __put_user(env->regwptr[UREG_L0 + i], &sp[i]);
+ unlock_user(sp, env->regwptr[UREG_SP], 16*4);
+
+ /* all other registers go to the mcontext */
+ __put_user(env->psr, &mc32->gregs[0]);
+ __put_user(env->pc, &mc32->gregs[1]);
+ __put_user(env->npc, &mc32->gregs[2]);
+ __put_user(env->y, &mc32->gregs[3]);
+ for (i=1; i < 8; i++) {
+ __put_user(env->gregs[i], &mc32->gregs[4+i-1]);
+ }
+ for (i=0; i < 8; i++) {
+ __put_user(env->regwptr[UREG_O0 + i], &mc32->gregs[11+i]);
+ }
+
+ __put_user(env->fsr, &mc32->fpfsr);
+ for (i=0; i < 16; i++) {
+ __put_user(env->fpr[i].d, &mc32->dregs[i]);
+ }
+
+ /* setup "success" return code for return from getcontext if required */
+ if (setret) {
+ __put_user(env->psr & ~PSR_CARRY, &mc32->gregs[0]);
+ __put_user(0, &mc32->gregs[11]);
+ }
+
+ return 0;
+}
+
+int restore_context(CPUSPARCState *env, struct target_mcontext *sc)
+{
+ struct target_mcontext32 *mc32 = &sc->_32;
+ abi_ulong *sp;
+ int i;
+
+ /* clean out windows, if any */
+ flush_windows(env);
+
+ /* get current window registers from mcontext (psr,pc,%y,%o0-7,%g1-7) */
+ __get_user(env->psr, &mc32->gregs[0]);
+ __get_user(env->pc, &mc32->gregs[1]);
+ __get_user(env->npc, &mc32->gregs[2]);
+ __get_user(env->y, &mc32->gregs[3]);
+ for (i=1; i < 8; i++) {
+ __get_user(env->gregs[i], &mc32->gregs[4+i-1]);
+ }
+ for (i=0; i < 8; i++) {
+ __get_user(env->regwptr[UREG_O0 + i], &mc32->gregs[11+i]);
+ }
+
+ __get_user(env->fsr, &mc32->fpfsr);
+ for (i=0; i < 16; i++) {
+ __get_user(env->fpr[i].d, &mc32->dregs[i]);
+ }
+
+ /* get %l0-7/%i0-7 from the stack */
+ if (!(sp = lock_user(VERIFY_READ, env->regwptr[UREG_SP], 16*4, 1)))
+ return -1;
+ for (i = 0; i < 16; i++)
+ __get_user(env->regwptr[UREG_L0 + i], &sp[i]);
+ unlock_user(sp, env->regwptr[UREG_SP], 0);
+
+ return 0;
+}
+
+static void setup_rt_frame(int sig, struct target_sigaction *ka,
+ target_siginfo_t *info,
+ target_sigset_t *set, CPUSPARCState *env)
+{
+ TaskState *ts = ENV_GET_CPU(env)->opaque;
+ abi_ulong sf_addr, sinf_addr;
+ struct target_signal_frame *sf = NULL;
+ struct target_siginfo *si = NULL;
+ int sigframe_size, siginfo_size, i;
+
+ /* signal frame setup */
+ sigframe_size = NF_ALIGNEDSZ;
+ siginfo_size = (info ? sizeof(struct target_siginfo) : 0);
+ sf_addr = get_sigframe(ka, env, sigframe_size + siginfo_size);
+ sinf_addr = sf_addr + sigframe_size;
+
+ sf = lock_user(VERIFY_WRITE, sf_addr, sizeof(struct target_signal_frame), 0);
+ if (!sf)
+ goto sigsegv;
+
+ if (info) {
+ si = lock_user(VERIFY_WRITE, sinf_addr, sizeof(struct target_siginfo), 0);
+ if (!si)
+ goto sigsegv;
+ }
+
+ /* UC_MCONTEXT */
+ if (save_context(env, &sf->fr_uc.tuc_mcontext, 0))
+ goto sigsegv;
+ /* UC_SIGMASK */
+ for (i = 0; i < TARGET_NSIG_WORDS; i++)
+ __put_user(set->sig[i], &sf->fr_uc.tuc_sigmask.sig[i]);
+ /* UC_STACK */
+ __put_user(0, &sf->fr_uc.tuc_stack.ss_sp);
+ __put_user(0, &sf->fr_uc.tuc_stack.ss_size);
+ __put_user(0, &sf->fr_uc.tuc_stack.ss_flags);
+
+ __put_user(0x0f, &sf->fr_uc.tuc_flags);
+ __put_user(ts->ctx_link, (abi_ulong *)&sf->fr_uc.tuc_link);
+ ts->ctx_link = sf_addr + offsetof(struct target_signal_frame, fr_uc);
+
+ /* setup stack for backtracing */
+ for (i = 0; i < 8; i++)
+ __put_user(env->regwptr[UREG_L0+i], &sf->fr_locals[i]);
+ for (i = 0; i < 8; i++)
+ __put_user(env->regwptr[UREG_I0+i], &sf->fr_ins[i]);
+
+ /* store siginfo, if any */
+ if (info)
+ tswap_siginfo(si, info);
+
+ /* setup signal handler parameters */
+ env->regwptr[UREG_SP] = sf_addr;
+ env->regwptr[UREG_O0] = sig;
+ env->regwptr[UREG_O1] = sinf_addr;
+ env->regwptr[UREG_O2] = sf_addr + offsetof(struct target_signal_frame, fr_uc);
+
+ /* point pc to signal handler */
+ env->pc = ka->_sa_handler;
+ env->npc = (env->pc + 4);
+
+ unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
+ unlock_user(si, sinf_addr, sizeof(struct target_siginfo));
+ return;
+sigsegv:
+ //fprintf(stderr, "force_sig\n");
+ if (sf)
+ unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
+ if (si)
+ unlock_user(si, sinf_addr, sizeof(struct target_siginfo));
+ force_sigsegv(env, sig);
+}
+
+static void setup_frame(int sig, struct target_sigaction *ka,
+ target_sigset_t *set, CPUSPARCState *env)
+{
+ setup_rt_frame(sig, ka, NULL, set, env);
+}
+
#elif defined(TARGET_SPARC)
#define __SUNOS_MAXWIN 31
@@ -2519,16 +2741,16 @@ struct target_rt_signal_frame {
qemu_siginfo_fpu_t fpu_state;
};
-#define UREG_O0 16
-#define UREG_O6 22
-#define UREG_I0 0
-#define UREG_I1 1
-#define UREG_I2 2
-#define UREG_I3 3
-#define UREG_I4 4
-#define UREG_I5 5
-#define UREG_I6 6
-#define UREG_I7 7
+#define UREG_I0 16
+#define UREG_I6 22
+#define UREG_O0 0
+#define UREG_O1 1
+#define UREG_O2 2
+#define UREG_O3 3
+#define UREG_O4 4
+#define UREG_O5 5
+#define UREG_O6 6
+#define UREG_O7 7
#define UREG_L0 8
#define UREG_FP UREG_I6
#define UREG_SP UREG_O6
@@ -2539,7 +2761,7 @@ static inline abi_ulong get_sigframe(struct target_sigaction *sa,
{
abi_ulong sp;
- sp = env->regwptr[UREG_FP];
+ sp = env->regwptr[UREG_SP];
/* This is the X/Open sanctioned signal stack switching. */
if (sa->sa_flags & TARGET_SA_ONSTACK) {
@@ -2564,7 +2786,7 @@ setup___siginfo(__siginfo_t *si, CPUSPARCState *env, abi_ulong mask)
__put_user(env->gregs[i], &si->si_regs.u_regs[i]);
}
for (i=0; i < 8; i++) {
- __put_user(env->regwptr[UREG_I0 + i], &si->si_regs.u_regs[i+8]);
+ __put_user(env->regwptr[UREG_O0 + i], &si->si_regs.u_regs[i+8]);
}
__put_user(mask, &si->si_mask);
return err;
@@ -2635,11 +2857,11 @@ static void setup_frame(int sig, struct target_sigaction *ka,
goto sigsegv;
/* 3. signal handler back-trampoline and parameters */
- env->regwptr[UREG_FP] = sf_addr;
- env->regwptr[UREG_I0] = sig;
- env->regwptr[UREG_I1] = sf_addr +
+ env->regwptr[UREG_SP] = sf_addr;
+ env->regwptr[UREG_O0] = sig;
+ env->regwptr[UREG_O1] = sf_addr +
offsetof(struct target_signal_frame, info);
- env->regwptr[UREG_I2] = sf_addr +
+ env->regwptr[UREG_O2] = sf_addr +
offsetof(struct target_signal_frame, info);
/* 4. signal handler */
@@ -2647,11 +2869,11 @@ static void setup_frame(int sig, struct target_sigaction *ka,
env->npc = (env->pc + 4);
/* 5. return to kernel instructions */
if (ka->sa_restorer) {
- env->regwptr[UREG_I7] = ka->sa_restorer;
+ env->regwptr[UREG_O7] = ka->sa_restorer;
} else {
uint32_t val32;
- env->regwptr[UREG_I7] = sf_addr +
+ env->regwptr[UREG_O7] = sf_addr +
offsetof(struct target_signal_frame, insns) - 2 * 4;
/* mov __NR_sigreturn, %g1 */
@@ -2672,11 +2894,11 @@ static void setup_frame(int sig, struct target_sigaction *ka,
return;
#if 0
sigill_and_return:
- force_sig(TARGET_SIGILL);
+ force_sig(env, TARGET_SIGILL);
#endif
sigsegv:
unlock_user(sf, sf_addr, sizeof(struct target_signal_frame));
- force_sigsegv(sig);
+ force_sigsegv(env, sig);
}
static void setup_rt_frame(int sig, struct target_sigaction *ka,
@@ -2695,7 +2917,7 @@ long do_sigreturn(CPUSPARCState *env)
sigset_t host_set;
int err=0, i;
- sf_addr = env->regwptr[UREG_FP];
+ sf_addr = env->regwptr[UREG_SP];
trace_user_do_sigreturn(env, sf_addr);
if (!lock_user_struct(VERIFY_READ, sf, sf_addr, 1)) {
goto segv_and_exit;
@@ -2727,7 +2949,7 @@ long do_sigreturn(CPUSPARCState *env)
__get_user(env->gregs[i], &sf->info.si_regs.u_regs[i]);
}
for (i=0; i < 8; i++) {
- __get_user(env->regwptr[i + UREG_I0], &sf->info.si_regs.u_regs[i+8]);
+ __get_user(env->regwptr[i + UREG_O0], &sf->info.si_regs.u_regs[i+8]);
}
/* FIXME: implement FPU save/restore:
@@ -2745,7 +2967,7 @@ long do_sigreturn(CPUSPARCState *env)
}
target_to_host_sigset_internal(&host_set, &set);
- set_sigmask(&host_set);
+ set_sigmask(env, &host_set);
if (err) {
goto segv_and_exit;
@@ -2755,7 +2977,7 @@ long do_sigreturn(CPUSPARCState *env)
segv_and_exit:
unlock_user_struct(sf, sf_addr, 0);
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -2844,7 +3066,7 @@ void sparc64_set_context(CPUSPARCState *env)
abi_ulong fp, i7, w_addr;
unsigned int i;
- ucp_addr = env->regwptr[UREG_I0];
+ ucp_addr = env->regwptr[UREG_O0];
if (!lock_user_struct(VERIFY_READ, ucp, ucp_addr, 1)) {
goto do_sigsegv;
}
@@ -2854,7 +3076,7 @@ void sparc64_set_context(CPUSPARCState *env)
if ((pc | npc) & 3) {
goto do_sigsegv;
}
- if (env->regwptr[UREG_I1]) {
+ if (env->regwptr[UREG_O1]) {
target_sigset_t target_set;
sigset_t set;
@@ -2869,7 +3091,7 @@ void sparc64_set_context(CPUSPARCState *env)
}
}
target_to_host_sigset_internal(&set, &target_set);
- set_sigmask(&set);
+ set_sigmask(env, &set);
}
env->pc = pc;
env->npc = npc;
@@ -2885,19 +3107,19 @@ void sparc64_set_context(CPUSPARCState *env)
__get_user(env->gregs[5], (&(*grp)[SPARC_MC_G5]));
__get_user(env->gregs[6], (&(*grp)[SPARC_MC_G6]));
__get_user(env->gregs[7], (&(*grp)[SPARC_MC_G7]));
- __get_user(env->regwptr[UREG_I0], (&(*grp)[SPARC_MC_O0]));
- __get_user(env->regwptr[UREG_I1], (&(*grp)[SPARC_MC_O1]));
- __get_user(env->regwptr[UREG_I2], (&(*grp)[SPARC_MC_O2]));
- __get_user(env->regwptr[UREG_I3], (&(*grp)[SPARC_MC_O3]));
- __get_user(env->regwptr[UREG_I4], (&(*grp)[SPARC_MC_O4]));
- __get_user(env->regwptr[UREG_I5], (&(*grp)[SPARC_MC_O5]));
- __get_user(env->regwptr[UREG_I6], (&(*grp)[SPARC_MC_O6]));
- __get_user(env->regwptr[UREG_I7], (&(*grp)[SPARC_MC_O7]));
+ __get_user(env->regwptr[UREG_O0], (&(*grp)[SPARC_MC_O0]));
+ __get_user(env->regwptr[UREG_O1], (&(*grp)[SPARC_MC_O1]));
+ __get_user(env->regwptr[UREG_O2], (&(*grp)[SPARC_MC_O2]));
+ __get_user(env->regwptr[UREG_O3], (&(*grp)[SPARC_MC_O3]));
+ __get_user(env->regwptr[UREG_O4], (&(*grp)[SPARC_MC_O4]));
+ __get_user(env->regwptr[UREG_O5], (&(*grp)[SPARC_MC_O5]));
+ __get_user(env->regwptr[UREG_O6], (&(*grp)[SPARC_MC_O6]));
+ __get_user(env->regwptr[UREG_O7], (&(*grp)[SPARC_MC_O7]));
__get_user(fp, &(ucp->tuc_mcontext.mc_fp));
__get_user(i7, &(ucp->tuc_mcontext.mc_i7));
- w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
+ w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_SP];
if (put_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
abi_ulong) != 0) {
goto do_sigsegv;
@@ -2930,7 +3152,7 @@ void sparc64_set_context(CPUSPARCState *env)
return;
do_sigsegv:
unlock_user_struct(ucp, ucp_addr, 0);
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
}
void sparc64_get_context(CPUSPARCState *env)
@@ -2945,7 +3167,7 @@ void sparc64_get_context(CPUSPARCState *env)
target_sigset_t target_set;
sigset_t set;
- ucp_addr = env->regwptr[UREG_I0];
+ ucp_addr = env->regwptr[UREG_O0];
if (!lock_user_struct(VERIFY_WRITE, ucp, ucp_addr, 0)) {
goto do_sigsegv;
}
@@ -2962,7 +3184,7 @@ void sparc64_get_context(CPUSPARCState *env)
* have any way to signal a failure or restart this operation since
* this is not a normal syscall.
*/
- err = do_sigprocmask(0, NULL, &set);
+ err = do_sigprocmask(env, 0, NULL, &set);
assert(err == 0);
host_to_target_sigset_internal(&target_set, &set);
if (TARGET_NSIG_WORDS == 1) {
@@ -2991,16 +3213,16 @@ void sparc64_get_context(CPUSPARCState *env)
__put_user(env->gregs[5], &((*grp)[SPARC_MC_G5]));
__put_user(env->gregs[6], &((*grp)[SPARC_MC_G6]));
__put_user(env->gregs[7], &((*grp)[SPARC_MC_G7]));
- __put_user(env->regwptr[UREG_I0], &((*grp)[SPARC_MC_O0]));
- __put_user(env->regwptr[UREG_I1], &((*grp)[SPARC_MC_O1]));
- __put_user(env->regwptr[UREG_I2], &((*grp)[SPARC_MC_O2]));
- __put_user(env->regwptr[UREG_I3], &((*grp)[SPARC_MC_O3]));
- __put_user(env->regwptr[UREG_I4], &((*grp)[SPARC_MC_O4]));
- __put_user(env->regwptr[UREG_I5], &((*grp)[SPARC_MC_O5]));
- __put_user(env->regwptr[UREG_I6], &((*grp)[SPARC_MC_O6]));
- __put_user(env->regwptr[UREG_I7], &((*grp)[SPARC_MC_O7]));
+ __put_user(env->regwptr[UREG_O0], &((*grp)[SPARC_MC_O0]));
+ __put_user(env->regwptr[UREG_O1], &((*grp)[SPARC_MC_O1]));
+ __put_user(env->regwptr[UREG_O2], &((*grp)[SPARC_MC_O2]));
+ __put_user(env->regwptr[UREG_O3], &((*grp)[SPARC_MC_O3]));
+ __put_user(env->regwptr[UREG_O4], &((*grp)[SPARC_MC_O4]));
+ __put_user(env->regwptr[UREG_O5], &((*grp)[SPARC_MC_O5]));
+ __put_user(env->regwptr[UREG_O6], &((*grp)[SPARC_MC_O6]));
+ __put_user(env->regwptr[UREG_O7], &((*grp)[SPARC_MC_O7]));
- w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_I6];
+ w_addr = TARGET_STACK_BIAS+env->regwptr[UREG_SP];
fp = i7 = 0;
if (get_user(fp, w_addr + offsetof(struct target_reg_window, ins[6]),
abi_ulong) != 0) {
@@ -3033,12 +3255,12 @@ void sparc64_get_context(CPUSPARCState *env)
return;
do_sigsegv:
unlock_user_struct(ucp, ucp_addr, 1);
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
}
#endif
#elif defined(TARGET_MIPS) || defined(TARGET_MIPS64)
-# if defined(TARGET_ABI_MIPSO32)
+# if defined(TARGET_ABI_MIPSO32) || defined(TARGET_ABI_IRIX)
struct target_sigcontext {
uint32_t sc_regmask; /* Unused */
uint32_t sc_status;
@@ -3081,12 +3303,16 @@ struct target_sigcontext {
# endif /* O32 */
struct sigframe {
+#ifndef TARGET_ABI_IRIX
uint32_t sf_ass[4]; /* argument save space for o32 */
uint32_t sf_code[2]; /* signal trampoline */
+#endif
struct target_sigcontext sf_sc;
target_sigset_t sf_mask;
};
+#ifndef TARGET_ABI_IRIX
+/* see linux-user/irix/target_signal.h */
struct target_ucontext {
target_ulong tuc_flags;
target_ulong tuc_link;
@@ -3095,14 +3321,18 @@ struct target_ucontext {
struct target_sigcontext tuc_mcontext;
target_sigset_t tuc_sigmask;
};
+#endif
struct target_rt_sigframe {
+#ifndef TARGET_ABI_IRIX
uint32_t rs_ass[4]; /* argument save space for o32 */
uint32_t rs_code[2]; /* signal trampoline */
+#endif
struct target_siginfo rs_info;
struct target_ucontext rs_uc;
};
+#ifndef TARGET_ABI_IRIX
/* Install trampoline to jump back from signal handler */
static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
{
@@ -3119,6 +3349,7 @@ static inline int install_sigtramp(unsigned int *tramp, unsigned int syscall)
__put_user(0x0000000c , tramp + 1);
return err;
}
+#endif
static inline void setup_sigcontext(CPUMIPSState *regs,
struct target_sigcontext *sc)
@@ -3187,13 +3418,86 @@ restore_sigcontext(CPUMIPSState *regs, struct target_sigcontext *sc)
}
}
+#ifdef TARGET_ABI_IRIX
+int
+save_context(CPUMIPSState *regs, struct target_mcontext *sc, int setret)
+{
+ int err = 0;
+ int i;
+
+ /* O32 saves a 32 bit context, N32 and N64 save a 64 bit context */
+#ifdef TARGET_ABI_MIPSO32
+ struct target_mcontext32 *mc = &sc->mc._32;
+#else
+ struct target_mcontext64 *mc = &sc->mc._64;
+#endif
+
+ /* store cpu registers */
+ __put_user(regs->active_tc.PC, &mc->gregs[35]);
+
+ __put_user( 0, &mc->gregs[0] );
+ for (i = 1; i < 32; i++) {
+ __put_user( regs->active_tc.gpr[i], &mc->gregs[i] );
+ }
+
+ __put_user(regs->active_tc.LO[0], &mc->gregs[32]);
+ __put_user(regs->active_tc.HI[0], &mc->gregs[33]);
+
+ /* store fpu registers */
+ for (i = 0; i < sizeof(mc->fregs)/sizeof(mc->fregs[0]); i++) {
+ __put_user( regs->active_fpu.fpr[i].d, (uint64_t *)&mc->fregs[i] );
+ }
+
+ __put_user( regs->active_fpu.fcr31, &mc->fpcsr );
+
+ /* set return code from getcontext if required */
+ if (setret) {
+ __put_user( 0, &mc->gregs[2] );
+ __put_user( 0, &mc->gregs[7] );
+ }
+
+ return err;
+}
+
+int
+restore_context(CPUMIPSState *regs, struct target_mcontext *sc)
+{
+ int err = 0;
+ int i;
+
+ /* O32 restores a 32 bit context, N32 and N64 restore a 64 bit context */
+#ifdef TARGET_ABI_MIPSO32
+ struct target_mcontext32 *mc = &sc->mc._32;
+#else
+ struct target_mcontext64 *mc = &sc->mc._64;
+#endif
+
+ /* restore cpu registers */
+ __get_user(regs->active_tc.PC, &mc->gregs[35]);
+
+ for (i = 1; i < 32; i++) {
+ __get_user( regs->active_tc.gpr[i], &mc->gregs[i] );
+ }
+
+ __get_user(regs->active_tc.LO[0], &mc->gregs[32]);
+ __get_user(regs->active_tc.HI[0], &mc->gregs[33]);
+
+ /* restore fpu registers */
+ for (i = 0; i < sizeof(mc->fregs)/sizeof(mc->fregs[0]); i++) {
+ __get_user( regs->active_fpu.fpr[i].d, (uint64_t *)&mc->fregs[i] );
+ }
+
+ return err;
+}
+#endif
+
/*
* Determine which stack to use..
*/
static inline abi_ulong
get_sigframe(struct target_sigaction *ka, CPUMIPSState *regs, size_t frame_size)
{
- unsigned long sp;
+ abi_ulong sp;
/* Default to using normal stack */
sp = regs->active_tc.gpr[29];
@@ -3222,11 +3526,22 @@ static void mips_set_hflags_isa_mode_from_pc(CPUMIPSState *env)
}
}
-# if defined(TARGET_ABI_MIPSO32)
+# if defined(TARGET_ABI_MIPSO32) || defined(TARGET_ABI_IRIX)
+/* IRIX knowhow taken from netbsd-5:/usr/src/sys/compat/irix/irix-signal.[ch].
+ * This is special insofar as the signal trampoline is part of libc, and the
+ * address of it is handed down to the kernel with sigaction. Linux uses the
+ * trampoline only for syscall(sigreturn), while in IRIX the trampoline controls
+ * the complete signal handling. It is called instead of the signal handler,
+ * and is given the signal handler as an argument.
+ */
+
/* compare linux/arch/mips/kernel/signal.c:setup_frame() */
static void setup_frame(int sig, struct target_sigaction * ka,
target_sigset_t *set, CPUMIPSState *regs)
{
+#ifdef TARGET_ABI_IRIX
+ TaskState *ts = ENV_GET_CPU(regs)->opaque;
+#endif
struct sigframe *frame;
abi_ulong frame_addr;
int i;
@@ -3237,7 +3552,9 @@ static void setup_frame(int sig, struct target_sigaction * ka,
goto give_sigsegv;
}
+#ifndef TARGET_ABI_IRIX
install_sigtramp(frame->sf_code, TARGET_NR_sigreturn);
+#endif
setup_sigcontext(regs, &frame->sf_sc);
@@ -3251,6 +3568,7 @@ static void setup_frame(int sig, struct target_sigaction * ka,
* a0 = signal number
* a1 = 0 (should be cause)
* a2 = pointer to struct sigcontext
+ * (a3 = pointer to signal handler) (ABI_IRIX)
*
* $25 and PC point to the signal handler, $29 points to the
* struct sigframe.
@@ -3259,17 +3577,23 @@ static void setup_frame(int sig, struct target_sigaction * ka,
regs->active_tc.gpr[ 5] = 0;
regs->active_tc.gpr[ 6] = frame_addr + offsetof(struct sigframe, sf_sc);
regs->active_tc.gpr[29] = frame_addr;
+#ifdef TARGET_ABI_IRIX
+ regs->active_tc.gpr[ 7] = ka->_sa_handler;
+ regs->active_tc.gpr[31] = 0;
+ regs->active_tc.PC = regs->active_tc.gpr[25] = ts->sigtramp;
+#else
regs->active_tc.gpr[31] = frame_addr + offsetof(struct sigframe, sf_code);
/* The original kernel code sets CP0_EPC to the handler
* since it returns to userland using eret
* we cannot do this here, and we must set PC directly */
regs->active_tc.PC = regs->active_tc.gpr[25] = ka->_sa_handler;
+#endif
mips_set_hflags_isa_mode_from_pc(regs);
unlock_user_struct(frame, frame_addr, 1);
return;
give_sigsegv:
- force_sigsegv(sig);
+ force_sigsegv(regs, sig);
}
long do_sigreturn(CPUMIPSState *regs)
@@ -3280,7 +3604,11 @@ long do_sigreturn(CPUMIPSState *regs)
target_sigset_t target_set;
int i;
+#ifdef TARGET_ABI_IRIX
+ frame_addr = regs->active_tc.gpr[ 5] - offsetof(struct sigframe, sf_sc);
+#else
frame_addr = regs->active_tc.gpr[29];
+#endif
trace_user_do_sigreturn(regs, frame_addr);
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1))
goto badframe;
@@ -3290,7 +3618,7 @@ long do_sigreturn(CPUMIPSState *regs)
}
target_to_host_sigset_internal(&blocked, &target_set);
- set_sigmask(&blocked);
+ set_sigmask(regs, &blocked);
restore_sigcontext(regs, &frame->sf_sc);
@@ -3306,15 +3634,17 @@ long do_sigreturn(CPUMIPSState *regs)
/* Unreached */
#endif
- regs->active_tc.PC = regs->CP0_EPC;
- mips_set_hflags_isa_mode_from_pc(regs);
- /* I am not sure this is right, but it seems to work
- * maybe a problem with nested signals ? */
- regs->CP0_EPC = 0;
+ if (regs->CP0_EPC) {
+ regs->active_tc.PC = regs->CP0_EPC;
+ mips_set_hflags_isa_mode_from_pc(regs);
+ /* I am not sure this is right, but it seems to work
+ * maybe a problem with nested signals ? */
+ regs->CP0_EPC = 0;
+ }
return -TARGET_QEMU_ESIGRETURN;
badframe:
- force_sig(TARGET_SIGSEGV);
+ force_sig(regs, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
# endif /* O32 */
@@ -3323,6 +3653,9 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
target_siginfo_t *info,
target_sigset_t *set, CPUMIPSState *env)
{
+#ifdef TARGET_ABI_IRIX
+ TaskState *ts = ENV_GET_CPU(env)->opaque;
+#endif
struct target_rt_sigframe *frame;
abi_ulong frame_addr;
int i;
@@ -3333,7 +3666,9 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
goto give_sigsegv;
}
+#ifndef TARGET_ABI_IRIX
install_sigtramp(frame->rs_code, TARGET_NR_rt_sigreturn);
+#endif
tswap_siginfo(&frame->rs_info, info);
@@ -3344,7 +3679,17 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
__put_user(sas_ss_flags(get_sp_from_cpustate(env)),
&frame->rs_uc.tuc_stack.ss_flags);
+#ifdef TARGET_ABI_IRIX
+ if (save_context(env, &frame->rs_uc.tuc_mcontext, 0))
+ goto give_sigsegv;
+ __put_user(ts->ctx_link, (abi_ulong *)&frame->rs_uc.tuc_link);
+ ts->ctx_link = frame_addr + offsetof(struct target_rt_sigframe, rs_uc);
+ __put_user(0x0f, &frame->rs_uc.tuc_flags);
+ for (i = 0; i < TARGET_NSIG_WORDS; i++)
+ __put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
+#else
setup_sigcontext(env, &frame->rs_uc.tuc_mcontext);
+#endif
for(i = 0; i < TARGET_NSIG_WORDS; i++) {
__put_user(set->sig[i], &frame->rs_uc.tuc_sigmask.sig[i]);
@@ -3356,6 +3701,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
* a0 = signal number
* a1 = pointer to siginfo_t
* a2 = pointer to ucontext_t
+ * (a3 = pointer to signal handler) (ABI_IRIX)
*
* $25 and PC point to the signal handler, $29 points to the
* struct sigframe.
@@ -3366,52 +3712,75 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
env->active_tc.gpr[ 6] = frame_addr
+ offsetof(struct target_rt_sigframe, rs_uc);
env->active_tc.gpr[29] = frame_addr;
+#ifdef TARGET_ABI_IRIX
+ /* inform trampoline about this being an rt sginal */
+ env->active_tc.gpr[ 4] |= 0x80000000L;
+ env->active_tc.gpr[ 7] = ka->_sa_handler;
+ env->active_tc.gpr[31] = 0;
+ env->active_tc.PC = env->active_tc.gpr[25] = ts->sigtramp;
+#else
env->active_tc.gpr[31] = frame_addr
+ offsetof(struct target_rt_sigframe, rs_code);
/* The original kernel code sets CP0_EPC to the handler
* since it returns to userland using eret
* we cannot do this here, and we must set PC directly */
env->active_tc.PC = env->active_tc.gpr[25] = ka->_sa_handler;
+#endif
mips_set_hflags_isa_mode_from_pc(env);
unlock_user_struct(frame, frame_addr, 1);
return;
give_sigsegv:
unlock_user_struct(frame, frame_addr, 1);
- force_sigsegv(sig);
+ force_sigsegv(env, sig);
}
long do_rt_sigreturn(CPUMIPSState *env)
{
+#ifdef TARGET_ABI_IRIX
+ TaskState *ts = ENV_GET_CPU(env)->opaque;
+#endif
struct target_rt_sigframe *frame;
abi_ulong frame_addr;
sigset_t blocked;
+#ifdef TARGET_ABI_IRIX
+ frame_addr = env->active_tc.gpr[ 5] - offsetof(struct target_rt_sigframe, rs_uc);
+#else
frame_addr = env->active_tc.gpr[29];
+#endif
trace_user_do_rt_sigreturn(env, frame_addr);
if (!lock_user_struct(VERIFY_READ, frame, frame_addr, 1)) {
goto badframe;
}
target_to_host_sigset(&blocked, &frame->rs_uc.tuc_sigmask);
- set_sigmask(&blocked);
+ set_sigmask(env, &blocked);
+#ifdef TARGET_ABI_IRIX
+ if (restore_context(env, &frame->rs_uc.tuc_mcontext))
+ goto badframe;
+ __get_user(ts->ctx_link, (abi_ulong *)&frame->rs_uc.tuc_link);
+#else
restore_sigcontext(env, &frame->rs_uc.tuc_mcontext);
+#endif
- if (do_sigaltstack(frame_addr +
+ if (do_sigaltstack(env, frame_addr +
offsetof(struct target_rt_sigframe, rs_uc.tuc_stack),
0, get_sp_from_cpustate(env)) == -EFAULT)
goto badframe;
- env->active_tc.PC = env->CP0_EPC;
- mips_set_hflags_isa_mode_from_pc(env);
- /* I am not sure this is right, but it seems to work
- * maybe a problem with nested signals ? */
- env->CP0_EPC = 0;
+ if (env->CP0_EPC) {
+ env->active_tc.PC = env->CP0_EPC;
+ mips_set_hflags_isa_mode_from_pc(env);
+ /* I am not sure this is right, but it seems to work
+ * maybe a problem with nested signals ? */
+ env->CP0_EPC = 0;
+ }
return -TARGET_QEMU_ESIGRETURN;
badframe:
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -3609,7 +3978,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
give_sigsegv:
unlock_user_struct(frame, frame_addr, 1);
- force_sigsegv(sig);
+ force_sigsegv(regs, sig);
}
static void setup_rt_frame(int sig, struct target_sigaction *ka,
@@ -3672,7 +4041,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
give_sigsegv:
unlock_user_struct(frame, frame_addr, 1);
- force_sigsegv(sig);
+ force_sigsegv(regs, sig);
}
long do_sigreturn(CPUSH4State *regs)
@@ -3699,7 +4068,7 @@ long do_sigreturn(CPUSH4State *regs)
goto badframe;
target_to_host_sigset_internal(&blocked, &target_set);
- set_sigmask(&blocked);
+ set_sigmask(regs, &blocked);
restore_sigcontext(regs, &frame->sc);
@@ -3708,7 +4077,7 @@ long do_sigreturn(CPUSH4State *regs)
badframe:
unlock_user_struct(frame, frame_addr, 0);
- force_sig(TARGET_SIGSEGV);
+ force_sig(regs, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -3725,11 +4094,11 @@ long do_rt_sigreturn(CPUSH4State *regs)
}
target_to_host_sigset(&blocked, &frame->uc.tuc_sigmask);
- set_sigmask(&blocked);
+ set_sigmask(regs, &blocked);
restore_sigcontext(regs, &frame->uc.tuc_mcontext);
- if (do_sigaltstack(frame_addr +
+ if (do_sigaltstack(regs, frame_addr +
offsetof(struct target_rt_sigframe, uc.tuc_stack),
0, get_sp_from_cpustate(regs)) == -EFAULT) {
goto badframe;
@@ -3740,7 +4109,7 @@ long do_rt_sigreturn(CPUSH4State *regs)
badframe:
unlock_user_struct(frame, frame_addr, 0);
- force_sig(TARGET_SIGSEGV);
+ force_sig(regs, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
#elif defined(TARGET_MICROBLAZE)
@@ -3919,7 +4288,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
unlock_user_struct(frame, frame_addr, 1);
return;
badframe:
- force_sigsegv(sig);
+ force_sigsegv(env, sig);
}
static void setup_rt_frame(int sig, struct target_sigaction *ka,
@@ -3949,7 +4318,7 @@ long do_sigreturn(CPUMBState *env)
__get_user(target_set.sig[i], &frame->extramask[i - 1]);
}
target_to_host_sigset_internal(&set, &target_set);
- set_sigmask(&set);
+ set_sigmask(env, &set);
restore_sigcontext(&frame->uc.tuc_mcontext, env);
/* We got here through a sigreturn syscall, our path back is via an
@@ -3959,7 +4328,7 @@ long do_sigreturn(CPUMBState *env)
unlock_user_struct(frame, frame_addr, 0);
return -TARGET_QEMU_ESIGRETURN;
badframe:
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -4090,7 +4459,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
unlock_user_struct(frame, frame_addr, 1);
return;
badframe:
- force_sigsegv(sig);
+ force_sigsegv(env, sig);
}
static void setup_rt_frame(int sig, struct target_sigaction *ka,
@@ -4121,13 +4490,13 @@ long do_sigreturn(CPUCRISState *env)
__get_user(target_set.sig[i], &frame->extramask[i - 1]);
}
target_to_host_sigset_internal(&set, &target_set);
- set_sigmask(&set);
+ set_sigmask(env, &set);
restore_sigcontext(&frame->sc, env);
unlock_user_struct(frame, frame_addr, 0);
return -TARGET_QEMU_ESIGRETURN;
badframe:
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -4262,7 +4631,7 @@ static int rt_restore_ucontext(CPUNios2State *env, struct target_ucontext *uc,
__get_user(env->regs[R_SP], &gregs[28]);
off = offsetof(struct target_rt_sigframe, uc.tuc_stack);
- err = do_sigaltstack(frame_addr + off, 0, get_sp_from_cpustate(env));
+ err = do_sigaltstack(env, frame_addr + off, 0, get_sp_from_cpustate(env));
if (err == -EFAULT) {
return 1;
}
@@ -4332,7 +4701,7 @@ give_sigsegv:
if (sig == TARGET_SIGSEGV) {
ka->_sa_handler = TARGET_SIG_DFL;
}
- force_sigsegv(sig);
+ force_sigsegv(env, sig);
return;
}
@@ -4356,7 +4725,7 @@ long do_rt_sigreturn(CPUNios2State *env)
}
target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
- do_sigprocmask(SIG_SETMASK, &set, NULL);
+ do_sigprocmask(env, SIG_SETMASK, &set, NULL);
if (rt_restore_ucontext(env, &frame->uc, &rval)) {
goto badframe;
@@ -4367,7 +4736,7 @@ long do_rt_sigreturn(CPUNios2State *env)
badframe:
unlock_user_struct(frame, frame_addr, 0);
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return 0;
}
/* TARGET_NIOS2 */
@@ -4565,7 +4934,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
give_sigsegv:
unlock_user_struct(frame, frame_addr, 1);
- force_sigsegv(sig);
+ force_sigsegv(env, sig);
}
long do_sigreturn(CPUOpenRISCState *env)
@@ -4746,7 +5115,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
return;
give_sigsegv:
- force_sigsegv(sig);
+ force_sigsegv(env, sig);
}
static void setup_rt_frame(int sig, struct target_sigaction *ka,
@@ -4801,7 +5170,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
return;
give_sigsegv:
- force_sigsegv(sig);
+ force_sigsegv(env, sig);
}
static int
@@ -4844,7 +5213,7 @@ long do_sigreturn(CPUS390XState *env)
__get_user(target_set.sig[0], &frame->sc.oldmask[0]);
target_to_host_sigset_internal(&set, &target_set);
- set_sigmask(&set); /* ~_BLOCKABLE? */
+ set_sigmask(env, &set); /* ~_BLOCKABLE? */
if (restore_sigregs(env, &frame->sregs)) {
goto badframe;
@@ -4854,7 +5223,7 @@ long do_sigreturn(CPUS390XState *env)
return -TARGET_QEMU_ESIGRETURN;
badframe:
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -4870,13 +5239,13 @@ long do_rt_sigreturn(CPUS390XState *env)
}
target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
- set_sigmask(&set); /* ~_BLOCKABLE? */
+ set_sigmask(env, &set); /* ~_BLOCKABLE? */
if (restore_sigregs(env, &frame->uc.tuc_mcontext)) {
goto badframe;
}
- if (do_sigaltstack(frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
+ if (do_sigaltstack(env, frame_addr + offsetof(rt_sigframe, uc.tuc_stack), 0,
get_sp_from_cpustate(env)) == -EFAULT) {
goto badframe;
}
@@ -4885,7 +5254,7 @@ long do_rt_sigreturn(CPUS390XState *env)
badframe:
unlock_user_struct(frame, frame_addr, 0);
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -5358,7 +5727,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
sigsegv:
unlock_user_struct(frame, frame_addr, 1);
- force_sigsegv(sig);
+ force_sigsegv(env, sig);
}
#endif /* !defined(TARGET_PPC64) */
@@ -5373,7 +5742,8 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
int i, err = 0;
#if defined(TARGET_PPC64)
struct target_sigcontext *sc = 0;
- struct image_info *image = ((TaskState *)thread_cpu->opaque)->info;
+ CPUState *cpu = ENV_GET_CPU(env);
+ struct image_info *image = ((TaskState *)cpu->opaque)->info;
#endif
rt_sf_addr = get_sigframe(ka, env, sizeof(*rt_sf));
@@ -5459,7 +5829,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
sigsegv:
unlock_user_struct(rt_sf, rt_sf_addr, 1);
- force_sigsegv(sig);
+ force_sigsegv(env, sig);
}
@@ -5483,7 +5853,7 @@ long do_sigreturn(CPUPPCState *env)
__get_user(set.sig[1], &sc->_unused[3]);
#endif
target_to_host_sigset_internal(&blocked, &set);
- set_sigmask(&blocked);
+ set_sigmask(env, &blocked);
__get_user(sr_addr, &sc->regs);
if (!lock_user_struct(VERIFY_READ, sr, sr_addr, 1))
@@ -5497,7 +5867,7 @@ long do_sigreturn(CPUPPCState *env)
sigsegv:
unlock_user_struct(sr, sr_addr, 1);
unlock_user_struct(sc, sc_addr, 1);
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
#endif /* !defined(TARGET_PPC64) */
@@ -5525,7 +5895,7 @@ static int do_setcontext(struct target_ucontext *ucp, CPUPPCState *env, int sig)
return 1;
target_to_host_sigset_internal(&blocked, &set);
- set_sigmask(&blocked);
+ set_sigmask(env, &blocked);
restore_user_regs(env, mcp, sig);
unlock_user_struct(mcp, mcp_addr, 1);
@@ -5544,7 +5914,7 @@ long do_rt_sigreturn(CPUPPCState *env)
if (do_setcontext(&rt_sf->uc, env, 1))
goto sigsegv;
- do_sigaltstack(rt_sf_addr
+ do_sigaltstack(env, rt_sf_addr
+ offsetof(struct target_rt_sigframe, uc.tuc_stack),
0, env->gpr[1]);
@@ -5553,7 +5923,7 @@ long do_rt_sigreturn(CPUPPCState *env)
sigsegv:
unlock_user_struct(rt_sf, rt_sf_addr, 1);
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -5711,7 +6081,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
return;
give_sigsegv:
- force_sigsegv(sig);
+ force_sigsegv(env, sig);
}
static inline void target_rt_save_fpu_state(struct target_ucontext *uc,
@@ -5894,7 +6264,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
give_sigsegv:
unlock_user_struct(frame, frame_addr, 1);
- force_sigsegv(sig);
+ force_sigsegv(env, sig);
}
long do_sigreturn(CPUM68KState *env)
@@ -5918,7 +6288,7 @@ long do_sigreturn(CPUM68KState *env)
}
target_to_host_sigset_internal(&set, &target_set);
- set_sigmask(&set);
+ set_sigmask(env, &set);
/* restore registers */
@@ -5928,7 +6298,7 @@ long do_sigreturn(CPUM68KState *env)
return -TARGET_QEMU_ESIGRETURN;
badframe:
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -5943,14 +6313,14 @@ long do_rt_sigreturn(CPUM68KState *env)
goto badframe;
target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
- set_sigmask(&set);
+ set_sigmask(env, &set);
/* restore registers */
if (target_rt_restore_ucontext(env, &frame->uc))
goto badframe;
- if (do_sigaltstack(frame_addr +
+ if (do_sigaltstack(env, frame_addr +
offsetof(struct target_rt_sigframe, uc.tuc_stack),
0, get_sp_from_cpustate(env)) == -EFAULT)
goto badframe;
@@ -5960,7 +6330,7 @@ long do_rt_sigreturn(CPUM68KState *env)
badframe:
unlock_user_struct(frame, frame_addr, 0);
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -6100,7 +6470,7 @@ static void setup_frame(int sig, struct target_sigaction *ka,
if (err) {
give_sigsegv:
- force_sigsegv(sig);
+ force_sigsegv(env, sig);
return;
}
@@ -6155,7 +6525,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
if (err) {
give_sigsegv:
- force_sigsegv(sig);
+ force_sigsegv(env, sig);
return;
}
@@ -6182,14 +6552,14 @@ long do_sigreturn(CPUAlphaState *env)
__get_user(target_set.sig[0], &sc->sc_mask);
target_to_host_sigset_internal(&set, &target_set);
- set_sigmask(&set);
+ set_sigmask(env, &set);
restore_sigcontext(env, sc);
unlock_user_struct(sc, sc_addr, 0);
return -TARGET_QEMU_ESIGRETURN;
badframe:
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -6204,10 +6574,10 @@ long do_rt_sigreturn(CPUAlphaState *env)
goto badframe;
}
target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
- set_sigmask(&set);
+ set_sigmask(env, &set);
restore_sigcontext(env, &frame->uc.tuc_mcontext);
- if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
+ if (do_sigaltstack(env, frame_addr + offsetof(struct target_rt_sigframe,
uc.tuc_stack),
0, env->ir[IR_SP]) == -EFAULT) {
goto badframe;
@@ -6219,7 +6589,7 @@ long do_rt_sigreturn(CPUAlphaState *env)
badframe:
unlock_user_struct(frame, frame_addr, 0);
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -6355,7 +6725,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
return;
give_sigsegv:
- force_sigsegv(sig);
+ force_sigsegv(env, sig);
}
long do_rt_sigreturn(CPUTLGState *env)
@@ -6369,10 +6739,10 @@ long do_rt_sigreturn(CPUTLGState *env)
goto badframe;
}
target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
- set_sigmask(&set);
+ set_sigmask(env, &set);
restore_sigcontext(env, &frame->uc.tuc_mcontext);
- if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
+ if (do_sigaltstack(env, frame_addr + offsetof(struct target_rt_sigframe,
uc.tuc_stack),
0, env->regs[TILEGX_R_SP]) == -EFAULT) {
goto badframe;
@@ -6384,7 +6754,7 @@ long do_rt_sigreturn(CPUTLGState *env)
badframe:
unlock_user_struct(frame, frame_addr, 0);
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -6520,7 +6890,7 @@ badframe:
if (sig == TARGET_SIGSEGV) {
ka->_sa_handler = TARGET_SIG_DFL;
}
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
}
static void restore_sigcontext(CPURISCVState *env, struct target_sigcontext *sc)
@@ -6553,7 +6923,7 @@ static void restore_ucontext(CPURISCVState *env, struct target_ucontext *uc)
}
target_to_host_sigset_internal(&blocked, &target_set);
- set_sigmask(&blocked);
+ set_sigmask(env, &blocked);
restore_sigcontext(env, &uc->uc_mcontext);
}
@@ -6571,7 +6941,7 @@ long do_rt_sigreturn(CPURISCVState *env)
restore_ucontext(env, &frame->uc);
- if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
+ if (do_sigaltstack(env, frame_addr + offsetof(struct target_rt_sigframe,
uc.uc_stack), 0, get_sp_from_cpustate(env)) == -EFAULT) {
goto badframe;
}
@@ -6581,7 +6951,7 @@ long do_rt_sigreturn(CPURISCVState *env)
badframe:
unlock_user_struct(frame, frame_addr, 0);
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return 0;
}
@@ -6741,7 +7111,7 @@ static void setup_rt_frame(int sig, struct target_sigaction *ka,
return;
give_sigsegv:
- force_sigsegv(sig);
+ force_sigsegv(env, sig);
}
long do_rt_sigreturn(CPUArchState *env)
@@ -6755,12 +7125,12 @@ long do_rt_sigreturn(CPUArchState *env)
goto badframe;
}
target_to_host_sigset(&set, &frame->uc.tuc_sigmask);
- set_sigmask(&set);
+ set_sigmask(env, &set);
restore_sigcontext(env, &frame->uc.tuc_mcontext);
unlock_user_struct(frame, frame_addr, 0);
- if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
+ if (do_sigaltstack(env, frame_addr + offsetof(struct target_rt_sigframe,
uc.tuc_stack),
0, env->gr[30]) == -EFAULT) {
goto badframe;
@@ -6770,7 +7140,7 @@ long do_rt_sigreturn(CPUArchState *env)
return -TARGET_QEMU_ESIGRETURN;
badframe:
- force_sig(TARGET_SIGSEGV);
+ force_sig(env, TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
@@ -6838,12 +7208,12 @@ static void handle_pending_signal(CPUArchState *cpu_env, int sig,
sig != TARGET_SIGURG &&
sig != TARGET_SIGWINCH &&
sig != TARGET_SIGCONT) {
- dump_core_and_abort(sig);
+ dump_core_and_abort(cpu_env, sig);
}
} else if (handler == TARGET_SIG_IGN) {
/* ignore sig */
} else if (handler == TARGET_SIG_ERR) {
- dump_core_and_abort(sig);
+ dump_core_and_abort(cpu_env, sig);
} else {
/* compute the blocked signals during the handler execution */
sigset_t *blocked_set;
@@ -6872,12 +7242,13 @@ static void handle_pending_signal(CPUArchState *cpu_env, int sig,
save_v86_state(env);
}
#endif
+
/* prepare the stack frame of the virtual CPU */
-#if defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \
+#if (defined(TARGET_ABI_MIPSN32) || defined(TARGET_ABI_MIPSN64) \
|| defined(TARGET_OPENRISC) || defined(TARGET_TILEGX) \
|| defined(TARGET_PPC64) || defined(TARGET_HPPA) \
|| defined(TARGET_NIOS2) || defined(TARGET_X86_64) \
- || defined(TARGET_RISCV)
+ || defined(TARGET_RISCV)) && !defined(TARGET_ABI_IRIX)
/* These targets do not have traditional signals. */
setup_rt_frame(sig, sa, &k->info, &target_old_set, cpu_env);
#else
diff --git a/linux-user/socket.h b/linux-user/socket.h
index 7051cd2cf4..ae1bc338fc 100644
--- a/linux-user/socket.h
+++ b/linux-user/socket.h
@@ -1,5 +1,91 @@
-#if defined(TARGET_MIPS)
+#if defined(TARGET_ABI_IRIX) || defined(TARGET_ABI_SOLARIS)
+
+ /* For setsockopt(2) */
+ #define TARGET_SOL_SOCKET 0xffff
+
+ #define TARGET_SO_DEBUG 0x0001
+ #define TARGET_SO_REUSEADDR 0x0004
+ #define TARGET_SO_KEEPALIVE 0x0008
+ #define TARGET_SO_DONTROUTE 0x0010
+ #define TARGET_SO_BROADCAST 0x0020
+ #define TARGET_SO_LINGER 0x0080
+ #define TARGET_SO_OOBINLINE 0x0100
+ #define TARGET_SO_ACCEPTCONN 0x0002
+ /* To add :#define TARGET_SO_REUSEPORT 0x0200 */
+
+ #define TARGET_SO_TYPE 0x1008
+ #define TARGET_SO_ERROR 0x1007
+ #define TARGET_SO_SNDBUF 0x1001
+ #define TARGET_SO_RCVBUF 0x1002
+ #define TARGET_SO_SNDBUFFORCE 0x10ff
+ #define TARGET_SO_RCVBUFFORCE 0x10fe
+ #define TARGET_SO_RCVLOWAT 0x1003
+ #define TARGET_SO_SNDLOWAT 0x1004
+ #define TARGET_SO_RCVTIMEO 0x1006
+ #define TARGET_SO_SNDTIMEO 0x1005
+ #define TARGET_SO_PROTOCOL 0x1009
+ #define TARGET_SO_DOMAIN 0x100c
+ #define TARGET_SO_TIMESTAMP 0x1013
+ #define TARGET_SCM_TIMESTAMP TARGET_SO_TIMESTAMP
+
+ /* linux-specific, might as well be the same as on i386 */
+ #define TARGET_SO_NO_CHECK 11
+ #define TARGET_SO_PRIORITY 12
+ #define TARGET_SO_BSDCOMPAT 14
+
+ #define TARGET_SO_PASSCRED 17
+ #define TARGET_SO_PEERCRED 18
+ #define TARGET_SO_BINDTODEVICE 25
+
+ /* Socket filtering */
+ #define TARGET_SO_ATTACH_FILTER 26
+ #define TARGET_SO_DETACH_FILTER 27
+
+ #define TARGET_SO_PEERNAME 28
+
+ #define TARGET_SO_PEERSEC 30
+ #define TARGET_SO_PASSSEC 34
+ #define TARGET_SO_TIMESTAMPNS 35
+ #define TARGET_SCM_TIMESTAMPNS TARGET_SO_TIMESTAMPNS
+
+ /* Security levels - as per NRL IPv6 - don't actually do anything */
+ #define TARGET_SO_SECURITY_AUTHENTICATION 19
+ #define TARGET_SO_SECURITY_ENCRYPTION_TRANSPORT 20
+ #define TARGET_SO_SECURITY_ENCRYPTION_NETWORK 21
+
+ #define TARGET_SO_MARK 36
+
+ #define TARGET_SO_TIMESTAMPING 37
+ #define TARGET_SCM_TIMESTAMPING TARGET_SO_TIMESTAMPING
+
+ #define TARGET_SO_RXQ_OVFL 40
+
+ #define TARGET_SO_WIFI_STATUS 41
+ #define TARGET_SCM_WIFI_STATUS TARGET_SO_WIFI_STATUS
+ #define TARGET_SO_PEEK_OFF 42
+
+ /* Instruct lower device to use last 4-bytes of skb data as FCS */
+ #define TARGET_SO_NOFCS 43
+
+ /** sock_type - Socket types */
+
+ #define ARCH_HAS_SOCKET_TYPES 1
+
+ enum sock_type {
+ TARGET_SOCK_STREAM = 2,
+ TARGET_SOCK_DGRAM = 1,
+ TARGET_SOCK_RAW = 4,
+ TARGET_SOCK_RDM = 5,
+ TARGET_SOCK_SEQPACKET = 6,
+ TARGET_SOCK_CLOEXEC = 0x080000,
+ TARGET_SOCK_NONBLOCK = 0x100000,
+ };
+
+ #define TARGET_SOCK_MAX (TARGET_SOCK_SEQPACKET + 1)
+ #define TARGET_SOCK_TYPE_MASK 0xf /* Covers up to TARGET_SOCK_MAX-1. */
+
+#elif defined(TARGET_MIPS)
/* MIPS special values for constants */
/*
diff --git a/linux-user/solaris/syscall_nr.h b/linux-user/solaris/syscall_nr.h
new file mode 100644
index 0000000000..d6873f14ea
--- /dev/null
+++ b/linux-user/solaris/syscall_nr.h
@@ -0,0 +1,360 @@
+/*
+ * Solaris syscalls. This is derived from Netbsd svr4_32_sysent.c and Solaris 7
+ * syscall.h, with extensions from Illumos for stuff undefined in Solaris 7.
+ */
+
+#define TARGET_NR_syscall 0
+#define TARGET_NR_exit 1
+#define TARGET_NR_fork 2
+#define TARGET_NR_read 3
+#define TARGET_NR_write 4
+#define TARGET_NR_open 5
+#define TARGET_NR_close 6
+#define TARGET_NR_linkat 7 /* wait in Solaris 7 */
+#define TARGET_NR_creat 8
+#define TARGET_NR_link 9
+#define TARGET_NR_unlink 10
+#define TARGET_NR_symlinkat 11 /* exec in Solaris 7 */
+#define TARGET_NR_chdir 12
+#define TARGET_NR_time 13
+#define TARGET_NR_mknod 14
+#define TARGET_NR_chmod 15
+#define TARGET_NR_chown 16
+#define TARGET_NR_brk 17
+#define TARGET_NR_stat 18
+#define TARGET_NR_lseek 19
+#define TARGET_NR_getpid 20
+#define TARGET_NR_mount 21
+#define TARGET_NR_readlinkat 22 /* umount in Solaris 7 */
+#define TARGET_NR_setuid 23
+#define TARGET_NR_getuid 24
+#define TARGET_NR_stime 25
+#define TARGET_NR_pcsample 26
+#define TARGET_NR_alarm 27
+#define TARGET_NR_fstat 28
+#define TARGET_NR_pause 29
+#define TARGET_NR_utime 30
+#define TARGET_NR_stty 31
+#define TARGET_NR_gtty 32
+#define TARGET_NR_access 33
+#define TARGET_NR_nice 34
+#define TARGET_NR_statfs 35
+#define TARGET_NR_sync 36
+#define TARGET_NR_kill 37
+#define TARGET_NR_fstatfs 38
+#define TARGET_NR_pgrpsys 39
+#define TARGET_NR_xenix 40 /* uucopystr for Solaris 10 */
+#define TARGET_NR_dup 41
+#define TARGET_NR_pipe 42
+#define TARGET_NR_times 43
+#define TARGET_NR_profil 44
+#define TARGET_NR_faccessat 45 /* plock in Solaris 7 */
+#define TARGET_NR_setgid 46
+#define TARGET_NR_getgid 47
+#define TARGET_NR_mknodat 48 /* signal in Solaris 7 */
+#define TARGET_NR_msgsys 49
+#define TARGET_NR_sysarch 50
+#define TARGET_NR_acct 51
+#define TARGET_NR_shmsys 52
+#define TARGET_NR_semsys 53
+#define TARGET_NR_ioctl 54
+#define TARGET_NR_uadmin 55
+#define TARGET_NR_fchownat 56 /* undefined for Solaris 7 */
+#define TARGET_NR_utssyssunos 57
+#define TARGET_NR_fdsync 58
+#define TARGET_NR_execve 59
+#define TARGET_NR_umask 60
+#define TARGET_NR_chroot 61
+#define TARGET_NR_fcntl 62
+#define TARGET_NR_ulimit 63
+#define TARGET_NR_renameat 64 /* undefined in Solaris 7 */
+#define TARGET_NR_unlinkat 65 /* undefined in Solaris 7 */
+#define TARGET_NR_fstatat 66 /* undefined in Solaris 7 */
+#define TARGET_NR_fstatat64 67 /* undefined in Solaris 7 */
+#define TARGET_NR_openat 68 /* undefined in Solaris 7 */
+#define TARGET_NR_openat64 69 /* undefined in Solaris 7 */
+#define TARGET_NR_tasksys 70 /* undefined in Solaris 7 */
+#define TARGET_NR_acctctl 71 /* undefined in Solaris 7 */
+#define TARGET_NR_exacctsys 72 /* undefined in Solaris 7 */
+#define TARGET_NR_getpagesizes 73 /* undefined in Solaris 7 */
+#define TARGET_NR_rctlsys 74 /* undefined in Solaris 7 */
+#define TARGET_NR_sidsys 75 /* undefined in Solaris 7 */
+#define TARGET_NR_fsat 76 /* undefined in Solaris 7 */
+#define TARGET_NR_lwp_park 77 /* undefined in Solaris 7 */
+#define TARGET_NR_sendfilev 78 /* undefined in Solaris 7 */
+#define TARGET_NR_rmdir 79
+#define TARGET_NR_mkdir 80
+#define TARGET_NR_getdents 81
+#define TARGET_NR_privsys 82 /* undefined in Solaris 7 */
+#define TARGET_NR_ucredsys 83 /* undefined in Solaris 7 */
+#define TARGET_NR_sysfs 84
+#define TARGET_NR_getmsg 85
+#define TARGET_NR_putmsg 86
+#define TARGET_NR_poll 87
+#define TARGET_NR_lstat 88
+#define TARGET_NR_symlink 89
+#define TARGET_NR_readlink 90
+#define TARGET_NR_setgroups 91
+#define TARGET_NR_getgroups 92
+#define TARGET_NR_fchmod 93
+#define TARGET_NR_fchown 94
+#define TARGET_NR_sigprocmask 95
+#define TARGET_NR_sigsuspend 96
+#define TARGET_NR_sigaltstack 97
+#define TARGET_NR_sigaction 98
+#define TARGET_NR_sigpendingsys 99
+#define TARGET_NR_context 100
+#define TARGET_NR_fchmodat 101 /* evsys in Solaris 7 */
+#define TARGET_NR_mkdirat 102 /* evtrapret in Solaris 7 */
+#define TARGET_NR_statvfs 103
+#define TARGET_NR_fstatvfs 104
+#define TARGET_NR_getloadavg 105
+#define TARGET_NR_nfssys 106
+#define TARGET_NR_waitid 107
+#define TARGET_NR_sigsendsys 108
+#define TARGET_NR_hrtsys 109
+#define TARGET_NR_acancel 110 /* utimesys in Solaris 10 */
+#define TARGET_NR_async 111 /* sigresend in Solaris 10 */
+#define TARGET_NR_priocntlsys 112
+#define TARGET_NR_pathconf 113
+#define TARGET_NR_mincore 114
+#define TARGET_NR_mmap 115
+#define TARGET_NR_mprotect 116
+#define TARGET_NR_munmap 117
+#define TARGET_NR_fpathconf 118
+#define TARGET_NR_vfork 119
+#define TARGET_NR_fchdir 120
+#define TARGET_NR_readv 121
+#define TARGET_NR_writev 122
+#define TARGET_NR_xstat 123 /* preadv in Solaris 10 */
+#define TARGET_NR_lxstat 124 /* pwritev in Solaris 10 */
+#define TARGET_NR_fxstat 125 /* undefined in Solaris 10 */
+#define TARGET_NR_xmknod 126 /* undefined in Solaris 10 */
+#define TARGET_NR_clocal 127 /* mmapobj in Solaris 10 */
+#define TARGET_NR_setrlimit 128
+#define TARGET_NR_getrlimit 129
+#define TARGET_NR_lchown 130
+#define TARGET_NR_memcntl 131
+#define TARGET_NR_getpmsg 132
+#define TARGET_NR_putpmsg 133
+#define TARGET_NR_rename 134
+#define TARGET_NR_unamesunos 135
+#define TARGET_NR_setegid 136
+#define TARGET_NR_sysconfig 137
+#define TARGET_NR_adjtime 138
+#define TARGET_NR_sysinfosunos 139
+#define TARGET_NR_sharefs 140 /* undefined for Solaris 7 */
+#define TARGET_NR_seteuid 141
+#define TARGET_NR_forksys 142 /* vtrace for Solaris 7 */
+#define TARGET_NR_fork1 143 /* undefined for Solaris 10 */
+#define TARGET_NR_sigtimedwait 144
+#define TARGET_NR_lwp_info 145
+#define TARGET_NR_yield 146
+#define TARGET_NR_lwp_sema_wait 147 /* undefined in Solaris 10 */
+#define TARGET_NR_lwp_sema_post 148
+#define TARGET_NR_lwp_sema_trywait 149
+#define TARGET_NR_lwp_detach 150 /* undefined for Solaris 7 */
+#define TARGET_NR_corectl 151
+#define TARGET_NR_modctl 152
+#define TARGET_NR_fchroot 153
+#define TARGET_NR_utimes 154
+#define TARGET_NR_vhangup 155
+#define TARGET_NR_gettimeofday 156
+#define TARGET_NR_getitimer 157
+#define TARGET_NR_setitimer 158
+#define TARGET_NR_lwp_create 159
+#define TARGET_NR_lwp_exit 160
+#define TARGET_NR_lwp_suspend 161
+#define TARGET_NR_lwp_continue 162
+#define TARGET_NR_lwp_kill 163
+#define TARGET_NR_lwp_self 164
+#define TARGET_NR_lwp_setprivate 165 /* lwp_sigmask for Solaris 10 */
+#define TARGET_NR_lwp_getprivate 166 /* lwp_private for Solaris 10 */
+#define TARGET_NR_lwp_wait 167
+#define TARGET_NR_lwp_mutex_wakeup 168
+#define TARGET_NR_lwp_mutex_lock 169 /* undefined in Solaris 10 */
+#define TARGET_NR_lwp_cond_wait 170
+#define TARGET_NR_lwp_cond_signal 171
+#define TARGET_NR_lwp_cond_broadcast 172
+#define TARGET_NR_pread 173
+#define TARGET_NR_pwrite 174
+#define TARGET_NR__llseek 175
+#define TARGET_NR_inst_sync 176
+#define TARGET_NR_brand 177
+#define TARGET_NR_kaio 178
+#define TARGET_NR_cpc 179 /* undefined in Solaris 7 */
+#define TARGET_NR_meminfosys 180 /* undefined in Solaris 7 */
+#define TARGET_NR_rusagesys 181 /* undefined in Solaris 7 */
+#define TARGET_NR_port 182 /* undefined in Solaris 7 */
+#define TARGET_NR_pollsys 183 /* undefined in Solaris 7 */
+#define TARGET_NR_tsolsys 184 /* labelsys in Solaris 10 */
+#define TARGET_NR_acl 185
+#define TARGET_NR_auditsys 186
+#define TARGET_NR_processor_bind 187
+#define TARGET_NR_processor_info 188
+#define TARGET_NR_p_online 189
+#define TARGET_NR_sigqueue 190
+#define TARGET_NR_clock_gettime 191
+#define TARGET_NR_clock_settime 192
+#define TARGET_NR_clock_getres 193
+#define TARGET_NR_timer_create 194
+#define TARGET_NR_timer_delete 195
+#define TARGET_NR_timer_settime 196
+#define TARGET_NR_timer_gettime 197
+#define TARGET_NR_timer_getoverrun 198
+#define TARGET_NR_nanosleep 199
+#define TARGET_NR_facl 200
+#define TARGET_NR_door 201
+#define TARGET_NR_setreuid 202
+#define TARGET_NR_setregid 203
+#define TARGET_NR_install_utrap 204
+#define TARGET_NR_signotify 205
+#define TARGET_NR_schedctl 206
+#define TARGET_NR_pset 207
+#define TARGET_NR_sparc_utrap_install 208
+#define TARGET_NR_resolvepath 209
+#define TARGET_NR_signotifywait 210 /* lwp_mutex_timedlock for Solaris 10 */
+#define TARGET_NR_lwp_sigredirect 211 /* lwp_sema_timedwait for Solaris 10 */
+#define TARGET_NR_lwp_alarm 212 /* lwp_rwlock_sys for Solaris 10 */
+/* system calls for large files ( > 2 gigabyte) */
+#define TARGET_NR_getdents64 213
+#define TARGET_NR_mmap64 214
+#define TARGET_NR_stat64 215
+#define TARGET_NR_lstat64 216
+#define TARGET_NR_fstat64 217
+#define TARGET_NR_statvfs64 218
+#define TARGET_NR_fstatvfs64 219
+#define TARGET_NR_setrlimit64 220
+#define TARGET_NR_getrlimit64 221
+#define TARGET_NR_pread64 222
+#define TARGET_NR_pwrite64 223
+#define TARGET_NR_creat64 224
+#define TARGET_NR_open64 225
+#define TARGET_NR_rpcsys 226
+#define TARGET_NR_zone 227 /* undefined in Solaris 7 */
+#define TARGET_NR_autofssys 228 /* undefined in Solaris 7 */
+#define TARGET_NR_getcwd 229
+#define TARGET_NR_so_socket 230
+#define TARGET_NR_so_socketpair 231
+#define TARGET_NR_bind 232
+#define TARGET_NR_listen 233
+#define TARGET_NR_accept 234
+#define TARGET_NR_connect 235
+#define TARGET_NR_shutdown 236
+#define TARGET_NR_recv 237
+#define TARGET_NR_recvfrom 238
+#define TARGET_NR_recvmsg 239
+#define TARGET_NR_send 240
+#define TARGET_NR_sendmsg 241
+#define TARGET_NR_sendto 242
+#define TARGET_NR_getpeername 243
+#define TARGET_NR_getsockname 244
+#define TARGET_NR_getsockopt 245
+#define TARGET_NR_setsockopt 246
+#define TARGET_NR_sockconfig 247
+/* NTP system calls */
+#define TARGET_NR_ntp_gettime 248
+#define TARGET_NR_ntp_adjtime 249
+#define TARGET_NR_lwp_mutex_unlock 250
+#define TARGET_NR_lwp_mutex_trylock 251
+#define TARGET_NR_lwp_mutex_register 252
+#define TARGET_NR_cladm 253
+#define TARGET_NR_uucopy 254 /* undefined in Solaris 7 */
+#define TARGET_NR_umount2 255 /* undefined in Solaris 7 */
+
+
+/* forksys(cmd) */
+#define TARGET_NR_forksys_forkx 0
+#define TARGET_NR_forksys_forkallx 1
+#define TARGET_NR_forksys_vforkx 2
+
+/* pgrpsys(cmd, ...) */
+#define TARGET_NR_pgrpsys_getpgrp 0
+#define TARGET_NR_pgrpsys_setpgrp 1
+#define TARGET_NR_pgrpsys_getsid 2
+#define TARGET_NR_pgrpsys_setsid 3
+#define TARGET_NR_pgrpsys_getpgid 4
+#define TARGET_NR_pgrpsys_setpgid 5
+
+/* sigpendingsys(cmd, ...) */
+#define TARGET_NR_sigpsys_sigpending 1
+#define TARGET_NR_sigpsys_sigfillset 2
+
+/* memcntl(..., ..., cmd, ...) */
+#define TARGET_NR_memcntl_msync 1
+#define TARGET_NR_memcntl_mlock 2
+#define TARGET_NR_memcntl_munlock 3
+#define TARGET_NR_memcntl_madvise 4
+#define TARGET_NR_memcntl_mlockall 5
+#define TARGET_NR_memcntl_munlockall 6
+#define TARGET_NR_memcntl_hatadvise 7
+
+/* context(cmd, ...) */
+#define TARGET_NR_context_getcontext 0
+#define TARGET_NR_context_setcontext 1
+
+/* fsat(cmd, ...) */
+#define TARGET_NR_fsat_openat 0
+#define TARGET_NR_fsat_openat64 1
+#define TARGET_NR_fsat_fstatat64 2
+#define TARGET_NR_fsat_fstatat 3
+#define TARGET_NR_fsat_renameat 4
+#define TARGET_NR_fsat_fchownat 5
+#define TARGET_NR_fsat_unlinkat 6
+#define TARGET_NR_fsat_futimesat 7
+
+/* msgsys(cmd, ...) */
+#define TARGET_NR_msgsys_msgget 0
+#define TARGET_NR_msgsys_msgctl 1
+#define TARGET_NR_msgsys_msgrcv 2
+#define TARGET_NR_msgsys_msgsnd 3
+#define TARGET_NR_msgsys_msgids 4
+#define TARGET_NR_msgsys_msgsnap 5
+
+/* shmsys(cmd, ...) */
+#define TARGET_NR_shmsys_shmat 0
+#define TARGET_NR_shmsys_shmctl 1
+#define TARGET_NR_shmsys_shmdt 2
+#define TARGET_NR_shmsys_shmget 3
+#define TARGET_NR_shmsys_shmids 4
+
+/* semsys(cmd, ...) */
+#define TARGET_NR_semsys_semctl 0
+#define TARGET_NR_semsys_semget 1
+#define TARGET_NR_semsys_semop 2
+#define TARGET_NR_semsys_semids 3
+#define TARGET_NR_semsys_semtimedop 4
+
+/* rusagesys(cmd, ...) */
+#define TARGET_NR_rusagesys_rusage 0
+#define TARGET_NR_rusagesys_rusagecld 1
+#define TARGET_NR_rusagesys_rusagelwp 2
+#define TARGET_NR_rusagesys_vmusage 3
+
+/* sysconfig(cmd) */
+#define TARGET_NR_sysconf_childmax 3
+#define TARGET_NR_sysconf_openmax 4
+#define TARGET_NR_sysconf_pagesize 6
+#define TARGET_NR_sysconf_clktick 7
+#define TARGET_NR_sysconf_nprocs 12
+#define TARGET_NR_sysconf_physmem 26
+#define TARGET_NR_sysconf_stckprot 43
+
+/* systnfosunos(cmd, ...) */
+#define TARGET_NR_sysinfo_gethostname 2
+#define TARGET_NR_sysinfo_sethostname 258
+#define TARGET_NR_sysinfo_getsrpcdomain 9
+#define TARGET_NR_sysinfo_setsrpcdomain 265
+#define TARGET_NR_sysinfo_sysname 1
+#define TARGET_NR_sysinfo_release 3
+#define TARGET_NR_sysinfo_version 4
+#define TARGET_NR_sysinfo_machine 5
+#define TARGET_NR_sysinfo_cpuarch 6
+#define TARGET_NR_sysinfo_hwserial 7
+#define TARGET_NR_sysinfo_hwproducer 8
+#define TARGET_NR_sysinfo_platform 513
+#define TARGET_NR_sysinfo_isalist 514
+#define TARGET_NR_sysinfo_arch32 516
+#define TARGET_NR_sysinfo_arch64 517
+#define TARGET_NR_sysinfo_archkern 518
+#define TARGET_NR_sysinfo_archnative 519
diff --git a/linux-user/solaris/target_cpu.h b/linux-user/solaris/target_cpu.h
new file mode 100644
index 0000000000..feab02e2cc
--- /dev/null
+++ b/linux-user/solaris/target_cpu.h
@@ -0,0 +1,44 @@
+/*
+ * SPARC specific CPU ABI and functions for linux-user
+ *
+ * Copyright (C) 2003 Thomas M. Ogrisegg
+ * Copyright (C) 2003-2005 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+#ifndef SOLARIS_TARGET_CPU_H
+#define SOLARIS_TARGET_CPU_H
+
+static inline void cpu_clone_regs(CPUSPARCState *env, target_ulong newsp)
+{
+ if (newsp) {
+ env->regwptr[22] = newsp;
+ }
+ /* syscall return for clone child: 0, and clear CF since
+ * this counts as a success return value.
+ */
+ env->regwptr[0] = 0;
+#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
+ env->xcc &= ~PSR_CARRY;
+#else
+ env->psr &= ~PSR_CARRY;
+#endif
+}
+
+static inline void cpu_set_tls(CPUSPARCState *env, target_ulong newtls)
+{
+ env->gregs[7] = newtls;
+}
+
+#endif
diff --git a/linux-user/solaris/target_elf.h b/linux-user/solaris/target_elf.h
new file mode 100644
index 0000000000..a510ceb612
--- /dev/null
+++ b/linux-user/solaris/target_elf.h
@@ -0,0 +1,18 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation, or (at your option) any
+ * later version. See the COPYING file in the top-level directory.
+ */
+
+#ifndef SPARC_TARGET_ELF_H
+#define SPARC_TARGET_ELF_H
+static inline const char *cpu_get_model(uint32_t eflags)
+{
+#ifdef TARGET_SPARC64
+ return "TI UltraSparc II";
+#else
+ return "Fujitsu MB86904";
+#endif
+}
+#endif
diff --git a/linux-user/solaris/target_signal.h b/linux-user/solaris/target_signal.h
new file mode 100644
index 0000000000..425a0e7684
--- /dev/null
+++ b/linux-user/solaris/target_signal.h
@@ -0,0 +1,91 @@
+#ifndef SOLARIS_TARGET_SIGNAL_H
+#define SOLARIS_TARGET_SIGNAL_H
+
+#include "cpu.h"
+
+/* this struct defines a stack used during syscall handling */
+
+typedef struct target_sigaltstack {
+ abi_ulong ss_sp;
+ abi_ulong ss_size;
+ abi_long ss_flags;
+} target_stack_t;
+
+
+/*
+ * sigaltstack controls
+ */
+#define TARGET_SS_ONSTACK 1
+#define TARGET_SS_DISABLE 2
+
+#define TARGET_MINSIGSTKSZ 4096
+#define TARGET_SIGSTKSZ 16384
+
+#ifndef UREG_O6
+#define UREG_O6 6
+#endif
+#ifndef UREG_SP
+#define UREG_SP UREG_O6
+#endif
+
+static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
+{
+ return state->regwptr[UREG_SP];
+}
+
+struct target_mcontext32 {
+ uint32_t gregs[19];
+ uint32_t gwins;
+ union {
+ double dregs[16];
+ float fregs[32];
+ };
+ uint32_t fqu; /* ptr to array of FQ entries */
+ uint32_t fpfsr; /* FPU status register */
+ uint8_t fpqcnt; /* # of entries in saved FQ */
+ uint8_t fpqesz; /* # of bytes per FQ entry */
+ uint8_t fpen; /* flag signifying fpu in use */
+ uint32_t pad1;
+ uint32_t xrsid;
+ uint32_t xrsptr;
+ uint32_t pad[19];
+};
+
+struct target_mcontext64 {
+ uint64_t gregs[21];
+ uint32_t gwins;
+ union {
+ double dregs[16];
+ float fregs[32];
+ };
+ uint32_t fqu; /* ptr to array of FQ entries */
+ uint32_t fpfsr; /* FPU status register */
+ uint8_t fpqcnt; /* # of entries in saved FQ */
+ uint8_t fpqesz; /* # of bytes per FQ entry */
+ uint8_t fpen; /* flag signifying fpu in use */
+ uint32_t pad1;
+ uint32_t xrsid;
+ uint32_t xrsptr;
+ uint32_t pad[19];
+};
+
+struct target_mcontext {
+ union {
+ struct target_mcontext32 _32;
+ struct target_mcontext64 _64;
+ };
+};
+
+struct target_ucontext {
+ abi_ulong tuc_flags;
+ abi_ulong tuc_link;
+ target_sigset_t tuc_sigmask;
+ struct target_sigaltstack tuc_stack;
+ int pad;
+ struct target_mcontext tuc_mcontext;
+};
+
+int save_context(CPUSPARCState *regs, struct target_mcontext *sc, int setret);
+int restore_context(CPUSPARCState *regs, struct target_mcontext *sc);
+
+#endif /* TARGET_SIGNAL_H */
diff --git a/linux-user/solaris/target_structs.h b/linux-user/solaris/target_structs.h
new file mode 100644
index 0000000000..17aa60b480
--- /dev/null
+++ b/linux-user/solaris/target_structs.h
@@ -0,0 +1,63 @@
+/*
+ * SPARC specific structures for linux-user
+ *
+ * Copyright (c) 2013 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+#ifndef SOLARIS_TARGET_STRUCTS_H
+#define SOLARIS_TARGET_STRUCTS_H
+
+struct target_ipc_perm {
+ abi_int __key; /* Key. */
+ abi_uint uid; /* Owner's user ID. */
+ abi_uint gid; /* Owner's group ID. */
+ abi_uint cuid; /* Creator's user ID. */
+ abi_uint cgid; /* Creator's group ID. */
+#if TARGET_ABI_BITS == 32
+ abi_ushort __pad1;
+ abi_ushort mode; /* Read/write permission. */
+ abi_ushort __pad2;
+#else
+ abi_ushort mode;
+ abi_ushort __pad1;
+#endif
+ abi_ushort __seq; /* Sequence number. */
+ uint64_t __unused1;
+ uint64_t __unused2;
+};
+
+struct target_shmid_ds {
+ struct target_ipc_perm shm_perm; /* operation permission struct */
+#if TARGET_ABI_BITS == 32
+ abi_uint __pad1;
+#endif
+ abi_ulong shm_atime; /* time of last shmat() */
+#if TARGET_ABI_BITS == 32
+ abi_uint __pad2;
+#endif
+ abi_ulong shm_dtime; /* time of last shmdt() */
+#if TARGET_ABI_BITS == 32
+ abi_uint __pad3;
+#endif
+ abi_ulong shm_ctime; /* time of last change by shmctl() */
+ abi_long shm_segsz; /* size of segment in bytes */
+ abi_ulong shm_cpid; /* pid of creator */
+ abi_ulong shm_lpid; /* pid of last shmop */
+ abi_long shm_nattch; /* number of current attaches */
+ abi_ulong __unused1;
+ abi_ulong __unused2;
+};
+
+#endif
diff --git a/linux-user/solaris/target_syscall.h b/linux-user/solaris/target_syscall.h
new file mode 100644
index 0000000000..e4d485867c
--- /dev/null
+++ b/linux-user/solaris/target_syscall.h
@@ -0,0 +1,24 @@
+#ifndef SOLARIS_TARGET_SYSCALL_H
+#define SOLARIS_TARGET_SYSCALL_H
+
+struct target_pt_regs {
+ abi_ulong psr;
+ abi_ulong pc;
+ abi_ulong npc;
+ abi_ulong y;
+ abi_ulong u_regs[16];
+};
+
+#define UNAME_MACHINE "sun4"
+#define UNAME_MINIMUM_RELEASE "2.6.32"
+
+/* SPARC kernels don't define this in their Kconfig, but they have the
+ * same ABI as if they did, implemented by sparc-specific code which fishes
+ * directly in the u_regs() struct for half the parameters in sparc_do_fork()
+ * and copy_thread().
+ */
+#define TARGET_MINSIGSTKSZ 4096
+#define TARGET_MLOCKALL_MCL_CURRENT 0x1
+#define TARGET_MLOCKALL_MCL_FUTURE 0x2
+
+#endif
diff --git a/linux-user/solaris/termbits.h b/linux-user/solaris/termbits.h
new file mode 100644
index 0000000000..24ea54e157
--- /dev/null
+++ b/linux-user/solaris/termbits.h
@@ -0,0 +1,280 @@
+/* from asm/termbits.h */
+
+#define TARGET_NCCS 19
+
+struct target_termios {
+ unsigned int c_iflag; /* input mode flags */
+ unsigned int c_oflag; /* output mode flags */
+ unsigned int c_cflag; /* control mode flags */
+ unsigned int c_lflag; /* local mode flags */
+ unsigned char c_cc[TARGET_NCCS]; /* control characters */
+};
+
+/* c_cc characters */
+#define TARGET_VINTR 0
+#define TARGET_VQUIT 1
+#define TARGET_VERASE 2
+#define TARGET_VKILL 3
+#define TARGET_VEOF 4
+#define TARGET_VEOL 5
+#define TARGET_VEOL2 6
+#define TARGET_VSWTC 7
+#define TARGET_VSTART 8
+#define TARGET_VSTOP 9
+
+#define TARGET_VSUSP 10
+#define TARGET_VDSUSP 11 /* SunOS POSIX nicety I do believe... */
+#define TARGET_VREPRINT 12
+#define TARGET_VDISCARD 13
+#define TARGET_VWERASE 14
+#define TARGET_VLNEXT 15
+
+/* Kernel keeps vmin/vtime separated, user apps assume vmin/vtime is
+ * shared with eof/eol
+ */
+#define TARGET_VMIN TARGET_VEOF
+#define TARGET_VTIME TARGET_VEOL
+
+/* c_iflag bits */
+#define TARGET_IGNBRK 0x00000001
+#define TARGET_BRKINT 0x00000002
+#define TARGET_IGNPAR 0x00000004
+#define TARGET_PARMRK 0x00000008
+#define TARGET_INPCK 0x00000010
+#define TARGET_ISTRIP 0x00000020
+#define TARGET_INLCR 0x00000040
+#define TARGET_IGNCR 0x00000080
+#define TARGET_ICRNL 0x00000100
+#define TARGET_IUCLC 0x00000200
+#define TARGET_IXON 0x00000400
+#define TARGET_IXANY 0x00000800
+#define TARGET_IXOFF 0x00001000
+#define TARGET_IMAXBEL 0x00002000
+#define TARGET_IUTF8 0x00004000
+
+/* c_oflag bits */
+#define TARGET_OPOST 0x00000001
+#define TARGET_OLCUC 0x00000002
+#define TARGET_ONLCR 0x00000004
+#define TARGET_OCRNL 0x00000008
+#define TARGET_ONOCR 0x00000010
+#define TARGET_ONLRET 0x00000020
+#define TARGET_OFILL 0x00000040
+#define TARGET_OFDEL 0x00000080
+#define TARGET_NLDLY 0x00000100
+#define TARGET_NL0 0x00000000
+#define TARGET_NL1 0x00000100
+#define TARGET_CRDLY 0x00000600
+#define TARGET_CR0 0x00000000
+#define TARGET_CR1 0x00000200
+#define TARGET_CR2 0x00000400
+#define TARGET_CR3 0x00000600
+#define TARGET_TABDLY 0x00001800
+#define TARGET_TAB0 0x00000000
+#define TARGET_TAB1 0x00000800
+#define TARGET_TAB2 0x00001000
+#define TARGET_TAB3 0x00001800
+#define TARGET_XTABS 0x00001800
+#define TARGET_BSDLY 0x00002000
+#define TARGET_BS0 0x00000000
+#define TARGET_BS1 0x00002000
+#define TARGET_VTDLY 0x00004000
+#define TARGET_VT0 0x00000000
+#define TARGET_VT1 0x00004000
+#define TARGET_FFDLY 0x00008000
+#define TARGET_FF0 0x00000000
+#define TARGET_FF1 0x00008000
+#define TARGET_PAGEOUT 0x00010000 /* SUNOS specific */
+#define TARGET_WRAP 0x00020000 /* SUNOS specific */
+
+/* c_cflag bit meaning */
+#define TARGET_CBAUD 0x0020000f
+#define TARGET_B0 0x00000000 /* hang up */
+#define TARGET_B50 0x00000001
+#define TARGET_B75 0x00000002
+#define TARGET_B110 0x00000003
+#define TARGET_B134 0x00000004
+#define TARGET_B150 0x00000005
+#define TARGET_B200 0x00000006
+#define TARGET_B300 0x00000007
+#define TARGET_B600 0x00000008
+#define TARGET_B1200 0x00000009
+#define TARGET_B1800 0x0000000a
+#define TARGET_B2400 0x0000000b
+#define TARGET_B4800 0x0000000c
+#define TARGET_B9600 0x0000000d
+#define TARGET_B19200 0x0000000e
+#define TARGET_B38400 0x0000000f
+#define TARGET_EXTA B19200
+#define TARGET_EXTB B38400
+#define TARGET_CSIZE 0x00000030
+#define TARGET_CS5 0x00000000
+#define TARGET_CS6 0x00000010
+#define TARGET_CS7 0x00000020
+#define TARGET_CS8 0x00000030
+#define TARGET_CSTOPB 0x00000040
+#define TARGET_CREAD 0x00000080
+#define TARGET_PARENB 0x00000100
+#define TARGET_PARODD 0x00000200
+#define TARGET_HUPCL 0x00000400
+#define TARGET_CLOCAL 0x00000800
+#define TARGET_CBAUDEX 0x00200000
+/* We'll never see these speeds with the Zilogs, but for completeness... */
+#define TARGET_B57600 (TARGET_CBAUDEX+1)
+#define TARGET_B115200 (TARGET_CBAUDEX+2)
+#define TARGET_B230400 (TARGET_CBAUDEX+3)
+#define TARGET_B460800 (TARGET_CBAUDEX+4)
+/* This is what we can do with the Zilogs. */
+#define TARGET_B76800 (TARGET_CBAUDEX+5)
+/* This is what we can do with the SAB82532. */
+#define TARGET_B153600 (TARGET_CBAUDEX+6)
+#define TARGET_B307200 (TARGET_CBAUDEX+7)
+#define TARGET_B614400 (TARGET_CBAUDEX+8)
+#define TARGET_B921600 (TARGET_CBAUDEX+9)
+/* And these are the rest... */
+#define TARGET_B500000 (TARGET_CBAUDEX+10)
+#define TARGET_B576000 (TARGET_CBAUDEX+11)
+#define TARGET_B1000000 (TARGET_CBAUDEX+12)
+#define TARGET_B1152000 (TARGET_CBAUDEX+13)
+#define TARGET_B1500000 (TARGET_CBAUDEX+14)
+#define TARGET_B2000000 (TARGET_CBAUDEX+15)
+/* These have totally bogus values and nobody uses them
+ so far. Later on we'd have to use say 0x10000x and
+ adjust CBAUD constant and drivers accordingly.
+#define B2500000 0x00001010
+#define B3000000 0x00001011
+#define B3500000 0x00001012
+#define B4000000 0x00001013 */
+#define TARGET_CIBAUD 0x004f0000 /* input baud rate (not used) */
+#define TARGET_CMSPAR 0x40000000 /* mark or space (stick) parity */
+#define TARGET_CRTSCTS 0x80000000 /* flow control */
+
+/* c_lflag bits */
+#define TARGET_ISIG 0x00000001
+#define TARGET_ICANON 0x00000002
+#define TARGET_XCASE 0x00000004
+#define TARGET_ECHO 0x00000008
+#define TARGET_ECHOE 0x00000010
+#define TARGET_ECHOK 0x00000020
+#define TARGET_ECHONL 0x00000040
+#define TARGET_NOFLSH 0x00000080
+#define TARGET_TOSTOP 0x00000100
+#define TARGET_ECHOCTL 0x00000200
+#define TARGET_ECHOPRT 0x00000400
+#define TARGET_ECHOKE 0x00000800
+#define TARGET_DEFECHO 0x00001000 /* SUNOS thing, what is it? */
+#define TARGET_FLUSHO 0x00002000
+#define TARGET_PENDIN 0x00004000
+#define TARGET_IEXTEN 0x00008000
+
+/* ioctls */
+#define TARGET_IO_(t,n) (((t)<<8)|(n))
+
+/* Big T */
+#define TARGET_TCGETA TARGET_IO_('T', 1)
+#define TARGET_TCSETA TARGET_IO_('T', 2)
+#define TARGET_TCSETAW TARGET_IO_('T', 3)
+#define TARGET_TCSETAF TARGET_IO_('T', 4)
+#define TARGET_TCSBRK TARGET_IO_('T', 5)
+#define TARGET_TCXONC TARGET_IO_('T', 6)
+#define TARGET_TCFLSH TARGET_IO_('T', 7)
+#define TARGET_TCGETS TARGET_IO_('T', 13)
+#define TARGET_TCSETS TARGET_IO_('T', 14)
+#define TARGET_TCSETSW TARGET_IO_('T', 15)
+#define TARGET_TCSETSF TARGET_IO_('T', 16)
+
+#define TARGET_TIOCGSOFTCAR TARGET_IO_('T', 105)
+#define TARGET_TIOCSSOFTCAR TARGET_IO_('T', 106)
+//#define __TIOCUCNTL _IOCTL('T', 102) /* SunOS Specific */
+#define TARGET_TIOCSWINSZ TARGET_IO_('T', 103)
+#define TARGET_TIOCGWINSZ TARGET_IO_('T', 104)
+
+//#define __TIOCREMOTE _IOCTL('t', 30) /* SunOS Specific */
+/* Note that all the ioctls that are not available in Linux have a
+ * double underscore on the front to: a) avoid some programs to
+ * thing we support some ioctls under Linux (autoconfiguration stuff)
+ */
+/* Little t */
+#define TARGET_TIOCGETD TARGET_IO_('t', 0)
+#define TARGET_TIOCSETD TARGET_IO_('t', 1)
+//#define __TIOCHPCL _IOCTL('t') /* SunOS Specific */
+//#define __TIOCMODG _IOCTL('t', 3) /* SunOS Specific */
+//#define __TIOCMODS _IOCTL('t', 4) /* SunOS Specific */
+//#define __TIOCGETP _IOCTL('t', 8) /* SunOS Specific */
+//#define __TIOCSETP _IOCTL('t', 9) /* SunOS Specific */
+//#define __TIOCSETN _IOCTL('t', 10) /* SunOS Specific */
+#define TARGET_TIOCEXCL TARGET_IO_('t', 13)
+#define TARGET_TIOCNXCL TARGET_IO_('t', 14)
+//#define __TIOCFLUSH _IOCTL('t', 16) /* SunOS Specific */
+//#define __TIOCSETC _IOCTL('t', 17) /* SunOS Specific */
+//#define __TIOCGETC _IOCTL('t', 18) /* SunOS Specific */
+//#define __TIOCTCNTL _IOCTL('t', 32) /* SunOS Specific */
+//#define __TIOCSIGNAL _IOCTL('t', 31) /* SunOS Specific */
+//#define __TIOCSETX _IOCTL('t', 34) /* SunOS Specific */
+//#define __TIOCGETX _IOCTL('t', 35) /* SunOS Specific */
+#define TARGET_TIOCCONS TARGET_IO_('t', 36)
+//#define __TIOCSSIZE _IOCTL('t', 37) /* SunOS Specific */
+//#define __TIOCGSIZE _IOCTL('t', 38) /* SunOS Specific */
+#define TARGET_TIOCMGET TARGET_IO_('t', 29)
+#define TARGET_TIOCMBIC TARGET_IO_('t', 28)
+#define TARGET_TIOCMBIS TARGET_IO_('t', 27)
+#define TARGET_TIOCMSET TARGET_IO_('t', 26)
+#define TARGET_TIOCSTART TARGET_IO_('t', 110)
+#define TARGET_TIOCSTOP TARGET_IO_('t', 111)
+#define TARGET_TIOCPKT TARGET_IO_('t', 112)
+#define TARGET_TIOCNOTTY TARGET_IO_('t', 113)
+#define TARGET_TIOCSTI TARGET_IO_('t', 23)
+#define TARGET_TIOCOUTQ TARGET_IO_('t', 115)
+//#define __TIOCGLTC _IOCTL('t', 116) /* SunOS Specific */
+//#define __TIOCSLTC _IOCTL('t', 117) /* SunOS Specific */
+/* 118 is the non-posix setpgrp tty ioctl */
+/* 119 is the non-posix getpgrp tty ioctl */
+//#define __TIOCCDTR TARGET_IO_('t', 120) /* SunOS Specific */
+//#define __TIOCSDTR TARGET_IO_('t', 121) /* SunOS Specific */
+#define TARGET_TIOCCBRK TARGET_IO_('t', 122)
+#define TARGET_TIOCSBRK TARGET_IO_('t', 123)
+//#define __TIOCLGET TARGET_IO_('t', 124) /* SunOS Specific */
+//#define __TIOCLSET TARGET_IO_('t', 125) /* SunOS Specific */
+//#define __TIOCLBIC TARGET_IO_('t', 126) /* SunOS Specific */
+//#define __TIOCLBIS TARGET_IO_('t', 127) /* SunOS Specific */
+//#define __TIOCISPACE TARGET_IO_('t', 128) /* SunOS Specific */
+//#define __TIOCISIZE TARGET_IO_('t', 129) /* SunOS Specific */
+#define TARGET_TIOCSPGRP TARGET_IO_('t', 21)
+#define TARGET_TIOCGPGRP TARGET_IO_('t', 20)
+#define TARGET_TIOCSCTTY TARGET_IO_('t', 132)
+#define TARGET_TIOCGSID TARGET_IO_('t', 22)
+/* Get minor device of a pty master's FD -- Solaris equiv is ISPTM */
+#define TARGET_TIOCGPTN TARGET_IO_('t', 134) /* Get Pty Number */
+#define TARGET_TIOCSPTLCK TARGET_IO_('t', 135) /* Lock/unlock PTY */
+
+/* Little f */
+#define TARGET_FIOCLEX TARGET_IO('f', 1)
+#define TARGET_FIONCLEX TARGET_IO('f', 2)
+#define TARGET_FIOASYNC TARGET_IOW('f', 125, int)
+#define TARGET_FIONBIO TARGET_IOW('f', 126, int)
+#define TARGET_FIONREAD TARGET_IOR('f', 127, int)
+#define TARGET_TIOCINQ TARGET_FIONREAD
+
+/* SCARY Rutgers local SunOS kernel hackery, perhaps I will support it
+ * someday. This is completely bogus, I know...
+ */
+//#define __TCGETSTAT TARGET_IO('T', 200) /* Rutgers specific */
+//#define __TCSETSTAT TARGET_IO('T', 201) /* Rutgers specific */
+
+/* Linux specific, no SunOS equivalent. */
+#define TARGET_TIOCLINUX 0x541C
+#define TARGET_TIOCGSERIAL 0x541E
+#define TARGET_TIOCSSERIAL 0x541F
+#define TARGET_TCSBRKP 0x5425
+#define TARGET_TIOCTTYGSTRUCT 0x5426
+#define TARGET_TIOCSERCONFIG 0x5453
+#define TARGET_TIOCSERGWILD 0x5454
+#define TARGET_TIOCSERSWILD 0x5455
+#define TARGET_TIOCGLCKTRMIOS 0x5456
+#define TARGET_TIOCSLCKTRMIOS 0x5457
+#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */
+#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */
+#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */
+#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */
+#define TARGET_TIOCMIWAIT 0x545C /* Wait input */
+#define TARGET_TIOCGICOUNT 0x545D /* Read serial port inline interrupt counts */
diff --git a/linux-user/sparc/target_signal.h b/linux-user/sparc/target_signal.h
index e445e2b463..8bc27d982d 100644
--- a/linux-user/sparc/target_signal.h
+++ b/linux-user/sparc/target_signal.h
@@ -21,16 +21,16 @@ typedef struct target_sigaltstack {
#define TARGET_MINSIGSTKSZ 4096
#define TARGET_SIGSTKSZ 16384
-#ifndef UREG_I6
-#define UREG_I6 6
+#ifndef UREG_O6
+#define UREG_O6 6
#endif
-#ifndef UREG_FP
-#define UREG_FP UREG_I6
+#ifndef UREG_SP
+#define UREG_SP UREG_O6
#endif
static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
{
- return state->regwptr[UREG_FP];
+ return state->regwptr[UREG_SP];
}
diff --git a/linux-user/sparc64/target_signal.h b/linux-user/sparc64/target_signal.h
index 4449457baf..7be685dab8 100644
--- a/linux-user/sparc64/target_signal.h
+++ b/linux-user/sparc64/target_signal.h
@@ -21,16 +21,16 @@ typedef struct target_sigaltstack {
#define TARGET_MINSIGSTKSZ 4096
#define TARGET_SIGSTKSZ 16384
-#ifndef UREG_I6
-#define UREG_I6 6
+#ifndef UREG_O6
+#define UREG_O6 6
#endif
-#ifndef UREG_FP
-#define UREG_FP UREG_I6
+#ifndef UREG_SP
+#define UREG_SP UREG_O6
#endif
static inline abi_ulong get_sp_from_cpustate(CPUSPARCState *state)
{
- return state->regwptr[UREG_FP];
+ return state->regwptr[UREG_SP];
}
diff --git a/linux-user/strace.c b/linux-user/strace.c
index bd897a3f20..7fc7b2c6fc 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -5,6 +5,9 @@
#include
#include
#include
+#include
+#include
+#include
#include
#include
#include
@@ -73,6 +76,7 @@ UNUSED static void print_socket_protocol(int domain, int type, int protocol);
/*
* Utility functions
*/
+#if defined(TARGET_NR_semctl) || defined(TARGET_NR_ipc)
static void
print_ipc_cmd(int cmd)
{
@@ -120,6 +124,7 @@ if( cmd == val ) { \
/* Some value we don't recognize */
gemu_log("%d",cmd);
}
+#endif
static void
print_signal(abi_ulong arg, int last)
@@ -188,6 +193,7 @@ static void print_si_code(int arg)
gemu_log("%s", codename);
}
+#if defined(TARGET_NR_rt_sigqueueinfo) || defined(TARGET_NR_rt_tgsigqueueinfo)
static void get_target_siginfo(target_siginfo_t *tinfo,
const target_siginfo_t *info)
{
@@ -241,8 +247,10 @@ static void get_target_siginfo(target_siginfo_t *tinfo,
case TARGET_SIGCHLD:
__get_user(tinfo->_sifields._sigchld._pid,
&info->_sifields._sigchld._pid);
+#if !defined(TARGET_ABI_IRIX) && !defined(TARGET_ABI_SOLARIS)
__get_user(tinfo->_sifields._sigchld._uid,
&info->_sifields._sigchld._uid);
+#endif
__get_user(tinfo->_sifields._sigchld._status,
&info->_sifields._sigchld._status);
__get_user(tinfo->_sifields._sigchld._utime,
@@ -274,6 +282,7 @@ static void get_target_siginfo(target_siginfo_t *tinfo,
tinfo->si_code = deposit32(si_code, 16, 16, si_type);
}
+#endif
static void print_siginfo(const target_siginfo_t *tinfo)
{
@@ -303,8 +312,8 @@ static void print_siginfo(const target_siginfo_t *tinfo)
tinfo->_sifields._timer._timer2);
break;
case QEMU_SI_POLL:
- gemu_log(", si_band=%d, si_fd=%d",
- tinfo->_sifields._sigpoll._band,
+ gemu_log(", si_band = "TARGET_ABI_FMT_ld", si_fd = %d",
+ (abi_long)tinfo->_sifields._sigpoll._band,
tinfo->_sifields._sigpoll._fd);
break;
case QEMU_SI_FAULT:
@@ -312,14 +321,20 @@ static void print_siginfo(const target_siginfo_t *tinfo)
print_pointer(tinfo->_sifields._sigfault._addr, 1);
break;
case QEMU_SI_CHLD:
- gemu_log(", si_pid=%u, si_uid=%u, si_status=%d"
+ gemu_log(", si_pid = %u"
+#if !defined(TARGET_ABI_IRIX) && !defined(TARGET_ABI_SOLARIS)
+ ", si_uid = %u"
+#endif
+ ", si_status = %d"
", si_utime=" TARGET_ABI_FMT_ld
", si_stime=" TARGET_ABI_FMT_ld,
(unsigned int)(tinfo->_sifields._sigchld._pid),
+#if !defined(TARGET_ABI_IRIX) && !defined(TARGET_ABI_SOLARIS)
(unsigned int)(tinfo->_sifields._sigchld._uid),
+#endif
tinfo->_sifields._sigchld._status,
- tinfo->_sifields._sigchld._utime,
- tinfo->_sifields._sigchld._stime);
+ (abi_long)tinfo->_sifields._sigchld._utime,
+ (abi_long)tinfo->_sifields._sigchld._stime);
break;
case QEMU_SI_RT:
gemu_log(", si_pid=%u, si_uid=%u, si_sigval=" TARGET_ABI_FMT_ld,
@@ -451,17 +466,22 @@ print_socket_type(int type)
case TARGET_SOCK_SEQPACKET:
gemu_log("SOCK_SEQPACKET");
break;
+#ifdef TARGET_SOCK_PACKET
case TARGET_SOCK_PACKET:
gemu_log("SOCK_PACKET");
break;
+#endif
}
}
static void
print_socket_protocol(int domain, int type, int protocol)
{
- if (domain == AF_PACKET ||
- (domain == AF_INET && type == TARGET_SOCK_PACKET)) {
+ if (domain == AF_PACKET
+#ifdef TARGET_SOCK_PACKET
+ || (domain == AF_INET && type == TARGET_SOCK_PACKET)
+#endif
+ ) {
switch (protocol) {
case 0x0003:
gemu_log("ETH_P_ALL");
@@ -725,6 +745,7 @@ print_syscall_ret_newselect(const struct syscallname *name, abi_long ret)
}
#endif
+#ifdef TARGET_NR_adjtimex
/* special meanings of adjtimex()' non-negative return values */
#define TARGET_TIME_OK 0 /* clock synchronized, no leap second */
#define TARGET_TIME_INS 1 /* insert leap second */
@@ -770,6 +791,7 @@ print_syscall_ret_adjtimex(const struct syscallname *name, abi_long ret)
gemu_log("\n");
}
+#endif
UNUSED static struct flags access_flags[] = {
FLAG_GENERIC(F_OK),
@@ -1410,6 +1432,7 @@ print_fcntl(const struct syscallname *name,
gemu_log("F_SETOWN,");
print_raw_param(TARGET_ABI_FMT_ld, arg2, 0);
break;
+#ifdef TARGET_F_SETSIG
case TARGET_F_GETSIG:
gemu_log("F_GETSIG");
break;
@@ -1417,6 +1440,7 @@ print_fcntl(const struct syscallname *name,
gemu_log("F_SETSIG,");
print_raw_param(TARGET_ABI_FMT_ld, arg2, 0);
break;
+#endif
#if TARGET_ABI_BITS == 32
case TARGET_F_GETLK64:
gemu_log("F_GETLK64,");
@@ -1543,8 +1567,11 @@ print_socket(const struct syscallname *name,
gemu_log(",");
print_socket_type(type);
gemu_log(",");
- if (domain == AF_PACKET ||
- (domain == AF_INET && type == TARGET_SOCK_PACKET)) {
+ if (domain == AF_PACKET
+#ifdef TARGET_SOCK_PACKET
+ || (domain == AF_INET && type == TARGET_SOCK_PACKET)
+#endif
+ ) {
protocol = tswap16(protocol);
}
print_socket_protocol(domain, type, protocol);
@@ -1888,16 +1915,25 @@ print_socketcall(const struct syscallname *name,
}
#endif
-#if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) || \
- defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64)
+#if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) || defined(TARGET_NR_xstat) || \
+ defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) || defined(TARGET_NR_lxstat)
static void
print_stat(const struct syscallname *name,
abi_long arg0, abi_long arg1, abi_long arg2,
abi_long arg3, abi_long arg4, abi_long arg5)
{
print_syscall_prologue(name);
+#if defined(TARGET_NR_xstat) || defined(TARGET_NR_lxstat)
+ if (name->nr == TARGET_NR_xstat || name->nr == TARGET_NR_lxstat) {
+ print_raw_param("%d", arg0, 0);
+ print_string(arg1, 0);
+ print_pointer(arg2, 1);
+ } else
+#endif
+ {
print_string(arg0, 0);
print_pointer(arg1, 1);
+ }
print_syscall_epilogue(name);
}
#define print_lstat print_stat
@@ -1905,15 +1941,24 @@ print_stat(const struct syscallname *name,
#define print_lstat64 print_stat
#endif
-#if defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64)
+#if defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) || defined(TARGET_NR_fxstat)
static void
print_fstat(const struct syscallname *name,
abi_long arg0, abi_long arg1, abi_long arg2,
abi_long arg3, abi_long arg4, abi_long arg5)
{
print_syscall_prologue(name);
+#ifdef TARGET_NR_fxstat
+ if (name->nr == TARGET_NR_fxstat) {
+ print_raw_param("%d", arg0, 0);
+ print_raw_param("%d", arg1, 0);
+ print_pointer(arg2, 1);
+ } else
+#endif
+ {
print_raw_param("%d", arg0, 0);
print_pointer(arg1, 1);
+ }
print_syscall_epilogue(name);
}
#define print_fstat64 print_fstat
@@ -2605,7 +2650,7 @@ print_syscall(int num,
int i;
const char *format="%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ")";
- gemu_log("%d ", getpid() );
+ gemu_log("%ld ", syscall(SYS_gettid) );
for(i=0;i
#include
+#include
+#include
+#include
+#include
+#include
+#include
#include
#include
#include
@@ -44,6 +50,8 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
@@ -182,38 +190,38 @@
#undef _syscall6
#define _syscall0(type,name) \
-static type name (void) \
+static inline type name (void) \
{ \
return syscall(__NR_##name); \
}
#define _syscall1(type,name,type1,arg1) \
-static type name (type1 arg1) \
+static inline type name (type1 arg1) \
{ \
return syscall(__NR_##name, arg1); \
}
#define _syscall2(type,name,type1,arg1,type2,arg2) \
-static type name (type1 arg1,type2 arg2) \
+static inline type name (type1 arg1,type2 arg2) \
{ \
return syscall(__NR_##name, arg1, arg2); \
}
#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
-static type name (type1 arg1,type2 arg2,type3 arg3) \
+static inline type name (type1 arg1,type2 arg2,type3 arg3) \
{ \
return syscall(__NR_##name, arg1, arg2, arg3); \
}
#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
-static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
+static inline type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
{ \
return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
}
#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
type5,arg5) \
-static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
+static inline type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5)\
{ \
return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
}
@@ -221,7 +229,7 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
type5,arg5,type6,arg6) \
-static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
+static inline type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,\
type6 arg6) \
{ \
return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
@@ -270,34 +278,44 @@ _syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, co
_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
loff_t *, res, uint, wh);
#endif
+#ifdef TARGET_NR_rt_sigqueueinfo
_syscall3(int, sys_rt_sigqueueinfo, pid_t, pid, int, sig, siginfo_t *, uinfo)
_syscall4(int, sys_rt_tgsigqueueinfo, pid_t, pid, pid_t, tid, int, sig,
siginfo_t *, uinfo)
+#endif
+#ifdef TARGET_NR_syslog
_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
-#ifdef __NR_exit_group
+#endif
+#if defined __NR_exit_group && defined TARGET_NR_exit_group
_syscall1(int,exit_group,int,error_code)
#endif
#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
_syscall1(int,set_tid_address,int *,tidptr)
#endif
-#if defined(TARGET_NR_futex) && defined(__NR_futex)
+#if defined(__NR_futex)
_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
const struct timespec *,timeout,int *,uaddr2,int,val3)
#endif
+#ifdef TARGET_NR_sched_getaffinity
#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
unsigned long *, user_mask_ptr);
#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
unsigned long *, user_mask_ptr);
+#endif
#define __NR_sys_getcpu __NR_getcpu
_syscall3(int, sys_getcpu, unsigned *, cpu, unsigned *, node, void *, tcache);
+#ifdef TARGET_NR_reboot
_syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd,
void *, arg);
+#endif
+#ifdef TARGET_NR_capget
_syscall2(int, capget, struct __user_cap_header_struct *, header,
struct __user_cap_data_struct *, data);
_syscall2(int, capset, struct __user_cap_header_struct *, header,
struct __user_cap_data_struct *, data);
+#endif
#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
_syscall2(int, ioprio_get, int, which, int, who)
#endif
@@ -570,6 +588,7 @@ static void fd_trans_dup(int oldfd, int newfd)
}
}
+#ifdef TARGET_NR_getcwd
static int sys_getcwd1(char *buf, size_t size)
{
if (getcwd(buf, size) == NULL) {
@@ -578,6 +597,7 @@ static int sys_getcwd1(char *buf, size_t size)
}
return strlen(buf)+1;
}
+#endif
#ifdef TARGET_NR_utimensat
#if defined(__NR_utimensat)
@@ -756,7 +776,9 @@ static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
[ESRMNT] = TARGET_ESRMNT,
[ECOMM] = TARGET_ECOMM,
[EPROTO] = TARGET_EPROTO,
+#if defined EDOTDOT && defined TARGET_EDOTDOT
[EDOTDOT] = TARGET_EDOTDOT,
+#endif
[EMULTIHOP] = TARGET_EMULTIHOP,
[EBADMSG] = TARGET_EBADMSG,
[ENAMETOOLONG] = TARGET_ENAMETOOLONG,
@@ -801,7 +823,9 @@ static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
[ENAVAIL] = TARGET_ENAVAIL,
[EISNAM] = TARGET_EISNAM,
[EREMOTEIO] = TARGET_EREMOTEIO,
+#if defined EDQUOT && defined TARGET_EDQUOT
[EDQUOT] = TARGET_EDQUOT,
+#endif
[ESHUTDOWN] = TARGET_ESHUTDOWN,
[ETOOMANYREFS] = TARGET_ETOOMANYREFS,
[ETIMEDOUT] = TARGET_ETIMEDOUT,
@@ -812,33 +836,37 @@ static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
[EINPROGRESS] = TARGET_EINPROGRESS,
[ESTALE] = TARGET_ESTALE,
[ECANCELED] = TARGET_ECANCELED,
+#if defined ENOMEDIUM && defined TARGET_ENOMEDIUM
[ENOMEDIUM] = TARGET_ENOMEDIUM,
+#endif
+#if defined EMEDIUMTYPE && defined TARGET_EMEDIUMTYPE
[EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
-#ifdef ENOKEY
+#endif
+#if defined ENOKEY && defined TARGET_ENOKEY
[ENOKEY] = TARGET_ENOKEY,
#endif
-#ifdef EKEYEXPIRED
+#if defined EKEYEXPIRED && defined TARGET_EKEYEXPIRED
[EKEYEXPIRED] = TARGET_EKEYEXPIRED,
#endif
-#ifdef EKEYREVOKED
+#if defined EKEYREVOKED && defined TARGET_EKEYREVOKED
[EKEYREVOKED] = TARGET_EKEYREVOKED,
#endif
-#ifdef EKEYREJECTED
+#if defined EKEYREJECTED && defined TARGET_EKEYREJECTED
[EKEYREJECTED] = TARGET_EKEYREJECTED,
#endif
-#ifdef EOWNERDEAD
+#if defined EOWNERDEAD && defined TARGET_EOWNERDEAD
[EOWNERDEAD] = TARGET_EOWNERDEAD,
#endif
-#ifdef ENOTRECOVERABLE
+#if defined ENOTRECOVERABLE && defined TARGET_ENOTRECOVERABLE
[ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
#endif
#ifdef ENOMSG
[ENOMSG] = TARGET_ENOMSG,
#endif
-#ifdef ERKFILL
+#if defined ERKFILL && defined TARGET_ERFKILL
[ERFKILL] = TARGET_ERFKILL,
#endif
-#ifdef EHWPOISON
+#if defined EHWPOISON && defined TARGET_EHWPOISON
[EHWPOISON] = TARGET_EHWPOISON,
#endif
};
@@ -890,39 +918,39 @@ const char *target_strerror(int err)
}
#define safe_syscall0(type, name) \
-static type safe_##name(void) \
+static inline type safe_##name(void) \
{ \
return safe_syscall(__NR_##name); \
}
#define safe_syscall1(type, name, type1, arg1) \
-static type safe_##name(type1 arg1) \
+static inline type safe_##name(type1 arg1) \
{ \
return safe_syscall(__NR_##name, arg1); \
}
#define safe_syscall2(type, name, type1, arg1, type2, arg2) \
-static type safe_##name(type1 arg1, type2 arg2) \
+static inline type safe_##name(type1 arg1, type2 arg2) \
{ \
return safe_syscall(__NR_##name, arg1, arg2); \
}
#define safe_syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
-static type safe_##name(type1 arg1, type2 arg2, type3 arg3) \
+static inline type safe_##name(type1 arg1, type2 arg2, type3 arg3) \
{ \
return safe_syscall(__NR_##name, arg1, arg2, arg3); \
}
#define safe_syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
type4, arg4) \
-static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
+static inline type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
{ \
return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4); \
}
#define safe_syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
type4, arg4, type5, arg5) \
-static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+static inline type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
type5 arg5) \
{ \
return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
@@ -930,7 +958,7 @@ static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
#define safe_syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
type4, arg4, type5, arg5, type6, arg6) \
-static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
+static inline type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
type5 arg5, type6 arg6) \
{ \
return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
@@ -1170,12 +1198,18 @@ static inline abi_long copy_from_user_fdset(fd_set *fds,
int n)
{
int i, nw, j, k;
+#ifdef TARGET_ABI_IRIX
+ abi_uint b, *target_fds;
+ int bw = 8*sizeof(b);
+#else
abi_ulong b, *target_fds;
+ int bw = TARGET_ABI_BITS;
+#endif
- nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
+ nw = DIV_ROUND_UP(n, bw);
if (!(target_fds = lock_user(VERIFY_READ,
target_fds_addr,
- sizeof(abi_ulong) * nw,
+ sizeof(b) * nw,
1)))
return -TARGET_EFAULT;
@@ -1184,7 +1218,7 @@ static inline abi_long copy_from_user_fdset(fd_set *fds,
for (i = 0; i < nw; i++) {
/* grab the abi_ulong */
__get_user(b, &target_fds[i]);
- for (j = 0; j < TARGET_ABI_BITS; j++) {
+ for (j = 0; j < bw; j++) {
/* check the bit inside the abi_ulong */
if ((b >> j) & 1)
FD_SET(k, fds);
@@ -1217,19 +1251,25 @@ static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
{
int i, nw, j, k;
abi_long v;
- abi_ulong *target_fds;
+#ifdef TARGET_ABI_IRIX
+ abi_uint b, *target_fds;
+ int bw = 8*sizeof(b);
+#else
+ abi_ulong b, *target_fds;
+ int bw = TARGET_ABI_BITS;
+#endif
- nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
+ nw = DIV_ROUND_UP(n, bw);
if (!(target_fds = lock_user(VERIFY_WRITE,
target_fds_addr,
- sizeof(abi_ulong) * nw,
+ sizeof(b) * nw,
0)))
return -TARGET_EFAULT;
k = 0;
for (i = 0; i < nw; i++) {
v = 0;
- for (j = 0; j < TARGET_ABI_BITS; j++) {
+ for (j = 0; j < bw; j++) {
v |= ((abi_ulong)(FD_ISSET(k, fds) != 0) << j);
k++;
}
@@ -1263,24 +1303,24 @@ static inline abi_long host_to_target_rusage(abi_ulong target_addr,
if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
return -TARGET_EFAULT;
- target_rusage->ru_utime.tv_sec = tswapal(rusage->ru_utime.tv_sec);
- target_rusage->ru_utime.tv_usec = tswapal(rusage->ru_utime.tv_usec);
- target_rusage->ru_stime.tv_sec = tswapal(rusage->ru_stime.tv_sec);
- target_rusage->ru_stime.tv_usec = tswapal(rusage->ru_stime.tv_usec);
- target_rusage->ru_maxrss = tswapal(rusage->ru_maxrss);
- target_rusage->ru_ixrss = tswapal(rusage->ru_ixrss);
- target_rusage->ru_idrss = tswapal(rusage->ru_idrss);
- target_rusage->ru_isrss = tswapal(rusage->ru_isrss);
- target_rusage->ru_minflt = tswapal(rusage->ru_minflt);
- target_rusage->ru_majflt = tswapal(rusage->ru_majflt);
- target_rusage->ru_nswap = tswapal(rusage->ru_nswap);
- target_rusage->ru_inblock = tswapal(rusage->ru_inblock);
- target_rusage->ru_oublock = tswapal(rusage->ru_oublock);
- target_rusage->ru_msgsnd = tswapal(rusage->ru_msgsnd);
- target_rusage->ru_msgrcv = tswapal(rusage->ru_msgrcv);
- target_rusage->ru_nsignals = tswapal(rusage->ru_nsignals);
- target_rusage->ru_nvcsw = tswapal(rusage->ru_nvcsw);
- target_rusage->ru_nivcsw = tswapal(rusage->ru_nivcsw);
+ __put_user(rusage->ru_utime.tv_sec, &target_rusage->ru_utime.tv_sec);
+ __put_user(rusage->ru_utime.tv_usec, &target_rusage->ru_utime.tv_usec);
+ __put_user(rusage->ru_stime.tv_sec, &target_rusage->ru_stime.tv_sec);
+ __put_user(rusage->ru_stime.tv_usec, &target_rusage->ru_stime.tv_usec);
+ __put_user(rusage->ru_maxrss, &target_rusage->ru_maxrss);
+ __put_user(rusage->ru_ixrss, &target_rusage->ru_ixrss);
+ __put_user(rusage->ru_idrss, &target_rusage->ru_idrss);
+ __put_user(rusage->ru_isrss, &target_rusage->ru_isrss);
+ __put_user(rusage->ru_minflt, &target_rusage->ru_minflt);
+ __put_user(rusage->ru_majflt, &target_rusage->ru_majflt);
+ __put_user(rusage->ru_nswap, &target_rusage->ru_nswap);
+ __put_user(rusage->ru_inblock, &target_rusage->ru_inblock);
+ __put_user(rusage->ru_oublock, &target_rusage->ru_oublock);
+ __put_user(rusage->ru_msgsnd, &target_rusage->ru_msgsnd);
+ __put_user(rusage->ru_msgrcv, &target_rusage->ru_msgrcv);
+ __put_user(rusage->ru_nsignals, &target_rusage->ru_nsignals);
+ __put_user(rusage->ru_nvcsw, &target_rusage->ru_nvcsw);
+ __put_user(rusage->ru_nivcsw, &target_rusage->ru_nivcsw);
unlock_user_struct(target_rusage, target_addr, 1);
return 0;
@@ -1291,7 +1331,7 @@ static inline rlim_t target_to_host_rlim(abi_ulong target_rlim)
abi_ulong target_rlim_swap;
rlim_t result;
- target_rlim_swap = tswapal(target_rlim);
+ __get_user(target_rlim_swap, &target_rlim);
if (target_rlim_swap == TARGET_RLIM_INFINITY)
return RLIM_INFINITY;
@@ -1311,11 +1351,43 @@ static inline abi_ulong host_to_target_rlim(rlim_t rlim)
target_rlim_swap = TARGET_RLIM_INFINITY;
else
target_rlim_swap = rlim;
- result = tswapal(target_rlim_swap);
+ __put_user(target_rlim_swap, &result);
return result;
}
+#ifdef TARGET_NR_getrlimit64
+static inline rlim_t target_to_host_rlim64(uint64_t target_rlim)
+{
+ uint64_t target_rlim_swap;
+ rlim_t result;
+
+ __get_user(target_rlim_swap, &target_rlim);
+ if (target_rlim_swap == TARGET_RLIM64_INFINITY)
+ return RLIM_INFINITY;
+
+ result = target_rlim_swap;
+ if (target_rlim_swap != (rlim_t)result)
+ return RLIM_INFINITY;
+
+ return result;
+}
+
+static inline uint64_t host_to_target_rlim64(rlim_t rlim)
+{
+ uint64_t target_rlim_swap;
+ uint64_t result;
+
+ if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim)
+ target_rlim_swap = TARGET_RLIM64_INFINITY;
+ else
+ target_rlim_swap = rlim;
+ __put_user(target_rlim_swap, &result);
+
+ return result;
+}
+#endif
+
static inline int target_to_host_resource(int code)
{
switch (code) {
@@ -1354,6 +1426,56 @@ static inline int target_to_host_resource(int code)
}
}
+#if defined(TARGET_NR_pathconf) || defined(TARGET_ABI_IRIX)
+static inline int target_to_host_pathconf(int code)
+{
+ switch (code) {
+ case TARGET_PC_LINK_MAX:
+ return _PC_LINK_MAX;
+ case TARGET_PC_MAX_CANON:
+ return _PC_MAX_CANON;
+ case TARGET_PC_MAX_INPUT:
+ return _PC_MAX_INPUT;
+ case TARGET_PC_NAME_MAX:
+ return _PC_NAME_MAX;
+ case TARGET_PC_PATH_MAX:
+ return _PC_PATH_MAX;
+ case TARGET_PC_PIPE_BUF:
+ return _PC_PIPE_BUF;
+ case TARGET_PC_NO_TRUNC:
+ return _PC_NO_TRUNC;
+ case TARGET_PC_VDISABLE:
+ return _PC_VDISABLE;
+ case TARGET_PC_CHOWN_RESTRICTED:
+ return _PC_CHOWN_RESTRICTED;
+ case TARGET_PC_ASYNC_IO:
+ return _PC_ASYNC_IO;
+ case TARGET_PC_PRIO_IO:
+ return _PC_PRIO_IO;
+ case TARGET_PC_SYNC_IO:
+ return _PC_SYNC_IO;
+#ifndef TARGET_ABI_IRIX
+ case TARGET_PC_ALLOC_SIZE_MIN:
+ return _PC_ALLOC_SIZE_MIN;
+ case TARGET_PC_REC_INCR_XFER_SIZE:
+ return _PC_REC_INCR_XFER_SIZE;
+ case TARGET_PC_REC_MAX_XFER_SIZE:
+ return _PC_REC_MAX_XFER_SIZE;
+ case TARGET_PC_REC_MIN_XFER_SIZE:
+ return _PC_REC_MIN_XFER_SIZE;
+ case TARGET_PC_REC_XFER_ALIGN:
+ return _PC_REC_XFER_ALIGN;
+ case TARGET_PC_SYMLINK_MAX:
+ return _PC_SYMLINK_MAX;
+ case TARGET_PC_2_SYMLINKS:
+ return _PC_2_SYMLINKS;
+#endif
+ default:
+ return code;
+ }
+}
+#endif
+
static inline abi_long copy_from_user_timeval(struct timeval *tv,
abi_ulong target_tv_addr)
{
@@ -1491,6 +1613,7 @@ static abi_long do_select(int n,
if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
return -TARGET_EFAULT;
+#ifndef TARGET_ABI_IRIX
if (target_tv_addr) {
tv.tv_sec = ts.tv_sec;
tv.tv_usec = ts.tv_nsec / 1000;
@@ -1498,6 +1621,7 @@ static abi_long do_select(int n,
return -TARGET_EFAULT;
}
}
+#endif
}
return ret;
@@ -1514,11 +1638,11 @@ static abi_long do_old_select(abi_ulong arg1)
return -TARGET_EFAULT;
}
- nsel = tswapal(sel->n);
- inp = tswapal(sel->inp);
- outp = tswapal(sel->outp);
- exp = tswapal(sel->exp);
- tvp = tswapal(sel->tvp);
+ __get_user(nsel, &sel->n);
+ __get_user(inp, &sel->inp);
+ __get_user(outp, &sel->outp);
+ __get_user(exp, &sel->exp);
+ __get_user(tvp, &sel->tvp);
unlock_user_struct(sel, arg1, 0);
@@ -1582,7 +1706,7 @@ static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
if (len == sizeof(struct target_ip_mreqn))
- mreqn->imr_ifindex = tswapal(target_smreqn->imr_ifindex);
+ __get_user(mreqn->imr_ifindex, &target_smreqn->imr_ifindex);
unlock_user(target_smreqn, target_addr, 0);
return 0;
@@ -1604,7 +1728,7 @@ static inline abi_long target_to_host_sockaddr(int fd, struct sockaddr *addr,
if (!target_saddr)
return -TARGET_EFAULT;
- sa_family = tswap16(target_saddr->sa_family);
+ __get_user(sa_family, &target_saddr->sa_family);
/* Oops. The caller might send a incomplete sun_path; sun_path
* must be terminated by \0 (see the manual page), but
@@ -1631,14 +1755,14 @@ static inline abi_long target_to_host_sockaddr(int fd, struct sockaddr *addr,
struct sockaddr_nl *nladdr;
nladdr = (struct sockaddr_nl *)addr;
- nladdr->nl_pid = tswap32(nladdr->nl_pid);
- nladdr->nl_groups = tswap32(nladdr->nl_groups);
+ __get_user(nladdr->nl_pid, &nladdr->nl_pid);
+ __get_user(nladdr->nl_groups, &nladdr->nl_groups);
} else if (sa_family == AF_PACKET) {
struct target_sockaddr_ll *lladdr;
lladdr = (struct target_sockaddr_ll *)addr;
- lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex);
- lladdr->sll_hatype = tswap16(lladdr->sll_hatype);
+ __get_user(lladdr->sll_ifindex, &lladdr->sll_ifindex);
+ __get_user(lladdr->sll_hatype, &lladdr->sll_hatype);
}
unlock_user(target_saddr, target_addr, 0);
@@ -1662,21 +1786,21 @@ static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
memcpy(target_saddr, addr, len);
if (len >= offsetof(struct target_sockaddr, sa_family) +
sizeof(target_saddr->sa_family)) {
- target_saddr->sa_family = tswap16(addr->sa_family);
+ __put_user(addr->sa_family, &target_saddr->sa_family);
}
if (addr->sa_family == AF_NETLINK && len >= sizeof(struct sockaddr_nl)) {
struct sockaddr_nl *target_nl = (struct sockaddr_nl *)target_saddr;
- target_nl->nl_pid = tswap32(target_nl->nl_pid);
- target_nl->nl_groups = tswap32(target_nl->nl_groups);
+ __put_user(target_nl->nl_pid, &target_nl->nl_pid);
+ __put_user(target_nl->nl_groups, &target_nl->nl_groups);
} else if (addr->sa_family == AF_PACKET) {
struct sockaddr_ll *target_ll = (struct sockaddr_ll *)target_saddr;
- target_ll->sll_ifindex = tswap32(target_ll->sll_ifindex);
- target_ll->sll_hatype = tswap16(target_ll->sll_hatype);
+ __put_user(target_ll->sll_ifindex, &target_ll->sll_ifindex);
+ __put_user(target_ll->sll_hatype, &target_ll->sll_hatype);
} else if (addr->sa_family == AF_INET6 &&
len >= sizeof(struct target_sockaddr_in6)) {
struct target_sockaddr_in6 *target_in6 =
(struct target_sockaddr_in6 *)target_saddr;
- target_in6->sin6_scope_id = tswap16(target_in6->sin6_scope_id);
+ __put_user(target_in6->sin6_scope_id, &target_in6->sin6_scope_id);
}
unlock_user(target_saddr, target_addr, len);
@@ -1692,10 +1816,10 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
struct target_cmsghdr *target_cmsg, *target_cmsg_start;
socklen_t space = 0;
- msg_controllen = tswapal(target_msgh->msg_controllen);
- if (msg_controllen < sizeof (struct target_cmsghdr))
+ __get_user(msg_controllen, &target_msgh->msg_controllen);
+ if (msg_controllen < sizeof (struct target_cmsghdr))
goto the_end;
- target_cmsg_addr = tswapal(target_msgh->msg_control);
+ __get_user(target_cmsg_addr, &target_msgh->msg_control);
target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
target_cmsg_start = target_cmsg;
if (!target_cmsg)
@@ -1704,9 +1828,10 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
while (cmsg && target_cmsg) {
void *data = CMSG_DATA(cmsg);
void *target_data = TARGET_CMSG_DATA(target_cmsg);
+ int len, level;
- int len = tswapal(target_cmsg->cmsg_len)
- - sizeof(struct target_cmsghdr);
+ __get_user(len, &target_cmsg->cmsg_len);
+ len -= TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
space += CMSG_SPACE(len);
if (space > msgh->msg_controllen) {
@@ -1724,12 +1849,13 @@ static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
break;
}
- if (tswap32(target_cmsg->cmsg_level) == TARGET_SOL_SOCKET) {
+ __get_user(level, &target_cmsg->cmsg_level);
+ if (level == TARGET_SOL_SOCKET) {
cmsg->cmsg_level = SOL_SOCKET;
} else {
- cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
+ cmsg->cmsg_level = level;
}
- cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
+ __get_user(cmsg->cmsg_type, &target_cmsg->cmsg_type);
cmsg->cmsg_len = CMSG_LEN(len);
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
@@ -1774,10 +1900,10 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
struct target_cmsghdr *target_cmsg, *target_cmsg_start;
socklen_t space = 0;
- msg_controllen = tswapal(target_msgh->msg_controllen);
- if (msg_controllen < sizeof (struct target_cmsghdr))
+ __get_user(msg_controllen, &target_msgh->msg_controllen);
+ if (msg_controllen < sizeof (struct target_cmsghdr))
goto the_end;
- target_cmsg_addr = tswapal(target_msgh->msg_control);
+ __get_user(target_cmsg_addr, &target_msgh->msg_control);
target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
target_cmsg_start = target_cmsg;
if (!target_cmsg)
@@ -1802,11 +1928,11 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
}
if (cmsg->cmsg_level == SOL_SOCKET) {
- target_cmsg->cmsg_level = tswap32(TARGET_SOL_SOCKET);
+ __put_user(TARGET_SOL_SOCKET, &target_cmsg->cmsg_level);
} else {
- target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
+ __put_user(cmsg->cmsg_level, &target_cmsg->cmsg_level);
}
- target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
+ __put_user(cmsg->cmsg_type, &target_cmsg->cmsg_type);
/* Payload types which need a different size of payload on
* the target must adjust tgt_len here.
@@ -1979,7 +2105,8 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
}
}
- target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(tgt_len));
+ tgt_len = TARGET_CMSG_LEN(tgt_len);
+ __put_user(tgt_len, &target_cmsg->cmsg_len);
tgt_space = TARGET_CMSG_SPACE(tgt_len);
if (msg_controllen < tgt_space) {
tgt_space = msg_controllen;
@@ -1992,7 +2119,7 @@ static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
}
unlock_user(target_cmsg, target_cmsg_addr, space);
the_end:
- target_msgh->msg_controllen = tswapal(space);
+ __put_user(space, &target_msgh->msg_controllen);
return 0;
}
@@ -2859,7 +2986,6 @@ static abi_long target_to_host_data_audit(struct nlmsghdr *nlh)
nlh->nlmsg_type);
return -TARGET_EINVAL;
}
-
return 0;
}
@@ -2874,6 +3000,7 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
{
abi_long ret;
int val;
+ void *target_optval;
struct ip_mreqn *ip_mreq;
struct ip_mreq_source *ip_mreq_source;
@@ -3032,6 +3159,7 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
}
break;
case TARGET_SOL_SOCKET:
+ ret = 0;
switch (optname) {
case TARGET_SO_RCVTIMEO:
{
@@ -3125,6 +3253,10 @@ set_timeout:
case TARGET_SO_REUSEADDR:
optname = SO_REUSEADDR;
break;
+ case TARGET_SO_LINGER:
+ optname = SO_LINGER;
+ if (optlen < sizeof(struct linger)) ret = -TARGET_EINVAL;
+ break;
case TARGET_SO_TYPE:
optname = SO_TYPE;
break;
@@ -3184,9 +3316,10 @@ set_timeout:
if (optlen < sizeof(uint32_t))
return -TARGET_EINVAL;
- if (get_user_u32(val, optval_addr))
+ if (!(target_optval = lock_user(VERIFY_READ, optval_addr, optlen, 1)))
return -TARGET_EFAULT;
- ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
+ ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, target_optval, optlen));
+ unlock_user(target_optval, optval_addr, 0);
break;
default:
unimplemented:
@@ -3422,8 +3555,10 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
total_len = 0;
for (i = 0; i < count; i++) {
- abi_ulong base = tswapal(target_vec[i].iov_base);
- abi_long len = tswapal(target_vec[i].iov_len);
+ abi_ulong base;
+ abi_long len;
+ __get_user(base, &target_vec[i].iov_base);
+ __get_user(len, &target_vec[i].iov_len);
if (len < 0) {
err = EINVAL;
@@ -3461,8 +3596,10 @@ static struct iovec *lock_iovec(int type, abi_ulong target_addr,
fail:
while (--i >= 0) {
- if (tswapal(target_vec[i].iov_len) > 0) {
- unlock_user(vec[i].iov_base, tswapal(target_vec[i].iov_base), 0);
+ if (vec[i].iov_len > 0) {
+ abi_ulong base;
+ __get_user(base, &target_vec[i].iov_base);
+ unlock_user(vec[i].iov_base, base, 0);
}
}
unlock_user(target_vec, target_addr, 0);
@@ -3482,8 +3619,10 @@ static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
count * sizeof(struct target_iovec), 1);
if (target_vec) {
for (i = 0; i < count; i++) {
- abi_ulong base = tswapal(target_vec[i].iov_base);
- abi_long len = tswapal(target_vec[i].iov_len);
+ abi_ulong base;
+ abi_long len;
+ __get_user(base, &target_vec[i].iov_base);
+ __get_user(len, &target_vec[i].iov_len);
if (len < 0) {
break;
}
@@ -3557,7 +3696,7 @@ static abi_long packet_target_to_host_sockaddr(void *host_addr,
}
memcpy(addr, target_saddr, len);
- addr->sa_family = tswap16(target_saddr->sa_family);
+ __get_user(addr->sa_family, &target_saddr->sa_family);
/* spkt_protocol is big-endian */
unlock_user(target_saddr, target_addr, 0);
@@ -3733,7 +3872,7 @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
abi_ulong target_vec;
if (msgp->msg_name) {
- msg.msg_namelen = tswap32(msgp->msg_namelen);
+ __get_user(msg.msg_namelen, &msgp->msg_namelen);
msg.msg_name = alloca(msg.msg_namelen+1);
ret = target_to_host_sockaddr(fd, msg.msg_name,
tswapal(msgp->msg_name),
@@ -3752,12 +3891,12 @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
msg.msg_name = NULL;
msg.msg_namelen = 0;
}
- msg.msg_controllen = 2 * tswapal(msgp->msg_controllen);
+ __get_user(msg.msg_controllen, &msgp->msg_controllen);
msg.msg_control = alloca(msg.msg_controllen);
- msg.msg_flags = tswap32(msgp->msg_flags);
+ __get_user(msg.msg_flags, &msgp->msg_flags);
- count = tswapal(msgp->msg_iovlen);
- target_vec = tswapal(msgp->msg_iov);
+ __get_user(count, &msgp->msg_iovlen);
+ __get_user(target_vec, &msgp->msg_iov);
if (count > IOV_MAX) {
/* sendrcvmsg returns a different errno for this condition than
@@ -3806,7 +3945,7 @@ static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
ret = host_to_target_cmsg(msgp, &msg);
}
if (!is_error(ret)) {
- msgp->msg_namelen = tswap32(msg.msg_namelen);
+ __put_user(msg.msg_namelen, &msgp->msg_namelen);
if (msg.msg_name != NULL && msg.msg_name != (void *)-1) {
ret = host_to_target_sockaddr(tswapal(msgp->msg_name),
msg.msg_name, msg.msg_namelen);
@@ -3850,6 +3989,7 @@ static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
#define MSG_WAITFORONE 0x10000
#endif
+#if defined(TARGET_NR_socketcall) || defined(TARGET_NR_sendmmsg)
static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec,
unsigned int vlen, unsigned int flags,
int send)
@@ -3872,7 +4012,7 @@ static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec,
if (is_error(ret)) {
break;
}
- mmsgp[i].msg_len = tswap32(ret);
+ __put_user(ret, &mmsgp[i].msg_len);
/* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
if (flags & MSG_WAITFORONE) {
flags |= MSG_DONTWAIT;
@@ -3889,6 +4029,7 @@ static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec,
}
return ret;
}
+#endif
/* do_accept4() Must return target values and target errnos. */
static abi_long do_accept4(int fd, abi_ulong target_addr,
@@ -3985,6 +4126,7 @@ static abi_long do_getsockname(int fd, abi_ulong target_addr,
return ret;
}
+#ifndef TARGET_ABI_SOLARIS
/* do_socketpair() Must return target values and target errnos. */
static abi_long do_socketpair(int domain, int type, int protocol,
abi_ulong target_tab_addr)
@@ -4002,6 +4144,7 @@ static abi_long do_socketpair(int domain, int type, int protocol,
}
return ret;
}
+#endif
/* do_sendto() Must return target values and target errnos. */
static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
@@ -4224,20 +4367,20 @@ static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
return -TARGET_EFAULT;
target_ip = &(target_sd->sem_perm);
- host_ip->__key = tswap32(target_ip->__key);
- host_ip->uid = tswap32(target_ip->uid);
- host_ip->gid = tswap32(target_ip->gid);
- host_ip->cuid = tswap32(target_ip->cuid);
- host_ip->cgid = tswap32(target_ip->cgid);
+ __get_user(host_ip->__key, &target_ip->__key);
+ __get_user(host_ip->uid, &target_ip->uid);
+ __get_user(host_ip->gid, &target_ip->gid);
+ __get_user(host_ip->cuid, &target_ip->cuid);
+ __get_user(host_ip->cgid, &target_ip->cgid);
#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
- host_ip->mode = tswap32(target_ip->mode);
+ __get_user(host_ip->mode, &target_ip->mode);
#else
- host_ip->mode = tswap16(target_ip->mode);
+ __get_user(host_ip->mode, &target_ip->mode);
#endif
#if defined(TARGET_PPC)
- host_ip->__seq = tswap32(target_ip->__seq);
+ __get_user(host_ip->__seq, &target_ip->__seq);
#else
- host_ip->__seq = tswap16(target_ip->__seq);
+ __get_user(host_ip->__seq, &target_ip->__seq);
#endif
unlock_user_struct(target_sd, target_addr, 0);
return 0;
@@ -4252,20 +4395,20 @@ static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
return -TARGET_EFAULT;
target_ip = &(target_sd->sem_perm);
- target_ip->__key = tswap32(host_ip->__key);
- target_ip->uid = tswap32(host_ip->uid);
- target_ip->gid = tswap32(host_ip->gid);
- target_ip->cuid = tswap32(host_ip->cuid);
- target_ip->cgid = tswap32(host_ip->cgid);
+ __put_user(host_ip->__key, &target_ip->__key);
+ __put_user(host_ip->uid, &target_ip->uid);
+ __put_user(host_ip->gid, &target_ip->gid);
+ __put_user(host_ip->cuid, &target_ip->cuid);
+ __put_user(host_ip->cgid, &target_ip->cgid);
#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
- target_ip->mode = tswap32(host_ip->mode);
+ __put_user(host_ip->mode, &target_ip->mode);
#else
- target_ip->mode = tswap16(host_ip->mode);
+ __put_user(host_ip->mode, &target_ip->mode);
#endif
#if defined(TARGET_PPC)
- target_ip->__seq = tswap32(host_ip->__seq);
+ __put_user(host_ip->__seq, &target_ip->__seq);
#else
- target_ip->__seq = tswap16(host_ip->__seq);
+ __put_user(host_ip->__seq, &target_ip->__seq);
#endif
unlock_user_struct(target_sd, target_addr, 1);
return 0;
@@ -4280,9 +4423,9 @@ static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
return -TARGET_EFAULT;
if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
return -TARGET_EFAULT;
- host_sd->sem_nsems = tswapal(target_sd->sem_nsems);
- host_sd->sem_otime = tswapal(target_sd->sem_otime);
- host_sd->sem_ctime = tswapal(target_sd->sem_ctime);
+ __get_user(host_sd->sem_nsems, &target_sd->sem_nsems);
+ __get_user(host_sd->sem_otime, &target_sd->sem_otime);
+ __get_user(host_sd->sem_ctime, &target_sd->sem_ctime);
unlock_user_struct(target_sd, target_addr, 0);
return 0;
}
@@ -4296,9 +4439,9 @@ static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
return -TARGET_EFAULT;
if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
return -TARGET_EFAULT;
- target_sd->sem_nsems = tswapal(host_sd->sem_nsems);
- target_sd->sem_otime = tswapal(host_sd->sem_otime);
- target_sd->sem_ctime = tswapal(host_sd->sem_ctime);
+ __put_user(host_sd->sem_nsems, &target_sd->sem_nsems);
+ __put_user(host_sd->sem_otime, &target_sd->sem_otime);
+ __put_user(host_sd->sem_ctime, &target_sd->sem_ctime);
unlock_user_struct(target_sd, target_addr, 1);
return 0;
}
@@ -4345,9 +4488,15 @@ union semun {
union target_semun {
int val;
+#ifdef TARGET_ABI32
+ abi_uint buf;
+ abi_uint array;
+ abi_uint __buf;
+#else
abi_ulong buf;
abi_ulong array;
abi_ulong __buf;
+#endif
};
static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
@@ -4559,14 +4708,14 @@ static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
return -TARGET_EFAULT;
if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
return -TARGET_EFAULT;
- host_md->msg_stime = tswapal(target_md->msg_stime);
- host_md->msg_rtime = tswapal(target_md->msg_rtime);
- host_md->msg_ctime = tswapal(target_md->msg_ctime);
- host_md->__msg_cbytes = tswapal(target_md->__msg_cbytes);
- host_md->msg_qnum = tswapal(target_md->msg_qnum);
- host_md->msg_qbytes = tswapal(target_md->msg_qbytes);
- host_md->msg_lspid = tswapal(target_md->msg_lspid);
- host_md->msg_lrpid = tswapal(target_md->msg_lrpid);
+ __get_user(host_md->msg_stime, &target_md->msg_stime);
+ __get_user(host_md->msg_rtime, &target_md->msg_rtime);
+ __get_user(host_md->msg_ctime, &target_md->msg_ctime);
+ __get_user(host_md->__msg_cbytes, &target_md->__msg_cbytes);
+ __get_user(host_md->msg_qnum, &target_md->msg_qnum);
+ __get_user(host_md->msg_qbytes, &target_md->msg_qbytes);
+ __get_user(host_md->msg_lspid, &target_md->msg_lspid);
+ __get_user(host_md->msg_lrpid, &target_md->msg_lrpid);
unlock_user_struct(target_md, target_addr, 0);
return 0;
}
@@ -4580,14 +4729,14 @@ static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
return -TARGET_EFAULT;
if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
return -TARGET_EFAULT;
- target_md->msg_stime = tswapal(host_md->msg_stime);
- target_md->msg_rtime = tswapal(host_md->msg_rtime);
- target_md->msg_ctime = tswapal(host_md->msg_ctime);
- target_md->__msg_cbytes = tswapal(host_md->__msg_cbytes);
- target_md->msg_qnum = tswapal(host_md->msg_qnum);
- target_md->msg_qbytes = tswapal(host_md->msg_qbytes);
- target_md->msg_lspid = tswapal(host_md->msg_lspid);
- target_md->msg_lrpid = tswapal(host_md->msg_lrpid);
+ __put_user(host_md->msg_stime, &target_md->msg_stime);
+ __put_user(host_md->msg_rtime, &target_md->msg_rtime);
+ __put_user(host_md->msg_ctime, &target_md->msg_ctime);
+ __put_user(host_md->__msg_cbytes, &target_md->__msg_cbytes);
+ __put_user(host_md->msg_qnum, &target_md->msg_qnum);
+ __put_user(host_md->msg_qbytes, &target_md->msg_qbytes);
+ __put_user(host_md->msg_lspid, &target_md->msg_lspid);
+ __put_user(host_md->msg_lrpid, &target_md->msg_lrpid);
unlock_user_struct(target_md, target_addr, 1);
return 0;
}
@@ -4676,7 +4825,7 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp,
unlock_user_struct(target_mb, msgp, 0);
return -TARGET_ENOMEM;
}
- host_mb->mtype = (abi_long) tswapal(target_mb->mtype);
+ __get_user(host_mb->mtype, &target_mb->mtype);
memcpy(host_mb->mtext, target_mb->mtext, msgsz);
ret = get_errno(safe_msgsnd(msqid, host_mb, msgsz, msgflg));
g_free(host_mb);
@@ -4719,7 +4868,7 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp,
unlock_user(target_mtext, target_mtext_addr, ret);
}
- target_mb->mtype = tswapal(host_mb->mtype);
+ __put_user(host_mb->mtype, &target_mb->mtype);
end:
if (target_mb)
@@ -5100,7 +5249,7 @@ struct IOCTLEntry {
#define MAX_STRUCT_SIZE 4096
-#ifdef CONFIG_FIEMAP
+#if defined(CONFIG_FIEMAP) && !defined(TARGET_ABI_IRIX) && !defined(TARGET_ABI_SOLARIS)
/* So fiemap access checks don't overflow on 32 bit systems.
* This is very slightly smaller than the limit imposed by
* the underlying kernel.
@@ -5283,6 +5432,7 @@ static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
return ret;
}
+#if !defined TARGET_ABI_IRIX && !defined TARGET_ABI_SOLARIS
static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
int cmd, abi_long arg)
{
@@ -5635,6 +5785,7 @@ static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp,
int sig = target_to_host_signal(arg);
return get_errno(safe_ioctl(fd, ie->host_cmd, sig));
}
+#endif
#ifdef TIOCGPTPEER
static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp,
@@ -5652,6 +5803,8 @@ static IOCTLEntry ioctl_entries[] = {
{ TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
#define IOCTL_IGNORE(cmd) \
{ TARGET_ ## cmd, 0, #cmd },
+#define IOCTL_MAP(tcmd, hcmd, access, ...) \
+ { TARGET_ ## tcmd, hcmd, #hcmd, access, 0, { __VA_ARGS__ } },
#include "ioctls.h"
{ 0, 0, },
};
@@ -5860,7 +6013,10 @@ static void target_to_host_termios (void *dst, const void *src)
target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
host->c_lflag =
target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
+#if defined TARGET_ABI_IRIX
+#elif !defined TARGET_ABI_SOLARIS
host->c_line = target->c_line;
+#endif
memset(host->c_cc, 0, sizeof(host->c_cc));
host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
@@ -5895,7 +6051,14 @@ static void host_to_target_termios (void *dst, const void *src)
tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
target->c_lflag =
tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
+#if defined TARGET_ABI_IRIX
+#ifdef NEW
+ target->c_ospeed = 0;
+ target->c_ispeed = 0;
+#endif
+#elif !defined TARGET_ABI_SOLARIS
target->c_line = host->c_line;
+#endif
memset(target->c_cc, 0, sizeof(target->c_cc));
target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
@@ -5984,10 +6147,10 @@ static abi_long write_ldt(CPUX86State *env,
return -TARGET_EINVAL;
if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
return -TARGET_EFAULT;
- ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
- ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
- ldt_info.limit = tswap32(target_ldt_info->limit);
- ldt_info.flags = tswap32(target_ldt_info->flags);
+ __get_user(ldt_info.entry_number, &target_ldt_info->entry_number);
+ __get_user(ldt_info.base_addr, &target_ldt_info->base_addr);
+ __get_user(ldt_info.limit, &target_ldt_info->limit);
+ __get_user(ldt_info.flags, &target_ldt_info->flags);
unlock_user_struct(target_ldt_info, ptr, 0);
if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
@@ -6057,8 +6220,8 @@ static abi_long write_ldt(CPUX86State *env,
/* Install the new entry ... */
install:
lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
- lp[0] = tswap32(entry_1);
- lp[1] = tswap32(entry_2);
+ __put_user(entry_1, &lp[0]);
+ __put_user(entry_2, &lp[1]);
return 0;
}
@@ -6099,15 +6262,15 @@ abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
if (!target_ldt_info)
return -TARGET_EFAULT;
- ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
- ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
- ldt_info.limit = tswap32(target_ldt_info->limit);
- ldt_info.flags = tswap32(target_ldt_info->flags);
+ __get_user(ldt_info.entry_number, &target_ldt_info->entry_number);
+ __get_user(ldt_info.base_addr, &target_ldt_info->base_addr);
+ __get_user(ldt_info.limit, &target_ldt_info->limit);
+ __get_user(ldt_info.flags, &target_ldt_info->flags);
if (ldt_info.entry_number == -1) {
for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
if (gdt_table[i] == 0) {
ldt_info.entry_number = i;
- target_ldt_info->entry_number = tswap32(i);
+ __put_user(i, &target_ldt_info->entry_number);
break;
}
}
@@ -6166,8 +6329,8 @@ abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
/* Install the new entry ... */
install:
lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
- lp[0] = tswap32(entry_1);
- lp[1] = tswap32(entry_2);
+ __put_user(entry_1, &lp[0]);
+ __put_user(entry_2, &lp[1]);
return 0;
}
@@ -6183,15 +6346,15 @@ static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
if (!target_ldt_info)
return -TARGET_EFAULT;
- idx = tswap32(target_ldt_info->entry_number);
+ __get_user(idx, &target_ldt_info->entry_number);
if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
idx > TARGET_GDT_ENTRY_TLS_MAX) {
unlock_user_struct(target_ldt_info, ptr, 1);
return -TARGET_EINVAL;
}
lp = (uint32_t *)(gdt_table + idx);
- entry_1 = tswap32(lp[0]);
- entry_2 = tswap32(lp[1]);
+ __get_user(entry_1, &lp[0]);
+ __get_user(entry_2, &lp[1]);
read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
contents = (entry_2 >> 10) & 3;
@@ -6211,9 +6374,9 @@ static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
base_addr = (entry_1 >> 16) |
(entry_2 & 0xff000000) |
((entry_2 & 0xff) << 16);
- target_ldt_info->base_addr = tswapal(base_addr);
- target_ldt_info->limit = tswap32(limit);
- target_ldt_info->flags = tswap32(flags);
+ __put_user(base_addr, &target_ldt_info->base_addr);
+ __put_user(limit, &target_ldt_info->limit);
+ __put_user(flags, &target_ldt_info->flags);
unlock_user_struct(target_ldt_info, ptr, 1);
return 0;
}
@@ -6286,6 +6449,11 @@ static void *clone_func(void *arg)
ts = (TaskState *)cpu->opaque;
info->tid = gettid();
task_settid(ts);
+#ifdef TARGET_ABI_IRIX
+ /* TODO: which fields in the PRDA are filled in by the IRIX kernel? */
+ __put_user(info->tid, (abi_int *)&ts->prda[0xe00]); /* t_pid */
+ __put_user(info->tid, (abi_int *)&ts->prda[0xe40]); /* t_rpid */
+#endif
if (info->child_tidptr)
put_user_u32(info->tid, info->child_tidptr);
if (info->parent_tidptr)
@@ -6308,7 +6476,7 @@ static void *clone_func(void *arg)
do_*() functions). */
static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
abi_ulong parent_tidptr, target_ulong newtls,
- abi_ulong child_tidptr)
+ abi_ulong child_tidptr, abi_ulong entry, abi_ulong arg)
{
CPUState *cpu = ENV_GET_CPU(env);
int ret;
@@ -6341,6 +6509,17 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
cpu_clone_regs(new_env, newsp);
new_cpu = ENV_GET_CPU(new_env);
new_cpu->opaque = ts;
+#ifdef TARGET_ABI_IRIX
+ if (entry) { /* sproc */
+ new_env->active_tc.PC = entry;
+ new_env->active_tc.gpr[4] = arg;
+ new_env->active_tc.gpr[29] = newsp;
+ }
+ ts->parent_task = parent_ts;
+ /* copy global parameters... */
+ ts->exit_sig = parent_ts->exit_sig;
+ ts->is_pthread = parent_ts->is_pthread;
+#endif
ts->bprm = parent_ts->bprm;
ts->info = parent_ts->info;
ts->signal_mask = parent_ts->signal_mask;
@@ -6411,16 +6590,18 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
return -TARGET_EINVAL;
}
- if (block_signals()) {
+ if (block_signals(env)) {
return -TARGET_ERESTARTSYS;
}
- fork_start();
+ fork_start(env);
ret = fork();
if (ret == 0) {
/* Child Process. */
cpu_clone_regs(env, newsp);
- fork_end(1);
+ ts = (TaskState *)cpu->opaque;
+ task_settid(ts);
+ fork_end(env, 1);
/* There is a race condition here. The parent process could
theoretically read the TID in the child process before the child
tid is set. This would require using either ptrace
@@ -6431,18 +6612,106 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
put_user_u32(gettid(), child_tidptr);
if (flags & CLONE_PARENT_SETTID)
put_user_u32(gettid(), parent_tidptr);
- ts = (TaskState *)cpu->opaque;
if (flags & CLONE_SETTLS)
cpu_set_tls (env, newtls);
if (flags & CLONE_CHILD_CLEARTID)
ts->child_tidptr = child_tidptr;
} else {
- fork_end(0);
+ fork_end(env, 0);
}
+#ifdef TARGET_ABI_SOLARIS
+ if (ret >= 0)
+ env->regwptr[1] = (ret == 0);
+ if (ret == 0)
+ ret = getppid();
+#endif
+#ifdef TARGET_ABI_IRIX
+ if (entry && ret == 0) { /* sproc, child */
+ env->active_tc.PC = entry;
+ env->active_tc.gpr[4] = arg;
+ env->active_tc.gpr[29] = newsp;
+ } else if (ret >= 0)
+ env->active_tc.gpr[3] = (ret == 0);
+#endif
}
return ret;
}
+static int do_exit(CPUArchState *env, abi_int status)
+{
+ CPUState *cpu = ENV_GET_CPU(env);
+
+ if (block_signals(env)) {
+ return -TARGET_ERESTARTSYS;
+ }
+
+ /* In old applications this may be used to implement _exit(2).
+ However in threaded applictions it is used for thread termination,
+ and _exit_group is used for application termination.
+ Do thread termination if we have more then one thread. */
+
+ cpu_list_lock();
+
+ if (CPU_NEXT(first_cpu)) {
+ TaskState *ts;
+
+ /* Remove the CPU from the list. */
+ QTAILQ_REMOVE(&cpus, cpu, node);
+
+ cpu_list_unlock();
+
+ ts = cpu->opaque;
+ if (ts->child_tidptr) {
+ put_user_u32(0, ts->child_tidptr);
+ sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
+ NULL, NULL, 0);
+ }
+#ifdef TARGET_ABI_IRIX
+ /* send exit_sig to share group if set */
+ if (ts->exit_sig) {
+ CPUState *p;
+ for (p = first_cpu; p; p = CPU_NEXT(p)) {
+ target_siginfo_t info = { 0 };
+ info.si_signo = ts->exit_sig;
+ queue_signal((CPUArchState *)p->env_ptr, info.si_signo,
+ QEMU_SI_KILL, &info);
+ /* TODO: must process here because thread may be blocked? */
+ process_pending_signals((CPUArchState *)p->env_ptr);
+ }
+ }
+ /* send termchild_sig to children if set */
+ {
+ CPUState *p; TaskState *t;
+ for (p = first_cpu; p; p = CPU_NEXT(p)) {
+ t = (TaskState *)p->opaque;
+ if (t->parent_task == ts && t->termchild_sig) {
+ target_siginfo_t info = { 0 };
+ info.si_signo = t->termchild_sig;
+ queue_signal((CPUArchState *)p->env_ptr, info.si_signo,
+ QEMU_SI_KILL, &info);
+ /* TODO: must process here because thread may be blocked? */
+ process_pending_signals((CPUArchState *)p->env_ptr);
+ }
+ }
+ }
+#endif
+ thread_cpu = NULL;
+ object_unref(OBJECT(cpu));
+ g_free(ts);
+ rcu_unregister_thread();
+ pthread_exit(NULL);
+ }
+
+ cpu_list_unlock();
+ /* either last thread, or unthreaded application */
+#ifdef TARGET_GPROF
+ _mcleanup();
+#endif
+ gdb_exit(env, status);
+ _exit(status);
+ return 0;
+}
+
/* warning : doesn't handle linux specific flags... */
static int target_to_host_fcntl_cmd(int cmd)
{
@@ -6463,10 +6732,12 @@ static int target_to_host_fcntl_cmd(int cmd)
return F_GETOWN;
case TARGET_F_SETOWN:
return F_SETOWN;
+#ifdef TARGET_F_GETSIG
case TARGET_F_GETSIG:
return F_GETSIG;
case TARGET_F_SETSIG:
return F_SETSIG;
+#endif
#if TARGET_ABI_BITS == 32
case TARGET_F_GETLK64:
return F_GETLK64;
@@ -6485,11 +6756,11 @@ static int target_to_host_fcntl_cmd(int cmd)
#endif
case TARGET_F_NOTIFY:
return F_NOTIFY;
-#ifdef F_GETOWN_EX
+#if defined F_GETOWN_EX && defined TARGET_F_GETOWN_EX
case TARGET_F_GETOWN_EX:
return F_GETOWN_EX;
#endif
-#ifdef F_SETOWN_EX
+#if defined F_SETOWN_EX && defined TARGET_F_SETOWN_EX
case TARGET_F_SETOWN_EX:
return F_SETOWN_EX;
#endif
@@ -6643,13 +6914,53 @@ static inline abi_long copy_to_user_flock64(abi_ulong target_flock_addr,
static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
{
struct flock64 fl64;
-#ifdef F_GETOWN_EX
+#if defined F_GETOWN_EX && defined TARGET_F_GETOWN_EX
struct f_owner_ex fox;
struct target_f_owner_ex *target_fox;
#endif
abi_long ret;
- int host_cmd = target_to_host_fcntl_cmd(cmd);
+ int host_cmd;
+#ifdef TARGET_F_ALLOCSP
+ if (cmd == TARGET_F_FREESP || cmd == TARGET_F_ALLOCSP)
+ {
+ struct stat st;
+ int wh;
+ ret = copy_from_user_flock(&fl64, arg);
+ if (ret) {
+ return ret;
+ }
+ if (fl64.l_whence == SEEK_CUR)
+ fl64.l_start += lseek(fd, 0, SEEK_CUR);
+ if (fl64.l_whence == SEEK_END && fstat(fd, &st) >= 0)
+ fl64.l_start += st.st_size;
+ wh = (cmd == TARGET_F_FREESP || cmd == TARGET_F_FREESP64 ? FALLOC_FL_PUNCH_HOLE : 0);
+ return get_errno(fallocate(fd, wh, (fl64.l_len ? fl64.l_start : 0), (fl64.l_len ?: fl64.l_start)));
+ }
+ if (cmd == TARGET_F_FREESP64 || cmd == TARGET_F_ALLOCSP64)
+ {
+ struct stat st;
+ int wh;
+ ret = copy_from_user_flock64(&fl64, arg);
+ if (ret) {
+ return ret;
+ }
+ if (fl64.l_whence == SEEK_CUR)
+ fl64.l_start += lseek(fd, 0, SEEK_CUR);
+ if (fl64.l_whence == SEEK_END && fstat(fd, &st) >= 0)
+ fl64.l_start += st.st_size;
+ wh = (cmd == TARGET_F_FREESP || cmd == TARGET_F_FREESP64 ? FALLOC_FL_PUNCH_HOLE : 0);
+ return get_errno(fallocate(fd, wh, (fl64.l_len ? fl64.l_start : 0), (fl64.l_len ?: fl64.l_start)));
+ }
+#endif
+#ifdef TARGET_F_DUP2FD
+ if (cmd == TARGET_F_DUP2FD)
+ {
+ return get_errno(dup2(fd, arg));
+ }
+#endif
+
+ host_cmd = target_to_host_fcntl_cmd(cmd);
if (host_cmd == -TARGET_EINVAL)
return host_cmd;
@@ -6706,25 +7017,25 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
fcntl_flags_tbl)));
break;
-#ifdef F_GETOWN_EX
+#if defined F_GETOWN_EX && defined TARGET_F_GETOWN_EX
case TARGET_F_GETOWN_EX:
ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
if (ret >= 0) {
if (!lock_user_struct(VERIFY_WRITE, target_fox, arg, 0))
return -TARGET_EFAULT;
- target_fox->type = tswap32(fox.type);
- target_fox->pid = tswap32(fox.pid);
+ __put_user(fox.type, &target_fox->type);
+ __put_user(fox.pid, &target_fox->pid);
unlock_user_struct(target_fox, arg, 1);
}
break;
#endif
-#ifdef F_SETOWN_EX
+#if defined F_SETOWN_EX && defined TARGET_F_SETOWN_EX
case TARGET_F_SETOWN_EX:
if (!lock_user_struct(VERIFY_READ, target_fox, arg, 1))
return -TARGET_EFAULT;
- fox.type = tswap32(target_fox->type);
- fox.pid = tswap32(target_fox->pid);
+ __get_user(fox.type, &target_fox->type);
+ __get_user(fox.pid, &target_fox->pid);
unlock_user_struct(target_fox, arg, 0);
ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
break;
@@ -6732,8 +7043,10 @@ static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
case TARGET_F_SETOWN:
case TARGET_F_GETOWN:
+#ifdef TARGET_F_SETSIG
case TARGET_F_SETSIG:
case TARGET_F_GETSIG:
+#endif
case TARGET_F_SETLEASE:
case TARGET_F_GETLEASE:
case TARGET_F_SETPIPE_SZ:
@@ -6843,10 +7156,18 @@ static inline int tswapid(int id)
#define __NR_sys_setresgid __NR_setresgid
#endif
+#ifdef TARGET_NR_setuid32
_syscall1(int, sys_setuid, uid_t, uid)
+#endif
+#ifdef TARGET_NR_setgid32
_syscall1(int, sys_setgid, gid_t, gid)
+#endif
+#if defined(TARGET_NR_setresuid) || defined(TARGET_NR_setresuid32)
_syscall3(int, sys_setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
+#endif
+#if defined(TARGET_NR_setresgid) || defined(TARGET_NR_setresgid32)
_syscall3(int, sys_setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
+#endif
void syscall_init(void)
{
@@ -6922,11 +7243,10 @@ static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
abi_long arg3,
abi_long arg4)
{
- if (regpairs_aligned(cpu_env, TARGET_NR_truncate64)) {
- arg2 = arg3;
- arg3 = arg4;
- }
- return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
+ if (regpairs_aligned(cpu_env, TARGET_NR_truncate64))
+ return get_errno(truncate64(arg1, target_offset64(arg3, arg4)));
+ else
+ return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
}
#endif
@@ -6936,11 +7256,10 @@ static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
abi_long arg3,
abi_long arg4)
{
- if (regpairs_aligned(cpu_env, TARGET_NR_ftruncate64)) {
- arg2 = arg3;
- arg3 = arg4;
- }
- return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
+ if (regpairs_aligned(cpu_env, TARGET_NR_ftruncate64))
+ return get_errno(ftruncate64(arg1, target_offset64(arg3, arg4)));
+ else
+ return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
}
#endif
@@ -6979,12 +7298,12 @@ static inline abi_long target_to_host_itimerspec(struct itimerspec *host_itspec,
return -TARGET_EFAULT;
}
- host_itspec->it_interval.tv_sec =
- tswapal(target_itspec->it_interval.tv_sec);
- host_itspec->it_interval.tv_nsec =
- tswapal(target_itspec->it_interval.tv_nsec);
- host_itspec->it_value.tv_sec = tswapal(target_itspec->it_value.tv_sec);
- host_itspec->it_value.tv_nsec = tswapal(target_itspec->it_value.tv_nsec);
+ __get_user(host_itspec->it_interval.tv_sec,
+ &target_itspec->it_interval.tv_sec);
+ __get_user(host_itspec->it_interval.tv_nsec,
+ &target_itspec->it_interval.tv_nsec);
+ __get_user(host_itspec->it_value.tv_sec, &target_itspec->it_value.tv_sec);
+ __get_user(host_itspec->it_value.tv_nsec, &target_itspec->it_value.tv_nsec);
unlock_user_struct(target_itspec, target_addr, 1);
return 0;
@@ -6999,11 +7318,11 @@ static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
return -TARGET_EFAULT;
}
- target_itspec->it_interval.tv_sec = tswapal(host_its->it_interval.tv_sec);
- target_itspec->it_interval.tv_nsec = tswapal(host_its->it_interval.tv_nsec);
+ __put_user(host_its->it_interval.tv_sec, &target_itspec->it_interval.tv_sec);
+ __put_user(host_its->it_interval.tv_nsec, &target_itspec->it_interval.tv_nsec);
- target_itspec->it_value.tv_sec = tswapal(host_its->it_value.tv_sec);
- target_itspec->it_value.tv_nsec = tswapal(host_its->it_value.tv_nsec);
+ __put_user(host_its->it_value.tv_sec, &target_itspec->it_value.tv_sec);
+ __put_user(host_its->it_value.tv_nsec, &target_itspec->it_value.tv_nsec);
unlock_user_struct(target_itspec, target_addr, 0);
return 0;
@@ -7099,14 +7418,14 @@ static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp,
(void *)(uintptr_t)tswapal(target_sevp->sigev_value.sival_ptr);
host_sevp->sigev_signo =
target_to_host_signal(tswap32(target_sevp->sigev_signo));
- host_sevp->sigev_notify = tswap32(target_sevp->sigev_notify);
- host_sevp->_sigev_un._tid = tswap32(target_sevp->_sigev_un._tid);
+ __get_user(host_sevp->sigev_notify, &target_sevp->sigev_notify);
+ __get_user(host_sevp->_sigev_un._tid, &target_sevp->_sigev_un._tid);
unlock_user_struct(target_sevp, target_addr, 1);
return 0;
}
-#if defined(TARGET_NR_mlockall)
+#if defined(TARGET_NR_mlockall) || defined(TARGET_NR_memcntl)
static inline int target_to_host_mlockall_arg(int arg)
{
int result = 0;
@@ -7121,6 +7440,39 @@ static inline int target_to_host_mlockall_arg(int arg)
}
#endif
+static inline abi_long host_to_target_stat(void *cpu_env,
+ abi_ulong target_addr,
+ struct stat *host_st)
+{
+ struct target_stat *target_st;
+
+ if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
+ return -TARGET_EFAULT;
+
+#ifdef TARGET_ABI_IRIX
+ memset(target_st, 0, sizeof(*target_st));
+#else
+ memset(target_st, 0, offsetof(struct target_stat,st_blocks));
+#endif
+ __put_user(host_st->st_dev, &target_st->st_dev);
+ __put_user(host_st->st_ino, &target_st->st_ino);
+ __put_user(host_st->st_mode, &target_st->st_mode);
+ __put_user(host_st->st_uid, &target_st->st_uid);
+ __put_user(host_st->st_gid, &target_st->st_gid);
+ __put_user(host_st->st_nlink, &target_st->st_nlink);
+ __put_user(host_st->st_rdev, &target_st->st_rdev);
+ __put_user(host_st->st_size, &target_st->st_size);
+ __put_user(host_st->st_blksize, &target_st->st_blksize);
+ __put_user(host_st->st_blocks, &target_st->st_blocks);
+ __put_user(host_st->st_atime, &target_st->target_st_atime);
+ __put_user(host_st->st_mtime, &target_st->target_st_mtime);
+ __put_user(host_st->st_ctime, &target_st->target_st_ctime);
+ unlock_user_struct(target_st, target_addr, 1);
+
+ return 0;
+}
+
+#if defined(TARGET_NR_stat64) || defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat) || defined(TARGET_ABI_IRIX)
static inline abi_long host_to_target_stat64(void *cpu_env,
abi_ulong target_addr,
struct stat *host_st)
@@ -7183,7 +7535,9 @@ static inline abi_long host_to_target_stat64(void *cpu_env,
return 0;
}
+#endif
+#ifdef TARGET_NR_futex
/* ??? Using host futex calls even when target atomic operations
are not really atomic probably breaks things. However implementing
futexes locally would make futexes shared between multiple processes
@@ -7235,6 +7589,8 @@ static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
return -TARGET_ENOSYS;
}
}
+#endif
+
#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname,
abi_long handle, abi_long mount_id,
@@ -7275,8 +7631,8 @@ static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname,
*/
memcpy(target_fh, fh, total_size);
- target_fh->handle_bytes = tswap32(fh->handle_bytes);
- target_fh->handle_type = tswap32(fh->handle_type);
+ __put_user(fh->handle_bytes, &target_fh->handle_bytes);
+ __put_user(fh->handle_type, &target_fh->handle_type);
g_free(fh);
unlock_user(target_fh, handle, total_size);
@@ -7310,7 +7666,7 @@ static abi_long do_open_by_handle_at(abi_long mount_fd, abi_long handle,
fh = g_memdup(target_fh, total_size);
fh->handle_bytes = size;
- fh->handle_type = tswap32(target_fh->handle_type);
+ __get_user(fh->handle_type, &target_fh->handle_type);
ret = get_errno(open_by_handle_at(mount_fd, fh,
target_to_host_bitmask(flags, fcntl_flags_tbl)));
@@ -7343,26 +7699,26 @@ host_to_target_signalfd_siginfo(struct signalfd_siginfo *tinfo,
tinfo->ssi_code == BUS_MCEERR_AO)) {
uint16_t *ssi_addr_lsb = (uint16_t *)(&info->ssi_addr + 1);
uint16_t *tssi_addr_lsb = (uint16_t *)(&tinfo->ssi_addr + 1);
- *tssi_addr_lsb = tswap16(*ssi_addr_lsb);
+ __put_user(*ssi_addr_lsb, tssi_addr_lsb);
}
#endif
- tinfo->ssi_signo = tswap32(sig);
- tinfo->ssi_errno = tswap32(tinfo->ssi_errno);
- tinfo->ssi_code = tswap32(info->ssi_code);
- tinfo->ssi_pid = tswap32(info->ssi_pid);
- tinfo->ssi_uid = tswap32(info->ssi_uid);
- tinfo->ssi_fd = tswap32(info->ssi_fd);
- tinfo->ssi_tid = tswap32(info->ssi_tid);
- tinfo->ssi_band = tswap32(info->ssi_band);
- tinfo->ssi_overrun = tswap32(info->ssi_overrun);
- tinfo->ssi_trapno = tswap32(info->ssi_trapno);
- tinfo->ssi_status = tswap32(info->ssi_status);
- tinfo->ssi_int = tswap32(info->ssi_int);
- tinfo->ssi_ptr = tswap64(info->ssi_ptr);
- tinfo->ssi_utime = tswap64(info->ssi_utime);
- tinfo->ssi_stime = tswap64(info->ssi_stime);
- tinfo->ssi_addr = tswap64(info->ssi_addr);
+ __put_user(sig, &tinfo->ssi_signo);
+ __put_user(info->ssi_errno, &tinfo->ssi_errno);
+ __put_user(info->ssi_code, &tinfo->ssi_code);
+ __put_user(info->ssi_pid, &tinfo->ssi_pid);
+ __put_user(info->ssi_uid, &tinfo->ssi_uid);
+ __put_user(info->ssi_fd, &tinfo->ssi_fd);
+ __put_user(info->ssi_tid, &tinfo->ssi_tid);
+ __put_user(info->ssi_band, &tinfo->ssi_band);
+ __put_user(info->ssi_overrun, &tinfo->ssi_overrun);
+ __put_user(info->ssi_trapno, &tinfo->ssi_trapno);
+ __put_user(info->ssi_status, &tinfo->ssi_status);
+ __put_user(info->ssi_int, &tinfo->ssi_int);
+ __put_user(info->ssi_ptr, &tinfo->ssi_ptr);
+ __put_user(info->ssi_utime, &tinfo->ssi_utime);
+ __put_user(info->ssi_stime, &tinfo->ssi_stime);
+ __put_user(info->ssi_addr, &tinfo->ssi_addr);
}
static abi_long host_to_target_data_signalfd(void *buf, size_t len)
@@ -7705,6 +8061,7 @@ static target_timer_t get_timer_id(abi_long arg)
return timerid;
}
+#if defined(TARGET_NR_eventfd) || defined(TARGET_NR_eventfd2)
static abi_long swap_data_eventfd(void *buf, size_t len)
{
uint64_t *counter = buf;
@@ -7726,6 +8083,7 @@ static TargetFdTrans target_eventfd_trans = {
.host_to_target_data = swap_data_eventfd,
.target_to_host_data = swap_data_eventfd,
};
+#endif
#if (defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)) || \
(defined(CONFIG_INOTIFY1) && defined(TARGET_NR_inotify_init1) && \
@@ -7754,6 +8112,116 @@ static TargetFdTrans target_inotify_trans = {
};
#endif
+#ifdef TARGET_ABI_IRIX
+/* IRIX usync stuff. usync synchronises accesses to an address */
+struct usync_ref {
+ abi_ulong addr;
+ pthread_mutex_t lock;
+ pthread_cond_t cond;
+ int waiters;
+ int count;
+ int handoffs;
+ struct usync_ref *next;
+};
+
+/* the usync list and the mutex protecting it */
+pthread_mutex_t usync_mutex = PTHREAD_MUTEX_INITIALIZER;
+struct usync_ref *usync_list;
+
+/* get the usync reference for addr, or create one if it doesn't exist */
+static struct usync_ref *usync_get_sync(abi_ulong addr)
+{
+ struct usync_ref *p;
+
+ pthread_mutex_lock(&usync_mutex);
+ for (p = usync_list; p; p = p->next) {
+ if (p->addr == addr)
+ break;
+ }
+ if (!p) {
+ p = malloc(sizeof(struct usync_ref));
+ if (p) {
+ pthread_mutex_init(&p->lock, NULL);
+ pthread_cond_init(&p->cond, NULL);
+ p->waiters = p->count = p->handoffs = 0;
+ p->addr = addr;
+ p->next = usync_list;
+ usync_list = p;
+ }
+ }
+ pthread_mutex_unlock(&usync_mutex);
+ return p;
+}
+
+/* IRIX psema stuff. POSIX semaphores */
+struct psema_ref {
+ char *name;
+ sem_t *sem;
+};
+
+/* the psema list and the mutex protecting it */
+#define PSEMA_MAX 30
+pthread_mutex_t psema_mutex = PTHREAD_MUTEX_INITIALIZER;
+struct psema_ref psema_list[PSEMA_MAX];
+
+/* get the pindex for sem or name, or -1 if it doesn't exist */
+static int psema_get_index(char *name, sem_t *sem, int create)
+{
+ struct psema_ref *p;
+ int i, empty = -1;
+
+ pthread_mutex_lock(&psema_mutex);
+ for (i = 0, p = psema_list; i < PSEMA_MAX; i++, p++) {
+ if (p->sem) {
+ if (p->sem == sem || (name && p->name && !strcmp(p->name, name))) {
+ pthread_mutex_unlock(&psema_mutex);
+ return i;
+ }
+ } else if (empty < 0)
+ empty = i;
+ }
+ if (create && empty >= 0) {
+ psema_list[empty].name = name ? strdup(name) : NULL;
+ psema_list[empty].sem = sem;
+ i = empty;
+ } else
+ i = -1;
+ pthread_mutex_unlock(&psema_mutex);
+ return i;
+}
+
+/* get sem_t for index */
+static sem_t *psema_get_sem(int index)
+{
+ if (index >= 0 && index < PSEMA_MAX)
+ return psema_list[index].sem;
+ return NULL;
+}
+
+/* drop semaphore from list */
+static void psema_remove_index(int index)
+{
+ if (index >= 0 && index < PSEMA_MAX) {
+ if (psema_list[index].name)
+ free(psema_list[index].name);
+ psema_list[index].name = NULL;
+ psema_list[index].sem = NULL;
+ }
+}
+
+/* remove name from semaphore */
+static void psema_unlink_index(char *name)
+{
+ int index = psema_get_index(name, NULL, 0);
+
+ if (index >= 0 && index < PSEMA_MAX) {
+ free(psema_list[index].name);
+ psema_list[index].name = NULL;
+ }
+}
+#endif
+
+#ifdef TARGET_NR_sched_getaffinity
static int target_to_host_cpu_mask(unsigned long *host_mask,
size_t host_size,
abi_ulong target_addr,
@@ -7820,6 +8288,7 @@ static int host_to_target_cpu_mask(const unsigned long *host_mask,
unlock_user(target_mask, target_addr, target_size);
return 0;
}
+#endif
/* do_syscall() should always have a single exit point at the end so
that actions, such as logging of syscall results, can be performed.
@@ -7833,6 +8302,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
abi_long ret;
struct stat st;
struct statfs stfs;
+#ifdef TARGET_NR_statvfs
+ struct statvfs stvfs;
+#endif
void *p;
#if defined(DEBUG_ERESTARTSYS)
@@ -7859,46 +8331,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
switch(num) {
case TARGET_NR_exit:
- /* In old applications this may be used to implement _exit(2).
- However in threaded applictions it is used for thread termination,
- and _exit_group is used for application termination.
- Do thread termination if we have more then one thread. */
-
- if (block_signals()) {
- ret = -TARGET_ERESTARTSYS;
- break;
- }
-
- cpu_list_lock();
-
- if (CPU_NEXT(first_cpu)) {
- TaskState *ts;
-
- /* Remove the CPU from the list. */
- QTAILQ_REMOVE(&cpus, cpu, node);
-
- cpu_list_unlock();
-
- ts = cpu->opaque;
- if (ts->child_tidptr) {
- put_user_u32(0, ts->child_tidptr);
- sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
- NULL, NULL, 0);
- }
- thread_cpu = NULL;
- object_unref(OBJECT(cpu));
- g_free(ts);
- rcu_unregister_thread();
- pthread_exit(NULL);
- }
-
- cpu_list_unlock();
-#ifdef TARGET_GPROF
- _mcleanup();
+#if defined(TARGET_ABI_IRIX) && defined(__NR_exit_group)
+ /* IRIX terminates all threads if this is a pthread */
+ if(((TaskState *)cpu->opaque)->is_pthread)
+ ret = get_errno(syscall(__NR_exit_group, arg1));
+ else
#endif
- gdb_exit(cpu_env, arg1);
- _exit(arg1);
- ret = 0; /* avoid warning */
+ ret = do_exit(cpu_env, arg1);
break;
case TARGET_NR_read:
if (arg3 == 0)
@@ -7941,6 +8380,18 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p, arg1, 0);
break;
#endif
+#ifdef TARGET_NR_open64
+ case TARGET_NR_open64:
+ if (!(p = lock_user_string(arg1)))
+ goto efault;
+ ret = get_errno(do_openat(cpu_env, AT_FDCWD, p,
+ target_to_host_bitmask(arg2 | TARGET_O_LARGEFILE, fcntl_flags_tbl),
+ arg3));
+ fd_trans_unregister(ret);
+ unlock_user(p, arg1, 0);
+ break;
+#endif
+#ifdef TARGET_NR_openat
case TARGET_NR_openat:
if (!(p = lock_user_string(arg2)))
goto efault;
@@ -7950,6 +8401,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
fd_trans_unregister(ret);
unlock_user(p, arg2, 0);
break;
+#endif
+#ifdef TARGET_NR_openat64
+ case TARGET_NR_openat64:
+ if (!(p = lock_user_string(arg2)))
+ goto efault;
+ ret = get_errno(do_openat(cpu_env, arg1, p,
+ target_to_host_bitmask(arg3 | TARGET_O_LARGEFILE, fcntl_flags_tbl),
+ arg4));
+ fd_trans_unregister(ret);
+ unlock_user(p, arg2, 0);
+#endif
#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
case TARGET_NR_name_to_handle_at:
ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5);
@@ -7963,6 +8425,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif
case TARGET_NR_close:
fd_trans_unregister(arg1);
+#ifdef TARGET_ABI_IRIX
+ /* TODO: is there something special for closing a negative fd in IRIX?
+ * Some software does this, and it isn't working without waiting some.
+ * Maybe a scheduling issue?
+ */
+ if (arg1 < 0) usleep(10000);
+#endif
ret = get_errno(close(arg1));
break;
case TARGET_NR_brk:
@@ -7970,7 +8439,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
break;
#ifdef TARGET_NR_fork
case TARGET_NR_fork:
- ret = get_errno(do_fork(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0));
+ ret = get_errno(do_fork(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0, 0, 0));
break;
#endif
#ifdef TARGET_NR_waitpid
@@ -7989,13 +8458,30 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
{
siginfo_t info;
info.si_pid = 0;
+#if defined TARGET_ABI_IRIX || defined TARGET_ABI_SOLARIS
+ /* TODO: this should go to something like target_to_host_waitopts */
+ int opt = arg4;
+ switch (arg1) {
+ case TARGET_P_PID: arg1 = P_PID; break;
+ case TARGET_P_PGID: arg1 = P_PGID; break;
+ case TARGET_P_ALL: arg1 = P_ALL; break;
+ default: arg1 = P_ALL; break;
+ }
+ arg4 = 0;
+ if (opt & TARGET_WNOHANG) arg4 |= WNOHANG;
+ if (opt & TARGET_WSTOPPED) arg4 |= WSTOPPED;
+ if (opt & TARGET_WEXITED) arg4 |= WEXITED;
+ if (opt & TARGET_WCONTINUED) arg4 |= WCONTINUED;
+ if (opt & TARGET_WNOWAIT) arg4 |= WNOWAIT;
+#endif
+ if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
+ goto efault;
ret = get_errno(safe_waitid(arg1, arg2, &info, arg4, NULL));
if (!is_error(ret) && arg3 && info.si_pid != 0) {
- if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
- goto efault;
host_to_target_siginfo(p, &info);
- unlock_user(p, arg3, sizeof(target_siginfo_t));
- }
+ } else
+ memset(p, 0, sizeof(target_siginfo_t));
+ unlock_user(p, arg3, sizeof(target_siginfo_t));
}
break;
#endif
@@ -8008,6 +8494,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p, arg1, 0);
break;
#endif
+#ifdef TARGET_NR_creat64
+ case TARGET_NR_creat64:
+ if (!(p = lock_user_string(arg1)))
+ goto efault;
+ ret = get_errno(open(p, O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, arg2));
+ fd_trans_unregister(ret);
+ unlock_user(p, arg1, 0);
+ break;
+#endif
#ifdef TARGET_NR_link
case TARGET_NR_link:
{
@@ -8055,6 +8550,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(unlinkat(arg1, p, arg3));
unlock_user(p, arg2, 0);
break;
+#endif
+#ifdef TARGET_NR_execv
+ case TARGET_NR_execv:
+ arg3 = 0; /* presumably unused. same as execve, but no environment */
#endif
case TARGET_NR_execve:
{
@@ -8125,7 +8624,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
* before the execve completes and makes it the other
* program's problem.
*/
- ret = get_errno(safe_execve(p, argp, envp));
+ ret = get_errno(safe_execve(path(p), argp, envp));
unlock_user(p, arg1, 0);
goto execve_end;
@@ -8164,13 +8663,23 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
{
time_t host_time;
ret = get_errno(time(&host_time));
+#ifndef TARGET_ABI_IRIX
if (!is_error(ret)
&& arg1
&& put_user_sal(host_time, arg1))
goto efault;
+#endif
}
break;
#endif
+#ifdef TARGET_NR_xmknod
+ case TARGET_NR_xmknod:
+ if (!(p = lock_user_string(arg2)))
+ goto efault;
+ ret = get_errno(mknod(p, arg3, arg4));
+ unlock_user(p, arg2, 0);
+ break;
+#endif
#ifdef TARGET_NR_mknod
case TARGET_NR_mknod:
if (!(p = lock_user_string(arg1)))
@@ -8206,6 +8715,41 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_lseek:
ret = get_errno(lseek(arg1, arg2, arg3));
break;
+#ifdef TARGET_NR_lseek64
+ case TARGET_NR_lseek64:
+ {
+ int64_t off = arg2, res;
+#if TARGET_ABI_BITS == 32
+ if (regpairs_aligned(cpu_env, num)) {
+ off = target_offset64(arg3, arg4);
+ arg3 = arg5;
+ } else {
+ off = target_offset64(arg2, arg3);
+ arg3 = arg4;
+ }
+#endif
+#if !defined(__NR_llseek)
+ res = lseek(arg1, off, arg3);
+ if (res == -1)
+ ret = get_errno(res);
+ else
+ ret = 0;
+#else
+ ret = get_errno(_llseek(arg1, (ulong)(off >> 32), (ulong)off, &res, arg3));
+#endif
+ if (ret < 0) {
+ res = ret;
+ }
+#if defined(TARGET_ABI_IRIX) && TARGET_ABI_BITS == 32
+ /* split the 64 bit return value */
+ ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = (abi_int) res;
+ ret = (abi_int) (res >> 32);
+#else
+ ret = res;
+#endif
+ }
+ break;
+#endif
#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
/* Alpha specific */
case TARGET_NR_getxpid:
@@ -8215,6 +8759,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif
#ifdef TARGET_NR_getpid
case TARGET_NR_getpid:
+#ifdef TARGET_ABI_SOLARIS
+ ((CPUSPARCState*)cpu_env)->regwptr[1] = getppid();
+#endif
+#ifdef TARGET_ABI_IRIX
+ ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = getppid();
+#endif
ret = get_errno(getpid());
break;
#endif
@@ -8291,8 +8841,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
break;
#endif
+#ifdef TARGET_NR_ptrace
case TARGET_NR_ptrace:
goto unimplemented;
+#endif
#ifdef TARGET_NR_alarm /* not on alpha */
case TARGET_NR_alarm:
ret = alarm(arg1);
@@ -8304,7 +8856,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif
#ifdef TARGET_NR_pause /* not on alpha */
case TARGET_NR_pause:
- if (!block_signals()) {
+ if (!block_signals(cpu_env)) {
sigsuspend(&((TaskState *)cpu->opaque)->signal_mask);
}
ret = -TARGET_EINTR;
@@ -8318,8 +8870,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (arg2) {
if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
goto efault;
- tbuf.actime = tswapal(target_tbuf->actime);
- tbuf.modtime = tswapal(target_tbuf->modtime);
+ __get_user(tbuf.actime, &target_tbuf->actime);
+ __get_user(tbuf.modtime, &target_tbuf->modtime);
unlock_user_struct(target_tbuf, arg2, 0);
host_tbuf = &tbuf;
} else {
@@ -8384,7 +8936,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_access:
if (!(p = lock_user_string(arg1)))
goto efault;
- ret = get_errno(access(path(p), arg2));
+#if defined TARGET_E_OK
+ if (arg2 & TARGET_E_OK)
+ ret = get_errno(euidaccess(path(p), arg2 & ~TARGET_E_OK));
+ else
+#endif
+ ret = get_errno(access(path(p), arg2));
unlock_user(p, arg1, 0);
break;
#endif
@@ -8513,10 +9070,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
if (!tmsp)
goto efault;
- tmsp->tms_utime = tswapal(host_to_target_clock_t(tms.tms_utime));
- tmsp->tms_stime = tswapal(host_to_target_clock_t(tms.tms_stime));
- tmsp->tms_cutime = tswapal(host_to_target_clock_t(tms.tms_cutime));
- tmsp->tms_cstime = tswapal(host_to_target_clock_t(tms.tms_cstime));
+ __put_user(host_to_target_clock_t(tms.tms_utime), &tmsp->tms_utime);
+ __put_user(host_to_target_clock_t(tms.tms_stime), &tmsp->tms_stime);
+ __put_user(host_to_target_clock_t(tms.tms_cutime), &tmsp->tms_cutime);
+ __put_user(host_to_target_clock_t(tms.tms_cstime), &tmsp->tms_cstime);
}
if (!is_error(ret))
ret = host_to_target_clock_t(ret);
@@ -8557,6 +9114,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
break;
#ifdef TARGET_NR_fcntl
case TARGET_NR_fcntl:
+#if defined(TARGET_ABI_IRIX) && defined(TARGET_ABI_MIPSN32)
+ /* for N32 map everything using struct flock to its 64 bit version */
+ if (arg2 == TARGET_F_ALLOCSP) arg2 = TARGET_F_ALLOCSP64;
+ else if (arg2 == TARGET_F_FREESP) arg2 = TARGET_F_FREESP64;
+ else if (arg2 == TARGET_F_GETLK) arg2 = TARGET_F_GETLK64;
+ else if (arg2 == TARGET_F_SETLK) arg2 = TARGET_F_SETLK64;
+ else if (arg2 == TARGET_F_SETLKW) arg2 = TARGET_F_SETLKW64;
+#endif
ret = do_fcntl(arg1, arg2, arg3);
break;
#endif
@@ -8564,12 +9129,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_mpx:
goto unimplemented;
#endif
+#ifdef TARGET_NR_setpgid
case TARGET_NR_setpgid:
ret = get_errno(setpgid(arg1, arg2));
break;
+#endif
#ifdef TARGET_NR_ulimit
case TARGET_NR_ulimit:
- goto unimplemented;
+ if (arg1 != UL_SETFSIZE)
+ ret = get_errno(ulimit(arg1, arg2, arg3));
+ else ret = -TARGET_EPERM;
+ break;
#endif
#ifdef TARGET_NR_oldolduname
case TARGET_NR_oldolduname:
@@ -8622,9 +9192,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(getpgrp());
break;
#endif
+#ifdef TARGET_NR_setsid
case TARGET_NR_setsid:
ret = get_errno(setsid());
break;
+#endif
#ifdef TARGET_NR_sigaction
case TARGET_NR_sigaction:
{
@@ -8641,7 +9213,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user_struct(old_act, arg2, 0);
pact = &act;
}
- ret = get_errno(do_sigaction(arg1, pact, &oact));
+ ret = get_errno(do_sigaction(cpu_env, arg1, pact, &oact));
if (!is_error(ret) && arg3) {
if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
goto efault;
@@ -8650,7 +9222,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
old_act->sa_flags = oact.sa_flags;
unlock_user_struct(old_act, arg3, 1);
}
-#elif defined(TARGET_MIPS)
+#elif defined(TARGET_MIPS) || defined(TARGET_ABI_SOLARIS)
struct target_sigaction act, oact, *pact, *old_act;
if (arg2) {
@@ -8665,19 +9237,26 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
pact = NULL;
}
- ret = get_errno(do_sigaction(arg1, pact, &oact));
+ ret = get_errno(do_sigaction(cpu_env, arg1, pact, &oact));
- if (!is_error(ret) && arg3) {
+#ifdef TARGET_ABI_IRIX
+ /* IRIX libc hands down its signal trampoline, such that the kernel
+ * needn't bother with installing one for the different ABIs
+ */
+ if (!is_error(ret))
+ ((TaskState*)cpu->opaque)->sigtramp = arg4;
+#endif
+ if (!is_error(ret) && arg3) {
if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
goto efault;
- old_act->_sa_handler = oact._sa_handler;
- old_act->sa_flags = oact.sa_flags;
- old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
- old_act->sa_mask.sig[1] = 0;
- old_act->sa_mask.sig[2] = 0;
- old_act->sa_mask.sig[3] = 0;
- unlock_user_struct(old_act, arg3, 1);
- }
+ old_act->_sa_handler = oact._sa_handler;
+ old_act->sa_flags = oact.sa_flags;
+ old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
+ old_act->sa_mask.sig[1] = 0;
+ old_act->sa_mask.sig[2] = 0;
+ old_act->sa_mask.sig[3] = 0;
+ unlock_user_struct(old_act, arg3, 1);
+ }
#else
struct target_old_sigaction *old_act;
struct target_sigaction act, oact, *pact;
@@ -8693,7 +9272,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
} else {
pact = NULL;
}
- ret = get_errno(do_sigaction(arg1, pact, &oact));
+ ret = get_errno(do_sigaction(cpu_env, arg1, pact, &oact));
if (!is_error(ret) && arg3) {
if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
goto efault;
@@ -8707,6 +9286,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
break;
#endif
+#ifdef TARGET_NR_rt_sigaction
case TARGET_NR_rt_sigaction:
{
#if defined(TARGET_ALPHA)
@@ -8735,7 +9315,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user_struct(rt_act, arg2, 0);
pact = &act;
}
- ret = get_errno(do_sigaction(arg1, pact, &oact));
+ ret = get_errno(do_sigaction(cpu_env, arg1, pact, &oact));
if (!is_error(ret) && arg3) {
if (!lock_user_struct(VERIFY_WRITE, rt_act, arg3, 0))
goto efault;
@@ -8775,7 +9355,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
} else
oact = NULL;
- ret = get_errno(do_sigaction(arg1, act, oact));
+ ret = get_errno(do_sigaction(cpu_env, arg1, act, oact));
rt_sigaction_fail:
if (act)
unlock_user_struct(act, arg2, 0);
@@ -8784,12 +9364,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif
}
break;
+#endif
#ifdef TARGET_NR_sgetmask /* not on alpha */
case TARGET_NR_sgetmask:
{
sigset_t cur_set;
abi_ulong target_set;
- ret = do_sigprocmask(0, NULL, &cur_set);
+ ret = do_sigprocmask(cpu_env, 0, NULL, &cur_set);
if (!ret) {
host_to_target_old_sigset(&target_set, &cur_set);
ret = target_set;
@@ -8803,7 +9384,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
sigset_t set, oset;
abi_ulong target_set = arg1;
target_to_host_old_sigset(&set, &target_set);
- ret = do_sigprocmask(SIG_SETMASK, &set, &oset);
+ ret = do_sigprocmask(cpu_env, SIG_SETMASK, &set, &oset);
if (!ret) {
host_to_target_old_sigset(&target_set, &oset);
ret = target_set;
@@ -8836,7 +9417,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
mask = arg2;
target_to_host_old_sigset(&set, &mask);
- ret = do_sigprocmask(how, &set, &oldset);
+ ret = do_sigprocmask(cpu_env, how, &set, &oldset);
if (!is_error(ret)) {
host_to_target_old_sigset(&mask, &oldset);
ret = mask;
@@ -8870,7 +9451,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
how = 0;
set_ptr = NULL;
}
- ret = do_sigprocmask(how, set_ptr, &oldset);
+ ret = do_sigprocmask(cpu_env, how, set_ptr, &oldset);
if (!is_error(ret) && arg3) {
if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
goto efault;
@@ -8881,6 +9462,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
break;
#endif
+#ifdef TARGET_NR_rt_sigprocmask
case TARGET_NR_rt_sigprocmask:
{
int how = arg1;
@@ -8915,7 +9497,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
how = 0;
set_ptr = NULL;
}
- ret = do_sigprocmask(how, set_ptr, &oldset);
+ ret = do_sigprocmask(cpu_env, how, set_ptr, &oldset);
if (!is_error(ret) && arg3) {
if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
goto efault;
@@ -8924,6 +9506,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
}
break;
+#endif
#ifdef TARGET_NR_sigpending
case TARGET_NR_sigpending:
{
@@ -8938,6 +9521,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
break;
#endif
+#ifdef TARGET_NR_rt_sigpending
case TARGET_NR_rt_sigpending:
{
sigset_t set;
@@ -8961,6 +9545,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
}
break;
+#endif
#ifdef TARGET_NR_sigsuspend
case TARGET_NR_sigsuspend:
{
@@ -8982,6 +9567,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
break;
#endif
+#ifdef TARGET_NR_rt_sigsuspend
case TARGET_NR_rt_sigsuspend:
{
TaskState *ts = cpu->opaque;
@@ -9001,6 +9587,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
}
break;
+#endif
+#ifdef TARGET_NR_rt_sigtimedwait
case TARGET_NR_rt_sigtimedwait:
{
sigset_t set;
@@ -9038,6 +9626,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
}
break;
+#endif
+#ifdef TARGET_NR_rt_sigqueueinfo
case TARGET_NR_rt_sigqueueinfo:
{
siginfo_t uinfo;
@@ -9064,33 +9654,44 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3, &uinfo));
}
break;
+#endif
#ifdef TARGET_NR_sigreturn
case TARGET_NR_sigreturn:
- if (block_signals()) {
+ if (block_signals(cpu_env)) {
ret = -TARGET_ERESTARTSYS;
} else {
- ret = do_sigreturn(cpu_env);
+#ifdef TARGET_ABI_IRIX
+ if (!((CPUMIPSState*)cpu_env)->active_tc.gpr[4])
+ ret = do_rt_sigreturn(cpu_env);
+ else
+#endif
+ ret = do_sigreturn(cpu_env);
}
break;
#endif
+#ifdef TARGET_NR_rt_sigreturn
case TARGET_NR_rt_sigreturn:
- if (block_signals()) {
+ if (block_signals(cpu_env)) {
ret = -TARGET_ERESTARTSYS;
} else {
ret = do_rt_sigreturn(cpu_env);
}
break;
+#endif
+#ifdef TARGET_NR_sethostname
case TARGET_NR_sethostname:
if (!(p = lock_user_string(arg1)))
goto efault;
ret = get_errno(sethostname(p, arg2));
unlock_user(p, arg1, 0);
break;
+#endif
case TARGET_NR_setrlimit:
{
int resource = target_to_host_resource(arg1);
struct target_rlimit *target_rlim;
struct rlimit rlim;
+
if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
goto efault;
rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
@@ -9099,6 +9700,22 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(setrlimit(resource, &rlim));
}
break;
+#ifdef TARGET_NR_setrlimit64
+ case TARGET_NR_setrlimit64:
+ {
+ int resource = target_to_host_resource(arg1);
+ struct target_rlimit64 *target_rlim;
+ struct rlimit rlim;
+
+ if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
+ goto efault;
+ rlim.rlim_cur = target_to_host_rlim64(target_rlim->rlim_cur);
+ rlim.rlim_max = target_to_host_rlim64(target_rlim->rlim_max);
+ unlock_user_struct(target_rlim, arg2, 0);
+ ret = get_errno(setrlimit(resource, &rlim));
+ }
+ break;
+#endif
case TARGET_NR_getrlimit:
{
int resource = target_to_host_resource(arg1);
@@ -9115,6 +9732,25 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
}
break;
+#ifdef TARGET_NR_getrlimit64
+ case TARGET_NR_getrlimit64:
+ {
+ int resource = target_to_host_resource(arg1);
+ struct target_rlimit64 *target_rlim;
+ struct rlimit rlim;
+
+ ret = get_errno(getrlimit(resource, &rlim));
+ if (!is_error(ret)) {
+ if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
+ goto efault;
+ target_rlim->rlim_cur = host_to_target_rlim64(rlim.rlim_cur);
+ target_rlim->rlim_max = host_to_target_rlim64(rlim.rlim_max);
+ unlock_user_struct(target_rlim, arg2, 1);
+ }
+ }
+ break;
+#endif
+#ifdef TARGET_NR_getrusage
case TARGET_NR_getrusage:
{
struct rusage rusage;
@@ -9124,6 +9760,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
}
break;
+#endif
+#ifdef TARGET_NR_gettimeofday
case TARGET_NR_gettimeofday:
{
struct timeval tv;
@@ -9134,6 +9772,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
}
break;
+#endif
+#ifdef TARGET_NR_settimeofday
case TARGET_NR_settimeofday:
{
struct timeval tv, *ptv = NULL;
@@ -9156,6 +9796,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(settimeofday(ptv, ptz));
}
break;
+#endif
#if defined(TARGET_NR_select)
case TARGET_NR_select:
#if defined(TARGET_WANT_NI_OLD_SELECT)
@@ -9232,8 +9873,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!arg7) {
goto efault;
}
- arg_sigset = tswapal(arg7[0]);
- arg_sigsize = tswapal(arg7[1]);
+ __get_user(arg_sigset, &arg7[0]);
+ __get_user(arg_sigsize, &arg7[1]);
unlock_user(arg7, arg6, 0);
if (arg_sigset) {
@@ -9373,6 +10014,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p, arg1, 0);
break;
#endif
+#ifdef TARGET_NR_reboot
case TARGET_NR_reboot:
if (arg3 == LINUX_REBOOT_CMD_RESTART2) {
/* arg4 must be ignored in all other cases */
@@ -9386,6 +10028,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(reboot(arg1, arg2, arg3, NULL));
}
break;
+#endif
#ifdef TARGET_NR_readdir
case TARGET_NR_readdir:
goto unimplemented;
@@ -9401,25 +10044,52 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
abi_ulong v1, v2, v3, v4, v5, v6;
if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
goto efault;
- v1 = tswapal(v[0]);
- v2 = tswapal(v[1]);
- v3 = tswapal(v[2]);
- v4 = tswapal(v[3]);
- v5 = tswapal(v[4]);
- v6 = tswapal(v[5]);
+ __get_user(v1, &v[0]);
+ __get_user(v2, &v[1]);
+ __get_user(v3, &v[2]);
+ __get_user(v4, &v[3]);
+ __get_user(v5, &v[4]);
+ __get_user(v6, &v[5]);
unlock_user(v, arg1, 0);
ret = get_errno(target_mmap(v1, v2, v3,
target_to_host_bitmask(v4, mmap_flags_tbl),
v5, v6));
}
#else
+#ifdef TARGET_ABI_IRIX
+ /* TODO: no MAP_AUTOGROW in linux. as a kludge resize the file */
+ if ((arg4 & TARGET_MAP_AUTOGROW) &&
+ arg5 >= 0 && fstat(arg5, &st) >= 0 && st.st_size < arg6+arg2)
+ ret = get_errno(ftruncate(arg5, arg6+arg2));
+#endif
ret = get_errno(target_mmap(arg1, arg2, arg3,
target_to_host_bitmask(arg4, mmap_flags_tbl),
- arg5,
- arg6));
+ arg5, arg6));
#endif
break;
#endif
+#ifdef TARGET_NR_mmap64
+ case TARGET_NR_mmap64:
+ {
+ off64_t off = arg6;
+#if TARGET_ABI_BITS == 32
+ if (regpairs_aligned(cpu_env, num))
+ off = target_offset64(arg7, arg8);
+ else
+ off = target_offset64(arg6, arg7);
+#endif
+#ifdef TARGET_ABI_IRIX
+ /* TODO: no MAP_AUTOGROW in linux. as a kludge resize the file */
+ if ((arg4 & TARGET_MAP_AUTOGROW) &&
+ arg5 >= 0 && fstat(arg5, &st) >= 0 && st.st_size < off+arg2)
+ ret = get_errno(ftruncate64(arg5, off+arg2));
+#endif
+ ret = get_errno(target_mmap(arg1, arg2, arg3,
+ target_to_host_bitmask(arg4, mmap_flags_tbl),
+ arg5, off));
+ }
+ break;
+#endif
#ifdef TARGET_NR_mmap2
case TARGET_NR_mmap2:
#ifndef MMAP_SHIFT
@@ -9479,15 +10149,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(munlockall());
break;
#endif
+#ifdef TARGET_NR_truncate
case TARGET_NR_truncate:
if (!(p = lock_user_string(arg1)))
goto efault;
ret = get_errno(truncate(p, arg2));
unlock_user(p, arg1, 0);
break;
+#endif
+#ifdef TARGET_NR_ftruncate
case TARGET_NR_ftruncate:
ret = get_errno(ftruncate(arg1, arg2));
break;
+#endif
case TARGET_NR_fchmod:
ret = get_errno(fchmod(arg1, arg2));
break;
@@ -9499,6 +10173,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p, arg2, 0);
break;
#endif
+#ifdef TARGET_NR_getpriority
case TARGET_NR_getpriority:
/* Note that negative values are valid for getpriority, so we must
differentiate based on errno settings. */
@@ -9516,9 +10191,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = 20 - ret;
#endif
break;
+#endif
+#ifdef TARGET_NR_setpriority
case TARGET_NR_setpriority:
ret = get_errno(setpriority(arg1, arg2, arg3));
break;
+#endif
#ifdef TARGET_NR_profil
case TARGET_NR_profil:
goto unimplemented;
@@ -9529,11 +10207,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(statfs(path(p), &stfs));
unlock_user(p, arg1, 0);
convert_statfs:
+#if defined(TARGET_ABI_IRIX) && defined(TARGET_ABI_MIPSN32)
+ goto convert_statfs64;
+#else
if (!is_error(ret)) {
struct target_statfs *target_stfs;
-
+#ifdef TARGET_ABI_IRIX /* IRIX has a length and a fs type arg */
+ struct target_statfs tmp_stfs;
+ if (arg3 > sizeof(tmp_stfs))
+ arg3 = sizeof(tmp_stfs);
+ target_stfs = &tmp_stfs;
+#else
if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
goto efault;
+#endif
__put_user(stfs.f_type, &target_stfs->f_type);
__put_user(stfs.f_bsize, &target_stfs->f_bsize);
__put_user(stfs.f_blocks, &target_stfs->f_blocks);
@@ -9546,8 +10233,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
__put_user(stfs.f_namelen, &target_stfs->f_namelen);
__put_user(stfs.f_frsize, &target_stfs->f_frsize);
memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
+#ifdef TARGET_ABI_IRIX
+ ret = copy_to_user(arg2, target_stfs, arg3);
+#else
unlock_user_struct(target_stfs, arg2, 1);
+#endif
}
+#endif
break;
case TARGET_NR_fstatfs:
ret = get_errno(fstatfs(arg1, &stfs));
@@ -9558,12 +10250,21 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
goto efault;
ret = get_errno(statfs(path(p), &stfs));
unlock_user(p, arg1, 0);
+#endif
+#if defined(TARGET_NR_statfs64) || (defined(TARGET_ABI_IRIX) && defined(TARGET_ABI_MIPSN32))
convert_statfs64:
if (!is_error(ret)) {
struct target_statfs64 *target_stfs;
+#ifdef TARGET_ABI_IRIX /* IRIX has a length and a fs type arg */
+ struct target_statfs64 tmp_stfs;
+ if (arg3 > sizeof(tmp_stfs))
+ arg3 = sizeof(tmp_stfs);
+ target_stfs = &tmp_stfs;
+#else
if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
goto efault;
+#endif
__put_user(stfs.f_type, &target_stfs->f_type);
__put_user(stfs.f_bsize, &target_stfs->f_bsize);
__put_user(stfs.f_blocks, &target_stfs->f_blocks);
@@ -9576,9 +10277,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
__put_user(stfs.f_namelen, &target_stfs->f_namelen);
__put_user(stfs.f_frsize, &target_stfs->f_frsize);
memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
+#ifdef TARGET_ABI_IRIX
+ ret = copy_to_user(arg2, target_stfs, arg3);
+#else
unlock_user_struct(target_stfs, arg3, 1);
+#endif
}
break;
+#endif
+#ifdef TARGET_NR_fstatfs64
case TARGET_NR_fstatfs64:
ret = get_errno(fstatfs(arg1, &stfs));
goto convert_statfs64;
@@ -9587,6 +10294,74 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_ioperm:
goto unimplemented;
#endif
+#ifdef TARGET_NR_fstatvfs
+ case TARGET_NR_fstatvfs:
+ ret = get_errno(fstatvfs(arg1, &stvfs));
+ goto convert_statvfs;
+#endif
+#ifdef TARGET_NR_statvfs
+ case TARGET_NR_statvfs:
+ if (!(p = lock_user_string(arg1)))
+ goto efault;
+ ret = get_errno(statvfs(path(p), &stvfs));
+ unlock_user(p, arg1, 0);
+
+ convert_statvfs:
+ if (!is_error(ret)) {
+ {
+ struct target_statvfs *target_stvfs;
+
+ if (!lock_user_struct(VERIFY_WRITE, target_stvfs, arg2, 0))
+ goto efault;
+ __put_user(stvfs.f_bsize, &target_stvfs->f_bsize);
+ __put_user(stvfs.f_frsize, &target_stvfs->f_frsize);
+ __put_user(stvfs.f_blocks, &target_stvfs->f_blocks);
+ __put_user(stvfs.f_bfree, &target_stvfs->f_bfree);
+ __put_user(stvfs.f_bavail, &target_stvfs->f_bavail);
+ __put_user(stvfs.f_files, &target_stvfs->f_files);
+ __put_user(stvfs.f_ffree, &target_stvfs->f_ffree);
+ __put_user(stvfs.f_favail, &target_stvfs->f_favail);
+ __put_user(stvfs.f_fsid, &target_stvfs->f_fsid);
+ __put_user(stvfs.f_flag, &target_stvfs->f_flag);
+ __put_user(stvfs.f_namemax, &target_stvfs->f_namemax);
+ unlock_user_struct(target_stvfs, arg2, 1);
+ }
+ }
+ break;
+#ifdef TARGET_NR_fstatvfs64
+ case TARGET_NR_fstatvfs64:
+ ret = get_errno(fstatvfs(arg1, &stvfs));
+ goto convert_statvfs64;
+#endif
+#ifdef TARGET_NR_statvfs64
+ case TARGET_NR_statvfs64:
+ if (!(p = lock_user_string(arg1)))
+ goto efault;
+ ret = get_errno(statvfs(path(p), &stvfs));
+ unlock_user(p, arg1, 0);
+
+ convert_statvfs64:
+ if (!is_error(ret)) {
+ struct target_statvfs64 *target_stvfs;
+
+ if (!lock_user_struct(VERIFY_WRITE, target_stvfs, arg2, 0))
+ goto efault;
+ __put_user(stvfs.f_bsize, &target_stvfs->f_bsize);
+ __put_user(stvfs.f_frsize, &target_stvfs->f_frsize);
+ __put_user(stvfs.f_blocks, &target_stvfs->f_blocks);
+ __put_user(stvfs.f_bfree, &target_stvfs->f_bfree);
+ __put_user(stvfs.f_bavail, &target_stvfs->f_bavail);
+ __put_user(stvfs.f_files, &target_stvfs->f_files);
+ __put_user(stvfs.f_ffree, &target_stvfs->f_ffree);
+ __put_user(stvfs.f_favail, &target_stvfs->f_favail);
+ __put_user(stvfs.f_fsid, &target_stvfs->f_fsid);
+ __put_user(stvfs.f_flag, &target_stvfs->f_flag);
+ __put_user(stvfs.f_namemax, &target_stvfs->f_namemax);
+ unlock_user_struct(target_stvfs, arg2, 1);
+ }
+ break;
+#endif
+#endif
#ifdef TARGET_NR_socketcall
case TARGET_NR_socketcall:
ret = do_socketcall(arg1, arg2);
@@ -9783,6 +10558,51 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
}
break;
+#ifdef TARGET_NR_xstat
+ case TARGET_NR_xstat:
+ if (!(p = lock_user_string(arg2)))
+ goto efault;
+#ifdef TARGET_ABI_IRIX
+ /* TODO: IRIX creates a virtual semaphore file, and libc checks it with
+ * xstat :-( As a kludge, check here for a named semaphore and return
+ * fake stat information. */
+ ret = psema_get_index(p, NULL, 0);
+ if (ret >= 0) {
+ memset(&st, 0, sizeof(st));
+ st.st_ino = ret; /* generate fake stat info for a semaphore */
+ } else
+#endif
+ ret = get_errno(stat(path(p), &st));
+ unlock_user(p, arg2, 0);
+ goto do_xstat;
+#endif
+#ifdef TARGET_NR_lxstat
+ case TARGET_NR_lxstat:
+ if (!(p = lock_user_string(arg2)))
+ goto efault;
+ ret = get_errno(lstat(path(p), &st));
+ unlock_user(p, arg2, 0);
+ goto do_xstat;
+#endif
+#ifdef TARGET_NR_fxstat
+ case TARGET_NR_fxstat:
+ ret = get_errno(fstat(arg2, &st));
+ goto do_xstat;
+#endif
+#if defined TARGET_ABI_IRIX || defined TARGET_ABI_SOLARIS
+ do_xstat:
+#if defined(TARGET_ABI_IRIX) && defined(TARGET_ABI_MIPSN32)
+ arg1 = TARGET_STAT64_VER;
+#endif
+#if defined(TARGET_ABI_IRIX) && TARGET_ABI_BITS == 32
+ if (!is_error(ret) && arg1 == TARGET_STAT64_VER) {
+ ret = host_to_target_stat64(cpu_env, arg3, &st);
+ break;
+ }
+#endif
+ arg2 = arg3;
+ goto do_stat;
+#endif
#ifdef TARGET_NR_stat
case TARGET_NR_stat:
if (!(p = lock_user_string(arg1)))
@@ -9799,35 +10619,24 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p, arg1, 0);
goto do_stat;
#endif
+#ifdef TARGET_NR_fstat
case TARGET_NR_fstat:
- {
- ret = get_errno(fstat(arg1, &st));
-#if defined(TARGET_NR_stat) || defined(TARGET_NR_lstat)
- do_stat:
+ ret = get_errno(fstat(arg1, &st));
+ goto do_stat;
#endif
- if (!is_error(ret)) {
- struct target_stat *target_st;
-
- if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
- goto efault;
- memset(target_st, 0, sizeof(*target_st));
- __put_user(st.st_dev, &target_st->st_dev);
- __put_user(st.st_ino, &target_st->st_ino);
- __put_user(st.st_mode, &target_st->st_mode);
- __put_user(st.st_uid, &target_st->st_uid);
- __put_user(st.st_gid, &target_st->st_gid);
- __put_user(st.st_nlink, &target_st->st_nlink);
- __put_user(st.st_rdev, &target_st->st_rdev);
- __put_user(st.st_size, &target_st->st_size);
- __put_user(st.st_blksize, &target_st->st_blksize);
- __put_user(st.st_blocks, &target_st->st_blocks);
- __put_user(st.st_atime, &target_st->target_st_atime);
- __put_user(st.st_mtime, &target_st->target_st_mtime);
- __put_user(st.st_ctime, &target_st->target_st_ctime);
- unlock_user_struct(target_st, arg2, 1);
- }
+ do_stat:
+ if (!is_error(ret)) {
+ ret = host_to_target_stat(cpu_env, arg2, &st);
}
break;
+#ifdef TARGET_NR_fstatat
+ case TARGET_NR_fstatat:
+ if (!(p = lock_user_string(arg2)))
+ goto efault;
+ ret = get_errno(fstatat(arg1, path(p), &st, arg4));
+ unlock_user(p, arg2, 0);
+ goto do_stat;
+#endif
#ifdef TARGET_NR_olduname
case TARGET_NR_olduname:
goto unimplemented;
@@ -9849,6 +10658,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
arg6, arg7, arg8, 0);
break;
#endif
+#ifdef TARGET_NR_wait4
case TARGET_NR_wait4:
{
int status;
@@ -9876,6 +10686,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
}
break;
+#endif
#ifdef TARGET_NR_swapoff
case TARGET_NR_swapoff:
if (!(p = lock_user_string(arg1)))
@@ -9884,6 +10695,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user(p, arg1, 0);
break;
#endif
+#ifdef TARGET_NR_sysinfo
case TARGET_NR_sysinfo:
{
struct target_sysinfo *target_value;
@@ -9911,6 +10723,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
}
break;
+#endif
#ifdef TARGET_NR_ipc
case TARGET_NR_ipc:
ret = do_ipc(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
@@ -9971,9 +10784,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = do_shmdt(arg1);
break;
#endif
+#ifdef TARGET_NR_fsync
case TARGET_NR_fsync:
ret = get_errno(fsync(arg1));
break;
+#endif
+#ifdef TARGET_NR_clone
case TARGET_NR_clone:
/* Linux manages to have three different orderings for its
* arguments to clone(); the BACKWARDS and BACKWARDS2 defines
@@ -9982,16 +10798,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
* implicit argument to clone for the TLS pointer.
*/
#if defined(TARGET_MICROBLAZE)
- ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5));
+ ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5, 0, 0));
#elif defined(TARGET_CLONE_BACKWARDS)
- ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
+ ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5, 0, 0));
#elif defined(TARGET_CLONE_BACKWARDS2)
- ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
+ ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4, 0, 0));
#else
- ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
+ ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4, 0, 0));
#endif
break;
-#ifdef __NR_exit_group
+#endif
+#if defined __NR_exit_group && defined TARGET_NR_exit_group
/* new thread calls */
case TARGET_NR_exit_group:
#ifdef TARGET_GPROF
@@ -10001,12 +10818,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(exit_group(arg1));
break;
#endif
+#ifdef TARGET_NR_setdomainname
case TARGET_NR_setdomainname:
if (!(p = lock_user_string(arg1)))
goto efault;
ret = get_errno(setdomainname(p, arg2));
unlock_user(p, arg1, 0);
break;
+#endif
+#ifdef TARGET_NR_uname
case TARGET_NR_uname:
/* no need to transcode because we use the linux syscall */
{
@@ -10028,6 +10848,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
unlock_user_struct(buf, arg1, 1);
}
break;
+#endif
#ifdef TARGET_I386
case TARGET_NR_modify_ldt:
ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
@@ -10040,6 +10861,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
break;
#endif
#endif
+#ifdef TARGET_NR_adjtimex
case TARGET_NR_adjtimex:
{
struct timex host_buf;
@@ -10055,6 +10877,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
}
break;
+#endif
#if defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME)
case TARGET_NR_clock_adjtime:
{
@@ -10074,18 +10897,23 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif
#ifdef TARGET_NR_create_module
case TARGET_NR_create_module:
-#endif
case TARGET_NR_init_module:
case TARGET_NR_delete_module:
+ goto unimplemented;
+#endif
#ifdef TARGET_NR_get_kernel_syms
case TARGET_NR_get_kernel_syms:
-#endif
goto unimplemented;
+#endif
+#ifdef TARGET_NR_quotactl
case TARGET_NR_quotactl:
goto unimplemented;
+#endif
+#ifdef TARGET_NR_getpgid
case TARGET_NR_getpgid:
ret = get_errno(getpgid(arg1));
break;
+#endif
case TARGET_NR_fchdir:
ret = get_errno(fchdir(arg1));
break;
@@ -10097,9 +10925,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_sysfs:
goto unimplemented;
#endif
+#ifdef TARGET_NR_personality
case TARGET_NR_personality:
ret = get_errno(personality(arg1));
break;
+#endif
#ifdef TARGET_NR_afs_syscall
case TARGET_NR_afs_syscall:
goto unimplemented;
@@ -10108,26 +10938,36 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR__llseek:
{
int64_t res;
+#ifdef TARGET_ABI_SOLARIS
+ int whence = arg4; /* no "loff_t *result" on Solaris */
+#else
+ int whence = arg5;
+#endif
#if !defined(__NR_llseek)
- res = lseek(arg1, ((uint64_t)arg2 << 32) | (abi_ulong)arg3, arg5);
+ /* llseek has 2 args for offset, so no target_offset64 here */
+ res = lseek(arg1, ((uint64_t)arg2 << 32) | (abi_ulong)arg3, whence);
if (res == -1) {
ret = get_errno(res);
} else {
ret = 0;
}
#else
- ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
+ ret = get_errno(_llseek(arg1, arg2, arg3, &res, whence));
#endif
+#ifndef TARGET_ABI_SOLARIS
if ((ret == 0) && put_user_s64(res, arg4)) {
goto efault;
}
+#endif
}
break;
#endif
+#ifdef TARGET_NR_ngetdents
+ case TARGET_NR_ngetdents:
+#endif
#ifdef TARGET_NR_getdents
case TARGET_NR_getdents:
#ifdef __NR_getdents
-#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
{
struct target_dirent *target_dirp;
struct linux_dirent *dirp;
@@ -10155,12 +10995,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
while (len > 0) {
reclen = de->d_reclen;
tnamelen = reclen - offsetof(struct linux_dirent, d_name);
+ tnamelen = strnlen(de->d_name, tnamelen) + 1;
assert(tnamelen >= 0);
treclen = tnamelen + offsetof(struct target_dirent, d_name);
- assert(count1 + treclen <= count);
- tde->d_reclen = tswap16(treclen);
- tde->d_ino = tswapal(de->d_ino);
- tde->d_off = tswapal(de->d_off);
+ /* XXX: avoid buffer overflow, for the price of lost entries */
+ if (count1 + treclen > count)
+ break;
+ __put_user(treclen, &tde->d_reclen);
+ __put_user(de->d_ino, &tde->d_ino);
+ __put_user(de->d_off, &tde->d_off);
memcpy(tde->d_name, de->d_name, tnamelen);
de = (struct linux_dirent *)((char *)de + reclen);
len -= reclen;
@@ -10172,33 +11015,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
g_free(dirp);
}
-#else
- {
- struct linux_dirent *dirp;
- abi_long count = arg3;
-
- if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
- goto efault;
- ret = get_errno(sys_getdents(arg1, dirp, count));
- if (!is_error(ret)) {
- struct linux_dirent *de;
- int len = ret;
- int reclen;
- de = dirp;
- while (len > 0) {
- reclen = de->d_reclen;
- if (reclen > len)
- break;
- de->d_reclen = tswap16(reclen);
- tswapls(&de->d_ino);
- tswapls(&de->d_off);
- de = (struct linux_dirent *)((char *)de + reclen);
- len -= reclen;
- }
- }
- unlock_user(dirp, arg2, ret);
- }
-#endif
#else
/* Implement getdents in terms of getdents64 */
{
@@ -10230,20 +11046,22 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
int64_t off = de->d_off;
uint8_t type = de->d_type;
- namelen = strlen(de->d_name);
+ namelen = de->d_reclen - offsetof(struct linux_dirent64, d_name);
+ namelen = strnlen(de->d_name, namelen);
treclen = offsetof(struct target_dirent, d_name)
+ namelen + 2;
treclen = QEMU_ALIGN_UP(treclen, sizeof(abi_long));
memmove(tde->d_name, de->d_name, namelen + 1);
- tde->d_ino = tswapal(ino);
- tde->d_off = tswapal(off);
- tde->d_reclen = tswap16(treclen);
+ __put_user(ino, &tde->d_ino);
+ __put_user(off, &tde->d_off);
+ __put_user(treclen, &tde->d_reclen);
+#if !defined TARGET_ABI_IRIX && !defined TARGET_ABI_SOLARIS
/* The target_dirent type is in what was formerly a padding
* byte at the end of the structure:
*/
*(((char *)tde) + treclen - 1) = type;
-
+#endif
de = (struct linux_dirent64 *)((char *)de + reclen);
tde = (struct target_dirent *)((char *)tde + treclen);
len -= reclen;
@@ -10253,11 +11071,71 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
unlock_user(dirp, arg2, ret);
}
+#endif
+#ifdef TARGET_NR_ngetdents
+ if (ret >= 0 && num == TARGET_NR_ngetdents) {
+ abi_long *p = lock_user(VERIFY_WRITE, arg4, sizeof(abi_long), 0);
+ __put_user(ret == 0, &p);
+ unlock_user(p, arg4, 0);
+ }
#endif
break;
#endif /* TARGET_NR_getdents */
+#ifdef TARGET_NR_ngetdents64
+ case TARGET_NR_ngetdents64:
+#endif
#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
case TARGET_NR_getdents64:
+#if defined TARGET_ABI_IRIX || defined TARGET_ABI_SOLARIS
+ {
+ struct target_dirent64 *target_dirp;
+ struct linux_dirent64 *dirp;
+ abi_long count = arg3;
+
+ dirp = malloc(count);
+ if (!dirp) {
+ ret = -TARGET_ENOMEM;
+ goto fail;
+ }
+
+ ret = get_errno(sys_getdents64(arg1, dirp, count));
+ if (!is_error(ret)) {
+ struct linux_dirent64 *de;
+ struct target_dirent64 *tde;
+ int len = ret;
+ int reclen, treclen;
+ int count1, tnamelen;
+
+ count1 = 0;
+ de = dirp;
+ if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
+ goto efault;
+ tde = target_dirp;
+ while (len > 0) {
+ reclen = de->d_reclen;
+ tnamelen = reclen - offsetof(struct linux_dirent64, d_name);
+ tnamelen = strnlen(de->d_name, tnamelen) + 1;
+ assert(tnamelen > 0);
+ treclen = tnamelen + offsetof(struct target_dirent64, d_name);
+ treclen = QEMU_ALIGN_UP(treclen, sizeof(abi_llong));
+ /* XXX: avoid buffer overflow, for the price of lost entries */
+ if (count1 + treclen > count)
+ break;
+ __put_user(treclen, &tde->d_reclen);
+ __put_user(de->d_ino, &tde->d_ino);
+ __put_user(de->d_off, &tde->d_off);
+ memcpy(tde->d_name, de->d_name, tnamelen);
+ de = (struct linux_dirent64 *)((char *)de + reclen);
+ len -= reclen;
+ tde = (struct target_dirent64 *)((char *)tde + treclen);
+ count1 += treclen;
+ }
+ ret = count1;
+ unlock_user(target_dirp, arg2, ret);
+ }
+ free(dirp);
+ }
+#else
{
struct linux_dirent64 *dirp;
abi_long count = arg3;
@@ -10273,7 +11151,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
reclen = de->d_reclen;
if (reclen > len)
break;
- de->d_reclen = tswap16(reclen);
+ __put_user(reclen, &de->d_reclen);
tswap64s((uint64_t *)&de->d_ino);
tswap64s((uint64_t *)&de->d_off);
de = (struct linux_dirent64 *)((char *)de + reclen);
@@ -10282,6 +11160,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
unlock_user(dirp, arg2, ret);
}
+#endif
+#ifdef TARGET_NR_ngetdents64
+ if (ret >= 0 && num == TARGET_NR_ngetdents64) {
+ abi_long *p = lock_user(VERIFY_WRITE, arg4, sizeof(abi_long), 0);
+ __put_user(ret == 0, &p);
+ unlock_user(p, arg4, 0);
+ }
+#endif
break;
#endif /* TARGET_NR_getdents64 */
#if defined(TARGET_NR__newselect)
@@ -10318,8 +11204,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
pfd = alloca(sizeof(struct pollfd) * nfds);
for (i = 0; i < nfds; i++) {
- pfd[i].fd = tswap32(target_pfd[i].fd);
- pfd[i].events = tswap16(target_pfd[i].events);
+ __get_user(pfd[i].fd, &target_pfd[i].fd);
+ __get_user(pfd[i].events, &target_pfd[i].events);
}
}
@@ -10393,18 +11279,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!is_error(ret)) {
for(i = 0; i < nfds; i++) {
- target_pfd[i].revents = tswap16(pfd[i].revents);
+ __put_user(pfd[i].revents, &target_pfd[i].revents);
}
}
unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds);
}
break;
#endif
+#ifdef TARGET_NR_flock
case TARGET_NR_flock:
/* NOTE: the flock constant seems to be the same for every
Linux platform */
ret = get_errno(safe_flock(arg1, arg2));
break;
+#endif
case TARGET_NR_readv:
{
struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
@@ -10453,10 +11341,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
break;
#endif
+#ifdef TARGET_NR_getsid
case TARGET_NR_getsid:
ret = get_errno(getsid(arg1));
break;
-#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
+#endif
+#ifdef TARGET_NR_fdatasync /* Not on alpha (osf_datasync ?) */
case TARGET_NR_fdatasync:
ret = get_errno(fdatasync(arg1));
break;
@@ -10468,6 +11358,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = -TARGET_ENOTDIR;
break;
#endif
+#ifdef TARGET_NR_sched_getaffinity
case TARGET_NR_sched_getaffinity:
{
unsigned int mask_size;
@@ -10534,6 +11425,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
}
break;
+#endif
+#ifdef TARGET_NR_getcpu
case TARGET_NR_getcpu:
{
unsigned cpu, node;
@@ -10551,6 +11444,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
}
break;
+#endif
+#ifdef TARGET_NR_sched_setparam
case TARGET_NR_sched_setparam:
{
struct sched_param *target_schp;
@@ -10561,7 +11456,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
goto efault;
- schp.sched_priority = tswap32(target_schp->sched_priority);
+ __get_user(schp.sched_priority, &target_schp->sched_priority);
unlock_user_struct(target_schp, arg2, 0);
ret = get_errno(sched_setparam(arg1, &schp));
}
@@ -10578,7 +11473,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!is_error(ret)) {
if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
goto efault;
- target_schp->sched_priority = tswap32(schp.sched_priority);
+ __put_user(schp.sched_priority, &target_schp->sched_priority);
unlock_user_struct(target_schp, arg2, 1);
}
}
@@ -10592,7 +11487,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
goto efault;
- schp.sched_priority = tswap32(target_schp->sched_priority);
+ __get_user(schp.sched_priority, &target_schp->sched_priority);
unlock_user_struct(target_schp, arg3, 0);
ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
}
@@ -10603,12 +11498,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_sched_yield:
ret = get_errno(sched_yield());
break;
+#ifdef TARGET_NR_sched_get_priority_max
case TARGET_NR_sched_get_priority_max:
ret = get_errno(sched_get_priority_max(arg1));
break;
case TARGET_NR_sched_get_priority_min:
ret = get_errno(sched_get_priority_min(arg1));
break;
+#endif
case TARGET_NR_sched_rr_get_interval:
{
struct timespec ts;
@@ -10618,6 +11515,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
}
break;
+#endif
case TARGET_NR_nanosleep:
{
struct timespec req, rem;
@@ -10636,6 +11534,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_nfsservctl:
goto unimplemented;
#endif
+#ifdef TARGET_NR_prctl
case TARGET_NR_prctl:
switch (arg1) {
case PR_GET_PDEATHSIG:
@@ -10684,6 +11583,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
break;
}
break;
+#endif
#ifdef TARGET_NR_arch_prctl
case TARGET_NR_arch_prctl:
#if defined(TARGET_I386) && !defined(TARGET_ABI32)
@@ -10695,32 +11595,59 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif
#ifdef TARGET_NR_pread64
case TARGET_NR_pread64:
- if (regpairs_aligned(cpu_env, num)) {
- arg4 = arg5;
- arg5 = arg6;
+ {
+ int64_t off = arg4;
+ if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
+ goto efault;
+#if TARGET_ABI_BITS == 32
+ if (regpairs_aligned(cpu_env, num))
+ off = target_offset64(arg5, arg6);
+ else
+ off = target_offset64(arg4, arg5);
+#endif
+ ret = get_errno(pread64(arg1, p, arg3, off));
+ unlock_user(p, arg2, ret);
}
- if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
- goto efault;
- ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
- unlock_user(p, arg2, ret);
break;
case TARGET_NR_pwrite64:
- if (regpairs_aligned(cpu_env, num)) {
- arg4 = arg5;
- arg5 = arg6;
+ {
+ int64_t off = arg4;
+ if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
+ goto efault;
+#if TARGET_ABI_BITS == 32
+ if (regpairs_aligned(cpu_env, num))
+ off = target_offset64(arg5, arg6);
+ else
+ off = target_offset64(arg4, arg5);
+#endif
+ ret = get_errno(pwrite64(arg1, p, arg3, off));
+ unlock_user(p, arg2, 0);
}
+ break;
+#endif
+#ifdef TARGET_NR_pread
+ case TARGET_NR_pread:
+ if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
+ goto efault;
+ ret = get_errno(pread(arg1, p, arg3, arg4));
+ unlock_user(p, arg2, ret);
+ break;
+ case TARGET_NR_pwrite:
if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
goto efault;
- ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
+ ret = get_errno(pwrite64(arg1, p, arg3, arg4));
unlock_user(p, arg2, 0);
break;
#endif
+#ifdef TARGET_NR_getcwd
case TARGET_NR_getcwd:
if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
goto efault;
ret = get_errno(sys_getcwd1(p, arg2));
unlock_user(p, arg1, ret);
break;
+#endif
+#ifdef TARGET_NR_capget
case TARGET_NR_capget:
case TARGET_NR_capset:
{
@@ -10735,8 +11662,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!lock_user_struct(VERIFY_WRITE, target_header, arg1, 1)) {
goto efault;
}
- header.version = tswap32(target_header->version);
- header.pid = tswap32(target_header->pid);
+ __get_user(header.version, &target_header->version);
+ __get_user(header.pid, &target_header->pid);
if (header.version != _LINUX_CAPABILITY_VERSION) {
/* Version 2 and up takes pointer to two user_data structs */
@@ -10758,9 +11685,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (num == TARGET_NR_capset) {
for (i = 0; i < data_items; i++) {
- data[i].effective = tswap32(target_data[i].effective);
- data[i].permitted = tswap32(target_data[i].permitted);
- data[i].inheritable = tswap32(target_data[i].inheritable);
+ __get_user(data[i].effective, &target_data[i].effective);
+ __get_user(data[i].permitted, &target_data[i].permitted);
+ __get_user(data[i].inheritable, &target_data[i].inheritable);
}
}
@@ -10774,15 +11701,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
/* The kernel always updates version for both capget and capset */
- target_header->version = tswap32(header.version);
+ __put_user(header.version, &target_header->version);
unlock_user_struct(target_header, arg1, 1);
if (arg2) {
if (num == TARGET_NR_capget) {
for (i = 0; i < data_items; i++) {
- target_data[i].effective = tswap32(data[i].effective);
- target_data[i].permitted = tswap32(data[i].permitted);
- target_data[i].inheritable = tswap32(data[i].inheritable);
+ __put_user(data[i].effective, &target_data[i].effective);
+ __put_user(data[i].permitted, &target_data[i].permitted);
+ __put_user(data[i].inheritable, &target_data[i].inheritable);
}
unlock_user(target_data, arg2, target_datalen);
} else {
@@ -10791,11 +11718,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
break;
}
+#endif
case TARGET_NR_sigaltstack:
- ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUArchState *)cpu_env));
+ ret = do_sigaltstack(cpu_env, arg1, arg2, get_sp_from_cpustate((CPUArchState *)cpu_env));
break;
#ifdef CONFIG_SENDFILE
+#ifdef TARGET_NR_sendfile
case TARGET_NR_sendfile:
{
off_t *offp = NULL;
@@ -10816,6 +11745,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
break;
}
+#endif
#ifdef TARGET_NR_sendfile64
case TARGET_NR_sendfile64:
{
@@ -10858,7 +11788,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_vfork:
ret = get_errno(do_fork(cpu_env,
CLONE_VFORK | CLONE_VM | TARGET_SIGCHLD,
- 0, 0, 0, 0));
+ 0, 0, 0, 0, 0, 0));
break;
#endif
#ifdef TARGET_NR_ugetrlimit
@@ -10942,11 +11872,23 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif
#ifdef TARGET_NR_getuid
case TARGET_NR_getuid:
+#ifdef TARGET_ABI_SOLARIS
+ ((CPUSPARCState*)cpu_env)->regwptr[1] = high2lowuid(geteuid());
+#endif
+#ifdef TARGET_ABI_IRIX
+ ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = high2lowuid(geteuid());
+#endif
ret = get_errno(high2lowuid(getuid()));
break;
#endif
#ifdef TARGET_NR_getgid
case TARGET_NR_getgid:
+#ifdef TARGET_ABI_SOLARIS
+ ((CPUSPARCState*)cpu_env)->regwptr[1] = high2lowuid(getegid());
+#endif
+#ifdef TARGET_ABI_IRIX
+ ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = high2lowuid(getegid());
+#endif
ret = get_errno(high2lowgid(getgid()));
break;
#endif
@@ -10966,6 +11908,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_setregid:
ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
break;
+#ifdef TARGET_NR_getgroups
case TARGET_NR_getgroups:
{
int gidsetsize = arg1;
@@ -11008,6 +11951,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(setgroups(gidsetsize, grouplist));
}
break;
+#endif
case TARGET_NR_fchown:
ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
break;
@@ -11071,18 +12015,27 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
break;
#endif
case TARGET_NR_setuid:
- ret = get_errno(sys_setuid(low2highuid(arg1)));
+ ret = get_errno(setuid(low2highuid(arg1)));
break;
case TARGET_NR_setgid:
- ret = get_errno(sys_setgid(low2highgid(arg1)));
+ ret = get_errno(setgid(low2highgid(arg1)));
break;
+#ifdef TARGET_NR_seteuid
+ case TARGET_NR_seteuid:
+ ret = get_errno(seteuid(low2highuid(arg1)));
+ break;
+ case TARGET_NR_setegid:
+ ret = get_errno(setegid(low2highgid(arg1)));
+ break;
+#endif
+#ifdef TARGET_NR_setfsuid
case TARGET_NR_setfsuid:
ret = get_errno(setfsuid(arg1));
break;
case TARGET_NR_setfsgid:
ret = get_errno(setfsgid(arg1));
break;
-
+#endif
#ifdef TARGET_NR_lchown32
case TARGET_NR_lchown32:
if (!(p = lock_user_string(arg1)))
@@ -11228,7 +12181,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
if (si_code != 0) {
target_siginfo_t info;
- info.si_signo = SIGFPE;
+ info.si_signo = TARGET_SIGFPE;
info.si_errno = 0;
info.si_code = si_code;
info._sifields._sigfault._addr
@@ -11272,7 +12225,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
mask = arg2;
target_to_host_old_sigset(&set, &mask);
- ret = do_sigprocmask(how, &set, &oldset);
+ ret = do_sigprocmask(cpu_env, how, &set, &oldset);
if (!ret) {
host_to_target_old_sigset(&mask, &oldset);
ret = mask;
@@ -11280,7 +12233,6 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
break;
#endif
-
#ifdef TARGET_NR_getgid32
case TARGET_NR_getgid32:
ret = get_errno(getgid());
@@ -11325,7 +12277,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
goto fail;
}
for(i = 0;i < ret; i++)
- target_grouplist[i] = tswap32(grouplist[i]);
+ __put_user(grouplist[i], &target_grouplist[i]);
unlock_user(target_grouplist, arg2, gidsetsize * 4);
}
}
@@ -11346,7 +12298,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
goto fail;
}
for(i = 0;i < gidsetsize; i++)
- grouplist[i] = tswap32(target_grouplist[i]);
+ __get_user(grouplist[i], &target_grouplist[i]);
unlock_user(target_grouplist, arg2, 0);
ret = get_errno(setgroups(gidsetsize, grouplist));
}
@@ -11423,9 +12375,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(setfsgid(arg1));
break;
#endif
-
+#ifdef TARGET_NR_pivot_root
case TARGET_NR_pivot_root:
goto unimplemented;
+#endif
#ifdef TARGET_NR_mincore
case TARGET_NR_mincore:
{
@@ -11538,7 +12491,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(0);
break;
#endif
-#if TARGET_ABI_BITS == 32
+#if TARGET_ABI_BITS == 32 && defined TARGET_NR_fcntl64
case TARGET_NR_fcntl64:
{
int cmd;
@@ -11601,18 +12554,18 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = TARGET_PAGE_SIZE;
break;
#endif
+#ifdef TARGET_NR_gettid
case TARGET_NR_gettid:
ret = get_errno(gettid());
break;
+#endif
#ifdef TARGET_NR_readahead
case TARGET_NR_readahead:
#if TARGET_ABI_BITS == 32
- if (regpairs_aligned(cpu_env, num)) {
- arg2 = arg3;
- arg3 = arg4;
- arg4 = arg5;
- }
- ret = get_errno(readahead(arg1, target_offset64(arg2, arg3) , arg4));
+ if (regpairs_aligned(cpu_env, num))
+ ret = get_errno(readahead(arg1, target_offset64(arg3, arg4), arg5));
+ else
+ ret = get_errno(readahead(arg1, target_offset64(arg2, arg3), arg4));
#else
ret = get_errno(readahead(arg1, arg2, arg3));
#endif
@@ -11831,7 +12784,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#endif
#ifdef TARGET_NR_getdomainname
case TARGET_NR_getdomainname:
- goto unimplemented_nowarn;
+ if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
+ goto efault;
+ ret = get_errno(getdomainname(p, arg2));
+ unlock_user(p, arg1, arg2);
+ break;
#endif
#ifdef TARGET_NR_clock_gettime
@@ -11882,15 +12839,18 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(set_tid_address((int *)g2h(arg1)));
break;
#endif
-
+#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
case TARGET_NR_tkill:
ret = get_errno(safe_tkill((int)arg1, target_to_host_signal(arg2)));
break;
+#endif
+#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
case TARGET_NR_tgkill:
ret = get_errno(safe_tgkill((int)arg1, (int)arg2,
target_to_host_signal(arg3)));
break;
+#endif
#ifdef TARGET_NR_set_robust_list
case TARGET_NR_set_robust_list:
@@ -11934,9 +12894,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
break;
#endif
+#ifdef TARGET_NR_futex
case TARGET_NR_futex:
ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
break;
+#endif
#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
case TARGET_NR_inotify_init:
ret = get_errno(sys_inotify_init());
@@ -12155,13 +13117,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#if defined(TARGET_NR_sync_file_range)
case TARGET_NR_sync_file_range:
#if TARGET_ABI_BITS == 32
-#if defined(TARGET_MIPS)
- ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
- target_offset64(arg5, arg6), arg7));
-#else
- ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
- target_offset64(arg4, arg5), arg6));
-#endif /* !TARGET_MIPS */
+ if (regpairs_aligned(cpu_env, num))
+ ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
+ target_offset64(arg5, arg6), arg7));
+ else
+ ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
+ target_offset64(arg4, arg5), arg6));
#else
ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
#endif
@@ -12210,12 +13171,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) {
goto efault;
}
- ep.events = tswap32(target_ep->events);
+ __get_user(ep.events, &target_ep->events);
/* The epoll_data_t union is just opaque data to the kernel,
* so we transfer all 64 bits across and need not worry what
* actual data type it is.
*/
- ep.data.u64 = tswap64(target_ep->data.u64);
+ __get_user(ep.data.u64, &target_ep->data.u64);
unlock_user_struct(target_ep, arg4, 0);
epp = &ep;
}
@@ -12298,8 +13259,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!is_error(ret)) {
int i;
for (i = 0; i < ret; i++) {
- target_ep[i].events = tswap32(ep[i].events);
- target_ep[i].data.u64 = tswap64(ep[i].data.u64);
+ __put_user(ep[i].events, &target_ep[i].events);
+ __put_user(ep[i].data.u64, &target_ep[i].data.u64);
}
unlock_user(target_ep, arg2,
ret * sizeof(struct target_epoll_event));
@@ -12322,8 +13283,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) {
goto efault;
}
- rnew.rlim_cur = tswap64(target_rnew->rlim_cur);
- rnew.rlim_max = tswap64(target_rnew->rlim_max);
+ __get_user(rnew.rlim_cur, &target_rnew->rlim_cur);
+ __get_user(rnew.rlim_max, &target_rnew->rlim_max);
unlock_user_struct(target_rnew, arg3, 0);
rnewp = &rnew;
}
@@ -12333,8 +13294,8 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) {
goto efault;
}
- target_rold->rlim_cur = tswap64(rold.rlim_cur);
- target_rold->rlim_max = tswap64(rold.rlim_max);
+ __put_user(rold.rlim_cur, &target_rold->rlim_cur);
+ __put_user(rold.rlim_max, &target_rold->rlim_max);
unlock_user_struct(target_rold, arg4, 1);
}
break;
@@ -12360,7 +13321,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
abi_ulong mem_value;
if (get_user_u32(mem_value, arg6)) {
target_siginfo_t info;
- info.si_signo = SIGSEGV;
+ info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = TARGET_SEGV_MAPERR;
info._sifields._sigfault._addr = arg6;
@@ -12576,11 +13537,1209 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(kcmp(arg1, arg2, arg3, arg4, arg5));
break;
#endif
+#ifdef TARGET_NR_gethostid
+ case TARGET_NR_gethostid:
+ ret = get_errno(gethostid());
+ break;
+ case TARGET_NR_sethostid:
+ ret = get_errno(sethostid(arg1));
+ break;
+#endif
+/* SVR4 specific system calls */
+#if defined TARGET_NR_getcontext
+ case TARGET_NR_getcontext:
+ {
+ struct target_ucontext *target_uc;
+ TaskState *ts = cpu->opaque;
+
+ if (!lock_user_struct(VERIFY_WRITE, target_uc, arg1, 1)) {
+ goto efault;
+ }
+ save_context(cpu_env, &target_uc->tuc_mcontext, 1);
+ __put_user( ts->ctx_link, (uint32_t *)&target_uc->tuc_link );
+ __put_user( 0xc, &target_uc->tuc_flags );
+ unlock_user_struct(target_uc, arg1, 1);
+ ret = 0;
+ break;
+ }
+ case TARGET_NR_setcontext:
+ {
+ struct target_ucontext *target_uc;
+ TaskState *ts = cpu->opaque;
+ target_sigset_t target_set;
+ sigset_t set;
+ int flags, i;
+
+ if (!lock_user_struct(VERIFY_READ, target_uc, arg1, 1)) {
+ goto efault;
+ }
+ restore_context(cpu_env, &target_uc->tuc_mcontext);
+ __get_user( flags, &target_uc->tuc_flags );
+ if (flags & 1) {
+ for (i = 0; i < TARGET_NSIG_WORDS; i++)
+ __get_user(target_set.sig[i], &target_uc->tuc_sigmask.sig[i]);
+ target_to_host_sigset(&set, &target_set);
+ do_sigprocmask(cpu_env, SIG_SETMASK, &set, NULL);
+ }
+ __get_user( ts->ctx_link, (uint32_t *)&target_uc->tuc_link );
+ unlock_user_struct(target_uc, arg1, 0);
+ ret = -TARGET_QEMU_ESIGRETURN;
+ break;
+ }
+#endif
+#ifdef TARGET_NR_msgsys
+ case TARGET_NR_msgsys: {
+ abi_ulong flags = 0;
+ switch (arg1) {
+ case TARGET_NR_msgsys_msgget:
+ flags |= arg3 & 0777;
+ if (arg3 & TARGET_IPC_CREAT) flags |= IPC_CREAT;
+ if (arg3 & TARGET_IPC_EXCL) flags |= IPC_EXCL;
+ ret = get_errno(msgget(arg2, flags));
+ break;
+ case TARGET_NR_msgsys_msgctl:
+ switch (arg3) {
+ case TARGET_IPC_RMID: arg3 = IPC_RMID; break;
+ /* TODO: IPC_STAT, IPC_SET - structure different */
+ }
+ ret = do_msgctl(arg2, arg3, arg4);
+ break;
+ case TARGET_NR_msgsys_msgrcv:
+ if (arg6 & TARGET_IPC_NOWAIT) flags |= IPC_NOWAIT;
+ if (arg6 & TARGET_MSG_NOERROR) flags |= MSG_NOERROR;
+ ret = do_msgrcv(arg2, arg3, arg4, arg5, flags);
+ break;
+ case TARGET_NR_msgsys_msgsnd:
+ if (arg5 & TARGET_IPC_NOWAIT) flags |= IPC_NOWAIT;
+ if (arg5 & TARGET_MSG_NOERROR) flags |= MSG_NOERROR;
+ ret = do_msgsnd(arg2, arg3, arg4, flags);
+ break;
+ default:
+ ret = -TARGET_EINVAL;
+ }
+ break;
+ }
+#endif
+#ifdef TARGET_NR_shmsys
+ case TARGET_NR_shmsys: {
+ abi_ulong flags = 0;
+ switch (arg1) {
+ case TARGET_NR_shmsys_shmat:
+ if (arg4 & TARGET_SHM_RDONLY) flags |= SHM_RDONLY;
+ if (arg4 & TARGET_SHM_RND) flags |= SHM_RND;
+ ret = do_shmat(cpu_env, arg2, arg3, flags);
+ break;
+ case TARGET_NR_shmsys_shmctl:
+ switch (arg3) {
+ case TARGET_SHM_LOCK: arg3 = SHM_LOCK; break;
+ case TARGET_SHM_UNLOCK: arg3 = SHM_UNLOCK; break;
+ case TARGET_IPC_RMID: arg3 = IPC_RMID; break;
+ /* TODO: IPC_STAT, IPC_SET - structure different */
+ }
+ ret = do_shmctl(arg2, arg3, arg4);
+ break;
+ case TARGET_NR_shmsys_shmdt:
+ ret = do_shmdt(arg2);
+ break;
+ case TARGET_NR_shmsys_shmget:
+ flags |= arg4 & 0777;
+ if (arg4 & TARGET_IPC_CREAT) flags |= IPC_CREAT;
+ if (arg4 & TARGET_IPC_EXCL) flags |= IPC_EXCL;
+ ret = get_errno(shmget(arg2, arg3, flags));
+ break;
+ default:
+ ret = -TARGET_EINVAL;
+ }
+ break;
+ }
+#endif
+#ifdef TARGET_NR_semsys
+ case TARGET_NR_semsys: {
+ abi_ulong flags = 0;
+ switch (arg1) {
+ case TARGET_NR_semsys_semctl:
+ switch (arg4) {
+ case TARGET_SEM_GETNCNT:arg4 = GETNCNT; break;
+ case TARGET_SEM_GETPID: arg4 = GETPID; break;
+ case TARGET_SEM_GETVAL: arg4 = GETVAL; break;
+ case TARGET_SEM_GETALL: arg4 = GETALL; break;
+ case TARGET_SEM_GETZCNT:arg4 = GETZCNT; break;
+ case TARGET_SEM_SETVAL: arg4 = SETVAL; break;
+ case TARGET_SEM_SETALL: arg4 = SETALL; break;
+ case TARGET_IPC_RMID: arg4 = IPC_RMID; break;
+ /* TODO: IPC_STAT, IPC_SET, structure rather different */
+ }
+ ret = do_semctl(arg2, arg3, arg4, arg5);
+ break;
+ case TARGET_NR_semsys_semget:
+ flags |= arg4 & 0777;
+ if (arg4 & TARGET_IPC_CREAT) flags |= IPC_CREAT;
+ if (arg4 & TARGET_IPC_EXCL) flags |= IPC_EXCL;
+ ret = get_errno(semget(arg2, arg3, flags));
+ break;
+ case TARGET_NR_semsys_semop:
+ ret = do_semop(arg2, arg3, arg4);
+ break;
+ default:
+ ret = -TARGET_EINVAL;
+ break;
+ }
+ break;
+ }
+#endif
+/* Solaris/SysV specific syscalls */
+#ifdef TARGET_NR_forksys
+ case TARGET_NR_forksys:
+ switch (arg1) {
+ case TARGET_NR_forksys_forkx:
+ ret = get_errno(do_fork(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0, 0, 0));
+ break;
+ case TARGET_NR_forksys_vforkx:
+ ret = get_errno(do_fork(cpu_env,
+ CLONE_VFORK | CLONE_VM | TARGET_SIGCHLD, 0, 0, 0, 0, 0, 0));
+ break;
+ default:
+ ret = -TARGET_EINVAL;
+ }
+ break;
+#endif
+#ifdef TARGET_NR_pgrpsys
+ case TARGET_NR_pgrpsys:
+ switch (arg1) {
+ case TARGET_NR_pgrpsys_getpgrp:
+ ret = get_errno(getpgrp());
+ break;
+ case TARGET_NR_pgrpsys_setpgrp:
+ ret = get_errno(setpgrp());
+ break;
+#ifdef TARGET_ABI_SOLARIS
+ case TARGET_NR_pgrpsys_getsid:
+ ret = get_errno(getsid(arg2));
+ break;
+ case TARGET_NR_pgrpsys_setsid:
+ ret = get_errno(setsid());
+ break;
+ case TARGET_NR_pgrpsys_getpgid:
+ ret = get_errno(getpgid(arg2));
+ break;
+ case TARGET_NR_pgrpsys_setpgid:
+ ret = get_errno(setpgid(arg2, arg3));
+ break;
+#endif
+ default:
+ ret = -TARGET_EINVAL;
+ }
+ break;
+#endif
+#ifdef TARGET_NR_sigpendingsys
+ case TARGET_NR_sigpendingsys:
+ switch (arg1) {
+ case TARGET_NR_sigpsys_sigpending:
+ {
+ sigset_t set;
+ ret = get_errno(sigpending(&set));
+ if (!is_error(ret)) {
+ if (!(p = lock_user(VERIFY_WRITE, arg2,
+ sizeof(target_sigset_t), 0)))
+ goto efault;
+ host_to_target_old_sigset(p, &set);
+ unlock_user(p, arg2, sizeof(target_sigset_t));
+ }
+ break;
+ }
+ case TARGET_NR_sigpsys_sigfillset:
+ {
+ if (!(p = lock_user(VERIFY_WRITE, arg2,
+ sizeof(target_sigset_t), 0)))
+ goto efault;
+ memset(p, 0xff, sizeof(target_sigset_t));
+ unlock_user(p, arg2, sizeof(target_sigset_t));
+ ret = 0;
+ break;
+ }
+ default:
+ ret = -TARGET_EINVAL;
+ }
+ break;
+#endif
+#ifdef TARGET_NR_memcntl
+ case TARGET_NR_memcntl:
+ switch (arg3) {
+ case TARGET_NR_memcntl_msync:
+ ret = get_errno(msync(g2h(arg1), arg2, arg4));
+ break;
+ case TARGET_NR_memcntl_mlock:
+ ret = get_errno(mlock(g2h(arg1), arg2));
+ break;
+ case TARGET_NR_memcntl_munlock:
+ ret = get_errno(munlock(g2h(arg1), arg2));
+ break;
+ case TARGET_NR_memcntl_mlockall:
+ ret = get_errno(mlockall(target_to_host_mlockall_arg(arg4)));
+ break;
+ case TARGET_NR_memcntl_munlockall:
+ ret = get_errno(munlockall());
+ break;
+ default:
+ ret = -TARGET_EINVAL;
+ }
+ break;
+#endif
+#ifdef TARGET_NR_fsat
+ case TARGET_NR_fsat:
+ if (!(p = lock_user_string(arg3)))
+ goto efault;
+ switch (arg1) {
+ case TARGET_NR_fsat_openat:
+ case TARGET_NR_fsat_openat64:
+ ret = do_openat(cpu_env, arg2, p,
+ target_to_host_bitmask(arg4, fcntl_flags_tbl), arg5);
+ break;
+ case TARGET_NR_fsat_fstatat:
+ ret = get_errno(fstatat(arg2, path(p), &st, arg5));
+ if (!is_error(ret))
+ ret = host_to_target_stat(cpu_env, arg4, &st);
+ break;
+ case TARGET_NR_fsat_fstatat64:
+ ret = get_errno(fstatat(arg2, path(p), &st, arg5));
+ if (!is_error(ret))
+ ret = host_to_target_stat64(cpu_env, arg4, &st);
+ break;
+ case TARGET_NR_fsat_renameat:
+ {
+ void *p2;
+ p2 = lock_user_string(arg5);
+ if (!p2)
+ ret = -TARGET_EFAULT;
+ else
+ ret = get_errno(renameat(arg2, p, arg4, p2));
+ unlock_user(p2, arg5, 0);
+ break;
+ }
+ case TARGET_NR_fsat_fchownat:
+ ret = get_errno(fchownat(arg2, p,
+ low2highuid(arg4), low2highgid(arg5), arg6));
+ break;
+ case TARGET_NR_fsat_unlinkat:
+ ret = get_errno(unlinkat(arg2, p, arg4));
+ break;
+ case TARGET_NR_fsat_futimesat:
+ {
+ struct timeval *tvp, tv[2];
+ if (arg4) {
+ if (copy_from_user_timeval(&tv[0], arg4) ||
+ copy_from_user_timeval(&tv[1],
+ arg4 + sizeof(struct target_timeval)))
+ unlock_user(p, arg3, 0);
+ goto efault;
+ tvp = tv;
+ } else {
+ tvp = NULL;
+ }
+ ret = get_errno(futimesat(arg2, path(p), tvp));
+ }
+ break;
+ default:
+ ret = -TARGET_EINVAL;
+ }
+ unlock_user(p, arg3, 0);
+ break;
+#endif
+#ifdef TARGET_NR_rusagesys
+ case TARGET_NR_rusagesys:
+ {
+ switch (arg1) {
+ case TARGET_NR_rusagesys_rusage:
+ ret = RUSAGE_SELF;
+ break;
+ case TARGET_NR_rusagesys_rusagecld:
+ ret = RUSAGE_CHILDREN;
+ break;
+ case TARGET_NR_rusagesys_rusagelwp:
+ ret = RUSAGE_THREAD;
+ break;
+ default:
+ ret = -TARGET_EINVAL;
+ }
+ if (!is_error(ret)) {
+ struct rusage rusage;
+ ret = get_errno(getrusage(ret, &rusage));
+ if (!is_error(ret)) {
+ ret = host_to_target_rusage(arg2, &rusage);
+ }
+ }
+ }
+ break;
+#endif
+#ifdef TARGET_NR_resolvepath
+ case TARGET_NR_resolvepath:
+ {
+ char *target_path, *target_buf, resolved_path[PATH_MAX];
+ if (!(target_path = lock_user_string(arg1)))
+ goto efault;
+ if (!(target_buf = lock_user(VERIFY_WRITE, arg2, arg3, 0))) {
+ unlock_user(target_path, arg1, 0);
+ goto efault;
+ }
+ if (realpath(path(target_path), resolved_path)) {
+ target_buf[arg3-1] = 0;
+ strncpy(target_buf, resolved_path, arg3-1);
+ ret = strlen(target_buf)+1;
+ } else
+ ret = -host_to_target_errno(errno);
+ unlock_user(target_path, arg1, 0);
+ unlock_user(target_buf, arg2, arg3);
+ break;
+ }
+#endif
+#ifdef TARGET_NR_fdsync
+ case TARGET_NR_fdsync:
+ if (arg2 & 0x10)
+ ret = get_errno(fsync(arg1));
+ else
+ ret = get_errno(fdatasync(arg1));
+ break;
+#endif
+#ifdef TARGET_NR_context
+ case TARGET_NR_context:
+ switch (arg1) {
+ case TARGET_NR_context_getcontext:
+ {
+ struct target_ucontext *target_uc;
+ TaskState *ts = cpu->opaque;
+
+ if (!lock_user_struct(VERIFY_WRITE, target_uc, arg2, 1)) {
+ goto efault;
+ }
+ /* UC_MCONTEXT */
+ save_context(cpu_env, &target_uc->tuc_mcontext, 1);
+ __put_user( ts->ctx_link, (uint32_t *)&target_uc->tuc_link );
+ __put_user( 0xc, &target_uc->tuc_flags );
+ unlock_user_struct(target_uc, arg2, 1);
+ ret = 0;
+ break;
+ }
+ case TARGET_NR_context_setcontext:
+ {
+ struct target_ucontext *target_uc;
+ TaskState *ts = cpu->opaque;
+ target_sigset_t target_set;
+ sigset_t set;
+ int flags, i;
+
+ /* Note: Solaris uses setcontext instead of sigreturn */
+ if (!lock_user_struct(VERIFY_READ, target_uc, arg2, 1)) {
+ goto efault;
+ }
+ __get_user( flags, &target_uc->tuc_flags );
+
+ /* UC_MCONTEXT */
+ restore_context(cpu_env, &target_uc->tuc_mcontext);
+ /* UC_SIGMASK */
+ if (flags & 1) {
+ for (i = 0; i < TARGET_NSIG_WORDS; i++)
+ __get_user(target_set.sig[i],
+ &target_uc->tuc_sigmask.sig[i]);
+ target_to_host_sigset(&set, &target_set);
+ do_sigprocmask(cpu_env, SIG_SETMASK, &set, NULL);
+ }
+
+ __get_user( ts->ctx_link, (uint32_t *)&target_uc->tuc_link );
+ unlock_user_struct(target_uc, arg2, 0);
+ ret = -TARGET_QEMU_ESIGRETURN;
+ break;
+ }
+ default:
+ ret = -TARGET_EINVAL;
+ }
+ break;
+#endif
+#ifdef TARGET_NR_so_socket
+ case TARGET_NR_so_socket:
+ /* TODO: how to handle arg4=devpath and arg5=version? */
+ ret = do_socket(arg1, arg2, arg3);
+ break;
+#endif
+#ifdef TARGET_NR_pathconf
+ case TARGET_NR_pathconf:
+ if (!(p = lock_user_string(arg1)))
+ goto efault;
+ ret = get_errno(pathconf(path(p), target_to_host_pathconf(arg2)));
+ unlock_user(p, arg1, 0);
+ break;
+ case TARGET_NR_fpathconf:
+ ret = get_errno(fpathconf(arg1, target_to_host_pathconf(arg2)));
+ break;
+#endif
+#ifdef TARGET_NR_sysconfig
+ case TARGET_NR_sysconfig:
+ switch (arg1) {
+ case TARGET_NR_sysconf_childmax:
+ ret = get_errno(sysconf(_SC_CHILD_MAX));
+ break;
+ case TARGET_NR_sysconf_openmax:
+ ret = get_errno(sysconf(_SC_OPEN_MAX));
+ break;
+ case TARGET_NR_sysconf_pagesize:
+ ret = TARGET_PAGE_SIZE;
+ break;
+ case TARGET_NR_sysconf_clktick:
+ ret = get_errno(sysconf(_SC_CLK_TCK));
+ break;
+ case TARGET_NR_sysconf_nprocs:
+ ret = 1;
+ break;
+ case TARGET_NR_sysconf_physmem:
+ ret = 1024*1024*1024/TARGET_PAGE_SIZE;
+ break;
+ case TARGET_NR_sysconf_stckprot:
+ ret = R_OK|W_OK|X_OK;
+ break;
+ default:
+ ret = -TARGET_EINVAL;
+ }
+ break;
+#endif
+#ifdef TARGET_NR_sysinfosunos
+ case TARGET_NR_sysinfosunos:
+ {
+ char *target_buf;
+
+ if (!(target_buf = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
+ goto efault;
+
+ ret = 0;
+ target_buf[arg3-1] = 0;
+ switch (arg1) {
+ case TARGET_NR_sysinfo_gethostname:
+ ret = get_errno(gethostname(target_buf, arg3-1));
+ break;
+ case TARGET_NR_sysinfo_sethostname:
+ ret = get_errno(sethostname(target_buf, arg3-1));
+ break;
+ case TARGET_NR_sysinfo_getsrpcdomain:
+ strncpy(target_buf, "", arg3-1);
+ break;
+
+ case TARGET_NR_sysinfo_sysname:
+ strncpy(target_buf, "SunOS", arg3-1);
+ break;
+ case TARGET_NR_sysinfo_release:
+ strncpy(target_buf, "5.7", arg3-1);
+ break;
+ case TARGET_NR_sysinfo_version:
+ strncpy(target_buf, "Generic", arg3-1);
+ break;
+ case TARGET_NR_sysinfo_machine:
+ strncpy(target_buf, "sun4m", arg3-1);
+ break;
+ case TARGET_NR_sysinfo_hwserial:
+ strncpy(target_buf, "0", arg3-1);
+ break;
+ case TARGET_NR_sysinfo_hwproducer:
+ strncpy(target_buf, "Qemu", arg3-1);
+ break;
+ case TARGET_NR_sysinfo_platform:
+ strncpy(target_buf, "sun4m", arg3-1);
+ break;
+ case TARGET_NR_sysinfo_isalist:
+ strncpy(target_buf, "sparcv7 sparc", arg3-1);
+ break;
+ case TARGET_NR_sysinfo_arch32:
+ case TARGET_NR_sysinfo_archkern:
+ case TARGET_NR_sysinfo_archnative:
+ case TARGET_NR_sysinfo_cpuarch:
+ strncpy(target_buf, "sparc", arg3-1);
+ break;
+ default:
+ ret = -TARGET_EINVAL;
+ }
+ ret = (ret ?: strlen(target_buf)+1);
+ unlock_user(target_buf, arg2, (ret > 0 ? ret : 0));
+ break;
+ }
+#endif
+#ifdef TARGET_NR_unamesunos
+ case TARGET_NR_unamesunos:
+ {
+ struct target_utsname *target_buf;
+ struct utsname buf;
+
+ if (!lock_user_struct(VERIFY_WRITE, target_buf, arg1, 0))
+ goto efault;
+ ret = get_errno(uname(&buf));
+ if (!is_error(ret)) {
+ /* Override the native machine name with whatever is being
+ emulated. */
+ strcpy (buf.machine, cpu_to_uname_machine(cpu_env));
+ /* Allow the user to override the reported release. */
+ if (qemu_uname_release && *qemu_uname_release)
+ strcpy (buf.release, qemu_uname_release);
+
+ strncpy(target_buf->sysname, "SunOS", sizeof(target_buf->sysname));
+ strncpy(target_buf->nodename, buf.nodename, sizeof(target_buf->nodename));
+ strncpy(target_buf->release, "5.7", sizeof(target_buf->release));
+ strncpy(target_buf->version, "Generic", sizeof(target_buf->version));
+ strncpy(target_buf->machine, "sun4m", sizeof(target_buf->machine));
+ ret = 1; /* says the illuminos code? */
+ }
+ unlock_user_struct(target_buf, arg1, 1);
+ break;
+ }
+#endif
+/* IRIX specific syscalls */
+#ifdef TARGET_NR_sproc
+ case TARGET_NR_nsproc: /* pid = nsproc(entry, flags, prthread, prsched) */
+ {
+ /* TODO: prsched? */
+ struct target_prthread *target_prthread;
+ abi_ulong prthread = arg3;
+ if (!lock_user_struct(VERIFY_READ, target_prthread, prthread, 0))
+ goto efault;
+ __get_user(arg3, &target_prthread->prt_arg);
+ __get_user(arg4, &target_prthread->prt_stkptr);
+ __get_user(arg5, &target_prthread->prt_stklen);
+ unlock_user_struct(target_prthread, prthread, 1);
+ goto do_sprocsp;
+ }
+ case TARGET_NR_sproc: /* pid = sproc(entry, flags, arg) */
+ arg5 = 16384; /* default stack size? */
+ arg4 = target_mmap(0, arg5, PROT_READ | PROT_WRITE,
+ MAP_ANON | MAP_PRIVATE, -1, 0);
+ if ((abi_int)arg4 == -1) {
+ ret = -TARGET_ENOMEM;
+ break;
+ }
+ goto do_sprocsp;
+
+ case TARGET_NR_sprocsp: /* pid = sprocsp(entry, flags, arg, stack, len) */
+ do_sprocsp:
+ {
+ int opt;
+
+ /* qemu only knows about (v)fork and pthread_create :-( */
+ if ((arg2 & (TARGET_PR_BLOCK|TARGET_PR_SALL)) ==
+ (TARGET_PR_BLOCK|TARGET_PR_SADDR))
+ /* treat this like vfork */
+ opt = CLONE_VFORK | CLONE_VM | TARGET_SIGCHLD;
+ else
+ /* treat everything else like pthread_create */
+ opt = CLONE_THREAD_FLAGS;
+ arg4 = arg4 + arg5 - 16; /* set stack top */
+ ret = get_errno(do_fork(cpu_env, opt, arg4, 0, 0, 0, arg1, arg3));
+ /* man page says PR_BLOCK blocks the parent process like procblk does */
+ if (ret > 0 && !(opt & CLONE_VFORK) && (arg2 & TARGET_PR_BLOCK)) {
+ TaskState *ts = cpu->opaque;
+ arg1 = TARGET_NR_procblk_block;
+ arg2 = ts->ts_tid;
+ goto do_procblk;
+ }
+ /* child, or error */
+ break;
+ }
+#endif
+#ifdef TARGET_NR_procblk
+ case TARGET_NR_procblk:
+ do_procblk:
+ {
+ TaskState *ts = find_task_state(arg2);
+ int old_count;
+ ret = 0;
+ if (!ts) {
+ ret = -TARGET_ESRCH;
+ break;
+ }
+ /* NOTE: implementation inspired by netbsd-5 code */
+ pthread_mutex_lock(&ts->procblk_mutex);
+ old_count = ts->procblk_count;
+ switch (arg1) {
+ case TARGET_NR_procblk_block: /* blockproc(pid) */
+ if (ts != cpu->opaque && old_count == 0)
+ ret = -TARGET_EPERM;
+ else
+ ts->procblk_count --;
+ break;
+ case TARGET_NR_procblk_unblock: /* unblockproc(pid) */
+ ts->procblk_count ++;
+ break;
+ case TARGET_NR_procblk_count: /* setblockproccnt(pid, val) */
+ if (ts != cpu->opaque && (old_count < 0) != (arg3 < 0))
+ ret = -TARGET_EPERM;
+ else
+ ts->procblk_count = arg3;
+ break;
+ /* TODO: block_all, unblock_all, count_all */
+ default:
+ gemu_log("qemu: Unsupported syscall: procblk(%d)\n", (int)arg1);
+ ret = -TARGET_ENOSYS;
+ break;
+ }
+ if (ret == 0 && ts) {
+ if (ts->procblk_count < 0 && old_count >= 0) {
+ ts->is_blocked = 1;
+ do {
+ pthread_cond_wait(&ts->procblk_cond, &ts->procblk_mutex);
+ } while (ts->is_blocked);
+ } else if (ts->procblk_count >= 0 && old_count < 0) {
+ ts->is_blocked = 0;
+ pthread_cond_broadcast(&ts->procblk_cond);
+ }
+ }
+ pthread_mutex_unlock(&ts->procblk_mutex);
+ }
+ break;
+#endif
+#ifdef TARGET_NR_usync_cntl
+ case TARGET_NR_usync_cntl:
+ {
+ struct target_usync *target_buf;
+ struct usync_ref *sync, *lock;
+ struct timespec ts;
+ if (!lock_user_struct(VERIFY_WRITE, target_buf, arg2, 0))
+ goto efault;
+ if (!(sync = usync_get_sync(tswap64(target_buf->u_sync)))) {
+ ret = -TARGET_ENOMEM;
+ break;
+ }
+ /* Unfortunately I discovered the netbsd-5 code is plainly wrong :-(
+ * The mtune usync file talks about a "synchronizing address", which is
+ * what all this is about. Nothing in user space is changed by usync.
+ */
+ switch (arg1) {
+ case TARGET_NR_usync_handoff: /* implements pthread_cond_wait? */
+ /* TODO: handoff uncovered by experiment, and it seems to work,
+ * but it looks rather strange. Is this correct? */
+ if (!(lock = usync_get_sync(tswap64(target_buf->u_lock)))) {
+ ret = -TARGET_ENOMEM;
+ break;
+ }
+ pthread_mutex_lock(&lock->lock);
+ lock->count ++;
+ lock->handoffs ++; /* Mark this as being used as handoff lock */
+ ret = pthread_cond_signal(&lock->cond);
+ pthread_mutex_unlock(&lock->lock);
+ /*FALLTHROUGH*/
+ case TARGET_NR_usync_block: /* block on address */
+ case TARGET_NR_usync_intr_block: /* interruptible block? */
+ __get_user(ts.tv_sec, &target_buf->u_sec);
+ __get_user(ts.tv_nsec, &target_buf->u_nsec);
+ pthread_mutex_lock(&sync->lock);
+ sync->waiters ++;
+ for (ret = 0; sync->count <= 0 && ret == 0; ) {
+ if (target_buf->u_flags & tswap16(TARGET_US_TIMEOUT))
+ ret = pthread_cond_timedwait(&sync->cond, &sync->lock, &ts);
+ else
+ ret = pthread_cond_wait(&sync->cond, &sync->lock);
+ }
+ if (!ret) {
+ sync->count --;
+ /* Notify the caller if this was used as handoff lock */
+ ret = sync->handoffs;
+ if (sync->handoffs)
+ sync->handoffs --;
+ }
+ sync->waiters --;
+ pthread_mutex_unlock(&sync->lock);
+ break;
+ case TARGET_NR_usync_unblock_all: /* unblock everyone waiting on addr */
+ pthread_mutex_lock(&sync->lock);
+ sync->count = sync->waiters;
+ ret = pthread_cond_broadcast(&sync->cond);
+ pthread_mutex_unlock(&sync->lock);
+ break;
+ case TARGET_NR_usync_unblock: /* unblock one process waiting on addr */
+ pthread_mutex_lock(&sync->lock);
+ sync->count ++;
+ ret = pthread_cond_signal(&sync->cond);
+ pthread_mutex_unlock(&sync->lock);
+ break;
+ case TARGET_NR_usync_get_state: /* get current wait state */
+ pthread_mutex_lock(&sync->lock);
+ ret = sync->count - sync->waiters;
+ pthread_mutex_unlock(&sync->lock);
+ break;
+ default:
+ gemu_log("qemu: Unsupported syscall: usynccntl(%d)\n", (int)arg1);
+ ret = -TARGET_ENOSYS;
+ break;
+ }
+ unlock_user_struct(target_buf, arg2, 1);
+ }
+ break;
+#endif
+#ifdef TARGET_NR_sgiprctl
+ case TARGET_NR_sgiprctl:
+ {
+ CPUState *p;
+ TaskState *ts = (TaskState *)cpu->opaque;
+ switch (arg1) {
+ case TARGET_NR_prctl_maxpprocs: /* #available processors */
+ ret = 1;
+ break;
+ case TARGET_NR_prctl_getnshare: /* #processes in share group? */
+ for (ret = 0, p = first_cpu; p; ret++, p = CPU_NEXT(p)) ;
+ break;
+ case TARGET_NR_prctl_lastshexit: /* checks if share group is empty?*/
+ ret = (CPU_NEXT(first_cpu) == NULL);
+ break;
+ case TARGET_NR_prctl_termchild: /* send SIGHUP to child if parent dies */
+ ts->termchild_sig = TARGET_SIGHUP;
+ ret = 0;
+ break;
+ case TARGET_NR_prctl_unblkonexec: /* on exec unblock parent thread */
+ /* TODO: for vfork, this should work right away, but otherwise? */
+ ret = 0;
+ break;
+ case TARGET_NR_prctl_setexitsig: /* on exit send signal to threads */
+ /* TODO: global parameters (that is, valid for all threads)? */
+ for (p = first_cpu; p; p = CPU_NEXT(p)) {
+ ts = (TaskState *)p->opaque;
+ ts->exit_sig = arg2;
+ }
+ ret = 0;
+ break;
+ case TARGET_NR_prctl_isblocked: /* is process blocked? */
+ /* TODO: only covers procblk/threadctl, not usync/psema/semsys? */
+ ts = find_task_state(arg2);
+ if (ts)
+ ret = ts->is_blocked;
+ else
+ ret = -TARGET_ESRCH;
+ break;
+ case TARGET_NR_prctl_initthreads: /* initialize process for pthreads? */
+ ts->is_pthread = 1;
+ ret = 0;
+ break;
+ case TARGET_NR_prctl_threadctl: /* pthread thread control */
+ switch (arg2) {
+ case TARGET_NR_prctl_thread_exit: /* exit() */
+ ret = do_exit(cpu_env, 0);
+ break;
+ case TARGET_NR_prctl_thread_block: /* block(), this thread */
+ pthread_mutex_lock(&ts->procblk_mutex);
+ ts->procblk_count --;
+ ts->is_blocked = 1;
+ for (ret = 0; ts->procblk_count < 0 && ret == 0; ) {
+ ret = pthread_cond_wait(&ts->procblk_cond, &ts->procblk_mutex);
+ };
+ ts->is_blocked = 0;
+ pthread_mutex_unlock(&ts->procblk_mutex);
+ if (ret)
+ ret = -host_to_target_errno(errno);
+ break;
+ case TARGET_NR_prctl_thread_unblock: /* unblock(tid) */
+ ts = find_task_state(arg3);
+ if (ts) {
+ pthread_mutex_lock(&ts->procblk_mutex);
+ ts->procblk_count ++;
+ pthread_cond_broadcast(&ts->procblk_cond);
+ pthread_mutex_unlock(&ts->procblk_mutex);
+ ret = 0;
+ } else
+ ret = -TARGET_ESRCH;
+ break;
+ case TARGET_NR_prctl_thread_kill: /* kill(tid, sig) */
+ {
+ CPUState *p = find_cpu_state(arg3);
+ target_siginfo_t info = { 0 };
+ info.si_signo = arg4;
+ if (p) {
+ queue_signal((CPUArchState *)p->env_ptr, info.si_signo,
+ QEMU_SI_KILL, &info);
+ /* TODO: must process here because thread may be blocked? */
+ process_pending_signals((CPUArchState *)p->env_ptr);
+ }
+ ret = 0;
+ break;
+ }
+ case TARGET_NR_prctl_thread_sched: /* what's this ?!? */
+ default:
+ ret = -TARGET_ENOSYS;
+ break;
+ }
+ break;
+ default:
+ gemu_log("qemu: Unsupported syscall: sgiprctl(%d)\n", (int)arg1);
+ ret = -TARGET_ENOSYS;
+ break;
+ }
+ break;
+ }
+#endif
+#ifdef TARGET_NR_psema_cntl
+ case TARGET_NR_psema_cntl:
+ {
+ char *p;
+ sem_t *s;
+ int v;
+ switch (arg1) {
+ case TARGET_NR_psema_open: /* idx = sem_open(name, flags, mode, val) */
+ /* TODO: On IRIX, this returns a small integer, probably an fd? */
+ if (!(p = lock_user_string(arg2)))
+ goto efault;
+ s = sem_open(p, target_to_host_bitmask(arg3, fcntl_flags_tbl),
+ arg4, arg5);
+ if (s == SEM_FAILED)
+ ret = -host_to_target_errno(errno);
+ else
+ ret = psema_get_index(p, s, 1);
+ unlock_user(p, arg2, 0);
+ break;
+ case TARGET_NR_psema_close: /* sem_close(idx) */
+ ret = get_errno(sem_close(psema_get_sem(arg2)));
+ if (ret == 0)
+ psema_remove_index(arg2);
+ break;
+ case TARGET_NR_psema_unlink: /* sem_unlink(name) */
+ if (!(p = lock_user_string(arg2)))
+ goto efault;
+ ret = get_errno(sem_unlink(p));
+ if (!is_error(ret))
+ psema_unlink_index(p);
+ unlock_user(p, arg2, 0);
+ break;
+ case TARGET_NR_psema_wait: /* sem_wait(idx) */
+ case TARGET_NR_psema_wait2: /* TODO: difference between wait, wait2? */
+ ret = get_errno(sem_wait(psema_get_sem(arg2)));
+ break;
+ case TARGET_NR_psema_trywait: /* sem_trywait(idx) */
+ ret = get_errno(sem_trywait(psema_get_sem(arg2)));
+ break;
+ case TARGET_NR_psema_post: /* sem_post(idx) */
+ ret = get_errno(sem_post(psema_get_sem(arg2)));
+ break;
+ case TARGET_NR_psema_getvalue: /* sem_getvalue(idx, &val) */
+ ret = get_errno(sem_getvalue(psema_get_sem(arg2), &v));
+ put_user(v, arg3, abi_int);
+ break;
+ default:
+ gemu_log("qemu: Unsupported syscall: psema_cntl(%d)\n", (int)arg1);
+ ret = -TARGET_ENOSYS;
+ break;
+ }
+ break;
+ }
+#endif
+#ifdef TARGET_NR_syssgi
+ case TARGET_NR_syssgi:
+ {
+ switch (arg1) {
+ case TARGET_NR_syssgi_elfmap: /* map ELF shared object */
+ {
+#ifdef TARGET_ABI_MIPSN64
+ struct elf64_phdr *target_phdr, *phdr;
+#else
+ struct elf32_phdr *target_phdr, *phdr;
+#endif
+ int i;
+ target_phdr = lock_user(VERIFY_READ, arg3, sizeof(*phdr)*arg4, 1);
+ if (!target_phdr) {
+ goto efault;
+ }
+ phdr = alloca(sizeof(*phdr)*arg4);
+ for (i = 0; i < arg4; i++) {
+ __get_user(phdr[i].p_type, &target_phdr[i].p_type);
+ __get_user(phdr[i].p_offset, &target_phdr[i].p_offset);
+ __get_user(phdr[i].p_vaddr, &target_phdr[i].p_vaddr);
+ __get_user(phdr[i].p_paddr, &target_phdr[i].p_paddr);
+ __get_user(phdr[i].p_filesz, &target_phdr[i].p_filesz);
+ __get_user(phdr[i].p_memsz, &target_phdr[i].p_memsz);
+ __get_user(phdr[i].p_flags, &target_phdr[i].p_flags);
+ __get_user(phdr[i].p_align, &target_phdr[i].p_align);
+ }
+ ret = sgi_map_elf_image(arg2, phdr, arg4);
+ unlock_user(target_phdr, arg3, 0);
+ break;
+ }
+ case TARGET_NR_syssgi_sigaltstack:
+ ret = do_sigaltstack(cpu_env, arg2, arg3,
+ get_sp_from_cpustate((CPUArchState *)cpu_env));
+ break;
+ case TARGET_NR_syssgi_settimeofday:
+ {
+ struct timeval tv;
+ if (copy_from_user_timeval(&tv, arg2))
+ goto efault;
+ ret = get_errno(settimeofday(&tv, NULL));
+ }
+ break;
+ case TARGET_NR_syssgi_getpgid:
+ ret = get_errno(getpgid(arg2));
+ break;
+ case TARGET_NR_syssgi_getsid:
+ ret = get_errno(getsid(arg2));
+ break;
+ case TARGET_NR_syssgi_sysconf:
+ switch (arg2) {
+ case TARGET_NR_sysconf_childmax:
+ ret = get_errno(sysconf(_SC_CHILD_MAX));
+ break;
+ case TARGET_NR_sysconf_openmax:
+ ret = get_errno(sysconf(_SC_OPEN_MAX));
+ break;
+ case TARGET_NR_sysconf_clktick:
+ ret = get_errno(sysconf(_SC_CLK_TCK));
+ break;
+ case TARGET_NR_sysconf_pagesize:
+ ret = TARGET_PAGE_SIZE;
+ break;
+ case TARGET_NR_sysconf_nprocs:
+ ret = 1;
+ break;
+ case TARGET_NR_sysconf_acl:
+ case TARGET_NR_sysconf_cap:
+ case TARGET_NR_sysconf_mac:
+ ret = 0;
+ break;
+ default:
+ gemu_log("qemu: Unsupported syscall: sysconf(%d)\n", (int)arg2);
+ ret = -TARGET_ENOSYS;
+ break;
+ }
+ break;
+ case TARGET_NR_syssgi_pathconf:
+ if (arg3 == 1) {
+ if (!(p = lock_user_string(arg1)))
+ goto efault;
+ ret = get_errno(pathconf(path(p), target_to_host_pathconf(arg2)));
+ unlock_user(p, arg1, 0);
+ } else
+ ret = get_errno(fpathconf(arg1, target_to_host_pathconf(arg2)));
+ break;
+ case TARGET_NR_syssgi_rusage:
+ {
+ struct rusage rusage;
+ ret = get_errno(getrusage(arg2, &rusage));
+ if (!is_error(ret)) {
+ ret = host_to_target_rusage(arg3, &rusage);
+ }
+ }
+ break;
+ case TARGET_NR_syssgi_fdhi: /* highest valid fd */
+ {
+ DIR *dir;
+ struct dirent *de;
+ int fdhi = 0;
+ if ((dir = opendir("/proc/self/fd"))) {
+ while ((de = readdir(dir))) {
+ if (de->d_name[0] != '.') {
+ char *err = NULL;
+ long l = strtol(de->d_name, &err, 10);
+ if (err && !*err && l > fdhi)
+ fdhi = l;
+ }
+ }
+ }
+ ret = (fdhi > 0 ? fdhi+1 : -TARGET_EBADF);
+ }
+ break;
+ case TARGET_NR_syssgi_getust: /* get unadjusted system time */
+ {
+ struct timespec ts;
+ struct timeval tv;
+ abi_ullong ust, *target_ust;
+
+ /* arg1: ptr to llong, some time in ns? */
+ target_ust = lock_user(VERIFY_WRITE, arg1, sizeof(ust), 0);
+ if (!target_ust)
+ goto efault;
+ ret = get_errno(clock_gettime(CLOCK_MONOTONIC_RAW, &ts));
+ if (!is_error(ret)) {
+ ust = ts.tv_sec * 1000000000LL + ts.tv_nsec;
+ __put_user(ust, target_ust);
+ }
+ unlock_user(target_ust, arg1, sizeof(ust));
+
+ /* arg2: optional ptr to timeval (equiv. to gettimeofday)? */
+ if (arg2 && !is_error(ret)) {
+ ret = get_errno(gettimeofday(&tv, NULL));
+ if (!is_error(ret) && arg2) {
+ if (copy_to_user_timeval(arg2, &tv))
+ goto efault;
+ }
+ }
+ }
+ break;
+ case TARGET_NR_syssgi_sysid:
+ {
+ char * buf = lock_user(VERIFY_WRITE, arg2, 64, 0);
+ if (!buf) {
+ goto efault;
+ }
+ snprintf(buf, 64, "%12llx", 0x08006900000DULL);
+ ret = 0;
+ unlock_user(buf, arg2, 64);
+ break;
+ }
+ case TARGET_NR_syssgi_rldenv:
+ case TARGET_NR_syssgi_tosstsave:
+ case TARGET_NR_syssgi_fpbcopy:
+ ret = 0;
+ break;
+ case TARGET_NR_syssgi_setgroups:
+ case TARGET_NR_syssgi_getgroups:
+ default:
+ gemu_log("qemu: Unsupported syscall: sgisys(%d)\n", (int)arg1);
+ ret = -TARGET_ENOSYS;
+ break;
+ }
+ break;
+ }
+#endif
+#ifdef TARGET_NR_sginap
+ case TARGET_NR_sginap: /* yield if arg1=0, else nap arg1 clk ticks */
+ if (arg1)
+ ret = get_errno(usleep(arg1*10000)); /* assume tick freq = 100 Hz */
+ else
+ ret = sched_yield();
+ break;
+#endif
+#ifdef TARGET_NR_getmountid
+ case TARGET_NR_getmountid:
+ {
+ uint32_t *mid = lock_user(VERIFY_WRITE, arg2, sizeof(uint32_t)*4, 0);
+ if (!(p = lock_user_string(arg1)))
+ goto efault;
+ ret = get_errno(statfs(p, &stfs));
+ memcpy(mid, &stfs.f_fsid, sizeof(uint32_t)*4);
+ __put_user(stfs.f_type, &mid[3]);
+ unlock_user(p, arg1, 0);
+ unlock_user(mid, arg2, sizeof(uint32_t)*4);
+ break;
+ }
+#endif
+ /* stub implementations for misc IRIX stuff */
+#ifdef TARGET_NR_sysmp
+ case TARGET_NR_sysmp:
+ {
+ switch (arg1) {
+ case TARGET_NR_sysmp_nprocs: /* #physical processors */
+ case TARGET_NR_sysmp_naprocs: /* #processors without process limit */
+ ret = 1;
+ break;
+ case TARGET_NR_sysmp_pgsize:
+ ret = TARGET_PAGE_SIZE;
+ break;
+ default:
+ gemu_log("qemu: Unsupported syscall: sgisysmp(%d)\n", (int)arg1);
+ ret = -TARGET_ENOSYS;
+ break;
+ }
+ break;
+ }
+#endif
+#ifdef TARGET_NR_swapctl
+ case TARGET_NR_swapctl:
+ {
+ switch (arg1) {
+ case TARGET_NR_swapctl_getfree:
+ put_user(512*512, arg2, abi_ulong);
+ ret = 0;
+ break;
+ default:
+ gemu_log("qemu: Unsupported syscall: swapctl(%d)\n", (int)arg1);
+ ret = -TARGET_ENOSYS;
+ break;
+ }
+ break;
+ }
+#endif
+#ifdef TARGET_NR_sysinfosgi
+ case TARGET_NR_sysinfosgi:
+ {
+ char *target_buf;
+
+ if (!(target_buf = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
+ goto efault;
+
+ ret = 0;
+ target_buf[arg3-1] = 0;
+ switch (arg1) {
+ case TARGET_NR_sysinfo_gethostname:
+ ret = get_errno(gethostname(target_buf, arg3-1));
+ break;
+ case TARGET_NR_sysinfo_sethostname:
+ ret = get_errno(sethostname(target_buf, arg3-1));
+ break;
+ case TARGET_NR_sysinfo_getsrpcdomain:
+ strncpy(target_buf, "", arg3-1);
+ break;
+
+ case TARGET_NR_sysinfo_sysname:
+ strncpy(target_buf, "IRIX", arg3-1);
+ break;
+ case TARGET_NR_sysinfo_release:
+ strncpy(target_buf, "6.5", arg3-1);
+ break;
+ case TARGET_NR_sysinfo_version:
+ strncpy(target_buf, "01010101", arg3-1);
+ break;
+ case TARGET_NR_sysinfo_machine:
+ strncpy(target_buf, "IP22", arg3-1);
+ break;
+ case TARGET_NR_sysinfo_hwserial:
+ snprintf(target_buf, arg3-1, "%12llx", 0x08006900000DULL);
+ break;
+ case TARGET_NR_sysinfo_hwproducer:
+ strncpy(target_buf, "Qemu", arg3-1);
+ break;
+
+ case TARGET_NR_sysinfo_processors:
+ strncpy(target_buf, "R4000 3.0", arg3-1);
+ break;
+ default:
+ gemu_log("qemu: Unsupported syscall: sgisysinfo(%d)\n", (int)arg1);
+ ret = -TARGET_EINVAL;
+ }
+ ret = (ret ?: strlen(target_buf)+1);
+ unlock_user(target_buf, arg2, (ret > 0 ? ret : 0));
+ break;
+ }
+#endif
+#if defined TARGET_NR_utssyssgi
+ case TARGET_NR_utssyssgi:
+ {
+ switch (arg3) {
+ case TARGET_NR_utssys_uname:
+ {
+ struct target_utsname *target_buf;
+ struct utsname buf;
+
+ if (!lock_user_struct(VERIFY_WRITE, target_buf, arg1, 0))
+ goto efault;
+ ret = get_errno(uname(&buf));
+ if (!is_error(ret)) {
+ /* Override the native machine name with whatever is being
+ emulated. */
+ strcpy (buf.machine, cpu_to_uname_machine(cpu_env));
+ /* Allow the user to override the reported release. */
+ if (qemu_uname_release && *qemu_uname_release)
+ strcpy (buf.release, qemu_uname_release);
+
+ strncpy(target_buf->sysname, "IRIX", sizeof(target_buf->sysname));
+ strncpy(target_buf->nodename, buf.nodename, sizeof(target_buf->nodename));
+ strncpy(target_buf->release, "6.5", sizeof(target_buf->release));
+ strncpy(target_buf->version, "01010101", sizeof(target_buf->version));
+ strncpy(target_buf->machine, "IP22", sizeof(target_buf->machine));
+ }
+ unlock_user_struct(target_buf, arg1, 1);
+ break;
+ }
+ default:
+ gemu_log("qemu: Unsupported syscall: utssys(%d)\n", (int)arg1);
+ ret = -TARGET_ENOSYS;
+ break;
+ }
+ break;
+ }
+#endif
default:
+ goto unimplemented;
+
unimplemented:
gemu_log("qemu: Unsupported syscall: %d\n", num);
-#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname) || defined(TARGET_NR_set_robust_list)
+#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_set_robust_list)
unimplemented_nowarn:
#endif
ret = -TARGET_ENOSYS;
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index e00e1b3862..eae23e8ad7 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -203,12 +203,21 @@ struct target_ip_mreq_source {
};
struct target_timeval {
+#if defined(TARGET_ABI_IRIX) && defined(TARGET_ABI_MIPSN64)
+ int tv_pad1;
+ abi_int tv_sec;
+#else
abi_long tv_sec;
+#endif
abi_long tv_usec;
};
struct target_timespec {
+#if defined(TARGET_ABI_IRIX) && defined(TARGET_ABI_MIPSN64)
+ abi_int tv_sec;
+#else
abi_long tv_sec;
+#endif
abi_long tv_nsec;
};
@@ -255,7 +264,11 @@ struct target_timex {
abi_int:32; abi_int:32; abi_int:32;
};
+#ifdef TARGET_ABI_IRIX
+typedef abi_int target_clock_t;
+#else
typedef abi_long target_clock_t;
+#endif
#define TARGET_HZ 100
@@ -267,8 +280,13 @@ struct target_tms {
};
struct target_utimbuf {
+#ifdef TARGET_ABI_IRIX
+ abi_int actime;
+ abi_int modtime;
+#else
abi_long actime;
abi_long modtime;
+#endif
};
struct target_sel_arg_struct {
@@ -286,9 +304,15 @@ struct target_msghdr {
abi_long msg_name; /* Socket name */
int msg_namelen; /* Length of name */
abi_long msg_iov; /* Data blocks */
+#ifdef TARGET_ABI_IRIX
+ abi_int msg_iovlen; /* Number of blocks */
+ abi_long msg_control; /* Per protocol magic (eg BSD file descriptor passing) */
+ abi_int msg_controllen; /* Length of cmsg list */
+#else
abi_long msg_iovlen; /* Number of blocks */
abi_long msg_control; /* Per protocol magic (eg BSD file descriptor passing) */
abi_long msg_controllen; /* Length of cmsg list */
+#endif
unsigned int msg_flags;
};
@@ -376,7 +400,9 @@ struct target_dirent64 {
uint64_t d_ino;
int64_t d_off;
unsigned short d_reclen;
+#if !defined TARGET_ABI_IRIX && !defined TARGET_ABI_SOLARIS
unsigned char d_type;
+#endif
char d_name[256];
};
@@ -386,24 +412,38 @@ struct target_dirent64 {
#define TARGET_SIG_IGN ((abi_long)1) /* ignore signal */
#define TARGET_SIG_ERR ((abi_long)-1) /* error return from signal */
-#ifdef TARGET_MIPS
+#if defined TARGET_MIPS || defined TARGET_ABI_SOLARIS
#define TARGET_NSIG 128
#else
#define TARGET_NSIG 64
#endif
+
+#if defined TARGET_ABI_IRIX || defined TARGET_ABI_SOLARIS
+#define TARGET_NSIG_BPW (8*sizeof(uint32_t))
+#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW)
+
+typedef struct {
+ uint32_t sig[TARGET_NSIG_WORDS];
+} target_sigset_t;
+#else
#define TARGET_NSIG_BPW TARGET_ABI_BITS
#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW)
typedef struct {
abi_ulong sig[TARGET_NSIG_WORDS];
} target_sigset_t;
+#endif
#ifdef BSWAP_NEEDED
static inline void tswap_sigset(target_sigset_t *d, const target_sigset_t *s)
{
int i;
for(i = 0;i < TARGET_NSIG_WORDS; i++)
+#if defined TARGET_ABI_IRIX || defined TARGET_ABI_SOLARIS
+ d->sig[i] = tswap32(s->sig[i]);
+#else
d->sig[i] = tswapal(s->sig[i]);
+#endif
}
#else
static inline void tswap_sigset(target_sigset_t *d, const target_sigset_t *s)
@@ -427,7 +467,7 @@ void host_to_target_old_sigset(abi_ulong *old_sigset,
void target_to_host_old_sigset(sigset_t *sigset,
const abi_ulong *old_sigset);
struct target_sigaction;
-int do_sigaction(int sig, const struct target_sigaction *act,
+int do_sigaction(CPUArchState *env, int sig, const struct target_sigaction *act,
struct target_sigaction *oact);
#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
@@ -438,7 +478,15 @@ int do_sigaction(int sig, const struct target_sigaction *act,
|| defined(TARGET_TILEGX) || defined(TARGET_HPPA) || defined(TARGET_NIOS2) \
|| defined(TARGET_RISCV)
-#if defined(TARGET_SPARC)
+#if defined(TARGET_ABI_IRIX) || defined(TARGET_ABI_SOLARIS)
+#define TARGET_SA_NOCLDSTOP 0x00020000
+#define TARGET_SA_NOCLDWAIT 0x00010000
+#define TARGET_SA_SIGINFO 0x00000008
+#define TARGET_SA_ONSTACK 0x00000001
+#define TARGET_SA_RESTART 0x00000004
+#define TARGET_SA_NODEFER 0x00000010
+#define TARGET_SA_RESETHAND 0x00000002
+#elif defined(TARGET_SPARC)
#define TARGET_SA_NOCLDSTOP 8u
#define TARGET_SA_NOCLDWAIT 0x100u
#define TARGET_SA_SIGINFO 0x200u
@@ -536,47 +584,7 @@ int do_sigaction(int sig, const struct target_sigaction *act,
#define TARGET_SIG_UNBLOCK 2
#define TARGET_SIG_SETMASK 3
-#elif defined(TARGET_SPARC)
-
-#define TARGET_SIGHUP 1
-#define TARGET_SIGINT 2
-#define TARGET_SIGQUIT 3
-#define TARGET_SIGILL 4
-#define TARGET_SIGTRAP 5
-#define TARGET_SIGABRT 6
-#define TARGET_SIGIOT 6
-#define TARGET_SIGSTKFLT 7 /* actually EMT */
-#define TARGET_SIGFPE 8
-#define TARGET_SIGKILL 9
-#define TARGET_SIGBUS 10
-#define TARGET_SIGSEGV 11
-#define TARGET_SIGSYS 12
-#define TARGET_SIGPIPE 13
-#define TARGET_SIGALRM 14
-#define TARGET_SIGTERM 15
-#define TARGET_SIGURG 16
-#define TARGET_SIGSTOP 17
-#define TARGET_SIGTSTP 18
-#define TARGET_SIGCONT 19
-#define TARGET_SIGCHLD 20
-#define TARGET_SIGTTIN 21
-#define TARGET_SIGTTOU 22
-#define TARGET_SIGIO 23
-#define TARGET_SIGXCPU 24
-#define TARGET_SIGXFSZ 25
-#define TARGET_SIGVTALRM 26
-#define TARGET_SIGPROF 27
-#define TARGET_SIGWINCH 28
-#define TARGET_SIGPWR 29
-#define TARGET_SIGUSR1 30
-#define TARGET_SIGUSR2 31
-#define TARGET_SIGRTMIN 32
-
-#define TARGET_SIG_BLOCK 0x01 /* for blocking signals */
-#define TARGET_SIG_UNBLOCK 0x02 /* for unblocking signals */
-#define TARGET_SIG_SETMASK 0x04 /* for setting the signal mask */
-
-#elif defined(TARGET_MIPS)
+#elif defined(TARGET_MIPS) || defined(TARGET_ABI_SOLARIS)
#define TARGET_SIGHUP 1 /* Hangup (POSIX). */
#define TARGET_SIGINT 2 /* Interrupt (ANSI). */
@@ -613,7 +621,11 @@ int do_sigaction(int sig, const struct target_sigaction *act,
#define TARGET_SIGPROF 29 /* Profiling alarm clock (4.2 BSD). */
#define TARGET_SIGXCPU 30 /* CPU limit exceeded (4.2 BSD). */
#define TARGET_SIGXFSZ 31 /* File size limit exceeded (4.2 BSD). */
+#ifdef TARGET_ABI_SOLARIS
+#define TARGET_SIGRTMIN 42
+#else
#define TARGET_SIGRTMIN 32
+#endif
#define TARGET_SIG_BLOCK 1 /* for blocking signals */
#define TARGET_SIG_UNBLOCK 2 /* for unblocking signals */
@@ -659,6 +671,46 @@ int do_sigaction(int sig, const struct target_sigaction *act,
#define TARGET_SIG_UNBLOCK 1
#define TARGET_SIG_SETMASK 2
+#elif defined(TARGET_SPARC)
+
+#define TARGET_SIGHUP 1
+#define TARGET_SIGINT 2
+#define TARGET_SIGQUIT 3
+#define TARGET_SIGILL 4
+#define TARGET_SIGTRAP 5
+#define TARGET_SIGABRT 6
+#define TARGET_SIGIOT 6
+#define TARGET_SIGSTKFLT 7 /* actually EMT */
+#define TARGET_SIGFPE 8
+#define TARGET_SIGKILL 9
+#define TARGET_SIGBUS 10
+#define TARGET_SIGSEGV 11
+#define TARGET_SIGSYS 12
+#define TARGET_SIGPIPE 13
+#define TARGET_SIGALRM 14
+#define TARGET_SIGTERM 15
+#define TARGET_SIGURG 16
+#define TARGET_SIGSTOP 17
+#define TARGET_SIGTSTP 18
+#define TARGET_SIGCONT 19
+#define TARGET_SIGCHLD 20
+#define TARGET_SIGTTIN 21
+#define TARGET_SIGTTOU 22
+#define TARGET_SIGIO 23
+#define TARGET_SIGXCPU 24
+#define TARGET_SIGXFSZ 25
+#define TARGET_SIGVTALRM 26
+#define TARGET_SIGPROF 27
+#define TARGET_SIGWINCH 28
+#define TARGET_SIGPWR 29
+#define TARGET_SIGUSR1 30
+#define TARGET_SIGUSR2 31
+#define TARGET_SIGRTMIN 32
+
+#define TARGET_SIG_BLOCK 0x01 /* for blocking signals */
+#define TARGET_SIG_UNBLOCK 0x02 /* for unblocking signals */
+#define TARGET_SIG_SETMASK 0x04 /* for setting the signal mask */
+
#else
/* OpenRISC Using the general signals */
@@ -723,7 +775,7 @@ struct target_sigaction {
target_sigset_t sa_mask;
abi_ulong sa_restorer;
};
-#elif defined(TARGET_MIPS)
+#elif defined(TARGET_MIPS) || defined(TARGET_ABI_SOLARIS)
struct target_sigaction {
uint32_t sa_flags;
#if defined(TARGET_ABI_MIPSN32)
@@ -812,7 +864,7 @@ typedef struct {
#define QEMU_SI_RT 5
typedef struct target_siginfo {
-#ifdef TARGET_MIPS
+#if defined(TARGET_MIPS) || defined(TARGET_ABI_SOLARIS)
int si_signo;
int si_code;
int si_errno;
@@ -847,10 +899,17 @@ typedef struct target_siginfo {
/* SIGCHLD */
struct {
pid_t _pid; /* which child */
+#if defined(TARGET_ABI_IRIX) || defined(TARGET_ABI_SOLARIS)
+ target_clock_t _utime;
+ int _status; /* exit code */
+ target_clock_t _stime;
+ int _swap;
+#else
uid_t _uid; /* sender's uid */
int _status; /* exit code */
target_clock_t _utime;
target_clock_t _stime;
+#endif
} _sigchld;
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
@@ -860,8 +919,13 @@ typedef struct target_siginfo {
/* SIGPOLL */
struct {
+#if defined(TARGET_ABI_IRIX) || defined(TARGET_ABI_SOLARIS)
+ int _fd;
+ abi_long _band; /* POLL_IN, POLL_OUT, POLL_MSG */
+#else
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
int _fd;
+#endif
} _sigpoll;
} _sifields;
} target_siginfo_t;
@@ -944,11 +1008,13 @@ struct target_rlimit {
#define TARGET_RLIM_INFINITY 0x7fffffffffffffffull
#elif defined(TARGET_MIPS) || (defined(TARGET_SPARC) && TARGET_ABI_BITS == 32)
#define TARGET_RLIM_INFINITY 0x7fffffffUL
+#define TARGET_RLIM64_INFINITY 0x7fffffffffffffffull
#else
#define TARGET_RLIM_INFINITY ((abi_ulong)-1)
+#define TARGET_RLIM64_INFINITY ((uint64_t)-1)
#endif
-#if defined(TARGET_MIPS)
+#if defined(TARGET_MIPS) || defined(TARGET_ABI_SOLARIS)
#define TARGET_RLIMIT_CPU 0
#define TARGET_RLIMIT_FSIZE 1
#define TARGET_RLIMIT_DATA 2
@@ -1008,6 +1074,10 @@ struct target_pollfd {
#define TARGET_KDSETLED 0x4B32 /* set led state [lights, not flags] */
#define TARGET_KDSIGACCEPT 0x4B4E
+#ifdef TARGET_ABI_IRIX
+#define TARGET_SIOCNREAD 0x4004730a
+#endif
+
#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_SH4)
#define TARGET_SIOCATMARK TARGET_IOR('s', 7, int)
#define TARGET_SIOCGPGRP TARGET_IOR('s', 9, pid_t)
@@ -1311,10 +1381,21 @@ struct target_pollfd {
#define TARGET_NCC 8
struct target_termio {
+#ifdef TARGET_ABI_IRIX
+ uint32_t c_iflag; /* input mode flags */
+ uint32_t c_oflag; /* output mode flags */
+ uint32_t c_cflag; /* control mode flags */
+ uint32_t c_lflag; /* local mode flags */
+#ifdef IRIX_NEW_TERMIO
+ uint32_t c_ospeed;
+ uint32_t c_ispeed;
+#endif
+#else
unsigned short c_iflag; /* input mode flags */
unsigned short c_oflag; /* output mode flags */
unsigned short c_cflag; /* control mode flags */
unsigned short c_lflag; /* local mode flags */
+#endif
unsigned char c_line; /* line discipline */
unsigned char c_cc[TARGET_NCC]; /* control characters */
};
@@ -1356,6 +1437,9 @@ struct target_winsize {
#define TARGET_MAP_NONBLOCK 0x20000 /* do not block on IO */
#define TARGET_MAP_STACK 0x40000 /* ignored */
#define TARGET_MAP_HUGETLB 0x80000 /* create a huge page mapping */
+#ifdef TARGET_ABI_IRIX
+#define TARGET_MAP_AUTOGROW 0x40
+#endif
#elif defined(TARGET_PPC)
#define TARGET_MAP_FIXED 0x10 /* Interpret addr exactly */
#define TARGET_MAP_ANONYMOUS 0x20 /* don't use a file */
@@ -1392,6 +1476,19 @@ struct target_winsize {
#define TARGET_MAP_NONBLOCK 0x20000 /* do not block on IO */
#define TARGET_MAP_STACK 0x40000 /* ignored */
#define TARGET_MAP_HUGETLB 0x80000 /* create a huge page mapping */
+#elif defined TARGET_ABI_SOLARIS
+#define TARGET_MAP_FIXED 0x10 /* Interpret addr exactly */
+#define TARGET_MAP_ANONYMOUS 0x0100 /* don't use a file */
+#define TARGET_MAP_GROWSDOWN 0 /* stack-like segment */
+#define TARGET_MAP_DENYWRITE 0 /* ETXTBSY */
+#define TARGET_MAP_EXECUTABLE 0x0400 /* mark it as an executable */
+#define TARGET_MAP_LOCKED 0 /* pages are locked */
+#define TARGET_MAP_NORESERVE 0x0040 /* don't check for reservations */
+#define TARGET_MAP_POPULATE 0 /* populate (prefault) pagetables */
+#define TARGET_MAP_NONBLOCK 0 /* do not block on IO */
+#define TARGET_MAP_UNINITIALIZED 0 /* for anonymous mmap, memory could be uninitialized */
+#define TARGET_MAP_STACK 0 /* ignored */
+#define TARGET_MAP_HUGETLB 0 /* create a huge page mapping */
#else
#define TARGET_MAP_FIXED 0x10 /* Interpret addr exactly */
#define TARGET_MAP_ANONYMOUS 0x20 /* don't use a file */
@@ -1504,6 +1601,56 @@ struct target_eabi_stat64 {
} QEMU_PACKED;
#endif
+#elif defined(TARGET_ABI_SOLARIS)
+
+struct target_stat {
+ abi_ulong st_dev;
+ abi_long st_pad1[3];
+ abi_ulong st_ino;
+ abi_uint st_mode;
+ abi_uint st_nlink;
+ abi_int st_uid;
+ abi_int st_gid;
+ abi_ulong st_rdev;
+ abi_long st_pad2[2];
+ abi_long st_size;
+ abi_long st_pad3;
+ abi_long target_st_atime;
+ abi_ulong __unused1;
+ abi_long target_st_mtime;
+ abi_ulong __unused2;
+ abi_long target_st_ctime;
+ abi_ulong __unused3;
+ abi_int st_blksize;
+ int64_t st_blocks;
+ char st_fstype[16];
+ abi_long __unused4[8];
+};
+
+#define TARGET_HAS_STRUCT_STAT64
+struct target_stat64 {
+ abi_ulong st_dev;
+ abi_long st_pad1[3];
+ uint64_t st_ino;
+ abi_uint st_mode;
+ abi_uint st_nlink;
+ abi_int st_uid;
+ abi_int st_gid;
+ abi_ulong st_rdev;
+ abi_long st_pad2[2];
+ int64_t st_size;
+ abi_long target_st_atime;
+ abi_ulong __unused1;
+ abi_long target_st_mtime;
+ abi_ulong __unused2;
+ abi_long target_st_ctime;
+ abi_ulong __unused3;
+ abi_int st_blksize;
+ int64_t st_blocks;
+ char st_fstype[16];
+ abi_long __unused4[8];
+};
+
#elif defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
struct target_stat {
unsigned int st_dev;
@@ -1583,7 +1730,7 @@ struct target_stat64 {
unsigned char __pad0[6];
unsigned short st_dev;
- uint64_t st_ino;
+ uint64_t st_ino;
unsigned int st_mode;
unsigned int st_nlink;
@@ -1597,6 +1744,7 @@ struct target_stat64 {
unsigned char __pad3[8];
int64_t st_size;
+
unsigned int st_blksize;
unsigned char __pad4[8];
@@ -1787,13 +1935,87 @@ struct target_stat64 {
unsigned long long st_ino;
} QEMU_PACKED;
+#elif defined (TARGET_ABI_IRIX)
+
+struct target_stat {
+ uint32_t st_dev;
+ abi_long st_pad0[3]; /* Reserved for st_dev expansion */
+ abi_ulong st_ino;
+
+ uint32_t st_mode;
+ uint32_t st_nlink;
+
+ int32_t st_uid;
+ int32_t st_gid;
+
+ uint32_t st_rdev;
+ abi_long st_pad1[2]; /* Reserved for st_rdev expansion */
+ abi_long st_size;
+ abi_long st_pad2;
+
+ /*
+ * Actually this should be timestruc_t st_atime, st_mtime and st_ctime
+ * but we don't have it under Linux.
+ */
+ int32_t target_st_atime;
+ abi_long target_st_atime_nsec;
+
+ int32_t target_st_mtime;
+ abi_long target_st_mtime_nsec;
+
+ int32_t target_st_ctime;
+ abi_long target_st_ctime_nsec;
+
+ abi_long st_blksize;
+ abi_long st_blocks;
+ char st_fstype[16];
+ abi_long st_projid;
+ abi_long st_pad[7];
+};
+
+#define TARGET_HAS_STRUCT_STAT64
+struct target_stat64 {
+ uint32_t st_dev;
+ abi_long st_pad0[3]; /* Reserved for st_dev expansion */
+ uint64_t st_ino;
+
+ uint32_t st_mode;
+ uint32_t st_nlink;
+
+ int32_t st_uid;
+ int32_t st_gid;
+
+ uint32_t st_rdev;
+ abi_long st_pad1[2]; /* Reserved for st_rdev expansion */
+ int64_t st_size;
+ abi_long st_pad2;
+
+ /*
+ * Actually this should be timestruc_t st_atime, st_mtime and st_ctime
+ * but we don't have it under Linux.
+ */
+ int32_t target_st_atime;
+ abi_long target_st_atime_nsec;
+
+ int32_t target_st_mtime;
+ abi_long target_st_mtime_nsec;
+
+ int32_t target_st_ctime;
+ abi_long target_st_ctime_nsec;
+
+ abi_long st_blksize;
+ int64_t st_blocks;
+ char st_fstype[16];
+ abi_long st_projid;
+ abi_long st_pad[7];
+};
+
#elif defined(TARGET_ABI_MIPSN64)
/* The memory layout is the same as of struct stat64 of the 32-bit kernel. */
struct target_stat {
unsigned int st_dev;
unsigned int st_pad0[3]; /* Reserved for st_dev expansion */
-
abi_ulong st_ino;
unsigned int st_mode;
@@ -1804,7 +2026,6 @@ struct target_stat {
unsigned int st_rdev;
unsigned int st_pad1[3]; /* Reserved for st_rdev expansion */
-
abi_ulong st_size;
/*
@@ -1822,32 +2043,80 @@ struct target_stat {
unsigned int st_blksize;
unsigned int st_pad2;
-
abi_ulong st_blocks;
};
#elif defined(TARGET_ABI_MIPSN32)
struct target_stat {
- abi_ulong st_dev;
- abi_ulong st_pad0[3]; /* Reserved for st_dev expansion */
- uint64_t st_ino;
- unsigned int st_mode;
- unsigned int st_nlink;
- int st_uid;
- int st_gid;
- abi_ulong st_rdev;
- abi_ulong st_pad1[3]; /* Reserved for st_rdev expansion */
- int64_t st_size;
- abi_long target_st_atime;
- abi_ulong target_st_atime_nsec; /* Reserved for st_atime expansion */
- abi_long target_st_mtime;
- abi_ulong target_st_mtime_nsec; /* Reserved for st_mtime expansion */
- abi_long target_st_ctime;
- abi_ulong target_st_ctime_nsec; /* Reserved for st_ctime expansion */
- abi_ulong st_blksize;
- abi_ulong st_pad2;
- int64_t st_blocks;
+ unsigned st_dev;
+ int st_pad0[3]; /* Reserved for network id */
+ unsigned int st_ino;
+ unsigned int st_mode;
+ unsigned int st_nlink;
+ int st_uid;
+ int st_gid;
+ unsigned st_rdev;
+ unsigned int st_pad1[2];
+ unsigned int st_size;
+ unsigned int st_pad2;
+ /*
+ * Actually this should be timestruc_t st_atime, st_mtime and st_ctime
+ * but we don't have it under Linux.
+ */
+ unsigned int target_st_atime;
+ unsigned int target_st_atime_nsec;
+ unsigned int target_st_mtime;
+ unsigned int target_st_mtime_nsec;
+ unsigned int target_st_ctime;
+ unsigned int target_st_ctime_nsec;
+ unsigned int st_blksize;
+ unsigned int st_blocks;
+ unsigned int st_pad3[14];
+};
+
+/*
+ * This matches struct stat64 in glibc2.1, hence the absolutely insane
+ * amounts of padding around dev_t's. The memory layout is the same as of
+ * struct stat of the 64-bit kernel.
+ */
+
+#define TARGET_HAS_STRUCT_STAT64
+struct target_stat64 {
+ unsigned int st_dev;
+ unsigned int st_pad0[3]; /* Reserved for st_dev expansion */
+
+ uint64_t st_ino;
+
+ unsigned int st_mode;
+ unsigned int st_nlink;
+
+ int st_uid;
+ int st_gid;
+
+ unsigned int st_rdev;
+
+ unsigned int st_pad1[3]; /* Reserved for st_rdev expansion */
+
+ int st_size;
+
+ /*
+ * Actually this should be timestruc_t st_atime, st_mtime and st_ctime
+ * but we don't have it under Linux.
+ */
+ int target_st_atime;
+ unsigned int target_st_atime_nsec; /* Reserved for st_atime expansion */
+
+ int target_st_mtime;
+ unsigned int target_st_mtime_nsec; /* Reserved for st_mtime expansion */
+
+ int target_st_ctime;
+ unsigned int target_st_ctime_nsec; /* Reserved for st_ctime expansion */
+
+ unsigned int st_blksize;
+
+ int st_blocks;
+ unsigned int st_pad2;
};
#elif defined(TARGET_ABI_MIPSO32)
@@ -2214,7 +2483,11 @@ typedef struct {
#ifdef TARGET_MIPS
#ifdef TARGET_ABI_MIPSN32
struct target_statfs {
+#ifdef TARGET_ABI_IRIX
+ short f_type;
+#else
int32_t f_type;
+#endif
int32_t f_bsize;
int32_t f_frsize; /* Fragment size - unsupported */
int32_t f_blocks;
@@ -2230,7 +2503,11 @@ struct target_statfs {
};
#else
struct target_statfs {
+#ifdef TARGET_ABI_IRIX
+ short f_type;
+#else
abi_long f_type;
+#endif
abi_long f_bsize;
abi_long f_frsize; /* Fragment size - unsupported */
abi_long f_blocks;
@@ -2247,10 +2524,18 @@ struct target_statfs {
#endif
struct target_statfs64 {
+#ifdef TARGET_ABI_IRIX
+ short f_type;
+ short __pad1;
+ uint32_t f_bsize;
+ uint32_t f_frsize; /* Fragment size - unsupported */
+ uint32_t __pad2;
+#else
uint32_t f_type;
uint32_t f_bsize;
uint32_t f_frsize; /* Fragment size - unsupported */
uint32_t __pad;
+#endif
uint64_t f_blocks;
uint64_t f_bfree;
uint64_t f_files;
@@ -2361,12 +2646,45 @@ struct target_statfs64 {
#define TARGET_F_SETLKW 9
#define TARGET_F_SETOWN 5 /* for sockets. */
#define TARGET_F_GETOWN 6 /* for sockets. */
+#define TARGET_F_SETOWN_EX 15
+#define TARGET_F_GETOWN_EX 16
+#define TARGET_F_SETSIG 10 /* for sockets. */
+#define TARGET_F_GETSIG 11 /* for sockets. */
#define TARGET_F_RDLCK 1
#define TARGET_F_WRLCK 2
#define TARGET_F_UNLCK 8
#define TARGET_F_EXLCK 16
#define TARGET_F_SHLCK 32
+#elif defined(TARGET_ABI_IRIX)
+#define TARGET_F_GETLK 14
+#define TARGET_F_SETLK 6
+#define TARGET_F_SETLKW 7
+#define TARGET_F_SETOWN 23 /* for sockets. */
+#define TARGET_F_GETOWN 24 /* for sockets. */
+#define TARGET_F_ALLOCSP 10
+#define TARGET_F_FREESP 11
+#define TARGET_F_ALLOCSP64 36
+#define TARGET_F_FREESP64 37
+
+#define TARGET_F_RDLCK 1
+#define TARGET_F_WRLCK 2
+#define TARGET_F_UNLCK 3
+#elif defined(TARGET_ABI_SOLARIS)
+#define TARGET_F_GETLK 14
+#define TARGET_F_SETLK 6
+#define TARGET_F_SETLKW 7
+#define TARGET_F_SETOWN 23 /* for sockets. */
+#define TARGET_F_GETOWN 24 /* for sockets. */
+#define TARGET_F_ALLOCSP 10
+#define TARGET_F_FREESP 11
+#define TARGET_F_ALLOCSP64 28
+#define TARGET_F_FREESP64 27
+#define TARGET_F_DUP2FD 9
+
+#define TARGET_F_RDLCK 1
+#define TARGET_F_WRLCK 2
+#define TARGET_F_UNLCK 3
#elif defined(TARGET_MIPS)
#define TARGET_F_GETLK 14
#define TARGET_F_SETLK 6
@@ -2388,9 +2706,12 @@ struct target_statfs64 {
#define TARGET_F_SETLKW 7
#define TARGET_F_SETOWN 8 /* for sockets. */
#define TARGET_F_GETOWN 9 /* for sockets. */
-#endif
#define TARGET_F_SETOWN_EX 15
#define TARGET_F_GETOWN_EX 16
+#define TARGET_F_SETSIG 10 /* for sockets. */
+#define TARGET_F_GETSIG 11 /* for sockets. */
+#endif
+
#ifndef TARGET_F_RDLCK
#define TARGET_F_RDLCK 0
@@ -2412,7 +2733,7 @@ struct target_statfs64 {
#define TARGET_F_GETSIG 11 /* for sockets. */
#endif
-#if defined(TARGET_MIPS)
+#if defined(TARGET_MIPS) || defined(TARGET_ABI_SOLARIS)
#define TARGET_F_GETLK64 33 /* using 'struct flock64' */
#define TARGET_F_SETLK64 34
#define TARGET_F_SETLKW64 35
@@ -2486,6 +2807,23 @@ struct target_statfs64 {
#define TARGET_O_NOFOLLOW 0100000 /* don't follow links */
#define TARGET_O_LARGEFILE 0200000
#define TARGET_O_DIRECT 0400000 /* direct disk access hint */
+#elif defined (TARGET_ABI_SOLARIS)
+#define TARGET_O_APPEND 0x0008
+#define TARGET_O_CREAT 0x0100 /* not fcntl */
+#define TARGET_O_NDELAY 0x0004
+#define TARGET_O_NONBLOCK 0x0080
+#define TARGET_O_LARGEFILE 0x2000
+#define TARGET_O_DSYNC 0x0040
+#define TARGET_O_TRUNC 0x0200 /* not fcntl */
+#define TARGET_O_EXCL 0x0400 /* not fcntl */
+#define TARGET_O_NOCTTY 0x0800 /* not fcntl */
+#define TARGET_O_CLOEXEC 0x800000
+#define TARGET___O_SYNC 0x0010
+#define TARGET_O_NOFOLLOW 0x20000
+#define TARGET_FASYNC 0
+#define TARGET_O_DIRECT 0
+#define TARGET_O_NOATIME 0
+#define TARGET_O_PATH 0
#elif defined (TARGET_SPARC)
#define TARGET_O_APPEND 0x0008
#define TARGET_FASYNC 0x0040 /* fcntl, for BSD compatibility */
@@ -2579,11 +2917,13 @@ struct target_flock {
short l_whence;
abi_long l_start;
abi_long l_len;
-#if defined(TARGET_MIPS)
+#if defined(TARGET_MIPS) || defined(TARGET_ABI_IRIX)
abi_long l_sysid;
+#elif defined(TARGET_ABI_SOLARIS)
+ abi_int l_sysid;
#endif
int l_pid;
-#if defined(TARGET_MIPS)
+#if defined TARGET_MIPS || defined TARGET_ABI_IRIX || defined TARGET_ABI_SOLARIS
abi_long pad[4];
#endif
};
@@ -2598,6 +2938,11 @@ struct target_flock64 {
#endif
abi_llong l_start;
abi_llong l_len;
+#if defined(TARGET_MIPS) || defined(TARGET_ABI_IRIX)
+ abi_long l_sysid;
+#elif defined(TARGET_ABI_SOLARIS)
+ abi_int l_sysid;
+#endif
int l_pid;
} QEMU_PACKED;
@@ -2898,9 +3243,18 @@ typedef int32_t target_timer_t;
/ sizeof(int32_t))
struct target_sigevent {
+#ifdef TARGET_ABI_IRIX
+ int sigev_notify;
+ struct {
+ int sigev_signo;
+ abi_ulong sigev_nifunc;
+ };
+ target_sigval_t sigev_value;
+#else
target_sigval_t sigev_value;
abi_int sigev_signo;
abi_int sigev_notify;
+#endif
union {
abi_int _pad[TARGET_SIGEV_PAD_SIZE];
abi_int _tid;
@@ -2952,4 +3306,168 @@ struct target_user_cap_data {
/* Return size of the log buffer */
#define TARGET_SYSLOG_ACTION_SIZE_BUFFER 10
+#if defined TARGET_ABI_IRIX || defined TARGET_ABI_SOLARIS
+struct target_statvfs {
+ abi_ulong f_bsize; /* fundamental file system block size */
+ abi_ulong f_frsize; /* fragment size */
+ abi_ulong f_blocks; /* total # of blocks of f_frsize on fs */
+ abi_ulong f_bfree; /* total # of free blocks of f_frsize */
+ abi_ulong f_bavail; /* # of free blocks avail to non-superuser */
+ abi_ulong f_files; /* total # of file nodes (inodes) */
+ abi_ulong f_ffree; /* total # of free file nodes */
+ abi_ulong f_favail; /* # of free nodes avail to non-superuser */
+ abi_ulong f_fsid; /* file system id (dev for now) */
+ uint32_t f_pad0[4];
+ abi_ulong f_flag; /* bit-mask of flags */
+ abi_ulong f_namemax; /* maximum file name length */
+ uint32_t f_pad1[24]; /* reserved for future expansion */
+};
+
+struct target_statvfs64 {
+ abi_ulong f_bsize; /* fundamental file system block size */
+ abi_ulong f_frsize; /* fragment size */
+ uint64_t f_blocks; /* total # of blocks of f_frsize on fs */
+ uint64_t f_bfree; /* total # of free blocks of f_frsize */
+ uint64_t f_bavail; /* # of free blocks avail to non-superuser */
+ uint64_t f_files; /* total # of file nodes (inodes) */
+ uint64_t f_ffree; /* total # of free file nodes */
+ uint64_t f_favail; /* # of free nodes avail to non-superuser */
+ abi_ulong f_fsid; /* file system id (dev for now) */
+ uint32_t f_pad0[4];
+ abi_ulong f_flag; /* bit-mask of flags */
+ abi_ulong f_namemax; /* maximum file name length */
+ uint32_t f_pad1[24]; /* reserved for future expansion */
+};
+
+struct target_utsname {
+ char sysname[257];
+ char nodename[257];
+ char release[257];
+ char version[257];
+ char machine[257];
+#ifdef TARGET_ABI_IRIX
+ char reserved[257][8];
+#endif
+};
+
+#define TARGET_P_PID 0
+#define TARGET_P_PGID 2
+#define TARGET_P_ALL 7
+
+/* wait flags */
+#define TARGET_WEXITED 0001
+#define TARGET_WSTOPPED 0004
+#define TARGET_WCONTINUED 0010
+#define TARGET_WNOHANG 0100
+#define TARGET_WNOWAIT 0200
+
+#define TARGET_STAT64_VER 3
+
+/* common sem/shm/msg definitions */
+#define TARGET_IPC_RMID 10
+#define TARGET_IPC_SET 11
+#define TARGET_IPC_STAT 12
+
+#define TARGET_IPC_CREAT 0001000
+#define TARGET_IPC_EXCL 0002000
+#define TARGET_IPC_NOWAIT 0004000
+
+/* sem function definitions */
+#define TARGET_SEM_GETNCNT 3
+#define TARGET_SEM_GETPID 4
+#define TARGET_SEM_GETVAL 5
+#define TARGET_SEM_GETALL 6
+#define TARGET_SEM_GETZCNT 7
+#define TARGET_SEM_SETVAL 8
+#define TARGET_SEM_SETALL 9
+
+/* shm function definitions */
+#define TARGET_SHM_LOCK 3
+#define TARGET_SHM_UNLOCK 4
+
+#define TARGET_SHM_RDONLY 010000
+#define TARGET_SHM_RND 020000
+
+/* msg function definitions */
+#define TARGET_MSG_NOERROR 010000
+#endif
+
+#ifdef TARGET_ABI_IRIX
+/* usync interface - undocumented by SGI, so there's some guesswork :-( */
+struct target_usync {
+ abi_int u_magic; /* 1002 in all cases? */
+ uint64_t u_sync; /* pointer to sync object */
+ uint16_t u_type; /* type of sync object? Either 1 or 2 */
+ uint16_t u_flags; /* e.g. timeout flag for timed wait */
+ abi_int u_unknown1[4]; /* some signal stuff? */
+ uint64_t u_lock; /* pointer to mutex for cond_wait */
+ uint64_t u_sec; /* timeout for cond_wait, tv_sec */
+ uint64_t u_nsec; /* timeout for cond_wait, tv_nsec */
+ abi_int u_unknown2[6];
+};
+
+#define TARGET_US_TIMEOUT 0x00000004
+
+/* nsproc interface - structure from sys/prctl.h */
+struct target_prthread {
+#ifdef TARGET_ABI_MIPSN32
+ abi_uint prt_entry;
+ abi_uint prt_arg;
+ abi_uint prt_flags;
+ abi_uint prt_stkptr;
+#else
+ abi_ulong prt_entry;
+ abi_ulong prt_arg;
+ abi_uint prt_flags;
+ abi_ulong prt_stkptr;
+#endif
+ abi_int prt_stklen;
+};
+
+/* sproc flags */
+#define TARGET_PR_SPROC 0x00000001
+#define TARGET_PR_SFDS 0x00000002
+#define TARGET_PR_SDIR 0x00000004
+#define TARGET_PR_SADDR 0x00000040
+#define TARGET_PR_SALL 0x0000007f
+#define TARGET_PR_BLOCK 0x01000000
+#endif
+
+#ifdef TARGET_ABI_SOLARIS
+#define TARGET_E_OK 8
+
+#define TARGET_PC_LINK_MAX 1
+#define TARGET_PC_MAX_CANON 2
+#define TARGET_PC_MAX_INPUT 3
+#define TARGET_PC_NAME_MAX 4
+#define TARGET_PC_PATH_MAX 5
+#define TARGET_PC_PIPE_BUF 6
+#define TARGET_PC_NO_TRUNC 7
+#define TARGET_PC_VDISABLE 8
+#define TARGET_PC_CHOWN_RESTRICTED 9
+#define TARGET_PC_ASYNC_IO 10
+#define TARGET_PC_PRIO_IO 11
+#define TARGET_PC_SYNC_IO 12
+#define TARGET_PC_ALLOC_SIZE_MIN 13
+#define TARGET_PC_REC_INCR_XFER_SIZE 14
+#define TARGET_PC_REC_MAX_XFER_SIZE 15
+#define TARGET_PC_REC_MIN_XFER_SIZE 16
+#define TARGET_PC_REC_XFER_ALIGN 17
+#define TARGET_PC_SYMLINK_MAX 18
+#define TARGET_PC_2_SYMLINKS 19
+#else
+#define TARGET_PC_LINK_MAX 1
+#define TARGET_PC_MAX_CANON 2
+#define TARGET_PC_MAX_INPUT 3
+#define TARGET_PC_NAME_MAX 4
+#define TARGET_PC_PATH_MAX 5
+#define TARGET_PC_PIPE_BUF 6
+#define TARGET_PC_NO_TRUNC 8
+#define TARGET_PC_VDISABLE 9
+#define TARGET_PC_CHOWN_RESTRICTED 7
+#define TARGET_PC_ASYNC_IO 64
+#define TARGET_PC_PRIO_IO 11
+#define TARGET_PC_SYNC_IO 10
+#endif
+
#endif
diff --git a/target/mips/Makefile.objs b/target/mips/Makefile.objs
index 651f36f517..5e8303d784 100644
--- a/target/mips/Makefile.objs
+++ b/target/mips/Makefile.objs
@@ -1,4 +1,4 @@
obj-y += translate.o dsp_helper.o op_helper.o lmi_helper.o helper.o cpu.o
-obj-y += gdbstub.o msa_helper.o mips-semi.o
+obj-y += gdbstub.o msa_helper.o mips-semi.o irix_helper.o
obj-$(CONFIG_SOFTMMU) += machine.o cp0_timer.o
obj-$(CONFIG_KVM) += kvm.o
diff --git a/target/mips/helper.h b/target/mips/helper.h
index 5f492348dd..2d3f1a6bfa 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -956,3 +956,26 @@ MSALDST_PROTO(d)
#undef MSALDST_PROTO
DEF_HELPER_3(cache, void, env, tl, i32)
+
+#ifdef TARGET_ABI_IRIX
+DEF_HELPER_2(irix_prda_ld_8, i64, tl, env)
+DEF_HELPER_2(irix_prda_ld_16, i64, tl, env)
+DEF_HELPER_2(irix_prda_ld_32, i64, tl, env)
+DEF_HELPER_2(irix_prda_ld_64, i64, tl, env)
+DEF_HELPER_2(irix_prda_ld_8s, i64, tl, env)
+DEF_HELPER_2(irix_prda_ld_16s, i64, tl, env)
+DEF_HELPER_2(irix_prda_ld_32s, i64, tl, env)
+DEF_HELPER_2(irix_prda_ld_16b, i64, tl, env)
+DEF_HELPER_2(irix_prda_ld_32b, i64, tl, env)
+DEF_HELPER_2(irix_prda_ld_64b, i64, tl, env)
+DEF_HELPER_2(irix_prda_ld_16sb, i64, tl, env)
+DEF_HELPER_2(irix_prda_ld_32sb, i64, tl, env)
+
+DEF_HELPER_3(irix_prda_st_8, void, i64, tl, env)
+DEF_HELPER_3(irix_prda_st_16, void, i64, tl, env)
+DEF_HELPER_3(irix_prda_st_32, void, i64, tl, env)
+DEF_HELPER_3(irix_prda_st_64, void, i64, tl, env)
+DEF_HELPER_3(irix_prda_st_16b, void, i64, tl, env)
+DEF_HELPER_3(irix_prda_st_32b, void, i64, tl, env)
+DEF_HELPER_3(irix_prda_st_64b, void, i64, tl, env)
+#endif
diff --git a/target/mips/irix_helper.c b/target/mips/irix_helper.c
new file mode 100644
index 0000000000..c14f0924fc
--- /dev/null
+++ b/target/mips/irix_helper.c
@@ -0,0 +1,164 @@
+/*
+ * IRIX PRDA access helper functions for QEMU
+ *
+ * Copyright (c) 2015 Kai-Uwe Bloem
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "exec/cpu_ldst.h"
+#include "exec/helper-proto.h"
+
+
+#ifdef TARGET_ABI_IRIX
+/* argh, ugly! need TaskState here to access PRDA storage */
+#include
+
+#define DEBUG(x) //x
+
+static inline void *prda_ptr(CPUMIPSState *env, target_ulong addr)
+{
+ TaskState *ts = ENV_GET_CPU(env)->opaque;
+ return &ts->prda[addr-0x200000];
+}
+
+uint64_t helper_irix_prda_ld_8(target_ulong addr, CPUMIPSState *env)
+{
+ uint64_t ret;
+ ret = ldub_p(prda_ptr(env, addr));
+ DEBUG(printf("ld8(%p) addr=%lx val=%lx\n",env,(long)addr,(long)ret));
+ return ret;
+}
+
+uint64_t helper_irix_prda_ld_16(target_ulong addr, CPUMIPSState *env)
+{
+ uint64_t ret;
+ ret = lduw_p(prda_ptr(env, addr));
+ DEBUG(printf("ld16(%p) addr=%lx val=%lx\n",env,(long)addr,(long)ret));
+ return ret;
+}
+uint64_t helper_irix_prda_ld_32(target_ulong addr, CPUMIPSState *env)
+{
+ uint64_t ret;
+ ret = (uint32_t)ldl_p(prda_ptr(env, addr));
+ DEBUG(printf("ld32(%p) addr=%lx val=%lx\n",env,(long)addr,(long)ret));
+ return ret;
+}
+uint64_t helper_irix_prda_ld_64(target_ulong addr, CPUMIPSState *env)
+{
+ uint64_t ret;
+ ret = ldq_p(prda_ptr(env, addr));
+ DEBUG(printf("ld64(%p) addr=%lx val=%lx\n",env,(long)addr,(long)ret));
+ return ret;
+}
+
+uint64_t helper_irix_prda_ld_8s(target_ulong addr, CPUMIPSState *env)
+{
+ uint64_t ret;
+ ret = ldsb_p(prda_ptr(env, addr));
+ DEBUG(printf("ld8s(%p) addr=%lx val=%lx\n",env,(long)addr,(long)ret));
+ return ret;
+}
+
+uint64_t helper_irix_prda_ld_16s(target_ulong addr, CPUMIPSState *env)
+{
+ uint64_t ret;
+ ret = ldsw_p(prda_ptr(env, addr));
+ DEBUG(printf("ld16s(%p) addr=%lx val=%lx\n",env,(long)addr,(long)ret));
+ return ret;
+}
+uint64_t helper_irix_prda_ld_32s(target_ulong addr, CPUMIPSState *env)
+{
+ uint64_t ret;
+ ret = (int32_t)ldl_p(prda_ptr(env, addr));
+ DEBUG(printf("ld32s(%p) addr=%lx val=%lx\n",env,(long)addr,(long)ret));
+ return ret;
+}
+
+uint64_t helper_irix_prda_ld_16b(target_ulong addr, CPUMIPSState *env)
+{
+ uint64_t ret;
+ ret = lduw_be_p(prda_ptr(env, addr));
+ DEBUG(printf("ld16b(%p) addr=%lx val=%lx\n",env,(long)addr,(long)ret));
+ return ret;
+}
+uint64_t helper_irix_prda_ld_32b(target_ulong addr, CPUMIPSState *env)
+{
+ uint64_t ret;
+ ret = (uint32_t)ldl_be_p(prda_ptr(env, addr));
+ DEBUG(printf("ld32b(%p) addr=%lx val=%lx\n",env,(long)addr,(long)ret));
+ return ret;
+}
+uint64_t helper_irix_prda_ld_64b(target_ulong addr, CPUMIPSState *env)
+{
+ uint64_t ret;
+ ret = ldq_be_p(prda_ptr(env, addr));
+ DEBUG(printf("ld64b(%p) addr=%lx val=%lx\n",env,(long)addr,(long)ret));
+ return ret;
+}
+uint64_t helper_irix_prda_ld_16sb(target_ulong addr, CPUMIPSState *env)
+{
+ uint64_t ret;
+ ret = ldsw_be_p(prda_ptr(env, addr));
+ DEBUG(printf("ld16sb(%p) addr=%lx val=%lx\n",env,(long)addr,(long)ret));
+ return ret;
+}
+uint64_t helper_irix_prda_ld_32sb(target_ulong addr, CPUMIPSState *env)
+{
+ uint64_t ret;
+ ret = (int32_t)ldl_be_p(prda_ptr(env, addr));
+ DEBUG(printf("ld32sb(%p) addr=%lx val=%lx\n",env,(long)addr,(long)ret));
+ return ret;
+}
+
+
+void helper_irix_prda_st_8(uint64_t val, target_ulong addr, CPUMIPSState *env)
+{
+ DEBUG(printf("st8(%p) addr=%lx val=%lx\n",env,(long)addr,(long)val));
+ stb_p(prda_ptr(env, addr), val);
+}
+void helper_irix_prda_st_16(uint64_t val, target_ulong addr, CPUMIPSState *env)
+{
+ DEBUG(printf("st16(%p) addr=%lx val=%lx\n",env,(long)addr,(long)val));
+ stw_p(prda_ptr(env, addr), val);
+}
+void helper_irix_prda_st_32(uint64_t val, target_ulong addr, CPUMIPSState *env)
+{
+ DEBUG(printf("st32(%p) addr=%lx val=%lx\n",env,(long)addr,(long)val));
+ stl_p(prda_ptr(env, addr), val);
+}
+void helper_irix_prda_st_64(uint64_t val, target_ulong addr, CPUMIPSState *env)
+{
+ DEBUG(printf("st64(%p) addr=%lx val=%lx\n",env,(long)addr,(long)val));
+ stq_p(prda_ptr(env, addr), val);
+}
+void helper_irix_prda_st_16b(uint64_t val, target_ulong addr, CPUMIPSState *env)
+{
+ DEBUG(printf("st16b(%p) addr=%lx val=%lx\n",env,(long)addr,(long)val));
+ stw_be_p(prda_ptr(env, addr), val);
+}
+void helper_irix_prda_st_32b(uint64_t val, target_ulong addr, CPUMIPSState *env)
+{
+ DEBUG(printf("st32b(%p) addr=%lx val=%lx\n",env,(long)addr,(long)val));
+ stl_be_p(prda_ptr(env, addr), val);
+}
+void helper_irix_prda_st_64b(uint64_t val, target_ulong addr, CPUMIPSState *env)
+{
+ DEBUG(printf("st64b(%p) addr=%lx val=%lx\n",env,(long)addr,(long)val));
+ stq_be_p(prda_ptr(env, addr), val);
+}
+
+#endif
diff --git a/target/mips/translate.c b/target/mips/translate.c
index d05ee67e63..675e30c6fd 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -2142,6 +2142,187 @@ static target_ulong pc_relative_pc (DisasContext *ctx)
return pc;
}
+#ifdef TARGET_ABI_IRIX
+static void (*irix_prda_helpers_ld[MO_SSIZE|MO_BSWAP])(TCGv_i64 ret, TCGv addr, TCGv_ptr env) = {
+ [MO_UB] = gen_helper_irix_prda_ld_8,
+ [MO_UW] = gen_helper_irix_prda_ld_16,
+ [MO_UL] = gen_helper_irix_prda_ld_32,
+ [MO_Q] = gen_helper_irix_prda_ld_64,
+ [MO_SB] = gen_helper_irix_prda_ld_8s,
+ [MO_SW] = gen_helper_irix_prda_ld_16s,
+ [MO_SL] = gen_helper_irix_prda_ld_32s,
+ [MO_UW|MO_BSWAP] = gen_helper_irix_prda_ld_16b,
+ [MO_UL|MO_BSWAP] = gen_helper_irix_prda_ld_32b,
+ [MO_Q|MO_BSWAP] = gen_helper_irix_prda_ld_64b,
+ [MO_SW|MO_BSWAP] = gen_helper_irix_prda_ld_16sb,
+ [MO_SL|MO_BSWAP] = gen_helper_irix_prda_ld_32sb,
+};
+
+static void (*irix_prda_helpers_st[MO_SSIZE|MO_BSWAP])(TCGv_i64 val, TCGv addr, TCGv_ptr env) = {
+ [MO_UB] = gen_helper_irix_prda_st_8,
+ [MO_UW] = gen_helper_irix_prda_st_16,
+ [MO_UL] = gen_helper_irix_prda_st_32,
+ [MO_Q] = gen_helper_irix_prda_st_64,
+ [MO_UW|MO_BSWAP] = gen_helper_irix_prda_st_16b,
+ [MO_UL|MO_BSWAP] = gen_helper_irix_prda_st_32b,
+ [MO_Q|MO_BSWAP] = gen_helper_irix_prda_st_64b,
+};
+
+extern int irix_emulate_prda;
+
+static void tcg_gen_irix_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
+{
+ if (irix_emulate_prda) {
+ TCGv t0, t1;
+ TCGv_i32 t2 = tcg_temp_local_new_i32();
+ TCGv_i64 t3;
+ TCGLabel *l1 = gen_new_label();
+ TCGLabel *l2 = gen_new_label();
+
+ t1 = tcg_temp_local_new();
+ tcg_gen_mov_tl(t1, addr);
+
+ t0 = tcg_temp_new();
+ tcg_gen_shri_tl(t0, t1, TARGET_PAGE_BITS);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x200000 >> TARGET_PAGE_BITS, l1);
+ tcg_temp_free(t0);
+
+ assert(irix_prda_helpers_ld[memop] != NULL);
+ t3 = tcg_temp_new_i64();
+ (irix_prda_helpers_ld[memop])(t3, t1, cpu_env);
+ tcg_gen_extrl_i64_i32(t2, t3);
+ tcg_temp_free_i64(t3);
+ tcg_gen_br(l2);
+
+ gen_set_label(l1);
+ tcg_gen_qemu_ld_i32(t2, t1, idx, memop);
+
+ gen_set_label(l2);
+ tcg_gen_mov_tl(addr, t1);
+ tcg_gen_mov_i32(val, t2);
+ tcg_temp_free(t1);
+ tcg_temp_free_i32(t2);
+ } else
+ tcg_gen_qemu_ld_i32(val, addr, idx, memop);
+}
+static void tcg_gen_irix_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
+{
+ if (irix_emulate_prda) {
+ TCGv t0, t1;
+ TCGv_i64 t2 = tcg_temp_local_new_i64();
+ TCGLabel *l1 = gen_new_label();
+ TCGLabel *l2 = gen_new_label();
+
+ t1 = tcg_temp_local_new();
+ tcg_gen_mov_tl(t1, addr);
+
+ t0 = tcg_temp_new();
+ tcg_gen_shri_tl(t0, t1, TARGET_PAGE_BITS);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x200000 >> TARGET_PAGE_BITS, l1);
+ tcg_temp_free(t0);
+
+ assert(irix_prda_helpers_ld[memop] != NULL);
+ (irix_prda_helpers_ld[memop])(t2, t1, cpu_env);
+ tcg_gen_br(l2);
+
+ gen_set_label(l1);
+ tcg_gen_qemu_ld_i64(t2, t1, idx, memop);
+
+ gen_set_label(l2);
+ tcg_gen_mov_tl(addr, t1);
+ tcg_gen_mov_i64(val, t2);
+ tcg_temp_free(t1);
+ tcg_temp_free_i64(t2);
+ } else
+ tcg_gen_qemu_ld_i64(val, addr, idx, memop);
+}
+#define tcg_gen_qemu_ld_i32(v,a,i,m) tcg_gen_irix_ld_i32(v,a,i,m)
+#define tcg_gen_qemu_ld_i64(v,a,i,m) tcg_gen_irix_ld_i64(v,a,i,m)
+
+#undef tcg_gen_qemu_ld_tl
+#if TARGET_LONG_BITS == 32
+#define tcg_gen_qemu_ld_tl(v,a,i,m) tcg_gen_irix_ld_i32(v,a,i,m)
+#else
+#define tcg_gen_qemu_ld_tl(v,a,i,m) tcg_gen_irix_ld_i64(v,a,i,m)
+#endif
+
+static void tcg_gen_irix_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, TCGMemOp memop)
+{
+ if (irix_emulate_prda) {
+ TCGv t0, t1;
+ TCGv_i32 t2;
+ TCGv_i64 t3;
+ TCGLabel *l1 = gen_new_label();
+ TCGLabel *l2 = gen_new_label();
+
+ t1 = tcg_temp_local_new();
+ tcg_gen_mov_tl(t1, addr);
+ t2 = tcg_temp_local_new_i32();
+ tcg_gen_mov_i32(t2, val);
+
+ t0 = tcg_temp_new();
+ tcg_gen_shri_tl(t0, t1, TARGET_PAGE_BITS);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x200000 >> TARGET_PAGE_BITS, l1);
+ tcg_temp_free(t0);
+
+ assert(irix_prda_helpers_st[memop] != NULL);
+ t3 = tcg_temp_new_i64();
+ tcg_gen_extu_i32_i64(t3, t2);
+ (irix_prda_helpers_st[memop])(t3, t1, cpu_env);
+ tcg_temp_free_i64(t3);
+ tcg_gen_br(l2);
+
+ gen_set_label(l1);
+ tcg_gen_qemu_st_i32(t2, t1, idx, memop);
+
+ gen_set_label(l2);
+ tcg_temp_free(t1);
+ tcg_temp_free_i32(t2);
+ } else
+ tcg_gen_qemu_st_i32(val, addr, idx, memop);
+}
+static void tcg_gen_irix_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, TCGMemOp memop)
+{
+ if (irix_emulate_prda) {
+ TCGv t0, t1;
+ TCGv_i64 t2;
+ TCGLabel *l1 = gen_new_label();
+ TCGLabel *l2 = gen_new_label();
+
+ t1 = tcg_temp_local_new();
+ tcg_gen_mov_tl(t1, addr);
+ t2 = tcg_temp_local_new_i64();
+ tcg_gen_mov_i64(t2, val);
+
+ t0 = tcg_temp_new();
+ tcg_gen_shri_tl(t0, t1, TARGET_PAGE_BITS);
+ tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0x200000 >> TARGET_PAGE_BITS, l1);
+ tcg_temp_free(t0);
+
+ assert(irix_prda_helpers_st[memop] != NULL);
+ (irix_prda_helpers_st[memop])(t2, t1, cpu_env);
+ tcg_gen_br(l2);
+
+ gen_set_label(l1);
+ tcg_gen_qemu_st_i64(t2, t1, idx, memop);
+
+ gen_set_label(l2);
+ tcg_temp_free(t1);
+ tcg_temp_free_i64(t2);
+ } else
+ tcg_gen_qemu_st_i64(val, addr, idx, memop);
+}
+#define tcg_gen_qemu_st_i32(v,a,i,m) tcg_gen_irix_st_i32(v,a,i,m)
+#define tcg_gen_qemu_st_i64(v,a,i,m) tcg_gen_irix_st_i64(v,a,i,m)
+
+#undef tcg_gen_qemu_st_tl
+#if TARGET_LONG_BITS == 32
+#define tcg_gen_qemu_st_tl(v,a,i,m) tcg_gen_irix_st_i32(v,a,i,m)
+#else
+#define tcg_gen_qemu_st_tl(v,a,i,m) tcg_gen_irix_st_i64(v,a,i,m)
+#endif
+#endif
+
/* Load */
static void gen_ld(DisasContext *ctx, uint32_t opc,
int rt, int base, int16_t offset)
@@ -2177,7 +2358,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
gen_store_gpr(t0, rt);
break;
case OPC_LDL:
- t1 = tcg_temp_new();
+ t1 = tcg_temp_local_new(); /*X*/
/* Do a byte access to possibly trigger a page
fault with the unaligned address. */
tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
@@ -2199,7 +2380,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
gen_store_gpr(t0, rt);
break;
case OPC_LDR:
- t1 = tcg_temp_new();
+ t1 = tcg_temp_local_new(); /*X*/
/* Do a byte access to possibly trigger a page
fault with the unaligned address. */
tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
@@ -2278,7 +2459,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
mem_idx = MIPS_HFLAG_UM;
/* fall through */
case OPC_LWL:
- t1 = tcg_temp_new();
+ t1 = tcg_temp_local_new(); /*X*/
/* Do a byte access to possibly trigger a page
fault with the unaligned address. */
tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
@@ -2304,7 +2485,7 @@ static void gen_ld(DisasContext *ctx, uint32_t opc,
mem_idx = MIPS_HFLAG_UM;
/* fall through */
case OPC_LWR:
- t1 = tcg_temp_new();
+ t1 = tcg_temp_local_new(); /*X*/
/* Do a byte access to possibly trigger a page
fault with the unaligned address. */
tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
diff --git a/target/mips/translate_init.c b/target/mips/translate_init.c
index c7ba6ee5f9..d1e23cacd2 100644
--- a/target/mips/translate_init.c
+++ b/target/mips/translate_init.c
@@ -636,6 +636,8 @@ const mips_def_t mips_defs[] =
.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
(1 << FCR0_D) | (1 << FCR0_S) |
(0x89 << FCR0_PRID) | (0x0 << FCR0_REV),
+ .CP1_fcr31 = 0,
+ .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
.SEGBITS = 42,
.PABITS = 36,
.insn_flags = CPU_MIPS64R2,
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
index ff6ed91f9a..bfee751f71 100644
--- a/target/sparc/cpu.c
+++ b/target/sparc/cpu.c
@@ -41,9 +41,9 @@ static void sparc_cpu_reset(CPUState *s)
#ifndef TARGET_SPARC64
env->wim = 1;
#endif
- env->regwptr = env->regbase + (env->cwp * 16);
CC_OP = CC_OP_FLAGS;
#if defined(CONFIG_USER_ONLY)
+ env->cwp = env->nwindows - 1;
#ifdef TARGET_SPARC64
env->cleanwin = env->nwindows - 2;
env->cansave = env->nwindows - 2;
@@ -74,6 +74,7 @@ static void sparc_cpu_reset(CPUState *s)
env->npc = env->pc + 4;
#endif
env->cache_control = 0;
+ env->regwptr = env->regbase + (env->cwp * 16);
}
static bool sparc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
diff --git a/target/sparc/cpu.h b/target/sparc/cpu.h
index 9724134a5b..4b67d3c5f6 100644
--- a/target/sparc/cpu.h
+++ b/target/sparc/cpu.h
@@ -820,4 +820,9 @@ static inline bool tb_am_enabled(int tb_flags)
#endif
}
+/* main.c */
+void flush_windows(CPUSPARCState *env);
+
+#include "exec/exec-all.h"
+
#endif
diff --git a/util/path.c b/util/path.c
index 7f9fc272fb..c720f268cc 100644
--- a/util/path.c
+++ b/util/path.c
@@ -15,13 +15,17 @@ struct pathelem
char *name;
/* Full path name, eg. /usr/gnemul/x86-linux/lib. */
char *pathname;
+ /* Entry type */
+ unsigned char type;
+ /* Parent */
struct pathelem *parent;
/* Children */
- unsigned int num_entries;
- struct pathelem *entries[0];
+ int num_entries;
+ struct pathelem **entries;
};
-static struct pathelem *base;
+static struct pathelem **base;
+int base_count;
/* First N chars of S1 match S2, and S2 is N chars long. */
static int strneq(const char *s1, unsigned int n, const char *s2)
@@ -37,14 +41,15 @@ static int strneq(const char *s1, unsigned int n, const char *s2)
static struct pathelem *add_entry(struct pathelem *root, const char *name,
unsigned type);
-static struct pathelem *new_entry(const char *root,
- struct pathelem *parent,
- const char *name)
+static struct pathelem *new_entry(const char *root, struct pathelem *parent,
+ const char *name, unsigned char type)
{
struct pathelem *new = g_malloc(sizeof(*new));
new->name = g_strdup(name);
new->pathname = g_strdup_printf("%s/%s", root, name);
- new->num_entries = 0;
+ new->type = type;
+ new->entries = NULL;
+ new->num_entries = -1;
return new;
}
@@ -64,6 +69,7 @@ static struct pathelem *add_dir_maybe(struct pathelem *path)
{
DIR *dir;
+ path->num_entries = 0;
if ((dir = opendir(path->pathname)) != NULL) {
struct dirent *dirent;
@@ -84,22 +90,18 @@ static struct pathelem *add_entry(struct pathelem *root, const char *name,
root->num_entries++;
- root = g_realloc(root, sizeof(*root)
- + sizeof(root->entries[0])*root->num_entries);
+ root->entries = g_realloc(root->entries,
+ sizeof(root->entries[0])*root->num_entries);
e = &root->entries[root->num_entries-1];
- *e = new_entry(root->pathname, root, name);
- if (is_dir_maybe(type)) {
- *e = add_dir_maybe(*e);
- }
-
+ *e = new_entry(root->pathname, root, name, type);
return root;
}
/* This needs to be done after tree is stabilized (ie. no more reallocs!). */
static void set_parents(struct pathelem *child, struct pathelem *parent)
{
- unsigned int i;
+ int i;
child->parent = parent;
for (i = 0; i < child->num_entries; i++)
@@ -108,9 +110,9 @@ static void set_parents(struct pathelem *child, struct pathelem *parent)
/* FIXME: Doesn't handle DIR/.. where DIR is not in emulated dir. */
static const char *
-follow_path(const struct pathelem *cursor, const char *name)
+follow_path(struct pathelem *cursor, const char *name)
{
- unsigned int i, namelen;
+ int i, namelen;
name += strspn(name, "/");
namelen = strcspn(name, "/");
@@ -124,6 +126,20 @@ follow_path(const struct pathelem *cursor, const char *name)
if (strneq(name, namelen, "."))
return follow_path(cursor, name + namelen);
+ if (cursor->num_entries < 0) {
+ static char path[255];
+ if (is_dir_maybe(cursor->type))
+ add_dir_maybe(cursor);
+ else if (cursor->type == DT_LNK &&
+ readlink(cursor->pathname, path, sizeof(path)) >= 0) {
+ if (*path != '/')
+ add_dir_maybe(cursor);
+ } else
+ cursor->num_entries = 0;
+ if (cursor->num_entries > 0)
+ set_parents(cursor, cursor->parent);
+ }
+
for (i = 0; i < cursor->num_entries; i++)
if (strneq(name, namelen, cursor->entries[i]->name))
return follow_path(cursor->entries[i], name + namelen);
@@ -132,46 +148,64 @@ follow_path(const struct pathelem *cursor, const char *name)
return NULL;
}
-void init_paths(const char *prefix)
+void init_paths(const char *prefix_list)
{
char pref_buf[PATH_MAX];
+ int count = base_count;
+ char *list, *prefix, *p;
- if (prefix[0] == '\0' ||
- !strcmp(prefix, "/"))
- return;
+ list = g_strdup(prefix_list);
- if (prefix[0] != '/') {
- char *cwd = getcwd(NULL, 0);
- size_t pref_buf_len = sizeof(pref_buf);
+ for (p = list; *p; p++) count += (*p == ':');
+ base = g_realloc(base, sizeof(*base) * (count + 1));
- if (!cwd)
- abort();
- pstrcpy(pref_buf, sizeof(pref_buf), cwd);
- pstrcat(pref_buf, pref_buf_len, "/");
- pstrcat(pref_buf, pref_buf_len, prefix);
- free(cwd);
- } else
- pstrcpy(pref_buf, sizeof(pref_buf), prefix + 1);
+ for (prefix = strtok(list, ":"); prefix; prefix = strtok(NULL, ":")) {
+ if (prefix[0] == '\0' || !strcmp(prefix, "/"))
+ continue;
- base = new_entry("", NULL, pref_buf);
- base = add_dir_maybe(base);
- if (base->num_entries == 0) {
- g_free(base->pathname);
- g_free(base->name);
- g_free(base);
- base = NULL;
- } else {
- set_parents(base, base);
+ if (prefix[0] != '/') {
+ char *cwd = getcwd(NULL, 0);
+ size_t pref_buf_len = sizeof(pref_buf);
+
+ if (!cwd)
+ abort();
+ pstrcpy(pref_buf, sizeof(pref_buf), cwd);
+ pstrcat(pref_buf, pref_buf_len, "/");
+ pstrcat(pref_buf, pref_buf_len, prefix);
+ free(cwd);
+ } else
+ pstrcpy(pref_buf, sizeof(pref_buf), prefix + 1);
+
+ base[base_count] = new_entry("", NULL, pref_buf, DT_DIR);
+ base[base_count] = add_dir_maybe(base[base_count]);
+
+ if (base[base_count]->num_entries <= 0) {
+ g_free(base[base_count]->pathname);
+ g_free(base[base_count]->name);
+ g_free(base[base_count]);
+ } else {
+ set_parents(base[base_count], base[base_count]);
+ base_count ++;
+ }
}
+ g_free(list);
}
/* Look for path in emulation dir, otherwise return name. */
const char *path(const char *name)
{
+ const char *p;
+ int i;
+
/* Only do absolute paths: quick and dirty, but should mostly be OK.
Could do relative by tracking cwd. */
if (!base || !name || name[0] != '/')
return name;
- return follow_path(base, name) ?: name;
+ for (i = 0; i < base_count; i++) {
+ if ((p = follow_path(base[i], name)))
+ return p;
+ }
+
+ return name;
}