diff options
author | marcel <marcel@FreeBSD.org> | 2003-09-19 22:51:26 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2003-09-19 22:51:26 +0000 |
commit | 901f7b2cb79afe6f5a842dc09d70124cbe1cb852 (patch) | |
tree | e14a4e318cf8c6b5b1727b77032fbd366ecc14e2 | |
parent | 3dba6f023a8688e876dce4fc38ed18481ed6c8ee (diff) | |
download | FreeBSD-src-901f7b2cb79afe6f5a842dc09d70124cbe1cb852.zip FreeBSD-src-901f7b2cb79afe6f5a842dc09d70124cbe1cb852.tar.gz |
Fix the most significant KSE breakage caused by not restoring the
restart instruction bits in the PSR. As such, we were returning
from interrupt to the instruction in the bundle that caused us
to enter the kernel, only now we're returning to a completely
different bundle.
While close here: add two KASSERTs to make sure that we restore
sync contexts only when entered the kernel through a syscall and
restore an async context only when entered the kernel through an
interrupt, trap or fault.
While not exactly here, but close enough: use suword64() when we
copy the dirty registers from the kernel stack to the user stack.
The code was intended to be be replaced shortly after being added,
but that was a couple of weeks ago. I might as well avoid that it
is a source for panics until it's replaced.
-rw-r--r-- | sys/ia64/ia64/machdep.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index 4bc763d..e08cea3 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -1079,9 +1079,9 @@ get_mcontext(struct thread *td, mcontext_t *mc, int clear_ret) ustk = (uint64_t*)s.bspstore; kstk = (uint64_t*)td->td_kstack; while (s.ndirty > 0) { - *ustk++ = *kstk++; + suword64(ustk++, *kstk++); if (((uintptr_t)ustk & 0x1ff) == 0x1f8) - *ustk++ = 0; + suword64(ustk++, 0); if (((uintptr_t)kstk & 0x1ff) == 0x1f8) { kstk++; s.ndirty -= 8; @@ -1124,6 +1124,7 @@ set_mcontext(struct thread *td, const mcontext_t *mc) { struct _special s; struct trapframe *tf; + uint64_t psrmask; tf = td->td_frame; @@ -1131,15 +1132,22 @@ set_mcontext(struct thread *td, const mcontext_t *mc) ("Whoa there! We have more than 8KB of dirty registers!")); s = mc->mc_special; - /* Only copy the user mask from the new context. */ - s.psr = (s.psr & 0x1f) | (tf->tf_special.psr & ~0x1f); + /* + * Only copy the user mask and the restart instruction bit from + * the new context. + */ + psrmask = IA64_PSR_BE | IA64_PSR_UP | IA64_PSR_AC | IA64_PSR_MFL | + IA64_PSR_MFH | IA64_PSR_RI; + s.psr = (tf->tf_special.psr & ~psrmask) | (s.psr & psrmask); /* 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")); tf->tf_scratch = mc->mc_scratch; tf->tf_scratch_fp = mc->mc_scratch_fp; /* XXX High FP */ } else { + KASSERT((tf->tf_flags & FRAME_SYSCALL) != 0, ("foo")); s.cfm = s.pfs; s.pfs = tf->tf_special.pfs; s.iip = s.rp; |