nuclear@17: #include nuclear@17: #include nuclear@17: #include nuclear@17: #include "vm.h" nuclear@17: #include nuclear@17: #include "intr.h" nuclear@17: #include "mem.h" nuclear@17: #include "panic.h" nuclear@17: nuclear@17: nuclear@17: /* defined in vm-asm.S */ nuclear@17: void enable_paging(void); nuclear@17: void set_pgdir_addr(uint32_t addr); nuclear@17: uint32_t get_fault_addr(void); nuclear@17: nuclear@17: static void pgfault(int inum, uint32_t err); nuclear@17: nuclear@17: /* page directory */ nuclear@18: static uint32_t *pgdir; nuclear@17: nuclear@17: #define KMEM_START 0xc0000000 nuclear@17: #define IDMAP_START 0xa0000 nuclear@17: nuclear@17: #define ATTR_PGDIR_MASK 0x3f nuclear@17: #define ATTR_PGTBL_MASK 0x1ff nuclear@17: #define ADDR_PGENT_MASK 0xfffff000 nuclear@17: nuclear@17: #define PAGEFAULT 14 nuclear@17: nuclear@17: void init_vm(struct mboot_info *mb) nuclear@17: { nuclear@19: uint32_t idmap_end; nuclear@19: nuclear@17: init_mem(mb); nuclear@17: nuclear@18: pgdir = (uint32_t*)alloc_phys_page(); nuclear@17: memset(pgdir, 0, sizeof pgdir); nuclear@17: nuclear@17: /* map the video memory and kernel code 1-1 */ nuclear@19: get_kernel_mem_range(0, &idmap_end); nuclear@19: map_mem_range(IDMAP_START, idmap_end - IDMAP_START, IDMAP_START, 0); nuclear@17: nuclear@17: interrupt(PAGEFAULT, pgfault); nuclear@17: nuclear@17: set_pgdir_addr((int32_t)pgdir); nuclear@17: enable_paging(); nuclear@17: } nuclear@17: nuclear@17: void map_page(int vpage, int ppage, unsigned int attr) nuclear@17: { nuclear@17: uint32_t *pgtbl; nuclear@17: int diridx = PAGE_TO_PGTBL(vpage); nuclear@17: int pgidx = PAGE_TO_PGTBL_PG(vpage); nuclear@17: nuclear@17: if(!(pgdir[diridx] & PG_PRESENT)) { nuclear@17: uint32_t addr = alloc_phys_page(); nuclear@17: pgtbl = (uint32_t*)addr; nuclear@18: memset(pgtbl, 0, PGSIZE); nuclear@18: nuclear@17: pgdir[diridx] = addr | (attr & ATTR_PGDIR_MASK) | PG_PRESENT; nuclear@17: } else { nuclear@17: pgtbl = (uint32_t*)(pgdir[diridx] & ADDR_PGENT_MASK); nuclear@17: } nuclear@17: nuclear@17: pgtbl[pgidx] = PAGE_TO_ADDR(ppage) | (attr & ATTR_PGTBL_MASK) | PG_PRESENT; nuclear@17: } nuclear@17: nuclear@17: void unmap_page(int vpage) nuclear@17: { nuclear@17: uint32_t *pgtbl; nuclear@17: int diridx = PAGE_TO_PGTBL(vpage); nuclear@17: int pgidx = PAGE_TO_PGTBL_PG(vpage); nuclear@17: nuclear@17: if(!(pgdir[diridx] & PG_PRESENT)) { nuclear@17: goto err; nuclear@17: } nuclear@17: pgtbl = (uint32_t*)(pgdir[diridx] & ADDR_PGENT_MASK); nuclear@17: nuclear@17: if(!(pgtbl[pgidx] & PG_PRESENT)) { nuclear@17: goto err; nuclear@17: } nuclear@17: pgtbl[pgidx] = 0; nuclear@17: nuclear@17: return; nuclear@17: err: nuclear@17: printf("unmap_page(%d): page already not mapped\n", vpage); nuclear@17: } nuclear@17: nuclear@17: void map_page_range(int vpg_start, int pgcount, int ppg_start, unsigned int attr) nuclear@17: { nuclear@17: int i; nuclear@17: nuclear@17: for(i=0; i