1 /****^  ***********************************************************
  2         *                                                         *
  3         * Copyright, (C) Honeywell Bull Inc., 1987                *
  4         *                                                         *
  5         * Copyright, (C) Honeywell Information Systems Inc., 1983 *
  6         *                                                         *
  7         *********************************************************** */
  8 
  9 
 10 make_sdw: proc (a_segno, a_tsdw, a_astep, a_ptp);
 11 
 12 /*        Last Modified: (Date and Reason)
 13    09/22/71 by Richard H. Gumpertz to change null devadds to include rel(ptp) for page
 14    08/--/71 by David R. Vinograd for page multi-level
 15    02/12/74 by Bernard S. Greenberg for 6180 cache
 16    04/09/74 by Bernard S. Greenberg for TBLS card
 17    07/17/74 by Mike Grady to move code to temp wire pages and
 18      look for pds and pl1_operators_
 19    02/10/75 by Andre Bensoussan for the new storage system.
 20    07/09/75 by Greenberg, incorporating 1/6/75 change by Mabee
 21      making SDW parameters 'like', instead of fixed (71).
 22    12/08/75 by Greenberg for pre-withdraw against HC partition
 23    07/20/78 by Greenberg for multi-vol HC part.
 24    01/31/79 by D. Spector to allocate deciduous segments on root phys vol
 25    03/22/81, W. Olin Sibert, for ADP PTWs and SDWs
 26    04/16/81, WOS, to make parameters fixed bin (71) again, use sdw_util_
 27    02/28/82, J. Bongiovanni, to eliminate use of FSDCT, add entries
 28              thread_hcp, reset_hcp
 29    08/11/82, J. Bongiovanni, to eliminate RLV parasites.
 30    10/18/82, BIM, $no_pages, entry for establishing segs on partitions
 31    04/06/83, KPL, bug fix to $no_pages to fill in length fields in aste
 32    12/13/83, KPL, for adding breakpoint page to executable segments.
 33    07/12/84, KPL, for setting sentinel in breakpoint page.
 34    */
 35 
 36           dcl     a_segno                fixed bin (18) parameter;
 37           dcl     a_tsdw                 fixed bin (71) parameter;
 38           dcl     a_ptp                  pointer parameter;
 39           dcl     a_astep                pointer parameter;
 40           dcl     a_pvtx                 fixed bin parameter;
 41 
 42           dcl     (error_table_no, pdsno, dsegno, pl1_ops_no, pl1_ops_pages, no_pages_wired) fixed bin;
 43           dcl     (ptsi, loopcnt)        fixed bin;
 44           dcl     pvtx                   fixed bin;
 45           dcl     temp_sdw               fixed bin (71);
 46           dcl     save_pts               fixed bin;
 47           dcl     dummy                  fixed bin;
 48           dcl     asp                    ptr;
 49           dcl     pts                    fixed bin (9);
 50           dcl     (i, j)                 fixed bin;
 51           dcl     unthreaded             bit (1) aligned;   /* Switch is on if unthreaded entry */
 52           dcl     no_pages               bit (1) aligned;
 53 
 54           dcl     1 sdwi                 aligned like sdw_info automatic;
 55 
 56           dcl     seg                    (0:262143) fixed bin based aligned;
 57           dcl     bfword                 (0:1) fixed bin based;
 58 
 59           dcl     hcp_thread             fixed bin int static init (0);
 60           dcl     hcp_first              fixed bin int static init (0);
 61 
 62           dcl     abs_seg$               external static;
 63           dcl     breakpoint_page$       external static;
 64           dcl     dseg$                  external static;
 65           dcl     name_table$            external static;
 66           dcl     pds$                   external static;
 67           dcl     slt$                   external static;
 68 
 69           dcl     pl1_operators_$end_pl1_operators fixed bin external static;
 70           dcl     error_table_$          external static;
 71           dcl     sys_info$system_type   fixed bin external static;
 72 
 73           dcl     absadr                 entry (ptr, fixed bin (35)) returns (fixed bin (26));
 74           dcl     config_$find           entry (char (4) aligned, ptr);
 75           dcl     get_ptrs_$given_astep  ext entry (ptr) returns (fixed bin (71));
 76           dcl     pmut$swap_sdw          entry (ptr, ptr);
 77           dcl     ptw_util_$make_core    entry (pointer, fixed bin (26));
 78           dcl     ptw_util_$make_null    entry (pointer, bit (22) aligned);
 79           dcl     ptw_util_$set_wired    entry (pointer);
 80           dcl     sdw_util_$construct    entry (pointer, pointer);
 81           dcl     sdw_util_$dissect      entry (pointer, pointer);
 82           dcl     syserr                 ext entry options (variable);
 83           dcl     thread$cin             ext entry (ptr, bit (18));
 84           dcl     thread$out             ext entry (ptr, bit (18));
 85 
 86           dcl     (addr, addrel, baseno, bin, bit, divide, fixed, hbound, max, null, ptr, rel, string, substr) builtin;
 87 
 88 /* ^L */
 89 
 90           unthreaded = "0"b;                                /* This is not the unthreaded entry */
 91           no_pages = "0"b;
 92           goto MAKE_SDW_COMMON;
 93 
 94 
 95 unthreaded: entry (a_segno, a_tsdw, a_astep, a_ptp);        /* Entry for unthreaded AST entry */
 96 
 97           unthreaded = "1"b;
 98           no_pages = "0"b;
 99           goto MAKE_SDW_COMMON;
100 
101 no_pages: entry (a_segno, a_tsdw, a_astep, a_ptp);
102           no_pages = "1"b;
103           unthreaded = "0"b;                                /* thread in ! */
104 
105 MAKE_SDW_COMMON:
106 
107           sstp = addr (sst_seg$);
108           pvt_arrayp = addr (pvt$array);
109           sltp = addr (slt$);
110           sltep = addr (slt.seg (a_segno));                 /* Set pointer to slt entry. */
111           asp = addr (abs_seg$);                            /* Used to withdraw seg */
112 
113           pdsno = fixed (baseno (addr (pds$)), 17);
114           dsegno = fixed (baseno (addr (dseg$)), 17);
115           pl1_ops_no = fixed (baseno (addr (pl1_operators_$end_pl1_operators)), 17);
116           pl1_ops_pages = divide (fixed (rel (addr (pl1_operators_$end_pl1_operators)), 18) + 1023, 1024, 17, 0);
117           error_table_no = fixed (baseno (addr (error_table_$)), 17);
118 
119           namep = ptr (addr (name_table$), slte.names_ptr); /* get ptr to name */
120           do i = 1 to hbound (table_corresp, 1);            /* scan variable size table names */
121                if table_corresp (i).slt_name = namep -> segnam.name (1)
122                then do tbcp = null repeat (tbcp);           /* scan config deck for size spec */
123                          call config_$find (tbl_card_name, tbcp); /* get a card */
124                          if tbcp = null then go to no_card; /* no more in deck */
125                          do j = 1 to hbound (tbls_card.tbl_spec, 1); /* scan this card */
126                               if tbls_card.tbl_name (j) = table_corresp (i).card_name then do;
127                                         pts, save_pts = tbls_card.cur_length (j); /* get length from card */
128                                         slte_uns.max_length =
129                                              max (pts, slte_uns.max_length);
130                                         slte_uns.cur_length = pts; /* set from card */
131                                         go to got_pts;
132                                    end;
133                          end;
134                     end;
135           end;
136 
137 no_card:  pts = max (slte_uns.max_length, slte_uns.cur_length); /* get page table size */
138           if (pts = 0 | (slte.abs_seg & ^ no_pages)) & ^unthreaded then do; /* No aste for abs segs unless user insists */
139                                                             /* If void seg, don't create unless forced */
140                                                             /* Avoid routine creation of abs segs */
141                     a_astep, a_ptp = null ();               /* Don't try using it */
142                     a_tsdw = 0;                             /* Quick segfault */
143                     return;
144                end;
145 
146           if ^ slte.breakpointable & ^ no_pages & substr (slte_uns.access, 2, 1) then do;/* execute => breakpointable */
147                slte_uns.breakpointable = "1"b;
148                slte_uns.max_length = slte_uns.max_length + 1;
149                slte_uns.cur_length = slte_uns.cur_length + 1;
150                pts = pts + 1;
151           end;
152           save_pts = pts;
153 
154 got_pts:  do i = 3 to 0 by -1 while (sst.pts (i) >= pts);   /* find correct page table pool */
155           end;
156 
157           ptsi = i + 1;
158           loopcnt = 0;                                      /* zero counter */
159           pts = sst.pts (ptsi);                             /* specify page table size */
160 
161           do astep = ptr (sstp, sst.ausedp (ptsi)) /* look for an ASTE for the segment */
162                repeat ptr (sstp, aste.fp) /* skip to next ASTE for free one */
163                while (aste.usedf & /* until it's free or */
164                loopcnt <= fixed (sst.no_aste (ptsi), 17));  /* there are no more ASTE's */
165                loopcnt = loopcnt + 1;                       /* how many times through the loop */
166           end;
167 
168           if loopcnt > fixed (sst.no_aste (ptsi), 18) then /* too many times; pool is empty */
169                call syserr (1, "make_sdw: aste pool ^d too small", ptsi);
170 
171           call thread$out (astep, sst.ausedp (ptsi));       /* thread the entry out of the used list */
172           do i = 0 to sst.astsize - 2;                      /* zero the AST entry */
173                astep -> bfword (i) = 0;
174           end;
175 
176 /* ^L */
177 
178           aste.usedf = "1"b;                                /* mark it as being used */
179           a_ptp = addrel (astep, sst.astsize);              /* get a pointer to the page table */
180 
181           if slte.wired then do;                            /* if this a temp wired seg */
182                     if a_segno = pdsno then no_pages_wired = 1; /* wire first page of pds */
183                     else if a_segno = dsegno then no_pages_wired = 1; /* wire first page of dseg */
184                     else if a_segno = pl1_ops_no then no_pages_wired = pl1_ops_pages; /* wire just the first few pages */
185                     else if a_segno = error_table_no then no_pages_wired = 1;
186                     else no_pages_wired = save_pts;         /* otherwise wire all pages */
187                     sst.wired = sst.wired + no_pages_wired;
188                end;
189           else no_pages_wired = 0;
190 
191           do i = 0 to pts - 1;                              /* initialize the page table array for the entry */
192                call ptw_util_$make_null (addrel (a_ptp, i), make_sdw_null_addr);
193                if i < no_pages_wired then call ptw_util_$set_wired (addrel (a_ptp, i));
194           end;
195 
196           if slte_uns.breakpointable then
197                if no_pages_wired > 0 then do;               /* wired seg - use breakpoint_page */
198                     call ptw_util_$make_core (addrel (a_ptp, save_pts - 1), absadr (addr (breakpoint_page$), (0)));
199                     call ptw_util_$set_wired (addrel (a_ptp, save_pts - 1));
200                     if no_pages_wired = save_pts then sst.wired = sst.wired - 1;  /* wired was one too high from counting all pages as new wired pages */
201                end;
202 
203           if ^unthreaded                                    /* If threaded.. */
204           then if slte.temp_seg then call thread$cin (astep, sst.atempp);
205                else if slte.branch_required then call thread$cin (astep, sst.ausedp (ptsi));
206                else if slte.init_seg then call thread$cin (astep, sst.ainitp);
207                else if slte.wired then do;                  /* if this is wired then */
208                          unthreaded = "1"b;                 /* don't thread it */
209                          aste.hc = "1"b;                    /* and mark as hardcore */
210                     end;
211                else aste.hc = "1"b;
212 
213           a_tsdw = get_ptrs_$given_astep (astep);           /* Get initial SDW, */
214           call sdw_util_$dissect (addr (a_tsdw), addr (sdwi)); /* and find out what's in it now */
215           sdwi.size = save_pts * 1024;                      /* Set the size as appropriate for a paged segment */
216           string (sdwi.access) = slte.access;               /* Access from SLT entry */
217           if sys_info$system_type = L68_SYSTEM then /* And cache, if appropriate */
218                sdwi.cache = slte.cache;
219           call sdw_util_$construct (addr (a_tsdw), addr (sdwi)); /* and put it all back together again */
220 
221           aste.nqsw = "1"b;                                 /* turn on no quota switch */
222           aste.dnzp = "1"b;                                 /* never null hardcore pages */
223           aste.ddnp = "1"b;                                 /* Never report prewithdrawns to free */
224           aste.strp = bit (a_segno, 18);                    /* store segment number in AST */
225           aste.ehs = "1"b;                                  /* Turn entry hold switch on if appropriate */
226           aste.hc_sdw = "1"b;                               /* sdw for a hardcore seg so no trailer */
227           aste.vtocx = -1;                                  /* VTOCE-less segment */
228 
229           a_astep = astep;
230 
231 /* If disk abs seg, don't attempt to prewithdraw pages. */
232 
233           if no_pages then aste.csl, aste.records = bit (bin (slte_uns.cur_length, 9), 9);  /* so status_, et al, know about it */
234 
235           if slte.abs_seg | no_pages then return;           /* If abs_seg forced, don't prewithdraw */
236                                                             /* or if pages are to be supplied by the caller */
237 
238 /* Allocate a volume with a hardcore partition for the segment. */
239 
240           if hcp_thread = 0 then do;                        /* This gets interesting. */
241                     if sst.root_pvtx = 0 then do;           /* PVT created before init-pvt */
242                               aste.pvtx = -1;               /* Cause a fault if used. */
243                               return;
244                          end;
245                     call syserr (1, "make_sdw: no hardcore partitions available.");
246                end;
247 
248 /* Allocate deciduous segments on root phys vol */
249           if slte.branch_required then do;
250                     pvtx = sst.root_pvtx;
251                     pvtep = addr (pvt_array (pvtx));
252                     goto got_pvtx;
253                end;
254 
255           do pvtx = hcp_thread repeat pvte.brother_pvtx;
256                pvtep = addr (pvt_array (pvtx));
257                if pvte.nleft >= save_pts then go to got_pvtx;
258                if pvte.brother_pvtx = hcp_thread then call syserr
259                          (1, "make_sdw: out of hardcore partition for ^a.", namep -> segnam.name (1));
260           end;
261 got_pvtx:
262           hcp_thread = pvte.brother_pvtx;                   /* Keep chain rotating */
263           aste.pvtx = pvtx;                                 /* This is where seg will go. */
264           aste.hc_part = "1"b;                              /* Uses a hardcore partition */
265 
266 /* Touch all the pages, causing withdrawing nulled addresses against hc partition */
267 
268           call pmut$swap_sdw (asp, addr (a_tsdw));
269           do i = 0 to save_pts - 1;                         /* real cur length */
270                dummy = asp -> seg (i * 1024);               /* touch for nulled withdraw */
271           end;
272 
273           if slte.breakpointable then do;                   /* set sentinel in bkpt_page (keeps page from being nulled) */
274                sdwi.access.write = "1"b;
275                call sdw_util_$construct (addr (temp_sdw), addr (sdwi)); /* force access */
276                call pmut$swap_sdw (asp, addr (temp_sdw));
277                addrel (asp, (save_pts - 1) * 1024) -> bkpt_page.sentinel = BKPT_page_sentinel;
278           end;
279 
280           temp_sdw = 0;
281           call pmut$swap_sdw (asp, addr (temp_sdw));        /* clear slot */
282 
283           return;
284 
285 %page;
286 /* Entries to manage allocation from the Hardcore Partition
287 
288    thread_hcp adds a PVTE index to the thread
289 
290    reset_hcp terminates allocation from the Hardcore Partition
291 */
292 
293 thread_hcp:
294      entry (a_pvtx);
295 
296           pvt_arrayp = addr (pvt$array);
297           if hcp_thread = 0                                 /* This is the first pvtx */
298           then hcp_thread, hcp_first = a_pvtx;
299           else do;
300                     pvt_array (hcp_thread).brother_pvtx = a_pvtx;
301                     hcp_thread = a_pvtx;
302                end;
303 
304           pvt_array (a_pvtx).brother_pvtx = hcp_first;
305 
306           return;
307 
308 
309 reset_hcp:
310      entry;
311 
312           hcp_thread, hcp_first = 0;
313           return;
314 
315 
316 %page; %include aste;
317 %page; %include bce_breakpoint_page;
318 %page; %include mc;
319 %page; %include null_addresses;
320 %page; %include pvte;
321 %page; %include sdw_info;
322 %page; %include slt;
323 %page; %include slte;
324 %page; %include sst;
325 %page; %include system_types;
326 %page; %include variable_tables;
327 
328 /* ^L */
329 
330 /* BEGIN MESSAGE DOCUMENTATION
331 
332    Message:
333    make_sdw: XXXk ast pool to small.
334 
335    S: $crash
336 
337    T: $init
338 
339    M: There were not enough AST entries of size XXX k to allocate
340    the permanent AST entries of the supervisor.
341 
342    A: Increase the number of AST entries of that size, as specified on
343    the SST CONFIG card, substantially, and reboot.
344 
345    Message:
346    make_sdw: no hardcore partitions available.
347 
348    S: $crash
349 
350    T: $init
351 
352    M: No hardcore partitions were defined on any of the packs on the drives
353    specified by the ROOT CONFIG card. At least the RPV must have a hardcore
354    partition.  Supervisor segments cannot be created.
355 
356    A: If this is a cold boot, which is most likely, the RPV was
357    initialized without a hardcore partition.  It must be reinitialized.
358    Check the PART HC CONFIG card, one of which must describe the RPV
359    during a cold boot, and reboot.  If this is not a cold boot, the RPV
360    has been damaged, and volume recovery must be undertaken.
361 
362    Message:
363    make_sdw: out of hardcore partition for SEGNAME.
364 
365    S: $crash
366 
367    T: $init
368 
369    M: In attempting to allocate space for hardcore segment SEGNAME, no
370    more room could be found in any of the defined hardcore partitions.
371 
372    A: If this is a cold boot, redefine the hardcore partition of the RPV
373    to be larger.  At least 1000 (decimal) records is recommended.  Change
374    the PART HC CONFIG card describing the RPV to indicate this, and
375    reboot.  If this is not a cold boot, this situation is highly unlikely
376    and indicates damage to one or more RLV volume labels.  Volume
377    recovery for part or all of the RLV should be undertaken.
378 
379    END MESSAGE DOCUMENTATION */
380 
381      end make_sdw;