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

全部博文(333)

文章存档

2015年(1)

2011年(116)

2010年(187)

2009年(25)

2008年(3)

2007年(1)

分类:

2009-04-18 00:03:29

一、kern/env.c
1、env_init()函数:对在envs数组中的所有Env结构并把他们加入到env_free_list
=======================================code========================================
void env_init(void){
 //init the list
 LIST_INIT(&env_free_list);
 //// setup free environments
 int i;
 for( i = NENV - 1; i >= 0; i--) {
  //set env as free
  envs[i].env_status = ENV_FREE;
  //set env_ids to 0
  envs[i].env_id = 0;
  //append head of list
  LIST_INSERT_HEAD(&env_free_list, &envs[i], env_link);
 }
}
=======================================end========================================
2、env_setup_vm()函数:为新的环境分配一个页目录并且初始化内核部分的新环境地址空间
=======================================code========================================
static int env_setup_vm(struct Env *e){
 int i, r;
 struct Page *p = NULL;
 // Allocate a page for the page directory
 if ((r = page_alloc(&p)) < 0)
  return r;
 //set env_pgdir's pp_ref
 p->pp_ref++;
 //set env_pgdir and env_cr3 of Env *e
 e->env_pgdir = page2kva(p); 
 e->env_cr3 = page2pa(p);
 //cprintf("env_setup_vm: env_cr3: \t%x\n", e->env_cr3);
 //init page directory 
 memset(e->env_pgdir, 0, PGSIZE); 
 //use pgdir entries above UTOP from boot_pgdir as template
 size_t size = (NPDENTRIES - PDX(UTOP)) * sizeof(pde_t);
 memmove(&e->env_pgdir[PDX(UTOP)], &boot_pgdir[PDX(UTOP)], size);
 
 //// VPT and UVPT map the env's own page table, with
 //// different permissions. 
 //set VPT and UVPT in pgdir to point to physical addr of self table
 e->env_pgdir[PDX(VPT)]  = e->env_cr3 | PTE_P | PTE_W;
 e->env_pgdir[PDX(UVPT)] = e->env_cr3 | PTE_P | PTE_U;
 return 0;
}
=======================================end========================================
3、segment_alloc()函数:为新的环境分配并映射一个物理内存
=======================================code========================================
static void segment_alloc(struct Env *e, void *va, size_t len){
 //round va down to nearest page address
 void *va_start = va - PGOFF(va);
 void *va_end = ROUNDUP(va + len, PGSIZE);
 //round len up to nearest page
 //len = ROUNDUP(len, PGSIZE);

 ////alloc and insert number of pages needed
 //get num pages needed
 assert( 0 == (va_end - va_start) % PGSIZE);
 int num_pages = (va_end - va_start) / PGSIZE;
 //alloc and insert each page
 struct Page *pp = NULL;
 int i;
 for(i=0; i < num_pages; i++) {
  //alloc page
  //cprintf("segment_alloc: page_allc\n");
  if(page_alloc(&pp) < 0)
   panic("segment_alloc: failed page alloc");
  //insert page into env's pgdir at each pages's va addr
  //cprintf("segment_alloc: page_insert\n");
  void *va_addr = va_start + i*PGSIZE;
  if(page_insert(e->env_pgdir, pp, va_addr, PTE_U | PTE_W) < 0)
   panic("segment_alloc: failed page insert");
 
  //cprintf("segment_alloc: va: %x\t\t mem: %x", va_addr, *((int*) va_addr));
  //cprintf("segment_alloc: alloc/insert page: %d\n", i);
 }
}
=======================================end========================================
4、load_icode()函数:装载新环境的用户地址空间的内容,这与boot loader的功能一致
=======================================code========================================
static void load_icode(struct Env *e, uint8_t *binary, size_t size){
 struct Elf *elf = (struct Elf *)binary;
 struct Proghdr *ph, *eph;
 uintptr_t i;
       struct Page *p;
   int r;
   pte_t* pte;
   uint32_t old_cr3 = rcr3();
 if(elf->e_magic != ELF_MAGIC)
  panic("elf->e_magic erro\n");
 //program header
 ph = (struct Proghdr *)(binary + elf->e_phoff);
 // one after last program header
   eph = ph + elf->e_phnum;
 // load the cr3 to be able to use memmove
 lcr3(PADDR(e->env_pgdir));
 // For each program header, load it into memory, zeroing as necessary
 for(; ph < eph; ph++){
  if(ph->p_type == ELF_PROG_LOAD){
   // Allocate the memory requested
   segment_alloc(e, (void *)ph->p_va, ph->p_memsz);
   // Copy data
   memmove((void *)ph->p_va, (void *)binary + ph->p_offset, ph->p_filesz);
   if(ph->p_memsz > ph->p_filesz)
    memset((void *)ph->p_va + ph->p_filesz, 0, ph->p_memsz -ph->p_filesz);
   }
  }
 
 // Set up the environment's trapframe to point to the right location
 // Other values for the trap frame as assigned in env_alloc
 e->env_tf.tf_eip = elf->e_entry;
 
 // Now map one page for the program's initial stack
 // at virtual address USTACKTOP - PGSIZE.
 // LAB 3: Your code here.
 r = page_alloc(&p);
 if(r < 0)
  panic("Alloc page erro at load_icode\n");
 page_insert(e->env_pgdir, p, (void *)USTACKTOP - PGSIZE, PTE_P|PTE_U|PTE_W);
 // Restore the old cr3
 lcr3(old_cr3);
}
=======================================end========================================
5、env_create()函数:利用env_alloc()函数分配一个环境并掉用load_icode装载一个ELF
=======================================code========================================
void env_create(uint8_t *binary, size_t size){
 struct Env *env = NULL;
 int r;
 // Since we setup the envs linked list so that the first one is
       // envs[0], all we have to do is allocate an environment
       r = env_alloc(&env, 0);
 if(r < 0)
  panic("env_alloc: %e",r);
 load_icode(env, binary, size);
}
=======================================end========================================
6、env_run()函数:以用户态运行一个给定的环境
=======================================code========================================
void env_run(struct Env *e){
 // Step 1
 curenv = e;
 curenv->env_runs++;
 lcr3(curenv->env_cr3);
 //Step 2
 env_pop_tf(&curenv->env_tf);
 }
=======================================end========================================
二、kern/trapentry.S
=======================================code========================================
_alltraps:
 # Build trap frame.
 pushl %ds
 pushl %es
 pushal
 # Set up data segments.
 movl $GD_KD, %eax
 movw %ax,%ds
 movw %ax,%es
 # Call trap(tf), where tf=%esp
 pushl %esp
 call trap
 popl %esp
 
 # Cleanup pushes and ret
 popal
 popl %es
 popl %ds
 iret
=======================================end========================================
 
 
 
阅读(5252) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~