diff options
author | Jake Burkholder <jake@FreeBSD.org> | 2003-04-01 04:58:50 +0000 |
---|---|---|
committer | Jake Burkholder <jake@FreeBSD.org> | 2003-04-01 04:58:50 +0000 |
commit | 73adf5691f5bfebd35f74ec3498ec4377f327323 (patch) | |
tree | c7ad340e884366712a864693cb1d6a845d1644e1 /sys/sparc64/sparc64/machdep.c | |
parent | 42d3ad71445d87458b54a3efd56c298072788e83 (diff) | |
download | src-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.c | 38 |
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); } /* |