📄 locore.s
字号:
* * 2 Jan 84 --jmcg * Added support for MicroVAX 1. * *************************************************************************/#include "../h/param.h"#include "../machine/psl.h"#include "../machine/pte.h"#include "../h/errno.h"#include "../h/cmap.h"#include "../h/cpudata.h"#include "../h/kmalloc.h"#include "../machine/mtpr.h"#include "../machine/pcb.h"#include "../machine/trap.h"#include "../machine/cpu.h"#include "../../machine/common/cpuconf.h"#include "../machine/b_params.h"#include "../machine/cons.h"#include "../machine/clock.h"#include "../io/bi/bireg.h"/*#include "../machine/nexus.h"#include "../io/uba/ubareg.h"*/#include "../machine/sas/vmb.h"#include "../h/smp_lock.h"#include "dh.h"#include "dz.h"#include "ss.h"#include "fc.h"#include "uu.h"#include "ps.h"#include "mba.h"#include "ci.h"#include "msi.h"#define is_vect_inst 0#define isnt_vect_inst 1#define ENTRY(name, regs) \ .globl _/**/name; .align 1; _/**/name: .word regs#define R0 0x01#define R1 0x02#define R2 0x04#define R3 0x08#define R4 0x10#define R5 0x20#define R6 0x40 .set INTSTK,1 # handle this interrupt on the interrupt stack .set HALT,3 # halt if this interrupt occurs .set HIGH,0x1f # mask for total disable .set MCKVEC,4 # offset into scb of machine check vector .set VPN_WIDTH,21 .set SYSPROC,10 # system process priority level/* * User structure is UPAGES at top of user space. */ .globl _u .set _u,0x80000000 - UPAGES*NBPG .globl _forkutl .set _forkutl,_u - FORKPAGES*NBPG .globl _intstack .globl _eintstack/* * Do a dump. * Called by auto-restart. * May be called manually. */ .align 2 .globl _doadump_doadump: nop; nop # .word 0x0101#define _rpbmap _Sysmap # rpb, scb, UNI*vec, istack*4 bicl2 $PG_PROT,_rpbmap bisl2 $PG_KW,_rpbmap mtpr $0,$TBIA bitl $2,_rpb+RP_FLAG # dump only once! bneq 1f bisl2 $2,_rpb+RP_FLAG movl sp,_edumpstack movab _edumpstack,sp mtpr sp,$ISP mfpr $PCBB,-(sp) mfpr $MAPEN,-(sp) mfpr $IPL,-(sp) cmpl $V_VAX,_cpu # Are we a Virtual VAX? bneq 2f # no: go to normal dump calls $0,_vvaxdump # yes brb 1f2: mtpr $HIGH,$IPL mtpr $0,$MAPEN pushr $0x3fff calls $0,_dumpsys1: pushl $TXDB_BOOT # reboot the system calls $1,_cons_putc # let cons_putc tell the console # (it handles VAX 8600) halt # come back and halt/* * Where called : qioinit is called in the generic dump driver. * Function : Called to initialize the dump device. * Parameters : None. * Side effects : Computes global variable _qioentry, the entry point * into the qio routine of the new boot driver. */ .globl _qioinit_qioinit: .word 0xffc # save r2 - r11 movl _vmbinfo,r8 # r8 points to info list movl INFO_RPBBAS(r8),r9 # required bu init routines movl INFO_BTDRBAS(r8),r7 # get address of boot driver addl3 r7,BQO$L_QIO(r7),_qioentry # compute address qio routine movl $1,r0 # in case no init routine. tstl BQO$L_UNIT_INIT(r7) # does init routine exist ? beql 4f # if not dont bother trying addl3 r7,BQO$L_UNIT_INIT(r7),r2 # calculate entry point/* * KLUDGE (for [T]MSCP controller types) to force total controller * initialization, otherwise we wait an awful long time for * initialization to complete. Also used to set up driver rings to * talk to VMB, not UFS. */#define IP 0#define SA 2 cmpb $BTD$K_UDA,RPB$B_DEVTYP(r9) # is this a uda/qda/kda ? beql 1f # yes, go hit it cmpb $BTD$K_TK50,RPB$B_DEVTYP(r9) # is this a TK50 controller ? beql 1f # yes, go hit it brb 2f # proceed with normal init1: movl RPB$L_CSRPHY(r9),r7 #get the IP register address clrw IP(r7) # poke it to make it step1: movw SA(r7),r0 # get the status register bitw $0xfe00,SA(r7) # is something active ? beql 1b # if not, wait until there is2: mfpr $SCBB,r7 # required by BI (BDA driver) callg *INFO_VMBARGBAS(r8),(r2) # do it4: ret/* * Where called : qiois called in the generic dump driver. * Function : Called to perform reading from core and writing to * the dump device. * Parameters : 1) Address mode, physical or virtual. * 2) Function, reading or writing virtual/physical space. * 3) Starting block number, starting disk block number. * 4) Transfer size, in bytes. * 5) Address of buffer, memory location. * Side effects : Performs io function and returns completion code. */ .globl _qio_qio: .word 0xe00 # save r9 - r11 movl _vmbinfo,r9 # point to the info list movl INFO_RPBBAS(r9),r9 # get address of the RPB pushl r9 # push address of RPB pushl 4(ap) # push address mode pushl 8(ap) # push I/O function code pushl 12(ap) # push starting block number pushl 16(ap) # push transfer size in bytes pushl 20(ap) # push address of buffer calls $6,*_qioentry # call qio routine ret # return completion code#ifdef VVAX/* * These two functions are versions of qio and qioinit which run with * Virtual Memory turned on. This is required by VVAX. *//* * Where called : v_qioinit is called in the generic dump driver. * Function : Called to initialize the dump device. * Parameters : None. * Side effects : Computes global variable _qioentry, the entry point * into the qio routine of the new boot driver. */ .globl _v_qioinit_v_qioinit: .word 0xffc # save r2 - r11 moval _vmb_info,r8 # r8 points to info list moval _rpb,r9 # required by init routines movl INFO_BTDRBAS(r8),r7 # get address of boot driver subl2 _vmbinfo,r7 # now convert to virtual addl2 r8,r7 # address addl3 r7,BQO$L_QIO(r7),_qioentry # compute address qio routine movl $1,r0 # in case no init routine. tstl BQO$L_UNIT_INIT(r7) # does init routine exist ? beql 1f # if not dont bother trying addl3 r7,BQO$L_UNIT_INIT(r7),r2 # calculate entry point movl INFO_VMBARGBAS(r8),r7 # get address of arg list subl2 _vmbinfo,r7 # now convert to virtual addl2 r8,r7 # address callg (r7),(r2) # do it1: ret/* * Where called : v_qio is called in the generic dump driver. * Function : Called to perform reading from core and writing to * the dump device. * Parameters : 1) Address mode, physical or virtual. * 2) Function, reading or writing virtual/physical space. * 3) Starting block number, starting disk block number. * 4) Transfer size, in bytes. * 5) Address of buffer, memory location. * Side effects : Performs io function and returns completion code. */ .globl _v_qio_v_qio: .word 0xe00 # save r9 - r11 pushal _rpb # push address of RPB pushl 4(ap) # push address mode pushl 8(ap) # push I/O function code pushl 12(ap) # push starting block number pushl 16(ap) # push transfer size in bytes pushl 20(ap) # push address of buffer calls $6,*_qioentry # call qio routine ret # return completion code#endif VVAX/* * {fu,su},{byte,word}, all massaged by asm.sed to jsb's */ .globl _Fuword_Fuword: prober $3,$4,(r0) beql fserr movl (r0),r0 rsbfserr: mnegl $1,r0 rsb .globl _Fubyte_Fubyte: prober $3,$1,(r0) beql fserr movzbl (r0),r0 rsb .globl _Suword_Suword: probew $3,$4,(r0) beql fserr movl r1,(r0) clrl r0 rsb .globl _Subyte_Subyte: probew $3,$1,(r0) beql fserr movb r1,(r0) clrl r0 rsb/* * Check address. * Given virtual address, byte count, and rw flag * returns 0 on no access. */_useracc: .globl _useracc .word 0x0 movl 4(ap),r0 # get va movl 8(ap),r1 # count tstl 12(ap) # test for read access ? bneq userar # yes cmpl $NBPG,r1 # can we do it in one probe ? bgeq uaw2 # yesuaw1: probew $3,$NBPG,(r0) beql uaerr # no access addl2 $NBPG,r0 acbl $NBPG+1,$-NBPG,r1,uaw1uaw2: probew $3,r1,(r0) beql uaerr movl $1,r0 retuserar: cmpl $NBPG,r1 bgeq uar2uar1: prober $3,$NBPG,(r0) beql uaerr addl2 $NBPG,r0 acbl $NBPG+1,$-NBPG,r1,uar1uar2: prober $3,r1,(r0) beql uaerr movl $1,r0 retuaerr: clrl r0 ret_addupc: .globl _addupc .word 0x0 movl 8(ap),r2 # &u.u_prof subl3 8(r2),4(ap),r0 # corrected pc blss 9f extzv $1,$31,r0,r0 # logical right shift extzv $1,$31,12(r2),r1 # ditto for scale emul r1,r0,$0,r0 ashq $-14,r0,r0 tstl r1 bneq 9f bicl2 $1,r0 cmpl r0,4(r2) # length bgequ 9f addl2 (r2),r0 # base probew $3,$2,(r0) beql 8f addw2 12(ap),(r0)9: ret8: clrl 12(r2) ret /* * Copy a null terminated string from the user address space into * the kernel address space. * * copyinstr(fromaddr, toaddr, maxlength, &lencopied) */ENTRY(copyinstr, R6) movl 12(ap),r6 # r6 = max length jlss 8f movl 4(ap),r1 # r1 = user address bicl3 $~(NBPG*CLSIZE-1),r1,r2 # r2 = bytes on first page subl3 r2,$NBPG*CLSIZE,r2 movl 8(ap),r3 # r3 = kernel address1: cmpl r6,r2 # r2 = min(bytes on page, length left); jgeq 2f movl r6,r22: prober $3,r2,(r1) # bytes accessible? jeql 8f subl2 r2,r6 # update bytes left count locc $0,r2,(r1) # null byte found? jneq 3f subl2 r2,r1 # back up pointer updated by `locc' movc3 r2,(r1),(r3) # copy in next piece movl $(NBPG*CLSIZE),r2 # check next page tstl r6 # run out of space? jneq 1b movl $ENAMETOOLONG,r0 # set error code and return jbr 9f3: tstl 16(ap) # return length? beql 4f subl3 r6,12(ap),r6 # actual len = maxlen - unused pages subl2 r0,r6 # - unused on this page addl3 $1,r6,*16(ap) # + the null byte4: subl2 r0,r2 # r2 = number of bytes to move subl2 r2,r1 # back up pointer updated by `locc' incl r2 # copy null byte as well movc3 r2,(r1),(r3) # copy in last piece clrl r0 # redundant ret8: movl $EFAULT,r09: tstl 16(ap) beql 1f subl3 r6,12(ap),*16(ap)1: ret/* * Copy a null terminated string from the kernel * address space to the user address space. * * copyoutstr(fromaddr, toaddr, maxlength, &lencopied) */ENTRY(copyoutstr, R6) movl 12(ap),r6 # r6 = max length jlss 8b movl 4(ap),r1 # r1 = kernel address movl 8(ap),r3 # r3 = user address bicl3 $~(NBPG*CLSIZE-1),r3,r2 # r2 = bytes on first page subl3 r2,$NBPG*CLSIZE,r21: cmpl r6,r2 # r2 = min(bytes on page, length left); jgeq 2f movl r6,r22: probew $3,r2,(r3) # bytes accessible? jeql 8b subl2 r2,r6 # update bytes left count locc $0,r2,(r1) # null byte found? jneq 3b subl2 r2,r1 # back up pointer updated by `locc' movc3 r2,(r1),(r3) # copy in next piece movl $(NBPG*CLSIZE),r2 # check next page tstl r6 # run out of space? jneq 1b movl $ENAMETOOLONG,r0 # set error code and return jbr 9b/* * Copy a null terminated string from one point to another in * the kernel address space. * * copystr(fromaddr, toaddr, maxlength, &lencopied) */ENTRY(copystr, R6) movl 12(ap),r6 # r6 = max length jlss 8b movl 4(ap),r1 # r1 = src address movl 8(ap),r3 # r3 = dest address1: movzwl $65535,r2 # r2 = bytes in first chunk cmpl r6,r2 # r2 = min(bytes in chunk, length left); jgeq 2f movl r6,r22: subl2 r2,r6 # update bytes left count locc $0,r2,(r1) # null byte found? jneq 3b subl2 r2,r1 # back up pointer updated by `locc' movc3 r2,(r1),(r3) # copy in next piece tstl r6 # run out of space? jneq 1b movl $ENAMETOOLONG,r0 # set error code and return jbr 9b/* * Copy specified amount of data from user space into the kernel * Copyin(from, to, len) * r1 == from (user source address) * r3 == to (kernel destination address) * r5 == length */ .globl _Copyin # massaged to jsb, args R1 R3 R5_Copyin:#ifdef SMP_DEBUG tstl _smp_debug beql 1f pushr $0x3f calls $0,_sleep_check popr $0x3f1:#endif cmpl r5,$(NBPG*CLSIZE) # probing one page or less ? bgtru 1f # no prober $3,r5,(r1) # bytes accessible ? beql ersb # no movc3 r5,(r1),(r3)/* clrl r0 # redundant */ rsb1: blss ersb # negative length? pushl r6 # r6 = length movl r5,r6 bicl3 $~(NBPG*CLSIZE-1),r1,r0 # r0 = bytes on first page subl3 r0,$(NBPG*CLSIZE),r0 addl2 $(NBPG*CLSIZE),r0 # plus one additional full page jbr 2fciloop: movc3 r0,(r1),(r3) movl $(2*NBPG*CLSIZE),r0 # next amount to move2: cmpl r0,r6
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -