diff options
author | marcel <marcel@FreeBSD.org> | 2003-12-14 01:59:31 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2003-12-14 01:59:31 +0000 |
commit | 6b2a4c99ba61541703526fbc3550dfc0f0540ce3 (patch) | |
tree | 0893fb8582f17206204ce3ad39bfa69f57410313 /sys/ia64 | |
parent | 2e9029791bdea7f89821d858a0b2e5bca0528924 (diff) | |
download | FreeBSD-src-6b2a4c99ba61541703526fbc3550dfc0f0540ce3.zip FreeBSD-src-6b2a4c99ba61541703526fbc3550dfc0f0540ce3.tar.gz |
In set_mcontext(), take into account that kse_switchin(2) will
eventually be passed an async. context as well as a syscall
context.
While here, fix a serious bug in that if the trapframe is a
syscall frame, but we're restoring an async context, we need
to clear the FRAME_SYSCALL flag so that we leave the kernel
via exception_restore.
Diffstat (limited to 'sys/ia64')
-rw-r--r-- | sys/ia64/ia64/machdep.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index 28aa70c..ae55edf 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -1118,13 +1118,18 @@ set_mcontext(struct thread *td, const mcontext_t *mc) if (mc->mc_flags & _MC_FLAGS_ASYNC_CONTEXT) { /* * We can get an async context passed to us while we - * entered the kernel through a syscall: sigreturn(2). + * entered the kernel through a syscall: sigreturn(2) + * and kse_switchin(2) both take contexts that could + * previously be the result of a trap or interrupt. * 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). + * a syscall frame, but we can assert that it's at + * least an expected syscall. */ - if (tf->tf_flags & FRAME_SYSCALL) - KASSERT(tf->tf_scratch.gr15 == SYS_sigreturn, ("foo")); + if (tf->tf_flags & FRAME_SYSCALL) { + KASSERT(tf->tf_scratch.gr15 == SYS_sigreturn || + tf->tf_scratch.gr15 == SYS_kse_switchin, ("foo")); + tf->tf_flags &= ~FRAME_SYSCALL; + } tf->tf_scratch = mc->mc_scratch; tf->tf_scratch_fp = mc->mc_scratch_fp; if (mc->mc_flags & _MC_FLAGS_HIGHFP_VALID) |