Skip to content

Commit fd7b2cf

Browse files
committed
Adjust and merge PR #219 into next
2 parents 71accbb + 1ee7c35 commit fd7b2cf

File tree

3 files changed

+117
-45
lines changed

3 files changed

+117
-45
lines changed

common/src/level_4_entries.rs

+79-19
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
use core::convert::TryInto;
1+
use crate::BootInfo;
2+
use bootloader_api::{config, info::MemoryRegion, BootloaderConfig};
3+
use core::{alloc::Layout, convert::TryInto};
4+
use usize_conversions::IntoUsize;
25
use x86_64::{
3-
structures::paging::{Page, PageTableIndex},
4-
VirtAddr,
6+
structures::paging::{Page, PageTableIndex, Size4KiB},
7+
PhysAddr, VirtAddr,
58
};
69
use xmas_elf::program::ProgramHeader;
710

@@ -13,35 +16,92 @@ pub struct UsedLevel4Entries {
1316
}
1417

1518
impl UsedLevel4Entries {
16-
/// Initializes a new instance from the given ELF program segments.
19+
/// Initializes a new instance.
1720
///
18-
/// Marks the virtual address range of all segments as used.
19-
pub fn new<'a>(
20-
segments: impl Iterator<Item = ProgramHeader<'a>>,
21-
virtual_address_offset: u64,
21+
/// Marks the statically configured virtual address ranges from the config as used.
22+
pub fn new(
23+
max_phys_addr: PhysAddr,
24+
regions_len: usize,
25+
framebuffer_size: usize,
26+
config: &BootloaderConfig,
2227
) -> Self {
2328
let mut used = UsedLevel4Entries {
2429
entry_state: [false; 512],
2530
};
2631

2732
used.entry_state[0] = true; // TODO: Can we do this dynamically?
2833

29-
for segment in segments {
30-
let start_page: Page = Page::containing_address(VirtAddr::new(
31-
segment.virtual_addr() + virtual_address_offset,
32-
));
33-
let end_page: Page = Page::containing_address(VirtAddr::new(
34-
segment.virtual_addr() + virtual_address_offset + segment.mem_size(),
35-
));
36-
37-
for p4_index in u64::from(start_page.p4_index())..=u64::from(end_page.p4_index()) {
38-
used.entry_state[p4_index as usize] = true;
39-
}
34+
// Mark the statically configured ranges from the config as used.
35+
36+
if let Some(config::Mapping::FixedAddress(physical_memory_offset)) =
37+
config.mappings.physical_memory
38+
{
39+
used.mark_range_as_used(physical_memory_offset, max_phys_addr.as_u64().into_usize());
40+
}
41+
42+
if let Some(config::Mapping::FixedAddress(recursive_address)) =
43+
config.mappings.page_table_recursive
44+
{
45+
let recursive_index = VirtAddr::new(recursive_address).p4_index();
46+
used.mark_p4_index_as_used(recursive_index);
47+
}
48+
49+
if let config::Mapping::FixedAddress(kernel_stack_address) = config.mappings.kernel_stack {
50+
used.mark_range_as_used(kernel_stack_address, config.kernel_stack_size);
51+
}
52+
53+
if let config::Mapping::FixedAddress(boot_info_address) = config.mappings.boot_info {
54+
let boot_info_layout = Layout::new::<BootInfo>();
55+
let regions = regions_len + 1; // one region might be split into used/unused
56+
let memory_regions_layout = Layout::array::<MemoryRegion>(regions).unwrap();
57+
let (combined, _) = boot_info_layout.extend(memory_regions_layout).unwrap();
58+
59+
used.mark_range_as_used(boot_info_address, combined.size());
60+
}
61+
62+
if let config::Mapping::FixedAddress(framebuffer_address) = config.mappings.framebuffer {
63+
used.mark_range_as_used(framebuffer_address, framebuffer_size);
4064
}
4165

4266
used
4367
}
4468

69+
/// Mark all p4 entries in the range `[address..address+size)` as used.
70+
///
71+
/// `size` can be a `u64` or `usize`.
72+
fn mark_range_as_used<S>(&mut self, address: u64, size: S)
73+
where
74+
VirtAddr: core::ops::Add<S, Output = VirtAddr>,
75+
{
76+
let start = VirtAddr::new(address);
77+
let end_inclusive = (start + size) - 1usize;
78+
let start_page = Page::<Size4KiB>::containing_address(start);
79+
let end_page_inclusive = Page::<Size4KiB>::containing_address(end_inclusive);
80+
81+
for p4_index in u16::from(start_page.p4_index())..=u16::from(end_page_inclusive.p4_index())
82+
{
83+
self.mark_p4_index_as_used(PageTableIndex::new(p4_index));
84+
}
85+
}
86+
87+
fn mark_p4_index_as_used(&mut self, p4_index: PageTableIndex) {
88+
self.entry_state[usize::from(p4_index)] = true;
89+
}
90+
91+
/// Marks the virtual address range of all segments as used.
92+
pub fn mark_segments<'a>(
93+
&mut self,
94+
segments: impl Iterator<Item = ProgramHeader<'a>>,
95+
virtual_address_offset: u64,
96+
) {
97+
for segment in segments.filter(|s| s.mem_size() > 0) {
98+
self.mark_range_as_used(
99+
segment.virtual_addr() + virtual_address_offset,
100+
segment.mem_size(),
101+
);
102+
}
103+
}
104+
45105
/// Returns a unused level 4 entry and marks it as used.
46106
///
47107
/// Since this method marks each returned index as used, it can be used multiple times

common/src/lib.rs

+30-14
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,7 @@ use bootloader_api::{
77
info::{FrameBuffer, FrameBufferInfo, MemoryRegion, TlsTemplate},
88
BootInfo, BootloaderConfig,
99
};
10-
use core::{
11-
arch::asm,
12-
mem::{self, MaybeUninit},
13-
slice,
14-
};
10+
use core::{alloc::Layout, arch::asm, mem::MaybeUninit, slice};
1511
use level_4_entries::UsedLevel4Entries;
1612
use usize_conversions::FromUsize;
1713
use x86_64::{
@@ -105,6 +101,7 @@ where
105101
&mut page_tables,
106102
system_info.framebuffer_addr,
107103
system_info.framebuffer_info.byte_len,
104+
&config,
108105
);
109106
let boot_info = create_boot_info(
110107
&config,
@@ -136,22 +133,34 @@ pub fn set_up_mappings<I, D>(
136133
page_tables: &mut PageTables,
137134
framebuffer_addr: PhysAddr,
138135
framebuffer_size: usize,
136+
config: &BootloaderConfig,
139137
) -> Mappings
140138
where
141139
I: ExactSizeIterator<Item = D> + Clone,
142140
D: LegacyMemoryRegion,
143141
{
144142
let kernel_page_table = &mut page_tables.kernel;
145143

144+
let mut used_entries = UsedLevel4Entries::new(
145+
frame_allocator.max_phys_addr(),
146+
frame_allocator.len(),
147+
framebuffer_size,
148+
config,
149+
);
150+
146151
// Enable support for the no-execute bit in page tables.
147152
enable_nxe_bit();
148153
// Make the kernel respect the write-protection bits even when in ring 0 by default
149154
enable_write_protect_bit();
150155

151156
let config = kernel.config;
152-
let (entry_point, tls_template, mut used_entries) =
153-
load_kernel::load_kernel(kernel, kernel_page_table, frame_allocator)
154-
.expect("no entry point");
157+
let (entry_point, tls_template) = load_kernel::load_kernel(
158+
kernel,
159+
kernel_page_table,
160+
frame_allocator,
161+
&mut used_entries,
162+
)
163+
.expect("no entry point");
155164
log::info!("Entry point at: {:#x}", entry_point.as_u64());
156165

157166
// create a stack
@@ -331,13 +340,20 @@ where
331340

332341
// allocate and map space for the boot info
333342
let (boot_info, memory_regions) = {
334-
let boot_info_addr = mapping_addr(config.mappings.boot_info, &mut mappings.used_entries);
335-
let boot_info_end = boot_info_addr + mem::size_of::<BootInfo>();
336-
let memory_map_regions_addr =
337-
boot_info_end.align_up(u64::from_usize(mem::align_of::<MemoryRegion>()));
343+
let boot_info_layout = Layout::new::<BootInfo>();
338344
let regions = frame_allocator.len() + 1; // one region might be split into used/unused
339-
let memory_map_regions_end =
340-
memory_map_regions_addr + regions * mem::size_of::<MemoryRegion>();
345+
let memory_regions_layout = Layout::array::<MemoryRegion>(regions).unwrap();
346+
let (combined, memory_regions_offset) =
347+
boot_info_layout.extend(memory_regions_layout).unwrap();
348+
349+
let boot_info_addr = mapping_addr(config.mappings.boot_info, &mut mappings.used_entries);
350+
assert!(
351+
boot_info_addr.is_aligned(u64::from_usize(combined.align())),
352+
"boot info addr is not properly aligned"
353+
);
354+
355+
let memory_map_regions_addr = boot_info_addr + memory_regions_offset;
356+
let memory_map_regions_end = boot_info_addr + combined.size();
341357

342358
let start_page = Page::containing_address(boot_info_addr);
343359
let end_page = Page::containing_address(memory_map_regions_end - 1u64);

common/src/load_kernel.rs

+8-12
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ where
4343
kernel: Kernel<'a>,
4444
page_table: &'a mut M,
4545
frame_allocator: &'a mut F,
46+
used_entries: &mut UsedLevel4Entries,
4647
) -> Result<Self, &'static str> {
4748
log::info!("Elf file loaded at {:#p}", kernel.elf.input);
4849
let kernel_offset = PhysAddr::new(&kernel.elf.input[0] as *const u8 as u64);
@@ -56,11 +57,13 @@ where
5657
header::Type::None => unimplemented!(),
5758
header::Type::Relocatable => unimplemented!(),
5859
header::Type::Executable => 0,
59-
header::Type::SharedObject => 0x400000,
60+
header::Type::SharedObject => used_entries.get_free_address().as_u64(),
6061
header::Type::Core => unimplemented!(),
6162
header::Type::ProcessorSpecific(_) => unimplemented!(),
6263
};
6364

65+
used_entries.mark_segments(elf_file.program_iter(), virtual_address_offset);
66+
6467
header::sanity_check(&elf_file)?;
6568
let loader = Loader {
6669
elf_file,
@@ -120,13 +123,6 @@ where
120123
fn entry_point(&self) -> VirtAddr {
121124
VirtAddr::new(self.elf_file.header.pt2.entry_point() + self.inner.virtual_address_offset)
122125
}
123-
124-
fn used_level_4_entries(&self) -> UsedLevel4Entries {
125-
UsedLevel4Entries::new(
126-
self.elf_file.program_iter(),
127-
self.inner.virtual_address_offset,
128-
)
129-
}
130126
}
131127

132128
impl<'a, M, F> Inner<'a, M, F>
@@ -513,10 +509,10 @@ pub fn load_kernel(
513509
kernel: Kernel<'_>,
514510
page_table: &mut (impl MapperAllSizes + Translate),
515511
frame_allocator: &mut impl FrameAllocator<Size4KiB>,
516-
) -> Result<(VirtAddr, Option<TlsTemplate>, UsedLevel4Entries), &'static str> {
517-
let mut loader = Loader::new(kernel, page_table, frame_allocator)?;
512+
used_entries: &mut UsedLevel4Entries,
513+
) -> Result<(VirtAddr, Option<TlsTemplate>), &'static str> {
514+
let mut loader = Loader::new(kernel, page_table, frame_allocator, used_entries)?;
518515
let tls_template = loader.load_segments()?;
519-
let used_entries = loader.used_level_4_entries();
520516

521-
Ok((loader.entry_point(), tls_template, used_entries))
517+
Ok((loader.entry_point(), tls_template))
522518
}

0 commit comments

Comments
 (0)