kern
diff src/vm.c @ 57:437360696883
I think we're done for now. two processes seem to be scheduled and switched just fine, fork seems to work (NO CoW YET!)
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Tue, 16 Aug 2011 03:26:53 +0300 |
parents | 88a6c4e192f9 |
children | c2692696f9ab |
line diff
1.1 --- a/src/vm.c Mon Aug 15 06:17:58 2011 +0300 1.2 +++ b/src/vm.c Tue Aug 16 03:26:53 2011 +0300 1.3 @@ -566,7 +566,6 @@ 1.4 /*printf("free_node\n");*/ 1.5 } 1.6 1.7 -#if 0 1.8 /* clone_vm makes a copy of the current page tables, thus duplicating the 1.9 * virtual address space. 1.10 * 1.11 @@ -574,11 +573,14 @@ 1.12 * we don't want to diplicate the page tables, just point all page directory 1.13 * entries to the same set of page tables. 1.14 * 1.15 + * If "cow" is non-zero it also marks the shared user-space pages as 1.16 + * read-only, to implement copy-on-write. 1.17 + * 1.18 * Returns the physical address of the new page directory. 1.19 */ 1.20 -uint32_t clone_vm(void) 1.21 +uint32_t clone_vm(int cow) 1.22 { 1.23 - int i, dirpg, tblpg, kstart_dirent; 1.24 + int i, j, dirpg, tblpg, kstart_dirent; 1.25 uint32_t paddr; 1.26 uint32_t *ndir, *ntbl; 1.27 1.28 @@ -597,7 +599,8 @@ 1.29 ntbl = (uint32_t*)PAGE_TO_ADDR(tblpg); 1.30 1.31 /* we will allocate physical pages and map them to this virtual page 1.32 - * as needed in the loop below. 1.33 + * as needed in the loop below. we don't need the physical page allocated 1.34 + * by pgalloc. 1.35 */ 1.36 free_phys_page(virt_to_phys((uint32_t)ntbl)); 1.37 1.38 @@ -606,10 +609,18 @@ 1.39 /* user space */ 1.40 for(i=0; i<kstart_dirent; i++) { 1.41 if(pgdir[i] & PG_PRESENT) { 1.42 + /* first go through all the entries of the existing 1.43 + * page table and unset the writable bits. 1.44 + */ 1.45 + for(j=0; j<1024; j++) { 1.46 + PGTBL(i)[j] &= ~(uint32_t)PG_WRITABLE; 1.47 + } 1.48 + 1.49 + /* allocate a page table for the clone */ 1.50 paddr = alloc_phys_page(); 1.51 - map_page(tblpg, ADDR_TO_PAGE(paddr), PG_USER | PG_WRITABLE); 1.52 1.53 /* copy the page table */ 1.54 + map_page(tblpg, ADDR_TO_PAGE(paddr), 0); 1.55 memcpy(ntbl, PGTBL(i), PGSIZE); 1.56 1.57 /* set the new page directory entry */ 1.58 @@ -624,9 +635,12 @@ 1.59 ndir[i] = pgdir[i]; 1.60 } 1.61 1.62 + /* we just changed all the page protection bits, so we need to flush the TLB */ 1.63 + flush_tlb(); 1.64 + 1.65 paddr = virt_to_phys((uint32_t)ndir); 1.66 1.67 - /* unmap before freeing to avoid deallocating the physical pages */ 1.68 + /* unmap before freeing the virtual pages, to avoid deallocating the physical pages */ 1.69 unmap_page(dirpg); 1.70 unmap_page(tblpg); 1.71 1.72 @@ -635,7 +649,50 @@ 1.73 1.74 return paddr; 1.75 } 1.76 -#endif 1.77 + 1.78 +int get_page_bit(int pgnum, uint32_t bit, int wholepath) 1.79 +{ 1.80 + int tidx = PAGE_TO_PGTBL(pgnum); 1.81 + int tent = PAGE_TO_PGTBL_PG(pgnum); 1.82 + uint32_t *pgtbl = PGTBL(tidx); 1.83 + 1.84 + if(wholepath) { 1.85 + if((pgdir[tidx] & bit) == 0) { 1.86 + return 0; 1.87 + } 1.88 + } 1.89 + 1.90 + return pgtbl[tent] & bit; 1.91 +} 1.92 + 1.93 +void set_page_bit(int pgnum, uint32_t bit, int wholepath) 1.94 +{ 1.95 + int tidx = PAGE_TO_PGTBL(pgnum); 1.96 + int tent = PAGE_TO_PGTBL_PG(pgnum); 1.97 + uint32_t *pgtbl = PGTBL(tidx); 1.98 + 1.99 + if(wholepath) { 1.100 + pgdir[tidx] |= bit; 1.101 + } 1.102 + pgtbl[tent] |= bit; 1.103 + 1.104 + flush_tlb_page(pgnum); 1.105 +} 1.106 + 1.107 +void clear_page_bit(int pgnum, uint32_t bit, int wholepath) 1.108 +{ 1.109 + int tidx = PAGE_TO_PGTBL(pgnum); 1.110 + int tent = PAGE_TO_PGTBL_PG(pgnum); 1.111 + uint32_t *pgtbl = PGTBL(tidx); 1.112 + 1.113 + if(wholepath) { 1.114 + pgdir[tidx] &= ~bit; 1.115 + } 1.116 + 1.117 + pgtbl[tent] &= ~bit; 1.118 + 1.119 + flush_tlb_page(pgnum); 1.120 +} 1.121 1.122 1.123 void dbg_print_vm(int area)