linux-user pull request 20220928-v2

use 'max' instead of 'qemu32' / 'qemu64'
 add  pidfd_open(), pidfd_send_signal() and pidfd_getfd()
 Improve madvise(MADV_DONTNEED)
 futex syscal rework
 strace improvement
 HP/PA fixes and improvement
 Misc fixes
 -----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEEzS913cjjpNwuT1Fz8ww4vT8vvjwFAmM0riISHGxhdXJlbnRA
 dml2aWVyLmV1AAoJEPMMOL0/L748gH4P/2wesXJKPMY2zQzP3Rld4iyefoPGG/Yp
 mdq59BbjO2jQMR8GBss/nl9l84cIzzkYRQIogaKsjljtZYm/OO5xRefqrzJY6apD
 eidxv20dAVjuaXHAIdGhbFlxot1ctExbZs9atB4uj5DWxfYGD6e/stoBy5/pSmr4
 M5EbGHhyrRI7tRbHGtVQVvG6AT6XGE0pT9tzT5JLaApF8UPMkgJwmez16PNWvcMm
 v8GEvKm/vEVS8CCpzLV4kfwVeo3f54VAOrEBDi29ph2Yo50IA21k8BvoRZaSp+Kn
 G6TMnnly/DkMspAs5EOVfat+kv3TziNNdDH7EnVU1vV1yTDdZgW/1204Uy/JY0Pw
 WotwAFuO9FYeHKmjY0CfnIIZZHYZpDYUOZ8M6dESD/O0EjoB8LMf5p9cbYlze4DE
 csJZCsVcz19HDv6QZXi5mvvDcJ83B2IDb8/PUAzSc0n62lXL9qjYD0wdb0QsLdAT
 I25qLDge1HCmQfCIKcaoHYvE0pDmvkF6ftuQUXLtIwtaV0Z/N5wDf2PEHikjOYHM
 gD2izz23/2wQx6KP/9ZNnCJ5QEBkEgm5wpHncsvjzSzi1uIdNlHyzJJwGTAcc5qZ
 hOeoJ7dT0D6g0BGnvOdg2W/bDx18KW65mNDxE4d+W0uzn0YmQtArk2YsnhKQNO46
 12/0ltPFnSV/
 =DIzQ
 -----END PGP SIGNATURE-----

Merge tag 'linux-user-for-7.2-pull-request' of https://gitlab.com/laurent_vivier/qemu into staging

linux-user pull request 20220928-v2

use 'max' instead of 'qemu32' / 'qemu64'
add  pidfd_open(), pidfd_send_signal() and pidfd_getfd()
Improve madvise(MADV_DONTNEED)
futex syscal rework
strace improvement
HP/PA fixes and improvement
Misc fixes

# -----BEGIN PGP SIGNATURE-----
#
# iQJGBAABCAAwFiEEzS913cjjpNwuT1Fz8ww4vT8vvjwFAmM0riISHGxhdXJlbnRA
# dml2aWVyLmV1AAoJEPMMOL0/L748gH4P/2wesXJKPMY2zQzP3Rld4iyefoPGG/Yp
# mdq59BbjO2jQMR8GBss/nl9l84cIzzkYRQIogaKsjljtZYm/OO5xRefqrzJY6apD
# eidxv20dAVjuaXHAIdGhbFlxot1ctExbZs9atB4uj5DWxfYGD6e/stoBy5/pSmr4
# M5EbGHhyrRI7tRbHGtVQVvG6AT6XGE0pT9tzT5JLaApF8UPMkgJwmez16PNWvcMm
# v8GEvKm/vEVS8CCpzLV4kfwVeo3f54VAOrEBDi29ph2Yo50IA21k8BvoRZaSp+Kn
# G6TMnnly/DkMspAs5EOVfat+kv3TziNNdDH7EnVU1vV1yTDdZgW/1204Uy/JY0Pw
# WotwAFuO9FYeHKmjY0CfnIIZZHYZpDYUOZ8M6dESD/O0EjoB8LMf5p9cbYlze4DE
# csJZCsVcz19HDv6QZXi5mvvDcJ83B2IDb8/PUAzSc0n62lXL9qjYD0wdb0QsLdAT
# I25qLDge1HCmQfCIKcaoHYvE0pDmvkF6ftuQUXLtIwtaV0Z/N5wDf2PEHikjOYHM
# gD2izz23/2wQx6KP/9ZNnCJ5QEBkEgm5wpHncsvjzSzi1uIdNlHyzJJwGTAcc5qZ
# hOeoJ7dT0D6g0BGnvOdg2W/bDx18KW65mNDxE4d+W0uzn0YmQtArk2YsnhKQNO46
# 12/0ltPFnSV/
# =DIzQ
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 28 Sep 2022 16:27:14 EDT
# 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-7.2-pull-request' of https://gitlab.com/laurent_vivier/qemu: (37 commits)
  linux-user: Add parameters of getrandom() syscall for strace
  linux-user: Lock log around strace
  linux-user: Update print_futex_op
  linux-user: Implement PI futexes
  linux-user: Convert signal number for FUTEX_FD
  linux-user: Implement FUTEX_WAKE_BITSET
  linux-user: Sink call to do_safe_futex
  linux-user: Combine do_futex and do_futex_time64
  linux-user: Set ELF_BASE_PLATFORM for MIPS
  linux-user: Introduce stubs for ELF AT_BASE_PLATFORM
  linux-user/s390x: Save/restore fpc when handling a signal
  linux-user: Don't assume 0 is not a valid host timer_t value
  linux-user: fix bug about missing signum convert of sigqueue
  linux-user/hppa: Fix setup_sigcontext()
  linux-user/hppa: Allow PROT_GROWSUP and PROT_GROWSDOWN in mprotect()
  linux-user/hppa: Increase guest stack size to 80MB for hppa target
  linux-user/hppa: Drop stack guard page on hppa target
  linux-user/hppa: Add signal trampoline for hppa target
  linux-user: Add proper strace format strings for getdents()/getdents64()
  linux-user: Fix TARGET_PROT_SEM for XTENSA
  ...

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
Stefan Hajnoczi 2022-09-28 17:03:54 -04:00
commit 36cd0aeac3
43 changed files with 795 additions and 260 deletions

View file

@ -2258,7 +2258,7 @@ int page_get_flags(target_ulong address)
#ifndef PAGE_TARGET_STICKY #ifndef PAGE_TARGET_STICKY
#define PAGE_TARGET_STICKY 0 #define PAGE_TARGET_STICKY 0
#endif #endif
#define PAGE_STICKY (PAGE_ANON | PAGE_TARGET_STICKY) #define PAGE_STICKY (PAGE_ANON | PAGE_PASSTHROUGH | PAGE_TARGET_STICKY)
/* Modify the flags of a page and invalidate the code if necessary. /* Modify the flags of a page and invalidate the code if necessary.
The flag PAGE_WRITE_ORG is positioned automatically depending The flag PAGE_WRITE_ORG is positioned automatically depending

View file

@ -262,6 +262,12 @@ extern const TargetPageBits target_page;
#define PAGE_TARGET_1 0x0200 #define PAGE_TARGET_1 0x0200
#define PAGE_TARGET_2 0x0400 #define PAGE_TARGET_2 0x0400
/*
* For linux-user, indicates that the page is mapped with the same semantics
* in both guest and host.
*/
#define PAGE_PASSTHROUGH 0x0800
#if defined(CONFIG_USER_ONLY) #if defined(CONFIG_USER_ONLY)
void page_dump(FILE *f); void page_dump(FILE *f);

View file

@ -0,0 +1 @@
#include "../generic/target_mman.h"

View file

@ -0,0 +1,8 @@
#ifndef ALPHA_TARGET_MMAN_H
#define ALPHA_TARGET_MMAN_H
#define TARGET_MADV_DONTNEED 6
#include "../generic/target_mman.h"
#endif

View file

@ -0,0 +1 @@
#include "../generic/target_mman.h"

View file

@ -27,9 +27,11 @@
do { \ do { \
CPUState *cs = env_cpu(env); \ CPUState *cs = env_cpu(env); \
fprintf(stderr, fmt , ## __VA_ARGS__); \ fprintf(stderr, fmt , ## __VA_ARGS__); \
fprintf(stderr, "Failing executable: %s\n", exec_path); \
cpu_dump_state(cs, stderr, 0); \ cpu_dump_state(cs, stderr, 0); \
if (qemu_log_separate()) { \ if (qemu_log_separate()) { \
qemu_log(fmt, ## __VA_ARGS__); \ qemu_log(fmt, ## __VA_ARGS__); \
qemu_log("Failing executable: %s\n", exec_path); \
log_cpu_state(cs, 0); \ log_cpu_state(cs, 0); \
} \ } \
} while (0) } while (0)

View file

@ -0,0 +1 @@
#include "../generic/target_mman.h"

View file

@ -1080,6 +1080,37 @@ static uint32_t get_elf_hwcap(void)
#define elf_check_abi(x) (!((x) & EF_MIPS_ABI2)) #define elf_check_abi(x) (!((x) & EF_MIPS_ABI2))
#endif #endif
#define ELF_BASE_PLATFORM get_elf_base_platform()
#define MATCH_PLATFORM_INSN(_flags, _base_platform) \
do { if ((cpu->env.insn_flags & (_flags)) == _flags) \
{ return _base_platform; } } while (0)
static const char *get_elf_base_platform(void)
{
MIPSCPU *cpu = MIPS_CPU(thread_cpu);
/* 64 bit ISAs goes first */
MATCH_PLATFORM_INSN(CPU_MIPS64R6, "mips64r6");
MATCH_PLATFORM_INSN(CPU_MIPS64R5, "mips64r5");
MATCH_PLATFORM_INSN(CPU_MIPS64R2, "mips64r2");
MATCH_PLATFORM_INSN(CPU_MIPS64R1, "mips64");
MATCH_PLATFORM_INSN(CPU_MIPS5, "mips5");
MATCH_PLATFORM_INSN(CPU_MIPS4, "mips4");
MATCH_PLATFORM_INSN(CPU_MIPS3, "mips3");
/* 32 bit ISAs */
MATCH_PLATFORM_INSN(CPU_MIPS32R6, "mips32r6");
MATCH_PLATFORM_INSN(CPU_MIPS32R5, "mips32r5");
MATCH_PLATFORM_INSN(CPU_MIPS32R2, "mips32r2");
MATCH_PLATFORM_INSN(CPU_MIPS32R1, "mips32");
MATCH_PLATFORM_INSN(CPU_MIPS2, "mips2");
/* Fallback */
return "mips";
}
#undef MATCH_PLATFORM_INSN
static inline void init_thread(struct target_pt_regs *regs, static inline void init_thread(struct target_pt_regs *regs,
struct image_info *infop) struct image_info *infop)
{ {
@ -1776,6 +1807,10 @@ static inline void init_thread(struct target_pt_regs *regs,
#endif /* TARGET_HEXAGON */ #endif /* TARGET_HEXAGON */
#ifndef ELF_BASE_PLATFORM
#define ELF_BASE_PLATFORM (NULL)
#endif
#ifndef ELF_PLATFORM #ifndef ELF_PLATFORM
#define ELF_PLATFORM (NULL) #define ELF_PLATFORM (NULL)
#endif #endif
@ -2096,10 +2131,16 @@ static abi_ulong setup_arg_pages(struct linux_binprm *bprm,
if (size < STACK_LOWER_LIMIT) { if (size < STACK_LOWER_LIMIT) {
size = STACK_LOWER_LIMIT; size = STACK_LOWER_LIMIT;
} }
if (STACK_GROWS_DOWN) {
guard = TARGET_PAGE_SIZE; guard = TARGET_PAGE_SIZE;
if (guard < qemu_real_host_page_size()) { if (guard < qemu_real_host_page_size()) {
guard = qemu_real_host_page_size(); guard = qemu_real_host_page_size();
} }
} else {
/* no guard page for hppa target where stack grows upwards. */
guard = 0;
}
prot = PROT_READ | PROT_WRITE; prot = PROT_READ | PROT_WRITE;
if (info->exec_stack) { if (info->exec_stack) {
@ -2118,7 +2159,6 @@ static abi_ulong setup_arg_pages(struct linux_binprm *bprm,
info->stack_limit = error + guard; info->stack_limit = error + guard;
return info->stack_limit + size - sizeof(void *); return info->stack_limit + size - sizeof(void *);
} else { } else {
target_mprotect(error + size, guard, PROT_NONE);
info->stack_limit = error + size; info->stack_limit = error + size;
return error; return error;
} }
@ -2215,8 +2255,8 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
int i; int i;
abi_ulong u_rand_bytes; abi_ulong u_rand_bytes;
uint8_t k_rand_bytes[16]; uint8_t k_rand_bytes[16];
abi_ulong u_platform; abi_ulong u_platform, u_base_platform;
const char *k_platform; const char *k_platform, *k_base_platform;
const int n = sizeof(elf_addr_t); const int n = sizeof(elf_addr_t);
sp = p; sp = p;
@ -2238,6 +2278,22 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
} }
} }
u_base_platform = 0;
k_base_platform = ELF_BASE_PLATFORM;
if (k_base_platform) {
size_t len = strlen(k_base_platform) + 1;
if (STACK_GROWS_DOWN) {
sp -= (len + n - 1) & ~(n - 1);
u_base_platform = sp;
/* FIXME - check return value of memcpy_to_target() for failure */
memcpy_to_target(sp, k_base_platform, len);
} else {
memcpy_to_target(sp, k_base_platform, len);
u_base_platform = sp;
sp += len + 1;
}
}
u_platform = 0; u_platform = 0;
k_platform = ELF_PLATFORM; k_platform = ELF_PLATFORM;
if (k_platform) { if (k_platform) {
@ -2279,6 +2335,8 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
} }
size = (DLINFO_ITEMS + 1) * 2; size = (DLINFO_ITEMS + 1) * 2;
if (k_base_platform)
size += 2;
if (k_platform) if (k_platform)
size += 2; size += 2;
#ifdef DLINFO_ARCH_ITEMS #ifdef DLINFO_ARCH_ITEMS
@ -2356,6 +2414,9 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
NEW_AUX_ENT(AT_HWCAP2, (abi_ulong) ELF_HWCAP2); NEW_AUX_ENT(AT_HWCAP2, (abi_ulong) ELF_HWCAP2);
#endif #endif
if (u_base_platform) {
NEW_AUX_ENT(AT_BASE_PLATFORM, u_base_platform);
}
if (u_platform) { if (u_platform) {
NEW_AUX_ENT(AT_PLATFORM, u_platform); NEW_AUX_ENT(AT_PLATFORM, u_platform);
} }

View file

@ -0,0 +1,92 @@
#ifndef LINUX_USER_TARGET_MMAN_H
#define LINUX_USER_TARGET_MMAN_H
#ifndef TARGET_MADV_NORMAL
#define TARGET_MADV_NORMAL 0
#endif
#ifndef TARGET_MADV_RANDOM
#define TARGET_MADV_RANDOM 1
#endif
#ifndef TARGET_MADV_SEQUENTIAL
#define TARGET_MADV_SEQUENTIAL 2
#endif
#ifndef TARGET_MADV_WILLNEED
#define TARGET_MADV_WILLNEED 3
#endif
#ifndef TARGET_MADV_DONTNEED
#define TARGET_MADV_DONTNEED 4
#endif
#ifndef TARGET_MADV_FREE
#define TARGET_MADV_FREE 8
#endif
#ifndef TARGET_MADV_REMOVE
#define TARGET_MADV_REMOVE 9
#endif
#ifndef TARGET_MADV_DONTFORK
#define TARGET_MADV_DONTFORK 10
#endif
#ifndef TARGET_MADV_DOFORK
#define TARGET_MADV_DOFORK 11
#endif
#ifndef TARGET_MADV_MERGEABLE
#define TARGET_MADV_MERGEABLE 12
#endif
#ifndef TARGET_MADV_UNMERGEABLE
#define TARGET_MADV_UNMERGEABLE 13
#endif
#ifndef TARGET_MADV_HUGEPAGE
#define TARGET_MADV_HUGEPAGE 14
#endif
#ifndef TARGET_MADV_NOHUGEPAGE
#define TARGET_MADV_NOHUGEPAGE 15
#endif
#ifndef TARGET_MADV_DONTDUMP
#define TARGET_MADV_DONTDUMP 16
#endif
#ifndef TARGET_MADV_DODUMP
#define TARGET_MADV_DODUMP 17
#endif
#ifndef TARGET_MADV_WIPEONFORK
#define TARGET_MADV_WIPEONFORK 18
#endif
#ifndef TARGET_MADV_KEEPONFORK
#define TARGET_MADV_KEEPONFORK 19
#endif
#ifndef TARGET_MADV_COLD
#define TARGET_MADV_COLD 20
#endif
#ifndef TARGET_MADV_PAGEOUT
#define TARGET_MADV_PAGEOUT 21
#endif
#ifndef TARGET_MADV_POPULATE_READ
#define TARGET_MADV_POPULATE_READ 22
#endif
#ifndef TARGET_MADV_POPULATE_WRITE
#define TARGET_MADV_POPULATE_WRITE 23
#endif
#ifndef TARGET_MADV_DONTNEED_LOCKED
#define TARGET_MADV_DONTNEED_LOCKED 24
#endif
#endif

View file

@ -0,0 +1 @@
#include "../generic/target_mman.h"

View file

@ -147,12 +147,15 @@ void cpu_loop(CPUHPPAState *env)
force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, env->iaoq_f); force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, env->iaoq_f);
break; break;
case EXCP_ILL: case EXCP_ILL:
EXCP_DUMP(env, "qemu: got CPU exception 0x%x - aborting\n", trapnr);
force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->iaoq_f); force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->iaoq_f);
break; break;
case EXCP_PRIV_OPR: case EXCP_PRIV_OPR:
EXCP_DUMP(env, "qemu: got CPU exception 0x%x - aborting\n", trapnr);
force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->iaoq_f); force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->iaoq_f);
break; break;
case EXCP_PRIV_REG: case EXCP_PRIV_REG:
EXCP_DUMP(env, "qemu: got CPU exception 0x%x - aborting\n", trapnr);
force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVREG, env->iaoq_f); force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVREG, env->iaoq_f);
break; break;
case EXCP_OVERFLOW: case EXCP_OVERFLOW:
@ -171,7 +174,8 @@ void cpu_loop(CPUHPPAState *env)
/* just indicate that signals should be handled asap */ /* just indicate that signals should be handled asap */
break; break;
default: default:
g_assert_not_reached(); EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
abort();
} }
process_pending_signals(env); process_pending_signals(env);
} }

View file

@ -41,7 +41,7 @@ struct target_ucontext {
}; };
struct target_rt_sigframe { struct target_rt_sigframe {
abi_uint tramp[9]; abi_uint tramp[2]; /* syscall restart return address */
target_siginfo_t info; target_siginfo_t info;
struct target_ucontext uc; struct target_ucontext uc;
/* hidden location of upper halves of pa2.0 64-bit gregs */ /* hidden location of upper halves of pa2.0 64-bit gregs */
@ -49,23 +49,13 @@ struct target_rt_sigframe {
static void setup_sigcontext(struct target_sigcontext *sc, CPUArchState *env) static void setup_sigcontext(struct target_sigcontext *sc, CPUArchState *env)
{ {
int flags = 0;
int i; int i;
/* ??? if on_sig_stack, flags |= 1 (PARISC_SC_FLAG_ONSTACK). */
if (env->iaoq_f < TARGET_PAGE_SIZE) {
/* In the gateway page, executing a syscall. */
flags |= 2; /* PARISC_SC_FLAG_IN_SYSCALL */
__put_user(env->gr[31], &sc->sc_iaoq[0]);
__put_user(env->gr[31] + 4, &sc->sc_iaoq[1]);
} else {
__put_user(env->iaoq_f, &sc->sc_iaoq[0]); __put_user(env->iaoq_f, &sc->sc_iaoq[0]);
__put_user(env->iaoq_b, &sc->sc_iaoq[1]); __put_user(env->iaoq_b, &sc->sc_iaoq[1]);
}
__put_user(0, &sc->sc_iasq[0]); __put_user(0, &sc->sc_iasq[0]);
__put_user(0, &sc->sc_iasq[1]); __put_user(0, &sc->sc_iasq[1]);
__put_user(flags, &sc->sc_flags); __put_user(0, &sc->sc_flags);
__put_user(cpu_hppa_get_psw(env), &sc->sc_gr[0]); __put_user(cpu_hppa_get_psw(env), &sc->sc_gr[0]);
for (i = 1; i < 32; ++i) { for (i = 1; i < 32; ++i) {
@ -101,9 +91,15 @@ static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc)
__get_user(env->cr[CR_SAR], &sc->sc_sar); __get_user(env->cr[CR_SAR], &sc->sc_sar);
} }
/* No, this doesn't look right, but it's copied straight from the kernel. */ #if TARGET_ABI_BITS == 32
#define SIGFRAME 64
#define FUNCTIONCALLFRAME 48
#else
#define SIGFRAME 128
#define FUNCTIONCALLFRAME 96
#endif
#define PARISC_RT_SIGFRAME_SIZE32 \ #define PARISC_RT_SIGFRAME_SIZE32 \
((sizeof(struct target_rt_sigframe) + 48 + 64) & -64) ((sizeof(struct target_rt_sigframe) + FUNCTIONCALLFRAME + SIGFRAME) & -SIGFRAME)
void setup_rt_frame(int sig, struct target_sigaction *ka, void setup_rt_frame(int sig, struct target_sigaction *ka,
target_siginfo_t *info, target_siginfo_t *info,
@ -118,7 +114,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) { if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) {
sp = (ts->sigaltstack_used.ss_sp + 0x7f) & ~0x3f; sp = (ts->sigaltstack_used.ss_sp + 0x7f) & ~0x3f;
} }
frame_addr = QEMU_ALIGN_UP(sp, 64); frame_addr = QEMU_ALIGN_UP(sp, SIGFRAME);
sp = frame_addr + PARISC_RT_SIGFRAME_SIZE32; sp = frame_addr + PARISC_RT_SIGFRAME_SIZE32;
trace_user_setup_rt_frame(env, frame_addr); trace_user_setup_rt_frame(env, frame_addr);
@ -139,14 +135,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
setup_sigcontext(&frame->uc.tuc_mcontext, env); setup_sigcontext(&frame->uc.tuc_mcontext, env);
__put_user(0x34190000, frame->tramp + 0); /* ldi 0,%r25 */
__put_user(0x3414015a, frame->tramp + 1); /* ldi __NR_rt_sigreturn,%r20 */
__put_user(0xe4008200, frame->tramp + 2); /* be,l 0x100(%sr2,%r0) */
__put_user(0x08000240, frame->tramp + 3); /* nop */
unlock_user_struct(frame, frame_addr, 1); unlock_user_struct(frame, frame_addr, 1);
env->gr[2] = h2g(frame->tramp); env->gr[2] = default_rt_sigreturn;
env->gr[30] = sp; env->gr[30] = sp;
env->gr[26] = sig; env->gr[26] = sig;
env->gr[25] = h2g(&frame->info); env->gr[25] = h2g(&frame->info);
@ -197,3 +188,23 @@ long do_rt_sigreturn(CPUArchState *env)
force_sig(TARGET_SIGSEGV); force_sig(TARGET_SIGSEGV);
return -QEMU_ESIGRETURN; return -QEMU_ESIGRETURN;
} }
void setup_sigtramp(abi_ulong sigtramp_page)
{
uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 6*4, 0);
abi_ulong SIGFRAME_CONTEXT_REGS32;
assert(tramp != NULL);
SIGFRAME_CONTEXT_REGS32 = offsetof(struct target_rt_sigframe, uc.tuc_mcontext);
SIGFRAME_CONTEXT_REGS32 -= PARISC_RT_SIGFRAME_SIZE32;
__put_user(SIGFRAME_CONTEXT_REGS32, tramp + 0);
__put_user(0x08000240, tramp + 1); /* nop - b/c dwarf2 unwind routines */
__put_user(0x34190000, tramp + 2); /* ldi 0, %r25 (in_syscall=0) */
__put_user(0x3414015a, tramp + 3); /* ldi __NR_rt_sigreturn, %r20 */
__put_user(0xe4008200, tramp + 4); /* ble 0x100(%sr2, %r0) */
__put_user(0x08000240, tramp + 5); /* nop */
default_rt_sigreturn = (sigtramp_page + 8) | 3;
unlock_user(tramp, sigtramp_page, 6*4);
}

View file

@ -0,0 +1,15 @@
#ifndef HPPA_TARGET_MMAN_H
#define HPPA_TARGET_MMAN_H
#define TARGET_MADV_MERGEABLE 65
#define TARGET_MADV_UNMERGEABLE 66
#define TARGET_MADV_HUGEPAGE 67
#define TARGET_MADV_NOHUGEPAGE 68
#define TARGET_MADV_DONTDUMP 69
#define TARGET_MADV_DODUMP 70
#define TARGET_MADV_WIPEONFORK 71
#define TARGET_MADV_KEEPONFORK 72
#include "../generic/target_mman.h"
#endif

View file

@ -70,18 +70,6 @@ typedef struct target_sigaltstack {
/* mask for all SS_xxx flags */ /* mask for all SS_xxx flags */
#define TARGET_SS_FLAG_BITS TARGET_SS_AUTODISARM #define TARGET_SS_FLAG_BITS TARGET_SS_AUTODISARM
/* #define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
* We cannot use a bare sigtramp page for hppa-linux.
*
* Unlike other guests where we use the instructions at PC to validate
* an offset from SP, the hppa libgcc signal frame fallback unwinding uses
* the PC address itself to find the frame. This is due to the fact that
* the hppa grows the stack upward, and the frame is of unknown size.
*
* TODO: We should be able to use a VDSO to address this, by providing
* proper unwind info for the sigtramp code, at which point the fallback
* unwinder will not be used.
*/
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0
#endif /* HPPA_TARGET_SIGNAL_H */ #endif /* HPPA_TARGET_SIGNAL_H */

View file

@ -26,4 +26,6 @@ struct target_pt_regs {
#define TARGET_MCL_FUTURE 2 #define TARGET_MCL_FUTURE 2
#define TARGET_MCL_ONFAULT 4 #define TARGET_MCL_ONFAULT 4
#define TARGET_DEFAULT_STACK_SIZE 80 * 1024 * 1024UL
#endif /* HPPA_TARGET_SYSCALL_H */ #endif /* HPPA_TARGET_SYSCALL_H */

View file

@ -9,6 +9,6 @@
#define I386_TARGET_ELF_H #define I386_TARGET_ELF_H
static inline const char *cpu_get_model(uint32_t eflags) static inline const char *cpu_get_model(uint32_t eflags)
{ {
return "qemu32"; return "max";
} }
#endif #endif

View file

@ -0,0 +1 @@
#include "../generic/target_mman.h"

View file

@ -0,0 +1 @@
#include "../generic/target_mman.h"

View file

@ -0,0 +1 @@
#include "../generic/target_mman.h"

View file

@ -124,10 +124,14 @@ static void usage(int exitcode);
static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX; static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
const char *qemu_uname_release; const char *qemu_uname_release;
#if !defined(TARGET_DEFAULT_STACK_SIZE)
/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
we allocate a bigger stack. Need a better solution, for example we allocate a bigger stack. Need a better solution, for example
by remapping the process stack directly at the right place */ by remapping the process stack directly at the right place */
unsigned long guest_stack_size = 8 * 1024 * 1024UL; #define TARGET_DEFAULT_STACK_SIZE 8 * 1024 * 1024UL
#endif
unsigned long guest_stack_size = TARGET_DEFAULT_STACK_SIZE;
/***********************************************************/ /***********************************************************/
/* Helper routines for implementing atomic operations. */ /* Helper routines for implementing atomic operations. */
@ -668,7 +672,8 @@ int main(int argc, char **argv, char **envp)
struct rlimit lim; struct rlimit lim;
if (getrlimit(RLIMIT_STACK, &lim) == 0 if (getrlimit(RLIMIT_STACK, &lim) == 0
&& lim.rlim_cur != RLIM_INFINITY && lim.rlim_cur != RLIM_INFINITY
&& lim.rlim_cur == (target_long)lim.rlim_cur) { && lim.rlim_cur == (target_long)lim.rlim_cur
&& lim.rlim_cur > guest_stack_size) {
guest_stack_size = lim.rlim_cur; guest_stack_size = lim.rlim_cur;
} }
} }

View file

@ -0,0 +1 @@
#include "../generic/target_mman.h"

View file

@ -0,0 +1 @@
#include "../generic/target_mman.h"

View file

@ -0,0 +1 @@
#include "../generic/target_mman.h"

View file

@ -22,6 +22,7 @@
#include "qemu.h" #include "qemu.h"
#include "user-internals.h" #include "user-internals.h"
#include "user-mmap.h" #include "user-mmap.h"
#include "target_mman.h"
static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
static __thread int mmap_lock_count; static __thread int mmap_lock_count;
@ -105,6 +106,8 @@ static int validate_prot_to_pageflags(int *host_prot, int prot)
page_flags |= PAGE_MTE; page_flags |= PAGE_MTE;
} }
} }
#elif defined(TARGET_HPPA)
valid |= PROT_GROWSDOWN | PROT_GROWSUP;
#endif #endif
return prot & ~valid ? 0 : page_flags; return prot & ~valid ? 0 : page_flags;
@ -253,8 +256,12 @@ static int mmap_frag(abi_ulong real_start,
# define TASK_UNMAPPED_BASE (1ul << 38) # define TASK_UNMAPPED_BASE (1ul << 38)
#endif #endif
#else #else
#ifdef TARGET_HPPA
# define TASK_UNMAPPED_BASE 0xfa000000
#else
# define TASK_UNMAPPED_BASE 0x40000000 # define TASK_UNMAPPED_BASE 0x40000000
#endif #endif
#endif
abi_ulong mmap_next_start = TASK_UNMAPPED_BASE; abi_ulong mmap_next_start = TASK_UNMAPPED_BASE;
unsigned long last_brk; unsigned long last_brk;
@ -426,7 +433,8 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, abi_ulong align)
abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot, abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
int flags, int fd, abi_ulong offset) int flags, int fd, abi_ulong offset)
{ {
abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len; abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len,
passthrough_start = -1, passthrough_end = -1;
int page_flags, host_prot; int page_flags, host_prot;
mmap_lock(); mmap_lock();
@ -539,6 +547,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
host_start += offset - host_offset; host_start += offset - host_offset;
} }
start = h2g(host_start); start = h2g(host_start);
passthrough_start = start;
passthrough_end = start + len;
} else { } else {
if (start & ~TARGET_PAGE_MASK) { if (start & ~TARGET_PAGE_MASK) {
errno = EINVAL; errno = EINVAL;
@ -621,6 +631,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
host_prot, flags, fd, offset1); host_prot, flags, fd, offset1);
if (p == MAP_FAILED) if (p == MAP_FAILED)
goto fail; goto fail;
passthrough_start = real_start;
passthrough_end = real_end;
} }
} }
the_end1: the_end1:
@ -628,7 +640,18 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
page_flags |= PAGE_ANON; page_flags |= PAGE_ANON;
} }
page_flags |= PAGE_RESET; page_flags |= PAGE_RESET;
if (passthrough_start == passthrough_end) {
page_set_flags(start, start + len, page_flags); page_set_flags(start, start + len, page_flags);
} else {
if (start < passthrough_start) {
page_set_flags(start, passthrough_start, page_flags);
}
page_set_flags(passthrough_start, passthrough_end,
page_flags | PAGE_PASSTHROUGH);
if (passthrough_end < start + len) {
page_set_flags(passthrough_end, start + len, page_flags);
}
}
the_end: the_end:
trace_target_mmap_complete(start); trace_target_mmap_complete(start);
if (qemu_loglevel_mask(CPU_LOG_PAGE)) { if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
@ -847,7 +870,7 @@ static bool can_passthrough_madv_dontneed(abi_ulong start, abi_ulong end)
} }
for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) { for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) {
if (!(page_get_flags(addr) & PAGE_ANON)) { if (!(page_get_flags(addr) & PAGE_PASSTHROUGH)) {
return false; return false;
} }
} }
@ -889,11 +912,12 @@ abi_long target_madvise(abi_ulong start, abi_ulong len_in, int advice)
* This is a hint, so ignoring and returning success is ok. * This is a hint, so ignoring and returning success is ok.
* *
* This breaks MADV_DONTNEED, completely implementing which is quite * This breaks MADV_DONTNEED, completely implementing which is quite
* complicated. However, there is one low-hanging fruit: host-page-aligned * complicated. However, there is one low-hanging fruit: mappings that are
* anonymous mappings. In this case passthrough is safe, so do it. * known to have the same semantics in the host and the guest. In this case
* passthrough is safe, so do it.
*/ */
mmap_lock(); mmap_lock();
if (advice == MADV_DONTNEED && if (advice == TARGET_MADV_DONTNEED &&
can_passthrough_madv_dontneed(start, end)) { can_passthrough_madv_dontneed(start, end)) {
ret = get_errno(madvise(g2h_untagged(start), len, MADV_DONTNEED)); ret = get_errno(madvise(g2h_untagged(start), len, MADV_DONTNEED));
if (ret == 0) { if (ret == 0) {

View file

@ -0,0 +1 @@
#include "../generic/target_mman.h"

View file

@ -0,0 +1 @@
#include "../generic/target_mman.h"

View file

@ -0,0 +1 @@
#include "../generic/target_mman.h"

View file

@ -0,0 +1 @@
#include "../generic/target_mman.h"

View file

@ -146,6 +146,7 @@ static void save_sigregs(CPUS390XState *env, target_sigregs *sregs)
* We have to store the fp registers to current->thread.fp_regs * We have to store the fp registers to current->thread.fp_regs
* to merge them with the emulated registers. * to merge them with the emulated registers.
*/ */
__put_user(env->fpc, &sregs->fpregs.fpc);
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
__put_user(*get_freg(env, i), &sregs->fpregs.fprs[i]); __put_user(*get_freg(env, i), &sregs->fpregs.fprs[i]);
} }
@ -331,6 +332,7 @@ static void restore_sigregs(CPUS390XState *env, target_sigregs *sc)
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
__get_user(env->aregs[i], &sc->regs.acrs[i]); __get_user(env->aregs[i], &sc->regs.acrs[i]);
} }
__get_user(env->fpc, &sc->fpregs.fpc);
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
__get_user(*get_freg(env, i), &sc->fpregs.fprs[i]); __get_user(*get_freg(env, i), &sc->fpregs.fprs[i]);
} }

View file

@ -0,0 +1 @@
#include "../generic/target_mman.h"

View file

@ -0,0 +1 @@
#include "../generic/target_mman.h"

View file

@ -118,4 +118,50 @@ static inline void finish_sigsuspend_mask(int ret)
} }
} }
#if defined(SIGSTKFLT) && defined(TARGET_SIGSTKFLT)
#define MAKE_SIG_ENTRY_SIGSTKFLT MAKE_SIG_ENTRY(SIGSTKFLT)
#else
#define MAKE_SIG_ENTRY_SIGSTKFLT
#endif
#if defined(SIGIOT) && defined(TARGET_SIGIOT)
#define MAKE_SIG_ENTRY_SIGIOT MAKE_SIG_ENTRY(SIGIOT)
#else
#define MAKE_SIG_ENTRY_SIGIOT
#endif
#define MAKE_SIGNAL_LIST \
MAKE_SIG_ENTRY(SIGHUP) \
MAKE_SIG_ENTRY(SIGINT) \
MAKE_SIG_ENTRY(SIGQUIT) \
MAKE_SIG_ENTRY(SIGILL) \
MAKE_SIG_ENTRY(SIGTRAP) \
MAKE_SIG_ENTRY(SIGABRT) \
MAKE_SIG_ENTRY(SIGBUS) \
MAKE_SIG_ENTRY(SIGFPE) \
MAKE_SIG_ENTRY(SIGKILL) \
MAKE_SIG_ENTRY(SIGUSR1) \
MAKE_SIG_ENTRY(SIGSEGV) \
MAKE_SIG_ENTRY(SIGUSR2) \
MAKE_SIG_ENTRY(SIGPIPE) \
MAKE_SIG_ENTRY(SIGALRM) \
MAKE_SIG_ENTRY(SIGTERM) \
MAKE_SIG_ENTRY(SIGCHLD) \
MAKE_SIG_ENTRY(SIGCONT) \
MAKE_SIG_ENTRY(SIGSTOP) \
MAKE_SIG_ENTRY(SIGTSTP) \
MAKE_SIG_ENTRY(SIGTTIN) \
MAKE_SIG_ENTRY(SIGTTOU) \
MAKE_SIG_ENTRY(SIGURG) \
MAKE_SIG_ENTRY(SIGXCPU) \
MAKE_SIG_ENTRY(SIGXFSZ) \
MAKE_SIG_ENTRY(SIGVTALRM) \
MAKE_SIG_ENTRY(SIGPROF) \
MAKE_SIG_ENTRY(SIGWINCH) \
MAKE_SIG_ENTRY(SIGIO) \
MAKE_SIG_ENTRY(SIGPWR) \
MAKE_SIG_ENTRY(SIGSYS) \
MAKE_SIG_ENTRY_SIGSTKFLT \
MAKE_SIG_ENTRY_SIGIOT
#endif #endif

View file

@ -53,40 +53,9 @@ abi_ulong default_rt_sigreturn;
QEMU_BUILD_BUG_ON(__SIGRTMAX + 1 != _NSIG); QEMU_BUILD_BUG_ON(__SIGRTMAX + 1 != _NSIG);
#endif #endif
static uint8_t host_to_target_signal_table[_NSIG] = { static uint8_t host_to_target_signal_table[_NSIG] = {
[SIGHUP] = TARGET_SIGHUP, #define MAKE_SIG_ENTRY(sig) [sig] = TARGET_##sig,
[SIGINT] = TARGET_SIGINT, MAKE_SIGNAL_LIST
[SIGQUIT] = TARGET_SIGQUIT, #undef MAKE_SIG_ENTRY
[SIGILL] = TARGET_SIGILL,
[SIGTRAP] = TARGET_SIGTRAP,
[SIGABRT] = TARGET_SIGABRT,
/* [SIGIOT] = TARGET_SIGIOT,*/
[SIGBUS] = TARGET_SIGBUS,
[SIGFPE] = TARGET_SIGFPE,
[SIGKILL] = TARGET_SIGKILL,
[SIGUSR1] = TARGET_SIGUSR1,
[SIGSEGV] = TARGET_SIGSEGV,
[SIGUSR2] = TARGET_SIGUSR2,
[SIGPIPE] = TARGET_SIGPIPE,
[SIGALRM] = TARGET_SIGALRM,
[SIGTERM] = TARGET_SIGTERM,
#ifdef SIGSTKFLT
[SIGSTKFLT] = TARGET_SIGSTKFLT,
#endif
[SIGCHLD] = TARGET_SIGCHLD,
[SIGCONT] = TARGET_SIGCONT,
[SIGSTOP] = TARGET_SIGSTOP,
[SIGTSTP] = TARGET_SIGTSTP,
[SIGTTIN] = TARGET_SIGTTIN,
[SIGTTOU] = TARGET_SIGTTOU,
[SIGURG] = TARGET_SIGURG,
[SIGXCPU] = TARGET_SIGXCPU,
[SIGXFSZ] = TARGET_SIGXFSZ,
[SIGVTALRM] = TARGET_SIGVTALRM,
[SIGPROF] = TARGET_SIGPROF,
[SIGWINCH] = TARGET_SIGWINCH,
[SIGIO] = TARGET_SIGIO,
[SIGPWR] = TARGET_SIGPWR,
[SIGSYS] = TARGET_SIGSYS,
/* next signals stay the same */ /* next signals stay the same */
}; };

View file

@ -0,0 +1 @@
#include "../generic/target_mman.h"

View file

@ -17,6 +17,8 @@
#include "qemu.h" #include "qemu.h"
#include "user-internals.h" #include "user-internals.h"
#include "strace.h" #include "strace.h"
#include "signal-common.h"
#include "target_mman.h"
struct syscallname { struct syscallname {
int nr; int nr;
@ -81,6 +83,7 @@ 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_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_timezone(abi_ulong, int); UNUSED static void print_timezone(abi_ulong, int);
UNUSED static void print_itimerval(abi_ulong, int); UNUSED static void print_itimerval(abi_ulong, int);
UNUSED static void print_number(abi_long, int); UNUSED static void print_number(abi_long, int);
@ -141,30 +144,21 @@ if( cmd == val ) { \
qemu_log("%d", cmd); qemu_log("%d", cmd);
} }
static const char * const target_signal_name[] = {
#define MAKE_SIG_ENTRY(sig) [TARGET_##sig] = #sig,
MAKE_SIGNAL_LIST
#undef MAKE_SIG_ENTRY
};
static void static void
print_signal(abi_ulong arg, int last) print_signal(abi_ulong arg, int last)
{ {
const char *signal_name = NULL; const char *signal_name = NULL;
switch(arg) {
case TARGET_SIGHUP: signal_name = "SIGHUP"; break; if (arg < ARRAY_SIZE(target_signal_name)) {
case TARGET_SIGINT: signal_name = "SIGINT"; break; signal_name = target_signal_name[arg];
case TARGET_SIGQUIT: signal_name = "SIGQUIT"; break;
case TARGET_SIGILL: signal_name = "SIGILL"; break;
case TARGET_SIGABRT: signal_name = "SIGABRT"; break;
case TARGET_SIGFPE: signal_name = "SIGFPE"; break;
case TARGET_SIGKILL: signal_name = "SIGKILL"; break;
case TARGET_SIGSEGV: signal_name = "SIGSEGV"; break;
case TARGET_SIGPIPE: signal_name = "SIGPIPE"; break;
case TARGET_SIGALRM: signal_name = "SIGALRM"; break;
case TARGET_SIGTERM: signal_name = "SIGTERM"; break;
case TARGET_SIGUSR1: signal_name = "SIGUSR1"; break;
case TARGET_SIGUSR2: signal_name = "SIGUSR2"; break;
case TARGET_SIGCHLD: signal_name = "SIGCHLD"; break;
case TARGET_SIGCONT: signal_name = "SIGCONT"; break;
case TARGET_SIGSTOP: signal_name = "SIGSTOP"; break;
case TARGET_SIGTTIN: signal_name = "SIGTTIN"; break;
case TARGET_SIGTTOU: signal_name = "SIGTTOU"; break;
} }
if (signal_name == NULL) { if (signal_name == NULL) {
print_raw_param("%ld", arg, last); print_raw_param("%ld", arg, last);
return; return;
@ -803,6 +797,24 @@ print_syscall_ret_clock_gettime(CPUArchState *cpu_env, const struct syscallname
#define print_syscall_ret_clock_getres print_syscall_ret_clock_gettime #define print_syscall_ret_clock_getres print_syscall_ret_clock_gettime
#endif #endif
#if defined(TARGET_NR_clock_gettime64)
static void
print_syscall_ret_clock_gettime64(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);
qemu_log(" (");
print_timespec64(arg1, 1);
qemu_log(")");
}
qemu_log("\n");
}
#endif
#ifdef TARGET_NR_gettimeofday #ifdef TARGET_NR_gettimeofday
static void static void
print_syscall_ret_gettimeofday(CPUArchState *cpu_env, const struct syscallname *name, print_syscall_ret_gettimeofday(CPUArchState *cpu_env, const struct syscallname *name,
@ -1494,6 +1506,11 @@ print_file_mode(abi_long mode, int last)
const char *sep = ""; const char *sep = "";
const struct flags *m; const struct flags *m;
if (mode == 0) {
qemu_log("000%s", get_comma(last));
return;
}
for (m = &mode_flags[0]; m->f_string != NULL; m++) { for (m = &mode_flags[0]; m->f_string != NULL; m++) {
if ((m->f_value & mode) == m->f_value) { if ((m->f_value & mode) == m->f_value) {
qemu_log("%s%s", m->f_string, sep); qemu_log("%s%s", m->f_string, sep);
@ -1660,6 +1677,27 @@ print_timespec(abi_ulong ts_addr, int last)
} }
} }
static void
print_timespec64(abi_ulong ts_addr, int last)
{
if (ts_addr) {
struct target__kernel_timespec *ts;
ts = lock_user(VERIFY_READ, ts_addr, sizeof(*ts), 1);
if (!ts) {
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));
unlock_user(ts, ts_addr, 0);
} else {
qemu_log("NULL%s", get_comma(last));
}
}
static void static void
print_timezone(abi_ulong tz_addr, int last) print_timezone(abi_ulong tz_addr, int last)
{ {
@ -2275,6 +2313,19 @@ print_clock_gettime(CPUArchState *cpu_env, const struct syscallname *name,
#define print_clock_getres print_clock_gettime #define print_clock_getres print_clock_gettime
#endif #endif
#if defined(TARGET_NR_clock_gettime64)
static void
print_clock_gettime64(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)
{
print_syscall_prologue(name);
print_enums(clockids, arg0, 0);
print_pointer(arg1, 1);
print_syscall_epilogue(name);
}
#endif
#ifdef TARGET_NR_clock_settime #ifdef TARGET_NR_clock_settime
static void static void
print_clock_settime(CPUArchState *cpu_env, const struct syscallname *name, print_clock_settime(CPUArchState *cpu_env, const struct syscallname *name,
@ -2969,6 +3020,46 @@ print_stat(CPUArchState *cpu_env, const struct syscallname *name,
#define print_lstat64 print_stat #define print_lstat64 print_stat
#endif #endif
#if defined(TARGET_NR_madvise)
static struct enums madvise_advice[] = {
ENUM_TARGET(MADV_NORMAL),
ENUM_TARGET(MADV_RANDOM),
ENUM_TARGET(MADV_SEQUENTIAL),
ENUM_TARGET(MADV_WILLNEED),
ENUM_TARGET(MADV_DONTNEED),
ENUM_TARGET(MADV_FREE),
ENUM_TARGET(MADV_REMOVE),
ENUM_TARGET(MADV_DONTFORK),
ENUM_TARGET(MADV_DOFORK),
ENUM_TARGET(MADV_MERGEABLE),
ENUM_TARGET(MADV_UNMERGEABLE),
ENUM_TARGET(MADV_HUGEPAGE),
ENUM_TARGET(MADV_NOHUGEPAGE),
ENUM_TARGET(MADV_DONTDUMP),
ENUM_TARGET(MADV_DODUMP),
ENUM_TARGET(MADV_WIPEONFORK),
ENUM_TARGET(MADV_KEEPONFORK),
ENUM_TARGET(MADV_COLD),
ENUM_TARGET(MADV_PAGEOUT),
ENUM_TARGET(MADV_POPULATE_READ),
ENUM_TARGET(MADV_POPULATE_WRITE),
ENUM_TARGET(MADV_DONTNEED_LOCKED),
ENUM_END,
};
static void
print_madvise(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)
{
print_syscall_prologue(name);
print_pointer(arg0, 0);
print_raw_param("%d", arg1, 0);
print_enums(madvise_advice, arg2, 1);
print_syscall_epilogue(name);
}
#endif
#if defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) #if defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64)
static void static void
print_fstat(CPUArchState *cpu_env, const struct syscallname *name, print_fstat(CPUArchState *cpu_env, const struct syscallname *name,
@ -3272,6 +3363,34 @@ print_openat(CPUArchState *cpu_env, const struct syscallname *name,
} }
#endif #endif
#ifdef TARGET_NR_pidfd_send_signal
static void
print_pidfd_send_signal(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)
{
void *p;
target_siginfo_t uinfo;
print_syscall_prologue(name);
print_raw_param("%d", arg0, 0);
print_signal(arg1, 0);
p = lock_user(VERIFY_READ, arg2, sizeof(target_siginfo_t), 1);
if (p) {
get_target_siginfo(&uinfo, p);
print_siginfo(&uinfo);
unlock_user(p, arg2, 0);
} else {
print_pointer(arg2, 1);
}
print_raw_param("%u", arg3, 0);
print_syscall_epilogue(name);
}
#endif
#ifdef TARGET_NR_mq_unlink #ifdef TARGET_NR_mq_unlink
static void static void
print_mq_unlink(CPUArchState *cpu_env, const struct syscallname *name, print_mq_unlink(CPUArchState *cpu_env, const struct syscallname *name,
@ -3489,6 +3608,21 @@ print_unshare(CPUArchState *cpu_env, const struct syscallname *name,
} }
#endif #endif
#ifdef TARGET_NR_clock_nanosleep
static void
print_clock_nanosleep(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)
{
print_syscall_prologue(name);
print_enums(clockids, arg0, 0);
print_raw_param("%d", arg1, 0);
print_timespec(arg2, 0);
print_timespec(arg3, 1);
print_syscall_epilogue(name);
}
#endif
#ifdef TARGET_NR_utime #ifdef TARGET_NR_utime
static void static void
print_utime(CPUArchState *cpu_env, const struct syscallname *name, print_utime(CPUArchState *cpu_env, const struct syscallname *name,
@ -3576,44 +3710,37 @@ print_munmap(CPUArchState *cpu_env, const struct syscallname *name,
#endif #endif
#ifdef TARGET_NR_futex #ifdef TARGET_NR_futex
static void print_futex_op(abi_long tflag, int last) static void print_futex_op(int cmd, int last)
{ {
#define print_op(val) \ static const char * const futex_names[] = {
if( cmd == val ) { \ #define NAME(X) [X] = #X
qemu_log(#val); \ NAME(FUTEX_WAIT),
return; \ NAME(FUTEX_WAKE),
} NAME(FUTEX_FD),
NAME(FUTEX_REQUEUE),
NAME(FUTEX_CMP_REQUEUE),
NAME(FUTEX_WAKE_OP),
NAME(FUTEX_LOCK_PI),
NAME(FUTEX_UNLOCK_PI),
NAME(FUTEX_TRYLOCK_PI),
NAME(FUTEX_WAIT_BITSET),
NAME(FUTEX_WAKE_BITSET),
NAME(FUTEX_WAIT_REQUEUE_PI),
NAME(FUTEX_CMP_REQUEUE_PI),
NAME(FUTEX_LOCK_PI2),
#undef NAME
};
int cmd = (int)tflag; unsigned base_cmd = cmd & FUTEX_CMD_MASK;
#ifdef FUTEX_PRIVATE_FLAG
if (cmd & FUTEX_PRIVATE_FLAG) { if (base_cmd < ARRAY_SIZE(futex_names)) {
qemu_log("FUTEX_PRIVATE_FLAG|"); qemu_log("%s%s%s",
cmd &= ~FUTEX_PRIVATE_FLAG; (cmd & FUTEX_PRIVATE_FLAG ? "FUTEX_PRIVATE_FLAG|" : ""),
(cmd & FUTEX_CLOCK_REALTIME ? "FUTEX_CLOCK_REALTIME|" : ""),
futex_names[base_cmd]);
} else {
qemu_log("0x%x", cmd);
} }
#endif
#ifdef FUTEX_CLOCK_REALTIME
if (cmd & FUTEX_CLOCK_REALTIME) {
qemu_log("FUTEX_CLOCK_REALTIME|");
cmd &= ~FUTEX_CLOCK_REALTIME;
}
#endif
print_op(FUTEX_WAIT)
print_op(FUTEX_WAKE)
print_op(FUTEX_FD)
print_op(FUTEX_REQUEUE)
print_op(FUTEX_CMP_REQUEUE)
print_op(FUTEX_WAKE_OP)
print_op(FUTEX_LOCK_PI)
print_op(FUTEX_UNLOCK_PI)
print_op(FUTEX_TRYLOCK_PI)
#ifdef FUTEX_WAIT_BITSET
print_op(FUTEX_WAIT_BITSET)
#endif
#ifdef FUTEX_WAKE_BITSET
print_op(FUTEX_WAKE_BITSET)
#endif
/* unknown values */
qemu_log("%d", cmd);
} }
static void static void
@ -3621,11 +3748,23 @@ print_futex(CPUArchState *cpu_env, const struct syscallname *name,
abi_long arg0, abi_long arg1, abi_long arg2, abi_long arg0, abi_long arg1, abi_long arg2,
abi_long arg3, abi_long arg4, abi_long arg5) abi_long arg3, abi_long arg4, abi_long arg5)
{ {
abi_long op = arg1 & FUTEX_CMD_MASK;
print_syscall_prologue(name); print_syscall_prologue(name);
print_pointer(arg0, 0); print_pointer(arg0, 0);
print_futex_op(arg1, 0); print_futex_op(arg1, 0);
print_raw_param(",%d", arg2, 0); print_raw_param(",%d", arg2, 0);
print_pointer(arg3, 0); /* struct timespec */ switch (op) {
case FUTEX_WAIT:
case FUTEX_WAIT_BITSET:
case FUTEX_LOCK_PI:
case FUTEX_LOCK_PI2:
case FUTEX_WAIT_REQUEUE_PI:
print_timespec(arg3, 0);
break;
default:
print_pointer(arg3, 0);
break;
}
print_pointer(arg4, 0); print_pointer(arg4, 0);
print_raw_param("%d", arg4, 1); print_raw_param("%d", arg4, 1);
print_syscall_epilogue(name); print_syscall_epilogue(name);
@ -3780,26 +3919,37 @@ print_syscall(CPUArchState *cpu_env, int num,
abi_long arg4, abi_long arg5, abi_long arg6) abi_long arg4, abi_long arg5, abi_long arg6)
{ {
int i; int i;
const char *format="%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ")"; FILE *f;
const char *format = "%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ","
TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ","
TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ")";
qemu_log("%d ", getpid()); f = qemu_log_trylock();
if (!f) {
return;
}
fprintf(f, "%d ", getpid());
for(i=0;i<nsyscalls;i++) for (i = 0; i < nsyscalls; i++) {
if( scnames[i].nr == num ) { if (scnames[i].nr == num) {
if( scnames[i].call != NULL ) { if (scnames[i].call != NULL) {
scnames[i].call( scnames[i].call(cpu_env, &scnames[i], arg1, arg2, arg3,
cpu_env, &scnames[i], arg1, arg2, arg3, arg4, arg5, arg6); arg4, arg5, arg6);
} else { } else {
/* XXX: this format system is broken because it uses /* XXX: this format system is broken because it uses
host types and host pointers for strings */ host types and host pointers for strings */
if( scnames[i].format != NULL ) if (scnames[i].format != NULL) {
format = scnames[i].format; format = scnames[i].format;
qemu_log(format,
scnames[i].name, arg1, arg2, arg3, arg4, arg5, arg6);
} }
fprintf(f, format, scnames[i].name, arg1, arg2,
arg3, arg4, arg5, arg6);
}
qemu_log_unlock(f);
return; return;
} }
qemu_log("Unknown syscall %d\n", num); }
fprintf(f, "Unknown syscall %d\n", num);
qemu_log_unlock(f);
} }
@ -3809,21 +3959,29 @@ print_syscall_ret(CPUArchState *cpu_env, int num, abi_long ret,
abi_long arg4, abi_long arg5, abi_long arg6) abi_long arg4, abi_long arg5, abi_long arg6)
{ {
int i; int i;
FILE *f;
for(i=0;i<nsyscalls;i++) f = qemu_log_trylock();
if( scnames[i].nr == num ) { if (!f) {
if( scnames[i].result != NULL ) { return;
}
for (i = 0; i < nsyscalls; i++) {
if (scnames[i].nr == num) {
if (scnames[i].result != NULL) {
scnames[i].result(cpu_env, &scnames[i], ret, scnames[i].result(cpu_env, &scnames[i], ret,
arg1, arg2, arg3, arg1, arg2, arg3,
arg4, arg5, arg6); arg4, arg5, arg6);
} else { } else {
if (!print_syscall_err(ret)) { if (!print_syscall_err(ret)) {
qemu_log(TARGET_ABI_FMT_ld, ret); fprintf(f, TARGET_ABI_FMT_ld, ret);
} }
qemu_log("\n"); fprintf(f, "\n");
} }
break; break;
} }
}
qemu_log_unlock(f);
} }
void print_taken_signal(int target_signum, const target_siginfo_t *tinfo) void print_taken_signal(int target_signum, const target_siginfo_t *tinfo)
@ -3831,9 +3989,17 @@ void print_taken_signal(int target_signum, const target_siginfo_t *tinfo)
/* Print the strace output for a signal being taken: /* Print the strace output for a signal being taken:
* --- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=0} --- * --- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=0} ---
*/ */
qemu_log("--- "); FILE *f;
f = qemu_log_trylock();
if (!f) {
return;
}
fprintf(f, "--- ");
print_signal(target_signum, 1); print_signal(target_signum, 1);
qemu_log(" "); fprintf(f, " ");
print_siginfo(tinfo); print_siginfo(tinfo);
qemu_log(" ---\n"); fprintf(f, " ---\n");
qemu_log_unlock(f);
} }

View file

@ -91,7 +91,8 @@
print_syscall_ret_clock_gettime }, print_syscall_ret_clock_gettime },
#endif #endif
#ifdef TARGET_NR_clock_nanosleep #ifdef TARGET_NR_clock_nanosleep
{ TARGET_NR_clock_nanosleep, "clock_nanosleep" , NULL, NULL, NULL }, { TARGET_NR_clock_nanosleep, "clock_nanosleep" , NULL, print_clock_nanosleep,
NULL },
#endif #endif
#ifdef TARGET_NR_clock_settime #ifdef TARGET_NR_clock_settime
{ TARGET_NR_clock_settime, "clock_settime" , NULL, print_clock_settime, NULL }, { TARGET_NR_clock_settime, "clock_settime" , NULL, print_clock_settime, NULL },
@ -278,10 +279,10 @@
{ TARGET_NR_getcwd, "getcwd" , "%s(%p,%d)", NULL, NULL }, { TARGET_NR_getcwd, "getcwd" , "%s(%p,%d)", NULL, NULL },
#endif #endif
#ifdef TARGET_NR_getdents #ifdef TARGET_NR_getdents
{ TARGET_NR_getdents, "getdents" , NULL, NULL, NULL }, { TARGET_NR_getdents, "getdents" , "%s(%d,%p,%u)", NULL, NULL },
#endif #endif
#ifdef TARGET_NR_getdents64 #ifdef TARGET_NR_getdents64
{ TARGET_NR_getdents64, "getdents64" , NULL, NULL, NULL }, { TARGET_NR_getdents64, "getdents64" , "%s(%d,%p,%u)", NULL, NULL },
#endif #endif
#ifdef TARGET_NR_getdomainname #ifdef TARGET_NR_getdomainname
{ TARGET_NR_getdomainname, "getdomainname" , NULL, NULL, NULL }, { TARGET_NR_getdomainname, "getdomainname" , NULL, NULL, NULL },
@ -351,7 +352,7 @@
{ TARGET_NR_getpriority, "getpriority", "%s(%#x,%#x)", NULL, NULL }, { TARGET_NR_getpriority, "getpriority", "%s(%#x,%#x)", NULL, NULL },
#endif #endif
#ifdef TARGET_NR_getrandom #ifdef TARGET_NR_getrandom
{ TARGET_NR_getrandom, "getrandom", NULL, NULL, NULL }, { TARGET_NR_getrandom, "getrandom", "%s(%p,%u,%u)", NULL, NULL },
#endif #endif
#ifdef TARGET_NR_getresgid #ifdef TARGET_NR_getresgid
{ TARGET_NR_getresgid, "getresgid" , NULL, NULL, NULL }, { TARGET_NR_getresgid, "getresgid" , NULL, NULL, NULL },
@ -541,7 +542,7 @@
{ TARGET_NR_lstat64, "lstat64" , NULL, print_lstat64, NULL }, { TARGET_NR_lstat64, "lstat64" , NULL, print_lstat64, NULL },
#endif #endif
#ifdef TARGET_NR_madvise #ifdef TARGET_NR_madvise
{ TARGET_NR_madvise, "madvise" , NULL, NULL, NULL }, { TARGET_NR_madvise, "madvise" , NULL, print_madvise, NULL },
#endif #endif
#ifdef TARGET_NR_madvise1 #ifdef TARGET_NR_madvise1
{ TARGET_NR_madvise1, "madvise1" , NULL, NULL, NULL }, { TARGET_NR_madvise1, "madvise1" , NULL, NULL, NULL },
@ -1664,6 +1665,15 @@
#ifdef TARGET_NR_pipe2 #ifdef TARGET_NR_pipe2
{ TARGET_NR_pipe2, "pipe2", NULL, NULL, NULL }, { TARGET_NR_pipe2, "pipe2", NULL, NULL, NULL },
#endif #endif
#ifdef TARGET_NR_pidfd_open
{ TARGET_NR_pidfd_open, "pidfd_open", "%s(%d,%u)", NULL, NULL },
#endif
#ifdef TARGET_NR_pidfd_send_signal
{ TARGET_NR_pidfd_send_signal, "pidfd_send_signal", NULL, print_pidfd_send_signal, NULL },
#endif
#ifdef TARGET_NR_pidfd_getfd
{ TARGET_NR_pidfd_getfd, "pidfd_getfd", "%s(%d,%d,%u)", NULL, NULL },
#endif
#ifdef TARGET_NR_atomic_cmpxchg_32 #ifdef TARGET_NR_atomic_cmpxchg_32
{ TARGET_NR_atomic_cmpxchg_32, "atomic_cmpxchg_32", NULL, NULL, NULL }, { TARGET_NR_atomic_cmpxchg_32, "atomic_cmpxchg_32", NULL, NULL, NULL },
#endif #endif
@ -1676,3 +1686,7 @@
#ifdef TARGET_NR_copy_file_range #ifdef TARGET_NR_copy_file_range
{ TARGET_NR_copy_file_range, "copy_file_range", "%s(%d,%p,%d,%p,"TARGET_ABI_FMT_lu",%u)", NULL, NULL }, { TARGET_NR_copy_file_range, "copy_file_range", "%s(%d,%p,%d,%p,"TARGET_ABI_FMT_lu",%u)", NULL, NULL },
#endif #endif
#ifdef TARGET_NR_clock_gettime64
{ TARGET_NR_clock_gettime64, "clock_gettime64" , NULL, print_clock_gettime64,
print_syscall_ret_clock_gettime64 },
#endif

View file

@ -346,6 +346,16 @@ _syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
_syscall6(int,sys_futex_time64,int *,uaddr,int,op,int,val, _syscall6(int,sys_futex_time64,int *,uaddr,int,op,int,val,
const struct timespec *,timeout,int *,uaddr2,int,val3) const struct timespec *,timeout,int *,uaddr2,int,val3)
#endif #endif
#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open)
_syscall2(int, pidfd_open, pid_t, pid, unsigned int, flags);
#endif
#if defined(__NR_pidfd_send_signal) && defined(TARGET_NR_pidfd_send_signal)
_syscall4(int, pidfd_send_signal, int, pidfd, int, sig, siginfo_t *, info,
unsigned int, flags);
#endif
#if defined(__NR_pidfd_getfd) && defined(TARGET_NR_pidfd_getfd)
_syscall3(int, pidfd_getfd, int, pidfd, int, targetfd, unsigned int, flags);
#endif
#define __NR_sys_sched_getaffinity __NR_sched_getaffinity #define __NR_sys_sched_getaffinity __NR_sched_getaffinity
_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len, _syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
unsigned long *, user_mask_ptr); unsigned long *, user_mask_ptr);
@ -515,20 +525,25 @@ _syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
#if defined(TARGET_NR_timer_create) #if defined(TARGET_NR_timer_create)
/* Maximum of 32 active POSIX timers allowed at any one time. */ /* Maximum of 32 active POSIX timers allowed at any one time. */
static timer_t g_posix_timers[32] = { 0, } ; #define GUEST_TIMER_MAX 32
static timer_t g_posix_timers[GUEST_TIMER_MAX];
static int g_posix_timer_allocated[GUEST_TIMER_MAX];
static inline int next_free_host_timer(void) static inline int next_free_host_timer(void)
{ {
int k ; int k;
/* FIXME: Does finding the next free slot require a lock? */ for (k = 0; k < ARRAY_SIZE(g_posix_timer_allocated); k++) {
for (k = 0; k < ARRAY_SIZE(g_posix_timers); k++) { if (qatomic_xchg(g_posix_timer_allocated + k, 1) == 0) {
if (g_posix_timers[k] == 0) {
g_posix_timers[k] = (timer_t) 1;
return k; return k;
} }
} }
return -1; return -1;
} }
static inline void free_host_timer_slot(int id)
{
qatomic_store_release(g_posix_timer_allocated + id, 0);
}
#endif #endif
static inline int host_to_target_errno(int host_errno) static inline int host_to_target_errno(int host_errno)
@ -7753,65 +7768,16 @@ static int do_safe_futex(int *uaddr, int op, int val,
futexes locally would make futexes shared between multiple processes futexes locally would make futexes shared between multiple processes
tricky. However they're probably useless because guest atomic tricky. However they're probably useless because guest atomic
operations won't work either. */ operations won't work either. */
#if defined(TARGET_NR_futex) #if defined(TARGET_NR_futex) || defined(TARGET_NR_futex_time64)
static int do_futex(CPUState *cpu, target_ulong uaddr, int op, int val, static int do_futex(CPUState *cpu, bool time64, target_ulong uaddr,
target_ulong timeout, target_ulong uaddr2, int val3) int op, int val, target_ulong timeout,
{
struct timespec ts, *pts;
int base_op;
/* ??? We assume FUTEX_* constants are the same on both host
and target. */
#ifdef FUTEX_CMD_MASK
base_op = op & FUTEX_CMD_MASK;
#else
base_op = op;
#endif
switch (base_op) {
case FUTEX_WAIT:
case FUTEX_WAIT_BITSET:
if (timeout) {
pts = &ts;
target_to_host_timespec(pts, timeout);
} else {
pts = NULL;
}
return do_safe_futex(g2h(cpu, uaddr),
op, tswap32(val), pts, NULL, val3);
case FUTEX_WAKE:
return do_safe_futex(g2h(cpu, uaddr),
op, val, NULL, NULL, 0);
case FUTEX_FD:
return do_safe_futex(g2h(cpu, uaddr),
op, val, NULL, NULL, 0);
case FUTEX_REQUEUE:
case FUTEX_CMP_REQUEUE:
case FUTEX_WAKE_OP:
/* For FUTEX_REQUEUE, FUTEX_CMP_REQUEUE, and FUTEX_WAKE_OP, the
TIMEOUT parameter is interpreted as a uint32_t by the kernel.
But the prototype takes a `struct timespec *'; insert casts
to satisfy the compiler. We do not need to tswap TIMEOUT
since it's not compared to guest memory. */
pts = (struct timespec *)(uintptr_t) timeout;
return do_safe_futex(g2h(cpu, uaddr), op, val, pts, g2h(cpu, uaddr2),
(base_op == FUTEX_CMP_REQUEUE
? tswap32(val3) : val3));
default:
return -TARGET_ENOSYS;
}
}
#endif
#if defined(TARGET_NR_futex_time64)
static int do_futex_time64(CPUState *cpu, target_ulong uaddr, int op,
int val, target_ulong timeout,
target_ulong uaddr2, int val3) target_ulong uaddr2, int val3)
{ {
struct timespec ts, *pts; struct timespec ts, *pts = NULL;
void *haddr2 = NULL;
int base_op; int base_op;
/* ??? We assume FUTEX_* constants are the same on both host /* We assume FUTEX_* constants are the same on both host and target. */
and target. */
#ifdef FUTEX_CMD_MASK #ifdef FUTEX_CMD_MASK
base_op = op & FUTEX_CMD_MASK; base_op = op & FUTEX_CMD_MASK;
#else #else
@ -7820,35 +7786,53 @@ static int do_futex_time64(CPUState *cpu, target_ulong uaddr, int op,
switch (base_op) { switch (base_op) {
case FUTEX_WAIT: case FUTEX_WAIT:
case FUTEX_WAIT_BITSET: case FUTEX_WAIT_BITSET:
if (timeout) { val = tswap32(val);
pts = &ts; break;
if (target_to_host_timespec64(pts, timeout)) { case FUTEX_WAIT_REQUEUE_PI:
return -TARGET_EFAULT; val = tswap32(val);
} haddr2 = g2h(cpu, uaddr2);
} else { break;
pts = NULL; case FUTEX_LOCK_PI:
} case FUTEX_LOCK_PI2:
return do_safe_futex(g2h(cpu, uaddr), op, break;
tswap32(val), pts, NULL, val3);
case FUTEX_WAKE: case FUTEX_WAKE:
return do_safe_futex(g2h(cpu, uaddr), op, val, NULL, NULL, 0); case FUTEX_WAKE_BITSET:
case FUTEX_TRYLOCK_PI:
case FUTEX_UNLOCK_PI:
timeout = 0;
break;
case FUTEX_FD: case FUTEX_FD:
return do_safe_futex(g2h(cpu, uaddr), op, val, NULL, NULL, 0); val = target_to_host_signal(val);
case FUTEX_REQUEUE: timeout = 0;
break;
case FUTEX_CMP_REQUEUE: case FUTEX_CMP_REQUEUE:
case FUTEX_CMP_REQUEUE_PI:
val3 = tswap32(val3);
/* fall through */
case FUTEX_REQUEUE:
case FUTEX_WAKE_OP: case FUTEX_WAKE_OP:
/* For FUTEX_REQUEUE, FUTEX_CMP_REQUEUE, and FUTEX_WAKE_OP, the /*
TIMEOUT parameter is interpreted as a uint32_t by the kernel. * For these, the 4th argument is not TIMEOUT, but VAL2.
But the prototype takes a `struct timespec *'; insert casts * But the prototype of do_safe_futex takes a pointer, so
to satisfy the compiler. We do not need to tswap TIMEOUT * insert casts to satisfy the compiler. We do not need
since it's not compared to guest memory. */ * to tswap VAL2 since it's not compared to guest memory.
pts = (struct timespec *)(uintptr_t) timeout; */
return do_safe_futex(g2h(cpu, uaddr), op, val, pts, g2h(cpu, uaddr2), pts = (struct timespec *)(uintptr_t)timeout;
(base_op == FUTEX_CMP_REQUEUE timeout = 0;
? tswap32(val3) : val3)); haddr2 = g2h(cpu, uaddr2);
break;
default: default:
return -TARGET_ENOSYS; return -TARGET_ENOSYS;
} }
if (timeout) {
pts = &ts;
if (time64
? target_to_host_timespec64(pts, timeout)
: target_to_host_timespec(pts, timeout)) {
return -TARGET_EFAULT;
}
}
return do_safe_futex(g2h(cpu, uaddr), op, val, pts, haddr2, val3);
} }
#endif #endif
@ -8026,7 +8010,11 @@ static int open_self_maps(CPUArchState *cpu_env, int fd)
continue; continue;
} }
#ifdef TARGET_HPPA
if (h2g(max) == ts->info->stack_limit) {
#else
if (h2g(min) == ts->info->stack_limit) { if (h2g(min) == ts->info->stack_limit) {
#endif
path = "[stack]"; path = "[stack]";
} else { } else {
path = e->path; path = e->path;
@ -8683,6 +8671,30 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
ret = do_open_by_handle_at(arg1, arg2, arg3); ret = do_open_by_handle_at(arg1, arg2, arg3);
fd_trans_unregister(ret); fd_trans_unregister(ret);
return ret; return ret;
#endif
#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open)
case TARGET_NR_pidfd_open:
return get_errno(pidfd_open(arg1, arg2));
#endif
#if defined(__NR_pidfd_send_signal) && defined(TARGET_NR_pidfd_send_signal)
case TARGET_NR_pidfd_send_signal:
{
siginfo_t uinfo;
p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
if (!p) {
return -TARGET_EFAULT;
}
target_to_host_siginfo(&uinfo, p);
unlock_user(p, arg3, 0);
ret = get_errno(pidfd_send_signal(arg1, target_to_host_signal(arg2),
&uinfo, arg4));
}
return ret;
#endif
#if defined(__NR_pidfd_getfd) && defined(TARGET_NR_pidfd_getfd)
case TARGET_NR_pidfd_getfd:
return get_errno(pidfd_getfd(arg1, arg2, arg3));
#endif #endif
case TARGET_NR_close: case TARGET_NR_close:
fd_trans_unregister(arg1); fd_trans_unregister(arg1);
@ -9690,7 +9702,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
} }
target_to_host_siginfo(&uinfo, p); target_to_host_siginfo(&uinfo, p);
unlock_user(p, arg3, 0); unlock_user(p, arg3, 0);
ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo)); ret = get_errno(sys_rt_sigqueueinfo(arg1, target_to_host_signal(arg2), &uinfo));
} }
return ret; return ret;
case TARGET_NR_rt_tgsigqueueinfo: case TARGET_NR_rt_tgsigqueueinfo:
@ -9703,7 +9715,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
} }
target_to_host_siginfo(&uinfo, p); target_to_host_siginfo(&uinfo, p);
unlock_user(p, arg4, 0); unlock_user(p, arg4, 0);
ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3, &uinfo)); ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, target_to_host_signal(arg3), &uinfo));
} }
return ret; return ret;
#ifdef TARGET_NR_sigreturn #ifdef TARGET_NR_sigreturn
@ -9912,11 +9924,22 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0); p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
if (!p || !p2) { if (!p || !p2) {
ret = -TARGET_EFAULT; ret = -TARGET_EFAULT;
} else if (!arg4) {
/* Short circuit this for the magic exe check. */
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; char real[PATH_MAX], *temp;
temp = realpath(exec_path, real); temp = realpath(exec_path, real);
ret = temp == NULL ? get_errno(-1) : strlen(real) ; /* Return value is # of bytes that we wrote to the buffer. */
snprintf((char *)p2, arg4, "%s", real); 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);
}
} else { } else {
ret = get_errno(readlinkat(arg1, path(p), p2, arg4)); ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
} }
@ -12318,11 +12341,11 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
#endif #endif
#ifdef TARGET_NR_futex #ifdef TARGET_NR_futex
case TARGET_NR_futex: case TARGET_NR_futex:
return do_futex(cpu, arg1, arg2, arg3, arg4, arg5, arg6); return do_futex(cpu, false, arg1, arg2, arg3, arg4, arg5, arg6);
#endif #endif
#ifdef TARGET_NR_futex_time64 #ifdef TARGET_NR_futex_time64
case TARGET_NR_futex_time64: case TARGET_NR_futex_time64:
return do_futex_time64(cpu, arg1, arg2, arg3, arg4, arg5, arg6); return do_futex(cpu, true, arg1, arg2, arg3, arg4, arg5, arg6);
#endif #endif
#ifdef CONFIG_INOTIFY #ifdef CONFIG_INOTIFY
#if defined(TARGET_NR_inotify_init) #if defined(TARGET_NR_inotify_init)
@ -12847,15 +12870,18 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
phost_sevp = &host_sevp; phost_sevp = &host_sevp;
ret = target_to_host_sigevent(phost_sevp, arg2); ret = target_to_host_sigevent(phost_sevp, arg2);
if (ret != 0) { if (ret != 0) {
free_host_timer_slot(timer_index);
return ret; return ret;
} }
} }
ret = get_errno(timer_create(clkid, phost_sevp, phtimer)); ret = get_errno(timer_create(clkid, phost_sevp, phtimer));
if (ret) { if (ret) {
phtimer = NULL; free_host_timer_slot(timer_index);
} else { } else {
if (put_user(TIMER_MAGIC | timer_index, arg3, target_timer_t)) { if (put_user(TIMER_MAGIC | timer_index, arg3, target_timer_t)) {
timer_delete(*phtimer);
free_host_timer_slot(timer_index);
return -TARGET_EFAULT; return -TARGET_EFAULT;
} }
} }
@ -12991,7 +13017,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
} else { } else {
timer_t htimer = g_posix_timers[timerid]; timer_t htimer = g_posix_timers[timerid];
ret = get_errno(timer_delete(htimer)); ret = get_errno(timer_delete(htimer));
g_posix_timers[timerid] = 0; free_host_timer_slot(timerid);
} }
return ret; return ret;
} }

View file

@ -1246,7 +1246,7 @@ struct target_winsize {
#include "termbits.h" #include "termbits.h"
#if defined(TARGET_MIPS) #if defined(TARGET_MIPS) || defined(TARGET_XTENSA)
#define TARGET_PROT_SEM 0x10 #define TARGET_PROT_SEM 0x10
#else #else
#define TARGET_PROT_SEM 0x08 #define TARGET_PROT_SEM 0x08
@ -2699,6 +2699,9 @@ struct target_drm_i915_getparam {
#define FUTEX_TRYLOCK_PI 8 #define FUTEX_TRYLOCK_PI 8
#define FUTEX_WAIT_BITSET 9 #define FUTEX_WAIT_BITSET 9
#define FUTEX_WAKE_BITSET 10 #define FUTEX_WAKE_BITSET 10
#define FUTEX_WAIT_REQUEUE_PI 11
#define FUTEX_CMP_REQUEUE_PI 12
#define FUTEX_LOCK_PI2 13
#define FUTEX_PRIVATE_FLAG 128 #define FUTEX_PRIVATE_FLAG 128
#define FUTEX_CLOCK_REALTIME 256 #define FUTEX_CLOCK_REALTIME 256

View file

@ -9,6 +9,6 @@
#define X86_64_TARGET_ELF_H #define X86_64_TARGET_ELF_H
static inline const char *cpu_get_model(uint32_t eflags) static inline const char *cpu_get_model(uint32_t eflags)
{ {
return "qemu64"; return "max";
} }
#endif #endif

View file

@ -0,0 +1 @@
#include "../generic/target_mman.h"

View file

@ -0,0 +1 @@
#include "../generic/target_mman.h"

View file

@ -85,9 +85,11 @@ void hppa_cpu_dump_state(CPUState *cs, FILE *f, int flags)
char psw_c[20]; char psw_c[20];
int i; int i;
qemu_fprintf(f, "IA_F " TARGET_FMT_lx " IA_B " TARGET_FMT_lx "\n", qemu_fprintf(f, "IA_F " TARGET_FMT_lx " IA_B " TARGET_FMT_lx
" IIR " TREG_FMT_lx "\n",
hppa_form_gva_psw(psw, env->iasq_f, env->iaoq_f), hppa_form_gva_psw(psw, env->iasq_f, env->iaoq_f),
hppa_form_gva_psw(psw, env->iasq_b, env->iaoq_b)); hppa_form_gva_psw(psw, env->iasq_b, env->iaoq_b),
env->cr[CR_IIR]);
psw_c[0] = (psw & PSW_W ? 'W' : '-'); psw_c[0] = (psw & PSW_W ? 'W' : '-');
psw_c[1] = (psw & PSW_E ? 'E' : '-'); psw_c[1] = (psw & PSW_E ? 'E' : '-');

View file

@ -0,0 +1,70 @@
#include <assert.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <unistd.h>
static void test_anonymous(void)
{
int pagesize = getpagesize();
char *page;
int ret;
page = mmap(NULL, pagesize, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
assert(page != MAP_FAILED);
/* Check that mprotect() does not interfere with MADV_DONTNEED. */
ret = mprotect(page, pagesize, PROT_READ | PROT_WRITE);
assert(ret == 0);
/* Check that MADV_DONTNEED clears the page. */
*page = 42;
ret = madvise(page, pagesize, MADV_DONTNEED);
assert(ret == 0);
assert(*page == 0);
ret = munmap(page, pagesize);
assert(ret == 0);
}
static void test_file(void)
{
char tempname[] = "/tmp/.cmadviseXXXXXX";
int pagesize = getpagesize();
ssize_t written;
char c = 42;
char *page;
int ret;
int fd;
fd = mkstemp(tempname);
assert(fd != -1);
ret = unlink(tempname);
assert(ret == 0);
written = write(fd, &c, sizeof(c));
assert(written == sizeof(c));
page = mmap(NULL, pagesize, PROT_READ, MAP_PRIVATE, fd, 0);
assert(page != MAP_FAILED);
/* Check that mprotect() does not interfere with MADV_DONTNEED. */
ret = mprotect(page, pagesize, PROT_READ | PROT_WRITE);
assert(ret == 0);
/* Check that MADV_DONTNEED resets the page. */
*page = 0;
ret = madvise(page, pagesize, MADV_DONTNEED);
assert(ret == 0);
assert(*page == c);
ret = munmap(page, pagesize);
assert(ret == 0);
ret = close(fd);
assert(ret == 0);
}
int main(void)
{
test_anonymous();
test_file();
return EXIT_SUCCESS;
}