Skip to content

Commit 2895f44

Browse files
authored
Merge pull request #175 from phil-opp/identity-map-gdt
Identity-map GDT into kernel address space
2 parents 6df1629 + 17ccbe2 commit 2895f44

File tree

4 files changed

+50
-1
lines changed

4 files changed

+50
-1
lines changed

Diff for: Changelog.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Unreleased
22

3+
- Identity-map GDT into kernel address space to fix `iretq` ([#175](https://github.com/rust-osdev/bootloader/pull/175))
34
- Uefi: Look for an ACPI2 RSDP first ([#174](https://github.com/rust-osdev/bootloader/pull/174))
45

56
# 0.10.5 – 2021-05-21

Diff for: src/binary/gdt.rs

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use x86_64::{
2+
instructions::segmentation,
3+
structures::{
4+
gdt::{Descriptor, GlobalDescriptorTable},
5+
paging::PhysFrame,
6+
},
7+
VirtAddr,
8+
};
9+
10+
pub fn create_and_load(frame: PhysFrame) {
11+
let phys_addr = frame.start_address();
12+
log::info!("Creating GDT at {:?}", phys_addr);
13+
let virt_addr = VirtAddr::new(phys_addr.as_u64()); // utilize identity mapping
14+
15+
let ptr: *mut GlobalDescriptorTable = virt_addr.as_mut_ptr();
16+
17+
let mut gdt = GlobalDescriptorTable::new();
18+
let code_selector = gdt.add_entry(Descriptor::kernel_code_segment());
19+
let data_selector = gdt.add_entry(Descriptor::kernel_data_segment());
20+
let gdt = unsafe {
21+
ptr.write(gdt);
22+
&*ptr
23+
};
24+
25+
gdt.load();
26+
unsafe {
27+
segmentation::set_cs(code_selector);
28+
segmentation::load_ds(data_selector);
29+
segmentation::load_es(data_selector);
30+
segmentation::load_ss(data_selector);
31+
}
32+
}

Diff for: src/binary/mod.rs

+13
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ pub mod bios;
2424
#[cfg(feature = "uefi_bin")]
2525
mod uefi;
2626

27+
mod gdt;
2728
/// Provides a frame allocator based on a BIOS or UEFI memory map.
2829
pub mod legacy_memory_region;
2930
/// Provides a type to keep track of used entries in a level 4 page table.
@@ -170,6 +171,18 @@ where
170171
}
171172
}
172173

174+
// create, load, and identity-map GDT (required for working `iretq`)
175+
let gdt_frame = frame_allocator
176+
.allocate_frame()
177+
.expect("failed to allocate GDT frame");
178+
gdt::create_and_load(gdt_frame);
179+
match unsafe {
180+
kernel_page_table.identity_map(gdt_frame, PageTableFlags::PRESENT, frame_allocator)
181+
} {
182+
Ok(tlb) => tlb.flush(),
183+
Err(err) => panic!("failed to identity map frame {:?}: {:?}", gdt_frame, err),
184+
}
185+
173186
// map framebuffer
174187
let framebuffer_virt_addr = if CONFIG.map_framebuffer {
175188
log::info!("Map framebuffer");

Diff for: tests/test_kernels/default_settings/src/bin/basic_boot.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ fn kernel_main(_boot_info: &'static mut BootInfo) -> ! {
1313

1414
/// This function is called on panic.
1515
#[panic_handler]
16-
fn panic(_info: &PanicInfo) -> ! {
16+
fn panic(info: &PanicInfo) -> ! {
17+
use core::fmt::Write;
18+
19+
let _ = writeln!(test_kernel_default_settings::serial(), "PANIC: {}", info);
1720
exit_qemu(QemuExitCode::Failed);
1821
}

0 commit comments

Comments
 (0)