mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-06 09:13:55 -06:00
Pull request linux-user 20230308-v2
Fix gdt on i386/x86_64 Handle traps on sparc Add translation for argument of msync Emulate CLONE_PIDFD flag in clone handle netlink flag NLA_F_NESTED fix sockaddr_in6 endianness Fix brk() to release pages fill out task state in /proc/self/stat add support for xtensa FDPIC Fix unaligned memory access in prlimit64 syscall add target to host netlink conversions fix timerfd read endianness conversion Fix access to /proc/self/exe Add strace for prlimit64() syscall -----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEEzS913cjjpNwuT1Fz8ww4vT8vvjwFAmQLqmMSHGxhdXJlbnRA dml2aWVyLmV1AAoJEPMMOL0/L748e+cP/3XYMvPbExNi09idDvgzzBrFFHgnkCnK WAV/laxjHSJkzRNK06jD5KN/G2Osy587GXAWLaN76Y8mYMNJs5x3wwlBrJm0RyeJ mWeETJOjxsFjW1+5LKhYv6fwiDxQcyJUoRKzJI27fYgDS+H+zIpa+uhy82Ah543z i/HPyerp25TWAuVyR6mQICt7cne+4yjhtcjg0GXmnvm2+UVp54FGjesjwpSdbALl OKdCre/JaNOkKoaRSsxm0UhNEyQarJIEf/dv0fTjsEpvNX2SMuLUGCm+n23wjXGN fdnSGkoVe8hHxBtG80Zx8AMfKEmJoVsQw9rSg4HwQKOyrYPnLhHjb8ln43X+f3MN gq9lDBIxH82LH2Q5JqQQe7S2UJycpYb+qj0xm7llH7Wl9VVKG6hRX/Cd7I1PQLEv baPIrtye5TuR6uo0kn6HBB+Hd9RNu2PPHelmEFIGEuNaAPkyOt4FhKFIE/j0BTcg mFVCNj6Os805ks0sjIBvpTU1DBtuqpLxdvvHOwxYKCNThTl70wfHJJEjumfvZ4qT T+me7hRsd+8v1rRjxYGuJn2gqC7JL8miuJCYlZkn2DfMAunmF00U5ULe9KiCJ8V3 kDfvO+CdnIN4MSlbtwt+eRSFCmJGGkzZ/jshVxPF3ZVirFu/undphYQnaEZDH+Xd KsPOh8MekMgJ =e55j -----END PGP SIGNATURE----- Merge tag 'linux-user-for-8.0-pull-request' of https://gitlab.com/laurent_vivier/qemu into staging Pull request linux-user 20230308-v2 Fix gdt on i386/x86_64 Handle traps on sparc Add translation for argument of msync Emulate CLONE_PIDFD flag in clone handle netlink flag NLA_F_NESTED fix sockaddr_in6 endianness Fix brk() to release pages fill out task state in /proc/self/stat add support for xtensa FDPIC Fix unaligned memory access in prlimit64 syscall add target to host netlink conversions fix timerfd read endianness conversion Fix access to /proc/self/exe Add strace for prlimit64() syscall # -----BEGIN PGP SIGNATURE----- # # iQJGBAABCAAwFiEEzS913cjjpNwuT1Fz8ww4vT8vvjwFAmQLqmMSHGxhdXJlbnRA # dml2aWVyLmV1AAoJEPMMOL0/L748e+cP/3XYMvPbExNi09idDvgzzBrFFHgnkCnK # WAV/laxjHSJkzRNK06jD5KN/G2Osy587GXAWLaN76Y8mYMNJs5x3wwlBrJm0RyeJ # mWeETJOjxsFjW1+5LKhYv6fwiDxQcyJUoRKzJI27fYgDS+H+zIpa+uhy82Ah543z # i/HPyerp25TWAuVyR6mQICt7cne+4yjhtcjg0GXmnvm2+UVp54FGjesjwpSdbALl # OKdCre/JaNOkKoaRSsxm0UhNEyQarJIEf/dv0fTjsEpvNX2SMuLUGCm+n23wjXGN # fdnSGkoVe8hHxBtG80Zx8AMfKEmJoVsQw9rSg4HwQKOyrYPnLhHjb8ln43X+f3MN # gq9lDBIxH82LH2Q5JqQQe7S2UJycpYb+qj0xm7llH7Wl9VVKG6hRX/Cd7I1PQLEv # baPIrtye5TuR6uo0kn6HBB+Hd9RNu2PPHelmEFIGEuNaAPkyOt4FhKFIE/j0BTcg # mFVCNj6Os805ks0sjIBvpTU1DBtuqpLxdvvHOwxYKCNThTl70wfHJJEjumfvZ4qT # T+me7hRsd+8v1rRjxYGuJn2gqC7JL8miuJCYlZkn2DfMAunmF00U5ULe9KiCJ8V3 # kDfvO+CdnIN4MSlbtwt+eRSFCmJGGkzZ/jshVxPF3ZVirFu/undphYQnaEZDH+Xd # KsPOh8MekMgJ # =e55j # -----END PGP SIGNATURE----- # gpg: Signature made Fri 10 Mar 2023 22:08:35 GMT # 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 * tag 'linux-user-for-8.0-pull-request' of https://gitlab.com/laurent_vivier/qemu: (28 commits) linux-user: fix bug about incorrect base addresss of gdt on i386 and x86_64 linux-user/sparc: Handle tag overflow traps linux-user/sparc: Handle floating-point exceptions linux-user/sparc: Handle unimplemented flush trap linux-user/sparc: Handle coprocessor disabled trap linux-user/sparc: Handle privilidged action trap linux-user/sparc: Handle priviledged opcode trap linux-user/sparc: Handle getcc, setcc, getpsr traps linux-user/sparc: Handle division by zero traps linux-user/sparc: Handle software breakpoint trap linux-user/sparc: Fix sparc64_{get, set}_context traps linux-user/sparc: Tidy window spill/fill traps linux-user/sparc: Use TT_TRAP for flush windows linux-user/sparc: Tidy syscall error return linux-user/sparc: Tidy syscall trap linux-user: Emulate CLONE_PIDFD flag in clone() linux-user: Add translation for argument of msync() linux-user: handle netlink flag NLA_F_NESTED linux-user: fix sockaddr_in6 endianness linux-user: Add strace for prlimit64() syscall ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
29c8a9e31a
18 changed files with 521 additions and 141 deletions
|
@ -3,6 +3,10 @@
|
|||
|
||||
#define TARGET_MADV_DONTNEED 6
|
||||
|
||||
#define TARGET_MS_ASYNC 1
|
||||
#define TARGET_MS_SYNC 2
|
||||
#define TARGET_MS_INVALIDATE 4
|
||||
|
||||
#include "../generic/target_mman.h"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1748,6 +1748,15 @@ static inline void init_thread(struct target_pt_regs *regs,
|
|||
regs->windowstart = 1;
|
||||
regs->areg[1] = infop->start_stack;
|
||||
regs->pc = infop->entry;
|
||||
if (info_is_fdpic(infop)) {
|
||||
regs->areg[4] = infop->loadmap_addr;
|
||||
regs->areg[5] = infop->interpreter_loadmap_addr;
|
||||
if (infop->interpreter_loadmap_addr) {
|
||||
regs->areg[6] = infop->interpreter_pt_dynamic_addr;
|
||||
} else {
|
||||
regs->areg[6] = infop->pt_dynamic_addr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* See linux kernel: arch/xtensa/include/asm/elf.h. */
|
||||
|
@ -2207,11 +2216,16 @@ static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef TARGET_ARM
|
||||
#if defined(TARGET_ARM)
|
||||
static int elf_is_fdpic(struct elfhdr *exec)
|
||||
{
|
||||
return exec->e_ident[EI_OSABI] == ELFOSABI_ARM_FDPIC;
|
||||
}
|
||||
#elif defined(TARGET_XTENSA)
|
||||
static int elf_is_fdpic(struct elfhdr *exec)
|
||||
{
|
||||
return exec->e_ident[EI_OSABI] == ELFOSABI_XTENSA_FDPIC;
|
||||
}
|
||||
#else
|
||||
/* Default implementation, always false. */
|
||||
static int elf_is_fdpic(struct elfhdr *exec)
|
||||
|
|
|
@ -1284,6 +1284,49 @@ static inline abi_long host_to_target_nlmsg_route(struct nlmsghdr *nlh,
|
|||
return host_to_target_for_each_nlmsg(nlh, len, host_to_target_data_route);
|
||||
}
|
||||
|
||||
static abi_long target_to_host_for_each_nlattr(struct nlattr *nlattr,
|
||||
size_t len,
|
||||
abi_long (*target_to_host_nlattr)
|
||||
(struct nlattr *))
|
||||
{
|
||||
unsigned short aligned_nla_len;
|
||||
abi_long ret;
|
||||
|
||||
while (len > sizeof(struct nlattr)) {
|
||||
if (tswap16(nlattr->nla_len) < sizeof(struct rtattr) ||
|
||||
tswap16(nlattr->nla_len) > len) {
|
||||
break;
|
||||
}
|
||||
nlattr->nla_len = tswap16(nlattr->nla_len);
|
||||
nlattr->nla_type = tswap16(nlattr->nla_type);
|
||||
ret = target_to_host_nlattr(nlattr);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
aligned_nla_len = NLA_ALIGN(nlattr->nla_len);
|
||||
if (aligned_nla_len >= len) {
|
||||
break;
|
||||
}
|
||||
len -= aligned_nla_len;
|
||||
nlattr = (struct nlattr *)(((char *)nlattr) + aligned_nla_len);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static abi_long target_to_host_data_inet6_nlattr(struct nlattr *nlattr)
|
||||
{
|
||||
switch (nlattr->nla_type) {
|
||||
/* uint8_t */
|
||||
case QEMU_IFLA_INET6_ADDR_GEN_MODE:
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "Unknown target AF_INET6 type: %d\n",
|
||||
nlattr->nla_type);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static abi_long target_to_host_for_each_rtattr(struct rtattr *rtattr,
|
||||
size_t len,
|
||||
abi_long (*target_to_host_rtattr)
|
||||
|
@ -1314,16 +1357,35 @@ static abi_long target_to_host_for_each_rtattr(struct rtattr *rtattr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static abi_long target_to_host_data_spec_nlattr(struct nlattr *nlattr)
|
||||
{
|
||||
switch (nlattr->nla_type & NLA_TYPE_MASK) {
|
||||
case AF_INET6:
|
||||
return target_to_host_for_each_nlattr(NLA_DATA(nlattr), nlattr->nla_len,
|
||||
target_to_host_data_inet6_nlattr);
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "Unknown target AF_SPEC type: %d\n",
|
||||
nlattr->nla_type);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static abi_long target_to_host_data_link_rtattr(struct rtattr *rtattr)
|
||||
{
|
||||
uint32_t *u32;
|
||||
|
||||
switch (rtattr->rta_type) {
|
||||
switch (rtattr->rta_type & NLA_TYPE_MASK) {
|
||||
/* uint32_t */
|
||||
case QEMU_IFLA_MTU:
|
||||
case QEMU_IFLA_TXQLEN:
|
||||
case QEMU_IFLA_EXT_MASK:
|
||||
u32 = RTA_DATA(rtattr);
|
||||
*u32 = tswap32(*u32);
|
||||
break;
|
||||
case QEMU_IFLA_AF_SPEC:
|
||||
return target_to_host_for_each_nlattr(RTA_DATA(rtattr), rtattr->rta_len,
|
||||
target_to_host_data_spec_nlattr);
|
||||
default:
|
||||
qemu_log_mask(LOG_UNIMP, "Unknown target QEMU_IFLA type: %d\n",
|
||||
rtattr->rta_type);
|
||||
|
@ -1622,7 +1684,7 @@ TargetFdTrans target_signalfd_trans = {
|
|||
.host_to_target_data = host_to_target_data_signalfd,
|
||||
};
|
||||
|
||||
static abi_long swap_data_eventfd(void *buf, size_t len)
|
||||
static abi_long swap_data_u64(void *buf, size_t len)
|
||||
{
|
||||
uint64_t *counter = buf;
|
||||
int i;
|
||||
|
@ -1640,8 +1702,12 @@ static abi_long swap_data_eventfd(void *buf, size_t len)
|
|||
}
|
||||
|
||||
TargetFdTrans target_eventfd_trans = {
|
||||
.host_to_target_data = swap_data_eventfd,
|
||||
.target_to_host_data = swap_data_eventfd,
|
||||
.host_to_target_data = swap_data_u64,
|
||||
.target_to_host_data = swap_data_u64,
|
||||
};
|
||||
|
||||
TargetFdTrans target_timerfd_trans = {
|
||||
.host_to_target_data = swap_data_u64,
|
||||
};
|
||||
|
||||
#if defined(CONFIG_INOTIFY) && (defined(TARGET_NR_inotify_init) || \
|
||||
|
|
|
@ -130,6 +130,7 @@ extern TargetFdTrans target_netlink_route_trans;
|
|||
extern TargetFdTrans target_netlink_audit_trans;
|
||||
extern TargetFdTrans target_signalfd_trans;
|
||||
extern TargetFdTrans target_eventfd_trans;
|
||||
extern TargetFdTrans target_timerfd_trans;
|
||||
#if (defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)) || \
|
||||
(defined(CONFIG_INOTIFY1) && defined(TARGET_NR_inotify_init1) && \
|
||||
defined(__NR_inotify_init1))
|
||||
|
|
|
@ -89,4 +89,17 @@
|
|||
#define TARGET_MADV_DONTNEED_LOCKED 24
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef TARGET_MS_ASYNC
|
||||
#define TARGET_MS_ASYNC 1
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_MS_INVALIDATE
|
||||
#define TARGET_MS_INVALIDATE 2
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_MS_SYNC
|
||||
#define TARGET_MS_SYNC 4
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -12,8 +12,8 @@ struct target_rlimit {
|
|||
};
|
||||
|
||||
struct target_rlimit64 {
|
||||
uint64_t rlim_cur;
|
||||
uint64_t rlim_max;
|
||||
abi_ullong rlim_cur;
|
||||
abi_ullong rlim_max;
|
||||
};
|
||||
|
||||
#define TARGET_RLIM_INFINITY ((abi_ulong)-1)
|
||||
|
|
|
@ -10,6 +10,10 @@
|
|||
#define TARGET_MADV_WIPEONFORK 71
|
||||
#define TARGET_MADV_KEEPONFORK 72
|
||||
|
||||
#define TARGET_MS_SYNC 1
|
||||
#define TARGET_MS_ASYNC 2
|
||||
#define TARGET_MS_INVALIDATE 4
|
||||
|
||||
#include "../generic/target_mman.h"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -314,8 +314,17 @@ void cpu_loop(CPUX86State *env)
|
|||
}
|
||||
}
|
||||
|
||||
static void target_cpu_free(void *obj)
|
||||
{
|
||||
CPUArchState *env = ((CPUState *)obj)->env_ptr;
|
||||
target_munmap(env->gdt.base, sizeof(uint64_t) * TARGET_GDT_ENTRIES);
|
||||
g_free(obj);
|
||||
}
|
||||
|
||||
void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
|
||||
{
|
||||
CPUState *cpu = env_cpu(env);
|
||||
OBJECT(cpu)->free = target_cpu_free;
|
||||
env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
|
||||
env->hflags |= HF_PE_MASK | HF_CPL_MASK;
|
||||
if (env->features[FEAT_1_EDX] & CPUID_SSE) {
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
#endif
|
||||
|
||||
char *exec_path;
|
||||
char real_exec_path[PATH_MAX];
|
||||
|
||||
int singlestep;
|
||||
static const char *argv0;
|
||||
|
@ -238,6 +239,14 @@ CPUArchState *cpu_copy(CPUArchState *env)
|
|||
|
||||
new_cpu->tcg_cflags = cpu->tcg_cflags;
|
||||
memcpy(new_env, env, sizeof(CPUArchState));
|
||||
#if defined(TARGET_I386) || defined(TARGET_X86_64)
|
||||
new_env->gdt.base = target_mmap(0, sizeof(uint64_t) * TARGET_GDT_ENTRIES,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||
memcpy(g2h_untagged(new_env->gdt.base), g2h_untagged(env->gdt.base),
|
||||
sizeof(uint64_t) * TARGET_GDT_ENTRIES);
|
||||
OBJECT(new_cpu)->free = OBJECT(cpu)->free;
|
||||
#endif
|
||||
|
||||
/* Clone all break/watchpoints.
|
||||
Note: Once we support ptrace with hw-debug register access, make sure
|
||||
|
@ -740,6 +749,11 @@ int main(int argc, char **argv, char **envp)
|
|||
}
|
||||
}
|
||||
|
||||
/* Resolve executable file name to full path name */
|
||||
if (realpath(exec_path, real_exec_path)) {
|
||||
exec_path = real_exec_path;
|
||||
}
|
||||
|
||||
/*
|
||||
* get binfmt_misc flags
|
||||
*/
|
||||
|
|
|
@ -149,6 +149,69 @@ static void flush_windows(CPUSPARCState *env)
|
|||
#endif
|
||||
}
|
||||
|
||||
static void next_instruction(CPUSPARCState *env)
|
||||
{
|
||||
env->pc = env->npc;
|
||||
env->npc = env->npc + 4;
|
||||
}
|
||||
|
||||
static uint32_t do_getcc(CPUSPARCState *env)
|
||||
{
|
||||
#ifdef TARGET_SPARC64
|
||||
return cpu_get_ccr(env) & 0xf;
|
||||
#else
|
||||
return extract32(cpu_get_psr(env), 20, 4);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void do_setcc(CPUSPARCState *env, uint32_t icc)
|
||||
{
|
||||
#ifdef TARGET_SPARC64
|
||||
cpu_put_ccr(env, (cpu_get_ccr(env) & 0xf0) | (icc & 0xf));
|
||||
#else
|
||||
cpu_put_psr(env, deposit32(cpu_get_psr(env), 20, 4, icc));
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t do_getpsr(CPUSPARCState *env)
|
||||
{
|
||||
#ifdef TARGET_SPARC64
|
||||
const uint64_t TSTATE_CWP = 0x1f;
|
||||
const uint64_t TSTATE_ICC = 0xfull << 32;
|
||||
const uint64_t TSTATE_XCC = 0xfull << 36;
|
||||
const uint32_t PSR_S = 0x00000080u;
|
||||
const uint32_t PSR_V8PLUS = 0xff000000u;
|
||||
uint64_t tstate = sparc64_tstate(env);
|
||||
|
||||
/* See <asm/psrcompat.h>, tstate_to_psr. */
|
||||
return ((tstate & TSTATE_CWP) |
|
||||
PSR_S |
|
||||
((tstate & TSTATE_ICC) >> 12) |
|
||||
((tstate & TSTATE_XCC) >> 20) |
|
||||
PSR_V8PLUS);
|
||||
#else
|
||||
return (cpu_get_psr(env) & (PSR_ICC | PSR_CWP)) | PSR_S;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Avoid ifdefs below for the abi32 and abi64 paths. */
|
||||
#ifdef TARGET_ABI32
|
||||
#define TARGET_TT_SYSCALL (TT_TRAP + 0x10) /* t_linux */
|
||||
#define syscall_cc psr
|
||||
#else
|
||||
#define TARGET_TT_SYSCALL (TT_TRAP + 0x6d) /* tl0_linux64 */
|
||||
#define syscall_cc xcc
|
||||
#endif
|
||||
|
||||
/* Avoid ifdefs below for the v9 and pre-v9 hw traps. */
|
||||
#ifdef TARGET_SPARC64
|
||||
#define TARGET_TT_SPILL TT_SPILL
|
||||
#define TARGET_TT_FILL TT_FILL
|
||||
#else
|
||||
#define TARGET_TT_SPILL TT_WIN_OVF
|
||||
#define TARGET_TT_FILL TT_WIN_UNF
|
||||
#endif
|
||||
|
||||
void cpu_loop (CPUSPARCState *env)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
|
@ -167,13 +230,7 @@ void cpu_loop (CPUSPARCState *env)
|
|||
}
|
||||
|
||||
switch (trapnr) {
|
||||
#ifndef TARGET_SPARC64
|
||||
case 0x88:
|
||||
case 0x90:
|
||||
#else
|
||||
case 0x110:
|
||||
case 0x16d:
|
||||
#endif
|
||||
case TARGET_TT_SYSCALL:
|
||||
ret = do_syscall (env, env->gregs[1],
|
||||
env->regwptr[0], env->regwptr[1],
|
||||
env->regwptr[2], env->regwptr[3],
|
||||
|
@ -183,67 +240,110 @@ void cpu_loop (CPUSPARCState *env)
|
|||
break;
|
||||
}
|
||||
if ((abi_ulong)ret >= (abi_ulong)(-515)) {
|
||||
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
|
||||
env->xcc |= PSR_CARRY;
|
||||
#else
|
||||
env->psr |= PSR_CARRY;
|
||||
#endif
|
||||
env->syscall_cc |= PSR_CARRY;
|
||||
ret = -ret;
|
||||
} else {
|
||||
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
|
||||
env->xcc &= ~PSR_CARRY;
|
||||
#else
|
||||
env->psr &= ~PSR_CARRY;
|
||||
#endif
|
||||
env->syscall_cc &= ~PSR_CARRY;
|
||||
}
|
||||
env->regwptr[0] = ret;
|
||||
/* next instruction */
|
||||
env->pc = env->npc;
|
||||
env->npc = env->npc + 4;
|
||||
break;
|
||||
case 0x83: /* flush windows */
|
||||
#ifdef TARGET_ABI32
|
||||
case 0x103:
|
||||
#endif
|
||||
|
||||
case TT_TRAP + 0x01: /* breakpoint */
|
||||
case EXCP_DEBUG:
|
||||
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
|
||||
break;
|
||||
|
||||
case TT_TRAP + 0x02: /* div0 */
|
||||
case TT_DIV_ZERO:
|
||||
force_sig_fault(TARGET_SIGFPE, TARGET_FPE_INTDIV, env->pc);
|
||||
break;
|
||||
|
||||
case TT_TRAP + 0x03: /* flush windows */
|
||||
flush_windows(env);
|
||||
/* next instruction */
|
||||
env->pc = env->npc;
|
||||
env->npc = env->npc + 4;
|
||||
next_instruction(env);
|
||||
break;
|
||||
#ifndef TARGET_SPARC64
|
||||
case TT_WIN_OVF: /* window overflow */
|
||||
save_window(env);
|
||||
|
||||
case TT_TRAP + 0x20: /* getcc */
|
||||
env->gregs[1] = do_getcc(env);
|
||||
next_instruction(env);
|
||||
break;
|
||||
case TT_WIN_UNF: /* window underflow */
|
||||
restore_window(env);
|
||||
case TT_TRAP + 0x21: /* setcc */
|
||||
do_setcc(env, env->gregs[1]);
|
||||
next_instruction(env);
|
||||
break;
|
||||
#else
|
||||
case TT_SPILL: /* window overflow */
|
||||
save_window(env);
|
||||
case TT_TRAP + 0x22: /* getpsr */
|
||||
env->gregs[1] = do_getpsr(env);
|
||||
next_instruction(env);
|
||||
break;
|
||||
case TT_FILL: /* window underflow */
|
||||
restore_window(env);
|
||||
break;
|
||||
#ifndef TARGET_ABI32
|
||||
case 0x16e:
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
case TT_TRAP + 0x6e:
|
||||
flush_windows(env);
|
||||
sparc64_get_context(env);
|
||||
break;
|
||||
case 0x16f:
|
||||
case TT_TRAP + 0x6f:
|
||||
flush_windows(env);
|
||||
sparc64_set_context(env);
|
||||
break;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
case TARGET_TT_SPILL: /* window overflow */
|
||||
save_window(env);
|
||||
break;
|
||||
case TARGET_TT_FILL: /* window underflow */
|
||||
restore_window(env);
|
||||
break;
|
||||
|
||||
case TT_FP_EXCP:
|
||||
{
|
||||
int code = TARGET_FPE_FLTUNK;
|
||||
target_ulong fsr = env->fsr;
|
||||
|
||||
if ((fsr & FSR_FTT_MASK) == FSR_FTT_IEEE_EXCP) {
|
||||
if (fsr & FSR_NVC) {
|
||||
code = TARGET_FPE_FLTINV;
|
||||
} else if (fsr & FSR_OFC) {
|
||||
code = TARGET_FPE_FLTOVF;
|
||||
} else if (fsr & FSR_UFC) {
|
||||
code = TARGET_FPE_FLTUND;
|
||||
} else if (fsr & FSR_DZC) {
|
||||
code = TARGET_FPE_FLTDIV;
|
||||
} else if (fsr & FSR_NXC) {
|
||||
code = TARGET_FPE_FLTRES;
|
||||
}
|
||||
}
|
||||
force_sig_fault(TARGET_SIGFPE, code, env->pc);
|
||||
}
|
||||
break;
|
||||
|
||||
case EXCP_INTERRUPT:
|
||||
/* just indicate that signals should be handled asap */
|
||||
break;
|
||||
case TT_ILL_INSN:
|
||||
force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc);
|
||||
break;
|
||||
case EXCP_DEBUG:
|
||||
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc);
|
||||
case TT_PRIV_INSN:
|
||||
force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->pc);
|
||||
break;
|
||||
case TT_TOVF:
|
||||
force_sig_fault(TARGET_SIGEMT, TARGET_EMT_TAGOVF, env->pc);
|
||||
break;
|
||||
#ifdef TARGET_SPARC64
|
||||
case TT_PRIV_ACT:
|
||||
/* Note do_privact defers to do_privop. */
|
||||
force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->pc);
|
||||
break;
|
||||
#else
|
||||
case TT_NCP_INSN:
|
||||
force_sig_fault(TARGET_SIGILL, TARGET_ILL_COPROC, env->pc);
|
||||
break;
|
||||
case TT_UNIMP_FLUSH:
|
||||
next_instruction(env);
|
||||
break;
|
||||
#endif
|
||||
case EXCP_ATOMIC:
|
||||
cpu_exec_step_atomic(cs);
|
||||
break;
|
||||
|
|
|
@ -503,7 +503,23 @@ long do_rt_sigreturn(CPUSPARCState *env)
|
|||
return -QEMU_ESIGRETURN;
|
||||
}
|
||||
|
||||
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32)
|
||||
#ifdef TARGET_ABI32
|
||||
void setup_sigtramp(abi_ulong sigtramp_page)
|
||||
{
|
||||
uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0);
|
||||
assert(tramp != NULL);
|
||||
|
||||
default_sigreturn = sigtramp_page;
|
||||
install_sigtramp(tramp, TARGET_NR_sigreturn);
|
||||
|
||||
default_rt_sigreturn = sigtramp_page + 8;
|
||||
install_sigtramp(tramp + 2, TARGET_NR_rt_sigreturn);
|
||||
|
||||
unlock_user(tramp, sigtramp_page, 2 * 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_SPARC64
|
||||
#define SPARC_MC_TSTATE 0
|
||||
#define SPARC_MC_PC 1
|
||||
#define SPARC_MC_NPC 2
|
||||
|
@ -575,7 +591,7 @@ void sparc64_set_context(CPUSPARCState *env)
|
|||
struct target_ucontext *ucp;
|
||||
target_mc_gregset_t *grp;
|
||||
target_mc_fpu_t *fpup;
|
||||
abi_ulong pc, npc, tstate;
|
||||
target_ulong pc, npc, tstate;
|
||||
unsigned int i;
|
||||
unsigned char fenab;
|
||||
|
||||
|
@ -773,18 +789,4 @@ do_sigsegv:
|
|||
unlock_user_struct(ucp, ucp_addr, 1);
|
||||
force_sig(TARGET_SIGSEGV);
|
||||
}
|
||||
#else
|
||||
void setup_sigtramp(abi_ulong sigtramp_page)
|
||||
{
|
||||
uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 2 * 8, 0);
|
||||
assert(tramp != NULL);
|
||||
|
||||
default_sigreturn = sigtramp_page;
|
||||
install_sigtramp(tramp, TARGET_NR_sigreturn);
|
||||
|
||||
default_rt_sigreturn = sigtramp_page + 8;
|
||||
install_sigtramp(tramp + 2, TARGET_NR_rt_sigreturn);
|
||||
|
||||
unlock_user(tramp, sigtramp_page, 2 * 8);
|
||||
}
|
||||
#endif
|
||||
#endif /* TARGET_SPARC64 */
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#define TARGET_SIGTRAP 5
|
||||
#define TARGET_SIGABRT 6
|
||||
#define TARGET_SIGIOT 6
|
||||
#define TARGET_SIGSTKFLT 7 /* actually EMT */
|
||||
#define TARGET_SIGEMT 7
|
||||
#define TARGET_SIGFPE 8
|
||||
#define TARGET_SIGKILL 9
|
||||
#define TARGET_SIGBUS 10
|
||||
|
|
|
@ -81,6 +81,7 @@ UNUSED static void print_syscall_epilogue(const struct syscallname *);
|
|||
UNUSED static void print_string(abi_long, int);
|
||||
UNUSED static void print_buf(abi_long addr, abi_long len, int last);
|
||||
UNUSED static void print_raw_param(const char *, abi_long, int);
|
||||
UNUSED static void print_raw_param64(const char *, long long, int last);
|
||||
UNUSED static void print_timeval(abi_ulong, int);
|
||||
UNUSED static void print_timespec(abi_ulong, int);
|
||||
UNUSED static void print_timespec64(abi_ulong, int);
|
||||
|
@ -1110,11 +1111,16 @@ UNUSED static const struct flags mmap_flags[] = {
|
|||
FLAG_END,
|
||||
};
|
||||
|
||||
#ifndef CLONE_PIDFD
|
||||
# define CLONE_PIDFD 0x00001000
|
||||
#endif
|
||||
|
||||
UNUSED static const struct flags clone_flags[] = {
|
||||
FLAG_GENERIC(CLONE_VM),
|
||||
FLAG_GENERIC(CLONE_FS),
|
||||
FLAG_GENERIC(CLONE_FILES),
|
||||
FLAG_GENERIC(CLONE_SIGHAND),
|
||||
FLAG_GENERIC(CLONE_PIDFD),
|
||||
FLAG_GENERIC(CLONE_PTRACE),
|
||||
FLAG_GENERIC(CLONE_VFORK),
|
||||
FLAG_GENERIC(CLONE_PARENT),
|
||||
|
@ -1642,6 +1648,19 @@ print_raw_param(const char *fmt, abi_long param, int last)
|
|||
qemu_log(format, param);
|
||||
}
|
||||
|
||||
/*
|
||||
* Same as print_raw_param() but prints out raw 64-bit parameter.
|
||||
*/
|
||||
static void
|
||||
print_raw_param64(const char *fmt, long long param, int last)
|
||||
{
|
||||
char format[64];
|
||||
|
||||
(void)snprintf(format, sizeof(format), "%s%s", fmt, get_comma(last));
|
||||
qemu_log(format, param);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
print_pointer(abi_long p, int last)
|
||||
{
|
||||
|
@ -1718,10 +1737,8 @@ print_timespec64(abi_ulong ts_addr, int last)
|
|||
print_pointer(ts_addr, last);
|
||||
return;
|
||||
}
|
||||
qemu_log("{tv_sec = %lld"
|
||||
",tv_nsec = %lld}%s",
|
||||
(long long)tswap64(ts->tv_sec), (long long)tswap64(ts->tv_nsec),
|
||||
get_comma(last));
|
||||
print_raw_param64("{tv_sec=%" PRId64, tswap64(ts->tv_sec), 0);
|
||||
print_raw_param64("tv_nsec=%" PRId64 "}", tswap64(ts->tv_nsec), last);
|
||||
unlock_user(ts, ts_addr, 0);
|
||||
} else {
|
||||
qemu_log("NULL%s", get_comma(last));
|
||||
|
@ -3854,6 +3871,94 @@ print_futex(CPUArchState *cpu_env, const struct syscallname *name,
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_prlimit64
|
||||
static const char *target_ressource_string(abi_ulong r)
|
||||
{
|
||||
#define RET_RES_ENTRY(res) case TARGET_##res: return #res;
|
||||
switch (r) {
|
||||
RET_RES_ENTRY(RLIMIT_AS);
|
||||
RET_RES_ENTRY(RLIMIT_CORE);
|
||||
RET_RES_ENTRY(RLIMIT_CPU);
|
||||
RET_RES_ENTRY(RLIMIT_DATA);
|
||||
RET_RES_ENTRY(RLIMIT_FSIZE);
|
||||
RET_RES_ENTRY(RLIMIT_LOCKS);
|
||||
RET_RES_ENTRY(RLIMIT_MEMLOCK);
|
||||
RET_RES_ENTRY(RLIMIT_MSGQUEUE);
|
||||
RET_RES_ENTRY(RLIMIT_NICE);
|
||||
RET_RES_ENTRY(RLIMIT_NOFILE);
|
||||
RET_RES_ENTRY(RLIMIT_NPROC);
|
||||
RET_RES_ENTRY(RLIMIT_RSS);
|
||||
RET_RES_ENTRY(RLIMIT_RTPRIO);
|
||||
#ifdef RLIMIT_RTTIME
|
||||
RET_RES_ENTRY(RLIMIT_RTTIME);
|
||||
#endif
|
||||
RET_RES_ENTRY(RLIMIT_SIGPENDING);
|
||||
RET_RES_ENTRY(RLIMIT_STACK);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
#undef RET_RES_ENTRY
|
||||
}
|
||||
|
||||
static void
|
||||
print_rlimit64(abi_ulong rlim_addr, int last)
|
||||
{
|
||||
if (rlim_addr) {
|
||||
struct target_rlimit64 *rl;
|
||||
|
||||
rl = lock_user(VERIFY_READ, rlim_addr, sizeof(*rl), 1);
|
||||
if (!rl) {
|
||||
print_pointer(rlim_addr, last);
|
||||
return;
|
||||
}
|
||||
print_raw_param64("{rlim_cur=%" PRId64, tswap64(rl->rlim_cur), 0);
|
||||
print_raw_param64("rlim_max=%" PRId64 "}", tswap64(rl->rlim_max),
|
||||
last);
|
||||
unlock_user(rl, rlim_addr, 0);
|
||||
} else {
|
||||
qemu_log("NULL%s", get_comma(last));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
print_prlimit64(CPUArchState *cpu_env, const struct syscallname *name,
|
||||
abi_long arg0, abi_long arg1, abi_long arg2,
|
||||
abi_long arg3, abi_long arg4, abi_long arg5)
|
||||
{
|
||||
const char *rlim_name;
|
||||
|
||||
print_syscall_prologue(name);
|
||||
print_raw_param("%d", arg0, 0);
|
||||
rlim_name = target_ressource_string(arg1);
|
||||
if (rlim_name) {
|
||||
qemu_log("%s,", rlim_name);
|
||||
} else {
|
||||
print_raw_param("%d", arg1, 0);
|
||||
}
|
||||
print_rlimit64(arg2, 0);
|
||||
print_pointer(arg3, 1);
|
||||
print_syscall_epilogue(name);
|
||||
}
|
||||
|
||||
static void
|
||||
print_syscall_ret_prlimit64(CPUArchState *cpu_env,
|
||||
const struct syscallname *name,
|
||||
abi_long ret, abi_long arg0, abi_long arg1,
|
||||
abi_long arg2, abi_long arg3, abi_long arg4,
|
||||
abi_long arg5)
|
||||
{
|
||||
if (!print_syscall_err(ret)) {
|
||||
qemu_log(TARGET_ABI_FMT_ld, ret);
|
||||
if (arg3) {
|
||||
qemu_log(" (");
|
||||
print_rlimit64(arg3, 1);
|
||||
qemu_log(")");
|
||||
}
|
||||
}
|
||||
qemu_log("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_NR_kill
|
||||
static void
|
||||
print_kill(CPUArchState *cpu_env, const struct syscallname *name,
|
||||
|
|
|
@ -656,7 +656,7 @@
|
|||
{ TARGET_NR_msgsnd, "msgsnd" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_msync
|
||||
{ TARGET_NR_msync, "msync" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_msync, "msync" , "%s(%p,%u,%d)", NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_multiplexer
|
||||
{ TARGET_NR_multiplexer, "multiplexer" , NULL, NULL, NULL },
|
||||
|
@ -1074,7 +1074,8 @@
|
|||
{ TARGET_NR_preadv, "preadv" , NULL, NULL, NULL },
|
||||
#endif
|
||||
#ifdef TARGET_NR_prlimit64
|
||||
{ TARGET_NR_prlimit64, "prlimit64" , NULL, NULL, NULL },
|
||||
{ TARGET_NR_prlimit64, "prlimit64" , NULL, print_prlimit64,
|
||||
print_syscall_ret_prlimit64 },
|
||||
#endif
|
||||
#ifdef TARGET_NR_process_vm_readv
|
||||
{ TARGET_NR_process_vm_readv, "process_vm_readv" , NULL, NULL, NULL },
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "qemu/path.h"
|
||||
#include "qemu/memfd.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "target_mman.h"
|
||||
#include <elf.h>
|
||||
#include <endian.h>
|
||||
#include <grp.h>
|
||||
|
@ -168,9 +169,13 @@
|
|||
#define CLONE_IGNORED_FLAGS \
|
||||
(CLONE_DETACHED | CLONE_IO)
|
||||
|
||||
#ifndef CLONE_PIDFD
|
||||
# define CLONE_PIDFD 0x00001000
|
||||
#endif
|
||||
|
||||
/* Flags for fork which we can implement within QEMU itself */
|
||||
#define CLONE_OPTIONAL_FORK_FLAGS \
|
||||
(CLONE_SETTLS | CLONE_PARENT_SETTID | \
|
||||
(CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_PIDFD | \
|
||||
CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID)
|
||||
|
||||
/* Flags for thread creation which we can implement within QEMU itself */
|
||||
|
@ -795,49 +800,52 @@ static inline int host_to_target_sock_type(int host_type)
|
|||
}
|
||||
|
||||
static abi_ulong target_brk;
|
||||
static abi_ulong target_original_brk;
|
||||
static abi_ulong brk_page;
|
||||
|
||||
void target_set_brk(abi_ulong new_brk)
|
||||
{
|
||||
target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
|
||||
target_brk = new_brk;
|
||||
brk_page = HOST_PAGE_ALIGN(target_brk);
|
||||
}
|
||||
|
||||
//#define DEBUGF_BRK(message, args...) do { fprintf(stderr, (message), ## args); } while (0)
|
||||
#define DEBUGF_BRK(message, args...)
|
||||
|
||||
/* do_brk() must return target values and target errnos. */
|
||||
abi_long do_brk(abi_ulong new_brk)
|
||||
abi_long do_brk(abi_ulong brk_val)
|
||||
{
|
||||
abi_long mapped_addr;
|
||||
abi_ulong new_alloc_size;
|
||||
abi_ulong new_brk, new_host_brk_page;
|
||||
|
||||
/* brk pointers are always untagged */
|
||||
|
||||
DEBUGF_BRK("do_brk(" TARGET_ABI_FMT_lx ") -> ", new_brk);
|
||||
|
||||
if (!new_brk) {
|
||||
DEBUGF_BRK(TARGET_ABI_FMT_lx " (!new_brk)\n", target_brk);
|
||||
return target_brk;
|
||||
}
|
||||
if (new_brk < target_original_brk) {
|
||||
DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk < target_original_brk)\n",
|
||||
target_brk);
|
||||
/* return old brk value if brk_val unchanged or zero */
|
||||
if (!brk_val || brk_val == target_brk) {
|
||||
return target_brk;
|
||||
}
|
||||
|
||||
/* If the new brk is less than the highest page reserved to the
|
||||
* target heap allocation, set it and we're almost done... */
|
||||
if (new_brk <= brk_page) {
|
||||
/* Heap contents are initialized to zero, as for anonymous
|
||||
* mapped pages. */
|
||||
if (new_brk > target_brk) {
|
||||
memset(g2h_untagged(target_brk), 0, new_brk - target_brk);
|
||||
new_brk = TARGET_PAGE_ALIGN(brk_val);
|
||||
new_host_brk_page = HOST_PAGE_ALIGN(brk_val);
|
||||
|
||||
/* brk_val and old target_brk might be on the same page */
|
||||
if (new_brk == TARGET_PAGE_ALIGN(target_brk)) {
|
||||
if (brk_val > target_brk) {
|
||||
/* empty remaining bytes in (possibly larger) host page */
|
||||
memset(g2h_untagged(target_brk), 0, new_host_brk_page - target_brk);
|
||||
}
|
||||
target_brk = new_brk;
|
||||
DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk <= brk_page)\n", target_brk);
|
||||
return target_brk;
|
||||
target_brk = brk_val;
|
||||
return target_brk;
|
||||
}
|
||||
|
||||
/* Release heap if necesary */
|
||||
if (new_brk < target_brk) {
|
||||
/* empty remaining bytes in (possibly larger) host page */
|
||||
memset(g2h_untagged(brk_val), 0, new_host_brk_page - brk_val);
|
||||
|
||||
/* free unused host pages and set new brk_page */
|
||||
target_munmap(new_host_brk_page, brk_page - new_host_brk_page);
|
||||
brk_page = new_host_brk_page;
|
||||
|
||||
target_brk = brk_val;
|
||||
return target_brk;
|
||||
}
|
||||
|
||||
/* We need to allocate more memory after the brk... Note that
|
||||
|
@ -846,10 +854,14 @@ abi_long do_brk(abi_ulong new_brk)
|
|||
* itself); instead we treat "mapped but at wrong address" as
|
||||
* a failure and unmap again.
|
||||
*/
|
||||
new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page);
|
||||
mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
|
||||
new_alloc_size = new_host_brk_page - brk_page;
|
||||
if (new_alloc_size) {
|
||||
mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
|
||||
PROT_READ|PROT_WRITE,
|
||||
MAP_ANON|MAP_PRIVATE, 0, 0));
|
||||
} else {
|
||||
mapped_addr = brk_page;
|
||||
}
|
||||
|
||||
if (mapped_addr == brk_page) {
|
||||
/* Heap contents are initialized to zero, as for anonymous
|
||||
|
@ -861,10 +873,8 @@ abi_long do_brk(abi_ulong new_brk)
|
|||
* then shrunken). */
|
||||
memset(g2h_untagged(target_brk), 0, brk_page - target_brk);
|
||||
|
||||
target_brk = new_brk;
|
||||
brk_page = HOST_PAGE_ALIGN(target_brk);
|
||||
DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr == brk_page)\n",
|
||||
target_brk);
|
||||
target_brk = brk_val;
|
||||
brk_page = new_host_brk_page;
|
||||
return target_brk;
|
||||
} else if (mapped_addr != -1) {
|
||||
/* Mapped but at wrong address, meaning there wasn't actually
|
||||
|
@ -872,10 +882,6 @@ abi_long do_brk(abi_ulong new_brk)
|
|||
*/
|
||||
target_munmap(mapped_addr, new_alloc_size);
|
||||
mapped_addr = -1;
|
||||
DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr != -1)\n", target_brk);
|
||||
}
|
||||
else {
|
||||
DEBUGF_BRK(TARGET_ABI_FMT_lx " (otherwise)\n", target_brk);
|
||||
}
|
||||
|
||||
#if defined(TARGET_ALPHA)
|
||||
|
@ -1713,6 +1719,11 @@ static inline abi_long target_to_host_sockaddr(int fd, struct sockaddr *addr,
|
|||
lladdr = (struct target_sockaddr_ll *)addr;
|
||||
lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex);
|
||||
lladdr->sll_hatype = tswap16(lladdr->sll_hatype);
|
||||
} else if (sa_family == AF_INET6) {
|
||||
struct sockaddr_in6 *in6addr;
|
||||
|
||||
in6addr = (struct sockaddr_in6 *)addr;
|
||||
in6addr->sin6_scope_id = tswap32(in6addr->sin6_scope_id);
|
||||
}
|
||||
unlock_user(target_saddr, target_addr, 0);
|
||||
|
||||
|
@ -6723,6 +6734,17 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
|
|||
return -TARGET_EINVAL;
|
||||
}
|
||||
|
||||
#if !defined(__NR_pidfd_open) || !defined(TARGET_NR_pidfd_open)
|
||||
if (flags & CLONE_PIDFD) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Can not allow CLONE_PIDFD with CLONE_PARENT_SETTID */
|
||||
if ((flags & CLONE_PIDFD) && (flags & CLONE_PARENT_SETTID)) {
|
||||
return -TARGET_EINVAL;
|
||||
}
|
||||
|
||||
if (block_signals()) {
|
||||
return -QEMU_ERESTARTSYS;
|
||||
}
|
||||
|
@ -6750,6 +6772,20 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
|
|||
ts->child_tidptr = child_tidptr;
|
||||
} else {
|
||||
cpu_clone_regs_parent(env, flags);
|
||||
if (flags & CLONE_PIDFD) {
|
||||
int pid_fd = 0;
|
||||
#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open)
|
||||
int pid_child = ret;
|
||||
pid_fd = pidfd_open(pid_child, 0);
|
||||
if (pid_fd >= 0) {
|
||||
fcntl(pid_fd, F_SETFD, fcntl(pid_fd, F_GETFL)
|
||||
| FD_CLOEXEC);
|
||||
} else {
|
||||
pid_fd = 0;
|
||||
}
|
||||
#endif
|
||||
put_user_u32(pid_fd, parent_tidptr);
|
||||
}
|
||||
fork_end(0);
|
||||
}
|
||||
g_assert(!cpu_in_exclusive_context(cpu));
|
||||
|
@ -7606,6 +7642,14 @@ static inline int target_to_host_mlockall_arg(int arg)
|
|||
}
|
||||
#endif
|
||||
|
||||
static inline int target_to_host_msync_arg(abi_long arg)
|
||||
{
|
||||
return ((arg & TARGET_MS_ASYNC) ? MS_ASYNC : 0) |
|
||||
((arg & TARGET_MS_INVALIDATE) ? MS_INVALIDATE : 0) |
|
||||
((arg & TARGET_MS_SYNC) ? MS_SYNC : 0) |
|
||||
(arg & ~(TARGET_MS_ASYNC | TARGET_MS_INVALIDATE | TARGET_MS_SYNC));
|
||||
}
|
||||
|
||||
#if (defined(TARGET_NR_stat64) || defined(TARGET_NR_lstat64) || \
|
||||
defined(TARGET_NR_fstat64) || defined(TARGET_NR_fstatat64) || \
|
||||
defined(TARGET_NR_newfstatat))
|
||||
|
@ -8079,6 +8123,9 @@ static int open_self_stat(CPUArchState *cpu_env, int fd)
|
|||
gchar *bin = g_strrstr(ts->bprm->argv[0], "/");
|
||||
bin = bin ? bin + 1 : ts->bprm->argv[0];
|
||||
g_string_printf(buf, "(%.15s) ", bin);
|
||||
} else if (i == 2) {
|
||||
/* task state */
|
||||
g_string_assign(buf, "R "); /* we are running right now */
|
||||
} else if (i == 3) {
|
||||
/* ppid */
|
||||
g_string_printf(buf, FMT_pid " ", getppid());
|
||||
|
@ -9989,18 +10036,13 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
|
|||
/* Short circuit this for the magic exe check. */
|
||||
ret = -TARGET_EINVAL;
|
||||
} else if (is_proc_myself((const char *)p, "exe")) {
|
||||
char real[PATH_MAX], *temp;
|
||||
temp = realpath(exec_path, real);
|
||||
/* Return value is # of bytes that we wrote to the buffer. */
|
||||
if (temp == NULL) {
|
||||
ret = get_errno(-1);
|
||||
} else {
|
||||
/* Don't worry about sign mismatch as earlier mapping
|
||||
* logic would have thrown a bad address error. */
|
||||
ret = MIN(strlen(real), arg3);
|
||||
/* We cannot NUL terminate the string. */
|
||||
memcpy(p2, real, ret);
|
||||
}
|
||||
/*
|
||||
* Don't worry about sign mismatch as earlier mapping
|
||||
* logic would have thrown a bad address error.
|
||||
*/
|
||||
ret = MIN(strlen(exec_path), arg3);
|
||||
/* We cannot NUL terminate the string. */
|
||||
memcpy(p2, exec_path, ret);
|
||||
} else {
|
||||
ret = get_errno(readlink(path(p), p2, arg3));
|
||||
}
|
||||
|
@ -10021,18 +10063,13 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
|
|||
/* Short circuit this for the magic exe check. */
|
||||
ret = -TARGET_EINVAL;
|
||||
} else if (is_proc_myself((const char *)p, "exe")) {
|
||||
char real[PATH_MAX], *temp;
|
||||
temp = realpath(exec_path, real);
|
||||
/* Return value is # of bytes that we wrote to the buffer. */
|
||||
if (temp == NULL) {
|
||||
ret = get_errno(-1);
|
||||
} else {
|
||||
/* Don't worry about sign mismatch as earlier mapping
|
||||
* logic would have thrown a bad address error. */
|
||||
ret = MIN(strlen(real), arg4);
|
||||
/* We cannot NUL terminate the string. */
|
||||
memcpy(p2, real, ret);
|
||||
}
|
||||
/*
|
||||
* Don't worry about sign mismatch as earlier mapping
|
||||
* logic would have thrown a bad address error.
|
||||
*/
|
||||
ret = MIN(strlen(exec_path), arg4);
|
||||
/* We cannot NUL terminate the string. */
|
||||
memcpy(p2, exec_path, ret);
|
||||
} else {
|
||||
ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
|
||||
}
|
||||
|
@ -10129,7 +10166,8 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
|
|||
/* ??? msync/mlock/munlock are broken for softmmu. */
|
||||
#ifdef TARGET_NR_msync
|
||||
case TARGET_NR_msync:
|
||||
return get_errno(msync(g2h(cpu, arg1), arg2, arg3));
|
||||
return get_errno(msync(g2h(cpu, arg1), arg2,
|
||||
target_to_host_msync_arg(arg3)));
|
||||
#endif
|
||||
#ifdef TARGET_NR_mlock
|
||||
case TARGET_NR_mlock:
|
||||
|
@ -12886,8 +12924,8 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
|
|||
if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) {
|
||||
return -TARGET_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;
|
||||
}
|
||||
|
@ -12897,8 +12935,8 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
|
|||
if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) {
|
||||
return -TARGET_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);
|
||||
}
|
||||
return ret;
|
||||
|
@ -13118,8 +13156,12 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
|
|||
|
||||
#if defined(TARGET_NR_timerfd_create) && defined(CONFIG_TIMERFD)
|
||||
case TARGET_NR_timerfd_create:
|
||||
return get_errno(timerfd_create(arg1,
|
||||
target_to_host_bitmask(arg2, fcntl_flags_tbl)));
|
||||
ret = get_errno(timerfd_create(arg1,
|
||||
target_to_host_bitmask(arg2, fcntl_flags_tbl)));
|
||||
if (ret >= 0) {
|
||||
fd_trans_register(ret, &target_timerfd_trans);
|
||||
}
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
#if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD)
|
||||
|
|
|
@ -717,6 +717,11 @@ typedef struct target_siginfo {
|
|||
#define TARGET_TRAP_HWBKPT (4) /* hardware breakpoint/watchpoint */
|
||||
#define TARGET_TRAP_UNK (5) /* undiagnosed trap */
|
||||
|
||||
/*
|
||||
* SIGEMT si_codes
|
||||
*/
|
||||
#define TARGET_EMT_TAGOVF 1 /* tag overflow */
|
||||
|
||||
#include "target_resource.h"
|
||||
|
||||
struct target_pollfd {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue