kern
changeset 25:9939a6d7a45a
protected critical sections in VM and the physical memory manager by disabling interrupts
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 06 Apr 2011 07:42:44 +0300 |
parents | 53588744382c |
children | 387078ef5c0d 8ea6debe4265 |
files | src/intr-asm.S src/intr.h src/mem.c src/vm.c |
diffstat | 4 files changed, 73 insertions(+), 8 deletions(-) [+] |
line diff
1.1 --- a/src/intr-asm.S Tue Apr 05 02:09:02 2011 +0300 1.2 +++ b/src/intr-asm.S Wed Apr 06 07:42:44 2011 +0300 1.3 @@ -17,6 +17,28 @@ 1.4 lidt (lim) 1.5 ret 1.6 1.7 +/* get_intr_state() 1.8 + * returns 1 if interrutps are enabled, 0 if disabled */ 1.9 + .globl get_intr_state 1.10 +get_intr_state: 1.11 + pushf 1.12 + popl %eax 1.13 + shr $9, %eax /* bit 9 of eflags is IF */ 1.14 + andl $1, %eax 1.15 + ret 1.16 + 1.17 +/* set_intr_state(int state) 1.18 + * enables interrupts if the argument is non-zero, disables them otherwise */ 1.19 + .globl set_intr_state 1.20 +set_intr_state: 1.21 + cmpl $0, 4(%esp) 1.22 + jz 0f 1.23 + sti 1.24 + ret 1.25 +0: cli 1.26 + ret 1.27 + 1.28 + 1.29 /* interrupt entry with error code macro 1.30 * this macro generates an interrupt entry point for the 1.31 * exceptions which include error codes in the stack frame
2.1 --- a/src/intr.h Tue Apr 05 02:09:02 2011 +0300 2.2 +++ b/src/intr.h Wed Apr 06 07:42:44 2011 +0300 2.3 @@ -2,6 +2,7 @@ 2.4 #define INTR_H_ 2.5 2.6 #include <inttypes.h> 2.7 +#include "asmops.h" 2.8 2.9 typedef void (*intr_func_t)(int, uint32_t); 2.10 2.11 @@ -10,4 +11,8 @@ 2.12 2.13 void interrupt(int intr_num, intr_func_t func); 2.14 2.15 +/* defined in intr-asm.S */ 2.16 +int get_intr_state(void); 2.17 +void set_intr_state(int s); 2.18 + 2.19 #endif /* INTR_H_ */
3.1 --- a/src/mem.c Tue Apr 05 02:09:02 2011 +0300 3.2 +++ b/src/mem.c Wed Apr 06 07:42:44 2011 +0300 3.3 @@ -3,6 +3,7 @@ 3.4 #include "mem.h" 3.5 #include "panic.h" 3.6 #include "vm.h" 3.7 +#include "intr.h" 3.8 3.9 #define FREE 0 3.10 #define USED 1 3.11 @@ -120,7 +121,10 @@ 3.12 */ 3.13 uint32_t alloc_phys_page(void) 3.14 { 3.15 - int i, idx, max; 3.16 + int i, idx, max, intr_state; 3.17 + 3.18 + intr_state = get_intr_state(); 3.19 + disable_intr(); 3.20 3.21 idx = last_alloc_idx; 3.22 max = bmsize / 4; 3.23 @@ -139,6 +143,8 @@ 3.24 last_alloc_idx = idx; 3.25 3.26 printf("alloc_phys_page() -> %x (page: %d)\n", PAGE_TO_ADDR(pg), pg); 3.27 + 3.28 + set_intr_state(intr_state); 3.29 return PAGE_TO_ADDR(pg); 3.30 } 3.31 } 3.32 @@ -147,6 +153,7 @@ 3.33 idx++; 3.34 } 3.35 3.36 + set_intr_state(intr_state); 3.37 return 0; 3.38 } 3.39 3.40 @@ -163,6 +170,9 @@ 3.41 int pg = ADDR_TO_PAGE(addr); 3.42 int bmidx = BM_IDX(pg); 3.43 3.44 + int intr_state = get_intr_state(); 3.45 + disable_intr(); 3.46 + 3.47 if(!IS_FREE(pg)) { 3.48 panic("free_phys_page(%d): I thought that was already free!\n", pg); 3.49 } 3.50 @@ -171,6 +181,8 @@ 3.51 if(bmidx < last_alloc_idx) { 3.52 last_alloc_idx = bmidx; 3.53 } 3.54 + 3.55 + set_intr_state(intr_state); 3.56 } 3.57 3.58 /* this is only ever used by the VM init code to find out what the extends of
4.1 --- a/src/vm.c Tue Apr 05 02:09:02 2011 +0300 4.2 +++ b/src/vm.c Wed Apr 06 07:42:44 2011 +0300 4.3 @@ -97,13 +97,17 @@ 4.4 int map_page(int vpage, int ppage, unsigned int attr) 4.5 { 4.6 uint32_t *pgtbl; 4.7 - int diridx, pgidx, pgon; 4.8 + int diridx, pgidx, pgon, intr_state; 4.9 + 4.10 + intr_state = get_intr_state(); 4.11 + disable_intr(); 4.12 4.13 pgon = get_paging_status(); 4.14 4.15 if(ppage < 0) { 4.16 uint32_t addr = alloc_phys_page(); 4.17 if(!addr) { 4.18 + set_intr_state(intr_state); 4.19 return -1; 4.20 } 4.21 ppage = ADDR_TO_PAGE(addr); 4.22 @@ -129,6 +133,7 @@ 4.23 pgtbl[pgidx] = PAGE_TO_ADDR(ppage) | (attr & ATTR_PGTBL_MASK) | PG_PRESENT; 4.24 flush_tlb_page(vpage); 4.25 4.26 + set_intr_state(intr_state); 4.27 return 0; 4.28 } 4.29 4.30 @@ -138,6 +143,9 @@ 4.31 int diridx = PAGE_TO_PGTBL(vpage); 4.32 int pgidx = PAGE_TO_PGTBL_PG(vpage); 4.33 4.34 + int intr_state = get_intr_state(); 4.35 + disable_intr(); 4.36 + 4.37 if(!(pgdir[diridx] & PG_PRESENT)) { 4.38 goto err; 4.39 } 4.40 @@ -149,9 +157,11 @@ 4.41 pgtbl[pgidx] = 0; 4.42 flush_tlb_page(vpage); 4.43 4.44 - return; 4.45 + if(0) { 4.46 err: 4.47 - printf("unmap_page(%d): page already not mapped\n", vpage); 4.48 + printf("unmap_page(%d): page already not mapped\n", vpage); 4.49 + } 4.50 + set_intr_state(intr_state); 4.51 } 4.52 4.53 /* if ppg_start is -1, we allocate physical pages to map with alloc_phys_page() */ 4.54 @@ -217,9 +227,12 @@ 4.55 */ 4.56 int pgalloc(int num, int area) 4.57 { 4.58 - int ret = -1; 4.59 + int intr_state, ret = -1; 4.60 struct page_range *node, *prev, dummy; 4.61 4.62 + intr_state = get_intr_state(); 4.63 + disable_intr(); 4.64 + 4.65 dummy.next = pglist[area]; 4.66 node = pglist[area]; 4.67 prev = &dummy; 4.68 @@ -252,14 +265,18 @@ 4.69 } 4.70 } 4.71 4.72 + set_intr_state(intr_state); 4.73 return ret; 4.74 } 4.75 4.76 void pgfree(int start, int num) 4.77 { 4.78 - int area, end; 4.79 + int area, end, intr_state; 4.80 struct page_range *node, *new, *prev, *next; 4.81 4.82 + intr_state = get_intr_state(); 4.83 + disable_intr(); 4.84 + 4.85 if(!(new = alloc_node())) { 4.86 panic("pgfree: can't allocate new page_range node to add the freed pages\n"); 4.87 } 4.88 @@ -295,6 +312,7 @@ 4.89 } 4.90 4.91 coalesce(prev, new, next); 4.92 + set_intr_state(intr_state); 4.93 } 4.94 4.95 static void coalesce(struct page_range *low, struct page_range *mid, struct page_range *high) 4.96 @@ -382,8 +400,14 @@ 4.97 4.98 void dbg_print_vm(int area) 4.99 { 4.100 - struct page_range *node = pglist[area]; 4.101 - int last = area == MEM_USER ? 0 : ADDR_TO_PAGE(KMEM_START); 4.102 + struct page_range *node; 4.103 + int last, intr_state; 4.104 + 4.105 + intr_state = get_intr_state(); 4.106 + disable_intr(); 4.107 + 4.108 + node = pglist[area]; 4.109 + last = area == MEM_USER ? 0 : ADDR_TO_PAGE(KMEM_START); 4.110 4.111 printf("%s vm space\n", area == MEM_USER ? "user" : "kernel"); 4.112 4.113 @@ -402,4 +426,6 @@ 4.114 last = node->end; 4.115 node = node->next; 4.116 } 4.117 + 4.118 + set_intr_state(intr_state); 4.119 }