diff --git a/alioth/src/hv/hv.rs b/alioth/src/hv/hv.rs index bc0361a3..c18a4f8a 100644 --- a/alioth/src/hv/hv.rs +++ b/alioth/src/hv/hv.rs @@ -111,6 +111,9 @@ pub enum Error { #[cfg(target_arch = "x86_64")] #[snafu(display("SEV command error code {code:#x?}"))] SevErr { code: SevStatus }, + #[cfg(target_arch = "x86_64")] + #[snafu(display("TDX command error code {code:#x?}"))] + TdxErr { code: u64 }, } impl From for Error { @@ -214,6 +217,9 @@ pub trait Vcpu { let pc = self.get_reg(Reg::Pc)?; self.set_regs(&[(Reg::Pc, pc + 4)]) } + + #[cfg(target_arch = "x86_64")] + fn tdx_init_mem_region(&self, data: &[u8], gpa: u64, measure: bool) -> Result<()>; } #[cfg(not(target_arch = "x86_64"))] diff --git a/alioth/src/hv/kvm/kvm.rs b/alioth/src/hv/kvm/kvm.rs index 86790f5b..5d01f68a 100644 --- a/alioth/src/hv/kvm/kvm.rs +++ b/alioth/src/hv/kvm/kvm.rs @@ -20,6 +20,8 @@ mod x86_64; mod device; #[cfg(target_arch = "x86_64")] mod sev; +#[cfg(target_arch = "x86_64")] +mod tdx; #[path = "vcpu/vcpu.rs"] mod vcpu; #[path = "vm/vm.rs"] diff --git a/alioth/src/hv/kvm/tdx.rs b/alioth/src/hv/kvm/tdx.rs new file mode 100644 index 00000000..78b18acb --- /dev/null +++ b/alioth/src/hv/kvm/tdx.rs @@ -0,0 +1,35 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::os::fd::OwnedFd; + +use snafu::ResultExt; + +use crate::hv::{Result, error}; +use crate::sys::kvm::kvm_memory_encrypt_op; +use crate::sys::tdx::{KvmTdxCmd, KvmTdxCmdId}; + +pub fn tdx_op(fd: &OwnedFd, cmd: KvmTdxCmdId, flags: u32, data: Option<&mut T>) -> Result<()> { + let mut req = KvmTdxCmd { + id: cmd, + flags, + data: data.map(|d| d as *mut _ as _).unwrap_or(0), + hw_error: 0, + }; + unsafe { kvm_memory_encrypt_op(fd, &mut req) }.context(error::MemEncrypt)?; + if req.hw_error != 0 { + return error::TdxErr { code: req.hw_error }.fail(); + } + Ok(()) +} diff --git a/alioth/src/hv/kvm/vcpu/vcpu.rs b/alioth/src/hv/kvm/vcpu/vcpu.rs index 47669904..94eff494 100644 --- a/alioth/src/hv/kvm/vcpu/vcpu.rs +++ b/alioth/src/hv/kvm/vcpu/vcpu.rs @@ -16,7 +16,7 @@ #[path = "vcpu_aarch64.rs"] mod aarch64; #[cfg(target_arch = "x86_64")] -#[path = "vcpu_x86_64.rs"] +#[path = "vcpu_x86_64/vcpu_x86_64.rs"] mod x86_64; mod vmentry; @@ -232,4 +232,9 @@ impl Vcpu for KvmVcpu { fn dump(&self) -> Result<(), Error> { Ok(()) } + + #[cfg(target_arch = "x86_64")] + fn tdx_init_mem_region(&self, data: &[u8], gpa: u64, measure: bool) -> Result<()> { + KvmVcpu::tdx_init_mem_region(self, data, gpa, measure) + } } diff --git a/alioth/src/hv/kvm/vcpu/vcpu_x86_64/tdx.rs b/alioth/src/hv/kvm/vcpu/vcpu_x86_64/tdx.rs new file mode 100644 index 00000000..8a3785f8 --- /dev/null +++ b/alioth/src/hv/kvm/vcpu/vcpu_x86_64/tdx.rs @@ -0,0 +1,39 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::hv::Result; +use crate::hv::kvm::tdx::tdx_op; +use crate::hv::kvm::vcpu::KvmVcpu; +use crate::sys::tdx::{KvmTdxCmdId, KvmTdxInitMemRegion, KvmTdxInitMemRegionFlag}; + +impl KvmVcpu { + pub fn tdx_init_mem_region(&self, data: &[u8], gpa: u64, measure: bool) -> Result<()> { + let mut region = KvmTdxInitMemRegion { + source_addr: data.as_ptr() as u64, + nr_pages: data.len() as u64 >> 12, + gpa, + }; + let flag = if measure { + KvmTdxInitMemRegionFlag::MEASURE_MEMORY_REGION + } else { + KvmTdxInitMemRegionFlag::empty() + }; + tdx_op( + &self.fd, + KvmTdxCmdId::INIT_MEM_REGION, + flag.bits(), + Some(&mut region), + ) + } +} diff --git a/alioth/src/hv/kvm/vcpu/vcpu_x86_64.rs b/alioth/src/hv/kvm/vcpu/vcpu_x86_64/vcpu_x86_64.rs similarity index 99% rename from alioth/src/hv/kvm/vcpu/vcpu_x86_64.rs rename to alioth/src/hv/kvm/vcpu/vcpu_x86_64/vcpu_x86_64.rs index b4bbd3f3..9f34c927 100644 --- a/alioth/src/hv/kvm/vcpu/vcpu_x86_64.rs +++ b/alioth/src/hv/kvm/vcpu/vcpu_x86_64/vcpu_x86_64.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +mod tdx; + use std::arch::x86_64::CpuidResult; use std::collections::HashMap; use std::iter::zip; diff --git a/alioth/src/hv/kvm/vcpu/vcpu_x86_64_test.rs b/alioth/src/hv/kvm/vcpu/vcpu_x86_64/vcpu_x86_64_test.rs similarity index 100% rename from alioth/src/hv/kvm/vcpu/vcpu_x86_64_test.rs rename to alioth/src/hv/kvm/vcpu/vcpu_x86_64/vcpu_x86_64_test.rs