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