aboutsummaryrefslogtreecommitdiff
path: root/sys/sparc64/sparc64/machdep.c
diff options
context:
space:
mode:
authorJake Burkholder <jake@FreeBSD.org>2003-04-01 04:58:50 +0000
committerJake Burkholder <jake@FreeBSD.org>2003-04-01 04:58:50 +0000
commit73adf5691f5bfebd35f74ec3498ec4377f327323 (patch)
treec7ad340e884366712a864693cb1d6a845d1644e1 /sys/sparc64/sparc64/machdep.c
parent42d3ad71445d87458b54a3efd56c298072788e83 (diff)
downloadsrc-73adf5691f5bfebd35f74ec3498ec4377f327323.tar.gz
src-73adf5691f5bfebd35f74ec3498ec4377f327323.zip
- Add a flags field to struct pcb. Use this to keep track of wether or
not the pcb has floating point registers saved in it. - Implement get_mcontext and set_mcontext.
Notes
Notes: svn path=/head/; revision=112924
Diffstat (limited to 'sys/sparc64/sparc64/machdep.c')
-rw-r--r--sys/sparc64/sparc64/machdep.c38
1 files changed, 34 insertions, 4 deletions
diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c
index 04c486520901..45d6c7cea166 100644
--- a/sys/sparc64/sparc64/machdep.c
+++ b/sys/sparc64/sparc64/machdep.c
@@ -513,17 +513,47 @@ freebsd4_sigreturn(struct thread *td, struct freebsd4_sigreturn_args *uap)
#endif
int
-get_mcontext(struct thread *td, mcontext_t *mcp)
+get_mcontext(struct thread *td, mcontext_t *mc)
{
+ struct trapframe *tf;
+ struct pcb *pcb;
- return (ENOSYS);
+ if (((uintptr_t)mc & (64 - 1)) != 0)
+ return (EINVAL);
+ tf = td->td_frame;
+ pcb = td->td_pcb;
+ bcopy(tf, mc, sizeof(*tf));
+ critical_enter();
+ if ((tf->tf_fprs & FPRS_FEF) != 0)
+ savefpctx(mc->mc_fp);
+ else if ((pcb->pcb_flags & PCB_FEF) != 0) {
+ bcopy(pcb->pcb_ufp, mc->mc_fp, sizeof(*mc->mc_fp));
+ mc->mc_fprs |= FPRS_FEF;
+ }
+ critical_exit();
+ return (0);
}
int
-set_mcontext(struct thread *td, const mcontext_t *mcp)
+set_mcontext(struct thread *td, const mcontext_t *mc)
{
+ struct trapframe *tf;
+ struct pcb *pcb;
+ uint64_t wstate;
- return (ENOSYS);
+ if (!TSTATE_SECURE(mc->mc_tstate))
+ return (EINVAL);
+ tf = td->td_frame;
+ pcb = td->td_pcb;
+ wstate = tf->tf_wstate;
+ bcopy(mc, tf, sizeof(*tf));
+ tf->tf_wstate = wstate;
+ if ((mc->mc_fprs & FPRS_FEF) != 0) {
+ tf->tf_fprs = 0;
+ bcopy(mc->mc_fp, pcb->pcb_ufp, sizeof(*pcb->pcb_ufp));
+ pcb->pcb_flags |= PCB_FEF;
+ }
+ return (0);
}
/*