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

Configurable kernel stack size, better non-x86_64 errors #72

Merged
merged 2 commits into from
Aug 5, 2019
Merged
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
57 changes: 31 additions & 26 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,44 @@
#[cfg(not(feature = "binary"))]
fn main() {}
fn main() {
#[cfg(target_arch = "x86")]
compile_error!(
"This crate currently does not support 32-bit protected mode. \
See https://github.com/rust-osdev/bootloader/issues/70 for more information."
);

#[cfg(not(any(target_arch = "x86_64", target_arch = "x86")))]
compile_error!("This crate only supports the x86_64 architecture.");
}

#[cfg(feature = "binary")]
fn address_from_env(env: &'static str) -> Option<u64> {
fn num_from_env(env: &'static str, aligned: bool) -> Option<u64> {
use std::env;
match env::var(env) {
Err(env::VarError::NotPresent) => None,
Err(env::VarError::NotUnicode(_)) => {
panic!("The `{}` environment variable must be valid unicode", env,)
}
Ok(s) => {
let addr = if s.starts_with("0x") {
let num = if s.starts_with("0x") {
u64::from_str_radix(&s[2..], 16)
} else {
u64::from_str_radix(&s, 10)
};

let addr = addr.expect(&format!(
let num = num.expect(&format!(
"The `{}` environment variable must be an integer\
(is `{}`).",
env, s
));

if addr % 0x1000 != 0 {
if aligned && num % 0x1000 != 0 {
panic!(
"The `{}` environment variable must be aligned to 0x1000 (is `{:#x}`).",
env, addr
env, num
);
}

Some(addr)
Some(num)
}
}
}
Expand Down Expand Up @@ -176,31 +185,26 @@ fn main() {
process::exit(1);
}

// create a file with the `PHYSICAL_MEMORY_OFFSET` constant
let file_path = out_dir.join("physical_memory_offset.rs");
let mut file = File::create(file_path).expect("failed to create physical_memory_offset.rs");
let physical_memory_offset = address_from_env("BOOTLOADER_PHYSICAL_MEMORY_OFFSET");
file.write_all(
format!(
"const PHYSICAL_MEMORY_OFFSET: Option<u64> = {:?};",
physical_memory_offset
)
.as_bytes(),
)
.expect("write to physical_memory_offset.rs failed");

// create a file with the `KERNEL_STACK_ADDRESS` constant
let file_path = out_dir.join("kernel_stack_address.rs");
let mut file = File::create(file_path).expect("failed to create kernel_stack_address.rs");
let kernel_stack_address = address_from_env("BOOTLOADER_KERNEL_STACK_ADDRESS");
// Configure constants for the bootloader
// We leave some variables as Option<T> rather than hardcoding their defaults so that they
// can be calculated dynamically by the bootloader.
let file_path = out_dir.join("bootloader_config.rs");
let mut file = File::create(file_path).expect("failed to create bootloader_config.rs");
let physical_memory_offset = num_from_env("BOOTLOADER_PHYSICAL_MEMORY_OFFSET", true);
let kernel_stack_address = num_from_env("BOOTLOADER_KERNEL_STACK_ADDRESS", true);
let kernel_stack_size = num_from_env("BOOTLOADER_KERNEL_STACK_SIZE", false);
file.write_all(
format!(
"const KERNEL_STACK_ADDRESS: Option<u64> = {:?};",
"const PHYSICAL_MEMORY_OFFSET: Option<u64> = {:?};
const KERNEL_STACK_ADDRESS: Option<u64> = {:?};
const KERNEL_STACK_SIZE: u64 = {};",
physical_memory_offset,
kernel_stack_address,
kernel_stack_size.unwrap_or(512), // size is in number of pages
)
.as_bytes(),
)
.expect("write to kernel_stack_address.rs failed");
.expect("write to bootloader_config.rs failed");

// pass link arguments to rustc
println!("cargo:rustc-link-search=native={}", out_dir.display());
Expand All @@ -212,6 +216,7 @@ fn main() {
println!("cargo:rerun-if-env-changed=KERNEL");
println!("cargo:rerun-if-env-changed=BOOTLOADER_PHYSICAL_MEMORY_OFFSET");
println!("cargo:rerun-if-env-changed=BOOTLOADER_KERNEL_STACK_ADDRESS");
println!("cargo:rerun-if-env-changed=BOOTLOADER_KERNEL_STACK_SIZE");
println!("cargo:rerun-if-changed={}", kernel.display());
println!("cargo:rerun-if-changed=build.rs");
}
15 changes: 9 additions & 6 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ use x86_64::structures::paging::{
use x86_64::ux::u9;
use x86_64::{PhysAddr, VirtAddr};

// The offset into the virtual address space where the physical memory is mapped if
// the `map_physical_memory` is activated. Set by the build script.
include!(concat!(env!("OUT_DIR"), "/physical_memory_offset.rs"));

// The virtual address of the kernel stack. Set by the build script.
include!(concat!(env!("OUT_DIR"), "/kernel_stack_address.rs"));
// The bootloader_config.rs file contains some configuration constants set by the build script:
// PHYSICAL_MEMORY_OFFSET: The offset into the virtual address space where the physical memory
// is mapped if the `map_physical_memory` feature is activated.
//
// KERNEL_STACK_ADDRESS: The virtual address of the kernel stack.
//
// KERNEL_STACK_SIZE: The number of pages in the kernel stack.
include!(concat!(env!("OUT_DIR"), "/bootloader_config.rs"));

global_asm!(include_str!("stage_1.s"));
global_asm!(include_str!("stage_2.s"));
Expand Down Expand Up @@ -271,6 +273,7 @@ fn load_elf(
let stack_end = page_table::map_kernel(
kernel_start.phys(),
kernel_stack_address,
KERNEL_STACK_SIZE,
&segments,
&mut rec_page_table,
&mut frame_allocator,
Expand Down
4 changes: 2 additions & 2 deletions src/page_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use xmas_elf::program::{self, ProgramHeader64};
pub(crate) fn map_kernel(
kernel_start: PhysAddr,
stack_start: Page,
stack_size: u64,
segments: &FixedVec<ProgramHeader64>,
page_table: &mut RecursivePageTable,
frame_allocator: &mut FrameAllocator,
Expand All @@ -20,9 +21,8 @@ pub(crate) fn map_kernel(
}

// Create a stack
let stack_size: u64 = 512; // in pages
let stack_start = stack_start + 1; // Leave the first page unmapped as a 'guard page'
let stack_end = stack_start + stack_size;
let stack_end = stack_start + stack_size; // stack_size is in pages

let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE;
let region_type = MemoryRegionType::KernelStack;
Expand Down