Skip to content

Commit 6ca12f0

Browse files
committed
arch/aarch64: use different RAM start addresses
EDK2 expects RAM to start at 0x4000_0000, and a while ago we decided to make this default for both the EFI and non-EFI flavors. The problem with this approach is that, on aarch64, the Linux kernel expects to be loaded at 0x8000_0000, meaning that region needs to be covered by RAM. For large VMs this isn't a problem but for VMs smaller than 1GB, that region gets uncovered. In theory, we could add another region dedicated to the kernel at 0x8000_0000 and let the rest of RAM start at 0x4000_0000, but this has two problems: - We would be using more RAM than what we were configured to. - It's very hard to find out exactly the size of the kernel region. So, instead, let's go back to use two different start addresses, depending on wether we're booting a firmware or a kernel, but let's do it in a cleaner way, so we don't depend on having an independent flavor. Fixes: #460 Signed-off-by: Sergio Lopez <slp@redhat.com>
1 parent eec81cd commit 6ca12f0

File tree

4 files changed

+36
-12
lines changed

4 files changed

+36
-12
lines changed

src/arch/src/aarch64/layout.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,14 @@
4949
//
5050
// Taken from (http://infocenter.arm.com/help/topic/com.arm.doc.den0001c/DEN0001C_principles_of_arm_memory_maps.pdf).
5151

52-
/// Start of RAM on 64 bit ARM.
53-
pub const DRAM_MEM_START: u64 = 0x4000_0000; // 1 GB.
52+
/// Start of RAM on 64 bit ARM when loading an EFI firmware.
53+
pub const DRAM_MEM_START_EFI: u64 = 0x4000_0000; // 1 GB.
54+
/// Start of RAM on 64 bit ARM when loading a kernel.
55+
pub const DRAM_MEM_START_KERNEL: u64 = 0x8000_0000; // 2 GB.
5456
/// The maximum addressable RAM address.
5557
pub const DRAM_MEM_END: u64 = 0x00FF_8000_0000; // 1024 - 2 = 1022 GB.
5658
/// The maximum RAM size.
57-
pub const DRAM_MEM_MAX_SIZE: u64 = DRAM_MEM_END - DRAM_MEM_START;
59+
pub const DRAM_MEM_MAX_SIZE: u64 = DRAM_MEM_END - DRAM_MEM_START_KERNEL;
5860

5961
/// Kernel command line maximum size.
6062
/// As per `arch/arm64/include/uapi/asm/setup.h`.

src/arch/src/aarch64/mod.rs

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ pub use self::macos::*;
1717

1818
use std::fmt::Debug;
1919

20-
use crate::{aarch64::layout::FIRMWARE_START, ArchMemoryInfo};
20+
use crate::{
21+
aarch64::layout::{DRAM_MEM_START_EFI, DRAM_MEM_START_KERNEL, FIRMWARE_START},
22+
ArchMemoryInfo,
23+
};
2124
use vm_memory::{GuestAddress, GuestMemoryMmap};
2225
use vmm_sys_util::align_upwards;
2326

@@ -43,13 +46,23 @@ pub fn arch_memory_regions(
4346
initrd_size: u64,
4447
firmware_size: Option<usize>,
4548
) -> (ArchMemoryInfo, Vec<(GuestAddress, usize)>) {
49+
let ram_start_addr = if firmware_size.is_some() {
50+
DRAM_MEM_START_EFI
51+
} else {
52+
DRAM_MEM_START_KERNEL
53+
};
4654
let page_size: usize = unsafe { libc::sysconf(libc::_SC_PAGESIZE).try_into().unwrap() };
4755
let dram_size = align_upwards!(size, page_size);
48-
let ram_last_addr = layout::DRAM_MEM_START + (dram_size as u64);
56+
let ram_last_addr = ram_start_addr + (dram_size as u64);
4957
let shm_start_addr = ((ram_last_addr / 0x4000_0000) + 1) * 0x4000_0000;
50-
let fdt_addr = ram_last_addr - layout::FDT_MAX_SIZE as u64;
58+
let fdt_addr = if firmware_size.is_some() {
59+
DRAM_MEM_START_EFI
60+
} else {
61+
ram_last_addr - layout::FDT_MAX_SIZE as u64
62+
};
5163

5264
let info = ArchMemoryInfo {
65+
ram_start_addr,
5366
ram_last_addr,
5467
shm_start_addr,
5568
page_size,
@@ -61,10 +74,10 @@ pub fn arch_memory_regions(
6174
vec![
6275
// Space for loading the firmware
6376
(GuestAddress(0u64), align_upwards!(firmware_size, page_size)),
64-
(GuestAddress(layout::DRAM_MEM_START), dram_size),
77+
(GuestAddress(ram_start_addr), dram_size),
6578
]
6679
} else {
67-
vec![(GuestAddress(layout::DRAM_MEM_START), dram_size)]
80+
vec![(GuestAddress(ram_start_addr), dram_size)]
6881
};
6982

7083
(info, regions)
@@ -100,15 +113,21 @@ mod tests {
100113
fn test_regions_lt_1024gb() {
101114
let (_mem_info, regions) = arch_memory_regions(1usize << 29, 0);
102115
assert_eq!(1, regions.len());
103-
assert_eq!(GuestAddress(super::layout::DRAM_MEM_START), regions[0].0);
116+
assert_eq!(
117+
GuestAddress(super::layout::DRAM_MEM_START_KERNEL),
118+
regions[0].0
119+
);
104120
assert_eq!(1usize << 29, regions[0].1);
105121
}
106122

107123
#[test]
108124
fn test_regions_gt_1024gb() {
109125
let (_mem_info, regions) = arch_memory_regions(1usize << 41, 0);
110126
assert_eq!(1, regions.len());
111-
assert_eq!(GuestAddress(super::layout::DRAM_MEM_START), regions[0].0);
127+
assert_eq!(
128+
GuestAddress(super::layout::DRAM_MEM_START_KERNEL),
129+
regions[0].0
130+
);
112131
assert_eq!(super::layout::DRAM_MEM_MAX_SIZE, regions[0].1 as u64);
113132
}
114133
}

src/arch/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@ pub struct ArchMemoryInfo {
1212
pub ram_below_gap: u64,
1313
#[cfg(target_arch = "x86_64")]
1414
pub ram_above_gap: u64,
15+
#[cfg(target_arch = "aarch64")]
16+
pub ram_start_addr: u64,
1517
pub ram_last_addr: u64,
1618
pub shm_start_addr: u64,
1719
pub page_size: usize,
20+
#[cfg(target_arch = "aarch64")]
1821
pub fdt_addr: u64,
1922
pub initrd_addr: u64,
2023
pub firmware_addr: u64,

src/devices/src/fdt/aarch64.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,10 @@ fn create_memory_node(
176176
_guest_mem: &GuestMemoryMmap,
177177
arch_memory_info: &ArchMemoryInfo,
178178
) -> Result<()> {
179-
let mem_size = arch_memory_info.ram_last_addr - arch::aarch64::layout::DRAM_MEM_START;
179+
let mem_size = arch_memory_info.ram_last_addr - arch_memory_info.ram_start_addr;
180180
// See https://github.com/torvalds/linux/blob/master/Documentation/devicetree/booting-without-of.txt#L960
181181
// for an explanation of this.
182-
let mem_reg_prop = generate_prop64(&[arch::aarch64::layout::DRAM_MEM_START, mem_size]);
182+
let mem_reg_prop = generate_prop64(&[arch_memory_info.ram_start_addr, mem_size]);
183183

184184
let mem_node = fdt.begin_node("memory")?;
185185
fdt.property_string("device_type", "memory")?;

0 commit comments

Comments
 (0)