Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / arch / arm / fpe-arm / armfpe_init.c
blob8a0b6898327f8be968a3ae0dabb6ee81f9abf95c
1 /* $NetBSD: armfpe_init.c,v 1.15 2009/03/18 10:22:23 cegger Exp $ */
3 /*
4 * Copyright (C) 1996 Mark Brinicombe
5 * Copyright (C) 1995 Neil A Carson.
6 * All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Mark Brinicombe.
19 * 4. The name of the company nor the name of the author may be used to
20 * endorse or promote products derived from this software without specific
21 * prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
35 * RiscBSD kernel project
37 * arm_fpe.c
39 * Stuff needed to interface the ARM floating point emulator module to RiscBSD.
41 * Created : 22/10/95
44 #include <sys/param.h>
46 __KERNEL_RCSID(0, "$NetBSD: armfpe_init.c,v 1.15 2009/03/18 10:22:23 cegger Exp $");
48 #include <sys/systm.h>
49 #include <sys/proc.h>
50 #include <sys/malloc.h>
51 #include <sys/acct.h>
52 #include <uvm/uvm_extern.h>
54 #include <machine/cpu.h>
55 #include <arm/arm32/katelib.h>
56 #include <machine/frame.h>
58 #include <arm/fpe-arm/armfpe.h>
60 extern u_int fpe_nexthandler;
62 extern u_int fpe_arm_start[];
63 extern arm_fpe_mod_hdr_t fpe_arm_header;
64 extern u_int undefined_handler_address;
65 u_int arm_fpe_old_handler_address;
66 u_int arm_fpe_core_workspace;
69 * Error messages for the various exceptions, numbered 0-5
72 static const char *exception_errors[] = {
73 "invalid operation",
74 "division by zero (0)",
75 "overflow",
76 "underflow",
77 "operation inexact",
78 "major faliure... core fault trapped... not good!"
83 * Initialisation point. The kernel calls this during the configuration of
84 * the CPU in order to install the FPE.
85 * The FPE specification needs to be filled in the specified cpu_t structure
86 * and the FPE needs to be installed on the CPU undefined instruction vector.
89 int
90 initialise_arm_fpe(void)
92 int error;
94 printf("%s: FPE: %s\n",
95 curcpu()->ci_dev->dv_xname, fpe_arm_header.core_identity_addr);
96 error = arm_fpe_boot();
97 if (error != 0) {
98 printf("%s: FPE boot failed\n", curcpu()->ci_dev->dv_xname);
99 return(1);
101 return(0);
105 * The actual FPE boot routine.
106 * This has to do a number of things :
107 * 1. Relocate the FPE - Note this requires write access to the kernel text area
108 * 2. Allocated memory for the FPE
109 * 3. Initialise the FPE
113 arm_fpe_boot(void)
115 u_int workspace;
116 int id;
118 #ifdef DEBUG
119 /* Print a bit of debugging info */
120 printf("FPE: base=%08x\n", (u_int)fpe_arm_start);
121 printf("FPE: global workspace size = %d bytes, context size = %d bytes\n",
122 fpe_arm_header.workspacelength, fpe_arm_header.contextlength);
123 #endif
125 /* Now we must do some memory allocation */
127 workspace = (u_int)malloc(fpe_arm_header.workspacelength, M_DEVBUF, M_NOWAIT);
128 if (!workspace)
129 return(ENOMEM);
131 arm_fpe_core_workspace = workspace;
132 arm_fpe_old_handler_address = undefined_handler_address;
134 /* Initialise out gloable workspace */
136 id = arm_fpe_core_initws(workspace, (u_int)&fpe_nexthandler,
137 (u_int)&fpe_nexthandler);
139 if (id == 0x81)
140 printf("%s: FPA11 found\n", curcpu()->ci_dev->dv_xname);
141 else
142 printf("%s: no FP hardware found\n",
143 curcpu()->ci_dev->dv_xname);
145 #ifdef DEBUG
146 printf("fpe id=%08x\n", id);
147 #endif
149 /* Initialise proc0's FPE context and select it */
151 arm_fpe_core_initcontext(FP_CONTEXT(&proc0));
152 arm_fpe_core_changecontext(FP_CONTEXT(&proc0));
155 * Set the default excpection mask. This will be inherited on
156 * a fork when the context is copied.
158 * XXX - The is done with FP instructions - the only ones in
159 * the kernel
162 arm_fpe_set_exception_mask(FP_X_DZ | FP_X_OFL);
164 return(0);
169 * Callback routine from the FPE when instruction emulation completes
172 void
173 arm_fpe_postproc(u_int fpframe, struct trapframe *frame)
175 register int sig;
176 register struct proc *p;
178 p = curproc;
179 p->p_addr->u_pcb.pcb_tf = frame;
181 /* take pending signals */
183 while ((sig = (CURSIG(p))) != 0) {
184 postsig(sig);
187 p->p_priority = p->p_usrpri;
189 if (curcpu()->ci_want_resched) {
191 * We are being preempted.
193 preempt();
194 while ((sig = (CURSIG(p))) != 0) {
195 postsig(sig);
199 /* Profiling. */
201 if (p->p_flag & P_PROFIL) {
202 extern int psratio;
203 u_int pc;
205 pc = ReadWord(fpframe + 15*4);
206 #ifdef DIAGNOSTIC
207 if (pc < 0x1000 || pc > 0xefc00000)
208 panic("armfpe_postproc: pc=%08x", pc);
209 #endif
210 addupc_task(p, pc, (int)(p->p_sticks - p->p_sticks) * psratio);
213 curcpu()->ci_schedstate.spc_curpriority = p->p_priority;
218 * Callback routine from the FPE when an exception occurs.
221 void
222 arm_fpe_exception(int exception, u_int fpframe, struct trapframe *frame)
224 struct lwp *l = curlwp;
225 struct proc *p = l->l_proc;
227 if (exception >= 0 && exception < 6)
228 printf("fpe exception: %s (%d)\n",
229 exception_errors[exception], exception);
230 else
231 printf("fpe exception: unknown (%d)\n", exception);
233 LWP_CACHE_CREDS(l, p);
235 trapsignal(p, SIGFPE, exception << 8);
237 userret(p);
241 void
242 arm_fpe_copycontext(u_int c1, u_int c2)
244 fp_context_frame_t fpcontext;
246 arm_fpe_core_savecontext(c1, &fpcontext, 0);
247 arm_fpe_core_loadcontext(c2, &fpcontext);
251 * Warning the arm_fpe_getcontext() and arm_fpe_setcontext() functions
252 * rely on the fact that the fp_context_frame_t type is structurally the
253 * same as struct fpreg and thus can just cast the pointer.
254 * If a change is made to either then a tempoary buffer will be needed
255 * and the structure members copied indiviually.
258 void arm_fpe_getcontext(p, fpregs)
259 struct proc *p;
260 struct fpreg *fpregs;
262 arm_fpe_core_savecontext(FP_CONTEXT(p), (fp_context_frame_t *)fpregs, 0);
265 void arm_fpe_setcontext(p, fpregs)
266 struct proc *p;
267 const struct fpreg *fpregs;
269 arm_fpe_core_loadcontext(FP_CONTEXT(p), (const fp_context_frame_t *)fpregs);
272 /* End of armfpe_init.c */