[知其然不知其所以然-9] linux e820/efi memory map是如何初始化的

原创 2015年11月17日 21:15:48

作为内核的内存布局来源,BIOS提供了两套内存布局信息,第一个是legacy启动时提供的e820 memory map,另一个是

efi启动时提供的efi memory map。

在继续之前,我们需要知道,x86启动的顺序是,BIOS,grub,real mode,protect mode

其中,real mode是进入内核前的最后一步,在这个模式下,会根据系统是legacy还是efi启动,

获取到不同的memory map信息。


首先对于legacy模式,有可能是grub,也可能是real mode代码,根据BIOS提供的接口,获取

到内存信息,保存到boot_params结构体。(见Zero-page.txt)

real mode获取内存布局的代码在:

arch\x86\boot/memory.c的detect_memory_e820函数,用BIOS提供的int service,循环执行

intcall(0x15, &ireg, &oreg);,获取所有的e820 map信息,保存到boot_params.e820_map。


对于efi启动方式,realmode下,则可能是arch/x86/boot/compressed/eboot.c里,

exit_boot时,调用efi提供的system table->get_memory_map,获取到内存布局信息,

再赋值给boot_params.efi_info。


进入protect模式后,

void __init setup_arch(char **cmdline_p)
{
        setup_memory_map();
	if (efi_enabled(EFI_BOOT))
		efi_init();

}


有了boot_params后,相关的内存布局初始化setup_memory_map:

该函数通过default_machine_specific_memory_setup,

先在sanitize_e820_map函数里,把boot_params.e820_map去重排序,再通过

append_e820_map加到全局变量数据e820_map里。接着e820_print_map

会打印这个e820 map的内存布局,也就是我们看到的:

[    0.000000] e820: BIOS-provided physical RAM map:
[    0.000000] BIOS-e820: [mem 0x0000000000000000-0x0000000000057fff] usable
[    0.000000] BIOS-e820: [mem 0x0000000000058000-0x0000000000058fff] reserved
[    0.000000] BIOS-e820: [mem 0x0000000000059000-0x000000000009dfff] usable

注意,以上只对legacy有效,因为他检查的是e820_map,对于efi模式,e820_map是空指针。

再看efi内存布局初始化,还是在setup_arch里:

	if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
		     EFI32_LOADER_SIGNATURE, 4)) {
		set_bit(EFI_BOOT, &efi.flags);
	} else if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
		     EFI64_LOADER_SIGNATURE, 4)) {
		set_bit(EFI_BOOT, &efi.flags);
		set_bit(EFI_64BIT, &efi.flags);
	}

	if (efi_enabled(EFI_BOOT))
		efi_memblock_x86_reserve_range();

	if (efi_enabled(EFI_BOOT))
		efi_init();
如果boot_params里有efi标志,那么就根据boot_params.efi_memmap获取efi的分区信息,

最后,还是通过e820_add_region加入到e820 table里去。具体流程是:

efi_init -> efi_memmap_init -> do_add_efi_memmap -> e820_add_region


To be more specific, I found a hibernation error which complains of:



A very good summary of efi linux at:

https://lwn.net/Articles/632528/

uboot下init_sequence_r函数集

common/board_r.c /*  * Over time we hope to remove these functions with code fragments and  * stub f...
  • sunlei0625
  • sunlei0625
  • 2017年03月16日 08:28
  • 447

ACPI之 系统地址映射接口

目前有三种方法将内存映射告诉OSPM, 1 . 通过 BIOS INT 15. 2. UEFI 通过GetMemoryMap()  boot service 告诉OS loader, 然后OS loa...
  • robinsongsog
  • robinsongsog
  • 2015年06月18日 12:14
  • 1773

e820与kernel物理内存映射

http://deltamaster.is-programmer.com/posts/37297.html 我们都对操作系统如何管理内存有一定的了解,然而,在操作系统开始管理内存之前,首先要获取...
  • hshl1214
  • hshl1214
  • 2013年05月19日 08:59
  • 1147

e820简介

本文系转载,原文地址:http://wangcong.org/blog/?p=320,其中附录部分为本人所加...    e820是和BIOS的一个中断相关的,具体说是int 0x15。之所以叫e82...
  • gxfan
  • gxfan
  • 2008年09月22日 15:54
  • 11629

Memory Map(Linux 存储映射IO)

本文主要总结自UNIX环境高级编程以及RedHat6.5系统man函数 存储映射IO函数说明 mmap#include void *mmap(void *addr,//指定映射区的起始地址。通常设置...
  • a931040
  • a931040
  • 2016年07月19日 14:40
  • 2106

从硬件获得内存布局--e820

内核如何通过e820获得内存布局
  • RichardYSteven
  • RichardYSteven
  • 2017年04月05日 21:50
  • 1699

Linux页表机制初始化

Linux启动并建立一套完整的页表机制要经过以下几个步骤: 1.临时内核页表的初始化(setup_32.s) 2.启动分页机制(head_32.s) 3.建立低端内存和高端内存固定映射区的页表(...
  • vanbreaker
  • vanbreaker
  • 2012年05月09日 17:18
  • 10538

内核sanitize_e820_map函数详解(征服内存管理模块的起点)

 原理:bios探测到的内存段信息可能是以下的情况,内核需要重新整理内存段信息:*        Sample memory map (w/overlaps):*           ____22__...
  • YUAN1125
  • YUAN1125
  • 2011年01月10日 18:53
  • 1628

深入理解linux内核架构(内存管理)

1:在内核使用高端内存页之前,必须使用下文讨论的kmap和kunmap函数将其映射到内存虚拟地址空间中。 2:UMA计算机(一致内存访问,uniform memory access)将可用内存以连续方...
  • xueli1991
  • xueli1991
  • 2017年02月20日 15:43
  • 1212

详解神秘Linux内核

本章要先浏览一下内核发出的启动信息,然后再逐个讲解一些有意思的点。 2.1 启动过程 图2-1显示了基于x86计算机Linux系统的启动顺序。第一步是BIOS从启动设备中导入主引导记录(MBR),...
  • fivedoumi
  • fivedoumi
  • 2012年04月28日 20:12
  • 89195
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[知其然不知其所以然-9] linux e820/efi memory map是如何初始化的
举报原因:
原因补充:

(最多只允许输入30个字)