kern

view src/vm.c @ 21:3ba93d8f586c

now ignoring parts of the memory map beyond 4gb instead of silently wrapping around and marking all holes as usable :)
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 03 Apr 2011 08:23:07 +0300
parents 096807345aa2
children 7ece008f09c5
line source
1 #include <stdio.h>
2 #include <string.h>
3 #include <inttypes.h>
4 #include "vm.h"
5 #include <stdio.h>
6 #include "intr.h"
7 #include "mem.h"
8 #include "panic.h"
11 /* defined in vm-asm.S */
12 void enable_paging(void);
13 void set_pgdir_addr(uint32_t addr);
14 uint32_t get_fault_addr(void);
16 static void pgfault(int inum, uint32_t err);
18 /* page directory */
19 static uint32_t *pgdir;
21 #define KMEM_START 0xc0000000
22 #define IDMAP_START 0xa0000
24 #define ATTR_PGDIR_MASK 0x3f
25 #define ATTR_PGTBL_MASK 0x1ff
26 #define ADDR_PGENT_MASK 0xfffff000
28 #define PAGEFAULT 14
30 void init_vm(struct mboot_info *mb)
31 {
32 uint32_t idmap_end;
34 init_mem(mb);
36 pgdir = (uint32_t*)alloc_phys_page();
37 memset(pgdir, 0, sizeof pgdir);
39 /* map the video memory and kernel code 1-1 */
40 get_kernel_mem_range(0, &idmap_end);
41 map_mem_range(IDMAP_START, idmap_end - IDMAP_START, IDMAP_START, 0);
43 interrupt(PAGEFAULT, pgfault);
45 set_pgdir_addr((int32_t)pgdir);
46 enable_paging();
47 }
49 void map_page(int vpage, int ppage, unsigned int attr)
50 {
51 uint32_t *pgtbl;
52 int diridx = PAGE_TO_PGTBL(vpage);
53 int pgidx = PAGE_TO_PGTBL_PG(vpage);
55 if(!(pgdir[diridx] & PG_PRESENT)) {
56 uint32_t addr = alloc_phys_page();
57 pgtbl = (uint32_t*)addr;
58 memset(pgtbl, 0, PGSIZE);
60 pgdir[diridx] = addr | (attr & ATTR_PGDIR_MASK) | PG_PRESENT;
61 } else {
62 pgtbl = (uint32_t*)(pgdir[diridx] & ADDR_PGENT_MASK);
63 }
65 pgtbl[pgidx] = PAGE_TO_ADDR(ppage) | (attr & ATTR_PGTBL_MASK) | PG_PRESENT;
66 }
68 void unmap_page(int vpage)
69 {
70 uint32_t *pgtbl;
71 int diridx = PAGE_TO_PGTBL(vpage);
72 int pgidx = PAGE_TO_PGTBL_PG(vpage);
74 if(!(pgdir[diridx] & PG_PRESENT)) {
75 goto err;
76 }
77 pgtbl = (uint32_t*)(pgdir[diridx] & ADDR_PGENT_MASK);
79 if(!(pgtbl[pgidx] & PG_PRESENT)) {
80 goto err;
81 }
82 pgtbl[pgidx] = 0;
84 return;
85 err:
86 printf("unmap_page(%d): page already not mapped\n", vpage);
87 }
89 void map_page_range(int vpg_start, int pgcount, int ppg_start, unsigned int attr)
90 {
91 int i;
93 for(i=0; i<pgcount; i++) {
94 map_page(vpg_start + i, ppg_start + i, attr);
95 }
96 }
98 void map_mem_range(uint32_t vaddr, size_t sz, uint32_t paddr, unsigned int attr)
99 {
100 int vpg_start, ppg_start, num_pages;
102 if(!sz) return;
104 if(ADDR_TO_PGOFFS(paddr)) {
105 panic("map_mem_range called with unaligned physical address: %x\n", paddr);
106 }
108 vpg_start = ADDR_TO_PAGE(vaddr);
109 ppg_start = ADDR_TO_PAGE(paddr);
110 num_pages = ADDR_TO_PAGE(sz) + 1;
112 map_page_range(vpg_start, num_pages, ppg_start, attr);
113 }
115 uint32_t virt_to_phys(uint32_t vaddr)
116 {
117 uint32_t pgaddr, *pgtbl;
118 int diridx = ADDR_TO_PGTBL(vaddr);
119 int pgidx = ADDR_TO_PGTBL_PG(vaddr);
121 if(!(pgdir[diridx] & PG_PRESENT)) {
122 panic("virt_to_phys(%x): page table %d not present\n", vaddr, diridx);
123 }
124 pgtbl = (uint32_t*)(pgdir[diridx] & PGENT_ADDR_MASK);
126 if(!(pgtbl[pgidx] & PG_PRESENT)) {
127 panic("virt_to_phys(%x): page %d not present\n", vaddr, ADDR_TO_PAGE(vaddr));
128 }
129 pgaddr = pgtbl[pgidx] & PGENT_ADDR_MASK;
131 return pgaddr | ADDR_TO_PGOFFS(vaddr);
132 }
134 static void pgfault(int inum, uint32_t err)
135 {
136 printf("~~~~ PAGE FAULT ~~~~\n");
138 printf("fault address: %x\n", get_fault_addr());
140 if(err & PG_PRESENT) {
141 if(err & 8) {
142 printf("reserved bit set in some paging structure\n");
143 } else {
144 printf("%s protection violation ", (err & PG_WRITABLE) ? "write" : "read");
145 printf("in %s mode\n", err & PG_USER ? "user" : "kernel");
146 }
147 } else {
148 printf("page not present\n");
149 }
151 panic("unhandled page fault\n");
152 }