实模式下,小于1M空间,包含了BIOS
EBDA(Extened BIOS Data Area),用来存放grub获取到的系统信息,比如内存信息等,grub把这些信息存放在EBDA区域,然后跳转到内核后,内核会从EBDA中获取启动的信息,在Linux内核中被称之为boot_params。
实模式下的地址空间布局
Linux boot protocol 基本上依赖EBDA区域
保护模式下的内核代码放在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, ®s) < 0)
return throw_err("Failed to set registers");
// 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;
// ** 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);