Simplify the contexts created by the kernel and remove the related

flags. We now create asynchronous contexts or syscall contexts only.
Syscall contexts differ from the minimal ABI dictated contexts by
having the scratch registers saved and restored because that's where
we keep the syscall arguments and syscall return values.
Since this change affects KSE, have it use kse_switchin(2) for the
"new" syscall context.
This commit is contained in:
Marcel Moolenaar 2003-12-07 20:47:33 +00:00
parent 377e7be416
commit 47eb01b822
4 changed files with 41 additions and 56 deletions

View File

@ -232,6 +232,12 @@ _thread_switch(struct kcb *kcb, struct tcb *tcb, int setmbox)
mc->mc_special.isr = (intptr_t)&tcb->tcb_tmbx;
}
_ia64_break_setcontext(mc);
} else if (mc->mc_flags & _MC_FLAGS_SYSCALL_CONTEXT) {
if (setmbox)
kse_switchin(mc, (long)&tcb->tcb_tmbx,
(long *)&kcb->kcb_kmbx.km_curthread);
else
kse_switchin(mc, 0L, NULL);
} else {
if (setmbox)
_ia64_restore_context(mc, (intptr_t)&tcb->tcb_tmbx,

View File

@ -232,6 +232,12 @@ _thread_switch(struct kcb *kcb, struct tcb *tcb, int setmbox)
mc->mc_special.isr = (intptr_t)&tcb->tcb_tmbx;
}
_ia64_break_setcontext(mc);
} else if (mc->mc_flags & _MC_FLAGS_SYSCALL_CONTEXT) {
if (setmbox)
kse_switchin(mc, (long)&tcb->tcb_tmbx,
(long *)&kcb->kcb_kmbx.km_curthread);
else
kse_switchin(mc, 0L, NULL);
} else {
if (setmbox)
_ia64_restore_context(mc, (intptr_t)&tcb->tcb_tmbx,

View File

@ -1,4 +1,5 @@
/*-
* Copyright (c) 2003 Marcel Moolenaar
* Copyright (c) 2000,2001 Doug Rabson
* All rights reserved.
*
@ -915,7 +916,7 @@ sendsig(sig_t catcher, int sig, sigset_t *mask, u_long code)
mtx_unlock(&psp->ps_mtx);
PROC_UNLOCK(p);
get_mcontext(td, &sf.sf_uc.uc_mcontext, GET_MC_IA64_SCRATCH);
get_mcontext(td, &sf.sf_uc.uc_mcontext, 0);
/* Copy the frame out to userland. */
if (copyout(&sf, sfp, sizeof(sf)) != 0) {
@ -1067,24 +1068,13 @@ get_mcontext(struct thread *td, mcontext_t *mc, int flags)
} else
mc->mc_special = tf->tf_special;
if (tf->tf_flags & FRAME_SYSCALL) {
if (flags & GET_MC_IA64_SCRATCH) {
mc->mc_flags |= _MC_FLAGS_SCRATCH_VALID;
mc->mc_scratch = tf->tf_scratch;
} else {
/*
* 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 ((flags & GET_MC_CLEAR_RET) == 0) {
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;
}
mc->mc_flags |= _MC_FLAGS_SYSCALL_CONTEXT;
mc->mc_scratch = tf->tf_scratch;
if (flags & GET_MC_CLEAR_RET) {
mc->mc_scratch.gr8 = 0;
mc->mc_scratch.gr9 = 0;
mc->mc_scratch.gr10 = 0;
mc->mc_scratch.gr11 = 0;
}
} else {
mc->mc_flags |= _MC_FLAGS_ASYNC_CONTEXT;
@ -1141,16 +1131,10 @@ set_mcontext(struct thread *td, const mcontext_t *mc)
td->td_pcb->pcb_high_fp = mc->mc_high_fp;
} else {
KASSERT((tf->tf_flags & FRAME_SYSCALL) != 0, ("foo"));
if ((mc->mc_flags & _MC_FLAGS_SCRATCH_VALID) == 0) {
if ((mc->mc_flags & _MC_FLAGS_SYSCALL_CONTEXT) == 0) {
s.cfm = tf->tf_special.cfm;
s.iip = tf->tf_special.iip;
tf->tf_scratch.gr15 = 0; /* Clear syscall nr. */
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;
}

View File

@ -45,48 +45,42 @@
* 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.
* The second variation is for synchronous contexts. When the kernel creates
* a synchronous context if needs to preserve the scratch registers, because
* the syscall argument and return values are stored there in the trapframe
* and they need to be preserved in order to restart a syscall or return the
* proper return values. Also, the IIP and CFM fields need to be preserved
* as they point to the syscall stub, which the kernel saves as a favor to
* userland (it keeps the stubs small and simple).
*
* 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.
* valid. IFF not set, _MC_FLAGS_SYSCALL_CONTEXT indicates if the
* synchronous context is one corresponding to a syscall or not.
* Only the kernel is expected to create such a context and it's
* probably wise to let the kernel restore it.
* _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.
* _MC_FLAGS_SYSCALL_CONTEXT
* If set (hence _MC_FLAGS_ASYNC_CONTEXT is not set) indicates
* that the scratch registers contain syscall arguments and
* return values and that additionally IIP and CFM are valid.
* Only the kernel is expected to create such a context. It's
* probably wise to let the kernel restore it.
*/
typedef struct __mcontext {
unsigned long mc_flags;
#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
#define _MC_FLAGS_KSE_SET_MBOX 0x0004 /* Undocumented. Has to go. */
#define _MC_FLAGS_SYSCALL_CONTEXT 0x0008
unsigned long _reserved_;
struct _special mc_special;
struct _callee_saved mc_preserved;
@ -96,9 +90,4 @@ typedef struct __mcontext {
struct _high_fp mc_high_fp;
} mcontext_t;
#ifdef _KERNEL
/* Flags for get_mcontext(). See also <sys/ucontext.h>. */
#define GET_MC_IA64_SCRATCH 0x10
#endif
#endif /* !_MACHINE_UCONTEXT_H_ */