1 " ***********************************************************
  2 " *                                                         *
  3 " * Copyright, (C) Honeywell Bull Inc., 1987                *
  4 " *                                                         *
  5 " * Copyright, (C) Honeywell Information Systems Inc., 1982 *
  6 " *                                                         *
  7 " * Copyright (c) 1972 by Massachusetts Institute of        *
  8 " * Technology and Honeywell Information Systems, Inc.      *
  9 " *                                                         *
 10 " ***********************************************************
 11 
 12 " SIGNALLER - Ring 0 Module to Perform Signalling Operation.
 13 "         Modification record: (Date and Reason)
 14 "         83-12-12  by BIM to unmask before -2 terminates
 15 "         7/81      by J. Bongiovanni for prev stack frame bug
 16 "         8/80      by J. A. Bush for DPS8/70M
 17 "         5/79      by M. Grady to implement stack 0 sharing.
 18 "         10/78     by B. Greenberg to set support bit in frame.
 19 "         10/75     by R. Bratt to signal on primary stack if prr ^= sp.ring_no
 20 "         7/75      by B. Greenberg, to limit MC saving
 21 "         3/75      by S. Webber to use new (safe) RCU conventions
 22 "         2/74      by Steve Webber to trace signallings in pds trace data
 23 "         10/73     by Steve Webber to separate out restart_fault code into different segment
 24 "         9/73      by M. Weaver to move fim_frame_flag and fill in entry ptr
 25 "         29 Aug 72 by R F Mabee to remove numerous followon conversion bugs.
 26 "         8/8/72    by Steve Webber to fix the 4 signaller bugs.
 27 "         6/26/72   by Bill Silver for 645F.
 28 
 29 
 30 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 31 "
 32 "         SIGNALLER -- This program must by called (transferred to) in ring
 33 "                   0 when a fault or condition is to be signalled. It
 34 "                   expects the machine conditions to be in pds$signal_data
 35 "                   and the condition name to be in pds$condition_name.
 36 "
 37 "                   A dummy (signaller) stack frame is created on the stack
 38 "                   being signalled on and the machine conditions and name
 39 "                   are copied into this frame. The signal_ procedure defined
 40 "                   by the signal_ptr in the stack header of the stack being
 41 "                   signalled on is then called.
 42 "
 43 "                   The procedure shares the stack frame with "restart_fault"
 44 "                   and hence any changes to stack variables in either program
 45 "                   must be reflected in the other.
 46 "
 47 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
 48 
 49 
 50           name      signaller
 51 
 52           inhibit   on                  <+><+><+><+><+><+><+><+><+><+><+><+>
 53 
 54 
 55 
 56 
 57 
 58           link      signaller_link,<*text>|0
 59           link      restart_fault_link,restart_fault$
 60           link      pds_link,pds$
 61 
 62 
 63 
 64           include   signaller_stack
 65           include   mc
 66           include   apte
 67           include   stack_header
 68           include   stack_frame
 69 " ^L
 70           entry     signaller
 71           entry     no_save
 72 
 73 no_save:                                "entry to signal illegal_return data
 74           tsplb     page_fault$trace_signaller
 75           eax7      2                   no save, but leave scux in fim_temp.
 76           tra       merge
 77 
 78 signaller:
 79           tsplb     page_fault$trace_signaller
 80           eax7      0                   set to save mc
 81 merge:    epaq      *
 82           lprplp    sb|stack_header.lot_ptr,*au
 83           eppbp     pds$signal_data     bp -> m.c. data in PDS.
 84 
 85 "         Now we must unmask to open level. All interrupts are
 86 "         allowed after we signal. We unmask here so that the
 87 "         following termination happens in an unmasked environment.
 88 
 89           ldaq      scs$open_level      open up mask
 90           lxl1      prds$processor_tag  CPU tag in X1
 91           lprpab    scs$mask_ptr,1      get pointer for masking
 92           xec       scs$set_mask,1
 93 
 94 " Terminate process if fault occurred during signalling.
 95 
 96           ldx0      bp|mc.scu.ppr.psr_word Pick up PPR.PRR and PPR.PSR
 97           anx0      scu.ppr.psr_mask,du from m.c. and zero PPR.PRR.
 98           cmpx0     lp|signaller_link   were we in signaller?
 99           tze       term4,*
100           cmpx0     lp|restart_fault_link what about restart_fault?
101           tze       term4,*             if so, bye-bye!
102 
103 
104 "         Now we must save the stack pointer we are currently using. This
105 "         will be used to reset the stack end pointer if we are signalling
106 "         on  a different stack.
107 
108           sprisp    bp|mc.mask
109           eppsp     bp|mc.prs+6*2,*     set sp to stack to signal on
110           eppap     sp|0                save for prev frame pointer
111           lda       bp|mc.scu.indicators_word see if we were in bar mode
112           cana      scu.ir.bm,dl        ..
113           tze       bar_mode
114           lda       bp|mc.prs+6*2       get ring of sp
115           als       18
116           era       bp|mc.scu.ppr.psr_word        compare to prr
117           cana      =o700000,du
118           tze       set_sb              equal - signal on sp
119           lda       bp|mc.scu.ppr.psr_word
120           arl       36-3
121           als       1
122           epbpsp    pds$stacks,al*
123           eppsp     sp|stack_header.stack_end_ptr,*
124           tra       set_sb              not equal - signal on pds$stacks (prr)
125 bar_mode: epbpsb    sp|0                make sb point to base of stack
126           lda       sb|stack_header.bar_mode_sp+1 get word offset of saved sp
127 "                                       (saved before entering BAR mode)
128           eawpsp    0,au                use this value since BAR mode pgm could clobber ADR6
129           eppap     sp|0                and save as prev pointer
130 "                                       which is also word offset of sp
131           ldaq      sp|stack_frame.next_sp get next sp from current frame
132           cmpaq     sb|stack_header.stack_end_ptr better be equal to stack end ptr
133           tnz       term8,*             it isn't...we can't trust sp so wipe the guy out
134 set_sb:
135 
136           epbpsb    sp|0                Make sb point to base of validated stack segment.
137 "                                       Get offset of next frame.
138           ldq       fim_frame_flag,dl   turn ON fim frame flag
139           orsq      sp|stack_frame.flag_word
140           ldq       sb|stack_header.stack_end_ptr+1
141 
142 " Add default frame size to frame offset in case fault occurred when adding a new frame
143 " but before all pointers were set - for example, in the middle of a "push".
144 
145           adlq      stack_frame.min_length,du
146           orq       fim_frame_flag,dl   OR in old fim frame flag bit.
147 "                                       Update the pointer in the old frame.
148           stq       sp|stack_frame.next_sp+1
149 
150 
151 " Setup "sp" to point to the new frame. We can't trust the segment number in
152 " the stack_header.stack_end_ptr nor in the next_sp pointer in the previous
153 " frame. We will use the validated "sb" as the segment number.  The offset
154 " we trust.
155 
156           eppsp     sb|0,qu             Offset still in QU.
157 "                                       Now "sp" points to the new frame.
158 
159           spriap    sp|stack_frame.prev_sp Store ptr to old frame.
160           ldx0      push                get size of signaller frame
161           eppap     sp|0,0              get pointer to end of frame
162           spriap    sp|stack_frame.next_sp Store ptr to next frame.
163           spriap    sb|stack_header.stack_end_ptr Update header.
164           sprilp    sp|stack_frame.lp_ptr
165           lda       4,du                fill in translator ID
166           sta       sp|stack_frame.translator_id
167           lda       stack_frame.support_bit,dl
168           orsa      sp|stack_frame.prev_sp turn on support bit.
169 
170           eppap     return_to_ring_0_$return_to_ring_0_
171           spriap    sp|stack_frame.entry_ptr
172           epaq      sp|0                now check to see if we're abandoning a stack
173           eax0      0,au                segno of new stack in x0
174           cmpx0     bp|mc.mask          same as old stack ?
175           tze       old_stack           we're still using this stack, don't reset
176           epbplb    bp|mc.mask,*        get pointer to base of old stack
177           ldaq      lb|stack_header.stack_begin_ptr reset end pointer to begin pointer
178           staq      lb|stack_header.stack_end_ptr
179 old_stack:
180 "
181 "         Save the machine conditions in the pds. We will only save the SCU data
182 "         and the pointers and lengths.
183 "
184           tsx1      copy_and_save_mc    save mc in pds and copy into stack frame
185 
186           eppap     mach_cond           get pointer to machine conditions
187           spriap    mc_ptr              save mc pointer in stack
188 
189           ldq       0,dl                          set up for no hregs (zero length)
190           szn       pds$hregs_saved               do history regs exist?
191           tze       *+2                           xfer if no, pad hreg blk with 0's
192           ldq       128*4,dl                      yes, set length
193           mlr       (pr,rl),(pr),fill(0)
194           desc9a    bp|48,ql
195           desc9a    history_registers,128*4
196 
197 " Copy the condition name into stack frame.
198 
199           eppbp     pds$condition_name  bp -> condition name in wired storage
200           eppap     signal_string       ap -> condition name in stack
201           mlr       (pr),(pr)
202           desc9a    bp|0,32
203           desc9a    ap|0,32
204 " ^L
205 " Make descriptors for call to signal.
206 
207           lda       signal_string       pick up first word of string
208           arl       27                  right-justify character count
209           ora       char_desc_mask,du   Insert bits for desc_mask
210           sta       string_descriptor   save the descriptor
211 
212           lda       ptr_desc_mask,du    Make a descriptor for pointer.
213           sta       ptr_descriptor      save the descriptor
214 
215 "         Now set up the cleanup handler to discard the MC if necessary
216 "
217           tsx1      set_up_cleanup      set up cleanup condition handler
218 
219 " Create argument list for call to signal.
220 
221           ldaq      arg_list_header     Setup argument list header.
222           staq      arglist
223 
224           eppap     null,*              ap contains null pointer
225           spriap    null_ptr            set up null pointer for call
226 
227           eppap     signal_string       set up argument list
228           spriap    arglist+2
229           lda       9*512,dl            don't forget the bit offset
230           orsa      arglist+3           for character string
231 
232           eppap     mc_ptr              call signal_ (condition_name, mc_ptr, mc, mc)
233           eppbp     null_ptr            ap -> m.c. pointer, bp -> null pointer.
234           spriap    arglist+4           set arguments
235 
236           eppap     null_ptr
237           spriap    arglist+6
238 
239           spribp    arglist+8
240 
241           eppap     string_descriptor   set pointers to descriptors
242           spriap    arglist+10
243 
244           eppap     ptr_descriptor
245           spriap    arglist+12
246           spriap    arglist+14
247           spriap    arglist+16
248 
249           eppbb     sb|stack_header.signal_ptr,* we want to call signal_
250           eppap     arglist             set up ap for call
251 join:
252           eppbp     return_to_ring_0_$return_to_ring_0_ get pointer which gets us to ring 0
253           spribp    sp|stack_frame.return_ptr save in normal return loc
254           spribp    sp|stack_frame.entry_ptr      for debuggers
255 
256 "
257 "         Before calling signal_, we return to system code in return_to_ring_0_ which
258 "         will execute in the user ring so that any pending ring alarm faults can be handled.
259 "         This is done by first returning to return_to_ring_0_ (which really returns to ring N)
260 "         which will then call signal_.
261 "
262           eppab     pds$signal_data+mc.mask return from this place
263           sprisb    ab|0                save this for ring number only
264           epaq      return_to_ring_0_$return_to_ring_n
265           stca      ab|0,70
266           stcq      ab|1,70
267           rtcd      ab|0                return to return_to_ring_n
268 "^L
269 "         for_linker
270 "
271 "         This entry is used by the linker to complete the work of calling the trap_caller
272 "         for a trap-before-link or trap-at-first-reference.
273 "
274 "         Call is:      call signaller$for_linker (stack_ptr, entry_ptr)
275 "
276           entry     for_linker
277 for_linker:
278           epbplb    sp|0                save pointer to stack we're on
279           eppbp     lb|stack_header.stack_begin_ptr,* reset stack
280           spribp    lb|stack_header.stack_end_ptr     ..
281 
282           eppbb     ap|2,*              get target stack pointer
283           eppsp     bb|0,*              into sp register
284           epbpsb    sp|0                generate pointer to stack base
285 
286           eppbb     ap|4,*              get entry to call
287           eppbb     bb|0,*              ,,
288 
289           eax7      0                   hopefully save machine conditions
290           eppbp     pds$signal_data     get ptr to place to stash data
291           tsx1      copy_and_save_mc    do the work
292           tsx1      set_up_cleanup      and set up a cleanup handler in outer ring
293 
294           eppap     sp|stack_frame.operator_ptr,* (left here by trap_caller_caller_)
295           tra       join
296 
297 "^L
298 "         Subroutines
299 "
300 
301 copy_and_save_mc:
302           ldx0      bp|mc.scu.ppr.psr_word                  what is ring?
303           canx0     =o700000,du                   pds ?
304           tnz       *+2                 if not, don't inhibit saving.
305           eax7      1                   Was the PDS, can't restart, so don't save.
306 
307           eax0      0                   set for 0 SCU index if not saved.
308           eax7      0,7                 Is state of mc rotten already?
309           tnz       dont_save           yes, don't save MC.
310 
311           eppap     pds$mc_save_ptr,*   get place to put data
312           eax0      ap|16               where will that put us?
313           cmpx0     pds$mc_save_limit   too many?
314           tpl       too_many            signal new problem if too many
315 
316           stx0      pds$mc_save_ptr     save new next ptr
317 
318           mlr       (pr),(pr)
319           desc9a    bp|mc.scu,8*4
320           desc9a    ap|0,8*4
321           mlr       (pr),(pr)
322           desc9a    bp|mc.eis_info,8*4
323           desc9a    ap|8,8*4
324           aos       pds$unique_scu_index
325           lxl0      pds$unique_scu_index
326           stx0      ap|scu.tsr_stat_word save unique index in ring 0 copy
327 
328 " Copy the machine conditions into stack frame.
329 
330 dont_save:
331           mlr       (pr),(pr)
332           desc9a    bp|0,48*4
333           desc9a    mach_cond,48*4
334           cmpx7     2,du                is this illegal return signal?
335           tze       *+2                 if so, leave original scux
336           stx0      mach_cond+mc.fim_temp save the unique index
337           tra       0,1
338 
339 set_up_cleanup:
340 
341 "         Generate condition unit for cleanup
342 
343           lda       =o100,dl            set condition flag
344           orsa      sp|stack_frame.prev_sp
345           equ       on_unit_offset,on_unit
346           eax0      on_unit_offset      get offset of on-unit structure in new stack frame
347           stx0      sp|stack_frame.on_unit_rel_ptrs
348 
349           eppbp     on_unit+8           get pointer to place to store string
350           spribp    on_unit             save it in the real on unit
351           lda       7,dl                set length of the name
352           sta       on_unit+4
353           stz       on_unit+5           clear flags word
354           eppbp     <restart_fault>|1
355           spribp    on_unit+2
356 
357           mlr       (),(pr),fill(040)   move the string into the stack
358           desc9a    cname,7
359           desc9a    on_unit+8,32
360 
361           tra       0,1
362 
363 "
364 "         User has willingly prevented mc cleanup. Flag the mc identifiably,
365 "         and don't save them.
366 "
367 too_many:
368           eax0      -1                  make identifiable flag in mc
369           tra       dont_save           merge
370 "^L
371 "         storage and constants
372 
373           even
374 term4:    its       -2,-4
375 term8:    its       -2,-8
376 null:     its       -1,1
377 
378 arg_list_header:
379           vfd       18/8,18/4
380           vfd       18/8,18/0
381 
382           bool      ptr_desc_mask,464000
383           bool      char_desc_mask,524000
384 
385 push:     push
386 cname:    aci       "cleanup"
387 
388           end