summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjake <jake@FreeBSD.org>2003-04-01 04:58:50 +0000
committerjake <jake@FreeBSD.org>2003-04-01 04:58:50 +0000
commitc40f0ee134c3131d84c03862215a1463873ea872 (patch)
treec7ad340e884366712a864693cb1d6a845d1644e1
parent6d2a0afa7c8d93769b09f0da8ca3d24d2f16f5ac (diff)
downloadFreeBSD-src-c40f0ee134c3131d84c03862215a1463873ea872.zip
FreeBSD-src-c40f0ee134c3131d84c03862215a1463873ea872.tar.gz
- 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.
-rw-r--r--sys/sparc64/include/pcb.h3
-rw-r--r--sys/sparc64/sparc64/exception.S4
-rw-r--r--sys/sparc64/sparc64/genassym.c2
-rw-r--r--sys/sparc64/sparc64/machdep.c38
-rw-r--r--sys/sparc64/sparc64/swtch.S3
5 files changed, 46 insertions, 4 deletions
diff --git a/sys/sparc64/include/pcb.h b/sys/sparc64/include/pcb.h
index c1e00f1..93615ba 100644
--- a/sys/sparc64/include/pcb.h
+++ b/sys/sparc64/include/pcb.h
@@ -33,11 +33,14 @@
#define MAXWIN 8
+#define PCB_FEF (1 << 0)
+
/* NOTE: pcb_ufp must be aligned on a 64 byte boundary. */
struct pcb {
uint32_t pcb_ufp[64];
u_long pcb_sp;
u_long pcb_pc;
+ u_long pcb_flags;
u_long pcb_nsaved;
u_long pcb_rwsp[MAXWIN];
struct rwindow pcb_rw[MAXWIN];
diff --git a/sys/sparc64/sparc64/exception.S b/sys/sparc64/sparc64/exception.S
index 3a4cb6c..cc0444b 100644
--- a/sys/sparc64/sparc64/exception.S
+++ b/sys/sparc64/sparc64/exception.S
@@ -1183,6 +1183,10 @@ END(tl0_sftrap)
.endm
ENTRY(tl0_fp_restore)
+ ldx [PCB_REG + PCB_FLAGS], %g1
+ andn %g1, PCB_FEF, %g1
+ stx %g1, [PCB_REG + PCB_FLAGS]
+
wr %g0, FPRS_FEF, %fprs
wr %g0, ASI_BLK_S, %asi
ldda [PCB_REG + PCB_UFP + (0 * 64)] %asi, %f0
diff --git a/sys/sparc64/sparc64/genassym.c b/sys/sparc64/sparc64/genassym.c
index b0389b9..e014d97 100644
--- a/sys/sparc64/sparc64/genassym.c
+++ b/sys/sparc64/sparc64/genassym.c
@@ -246,9 +246,11 @@ ASSYM(PCB_SIZEOF, sizeof(struct pcb));
ASSYM(PCB_UFP, offsetof(struct pcb, pcb_ufp));
ASSYM(PCB_SP, offsetof(struct pcb, pcb_sp));
ASSYM(PCB_PC, offsetof(struct pcb, pcb_pc));
+ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
ASSYM(PCB_NSAVED, offsetof(struct pcb, pcb_nsaved));
ASSYM(PCB_RWSP, offsetof(struct pcb, pcb_rwsp));
ASSYM(PCB_RW, offsetof(struct pcb, pcb_rw));
+ASSYM(PCB_FEF, PCB_FEF);
ASSYM(VM_PMAP, offsetof(struct vmspace, vm_pmap));
ASSYM(PM_ACTIVE, offsetof(struct pmap, pm_active));
diff --git a/sys/sparc64/sparc64/machdep.c b/sys/sparc64/sparc64/machdep.c
index 04c4865..45d6c7c 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);
}
/*
diff --git a/sys/sparc64/sparc64/swtch.S b/sys/sparc64/sparc64/swtch.S
index 402928d..d506a07 100644
--- a/sys/sparc64/sparc64/swtch.S
+++ b/sys/sparc64/sparc64/swtch.S
@@ -76,6 +76,9 @@ ENTRY(cpu_switch)
wr %g0, 0, %fprs
andn %l3, FPRS_FEF, %l3
stx %l3, [%l2 + TF_FPRS]
+ ldx [%l1 + PCB_FLAGS], %l3
+ or %l3, PCB_FEF, %l3
+ stx %l3, [%l1 + PCB_FLAGS]
/*
* Flush the windows out to the stack and save the current frame
OpenPOWER on IntegriCloud