Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cpu: fix IDT and GDT lifetimes on load methods #366

Merged
merged 2 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 33 additions & 29 deletions kernel/src/cpu/gdt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ pub struct GDT {

impl GDT {
pub const fn new() -> Self {
GDT {
Self {
entries: [
GDTEntry::null(),
GDTEntry::code_64_kernel(),
Expand All @@ -74,20 +74,33 @@ impl GDT {
}
}

pub fn base_limit(&self) -> (u64, u32) {
let gdt_entries = GDT_SIZE as usize;
let base = (self as *const GDT) as u64;
let limit = ((mem::size_of::<u64>() * gdt_entries) - 1) as u32;
(base, limit)
unsafe fn set_tss_entry(&mut self, desc0: GDTEntry, desc1: GDTEntry) {
let idx = (SVSM_TSS / 8) as usize;

let tss_entries = &self.entries[idx..idx + 1].as_mut_ptr();

tss_entries.add(0).write_volatile(desc0);
tss_entries.add(1).write_volatile(desc1);
}

fn descriptor(&self) -> GDTDesc {
GDTDesc {
size: (GDT_SIZE * 8) - 1,
addr: VirtAddr::from(self.entries.as_ptr()),
unsafe fn clear_tss_entry(&mut self) {
self.set_tss_entry(GDTEntry::null(), GDTEntry::null());
}

pub fn load_tss(&mut self, tss: &X86Tss) {
let (desc0, desc1) = tss.to_gdt_entry();

unsafe {
self.set_tss_entry(desc0, desc1);
asm!("ltr %ax", in("ax") SVSM_TSS, options(att_syntax));
self.clear_tss_entry()
}
}
}

impl ReadLockGuard<'static, GDT> {
/// Load a GDT. Its lifetime must be static so that its entries are
/// always available to the CPU.
pub fn load(&self) {
let gdt_desc = self.descriptor();
unsafe {
Expand Down Expand Up @@ -115,27 +128,18 @@ impl GDT {
}
}

unsafe fn set_tss_entry(&mut self, desc0: GDTEntry, desc1: GDTEntry) {
let idx = (SVSM_TSS / 8) as usize;

let tss_entries = &self.entries[idx..idx + 1].as_mut_ptr();

tss_entries.add(0).write_volatile(desc0);
tss_entries.add(1).write_volatile(desc1);
}

unsafe fn clear_tss_entry(&mut self) {
self.set_tss_entry(GDTEntry::null(), GDTEntry::null());
fn descriptor(&self) -> GDTDesc {
GDTDesc {
size: (GDT_SIZE * 8) - 1,
addr: VirtAddr::from(self.entries.as_ptr()),
}
}

pub fn load_tss(&mut self, tss: &X86Tss) {
let (desc0, desc1) = tss.to_gdt_entry();

unsafe {
self.set_tss_entry(desc0, desc1);
asm!("ltr %ax", in("ax") SVSM_TSS, options(att_syntax));
self.clear_tss_entry()
}
pub fn base_limit(&self) -> (u64, u32) {
let gdt_entries = GDT_SIZE as usize;
let base: *const GDT = core::ptr::from_ref(self);
let limit = ((mem::size_of::<u64>() * gdt_entries) - 1) as u32;
(base as u64, limit)
}
}

Expand Down
26 changes: 15 additions & 11 deletions kernel/src/cpu/idt/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,18 @@ impl IDT {

self
}
}

impl Default for IDT {
fn default() -> Self {
Self::new()
}
}

pub fn load(&self) -> &Self {
impl WriteLockGuard<'static, IDT> {
/// Load an IDT. Its lifetime must be static so that its entries are
/// always available to the CPU.
pub fn load(&self) {
let desc: IdtDesc = IdtDesc {
size: (IDT_ENTRIES * 16) as u16,
address: VirtAddr::from(self.entries.as_ptr()),
Expand All @@ -186,20 +196,14 @@ impl IDT {
unsafe {
asm!("lidt (%rax)", in("rax") &desc, options(att_syntax));
}

self
}
}

impl ReadLockGuard<'static, IDT> {
pub fn base_limit(&self) -> (u64, u32) {
let base = (self as *const IDT) as u64;
let base: *const IDT = core::ptr::from_ref(self);
joergroedel marked this conversation as resolved.
Show resolved Hide resolved
let limit = (IDT_ENTRIES * mem::size_of::<IdtEntry>()) as u32;
(base, limit)
}
}

impl Default for IDT {
fn default() -> Self {
Self::new()
(base as u64, limit)
}
}

Expand Down
12 changes: 6 additions & 6 deletions kernel/src/cpu/idt/stage2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ use core::ptr::addr_of;

pub fn early_idt_init_no_ghcb() {
unsafe {
idt_mut()
.init(addr_of!(stage2_idt_handler_array_no_ghcb), 32)
.load();
let mut idt = idt_mut();
idt.init(addr_of!(stage2_idt_handler_array_no_ghcb), 32);
idt.load();
}
}

pub fn early_idt_init() {
unsafe {
idt_mut()
.init(addr_of!(stage2_idt_handler_array), 32)
.load();
let mut idt = idt_mut();
idt.init(addr_of!(stage2_idt_handler_array), 32);
idt.load();
}
}

Expand Down
4 changes: 2 additions & 2 deletions kernel/src/cpu/idt/svsm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ use super::super::extable::handle_exception_table;
use super::super::percpu::{current_task, this_cpu};
use super::super::tss::IST_DF;
use super::super::vc::handle_vc_exception;
use super::common::PF_ERROR_WRITE;
use super::common::{
idt_mut, user_mode, IdtEntry, AC_VECTOR, BP_VECTOR, BR_VECTOR, CP_VECTOR, DB_VECTOR, DE_VECTOR,
DF_VECTOR, GP_VECTOR, HV_VECTOR, MCE_VECTOR, MF_VECTOR, NMI_VECTOR, NM_VECTOR, NP_VECTOR,
OF_VECTOR, PF_VECTOR, SS_VECTOR, SX_VECTOR, TS_VECTOR, UD_VECTOR, VC_VECTOR, XF_VECTOR,
OF_VECTOR, PF_ERROR_WRITE, PF_VECTOR, SS_VECTOR, SX_VECTOR, TS_VECTOR, UD_VECTOR, VC_VECTOR,
XF_VECTOR,
};
use crate::address::VirtAddr;
use crate::cpu::percpu::this_cpu_unsafe;
Expand Down
Loading