aboutsummaryrefslogtreecommitdiff
path: root/linux-user
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2019-07-01 15:55:40 +0100
committerPeter Maydell <peter.maydell@linaro.org>2019-07-01 15:55:40 +0100
commitae9108f8f0746ce64d02afb1a216153a50926132 (patch)
tree39be1aa6762b6f1125164e6d0517c0893e1de37b /linux-user
parent8351ef7aa92defd961581b12c8a340d49450a397 (diff)
parentb50d1e42a4a7dc746ecd42c34c386d81a997759c (diff)
downloadqemu-ae9108f8f0746ce64d02afb1a216153a50926132.zip
qemu-ae9108f8f0746ce64d02afb1a216153a50926132.tar.gz
qemu-ae9108f8f0746ce64d02afb1a216153a50926132.tar.bz2
Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-4.1-pull-request' into staging
Update ppc64 feature and default CPU next setsockops() options Improve "-L" option Another fix for 5.2-rc1 headers # gpg: Signature made Wed 26 Jun 2019 13:11:04 BST # gpg: using RSA key CD2F75DDC8E3A4DC2E4F5173F30C38BD3F2FBE3C # gpg: issuer "laurent@vivier.eu" # gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>" [full] # gpg: aka "Laurent Vivier <laurent@vivier.eu>" [full] # gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>" [full] # Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C * remotes/vivier2/tags/linux-user-for-4.1-pull-request: linux-user: set default PPC64 CPU linux-user: update PPC64 HWCAP2 feature list linux-user: Add support for setsockopt() options IPV6_<ADD|DROP>_MEMBERSHIP linux-user: Add support for setsockopt() option SOL_ALG linux-user: emulate msgsnd(), msgrcv() and semtimedop() util/path: Do not cache all filenames at startup Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'linux-user')
-rw-r--r--linux-user/elfload.c12
-rw-r--r--linux-user/ppc/target_elf.h2
-rw-r--r--linux-user/syscall.c111
-rw-r--r--linux-user/syscall_defs.h1
4 files changed, 92 insertions, 34 deletions
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 9fd6570..bd43c48 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/ppc/target_elf.h b/linux-user/ppc/target_elf.h
index 576a5b9..0616618 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/syscall.c b/linux-user/syscall.c
index b187c12..d2c9817 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 7f141f6..3175440 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