From 6ef515f72a2fd76a0660b8c6aa8bd611f5481882 Mon Sep 17 00:00:00 2001 From: benno Date: Mon, 13 May 2002 07:44:48 +0000 Subject: FPU support. Obtained from: NetBSD (portions) --- sys/powerpc/aim/machdep.c | 91 +------------------------- sys/powerpc/aim/trap.c | 35 +++++----- sys/powerpc/include/fpu.h | 11 ++++ sys/powerpc/include/ieeefp.h | 25 +++++++ sys/powerpc/include/pcb.h | 2 + sys/powerpc/include/pcpu.h | 3 +- sys/powerpc/powerpc/fpu.c | 147 ++++++++++++++++++++++++++++++++++++++++++ sys/powerpc/powerpc/machdep.c | 91 +------------------------- sys/powerpc/powerpc/trap.c | 35 +++++----- 9 files changed, 219 insertions(+), 221 deletions(-) create mode 100644 sys/powerpc/include/ieeefp.h create mode 100644 sys/powerpc/powerpc/fpu.c (limited to 'sys/powerpc') diff --git a/sys/powerpc/aim/machdep.c b/sys/powerpc/aim/machdep.c index 1330e0f..ac35d8f 100644 --- a/sys/powerpc/aim/machdep.c +++ b/sys/powerpc/aim/machdep.c @@ -350,6 +350,7 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, char *args) bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize); bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize); bcopy(&trapcode, (void *)EXC_SC, (size_t)&trapsize); + bcopy(&trapcode, (void *)EXC_FPU, (size_t)&trapsize); /* * Start initializing proc0 and thread0. @@ -960,93 +961,3 @@ cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz) pcpu->pc_current_asngen = 1; } - -void -enable_fpu(struct pcb *pcb) -{ - int msr, scratch; - - if (!(pcb->pcb_flags & PCB_FPU)) { - bzero(&pcb->pcb_fpu, sizeof pcb->pcb_fpu); - pcb->pcb_flags |= PCB_FPU; - } - __asm volatile ("mfmsr %0; ori %1,%0,%2; mtmsr %1; isync" - : "=r"(msr), "=r"(scratch) : "K"(PSL_FP)); - __asm volatile ("lfd 0,0(%0); mtfsf 0xff,0" :: "b"(&pcb->pcb_fpu.fpscr)); - __asm ("lfd 0,0(%0);" - "lfd 1,8(%0);" - "lfd 2,16(%0);" - "lfd 3,24(%0);" - "lfd 4,32(%0);" - "lfd 5,40(%0);" - "lfd 6,48(%0);" - "lfd 7,56(%0);" - "lfd 8,64(%0);" - "lfd 9,72(%0);" - "lfd 10,80(%0);" - "lfd 11,88(%0);" - "lfd 12,96(%0);" - "lfd 13,104(%0);" - "lfd 14,112(%0);" - "lfd 15,120(%0);" - "lfd 16,128(%0);" - "lfd 17,136(%0);" - "lfd 18,144(%0);" - "lfd 19,152(%0);" - "lfd 20,160(%0);" - "lfd 21,168(%0);" - "lfd 22,176(%0);" - "lfd 23,184(%0);" - "lfd 24,192(%0);" - "lfd 25,200(%0);" - "lfd 26,208(%0);" - "lfd 27,216(%0);" - "lfd 28,224(%0);" - "lfd 29,232(%0);" - "lfd 30,240(%0);" - "lfd 31,248(%0)" :: "b"(&pcb->pcb_fpu.fpr[0])); - __asm volatile ("mtmsr %0; isync" :: "r"(msr)); -} - -void -save_fpu(struct pcb *pcb) -{ - int msr, scratch; - - __asm volatile ("mfmsr %0; ori %1,%0,%2; mtmsr %1; isync" - : "=r"(msr), "=r"(scratch) : "K"(PSL_FP)); - __asm ("stfd 0,0(%0);" - "stfd 1,8(%0);" - "stfd 2,16(%0);" - "stfd 3,24(%0);" - "stfd 4,32(%0);" - "stfd 5,40(%0);" - "stfd 6,48(%0);" - "stfd 7,56(%0);" - "stfd 8,64(%0);" - "stfd 9,72(%0);" - "stfd 10,80(%0);" - "stfd 11,88(%0);" - "stfd 12,96(%0);" - "stfd 13,104(%0);" - "stfd 14,112(%0);" - "stfd 15,120(%0);" - "stfd 16,128(%0);" - "stfd 17,136(%0);" - "stfd 18,144(%0);" - "stfd 19,152(%0);" - "stfd 20,160(%0);" - "stfd 21,168(%0);" - "stfd 22,176(%0);" - "stfd 23,184(%0);" - "stfd 24,192(%0);" - "stfd 25,200(%0);" - "stfd 26,208(%0);" - "stfd 27,216(%0);" - "stfd 28,224(%0);" - "stfd 29,232(%0);" - "stfd 30,240(%0);" - "stfd 31,248(%0)" :: "b"(&pcb->pcb_fpu.fpr[0])); - __asm volatile ("mffs 0; stfd 0,0(%0)" :: "b"(&pcb->pcb_fpu.fpscr)); - __asm volatile ("mtmsr %0; isync" :: "r"(msr)); -} diff --git a/sys/powerpc/aim/trap.c b/sys/powerpc/aim/trap.c index 13f8646..cdceed3 100644 --- a/sys/powerpc/aim/trap.c +++ b/sys/powerpc/aim/trap.c @@ -94,11 +94,14 @@ int setfault(faultbuf); /* defined in locore.S */ int badaddr(void *, size_t); int badaddr_read(void *, size_t, int *); +extern char *syscallnames[]; + void trap(frame) struct trapframe *frame; { struct thread *td = PCPU_GET(curthread); + struct thread *fputhread; struct proc *p = td->td_proc; int type = frame->exc; int ftype, rv; @@ -363,24 +366,15 @@ syscall_bad: break; case EXC_FPU|EXC_USER: -#if 0 - curcpu()->ci_ev_fpu.ev_count++; -#endif -#if 0 - if (fpuproc) { - curcpu()->ci_ev_fpusw.ev_count++; - save_fpu(fpuproc); + if ((fputhread = PCPU_GET(fputhread)) != NULL) { + KASSERT(fputhread != td, + ("floating-point already enabled")); + save_fpu(fputhread); } -#endif -#if defined(MULTIPROCESSOR) - if (p->p_addr->u_pcb.pcb_fpcpu) - save_fpu_proc(p); -#endif -#if 0 - fpuproc = p; - p->p_addr->u_pcb.pcb_fpcpu = curcpu(); - enable_fpu(p); -#endif + PCPU_SET(fputhread, td); + td->td_pcb->pcb_fpcpu = PCPU_GET(cpuid); + enable_fpu(td); + frame->srr1 |= PSL_FP; break; #ifdef ALTIVEC @@ -483,6 +477,7 @@ brain_damage2: panic("trap"); } +#if 0 /* Take pending signals. */ { int sig; @@ -490,15 +485,15 @@ brain_damage2: while ((sig = CURSIG(p)) != 0) postsig(sig); } +#endif /* * If someone stole the fp or vector unit while we were away, * disable it */ -#if 0 - if (p != fpuproc || p->p_addr->u_pcb.pcb_fpcpu != curcpu()) + if (td != PCPU_GET(fputhread) || + td->td_pcb->pcb_fpcpu != PCPU_GET(cpuid)) frame->srr1 &= ~PSL_FP; -#endif #ifdef ALTIVEC if (p != vecproc) frame->srr1 &= ~PSL_VEC; diff --git a/sys/powerpc/include/fpu.h b/sys/powerpc/include/fpu.h index 1f23caa..c01637b 100644 --- a/sys/powerpc/include/fpu.h +++ b/sys/powerpc/include/fpu.h @@ -68,4 +68,15 @@ #define FPSCR_NI 0x00000004 #define FPSCR_RN 0x00000003 +#ifdef _KERNEL + +/* List of PowerPC architectures that support FPUs. */ +#if defined(MPC750) +#define PPC_HAVE_FPU + +void enable_fpu(struct thread *); +void save_fpu(struct thread *); +#endif /* PPC_HAVE_FPU */ +#endif /* _KERNEL */ + #endif /* _MACHINE_FPU_H_ */ diff --git a/sys/powerpc/include/ieeefp.h b/sys/powerpc/include/ieeefp.h new file mode 100644 index 0000000..42701e2 --- /dev/null +++ b/sys/powerpc/include/ieeefp.h @@ -0,0 +1,25 @@ +/* + * Written by J.T. Conklin, Apr 6, 1995 + * Public domain. + * $NetBSD: ieeefp.h,v 1.2 1999/07/07 01:52:26 danw Exp $ + * $FreeBSD$ + */ + +#ifndef _MACHINE_IEEEFP_H_ +#define _MACHINE_IEEEFP_H_ + +typedef int fp_except_t; +#define FP_X_IMP 0x01 /* imprecise (loss of precision) */ +#define FP_X_DZ 0x02 /* divide-by-zero exception */ +#define FP_X_UFL 0x04 /* underflow exception */ +#define FP_X_OFL 0x08 /* overflow exception */ +#define FP_X_INV 0x10 /* invalid operation exception */ + +typedef enum { + FP_RN=0, /* round to nearest representable number */ + FP_RZ=1, /* round to zero (truncate) */ + FP_RP=2, /* round toward positive infinity */ + FP_RM=3 /* round toward negative infinity */ +} fp_rnd_t; + +#endif /* _MACHINE_IEEEFP_H_ */ diff --git a/sys/powerpc/include/pcb.h b/sys/powerpc/include/pcb.h index fbd7cbf..41ec35c 100644 --- a/sys/powerpc/include/pcb.h +++ b/sys/powerpc/include/pcb.h @@ -52,6 +52,8 @@ struct pcb { double fpr[32]; double fpscr; /* FPSCR stored as double for easier access */ } pcb_fpu; /* Floating point processor */ + unsigned int pcb_fpcpu; /* which CPU had our FPU + stuff. */ }; struct md_coredump { diff --git a/sys/powerpc/include/pcpu.h b/sys/powerpc/include/pcpu.h index c222ee0..a2c88c4 100644 --- a/sys/powerpc/include/pcpu.h +++ b/sys/powerpc/include/pcpu.h @@ -39,7 +39,8 @@ struct pmap; int pc_inside_intr; \ u_int32_t pc_next_asn; /* next ASN to alloc */ \ u_int32_t pc_current_asngen; /* ASN rollover check */\ - struct pmap *pc_curpmap /* current pmap */ + struct pmap *pc_curpmap; /* current pmap */ \ + struct thread *pc_fputhread /* current user of the fpu */ #define PCPUP ((struct pcpu *) powerpc_get_pcpup()) diff --git a/sys/powerpc/powerpc/fpu.c b/sys/powerpc/powerpc/fpu.c new file mode 100644 index 0000000..b82d09f --- /dev/null +++ b/sys/powerpc/powerpc/fpu.c @@ -0,0 +1,147 @@ +/* + * Copyright (C) 1996 Wolfgang Solfrank. + * Copyright (C) 1996 TooLs GmbH. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by TooLs GmbH. + * 4. The name of TooLs GmbH may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $NetBSD: fpu.c,v 1.5 2001/07/22 11:29:46 wiz Exp $ */ + */ + +#ifndef lint +static const char rcsid[] = + "$FreeBSD$"; +#endif /* not lint */ + +#include +#include +#include +#include + +#include +#include + +void +enable_fpu(struct thread *td) +{ + int msr, scratch; + struct pcb *pcb; + struct trapframe *tf; + + pcb = td->td_pcb; + tf = trapframe(td); + + tf->srr1 |= PSL_FP; + if (!(pcb->pcb_flags & PCB_FPU)) { + memset(&pcb->pcb_fpu, 0, sizeof pcb->pcb_fpu); + pcb->pcb_flags |= PCB_FPU; + } + __asm __volatile ("mfmsr %0; ori %1,%0,%2; mtmsr %1; isync" + : "=r"(msr), "=r"(scratch) : "K"(PSL_FP)); + __asm __volatile ("lfd 0,0(%0); mtfsf 0xff,0" + :: "b"(&pcb->pcb_fpu.fpscr)); + __asm ("lfd 0,0(%0);" + "lfd 1,8(%0);" + "lfd 2,16(%0);" + "lfd 3,24(%0);" + "lfd 4,32(%0);" + "lfd 5,40(%0);" + "lfd 6,48(%0);" + "lfd 7,56(%0);" + "lfd 8,64(%0);" + "lfd 9,72(%0);" + "lfd 10,80(%0);" + "lfd 11,88(%0);" + "lfd 12,96(%0);" + "lfd 13,104(%0);" + "lfd 14,112(%0);" + "lfd 15,120(%0);" + "lfd 16,128(%0);" + "lfd 17,136(%0);" + "lfd 18,144(%0);" + "lfd 19,152(%0);" + "lfd 20,160(%0);" + "lfd 21,168(%0);" + "lfd 22,176(%0);" + "lfd 23,184(%0);" + "lfd 24,192(%0);" + "lfd 25,200(%0);" + "lfd 26,208(%0);" + "lfd 27,216(%0);" + "lfd 28,224(%0);" + "lfd 29,232(%0);" + "lfd 30,240(%0);" + "lfd 31,248(%0)" :: "b"(&pcb->pcb_fpu.fpr[0])); + __asm __volatile ("mtmsr %0; isync" :: "r"(msr)); +} + +void +save_fpu(struct thread *td) +{ + int msr, scratch; + struct pcb *pcb; + + pcb = td->td_pcb; + + __asm __volatile ("mfmsr %0; ori %1,%0,%2; mtmsr %1; isync" + : "=r"(msr), "=r"(scratch) : "K"(PSL_FP)); + __asm ("stfd 0,0(%0);" + "stfd 1,8(%0);" + "stfd 2,16(%0);" + "stfd 3,24(%0);" + "stfd 4,32(%0);" + "stfd 5,40(%0);" + "stfd 6,48(%0);" + "stfd 7,56(%0);" + "stfd 8,64(%0);" + "stfd 9,72(%0);" + "stfd 10,80(%0);" + "stfd 11,88(%0);" + "stfd 12,96(%0);" + "stfd 13,104(%0);" + "stfd 14,112(%0);" + "stfd 15,120(%0);" + "stfd 16,128(%0);" + "stfd 17,136(%0);" + "stfd 18,144(%0);" + "stfd 19,152(%0);" + "stfd 20,160(%0);" + "stfd 21,168(%0);" + "stfd 22,176(%0);" + "stfd 23,184(%0);" + "stfd 24,192(%0);" + "stfd 25,200(%0);" + "stfd 26,208(%0);" + "stfd 27,216(%0);" + "stfd 28,224(%0);" + "stfd 29,232(%0);" + "stfd 30,240(%0);" + "stfd 31,248(%0)" :: "b"(&pcb->pcb_fpu.fpr[0])); + __asm __volatile ("mffs 0; stfd 0,0(%0)" :: "b"(&pcb->pcb_fpu.fpscr)); + __asm __volatile ("mtmsr %0; isync" :: "r"(msr)); + pcb->pcb_fpcpu = NULL; + PCPU_SET(fputhread, NULL); +} diff --git a/sys/powerpc/powerpc/machdep.c b/sys/powerpc/powerpc/machdep.c index 1330e0f..ac35d8f 100644 --- a/sys/powerpc/powerpc/machdep.c +++ b/sys/powerpc/powerpc/machdep.c @@ -350,6 +350,7 @@ powerpc_init(u_int startkernel, u_int endkernel, u_int basekernel, char *args) bcopy(&dsitrap, (void *)EXC_DSI, (size_t)&dsisize); bcopy(&isitrap, (void *)EXC_ISI, (size_t)&isisize); bcopy(&trapcode, (void *)EXC_SC, (size_t)&trapsize); + bcopy(&trapcode, (void *)EXC_FPU, (size_t)&trapsize); /* * Start initializing proc0 and thread0. @@ -960,93 +961,3 @@ cpu_pcpu_init(struct pcpu *pcpu, int cpuid, size_t sz) pcpu->pc_current_asngen = 1; } - -void -enable_fpu(struct pcb *pcb) -{ - int msr, scratch; - - if (!(pcb->pcb_flags & PCB_FPU)) { - bzero(&pcb->pcb_fpu, sizeof pcb->pcb_fpu); - pcb->pcb_flags |= PCB_FPU; - } - __asm volatile ("mfmsr %0; ori %1,%0,%2; mtmsr %1; isync" - : "=r"(msr), "=r"(scratch) : "K"(PSL_FP)); - __asm volatile ("lfd 0,0(%0); mtfsf 0xff,0" :: "b"(&pcb->pcb_fpu.fpscr)); - __asm ("lfd 0,0(%0);" - "lfd 1,8(%0);" - "lfd 2,16(%0);" - "lfd 3,24(%0);" - "lfd 4,32(%0);" - "lfd 5,40(%0);" - "lfd 6,48(%0);" - "lfd 7,56(%0);" - "lfd 8,64(%0);" - "lfd 9,72(%0);" - "lfd 10,80(%0);" - "lfd 11,88(%0);" - "lfd 12,96(%0);" - "lfd 13,104(%0);" - "lfd 14,112(%0);" - "lfd 15,120(%0);" - "lfd 16,128(%0);" - "lfd 17,136(%0);" - "lfd 18,144(%0);" - "lfd 19,152(%0);" - "lfd 20,160(%0);" - "lfd 21,168(%0);" - "lfd 22,176(%0);" - "lfd 23,184(%0);" - "lfd 24,192(%0);" - "lfd 25,200(%0);" - "lfd 26,208(%0);" - "lfd 27,216(%0);" - "lfd 28,224(%0);" - "lfd 29,232(%0);" - "lfd 30,240(%0);" - "lfd 31,248(%0)" :: "b"(&pcb->pcb_fpu.fpr[0])); - __asm volatile ("mtmsr %0; isync" :: "r"(msr)); -} - -void -save_fpu(struct pcb *pcb) -{ - int msr, scratch; - - __asm volatile ("mfmsr %0; ori %1,%0,%2; mtmsr %1; isync" - : "=r"(msr), "=r"(scratch) : "K"(PSL_FP)); - __asm ("stfd 0,0(%0);" - "stfd 1,8(%0);" - "stfd 2,16(%0);" - "stfd 3,24(%0);" - "stfd 4,32(%0);" - "stfd 5,40(%0);" - "stfd 6,48(%0);" - "stfd 7,56(%0);" - "stfd 8,64(%0);" - "stfd 9,72(%0);" - "stfd 10,80(%0);" - "stfd 11,88(%0);" - "stfd 12,96(%0);" - "stfd 13,104(%0);" - "stfd 14,112(%0);" - "stfd 15,120(%0);" - "stfd 16,128(%0);" - "stfd 17,136(%0);" - "stfd 18,144(%0);" - "stfd 19,152(%0);" - "stfd 20,160(%0);" - "stfd 21,168(%0);" - "stfd 22,176(%0);" - "stfd 23,184(%0);" - "stfd 24,192(%0);" - "stfd 25,200(%0);" - "stfd 26,208(%0);" - "stfd 27,216(%0);" - "stfd 28,224(%0);" - "stfd 29,232(%0);" - "stfd 30,240(%0);" - "stfd 31,248(%0)" :: "b"(&pcb->pcb_fpu.fpr[0])); - __asm volatile ("mffs 0; stfd 0,0(%0)" :: "b"(&pcb->pcb_fpu.fpscr)); - __asm volatile ("mtmsr %0; isync" :: "r"(msr)); -} diff --git a/sys/powerpc/powerpc/trap.c b/sys/powerpc/powerpc/trap.c index 13f8646..cdceed3 100644 --- a/sys/powerpc/powerpc/trap.c +++ b/sys/powerpc/powerpc/trap.c @@ -94,11 +94,14 @@ int setfault(faultbuf); /* defined in locore.S */ int badaddr(void *, size_t); int badaddr_read(void *, size_t, int *); +extern char *syscallnames[]; + void trap(frame) struct trapframe *frame; { struct thread *td = PCPU_GET(curthread); + struct thread *fputhread; struct proc *p = td->td_proc; int type = frame->exc; int ftype, rv; @@ -363,24 +366,15 @@ syscall_bad: break; case EXC_FPU|EXC_USER: -#if 0 - curcpu()->ci_ev_fpu.ev_count++; -#endif -#if 0 - if (fpuproc) { - curcpu()->ci_ev_fpusw.ev_count++; - save_fpu(fpuproc); + if ((fputhread = PCPU_GET(fputhread)) != NULL) { + KASSERT(fputhread != td, + ("floating-point already enabled")); + save_fpu(fputhread); } -#endif -#if defined(MULTIPROCESSOR) - if (p->p_addr->u_pcb.pcb_fpcpu) - save_fpu_proc(p); -#endif -#if 0 - fpuproc = p; - p->p_addr->u_pcb.pcb_fpcpu = curcpu(); - enable_fpu(p); -#endif + PCPU_SET(fputhread, td); + td->td_pcb->pcb_fpcpu = PCPU_GET(cpuid); + enable_fpu(td); + frame->srr1 |= PSL_FP; break; #ifdef ALTIVEC @@ -483,6 +477,7 @@ brain_damage2: panic("trap"); } +#if 0 /* Take pending signals. */ { int sig; @@ -490,15 +485,15 @@ brain_damage2: while ((sig = CURSIG(p)) != 0) postsig(sig); } +#endif /* * If someone stole the fp or vector unit while we were away, * disable it */ -#if 0 - if (p != fpuproc || p->p_addr->u_pcb.pcb_fpcpu != curcpu()) + if (td != PCPU_GET(fputhread) || + td->td_pcb->pcb_fpcpu != PCPU_GET(cpuid)) frame->srr1 &= ~PSL_FP; -#endif #ifdef ALTIVEC if (p != vecproc) frame->srr1 &= ~PSL_VEC; -- cgit v1.1