Skip to content

Commit 4a0e61b

Browse files
committed
Add CCA feature
This is WIP Signed-off-by: Matias Ezequiel Vara Larsen <[email protected]>
1 parent 86f75cd commit 4a0e61b

File tree

8 files changed

+208
-26
lines changed

8 files changed

+208
-26
lines changed

Makefile

+3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ ifeq ($(SEV),1)
2727
INIT_SRC += $(SNP_INIT_SRC)
2828
BUILD_INIT = 0
2929
endif
30+
ifeq ($(CCA), 1)
31+
FEATURE_FLAGS := --features cca
32+
endif
3033
ifeq ($(GPU),1)
3134
FEATURE_FLAGS += --features gpu
3235
endif

src/arch/src/aarch64/fdt.rs

+3
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,10 @@ fn create_psci_node(fdt: &mut FdtWriter) -> Result<()> {
285285
// Two methods available: hvc and smc.
286286
// As per documentation, PSCI calls between a guest and hypervisor may use the HVC conduit instead of SMC.
287287
// So, since we are using kvm, we need to use hvc.
288+
#[cfg(not(feature = "cca"))]
288289
fdt.property_string("method", "hvc")?;
290+
#[cfg(feature = "cca")]
291+
fdt.property_string("method", "smc")?;
289292
fdt.end_node(node)?;
290293

291294
Ok(())

src/arch/src/aarch64/linux/regs.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,10 @@ arm64_sys_reg!(MPIDR_EL1, 3, 0, 0, 0, 5);
125125
/// * `boot_ip` - Starting instruction pointer.
126126
/// * `mem` - Reserved DRAM for current VM.
127127
pub fn setup_regs(vcpu: &VcpuFd, cpu_id: u8, boot_ip: u64, mem: &GuestMemoryMmap) -> Result<()> {
128-
// Get the register index of the PSTATE (Processor State) register.
128+
// PSTATE cannot be accesed from the host in CCA
129+
#[cfg(not(feature = "cca"))]
129130
#[allow(deref_nullptr)]
131+
// Get the register index of the PSTATE (Processor State) register.
130132
vcpu.set_one_reg(arm64_core_reg!(pstate), &PSTATE_FAULT_BITS_64.to_le_bytes())
131133
.map_err(Error::SetCoreRegister)?;
132134

src/arch/src/aarch64/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ pub fn arch_memory_regions(size: usize) -> (ArchMemoryInfo, Vec<(GuestAddress, u
6969
} else {
7070
vec![
7171
(GuestAddress(layout::DRAM_MEM_START), dram_size),
72-
(GuestAddress(shm_start_addr), MMIO_SHM_SIZE as usize),
72+
//(GuestAddress(shm_start_addr), MMIO_SHM_SIZE as usize),
7373
]
7474
};
7575

src/vmm/src/builder.rs

+118-15
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33

44
//! Enables pre-boot setup, instantiation and booting of a Firecracker VMM.
55
6+
use cca::Algo;
67
#[cfg(target_os = "macos")]
78
use crossbeam_channel::{unbounded, Sender};
9+
use std::cmp::max;
810
use std::fmt::{Display, Formatter};
911
use std::fs::File;
1012
use std::io;
@@ -29,9 +31,6 @@ use devices::virtio::{port_io, MmioTransport, PortDescription, Vsock};
2931
#[cfg(target_os = "macos")]
3032
use hvf::MemoryMapping;
3133

32-
#[cfg(feature = "tee")]
33-
use kbs_types::Tee;
34-
3534
use crate::device_manager;
3635
#[cfg(feature = "tee")]
3736
use crate::resources::TeeConfig;
@@ -49,13 +48,16 @@ use crate::vmm_config::fs::FsBuilder;
4948
use crate::vmm_config::kernel_bundle::{InitrdBundle, QbootBundle};
5049
#[cfg(target_os = "linux")]
5150
use crate::vstate::KvmContext;
52-
#[cfg(all(target_os = "linux", feature = "tee"))]
51+
#[cfg(all(target_os = "linux", any(feature = "tee", feature = "cca")))]
5352
use crate::vstate::MeasuredRegion;
5453
use crate::vstate::{Error as VstateError, Vcpu, VcpuConfig, Vm};
54+
use arch::aarch64::layout;
5555
use arch::ArchMemoryInfo;
5656
#[cfg(feature = "tee")]
5757
use arch::InitrdConfig;
5858
#[cfg(feature = "tee")]
59+
use kbs_types::Tee;
60+
#[cfg(feature = "tee")]
5961
use kvm_bindings::KVM_MAX_CPUID_ENTRIES;
6062
use libc::{STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO};
6163
use nix::unistd::isatty;
@@ -68,7 +70,9 @@ use vm_memory::mmap::MmapRegion;
6870
#[cfg(any(target_arch = "aarch64", feature = "tee"))]
6971
use vm_memory::Bytes;
7072
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;
7276

7377
#[cfg(feature = "efi")]
7478
static 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: 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,52 @@ 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+
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+
686766
vmm.start_vcpus(vcpus)
687767
.map_err(StartMicrovmError::Internal)?;
688768

@@ -809,7 +889,7 @@ fn load_cmdline(vmm: &Vmm) -> std::result::Result<(), StartMicrovmError> {
809889
.map_err(StartMicrovmError::LoadCommandline)
810890
}
811891

812-
#[cfg(all(target_os = "linux", not(feature = "tee")))]
892+
#[cfg(all(target_os = "linux", not(feature = "tee"), not(feature = "cca")))]
813893
pub(crate) fn setup_vm(
814894
guest_memory: &GuestMemoryMmap,
815895
) -> std::result::Result<Vm, StartMicrovmError> {
@@ -824,6 +904,29 @@ pub(crate) fn setup_vm(
824904
.map_err(StartMicrovmError::Internal)?;
825905
Ok(vm)
826906
}
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+
}
827930
#[cfg(all(target_os = "linux", feature = "tee"))]
828931
pub(crate) fn setup_vm(
829932
kvm: &KvmContext,
@@ -1021,7 +1124,7 @@ fn create_vcpus_aarch64(
10211124
) -> super::Result<Vec<Vcpu>> {
10221125
let mut vcpus = Vec::with_capacity(vcpu_config.vcpu_count as usize);
10231126
for cpu_index in 0..vcpu_config.vcpu_count {
1024-
let mut vcpu = Vcpu::new_aarch64(
1127+
let mut vcpu: Vcpu = Vcpu::new_aarch64(
10251128
cpu_index,
10261129
vm.fd(),
10271130
exit_evt.try_clone().map_err(Error::EventFd)?,

src/vmm/src/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -55,15 +55,20 @@ use crate::vstate::{Vcpu, VcpuHandle, VcpuResponse, Vm};
5555
use arch::ArchMemoryInfo;
5656
use arch::DeviceType;
5757
use arch::InitrdConfig;
58+
use cca::Algo;
5859
#[cfg(target_os = "macos")]
5960
use crossbeam_channel::Sender;
6061
use devices::virtio::VmmExitObserver;
6162
use devices::BusDevice;
6263
use kernel::cmdline::Cmdline as KernelCmdline;
64+
use kvm_bindings::KVM_ARM_VCPU_REC;
6365
use polly::event_manager::{self, EventManager, Subscriber};
6466
use utils::epoll::{EpollEvent, EventSet};
6567
use utils::eventfd::EventFd;
68+
use vm_memory::Address;
69+
use vm_memory::GuestMemory;
6670
use vm_memory::GuestMemoryMmap;
71+
use vm_memory::GuestMemoryRegion;
6772

6873
/// Success exit code.
6974
pub const FC_EXIT_CODE_OK: u8 = 0;

0 commit comments

Comments
 (0)