实模式下,小于1M空间,包含了BIOS

EBDA(Extened BIOS Data Area),用来存放grub获取到的系统信息,比如内存信息等,grub把这些信息存放在EBDA区域,然后跳转到内核后,内核会从EBDA中获取启动的信息,在Linux内核中被称之为boot_params。

实模式下的地址空间布局

Untitled

Linux boot protocol 基本上依赖EBDA区域

Untitled

保护模式下的内核代码放在0x100000、也就是1M处,1M以下的空间不能使用,0xA0000~0xFFFFF 之间是保留区域(Video Memor、ROM),Linux的boot params可以放在0x10000(被称之为zero page) 这部分是可以被使用的空间,一直到0xA0000为止(这个部分区域,实模式下的内核代码也会使用,所以需要规划好)。 kernel cmdline可以放在0x20000处。最后把boot params的地址传递给rsi寄存器,作为内核的入口的参数,内核通过这个参数就知道了boot params的位置,然后再从boot params中获取到kernel cmdline的位置。

  regs.rflags = 2;
  regs.rip = 0x100000, regs.rsi = 0x10000;
  if (ioctl(v->vcpu_fd, KVM_SET_REGS, &regs) < 0)
      return throw_err("Failed to set registers");

Crosvm x86-64 guest memory layout

Untitled

// 128M预留给了LAPIC、 IOAPIC等
// Reserved memory for nand_bios/LAPIC/IOAPIC/HPET/.....
const RESERVED_MEM_SIZE: u64 = 0x800_0000;

// Make sure it align to 256MB for MTRR convenient
const MEM_32BIT_GAP_SIZE: u64 = 768 * MB;

Cloud-hypervisor

// ** Low RAM (start: 0, length: 640KiB) **
pub const LOW_RAM_START: GuestAddress = GuestAddress(0x0);

// ** EBDA reserved area (start: 640KiB, length: 384KiB) **
pub const EBDA_START: GuestAddress = GuestAddress(0xa0000);

// MPTABLE, describing VCPUS.
pub const MPTABLE_START: GuestAddress = GuestAddress(0x9fc00);

/// The 'zero page', a.k.a linux kernel bootparams.
pub const ZERO_PAGE_START: GuestAddress = GuestAddress(0x7000);
pub const CMDLINE_START: GuestAddress = GuestAddress(0x20000);
/// Kernel command line start address maximum size.
pub const CMDLINE_MAX_SIZE: usize = 0x10000;
pub const BOOT_STACK_POINTER: u64 = 0x8000;

// ** High RAM (start: 1MiB, length: 3071MiB) **
pub const HIGH_RAM_START: GuestAddress = GuestAddress(0x100000);