Skip to content

Commit

Permalink
Switches from VMM GDT to kernel GDT (#992)
Browse files Browse the repository at this point in the history
  • Loading branch information
ultimaweapon committed Sep 21, 2024
1 parent 19eabaf commit 79aeff9
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 5 deletions.
1 change: 1 addition & 0 deletions src/obkrnl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ edition = "2021"

[dependencies]
anstyle = { version = "1.0.8", default-features = false }
bitfield-struct = "0.8.0"
hashbrown = "0.14.5"
macros = { path = "../macros" }
obconf = { path = "../obconf" }
Expand Down
3 changes: 3 additions & 0 deletions src/obkrnl/src/aarch64.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub unsafe fn setup_main_cpu() {
todo!()
}
15 changes: 10 additions & 5 deletions src/obkrnl/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ use core::mem::zeroed;
use core::panic::PanicInfo;
use obconf::{BootEnv, Config};

#[cfg_attr(target_arch = "aarch64", path = "aarch64.rs")]
#[cfg_attr(target_arch = "x86_64", path = "x86_64.rs")]
mod arch;
mod config;
mod console;
mod context;
Expand Down Expand Up @@ -37,24 +40,26 @@ extern crate alloc;
/// See PS4 kernel entry point for a reference.
#[allow(dead_code)]
#[cfg_attr(target_os = "none", no_mangle)]
extern "C" fn _start(env: &'static BootEnv, conf: &'static Config) -> ! {
unsafe extern "C" fn _start(env: &'static BootEnv, conf: &'static Config) -> ! {
// SAFETY: This function has a lot of restrictions. See Context documentation for more details.
unsafe { crate::config::setup(env, conf) };
crate::config::setup(env, conf);

info!("Starting Obliteration Kernel.");

self::arch::setup_main_cpu();

// Setup thread0 to represent this thread.
let thread0 = unsafe { Thread::new_bare() };
let thread0 = Thread::new_bare();

// Initialize foundations.
let pmgr = ProcMgr::new();

// Activate CPU context. We use a different mechanism here. The PS4 put all of pcpu at a global
// level but we put it on each CPU stack instead.
let thread0 = Arc::new(thread0);
let mut cx = unsafe { Context::new(0, thread0, pmgr.clone()) };
let mut cx = Context::new(0, thread0, pmgr.clone());

unsafe { cx.activate() };
cx.activate();

main(pmgr);
}
Expand Down
96 changes: 96 additions & 0 deletions src/obkrnl/src/x86_64.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
use bitfield_struct::bitfield;
use core::arch::global_asm;

pub unsafe fn setup_main_cpu() {
// Switch GDT from bootloader GDT to our own.
static GDT: [SegmentDescriptor; 3] = [
// Null descriptor.
SegmentDescriptor::new(),
// Code segment.
SegmentDescriptor::new()
.with_ty(0b1000) // This required somehow although the docs said it is ignored.
.with_s(true) // Same here.
.with_p(true)
.with_l(true), // 64-bit mode.
// Data segment.
SegmentDescriptor::new()
.with_ty(0b0010) // This required somehow although the docs said it is ignored.
.with_s(true) // Same here.
.with_p(true),
];

set_gdtr(
&Gdtr {
limit: (size_of_val(&GDT) - 1).try_into().unwrap(),
addr: GDT.as_ptr(),
},
SegmentSelector::new().with_si(1),
SegmentSelector::new().with_si(2),
);
}

extern "C" {
fn set_gdtr(v: &Gdtr, code: SegmentSelector, data: SegmentSelector);
}

// See lgdt on the PS4 for a reference.
global_asm!(
"set_gdtr:",
"lgdt qword ptr [rdi]",
"mov ds, dx",
"mov es, dx",
"mov fs, dx",
"mov gs, dx",
"mov ss, dx",
"pop rax", // Return address.
"push rsi", // Code segment selector.
"push rax",
"retfq" // Set CS then return.
);

/// Raw value of a Global Descriptor-Table Register.
///
/// See Global Descriptor-Table Register section on AMD64 Architecture Programmer's Manual Volume 2
/// for details.
#[repr(C, packed)]
struct Gdtr {
limit: u16,
addr: *const SegmentDescriptor,
}

/// Raw value of a Segment Descriptor.
///
/// See Legacy Segment Descriptors section on AMD64 Architecture Programmer's Manual Volume 2 for
/// more details.
#[bitfield(u64)]
struct SegmentDescriptor {
limit1: u16,
#[bits(24)]
base1: u32,
#[bits(4)]
ty: u8,
s: bool,
#[bits(2)]
dpl: u8,
p: bool,
#[bits(4)]
limit2: u8,
avl: bool,
l: bool,
db: bool,
g: bool,
base2: u8,
}

/// Raw value of a Segment Selector (e.g. `CS` and `DS` register).
///
/// See Segment Selectors section on AMD64 Architecture Programmer's Manual Volume 2 for more
/// details.
#[bitfield(u16)]
struct SegmentSelector {
#[bits(2)]
rpl: u8,
ti: bool,
#[bits(13)]
si: u16,
}

0 comments on commit 79aeff9

Please sign in to comment.