Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1879399
  • 博文数量: 333
  • 博客积分: 10791
  • 博客等级: 上将
  • 技术积分: 4314
  • 用 户 组: 普通用户
  • 注册时间: 2007-08-08 07:39
文章分类

全部博文(333)

文章存档

2015年(1)

2011年(116)

2010年(187)

2009年(25)

2008年(3)

2007年(1)

分类:

2009-03-25 03:20:36

1、pgdir_walk(),返回指向为线性地址va分配的页表入口地址。如果相关页表没有在页目录中,那么做如下工作:
   如果create为0,那么返回NULL。否则,pgdir_walk()用page_alloc()分配一个新页,将pp_ref设置为1
===============================code=====================================
pte_t *
pgdir_walk(pde_t *pgdir, const void *va, int create)
{
 // Fill this function in       
      //
      // +--------10------+-------10-------+---------12----------+
      // | Page Directory |   Page Table   | Offset within Page  |
      // |      Index     |      Index     |                     |
      // +----------------+----------------+---------------------+
      //  \--- PDX(la) --/ \--- PTX(la) --/ \---- PGOFF(la) ----/
      //  \----------- PPN(la) -----------/
     
 struct Page* p;
 pte_t *pt;
 pgdir = (pde_t *)&pgdir[PDX(va)];
 //whether the page table exist or not
 //it isn't exist~ 
 if(0 == (*pgdir& PTE_P)){
  if(0 == create)return NULL;
  //allocate a page
  if(page_alloc(&p) < 0)return NULL;
  //p points to an entry in the pages table and set pp_ref to 1
  p->pp_ref = 1;
  //set the page clear
  memset(KADDR(page2pa(p)), 0, PGSIZE);
  //make the page directory point to that page (contains pt)
  *pgdir = page2pa(p) | PTE_U |PTE_W | PTE_P;
  }
 pt = (pte_t*) KADDR(PTE_ADDR(*pgdir));
 
 // Page table exists, return the VA of the page table entry
 return &pt[PTX(va)];
}
================================end=====================================
2、boot_map_segment(),将[la, la+size)的线性地址映射到[pa, pa+size)的物理地址上:
===============================code=====================================
static void
boot_map_segment(pde_t *pgdir, uintptr_t la, size_t size, physaddr_t pa, int perm)
{
 // Fill this function in
 uintptr_t i;
 pte_t *p;
 
 //1)Size is a multiple of PGSIZE and la must be a multiple of PGSIZE
 size = ROUNDUP(size, PGSIZE);
 assert (0 == la % PGSIZE); //assert va is a multiple of BY2PG.
 //2)size is multiple of PGSIZE,so we should creat pages no less 1
 for(i = 0; i < size; i+=PGSIZE){
  p = pgdir_walk(pgdir, (void*)la + i, 1);
  assert(p != NULL);
  *p = (pa +i) |perm |PTE_P;
  }//end for
 
}
================================end=====================================
3、page_lookup(),返回在虚拟地址va处分配的页面。
===============================code=====================================
struct Page *
page_lookup(pde_t *pgdir, void *va, pte_t **pte_store)
{
 // Fill this function in
 //pte is the pointer to the page table entry for va
 pte_t *pte = pgdir_walk(pgdir, va, 0);
 if(NULL == pte)
  return NULL;
 
  // If pte_store is not zero, then we store in it the address
   // of the pte for that page
 if(pte_store != NULL)
  *pte_store = pte;
 return pa2page(*pte); 
}
================================end=====================================
4、page_remove():
===============================code=====================================
void
page_remove(pde_t *pgdir, void *va)
{
 // Fill this function in
 pte_t *pte = NULL;
 struct Page *p;
 
 p = page_lookup(pgdir, va, &pte);
 if(NULL == p) return;
 //The ref count on the physical page should decrement
 page_decref(p);
 // Set the respective page table entry to 0
   if(pte != NULL)
      *pte = 0;
 //Set the TLB invalid
 tlb_invalidate(pgdir,  va);
 
}
================================end=====================================
5、page_insert()
===============================code=====================================
int
page_insert(pde_t *pgdir, struct Page *pp, void *va, int perm)
{
 // Fill this function in
 pte_t *pte;
 
 pte = pgdir_walk(pgdir, va, 1);
 if(NULL == pte)
  return -E_NO_MEM;
 // First increase the reference count so the page doesn't get
 // removed in the next step if we try to repeat a mapping
  pp->pp_ref++;
 // If there is something mapped there, page remove it
 if( (*pte & PTE_P) != 0)
  page_remove(pgdir, va);
 
 *pte = page2pa(pp) |PTE_P |perm;
 
 return 0;
}
================================end=====================================
6、补全i386_vm_init()
===============================code=====================================
void
i386_vm_init(void)
{
......
 //////////////////////////////////////////////////////////////////////
 // Map 'pages' read-only by the user at linear address UPAGES
 // (ie. perm = PTE_U | PTE_P)
 // Permissions:
 //    - pages -- kernel RW, user NONE
 //    - the read-only version mapped at  -- kernel R, user R
 // Your code goes here:
 n = ROUNDUP(npage*sizeof(struct Page), PGSIZE);
 assert(n < 4 *1024 * 1024);
 boot_map_segment(pgdir, UPAGES, n,
      PADDR(pages),PTE_W |PTE_U);
 //////////////////////////////////////////////////////////////////////
 // Map the kernel stack (symbol name "bootstack").  The complete VA
 // range of the stack, [KSTACKTOP-PTSIZE, KSTACKTOP), breaks into two
 // pieces:
 //     * [KSTACKTOP-KSTKSIZE, KSTACKTOP) -- backed by physical memory
 //     * [KSTACKTOP-PTSIZE, KSTACKTOP-KSTKSIZE) -- not backed => faults
 //     Permissions: kernel RW, user NONE
 // Your code goes here:
 boot_map_segment(pgdir, KSTACKTOP-KSTKSIZE, KSTKSIZE,
      PADDR(bootstack), PTE_W |PTE_P)

 boot_map_segment(pgdir, KSTACKTOP-PTSIZE, PTSIZE-KSTKSIZE, 0, 0);
 
 //////////////////////////////////////////////////////////////////////
 // Map all of physical memory at KERNBASE.
 // Ie.  the VA range [KERNBASE, 2^32) should map to
 //      the PA range [0, 2^32 - KERNBASE)
 // We might not have 2^32 - KERNBASE bytes of physical memory, but
 // we just set up the amapping anyway.
 // Permissions: kernel RW, user NONE
 // Your code goes here:
 boot_map_segment(pgdir, KERNBASE, ~KERNBASE+1,0, PTE_W|PTE_P);
......
}
================================end=====================================
   
阅读(4412) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~