diff options
Diffstat (limited to 'linux-user')
| -rw-r--r-- | linux-user/Makefile.objs | 1 | ||||
| -rw-r--r-- | linux-user/elfload.c | 12 | ||||
| -rw-r--r-- | linux-user/m68k-sim.c | 163 | ||||
| -rw-r--r-- | linux-user/m68k/cpu_loop.c | 17 | ||||
| -rw-r--r-- | linux-user/m68k/target_syscall.h | 2 | ||||
| -rw-r--r-- | linux-user/ppc/target_elf.h | 2 | ||||
| -rw-r--r-- | linux-user/qemu.h | 1 | ||||
| -rw-r--r-- | linux-user/syscall.c | 111 | ||||
| -rw-r--r-- | linux-user/syscall_defs.h | 1 |
9 files changed, 93 insertions, 217 deletions
diff --git a/linux-user/Makefile.objs b/linux-user/Makefile.objs index 285c5dfa17..d2f33beb5e 100644 --- a/linux-user/Makefile.objs +++ b/linux-user/Makefile.objs @@ -8,4 +8,3 @@ obj-$(TARGET_I386) += vm86.o obj-$(TARGET_ARM) += arm/nwfpe/ obj-$(TARGET_ARM) += arm/semihost.o obj-$(TARGET_AARCH64) += arm/semihost.o -obj-$(TARGET_M68K) += m68k-sim.o diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 9fd65708c4..bd43c4817d 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -768,7 +768,13 @@ enum { QEMU_PPC_FEATURE2_HAS_EBB = 0x10000000, /* Event Base Branching */ QEMU_PPC_FEATURE2_HAS_ISEL = 0x08000000, /* Integer Select */ QEMU_PPC_FEATURE2_HAS_TAR = 0x04000000, /* Target Address Register */ + QEMU_PPC_FEATURE2_VEC_CRYPTO = 0x02000000, + QEMU_PPC_FEATURE2_HTM_NOSC = 0x01000000, QEMU_PPC_FEATURE2_ARCH_3_00 = 0x00800000, /* ISA 3.00 */ + QEMU_PPC_FEATURE2_HAS_IEEE128 = 0x00400000, /* VSX IEEE Bin Float 128-bit */ + QEMU_PPC_FEATURE2_DARN = 0x00200000, /* darn random number insn */ + QEMU_PPC_FEATURE2_SCV = 0x00100000, /* scv syscall */ + QEMU_PPC_FEATURE2_HTM_NO_SUSPEND = 0x00080000, /* TM w/o suspended state */ }; #define ELF_HWCAP get_elf_hwcap() @@ -822,8 +828,10 @@ static uint32_t get_elf_hwcap2(void) GET_FEATURE(PPC_ISEL, QEMU_PPC_FEATURE2_HAS_ISEL); GET_FEATURE2(PPC2_BCTAR_ISA207, QEMU_PPC_FEATURE2_HAS_TAR); GET_FEATURE2((PPC2_BCTAR_ISA207 | PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 | - PPC2_ISA207S), QEMU_PPC_FEATURE2_ARCH_2_07); - GET_FEATURE2(PPC2_ISA300, QEMU_PPC_FEATURE2_ARCH_3_00); + PPC2_ISA207S), QEMU_PPC_FEATURE2_ARCH_2_07 | + QEMU_PPC_FEATURE2_VEC_CRYPTO); + GET_FEATURE2(PPC2_ISA300, QEMU_PPC_FEATURE2_ARCH_3_00 | + QEMU_PPC_FEATURE2_DARN); #undef GET_FEATURE #undef GET_FEATURE2 diff --git a/linux-user/m68k-sim.c b/linux-user/m68k-sim.c deleted file mode 100644 index 9bc6ff3d3a..0000000000 --- a/linux-user/m68k-sim.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * m68k simulator syscall interface - * - * Copyright (c) 2005 CodeSourcery, LLC. Written by Paul Brook. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program 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 General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. - */ - -#include "qemu/osdep.h" - -#include "qemu.h" - -#define SYS_EXIT 1 -#define SYS_READ 3 -#define SYS_WRITE 4 -#define SYS_OPEN 5 -#define SYS_CLOSE 6 -#define SYS_BRK 17 -#define SYS_FSTAT 28 -#define SYS_ISATTY 29 -#define SYS_LSEEK 199 - -struct m68k_sim_stat { - uint16_t sim_st_dev; - uint16_t sim_st_ino; - uint32_t sim_st_mode; - uint16_t sim_st_nlink; - uint16_t sim_st_uid; - uint16_t sim_st_gid; - uint16_t sim_st_rdev; - uint32_t sim_st_size; - uint32_t sim_st_atime; - uint32_t sim_st_mtime; - uint32_t sim_st_ctime; - uint32_t sim_st_blksize; - uint32_t sim_st_blocks; -}; - -static inline uint32_t check_err(CPUM68KState *env, uint32_t code) -{ - env->dregs[0] = code; - if (code == (uint32_t)-1) { - env->dregs[1] = errno; - } else { - env->dregs[1] = 0; - } - return code; -} - -#define SIM_O_APPEND 0x0008 -#define SIM_O_CREAT 0x0200 -#define SIM_O_TRUNC 0x0400 -#define SIM_O_EXCL 0x0800 -#define SIM_O_NONBLOCK 0x4000 -#define SIM_O_NOCTTY 0x8000 -#define SIM_O_SYNC 0x2000 - -static int translate_openflags(int flags) -{ - int hf; - - switch (flags & 3) { - case 0: hf = O_RDONLY; break; - case 1: hf = O_WRONLY; break; - case 2: hf = O_RDWR; break; - default: hf = O_RDWR; break; - } - - if (flags & SIM_O_APPEND) hf |= O_APPEND; - if (flags & SIM_O_CREAT) hf |= O_CREAT; - if (flags & SIM_O_TRUNC) hf |= O_TRUNC; - if (flags & SIM_O_EXCL) hf |= O_EXCL; - if (flags & SIM_O_NONBLOCK) hf |= O_NONBLOCK; - if (flags & SIM_O_NOCTTY) hf |= O_NOCTTY; - if (flags & SIM_O_SYNC) hf |= O_SYNC; - - return hf; -} - -#define ARG(x) tswap32(args[x]) -void do_m68k_simcall(CPUM68KState *env, int nr) -{ - uint32_t *args; - - args = (uint32_t *)(unsigned long)(env->aregs[7] + 4); - switch (nr) { - case SYS_EXIT: - exit(ARG(0)); - case SYS_READ: - check_err(env, read(ARG(0), (void *)(unsigned long)ARG(1), ARG(2))); - break; - case SYS_WRITE: - check_err(env, write(ARG(0), (void *)(unsigned long)ARG(1), ARG(2))); - break; - case SYS_OPEN: - check_err(env, open((char *)(unsigned long)ARG(0), - translate_openflags(ARG(1)), ARG(2))); - break; - case SYS_CLOSE: - { - /* Ignore attempts to close stdin/out/err. */ - int fd = ARG(0); - if (fd > 2) - check_err(env, close(fd)); - else - check_err(env, 0); - break; - } - case SYS_BRK: - { - int32_t ret; - - ret = do_brk((abi_ulong)ARG(0)); - if (ret == -ENOMEM) - ret = -1; - check_err(env, ret); - } - break; - case SYS_FSTAT: - { - struct stat s; - int rc; - struct m68k_sim_stat *p; - rc = check_err(env, fstat(ARG(0), &s)); - if (rc == 0) { - p = (struct m68k_sim_stat *)(unsigned long)ARG(1); - p->sim_st_dev = tswap16(s.st_dev); - p->sim_st_ino = tswap16(s.st_ino); - p->sim_st_mode = tswap32(s.st_mode); - p->sim_st_nlink = tswap16(s.st_nlink); - p->sim_st_uid = tswap16(s.st_uid); - p->sim_st_gid = tswap16(s.st_gid); - p->sim_st_rdev = tswap16(s.st_rdev); - p->sim_st_size = tswap32(s.st_size); - p->sim_st_atime = tswap32(s.st_atime); - p->sim_st_mtime = tswap32(s.st_mtime); - p->sim_st_ctime = tswap32(s.st_ctime); - p->sim_st_blksize = tswap32(s.st_blksize); - p->sim_st_blocks = tswap32(s.st_blocks); - } - } - break; - case SYS_ISATTY: - check_err(env, isatty(ARG(0))); - break; - case SYS_LSEEK: - check_err(env, lseek(ARG(0), (int32_t)ARG(1), ARG(2))); - break; - default: - cpu_abort(env_cpu(env), "Unsupported m68k sim syscall %d\n", nr); - } -} diff --git a/linux-user/m68k/cpu_loop.c b/linux-user/m68k/cpu_loop.c index e8d39d15f3..c7a500b58c 100644 --- a/linux-user/m68k/cpu_loop.c +++ b/linux-user/m68k/cpu_loop.c @@ -28,7 +28,6 @@ void cpu_loop(CPUM68KState *env) int trapnr; unsigned int n; target_siginfo_t info; - TaskState *ts = cs->opaque; for(;;) { cpu_exec_start(cs); @@ -37,26 +36,14 @@ void cpu_loop(CPUM68KState *env) process_queued_cpu_work(cs); switch(trapnr) { - case EXCP_ILLEGAL: - { - if (ts->sim_syscalls) { - uint16_t nr; - get_user_u16(nr, env->pc + 2); - env->pc += 4; - do_m68k_simcall(env, nr); - } else { - goto do_sigill; - } - } - break; case EXCP_HALT_INSN: /* Semihosing syscall. */ env->pc += 4; do_m68k_semihosting(env, env->dregs[0]); break; + case EXCP_ILLEGAL: case EXCP_LINEA: case EXCP_LINEF: - do_sigill: info.si_signo = TARGET_SIGILL; info.si_errno = 0; info.si_code = TARGET_ILL_ILLOPN; @@ -80,7 +67,6 @@ void cpu_loop(CPUM68KState *env) case EXCP_TRAP0: { abi_long ret; - ts->sim_syscalls = 0; n = env->dregs[0]; env->pc += 2; ret = do_syscall(env, @@ -154,7 +140,6 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs) env->aregs[7] = regs->usp; env->sr = regs->sr; - ts->sim_syscalls = 1; ts->stack_base = info->start_stack; ts->heap_base = info->brk; /* This will be filled in on the first SYS_HEAPINFO call. */ diff --git a/linux-user/m68k/target_syscall.h b/linux-user/m68k/target_syscall.h index 632ee4fcf8..c0366b1c62 100644 --- a/linux-user/m68k/target_syscall.h +++ b/linux-user/m68k/target_syscall.h @@ -26,6 +26,4 @@ struct target_pt_regs { #define TARGET_WANT_OLD_SYS_SELECT -void do_m68k_simcall(CPUM68KState *, int); - #endif /* M68K_TARGET_SYSCALL_H */ diff --git a/linux-user/ppc/target_elf.h b/linux-user/ppc/target_elf.h index 576a5b9959..0616618854 100644 --- a/linux-user/ppc/target_elf.h +++ b/linux-user/ppc/target_elf.h @@ -10,7 +10,7 @@ static inline const char *cpu_get_model(uint32_t eflags) { #ifdef TARGET_PPC64 - return "POWER8"; + return "POWER9"; #else return "750"; #endif diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 82d33d7e93..fab287b7ec 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -116,7 +116,6 @@ typedef struct TaskState { #endif abi_ulong child_tidptr; #ifdef TARGET_M68K - int sim_syscalls; abi_ulong tp_value; #endif #if defined(TARGET_ARM) || defined(TARGET_M68K) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index b187c1281d..d2c9817938 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -102,6 +102,7 @@ #include <linux/blkpg.h> #include <netpacket/packet.h> #include <linux/netlink.h> +#include <linux/if_alg.h> #include "linux_loop.h" #include "uname.h" @@ -762,50 +763,21 @@ safe_syscall2(int, nanosleep, const struct timespec *, req, safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags, const struct timespec *, req, struct timespec *, rem) #endif -#if !defined(__NR_msgsnd) || !defined(__NR_msgrcv) || !defined(__NR_semtimedop) -/* This host kernel architecture uses a single ipc syscall; fake up - * wrappers for the sub-operations to hide this implementation detail. - * Annoyingly we can't include linux/ipc.h to get the constant definitions - * for the call parameter because some structs in there conflict with the - * sys/ipc.h ones. So we just define them here, and rely on them being - * the same for all host architectures. - */ -#define Q_SEMTIMEDOP 4 -#define Q_MSGSND 11 -#define Q_MSGRCV 12 -#define Q_IPCCALL(VERSION, OP) ((VERSION) << 16 | (OP)) - +#ifdef __NR_ipc safe_syscall6(int, ipc, int, call, long, first, long, second, long, third, void *, ptr, long, fifth) #endif #ifdef __NR_msgsnd safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz, int, flags) -#else -static int safe_msgsnd(int msgid, const void *msgp, size_t sz, int flags) -{ - return safe_ipc(Q_IPCCALL(0, Q_MSGSND), msgid, sz, flags, (void *)msgp, 0); -} #endif #ifdef __NR_msgrcv safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz, long, msgtype, int, flags) -#else -static int safe_msgrcv(int msgid, void *msgp, size_t sz, long type, int flags) -{ - return safe_ipc(Q_IPCCALL(1, Q_MSGRCV), msgid, sz, flags, msgp, type); -} #endif #ifdef __NR_semtimedop safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops, unsigned, nsops, const struct timespec *, timeout) -#else -static int safe_semtimedop(int semid, struct sembuf *tsops, unsigned nsops, - const struct timespec *timeout) -{ - return safe_ipc(Q_IPCCALL(0, Q_SEMTIMEDOP), semid, nsops, 0, tsops, - (long)timeout); -} #endif #if defined(TARGET_NR_mq_open) && defined(__NR_mq_open) safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr, @@ -1920,6 +1892,25 @@ static abi_long do_setsockopt(int sockfd, int level, int optname, &pki, sizeof(pki))); break; } + case IPV6_ADD_MEMBERSHIP: + case IPV6_DROP_MEMBERSHIP: + { + struct ipv6_mreq ipv6mreq; + + if (optlen < sizeof(ipv6mreq)) { + return -TARGET_EINVAL; + } + + if (copy_from_user(&ipv6mreq, optval_addr, sizeof(ipv6mreq))) { + return -TARGET_EFAULT; + } + + ipv6mreq.ipv6mr_interface = tswap32(ipv6mreq.ipv6mr_interface); + + ret = get_errno(setsockopt(sockfd, level, optname, + &ipv6mreq, sizeof(ipv6mreq))); + break; + } default: goto unimplemented; } @@ -1970,6 +1961,36 @@ static abi_long do_setsockopt(int sockfd, int level, int optname, goto unimplemented; } break; +#if defined(SOL_ALG) && defined(ALG_SET_KEY) && defined(ALG_SET_AEAD_AUTHSIZE) + case SOL_ALG: + switch (optname) { + case ALG_SET_KEY: + { + char *alg_key = g_malloc(optlen); + + if (!alg_key) { + return -TARGET_ENOMEM; + } + if (copy_from_user(alg_key, optval_addr, optlen)) { + g_free(alg_key); + return -TARGET_EFAULT; + } + ret = get_errno(setsockopt(sockfd, level, optname, + alg_key, optlen)); + g_free(alg_key); + break; + } + case ALG_SET_AEAD_AUTHSIZE: + { + ret = get_errno(setsockopt(sockfd, level, optname, + NULL, optlen)); + break; + } + default: + goto unimplemented; + } + break; +#endif case TARGET_SOL_SOCKET: switch (optname) { case TARGET_SO_RCVTIMEO: @@ -3529,11 +3550,21 @@ static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf, static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops) { struct sembuf sops[nsops]; + abi_long ret; if (target_to_host_sembuf(sops, ptr, nsops)) return -TARGET_EFAULT; - return get_errno(safe_semtimedop(semid, sops, nsops, NULL)); + ret = -TARGET_ENOSYS; +#ifdef __NR_semtimedop + ret = get_errno(safe_semtimedop(semid, sops, nsops, NULL)); +#endif +#ifdef __NR_ipc + if (ret == -TARGET_ENOSYS) { + ret = get_errno(safe_ipc(IPCOP_semtimedop, semid, nsops, 0, sops, 0)); + } +#endif + return ret; } struct target_msqid_ds @@ -3688,7 +3719,16 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp, } host_mb->mtype = (abi_long) tswapal(target_mb->mtype); memcpy(host_mb->mtext, target_mb->mtext, msgsz); + ret = -TARGET_ENOSYS; +#ifdef __NR_msgsnd ret = get_errno(safe_msgsnd(msqid, host_mb, msgsz, msgflg)); +#endif +#ifdef __NR_ipc + if (ret == -TARGET_ENOSYS) { + ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg, + host_mb, 0)); + } +#endif g_free(host_mb); unlock_user_struct(target_mb, msgp, 0); @@ -3716,7 +3756,16 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp, ret = -TARGET_ENOMEM; goto end; } + ret = -TARGET_ENOSYS; +#ifdef __NR_msgrcv ret = get_errno(safe_msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg)); +#endif +#ifdef __NR_ipc + if (ret == -TARGET_ENOSYS) { + ret = get_errno(safe_ipc(IPCOP_CALL(1, IPCOP_msgrcv), msqid, msgsz, + msgflg, host_mb, msgtyp)); + } +#endif if (ret > 0) { abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong); diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 7f141f699c..3175440e9d 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -32,6 +32,7 @@ #define TARGET_SYS_RECVMMSG 19 /* recvmmsg() */ #define TARGET_SYS_SENDMMSG 20 /* sendmmsg() */ +#define IPCOP_CALL(VERSION, OP) ((VERSION) << 16 | (OP)) #define IPCOP_semop 1 #define IPCOP_semget 2 #define IPCOP_semctl 3 |