1 /****^  ***********************************************************
  2         *                                                         *
  3         * Copyright, (C) Honeywell Bull Inc., 1987                *
  4         *                                                         *
  5         * Copyright, (C) Honeywell Information Systems Inc., 1982 *
  6         *                                                         *
  7         *********************************************************** */
  8 /* format: style4,delnl,insnl,indattr,ifthen,dclind10 */
  9          /* use: pl1_macro pc_abs.pl1.pmac  -target l68 */
 10 pc_abs:
 11      procedure;
 12 
 13 /* This procedure is responsible for adding and removing blocks of memory
 14    and for abs-wiring memory for I/O segments.
 15 
 16    The original pc_abs was written by Roger R. Schell in September 1970.
 17    Rewritten 6/3/74 by Bernard S. Greenberg for evict_page and page$pwait.
 18    Abs-wire functions removed 6/3/74 by B. Greenberg for I/O Buffer manager.
 19    Totally rewritten for new cme protocols, no remove list, and 75% code reduction, 03/12/75, BSG.
 20    Modified to allow evict_page to delete, for automatic parity deletion, BSG, 05/11/78.
 21    Modified to handle case when pages to be deleted are already gone, Chris Jones, 8/84
 22    Modified 1984-10-26 BIM to pay attention to the first argument to
 23             wire/unwire.
 24    Modified 1984-12-07, Keith Loepere, to not avoid abs wiring in low 256K.
 25 */
 26 
 27 
 28 /****^  HISTORY COMMENTS:
 29   1) change(86-10-07,Farley), approve(86-11-20,MECR0002),
 30      audit(86-11-19,Fawcett), install(86-11-20,MR12.0-1222):
 31      Added three checks to the unwire_abs entry. First verify that the Astep
 32      parameter is non-null. Second verify that the page table word does really
 33      define a wired/in-core page. Third verify that the CME is really abs wired.
 34      Crash if any of these are incorrect.
 35   2) change(86-12-19,Farley), approve(86-12-19,MCR7587),
 36      audit(86-12-19,Fawcett), install(87-01-05,MR12.0-1253):
 37      Formal installation to close out above MECR0002.
 38                                                    END HISTORY COMMENTS */
 39 
 40 
 41 dcl       Code                   fixed bin (35) parameter;
 42 dcl       Absaddr                fixed bin (26) parameter;
 43 dcl       Fpage                  fixed bin (9) parameter; /* zero based */
 44 dcl       Npages                 fixed bin (9) parameter;
 45 dcl       Fframe                 fixed bin (16) parameter;
 46 dcl       Nframes                fixed bin (16) parameter;
 47 dcl       Modulus                fixed bin (16) parameter;
 48 dcl       Astep                  pointer parameter;
 49 
 50 dcl       astep                  ptr;
 51 dcl       (ind, aind)            fixed bin (35);
 52 dcl       (fframe, nframes, frame, modulus)
 53                                  fixed bin (16);
 54 dcl       (fp, np, page)         fixed bin (9);
 55 dcl       frames                 (0:255) fixed bin (16);
 56 
 57 dcl       oldmask                fixed bin (71) aligned;
 58 dcl       sptp                   ptr;
 59 
 60 dcl       based_word             fixed bin (35) aligned based;
 61 
 62 dcl       page$evict             entry (ptr, fixed bin (35));
 63 dcl       page$pwait             entry (fixed bin (35));
 64 dcl       page$wire_abs          entry (ptr, fixed bin (35), ptr, fixed bin (9));
 65 dcl       pmut$lock_ptl          entry (fixed bin (71) aligned, ptr);
 66 dcl       pmut$unlock_ptl        entry (fixed bin (71) aligned, ptr);
 67 dcl       syserr                 entry options (variable);
 68 
 69 dcl       ALL_ONES               fixed bin (35) static options (constant) init (-1);
 70 dcl       CORE                   bit (4) static options (constant) init ("8"b4);
 71 
 72 dcl       error_table_$out_of_main_memory
 73                                  fixed bin (35) external static;
 74 dcl       sst$abs_wired_count    fixed bin (35) external;
 75 dcl       sst$astsize            fixed bin (17) external;
 76 dcl       sst$cmp                ptr external;
 77 dcl       sst$first_core_block   fixed bin (16) external;
 78 dcl       sst$last_core_block    fixed bin (16) external;
 79 dcl       sst$nused              fixed bin (35) external;
 80 dcl       sst$usedp              bit (18) aligned external;
 81 dcl       sst$wusedp             bit (18) aligned external;
 82 dcl       sst$wired              fixed bin (35) external;
 83 dcl       sys_info$page_size     fixed bin (17) external static;
 84 
 85 dcl       (addr, addrel, binary, max, mod, null, ptr, rel, wordno)
 86                                  builtin;
 87 ^L
 88 remove_core:
 89      entry (Fframe, Nframes, Code);
 90 
 91           Code = 0;
 92           fframe = Fframe;
 93           nframes = Nframes;
 94 
 95           call lock;                                        /* wire and lock */
 96 
 97           do frame = 1 to nframes;                          /* make sure it is not in use */
 98                if sst$cmp -> cma (fframe + frame - 1).abs_w then do;
 99                     call unlock;
100                     Code = 2;                               /* return error code */
101                     return;
102                end;
103           end;
104 
105           call remove_frames;                               /* get rid of them */
106 
107           call unlock;
108           return;
109 %skip (3);
110 remove_core_mod:
111      entry (Nframes, Modulus, Absaddr, Code);
112 
113           nframes = Nframes;
114           modulus = Modulus;
115           Absaddr = -1;
116           Code = 0;
117 
118           call lock;
119           call find_frames;
120           call remove_frames;
121           call unlock;
122 
123           Absaddr = fframe * sys_info$page_size;
124           return;
125 ^L
126 wire_abs_contig:
127      entry (Astep, Fpage, Npages, Code);
128 
129           astep = Astep;                                    /* Copy args before locking page table lock */
130           fp = Fpage;
131           np, nframes = Npages;
132           Code = 0;
133 
134           call lock;
135 
136           modulus = 1;
137 retry_contig:
138           call find_frames;
139 
140           if fframe >= 256 then
141                goto noalloc;                                /* must keep I/O buffers low */
142                                                             /* see iom_connect.alm for details. */
143 
144           do frame = 0 to nframes - 1;
145                frames (frame) = fframe + frame;
146           end;
147 
148           if ^abs_wire_frames () then
149                goto retry_contig;
150 
151           call unlock;
152 
153           return;
154 ^L
155 wire_abs:
156      entry (Astep, Fpage, Npages, Code);
157 
158           astep = Astep;
159           fp = Fpage;
160           np, nframes = Npages;
161           Code = 0;
162 
163           call lock;
164 
165 retry:
166           page = 0;
167           do fframe = max (sst$first_core_block, 256) to sst$last_core_block while (page < np);
168                                                             /* save low 256K for wire_abs_contig */
169                cmep = addr (sst$cmp -> cma (fframe));
170                if (cmep -> based_word ^= ALL_ONES) & ^cme.abs_w & ^cme.removing & cme.abs_usable
171                     & ((cme.fp ^= ""b) | (cme.ptwp ^= ""b)) then do;
172                     frames (page) = fframe;
173                     page = page + 1;
174                end;
175           end;
176           if page < np then do;
177 noalloc:
178                call unlock;
179                Code = error_table_$out_of_main_memory;
180                return;
181           end;
182 
183           if ^abs_wire_frames () then
184                goto retry;
185 
186           call unlock;
187           return;
188 ^L
189 unwire_abs:
190      entry (Astep, Fpage, Npages);
191 
192           astep = Astep;
193           fp = Fpage;
194           np = Npages;
195 
196           if astep = null () then do;
197                call syserr (CRASH, "pc_abs$unwire_abs: Called with NULL astep.");
198                return;
199           end;
200 
201           do page = fp to fp + np - 1;                      /* unwire the pages */
202                ptp = addrel (astep, sst$astsize + page);
203                if (ptw.add_type = CORE) & ptw.wired then do;/* valid PTW */
204                     frame = core_ptw.frame;                 /* find the core frame */
205 
206                     cmep = addr (sst$cmp -> cma (frame));
207                     if ^cme.abs_w
208                          then call syserr (CRASH, "pc_abs$unwire_abs: Attempt to unwire inconsistent CME at ^p.", cmep);
209 
210 /* reset wired & abs_w here */
211 
212                     ptw.phm = "1"b;                         /* in case the IOM modified it */
213                     ptw.wired = "0"b;                       /* not wired any more */
214 
215                     cme.abs_w = "0"b;
216 
217                     sst$wired = sst$wired - 1;
218                     sst$abs_wired_count = sst$abs_wired_count - 1;
219                end;
220                else call syserr (CRASH, "pc_abs$unwire_abs: Attempt to unwire inconsistent PTW at ^p.", ptp);
221           end;
222 
223           return;
224 ^L
225 find_frames:
226      procedure;
227 
228 dcl       j                      fixed bin (16);
229 
230           do fframe = sst$first_core_block + mod (-sst$first_core_block, modulus) by modulus to sst$last_core_block;
231                                                             /* find a possible first page */
232                j = 0;
233                if mod (fframe + nframes - 1, 256) < (nframes - 1) then
234                     goto will_not_do;                       /* and we won't cross 256K boundary */
235                do j = 0 to nframes - 1;                     /* check each page */
236                     cmep = addr (sst$cmp -> cma (fframe + j));
237                                                             /* get ptr to cme */
238                     if (cmep -> based_word = ALL_ONES) | cme.abs_w | cme.removing | (^cme.abs_usable)
239                          | ((cme.fp = ""b) & (cme.ptwp = ""b)) then
240                          go to will_not_do;                 /* OS are just fine, as long as... */
241                end;
242 
243                return;
244 
245 will_not_do:
246                fframe = fframe + j - mod (j, modulus);
247           end;
248 
249           goto noalloc;
250 
251      end find_frames;
252 ^L
253 remove_frames:
254      procedure;
255 
256           do frame = 1 to nframes;                          /* mark all frames */
257                sst$cmp -> cma (fframe + frame - 1).removing = "1"b;
258           end;
259 
260           ind = -1;                                         /* do at least one pass */
261           do while (ind ^= 0);                              /* loop until it's done */
262                ind = 0;
263                do frame = 1 to nframes;                     /* for each frame to be evicted */
264                     cmep = addr (sst$cmp -> cma (fframe + frame - 1));
265                                                             /* find CME */
266                     if cmep -> based_word ^= ALL_ONES then do;
267                                                             /* it has not yet been deleted */
268                          call page$evict (cmep, aind);      /* start it out */
269                          if (cmep -> based_word ^= ALL_ONES) & (aind = 0) then do;
270                               ptr (cmep, cme.fp) -> cme.bp = cme.bp;
271                                                             /* unthread it */
272                               ptr (cmep, cme.bp) -> cme.fp = cme.fp;
273                               if sst$usedp = rel (cmep) then
274                                    sst$usedp = cme.fp;
275                               if sst$wusedp = rel (cmep) then
276                                    sst$wusedp = cme.fp;
277                               cmep -> based_word = ALL_ONES;/* mark it gone */
278                               cme.abs_usable, cme.removing = "0"b;
279                               sst$nused = sst$nused - 1;
280                          end;
281                          else if ind = 0 then
282                               ind = aind;                   /* multiplex waits */
283                     end;
284                end;
285                if ind ^= 0 then
286                     call page$pwait (ind);
287           end;
288 
289           if (fframe + nframes) > sst$last_core_block then
290                sst$last_core_block = fframe - 1;
291 
292           return;
293 
294      end remove_frames;
295 ^L
296 abs_wire_frames:
297      procedure returns (bit (1) aligned);
298 
299 /**** In this procedure, "page" is the index (from zero)
300       into the array of abs_usuable pages found in the core map,
301       and fp + page is the index into the segment's page table. */
302 
303           do frame = 1 to nframes;                          /* mark them used */
304                sst$cmp -> cma (frames (frame - 1)).abs_w = "1"b;
305           end;
306 
307           ind = -1;
308           do while (ind ^= 0);
309                ind, aind = 0;
310                do page = 0 to np - 1;
311                     cmep = addr (sst$cmp -> cma (frames (page)));
312                     if (wordno (astep) + sst$astsize + fp + page) ^= binary (cme.ptwp, 18) then
313                          call page$evict (cmep, aind);
314 
315                     if cmep -> based_word = ALL_ONES then do;
316                          call syserr (CRASH, "pc_abs: Parity error in I/O buffer.");
317                          return ("0"b);
318                     end;
319 
320                     if aind = 0 then
321                          call page$wire_abs (cmep, aind, astep, fp + page);
322 
323                     if ind = 0 then
324                          ind = aind;
325                end;
326 
327                if ind ^= 0 then
328                     call page$pwait (ind);
329           end;
330 
331           sst$abs_wired_count = sst$abs_wired_count + nframes;
332           return ("1"b);
333 
334      end abs_wire_frames;
335 ^L
336 lock:
337      procedure;
338 
339           call pmut$lock_ptl (oldmask, sptp);               /* lock the ptl */
340           return;
341 
342      end lock;
343 
344 
345 unlock:
346      procedure;
347 
348           call pmut$unlock_ptl (oldmask, sptp);             /* almost done */
349           return;
350 
351      end unlock;
352 ^L
353 %include syserr_constants;
354 %page;
355 %include cmp;
356 %INCLUDE "ptw.macro";
357 ^L
358 /* BEGIN MESSAGE DOCUMENTATION
359 
360    Message:
361    pc_abs: Parity error in I/O buffer.
362 
363    S:     $crash
364 
365    T:     $run
366 
367    M:     $err
368 
369    A:     $recover
370 
371    Message:
372    pc_abs$unwire_abs: Called with NULL astep.
373 
374    S:     $crash
375 
376    T:     $run
377 
378    M:     $err
379 
380    A:     $inform
381    $recover
382 
383    Message:
384    pc_abs$unwire_abs: Attempt to unwire inconsistent CME at CMEP.
385 
386    S:     $crash
387 
388    T:     $run
389 
390    M:     The core map entry for the page being abs unwired did not
391    have the abs_w flag on, which indicates that it was properly abs wired.
392    $err
393 
394    A:     $inform
395    $recover
396 
397    Message:
398    pc_abs$unwire_abs: Attempt to unwire inconsistent PTW at PTP.
399 
400    S:     $crash
401 
402    T:     $run
403 
404    M:     A page at PTP, within the range of pages being unwired for,
405    was found to either not be wired or no longer in memory.
406    $err
407 
408    A:     $inform
409    $recover
410 
411    END MESSAGE DOCUMENTATION */
412 
413      end pc_abs;