From 350f3c6a7f25f567fc2ba783526cb21bfeab0e16 Mon Sep 17 00:00:00 2001 From: rafael Date: Wed, 11 Sep 2024 11:57:34 -0300 Subject: [PATCH] [kernel] E: Check lower memory regions are available --- src/hal/mod.rs | 9 ++++- src/hal/platform/bootinfo.rs | 5 +++ src/hal/platform/microvm.rs | 3 +- src/hal/platform/pc/mboot/basic_mem_info.rs | 2 +- src/hal/platform/pc/mod.rs | 38 ++++++++++++++++++--- src/kmain.rs | 16 +++++++-- 6 files changed, 63 insertions(+), 10 deletions(-) diff --git a/src/hal/mod.rs b/src/hal/mod.rs index be053c66..8adcc5b1 100644 --- a/src/hal/mod.rs +++ b/src/hal/mod.rs @@ -63,13 +63,20 @@ pub fn init( memory_regions: &mut LinkedList>, mmio_regions: &mut LinkedList>, madt: &Option, + mem_lower: Option, ) -> Result { info!("initializing hardware abstraction layer..."); let mut ioports: IoPortAllocator = IoPortAllocator::new(); let mut ioaddresses: IoMemoryAllocator = IoMemoryAllocator::new(); let mut platform: Platform = - platform::init(&mut ioports, &mut ioaddresses, memory_regions, mmio_regions, madt)?; + platform::init( + &mut ioports, + &mut ioaddresses, + memory_regions, + mmio_regions, + madt, + mem_lower)?; // Initialize the interrupt manager. let intman: Option = match platform.arch.controller.take() { diff --git a/src/hal/platform/bootinfo.rs b/src/hal/platform/bootinfo.rs index 0c891932..cba67bd2 100644 --- a/src/hal/platform/bootinfo.rs +++ b/src/hal/platform/bootinfo.rs @@ -31,6 +31,8 @@ use ::alloc::collections::LinkedList; pub struct BootInfo { /// ACPI MADT information. pub madt: Option, + /// Lower memory size. + pub mem_lower: Option, /// General-purpose memory regions. pub memory_regions: LinkedList>, /// Memory-mapped I/O regions. @@ -52,6 +54,7 @@ impl BootInfo { /// # Parameters /// /// - `madt`: ACPI MADT information. + /// - `mem_lower`: Available Lower memory. /// - `memory_regions`: General-purpose memory regions. /// - `mmio_regions`: Memory-mapped I/O regions. /// - `kernel_modules`: Kernel modules. @@ -62,12 +65,14 @@ impl BootInfo { /// pub fn new( madt: Option, + mem_lower: Option, memory_regions: LinkedList>, mmio_regions: LinkedList>, kernel_modules: LinkedList, ) -> Self { Self { madt, + mem_lower, memory_regions, mmio_regions, kernel_modules, diff --git a/src/hal/platform/microvm.rs b/src/hal/platform/microvm.rs index 33ac5f0c..03108399 100644 --- a/src/hal/platform/microvm.rs +++ b/src/hal/platform/microvm.rs @@ -200,7 +200,7 @@ pub fn parse_bootinfo(magic: u32, info: usize) -> Result { kernel_modules.push_back(module); } - Ok(BootInfo::new(None, LinkedList::new(), LinkedList::new(), kernel_modules)) + Ok(BootInfo::new(None, None, LinkedList::new(), LinkedList::new(), kernel_modules)) } pub fn init( @@ -209,6 +209,7 @@ pub fn init( _memory_regions: &mut LinkedList>, _mmio_regions: &mut LinkedList>, madt: &Option, + _mem_lower: Option ) -> Result { Ok(Platform { arch: x86::init(ioports, ioaddresses, madt)?, diff --git a/src/hal/platform/pc/mboot/basic_mem_info.rs b/src/hal/platform/pc/mboot/basic_mem_info.rs index c38581ae..09ada4c3 100644 --- a/src/hal/platform/pc/mboot/basic_mem_info.rs +++ b/src/hal/platform/pc/mboot/basic_mem_info.rs @@ -5,7 +5,7 @@ // Imports //================================================================================================== -use ::error::{ +use ::sys::error::{ Error, ErrorCode, }; diff --git a/src/hal/platform/pc/mod.rs b/src/hal/platform/pc/mod.rs index 9845a932..d25ab45a 100644 --- a/src/hal/platform/pc/mod.rs +++ b/src/hal/platform/pc/mod.rs @@ -33,7 +33,10 @@ use ::arch::{ cpu::pic, mem, }; -use ::sys::error::Error; +use ::sys::error::{ + Error, + ErrorCode, +}; use ::sys::{ config, mm::VirtualAddress, @@ -107,7 +110,16 @@ pub struct Platform { #[cfg(feature = "bios")] fn register_bios_data_area( memory_regions: &mut LinkedList>, + mem_lower_size: usize, ) -> Result<(), Error> { + + // This is possible because mem_lower_size start at address 0x0. + if mem_lower_size < bios::BiosDataArea::BASE + mem::PAGE_SIZE { + let reason: &str = "bios data memory region is not available"; + error!("register_bios_data_area(): {:?}", reason); + return Err(Error::new(ErrorCode::OutOfMemory, reason)); + } + let bios_data_area: MemoryRegion = MemoryRegion::new( "bios data area", VirtualAddress::from_raw_value(bios::BiosDataArea::BASE)? @@ -156,6 +168,7 @@ pub fn init( memory_regions: &mut LinkedList>, mmio_regions: &mut LinkedList>, madt: &Option, + mem_lower: Option, ) -> Result { // Register I/O ports for 8259 PIC. ioports.register_read_write(pic::PIC_CTRL_MASTER as u16)?; @@ -182,8 +195,25 @@ pub fn init( // Register BIOS data area. #[cfg(feature = "bios")] - register_bios_data_area(memory_regions)?; + let mem_lower_size = match mem_lower { + Some(mem_lower_size) => { + mem_lower_size as usize + }, + None => { + let reason: &str = "availability of lower memory is not known"; + error!("init(): {:?}", reason); + return Err(Error::new(ErrorCode::InvalidArgument, reason)); + } + }; + + register_bios_data_area(memory_regions, mem_lower_size)?; + // This is possible because mem_lower start at address 0x0. + if mem_lower_size < platform::TRAMPOLINE_ADDRESS.into_raw_value() + mem::PAGE_SIZE { + let reason: &str = "trampoline memory region is not available"; + error!("init(): {:?}", reason); + return Err(Error::new(ErrorCode::OutOfMemory, reason)); + } // Trampoline. let trampoline: MemoryRegion = MemoryRegion::new( "trampoline", @@ -195,7 +225,7 @@ pub fn init( memory_regions.push_back(trampoline); // Register video display memory. - // TODO: we should read this region from the multi-boot information passed by Grub. + // FIXME: https://github.com/nanvix/kernel/issues/435 let video_display_memory: TruncatedMemoryRegion = TruncatedMemoryRegion::new( "video display memory", PageAligned::from_raw_value(0x000a0000)?, @@ -207,7 +237,7 @@ pub fn init( mmio_regions.push_back(video_display_memory); // Bios memory. - // TODO: we should read this region from the multi-boot information passed by Grub. + // FIXME: https://github.com/nanvix/kernel/issues/435 let bios: MemoryRegion = MemoryRegion::new( "bios memory", VirtualAddress::from_raw_value(0x000c0000)?, diff --git a/src/kmain.rs b/src/kmain.rs index fdf6817d..4d8e939c 100644 --- a/src/kmain.rs +++ b/src/kmain.rs @@ -213,14 +213,19 @@ pub extern "C" fn kmain(kargs: &KernelArguments) { // Parse kernel arguments. info!("parsing kernel arguments..."); - let (madt, mut memory_regions, mut mmio_regions, kernel_modules): ( + let (madt, mem_lower, mut memory_regions, mut mmio_regions, kernel_modules): ( Option, + Option, LinkedList>, LinkedList>, LinkedList, ) = match kargs.parse() { Ok(bootinfo) => { - (bootinfo.madt, bootinfo.memory_regions, bootinfo.mmio_regions, bootinfo.kernel_modules) + (bootinfo.madt, + bootinfo.mem_lower, + bootinfo.memory_regions, + bootinfo.mmio_regions, + bootinfo.kernel_modules) }, Err(err) => { panic!("failed to parse kernel arguments: {:?}", err); @@ -255,7 +260,12 @@ pub extern "C" fn kmain(kargs: &KernelArguments) { } } - let mut hal: Hal = match hal::init(&mut memory_regions, &mut mmio_regions, &madt) { + let mut hal: Hal = match hal::init( + &mut memory_regions, + &mut mmio_regions, + &madt, + mem_lower) + { Ok(hal) => hal, Err(err) => { panic!("failed to initialize hardware abstraction layer: {:?}", err);