Notes on Memory Map Detection in the Kernel
The kernel needs to know the system memory map to initialize its memory management subsystem at early boot. The memory map defines the physical memory layout, which specifies how much memory is available on the system and which parts of the physical memory are reserved for memory-mapped I/O or other special purposes. The kernel uses the memory map to setup its internal memory management data structures in regions of the memory that are safe to use.
System memory is typically initialized by the firmware, which has most information about hardware in general. The firmware therefore knows the system memory map. The kernel has two methods for obtaining the memory map: the kernel can query the firmware for a memory map or the kernel can ask the boot loader to provide it. Both methods are used by kernels, usually depending on which machine architecture they're running on.
E820 Memory Map
On x86, memory detection using firmware services is typically done using the
E820 INT15h BIOS function that is supported by all modern PCs. The function returns a memory map that describes the different physical memory regions in the system. The kernel is free to use all memory regions marked as available, as long as it remembers to not reuse the memory allocated by firmware and the kernel image. It is typically safe to just ignore all memory below 1 MiB mark and the memory area used by the kernel image.
E820 INT15h function is a robust method for memory detection and kernels like Linux and Windows use it. However, the main disadvantage of
E820 INT15h method is that it requires a BIOS call, which is tricky when the CPU is in 64-bit mode. Kernels therefore usually query for the
E820 INT15h early in the boot process when the CPU is still in real mode and store the information for further processing when the CPU is in 64-bit mode.
System Management BIOS (SMBIOS) is a standard that provides a mechanism for the OS to query information about hardware resources. The BIOS stores a SMBIOS table in the system memory that the OS needs to probe and parse. In SMBIOS data structures, the memory map is defined in the Memory Array Mapped Address structure.
Unified Extensible Firmware Interface (UEFI) is a modern replacement for BIOS. In UEFI, the memory map can be obtained using the
GetMemoryMap() UEFI boot service.
Multiboot specification defines an interface between the bootloader and the kernel. The specification defines a format for providing memory map information to the kernel. In Multiboot 1 format, the memory map is defined in the
mmap_* fields of the Multiboot information data structure. In Multiboot 2 format, the memory map is defined in the Memory Map section. The popular GNU GRUB bootloader, for example, supports the Multiboot specification.
Flattened Device Tree (FDT) is a binary format that describes hardware resources that are not self-enumerated. The bootloader copies the FDT blob into system memory and passes the kernel a memory address where the blob can be located in. In FDT, the memory map is defined in the
/memory node of the device tree.
QEMU has an built-in bootloader that supports FDT on 32-bit and 64-bit ARM architecture. The bootloader can either load a DTB blob or construct one. See the
load_dtb() function in the
hw/arm/boot.c file for details.
The kernel can either query the firmware or ask the bootloader to provide a memory map. There are multiple specifications for both of the methods on different machine architectures.