Skip to content

Commit 867672b

Browse files
committed
Identity-map GDT into kernel address space
1 parent 6df1629 commit 867672b

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

src/binary/gdt.rs

Lines changed: 32 additions & 0 deletions
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+
}

src/binary/mod.rs

Lines changed: 13 additions & 0 deletions
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");

0 commit comments

Comments
 (0)