boot_alloc()
要点:a. ROUNDUP()是用来向上对齐的。
b. 此时memory的上限在i386_detect_memory()里根据读取CMOS的信息来得到。
102 if (n > 0) {
103 result = nextfree;
104 nextfree = (char*) (nextfree + n);
105 nextfree = ROUNDUP((char *) nextfree , PGSIZE);
106 } else if (n == 0)
107 result = nextfree;
108 else
109 result = NULL;
112
113 if (nextfree > (char *)(KERNBASE + npages * PGSIZE))
114 panic("Run out of memory, nextfree = 0x%x\n", nextfree);
115
116 return result;
mem_init()
(only up to the call to check_page_free_list(1)
)
在i386_detect_memory()里用CMOS检测内存大小,可参考CMOS文档:
http://web.archive.org/web/20040603005903/http://members.iweb.net.au/~pstorr/pcbook/book5/cmoslist.htm
15h - Base Memory in K, Low Byte 16h Base Memory in K, High Byte The value in 15h-16h should be the same as in 0:413h and that returned by Int 12h. A PC having 640k (280h) of conventional memory will return 80h in byte 15h and 02h in byte 16h. 17h - Extended Memory in K, Low Byte 18h - Extended Memory in K, High Byte (some systems will only accommodate 15 Mb extended or 16 Mb total) Format is the same as in 15h-16h
page_init() {
302 int i;
303 int lower_pgnum = PGNUM(IOPHYSMEM);
304 int upper_pgnum = PGNUM(ROUNDUP((int)boot_alloc(0) - KERNBASE,PGSIZE));
305
306 page_free_list = NULL;
307 for (i = 0; i < npages; i++) {
308 pages[i].pp_ref = 0;
309 if ((i >= lower_pgnum) && (i < upper_pgnum))
310 continue;
311 if (i == 0)
312 continue;
313 ;
314 pages[i].pp_link = page_free_list;
315 page_free_list = &pages[i];
316 }
最后的page_table会如下所示:
0x00117000 0x00000000 0x00000000 0xf0126ff8 0x00000000
0x00117010 0xf0117008 0x00000000 0xf0117010 0x00000000
0x00117020 0xf0117018 0x00000000 0xf0117020 0x00000000
...
0x001174f0 0xf01174e8 0x00000000 0xf01174f0 0x00000000
0x00117500 0x00000000 0x00000000 0x00000000 0x00000000
0x00117510 0x00000000 0x00000000 0x00000000 0x00000000
...
0x00117930 0x00000000 0x00000000 0xf01174f8 0x00000000
0x00117940 0xf0117938 0x00000000 0xf0117940 0x00000000
0x00117950 0xf0117948 0x00000000 0xf0117950 0x00000000
...
0x00126fe0 0xf0126fd8 0x00000000 0xf0126fe0 0x00000000
0x00126ff0 0xf0126fe8 0x00000000 0xf0126ff0 0x00000000
0x00127000 0x97979797 0x97979797 0x97979797 0x97979797
0x00127010 0x97979797 0x97979797 0x97979797 0x97979797
...
0x00127070 0x97979797 0x97979797 0x97979797 0x97979797
0x00127080 0x00000000 0x00000000 0x00000000 0x00000000
page_free_list 初始化指向 0xf0118ff8,所以物理页是从高往低分配。
page_alloc()
page_free()
这两个相对简单,只要注意page_free_list是一个循环链表,处理只剩一个节点的状况就没问题了。
check_page_free_list()
andcheck_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.