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