📄 locore.s
字号:
/* @(#)locore.s 1.1 92/07/30 *//* * Copyright (c) 1986 by Sun Microsystems, Inc. */#include "assym.s"#include <sys/errno.h>#include <sys/param.h>#include <machine/asm_linkage.h>#include <machine/reg.h>#include <machine/mmu.h>#include <machine/psl.h>#include <machine/pte.h>#include <machine/enable.h>#include <machine/cpu.h>#include <machine/trap.h>#include <machine/eeprom.h>#include "../../debug/debug.h"/* * The debug stack. This must be the first thing in the data * segment (other than an sccs string) so that we don't stomp * on anything important. We get a red zone below this stack * for free when the text is write protected. */#define STACK_SIZE 0x8000 .seg "data" .global _estack .skip STACK_SIZE_estack: ! end (top) of debugger stackfpuregs: .skip 33*4 ! %f0 - %f31 plus %fsr/* * The number of windows, set by fiximp when machine is booted. */ .global _nwindows/* * The parent callback routine. */ .global _release_parent_release_parent: .word 0 .seg "text"/* * Trap vector macros. */#define TRAP(H) \ b (H); mov %psr,%l0; nop; nop;/* * The constant in the last expression must be (nwindows-1). * See fiximp() below. */#define WIN_TRAP(H) \ mov %psr,%l0; mov %wim,%l3; b (H); mov 7,%l6;#define SYS_TRAP(T) \ mov %psr,%l0; sethi %hi(T),%l3; b sys_trap; or %l3,%lo(T),%l3;#define BAD_TRAP SYS_TRAP(_fault);/* * Trap vector table. * This must be the first text in the boot image. * * When a trap is taken, we vector to DEBUGSTART+(TT*16) and we have * the following state: * 2) traps are disabled * 3) the previous state of PSR_S is in PSR_PS * 4) the CWP has been decremented into the trap window * 5) the previous pc and npc is in %l1 and %l2 respectively. * * Registers: * %l0 - %psr immediately after trap * %l1 - trapped pc * %l2 - trapped npc * %l3 - trap handler pointer (sys_trap only) * or current %wim (win_trap only) * %l6 - NW-1, for wim calculations (win_trap only) * * Note: DEBUGGER receives control at vector 0 (trap). */ .seg "text" .align 4 .global _our_die_routine .global _start, _scb_start:_scb: TRAP(enter); ! 00 BAD_TRAP; ! 01 text fault BAD_TRAP; ! 02 unimp instruction BAD_TRAP; ! 03 priv instruction TRAP(_fp_disabled); ! 04 fp disabled WIN_TRAP(_window_overflow); ! 05 WIN_TRAP(_window_underflow); ! 06 BAD_TRAP; ! 07 alignment BAD_TRAP; ! 08 fp exception SYS_TRAP(_fault); ! 09 data fault BAD_TRAP; ! 0A tag_overflow BAD_TRAP; BAD_TRAP; ! 0B - 0C BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 0D - 10 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 11 - 14 int 1-4 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 15 - 18 int 5-8 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 19 - 1C int 9-12 BAD_TRAP; BAD_TRAP; ! 1D - 1E int 13-14 SYS_TRAP(_level15); ! 1F int 15 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 20 - 23 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 24 - 27 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 28 - 2B BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 2C - 2F BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 30 - 34 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 34 - 37 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 38 - 3B BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 3C - 3F BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 40 - 44 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 44 - 47 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 48 - 4B BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 4C - 4F BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 50 - 53 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 54 - 57 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 58 - 5B BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 5C - 5F BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 60 - 64 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 64 - 67 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 68 - 6B BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 6C - 6F BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 70 - 74 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 74 - 77 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 78 - 7B BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 7C - 7F ! ! software traps ! BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 80 - 83 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 84 - 87 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 88 - 8B BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 8C - 8F BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 90 - 93 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 94 - 97 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 98 - 9B BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! 9C - 9F BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! A0 - A3 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! A4 - A7 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! A8 - AB BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! AC - AF BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! B0 - B3 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! B4 - B7 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! B8 - BB BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! BC - BF BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! C0 - C3 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! C4 - C7 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! C8 - CB BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! CC - CF BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! D0 - D3 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! D4 - D7 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! D8 - DB BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! DC - DF BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! E0 - E3 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! E4 - E7 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! E8 - EB BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! EC - EF BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! F0 - F3 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! F4 - F7 BAD_TRAP; BAD_TRAP; BAD_TRAP; BAD_TRAP; ! F8 - FB BAD_TRAP; BAD_TRAP; ! FC - FD TRAP(_trap); ! FE enter debugger TRAP(_trap); ! FF breakpoint/* * Debugger vector table. * Must follow trap table. */dvec: b,a enter ! dv_entry .word _trap ! dv_trap .word _pagesused ! dv_pages .word _scbsync ! dv_scbsync .word 0/* * Debugger entry point. * First we must figure out if we are running in correctly adjusted * addresses. If so, we must have been called by debugged code * and thus we just want to call the command interpreter. If not, * then we continue to run in the wrong adddress. All of the code * must be carefully written to be position independent, since * we are linked for running out of high addresses, but we get control * running in low addresses. We depend on the boot stack for work space. */enter: mov %o0, %o1 ! o0 might be romp: pass it as o1 later mov %o2, %l1 ! o2 might be the parent callback routine mov %o7, %o5 ! save o7acall: call lea ! %o7 = physical(acall) sethi %hi(acall), %o3 ! %o3 = virtual(acall)lea: or %o3, %lo(acall), %o3 ! cmp %o3, %o7 ! compare to see if virtual == physical set _start, %o2 ! %o2 = virtual(_start) sub %o3, %o2, %o4 ! %o4 = acall - _start sub %o7, %o4, %o0 ! %o0 = physical(start) bne init ! if != then not relocated yet mov %o5, %o7 ! restore o7 ! ! Enter debugger by doing a software trap. ! We ASSUME that the software trap we have set up is still there. ! t TRAPBRKNO-1 nop retl nop ! ! We have not been relocated yet. !init: mov %psr, %g1 bclr PSR_PIL, %g1 ! PIL = 15 bset (15 << 8), %g1 mov %g1, %psr nop; nop; nop ! ! Preserve the romp across the call to early_startup(). ! Save it in %l0: since we're going to reset the world later, ! we can trash our caller's registers. ! mov %o1, %l0 set _early_startup, %o3 ! get offset of early_startup() sub %o3, %o2, %o4 ! from _start add %o4, %o0, %o4 ! add to _start's current address jmpl %o4, %o7 ! call early_startup(real) nop set jmpstart, %g1 ! now that it is relocated, jump to it jmp %g1 nopjmpstart: ! ! PHEW! Now we are running with correct addresses ! and can use non-position-independent code. ! ! Save romp. ! set _romp, %o0 st %l0, [%o0] ! ! Save parent callback routine ! set _release_parent, %o0 st %l1, [%o0] ! ! Save monitor's level14 clock interrupt vector code and trap #0. ! mov %tbr, %l4 ! save monitor's tbr bclr 0xfff, %l4 ! remove tt or %l4, TT(T_INT_LEVEL_14), %l4 set _scb, %l5 or %l5, TT(T_INT_LEVEL_14), %l5 ldd [%l4], %o0 std %o0, [%l5] ldd [%l4+8], %o0 std %o0, [%l5+8] bclr 0xfff, %l4 ! remove tt or %l4, TT(T_SYSCALL), %l4 bclr 0xfff, %l5 or %l5, TT(T_SYSCALL), %l5 ldd [%l4], %o0 std %o0, [%l5] ldd [%l4+8], %o0 std %o0, [%l5+8] ! ! Take over the world. Save the current stack pointer, as ! we're going to need it for a little while longer. ! mov %sp, %g2 set _scb, %g1 ! setup kadb tbr mov %g1, %tbr nop; nop; nop mov 0x2, %wim mov %psr, %g1 bclr PSR_CWP, %g1 mov %g1, %psr nop; nop; nop; ! psr delay sub %g2, SA(MINFRAME), %sp ! ! Fix the implementation dependent parameters. !fiximp: ! ! Find out how many windows we have and set the global variable. ! We must be in window 0 for this to work. ! set _nwindows, %g2 save ! CWP is now (nwindows - 1) mov %psr, %g1 and %g1, PSR_CWP, %g1 inc %g1 st %g1, [%g2] restore ! ! Fix the number of windows in the trap vectors. ! The last byte of the window handler trap vectors must be equal to ! the number of windows in the implementation minus one. ! dec %g1 ! last byte of trap vectors get NW-1 set _scb, %g2 add %g2, (5 << 4), %g2 ! window overflow trap handler offset stb %g1, [%g2 + 15] ! write last byte of trap vector add %g2, 16, %g2 ! now get window underflow trap stb %g1, [%g2 + 15] ! write last byte of trap vector ! ! Call startup to do the rest of the startup work. ! call _startup nop ! ! call main to enter the debugger ! call _main nop mov %psr, %g1 bclr PSR_PIL, %g1 ! PIL = 14 bset (14 << 8), %g1 mov %g1, %psr nop;nop;nop t TRAPBRKNO-1 ! ! In the unlikely event we get here, return to the monitor. ! set _romp, %g1 ld [%g1], %g2 ld [%g2 + EXIT_TO_MON], %g1 jmp %g1 clr %o0/* * exitto(addr) * int *addr; */ ENTRY(_exitto) save %sp, -SA(MINFRAME), %sp set 1, %o1 sethi %hi(_use_kern_tbr), %o0 st %o1, [%o0 + %lo(_use_kern_tbr)] set _romp, %g1 ld [%g1], %g1 ld [%g1 + V_ROMVEC_VERSION], %g1 ! check romp->v_romvec_version tst %g1 be dont_kill_parent ! only callback if version > 0 nop set _release_parent, %g1 ! call back boot's release function ld [%g1], %g1 tst %g1 be dont_kill_parent ! only callback if function exists nop jmpl %g1, %o7 ! pass return addr in %o0 for add %o7, 8, %o0 ! romp->op_chain() functiondont_kill_parent: set _our_die_routine, %o2 ! pass our release func to callee set dvec, %o1 ! pass dvec address to callee set _romp, %o0 ! pass the romp to callee jmpl %i0, %o7 ! register-indirect call ld [%o0], %o0 ret restore/* * This is where breakpoint traps go. * We assume we are in the normal condition after a trap. */ ENTRY(trap) ! ! dump the whole cpu state (all windows) on the stack. ! set _regsave, %l3 st %l0, [%l3 + R_PSR] st %l1, [%l3 + R_PC] st %l2, [%l3 + R_NPC] mov %wim, %l4 st %l4, [%l3 + R_WIM] mov %g0, %wim ! zero wim so that we can move around mov %tbr, %l4 st %l4, [%l3 + R_TBR] mov %y, %l4 st %l4, [%l3 + R_Y] st %g1, [%l3 + R_G1] st %g2, [%l3 + R_G2] st %g3, [%l3 + R_G3] st %g4, [%l3 + R_G4] st %g5, [%l3 + R_G5] st %g6, [%l3 + R_G6] st %g7, [%l3 + R_G7] add %l3, R_WINDOW, %g7 sethi %hi(_nwindows), %g6 ld [%g6 + %lo(_nwindows)], %g6 bclr PSR_CWP, %l0 ! go to window 0 mov %l0, %psr nop; nop; nop; ! psr delay1: st %l0, [%g7 + 0*4] ! save locals st %l1, [%g7 + 1*4] st %l2, [%g7 + 2*4] st %l3, [%g7 + 3*4] st %l4, [%g7 + 4*4] st %l5, [%g7 + 5*4] st %l6, [%g7 + 6*4] st %l7, [%g7 + 7*4] st %i0, [%g7 + 8*4] ! save ins st %i1, [%g7 + 9*4] st %i2, [%g7 + 10*4] st %i3, [%g7 + 11*4] st %i4, [%g7 + 12*4] st %i5, [%g7 + 13*4] st %i6, [%g7 + 14*4] st %i7, [%g7 + 15*4] add %g7, WINDOWSIZE, %g7 subcc %g6, 1, %g6 ! all windows done? bnz 1b restore ! delay slot, increment CWP ! ! Back in window 0. ! set _regsave, %g2 ! need to get back to state of entering ld [%g2 + R_WIM], %g1 mov %g1, %wim ld [%g2 + R_PSR], %g1 bclr PSR_PIL, %g1 ! PIL = 14 bset (14 << 8), %g1 mov %g1, %psr ! go back to orig window nop;nop;nop ! ! Now we must make sure all the window stuff goes to memory. ! Flush all register windows to the stack. ! But wait! If we trapped into the invalid window, we can't just ! save because we'll slip under the %wim tripwire. ! Do one restore first, so subsequent saves are guaranteed ! to flush the registers. (Don't worry about the restore ! triggering a window underflow, since if we're in a trap ! window the next window up has to be OK.) ! Do all this while still using the kernel %tbr: let it worry ! about user windows and user stack faults. ! restore mov %psr, %g1 ! get new CWP wr %g1, PSR_ET, %psr ! enable traps nop;nop;nop save %sp, -SA(MINFRAME), %sp ! now we're back in the trap window mov %sp, %g3 mov %fp, %g4 sethi %hi(_nwindows), %g7 ld [%g7 + %lo(_nwindows)], %g7 sub %g7, 2, %g6 ! %g6 = NWINDOW - 21: deccc %g6 ! all windows done? bnz 1b save %sp, -WINDOWSIZE, %sp sub %g7, 2, %g6 ! %g6 = NWINDOW - 22: deccc %g6 ! all windows done? bnz 2b restore ! delay slot, increment CWP mov %psr, %g1 wr %g1, PSR_ET, %psr ! disable traps while working mov 2, %wim ! setup wim bclr PSR_CWP, %g1 ! go to window 0 bclr PSR_PIL, %g1 ! PIL = 14 bset (14 << 8), %g1 wr %g1, PSR_ET, %psr ! rewrite %psr, but keep traps disabled nop; nop; nop mov %g3, %sp ! put back %sp and %fp mov %g4, %fp mov %g1, %psr ! now enable traps nop; nop; nop ! save fpu sethi %hi(_fpu_exists), %g1 ld [%g1 + %lo(_fpu_exists)], %g1 tst %g1 ! don't bother if no fpu bz 1f nop set _regsave, %l3 ! was it on? ld [%l3 + R_PSR], %l0 set PSR_EF, %l5 ! FPU enable bit btst %l5, %l0 ! was the FPU enabled? bz 1f nop ! ! Save floating point registers and status. ! All floating point operations must be complete. ! Storing the fsr first will accomplish this. ! set fpuregs, %g7 st %fsr, [%g7+(32*4)]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -