Skip to content

Commit

Permalink
Merge #185
Browse files Browse the repository at this point in the history
185: Rework paging r=stlankes a=mkroening



Co-authored-by: Martin Kröning <[email protected]>
  • Loading branch information
bors[bot] and mkroening authored Jan 13, 2023
2 parents 88ab701 + 95d27a0 commit e9fd30d
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 505 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ multiboot = "0.8"
[target.'cfg(target_arch = "x86_64")'.dependencies]
bitflags = "1.3"
uart_16550 = "0.2"
x86_64 = { version = "0.14", default-features = false }

[target.'cfg(target_arch = "aarch64")'.dependencies]
aarch64 = "0.0.7"
Expand Down
88 changes: 34 additions & 54 deletions src/arch/x86_64/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
pub mod paging;
pub mod physicalmem;
mod paging;
mod physicalmem;

use core::arch::asm;
#[cfg(target_os = "none")]
use core::ptr::write_bytes;
#[cfg(target_os = "none")]
use core::{cmp, mem, slice};
use core::{mem, slice};

use hermit_entry::{
boot_info::{BootInfo, HardwareInfo, PlatformInfo, RawBootInfo, SerialPortBase},
Expand All @@ -16,8 +16,9 @@ use log::info;
#[cfg(target_os = "none")]
use multiboot::information::{MemoryManagement, Multiboot, PAddr};
use uart_16550::SerialPort;
use x86_64::structures::paging::{PageSize, PageTableFlags, Size2MiB, Size4KiB};

use paging::{BasePageSize, LargePageSize, PageSize, PageTableEntryFlags};
use self::physicalmem::PhysAlloc;

#[cfg(target_os = "none")]
extern "C" {
Expand Down Expand Up @@ -82,11 +83,14 @@ pub unsafe fn boot_kernel(

#[cfg(target_os = "none")]
pub unsafe fn find_kernel() -> &'static [u8] {
use core::cmp;

paging::clean_up();
// Identity-map the Multiboot information.
assert!(mb_info > 0, "Could not find Multiboot information");
info!("Found Multiboot information at {:#x}", mb_info);
let page_address = align_down!(mb_info, BasePageSize::SIZE);
paging::map::<BasePageSize>(page_address, page_address, 1, PageTableEntryFlags::WRITABLE);
let page_address = align_down!(mb_info, Size4KiB::SIZE as usize);
paging::map::<Size4KiB>(page_address, page_address, 1, PageTableFlags::empty());

// Load the Multiboot information and identity-map the modules information.
let multiboot = Multiboot::from_ptr(mb_info as u64, &mut MEM).unwrap();
Expand All @@ -96,8 +100,8 @@ pub unsafe fn find_kernel() -> &'static [u8] {
.next()
.expect("Could not find first map address")
.start as usize;
let page_address = align_down!(modules_address, BasePageSize::SIZE);
paging::map::<BasePageSize>(page_address, page_address, 1, PageTableEntryFlags::empty());
let page_address = align_down!(modules_address, 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.
Expand All @@ -123,11 +127,11 @@ pub unsafe fn find_kernel() -> &'static [u8] {
let elf_len = end_address - start_address;
info!("Module length: {:#x}", elf_len);

let free_memory_address = align_up!(end_address, LargePageSize::SIZE);
let free_memory_address = align_up!(end_address, Size2MiB::SIZE as usize);
// TODO: Workaround for https://github.com/hermitcore/rusty-loader/issues/96
let free_memory_address = cmp::max(free_memory_address, 0x800000);
// Memory after the highest end address is unused and available for the physical memory manager.
physicalmem::init(free_memory_address);
PhysAlloc::init(free_memory_address);

// Identity-map the ELF header of the first module.
assert!(
Expand All @@ -136,33 +140,18 @@ pub unsafe fn find_kernel() -> &'static [u8] {
);
assert!(start_address > 0);
info!("Found an ELF module at {:#x}", start_address);
let page_address = align_down!(start_address, BasePageSize::SIZE);
let counter =
(align_up!(start_address, LargePageSize::SIZE) - page_address) / BasePageSize::SIZE;
info!(
"Map {} pages at {:#x} (page size {} KByte)",
counter,
page_address,
BasePageSize::SIZE / 1024
);
paging::map::<BasePageSize>(
page_address,
page_address,
counter,
PageTableEntryFlags::empty(),
);
let page_address =
align_down!(start_address, Size4KiB::SIZE as usize) + Size4KiB::SIZE as usize;
let counter = (align_up!(start_address, 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 = align_up!(start_address, LargePageSize::SIZE);
let counter = (align_up!(end_address, LargePageSize::SIZE) - address) / LargePageSize::SIZE;
let address = align_up!(start_address, Size2MiB::SIZE as usize);
let counter =
(align_up!(end_address, Size2MiB::SIZE as usize) - address) / Size2MiB::SIZE as usize;
if counter > 0 {
info!(
"Map {} pages at {:#x} (page size {} KByte)",
counter,
address,
LargePageSize::SIZE / 1024
);
paging::map::<LargePageSize>(address, address, counter, PageTableEntryFlags::WRITABLE);
paging::map::<Size2MiB>(address, address, counter, PageTableFlags::empty());
}

slice::from_raw_parts(elf_start as *const u8, elf_len)
Expand All @@ -177,43 +166,34 @@ pub unsafe fn boot_kernel(kernel_info: LoadedKernel) -> ! {

let multiboot = Multiboot::from_ptr(mb_info as u64, &mut MEM).unwrap();

let command_line = multiboot.command_line().map(|command_line| {
let address = command_line.as_ptr();

// Identity-map the command line.
let page_address = align_down!(address as usize, BasePageSize::SIZE);
paging::map::<BasePageSize>(page_address, page_address, 1, PageTableEntryFlags::empty());

command_line
});

// determine boot stack address
let mut new_stack = align_up!(&kernel_end as *const u8 as usize, BasePageSize::SIZE);
let mut new_stack = align_up!(&kernel_end as *const u8 as usize, Size4KiB::SIZE as usize);

if new_stack + KERNEL_STACK_SIZE as usize > mb_info {
new_stack = align_up!(
mb_info + mem::size_of::<Multiboot<'_, '_>>(),
BasePageSize::SIZE
Size4KiB::SIZE as usize
);
}

let command_line = multiboot.command_line();
if let Some(command_line) = command_line {
let cmdline = command_line.as_ptr() as usize;
let cmdsize = command_line.len();
if new_stack + KERNEL_STACK_SIZE as usize > cmdline {
new_stack = align_up!((cmdline + cmdsize), BasePageSize::SIZE);
new_stack = align_up!((cmdline + cmdsize), Size4KiB::SIZE as usize);
}
}

let current_stack_address = new_stack as u64;
info!("Use stack address {:#x}", current_stack_address);

// map stack in the address space
paging::map::<BasePageSize>(
paging::map::<Size4KiB>(
new_stack,
new_stack,
KERNEL_STACK_SIZE as usize / BasePageSize::SIZE,
PageTableEntryFlags::WRITABLE,
KERNEL_STACK_SIZE as usize / Size4KiB::SIZE as usize,
PageTableFlags::WRITABLE,
);

// clear stack
Expand Down Expand Up @@ -271,15 +251,15 @@ pub unsafe fn boot_kernel(kernel_info: LoadedKernel) -> ! {
}

unsafe fn map_memory(address: usize, memory_size: usize) -> usize {
let address = align_up!(address, LargePageSize::SIZE);
let page_count = align_up!(memory_size, LargePageSize::SIZE) / LargePageSize::SIZE;
let address = align_up!(address, Size2MiB::SIZE as usize);
let page_count = align_up!(memory_size, Size2MiB::SIZE as usize) / Size2MiB::SIZE as usize;

paging::map::<LargePageSize>(address, address, page_count, PageTableEntryFlags::WRITABLE);
paging::map::<Size2MiB>(address, address, page_count, PageTableFlags::WRITABLE);

address
}

pub unsafe fn get_memory(memory_size: u64) -> u64 {
let address = physicalmem::allocate(align_up!(memory_size as usize, LargePageSize::SIZE));
let address = PhysAlloc::allocate(align_up!(memory_size as usize, Size2MiB::SIZE as usize));
map_memory(address, memory_size as usize) as u64
}
Loading

0 comments on commit e9fd30d

Please sign in to comment.