Exercise 1. In the file kern/pmap.c, you must implement code for the following functions (probably in the order given).
`boot_alloc()`
`mem_init()` (only up to the call to `check_page_free_list(1)`)
`page_init()`
`page_alloc()`
`page_free()`
check_page_free_list() and check_page_alloc() test your physical page allocator. You should boot JOS and see whether check_page_alloc() reports success. Fix your code so that it passes. You may find it helpful to add your own assert()s to verify that your assumptions are correct.
boot_alloc()
上面的代码默认分配了 bss 片段,并将 nextfree 指向末尾,这里只需要再分配 n byte 即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Allocate a chunk large enough to hold 'n' bytes, then update
// nextfree. Make sure nextfree is kept aligned to a multiple of PGSIZE.
/* ***************************************************************
* LAB 2: Your code here.
* ***************************************************************/cprintf("\n>>>Function <%s> called.<<<\n",__FUNCTION__);if(n!=0){cprintf("boot_alloc memory at <%x>\n",nextfree);char*next=nextfree;// keep aligned to a mutiple of PGSIZE
nextfree=ROUNDUP((char*)(nextfree+n),PGSIZE);cprintf("Next free memory at <%x>\n",nextfree);returnnext;}returnnextfree;
mem_init()
根据注释,注释掉这行,保证后面可以正常执行
1
2
// Remove this line when you're ready to test this function.
// panic("mem_init: This function is not finished\n");
//////////////////////////////////////////////////////////////////////
// Allocate an array of npages 'struct PageInfo's and store it in 'pages'.
// The kernel uses this array to keep track of physical pages: for
// each physical page, there is a corresponding struct PageInfo in this
// array. 'npages' is the number of physical pages in memory. Use memset
// to initialize all fields of each struct PageInfo to 0.
// Your code goes here:
pages=(structPageInfo*)boot_alloc(sizeof(structPageInfo)*npages);memset(pages,0,sizeof(structPageInfo)*npages);
// The example code here marks all physical pages as free.
// However this is not truly the case. What memory is free?
// 1) Mark physical page 0 as in use.
// This way we preserve the real-mode IDT and BIOS structures
// in case we ever need them. (Currently we don't, but...)
// 2) The rest of base memory, [PGSIZE, npages_basemem * PGSIZE)
// is free.
// 3) Then comes the IO hole [IOPHYSMEM, EXTPHYSMEM), which must
// never be allocated.
// 4) Then extended memory [EXTPHYSMEM, ...).
// Some of it is in use, some is free. Where is the kernel
// in physical memory? Which pages are already in use for
// page tables and other data structures?
//
// Change the code to reflect this.
// NB: DO NOT actually touch the physical memory corresponding to
// free pages!
cprintf("\n>>> Function <%s> called <<<\n",__FUNCTION__);size_ti;for(i=1;i<npages_basemem;i++){pages[i].pp_ref=0;pages[i].pp_link=page_free_list;page_free_list=&pages[i];}char*nextfree=boot_alloc(0);size_tkern_end_page=PGNUM(PADDR(nextfree));cprintf("kern end page:%d\n",kern_end_page);// char *nextfree = (char *)(page_free_list + 1); //boot_alloc(0);
// size_t kern_end_page = PGNUM(PADDR(nextfree));
// cprintf("kern end pages:%d\n", kern_end_page);
for(i=kern_end_page;i<npages;i++){pages[i].pp_ref=0;pages[i].pp_link=page_free_list;page_free_list=&pages[i];}
structPageInfo*page_alloc(intalloc_flags){if(page_free_list){// has free memory
structPageInfo*ret=page_free_list;page_free_list=page_free_list->pp_link;ret->pp_link=NULL;if(alloc_flags&ALLOC_ZERO)memset(page2kva(ret),0,PGSIZE);// page2kna() takes physical address and returns virtual address
returnret;}else{// out of free memory
returnNULL;}}
page_free()
简单的指针使用,将其添加到链表即可,这里的 Hint 内判断的 NULL 需要与 page_alloc 搭配食用。
1
2
3
4
5
6
7
8
9
10
11
voidpage_free(structPageInfo*pp){// Fill this function in
// Hint: You may want to panic if pp->pp_ref is nonzero or
// pp->pp_link is not NULL.
if(pp->pp_ref!=0||pp->pp_link!=NULL)_panic(__FILE__,0,"page_free called with invalid PageInfo %x",pp);pp->pp_link=page_free_list;page_free_list=pp;}
$ make qemu-nox
+ cc kern/pmap.c
+ ld obj/kern/kernel
ld: warning: section `.bss' type changed to PROGBITS
+ mk obj/kern/kernel.img
***
*** Use Ctrl-a x to exit qemu
***
qemu-system-i386 -nographic -drive file=obj/kern/kernel.img,index=0,media=disk,format=raw -serial mon:stdio -gdb
tcp::26000 -D qemu.log
6828 decimal is octal!
Physical memory: 131072K available, base = 640K, extended = 130432K
>>>Function <boot_alloc> called.<<<
boot_alloc memory at <f0117000>
Next free memory at <f0118000>
>>>Function <boot_alloc> called.<<<
boot_alloc memory at <f0118000>
Next free memory at <f0158000>
>>> Function <page_init> called <<<
>>>Function <boot_alloc> called.<<<
nextfree = 0xf0158000kern end page:344
>>> Function <check_page_free_list> called <<<
>>>Function <boot_alloc> called.<<<
check_page_free_list() succeeded!
>>> Function <check_page_alloc> called <<<
check_page_alloc() succeeded!
>>> Function <check_page> called <<<
kernel panic at kern/pmap.c:726: assertion failed: page_insert(kern_pgdir, pp1, 0x0, PTE_W) < 0
Welcome to the JOS kernel monitor!
Type 'help'for a list of commands.
K> QEMU: Terminated