Skip to content
Merged
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
14 changes: 12 additions & 2 deletions src/devices/vmcall_raw/src/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use crate::transport::vmcall::{
vmcall_raw_transport_can_recv, vmcall_raw_transport_dequeue, vmcall_raw_transport_enqueue,
vmcall_raw_transport_init, VMCALL_MIG_CONTEXT_FLAGS,
vmcall_raw_transport_init, VMCALL_MIG_CONTEXT_FLAGS, VMCALL_RAW_SEND_PAYLOAD_MTU,
};
use core::sync::atomic::AtomicBool;

Expand Down Expand Up @@ -61,7 +61,17 @@ impl VmcallRaw {
}

pub async fn send(&mut self, buf: &[u8], _flags: u32) -> Result<usize> {
let _ = vmcall_raw_transport_enqueue(self, buf).await?;
// A single Service.MigTD.Send VMCALL can only carry one MTU-sized
// payload (the same cap the receive side advertises). Chunk here so
// callers that don't loop on partial writes (TLS, SPDM transport)
// keep working when the pre-session policy + issuer chain blob
// exceeds one VMCALL.
let mut sent = 0;
while sent < buf.len() {
let end = core::cmp::min(buf.len(), sent + VMCALL_RAW_SEND_PAYLOAD_MTU);
let _ = vmcall_raw_transport_enqueue(self, &buf[sent..end]).await?;
sent = end;
}
Ok(buf.len())
}

Expand Down
11 changes: 10 additions & 1 deletion src/devices/vmcall_raw/src/transport/vmcall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,16 @@ use td_payload::arch::idt::InterruptStack;
use td_payload::mm::shared::SharedMemory;
use tdx_tdcall::tdx;

const MAX_VMCALL_RAW_STREAM_MTU: usize = 0x1000 * 16;
pub(crate) const MAX_VMCALL_RAW_STREAM_MTU: usize = 0x1000 * 16;
/// GHCI 1.5 buffer header overhead (8-byte status + 4-byte length) prepended
/// by `vmcall_raw_transport_enqueue` to each VMCALL payload.
pub(crate) const VMCALL_RAW_GHCI_HEADER_LEN: usize = 12;
/// Largest payload that can ride in a single `Service.MigTD.Send` VMCALL.
/// The VMM-side buffer for the migration data channel matches the MTU the
/// receive side advertises; sending more than this in one VMCALL fails with
/// TDX_VMCALL_STATUS != SUCCESS.
pub(crate) const VMCALL_RAW_SEND_PAYLOAD_MTU: usize =
MAX_VMCALL_RAW_STREAM_MTU - VMCALL_RAW_GHCI_HEADER_LEN;
const VMCALL_VECTOR: u8 = 0x52;

lazy_static! {
Expand Down
Loading