Chinaunix首页 | 论坛 | 博客
  • 博客访问: 450864
  • 博文数量: 150
  • 博客积分: 2706
  • 博客等级: 少校
  • 技术积分: 1200
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-09 11:41
文章分类

全部博文(150)

文章存档

2012年(7)

2011年(6)

2010年(68)

2009年(69)

我的朋友

分类: LINUX

2009-12-06 21:19:59

Q:

  正在对照着看陈老师翻译的ULK2和Understanding The Linux Virtual Memory Manager(以下简称书2)两本书,现在有了如下的疑问:

1、arch/i386/kernel/head.S文件中,启动代码在启用分页单元之前,首先要建立pg0和pg1两个临时内核页表来映射8MB的物理地址,请问这8MB的物理地址究竟是0-8MB(ULK2中的说法)还是1-9MB(书2中的说法)?
个人比较倾向于后面一种说法,因为内核是被加载到内存的1MB开始处的,第1个MB的内存某些地址是保留给BIOS传递参数用的。

2、ULK2中提到了swapper_pg_dir中的第0和768项、第1和769项的地址字段中填充的分别是pg0和pg1的物理地址,我在arch/i386/kernel/head.S文件中找到了如下的代码
380 .org 0x1000
381 ENTRY(swapper_pg_dir)
382         .long 0x00102007
383         .long 0x00103007
384         .fill BOOT_USER_PGD_PTRS-2,4,0
385         /* default: 766 entries */
386         .long 0x00102007
387         .long 0x00103007
388         /* default: 254 entries */
389         .fill BOOT_KERNEL_PGD_PTRS-2,4,0
请问这段代码就达到了上面所说的目的吗?

3、临时内核页表pg0和pg1中的内容又是什么呢?

最后给出我看的Linux 2.4.20的源代码中的arch/i386/kernel/head.S文件链接:


请知道答案的大侠指点一下,谢谢!
 
A:
请看 head.S 中这段代码:

/*
* Initialize page tables
*/
      movl $pg0-__PAGE_OFFSET,%edi /* initialize page tables */
      movl $007,%eax              /* "007" doesn't mean with right to kill, but
                              PRESENT+RW+USER */
2:       stosl
      add $0x1000,%eax
      cmp $empty_zero_page-__PAGE_OFFSET,%edi
      jne 2b
 
在做页表了:从pg0~empty_zero_page来8k来做映射c0000000~c0000000+8m的虚拟空间到物理空间
0~8m,内核解压后+初始化到还没建立完整页目录页表前要用的ram是小于7m的,所以现在建个8m的
页表就行了。
/*
页表项是这样的一个32位结构:
31 12 11 9 8 7 6 5 4 3 2 1 0
| 物理页基地址| |...........|u/s|r/w|p 所以007是指基地址为0最后3为置位。
通过循环下边4条语句,把一个管理8m内存的页表给建起来了。 结果为:
页表项物理地址 页表项的值 对应的物理空间
0x102000 0x007 0~4k
0x102004 0x1007 8~16k
.
.
.
0x104000 0x2000007 8m-4k~8m
*/
2: stosl
add $0x1000,%eax
cmp $empty_zero_page-__PAGE_OFFSET,%edi /*empty_zero_page-__PAGE_OFFSET=0x104000*/
jne 2b //如果还没到empty_zero_page那个物理地址,就跳回2继续stosl,add了
[引用网络上的一段解释:By default, the linux kernel image(or vmlinux elf file) will begin its TEXT starting at 0xC0100000(The 3G edege). This can be found from makfile and link script-vmlinux.lnk.

Corresponding the above setting, PAGE_OFFSET is also set with the value of 0xC0000000.

Now, let's go back to the pg0, which is the (temporary) **first** page table, which will cover first 4M virtual<-->physical memory. (1024x4K page size). Note that kernel 2.2 only use pg0, whereas kernel 2.4 alsu use pg1 to cover another 4M. In other words, kernel 2.4 cover 8M when system initialized and before the paging_init get executed.

From head.S, we can find: both swapper_page_dir , pg0 and pg1 data structurre(an array actually) is **hard coded** at ox1000,0x2000 and 0x3000, respectively.

At this point, we may use to figure out your question.

After compiled and linked, what the addresses of swapper_page_dir, pg0 and pg1 symbol? From the map file, we can easily find these below conclusions:

swapper_page_dir: 0xC0101000
pg0: 0xC0102000
pg1:0xC0103000.
//The above values are determined by linker scripts and the compiler

Now, you tell me what the value of $pg0-PAGE_OFFSET....:-)


Given that the kernel image will be loaded at **physical address of 1M-0x100000. Hence, we understand that $pg0-PAGE_OFFSET is the value of the physical address of the pg0 pointer.
]

我们知道,内核 image 的起始物理地址是 0x100000,而pg0 相对与 kernel image 的地址是 0x2000, pg1 是 0x3000, empty_zero_page 是 0x4000

这段代码要把 pg0 至 empty_zero_page 之间的共 8K 内存初始化。
初始化后,这 2048 项的内容是:
0x0007, 0x1007, 0x2007, 0x3007 .......

取这些 32 地址的高20位,将低12位设置为0,就得到了物理页面的其实地址,因此,pg0, pg1 映射的是 前8M的物理页面。
这里的低 3 bit 为 111,表示 PRESENT+RW+USER


再看 swapper_pg_dir 的第 0 项和第1项,分别是 0x00102007 和 0x00103007,其高 20 bit 正是指向 pg0 和 pg1的起始地址,至于低 3  bit 为 111,同样表示 PRESENT+RW+USER



请看附件我画的一张物理内存布局图

 
 

阅读(1415) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~