locore.s revision 1.69 1 1.69 andvar /* $NetBSD: locore.s,v 1.69 2022/03/16 20:31:02 andvar 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 /* interrupt counters (needed by vmstat) */
474 1.19 jeremy GLOBAL(intrnames)
475 1.1 gwr .asciz "spur" | 0
476 1.1 gwr .asciz "lev1" | 1
477 1.1 gwr .asciz "lev2" | 2
478 1.1 gwr .asciz "lev3" | 3
479 1.1 gwr .asciz "lev4" | 4
480 1.1 gwr .asciz "clock" | 5
481 1.1 gwr .asciz "lev6" | 6
482 1.1 gwr .asciz "nmi" | 7
483 1.19 jeremy GLOBAL(eintrnames)
484 1.1 gwr
485 1.1 gwr .data
486 1.1 gwr .even
487 1.19 jeremy GLOBAL(intrcnt)
488 1.68 simonb .long 0,0,0,0,0,0,0,0
489 1.19 jeremy GLOBAL(eintrcnt)
490 1.1 gwr .text
491 1.1 gwr
492 1.1 gwr /*
493 1.1 gwr * Emulation of VAX REI instruction.
494 1.1 gwr *
495 1.1 gwr * This code is (mostly) un-altered from the hp300 code,
496 1.1 gwr * except that sun machines do not need a simulated SIR
497 1.1 gwr * because they have a real software interrupt register.
498 1.1 gwr *
499 1.1 gwr * This code deals with checking for and servicing ASTs
500 1.1 gwr * (profiling, scheduling) and software interrupts (network, softclock).
501 1.1 gwr * We check for ASTs first, just like the VAX. To avoid excess overhead
502 1.1 gwr * the T_ASTFLT handling code will also check for software interrupts so we
503 1.1 gwr * do not have to do it here. After identifying that we need an AST we
504 1.1 gwr * drop the IPL to allow device interrupts.
505 1.1 gwr *
506 1.1 gwr * This code is complicated by the fact that sendsig may have been called
507 1.1 gwr * necessitating a stack cleanup.
508 1.1 gwr */
509 1.1 gwr
510 1.19 jeremy ASGLOBAL(rei)
511 1.1 gwr #ifdef DIAGNOSTIC
512 1.69 andvar tstl _C_LABEL(panicstr) | have we panicked?
513 1.1 gwr jne Ldorte | yes, do not make matters worse
514 1.1 gwr #endif
515 1.19 jeremy tstl _C_LABEL(astpending) | AST pending?
516 1.1 gwr jeq Ldorte | no, done
517 1.1 gwr Lrei1:
518 1.45 chs btst #5,%sp@ | yes, are we returning to user mode?
519 1.1 gwr jne Ldorte | no, done
520 1.45 chs movw #PSL_LOWIPL,%sr | lower SPL
521 1.45 chs clrl %sp@- | stack adjust
522 1.45 chs moveml #0xFFFF,%sp@- | save all registers
523 1.45 chs movl %usp,%a1 | including
524 1.45 chs movl %a1,%sp@(FR_SP) | the users SP
525 1.45 chs clrl %sp@- | VA == none
526 1.45 chs clrl %sp@- | code == none
527 1.45 chs movl #T_ASTFLT,%sp@- | type == async system trap
528 1.56 tsutsui pea %sp@(12) | fp == address of trap frame
529 1.19 jeremy jbsr _C_LABEL(trap) | go handle it
530 1.56 tsutsui lea %sp@(16),%sp | pop value args
531 1.45 chs movl %sp@(FR_SP),%a0 | restore user SP
532 1.45 chs movl %a0,%usp | from save area
533 1.45 chs movw %sp@(FR_ADJ),%d0 | need to adjust stack?
534 1.1 gwr jne Laststkadj | yes, go to it
535 1.45 chs moveml %sp@+,#0x7FFF | no, restore most user regs
536 1.45 chs addql #8,%sp | toss SP and stack adjust
537 1.1 gwr rte | and do real RTE
538 1.1 gwr Laststkadj:
539 1.45 chs lea %sp@(FR_HW),%a1 | pointer to HW frame
540 1.45 chs addql #8,%a1 | source pointer
541 1.45 chs movl %a1,%a0 | source
542 1.45 chs addw %d0,%a0 | + hole size = dest pointer
543 1.45 chs movl %a1@-,%a0@- | copy
544 1.45 chs movl %a1@-,%a0@- | 8 bytes
545 1.45 chs movl %a0,%sp@(FR_SP) | new SSP
546 1.45 chs moveml %sp@+,#0x7FFF | restore user registers
547 1.45 chs movl %sp@,%sp | and our SP
548 1.1 gwr Ldorte:
549 1.1 gwr rte | real return
550 1.1 gwr
551 1.1 gwr /*
552 1.1 gwr * Initialization is at the beginning of this file, because the
553 1.1 gwr * kernel entry point needs to be at zero for compatibility with
554 1.1 gwr * the Sun boot loader. This works on Sun machines because the
555 1.1 gwr * interrupt vector table for reset is NOT at address zero.
556 1.1 gwr * (The MMU has a "boot" bit that forces access to the PROM)
557 1.1 gwr */
558 1.1 gwr
559 1.1 gwr /*
560 1.16 thorpej * Use common m68k sigcode.
561 1.1 gwr */
562 1.16 thorpej #include <m68k/m68k/sigcode.s>
563 1.44 jdolecek #ifdef COMPAT_SUNOS
564 1.44 jdolecek #include <m68k/m68k/sunos_sigcode.s>
565 1.44 jdolecek #endif
566 1.16 thorpej
567 1.1 gwr .text
568 1.1 gwr
569 1.1 gwr /*
570 1.1 gwr * Primitives
571 1.1 gwr */
572 1.1 gwr
573 1.1 gwr /*
574 1.12 thorpej * Use common m68k support routines.
575 1.1 gwr */
576 1.12 thorpej #include <m68k/m68k/support.s>
577 1.1 gwr
578 1.1 gwr /*
579 1.51 thorpej * Use common m68k process/lwp switch and context save subroutines.
580 1.1 gwr */
581 1.51 thorpej #define FPCOPROC /* XXX: Temp. Reqd. */
582 1.51 thorpej #include <m68k/m68k/switch_subr.s>
583 1.1 gwr
584 1.1 gwr
585 1.20 gwr /* suline() */
586 1.1 gwr
587 1.1 gwr #ifdef DEBUG
588 1.1 gwr .data
589 1.19 jeremy ASGLOBAL(fulltflush)
590 1.1 gwr .long 0
591 1.19 jeremy ASGLOBAL(fullcflush)
592 1.1 gwr .long 0
593 1.1 gwr .text
594 1.1 gwr #endif
595 1.1 gwr
596 1.1 gwr ENTRY(ecacheon)
597 1.1 gwr rts
598 1.1 gwr
599 1.1 gwr ENTRY(ecacheoff)
600 1.1 gwr rts
601 1.1 gwr
602 1.1 gwr /*
603 1.1 gwr * Get callers current SP value.
604 1.1 gwr * Note that simply taking the address of a local variable in a C function
605 1.1 gwr * doesn't work because callee saved registers may be outside the stack frame
606 1.1 gwr * defined by A6 (e.g. GCC generated code).
607 1.20 gwr *
608 1.1 gwr * [I don't think the ENTRY() macro will do the right thing with this -- glass]
609 1.1 gwr */
610 1.19 jeremy GLOBAL(getsp)
611 1.45 chs movl %sp,%d0 | get current SP
612 1.45 chs addql #4,%d0 | compensate for return address
613 1.45 chs movl %d0,%a0
614 1.1 gwr rts
615 1.1 gwr
616 1.1 gwr ENTRY(getvbr)
617 1.45 chs movc %vbr,%d0
618 1.45 chs movl %d0,%a0
619 1.1 gwr rts
620 1.1 gwr
621 1.1 gwr ENTRY(setvbr)
622 1.45 chs movl %sp@(4),%d0
623 1.45 chs movc %d0,%vbr
624 1.1 gwr rts
625 1.1 gwr
626 1.1 gwr /*
627 1.1 gwr * Load a new CPU Root Pointer (CRP) into the MMU.
628 1.2 gwr * void loadcrp(struct mmu_rootptr *);
629 1.1 gwr */
630 1.1 gwr ENTRY(loadcrp)
631 1.45 chs movl %sp@(4),%a0 | arg1: &CRP
632 1.45 chs movl #CACHE_CLR,%d0
633 1.45 chs movc %d0,%cacr | invalidate cache(s)
634 1.1 gwr pflusha | flush entire TLB
635 1.45 chs pmove %a0@,%crp | load new user root pointer
636 1.45 chs rts
637 1.45 chs
638 1.45 chs ENTRY(getcrp)
639 1.45 chs movl %sp@(4),%a0 | arg1: &crp
640 1.45 chs pmove %crp,%a0@ | *crpp = %crp
641 1.10 gwr rts
642 1.10 gwr
643 1.10 gwr /*
644 1.10 gwr * Get the physical address of the PTE for a given VA.
645 1.10 gwr */
646 1.10 gwr ENTRY(ptest_addr)
647 1.45 chs movl %sp@(4),%a1 | VA
648 1.45 chs ptestr #5,%a1@,#7,%a0 | %a0 = addr of PTE
649 1.48 scw movl %a0,%d0 | Result in %d0 (not a pointer return)
650 1.1 gwr rts
651 1.1 gwr
652 1.1 gwr /*
653 1.1 gwr * Set processor priority level calls. Most are implemented with
654 1.1 gwr * inline asm expansions. However, we need one instantiation here
655 1.1 gwr * in case some non-optimized code makes external references.
656 1.21 gwr * Most places will use the inlined functions param.h supplies.
657 1.1 gwr */
658 1.1 gwr
659 1.21 gwr ENTRY(_getsr)
660 1.45 chs clrl %d0
661 1.45 chs movw %sr,%d0
662 1.45 chs movl %a1,%d0
663 1.21 gwr rts
664 1.21 gwr
665 1.1 gwr ENTRY(_spl)
666 1.45 chs clrl %d0
667 1.45 chs movw %sr,%d0
668 1.45 chs movl %sp@(4),%d1
669 1.45 chs movw %d1,%sr
670 1.1 gwr rts
671 1.1 gwr
672 1.21 gwr ENTRY(_splraise)
673 1.45 chs clrl %d0
674 1.45 chs movw %sr,%d0
675 1.45 chs movl %d0,%d1
676 1.45 chs andl #PSL_HIGHIPL,%d1 | old &= PSL_HIGHIPL
677 1.45 chs cmpl %sp@(4),%d1 | (old - new)
678 1.21 gwr bge Lsplr
679 1.45 chs movl %sp@(4),%d1
680 1.45 chs movw %d1,%sr
681 1.21 gwr Lsplr:
682 1.1 gwr rts
683 1.1 gwr
684 1.1 gwr /*
685 1.1 gwr * _delay(unsigned N)
686 1.1 gwr * Delay for at least (N/256) microseconds.
687 1.1 gwr * This routine depends on the variable: delay_divisor
688 1.1 gwr * which should be set based on the CPU clock rate.
689 1.26 gwr * XXX: Currently this is set based on the CPU model,
690 1.26 gwr * XXX: but this should be determined at run time...
691 1.1 gwr */
692 1.19 jeremy GLOBAL(_delay)
693 1.45 chs | %d0 = arg = (usecs << 8)
694 1.45 chs movl %sp@(4),%d0
695 1.45 chs | %d1 = delay_divisor;
696 1.45 chs movl _C_LABEL(delay_divisor),%d1
697 1.36 thorpej jra L_delay /* Jump into the loop! */
698 1.36 thorpej
699 1.36 thorpej /*
700 1.36 thorpej * Align the branch target of the loop to a half-line (8-byte)
701 1.36 thorpej * boundary to minimize cache effects. This guarantees both
702 1.36 thorpej * that there will be no prefetch stalls due to cache line burst
703 1.36 thorpej * operations and that the loop will run from a single cache
704 1.36 thorpej * half-line.
705 1.36 thorpej */
706 1.46 kleink #ifdef __ELF__
707 1.36 thorpej .align 8
708 1.46 kleink #else
709 1.46 kleink .align 3
710 1.46 kleink #endif
711 1.1 gwr L_delay:
712 1.45 chs subl %d1,%d0
713 1.1 gwr jgt L_delay
714 1.1 gwr rts
715 1.1 gwr
716 1.1 gwr | Define some addresses, mostly so DDB can print useful info.
717 1.24 gwr | Not using _C_LABEL() here because these symbols are never
718 1.24 gwr | referenced by any C code, and if the leading underscore
719 1.24 gwr | ever goes away, these lines turn into syntax errors...
720 1.61 tsutsui .set _KERNBASE3X,KERNBASE3X
721 1.26 gwr .set _MONSTART,SUN3X_MONSTART
722 1.26 gwr .set _PROM_BASE,SUN3X_PROM_BASE
723 1.26 gwr .set _MONEND,SUN3X_MONEND
724 1.1 gwr
725 1.1 gwr |The end!
726