1ab937509Skarels/* 2ab937509Skarels * Copyright (c) 1988 Regents of the University of California. 3ab937509Skarels * All rights reserved. The Berkeley software License Agreement 4ab937509Skarels * specifies the terms and conditions for redistribution. 5ab937509Skarels * 6*bff07831Sbostic * @(#)locore.s 7.21 (Berkeley) 09/23/93 7ab937509Skarels */ 87479596bSsam 9d357015aSbostic#include "tahoe/include/mtpr.h" 10d357015aSbostic#include "tahoe/include/trap.h" 11d357015aSbostic#include "tahoe/include/psl.h" 12d357015aSbostic#include "tahoe/include/pte.h" 13d357015aSbostic#include "tahoe/tahoe/cp.h" 14d357015aSbostic#include "tahoe/tahoe/mem.h" 15d357015aSbostic#include "tahoe/tahoe/SYS.h" 16ab937509Skarels 17d357015aSbostic#include "tahoe/math/fp.h" 187479596bSsam 19d357015aSbostic#include "sys/errno.h" 20d357015aSbostic#include "sys/syscall.h" 21d357015aSbostic#include "sys/cmap.h" 227479596bSsam 237479596bSsam .set HIGH,0x1f # mask for total disable 247479596bSsam .set NISP,3 # number of interrupt stack pages 257479596bSsam .set SYSTEM,0xC0000000 # virtual address of system start 26477ef2c3Ssam .set PPAGES,0x100000 # possible pages in P0,P1, etc. 277479596bSsam 287479596bSsam/* ACBL for non-negative '_add' */ 297479596bSsam#define ACBL(_limit,_add,_index,_displ) \ 307479596bSsam addl2 _add,_index; \ 317479596bSsam cmpl _index,_limit; \ 327479596bSsam bleq _displ 337479596bSsam 347479596bSsam/* _ACBL for negative '_add' */ 357479596bSsam#define _ACBL(_limit,_add,_index,_displ) \ 367479596bSsam addl2 _add,_index; \ 377479596bSsam cmpl _index,_limit; \ 387479596bSsam bgeq _displ 397479596bSsam 400b8444b9Ssam#define MOVC3(_srcaddr,_dstaddr,_len) \ 417479596bSsam movl _srcaddr,r0; \ 427479596bSsam movl _dstaddr,r1; \ 437479596bSsam movl _len,r2; \ 447479596bSsam movblk 457479596bSsam 460b8444b9Ssam/* keep address of psl if coming from user mode */ 477479596bSsam#define CHECK_SFE(_delta) \ 487479596bSsam bitl $PSL_CURMOD,_delta(sp); \ 497479596bSsam jeql 1f; \ 507479596bSsam moval _delta(sp),_user_psl; \ 517479596bSsam1: 527479596bSsam 537479596bSsam/* 547479596bSsam * User structure is UPAGES at top of user space. 557479596bSsam */ 567479596bSsam .globl _u 577479596bSsam .set _u,SYSTEM - UPAGES*NBPG 587479596bSsam 597479596bSsam/* 607479596bSsam * Restart stack. Used on power recovery or panic. 617479596bSsam * Takes a core-dump and then halts. 627479596bSsam */ 637479596bSsam .globl _rsstk 647479596bSsam .globl pwfl_stk 650b8444b9Ssam_rsstk: 660b8444b9Ssam .space 1024-8 670b8444b9Ssampwfl_stk: 680b8444b9Ssam .space 4 690b8444b9Ssamdumpflag: 700b8444b9Ssam .space 4 717479596bSsam 727479596bSsam .globl _intstack 737479596bSsam_intstack: 747479596bSsam .space NISP*NBPG 757479596bSsameintstack: 767479596bSsam 770b8444b9Ssam/* 780b8444b9Ssam * Power failure storage block and 790b8444b9Ssam * macros for saving and restoring. 800b8444b9Ssam */ 810b8444b9Ssam#define POWERFAIL(id,longs) \ 820b8444b9Ssam .globl pwfl_/**/id \ 830b8444b9Ssampwfl_/**/id: .space longs*4 847479596bSsam .data 850b8444b9Ssam POWERFAIL(r0, 14) # r0-r13 860b8444b9Ssam POWERFAIL(sp, 1) # r14 870b8444b9Ssam POWERFAIL(SCBB, 1) # system control block base 880b8444b9Ssam POWERFAIL(SBR, 1) # system pte base 890b8444b9Ssam POWERFAIL(SLR, 1) # system pte length 900b8444b9Ssam POWERFAIL(P0BR, 1) # p0 pte base 910b8444b9Ssam POWERFAIL(P0LR, 1) # p0 pte length 920b8444b9Ssam POWERFAIL(P1BR, 1) # p1 pte base 930b8444b9Ssam POWERFAIL(P1LR, 1) # p1 pte length 940b8444b9Ssam POWERFAIL(P2BR, 1) # p2 pte base 950b8444b9Ssam POWERFAIL(P2LR, 1) # p2 pte length 960b8444b9Ssam POWERFAIL(IPL, 1) # interrupt priority level 970b8444b9Ssam POWERFAIL(DCK, 1) # data cache key 980b8444b9Ssam POWERFAIL(CCK, 1) # code cache key 990b8444b9Ssam POWERFAIL(PCBB, 1) # process control block base 1000b8444b9Ssam POWERFAIL(ISP, 1) # interrupt stack pointer 1010b8444b9Ssam POWERFAIL(KSP, 1) # kernel mode stack pointer 1020b8444b9Ssam POWERFAIL(USP, 1) # user mode stack pointer 1030b8444b9Ssam POWERFAIL(MME, 1) # memory management enable 1040b8444b9Ssam POWERFAIL(PSL, 1) # processor status longword 1050b8444b9Ssam 1060b8444b9Ssam/* 1070b8444b9Ssam * Save current state in power fail storage block. 1080b8444b9Ssam */ 1090b8444b9Ssam#define SAVEpwfl() \ 1100b8444b9Ssam movpsl pwfl_PSL # Keeps all flags, etc. \ 1110b8444b9Ssam storer $0x3fff,pwfl_r0 # Saves r0-r13 \ 1120b8444b9Ssam moval 0(sp),pwfl_sp # Saves sp (=r14) \ 1130b8444b9Ssam mfpr $SBR,pwfl_SBR # Save all re_loadable registers \ 1140b8444b9Ssam mfpr $SLR,pwfl_SLR \ 1150b8444b9Ssam mfpr $P0BR,pwfl_P0BR \ 1160b8444b9Ssam mfpr $P0LR,pwfl_P0LR \ 1170b8444b9Ssam mfpr $P1BR,pwfl_P1BR \ 1180b8444b9Ssam mfpr $P1LR,pwfl_P1LR \ 1190b8444b9Ssam mfpr $P2BR,pwfl_P2BR \ 1200b8444b9Ssam mfpr $P2LR,pwfl_P2LR \ 1210b8444b9Ssam mfpr $IPL,pwfl_IPL \ 1220b8444b9Ssam mfpr $MME,pwfl_MME \ 1230b8444b9Ssam mfpr $DCK,pwfl_DCK \ 1240b8444b9Ssam mfpr $CCK,pwfl_CCK \ 1250b8444b9Ssam mfpr $PCBB,pwfl_PCBB \ 1260b8444b9Ssam mfpr $ISP,pwfl_ISP \ 1270b8444b9Ssam mfpr $SCBB,pwfl_SCBB \ 1280b8444b9Ssam mfpr $KSP,pwfl_KSP \ 1290b8444b9Ssam mfpr $USP,pwfl_USP 1300b8444b9Ssam 1310b8444b9Ssam/* 1320b8444b9Ssam * Restore state saved in power fail block and 1330b8444b9Ssam * jmp to location specified after (possibly) 1340b8444b9Ssam * enabling memory management. 1350b8444b9Ssam */ 1360b8444b9Ssam#define RESTOREpwfl(loc) \ 1370b8444b9Ssam loadr $0x3fff,pwfl_r0 # Restore r0-r13 \ 1380b8444b9Ssam movl pwfl_sp,sp # Restore sp (=r14) \ 1390b8444b9Ssam mtpr pwfl_SCBB,$SCBB \ 1400b8444b9Ssam mtpr pwfl_SBR,$SBR # Restore all re_loadable registers \ 1410b8444b9Ssam mtpr pwfl_SLR,$SLR \ 1420b8444b9Ssam mtpr pwfl_P0BR,$P0BR \ 1430b8444b9Ssam mtpr pwfl_P0LR,$P0LR \ 1440b8444b9Ssam mtpr pwfl_P1BR,$P1BR \ 1450b8444b9Ssam mtpr pwfl_P1LR,$P1LR \ 1460b8444b9Ssam mtpr pwfl_P2BR,$P2BR \ 1470b8444b9Ssam mtpr pwfl_P2LR,$P2LR \ 1480b8444b9Ssam mtpr pwfl_IPL,$IPL \ 1490b8444b9Ssam mtpr pwfl_DCK,$DCK \ 1500b8444b9Ssam mtpr pwfl_CCK,$CCK \ 1510b8444b9Ssam mtpr pwfl_PCBB,$PCBB \ 1520b8444b9Ssam mtpr pwfl_ISP,$ISP \ 1530b8444b9Ssam mtpr pwfl_KSP,$KSP \ 1540b8444b9Ssam mtpr pwfl_USP,$USP \ 1550b8444b9Ssam\ 1560b8444b9Ssam bicpsw $0xff # Restore PSW. \ 1570b8444b9Ssam bispsw pwfl_PSL+2 # Set original bits back (just in case..) \ 1580b8444b9Ssam# now go to mapped mode \ 1590b8444b9Ssam# Have to change PC to system addresses \ 1600b8444b9Ssam mtpr $1,$PACC # Thoroughly clean up caches. \ 1610b8444b9Ssam mtpr $1,$PADC \ 1620b8444b9Ssam mtpr $1,$TBIA \ 1630b8444b9Ssam mtpr pwfl_MME,$MME # Restore MME. Last thing to be done. \ 1640b8444b9Ssam jmp loc 1657479596bSsam 1667479596bSsam/* 1677479596bSsam * Do a dump. 1687479596bSsam * Called by auto-restart. 1697479596bSsam * May be called manually. 1707479596bSsam */ 1717479596bSsam .align 2 1727479596bSsam .text 1737479596bSsam .globl _Xdoadump 1747479596bSsam .globl _doadump 1750b8444b9Ssam_Xdoadump: # CP comes here after power fail 1760b8444b9Ssam RESTOREpwfl(*0f) # restore state 1777479596bSsam_doadump: 1787479596bSsam .word 0 1790b8444b9Ssam0: mtpr $HIGH,$IPL 1800b8444b9Ssam#define _rsstkmap _Sysmap+12 # powerfail storage, scb, rsstk, int stack 1817479596bSsam tstl dumpflag # dump only once! 1827479596bSsam bneq 1f 183844a1895Skarels andl2 $~PG_PROT,_rsstkmap 184844a1895Skarels orl2 $PG_KW,_rsstkmap # Make dump stack r/w 1857479596bSsam mtpr $0,$TBIA 186844a1895Skarels movl $1,dumpflag 1877479596bSsam movab dumpflag,sp 1887479596bSsam callf $4,_dumpsys 1897479596bSsam1: 1907479596bSsam halt 1917479596bSsam 1927479596bSsam/* 1937479596bSsam * Interrupt vector routines 1947479596bSsam */ 1957479596bSsam .globl _waittime 1967479596bSsam#define SCBVEC(name) \ 1977479596bSsam .align 2; \ 1987479596bSsam .globl _X/**/name; \ 1997479596bSsam_X/**/name 2000b8444b9Ssam#define PANIC(msg) \ 2010b8444b9Ssam clrl _waittime; pushab 1f; callf $8,_panic; 1: .asciz msg 2020b8444b9Ssam#define PRINTF(n,msg) \ 2030b8444b9Ssam pushab 1f; callf $(n+2)*4,_printf; MSG(msg) 2047479596bSsam#define MSG(msg) .data; 1: .asciz msg; .text 2050b8444b9Ssam/* 2064d144ff4Skarels * r0-r5 are saved across all faults and interrupts. 207477ef2c3Ssam * Routines below and those hidden in vbglue.s (device 2080b8444b9Ssam * interrupts) invoke the PUSHR/POPR macros to execute 2090b8444b9Ssam * this. Also, certain stack frame offset calculations 2104d144ff4Skarels * use this, using the REGSPC definition (and FPSPC defined below). 2110b8444b9Ssam */ 2124d144ff4Skarels#define REGSPC 6*4 2134d144ff4Skarels#define PUSHR movab -REGSPC(sp),sp; storer $0x3f,(sp) 2144d144ff4Skarels#define POPR loadr $0x3f,(sp); movab REGSPC(sp),sp 2157479596bSsam 2160b8444b9Ssam/* 2170b8444b9Ssam * Floating point state is saved across faults and 2180b8444b9Ssam * interrupts. The state occupies 4 longwords on 2190b8444b9Ssam * the stack: 2200b8444b9Ssam * precision indicator (single = 0/double = 1) 2210b8444b9Ssam * double representation of accumulator 2220b8444b9Ssam * save accumulator status flag (pcb_savacc) 2230b8444b9Ssam */ 2240b8444b9Ssam#define FPSPC (4*4) 2257479596bSsam 2260b8444b9Ssam#define SAVE_FPSTAT(_delta) \ 2270b8444b9Ssam bitl $PSL_DBL,_delta(sp); \ 2287479596bSsam beql 1f; \ 2297479596bSsam pushl $1; \ 2307479596bSsam pushd; \ 2317479596bSsam jmp 2f; \ 2327479596bSsam1: pushl $0; \ 2337479596bSsam pushl $0; \ 2347479596bSsam stf -(sp); \ 2357479596bSsam2: tstl _u+PCB_SAVACC; \ 2367479596bSsam bneq 3f; \ 2377479596bSsam moval 0(sp),_u+PCB_SAVACC; \ 2387479596bSsam orl2 $2,8(sp);\ 2397479596bSsam3: pushl $0; 2407479596bSsam 2410b8444b9Ssam#define REST_FPSTAT \ 2420b8444b9Ssam tstl (sp)+; \ 2437479596bSsam bitl $2,8(sp);\ 2447479596bSsam beql 1f;\ 2457479596bSsam movl $0,_u+PCB_SAVACC; \ 2467479596bSsam1: bitl $1,8(sp); \ 2477479596bSsam beql 2f; \ 2487479596bSsam ldd (sp); \ 2497479596bSsam jmp 3f; \ 2507479596bSsam2: ldf (sp); \ 2517479596bSsam3: moval 12(sp),sp; 2527479596bSsam 2530b8444b9Ssam#define REST_ACC \ 2540b8444b9Ssam tstl _u+PCB_SAVACC; \ 2557479596bSsam beql 2f; \ 2567479596bSsam movl _u+PCB_SAVACC,r1; \ 2577479596bSsam andl3 $(EXPMASK|SIGNBIT),(r1),-(sp); \ 2587479596bSsam cmpl $0x80000000,(sp)+; \ 2597479596bSsam bneq 3f; \ 2607479596bSsam clrl (r1); \ 2617479596bSsam3: bitl $1,8(r1); \ 2627479596bSsam beql 1f; \ 2637479596bSsam ldd (r1); \ 2647479596bSsam jmp 2f; \ 2657479596bSsam1: ldf (r1); \ 2667479596bSsam2: ; 2677479596bSsam 2680b8444b9Ssam .data 2690b8444b9Ssamnofault: .space 4 # bus error non-local goto label 2707479596bSsam 2710b8444b9Ssam .text 2727479596bSsamSCBVEC(buserr): 2737479596bSsam CHECK_SFE(12) 2740b8444b9Ssam SAVE_FPSTAT(12) 2756ed0f239Ssam incl _intrcnt+I_BUSERR # keep stats... 2760b8444b9Ssam pushl r0 # must save 2770b8444b9Ssam andl3 24(sp),$ERRCD,r0 # grab pushed MER value 2780b8444b9Ssam cmpl r0,$APE # address parity error? 2797479596bSsam jneq 1f 2800b8444b9Ssam halt 2810b8444b9Ssam1: cmpl r0,$VBE # versabus error? 2820b8444b9Ssam jneq 2f 2830b8444b9Ssam halt 2840b8444b9Ssam2: 2850b8444b9Ssam movl (sp)+,r0 # restore r0 and... 2860b8444b9Ssam bitl $PSL_CURMOD,4*4+3*4(sp) # check if happened in user mode? 2870b8444b9Ssam jeql 3f # yes, then shift stack up for trap... 2880b8444b9Ssam movl 12(sp),16(sp) # sorry, no space for which-buss... 2890b8444b9Ssam movl 8(sp),12(sp) 2900b8444b9Ssam movl 4(sp),8(sp) 2910b8444b9Ssam movl 0(sp),4(sp) 2920b8444b9Ssam movl $T_BUSERR,0(sp) # push trap type code and... 2930b8444b9Ssam jbr alltraps # ...merge with all other traps 2940b8444b9Ssam3: # kernel mode, check to see if... 2950b8444b9Ssam tstl nofault # ...doing peek/poke? 2960b8444b9Ssam jeql 4f # nofault set? if so, jump to it... 2970b8444b9Ssam movl nofault,4*4+2*4(sp) # ...setup for non-local goto 2980b8444b9Ssam clrl nofault 2990b8444b9Ssam jbr 5f 3000b8444b9Ssam4: 3010b8444b9Ssam PUSHR 3024d144ff4Skarels pushab 4*4+REGSPC(sp) # address of bus error parameters 3037479596bSsam callf $8,_buserror 3047479596bSsam POPR 3050b8444b9Ssam5: 3060b8444b9Ssam REST_FPSTAT 3070b8444b9Ssam movab 8(sp),sp # remove bus error parameters 3087479596bSsam rei 3097479596bSsam 3107479596bSsamSCBVEC(powfail): # We should be on interrupt stack now. 3110b8444b9Ssam SAVEpwfl() # save machine state 312477ef2c3Ssam moval _Xdoadump-SYSTEM,_scb+SCB_DOADUMP 3137479596bSsam halt 3147479596bSsam 3157479596bSsamSCBVEC(stray): 3169dab7c56Ssam incl _cnt+V_INTR # add to statistics 3177479596bSsam rei 3187479596bSsam 319d357015aSbostic#include "net/netisr.h" 3207479596bSsam .globl _netisr 3217479596bSsamSCBVEC(netintr): 3227479596bSsam CHECK_SFE(4) 323477ef2c3Ssam SAVE_FPSTAT(4); PUSHR 324477ef2c3Ssam#include "imp.h" 325477ef2c3Ssam#if NIMP > 0 326477ef2c3Ssam bbc $NETISR_IMP,_netisr,1f; 327477ef2c3Ssam andl2 $~(1<<NETISR_IMP),_netisr 328477ef2c3Ssam callf $4,_impintr; 3297479596bSsam1: 330477ef2c3Ssam#endif 3317479596bSsam#ifdef INET 3323651b6b8Ssklower bbc $NETISR_ARP,_netisr,1f 3333651b6b8Ssklower andl2 $~(1<<NETISR_ARP),_netisr 3343651b6b8Ssklower callf $4,_arpintr 3353651b6b8Ssklower1: 3367479596bSsam bbc $NETISR_IP,_netisr,1f 3370b8444b9Ssam andl2 $~(1<<NETISR_IP),_netisr 3387479596bSsam callf $4,_ipintr 3397479596bSsam1: 3407479596bSsam#endif 3417479596bSsam#ifdef NS 3427479596bSsam bbc $NETISR_NS,_netisr,1f 3430b8444b9Ssam andl2 $~(1<<NETISR_NS),_netisr 3447479596bSsam callf $4,_nsintr 3457479596bSsam1: 3467479596bSsam#endif 347fb5e3f58Skarels#ifdef ISO 348fb5e3f58Skarels bbc $NETISR_ISO,_netisr,1f 349fb5e3f58Skarels andl2 $~(1<<NETISR_ISO),_netisr 350fb5e3f58Skarels callf $4,_clnlintr 351477ef2c3Ssam1: 352fb5e3f58Skarels#endif 353477ef2c3Ssam incl _cnt+V_SOFT 354477ef2c3Ssam POPR; REST_FPSTAT 3557479596bSsam rei 3567479596bSsam 3577479596bSsamSCBVEC(cnrint): 3587479596bSsam CHECK_SFE(4) 3597479596bSsam SAVE_FPSTAT(4); PUSHR; 3606ed0f239Ssam pushl $CPCONS; callf $8,_cnrint; 3616ed0f239Ssam incl _intrcnt+I_CNR 3626ed0f239Ssam incl _cnt+V_INTR 3630b8444b9Ssam POPR; REST_FPSTAT; 3640b8444b9Ssam rei 3657479596bSsamSCBVEC(cnxint): 3667479596bSsam CHECK_SFE(4) 3677479596bSsam SAVE_FPSTAT(4); PUSHR; 3686ed0f239Ssam pushl $CPCONS; callf $8,_cnxint; 3696ed0f239Ssam incl _intrcnt+I_CNX 3706ed0f239Ssam incl _cnt+V_INTR 3710b8444b9Ssam POPR; REST_FPSTAT; 3720b8444b9Ssam rei 3737479596bSsamSCBVEC(rmtrint): 3747479596bSsam CHECK_SFE(4) 3757479596bSsam SAVE_FPSTAT(4); PUSHR; 3766ed0f239Ssam pushl $CPREMOT; callf $8,_cnrint; 3776ed0f239Ssam incl _intrcnt+I_RMTR 3786ed0f239Ssam incl _cnt+V_INTR 3790b8444b9Ssam POPR; REST_FPSTAT; 3800b8444b9Ssam rei 3817479596bSsamSCBVEC(rmtxint): 3827479596bSsam CHECK_SFE(4) 3837479596bSsam SAVE_FPSTAT(4); PUSHR; 3846ed0f239Ssam pushl $CPREMOT; callf $8,_cnxint; 3856ed0f239Ssam incl _intrcnt+I_RMTX 3866ed0f239Ssam incl _cnt+V_INTR 3870b8444b9Ssam POPR; REST_FPSTAT; 3880b8444b9Ssam rei 3897479596bSsam 3900b8444b9Ssam#define PUSHPCPSL pushl 4+FPSPC+REGSPC(sp); pushl 4+FPSPC+REGSPC(sp); 3917479596bSsam 3927479596bSsamSCBVEC(hardclock): 3930b8444b9Ssam tstl _clk_enable 3940b8444b9Ssam bneq 1f 3950b8444b9Ssam rei 3960b8444b9Ssam1: 3977479596bSsam CHECK_SFE(4) 3980b8444b9Ssam SAVE_FPSTAT(4); PUSHR 3997479596bSsam PUSHPCPSL # push pc and psl 4007479596bSsam callf $12,_hardclock # hardclock(pc,psl) 4016ed0f239Ssam incl _intrcnt+I_CLOCK 4027479596bSsam incl _cnt+V_INTR ## temp so not to break vmstat -= HZ 4030b8444b9Ssam POPR; REST_FPSTAT 4047479596bSsam rei 4057479596bSsamSCBVEC(softclock): 4067479596bSsam CHECK_SFE(4) 4070b8444b9Ssam SAVE_FPSTAT(4); PUSHR; 4087479596bSsam PUSHPCPSL # push pc and psl 4097479596bSsam callf $12,_softclock # softclock(pc,psl) 4106ed0f239Ssam incl _cnt+V_SOFT 4110b8444b9Ssam POPR; REST_FPSTAT 4127479596bSsam rei 4137479596bSsam 4147479596bSsam/* 415477ef2c3Ssam * Stray VERSAbus interrupt catch routines 416477ef2c3Ssam */ 417477ef2c3Ssam .data 418477ef2c3Ssam#define PJ .align 2; callf $4,_Xvstray 419477ef2c3Ssam .globl _catcher 420477ef2c3Ssam_catcher: 421477ef2c3Ssam PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 422477ef2c3Ssam PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 423477ef2c3Ssam PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 424477ef2c3Ssam PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 425477ef2c3Ssam PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 426477ef2c3Ssam PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 427477ef2c3Ssam PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 428477ef2c3Ssam PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 429477ef2c3Ssam PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 430477ef2c3Ssam PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 431477ef2c3Ssam PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 432477ef2c3Ssam PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ;PJ 433477ef2c3Ssam 434477ef2c3Ssam .align 2 435477ef2c3Ssam .globl _cold 436477ef2c3Ssam_cold: .long 0x3 437477ef2c3Ssam 438477ef2c3Ssam .text 439477ef2c3SsamSCBVEC(vstray): 440477ef2c3Ssam .word 0 441477ef2c3Ssam bbc $0,_cold,2f # system running? 442477ef2c3Ssam bbc $1,_cold,1f # doing autoconfig? 443477ef2c3Ssam jbr 3f # random interrupt, ignore 444477ef2c3Ssam1: 445477ef2c3Ssam mfpr $IPL,r12 # ...setup br and cvec 446477ef2c3Ssam subl3 $_catcher+7,-8(fp),r11; shar $3,r11,r11 447477ef2c3Ssam addl2 $SCB_DEVBASE,r11 448477ef2c3Ssam jbr 3f 449477ef2c3Ssam2: 450477ef2c3Ssam PUSHR 451477ef2c3Ssam subl3 $_catcher+7,-8(fp),r0; shar $3,r0,r0 452477ef2c3Ssam addl3 $SCB_DEVBASE,r0,-(sp); 453477ef2c3Ssam mfpr $IPL,-(sp) 454477ef2c3Ssam PRINTF(2, "stray intr ipl %x vec %x\n") 455477ef2c3Ssam POPR 456477ef2c3Ssam3: moval 0f,-8(fp); ret # pop callf frame... 457477ef2c3Ssam0: rei # ...and return 458477ef2c3Ssam 459477ef2c3Ssam/* 4607479596bSsam * Trap and fault vector routines 4617479596bSsam */ 4627479596bSsam#define TRAP(a) pushl $T_/**/a; jbr alltraps 4637479596bSsam 4647479596bSsam/* 4657479596bSsam * Ast delivery (profiling and/or reschedule) 4667479596bSsam */ 4677479596bSsam 4687479596bSsamSCBVEC(kspnotval): 4697479596bSsam CHECK_SFE(4) 4707479596bSsam pushl $0; 4717479596bSsam SAVE_FPSTAT(8) 4727479596bSsam TRAP(KSPNOTVAL) 4737479596bSsamSCBVEC(privinflt): 4747479596bSsam CHECK_SFE(4) 4757479596bSsam pushl $0; 4767479596bSsam SAVE_FPSTAT(8) 4777479596bSsam TRAP(PRIVINFLT) 4787479596bSsamSCBVEC(resopflt): 4797479596bSsam CHECK_SFE(4) 4807479596bSsam pushl $0; 4817479596bSsam SAVE_FPSTAT(8) 4827479596bSsam TRAP(RESOPFLT) 4837479596bSsamSCBVEC(resadflt): 4847479596bSsam CHECK_SFE(4) 4857479596bSsam pushl $0; 4867479596bSsam SAVE_FPSTAT(8) 4877479596bSsam TRAP(RESADFLT) 4887479596bSsamSCBVEC(bptflt): 4897479596bSsam CHECK_SFE(4) 4907479596bSsam pushl $0; 4917479596bSsam SAVE_FPSTAT(8) 4927479596bSsam TRAP(BPTFLT) 493e281991cSsamSCBVEC(kdbintr): 494e281991cSsam CHECK_SFE(4); 495e281991cSsam pushl $0; 496e281991cSsam SAVE_FPSTAT(8); 497e281991cSsam TRAP(KDBTRAP); 4987479596bSsamSCBVEC(tracep): 4997479596bSsam CHECK_SFE(4) 5007479596bSsam pushl $0; 5017479596bSsam SAVE_FPSTAT(8) 5027479596bSsam TRAP(TRCTRAP) 5037479596bSsamSCBVEC(alignflt): 50463a4e097Ssam#ifdef ALIGN 5059dab7c56Ssam bitl $PSL_CURMOD,4(sp) 5069dab7c56Ssam jeql align_excp # Can't emulate for kernel mode ! 5079dab7c56Ssam jbr non_aligned # Only emulated for user mode. 5089dab7c56Ssamalign_excp: 5099dab7c56Ssam#else 5107479596bSsam CHECK_SFE(4) 5119dab7c56Ssam#endif 5127479596bSsam pushl $0; 5137479596bSsam SAVE_FPSTAT(8) 5147479596bSsam TRAP(ALIGNFLT) 5157479596bSsamSCBVEC(arithtrap): 5167479596bSsam CHECK_SFE(8) 5177479596bSsam SAVE_FPSTAT(8) 5187479596bSsam TRAP(ARITHTRAP) 5197479596bSsam 5207479596bSsamSCBVEC(protflt): 5217479596bSsam CHECK_SFE(12) 5227479596bSsam bitl $1,(sp)+ 5237479596bSsam jneq segflt 5247479596bSsam SAVE_FPSTAT(8) 5257479596bSsam TRAP(PROTFLT) 5267479596bSsamsegflt: 5277479596bSsam SAVE_FPSTAT(8) 5287479596bSsam TRAP(SEGFLT) 5297479596bSsam 5300b8444b9SsamSCBVEC(fpm): # Floating Point Emulation 53163a4e097Ssam#ifdef FPE 5327479596bSsam CHECK_SFE(16) 5337479596bSsam SAVE_FPSTAT(16) 5349dab7c56Ssam incl _cnt+V_FPE # count emulation traps 5357479596bSsam callf $4,_fpemulate 5367479596bSsam REST_FPSTAT 53763a4e097Ssam#endif 5387479596bSsam moval 8(sp),sp # Pop operand 5397479596bSsam tstl (sp) # Stack= PSL, PC, return_code 5407479596bSsam jneq _Xarithtrap # If not OK, emulate F.P. exception 5417479596bSsam movab 4(sp),sp # Else remove return_code and 5427479596bSsam rei 5437479596bSsam 5447479596bSsamSCBVEC(sfexcep): 5457479596bSsam CHECK_SFE(4) 5467479596bSsam pushl $0 5477479596bSsam SAVE_FPSTAT(8) 5487479596bSsam TRAP(ASTFLT) 5497479596bSsam 5507479596bSsamSCBVEC(transflt): 5517479596bSsam CHECK_SFE(12) 55220b06c77Skarels bitl $2,(sp)+ 5537479596bSsam bneq tableflt 5547479596bSsampageflt: 5557479596bSsam SAVE_FPSTAT(8) 5567479596bSsam TRAP(PAGEFLT) 5577479596bSsamtableflt: 5587479596bSsam SAVE_FPSTAT(8) 5597479596bSsam TRAP(TABLEFLT) 5607479596bSsam 5617479596bSsam#define REST_STACK movab 4(sp), sp; REST_FPSTAT; movab 4(sp), sp 5627479596bSsam 5637479596bSsamalltraps: 5647479596bSsam mfpr $USP,-(sp); 5650b8444b9Ssam callf $4,_trap; 5660b8444b9Ssam mtpr (sp)+,$USP 5677479596bSsam incl _cnt+V_TRAP 5680b8444b9Ssam REST_STACK # pop type, code, and fp stuff 5697479596bSsam mtpr $HIGH,$IPL ## dont go to a higher IPL (GROT) 5707479596bSsam rei 5717479596bSsam 5727479596bSsamSCBVEC(syscall): 5737479596bSsam CHECK_SFE(8) 5747479596bSsam SAVE_FPSTAT(8) 5757479596bSsam pushl $T_SYSCALL 5760b8444b9Ssam mfpr $USP,-(sp); 5770b8444b9Ssam callf $4,_syscall; 5780b8444b9Ssam mtpr (sp)+,$USP 5797479596bSsam incl _cnt+V_SYSCALL 5800b8444b9Ssam REST_STACK # pop type, code, and fp stuff 5817479596bSsam mtpr $HIGH,$IPL ## dont go to a higher IPL (GROT) 5827479596bSsam rei 5837479596bSsam 5847479596bSsam/* 58557e96b6cSsam * System page table. 58657e96b6cSsam * 587477ef2c3Ssam * Mbmap and Usrptmap are enlarged by CLSIZE entries 588477ef2c3Ssam * as they are managed by resource maps starting with index 1 or CLSIZE. 5897479596bSsam */ 5907479596bSsam#define vaddr(x) ((((x)-_Sysmap)/4)*NBPG+SYSTEM) 5917479596bSsam#define SYSMAP(mname, vname, npte) \ 5927479596bSsam_/**/mname: .globl _/**/mname; \ 593477ef2c3Ssam .space (npte)*4; \ 5947479596bSsam .globl _/**/vname; \ 5957479596bSsam .set _/**/vname,vaddr(_/**/mname) 5965bffa242Skarels#define ADDMAP(npte) .space (npte)*4 5977479596bSsam 5987479596bSsam .data 5997479596bSsam .align 2 6007479596bSsam SYSMAP(Sysmap ,Sysbase ,SYSPTSIZE ) 6017479596bSsam SYSMAP(Forkmap ,forkutl ,UPAGES ) 6027479596bSsam SYSMAP(Xswapmap ,xswaputl ,UPAGES ) 6037479596bSsam SYSMAP(Xswap2map,xswap2utl ,UPAGES ) 6047479596bSsam SYSMAP(Swapmap ,swaputl ,UPAGES ) 6057479596bSsam SYSMAP(Pushmap ,pushutl ,UPAGES ) 6067479596bSsam SYSMAP(Vfmap ,vfutl ,UPAGES ) 6077479596bSsam SYSMAP(CMAP1 ,CADDR1 ,1 ) 6087479596bSsam SYSMAP(CMAP2 ,CADDR2 ,1 ) 6097479596bSsam SYSMAP(mmap ,vmmap ,1 ) 610477ef2c3Ssam SYSMAP(alignmap ,alignutl ,1 ) /* XXX */ 6117479596bSsam SYSMAP(msgbufmap,msgbuf ,MSGBUFPTECNT ) 6129ea5c536Sbostic SYSMAP(Mbmap ,mbutl ,NMBCLUSTERS*MCLBYTES/NBPG+CLSIZE ) 61382e348a9Smckusick#ifdef MFS 614d357015aSbostic#include "ufs/mfsiom.h" 6159dcee661Smckusick /* 61682e348a9Smckusick * Used by the mfs_doio() routine for physical I/O 6179dcee661Smckusick */ 61882e348a9Smckusick SYSMAP(Mfsiomap ,mfsiobuf ,MFS_MAPREG ) 61982e348a9Smckusick#endif /* MFS */ 62082e348a9Smckusick#ifdef NFS 621d357015aSbostic#include "nfs/nfsiom.h" 62282e348a9Smckusick /* 62382e348a9Smckusick * Used by the nfs_doio() routine for physical I/O 62482e348a9Smckusick */ 62582e348a9Smckusick SYSMAP(Nfsiomap ,nfsiobuf ,NFS_MAPREG ) 6269dcee661Smckusick#endif /* NFS */ 627e7123664Smckusick /* 6288fd09904Smckusick * This is the map used by the kernel memory allocator. 6298fd09904Smckusick * It is expanded as necessary by the special features 6308fd09904Smckusick * that use it. 6318fd09904Smckusick */ 6322ee96521Smckusick SYSMAP(kmempt ,kmembase ,NKMEMCLUSTERS*CLSIZE ) 6332ee96521Smckusick#ifdef SYSVSHM 6342ee96521Smckusick ADDMAP( SHMMAXPGS ) 6352ee96521Smckusick#endif 6368fd09904Smckusick#ifdef GPROF 6378fd09904Smckusick ADDMAP( 600*CLSIZE ) 6388fd09904Smckusick#endif 6398fd09904Smckusick /* 640dbe30e8bSkarels * Enlarge kmempt as needed for bounce buffers allocated 641e7123664Smckusick * by tahoe controllers. 642e7123664Smckusick */ 6439ea5c536Sbostic#include "hd.h" 6449ea5c536Sbostic#if NHD > 0 6459ea5c536Sbostic ADDMAP( NHDC*(MAXPHYS/NBPG+CLSIZE) ) 6469ea5c536Sbostic#endif 647e7123664Smckusick#include "dk.h" 6489ea5c536Sbostic#if NDK > 0 6495bffa242Skarels ADDMAP( NVD*(MAXPHYS/NBPG+CLSIZE) ) 6509ea5c536Sbostic#endif 651e7123664Smckusick#include "yc.h" 6529ea5c536Sbostic#if NYC > 0 6535bffa242Skarels ADDMAP( NCY*(MAXPHYS/NBPG+CLSIZE) ) 6549ea5c536Sbostic#endif 655dbe30e8bSkarels#include "mp.h" 6565bffa242Skarels ADDMAP( NMP*14 ) 657dbe30e8bSkarels SYSMAP(ekmempt ,kmemlimit ,0 ) 658dbe30e8bSkarels 659477ef2c3Ssam SYSMAP(VMEMbeg ,vmembeg ,0 ) 66057e96b6cSsam SYSMAP(VMEMmap ,vmem ,VBIOSIZE ) 661e7123664Smckusick SYSMAP(VMEMmap1 ,vmem1 ,0 ) 662e7123664Smckusick#include "ace.h" 663bbf21aa2Sbostic#if NACE > 0 6645bffa242Skarels ADDMAP( NACE*32 ) 665bbf21aa2Sbostic#endif 666bbf21aa2Sbostic#if NHD > 0 667bbf21aa2Sbostic ADDMAP( NHDC ) 668bbf21aa2Sbostic#endif 669fb5e3f58Skarels#include "vx.h" 670fb5e3f58Skarels#if NVX > 0 671fb5e3f58Skarels ADDMAP( NVX * 16384/NBPG ) 672fb5e3f58Skarels#endif 673477ef2c3Ssam SYSMAP(VMEMend ,vmemend ,0 ) 674dbe30e8bSkarels 67520b06c77Skarels SYSMAP(VBmap ,vbbase ,CLSIZE ) 6769ea5c536Sbostic#if NHD > 0 6779ea5c536Sbostic ADDMAP( NHDC*(MAXPHYS/NBPG+CLSIZE) ) 6789ea5c536Sbostic#endif 6799ea5c536Sbostic#if NDK > 0 6805bffa242Skarels ADDMAP( NVD*(MAXPHYS/NBPG+CLSIZE) ) 6819ea5c536Sbostic#endif 6829ea5c536Sbostic#if NYC > 0 6835bffa242Skarels ADDMAP( NCY*(MAXPHYS/NBPG+CLSIZE) ) 6849ea5c536Sbostic#endif 6855bffa242Skarels ADDMAP( NMP*14 ) 68657e96b6cSsam SYSMAP(eVBmap ,vbend ,0 ) 687dbe30e8bSkarels 688477ef2c3Ssam SYSMAP(Usrptmap ,usrpt ,USRPTSIZE+CLSIZE ) 6897479596bSsameSysmap: 6907479596bSsam .globl _Syssize 6917479596bSsam .set _Syssize,(eSysmap-_Sysmap)/4 6927479596bSsam 6937479596bSsam .text 6947479596bSsam/* 6957479596bSsam * Initialization 6967479596bSsam * 6977479596bSsam * IPL 0x1f; MME 0; scbb, pcbb, sbr, slr, isp, ksp not set 6987479596bSsam */ 6997479596bSsam .align 2 7007479596bSsam .globl start 7017479596bSsamstart: 7027479596bSsam .word 0 7037479596bSsam/* set system control block base and system page table params */ 7047479596bSsam mtpr $_scb-SYSTEM,$SCBB 7057479596bSsam mtpr $_Sysmap-SYSTEM,$SBR 7067479596bSsam mtpr $_Syssize,$SLR 7077479596bSsam/* double map the kernel into the virtual user addresses of phys mem */ 7087479596bSsam mtpr $_Sysmap,$P0BR 7097479596bSsam mtpr $_Syssize,$P0LR 7100b8444b9Ssam mtpr $_Sysmap,$P1BR # against Murphy 7117479596bSsam mtpr $_Syssize,$P1LR 7127479596bSsam/* set ISP */ 7130b8444b9Ssam movl $_intstack-SYSTEM+NISP*NBPG,sp # still physical 7147479596bSsam mtpr $_intstack+NISP*NBPG,$ISP 715fb5e3f58Skarels/* count up memory; _physmem contains limit */ 7167479596bSsam clrl r7 717fb5e3f58Skarels shll $PGSHIFT,_physmem,r8 718fb5e3f58Skarels decl r8 7197479596bSsam1: pushl $1; pushl r7; callf $12,_badaddr; tstl r0; bneq 9f 720fb5e3f58Skarels ACBL(r8,$64*1024,r7,1b) 7217479596bSsam9: 7227479596bSsam/* clear memory from kernel bss and pages for proc 0 u. and page table */ 723e281991cSsam movab _edata,r6; andl2 $~SYSTEM,r6 724e281991cSsam movab _end,r5; andl2 $~SYSTEM,r5 725189fe34eSkarels#ifdef KADB 726e281991cSsam subl2 $4,r5 727e281991cSsam1: clrl (r6); ACBL(r5,$4,r6,1b) # clear just bss 728e281991cSsam addl2 $4,r5 729e281991cSsam bbc $6,r11,0f # check RB_KDB 730e281991cSsam andl3 $~SYSTEM,r9,r5 # skip symbol & string tables 731e281991cSsam andl3 $~SYSTEM,r9,r6 732e281991cSsam#endif 733e281991cSsam0: orl3 $SYSTEM,r5,r9 # convert to virtual address 734e281991cSsam addl2 $NBPG-1,r9 # roundup to next page 7357479596bSsam addl2 $(UPAGES*NBPG)+NBPG+NBPG,r5 7367479596bSsam1: clrl (r6); ACBL(r5,$4,r6,1b) 7370b8444b9Ssam/* trap(), syscall(), and fpemulate() save r0-r12 in the entry mask */ 7387479596bSsam orw2 $0x01fff,_trap 7397479596bSsam orw2 $0x01fff,_syscall 74063a4e097Ssam#ifdef FPE 7417479596bSsam orw2 $0x01fff,_fpemulate 74263a4e097Ssam#endif 7430b8444b9Ssam orw2 $0x01ffc,_panic # for debugging (no r0|r1) 744477ef2c3Ssam callf $4,_fixctlrmask # setup for autoconfig 7457479596bSsam/* initialize system page table: scb and int stack writeable */ 7467479596bSsam clrl r2 7477479596bSsam movab eintstack,r1 7480b8444b9Ssam andl2 $~SYSTEM,r1 7490b8444b9Ssam shrl $PGSHIFT,r1,r1 # r1-page number of eintstack 750844a1895Skarels/* make 1st page processor storage read/only, 2nd read/write */ 7517479596bSsam orl3 $PG_V|PG_KR,r2,_Sysmap[r2]; incl r2; 752844a1895Skarels orl3 $PG_V|PG_KW,r2,_Sysmap[r2]; incl r2; 7530b8444b9Ssam/* other parts of the system are read/write for kernel */ 7547479596bSsam1: orl3 $PG_V|PG_KW,r2,_Sysmap[r2]; # data:kernel write+phys=virtual 7557479596bSsam aoblss r1,r2,1b 7567479596bSsam/* make rsstk read-only as red zone for interrupt stack */ 7570b8444b9Ssam andl2 $~PG_PROT,_rsstkmap 7580b8444b9Ssam orl2 $PG_V|PG_KR,_rsstkmap 7597479596bSsam/* make kernel text space read-only */ 7607479596bSsam movab _etext+NBPG-1,r1 7610b8444b9Ssam andl2 $~SYSTEM,r1 7627479596bSsam shrl $PGSHIFT,r1,r1 7637479596bSsam1: orl3 $PG_V|PG_KR,r2,_Sysmap[r2] 7647479596bSsam aoblss r1,r2,1b 7657479596bSsam/* make kernel data, bss, read-write */ 766e281991cSsam andl3 $~SYSTEM,r9,r1 7677479596bSsam shrl $PGSHIFT,r1,r1 7687479596bSsam1: orl3 $PG_V|PG_KW,r2,_Sysmap[r2] 7697479596bSsam aoblss r1,r2,1b 7700b8444b9Ssam/* go to mapped mode, have to change both pc and sp to system addresses */ 7717479596bSsam mtpr $1,$TBIA 7720b8444b9Ssam mtpr $1,$PADC # needed by HW parity&ECC logic 7730b8444b9Ssam mtpr $1,$PACC # just in case 7747479596bSsam mtpr $1,$MME 7757479596bSsam movab SYSTEM(sp),sp 7767479596bSsam jmp *$0f 7777479596bSsam0: 7787479596bSsam/* disable any interrupts */ 7797479596bSsam movl $0,_intenable 7807479596bSsam/* init mem sizes */ 781fb5e3f58Skarels shrl $PGSHIFT,r7,_physmem 7820b8444b9Ssam/* setup context for proc[0] == scheduler */ 783e281991cSsam andl3 $~SYSTEM,r9,r6 # convert to physical 7840b8444b9Ssam andl2 $~(NBPG-1),r6 # make page boundary 7857479596bSsam/* setup page table for proc[0] */ 7867479596bSsam shrl $PGSHIFT,r6,r3 # r3 = btoc(r6) 7877479596bSsam orl3 $PG_V|PG_KW,r3,_Usrptmap # init first upt entry 7887479596bSsam incl r3 # r3 - next page 7897479596bSsam movab _usrpt,r0 # r0 - first user page 7907479596bSsam mtpr r0,$TBIS 7917479596bSsam/* init p0br, p0lr */ 7920b8444b9Ssam mtpr r0,$P0BR # no p0 for proc[0] 7937479596bSsam mtpr $0,$P0LR 7940b8444b9Ssam mtpr r0,$P1BR # no p1 either 7957479596bSsam mtpr $0,$P1LR 7967479596bSsam/* init p2br, p2lr */ 7977479596bSsam movab NBPG(r0),r0 7987479596bSsam movl $PPAGES-UPAGES,r1 7997479596bSsam mtpr r1,$P2LR 8007479596bSsam moval -4*PPAGES(r0),r2 8017479596bSsam mtpr r2,$P2BR 8027479596bSsam/* setup mapping for UPAGES of _u */ 8030b8444b9Ssam clrl r2 8047479596bSsam movl $SYSTEM,r1 8057479596bSsam addl2 $UPAGES,r3 8067479596bSsam jbr 2f 8077479596bSsam1: decl r3 8080b8444b9Ssam moval -NBPG(r1),r1 # r1 = virtual add of next (downward) _u page 8097479596bSsam subl2 $4,r0 # r0 = pte address 8107479596bSsam orl3 $PG_V|PG_URKW,r3,(r0) 8117479596bSsam mtpr r1,$TBIS 8127479596bSsam2: aobleq $UPAGES,r2,1b 8137479596bSsam/* initialize (slightly) the pcb */ 8147479596bSsam movab UPAGES*NBPG(r1),PCB_KSP(r1) # KSP starts at end of _u 8157479596bSsam movl r1,PCB_USP(r1) # USP starts just below _u 8167479596bSsam mfpr $P0BR,PCB_P0BR(r1) 8177479596bSsam mfpr $P0LR,PCB_P0LR(r1) 8187479596bSsam mfpr $P1BR,PCB_P1BR(r1) 8197479596bSsam mfpr $P1LR,PCB_P1LR(r1) 8207479596bSsam mfpr $P2BR,PCB_P2BR(r1) 8217479596bSsam mfpr $P2LR,PCB_P2LR(r1) 8227479596bSsam movl $CLSIZE,PCB_SZPT(r1) # init u.u_pcb.pcb_szpt 823e281991cSsam movl r9,PCB_R9(r1) # r9 obtained from boot 824e281991cSsam movl r10,PCB_R10(r1) # r10 obtained from boot 8257479596bSsam movl r11,PCB_R11(r1) # r11 obtained from CP on boot 8267479596bSsam movab 1f,PCB_PC(r1) # initial pc 8277479596bSsam clrl PCB_PSL(r1) # kernel mode, ipl=0 8287479596bSsam shll $PGSHIFT,r3,r3 8290b8444b9Ssam mtpr r3,$PCBB # first pcbb (physical) 8300b8444b9Ssam/* go to kernel mode */ 8317479596bSsam ldpctx 8320b8444b9Ssam rei # Actually next instruction: 8337479596bSsam/* put signal trampoline code in u. area */ 8340b8444b9Ssam1: movab sigcode,r0 8350b8444b9Ssam movab _u+PCB_SIGC,r1 8360b8444b9Ssam movl $19,r2 8370b8444b9Ssam movblk 838bbb01fa4Ssam/* save boot device in global _bootdev */ 839bbb01fa4Ssam movl r10,_bootdev 8407479596bSsam/* save reboot flags in global _boothowto */ 8417479596bSsam movl r11,_boothowto 8423274904bSbostic#ifdef KADB 843e281991cSsam/* save end of symbol & string table in global _bootesym */ 844e281991cSsam subl3 $NBPG-1,r9,_bootesym 8453274904bSbostic#endif 8467479596bSsam/* calculate firstaddr, and call main() */ 847e281991cSsam andl3 $~SYSTEM,r9,r0 8487479596bSsam shrl $PGSHIFT,r0,-(sp) 8490b8444b9Ssam addl2 $UPAGES+1,(sp) # first physical unused page 8507479596bSsam callf $8,_main 8517479596bSsam/* proc[1] == /etc/init now running here in kernel mode; run icode */ 8527479596bSsam pushl $PSL_CURMOD # User mode PSL 8537479596bSsam pushl $0 # PC = 0 (virtual now) 8547479596bSsam rei 8557479596bSsam 8560b8444b9Ssam/* 8570b8444b9Ssam * Mask for saving/restoring registers on entry to 8580b8444b9Ssam * a user signal handler. Space for the registers 8590b8444b9Ssam * is reserved in sendsig, so beware if you want 8600b8444b9Ssam * to change the mask. 8610b8444b9Ssam */ 8620b8444b9Ssam#define SIGREGS (R0|R1|R2|R3|R4|R5) 8637479596bSsam .align 2 8640b8444b9Ssam .globl sigcode 8650b8444b9Ssamsigcode: 8660b8444b9Ssam storer $SIGREGS,16(sp) # save volatile registers 8670b8444b9Ssam calls $4*3+4,*12(sp) # params pushed by sendsig for handler 8680b8444b9Ssam loadr $SIGREGS,4(sp) # restore volatile registers 8690b8444b9Ssam movab 24(sp),fp # use parameter list set up in sendsig 8700b8444b9Ssam kcall $SYS_sigreturn # cleanup mask and onsigstack 8710b8444b9Ssam halt # sigreturn does not return! 8720b8444b9Ssam 8730b8444b9Ssam .globl _icode 8740b8444b9Ssam .globl _initflags 8750b8444b9Ssam .globl _szicode 876f5e105aeSmckusick .data 8770b8444b9Ssam/* 8780b8444b9Ssam * Icode is copied out to process 1 to exec /etc/init. 8790b8444b9Ssam * If the exec fails, process 1 exits. 8800b8444b9Ssam */ 8810b8444b9Ssam .align 2 8820b8444b9Ssam_icode: 88319e071f5Sbostic /* try /sbin/init */ 884250e3e7bSkarels pushl $0 88519e071f5Sbostic pushab b`argv1-l0(pc) 88619e071f5Sbosticl0: pushab b`init1-l1(pc) 8870b8444b9Ssaml1: pushl $2 8880b8444b9Ssam movab (sp),fp 889250e3e7bSkarels kcall $SYS_execve 89019e071f5Sbostic /* try /etc/init */ 891250e3e7bSkarels pushl $0 89219e071f5Sbostic pushab b`argv2-l2(pc) 89319e071f5Sbosticl2: pushab b`init2-l3(pc) 89419e071f5Sbosticl3: pushl $2 89519e071f5Sbostic movab (sp),fp 896250e3e7bSkarels kcall $SYS_execve 89719e071f5Sbostic /* give up */ 898e034e083Skarels pushl r0 89919e071f5Sbostic pushl $1 90019e071f5Sbostic movab (sp),fp 9010b8444b9Ssam kcall $SYS_exit 9020b8444b9Ssam 90319e071f5Sbosticinit1: .asciz "/sbin/init" 90419e071f5Sbosticinit2: .asciz "/etc/init" 9050b8444b9Ssam .align 2 9060b8444b9Ssam_initflags: 9070b8444b9Ssam .long 0 90819e071f5Sbosticargv1: .long init1+6-_icode 90919e071f5Sbostic .long _initflags-_icode 91019e071f5Sbostic .long 0 91119e071f5Sbosticargv2: .long init2+5-_icode 9120b8444b9Ssam .long _initflags-_icode 9130b8444b9Ssam .long 0 9140b8444b9Ssam_szicode: 9150b8444b9Ssam .long _szicode-_icode 916f5e105aeSmckusick .text 9177479596bSsam 9187479596bSsam/* 9197479596bSsam * Primitives 9207479596bSsam */ 9217479596bSsam 9227479596bSsam/* 9237479596bSsam * badaddr(addr, len) 9247479596bSsam * see if access addr with a len type instruction causes a machine check 9257479596bSsam * len is length of access (1=byte, 2=short, 4=long) 9267479596bSsam * r0 = 0 means good(exists); r0 =1 means does not exist. 9277479596bSsam */ 9280b8444b9SsamENTRY(badaddr, R3|R4) 9297479596bSsam mfpr $IPL,r1 9307479596bSsam mtpr $HIGH,$IPL 931477ef2c3Ssam movl _scb+SCB_BUSERR,r2 9327479596bSsam movl 4(fp),r3 9337479596bSsam movl 8(fp),r4 934477ef2c3Ssam movab 9f,_scb+SCB_BUSERR 9357479596bSsam bbc $0,r4,1f; tstb (r3) 9367479596bSsam1: bbc $1,r4,1f; tstw (r3) 9377479596bSsam1: bbc $2,r4,1f; tstl (r3) 9380b8444b9Ssam1: clrl r0 939477ef2c3Ssam2: movl r2,_scb+SCB_BUSERR 9407479596bSsam mtpr r1,$IPL 9417479596bSsam ret 9427479596bSsam 943cff2b5daSbostic/* 944cff2b5daSbostic * wbadaddr(addr, len, value) 945cff2b5daSbostic * see if write of value to addr with a len type instruction causes 946cff2b5daSbostic * a machine check 947cff2b5daSbostic * len is length of access (1=byte, 2=short, 4=long) 948cff2b5daSbostic * r0 = 0 means good(exists); r0 =1 means does not exist. 949cff2b5daSbostic */ 950cff2b5daSbosticENTRY(wbadaddr, R3|R4) 951cff2b5daSbostic mfpr $IPL,r1 952cff2b5daSbostic mtpr $HIGH,$IPL 953cff2b5daSbostic movl _scb+SCB_BUSERR,r2 954cff2b5daSbostic movl 4(fp),r3 955cff2b5daSbostic movl 8(fp),r4 956cff2b5daSbostic movab 9f,_scb+SCB_BUSERR 957cff2b5daSbostic bbc $0,r4,1f; movb 15(fp), (r3) 958cff2b5daSbostic1: bbc $1,r4,1f; movw 14(fp), (r3) 959cff2b5daSbostic1: bbc $2,r4,1f; movl 12(fp), (r3) 960fb5e3f58Skarels1: movl $30000,r0 # delay for error interrupt 961fb5e3f58Skarels1: decl r0 962fb5e3f58Skarels jneq 1b 963fb5e3f58Skarels2: movl r2,_scb+SCB_BUSERR # made it w/o machine checks; r0 is 0 964cff2b5daSbostic mtpr r1,$IPL 965cff2b5daSbostic ret 966cff2b5daSbostic 9677479596bSsam .align 2 9680b8444b9Ssam9: # catch buss error (if it comes) 9697479596bSsam andl3 4(sp),$ERRCD,r0 9707479596bSsam cmpl r0,$APE 9717479596bSsam jneq 1f 9720b8444b9Ssam halt # address parity error 9737479596bSsam1: cmpl r0,$VBE 9747479596bSsam jneq 1f 9757479596bSsam halt # Versabus error 9767479596bSsam1: 9777479596bSsam movl $1,r0 # Anything else = bad address 9787479596bSsam movab 8(sp),sp # discard buss error trash 9797479596bSsam movab 2b,(sp) # new program counter on stack. 9807479596bSsam rei 9817479596bSsam 9827479596bSsam/* 9837479596bSsam * badcyaddr(addr) 9847479596bSsam * see if access tape master controller addr causes a bus error 9857479596bSsam * r0 = 0: no error; r0 = 1: timeout error. 9867479596bSsam */ 9870b8444b9SsamENTRY(badcyaddr, 0) 9887479596bSsam mfpr $IPL,r1 9897479596bSsam mtpr $HIGH,$IPL 9900b8444b9Ssam clrl r2 9910b8444b9Ssam movab 2f,nofault 9927479596bSsam movob $-1, *4(fp) 9930b8444b9Ssam1: aobleq $1000, r2, 1b 9940b8444b9Ssam clrl nofault # made it w/o bus error 9950b8444b9Ssam clrl r0 9960b8444b9Ssam jbr 3f 9970b8444b9Ssam2: movl $1,r0 9980b8444b9Ssam3: mtpr r1,$IPL 9997479596bSsam ret 10007479596bSsam 10010b8444b9Ssam/* 10020b8444b9Ssam * peek(addr) 10030b8444b9Ssam * fetch word and catch any bus error 10040b8444b9Ssam */ 10050b8444b9SsamENTRY(peek, 0) 10060b8444b9Ssam mfpr $IPL,r1 10070b8444b9Ssam mtpr $0x18,$IPL # not reentrant 10080b8444b9Ssam movl 4(fp),r2 10090b8444b9Ssam movab 1f,nofault 10100b8444b9Ssam movw (r2),r0 10110b8444b9Ssam clrl nofault 10120b8444b9Ssam andl2 $0xffff,r0 10130b8444b9Ssam jbr 2f 10140b8444b9Ssam1: movl $-1,r0 # bus error 10150b8444b9Ssam2: mtpr r1,$IPL 10167479596bSsam ret 10177479596bSsam 10180b8444b9Ssam/* 10190b8444b9Ssam * poke(addr, val) 10200b8444b9Ssam * write word and catch any bus error 10210b8444b9Ssam */ 10220b8444b9SsamENTRY(poke, R3) 10230b8444b9Ssam mfpr $IPL,r1 10240b8444b9Ssam mtpr $0x18,$IPL # not reentrant 10250b8444b9Ssam movl 4(fp),r2 10260b8444b9Ssam movl 8(fp),r3 10270b8444b9Ssam clrl r0 10280b8444b9Ssam movab 1f,nofault 10290b8444b9Ssam movw r3,(r2) 10300b8444b9Ssam clrl nofault 10310b8444b9Ssam jbr 2f 10320b8444b9Ssam1: movl $-1,r0 # bus error 10330b8444b9Ssam2: mtpr r1,$IPL 10340b8444b9Ssam ret 10350b8444b9Ssam 10360b8444b9Ssam/* 10370b8444b9Ssam * Copy a potentially overlapping block of memory. 10380b8444b9Ssam * 10390b8444b9Ssam * ovbcopy(src, dst, count) 10400b8444b9Ssam * caddr_t src, dst; unsigned count; 10410b8444b9Ssam */ 10420b8444b9SsamENTRY(ovbcopy, R3|R4) 10437479596bSsam movl 4(fp),r0 10447479596bSsam movl 8(fp),r1 10457479596bSsam movl 12(fp),r2 10467479596bSsam cmpl r0,r1 10477479596bSsam bgtru 1f # normal forward case 10487479596bSsam beql 2f # equal, nothing to do 10497479596bSsam addl2 r2,r0 # may be overlapping 10507479596bSsam cmpl r0,r1 10517479596bSsam bgtru 3f 10527479596bSsam subl2 r2,r0 # normal forward case 10537479596bSsam1: 10547479596bSsam movblk 10557479596bSsam2: 10567479596bSsam ret 10577479596bSsam3: 10587479596bSsam addl2 r2,r1 # overlapping, must do backwards 10597479596bSsam subl3 r0,r1,r3 10607479596bSsam movl r2,r4 10617479596bSsam jbr 5f 10627479596bSsam4: 10637479596bSsam subl2 r3,r0 10647479596bSsam subl2 r3,r1 10657479596bSsam movl r3,r2 10667479596bSsam movblk 10677479596bSsam subl2 r3,r0 10687479596bSsam subl2 r3,r1 10697479596bSsam subl2 r3,r4 10707479596bSsam5: 10717479596bSsam cmpl r4,r3 10727479596bSsam jgtr 4b 10737479596bSsam movl r4,r2 10747479596bSsam subl2 r2,r0 10757479596bSsam subl2 r2,r1 10767479596bSsam movblk 10777479596bSsam ret 10787479596bSsam 10797479596bSsam/* 10800b8444b9Ssam * Copy a null terminated string from the user address space into 10810b8444b9Ssam * the kernel address space. 10820b8444b9Ssam * 10830b8444b9Ssam * copyinstr(fromaddr, toaddr, maxlength, &lencopied) 10847479596bSsam */ 108547fd5358SmckusickENTRY(copyinstr, 0) 10860b8444b9Ssam movl 12(fp),r5 # r5 = max length 108747fd5358Smckusick jlss 5f 108847fd5358Smckusick movl 8(fp),r4 # r4 = kernel address 10890b8444b9Ssam movl 4(fp),r0 # r0 = user address 10900b8444b9Ssam andl3 $(NBPG*CLSIZE-1),r0,r2 # r2 = bytes on first page 10910b8444b9Ssam subl3 r2,$(NBPG*CLSIZE),r2 10927479596bSsam1: 10930b8444b9Ssam cmpl r5,r2 # r2 = min(bytes on page, length left); 10940b8444b9Ssam jgeq 2f 10950b8444b9Ssam movl r5,r2 10960b8444b9Ssam2: 10970b8444b9Ssam prober $1,(r0),r2 # bytes accessible? 109847fd5358Smckusick jeql 5f 10990b8444b9Ssam subl2 r2,r5 # update bytes left count 110047fd5358Smckusick movl r2,r3 # r3 = saved count 110147fd5358Smckusick movl r0,r1 110247fd5358Smckusick cmps3 # check for null 110347fd5358Smckusick tstl r2 11040b8444b9Ssam jneq 3f 110547fd5358Smckusick subl2 r3,r0 # back up r0 110647fd5358Smckusick movl r4,r1 110747fd5358Smckusick movl r3,r2 110847fd5358Smckusick movblk # copy in next piece 110947fd5358Smckusick movl r1,r4 11100b8444b9Ssam movl $(NBPG*CLSIZE),r2 # check next page 11110b8444b9Ssam tstl r5 # run out of space? 11120b8444b9Ssam jneq 1b 111398cc6a9fSmckusick movl $ENAMETOOLONG,r0 # set error code and return 111447fd5358Smckusick jbr 6f 11150b8444b9Ssam3: 11160b8444b9Ssam tstl 16(fp) # return length? 11170b8444b9Ssam beql 4f 11180b8444b9Ssam subl3 r5,12(fp),r5 # actual len = maxlen - unused pages 11190b8444b9Ssam subl2 r2,r5 # - unused on this page 11200b8444b9Ssam addl3 $1,r5,*16(fp) # + the null byte 11210b8444b9Ssam4: 112247fd5358Smckusick movl r4,r1 112347fd5358Smckusick subl3 r2,r3,r2 # calc char cnt 112447fd5358Smckusick subl2 r2,r0 # back up r0 112547fd5358Smckusick incl r2 # add on null byte 112647fd5358Smckusick movblk # copy last piece 11277479596bSsam clrl r0 11287479596bSsam ret 112947fd5358Smckusick5: 11300b8444b9Ssam movl $EFAULT,r0 113147fd5358Smckusick6: 11320b8444b9Ssam tstl 16(fp) 113347fd5358Smckusick beql 7f 11340b8444b9Ssam subl3 r5,12(fp),*16(fp) 113547fd5358Smckusick7: 11360b8444b9Ssam ret 11377479596bSsam 11380b8444b9Ssam/* 11390b8444b9Ssam * Copy a null terminated string from the kernel 11400b8444b9Ssam * address space to the user address space. 11410b8444b9Ssam * 11420b8444b9Ssam * copyoutstr(fromaddr, toaddr, maxlength, &lencopied) 11430b8444b9Ssam */ 114447fd5358SmckusickENTRY(copyoutstr, 0) 11450b8444b9Ssam movl 12(fp),r5 # r5 = max length 1146cfd41addSmckusick jlss 5f 11470b8444b9Ssam movl 4(fp),r0 # r0 = kernel address 114847fd5358Smckusick movl 8(fp),r4 # r4 = user address 114947fd5358Smckusick andl3 $(NBPG*CLSIZE-1),r4,r2 # r2 = bytes on first page 11500b8444b9Ssam subl3 r2,$(NBPG*CLSIZE),r2 11510b8444b9Ssam1: 11520b8444b9Ssam cmpl r5,r2 # r2 = min(bytes on page, length left); 11530b8444b9Ssam jgeq 2f 11540b8444b9Ssam movl r5,r2 11550b8444b9Ssam2: 115647fd5358Smckusick probew $1,(r4),r2 # bytes accessible? 1157cfd41addSmckusick jeql 5f 11580b8444b9Ssam subl2 r2,r5 # update bytes left count 115947fd5358Smckusick movl r2,r3 # r3 = saved count 116047fd5358Smckusick movl r0,r1 1161bc47b33fSkarels/* 1162bc47b33fSkarels * This is a workaround for a microcode bug that causes 1163bc47b33fSkarels * a trap type 9 when cmps3/movs3 touches the last byte 1164bc47b33fSkarels * on a valid page immediately followed by an invalid page. 1165bc47b33fSkarels */ 116647fd5358Smckusick#ifdef good_cmps3 116747fd5358Smckusick cmps3 # check for null 11680b8444b9Ssam tstl r2 11690b8444b9Ssam jneq 3b 117047fd5358Smckusick#else 117147fd5358Smckusick decl r2 117233b304f1Smckusick beql 9f # cannot handle case of r2 == 0! 117347fd5358Smckusick cmps3 # check for null up to last byte 117433b304f1Smckusick9: 117547fd5358Smckusick incl r2 117647fd5358Smckusick cmpl $1,r2 # get to last byte on page? 117747fd5358Smckusick bneq 3b 117847fd5358Smckusick tstb (r0) # last byte on page null? 117933b304f1Smckusick beql 3b 118047fd5358Smckusick incl r0 # not null, so bump pointer 118133b304f1Smckusick#endif not good_cmps3 118247fd5358Smckusick subl2 r3,r0 # back up r0 118347fd5358Smckusick movl r4,r1 118447fd5358Smckusick movl r3,r2 118547fd5358Smckusick movblk # copy out next piece 118647fd5358Smckusick movl r1,r4 11870b8444b9Ssam movl $(NBPG*CLSIZE),r2 # check next page 11880b8444b9Ssam tstl r5 # run out of space? 11890b8444b9Ssam jneq 1b 119098cc6a9fSmckusick movl $ENAMETOOLONG,r0 # set error code and return 119147fd5358Smckusick jbr 6b 1192cfd41addSmckusick5: 1193cfd41addSmckusick clrl *$0 # this should never execute, if it does 1194cfd41addSmckusick movl $EFAULT,r0 # save me a core dump (mkm - 9/87) 1195cfd41addSmckusick6: 1196cfd41addSmckusick tstl 16(fp) 1197cfd41addSmckusick beql 7f 1198cfd41addSmckusick subl3 r5,12(fp),*16(fp) 1199cfd41addSmckusick7: 1200cfd41addSmckusick ret 1201cfd41addSmckusick 12020b8444b9Ssam 12030b8444b9Ssam/* 12040b8444b9Ssam * Copy a null terminated string from one point to another in 12050b8444b9Ssam * the kernel address space. 12060b8444b9Ssam * 12070b8444b9Ssam * copystr(fromaddr, toaddr, maxlength, &lencopied) 12080b8444b9Ssam */ 120947fd5358SmckusickENTRY(copystr, 0) 121047fd5358Smckusick movl 12(fp),r3 # r3 = max length 121147fd5358Smckusick jlss 5b 12120b8444b9Ssam movl 4(fp),r0 # r0 = src address 121347fd5358Smckusick movl 8(fp),r4 # r4 = dest address 121447fd5358Smckusick clrl r5 # r5 = bytes left 121547fd5358Smckusick movl r3,r2 # r2 = max bytes to copy 121647fd5358Smckusick movl r0,r1 121747fd5358Smckusick cmps3 # check for null 121847fd5358Smckusick tstl r2 12190b8444b9Ssam jneq 3b 122047fd5358Smckusick subl2 r3,r0 # back up r0 122147fd5358Smckusick movl r4,r1 122247fd5358Smckusick movl r3,r2 122347fd5358Smckusick movblk # copy next piece 122498cc6a9fSmckusick movl $ENAMETOOLONG,r0 # set error code and return 122547fd5358Smckusick jbr 6b 12260b8444b9Ssam 12270b8444b9Ssam/* 12280b8444b9Ssam * Copy a block of data from the user address space into 12290b8444b9Ssam * the kernel address space. 12300b8444b9Ssam * 12310b8444b9Ssam * copyin(fromaddr, toaddr, count) 12320b8444b9Ssam */ 12330b8444b9SsamENTRY(copyin, 0) 12340b8444b9Ssam movl 12(fp),r0 # copy length 12350b8444b9Ssam blss 9f 12360b8444b9Ssam movl 4(fp),r1 # copy user address 12370b8444b9Ssam cmpl $(CLSIZE*NBPG),r0 # probing one page or less ? 12380b8444b9Ssam bgeq 2f # yes 12390b8444b9Ssam1: 12400b8444b9Ssam prober $1,(r1),$(CLSIZE*NBPG) # bytes accessible ? 12410b8444b9Ssam beql 9f # no 12420b8444b9Ssam addl2 $(CLSIZE*NBPG),r1 # incr user address ptr 12430b8444b9Ssam _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r0,1b) # reduce count and loop 12440b8444b9Ssam2: 12450b8444b9Ssam prober $1,(r1),r0 # bytes accessible ? 1246250e3e7bSkarels bneq 7f # yes 1247250e3e7bSkarels tstl r0 # copin 0 bytes ? 1248250e3e7bSkarels bneq 9f # no, can't copyin 1249250e3e7bSkarels ret # lie! 1250250e3e7bSkarels7: 12510b8444b9Ssam MOVC3(4(fp),8(fp),12(fp)) 12520b8444b9Ssam clrl r0 12530b8444b9Ssam ret 12540b8444b9Ssam9: 12557479596bSsam movl $EFAULT,r0 12567479596bSsam ret 12577479596bSsam 12580b8444b9Ssam/* 12590b8444b9Ssam * Copy a block of data from the kernel 12600b8444b9Ssam * address space to the user address space. 12610b8444b9Ssam * 12620b8444b9Ssam * copyout(fromaddr, toaddr, count) 12630b8444b9Ssam */ 12640b8444b9SsamENTRY(copyout, 0) 12657479596bSsam movl 12(fp),r0 # get count 12660b8444b9Ssam blss 9b 12677479596bSsam movl 8(fp),r1 # get user address 12680b8444b9Ssam cmpl $(CLSIZE*NBPG),r0 # can do in one probew? 12690b8444b9Ssam bgeq 2f # yes 12700b8444b9Ssam1: 12710b8444b9Ssam probew $1,(r1),$(CLSIZE*NBPG) # bytes accessible? 12720b8444b9Ssam beql 9b # no 12730b8444b9Ssam addl2 $(CLSIZE*NBPG),r1 # increment user address 12740b8444b9Ssam _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r0,1b) # reduce count and loop 12750b8444b9Ssam2: 12767479596bSsam probew $1,(r1),r0 # bytes accessible? 1277250e3e7bSkarels bneq 7f # yes 1278250e3e7bSkarels tstl r0 # copin 0 bytes ? 1279250e3e7bSkarels bneq 9b # no, can't copyin 1280250e3e7bSkarels ret # lie! 1281250e3e7bSkarels7: 12820b8444b9Ssam MOVC3(4(fp),8(fp),12(fp)) 12837479596bSsam clrl r0 12847479596bSsam ret 12857479596bSsam 12867479596bSsam/* 12874cb53c90Skarels * savectx is like setjmp but saves all registers. 12880b8444b9Ssam * Called before swapping out the u. area, restored by resume() 12890b8444b9Ssam * below. 12900b8444b9Ssam */ 12910b8444b9SsamENTRY(savectx, 0) 12920b8444b9Ssam movl 4(fp),r2 12930b8444b9Ssam storer $0x1ff8,(r2); addl2 $40,r2 # r3-r12 12940b8444b9Ssam movl (fp),(r2); addl2 $4,r2 # fp 12950b8444b9Ssam movab 8(fp),(r2); addl2 $4,r2 # sp 12960b8444b9Ssam movl -8(fp),(r2) # pc 12970b8444b9Ssam clrl r0 12980b8444b9Ssam ret 12997479596bSsam 1300189fe34eSkarels#ifdef KADB 1301e281991cSsam/* 13024cb53c90Skarels * C library -- reset, setexit -- XXX 1303e281991cSsam * 1304e281991cSsam * reset(x) 1305e281991cSsam * will generate a "return" from 1306e281991cSsam * the last call to 1307e281991cSsam * setexit() 1308e281991cSsam * by restoring r2 - r12, fp 1309e281991cSsam * and doing a return. 1310e281991cSsam * The returned value is x; on the original 1311e281991cSsam * call the returned value is 0. 1312e281991cSsam */ 1313e281991cSsamENTRY(setexit, 0) 1314e281991cSsam movab setsav,r0 1315e281991cSsam storer $0x1ffc, (r0) 1316e281991cSsam movl (fp),44(r0) # fp 1317e281991cSsam moval 4(fp),48(r0) # sp 1318e281991cSsam movl -8(fp),52(r0) # pc 1319e281991cSsam clrl r0 1320e281991cSsam ret 1321e281991cSsam 1322e281991cSsamENTRY(reset, 0) 1323e281991cSsam movl 4(fp),r0 # returned value 1324e281991cSsam movab setsav,r1 1325e281991cSsam loadr $0x1ffc,(r1) 1326e281991cSsam movl 44(r1),fp 1327e281991cSsam movl 48(r1),sp 1328e281991cSsam jmp *52(r1) 1329e281991cSsam 1330e281991cSsam .data 1331e281991cSsam .align 2 1332e281991cSsamsetsav: .space 14*4 1333e281991cSsam .text 1334e281991cSsam#endif 1335e281991cSsam 13367479596bSsam .globl _whichqs 13377479596bSsam .globl _qs 13387479596bSsam .globl _cnt 13397479596bSsam 13407479596bSsam .globl _noproc 13417479596bSsam .comm _noproc,4 13427479596bSsam .globl _runrun 13437479596bSsam .comm _runrun,4 13447479596bSsam/* 13457479596bSsam * The following primitives use the fancy TAHOE instructions. 13461d771ceeSbostic * _whichqs tells which of the 32 queues _qs have processes in 13471d771ceeSbostic * them. Setrunqueue puts processes into queues, remrq removes 13481d771ceeSbostic * them from queues. The running process is on no queue, other 1349*bff07831Sbostic * processes are on a queue related to p->p_priority, divided by 4 13507479596bSsam * actually to shrink the 0-127 range of priorities into the 32 available 13517479596bSsam * queues. 13527479596bSsam */ 13537479596bSsam 13547479596bSsam/* 13551d771ceeSbostic * setrunqueue(p), using fancy TAHOE instructions. 13567479596bSsam * 13577479596bSsam * Call should be made at spl8(), and p->p_stat should be SRUN 13587479596bSsam */ 13591d771ceeSbosticENTRY(setrunqueue, 0) 13607479596bSsam movl 4(fp),r0 1361*bff07831Sbostic tstl P_BACK(r0) ## firewall: p->p_back must be 0 13627479596bSsam beql set1 ## 13637479596bSsam pushab set3 ## 13647479596bSsam callf $8,_panic ## 13657479596bSsamset1: 1366*bff07831Sbostic movzbl P_PRIORITY(r0),r1 # put on p->p_pri / 4 queue 13677479596bSsam shar $2,r1,r1 13687479596bSsam shal $1,r1,r2 13697479596bSsam moval _qs[r2],r2 13707479596bSsam insque (r0),*4(r2) # at end of queue 13717479596bSsam shal r1,$1,r1 13727479596bSsam orl2 r1,_whichqs # mark queue non-empty 13737479596bSsam ret 13747479596bSsam 13751d771ceeSbosticset3: .asciz "setrunqueue" 13767479596bSsam 13777479596bSsam/* 13787479596bSsam * remrq(p), using fancy TAHOE instructions 13797479596bSsam * 13807479596bSsam * Call should be made at spl8(). 13817479596bSsam */ 13820b8444b9SsamENTRY(remrq, 0) 13837479596bSsam movl 4(fp),r0 1384*bff07831Sbostic movzbl P_PRIORITY(r0),r1 13857479596bSsam shar $2,r1,r1 13867479596bSsam bbs r1,_whichqs,rem1 13877479596bSsam pushab rem3 # it wasn't recorded to be on its q 13887479596bSsam callf $8,_panic 13897479596bSsamrem1: 13907479596bSsam remque (r0) 13917479596bSsam bneq rem2 # q not empty yet 13927479596bSsam shal r1,$1,r1 13937479596bSsam mcoml r1,r1 13947479596bSsam andl2 r1,_whichqs # mark queue empty 13957479596bSsamrem2: 1396*bff07831Sbostic clrl P_BACK(r0) ## for firewall checking 13977479596bSsam ret 13987479596bSsam 13997479596bSsamrem3: .asciz "remrq" 14007479596bSsam 14017479596bSsam/* 14027479596bSsam * Masterpaddr is the p->p_addr of the running process on the master 14037479596bSsam * processor. When a multiprocessor system, the slave processors will have 14047479596bSsam * an array of slavepaddr's. 14057479596bSsam */ 14067479596bSsam .globl _masterpaddr 14077479596bSsam .data 1408e281991cSsam .align 2 14090b8444b9Ssam_masterpaddr: .long 0 14107479596bSsam 14117479596bSsam .text 1412*bff07831Sbosticsw0: .asciz "Xswitch" 1413844a1895Skarels 1414844a1895Skarels/* 1415*bff07831Sbostic * When no processes are on the runq, Xswitch branches to idle 1416844a1895Skarels * to wait for something to come ready. 1417844a1895Skarels */ 1418844a1895Skarels .globl Idle 1419844a1895SkarelsIdle: idle: 1420717b2398Skarels movl $1,_noproc 1421844a1895Skarels mtpr $0,$IPL # must allow interrupts here 1422844a1895Skarels1: 1423844a1895Skarels tstl _whichqs # look for non-empty queue 1424844a1895Skarels bneq sw1 1425844a1895Skarels brb 1b 1426844a1895Skarels 1427844a1895Skarelsbadsw: pushab sw0 1428844a1895Skarels callf $8,_panic 1429844a1895Skarels /* NOTREACHED */ 1430844a1895Skarels 1431844a1895Skarels .align 2 14327479596bSsam/* 1433*bff07831Sbostic * Xswitch(), using fancy tahoe instructions 14347479596bSsam */ 1435*bff07831SbosticENTRY(Xswitch, 0) 14367479596bSsam movl (fp),fp # prepare for rei 14377479596bSsam movl (sp),4(sp) # saved pc 14387479596bSsam tstl (sp)+ 14397479596bSsam movpsl 4(sp) 1440844a1895Skarels incl _cnt+V_SWTCH 14417479596bSsamsw1: ffs _whichqs,r0 # look for non-empty queue 1442844a1895Skarels blss idle # if none, idle 1443844a1895Skarels mtpr $0x18,$IPL # lock out all so _whichqs==_qs 1444844a1895Skarels bbc r0,_whichqs,sw1 # proc moved via interrupt 14457479596bSsam shal $1,r0,r1 14467479596bSsam moval _qs[r1],r1 14477479596bSsam movl (r1),r2 # r2 = p = highest pri process 14487479596bSsam remque *(r1) 1449844a1895Skarels bvs badsw # make sure something was there 1450844a1895Skarels bneq sw2 14517479596bSsam shal r0,$1,r1 14527479596bSsam mcoml r1,r1 14537479596bSsam andl2 r1,_whichqs # no more procs in this queue 1454844a1895Skarelssw2: 14557479596bSsam clrl _noproc 1456844a1895Skarels clrl _runrun 1457717b2398Skarels#ifdef notdef 14587479596bSsam tstl P_WCHAN(r2) ## firewalls 1459844a1895Skarels bneq badsw ## 14608306c720Ssam cmpb P_STAT(r2),$SRUN ## 1461844a1895Skarels bneq badsw ## 1462717b2398Skarels#endif 1463*bff07831Sbostic clrl P_BACK(r2) ## 14647479596bSsam movl *P_ADDR(r2),r0 14650b8444b9Ssam#ifdef notdef 1466844a1895Skarels cmpl r0,_masterpaddr # resume of current proc is easy 14670b8444b9Ssam beql res0 14680b8444b9Ssam#endif 1469844a1895Skarels movl r0,_masterpaddr 1470844a1895Skarels shal $PGSHIFT,r0,r0 # r0 = pcbb(p) 14717479596bSsam brb swresume 14727479596bSsam 14737479596bSsam/* 14747479596bSsam * resume(pf) 14757479596bSsam */ 14760b8444b9SsamENTRY(resume, 0) 14770b8444b9Ssam shal $PGSHIFT,4(fp),r0 # r0 = pcbb(pf) 14787479596bSsam movl (fp),fp # prepare for rei 14797479596bSsam movl (sp)+,4(sp) # saved pc 14807479596bSsam tstl (sp)+ 14817479596bSsam movpsl 4(sp) 14827479596bSsamswresume: 14837479596bSsam mtpr $0x18,$IPL # no interrupts, please 14847479596bSsam movl _CMAP2,_u+PCB_CMAP2 # yech 14857479596bSsam REST_ACC # restore original accumulator 14867479596bSsam svpctx 14877479596bSsam mtpr r0,$PCBB 14887479596bSsam ldpctx 14897479596bSsam movl _u+PCB_CMAP2,_CMAP2 # yech 14907479596bSsam mtpr $_CADDR2,$TBIS 14917479596bSsamres0: 14920b8444b9Ssam movl _u+U_PROCP,r2 # r2 = u.u_procp 14930b8444b9Ssam tstl P_CKEY(r2) # does proc have code key? 14940b8444b9Ssam bneq 1f 14950b8444b9Ssam callf $4,_getcodekey # no, give him one 14968306c720Ssam movl _u+U_PROCP,r2 # r2 = u.u_procp 14970b8444b9Ssam movl r0,P_CKEY(r2) 14980b8444b9Ssam1: 14990b8444b9Ssam tstl P_DKEY(r2) # does proc have data key? 15000b8444b9Ssam bneq 1f 15010b8444b9Ssam callf $4,_getdatakey # no, give him one 15028306c720Ssam movl _u+U_PROCP,r2 # r2 = u.u_procp 15030b8444b9Ssam movl r0,P_DKEY(r2) 15040b8444b9Ssam1: 15050b8444b9Ssam mtpr P_CKEY(r2),$CCK # set code cache key 15060b8444b9Ssam mtpr P_DKEY(r2),$DCK # set data cache key 15077479596bSsam tstl _u+PCB_SSWAP 15080b8444b9Ssam bneq res1 15090b8444b9Ssam rei 15104cb53c90Skarelsres1: # restore alternate saved context 15117479596bSsam movl _u+PCB_SSWAP,r2 15127479596bSsam clrl _u+PCB_SSWAP 15130b8444b9Ssam loadr $0x3ff8,(r2); addl2 $44,r2 # restore r3-r13 (r13=fp) 15140b8444b9Ssam movl (r2),r1; addl2 $4,r2 # fetch previous sp ... 15150b8444b9Ssam movab (sp),r0 # ... and current sp and 15160b8444b9Ssam cmpl r1,r0 # check for credibility, 15170b8444b9Ssam bgequ 1f # if further up stack ... 15180b8444b9Ssam pushab 2f; callf $8,_panic # ... panic 15190b8444b9Ssam /*NOTREACHED*/ 15200b8444b9Ssam1: # sp ok, complete return 15210b8444b9Ssam movl r1,sp # restore sp 1522c1693b91Smckusick pushl $PSL_PRVMOD # kernel mode, ipl 0 1523c1693b91Smckusick pushl (r2) # return address 15247479596bSsam rei 15250b8444b9Ssam2: .asciz "ldctx" 15267479596bSsam 15277479596bSsam/* 15287479596bSsam * {fu,su},{byte,word} 15297479596bSsam */ 15300b8444b9SsamENTRY(fuword, 0) 15317479596bSsam movl 4(fp), r1 15327479596bSsam prober $1,(r1),$4 # check access 15337479596bSsam beql fserr # page unreadable 15347479596bSsam bitl $1,r1 # check byte alignment 15357479596bSsam bneq 2f # odd, do byte-word-byte 15367479596bSsam bitl $2,r1 # check word alignment 15377479596bSsam bneq 1f # odd, do in 2 words 15387479596bSsam movl (r1),r0 # move longword 15397479596bSsam ret 15407479596bSsam1: 15417479596bSsam movw (r1),r0 # move two words 15427479596bSsam shal $16,r0,r0 15437479596bSsam movzwl 2(r1),r1 # orw2 sign extends 15447479596bSsam orl2 r1,r0 15457479596bSsam ret 15467479596bSsam2: 15477479596bSsam movb (r1),r0 # move byte-word-byte 15487479596bSsam shal $24,r0,r0 15497479596bSsam movzwl 1(r1),r2 # orw2 sign extends 15507479596bSsam shal $8,r2,r2 15517479596bSsam movzbl 3(r1),r1 # orb2 sign extends 15527479596bSsam orl2 r2,r1 15537479596bSsam orl2 r1,r0 15547479596bSsam ret 15557479596bSsamfserr: 15567479596bSsam mnegl $1,r0 15577479596bSsam ret 15587479596bSsam 15590b8444b9SsamENTRY(fubyte, 0) 15607479596bSsam prober $1,*4(fp),$1 15617479596bSsam beql fserr 15627479596bSsam movzbl *4(fp),r0 15637479596bSsam ret 15647479596bSsam 15650b8444b9SsamENTRY(suword, 0) 15667479596bSsam movl 4(fp), r0 15677479596bSsam probew $1,(r0),$4 # check access 15687479596bSsam beql fserr # page unwritable 15697479596bSsam bitl $1,r0 # check byte alignment 15707479596bSsam bneq 1f # odd byte boundary 15717479596bSsam bitl $2,r0 # check word alignment 15727479596bSsam beql 2f # longword aligned 15737479596bSsam movw 8(fp),(r0) # move two words 15747479596bSsam movw 10(fp),2(r0) 15757479596bSsam jbr 3f 15767479596bSsam1: 15777479596bSsam movb 8(fp),(r0) 15787479596bSsam movb 9(fp),1(r0) 15797479596bSsam movb 10(fp),2(r0) 15807479596bSsam movb 11(fp),3(r0) 15817479596bSsam jbr 3f 15827479596bSsam2: 15837479596bSsam movl 8(fp),(r0) 15847479596bSsam3: 15857479596bSsam clrl r0 15867479596bSsam ret 15877479596bSsam 15880b8444b9SsamENTRY(subyte, 0) 15897479596bSsam probew $1,*4(fp),$1 15907479596bSsam beql fserr 15917479596bSsam movb 11(fp),*4(fp) 15927479596bSsam clrl r0 15937479596bSsam ret 15947479596bSsam 15957479596bSsam/* 15967479596bSsam * Copy 1 relocation unit (NBPG bytes) 15977479596bSsam * from user virtual address to physical address 15987479596bSsam */ 15990b8444b9SsamENTRY(copyseg, 0) 16007479596bSsam orl3 $PG_V|PG_KW,8(fp),_CMAP2 16017479596bSsam mtpr $_CADDR2,$TBIS # invalidate entry for copy 16020b8444b9Ssam MOVC3(4(fp),$_CADDR2,$NBPG) 16037479596bSsam ret 16047479596bSsam 16057479596bSsam/* 16060b8444b9Ssam * Clear a page of memory. The page frame is specified. 16077479596bSsam * 16080b8444b9Ssam * clearseg(pf); 16097479596bSsam */ 16100b8444b9SsamENTRY(clearseg, 0) 16117479596bSsam orl3 $PG_V|PG_KW,4(fp),_CMAP1 # Maps to virtual addr CADDR1 16127479596bSsam mtpr $_CADDR1,$TBIS 16137479596bSsam movl $255,r0 # r0 = limit 16147479596bSsam clrl r1 # r1 = index of cleared long 16157479596bSsam1: 16167479596bSsam clrl _CADDR1[r1] 16177479596bSsam aobleq r0,r1,1b 16187479596bSsam ret 16197479596bSsam 16207479596bSsam/* 16210b8444b9Ssam * Check user mode read/write access. 16220b8444b9Ssam * 16230b8444b9Ssam * useracc(addr, count, mode) 16240b8444b9Ssam * caddr_t addr; int count, mode; 16250b8444b9Ssam * mode = 0 write access 16260b8444b9Ssam * mode = 1 read access 16277479596bSsam */ 16280b8444b9SsamENTRY(useracc, 0) 16297479596bSsam movl $1,r2 # r2 = 'user mode' for probew/probew 16307479596bSsamprobes: 16317479596bSsam movl 4(fp),r0 # get va 16327479596bSsam movl 8(fp),r1 # count 16337479596bSsam tstl 12(fp) # test for read access ? 16347479596bSsam bneq userar # yes 16350b8444b9Ssam cmpl $(CLSIZE*NBPG),r1 # can we do it in one probe ? 16367479596bSsam bgeq uaw2 # yes 16377479596bSsamuaw1: 16380b8444b9Ssam probew r2,(r0),$(CLSIZE*NBPG) 16397479596bSsam beql uaerr # no access 16400b8444b9Ssam addl2 $(CLSIZE*NBPG),r0 16410b8444b9Ssam _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r1,uaw1) 16427479596bSsamuaw2: 16437479596bSsam probew r2,(r0),r1 16447479596bSsam beql uaerr 16457479596bSsam movl $1,r0 16467479596bSsam ret 16477479596bSsamuserar: 16480b8444b9Ssam cmpl $(CLSIZE*NBPG),r1 16497479596bSsam bgeq uar2 16507479596bSsamuar1: 16510b8444b9Ssam prober r2,(r0),$(CLSIZE*NBPG) 16527479596bSsam beql uaerr 16530b8444b9Ssam addl2 $(CLSIZE*NBPG),r0 16540b8444b9Ssam _ACBL($(CLSIZE*NBPG+1),$(-CLSIZE*NBPG),r1,uar1) 16557479596bSsamuar2: 16567479596bSsam prober r2,(r0),r1 16577479596bSsam beql uaerr 16587479596bSsam movl $1,r0 16597479596bSsam ret 16607479596bSsamuaerr: 16617479596bSsam clrl r0 16627479596bSsam ret 16637479596bSsam 16647479596bSsam/* 16650b8444b9Ssam * Check kernel mode read/write access. 16660b8444b9Ssam * 16670b8444b9Ssam * kernacc(addr, count, mode) 16680b8444b9Ssam * caddr_t addr; int count, mode; 16690b8444b9Ssam * mode = 0 write access 16700b8444b9Ssam * mode = 1 read access 16717479596bSsam */ 16720b8444b9SsamENTRY(kernacc, 0) 16737479596bSsam clrl r2 # r2 = 0 means kernel mode probe. 16747479596bSsam jbr probes # Dijkstra would get gastric distress here. 16757479596bSsam 16767479596bSsam/* 16777479596bSsam * addupc - increment some histogram counter 16787479596bSsam * in the profiling buffer 16797479596bSsam * 16800b8444b9Ssam * addupc(pc, prof, delta) 16810b8444b9Ssam * long pc; short delta; struct uprof *prof; 16827479596bSsam * 16837479596bSsam * struct uprof { # profile arguments 16847479596bSsam * short *r_base; # buffer base 16857479596bSsam * unsigned pr_size; # buffer size 16867479596bSsam * unsigned pr_off; # pc offset 16877479596bSsam * unsigned pr_scale; # pc scaling 16887479596bSsam * } 16897479596bSsam */ 16900b8444b9SsamENTRY(addupc, 0) 16917479596bSsam movl 8(fp),r2 # r2 points to structure 16927479596bSsam subl3 8(r2),4(fp),r0 # r0 = PC - lowpc 16937479596bSsam jlss 9f # PC < lowpc , out of range ! 16947479596bSsam shrl $1,r0,r0 # the unit is words 16957479596bSsam shrl $1,12(r2),r1 # ditto for scale 16967479596bSsam emul r1,r0,$0,r0 16977479596bSsam shrq $14,r0,r0 16987479596bSsam tstl r0 # too big 16997479596bSsam jneq 9f 17007479596bSsam cmpl r1,4(r2) # Check buffer overflow 17017479596bSsam jgequ 9f 17027479596bSsam probew $1,*0(r2)[r1],$2 # counter accessible? 17037479596bSsam jeql 9f 17047479596bSsam shrl $1,r1,r1 # make r1 word index 17057479596bSsam addw2 14(fp),*0(r2)[r1] 17067479596bSsam9: ret 17070b8444b9Ssam 17080b8444b9Ssam/* 17090b8444b9Ssam * scanc(size, cp, table, mask) 17100b8444b9Ssam */ 17110b8444b9SsamENTRY(scanc, R3|R4) 17120b8444b9Ssam movl 8(fp),r0 # r0 = cp 17130b8444b9Ssam addl3 4(fp),r0,r2 # end = &cp[size] 17140b8444b9Ssam movl 12(fp),r1 # r1 = table 17150b8444b9Ssam movb 19(fp),r4 # r4 = mask 17160b8444b9Ssam decl r0 # --cp 17170b8444b9Ssam jbr 0f # just like Fortran... 17180b8444b9Ssam1: # do { 17190b8444b9Ssam movzbl (r0),r3 17200b8444b9Ssam bitb r4,(r1)[r3] # if (table[*cp] & mask) 17210b8444b9Ssam jneq 2f # break; 17220b8444b9Ssam0: aoblss r2,r0,1b # } while (++cp < end); 17230b8444b9Ssam2: 17240b8444b9Ssam subl3 r0,r2,r0; ret # return (end - cp); 17250b8444b9Ssam 17260b8444b9Ssam/* 17270b8444b9Ssam * skpc(mask, size, cp) 17280b8444b9Ssam */ 17290b8444b9SsamENTRY(skpc, 0) 17300b8444b9Ssam movl 12(fp),r0 # r0 = cp 17310b8444b9Ssam addl3 8(fp),r0,r1 # r1 = end = &cp[size]; 17320b8444b9Ssam movb 7(fp),r2 # r2 = mask 17330b8444b9Ssam decl r0 # --cp; 17340b8444b9Ssam jbr 0f 17350b8444b9Ssam1: # do 17360b8444b9Ssam cmpb (r0),r2 # if (*cp != mask) 17370b8444b9Ssam jneq 2f # break; 17380b8444b9Ssam0: aoblss r1,r0,1b # while (++cp < end); 17390b8444b9Ssam2: 17400b8444b9Ssam subl3 r0,r1,r0; ret # return (end - cp); 17410b8444b9Ssam 17420b8444b9Ssam/* 17430b8444b9Ssam * locc(mask, size, cp) 17440b8444b9Ssam */ 17450b8444b9SsamENTRY(locc, 0) 17460b8444b9Ssam movl 12(fp),r0 # r0 = cp 17470b8444b9Ssam addl3 8(fp),r0,r1 # r1 = end = &cp[size] 17480b8444b9Ssam movb 7(fp),r2 # r2 = mask 17490b8444b9Ssam decl r0 # --cp; 17500b8444b9Ssam jbr 0f 17510b8444b9Ssam1: # do 17520b8444b9Ssam cmpb (r0),r2 # if (*cp == mask) 17530b8444b9Ssam jeql 2f # break; 17540b8444b9Ssam0: aoblss r1,r0,1b # while (++cp < end); 17550b8444b9Ssam2: 17560b8444b9Ssam subl3 r0,r1,r0; ret # return (end - cp); 17579dab7c56Ssam 175863a4e097Ssam#ifdef ALIGN 1759d357015aSbostic#include "tahoe/align/align.h" 17609dab7c56Ssam 17619dab7c56Ssam .globl _alignment 17629dab7c56Ssam/* 17639dab7c56Ssam * There's an intimate relationship between this piece of code 17649dab7c56Ssam * and the alignment emulation code (especially the layout 17659dab7c56Ssam * of local variables in alignment.c! Don't change unless 17669dab7c56Ssam * you update both this, alignment.h and alignment.c !! 17679dab7c56Ssam */ 17689dab7c56Ssamnon_aligned: 17699dab7c56Ssam orb2 $EMULATEALIGN,_u+U_EOSYS 17709dab7c56Ssam incl _cnt+V_TRAP 17719dab7c56Ssam incl _cnt+V_ALIGN # count emulated alignment traps 17729dab7c56Ssam moval 4(sp),_user_psl 17739dab7c56Ssam SAVE_FPSTAT(4) # Also zeroes out ret_exception ! 17749dab7c56Ssam pushl $0 # ret_addr 17759dab7c56Ssam pushl $0 # ret_code 17769dab7c56Ssam mfpr $USP,-(sp) # user sp 17779dab7c56Ssam callf $4,_alignment # call w/o parms so regs may be modified 17789dab7c56Ssam /* 17799dab7c56Ssam * We return here after a successful emulation or an exception. 17809dab7c56Ssam * The registers have been restored and we must not alter them 17819dab7c56Ssam * before returning to the user. 17829dab7c56Ssam */ 17839dab7c56Ssam2: mtpr (sp)+,$USP # restore user sp 17849dab7c56Ssam tstl 8(sp) # Any exception ? 17859dab7c56Ssam bneq got_excp # Yes, reflect it back to user. 17869dab7c56Ssam moval 8(sp),sp # pop 2 zeroes pushed above 17879dab7c56Ssam REST_FPSTAT 17889dab7c56Ssam xorb2 $EMULATEALIGN,_u+U_EOSYS 17899dab7c56Ssam 17909dab7c56Ssam bitl $PSL_T,4(sp) # check for trace bit set 17919dab7c56Ssam beql 9f 17929dab7c56Ssam CHECK_SFE(4) 17939dab7c56Ssam pushl $0 17949dab7c56Ssam SAVE_FPSTAT(8) 17959dab7c56Ssam TRAP(TRCTRAP) 17969dab7c56Ssam9: rei 17979dab7c56Ssam 17989dab7c56Ssamgot_excp: # decode exception 17999dab7c56Ssam casel 8(sp),$ILL_ADDRMOD,$ALIGNMENT 18009dab7c56Ssam .align 1 18019dab7c56SsamL1: 18029dab7c56Ssam .word ill_addrmod-L1 18039dab7c56Ssam .word ill_access-L1 18049dab7c56Ssam .word ill_oprnd-L1 18059dab7c56Ssam .word arithmetic-L1 18069dab7c56Ssam .word alignment-L1 18079dab7c56Ssam brw alignment # default - shouldn't come here at all ! 18089dab7c56Ssam 18099dab7c56Ssamill_addrmod: # No other parameters. Set up stack as 18109dab7c56Ssam moval 8(sp),sp # the HW would do it in a real case. 18119dab7c56Ssam REST_FPSTAT 18129dab7c56Ssam jbr _Xresadflt 18139dab7c56Ssamill_oprnd: 18149dab7c56Ssam moval 8(sp),sp 18159dab7c56Ssam REST_FPSTAT 18169dab7c56Ssam jbr _Xresopflt 18179dab7c56Ssamalignment: 18189dab7c56Ssam moval 8(sp),sp 18199dab7c56Ssam REST_FPSTAT 18209dab7c56Ssam jbr align_excp # NB: going to _Xalignflt would cause loop 18219dab7c56Ssamill_access: 18229dab7c56Ssam /* 18239dab7c56Ssam * Must restore accumulator w/o modifying sp and w/o using 18249dab7c56Ssam * registers. Solution: copy things needed by REST_FPSTAT. 18259dab7c56Ssam */ 18269dab7c56Ssam pushl 20(sp) # The flags longword 18279dab7c56Ssam pushl 20(sp) # acc_low 18289dab7c56Ssam pushl 20(sp) # acc_high 18299dab7c56Ssam pushl 20(sp) # ret_exception ignored by REST_FPSTAT 18309dab7c56Ssam REST_FPSTAT # Back where we were with the sp ! 18319dab7c56Ssam movl (sp),16(sp) # code for illegal access 18329dab7c56Ssam movl 4(sp),20(sp) # original virtual address 18339dab7c56Ssam moval 16(sp),sp # Just like the HW would set it up 18349dab7c56Ssam jbr _Xprotflt 18359dab7c56Ssamarithmetic: # same trickery as above 18369dab7c56Ssam pushl 20(sp) # The flags longword 18379dab7c56Ssam pushl 20(sp) # acc_low 18389dab7c56Ssam pushl 20(sp) # acc_high 18399dab7c56Ssam pushl 20(sp) # ret_exception ignored by REST_FPSTAT 18409dab7c56Ssam REST_FPSTAT # Back where we were with the sp ! 18419dab7c56Ssam movl (sp),20(sp) # code for arithmetic exception 18429dab7c56Ssam moval 20(sp),sp # Just like the HW would set it up 18439dab7c56Ssam jbr _Xarithtrap 18449dab7c56Ssam#endif 1845