Browse Source
Move safe_syscall() from linux-user to common-user.
Add FreeBSD support to safe_syscall_base().
Tidy top-level meson.build wrt {bsd,linux}-user.
-----BEGIN PGP SIGNATURE-----
iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmHA3YMdHHJpY2hhcmQu
aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV+/XggAqZ2kp/xhmhlVKR8X
YzxmeAkPPuJSCQZt8v0UFPye2/HQTpXCboi4Lo+IgjI+6tpY4LhcY48071iiI5Ug
uWXIW9Y4+GnHPEDbyU3I1Wxg/OtXOj9B0Fy0ULw8ct0vKBjVgPBkiaQqtn+jCzOZ
+7SGdIJMz5hsgW+krP60BHyyXypU/NIDPhCEBRwusZ6Vp5UvkVicNmZaQjh4suZt
5gCFNSq43gw/+KhzjDEZvRTG00LteaCHUDY5nAfbyvE0o8hTDuroO16hCWCb7gZ+
8MH5NMJMOcKupPLk7YCJ+o5NQlWhR86ygZSiTg+WZyHldfXMPBINiLN1b878kNfT
NjcGRA==
=i5x2
-----END PGP SIGNATURE-----
Merge tag 'pull-user-20211220' of https://gitlab.com/rth7680/qemu into staging
Move errno processing from safe_syscall() to safe_syscall_base().
Move safe_syscall() from linux-user to common-user.
Add FreeBSD support to safe_syscall_base().
Tidy top-level meson.build wrt {bsd,linux}-user.
# gpg: Signature made Mon 20 Dec 2021 11:46:11 AM PST
# gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F
# gpg: issuer "richard.henderson@linaro.org"
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg: There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F
* tag 'pull-user-20211220' of https://gitlab.com/rth7680/qemu:
meson: Move bsd_user_ss to bsd-user/
meson: Move linux_user_ss to linux-user/
linux-user: Move thunk.c from top-level
common-user: Adjust system call return on FreeBSD
common-user: Move safe-syscall.* from linux-user
bsd-user: Create special-errno.h
linux-user: Create special-errno.h
linux-user: Rename TARGET_QEMU_ESIGRETURN to QEMU_ESIGRETURN
bsd-user: Rename TARGET_ERESTARTSYS to QEMU_ERESTARTSYS
linux-user: Rename TARGET_ERESTARTSYS to QEMU_ERESTARTSYS
linux-user: Remove HAVE_SAFE_SYSCALL and hostdep.h
linux-user/host/sparc64: Add safe-syscall.inc.S
linux-user/host/mips: Add safe-syscall.inc.S
linux-user: Move syscall error detection into safe_syscall_base
linux-user: Untabify all safe-syscall.inc.S
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
pull/202/head
80 changed files with 1097 additions and 930 deletions
@ -0,0 +1,24 @@ |
|||
/* SPDX-License-Identifier: BSD-3-Clause */ |
|||
/*
|
|||
* QEMU internal errno values for implementing user-only POSIX. |
|||
* |
|||
* Copyright (c) 2021 Linaro, Ltd. |
|||
*/ |
|||
|
|||
#ifndef SPECIAL_ERRNO_H |
|||
#define SPECIAL_ERRNO_H |
|||
|
|||
/*
|
|||
* All of these are QEMU internal, not visible to the guest. |
|||
* They should be chosen so as to not overlap with any host |
|||
* or guest errno. |
|||
*/ |
|||
|
|||
/*
|
|||
* This is returned when a system call should be restarted, to tell the |
|||
* main loop that it should wind the guest PC backwards so it will |
|||
* re-execute the syscall after handling any pending signals. |
|||
*/ |
|||
#define QEMU_ERESTARTSYS 255 |
|||
|
|||
#endif /* SPECIAL_ERRNO_H */ |
|||
@ -0,0 +1,88 @@ |
|||
/* |
|||
* safe-syscall.inc.S : host-specific assembly fragment |
|||
* to handle signals occurring at the same time as system calls. |
|||
* This is intended to be included by common-user/safe-syscall.S |
|||
* |
|||
* Written by Richard Henderson <rth@twiddle.net> |
|||
* Copyright (C) 2016 Red Hat, Inc. |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
.global safe_syscall_base |
|||
.global safe_syscall_start |
|||
.global safe_syscall_end |
|||
.type safe_syscall_base, #function |
|||
.type safe_syscall_start, #function |
|||
.type safe_syscall_end, #function |
|||
|
|||
/* This is the entry point for making a system call. The calling |
|||
* convention here is that of a C varargs function with the |
|||
* first argument an 'int *' to the signal_pending flag, the |
|||
* second one the system call number (as a 'long'), and all further |
|||
* arguments being syscall arguments (also 'long'). |
|||
*/ |
|||
safe_syscall_base: |
|||
.cfi_startproc |
|||
/* The syscall calling convention isn't the same as the |
|||
* C one: |
|||
* we enter with x0 == &signal_pending |
|||
* x1 == syscall number |
|||
* x2 ... x7, (stack) == syscall arguments |
|||
* and return the result in x0 |
|||
* and the syscall instruction needs |
|||
* x8 == syscall number |
|||
* x0 ... x6 == syscall arguments |
|||
* and returns the result in x0 |
|||
* Shuffle everything around appropriately. |
|||
*/ |
|||
mov x9, x0 /* signal_pending pointer */ |
|||
mov x8, x1 /* syscall number */ |
|||
mov x0, x2 /* syscall arguments */ |
|||
mov x1, x3 |
|||
mov x2, x4 |
|||
mov x3, x5 |
|||
mov x4, x6 |
|||
mov x5, x7 |
|||
ldr x6, [sp] |
|||
|
|||
/* This next sequence of code works in conjunction with the |
|||
* rewind_if_safe_syscall_function(). If a signal is taken |
|||
* and the interrupted PC is anywhere between 'safe_syscall_start' |
|||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. |
|||
* The code sequence must therefore be able to cope with this, and |
|||
* the syscall instruction must be the final one in the sequence. |
|||
*/ |
|||
safe_syscall_start: |
|||
/* if signal_pending is non-zero, don't do the call */ |
|||
ldr w10, [x9] |
|||
cbnz w10, 2f |
|||
svc 0x0 |
|||
safe_syscall_end: |
|||
|
|||
/* code path for having successfully executed the syscall */ |
|||
#if defined(__linux__) |
|||
/* Linux kernel returns (small) negative errno. */ |
|||
cmp x0, #-4096 |
|||
b.hi 0f |
|||
#elif defined(__FreeBSD__) |
|||
/* FreeBSD kernel returns positive errno and C bit set. */ |
|||
b.cs 1f |
|||
#else |
|||
#error "unsupported os" |
|||
#endif |
|||
ret |
|||
|
|||
#if defined(__linux__) |
|||
/* code path setting errno */ |
|||
0: neg w0, w0 |
|||
b safe_syscall_set_errno_tail |
|||
#endif |
|||
|
|||
/* code path when we didn't execute the syscall */ |
|||
2: mov w0, #QEMU_ERESTARTSYS |
|||
1: b safe_syscall_set_errno_tail |
|||
|
|||
.cfi_endproc |
|||
.size safe_syscall_base, .-safe_syscall_base |
|||
@ -0,0 +1,108 @@ |
|||
/* |
|||
* safe-syscall.inc.S : host-specific assembly fragment |
|||
* to handle signals occurring at the same time as system calls. |
|||
* This is intended to be included by common-user/safe-syscall.S |
|||
* |
|||
* Written by Richard Henderson <rth@twiddle.net> |
|||
* Copyright (C) 2016 Red Hat, Inc. |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
.global safe_syscall_base |
|||
.global safe_syscall_start |
|||
.global safe_syscall_end |
|||
.type safe_syscall_base, %function |
|||
|
|||
.cfi_sections .debug_frame |
|||
|
|||
.text |
|||
.syntax unified |
|||
.arm |
|||
.align 2 |
|||
|
|||
/* This is the entry point for making a system call. The calling |
|||
* convention here is that of a C varargs function with the |
|||
* first argument an 'int *' to the signal_pending flag, the |
|||
* second one the system call number (as a 'long'), and all further |
|||
* arguments being syscall arguments (also 'long'). |
|||
*/ |
|||
safe_syscall_base: |
|||
.fnstart |
|||
.cfi_startproc |
|||
mov r12, sp /* save entry stack */ |
|||
push { r4, r5, r6, r7, r8, lr } |
|||
.save { r4, r5, r6, r7, r8, lr } |
|||
.cfi_adjust_cfa_offset 24 |
|||
.cfi_rel_offset r4, 0 |
|||
.cfi_rel_offset r5, 4 |
|||
.cfi_rel_offset r6, 8 |
|||
.cfi_rel_offset r7, 12 |
|||
.cfi_rel_offset r8, 16 |
|||
.cfi_rel_offset lr, 20 |
|||
|
|||
/* The syscall calling convention isn't the same as the C one: |
|||
* we enter with r0 == &signal_pending |
|||
* r1 == syscall number |
|||
* r2, r3, [sp+0] ... [sp+12] == syscall arguments |
|||
* and return the result in r0 |
|||
* and the syscall instruction needs |
|||
* r7 == syscall number |
|||
* r0 ... r6 == syscall arguments |
|||
* and returns the result in r0 |
|||
* Shuffle everything around appropriately. |
|||
* Note the 16 bytes that we pushed to save registers. |
|||
*/ |
|||
mov r8, r0 /* copy signal_pending */ |
|||
mov r7, r1 /* syscall number */ |
|||
mov r0, r2 /* syscall args */ |
|||
mov r1, r3 |
|||
ldm r12, { r2, r3, r4, r5, r6 } |
|||
|
|||
/* This next sequence of code works in conjunction with the |
|||
* rewind_if_safe_syscall_function(). If a signal is taken |
|||
* and the interrupted PC is anywhere between 'safe_syscall_start' |
|||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. |
|||
* The code sequence must therefore be able to cope with this, and |
|||
* the syscall instruction must be the final one in the sequence. |
|||
*/ |
|||
safe_syscall_start: |
|||
/* if signal_pending is non-zero, don't do the call */ |
|||
ldr r12, [r8] /* signal_pending */ |
|||
tst r12, r12 |
|||
bne 2f |
|||
swi 0 |
|||
safe_syscall_end: |
|||
|
|||
/* code path for having successfully executed the syscall */ |
|||
#if defined(__linux__) |
|||
/* Linux kernel returns (small) negative errno. */ |
|||
cmp r0, #-4096 |
|||
neghi r0, r0 |
|||
bhi 1f |
|||
#elif defined(__FreeBSD__) |
|||
/* FreeBSD kernel returns positive errno and C bit set. */ |
|||
bcs 1f |
|||
#else |
|||
#error "unsupported os" |
|||
#endif |
|||
pop { r4, r5, r6, r7, r8, pc } |
|||
|
|||
/* code path when we didn't execute the syscall */ |
|||
2: mov r0, #QEMU_ERESTARTSYS |
|||
|
|||
/* code path setting errno */ |
|||
1: pop { r4, r5, r6, r7, r8, lr } |
|||
.cfi_adjust_cfa_offset -24 |
|||
.cfi_restore r4 |
|||
.cfi_restore r5 |
|||
.cfi_restore r6 |
|||
.cfi_restore r7 |
|||
.cfi_restore r8 |
|||
.cfi_restore lr |
|||
b safe_syscall_set_errno_tail |
|||
|
|||
.fnend |
|||
.cfi_endproc |
|||
.size safe_syscall_base, .-safe_syscall_base |
|||
@ -0,0 +1,126 @@ |
|||
/* |
|||
* safe-syscall.inc.S : host-specific assembly fragment |
|||
* to handle signals occurring at the same time as system calls. |
|||
* This is intended to be included by common-user/safe-syscall.S |
|||
* |
|||
* Written by Richard Henderson <rth@twiddle.net> |
|||
* Copyright (C) 2016 Red Hat, Inc. |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
.global safe_syscall_base |
|||
.global safe_syscall_start |
|||
.global safe_syscall_end |
|||
.type safe_syscall_base, @function |
|||
|
|||
/* This is the entry point for making a system call. The calling |
|||
* convention here is that of a C varargs function with the |
|||
* first argument an 'int *' to the signal_pending flag, the |
|||
* second one the system call number (as a 'long'), and all further |
|||
* arguments being syscall arguments (also 'long'). |
|||
*/ |
|||
safe_syscall_base: |
|||
.cfi_startproc |
|||
push %ebp |
|||
.cfi_adjust_cfa_offset 4 |
|||
.cfi_rel_offset ebp, 0 |
|||
push %esi |
|||
.cfi_adjust_cfa_offset 4 |
|||
.cfi_rel_offset esi, 0 |
|||
push %edi |
|||
.cfi_adjust_cfa_offset 4 |
|||
.cfi_rel_offset edi, 0 |
|||
push %ebx |
|||
.cfi_adjust_cfa_offset 4 |
|||
.cfi_rel_offset ebx, 0 |
|||
|
|||
/* The syscall calling convention isn't the same as the C one: |
|||
* we enter with 0(%esp) == return address |
|||
* 4(%esp) == &signal_pending |
|||
* 8(%esp) == syscall number |
|||
* 12(%esp) ... 32(%esp) == syscall arguments |
|||
* and return the result in eax |
|||
* and the syscall instruction needs |
|||
* eax == syscall number |
|||
* ebx, ecx, edx, esi, edi, ebp == syscall arguments |
|||
* and returns the result in eax |
|||
* Shuffle everything around appropriately. |
|||
* Note the 16 bytes that we pushed to save registers. |
|||
*/ |
|||
mov 12+16(%esp), %ebx /* the syscall arguments */ |
|||
mov 16+16(%esp), %ecx |
|||
mov 20+16(%esp), %edx |
|||
mov 24+16(%esp), %esi |
|||
mov 28+16(%esp), %edi |
|||
mov 32+16(%esp), %ebp |
|||
|
|||
/* This next sequence of code works in conjunction with the |
|||
* rewind_if_safe_syscall_function(). If a signal is taken |
|||
* and the interrupted PC is anywhere between 'safe_syscall_start' |
|||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. |
|||
* The code sequence must therefore be able to cope with this, and |
|||
* the syscall instruction must be the final one in the sequence. |
|||
*/ |
|||
safe_syscall_start: |
|||
/* if signal_pending is non-zero, don't do the call */ |
|||
mov 4+16(%esp), %eax /* signal_pending */ |
|||
cmpl $0, (%eax) |
|||
jnz 2f |
|||
mov 8+16(%esp), %eax /* syscall number */ |
|||
int $0x80 |
|||
safe_syscall_end: |
|||
|
|||
/* code path for having successfully executed the syscall */ |
|||
#if defined(__linux__) |
|||
/* Linux kernel returns (small) negative errno. */ |
|||
cmp $-4095, %eax |
|||
jae 0f |
|||
#elif defined(__FreeBSD__) |
|||
/* FreeBSD kernel returns positive errno and C bit set. */ |
|||
jc 1f |
|||
#else |
|||
#error "unsupported os" |
|||
#endif |
|||
pop %ebx |
|||
.cfi_remember_state |
|||
.cfi_adjust_cfa_offset -4 |
|||
.cfi_restore ebx |
|||
pop %edi |
|||
.cfi_adjust_cfa_offset -4 |
|||
.cfi_restore edi |
|||
pop %esi |
|||
.cfi_adjust_cfa_offset -4 |
|||
.cfi_restore esi |
|||
pop %ebp |
|||
.cfi_adjust_cfa_offset -4 |
|||
.cfi_restore ebp |
|||
ret |
|||
.cfi_restore_state |
|||
|
|||
#if defined(__linux__) |
|||
0: neg %eax |
|||
jmp 1f |
|||
#endif |
|||
|
|||
/* code path when we didn't execute the syscall */ |
|||
2: mov $QEMU_ERESTARTSYS, %eax |
|||
|
|||
/* code path setting errno */ |
|||
1: pop %ebx |
|||
.cfi_adjust_cfa_offset -4 |
|||
.cfi_restore ebx |
|||
pop %edi |
|||
.cfi_adjust_cfa_offset -4 |
|||
.cfi_restore edi |
|||
pop %esi |
|||
.cfi_adjust_cfa_offset -4 |
|||
.cfi_restore esi |
|||
pop %ebp |
|||
.cfi_adjust_cfa_offset -4 |
|||
.cfi_restore ebp |
|||
jmp safe_syscall_set_errno_tail |
|||
|
|||
.cfi_endproc |
|||
.size safe_syscall_base, .-safe_syscall_base |
|||
@ -0,0 +1,148 @@ |
|||
/* |
|||
* safe-syscall.inc.S : host-specific assembly fragment |
|||
* to handle signals occurring at the same time as system calls. |
|||
* This is intended to be included by common-user/safe-syscall.S |
|||
* |
|||
* Written by Richard Henderson <richard.henderson@linaro.org> |
|||
* Copyright (C) 2021 Linaro, Inc. |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
#include "sys/regdef.h" |
|||
#include "sys/asm.h" |
|||
|
|||
.text |
|||
.set nomips16 |
|||
.set reorder |
|||
|
|||
.global safe_syscall_start |
|||
.global safe_syscall_end |
|||
.type safe_syscall_start, @function |
|||
.type safe_syscall_end, @function |
|||
|
|||
/* |
|||
* This is the entry point for making a system call. The calling |
|||
* convention here is that of a C varargs function with the |
|||
* first argument an 'int *' to the signal_pending flag, the |
|||
* second one the system call number (as a 'long'), and all further |
|||
* arguments being syscall arguments (also 'long'). |
|||
*/ |
|||
|
|||
#if _MIPS_SIM == _ABIO32 |
|||
/* 8 * 4 = 32 for outgoing parameters; 1 * 4 for s0 save; 1 * 4 for align. */ |
|||
#define FRAME 40 |
|||
#define OFS_S0 32 |
|||
#else |
|||
/* 1 * 8 for s0 save; 1 * 8 for align. */ |
|||
#define FRAME 16 |
|||
#define OFS_S0 0 |
|||
#endif |
|||
|
|||
|
|||
NESTED(safe_syscall_base, FRAME, ra) |
|||
.cfi_startproc |
|||
PTR_ADDIU sp, sp, -FRAME |
|||
.cfi_adjust_cfa_offset FRAME |
|||
REG_S s0, OFS_S0(sp) |
|||
.cfi_rel_offset s0, OFS_S0 |
|||
#if _MIPS_SIM == _ABIO32 |
|||
/* |
|||
* The syscall calling convention is nearly the same as C: |
|||
* we enter with a0 == &signal_pending |
|||
* a1 == syscall number |
|||
* a2, a3, stack == syscall arguments |
|||
* and return the result in a0 |
|||
* and the syscall instruction needs |
|||
* v0 == syscall number |
|||
* a0 ... a3, stack == syscall arguments |
|||
* and returns the result in v0 |
|||
* Shuffle everything around appropriately. |
|||
*/ |
|||
move s0, a0 /* signal_pending pointer */ |
|||
move v0, a1 /* syscall number */ |
|||
move a0, a2 /* syscall arguments */ |
|||
move a1, a3 |
|||
lw a2, FRAME+16(sp) |
|||
lw a3, FRAME+20(sp) |
|||
lw t4, FRAME+24(sp) |
|||
lw t5, FRAME+28(sp) |
|||
lw t6, FRAME+32(sp) |
|||
lw t7, FRAME+40(sp) |
|||
sw t4, 16(sp) |
|||
sw t5, 20(sp) |
|||
sw t6, 24(sp) |
|||
sw t7, 28(sp) |
|||
#else |
|||
/* |
|||
* The syscall calling convention is nearly the same as C: |
|||
* we enter with a0 == &signal_pending |
|||
* a1 == syscall number |
|||
* a2 ... a7 == syscall arguments |
|||
* and return the result in a0 |
|||
* and the syscall instruction needs |
|||
* v0 == syscall number |
|||
* a0 ... a5 == syscall arguments |
|||
* and returns the result in v0 |
|||
* Shuffle everything around appropriately. |
|||
*/ |
|||
move s0, a0 /* signal_pending pointer */ |
|||
move v0, a1 /* syscall number */ |
|||
move a0, a2 /* syscall arguments */ |
|||
move a1, a3 |
|||
move a2, a4 |
|||
move a3, a5 |
|||
move a4, a6 |
|||
move a5, a7 |
|||
#endif |
|||
|
|||
/* |
|||
* This next sequence of code works in conjunction with the |
|||
* rewind_if_safe_syscall_function(). If a signal is taken |
|||
* and the interrupted PC is anywhere between 'safe_syscall_start' |
|||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. |
|||
* The code sequence must therefore be able to cope with this, and |
|||
* the syscall instruction must be the final one in the sequence. |
|||
*/ |
|||
safe_syscall_start: |
|||
/* If signal_pending is non-zero, don't do the call */ |
|||
lw t1, 0(s0) |
|||
bnez t1, 2f |
|||
syscall |
|||
safe_syscall_end: |
|||
|
|||
/* code path for having successfully executed the syscall */ |
|||
REG_L s0, OFS_S0(sp) |
|||
PTR_ADDIU sp, sp, FRAME |
|||
.cfi_remember_state |
|||
.cfi_adjust_cfa_offset -FRAME |
|||
.cfi_restore s0 |
|||
bnez a3, 1f |
|||
jr ra |
|||
.cfi_restore_state |
|||
|
|||
/* code path when we didn't execute the syscall */ |
|||
2: REG_L s0, OFS_S0(sp) |
|||
PTR_ADDIU sp, sp, FRAME |
|||
.cfi_adjust_cfa_offset -FRAME |
|||
.cfi_restore s0 |
|||
li v0, QEMU_ERESTARTSYS |
|||
|
|||
/* code path setting errno */ |
|||
/* |
|||
* We didn't setup GP on entry, optimistic of the syscall success. |
|||
* We must do so now to load the address of the helper, as required |
|||
* by the ABI, into t9. |
|||
* |
|||
* Note that SETUP_GPX and SETUP_GPX64 are themselves conditional, |
|||
* so we can simply let the one that's not empty succeed. |
|||
*/ |
|||
1: USE_ALT_CP(t0) |
|||
SETUP_GPX(t1) |
|||
SETUP_GPX64(t0, t1) |
|||
PTR_LA t9, safe_syscall_set_errno_tail |
|||
jr t9 |
|||
|
|||
.cfi_endproc |
|||
END(safe_syscall_base) |
|||
@ -0,0 +1,94 @@ |
|||
/* |
|||
* safe-syscall.inc.S : host-specific assembly fragment |
|||
* to handle signals occurring at the same time as system calls. |
|||
* This is intended to be included by common-user/safe-syscall.S |
|||
* |
|||
* Written by Richard Henderson <rth@twiddle.net> |
|||
* Copyright (C) 2016 Red Hat, Inc. |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
.global safe_syscall_base |
|||
.global safe_syscall_start |
|||
.global safe_syscall_end |
|||
.type safe_syscall_base, @function |
|||
|
|||
.text |
|||
|
|||
/* This is the entry point for making a system call. The calling |
|||
* convention here is that of a C varargs function with the |
|||
* first argument an 'int *' to the signal_pending flag, the |
|||
* second one the system call number (as a 'long'), and all further |
|||
* arguments being syscall arguments (also 'long'). |
|||
*/ |
|||
#if _CALL_ELF == 2 |
|||
safe_syscall_base: |
|||
.cfi_startproc |
|||
.localentry safe_syscall_base,0 |
|||
#else |
|||
.section ".opd","aw" |
|||
.align 3 |
|||
safe_syscall_base: |
|||
.quad .L.safe_syscall_base,.TOC.@tocbase,0 |
|||
.previous |
|||
.L.safe_syscall_base: |
|||
.cfi_startproc |
|||
#endif |
|||
/* We enter with r3 == &signal_pending |
|||
* r4 == syscall number |
|||
* r5 ... r10 == syscall arguments |
|||
* and return the result in r3 |
|||
* and the syscall instruction needs |
|||
* r0 == syscall number |
|||
* r3 ... r8 == syscall arguments |
|||
* and returns the result in r3 |
|||
* Shuffle everything around appropriately. |
|||
*/ |
|||
std 14, 16(1) /* Preserve r14 in SP+16 */ |
|||
.cfi_offset 14, 16 |
|||
mr 14, 3 /* signal_pending */ |
|||
mr 0, 4 /* syscall number */ |
|||
mr 3, 5 /* syscall arguments */ |
|||
mr 4, 6 |
|||
mr 5, 7 |
|||
mr 6, 8 |
|||
mr 7, 9 |
|||
mr 8, 10 |
|||
|
|||
/* This next sequence of code works in conjunction with the |
|||
* rewind_if_safe_syscall_function(). If a signal is taken |
|||
* and the interrupted PC is anywhere between 'safe_syscall_start' |
|||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. |
|||
* The code sequence must therefore be able to cope with this, and |
|||
* the syscall instruction must be the final one in the sequence. |
|||
*/ |
|||
safe_syscall_start: |
|||
/* if signal_pending is non-zero, don't do the call */ |
|||
lwz 12, 0(14) |
|||
cmpwi 0, 12, 0 |
|||
bne- 2f |
|||
sc |
|||
safe_syscall_end: |
|||
/* code path when we did execute the syscall */ |
|||
ld 14, 16(1) /* restore r14 */ |
|||
bso- 1f |
|||
blr |
|||
|
|||
/* code path when we didn't execute the syscall */ |
|||
2: ld 14, 16(1) /* restore r14 */ |
|||
addi 3, 0, QEMU_ERESTARTSYS |
|||
|
|||
/* code path setting errno */ |
|||
1: b safe_syscall_set_errno_tail |
|||
nop /* per abi, for the linker to modify */ |
|||
|
|||
.cfi_endproc |
|||
|
|||
#if _CALL_ELF == 2 |
|||
.size safe_syscall_base, .-safe_syscall_base |
|||
#else |
|||
.size safe_syscall_base, .-.L.safe_syscall_base |
|||
.size .L.safe_syscall_base, .-.L.safe_syscall_base |
|||
#endif |
|||
@ -0,0 +1,79 @@ |
|||
/* |
|||
* safe-syscall.inc.S : host-specific assembly fragment |
|||
* to handle signals occurring at the same time as system calls. |
|||
* This is intended to be included by common-user/safe-syscall.S |
|||
* |
|||
* Written by Richard Henderson <rth@twiddle.net> |
|||
* Copyright (C) 2018 Linaro, Inc. |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
.global safe_syscall_base |
|||
.global safe_syscall_start |
|||
.global safe_syscall_end |
|||
.type safe_syscall_base, @function |
|||
.type safe_syscall_start, @function |
|||
.type safe_syscall_end, @function |
|||
|
|||
/* |
|||
* This is the entry point for making a system call. The calling |
|||
* convention here is that of a C varargs function with the |
|||
* first argument an 'int *' to the signal_pending flag, the |
|||
* second one the system call number (as a 'long'), and all further |
|||
* arguments being syscall arguments (also 'long'). |
|||
*/ |
|||
safe_syscall_base: |
|||
.cfi_startproc |
|||
/* |
|||
* The syscall calling convention is nearly the same as C: |
|||
* we enter with a0 == &signal_pending |
|||
* a1 == syscall number |
|||
* a2 ... a7 == syscall arguments |
|||
* and return the result in a0 |
|||
* and the syscall instruction needs |
|||
* a7 == syscall number |
|||
* a0 ... a5 == syscall arguments |
|||
* and returns the result in a0 |
|||
* Shuffle everything around appropriately. |
|||
*/ |
|||
mv t0, a0 /* signal_pending pointer */ |
|||
mv t1, a1 /* syscall number */ |
|||
mv a0, a2 /* syscall arguments */ |
|||
mv a1, a3 |
|||
mv a2, a4 |
|||
mv a3, a5 |
|||
mv a4, a6 |
|||
mv a5, a7 |
|||
mv a7, t1 |
|||
|
|||
/* |
|||
* This next sequence of code works in conjunction with the |
|||
* rewind_if_safe_syscall_function(). If a signal is taken |
|||
* and the interrupted PC is anywhere between 'safe_syscall_start' |
|||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. |
|||
* The code sequence must therefore be able to cope with this, and |
|||
* the syscall instruction must be the final one in the sequence. |
|||
*/ |
|||
safe_syscall_start: |
|||
/* If signal_pending is non-zero, don't do the call */ |
|||
lw t1, 0(t0) |
|||
bnez t1, 2f |
|||
scall |
|||
safe_syscall_end: |
|||
/* code path for having successfully executed the syscall */ |
|||
li t2, -4096 |
|||
bgtu a0, t2, 0f |
|||
ret |
|||
|
|||
/* code path setting errno */ |
|||
0: neg a0, a0 |
|||
j safe_syscall_set_errno_tail |
|||
|
|||
/* code path when we didn't execute the syscall */ |
|||
2: li a0, QEMU_ERESTARTSYS |
|||
j safe_syscall_set_errno_tail |
|||
|
|||
.cfi_endproc |
|||
.size safe_syscall_base, .-safe_syscall_base |
|||
@ -0,0 +1,98 @@ |
|||
/* |
|||
* safe-syscall.inc.S : host-specific assembly fragment |
|||
* to handle signals occurring at the same time as system calls. |
|||
* This is intended to be included by common-user/safe-syscall.S |
|||
* |
|||
* Written by Richard Henderson <rth@twiddle.net> |
|||
* Copyright (C) 2016 Red Hat, Inc. |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
.global safe_syscall_base |
|||
.global safe_syscall_start |
|||
.global safe_syscall_end |
|||
.type safe_syscall_base, @function |
|||
|
|||
/* This is the entry point for making a system call. The calling |
|||
* convention here is that of a C varargs function with the |
|||
* first argument an 'int *' to the signal_pending flag, the |
|||
* second one the system call number (as a 'long'), and all further |
|||
* arguments being syscall arguments (also 'long'). |
|||
*/ |
|||
safe_syscall_base: |
|||
.cfi_startproc |
|||
stmg %r6,%r15,48(%r15) /* save all call-saved registers */ |
|||
.cfi_offset %r15,-40 |
|||
.cfi_offset %r14,-48 |
|||
.cfi_offset %r13,-56 |
|||
.cfi_offset %r12,-64 |
|||
.cfi_offset %r11,-72 |
|||
.cfi_offset %r10,-80 |
|||
.cfi_offset %r9,-88 |
|||
.cfi_offset %r8,-96 |
|||
.cfi_offset %r7,-104 |
|||
.cfi_offset %r6,-112 |
|||
lgr %r1,%r15 |
|||
lg %r0,8(%r15) /* load eos */ |
|||
aghi %r15,-160 |
|||
.cfi_adjust_cfa_offset 160 |
|||
stg %r1,0(%r15) /* store back chain */ |
|||
stg %r0,8(%r15) /* store eos */ |
|||
|
|||
/* |
|||
* The syscall calling convention isn't the same as the C one: |
|||
* we enter with r2 == &signal_pending |
|||
* r3 == syscall number |
|||
* r4, r5, r6, (stack) == syscall arguments |
|||
* and return the result in r2 |
|||
* and the syscall instruction needs |
|||
* r1 == syscall number |
|||
* r2 ... r7 == syscall arguments |
|||
* and returns the result in r2 |
|||
* Shuffle everything around appropriately. |
|||
*/ |
|||
lgr %r8,%r2 /* signal_pending pointer */ |
|||
lgr %r1,%r3 /* syscall number */ |
|||
lgr %r2,%r4 /* syscall args */ |
|||
lgr %r3,%r5 |
|||
lgr %r4,%r6 |
|||
lmg %r5,%r7,320(%r15) |
|||
|
|||
/* This next sequence of code works in conjunction with the |
|||
* rewind_if_safe_syscall_function(). If a signal is taken |
|||
* and the interrupted PC is anywhere between 'safe_syscall_start' |
|||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. |
|||
* The code sequence must therefore be able to cope with this, and |
|||
* the syscall instruction must be the final one in the sequence. |
|||
*/ |
|||
safe_syscall_start: |
|||
/* if signal_pending is non-zero, don't do the call */ |
|||
icm %r0,15,0(%r8) |
|||
jne 2f |
|||
svc 0 |
|||
safe_syscall_end: |
|||
|
|||
/* code path for having successfully executed the syscall */ |
|||
lg %r15,0(%r15) /* load back chain */ |
|||
.cfi_remember_state |
|||
.cfi_adjust_cfa_offset -160 |
|||
lmg %r6,%r15,48(%r15) /* load saved registers */ |
|||
|
|||
lghi %r0, -4095 /* check for syscall error */ |
|||
clgr %r2, %r0 |
|||
blr %r14 /* return on success */ |
|||
lcr %r2, %r2 /* create positive errno */ |
|||
jg safe_syscall_set_errno_tail |
|||
.cfi_restore_state |
|||
|
|||
/* code path when we didn't execute the syscall */ |
|||
2: lg %r15,0(%r15) /* load back chain */ |
|||
.cfi_adjust_cfa_offset -160 |
|||
lmg %r6,%r15,48(%r15) /* load saved registers */ |
|||
lghi %r2, QEMU_ERESTARTSYS |
|||
jg safe_syscall_set_errno_tail |
|||
|
|||
.cfi_endproc |
|||
.size safe_syscall_base, .-safe_syscall_base |
|||
@ -0,0 +1,89 @@ |
|||
/* |
|||
* safe-syscall.inc.S : host-specific assembly fragment |
|||
* to handle signals occurring at the same time as system calls. |
|||
* This is intended to be included by common-user/safe-syscall.S |
|||
* |
|||
* Written by Richard Henderson <richard.henderson@linaro.org> |
|||
* Copyright (C) 2021 Linaro, Inc. |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
.text |
|||
.balign 4 |
|||
|
|||
.register %g2, #scratch |
|||
.register %g3, #scratch |
|||
|
|||
.global safe_syscall_base |
|||
.global safe_syscall_start |
|||
.global safe_syscall_end |
|||
.type safe_syscall_base, @function |
|||
.type safe_syscall_start, @function |
|||
.type safe_syscall_end, @function |
|||
|
|||
#define STACK_BIAS 2047 |
|||
#define PARAM(N) STACK_BIAS + N*8 |
|||
|
|||
/* |
|||
* This is the entry point for making a system call. The calling |
|||
* convention here is that of a C varargs function with the |
|||
* first argument an 'int *' to the signal_pending flag, the |
|||
* second one the system call number (as a 'long'), and all further |
|||
* arguments being syscall arguments (also 'long'). |
|||
*/ |
|||
safe_syscall_base: |
|||
.cfi_startproc |
|||
/* |
|||
* The syscall calling convention isn't the same as the C one: |
|||
* we enter with o0 == &signal_pending |
|||
* o1 == syscall number |
|||
* o2 ... o5, (stack) == syscall arguments |
|||
* and return the result in x0 |
|||
* and the syscall instruction needs |
|||
* g1 == syscall number |
|||
* o0 ... o5 == syscall arguments |
|||
* and returns the result in o0 |
|||
* Shuffle everything around appropriately. |
|||
*/ |
|||
mov %o0, %g2 /* signal_pending pointer */ |
|||
mov %o1, %g1 /* syscall number */ |
|||
mov %o2, %o0 /* syscall arguments */ |
|||
mov %o3, %o1 |
|||
mov %o4, %o2 |
|||
mov %o5, %o3 |
|||
ldx [%sp + PARAM(6)], %o4 |
|||
ldx [%sp + PARAM(7)], %o5 |
|||
|
|||
/* |
|||
* This next sequence of code works in conjunction with the |
|||
* rewind_if_safe_syscall_function(). If a signal is taken |
|||
* and the interrupted PC is anywhere between 'safe_syscall_start' |
|||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. |
|||
* The code sequence must therefore be able to cope with this, and |
|||
* the syscall instruction must be the final one in the sequence. |
|||
*/ |
|||
safe_syscall_start: |
|||
/* if signal_pending is non-zero, don't do the call */ |
|||
lduw [%g2], %g3 |
|||
brnz,pn %g3, 2f |
|||
nop |
|||
ta 0x6d |
|||
safe_syscall_end: |
|||
/* code path for having successfully executed the syscall */ |
|||
bcs,pn %xcc, 1f |
|||
nop |
|||
ret |
|||
nop |
|||
|
|||
/* code path when we didn't execute the syscall */ |
|||
2: set QEMU_ERESTARTSYS, %o0 |
|||
|
|||
/* code path setting errno */ |
|||
1: mov %o7, %g1 |
|||
call safe_syscall_set_errno_tail |
|||
mov %g1, %o7 |
|||
|
|||
.cfi_endproc |
|||
.size safe_syscall_base, .-safe_syscall_base |
|||
@ -0,0 +1,6 @@ |
|||
common_user_inc += include_directories('host/' / host_arch) |
|||
|
|||
common_user_ss.add(files( |
|||
'safe-syscall.S', |
|||
'safe-syscall-error.c', |
|||
)) |
|||
@ -0,0 +1,25 @@ |
|||
/*
|
|||
* safe-syscall-error.c: errno setting fragment |
|||
* This is intended to be invoked by safe-syscall.S |
|||
* |
|||
* Written by Richard Henderson <rth@twiddle.net> |
|||
* Copyright (C) 2021 Red Hat, Inc. |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
#include "qemu/osdep.h" |
|||
#include "user/safe-syscall.h" |
|||
|
|||
/*
|
|||
* This is intended to be invoked via tail-call on the error path |
|||
* from the assembly in host/arch/safe-syscall.inc.S. This takes |
|||
* care of the host specific addressing of errno. |
|||
* Return -1 to finalize the return value for safe_syscall_base. |
|||
*/ |
|||
long safe_syscall_set_errno_tail(int value) |
|||
{ |
|||
errno = value; |
|||
return -1; |
|||
} |
|||
@ -1,18 +0,0 @@ |
|||
/*
|
|||
* hostdep.h : things which are dependent on the host architecture |
|||
* |
|||
* * Written by Peter Maydell <peter.maydell@linaro.org> |
|||
* |
|||
* Copyright (C) 2016 Linaro Limited |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
#ifndef AARCH64_HOSTDEP_H |
|||
#define AARCH64_HOSTDEP_H |
|||
|
|||
/* We have a safe-syscall.inc.S */ |
|||
#define HAVE_SAFE_SYSCALL |
|||
|
|||
#endif |
|||
@ -1,75 +0,0 @@ |
|||
/* |
|||
* safe-syscall.inc.S : host-specific assembly fragment |
|||
* to handle signals occurring at the same time as system calls. |
|||
* This is intended to be included by linux-user/safe-syscall.S |
|||
* |
|||
* Written by Richard Henderson <rth@twiddle.net> |
|||
* Copyright (C) 2016 Red Hat, Inc. |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
.global safe_syscall_base |
|||
.global safe_syscall_start |
|||
.global safe_syscall_end |
|||
.type safe_syscall_base, #function |
|||
.type safe_syscall_start, #function |
|||
.type safe_syscall_end, #function |
|||
|
|||
/* This is the entry point for making a system call. The calling |
|||
* convention here is that of a C varargs function with the |
|||
* first argument an 'int *' to the signal_pending flag, the |
|||
* second one the system call number (as a 'long'), and all further |
|||
* arguments being syscall arguments (also 'long'). |
|||
* We return a long which is the syscall's return value, which |
|||
* may be negative-errno on failure. Conversion to the |
|||
* -1-and-errno-set convention is done by the calling wrapper. |
|||
*/ |
|||
safe_syscall_base: |
|||
.cfi_startproc |
|||
/* The syscall calling convention isn't the same as the |
|||
* C one: |
|||
* we enter with x0 == *signal_pending |
|||
* x1 == syscall number |
|||
* x2 ... x7, (stack) == syscall arguments |
|||
* and return the result in x0 |
|||
* and the syscall instruction needs |
|||
* x8 == syscall number |
|||
* x0 ... x6 == syscall arguments |
|||
* and returns the result in x0 |
|||
* Shuffle everything around appropriately. |
|||
*/ |
|||
mov x9, x0 /* signal_pending pointer */ |
|||
mov x8, x1 /* syscall number */ |
|||
mov x0, x2 /* syscall arguments */ |
|||
mov x1, x3 |
|||
mov x2, x4 |
|||
mov x3, x5 |
|||
mov x4, x6 |
|||
mov x5, x7 |
|||
ldr x6, [sp] |
|||
|
|||
/* This next sequence of code works in conjunction with the |
|||
* rewind_if_safe_syscall_function(). If a signal is taken |
|||
* and the interrupted PC is anywhere between 'safe_syscall_start' |
|||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. |
|||
* The code sequence must therefore be able to cope with this, and |
|||
* the syscall instruction must be the final one in the sequence. |
|||
*/ |
|||
safe_syscall_start: |
|||
/* if signal_pending is non-zero, don't do the call */ |
|||
ldr w10, [x9] |
|||
cbnz w10, 0f |
|||
svc 0x0 |
|||
safe_syscall_end: |
|||
/* code path for having successfully executed the syscall */ |
|||
ret |
|||
|
|||
0: |
|||
/* code path when we didn't execute the syscall */ |
|||
mov x0, #-TARGET_ERESTARTSYS |
|||
ret |
|||
.cfi_endproc |
|||
|
|||
.size safe_syscall_base, .-safe_syscall_base |
|||
@ -1,18 +0,0 @@ |
|||
/*
|
|||
* hostdep.h : things which are dependent on the host architecture |
|||
* |
|||
* * Written by Peter Maydell <peter.maydell@linaro.org> |
|||
* |
|||
* Copyright (C) 2016 Linaro Limited |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
#ifndef ARM_HOSTDEP_H |
|||
#define ARM_HOSTDEP_H |
|||
|
|||
/* We have a safe-syscall.inc.S */ |
|||
#define HAVE_SAFE_SYSCALL |
|||
|
|||
#endif |
|||
@ -1,90 +0,0 @@ |
|||
/* |
|||
* safe-syscall.inc.S : host-specific assembly fragment |
|||
* to handle signals occurring at the same time as system calls. |
|||
* This is intended to be included by linux-user/safe-syscall.S |
|||
* |
|||
* Written by Richard Henderson <rth@twiddle.net> |
|||
* Copyright (C) 2016 Red Hat, Inc. |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
.global safe_syscall_base |
|||
.global safe_syscall_start |
|||
.global safe_syscall_end |
|||
.type safe_syscall_base, %function |
|||
|
|||
.cfi_sections .debug_frame |
|||
|
|||
.text |
|||
.syntax unified |
|||
.arm |
|||
.align 2 |
|||
|
|||
/* This is the entry point for making a system call. The calling |
|||
* convention here is that of a C varargs function with the |
|||
* first argument an 'int *' to the signal_pending flag, the |
|||
* second one the system call number (as a 'long'), and all further |
|||
* arguments being syscall arguments (also 'long'). |
|||
* We return a long which is the syscall's return value, which |
|||
* may be negative-errno on failure. Conversion to the |
|||
* -1-and-errno-set convention is done by the calling wrapper. |
|||
*/ |
|||
safe_syscall_base: |
|||
.fnstart |
|||
.cfi_startproc |
|||
mov r12, sp /* save entry stack */ |
|||
push { r4, r5, r6, r7, r8, lr } |
|||
.save { r4, r5, r6, r7, r8, lr } |
|||
.cfi_adjust_cfa_offset 24 |
|||
.cfi_rel_offset r4, 0 |
|||
.cfi_rel_offset r5, 4 |
|||
.cfi_rel_offset r6, 8 |
|||
.cfi_rel_offset r7, 12 |
|||
.cfi_rel_offset r8, 16 |
|||
.cfi_rel_offset lr, 20 |
|||
|
|||
/* The syscall calling convention isn't the same as the C one: |
|||
* we enter with r0 == *signal_pending |
|||
* r1 == syscall number |
|||
* r2, r3, [sp+0] ... [sp+12] == syscall arguments |
|||
* and return the result in r0 |
|||
* and the syscall instruction needs |
|||
* r7 == syscall number |
|||
* r0 ... r6 == syscall arguments |
|||
* and returns the result in r0 |
|||
* Shuffle everything around appropriately. |
|||
* Note the 16 bytes that we pushed to save registers. |
|||
*/ |
|||
mov r8, r0 /* copy signal_pending */ |
|||
mov r7, r1 /* syscall number */ |
|||
mov r0, r2 /* syscall args */ |
|||
mov r1, r3 |
|||
ldm r12, { r2, r3, r4, r5, r6 } |
|||
|
|||
/* This next sequence of code works in conjunction with the |
|||
* rewind_if_safe_syscall_function(). If a signal is taken |
|||
* and the interrupted PC is anywhere between 'safe_syscall_start' |
|||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. |
|||
* The code sequence must therefore be able to cope with this, and |
|||
* the syscall instruction must be the final one in the sequence. |
|||
*/ |
|||
safe_syscall_start: |
|||
/* if signal_pending is non-zero, don't do the call */ |
|||
ldr r12, [r8] /* signal_pending */ |
|||
tst r12, r12 |
|||
bne 1f |
|||
swi 0 |
|||
safe_syscall_end: |
|||
/* code path for having successfully executed the syscall */ |
|||
pop { r4, r5, r6, r7, r8, pc } |
|||
|
|||
1: |
|||
/* code path when we didn't execute the syscall */ |
|||
ldr r0, =-TARGET_ERESTARTSYS |
|||
pop { r4, r5, r6, r7, r8, pc } |
|||
.fnend |
|||
.cfi_endproc |
|||
|
|||
.size safe_syscall_base, .-safe_syscall_base |
|||
@ -1,18 +0,0 @@ |
|||
/*
|
|||
* hostdep.h : things which are dependent on the host architecture |
|||
* |
|||
* * Written by Peter Maydell <peter.maydell@linaro.org> |
|||
* |
|||
* Copyright (C) 2016 Linaro Limited |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
#ifndef I386_HOSTDEP_H |
|||
#define I386_HOSTDEP_H |
|||
|
|||
/* We have a safe-syscall.inc.S */ |
|||
#define HAVE_SAFE_SYSCALL |
|||
|
|||
#endif |
|||
@ -1,100 +0,0 @@ |
|||
/* |
|||
* safe-syscall.inc.S : host-specific assembly fragment |
|||
* to handle signals occurring at the same time as system calls. |
|||
* This is intended to be included by linux-user/safe-syscall.S |
|||
* |
|||
* Written by Richard Henderson <rth@twiddle.net> |
|||
* Copyright (C) 2016 Red Hat, Inc. |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
.global safe_syscall_base |
|||
.global safe_syscall_start |
|||
.global safe_syscall_end |
|||
.type safe_syscall_base, @function |
|||
|
|||
/* This is the entry point for making a system call. The calling |
|||
* convention here is that of a C varargs function with the |
|||
* first argument an 'int *' to the signal_pending flag, the |
|||
* second one the system call number (as a 'long'), and all further |
|||
* arguments being syscall arguments (also 'long'). |
|||
* We return a long which is the syscall's return value, which |
|||
* may be negative-errno on failure. Conversion to the |
|||
* -1-and-errno-set convention is done by the calling wrapper. |
|||
*/ |
|||
safe_syscall_base: |
|||
.cfi_startproc |
|||
push %ebp |
|||
.cfi_adjust_cfa_offset 4 |
|||
.cfi_rel_offset ebp, 0 |
|||
push %esi |
|||
.cfi_adjust_cfa_offset 4 |
|||
.cfi_rel_offset esi, 0 |
|||
push %edi |
|||
.cfi_adjust_cfa_offset 4 |
|||
.cfi_rel_offset edi, 0 |
|||
push %ebx |
|||
.cfi_adjust_cfa_offset 4 |
|||
.cfi_rel_offset ebx, 0 |
|||
|
|||
/* The syscall calling convention isn't the same as the C one: |
|||
* we enter with 0(%esp) == return address |
|||
* 4(%esp) == *signal_pending |
|||
* 8(%esp) == syscall number |
|||
* 12(%esp) ... 32(%esp) == syscall arguments |
|||
* and return the result in eax |
|||
* and the syscall instruction needs |
|||
* eax == syscall number |
|||
* ebx, ecx, edx, esi, edi, ebp == syscall arguments |
|||
* and returns the result in eax |
|||
* Shuffle everything around appropriately. |
|||
* Note the 16 bytes that we pushed to save registers. |
|||
*/ |
|||
mov 12+16(%esp), %ebx /* the syscall arguments */ |
|||
mov 16+16(%esp), %ecx |
|||
mov 20+16(%esp), %edx |
|||
mov 24+16(%esp), %esi |
|||
mov 28+16(%esp), %edi |
|||
mov 32+16(%esp), %ebp |
|||
|
|||
/* This next sequence of code works in conjunction with the |
|||
* rewind_if_safe_syscall_function(). If a signal is taken |
|||
* and the interrupted PC is anywhere between 'safe_syscall_start' |
|||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. |
|||
* The code sequence must therefore be able to cope with this, and |
|||
* the syscall instruction must be the final one in the sequence. |
|||
*/ |
|||
safe_syscall_start: |
|||
/* if signal_pending is non-zero, don't do the call */ |
|||
mov 4+16(%esp), %eax /* signal_pending */ |
|||
cmpl $0, (%eax) |
|||
jnz 1f |
|||
mov 8+16(%esp), %eax /* syscall number */ |
|||
int $0x80 |
|||
safe_syscall_end: |
|||
/* code path for having successfully executed the syscall */ |
|||
pop %ebx |
|||
.cfi_remember_state |
|||
.cfi_adjust_cfa_offset -4 |
|||
.cfi_restore ebx |
|||
pop %edi |
|||
.cfi_adjust_cfa_offset -4 |
|||
.cfi_restore edi |
|||
pop %esi |
|||
.cfi_adjust_cfa_offset -4 |
|||
.cfi_restore esi |
|||
pop %ebp |
|||
.cfi_adjust_cfa_offset -4 |
|||
.cfi_restore ebp |
|||
ret |
|||
|
|||
1: |
|||
/* code path when we didn't execute the syscall */ |
|||
.cfi_restore_state |
|||
mov $-TARGET_ERESTARTSYS, %eax |
|||
jmp safe_syscall_end |
|||
.cfi_endproc |
|||
|
|||
.size safe_syscall_base, .-safe_syscall_base |
|||
@ -1,15 +0,0 @@ |
|||
/*
|
|||
* hostdep.h : things which are dependent on the host architecture |
|||
* |
|||
* * Written by Peter Maydell <peter.maydell@linaro.org> |
|||
* |
|||
* Copyright (C) 2016 Linaro Limited |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
#ifndef IA64_HOSTDEP_H |
|||
#define IA64_HOSTDEP_H |
|||
|
|||
#endif |
|||
@ -1,15 +0,0 @@ |
|||
/*
|
|||
* hostdep.h : things which are dependent on the host architecture |
|||
* |
|||
* * Written by Peter Maydell <peter.maydell@linaro.org> |
|||
* |
|||
* Copyright (C) 2016 Linaro Limited |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
#ifndef MIPS_HOSTDEP_H |
|||
#define MIPS_HOSTDEP_H |
|||
|
|||
#endif |
|||
@ -1,15 +0,0 @@ |
|||
/*
|
|||
* hostdep.h : things which are dependent on the host architecture |
|||
* |
|||
* * Written by Peter Maydell <peter.maydell@linaro.org> |
|||
* |
|||
* Copyright (C) 2016 Linaro Limited |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
#ifndef PPC_HOSTDEP_H |
|||
#define PPC_HOSTDEP_H |
|||
|
|||
#endif |
|||
@ -1,18 +0,0 @@ |
|||
/*
|
|||
* hostdep.h : things which are dependent on the host architecture |
|||
* |
|||
* * Written by Peter Maydell <peter.maydell@linaro.org> |
|||
* |
|||
* Copyright (C) 2016 Linaro Limited |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
#ifndef PPC64_HOSTDEP_H |
|||
#define PPC64_HOSTDEP_H |
|||
|
|||
/* We have a safe-syscall.inc.S */ |
|||
#define HAVE_SAFE_SYSCALL |
|||
|
|||
#endif |
|||
@ -1,96 +0,0 @@ |
|||
/* |
|||
* safe-syscall.inc.S : host-specific assembly fragment |
|||
* to handle signals occurring at the same time as system calls. |
|||
* This is intended to be included by linux-user/safe-syscall.S |
|||
* |
|||
* Written by Richard Henderson <rth@twiddle.net> |
|||
* Copyright (C) 2016 Red Hat, Inc. |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
.global safe_syscall_base |
|||
.global safe_syscall_start |
|||
.global safe_syscall_end |
|||
.type safe_syscall_base, @function |
|||
|
|||
.text |
|||
|
|||
/* This is the entry point for making a system call. The calling |
|||
* convention here is that of a C varargs function with the |
|||
* first argument an 'int *' to the signal_pending flag, the |
|||
* second one the system call number (as a 'long'), and all further |
|||
* arguments being syscall arguments (also 'long'). |
|||
* We return a long which is the syscall's return value, which |
|||
* may be negative-errno on failure. Conversion to the |
|||
* -1-and-errno-set convention is done by the calling wrapper. |
|||
*/ |
|||
#if _CALL_ELF == 2 |
|||
safe_syscall_base: |
|||
.cfi_startproc |
|||
.localentry safe_syscall_base,0 |
|||
#else |
|||
.section ".opd","aw" |
|||
.align 3 |
|||
safe_syscall_base: |
|||
.quad .L.safe_syscall_base,.TOC.@tocbase,0 |
|||
.previous |
|||
.L.safe_syscall_base: |
|||
.cfi_startproc |
|||
#endif |
|||
/* We enter with r3 == *signal_pending |
|||
* r4 == syscall number |
|||
* r5 ... r10 == syscall arguments |
|||
* and return the result in r3 |
|||
* and the syscall instruction needs |
|||
* r0 == syscall number |
|||
* r3 ... r8 == syscall arguments |
|||
* and returns the result in r3 |
|||
* Shuffle everything around appropriately. |
|||
*/ |
|||
std 14, 16(1) /* Preserve r14 in SP+16 */ |
|||
.cfi_offset 14, 16 |
|||
mr 14, 3 /* signal_pending */ |
|||
mr 0, 4 /* syscall number */ |
|||
mr 3, 5 /* syscall arguments */ |
|||
mr 4, 6 |
|||
mr 5, 7 |
|||
mr 6, 8 |
|||
mr 7, 9 |
|||
mr 8, 10 |
|||
|
|||
/* This next sequence of code works in conjunction with the |
|||
* rewind_if_safe_syscall_function(). If a signal is taken |
|||
* and the interrupted PC is anywhere between 'safe_syscall_start' |
|||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. |
|||
* The code sequence must therefore be able to cope with this, and |
|||
* the syscall instruction must be the final one in the sequence. |
|||
*/ |
|||
safe_syscall_start: |
|||
/* if signal_pending is non-zero, don't do the call */ |
|||
lwz 12, 0(14) |
|||
cmpwi 0, 12, 0 |
|||
bne- 0f |
|||
sc |
|||
safe_syscall_end: |
|||
/* code path when we did execute the syscall */ |
|||
ld 14, 16(1) /* restore r14 to its original value */ |
|||
bnslr+ |
|||
|
|||
/* syscall failed; return negative errno */ |
|||
neg 3, 3 |
|||
blr |
|||
|
|||
/* code path when we didn't execute the syscall */ |
|||
0: addi 3, 0, -TARGET_ERESTARTSYS |
|||
ld 14, 16(1) /* restore r14 to its original value */ |
|||
blr |
|||
.cfi_endproc |
|||
|
|||
#if _CALL_ELF == 2 |
|||
.size safe_syscall_base, .-safe_syscall_base |
|||
#else |
|||
.size safe_syscall_base, .-.L.safe_syscall_base |
|||
.size .L.safe_syscall_base, .-.L.safe_syscall_base |
|||
#endif |
|||
@ -1,14 +0,0 @@ |
|||
/*
|
|||
* hostdep.h : things which are dependent on the host architecture |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
#ifndef RISCV_HOSTDEP_H |
|||
#define RISCV_HOSTDEP_H |
|||
|
|||
/* We have a safe-syscall.inc.S */ |
|||
#define HAVE_SAFE_SYSCALL |
|||
|
|||
#endif |
|||
@ -1,77 +0,0 @@ |
|||
/* |
|||
* safe-syscall.inc.S : host-specific assembly fragment |
|||
* to handle signals occurring at the same time as system calls. |
|||
* This is intended to be included by linux-user/safe-syscall.S |
|||
* |
|||
* Written by Richard Henderson <rth@twiddle.net> |
|||
* Copyright (C) 2018 Linaro, Inc. |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
.global safe_syscall_base |
|||
.global safe_syscall_start |
|||
.global safe_syscall_end |
|||
.type safe_syscall_base, @function |
|||
.type safe_syscall_start, @function |
|||
.type safe_syscall_end, @function |
|||
|
|||
/* |
|||
* This is the entry point for making a system call. The calling |
|||
* convention here is that of a C varargs function with the |
|||
* first argument an 'int *' to the signal_pending flag, the |
|||
* second one the system call number (as a 'long'), and all further |
|||
* arguments being syscall arguments (also 'long'). |
|||
* We return a long which is the syscall's return value, which |
|||
* may be negative-errno on failure. Conversion to the |
|||
* -1-and-errno-set convention is done by the calling wrapper. |
|||
*/ |
|||
safe_syscall_base: |
|||
.cfi_startproc |
|||
/* |
|||
* The syscall calling convention is nearly the same as C: |
|||
* we enter with a0 == *signal_pending |
|||
* a1 == syscall number |
|||
* a2 ... a7 == syscall arguments |
|||
* and return the result in a0 |
|||
* and the syscall instruction needs |
|||
* a7 == syscall number |
|||
* a0 ... a5 == syscall arguments |
|||
* and returns the result in a0 |
|||
* Shuffle everything around appropriately. |
|||
*/ |
|||
mv t0, a0 /* signal_pending pointer */ |
|||
mv t1, a1 /* syscall number */ |
|||
mv a0, a2 /* syscall arguments */ |
|||
mv a1, a3 |
|||
mv a2, a4 |
|||
mv a3, a5 |
|||
mv a4, a6 |
|||
mv a5, a7 |
|||
mv a7, t1 |
|||
|
|||
/* |
|||
* This next sequence of code works in conjunction with the |
|||
* rewind_if_safe_syscall_function(). If a signal is taken |
|||
* and the interrupted PC is anywhere between 'safe_syscall_start' |
|||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. |
|||
* The code sequence must therefore be able to cope with this, and |
|||
* the syscall instruction must be the final one in the sequence. |
|||
*/ |
|||
safe_syscall_start: |
|||
/* If signal_pending is non-zero, don't do the call */ |
|||
lw t1, 0(t0) |
|||
bnez t1, 0f |
|||
scall |
|||
safe_syscall_end: |
|||
/* code path for having successfully executed the syscall */ |
|||
ret |
|||
|
|||
0: |
|||
/* code path when we didn't execute the syscall */ |
|||
li a0, -TARGET_ERESTARTSYS |
|||
ret |
|||
.cfi_endproc |
|||
|
|||
.size safe_syscall_base, .-safe_syscall_base |
|||
@ -1,15 +0,0 @@ |
|||
/*
|
|||
* hostdep.h : things which are dependent on the host architecture |
|||
* |
|||
* * Written by Peter Maydell <peter.maydell@linaro.org> |
|||
* |
|||
* Copyright (C) 2016 Linaro Limited |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
#ifndef S390_HOSTDEP_H |
|||
#define S390_HOSTDEP_H |
|||
|
|||
#endif |
|||
@ -1,18 +0,0 @@ |
|||
/*
|
|||
* hostdep.h : things which are dependent on the host architecture |
|||
* |
|||
* * Written by Peter Maydell <peter.maydell@linaro.org> |
|||
* |
|||
* Copyright (C) 2016 Linaro Limited |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
#ifndef S390X_HOSTDEP_H |
|||
#define S390X_HOSTDEP_H |
|||
|
|||
/* We have a safe-syscall.inc.S */ |
|||
#define HAVE_SAFE_SYSCALL |
|||
|
|||
#endif |
|||
@ -1,90 +0,0 @@ |
|||
/* |
|||
* safe-syscall.inc.S : host-specific assembly fragment |
|||
* to handle signals occurring at the same time as system calls. |
|||
* This is intended to be included by linux-user/safe-syscall.S |
|||
* |
|||
* Written by Richard Henderson <rth@twiddle.net> |
|||
* Copyright (C) 2016 Red Hat, Inc. |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
.global safe_syscall_base |
|||
.global safe_syscall_start |
|||
.global safe_syscall_end |
|||
.type safe_syscall_base, @function |
|||
|
|||
/* This is the entry point for making a system call. The calling |
|||
* convention here is that of a C varargs function with the |
|||
* first argument an 'int *' to the signal_pending flag, the |
|||
* second one the system call number (as a 'long'), and all further |
|||
* arguments being syscall arguments (also 'long'). |
|||
* We return a long which is the syscall's return value, which |
|||
* may be negative-errno on failure. Conversion to the |
|||
* -1-and-errno-set convention is done by the calling wrapper. |
|||
*/ |
|||
safe_syscall_base: |
|||
.cfi_startproc |
|||
stmg %r6,%r15,48(%r15) /* save all call-saved registers */ |
|||
.cfi_offset %r15,-40 |
|||
.cfi_offset %r14,-48 |
|||
.cfi_offset %r13,-56 |
|||
.cfi_offset %r12,-64 |
|||
.cfi_offset %r11,-72 |
|||
.cfi_offset %r10,-80 |
|||
.cfi_offset %r9,-88 |
|||
.cfi_offset %r8,-96 |
|||
.cfi_offset %r7,-104 |
|||
.cfi_offset %r6,-112 |
|||
lgr %r1,%r15 |
|||
lg %r0,8(%r15) /* load eos */ |
|||
aghi %r15,-160 |
|||
.cfi_adjust_cfa_offset 160 |
|||
stg %r1,0(%r15) /* store back chain */ |
|||
stg %r0,8(%r15) /* store eos */ |
|||
|
|||
/* The syscall calling convention isn't the same as the |
|||
* C one: |
|||
* we enter with r2 == *signal_pending |
|||
* r3 == syscall number |
|||
* r4, r5, r6, (stack) == syscall arguments |
|||
* and return the result in r2 |
|||
* and the syscall instruction needs |
|||
* r1 == syscall number |
|||
* r2 ... r7 == syscall arguments |
|||
* and returns the result in r2 |
|||
* Shuffle everything around appropriately. |
|||
*/ |
|||
lgr %r8,%r2 /* signal_pending pointer */ |
|||
lgr %r1,%r3 /* syscall number */ |
|||
lgr %r2,%r4 /* syscall args */ |
|||
lgr %r3,%r5 |
|||
lgr %r4,%r6 |
|||
lmg %r5,%r7,320(%r15) |
|||
|
|||
/* This next sequence of code works in conjunction with the |
|||
* rewind_if_safe_syscall_function(). If a signal is taken |
|||
* and the interrupted PC is anywhere between 'safe_syscall_start' |
|||
* and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. |
|||
* The code sequence must therefore be able to cope with this, and |
|||
* the syscall instruction must be the final one in the sequence. |
|||
*/ |
|||
safe_syscall_start: |
|||
/* if signal_pending is non-zero, don't do the call */ |
|||
icm %r0,15,0(%r8) |
|||
jne 2f |
|||
svc 0 |
|||
safe_syscall_end: |
|||
|
|||
1: lg %r15,0(%r15) /* load back chain */ |
|||
.cfi_remember_state |
|||
.cfi_adjust_cfa_offset -160 |
|||
lmg %r6,%r15,48(%r15) /* load saved registers */ |
|||
br %r14 |
|||
.cfi_restore_state |
|||
2: lghi %r2, -TARGET_ERESTARTSYS |
|||
j 1b |
|||
.cfi_endproc |
|||
|
|||
.size safe_syscall_base, .-safe_syscall_base |
|||
@ -1,15 +0,0 @@ |
|||
/*
|
|||
* hostdep.h : things which are dependent on the host architecture |
|||
* |
|||
* * Written by Peter Maydell <peter.maydell@linaro.org> |
|||
* |
|||
* Copyright (C) 2016 Linaro Limited |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
#ifndef SPARC_HOSTDEP_H |
|||
#define SPARC_HOSTDEP_H |
|||
|
|||
#endif |
|||
@ -1,15 +0,0 @@ |
|||
/*
|
|||
* hostdep.h : things which are dependent on the host architecture |
|||
* |
|||
* * Written by Peter Maydell <peter.maydell@linaro.org> |
|||
* |
|||
* Copyright (C) 2016 Linaro Limited |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
#ifndef SPARC64_HOSTDEP_H |
|||
#define SPARC64_HOSTDEP_H |
|||
|
|||
#endif |
|||
@ -1,15 +0,0 @@ |
|||
/*
|
|||
* hostdep.h : things which are dependent on the host architecture |
|||
* |
|||
* * Written by Peter Maydell <peter.maydell@linaro.org> |
|||
* |
|||
* Copyright (C) 2016 Linaro Limited |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
#ifndef X32_HOSTDEP_H |
|||
#define X32_HOSTDEP_H |
|||
|
|||
#endif |
|||
@ -1,18 +0,0 @@ |
|||
/*
|
|||
* hostdep.h : things which are dependent on the host architecture |
|||
* |
|||
* * Written by Peter Maydell <peter.maydell@linaro.org> |
|||
* |
|||
* Copyright (C) 2016 Linaro Limited |
|||
* |
|||
* This work is licensed under the terms of the GNU GPL, version 2 or later. |
|||
* See the COPYING file in the top-level directory. |
|||
*/ |
|||
|
|||
#ifndef X86_64_HOSTDEP_H |
|||
#define X86_64_HOSTDEP_H |
|||
|
|||
/* We have a safe-syscall.inc.S */ |
|||
#define HAVE_SAFE_SYSCALL |
|||
|
|||
#endif |
|||
@ -0,0 +1,32 @@ |
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */ |
|||
/*
|
|||
* QEMU internal errno values for implementing user-only POSIX. |
|||
* |
|||
* Copyright (c) 2003 Fabrice Bellard |
|||
* Copyright (c) 2021 Linaro, Ltd. |
|||
*/ |
|||
|
|||
#ifndef SPECIAL_ERRNO_H |
|||
#define SPECIAL_ERRNO_H |
|||
|
|||
/*
|
|||
* All of these are QEMU internal, not visible to the guest. |
|||
* They should be chosen so as to not overlap with any host |
|||
* or guest errno. |
|||
*/ |
|||
|
|||
/*
|
|||
* This is returned when a system call should be restarted, to tell the |
|||
* main loop that it should wind the guest PC backwards so it will |
|||
* re-execute the syscall after handling any pending signals. |
|||
*/ |
|||
#define QEMU_ERESTARTSYS 512 |
|||
|
|||
/*
|
|||
* This is returned after a successful sigreturn syscall, to indicate |
|||
* that it has correctly set the guest registers and so the main loop |
|||
* should not touch them. |
|||
*/ |
|||
#define QEMU_ESIGRETURN 513 |
|||
|
|||
#endif /* SPECIAL_ERRNO_H */ |
|||
Loading…
Reference in new issue