Handle TDX MMIO and DMA direct

This commit is contained in:
Hsy-Intel
2024-03-11 14:02:42 +08:00
committed by Tate, Hongliang Tian
parent 461c872c43
commit 37c3a7a48c
18 changed files with 720 additions and 55 deletions

View File

@ -10,4 +10,3 @@ x86_64 = "0.14.10"
bitflags = "1.3"
raw-cpuid = "10"
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }

View File

@ -11,6 +11,8 @@ mod asm;
pub mod tdcall;
pub mod tdvmcall;
use core::sync::atomic::{AtomicBool, Ordering::Relaxed};
use raw_cpuid::{native_cpuid::cpuid_count, CpuIdResult};
use tdcall::{InitError, TdgVpInfo};
@ -19,8 +21,16 @@ pub use self::{
tdvmcall::print,
};
static TDX_ENABLED: AtomicBool = AtomicBool::new(false);
#[inline(always)]
pub fn tdx_is_enabled() -> bool {
TDX_ENABLED.load(Relaxed)
}
pub fn init_tdx() -> Result<TdgVpInfo, InitError> {
check_tdx_guest()?;
TDX_ENABLED.store(true, Relaxed);
Ok(tdcall::get_tdinfo()?)
}
@ -32,7 +42,7 @@ fn check_tdx_guest() -> Result<(), InitError> {
}
let cpuid_result: CpuIdResult = cpuid_count(TDX_CPUID_LEAF_ID as u32, 0);
if &cpuid_result.ebx.to_ne_bytes() != b"Inte"
|| &cpuid_result.ebx.to_ne_bytes() != b"lTDX"
|| &cpuid_result.edx.to_ne_bytes() != b"lTDX"
|| &cpuid_result.ecx.to_ne_bytes() != b" "
{
return Err(InitError::TdxVendorIdError);

View File

@ -327,6 +327,7 @@ pub enum TdxVirtualExceptionType {
VmCall,
Mwait,
Monitor,
EptViolation,
Wbinvd,
Rdpmc,
Other,
@ -344,6 +345,7 @@ impl From<u32> for TdxVirtualExceptionType {
32 => Self::MsrWrite,
36 => Self::Mwait,
39 => Self::Monitor,
48 => Self::EptViolation,
54 => Self::Wbinvd,
_ => Self::Other,
}
@ -435,10 +437,10 @@ pub fn verify_report(report_mac_gpa: &[u8]) -> Result<(), TdCallError> {
/// Accept a pending private page and initialize it to all-0 using the TD ephemeral private key.
/// # Safety
/// The 'gpa' parameter must be a valid address.
pub unsafe fn accept_page(sept_level: u64, gpa: &[u8]) -> Result<(), TdCallError> {
pub unsafe fn accept_page(sept_level: u64, gpa: u64) -> Result<(), TdCallError> {
let mut args = TdcallArgs {
rax: TdcallNum::MemPageAccept as u64,
rcx: sept_level | ((gpa.as_ptr() as u64) << 12),
rcx: sept_level | gpa,
..Default::default()
};
td_call(&mut args)

View File

@ -163,12 +163,12 @@ pub fn perform_cache_operation(cache_operation: u64) -> Result<(), TdVmcallError
/// # Safety
/// Make sure the mmio address is valid.
pub unsafe fn read_mmio(size: IoSize, mmio_gpa: &[u8]) -> Result<u64, TdVmcallError> {
pub unsafe fn read_mmio(size: IoSize, mmio_gpa: u64) -> Result<u64, TdVmcallError> {
let mut args = TdVmcallArgs {
r11: TdVmcallNum::RequestMmio as u64,
r12: size as u64,
r13: 0,
r14: mmio_gpa.as_ptr() as u64,
r14: mmio_gpa,
..Default::default()
};
td_vmcall(&mut args)?;
@ -177,18 +177,32 @@ pub unsafe fn read_mmio(size: IoSize, mmio_gpa: &[u8]) -> Result<u64, TdVmcallEr
/// # Safety
/// Make sure the mmio address is valid.
pub unsafe fn write_mmio(size: IoSize, mmio_gpa: &[u8], data: u64) -> Result<(), TdVmcallError> {
pub unsafe fn write_mmio(size: IoSize, mmio_gpa: u64, data: u64) -> Result<(), TdVmcallError> {
let mut args = TdVmcallArgs {
r11: TdVmcallNum::RequestMmio as u64,
r12: size as u64,
r13: 1,
r14: mmio_gpa.as_ptr() as u64,
r14: mmio_gpa,
r15: data,
..Default::default()
};
td_vmcall(&mut args)
}
/// MapGPA TDG.VP.VMCALL is used to help request the host VMM to map a GPA range as private
/// or shared-memory mappings. This API may also be used to convert page mappings from
/// private to shared. The GPA range passed in this operation can indicate if the mapping is
/// requested for a shared or private memory via the GPA.Shared bit in the start address.
pub fn map_gpa(gpa: u64, size: u64) -> Result<(), (u64, TdVmcallError)> {
let mut args = TdVmcallArgs {
r11: TdVmcallNum::Mapgpa as u64,
r12: gpa,
r13: size,
..Default::default()
};
td_vmcall(&mut args).map_err(|e| (args.r11, e))
}
macro_rules! io_read {
($port:expr, $ty:ty) => {{
let mut args = TdVmcallArgs {