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