3
3
4
4
//! Enables pre-boot setup, instantiation and booting of a Firecracker VMM.
5
5
6
+ use cca:: Algo ;
6
7
#[ cfg( target_os = "macos" ) ]
7
8
use crossbeam_channel:: { unbounded, Sender } ;
9
+ use std:: cmp:: max;
8
10
use std:: fmt:: { Display , Formatter } ;
9
11
use std:: fs:: File ;
10
12
use std:: io;
@@ -29,9 +31,6 @@ use devices::virtio::{port_io, MmioTransport, PortDescription, Vsock};
29
31
#[ cfg( target_os = "macos" ) ]
30
32
use hvf:: MemoryMapping ;
31
33
32
- #[ cfg( feature = "tee" ) ]
33
- use kbs_types:: Tee ;
34
-
35
34
use crate :: device_manager;
36
35
#[ cfg( feature = "tee" ) ]
37
36
use crate :: resources:: TeeConfig ;
@@ -49,13 +48,16 @@ use crate::vmm_config::fs::FsBuilder;
49
48
use crate :: vmm_config:: kernel_bundle:: { InitrdBundle , QbootBundle } ;
50
49
#[ cfg( target_os = "linux" ) ]
51
50
use crate :: vstate:: KvmContext ;
52
- #[ cfg( all( target_os = "linux" , feature = "tee" ) ) ]
51
+ #[ cfg( all( target_os = "linux" , any ( feature = "tee" , feature = "cca" ) ) ) ]
53
52
use crate :: vstate:: MeasuredRegion ;
54
53
use crate :: vstate:: { Error as VstateError , Vcpu , VcpuConfig , Vm } ;
54
+ use arch:: aarch64:: layout;
55
55
use arch:: ArchMemoryInfo ;
56
56
#[ cfg( feature = "tee" ) ]
57
57
use arch:: InitrdConfig ;
58
58
#[ cfg( feature = "tee" ) ]
59
+ use kbs_types:: Tee ;
60
+ #[ cfg( feature = "tee" ) ]
59
61
use kvm_bindings:: KVM_MAX_CPUID_ENTRIES ;
60
62
use libc:: { STDERR_FILENO , STDIN_FILENO , STDOUT_FILENO } ;
61
63
use nix:: unistd:: isatty;
@@ -68,7 +70,9 @@ use vm_memory::mmap::MmapRegion;
68
70
#[ cfg( any( target_arch = "aarch64" , feature = "tee" ) ) ]
69
71
use vm_memory:: Bytes ;
70
72
use 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 ;
72
76
73
77
#[ cfg( feature = "efi" ) ]
74
78
static EDK2_BINARY : & [ u8 ] = include_bytes ! ( "../../../edk2/KRUN_EFI.silent.fd" ) ;
@@ -433,19 +437,49 @@ pub fn build_microvm(
433
437
m
434
438
} ;
435
439
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: 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
+
436
469
// On x86_64 always create a serial device,
437
470
// 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") {
439
473
Some ( setup_serial_device (
440
474
event_manager,
441
475
None ,
442
- None ,
476
+ // None,
443
477
// 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
+ // };
449
483
450
484
let exit_evt = EventFd :: new ( utils:: eventfd:: EFD_NONBLOCK )
451
485
. map_err ( Error :: EventFd )
@@ -559,7 +593,7 @@ pub fn build_microvm(
559
593
) ?;
560
594
}
561
595
562
- #[ cfg( not( feature = "tee" ) ) ]
596
+ #[ cfg( all ( not( feature = "tee" ) , not ( feature = "cca" ) ) ) ]
563
597
let _shm_region = Some ( VirtioShmRegion {
564
598
host_addr : guest_memory
565
599
. get_host_address ( GuestAddress ( arch_memory_info. shm_start_addr ) )
@@ -683,6 +717,52 @@ pub fn build_microvm(
683
717
println ! ( "Starting TEE/microVM." ) ;
684
718
}
685
719
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
+ if region. populate {
737
+ vmm. kvm_vm ( )
738
+ . realm
739
+ . populate (
740
+ vmm. kvm_vm ( ) . fd ( ) ,
741
+ region. guest_addr ,
742
+ region. size . try_into ( ) . unwrap ( ) ,
743
+ )
744
+ . unwrap ( ) ;
745
+ } else {
746
+ vmm. kvm_vm ( )
747
+ . realm
748
+ . initiate (
749
+ vmm. kvm_vm ( ) . fd ( ) ,
750
+ region. guest_addr ,
751
+ region. size . try_into ( ) . unwrap ( ) ,
752
+ )
753
+ . unwrap ( ) ;
754
+ }
755
+ }
756
+
757
+ let feature = KVM_ARM_VCPU_REC as i32 ;
758
+
759
+ for vcpu in vcpus. iter ( ) {
760
+ vcpu. fd . vcpu_finalize ( & feature) . unwrap ( ) ;
761
+ }
762
+
763
+ vmm. kvm_vm ( ) . realm . activate ( vmm. kvm_vm ( ) . fd ( ) ) . unwrap ( ) ;
764
+ }
765
+
686
766
vmm. start_vcpus ( vcpus)
687
767
. map_err ( StartMicrovmError :: Internal ) ?;
688
768
@@ -809,7 +889,7 @@ fn load_cmdline(vmm: &Vmm) -> std::result::Result<(), StartMicrovmError> {
809
889
. map_err ( StartMicrovmError :: LoadCommandline )
810
890
}
811
891
812
- #[ cfg( all( target_os = "linux" , not( feature = "tee" ) ) ) ]
892
+ #[ cfg( all( target_os = "linux" , not( feature = "tee" ) , not ( feature = "cca" ) ) ) ]
813
893
pub ( crate ) fn setup_vm (
814
894
guest_memory : & GuestMemoryMmap ,
815
895
) -> std:: result:: Result < Vm , StartMicrovmError > {
@@ -824,6 +904,29 @@ pub(crate) fn setup_vm(
824
904
. map_err ( StartMicrovmError :: Internal ) ?;
825
905
Ok ( vm)
826
906
}
907
+ #[ cfg( all( target_os = "linux" , feature = "cca" ) ) ]
908
+ pub ( crate ) fn setup_vm (
909
+ guest_memory : & GuestMemoryMmap ,
910
+ ) -> std:: result:: Result < Vm , StartMicrovmError > {
911
+ let kvm = KvmContext :: new ( )
912
+ . map_err ( Error :: KvmContext )
913
+ . map_err ( StartMicrovmError :: Internal ) ?;
914
+
915
+ // calculate max_addr for max_ipa
916
+ let mut max_addr = 0 ;
917
+ for ( _index, region) in guest_memory. iter ( ) . enumerate ( ) {
918
+ max_addr = max ( max_addr, region. start_addr ( ) . raw_value ( ) + region. len ( ) - 1 ) ;
919
+ }
920
+
921
+ let mut vm = Vm :: new ( kvm. fd ( ) , max_addr as usize )
922
+ . map_err ( Error :: Vm )
923
+ . map_err ( StartMicrovmError :: Internal ) ?;
924
+
925
+ vm. memory_init ( guest_memory, kvm. max_memslots ( ) , true )
926
+ . map_err ( Error :: Vm )
927
+ . map_err ( StartMicrovmError :: Internal ) ?;
928
+ Ok ( vm)
929
+ }
827
930
#[ cfg( all( target_os = "linux" , feature = "tee" ) ) ]
828
931
pub ( crate ) fn setup_vm (
829
932
kvm : & KvmContext ,
@@ -1021,7 +1124,7 @@ fn create_vcpus_aarch64(
1021
1124
) -> super :: Result < Vec < Vcpu > > {
1022
1125
let mut vcpus = Vec :: with_capacity ( vcpu_config. vcpu_count as usize ) ;
1023
1126
for cpu_index in 0 ..vcpu_config. vcpu_count {
1024
- let mut vcpu = Vcpu :: new_aarch64 (
1127
+ let mut vcpu: Vcpu = Vcpu :: new_aarch64 (
1025
1128
cpu_index,
1026
1129
vm. fd ( ) ,
1027
1130
exit_evt. try_clone ( ) . map_err ( Error :: EventFd ) ?,
0 commit comments