-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #224 from joergroedel/mutable-static
Get rid of some mutable global statics
- Loading branch information
Showing
15 changed files
with
332 additions
and
203 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,3 +7,5 @@ | |
pub mod common; | ||
pub mod stage2; | ||
pub mod svsm; | ||
|
||
pub use common::{idt, idt_mut}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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(); | ||
} | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.