[MIT6.828]LAB2 Exercise & Question总结

E1:In the file kern/pmap.c, you must implement code for the following functions.

static void *boot_alloc(uint32_t n, uint32_t align)
	extern char end[];
	void *v;
	if (boot_freemem == 0)
		boot_freemem = end;
	boot_freemem = ROUNDUP(boot_freemem, align);
	v = boot_freemem;
	boot_freemem += n;
	return v;
void page_init(void)
	extern char end[];
	int i=0;

	memset(pages, 0, npage*sizeof(pages[0]));
	//page 0
	pages[0].pp_ref = 1;
	//rest basemem
	for (i=1 ; i < (basemem>>PGSHIFT); ++i)
		LIST_INSERT_HEAD(&page_free_list, &pages[i], pp_link);
	//page io
	for (i; i < (EXTPHYSMEM>>PGSHIFT); ++i)
		pages[i].pp_ref = 1;
	//externed mem
	//kernel code1
	for (i; i < (ROUNDUP(PADDR(bootstack), PGSIZE)>>PGSHIFT); ++i)
		pages[i].pp_ref = 1;
	//kernel stack
	for (i; i < (KSTKSIZE>>PGSHIFT); ++i)
		pages[i].pp_ref = 2;
	//kernel code2 & static data
	for (i; i < (ROUNDUP(PADDR(end), PGSIZE)>>PGSHIFT); ++i)
		pages[i].pp_ref = 1;
	//Page directory
	pages[i++].pp_ref = 3;
	//Page list
	for(i; i< (ROUNDUP(PADDR(pages+npage), PGSIZE)>>PGSHIFT); ++i)
		pages[i].pp_ref = 2;
	//other boot alloc
	for(i; i< (ROUNDUP(PADDR(boot_freemem), PGSIZE)>>PGSHIFT); ++i)
		pages[i].pp_ref =1;
	for(i; i< npage; ++i)
		LIST_INSERT_HEAD(&page_free_list, &pages[i], pp_link);
int page_alloc(struct Page **pp_store)
	*pp_store = LIST_FIRST(&page_free_list); //find a free page
	if (*pp_store == NULL)
		return -E_NO_MEM; //no free
	LIST_REMOVE(*pp_store, pp_link); // remove from list
	page_initpp(*pp_store);	//clear
	return 0;
void page_free(struct Page *pp)
	assert(pp->pp_ref ==0 ); // reference == 0 then free
	LIST_INSERT_HEAD(&page_free_list, pp, pp_link);


pages = boot_alloc(npage*sizeof(struct Page), PGSIZE);







E4:In the file kern/pmap.c, you must implement code for the following functions.

pte_t *pgdir_walk(pde_t *pgdir, const void *va, int create)
	pte_t *pptab;
	struct Page *pp;
	pgdir = pgdir + PDX(va);// locate the pde
	if (! (*pgdir & PTE_P) )
	{// not present
		if ( !create )
			return NULL;
		//create page table;
		if ( page_alloc(&pp) == -E_NO_MEM )
			return NULL;//no free page
		pptab = (pte_t *)page2kva(pp); // VIRTUAL ADDR!!!
		memset(pptab, 0, PGSIZE); // clear
		*pgdir = PADDR(pptab)|PTE_USER;// pde & priority
		pp->pp_ref++;		//reference  ++
		pptab =(pte_t *) KADDR(PTE_ADDR(*pgdir)); // VIRTUAL ADDR!!!
	return pptab+PTX(va);
//注意处理 页被重新映射到同一块地址的情况,权限位要变,TLB要失效,引用计数不变。
int page_insert(pde_t *pgdir, struct Page *pp, void *va, int perm)
	pte_t *ppte = pgdir_walk(pgdir, va, 1);
	if (ppte == NULL) //cann't alloc pagetable
		return -E_NO_MEM;
	if( ISPTE_P(*ppte))
		if (page2pa(pp) != PTE_ADDR(*ppte))//not equal, remove
			page_remove(pgdir, va);
			tlb_invalidate(pgdir, va),pp->pp_ref --;
	pp->pp_ref ++;
	*ppte = page2pa(pp)|perm|PTE_P;
	return 0;
static void boot_map_segment(pde_t *pgdir, uintptr_t la, size_t size, physaddr_t pa, int perm)
	pte_t *ppte;
	uintptr_t lla = la +size;
	while ( la!=lla )//ATTENTION overflow!!!
		ppte = pgdir_walk(pgdir, (void *)(la), 1);
		assert( ppte!=NULL || ISPTE_P(*ppte));//null or remap
		*ppte = PTE_ADDR(pa)|perm|PTE_P;
		la += PGSIZE;
		pa += PGSIZE;
struct Page *page_lookup(pde_t *pgdir, void *va, pte_t **pte_store)
	pte_t *ppte = pgdir_walk(pgdir, va, 0);
	if (ppte == NULL)//page table not present
		return NULL;
	if (pte_store != NULL)
		*pte_store = ppte;
	return pa2page(*ppte);
void page_remove(pde_t *pgdir, void *va)
	pte_t *ppte;
	struct Page *ppage;

	ppage = page_lookup(pgdir, va, &ppte);
	if (ppage != NULL && ISPTE_P(*ppte))//present
		*ppte = (pte_t)0;
		tlb_invalidate(pgdir, va);


Exercise 5.  Fill in the missing code in i386_vm_init() after the call to page_check().


boot_map_segment(pgdir, UPAGES, ROUNDUP(npage*sizeof(struct Page), PGSIZE), PADDR(pages), PTE_U|PTE_P);
boot_map_segment(pgdir, KSTACK, ROUNDUP(KSTKSIZE,PGSIZE), PADDR(bootstack), PTE_W|PTE_P);
boot_map_segment(pgdir, KERNBASE, ROUNDUP(~KERNBASE, PGSIZE), 0, PTE_W|PTE_P);


Q1:Assuming that the following JOS kernel code is correct, what type should variable x have, uintptr_t or physaddr_t?
    mystery_t x;
    char* value = return_a_pointer();
    *value = 10;
    x = (mystery_t) value;
value是可以直接操作虚拟内存的char * ,x是从value强制转化而来,没有经过虚拟内存转物理内存的步骤,所以mystery_t应该也是虚拟内存的一种,故x是uintptr_t类型。

Q2:What entries (rows) in the page directory have been filled in at this point? What addresses do they map and where do they point? In other words, fill out this table as much as possible:

Entry 	Base Virtual Address 	Points to (logically):
1023	0xffc0000		page table for top 4MB of phys memory
1022	0xff80000		page table for 248MB--(252MB-1) phys mem
.	.			page table for ... phys mem
960	0xf000000(KERNBASE)	page table for kernel code & static data 0--(4MB-1) phys mem
959	0xefc0000(VPT)		page directory self(kernel RW)
958	0xef80000(ULIM)		page table for kernel stack
957	0xef40000(UVPT)		same as 959 (user kernel R)
956	0xef00000(UPAGES)	page table for struct Pages[]
.	.			NULL
1	0x00400000		NULL
0	0x00000000		same as 960 (then turn to NULL)

Q3:After check_boot_pgdir(), i386_vm_init() maps the first four MB of virtual address space to the first four MB of physical memory, then deletes this mapping at the end of the function. Why is this mapping necessary? What would happen if it were omitted? Does this actually limit our kernel to be 4MB? What must be true if our kernel were larger than 4MB?

Q4:(From Lecture 4) We have placed the kernel and user environment in the same address space. Why will user programs not be able to read or write the kernel’s memory? What specific mechanisms protect the kernel memory?


Q5:What is the maximum amount of physical memory that this operating system can support? Why?


Q6:How much space overhead is there for managing memory, if we actually had the maximum amount of physical memory? How is this overhead broken down?

[0, 4K)			保留给实模式的IDT和BIOS
[640K,1M)		用于IO映射
[., end)		用户内核代码和数据存储
[., ROUNDUP(.,PAGE))	用于内存对齐
[., .+PGSIZE)		用于保存页目录
[., .+12*phymem/4K)	用于保存物理页信息
4K*2			用于保存内核栈页表和pages映射页表。
phymem/4M		用于保存其他全部页表



This entry was posted in 操作系统 and tagged . Bookmark the permalink.

2 Responses to [MIT6.828]LAB2 Exercise & Question总结

  1. snail says:



您的电子邮箱地址不会被公开。 必填项已用 * 标注