diff options
| author | Marcel Moolenaar <marcel@FreeBSD.org> | 2003-08-07 07:52:39 +0000 |
|---|---|---|
| committer | Marcel Moolenaar <marcel@FreeBSD.org> | 2003-08-07 07:52:39 +0000 |
| commit | 1634f50b1bd795c2fba20dbd28aea9cdbb2be7ef (patch) | |
| tree | 9e00517f87f37af81280ea200d2d22523af76512 | |
| parent | dab4fca49b6e1a93ecf662f118fff6f9f0952f54 (diff) | |
Notes
| -rw-r--r-- | sys/ia64/ia64/machdep.c | 102 | ||||
| -rw-r--r-- | sys/ia64/include/ucontext.h | 54 |
2 files changed, 121 insertions, 35 deletions
diff --git a/sys/ia64/ia64/machdep.c b/sys/ia64/ia64/machdep.c index dc0501629a4a..00cab574a9f6 100644 --- a/sys/ia64/ia64/machdep.c +++ b/sys/ia64/ia64/machdep.c @@ -886,8 +886,9 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) mc = &sf.sf_uc.uc_mcontext; mc->mc_special = tf->tf_special; mc->mc_scratch = tf->tf_scratch; + if ((tf->tf_flags & FRAME_SYSCALL) == 0) { - mc->mc_flags |= IA64_MC_FLAGS_SCRATCH_VALID; + mc->mc_flags |= _MC_FLAGS_ASYNC_CONTEXT; mc->mc_scratch_fp = tf->tf_scratch_fp; /* * XXX High FP. If the process has never used the high FP, @@ -896,7 +897,9 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code) * already there (ie get them from the CPU that has them) * and write them in the context. */ - } + } else + mc->mc_flags |= _MC_FLAGS_SCRATCH_VALID; + save_callee_saved(&mc->mc_preserved); save_callee_saved_fp(&mc->mc_preserved_fp); @@ -992,22 +995,29 @@ sigreturn(struct thread *td, return (EFAULT); /* - * XXX make sure ndirty in the current trapframe is less than - * 0x1f8 so that if we throw away the current register stack, - * we have reached the bottom of the kernel register stack. - * See also exec_setregs. - */ - - /* - * Restore the user-supplied information + * Restore the user-supplied information. + * XXX Very much incomplete. */ mc = &uc.uc_mcontext; tf->tf_special = mc->mc_special; - tf->tf_scratch = mc->mc_scratch; - if ((mc->mc_flags & IA64_MC_FLAGS_SCRATCH_VALID) != 0) { + + if (mc->mc_flags & _MC_FLAGS_ASYNC_CONTEXT) { + tf->tf_scratch = mc->mc_scratch; tf->tf_scratch_fp = mc->mc_scratch_fp; /* XXX high FP. */ + } else { + if ((mc->mc_flags & _MC_FLAGS_SCRATCH_VALID) == 0) { + tf->tf_scratch.gr15 = 0; + if (mc->mc_flags & _MC_FLAGS_RETURN_VALID) { + tf->tf_scratch.gr8 = mc->mc_scratch.gr8; + tf->tf_scratch.gr9 = mc->mc_scratch.gr9; + tf->tf_scratch.gr10 = mc->mc_scratch.gr10; + tf->tf_scratch.gr11 = mc->mc_scratch.gr11; + } + } else + tf->tf_scratch = mc->mc_scratch; } + restore_callee_saved(&mc->mc_preserved); restore_callee_saved_fp(&mc->mc_preserved_fp); @@ -1043,10 +1053,8 @@ get_mcontext(struct thread *td, mcontext_t *mc, int clear_ret) uint64_t bspst, *kstk, *ustk; tf = td->td_frame; + bzero(mc, sizeof(*mc)); s = tf->tf_special; - s.pfs = s.cfm; - s.rp = s.iip; - s.cfm = s.iip = 0; if (s.ndirty != 0) { __asm __volatile("mov ar.rsc=0;;"); __asm __volatile("mov %0=ar.bspstore" : "=r"(bspst)); @@ -1068,19 +1076,32 @@ get_mcontext(struct thread *td, mcontext_t *mc, int clear_ret) } s.bspstore = (uintptr_t)ustk; } + if (tf->tf_flags & FRAME_SYSCALL) { + s.pfs = s.cfm; + s.rp = s.iip; + s.cfm = s.iip = 0; + /* + * Put the syscall return values in the context. We need this + * for swapcontext() to work. Note that we don't use gr11 in + * the kernel, but the runtime specification defines it as a + * return register, just like gr8-gr10. + */ + mc->mc_flags |= _MC_FLAGS_RETURN_VALID; + if (!clear_ret) { + mc->mc_scratch.gr8 = tf->tf_scratch.gr8; + mc->mc_scratch.gr9 = tf->tf_scratch.gr9; + mc->mc_scratch.gr10 = tf->tf_scratch.gr10; + mc->mc_scratch.gr11 = tf->tf_scratch.gr11; + } + } else { + mc->mc_flags |= _MC_FLAGS_ASYNC_CONTEXT; + mc->mc_scratch = tf->tf_scratch; + mc->mc_scratch_fp = tf->tf_scratch_fp; + /* XXX High FP */ + } mc->mc_special = s; save_callee_saved(&mc->mc_preserved); save_callee_saved_fp(&mc->mc_preserved_fp); - /* - * Put the syscall return values in the context. We need this - * for swapcontext() to work. Note that we don't use gr11 in - * the kernel, but the runtime specification defines it as a - * return register, just like gr8-gr10. - */ - mc->mc_scratch.gr8 = (clear_ret) ? 0 : tf->tf_scratch.gr8; - mc->mc_scratch.gr9 = (clear_ret) ? 0 : tf->tf_scratch.gr9; - mc->mc_scratch.gr10 = (clear_ret) ? 0 : tf->tf_scratch.gr10; - mc->mc_scratch.gr11 = (clear_ret) ? 0 : tf->tf_scratch.gr11; return (0); } @@ -1092,19 +1113,34 @@ set_mcontext(struct thread *td, const mcontext_t *mc) tf = td->td_frame; s = mc->mc_special; - s.cfm = s.pfs; - s.iip = s.rp; - s.pfs = tf->tf_special.pfs; - s.rp = tf->tf_special.rp; /* Only copy the user mask from the new context. */ s.psr = (s.psr & 0x1f) | (tf->tf_special.psr & ~0x1f); + if (mc->mc_flags & _MC_FLAGS_ASYNC_CONTEXT) { + tf->tf_scratch = mc->mc_scratch; + tf->tf_scratch_fp = mc->mc_scratch_fp; + /* XXX High FP */ + } else { + s.cfm = s.pfs; + s.pfs = tf->tf_special.pfs; + s.iip = s.rp; + s.rp = tf->tf_special.rp; + if ((mc->mc_flags & _MC_FLAGS_SCRATCH_VALID) == 0) { + if (mc->mc_flags & _MC_FLAGS_RETURN_VALID) { + tf->tf_scratch.gr8 = mc->mc_scratch.gr8; + tf->tf_scratch.gr9 = mc->mc_scratch.gr9; + tf->tf_scratch.gr10 = mc->mc_scratch.gr10; + tf->tf_scratch.gr11 = mc->mc_scratch.gr11; + } + } else + tf->tf_scratch = mc->mc_scratch; + } tf->tf_special = s; restore_callee_saved(&mc->mc_preserved); restore_callee_saved_fp(&mc->mc_preserved_fp); - tf->tf_scratch.gr8 = mc->mc_scratch.gr8; - tf->tf_scratch.gr9 = mc->mc_scratch.gr9; - tf->tf_scratch.gr10 = mc->mc_scratch.gr10; - tf->tf_scratch.gr11 = mc->mc_scratch.gr11; + + if (mc->mc_flags & _MC_FLAGS_KSE_SET_MBOX) + suword((caddr_t)mc->mc_special.ifa, mc->mc_special.isr); + return (0); } diff --git a/sys/ia64/include/ucontext.h b/sys/ia64/include/ucontext.h index e5fae653092a..66f8ffff0075 100644 --- a/sys/ia64/include/ucontext.h +++ b/sys/ia64/include/ucontext.h @@ -33,10 +33,60 @@ #include <machine/_regset.h> +/* + * The mc_flags field provides the necessary clues when dealing with the gory + * details of ia64 specific contexts. A comprehensive explanation is added for + * everybody's sanity, including the author's. + * + * The first and foremost variation in the context is synchronous contexts + * (= synctx) versus asynchronous contexts (= asynctx). A synctx is created + * synchronously WRT program execution and has the advantage that none of the + * scratch registers have to be saved. They are assumed to be clobbered by the + * call to the function that creates the context. An asynctx needs to have the + * scratch registers preserved because it can describe any point in a thread's + * (or process') execution. + * + * Below a description of the flags and their meaning: + * + * _MC_FLAGS_ASYNC_CONTEXT + * If set, indicates that mc_scratch and mc_scratch_fp are both + * valid. IFF not set, _MC_FLAGS_RETURN_VALID indicates if the + * return registers are valid or not. + * _MC_FLAGS_HIGHFP_VALID + * If set, indicates that the high FP registers (f32-f127) are + * valid. This flag is very likely not going to be set for any + * sensible synctx, but is not explicitly disallowed. Any synctx + * that has this flag may or may not have the high FP registers + * restored. In short: don't do it. + * _MC_FLAGS_KSE_SET_MBOX + * This flag is special to setcontext(2) and swapcontext(2). It + * instructs the kernel to write the value in mc_special.isr to + * the memory address pointed to by mc_special.ifa. This allows + * the kernel to switch to a new context in a KSE based threaded + * program. Note that this is a non-srandard extension to the + * otherwise standard system calls and use of this flag should be + * limited to KSE. + * _MC_FLAGS_RETURN_VALID + * If set and _MC_FLAGS_ASYNC_CONTEXT is not set indicates that + * the ABI defined return registers are valid. Both getcontext(2) + * and swapcontext(2) need to save the system call return values. + * Any synctx that does not have this flag may still have the + * return registers restored from the context. + * _MC_FLAGS_SCRATCH_VALID + * If set and _MC_FLAGS_ASYNC_CONTEXT is not set indicates that + * the scratch registers, but not the FP registers are valid. + * This flag is set in contexts passed to signal handlers. This + * flag is a superset of _MC_FLAGS_RETURN_VALID. If both flags + * are set, this flag takes precedence. + */ + typedef struct __mcontext { unsigned long mc_flags; -#define IA64_MC_FLAGS_SCRATCH_VALID 1 -#define IA64_MC_FLAGS_HIGHFP_VALID 2 +#define _MC_FLAGS_ASYNC_CONTEXT 0x0001 +#define _MC_FLAGS_HIGHFP_VALID 0x0002 +#define _MC_FLAGS_KSE_SET_MBOX 0x0004 +#define _MC_FLAGS_RETURN_VALID 0x0008 +#define _MC_FLAGS_SCRATCH_VALID 0x0010 unsigned long _reserved_; struct _special mc_special; struct _callee_saved mc_preserved; |
