Skip to content

Commit

Permalink
Merge pull request #224 from joergroedel/mutable-static
Browse files Browse the repository at this point in the history
Get rid of some mutable global statics
  • Loading branch information
joergroedel authored Jan 25, 2024
2 parents 8b633c4 + 5ffc83e commit c6bd164
Show file tree
Hide file tree
Showing 15 changed files with 332 additions and 203 deletions.
174 changes: 108 additions & 66 deletions src/cpu/gdt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,98 +4,140 @@
//
// Author: Joerg Roedel <[email protected]>

use super::tss::{X86Tss, TSS_LIMIT};
use super::tss::X86Tss;
use crate::address::VirtAddr;
use crate::locking::{RWLock, ReadLockGuard, WriteLockGuard};
use crate::types::{SVSM_CS, SVSM_DS, SVSM_TSS};
use core::arch::asm;
use core::mem;

#[repr(C, packed(2))]
#[derive(Clone, Copy, Debug)]
pub struct GdtDesc {
struct GDTDesc {
size: u16,
addr: VirtAddr,
}

const GDT_SIZE: u16 = 8;

static mut GDT: [u64; GDT_SIZE as usize] = [
0,
0x00af9a000000ffff, // 64-bit code segment
0x00cf92000000ffff, // 64-bit data segment
0, // Reserved for User code
0, // Reserver for User data
0, // Reverved
0, // TSS
0, // TSS continued
];
#[derive(Copy, Clone, Debug)]
pub struct GDTEntry(u64);

pub fn load_tss(tss: &X86Tss) {
let addr = (tss as *const X86Tss) as u64;
impl GDTEntry {
pub const fn from_raw(entry: u64) -> Self {
Self(entry)
}

let mut desc0: u64 = 0;
let mut desc1: u64 = 0;
pub fn to_raw(&self) -> u64 {
self.0
}

// Limit
desc0 |= TSS_LIMIT & 0xffffu64;
desc0 |= ((TSS_LIMIT >> 16) & 0xfu64) << 48;
pub const fn null() -> Self {
Self(0u64)
}

// Address
desc0 |= (addr & 0x00ff_ffffu64) << 16;
desc0 |= (addr & 0xff00_0000u64) << 32;
desc1 |= addr >> 32;
pub const fn code_64_kernel() -> Self {
Self(0x00af9a000000ffffu64)
}

// Present
desc0 |= 1u64 << 47;
pub const fn data_64_kernel() -> Self {
Self(0x00cf92000000ffffu64)
}
}

// Type
desc0 |= 0x9u64 << 40;
const GDT_SIZE: u16 = 8;

unsafe {
let idx = (SVSM_TSS / 8) as usize;
GDT[idx] = desc0;
GDT[idx + 1] = desc1;
#[derive(Copy, Clone, Debug)]
pub struct GDT {
entries: [GDTEntry; GDT_SIZE as usize],
}

asm!("ltr %ax", in("ax") SVSM_TSS, options(att_syntax));
impl GDT {
pub const fn new() -> Self {
GDT {
entries: [
GDTEntry::null(),
GDTEntry::code_64_kernel(),
GDTEntry::data_64_kernel(),
GDTEntry::null(),
GDTEntry::null(),
GDTEntry::null(),
GDTEntry::null(),
GDTEntry::null(),
],
}
}
}

pub fn gdt_base_limit() -> (u64, u32) {
unsafe {
pub fn base_limit(&self) -> (u64, u32) {
let gdt_entries = GDT_SIZE as usize;
let base = (&GDT as *const [u64; GDT_SIZE as usize]) as u64;
let base = (self as *const GDT) as u64;
let limit = ((mem::size_of::<u64>() * gdt_entries) - 1) as u32;
(base, limit)
}
}

pub fn load_gdt() {
unsafe {
let gdt_desc: GdtDesc = GdtDesc {
fn descriptor(&self) -> GDTDesc {
GDTDesc {
size: (GDT_SIZE * 8) - 1,
addr: VirtAddr::from(GDT.as_ptr()),
};

asm!(r#" /* Load GDT */
lgdt (%rax)
/* Reload data segments */
movw %cx, %ds
movw %cx, %es
movw %cx, %fs
movw %cx, %gs
movw %cx, %ss
/* Reload code segment */
pushq %rdx
leaq 1f(%rip), %rax
pushq %rax
lretq
1:
"#,
in("rax") &gdt_desc,
in("rdx") SVSM_CS,
in("rcx") SVSM_DS,
options(att_syntax));
addr: VirtAddr::from(self.entries.as_ptr()),
}
}

pub fn load(&self) {
let gdt_desc = self.descriptor();
unsafe {
asm!(r#" /* Load GDT */
lgdt (%rax)
/* Reload data segments */
movw %cx, %ds
movw %cx, %es
movw %cx, %fs
movw %cx, %gs
movw %cx, %ss
/* Reload code segment */
pushq %rdx
leaq 1f(%rip), %rax
pushq %rax
lretq
1:
"#,
in("rax") &gdt_desc,
in("rdx") SVSM_CS,
in("rcx") SVSM_DS,
options(att_syntax));
}
}

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

self.entries[idx] = desc0;
self.entries[idx + 1] = desc1;
}

fn clear_tss_entry(&mut self) {
let idx = (SVSM_TSS / 8) as usize;

self.entries[idx] = GDTEntry::null();
self.entries[idx + 1] = GDTEntry::null();
}

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

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

static GDT: RWLock<GDT> = RWLock::new(GDT::new());

pub fn gdt() -> ReadLockGuard<'static, GDT> {
GDT.lock_read()
}

pub fn gdt_mut() -> WriteLockGuard<'static, GDT> {
GDT.lock_write()
}
63 changes: 50 additions & 13 deletions src/cpu/idt/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use crate::address::{Address, VirtAddr};
use crate::cpu::registers::{X86GeneralRegs, X86InterruptFrame};
use crate::locking::{RWLock, ReadLockGuard, WriteLockGuard};
use crate::types::SVSM_CS;
use core::arch::{asm, global_asm};
use core::mem;
Expand Down Expand Up @@ -104,27 +105,63 @@ struct IdtDesc {
address: VirtAddr,
}

pub type Idt = [IdtEntry; IDT_ENTRIES];
#[derive(Copy, Clone, Debug)]
pub struct IDT {
entries: [IdtEntry; IDT_ENTRIES],
}

pub static mut GLOBAL_IDT: Idt = [IdtEntry::no_handler(); IDT_ENTRIES];
impl IDT {
pub const fn new() -> Self {
IDT {
entries: [IdtEntry::no_handler(); IDT_ENTRIES],
}
}

pub fn idt_base_limit() -> (u64, u32) {
unsafe {
let base = (&GLOBAL_IDT as *const Idt) as u64;
pub fn init(&mut self, handler_array: *const u8, size: usize) -> &mut Self {
// Set IDT handlers
let handlers = VirtAddr::from(handler_array);

for idx in 0..size {
self.set_entry(idx, IdtEntry::entry(handlers + (32 * idx)));
}

self
}

pub fn set_entry(&mut self, idx: usize, entry: IdtEntry) -> &mut Self {
self.entries[idx] = entry;

self
}

pub fn load(&self) -> &Self {
let desc: IdtDesc = IdtDesc {
size: (IDT_ENTRIES * 16) as u16,
address: VirtAddr::from(self.entries.as_ptr()),
};

unsafe {
asm!("lidt (%rax)", in("rax") &desc, options(att_syntax));
}

self
}

pub fn base_limit(&self) -> (u64, u32) {
let base = (self as *const IDT) as u64;
let limit = (IDT_ENTRIES * mem::size_of::<IdtEntry>()) as u32;
(base, limit)
}
}

pub fn load_idt(idt: &Idt) {
let desc: IdtDesc = IdtDesc {
size: (IDT_ENTRIES * 16) as u16,
address: VirtAddr::from(idt.as_ptr()),
};
static IDT: RWLock<IDT> = RWLock::new(IDT::new());

unsafe {
asm!("lidt (%rax)", in("rax") &desc, options(att_syntax));
}
pub fn idt() -> ReadLockGuard<'static, IDT> {
IDT.lock_read()
}

pub fn idt_mut() -> WriteLockGuard<'static, IDT> {
IDT.lock_write()
}

pub fn triple_fault() {
Expand Down
2 changes: 2 additions & 0 deletions src/cpu/idt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@
pub mod common;
pub mod stage2;
pub mod svsm;

pub use common::{idt, idt_mut};
24 changes: 7 additions & 17 deletions src/cpu/idt/stage2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,25 @@
//
// Author: Joerg Roedel <[email protected]>

use super::common::{load_idt, Idt, IdtEntry, DF_VECTOR, GLOBAL_IDT, HV_VECTOR, VC_VECTOR};
use crate::address::VirtAddr;
use super::common::{idt_mut, DF_VECTOR, HV_VECTOR, VC_VECTOR};
use crate::cpu::control_regs::read_cr2;
use crate::cpu::vc::{stage2_handle_vc_exception, stage2_handle_vc_exception_no_ghcb};
use crate::cpu::X86ExceptionContext;
use core::arch::global_asm;

fn init_idt(idt: &mut Idt, handler_array: *const u8) {
// Set IDT handlers
let handlers = VirtAddr::from(handler_array);
for (i, entry) in idt.iter_mut().enumerate() {
*entry = IdtEntry::entry(handlers + (32 * i));
}
}

pub fn early_idt_init_no_ghcb() {
unsafe {
init_idt(
&mut GLOBAL_IDT,
&stage2_idt_handler_array_no_ghcb as *const u8,
);
load_idt(&GLOBAL_IDT);
idt_mut()
.init(&stage2_idt_handler_array_no_ghcb as *const u8, 32)
.load();
}
}

pub fn early_idt_init() {
unsafe {
init_idt(&mut GLOBAL_IDT, &stage2_idt_handler_array as *const u8);
load_idt(&GLOBAL_IDT);
idt_mut()
.init(&stage2_idt_handler_array as *const u8, 32)
.load();
}
}

Expand Down
29 changes: 12 additions & 17 deletions src/cpu/idt/svsm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,39 +11,34 @@ use super::super::tss::IST_DF;
use super::super::vc::handle_vc_exception;
use super::common::PF_ERROR_WRITE;
use super::common::{
load_idt, Idt, IdtEntry, BP_VECTOR, DF_VECTOR, GLOBAL_IDT, GP_VECTOR, HV_VECTOR, PF_VECTOR,
VC_VECTOR,
idt_mut, IdtEntry, BP_VECTOR, DF_VECTOR, GP_VECTOR, HV_VECTOR, PF_VECTOR, VC_VECTOR,
};
use crate::address::VirtAddr;
use crate::cpu::X86ExceptionContext;
use crate::debug::gdbstub::svsm_gdbstub::handle_debug_exception;
use core::arch::global_asm;

fn init_idt(idt: &mut Idt) {
// Set IDT handlers
let handlers = unsafe { VirtAddr::from(&svsm_idt_handler_array as *const u8) };
for (i, entry) in idt.iter_mut().enumerate() {
*entry = IdtEntry::entry(handlers + (32 * i));
fn init_ist_vectors() {
unsafe {
let handler = VirtAddr::from(&svsm_idt_handler_array as *const u8) + (32 * DF_VECTOR);
idt_mut().set_entry(
DF_VECTOR,
IdtEntry::ist_entry(handler, IST_DF.try_into().unwrap()),
);
}
}

unsafe fn init_ist_vectors(idt: &mut Idt) {
let handler = VirtAddr::from(&svsm_idt_handler_array as *const u8) + (32 * DF_VECTOR);
idt[DF_VECTOR] = IdtEntry::ist_entry(handler, IST_DF.try_into().unwrap());
}

pub fn early_idt_init() {
unsafe {
init_idt(&mut GLOBAL_IDT);
load_idt(&GLOBAL_IDT);
idt_mut()
.init(&svsm_idt_handler_array as *const u8, 32)
.load();
}
}

pub fn idt_init() {
// Set IST vectors
unsafe {
init_ist_vectors(&mut GLOBAL_IDT);
}
init_ist_vectors();
}

#[no_mangle]
Expand Down
Loading

0 comments on commit c6bd164

Please sign in to comment.