@@ -63,7 +63,7 @@ limitations under the License.
6363use std:: fmt:: Debug ;
6464use std:: mem:: { offset_of, size_of} ;
6565
66- use hyperlight_common:: mem:: { GuestMemoryRegion , HyperlightPEB , PAGE_SIZE_USIZE } ;
66+ use hyperlight_common:: mem:: { HyperlightPEB , PAGE_SIZE_USIZE } ;
6767use tracing:: { Span , instrument} ;
6868
6969use super :: memory_region:: MemoryRegionType :: { Code , Heap , InitData , Peb } ;
@@ -92,6 +92,7 @@ pub(crate) struct SandboxMemoryLayout {
9292 peb_output_data_offset : usize ,
9393 peb_init_data_offset : usize ,
9494 peb_heap_data_offset : usize ,
95+ peb_file_mappings_offset : usize ,
9596
9697 guest_heap_buffer_offset : usize ,
9798 init_data_offset : usize ,
@@ -141,6 +142,10 @@ impl Debug for SandboxMemoryLayout {
141142 "Guest Heap Offset" ,
142143 & format_args ! ( "{:#x}" , self . peb_heap_data_offset) ,
143144 )
145+ . field (
146+ "File Mappings Offset" ,
147+ & format_args ! ( "{:#x}" , self . peb_file_mappings_offset) ,
148+ )
144149 . field (
145150 "Guest Heap Buffer Offset" ,
146151 & format_args ! ( "{:#x}" , self . guest_heap_buffer_offset) ,
@@ -211,13 +216,25 @@ impl SandboxMemoryLayout {
211216 let peb_output_data_offset = peb_offset + offset_of ! ( HyperlightPEB , output_stack) ;
212217 let peb_init_data_offset = peb_offset + offset_of ! ( HyperlightPEB , init_data) ;
213218 let peb_heap_data_offset = peb_offset + offset_of ! ( HyperlightPEB , guest_heap) ;
219+ let peb_file_mappings_offset = peb_offset + offset_of ! ( HyperlightPEB , file_mappings) ;
214220
215221 // The following offsets are the actual values that relate to memory layout,
216222 // which are written to PEB struct
217223 let peb_address = Self :: BASE_ADDRESS + peb_offset;
218- // make sure heap buffer starts at 4K boundary
219- let guest_heap_buffer_offset = ( peb_heap_data_offset + size_of :: < GuestMemoryRegion > ( ) )
220- . next_multiple_of ( PAGE_SIZE_USIZE ) ;
224+ // make sure heap buffer starts at 4K boundary.
225+ // The FileMappingInfo array is stored immediately after the PEB struct.
226+ // We statically reserve space for MAX_FILE_MAPPINGS entries so that
227+ // the heap never overlaps the array, even when all slots are used.
228+ // The host writes file mapping metadata here via write_file_mapping_entry;
229+ // the guest only reads the entries. We don't know at layout time how
230+ // many file mappings the host will register, so we reserve space for
231+ // the maximum number.
232+ // The heap starts at the next page boundary after this reserved area.
233+ let file_mappings_array_end = peb_offset
234+ + size_of :: < HyperlightPEB > ( )
235+ + hyperlight_common:: mem:: MAX_FILE_MAPPINGS
236+ * size_of :: < hyperlight_common:: mem:: FileMappingInfo > ( ) ;
237+ let guest_heap_buffer_offset = file_mappings_array_end. next_multiple_of ( PAGE_SIZE_USIZE ) ;
221238
222239 // make sure init data starts at 4K boundary
223240 let init_data_offset =
@@ -230,6 +247,7 @@ impl SandboxMemoryLayout {
230247 peb_output_data_offset,
231248 peb_init_data_offset,
232249 peb_heap_data_offset,
250+ peb_file_mappings_offset,
233251 sandbox_memory_config : cfg,
234252 code_size,
235253 guest_heap_buffer_offset,
@@ -350,6 +368,28 @@ impl SandboxMemoryLayout {
350368 self . peb_heap_data_offset
351369 }
352370
371+ /// Get the offset in guest memory to the file_mappings count field
372+ /// (the `size` field of the `GuestMemoryRegion` in the PEB).
373+ pub ( crate ) fn get_file_mappings_size_offset ( & self ) -> usize {
374+ self . peb_file_mappings_offset
375+ }
376+
377+ /// Get the offset in guest memory to the file_mappings pointer field.
378+ fn get_file_mappings_pointer_offset ( & self ) -> usize {
379+ self . get_file_mappings_size_offset ( ) + size_of :: < u64 > ( )
380+ }
381+
382+ /// Get the offset in snapshot memory where the FileMappingInfo array starts
383+ /// (immediately after the PEB struct, within the same page).
384+ pub ( crate ) fn get_file_mappings_array_offset ( & self ) -> usize {
385+ self . peb_offset + size_of :: < HyperlightPEB > ( )
386+ }
387+
388+ /// Get the guest address of the FileMappingInfo array.
389+ fn get_file_mappings_array_gva ( & self ) -> u64 {
390+ ( Self :: BASE_ADDRESS + self . get_file_mappings_array_offset ( ) ) as u64
391+ }
392+
353393 /// Get the offset of the heap pointer in guest memory,
354394 #[ instrument( skip_all, parent = Span :: current( ) , level= "Trace" ) ]
355395 fn get_heap_pointer_offset ( & self ) -> usize {
@@ -446,9 +486,12 @@ impl SandboxMemoryLayout {
446486 ) ) ;
447487 }
448488
449- // PEB
489+ // PEB + preallocated FileMappingInfo array
490+ let peb_and_array_size = size_of :: < HyperlightPEB > ( )
491+ + hyperlight_common:: mem:: MAX_FILE_MAPPINGS
492+ * size_of :: < hyperlight_common:: mem:: FileMappingInfo > ( ) ;
450493 let heap_offset = builder. push_page_aligned (
451- size_of :: < HyperlightPEB > ( ) ,
494+ peb_and_array_size ,
452495 MemoryRegionFlags :: READ | MemoryRegionFlags :: WRITE ,
453496 Peb ,
454497 ) ;
@@ -588,6 +631,18 @@ impl SandboxMemoryLayout {
588631 shared_mem. write_u64 ( self . get_heap_size_offset ( ) , self . heap_size . try_into ( ) ?) ?;
589632 shared_mem. write_u64 ( self . get_heap_pointer_offset ( ) , addr) ?;
590633
634+ // Set up the file_mappings descriptor in the PEB.
635+ // - The `size` field holds the number of valid FileMappingInfo
636+ // entries currently written (initially 0 — entries are added
637+ // later by map_file_cow / evolve).
638+ // - The `ptr` field holds the guest address of the preallocated
639+ // FileMappingInfo array
640+ shared_mem. write_u64 ( self . get_file_mappings_size_offset ( ) , 0 ) ?;
641+ shared_mem. write_u64 (
642+ self . get_file_mappings_pointer_offset ( ) ,
643+ self . get_file_mappings_array_gva ( ) ,
644+ ) ?;
645+
591646 // End of setting up the PEB
592647
593648 // The input and output data regions do not have their layout
@@ -611,7 +666,11 @@ mod tests {
611666 // in order of layout
612667 expected_size += layout. code_size ;
613668
614- expected_size += size_of :: < HyperlightPEB > ( ) . next_multiple_of ( PAGE_SIZE_USIZE ) ;
669+ // PEB + preallocated FileMappingInfo array
670+ let peb_and_array = size_of :: < HyperlightPEB > ( )
671+ + hyperlight_common:: mem:: MAX_FILE_MAPPINGS
672+ * size_of :: < hyperlight_common:: mem:: FileMappingInfo > ( ) ;
673+ expected_size += peb_and_array. next_multiple_of ( PAGE_SIZE_USIZE ) ;
615674
616675 expected_size += layout. heap_size . next_multiple_of ( PAGE_SIZE_USIZE ) ;
617676
0 commit comments