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."