1 /****^  ******************************************************
  2         *                                                    *
  3         * Copyright, (C) Honeywell Bull Inc., 1987           *
  4         *                                                    *
  5         * Copyright (c) 1986 by Massachusetts Institute of   *
  6         * Technology and Honeywell Information Systems, Inc. *
  7         *                                                    *
  8         * Copyright (c) 1972 by Massachusetts Institute of   *
  9         * Technology and Honeywell Information Systems, Inc. *
 10         *                                                    *
 11         ****************************************************** */
 12 
 13 
 14 
 15 /****^  HISTORY COMMENTS:
 16   1) change(86-05-13,GJohnson), approve(86-05-13,MCR7387),
 17      audit(86-05-13,Martinson), install(86-05-14,MR12.0-1056):
 18      Correct error message documentation.
 19                                                    END HISTORY COMMENTS */
 20 
 21 
 22 /* format: style2 */
 23 
 24 /* RING_ALARM - The Ring Alarm Register Management Procedure.
 25           coded 10/2/72 by S. H. Webber and N. I. Morris
 26           modified 2/26/76 by Noel I. Morris for new reconfig
 27           modified 2/8/82 by J. Bongiovanni to set ralr to 1 if masked (conditionally)
 28 
 29           modified 830518 BIM to correctly check pds */
 30 /*        futher modified 8306 to revamp strategy -- call side polling added */
 31 
 32 /* 830529 BIM to add poll entrypoint for call side ring alarm check */
 33 /* Modified 1985-01-21, BIM: admin_privilege resetting. */
 34 
 35 /* See level.alm for explanation of validation level protocols. */
 36 
 37 
 38 ring_alarm:
 39      procedure;
 40 
 41 
 42           dcl     a_mcp                  ptr;               /* pointer to machine conditions */
 43 
 44           dcl     target_ring            fixed bin (3);     /* target ring which caused ring alarm fault */
 45           dcl     i                      fixed bin;         /* ring number iteration variable */
 46           dcl     mask                   fixed bin (71);    /* interrupt mask */
 47           dcl     setting                fixed bin (4);     /* new setting for ring alarm register */
 48 
 49           dcl     pds$admin_privileges   bit (36) aligned ext;
 50           dcl     pds$alarm_ring         fixed bin (3) ext; /* setting of ring alarm register */
 51           dcl     pds$apt_ptr            ptr ext;           /* pointer to APT entry for this process */
 52           dcl     pds$connect_pending    bit (1) aligned ext;
 53                                                             /* non-zero if fim to do connect after return */
 54           dcl     pds$ips_mask           (0:7) bit (36) aligned ext;
 55                                                             /* mask for IPS signals in each ring */
 56           dcl     pds$ring_alarm_val     (0:7) fixed bin (3) ext;
 57 
 58           dcl     pds$process_group_id   char (32) ext static;
 59           dcl     pds$validation_level   fixed bin (3) ext; /* current validation level */
 60 
 61           dcl     scs$sys_level          fixed bin (71) ext;
 62 
 63           dcl     wired_hardcore_data$trap_invalid_masked
 64                                          bit (1) aligned ext;
 65           dcl     severity               fixed bin;
 66           dcl     (stop_flag, pre_empt_flag, ips_flag, check_ips, validation_flag, privileges_flag)
 67                                          bit (1) aligned init ("0"b);
 68                                                             /* flags to prevent resetting alarm after detecting condition */
 69 
 70           dcl     fs_get$path_name       entry (ptr, char (*), fixed bin (21), char (*), fixed bin (35));
 71           dcl     pmut$lrar              entry (fixed bin (3));
 72           dcl     pmut$read_mask         entry (fixed bin (71));
 73           dcl     pxss$force_stop        entry;
 74           dcl     set_privileges$admin_ring_alarm
 75                                          entry;
 76           dcl     syserr                 entry options (variable);
 77           dcl     syserr$binary          entry options (variable);
 78           dcl     (addr, codeptr, fixed, max, min, mod)
 79                                          builtin;
 80 
 81           declare active_hardcore_data$validation_fix_severity
 82                                          fixed bin external;
 83           dcl     any_other              condition;
 84 ^L
 85 
 86 /* RING_ALARM$FAULT - The Ring Alarm Fault Handler. */
 87 
 88 fault:
 89      entry (a_mcp);
 90           mcp = a_mcp;                                      /* copy arg */
 91 
 92           scup = addr (mcp -> mc.scu (0));                  /* get pointer to SCU data */
 93 
 94 /* Determine the target ring at the time of the fault. */
 95 
 96           target_ring = fixed (scup -> scu.tpr.trr, 3);
 97 
 98           call ANALYZE_RING_ALARM$$fault (target_ring);
 99 
100 
101           pds$connect_pending = pds$connect_pending | stop_flag | pre_empt_flag | ips_flag;
102                                                             /* On fault side we still take connects */
103 
104 /* No other checks are made now.  We will drop into the code for
105    ring_alarm$reset to compute and set a new value for the
106    ring alarm register.                                               */
107 ^L
108 
109 /* RING_ALARM$RESET - Compute new setting for ring alarm register. */
110 
111 reset:
112      entry;
113 
114 Reset_common:
115           pds$alarm_ring = 0;                               /* we do complete calculation, so */
116           setting = 8;                                      /* Start with ring alarm reg turned off. */
117 
118           aptep = pds$apt_ptr;                              /* Get a pointer to APT entry for this process. */
119           check_ips = ^ips_flag & (apte.ips_message ^= ""b);
120 
121 
122           do i = 0 to 7 while (setting = 8);                /* Iterate through all rings. */
123 
124                if check_ips & ((apte.ips_message & pds$ips_mask (i)) ^= ""b)
125                                                             /** if pending IPS */
126                then setting = i;
127                else if pds$ring_alarm_val (i) ^= 0          /** or validation level was set to this ring ... */
128                     & (i < 7)                               /** cant call into 7 */
129                then setting = i + 1;                        /* if we go beyond this ring */
130           end;
131 
132           if (pds$admin_privileges ^= ""b)                  /* Can only happen in ring 0 */
133           then setting = min (2, setting);                  /* target ring is 2 */
134 
135 /* Test for deferred pre-empt or stop. */
136 
137           if (apte.pre_empt_pending & ^pre_empt_flag)
138           then setting = 1;
139           else if (apte.stop_pending & ^stop_flag)
140           then setting = 1;
141 
142 /* Test for interrupts masked if debug parameter is set */
143 
144           if wired_hardcore_data$trap_invalid_masked
145           then do;
146                     call pmut$read_mask (mask);
147                     if mask = scs$sys_level
148                     then setting = 1;
149                end;
150 
151 
152 /* Now, reset the ring alarm register if necessary. */
153 
154           setting = mod (setting, 8);                       /* Compute new value for RAR. */
155           call set (fixed (setting, 3));                    /* And call recursively to set it. */
156 
157           return;
158 
159 reset_no_pre_empt:
160      entry;
161 
162           pre_empt_flag = "1"b;
163           go to Reset_common;
164 ^L
165 
166 /* SET - Entry to set the ring alarm ring. */
167 
168 set:
169      entry (ringno);
170 
171           dcl     ringno                 fixed bin (3);     /* ring number to which to set ring alarm */
172 
173 
174           setting = pds$alarm_ring;                         /* Get current RAR setting. */
175           if setting = 0
176           then setting = 8;                                 /* Set to 8 if RAR turned off. */
177           setting = min (setting, ringno);                  /* Set new RAR value. */
178           pds$alarm_ring = mod (setting, 8);                /* .. */
179           call pmut$lrar (pds$alarm_ring);                  /* Call privileged procedure to load RAR. */
180 
181           return;
182 ^L
183 
184 /* RING_ALARM$POLL -- on call side, check for ring alarms that we can avoid. */
185 
186 
187 poll:
188      entry returns (bit (1) aligned);
189 
190           declare callerframe            pointer;
191           declare outer_ring_ptr         pointer;
192           declare its_ptr                pointer;
193 
194           if wired_hardcore_data$trap_invalid_masked
195           then do;
196                     call pmut$read_mask (mask);
197                     if mask = scs$sys_level
198                     then call syserr (CRASH, "ring_alarm$poll: processor is masked at exit from ring 0.");
199                end;
200 
201 
202           callerframe = stackframeptr () -> stack_frame.prev_sp -> stack_frame.prev_sp;
203                                                             /* caller of the gate that called us */
204 
205           outer_ring_ptr = callerframe -> stack_frame.return_ptr;
206                                                             /* now, the ring number of outer_ring_ptr has to be first ring number of the caller's stack or larger */
207 
208           its_ptr = addr (outer_ring_ptr);
209           target_ring = its_ptr -> its_unsigned.ringno;     /* get it as fb */
210 
211           call ANALYZE_RING_ALARM (target_ring);
212 
213           if ^pre_empt_flag & ^stop_flag
214           then do;                                          /* Was either validation level, which ANALYZE fixed, */
215                                                             /* or privileges, which ANALYZE fixed, */
216                                                             /* or IPS, which we cannot handle yet, */
217                                                             /* or completely off the wall.  */
218                     call reset;                             /* recurse: another ring may still need an rar */
219                     return ("0"b);                          /* returns to outer ring for the gate */
220                end;
221 
222 
223           if stop_flag
224           then call pxss$force_stop;                        /* This is supposed to be easy */
225 
226 /* PRE-EMPT */
227 
228           if pre_empt_flag
229           then do;
230                     call reset_no_pre_empt;                 /* in case of val level or IPS */
231                     return ("1"b);
232                end;
233 
234           call syserr (CRASH, "ring_alarm$poll: Mysterious ring alarm.");
235 ^L
236 
237 /* This procedure looks at the state in the PDS, and sets bits to indicate */
238 /* why the ring alarm register was set.  */
239 
240 
241 ANALYZE_RING_ALARM:
242      procedure (Target_ring);
243 
244           declare Target_ring            fixed bin (3);
245           declare fault                  bit (1);
246           declare old_validation_level   fixed bin (3);
247 
248           fault = "0"b;
249           go to Join;
250 
251 ANALYZE_RING_ALARM$$fault:
252      entry (Target_ring);
253 
254           fault = "1"b;
255 
256 Join:
257           old_validation_level = pds$validation_level;
258 
259           do i = 0 to Target_ring - 1;                      /* check all rings up to the one being returned to */
260                if pds$ring_alarm_val (i) ^= 0
261                then do;
262                          pds$validation_level = pds$ring_alarm_val (i);
263                          pds$ring_alarm_val (i) = 0;        /* no longer important */
264                     end;
265           end;
266 
267           pds$validation_level = max (Target_ring, pds$validation_level);
268                                                             /* never let it be < execution ring */
269                                                             /* do this LAST, to respect saved value if possible. */
270 
271           if old_validation_level ^= pds$validation_level & active_hardcore_data$validation_fix_severity >= 0
272           then do;
273                     call syserr (active_hardcore_data$validation_fix_severity,
274                          "ring_alarm: Fixed validation level^[ on fault^] from ^d to ^d.", fault, old_validation_level,
275                          pds$validation_level);
276                     validation_flag = "1"b;
277                end;
278 
279           if pds$admin_privileges ^= ""b & Target_ring > 1
280           then do;                                          /* Always call syserr, since this is always a bug */
281                     if active_hardcore_data$validation_fix_severity = -1
282                     then severity = JUST_LOG;
283                     else severity = active_hardcore_data$validation_fix_severity;
284                     call syserr (severity, "ring_alarm: Reset admin privileges^[ on fault^].", fault);
285                     call set_privileges$admin_ring_alarm;
286                     privileges_flag = "1"b;
287                end;
288 
289 /* Check to see if a stop interrupt has been delayed */
290 
291           aptep = pds$apt_ptr;                              /* Get pointer to our APT entry. */
292           if apte.stop_pending
293           then stop_flag = "1"b;
294 
295 /* Check to see if a pre-empt interrupt has been delayed. */
296 
297           else if apte.pre_empt_pending
298           then pre_empt_flag = "1"b;
299 
300 /* Now check for any delayed IPS signals */
301 
302           else if apte.ips_message & pds$ips_mask (Target_ring)
303           then ips_flag = "1"b;
304 
305           return;                                           /* Caller can now decide what to do with this mess */
306 
307      end ANALYZE_RING_ALARM;
308 
309 
310 /* BEGIN MESSAGE DOCUMENTATION
311 
312    Message:
313    ring_alarm$poll: processor is masked at exit from ring 0.
314 
315    S:  $crash
316 
317    T:  $run
318 
319    M:  A software bug has left interrupts masked to system level at
320    exit from ring 0.
321 
322    A:  $inform
323 
324 
325    Message:
326    ring_alarm$poll: Mysterious ring alarm.
327 
328    S:  $crash
329 
330    T:  $run
331 
332    M:  The ring alarm register was set on exit from ring zero, but no reason
333    for it was recorded for the process.
334 
335    A:  $inform
336 
337 
338    Message:
339    ring_alarm: Fixed validation level {on fault} from OLD to NEW.
340 
341    S:   $beep
342 
343    T:   $run
344 
345    M:   On exit from ring zero, the validation level was less than the ring
346    that is being returned to. The validation level is corrected to its
347    value when it called into the inner ring. This indicates a benign
348    bug in the inner ring entry called.
349 
350    A:   $inform
351 
352 
353    Message:
354    ring_alarm$fault: Reset admin privileges.
355 
356    S:   $log
357 
358    T:   $run
359 
360    M:   On exit from ring one, one or more AIM privileges were still set
361    by privileged ring 1 code. These are reset, and the following
362    log message from set_privileges lists them. This indicates
363    a benign bug in the ring one program that was running.
364 
365    A:   $inform
366 
367 END MESSAGE DOCUMENTATION */
368 
369 /* format: off */
370 
371 %page; %include mc;
372 %page; %include apte;
373 %page; %include syserr_constants;
374 %page; %include its;
375 %page; %include signaller_stack;
376 %page; %include stack_frame;
377 %page; %include stack_header;
378 %page; %include syserr_binary_def;
379      end ring_alarm;