Skip to content

Commit 05913f7

Browse files
committed
fix: validate queue types at construction
Signed-off-by: Tomasz Andrzejak <andreiltd@gmail.com>
1 parent e372fa2 commit 05913f7

1 file changed

Lines changed: 60 additions & 48 deletions

File tree

src/hyperlight_host/src/mem/layout.rs

Lines changed: 60 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
use std::fmt::Debug;
5555
use std::mem::size_of;
5656

57-
use hyperlight_common::layout::TransportArena;
57+
use hyperlight_common::layout::{QueueDims, TransportArena};
5858
use hyperlight_common::mem::HyperlightPEB;
5959
use hyperlight_common::vmem::PAGE_SIZE;
6060
use tracing::{Span, instrument};
@@ -255,18 +255,16 @@ pub(crate) struct SandboxMemoryLayout {
255255
init_data_permissions: Option<MemoryRegionFlags>,
256256
/// The size of the scratch region in physical memory.
257257
scratch_size: usize,
258-
/// Number of descriptors in the G2H virtqueue.
259-
g2h_queue_size: usize,
260-
/// Number of descriptors in the H2G virtqueue.
261-
h2g_queue_size: usize,
258+
/// G2H ring and buffer pool dimensions.
259+
g2h_dims: QueueDims,
260+
/// H2G ring and buffer pool dimensions.
261+
h2g_dims: QueueDims,
262262
/// Capacity of each G2H upper-tier buffer.
263263
g2h_buffer_size: usize,
264264
/// Capacity of each H2G buffer.
265265
h2g_buffer_size: usize,
266-
/// Number of pages in the G2H buffer pool.
267-
g2h_pool_pages: usize,
268-
/// Number of pages in the H2G buffer pool.
269-
h2g_pool_pages: usize,
266+
/// Fixed ring and pool placement within scratch.
267+
transport_arena: TransportArena,
270268
/// Size of the primary guest memory region at `BASE_ADDRESS`
271269
/// (code, PEB, heap, init data). For a snapshot-backed layout
272270
/// this is also the guest-visible prefix of the host snapshot
@@ -301,12 +299,12 @@ impl Debug for SandboxMemoryLayout {
301299
&format_args!("{:#x}", self.output_data_size),
302300
)
303301
.field("Scratch Size", &format_args!("{:#x}", self.scratch_size))
304-
.field("G2H Queue Size", &self.g2h_queue_size)
305-
.field("H2G Queue Size", &self.h2g_queue_size)
302+
.field("G2H Queue Size", &self.get_g2h_queue_size())
303+
.field("H2G Queue Size", &self.get_h2g_queue_size())
306304
.field("G2H Buffer Size", &self.g2h_buffer_size)
307305
.field("H2G Buffer Size", &self.h2g_buffer_size)
308-
.field("G2H Pool Pages", &self.g2h_pool_pages)
309-
.field("H2G Pool Pages", &self.h2g_pool_pages)
306+
.field("G2H Pool Pages", &self.get_g2h_pool_pages())
307+
.field("H2G Pool Pages", &self.get_h2g_pool_pages())
310308
.field("Snapshot Size", &format_args!("{:#x}", self.snapshot_size))
311309
.field("PT Size", &format_args!("{:#x}", self.pt_size.unwrap_or(0)))
312310
.field(
@@ -380,6 +378,15 @@ impl SandboxMemoryLayout {
380378
return Err(MemoryRequestTooSmall(scratch_size, min_scratch_size));
381379
}
382380

381+
let g2h_dims = QueueDims::new(g2h_queue_size, g2h_pool_pages)
382+
.ok_or_else(|| new_error!("invalid G2H queue dimensions"))?;
383+
let h2g_dims = QueueDims::new(h2g_queue_size, h2g_pool_pages)
384+
.ok_or_else(|| new_error!("invalid H2G queue dimensions"))?;
385+
let arena_base_gpa = hyperlight_common::layout::scratch_base_gpa(scratch_size)
386+
+ (input_data_size + output_data_size).next_multiple_of(PAGE_SIZE) as u64;
387+
let transport_arena = TransportArena::new(arena_base_gpa, g2h_dims, h2g_dims)
388+
.ok_or_else(|| new_error!("invalid virtqueue arena dimensions"))?;
389+
383390
let mut ret = Self {
384391
input_data_size,
385392
output_data_size,
@@ -389,12 +396,11 @@ impl SandboxMemoryLayout {
389396
init_data_permissions,
390397
pt_size: None,
391398
scratch_size,
392-
g2h_queue_size,
393-
h2g_queue_size,
399+
g2h_dims,
400+
h2g_dims,
394401
g2h_buffer_size,
395402
h2g_buffer_size,
396-
g2h_pool_pages,
397-
h2g_pool_pages,
403+
transport_arena,
398404
snapshot_size: 0,
399405
};
400406
ret.set_snapshot_size(ret.get_memory_size()?);
@@ -431,12 +437,12 @@ impl SandboxMemoryLayout {
431437

432438
#[allow(dead_code)]
433439
pub(crate) fn get_g2h_queue_size(&self) -> usize {
434-
self.g2h_queue_size
440+
usize::from(self.g2h_dims.size().get())
435441
}
436442

437443
#[allow(dead_code)]
438444
pub(crate) fn get_h2g_queue_size(&self) -> usize {
439-
self.h2g_queue_size
445+
usize::from(self.h2g_dims.size().get())
440446
}
441447

442448
#[allow(dead_code)]
@@ -451,22 +457,20 @@ impl SandboxMemoryLayout {
451457

452458
#[allow(dead_code)]
453459
pub(crate) fn get_g2h_pool_pages(&self) -> usize {
454-
self.g2h_pool_pages
460+
self.g2h_dims.pool_pages().get()
455461
}
456462

457463
#[allow(dead_code)]
458464
pub(crate) fn get_h2g_pool_pages(&self) -> usize {
459-
self.h2g_pool_pages
465+
self.h2g_dims.pool_pages().get()
460466
}
461467

462-
pub(crate) fn get_g2h_queue_dims(&self) -> hyperlight_common::layout::QueueDims {
463-
hyperlight_common::layout::QueueDims::new(self.g2h_queue_size, self.g2h_pool_pages)
464-
.expect("validated G2H queue dimensions")
468+
pub(crate) fn get_g2h_queue_dims(&self) -> QueueDims {
469+
self.g2h_dims
465470
}
466471

467-
pub(crate) fn get_h2g_queue_dims(&self) -> hyperlight_common::layout::QueueDims {
468-
hyperlight_common::layout::QueueDims::new(self.h2g_queue_size, self.h2g_pool_pages)
469-
.expect("validated H2G queue dimensions")
472+
pub(crate) fn get_h2g_queue_dims(&self) -> QueueDims {
473+
self.h2g_dims
470474
}
471475

472476
/// Guest-visible prefix size of the snapshot blob.
@@ -494,10 +498,10 @@ impl SandboxMemoryLayout {
494498
let min_fixed_scratch = hyperlight_common::layout::min_scratch_size(
495499
self.input_data_size,
496500
self.output_data_size,
497-
self.g2h_queue_size,
498-
self.h2g_queue_size,
499-
self.g2h_pool_pages,
500-
self.h2g_pool_pages,
501+
self.get_g2h_queue_size(),
502+
self.get_h2g_queue_size(),
503+
self.get_g2h_pool_pages(),
504+
self.get_h2g_pool_pages(),
501505
);
502506
let min_scratch = min_fixed_scratch.saturating_add(size);
503507
if self.scratch_size < min_scratch {
@@ -760,36 +764,23 @@ impl SandboxMemoryLayout {
760764
/// Offset from the beginning of the scratch region to the location
761765
/// where page tables are eagerly copied on restore.
762766
pub(crate) fn get_pt_base_scratch_offset(&self) -> usize {
763-
self.get_virtq_base_scratch_offset() + self.get_transport_arena().size()
767+
(self.get_pt_base_gpa() - hyperlight_common::layout::scratch_base_gpa(self.scratch_size))
768+
as usize
764769
}
765770

766771
/// Base GPA to which the page tables are eagerly copied on restore.
767772
pub(crate) fn get_pt_base_gpa(&self) -> u64 {
768-
hyperlight_common::layout::scratch_base_gpa(self.scratch_size)
769-
+ self.get_pt_base_scratch_offset() as u64
773+
self.transport_arena.end_addr()
770774
}
771775

772776
/// First GPA available to the guest scratch allocator.
773777
pub(crate) fn get_first_free_scratch_gpa(&self) -> u64 {
774778
self.get_pt_base_gpa() + self.pt_size.unwrap_or(0) as u64
775779
}
776780

777-
fn get_virtq_base_scratch_offset(&self) -> usize {
778-
(self.input_data_size + self.output_data_size)
779-
.next_multiple_of(hyperlight_common::vmem::PAGE_SIZE)
780-
}
781-
782781
/// Exact transport placement in the fixed scratch prefix.
783782
pub(crate) fn get_transport_arena(&self) -> TransportArena {
784-
let base_gpa = hyperlight_common::layout::scratch_base_gpa(self.scratch_size)
785-
+ self.get_virtq_base_scratch_offset() as u64;
786-
787-
TransportArena::new(
788-
base_gpa,
789-
self.get_g2h_queue_dims(),
790-
self.get_h2g_queue_dims(),
791-
)
792-
.expect("validated virtqueue arena dimensions")
783+
self.transport_arena
793784
}
794785

795786
/// Total size of guest memory in `self`'s memory layout.
@@ -847,6 +838,27 @@ mod tests {
847838
);
848839
}
849840

841+
#[test]
842+
fn transport_arena_after_unaligned_io_buffers() {
843+
let mut cfg = SandboxConfiguration::default();
844+
cfg.set_input_data_size(0x4001);
845+
cfg.set_output_data_size(0x2001);
846+
let mut layout = SandboxMemoryLayout::new(cfg, 4096, 0, None).unwrap();
847+
let arena = layout.get_transport_arena();
848+
let scratch_base = hyperlight_common::layout::scratch_base_gpa(layout.get_scratch_size());
849+
850+
assert_eq!(arena.base_addr(), scratch_base + 0x7000);
851+
assert_eq!(layout.get_pt_base_gpa(), arena.end_addr());
852+
853+
layout.set_pt_size(PAGE_SIZE).unwrap();
854+
855+
assert_eq!(layout.get_transport_arena(), arena);
856+
assert_eq!(
857+
layout.get_first_free_scratch_gpa(),
858+
arena.end_addr() + PAGE_SIZE as u64
859+
);
860+
}
861+
850862
#[test]
851863
fn transport_memory_is_part_of_minimum_scratch_size() {
852864
let mut cfg = SandboxConfiguration::default();

0 commit comments

Comments
 (0)