这是MIPS虚拟映射布局图,在接下来的实验中,我们需要特别注意的地址分别是kuseg和kseg0区,首先列出这两个区域的意义。
MIPS虚存映射布局
32位的MIPS CPU最大寻址空间为4GB(2^32字节),这4GB虚存空间被划分为四个部分:
kuseg (TLB-mapped cacheable user space, 0x00000000 - 0x7fffffff): 这一段是用户模式下可用的地址,大小为2G,也就是MIPS约定的用户内存空间。需要通过MMU进行虚拟地址到物理 地址的转换。
kseg0 (direct-mapped cached kernel space, 0x80000000 - 0x9fffffff): 这一段是内核地址,其内存虚存地址到物理内存地址的映射转换不通过MMU,使用时只需要将地址的最高位清零 (& 0x7fffffff), 这些地址就被转换为物理地址。也就是说,这段逻辑地址被连续地映射到物理内存的低端512M空间。对这段地址 的存取都会通过高速缓存(cached)。通常在没有MMU的系统中,这段空间用于存放大多数程序和数据。对于有 MMU 的系统,操作系统的内核会存放在这个区域。
kuseg中有三个大小为PDMAP(4MB)的区域,分别从0x7f400000开始是ENVS,PAGES和User VPT。需要注意的是PAGES和User VPT的关系:User VPT中存放了1024个页表,由于自映射的关系,这个页表里又包括了页目录的页表,每一个页表中又有1024个页表项。PAGES存放了48个页表,这48个页表映射的内容是16*1024个物理页框的结构体(struct Page)的物理内存。在lab2实验中,我们只用了boot_map_segment函数将PAGES的内容进行了映射,并没有操作User VPT的空间。
第一幅图将是我们理解整个mm/pmap.c的核心,接下来将按照init/init.c中的顺序进行逐一解释每个函数的细节和整体的启动布局。
1 //这是init/init.c里的函数调用顺序
2 mips_detect_memory();
3 mips_vm_init();
4 page_init();
一、mips_detect_memory()
1.代码块
1 void mips_detect_memory()
2 {
3 //in bytes
4 basemem = 64 * 1024 * 1024;//物理内存的大小为64MB-->26位
5 npage = 16 * 1024;//物理页框的个数
6 maxpa = basemem;//最大的物理地址
7 extmem = 0;//延申的空间
8 printf("Physical memory: %dK available, ", (int)(maxpa / 1024));
9 printf("base = %dK, extended = %dK\n", (int)(basemem / 1024),
10 (int)(extmem / 1024));
11 }
2.初始化一些内存相关的参数,意义写在注释里,不赘述。
二、mips_vm_init()
1.代码块
1 void mips_vm_init()
2 {
3 extern char end[];
4 extern int mCONTEXT;
5 extern struct Env *envs;
6
7 Pde *pgdir;
8 u_int n;
9
10 /* Step 1 */
11 pgdir = alloc(BY2PG, BY2PG, 1);
12 printf("to memory %x for struct page directory.\n", freemem);
13 mCONTEXT = (int)pgdir;//mCONTEXT是虚拟地址
14
15 boot_pgdir = pgdir;
16
17 /* Step 2*/
18 pages = (struct Page *)alloc(npage * sizeof(struct Page), BY2PG, 1);
19 printf("to memory %x for struct Pages.\n", freemem);
20
21 n = ROUND(npage * sizeof(struct Page), BY2PG);
22
23 boot_map_segment(pgdir, UPAGES, n, PADDR(pages), PTE_R);
24
25 /* Step 3*/
26 envs = (struct Env *)alloc(NENV * sizeof(struct Env), BY2PG, 1);
27 n = ROUND(NENV * sizeof(struct Env), BY2PG);
28 boot_map_segment(pgdir, UENVS, n, PADDR(envs), PTE_R);
29
30 printf("pmap.c:\t mips vm init success\n");
31 }
来源:oschina
链接:https://my.oschina.net/u/4358626/blog/3585409