{tentative}Segment Fault Actions
A message is sent to the segment keeper providing information and authority sufficient to change the segment so as to conform to the requirements of the memory access {which will presumably be repeated when the domain is restarted}. {(segkeepcall)}
When the segment keeper is done it uses a fault key to report back. If it was successful then it sends 0 as the return code which results in the action described at (f31). In this case the domain's trap code does not cause a trap to the domain's keeper because there is never a process in the domain while the trap code is nonzero.
If the keeper didn't repair the segment then the keeper sends back a seven-bit nonzero excuse as its return code, which is incorporated in the trap code as a message to the domain's keeper by the logic described at (f32). The kernel-supplied keeper always returns the error code.
This {new} fault handling allows a program to more easily establish which sub segment caused an unanticipated trap by the program running in the domain.
The Gnosis memory tree logic partly overcomes the limitations of the small address. A Gnosis style memory tree can be built, for example, with three 1 meg segments and fifty 64K segments. This could not be done if the 24 bit virtual address had been permanently divided into segment and byte portions.
With window keys, segments with sizes such as 2 & 3 meg can be placed directly in the virtual memory, {impossible with Multics}.
With much larger segments windowing must be dynamically managed by the program.
The owner of the segment has even more obvious reasons for turning on these bits -- to keep the segment from being influenced.
Here are two applications which seems to require the NO_CALL bit.
X constructs a segment node S' with LSS = 12 and with segment keeper X1. A segment key to S with the NO_CALL bit on is placed in S'. Everything works fine until P references an address A relative to S with no page behind it. In that case X1 gets control and is told A. X1 runs under the same meter and charge set as P {the contract meter perhaps} so that meter is not coasting. {X should be able to transfer the CPU charge that X1 runs up from P's meter to some other meter.} X1 notes the coasting counter in P's meter then references address A in S {using a key to S without the NO_CALL bit}. This causes the segment keeper in S to be called, and P's meter is {may be} now coasting. When S's segment keeper returns to X1, X1 resets the coasting counter in P's meter to its former value {transferring the difference to X's meter} and then returns to P. This solution probably requires S to be consistent.
If the kernel called the first keeper, the domain designer could insulate his domain from memory traps by installing a keeper next to the domain that would provide pages for addresses that other segment keepers trapped on. This intermediate keeper first probes the lower segment keeper to see if it will provide the page.
But this effect can be had in the current design by the use of the no-call bit. The domain designer installs a segment node with a keeper for his memory tree root. In this node he places a segmode key with the no-call bit to a node that holds the original memory tree root. The keeper is given direct access to this latter root.
Gnosis once prohibited node keys from serving the function of segment keys in segment nodes so that synthetic node keys might be supported. If this were not the case a synthetic node key {really a gate} would fail when used in the position of a node key in a segment node.
It turns out that a segment key can model a node key in the role of either a place to put keys or, in its other function, as a memory key.
If a start key is found in a memory tree slot which the program is accessing the start key is called as if it were a segment keeper key except that no node key {to a segment node} is passed. This is to provide an archive service where a page key has been replaced by a tape block entry, which is a program that knows how to get the real page back. This mechanism does not provide for access to the segment node; to do so would create Trojan Horses in the form of alleged pages that were entries. The archiver must resort to some other {god?} license to replace these entries with the new page keys.
How shall we build a 50 page segment with a segment keeper? We first build three 16 page segments and a two page segment. The segment nodes defining the 16 page segments must be black in order hold the 16 page keys for the constituent pages. We then make segmode keys to these four segment nodes and place them in a new node that we format as a red segment node. Also in the new node is the start key for the segment keeper. If the new node were not red there would be no room for the segment keeper key.
If the top node were black, segment keys to the node would specify an lss of 4 and the segment would be forever limited to 256 pages because there is no general way to find and access all of those segment keys. With a red segment node the lss can be increased to meet future requirements because the only record of the lss is in the red segment node to which we may retain access.
Specifically we are vulnerable to instruction termination due to protection exceptions caused by mismatch of storage key and PSW key. We seek here the minimum kernel architecture change to support programs in coping with machines that terminate upon protection exceptions when those programs are expected to run thru ports to machines with such behavior.
The bit in the data byte that we define here may also be of use in machines that sport memory mapped IO.
Consider a state machine M that travels down the memory tree from the domain to the page. Call the states A, B, C, W and F just now. As a domain performs a read access, M is initialized to state A. The initial state is W for a domain that performs a write operation. Four stimuli drive M's state. Encounters with TP (Termination Protection) bits, encounters with RO (read-only) bits on a CPU that does not terminate, encounters of RO on CPUs that do (ROT), and page keys.
State B - Need write access if CPU terminates
State C - Need read only access
State W - Need write access
State F - Futile, will fault, but how?
An entry "fault" in this table indicates that the state machine stops at that point in the tree and a fault in reported to the appropriate keeper. Non read-only faults are not shown above. State B, encountering a RO bit on a CPU that terminates (ROT) may either fault or go into state F depend on the model of the kernel. If a non-memory key should occur subsequent to the RO bit then some other access fault would be reported to the segment keeper.
I find the above information much clearer as a state diagram.
An alternate state diagram
The TP bit is never ignored. This state machine has the advantage, I think, in the following case. If the memory tree has a TP bit, then a RO bit, then a bad key, it will complain about the key regardless of what kind of machine you run on. Another advantage is that the test for the kind of machine is done only once, just before filling in the page table entry.
The meaning of the message to the segment keeper in this latter case is: "Someone tried to access a page in your segment. He only has read access but does not want read access unless he can have write access." How is the keeper to respond?
{ni}Define a way to get a page key with the TP bit. The kernel is coded to interpret bit but not to produce it.
An application that intends to write into an area of storage that may be kept by a segment keeper that is designed to respond to write faults, interposes a memory key with the termination protection bit set. This has the effect of signaling the segment keeper with a write fault upon first read of a given page of the segment. There are two interesting cases. (1) The real write is nearly as early as the first read, in which case there is little extra cost. (2) The real write comes never or much later. In this case an extra page is required for this duration that would not otherwise have been needed on machines that do not terminate instructions.