This Multics source file was rescued from the messed-up source archive at MIT.
Fault Interceptor Module. This program is entered from the hardware fault vector when the CPU takes a fault.
Back to Multics Source index.
fim.alm 11/17/83 0850.4r 11/17/83 0846.2 361530
" FIM - Multics Fault Intercept Module.
"
" Modification record: (Date and Reason)
" 13 October 1982 (Wednesday, this month) by E. N. Kittlitz for instruction size
" 06 October 1982 by BIM to check for signal_entry fault
" in fim, running fim in collection 1.
" 24 March 1983 by J. A. Bush for 16/32K cache parity data capture
" 6 April 1983 by E. N. Kittlitz DRL in ring 0 causes crash.
" sometime by BIM for bootload multics.
" 17 July 1981 by M. Weaver for undefined_pointer
" 04 June 81 by J. A. Bush to fix some unreported bugs
" 3 April 81 by Benson I. Margulies for null_pointer
" 17 Jan 81 by J. Bongiovanni for fault_counters
" 27 August 80 by J. A. Bush for the DPS8/70M
" 25 march 80 by J. A. Bush to fix negative exp. overflow bug
" 15 Jan 80 by J. A. Bush for cache parity error data capture
" 24 July 79 by J. A. Bush for new signal_entry and to merge fim_table back in.
" 1 Feb 79 by D. Spector for new scs format for 8-cpu cioc
" 2/8/76 by Noel I. Morris for new reconfig
" 10/14/75 by R. Bratt for prelinking
" 6/20/75 by S.Webber for static handlers
" 3/75 by S. Webber for new restarting conventions and returning
" history registers to users.
" 5/29/74 by M. Weaver to special case out of bounds on stack
" 11/1/73 by Steve Webber to allow truncation (stringsize) faults to be restarted
" 10/15/73 by Steve Webber to correct some illegal procedure "fanout" mapping problems.
" 07/21/71 by Richard H. Gumpertz to use prds_link to get prds segment number
" 5/30/70 - Noel I. Morris
" ******************************************************
" * *
" * *
" * Copyright (c) 1972 by Massachusetts Institute of *
" * Technology and Honeywell Information Systems, Inc. *
" * *
" * *
" ******************************************************
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" FIM is transferred to as the result of a fault. The control
" unit data has been stored either in pds$fim_data or pds$signal_data.
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
name fim
inhibit on <+><+><+><+><+><+><+><+><+><+><+><+>
"
link prds_link,prds$+0
bool lprp_insts,760000
bool minus_128,400000
bool dp_opcode,2000
bool inst_bit27_on,400
bool op_code_mask,777400
bool fstr_inst,470000
bool dfstr_inst,472000
bool cu_hreg,40
bool apu_hreg,140
tempd v_temp temporary for virtual time computation
tempd v_delta temporary to remember virtual_delta
tempd pad(2)
temp8 mach_cond(6) machine conditions
temp8 history_registers(16)
tempd mc_ptr pointer to machine conditions
tempd call_ptr pointer to fault handling routine
tempd arglist(4) argument list
temp fcode fault code
temp temp(3) temporary cells
"
" ACCESS_VIOLATION_ENTRY - Handle Access Violation Faults.
segdef access_violation_entry
even
access_violation_entry:
spri prs,* save prs
eppbp prs,* bp -> machine conditions
sreg bp|mc.regs save registers
epplp lp,* set lp value
spl bp|mc.eis_info save eis ptrs and lengths
tsx0 fim_util$fim_v_time_init remember accrued virtual time
tsx0 fim_util$check_fault is it OK to take this fault?
epaq * get our segment number
era bp|mc.scu.ppr.psr_word compare against procedure segment register
ana scu.ppr.psr_mask,du were we in the fim?
tze die_die_die_ suicide
tra fault_join
"
" ONC_START_SHUT_ENTRY - entry to handle op-not-complete, startup and shutdown faults
segdef onc_start_shut_entry
even
onc_start_shut_entry:
spri prs,* save prs
eppbp prs,* bp -> machine conditions
sreg bp|mc.regs save registers
epplp lp,* set lp value
spl bp|mc.eis_info save eis ptrs and lengths
tsx0 fim_util$fim_v_time_init remember accrued virtual time
tsx0 fim_util$check_fault kill Multics if not legal fault
eppbb pds$history_reg_data bb -> place to store history regs
tsx0 fim_util$check_mct go save M.C.'s an hregs if required
tsx0 fim_util$force_hist_regs (ret ic +1) force save hregs in pds
tra onc_par_join go join common code
"
" drl_entry - entry to handle derail faults, special case of signal_entry.
segdef drl_entry
even
drl_entry:
spri sig_prs,* save prs
eppbp sig_prs,* bp -> machine conditions
sreg bp|mc.regs save registers
epplp lp,* set lp value
spl bp|mc.eis_info what the hell...
ldq bp|mc.scu.ppr.prr_word check whether running in ring-0
canq scu.ppr.prr_mask,du ring number in ppr
tnz drl_join not ring 0
stz scs$drl_message_pointer assume the worst
lda bp|mc.scu.ilc_word
eppbb 0,au offset of DRL
lda bp|mc.scu.ppr.psr_word
ana scu.ppr.psr_mask,du
easpbb 0,au segno of DRL
lda bb|0 get the DRL instruction
ana =o777777,du
tze *+3 no operand
eawpbb 0,au operand of DRL instruction
sprpbb scs$drl_message_pointer
tra fim_util$drl_fault_trouble punt ye system
"
" parity_entry - entry to handle parity faults
segdef parity_entry
even
parity_entry:
lcpr cache_off,02 turn cache off in case this is cache parity
spri prs,* save prs
eppbp prs,* bp -> machine conditions
sreg bp|mc.regs save registers
epplp lp,* set lp value
spl bp|mc.eis_info save eis ptrs and lengths
tsx0 fim_util$fim_v_time_init remember accrued virtual time
eppbb pds$history_reg_data bb -> place to store history regs
tsx0 fim_util$check_mct go save M. C.'s and hregs if required
tsx0 fim_util$force_hist_regs (ret ic +1) force save hregs in pds
lda bp|mc.fault_reg load fault reg
cana 12,dl is it cache store or cache dir parity?
tnz csd_par xfer if yes
tsx0 fim_util$check_fault no, kill Multics if parity in hardcore etc.
tra onc_par_join and join common code
csd_par: stz pds$cpar_info initialize cache parity info structure
cana 4,dl is it cache store parity?
tnz cstr_par xfer if yes
tsx0 fim_util$check_fault no cache dir parity
tsx0 save_cache go save cache enable bits
tra onc_par_join and join common code
cstr_par: lda bp|mc.scu.cpu_no_word Get the cpu number in A
ana scu.cpu_no_mask,dl
arl scu.cpu_shift right justify in AL
ldx1 scs$processor_data,al Get cache size
anx1 7,du in X1
eax1 -1,1 can't have 0 size at this point
epaq fim_abs_seg$ get ptr to abs seg
als 1 multiply by 2
eax7 0,au copy segno to x7
eppap fim_abs_seg$ set ap with abs_seg ptr
eax2 15*2 set initial cu hreg index
cuhrlp: eax5 15*2 set initial apu hreg index
tsx0 fnd_crd go check for cache read cycle
tra apuhrlp return ic+1, cache read (L68)
tra dps8_hit return ic+2, cache read (DPS8)
dec_cux: eax2 -2,2 return ic+3, not cache read
tmi no_find exit if no more cu hregs
tra cuhrlp go get next cu hreg
apuhrlp: ldaq bb|apu_hreg,5 load next apu hreg
cana apuhra.fap+apuhra.fanp,dl is this final address (fanp or fap)?
tze dec_apx xfer if no, skip to next apu hreg
qrl apuhra.finadd_shift right justify abs addr
anq =o777,dl and out upper addr bits
cmpq bp|mc.fim_temp is this the same as cu addr?
tze addmatch xfer if yes
dec_apx: eax5 -2,5 no, go to nxt apu hreg
tmi dec_cux get nxt cu hreg is apu hregs exhausted
tra apuhrlp get nxt apu hreg
addmatch: lda bb|apu_hreg+1,5 matching cu and apu address
cana apuhra.encache,dl is segment encacheable?
tze dec_cux xfer if no, go to nxt cu/apu match
dps8_hit: " Enter here if dps8 cache read
arl 12 zero out all but 24 bit address
sta pds$cpar_info and save
eax6 0,al copy lower 256k address to x6
anx6 c_256k_mask,1 make mod <cache size> address
ana c_abs_addr_mask,1 make absaddr mod <cache size>
als 12 shift into position
ora sdw.valid,dl set directed fault bit
ldq c_sdw_bounds,1 set up rest of sdw
staq dseg$,7 set sdw in dseg
cams "clear associative memory
camp
ldaq ap|0,6 get memory contents
staq pds$cpar_mem_data and save
anx6 c_lv_st_mask,1 make address start at level 0
eax3 -4 x3 counts levels
cparlvlp: ldi scu.ir.parm,dl set parity mask
lcpr cache_to_reg_mode,02 set cache dump mode
ldaq ap|0,6 dump cache contents
lcpr cache_off,02 reset cache dump mode
sti bp|mc.fim_temp save indicators
eraq pds$cpar_mem_data exclusive or it with data in mem
staq pds$cpar_err_data save it
ldi 0,dl reset parity mask
lda bp|mc.fim_temp load indicators
cana scu.ir.par,dl parity error?
tnz cpar_hit xfer if yes
nxt_lvl: adx6 c_lv_inc_tab,1 get set for nxt level
eax3 1,3 any more levels?
tmi cparlvlp yes, go to nxt level
tra dec_cux no, go check previous read
cpar_hit: ldi scu.ir.oflm,dl mask overflows
lcaq pds$cpar_err_data get compliment of XOR data
ldi 0,dl reset overflow mask
anaq pds$cpar_err_data and 2s compliment data with itself
cmpaq pds$cpar_err_data if single bit failure, it should compare
tnz nxt_lvl multiple bit failure, go try nxt level
ldi scu.ir.parm,dl set parity mask
lcpr cache_to_reg_mode,02 set cache dump mode
ldaq ap|0,6 dump cache contents
lcpr cache_off,02 reset cache dump mode
staq pds$cpar_err_data save it
ldi 0,dl reset parity mask
eaa 0,6 copy level info to a
arl c_lv_shift,1 position per cache size
ana =o300,du and out all but level
ora =o400000,du set flag for data capture
orsa pds$cpar_info and save
no_find: lda 0,du
ldq 0,du zero out abs seg sdw
staq dseg$,7
cams 4 clear assosiative memory and cache
camp
tsx0 save_cache go save cache enable bits
tsx0 fim_util$check_fault now go check to see if fault in hardcore
tra onc_par_join and go join common code
"
" signal_entry - entry to handle faults that are directly signalable
" in the outer rings (not ring 0)
segdef signal_entry
even
signal_entry:
spri sig_prs,* save prs
eppbp sig_prs,* bp -> machine conditions
sreg bp|mc.regs save registers
epplp lp,* set lp value
spl bp|mc.eis_info save eis ptrs and lengths
drl_join:
tsx0 fim_util$fim_v_time_init remember accrued virtual time
tsx0 fim_util$check_fault kill Multics if not legal fault
lda bp|mc.scu.fault_data_word
ana scu.fi_num_mask,dl get fault address
signal_it:
sta bp|mc.errcode temporarily save fault code
arl 1 divide by 2
aos wired_hardcore_data$fault_counters,al increment fault counter
als 1 multiply by 2
ldaq fault_table,al pick up table entry
anq audit_flags.mask,dl do we need to audit this event?
tze no_sig_audit xfer if no.
qls 18 put audit flags in upper half
canq pds$audit_flags check appropriate audit flag
tze no_sig_audit xfer if not auditing
tsx1 call_audit yes, go do it
no_sig_audit:
tra 0,au dispatch on entry value
call_signaller: "most signalable faults come here directly
eppbb pds$history_reg_data bb -> place to store history regs
tsx0 fim_util$check_mct go save M. C.'s and hregs if required
tsx0 fim_util$hist_regs (ret ic +1) save hregs in pds
tsx0 fim_util$reset_mode_reg (ret ic +2) turn them back on now
lda bp|mc.errcode get fault code for retrieving name
arl 1 divide by 2
sta bp|mc.fim_temp save the sct index for signal_
als 1 multiply by 2
stz bp|mc.errcode initialize error code
lda fault_table+1,al pick up second word of fault table entry
eppbb 0,au get pointer to name from its left half word
eppab pds$condition_name get pointer to place to store name
ldq bb|0 get first word of string for ACC size
qrl 27 right justify size of string
adlq 1,dl add 1 for count character
mlr (pr,rl),(pr),fill(0)
desc9a bb|0,ql
desc9a ab|0,32
eppsb pds$stack_0_ptr,* set SB to the ring 0 stack
tra signaller$signaller now give control to the signaller
"
" PRIMARY_FAULT_ENTRY - Most faults arrive at this entry.
segdef primary_fault_entry
even
primary_fault_entry:
spri prs,* save prs
eppbp prs,* bp -> machine conditions
sreg bp|mc.regs save registers
epplp lp,* set lp value
spl bp|mc.eis_info save eis ptrs and lengths
tsx0 fim_util$fim_v_time_init remember accrued virtual time
tsx0 fim_util$check_fault kill Multics if not legal fault
fault_join:
eppbb pds$history_reg_data bb -> place to store history regs
tsx0 fim_util$check_mct go save M.C.'s an hregs if required
tsx0 fim_util$hist_regs (ret ic +1) save hregs (if not saved by check_mct)
onc_par_join:
tsx0 fim_util$reset_mode_reg (ret ic +2) turn them back on now
eppsb pds$stack_0_ptr,* make FIM's stack frame on the ring 0 stack
ldx7 push ..
tsx0 fim_util$push_stack ..
eppap mach_cond ap -> place for machine conditions
tsx0 fim_util$copy_mc copy machine conditions into stack frame
spribp mc_ptr set mc_ptr in stack frame
ldaq pds$fim_v_temp save CPU time at start of fault
staq v_temp ..
ldaq pds$fim_v_delta save virtual delta at start of fault
staq v_delta ..
szn pds$hregs_saved do we want to copy hregs?
tze no_hist
eppap history_registers bb -> hregs either in mc_trace buffer or pds
mlr (pr),(pr) copy hregs into stack frame
desc9a bb|0,128*4
desc9a ap|0,128*4
no_hist: inhibit off <-><-><-><-><-><-><-><-><-><-><-><->
" Dispatch on Fault Code.
stz bp|mc.errcode clear the error code
lda bp|mc.scu.fault_data_word get fault number
ana scu.fi_num_mask,dl
set_fault:
sta fcode save the fault code
arl 1 divide by 2
aos wired_hardcore_data$fault_counters,al
sta bp|mc.fim_temp save the fault code in the MC
als 1 multiply by 2
ldaq fault_table,al pick up table entry
anq audit_flags.mask,dl get special action code for this fault
tnz audit_ck we need to audit this event
normal_set_fault:
tra 0,au dispatch on entry value
"
audit_ck:
qls 18 put audit flags in upper half
canq pds$audit_flags Check appropriate audit flag
tze normal_set_fault Not auditing, go back
eppap mc_ptr Get machine conditions pointer
spriap arglist+2 Stuff it in arg list
fld =1b24,dl One argument
ora =o4,dl Make arglist header
staq arglist Stuff it where it belongs
call protection_audit_$fault(arglist) Call fault entry in auditor
lda fcode Pick up the fault code again
lda fault_table,al Pick up the table entry
tra normal_set_fault Go back
"
" Set up the call to the appropriate handler.
"
" The right half of the accumulator contains an offset
" in the fim's linkage section of the procedure to call
" to handle the fault.
"
" All handlers are called in the following way:
"
" call handler (mc_ptr)
"
" where mc_ptr points to the machine conditions, not the
" SCU data.
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
call_signaller_signal:
arg call_signaller
arg call_signal
standard.signal_check_coll:
eax0 1
tra standard.check_common
standard.signaller_check_coll:
eax0 0
standard.check_common:
ldq sys_info$initialization_state
cmpq 1,dl
tmoz call_signaller_signal,x0*
standard:
eppap lp|0,al* generate pointer to the handler
spriap call_ptr save the handler pointer
fld =1b24,dl set up argument list header (1 argument)
ora =o4,dl
staq arglist
eppap mc_ptr set up argument list (1st arg is mc_ptr)
spriap arglist+2
tra call
"
" Access Violation faults
"
" All access violation subcases are separated out
" in the next sequence of code. Some are signalled, some are handled
" by the system.
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
access_violation:
lda bp|mc.scu.fault_data_word get sub-class of access violation fault
ana -1,du leave only sub-class bits
eax7 0 Determine which is highest bit on.
acv_bit_loop:
cana =o400000,du Test bit.
tnz acv_bit_end
eax7 2,7 On to next bit.
als 1
tnz acv_bit_loop Unless all bits off.
acv_bit_end:
eaa avf,7 generate simulated code word
cmpa oob,du see if bound fault (if so make special checks)
tze check_special_oob yes, make tests
tra fixindex_1 must be normal access violation of some type
check_special_oob:
ldq bp|mc.scu.tpr.tsr_word "fetch the TSR
anq scu.tpr.tsr_mask,du leave only segment number
eax7 null get set for simfault
cmpq =o077777,du is it a null pointer?
tze fixindex yes, handle the null pointer.
cmpq =o077776,du is a terminate process?
tze term_it yes, go handle it
eax7 undefp get set for undefined_pointer
cmpq =o077775,du is it an undefined pointer?
tze fixindex yes, handle it
eax7 stk_oob get set for out_of_bounds on stack
erq bp|mc.prs+6*2 exclusive or stack segno with tsr
anq =o077777,du set indicators to note any difference
tze fixindex no, call handler to extend stack
tra fixindex_1 not special oob, treat as real oob
fixindex:
eaa 0,7 new index in A
fixindex_1:
sbla fault_table,du get relative address
arl 18 right-justify
tra set_fault back to the dispatch table
"
" Command faults
"
" The command fault could be either hardware oriented, configuration
" oriented, or an attempt to load a faulting packed pointer.
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
command_fault:
eax7 com assume normal command fault
ldq bp|mc.scu.port_stat_word check illegal action
canq scu.ial_mask,dl
tnz fixindex nonzero, treat as normal case
ldq bp|scu.even_inst_word check for LPRPxx instruction
anq =o770400,dl
cmpq lprp_insts,dl
tnz fixindex isn't LPRPxx, treat as normal
" It is packed pointer fault. See if system version.
eax7 ppf
ldq bp|mc.scu.ca_word pick up faulting pointer pair
lda bp|mc.scu.tpr.tsr_word
ana scu.tpr.tsr_mask,du
easp3 0,au generate pointer
eawp3 0,qu
lda bb|0 pick up the packed pointer
cana =o100000,du check system bit
tze fixindex not ON. Treat as normal packed pointer fault
ana =o000777,du
cmpa 3,du
tpl fixindex
als 1 multiply by 2
eax7 sppf,au
tra fixindex
"
" Overflow faults
"
" The overflow fault could result from one of:
"
" fixedoverflow
" exponent overflow
" exponent underflow
" stringesize (EIS truncation fault)
"
"
" The following code looks at the indicators to see what kind
" of overflow fault occured and to remap the fault into the
" corresponding name.
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
inhibit on <+><+><+><+><+><+><+><+><+><+><+><+>
split_overflow:
ldq bp|mc.scu.indicators_word get the indicators and ilc
canq scu.ir.ovfl,dl is it "fixedoverflow"?
tnz ck_eis_size yes go check for eis size.
canq scu.ir.eufl,dl is it "underflow"?
tze ck_eovfl no, go check for exp overflow
eax7 eufl yes, set exp underflow index
tsx1 ck_str_rd go get op_code from object seg
tra sig_index return (ic+1), don't restart EIS
tra set_und_rfi return (ic+2) don't increment ic
adlq 1,du return (ic+3) increment ic
stq bp|mc.scu.ilc_word by one and restore ic word
set_und_rfi:
lda scu.cu.rfi+scu.cu.if,dl set rfi and if bits
orsa bp|mc.scu.cu_stat_word in cu status word
stz bp|mc.regs+4 zero out saved a
stz bp|mc.regs+5 and q regs
lda minus_128,du and set e reg to -128
sta bp|mc.regs+6
szn pds$exp_undfl_rest restart fault in the fim?
tze sig_index xfer if no, go signal fault
lda bp|mc.scu.indicators_word get indicator reg
ana =o177777,dl and out negative indicator
ora scu.ir.zero,dl and set zero indicator
stba bp|mc.scu.indicators_word,14 and restore indicators
und_ovr_rest:
lca scu.ir.eufl+scu.ir.eovf+1,dl reset exp over/under flow indicators
ansa bp|mc.scu.indicators_word
tsx0 fim_util$reset_mode_reg turn hregs back on
sznc pds$connect_pending is connect pending?
tze no_con_pend if not, skip next
lxl1 prds$processor_tag CPU tag in X1
cioc scs$cow_ptrs,1* do a connect now
lra =0 prevent ring alarm before cioc takes
no_con_pend:
lreg bp|mc.regs restore the registers
lpri bp|mc.prs and the prs
rcu sig_scu,* return to faulting location
ck_eovfl:
canq scu.ir.eovf,dl is it "overflow"?
tze ck_trunc no, go check truncation
eax7 eovf yes, load table index
tsx1 ck_str_rd check for fstr/dfstr instr
tra sig_index return (ic+1), don't restart EIS
tra ck_ovfl_rest return (ic+2), don't increment ic
adlq 1,du return (ic+3) increment ic
stq bp|mc.scu.ilc_word by one and restore ic word
ck_ovfl_rest:
szn pds$exp_ovfl_rest restart fault in fim?
tze sig_index xfer if no, go signal fault
canx5 dp_opcode,du yes, is this double precision?
tnz doub_prec xfer if yes
fld pds$eovfl_value no, load sp restart value
tra str_rest_vlu and go store it
doub_prec:
dfld pds$eovfl_value load dp restart value
str_rest_vlu:
szn bp|mc.regs+4 is this a negative overflow?
tpl no_negate no, store value as is
fneg 0 yes, negate the value
no_negate:
staq bp|mc.regs+4 and store it
ste bp|mc.regs+6 store exponent
lda scu.cu.rfi+scu.cu.if,dl set rfi and if bits
orsa bp|mc.scu.cu_stat_word in cu status word
tra und_ovr_rest go restart overflow
ck_eis_size:
eax7 ovfl set up for "fixedoverflow"
canq scu.ir.mif,dl is it EIS fault?
tnz ck_sz_loc xfer if yes
sig_index:
eaa 0,7 copy fault index to a
sbla fault_table,du get relative address
arl 18 right justify
tra signal_it and go signal fault
ck_sz_loc:
lda bp|scu.even_inst_word is this potenialy eis instr?
cana inst_bit27_on,dl if bit 27 is not on, can't be eis inst
tze sig_index no, signal fixedoverflow
eax7 size_loc set size fault index
tra sig_index and go signal it
ck_trunc:
canq scu.ir.tru,dl is it truncation?
tze fim_util$fault_trouble hardware error id none of above
eax7 trun yes, set truncation fault index
"
" We have a "stringsize" condition. Set up the machine
" conditions so we can restart the instruction.
"
szn pds$pl1_machine can we alter apparent machine ops?
tze sig_index xfer if no, bare 6180 machine
tsx1 get_instruction_size
adla bp|mc.scu.ilc_word increment ic by eis instr size
sta bp|mc.scu.ilc_word and restore ic word
lca scu.ir.mif+1,dl we must turn OFF this indicator so the next
ansa bp|mc.scu.indicators_word EIS instruction will be correctly initialized
lda scu.cu.rfi+scu.cu.if,dl set rfi and if bits
orsa bp|mc.scu.cu_stat_word in cu status word
tra sig_index go signal "stringsize"
"
" Illegal procedure faults
"
" There are several subcases which are distinguished
" They are:
" illegal op code
" illegal address and modifier
" other illegal procedure faults
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
illegal_procedure:
epaq * get our segment number
era bp|mc.scu.ppr.psr_word compare against procedure segment register
ana scu.ppr.psr_mask,du were we in the fim?
tze die_die_die_ suicide
lda bp|mc.scu.fault_data_word get the fault dataister
eax7 foc get set for illegal op code
cana scu.fd.ioc,du
tnz sig_index yes, use the given index
eax7 bam get set for bad modifier or address
cana scu.fd.ia_im,du
tnz sig_index
eax7 ipr get set for all other illegal procedure
tra sig_index
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" fnd_crd - subroutine to check for cache read cycle in current CU history reg
" for cache parity diagnostics.
" return is ic+1, if L68 cache read cycle,
" ic+2, if dps8 cache read cycle (A reg contains abs addr, in upper)
" ic+3, if not a cache read cycle
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
fnd_crd: ldaq bb|cu_hreg,2 load next cu hreg
cmpx4 1,du is this a dps8 cpu?
tze cu_dps8 xfer if yes, otherwise L68
canq cuhra.dir,dl is this direct cu cycle?
tnz 2,0 xfer if yes, skip to next cu hreg
lls 18 position addr in al
anq =o760000,du mem cmd in qu
tze l68_rd_cmd xfer if single precision read
cmpq =o40000,du no, is it D.P read?
tze l68_rd_cmd xfer if yes
tra 2,0 not cache read, return ic+3
l68_rd_cmd:
ana =o777,dl discard upper address
sta bp|mc.fim_temp save address
tra 0,0 return ic+1, L68 cache read
cu_dps8: cana cuhr.pia,du dps8 pia cycle?
tze 2,0 No, return ic+3
cana cuhr.internal,du dps8 cache cycle?
tze 2,0 No, return ic+3
lda bb|cu_hreg+1,2 got a hit, load abs addr in A
tra 1,0 return ic+2, DPS8 cache read
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" save_cache - subroutine to save current state of cache memory enable bits
" (csh1 and csh2) located in the prds$cache_luf_reg and then reset the bits
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
save_cache:
lda prds$cache_luf_reg get current cache enable bits
ana =o600000,dl and out all but csh1 and csh2
als 10 position
orsa pds$cpar_info and save in pds
lda 3,dl
ansa prds$cache_luf_reg turn off all cache enable bits
tra 0,0 return to caller
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" ck_str_rd - subroutine to check if faulting instruction is a
" FSTR or DFSTR by looking in the object segment at psr|ic.
" entry: tsx1 ck_str_rd
" in regs: QR = ilc,indicator word from scu data
" BP -> machine conditions
" out regs: QR is unchanged
" x5 = instruction op code
" return: ic+1 if bit 27 is on (EIS instruction)
" ic+2 if instruction is fstr or dfstr instruction
" ic+3 if any other instruction
"
" NOTE:
" Theory of touching the text segment, as of 82-10-26.
" Yes, we might take a page or segment fault on the load
" of the instruction word. However, it is VERY unlikely, given
" selection algorithms for evicting a page/segment.
" Further, the SDW and PTW are almost certainly in our AM, and
" we haven't been listening to any connects to get them out.
" If we take a seg_fault, we'll be using fim_data for machine
" conditions, and the only fim routines that call this routine
" are supposed to have come in using signal_data/signal_entry.
" Thus, we don't have to worry about our data getting clobbered.
" If we end up taking a seg-fault error (seg deleted), or
" a page-fault error, we're just going to signal that error
" anyhow. For anything except the original fault being in
" ring zero, this means crawlout.
" For ring zero, we would conceivably have to worry about
" someone having a handler for such an error and actually
" wanting to restart the original fault. "It'll never happen."
"
" All this makes us think that it isn't worth the expense
" of moving the machine conditions to a stack frame before
" touching the text instruction.
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
ck_str_rd:
lda bp|mc.scu.ppr.psr_word
ana scu.ppr.psr_mask,du
eppab 0,qu set word offset, pr.ringno=0
easpab 0,au get segno from psr
lxl5 ab|0 load instruction op code in x5
anx5 op_code_mask,du just look at op code
canx5 inst_bit27_on,du is this an EIS instruction?
tnz 0,1 yes, return ic+1
cmpx5 fstr_inst,du fstr instruction?
tze 1,1 return ic+2 if yes
cmpx5 dfstr_inst,du no, dfstr instruction?
tze 1,1 return ic+2 if yes
tra 2,1 no, return ic+3
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" get_instruction_size - subroutine to determine the size of an instruction
" by looking in the object segment at psr|ic.
" entry: tsx1 get_instruction_size
" in regs: QR = ilc,indicator word from scu data
" BP -> machine conditions
" out regs: QR is unchanged
" X5 = instruction op code
" AU = instruction size
"
" See the NOTE in check_str_rd.
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
get_instruction_size:
lda bp|mc.scu.ppr.psr_word
ana scu.ppr.psr_mask,du
eppab 0,qu get word offset from ilc, set PRab.ring = 0
easpab 0,au get segno from psr
lxl5 ab|0 load instruction op code in x5
anx5 op_code_mask,du just look at op code
lda 1,dl default to 1 word
canx5 inst_bit27_on,du is this an EIS instruction?
tze 0,1 no, return
eaa gis_table table pointer
gis_loop: cmpx5 0,au gone far enough down the table?
tnc gis_found got it
eaa 1,au get next entry
tra gis_loop
gis_found:
lda 0,au return the size
als 18
tra 0,1
gis_table:
vfd 9o/057,1/1,8/0,18/4 mve,mvne
vfd 9o/117,1/1,8/0,18/3 csl,csr,sztl,sztr,cmpb,mlr,mrl,cmpc
vfd 9o/127,1/1,8/0,18/4 scd,scdr,scm,scmr
vfd 9o/157,1/1,8/0,18/1 sptr
vfd 9o/167,1/1,8/0,18/4 mvt,tct,tctr
vfd 9o/177,1/1,8/0,18/1 lptr
vfd 9o/217,1/1,8/0,18/3 ad2d,sb2d,mp2d,dv2d
vfd 9o/227,1/1,8/0,18/4 ad3d,sb3d,mp3d,dv3d
vfd 9o/277,1/1,8/0,18/1 lsdr,sbpb0-3,ssdr,lptp
vfd 9o/307,1/1,8/0,18/3 mvn,btd,cmpn,dtb
vfd 9o/777,9o/777,18/1 easpN,epbpN,sareg,spl,lareg,
" and all the others...
"
call_audit:
eppsb pds$stack_0_ptr,* make FIM's stack frame on the ring 0 stack
ldx7 push ..
tsx0 fim_util$push_stack ..
eppap mach_cond ap -> place for machine conditions
tsx0 fim_util$copy_mc copy machine conditions into stack frame
inhibit off <-><-><-><-><-><-><-><-><-><-><-><->
spribp mc_ptr set mc_ptr in stack frame
eppap mc_ptr Get machine conditions pointer
spriap arglist+2 Stuff it in arg list
fld =1b24,dl One argument
ora =o4,dl Make arglist header
staq arglist Stuff it where it belongs
call protection_audit_$fault(arglist) Call fault entry in auditor
eppap pds$signal_data copy M.C.s back to signal data
tsx0 fim_util$copy_mc
inhibit on <+><+><+><+><+><+><+><+><+><+><+><+>
sprisp sb|stack_header.stack_end_ptr reset stack end pointer (and pop frame)
lda bp|mc.errcode restore the fault code from the MC
lda fault_table,al and pick up table entry
tra 0,1 and return
"
inhibit off <-><-><-><-><-><-><-><-><-><-><-><->
" Make call to fault handler.
call:
call call_ptr,*(arglist) make the call
" Test for error .
eppbp mach_cond bp -> machine conditions
szn bp|mc.errcode test for error
tnz call_signal ..
inhibit on <+><+><+><+><+><+><+><+><+><+><+><+>
eppap prs,* ap -> wired-down m.c.
mlr (pr),(pr)
desc9a bp|mc.scu,8*4
desc9a ap|mc.scu,8*4
ldaq v_temp restore virtual time parameters
staq pds$fim_v_temp ..
ldaq v_delta ..
staq pds$fim_v_delta ..
lda fcode get fault code again
ldaq fault_table,al load table entry
sprisp sb|stack_header.stack_end_ptr reset stack end pointer
sznc pds$connect_pending must we do connect?
tze no_connect if not, skip next
lxl1 prds$processor_tag CPU tag in X1
cioc scs$cow_ptrs,1* do a connect now
lra =0 prevent ring alarm before connect takes
no_connect:
canq =o1,dl suspend virtual time?
tze no_v_time_meter if not, don't meter
odd
tsx0 fim_util$fim_v_time_calc compute virtual delta
no_v_time_meter:
lpl bp|mc.eis_info save eis ptrs and lengths
lreg bp|mc.regs restore the registers
lpri bp|mc.prs and the prs
rcu scu,* return to faulting location
"
" Come here when time to signal the event.
call_signal:
lda bp|mc.fim_temp resignal?
cana =o400000,dl ..
tze call_signal.1 no.
als 1 get new fault code
stca fcode,07
call_signal.1:
lxl7 fcode get fault code for retrieving name
lda fault_table+1,7 pick up second word of fault table entry
eppbb 0,au get pointer to name from its left half word
eppab pds$condition_name get pointer to place to store name
ldq bb|0 get first word of string for ACC size
qrl 27 right justify size of string
adlq 1,dl add 1 for count character
mlr (pr,rl),(pr),fill(0)
desc9a bb|0,ql
desc9a ab|0,32
eppap pds$signal_data
tsx0 fim_util$copy_mc
szn pds$hregs_saved
tze signaller$signaller
mlr (pr),(pr)
desc9a history_registers,128*4
desc9a ap|48,128*4
tra signaller$signaller now give control to the signaller
"
" Arrive Here If Fault Occurred While Running in the FIM.
die_die_die_:
eppsb pds$stack_0_ptr,* get a pointer to the base of the ring 0 stack
" Try to preserve stack history in case the original fault was
" on the ring 0 stack.
eppsp sb|stack_header.stack_end_ptr,* " where does it think it is?
eax0 sp|0
cmpx0 =o30000,du reasonable ?
tmoz die_die_die_.use_end_ptr
eppsp sb|stack_header.stack_begin_ptr,* lay down frame at first available place
sprisp sb|stack_header.stack_end_ptr
die_die_die_.use_end_ptr:
ldx7 push get size of stack frame
tsx0 fim_util$push_stack make frame at base of pds
lda -1,du
tra die_die_die_.fake_ca
term_it:
lda bp|mc.scu.ca_word get computed address
die_die_die_.fake_ca:
ars 18 convert to fixed bin
sta temp save in stack (temporary cell)
szn tc_data$wait_enable
tze wired_fim$unexp_fault
eppap terminate_proc$terminate_proc kill this process
spriap call_ptr ..
eppap temp
spriap arglist+2
fld =1b24,dl one argument
ora =o4,dl make PL/1 calling sequence
staq arglist ..
tra call make the call
"
" Storage and Constants.
illegal_fault: "transfer vector for illegal fault
tra fim_util$fault_trouble
inhibit off <-><-><-><-><-><-><-><-><-><-><-><->
" The following items must be filled in at
" system initialization time.
segdef lp,prs,scu,sig_prs,sig_scu
even
lp: its -1,1 lp value for fim
prs: its -1,1 pointer to pds$fim_data
scu: its -1,1 pointer to pds$fim_data+24
sig_prs: its -1,1 pointer to pds$signal_data
sig_scu: its -1,1 pointer to pds$signal_data+24
push: push " used to get size of stack frame
cache_off:
vfd 36/3 constant to turn off cache, luf time max
cache_to_reg_mode:
oct 10003 constant to dump cache to aq, luf time max
"
" Tables indexed by cache size used for cache parity error diagnosis
c_sdw_bounds: "template for last half of abs_seg sdw
vfd 1/,o14/177,3/sdw.read,o18/sdw.unpaged for 2k (L68) cache
vfd 1/,o14/777,3/sdw.read,o18/sdw.unpaged for 8k (DPS8) cache
vfd 1/,o14/777,3/sdw.read,o18/sdw.unpaged for 8k (DPS8 VS & SC) cache
vfd 1/,o14/1777,3/sdw.read,o18/sdw.unpaged for 16k (DPS8 VS & SC) cache
vfd 1/,o14/3777,3/sdw.read,o18/sdw.unpaged for 32k (DPS8 VS & SC) cache
c_lv_inc_tab: " to increment cache levels
vfd o18/1000,18/0 for 2k (L68) cache
vfd o18/4000,18/0 for 8k (DPS8) cache
vfd o18/4000,18/0 for 8k (DPS8 VS & SC) cache
vfd o18/10000,18/0 for 16k (DPS8 VS & SC) cache
vfd o18/20000,18/0 for 32k (DPS8 VS & SC) cache
c_lv_st_mask: " to mask to level 0 for start
vfd o18/776,18/0 for 2k (L68) cache
vfd o18/3776,18/0 for 8k (DPS8) cache
vfd o18/3776,18/0 for 8k (DPS8 VS & SC) cache
vfd o18/7776,18/0 for 16k (DPS8 VS & SC) cache
vfd o18/17776,18/0 for 32k (DPS8 VS & SC) cache
c_256k_mask: " to mask cache addr within mod cache size
vfd o18/3776,18/0 for 2k (L68) cache
vfd o18/17776,18/0 for 8k (DPS8) cache
vfd o18/17776,18/0 for 8k (DPS8 VS & SC) cache
vfd o18/37776,18/0 for 16k (DPS8 VS & SC) cache
vfd o18/77776,18/0 for 32k (DPS8 VS & SC) cache
c_abs_addr_mask: " to mask abs addr to mod cache size for SDW
vfd 12/0,o15/77774,9/0 for 2k (L68) cache
vfd 12/0,o15/77760,9/0 for 8k (DPS8) cache
vfd 12/0,o15/77760,9/0 for 8k (DPS8 VS & SC) cache
vfd 12/0,o15/77740,9/0 for 16k (DPS8 VS & SC) cache
vfd 12/0,o15/77700,9/0 for 32k (DPS8 VS & SC) cache
c_lv_shift: " to shift level info for saving
dec 3 for 2k (L68) cache
dec 5 for 8k (DPS8) cache
dec 5 for 8k (DPS8 VS & SC) cache
dec 6 for 16k (DPS8 VS & SC) cache
dec 7 for 32k (DPS8 VS & SC) cache
"
" Dispatch Table for fim.
" modified 1/7/76 by D. M. Wells to add neti condition
" modified 2/26/76 by Noel I. Morris to place in separate segment.
" modified July 77 by T. Casey to add susp and term.
" modified Oct 77 by T. Casey to rename them to sus_ and trm_.
" modified 7/79 by J. A. Bush for new signal_entry of fim and to merge back into the fim
" Each entry in the dispatch table contains two words. The first
" word has an entrypoint in the fim to transfer to to handle the fault
" in the left half and a pointer relative to the linkage section of
" an external entry to call in the right half. If the left half
" is not standard, the right half is not defined.
" The second word contains a relative pointer to the ACC string name
" of the condition associated with the fault in the left half. The right
" half contains flags, which currently are used to indicate
" the necessity of auditing this fault
" (one or more bits in the left 15 bits of this field).
" The presence of the low-order bit indicates that the time
" for processing this fault should be accrued to virtual time.
"
" ___________________________________________
" | | |
" | FIM handler | External handler |
" _|_____________________|_____________________|
" | | |
" | ACC string ptr | FLAGS |
" _|_____________________|_____________________|
"
"
" The following macro is used to generate entries in the dispatch table.
" The unique string (label) is the value of the SCT index.
macro table
zero &1,&2
vfd 18/&U,18/&4
use names
&U: acc "&3"
use main
"
&end
use names
use main
join /text/main,names
"
" External Links.
link am_fault_link,access_viol$am_fault
link ring_alarm_fault_link,ring_alarm$fault
link seg_fault_link,seg_fault$seg_fault
link hardware_fault_link,hardware_fault$hardware_fault
link boundfault_link,boundfault$boundfault
link linkage_fault_link,link_snap$link_fault
link owc_link,outward_call_handler$outward_call_handler
link stack_oob_handler,stack_oob_handler$stack_oob_handler
"
even
fault_table:
table standard,hardware_fault_link,shutdown
table call_signaller,,store
table call_signaller,,mme1
table call_signaller,,fault_tag_1
table illegal_fault,,timer_runout
table command_fault,,command
table call_signaller,,derail
table call_signaller,,lockup
table illegal_fault,,connect
table standard,hardware_fault_link,parity
table illegal_procedure,,illegal_procedure
table standard,hardware_fault_link,op_not_complete
table standard,hardware_fault_link,startup
table split_overflow,,ovrflo
table call_signaller,,zerodivide
table illegal_fault,,execute
table standard.signaller_check_coll,seg_fault_link,seg_fault_error,1
pf_loc: table illegal_fault,,page_fault_error
table illegal_fault,,directed_fault_2
table call_signaller,,directed_fault_3
table access_violation,,accessviolation
table call_signaller,,mme2
table call_signaller,,mme3
table call_signaller,,mme4
table standard.signaller_check_coll,linkage_fault_link,linkage_error
table call_signaller,,fault_tag_3
table illegal_fault,,undefined_fault
table illegal_fault,,undefined_fault
table illegal_fault,,undefined_fault
table illegal_fault,,undefined_fault
table illegal_fault,,undefined_fault
table illegal_fault,,trouble
"
" Additional entries for subcases of faults.
foc: table call_signaller,,illegal_opcode,audit_flags.ipr
null: table call_signal,,null_pointer
bam: table call_signaller,,illegal_modifier,audit_flags.ipr
avf: table call_signal,,illegal_ring_order,audit_flags.acv_ring
table call_signal,,not_in_execute_bracket,audit_flags.acv_ring
table call_signal,,no_execute_permission,audit_flags.acv_mode
table call_signal,,not_in_read_bracket,audit_flags.acv_ring
table call_signal,,no_read_permission,audit_flags.acv_mode
table call_signal,,not_in_write_bracket,audit_flags.acv_ring
table call_signal,,no_write_permission,audit_flags.acv_mode
table call_signal,,not_a_gate,audit_flags.acv_ring
table call_signal,,not_in_call_bracket,audit_flags.acv_ring
table standard.signal_check_coll,owc_link,outward_call
table call_signal,,bad_outward_call,audit_flags.acv_ring
table call_signal,,inward_return,audit_flags.acv_ring
table call_signal,,cross_ring_transfer
table standard.signal_check_coll,ring_alarm_fault_link,ring_alarm_fault,1
table standard,am_fault_link,am_fault
oob: table standard.signal_check_coll,boundfault_link,out_of_bounds,1
ovfl: table call_signaller,,fixedoverflow
eovf: table call_signaller,,overflow
eufl: table call_signaller,,underflow
trun: table call_signaller,,stringsize
ipr: table call_signaller,,illegal_procedure
stk_oob: table standard.signal_check_coll,stack_oob_handler,storage
ppf: table call_signal,,packed_pointer_fault
sppf: table call_signal,,lot_fault
table call_signal,,isot_fault
table call_signal,,system_packed_pointer
quit_loc: table call_signal,,quit
alrm_loc: table call_signal,,alrm
cput_loc: table call_signal,,cput
rqo_loc: table call_signal,,record_quota_overflow
size_loc: table call_signaller,,size
table call_signal,,neti
com: table standard,hardware_fault_link,command
table call_signal,,sus_
table call_signal,,trm_
table call_signal,,wkp_
undefp: table call_signal,,undefined_pointer
include mc
include stack_header
"
include audit_flags
include sdw
"
include history_regs_dps8
"
include history_regs_l68
end
fim_util.alm 08/11/83 1813.6r 08/11/83 1735.0 149139
" FIM_UTIL - Utility subroutines for the fim, wired_fim, and ii.
" consolidated 10/18/76 by Noel I. Morris
" Modified 1 Feb 79 by D. Spector for new scs format for 8-cpu cioc
" Modified 8/27/79 by J. A. Bush to reorganize the check_fault subroutine
" Modified 8/25/80 by J. A. Bush for the DPS8/70M CPU
" Modified 2/23/81 by J. Bongiovanni for fast connect code
" Modified 3/5/81 by J. Bongiovanni for OOSB on prds
" Modified 3/23/81 by J. A. Bush to dump extended APU history reg. for DPS8/70M.
" Modified 9/23/81 by J. A. Bush to not use QU mode when saving AMs
" Modified 10/28/81 by J. Bongiovanni for bug in check_fault
" Modified 2/8/82 by J. Bongiovanni to trap on masked in user ring (conditionally)
" Modified 02/16/82 by J. A. Bush to not trash mc.fault_reg for sys_trouble crash
" Modified 07/30/82 by J. Bongiovanni for scs$trouble_processid
" Modified 10/13/82 by E. N. Kittlitz to clear indicators in v_time_init.
" Modified sometime by B. I. Margulies for bootload multics.
" Modified 4/7/83 by E. N. Kittlitz for drl_fault_trouble.
name fim_util
segdef check_fault validate a fault
segdef check_interrupt validate an interrupt
segdef fault_trouble illegal fault condition
segdef drl_fault_trouble illegal fault, you say what it is
segdef copy_mc copy machine conditions
segdef push_stack push stack frame
segdef push_stack_32 push stack frame with grace area
segdef set_mask set controller mask to sys level
segdef restore_mask restore previous controller mask
segdef hist_regs save history regs and AMs
segdef force_hist_regs force save history regs and AMs
segdef check_mct check and trace machine conditions and hregs
segdef reset_mode_reg turn on hist reg and cache
segdef v_time_init start virtual time meter
segdef fim_v_time_init save virtual time for FIM
segdef v_time_calc stop virtual time meter
segdef fim_v_time_calc compute virtual time for FIM
link prds_link,prds$+0
inhibit on <+><+><+><+><+><+><+><+><+><+><+><+>
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" Procedure to check validity of faults and interrupts
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
check_fault:
ldaq pds$apt_ptr get pointer to our APT entry
cmpaq prds$idle_ptr are we in idle process?
tze idle_trouble if so, stop the entire system at once
szn wired_hardcore_data$trap_invalid_masked Are we trapping invalid sys_level
tze check_interrupt no
lxl1 prds$processor_tag
lprpab scs$mask_ptr,1
xec scs$read_mask,1
cmpaq scs$sys_level masked to system level
tnz check_interrupt no
lda bp|mc.scu.ppr.prr_word
cana scu.ppr.prr_mask,du in ring-0
tnz masked_in_user_ring no--bye-bye
lda bp|mc.scu.fault_data_word
cana scu.fd.ralr,du possibly RALR (must also be ACV)
tze check_interrupt no--let it slide
ana scu.fi_num_mask+scu.fi_flag_mask,dl
cmpa 2*FAULT_NO_ACV+1,dl is it an ACV
tnz check_interrupt no
masked_in_user_ring:
lca trbl_masked_user_ring,dl
tra check_fault_trouble
check_interrupt:
lda bp|mc.scu.ppr.prr_word check whether running in ring-0
cana scu.ppr.prr_mask,du ring number in ppr
tnz not_invalid not ring-0
eax7 0 nothing invalid yet
lda bp|mc.prs+6*2 1st word of stack pointer
ldq =o77777,dl mask to check seg-no and val. ring
cmk lp|prds_link is stack=prds and ring-0
tnz not_on_prds no
ldx7 -trbl_prds_fi,du fault on prds
lda bp|mc.scu.tpr.tsr_word now check for stack overflow
ldq =o777777,dl ring number, segment number in TSR
cmk lp|prds_link was target prds
tnz not_on_prds no
lda bp|mc.scu.fault_data_word stack overflow is OOSB
cana scu.fd.oosb,du is it possibly OOSB (must also be acv)
tze not_on_prds not at all
ana scu.fi_num_mask+scu.fi_flag_mask,dl check fault type
cmpa 2*FAULT_NO_ACV+1,dl fault/access violation
tnz not_on_prds no
lca trbl_oosb_prds,dl yes--oosb on prds (stack overflow)
tra check_fault_trouble ..
not_on_prds:
lda pds$processid do we have ptr locked
cmpa sst$ptl
tnz not_ptl_locked no
ldx7 -trbl_ptl_fi,du f/i with ptl locked
not_ptl_locked:
eaa 0,7 any invalid condition found
tze not_invalid no
ars 18 set up sys_trouble_pending
tra check_fault_trouble ..
not_invalid:
lca scu.ir.parm+1,dl turn OFF parity mask
ansa bp|mc.scu.indicators_word
tra 0,0 return to caller
idle_trouble:
lca trbl_idle_flt,dl fault while in idle process
tra check_fault_trouble ..
fault_trouble:
lca trbl_illeg_flt,dl unrecognized fault
tra check_fault_trouble
drl_fault_trouble:
lca trbl_r0_drl_flt,dl ring 0 derail
tra check_fault_trouble
check_fault_trouble:
sta scs$sys_trouble_pending set trouble flags
lda pds$processid save our process ID
stac scs$trouble_processid if we're the first
tsx1 save_fault_reg save fault reg and cpu type
lda sys_info$initialization_state Too early for connect?
cmpa =2,dl Multiprocessing?
tmoz sys_trouble$sys_trouble Go directly to jail ...
lxl1 prds$processor_tag prepare to send connect
cioc scs$cow_ptrs,1* ZAP
dis * cannot inhibit connects at a DIS
tra -1,ic STOP
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" COPY_MC - Procedure to copy machine conditions
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
copy_mc:
mlr (pr),(pr) copy machine conditions
desc9a bp|0,48*4
desc9a ap|0,48*4
eppbp ap|0 make bp -> copied conditions
tra 0,0 return to caller
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" PUSH_STACK - Procedure to create a stack frame
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
push_stack:
eppap sb|stack_header.stack_end_ptr,* ap -> place for frame
push_join:
sprisp ap|stack_frame.prev_sp save current sp
eppsp ap|0 set sp to new frame
eppap sp|0,7 ap -> end of frame
spriap sp|stack_frame.next_sp save next sp
spriap sb|stack_header.stack_end_ptr save end pointer
sprilp sp|stack_frame.lp_ptr save our linkage ptr
tra 0,0 return to caller
push_stack_32:
eppap sb|stack_header.stack_end_ptr,* ap -> place for frame
eppap ap|32 leave room for push in progress
tra push_join join common code
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" Procedures to save and restore controller masks
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
set_mask:
lxl1 prds$processor_tag processor tag in X1
lprpab scs$mask_ptr,1 get pointer for masking
xec scs$read_mask,1 read mask, if assigned
staq bp|mc.mask save it
lxl1 prds$processor_tag CPU tag in X1
lprpab scs$mask_ptr,1 get pointer for masking
ldaq scs$sys_level going to mask all interrupts
xec scs$set_mask,1 only if mask is assigned
tra 0,0
restore_mask:
lxl1 prds$processor_tag CPU tag in X1
lprpab scs$mask_ptr,1 get pointer for masking
ldaq bp|mc.mask get original mask
oraq channel_mask_set make sure channel mask is correct
anaq scs$open_level ..
xec scs$set_mask,1 restore the mask
tra 0,0 return to caller
even
channel_mask_set:
oct 17,17
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" Procedures to save history regs. Enter with bb -> place to store history regs.
" hist_regs - save history regs only if per-system
" (wired_hardcore_data$global_hregs) or per-process
" (pds$save_history_regs) flags are set.
" force_hist_regs - save history regs unconditionaly
"
" X4 is set with the cpu type (0 = L68/DPS, 1 = DPS8) by the
" save_fault_reg subroutine which is called by the check_mct subroutine
" which is called by all callers of this subroutine.
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
hist_regs:
szn wired_hardcore_data$global_hregs is global history reg save flag on?
tmi force_hist_regs xfer if yes
szn pds$save_history_regs no, is per_process hregs switch on?
tmi force_hist_regs xfer if yes
stz pds$hregs_saved no, zero switch for signaller
tra 0,0 and return to caller
force_hist_regs:
lda =o400000,du set hreg saved switch
sta pds$hregs_saved for signaller
tsx1 save_am go save associative memory
ldq 2,du get a 2 for stepping address
eax6 4 4 blocks of
scpr1: eax7 16 16 history registers
eax3 0 set up for L68 CPU type initally
cmpx4 1,du is this a DPS8/70M CPU?
tnz scpr2 xfer if no, it is L68
eax3 48 yes, set up to skip first 48 hregs
scpr2: lda scpr-1,6 get correct instruction
sta bp|mc.fim_temp save in stack
scpr3: xec bp|mc.fim_temp execute the instruction
cmpx3 0,du are we through skipping hregs?
tze scpr4 yes, go increment address
eax3 -1,3 no, skip another
tra scpr3 and go execute scpr again
scpr4: asq bp|mc.fim_temp increment address of instruction
eax7 -1,7 count down
tnz scpr3 more of this 16 double word block
eax6 -1,6 count down
tnz scpr1 another kind of hreg
eax7 64 initially set clear count to 64
cmpx4 1,du is this a DPS8/70M CPU?
tze *+2 yes, clear all 64 hregs
eax7 16 no, clear only 16 hregs
lcpr 0,03 set all history regs to zero
eax7 -1,7 count down
tpnz *-2 xfer if more to do
tra 0,0 return to caller
scpr: scpr bb|0,40 OU History Regs for L68, OU/DU for DPS8
scpr bb|32,20 CU History Regs
scpr bb|64,10 DU History Regs for L68, extended APU for DPS8
scpr bb|96,00 APU History Regs
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" Internal subroutine for saving fault register, extended fault
" register and CPU type (from RSW (2)), int the machine condition area.
" entry via tsx1 save_fault_reg. Exit with x4 containing the CPU type
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
save_fault_reg:
scpr bp|mc.fim_temp,01 store the fault register
ldaq bp|mc.fim_temp
sta bp|mc.fault_reg save M.S. 36 bits
rsw 2 get cpu type in a
arl 30 position in al
ana 3,dl
eax4 0,al save cpu type in x4
lrl mc.cpu_type_shift merge with ext. fault reg
stcq bp|mc.cpu_type_word,70 and save in M.C.
tra 0,1 return
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" Internal subroutine for saving associative memory in the prds
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
save_am:
eax3 4 4 instructions to execute
eax6 3 initialy set for DPS8 (4 sets of 16)
cmpx4 1,du is it a DPS8 CPU?
tze sam1 yes, go execute code
eax6 0 no, only 1 set for each type on L68
sam1: xec samt1-1,3 load LB with proper AM type
lda samt2-1,3 load instruction to execute in A
sta bp|mc.fim_temp and save
eax7 0,6 initialize counter
sam2: eaq 0,7 copy to qu
qls 4 multiply by 16
cmpx3 2,du is it for sdw_am_regs?
tnz *+2 xfwr if no
qls 1 yes, make it times 32
stcq bp|mc.fim_temp,30 set quad offset
xec bp|mc.fim_temp execute instruction
eax7 -1,7 count down
tpl sam2 do next set
eax3 -1,3 count down instructions to exucute
tnz sam1 go do next instuction set
tra 0,1 return to caller
samt1: epplb prds$sdw_am_ptrs
epplb prds$sdw_am_regs
epplb prds$ptw_am_ptrs
epplb prds$ptw_am_regs
samt2: ssdp lb|0
ssdr lb|0
sptp lb|0
sptr lb|0
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" Procedure to check if conditions are met for machine condition tracing
" if conditions are not true for machine condition tracing, return is ic +1 (tra 0,0)
" if conditions are met for machine condition tracing, then
" return is ic +2 (tra 1,0), bb -> place to pick up history regs and
" lb -> place to pick up machine conditions directly from machine condition trace buffer
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
check_mct:
tsx1 save_fault_reg save fault reg and get CPU type in x4
szn pds$mc_trace_sw is this process tracing machine conditions?
tpl 0,0 return to caller if no
szn pds$mc_trace_seg Does user want to trace all M. Cs?
tze cp_hregs xfer if seg number zero
lda bp|mc.scu.ppr.psr_word look at the psr
ana scu.ppr.psr_mask,du and out everything except psr
cmpa pds$mc_trace_seg compare psr to object we are tracing
tze cp_hregs xfer if psr = object we are tracing
lda bp|mc.scu.tpr.tsr_word look at tsr
ana scu.tpr.tsr_mask,du and out everthing except tsr
cmpa pds$mc_trace_seg compare tsr to object we are tracing
tnz 0,0 return to caller if psr or tsr don't have seg
cp_hregs:
lprplb pds$mc_trace_buf get packed ptr to wired trace buffer
stx0 lb|mctseg.x0save safe store return address
lxl5 lb|mctseg.hr_nxtad x5 = rel ptr to next H. R. storage location
cmpx5 lb|mctseg.hr_lim do we have to roll over the trace?
tmi hr_roll xfer if no
ldx5 lb|mctseg.hr_strt yes, pick up initial storage location
sxl5 lb|mctseg.hr_nxtad store new location
hr_roll:
eax5 mctseg.hr_size,5 increment storage location
sxl5 lb|mctseg.hr_nxtad set rel ptr to next H. R. storage location
eppbb lb|-mctseg.hr_size,5 bb -> current HR storage location
tsx0 force_hist_regs go save history regs in mc_trace buf
lprplb pds$mc_trace_buf get packed ptr to wired trace buffer
ldx0 lb|mctseg.x0save restore return address
lxl5 lb|mctseg.mc_nxtad x5 = rel ptr to next M. C. storage location
cmpx5 lb|mctseg.mc_lim do we have to roll over the trace?
tmi mc_roll xfer if no
ldx5 lb|mctseg.mc_strt yes, pick up initial storage location
sxl5 lb|mctseg.mc_nxtad store new location
mc_roll:
eax5 mctseg.mc_size,5 increment storage location
sxl5 lb|mctseg.mc_nxtad set rel ptr to next M. C. storage location
epplb lb|-mctseg.mc_size,5 lp -> current MC storage location
mlr (pr),(pr) move the data to wired buffer
desc9a bp|0,mctseg.mc_size*4
desc9a lb|0,mctseg.mc_size*4
tra 1,0 return to caller at ic +2
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" Procedure to reset mode registers to continue strobing
" data into the history registers.
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
reset_mode_reg:
epplb prds$cache_luf_reg point to cache/luf reg setting
lcpr lb|0,02 set cache enable and full luf time
lda prds$mode_reg retrieve template mode reg
ora mr.enable_mr+mr.enable_hist,dl enable mode reg and enable hist regs
sta prds$mode_reg_enabled save this mode reg value
epplb prds$mode_reg_enabled get pointer to temp mode reg value
lcpr lb|0,04 reload the mode register
tra 0,0 return to caller
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" Procedures to suspend virtual time metering
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
even
v_time_init:
tsx7 get_times get fault time and virtual time
aos pds$vtime_count step virtual time count
tpnz 0,0 if already set, don't meter
staq pds$time_v_temp save for later
ldi 0,dl clear indicators as a service to our caller
tra 0,0
odd
fim_v_time_init:
tsx7 get_times get times
szn pds$vtime_count metering already?
tpl 0,0 if so, return
staq pds$fim_v_temp save current virtual time
ldaq pds$virtual_delta save current delta
staq pds$fim_v_delta ..
ldi 0,dl clear indicators as a service to our caller
tra 0,0 and return to caller
even
get_times:
rccl sys_info$clock_,* read the clock
staq bp|mc.fault_time save time of fault/interrupt
sbaq pds$cpu_time compute virtual time
tra 0,7 return to caller
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" Procedures to reinstate virtual time metering
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
even
v_time_calc:
lca 1,dl decrement virtual time count
asa pds$vtime_count ..
tpl 0,0 if others, don't meter
v_calc_join:
rccl sys_info$clock_,* read the clock
adl 96,dl add in correction delta
sbaq pds$cpu_time get current value of CPU time
sbaq pds$time_v_temp get time we used
staq pds$time_v_temp save temporarily
adaq pds$virtual_delta compute virtual time increment
staq pds$virtual_delta and save
ldaq pds$time_v_temp time used in AQ again
adaq tc_data$delta_vcpu compute total vcpu time
staq tc_data$delta_vcpu ..
tra 0,0
even
fim_v_time_calc:
szn pds$vtime_count metering virtual time?
tpl 0,0 if not, just return
ldaq pds$virtual_delta get current virtual delta
sbaq pds$fim_v_delta subtract original delta
adaq pds$fim_v_temp correct FIM time
staq pds$time_v_temp store corrected time
tra v_calc_join join common code
"
include stack_frame
"
include stack_header
include mctseg
"
include sys_trouble_codes
include mode_reg
include mc
"
include fault_vector
end
iom_interrupt.alm 10/20/82 1323.9r w 10/20/82 1315.7 69345
" ******************************************************
" * *
" * *
" * Copyright (c) 1972 by Massachusetts Institute of *
" * Technology and Honeywell Information Systems, Inc. *
" * *
" * *
" ******************************************************
" iom_interrupt: IOM interrupt handler
" Stolen from iom_manager and ii November 1980 by C. Hornig
name iom_interrupt
segdef interrupt_entry " interrupt vector transfers here
segdef iilink " ITS ptr to linkage section
segdef prds_prs " ITS ptr to space for spri
segdef prds_scu " ITS ptr to space for SCU
tempd hlr_arglist(4) " argument list for interrupt handler
tempd time " time handler called
tempd imw_save " current IMW for scan
temp int_level " interrupt level for handler (1 3 5 7)
temp index " index for this channel
temp chantab_base " offset in chantab for this IOM
temp device " offset in per_device for this channel
temp chx " channel index from chantab
temp int_count " handlers called this time around
" Index register conventions:
" X0 - internal subroutine calls.
" X1 - index into devtab.
" X2 - index into mailbox.
" X3 - Used to index iomd.per_iom.
" X4 - interrupt cell #.
" X5 - interrupt level #.
" X6 - index in status queue
" Pointer Register Conventions:
" AP -> machine conditions
" AB -> inetrnal calls
" BP -> <iom_data>|0
" BB -> mailbox for this IOM.
" LP -> linkage section
" LB -> status queue
" These are initialized by initialize_faults
even
iilink: its -1,1 " our LP
prds_prs: its -1,1 " where to store PRs
prds_scu: its -1,1 " and CU info
three_args_nd:
zero 6,4
zero: zero 0
push_value:
push
chanpos: " table of chantab offsets
zero 0,0*4*per_iom_size+32
zero 0,1*4*per_iom_size+32
zero 0,2*4*per_iom_size+32
zero 0,3*4*per_iom_size+32
zero 0,0*4*per_iom_size
zero 0,1*4*per_iom_size
zero 0,2*4*per_iom_size
zero 0,3*4*per_iom_size
"
" This entry is transferred to by the interrupt vector.
" It is responsible for calling the interrupt handlers of various DIM's
" for which interrupts have been stored in the IMW array.
" It calls the interrupt routine as follows:
" call int_proc (idx, int_level, data_word)
" where int_level (1 3 5 7) corresponds to the level passed by the channel
" to the IOM and data_word in the system fault or special status word.
inhibit on <+><+><+><+><+><+><+><+><+><+><+><+><+>
interrupt_entry:
spri prds_prs-*,ic* " save pointer registers
eppbp prds_prs-*,ic* " ab -> machine conditions
sreg bp|mc.regs " save registers
lxl7 bp|mc.scu.indicators_word
canx7 scu.ir.mif,du " check for EIS
tze 2,ic " so we can save
spl bp|mc.eis_info " the pointers and lengths
epplp iilink-*,ic* " set up LP
tsx0 fim_util$v_time_init " meter virtual time
tsx0 fim_util$check_interrupt " make sure we're not not prds
tsx0 fim_util$check_mct " go save M.C.s and hregs
" if trace is on
nop " return ic +1
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" Establish a stack frame and mask interrupts.
"
epbpsb prds$ " use prds
ldx7 push_value-*,ic " get size of stack frame
tsx0 fim_util$push_stack " push the frame
tsx0 fim_util$set_mask " mask to sys level
inhibit off <-><-><-><-><-><-><-><-><-><-><-><->
tsx0 fim_util$reset_mode_reg
" turn on hist regs and cache
ldq bp|mc.scu.fault_data_word
anq scu.fi_num_mask,dl " get the interrupt number
qrl scu.fi_num_shift
eax4 0,ql " interrupt cell in X4
"
anq =7,dl " get base channel table position
lda chanpos,ql
sta chantab_base " save it for later
eaa 0,x4 " get interrupt cell
arl 18+2 " interrupt level in AL
ora =1,dl " always odd
sta int_level " save for handler
ldaq three_args_nd-*,ic " Build argument list for handler
staq hlr_arglist " call handler (index, int_level, ""b)
epplb index
sprilb hlr_arglist+2
epplb int_level
sprilb hlr_arglist+4
epplb zero-*,ic
sprilb hlr_arglist+6
"
" set up to search IMW area
"
eppbp iom_data$
stz int_count " no interrupts yet
ldac iom_mailbox$+iom_mailbox_seg.imw_array_word,x4
tze null_int-*,ic " no IMW bit set
ldq 0,du " make a fake float number
lde 0,du
lrl 1
tra imw_begin-*,ic " start scanning
" Scan the IMW for any bits on and process these interrupts.
imw_retry:
dfld imw_save " get back remaining bits
tze interrupt_return " no bits left
imw_begin:
ldi 0,dl " clear hex and overflow bits
fno
era =o200000,du " clear the bit
dfst imw_save
lda imw_save " get channel number
ars 36-8 " in AL
neg 0
ada chantab_base " add chantab offset
sta index " store in case of error
mrl (pr,al),(pr),fill(0) " Reference the channel table.
desc9a bp|iom_data.per_iom+per_iom.chantab_word,1
desc9a chx,4 " Word will be leading zero padded.
eppap hlr_arglist
ldq chx " chx in QL
tze invalid_int-*,ic " Ignore interrupt if channel not assigned.
mpy per_device_size,dl
eax1 -per_device_size,ql " index into per_device
lda bp|iom_data.per_device+per_device.flags,x1
" is there a handler?
cana per_device.in_use,du
tze invalid_int-*,ic " Return if no handler assigned.
lda bp|iom_data.per_device+per_device.index,x1
sta index " save the handler's index
stx1 device " save per_device index for ext. call
rccl sys_info$clock_,* " Get int_time now.
staq time " And save it.
short_call bp|iom_data.per_device+per_device.handler,x1*
" Call handler.
rccl sys_info$clock_,* " Get int_time again.
sbaq time " Compute delta.
eppbp iom_data$ " re-establish addressability
ldx1 device " restore per_device offset
adaq bp|iom_data.per_device+per_device.interrupt_time,x1
staq bp|iom_data.per_device+per_device.interrupt_time,x1
ldaq bp|iom_data.per_device+per_device.interrupts,x1
adl =1,dl " update meters
staq bp|iom_data.per_device+per_device.interrupts,x1
aos int_count " count interrupts
tra imw_retry-*,ic " find more interrupts
invalid_int:
aos bp|iom_data.invalid_interrupts
" meter unexpected interrupts
short_call iom_error$invalid_interrupt
" and tell the world
eppbp iom_data$ " re-establish addressability
tra imw_retry-*,ic " find more channels
"
null_int: " meter interrupts with null IMW
aos bp|iom_data.null_interrupts
interrupt_return:
lda int_count " meter multiple interrupts
cmpa =1,dl
tmoz 2,ic
aos bp|iom_data.multiple_interrupts
ldaq tc_data$interrupt_count
adl 1,dl " count interrupts
staq tc_data$interrupt_count
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" Relinquish stack frame and open interrupt mask.
"
eppbp prds_prs-*,ic* " restore MC ptr
tsx0 fim_util$restore_mask
inhibit on <+><+><+><+><+><+><+><+><+><+><+><+>
epbpsb sp|0 get ptr to base of stack
sprisp sb|stack_header.stack_end_ptr pop our stack frame
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" Perform interrupt metering and exit.
"
ldaq bp|mc.fault_time " get fault time
ana =o777777,dl " clear CPU type
staq prds$iitemp " save for now
rccl sys_info$clock_,* " read the clock
sbaq prds$iitemp " compute real time spent
adaq tc_data$interrupt_time " add in to total
staq tc_data$interrupt_time " ..
odd
tsx0 fim_util$v_time_calc " compute virtual time
lxl1 bp|mc.scu.indicators_word
canx1 scu.ir.mif,du " check for EIS if not don't reload pl
tze 2,ic
lpl bp|mc.eis_info restore pointers and lengths
lreg bp|mc.regs and registers
lpri prds_prs-*,ic* restore prs
rcu prds_scu-*,ic* and dismiss the interrupt
"
include iom_data
include mc
include stack_header
end
sys_trouble.alm 08/11/83 1813.6r 08/11/83 1735.0 111636
" ***********************************************************
" * *
" * Copyright, (C) Honeywell Information Systems Inc., 1982 *
" * *
" ***********************************************************
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" SYS_TROUBLE - Handle the system trouble connect
"
" The system may be in serious trouble when this code
" is entered. No stack frame is created and no calls
" are made. All other processors are stopped and
" the bootload processor returns to BOS. A return
" from BOS will cause all processors to be restarted.
" Machine conditions for the system trouble interrupt
" can be found at prds$sys_trouble_data.
"
" Coded by Roger R. Schell - September 23, 1969
" Recoded by Noel I. Morris - July 22, 1971
" Modified 1 Feb 79 by D. Spector for new scs format for 8-cpu cioc
" Modified by Noel I. Morris - February 8, 1976
" Modified for BOS messages by Noel I. Morris - May 5, 1977
" Modified 80 Sept 2 by Art Beattie - make it shutdown CPUs 4-7.
" Modified by J. A. Bush 10/06/80 for the DPS8/70M CPU
" Modified by J. Bongiovanni 3/4/81 for OOSB on prds
" Modified by J. Bongiovanni 2/24/82 for Masked in User Ring
" Modified by J. Bongiovanni 1/10/83 to ignore lockup faults absolutely
" Modified by E. N. Kittlitz 4/11/83 for ring-0 derail crash mechanism.
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
name sys_trouble
segdef sys_trouble
segdef ignore_data
" ******************************************************
" * *
" * *
" * Copyright (c) 1972 by Massachusetts Institute of *
" * Technology and Honeywell Information Systems, Inc. *
" * *
" * *
" ******************************************************
equ bos_xed_loc,4 absolute location for BOS entry
inhibit on <+><+><+><+><+><+><+><+><+><+><+><+>
use main
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" Before spinning waiting for console I/O to die, and before going to
" BOS, the fault vector for lockup is patched to do an SCU/RCU
" in absolute mode. This must be in absolute mode, in case the lockup
" happens in early BOS. The target of the SCU/RCU is in this program
" rather than prds$ignore_data, since the latter may not be in the
" low-order 256K.
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
eight
ignore_data:
bss ,8 " SCU data for SCU/RCU on lockup fault
ignore_scu_rcu:
scu 0 " Put into fault vector for lockup fault
rcu 0 " after absolute address inserted into Y-field
"
sys_trouble:
lda prds$processor_pattern get bit pattern for this CPU
cana scs$bos_restart_flags are we restarting this processor?
tnz restart if so, get it running again
" If this is the first processor to enter this code,
" a system trouble connect must be sent to all other
" processors to stop them too.
lda scs$processor get flags for all running CPU's
stac scs$trouble_flags are we the first processor?
tnz *+2 if not, skip broadcast
tsx0 broadcast broadcast system trouble connects to others
tsx0 fim_util$set_mask save mask and mask down
"
" Copy the machine conditions into prds$sys_trouble_data.
" This prevents overwriting the data when another
" system trouble interrupt is used to restart CPU's.
lda bp|mc.scu.fault_data_word get fault code
ana scu.fi_num_mask,dl mask fault code
arl scu.fi_num_shift right-justify
cmpa FAULT_NO_CON,dl connect fault?
tnz no_copy if not, conditions already in trouble_data
eppap prds$sys_trouble_data ap -> cache for machine conditions
tsx0 fim_util$copy_mc copy the machine conditions
no_copy:
eppbb pds$history_reg_data bb -> place to store history regs
tsx0 fim_util$check_mct go copy cpu type into machine conditions
tsx0 fim_util$force_hist_regs save the history registers in pds
lda prds$processor_tag CPU tag in A
als 1 multiply by 2
sdbr scs$trouble_dbrs,al save DBR for debugging
" If this is the bootload CPU, enter BOS.
" Otherwise, die gracefully.
lca 1,dl all one's in A
era prds$processor_pattern CPU pattern mask in A
ansa scs$processor indicate that this CPU is stopped
lda prds$processor_tag processor tag in A
cmpa scs$bos_processor_tag is this the bootload CPU?
tze enter_bos if so, go to BOS
die:
dis -1,du stop
tra *-1 I said stop!
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" The second trouble connect for restarting processors
" causes control to be transferred here.
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
restart:
lda prds$processor_pattern get bit for this processor
orsa scs$processor indicate CPU is running again
era =-1 complement to make a mask
ansa scs$bos_restart_flags indicate processor has been restarted
ansa scs$sys_trouble_pending turn off trouble flag for this processor
eppbp wired_fim$trouble_prs,* bp -> system trouble m.c. area
tsx0 fim_util$restore_mask restore original controller mask
szn scs$faults_initialized see if system ready for cache
tze trouble_exit transfer if not
tsx0 fim_util$reset_mode_reg restore mode and cache mode regs
odd
trouble_exit:
tsx0 fim_util$v_time_calc start virtual time meters again
lpl bp|mc.eis_info restore ptrs and lgths
lreg bp|mc.regs and regs
lpri bp|mc.prs and prs
rcu wired_fim$trouble_scuinfo,* get running again
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" The following code copies an error message into the BOS
" flagbox message buffer.
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
enter_bos:
lda scs$sys_trouble_pending get flags
als 18 extract low-order
ars 18 could be negative number
neg 0 or zero
tze rtb_no_message if zero, no message
eppbb flagbox$ bb -> BOS flagbox
mlr (),(pr) copy program ID
desc9a sys_trouble_name,13
desc9a bb|fgbx.message,13
mlr (id),(pr),fill(040) copy error message
arg trouble_messages-1,al
desc9a bb|fgbx.message+3(1),64-13
cmpa trbl_r0_drl_flt,dl is it a ring-0 derail?
tnz non_drl nope, that's all
szn scs$drl_message_pointer augment the message
tze non_drl nothing to say
lprplb scs$drl_message_pointer
lda lb|0 acc length in upper 9
arl 27 lower 9, now
mlr (pr,rl),(pr),fill(040) Your life story in 32 characters.
desc9a lb|0(1),al
desc9a bb|fgbx.message+8,64-32
non_drl: ldq fgbx.mess+fgbx.alert,du set flags for message printing
orsq bb|fgbx.rtb ..
tra rtb_no_message no, go back to BOS
sys_trouble_name:
aci "sys_trouble: "
"
macro message
desc9a &U,&l1
maclist off,save
use message
maclist restore
&U:
aci "&1"
maclist off,save
use main
maclist restore
&end
trouble_messages:
message (Page fault while on prds.)
message (Fault/interrupt while on prds.)
message (Fault in idle process.)
message (Fault/interrupt with ptl set.)
message (Unrecognized fault.)
message (Unexpected fault.)
message (Execute fault by operator.)
message (Out-of-Segment-Bounds on prds.)
message (Interrupts Masked in User Ring.)
message (Fault in bound_interceptors.)
message (Ring 0 derail.)
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" The following code enters BOS by placing the two
" absolute mode instructions needed to enter BOS
" into the fault vector slot for the derail fault.
" NOTE: bp must be preserved across call to BOS since
" we use it to restore pointer registers upon return.
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
rtb_no_message:
eppbb fault_vector$+0 bb -> fault vector segment
ldaq bb|2*FAULT_NO_LUF+fv.fpair
staq lp|save_lockup_fault save SCU/TRA
absa ignore_data abs addr in 0-23
als 6 abs addr in 0-17 of Areg
eaq 0,au abs addr in 0-17 of Qreg
oraq ignore_scu_rcu replace lockup fault vector
staq bb|2*FAULT_NO_LUF+fv.fpair
szn scs$processor all CPU's stopped?
tnz *-1 if not, wait here
lda 4,du wait for operator's console output to finish
odd
sba 1,dl to allow I/O to drain off
tnz *-1 ..
ldaq bb|2*FAULT_NO_DRL+fv.fpair grab SCU-TRA pair from fault vector
staq lp|save_derail_fault
ldaq bos_toehold$+bos_xed_loc pick up code to enter BOS
staq bb|2*FAULT_NO_DRL+fv.fpair set it in fault vector
drl: drl 0 ****** BOS is entered here ******
szn scs$connect_lock did we enter through pmut call?
tze drl if not, cannot restart
ldac scs$trouble_flags get and clear trouble flags
sta scs$bos_restart_flags set for restarting CPU's
ldaq lp|save_derail_fault
staq bb|2*FAULT_NO_DRL+fv.fpair ..
ldaq lp|save_lockup_fault restore lockup faults
staq bb|2*FAULT_NO_LUF+fv.fpair ..
tsx0 broadcast send trouble connects to start CPU's
tra restart restart the bootload CPU
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" BROADCAST - Send system trouble connects to all other
" processors.
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
broadcast:
ldq hbound_processor_data,dl initialize the Q with maximum configurable CPUs
broadcast_loop:
cmpq prds$processor_tag test for ourselves
tze broadcast_next don't hit ourselves
lda scs$processor_data,ql get processor data for this CPU
cana processor_data.online,du is it configured?
tze broadcast_next if not, don't hit it
cioc scs$cow_ptrs,ql* Zap
broadcast_next:
sbq 1,dl step to next CPU
tpl broadcast_loop if more, get the others
tra 0,0 return to caller
"
use internal_static
join /link/internal_static
even
save_lockup_fault:
bss ,2 place to save lockup fault SCU and TRA
save_derail_fault:
bss ,2 place to save derail fault SCU and TRA
include mc
"
include scs
include fgbx
include sys_trouble_codes
include fault_vector
"
" BEGIN MESSAGE DOCUMENTATION
"
" Message:
" sys_trouble: Page fault while on prds.
"
" S: $crash
"
" T: $run
"
" M: $err
"
" A: $recov
"
"
" Message:
" sys_trouble: Fault/interrupt while on prds.
"
" S: $crash
"
" T: $run
"
" M: $err
"
" A: $recov
"
"
" Message:
" sys_trouble: Fault in idle process.
"
" S: $crash
"
" T: $run
"
" M: $err
"
" A: $recov
"
"
" Message:
" sys_trouble: Fault/interrupt with ptl set.
"
" S: $crash
"
" T: $run
"
" M: $err
"
" A: $recov
"
"
" Message:
" sys_trouble: Unrecognized fault.
"
" S: $crash
"
" T: $run
"
" M: Unexpected or unrecognized fault subcondition.
" Probable hardware malfunction.
"
" A: $contact
"
"
" Message:
" sys_trouble: Unexpected fault.
"
" S: $crash
"
" T: $init
"
" M: $err
"
" A: $recov
"
"
" Message:
" sys_trouble: Execute fault by operator.
"
" S: $crash
"
" T: $run
"
" M: Operator depressed execute pushbutton on processor.
"
" A: $recov
"
"
" Message:
" sys_trouble: Out-of-Segment-Bounds on prds.
"
" S: $crash
"
" T: $run
"
" M: While running with the prds as a stack, an attempt was
" made to reference beyond the end of the prds. The likely
" cause was stack overflow, due either to a recursive loop
" in the procedures running on the prds or insufficient
" space allocated for the prds. If the latter, the size of
" the prds should be increased by means of the TBLS Configuration
" Card.
"
" A: $recover
"
"
" Message:
" sys_trouble: Interrupts Masked in User Ring.
"
" S: $crash
"
" T: $run
"
" M: During processing of a fault, it was noticed that interrupts
" were masked in user-ring, an invalid condition. This is a
" debug trap crash, enabled by the hidden tuning parameter
" trap_invalid_masked.
"
" A: Contact the Multics System Development staff.
"
"
" Message:
" sys_trouble: Fault in bound_interceptors.
"
" S: $crash
"
" T: $run
"
" M: A fault occured while handling another fault.
"
" A: $recov
"
"
" Message:
" sys_trouble: Ring 0 derail. {MESSAGE}
"
" S: $crash
"
" T: $run
"
" M: A supervisor software module discovered an untenable situation, and
" crashed the system by executing a derail (DRL) instruction.
" If MESSAGE is also present, it will be of the form:
" "module: explanation", and further details can be found in
" this documentation in the description of "module".
"
" A: $recov
"
" END MESSAGE DOCUMENTATION
end
wired_fim.alm 09/09/82 1508.6rew 09/09/82 1503.4 121842
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" wired_fim
"
" Last Modified: (Date and Reason)
" Written 1/70 S.Webber
" Modified by S.Webber 01/01/72 for followon
" Modified by S.Webber 10/15/73 to add SPL/LPL code for all faults
" Modified by S.Webber 12/18/73 to remove page fault code
" Modified by Noel I. Morris 2/11/76 for new connect faults
" Modified by Mike Grady 6/79 to do stop on prds
" Modified by J. A. Bush 3/80 to store execute fault time in machine conditions
" Modified by J. Bongiovanni 1/81 for fault_counters
" Modified by J. Bongiovanni 2/81 for fast connect code,
" traffic control race condition
" Modified by J. A. Bush 6/3/81 to save fault time for unexpected faults
" Modified by J. Bongiovanni 1/05/82 to fix CPU start wait bug
"
" The following entries exist within this procedure:
"
" connect_handler handles inter-processor communication
"
" pre_empt_return return from pxss after pre-empt
"
" ignore certain faults are ignored here
"
" timer_runout timer runout faults are mapped into
" pre-empts
"
" unexp_fault unexpected faults come here during
" system initialization
"
" xec_fault execute faults will cause return to BOS
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
name wired_fim
" ******************************************************
" * *
" * *
" * Copyright (c) 1972 by Massachusetts Institute of *
" * Technology and Honeywell Information Systems, Inc. *
" * *
" * *
" ******************************************************
"
include pxss_page_stack
"
segdef prs,scuinfo
segdef int_scuinfo
segdef trouble_prs,trouble_scuinfo
segdef ignore_scuinfo
segdef my_linkage_ptr
segdef pre_empt_return
segdef ignore
segdef timer_runout
segdef connect_handler
segdef unexp_fault
segdef xec_fault
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" The following variables are set up during initialization.
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
even
prs: bss ,2
scuinfo: bss ,2
int_scuinfo:
bss ,2
trouble_prs:
bss ,2
trouble_scuinfo:
bss ,2
ignore_scuinfo:
bss ,2
my_linkage_ptr:
bss ,2
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" CONNECT_HANDLER -- Handle Connect Faults.
"
" Connect faults may be sent for the following reasons:
" 1. To cause a system trouble abort.
" 2. To clear cache and associative memory.
" (the clearing has already been done by
" prds$fast_connect_code by the time we get here)
" 3. To wait for a new CPU to start up.
" 4. To cause a processor to delete itself.
" 5. To cause a process pre-empt.
" 6. To cause a process stop.
" 7. To cause an IPS event to be signalled.
"
"
" By the time this entry has been called, the fast connect
" in the prds has been called. This code has done the
" following:
"
" 1. If scs$fast_cam_pending was set for this cpu,
" xed scs$cam_pair
" stz scs$fast_cam_pending + <processor tag>
" 2. Added 1 to the counter
" wired_hardcore_data$fault_counters + <FAULT_NO_CON>
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
inhibit on <+><+><+><+><+><+><+><+><+><+><+><+>
even
connect_handler:
spri prs,* save prs
eppbp prs,* bp -> place for machine conditions
sreg bp|mc.regs save regs
spl bp|mc.eis_info save EIS ptrs and lgths
epplp my_linkage_ptr,* set up linkage ptr
tsx0 fim_util$v_time_init start virtual time metering
lda scs$sys_trouble_pending system trouble?
cana prds$processor_pattern for this CPU?
tnz sys_trouble$sys_trouble go handle it
tsx0 fim_util$check_mct go save M.C.s and hregs if trace is on
nop " return ic +1
tsx0 fim_util$reset_mode_reg start up hist regs again
lda prds$processor_pattern see if we're waiting for
cana scs$cam_wait for all cams to clear
tnz cam_wait yes--go do it
cana scs$processor_start_wait waiting for CPU to start up?
tnz start_wait if so, go wait
lxl1 prds$processor_tag CPU tag in X1
lda scs$processor_data,1 look at CPU flags
cana processor_data.delete_cpu,du is this CPU to delete itself?
tnz delete_cpu if so, cause a pre-emption
more: epplb pds$apt_ptr,* lb -> APT entry for this process
lda lb|apte.flags look at process flags
cana apte.stop_pending,du stop?
tnz stop go handle stop
cana apte.pre_empt_pending,du pre-empt?
tnz pre_empt go handle pre-empt
lda lb|apte.ips_message IPS message?
tnz ips go handle IPS
tra exit drop through to exit
"
ralr_set_1:
lda 1,dl cannot handle fault now
sta pds$alarm_ring defer it until later
odd
exit:
tsx0 fim_util$v_time_calc calculate virtual time
exit_1:
lpl bp|mc.eis_info restore EIS ptrs and lths
lra pds$alarm_ring FIM may have reset this
lreg bp|mc.regs restore regs
lpri bp|mc.prs and prs
rcu scuinfo,* good-bye
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" IGNORE -- several faults are ignored by directing them
" to this entry.
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
ignore:
rcu ignore_scuinfo,* restore the machine conditions
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" XEC_FAULT and UNEXP_FAULT -- These entries cause
" the system to abort.
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
xec_fault:
spri trouble_prs,* save prs
eppbp trouble_prs,* bp -> machine conditions
sreg bp|mc.regs save regs
spl bp|mc.eis_info save EIS ptrs and lths
epplp my_linkage_ptr,* establish linkage ptr
rccl sys_info$clock_,* read the clock
staq bp|mc.fault_time and save in machine conditions
lca trbl_exec_flt,dl set sys trouble indicator
sta scs$sys_trouble_pending ..
lda pds$processid save our process ID
stac scs$trouble_processid if we're the first
tra sys_trouble$sys_trouble map into sys_trouble code
unexp_fault:
spri trouble_prs,* save prs
eppbp trouble_prs,* bp -> machine conditions
sreg bp|mc.regs save regs
spl bp|mc.eis_info save EIS ptrs and lths
epplp my_linkage_ptr,* establish linkage ptr
rccl sys_info$clock_,* read the clock
staq bp|mc.fault_time and save in machine conditions
lca trbl_unexp_flt,dl set sys trouble indicator
sta scs$sys_trouble_pending ..
lda pds$processid save our process ID
stac scs$trouble_processid if we're the first
tra sys_trouble$sys_trouble map into sys_trouble code
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" TIMER_RUNOUT - Timer runouts are mapped into pre-empts.
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
even
timer_runout:
spri prs,* save prs
eppbp prs,* bp -> machine conditions
sreg bp|mc.regs save regs
spl bp|mc.eis_info save EIS ptrs and lths
epplp my_linkage_ptr,* establish linkage ptr
tsx0 fim_util$v_time_init start virtual time meter
tsx0 fim_util$check_mct go save M.Cs ad hregs if trace is on
nop " return ic +1
tsx0 fim_util$reset_mode_reg start up hist regs
aos wired_hardcore_data$fault_counters+FAULT_NO_TRO
cause_pre_empt:
epplb pds$apt_ptr,* lb -> APT entry for this process
ldx0 apte.pre_empt_pending,du get pre-empt indicator flag
orsx0 lb|apte.flags set pre-empt flag
tra pre_empt join common code
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" DELETE_CPU - Cause a pre-empt to stop CPU.
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
delete_cpu:
lca 1,dl all ones in A
era prds$processor_pattern get bit for CPU to be deleted
ansa scs$connect_lock undo the connect lock
tra cause_pre_empt now, cause a pre-empt to take place
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" CAM_WAIT -- Wait for all cpus to clear, and originator to
" give "Go"
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
cam_wait:
eppsb prds$ push a frame onto the prds
ldx7 push ..
tsx0 fim_util$push_stack_32 ..
eppap notify_regs ap -> place to copy conditions
tsx0 fim_util$copy_mc copy the conditions into stack
tsx0 fim_util$set_mask must uninhibit to prevent lockup
inhibit off <-><-><-><-><-><-><-><-><-><-><-><->
lda prds$processor_pattern get bit for this CPU
cana scs$cam_wait still waiting?
tze *+4 if not, exit loop
llr 72
llr 72
tra *-4 if so, wait more
tsx0 fim_util$restore_mask can inhibit again
inhibit on <+><+><+><+><+><+><+><+><+><+><+><+>
cams 0 now, clear A.M.'s
camp 0 ..
eppap prs,* prepare to copy machine conditions back
tsx0 fim_util$copy_mc ..
eppap sp|-32 get original stack end pointer
spriap sb|stack_header.stack_end_ptr pop our stack frame
tra more and leave
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" START_WAIT - Wait until new CPU has started up.
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
start_wait:
lca 1,dl all ones in A
era prds$processor_pattern turn off bit for this CPU
ansa scs$processor_start_wait check ourselves off
eppsb prds$ push a frame onto the prds
ldx7 push ..
tsx0 fim_util$push_stack_32 ..
eppap notify_regs ap -> place to copy conditions
tsx0 fim_util$copy_mc copy the conditions into stack
tsx0 fim_util$set_mask uninhibit to prevent lockups
inhibit off <-><-><-><-><-><-><-><-><-><-><-><->
szn scs$connect_lock test connect lock
tze *+4 wait until it is cleared
llr 72
llr 72
tra *-4
tsx0 fim_util$restore_mask can inhibit again
inhibit on <+><+><+><+><+><+><+><+><+><+><+><+>
eppap prs,* prepare to copy machine conditions back
tsx0 fim_util$copy_mc ..
eppap sp|-32 get original stack end pointer
spriap sb|stack_header.stack_end_ptr pop our stack frame
tra exit all finished waiting
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" PRE_EMPT - Handle process pre-emptions.
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
pre_empt:
tsx0 ring_test ring 0 & not idle?
tra ralr_set_1 if so, delay this for later
eppap pds$page_fault_data copy machine conditions
tsx0 fim_util$copy_mc ..
tsx0 fim_util$set_mask mask system controller
eppsb prds$ establish stack frame on the prds
ldx7 push ..
tsx0 fim_util$push_stack ..
inhibit off <-><-><-><-><-><-><-><-><-><-><-><->
tra pxss$pre_empt go to pxss
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" PRE_EMPT_RETURN -- Transferred to when pre_empt has been processed
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
pre_empt_return:
epplp my_linkage_ptr,*
eppbp pds$page_fault_data get pointer to machine conditions
tsx0 fim_util$restore_mask restore old controller mask
inhibit on <+><+><+><+><+><+><+><+><+><+><+><+>
ldaq sb|stack_header.stack_begin_ptr restore prds to virgin state
staq sb|stack_header.stack_end_ptr ..
odd
tsx0 fim_util$v_time_calc compute virtual time
lpl bp|mc.eis_info restore EIS ptrs and lths
lreg bp|mc.regs restore regs
lpri bp|mc.prs and prs
rcu int_scuinfo,* bye-bye
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" STOP - Handle process stop
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
stop:
tsx0 ring_test ring 0 & not idle?
tra ralr_set_1 if so, delay handling this
eppap pds$page_fault_data copy machine conditions
tsx0 fim_util$copy_mc ..
tsx0 fim_util$set_mask mask system controller
eppsb prds$ Establish stack on prds
ldx7 push ..
tsx0 fim_util$push_stack ..
inhibit off <-><-><-><-><-><-><-><-><-><-><-><->
tra pxss$force_stop go to pxss
inhibit on <+><+><+><+><+><+><+><+><+><+><+><+>
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" IPS - Handle Interprocess Signals
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
ips:
tsx0 ring_test ring 0 & not idle?
tra ralr_set_1 we'll hear about this later
eppap pds$signal_data copy the machine conditions
tsx0 fim_util$copy_mc ..
eppsb pds$stack_0_ptr,* Establish pageable stack.
ldx7 push ..
tsx0 fim_util$push_stack ..
tsx0 fim_util$v_time_calc compute virtual time
inhibit off <-><-><-><-><-><-><-><-><-><-><-><->
call proc_int_handler$proc_int_handler
inhibit on <+><+><+><+><+><+><+><+><+><+><+><+>
eppap prs,* copy SCU data only back
mlr (pr),(pr) ..
desc9a bp|mc.scu,8*4
desc9a ap|mc.scu,8*4
sprisp sb|stack_header.stack_end_ptr release our stack frame
tra exit_1 all finished
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
"
" RING_TEST - internal subroutine to see if process
" is in ring 0 and not an idle process
"
"
" " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
ring_test:
lda bp|mc.scu.ppr.prr_word get PRR
ana scu.ppr.prr_mask,du ..
tnz 1,0 if outer ring, take second return
lda lb|apte.flags get process flags
cana apte.idle,du idle process?
tze 0,0 if not, take first return
epaq sp|0 get stack pointer in AQ
eax7 0,au stack segno in X7
cmpx7 trouble_scuinfo is it prds?
tze 0,0 if so, go away
tra 1,0 if not, take second return
"
push: push
include mc
"
include stack_header
"
include scs
include sys_trouble_codes
"
include apte
"
include fault_vector
end
"This material is presented to ensure dissemination of scholarly and technical work. Copyright and all rights therein are retained by authors or by other copyright holders. All persons copying this information are expected to adhere to the terms and constraints invoked by each author's copyright. In most cases, these works may not be reposted without the explicit permission of the copyright holder."