1 /* $NetBSD: armfpe_init.c,v 1.15 2009/03/18 10:22:23 cegger Exp $ */
4 * Copyright (C) 1996 Mark Brinicombe
5 * Copyright (C) 1995 Neil A Carson.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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
35 * RiscBSD kernel project
39 * Stuff needed to interface the ARM floating point emulator module to RiscBSD.
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>
50 #include <sys/malloc.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
[] = {
74 "division by zero (0)",
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.
90 initialise_arm_fpe(void)
94 printf("%s: FPE: %s\n",
95 curcpu()->ci_dev
->dv_xname
, fpe_arm_header
.core_identity_addr
);
96 error
= arm_fpe_boot();
98 printf("%s: FPE boot failed\n", curcpu()->ci_dev
->dv_xname
);
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
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
);
125 /* Now we must do some memory allocation */
127 workspace
= (u_int
)malloc(fpe_arm_header
.workspacelength
, M_DEVBUF
, M_NOWAIT
);
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
);
140 printf("%s: FPA11 found\n", curcpu()->ci_dev
->dv_xname
);
142 printf("%s: no FP hardware found\n",
143 curcpu()->ci_dev
->dv_xname
);
146 printf("fpe id=%08x\n", id
);
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
162 arm_fpe_set_exception_mask(FP_X_DZ
| FP_X_OFL
);
169 * Callback routine from the FPE when instruction emulation completes
173 arm_fpe_postproc(u_int fpframe
, struct trapframe
*frame
)
176 register struct proc
*p
;
179 p
->p_addr
->u_pcb
.pcb_tf
= frame
;
181 /* take pending signals */
183 while ((sig
= (CURSIG(p
))) != 0) {
187 p
->p_priority
= p
->p_usrpri
;
189 if (curcpu()->ci_want_resched
) {
191 * We are being preempted.
194 while ((sig
= (CURSIG(p
))) != 0) {
201 if (p
->p_flag
& P_PROFIL
) {
205 pc
= ReadWord(fpframe
+ 15*4);
207 if (pc
< 0x1000 || pc
> 0xefc00000)
208 panic("armfpe_postproc: pc=%08x", pc
);
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.
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
);
231 printf("fpe exception: unknown (%d)\n", exception
);
233 LWP_CACHE_CREDS(l
, p
);
235 trapsignal(p
, SIGFPE
, exception
<< 8);
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
)
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
)
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 */