locore.s revision 1.78 1 1.78 thorpej /* $NetBSD: locore.s,v 1.78 2024/01/17 12:33:51 thorpej 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.1 gwr /*
424 1.1 gwr * Interrupt handlers. Most are auto-vectored,
425 1.1 gwr * and hard-wired the same way on all sun3 models.
426 1.1 gwr * Format in the stack is:
427 1.45 chs * %d0,%d1,%a0,%a1, sr, pc, vo
428 1.1 gwr */
429 1.1 gwr
430 1.1 gwr /* clock: see clock.c */
431 1.46 kleink #ifdef __ELF__
432 1.46 kleink .align 4
433 1.46 kleink #else
434 1.1 gwr .align 2
435 1.46 kleink #endif
436 1.19 jeremy GLOBAL(_isr_clock)
437 1.1 gwr INTERRUPT_SAVEREG
438 1.19 jeremy jbsr _C_LABEL(clock_intr)
439 1.65 christos INTERRUPT_RESTOREREG
440 1.19 jeremy jra _ASM_LABEL(rei)
441 1.1 gwr
442 1.1 gwr /*
443 1.1 gwr * Emulation of VAX REI instruction.
444 1.1 gwr *
445 1.1 gwr * This code is (mostly) un-altered from the hp300 code,
446 1.1 gwr * except that sun machines do not need a simulated SIR
447 1.1 gwr * because they have a real software interrupt register.
448 1.1 gwr *
449 1.1 gwr * This code deals with checking for and servicing ASTs
450 1.1 gwr * (profiling, scheduling) and software interrupts (network, softclock).
451 1.1 gwr * We check for ASTs first, just like the VAX. To avoid excess overhead
452 1.1 gwr * the T_ASTFLT handling code will also check for software interrupts so we
453 1.1 gwr * do not have to do it here. After identifying that we need an AST we
454 1.1 gwr * drop the IPL to allow device interrupts.
455 1.1 gwr *
456 1.1 gwr * This code is complicated by the fact that sendsig may have been called
457 1.1 gwr * necessitating a stack cleanup.
458 1.1 gwr */
459 1.1 gwr
460 1.19 jeremy ASGLOBAL(rei)
461 1.1 gwr #ifdef DIAGNOSTIC
462 1.69 andvar tstl _C_LABEL(panicstr) | have we panicked?
463 1.1 gwr jne Ldorte | yes, do not make matters worse
464 1.1 gwr #endif
465 1.19 jeremy tstl _C_LABEL(astpending) | AST pending?
466 1.1 gwr jeq Ldorte | no, done
467 1.1 gwr Lrei1:
468 1.45 chs btst #5,%sp@ | yes, are we returning to user mode?
469 1.1 gwr jne Ldorte | no, done
470 1.45 chs movw #PSL_LOWIPL,%sr | lower SPL
471 1.45 chs clrl %sp@- | stack adjust
472 1.45 chs moveml #0xFFFF,%sp@- | save all registers
473 1.45 chs movl %usp,%a1 | including
474 1.45 chs movl %a1,%sp@(FR_SP) | the users SP
475 1.45 chs clrl %sp@- | VA == none
476 1.45 chs clrl %sp@- | code == none
477 1.45 chs movl #T_ASTFLT,%sp@- | type == async system trap
478 1.56 tsutsui pea %sp@(12) | fp == address of trap frame
479 1.19 jeremy jbsr _C_LABEL(trap) | go handle it
480 1.56 tsutsui lea %sp@(16),%sp | pop value args
481 1.45 chs movl %sp@(FR_SP),%a0 | restore user SP
482 1.45 chs movl %a0,%usp | from save area
483 1.45 chs movw %sp@(FR_ADJ),%d0 | need to adjust stack?
484 1.1 gwr jne Laststkadj | yes, go to it
485 1.45 chs moveml %sp@+,#0x7FFF | no, restore most user regs
486 1.45 chs addql #8,%sp | toss SP and stack adjust
487 1.1 gwr rte | and do real RTE
488 1.1 gwr Laststkadj:
489 1.45 chs lea %sp@(FR_HW),%a1 | pointer to HW frame
490 1.45 chs addql #8,%a1 | source pointer
491 1.45 chs movl %a1,%a0 | source
492 1.45 chs addw %d0,%a0 | + hole size = dest pointer
493 1.45 chs movl %a1@-,%a0@- | copy
494 1.45 chs movl %a1@-,%a0@- | 8 bytes
495 1.45 chs movl %a0,%sp@(FR_SP) | new SSP
496 1.45 chs moveml %sp@+,#0x7FFF | restore user registers
497 1.45 chs movl %sp@,%sp | and our SP
498 1.1 gwr Ldorte:
499 1.1 gwr rte | real return
500 1.1 gwr
501 1.1 gwr /*
502 1.1 gwr * Initialization is at the beginning of this file, because the
503 1.1 gwr * kernel entry point needs to be at zero for compatibility with
504 1.1 gwr * the Sun boot loader. This works on Sun machines because the
505 1.1 gwr * interrupt vector table for reset is NOT at address zero.
506 1.1 gwr * (The MMU has a "boot" bit that forces access to the PROM)
507 1.1 gwr */
508 1.1 gwr
509 1.1 gwr /*
510 1.1 gwr * Primitives
511 1.1 gwr */
512 1.1 gwr
513 1.1 gwr /*
514 1.51 thorpej * Use common m68k process/lwp switch and context save subroutines.
515 1.1 gwr */
516 1.51 thorpej #define FPCOPROC /* XXX: Temp. Reqd. */
517 1.51 thorpej #include <m68k/m68k/switch_subr.s>
518 1.1 gwr
519 1.1 gwr
520 1.20 gwr /* suline() */
521 1.1 gwr
522 1.1 gwr #ifdef DEBUG
523 1.1 gwr .data
524 1.19 jeremy ASGLOBAL(fulltflush)
525 1.1 gwr .long 0
526 1.19 jeremy ASGLOBAL(fullcflush)
527 1.1 gwr .long 0
528 1.1 gwr .text
529 1.1 gwr #endif
530 1.1 gwr
531 1.1 gwr ENTRY(ecacheon)
532 1.1 gwr rts
533 1.1 gwr
534 1.1 gwr ENTRY(ecacheoff)
535 1.1 gwr rts
536 1.1 gwr
537 1.1 gwr /*
538 1.1 gwr * Load a new CPU Root Pointer (CRP) into the MMU.
539 1.2 gwr * void loadcrp(struct mmu_rootptr *);
540 1.1 gwr */
541 1.1 gwr ENTRY(loadcrp)
542 1.45 chs movl %sp@(4),%a0 | arg1: &CRP
543 1.45 chs movl #CACHE_CLR,%d0
544 1.45 chs movc %d0,%cacr | invalidate cache(s)
545 1.1 gwr pflusha | flush entire TLB
546 1.45 chs pmove %a0@,%crp | load new user root pointer
547 1.45 chs rts
548 1.45 chs
549 1.45 chs ENTRY(getcrp)
550 1.45 chs movl %sp@(4),%a0 | arg1: &crp
551 1.45 chs pmove %crp,%a0@ | *crpp = %crp
552 1.10 gwr rts
553 1.10 gwr
554 1.10 gwr /*
555 1.10 gwr * Get the physical address of the PTE for a given VA.
556 1.10 gwr */
557 1.10 gwr ENTRY(ptest_addr)
558 1.45 chs movl %sp@(4),%a1 | VA
559 1.45 chs ptestr #5,%a1@,#7,%a0 | %a0 = addr of PTE
560 1.48 scw movl %a0,%d0 | Result in %d0 (not a pointer return)
561 1.1 gwr rts
562 1.1 gwr
563 1.1 gwr /*
564 1.1 gwr * _delay(unsigned N)
565 1.1 gwr * Delay for at least (N/256) microseconds.
566 1.1 gwr * This routine depends on the variable: delay_divisor
567 1.1 gwr * which should be set based on the CPU clock rate.
568 1.26 gwr * XXX: Currently this is set based on the CPU model,
569 1.26 gwr * XXX: but this should be determined at run time...
570 1.1 gwr */
571 1.19 jeremy GLOBAL(_delay)
572 1.45 chs | %d0 = arg = (usecs << 8)
573 1.45 chs movl %sp@(4),%d0
574 1.45 chs | %d1 = delay_divisor;
575 1.45 chs movl _C_LABEL(delay_divisor),%d1
576 1.36 thorpej jra L_delay /* Jump into the loop! */
577 1.36 thorpej
578 1.36 thorpej /*
579 1.36 thorpej * Align the branch target of the loop to a half-line (8-byte)
580 1.36 thorpej * boundary to minimize cache effects. This guarantees both
581 1.36 thorpej * that there will be no prefetch stalls due to cache line burst
582 1.36 thorpej * operations and that the loop will run from a single cache
583 1.36 thorpej * half-line.
584 1.36 thorpej */
585 1.46 kleink #ifdef __ELF__
586 1.36 thorpej .align 8
587 1.46 kleink #else
588 1.46 kleink .align 3
589 1.46 kleink #endif
590 1.1 gwr L_delay:
591 1.45 chs subl %d1,%d0
592 1.1 gwr jgt L_delay
593 1.1 gwr rts
594 1.1 gwr
595 1.1 gwr | Define some addresses, mostly so DDB can print useful info.
596 1.24 gwr | Not using _C_LABEL() here because these symbols are never
597 1.24 gwr | referenced by any C code, and if the leading underscore
598 1.24 gwr | ever goes away, these lines turn into syntax errors...
599 1.61 tsutsui .set _KERNBASE3X,KERNBASE3X
600 1.26 gwr .set _MONSTART,SUN3X_MONSTART
601 1.26 gwr .set _PROM_BASE,SUN3X_PROM_BASE
602 1.26 gwr .set _MONEND,SUN3X_MONEND
603 1.1 gwr
604 1.1 gwr |The end!
605