Skip to content

Instantly share code, notes, and snippets.

@boddumanohar
Created May 29, 2018 04:57
Show Gist options
  • Save boddumanohar/37db9a3a6954f29bcde119ae80b90dd5 to your computer and use it in GitHub Desktop.
Save boddumanohar/37db9a3a6954f29bcde119ae80b90dd5 to your computer and use it in GitHub Desktop.

Notes on Memory Map Detection in the Kernel

Introduction

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.

Firmware Methods

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.

The 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.

SMBIOS

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.

UEFI

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.

Bootloader Methods

Multiboot

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.

Device Tree

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.

Summary

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment