33
44//! Enables pre-boot setup, instantiation and booting of a Firecracker VMM.
55
6+ use cca:: Algo ;
67#[ cfg( target_os = "macos" ) ]
78use crossbeam_channel:: { unbounded, Sender } ;
9+ use std:: cmp:: max;
810use std:: fmt:: { Display , Formatter } ;
911use std:: fs:: File ;
1012use std:: io;
@@ -29,9 +31,6 @@ use devices::virtio::{port_io, MmioTransport, PortDescription, Vsock};
2931#[ cfg( target_os = "macos" ) ]
3032use hvf:: MemoryMapping ;
3133
32- #[ cfg( feature = "tee" ) ]
33- use kbs_types:: Tee ;
34-
3534use crate :: device_manager;
3635#[ cfg( feature = "tee" ) ]
3736use crate :: resources:: TeeConfig ;
@@ -49,13 +48,16 @@ use crate::vmm_config::fs::FsBuilder;
4948use crate :: vmm_config:: kernel_bundle:: { InitrdBundle , QbootBundle } ;
5049#[ cfg( target_os = "linux" ) ]
5150use crate :: vstate:: KvmContext ;
52- #[ cfg( all( target_os = "linux" , feature = "tee" ) ) ]
51+ #[ cfg( all( target_os = "linux" , any ( feature = "tee" , feature = "cca" ) ) ) ]
5352use crate :: vstate:: MeasuredRegion ;
5453use crate :: vstate:: { Error as VstateError , Vcpu , VcpuConfig , Vm } ;
54+ use arch:: aarch64:: layout;
5555use arch:: ArchMemoryInfo ;
5656#[ cfg( feature = "tee" ) ]
5757use arch:: InitrdConfig ;
5858#[ cfg( feature = "tee" ) ]
59+ use kbs_types:: Tee ;
60+ #[ cfg( feature = "tee" ) ]
5961use kvm_bindings:: KVM_MAX_CPUID_ENTRIES ;
6062use libc:: { STDERR_FILENO , STDIN_FILENO , STDOUT_FILENO } ;
6163use nix:: unistd:: isatty;
@@ -68,7 +70,9 @@ use vm_memory::mmap::MmapRegion;
6870#[ cfg( any( target_arch = "aarch64" , feature = "tee" ) ) ]
6971use vm_memory:: Bytes ;
7072use vm_memory:: GuestMemory ;
71- use vm_memory:: { GuestAddress , GuestMemoryMmap } ;
73+ use vm_memory:: { Address , GuestAddress , GuestMemoryMmap , GuestMemoryRegion } ;
74+
75+ use kvm_bindings:: KVM_ARM_VCPU_REC ;
7276
7377#[ cfg( feature = "efi" ) ]
7478static EDK2_BINARY : & [ u8 ] = include_bytes ! ( "../../../edk2/KRUN_EFI.silent.fd" ) ;
@@ -433,19 +437,49 @@ pub fn build_microvm(
433437 m
434438 } ;
435439
440+ #[ cfg( feature = "cca" ) ]
441+ // TODO: to fix the regions that require measurement
442+ let measured_regions = {
443+ let m = vec ! [
444+ MeasuredRegion {
445+ guest_addr: layout:: DRAM_MEM_START , // kernel_bundle.guest_addr
446+ // TODO: remove host_addr
447+ host_addr: guest_memory
448+ . get_host_address( GuestAddress ( kernel_bundle. guest_addr) )
449+ . unwrap( ) as u64 ,
450+ size: vm_resources. vm_config( ) . mem_size_mib. unwrap( ) << 20 ,
451+ populate: true ,
452+ } ,
453+ /*
454+ MeasuredRegion {
455+ guest_addr: kernel_bundle.guest_addr + kernel_bundle.size as u64,
456+ host_addr: guest_memory
457+ .get_host_address(GuestAddress(kernel_bundle.guest_addr + kernel_bundle.size as u64))
458+ .unwrap() as u64,
459+ // this is probably wrong
460+ size: vm_resources.vm_config().mem_size_mib.unwrap() << 20 - kernel_bundle.size,
461+ populate: false
462+ },
463+ */
464+ ] ;
465+
466+ m
467+ } ;
468+
436469 // On x86_64 always create a serial device,
437470 // while on aarch64 only create it if 'console=' is specified in the boot args.
438- let serial_device = if cfg ! ( feature = "efi" ) {
471+ // TODO: to comment this
472+ let serial_device = //if cfg!(feature = "efi") {
439473 Some ( setup_serial_device (
440474 event_manager,
441475 None ,
442- None ,
476+ // None,
443477 // Uncomment this to get EFI output when debugging EDK2.
444- // Some(Box::new(io::stdout())),
445- ) ?)
446- } else {
447- None
448- } ;
478+ Some ( Box :: new ( io:: stdout ( ) ) ) ,
479+ ) ?) ;
480+ // } else {
481+ // None
482+ // };
449483
450484 let exit_evt = EventFd :: new ( utils:: eventfd:: EFD_NONBLOCK )
451485 . map_err ( Error :: EventFd )
@@ -559,7 +593,7 @@ pub fn build_microvm(
559593 ) ?;
560594 }
561595
562- #[ cfg( not( feature = "tee" ) ) ]
596+ #[ cfg( all ( not( feature = "tee" ) , not ( feature = "cca" ) ) ) ]
563597 let _shm_region = Some ( VirtioShmRegion {
564598 host_addr : guest_memory
565599 . get_host_address ( GuestAddress ( arch_memory_info. shm_start_addr ) )
@@ -683,6 +717,53 @@ pub fn build_microvm(
683717 println ! ( "Starting TEE/microVM." ) ;
684718 }
685719
720+ // after this point guest memory and regs are not accesible anymore
721+ #[ cfg( feature = "cca" ) ]
722+ {
723+ let _ = vmm
724+ . kvm_vm ( )
725+ . realm
726+ . configure_measurement ( vmm. kvm_vm ( ) . fd ( ) , Algo :: AlgoSha256 ) ;
727+
728+ vmm. kvm_vm ( )
729+ . realm
730+ . create_realm_descriptor ( vmm. kvm_vm ( ) . fd ( ) )
731+ . unwrap ( ) ;
732+
733+ println ! ( "Injecting and measuring memory regions. This may take a while." ) ;
734+
735+ for region in measured_regions. iter ( ) {
736+ println ! ( "{:?}" , region) ;
737+ if region. populate {
738+ vmm. kvm_vm ( )
739+ . realm
740+ . populate (
741+ vmm. kvm_vm ( ) . fd ( ) ,
742+ region. guest_addr ,
743+ region. size . try_into ( ) . unwrap ( ) ,
744+ )
745+ . unwrap ( ) ;
746+ } else {
747+ vmm. kvm_vm ( )
748+ . realm
749+ . initiate (
750+ vmm. kvm_vm ( ) . fd ( ) ,
751+ region. guest_addr ,
752+ region. size . try_into ( ) . unwrap ( ) ,
753+ )
754+ . unwrap ( ) ;
755+ }
756+ }
757+
758+ let feature = KVM_ARM_VCPU_REC as i32 ;
759+
760+ for vcpu in vcpus. iter ( ) {
761+ vcpu. fd . vcpu_finalize ( & feature) . unwrap ( ) ;
762+ }
763+
764+ vmm. kvm_vm ( ) . realm . activate ( vmm. kvm_vm ( ) . fd ( ) ) . unwrap ( ) ;
765+ }
766+
686767 vmm. start_vcpus ( vcpus)
687768 . map_err ( StartMicrovmError :: Internal ) ?;
688769
@@ -809,7 +890,7 @@ fn load_cmdline(vmm: &Vmm) -> std::result::Result<(), StartMicrovmError> {
809890 . map_err ( StartMicrovmError :: LoadCommandline )
810891}
811892
812- #[ cfg( all( target_os = "linux" , not( feature = "tee" ) ) ) ]
893+ #[ cfg( all( target_os = "linux" , not( feature = "tee" ) , not ( feature = "cca" ) ) ) ]
813894pub ( crate ) fn setup_vm (
814895 guest_memory : & GuestMemoryMmap ,
815896) -> std:: result:: Result < Vm , StartMicrovmError > {
@@ -824,6 +905,29 @@ pub(crate) fn setup_vm(
824905 . map_err ( StartMicrovmError :: Internal ) ?;
825906 Ok ( vm)
826907}
908+ #[ cfg( all( target_os = "linux" , feature = "cca" ) ) ]
909+ pub ( crate ) fn setup_vm (
910+ guest_memory : & GuestMemoryMmap ,
911+ ) -> std:: result:: Result < Vm , StartMicrovmError > {
912+ let kvm = KvmContext :: new ( )
913+ . map_err ( Error :: KvmContext )
914+ . map_err ( StartMicrovmError :: Internal ) ?;
915+
916+ // calculate max_addr for max_ipa
917+ let mut max_addr = 0 ;
918+ for ( _index, region) in guest_memory. iter ( ) . enumerate ( ) {
919+ max_addr = max ( max_addr, region. start_addr ( ) . raw_value ( ) + region. len ( ) - 1 ) ;
920+ }
921+
922+ let mut vm = Vm :: new ( kvm. fd ( ) , max_addr as usize )
923+ . map_err ( Error :: Vm )
924+ . map_err ( StartMicrovmError :: Internal ) ?;
925+
926+ vm. memory_init ( guest_memory, kvm. max_memslots ( ) , true )
927+ . map_err ( Error :: Vm )
928+ . map_err ( StartMicrovmError :: Internal ) ?;
929+ Ok ( vm)
930+ }
827931#[ cfg( all( target_os = "linux" , feature = "tee" ) ) ]
828932pub ( crate ) fn setup_vm (
829933 kvm : & KvmContext ,
@@ -1021,7 +1125,7 @@ fn create_vcpus_aarch64(
10211125) -> super :: Result < Vec < Vcpu > > {
10221126 let mut vcpus = Vec :: with_capacity ( vcpu_config. vcpu_count as usize ) ;
10231127 for cpu_index in 0 ..vcpu_config. vcpu_count {
1024- let mut vcpu = Vcpu :: new_aarch64 (
1128+ let mut vcpu: Vcpu = Vcpu :: new_aarch64 (
10251129 cpu_index,
10261130 vm. fd ( ) ,
10271131 exit_evt. try_clone ( ) . map_err ( Error :: EventFd ) ?,
0 commit comments