{ ************************************************ * Asuro * Unit: VMemoryManager * Description: Manages Pages of Virtual Memory ************************************************ * Author: K Morris * Contributors: ************************************************ } unit vmemorymanager; interface uses util, pmemorymanager, console; type PPageDirEntry = ^TPageDirEntry; TPageDirEntry = bitpacked record Present, Writable, UserMode, WriteThrough, NotCacheable, Accessed, Reserved, PageSize, GlobalPage: Boolean; Available: UBit3; Address: UBit20; end; TPageDirectory = Array[0..1023] of TPageDirEntry; PPageDirectory = ^TPageDirectory; var KERNEL_PAGE_DIRECTORY : PPageDirectory; PageDirectory : PPageDirectory; procedure init; function new_page(page_number : uint16) : boolean; function map_page(page_number : uint16; block : uint16) : boolean; function map_page_ex(page_number : uint16; block : uint16; PD : PPageDirectory) : boolean; function new_page_at_address(address : uint32) : boolean; procedure free_page(page_number : uint16); procedure free_page_at_address(address : uint32); function new_page_directory : uint32; function new_kernel_mapped_page_directory : uint32; implementation uses lmemorymanager; function new_page_directory : uint32; begin new_page_directory:= uint32(kalloc(sizeof(TPageDirectory))); end; function new_kernel_mapped_page_directory : uint32; var PD : PPageDirectory; i : uint32; begin PD:= PPageDirectory(new_page_directory); for i:=KERNEL_PAGE_NUMBER to 1023 do begin PD^[i]:= KERNEL_PAGE_DIRECTORY^[i]; end; new_kernel_mapped_page_directory:= uint32(PD); end; function load_current_page_directory : PPageDirectory; var Directory : uint32; begin asm MOV EAX, CR3 MOV Directory, EAX end; Directory:= Directory + KERNEL_VIRTUAL_BASE; load_current_page_directory:= PPageDirectory(Directory); end; procedure init; var i : uint32; begin console.writestringln('VMM: INIT BEGIN.'); PageDirectory:= load_current_page_directory; KERNEL_PAGE_DIRECTORY:= PageDirectory; map_page(KERNEL_PAGE_NUMBER + 1, 1); map_page(KERNEL_PAGE_NUMBER + 2, 2); map_page(KERNEL_PAGE_NUMBER + 3, 3); console.writestringln('VMM: INIT END.'); end; function map_page_ex(page_number : uint16; block : uint16; PD : PPageDirectory) : boolean; var addr : ubit20; page : uint16; begin map_page_ex:= false; PD^[page_number].Present:= true; addr:= block; PD^[page_number].Address:= addr SHL 10; PD^[page_number].PageSize:= true; PD^[page_number].Writable:= true; //console.writestringln('VMM: New Page Added:'); //console.writestring('VMM: - P:'); //console.writehex(page_number); // console.writestring('-->B:'); // console.writehexln(block); // console.writestring('VMM: - P:['); // console.writehex(page_number SHL 22); // console.writestring(' - '); // console.writehex(((page_number+1) SHL 22)); // console.writestring(']-->B:['); // console.writehex(block SHL 22); // console.writestring(' - '); // console.writehex(((block+1) SHL 22)); // console.writestringln(']'); map_page_ex:= true; end; function map_page(page_number : uint16; block : uint16) : boolean; var addr : ubit20; page : uint16; rldpd : uint32; begin map_page:= false; PageDirectory^[page_number].Present:= true; addr:= block; PageDirectory^[page_number].Address:= addr SHL 10; PageDirectory^[page_number].PageSize:= true; PageDirectory^[page_number].Writable:= true; map_page:= map_page_ex(page_number, block, PageDirectory); rldpd:= uint32(PageDirectory) - KERNEL_VIRTUAL_BASE; asm mov eax, rldpd mov CR3, eax end; end; function new_page(page_number : uint16) : boolean; var block : uint16; begin new_page:= false; if PageDirectory^[page_number].Present then exit; if PageDirectory^[page_number].Reserved then exit; block:= pmemorymanager.new_block(uint32(PageDirectory)); if block < 2 then begin GPF; exit; end else begin new_page:= map_page(page_number, block); end; end; function new_page_at_address(address : uint32) : boolean; var page_number : uint16; begin page_number:= address SHR 22; new_page_at_address:= new_page(page_number); end; procedure free_page(page_number : uint16); var block : uint16; begin if PageDirectory^[page_number].Present then begin block:= PageDirectory^[page_number].Address; asm invlpg [page_number] end; pmemorymanager.free_block(block, uint32(PageDirectory)); end else begin GPF; end; end; procedure free_page_at_address(address : uint32); var page_number : uint16; begin page_number:= address SHR 22; free_page(page_number); end; end.