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:
Peter Maydell 2023-03-12 10:57:00 +00:00
commit 29c8a9e31a
18 changed files with 521 additions and 141 deletions

View File

@ -1619,6 +1619,7 @@ typedef struct elf64_shdr {
#define ELFOSABI_MODESTO 11 /* Novell Modesto. */ #define ELFOSABI_MODESTO 11 /* Novell Modesto. */
#define ELFOSABI_OPENBSD 12 /* OpenBSD. */ #define ELFOSABI_OPENBSD 12 /* OpenBSD. */
#define ELFOSABI_ARM_FDPIC 65 /* ARM FDPIC */ #define ELFOSABI_ARM_FDPIC 65 /* ARM FDPIC */
#define ELFOSABI_XTENSA_FDPIC 65 /* Xtensa FDPIC */
#define ELFOSABI_ARM 97 /* ARM */ #define ELFOSABI_ARM 97 /* ARM */
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ #define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */

View File

@ -3,6 +3,10 @@
#define TARGET_MADV_DONTNEED 6 #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" #include "../generic/target_mman.h"
#endif #endif

View File

@ -1748,6 +1748,15 @@ static inline void init_thread(struct target_pt_regs *regs,
regs->windowstart = 1; regs->windowstart = 1;
regs->areg[1] = infop->start_stack; regs->areg[1] = infop->start_stack;
regs->pc = infop->entry; 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. */ /* 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) static int elf_is_fdpic(struct elfhdr *exec)
{ {
return exec->e_ident[EI_OSABI] == ELFOSABI_ARM_FDPIC; 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 #else
/* Default implementation, always false. */ /* Default implementation, always false. */
static int elf_is_fdpic(struct elfhdr *exec) static int elf_is_fdpic(struct elfhdr *exec)

View File

@ -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); 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, static abi_long target_to_host_for_each_rtattr(struct rtattr *rtattr,
size_t len, size_t len,
abi_long (*target_to_host_rtattr) abi_long (*target_to_host_rtattr)
@ -1314,16 +1357,35 @@ static abi_long target_to_host_for_each_rtattr(struct rtattr *rtattr,
return 0; 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) static abi_long target_to_host_data_link_rtattr(struct rtattr *rtattr)
{ {
uint32_t *u32; uint32_t *u32;
switch (rtattr->rta_type) { switch (rtattr->rta_type & NLA_TYPE_MASK) {
/* uint32_t */ /* uint32_t */
case QEMU_IFLA_MTU:
case QEMU_IFLA_TXQLEN:
case QEMU_IFLA_EXT_MASK: case QEMU_IFLA_EXT_MASK:
u32 = RTA_DATA(rtattr); u32 = RTA_DATA(rtattr);
*u32 = tswap32(*u32); *u32 = tswap32(*u32);
break; 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: default:
qemu_log_mask(LOG_UNIMP, "Unknown target QEMU_IFLA type: %d\n", qemu_log_mask(LOG_UNIMP, "Unknown target QEMU_IFLA type: %d\n",
rtattr->rta_type); rtattr->rta_type);
@ -1622,7 +1684,7 @@ TargetFdTrans target_signalfd_trans = {
.host_to_target_data = host_to_target_data_signalfd, .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; uint64_t *counter = buf;
int i; int i;
@ -1640,8 +1702,12 @@ static abi_long swap_data_eventfd(void *buf, size_t len)
} }
TargetFdTrans target_eventfd_trans = { TargetFdTrans target_eventfd_trans = {
.host_to_target_data = swap_data_eventfd, .host_to_target_data = swap_data_u64,
.target_to_host_data = swap_data_eventfd, .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) || \ #if defined(CONFIG_INOTIFY) && (defined(TARGET_NR_inotify_init) || \

View File

@ -130,6 +130,7 @@ extern TargetFdTrans target_netlink_route_trans;
extern TargetFdTrans target_netlink_audit_trans; extern TargetFdTrans target_netlink_audit_trans;
extern TargetFdTrans target_signalfd_trans; extern TargetFdTrans target_signalfd_trans;
extern TargetFdTrans target_eventfd_trans; extern TargetFdTrans target_eventfd_trans;
extern TargetFdTrans target_timerfd_trans;
#if (defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)) || \ #if (defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)) || \
(defined(CONFIG_INOTIFY1) && defined(TARGET_NR_inotify_init1) && \ (defined(CONFIG_INOTIFY1) && defined(TARGET_NR_inotify_init1) && \
defined(__NR_inotify_init1)) defined(__NR_inotify_init1))

View File

@ -89,4 +89,17 @@
#define TARGET_MADV_DONTNEED_LOCKED 24 #define TARGET_MADV_DONTNEED_LOCKED 24
#endif #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 #endif

View File

@ -12,8 +12,8 @@ struct target_rlimit {
}; };
struct target_rlimit64 { struct target_rlimit64 {
uint64_t rlim_cur; abi_ullong rlim_cur;
uint64_t rlim_max; abi_ullong rlim_max;
}; };
#define TARGET_RLIM_INFINITY ((abi_ulong)-1) #define TARGET_RLIM_INFINITY ((abi_ulong)-1)

View File

@ -10,6 +10,10 @@
#define TARGET_MADV_WIPEONFORK 71 #define TARGET_MADV_WIPEONFORK 71
#define TARGET_MADV_KEEPONFORK 72 #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" #include "../generic/target_mman.h"
#endif #endif

View File

@ -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) 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->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
env->hflags |= HF_PE_MASK | HF_CPL_MASK; env->hflags |= HF_PE_MASK | HF_CPL_MASK;
if (env->features[FEAT_1_EDX] & CPUID_SSE) { if (env->features[FEAT_1_EDX] & CPUID_SSE) {

View File

@ -66,6 +66,7 @@
#endif #endif
char *exec_path; char *exec_path;
char real_exec_path[PATH_MAX];
int singlestep; int singlestep;
static const char *argv0; static const char *argv0;
@ -238,6 +239,14 @@ CPUArchState *cpu_copy(CPUArchState *env)
new_cpu->tcg_cflags = cpu->tcg_cflags; new_cpu->tcg_cflags = cpu->tcg_cflags;
memcpy(new_env, env, sizeof(CPUArchState)); 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. /* Clone all break/watchpoints.
Note: Once we support ptrace with hw-debug register access, make sure 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 * get binfmt_misc flags
*/ */

View File

@ -149,6 +149,69 @@ static void flush_windows(CPUSPARCState *env)
#endif #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) void cpu_loop (CPUSPARCState *env)
{ {
CPUState *cs = env_cpu(env); CPUState *cs = env_cpu(env);
@ -167,13 +230,7 @@ void cpu_loop (CPUSPARCState *env)
} }
switch (trapnr) { switch (trapnr) {
#ifndef TARGET_SPARC64 case TARGET_TT_SYSCALL:
case 0x88:
case 0x90:
#else
case 0x110:
case 0x16d:
#endif
ret = do_syscall (env, env->gregs[1], ret = do_syscall (env, env->gregs[1],
env->regwptr[0], env->regwptr[1], env->regwptr[0], env->regwptr[1],
env->regwptr[2], env->regwptr[3], env->regwptr[2], env->regwptr[3],
@ -183,67 +240,110 @@ void cpu_loop (CPUSPARCState *env)
break; break;
} }
if ((abi_ulong)ret >= (abi_ulong)(-515)) { if ((abi_ulong)ret >= (abi_ulong)(-515)) {
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) env->syscall_cc |= PSR_CARRY;
env->xcc |= PSR_CARRY;
#else
env->psr |= PSR_CARRY;
#endif
ret = -ret; ret = -ret;
} else { } else {
#if defined(TARGET_SPARC64) && !defined(TARGET_ABI32) env->syscall_cc &= ~PSR_CARRY;
env->xcc &= ~PSR_CARRY;
#else
env->psr &= ~PSR_CARRY;
#endif
} }
env->regwptr[0] = ret; env->regwptr[0] = ret;
/* next instruction */ /* next instruction */
env->pc = env->npc; env->pc = env->npc;
env->npc = env->npc + 4; env->npc = env->npc + 4;
break; break;
case 0x83: /* flush windows */
#ifdef TARGET_ABI32 case TT_TRAP + 0x01: /* breakpoint */
case 0x103: case EXCP_DEBUG:
#endif 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); flush_windows(env);
/* next instruction */ next_instruction(env);
env->pc = env->npc;
env->npc = env->npc + 4;
break; break;
#ifndef TARGET_SPARC64
case TT_WIN_OVF: /* window overflow */ case TT_TRAP + 0x20: /* getcc */
save_window(env); env->gregs[1] = do_getcc(env);
next_instruction(env);
break; break;
case TT_WIN_UNF: /* window underflow */ case TT_TRAP + 0x21: /* setcc */
restore_window(env); do_setcc(env, env->gregs[1]);
next_instruction(env);
break; break;
#else case TT_TRAP + 0x22: /* getpsr */
case TT_SPILL: /* window overflow */ env->gregs[1] = do_getpsr(env);
save_window(env); next_instruction(env);
break; break;
case TT_FILL: /* window underflow */
restore_window(env); #ifdef TARGET_SPARC64
break; case TT_TRAP + 0x6e:
#ifndef TARGET_ABI32
case 0x16e:
flush_windows(env); flush_windows(env);
sparc64_get_context(env); sparc64_get_context(env);
break; break;
case 0x16f: case TT_TRAP + 0x6f:
flush_windows(env); flush_windows(env);
sparc64_set_context(env); sparc64_set_context(env);
break; break;
#endif #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: case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */ /* just indicate that signals should be handled asap */
break; break;
case TT_ILL_INSN: case TT_ILL_INSN:
force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc); force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->pc);
break; break;
case EXCP_DEBUG: case TT_PRIV_INSN:
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->pc); force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->pc);
break; 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: case EXCP_ATOMIC:
cpu_exec_step_atomic(cs); cpu_exec_step_atomic(cs);
break; break;

View File

@ -503,7 +503,23 @@ long do_rt_sigreturn(CPUSPARCState *env)
return -QEMU_ESIGRETURN; 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_TSTATE 0
#define SPARC_MC_PC 1 #define SPARC_MC_PC 1
#define SPARC_MC_NPC 2 #define SPARC_MC_NPC 2
@ -575,7 +591,7 @@ void sparc64_set_context(CPUSPARCState *env)
struct target_ucontext *ucp; struct target_ucontext *ucp;
target_mc_gregset_t *grp; target_mc_gregset_t *grp;
target_mc_fpu_t *fpup; target_mc_fpu_t *fpup;
abi_ulong pc, npc, tstate; target_ulong pc, npc, tstate;
unsigned int i; unsigned int i;
unsigned char fenab; unsigned char fenab;
@ -773,18 +789,4 @@ do_sigsegv:
unlock_user_struct(ucp, ucp_addr, 1); unlock_user_struct(ucp, ucp_addr, 1);
force_sig(TARGET_SIGSEGV); force_sig(TARGET_SIGSEGV);
} }
#else #endif /* TARGET_SPARC64 */
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

View File

@ -8,7 +8,7 @@
#define TARGET_SIGTRAP 5 #define TARGET_SIGTRAP 5
#define TARGET_SIGABRT 6 #define TARGET_SIGABRT 6
#define TARGET_SIGIOT 6 #define TARGET_SIGIOT 6
#define TARGET_SIGSTKFLT 7 /* actually EMT */ #define TARGET_SIGEMT 7
#define TARGET_SIGFPE 8 #define TARGET_SIGFPE 8
#define TARGET_SIGKILL 9 #define TARGET_SIGKILL 9
#define TARGET_SIGBUS 10 #define TARGET_SIGBUS 10

View File

@ -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_string(abi_long, int);
UNUSED static void print_buf(abi_long addr, abi_long len, int last); 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_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_timeval(abi_ulong, int);
UNUSED static void print_timespec(abi_ulong, int); UNUSED static void print_timespec(abi_ulong, int);
UNUSED static void print_timespec64(abi_ulong, int); UNUSED static void print_timespec64(abi_ulong, int);
@ -1110,11 +1111,16 @@ UNUSED static const struct flags mmap_flags[] = {
FLAG_END, FLAG_END,
}; };
#ifndef CLONE_PIDFD
# define CLONE_PIDFD 0x00001000
#endif
UNUSED static const struct flags clone_flags[] = { UNUSED static const struct flags clone_flags[] = {
FLAG_GENERIC(CLONE_VM), FLAG_GENERIC(CLONE_VM),
FLAG_GENERIC(CLONE_FS), FLAG_GENERIC(CLONE_FS),
FLAG_GENERIC(CLONE_FILES), FLAG_GENERIC(CLONE_FILES),
FLAG_GENERIC(CLONE_SIGHAND), FLAG_GENERIC(CLONE_SIGHAND),
FLAG_GENERIC(CLONE_PIDFD),
FLAG_GENERIC(CLONE_PTRACE), FLAG_GENERIC(CLONE_PTRACE),
FLAG_GENERIC(CLONE_VFORK), FLAG_GENERIC(CLONE_VFORK),
FLAG_GENERIC(CLONE_PARENT), FLAG_GENERIC(CLONE_PARENT),
@ -1642,6 +1648,19 @@ print_raw_param(const char *fmt, abi_long param, int last)
qemu_log(format, param); 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 static void
print_pointer(abi_long p, int last) print_pointer(abi_long p, int last)
{ {
@ -1718,10 +1737,8 @@ print_timespec64(abi_ulong ts_addr, int last)
print_pointer(ts_addr, last); print_pointer(ts_addr, last);
return; return;
} }
qemu_log("{tv_sec = %lld" print_raw_param64("{tv_sec=%" PRId64, tswap64(ts->tv_sec), 0);
",tv_nsec = %lld}%s", print_raw_param64("tv_nsec=%" PRId64 "}", tswap64(ts->tv_nsec), last);
(long long)tswap64(ts->tv_sec), (long long)tswap64(ts->tv_nsec),
get_comma(last));
unlock_user(ts, ts_addr, 0); unlock_user(ts, ts_addr, 0);
} else { } else {
qemu_log("NULL%s", get_comma(last)); qemu_log("NULL%s", get_comma(last));
@ -3854,6 +3871,94 @@ print_futex(CPUArchState *cpu_env, const struct syscallname *name,
} }
#endif #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 #ifdef TARGET_NR_kill
static void static void
print_kill(CPUArchState *cpu_env, const struct syscallname *name, print_kill(CPUArchState *cpu_env, const struct syscallname *name,

View File

@ -656,7 +656,7 @@
{ TARGET_NR_msgsnd, "msgsnd" , NULL, NULL, NULL }, { TARGET_NR_msgsnd, "msgsnd" , NULL, NULL, NULL },
#endif #endif
#ifdef TARGET_NR_msync #ifdef TARGET_NR_msync
{ TARGET_NR_msync, "msync" , NULL, NULL, NULL }, { TARGET_NR_msync, "msync" , "%s(%p,%u,%d)", NULL, NULL },
#endif #endif
#ifdef TARGET_NR_multiplexer #ifdef TARGET_NR_multiplexer
{ TARGET_NR_multiplexer, "multiplexer" , NULL, NULL, NULL }, { TARGET_NR_multiplexer, "multiplexer" , NULL, NULL, NULL },
@ -1074,7 +1074,8 @@
{ TARGET_NR_preadv, "preadv" , NULL, NULL, NULL }, { TARGET_NR_preadv, "preadv" , NULL, NULL, NULL },
#endif #endif
#ifdef TARGET_NR_prlimit64 #ifdef TARGET_NR_prlimit64
{ TARGET_NR_prlimit64, "prlimit64" , NULL, NULL, NULL }, { TARGET_NR_prlimit64, "prlimit64" , NULL, print_prlimit64,
print_syscall_ret_prlimit64 },
#endif #endif
#ifdef TARGET_NR_process_vm_readv #ifdef TARGET_NR_process_vm_readv
{ TARGET_NR_process_vm_readv, "process_vm_readv" , NULL, NULL, NULL }, { TARGET_NR_process_vm_readv, "process_vm_readv" , NULL, NULL, NULL },

View File

@ -22,6 +22,7 @@
#include "qemu/path.h" #include "qemu/path.h"
#include "qemu/memfd.h" #include "qemu/memfd.h"
#include "qemu/queue.h" #include "qemu/queue.h"
#include "target_mman.h"
#include <elf.h> #include <elf.h>
#include <endian.h> #include <endian.h>
#include <grp.h> #include <grp.h>
@ -168,9 +169,13 @@
#define CLONE_IGNORED_FLAGS \ #define CLONE_IGNORED_FLAGS \
(CLONE_DETACHED | CLONE_IO) (CLONE_DETACHED | CLONE_IO)
#ifndef CLONE_PIDFD
# define CLONE_PIDFD 0x00001000
#endif
/* Flags for fork which we can implement within QEMU itself */ /* Flags for fork which we can implement within QEMU itself */
#define CLONE_OPTIONAL_FORK_FLAGS \ #define CLONE_OPTIONAL_FORK_FLAGS \
(CLONE_SETTLS | CLONE_PARENT_SETTID | \ (CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_PIDFD | \
CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID) CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID)
/* Flags for thread creation which we can implement within QEMU itself */ /* Flags for thread creation which we can implement within QEMU itself */
@ -795,48 +800,51 @@ static inline int host_to_target_sock_type(int host_type)
} }
static abi_ulong target_brk; static abi_ulong target_brk;
static abi_ulong target_original_brk;
static abi_ulong brk_page; static abi_ulong brk_page;
void target_set_brk(abi_ulong new_brk) 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); 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. */ /* 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_long mapped_addr;
abi_ulong new_alloc_size; abi_ulong new_alloc_size;
abi_ulong new_brk, new_host_brk_page;
/* brk pointers are always untagged */ /* brk pointers are always untagged */
DEBUGF_BRK("do_brk(" TARGET_ABI_FMT_lx ") -> ", new_brk); /* return old brk value if brk_val unchanged or zero */
if (!brk_val || brk_val == target_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 target_brk; return target_brk;
} }
/* If the new brk is less than the highest page reserved to the new_brk = TARGET_PAGE_ALIGN(brk_val);
* target heap allocation, set it and we're almost done... */ new_host_brk_page = HOST_PAGE_ALIGN(brk_val);
if (new_brk <= brk_page) {
/* Heap contents are initialized to zero, as for anonymous /* brk_val and old target_brk might be on the same page */
* mapped pages. */ if (new_brk == TARGET_PAGE_ALIGN(target_brk)) {
if (new_brk > target_brk) { if (brk_val > target_brk) {
memset(g2h_untagged(target_brk), 0, new_brk - 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; target_brk = brk_val;
DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk <= brk_page)\n", target_brk); 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; return target_brk;
} }
@ -846,10 +854,14 @@ abi_long do_brk(abi_ulong new_brk)
* itself); instead we treat "mapped but at wrong address" as * itself); instead we treat "mapped but at wrong address" as
* a failure and unmap again. * a failure and unmap again.
*/ */
new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page); new_alloc_size = new_host_brk_page - brk_page;
if (new_alloc_size) {
mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size, mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
PROT_READ|PROT_WRITE, PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, 0, 0)); MAP_ANON|MAP_PRIVATE, 0, 0));
} else {
mapped_addr = brk_page;
}
if (mapped_addr == brk_page) { if (mapped_addr == brk_page) {
/* Heap contents are initialized to zero, as for anonymous /* Heap contents are initialized to zero, as for anonymous
@ -861,10 +873,8 @@ abi_long do_brk(abi_ulong new_brk)
* then shrunken). */ * then shrunken). */
memset(g2h_untagged(target_brk), 0, brk_page - target_brk); memset(g2h_untagged(target_brk), 0, brk_page - target_brk);
target_brk = new_brk; target_brk = brk_val;
brk_page = HOST_PAGE_ALIGN(target_brk); brk_page = new_host_brk_page;
DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr == brk_page)\n",
target_brk);
return target_brk; return target_brk;
} else if (mapped_addr != -1) { } else if (mapped_addr != -1) {
/* Mapped but at wrong address, meaning there wasn't actually /* 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); target_munmap(mapped_addr, new_alloc_size);
mapped_addr = -1; 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) #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 = (struct target_sockaddr_ll *)addr;
lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex); lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex);
lladdr->sll_hatype = tswap16(lladdr->sll_hatype); 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); 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; 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()) { if (block_signals()) {
return -QEMU_ERESTARTSYS; return -QEMU_ERESTARTSYS;
} }
@ -6750,6 +6772,20 @@ static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
ts->child_tidptr = child_tidptr; ts->child_tidptr = child_tidptr;
} else { } else {
cpu_clone_regs_parent(env, flags); 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); fork_end(0);
} }
g_assert(!cpu_in_exclusive_context(cpu)); g_assert(!cpu_in_exclusive_context(cpu));
@ -7606,6 +7642,14 @@ static inline int target_to_host_mlockall_arg(int arg)
} }
#endif #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) || \ #if (defined(TARGET_NR_stat64) || defined(TARGET_NR_lstat64) || \
defined(TARGET_NR_fstat64) || defined(TARGET_NR_fstatat64) || \ defined(TARGET_NR_fstat64) || defined(TARGET_NR_fstatat64) || \
defined(TARGET_NR_newfstatat)) 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], "/"); gchar *bin = g_strrstr(ts->bprm->argv[0], "/");
bin = bin ? bin + 1 : ts->bprm->argv[0]; bin = bin ? bin + 1 : ts->bprm->argv[0];
g_string_printf(buf, "(%.15s) ", bin); 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) { } else if (i == 3) {
/* ppid */ /* ppid */
g_string_printf(buf, FMT_pid " ", getppid()); 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. */ /* Short circuit this for the magic exe check. */
ret = -TARGET_EINVAL; ret = -TARGET_EINVAL;
} else if (is_proc_myself((const char *)p, "exe")) { } else if (is_proc_myself((const char *)p, "exe")) {
char real[PATH_MAX], *temp; /*
temp = realpath(exec_path, real); * Don't worry about sign mismatch as earlier mapping
/* Return value is # of bytes that we wrote to the buffer. */ * logic would have thrown a bad address error.
if (temp == NULL) { */
ret = get_errno(-1); ret = MIN(strlen(exec_path), arg3);
} 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. */ /* We cannot NUL terminate the string. */
memcpy(p2, real, ret); memcpy(p2, exec_path, ret);
}
} else { } else {
ret = get_errno(readlink(path(p), p2, arg3)); 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. */ /* Short circuit this for the magic exe check. */
ret = -TARGET_EINVAL; ret = -TARGET_EINVAL;
} else if (is_proc_myself((const char *)p, "exe")) { } else if (is_proc_myself((const char *)p, "exe")) {
char real[PATH_MAX], *temp; /*
temp = realpath(exec_path, real); * Don't worry about sign mismatch as earlier mapping
/* Return value is # of bytes that we wrote to the buffer. */ * logic would have thrown a bad address error.
if (temp == NULL) { */
ret = get_errno(-1); ret = MIN(strlen(exec_path), arg4);
} 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. */ /* We cannot NUL terminate the string. */
memcpy(p2, real, ret); memcpy(p2, exec_path, ret);
}
} else { } else {
ret = get_errno(readlinkat(arg1, path(p), p2, arg4)); 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. */ /* ??? msync/mlock/munlock are broken for softmmu. */
#ifdef TARGET_NR_msync #ifdef TARGET_NR_msync
case 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 #endif
#ifdef TARGET_NR_mlock #ifdef TARGET_NR_mlock
case 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)) { if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) {
return -TARGET_EFAULT; return -TARGET_EFAULT;
} }
rnew.rlim_cur = tswap64(target_rnew->rlim_cur); __get_user(rnew.rlim_cur, &target_rnew->rlim_cur);
rnew.rlim_max = tswap64(target_rnew->rlim_max); __get_user(rnew.rlim_max, &target_rnew->rlim_max);
unlock_user_struct(target_rnew, arg3, 0); unlock_user_struct(target_rnew, arg3, 0);
rnewp = &rnew; 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)) { if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) {
return -TARGET_EFAULT; return -TARGET_EFAULT;
} }
target_rold->rlim_cur = tswap64(rold.rlim_cur); __put_user(rold.rlim_cur, &target_rold->rlim_cur);
target_rold->rlim_max = tswap64(rold.rlim_max); __put_user(rold.rlim_max, &target_rold->rlim_max);
unlock_user_struct(target_rold, arg4, 1); unlock_user_struct(target_rold, arg4, 1);
} }
return ret; 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) #if defined(TARGET_NR_timerfd_create) && defined(CONFIG_TIMERFD)
case TARGET_NR_timerfd_create: case TARGET_NR_timerfd_create:
return get_errno(timerfd_create(arg1, ret = get_errno(timerfd_create(arg1,
target_to_host_bitmask(arg2, fcntl_flags_tbl))); target_to_host_bitmask(arg2, fcntl_flags_tbl)));
if (ret >= 0) {
fd_trans_register(ret, &target_timerfd_trans);
}
return ret;
#endif #endif
#if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD) #if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD)

View File

@ -717,6 +717,11 @@ typedef struct target_siginfo {
#define TARGET_TRAP_HWBKPT (4) /* hardware breakpoint/watchpoint */ #define TARGET_TRAP_HWBKPT (4) /* hardware breakpoint/watchpoint */
#define TARGET_TRAP_UNK (5) /* undiagnosed trap */ #define TARGET_TRAP_UNK (5) /* undiagnosed trap */
/*
* SIGEMT si_codes
*/
#define TARGET_EMT_TAGOVF 1 /* tag overflow */
#include "target_resource.h" #include "target_resource.h"
struct target_pollfd { struct target_pollfd {

View File

@ -197,8 +197,7 @@ enum {
#define FSR_FTT2 (1ULL << 16) #define FSR_FTT2 (1ULL << 16)
#define FSR_FTT1 (1ULL << 15) #define FSR_FTT1 (1ULL << 15)
#define FSR_FTT0 (1ULL << 14) #define FSR_FTT0 (1ULL << 14)
//gcc warns about constant overflow for ~FSR_FTT_MASK #define FSR_FTT_MASK (FSR_FTT2 | FSR_FTT1 | FSR_FTT0)
//#define FSR_FTT_MASK (FSR_FTT2 | FSR_FTT1 | FSR_FTT0)
#ifdef TARGET_SPARC64 #ifdef TARGET_SPARC64
#define FSR_FTT_NMASK 0xfffffffffffe3fffULL #define FSR_FTT_NMASK 0xfffffffffffe3fffULL
#define FSR_FTT_CEXC_NMASK 0xfffffffffffe3fe0ULL #define FSR_FTT_CEXC_NMASK 0xfffffffffffe3fe0ULL