SUBSYSTEMS: Directory Control, Segment Control, Device Control, Page Control
Segment -- permanent storage on disk for a segment is comprised of
System Segment Table (sst) -- contains
Core Map - contains
Virtual Segment of a Process - described by a
After a process has initiated a segment, that segment is known as one of the process's virtual segments: a program running in that process can directly access words, characters or bits of that segment.
Steps taken to initiate the segment are outlined below as Task A. Task A was explained in the topic: initiate_seg.gi.info
Connect a Segment to a Process
A) Make Segment Known to the Process
- Find segment information using the
directory hierarchy.
- Verify process has some access rights to segment.
- If segment is on a private LV: verify LV is mounted and
attached by the user process.
- Get KSTE and SDW for segment.
- Re-use existing KSTE/SDW if segment already in-use by
process, or has been used earlier in the session.
- Extend seg access (if ACL/RBs now grant write access)
OR
- Describe new Virtual Segment to Hardware and Supervisor
- Fill-in faulted Segment Descriptor Word (SDW)
- Fill-in Known Segment Table Entry (KSTE)
However, the SDW for that virtual segment may not be valid when a program tries to reference the segment. In that case, the reference will cause a segment fault. The supervisor fault handler must perform the steps outlined below in Task B to connect the SDW and KSTE to an ASTE and Page Table describing the segment to Segment Control and Page Control.
B) Segment Fault When SDW is Accessed by the Process
- Find segment in, or add the segment to, the
List of Active Segments in-use by the system.
- Fill-in process access rights in SDW and KSTE.
- If process rights change encacheability of the segment,
change encacheability setting in SDWs of ALL referencing
processes.
- Add SDW Trailer Record (STR) to ASTE tracking this process as
referencing the active segment.
The "segment fault" mechanism ties together the structures that
describe the segment from several different viewpoints.
The next few sections of this topic present the relevant elements
of structures introduced earlier (describing a segment as it is stored
on disk, and as a virtual segment of a process); and then introduce
structures describing segments as they are activated for use by the
system. Further sections summarize the segment fault resolution
mechanism.
Structures for describing a segment stored permanently on disk were introduced by the topic: disk_segment.gi.info
These include the Directory Entry (entry) describing logical attributes
of the segment, and the Volume Table of Contents Entry (vtoce)
describing physical attributes of the segment.
For purposes of this info topic, the main elements of the entry
declaration (>ldd>incl>dir_entry.incl.pl1) are:
dcl 1 entry based (ep) aligned, /* Directory Entry */
...
2 uid bit (36), /* unique id of entry */
2 dtem bit (36), /* date-time entry modified */
...
2 pvid bit (36), /* physical volume id */
2 vtocx fixed bin (17), /* vtoc entry index */
...
2 dirsw bit (1), /* "1"b - entry is a directory seg */
/* "0"b - entry is a non-dir seg */
...
2 multiple_class bit (1), /* seg has several security classes*/
...
2 entrypt_sw bit (1), /* "1"b - call limiter enabled */
...
2 entrypt_bound bit (14), /* call limiter for gate segments */
2 access_class bit (72), /* security attributes: */
/* level and category */
2 ring_brackets (3) bit (3), /* ring brackets on segment */
2 ex_ring_brackets (3) bit (3),
/* extended ring brackets */
2 acle_count fixed bin (17), /* number of entries on ACL */
2 acl_frp bit (18), /* relp to start of ACL */
2 acl_brp bit (18), /* relp to end of ACL */
/* Both are offsets in dir seg */
...
2 bc fixed bin (24), /* bit count */
For purposes of this info topic, the main elements of the vtoce
declaration (>ldd>incl>vtoce.incl.pl1) are:
dcl 1 vtoce based (vtocep) aligned, /* VTOCE Entry */
2 uid bit (36), /* segment uid - "0"b if vtoce free */
2 msl bit (9), /* max seg length */
2 csl bit (9), /* current seg length */
2 records bit (9), /* number of records used on disk */
... /* above 3 items in 1024-word units*/
2 dtu bit (36), /* date/time segment last used */
2 dtm bit (36), /* date/time segment last modified */
...
2 fm (0:255) bit (18), /* file map - each positive value is*/
/* index of a 1024-word record in */
/* disk record array on that */
/* physical disk volume; or */
/* "000000"b - null disk address */
/* (record holds only "0"b bits) */
Structures describing a segment as a virtual segment of a process were introduced by the topic: virtual_segment.gi.info
These include: the hardware-software register: SDW; and software's extra information about the segment: KSTE.
The next few sections add a few more details about how the virtual segments of a process are described to the hardware; and present portions of the SDW and KSTE structures that are significant to the segment fault resolution mechanism.
As each process is scheduled to run on a hardware processor (CPU), its
memory workspace is defined to that CPU by loading the CPU's
Descriptor Base Register (DBR) with information about the process's
Descriptor Segment ([pd]>dseg).
The DBR contains some of the same information as an SDW for the dseg:
Whenever the azm select_process (slp) request selects a process for
display, its DBR address (dbr.add element) is listed as an octal
address as shown in the following slp output:
Proc 9 DBR 16630134 running on cpu a GDixon.Multics.a
However, the complete DBR register contents for each process is saved
in its Active Process Table Entry (apte.dbr). APTE structures
(>ldd>incl>apte.incl.pl1) are displayed by the azm apte request.
For example:
azm: apte -run
APTE #12 at ADDR 4100:
Processid: 004100247203 (GDixon.Multics.a); DBR: 16630134
State: running at 2/18/* 17:49:25.522731
APTE structures are stored in Traffic Control's tc_data segment.
azm: d tc_data|4100 -as apte.dbr
dbr = 1091842560835687055379
Seeing the DBR contents as a long decimal number isn't very helpful.
The offset within the APTE for the 2-word apte.dbr element can be
obtained using the azm search request to look for the first 12 digits
of the DBR's octal value in the apte structure.
azm: octal 1091842560835687055379
166301340004001775100023o
azm: search tc_data|4100 100 166301340004
Segment 112 tc_data
from 4100 to 4200
112|4144 = 166301340004
Knowing the location of the apte.dbr element allows the full DBR
structure to be displayed.
azm: d tc_data|4144 -as l68_dbr
l68_dbr at 112|4144
add = "16630134"b3, bound = "00000001111111"b, stack_base_segno = 19
OFF: unpaged
Its dbr.bound value defines the number of SDWs stored in the pages of
the dseg.
azm: calc "(1111111b+1)*16"
= 2048
The normal dseg is 2048 words (2 pages) long; and each SDW occupies 2
words. So this dseg contains SDWs describing 1024 segments.
Its dbr.stack_base_segno gives the first two digits of stack segment
numbers. 19 decimal is 23 octal; concatenated with the octal
ring-of-execution number gives the octal segment number of the stack
segment in each ring-of-execution: 230 is the segment number for
[pd]>stack_0, 231 for [pd]>stack_1, ..., 234 for [pd]>stack_4, etc.
The CALL6 instruction uses this value to select the stack segment when
crossing into a lower (more privileged) ring-of-execution.
See the Multics Processor Manual (AL39-01C) description of the CALL6 instruction for a discussion of this stack segno identification mechanism.
See Figure 5-3 in that same manual for a diagram showing how loading the DBR register defines a process workspace to the CPU hardware.
For any active process, the supervisor can examine the workspace of
that process using an abs_seg: a ring-0 temporary virtual segment
which can overlay any active segment using information in its ASTE and
associated page table.
Segment Control holds in the sst (prevents from being deactivated) the
ASTE describing the Descriptor Segment (dseg) of each active process.
An abs_seg can overlay another process's dseg (using the apte.dbr
values, as described above) to access any SDW of that process. This is
an important capability, because the SDWs for all processes referencing
a given segment must be updated when the segment changes length, or
access attributes, or is deactivated, etc.
For the process running on a CPU, the supervisor can use a variable
to locate that process' dseg ASTE:
dcl pds$dstep bit (18) aligned external;
/* offset in sst_seg of ASTE for process' dseg */
The Process Data Segment ([pd]>pds) is an object segment describing
properties of a process. Each process has its own copy of the pds
segment.
However, the supervisor can access any SDW in the running process
directly by referencing that sdw in its dseg array of SDWs:
sdwap = addr(dseg$);
sdwp = addr(sdwa(segno));
Each virtual segment of a process is defined to the hardware by a
Segment Descriptor Word (SDW); and defined to the supervisor by its
SDW plus the Known Segment Table Entry (KSTE) for that segment.
For purposes of this info topic, the process' array of SDWs can be
described as follows:
dcl 1 sdwa (0:1023) based (sdwap) aligned like sdw; /* SDW array */
The sole content of the process' Descriptor Segment ([pd]>dseg) is
this array of SDWs.
The complete SDW structure is declared below. Data elements of the
SDW and its page table tell the hardware exactly what access was
granted to the process (by the disk segment's ACL, ring brackets, and
AIM access controls) in each possible ring of execution.
dcl 1 sdw based (sdwp) aligned, /* Segment Descriptor Word */
(2 add bit (24), /* absolute address in hardware memory*/
/* of virtual seg's page table */
2 (r1, r2, r3) bit (3), /* ring brackets for the segment */
2 df bit (1), /* "0"b = seg ^valid (directed fault) */
/* "1"b = seg valid (no fault occurs)*/
2 df_no bit (2), /* "00"b = fault treated as seg fault */
2 pad1 bit (1),
2 bound bit (14), /* segment length (in 16 word blocks) */
2 access, /* access bits: */
/* a running program can... */
3 read bit (1), /* "1"b = read seg's bits/chars/words */
3 execute bit (1), /* "1"b = execute or transfer to seg */
/* words as instructions */
3 write bit (1), /* "1"b = write seg's bits/chars/words*/
3 privileged bit (1), /* "1"b = seg holding running program */
/* can include "privileged */
/* instructions" only allowed*/
/* in ring-0 supervisor code.*/
2 unpaged bit (1), /* "0"b = segment is paged. Only */
/* ring-0 segs can be unpaged. */
2 entry_bound_sw bit (1), /* "0"b = entry to seg via CALL6 only */
/* to certain words at start */
/* of a gate segment. */
/* "1"b = segment is NOT a gate. */
2 cache bit (1), /* "1"b = segment data loaded through */
/* cache memory. */
2 entry_bound bit (14)) /* entry bound - CALL6 ADDR limit */
/* ADDR <= seg|entry_bound */
) unaligned;
Information in the "Known Segment Table (kst) header" includes:
For purposes of this info topic, the main elements of the kst and kste
declarations are:
dcl 1 kst aligned based (kstp), /* KST header */
...
2 uid_hash_bucket (0 : 127) bit (18) unaligned,
/* hash buckets */
2 kst_entry (0 refer (kst.lowseg):0 refer (kst.highseg))
aligned like kste, /* kst entries */
...
The KSTE for a given segment number can be located in the kst
segment of the process.
kstep = addr( kst.kst_entry(seg_fault_referenced_segno) );
Each "Known Segment Table Entry (kste)" structure holds information
which must be supplied from the ASTE or the directory entry describing
the active segment. These include the following elements:
dcl 1 kste based (kstep) aligned, /* KST entry */
2 fp bit (18) unaligned, /* forward relp to thread of */
/* KSTEs in a uid hash bucket*/
/* list or free KSTE list. */
2 segno fixed bin (17) unaligned, /* segment number */
2 usage_count (0:7) /* count of initiates in each */
fixed bin (8) unaligned, /* ring-of-execution */
2 entryp ptr unaligned, /* branch pointer */
2 uid bit (36) aligned, /* unique identifier */
2 access_information unaligned,
3 dtbm bit (36), /* date time branch modified */
3 extended_access bit (33), /* extended access from entry */
3 access bit (3), /* rew */
3 ex_rb (3) bit (3), /* extended ring brackets */
...
2 flags unaligned,
3 dirsw bit (1), /* directory switch */
...
Segment Control provides the glue that connects the two preceding views
of a segment. It assigns an ASTE and Page Table structure when
"activating the segment": adding it to the list of segments currently
in-use on the system. And it records which processes have "initiated
the segment": threading to the segment's ASTE an SDW Trailer Record
(str) structure for each process accessing the segment.
The next few sections introduce these data structures and the segments
that contain them.
Segment Control maintains the "List of Active Segments". Page Control
maintains a related "Core Map List" describing current contents of
each page of hardware memory. Both lists begin in the SST header.
The "System Segment Table (SST)" ...
Earlier versions of sst_seg also held the array of structures that
describe how each frame in hardware memory is used: Core Map Entries
(CMEs). This array has been moved to a separate segment: the
core_map segment. However, header information for the Core Map List
remains in the SST. Thus, the SST is shared by both Segment Control
and Page Control subsystems.
The sst structure (>ldd>incl>sst.incl.pl1) resides at the base of the
sst_seg supervisor segment; that segment has a second name: sst. Since
this segment holds page tables, the sst pages must be wired in memory
frames. Page Control cannot take a page fault while referencing an
ASTE or Page Table.
Demand Paging hardware requires pages of sst_seg to be in consecutive
hardware memory frames because the hardware requires all PTWs of a
Page Table array to reside in contiguous words of hardware memory.
If a Page Table crosses a page boundary, the two halves of the table
must reside in contiguous hardware memory frames. For this reason, all
SST pages are in contiguous memory frames.
Page Control software also requires these pages to be in consecutive
order within hardware memory. It depends on this feature to convert
the absolute address of a page table (given by sdw.add) to a relative
offset of that Page Table within the sst_seg (referenced by cme.ptwp
values): pt_offset_in_sst = sdw.add - sst.ptwbase;
For purposes of this info topic, the main elements of the sst declaration are:
dcl sst_seg$ external; /* sst seg location as PL/1 variable */
dcl 1 sst based (sstp) aligned, /* System Segment Table */
2 space (8) fixed bin, /* empty space to watch for bugs */
/* SST HEADER */
/* locks for ... */
2 ptl bit (36), /* - global page table (a loop lock) */
2 astl bit (36), /* - global ast allocs (a block lock) */
2 astl_event bit (36), /* - wait_event for waits on AST lock */
...
2 nused fixed bin, /* count of page control memory frames */
2 ptwbase fixed bin (24), /* absolute address of sst_seg */
2 tfreep ptr, /* pointer to 1st free STR in str_seg */
2 astap ptr, /* pointer to 1st ASTE in sst_seg */
...
2 root_astep ptr, /* pointer to AST for root (">") dir */
2 pts (0: 3) fixed bin, /* array of page table sizes (in pages)*/
2 level (0:3), /* pool of ASTE's by page table size */
3 (ausedp, /* relp to 1st ASTE in this pool */
no_aste /* count of ASTEs in this pool */
) bit (18) unaligned,
...
/* CORE MAP HEADER */
2 cmp ptr, /* pointer to start of CME array in */
/* core_map seg. */
2 usedp bit (18), /* relp to threaded list of CMEs */
/* managed by Page Control. */
...
/* OTHER AST ELEMENTS */
2 ast_ht_ptr ptr, /* ASTE hash table pointer */
/* hashed by aste.uid (= entry.uid) */
2 ast_ht_n_buckets fixed bin,
/* no. of buckets in ASTE hash table */
...
2 n_trailers fixed bin, /* length of ASTE SDW Trailer Record */
/* array (STR structs in str_seg$) */
...
2 wusedp bit (18), /* relp to next CME to be examined by */
/* claim_mod_core for write to disk */
...
An "Active Segment Table Entry (ASTE)" precedes each Page Table in the
SST. The ASTE holds information about the disk storage for the
segment being accessed by that Page Table. This information includes:
aste.uid);aste.msl);aste.csl);aste.records);aste.dirsw);aste.pvtx, aste.vtocx).aste.np).The group of ASTEs form the system's "List of Active Segments".
Segment Control limits the number of segments in its active segments
list by pre-allocating storage for a fixed count of Page Tables in
four popular lengths: 4-, 16-, 64- and 256-PTWs long. ASTEs
associated with Page Tables of the same size are pooled (threaded
together) in the SST segment (sst.level(N) substructure where N ranges
from 0 and 3 to choose from the 4 page table lengths above).
Each aste structure (>ldd>incl>aste.incl.pl1) is even-word-aligned and
occupies 12 words in memory. For purposes of this info topic, the
main elements of the aste declaration are:
dcl 1 aste based (astep) aligned, /* Active Segment Table Entry */
(2 fp bit (18), /* forward ausedp thread relp */
2 bp bit (18), /* backward ausedp thread relp */
/* Both are offsets within sst_seg. */
...
2 strp bit (18), /* relp to ASTE SDW Trailer Record (STR) */
/* in str_seg. */
2 par_astep bit (18), /* relp to parent dir's ASTE in sst_seg */
2 uid bit (36), /* segment unique id */
2 msl bit (9), /* maximum seg length in 1024-word units */
2 pvtx fixed bin (8), /* seg physical disk volume table index */
2 vtocx fixed bin (17), /* seg vtoc entry index */
2 usedf bit (1), /* ASTE is being used if non-zero */
...
2 dirsw bit (1), /* ="1"b ASTE is for a directory */
2 master_dir bit (1), /* ="1"b master dir - root of log. vol.*/
2 volmap_seg bit (1), /* ="1"b phys vol bit map: for pvtx */
/* (ASTE does not describe a real seg) */
...
2 dtu bit (36), /* date and time segment last used */
2 dtm bit (36), /* date and time segment last modified */
...
2 csl bit (9), /* current seg length in 1024-word units */
...
2 records bit (9), /* count of records used on disk for seg */
2 np bit (9), /* count of seg pages currently in memory*/
...
2 ptsi bit (2), /* page table size index */
/* ="00"b 4-word page table follows */
/* ="01"b 16-word page table follows */
/* ="10"b 64-word page table follows */
/* ="11"b 256-word page table follows */
2 marker bit (6) /* marker to indicate last word of ASTE */
) unaligned;
For purposes of this info topic, the Page Table which follows a given
ASTE can be located from its associated ASTE's location.
For an ASTE located by astep pointer...
ptp = addwordno( astep, size(aste) );
pt_size = sst.pts( fixed(aste.ptsi) ) - 1;
dcl 1 ptwa (0:pt_size) based (ptp) aligned like ptw; /* Page Table */
For a description of the PL/I addwordno and wordno builtin functions,
use the Multics help command: help pl1_new_features
Each SDW Trailer Record (str) tracks use by a process of an ASTE and
its associated Page Table. These STR records are threaded onto the
ASTE (aste.strp).
The str (>ldd>incl>str.incl.pl1) is a word aligned structure stored in
two words of the str_seg segment. Its full declaration is:
dcl 1 str based (strp) aligned, /* SDW Trailer Record (STR) */
(2 fp bit (18), /* forward STR thread relp */
2 bp bit (18), /* backward STR thread relp */
/* Both are offsets in str_seg. */
2 segno bit (18), /* segment number of referencing */
/* SDW in other process's dseg. */
2 dstep bit (18) /* offset w/in sst_seg of ASTE for */
) unaligned; /* that process's dseg segment. */
The str.dstep provides a third way of locating another process's dseg
ASTE and Page Table so an abs_segcan be setup to reference that
process's SDWs.
The next section describes how the segment fault handler of the
supervisor "activates a segment" by either:
When an instruction in the executing program references a segment whose
SDW is invalid (sdw.df="0"b and sdw.df_no="00"b), a "segment fault"
event occurs.
To handle the fault, the processor shifts the process execution point
into the fault_vector segment: a ring-0 supervisor segment containing
an array of instruction pairs, one pair for each fault type.
The pair for a segment fault (directed fault 0) does the following:
fim.alm) entry point which stores contents of all registers intoThe seg_fault entry point receives one input argument, a pointer to
the stored machine conditions (>ldd>incl>mc.incl.pl1). For a segment
fault, fim pushes its own stack frame on the ring-0 stack (stack_0);
and stores the machine conditions data at: pds$fim_data
addr(pds$fim_data) ---> mcp
call seg_fault( mcp );
seg_fault checks the machine conditions to determine whether the fault
occurred:
Processor state data in the machine conditions tells the code which of
these two possibilities caused the segment fault. seg_fault then
obtains a segment number (segno) from either:
seg_fault first checks whether the segment reference was to a stack
segment which is unknown to the process. A stack segment provides
automatic storage and subroutine call history for a ring-of-execution.
Notice that the CALL6 instruction generates a reference to the
inner-ring stack when crossing into a lower, more privileged ring.
Process initialization code creates the ring-0 stack segment for each
process. The Multics supervisor must create the stack segment when
the first call to a ring (other than ring-0) occurs.
[pd]>stack_N);initiate_ to make the new stack known to the processFor details on initiate_.pl1, select the link: initiate_seg.gi.info
makestack returns, seg_fault returns to its caller to causeseg_fault. The SDW and KSTE are now in aseg_fault will occur to resolve that fault using the updated SDWThe next sections of this topic describe steps taken by seg_fault
to locate and update contents of the SDW and KSTE for the segment being
referenced when the segment fault occurred.
The mechanism for "Connecting a segment to a process" assigned a
segment number by which that segment was known in the process. That
segment number identifies an SDW and KSTE in the process.
For details of this connection mechanism, select: initiate_seg.gi.info
Using the faulted SDW's segment number from the machine conditions,
seg_fault then:
Gets a pointer to the faulting process' KSTE (kstep) for the faulted
segment.
Calls sum$getbranch_root_my to get the directory entry describing
the faulted segment. This call validates contents of kste.entryp
that points to the directory entry as it is known to that process.
call sum$getbranch_root_my (segptr, "0"b, ep, code);
Note that every directory named in a pathname passed to the
supervisor must be known in the calling process to permit the
supervisor running in that process to search in that directory. Thus, the call to sum$getbranch_root_my may cause recursive
seg_fault events as sum accesses directories superior to the parent
directory of the faulted segment.
sum returns to seg_fault with a pointer (ep) to the directory entry
describing the faulted segment, and with the containing parent
directory locked. The entry structure is based on the ep pointer.
After initiating a segment not previously known to the process, the
KSTE and SDW contain no information about mode of access the process
is authorized to have for that segment. To obtain access mode
information, seg_fault must do the following.
dc_find$seg_fault to set access elements of the KSTE basedPerson_ID.Project_ID of the process by call dc_find$seg_fault (kstep, ep, code);
dc_find calls the update_kste_access.pl1 subroutine to store
access elements in the KSTE for a segment.
update_kste_access calls access_mode$authorization toPerson_ID.Project_ID of the process;update_kste_access returns the mode and ex_mode to dc_find.dc_find$seg_fault uses the mode, ex_mode and data from the
directory entry (ring bracket values) to set access fields in
SDW and KSTE.
- ring_brackets (entry.ring_brackets(1)) ---> (sdw.r1)
(entry.ring_brackets(2)) ---> (sdw.r2)
(entry.ring_brackets(3)) ---> (sdw.r3)
- mode (mode) ---> string(sdw.access)
(mode) ---> (kste.mode)
- ex_mode (ex_mode) ---> (kste.ex_mode)
- date/time entry modified (entry.dtem) ---> (kste.dtbm)
The entry.dtem is copied into the KSTE to record the most recent
date/time stamp at which process' access to the segment was last
determined.
seg_fault continues to resolve the segment fault.
Copy gate-related information (entry.entrypt_sw,
entry.entrypt_bound) from the directory entry while the directory
is locked. This will be used later when updating the SDW.
If the faulted segment is stored on a private Logical Volume (LV),
seg_fault checks that this LV has been mounted and that the LV was
attached by the process.
seg_fault calls activate$activate_long (in activate.pl1) to obtain an
ASTE and associated Page Table for the faulted segment. A pointer to
the ASTE is returned, and the Active Segment Table (AST) remains
locked. The page table size (aste.ptsi) is already set in this ASTE.
astep = call activate$activate_long( ep, activated_sw, code );
ptp = addwordno( astep, size(aste) );
If the segment was already activated (activated_sw="0"b), the
astep pointer locates the existing ASTE and its Page Table.
OR, a free ASTE in the pool with Page Table size >= vtoce.csl is
selected; and that ASTE and Page Table are initialized.
- physical volume ID (entry.pvid) --~> (aste.pvtx)
- vtoce index on PV (entry.vtocx) ---> (aste.vtocx)
- branch type (entry.dirsw) ---> (aste.dirsw)
- maximum length (vtoce.msl) ---> (aste.msl)
- current length (vtoce.csl) ---> (aste.csl)
- no of records on disk (vtoce.records) ---> (aste.records)
- count of pages in memory "0"b ---> (aste.np)
- date last used (vtoce.dtu) ---> (aste.dtu)
- date last modified (vtoce.dtm) ---> (aste.dtm)
- multi_class (entry.multiple_class) ---> (aste.multi_class)
- Page Table do i = 0 to vtoce.csl-1;
(vtoce.fm(i)) ---> (ptw(i).add)
end;
- ASTE & Page Table in-use "1"b ---> (aste.usedf)
- unique ID (entry.uid) ---> (aste.uid)
The physical volume ID in the directory entry (entry.pvid) is
changed to a physical volume index (aste.pvtx) of the equivalent
disk in the Storage System's "Physical Volume Table (PVT)".
- dstep pds$dstep ---> str.dstep
- segno segno ---> str.segno
- fp aste.strp ---> str.fp
- bp "0"b ---> str.bp
The STR is then threaded onto the ASTE.
wordno(strp) ---> pointer( str_seg$, aste.strp ) -> str.bp
wordno(strp) ---> aste.strp
This STR threaded list allows Segment Control to adjust all SDWs
referencing a segment if:
seg_fault is finally ready to resolve the segment fault by updating
final information in the SDW for the faulted segment.
Update the SDW for the segment with latest effective access and
encacheability settings.
For a directory segment:
Note that seg_fault gives all processes read-write access to all
directories to permit searches of directories for a specific entry
name (even if the process does not have status mode on that
directory). Directory Control software recalculates the process'
effective access to the directory if the process tries to list
the directory or modify its contents.
For a non-directory segment, the call to dc_find$seg_fault
(described above) sets the sdw.access and sdw.(r1 r2 r3) fields.
If only one process is accessing the segment, or none of the
accessing processes have write access, then the SDW is marked as
encacheable:
For a gate segment, additional SDW updates are needed.
- entry_bound_sw (^entry.entrypt_sw) ---> sdw.entry_bound_sw
- gate_entry_bound (entry.entrypt_bound) ---> sdw.entry_bound
For all segments, a bound (in 16-word blocks) is placed on the length
to which the segment can be extended using the calculation shown
below. Then the SDW is marked as valid.
page_table_size = sst$pts ( aste.ptsi );
seg_words = min( page_table_size, aste.msl ) * 1024;
seg_16_word_blocks = (seg_words + 15) / 16;
- bound (seg_16_word_blocks - 1) ---> sdw.bound
- page table wordno(ptp) + sst.ptwbase ---> sdw.add
- valid SDW "1"b ---> sdw.df
seg_fault ends by unlocking the AST and the parent directory. When
seg_fault returns, the fim code issues an RCU instruction to restart
the faulting instruction with the SDW now valid for use in the
segment-fault-interrupted instruction reference.
When seg_fault returns, the process has connected an SDW for a segment with a supporting Page Table describing pages of the virtual segment. However, if the process is the first process to initiate the segment, none of its pages will be in hardware memory. Reference to any page will cause a "page fault" event.
The next topic explains steps taken by the Page Control subsystem to read a segment's permanent record from disk into a hardware memory frame whenever the corresponding page of the virtual segment is referenced. To display that topic select the link: demand_paging.gi.info