x86_64: split e820 map at 640 KB

Don't create a single e820 memory map entry that spans the legacy low
memory area (0-640K) and the beyond-1MB area, since this confuses some
guest kernels that expect the traditional PC layout and ignore any
regions with a base address below 1 MB.

BUG=b:354053941

Change-Id: I5533ada9cfb69da895b5f0eaa685de9af4693717
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/5747612
Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-by: Dmitry Torokhov <dtor@chromium.org>
This commit is contained in:
Daniel Verkamp 2024-07-29 16:04:46 -07:00 committed by crosvm LUCI
parent 20eee9bace
commit 4664e7bb24

View file

@ -339,6 +339,7 @@ const GB: u64 = 1 << 30;
pub const BOOT_STACK_POINTER: u64 = 0x8000;
const START_OF_RAM_32BITS: u64 = 0;
const FIRST_ADDR_PAST_20BITS: u64 = 1 << 20;
const FIRST_ADDR_PAST_32BITS: u64 = 1 << 32;
// Linux (with 4-level paging) has a physical memory limit of 46 bits (64 TiB).
const HIGH_MMIO_MAX_END: u64 = (1u64 << 46) - 1;
@ -486,17 +487,26 @@ fn configure_system(
params.ext_ramdisk_size = (initrd_size as u64 >> 32) as u32;
}
// Some guest kernels expect a typical PC memory layout where the region between 640 KB and 1 MB
// is reserved for device memory/ROMs and get confused if there is a RAM region spanning this
// area, so we provide the traditional 640 KB low memory and 1 MB+ high memory regions.
let ram_below_1m_end = 640 * 1024;
let ram_below_1m = AddressRange {
start: START_OF_RAM_32BITS,
end: ram_below_1m_end - 1,
};
// GuestMemory::end_addr() returns the first address past the end, so subtract 1 to get the
// inclusive end.
let guest_mem_end = guest_mem.end_addr().offset() - 1;
let ram_below_4g = AddressRange {
start: START_OF_RAM_32BITS,
start: FIRST_ADDR_PAST_20BITS,
end: guest_mem_end.min(read_pci_mmio_before_32bit().start - 1),
};
let ram_above_4g = AddressRange {
start: FIRST_ADDR_PAST_32BITS,
end: guest_mem_end,
};
add_e820_entry(&mut params, ram_below_1m, E820Type::Ram)?;
add_e820_entry(&mut params, ram_below_4g, E820Type::Ram)?;
if !ram_above_4g.is_empty() {
add_e820_entry(&mut params, ram_above_4g, E820Type::Ram)?