DIRECTORY DiskFace USING [FileID, Type, DontCare, wordsPerPage], PrincOps USING [aASSOC, aGETF, alpha, aSETF, ControlLink, flagsVacant, FrameHandle, InterimPageState, PageCount, PageFlags, PageNumber, PageState, PageValue, RealPageNumber, zMISC], ProcessorFace USING [useLongMapOps]; BootFile: DEFINITIONS IMPORTS ProcessorFace = BEGIN OPEN PrincOps; currentVersion: CARDINAL = 102; Location: TYPE = MACHINE DEPENDENT RECORD[ deviceType(0): DiskFace.Type, deviceOrdinal(1): CARDINAL, vp(2): SELECT OVERLAID * FROM disk => [diskFileID(2): DiskFileID], ethernet => [bootFileNumber(2): CARDINAL, net(3), host(4): CARDINAL _ 0], any => [a(2), b(3), c(4), d(5), e(6), f(7), g(10B), h(11B): WORD], ENDCASE ]; DiskFileID: TYPE = MACHINE DEPENDENT RECORD[ fID: DiskFace.FileID, -- for disk label -- firstPage: INT, -- for disk label -- firstLink: DiskFace.DontCare -- initial boot chain link -- ]; nullLink: DiskFace.DontCare = LOOPHOLE[LONG[0]]; Header: TYPE = MACHINE DEPENDENT RECORD [ -- first page of boot file version(0): CARDINAL _ currentVersion, creationDate(1): LONG CARDINAL, -- System.GreenwichMeanTime pStartListHeader(3): POINTER, -- when continuation kind=initial (relative to that mds) inLoadMode(4): InLoadMode, continuation(5): Continuation, countData(7): CARDINAL, -- number of nonvacant pages (not counting germ) entries(HeaderStart): HeaderArray ]; HeaderStart: NAT = 10B; HeaderArray: TYPE = ARRAY [0..maxEntriesPerHeader) OF Entry; maxEntriesPerHeader: CARDINAL = (DiskFace.wordsPerPage-HeaderStart)/SIZE[Entry]; Trailer: TYPE = MACHINE DEPENDENT RECORD [ -- entry table after exhausting "Header" version(0): CARDINAL _ currentVersion, entries(1): TrailerArray ]; TrailerStart: NAT = 1; TrailerArray: TYPE = ARRAY [0..maxEntriesPerTrailer) OF Entry; maxEntriesPerTrailer: CARDINAL = (DiskFace.wordsPerPage-TrailerStart)/SIZE[Entry]; Entry: TYPE = MACHINE DEPENDENT RECORD [ page (0): CARDINAL, --PageNumber-- value (1): PageValue ]; InLoadMode: TYPE = {load, restore}; Continuation: TYPE = MACHINE DEPENDENT RECORD [ vp(0): SELECT kind(0:0..7): ContinuationKind FROM initial => [ mdsi(0:8..15): MDSIndex, destination(1): ControlLink ], resumptive => [ mdsi(0:8..15): MDSIndex, -- for WriteMDS hack -- resumee(1): FrameHandle ], ENDCASE ]; ContinuationKind: TYPE = {initial, resumptive}; MDSIndex: TYPE = RECORD [index: [0..256)]; -- high order bits of MDS base pointer MemorySizeToFileSize: PROC [countReal: PageCount] RETURNS [INT] = INLINE { RETURN[ countReal -- total data pages +1 -- header page +(MAX[countReal, maxEntriesPerHeader]-maxEntriesPerHeader+maxEntriesPerTrailer-1) /maxEntriesPerTrailer -- trailer pages ] }; aSETMAP: alpha = 150B; aGETMAPFLAGS: alpha = 151B; aSETMAPFLAGS: alpha = 152B; ExchangePageState: PROC [virtual: PageNumber, newState: PageState] RETURNS [pv: PageValue] = INLINE { OldExchangePageState: PROC [virtual: CARDINAL, state: InterimPageState] RETURNS [oldState: InterimPageState] = MACHINE CODE {zMISC, aSETF}; NewExchangePageState: PROC [vp: LONG CARDINAL, flgs: PageState] RETURNS [tState: PageState, rp: LONG CARDINAL] = MACHINE CODE {zMISC, aSETMAPFLAGS}; IF ProcessorFace.useLongMapOps THEN [tState: pv.state, rp: pv.real] _ NewExchangePageState[virtual, newState] ELSE [flags: pv.state.flags, realPage: pv.real] _ OldExchangePageState[virtual, InterimPageState[FALSE, newState.flags, 0]].oldState; }; ExchangePageFlags: PROC [virtual: PageNumber, newFlags: PageFlags] RETURNS [PageValue] = INLINE { RETURN ExchangePageState[virtual, PageStateFromFlags[newFlags]]; }; GetPageValue: PROC [virtual: PageNumber] RETURNS [pv: PageValue] = INLINE { OldGetPageValue: PROC [virtual: CARDINAL] RETURNS [state: InterimPageState] = MACHINE CODE {zMISC, aGETF}; NewGetPageValue: PROC [vp: LONG CARDINAL] RETURNS [tState: PageState, rp: LONG CARDINAL] = MACHINE CODE {zMISC, aGETMAPFLAGS}; IF ProcessorFace.useLongMapOps THEN [tState: pv.state, rp: pv.real] _ NewGetPageValue[virtual] ELSE [flags: pv.state.flags, realPage: pv.real] _ OldGetPageValue[virtual].state; }; SetPageValue: PROC [virtual: PageNumber, pv: PageValue] = INLINE { OldSetPageValue: PROC [virtual: CARDINAL, state: InterimPageState] = MACHINE CODE {zMISC, aASSOC}; NewSetPageValue: PROC [vp, rp: LONG CARDINAL, flgs: PageState] = MACHINE CODE {zMISC, aSETMAP}; IF ProcessorFace.useLongMapOps THEN NewSetPageValue[virtual, pv.real, pv.state] ELSE OldSetPageValue[virtual, InterimPageState[FALSE, pv.state.flags, pv.real]]; }; SetPageFlags: PROC [virtual: PageNumber, real: RealPageNumber, flags: PageFlags] = INLINE { SetPageValue[virtual, [state: PageStateFromFlags[flags], real: real]]; }; IsMapped: SAFE PROC [virtual: PageNumber] RETURNS [BOOL] = TRUSTED INLINE {RETURN[GetPageValue[virtual].state.flags ~= flagsVacant]}; IsVacant: SAFE PROC [virtual: PageNumber] RETURNS [BOOL] = TRUSTED INLINE {RETURN[GetPageValue[virtual].state.flags = flagsVacant]}; PageStateFromFlags: SAFE PROC [flags: PageFlags] RETURNS [PageState] = TRUSTED INLINE {RETURN[LOOPHOLE[flags]]}; END. tBootFile.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Andrew Birrell April 29, 1983 4:11 pm Russ Atkinson (RRA) February 27, 1985 8:39:30 pm PST Doug Wyatt, February 22, 1985 5:41:23 pm PST Layout of boot files. for boot files written using these definitions (see Header below) (102 corresponds to changes that allow > 1 Mword physical memory) Identification of a boot file for loading it. Commentary: A boot file is intended to capture the state of real memory and the relevant processor registers, most notably the map. It consists of a Header page followed by one or more data pages, followed by zero or more groups each consisting of a Trailer page followed by one or more data pages. Each Header or Trailer page assigns virtual and real addresses and flag bits to the accompanying data pages. The Header page contains some additional global state. Assertion: if Entry[p, v] precedes Entry[p', v'] in a boot file, then p is less than (and not equal to) p'. If a boot file does NOT contain an entry for a given page, that page is understood to be vacant. There are two variations of boot files, corresponding to whether the captured state is a snapshot of a running program or has been fabricated with "bit tweezers". In the former case (resumptive Continuation), some process is waiting on the BootSwap.pMon.condResponse condition variable. In the latter case (initial Continuation), a distinguished PSB is made ready to xfer to a given control link and the BootSwapGerm waits. There is an additional distinction depending on whether the inLoadMode of a boot file is load or resume. An inLoadMode=load signifies that the program captured in the boot file does not care into which real pages it is loaded. In this case InLoad expects all real memory to be mapped to an initial prefix of virtual memory; it leaves all excess real memory mapped immediately following the last virtual page it loads. (Thus those virtual pages between ones which are loaded are set vacant.) An inLoadMode=restore signifies that the program captured in the boot file expects to be reloaded into the real pages specified in the boot file. With either inLoadMode, the flags (W, D, R) of the loaded pages are set to the values specified in the boot file. To be distributed via the current ethernet boot servers, one of these boot files would have to be "encapsulated" by preceding it with a dummy page containing an appropriate timestamp. Calculate upper bound on file pages for boot file as function of real memory size. Utilities for Virtual Memory Map (wizards only) Note that these definitions are intended to be used BELOW the level of VMInternal in the system. Using these definitions will involve procedure calls, so the definitions in VMInternal are preferable for all code at or above the level of VM. Gets the state and real page of a virtual page; If the page is mapped, also sets the flags to newState. Gets the state and real page of a virtual page; If the page is mapped, also sets the flags to newFlags. Gets the state and real page of a virtual page. Sets the real page and state of a virtual page. Sets the real page and flags of a virtual page. Κ˜codešœ ™ Kšœ Οmœ1™Kšœžœ(žœ˜RK˜š œžœžœž œžœ˜(Kšœ žœŸ˜"Kšœ˜Kšœ˜—K˜Kšœ žœ˜#K˜š œžœžœž œžœ˜/šœžœ ž˜1šœ ˜ Kšœ˜Kšœ˜Kšœ˜—šœ˜KšœŸ˜0Kšœ˜Kšœ˜—Kšž˜—Kšœ˜K˜—šœžœ˜/K˜—Kšœ žœžœŸ&˜QK˜š Οnœžœžœžœžœ˜JKšœR™RKš žœ ŸœŸœžœcŸœ˜²Kšœ˜K˜—K™šŸ0™0K™K™ρ—˜K˜K˜K˜K˜š œž˜Kšœ*žœžœ˜Mšœ/™/Kšœ7™7—š œž˜Kšœ žœžœ˜SKšžœžœ˜—š œž˜Kš œžœžœžœžœžœ˜UKšžœžœ˜#—šžœ˜šž˜KšœI˜I—šž˜šœ,˜,Kšœ/žœ˜S———Kšœ˜K˜—š œž˜Kšœ*žœžœ˜Išœ/™/Kšœ7™7—Kšžœ:˜@Kšœ˜K˜—š  œžœžœžœ˜KKšœ/™/š œž˜Kšœ žœžœ˜7Kšžœžœ˜—š œž˜Kš œž œžœžœžœ˜DKšžœžœ˜#—šžœ˜šž˜Kšœ:˜:—šž˜KšœL˜L——Kšœ˜K˜—š  œžœ(žœ˜BKšœ/™/š œžœ žœ˜DKšžœžœ˜—š œžœ ž œ˜@Kšžœžœ˜—šžœ˜Kšžœ,˜0Kšžœ+žœ˜P—K˜K˜—š  œžœAžœ˜[Kšœ/™/KšœF˜FKšœ˜K˜—š  œžœžœžœžœ˜:Kšžœžœžœ4˜JK˜—š  œžœžœžœžœ˜:Kšžœžœžœ3˜IK˜—š œžœžœžœ˜FKšžœžœžœžœ ˜)—K™—Kšžœ˜—…—ž'