absadr.alm 11/11/89 1106.2rew 11/11/89 0803.8 28269 " *********************************************************** " * * " * Copyright, (C) Honeywell Bull Inc., 1987 * " * * " * Copyright, (C) Honeywell Information Systems Inc., 1982 * " * * " * Copyright (c) 1972 by Massachusetts Institute of * " * Technology and Honeywell Information Systems, Inc. * " * * " *********************************************************** " ABSADR - Compute Absolute Address from ITS Pair. " Written 06/02/67 - Noel I. Morris " Other modifications made through the years by various Multicians who " curiously prefer the cloak of anonymity. " Modified 03/21/81, W. Olin Sibert, for ADP conversion " Calling Sequence: " absolute_address = absadr (pointer, error) " " Where: " pointer - its pointer. " absolute_address - answer as fixed bin (24) integer. " error - error code. " " Errors: " 1. Bound fault. " 2. Directed Fault in SDW. " 3. Directed Fault in PTW. " name absadr entry absadr tempd sdw_save,temp temp word_offset,temp1 include sdw include ptw " absadr: push eppbp ap|2,* pick up pointer to its pair epaq bp|0,* get info into aq-reg anq -1,du stq word_offset save word offset of effective pointer ana -1,du als 1 * 2 eax0 0,au seg no * 2 to X0 epaq abs_seg$+0 als 1 eax1 0,au ldaq dseg$+0,x1 pick up previous SDW for absolute segment staq sdw_save and stash it away ldaq dseg$+0,x0 pick up SDW for segment staq temp save it cana sdw.valid,dl test for directed fault tze error_2 .. qrl sdw.bound_shift " Check against the SDW bound anq sdw.bound_mask,dl qls 18+4 " Convert to word count in QU adlq =o17,du " And add 15 to get word count cmpq word_offset compare against word offset tnc error_1 test for bound fault ldaq temp restore SDW to AQ canq sdw.unpaged,dl paged ? tnz addr no lda word_offset get address arl 10 take address mod (page size - 1024) eax6 0,au put page number in x6 lda temp get page table addr from sdw als 18-sdw.add_shift right justify it in au ana =o17,du find its offset from a 0 mod 16 word addr sta temp1 save this number a bit adx6 temp1 x6 now has addr of desired page table word " as an offset from a 0 mod 16 boundary ldaq temp ana =o777777607777 make address field 0 mod 16 for unpaged sdw orq sdw.unpaged,dl make it unpaged staq dseg$+0,x1 store in SDW for absolute segment cams 0 clear assoc. memory lda abs_seg$+0,x6 pick up PTW cana ptw.valid,dl test for directed fault tze error_3 .. addr: absa bp|0,* generate absolute address arl 12 sta ap|6,* return absolute address ldq 0,dl make error code zero end: stq ap|4,* return error code ldaq sdw_save restore previous SDW staq dseg$+0,x1 .. cams 0 reset associative memory return error_1: ldq 1,dl bound fault tra end .. error_2: ldq 2,dl directed fault in SDW tra end .. error_3: ldq 3,dl directed fault in PTW tra end .. end  parity_check.alm 11/11/89 1106.2r 11/11/89 0803.8 18081 " *********************************************************** " * * " * Copyright, (C) Honeywell Bull Inc., 1987 * " * * " * Copyright, (C) Honeywell Information Systems Inc., 1982 * " * * " * Copyright (c) 1972 by Massachusetts Institute of * " * Technology and Honeywell Information Systems, Inc. * " * * " *********************************************************** name parity_check entry parity_check entry set_parity_mask entry reset_parity_mask " Last Modified by RBSnyder 02/14/73 for follow-on " " call parity_check(loc, word, check) " " loc pointer pointer to parity cell " word bit(36) contents of cell indicating parity " check fixed bin = 0 if no parity " " " This routine is called to validate the existence of a parity error " by re-accessing the word in question. " It is used by the software to verify that the " condition was in fact a memory parity error. " " " " " call set_parity_mask " " This entry is used to set the parity mask indicator in " the caller's indicators. " " " call reset_parity_mask " " This entry is the reverse of the one above " include mc " parity_check: ldi scu.ir.parm,dl Set mask eppbp ap|2,* Pick up pointer to cell lda bp|0,* Read from cell sta ap|4,* Return contents sti ap|6,* Store indicators into return arg lda scu.ir.par,dl Pick up mask ansa ap|6,* If error occured, will be non-zero short_return set_parity_mask: sti sp|0 store the current indicators lda scu.ir.parm,dl Pick up masking bit orsa sp|0 store into stored indicators ldi sp|0 reload indicators short_return reset_parity_mask: sti sp|0 save current indicators lca scu.ir.parm+1,dl Form 1-s complement of mask ansa sp|0 and delete the bit ldi sp|0 get new indicators short_return end parity_check  privileged_mode_ut.alm 11/11/89 1106.2rew 11/11/89 0804.2 304461 " *********************************************************** " * * " * Copyright, (C) Honeywell Bull Inc., 1987 * " * * " * Copyright, (C) Honeywell Information Systems Inc., 1984 * " * * " * Copyright (c) 1972 by Massachusetts Institute of * " * Technology and Honeywell Information Systems, Inc. * " * * " *********************************************************** " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " privileged_mode_ut " " This segment contains master mode utility routines " required by hardcore ring procedures in order to execute " 6180 instructions which can only be executed in " privileged mode. " " Revised for New File System 1/69 SHW " " Converted for the follow-on by Craig Jensen on 6/27/72. " Code for 6180 cache added 2/74 by B. Greenberg " Modified 4/8/74 by S.H.Webber to remove checks and change lockptl meter code " Lock PTL code and cam code moved to page, 6/19/74 BSG " Modified on 01/06/75 at 21:57:15 by R F Mabee. Fixed SDW alignment assumptions. " Modified 6/16/75 by R.F.Mabee. Fixed parity_error reporting bug per BSG. " Modified 2/18/76 by S. Webber for new reconfiguration " Modified 7/18/78 by J. A. Bush for new smic_port entry " Modified 5/11/79 by Mike Grady for stack 0 sharing. " Modified 3/11/80 by Mike Grady to make mask restores more robust. " Modified 5/30/80 by J. A. Bush to wire (and unwire) number of pages " in wired_hardcore_data$wire_pages " Modified 1/08/81 by J. Bongiovanni to account for wired pages " Modified 2/10/81 by J. A. Bush for the read_id_prom entry " Modified 1/05/82 by J. Bongiovanni to make check_parity_for_use " faster " Modified 2/8/82 by J. Bongiovanni to set ralr to 1 on mask to " sys_level (optionally), add entry read_mask " Modified 6/23/82 by J. A. Bush to add the clear_cache entry " Modified 7/82 BIM to merge in ldt and ldbr from privileged_mode_init. " for the 10 instructions here that program could be deleted. " Modified 8/82 JJB for scs footprints to identify crash process. " Modified 1/83 JJB to set lockup fault vector to ignore faults absolutely " Modified 6/83 ENK for load_mode_reg " Modified 8/83 KPL for bootload Multics shutdown, also for camp entry " Modified 10/83 KPL for checking sst_boundary for unpaged " Modified 1/84 KPL for special_bce_return " Modified 5/84 KPL for cam_both " Modified 1985-03-11, BIM: clear mem before checking for freecore " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " HISTORY COMMENTS: " 1) change(88-07-27,Farley), approve(88-10-05,MCR7968), " audit(88-10-10,Beattie), install(88-10-14,MR12.2-1166): " Added new entry check_for_mem_overlap to check for memory addressing " overlap conditions, which cannot be detected by simply reading the SCU " configuration. " END HISTORY COMMENTS name privileged_mode_ut entry bce entry bce_and_return entry cam entry cam_both entry cam_cache entry clear_cache entry check_for_mem_overlap entry check_parity_for_use,check_parity_for_add entry cioc entry ldt entry ldbr entry load_mode_reg entry lock_ptl entry lrar entry read_id_prom entry read_mask entry rscr entry rsw entry set_mask entry smcm entry smic entry smic_port entry special_bce_return entry sscr entry swap_sdw entry camp entry trace_rsw entry unlock_ptl entry unwire_unmask entry wire_and_mask even channel_mask_set: " used to retain current channel mask oct 000000000017,000000000017 temp8 rip_str1,rip_str2 tempd maskd,save_sdw,save_sdw1 temp old_low_data,new_low_data,old_high_data,new_high_data temp indicators,save_indicators,new_value,addr,indicators_no_par,call_type temp lock_sw,temp,rsw_xec,tally_wd " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " read_mask is used to obtain the current value of the interrupt " mask on the running CPU " " The calling sequence is " " call privileged_mode_ut$read_mask (mask_pattern) " " where mask_pattern is a fixed bin (71) value " into which will be stored the value of the " interrupt mask " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " read_mask: inhibit on <+><+><+><+><+><+><+><+><+><+><+><+> lxl1 prds$processor_tag lprpab scs$mask_ptr,1 xec scs$read_mask,1 inhibit off <-><-><-><-><-><-><-><-><-><-><-><-> staq ap|2,* short_return " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " set_mask is called from the interrupt interceptor. " " The calling sequence is: " " call privileged_mode_ut$set_mask(mask_pattern,temp) " " where mask_pattern is a fixed bin (71) value which " will be loaded into the mask register of the system " controller assigned to send interrupts to the " processor on which this procedure is executing, " " and temp is a fixed bin (71) item which the mask register " at the time of entry will be loaded into. " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " set_mask: push " Note that the processor may be lost between reading and setting the mask. inhibit on <+><+><+><+><+><+><+><+><+><+><+><+> lxl1 prds$processor_tag lprpab scs$mask_ptr,1 xec scs$read_mask,1 read mask staq maskd save temporarily ldaq ap|2,* get new mask oraq channel_mask_set forget old channel mask anaq scs$open_level correct mask lxl1 prds$processor_tag lprpab scs$mask_ptr,1 xec scs$set_mask,1 set new mask inhibit off <-><-><-><-><-><-><-><-><-><-><-><-> szn wired_hardcore_data$trap_invalid_masked are we checking mask tze not_sys_level no cmpaq scs$sys_level masking to system level tnz not_sys_level no lda 1,dl set ring alarm sta pds$alarm_ring lra pds$alarm_ring not_sys_level: ldaq maskd get old mask ldx7 ap|0 get arg count cmpx7 2*2,du two args? tmi *+2 if not, don't return old mask staq ap|4,* return old mask return " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " lock_ptl used to lock page table lock and mask. " Call is: " " call privileged_mode_ut$lock_ptl(oldmask,ptwp) " " dcl oldmask fixed bin (71) " dcl ptwp ptr " " wire_and_mask used to wire stack and mask " same calling seq as lock_ptl " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " link sst_link,sst$ link abs_seg_link,abs_seg$ link abs_seg_link1,abs_seg1$ link prds_link,prds$ wire_and_mask: eax2 0 set sw not to lock tra lptl1 lock_ptl: eax2 1 set sw to lock lptl1: inhibit on <+><+><+><+><+><+><+><+><+><+><+><+> lxl1 prds$processor_tag lprpab scs$mask_ptr,1 xec scs$read_mask,1 read current mask staq ap|2,* return current mask lxl1 prds$processor_tag lprpab scs$mask_ptr,1 ldaq scs$sys_level mask down to sys level xec scs$set_mask,1 set the new mask inhibit off <-><-><-><-><-><-><-><-><-><-><-><-> " set ring-alarm to 1 if we're checking for masked in user-ring szn wired_hardcore_data$trap_invalid_masked tze not_checking lda 1,dl sta pds$alarm_ring lra pds$alarm_ring not_checking: " " now wire down pages of the stack (determined from wired_hardcore_data$wire_pages) " eppbb sst$ get pointer into the SST spribb ap|4,* arg -> |0 if we don't wire epaq sp|0 find the stack's segment number eax0 0,au get segno in x0 cmpx0 lp|prds_link are we running on prds? tze no_wire yes, skip wiring als 1 Double seg. no. since SDW's are 72 bits long. eax3 0,au copy sdw index ldaq dseg$,au arl sdw.add_shift Get abs addr of stack's page table. cmpa unpaged_page_tables$0+upt.sst_last_loc Page table not in sst tpnz no_wire => unpaged seg sbla unpaged_page_tables$0+upt.sst_absloc Get offset of stack's tmi no_wire page table in SST. eppbp bb|0,al bp -> page table lda ptw.wired,dl get wired bit for page 0 cana bp|0 is it already wired? tnz already_wired_and_masked orsa bp|0 make it wired now aos bb|sst.wired adjust count of wired pages eaq sp|0 get offset in stack of current frame qrl 18+10 get page number in q eppbp bp|0,ql bp -> ptw spribp ap|4,* return pointer to caller lxl4 wired_hardcore_data$wire_pages get number of pages to wire bound_lp: epplb sp|0 copy stack ptr eaq 0,4 copy pages to wire to qu qls 10 multiply by 1024 to get number of words awd lb|0,qu add to lb word offset epaq lb|0 copy ptr to aq lls 18 word offset in al sbla 1,dl arl 4 divide by 16 ldq dseg$+1,3 load sdw bound in q qls 15 shift out old bounds lls 18+3 a reg now contains new sdw bounds + rest of sdw 2nd word cmpa dseg$+1,3 is the final address out of bounds? tmi bound_ok no, wire whats in x4 eax4 -1,4 yes, subtract 1 from pages to wire tra bound_lp and go try again bound_ok: eaa 0,4 get number of pages wired ana =o77,du can't be more than 63 pages arl 12 position so number will be in bits 24 to 29 orsa ap|2,* set in unused area of mask epbplb sp|0 get ptr to stack base szn lb|0 touch page 0 to make sure its in core eax0 0 initialize ptw index epplb sp|0 copy our stack ptr lda ptw.wired,dl set wired bit in a lk_lp1: cana bp|0,0 is page already wired tnz lk_lp1_wired yes orsa bp|0,0 wire page aos bb|sst.wired bump count of wired pages lk_lp1_wired: szn lb|0 touch it to get it in core eax0 1,0 increment ptw index adwplb 1024,du increment stack page address eax4 -1,4 decrement pages to wire tnz lk_lp1 wire next one if not done yet no_wire: eax2 0,2 see if lock entry tnz device_control$ptl_waitlock "contract: 1. I am running in stack frame to which I want to be returned. " 2. Only remaining instruction is "return". " 3. Wired stack, sys masked. " 4. Don't return until ptl locked. short_return already_wired_and_masked: lda =o40,dl Indicate wired state. orsa ap|2,* move to arg. tra no_wire " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " unlock_ptl entry to unlock and unmask after finishing messing with " the page control data. " Call is: " " call privileged_mode_ut$unlock_ptl(oldmask,ptwp) " " dcl oldmask fixed bin (71) " dcl ptwp ptr " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " unlock_ptl: tra page_fault$pmut_unlock_ptl avoid push, minimal elegance unwire_unmask: ldaq ap|2,* pick up mask setting inhibit on <+><+><+><+><+><+><+><+><+><+><+><+> oraq channel_mask_set forget old channel mask anaq scs$open_level lxl1 prds$processor_tag get tag for masking lprpab scs$mask_ptr,1 xec scs$set_mask,1 inhibit off <-><-><-><-><-><-><-><-><-><-><-><-> " " now unwire the pages wired down by lock_ptl " lda ap|2,* Get the mask and flag back cana =o40,dl Was it wired already? tnz .rt Yes, just exit. als 12 position number of pages wired ana =o77,du allow only 63 pages eax4 0,au copy to x4 eppbp ap|4,* get page table pointer eppbp bp|0,* eax0 bp|0 is offset zero? tze .rt if so, don't unwire eax2 0 -(count of pages unwired) epaq sp|0 get ptr to stack for segno als 1 times two since SDW's are 72 bits lda dseg$,au load SDW arl sdw.add_shift shift address for ptw eppbb sst$ ptw's are in sst sbla bb|sst.ptwbase offset for page 0 ptw eppbb bb|0,al bb -> page 0 ptw lca ptw.wired+1,dl get set to turn off wired bits ldq ptw.wired,dl and to check wired bits canq bb|0 is page still wired tze ul_p0_unwired no ansa bb|0 turn off wired bit in page 0 eax2 -1,2 count page unwired ul_p0_unwired: eax0 0 count ptws ul_l1: canq bp|0,0 is page still wired tze ul_pg_unwired no ansa bp|0,0 unwire this page eax2 -1,2 count page unwired ul_pg_unwired: eax0 1,0 move on eax4 -1,4 decrement number of pages wired tnz ul_l1 eaq 0,2 qu=-(count of pages unwired) qrs 18 qr=-(count of pages unwired) asq sst$0+sst.wired adjust count of wired pages .rt: short_return " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " cioc is called to connect to any of the active modules on " a system controller except a processor. " " The calling sequence is: " " call privileged_mode_ut$cioc(cow) " " where cow is a 36 bit aligned connect operand " word. " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " cioc: eppbp ap|2,* Issue cioc instruction cioc bp|0,* at arg1 short_return " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " LRAR " " Entry to set the ring alarm register. " Call is: " " call pmut$lrar (rar_value) " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " lrar: lra ap|2,* load the ring alarm register short_return short and sweet " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " Entry to load the mode register " Call is: " " call pmut$load_mode_reg; " " called after the caller has altered pds$hfp_exponent_enabled. " (this code duplicates pxss at process switch.) " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " inhibit on <+><+><+><+><+><+><+><+><+><+><+><+> load_mode_reg: eppab prds$mode_reg_enabled lca mr.enable_hfp+1,dl is hex fp enabled for this process? ana prds$mode_reg szn pds$hfp_exponent_enabled tze *+2 ora mr.enable_hfp,dl sta prds$mode_reg ora mr.enable_mr+mr.enable_hist,dl enable mode reg and enable hist regs sta ab|0 lcpr ab|0,04 inhibit off <-><-><-><-><-><-><-><-><-><-><-><-> short_return " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " cam code moved to page by BSG, 6/19/74 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " cam: tra page$cam cam_cache: tra page$cam_cache " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " clear_cache - entry to clear cache by turning cache off and " then back on. Note that this will work for both " the L68 and the DPS8M cpus, while the execution of " a "cams 4" instruction will only clear cache " for the L68 cpu and is effectively a NOP on the " DPS8M cpu. " " Usage: dcl privileged_mode_ut$clear_cache entry; " call privileged_mode_ut$clear_cache (); " " set_proc_required must be called before calling the clear_cache " entry, to assure the the cache on the desired processor is cleared. " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " clear_cache: epplb prds$cache_luf_reg set ptr to "turn on" constant even inhibit on <+><+><+><+><+><+><+><+><+><+><+><+> lcpr clear_template,02 turn cache off lcpr lb|0,02 and back on. inhibit off <-><-><-><-><-><-><-><-><-><-><-><-> short_return clear_template: oct 3 cache "turn off" constant " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " swap_sdw is called to swap descriptor words for a given " segment number. " " The calling sequence is: " " call privileged_mode_ut$swap_sdw (segptr, sdw_ptr) " " Where segptr contains the segment number, sdw is the new " descriptor word. The sdw is an aligned 72 bit quantity. " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " swap_sdw: ldx0 ap|2,* pick up segment number adlx0 ap|2,* multiply by 2 eppbp ap|4,* get new descriptor word eppbp bp|0,* lda bp|0 ldq bp|1 staq dseg$,0 set the SDW tsx7 clear_AM_both short_return " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " This entry clears the ptw am on the current processor after " " mucking with a set of ptws. " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " camp: iftarget L68 camp ifend iftarget ADP decor ORIONp camp1 ifend short_return " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " This entry clears both AM's after bce mucks with ptws, sdws. " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " cam_both: tsx7 clear_AM_both short_return " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " These entries are called when we wish to discontinue operation " " of Multics and go to bce. There can be a return and Multics " " operation resumed. Since bce must be entered on the bootload " " processor with all other processors stopped, the actual transfer " " to bce is forced by sending a system trouble connect. " " " " Recoded 8 February 1976 by Noel I. Morris " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " bce_and_return: bce: ldq prds$processor_tag get this CPU's tag lda scs$processor_data,ql get data for this CPU cana processor_data.online,du during initialization? tze special_go_to_bce yes lda pds$processid get process ID stac scs$connect_lock lock for doing a connect nop nop tnz *-3 wait until lock set stac scs$trouble_processid " Save if we are the first (its clear) lda scs$processor processor bits in A sta scs$sys_trouble_pending set trouble flag inhibit on <+><+><+><+><+><+><+><+><+><+><+><+> cioc scs$cow_ptrs,ql* send trouble connect dis * wait for it to take effect inhibit off <-><-><-><-><-><-><-><-><-><-><-><-> lda 0,dl clear the A ansa scs$trouble_processid ansa scs$connect_lock undo the lock, now bce_return: short_return Return to caller " use linkage join /link/linkage even save_drl: bss ,2 save_luf: bss ,2 drl_to_do:bss ,2 use main eight ignore_data: bss ,8 inhibit on <+><+><+><+><+><+><+><+><+><+><+><+><+><+><+><+><+> ignore_scu_rcu: scu 0 rcu 0 " """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " " " special_bce_return - used by bce to return to bos or multics " " " """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" special_bce_return: ldaq ap|2,* arg is pair to put into drl staq lp|drl_to_do fault vector tra leave_multics special_go_to_bce: ldaq toehold$+2*TOE_HOLD_MULTICS_ENTRY get interrupt pair staq lp|drl_to_do leave_multics: eppbb fault_vector$ ldaq bb|2*FAULT_NO_LUF+fv.fpair save lockup fault vector staq lp|save_luf absa ignore_data abs addr in 0-23 als 6 abs addr in 0-17 Areg eaq 0,au abs addr in 0-17 Qreg oraq ignore_scu_rcu new lockup fault vector staq bb|2*FAULT_NO_LUF+fv.fpair lda 8,du loop waiting for i/o to die down odd sba 1,dl tnz *-1 ldaq bb|2*FAULT_NO_DRL+fv.fpair pick up derail from fault vector staq lp|save_drl save for restore later ldaq lp|drl_to_do get interrupt pair staq bb|2*FAULT_NO_DRL+fv.fpair store into derail slot of fault vector drl " go to bce ldaq lp|save_drl restore derail fault pair staq bb|2*FAULT_NO_DRL+fv.fpair ldaq lp|save_luf restore lockup fault pair staq bb|2*FAULT_NO_LUF+fv.fpair tra bce_return inhibit off <-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-><-> " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " rsw and trace_rsw are called in order to execute the rsw privileged instruction. " They return in "value" the same bits returned after " the rsw instruction is executed trace_rsw does not require rsw_code to be " input. " Instead it is assumed to be zero. " " Usage: " " % include rsw; " dcl rsw_code fixed(35), value bit(36) aligned; " call privileged_mode_ut$rsw ( rsw_code, value ); " call privileged_mode_ut$trace_rsw ( value ); " " rsw_code is 0, 1, 2, 3 or 4, depending on what bits are to be read by " rsw. See the processor manual for the definition of these. " This procedure does not check that rsw_code is 0, 1, 2, 3 or 4. " (Input). " " value is the bit string put in the a-register by rsw. See the " rsw.incl.pl1 file and the " processor manual for the meaning of this. (Output). " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " rsw: lxl0 ap|2,* c(x0) = rsw_code. rsw 0,0 Get value. sta ap|4,* short_return trace_rsw: rsw 0 Get value. sta ap|2,* short_return " """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" " " read_id_prom " used to read a selected string of bytes (characters) from " the ID PROM of a DPS8 CPU " " Usage: " dcl privileged_mode_ut$read_id_prom entry (char (*) aligned, fixed bin); " call privileged_mode_ut$read_id_prom (id_string, start_pos); " " where: " " id_string is an aligned character string, in which the ID PROM info is " to be stored. The number of bytes to read is obtained from " the argument descriptor (length) of id_string. " " start_pos is the first byte number to be read from the ID PROM " " This subroutine will only work for DPS8 cpus, indeterminent results " will be obtained if this subroutine is executed on a L68 or DPS cpu. " The calling routine should guarantee execution on the desired CPU by " first calling pxss$set_proc_required. " """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" read_id_prom: push lxl7 ap|4,* get starting byte number lxl6 ap|6,* and target string length from desc. anx6 =o77,du allow only 63 characters eppbp ap|2,* get ptr to target string epaq rip_str1 ptr to temp string in AQ lls 18 string ptr word offset in AL eaq 0,6 copy string length qls 6 position tally count orq 32,du or in 9 bit char type lls 18 tally word in A sta tally_wd store tally word (starting char pos = 0) lda rsw_template get rsw instruction template sta rsw_xec and store in stack rip_lp1: stx7 rsw_xec set byte number in rsw instruction xec rsw_xec execute the rsw instruction ana =o377,dl and out M.S bit in case it is set sta tally_wd,sc store ID byte in string ttn rip_exit return on tally runout eax7 1,7 increment byte number tra rip_lp1 and get next ID byte rip_exit: mlr (pr,rl),(pr,rl),fill(040) desc9a rip_str1,x6 copy ID string to user storage desc9a bp|0,x6 return rsw_template: rsw 0,dl used to read ID prom " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " rscr and sscr are called in order to execute the rscr and sscr " instructions, respectively. "value" is the output or input argument " for these instructions as specified in the processor manual, " respectively. " " Usage: " " % include scr; " dcl scr_input bit(36) aligned, value bit (72) aligned; " call privileged_mode_ut$rscr (port_no, scr_input, value ); " call privileged_mode_ut$sscr (port_no, scr_input, value ); " " scr_input is one of the legal arguments specified as a y-field in " an rscr or sscr instruction. See the processor manual " and the scr.incl.pl1 file for an " explanation of the legal values of scr_input. This procedure " does not verify that a legal value of scr_input was input. " (Input). " " value is the bit string read or stored by rscr or sscr, respectively. " See the processor manual and the scr.incl.pl1 file for the " definition of this bit string. " (Output of rscr. Input of sscr.) " " port_no Is the processor port number to which the " rscr or sscr instruction is to be directed. " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " rscr: lda ap|2,* port number in A als 10-3 multiply by 128 adla ap|4,* add in scr_input als 3 port*1024 + scr_input*8 rscr scas$,al read controller regs staq ap|6,* Output value. short_return sscr: lda ap|2,* port number in A als 10-3 multiply by 128 adla ap|4,* insert scr_input als 3 port*1024 + scr_input*8 eax0 0,al place in X0 ldaq ap|6,* Get input value. sscr scas$,0 set controller regs short_return " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " smcm is called to execute the smcm instruction unconditionally. " " Usage: " dcl port_no fixed bin (3), mask bit (72) aligned; " call privileged_mode_ut$smcm (port_no, mask); " " port_no is the processor port number to which the smcm " is directed. " " mask is the mask to be set by an SMCM instruction. " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " smcm: lxl1 ap|2,* port number in X1 ldaq ap|4,* mask in AQ smcm scs$port_addressing_word,1* set the mask short_return " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " privileged_mode_ut$ldt " " loads the timer register with its argument. " " declare privileged_mode_ut$ldt entry (fixed bin (35)); " call privileged_mode_ut$ldt (timer); " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " ldt: ldt ap|2,* load the timer short_return " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " ldbr " " This entry loads a new dbr for make_segs_paged, " which has just finished setting up ASTE's and " SDW's in a new dseg for the paged segments. " " Call is: " " call privileged_mode_init$ldbr(new_dbr) " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " inhibit on <+><+><+><+><+><+><+><+><+><+><+> ldbr: ldbr ap|2,* load the new DBR inhibit off <-><-><-><-><-><-><-><-><-><-><-> short_return " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " smic is called to set an interrupt pattern in the bootload SCU " " Usage: " dcl privileged_mode_ut$smic entry (bit (36)); " call privileged_mode_ut$smic (smic_pattern); " " smic_pattern is a bit pattern to be used by the SMIC " instruction. " " smic_port is called to set an interrupt pattern in any SCU " " Usage: " dcl privileged_mode_ut$smic_port entry (bit (36), fixed bin (5)); " call privileged_mode_ut$smic_port (smic_pattern, port_number); " port_number is the port to which to send the smic instruction " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " smic_port: lxl7 ap|4,* pick up port number in X7 tra smic_common smic: lxl7 scs$interrupt_controller bootload controller port in X7 smic_common: lda ap|2,* pick up SMIC pattern in A smic scs$port_addressing_word,7* SMIC short_return " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " pmut$check_for_mem_overlap " " This entry is used to determine if a memory addressing overlap " exists in an SCU. " " It is called during SCU initialization. " " It returns a nonzero code if a memory overlap error is found. " " call is: " " call pmut$check_for_mem_overlap (low_block, high_block, code) " " low_block, high_block are 1024-word frame numbers, code is returned " nonzero if a memory overlap error is found " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " check_for_mem_overlap: push ldx0 lp|abs_seg_link get segno of abs_seg adlx0 lp|abs_seg_link multiply by 2 (SDW size) ldx1 lp|abs_seg_link1 get segno of abs_seg1 adlx1 lp|abs_seg_link1 multiply by 2 (SDW size) ldaq dseg$,0 pick up old contents of abs_seg SDW staq save_sdw save in stack ldaq dseg$,1 pick up old contents of abs_seg1 SDW staq save_sdw1 save in stack ldq ap|2,* pick up low address input arg stq new_low_data save for check lls 36+12+10 36 for a, 12 for sdw, 10 for 1024 word blocks oraq abs_seg_sdw make an SDW out of the a-q staq dseg$,0 place in SDW slot for abs_seg ldq ap|4,* pick up high address input arg stq new_high_data save for check lls 36+12+10 36 for a, 12 for sdw, 10 for 1024 word blocks oraq abs_seg_sdw make an SDW out of the a-q staq dseg$,1 place in SDW slot for abs_seg1 tsx7 clear_AM_segs sti save_indicators save the indicators sti indicators_no_par save current indicators lda indicators_no_par we must turn OFF parity indicator ana -1-scu.par,dl .. ora scu.parm,dl and turn ON parity mask sta indicators_no_par eppap abs_seg$ ap -> low address to check eppbp abs_seg1$ bp -> high address to check ldi indicators_no_par lda ap|0 get low address contents sta old_low_data and save for later restore lda bp|0 get high address contents sta old_high_data and save for possible later restore lda new_low_data sta ap|0 save low address in low address lda new_high_data sta bp|0 save high address in high address lda ap|0 now check contents of low address cmpa new_low_data against what was originally written tnz overlap_error if OVERLAP leave non-zero data in A-reg lda 0,dl otherwise zero A-reg for return code ldq old_high_data replace original high data stq bp|0 when no error detected overlap_error: ldq old_low_data replace original low data stq ap|0 even when error is found eppap sp|stack_frame.arg_ptr,* restore arg pointer sta ap|6,* ldaq save_sdw restore abs_seg SDW staq dseg$,0 ldaq save_sdw1 restore abs_seg1 SDW staq dseg$,1 tsx7 clear_AM_segs ldi save_indicators return " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " pmut$check_parity_for_use " " This entry is used to determine if a parity error exists in a main memory frame. " " It is called " when hardware_fault catches a store parity error, in which case " all configured main memory is checked. " " It returns a code if a parity error is found. " It leaves the responsibility of getting the " data page somewhere else without a parity error on page control, " who will subsequently be called to delete the page anyway. " " call is: " " call pmut$check_parity_for_use (blocknumber, code) " " blocknumber is 1024-word frame number, code returned nonzero if parity " error found " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " check_parity_for_use: push aos lp|check_parity_calls meter calls ldx0 lp|abs_seg_link get segno of abs_seg adlx0 lp|abs_seg_link multiply by 2 (SDW size) ldaq dseg$,0 pick up old contents of abs_seg SDW staq save_sdw save in stack ldq ap|2,* pick up core address as input argument lls 36+12+10 36 for a, 12 for sdw, 10 for 1024 word blocks oraq abs_seg_sdw make an SDW out of the a-q staq dseg$,0 place in SDW slot for abs_seg tsx7 clear_AM_segs sti save_indicators save the indicators sti indicators_no_par save current indicators lda indicators_no_par we must turn OFF parity indicator ana -1-scu.par,dl .. ora scu.parm,dl and turn ON parity mask sta indicators_no_par eppap abs_seg$ ap -> page to check ldx1 1024*4,du size of a page in characters inhibit on <+><+><+><+><+><+><+><+><+><+><+><+> ldi indicators_no_par cmpc (pr,rl),(pr,rl) read entire page without modifying desc9a ap|0,x1 desc9a ap|0,x1 nop 0 nop 0 " The cmpc may not have examined all words in the page, since another " CPU or an IOM could modify a double-word between the two fetches. " If this happens, we punt, and check the page the hard way. tnz slow_pc lost race -- do it the hard way sti indicators inhibit off <-><-><-><-><-><-><-><-><-><-><-><-> lda 0,dl pre-set error code to 0 ldq indicators check for a parity error canq scu.par,dl .. tze checkpar_returns_code None found checkpar_report_error: lda 1,dl non-zero error code tra checkpar_returns_code slow_pc: aos lp|check_parity_slow count these eax1 1022 check page a double-word at a time inhibit on <+><+><+><+><+><+><+><+><+><+><+><+> slow_pc_loop: ldaq abs_seg$,1 nop 0 let things settle nop 0 sti indicators ldi indicators_no_par inhibit off <-><-><-><-><-><-><-><-><-><-><-><-> ldq indicators check for a parity error canq scu.par,dl tnz checkpar_report_error eax1 -2,1 tpl slow_pc_loop lda 0,dl zero error code checkpar_returns_code: eppap sp|stack_frame.arg_ptr,* restore arg pointer sta ap|4,* ldaq save_sdw restore abs_seg SDW staq dseg$,0 tsx7 clear_AM_segs ldi save_indicators return " check_parity_for_add " " This entrypoint is just as the above, except that " is clears the memory first to get rid of parity errors " left from uninitialized SCU's. check_parity_for_add: push aos lp|check_parity_calls meter calls ldx0 lp|abs_seg_link get segno of abs_seg adlx0 lp|abs_seg_link multiply by 2 (SDW size) ldaq dseg$,0 pick up old contents of abs_seg SDW staq save_sdw save in stack ldq ap|2,* pick up core address as input argument lls 36+12+10 36 for a, 12 for sdw, 10 for 1024 word blocks oraq abs_seg_sdw make an SDW out of the a-q staq dseg$,0 place in SDW slot for abs_seg tsx7 clear_AM_segs sti save_indicators save the indicators sti indicators_no_par save current indicators lda indicators_no_par we must turn OFF parity indicator ana -1-scu.par,dl .. ora scu.parm,dl and turn ON parity mask sta indicators_no_par eppap abs_seg$ ap -> page to check ldx1 1024*4,du size of a page in characters mlr (),(pr,rl) zero entire page desc9a 0 desc9a ap|0,x1 inhibit on <+><+><+><+><+><+><+><+><+><+><+><+> ldi indicators_no_par cmpc (pr,rl),(pr,rl) read entire page without modifying desc9a ap|0,x1 desc9a ap|0,x1 nop 0 nop 0 sti indicators inhibit off <-><-><-><-><-><-><-><-><-><-><-><-> lda 0,dl pre-set error code to 0 ldq indicators check for a parity error canq scu.par,dl .. tze checkpar_returns_code None found tra checkpar_report_error Borrow returns from _for_use even abs_seg_sdw: vfd o36/sdw.valid vfd 1/,o14/37777,3/sdw.read+sdw.write,o18/sdw.unpaged clear_AM_both: iftarget L68 camp ifend iftarget ADP decor ORIONp camp1 ifend clear_AM_segs: iftarget L68 cams ifend iftarget ADP decor ORIONp cams1 decor L68 ifend tra 0,x7 use .link check_parity_calls: dec 0 check_parity_slow: dec 0 use .text. join /link/.link include apte include fault_vector include mode_reg include ptw include sdw include sst include scs include stack_frame include stack_header include toe_hold include unpaged_page_tables end  syserr.alm 11/11/89 1106.2r w 11/11/89 0804.9 34704 " *********************************************************** " * * " * Copyright, (C) Honeywell Bull Inc., 1987 * " * * " * Copyright, (C) Honeywell Information Systems Inc., 1984 * " * * " * Copyright (c) 1972 by Massachusetts Institute of * " * Technology and Honeywell Information Systems, Inc. * " * * " *********************************************************** " " SYSERR - Procedure to call syserr_real after setting up stack frame. " Modified August 1975 by Larry Johnson to add binary and error_code entries " Modified 3/76 by S. H. Webber for new reconfig " Modified 12/80 by J. J. Bongiovanni for multiplexed ring-0 stacks " Modified 4/81 by J. J. Bongiovanni to add checks for wired stack, interrupts masked " Modified 10/83 by Keith Loepere for paged unpaged segments. " Modified 12/21/84 by EJ Sharpe for multiple_binary name syserr entry syserr entry binary entry error_code entry multiple_binary bool die_offset,030000 " include ptw " include sdw " include stack_frame " include stack_header " include unpaged_page_tables " " The main syserr entry is called by ring 0 procedures to type a message on the " operator's console. Its main functions is to transfer this call to syserr_real. " If all the conditions listed below are true then we will also adjust the current " stack so the next frame will be at a high location in the stack. This is done so " the stack history of the procedures which have just returned to the caller of syserr " will not be destroyed. This stack history may be useful in analyzing a dump of " the crash. The conditions which must all be met before the stack is changed are: " 1. The syserr code must be (1). This => a fatal error. " 2. The current stack must be the per-process stack. " 3. The per-process stack must be paged. " 4. The page table lock must NOT be locked. " 5. The current stack must not be wired " 6. Interrupts must not be masked syserr: ldx7 0,du set code to be syserr call tra common binary: ldx7 1,du set code to be syserr$binary call tra common error_code: ldx7 2,du set code to be syserr$error_code call tra common multiple_binary: ldx7 3,du set code to be syserr$multiple_binary common: lda 1,dl check for kill call cmpa ap|2,* ARG 1 = 1 tnz no_reset Not a kill call so don't reset epaq sp|0 Ptr to stack to AQ eax1 0,au Seg no to X1 cmpx1 |[stack_0_ptr] Are we on the per-process stack? tnz no_reset als 1 Segno * 2 ldaq |0,au Get SDW of stack arl sdw.add_shift abs addr of stack's page table cmpa unpaged_page_tables$0+upt.sst_last_loc check if unpaged tpl no_reset out of sst => unpaged sba unpaged_page_tables$0+upt.sst_absloc offset of stack's PT in SST tmi no_reset lda sst$,al PTW for page 0 of stack cana ptw.wired,dl is it wired tnz no_reset yes szn sst$ptl is page table locked? tnz no_reset yes inhibit on <+><+><+><+><+><+><+><+><+><+><+><+><+><+><+> lxl1 prds$processor_tag lprpab scs$mask_ptr,1 xec scs$read_mask,1 read current mask cmpaq scs$sys_level are interrupts masked tze no_reset yes inhibit off <-><-><-><-><-><-><-><-><-><-><-><-><-><-><-> ldaq sp|stack_frame.next_sp pick up foward ptr staq sp|stack_frame.entry_ptr save a copy ldq die_offset,du Next frame way up in stack. stq sp|stack_frame.next_sp+1 Reset foward ptr stq sb|stack_header.stack_end_ptr+1 no_reset: tra *+1,7 transfer to correct syserr_real entry tra |[syserr_real] tra |[binary] tra |[error_code] tra |[multiple_binary] end  syserr_real.pl1 11/11/89 1106.2rew 11/11/89 0804.9 293589 /****^ *********************************************************** * * * Copyright, (C) BULL HN Information Systems Inc., 1989 * * * * Copyright, (C) Honeywell Bull Inc., 1987 * * * * Copyright, (C) Honeywell Information Systems Inc., 1982 * * * * Copyright (c) 1972 by Massachusetts Institute of * * Technology and Honeywell Information Systems, Inc. * * * *********************************************************** */ /****^ HISTORY COMMENTS: 1) change(89-08-28,Farley), approve(89-09-18,MCR8132), audit(89-10-10,WAAnderson), install(89-10-11,MR12.3-1091): Increased the size of the console output buffer (out_buf) from 132 to 256 to be consistent with oc_trans_output_. END HISTORY COMMENTS */ /* format: style4,indattr,ifthenstmt,ifthen,idind35,^indcomtxt */ syserr_real: procedure (arg_code); /* This procedure completely recoded June 28, 1973 by Bill Silver. */ /* Modified 750227 by LJS to change max length of syserr messages */ /* Modified August, 1975 by Larry Johnson to implement error_code and binary entries */ /* Modified January 1976 by Larry Johnson to fix bugs in "=" message handling */ /* Modified March 1976 by Steve Webber to use logger HPROC */ /* Modified May 1976 by Larry Johnson to add "binary_mylock" entry for use by ocdcm_ */ /* Modified November 1976 by Larry Johnson to stop logging "=" messages */ /* Modified May 1977 by Noel I. Morris to shrink stack frame and implement panic */ /* Modified August 1977 by Noel I. Morris to fix bug in *lost "=" messages */ /* Modified August 1978 by Bernard S. Greenberg to eliminate calling ocdcm with syserr lock locked. */ /* Modified April 1982 by C. Hornig to add NL to console messages. */ /* Modified June 1982 by E. N. Kittlitz to not equalize alarm messages. */ /* Modified September 1982 by C. Hornig to use automatic buffer for console */ /* Modified 830601 BIM to check for silly error codes. */ /* Modified 830622 for new ocdcm_ interface... -E. A. Ranzenbach */ /* Modified 83-12-19 BIM for better call to terminate_proc */ /* Modified 83-??-?? Keith Loepere for calls to bce. */ /* Modified 1984-11-26, BIM: options (validate) changed to pmut$wire_and_mask, actually call the copy primitive if we are called unwired. */ /* Modified 1984-12-20, BIM: avoid recursive copy attempts by checking the paged syserr log lock before actually copying. */ /* Modified 1984-12-21, EJ Sharpe for multiple_binary entrypoint */ /* Modified 1985-01-21, EJ Sharpe for 2047 char text (was 512), also added process_id to wired msg */ /* Modified 1985-01-25, Keith Loepere, to fix race in log copying. */ /* Modified 1985-02-15, Keith Loepere, to restructure syserr paged vs wired lock startegy; basically to make the paged lock the highest paged lock in the system so that a copy into the paged lock is always possible from any paged process. */ /* Modified 1985-03-28, EJ Sharpe, avoid copy to paged log when process is to be terminated or system is to be crashed. */ /* The syserr code which we receive as an argument is converted to an action code whose value is mod 10 of the original value. The meaning of the ten possible action codes is: 0 => write message without alarm, log, and return. 1 => write message with alarm, log, and CRASH system - allow bce to return. 2 => write message with alarm, log, and terminate process. 3 => write message with alarm, log, and return. 4 => log message and return, don't write message unless message not logged. 5 => log message and return, don't write message even if not logged. (6 - 9) not used, mapped into code 5. /* PARAMETER DATA */ dcl arg_code fixed bin; /* (I) The syserr code. */ dcl arg_data_code fixed bin; /* (I) Format of binary data on $binary entry */ dcl arg_data_len fixed bin; /* (I) Length of binary data on $binary entry */ dcl arg_data_pieces_array_ptr ptr; /* ptr to array of ptrs and lengths of bin data */ dcl arg_data_ptr ptr; /* (I) Pointer to binary data on $binary entry */ dcl arg_error_code ptr unal; /* (I) error_table_$ code on $error_code entry */ dcl arg_n_data_pieces fixed bin; /* number of pieces of bin data */ dcl arg_panic_mess char (*); /* (I) message to panic entry */ /* AUTOMATIC DATA */ dcl alarm_flag bit (1) aligned; /* ON => write message with alarm. */ dcl arg_list_ptr ptr; /* arg list to syserr_real */ dcl 1 auto_mbuf aligned, /* refer to DATA STRUCTURING below */ 2 header like mbuf_header, 2 equal char (4) unal; dcl 1 auto_wlog_header aligned like wlog_header; dcl 1 auto_wmess_header aligned like wmess_header; dcl binary_call bit (1); /* ON => entered through $binary entry */ dcl code fixed bin; /* copy of code passed to syserr */ dcl cont_flag bit (1) aligned; /* Continuation line flag used by oc_trans_output_. */ dcl copying_permitted bit (1) aligned; /* environment permits page faults */ dcl cs_pos fixed bin; /* Position of ioa_ ccntrol string in param list */ dcl data_code fixed bin; /* Data classification code */ dcl data_len fixed bin; /* Length of binary data */ dcl data_piece_len fixed bin; /* Length of piece of binary data */ dcl data_piece_ptr ptr; /* Pointer to piece of binary data */ dcl data_pieces_array_ptr pointer; /* pointer to array of ptrs and lengths of the pieces of the binary data */ dcl data_ptr ptr; /* Pointer to binary data */ dcl error_table_call bit (1); /* ON => entered through $error_code entry */ dcl error_table_code fixed bin (35); dcl etmsgp ptr; /* Pointer to error table message on $error_code call */ dcl mbuf_ptr ptr; /* Pointer to ASCII message buffer. */ dcl message_len fixed bin (21); /* length of syserr message in data */ dcl n_data_pieces fixed bin; /* number of binary data parts */ dcl nargs fixed bin; dcl 1 oc_io aligned like console_io; dcl oc_line_leng fixed bin; /* line length of the console... */ dcl oc_printed_leng fixed bin; /* how much we will print on console */ dcl ocdcm_code fixed bin (35); /* returned by ocdcm_... */ dcl old_mask bit (72) aligned; /* actually entry value of the mask */ dcl old_wlog_ptr ptr; /* to copy of syserr_data$wired_log_area */ dcl olen fixed bin (19); /* Length of the output string in WORDS. */ dcl optr ptr; /* Pointer to beginning of the output buffer. */ dcl out_buf char (256) aligned; /* console buffer */ dcl piece_index fixed bin; /* index of binary data piece */ dcl print_len fixed bin (21); /* number of chars to print on console */ dcl print_ptr ptr; /* Pointer to beginning of expanded message for console */ dcl print_this_line_len fixed bin (21); /* Number of characters processed. */ dcl rtime fixed bin (71); /* Raw time in microseconds. */ dcl sys_code fixed bin; /* Syserr code of this message. */ dcl tenths_min fixed bin; /* Number of tenths of a minute. */ dcl wire_arg bit (72) aligned; /* mask with pmut's nasty note or'ed into it */ dcl wired bit (1) aligned; /* wired and masked */ dcl wired_wlog_ptr ptr; /* to syserr_data$wired_log_area */ dcl wired_wmess_ptr ptr; /* to where we would add message to syserr_data */ dcl wired_stack_ptr pointer; /* restore value for unwire_unmask */ dcl wmess_len fixed bin; /* Size of current wired message entry. */ dcl write_flag bit (1) aligned; /* ON => this message should be written. */ /* BASED DATA */ dcl CR_NL char (5) based (addr (CR_NL_bits)); /* DATA STRUCTURING: This program endeavors to avoid copying data many times. As such, it overlays various data structures such that the large data areas need be copied as seldom as possible. The idea is to build a wlog structure that is acceptable to syserr_copy$wired_log. However, the text in this wlog structure also wants to be part of a mbuf structure for console purposes. So, we lay down the text and data as for a wlog structure, but not the header. Instead, we allow for enough room for either a wlog/wmess header, or a mbuf header, but keep these headers in auto storage, and overlay them in front of the text when necessary. */ dcl binary_data (data_len) bit (36) aligned based (data_ptr); /* binary data on $binary entry */ dcl data_piece (data_piece_len) bit (36) aligned based (data_piece_ptr); /* Binary data on $multiple_binary entry */ dcl 1 data_pieces_array (n_data_pieces) aligned based (data_pieces_array_ptr), /* an array of pointers pieces of the binary data */ 2 ptr pointer, /* pointer to part of the binary data */ 2 len fixed bin; /* number of words */ dcl 1 et aligned based (etmsgp), /* An error table message */ 2 len fixed bin (8) unal, /* Length of the message */ 2 msg char (et.len) unal; /* The message */ /* This buffer will hold the ASCII message. When writing a message the string will start at either mbuf.no_log or mbuf.time and extend to and include mbuf.text. */ dcl 1 mbuf aligned based (mbuf_ptr), 2 header aligned like mbuf_header, 2 text char (2047) unal; /* Expanded syserr message in ASCII. */ dcl 1 mbuf_header aligned based, 2 no_log, /* Special message written only if there is no room in the wired log buffer for this message entry. */ 3 lost char (6) unal, /* "*lost " */ 3 seq_num pic "9999" unal, 3 comma char (2) unal, /* ", " */ 3 sys_code pic "9" unal, 3 pad char (3) unal, 2 time, /* Time message logged. Converted to: "hhmm.t" where t = tenths of minutes. */ 3 hh pic "99" unal, 3 mmt pic "99.9" unal, 3 pad char (2) unal; dcl old_wlog (syserr_data$wired_log_size) bit (36) aligned based (old_wlog_ptr); /* allocated copy of syserr_data$wired_log_area */ dcl wmess_copy (wmess_len) bit (36) aligned based; /* for copying wmess into syserr_data */ /* EXTERNAL ENTRIES CALLED */ dcl arg_count_ entry (fixed bin); dcl arg_list_ptr_ entry (ptr); dcl formline_ entry (fixed bin, fixed bin, ptr, fixed bin (21), fixed bin, ptr); dcl oc_trans_output_ entry (ptr, fixed bin (21), fixed bin (21), ptr, fixed bin (19), fixed bin, bit (1) aligned); dcl ocdcm_$console_info entry (char (4), bit (36), char (8), fixed bin, fixed bin, fixed bin (35)); dcl ocdcm_$drain_io entry (); dcl ocdcm_$priority_io entry (ptr); dcl pmut$bce_and_return entry options (variable); dcl pmut$read_mask entry (bit (72) aligned); dcl pmut$set_mask entry (bit (72) aligned); dcl pmut$unwire_unmask entry (bit (72) aligned, pointer); dcl pmut$wire_and_mask entry (bit (72) aligned, pointer); dcl pxss$unique_ring_0_wakeup entry (bit (36) aligned, fixed bin (71), fixed bin (71), fixed bin (35)); dcl syserr entry options (variable); dcl syserr_copy$lock entry (); dcl syserr_copy$unlock entry (); dcl syserr_copy$wired_log entry (ptr); dcl syserr_real$syserr_real entry options (variable); dcl terminate_proc entry (fixed bin (35)); dcl wired_utility_$grow_stack_frame entry (fixed bin) returns (ptr); /* EXTERNAL DATA */ dcl error_table_$ ext; dcl pds$process_group_id char (32) aligned ext; dcl pds$processid bit (36) aligned ext; dcl pds$apt_ptr pointer ext; dcl prds$ ext; dcl prds$idle_ptr pointer ext; dcl scs$open_level bit (72) aligned ext; dcl sys_info$time_correction_constant fixed bin (71) ext; dcl syserr_data$logger_ec fixed bin (71) ext; dcl syserr_data$logger_proc_id bit (36) aligned ext; dcl syserr_data$wired_log_size fixed bin ext; /* MISCELANEOUS */ dcl cleanup condition; dcl (add, addcharno, addr, addrel, baseno, bin, bit, byte, clock, currentsize, divide, length, max, min, mod, multiply, ptr, rel, rtrim, segno, size, stac, stackbaseptr, stacq, string, substr, unspec, wordno) builtin; /* CONSTANTS */ dcl CR_NL_bits bit (45) static options (constant) init ("015012177177177"b3); /* cr, nl, 3 pads - sufficient to add nl to console string */ dcl bad_ring1_msg char (24) static options (constant) init ("syserr: Bad ring 1 call."); dcl crash_msg char (46) static options (constant) init ("Multics not in operation; control process: ^a."); dcl lock_msg char (21) static options (constant) init ("syserr: Mylock error."); dcl terminate_msg char (33) static options (constant) init ("Now terminating user process: ^a."); %page; /* MAIN SYSERR_REAL ENTRY - CALLED BY SYSERR */ cs_pos = 2; /* formline_ control string is second param */ call ring0_setup; syserr_start: data_len = 0; call arg_list_ptr_ (arg_list_ptr); call SETUP_AND_TEXT; go to COMMON; /* Entry point if binary data is included */ binary: entry (arg_code, arg_data_ptr, arg_data_code, arg_data_len); cs_pos = 5; /* formline_ control string is 5th param */ call ring0_setup; syserr_binary_start: data_len = arg_data_len; call arg_list_ptr_ (arg_list_ptr); call SETUP_AND_TEXT; if data_len > 0 then do; /* If there is binary data */ binary_call = "1"b; /* this is binary call */ data_code = arg_data_code; data_ptr -> binary_data = arg_data_ptr -> binary_data; /* Copy to wired stack */ end; go to COMMON; /* Entry point if binary data is supplied in pieces */ multiple_binary: entry (arg_code, arg_data_pieces_array_ptr, arg_n_data_pieces, arg_data_code); cs_pos = 5; call ring0_setup; syserr_multiple_binary_start: data_pieces_array_ptr = arg_data_pieces_array_ptr; n_data_pieces = arg_n_data_pieces; data_len = 0; do piece_index = 1 to n_data_pieces; data_len = data_len + data_pieces_array (piece_index).len; end; call arg_list_ptr_ (arg_list_ptr); call SETUP_AND_TEXT; if data_len > 0 then do; binary_call = "1"b; /* there's something for us */ data_code = arg_data_code; data_piece_ptr = data_ptr; do piece_index = 1 to n_data_pieces; /* copy it piece by piece */ data_piece_len = data_pieces_array (piece_index).len; data_piece_ptr -> data_piece = data_pieces_array (piece_index).ptr -> data_piece; data_piece_ptr = addrel (data_piece_ptr, data_piece_len); end; end; goto COMMON; /* Enter here with error code to expand */ error_code: entry (arg_code, arg_error_code); cs_pos = 3; /* formline_ control string is 3rd */ call ring0_setup; syserr_error_start: error_table_call = "1"b; data_len = 0; call arg_list_ptr_ (arg_list_ptr); call SETUP_AND_TEXT; go to COMMON; %page; /* Ring 1 entry points to syserr. These entries are the same as the corresponding ring 0 entries, except that a ring 1 caller is not allowed to crash the system or terminate a process. */ ring1: entry (arg_code); cs_pos = 2; /* control string is second */ call arg_count_ (nargs); /* get argument count */ call ring1_setup; go to syserr_start; /* normal ring0 entry starts here */ ring1_error_code: entry (arg_code, arg_error_code); cs_pos = 3; /* control string is 3rd */ call arg_count_ (nargs); /* get argument count */ call ring1_setup; go to syserr_error_start; /* ring0 entry starts here */ ring1_binary: entry (arg_code, arg_data_ptr, arg_data_code, arg_data_len); cs_pos = 5; /* control string is 5th */ call arg_count_ (nargs); /* get argument count */ call ring1_setup; go to syserr_binary_start; ring1_multiple_binary: entry (arg_code, arg_data_pieces_array_ptr, arg_n_data_pieces, arg_data_code); cs_pos = 5; call arg_count_ (nargs); /* get argument count */ call ring1_setup; goto syserr_multiple_binary_start; %page; COMMON: wired = "0"b; on cleanup begin; /* locks will be unlocked by verify_lock */ if wired then call pmut$unwire_unmask (wire_arg, wired_stack_ptr); end; copying_permitted = "0"b; sd_ptr = addr (syserr_data$syserr_area); call pmut$read_mask (old_mask); if old_mask = scs$open_level then /* allowing interrupts */ if pds$apt_ptr ^= prds$idle_ptr then /* Not an idle process */ if stackbaseptr () ^= addr (prds$) then /* Not on the PRDS */ if ^termp_flags (sys_code) & ^crash_flags (sys_code) then/* not if process/system will disappear */ if sd.log_flag then /* WARNING, this is a paged database. */ /* The following tree touches it IFF all the other conditions are satisfied. */ if addr (syserr_log_data$) -> syserr_log_data.lock.pid ^= pds$processid then /* Not in the middle of copying the log already */ copying_permitted = "1"b; /* All these pass? then we can copy here. */ write_flag = write_flags (sys_code); /* Set flag if message is to be written */ alarm_flag = alarm_flags (sys_code); /* set flag if alarm needed */ rtime = clock (); /* Get raw time in microseconds. */ auto_wmess_header.code = code; /* fill in wmess header that we can unwired */ auto_wmess_header.time = rtime; auto_wmess_header.pad = "0"b; auto_wmess_header.process_id = pds$processid; auto_wmess_header.data_code = data_code; wired_wlog_ptr = addr (syserr_data$wired_log_area); /* place for old messages */ if copying_permitted then do; /* when we can copy, we get and hold the paged lock. The wired area is emptied into the paged log, and then we add our message to the paged log. Our message never goes into the wired area. */ call syserr_copy$lock (); old_wlog_ptr = wired_utility_$grow_stack_frame (syserr_data$wired_log_size); end; call pmut$wire_and_mask (wire_arg, wired_stack_ptr); wired = "1"b; /* Before we reference any data in syserr_data we may have to lock it. Note, this lock controls all the data in syserr_data including the wired_log_area. */ if ^sd.ocdcm_init_flag then call panic (mbuf.text); call SR_LOCK (); /* Now fill in the time of message string that goes before each message. It is in the form: "hhmm.t ". */ print_ptr = addr (mbuf.time); /* For now, console message starts with time. */ print_len = message_len + length (string (mbuf.time)); /* Get total length of string being written. */ tenths_min = mod (divide (rtime - sys_info$time_correction_constant, 6000000, 52, 0), 14400); /* Number of 10ths of minutes so far today */ auto_mbuf.header.time.hh = divide (tenths_min, 600, 5); auto_mbuf.header.time.mmt = tenths_min - divide (tenths_min, 600, 5) * 600; auto_mbuf.header.time.pad = ""; %page; if ^sd.log_flag then /* Is logging mechanism ON? */ /* NO, can't log message. */ auto_wmess_header.seq_num = 0; /* Thus there is no sequence number. */ else if copying_permitted then do; /* look for old messages to copy out */ if wired_wlog_ptr -> wlog.count > 0 then do; old_wlog_ptr -> old_wlog = wired_wlog_ptr -> old_wlog; /* copy out old messages */ wired_wlog_ptr -> wlog.next = rel (addr (wired_wlog_ptr -> wlog.buffer)); /* reset wired log */ wired_wlog_ptr -> wlog.count = 0; end; else old_wlog_ptr -> wlog.count = 0; /* no old messages */ auto_wmess_header.seq_num, wired_wlog_ptr -> wlog.seq_num = wired_wlog_ptr -> wlog.seq_num + 1; end; %page; /* This code is entered to put the current syserr message into the wired log. Each time this procedure is called we want to wake up the syserr logger HPROC who takes the messages out of the wired log buffer. */ else do; /* Get pointer to this message entry. We have to fill in the length of the text before we know where the end of the entry will be. Assume for now that there is room for this message. */ wired_wmess_ptr = ptr (wired_wlog_ptr, wired_wlog_ptr -> wlog.next); RETRY_ADD: /* here to retry with a shrunk message */ /* Now check to see if there really is room for this message entry in the wired buffer. If not, we will have to write out the message with a special prefix: "*lost xxxxxx, z " where xxxxxx is the sequence number of the message, and z is the syserr code of the message. */ if wmess_len > (size (wlog_header) + wired_wlog_ptr -> wlog.bsize) - (bin (wired_wlog_ptr -> wlog.next, 18) - wordno (wired_wlog_ptr)) then do; /* Is entry too big? Do this if YES. */ if binary_call then do; /* First try throwing away binary data */ binary_call = "0"b; /* by making it no longer a binary call */ wmess_len = wmess_len - auto_wmess_header.data_size; auto_wmess_header.data_size = 0; go to RETRY_ADD; end; auto_wmess_header.seq_num, /* Get sequence number of this message. */ wired_wlog_ptr -> wlog.seq_num = wired_wlog_ptr -> wlog.seq_num + 1; /* claim sequence number now. */ if wifnl_flags (sys_code) then do; /* If message should be written if not logged */ write_flag = "1"b; /* causes message to be written */ print_ptr = addr (mbuf.no_log); /* Now writing special note. */ print_len = print_len + length (string (mbuf.no_log)); auto_mbuf.header.no_log.lost = "*lost"; /* initialize work area */ auto_mbuf.header.no_log.comma = ","; auto_mbuf.header.no_log.pad = ""; auto_mbuf.header.no_log.seq_num = mod (auto_wmess_header.seq_num, 10000); /* edit sequence number */ auto_mbuf.header.no_log.sys_code = sys_code; /* edit code */ end; end; else do; /* There is room for this message in the wired log. Thus we can fill in the entry. */ auto_wmess_header.seq_num, /* Get sequence number of this message. */ wired_wlog_ptr -> wlog.seq_num = wired_wlog_ptr -> wlog.seq_num + 1; /* now that we know for sure that we are sending it. */ wired_wlog_ptr -> wlog.next = bit (add (bin (wired_wlog_ptr -> wlog.next, 18), wmess_len, 18), 18); /* Incr address of where next entry goes. */ wired_wlog_ptr -> wlog.count = wired_wlog_ptr -> wlog.count + 1; /* Add message to log buffer. */ wmess_ptr -> wmess.header = auto_wmess_header; /* construct wmess_header in front of message */ wired_wmess_ptr -> wmess_copy = wmess_ptr -> wmess_copy; /* add wmess to syserr_data */ end; call WAKEUP_DAEMON; /* move these messages! */ end; %page; /* If we don't have to write this message then we are all done. If we must write it then we must first convert it for console output. Note, a maximum of 80 characters can be typed on one line. With the "no_log" and "time" strings at the beginning of the line and since ASCII characters may convert into more than one typed character, it is possible the output string will be too long. In this case the line will be continued. Note, the message itself may consist of more than one line. */ if write_flag then do; /* write - code is (4 - 9). */ /* Check here for a non-alarm syserr message being the same as the last message written. If this is the case, only an "=" will be printed. */ if ^alarm_flag & mbuf.text = sd.prev_text_written then do; /* A match */ print_len = print_len - message_len + 1; message_len = 1; /* set length to 1 character */ print_ptr = addrel (addr (auto_mbuf), wordno (print_ptr) - wordno (mbuf_ptr)); /* lie - tell ocdcm_ to print only this header */ if mbuf.text ^= " " then auto_mbuf.equal = "="; else auto_mbuf.equal = ""; /* substitute "=" unless blank message */ end; else do; /* New message */ if message_len > length (sd.prev_text_written) then /* too long to save */ unspec (sd.prev_text_written) = "0"b; /* so clear out old message */ else sd.prev_text_written = substr (mbuf.text, 1, message_len); /* save text */ mbuf_ptr -> mbuf_header = auto_mbuf.header; /* get the real mbuf header in front of the message for printing */ end; end; %page; /* Syserr data has been globally updated. Now we need to write the actual message, which is done from data in the stack. */ call SR_UNLOCK; /* Unlock syserr data */ if write_flag then do; optr = addr (out_buf); /* Pointer to output buffer. */ cont_flag = "0"b; /* => 1st line of message. oc_trans_output_ turns it ON in case of a continuation line. */ /* Each iteration processes 1 console output line. There may be more than one line in the syserr message or there may be a continuation line. */ call ocdcm_$console_info ("", "0"b, "", 0, oc_line_leng, ocdcm_code); /* get console line length... */ if ocdcm_code ^= 0 then oc_line_leng = 80; /* default line length... */ do while (print_len > 0); call oc_trans_output_ (print_ptr, print_len, print_this_line_len, optr, olen, oc_line_leng, cont_flag); oc_printed_leng = multiply (olen, 4, 17); oc_io.read = "0"b; oc_io.alert = alarm_flag; oc_io.sequence_no = auto_wmess_header.seq_num; oc_io.event_chan = 0; if print_this_line_len >= print_len then do; /* this is the last line - add CR NL */ oc_printed_leng = length (rtrim (substr (out_buf, 1, oc_printed_leng), byte (127))); /* actual last char */ substr (out_buf, oc_printed_leng + 1, 5) = CR_NL; olen = divide (oc_printed_leng + 5, 4, 17); /* 2 for cr/nl, 3 for rounding up to word */ oc_printed_leng = multiply (olen, 4, 17); end; /* advance for next line */ print_ptr = addcharno (print_ptr, print_this_line_len); print_len = print_len - print_this_line_len; alarm_flag = "0"b; /* Don't want alarm ON more than once. */ oc_io.leng = olen; oc_io.text = substr (out_buf, 1, oc_printed_leng); call ocdcm_$priority_io (addr (oc_io)); /* do the I/O...*/ end; %page; /* Now check to see if we have to terminate the process or CRASH the system. */ if termp_flags (sys_code) then do; /* If process to be terminated */ call syserr_real$syserr_real (LOG, terminate_msg, pds$process_group_id); call pmut$set_mask (scs$open_level); /* Unmask so that recursive call wires */ call terminate_proc (error_table_code); end; else if crash_flags (sys_code) then do; /* If system is to crash */ /* TOO BAD we must CRASH. Before we call bce we must be sure that all of the messages on the ocdcm_ syserr write queue have been written. We will call a special entry in ocdcm_ which completes all pending I/O. */ call syserr_real$syserr_real (ANNOUNCE, crash_msg, pds$process_group_id); call ocdcm_$drain_io (); /* flush pending I/O... */ call pmut$bce_and_return; end; end; %page; /* Time to leave */ call pmut$unwire_unmask (wire_arg, wired_stack_ptr); if copying_permitted then do; if old_wlog_ptr -> wlog.count > 0 then call syserr_copy$wired_log (old_wlog_ptr); wlog_ptr -> wlog_header = auto_wlog_header; /* reconstruct wlog header before text */ wlog.count = 1; wmess_ptr -> wmess_header = auto_wmess_header; call syserr_copy$wired_log (wlog_ptr); /* add in our new message */ call syserr_copy$unlock; end; return; %page; /* All this entry does is force the sd.lock OFF. */ syserr_reset: entry; addr (syserr_data$syserr_area) -> sd.lock = "0"b; return; /* This entry is called if syserr is called before the IOM and operator's console software has been initialized. It is also called when trouble is encountered in syserr or ocdcm_. */ panic: entry (arg_panic_mess); fgbxp = addr (flagbox$); /* Get pointer to bce flagbox. */ fgbx.message = arg_panic_mess; /* Copy the message. */ fgbx.alert, fgbx.mess = "1"b; /* Turn on flag bits. */ do while ("1"b); /* Back to bce. */ call pmut$bce_and_return; end; %page; /* common processing for ring 1 calls */ ring1_setup: proc; binary_call = "0"b; /* defaults */ data_code = 0; error_table_call = "0"b; if nargs < cs_pos then do; /* if not enough */ call syserr (4, bad_ring1_msg); go to ring1_return; end; code = arg_code; /* copy the code */ sys_code = mod (code, 10); /* compute action code */ code = divide (code, 10, 17, 0); /* check sort code */ if code < 0 | code > 24 then code = 24; /* apply default if out of range */ code = 10 * code + sys_code; /* this is new code after errors removed */ end ring1_setup; ring1_return: return; /* nonlocal return from ring1_setup */ ring0_setup: proc; binary_call = "0"b; /* defaults */ data_code = 0; error_table_call = "0"b; code = arg_code; /* copy syserr code */ sys_code = mod (code, 10); /* compute action code */ return; end ring0_setup; %page; /* This internal procedure is called to unlock the wired log. */ SR_UNLOCK: procedure; if stacq (sd.lock, "0"b, sd.lock) then ; /* Unlock unconditionally */ end SR_UNLOCK; SR_LOCK: procedure; if sd.lock = pds$processid then call panic (lock_msg); do while (^stac (addr (sd.lock), pds$processid)); end; return; end SR_LOCK; WAKEUP_DAEMON: procedure; call pxss$unique_ring_0_wakeup (syserr_data$logger_proc_id, syserr_data$logger_ec, 0, (0)); return; end WAKEUP_DAEMON; %page; SETUP_AND_TEXT: proc; /* allocate a wlog structure to hold our message; generate the text of the message */ dcl len_for_et fixed bin; dcl max_header_size fixed bin; dcl text_and_data_size fixed bin; dcl work_ptr ptr; auto_wmess_header.text_len, message_len = 2047; /* maximum */ auto_wmess_header.data_size = data_len; text_and_data_size = currentsize (addr (auto_wmess_header) -> wmess); /* how much a wmess corresponding to this auto header would need */ max_header_size = max (size (wlog_header) + size (wmess_header), size (mbuf_header)); work_ptr = wired_utility_$grow_stack_frame (max_header_size + text_and_data_size); /* Allocate message buffer. */ wlog_ptr = addrel (work_ptr, max_header_size - (size (wlog_header) + size (wmess_header))); wmess_ptr = addrel (wlog_ptr, size (wlog_header)); mbuf_ptr = addrel (work_ptr, max_header_size - size (mbuf_header)); call formline_ (cs_pos, cs_pos + 1, addr (wmess.text), message_len, 1, arg_list_ptr); /* Expand syserr message. */ if message_len = 0 then do; /* if asked to write null message, be careful */ substr (wmess.text, 1, 4) = ""; /* clear text buffer */ message_len = 1; /* write 1 blank */ end; error_table_code = -9; if error_table_call then do; /* If passed an error table code */ etmsgp = arg_error_code; /* Copy packed pointer. */ unspec (error_table_code) = unspec (arg_error_code); if baseno (etmsgp) = "077777"b3 then /* If segment is -1 ... */ etmsgp = ptr (addr (error_table_$), rel (etmsgp)); /* Use error_table_. */ if segno (etmsgp) = 0 then error_table_code = -9; else do; len_for_et = auto_wmess_header.text_len - message_len; /* Amount of room left to insert message */ len_for_et = min (len_for_et, et.len + 1); if len_for_et > 0 then do; substr (wmess.text, message_len + 1, 1) = " "; substr (wmess.text, message_len + 2, len_for_et - 1) = et.msg; /* Concatenate message on end */ message_len = message_len + len_for_et; /* Adjust message length */ end; end; end; auto_wmess_header.text_len = message_len; wmess_len = currentsize (addr (auto_wmess_header) -> wmess); data_ptr = addrel (wmess_ptr, wmess_len - data_len); return; end SETUP_AND_TEXT; %page; %include flagbox; %page; %include oc_data; %page; %include syserr_actions; %page; %include syserr_constants; %page; %include syserr_data; %page; %include syserr_log_dcls; %page; /* BEGIN MESSAGE DOCUMENTATION Message: syserr: Mylock error. S: $crash T: $run M: $err A: $recover Message: Now terminating user process: PERSON.PROJ. S: $info T: $run M: This line is always preceded by an explanation of the error which required the terminaation of the user process PERSON.PROJ. A: $ignore Message: Multics not in operation; control process: PERSON.PROJ. S: $crash T: $run M: This message is always preceded by an explanation of the error which crashed the system. A: $recover Message: syserr: Bad ring 1 call. S: $log T: $run M: A bad call to syserr was made from ring 1. The system keeps running. A: $ignore END MESSAGE DOCUMENTATION */ end syserr_real;  wire_stack.alm 11/11/89 1106.2r w 11/11/89 0803.8 61650 " *********************************************************** " * * " * Copyright, (C) Honeywell Bull Inc., 1987 * " * * " * Copyright, (C) Honeywell Information Systems Inc., 1982 * " * * " * Copyright (c) 1972 by Massachusetts Institute of * " * Technology and Honeywell Information Systems, Inc. * " * * " *********************************************************** name wire_stack " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " Calling Sequence: " call wire_stack " " This procedure is designed to be called only from PL/1 programs " through the use of the validate option. " " wire_stack performs the following steps: " 1. If the current stack is the PRDS, or if this is too " early in initialization, return. Too early in " initialization means before the SCS is set up, as this " is when the masking mechanism is operative. " 2. A stack frame for wire_stack is created which " overlays the caller's stack frame. " 3. The memory mask is set to sys_level. " 4. The current and next pages of the stack are wired down. " 5. A cleanup condition is established. " 6. A new stack frame is manfactured for the caller. " 7. The caller is returned to in his new frame. " " The steps above are undone either when the caller returns " or when a non-local goto occurs. " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " segref scs,faults_initialized segref scs,read_mask,mask_ptr,sys_level segref prds,processor_tag segref tc_data,system_shutdown segref privileged_mode_ut,wire_and_mask,unwire_unmask segref condition_,condition_ link prds_link,|0 tempd ptp pointer to stack's page table tempd save_mask previous memory controller mask tempd label(2) label for cleanup condition tempd arglist(5) argument list for call to condition_ " include stack_header include stack_frame include scs " entry wire_stack wire_stack: " Ignore this call if on the PRDS or if too early in initialization epaq sp|0 segment # of stack in AU eax0 0,au place in X0 cmpx0 lp|prds_link are we on the prds? tze .rt if so, just return ldq prds$processor_tag lda scs$processor_data,ql get data for this CPU cana processor_data.online+processor_data.offline,du early initialization? tze .rt yes, ignore call " Ignore this call if masked down. inhibit on <+><+><+><+><+><+><+><+><+><+><+><+> lxl1 processor_tag CPU tag in X1 lprpab mask_ptr,1 get pointer for masking xec read_mask,1 read system controller mask eraq sys_level masked to sys level? anaq =v16/-1,20/,16/-1,20/ .. tze .rt if so, ignore the call inhibit off <-><-><-><-><-><-><-><-><-><-><-><-> " Make stack frame for wire_stack. eppap sp|stack_frame.min_length establish stack frame for wire stack sprisp ap|stack_frame.prev_sp leave only the bare minimum of old frame eppsp ap|0 caller's old frame will be rethreaded later adwpap push ap -> new frame for caller spriap sp|stack_frame.next_sp set pointer to next frame eppbb sb|stack_header.stack_end_ptr,* save stack end ptr in bb spriap sb|stack_header.stack_end_ptr set pointer to new end of stack sprilp sp|stack_frame.lp_ptr save linkage pointer " Call privileged_mode_ut$wire_and_mask to do the work. eppbp save_mask bp -> place for saved controller mask spribp arglist+2 .. eppbp ptp bp -> place for page table pointer spribp arglist+4 .. ldaq =v18/4,18/4 set arglist header staq arglist .. call wire_and_mask(arglist) wire and mask " Set up argument list and call condition_. szn faults_initialized have faults been initialized yet? tze create_frame if not, skip call to condition_ szn system_shutdown are we shutting down? tnz create_frame if so, don't establish condition link cleanup_link,<*text>|[cleanup_handler] eppap lp|cleanup_link,* make label for cleanup handler spriap label .. sprisp label+2 .. eppap lp|condition_name ap -> character string spriap arglist+2 set up argument list eppap label ap -> label spriap arglist+4 .. eppap lp|condition_name_desc set up descriptor list spriap arglist+6 .. eppap lp|label_desc .. spriap arglist+8 .. ldaq =v18/4,18/4,18/4 set argument list header staq arglist .. sprilp sp|stack_frame.lp_ptr be careful to save linkage pair call condition_(arglist) establish the condition epplp sp|stack_frame.lp_ptr,* restore the linkage pair now " Create new stack frame for caller. create_frame: eppbp sb|stack_header.stack_end_ptr,* bp -> caller's new frame eppap sp|stack_frame.prev_sp,* ap -> caller's old frame mlr (pr),(pr) copy the stack frame header desc9a ap|0,stack_frame.min_length*4 desc9a bp|0,stack_frame.min_length*4 eax1 bb|0 X1 contains offset of original end ptr sblx1 sp|stack_frame.prev_sp+1 compute length of caller's frame sprisp ap|stack_frame.next_sp set next sp in old frame sprisp bp|stack_frame.prev_sp set last sp in new frame eppap bp|0,1 compute next sp for new frame spriap bp|stack_frame.next_sp and set it spriap sb|stack_header.stack_end_ptr save new stack end ptr " Fill in wire_stack's frame with vital info. link return_link,<*text>|[return] eppap lp|return_link,* ap -> return entry spriap sp|stack_frame.return_ptr set return control double info sprilp sp|stack_frame.lp_ptr save pointer so return op will work " Switch to new frame and return to caller. eppsp bp|0 sp -> new frame sprisp sp|12 doctor the stored prs .rt: eppap sp|stack_frame.operator_ptr,* restore pr to operators rtcd sp|stack_frame.return_ptr return to caller " entry return return: "normal return from caller eppbp sp|0 bp -> stack frame tsx7 undo unwire and unmask inhibit on <+><+><+><+><+><+><+><+><+><+><+><+> eppsp sp|stack_frame.prev_sp,* sp -> caller's old frame return " return to caller's caller inhibit off <-><-><-><-><-><-><-><-><-><-><-><-> entry cleanup_handler cleanup_handler: "invoked by non-local goto push: push ldx0 ap|0 2 * number of args in X0 eppbp ap|2,0* grab display pointer tsx7 undo clean things up return return to the unwinder " Subroutine to perform unwiring and unmasking. undo: eppap bp|save_mask ap -> save mask spriap bp|arglist+2 .. eppap bp|ptp ap -> page table pointer spriap bp|arglist+4 .. ldaq =v18/4,18/4 set arglist header staq bp|arglist .. call unwire_unmask(bp|arglist) unwire and unmask tra 0,7 return to caller " even null: its -1,1 null pointer use internal_static join /link/internal_static condition_name: aci "cleanup" condition_name_desc: vfd o18/10121,18/7 label_desc: vfd o18/172 end bull_copyright_notice.txt 08/30/05 1008.4r 08/30/05 1007.3 00020025 ----------------------------------------------------------- Historical Background This edition of the Multics software materials and documentation is provided and donated to Massachusetts Institute of Technology by Group Bull including Bull HN Information Systems Inc. as a contribution to computer science knowledge. This donation is made also to give evidence of the common contributions of Massachusetts Institute of Technology, Bell Laboratories, General Electric, Honeywell Information Systems Inc., Honeywell Bull Inc., Groupe Bull and Bull HN Information Systems Inc. to the development of this operating system. Multics development was initiated by Massachusetts Institute of Technology Project MAC (1963-1970), renamed the MIT Laboratory for Computer Science and Artificial Intelligence in the mid 1970s, under the leadership of Professor Fernando Jose Corbato.Users consider that Multics provided the best software architecture for managing computer hardware properly and for executing programs. Many subsequent operating systems incorporated Multics principles. Multics was distributed in 1975 to 2000 by Group Bull in Europe , and in the U.S. by Bull HN Information Systems Inc., as successor in interest by change in name only to Honeywell Bull Inc. and Honeywell Information Systems Inc. . ----------------------------------------------------------- Permission to use, copy, modify, and distribute these programs and their documentation for any purpose and without fee is hereby granted,provided that the below copyright notice and historical background appear in all copies and that both the copyright notice and historical background and this permission notice appear in supporting documentation, and that the names of MIT, HIS, Bull or Bull HN not be used in advertising or publicity pertaining to distribution of the programs without specific prior written permission. Copyright 1972 by Massachusetts Institute of Technology and Honeywell Information Systems Inc. Copyright 2006 by Bull HN Information Systems Inc. Copyright 2006 by Bull SAS All Rights Reserved