locore.s revision 1.60 1 1.60 skrll /* $NetBSD: locore.s,v 1.60 2010/02/25 07:21:20 skrll Exp $ */
2 1.1 gwr
3 1.1 gwr /*
4 1.1 gwr * Copyright (c) 1980, 1990, 1993
5 1.1 gwr * The Regents of the University of California. All rights reserved.
6 1.52 agc *
7 1.52 agc * This code is derived from software contributed to Berkeley by
8 1.52 agc * the Systems Programming Group of the University of Utah Computer
9 1.52 agc * Science Department.
10 1.52 agc *
11 1.52 agc * Redistribution and use in source and binary forms, with or without
12 1.52 agc * modification, are permitted provided that the following conditions
13 1.52 agc * are met:
14 1.52 agc * 1. Redistributions of source code must retain the above copyright
15 1.52 agc * notice, this list of conditions and the following disclaimer.
16 1.52 agc * 2. Redistributions in binary form must reproduce the above copyright
17 1.52 agc * notice, this list of conditions and the following disclaimer in the
18 1.52 agc * documentation and/or other materials provided with the distribution.
19 1.52 agc * 3. Neither the name of the University nor the names of its contributors
20 1.52 agc * may be used to endorse or promote products derived from this software
21 1.52 agc * without specific prior written permission.
22 1.52 agc *
23 1.52 agc * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 1.52 agc * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 1.52 agc * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 1.52 agc * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 1.52 agc * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 1.52 agc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 1.52 agc * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 1.52 agc * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 1.52 agc * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 1.52 agc * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 1.52 agc * SUCH DAMAGE.
34 1.52 agc *
35 1.52 agc * from: Utah $Hdr: locore.s 1.66 92/12/22$
36 1.52 agc * @(#)locore.s 8.6 (Berkeley) 5/27/94
37 1.52 agc */
38 1.52 agc /*
39 1.52 agc * Copyright (c) 1988 University of Utah.
40 1.1 gwr *
41 1.1 gwr * This code is derived from software contributed to Berkeley by
42 1.1 gwr * the Systems Programming Group of the University of Utah Computer
43 1.1 gwr * Science Department.
44 1.1 gwr *
45 1.1 gwr * Redistribution and use in source and binary forms, with or without
46 1.1 gwr * modification, are permitted provided that the following conditions
47 1.1 gwr * are met:
48 1.1 gwr * 1. Redistributions of source code must retain the above copyright
49 1.1 gwr * notice, this list of conditions and the following disclaimer.
50 1.1 gwr * 2. Redistributions in binary form must reproduce the above copyright
51 1.1 gwr * notice, this list of conditions and the following disclaimer in the
52 1.1 gwr * documentation and/or other materials provided with the distribution.
53 1.1 gwr * 3. All advertising materials mentioning features or use of this software
54 1.1 gwr * must display the following acknowledgement:
55 1.1 gwr * This product includes software developed by the University of
56 1.1 gwr * California, Berkeley and its contributors.
57 1.1 gwr * 4. Neither the name of the University nor the names of its contributors
58 1.1 gwr * may be used to endorse or promote products derived from this software
59 1.1 gwr * without specific prior written permission.
60 1.1 gwr *
61 1.1 gwr * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
62 1.1 gwr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
63 1.1 gwr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
64 1.1 gwr * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
65 1.1 gwr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
66 1.1 gwr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
67 1.1 gwr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
68 1.1 gwr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
69 1.1 gwr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
70 1.1 gwr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
71 1.1 gwr * SUCH DAMAGE.
72 1.1 gwr *
73 1.1 gwr * from: Utah $Hdr: locore.s 1.66 92/12/22$
74 1.1 gwr * @(#)locore.s 8.6 (Berkeley) 5/27/94
75 1.1 gwr */
76 1.1 gwr
77 1.29 thorpej #include "opt_compat_netbsd.h"
78 1.34 kleink #include "opt_compat_svr4.h"
79 1.35 christos #include "opt_compat_sunos.h"
80 1.47 lukem #include "opt_kgdb.h"
81 1.42 thorpej #include "opt_lockdebug.h"
82 1.27 gwr
83 1.1 gwr #include "assym.h"
84 1.17 thorpej #include <machine/asm.h>
85 1.1 gwr #include <machine/trap.h>
86 1.1 gwr
87 1.1 gwr | Remember this is a fun project!
88 1.1 gwr
89 1.1 gwr .data
90 1.19 jeremy GLOBAL(mon_crp)
91 1.1 gwr .long 0,0
92 1.1 gwr
93 1.1 gwr | This is for kvm_mkdb, and should be the address of the beginning
94 1.1 gwr | of the kernel text segment (not necessarily the same as kernbase).
95 1.1 gwr .text
96 1.19 jeremy GLOBAL(kernel_text)
97 1.1 gwr
98 1.1 gwr | This is the entry point, as well as the end of the temporary stack
99 1.1 gwr | used during process switch (one 8K page ending at start)
100 1.19 jeremy ASGLOBAL(tmpstk)
101 1.20 gwr ASGLOBAL(start)
102 1.19 jeremy
103 1.1 gwr | The first step, after disabling interrupts, is to map enough of the kernel
104 1.1 gwr | into high virtual address space so that we can use position dependent code.
105 1.1 gwr | This is a tricky task on the sun3x because the MMU is already enabled and
106 1.1 gwr | the ROM monitor provides no indication of where the root MMU table is mapped.
107 1.1 gwr | Therefore we must use one of the 68030's 'transparent translation' registers
108 1.1 gwr | to define a range in the address space where the MMU translation is
109 1.1 gwr | turned off. Once this is complete we can modify the MMU table directly
110 1.1 gwr | without the need for it to be mapped into virtual memory.
111 1.1 gwr | All code must be position independent until otherwise noted, as the
112 1.1 gwr | boot loader has loaded us into low memory but all the symbols in this
113 1.1 gwr | code have been linked high.
114 1.45 chs movw #PSL_HIGHIPL,%sr | no interrupts
115 1.45 chs movl #KERNBASE,%a5 | for vtop conversion
116 1.45 chs lea _C_LABEL(mon_crp),%a0 | where to store the CRP
117 1.45 chs subl %a5,%a0
118 1.1 gwr | Note: borrowing mon_crp for tt0 setup...
119 1.45 chs movl #0x3F8107,%a0@ | map the low 1GB v=p with the
120 1.14 jeremy .long 0xf0100800 | transparent translation reg0
121 1.14 jeremy | [ pmove a0@, tt0 ]
122 1.1 gwr | In order to map the kernel into high memory we will copy the root table
123 1.1 gwr | entry which maps the 16 megabytes of memory starting at 0x0 into the
124 1.1 gwr | entry which maps the 16 megabytes starting at KERNBASE.
125 1.45 chs pmove %crp,%a0@ | Get monitor CPU root pointer
126 1.45 chs movl %a0@(4),%a1 | 2nd word is PA of level A table
127 1.1 gwr
128 1.45 chs movl %a1,%a0 | compute the descriptor address
129 1.45 chs addl #0x3e0,%a1 | for VA starting at KERNBASE
130 1.45 chs movl %a0@,%a1@ | copy descriptor type
131 1.45 chs movl %a0@(4),%a1@(4) | copy physical address
132 1.1 gwr
133 1.1 gwr | Kernel is now double mapped at zero and KERNBASE.
134 1.1 gwr | Force a long jump to the relocated code (high VA).
135 1.45 chs movl #IC_CLEAR,%d0 | Flush the I-cache
136 1.45 chs movc %d0,%cacr
137 1.1 gwr jmp L_high_code:l | long jump
138 1.1 gwr
139 1.1 gwr L_high_code:
140 1.1 gwr | We are now running in the correctly relocated kernel, so
141 1.1 gwr | we are no longer restricted to position-independent code.
142 1.1 gwr | It is handy to leave transparent translation enabled while
143 1.20 gwr | for the low 1GB while _bootstrap() is doing its thing.
144 1.1 gwr
145 1.1 gwr | Do bootstrap stuff needed before main() gets called.
146 1.1 gwr | Our boot loader leaves a copy of the kernel's exec header
147 1.1 gwr | just before the start of the kernel text segment, so the
148 1.1 gwr | kernel can sanity-check the DDB symbols at [end...esym].
149 1.20 gwr | Pass the struct exec at tmpstk-32 to _bootstrap().
150 1.7 gwr | Also, make sure the initial frame pointer is zero so that
151 1.7 gwr | the backtrace algorithm used by KGDB terminates nicely.
152 1.45 chs lea _ASM_LABEL(tmpstk)-32,%sp
153 1.45 chs movl #0,%a6
154 1.26 gwr jsr _C_LABEL(_bootstrap) | See locore2.c
155 1.1 gwr
156 1.1 gwr | Now turn off the transparent translation of the low 1GB.
157 1.1 gwr | (this also flushes the ATC)
158 1.45 chs clrl %sp@-
159 1.14 jeremy .long 0xf0170800 | pmove sp@,tt0
160 1.45 chs addql #4,%sp
161 1.1 gwr
162 1.20 gwr | Now that _bootstrap() is done using the PROM functions,
163 1.1 gwr | we can safely set the sfc/dfc to something != FC_CONTROL
164 1.45 chs moveq #FC_USERD,%d0 | make movs access "user data"
165 1.45 chs movc %d0,%sfc | space for copyin/copyout
166 1.45 chs movc %d0,%dfc
167 1.1 gwr
168 1.1 gwr | Setup process zero user/kernel stacks.
169 1.58 matt lea _C_LABEL(lwp0),%a0 | get lwp0
170 1.59 rmind movl %a0@(L_PCB),%a1 | XXXuvm_lwp_getuarea
171 1.45 chs lea %a1@(USPACE-4),%sp | set SSP to last word
172 1.45 chs movl #USRSTACK-4,%a2
173 1.45 chs movl %a2,%usp | init user SP
174 1.1 gwr
175 1.20 gwr | Note curpcb was already set in _bootstrap().
176 1.1 gwr | Will do fpu initialization during autoconfig (see fpu.c)
177 1.1 gwr | The interrupt vector table and stack are now ready.
178 1.1 gwr | Interrupts will be enabled later, AFTER autoconfiguration
179 1.1 gwr | is finished, to avoid spurrious interrupts.
180 1.1 gwr
181 1.1 gwr /*
182 1.60 skrll * Create a fake exception frame so that cpu_lwp_fork() can copy it.
183 1.49 chs * main() nevers returns; we exit to user mode from a forked process
184 1.49 chs * later on.
185 1.1 gwr */
186 1.45 chs clrw %sp@- | tf_format,tf_vector
187 1.45 chs clrl %sp@- | tf_pc (filled in later)
188 1.45 chs movw #PSL_USER,%sp@- | tf_sr for user mode
189 1.45 chs clrl %sp@- | tf_stackadj
190 1.45 chs lea %sp@(-64),%sp | tf_regs[16]
191 1.58 matt movl %a1,%a0@(L_MD_REGS) | lwp0.l_md.md_regs = trapframe
192 1.19 jeremy jbsr _C_LABEL(main) | main(&trapframe)
193 1.49 chs PANIC("main() returned")
194 1.1 gwr
195 1.1 gwr | That is all the assembly startup code we need on the sun3x!
196 1.1 gwr | The rest of this is like the hp300/locore.s where possible.
197 1.1 gwr
198 1.1 gwr /*
199 1.1 gwr * Trap/interrupt vector routines
200 1.1 gwr */
201 1.17 thorpej #include <m68k/m68k/trap_subr.s>
202 1.1 gwr
203 1.19 jeremy GLOBAL(buserr)
204 1.19 jeremy tstl _C_LABEL(nofault) | device probe?
205 1.19 jeremy jeq _C_LABEL(addrerr) | no, handle as usual
206 1.45 chs movl _C_LABEL(nofault),%sp@- | yes,
207 1.19 jeremy jbsr _C_LABEL(longjmp) | longjmp(nofault)
208 1.19 jeremy GLOBAL(addrerr)
209 1.45 chs clrl %sp@- | stack adjust count
210 1.45 chs moveml #0xFFFF,%sp@- | save user registers
211 1.45 chs movl %usp,%a0 | save the user SP
212 1.45 chs movl %a0,%sp@(FR_SP) | in the savearea
213 1.45 chs lea %sp@(FR_HW),%a1 | grab base of HW berr frame
214 1.45 chs moveq #0,%d0
215 1.45 chs movw %a1@(10),%d0 | grab SSW for fault processing
216 1.45 chs btst #12,%d0 | RB set?
217 1.1 gwr jeq LbeX0 | no, test RC
218 1.45 chs bset #14,%d0 | yes, must set FB
219 1.45 chs movw %d0,%a1@(10) | for hardware too
220 1.1 gwr LbeX0:
221 1.45 chs btst #13,%d0 | RC set?
222 1.1 gwr jeq LbeX1 | no, skip
223 1.45 chs bset #15,%d0 | yes, must set FC
224 1.45 chs movw %d0,%a1@(10) | for hardware too
225 1.1 gwr LbeX1:
226 1.45 chs btst #8,%d0 | data fault?
227 1.1 gwr jeq Lbe0 | no, check for hard cases
228 1.45 chs movl %a1@(16),%d1 | fault address is as given in frame
229 1.1 gwr jra Lbe10 | thats it
230 1.1 gwr Lbe0:
231 1.45 chs btst #4,%a1@(6) | long (type B) stack frame?
232 1.1 gwr jne Lbe4 | yes, go handle
233 1.45 chs movl %a1@(2),%d1 | no, can use save PC
234 1.45 chs btst #14,%d0 | FB set?
235 1.1 gwr jeq Lbe3 | no, try FC
236 1.45 chs addql #4,%d1 | yes, adjust address
237 1.1 gwr jra Lbe10 | done
238 1.1 gwr Lbe3:
239 1.45 chs btst #15,%d0 | FC set?
240 1.1 gwr jeq Lbe10 | no, done
241 1.45 chs addql #2,%d1 | yes, adjust address
242 1.1 gwr jra Lbe10 | done
243 1.1 gwr Lbe4:
244 1.45 chs movl %a1@(36),%d1 | long format, use stage B address
245 1.45 chs btst #15,%d0 | FC set?
246 1.1 gwr jeq Lbe10 | no, all done
247 1.45 chs subql #2,%d1 | yes, adjust address
248 1.1 gwr Lbe10:
249 1.45 chs movl %d1,%sp@- | push fault VA
250 1.45 chs movl %d0,%sp@- | and padded SSW
251 1.45 chs movw %a1@(6),%d0 | get frame format/vector offset
252 1.45 chs andw #0x0FFF,%d0 | clear out frame format
253 1.45 chs cmpw #12,%d0 | address error vector?
254 1.1 gwr jeq Lisaerr | yes, go to it
255 1.1 gwr
256 1.1 gwr /* MMU-specific code to determine reason for bus error. */
257 1.45 chs movl %d1,%a0 | fault address
258 1.45 chs movl %sp@,%d0 | function code from ssw
259 1.45 chs btst #8,%d0 | data fault?
260 1.1 gwr jne Lbe10a
261 1.45 chs movql #1,%d0 | user program access FC
262 1.1 gwr | (we dont separate data/program)
263 1.45 chs btst #5,%a1@ | supervisor mode?
264 1.1 gwr jeq Lbe10a | if no, done
265 1.45 chs movql #5,%d0 | else supervisor program access
266 1.1 gwr Lbe10a:
267 1.45 chs ptestr %d0,%a0@,#7 | do a table search
268 1.45 chs pmove %psr,%sp@ | save result
269 1.45 chs movb %sp@,%d1
270 1.45 chs btst #2,%d1 | invalid? (incl. limit viol and berr)
271 1.1 gwr jeq Lmightnotbemerr | no -> wp check
272 1.45 chs btst #7,%d1 | is it MMU table berr?
273 1.1 gwr jeq Lismerr | no, must be fast
274 1.1 gwr jra Lisberr1 | real bus err needs not be fast
275 1.1 gwr Lmightnotbemerr:
276 1.45 chs btst #3,%d1 | write protect bit set?
277 1.1 gwr jeq Lisberr1 | no, must be bus error
278 1.45 chs movl %sp@,%d0 | ssw into low word of d0
279 1.45 chs andw #0xc0,%d0 | write protect is set on page:
280 1.45 chs cmpw #0x40,%d0 | was it read cycle?
281 1.1 gwr jeq Lisberr1 | yes, was not WPE, must be bus err
282 1.1 gwr /* End of MMU-specific bus error code. */
283 1.1 gwr
284 1.1 gwr Lismerr:
285 1.45 chs movl #T_MMUFLT,%sp@- | show that we are an MMU fault
286 1.17 thorpej jra _ASM_LABEL(faultstkadj) | and deal with it
287 1.1 gwr Lisaerr:
288 1.45 chs movl #T_ADDRERR,%sp@- | mark address error
289 1.17 thorpej jra _ASM_LABEL(faultstkadj) | and deal with it
290 1.1 gwr Lisberr1:
291 1.45 chs clrw %sp@ | re-clear pad word
292 1.1 gwr Lisberr:
293 1.45 chs movl #T_BUSERR,%sp@- | mark bus error
294 1.17 thorpej jra _ASM_LABEL(faultstkadj) | and deal with it
295 1.1 gwr
296 1.1 gwr /*
297 1.1 gwr * FP exceptions.
298 1.1 gwr */
299 1.19 jeremy GLOBAL(fpfline)
300 1.45 chs clrl %sp@- | stack adjust count
301 1.45 chs moveml #0xFFFF,%sp@- | save registers
302 1.45 chs moveq #T_FPEMULI,%d0 | denote as FP emulation trap
303 1.19 jeremy jra _ASM_LABEL(fault) | do it
304 1.1 gwr
305 1.19 jeremy GLOBAL(fpunsupp)
306 1.45 chs clrl %sp@- | stack adjust count
307 1.45 chs moveml #0xFFFF,%sp@- | save registers
308 1.45 chs moveq #T_FPEMULD,%d0 | denote as FP emulation trap
309 1.19 jeremy jra _ASM_LABEL(fault) | do it
310 1.1 gwr
311 1.1 gwr /*
312 1.1 gwr * Handles all other FP coprocessor exceptions.
313 1.1 gwr * Note that since some FP exceptions generate mid-instruction frames
314 1.1 gwr * and may cause signal delivery, we need to test for stack adjustment
315 1.1 gwr * after the trap call.
316 1.1 gwr */
317 1.19 jeremy GLOBAL(fpfault)
318 1.45 chs clrl %sp@- | stack adjust count
319 1.45 chs moveml #0xFFFF,%sp@- | save user registers
320 1.45 chs movl %usp,%a0 | and save
321 1.45 chs movl %a0,%sp@(FR_SP) | the user stack pointer
322 1.45 chs clrl %sp@- | no VA arg
323 1.45 chs movl _C_LABEL(curpcb),%a0 | current pcb
324 1.45 chs lea %a0@(PCB_FPCTX),%a0 | address of FP savearea
325 1.45 chs fsave %a0@ | save state
326 1.45 chs tstb %a0@ | null state frame?
327 1.1 gwr jeq Lfptnull | yes, safe
328 1.45 chs clrw %d0 | no, need to tweak BIU
329 1.45 chs movb %a0@(1),%d0 | get frame size
330 1.45 chs bset #3,%a0@(0,%d0:w) | set exc_pend bit of BIU
331 1.1 gwr Lfptnull:
332 1.45 chs fmovem %fpsr,%sp@- | push fpsr as code argument
333 1.45 chs frestore %a0@ | restore state
334 1.45 chs movl #T_FPERR,%sp@- | push type arg
335 1.17 thorpej jra _ASM_LABEL(faultstkadj) | call trap and deal with stack cleanup
336 1.1 gwr
337 1.1 gwr /*
338 1.1 gwr * Other exceptions only cause four and six word stack frame and require
339 1.1 gwr * no post-trap stack adjustment.
340 1.1 gwr */
341 1.19 jeremy GLOBAL(badtrap)
342 1.45 chs clrl %sp@- | stack adjust count
343 1.45 chs moveml #0xFFFF,%sp@- | save std frame regs
344 1.19 jeremy jbsr _C_LABEL(straytrap) | report
345 1.45 chs moveml %sp@+,#0xFFFF | restore regs
346 1.45 chs addql #4,%sp | stack adjust count
347 1.19 jeremy jra _ASM_LABEL(rei) | all done
348 1.1 gwr
349 1.1 gwr /*
350 1.1 gwr * Trap 0 is for system calls
351 1.1 gwr */
352 1.19 jeremy GLOBAL(trap0)
353 1.45 chs clrl %sp@- | stack adjust count
354 1.45 chs moveml #0xFFFF,%sp@- | save user registers
355 1.45 chs movl %usp,%a0 | save the user SP
356 1.45 chs movl %a0,%sp@(FR_SP) | in the savearea
357 1.45 chs movl %d0,%sp@- | push syscall number
358 1.19 jeremy jbsr _C_LABEL(syscall) | handle it
359 1.45 chs addql #4,%sp | pop syscall arg
360 1.45 chs movl %sp@(FR_SP),%a0 | grab and restore
361 1.45 chs movl %a0,%usp | user SP
362 1.45 chs moveml %sp@+,#0x7FFF | restore most registers
363 1.45 chs addql #8,%sp | pop SP and stack adjust
364 1.19 jeremy jra _ASM_LABEL(rei) | all done
365 1.11 gwr
366 1.11 gwr /*
367 1.11 gwr * Trap 12 is the entry point for the cachectl "syscall"
368 1.11 gwr * cachectl(command, addr, length)
369 1.11 gwr * command in d0, addr in a1, length in d1
370 1.11 gwr */
371 1.19 jeremy GLOBAL(trap12)
372 1.51 thorpej movl _C_LABEL(curlwp),%a0
373 1.51 thorpej movl %a0@(L_PROC),%sp@- | push curproc pointer
374 1.45 chs movl %d1,%sp@- | push length
375 1.45 chs movl %a1,%sp@- | push addr
376 1.45 chs movl %d0,%sp@- | push command
377 1.32 is jbsr _C_LABEL(cachectl1) | do it
378 1.45 chs lea %sp@(16),%sp | pop args
379 1.19 jeremy jra _ASM_LABEL(rei) | all done
380 1.1 gwr
381 1.1 gwr /*
382 1.1 gwr * Trace (single-step) trap. Kernel-mode is special.
383 1.1 gwr * User mode traps are simply passed on to trap().
384 1.1 gwr */
385 1.19 jeremy GLOBAL(trace)
386 1.45 chs clrl %sp@- | stack adjust count
387 1.45 chs moveml #0xFFFF,%sp@-
388 1.45 chs moveq #T_TRACE,%d0
389 1.37 itohy
390 1.37 itohy | Check PSW and see what happen.
391 1.37 itohy | T=0 S=0 (should not happen)
392 1.37 itohy | T=1 S=0 trace trap from user mode
393 1.37 itohy | T=0 S=1 trace trap on a trap instruction
394 1.37 itohy | T=1 S=1 trace trap from system mode (kernel breakpoint)
395 1.37 itohy
396 1.45 chs movw %sp@(FR_HW),%d1 | get PSW
397 1.45 chs notw %d1 | XXX no support for T0 on 680[234]0
398 1.45 chs andw #PSL_TS,%d1 | from system mode (T=1, S=1)?
399 1.37 itohy jeq _ASM_LABEL(kbrkpt) | yes, kernel brkpt
400 1.19 jeremy jra _ASM_LABEL(fault) | no, user-mode fault
401 1.1 gwr
402 1.1 gwr /*
403 1.1 gwr * Trap 15 is used for:
404 1.1 gwr * - GDB breakpoints (in user programs)
405 1.1 gwr * - KGDB breakpoints (in the kernel)
406 1.1 gwr * - trace traps for SUN binaries (not fully supported yet)
407 1.11 gwr * User mode traps are simply passed to trap().
408 1.1 gwr */
409 1.19 jeremy GLOBAL(trap15)
410 1.45 chs clrl %sp@- | stack adjust count
411 1.45 chs moveml #0xFFFF,%sp@-
412 1.45 chs moveq #T_TRAP15,%d0
413 1.45 chs btst #5,%sp@(FR_HW) | was supervisor mode?
414 1.19 jeremy jne _ASM_LABEL(kbrkpt) | yes, kernel brkpt
415 1.19 jeremy jra _ASM_LABEL(fault) | no, user-mode fault
416 1.1 gwr
417 1.19 jeremy ASLOCAL(kbrkpt)
418 1.45 chs | Kernel-mode breakpoint or trace trap. (%d0=trap_type)
419 1.1 gwr | Save the system sp rather than the user sp.
420 1.45 chs movw #PSL_HIGHIPL,%sr | lock out interrupts
421 1.45 chs lea %sp@(FR_SIZE),%a6 | Save stack pointer
422 1.45 chs movl %a6,%sp@(FR_SP) | from before trap
423 1.1 gwr
424 1.1 gwr | If we are not on tmpstk switch to it.
425 1.1 gwr | (so debugger can change the stack pointer)
426 1.45 chs movl %a6,%d1
427 1.45 chs cmpl #_ASM_LABEL(tmpstk),%d1
428 1.1 gwr jls Lbrkpt2 | already on tmpstk
429 1.1 gwr | Copy frame to the temporary stack
430 1.45 chs movl %sp,%a0 | %a0=src
431 1.45 chs lea _ASM_LABEL(tmpstk)-96,%a1 | %a1=dst
432 1.45 chs movl %a1,%sp | sp=new frame
433 1.45 chs moveq #FR_SIZE,%d1
434 1.1 gwr Lbrkpt1:
435 1.45 chs movl %a0@+,%a1@+
436 1.45 chs subql #4,%d1
437 1.1 gwr bgt Lbrkpt1
438 1.1 gwr
439 1.1 gwr Lbrkpt2:
440 1.11 gwr | Call the trap handler for the kernel debugger.
441 1.6 gwr | Do not call trap() to handle it, so that we can
442 1.1 gwr | set breakpoints in trap() if we want. We know
443 1.1 gwr | the trap type is either T_TRACE or T_BREAKPOINT.
444 1.45 chs movl %d0,%sp@- | push trap type
445 1.19 jeremy jbsr _C_LABEL(trap_kdebug)
446 1.45 chs addql #4,%sp | pop args
447 1.6 gwr
448 1.1 gwr | The stack pointer may have been modified, or
449 1.1 gwr | data below it modified (by kgdb push call),
450 1.1 gwr | so push the hardware frame at the current sp
451 1.1 gwr | before restoring registers and returning.
452 1.45 chs movl %sp@(FR_SP),%a0 | modified sp
453 1.45 chs lea %sp@(FR_SIZE),%a1 | end of our frame
454 1.45 chs movl %a1@-,%a0@- | copy 2 longs with
455 1.45 chs movl %a1@-,%a0@- | ... predecrement
456 1.45 chs movl %a0,%sp@(FR_SP) | sp = h/w frame
457 1.45 chs moveml %sp@+,#0x7FFF | restore all but sp
458 1.45 chs movl %sp@,%sp | ... and sp
459 1.1 gwr rte | all done
460 1.1 gwr
461 1.11 gwr /* Use common m68k sigreturn */
462 1.11 gwr #include <m68k/m68k/sigreturn.s>
463 1.1 gwr
464 1.1 gwr /*
465 1.1 gwr * Interrupt handlers. Most are auto-vectored,
466 1.1 gwr * and hard-wired the same way on all sun3 models.
467 1.1 gwr * Format in the stack is:
468 1.45 chs * %d0,%d1,%a0,%a1, sr, pc, vo
469 1.1 gwr */
470 1.1 gwr
471 1.1 gwr #define INTERRUPT_SAVEREG \
472 1.45 chs moveml #0xC0C0,%sp@-
473 1.1 gwr
474 1.1 gwr #define INTERRUPT_RESTORE \
475 1.45 chs moveml %sp@+,#0x0303
476 1.1 gwr
477 1.1 gwr /*
478 1.1 gwr * This is the common auto-vector interrupt handler,
479 1.1 gwr * for which the CPU provides the vector=0x18+level.
480 1.1 gwr * These are installed in the interrupt vector table.
481 1.1 gwr */
482 1.46 kleink #ifdef __ELF__
483 1.46 kleink .align 4
484 1.46 kleink #else
485 1.1 gwr .align 2
486 1.46 kleink #endif
487 1.19 jeremy GLOBAL(_isr_autovec)
488 1.1 gwr INTERRUPT_SAVEREG
489 1.19 jeremy jbsr _C_LABEL(isr_autovec)
490 1.1 gwr INTERRUPT_RESTORE
491 1.19 jeremy jra _ASM_LABEL(rei)
492 1.1 gwr
493 1.1 gwr /* clock: see clock.c */
494 1.46 kleink #ifdef __ELF__
495 1.46 kleink .align 4
496 1.46 kleink #else
497 1.1 gwr .align 2
498 1.46 kleink #endif
499 1.19 jeremy GLOBAL(_isr_clock)
500 1.1 gwr INTERRUPT_SAVEREG
501 1.19 jeremy jbsr _C_LABEL(clock_intr)
502 1.1 gwr INTERRUPT_RESTORE
503 1.19 jeremy jra _ASM_LABEL(rei)
504 1.1 gwr
505 1.1 gwr | Handler for all vectored interrupts (i.e. VME interrupts)
506 1.46 kleink #ifdef __ELF__
507 1.46 kleink .align 4
508 1.46 kleink #else
509 1.1 gwr .align 2
510 1.46 kleink #endif
511 1.19 jeremy GLOBAL(_isr_vectored)
512 1.1 gwr INTERRUPT_SAVEREG
513 1.19 jeremy jbsr _C_LABEL(isr_vectored)
514 1.1 gwr INTERRUPT_RESTORE
515 1.19 jeremy jra _ASM_LABEL(rei)
516 1.1 gwr
517 1.1 gwr #undef INTERRUPT_SAVEREG
518 1.1 gwr #undef INTERRUPT_RESTORE
519 1.1 gwr
520 1.1 gwr /* interrupt counters (needed by vmstat) */
521 1.19 jeremy GLOBAL(intrnames)
522 1.1 gwr .asciz "spur" | 0
523 1.1 gwr .asciz "lev1" | 1
524 1.1 gwr .asciz "lev2" | 2
525 1.1 gwr .asciz "lev3" | 3
526 1.1 gwr .asciz "lev4" | 4
527 1.1 gwr .asciz "clock" | 5
528 1.1 gwr .asciz "lev6" | 6
529 1.1 gwr .asciz "nmi" | 7
530 1.19 jeremy GLOBAL(eintrnames)
531 1.1 gwr
532 1.1 gwr .data
533 1.1 gwr .even
534 1.19 jeremy GLOBAL(intrcnt)
535 1.1 gwr .long 0,0,0,0,0,0,0,0,0,0
536 1.19 jeremy GLOBAL(eintrcnt)
537 1.1 gwr .text
538 1.1 gwr
539 1.1 gwr /*
540 1.1 gwr * Emulation of VAX REI instruction.
541 1.1 gwr *
542 1.1 gwr * This code is (mostly) un-altered from the hp300 code,
543 1.1 gwr * except that sun machines do not need a simulated SIR
544 1.1 gwr * because they have a real software interrupt register.
545 1.1 gwr *
546 1.1 gwr * This code deals with checking for and servicing ASTs
547 1.1 gwr * (profiling, scheduling) and software interrupts (network, softclock).
548 1.1 gwr * We check for ASTs first, just like the VAX. To avoid excess overhead
549 1.1 gwr * the T_ASTFLT handling code will also check for software interrupts so we
550 1.1 gwr * do not have to do it here. After identifying that we need an AST we
551 1.1 gwr * drop the IPL to allow device interrupts.
552 1.1 gwr *
553 1.1 gwr * This code is complicated by the fact that sendsig may have been called
554 1.1 gwr * necessitating a stack cleanup.
555 1.1 gwr */
556 1.1 gwr
557 1.19 jeremy ASGLOBAL(rei)
558 1.1 gwr #ifdef DIAGNOSTIC
559 1.19 jeremy tstl _C_LABEL(panicstr) | have we paniced?
560 1.1 gwr jne Ldorte | yes, do not make matters worse
561 1.1 gwr #endif
562 1.19 jeremy tstl _C_LABEL(astpending) | AST pending?
563 1.1 gwr jeq Ldorte | no, done
564 1.1 gwr Lrei1:
565 1.45 chs btst #5,%sp@ | yes, are we returning to user mode?
566 1.1 gwr jne Ldorte | no, done
567 1.45 chs movw #PSL_LOWIPL,%sr | lower SPL
568 1.45 chs clrl %sp@- | stack adjust
569 1.45 chs moveml #0xFFFF,%sp@- | save all registers
570 1.45 chs movl %usp,%a1 | including
571 1.45 chs movl %a1,%sp@(FR_SP) | the users SP
572 1.45 chs clrl %sp@- | VA == none
573 1.45 chs clrl %sp@- | code == none
574 1.45 chs movl #T_ASTFLT,%sp@- | type == async system trap
575 1.56 tsutsui pea %sp@(12) | fp == address of trap frame
576 1.19 jeremy jbsr _C_LABEL(trap) | go handle it
577 1.56 tsutsui lea %sp@(16),%sp | pop value args
578 1.45 chs movl %sp@(FR_SP),%a0 | restore user SP
579 1.45 chs movl %a0,%usp | from save area
580 1.45 chs movw %sp@(FR_ADJ),%d0 | need to adjust stack?
581 1.1 gwr jne Laststkadj | yes, go to it
582 1.45 chs moveml %sp@+,#0x7FFF | no, restore most user regs
583 1.45 chs addql #8,%sp | toss SP and stack adjust
584 1.1 gwr rte | and do real RTE
585 1.1 gwr Laststkadj:
586 1.45 chs lea %sp@(FR_HW),%a1 | pointer to HW frame
587 1.45 chs addql #8,%a1 | source pointer
588 1.45 chs movl %a1,%a0 | source
589 1.45 chs addw %d0,%a0 | + hole size = dest pointer
590 1.45 chs movl %a1@-,%a0@- | copy
591 1.45 chs movl %a1@-,%a0@- | 8 bytes
592 1.45 chs movl %a0,%sp@(FR_SP) | new SSP
593 1.45 chs moveml %sp@+,#0x7FFF | restore user registers
594 1.45 chs movl %sp@,%sp | and our SP
595 1.1 gwr Ldorte:
596 1.1 gwr rte | real return
597 1.1 gwr
598 1.1 gwr /*
599 1.1 gwr * Initialization is at the beginning of this file, because the
600 1.1 gwr * kernel entry point needs to be at zero for compatibility with
601 1.1 gwr * the Sun boot loader. This works on Sun machines because the
602 1.1 gwr * interrupt vector table for reset is NOT at address zero.
603 1.1 gwr * (The MMU has a "boot" bit that forces access to the PROM)
604 1.1 gwr */
605 1.1 gwr
606 1.1 gwr /*
607 1.16 thorpej * Use common m68k sigcode.
608 1.1 gwr */
609 1.16 thorpej #include <m68k/m68k/sigcode.s>
610 1.44 jdolecek #ifdef COMPAT_SUNOS
611 1.44 jdolecek #include <m68k/m68k/sunos_sigcode.s>
612 1.44 jdolecek #endif
613 1.44 jdolecek #ifdef COMPAT_SVR4
614 1.44 jdolecek #include <m68k/m68k/svr4_sigcode.s>
615 1.44 jdolecek #endif
616 1.16 thorpej
617 1.1 gwr .text
618 1.1 gwr
619 1.1 gwr /*
620 1.1 gwr * Primitives
621 1.1 gwr */
622 1.1 gwr
623 1.1 gwr /*
624 1.12 thorpej * Use common m68k support routines.
625 1.1 gwr */
626 1.12 thorpej #include <m68k/m68k/support.s>
627 1.1 gwr
628 1.1 gwr /*
629 1.51 thorpej * Use common m68k process/lwp switch and context save subroutines.
630 1.1 gwr */
631 1.51 thorpej #define FPCOPROC /* XXX: Temp. Reqd. */
632 1.51 thorpej #include <m68k/m68k/switch_subr.s>
633 1.1 gwr
634 1.1 gwr
635 1.20 gwr /* suline() */
636 1.1 gwr
637 1.1 gwr #ifdef DEBUG
638 1.1 gwr .data
639 1.19 jeremy ASGLOBAL(fulltflush)
640 1.1 gwr .long 0
641 1.19 jeremy ASGLOBAL(fullcflush)
642 1.1 gwr .long 0
643 1.1 gwr .text
644 1.1 gwr #endif
645 1.1 gwr
646 1.1 gwr ENTRY(ecacheon)
647 1.1 gwr rts
648 1.1 gwr
649 1.1 gwr ENTRY(ecacheoff)
650 1.1 gwr rts
651 1.1 gwr
652 1.1 gwr /*
653 1.1 gwr * Get callers current SP value.
654 1.1 gwr * Note that simply taking the address of a local variable in a C function
655 1.1 gwr * doesn't work because callee saved registers may be outside the stack frame
656 1.1 gwr * defined by A6 (e.g. GCC generated code).
657 1.20 gwr *
658 1.1 gwr * [I don't think the ENTRY() macro will do the right thing with this -- glass]
659 1.1 gwr */
660 1.19 jeremy GLOBAL(getsp)
661 1.45 chs movl %sp,%d0 | get current SP
662 1.45 chs addql #4,%d0 | compensate for return address
663 1.45 chs movl %d0,%a0
664 1.1 gwr rts
665 1.1 gwr
666 1.1 gwr ENTRY(getsfc)
667 1.45 chs movc %sfc,%d0
668 1.45 chs movl %d0,%a0
669 1.1 gwr rts
670 1.1 gwr
671 1.1 gwr ENTRY(getdfc)
672 1.45 chs movc %dfc,%d0
673 1.45 chs movl %d0,%a0
674 1.1 gwr rts
675 1.1 gwr
676 1.1 gwr ENTRY(getvbr)
677 1.45 chs movc %vbr,%d0
678 1.45 chs movl %d0,%a0
679 1.1 gwr rts
680 1.1 gwr
681 1.1 gwr ENTRY(setvbr)
682 1.45 chs movl %sp@(4),%d0
683 1.45 chs movc %d0,%vbr
684 1.1 gwr rts
685 1.1 gwr
686 1.1 gwr /*
687 1.1 gwr * Load a new CPU Root Pointer (CRP) into the MMU.
688 1.2 gwr * void loadcrp(struct mmu_rootptr *);
689 1.1 gwr */
690 1.1 gwr ENTRY(loadcrp)
691 1.45 chs movl %sp@(4),%a0 | arg1: &CRP
692 1.45 chs movl #CACHE_CLR,%d0
693 1.45 chs movc %d0,%cacr | invalidate cache(s)
694 1.1 gwr pflusha | flush entire TLB
695 1.45 chs pmove %a0@,%crp | load new user root pointer
696 1.45 chs rts
697 1.45 chs
698 1.45 chs ENTRY(getcrp)
699 1.45 chs movl %sp@(4),%a0 | arg1: &crp
700 1.45 chs pmove %crp,%a0@ | *crpp = %crp
701 1.10 gwr rts
702 1.10 gwr
703 1.10 gwr /*
704 1.10 gwr * Get the physical address of the PTE for a given VA.
705 1.10 gwr */
706 1.10 gwr ENTRY(ptest_addr)
707 1.45 chs movl %sp@(4),%a1 | VA
708 1.45 chs ptestr #5,%a1@,#7,%a0 | %a0 = addr of PTE
709 1.48 scw movl %a0,%d0 | Result in %d0 (not a pointer return)
710 1.1 gwr rts
711 1.1 gwr
712 1.1 gwr /*
713 1.1 gwr * Set processor priority level calls. Most are implemented with
714 1.1 gwr * inline asm expansions. However, we need one instantiation here
715 1.1 gwr * in case some non-optimized code makes external references.
716 1.21 gwr * Most places will use the inlined functions param.h supplies.
717 1.1 gwr */
718 1.1 gwr
719 1.21 gwr ENTRY(_getsr)
720 1.45 chs clrl %d0
721 1.45 chs movw %sr,%d0
722 1.45 chs movl %a1,%d0
723 1.21 gwr rts
724 1.21 gwr
725 1.1 gwr ENTRY(_spl)
726 1.45 chs clrl %d0
727 1.45 chs movw %sr,%d0
728 1.45 chs movl %sp@(4),%d1
729 1.45 chs movw %d1,%sr
730 1.1 gwr rts
731 1.1 gwr
732 1.21 gwr ENTRY(_splraise)
733 1.45 chs clrl %d0
734 1.45 chs movw %sr,%d0
735 1.45 chs movl %d0,%d1
736 1.45 chs andl #PSL_HIGHIPL,%d1 | old &= PSL_HIGHIPL
737 1.45 chs cmpl %sp@(4),%d1 | (old - new)
738 1.21 gwr bge Lsplr
739 1.45 chs movl %sp@(4),%d1
740 1.45 chs movw %d1,%sr
741 1.21 gwr Lsplr:
742 1.1 gwr rts
743 1.1 gwr
744 1.1 gwr /*
745 1.1 gwr * Save and restore 68881 state.
746 1.1 gwr */
747 1.1 gwr ENTRY(m68881_save)
748 1.45 chs movl %sp@(4),%a0 | save area pointer
749 1.45 chs fsave %a0@ | save state
750 1.45 chs tstb %a0@ | null state frame?
751 1.1 gwr jeq Lm68881sdone | yes, all done
752 1.45 chs fmovem %fp0-%fp7,%a0@(FPF_REGS) | save FP general regs
753 1.45 chs fmovem %fpcr/%fpsr/%fpi,%a0@(FPF_FPCR) | save FP control regs
754 1.1 gwr Lm68881sdone:
755 1.1 gwr rts
756 1.1 gwr
757 1.1 gwr ENTRY(m68881_restore)
758 1.45 chs movl %sp@(4),%a0 | save area pointer
759 1.45 chs tstb %a0@ | null state frame?
760 1.1 gwr jeq Lm68881rdone | yes, easy
761 1.45 chs fmovem %a0@(FPF_FPCR),%fpcr/%fpsr/%fpi | restore FP control regs
762 1.45 chs fmovem %a0@(FPF_REGS),%fp0-%fp7 | restore FP general regs
763 1.1 gwr Lm68881rdone:
764 1.45 chs frestore %a0@ | restore state
765 1.1 gwr rts
766 1.1 gwr
767 1.1 gwr /*
768 1.1 gwr * _delay(unsigned N)
769 1.1 gwr * Delay for at least (N/256) microseconds.
770 1.1 gwr * This routine depends on the variable: delay_divisor
771 1.1 gwr * which should be set based on the CPU clock rate.
772 1.26 gwr * XXX: Currently this is set based on the CPU model,
773 1.26 gwr * XXX: but this should be determined at run time...
774 1.1 gwr */
775 1.19 jeremy GLOBAL(_delay)
776 1.45 chs | %d0 = arg = (usecs << 8)
777 1.45 chs movl %sp@(4),%d0
778 1.45 chs | %d1 = delay_divisor;
779 1.45 chs movl _C_LABEL(delay_divisor),%d1
780 1.36 thorpej jra L_delay /* Jump into the loop! */
781 1.36 thorpej
782 1.36 thorpej /*
783 1.36 thorpej * Align the branch target of the loop to a half-line (8-byte)
784 1.36 thorpej * boundary to minimize cache effects. This guarantees both
785 1.36 thorpej * that there will be no prefetch stalls due to cache line burst
786 1.36 thorpej * operations and that the loop will run from a single cache
787 1.36 thorpej * half-line.
788 1.36 thorpej */
789 1.46 kleink #ifdef __ELF__
790 1.36 thorpej .align 8
791 1.46 kleink #else
792 1.46 kleink .align 3
793 1.46 kleink #endif
794 1.1 gwr L_delay:
795 1.45 chs subl %d1,%d0
796 1.1 gwr jgt L_delay
797 1.1 gwr rts
798 1.1 gwr
799 1.1 gwr | Define some addresses, mostly so DDB can print useful info.
800 1.24 gwr | Not using _C_LABEL() here because these symbols are never
801 1.24 gwr | referenced by any C code, and if the leading underscore
802 1.24 gwr | ever goes away, these lines turn into syntax errors...
803 1.24 gwr .set _KERNBASE,KERNBASE
804 1.26 gwr .set _MONSTART,SUN3X_MONSTART
805 1.26 gwr .set _PROM_BASE,SUN3X_PROM_BASE
806 1.26 gwr .set _MONEND,SUN3X_MONEND
807 1.1 gwr
808 1.1 gwr |The end!
809