From 9d52656a5ad2d25c578cb6c7ae52a7a03f36dc34 Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Tue, 11 Nov 2003 09:25:19 +0000 Subject: [PATCH] Fix a nasty bug that got exposed when the sendsig() and sigreturn() functions switched to using {g|s}et_mcontext(). The problem is that sigreturn(), being a syscall, can be given an async. context (i.e. one corresponding to an interrupt or trap). When this happens, we try to return to user mode via epc_syscall_return with a trapframe that can only be used to return to user mode via exception_restore. To fix this, we check the frame's flags immediately prior to epc_syscall_return and branch to exception_restore for non-syscall frames. Modify the assertion in set_mcontext() to check that if there's a mismatch, it's because of sigreturn(). --- sys/ia64/ia64/machdep.c | 11 ++++++++++- sys/ia64/ia64/syscall.S | 21 +++++++++++++++++---- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index b52abf9f596e..9f6ef66a51d0 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -1114,7 +1115,15 @@ set_mcontext(struct thread *td, const mcontext_t *mc) /* We don't have any dirty registers of the new context. */ s.ndirty = 0; if (mc->mc_flags & _MC_FLAGS_ASYNC_CONTEXT) { - KASSERT((tf->tf_flags & FRAME_SYSCALL) == 0, ("foo")); + /* + * We can get an async context passed to us while we + * entered the kernel through a syscall: sigreturn(2). + * Hence, we cannot assert that the trapframe is not + * a syscall frame, but we can assert that if it is + * the syscall is sigreturn(2). + */ + if (tf->tf_flags & FRAME_SYSCALL) + KASSERT(tf->tf_scratch.gr15 == SYS_sigreturn, ("foo")); tf->tf_scratch = mc->mc_scratch; tf->tf_scratch_fp = mc->mc_scratch_fp; /* XXX High FP */ diff --git a/sys/ia64/ia64/syscall.S b/sys/ia64/ia64/syscall.S index 60e5d80f4014..b009b86fe5f9 100644 --- a/sys/ia64/ia64/syscall.S +++ b/sys/ia64/ia64/syscall.S @@ -371,7 +371,7 @@ ENTRY(epc_syscall, 8) movl gp=__gp ;; } -epc_syscall_restart: +1: { .mib srlz.d add out0=16,sp @@ -384,12 +384,25 @@ epc_syscall_restart: br.call.sptk rp=do_ast ;; } -{ .mfb +{ .mib cmp4.eq p15,p0=ERESTART,r8 - nop 0 -(p15) br.spnt epc_syscall_restart + add r14=24,sp +(p15) br.spnt 1b // restart syscall ;; } +{ .mfb + ld8 r14=[r14] // tf_flags + nop 0 + nop 0 + ;; +} +{ .mib + nop 0 + tbit.z p15,p0=r14,0 +(p15) br.spnt exception_restore + ;; +} + .global epc_syscall_return epc_syscall_return: { .mmi