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