Handle other CPU exceptions & use trait method

This commit is contained in:
Hsy-Intel 2023-09-15 10:01:51 +08:00 committed by Tate, Hongliang Tian
parent c90f757b86
commit f2b2c20967
3 changed files with 135 additions and 56 deletions

View File

@ -6,7 +6,7 @@ use core::fmt::Debug;
use trapframe::{GeneralRegs, UserContext as RawUserContext};
#[cfg(feature = "intel_tdx")]
use crate::arch::tdx_guest::handle_virtual_exception;
use crate::arch::tdx_guest::{handle_virtual_exception, TdxTrapFrame};
use log::debug;
#[cfg(feature = "intel_tdx")]
use tdx_guest::tdcall;
@ -43,6 +43,55 @@ 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
@ -81,7 +130,8 @@ impl UserContextApiInternal for UserContext {
if *exception == VIRTUALIZATION_EXCEPTION {
let ve_info =
tdcall::get_veinfo().expect("#VE handler: fail to get VE info\n");
handle_virtual_exception(&mut (*self.general_regs_mut()).into(), &ve_info);
let mut ve_f = VeGeneralRegs(self.general_regs_mut());
handle_virtual_exception(&mut ve_f, &ve_info);
continue;
}
if exception.typ == CpuExceptionType::FaultOrTrap

View File

@ -5,45 +5,24 @@ use tdx_guest::{
};
use trapframe::{GeneralRegs, TrapFrame};
pub struct TdxTrapFrame {
rax: usize,
rbx: usize,
rcx: usize,
rdx: usize,
rsi: usize,
rdi: usize,
rip: usize,
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);
}
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) {
pub fn handle_virtual_exception(trapframe: &mut dyn TdxTrapFrame, ve_info: &TdgVeInfo) {
match ve_info.exit_reason.into() {
TdxVirtualExceptionType::Hlt => {
serial_println!("Ready to halt");
@ -56,29 +35,29 @@ pub fn handle_virtual_exception(trapframe: &mut TdxTrapFrame, ve_info: &TdgVeInf
}
}
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;
let msr = unsafe { 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);
unsafe { wrmsr(trapframe.rcx as u32, data).unwrap() };
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 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;
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.rip += ve_info.exit_instruction_length as usize;
trapframe.set_rip(trapframe.rip() + ve_info.exit_instruction_length as usize);
}
fn handle_io(trapframe: &mut TdxTrapFrame, ve_info: &tdcall::TdgVeInfo) -> bool {
fn handle_io(trapframe: &mut dyn TdxTrapFrame, ve_info: &tdcall::TdgVeInfo) -> bool {
let size = match ve_info.exit_qualification & 0x3 {
0 => IoSize::Size1,
1 => IoSize::Size2,
@ -99,10 +78,10 @@ fn handle_io(trapframe: &mut TdxTrapFrame, ve_info: &tdcall::TdgVeInfo) -> bool
match direction {
tdvmcall::Direction::In => {
trapframe.rax = tdvmcall::io_read(size, port).unwrap() as usize;
trapframe.set_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

View File

@ -1,11 +1,60 @@
use crate::{arch::irq::IRQ_LIST, cpu::CpuException};
#[cfg(feature = "intel_tdx")]
use crate::arch::tdx_guest::handle_virtual_exception;
use crate::arch::tdx_guest::{handle_virtual_exception, TdxTrapFrame};
#[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) {
@ -13,9 +62,10 @@ 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");
handle_virtual_exception(&mut (*f).into(), &ve_info);
let mut ve_f = VeTrapFrame(f);
handle_virtual_exception(&mut ve_f, &ve_info);
return;
}
#[cfg(not(feature = "intel_tdx"))]
panic!("cannot handle kernel cpu fault now, information:{:#x?}", f);
} else {
call_irq_callback_functions(f);