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  }