Exercise 4.In the file kern/pmap.c,you must implement code for the following functions.
当使用80x86处理器时,必须区分三个地址
逻辑地址(Logical address):每个逻辑地址包括一个段和偏移,偏移指从段起始地址到实际地址的偏移。
线性地址(Linear address)(也称虚拟地址):一个32位无符号整数,可以用来表示高达4GB的地址,通常用十六进制表示,范围从0x00000000到0xffffffff
物理地址(physical address):用于在内存芯片上寻址内存单元。与从CPU地址引脚发送到内存总线的电信号相对应。
MMU通过一种称为分段单元(segmentation unit)的硬件电路吧逻辑地址转换成线性地址,接着分页单元(paging uni)的硬件电路把线性地址转换成一个物理地址。
Exercise 4的几个函数都是基于线性地址到物理地址的转换,具体的转换可以参考i386手册中关于paging的部分。pgdir_walk() 416 pte_t *result = NULL; 417 pde_t *pdt = pgdir + PDX(va); 419 struct Page* newpta = NULL; 421 cprintf("%s(0x%x, 0x%x, %d, pdt = %x,*pdt = %x),\n",__func__,pgdir,va,create,pdt, *pdt); 423 if (!(*pdt & PTE_P)) { // the page table entry not present yet 424 if(create) { 425 newpta = page_alloc(PGSIZE); 427 if(newpta == NULL) { 429 return NULL; 430 } else { 431 memset(page2kva(newpta), 0, PGSIZE); 432 newpta->pp_ref++; 433 *pdt = PADDR(page2kva(newpta))|PTE_U|PTE_W|PTE_P; 435 } 436 } else { 438 return NULL; 439 } 440 } 441 result = (pte_t *)KADDR(PTE_ADDR(*pdt)) + PTX(va); boot_map_region() 469 int n = ROUNDUP(size, PGSIZE) / PGSIZE; 470 int i; 471 pte_t *pte = NULL; 472 for(i = 0; i < n; i++) { 473 pte = pgdir_walk(pgdir, (void *)(va + i*PGSIZE), 1); 474 *pte = (pa + i*PGSIZE)|perm|PTE_P; 475 } page_lookup() 554 pte_t *pte = pgdir_walk(pgdir, va, 0); 556 if(pte_store != NULL) { 557 *pte_store = pte; 559 } 560 if ((pte == NULL) || ((*pte & PTE_P) == 0)) { 562 return NULL; 563 } 565 return pa2page(PTE_ADDR(*pte)); page_remove() 587 pte_t *pte; 588 struct Page *pa = page_lookup(pgdir, va, &pte); 589 if(!pa) { 591 return; 592 } 593 page_decref(pa); 594 *pte = 0; 595 if (!pa->pp_ref) { 596 page_free(pa); 597 } 598 tlb_invalidate(pgdir,va); page_insert() 507 pte_t *pte = pgdir_walk(pgdir, va, 1); 508 if (!pte) 509 return -E_NO_MEM; 510 if(PTE_ADDR(*pte) != page2pa(pp)) { 512 page_remove(pgdir, va); 513 pte = pgdir_walk(pgdir, va, 1); 515 pp->pp_ref++; 516 } 517 *pte = page2pa(pp)|perm|PTE_P; 518 return 0;