📄 vaxexception.s
字号:
/* @(#)vaxexception.s 4.1 7/2/90 */#include "../machine/emul/vaxemul.h"#include "../machine/psl.h"#include "../machine/emul/vaxregdef.h"#include "../machine/mtpr.h"/************************************************************************ * * * Copyright (c) 1984,85,88 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * */************************************************************************ * * Modification History * * Fred Canter, 15-Feb-88 * Added VAX420, VAX3600, and VAX6200 to MVAX for calling * vax$modify_exception routine. * * Stephen Reilly, 25-Mar-85 * 003- Fixed the exception handler so that if an access violation occurs * during the emulation of a floation point instruction it will point * to the emulated instruction and not into the emulation code that * caused the exception. * * Stephen Reilly, 22-Jul-84 * 002- Added #ifdef for the new floating point option * * Stephen Reilly, 11-Jul-84 * 001- Changes were made so that in the event of a stack overflow the * exception handling will die gracefully. * * Stephen Reilly, 20-Mar-84 * 000- This code is the modification of the VMS emulation code that * was written by Dave Cutler. This routine includes sysunwind.mar, * exception.mar and exeadjstk.mar. The reason was so that all of the * handling for the emulation code could be found in one module. * These routines have been modified to run on Ultrix * ***********************************************************************/ # # d. n. cutler 6-jul-76 # # modified by: # # v03-005 ly00b2 larry yetto 10-feb-1984 09:56 # fix truncation error # # v03-005 ljk0260 lawrence j. kenah 5-feb-1984 # allow exception dispatching to take a detour through an # instruction emulator so that the exception parameters can # be modified to describe an exception at the site of the # emulated instruction rather than inside the emulator. # correct errors that appeared in comments. # # v03-004 acg0393 andrew c. goldstein, 20-jan-1984 1:38 # fix fp validation in condition handler search# also # call exe$unwind directly to avoid p1 vectors # # v03-003 wmc0001 wayne cardoza 28-oct-1983 # change mode to user or supervisor handlers should not get # control in privileged modes. # # v03-002 acg0348 andrew c. goldstein, 4-aug-1983 17:01 # fix unwinding to frame of exception # # v03-001 acg0310 andrew c. goldstein, 31-jan-1983 13:44 # fix probing of stack after expansion # # v02-016 msh0001 maryann hinden 09-feb-1982 # fix probe problem. # # v02-015 acg0261 andrew c. goldstein, 4-feb-1982 13:50 # fix skipping over vectored handler invocations # in nested exceptions. # # v02-014 acg0260 andrew c. goldstein, 1-feb-1982 16:25 # make failure to create stack space non-fatal for user # and super modes # # v02-013 acg0242 andrew c. goldstein, 30-dec-1981 19:12 # catch exceptions at ast call site # # v02-012 acg0224 andrew c. goldstein, 23-nov-1981 14:31 # fix access mode used to report ast faults # # v02-011 acg0222 andrew c. goldstein, 17-nov-1981 16:52 # fix context bug in compatibility mode check # # v02-010 dwt0003 david w. thiel 11-nov-1981 # allow t-bit traps during call to a condition handler. # fix search's condition handler. # define global entry (exe$sigtoret) for a condition handler # that turns an exception into a return with status. # # v02-009 kdm0064 kathleen d. morse 25-aug-1981 # change label of exception to exe$exception, for the use of # the multi-processing code. # # v02-008 ljk0036 lawrence j. kenah 23-jun-1981 # convert fatal exception for executive mode into a # nonfatal bugcheck. # # v02-007 kta0022 kerbey t. altmann 10-jun-1981 # add some code for inhibited system services. change # stack range check to use new top limit array. # # v02-006 kdm0037 kathleen d. morse 12-feb-1981 # change non-kernel mode references to sch$gl_curpcb # to use ctl$gl_pcb instead. # # v02-005 acg0183 andrew c. goldstein, 29-dec-1980 20:01 # fix condition handler search bugs, add entry point for # lib$signal, add support for lib$stop, add checks to catch # call failures to handlers. # # # hardware exception handling # #**************************************************************************** # # fair warning!! the exception reflection and condition handling code in # this module crawls with assumptions about the format of the stack and # argument lists, as documented in various comments throughout. since # the stack pointer moves frequently, no attempt has been made to use # symbolic offsets for stack relative references. changes to the stack # format should be made only after thorough inspection and understanding # of the code (not to mention appendix c of the architecture handbook). # note also that lib$signal must track the stack formats used here. # #**************************************************************************** # # # local symbols # # call frame offset definitions # #define handler 0 #condition handler address#define savpsw 4 #saved psw from call#define savmsk 6 #register save mask#define savap 8 #saved ap register image#define savfp 12 #saved fp register image#define savpc 16 #saved pc register image#define savrg 20 #other saved register images # # local data # #define final_idx 0 #indices to fetch message addresses#define attconsto_idx 1#define badhandler_idx 2#define badast_idx 3 # #+ # exe$acviolat - access violate fault # # this routine is automatically vectored to when an access violation is # detected. the state of the stack on entry is: # # 00(sp) = access violation reason mask. # 04(sp) = access violation virtual address. # 08(sp) = exception pc. # 12(sp) = exception psl. # # access violation reason mask format is: # # bit 0 = type of access violation. # 0 = pte access code did not permit intented access. # 1 = p0lr, p1lr, or s0lr length violation. # bit 1 = pte reference. # 0 = specified virtual address not accessible. # 1 = associated page table entry not accessible. # bit 2 = intended access type. # 0 = read. # 1 = modify. # # the exception name followed by the number of exception arguments are # pushed on the stack. final processing is accomplished in common code. #- .align 2 .globl exe$acviolat exe$acviolat: #access violation faults/* * The following code emulates what is done with a SEGFLT in the * module trap.c. The reason for this is that if a length violation * has occured we attempt to extend the stack. If we fail then continue * where the code will had an actual stack overflow. The only problem with * this is the address the user sees causing the violation is not the * emulated instruction, instead it is the instruction in the emulation * code. */ blbc (sp),acviolat #001 is this a lenght violation? cmpzv $psl$v_curmod,$psl$s_curmod,12(sp),$psl$c_user # check for user bneq acviolat #001 no, really an access violation pushr $0x03f #001 save r0-r1 because C uses these # as temp registers and never saves # them mfpr $USP,-(sp) #001 get user stack calls $1,_grow #001 see if we can grow blbs r0,1f #001 br if we did grow pushl (4+(6*4))(sp) #001 get address that caused the # violation calls $1,_grow #001 try to grow blbc r0,2f #001 br if we fail1: popr $0x3f #001 restore r0-r1 addl2 $8,sp #clean exception parameters from stack rei #and return to retry instruction2: popr $0x03f #restore registers r0-r1 acviolat: # movzwl $ss$_accvio,-(sp) #set exception nameex5arg: pushl $5 #set number of signal arguments jmp exe$exception #finish in common code #+ # exe$reflect - reflect exception from mode other than kernel # # this routine is jumped to reflect an exception from a mode other than kernel. # the signal arguments are assumed to be set up properly on the stack. # note that the previous mode field of the psl contains the access mode # of the exception. #- .globl exe$reflectexe$reflect: #reflect exception pushl $1 #save code indicating signal # pushr $^m<r0,r1> #save registers r0 and r1 pushr $0x03 # 003 We do not have primary and secondary exception vectors so because # of this we set to -1 the frame depth. mnegl $1,-(sp) #set initial frame depth pushl fp #set initial handler establisher frame pushl $4 #set number of mechanism arguments # # at this point the stack has the following format: # # 00(sp) = number of mechanism arguments (always 4). # 04(sp) = fp of handler establisher frame (tentative). # 08(sp) = frame depth (always -1). # 12(sp) = saved r0. # 16(sp) = saved r1. # 20(sp) = flags longword # 24(sp) = number of signal arguments. # 28(sp) = exception name (integer value). # 32(sp) = first exception parameter (if any). # 36(sp) = second exception parameter (if any). # . # . # . # 28+n*4(sp) = n'th exception parameter (if any). # 28+n*4+4(sp) = exception pc. # 28+n*4+8(sp) = exception psl. # movpsl r0 #read current psl extzv $psl$v_curmod,$psl$s_curmod,r0,r1 #current mode kernel? beql 3f #if eql yes cmpzv $psl$v_prvmod,$psl$s_prvmod,r0,r1 #is current eql previous? beql 4f #if eql yes # # adjust previous mode stack pointer using system service # # pushr $^m<r2,r3,r4> #save registers r2, r3, and r4 pushr $0x01c addl3 $7,36(sp),r3 #calculate number of longwords to move pushab normal #assume information can be copied clrl -(sp) #set to use current stack pointer value pushab (sp) #push address to store updated stack value ashl $2,r3,-(sp) #calculate stack adjustment value mnegl (sp),(sp) #set negative adjustment value extzv $psl$v_prvmod,$psl$s_prvmod,r0,-(sp) #push access mode of stack pushl $3 #push number of arguments callg (sp),*$sys$adjstk #adjust previous mode stack pointer blbs r0,2f #if lbs successful completion addl2 $((6*4)+(3*4)),sp #001 strip of the stuff associated #001 with the sys$adjstk call movab 28(sp),sp #001 set sp to the exception name jmp start_handling #001 handle the exception /* *1: movab w^badstack,20(sp) #set bad stack return * movl 4(sp),r2 #retrieve previous access mode * movl *$ctl$al_stack[r2],16(sp) #set to use specifed stack pointer value * callg (sp),sys$adjstk #reload previous mode stack pointer * blbs r0,20$ #if lbs successful completion * subl3 $4,*$ctl$al_stack[r2],-(sp) #calculate top address of stack range * addl3 12(sp),(sp),-(sp) #calculate bottom address of stack range * bsbw crestack #re-create virtual space under stack * addl $8,sp #remove virtual address descriptor * brb 10$ #and try again */2: addl2 $16,sp #remove argument list from stack # popr $^m<r1> #get new previous mode stack pointer value popr $0x02 brw copyargs #3: jmp reflect #4: brw normal # # # # all exceptions converge to this point with: # # 00(sp) = number of signal arguments. # 04(sp) = exception name (integer value). # 08(sp) = first exception parameter (if any). # 12(sp) = second exception parameter (if any). # . # . # . # 04+n*4(sp) = n'th exception parameter (if any). # 04+n*4+4(sp) = exception pc. # 04+n*4+8(sp) = exception psl. # # note that the previous mode field of the psl contains the access mode # of the exception. # .globl exe$exceptionexe$exception: #this label must be global for mp code pushl $1 #set code indicating signal # pushr $^m<r0,r1> #save registers r0 and r1 pushr $0x03 mnegl $3,-(sp) #set initial frame depth pushl fp #set initial handler establisher frame pushl $4 #set number of mechanism arguments # # at this point the stack has the following format: # # 00(sp) = number of mechanism arguments (always 4). # 04(sp) = fp of handler establisher frame (tentative). # 08(sp) = frame depth (always -3). # 12(sp) = saved r0. # 16(sp) = saved r1. # 20(sp) = flags longword # 24(sp) = number of signal arguments. # 28(sp) = exception name (integer value). # 32(sp) = first exception parameter (if any). # 36(sp) = second exception parameter (if any). # . # . # . # 28+n*4(sp) = n'th exception parameter (if any). # 28+n*4+4(sp) = exception pc. # 28+n*4+8(sp) = exception psl. # reflect: #reflect exception to proper access mode/* addl3 $6,24(sp),r0 #calculate longword offset to saved psl * assume psl$v_cm eq 31 * tstl (sp)[r0] #previously in compatibility mode? * bgeq 10$ #branch if not * moval *$ctl$al_cmcntx,r1 #get address of compatibility context area * movq 12(sp),(r1)+ #save r0 and r1 * movq r2,(r1)+ #save r2 and r3 * movq r4,(r1)+ #save r4 and r5 * movl r6,(r1)+ #save r6 * movzbl $8,(r1)+ #set cm exception type * movl -4(sp)[r0],(r1)+ #save pc * movl (sp)[r0],(r1) #save psl */1: movpsl r1 #read current psl/* * mfpr $pr$_ipl,r0 #read current ipl * cmpl $ipl$_astdel,r0 #invalid priority level? * blss 20$ #if lss yes * bbc $psl$v_is,r1,30$ #if clr, then not on interrupt stack *20$: bug_check invexceptn,fatal #invalid exception *30$: ifnord $4,*$ctl$al_stack,20$ #is there a control region? */ # (not swapper,nullproc) extzv $psl$v_prvmod,$psl$s_prvmod,r1,r0 #extract previous mode field bneq 8f #if eql previous mode was kernel jmp normal #8: jmp 9f #goto paged code9: # pushr $^m<r2,r3,r4> #save registers r2, r3, r4 pushr $0x01c pushab normal #assume information can be copied movl r0,r2 #save previous mode addl3 $7,40(sp),r3 #calculate number of longwords to move mfpr r2,r1 #read previous mode stack pointer 8: bsbw check_stack #check stack range bneq 4f #continue if stack ok cmpl $psl$c_user,r2 #is it user mode stack fault? bneq 5f #no, then bad stack # pushr $^m<r1,r2,r3,r4,r5> #save registers pushr $0x03e # movl r0,r2 #get lowest stack address from check_st *ack pushl r0 #001 push address to grow calls $1,_grow #001 try to grow # bsbw exe$expandstk #and call to expand stack # popr $^m<r1,r2,r3,r4,r5> #restore registers popr $0x3e blbc r0,5f #br if any error to declare bad stack brb 8b #check the stack again #note- check_stack prevents us from loping5: movab 44(sp),sp #001 pop everthing except the exception # stuff jmp start_handling #001 go to general handler4:/* cmpl r1,*$ctl$al_stack[r2] #top address of stack in range? * bgtru 50$ #if gtru no */ cmpl $psl$c_user,r2 #previous mode user? beql 7f #if eql yes/* cmpl r0,*$ctl$al_stacklim[r2]#bottom address of stack in range? * bgequ 70$ #if gequ yes *50$: movab w^badstack,(sp) #set bad stack return * movl *$ctl$al_stack[r2],r1 #get starting address of previous mode stack * bsbw check_stack #check stack range * bneq 70$ #if neq successful range check * pushal -(r1) #push top address of stack range * movab -1024+4(r1),-(sp) #push bottom address of stack range * bsbb crestack #re-create stack space * addl $8,sp #remove virtual address limits from stack * movl *$ctl$al_stack[r2],r1 #get starting address of previous mode stack */7: ashl $2,r3,r0 #calculate number of bytes to move subl2 r0,r1 #calculate new top of stack address mtpr r1,r2 #set new previous mode stack pointer brw copyargs #
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -