/* set up page tables for kernel */ void init_page(void) { CR0 cr0; CR3 cr3; PDE *pdir = (PDE *)va_to_pa(kpdir); PTE *ptable = (PTE *)va_to_pa(kptable); uint32_t pdir_idx; /* make all PDEs invalid */ memset(pdir, 0, NR_PDE * sizeof(PDE)); /* fill PDEs */ for (pdir_idx = 0; pdir_idx < PHY_MEM / PT_SIZE; pdir_idx ++) { pdir[pdir_idx].val = make_pde(ptable); pdir[pdir_idx + KOFFSET / PT_SIZE].val = make_pde(ptable); ptable += NR_PTE; } /* fill PTEs */ /* We use inline assembly here to fill PTEs for efficiency. * If you do not understand it, refer to the C code below. */ asm volatile ("std;\ 1: stosl;\ subl %0, %%eax;\ jge 1b;\ cld" : : "i"(PAGE_SIZE), "a"((PHY_MEM - PAGE_SIZE) | 0x7), "D"(ptable - 1)); /* ===== referenced code for the inline assembly above ===== uint32_t pframe_addr = PHY_MEM - PAGE_SIZE; ptable --; // fill PTEs reversely for (; pframe_addr >= 0; pframe_addr -= PAGE_SIZE) { ptable->val = make_pte(pframe_addr); ptable --; } */ /* make CR3 to be the entry of page directory */ cr3.val = 0; cr3.page_directory_base = ((uint32_t)pdir) >> 12; write_cr3(cr3.val); /* set PG bit in CR0 to enable paging */ cr0.val = read_cr0(); cr0.paging = 1; write_cr0(cr0.val); }
void map_page(uint32_t *page_dir, uint32_t virt_page_num, uint32_t phy_page_num, bool global, bool user, bool read_write) { uint16_t pd_idx = PD_IDX(virt_page_num), pt_idx = PT_IDX(virt_page_num); uint32_t *page_table; if(!(page_dir[pd_idx] & 0x1)) { uint32_t pt_page_num = alloc_phy_page(0, 1023); map_kernel_page(pt_page_num, pt_page_num, true, false, true); memset((void *)(pt_page_num << 12), 0, 4096); page_dir[pd_idx] = make_pde(pt_page_num, user, read_write); } page_table = (uint32_t *)(page_dir[pd_idx] & 0xfffff000); page_table[pt_idx] = make_pte(phy_page_num, global, user, read_write); ++phy_mem_rc[phy_page_num]; __asm__ volatile( ".intel_syntax noprefix;" "mov eax, cr3;" "mov cr3, eax;" ".att_syntax;" :::"eax" ); }
/* Build a page table for the kernel */ void init_page(void) { CR0 cr0; CR3 cr3; PDE *pdir = (PDE *)va_to_pa(kpdir); PTE *ptable = (PTE *)va_to_pa(kptable); uint32_t pdir_idx, ptable_idx, pframe_idx; for (pdir_idx = 0; pdir_idx < NR_PDE; pdir_idx ++) { make_invalid_pde(&pdir[pdir_idx]); } pframe_idx = 0; for (pdir_idx = 0; pdir_idx < PHY_MEM / PD_SIZE; pdir_idx ++) { make_pde(&pdir[pdir_idx], ptable); make_pde(&pdir[pdir_idx + KOFFSET / PD_SIZE], ptable); for (ptable_idx = 0; ptable_idx < NR_PTE; ptable_idx ++) { make_pte(ptable, (void*)(pframe_idx << 12)); pframe_idx ++; ptable ++; } } /* make CR3 to be the entry of page directory */ cr3.val = 0; cr3.page_directory_base = ((uint32_t)pdir) >> 12; write_cr3(&cr3); /* set PG bit in CR0 to enable paging */ cr0.val = read_cr0(); cr0.paging = 1; write_cr0(&cr0); /* Now we can access global variables! * Store CR3 in the global variable for future use. */ kcr3.val = cr3.val; }
void create_video_mapping() { /* TODO: create an identical mapping from virtual memory area * [0xa0000, 0xa0000 + SCR_SIZE) to physical memory area * [0xa0000, 0xa0000 + SCR_SIZE) for user program. You may define * some page tables to create this mapping. */ PDE *pdir = (PDE *)get_updir(); PTE *ptable = (PTE *)va_to_pa(vdtable); // ptable += (SCR_SIZE / PAGE_SIZE + 1) * PAGE_SIZE; pdir->val = make_pde(vdtable); // pdir[0 + KOFFSET / PT_SIZE].val = make_pde(vdtable); // ptable --; uint32_t pframe_addr = VMEM_ADDR; int i=0; for(; i<=0xf; i++) { ptable[i+0xa0].val = make_pte(pframe_addr); pframe_addr += PAGE_SIZE; } // panic("please implement me"); }