// vmm.c // Author: Josh Holtrop // Date: 09/30/03 PageDirectory *vmm_PDBR = 0; dword vmm_first_virtual_address = 0; void vmm_init() { if (!(vmm_PDBR = mm_palloc(1, PID_KERNEL))) { printf("ERROR! COULD NOT ALLOCATE PAGE FOR INITIAL PAGE DIRECTORY!!\n"); halt(); } vmm_init_pagetable((dword)vmm_PDBR); if (mm_totalmem % 4096) vmm_first_virtual_address = mm_totalmem + (4096 - (mm_totalmem % 4096)); else vmm_first_virtual_address = mm_totalmem; if (vmm_mapn(0, 0, 0x03, mm_totalmem/4096+1)) { printf("Could not page in all physical RAM!\n"); halt(); } //we also need to map in the video framebuffer memory: if (video_mode.PhysBasePtr > 0 && video_mode.BitsPerPixel > 0) { if (vmm_mapn(video_mode.PhysBasePtr, video_mode.PhysBasePtr, 0x03, (video_mode.BitsPerPixel/8 * video_mode.XResolution * video_mode.YResolution)/4096+1)) { printf("Could not page in video memory at 0x%x!\n", video_mode.PhysBasePtr); halt(); } } } void vmm_enable_paging() { write_cr3((dword)vmm_PDBR); write_cr0(0x80000000|read_cr0()); } int vmm_map1(dword virtual, dword physical, dword flags) { if (virtual & 0x00000FFF) return 1; // ERROR 1: address not page-aligned if (physical & 0x00000FFF) return 1; // ERROR 1: address not page-aligned int pde = (virtual & 0xFFC00000) >> 22; int pte = (virtual & 0x003FF000) >> 12; if (!(vmm_PDBR->pageTables[pde] & 0x01)) { vmm_PDBR->pageTables[pde] = (dword)mm_palloc(1, PID_KERNEL) | 0x7; //user, r/w, present vmm_init_pagetable(vmm_PDBR->pageTables[pde] & 0xFFFFF000); if (vmm_PDBR->pageTables[pde] == 0x07) return 2; // ERROR 2: page table could not be created } PageTable *ptp = (PageTable *)(vmm_PDBR->pageTables[pde] & 0xFFFFF000); if (ptp->page[pte] & 0x01) return 3; // ERROR 3: page table entry already exists ptp->page[pte] = physical | flags; return 0; } int vmm_mapn(dword virtual, dword physical, dword flags, dword n) { int mapped; int result = 0; dword va = virtual; dword pa = physical; for (mapped = 0; mapped < n; mapped++) { result = vmm_map1(va, pa, flags); if (result != 0) { if (mapped > 0) vmm_unmapn(virtual, mapped); return result; } va += 4096; pa += 4096; } } int vmm_unmap1(dword virtual) { int pde = (virtual & 0xFFC00000) >> 22; int pte = (virtual & 0x003FF000) >> 12; if (virtual & 0x00000FFF) return 1; // ERROR 1: address not page-aligned PageTable *ptp = (PageTable *)(vmm_PDBR->pageTables[pde] & 0xFFFFF000); } int vmm_unmapn(dword virtual, dword n) { } void vmm_init_pagetable(dword address) { PageTable *ptp = (PageTable *)address; int n; for (n = 0; n < 1024; n++) ptp->page[n] = 0; } void *malloc(dword bytes) { } int free(void *ptr) { }