Skip to content

Commit a128a08

Browse files
committed
[interrupt-handlers] added GDT/GDTR
- added GdtEntry struct for GDT static mut global var, - added null, kernel code, and kernel data segments to GDT, - added code to load the GDT, and - added calls to init_idt, load_idt, and load_gdt to entrypoint. Signed-off-by: danbugs <[email protected]>
1 parent 801d285 commit a128a08

File tree

3 files changed

+107
-3
lines changed

3 files changed

+107
-3
lines changed

src/hyperlight_guest/src/entrypoint.rs

+6
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ use hyperlight_common::mem::{HyperlightPEB, RunMode};
2222
use log::LevelFilter;
2323
use spin::Once;
2424

25+
use crate::gdt::load_gdt;
2526
use crate::guest_error::reset_error;
2627
use crate::guest_function_call::dispatch_function;
2728
use crate::guest_logger::init_logger;
2829
use crate::host_function_call::{outb, OutBAction};
30+
use crate::idtr::load_idt;
2931
use crate::{
3032
__security_cookie, HEAP_ALLOCATOR, MIN_STACK_ADDRESS, OS_PAGE_SIZE, OUTB_PTR,
3133
OUTB_PTR_WITH_CONTEXT, P_PEB, RUNNING_MODE,
@@ -104,6 +106,10 @@ pub extern "win64" fn entrypoint(peb_address: u64, seed: u64, ops: u64, max_log_
104106
// It also means that should we change the layout of the struct in the future, we
105107
// don't have to change the assembly code.
106108
MIN_STACK_ADDRESS = (*peb_ptr).gueststackData.minUserStackAddress;
109+
110+
// Setup GDT and IDT
111+
load_gdt();
112+
load_idt();
107113
}
108114
RunMode::InProcessLinux | RunMode::InProcessWindows => {
109115
RUNNING_MODE = (*peb_ptr).runMode;

src/hyperlight_guest/src/gdt.rs

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
Copyright 2024 The Hyperlight Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
use core::arch::asm;
18+
use core::ptr::addr_of;
19+
20+
/// Entry in the Global Descriptor Table (GDT)
21+
/// For reference, see page 3-10 Vol. 3A of Intel 64 and IA-32
22+
/// Architectures Software Developer's Manual, figure 3-8
23+
/// (https://i.imgur.com/1i9xUmx.png).
24+
/// From the bottom, we have:
25+
/// - segment limit 15..0 = limit_low
26+
/// - base address 31..16 = base_low
27+
/// - base 23..16 = base_middle
28+
/// - p dpl s type 15..8 = access
29+
/// - p d/b l avl seg. limit 23..16 = flags_limit
30+
/// - base 31..24 = base_high
31+
#[repr(C, align(8))]
32+
pub struct GdtEntry {
33+
limit_low: u16,
34+
base_low: u16,
35+
base_middle: u8,
36+
access: u8,
37+
flags_limit: u8,
38+
base_high: u8,
39+
}
40+
41+
impl GdtEntry {
42+
/// Creates a new GDT entry.
43+
pub const fn new(base: u32, limit: u32, access: u8, flags: u8) -> Self {
44+
Self {
45+
base_low: (base & 0xffff) as u16,
46+
base_middle: ((base >> 16) & 0xff) as u8,
47+
base_high: ((base >> 24) & 0xff) as u8,
48+
limit_low: (limit & 0xffff) as u16,
49+
flags_limit: (((limit >> 16) & 0x0f) as u8) | ((flags & 0x0f) << 4),
50+
access,
51+
}
52+
}
53+
}
54+
55+
// Global Descriptor Table (GDT)
56+
// For reference, see page 2-3 Vol. 3A of Intel 64 and IA-32
57+
// Architectures Software Developer's Manual.
58+
static mut GDT: [GdtEntry; 3] = [
59+
// Null descriptor
60+
GdtEntry::new(0, 0, 0, 0),
61+
// Kernel Code Segment (0x08)
62+
GdtEntry::new(0, 0, 0x9A, 0xA),
63+
// Kernel Data Segment (0x10)
64+
GdtEntry::new(0, 0, 0x92, 0xC),
65+
];
66+
67+
/// GDTR (GDT pointer)
68+
#[repr(C, packed)]
69+
struct GdtPointer {
70+
size: u16,
71+
base: u64,
72+
}
73+
74+
/// Load the GDT
75+
pub unsafe fn load_gdt() {
76+
let gdt_ptr = GdtPointer {
77+
size: (core::mem::size_of::<[GdtEntry; 3]>() - 1) as u16,
78+
base: addr_of!(GDT) as *const _ as u64,
79+
};
80+
81+
asm!(
82+
"lgdt [{0}]",
83+
"mov ax, 0x10", // Load data segment registers
84+
"mov ds, ax",
85+
"mov es, ax",
86+
"mov fs, ax",
87+
"mov gs, ax",
88+
"mov ss, ax",
89+
"push 0x08", // Push CS (kernel code segment)
90+
"lea rax, [2f + rip]", // Load the next instruction's address
91+
"push rax", // Push address onto stack
92+
"retfq", // Far return to update CS
93+
"2:", // Label for continued execution
94+
in(reg) &gdt_ptr,
95+
options(nostack, preserves_flags)
96+
);
97+
}

src/hyperlight_guest/src/lib.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,12 @@ pub mod setjmp;
5050

5151
pub mod chkstk;
5252
pub mod error;
53-
pub mod logging;
54-
pub mod interrupt_entry;
55-
pub mod interrupt_handlers;
53+
pub mod gdt;
5654
pub mod idt;
5755
pub mod idtr;
56+
pub mod interrupt_entry;
57+
pub mod interrupt_handlers;
58+
pub mod logging;
5859

5960
// Unresolved symbols
6061
///cbindgen:ignore

0 commit comments

Comments
 (0)