Skip to content

Commit f890cc1

Browse files
authored
add dynamic range configuration (#229)
1 parent 66637c1 commit f890cc1

File tree

8 files changed

+68
-7
lines changed

8 files changed

+68
-7
lines changed

Diff for: Cargo.lock

+9-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ required-features = ["uefi_bin"]
3535

3636
[dependencies]
3737
xmas-elf = { version = "0.8.0", optional = true }
38-
x86_64 = { version = "0.14.7", optional = true, default-features = false, features = ["instructions", "inline_asm"] }
38+
x86_64 = { version = "0.14.9", optional = true, default-features = false, features = ["instructions", "inline_asm", "step_trait"] }
3939
usize_conversions = { version = "0.2.0", optional = true }
4040
bit_field = { version = "0.10.0", optional = true }
4141
log = { version = "0.4.8", optional = true }

Diff for: build.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,8 @@ mod binary {
366366
pub framebuffer_address: Option<AlignedAddress>,
367367
pub minimum_framebuffer_height: Option<usize>,
368368
pub minimum_framebuffer_width: Option<usize>,
369+
pub dynamic_range_start: Option<AlignedAddress>,
370+
pub dynamic_range_end: Option<AlignedAddress>,
369371
}
370372

371373
/// Convert to tokens suitable for initializing the `Config` struct.
@@ -387,6 +389,8 @@ mod binary {
387389
let framebuffer_address = optional(self.framebuffer_address);
388390
let minimum_framebuffer_height = optional(self.minimum_framebuffer_height);
389391
let minimum_framebuffer_width = optional(self.minimum_framebuffer_width);
392+
let dynamic_range_start = optional(self.dynamic_range_start);
393+
let dynamic_range_end = optional(self.dynamic_range_end);
390394

391395
tokens.extend(quote! { Config {
392396
map_physical_memory: #map_physical_memory,
@@ -400,7 +404,9 @@ mod binary {
400404
boot_info_address: #boot_info_address,
401405
framebuffer_address: #framebuffer_address,
402406
minimum_framebuffer_height: #minimum_framebuffer_height,
403-
minimum_framebuffer_width: #minimum_framebuffer_width
407+
minimum_framebuffer_width: #minimum_framebuffer_width,
408+
dynamic_range_start: #dynamic_range_start,
409+
dynamic_range_end: #dynamic_range_end,
404410
}});
405411
}
406412
}

Diff for: src/binary/level_4_entries.rs

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use core::{alloc::Layout, convert::TryInto};
1+
use core::{alloc::Layout, convert::TryInto, iter::Step};
22
use rand::{
33
distributions::{Distribution, Uniform},
44
seq::IteratorRandom,
@@ -70,6 +70,28 @@ impl UsedLevel4Entries {
7070
}
7171
}
7272

73+
// Mark everything before the dynamic range as unusable.
74+
if let Some(dynamic_range_start) = CONFIG.dynamic_range_start {
75+
let dynamic_range_start = VirtAddr::new(dynamic_range_start);
76+
let start_page: Page = Page::containing_address(dynamic_range_start);
77+
if let Some(unusable_page) = Step::backward_checked(start_page, 1) {
78+
for i in 0..=u16::from(unusable_page.p4_index()) {
79+
used.mark_p4_index_as_used(PageTableIndex::new(i));
80+
}
81+
}
82+
}
83+
84+
// Mark everything after the dynamic range as unusable.
85+
if let Some(dynamic_range_end) = CONFIG.dynamic_range_end {
86+
let dynamic_range_end = VirtAddr::new(dynamic_range_end);
87+
let end_page: Page = Page::containing_address(dynamic_range_end);
88+
if let Some(unusable_page) = Step::forward_checked(end_page, 1) {
89+
for i in u16::from(unusable_page.p4_index())..512 {
90+
used.mark_p4_index_as_used(PageTableIndex::new(i));
91+
}
92+
}
93+
}
94+
7395
used
7496
}
7597

Diff for: src/config.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const PAGE_SIZE: u64 = 4096;
3333
///
3434
/// All memory addresses are optional, even if their corresponding switch is enabled. If no
3535
/// address is specified, the bootloader will choose an unused entry of the level 4 page table
36-
/// at runtime.
36+
/// at runtime. The addresses can be restricted by setting the `dynamic-range` configuration key.
3737
#[derive(Debug)]
3838
pub struct Config {
3939
/// Whether to create a virtual mapping of the complete physical memory.
@@ -96,6 +96,14 @@ pub struct Config {
9696
/// `minimum_framebuffer_width` is supplied, and using the last available mode that
9797
/// fits them if 1 or more is set.
9898
pub minimum_framebuffer_width: Option<usize>,
99+
/// The lowest virtual address for dynamic addresses.
100+
///
101+
/// Defaults to `0`.
102+
pub dynamic_range_start: Option<u64>,
103+
/// The highest virtual address for dynamic addresses.
104+
///
105+
/// Defaults to `0xffff_ffff_ffff_f000`.
106+
pub dynamic_range_end: Option<u64>,
99107
}
100108

101109
#[cfg(feature = "binary")]

Diff for: src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ for all possible configuration options.
6767

6868
#![cfg_attr(not(feature = "builder"), no_std)]
6969
#![feature(maybe_uninit_slice)]
70+
#![feature(step_trait)]
7071
#![deny(unsafe_op_in_unsafe_fn)]
7172
#![warn(missing_docs)]
7273

Diff for: tests/test_kernels/higher_half/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,6 @@ edition = "2018"
88
bootloader = { path = "../../.." }
99
x86_64 = { version = "0.14.7", default-features = false, features = ["instructions", "inline_asm"] }
1010
uart_16550 = "0.2.10"
11+
12+
[package.metadata.bootloader]
13+
dynamic-range-start = "0xffff_8000_0000_0000"

Diff for: tests/test_kernels/higher_half/src/bin/verify_higher_half.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,25 @@ use test_kernel_higher_half::{exit_qemu, QemuExitCode};
77

88
entry_point!(kernel_main);
99

10-
fn kernel_main(_boot_info: &'static mut BootInfo) -> ! {
10+
fn kernel_main(boot_info: &'static mut BootInfo) -> ! {
1111
// verify that kernel is really running in the higher half of the address space
1212
// (set in `x86_64-higher_half.json` custom target)
1313
let rip = x86_64::registers::read_rip().as_u64();
1414
assert_eq!(rip & 0xffffffffffff0000, 0xffff800000000000);
15+
16+
// verify that the boot info is located in the higher half of the address space
17+
assert_eq!(
18+
(boot_info as *const _ as usize) & 0xffff800000000000,
19+
0xffff800000000000
20+
);
21+
22+
// verify that the stack is located in the higher half of the address space.
23+
let stack_addr = &rip;
24+
assert_eq!(
25+
(boot_info as *const _ as usize) & 0xffff800000000000,
26+
0xffff800000000000
27+
);
28+
1529
exit_qemu(QemuExitCode::Success);
1630
}
1731

0 commit comments

Comments
 (0)