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
#define PAGE_TARGET_STICKY 0
#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.
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_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)
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 { \
CPUState *cs = env_cpu(env); \
fprintf(stderr, fmt , ## __VA_ARGS__); \
fprintf(stderr, "Failing executable: %s\n", exec_path); \
cpu_dump_state(cs, stderr, 0); \
if (qemu_log_separate()) { \
qemu_log(fmt, ## __VA_ARGS__); \
qemu_log("Failing executable: %s\n", exec_path); \
log_cpu_state(cs, 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))
#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,
struct image_info *infop)
{
@ -1776,6 +1807,10 @@ static inline void init_thread(struct target_pt_regs *regs,
#endif /* TARGET_HEXAGON */
#ifndef ELF_BASE_PLATFORM
#define ELF_BASE_PLATFORM (NULL)
#endif
#ifndef ELF_PLATFORM
#define ELF_PLATFORM (NULL)
#endif
@ -2096,9 +2131,15 @@ static abi_ulong setup_arg_pages(struct linux_binprm *bprm,
if (size < STACK_LOWER_LIMIT) {
size = STACK_LOWER_LIMIT;
}
guard = TARGET_PAGE_SIZE;
if (guard < qemu_real_host_page_size()) {
guard = qemu_real_host_page_size();
if (STACK_GROWS_DOWN) {
guard = TARGET_PAGE_SIZE;
if (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;
@ -2118,7 +2159,6 @@ static abi_ulong setup_arg_pages(struct linux_binprm *bprm,
info->stack_limit = error + guard;
return info->stack_limit + size - sizeof(void *);
} else {
target_mprotect(error + size, guard, PROT_NONE);
info->stack_limit = error + size;
return error;
}
@ -2215,8 +2255,8 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
int i;
abi_ulong u_rand_bytes;
uint8_t k_rand_bytes[16];
abi_ulong u_platform;
const char *k_platform;
abi_ulong u_platform, u_base_platform;
const char *k_platform, *k_base_platform;
const int n = sizeof(elf_addr_t);
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;
k_platform = ELF_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;
if (k_base_platform)
size += 2;
if (k_platform)
size += 2;
#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);
#endif
if (u_base_platform) {
NEW_AUX_ENT(AT_BASE_PLATFORM, u_base_platform);
}
if (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);
break;
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);
break;
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);
break;
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);
break;
case EXCP_OVERFLOW:
@ -171,7 +174,8 @@ void cpu_loop(CPUHPPAState *env)
/* just indicate that signals should be handled asap */
break;
default:
g_assert_not_reached();
EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr);
abort();
}
process_pending_signals(env);
}

View File

@ -41,7 +41,7 @@ struct target_ucontext {
};
struct target_rt_sigframe {
abi_uint tramp[9];
abi_uint tramp[2]; /* syscall restart return address */
target_siginfo_t info;
struct target_ucontext uc;
/* 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)
{
int flags = 0;
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_b, &sc->sc_iaoq[1]);
}
__put_user(env->iaoq_f, &sc->sc_iaoq[0]);
__put_user(env->iaoq_b, &sc->sc_iaoq[1]);
__put_user(0, &sc->sc_iasq[0]);
__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]);
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);
}
/* 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 \
((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,
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)) {
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;
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);
__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);
env->gr[2] = h2g(frame->tramp);
env->gr[2] = default_rt_sigreturn;
env->gr[30] = sp;
env->gr[26] = sig;
env->gr[25] = h2g(&frame->info);
@ -197,3 +188,23 @@ long do_rt_sigreturn(CPUArchState *env)
force_sig(TARGET_SIGSEGV);
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 */
#define TARGET_SS_FLAG_BITS TARGET_SS_AUTODISARM
/*
* 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
#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
#endif /* HPPA_TARGET_SIGNAL_H */

View File

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

View File

@ -9,6 +9,6 @@
#define I386_TARGET_ELF_H
static inline const char *cpu_get_model(uint32_t eflags)
{
return "qemu32";
return "max";
}
#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;
const char *qemu_uname_release;
#if !defined(TARGET_DEFAULT_STACK_SIZE)
/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
we allocate a bigger stack. Need a better solution, for example
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. */
@ -668,7 +672,8 @@ int main(int argc, char **argv, char **envp)
struct rlimit lim;
if (getrlimit(RLIMIT_STACK, &lim) == 0
&& 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;
}
}

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 "user-internals.h"
#include "user-mmap.h"
#include "target_mman.h"
static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
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;
}
}
#elif defined(TARGET_HPPA)
valid |= PROT_GROWSDOWN | PROT_GROWSUP;
#endif
return prot & ~valid ? 0 : page_flags;
@ -253,8 +256,12 @@ static int mmap_frag(abi_ulong real_start,
# define TASK_UNMAPPED_BASE (1ul << 38)
#endif
#else
#ifdef TARGET_HPPA
# define TASK_UNMAPPED_BASE 0xfa000000
#else
# define TASK_UNMAPPED_BASE 0x40000000
#endif
#endif
abi_ulong mmap_next_start = TASK_UNMAPPED_BASE;
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,
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;
mmap_lock();
@ -539,6 +547,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
host_start += offset - host_offset;
}
start = h2g(host_start);
passthrough_start = start;
passthrough_end = start + len;
} else {
if (start & ~TARGET_PAGE_MASK) {
errno = EINVAL;
@ -621,6 +631,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
host_prot, flags, fd, offset1);
if (p == MAP_FAILED)
goto fail;
passthrough_start = real_start;
passthrough_end = real_end;
}
}
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_RESET;
page_set_flags(start, start + len, page_flags);
if (passthrough_start == passthrough_end) {
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:
trace_target_mmap_complete(start);
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) {
if (!(page_get_flags(addr) & PAGE_ANON)) {
if (!(page_get_flags(addr) & PAGE_PASSTHROUGH)) {
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 breaks MADV_DONTNEED, completely implementing which is quite
* complicated. However, there is one low-hanging fruit: host-page-aligned
* anonymous mappings. In this case passthrough is safe, so do it.
* complicated. However, there is one low-hanging fruit: mappings that are
* known to have the same semantics in the host and the guest. In this case
* passthrough is safe, so do it.
*/
mmap_lock();
if (advice == MADV_DONTNEED &&
if (advice == TARGET_MADV_DONTNEED &&
can_passthrough_madv_dontneed(start, end)) {
ret = get_errno(madvise(g2h_untagged(start), len, MADV_DONTNEED));
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
* to merge them with the emulated registers.
*/
__put_user(env->fpc, &sregs->fpregs.fpc);
for (i = 0; i < 16; 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++) {
__get_user(env->aregs[i], &sc->regs.acrs[i]);
}
__get_user(env->fpc, &sc->fpregs.fpc);
for (i = 0; i < 16; 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

View File

@ -53,40 +53,9 @@ abi_ulong default_rt_sigreturn;
QEMU_BUILD_BUG_ON(__SIGRTMAX + 1 != _NSIG);
#endif
static uint8_t host_to_target_signal_table[_NSIG] = {
[SIGHUP] = TARGET_SIGHUP,
[SIGINT] = TARGET_SIGINT,
[SIGQUIT] = TARGET_SIGQUIT,
[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,
#define MAKE_SIG_ENTRY(sig) [sig] = TARGET_##sig,
MAKE_SIGNAL_LIST
#undef MAKE_SIG_ENTRY
/* 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 "user-internals.h"
#include "strace.h"
#include "signal-common.h"
#include "target_mman.h"
struct syscallname {
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_timeval(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_itimerval(abi_ulong, int);
UNUSED static void print_number(abi_long, int);
@ -141,30 +144,21 @@ if( cmd == val ) { \
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
print_signal(abi_ulong arg, int last)
{
const char *signal_name = NULL;
switch(arg) {
case TARGET_SIGHUP: signal_name = "SIGHUP"; break;
case TARGET_SIGINT: signal_name = "SIGINT"; break;
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 (arg < ARRAY_SIZE(target_signal_name)) {
signal_name = target_signal_name[arg];
}
if (signal_name == NULL) {
print_raw_param("%ld", arg, last);
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
#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
static void
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 struct flags *m;
if (mode == 0) {
qemu_log("000%s", get_comma(last));
return;
}
for (m = &mode_flags[0]; m->f_string != NULL; m++) {
if ((m->f_value & mode) == m->f_value) {
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
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
#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
static void
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
#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)
static void
print_fstat(CPUArchState *cpu_env, const struct syscallname *name,
@ -3272,6 +3363,34 @@ print_openat(CPUArchState *cpu_env, const struct syscallname *name,
}
#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
static void
print_mq_unlink(CPUArchState *cpu_env, const struct syscallname *name,
@ -3489,6 +3608,21 @@ print_unshare(CPUArchState *cpu_env, const struct syscallname *name,
}
#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
static void
print_utime(CPUArchState *cpu_env, const struct syscallname *name,
@ -3576,44 +3710,37 @@ print_munmap(CPUArchState *cpu_env, const struct syscallname *name,
#endif
#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) \
if( cmd == val ) { \
qemu_log(#val); \
return; \
}
static const char * const futex_names[] = {
#define NAME(X) [X] = #X
NAME(FUTEX_WAIT),
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;
#ifdef FUTEX_PRIVATE_FLAG
if (cmd & FUTEX_PRIVATE_FLAG) {
qemu_log("FUTEX_PRIVATE_FLAG|");
cmd &= ~FUTEX_PRIVATE_FLAG;
unsigned base_cmd = cmd & FUTEX_CMD_MASK;
if (base_cmd < ARRAY_SIZE(futex_names)) {
qemu_log("%s%s%s",
(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
@ -3621,11 +3748,23 @@ print_futex(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)
{
abi_long op = arg1 & FUTEX_CMD_MASK;
print_syscall_prologue(name);
print_pointer(arg0, 0);
print_futex_op(arg1, 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_raw_param("%d", arg4, 1);
print_syscall_epilogue(name);
@ -3780,26 +3919,37 @@ print_syscall(CPUArchState *cpu_env, int num,
abi_long arg4, abi_long arg5, abi_long arg6)
{
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++)
if( scnames[i].nr == num ) {
if( scnames[i].call != NULL ) {
scnames[i].call(
cpu_env, &scnames[i], arg1, arg2, arg3, arg4, arg5, arg6);
for (i = 0; i < nsyscalls; i++) {
if (scnames[i].nr == num) {
if (scnames[i].call != NULL) {
scnames[i].call(cpu_env, &scnames[i], arg1, arg2, arg3,
arg4, arg5, arg6);
} else {
/* XXX: this format system is broken because it uses
host types and host pointers for strings */
if( scnames[i].format != NULL )
if (scnames[i].format != NULL) {
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;
}
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)
{
int i;
FILE *f;
for(i=0;i<nsyscalls;i++)
if( scnames[i].nr == num ) {
if( scnames[i].result != NULL ) {
f = qemu_log_trylock();
if (!f) {
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,
arg1, arg2, arg3,
arg4, arg5, arg6);
} else {
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;
}
}
qemu_log_unlock(f);
}
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:
* --- 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);
qemu_log(" ");
fprintf(f, " ");
print_siginfo(tinfo);
qemu_log(" ---\n");
fprintf(f, " ---\n");
qemu_log_unlock(f);
}

View File

@ -91,7 +91,8 @@
print_syscall_ret_clock_gettime },
#endif
#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
#ifdef TARGET_NR_clock_settime
{ TARGET_NR_clock_settime, "clock_settime" , NULL, print_clock_settime, NULL },
@ -278,10 +279,10 @@
{ TARGET_NR_getcwd, "getcwd" , "%s(%p,%d)", NULL, NULL },
#endif
#ifdef TARGET_NR_getdents
{ TARGET_NR_getdents, "getdents" , NULL, NULL, NULL },
{ TARGET_NR_getdents, "getdents" , "%s(%d,%p,%u)", NULL, NULL },
#endif
#ifdef TARGET_NR_getdents64
{ TARGET_NR_getdents64, "getdents64" , NULL, NULL, NULL },
{ TARGET_NR_getdents64, "getdents64" , "%s(%d,%p,%u)", NULL, NULL },
#endif
#ifdef TARGET_NR_getdomainname
{ TARGET_NR_getdomainname, "getdomainname" , NULL, NULL, NULL },
@ -351,7 +352,7 @@
{ TARGET_NR_getpriority, "getpriority", "%s(%#x,%#x)", NULL, NULL },
#endif
#ifdef TARGET_NR_getrandom
{ TARGET_NR_getrandom, "getrandom", NULL, NULL, NULL },
{ TARGET_NR_getrandom, "getrandom", "%s(%p,%u,%u)", NULL, NULL },
#endif
#ifdef TARGET_NR_getresgid
{ TARGET_NR_getresgid, "getresgid" , NULL, NULL, NULL },
@ -541,7 +542,7 @@
{ TARGET_NR_lstat64, "lstat64" , NULL, print_lstat64, NULL },
#endif
#ifdef TARGET_NR_madvise
{ TARGET_NR_madvise, "madvise" , NULL, NULL, NULL },
{ TARGET_NR_madvise, "madvise" , NULL, print_madvise, NULL },
#endif
#ifdef TARGET_NR_madvise1
{ TARGET_NR_madvise1, "madvise1" , NULL, NULL, NULL },
@ -1664,6 +1665,15 @@
#ifdef TARGET_NR_pipe2
{ TARGET_NR_pipe2, "pipe2", NULL, NULL, NULL },
#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
{ TARGET_NR_atomic_cmpxchg_32, "atomic_cmpxchg_32", NULL, NULL, NULL },
#endif
@ -1676,3 +1686,7 @@
#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 },
#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,
const struct timespec *,timeout,int *,uaddr2,int,val3)
#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
_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
unsigned long *, user_mask_ptr);
@ -515,20 +525,25 @@ _syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
#if defined(TARGET_NR_timer_create)
/* 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)
{
int k ;
/* FIXME: Does finding the next free slot require a lock? */
for (k = 0; k < ARRAY_SIZE(g_posix_timers); k++) {
if (g_posix_timers[k] == 0) {
g_posix_timers[k] = (timer_t) 1;
int k;
for (k = 0; k < ARRAY_SIZE(g_posix_timer_allocated); k++) {
if (qatomic_xchg(g_posix_timer_allocated + k, 1) == 0) {
return k;
}
}
return -1;
}
static inline void free_host_timer_slot(int id)
{
qatomic_store_release(g_posix_timer_allocated + id, 0);
}
#endif
static inline int host_to_target_errno(int host_errno)
@ -7753,15 +7768,16 @@ static int do_safe_futex(int *uaddr, int op, int val,
futexes locally would make futexes shared between multiple processes
tricky. However they're probably useless because guest atomic
operations won't work either. */
#if defined(TARGET_NR_futex)
static int do_futex(CPUState *cpu, target_ulong uaddr, int op, int val,
target_ulong timeout, target_ulong uaddr2, int val3)
#if defined(TARGET_NR_futex) || defined(TARGET_NR_futex_time64)
static int do_futex(CPUState *cpu, bool time64, target_ulong uaddr,
int op, int val, target_ulong timeout,
target_ulong uaddr2, int val3)
{
struct timespec ts, *pts;
struct timespec ts, *pts = NULL;
void *haddr2 = NULL;
int base_op;
/* ??? We assume FUTEX_* constants are the same on both host
and target. */
/* We assume FUTEX_* constants are the same on both host and target. */
#ifdef FUTEX_CMD_MASK
base_op = op & FUTEX_CMD_MASK;
#else
@ -7770,85 +7786,53 @@ static int do_futex(CPUState *cpu, target_ulong uaddr, int op, int val,
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);
val = tswap32(val);
break;
case FUTEX_WAIT_REQUEUE_PI:
val = tswap32(val);
haddr2 = g2h(cpu, uaddr2);
break;
case FUTEX_LOCK_PI:
case FUTEX_LOCK_PI2:
break;
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:
return do_safe_futex(g2h(cpu, uaddr),
op, val, NULL, NULL, 0);
case FUTEX_REQUEUE:
val = target_to_host_signal(val);
timeout = 0;
break;
case FUTEX_CMP_REQUEUE:
case FUTEX_CMP_REQUEUE_PI:
val3 = tswap32(val3);
/* fall through */
case FUTEX_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));
/*
* For these, the 4th argument is not TIMEOUT, but VAL2.
* But the prototype of do_safe_futex takes a pointer, so
* insert casts to satisfy the compiler. We do not need
* to tswap VAL2 since it's not compared to guest memory.
*/
pts = (struct timespec *)(uintptr_t)timeout;
timeout = 0;
haddr2 = g2h(cpu, uaddr2);
break;
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)
{
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;
if (target_to_host_timespec64(pts, timeout)) {
return -TARGET_EFAULT;
}
} else {
pts = NULL;
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,
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;
}
return do_safe_futex(g2h(cpu, uaddr), op, val, pts, haddr2, val3);
}
#endif
@ -8026,7 +8010,11 @@ static int open_self_maps(CPUArchState *cpu_env, int fd)
continue;
}
#ifdef TARGET_HPPA
if (h2g(max) == ts->info->stack_limit) {
#else
if (h2g(min) == ts->info->stack_limit) {
#endif
path = "[stack]";
} else {
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);
fd_trans_unregister(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
case TARGET_NR_close:
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);
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;
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);
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;
#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);
if (!p || !p2) {
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")) {
char real[PATH_MAX], *temp;
temp = realpath(exec_path, real);
ret = temp == NULL ? get_errno(-1) : strlen(real) ;
snprintf((char *)p2, arg4, "%s", 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);
}
} else {
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
#ifdef 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
#ifdef 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
#ifdef CONFIG_INOTIFY
#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;
ret = target_to_host_sigevent(phost_sevp, arg2);
if (ret != 0) {
free_host_timer_slot(timer_index);
return ret;
}
}
ret = get_errno(timer_create(clkid, phost_sevp, phtimer));
if (ret) {
phtimer = NULL;
free_host_timer_slot(timer_index);
} else {
if (put_user(TIMER_MAGIC | timer_index, arg3, target_timer_t)) {
timer_delete(*phtimer);
free_host_timer_slot(timer_index);
return -TARGET_EFAULT;
}
}
@ -12991,7 +13017,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
} else {
timer_t htimer = g_posix_timers[timerid];
ret = get_errno(timer_delete(htimer));
g_posix_timers[timerid] = 0;
free_host_timer_slot(timerid);
}
return ret;
}

View File

@ -1246,7 +1246,7 @@ struct target_winsize {
#include "termbits.h"
#if defined(TARGET_MIPS)
#if defined(TARGET_MIPS) || defined(TARGET_XTENSA)
#define TARGET_PROT_SEM 0x10
#else
#define TARGET_PROT_SEM 0x08
@ -2699,6 +2699,9 @@ struct target_drm_i915_getparam {
#define FUTEX_TRYLOCK_PI 8
#define FUTEX_WAIT_BITSET 9
#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_CLOCK_REALTIME 256

View File

@ -9,6 +9,6 @@
#define X86_64_TARGET_ELF_H
static inline const char *cpu_get_model(uint32_t eflags)
{
return "qemu64";
return "max";
}
#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];
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_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[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;
}