mirror of
https://github.com/freebsd/freebsd-src
synced 2024-10-04 23:50:27 +00:00
- Rename pcb_fpstate to pcb_ufp (user floating point), and change it to
a simple array of 64 ints. - Use a critical section when saving floating point state in cpu_fork instead of sched_lock.
This commit is contained in:
parent
70d5093a8b
commit
f217a77ce4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=112920
|
@ -27,26 +27,13 @@
|
|||
#ifndef _MACHINE_FP_H_
|
||||
#define _MACHINE_FP_H_
|
||||
|
||||
/* A block of 8 double-precision (16 single-precision) FP registers. */
|
||||
struct fpblock {
|
||||
u_int fpb_i[16];
|
||||
};
|
||||
|
||||
struct fpstate {
|
||||
struct fpblock fp_fb[4];
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
struct pcb;
|
||||
struct thread;
|
||||
|
||||
/*
|
||||
* Note: The pointers passed to the next two functions must be aligned on
|
||||
* 64 byte boundaries.
|
||||
* Note: The pointer passed to savefpctx must be aligned on a 64 byte
|
||||
* boundary.
|
||||
*/
|
||||
void savefpctx(struct fpstate *);
|
||||
void restorefpctx(struct fpstate *);
|
||||
void savefpctx(uint32_t *fp);
|
||||
|
||||
#endif /* _KERNEL */
|
||||
#endif /* !_MACHINE_FP_H_ */
|
||||
|
|
|
@ -29,14 +29,13 @@
|
|||
#ifndef _MACHINE_PCB_H_
|
||||
#define _MACHINE_PCB_H_
|
||||
|
||||
#include <machine/fp.h>
|
||||
#include <machine/frame.h>
|
||||
|
||||
#define MAXWIN 8
|
||||
|
||||
/* NOTE: pcb_fpstate must be aligned on a 64 byte boundary. */
|
||||
/* NOTE: pcb_ufp must be aligned on a 64 byte boundary. */
|
||||
struct pcb {
|
||||
struct fpstate pcb_fpstate;
|
||||
uint32_t pcb_ufp[64];
|
||||
u_long pcb_sp;
|
||||
u_long pcb_pc;
|
||||
u_long pcb_nsaved;
|
||||
|
|
|
@ -482,18 +482,6 @@ END(rsf_fatal)
|
|||
.endr
|
||||
.endm
|
||||
|
||||
.macro tl0_fp_restore
|
||||
wr %g0, FPRS_FEF, %fprs
|
||||
wr %g0, ASI_BLK_S, %asi
|
||||
ldda [PCB_REG + PCB_FPSTATE + FP_FB0] %asi, %f0
|
||||
ldda [PCB_REG + PCB_FPSTATE + FP_FB1] %asi, %f16
|
||||
ldda [PCB_REG + PCB_FPSTATE + FP_FB2] %asi, %f32
|
||||
ldda [PCB_REG + PCB_FPSTATE + FP_FB3] %asi, %f48
|
||||
membar #Sync
|
||||
done
|
||||
.align 32
|
||||
.endm
|
||||
|
||||
.macro tl0_insn_excptn
|
||||
wrpr %g0, PSTATE_ALT, %pstate
|
||||
wr %g0, ASI_IMMU, %asi
|
||||
|
@ -1188,6 +1176,23 @@ END(tl0_sftrap)
|
|||
.align 32
|
||||
.endm
|
||||
|
||||
.macro tl0_fp_restore
|
||||
ba,a %xcc, tl0_fp_restore
|
||||
nop
|
||||
.align 32
|
||||
.endm
|
||||
|
||||
ENTRY(tl0_fp_restore)
|
||||
wr %g0, FPRS_FEF, %fprs
|
||||
wr %g0, ASI_BLK_S, %asi
|
||||
ldda [PCB_REG + PCB_UFP + (0 * 64)] %asi, %f0
|
||||
ldda [PCB_REG + PCB_UFP + (1 * 64)] %asi, %f16
|
||||
ldda [PCB_REG + PCB_UFP + (2 * 64)] %asi, %f32
|
||||
ldda [PCB_REG + PCB_UFP + (3 * 64)] %asi, %f48
|
||||
membar #Sync
|
||||
done
|
||||
END(tl0_fp_restore)
|
||||
|
||||
.macro tl1_insn_excptn
|
||||
wrpr %g0, PSTATE_ALT, %pstate
|
||||
wr %g0, ASI_IMMU, %asi
|
||||
|
|
|
@ -243,7 +243,7 @@ ASSYM(TD_PCB, offsetof(struct thread, td_pcb));
|
|||
ASSYM(TD_PROC, offsetof(struct thread, td_proc));
|
||||
|
||||
ASSYM(PCB_SIZEOF, sizeof(struct pcb));
|
||||
ASSYM(PCB_FPSTATE, offsetof(struct pcb, pcb_fpstate));
|
||||
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_NSAVED, offsetof(struct pcb, pcb_nsaved));
|
||||
|
@ -255,11 +255,6 @@ ASSYM(PM_ACTIVE, offsetof(struct pmap, pm_active));
|
|||
ASSYM(PM_CONTEXT, offsetof(struct pmap, pm_context));
|
||||
ASSYM(PM_TSB, offsetof(struct pmap, pm_tsb));
|
||||
|
||||
ASSYM(FP_FB0, offsetof(struct fpstate, fp_fb[0]));
|
||||
ASSYM(FP_FB1, offsetof(struct fpstate, fp_fb[1]));
|
||||
ASSYM(FP_FB2, offsetof(struct fpstate, fp_fb[2]));
|
||||
ASSYM(FP_FB3, offsetof(struct fpstate, fp_fb[3]));
|
||||
|
||||
ASSYM(CCFSZ, sizeof(struct frame));
|
||||
ASSYM(SPOFF, SPOFF);
|
||||
|
||||
|
|
|
@ -682,8 +682,7 @@ fill_fpregs(struct thread *td, struct fpreg *fpregs)
|
|||
|
||||
pcb = td->td_pcb;
|
||||
tf = td->td_frame;
|
||||
bcopy(pcb->pcb_fpstate.fp_fb, fpregs->fr_regs,
|
||||
sizeof(pcb->pcb_fpstate.fp_fb));
|
||||
bcopy(pcb->pcb_ufp, fpregs->fr_regs, sizeof(fpregs->fr_regs));
|
||||
fpregs->fr_fsr = tf->tf_fsr;
|
||||
fpregs->fr_gsr = tf->tf_gsr;
|
||||
return (0);
|
||||
|
@ -697,8 +696,7 @@ set_fpregs(struct thread *td, struct fpreg *fpregs)
|
|||
|
||||
pcb = td->td_pcb;
|
||||
tf = td->td_frame;
|
||||
bcopy(fpregs->fr_regs, pcb->pcb_fpstate.fp_fb,
|
||||
sizeof(fpregs->fr_regs));
|
||||
bcopy(fpregs->fr_regs, pcb->pcb_ufp, sizeof(pcb->pcb_ufp));
|
||||
tf->tf_fsr = fpregs->fr_fsr;
|
||||
tf->tf_gsr = fpregs->fr_gsr;
|
||||
return (0);
|
||||
|
|
|
@ -68,10 +68,10 @@ ENTRY(cpu_switch)
|
|||
nop
|
||||
wr %g0, FPRS_FEF, %fprs
|
||||
wr %g0, ASI_BLK_S, %asi
|
||||
stda %f0, [%l1 + PCB_FPSTATE + FP_FB0] %asi
|
||||
stda %f16, [%l1 + PCB_FPSTATE + FP_FB1] %asi
|
||||
stda %f32, [%l1 + PCB_FPSTATE + FP_FB2] %asi
|
||||
stda %f48, [%l1 + PCB_FPSTATE + FP_FB3] %asi
|
||||
stda %f0, [%l1 + PCB_UFP + (0 * 64)] %asi
|
||||
stda %f16, [%l1 + PCB_UFP + (1 * 64)] %asi
|
||||
stda %f32, [%l1 + PCB_UFP + (2 * 64)] %asi
|
||||
stda %f48, [%l1 + PCB_UFP + (3 * 64)] %asi
|
||||
membar #Sync
|
||||
wr %g0, 0, %fprs
|
||||
andn %l3, FPRS_FEF, %l3
|
||||
|
@ -278,31 +278,16 @@ ENTRY(savectx)
|
|||
END(savectx)
|
||||
|
||||
/*
|
||||
* void savefpctx(struct fpstate *);
|
||||
* void savefpctx(uint32_t *);
|
||||
*/
|
||||
ENTRY(savefpctx)
|
||||
wr %g0, FPRS_FEF, %fprs
|
||||
wr %g0, ASI_BLK_S, %asi
|
||||
stda %f0, [%o0 + PCB_FPSTATE + FP_FB0] %asi
|
||||
stda %f16, [%o0 + PCB_FPSTATE + FP_FB1] %asi
|
||||
stda %f32, [%o0 + PCB_FPSTATE + FP_FB2] %asi
|
||||
stda %f48, [%o0 + PCB_FPSTATE + FP_FB3] %asi
|
||||
stda %f0, [%o0 + (0 * 64)] %asi
|
||||
stda %f16, [%o0 + (1 * 64)] %asi
|
||||
stda %f32, [%o0 + (2 * 64)] %asi
|
||||
stda %f48, [%o0 + (3 * 64)] %asi
|
||||
membar #Sync
|
||||
retl
|
||||
wr %g0, 0, %fprs
|
||||
END(savefpctx)
|
||||
|
||||
/*
|
||||
* void restorefpctx(struct fpstate *);
|
||||
*/
|
||||
ENTRY(restorefpctx)
|
||||
wr %g0, FPRS_FEF, %fprs
|
||||
wr %g0, ASI_BLK_S, %asi
|
||||
ldda [%o0 + PCB_FPSTATE + FP_FB0] %asi, %f0
|
||||
ldda [%o0 + PCB_FPSTATE + FP_FB1] %asi, %f16
|
||||
ldda [%o0 + PCB_FPSTATE + FP_FB2] %asi, %f32
|
||||
ldda [%o0 + PCB_FPSTATE + FP_FB3] %asi, %f48
|
||||
membar #Sync
|
||||
retl
|
||||
wr %g0, 0, %fprs
|
||||
END(restorefpctx)
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
|
||||
#include <machine/cache.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/fp.h>
|
||||
#include <machine/fsr.h>
|
||||
#include <machine/frame.h>
|
||||
#include <machine/md_var.h>
|
||||
|
@ -186,11 +187,10 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
|
|||
/*
|
||||
* Ensure that p1's pcb is up to date.
|
||||
*/
|
||||
if ((td1->td_frame->tf_fprs & FPRS_FEF) != 0) {
|
||||
mtx_lock_spin(&sched_lock);
|
||||
savefpctx(&pcb1->pcb_fpstate);
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
}
|
||||
critical_enter();
|
||||
if ((td1->td_frame->tf_fprs & FPRS_FEF) != 0)
|
||||
savefpctx(pcb1->pcb_ufp);
|
||||
critical_exit();
|
||||
/* Make sure the copied windows are spilled. */
|
||||
flushw();
|
||||
/* Copy the pcb (this will copy the windows saved in the pcb, too). */
|
||||
|
|
Loading…
Reference in a new issue