linux-user: Move syscall error detection into safe_syscall_base
The current api from safe_syscall_base() is to return -errno, which is the interface provided by *some* linux kernel abis. The wrapper macro, safe_syscall(), detects error, stores into errno, and returns -1, to match the api of the system syscall(). For those kernel abis that do not return -errno natively, this leads to double syscall error detection. E.g. Linux ppc64, which sets the SO flag for error. Simplify the usage from C by moving the error detection into assembly, and usage from assembly by providing a C helper with which to set errno. Reviewed-by: Warner Losh <imp@bsdimp.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
b9d2af3c62
commit
a3310c0397
@ -22,15 +22,12 @@
|
|||||||
* first argument an 'int *' to the signal_pending flag, the
|
* first argument an 'int *' to the signal_pending flag, the
|
||||||
* second one the system call number (as a 'long'), and all further
|
* second one the system call number (as a 'long'), and all further
|
||||||
* arguments being syscall arguments (also 'long').
|
* 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:
|
safe_syscall_base:
|
||||||
.cfi_startproc
|
.cfi_startproc
|
||||||
/* The syscall calling convention isn't the same as the
|
/* The syscall calling convention isn't the same as the
|
||||||
* C one:
|
* C one:
|
||||||
* we enter with x0 == *signal_pending
|
* we enter with x0 == &signal_pending
|
||||||
* x1 == syscall number
|
* x1 == syscall number
|
||||||
* x2 ... x7, (stack) == syscall arguments
|
* x2 ... x7, (stack) == syscall arguments
|
||||||
* and return the result in x0
|
* and return the result in x0
|
||||||
@ -60,16 +57,21 @@ safe_syscall_base:
|
|||||||
safe_syscall_start:
|
safe_syscall_start:
|
||||||
/* if signal_pending is non-zero, don't do the call */
|
/* if signal_pending is non-zero, don't do the call */
|
||||||
ldr w10, [x9]
|
ldr w10, [x9]
|
||||||
cbnz w10, 0f
|
cbnz w10, 2f
|
||||||
svc 0x0
|
svc 0x0
|
||||||
safe_syscall_end:
|
safe_syscall_end:
|
||||||
/* code path for having successfully executed the syscall */
|
/* code path for having successfully executed the syscall */
|
||||||
|
cmp x0, #-4096
|
||||||
|
b.hi 0f
|
||||||
ret
|
ret
|
||||||
|
|
||||||
0:
|
/* code path setting errno */
|
||||||
|
0: neg w0, w0
|
||||||
|
b safe_syscall_set_errno_tail
|
||||||
|
|
||||||
/* code path when we didn't execute the syscall */
|
/* code path when we didn't execute the syscall */
|
||||||
mov x0, #-TARGET_ERESTARTSYS
|
2: mov w0, #TARGET_ERESTARTSYS
|
||||||
ret
|
b safe_syscall_set_errno_tail
|
||||||
.cfi_endproc
|
|
||||||
|
|
||||||
|
.cfi_endproc
|
||||||
.size safe_syscall_base, .-safe_syscall_base
|
.size safe_syscall_base, .-safe_syscall_base
|
||||||
|
@ -27,9 +27,6 @@
|
|||||||
* first argument an 'int *' to the signal_pending flag, the
|
* first argument an 'int *' to the signal_pending flag, the
|
||||||
* second one the system call number (as a 'long'), and all further
|
* second one the system call number (as a 'long'), and all further
|
||||||
* arguments being syscall arguments (also 'long').
|
* 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:
|
safe_syscall_base:
|
||||||
.fnstart
|
.fnstart
|
||||||
@ -46,7 +43,7 @@ safe_syscall_base:
|
|||||||
.cfi_rel_offset lr, 20
|
.cfi_rel_offset lr, 20
|
||||||
|
|
||||||
/* The syscall calling convention isn't the same as the C one:
|
/* The syscall calling convention isn't the same as the C one:
|
||||||
* we enter with r0 == *signal_pending
|
* we enter with r0 == &signal_pending
|
||||||
* r1 == syscall number
|
* r1 == syscall number
|
||||||
* r2, r3, [sp+0] ... [sp+12] == syscall arguments
|
* r2, r3, [sp+0] ... [sp+12] == syscall arguments
|
||||||
* and return the result in r0
|
* and return the result in r0
|
||||||
@ -74,17 +71,29 @@ safe_syscall_start:
|
|||||||
/* if signal_pending is non-zero, don't do the call */
|
/* if signal_pending is non-zero, don't do the call */
|
||||||
ldr r12, [r8] /* signal_pending */
|
ldr r12, [r8] /* signal_pending */
|
||||||
tst r12, r12
|
tst r12, r12
|
||||||
bne 1f
|
bne 2f
|
||||||
swi 0
|
swi 0
|
||||||
safe_syscall_end:
|
safe_syscall_end:
|
||||||
/* code path for having successfully executed the syscall */
|
/* code path for having successfully executed the syscall */
|
||||||
|
cmp r0, #-4096
|
||||||
|
neghi r0, r0
|
||||||
|
bhi 1f
|
||||||
pop { r4, r5, r6, r7, r8, pc }
|
pop { r4, r5, r6, r7, r8, pc }
|
||||||
|
|
||||||
1:
|
|
||||||
/* code path when we didn't execute the syscall */
|
/* code path when we didn't execute the syscall */
|
||||||
ldr r0, =-TARGET_ERESTARTSYS
|
2: mov r0, #TARGET_ERESTARTSYS
|
||||||
pop { r4, r5, r6, r7, r8, pc }
|
|
||||||
|
/* 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
|
.fnend
|
||||||
.cfi_endproc
|
.cfi_endproc
|
||||||
|
|
||||||
.size safe_syscall_base, .-safe_syscall_base
|
.size safe_syscall_base, .-safe_syscall_base
|
||||||
|
@ -20,9 +20,6 @@
|
|||||||
* first argument an 'int *' to the signal_pending flag, the
|
* first argument an 'int *' to the signal_pending flag, the
|
||||||
* second one the system call number (as a 'long'), and all further
|
* second one the system call number (as a 'long'), and all further
|
||||||
* arguments being syscall arguments (also 'long').
|
* 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:
|
safe_syscall_base:
|
||||||
.cfi_startproc
|
.cfi_startproc
|
||||||
@ -41,7 +38,7 @@ safe_syscall_base:
|
|||||||
|
|
||||||
/* The syscall calling convention isn't the same as the C one:
|
/* The syscall calling convention isn't the same as the C one:
|
||||||
* we enter with 0(%esp) == return address
|
* we enter with 0(%esp) == return address
|
||||||
* 4(%esp) == *signal_pending
|
* 4(%esp) == &signal_pending
|
||||||
* 8(%esp) == syscall number
|
* 8(%esp) == syscall number
|
||||||
* 12(%esp) ... 32(%esp) == syscall arguments
|
* 12(%esp) ... 32(%esp) == syscall arguments
|
||||||
* and return the result in eax
|
* and return the result in eax
|
||||||
@ -70,11 +67,13 @@ safe_syscall_start:
|
|||||||
/* if signal_pending is non-zero, don't do the call */
|
/* if signal_pending is non-zero, don't do the call */
|
||||||
mov 4+16(%esp), %eax /* signal_pending */
|
mov 4+16(%esp), %eax /* signal_pending */
|
||||||
cmpl $0, (%eax)
|
cmpl $0, (%eax)
|
||||||
jnz 1f
|
jnz 2f
|
||||||
mov 8+16(%esp), %eax /* syscall number */
|
mov 8+16(%esp), %eax /* syscall number */
|
||||||
int $0x80
|
int $0x80
|
||||||
safe_syscall_end:
|
safe_syscall_end:
|
||||||
/* code path for having successfully executed the syscall */
|
/* code path for having successfully executed the syscall */
|
||||||
|
cmp $-4095, %eax
|
||||||
|
jae 0f
|
||||||
pop %ebx
|
pop %ebx
|
||||||
.cfi_remember_state
|
.cfi_remember_state
|
||||||
.cfi_adjust_cfa_offset -4
|
.cfi_adjust_cfa_offset -4
|
||||||
@ -89,12 +88,28 @@ safe_syscall_end:
|
|||||||
.cfi_adjust_cfa_offset -4
|
.cfi_adjust_cfa_offset -4
|
||||||
.cfi_restore ebp
|
.cfi_restore ebp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
1:
|
|
||||||
/* code path when we didn't execute the syscall */
|
|
||||||
.cfi_restore_state
|
.cfi_restore_state
|
||||||
mov $-TARGET_ERESTARTSYS, %eax
|
|
||||||
jmp safe_syscall_end
|
|
||||||
.cfi_endproc
|
|
||||||
|
|
||||||
|
0: neg %eax
|
||||||
|
jmp 1f
|
||||||
|
|
||||||
|
/* code path when we didn't execute the syscall */
|
||||||
|
2: mov $TARGET_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
|
.size safe_syscall_base, .-safe_syscall_base
|
||||||
|
@ -22,9 +22,6 @@
|
|||||||
* first argument an 'int *' to the signal_pending flag, the
|
* first argument an 'int *' to the signal_pending flag, the
|
||||||
* second one the system call number (as a 'long'), and all further
|
* second one the system call number (as a 'long'), and all further
|
||||||
* arguments being syscall arguments (also 'long').
|
* 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
|
#if _CALL_ELF == 2
|
||||||
safe_syscall_base:
|
safe_syscall_base:
|
||||||
@ -39,7 +36,7 @@ safe_syscall_base:
|
|||||||
.L.safe_syscall_base:
|
.L.safe_syscall_base:
|
||||||
.cfi_startproc
|
.cfi_startproc
|
||||||
#endif
|
#endif
|
||||||
/* We enter with r3 == *signal_pending
|
/* We enter with r3 == &signal_pending
|
||||||
* r4 == syscall number
|
* r4 == syscall number
|
||||||
* r5 ... r10 == syscall arguments
|
* r5 ... r10 == syscall arguments
|
||||||
* and return the result in r3
|
* and return the result in r3
|
||||||
@ -71,21 +68,22 @@ safe_syscall_start:
|
|||||||
/* if signal_pending is non-zero, don't do the call */
|
/* if signal_pending is non-zero, don't do the call */
|
||||||
lwz 12, 0(14)
|
lwz 12, 0(14)
|
||||||
cmpwi 0, 12, 0
|
cmpwi 0, 12, 0
|
||||||
bne- 0f
|
bne- 2f
|
||||||
sc
|
sc
|
||||||
safe_syscall_end:
|
safe_syscall_end:
|
||||||
/* code path when we did execute the syscall */
|
/* code path when we did execute the syscall */
|
||||||
ld 14, 16(1) /* restore r14 to its original value */
|
ld 14, 16(1) /* restore r14 */
|
||||||
bnslr+
|
bso- 1f
|
||||||
|
|
||||||
/* syscall failed; return negative errno */
|
|
||||||
neg 3, 3
|
|
||||||
blr
|
blr
|
||||||
|
|
||||||
/* code path when we didn't execute the syscall */
|
/* code path when we didn't execute the syscall */
|
||||||
0: addi 3, 0, -TARGET_ERESTARTSYS
|
2: ld 14, 16(1) /* restore r14 */
|
||||||
ld 14, 16(1) /* restore r14 to its original value */
|
addi 3, 0, TARGET_ERESTARTSYS
|
||||||
blr
|
|
||||||
|
/* code path setting errno */
|
||||||
|
1: b safe_syscall_set_errno_tail
|
||||||
|
nop /* per abi, for the linker to modify */
|
||||||
|
|
||||||
.cfi_endproc
|
.cfi_endproc
|
||||||
|
|
||||||
#if _CALL_ELF == 2
|
#if _CALL_ELF == 2
|
||||||
|
@ -23,15 +23,12 @@
|
|||||||
* first argument an 'int *' to the signal_pending flag, the
|
* first argument an 'int *' to the signal_pending flag, the
|
||||||
* second one the system call number (as a 'long'), and all further
|
* second one the system call number (as a 'long'), and all further
|
||||||
* arguments being syscall arguments (also 'long').
|
* 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:
|
safe_syscall_base:
|
||||||
.cfi_startproc
|
.cfi_startproc
|
||||||
/*
|
/*
|
||||||
* The syscall calling convention is nearly the same as C:
|
* The syscall calling convention is nearly the same as C:
|
||||||
* we enter with a0 == *signal_pending
|
* we enter with a0 == &signal_pending
|
||||||
* a1 == syscall number
|
* a1 == syscall number
|
||||||
* a2 ... a7 == syscall arguments
|
* a2 ... a7 == syscall arguments
|
||||||
* and return the result in a0
|
* and return the result in a0
|
||||||
@ -62,16 +59,21 @@ safe_syscall_base:
|
|||||||
safe_syscall_start:
|
safe_syscall_start:
|
||||||
/* If signal_pending is non-zero, don't do the call */
|
/* If signal_pending is non-zero, don't do the call */
|
||||||
lw t1, 0(t0)
|
lw t1, 0(t0)
|
||||||
bnez t1, 0f
|
bnez t1, 2f
|
||||||
scall
|
scall
|
||||||
safe_syscall_end:
|
safe_syscall_end:
|
||||||
/* code path for having successfully executed the syscall */
|
/* code path for having successfully executed the syscall */
|
||||||
|
li t2, -4096
|
||||||
|
bgtu a0, t2, 0f
|
||||||
ret
|
ret
|
||||||
|
|
||||||
0:
|
/* code path setting errno */
|
||||||
|
0: neg a0, a0
|
||||||
|
j safe_syscall_set_errno_tail
|
||||||
|
|
||||||
/* code path when we didn't execute the syscall */
|
/* code path when we didn't execute the syscall */
|
||||||
li a0, -TARGET_ERESTARTSYS
|
2: li a0, TARGET_ERESTARTSYS
|
||||||
ret
|
j safe_syscall_set_errno_tail
|
||||||
.cfi_endproc
|
|
||||||
|
|
||||||
|
.cfi_endproc
|
||||||
.size safe_syscall_base, .-safe_syscall_base
|
.size safe_syscall_base, .-safe_syscall_base
|
||||||
|
@ -20,9 +20,6 @@
|
|||||||
* first argument an 'int *' to the signal_pending flag, the
|
* first argument an 'int *' to the signal_pending flag, the
|
||||||
* second one the system call number (as a 'long'), and all further
|
* second one the system call number (as a 'long'), and all further
|
||||||
* arguments being syscall arguments (also 'long').
|
* 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:
|
safe_syscall_base:
|
||||||
.cfi_startproc
|
.cfi_startproc
|
||||||
@ -44,9 +41,9 @@ safe_syscall_base:
|
|||||||
stg %r1,0(%r15) /* store back chain */
|
stg %r1,0(%r15) /* store back chain */
|
||||||
stg %r0,8(%r15) /* store eos */
|
stg %r0,8(%r15) /* store eos */
|
||||||
|
|
||||||
/* The syscall calling convention isn't the same as the
|
/*
|
||||||
* C one:
|
* The syscall calling convention isn't the same as the C one:
|
||||||
* we enter with r2 == *signal_pending
|
* we enter with r2 == &signal_pending
|
||||||
* r3 == syscall number
|
* r3 == syscall number
|
||||||
* r4, r5, r6, (stack) == syscall arguments
|
* r4, r5, r6, (stack) == syscall arguments
|
||||||
* and return the result in r2
|
* and return the result in r2
|
||||||
@ -77,14 +74,25 @@ safe_syscall_start:
|
|||||||
svc 0
|
svc 0
|
||||||
safe_syscall_end:
|
safe_syscall_end:
|
||||||
|
|
||||||
1: lg %r15,0(%r15) /* load back chain */
|
/* code path for having successfully executed the syscall */
|
||||||
|
lg %r15,0(%r15) /* load back chain */
|
||||||
.cfi_remember_state
|
.cfi_remember_state
|
||||||
.cfi_adjust_cfa_offset -160
|
.cfi_adjust_cfa_offset -160
|
||||||
lmg %r6,%r15,48(%r15) /* load saved registers */
|
lmg %r6,%r15,48(%r15) /* load saved registers */
|
||||||
br %r14
|
|
||||||
.cfi_restore_state
|
|
||||||
2: lghi %r2, -TARGET_ERESTARTSYS
|
|
||||||
j 1b
|
|
||||||
.cfi_endproc
|
|
||||||
|
|
||||||
|
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, TARGET_ERESTARTSYS
|
||||||
|
jg safe_syscall_set_errno_tail
|
||||||
|
|
||||||
|
.cfi_endproc
|
||||||
.size safe_syscall_base, .-safe_syscall_base
|
.size safe_syscall_base, .-safe_syscall_base
|
||||||
|
@ -19,9 +19,6 @@
|
|||||||
* first argument an 'int *' to the signal_pending flag, the
|
* first argument an 'int *' to the signal_pending flag, the
|
||||||
* second one the system call number (as a 'long'), and all further
|
* second one the system call number (as a 'long'), and all further
|
||||||
* arguments being syscall arguments (also 'long').
|
* 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:
|
safe_syscall_base:
|
||||||
.cfi_startproc
|
.cfi_startproc
|
||||||
@ -35,9 +32,9 @@ safe_syscall_base:
|
|||||||
.cfi_adjust_cfa_offset 8
|
.cfi_adjust_cfa_offset 8
|
||||||
.cfi_rel_offset rbp, 0
|
.cfi_rel_offset rbp, 0
|
||||||
|
|
||||||
/* The syscall calling convention isn't the same as the
|
/*
|
||||||
* C one:
|
* The syscall calling convention isn't the same as the C one:
|
||||||
* we enter with rdi == *signal_pending
|
* we enter with rdi == &signal_pending
|
||||||
* rsi == syscall number
|
* rsi == syscall number
|
||||||
* rdx, rcx, r8, r9, (stack), (stack) == syscall arguments
|
* rdx, rcx, r8, r9, (stack), (stack) == syscall arguments
|
||||||
* and return the result in rax
|
* and return the result in rax
|
||||||
@ -68,24 +65,30 @@ safe_syscall_base:
|
|||||||
safe_syscall_start:
|
safe_syscall_start:
|
||||||
/* if signal_pending is non-zero, don't do the call */
|
/* if signal_pending is non-zero, don't do the call */
|
||||||
cmpl $0, (%rbp)
|
cmpl $0, (%rbp)
|
||||||
jnz 1f
|
jnz 2f
|
||||||
syscall
|
syscall
|
||||||
safe_syscall_end:
|
safe_syscall_end:
|
||||||
/* code path for having successfully executed the syscall */
|
/* code path for having successfully executed the syscall */
|
||||||
|
cmp $-4095, %rax
|
||||||
|
jae 0f
|
||||||
pop %rbp
|
pop %rbp
|
||||||
.cfi_remember_state
|
.cfi_remember_state
|
||||||
.cfi_def_cfa_offset 8
|
.cfi_def_cfa_offset 8
|
||||||
.cfi_restore rbp
|
.cfi_restore rbp
|
||||||
ret
|
ret
|
||||||
|
|
||||||
1:
|
|
||||||
/* code path when we didn't execute the syscall */
|
|
||||||
.cfi_restore_state
|
.cfi_restore_state
|
||||||
mov $-TARGET_ERESTARTSYS, %rax
|
|
||||||
pop %rbp
|
0: neg %eax
|
||||||
|
jmp 1f
|
||||||
|
|
||||||
|
/* code path when we didn't execute the syscall */
|
||||||
|
2: mov $TARGET_ERESTARTSYS, %eax
|
||||||
|
|
||||||
|
/* code path setting errno */
|
||||||
|
1: pop %rbp
|
||||||
.cfi_def_cfa_offset 8
|
.cfi_def_cfa_offset 8
|
||||||
.cfi_restore rbp
|
.cfi_restore rbp
|
||||||
ret
|
jmp safe_syscall_set_errno_tail
|
||||||
.cfi_endproc
|
.cfi_endproc
|
||||||
|
|
||||||
.size safe_syscall_base, .-safe_syscall_base
|
.size safe_syscall_base, .-safe_syscall_base
|
||||||
|
@ -10,6 +10,7 @@ linux_user_ss.add(files(
|
|||||||
'main.c',
|
'main.c',
|
||||||
'mmap.c',
|
'mmap.c',
|
||||||
'safe-syscall.S',
|
'safe-syscall.S',
|
||||||
|
'safe-syscall-error.c',
|
||||||
'signal.c',
|
'signal.c',
|
||||||
'strace.c',
|
'strace.c',
|
||||||
'syscall.c',
|
'syscall.c',
|
||||||
|
28
linux-user/safe-syscall-error.c
Normal file
28
linux-user/safe-syscall-error.c
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* 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 "hostdep.h"
|
||||||
|
#include "safe-syscall.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_SAFE_SYSCALL
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
#endif
|
@ -127,21 +127,15 @@
|
|||||||
#ifdef HAVE_SAFE_SYSCALL
|
#ifdef HAVE_SAFE_SYSCALL
|
||||||
/* The core part of this function is implemented in assembly */
|
/* The core part of this function is implemented in assembly */
|
||||||
extern long safe_syscall_base(int *pending, long number, ...);
|
extern long safe_syscall_base(int *pending, long number, ...);
|
||||||
|
extern long safe_syscall_set_errno_tail(int value);
|
||||||
|
|
||||||
/* These are defined by the safe-syscall.inc.S file */
|
/* These are defined by the safe-syscall.inc.S file */
|
||||||
extern char safe_syscall_start[];
|
extern char safe_syscall_start[];
|
||||||
extern char safe_syscall_end[];
|
extern char safe_syscall_end[];
|
||||||
|
|
||||||
#define safe_syscall(...) \
|
#define safe_syscall(...) \
|
||||||
({ \
|
safe_syscall_base(&((TaskState *)thread_cpu->opaque)->signal_pending, \
|
||||||
long ret_; \
|
__VA_ARGS__)
|
||||||
int *psp_ = &((TaskState *)thread_cpu->opaque)->signal_pending; \
|
|
||||||
ret_ = safe_syscall_base(psp_, __VA_ARGS__); \
|
|
||||||
if (is_error(ret_)) { \
|
|
||||||
errno = -ret_; \
|
|
||||||
ret_ = -1; \
|
|
||||||
} \
|
|
||||||
ret_; \
|
|
||||||
})
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user