mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-20 04:56:32 +00:00
Add tdx early init and ve handler functions
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
d7710207bb
commit
4f0df44b29
@ -6,6 +6,8 @@ use core::fmt::Debug;
|
|||||||
use trapframe::{GeneralRegs, UserContext as RawUserContext};
|
use trapframe::{GeneralRegs, UserContext as RawUserContext};
|
||||||
|
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
#[cfg(feature = "intel_tdx")]
|
||||||
|
use tdx_guest::{serial_println, tdcall, tdvmcall, TdxVirtualExceptionType};
|
||||||
use x86_64::registers::rflags::RFlags;
|
use x86_64::registers::rflags::RFlags;
|
||||||
|
|
||||||
use crate::trap::call_irq_callback_functions;
|
use crate::trap::call_irq_callback_functions;
|
||||||
@ -39,6 +41,75 @@ pub struct TrapInformation {
|
|||||||
pub err: usize,
|
pub err: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "intel_tdx")]
|
||||||
|
pub fn virtual_exception_handler(trapframe: &mut GeneralRegs, ve_info: &tdcall::TdgVeInfo) {
|
||||||
|
match ve_info.exit_reason.into() {
|
||||||
|
TdxVirtualExceptionType::Hlt => {
|
||||||
|
serial_println!("Ready to halt");
|
||||||
|
tdvmcall::hlt();
|
||||||
|
}
|
||||||
|
TdxVirtualExceptionType::Io => {
|
||||||
|
if !handle_ve_io(trapframe, ve_info) {
|
||||||
|
serial_println!("Handle tdx ioexit errors, ready to halt");
|
||||||
|
tdvmcall::hlt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TdxVirtualExceptionType::MsrRead => {
|
||||||
|
let msr = tdvmcall::rdmsr(trapframe.rcx as u32).unwrap();
|
||||||
|
trapframe.rax = (msr as u32 & u32::MAX) as usize;
|
||||||
|
trapframe.rdx = ((msr >> 32) as u32 & u32::MAX) as usize;
|
||||||
|
}
|
||||||
|
TdxVirtualExceptionType::MsrWrite => {
|
||||||
|
let data = trapframe.rax as u64 | ((trapframe.rdx as u64) << 32);
|
||||||
|
tdvmcall::wrmsr(trapframe.rcx as u32, data).unwrap();
|
||||||
|
}
|
||||||
|
TdxVirtualExceptionType::CpuId => {
|
||||||
|
let cpuid_info = tdvmcall::cpuid(trapframe.rax as u32, trapframe.rcx as u32).unwrap();
|
||||||
|
let mask = 0xFFFF_FFFF_0000_0000_usize;
|
||||||
|
trapframe.rax = (trapframe.rax & mask) | cpuid_info.eax;
|
||||||
|
trapframe.rbx = (trapframe.rbx & mask) | cpuid_info.ebx;
|
||||||
|
trapframe.rcx = (trapframe.rcx & mask) | cpuid_info.ecx;
|
||||||
|
trapframe.rdx = (trapframe.rdx & mask) | cpuid_info.edx;
|
||||||
|
}
|
||||||
|
TdxVirtualExceptionType::Other => panic!("Unknown TDX vitrual exception type"),
|
||||||
|
_ => return,
|
||||||
|
}
|
||||||
|
trapframe.rip = trapframe.rip + ve_info.exit_instruction_length as usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "intel_tdx")]
|
||||||
|
pub fn handle_ve_io(trapframe: &mut GeneralRegs, ve_info: &tdcall::TdgVeInfo) -> bool {
|
||||||
|
let size = match ve_info.exit_qualification & 0x3 {
|
||||||
|
0 => 1,
|
||||||
|
1 => 2,
|
||||||
|
3 => 4,
|
||||||
|
_ => panic!("Invalid size value"),
|
||||||
|
};
|
||||||
|
let direction = if (ve_info.exit_qualification >> 3) & 0x1 == 0 {
|
||||||
|
tdvmcall::Direction::Out
|
||||||
|
} else {
|
||||||
|
tdvmcall::Direction::In
|
||||||
|
};
|
||||||
|
let string = (ve_info.exit_qualification >> 4) & 0x1 == 1;
|
||||||
|
let repeat = (ve_info.exit_qualification >> 5) & 0x1 == 1;
|
||||||
|
let operand = if (ve_info.exit_qualification >> 6) & 0x1 == 0 {
|
||||||
|
tdvmcall::Operand::Dx
|
||||||
|
} else {
|
||||||
|
tdvmcall::Operand::Immediate
|
||||||
|
};
|
||||||
|
let port = (ve_info.exit_qualification >> 16) as u16;
|
||||||
|
|
||||||
|
match direction {
|
||||||
|
tdvmcall::Direction::In => {
|
||||||
|
trapframe.rax = tdvmcall::io_read(size, port).unwrap() as usize;
|
||||||
|
}
|
||||||
|
tdvmcall::Direction::Out => {
|
||||||
|
tdvmcall::io_write(size, port, trapframe.rax as u32).unwrap();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
impl UserContext {
|
impl UserContext {
|
||||||
pub fn general_regs(&self) -> &GeneralRegs {
|
pub fn general_regs(&self) -> &GeneralRegs {
|
||||||
&self.user_context.general
|
&self.user_context.general
|
||||||
@ -73,6 +144,13 @@ impl UserContextApiInternal for UserContext {
|
|||||||
self.user_context.run();
|
self.user_context.run();
|
||||||
match CpuException::to_cpu_exception(self.user_context.trap_num as u16) {
|
match CpuException::to_cpu_exception(self.user_context.trap_num as u16) {
|
||||||
Some(exception) => {
|
Some(exception) => {
|
||||||
|
#[cfg(feature = "intel_tdx")]
|
||||||
|
if *exception == VIRTUALIZATION_EXCEPTION {
|
||||||
|
let ve_info =
|
||||||
|
tdcall::get_veinfo().expect("#VE handler: fail to get VE info\n");
|
||||||
|
virtual_exception_handler(self.general_regs_mut(), &ve_info);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if exception.typ == CpuExceptionType::FaultOrTrap
|
if exception.typ == CpuExceptionType::FaultOrTrap
|
||||||
|| exception.typ == CpuExceptionType::Fault
|
|| exception.typ == CpuExceptionType::Fault
|
||||||
|| exception.typ == CpuExceptionType::Trap
|
|| exception.typ == CpuExceptionType::Trap
|
||||||
|
@ -40,6 +40,8 @@ pub use self::prelude::Result;
|
|||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use arch::irq::{IrqCallbackHandle, IrqLine};
|
use arch::irq::{IrqCallbackHandle, IrqLine};
|
||||||
use core::{mem, panic::PanicInfo};
|
use core::{mem, panic::PanicInfo};
|
||||||
|
#[cfg(feature = "intel_tdx")]
|
||||||
|
use tdx_guest::tdx_early_init;
|
||||||
use trapframe::TrapFrame;
|
use trapframe::TrapFrame;
|
||||||
|
|
||||||
static mut IRQ_CALLBACK_LIST: Vec<IrqCallbackHandle> = Vec::new();
|
static mut IRQ_CALLBACK_LIST: Vec<IrqCallbackHandle> = Vec::new();
|
||||||
@ -47,6 +49,13 @@ static mut IRQ_CALLBACK_LIST: Vec<IrqCallbackHandle> = Vec::new();
|
|||||||
pub fn init() {
|
pub fn init() {
|
||||||
arch::before_all_init();
|
arch::before_all_init();
|
||||||
logger::init();
|
logger::init();
|
||||||
|
#[cfg(feature = "intel_tdx")]
|
||||||
|
let td_info = tdx_early_init().unwrap();
|
||||||
|
#[cfg(feature = "intel_tdx")]
|
||||||
|
println!(
|
||||||
|
"td gpaw: {}, td attributes: {:?}\nTDX guest is initialized",
|
||||||
|
td_info.gpaw, td_info.attributes
|
||||||
|
);
|
||||||
vm::heap_allocator::init();
|
vm::heap_allocator::init();
|
||||||
boot::init();
|
boot::init();
|
||||||
vm::init();
|
vm::init();
|
||||||
|
@ -1,14 +1,92 @@
|
|||||||
use crate::{arch::irq::IRQ_LIST, cpu::CpuException};
|
use crate::{arch::irq::IRQ_LIST, cpu::CpuException};
|
||||||
|
|
||||||
|
#[cfg(feature = "intel_tdx")]
|
||||||
|
use tdx_guest::{serial_println, tdcall, tdvmcall, TdxVirtualExceptionType};
|
||||||
use trapframe::TrapFrame;
|
use trapframe::TrapFrame;
|
||||||
|
|
||||||
|
#[cfg(feature = "intel_tdx")]
|
||||||
|
pub fn virtual_exception_handler(trapframe: &mut TrapFrame, ve_info: &tdcall::TdgVeInfo) {
|
||||||
|
match ve_info.exit_reason.into() {
|
||||||
|
TdxVirtualExceptionType::Hlt => {
|
||||||
|
serial_println!("Ready to halt");
|
||||||
|
tdvmcall::hlt();
|
||||||
|
}
|
||||||
|
TdxVirtualExceptionType::Io => {
|
||||||
|
if !handle_ve_io(trapframe, ve_info) {
|
||||||
|
serial_println!("Handle tdx ioexit errors, ready to halt");
|
||||||
|
tdvmcall::hlt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TdxVirtualExceptionType::MsrRead => {
|
||||||
|
let msr = tdvmcall::rdmsr(trapframe.rcx as u32).unwrap();
|
||||||
|
trapframe.rax = (msr as u32 & u32::MAX) as usize;
|
||||||
|
trapframe.rdx = ((msr >> 32) as u32 & u32::MAX) as usize;
|
||||||
|
}
|
||||||
|
TdxVirtualExceptionType::MsrWrite => {
|
||||||
|
let data = trapframe.rax as u64 | ((trapframe.rdx as u64) << 32);
|
||||||
|
tdvmcall::wrmsr(trapframe.rcx as u32, data).unwrap();
|
||||||
|
}
|
||||||
|
TdxVirtualExceptionType::CpuId => {
|
||||||
|
let cpuid_info = tdvmcall::cpuid(trapframe.rax as u32, trapframe.rcx as u32).unwrap();
|
||||||
|
let mask = 0xFFFF_FFFF_0000_0000_usize;
|
||||||
|
trapframe.rax = (trapframe.rax & mask) | cpuid_info.eax;
|
||||||
|
trapframe.rbx = (trapframe.rbx & mask) | cpuid_info.ebx;
|
||||||
|
trapframe.rcx = (trapframe.rcx & mask) | cpuid_info.ecx;
|
||||||
|
trapframe.rdx = (trapframe.rdx & mask) | cpuid_info.edx;
|
||||||
|
}
|
||||||
|
TdxVirtualExceptionType::Other => panic!("Unknown TDX vitrual exception type"),
|
||||||
|
_ => return,
|
||||||
|
}
|
||||||
|
trapframe.rip = trapframe.rip + ve_info.exit_instruction_length as usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "intel_tdx")]
|
||||||
|
pub fn handle_ve_io(trapframe: &mut TrapFrame, ve_info: &tdcall::TdgVeInfo) -> bool {
|
||||||
|
let size = match ve_info.exit_qualification & 0x3 {
|
||||||
|
0 => 1,
|
||||||
|
1 => 2,
|
||||||
|
3 => 4,
|
||||||
|
_ => panic!("Invalid size value"),
|
||||||
|
};
|
||||||
|
let direction = if (ve_info.exit_qualification >> 3) & 0x1 == 0 {
|
||||||
|
tdvmcall::Direction::Out
|
||||||
|
} else {
|
||||||
|
tdvmcall::Direction::In
|
||||||
|
};
|
||||||
|
let string = (ve_info.exit_qualification >> 4) & 0x1 == 1;
|
||||||
|
let repeat = (ve_info.exit_qualification >> 5) & 0x1 == 1;
|
||||||
|
let operand = if (ve_info.exit_qualification >> 6) & 0x1 == 0 {
|
||||||
|
tdvmcall::Operand::Dx
|
||||||
|
} else {
|
||||||
|
tdvmcall::Operand::Immediate
|
||||||
|
};
|
||||||
|
let port = (ve_info.exit_qualification >> 16) as u16;
|
||||||
|
|
||||||
|
match direction {
|
||||||
|
tdvmcall::Direction::In => {
|
||||||
|
trapframe.rax = tdvmcall::io_read(size, port).unwrap() as usize;
|
||||||
|
}
|
||||||
|
tdvmcall::Direction::Out => {
|
||||||
|
tdvmcall::io_write(size, port, trapframe.rax as u32).unwrap();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
/// Only from kernel
|
/// Only from kernel
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "sysv64" fn trap_handler(f: &mut TrapFrame) {
|
extern "sysv64" fn trap_handler(f: &mut TrapFrame) {
|
||||||
if CpuException::is_cpu_exception(f.trap_num as u16) {
|
if CpuException::is_cpu_exception(f.trap_num as u16) {
|
||||||
|
#[cfg(feature = "intel_tdx")]
|
||||||
|
if f.trap_num as u16 == 20 {
|
||||||
|
let ve_info = tdcall::get_veinfo().expect("#VE handler: fail to get VE info\n");
|
||||||
|
virtual_exception_handler(f, &ve_info);
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "intel_tdx"))]
|
||||||
panic!("cannot handle kernel cpu fault now, information:{:#x?}", f);
|
panic!("cannot handle kernel cpu fault now, information:{:#x?}", f);
|
||||||
|
} else {
|
||||||
|
call_irq_callback_functions(f);
|
||||||
}
|
}
|
||||||
call_irq_callback_functions(f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn call_irq_callback_functions(trap_frame: &TrapFrame) {
|
pub(crate) fn call_irq_callback_functions(trap_frame: &TrapFrame) {
|
||||||
|
Reference in New Issue
Block a user