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_OPENBSD 12 /* OpenBSD. */
#define ELFOSABI_ARM_FDPIC 65 /* ARM FDPIC */
#define ELFOSABI_XTENSA_FDPIC 65 /* Xtensa FDPIC */
#define ELFOSABI_ARM 97 /* ARM */
#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */

View File

@ -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

View File

@ -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)

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);
}
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) || \

View File

@ -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))

View File

@ -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

View File

@ -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)

View File

@ -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

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)
{
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) {

View File

@ -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
*/

View File

@ -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;

View File

@ -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 */

View File

@ -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

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_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,

View File

@ -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 },

View File

@ -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)

View File

@ -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 {

View File

@ -197,8 +197,7 @@ enum {
#define FSR_FTT2 (1ULL << 16)
#define FSR_FTT1 (1ULL << 15)
#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
#define FSR_FTT_NMASK 0xfffffffffffe3fffULL
#define FSR_FTT_CEXC_NMASK 0xfffffffffffe3fe0ULL