locore.s
来自「操作系统SunOS 4.1.3版本的源码」· S 代码 · 共 263 行
S
263 行
.data .asciz "@(#)locore.s 1.1 92/07/30 SMI" .even .text/* * Copyright (c) 1988 by Sun Microsystems, Inc. */#include <sys/errno.h>#include <sys/param.h>#include <machine/asm_linkage.h>#include <machine/mmu.h>#include <machine/psl.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. Since the debugger * is loaded with the "-N" flag, we pad this stack by a page * because when the page level protection is done, we will lose * part of this stack. Thus the usable stack will be at least * MIN_STACK_SZ bytes and at most MIN_STACK_SZ+NBPG bytes. */#define MIN_STACK_SZ 0x2000 .data .globl _estack . = . + NBPG + MIN_STACK_SZ_estack: | end (top) of debugger stack .text#define SAVEALL() \ clrw sp@-;\ movl sp,sp@-;\ moveml #0xfffe,sp@-;\ movc dfc,d1;\ movc sfc,d0;\ moveml #0xc000,sp@-#define RESTOREALL() \ moveml sp@+,#0x0003;\ movc d0,sfc;\ movc d1,dfc;\ moveml sp@+,#0x7fff;\ addqw #6,sp/* * Debugger receives control at the label `_start' which * must be at offset zero in this file; this file must * be the first thing in the boot image. At start * is a struct dvec. */ ENTRY(start) bra 0f | dv_entry .long _trap | dv_trap .long _pagesused | dv_pages .long _scbsync | dv_scbsync .long 0/* * First we must figure out if we are running in correctly adjusted * addresses. If so, we must have been called via a jsr to _start * 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 code, since * we are linked for running out of high addresses, but we get control * running in low addresses. We run off the stack set up by the caller. */#ifndef sun3x#ifndef CTXSIZE#define CTXSIZE (NBSG * NSEGMAP)#endif !CTXSIZE#endif !sun3x0: movl a0,sp@- | save a0#ifndef sun3x movl d0,sp@- | and d0#endif sun3xleax: lea pc@(_start-(leax+2)),a0 | a0 = true current location of _start#ifndef sun3x movl a0,d0 | get a copy that we can play with andl #CTXSIZE-1,d0 | mask off unused virtual bits to movl d0,a0 | avoid believing them movl sp@+,d0 | restore d0, we don't need it anymore#endif sun3x cmpl #_start,a0 | is desired value == current value? movl sp@+,a0 | restore a0 - NOTE, cc not affected beq docall | if relocated already, go to docall() | first time through, still be careful lea _startup,a1 | virtual startup address subl #_start,a1 | subtract off virtual load address addl a0,a1 | a1 has adjusted startup pea a0@ jsr a1@ | CALL(startup)(real); addqw #4,sp jmp cont:l | force non-PC rel branchcont:/* * PHEW! Now we are running with correct addresses * and can use non-position independent code. */ jsr _main rts | should not return/* * This is where we break into when we catch a breakpoint */ ENTRY(trap) movw #SR_HIGH,sr SAVEALL() jsr _cmdret: RESTOREALL() rte/* * This is where we break into when trace trap is taken */ ENTRY(trace) tstl _dotrace | are we expecting this? jeq ktraceret | if not branch movw #SR_HIGH,sr SAVEALL() jsr _cmd tstl d0 | test return value jeq ret | if 0, then simply return RESTOREALL() | else restore regs and | pass trace exception to debuggeektraceret: | go to kernel's trace routine movl _ktrace,sp@- | push address to goto rts | and get there as if nothing happened/* * This is where we call to enter debugger (i.e. from * monitor command or an explicit call from kernel). */ .datapcsave: .long 0 .textdocall: movl sp@+,pcsave | copy return pc clrw sp@- | zero out fake fmt value movl pcsave,sp@- | push return pc movw sr,sp@- movw #SR_HIGH,sr SAVEALL() jsr _cmd jra ret ENTRY(fault) movw #SR_HIGH,sr SAVEALL() /* * Reset the sfc and dfc to FC_MAP to avoid problems if the * monitor was dorking with these registers. We don't have * to worry about the current contents of sfc and dfc as * they are restored to the original value before returning * to the program being debugged. */ lea FC_MAP,a0 movc a0,dfc movc a0,sfc jsr _faulterr | call fault handler jsr _cmd | not resolved, go into debugger jra ret | try to return back now ENTRY(getvbr) movc vbr,d0 rts/* * peekl(addr) * * peekl() and pokel() are like the standard peek (peekc) and * poke (pokec) functions except they use longwords and set * errno to EFAULT on failure (so that succeeding w/ -1 looks * different than a failure). */ ENTRY(peekl) movl sp@(4),a0 | Get address to probe movc vbr,a1 | get vbr movl a1@(8),d1 | save bus error handler movl #BEhand,a1@(8) | set up our own handler movl sp,a1 | save current stack pointer movl a0,d0 btst #0,d0 | See if odd address bne BEhand | Yes, the probe fails. movl a0@,d0 | Read a longword.PAexit: movc vbr,a1 | get vbr movl d1,a1@(8) | restore bus error handler rtsBEhand: movl a1,sp | Restore stack after bus error moveq #-1,d0 | Set result of -1, indicating fault. movl #EFAULT,_errno | Indicate failure using errno bra PAexit ENTRY(pokel) movl sp@(4),a0 | Get address to probe movc vbr,a1 | get vbr movl a1@(8),d1 | save bus error handler movl #BEhand,a1@(8) | set up our own handler movl sp,a1 | save current stack pointer movl sp@(8),a0@ | Write a longword| A fault in the movl will vector us to BEhand above. moveq #0,d0 | It worked; return 0 as result. bra PAexit | restores bus error handler and returns - above/* * Peekc is so named to avoid a naming conflict * with adb which has a variable named peekc */ ENTRY(Peekc) movl sp@(4),a0 | Get address to probe movc vbr,a1 | get vbr movl a1@(8),d1 | save bus error handler movl #BEhand,a1@(8) | set up our own handler movl sp,a1 | save current stack pointer moveq #0,d0 | Clear upper half movb a0@,d0 | Read a byte| A fault in the movb will vector us to BEhand above. bra PAexit | restores bus error handler and returns - above/* * Return current sp value to caller */ ENTRY(getsp) movl sp,d0 rts#if defined(sun3) || defined(sun3x)/* * Flush '20 or '30 instruction cache */ ENTRY(flush20) movc cacr,d0 | get current cache control register#ifdef sun3 orl #CACHE_CLEAR,d0 | or in clear flag#endif sun3#ifdef sun3x orl #ICACHE_CLEAR,d0 | or in clear flag#endif sun3x movc d0,cacr | clear cache (regardless of state) rts#endif sun3 || sun3x ENTRY(_exitto) movl sp@(4),a0 | Address to call. jsr a0@ | Jump to callee using caller's stack. rts
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?