Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

simplify find_kernel for x86_64 #376

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 29 additions & 40 deletions src/arch/x86_64/multiboot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,38 +100,30 @@ pub fn find_kernel() -> &'static [u8] {
assert!(mb_info > 0, "Could not find Multiboot information");
info!("Found Multiboot information at {:#x}", mb_info);
}
let page_address = unsafe { mb_info.align_down(Size4KiB::SIZE as usize) };
paging::map::<Size4KiB>(page_address, page_address, 1, PageTableFlags::empty());
unsafe { paging::map::<Size4KiB>(mb_info, mb_info, 1, PageTableFlags::empty()) };

let mut mem = Mem;
// Load the Multiboot information and identity-map the modules information.
let multiboot = unsafe { Multiboot::from_ptr(mb_info as u64, &mut mem).unwrap() };
let modules_address = multiboot
.modules()
.expect("Could not find a memory map in the Multiboot information")
.next()
.expect("Could not find first map address")
.start as usize;
let page_address = modules_address.align_down(Size4KiB::SIZE as usize);
paging::map::<Size4KiB>(page_address, page_address, 1, PageTableFlags::empty());

// Iterate through all modules.
// Collect the start address of the first module and the highest end address of all modules.
let modules = multiboot.modules().unwrap();
let mut found_module = false;
let mut start_address = 0;
let mut end_address = 0;

for m in modules {
found_module = true;

if start_address == 0 {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assumed this line is to check if this is the first iteration of the loop (because the variable is initialized to 0) but if it is possible that some of the modules have 0 as their start value, my assumption is incorrect and the new code behaves differently. I don't think that is possible, though.

start_address = m.start as usize;
}

if m.end as usize > end_address {
end_address = m.end as usize;
}
let mut module_iter = multiboot
.modules()
.expect("Could not find a memory map in the Multiboot information");
let start_address;
let mut end_address;

if let Some(first_module) = module_iter.next() {
start_address = first_module.start as usize;
info!("Found an ELF module at {:#x}", start_address);
end_address = first_module.end as usize;
} else {
panic!("Could not find a single module in the Multiboot information")
}
// Find the maximum end address from the remaining modules
for m in module_iter {
end_address = usize::max(end_address, m.end as usize);
}

info!("Found module: [{:#x} - {:#x}]", start_address, end_address);
Expand All @@ -146,24 +138,21 @@ pub fn find_kernel() -> &'static [u8] {
PhysAlloc::init(free_memory_address);

// Identity-map the ELF header of the first module.
assert!(
found_module,
"Could not find a single module in the Multiboot information"
let first_module_mapping_end = start_address.align_up(Size2MiB::SIZE as usize);
paging::map_range::<Size4KiB>(
start_address,
start_address,
first_module_mapping_end,
PageTableFlags::empty(),
);
assert!(start_address > 0);
info!("Found an ELF module at {:#x}", start_address);
let page_address = start_address.align_down(Size4KiB::SIZE as usize) + Size4KiB::SIZE as usize;
let counter =
(start_address.align_up(Size2MiB::SIZE as usize) - page_address) / Size4KiB::SIZE as usize;
paging::map::<Size4KiB>(page_address, page_address, counter, PageTableFlags::empty());

// map also the rest of the module
let address = start_address.align_up(Size2MiB::SIZE as usize);
let counter =
(end_address.align_up(Size2MiB::SIZE as usize) - address) / Size2MiB::SIZE as usize;
if counter > 0 {
paging::map::<Size2MiB>(address, address, counter, PageTableFlags::empty());
}
paging::map_range::<Size2MiB>(
first_module_mapping_end,
first_module_mapping_end,
free_memory_address,
PageTableFlags::empty(),
);

unsafe { slice::from_raw_parts(sptr::from_exposed_addr(elf_start), elf_len) }
}
Expand Down
34 changes: 34 additions & 0 deletions src/arch/x86_64/paging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,40 @@ where
}
}

#[cfg(all(target_arch = "x86_64", not(feature = "fc")))]
pub fn map_range<S>(
virtual_start: usize,
phys_start: usize,
phys_end: usize,
mut flags: PageTableFlags,
) where
S: PageSize + Debug,
RecursivePageTable<'static>: Mapper<S>,
{
let first_page = Page::<S>::containing_address(x86_64::VirtAddr::new(virtual_start as u64));
let first_frame = PhysFrame::containing_address(x86_64::PhysAddr::new(phys_start as u64));
let last_frame = PhysFrame::containing_address(x86_64::PhysAddr::new(phys_end as u64));
warn!(
"Mapping {size} pages starting from {from_start:p} to frames {to_start:p}..{to_end:p}",
size = S::DEBUG_STR,
from_start = first_page.start_address(),
to_start = first_frame.start_address(),
to_end = last_frame.start_address()
);
flags |= PageTableFlags::PRESENT;
let mut table = unsafe { recursive_page_table() };
let page_range = core::iter::successors(Some(first_page), |page| Some(*page + 1u64));
let frame_range = PhysFrame::<S>::range(first_frame, last_frame);
for (page, frame) in core::iter::zip(page_range, frame_range) {
unsafe {
table
.map_to(page, frame, flags, &mut PhysAlloc)
.unwrap()
.flush();
}
}
}

pub fn clean_up() {
let mut table = unsafe { recursive_page_table() };

Expand Down