xv6 lab2 内存管理

  • 学习xv6 lab2 内存管理

1.Setup of paging
    当kernel开启分页机制之后,kernel code and data in RAM 前4M的物理地址就会映射到虚拟地址,即0x00000000 to 0x003fffff映射到0xf0000000 to 0xf03fffff 。那么如果访问0xf0400000会出现什么情况?

 42 .globl entry
 43 entry:                                                                                                                      
 44     movw    $0x1234,0x472           # warm boot
 54
 55     # Load the physical address of entry_pgdir into cr3.  entry_pgdir
 56     # is defined in entrypgdir.c.
 57     movl    $(RELOC(entry_pgdir)), %eax
 58     movl    %eax, %cr3
 59     # Turn on paging.
 60     movl    %cr0, %eax
 61     orl $(CR0_PE|CR0_PG|CR0_WP), %eax
 62    movl    %eax, %cr0

   未开启分页机制前,查看地址0xf0400000:

(gdb)b *0x100015
(gdb)c
(gdb) x/1b 0xf0400000 
0xf0400000:     0x00

   执行si指令到0x100025 mov %eax,%cr0 ,即开启分页机制,再次查看该地址:

(gdb) x/1b 0xf0400000
0xf0400000:     Cannot access memory at address 0xf0400000

2.Physical Page Management
   首先区分物理内存和虚拟内存,分布区如下所示:
   物理内存分布图:

+------------------+  <- 0xFFFFFFFF (4GB)
|      32-bit      |
|  memory mapped   |
|     devices      |
|                  |
/\/\/\/\/\/\/\/\/\/\

/\/\/\/\/\/\/\/\/\/\
|                  |
|      Unused      |
|                  |
+------------------+  <- depends on amount of RAM
|                  |
|                  |
| Extended Memory  |
|------------------|
|       kernnel    |
+------------------+  <- 0x00100000 (1MB)
|     BIOS ROM     |
+------------------+  <- 0x000F0000 (960KB)
|  16-bit devices, |
|  expansion ROMs  |
+------------------+  <- 0x000C0000 (768KB)
|   VGA Display    |
+------------------+  <- 0x000A0000 (640KB)
|                  |
|    Low Memory    |
|------------------|  <-0x00010000 (elf herader here!)
|------------------|  <-0x00007c00   (boot loader here!)
|  bootmain stack  |
+------------------+  <- 0x00000000

   虚拟内存分布图:
在这里插入图片描述
2.1.Exercise 1
  实验之前首先介绍gdb调试kernel如何设置断点:
  进入kernel之前代码执行地址都是物理地址,所以设置断点也是使用物理地址,在执行到下面指令的时候开启虚拟地址寻址,此时设置断点必须使用虚拟地址。

  obj/kern/kernel.asm:
  42     mov $relocated, %eax
  43 f0100028:   b8 2f 00 10 f0          mov    $0xf010002f,%eax
  44     jmp *%eax
  45 f010002d:   ff e0                   jmp    *%eax

例如:

The target architecture is assumed to be i8086
[f000:fff0]    0xffff0:	ljmp   $0xf000,$0xe05b
0x0000fff0 in ?? ()
+ symbol-file obj/kern/kernel
(gdb) b *0x10002d
Breakpoint 1 at 0x10002d
(gdb) c
Continuing.
The target architecture is assumed to be i386
=> 0x10002d:	jmp    *%eax

Breakpoint 1, 0x0010002d in ?? ()
(gdb) b *0xf0100929          #page_init address
Breakpoint 2 at 0xf0100929: file kern/pmap.c, line 245.
(gdb) c
Continuing.
=> 0xf0100929 <page_init>:	push   %ebp

Breakpoint 2, page_init () at kern/pmap.c:245
245	{

介绍boot_alloc实现流程:

kern/init.c:
  i386_init->mem_init->boot_alloc

  首先分析变量extern char end[] in boot_alloc function
  In the linker script we see: PROVIDE(end = .); right after the .bss section. So this is where the linker placed the symbol represented by end.

 kern/kernel.ld:
 52     .bss : {
 53         *(.bss)
 54     }
 55 
 56     PROVIDE(end = .);
 57 
 58     /DISCARD/ : {
 59         *(.eh_frame .note.GNU-stack)
 60     }
 61 }                                                                                                    

gdb 调试查看end:

(gdb) b *0x10002d
(gdb) si
(gdb) x/x &nextfree
0xf011b7d4 <nextfree>:  0x00000000
(gdb) x/x &end
0xf011bbf0:     0x00000000

  如上所示:指针变量nextfree地址为0xf011b7d4, 变量end地址为0xf011bbf0,对应查看 obj/kern/kernel.asm第2553行,value of kernel.asm to confirm:

2550         extern char end[];
2551         nextfree = ROUNDUP((char *) end, PGSIZE);
2552 f01014e4:   c7 45 f4 00 10 00 00    movl   $0x1000,-0xc(%ebp)
2553 f01014eb:   b8 f0 bb 11 f0          mov    $0xf011bbf0,%eax  

  Let’s verify the value of 0xf011bbf0 from the executable itself:

jos/lab2$ objdump -h obj/kern/kernel | egrep 'Idx|\.data|\.bss'
Idx Name          Size      VMA       LMA       File off  Algn
  4 .data         0000a588  f0111000  00111000  00012000  2**12
  5 .bss          00000650  f011b5a0  0011b5a0  0001c588  2**5
jos/lab2$ python -c 'print(hex(0xf011b5a0+0x00000650))'
0xf011bbf0

  如上所示,end地址0xf011bbf0正好位于.bss段地址末尾。通过执行si命令到分配内存成功时,如下所示:

汇编指令执行到这时,查看nextfree:
 nextfree = ROUNDUP((char *) end, PGSIZE);
 f010150f:   a3 d4 b7 11 f0          mov    %eax,0xf011b7d4
(gdb) x/x &nextfree
0xf011b7d4 <nextfree>:  0xf011c000

  Addresses that are lower than nextfree are considered allocated, and addresses equal or above nextfree (up to 0xf03fffff) are considered unallocated. As a consequence, nextfree points to the first free address.It is also worth mentioning that the addresses of nextfree and result must be divisible by 4096 (page size). Thus, the first address returned by this function is 0xf011c000).

  An array of npages实现流程:

  148     //
  149     // Allocate an array of npages 'struct PageInfo's and store it in 'pages'.
  150     // The kernel uses this array to keep track of physical pages: for
  151     // each physical page, there is a corresponding struct PageInfo in this
  152     // array.  'npages' is the number of physical pages in memory.  Use memset
  153     // to initialize all fields of each struct PageInfo to 0.
  154     // Your code goes here:
  155     pages = (struct PageInfo *) boot_alloc(npages * sizeof(struct PageInfo));                                             
  156     uintptr_t pages_region_sz = (uintptr_t)boot_alloc(0) - (uintptr_t)pages;
  157     memset(pages, 0, pages_region_sz);

  关于pages_region_sz的理解:
  通过gdb调试:pages_region_sz = 0xf0155000 - 0xf0115000 = 0x4000 = 4页。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值