Skip to content

Commit

Permalink
Kernel+Mem: Provide kernel's boot info to Virt Mem Map
Browse files Browse the repository at this point in the history
  • Loading branch information
corigan01 committed Jan 13, 2025
1 parent f9cac06 commit 199afe9
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 41 deletions.
5 changes: 4 additions & 1 deletion bootloader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,8 @@ pub struct Stage32toStage64 {
pub struct KernelBootHeader {
pub phys_mem_map: &'static PhysMemoryMap<MEMORY_REGIONS>,
pub video_mode: Option<(VesaModeId, VesaMode)>,
pub init_alloc_region: (u64, usize),
pub kernel_elf: (u64, usize),
pub kernel_exe: (u64, usize),
pub kernel_stack: (u64, usize),
pub kernel_init_heap: (u64, usize),
}
11 changes: 10 additions & 1 deletion bootloader/stage-64bit/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,16 @@ fn main(stage_to_stage: &Stage32toStage64) {
*s2k = Some(KernelBootHeader {
phys_mem_map: mm,
video_mode: stage_to_stage.video_mode,
init_alloc_region: (
kernel_elf: (kernel_elf_ptr, kernel_elf_size as usize),
kernel_exe: (
virt_info.exe_start_virt,
(virt_info.exe_end_virt - virt_info.exe_start_virt) as usize,
),
kernel_stack: (
virt_info.stack_start_virt,
(virt_info.stack_end_virt - virt_info.stack_start_virt) as usize,
),
kernel_init_heap: (
virt_info.init_start_virt,
(virt_info.init_end_virt - virt_info.init_start_virt) as usize,
),
Expand Down
8 changes: 4 additions & 4 deletions bootloader/stage-64bit/src/paging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ pub struct PageTableConfig {
pub struct KernelVirtInfo {
pub exe_start_virt: u64,
pub exe_end_virt: u64,
pub _stack_start_virt: u64,
pub stack_start_virt: u64,
pub stack_end_virt: u64,
pub init_start_virt: u64,
pub init_end_virt: u64,
Expand All @@ -80,8 +80,8 @@ impl KernelVirtInfo {
pub fn _stack_slice(&mut self) -> &'static mut [u8] {
unsafe {
core::slice::from_raw_parts_mut(
self._stack_start_virt as *mut u8,
(self.stack_end_virt - self._stack_start_virt) as usize,
self.stack_start_virt as *mut u8,
(self.stack_end_virt - self.stack_start_virt) as usize,
)
}
}
Expand Down Expand Up @@ -194,7 +194,7 @@ pub fn build_page_tables(c: PageTableConfig) -> KernelVirtInfo {
KernelVirtInfo {
exe_start_virt: c.kernel_virt,
exe_end_virt: c.kernel_virt + (exe_pages * PAGE_2M) as u64,
_stack_start_virt: c.kernel_virt + ((exe_pages + 1) * PAGE_2M) as u64,
stack_start_virt: c.kernel_virt + ((exe_pages + 1) * PAGE_2M) as u64,
stack_end_virt: c.kernel_virt + ((exe_pages + stack_pages + 1) * PAGE_2M) as u64,
init_start_virt: c.kernel_virt + ((exe_pages + stack_pages + 2) * PAGE_2M) as u64,
init_end_virt: c.kernel_virt
Expand Down
96 changes: 77 additions & 19 deletions crates/mem/src/vmm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,13 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

use core::ops::{BitOr, BitOrAssign};
use core::{
fmt::Debug,
ops::{BitOr, BitOrAssign},
};

use crate::{MemoryError, pmm::PhysPage};
use alloc::{boxed::Box, collections::BTreeMap, string::String, vec::Vec};
use alloc::{boxed::Box, collections::BTreeMap, format, string::String, vec::Vec};
use arch::idt64::{InterruptFlags, InterruptInfo};
use hw::make_hw;
use lldebug::logln;

Check warning on line 35 in crates/mem/src/vmm.rs

View workflow job for this annotation

GitHub Actions / Build OS

unused import: `lldebug::logln`
Expand Down Expand Up @@ -56,7 +59,7 @@ impl Iterator for VmPageIter {
}
}

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct VmRegion {
pub start: VirtPage,
pub end: VirtPage,
Expand All @@ -76,7 +79,7 @@ impl VmRegion {
}
}

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct VirtPage(pub usize);

impl VirtPage {
Expand Down Expand Up @@ -141,7 +144,18 @@ trait VmBacking {
field(RW, 3, user)
)]
#[derive(Clone, Copy)]
struct VmPermissions(u8);
pub struct VmPermissions(u8);

impl Debug for VmPermissions {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("VmPermissions")
.field("exec", &self.is_exec_set())
.field("read", &self.is_read_set())
.field("write", &self.is_write_set())
.field("user", &self.is_user_set())
.finish()
}
}

impl VmPermissions {
pub const NONE: VmPermissions = VmPermissions(0);
Expand Down Expand Up @@ -171,7 +185,7 @@ impl BitOrAssign for VmPermissions {

struct VmObject {
region: VmRegion,
backing: Box<dyn VmBacking>,
backing: Option<Box<dyn VmBacking>>,

Check warning on line 188 in crates/mem/src/vmm.rs

View workflow job for this annotation

GitHub Actions / Build OS

fields `backing` and `page_table` are never read
permissions: VmPermissions,
what: String,
// FIXME: We shouldn't create a page table for each process, we should only create the entries we need
Expand All @@ -182,6 +196,18 @@ struct VmObject {
page_table: page::VmSafePageTable,
}

impl Debug for VmObject {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("VmObject")
.field("region", &self.region)
.field("permissions", &self.permissions)
.field("what", &self.what)
.field("page_table", &"...")
.field("backing", &"...")
.finish()
}
}

impl VmObject {
/// Link this physical page to this virtal page.
fn hydrate_page(&mut self, vpage: VirtPage, ppage: PhysPage) -> Result<(), MemoryError> {

Check warning on line 213 in crates/mem/src/vmm.rs

View workflow job for this annotation

GitHub Actions / Build OS

methods `hydrate_page`, `fault_handler`, and `vm_pages` are never used
Expand All @@ -197,8 +223,12 @@ impl VmObject {
return Err(MemoryError::DidNotHandleException);
};

let Some(backing) = self.backing.as_mut() else {
return Err(MemoryError::DidNotHandleException);
};

assert_eq!(
self.backing.backing_kind(),
backing.backing_kind(),
VmBackingKind::Physical,
"TODO: Currently we only support Physical Page backing!"
);
Expand All @@ -210,7 +240,7 @@ impl VmObject {

// This page does not exist, make it!
if present {
let ppage = self.backing.alloc_anywhere()?;
let ppage = backing.alloc_anywhere()?;
self.hydrate_page(VirtPage::containing_page(virt_addr), ppage)?;

Ok(())
Expand All @@ -224,12 +254,31 @@ impl VmObject {
}
}

#[derive(Debug, Clone, Copy)]
pub enum KernelRegionKind {
KernelExe,
KernelElf,
KernelStack,
KernelHeap,
}

struct VmProcess {
vm_process_id: usize,
objects: Vec<VmObject>,
page_table: page::VmSafePageTable,

Check warning on line 268 in crates/mem/src/vmm.rs

View workflow job for this annotation

GitHub Actions / Build OS

field `page_table` is never read
}

impl Debug for VmProcess {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("VmProcess")
.field("vm_process_id", &self.vm_process_id)
.field("objects", &self.objects)
.field("page_table", &"...")
.finish()
}
}

#[derive(Debug)]
pub struct Vmm {
active_process: usize,
table: BTreeMap<usize, VmProcess>,
Expand All @@ -247,27 +296,36 @@ impl Vmm {

pub fn init_kernel_process(
&mut self,
kernel_regions: impl Iterator<Item = VmRegion>,
kernel_regions: impl Iterator<Item = (VmRegion, KernelRegionKind)>,
) -> Result<(), MemoryError> {
let page_tables = page::VmSafePageTable::copy_from_bootloader();
unsafe { page_tables.load() };

let mut vm_objects = Vec::new();
vm_objects.push(VmObject {
region: todo!(),
backing: todo!(),
permissions: todo!(),
page_table: page_tables,
what: todo!(),
});
let vm_objects = kernel_regions
.map(|(region, kind)| {
let permissions = match kind {
KernelRegionKind::KernelExe => VmPermissions::EXEC | VmPermissions::READ,
KernelRegionKind::KernelElf => VmPermissions::READ,
KernelRegionKind::KernelStack => VmPermissions::READ | VmPermissions::WRITE,
KernelRegionKind::KernelHeap => VmPermissions::READ | VmPermissions::WRITE,
};

VmObject {
region,
backing: None,
permissions,
page_table: page_tables.clone(),
what: format!("{:?}", kind),
}
})
.collect();

self.table.insert(Self::KERNEL_PROCESS, VmProcess {
vm_process_id: 0,
objects: vm_objects,
page_table: page_tables,
});

unsafe { page_tables.load() };
todo!()
Ok(())
}
}
9 changes: 1 addition & 8 deletions crates/mem/src/vmm/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,10 +310,7 @@ impl VmSafePageTable {
is_align_to(vm_table_ptr, 4096) && is_align_to(phys_table_ptr, 4096),
"Page tables are not aligned!"
);
logln!("{:#016x}", phys_table_ptr);

unsafe { arch::registers::cr3::set_page_directory_base_register(phys_table_ptr) };
logln!("Loaded!");
}

/// Attempts to return the Physical Address for the given Virt Address.
Expand Down Expand Up @@ -360,11 +357,7 @@ impl VmSafePageTable {
}

/// Maps the PhysPage to the VirtPage.
pub fn map_page(
&mut self,
virt_page: VirtPage,
phys_page: PhysPage,
) -> Result<(), MemoryError> {
pub fn map_page(&self, virt_page: VirtPage, phys_page: PhysPage) -> Result<(), MemoryError> {

Check warning on line 360 in crates/mem/src/vmm/page.rs

View workflow job for this annotation

GitHub Actions / Build OS

unused variable: `virt_page`

Check warning on line 360 in crates/mem/src/vmm/page.rs

View workflow job for this annotation

GitHub Actions / Build OS

unused variable: `phys_page`
todo!()
}
}
Expand Down
45 changes: 37 additions & 8 deletions kernel/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use lldebug::{debug_ready, logln, make_debug};
use mem::{
alloc::{KernelAllocator, dump_allocator, provide_init_region},
pmm::Pmm,
vmm::{VirtPage, VmRegion, Vmm},
vmm::{KernelRegionKind, VirtPage, VmRegion, Vmm},
};
use serial::{Serial, baud::SerialBaud};
use timer::kernel_ticks;
Expand Down Expand Up @@ -73,10 +73,10 @@ fn main(kbh: &KernelBootHeader) {

logln!(
"Init Heap Region ({})",
HumanBytes::from(kbh.init_alloc_region.1)
HumanBytes::from(kbh.kernel_init_heap.1)
);
provide_init_region(unsafe {
core::slice::from_raw_parts_mut(kbh.init_alloc_region.0 as *mut u8, kbh.init_alloc_region.1)
core::slice::from_raw_parts_mut(kbh.kernel_init_heap.0 as *mut u8, kbh.kernel_init_heap.1)
});

logln!("Init PhysMemoryManager");
Expand All @@ -85,14 +85,43 @@ fn main(kbh: &KernelBootHeader) {
logln!("Init VirtMemoryManager");
let mut vmm = Vmm::new();
vmm.init_kernel_process(
[VmRegion {
start: VirtPage(0),
end: VirtPage(10),
}]
[
(
VmRegion {
start: VirtPage::containing_page(kbh.kernel_elf.0),
end: VirtPage::containing_page(kbh.kernel_elf.0 + kbh.kernel_elf.1 as u64),
},
KernelRegionKind::KernelElf,
),
(
VmRegion {
start: VirtPage::containing_page(kbh.kernel_exe.0),
end: VirtPage::containing_page(kbh.kernel_exe.0 + kbh.kernel_exe.1 as u64),
},
KernelRegionKind::KernelExe,
),
(
VmRegion {
start: VirtPage::containing_page(kbh.kernel_stack.0),
end: VirtPage::containing_page(kbh.kernel_stack.0 + kbh.kernel_stack.1 as u64),
},
KernelRegionKind::KernelStack,
),
(
VmRegion {
start: VirtPage::containing_page(kbh.kernel_init_heap.0),
end: VirtPage::containing_page(
kbh.kernel_init_heap.0 + kbh.kernel_init_heap.1 as u64,
),
},
KernelRegionKind::KernelHeap,
),
]
.into_iter(),
)
.unwrap();

logln!("{:#?}", vmm);

logln!("Finished in {}ms", kernel_ticks());
dump_allocator();
}

0 comments on commit 199afe9

Please sign in to comment.