您的位置:首页 > 其它

Jos-lab3 (Exercise 1 & 2)

2014-01-23 15:40 417 查看
Exercise 1.Modify
mem_init()
in
kern/pmap.cto allocate and map the
envs
array.This array consists o fexactly
NENV
instances of the
Env
structure allocated much like how you allocated the
pages
array.Also like the
pages
array, the memory backing
envs
should also be mapped user read-only at
UENVS
(defined in
inc/memlayout.h) so user processes can read from this array.

You should run your code and make sure
check_kern_pgdir()
succeeds.

Answer:

        // Make 'envs' point to an array of size 'NENV' of 'struct Env'.
        // LAB 3: Your code here.

-

+      envs = (struct Env *)boot_alloc(NENV * sizeof(struct Env));

+       memset(pages, 0, NENV * sizeof(struct Env));

        //////////////////////////////////////////////////////////////////////

        // Now that we've allocated the initial kernel data structures, we set

        // up the list of free physicalpages. Once we've done so, all further

@@ -203,7 +204,9 @@ mem_init(void)

        //    - the new image atUENVS  -- kernel R, user R

        //    -envs itself -- kernel RW, user NONE

        // LAB 3: Your code here.

-

+       boot_map_region(kern_pgdir,UENVS,

+                       ROUNDUP(NENV*sizeof(struct Env), PGSIZE),

+                       PADDR(envs), PTE_U);

Exercise 2.In the file env.c,finish coding the following functions:

env_init()
Initialize all of the
Env
structures in the
envs
array and add them to the
env_free_list
.Also calls
env_init_percpu
, which configures the segmentation hardware with separate segments for privilege level 0 (kernel) and privilege level 3 (user).122         env_free_list =envs;

123         struct Env *iter = env_free_list;

124         while (i < NENV) {

125                envs[i].env_id = 0;

126                envs[i].env_status = ENV_FREE;

127                 i++;

128                 iter->env_link =envs + i;

129         }Q:envs在mem_init()里用boot_map_region()已经申请过空间了,就物理空间上应该是紧挨着pages?
env_setup_vm()
Allocate a page directory for a new environmentand initialize the kernel portionof the new environment's address space.198         p->pp_ref++;

199         e->env_pgdir = page2kva(p);

200         memmove(e->env_pgdir,kern_pgdir,PGSIZE);

201         memset(e->env_pgdir,0,PDX(UTOP)*sizeof(pde_t));

原来以为是做映射,其实这边每个enviroment都需要有一个pgdir,让每个用户环境都能映射到4GB的空间。kern_pgdir已经映射到4GB空间,而对于UTOP以上的空间,所有的user enviroment都是和kernel一样的映射,因此可以直接copy过来用。

region_alloc()
Allocates and maps physical memory for an environment284         uint32_t ua,la;

285         ua = (uint32_t)ROUNDUP(va+len, PGSIZE);

286         la = (uint32_t)ROUNDDOWN(va, PGSIZE);

287         uint32_t size = 0;

288         struct Page *p = NULL;

289         for(size = 0;size < (ua - la);size += PGSIZE) {

290                 if (!(p = page_alloc(ALLOC_ZERO)))

291                         panic("page allocation failed!\n");

292 // Jacky: Original I thought should use boot_map_region to map, but     actually it's only a static mapping, should use page_insert

293 //              boot_map_region(e->env_pgdir, va+size, PGSIZE,

294 //                              page2pa(p), PTE_W|PTE_U);

295                 page_insert(e->env_pgdir, p, va+size, PTE_W|PTE_U);

296         }

load_icode()
You will need to parse an ELF binary image,much like the boot loader already does,and load its contents into the user address spaceof a new environment.358         // LAB 3: Jacky 14020.

359         struct Elf *elf = (struct Elf *)binary;

360         struct Proghdr *ph, *eph;

361         if(elf->e_magic != ELF_MAGIC) {

362                 cprintf("%s() It's not an ELF file!\n",__func__);

363                 return;

364         }

365         // Mistake 1: Almost miss this one, it's changing the address space from k    ernel to e enviroment;

366         lcr3((uint32_t)e->env_pgdir);

367         ph = (struct Proghdr *) ((uint8_t *)elf + elf->e_phoff);

368         eph = ph + elf->e_phnum;

369         for (;ph<eph;ph++) {

370                 if (ph->p_type != ELF_PROG_LOAD)

371                         continue;

372                 region_alloc(e,(void *)ph->p_va,ph->p_memsz);

373                 memmove((void *)ph->p_va, (uint8_t *)elf + ph->p_offset, ph->p_fil    esz);

374                 memset((void *)(ph->p_va + ph->p_filesz), 0, ph->p_memsz - ph->p_f    ilesz);

375         }

376         // Mistake 2: set the enviroment's entry point

377         e->env_tf.tf_eip = elf->e_entry;

378

379         // Now map one page for the program's initial stack

380         // at virtual address USTACKTOP - PGSIZE.

381

382         // LAB 3: Jacky 140120

383         region_alloc(e, (void *)(USTACKTOP-PGSIZE), PGSIZE);

env_create()
Allocate an environment with
env_alloc
and call
load_icode
load an ELF binary into it.395 {

396         // LAB 3: Jacky140120

397         struct Env* e;

398         int failno = env_alloc(&e, 0);

399         if (failno < 0) {

400                 cprintf("%s(0x%x, %d, %d) failed, fail code = %d!\n",__func__, bin    ary, size, type);

401                 return;

402         }

403         load_icode(*e, binary, size)

404         e->env_type = type;

405 }      

env_run()
Start a given environment running in user mode.521         if (curenv) {

522                 if(curenv->env_status == ENV_RUNNING)

523                         curenv->env_status = ENV_RUNNABLE;

524         }

525         curenv = e;

526         curenv->env_status = ENV_RUNNING;

527         curenv->env_runs++;

528         lcr3(PADDR(curenv->env_pgdir));

529

530         env_pop_tf(&curenv->env_tf);

531         panic("env_run not yet implemented");
As you write these functions,you might find the new cprintf verb
%e
useful -- it prints a description corresponding to an error code.For example,

r = -E_NO_MEM;
panic("env_alloc: %e", r);

will panic with the message "env_alloc: out of memory".
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  OS x86 qemu