DIRECTORY PrincOpsUtils USING[ LongCOPY ], PrincOps USING[ BytePC, InstWord, op, zBRK ], VM USING[ PageNumberForAddress, MakeReadOnly, MakeReadWrite, PageNumber, State ], WorldVM USING[ Address, LocalWorld, World ], WVMPrivate USING[ GetPage, PageData, PageHandle, PageNumber, pageSize, ReleasePage, WriteAndReleasePage ]; WVMImpl: MONITOR-- mutual exclusion on making code pages writable(!) -- IMPORTS PrincOpsUtils, VM, WorldVM, WVMPrivate EXPORTS WorldVM, WVMPrivate = BEGIN OPEN WorldVM; local: WorldVM.World = WorldVM.LocalWorld[]; Read: PUBLIC PROC[world: World, addr: Address] RETURNS[ i: CARDINAL ] = BEGIN n: WVMPrivate.PageNumber; w: [0..WVMPrivate.pageSize); h: WVMPrivate.PageHandle; d: REF WVMPrivate.PageData; IF world = local THEN RETURN[LOOPHOLE[addr, LONG POINTER TO CARDINAL]^]; [n, w, h, d] _ PageFromAddr[world, addr]; i _ d[w]; WVMPrivate.ReleasePage[h]; END; Write: PUBLIC PROC[world: World, addr: Address, value: CARDINAL] = BEGIN n: WVMPrivate.PageNumber; w: [0..WVMPrivate.pageSize); h: WVMPrivate.PageHandle; d: REF WVMPrivate.PageData; IF world = local THEN { LOOPHOLE[addr, LONG POINTER TO CARDINAL]^ _ value; RETURN }; [n, w, h, d] _ PageFromAddr[world, addr]; d[w] _ value; WVMPrivate.WriteAndReleasePage[h]; END; LongRead: PUBLIC PROC[world: World, addr: Address] RETURNS[ i: LONG CARDINAL ] = BEGIN n: WVMPrivate.PageNumber; w: [0..WVMPrivate.pageSize); h: WVMPrivate.PageHandle; d: REF WVMPrivate.PageData; IF world = local THEN RETURN[LOOPHOLE[addr, LONG POINTER TO LONG CARDINAL]^]; [n, w, h, d] _ PageFromAddr[world, addr]; IF w = WVMPrivate.pageSize-1 THEN { WVMPrivate.ReleasePage[h]; CopyRead[world,addr,SIZE[LONG CARDINAL],@i] } ELSE BEGIN i _ LOOPHOLE[@d[w],LONG POINTER TO LONG CARDINAL]^; WVMPrivate.ReleasePage[h]; END; END; LongWrite: PUBLIC PROC[world: World, addr: Address, value: LONG CARDINAL] = BEGIN n: WVMPrivate.PageNumber; w: [0..WVMPrivate.pageSize); h: WVMPrivate.PageHandle; d: REF WVMPrivate.PageData; IF world = local THEN { LOOPHOLE[addr, LONG POINTER TO LONG CARDINAL]^ _ value; RETURN }; [n, w, h, d] _ PageFromAddr[world, addr]; IF w = WVMPrivate.pageSize-1 THEN { WVMPrivate.ReleasePage[h]; CopyWrite[world,@value,SIZE[LONG CARDINAL],addr] } ELSE BEGIN LOOPHOLE[@d[w],LONG POINTER TO LONG CARDINAL]^ _ value; WVMPrivate.WriteAndReleasePage[h]; END; END; CopyRead: PUBLIC PROC[world: World, from: Address, nwords: INT, to: LONG POINTER] = BEGIN n: WVMPrivate.PageNumber; w: [0..WVMPrivate.pageSize); h: WVMPrivate.PageHandle; d: REF WVMPrivate.PageData; IF world = local THEN { PrincOpsUtils.LongCOPY[from: LOOPHOLE[from], nwords: nwords, to: to]; RETURN }; WHILE nwords > 0 DO amount: (0..WVMPrivate.pageSize]; [n, w, h, d] _ PageFromAddr[world, from]; amount _ MIN[nwords,WVMPrivate.pageSize-w]; PrincOpsUtils.LongCOPY[from: @d[w], to: to, nwords: amount]; nwords _ nwords - amount; from _ from + amount; to _ to + amount; WVMPrivate.ReleasePage[h]; ENDLOOP; END; CopyWrite: PUBLIC PROC[world: World, from: LONG POINTER, nwords: INT, to: Address] = BEGIN n: WVMPrivate.PageNumber; w: [0..WVMPrivate.pageSize); h: WVMPrivate.PageHandle; d: REF WVMPrivate.PageData; IF world = local THEN { PrincOpsUtils.LongCOPY[from: from, nwords: nwords, to: LOOPHOLE[to]]; RETURN }; WHILE nwords > 0 DO amount: [0..WVMPrivate.pageSize); [n, w, h, d] _ PageFromAddr[world, to]; amount _ MIN[nwords,WVMPrivate.pageSize-w]; PrincOpsUtils.LongCOPY[from: from, to: @d[w], nwords: amount]; nwords _ nwords - amount; from _ from + amount; to _ to + amount; WVMPrivate.WriteAndReleasePage[h]; ENDLOOP; END; PageFromAddr: PROC[world: WorldVM.World, addr: WorldVM.Address] RETURNS[n: WVMPrivate.PageNumber, w: [0..WVMPrivate.pageSize), h: WVMPrivate.PageHandle, d: REF WVMPrivate.PageData] = BEGIN n _ addr / WVMPrivate.pageSize; w _ addr - n * LONG[WVMPrivate.pageSize]; [d, h] _ WVMPrivate.GetPage[world, n]; END; SetBreak: PUBLIC PROC[world: World, addr: Address, offset: PrincOps.BytePC] RETURNS[ oldByte: PrincOps.op ] = BEGIN oldByte _ Patch[world, addr+offset/2, offset MOD 2, PrincOps.zBRK]; IF oldByte = PrincOps.zBRK THEN ERROR IllegalPatch; END; ClearBreak: PUBLIC PROC[world: World, addr: Address, offset: PrincOps.BytePC, oldByte: PrincOps.op] = BEGIN brk: PrincOps.op = Patch[world, addr+offset/2, offset MOD 2, oldByte]; IF brk # PrincOps.zBRK THEN ERROR IllegalPatch; END; IllegalPatch: PUBLIC ERROR = CODE; Patch: PUBLIC ENTRY PROC[world: World, addr: Address, offset: [0..1], byte: PrincOps.op] RETURNS[oldByte: PrincOps.op] = BEGIN ENABLE UNWIND => NULL; value: PrincOps.InstWord _ LOOPHOLE[Read[world, addr]]; -- new memory word contents -- oldByte _ IF offset=0 THEN value.evenbyte ELSE value.oddbyte; IF offset=0 THEN value.evenbyte _ byte ELSE value.oddbyte _ byte; IF world = local THEN BEGIN ptr: LONG POINTER = LOOPHOLE[addr]; page: VM.PageNumber = VM.PageNumberForAddress[ptr]; readOnly: BOOL = VM.State[page].readOnly; IF readOnly THEN VM.MakeReadWrite[[page: page, count: 1]]; ptr^ _ value; IF readOnly THEN VM.MakeReadOnly[[page: page, count: 1]]; END ELSE BEGIN n: WVMPrivate.PageNumber; w: [0..WVMPrivate.pageSize); h: WVMPrivate.PageHandle; d: REF WVMPrivate.PageData; [n, w, h, d] _ PageFromAddr[world, addr]; d[w] _ LOOPHOLE[value]; WVMPrivate.WriteAndReleasePage[h]; END; END; END. ”Cedar Remote Debugging: word-level implementation WVMImpl.mesa Andrew Birrell August 1, 1983 12:57 pm Paul Rovner, August 10, 1983 12:05 pm Ê–˜Jšœ1™1Jšœ ™ Jšœ'™'Jšœ%™%J˜šÏk ˜ Jšœœ ˜ Jšœ œ˜-JšœœI˜QJšœœ˜,Jšœ œZ˜j—J˜šœ Ïc7˜GJšœœ˜.Jšœ˜—J˜Jš˜J˜Jšœ ˜ J˜J˜,J˜š Ïnœœœœœ˜GJš˜J˜J˜J˜Jšœœ˜Jšœ˜Jšœœœœœœœ˜7J˜)J˜ J˜Jšœ˜J˜—šŸœœœ%œ˜BJš˜J˜J˜J˜Jšœœ˜Jšœ˜Jšœœœœœœ œ˜CJ˜)J˜ J˜"Jšœ˜J˜—š Ÿœœœœœœ˜PJš˜J˜J˜J˜Jšœœ˜Jšœ˜Jšœœœœœœœœ˜J˜AJ˜"—Jšœ˜Jšœ˜J˜—šŸ œœ-˜?šœ7˜>Jšœœ˜7—Jš˜J˜Jšœœ˜)J˜&Jšœ˜J˜—šŸœœœ6˜KJšœ˜!Jš˜Jšœ-œ˜CJšœœœ˜3Jšœ˜J˜—šŸ œœœ˜4J˜J˜Jš˜Jšœ6œ ˜FJšœœœ˜/Jšœ˜J˜—Jšœœœœ˜"J˜šŸœœœœ˜5J˜"Jšœ˜Jš˜Jšœœœ˜Jšœœž˜VJšœ œ œœ˜=Jšœ œœ˜AJšœ˜šœ˜ Jšœœœœ˜#Jšœœœ˜3Jšœ œœ˜)Jšœ œœ'˜:Jšœ ˜ Jšœ œœ&˜9Jš˜—šœ˜ J˜J˜J˜Jšœœ˜Jšœ)˜)Jšœœ˜Jšœ"˜"Jšœ˜—Jšœ˜J˜—Jšœ˜J˜J˜—…—žÈ