kern
changeset 43:5f6c5751ae05
- implemented clone_vmem
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 25 Jul 2011 11:29:02 +0300 |
parents | e6de3c6015cb |
children | 7bc74736c7e8 |
files | src/asmops.h src/main.c src/panic.c src/proc.c src/proc.h src/vm.c src/vm.h |
diffstat | 7 files changed, 113 insertions(+), 51 deletions(-) [+] |
line diff
1.1 --- a/src/asmops.h Sun Jul 24 18:29:24 2011 +0300 1.2 +++ b/src/asmops.h Mon Jul 25 11:29:02 2011 +0300 1.3 @@ -1,6 +1,8 @@ 1.4 #ifndef ASMOPS_H_ 1.5 #define ASMOPS_H_ 1.6 1.7 +#include <inttypes.h> 1.8 + 1.9 /* general purpose registers as they are pushed by pusha */ 1.10 struct registers { 1.11 uint32_t edi, esi, ebp, esp;
2.1 --- a/src/main.c Sun Jul 24 18:29:24 2011 +0300 2.2 +++ b/src/main.c Mon Jul 25 11:29:02 2011 +0300 2.3 @@ -10,35 +10,6 @@ 2.4 #include "mem.h" 2.5 #include "vm.h" 2.6 2.7 -static void do_nothing(); 2.8 - 2.9 -/* special keys */ 2.10 -enum { 2.11 - LALT, RALT, 2.12 - LCTRL, RCTRL, 2.13 - LSHIFT, RSHIFT, 2.14 - F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, 2.15 - CAPSLK, NUMLK, SCRLK, SYSRQ, 2.16 - ESC = 27, 2.17 - INSERT, DEL, HOME, END, PGUP, PGDN, LEFT, RIGHT, UP, DOWN, 2.18 - NUM_DOT, NUM_ENTER, NUM_PLUS, NUM_MINUS, NUM_MUL, NUM_DIV, 2.19 - NUM_0, NUM_1, NUM_2, NUM_3, NUM_4, NUM_5, NUM_6, NUM_7, NUM_8, NUM_9, 2.20 - BACKSP = 127 2.21 -}; 2.22 - 2.23 -/* table with rough translations from set 1 scancodes to ASCII-ish */ 2.24 -static int keycodes[] = { 2.25 - 0, ESC, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', /* 0 - e */ 2.26 - '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* f - 1c */ 2.27 - LCTRL, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', /* 1d - 29 */ 2.28 - LSHIFT, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', RSHIFT, /* 2a - 36 */ 2.29 - NUM_MUL, LALT, ' ', CAPSLK, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, /* 37 - 44 */ 2.30 - NUMLK, SCRLK, NUM_7, NUM_8, NUM_9, NUM_MINUS, NUM_4, NUM_5, NUM_6, NUM_PLUS, /* 45 - 4e */ 2.31 - NUM_1, NUM_2, NUM_3, NUM_0, NUM_DOT, SYSRQ, 0, 0, F11, F12, /* 4d - 58 */ 2.32 - 0, 0, 0, 0, 0, 0, 0, /* 59 - 5f */ 2.33 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 60 - 6f */ 2.34 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 /* 70 - 7f */ 2.35 -}; 2.36 2.37 void kmain(struct mboot_info *mbinf) 2.38 { 2.39 @@ -72,13 +43,6 @@ 2.40 2.41 2.42 for(;;) { 2.43 - char c, keypress; 2.44 - do { 2.45 - inb(keypress, 0x64); 2.46 - } while(!(keypress & 1)); 2.47 - inb(c, 0x60); 2.48 - if(!(c & 0x80)) { 2.49 - putchar(keycodes[(int)c]); 2.50 - } 2.51 + halt_cpu(); 2.52 } 2.53 }
3.1 --- a/src/panic.c Sun Jul 24 18:29:24 2011 +0300 3.2 +++ b/src/panic.c Mon Jul 25 11:29:02 2011 +0300 3.3 @@ -3,7 +3,7 @@ 3.4 #include <stdarg.h> 3.5 #include "asmops.h" 3.6 3.7 -struct registers { 3.8 +struct all_registers { 3.9 uint32_t eax, ebx, ecx, edx; 3.10 uint32_t esp, ebp, esi, edi; 3.11 uint32_t eflags; 3.12 @@ -12,12 +12,12 @@ 3.13 }; 3.14 3.15 /* defined in regs.S */ 3.16 -void get_regs(struct registers *regs); 3.17 +void get_regs(struct all_registers *regs); 3.18 3.19 void panic(const char *fmt, ...) 3.20 { 3.21 va_list ap; 3.22 - struct registers regs; 3.23 + struct all_registers regs; 3.24 3.25 disable_intr(); 3.26
4.1 --- a/src/proc.c Sun Jul 24 18:29:24 2011 +0300 4.2 +++ b/src/proc.c Mon Jul 25 11:29:02 2011 +0300 4.3 @@ -11,6 +11,7 @@ 4.4 /* prepare the first process */ 4.5 4.6 /* create the virtual address space for this process */ 4.7 + proc[0].ctx.pgtbl_paddr = clone_vmem(); 4.8 4.9 /* allocate a chunk of memory for the process image 4.10 * and copy the code of test_proc there. 4.11 @@ -28,10 +29,11 @@ 4.12 */ 4.13 } 4.14 4.15 +/* 4.16 void save_context(struct intr_frame *ifrm) 4.17 { 4.18 proc[cur_pid].ctx->regs = ifrm->regs; 4.19 proc[cur_pid].ctx->instr_ptr = ifrm->eip; 4.20 proc[cur_pid].ctx->stack_ptr = ifrm->esp; 4.21 proc[cur_pid].ctx->flags = ifrm->eflags; 4.22 -} 4.23 +}*/
5.1 --- a/src/proc.h Sun Jul 24 18:29:24 2011 +0300 5.2 +++ b/src/proc.h Mon Jul 25 11:29:02 2011 +0300 5.3 @@ -1,6 +1,7 @@ 5.4 #ifndef PROC_H_ 5.5 #define PROC_H_ 5.6 5.7 +#include <inttypes.h> 5.8 #include "asmops.h" 5.9 5.10 #define MAX_PROC 128 5.11 @@ -10,6 +11,7 @@ 5.12 uint32_t instr_ptr; 5.13 uint32_t stack_ptr; 5.14 uint32_t flags; 5.15 + uint32_t pgtbl_paddr; 5.16 /* TODO add FPU state */ 5.17 }; 5.18
6.1 --- a/src/vm.c Sun Jul 24 18:29:24 2011 +0300 6.2 +++ b/src/vm.c Mon Jul 25 11:29:02 2011 +0300 6.3 @@ -134,9 +134,10 @@ 6.4 return 0; 6.5 } 6.6 6.7 -void unmap_page(int vpage) 6.8 +int unmap_page(int vpage) 6.9 { 6.10 uint32_t *pgtbl; 6.11 + int res = 0; 6.12 int diridx = PAGE_TO_PGTBL(vpage); 6.13 int pgidx = PAGE_TO_PGTBL_PG(vpage); 6.14 6.15 @@ -157,8 +158,10 @@ 6.16 if(0) { 6.17 err: 6.18 printf("unmap_page(%d): page already not mapped\n", vpage); 6.19 + res = -1; 6.20 } 6.21 set_intr_state(intr_state); 6.22 + return res; 6.23 } 6.24 6.25 /* if ppg_start is -1, we allocate physical pages to map with alloc_phys_page() */ 6.26 @@ -173,6 +176,18 @@ 6.27 return 0; 6.28 } 6.29 6.30 +int unmap_page_range(int vpg_start, int pgcount) 6.31 +{ 6.32 + int i, res = 0; 6.33 + 6.34 + for(i=0; i<pgcount; i++) { 6.35 + if(unmap_page(vpg_start + i) == -1) { 6.36 + res = -1; 6.37 + } 6.38 + } 6.39 + return res; 6.40 +} 6.41 + 6.42 /* if paddr is 0, we allocate physical pages with alloc_phys_page() */ 6.43 int map_mem_range(uint32_t vaddr, size_t sz, uint32_t paddr, unsigned int attr) 6.44 { 6.45 @@ -193,21 +208,39 @@ 6.46 6.47 uint32_t virt_to_phys(uint32_t vaddr) 6.48 { 6.49 + int pg; 6.50 + uint32_t pgaddr; 6.51 + 6.52 + if((pg = virt_to_phys_page(ADDR_TO_PAGE(vaddr))) == -1) { 6.53 + return 0; 6.54 + } 6.55 + pgaddr = PAGE_TO_ADDR(pg); 6.56 + 6.57 + return pgaddr | ADDR_TO_PGOFFS(vaddr); 6.58 +} 6.59 + 6.60 +int virt_to_phys_page(int vpg) 6.61 +{ 6.62 uint32_t pgaddr, *pgtbl; 6.63 - int diridx = ADDR_TO_PGTBL(vaddr); 6.64 - int pgidx = ADDR_TO_PGTBL_PG(vaddr); 6.65 + int diridx, pgidx; 6.66 + 6.67 + if(vpg < 0 || vpg >= PAGE_COUNT) { 6.68 + return -1; 6.69 + } 6.70 + 6.71 + diridx = PAGE_TO_PGTBL(vpg); 6.72 + pgidx = PAGE_TO_PGTBL_PG(vpg); 6.73 6.74 if(!(pgdir[diridx] & PG_PRESENT)) { 6.75 - panic("virt_to_phys(%x): page table %d not present\n", vaddr, diridx); 6.76 + return -1; 6.77 } 6.78 pgtbl = PGTBL(diridx); 6.79 6.80 if(!(pgtbl[pgidx] & PG_PRESENT)) { 6.81 - panic("virt_to_phys(%x): page %d not present\n", vaddr, ADDR_TO_PAGE(vaddr)); 6.82 + return -1; 6.83 } 6.84 pgaddr = pgtbl[pgidx] & PGENT_ADDR_MASK; 6.85 - 6.86 - return pgaddr | ADDR_TO_PGOFFS(vaddr); 6.87 + return ADDR_TO_PAGE(pgaddr); 6.88 } 6.89 6.90 /* allocate a contiguous block of virtual memory pages along with 6.91 @@ -266,9 +299,9 @@ 6.92 disable_intr(); 6.93 6.94 for(i=0; i<num; i++) { 6.95 - uint32_t phys = virt_to_phys(PAGE_TO_ADDR(start + i)); 6.96 - if(phys) { 6.97 - free_phys_page(ADDR_TO_PAGE(phys)); 6.98 + int phys_pg = virt_to_phys_page(start + i); 6.99 + if(phys_pg != -1) { 6.100 + free_phys_page(phys_pg); 6.101 } 6.102 } 6.103 6.104 @@ -393,6 +426,60 @@ 6.105 } 6.106 6.107 6.108 +/* clone_vmem makes a copy of the current page tables, thus duplicating 6.109 + * the virtual address space. 6.110 + * 6.111 + * Returns the physical address of the new page directory. 6.112 + */ 6.113 +uint32_t clone_vmem(void) 6.114 +{ 6.115 + int i, dirpg, tblpg; 6.116 + uint32_t paddr; 6.117 + uint32_t *ndir, *ntbl; 6.118 + 6.119 + if((dirpg = pgalloc(1, MEM_KERNEL)) == -1) { 6.120 + panic("clone_vmem: failed to allocate page directory page\n"); 6.121 + } 6.122 + ndir = (uint32_t*)PAGE_TO_ADDR(dirpg); 6.123 + 6.124 + if((tblpg = pgalloc(1, MEM_KERNEL)) == -1) { 6.125 + panic("clone_vmem: failed to allocate page table page\n"); 6.126 + } 6.127 + ntbl = (uint32_t*)PAGE_TO_ADDR(tblpg); 6.128 + 6.129 + /* we will allocate physical pages and map them to this virtual page 6.130 + * as needed in the loop below. 6.131 + */ 6.132 + free_phys_page(virt_to_phys(tblpg)); 6.133 + 6.134 + for(i=0; i<1024; i++) { 6.135 + if(pgdir[i] & PG_PRESENT) { 6.136 + paddr = alloc_phys_page(); 6.137 + map_page(tblpg, ADDR_TO_PAGE(paddr), 0); 6.138 + 6.139 + /* copy the page table */ 6.140 + memcpy(ntbl, PGTBL(i), PGSIZE); 6.141 + 6.142 + /* set the new page directory entry */ 6.143 + ndir[i] = paddr | (pgdir[i] & PGOFFS_MASK); 6.144 + } else { 6.145 + ndir[i] = 0; 6.146 + } 6.147 + } 6.148 + 6.149 + paddr = virt_to_phys(dirpg); 6.150 + 6.151 + /* unmap before freeing to avoid deallocating the physical pages */ 6.152 + unmap_page(dirpg); 6.153 + unmap_page(tblpg); 6.154 + 6.155 + pgfree(dirpg, 1); 6.156 + pgfree(tblpg, 1); 6.157 + 6.158 + return paddr; 6.159 +} 6.160 + 6.161 + 6.162 void dbg_print_vm(int area) 6.163 { 6.164 struct page_range *node;
7.1 --- a/src/vm.h Sun Jul 24 18:29:24 2011 +0300 7.2 +++ b/src/vm.h Mon Jul 25 11:29:02 2011 +0300 7.3 @@ -38,9 +38,12 @@ 7.4 void init_vm(void); 7.5 7.6 int map_page(int vpage, int ppage, unsigned int attr); 7.7 +int unmap_page(int vpage); 7.8 int map_page_range(int vpg_start, int pgcount, int ppg_start, unsigned int attr); 7.9 +int unmap_page_range(int vpg_start, int pgcount); 7.10 int map_mem_range(uint32_t vaddr, size_t sz, uint32_t paddr, unsigned int attr); 7.11 7.12 +int virt_to_phys_page(int vpg); 7.13 uint32_t virt_to_phys(uint32_t vaddr); 7.14 7.15 enum { 7.16 @@ -51,6 +54,8 @@ 7.17 int pgalloc(int num, int area); 7.18 void pgfree(int start, int num); 7.19 7.20 +uint32_t clone_vmem(void); 7.21 + 7.22 void dbg_print_vm(int area); 7.23 7.24 #endif /* VM_H_ */