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