2024-01-03 03:22:36 +00:00
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
|
2024-07-09 02:34:59 +00:00
|
|
|
use ostd::mm::{DmaCoherent, FrameAllocOptions, HasPaddr, VmIo};
|
2024-06-18 09:07:27 +00:00
|
|
|
use tdx_guest::tdcall::{get_report, TdCallError};
|
2023-11-29 02:30:05 +00:00
|
|
|
|
2024-02-25 14:09:24 +00:00
|
|
|
use super::*;
|
|
|
|
|
use crate::{
|
|
|
|
|
error::Error,
|
|
|
|
|
events::IoEvents,
|
|
|
|
|
fs::{inode_handle::FileIo, utils::IoctlCmd},
|
2024-11-02 02:11:39 +00:00
|
|
|
process::signal::{Pollable, Poller},
|
2024-02-25 14:09:24 +00:00
|
|
|
};
|
|
|
|
|
|
2023-11-29 02:30:05 +00:00
|
|
|
const TDX_REPORTDATA_LEN: usize = 64;
|
|
|
|
|
const TDX_REPORT_LEN: usize = 1024;
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, Pod)]
|
|
|
|
|
#[repr(C)]
|
|
|
|
|
pub struct TdxReportRequest {
|
2024-06-18 09:07:27 +00:00
|
|
|
report_data: [u8; TDX_REPORTDATA_LEN],
|
|
|
|
|
tdx_report: [u8; TDX_REPORT_LEN],
|
2023-11-29 02:30:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct TdxGuest;
|
|
|
|
|
|
|
|
|
|
impl Device for TdxGuest {
|
|
|
|
|
fn type_(&self) -> DeviceType {
|
|
|
|
|
DeviceType::MiscDevice
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn id(&self) -> DeviceId {
|
2023-11-30 06:30:32 +00:00
|
|
|
DeviceId::new(0xa, 0x7b)
|
2023-11-29 02:30:05 +00:00
|
|
|
}
|
|
|
|
|
}
|
2023-11-30 06:30:32 +00:00
|
|
|
|
2023-12-06 09:04:07 +00:00
|
|
|
impl From<TdCallError> for Error {
|
|
|
|
|
fn from(err: TdCallError) -> Self {
|
|
|
|
|
match err {
|
|
|
|
|
TdCallError::TdxNoValidVeInfo => {
|
|
|
|
|
Error::with_message(Errno::EINVAL, "TdCallError::TdxNoValidVeInfo")
|
|
|
|
|
}
|
|
|
|
|
TdCallError::TdxOperandInvalid => {
|
|
|
|
|
Error::with_message(Errno::EINVAL, "TdCallError::TdxOperandInvalid")
|
|
|
|
|
}
|
|
|
|
|
TdCallError::TdxPageAlreadyAccepted => {
|
|
|
|
|
Error::with_message(Errno::EINVAL, "TdCallError::TdxPageAlreadyAccepted")
|
|
|
|
|
}
|
|
|
|
|
TdCallError::TdxPageSizeMismatch => {
|
|
|
|
|
Error::with_message(Errno::EINVAL, "TdCallError::TdxPageSizeMismatch")
|
|
|
|
|
}
|
|
|
|
|
TdCallError::TdxOperandBusy => {
|
|
|
|
|
Error::with_message(Errno::EBUSY, "TdCallError::TdxOperandBusy")
|
|
|
|
|
}
|
|
|
|
|
TdCallError::Other => Error::with_message(Errno::EAGAIN, "TdCallError::Other"),
|
2024-07-09 02:34:59 +00:00
|
|
|
_ => todo!(),
|
2023-12-06 09:04:07 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-02 06:31:20 +00:00
|
|
|
impl Pollable for TdxGuest {
|
|
|
|
|
fn poll(&self, mask: IoEvents, _poller: Option<&mut Poller>) -> IoEvents {
|
|
|
|
|
let events = IoEvents::IN | IoEvents::OUT;
|
|
|
|
|
events & mask
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-29 02:30:05 +00:00
|
|
|
impl FileIo for TdxGuest {
|
2024-08-22 07:52:20 +00:00
|
|
|
fn read(&self, _writer: &mut VmWriter) -> Result<usize> {
|
2023-11-29 02:30:05 +00:00
|
|
|
return_errno_with_message!(Errno::EPERM, "Read operation not supported")
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-22 07:52:20 +00:00
|
|
|
fn write(&self, _reader: &mut VmReader) -> Result<usize> {
|
2023-11-29 02:30:05 +00:00
|
|
|
return_errno_with_message!(Errno::EPERM, "Write operation not supported")
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-18 09:07:27 +00:00
|
|
|
fn ioctl(&self, cmd: IoctlCmd, arg: usize) -> Result<i32> {
|
2023-11-29 02:30:05 +00:00
|
|
|
match cmd {
|
2024-06-18 09:07:27 +00:00
|
|
|
IoctlCmd::TDXGETREPORT => handle_get_report(arg),
|
2023-11-29 02:30:05 +00:00
|
|
|
_ => return_errno_with_message!(Errno::EPERM, "Unsupported ioctl"),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-06-18 09:07:27 +00:00
|
|
|
|
|
|
|
|
fn handle_get_report(arg: usize) -> Result<i32> {
|
|
|
|
|
const SHARED_BIT: u8 = 51;
|
|
|
|
|
const SHARED_MASK: u64 = 1u64 << SHARED_BIT;
|
2024-10-10 05:49:01 +00:00
|
|
|
let current_task = ostd::task::Task::current().unwrap();
|
|
|
|
|
let user_space = CurrentUserSpace::new(¤t_task);
|
2024-08-09 08:11:43 +00:00
|
|
|
let user_request: TdxReportRequest = user_space.read_val(arg)?;
|
2024-06-18 09:07:27 +00:00
|
|
|
|
|
|
|
|
let vm_segment = FrameAllocOptions::new(2)
|
|
|
|
|
.is_contiguous(true)
|
|
|
|
|
.alloc_contiguous()
|
|
|
|
|
.unwrap();
|
|
|
|
|
let dma_coherent = DmaCoherent::map(vm_segment, false).unwrap();
|
|
|
|
|
dma_coherent
|
|
|
|
|
.write_bytes(0, &user_request.report_data)
|
|
|
|
|
.unwrap();
|
|
|
|
|
// 1024-byte alignment.
|
|
|
|
|
dma_coherent
|
|
|
|
|
.write_bytes(1024, &user_request.tdx_report)
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
|
|
if let Err(err) = get_report(
|
|
|
|
|
((dma_coherent.paddr() + 1024) as u64) | SHARED_MASK,
|
|
|
|
|
(dma_coherent.paddr() as u64) | SHARED_MASK,
|
|
|
|
|
) {
|
|
|
|
|
println!("[kernel]: get TDX report error: {:?}", err);
|
|
|
|
|
return Err(err.into());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let tdx_report_vaddr = arg + TDX_REPORTDATA_LEN;
|
|
|
|
|
let mut generated_report = vec![0u8; TDX_REPORT_LEN];
|
|
|
|
|
dma_coherent
|
|
|
|
|
.read_bytes(1024, &mut generated_report)
|
|
|
|
|
.unwrap();
|
2024-07-09 02:34:59 +00:00
|
|
|
let report_slice: &[u8] = &generated_report;
|
2024-08-09 08:11:43 +00:00
|
|
|
user_space.write_bytes(tdx_report_vaddr, &mut VmReader::from(report_slice))?;
|
2024-06-18 09:07:27 +00:00
|
|
|
Ok(0)
|
|
|
|
|
}
|