summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2003-08-10 08:04:21 +0000
committermarcel <marcel@FreeBSD.org>2003-08-10 08:04:21 +0000
commit07045a57cf3884226d25504b823b4b69a28b2efc (patch)
tree3c3448e475c2e17ad5f4ec39b486f831772fcacf
parent575d334b60937c29ad7d5192fece9b3d61891357 (diff)
downloadFreeBSD-src-07045a57cf3884226d25504b823b4b69a28b2efc.zip
FreeBSD-src-07045a57cf3884226d25504b823b4b69a28b2efc.tar.gz
Now that we can ignore up to 8KB of dirty registers, remove the RSE
magic from exec_setregs(). In set_mcontext() we now also don't have to worry that we entered the kernel with more that 512 bytes of dirty registers on the kernel stack. Note that we cannot make any assumptions anymore WRT to NaT collection points in exec_setregs(), so we have to deal with them now.
-rw-r--r--sys/ia64/ia64/machdep.c75
1 files changed, 30 insertions, 45 deletions
diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c
index 00cab57..1779341 100644
--- a/sys/ia64/ia64/machdep.c
+++ b/sys/ia64/ia64/machdep.c
@@ -1112,9 +1112,15 @@ set_mcontext(struct thread *td, const mcontext_t *mc)
struct trapframe *tf;
tf = td->td_frame;
+
+ KASSERT((tf->tf_special.ndirty & ~PAGE_MASK) == 0,
+ ("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);
+ /* We don't have any dirty registers of the new context. */
+ s.ndirty = 0;
if (mc->mc_flags & _MC_FLAGS_ASYNC_CONTEXT) {
tf->tf_scratch = mc->mc_scratch;
tf->tf_scratch_fp = mc->mc_scratch_fp;
@@ -1171,67 +1177,46 @@ void
exec_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings)
{
struct trapframe *tf;
- uint64_t bspst, kstack, ndirty;
- size_t rssz;
+ uint64_t *ksttop, *kst;
tf = td->td_frame;
- kstack = td->td_kstack;
+ ksttop = (uint64_t*)(td->td_kstack + tf->tf_special.ndirty);
/*
- * RSE magic: We have ndirty registers of the process on the kernel
- * stack which don't belong to the new image. Discard them. Note
- * that for the "legacy" syscall support we need to keep 3 registers
- * worth of dirty bytes. These 3 registers are the initial arguments
- * to the newly executing program.
- * However, we cannot discard all the ndirty registers by simply
- * moving the kernel related registers to the bottom of the kernel
- * stack and lowering the current bspstore, because we get into
- * trouble with the NaT collections. We need to keep that in sync
- * with the registers. Hence, we can only copy a multiple of 512
- * bytes. Consequently, we may end up with some registers of the
- * previous image on the kernel stack. This we ignore by making
- * sure we mask-off the lower 9 bits of the bspstore value just
- * prior to saving it in ar.k6.
+ * We can ignore up to 8KB of dirty registers by masking off the
+ * lower 13 bits in exception_restore() or epc_syscall(). This
+ * should be enough for a couple of years, but if there are more
+ * than 8KB of dirty registers, we lose track of the bottom of
+ * the kernel stack. The solution is to copy the active part of
+ * the kernel stack down 1 page (or 2, but not more than that)
+ * so that we always have less than 8KB of dirty registers.
*/
- ndirty = tf->tf_special.ndirty & ~0x1ff;
- if (ndirty > 0) {
- __asm __volatile("mov ar.rsc=0;;");
- __asm __volatile("mov %0=ar.bspstore" : "=r"(bspst));
- /*
- * Make sure we have all the user registers written out.
- * We're doing culculations with ndirty and ar.bspstore
- * and we better make sure ar.bspstore >= ndirty.
- */
- rssz = bspst - kstack;
- if (rssz < ndirty) {
- __asm __volatile("flushrs;;");
- __asm __volatile("mov %0=ar.bspstore" : "=r"(bspst));
- rssz = bspst - kstack;
- }
- bcopy((void*)(kstack + ndirty), (void*)kstack, rssz - ndirty);
- bspst -= ndirty;
- __asm __volatile("mov ar.bspstore=%0;;" :: "r"(bspst));
- __asm __volatile("mov ar.rsc=3");
- tf->tf_special.ndirty -= ndirty;
- }
- ndirty = tf->tf_special.ndirty;
+ KASSERT((tf->tf_special.ndirty & ~PAGE_MASK) == 0,
+ ("Whoa there! We have more than 8KB of dirty registers!"));
bzero(&tf->tf_special, sizeof(tf->tf_special));
-
if ((tf->tf_flags & FRAME_SYSCALL) == 0) { /* break syscalls. */
bzero(&tf->tf_scratch, sizeof(tf->tf_scratch));
bzero(&tf->tf_scratch_fp, sizeof(tf->tf_scratch_fp));
tf->tf_special.iip = entry;
tf->tf_special.cfm = (1UL<<63) | (3UL<<7) | 3UL;
tf->tf_special.bspstore = td->td_md.md_bspstore;
- tf->tf_special.ndirty = 24;
/*
* Copy the arguments onto the kernel register stack so that
- * they get loaded by the loadrs instruction.
+ * they get loaded by the loadrs instruction. Skip over the
+ * NaT collection points.
*/
- *(uint64_t*)(kstack + ndirty - 24) = stack;
- *(uint64_t*)(kstack + ndirty - 16) = ps_strings;
- *(uint64_t*)(kstack + ndirty - 8) = 0;
+ kst = ksttop - 1;
+ if (((uintptr_t)kst & 0x1ff) == 0x1f8)
+ *kst-- = 0;
+ *kst-- = 0;
+ if (((uintptr_t)kst & 0x1ff) == 0x1f8)
+ *kst-- = 0;
+ *kst-- = ps_strings;
+ if (((uintptr_t)kst & 0x1ff) == 0x1f8)
+ *kst-- = 0;
+ *kst = stack;
+ tf->tf_special.ndirty = (ksttop - kst) << 3;
} else { /* epc syscalls (default). */
tf->tf_special.rp = entry;
tf->tf_special.pfs = (3UL<<62) | (3UL<<7) | 3UL;
OpenPOWER on IntegriCloud