Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement KVM_TDX_INIT_MEMORY_REGION and KVM_TDX_FINALIZE_VM #3

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,6 @@ rust-version = "1.71"

[dependencies]
bitflags = "2.4.2"
kvm-bindings = "0.7.0"
kvm-ioctls = "0.16.0"
vmm-sys-util = "0.12.1"
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,6 @@

pub mod vcpu;
pub mod vm;

#[cfg(target_os = "linux")]
pub mod linux;
65 changes: 65 additions & 0 deletions src/linux/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// SPDX-License-Identifier: Apache-2.0

/// Trust Domain eXtensions sub-ioctl() commands
#[repr(u32)]
pub enum CmdId {
GetCapabilities = 0,
InitVm = 1,
InitVcpu = 2,
InitMemRegion = 3,
FinalizeVm = 4,
}

/// Contains information for the sub-ioctl() command to be run. This is
/// equivalent to `struct kvm_tdx_cmd` in the kernel.
#[derive(Default)]
#[repr(C)]
pub struct Cmd {
/// TDX command identifier
pub id: u32,

/// Flags for sub-command. If sub-command doesn't use it, set to zero.
pub flags: u32,

/// A u64 representing a generic pointer to the respective ioctl input.
/// This data is read differently according to the TDX ioctl identifier.
pub data: u64,

/// Auxiliary error code. The sub-command may return TDX SEAMCALL status
/// code in addition to -Exxx.
pub error: u64,

/// Reserved.
pub _unused: u64,
}

#[derive(Debug)]
pub struct TdxError {
pub code: i32,
pub message: String,
}

impl From<kvm_ioctls::Error> for TdxError {
fn from(kvm_err: kvm_ioctls::Error) -> Self {
TdxError::from(kvm_err.errno())
}
}

impl From<i32> for TdxError {
fn from(errno: i32) -> Self {
match errno {
7 => TdxError {
code: 7,
message: String::from("Invalid value for NR_CPUID_CONFIGS"),
},
25 => TdxError {
code: 25,
message: String::from("Inappropriate ioctl for device. Ensure the proper VM type is being used for the ioctl"),
},
_ => TdxError {
code: errno,
message: format!("errno: {}", errno),
},
}
}
}
2 changes: 2 additions & 0 deletions src/vcpu/linux/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
// SPDX-License-Identifier: Apache-2.0

pub mod ioctl;
35 changes: 35 additions & 0 deletions src/vcpu/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,36 @@
// SPDX-License-Identifier: Apache-2.0

mod linux;

use crate::linux::{Cmd, CmdId, TdxError};
use kvm_bindings::*;
use vmm_sys_util::*;

vmm_sys_util::ioctl_iowr_nr!(KVM_MEMORY_ENCRYPT_OP, KVMIO, 0xba, std::os::raw::c_ulong);

pub struct TdxVcpu {
pub fd: kvm_ioctls::VcpuFd,
}

impl TdxVcpu {
pub fn new(vm: &crate::vm::TdxVm, id: u64) -> Result<TdxVcpu, TdxError> {
let vcpufd = vm.fd.create_vcpu(id)?;
Ok(Self { fd: vcpufd })
}

/// TDX specific VCPU initialization using a TDVF HOB address
pub fn init_vcpu(&self, hob_addr: u64) -> Result<(), TdxError> {
let mut cmd = Cmd {
id: CmdId::InitVcpu as u32,
flags: 0,
data: hob_addr as *const u64 as _,
error: 0,
_unused: 0,
};
let ret = unsafe { ioctl::ioctl_with_mut_ptr(&self.fd, KVM_MEMORY_ENCRYPT_OP(), &mut cmd) };
if ret < 0 {
return Err(TdxError::from(ret));
}
Ok(())
}
}
56 changes: 26 additions & 30 deletions src/vm/linux/ioctl.rs
Original file line number Diff line number Diff line change
@@ -1,35 +1,7 @@
// SPDX-License-Identifier: Apache-2.0

use crate::vm::linux::types::Capabilities;

/// Trust Domain eXtensions sub-ioctl() commands
#[repr(u32)]
pub enum CmdId {
GetCapabilities = 0,
}

/// Contains information for the sub-ioctl() command to be run. This is
/// equivalent to `struct kvm_tdx_cmd` in the kernel.
#[derive(Default)]
#[repr(C)]
pub struct Cmd {
/// TDX command identifier
pub id: u32,

/// Flags for sub-command. If sub-command doesn't use it, set to zero.
pub flags: u32,

/// A u64 representing a generic pointer to the respective ioctl input.
/// This data is read differently according to the TDX ioctl identifier.
pub data: u64,

/// Auxiliary error code. The sub-command may return TDX SEAMCALL status
/// code in addition to -Exxx.
pub error: u64,

/// Reserved.
pub _unused: u64,
}
use crate::linux::{Cmd, CmdId};
use crate::vm::linux::types::{Capabilities, InitMemRegion, InitVm};

impl From<&Capabilities> for Cmd {
fn from(caps: &Capabilities) -> Self {
Expand All @@ -42,3 +14,27 @@ impl From<&Capabilities> for Cmd {
}
}
}

impl From<&InitVm> for Cmd {
fn from(init_vm: &InitVm) -> Self {
Self {
id: CmdId::InitVm as u32,
flags: 0,
data: init_vm as *const InitVm as _,
error: 0,
_unused: 0,
}
}
}

impl From<&InitMemRegion> for Cmd {
fn from(init_mem_region: &InitMemRegion) -> Self {
Self {
id: CmdId::InitMemRegion as u32,
flags: 0,
data: init_mem_region as *const InitMemRegion as _,
error: 0,
_unused: 0,
}
}
}
78 changes: 78 additions & 0 deletions src/vm/linux/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,81 @@ impl Default for Capabilities {
}
}
}

/// TDX specific VM initialization information
#[derive(Debug)]
#[repr(C)]
pub struct InitVm {
/// attributes specifies various guest TD attributes
pub attributes: u64,

/// mrconfigid is a software-defined ID for non-owner-defined configuration of the guest TD
/// (runtime or OS configuration)
pub mrconfigid: [u64; 6],

/// mrowner is a software-defined ID for the guest TD’s owner
pub mrowner: [u64; 6],

/// mrownerconfig is a software-defined ID for owner-defined configuration of the guest TD
/// (specific to the workload)
pub mrownerconfig: [u64; 6],

/// reserved for future extensibility
reserved: [u64; 1004],

/// direct configuration of CPUID leaves/subleaves virtualization
pub cpuid_nent: u32,
cpuid_padding: u32,
pub cpuid_entries: [kvm_bindings::kvm_cpuid_entry2; 256],
}

impl InitVm {
pub fn new(cpuid_entries: &Vec<kvm_bindings::kvm_cpuid_entry2>) -> Self {
Self {
cpuid_nent: cpuid_entries.len() as u32,
cpuid_entries: cpuid_entries.as_slice().try_into().unwrap(),
..Default::default()
}
}
}

impl Default for InitVm {
fn default() -> Self {
Self {
// set the SEPT_VE_DISABLE bit by default to prevent an Extended Page Table
// (EPT) violation to #VE caused by guest TD access of PENDING pages
attributes: crate::vm::AttributesFlags::SEPT_VE_DISABLE.bits(),
mrconfigid: [0; 6],
mrowner: [0; 6],
mrownerconfig: [0; 6],
reserved: [0; 1004],
cpuid_nent: 0,
cpuid_padding: 0,
cpuid_entries: [Default::default(); 256],
}
}
}

/// Information to encrypt a contiguous memory region
#[derive(Debug)]
#[repr(C)]
pub struct InitMemRegion {
/// private page image
pub source_addr: u64,

/// guest address to map the private page image to
pub gpa: u64,

/// number of 4KB private pages
pub nr_pages: u64,
}

impl From<&crate::vm::TdxInitMemRegion> for InitMemRegion {
fn from(value: &crate::vm::TdxInitMemRegion) -> Self {
Self {
source_addr: value.host_address,
gpa: value.guest_address,
nr_pages: value.nr_pages,
}
}
}
Loading