mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-21 08:16:32 +00:00
Heapless memory region initialization
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
0c8200dc7b
commit
51349a3da1
@ -38,7 +38,7 @@ pub(crate) fn init() {
|
|||||||
let mut writer = {
|
let mut writer = {
|
||||||
let framebuffer = boot::framebuffer_arg();
|
let framebuffer = boot::framebuffer_arg();
|
||||||
let mut size = 0;
|
let mut size = 0;
|
||||||
for region in memory_regions() {
|
for region in memory_regions().iter() {
|
||||||
if region.typ() == MemoryRegionType::Framebuffer {
|
if region.typ() == MemoryRegionType::Framebuffer {
|
||||||
size = region.len();
|
size = region.len();
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
pub mod smp;
|
pub mod smp;
|
||||||
|
|
||||||
use alloc::{string::String, vec::Vec};
|
use alloc::string::String;
|
||||||
use core::arch::global_asm;
|
use core::arch::global_asm;
|
||||||
|
|
||||||
use fdt::Fdt;
|
use fdt::Fdt;
|
||||||
@ -13,7 +13,10 @@ use spin::Once;
|
|||||||
use crate::{
|
use crate::{
|
||||||
boot::{
|
boot::{
|
||||||
kcmdline::KCmdlineArg,
|
kcmdline::KCmdlineArg,
|
||||||
memory_region::{non_overlapping_regions_from, MemoryRegion, MemoryRegionType},
|
memory_region::{
|
||||||
|
non_overlapping_regions_from, MemoryRegion, MemoryRegionArray, MemoryRegionType,
|
||||||
|
MAX_REGIONS,
|
||||||
|
},
|
||||||
BootloaderAcpiArg, BootloaderFramebufferArg,
|
BootloaderAcpiArg, BootloaderFramebufferArg,
|
||||||
},
|
},
|
||||||
early_println,
|
early_println,
|
||||||
@ -50,8 +53,8 @@ fn init_acpi_arg(acpi: &'static Once<BootloaderAcpiArg>) {
|
|||||||
|
|
||||||
fn init_framebuffer_info(_framebuffer_arg: &'static Once<BootloaderFramebufferArg>) {}
|
fn init_framebuffer_info(_framebuffer_arg: &'static Once<BootloaderFramebufferArg>) {}
|
||||||
|
|
||||||
fn init_memory_regions(memory_regions: &'static Once<Vec<MemoryRegion>>) {
|
fn init_memory_regions(memory_regions: &'static Once<MemoryRegionArray>) {
|
||||||
let mut regions = Vec::<MemoryRegion>::new();
|
let mut regions = MemoryRegionArray::new();
|
||||||
|
|
||||||
for region in DEVICE_TREE.get().unwrap().memory().regions() {
|
for region in DEVICE_TREE.get().unwrap().memory().regions() {
|
||||||
if region.size.unwrap_or(0) > 0 {
|
if region.size.unwrap_or(0) > 0 {
|
||||||
@ -89,7 +92,7 @@ fn init_memory_regions(memory_regions: &'static Once<Vec<MemoryRegion>>) {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
memory_regions.call_once(|| non_overlapping_regions_from(regions.as_ref()));
|
memory_regions.call_once(|| regions.into_non_overlapping());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_initramfs_range() -> Option<(usize, usize)> {
|
fn parse_initramfs_range() -> Option<(usize, usize)> {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
//! The Linux 64-bit Boot Protocol supporting module.
|
//! The Linux 64-bit Boot Protocol supporting module.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use alloc::{borrow::ToOwned, format, string::String, vec::Vec};
|
use alloc::{borrow::ToOwned, format, string::String};
|
||||||
use core::ffi::CStr;
|
use core::ffi::CStr;
|
||||||
|
|
||||||
use linux_boot_params::{BootParams, E820Type, LINUX_BOOT_HEADER_MAGIC};
|
use linux_boot_params::{BootParams, E820Type, LINUX_BOOT_HEADER_MAGIC};
|
||||||
@ -12,7 +12,7 @@ use spin::Once;
|
|||||||
use crate::{
|
use crate::{
|
||||||
boot::{
|
boot::{
|
||||||
kcmdline::KCmdlineArg,
|
kcmdline::KCmdlineArg,
|
||||||
memory_region::{non_overlapping_regions_from, MemoryRegion, MemoryRegionType},
|
memory_region::{MemoryRegion, MemoryRegionArray, MemoryRegionType},
|
||||||
BootloaderAcpiArg, BootloaderFramebufferArg,
|
BootloaderAcpiArg, BootloaderFramebufferArg,
|
||||||
},
|
},
|
||||||
mm::kspace::{paddr_to_vaddr, LINEAR_MAPPING_BASE_VADDR},
|
mm::kspace::{paddr_to_vaddr, LINEAR_MAPPING_BASE_VADDR},
|
||||||
@ -118,39 +118,45 @@ impl From<E820Type> for MemoryRegionType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_memory_regions(memory_regions: &'static Once<Vec<MemoryRegion>>) {
|
fn init_memory_regions(memory_regions: &'static Once<MemoryRegionArray>) {
|
||||||
let mut regions = Vec::<MemoryRegion>::new();
|
let mut regions = MemoryRegionArray::new();
|
||||||
|
|
||||||
let boot_params = BOOT_PARAMS.get().unwrap();
|
let boot_params = BOOT_PARAMS.get().unwrap();
|
||||||
|
|
||||||
// Add regions from E820.
|
// Add regions from E820.
|
||||||
let num_entries = boot_params.e820_entries as usize;
|
let num_entries = boot_params.e820_entries as usize;
|
||||||
for e820_entry in &boot_params.e820_table[0..num_entries] {
|
for e820_entry in &boot_params.e820_table[0..num_entries] {
|
||||||
regions.push(MemoryRegion::new(
|
regions
|
||||||
|
.push(MemoryRegion::new(
|
||||||
e820_entry.addr as usize,
|
e820_entry.addr as usize,
|
||||||
e820_entry.size as usize,
|
e820_entry.size as usize,
|
||||||
e820_entry.typ.into(),
|
e820_entry.typ.into(),
|
||||||
));
|
))
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the kernel region.
|
// Add the kernel region.
|
||||||
regions.push(MemoryRegion::kernel());
|
regions.push(MemoryRegion::kernel()).unwrap();
|
||||||
|
|
||||||
// Add the initramfs region.
|
// Add the initramfs region.
|
||||||
regions.push(MemoryRegion::new(
|
regions
|
||||||
|
.push(MemoryRegion::new(
|
||||||
boot_params.hdr.ramdisk_image as usize,
|
boot_params.hdr.ramdisk_image as usize,
|
||||||
boot_params.hdr.ramdisk_size as usize,
|
boot_params.hdr.ramdisk_size as usize,
|
||||||
MemoryRegionType::Module,
|
MemoryRegionType::Module,
|
||||||
));
|
))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Add the AP boot code region that will be copied into by the BSP.
|
// Add the AP boot code region that will be copied into by the BSP.
|
||||||
regions.push(MemoryRegion::new(
|
regions
|
||||||
|
.push(MemoryRegion::new(
|
||||||
super::smp::AP_BOOT_START_PA,
|
super::smp::AP_BOOT_START_PA,
|
||||||
super::smp::ap_boot_code_size(),
|
super::smp::ap_boot_code_size(),
|
||||||
MemoryRegionType::Reclaimable,
|
MemoryRegionType::Reclaimable,
|
||||||
));
|
))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
memory_regions.call_once(|| non_overlapping_regions_from(regions.as_ref()));
|
memory_regions.call_once(|| regions.into_non_overlapping());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The entry point of the Rust code portion of Asterinas.
|
/// The entry point of the Rust code portion of Asterinas.
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use alloc::{string::String, vec::Vec};
|
use alloc::string::String;
|
||||||
use core::arch::global_asm;
|
use core::arch::global_asm;
|
||||||
|
|
||||||
use spin::Once;
|
use spin::Once;
|
||||||
@ -8,7 +8,7 @@ use spin::Once;
|
|||||||
use crate::{
|
use crate::{
|
||||||
boot::{
|
boot::{
|
||||||
kcmdline::KCmdlineArg,
|
kcmdline::KCmdlineArg,
|
||||||
memory_region::{non_overlapping_regions_from, MemoryRegion, MemoryRegionType},
|
memory_region::{MemoryRegion, MemoryRegionArray, MemoryRegionType},
|
||||||
BootloaderAcpiArg, BootloaderFramebufferArg,
|
BootloaderAcpiArg, BootloaderFramebufferArg,
|
||||||
},
|
},
|
||||||
mm::{
|
mm::{
|
||||||
@ -103,8 +103,8 @@ fn init_framebuffer_info(framebuffer_arg: &'static Once<BootloaderFramebufferArg
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_memory_regions(memory_regions: &'static Once<Vec<MemoryRegion>>) {
|
fn init_memory_regions(memory_regions: &'static Once<MemoryRegionArray>) {
|
||||||
let mut regions = Vec::<MemoryRegion>::new();
|
let mut regions = MemoryRegionArray::new();
|
||||||
|
|
||||||
let info = MB1_INFO.get().unwrap();
|
let info = MB1_INFO.get().unwrap();
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ fn init_memory_regions(memory_regions: &'static Once<Vec<MemoryRegion>>) {
|
|||||||
entry.length().try_into().unwrap(),
|
entry.length().try_into().unwrap(),
|
||||||
entry.memory_type(),
|
entry.memory_type(),
|
||||||
);
|
);
|
||||||
regions.push(region);
|
regions.push(region).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the framebuffer region.
|
// Add the framebuffer region.
|
||||||
@ -126,14 +126,16 @@ fn init_memory_regions(memory_regions: &'static Once<Vec<MemoryRegion>>) {
|
|||||||
height: info.framebuffer_table.height as usize,
|
height: info.framebuffer_table.height as usize,
|
||||||
bpp: info.framebuffer_table.bpp as usize,
|
bpp: info.framebuffer_table.bpp as usize,
|
||||||
};
|
};
|
||||||
regions.push(MemoryRegion::new(
|
regions
|
||||||
|
.push(MemoryRegion::new(
|
||||||
fb.address,
|
fb.address,
|
||||||
(fb.width * fb.height * fb.bpp + 7) / 8, // round up when divide with 8 (bits/Byte)
|
(fb.width * fb.height * fb.bpp + 7) / 8, // round up when divide with 8 (bits/Byte)
|
||||||
MemoryRegionType::Framebuffer,
|
MemoryRegionType::Framebuffer,
|
||||||
));
|
))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Add the kernel region.
|
// Add the kernel region.
|
||||||
regions.push(MemoryRegion::kernel());
|
regions.push(MemoryRegion::kernel()).unwrap();
|
||||||
|
|
||||||
// Add the initramfs area.
|
// Add the initramfs area.
|
||||||
if info.mods_count != 0 {
|
if info.mods_count != 0 {
|
||||||
@ -145,22 +147,26 @@ fn init_memory_regions(memory_regions: &'static Once<Vec<MemoryRegion>>) {
|
|||||||
(*(paddr_to_vaddr(modules_addr + 4) as *const u32)) as usize,
|
(*(paddr_to_vaddr(modules_addr + 4) as *const u32)) as usize,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
regions.push(MemoryRegion::new(
|
regions
|
||||||
|
.push(MemoryRegion::new(
|
||||||
start,
|
start,
|
||||||
end - start,
|
end - start,
|
||||||
MemoryRegionType::Module,
|
MemoryRegionType::Module,
|
||||||
));
|
))
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the AP boot code region that will be copied into by the BSP.
|
// Add the AP boot code region that will be copied into by the BSP.
|
||||||
regions.push(MemoryRegion::new(
|
regions
|
||||||
|
.push(MemoryRegion::new(
|
||||||
super::smp::AP_BOOT_START_PA,
|
super::smp::AP_BOOT_START_PA,
|
||||||
super::smp::ap_boot_code_size(),
|
super::smp::ap_boot_code_size(),
|
||||||
MemoryRegionType::Reclaimable,
|
MemoryRegionType::Reclaimable,
|
||||||
));
|
))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Initialize with non-overlapping regions.
|
// Initialize with non-overlapping regions.
|
||||||
memory_regions.call_once(move || non_overlapping_regions_from(regions.as_ref()));
|
memory_regions.call_once(move || regions.into_non_overlapping());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Representation of Multiboot Information according to specification.
|
/// Representation of Multiboot Information according to specification.
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use alloc::{
|
use alloc::string::{String, ToString};
|
||||||
string::{String, ToString},
|
|
||||||
vec::Vec,
|
|
||||||
};
|
|
||||||
use core::arch::global_asm;
|
use core::arch::global_asm;
|
||||||
|
|
||||||
use multiboot2::{BootInformation, BootInformationHeader, MemoryAreaType};
|
use multiboot2::{BootInformation, BootInformationHeader, MemoryAreaType};
|
||||||
@ -12,7 +9,7 @@ use spin::Once;
|
|||||||
use crate::{
|
use crate::{
|
||||||
boot::{
|
boot::{
|
||||||
kcmdline::KCmdlineArg,
|
kcmdline::KCmdlineArg,
|
||||||
memory_region::{non_overlapping_regions_from, MemoryRegion, MemoryRegionType},
|
memory_region::{MemoryRegion, MemoryRegionArray, MemoryRegionType},
|
||||||
BootloaderAcpiArg, BootloaderFramebufferArg,
|
BootloaderAcpiArg, BootloaderFramebufferArg,
|
||||||
},
|
},
|
||||||
mm::kspace::paddr_to_vaddr,
|
mm::kspace::paddr_to_vaddr,
|
||||||
@ -99,8 +96,8 @@ impl From<MemoryAreaType> for MemoryRegionType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_memory_regions(memory_regions: &'static Once<Vec<MemoryRegion>>) {
|
fn init_memory_regions(memory_regions: &'static Once<MemoryRegionArray>) {
|
||||||
let mut regions = Vec::<MemoryRegion>::new();
|
let mut regions = MemoryRegionArray::new();
|
||||||
|
|
||||||
let mb2_info = MB2_INFO.get().unwrap();
|
let mb2_info = MB2_INFO.get().unwrap();
|
||||||
|
|
||||||
@ -117,7 +114,7 @@ fn init_memory_regions(memory_regions: &'static Once<Vec<MemoryRegion>>) {
|
|||||||
(end - start).try_into().unwrap(),
|
(end - start).try_into().unwrap(),
|
||||||
area_typ,
|
area_typ,
|
||||||
);
|
);
|
||||||
regions.push(region);
|
regions.push(region).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(Ok(fb_tag)) = mb2_info.framebuffer_tag() {
|
if let Some(Ok(fb_tag)) = mb2_info.framebuffer_tag() {
|
||||||
@ -128,35 +125,41 @@ fn init_memory_regions(memory_regions: &'static Once<Vec<MemoryRegion>>) {
|
|||||||
height: fb_tag.height() as usize,
|
height: fb_tag.height() as usize,
|
||||||
bpp: fb_tag.bpp() as usize,
|
bpp: fb_tag.bpp() as usize,
|
||||||
};
|
};
|
||||||
regions.push(MemoryRegion::new(
|
regions
|
||||||
|
.push(MemoryRegion::new(
|
||||||
fb.address,
|
fb.address,
|
||||||
(fb.width * fb.height * fb.bpp + 7) / 8, // round up when divide with 8 (bits/Byte)
|
(fb.width * fb.height * fb.bpp + 7) / 8, // round up when divide with 8 (bits/Byte)
|
||||||
MemoryRegionType::Framebuffer,
|
MemoryRegionType::Framebuffer,
|
||||||
));
|
))
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the kernel region since Grub does not specify it.
|
// Add the kernel region since Grub does not specify it.
|
||||||
regions.push(MemoryRegion::kernel());
|
regions.push(MemoryRegion::kernel()).unwrap();
|
||||||
|
|
||||||
// Add the boot module region since Grub does not specify it.
|
// Add the boot module region since Grub does not specify it.
|
||||||
let mb2_module_tag = mb2_info.module_tags();
|
let mb2_module_tag = mb2_info.module_tags();
|
||||||
for module in mb2_module_tag {
|
for module in mb2_module_tag {
|
||||||
regions.push(MemoryRegion::new(
|
regions
|
||||||
|
.push(MemoryRegion::new(
|
||||||
module.start_address() as usize,
|
module.start_address() as usize,
|
||||||
module.module_size() as usize,
|
module.module_size() as usize,
|
||||||
MemoryRegionType::Module,
|
MemoryRegionType::Module,
|
||||||
));
|
))
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the AP boot code region that will be copied into by the BSP.
|
// Add the AP boot code region that will be copied into by the BSP.
|
||||||
regions.push(MemoryRegion::new(
|
regions
|
||||||
|
.push(MemoryRegion::new(
|
||||||
super::smp::AP_BOOT_START_PA,
|
super::smp::AP_BOOT_START_PA,
|
||||||
super::smp::ap_boot_code_size(),
|
super::smp::ap_boot_code_size(),
|
||||||
MemoryRegionType::Reclaimable,
|
MemoryRegionType::Reclaimable,
|
||||||
));
|
))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
// Initialize with non-overlapping regions.
|
// Initialize with non-overlapping regions.
|
||||||
memory_regions.call_once(move || non_overlapping_regions_from(regions.as_ref()));
|
memory_regions.call_once(move || regions.into_non_overlapping());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The entry point of Rust code called by inline asm.
|
/// The entry point of Rust code called by inline asm.
|
||||||
|
@ -3,8 +3,7 @@
|
|||||||
//! Information of memory regions in the boot phase.
|
//! Information of memory regions in the boot phase.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
use alloc::{vec, vec::Vec};
|
use core::ops::Deref;
|
||||||
use core::mem::swap;
|
|
||||||
|
|
||||||
use crate::mm::kspace::kernel_loaded_offset;
|
use crate::mm::kspace::kernel_loaded_offset;
|
||||||
|
|
||||||
@ -40,10 +39,19 @@ pub struct MemoryRegion {
|
|||||||
|
|
||||||
impl MemoryRegion {
|
impl MemoryRegion {
|
||||||
/// Constructs a valid memory region.
|
/// Constructs a valid memory region.
|
||||||
pub fn new(base: usize, len: usize, typ: MemoryRegionType) -> Self {
|
pub const fn new(base: usize, len: usize, typ: MemoryRegionType) -> Self {
|
||||||
MemoryRegion { base, len, typ }
|
MemoryRegion { base, len, typ }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constructs a bad memory region.
|
||||||
|
pub const fn bad() -> Self {
|
||||||
|
MemoryRegion {
|
||||||
|
base: 0,
|
||||||
|
len: 0,
|
||||||
|
typ: MemoryRegionType::BadMemory,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Constructs a memory region where kernel sections are loaded.
|
/// Constructs a memory region where kernel sections are loaded.
|
||||||
///
|
///
|
||||||
/// Most boot protocols do not mark the place where the kernel loads as unusable. In this case,
|
/// Most boot protocols do not mark the place where the kernel loads as unusable. In this case,
|
||||||
@ -83,11 +91,11 @@ impl MemoryRegion {
|
|||||||
|
|
||||||
/// Removes range `t` from self, resulting in 0, 1 or 2 truncated ranges.
|
/// Removes range `t` from self, resulting in 0, 1 or 2 truncated ranges.
|
||||||
/// We need to have this method since memory regions can overlap.
|
/// We need to have this method since memory regions can overlap.
|
||||||
pub fn truncate(&self, t: &MemoryRegion) -> Vec<MemoryRegion> {
|
pub fn truncate(&self, t: &MemoryRegion) -> MemoryRegionArray<2> {
|
||||||
if self.base < t.base {
|
if self.base < t.base {
|
||||||
if self.base + self.len > t.base {
|
if self.base + self.len > t.base {
|
||||||
if self.base + self.len > t.base + t.len {
|
if self.base + self.len > t.base + t.len {
|
||||||
vec![
|
MemoryRegionArray::from(&[
|
||||||
MemoryRegion {
|
MemoryRegion {
|
||||||
base: self.base,
|
base: self.base,
|
||||||
len: t.base - self.base,
|
len: t.base - self.base,
|
||||||
@ -98,72 +106,153 @@ impl MemoryRegion {
|
|||||||
len: self.base + self.len - (t.base + t.len),
|
len: self.base + self.len - (t.base + t.len),
|
||||||
typ: self.typ,
|
typ: self.typ,
|
||||||
},
|
},
|
||||||
]
|
])
|
||||||
} else {
|
} else {
|
||||||
vec![MemoryRegion {
|
MemoryRegionArray::from(&[MemoryRegion {
|
||||||
base: self.base,
|
base: self.base,
|
||||||
len: t.base - self.base,
|
len: t.base - self.base,
|
||||||
typ: self.typ,
|
typ: self.typ,
|
||||||
}]
|
}])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vec![*self]
|
MemoryRegionArray::from(&[*self])
|
||||||
}
|
}
|
||||||
} else if self.base < t.base + t.len {
|
} else if self.base < t.base + t.len {
|
||||||
if self.base + self.len > t.base + t.len {
|
if self.base + self.len > t.base + t.len {
|
||||||
vec![MemoryRegion {
|
MemoryRegionArray::from(&[MemoryRegion {
|
||||||
base: t.base + t.len,
|
base: t.base + t.len,
|
||||||
len: self.base + self.len - (t.base + t.len),
|
len: self.base + self.len - (t.base + t.len),
|
||||||
typ: self.typ,
|
typ: self.typ,
|
||||||
}]
|
}])
|
||||||
} else {
|
} else {
|
||||||
vec![]
|
MemoryRegionArray::new()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vec![*self]
|
MemoryRegionArray::from(&[*self])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Truncates regions, resulting in a set of regions that does not overlap.
|
/// The maximum number of regions that can be handled.
|
||||||
///
|
///
|
||||||
/// The truncation will be done according to the type of the regions, that
|
/// The choice of 512 is probably fine since old Linux boot protocol only
|
||||||
/// usable and reclaimable regions will be truncated by the unusable regions.
|
/// allows 128 regions.
|
||||||
pub fn non_overlapping_regions_from(regions: &[MemoryRegion]) -> Vec<MemoryRegion> {
|
//
|
||||||
|
// TODO: confirm the number or make it configurable.
|
||||||
|
pub const MAX_REGIONS: usize = 512;
|
||||||
|
|
||||||
|
/// A heapless set of memory regions.
|
||||||
|
///
|
||||||
|
/// The set cannot contain more than `LEN` regions.
|
||||||
|
pub struct MemoryRegionArray<const LEN: usize = MAX_REGIONS> {
|
||||||
|
regions: [MemoryRegion; LEN],
|
||||||
|
count: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const LEN: usize> Default for MemoryRegionArray<LEN> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const LEN: usize> Deref for MemoryRegionArray<LEN> {
|
||||||
|
type Target = [MemoryRegion];
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.regions[..self.count]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<const LEN: usize> MemoryRegionArray<LEN> {
|
||||||
|
/// Constructs an empty set.
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
regions: [MemoryRegion::bad(); LEN],
|
||||||
|
count: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Constructs from an array of regions.
|
||||||
|
pub fn from(array: &[MemoryRegion]) -> Self {
|
||||||
|
Self {
|
||||||
|
regions: core::array::from_fn(|i| {
|
||||||
|
if i < array.len() {
|
||||||
|
array[i]
|
||||||
|
} else {
|
||||||
|
MemoryRegion::bad()
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
count: array.len(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Appends a region to the set.
|
||||||
|
///
|
||||||
|
/// If the set is full, an error is returned.
|
||||||
|
pub fn push(&mut self, region: MemoryRegion) -> Result<(), &'static str> {
|
||||||
|
if self.count < self.regions.len() {
|
||||||
|
self.regions[self.count] = region;
|
||||||
|
self.count += 1;
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err("MemoryRegionArray is full")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clears the set.
|
||||||
|
pub fn clear(&mut self) {
|
||||||
|
self.count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Truncates regions, resulting in a set of regions that does not overlap.
|
||||||
|
///
|
||||||
|
/// The truncation will be done according to the type of the regions, that
|
||||||
|
/// usable and reclaimable regions will be truncated by the unusable regions.
|
||||||
|
///
|
||||||
|
/// If the output regions are more than `LEN`, the extra regions will be ignored.
|
||||||
|
pub fn into_non_overlapping(self) -> Self {
|
||||||
// We should later use regions in `regions_unusable` to truncate all
|
// We should later use regions in `regions_unusable` to truncate all
|
||||||
// regions in `regions_usable`.
|
// regions in `regions_usable`.
|
||||||
// The difference is that regions in `regions_usable` could be used by
|
// The difference is that regions in `regions_usable` could be used by
|
||||||
// the frame allocator.
|
// the frame allocator.
|
||||||
let mut regions_usable = Vec::<MemoryRegion>::new();
|
let mut regions_usable = MemoryRegionArray::<LEN>::new();
|
||||||
let mut regions_unusable = Vec::<MemoryRegion>::new();
|
let mut regions_unusable = MemoryRegionArray::<LEN>::new();
|
||||||
|
|
||||||
for r in regions {
|
for r in self.iter() {
|
||||||
match r.typ {
|
match r.typ {
|
||||||
MemoryRegionType::Usable | MemoryRegionType::Reclaimable => {
|
MemoryRegionType::Usable | MemoryRegionType::Reclaimable => {
|
||||||
regions_usable.push(*r);
|
// If usable memory regions exceeded it's fine to ignore the rest.
|
||||||
|
let _ = regions_usable.push(*r);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
regions_unusable.push(*r);
|
regions_unusable
|
||||||
|
.push(*r)
|
||||||
|
.expect("Too many unusable memory regions");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// `regions_*` are 2 rolling vectors since we are going to truncate
|
// `regions_*` are 2 rolling vectors since we are going to truncate
|
||||||
// the regions in a iterative manner.
|
// the regions in a iterative manner.
|
||||||
let mut regions = Vec::<MemoryRegion>::new();
|
let mut regions = MemoryRegionArray::<LEN>::new();
|
||||||
let regions_src = &mut regions_usable;
|
let regions_src = &mut regions_usable;
|
||||||
let regions_dst = &mut regions;
|
let regions_dst = &mut regions;
|
||||||
// Truncate the usable regions.
|
// Truncate the usable regions.
|
||||||
for &r_unusable in ®ions_unusable {
|
for r_unusable in regions_unusable.iter() {
|
||||||
regions_dst.clear();
|
regions_dst.clear();
|
||||||
for r_usable in &*regions_src {
|
for r_usable in regions_src.iter() {
|
||||||
regions_dst.append(&mut r_usable.truncate(&r_unusable));
|
for truncated in r_usable.truncate(r_unusable).iter() {
|
||||||
|
let _ = regions_dst.push(*truncated);
|
||||||
}
|
}
|
||||||
swap(regions_src, regions_dst);
|
}
|
||||||
|
core::mem::swap(regions_src, regions_dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Combine all the regions processed.
|
// Combine all the regions processed.
|
||||||
let mut all_regions = regions_unusable;
|
let mut all_regions = regions_unusable;
|
||||||
all_regions.append(&mut regions_usable);
|
for r in regions_usable.iter() {
|
||||||
|
let _ = all_regions.push(*r);
|
||||||
|
}
|
||||||
all_regions
|
all_regions
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,12 +12,12 @@ pub mod kcmdline;
|
|||||||
pub mod memory_region;
|
pub mod memory_region;
|
||||||
pub mod smp;
|
pub mod smp;
|
||||||
|
|
||||||
use alloc::{string::String, vec::Vec};
|
use alloc::string::String;
|
||||||
|
|
||||||
use kcmdline::KCmdlineArg;
|
use kcmdline::KCmdlineArg;
|
||||||
use spin::Once;
|
use spin::Once;
|
||||||
|
|
||||||
use self::memory_region::MemoryRegion;
|
use self::memory_region::MemoryRegionArray;
|
||||||
|
|
||||||
/// ACPI information from the bootloader.
|
/// ACPI information from the bootloader.
|
||||||
///
|
///
|
||||||
@ -99,7 +99,7 @@ define_global_static_boot_arguments!(
|
|||||||
initramfs, INITRAMFS, &'static [u8];
|
initramfs, INITRAMFS, &'static [u8];
|
||||||
acpi_arg, ACPI_ARG, BootloaderAcpiArg;
|
acpi_arg, ACPI_ARG, BootloaderAcpiArg;
|
||||||
framebuffer_arg, FRAMEBUFFER_ARG, BootloaderFramebufferArg;
|
framebuffer_arg, FRAMEBUFFER_ARG, BootloaderFramebufferArg;
|
||||||
memory_regions, MEMORY_REGIONS, Vec<MemoryRegion>;
|
memory_regions, MEMORY_REGIONS, MemoryRegionArray;
|
||||||
);
|
);
|
||||||
|
|
||||||
/// The initialization method of the boot module.
|
/// The initialization method of the boot module.
|
||||||
|
Reference in New Issue
Block a user