From 29952636d30c5ccf87e7827d4b41efa18de57f6d Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Sun, 10 Aug 2003 08:04:21 +0000 Subject: [PATCH] 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. --- sys/ia64/ia64/machdep.c | 75 +++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 45 deletions(-) diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index 00cab574a9f..1779341358d 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;