?? memcode.inc
字號:
;=============================================================================
; MMURTL Operating System Source Code
; Copyright 1991,1992,1993, Richard A. Burgess
; ALL RIGHTS RESERVED
; Version x0.8
;
; MEMORY Management Code
; OS Internal support calls (near) are at top of this file.
; OS PUBLIC calls are at the bottom
;
; The following internals deal with PHYSICAL memory and the Page
; Allocation Map (PAM).
;
; FindHiPage - Finds first available physical page from top of memory
; down and sets it allocated then returns the
; Physical address of the page.
; FindLoPage - Finds first available physical page from BOTTOM of memory
; and sets it allocated then returns the
; Physical address of the page. This is for DMA.
; MarkPage - Given a physical page address, this SETS the PAM bit
; to allocate it.
; UnMarkPage - Given the physical page address, this RESETS the PAM bit
; to deallocate it.
;
; The following internals deal with LINEAR memory and PTs.
;
; LinToPhy - Converts a linear to a physical address (OS or APP).
; Also provides lin address to PTE in question.
; IN: EBX is Linear address
; EAX is Job Number (for PD)
; OUT: EAX is Physical address
; ESI is Linear address of PTE for EBX Lin Add
; FindRun - Finds a run of FREE contiguous PTEs
; IN: EAX = 0 for OS run, or 256 for User run
; EBX = nPages
; OUT: EAX = Linear Address of run (0 if can't find)
; EBX = nPages (same as in)
; AddRun - Creates one or more PTEs (first owner)
; IN: EAX = Linear address of page(s) to add.
; EBX = count of pages
; OUT: EAX = 0 if OK, else Error
; EBX = count of pages (same as in)
;
; AliasRun - Creates one or more ALIAS PTEs
;
; AddUserPT - Allocates physical memory and adds new PT to user PD
;
; AddOSPT - Allocates physical memory and adds new PT to ALL PDs
;
;========================================================================
FindHiPage:
; This finds the first unused physical page in memory from the TOP down
; and returns the physical address of it to the caller.
; It also MARKS the page as used (assuming that we will allocate it).
; Of course this means if we call FindHiPage and don't use it we
; must call UnMarkPage to release it.
; This reduces nPagesFree by one.
;
;IN : Nothing
;OUT : EBX is the physical address of the new page, or 0 if error
;USED: EBX, Flags
PUSH EAX
PUSH ECX
PUSH EDX
MOV ECX, OFFSET rgPAM ;Page Allocation Map
MOV EAX, sPAM ;Where we are in PAM
DEC EAX ;EAX+ECX will be offset into PAM
FHP1:
CMP BYTE PTR [ECX+EAX],0FFh ;All 8 pages used?
JNE FHP2 ;No
CMP EAX, 0 ;Are we at Bottom of PAM?
JE FHPn ;no memory left...
DEC EAX ;Another Byte lower
JMP SHORT FHP1 ;Back for next byte
FHP2:
MOV EBX, 7 ;
XOR EDX, EDX
MOV DL, BYTE PTR [ECX+EAX] ;Get the byte with a whole in it...
FHP3:
BT EDX, EBX ;Test bits
JNC FHPf ;FOUND ONE! (goto found)
CMP EBX, 0 ;At the bottom of the Byte?
JE FHPn ;Error (BAD CPU???)
DEC EBX ;Next bit
JMP FHP3
FHPf:
BTS EDX, EBX ;Set the bit indexed by EBX
MOV BYTE PTR [ECX+EAX], DL ;Set page in use
SHL EAX, 3 ;Multiply time 8 (page number base in byte)
ADD EBX, EAX ;Add page number in byte
SHL EBX, 12 ;Now EBX = Physical Page Addr (EBX*4096)
DEC _nPagesFree ;One less available
POP EDX
POP ECX
POP EAX
RETN
FHPn:
XOR EBX, EBX ;Set to zero for error
POP EDX
POP ECX
POP EAX
RETN
;========================================================================
FindLoPage:
; This finds the first unused physical page in memory from the BOTTOM up
; and returns the physical address of it to the caller.
; It also MARKS the page as used (assuming that we will allocate it).
; Of course this means if we call FindLoPage and don't use it we
; must call UnMarkPage to release it.
; This reduces nPagesFree by one.
;
;IN : Nothing
;OUT : EBX is the physical address of the new page, or 0 if error
;USED: EBX, Flags
PUSH EAX
PUSH ECX
PUSH EDX
MOV ECX, OFFSET rgPAM ;Page Allocation Map
XOR EAX, EAX ;Start at first byte in PAM
FLP1:
CMP BYTE PTR [ECX+EAX],0FFh ;All 8 pages used?
JNE FLP2 ;No
INC EAX ;Another Byte lower
CMP EAX, sPAM ;Are we past at TOP of PAM?
JAE FLPn ;no memory left...
JMP SHORT FLP1 ;Back for next byte
FLP2:
XOR EBX, EBX ;
XOR EDX, EDX
MOV DL, BYTE PTR [ECX+EAX] ;Get the byte with a whole in it...
FLP3:
BT EDX, EBX ;Test bits
JNC FLPf ;FOUND ONE! (goto found)
INC EBX ;Next bit
CMP EBX, 8 ;End of the Byte?
JAE FLPn ;Error (BAD CPU???)
JMP FLP3
FLPf:
BTS EDX, EBX ;Set the bit indexed by EBX
MOV BYTE PTR [ECX+EAX], DL ;Set page in use
SHL EAX, 3 ;Multiply time 8 (page number base in byte)
ADD EBX, EAX ;Add page number in byte
SHL EBX, 12 ;Now EBX = Physical Page Addr (EBX*4096)
DEC _nPagesFree ;One less available
POP EDX
POP ECX
POP EAX
RETN
FLPn:
XOR EBX, EBX ;Set to zero for error
POP EDX
POP ECX
POP EAX
RETN
;========================================================================
MarkPage:
; Given a physical memory address, this finds the bit in the PAM associated
; with it and SETS it to show the physical page in use. This is used
; with the routines that initialize all memory mgmt function.
; This reduces nPagesFree by one.
;
;IN : EBX is the physical address of the page to mark
;OUT : Nothing
;USED: EBX, Flags
PUSH EAX
PUSH ECX
PUSH EDX
MOV EAX, OFFSET rgPAM ;Page Allocation Map
AND EBX, 0FFFFF000h ;Round down to page modulo 4096
MOV ECX, EBX
SHR ECX, 15 ;ECX is now byte offset into PAM
SHR EBX, 12 ;Get Bit offset into PAM
AND EBX, 07h ;EBX is now bit offset into byte of PAM
MOV DL, [EAX+ECX] ;Get the byte into DL
BTS EDX, EBX ;BitSet nstruction with Bit Offset
MOV [EAX+ECX], DL ;Save the new PAM byte
DEC _nPagesFree ;One less available
POP EDX
POP ECX
POP EAX
RETN
;========================================================================
UnMarkPage:
; Given a physical memory address, this finds the bit in the PAM associated
; with it and RESETS it to show the physical page available again.
; This increases nPagesFree by one.
;
;IN : EBX is the physical address of the page to UNmark
;OUT : Nothing
;USED: EBX, Flags
PUSH EAX
PUSH ECX
PUSH EDX
MOV EAX, OFFSET rgPAM ;Page Allocation Map
AND EBX, 0FFFFF000h ;Round down to page modulo
MOV ECX, EBX
SHR ECX, 15 ;ECX is now byte offset into PAM
SHR EBX, 12 ;
AND EBX, 07h ;EBX is now bit offset into byte of PAM
ADD EAX, ECX
MOV DL, [EAX]
BTR EDX, EBX ;BitReset instruction
MOV [EAX], DL
INC _nPagesFree ;One more available
POP EDX
POP ECX
POP EAX
RETN
;============================================================
;
; LinToPhy
; Looks Up the Physical address of a 32 bit linear address passed in.
; The JCB is used to identify who's page tables we are translating.
; The linear address is used to look up the Page Table entry which is
; used to get the physical address. This call is used for things like
; aliasing for messages, DMA operations, etc.
; This also leave the Linear Address of the PTE itself in ESI
; for callers that need it.
;
; INPUT: EAX -- Job Number that owns memory we are aliasing
; EBX -- Linear address
;
; OUTPUT: EAX -- Physical Address
; ESI -- Linear Address of PTE for this linear address
;
; USED: EAX, EBX, ESI, EFlags
;
LinToPhy:
PUSH EBX ;Save Linear
CALL GetpJCB ;Leaves pJCB in EAX
MOV EAX, [EAX.JcbPD] ;EAX now has ptr to PD!
ADD EAX, 2048 ;Move to shadow addresses in PD
SHR EBX, 22 ;Shift out lower 22 bits leaving 10 bit offset
SHL EBX, 2 ;*4 to make it a byte offset into PD shadow
ADD EBX, EAX ;EBX/EAX now points to shadow
MOV EAX, [EBX] ;EAX now has Linear of Page Table
POP EBX ;Get original linear back in EBX
PUSH EBX ;Save it again
AND EBX, 003FFFFFh ;Get rid of upper 10 bits
SHR EBX, 12 ;get rid of lower 12 to make it an index
SHL EBX, 2 ;*4 makes it byte offset in PT
ADD EBX, EAX ;EBX now points to Page Table entry!
MOV ESI, EBX ;Save this address for caller
MOV EAX, [EBX] ;Physical base of page is in EAX
AND EAX, 0FFFFF000h ;mask off lower 12
POP EBX ;Get original linear
AND EBX, 00000FFFh ;Cut off upper 22 bits of linear
OR EAX, EBX ;EAX now has REAL PHYSICAL ADDRESS!
RETN
;=============================================================================
; FindRun
; This finds a linear run of FREE LINEAR memory in one of the USER or OS PTs.
; This is either at address base 0 (for OS) or 1Gb (for user).
; EAX = 0 if we are looking for OS memory, else
; EAX = 256 if we are looking for USER memory.
; The linear address of the run is returned in EAX unless no
; run that large exists, in which case we return 0.
; The linear run may span page tables (if they already exist).
; This is an interesting routine because it uses two nested loops
; to walk thru the page directory and page tables while using the
; SIB (Scale Index Base) addressing of the 386 for indexing.
;
; IN : EAX PD Shadow Base Offset for memory (0 for OS, 256 for user)
; EBX Number of Pages for run
;
; OUT: EAX Linear address or 0 if no run is large enough
; EBX still has count of pages
; USED: EAX, EBX, EFlags (all other registers saved & restored)
;
;
FindRun:
PUSH EBX ;Holds count of pages (saved for caller)
PUSH ECX ;Keeps count of how many free found so far
PUSH EDX ;Index into PD for PT we are working on
PUSH ESI ;Address of PD saved here
PUSH EDI ;
MOV ECX, EBX ;Copy number of pages to ECX. Save in EBX
MOV EDX, EAX ;Index into shadow addresses from EAX
CALL GetpCrntJCB ;Leaves pCrntJCB in EAX
MOV ESI, [EAX.JcbPD] ;ESI now has ptr to PD
ADD ESI, 2048 ;Move to shadow addresses
FR0:
MOV EDI, [ESI+EDX*4] ;Linear address of next page table into EDI
OR EDI, EDI ;Is the address NON-ZERO (valid)?
JNZ FR1 ;Yes, go for it
XOR EAX, EAX ;Return 0 cause we didn't find it!
JMP SHORT FREXIT ;
FR1:
XOR EAX, EAX ;EAX indexes into PT (to compare PTEs)
FR2:
CMP EAX, 1024 ;Are we past last PTE of this PT?
JB FR3 ;No, keep testing
INC EDX ;Next PT!
JMP SHORT FR0 ;
FR3:
CMP DWORD PTR [EDI+EAX*4], 0 ;Zero means it's empty (available)
JNE FR4 ;In use
DEC ECX ;One more empty one!
JZ FROK ;We found enough entries goto OK
INC EAX ;Not done yet, Next PTE Please...
JMP SHORT FR2 ;
FR4:
;If we got here we must reset ECX for full count and
;go back and start looking again
INC EAX ;Not empty, next PTE please
MOV ECX, EBX ;We kept original count in EBX
JMP FR2
FROK:
;If we got here it means that ECX has made it to zero and
;we have a linear run large enough to satisy the request.
;The starting linear address is equal to number of the last
;PTE we found minus ((npages -1) * 4096)
;EDX was index into PD, while EAX was index into PT.
;EBX still has count of pages.
SHL EDX, 22 ;EDX is 10 MSBs of Linear Address
SHL EAX, 12 ;EAX is next 10 bits of LA
OR EAX, EDX ;This is the linear address we ended at
DEC EBX ;One less page (0 offset)
SHL EBX, 12 ;Times size of page (* 4096)
SUB EAX, EBX ;From current linear address in tables
FREXIT:
POP EDI ;
POP ESI ;
POP EDX ;
POP ECX ;
POP EBX ;
RETN
;=============================================================================
; AddRun
; This adds one or more PTEs to a page table (or tables if the run
; spans two or more tables).
; The address determines the protection level of the PTE's we add.
; If it is less than 1GB it means OS memory which we will set to SYSTEM.
; Above 1Gb is user which we will set to user level protection.
; The linear address of the run should be in EAX, and the count of
; pages should be in EBX (this is the way FindRun left them).
;
; IN : EAX Linear address of first page
; EBX Number of Pages to add
; OUT: Nothing
; USED: EAX, EFlags
;
AddRun:
PUSH EBX ;(save for caller)
PUSH ECX ;
PUSH EDX ;
PUSH ESI ;
PUSH EDI ;
MOV ECX, EBX ;Copy number of pages to ECX (EBX free to use).
MOV EDX, EAX ;LinAdd to EDX
SHR EDX, 22 ;Get index into PD for first PT
SHL EDX, 2 ;Make it index to DWORDS
PUSH EAX ;Save EAX thru GetpCrntJCB call
CALL GetpCrntJCB ;Leaves pCrntJCB in EAX
MOV ESI, [EAX.JcbPD] ;ESI now has ptr to PD!
POP EAX ;Restore linear address
ADD ESI, 2048 ;Offset to shadow address of PD
ADD ESI, EDX ;ESI now points to initial PT (EDX now free)
MOV EDX, EAX ;LinAdd into EDX again
AND EDX, 003FF000h ;get rid of upper 10 bits & lower 12
SHR EDX, 10 ;Index into PD for PT (10 vice 12 -> DWORDS)
AR0:
MOV EDI, [ESI] ;Linear address of next page table into EDI
;At this point, EDI is pointing the next PT.
;SO EDI+EDX will point to the next PTE to do.
;Now we must call FindPage to get a physical address into EBX,
;then check the original linear address to see if SYSTEM or USER
;and OR in the appropriate control bits, THEN store it in PT.
AR1:
CALL FindHiPage ;EBX has Phys Pg (only EBX affected)
OR EBX, MEMSYS ;Set PTE to present, User ReadOnly
CMP EAX, 40000000h ;See if it's a user page
JB AR2
OR EBX, MEMUSERD ;Sets User/Writable bits of PTE
AR2:
MOV DWORD PTR [EDI+EDX], EBX ;EDX is index to exact entry
DEC ECX ;Are we done??
JZ ARDone
ADD EDX, 4 ;Next PTE please...
CMP EDX, 4096 ;Are we past last PTE of this PT?
JB AR1 ;No, go do next PTE
ADD ESI, 4 ;Yes, next PDE (to get next PT)
XOR EDX,EDX ;Start at the entry 0 of next PT
JMP SHORT AR0 ;
ARDone:
POP EDI ;
POP ESI ;
POP EDX ;
POP ECX ;
POP EBX ;
RETN
;=============================================================================
; AddAliasRun
; This adds one or more PTEs to a page table (or tables if the run
; spans two or more tables) adding PTEs from another job's PTs marking
; them as ALIAS entries.
; Aliased runs are ALWAYS at USER protection levels even if in the
; OS address span!
;
; The NEW linear address of the run should be in EAX, and the count of
; pages should be in EBX (this is the way FindRun left them).
; ESI has the linear address we are aliasing and EDX has the Job#
;
; IN : EAX Linear address of first page of new alias entries
; (from find run)
; EBX Number of Pages to alias
; ESI Linear Address of pages to Alias (from other job)
; EDX Job Number of Job we are aliasing
;
; OUT: Nothing
; USED: EAX, EFlags
;
AliasLin EQU DWORD PTR [EBP-4]
AliasJob EQU DWORD PTR [EBP-8]
AddAliasRun:
PUSH EBP ;
MOV EBP,ESP ;
SUB ESP, 8
MOV AliasLin, ESI
MOV AliasJob, EDX
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -