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)