Skip to content

Commit

Permalink
Fix: Mark ramdisk frames as used in memory map
Browse files Browse the repository at this point in the history
  • Loading branch information
phil-opp committed Dec 28, 2023
1 parent 1b84c46 commit 6b23732
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 3 deletions.
47 changes: 46 additions & 1 deletion common/src/legacy_memory_region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,12 @@ where
regions: &mut [MaybeUninit<MemoryRegion>],
kernel_slice_start: PhysAddr,
kernel_slice_len: u64,
ramdisk_slice_start: Option<PhysAddr>,
ramdisk_slice_len: u64,
) -> &mut [MemoryRegion] {
let mut next_index = 0;
let kernel_slice_start = kernel_slice_start.as_u64();
let ramdisk_slice_start = ramdisk_slice_start.map(|a| a.as_u64());

for descriptor in self.original {
let mut start = descriptor.start();
Expand Down Expand Up @@ -157,8 +160,9 @@ where
kind,
};

// check if region overlaps with kernel
// check if region overlaps with kernel or ramdisk
let kernel_slice_end = kernel_slice_start + kernel_slice_len;
let ramdisk_slice_end = ramdisk_slice_start.map(|s| s + ramdisk_slice_len);
if region.kind == MemoryRegionKind::Usable
&& kernel_slice_start < region.end
&& kernel_slice_end > region.start
Expand Down Expand Up @@ -198,6 +202,47 @@ where
Self::add_region(before_kernel, regions, &mut next_index);
Self::add_region(kernel, regions, &mut next_index);
Self::add_region(after_kernel, regions, &mut next_index);
} else if region.kind == MemoryRegionKind::Usable
&& ramdisk_slice_start.map(|s| s < region.end).unwrap_or(false)
&& ramdisk_slice_end.map(|e| e > region.start).unwrap_or(false)
{
// region overlaps with ramdisk -> we might need to split it
let ramdisk_slice_start = ramdisk_slice_start.unwrap();
let ramdisk_slice_end = ramdisk_slice_end.unwrap();

// ensure that the ramdisk allocation does not span multiple regions
assert!(
ramdisk_slice_start >= region.start,
"region overlaps with ramdisk, but ramdisk begins before region \
(ramdisk_start: {ramdisk_slice_start:#x}, region_start: {:#x})",
region.start
);
assert!(
ramdisk_slice_end <= region.end,
"region overlaps with ramdisk, but region ends before ramdisk \
(ramdisk_end: {ramdisk_slice_end:#x}, region_end: {:#x})",
region.end,
);

// split the region into three parts
let before_ramdisk = MemoryRegion {
end: ramdisk_slice_start,
..region
};
let ramdisk = MemoryRegion {
start: ramdisk_slice_start,
end: ramdisk_slice_end,
kind: MemoryRegionKind::Bootloader,
};
let after_ramdisk = MemoryRegion {
start: ramdisk_slice_end,
..region
};

// add the three regions (empty regions are ignored in `add_region`)
Self::add_region(before_ramdisk, regions, &mut next_index);
Self::add_region(ramdisk, regions, &mut next_index);
Self::add_region(after_ramdisk, regions, &mut next_index);
} else {
// add the region normally
Self::add_region(region, regions, &mut next_index);
Expand Down
8 changes: 6 additions & 2 deletions common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,14 +293,14 @@ where
None
};
let ramdisk_slice_len = system_info.ramdisk_len;
let ramdisk_slice_start = if let Some(ramdisk_address) = system_info.ramdisk_addr {
let ramdisk_slice_phys_start = system_info.ramdisk_addr.map(PhysAddr::new);
let ramdisk_slice_start = if let Some(physical_address) = ramdisk_slice_phys_start {
let start_page = mapping_addr_page_aligned(
config.mappings.ramdisk_memory,
system_info.ramdisk_len,
&mut used_entries,
"ramdisk start",
);
let physical_address = PhysAddr::new(ramdisk_address);
let ramdisk_physical_start_page: PhysFrame<Size4KiB> =
PhysFrame::containing_address(physical_address);
let ramdisk_page_count = (system_info.ramdisk_len - 1) / Size4KiB::SIZE;
Expand Down Expand Up @@ -404,6 +404,7 @@ where
kernel_slice_len,
kernel_image_offset,

ramdisk_slice_phys_start,
ramdisk_slice_start,
ramdisk_slice_len,
}
Expand Down Expand Up @@ -433,6 +434,7 @@ pub struct Mappings {
pub kernel_slice_len: u64,
/// Relocation offset of the kernel image in virtual memory.
pub kernel_image_offset: VirtAddr,
pub ramdisk_slice_phys_start: Option<PhysAddr>,
pub ramdisk_slice_start: Option<VirtAddr>,
pub ramdisk_slice_len: u64,
}
Expand Down Expand Up @@ -516,6 +518,8 @@ where
memory_regions,
mappings.kernel_slice_start,
mappings.kernel_slice_len,
mappings.ramdisk_slice_phys_start,
mappings.ramdisk_slice_len,
);

log::info!("Create bootinfo");
Expand Down

0 comments on commit 6b23732

Please sign in to comment.