mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-26 19:03:27 +00:00
Polish tdx-guest crate and Jinux VE handler
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
82518955d7
commit
c90f757b86
@ -6,7 +6,7 @@ use core::fmt::Debug;
|
||||
use trapframe::{GeneralRegs, UserContext as RawUserContext};
|
||||
|
||||
#[cfg(feature = "intel_tdx")]
|
||||
use crate::arch::tdx_guest::{virtual_exception_handler, TdxTrapFrame};
|
||||
use crate::arch::tdx_guest::handle_virtual_exception;
|
||||
use log::debug;
|
||||
#[cfg(feature = "intel_tdx")]
|
||||
use tdx_guest::tdcall;
|
||||
@ -43,55 +43,6 @@ pub struct TrapInformation {
|
||||
pub err: usize,
|
||||
}
|
||||
|
||||
#[cfg(feature = "intel_tdx")]
|
||||
struct VeGeneralRegs<'a>(&'a mut GeneralRegs);
|
||||
|
||||
#[cfg(feature = "intel_tdx")]
|
||||
impl TdxTrapFrame for VeGeneralRegs<'_> {
|
||||
fn rax(&self) -> usize {
|
||||
self.0.rax
|
||||
}
|
||||
fn set_rax(&mut self, rax: usize) {
|
||||
self.0.rax = rax;
|
||||
}
|
||||
fn rbx(&self) -> usize {
|
||||
self.0.rbx
|
||||
}
|
||||
fn set_rbx(&mut self, rbx: usize) {
|
||||
self.0.rbx = rbx;
|
||||
}
|
||||
fn rcx(&self) -> usize {
|
||||
self.0.rcx
|
||||
}
|
||||
fn set_rcx(&mut self, rcx: usize) {
|
||||
self.0.rcx = rcx;
|
||||
}
|
||||
fn rdx(&self) -> usize {
|
||||
self.0.rdx
|
||||
}
|
||||
fn set_rdx(&mut self, rdx: usize) {
|
||||
self.0.rdx = rdx;
|
||||
}
|
||||
fn rsi(&self) -> usize {
|
||||
self.0.rsi
|
||||
}
|
||||
fn set_rsi(&mut self, rsi: usize) {
|
||||
self.0.rsi = rsi;
|
||||
}
|
||||
fn rdi(&self) -> usize {
|
||||
self.0.rdi
|
||||
}
|
||||
fn set_rdi(&mut self, rdi: usize) {
|
||||
self.0.rdi = rdi;
|
||||
}
|
||||
fn rip(&self) -> usize {
|
||||
self.0.rip
|
||||
}
|
||||
fn set_rip(&mut self, rip: usize) {
|
||||
self.0.rip = rip;
|
||||
}
|
||||
}
|
||||
|
||||
impl UserContext {
|
||||
pub fn general_regs(&self) -> &GeneralRegs {
|
||||
&self.user_context.general
|
||||
@ -130,8 +81,7 @@ impl UserContextApiInternal for UserContext {
|
||||
if *exception == VIRTUALIZATION_EXCEPTION {
|
||||
let ve_info =
|
||||
tdcall::get_veinfo().expect("#VE handler: fail to get VE info\n");
|
||||
let mut ve_f = VeGeneralRegs(self.general_regs_mut());
|
||||
virtual_exception_handler(&mut ve_f, &ve_info);
|
||||
handle_virtual_exception(&mut (*self.general_regs_mut()).into(), &ve_info);
|
||||
continue;
|
||||
}
|
||||
if exception.typ == CpuExceptionType::FaultOrTrap
|
||||
|
@ -1,31 +1,88 @@
|
||||
use tdx_guest::{
|
||||
tdcall::TdgVeInfo,
|
||||
tdvmcall::{cpuid, hlt, rdmsr, wrmsr},
|
||||
tdvmcall::{cpuid, hlt, rdmsr, wrmsr, IoSize},
|
||||
{serial_println, tdcall, tdvmcall, TdxVirtualExceptionType},
|
||||
};
|
||||
use trapframe::{GeneralRegs, TrapFrame};
|
||||
|
||||
pub trait TdxTrapFrame {
|
||||
fn rax(&self) -> usize;
|
||||
fn set_rax(&mut self, rax: usize);
|
||||
fn rbx(&self) -> usize;
|
||||
fn set_rbx(&mut self, rbx: usize);
|
||||
fn rcx(&self) -> usize;
|
||||
fn set_rcx(&mut self, rcx: usize);
|
||||
fn rdx(&self) -> usize;
|
||||
fn set_rdx(&mut self, rdx: usize);
|
||||
fn rsi(&self) -> usize;
|
||||
fn set_rsi(&mut self, rsi: usize);
|
||||
fn rdi(&self) -> usize;
|
||||
fn set_rdi(&mut self, rdi: usize);
|
||||
fn rip(&self) -> usize;
|
||||
fn set_rip(&mut self, rip: usize);
|
||||
pub struct TdxTrapFrame {
|
||||
rax: usize,
|
||||
rbx: usize,
|
||||
rcx: usize,
|
||||
rdx: usize,
|
||||
rsi: usize,
|
||||
rdi: usize,
|
||||
rip: usize,
|
||||
}
|
||||
|
||||
fn io_handler(trapframe: &mut dyn TdxTrapFrame, ve_info: &tdcall::TdgVeInfo) -> bool {
|
||||
impl From<TrapFrame> for TdxTrapFrame {
|
||||
fn from(tf: TrapFrame) -> Self {
|
||||
Self {
|
||||
rax: tf.rax,
|
||||
rbx: tf.rbx,
|
||||
rcx: tf.rcx,
|
||||
rdx: tf.rdx,
|
||||
rsi: tf.rsi,
|
||||
rdi: tf.rdi,
|
||||
rip: tf.rip,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<GeneralRegs> for TdxTrapFrame {
|
||||
fn from(gr: GeneralRegs) -> Self {
|
||||
Self {
|
||||
rax: gr.rax,
|
||||
rbx: gr.rbx,
|
||||
rcx: gr.rcx,
|
||||
rdx: gr.rdx,
|
||||
rsi: gr.rsi,
|
||||
rdi: gr.rdi,
|
||||
rip: gr.rip,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_virtual_exception(trapframe: &mut TdxTrapFrame, ve_info: &TdgVeInfo) {
|
||||
match ve_info.exit_reason.into() {
|
||||
TdxVirtualExceptionType::Hlt => {
|
||||
serial_println!("Ready to halt");
|
||||
hlt();
|
||||
}
|
||||
TdxVirtualExceptionType::Io => {
|
||||
if !handle_io(trapframe, ve_info) {
|
||||
serial_println!("Handle tdx ioexit errors, ready to halt");
|
||||
hlt();
|
||||
}
|
||||
}
|
||||
TdxVirtualExceptionType::MsrRead => {
|
||||
let msr = unsafe { 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);
|
||||
unsafe { wrmsr(trapframe.rcx as u32, data).unwrap() };
|
||||
}
|
||||
TdxVirtualExceptionType::CpuId => {
|
||||
let cpuid_info = 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 += ve_info.exit_instruction_length as usize;
|
||||
}
|
||||
|
||||
fn handle_io(trapframe: &mut TdxTrapFrame, ve_info: &tdcall::TdgVeInfo) -> bool {
|
||||
let size = match ve_info.exit_qualification & 0x3 {
|
||||
0 => 1,
|
||||
1 => 2,
|
||||
3 => 4,
|
||||
0 => IoSize::Size1,
|
||||
1 => IoSize::Size2,
|
||||
3 => IoSize::Size4,
|
||||
_ => panic!("Invalid size value"),
|
||||
};
|
||||
let direction = if (ve_info.exit_qualification >> 3) & 0x1 == 0 {
|
||||
@ -33,8 +90,6 @@ fn io_handler(trapframe: &mut dyn TdxTrapFrame, ve_info: &tdcall::TdgVeInfo) ->
|
||||
} 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 {
|
||||
@ -44,46 +99,11 @@ fn io_handler(trapframe: &mut dyn TdxTrapFrame, ve_info: &tdcall::TdgVeInfo) ->
|
||||
|
||||
match direction {
|
||||
tdvmcall::Direction::In => {
|
||||
trapframe.set_rax(tdvmcall::io_read(size, port).unwrap() as usize);
|
||||
trapframe.rax = tdvmcall::io_read(size, port).unwrap() as usize;
|
||||
}
|
||||
tdvmcall::Direction::Out => {
|
||||
tdvmcall::io_write(size, port, trapframe.rax() as u32).unwrap();
|
||||
tdvmcall::io_write(size, port, trapframe.rax as u32).unwrap();
|
||||
}
|
||||
};
|
||||
true
|
||||
}
|
||||
|
||||
pub fn virtual_exception_handler(trapframe: &mut impl TdxTrapFrame, ve_info: &TdgVeInfo) {
|
||||
match ve_info.exit_reason.into() {
|
||||
TdxVirtualExceptionType::Hlt => {
|
||||
serial_println!("Ready to halt");
|
||||
hlt();
|
||||
}
|
||||
TdxVirtualExceptionType::Io => {
|
||||
if !io_handler(trapframe, ve_info) {
|
||||
serial_println!("Handle tdx ioexit errors, ready to halt");
|
||||
hlt();
|
||||
}
|
||||
}
|
||||
TdxVirtualExceptionType::MsrRead => {
|
||||
let msr = rdmsr(trapframe.rcx() as u32).unwrap();
|
||||
trapframe.set_rax((msr as u32 & u32::MAX) as usize);
|
||||
trapframe.set_rdx(((msr >> 32) as u32 & u32::MAX) as usize);
|
||||
}
|
||||
TdxVirtualExceptionType::MsrWrite => {
|
||||
let data = trapframe.rax() as u64 | ((trapframe.rdx() as u64) << 32);
|
||||
wrmsr(trapframe.rcx() as u32, data).unwrap();
|
||||
}
|
||||
TdxVirtualExceptionType::CpuId => {
|
||||
let cpuid_info = cpuid(trapframe.rax() as u32, trapframe.rcx() as u32).unwrap();
|
||||
let mask = 0xFFFF_FFFF_0000_0000_usize;
|
||||
trapframe.set_rax((trapframe.rax() & mask) | cpuid_info.eax);
|
||||
trapframe.set_rbx((trapframe.rbx() & mask) | cpuid_info.ebx);
|
||||
trapframe.set_rcx((trapframe.rcx() & mask) | cpuid_info.ecx);
|
||||
trapframe.set_rdx((trapframe.rdx() & mask) | cpuid_info.edx);
|
||||
}
|
||||
TdxVirtualExceptionType::Other => panic!("Unknown TDX vitrual exception type"),
|
||||
_ => return,
|
||||
}
|
||||
trapframe.set_rip(trapframe.rip() + ve_info.exit_instruction_length as usize);
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ use alloc::vec::Vec;
|
||||
use arch::irq::{IrqCallbackHandle, IrqLine};
|
||||
use core::{mem, panic::PanicInfo};
|
||||
#[cfg(feature = "intel_tdx")]
|
||||
use tdx_guest::tdx_early_init;
|
||||
use tdx_guest::init_tdx;
|
||||
use trapframe::TrapFrame;
|
||||
|
||||
static mut IRQ_CALLBACK_LIST: Vec<IrqCallbackHandle> = Vec::new();
|
||||
@ -50,7 +50,7 @@ pub fn init() {
|
||||
arch::before_all_init();
|
||||
logger::init();
|
||||
#[cfg(feature = "intel_tdx")]
|
||||
let td_info = tdx_early_init().unwrap();
|
||||
let td_info = init_tdx().unwrap();
|
||||
#[cfg(feature = "intel_tdx")]
|
||||
println!(
|
||||
"td gpaw: {}, td attributes: {:?}\nTDX guest is initialized",
|
||||
|
@ -1,60 +1,11 @@
|
||||
use crate::{arch::irq::IRQ_LIST, cpu::CpuException};
|
||||
|
||||
#[cfg(feature = "intel_tdx")]
|
||||
use crate::arch::tdx_guest::{virtual_exception_handler, TdxTrapFrame};
|
||||
use crate::arch::tdx_guest::handle_virtual_exception;
|
||||
#[cfg(feature = "intel_tdx")]
|
||||
use tdx_guest::tdcall;
|
||||
use trapframe::TrapFrame;
|
||||
|
||||
#[cfg(feature = "intel_tdx")]
|
||||
struct VeTrapFrame<'a>(&'a mut TrapFrame);
|
||||
|
||||
#[cfg(feature = "intel_tdx")]
|
||||
impl TdxTrapFrame for VeTrapFrame<'_> {
|
||||
fn rax(&self) -> usize {
|
||||
self.0.rax
|
||||
}
|
||||
fn set_rax(&mut self, rax: usize) {
|
||||
self.0.rax = rax;
|
||||
}
|
||||
fn rbx(&self) -> usize {
|
||||
self.0.rbx
|
||||
}
|
||||
fn set_rbx(&mut self, rbx: usize) {
|
||||
self.0.rbx = rbx;
|
||||
}
|
||||
fn rcx(&self) -> usize {
|
||||
self.0.rcx
|
||||
}
|
||||
fn set_rcx(&mut self, rcx: usize) {
|
||||
self.0.rcx = rcx;
|
||||
}
|
||||
fn rdx(&self) -> usize {
|
||||
self.0.rdx
|
||||
}
|
||||
fn set_rdx(&mut self, rdx: usize) {
|
||||
self.0.rdx = rdx;
|
||||
}
|
||||
fn rsi(&self) -> usize {
|
||||
self.0.rsi
|
||||
}
|
||||
fn set_rsi(&mut self, rsi: usize) {
|
||||
self.0.rsi = rsi;
|
||||
}
|
||||
fn rdi(&self) -> usize {
|
||||
self.0.rdi
|
||||
}
|
||||
fn set_rdi(&mut self, rdi: usize) {
|
||||
self.0.rdi = rdi;
|
||||
}
|
||||
fn rip(&self) -> usize {
|
||||
self.0.rip
|
||||
}
|
||||
fn set_rip(&mut self, rip: usize) {
|
||||
self.0.rip = rip;
|
||||
}
|
||||
}
|
||||
|
||||
/// Only from kernel
|
||||
#[no_mangle]
|
||||
extern "sysv64" fn trap_handler(f: &mut TrapFrame) {
|
||||
@ -62,8 +13,7 @@ extern "sysv64" fn trap_handler(f: &mut TrapFrame) {
|
||||
#[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");
|
||||
let mut ve_f = VeTrapFrame(f);
|
||||
virtual_exception_handler(&mut ve_f, &ve_info);
|
||||
handle_virtual_exception(&mut (*f).into(), &ve_info);
|
||||
}
|
||||
#[cfg(not(feature = "intel_tdx"))]
|
||||
panic!("cannot handle kernel cpu fault now, information:{:#x?}", f);
|
||||
|
Reference in New Issue
Block a user