kern
diff src/vm.c @ 22:7ece008f09c5
writing the vm
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sun, 03 Apr 2011 18:42:19 +0300 |
parents | 8be069e6bb05 |
children | 5454cee245a3 |
line diff
1.1 --- a/src/vm.c Sun Apr 03 08:23:07 2011 +0300 1.2 +++ b/src/vm.c Sun Apr 03 18:42:19 2011 +0300 1.3 @@ -8,16 +8,6 @@ 1.4 #include "panic.h" 1.5 1.6 1.7 -/* defined in vm-asm.S */ 1.8 -void enable_paging(void); 1.9 -void set_pgdir_addr(uint32_t addr); 1.10 -uint32_t get_fault_addr(void); 1.11 - 1.12 -static void pgfault(int inum, uint32_t err); 1.13 - 1.14 -/* page directory */ 1.15 -static uint32_t *pgdir; 1.16 - 1.17 #define KMEM_START 0xc0000000 1.18 #define IDMAP_START 0xa0000 1.19 1.20 @@ -27,6 +17,30 @@ 1.21 1.22 #define PAGEFAULT 14 1.23 1.24 + 1.25 +struct page_range { 1.26 + int start, end; 1.27 + struct page_range *next; 1.28 +}; 1.29 + 1.30 +/* defined in vm-asm.S */ 1.31 +void enable_paging(void); 1.32 +void set_pgdir_addr(uint32_t addr); 1.33 +uint32_t get_fault_addr(void); 1.34 + 1.35 +static void pgfault(int inum, uint32_t err); 1.36 +static struct page_range *alloc_node(void); 1.37 +static void free_node(struct page_range *node); 1.38 + 1.39 +/* page directory */ 1.40 +static uint32_t *pgdir; 1.41 + 1.42 +/* 2 lists of free ranges, for kernel memory and user memory */ 1.43 +static struct page_range *pglist[2]; 1.44 +/* list of free page_range structures to be used in the lists */ 1.45 +static struct page_range *node_pool; 1.46 + 1.47 + 1.48 void init_vm(struct mboot_info *mb) 1.49 { 1.50 uint32_t idmap_end; 1.51 @@ -86,12 +100,15 @@ 1.52 printf("unmap_page(%d): page already not mapped\n", vpage); 1.53 } 1.54 1.55 +/* if ppg_start is -1, we allocate physical pages to map with alloc_phys_page() */ 1.56 void map_page_range(int vpg_start, int pgcount, int ppg_start, unsigned int attr) 1.57 { 1.58 int i; 1.59 1.60 for(i=0; i<pgcount; i++) { 1.61 - map_page(vpg_start + i, ppg_start + i, attr); 1.62 + uint32_t paddr = ppg_start == -1 ? alloc_phys_page() : ppg_start + i; 1.63 + 1.64 + map_page(vpg_start + i, paddr, attr); 1.65 } 1.66 } 1.67 1.68 @@ -131,6 +148,52 @@ 1.69 return pgaddr | ADDR_TO_PGOFFS(vaddr); 1.70 } 1.71 1.72 +/* allocate a contiguous block of virtual memory pages along with 1.73 + * backing physical memory for them, and update the page table. 1.74 + */ 1.75 +int pgalloc(int num, int area) 1.76 +{ 1.77 + int ret = -1; 1.78 + struct page_range *node, *prev, dummy; 1.79 + 1.80 + dummy.next = pglist[area]; 1.81 + node = pglist[area]; 1.82 + prev = &dummy; 1.83 + 1.84 + while(node) { 1.85 + if(node->end - node->start >= num) { 1.86 + ret = node->start; 1.87 + node->start += num; 1.88 + 1.89 + if(node->start == node->end) { 1.90 + prev->next = node->next; 1.91 + node->next = 0; 1.92 + 1.93 + if(node == pglist[area]) { 1.94 + pglist[area] = 0; 1.95 + } 1.96 + free_node(node); 1.97 + } 1.98 + break; 1.99 + } 1.100 + 1.101 + prev = node; 1.102 + node = node->next; 1.103 + } 1.104 + 1.105 + if(ret >= 0) { 1.106 + /* allocate physical storage and map them */ 1.107 + map_page_range(ret, num, -1, 0); 1.108 + } 1.109 + 1.110 + return ret; 1.111 +} 1.112 + 1.113 +void pgfree(int start, int num) 1.114 +{ 1.115 + /* TODO */ 1.116 +} 1.117 + 1.118 static void pgfault(int inum, uint32_t err) 1.119 { 1.120 printf("~~~~ PAGE FAULT ~~~~\n"); 1.121 @@ -150,3 +213,33 @@ 1.122 1.123 panic("unhandled page fault\n"); 1.124 } 1.125 + 1.126 +/* --- page range list node management --- */ 1.127 +static struct page_range *alloc_node(void) 1.128 +{ 1.129 + struct page_range *node; 1.130 + uint32_t paddr; 1.131 + 1.132 + if(node_pool) { 1.133 + node = node_pool; 1.134 + node_pool = node_pool->next; 1.135 + return node; 1.136 + } 1.137 + 1.138 + /* no node structures in the pool, we need to allocate and map 1.139 + * a page, split it up into node structures, add them in the pool 1.140 + * and allocate one of them. 1.141 + */ 1.142 + if(!(paddr = alloc_phys_page())) { 1.143 + panic("ran out of physical memory while allocating VM range structures\n"); 1.144 + } 1.145 + 1.146 + /* TODO cont. */ 1.147 + return 0; 1.148 +} 1.149 + 1.150 +static void free_node(struct page_range *node) 1.151 +{ 1.152 + node->next = node_pool; 1.153 + node_pool = node; 1.154 +}