lab2 物理内存管理

物理内存探测

物理内存分布和大小是用bios进行中断调用进行的,而中断调用需要用到bios,bios怎么运用呢?需要在实模式下,也就是bootloader还未加载前使用,BIOS中断获取内存可调用参数为e820h的INT 15h BIOS中断。返回值用di来增长,找到一个个内存的entry,然后用下面结构的缓冲区来保存

struct e820map {
   
                  int nr_map;
                  struct {
   
                                    long long addr;
                                    long long size;
                                    long type;
                  } map[E820MAX];
};

中断返回值

eflags的CF位:若INT 15中断执行成功,则不置位,否则置位;

eax:534D4150h ('SMAP') ;

es:di:指向保存地址范围描述符的缓冲区,此时缓冲区内的数据已由BIOS填写完毕

ebx:下一个地址范围描述符的计数地址

ecx    :返回BIOS往ES:DI处写的地址范围描述符的字节大小

ah:失败时保存出错代码

实现物理内存的探测
先是做准备:

probe_memory:
//对0x8000处的32位单元清零,即给位于0x8000处的
//struct e820map的成员变量nr_map清零
                  movl $0, 0x8000
                  xorl %ebx, %ebx
//表示设置调用INT 15h BIOS中断后,BIOS返回的映射地址描述符的起始地址
                  movw $0x8004, %di

cont:
//设置下一个BIOS返回的映射地址描述符的起始地址
                  addw $20, %di
//递增struct e820map的成员变量nr_map
                  incl 0x8000
//如果INT0x15返回的ebx为零,表示探测结束,否则继续探测
                  cmpl $0, %ebx
                  jnz start_probe
finish_probe:

然后设置中断参数

start_probe:
                  movl $0xE820, %eax // INT 15的中断调用参数
//设置地址范围描述符的大小为20字节,其大小等于struct e820map的成员变量map的大小
                  movl $20, %ecx
//设置edx为534D4150h (即4个ASCII字符“SMAP”),这是一个约定
                  movl $SMAP, %edx
//调用int 0x15中断,要求BIOS返回一个用地址范围描述符表示的内存段信息
                  int $0x15
//如果eflags的CF位为0,则表示还有内存段需要探测
                  jnc cont
//探测有问题,结束探测
                  movw $12345, 0x8000
                  jmp finish_probe
cont:
//设置下一个BIOS返回的映射地址描述符的起始地址
                  addw $20, %di
//递增struct e820map的成员变量nr_map
                  incl 0x8000
//如果INT0x15返回的ebx为零,表示探测结束,否则继续探测
                  cmpl $0, %ebx
                  jnz start_probe
finish_probe:

上面的代码执行完成后,将内存分布情况存储在0x8000,以结构体e820map的方式存储,在bootloader启动ucore后,由page_init函数来完成对机器的总体管理,且依据e820map的mmap进行管理,为0x8000

ucore的各个部分由一些.a和.o文件组成。而ld脚本把这些文件链接起来,这些各个组成部分在文件中的地址和ld脚本有关。而链接脚本主要规定如何把这些组成部分的section给到kernel文件,并且让它输出各个部分的空间地址的布局

/* Simple linker script for the ucore kernel.
   See the GNU ld 'info' manual ("info ld") to learn the syntax. */

OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(kern_entry)
//初始化内核入口
SECTIONS {
   
    /* Load the kernel at this address: "." means the current address */
    . = 0xC0100000;
//在这个地址加载内核
    .text : {
   
        *(.text .stub .text.* .gnu.linkonce.t.*)
    }

    PROVIDE(etext = .)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值