-
Notifications
You must be signed in to change notification settings - Fork 153
tdisp: Add OpenHCL and host TDISP crates #2069
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
Open
mfrohlich-msft
wants to merge
31
commits into
microsoft:main
Choose a base branch
from
mfrohlich-msft:openhcl_tdisp_modules
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
d070c52
add openhcl_tdisp_resources and openhcl_tdisp modules
mfrohlich-msft 23c2fc9
comment cleanup
mfrohlich-msft 480fe56
add tdisp module
mfrohlich-msft 98d45c1
add modules to root level cargo
mfrohlich-msft e3e8a85
cleanup docs in tdisp module
mfrohlich-msft f63fd42
old trait not needed
mfrohlich-msft 3c9a604
refactor away openhcl_tdisp_resources crate into just openhcl_tdisp
mfrohlich-msft 02f1c84
cleanup devicereport
mfrohlich-msft a53f532
cleanup lib.rs
mfrohlich-msft e017631
cleanup serialize.rs
mfrohlich-msft 0494793
cleanup openhcl_tdisp lib.rs
mfrohlich-msft 5c69ec9
cleanup tracing
mfrohlich-msft 55c9d67
remove panic in favor of error
mfrohlich-msft 8a09c39
remove panic in favor of unknown state for TdispGuestOperationError
mfrohlich-msft 6df2e7d
fix trace
mfrohlich-msft ece4b27
add license headers
mfrohlich-msft 5208e08
ensure openhcl_tdisp builds in underhill core
mfrohlich-msft c940ce4
cr: sort pub use, remove bad doc
mfrohlich-msft bbf7b3a
cr: split combined use statements and sort pub use
mfrohlich-msft 064cca7
cr: typo
mfrohlich-msft 63a7002
cr: remove accidential Debug implementation
mfrohlich-msft 616ca28
cr: refactor TdispCommandId to open_enum
mfrohlich-msft 735fb95
only try to deserialize a payload if there is one supplied in the packet
mfrohlich-msft 09c80c3
cr: refactor TdispReportType for open_enum
mfrohlich-msft f25f2fc
cr: refactor TdispTdiState for open_enum
mfrohlich-msft 7b3d2ab
cr: refactor TdispGuestOperationError for open_enum (also allow it to…
mfrohlich-msft 0adbc6d
cr: remove default impls
mfrohlich-msft dfac5c0
cr: cleanup From<> and Into<> traits
mfrohlich-msft d95b830
cr: repr(C) on structures to ensure they have a known serialized layout
mfrohlich-msft 81c2bf0
cr: allow setting debug device id in constructor
mfrohlich-msft ecb4b24
xfmt --fix
mfrohlich-msft File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Copyright (c) Microsoft Corporation. | ||
# Licensed under the MIT License. | ||
|
||
[package] | ||
name = "openhcl_tdisp" | ||
rust-version.workspace = true | ||
edition.workspace = true | ||
|
||
[dependencies] | ||
inspect.workspace = true | ||
tdisp.workspace = true | ||
|
||
anyhow.workspace = true | ||
|
||
[lints] | ||
workspace = true |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
//! | ||
//! This module provides resources and traits for a TDISP client device | ||
//! interface for assigned devices in OpenHCL. | ||
//! | ||
//! See: `vm/tdisp` for more information. | ||
|
||
pub use tdisp::TDISP_INTERFACE_VERSION_MAJOR; | ||
pub use tdisp::TDISP_INTERFACE_VERSION_MINOR; | ||
pub use tdisp::TdispCommandId; | ||
|
||
use inspect::Inspect; | ||
use std::future::Future; | ||
use tdisp::GuestToHostCommand; | ||
use tdisp::GuestToHostResponse; | ||
use tdisp::TdispGuestUnbindReason; | ||
use tdisp::devicereport::TdiReportStruct; | ||
use tdisp::devicereport::TdispReportType; | ||
|
||
/// Represents a TDISP device assigned to a guest partition. This trait allows | ||
/// the guest to send TDISP commands to the host through the backing interface. | ||
/// [TDISP TODO] Change out `anyhow` for a `TdispError` type? | ||
pub trait ClientDevice: Send + Sync + Inspect { | ||
/// Send a TDISP command to the host through the backing interface. | ||
fn tdisp_command_to_host( | ||
&self, | ||
command: GuestToHostCommand, | ||
) -> anyhow::Result<GuestToHostResponse>; | ||
|
||
/// Checks if the device is TDISP capable and returns the device interface info if so. | ||
fn tdisp_get_device_interface_info(&self) -> anyhow::Result<tdisp::TdispDeviceInterfaceInfo>; | ||
|
||
/// Bind the device to the current partition and transition to Locked. | ||
fn tdisp_bind_interface(&self) -> anyhow::Result<()>; | ||
} | ||
|
||
/// Represents a TDISP device assigned to a guest partition that can be used to | ||
/// send TDISP commands to the host through a backing interface. | ||
pub trait VpciTdispInterface: Send + Sync { | ||
/// Sends a TDISP command to the device through the VPCI channel. | ||
fn send_tdisp_command( | ||
&self, | ||
payload: GuestToHostCommand, | ||
) -> impl Future<Output = Result<GuestToHostResponse, anyhow::Error>> + Send; | ||
|
||
/// Get the TDISP interface info for the device. | ||
fn tdisp_get_device_interface_info( | ||
&self, | ||
) -> impl Future<Output = anyhow::Result<tdisp::TdispDeviceInterfaceInfo>> + Send; | ||
|
||
/// Bind the device to the current partition and transition to Locked. | ||
/// NOTE: While the device is in the Locked state, it can continue to | ||
/// perform unencrypted operations until it is moved to the Running state. | ||
/// The Locked state is a transitional state that is designed to keep | ||
/// the device from modifying its resources prior to attestation. | ||
fn tdisp_bind_interface(&self) -> impl Future<Output = anyhow::Result<()>> + Send; | ||
smalis-msft marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/// Start a bound device by transitioning it from the Locked state to the Run state. | ||
/// This allows for attestation and for resources to be accepted into the guest context. | ||
fn tdisp_start_device(&self) -> impl Future<Output = anyhow::Result<()>> + Send; | ||
|
||
/// Request a device report from the TDI or physical device depending on the report type. | ||
fn tdisp_get_device_report( | ||
&self, | ||
report_type: &TdispReportType, | ||
) -> impl Future<Output = anyhow::Result<Vec<u8>>> + Send; | ||
|
||
/// Request a TDI report from the TDI or physical device. | ||
fn tdisp_get_tdi_report(&self) -> impl Future<Output = anyhow::Result<TdiReportStruct>> + Send; | ||
|
||
/// Request the TDI device id from the vpci channel. | ||
fn tdisp_get_tdi_device_id(&self) -> impl Future<Output = anyhow::Result<u64>> + Send; | ||
|
||
/// Request to unbind the device and return to the Unlocked state. | ||
fn tdisp_unbind( | ||
&self, | ||
reason: TdispGuestUnbindReason, | ||
) -> impl Future<Output = anyhow::Result<()>> + Send; | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# Copyright (c) Microsoft Corporation. | ||
# Licensed under the MIT License. | ||
|
||
[package] | ||
name = "tdisp" | ||
edition.workspace = true | ||
rust-version.workspace = true | ||
|
||
[dependencies] | ||
anyhow.workspace = true | ||
bitfield-struct.workspace = true | ||
open_enum.workspace = true | ||
parking_lot.workspace = true | ||
static_assertions.workspace = true | ||
thiserror.workspace = true | ||
tracing.workspace = true | ||
zerocopy.workspace = true | ||
|
||
[lints] | ||
workspace = true |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
// Copyright (c) Microsoft Corporation. | ||
// Licensed under the MIT License. | ||
|
||
use crate::TdispGuestOperationError; | ||
use crate::TdispTdiState; | ||
use open_enum::open_enum; | ||
use zerocopy::FromBytes; | ||
use zerocopy::Immutable; | ||
use zerocopy::IntoBytes; | ||
use zerocopy::KnownLayout; | ||
|
||
/// Represents a TDISP command sent from the guest to the host. | ||
#[derive(Debug, Copy, Clone)] | ||
pub struct GuestToHostCommand { | ||
/// Device ID of the target device. | ||
pub device_id: u64, | ||
/// The command ID. | ||
pub command_id: TdispCommandId, | ||
/// The payload of the command if it has one. | ||
pub payload: TdispCommandRequestPayload, | ||
} | ||
|
||
/// Represents a response from a TDISP command sent to the host by a guest. | ||
#[derive(Debug, Clone)] | ||
pub struct GuestToHostResponse { | ||
/// The command ID. | ||
pub command_id: TdispCommandId, | ||
/// The result status of the command. | ||
pub result: TdispGuestOperationError, | ||
/// The state of the TDI before the command was executed. | ||
pub tdi_state_before: TdispTdiState, | ||
/// The state of the TDI after the command was executed. | ||
pub tdi_state_after: TdispTdiState, | ||
/// The payload of the response if it has one. | ||
pub payload: TdispCommandResponsePayload, | ||
} | ||
|
||
open_enum! { | ||
/// Represents the command type for a packet sent from the guest to the host or | ||
/// the response from the host to the guest. | ||
pub enum TdispCommandId: u64 { | ||
/// Invalid command id. | ||
UNKNOWN = 0, | ||
|
||
/// Request the device's TDISP interface information. | ||
GET_DEVICE_INTERFACE_INFO = 1, | ||
|
||
/// Bind the device to the current partition and transition to Locked. | ||
BIND = 2, | ||
|
||
/// Get the TDI report for attestation from the host for the device. | ||
GET_TDI_REPORT = 3, | ||
|
||
/// Transition the device to the Start state after successful attestation. | ||
START_TDI = 4, | ||
|
||
/// Unbind the device from the partition, reverting it back to the Unlocked state. | ||
UNBIND = 5, | ||
} | ||
} | ||
|
||
/// Represents the TDISP device interface information, such as the version and supported features. | ||
#[derive(Debug, Clone, Copy, FromBytes, IntoBytes, KnownLayout, Immutable)] | ||
pub struct TdispDeviceInterfaceInfo { | ||
/// The major version for the interface. This does not necessarily match to a TDISP specification version. | ||
/// [TDISP TODO] dead_code | ||
pub interface_version_major: u32, | ||
|
||
/// The minor version for the interface. This does not necessarily match to a TDISP specification version. | ||
/// [TDISP TODO] dead_code | ||
pub interface_version_minor: u32, | ||
|
||
/// [TDISP TODO] Placeholder for bitfield advertising feature set capabilities. | ||
pub supported_features: u64, | ||
|
||
/// Device ID used to communicate with firmware for this particular device. | ||
pub tdisp_device_id: u64, | ||
} | ||
|
||
/// Serialized to and from the payload field of a TdispCommandResponse | ||
#[derive(Debug, Clone)] | ||
pub enum TdispCommandResponsePayload { | ||
/// No payload. | ||
None, | ||
|
||
/// TdispCommandId::GetDeviceInterfaceInfo | ||
GetDeviceInterfaceInfo(TdispDeviceInterfaceInfo), | ||
|
||
/// TdispCommandId::GetTdiReport | ||
GetTdiReport(TdispCommandResponseGetTdiReport), | ||
} | ||
|
||
/// Serialized to and from the payload field of a TdispCommandRequest | ||
#[derive(Debug, Copy, Clone)] | ||
pub enum TdispCommandRequestPayload { | ||
/// No payload. | ||
None, | ||
|
||
/// TdispCommandId::Unbind | ||
Unbind(TdispCommandRequestUnbind), | ||
|
||
/// TdispCommandId::GetTdiReport | ||
GetTdiReport(TdispCommandRequestGetTdiReport), | ||
} | ||
|
||
/// Represents a request to unbind the device back to the Unlocked state. | ||
#[derive(Debug, Copy, Clone, FromBytes, IntoBytes, KnownLayout, Immutable)] | ||
pub struct TdispCommandRequestUnbind { | ||
/// The reason for the unbind. See: `TdispGuestUnbindReason` | ||
pub unbind_reason: u64, | ||
} | ||
|
||
/// Represents a request to get a specific device report form the TDI. | ||
#[derive(Debug, Clone, Copy, FromBytes, IntoBytes, KnownLayout, Immutable)] | ||
pub struct TdispCommandRequestGetTdiReport { | ||
/// The type of report to request. | ||
/// See: `TdispDeviceReportType`` | ||
pub report_type: u32, | ||
} | ||
|
||
/// Represents the payload of the resposne for a TdispCommandId::GetTdiReport. | ||
#[derive(Debug, Clone)] | ||
pub struct TdispCommandResponseGetTdiReport { | ||
/// The type of report requested. | ||
/// See: `TdispDeviceReportType`` | ||
pub report_type: u32, | ||
|
||
/// The buffer containing the requested report. | ||
pub report_buffer: Vec<u8>, | ||
} | ||
|
||
/// Represents the serialized form of a TdispCommandRequestGetTdiReport. | ||
#[derive(Debug, Clone, Copy, FromBytes, IntoBytes, KnownLayout, Immutable)] | ||
pub struct TdispSerializedCommandRequestGetTdiReport { | ||
/// The type of report to request. See: `TdispDeviceReportType`` | ||
pub report_type: u32, | ||
|
||
/// The size of the report buffer. | ||
pub report_buffer_size: u32, | ||
// The remainder of the `report_buffer_size` bytes to follow are the bytes of the returned report. | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can all these functions just be
async
instead of doing manualimpl Future
s?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the quick jump on this PR :)
I was recommended to use
impl Future
for traits instead of async by rust_analyzer. I believe this has to do with the way that async needs to express itself in traits vs. its implementations. I do not really understand it further than that.