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 " HISTORY COMMENTS:
13 " 1) change87-06-22Fawcett, approve87-06-23MCR7734,
14 " audit87-07-14Farley, install87-07-17MR12.1-1043:
15 " Change the checking for the "mylock" on the ptl for after the first stac
16 " instructions indicates that the lock was in fact locked.
17 " END HISTORY COMMENTS
18
19
20 " " " " " " " "" " " " " " " " " " " " " " " " " " " " " " " " " " " "
21 "
22 " page_fault
23 "
24 " This is the major procedure of Multics page control. For details, see
25 " the Storage System PLM, Order Number AN61.
26 "
27 " Coded 1/70 by S.Webber
28 " Last Modified Date and Reason:
29 " Modified by S.Webber 07/01/71 to add page multilevel
30 " Modified by S.Webber 07/01/72 for followon
31 " Modified by S.Webber 10/01/73 to merge with privileged code
32 " Modified by B. Greenberg 06/10/74 for IOBM and put all cam/lock_ptl in page.
33 " Modified by B. Greenberg 11/12/74 for overlap-lookahead core control.
34 " Modified by B. Greenberg 02/05/75 for new storage system.
35 " Modified by S. Webber 02/05/76 for new reconfiguration
36 " Modified by B. Greenberg 03/08/76 for waiting on PTL
37 " Modified by B. Greenberg 05/13/76 for pdme's with uid/pageno
38 " Modified by B. Greenberg 12/76 for core_queue_man delay queue.
39 " Modified by B. Greenberg 3/31/77 for disk_emergency and new page_error.
40 " Modified by B. Greenberg 5/03/77 for page$pcleanup, aste.damaged.
41 " Modified by RE Mullen 5/13/77 for concurrent scheduler
42 " Modified by B. Greenberg 8/77 for pc_recover_sst, misc. cleanups.
43 " Modified by B. Greenberg 9/20/77 for disk offline waiting.
44 " Modified by B. Greenberg 3/15/78 for large sst, ptw.phm1
45 " Modified by B. Greenberg 5/1/78 for parity errors.
46 " Modified by D. Spector 2/20/79 for 18-bit unsigned quota
47 " Modified by B. Greenberg 2/79 for variable write_limit
48 " Modified by B. Greenberg 2/79 for 8-cpu port expander
49 " Modified by J. A. Bush 3/80 to store fault time in machine conditions
50 " Modified by B. Greenberg 6/23/80 for loop & unlock meters
51 " Modified by J. A. Bush 8/80 for the DPS8/70M CPU
52 " Modified by E.N. Kittlitz per WOS to not update PF count on gtus segments.
53 " Modified by E.N. Kittlitz 11/17/80 for new dtu/dtm calculation.
54 " Modified by J. Bongiovanni 1/81 for fault_counters
55 " Modified by M. Pierret 11/80 to use page pinning algorithm
56 " Modified by J. Bongiovanni 2/81 to remove cam/cache code
57 " Modified by W. Olin Sibert, 2/26/81, for ADP conversion, phase one
58 " Modified by C. Hornig, January 1982, to only CAM if segment accessible.
59 " Modified by J. Bongiovanni, January 1982, to remove PML code, add
60 " extended page fault trace type
61 " Modified by J. Bongiovanni, February 1982, for stocks
62 " Modified by E. N. Kittlitz, 6/21/82, summer solstice sacrifice of core map.
63 " Modified by J. Bongiovanni, July 1982, scs$trouble_processid, scavenger
64 " Modified by J. Bongiovanni, October 1982, synchronized segment support,
65 " don't decrement quota through zero
66 " Modified by E. N. Kittlitz Massachusetts agent for W.O. Sibert to pin those pages again.
67 " Modified by Keith Loepere, October 1983, for paged unpaged dseg and
68 " for bug fix to find_core loop.
69 " Modified by R. Coppola 10/13/83 to meter DF1 on per-cpu basis and
70 " added code to meter cache errors when mc_trace'ing
71 " Modified by BIM 83-12-03 for pgt_ IPS signal.
72 " Modified by TO 84-10-17 to remove write_limit and disk_run'ing.
73 " Modified by Keith Loepere, December 1984, for covert channel
74 " detection and a little cleanup.
75 " Modified by Keith Loepere, January 1985, for updated covert
76 " channel detection.
77 " Modified by Keith Loepere, January 1985, for fix to aste.records race.
78 " Modified by Tom Oke, February 1985, to remove a missed write_limit
79 " and disk run.
80 "^L
81 " The following entries exist within this procedure given by entry name to "page":
82 "
83 " done used by the paging DIMs to signal the completion
84 " of an I/O request.
85 "
86 " enter_data places an entry into the per-process trace table
87 "
88 " fault transferred to upon page faults from the fault vector
89 "
90 " lock_ptl used to lock the page table lock
91 "
92 " pccleanup used to get a page out of core
93 "
94 " pread used to read a page into core
95 "
96 " pwrite used to write a page out of core
97 "
98 " reset_working_set is obsolete and does nothing
99 "
100 " trace_marker places a user marker entry into the per-process
101 " trace table
102 "
103 " unlock_ptl used to unlock the page table lock
104 "
105 "
106 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
107
108 "
109 " ^L
110 "
111 " The very beginning
112 "
113 name page_fault
114
115
116 entry wait_return,pmut_unlock_ptl
117 entry ptl_wait_return
118
119 segdef check_accessible " See whether anyone can access segment
120 segdef cleanup_page " Evict one page from memory
121 segdef cme_offsets " Core map ITS pointers, 1 per cme word
122 segdef cme_0,cme_bp,cme_fp " ITS to word 0 of cme
123 segdef cme_1,cme_devadd,cme_flags " ITS to word 1 of cme
124 segdef cme_2,cme_astep,cme_ptwp " ITS to word 2 of cme
125 segdef cme_3,cme_pin_counter,cme_synch_page_entryp " ITS to word 3 of cme
126
127 segdef delete_mm_frame " Clear out and deconfigure main memory frame
128 segdef disk_offline_event " Wait event for disk offline
129 segdef disk_offlinep " Check whether disk is offline
130 segdef done " Post completion of I/O
131 segdef done_ " Post completion with PTL locked
132 segdef enter_data " Enter per-process trace data
133 segdef fault " Page Fault entry
134 segdef find_core_ " Find a frame of core
135 segdef init_savex " Init x7 save stack
136 segdef init_savex_bb " Init x7 save stack, set bb -> sst
137 segdef lock_ptl " Lock PTL
138 segdef lock_ptl_ext " Lock PTL from outside ALm PC
139 segdef lock_ptl_no_lp " Lock PTL, don't save lp
140 segdef my_lp " lp for bound_page_control
141 segdef notify_return " Side-door return from pxss$notify_page
142 segdef page_fault_error " Call to page_error - fatal
143 segdef pcleanup " Entry to get a page out of core
144 segdef pf_prs " Pointer to saved prs on page fault
145 segdef pf_scuinfo " Pointer to SCU data on page fault
146 segdef pre_page_info " Obsolete
147 segdef pread " Entry to read a page
148 segdef pwrite " Entry to write a page
149 segdef read_page_abs " Same as read_page, but OOPV not allowed
150 segdef reset_working_set " Obsolete
151 segdef savex " Save x7 in save stack for recursive use
152 segdef set_up_abs_seg " Setup abs_seg_1
153 segdef thread_in " Thread CME as MRU
154 segdef thread_lru_ext " Thread CME as LRU, ouside of ALM PC
155 segdef thread_out " Thread CME out of used list
156 segdef thread_to_lru " Thread CME as LRU
157 segdef trace_marker " Add user marker to per-process trace
158 segdef trace_restart_fault " Add restart_fault to per-process trace
159 segdef trace_scheduling " Add reschedule to per-process trace
160 segdef trace_signaller " Add signaller to per-process trace
161 segdef unlock_ptl " Unlock PTL
162 segdef unlock_ptl_ext " Unlock PTL, outside of ALM PC
163 segdef unsavex " Pop save stack, tra 0,x7
164 segdef unsavex_1 " Pop save stack, tra 1,x7
165 segdef unsavex_2 " Pop save stack, tra 2,x7
166 segdef write_page " Write page out if necessary
167 "^L
168
169 include page_regs
170 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
171 "
172 " Temporary storage, INCLUDE files, and constants
173 "
174 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
175
176
177 link prds_link,prds$
178 link abs_seg1_link,abs_seg1$
179
180 include stack_frame
181 include stack_header
182 include trace_types
183 include sys_trouble_codes
184 include mode_reg
185 include pxss_page_stack
186 include page_error_types
187 include page_info
188 include apte
189 include sst
190 include tc_meters
191 include wcte
192 include sdw
193 include ptw
194 include add_type
195 include aste
196 include cmp
197 include mc
198 include null_addresses
199 include static_handlers
200 include device_error
201 include mctseg
202 include fault_vector
203 include unpaged_page_tables
204 "^L
205 " check for wild transfers to bound_page_control|0
206
207 tsx5 page_fault_error "ERROR - TRA TO PAGE|0"
208 tsx5 page_fault_error "ERROR - TRA TO PAGE|1"
209 "
210 "
211 " The following code located at bound_page_control|2 is used for
212 " hardware debugging to make it easy to restart the last page
213 " fault via restoring the machine conditions and doing an RCU.
214 "
215 epplp my_lp,* restore page's linkage
216 eppap pds$page_fault_data
217 tra restart_fault
218
219 dec 0 " bpc|5 -- address_mask used to be here
220
221 " This location bound_page_control|6 is left unused so that
222 " obsolete patches of run limit write_limit will not crash system.
223 obsolete_wlim:
224 dec 0
225
226 even
227 pf_prs: its -1,1
228 pf_scuinfo:
229 its -1,1
230 my_lp:
231 its -1,1
232
233 cme_offsets: " set up by initialize_faults.
234 cme_0:
235 cme_bp:
236 cme_fp: its -1,0
237
238 cme_1:
239 cme_devadd:
240 cme_flags:
241 its -1,1
242
243 cme_2:
244 cme_ptwp:
245 cme_astep:
246 its -1,2
247
248 cme_3:
249 cme_pin_counter:
250 cme_synch_page_entryp:
251 its -1,3
252
253 sdw_bits: " Bits for abs-seg SDW -- it is
254 " Address 0, read/write, one unpaged page
255
256 iftarget L68 " SDW is different format for each
257 vfd 18/0,18/sdw.valid
258 vfd 1/0,14/1024/16-1,3/sdw.read+sdw.write,18/sdw.unpaged
259 ifend
260
261 iftarget ADP
262 vfd 18/0,18/sdw.valid
263 vfd 14/1024/16-1,4/0,18/sdw.read+sdw.write+sdw.unpaged
264 ifend
265
266 channel_mask_set:
267 oct 17,17
268
269 unnull_mask:
270 zero -1-ptw.nulled,-1 mask to resurrect an address
271
272 even
273 null: its -1,1
274 pc_signal_arglist:
275 vfd 18/6,18/4,18/0,18/0
276
277 "*********************************************************************
278 "*********************************************************************
279 "*********************************************************************
280 "********* **********
281 "********* HERE ARE THE CONSTANTS ... AND **********
282 "********* HERE BEGINS THE CODE OF PAGE_FAULT. **********
283 "********* **********
284 "*********************************************************************
285 "*********************************************************************
286 "*********************************************************************
287 "^L
288 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
289 "
290 " Subroutines:
291 "
292 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
293
294 lock_ptl:
295 sprilp sp|stack_frame.lp_ptr we don't do a normal 'entry' so ...
296 lock_ptl_no_lp:
297 epbpbb sst$ bb -> SST through out page
298 lda pds$processid lock the page table lock
299 stac sst|sst.ptl
300 tze ptl_ok branch if we think locked it
301 read_clock meter time waiting for lock
302 cmpa sst|sst.ptl check for mylock on page table lock
303 tze page_error$ptl_mylock complain if lock already set
304 staq pds$arg_1
305 lda pds$processid get set to lock again
306 ptl_repeat:
307 stac sst|sst.ptl hurry up and wait
308 nop
309 nop
310 tnz ptlfail locked, see if wait needed
311 read_clock
312 sbaq pds$arg_1
313 adaq sst|sst.loop_lock_time
314 staq sst|sst.loop_lock_time
315 increment sst|sst.loop_locks meter times we had to loop lock
316 ptl_ok:
317 lda pds$processid did we lock ok?
318 cmpa sst|sst.ptl
319 tze *+2
320 tsx5 page_fault_error "ERROR - PTL STAC FAILED"
321 tra 0,.ret
322
323 ptlfail:
324 cmpx .ret,pft_lret,du locking for page fault?
325 tnz ptl_repeat no, loop some more
326 read_clock account for partial pf time
327 sbaq pds$time_1 account for partial pf time
328 adaq tc_data$cpu_pf_time account for partial pf time
329 staq tc_data$cpu_pf_time account for partial pf time
330 tra pxss$ptl_wait yes, wait for lock
331
332 ptl_wait_return: "return location from pxss$ptl_wait
333 eppap pds$page_fault_data
334 read_clock account for rest of pf time
335 staq pds$time_1 account for rest of pf time
336 tra masked_switched_legal
337
338 pmut_unlock_ptl:
339 push
340 tsx .2ret,init_savex_bb
341 tsx .ret,unlock_ptl
342 eppap sp|stack_frame.arg_ptr,*
343 sprisp sb|stack_header.stack_end_ptr
344 eppsp sp|stack_frame.prev_sp,*
345 tra pmut$unwire_unmask
346 unlock_ptl_ext:
347 push
348 tsx .2ret,init_savex_bb
349 tsx .ret,unlock_ptl unlock the ptl
350 tra return
351
352
353 unlock_ptl:
354 tra core_queue_man$unlock_ptl Hoo, boy!
355
356 lock_ptl_ext:
357 eax .ret,.rt
358 tra lock_ptl_no_lp
359 .rt: short_return
360
361 non_fatal_error:
362 eax5 -1,.ret
363 tsx .2ret,page_error$non_fatal_error
364 tra 0,.ret
365
366 page_fault_error:
367 eax5 -1,5 set x5 to point to actual call to subroutine
368 tra page_error$page_fault_error die
369
370 init_savex_bb:
371 epp sst,sst$
372 init_savex:
373 eaa save_stack get address of save stack base
374 ora stack_size*64,dl set up a tally word for storing into save_stack
375 sta stackp stash this away
376 tra 0,.2ret return to the caller
377
378
379 savex:
380 stx .ret,stackp,id store x7 in save stack using tally word
381 ttf 0,.2ret return to the caller if tally not runout
382 tsx5 page_fault_error "ERROR - SAVE STACK OVERFLOW"
383
384 unsavex:
385 ldx .ret,stackp,di pop value of x7 also updating tally word properly
386 tra 0,.ret
387 unsavex_1:
388 ldx .ret,stackp,di pop value of x7 also updating tally word properly
389 tra 1,.ret
390
391 "^L
392 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""
393 " "
394 " Subroutines to manage used list threading "
395 " "
396 " "
397 " "
398 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
399
400 "
401 " Move an entry to least-recently-used place
402 "
403 thread_to_lru:
404
405
406 " assumes .cme -> cme
407
408 cmpx .cme,sst|sst.usedp see if already at lru point
409 tze 0,.ret leave it if so
410
411 szn cme_fp,*.cme make sure threaded in could be postpurge os
412 tmoz 0,.ret
413
414
415 "
416 " Load pointers to current brothers, thread out.
417 "
418 ldx .nxt,cme_fp,*.cme next
419 lxl .lst,cme_bp,*.cme previous
420
421 cmpx .cme,sst|sst.wusedp see if write point is on .cme
422 tnz *+2
423 stx .nxt,sst|sst.wusedp make writes start at next
424
425 " Thread out
426
427 stx .nxt,cme_fp,*.lst successorlast = successor
428 sxl .lst,cme_bp,*.nxt lastsuccessor = last
429
430 " Move to usedp
431
432 mv_to_usedp:
433 ldx .nxt,sst|sst.usedp point to successor to be
434
435 " See if usedp at wusedp. If so, back up wusedp.
436
437 cmpx .nxt,sst|sst.wusedp see if wusedp = usedp
438 tnz *+2 no, not equal.
439 stx .cme,sst|sst.wusedp our cme is new wused
440
441 stx .cme,sst|sst.usedp in any case, our cme is new used.
442
443 thread_behind:
444 lxl .lst,cme_bp,*.nxt point to last to be
445
446 " Thread to .cme
447
448 stx .cme,cme_fp,*.lst successor last = cme
449 sxl .cme,cme_bp,*.nxt last successor = cme
450
451 " Thread cme to environment
452
453 stx .nxt,cme_fp,*.cme successor cme = successor
454 sxl .lst,cme_bp,*.cme last cme = last
455
456 tra 0,.ret
457
458 "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "
459 " "
460 " Thread a cme out of the used list. "
461 " "
462 "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "
463
464 thread_out:
465
466 " Point to environment
467
468 ldx .nxt,cme_fp,*.cme successor = successor cme
469 tpnz *+2
470 tsx5 page_fault_error "ERROR - THREADING OUT UNTHREADED CME"
471
472 lxl .lst,cme_bp,*.cme last = last cme
473
474 " Make sure replacement and writing pointers are not
475 " looking at .cme.
476
477 cmpx .cme,sst|sst.usedp
478 tnz *+2
479 stx .nxt,sst|sst.usedp move usedp to successor if so
480
481 cmpx .cme,sst|sst.wusedp
482 tnz *+2
483 stx .nxt,sst|sst.wusedp
484
485 " Thread out
486
487 sxl .lst,cme_bp,*.nxt last successor = last
488 stx .nxt,cme_fp,*.lst successor last = successor
489
490 stz cme_fp,*.cme
491 tra 0,.ret
492
493 "^L
494 "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "
495 " "
496 " Thread an unthreaded entry to lru "
497 " "
498 " "
499 "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "
500
501 thread_in:
502 szn cme_fp,*.cme make sure not threaded in already
503 tmoz mv_to_usedp
504 tsx5 page_fault_error "ERROR - THREADING IN THREADED CME"
505
506 "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "
507 "
508 " Thread an unthreaded entry to MRU. "
509 " "
510 "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "" "
511
512 thread_in_mru:
513 ldx .nxt,sst|sst.wusedp thread in behind wusedp.
514 szn cme_fp,*.cme make sure not threaded in
515 tmoz thread_behind move behind wusedp
516 tsx5 page_fault_error "ERROR - MRU THREADING THREADED CME"
517
518 "
519 " External entry to thread to lru.
520 "
521 thread_lru_ext:
522 eppbp ap|2,* ap -> cmep
523 eax .cme,bp|0,*
524 epp sst,sst$ set up sst ptr
525 tsx .ret,thread_to_lru
526 short_return
527 "^L
528
529 inhibit on
530 even
531 meter_virtual_time:
532 lca 1,dl check for recursive metering
533 asa pds$vtime_count ..
534 tpl 0,.ret yes, do no more
535 read_clock get current value of CPU time
536 adl 96,dl add in correction delta
537 sbaq pds$cpu_time ..
538 sbaq pds$time_v_temp get time used for this fault/interrupt
539 staq pds$time_v_temp
540 adaq pds$virtual_delta save as virtual time increment
541 staq pds$virtual_delta ..
542 ldaq pds$time_v_temp also calculate total vcpu
543 adaq tc_data$+delta_vcpu
544 staq tc_data$+delta_vcpu
545 tra 0,.ret
546 inhibit off
547
548 set_up_abs_seg:
549 lda core_add
550 als coreadd_to_sdw.ls shift core addr into sdw pos
551 eaq 0 clear q-reg
552 oraq sdw_bits turn on other interesting bits
553 eppap abs_seg1$ get pointer to core area
554 ldx .tem,lp|abs_seg1_link get segno of abs_seg1
555 adlx .tem,lp|abs_seg1_link multiply by 2
556 staq dseg$,.tem store in descriptor segment
557 cams
558 tra 0,.2ret
559
560 store_pattern:
561 tsx .2ret,set_up_abs_seg get abs_seg1 ready
562 ldaq =vo36/777666333222,o36/444000111555
563 staq ap|0 and store it into the page
564 staq ap|1022 ..
565 tra 0,.ret
566
567 check_pattern:
568 tsx .2ret,set_up_abs_seg
569 ldaq =vo36/777666333222,o36/444000111555
570 cmpaq ap|0 if the same we have trouble
571 tze 1,.ret take error return
572 cmpaq ap|1022 try the last 2 words
573 tnz 0,.ret ok if not the same
574 tra 1,.ret bad news if the same
575
576 clear_core:
577 tsx .2ret,set_up_abs_seg make abs_seg1 point to core_add
578 eax .tem,4096 zero out 4096 characters
579 mlr ,prrl,fill0
580 desc9a 0,0
581 desc9a ap|0,x0 .tem
582 tra 0,.ret
583
584 check_for_zero: " assumes abs_seg1 setup
585 eppap abs_seg1$
586 eax .tem,4096 number of characters in a page
587 cmpc ,prrl,fill0
588 desc9a 0,0
589 desc9a ap|0,x0 .tem
590 tze 1,.ret
591 tra 0,.ret
592
593
594 " ^L
595 "
596 " The following subroutine reset_mode_reg is called before masking down.
597 " It therefore must be inhibited.
598 "
599 inhibit on
600 reset_mode_reg:
601 rsw 2 get cpu type in a
602 als mc.cpu_type_shift get the CPU type
603 ana mc.cpu_type_mask,du
604 stca ap|mc.cpu_type_word,70 store in machine conditions
605 arl 18-mc.cpu_type_shift position in au lower
606 eax4 0,au copy to x4
607 szn pds$mc_trace_sw is this process tracing machine conditions?
608 tpl no_trace_mc xfer if no
609 szn pds$mc_trace_seg Does user want to trace all M. Cs?
610 tze cp_hregs xfer if seg number zero
611 lda ap|mc.scu.ppr.psr_word look at the psr
612 ana scu.ppr.psr_mask,du and out everything except psr
613 cmpa pds$mc_trace_seg compare psr to object we are tracing
614 tze cp_hregs xfer if psr = object we are tracing
615 lda ap|mc.scu.tpr.tsr_word look at tsr
616 ana scu.tpr.tsr_mask,du and out everthing except tsr
617 cmpa pds$mc_trace_seg compare tsr to object we are tracing
618 tnz no_trace_mc do not trace if psr and tsr don't have seg
619 cp_hregs: scpr ap|mc.fim_temp,01 save fault register
620 ldaq ap|mc.fim_temp note that scpr does D.P. store and
621 sta ap|mc.fault_reg stores zeroes in mc.fault_reg
622 qrl mc.cpu_type_shift make room for cpu type
623 orq ap|mc.cpu_type_word or in cpu type
624 stcq ap|mc.cpu_type_word,70 store cpu type and ext fault reg
625 lda prds$processor_tag get cpu num
626 xec cache_ctr_tab,al lb=> per-cpu cache err ctrs
627 lda ap|mc.fault_reg reload PFR
628 ana =o10,dl cache dir parity bit 32?
629 tze check_efr no, go check EFR
630 aos lb|1 yes, increment the per-cpu ctr
631 check_efr:
632 anq mc.ext_fault_reg_mask,du mask unwanted bits OFF
633 tze no_efr no bits on, bypass
634 qls 2 get EFR bits in Q 1-17
635 eaa 0 set up A as incrementer
636 efr_loop:
637 ada 1,dl increment EFR slot number
638 qls 1 is this bit on?
639 tpnz efr_loop no, but some other bit on
640 tze no_efr no more EFR bits
641 aos lb|1,al increment EFR counter
642 tra efr_loop look for nxt EFR bit
643
644 no_efr: lprplb pds$mc_trace_buf get packed ptr to wired trace buffer
645 lxl5 lb|mctseg.hr_nxtad x5 = rel ptr to next H. R. storage location
646 cmpx5 lb|mctseg.hr_lim do we have to roll over the trace?
647 tmi hr_roll xfer if no
648 ldx5 lb|mctseg.hr_strt yes, pick up initial storage location
649 sxl5 lb|mctseg.hr_nxtad store new location
650 hr_roll: eax5 mctseg.hr_size,5 increment storage location
651 sxl5 lb|mctseg.hr_nxtad set rel ptr to next H. R. storage location
652 epplb lb|-mctseg.hr_size,5 lp -> current HR storage location
653 ldq 2,du get a 2 for stepping address
654 eax6 4 4 blocks of
655 scpr1: eax5 16 16 history registers
656 eax3 0 set up for L68 CPU type initally
657 cmpx4 1,du is this a DPS8/70M CPU?
658 tnz scpr2 xfer if no, it is L68
659 eax3 48 yes, set up to skip first 48 hregs
660 cmpx6 3,du DU hreg? Don't have one on DPS8/70M
661 tnz scpr2 no, go execute it
662 mlr ,pr,fill0 zero out this 32 word block
663 desc9a 0,0
664 desc9a lb|64,32*4
665 eax6 -1,6 yes, skip it
666 scpr2: lda scpr-1,6 get correct instruction
667 sta ap|mc.fim_temp save in stack
668 scpr3: xec ap|mc.fim_temp execute the instruction
669 cmpx3 0,du are we through skipping hregs?
670 tze scpr4 yes, go increment address
671 eax3 -1,3 no, skip another
672 tra scpr3 and go execute scpr again
673
674 scpr4: asq ap|mc.fim_temp increment address of instruction
675 eax5 -1,5 count down
676 tnz scpr3 more of this 16 double word block
677 eax6 -1,6 count down
678 tnz scpr1 another kind of hreg
679
680 eax5 64 initially set clear count to 64
681 cmpx4 1,du is this a DPS8/70M CPU?
682 tze *+2 yes, clear all 64 hregs
683 eax5 16 no, clear only 16 hregs
684 lcpr 0,03 set all history regs to zero
685 eax5 -1,5 count down
686 tpnz *-2 xfer if more to do
687 eawplb 0
688 trace_mc:
689 lxl5 lb|mctseg.mc_nxtad x5 = rel ptr to next M. C. storage loc
690 cmpx5 lb|mctseg.mc_lim do we have to roll over the trace?
691 tmi mc_roll xfer if no
692 ldx5 lb|mctseg.mc_strt yes, pick up initial storage location
693 sxl5 lb|mctseg.mc_nxtad store new location
694 mc_roll:
695 eax5 mctseg.mc_size,5 increment storage location
696 sxl5 lb|mctseg.mc_nxtad set rel ptr to next M. C. storage location
697 epplb lb|-mctseg.mc_size,5 lp -> current MC storage location
698 mlr pr,pr move the data to wired buffer
699 desc9a ap|0,mctseg.mc_size*4
700 desc9a lb|0,mctseg.mc_size*4
701 no_trace_mc:
702 epplb prds$cache_luf_reg reset cache control reg
703 lcpr lb|0,02 lcpr to reload luf and cache control
704 lda prds$mode_reg retrieve template mode reg
705 ora mr.enable_mr+mr.enable_hist,dl enable mode reg and hist regs
706 sta prds$mode_reg_enabled save this mode reg value
707 epplb prds$mode_reg_enabled get pointer to temp mode reg value
708 lcpr lb|0,04 reload the mode register
709 tra 0,.ret return to caller
710
711 scpr: scpr lb|0,40 OU History Regs for L68, OU/DU for DPS8
712 scpr lb|32,20 CU History Regs
713 scpr lb|64,10 DU History Regs for L68, not used for DPS8
714 scpr lb|96,00 APU History Regs
715
716 cache_ctr_tab:
717 epplb wired_hardcore_data$cpu_a_cache_err_ctr_array
718 epplb wired_hardcore_data$cpu_b_cache_err_ctr_array
719 epplb wired_hardcore_data$cpu_c_cache_err_ctr_array
720 epplb wired_hardcore_data$cpu_d_cache_err_ctr_array
721 epplb wired_hardcore_data$cpu_e_cache_err_ctr_array
722 epplb wired_hardcore_data$cpu_f_cache_err_ctr_array
723 epplb wired_hardcore_data$cpu_g_cache_err_ctr_array
724 epplb wired_hardcore_data$cpu_h_cache_err_ctr_array
725
726 fault_ctr_table:
727 eppab wired_hardcore_data$cpu_a_flt_ctr_array
728 eppab wired_hardcore_data$cpu_b_flt_ctr_array
729 eppab wired_hardcore_data$cpu_c_flt_ctr_array
730 eppab wired_hardcore_data$cpu_d_flt_ctr_array
731 eppab wired_hardcore_data$cpu_e_flt_ctr_array
732 eppab wired_hardcore_data$cpu_f_flt_ctr_array
733 eppab wired_hardcore_data$cpu_g_flt_ctr_array
734 eppab wired_hardcore_data$cpu_h_flt_ctr_array
735
736 inhibit off
737
738 get_pvtx:
739 lda ast|aste.pvtx_word,.aste
740 arl aste.pvtx_shift
741 ana aste.pvtx_mask,dl
742 sta pvtx
743 tra 0,.ret
744
745
746 " ^L
747 " " " " " " " " " " " " " " "
748 "
749 " enter_data -- entry to add data to the 'system trace list'
750 " Call is:
751 "
752 " call page$enter_datadata_word type
753 "
754 " where data_word is a word value to be
755 " entered into the next available slot in the trace
756 " list. If type = 0 page fault type then a return is
757 " done and the entry is not placed in the list.
758 "
759 " " " " " " " " " " " " " " " " " " " " "
760
761 include sys_trace
762
763 trace_signaller:
764 epplp my_lp,* set linkage pointer
765 lda pds$condition_name get first four characters of name
766 ldq pds$condition_name+1
767 lls 9 shift out ACC count field
768 ldq signaller_type,du get coded type
769 tsx .ret,enter
770 tra lb|0 return via special code
771
772 trace_restart_fault:
773 epplp my_lp,*
774 eaa 0 code for restart is zero
775 ldq restart_fault_type,du
776 tsx .ret,enter
777 tra lb|0 return via special code
778
779 trace_marker:
780 lda ap|2,* get char string to use as marker
781 ldq marker_type,du set type appropriately
782 tsx .ret,enter
783 short_return
784
785 trace_scheduling:
786 eaa 0 code word is all zeros
787 ldq reschedule_type,du get type code
788 tra enter
789
790 enter_data:
791 lda ap|2,* pick up the data_word
792 ldq ap|4,* make sure non-zero type given
793 qls 30 left justify
794 tze short_return return if illegal type given
795 tsx .ret,enter
796 short_return:
797 short_return
798
799 return: return
800
801 "
802 " Subroutine to enter a page fault into the system-trace list
803 "
804 page_util_enter:
805 stx .aste,temp astep
806 eax .tem,-aste_size,.ptw PTW addr - ASTE size
807 sblx .tem,temp page number
808 anx .tem,=o377,du only significant bits
809
810 szn tc_data$post_purge_switch are we post-purging?
811 tze extended_page_util_enter no -- we can stuff more data into trace
812
813 " We are post-purging, so we need old format trace entry
814
815 ldq pds$page_fault_data+mc.scu.tpr.tsr_word get segno in q
816 eaa 0,.aste get astep in a-reg
817 arl 18
818 lls 18 fabricate entire code word
819 eaq 0,.tem page number low order bits in upper
820 tra enter
821
822 extended_page_util_enter:
823 lda pds$page_fault_data+mc.scu.ppr.psr_word PPR in AU
824 ana =o7777,du Low-order bits only
825 arl 18 PPR in AL
826 ldq pds$page_fault_data+mc.scu.ilc_word IC in QU
827 anq -1,du strip out garbage indicators
828 lls 18+6 1st 30 bits or first word
829 sta temp
830 lda pds$page_fault_data+mc.scu.ppr.psr_word PPR in AU
831 ldq pds$page_fault_data+mc.scu.cu_stat_word CU status bits
832 canq scu.cu.if,dl fault on instruction fetch
833 tnz *+2 yes - use PPR
834 lda pds$page_fault_data+mc.scu.tpr.tsr_word no - use TSR
835 ana =o7777,du Low-order bits only
836 arl 18 segno in AL
837 eaq 0,.tem pageno in QU
838 qls 18-8
839 lrl 6
840 qrl 6
841 ora temp
842 orq extended_page_fault_type,du
843
844 enter: eppap pds$trace get pointer to trace structure
845 ldx .tem,ap|trace.next_free_word get current index to next free slot
846 staq ap|trace.data,.tem save coded information
847 read_clock
848 sbaq ap|trace.ttime get incremental time
849 stq ap|trace.temp save in temporary
850 adaq ap|trace.ttime recalculate last fault time
851 staq ap|trace.ttime
852 ldq ap|trace.temp retrieve delta-time
853 qrl 6 in terms of 64 micro-seconds
854 cmpq =o177777,dl see if time is too large
855 tmi *+2 no, use it
856 ldq =o177777,dl yes, time is too large, use standard large value
857 orsq ap|trace.data+1,.tem OR time value into trace entry
858 eax .tem,2,.tem bump entry index
859 cmpx .tem,ap|trace.last_available_word check for wrap-around
860 tnz trace.no_wrap not now, though
861 eax .tem,0 we wrapped. reset to beginning
862 trace.no_wrap:
863 cmpx .tem,ap|trace.threshold_word signal?
864 tnz trace.no_signal nope
865 lda ap|trace.send_ips_word Signals enabled?
866 cana trace.send_ips,dl
867 tze trace.no_signal
868 eppbp pds$apt_ptr,* no need to lock, we use stacq
869 trace.retry_ips:
870 lda sys_info$pgt_mask This cannot recurse,
871 ora bp|apte.ips_message since we only test EQUAL to
872 ldq bp|apte.ips_message threshold. The pgt_ trace
873 stacq bp|apte.ips_message will be GREATER.
874 tnz trace.retry_ips
875 lda 1,dl set ring alarm
876 sta pds$alarm_ring store in simulated spot
877 lra pds$alarm_ring set for real
878 trace.no_signal:
879 stx .tem,ap|trace.next_free_word
880
881 tra 0,.ret
882
883
884 reset_working_set:
885 short_return
886
887 pre_page_info:
888 stz ap|4,* pre-page calls
889 stz ap|6,* paging device page faults
890 stz ap|8,* no pre-paging
891 short_return
892 "^L
893
894 " quota primitives - check for RQO, decrement quota, increment quota
895
896 check_quota:
897 lda ptw|0 inspect ptw
898 cana add_type.non_null,dl see if not_null address
899 tze check_quota.real_null
900 als 0
901 tpl 0,.ret real address, return
902
903 check_quota.real_null:
904 tsx .2ret,type_terminal_quota
905 tra *+2 seg quota
906 tra 0,.ret dir quota, skip it for now
907
908 eax .tem,0,.aste loop up parents
909 quota_c: lxl .tem,ast|aste.par_astep,.tem get father
910 cana ast|aste.tqsw_word,.tem see if terminal
911 tze quota_c no, loop up
912
913 szn pds$quota_inhib special consideration?
914 tnz 0,.ret yes, return
915
916 lda entry_sw don't check on read entry
917 cmpa read_entry,dl
918 tze 0,.ret read entry, don't check
919
920 lda ap|mc.scu.tpr.trr_word get ring of faulting reference
921 cana scu.tpr.trr_mask,du see if in ring 0
922 tze 0,.ret yes, don't check quota
923
924 ldx .2ret,ast|aste.used,.tem check seg quota for over
925 cmpx .2ret,ast|aste.quota,.tem
926 tnc 0,.ret not over quota, return
927 lda PAGE_ERROR_RQO,dl type of error to signal
928 eppab ast|0,.tem ASTE of quota account
929 tra errquit
930
931 " subtract 1 from quota cell
932
933 reset_quota:
934 eax .tem,0,.aste start at current aste
935 tsx .2ret,type_terminal_quota find quota parent
936 lxl .tem,ast|aste.par_astep,.tem seg quota applies to parent
937
938 quota_r: xec quota.lx,ql fetch correct cell
939 tze *+3 don't decrement thru 0
940 sblx .2ret,1,du
941 xec quota.sx,ql save back
942 cana ast|aste.tqsw_word,.tem stop at terminal account
943 tnz 0,.ret
944 lxl .tem,ast|aste.par_astep,.tem parent cell
945 tra quota_r
946
947 " add 1 to quota cell
948
949 bump_quota:
950 lda aste.fmchanged,du turn on fmchanged
951 orsa ast|aste.fmchanged_word,.aste
952
953 eax .tem,0,.aste start at current aste
954 tsx .2ret,type_terminal_quota find quota parent
955 lxl .tem,ast|aste.par_astep,.tem seg quota applies to parent
956
957 quota_b: xec quota.lx,ql fetch correct cell
958 adlx .2ret,1,du
959 xec quota.sx,ql save back
960 cana ast|aste.tqsw_word,.tem stop at terminal account
961 tnz 0,.ret
962 lxl .tem,ast|aste.par_astep,.tem parent cell
963 tra quota_b
964
965 bump_quota_covert_check:
966
967 " Add 1 to quota cell, also check that there exists a terminal quota node
968 " before the first upgraded node. This should be used only for dirs,
969 " so that we don't require terminal dir quota for upgraded dirs.
970
971 lda aste.fmchanged,du turn on fmchanged
972 orsa ast|aste.fmchanged_word,.aste
973
974 eax .tem,0,.aste start at current aste
975 tsx .2ret,type_terminal_quota find quota parent
976 lxl .tem,ast|aste.par_astep,.tem seg quota applies to parent
977 ora aste.multi_class,du we will "stop" on terminal
978 " node or upgraded node
979 stz temp assume terminal-ness
980
981 quota_bc: xec quota.lx,ql fetch correct cell
982 adlx .2ret,1,du
983 xec quota.sx,ql save back
984 cana ast|aste.tqsw_word,.tem look at tqsw and multi_class
985 tze quota_bc_next neither upgraded nor terminal
986
987 lxl .2ret,ast|aste.tqsw_word,.tem terminal half-word
988 canx .2ret,quota.tq_mask,ql
989 tnz quota_bc_term terminal found
990 sta temp upgraded found first
991 quota_bc_next:
992 lxl .tem,ast|aste.par_astep,.tem parent cell
993 tra quota_bc
994
995 quota_bc_term:
996 lda temp
997 tnz 0,.ret upgraded found first
998 tra 1,.ret terminal-ness okay
999
1000 " determines type of quota seg/dir, returns to call+1/2 so depending
1001 " also sets a to have corresponding mask bit for tqsw,
1002 " q to have a 0/1 corresponding to seg/dir
1003
1004 type_terminal_quota:
1005 lda ast|aste.nqsw_word,.aste special seg?
1006 cana aste.nqsw,dl ..
1007 tnz 0,.ret leave whole biz if so
1008
1009 cana aste.dirsw,dl dirsw_word same as nqsw_word
1010 tnz type.dir_quota
1011
1012 lda aste.tqsw,dl seg quota type
1013 ldq 0,dl
1014 tra 0,.2ret
1015 type.dir_quota:
1016 lda aste.tqsw/2,dl
1017 ldq 1,dl
1018 tra 1,.2ret
1019
1020 quota.lx: ldx .2ret,ast|aste.used,.tem instructions to load desired
1021 lxl .2ret,ast|aste.used,.tem quota cell
1022
1023 quota.sx: stx .2ret,ast|aste.used,.tem instructions to store desired
1024 sxl .2ret,ast|aste.used,.tem quota cell
1025
1026 quota.tq_mask:
1027 arg aste.tqsw values for checking for tqsw
1028 arg aste.tqsw/2 in bump_quota_covert_check
1029 "^L
1030 " " " " " " " " " " " " " " " " " " " " " " " "
1031 "
1032 " check_accessible subroutine to check if any processor can access
1033 " the page in question. This tells us whether to
1034 " clear all the AM's.
1035 "
1036 " " " " " " " " " " " " " " " " " " " " " " " "
1037
1038 check_accessible:
1039 ldx .tem,ast|aste.strp,.aste " get aste.strp
1040 tnz 0,.2ret " must CAM
1041 lda ast|aste.hc_sdw_word,.aste " check for HC segment
1042 cana aste.hc_sdw,du " aste.hc_sdw?
1043 tnz 0,.2ret " yes, CAM
1044 " volmap_seg_word same as hc_sdw_word
1045 cana aste.volmap_seg,dl " aste.volmap_seg?
1046 tnz 0,.2ret " yes, CAM
1047 tra 1,.2ret " we save some connects!
1048 "^L
1049 " " " " " " " " " " " " " " " " " " " " " " " " "
1050 "
1051 " Routines to check for pages of synchronized segments
1052 "
1053 "
1054 " On evict, do housekeeping
1055 "
1056 " tsx7 check_synch_cleanup
1057 "
1058 " On write, check if page must be held
1059 "
1060 " tsx7 check_for_synch_hold
1061 " <return if page cannot be written>
1062 " <normal return>
1063 "
1064 " " " " " " " " " " " " " " " " " " " " " " " " "
1065
1066
1067 check_synch_cleanup:
1068 lda cme_flags,*.cme
1069 cana cme.synch_held,dl synchronized page
1070 tze 0,.ret no
1071 tra page_synch$cleanup return to 0,x7
1072
1073 check_for_synch_hold:
1074 lda ast|aste.synchronized_word,.aste
1075 cana aste.synchronized,dl synchronized page
1076 tze 1,.ret no
1077 tsx .2ret,savex recursive use of x7
1078 tsx .ret,page_synch$write check whether we should write
1079 tra unsavex do not write
1080 tra unsavex_1 write OK
1081
1082 "^L
1083 " " " " " " " " " " " " " " " " " " " " " " " "
1084 "
1085 " update_csl subroutine to make sure the csl
1086 " for a segment is correct. It is called
1087 " when a page is found to be zero,
1088 " either by being modified to zeroes or
1089 " by being a non-modified null address.
1090 "
1091 " " " " " " " " " " " " " " " " " " " " " " " " "
1092
1093 update_csl:
1094 stz temp zero out entire word
1095 stz temp+1 and next as well
1096 eax .tem,aste_size,.aste get a pointer to the page table
1097 stx .tem,temp save for now
1098 stx .tem,temp+1
1099 eax .tem,1,.ptw get page number by subtracting base of PT from ptp
1100 sblx .tem,temp add 1 to get csl
1101 stx .tem,temp
1102 lda ast|aste.csl_word,.aste pick up csl of segment
1103 ana aste.csl_mask_inner,du
1104 arl aste.csl_shift-18 shift to upper a, right justified
1105 cmpa temp compare with page number
1106 tnz 0,.ret not the same, don't change csl
1107 eax .tem,-1,.ptw start search at previous page
1108 cmpx .tem,temp+1 end search at first page of segment
1109 tnc up_csl.set_csl done at page zero
1110 ldq ptw.valid,dl get in core flag for compares
1111 csl_loop:
1112 canq sst|0,.tem is current page in core ?
1113 tnz up_csl.set_csl yes, stop and set csl here
1114 lda sst|0,.tem get ptw
1115 cana add_type.non_null,dl is there a real address?
1116 tze up_csl.dont_count
1117 als 0 test sign
1118 tpl up_csl.set_csl real disk address
1119 up_csl.dont_count:
1120 eax .tem,-1,.tem go to previous PTW
1121 cmpx .tem,temp+1 are we passed the start ?
1122 trc csl_loop no, loop back and check this page
1123 up_csl.set_csl:
1124 "update csl into AST entry
1125 eaa 1,.tem get curerrent ptp +1 to convert to csl format
1126 sbla temp+1 subtract out base of page table
1127 als aste.csl_shift-18 shift to position in AST entry
1128 era ast|aste.csl_word,.aste and store in AST entry
1129 ana aste.csl_mask_inner,du
1130 ersa ast|aste.csl_word,.aste
1131 tra 0,.ret return
1132
1133 " ^L
1134 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1135 "
1136 " fault
1137 "
1138 " This entry is transferred to from the fault vector when a page fault
1139 " occurs. The pointers, registers, etc. must be saved...
1140 "
1141 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1142
1143 even
1144 fault:
1145 inhibit on
1146 spri pf_prs,*
1147 eppap pf_prs,* get pointer to MC
1148 sreg ap|mc.regs save registers
1149 spl ap|mc.eis_info
1150 epplp my_lp,* set up linkage pointer
1151 read_clock start metering
1152 staq ap|mc.fault_time save fault time in machine conditions
1153 staq pds$time_1 and in pds
1154 aos pds$vtime_count check for recursive virtual metering
1155 tpnz already_metering ..
1156 sbaq pds$cpu_time calculate virtual time
1157 staq pds$time_v_temp save until RCU time
1158 already_metering:
1159 tsx .ret,reset_mode_reg reset mode register turn on history regs
1160
1161 rsw 0 get set for possible tracing
1162 sta sst$+sst.trace_sw
1163
1164 lxl1 prds$processor_tag get set for masking
1165 lprpab scs$mask_ptr,1
1166 xec scs$read_mask,1
1167 staq ap|mc.mask
1168 ldaq scs$sys_level
1169 xec scs$set_mask,1
1170 xec fault_ctr_table,1 AB => per-cpu fault ctr array
1171 aos ab|0+FAULT_NO_DF1
1172 inhibit off
1173
1174 eppab sp|0 save sp in ab
1175 eppsp prds$+stack_header.stack_begin_ptr,* get set for push macro
1176 epbpsb sp|0 set stack base pointer
1177 push
1178
1179 spriab sp|stack_frame.prev_sp now save previous sp
1180 lca scu.ir.parm+1,dl make sure parity mask is OFF
1181 ansa ap|mc.scu.indicators_word
1182
1183 "
1184 " The following code checks to make sure we don't get a fault while
1185 " we're on the PRDS.
1186 "
1187 lxl7 ap|mc.prs+6*2 however, if were not in ring 0, OK
1188 canx7 =o700000,du
1189 tnz masked_switched_legal not in ring 0, OK
1190 ldx7 ap|mc.prs+6*2 get SP at time of fault
1191 cmpx7 lp|prds_link compare segment number to that of PRDS
1192 tze fault_while_on_prds bad news, return to bos
1193 masked_switched_legal:
1194
1195 tsx .2ret,init_savex initialize save_stack for x7
1196 tsx .ret,lock_ptl lock the page table lock
1197 pft_lret:
1198
1199 stz entry_sw fault entry, set switch
1200 stz ap|mc.errcode zero error code for later use
1201
1202 eppap pds$page_fault_data restore pointer to fault data
1203 epplb dseg$ get pointer to descriptor segment
1204
1205 " If a page fault is taken during an instruction fetch then the CU status
1206 " bit IF instruction fetch will be ON.
1207
1208 lxl1 ap|mc.scu.cu_stat_word Get CU status bits
1209 canx1 scu.cu.if,du Is IF bit ON?
1210 tze regular_page_fault not on, must be normal one so use TSR
1211
1212 lda ap|mc.scu.ppr.psr_word For an IF page fault the PSR is valid
1213 lxl1 ap|mc.scu.apu_stat_word Reset x1 to APU status bits.
1214 tra all_page_faults Go join normal path
1215 regular_page_fault:
1216 lxl1 ap|mc.scu.apu_stat_word see what type of fault
1217 canx1 scu.apu.ptw+scu.apu.dsptw+scu.apu.ptw2,du is it a normal page fault?
1218 tnz *+2 if one of these bits is on we're OK
1219 tsx5 page_fault_error "ERROR - BAD SCU DATA NO APU BITS"
1220 lda ap|mc.scu.tpr.tsr_word This is the normal path. The segno is in TSR
1221
1222 all_page_faults:
1223 ldq ap|mc.scu.ca_word page number is derived from CA field
1224 canx1 scu.apu.ptw2,du is it a pre-page decimal instruction
1225 tze *+2 no, don't increment page number
1226 adlq 1024,du yes, up the page number by 1
1227 ana scu.tpr.tsr_mask,du leave just the segno in AU
1228 sta temp save for bound comparison.
1229 als 1 multiply by sdw size
1230 eax .tem,0,au put in x0
1231 lda lb|1 get DSEG sdw bounds word bound 377770
1232 ora =o7,du convert bounds to max segno
1233 cmpa temp this is segno 377770000000
1234 tmi bad_segno Segno out of reason.
1235 stq temp save tsr word offset
1236 ldaq lb|0 get addr of descriptor segment from its sdw DBR
1237 arl sdw.add_shift move to fixed bin
1238 " see if dseg paged
1239 sbla unpaged_page_tables$0+upt.sst_absloc convert to page table pointer
1240 tmi not_dseg unpaged page tables are below sst
1241 eppbp sst|0,al make bp point to first page table word
1242 eaa 0,.tem get two times segno
1243 arl 10 get page number of dseg
1244
1245 canx1 scu.apu.dsptw,du Is this a page fault on the dseg?
1246 tnz dseg_page_fault Yes, skip the following code
1247
1248 lda ptw|0,au get correct PTW for dseg
1249 cana ptw.valid,dl ..
1250 tze quit there is fault, go take it
1251 not_dseg:
1252 ldaq lb|0,.tem look for seg-fault, get sdw of segment
1253 cana sdw.valid,dl see if directed fault set
1254 tze quit go handle seg-fault
1255 staq pf_sdw save access fields
1256 arl 36-24 move to fixed bin
1257 sbla sst|sst.ptwbase no seg-fault, get page table index
1258 eppbp sst|0,al get the astep +aste_size
1259 ldq temp get back word offset
1260 qrl page_power convert to page number
1261 tra found_faulted_page skip code for dseg faults
1262
1263 dseg_page_fault:
1264 stq pf_sdw+1 address word doesn't matter for dseg
1265 eaq 0,au copy page number into q
1266 found_faulted_page:
1267 eax .aste,ptw|-aste_size get real astep into x3
1268 eppbp ptw|0,qu adjust ptwp to point to the actual PTW
1269 eax .ptw,ptw|0 and save it in x2
1270
1271 ldq ptw|0 get PTW in q-reg
1272 canq ptw.valid,dl see if fault still exists
1273 tnz quit no, return
1274 canq ptw.os,dl is the page out of service?
1275 tnz short_page_fault process short pf
1276 canq ptw.er,dl is page in error from earlier read?
1277 tnz page_read_error yes, signal an error.
1278
1279 lda ast|aste.npfs_word,.aste see if no-page-fault-switch is on
1280 cana aste.npfs,du ..
1281 tnz create_segment_fault
1282
1283
1284 "
1285 " Here the commitment has been made to actually
1286 " read in one page of virtual memory.
1287 "
1288
1289 tsx .ret,pc_trace$page_fault
1290
1291
1292 tsx .ret,read_page
1293 tra readin.goon must wait for page
1294 tra readin.goon
1295 tra wait_any_event_apte wait for volmap event in APTE by now
1296
1297 readin.goon:
1298 tsx .ret,pc_trace$page_fault_end
1299 tsx .ret,page_util_enter enter the page in the trace list
1300 "
1301 " The following are various per-process meters about paging activity
1302 " as well as some system meters about where page faults are
1303 " happening.
1304 "
1305 lda ast|aste.per_process_word,.aste count pdir faults
1306 cana aste.per_process,du
1307 tze *+2
1308 increment sst|sst.pdir_page_faults
1309
1310 lxl .tem,ast|aste.par_astep,.aste count faults in segs off dirs off root
1311 lxl .tem,ast|aste.par_astep,.tem
1312 cmpx .tem,sst|sst.root_astep+1
1313 tnz *+2
1314 increment sst|sst.level_1_page_faults
1315
1316 lda ast|aste.dirsw_word,.aste count dir pfts
1317 cana aste.dirsw,dl
1318 tze readin.meter_ndir_pft meter in AST
1319 increment sst|sst.dir_page_faults
1320 tra readin.meter_sgdir_join
1321
1322 readin.meter_ndir_pft: "count in ASTE
1323 cana aste.gtus,du " gtus in same word as dirsw
1324 tnz readin.meter_sgdir_join " if transparent, can't count faults
1325 lda ast|seg_aste.usage,.aste
1326 adla 1,dl LOGICAL arith, please
1327 sta ast|seg_aste.usage,.aste
1328
1329 readin.meter_sgdir_join:
1330 lda pds$page_fault_data+mc.scu.tpr.trr_word count ring 0 page faults
1331 cana scu.tpr.trr_mask,du
1332 tnz *+2
1333 increment sst|sst.ring_0_page_faults
1334
1335 aos pds$page_waits meter page waits
1336 aos pds$number_of_pages_in_use
1337 ldq sst|sst.nused number of available pages
1338 eppbb pds$apt_ptr,* can also be used to reference tc_data
1339 epbpbp bb|0 get pointer to base of apt
1340 lda tc_data$n_eligible make sure it isn't zero can it ever be?
1341 tze no_eligible
1342 sta temp
1343 div temp divide by the eligibility
1344 eaa 0 clear a-reg
1345 staq temp save measurement
1346 cmpq pds$number_of_pages_in_use are we in equilibrium
1347 tmi in_equilibrium yes
1348 ldq pds$number_of_pages_in_use until then use this value
1349 staq temp save it as the measure
1350 asq temp+1 which is doubled when not in equilibrium
1351 in_equilibrium:
1352 adaq bp|cumulative_memory_usage
1353 staq bp|cumulative_memory_usage
1354 ldaq temp reload measure for updating apte.paging_measure
1355 adaq bb|apte.paging_measure add the paging measure
1356 staq bb|apte.paging_measure and save it again
1357
1358 no_eligible:
1359 ldx2 bb|apte.wct_index
1360 tze skip_pinning no WCTEs yet initialization
1361 " bp -> to base of apt set above
1362 lxl .tem,bp|wcte.pin_weight,2 get pin weight
1363 stx .tem,cme_pin_counter,*.cme
1364
1365 skip_pinning:
1366 epp sst,sst$ restore sst ptr
1367
1368 sxl .cme,cmep save cmep
1369 tsx .ret,claim_mod_core write out mod pages
1370 lxl .cme,cmep
1371 ldx .ptw,ptp_astep reload .ptw
1372 lxl .aste,ptp_astep and .aste
1373
1374 eppbp tc_data$ restore tcd ptr
1375 read_clock meter page fault time
1376 sbaq pds$time_1 get cpu time for this fault
1377 adaq bp|cpu_pf_time keep sum of times
1378 staq bp|cpu_pf_time
1379 aos bp|cpu_pf_count and count of faults
1380
1381 "
1382 "
1383 " Wait for the page fault as appropriate.
1384 "
1385 epp ptw,sst|0,.ptw
1386
1387
1388 wait_ret: "here to wait for non/pd i/o
1389 lda ptw|0 make this check just in case..
1390 cana ptw.os,dl
1391 tze quit
1392
1393 "tra to pxss to wait for PTW I/O.
1394 ldq cme.notify_requested,dl set flag for notify
1395 orsq cme_flags,*.cme ..
1396 eaa 0,.ptw create PTW event
1397 wait_page_fault_event:
1398 arl 18 right justified
1399 wait_any_event:
1400 eppap pds$apt_ptr,* get apte ptr
1401 sta ap|apte.wait_event make it where can get notified.
1402
1403 wait_any_event_apte:
1404 store_clock pds$time_1
1405 tsx .ret,unlock_ptl dump posting queue, possibly notifying
1406 "this event, and unlock ptl.
1407 meter_time pds$time_1,sst|sst.pf_unlock_ptl_time,sst|sst.pf_unlock_ptl_meterings
1408
1409 tra pxss$page_wait
1410
1411
1412 "^L
1413 "
1414 " End of page fault processing here.
1415 " These labels restart the page fault.
1416 "
1417 quit: tsx .ret,unlock_ptl unlock page table lock
1418
1419 wait_return: "return location from pxss$page_wait
1420 eppap pds$page_fault_data get pointer to fault data
1421
1422 read_clock
1423 cmpaq pds$first_covert_event_time
1424 tpl wait_return_no_delay
1425
1426 " must wait until first_covert_event_time is met- that is, until covert channel
1427 " time is up
1428
1429 ldaq pds$first_covert_event_time
1430 staq pds$arg_1
1431 tra pxss$page_pause " will return at wait_return
1432
1433 wait_return_no_delay:
1434 inhibit on
1435 ldaq ap|mc.mask retrieve previous mask
1436 oraq channel_mask_set turn on all channel mask
1437 anaq scs$open_level turn off unconfigured channel mask bits
1438 lxl1 prds$processor_tag
1439 lprpab scs$mask_ptr,1
1440 xec scs$set_mask,1
1441
1442 ldaq prds$+stack_header.stack_begin_ptr restore stack end pointer for PRDS
1443 staq prds$+stack_header.stack_end_ptr
1444
1445 odd
1446 tsx .ret,meter_virtual_time measure time to be taken out as virtual
1447
1448 restart_fault:
1449 lpl ap|mc.eis_info restore EIS pointers and lengths
1450 lreg ap|mc.regs
1451 lpri pf_prs,*
1452 rcu pf_scuinfo,*
1453 inhibit off
1454
1455 "^L
1456
1457 "
1458 " Error and unconventional cases in page fault processing.
1459 "
1460 fault_while_on_prds:
1461 lca trbl_prds_pf,dl flag for page fault on prds
1462 sta scs$sys_trouble_pending
1463 lda pds$processid save our process ID
1464 stac scs$trouble_processid if we're the first
1465 lxl1 prds$processor_tag
1466 cioc scs$cow_ptrs,1* send connect to self
1467 nop
1468 nop
1469 nop
1470 tra fault_while_on_prds
1471 "
1472 " Come here when fault taken on page already being read.
1473 "
1474
1475 short_page_fault:
1476 " Compute cme addr so that wait_ret can turn on notify_requested.
1477 "
1478
1479 increment sst|sst.short_pf_count meter
1480
1481 iftarget l68 " Shift different on L68/ADP
1482 qrl ptw_to_cmep.rl
1483 ifend
1484 iftarget adp
1485 anq ptw_add_mask,du " Must mask off all but page number
1486 qls ptw_to_cmep.ls
1487 ifend
1488
1489 eax .cme,sst|sst.cmp,*qu point to cme.
1490 tra wait_ret and wait for the page
1491
1492 "
1493 " Error bit set by done_ done_read. Signal in
1494 " faulting process.
1495 "
1496 page_read_error:
1497
1498 tsx .ret,disk_offlinep is disk down as per pvt?
1499 tra wait_any_event yes, wait for it, event in A
1500
1501 lca ptw.er+1,dl turn off error flag
1502 ansa ptw|0 in PTW
1503
1504 lda PAGE_ERROR_IOERR,dl
1505 eppab ast|0,.aste ASTE
1506 tra errquit
1507
1508 bad_segno:
1509 lda PAGE_ERROR_BADFAULT,dl
1510 eppab null,*
1511 tra errquit
1512
1513 errquit: sta pc_err_type
1514 sprpab pc_err_astep
1515 sprp ptw,pc_err_ptwp
1516
1517 tsx .ret,unlock_ptl
1518
1519 "
1520 " Call pc_signal to copy machine conditions, and otherwise set
1521 " up for the signaller
1522
1523 ldaq pc_signal_arglist
1524 staq arg
1525 eppap pc_err_type
1526 spriap arg+2
1527 eppap pc_err_astep
1528 spriap arg+4
1529 eppap pc_err_ptwp
1530 spriap arg+6
1531 call pc_signal$pc_signalarg
1532
1533 "
1534 " Now change the stack pointer so that if a process takes a page
1535 " fault while signalling which also gets an error RQO possibly
1536 " that we don't crash the system because our sp will still point
1537 " to the PRDS.
1538 "
1539 ldaq prds$+stack_header.stack_begin_ptr
1540 staq prds$+stack_header.stack_end_ptr reset stack end pointer
1541 eppap pds$signal_data
1542 eppsp ap|mc.prs+6*2,* change sp to that at time of the fault
1543
1544 "
1545 " Now complete the virtual time calculation that were by-passed because we did
1546 " not do an RCU.
1547 "
1548 tsx .ret,meter_virtual_time
1549 tra signaller$signaller now let the signaller do the work
1550
1551 " data for signal call.
1552
1553
1554 " ^L
1555 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1556 "
1557 " pread
1558 "
1559 " Entry to read a page into core.
1560 "
1561 " Call is:
1562 " call page$preadasteppagenowaitev
1563 "
1564 " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1565
1566 pread:
1567 push
1568 stz ap|6,*
1569 lda read_entry,dl set entry switch
1570 sta entry_sw
1571 tsx .2ret,init_savex set up stack
1572
1573 pread.loop: "may have paged in 2 or more stages, tho.
1574 eppap sp|stack_frame.arg_ptr,*
1575 eppbp ap|2,*
1576 epp sst,sst$
1577 eppbp bp|0,*
1578 eax .aste,bp|0
1579 lda ap|4,*
1580 eax .ptw,bp|aste_size,al point to ptw
1581 epp ptw,sst|0,.ptw
1582
1583 lda ptw|0 is page in?
1584 cana ptw.valid,dl
1585 tnz return yes, no problem.
1586
1587 cana ptw.er,dl error from previous read?
1588 tze pread.read_page no, just read
1589
1590 tsx .ret,disk_offlinep
1591 tra pread.wait_any go wait global event if needed
1592
1593 pread.read_page:
1594 tsx .ret,read_page do some work.
1595 tra pread.wait must wait, indicate or loop
1596 tra pread.loop must check again.
1597
1598 eppap pds$apt_ptr,* retrieve wait event
1599 lda ap|apte.wait_event
1600 tra pread.wait_any volmap event
1601 pread.wait:
1602
1603
1604 pread.wait_ret:
1605 arl 18 convert to wait event
1606 pread.wait_any:
1607 eppap sp|stack_frame.arg_ptr,* retrieve arg pointer
1608 sta ap|6,* return wait event
1609 tra return
1610 "^L
1611 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1612 "
1613 " pwrite
1614 "
1615 " Entry to write a page out.
1616 "
1617 " Call is:
1618 " call page$pwriteasteppageno
1619 "
1620 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1621
1622 pwrite:
1623 push
1624 lda write_entry,dl set up entry switch
1625 sta entry_sw
1626 eppbp ap|2,* get pointer to APT
1627 eppbp bp|0,*
1628 epbpbb bp|0 let bb point to base of sst
1629 eax .aste,bp|0
1630 lda ap|4,* get page number
1631 eax2 bp|aste_size,al
1632 eppbp sst|0,.ptw make sure bp points to PTW
1633 lda ptw|0 pick up page table word
1634
1635 iftarget l68 " Shift different on L68/ADP
1636 arl ptw_to_cmep.rl
1637 ifend
1638 iftarget adp
1639 ana ptw_add_mask,du " Must mask off all but page number
1640 als ptw_to_cmep.ls
1641 ifend
1642
1643 eax .cme,sst|sst.cmp,*au
1644 tsx .2ret,init_savex initialize save stack for x7
1645 tsx .ret,write_page
1646
1647
1648 tra return
1649 " ^L
1650 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1651 "
1652 " pcleanup
1653 "
1654 " Entry to get a page out of core.
1655 "
1656 " Call is:
1657 " call page$pcleanup astep pageno
1658 "
1659 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1660
1661 pcleanup:
1662 push
1663 lda cleanup_entry,dl
1664 sta entry_sw
1665
1666 tsx .2ret,init_savex_bb
1667
1668 epp ptw,ap|2,*
1669 epp ptw,ptw|0,* get astep
1670 eax .aste,ptw|0
1671 lda ap|4,* get pageno
1672 eax .ptw,ptw|aste_size,al
1673 epp ptw,sst|0,.ptw
1674
1675 lda ptw|0 get ptw
1676 cana add_type.disk+ptw.os,dl
1677 tze *+2
1678 tsx5 page_fault_error "ERROR - PCLEANUP: CALLED ON BAD-STATE PAGE
1679
1680 iftarget l68 " Shift different on L68/ADP
1681 arl ptw_to_cmep.rl
1682 ifend
1683 iftarget adp
1684 ana ptw_add_mask,du " Must mask off all but page number
1685 als ptw_to_cmep.ls
1686 ifend
1687
1688 eax .cme,sst|sst.cmp,*au
1689 arl cmep_to_coreadd.rl
1690 sta core_add
1691
1692 lca ptw.valid+1,dl
1693 ansa ptw|0 turn off ptw access
1694
1695 tsx .2ret,check_accessible " only CAM if needed
1696 tsx .ret,cam_cache$cam_cache make sure it takes
1697
1698 tsx .ret,cleanup_page do the work.
1699 return
1700 "^L
1701 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
1702 "
1703 " read_page, read_page_abs
1704 "
1705 " Subroutine called by tsx7 to read a page into core or if
1706 " the page has never beeen referenced it will zero the core.
1707 " A free block of core is found and possibly several 'writes' are
1708 " queued in searching for the free core for the read_page entry.
1709 " For the read_page_abs entry the free block of core
1710 " specified by the caller is used.
1711 "
1712 " tsx7 read_page
1713 " <return with wait event in Areg>
1714 " <return if page in memory>
1715 " <return with volmap wait event set in APTE>
1716 "
1717 " The subroutine expects
1718 "
1719 " x2 = pointer to PTW
1720 " x3 = pointer to AST entry
1721 " bp = pointer somewhere into SST
1722 " bb = pointer to base of SST
1723 "
1724 " In addition, the read_page_abs entry expects
1725 "
1726 " x4 = pointer to core map entry of free block
1727 " " " " " " " " "" " " " " " " " " " " " " " " " " " " " " " " " "
1728
1729 read_page_abs:
1730 tsx .2ret,savex recursive use of index 7
1731
1732 tsx .ret,check_allocation make sure we have disk.
1733 tsx5 page_fault_error "ERROR - OOPV ON EHS SEG"
1734 tra read_page_abs.apte_event volmap event
1735
1736 tra read_page_join
1737
1738 read_page_abs.apte_event:
1739 eppap pds$apt_ptr,* event is in APTE
1740 lda ap|apte.wait_event
1741 tra unsavex_2 return to caller
1742
1743 read_page:
1744 tsx .2ret,savex recursive use of index 7
1745
1746 tsx .ret,check_quota check for quota overflow
1747 tsx .ret,check_allocation is there disk available?
1748 tra read_page.oodev no disk on this PV
1749 tra unsavex_2 must wait for volmap event
1750
1751 stx .ptw,ptp_astep save x2 and x3 for now
1752 sxl .aste,ptp_astep ..
1753 tsx .ret,find_core find a free block of core
1754 ldx .ptw,ptp_astep restore x2 and x3
1755 eppbp sst|0,.ptw make sure bp points to PTW as well
1756 lxl .aste,ptp_astep ..
1757 "^L
1758 read_page_join:
1759
1760 " At this point, a cme to ptw binding is established. To validate the
1761 " assumptions of pc_recover_sst, it must be done in following order:
1762 " Auxiliary info into CME
1763 " cme.ptwp <= ptwp
1764 " ptw.add <= CORE
1765
1766 lca ptw.phm+ptw.phm1+ptw.er+1,dl " turn off bad bits.
1767 ansa ptw|0
1768 lda ptw|0 copy device address to core map entry
1769 staddra cme_devadd,*.cme store address from ptw into cme
1770 lca cme.io+cme.phm_hedge+cme.removing+cme.notify_requested+1,dl
1771 ansa cme_flags,*.cme clear random flags
1772
1773 sxl .aste,cme_astep,*.cme Associate astep with cme, not ptp yet.
1774 " Do not store ptwp in cme until cme is ready, core clear, or ptw os.
1775
1776
1777 eaa 0,.cme copy relcmep to a-reg
1778 sbla sst|sst.cmp+1 to get core address
1779 arl cmep_to_coreadd.rl
1780 sta core_add save core address
1781
1782 ldq aste.init,du turn off init bit in aste
1783 orsq ast|aste.init_word,.aste ..
1784 ersq ast|aste.init_word,.aste ..
1785 ldq ast|aste.np_word,.aste increment number of pages in core
1786 anq aste.np_mask,dl
1787 tnz read.incr_np
1788 "
1789 " Reading in the first page causes dtu to advance. Also, the dtm may be
1790 " advanced. Lets see.
1791 "
1792 ldq 1,dl this will advance to 1 page
1793 szn pds$throttle_segment_state_changes
1794 tze read.set_np don't count events
1795 szn entry_sw
1796 tnz read.set_np only count on fault side
1797
1798 " Count this event. Our assumptions:
1799 " dtm - w access implies that we can and must assume we will advance dtm.
1800 " Advancing dtm is always lower class visible since it propogates up
1801 " the hierarchy. However, we know that dirs advance dtm only when
1802 " they want to in sum$dirmod, so we don't count dirs as setting
1803 " dtm here.
1804 "
1805 " dtu - w access implies that our authorization equals the access class
1806 " of the object, hence our setting dtu is not lower class visible.
1807 " However, multi-class and directories violate this rule.
1808 "
1809 " Hence: a non-directory, multi-class writable object advances dtu and dtm
1810 " in a lower class visible way. All other cases advance either dtu or dtm
1811 " but not both.
1812
1813 lda pf_sdw+1
1814 cana sdw.write,du check for write
1815 tze read.covert_1 no write
1816 lda ast|aste.dirsw_word,.aste " also multi_class word
1817 cana aste.multi_class,du
1818 tze read.covert_1 non-multi-class
1819 cana aste.dirsw,dl
1820 tnz read.covert_1 is a dir
1821
1822 tsx .ret,limit_covert_channel both dtu and dtm set
1823 read.covert_1:
1824 tsx .ret,limit_covert_channel only dtu or dtm set
1825 ldq 1,dl advance np to 1 page
1826 tra read.set_np
1827
1828 read.incr_np:
1829 adlq 1,dl
1830 erq ast|aste.np_word,.aste
1831 anq aste.np_mask,dl
1832 read.set_np:
1833 ersq ast|aste.np_word,.aste
1834
1835 lda cme_devadd,*.cme pick up cme devadd
1836 cana add_type.non_null,dl is there an address?
1837 tnz *+2 must have real allocation here
1838 tsx5 page_fault_error "ERROR - NO ALLOCATION IN PTW: READ_PAGE"
1839 als 0 is it a real address?
1840 tpl must_read yes, actually read it
1841
1842 "
1843 "Make zeroes for a predeposited address.
1844 "
1845 "tra read.create_zeros is right on the next page
1846 "^L
1847 "
1848 " Page had either a null or nulled address in PTW.
1849 " Create a fresh page of zeroes.
1850 "
1851
1852 read.create_zeros:
1853 lda ast|aste.records_word,.aste
1854 adla =o001000,dl increment records used
1855 era ast|aste.records_word,.aste
1856 ana aste.records_mask_inner,dl
1857 ersa ast|aste.records_word,.aste
1858
1859 " Adding a page can be a covert event, if this is a multi-class object
1860 " records used etc. lower class visible or if this is a dir without
1861 " terminal quota between it and the nearest upgraded node.
1862 " We don't have to worry about questions of setting csl/ru since the only
1863 " cases where page creations are covert events are cases where the page
1864 " creations are performed by trusted code themselves, and in which we know
1865 " that pages are created serially. The user cannot create any random page
1866 " in these segments, only the next. Thus, csl and ru contain the same
1867 " information, even though ru may later become less than csl if some of
1868 " these new pages end up zero.
1869
1870 szn pds$throttle_segment_state_changes
1871 tze read.bump_quota don't count events
1872 szn entry_sw
1873 tnz read.bump_quota only on fault side
1874
1875 lda ast|aste.multi_class_word,.aste
1876 cana aste.multi_class,du
1877 tze read.create_check_dir
1878 tsx .ret,limit_covert_channel multi-class
1879 tra read.bump_quota
1880
1881 read.create_check_dir:
1882 cana aste.dirsw,dl
1883 tze read.bump_quota non-dir
1884
1885 " We have a dir. We shall do a special bump quota which checks for
1886 " terminal-ness.
1887
1888 tsx .ret,bump_quota_covert_check increment used
1889 tsx .ret,limit_covert_channel upgraded found first
1890 tra read.quota_bumped
1891
1892 read.bump_quota:
1893 tsx .ret,bump_quota increment used
1894 read.quota_bumped:
1895 increment sst|sst.new_pages meter new pages created
1896 tsx .ret,clear_core zero out the core
1897 "
1898 " Now it is safe to store .ptw in cme
1899 "
1900 stx .ptw,cme_ptwp,*.cme
1901 lda core_add pick up core address again
1902 als coreadd_to_ptw.ls
1903 ora add_type.core,dl
1904 staddra ptw|0 store in ptw
1905
1906 lda ptw.phu+ptw.valid+df1,dl make used, accessible, refresh bit
1907 orsa ptw|0
1908
1909 stx .aste,temp calculate page number
1910 eax .tem,1-aste_size,.ptw by subtracting astep from ptwp-aste_size+1
1911 sblx .tem,temp
1912 stz temp
1913 sxl .tem,temp save in temp
1914 lda ast|aste.csl_word,.aste pick up current csl
1915 ana aste.csl_mask_inner,du
1916 arl aste.csl_shift
1917 cmpa temp compare ...
1918 tpl unsavex_1 csl already larger than this
1919 ldq temp retrieve new csl value
1920 qls aste.csl_shift position for store into ASTE
1921 erq ast|aste.csl_word,.aste
1922 anq aste.csl_mask_inner,du
1923 ersq ast|aste.csl_word,.aste
1924 tra unsavex_1
1925 "^L
1926 " covert channel test - update covert channel event count, test bandwidth
1927 "
1928 limit_covert_channel:
1929 aos pds$covert_event_count
1930 tmi 0,.ret not enough events to monitor, yet
1931
1932 " arriving here, we need to determine the bandwidth of these covert channel
1933 " events and possible audit or delay
1934
1935 read_clock
1936 sbaq pds$first_covert_event_time
1937 cmpaq covert.big_time
1938 tpl covert.reset_clock time too great to count
1939 div sst|sst.seg_state_change_limit usecs/bit in q
1940 stq temp and temp
1941 mpy sst|sst.audit_seg_state_change_bw
1942 cmpaq covert.million
1943 tpl covert.test_delay usecs/bit*max_bps<1000000
1944
1945 " audit here
1946
1947 increment sst|sst.audit_seg_state_chg
1948 tsx .2ret,page_error$excessive_seg_state_chg
1949
1950 covert.test_delay:
1951 ldq temp
1952 mpy sst|sst.max_seg_state_change_bw
1953 cmpaq covert.million
1954 tpl covert.reset_clock usecs/bit*max_bps<1000000
1955
1956 " delay process
1957
1958 increment sst|sst.delayed_seg_state_chg
1959
1960 ldaq covert.million
1961 div sst|sst.max_seg_state_change_bw desired usecs/bit
1962 sbq temp delay as usecs/bit
1963 mpy sst|sst.seg_state_change_limit delay in aq
1964 staq pds$first_covert_event_time temp storage
1965 adlaq sst|sst.seg_state_chg_delay " this isn't really correct,
1966 " this is how long we want to delay,
1967 " not how long we will - but it's not
1968 " worth metering the real delay
1969 staq sst|sst.seg_state_chg_delay
1970
1971 read_clock set time to delay until
1972 adaq pds$first_covert_event_time see wait_return for use of time
1973 tra covert.reset
1974
1975 covert.reset_clock:
1976 read_clock
1977 covert.reset:
1978 staq pds$first_covert_event_time
1979 lca sst|sst.seg_state_change_limit
1980 sta pds$covert_event_count
1981 tra 0,.ret
1982
1983 even
1984 covert.big_time:
1985 oct 0,377777777777
1986 covert.million:
1987 dec 0,1000000
1988 "^L
1989 "
1990 " Page had non-null add type. Must actually read page in.
1991 " PTW is in A register.
1992 "
1993
1994 must_read:
1995 sta devadd save device address in stack
1996
1997
1998 tsx .ret,get_pvtx get segment pvtx for fault
1999
2000 read.must_rd.merge:
2001 tsx .ret,device_control$check_ckdv see if checking device incomplete
2002 tsx .ret,store_pattern if so, store pattern
2003
2004 "
2005 " Set up os bit before storing ptwp in cme, so page goes back in pc_r_sst.
2006 "
2007 lca cme.io+1,dl set io flag to "read"
2008 ansa cme_flags,*.cme
2009
2010 lda ptw.os,dl turn it on
2011 orsa ptw|0
2012
2013 stx .ptw,cme_ptwp,*.cme
2014
2015
2016 lda core_add set up ptw afresh
2017 als coreadd_to_ptw.ls
2018 ora add_type.core,dl
2019 staddra ptw|0 put in coreadd
2020
2021 tsx .ret,thread_out OS out of list
2022
2023 lda int+pri,dl almost always interrupt on reads
2024 sta inter
2025 tsx .ret,device_control$dev_read read the page into core
2026 eaa 0,.ptw ptw is he wait event
2027 tra unsavex wait this event
2028 "^L
2029 "
2030 " Peculiar exits of read_page
2031 "
2032
2033 read_page.oodev: "out of physical volume.
2034 "Signal a segfault.
2035 increment sst|sst.oopv meter
2036
2037 lda aste.pack_ovfl,dl turn on aste bit
2038 orsa ast|aste.pack_ovfl_word,.aste in AST
2039
2040 szn entry_sw better be a page_fault
2041 tze *+2
2042 tsx5 page_fault_error "ERROR - OOPV ON READ_PAGE CALL"
2043 create_segment_fault:
2044 eppap pds$page_fault_data address mc
2045 lda ap|mc.scu.apu_stat_word
2046 cana scu.apu.dsptw,dl is this ds fault?
2047 tze *+2
2048 tsx5 page_fault_error "ERROR - SETFAULT DESCRIPTOR SEGMENT"
2049
2050 lxl .tem,ap|mc.scu.cu_stat_word was it IF?
2051 canx .tem,scu.cu.if,du
2052 tnz *+2
2053 lda ap|mc.scu.tpr.tsr_word get TSR if not IF
2054 als 1 double segno
2055 ana =o177776,du
2056
2057 iftarget l68 " On Level 68 only, must also set df_no to zero
2058 lcq sdw.valid+sdw.df_no_mask+1,dl
2059 ifend
2060 iftarget adp
2061 lcq sdw.valid+1,dl
2062 ifend
2063
2064 ansq dseg$,au
2065 tsx .ret,cam_cache$cam
2066 tra quit seg mover will handle
2067
2068 "^L
2069 " " " " " " " " " " " " " " " " " " " " " " " " " " "
2070 " "
2071 " disk_offlinep "
2072 " "
2073 " Is the seg's disk offline? "
2074 " "
2075 " tsx .ret,disk_offlinep "
2076 " tra yes, event in A "
2077 " null no "
2078 " "
2079 " " " " " " " " " " " " " " " " " " " " " " " " " " "
2080
2081 disk_offlinep:
2082 tsx .2ret,savex
2083 tsx .ret,get_pvtx
2084 tsx .ret,device_control$disk_offlinep
2085 tra *+2 offline
2086 tra unsavex_1 not offline
2087
2088 lca ptw.er+1,dl turn OFF the error bit. This is
2089 ansa ptw|0 so that when the guy tries again
2090 "when the disk finally comes back,
2091 "the next call to disk_offlinep
2092 "doesnt cause a signal.
2093 lda disk_offline_event
2094 tra unsavex
2095
2096 disk_offline_event:
2097 aci "dskw"
2098 "^L
2099 "
2100 " Check to see if page has allocation. Give one
2101 " if needed.
2102 "
2103 " tsx7 check_allocation
2104 " <return in out of room on physical volume>
2105 " <return if must wait volmap event, event set in APTE>
2106 " <return if page has allocation>
2107
2108 check_allocation:
2109 lda ptw|0 grab ptw
2110 cana add_type.core,dl
2111 tze *+2 make sure we're doing this right
2112 tsx5 page_fault_error "ERROR - CORE ADDR IN PTW: READ_PAGE"
2113 cana add_type.disk,dl " real devadd?
2114 tnz 2,.ret yes, that's fine.
2115
2116 stx .aste,pageno ASTE offset
2117 eax .tem,-aste_size,.ptw
2118 sblx .tem,pageno Page number
2119 eaq 0,.tem
2120 qrl 18
2121 stq pageno
2122 ldq ast|aste.vtocx,.aste
2123 anq -1,dl VTOCE Index
2124 stq vtocx
2125
2126 tsx .2ret,savex enter free_store
2127 tsx .ret,get_pvtx get pvtx
2128 tsx .ret,free_store$withdraw get an address
2129 tra unsavex OOPV
2130 tra unsavex_1 volmap wait event
2131
2132 "
2133 " Put nulled address where null one was. With respect to pc_recover_sst,
2134 " this is all the same.
2135 "
2136 lda devadd
2137 ora ptw.nulled,du this is semikilled address
2138 sta devadd
2139
2140 staddra ptw|0 put in new address
2141 unsavex_2:
2142 ldx .ret,stackp,di
2143 tra 2,.ret return
2144 "^L
2145 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2146 "
2147 " find_core_
2148 "
2149 " Subroutine to find a block of free core.
2150 "
2151 " Call is:
2152 " tsx7 page_fault$find_core_
2153 "
2154 " tsx7 find_core
2155 "
2156 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2157
2158 equ pre_seek_limit,15 " Mod failure detection
2159
2160 find_core_: " Externally available to ALM PC
2161
2162 find_core:
2163 tsx .2ret,savex save index 7
2164 increment sst|sst.needc meter times core was needed
2165 lca 1,du init ctr for out-of-core to -2**18
2166 sta total_steps
2167 fploop:
2168 stz count zero count of steps
2169 lca pre_seek_limit,dl initialize mod failure ctr
2170 sta temp1
2171 ldx .cme,sst|sst.usedp set cmep
2172
2173 " re-entry from find_core.ptw_ng and find_core.skip_meter_mod
2174
2175 fc1:
2176 lda cme_flags,*.cme check for total acceptability
2177 cana cme.removing+cme.abs_w,dl
2178 tnz find_core.cme_ng something unusable- meter & skip
2179
2180 ldx .ptw,cme_ptwp,*.cme Is core free? Set ptp.
2181 tze found_core yes, take it.
2182 epp ptw,sst|0,.ptw point at ptw
2183 lda ptw|0 let's examine the ptw...
2184
2185 cana ptw.phu+ptw.wired+ptw.os+ptw.phm+ptw.phm1,dl " make quick check
2186 tnz find_core.ptw_ng something in ptw is unacceptable.
2187
2188 ldx .tem,cme_pin_counter,*.cme
2189 tpnz find_core.skip_pinned do not evict if still pinned
2190
2191 "
2192 " Now attempt to evict the page.
2193 "
2194 "^L
2195 "
2196 " Here is where access is taken off for a potential eviction.
2197 " If we lose timing window, access comes back. Note that core address
2198 " in PTW stays valid until cleanup_page has run, and contents of
2199 " core page can be ignored we are sure page is pure.
2200
2201 lca ptw.valid+1,dl set directed fault 1 in ptw
2202 ansa ptw|0 ..
2203 lda ptw|0 make sure coreadd gets set
2204 ana ptw_add_mask,du " Mask off all but the page address bits
2205 arl ptw_to_coreadd.rl " Clear the right place in the cache
2206 sta core_add ..
2207
2208 lxl .aste,cme_astep,*.cme " get astep
2209 tsx .2ret,check_accessible " CAM if needed
2210 tsx .ret,cam_cache$cam_cache " make sure the access gets turned off
2211
2212 lda ptw|0 retrieve ptw for modified bit test
2213 cana ptw.phm+ptw.phm1+ptw.wired,dl has the page been modified now? or wired?
2214 tnz restore_ptw_access appear to have lost race
2215
2216 stx .cme,sst|sst.usedp this frame now LRU
2217 tsx .ret,cleanup_page evict the page
2218
2219 found_core:
2220 increment sst|sst.steps meter
2221 ldx .tem,cme_fp,*.cme move to MRU
2222 stx .tem,sst|sst.usedp
2223 tra unsavex find_core returns
2224 "^L
2225 "
2226 " PTW has some kind of unacceptable state: possibilities:
2227 "
2228 " 1. out of service- illegal- crash system
2229 " 2. wired- skip and meter
2230 " 3. modified- leave alone for claim_m_c to evict/unuse.
2231 " 4. nypd- leave alone for c_m_c to write to pd if unused.
2232 " 5. used- "unuse" for replacement algorithm.
2233
2234 find_core.ptw_ng:
2235 cana ptw.os,dl this ought not be..
2236 tze *+2
2237 tsx5 page_fault_error "ERROR - FINDCORE FINDS OS ON LIST
2238
2239 cana ptw.phm+ptw.phm1,dl has it been modified?
2240 tnz find_core.skip_meter_mod must be written, can't take.
2241 "don't care whether used or not -must leave
2242 "both bits for c_m_c, who will off them.
2243
2244 cana ptw.wired,dl is it wired?
2245 tnz find_core.skip_wired
2246 "
2247 " Must be used, skip and meter, impl. replacement algorithm
2248 " by turning bit off.
2249 "
2250 increment sst|sst.skipu count used.
2251 lca ptw.phu+1,dl turn off phu bit in PTW
2252 ansa ptw|0
2253 lda ptw.phu1,dl turn PHU1 ON in PTW
2254 orsa ptw|0
2255
2256 skip:
2257 ldx .cme,cme_fp,*.cme go to next core map entry in list
2258 increment sst|sst.steps count step
2259 aos total_steps up count of steps taken looking for core
2260 tmi fc1 if still neg, loop on.
2261 tra page_error$out_of_core Multics not in operation.
2262
2263
2264 restore_ptw_access: "come here when 2nd cpu mod in window
2265 lda ptw.valid,dl remove directed fault from ptw
2266 orsa ptw|0 ..
2267 find_core.skip_meter_mod:
2268 increment sst|sst.skipm count skip mod
2269 cmod1: increment sst|sst.steps
2270 ldx .tem,cme_fp,*.cme pt at next cme
2271 cmpx .tem,sst|sst.usedp have we walked whole queue?
2272 tze mods_excessive will run claim_mod_core on whole mem
2273 eax .cme,0,.tem go to next cme
2274 aos temp1 see if too many skipmods
2275 tpl mods_excessive too many
2276 tra fc1
2277
2278 find_core.skip_pinned:
2279 increment sst|sst.fc_skips_pinned no. of pin skips in find_core
2280 ldx .tem,cme_pin_counter,*.cme
2281 sblx .tem,1,du
2282 tmi skip never happen
2283 stx .tem,cme_pin_counter,*.cme
2284 tra skip
2285
2286
2287 "^L
2288 "
2289 " cme is unacceptable- following may be the case:
2290 "
2291 " 1. removing can't page in, must not be used. skip.
2292 " 2. abs_w IN PROCESS of being abs-wired.. may not
2293 " page in evict_page will do it by special means,
2294 " must avoid getting vol map in here by accident.
2295
2296 find_core.cme_ng:
2297
2298 cana cme.abs_w,dl abs wiring?
2299 tze skip no, just skip.
2300
2301 find_core.skip_wired:
2302 increment sst|sst.skipw
2303 tra skip ..
2304
2305 "
2306 " We arrive here when an excess of skips-mod have been made.
2307 " Potentially, every page in core can be mod and used. Hence,
2308 " tentatively, the fast find_core has failed. Do it the old way.
2309 "
2310 mods_excessive:
2311 stx .cme,sst|sst.usedp save ptr to NEXT cme
2312 increment sst|sst.pre_seeks_failed meter
2313 tsx .ret,claim_mod_core do writes, may even post.
2314 tra fploop restart find_core_
2315
2316 "^L
2317 """"""""""""""""""""""""""""""""""""""""""""""""""
2318 " "
2319 " Subroutine to evict one "
2320 " page from core. "
2321 " "
2322 """"""""""""""""""""""""""""""""""""""""""""""""""
2323
2324 cleanup_page:
2325 tsx .2ret,savex
2326 lxl .aste,cme_astep,*.cme get astep
2327
2328 "
2329 " Unbind core from ptw here. For validity of pc_recover_sst, this
2330 " must be done in the following order:
2331 " Put non-core address back in ptw
2332 " cme.ptwp <= 000000
2333 " Clean up cme
2334 "
2335 lda cme_devadd,*.cme clear out ptw
2336 staddra ptw|0
2337
2338 lda ast|aste.np_word,.aste subtract from count of pages in core
2339 sbla 1,dl
2340 era ast|aste.np_word,.aste
2341 ana aste.np_mask,dl
2342 ersa ast|aste.np_word,.aste
2343 lda ast|aste.np_word,.aste
2344 cana aste.np_mask,dl see if any pages left in core
2345 tnz cleanup.np_nonzero yes, continue
2346
2347 lda aste.init,du no, turn init bit ON in ASTE
2348 ora ast|aste.init_word,.aste ..
2349 sta ast|aste.init_word,.aste gtus is in same word, so...
2350 cana aste.gtus,du check gtus. If on, leave dtu alone
2351 tnz cleanup.np_nonzero nothing to do
2352
2353 read_clock get time
2354 lls 20 convert to fstime in A
2355 sta ast|aste.dtu,.aste and drop it in
2356
2357 cleanup.np_nonzero:
2358 tsx .ret,check_synch_cleanup do housekeeping for synchronized page
2359 lda ptw|0 if not live address, must adjust quota...
2360 cana add_type.non_null,dl and records_used.
2361 tze cleanup.rsq null, reset recs.
2362 cana ptw.nulled,du is it nulled?
2363 tze cleanup.nrsq1 not nulled, don't reset.
2364 cleanup.rsq:
2365 tsx .ret,update_csl make sure csl is correct
2366 lda ast|aste.records_word,.aste
2367 ana aste.records_mask_inner,dl
2368 sbla =o001000,dl decrement records used
2369 tpl cleanup.recused_okay
2370 szn pvt$esd_state
2371 tnz cleanup.recused_okay
2372 tsx5 page_fault_error "ERROR - RECUSED WENT NEG: CLEANUP"
2373 cleanup.recused_okay:
2374 era ast|aste.records_word,.aste
2375 ana aste.records_mask_inner,dl
2376 ersa ast|aste.records_word,.aste
2377 tsx .ret,reset_quota deduct a quotum used
2378 cleanup.nrsq1:
2379 eax .tem,0 zero ptw correspondence
2380 stx .tem,cme_ptwp,*.cme ..
2381 sxl .tem,cme_astep,*.cme zero astep correspondence too
2382 tsx .ret,thread_to_lru move to head of list
2383 lca ptw.phm+ptw.phm1+1,dl " turn off mod
2384 ansa ptw|0
2385 tra unsavex
2386 "^L
2387 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
2388 " "
2389 " "
2390 " claim_mod_core "
2391 " "
2392 " Tsx .ret,claim_mod_core to sweep "
2393 " up all the writes that "
2394 " find_core chose not to do. "
2395 " "
2396 """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
2397
2398 claim_mod_core:
2399 tsx .2ret,savex save return
2400 increment sst|sst.write_hunts meter
2401
2402 mc_continue:
2403 ldx .cme,sst|sst.wusedp start at last point
2404
2405 mclp: cmpx .cme,sst|sst.usedp are we up to find_core?
2406 tze cl_done
2407 increment sst|sst.claim_steps meter steps
2408
2409 lda cme_flags,*.cme look at cme
2410 cana cme.removing+cme.abs_w,dl " check unacceptable states
2411 tnz cl_bad
2412
2413 ldx .ptw,cme_ptwp,*.cme point to ptw
2414 tze cl_free this is really bad, for
2415 "this cme should be
2416 "in front of usedp.
2417 epp ptw,sst|0,.ptw point to ptw
2418
2419 lda ptw|0 consider ptw
2420 cana ptw.os+ptw.wired,dl
2421 tnz cl_ptwbad
2422 cana ptw.phm+ptw.phm1,dl " we only care about those f_c_ skipped
2423 tze cl_notmod
2424
2425 cana ptw.phu,dl see if used
2426 tnz cl_used turn off used if on
2427
2428 ldx .tem,cme_pin_counter,*.cme see if page is pinned
2429 tpnz cl_pinned
2430
2431 increment sst|sst.claim_writes meters
2432 ldx .tem,cme_fp,*.cme peek ahead to next cme
2433 stx .tem,sst|sst.wusedp save pointer
2434
2435 lxl .aste,cme_astep,*.cme pick up astep
2436 tsx .ret,write_page write_page will do all necessary
2437 tra mc_continue
2438
2439 mc_end: ldx .cme,cme_fp,*.cme scan on into map
2440 tra mclp
2441
2442 cl_bad:
2443 increment sst|sst.claim_skip_cme A CME had permanent unacceptable state, or RWS
2444 tra mc_end
2445
2446 cl_ptwbad:
2447 increment sst|sst.claim_skip_ptw PTW wired
2448 tra mc_end
2449
2450 cl_free:
2451 increment sst|sst.claim_skip_free A CME was free to claim_mod_core
2452 tra mc_end
2453
2454 cl_notmod:
2455 increment sst|sst.claim_notmod not modified, not interesting
2456 tra mc_end
2457
2458 cl_used:
2459 lcq ptw.phu+1,dl mod, but used.
2460 ansq ptw|0 turn off used and pray for cam.
2461 ldq ptw.phu1,dl dont screw up working sets
2462 orsq ptw|0
2463 increment sst|sst.claim_passed_used
2464 tra mc_end
2465
2466 cl_pinned:
2467 increment sst|sst.cl_skips_pinned no. of pin skips in claim_mod
2468 " cme_pin_counter in x0
2469 sblx .tem,1,du
2470 tmi mc_end never happen
2471 stx .tem,cme_pin_counter,*.cme
2472 tra mc_end
2473
2474 cl_done:
2475 stx .cme,sst|sst.wusedp
2476 tra unsavex
2477 "^L
2478 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2479 "
2480 " write_page
2481 "
2482 " Subroutine to check to see a page should be written out.
2483 " If so, initiate the I/O.
2484 "
2485 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2486
2487 write_page:
2488 "
2489 " Page has been modified
2490 "
2491 tsx .2ret,savex recursive use of .ret
2492 tsx .ret,get_pvtx get pvtx from AST
2493 tsx .ret,pc_trace$write_page
2494 eaa 0,.cme compute core_add from cmep
2495 sbla sst|sst.cmp+1
2496 arl cmep_to_coreadd.rl ..
2497 sta core_add
2498 lda cme_devadd,*.cme save devadd in stack
2499 sta devadd ..
2500
2501 lda ptw|0 inspect ptw
2502 cana ptw.os,dl check for o/s
2503 tze *+2
2504 tsx5 page_fault_error "ERROR - WRITE CALL ON OS PAGE"
2505 cana ptw.phm+ptw.phm1,dl " if neither on, obsolete call
2506 tze unsavex
2507
2508
2509 lxl .tem,ast|aste.par_astep,.aste dont update if no parent
2510 tze write.dont_set_fms
2511
2512 ldq ast|aste.gtms_word,.aste check global-transparent-modified-switch
2513 canq aste.gtms,du
2514 tnz write.dont_set_fms if on, don't set fms
2515
2516 cana ptw.phm,dl was fms set by pc$update_incore_fms?
2517 tze write.dont_set_fms yes, don't set it
2518
2519 eax .tem,0,.aste copy AST parent to x0 first time is AST
2520 read_clock get current time
2521 lrs 16 convert to fstime in Q
2522 lda aste.fms,du get set to turn on all superior fms's
2523
2524 write.set_parent_fms:
2525 orsa ast|aste.fms_word,.tem
2526 stq ast|aste.dtm,.tem set dtm as well
2527 lxl .tem,ast|aste.par_astep,.tem
2528 tnz write.set_parent_fms
2529
2530 write.dont_set_fms:
2531 tsx .2ret,set_up_abs_seg abs_seg1 -> page in memory, ap -> abs_seg1
2532 tsx .ret,check_for_synch_hold synchronized page, not to be written
2533 tra unsavex yes - don't write
2534
2535 szn tc_data$system_shutdown don't null pages during shutdown
2536 tnz page_non_zero yes, pretend page non-zerodon't deposit anything
2537 ldq ast|aste.dnzp_word,.aste don't null if special flag set
2538 canq aste.dnzp,du ..
2539 tnz page_non_zero
2540
2541 lda ptw|0 Don't null wired pages.
2542 cana ptw.wired,dl
2543 tnz page_non_zero
2544
2545 tsx .ret,check_for_zero test for a zero page
2546 tra page_non_zero return here if really not zero
2547 lca ptw.valid+1,dl set directed fault 1 in ptw
2548 ansa ptw|0 ..
2549
2550 tsx .2ret,check_accessible " only CAM if needed
2551 tsx .ret,cam_cache$cam_cache make sure people see it
2552
2553 tsx .ret,check_for_zero try again after turning off access
2554 tra page_non_zero_a he just modified it before we zapped access, phooey
2555 "
2556 " page was all zeroes
2557 "
2558 increment sst|sst.zero_pages
2559 tsx .ret,pc_trace$zero_page
2560
2561
2562 lda ptw.nulled,du null the disk addr in cme.
2563 orsa cme_devadd,*.cme
2564
2565 lda aste.fmchanged,du turn on map changed bit
2566 orsa ast|aste.fmchanged_word,.aste
2567 tsx .ret,cleanup_page evict page from core, turns off phm.
2568 tra unsavex
2569 " ^L
2570 " come here because the page is non-zero and must be written out
2571 "
2572
2573 page_non_zero_a:
2574 lda ptw.valid,dl remove directed fault from ptw
2575 orsa ptw|0 ..
2576 page_non_zero:
2577 lda cme_devadd,*.cme
2578 cana add_type.non_null,dl is it real null?
2579 tnz write.pnz.to_disk
2580
2581 "
2582 " Was a real null address- this must not be so at this point!!!
2583 "
2584 write.nz.was_real_null:
2585 "
2586 tsx5 page_fault_error "ERROR - NO ALLOCATION AT WRITE TIME"
2587
2588
2589
2590 write.pnz.to_disk:
2591 lda unnull_mask unnull, but not in core map
2592 ansa devadd
2593
2594 "^L
2595 "
2596 " Actually set up like we're gonna write.
2597 " Recovery strategy requires cme.io set before os set.
2598 "
2599
2600 do_write:
2601 tsx .ret,thread_out OS out of list
2602
2603 lda cme.io,dl turn on write bit in CME
2604 orsa cme_flags,*.cme ..
2605
2606 lda ptw.os,dl set ptw out of service
2607 orsa ptw|0
2608
2609 lca ptw.phm+ptw.phm1+1,dl turn it off once ptw.os is on.
2610 ansa ptw|0
2611
2612 tsx .2ret,check_accessible " if needed:
2613 tsx .ret,cam_cache$cam_ptws turn it off on all cpus.
2614
2615 do_write.not_mod:
2616 stz inter generally don't interrupt on writes
2617 lda entry_sw see if write entry
2618 cmpa write_entry,dl
2619 tnz do_write.not_pri not, continue
2620
2621 lda int+pri,dl interrupt on write entry
2622 sta inter
2623 do_write.not_pri:
2624 tsx .ret,device_control$dev_write initiate the write
2625 tra unsavex
2626
2627 "^L
2628 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2629 "
2630 " done,done_
2631 "
2632 " Entry subroutine to post the completion of I/O.
2633 " Call is
2634 " call donecore_adderrcode
2635 " or
2636 " tsx7 done_
2637 "
2638 " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " " "
2639
2640 done:
2641 tra core_queue_man$disk_post
2642
2643
2644 done_:
2645 eppbb sst$ bb must point into SST for PAGE
2646 tsx .2ret,savex save return loc in stack
2647 lda core_add get core map entry pointer
2648 als coreadd_to_cmep.ls
2649 eax .cme,sst|sst.cmp,*au set up .cme
2650
2651 tsx .ret,pc_trace$done
2652 "
2653 " Flags to A-reg until we know where we're headed.
2654 "
2655 lxl .tem,cme_astep,*.cme save astep for later
2656 stx .tem,done_astep
2657
2658 lda cme_flags,*.cme see if a read/write sequence is active
2659
2660 ldq cme_devadd,*.cme pick up device address out of CM entry
2661 stq devadd and save in stack
2662
2663 ldx .ptw,cme_ptwp,*.cme get ptp
2664 tze page_error$error_in_done core must be used
2665 eppbp sst|0,.ptw
2666 lxl .tem,ptw|0 check for out of service
2667 canx .tem,ptw.os,du
2668 tze page_error$error_in_done
2669 lxl .aste,cme_astep,*.cme get astep
2670
2671 cana cme.io,dl Was this a write?
2672 tnz done_write yes, go handle it
2673 "tra done_read *** is on the next page ***
2674 "^L
2675 " done_read -- thread core in mru,
2676 " and turn on PTW access.
2677 "
2678
2679 done_read:
2680 tsx .ret,thread_in_mru make most recently used
2681
2682 szn errcode check error code
2683 tnz error_on_read error ...
2684 "
2685 " Check for device incomplete
2686 "
2687 tsx .ret,device_control$check_ckdv
2688 tsx .ret,check_pattern dvctl returns here if checking on
2689 tra done.read.no_ckdv_error c_p comes here if no error.
2690 "also, dvctl comes here if not checking!
2691 tsx .2ret,page_error$device_error
2692 tra error_on_read treat as fatal error
2693
2694 done.read.no_ckdv_error:
2695 lda ptw.valid+df1,dl turn on access
2696 orsa ptw|0
2697 lca ptw.os+1,dl turn off os bit
2698 ansa ptw|0
2699
2700 " tra notify_code " Actually just fall through to this
2701 "
2702 "
2703
2704 "
2705 "^L
2706 " Post a read or write complete, with or without error.
2707 " Call handler for I/O to volmap_seg.
2708 " Cause a page faulter to restart his fault, and cause
2709 " call side to retry.
2710 "
2711 notify_code:
2712 "
2713 " Check for notify_requested. If none, neither notify
2714 " nor idle pre_empt.
2715 "
2716 lda cme.notify_requested,dl get flag
2717 cana cme_flags,*.cme see if on in cme
2718 tze notify_end no, just return
2719 ersa cme_flags,*.cme was on. Turn off and
2720 "notify/preempt.
2721 done.notify.uncond:
2722 szn tc_data$pre_empt_flag see if we're pre-empting and notifying
2723 tnz check_idle we're not pre-empting. are we an idle process ?
2724 eaq 0,.ptw get event from ptw addr
2725 qrl 18
2726 stq pds$arg_1 save argument
2727 tra pxss$page_notify
2728
2729 entry notify_return
2730 notify_return:
2731 epp sst,sst$ restore sst pr, possibly for done_ entry.
2732 notify_end:
2733 ldx .tem,done_astep astep
2734 lda sst|aste.volmap_seg_word,.tem see if this is a volmap_seg
2735 cana aste.volmap_seg,dl
2736 tze unsavex no - return to the caller of done
2737 lda sst|aste.pvtx_word,.tem
2738 arl aste.pvtx_shift
2739 ana aste.pvtx_mask,dl pvtx in Areg
2740 tsx .ret,volmap_page$post_io do asynchronous stuff
2741 epp sst,sst$ restore
2742 tra unsavex return to caller of done
2743
2744 check_idle:
2745 ldaq pds$apt_ptr see if we're an idle process
2746 cmpaq prds$idle_ptr
2747 tnz notify_end no, just return
2748 lda apte.pre_empt_pending,du
2749 eppbp pds$apt_ptr,*
2750 orsa bp|apte.flags
2751 lxl1 prds$processor_tag
2752 stc2 pds$connect_pending
2753 cioc scs$cow_ptrs,1*
2754 tra notify_end
2755 "^L
2756 "
2757 " error_on_read - put Pdisk address back in PTW
2758 "
2759
2760 error_on_read:
2761 increment sst|sst.page_read_errors meter
2762 tsx .ret,cleanup_page out of core
2763
2764 lca ptw.os+1,dl Now oocore, off os.
2765 ansa ptw|0
2766
2767 lda ptw.er,dl mark ptw as signalable
2768 orsa ptw|0
2769 tsx .ret,get_pvtx
2770 tsx .ret,call_disk_emergency
2771 tra done.notify.uncond
2772 "^L
2773 "
2774 " done_write - remove O/S status,
2775 " and thread core in LRU.
2776 "
2777
2778 done_write:
2779
2780 lca 1,dl decrement global count of writes.
2781 asa sst|sst.wtct
2782 tpl *+2
2783 stz sst|sst.wtct make sure stays +.
2784
2785 lda ptw.phm+ptw.phu,dl count uses of pages being written
2786 cana ptw|0 ..
2787 tze *+2 not used, don't count
2788 increment sst|sst.mod_during_write
2789 lca ptw.os+ptw.er+1,dl turn off OS and ERR flags.
2790 ansa ptw|0
2791 lda ptw.valid,dl turn access on - it's off for synch pages
2792 orsa ptw|0
2793
2794 ldq errcode if error, go process it, passing
2795 tnz error_on_write error code in Q.
2796
2797 lca cme.phm_hedge+1,dl turn off write
2798 ansa cme_flags,*.cme scheduler and pd_upflag
2799
2800 "
2801 resurgo:
2802 lda cme_devadd,*.cme
2803 cana ptw.nulled,du is this null?
2804 tze rethread no, ordinary write.
2805 era ptw.nulled,du
2806 sta cme_devadd,*.cme
2807 increment sst|sst.resurrections meter
2808 resurgo.fmchanged:
2809 lda aste.fmchanged,du turn on fmc bit
2810 orsa ast|aste.fmchanged_word,.aste
2811 no_dblw:
2812 rethread:
2813 tsx .ret,thread_in insert in core map at lru
2814 tra notify_code and notify waiting processes
2815 "^L
2816 "
2817 " error_on_write - Zero data if data error,
2818 " but leave in core as modified if device inop.
2819 "
2820
2821 error_on_write: "errcode passed in Q.
2822 increment sst|sst.page_write_errors meter
2823
2824 canq errflags.memory_unusable,dl page damage or mem problem
2825 tnz done.werr.deverr
2826
2827
2828 " not pd case- analyze errcode
2829 canq errflags.device_inoperative,dl disk down?
2830 tnz write_device_inop yes, handle it
2831
2832 "
2833 " Must be data error on write
2834 done.werr.deverr:
2835 "
2836 lda aste.damaged,dl
2837 orsa ast|aste.damaged_word,.aste
2838 lda aste.fmchanged,du cause vtoce update
2839 orsa ast|aste.fmchanged_word,.aste
2840
2841 tsx .ret,thread_in get core in list
2842 lca ptw.valid+1,dl turn off access
2843 ansa ptw|0
2844 tsx .ret,cam_cache$cam_cache
2845 tsx .ret,cleanup_page drive guy out of core
2846
2847 lda ptw.er,dl
2848 orsa ptw|0
2849 "
2850 " Try for an older copy of the page in any case.
2851 "
2852 eax .ret,page_error$reverting_page assume some stuff out there
2853 lda cme_devadd,*.cme get diskaddr or pdaddr
2854 cana add_type.non_null,dl any good stuff atall?
2855 tnz done.werr.deverr.printerr ptw ok
2856
2857 eax .ret,page_error$zeroing_page
2858 ldq errcode see what case
2859 lda page_bad_null,du assume device lossage
2860 canq errflags.memory_unusable,dl
2861 tze *+2
2862 lda page_devparity_null,du parity case
2863 staddra ptw|0 in the ptw
2864 done.werr.deverr.printerr:
2865 tsx .ret,0,.ret print barfage
2866 lda errcode do we have to make main mem vanish?
2867 cana errflags.memory_unusable,dl
2868 tze done.notify.uncond exit
2869
2870 tsx .ret,delete_mm_frame delete this frame of main mem
2871 tra done.notify.uncond
2872 "cme has been freed, don't know whether
2873 "to notify or not, so do it.
2874
2875 write_device_inop:
2876 tsx .ret,get_pvtx
2877 tsx .ret,call_disk_emergency
2878
2879 lda ptw.phm1,dl turn mod bit back on
2880 orsa ptw|0
2881
2882 finish_write_error:
2883 tsx .ret,thread_in_mru avoid repl algorithm
2884 tra notify_code
2885
2886
2887
2888 "^L
2889 "
2890 " Clear out and deconfigure main memory frame.
2891 "
2892 delete_mm_frame:
2893 tsx .2ret,savex
2894 tsx .ret,thread_out good move
2895 lca 1,dl just zap first word
2896 sta cme_0,*.cme
2897 asa sst|sst.nused it's not used.
2898 tsx .ret,page_error$deleting_mm_frame annuntio
2899 tra unsavex
2900
2901 "
2902 " Subroutine to call disk_emergency on disk-errors,
2903 " So that he might make assessments of system-wide
2904 " implications of disk device status.
2905
2906 call_disk_emergency:
2907 sta pvtx pvtx in a-reg
2908 eppap pvtx
2909 spriap arg+2
2910 eppap errcode
2911 spriap arg+4
2912 ldaq =v18/4,18/4,36/0
2913 staq arg
2914 call disk_emergency$disk_emergencysp|arg
2915 tra 0,.ret
2916
2917
2918 end