Skip to content

Commit

Permalink
Add CCA feature
Browse files Browse the repository at this point in the history
This is WIP

Signed-off-by: Matias Ezequiel Vara Larsen <[email protected]>
  • Loading branch information
MatiasVara committed Sep 10, 2024
1 parent 86f75cd commit 4a0e61b
Show file tree
Hide file tree
Showing 8 changed files with 208 additions and 26 deletions.
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ ifeq ($(SEV),1)
INIT_SRC += $(SNP_INIT_SRC)
BUILD_INIT = 0
endif
ifeq ($(CCA), 1)
FEATURE_FLAGS := --features cca
endif
ifeq ($(GPU),1)
FEATURE_FLAGS += --features gpu
endif
Expand Down
3 changes: 3 additions & 0 deletions src/arch/src/aarch64/fdt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,10 @@ fn create_psci_node(fdt: &mut FdtWriter) -> Result<()> {
// Two methods available: hvc and smc.
// As per documentation, PSCI calls between a guest and hypervisor may use the HVC conduit instead of SMC.
// So, since we are using kvm, we need to use hvc.
#[cfg(not(feature = "cca"))]
fdt.property_string("method", "hvc")?;
#[cfg(feature = "cca")]
fdt.property_string("method", "smc")?;
fdt.end_node(node)?;

Ok(())
Expand Down
4 changes: 3 additions & 1 deletion src/arch/src/aarch64/linux/regs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,8 +125,10 @@ arm64_sys_reg!(MPIDR_EL1, 3, 0, 0, 0, 5);
/// * `boot_ip` - Starting instruction pointer.
/// * `mem` - Reserved DRAM for current VM.
pub fn setup_regs(vcpu: &VcpuFd, cpu_id: u8, boot_ip: u64, mem: &GuestMemoryMmap) -> Result<()> {
// Get the register index of the PSTATE (Processor State) register.
// PSTATE cannot be accesed from the host in CCA
#[cfg(not(feature = "cca"))]
#[allow(deref_nullptr)]
// Get the register index of the PSTATE (Processor State) register.
vcpu.set_one_reg(arm64_core_reg!(pstate), &PSTATE_FAULT_BITS_64.to_le_bytes())
.map_err(Error::SetCoreRegister)?;

Expand Down
2 changes: 1 addition & 1 deletion src/arch/src/aarch64/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ pub fn arch_memory_regions(size: usize) -> (ArchMemoryInfo, Vec<(GuestAddress, u
} else {
vec![
(GuestAddress(layout::DRAM_MEM_START), dram_size),
(GuestAddress(shm_start_addr), MMIO_SHM_SIZE as usize),
//(GuestAddress(shm_start_addr), MMIO_SHM_SIZE as usize),
]
};

Expand Down
133 changes: 118 additions & 15 deletions src/vmm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@

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

#[cfg(feature = "tee")]
use kbs_types::Tee;

use crate::device_manager;
#[cfg(feature = "tee")]
use crate::resources::TeeConfig;
Expand All @@ -49,13 +48,16 @@ use crate::vmm_config::fs::FsBuilder;
use crate::vmm_config::kernel_bundle::{InitrdBundle, QbootBundle};
#[cfg(target_os = "linux")]
use crate::vstate::KvmContext;
#[cfg(all(target_os = "linux", feature = "tee"))]
#[cfg(all(target_os = "linux", any(feature = "tee", feature = "cca")))]
use crate::vstate::MeasuredRegion;
use crate::vstate::{Error as VstateError, Vcpu, VcpuConfig, Vm};
use arch::aarch64::layout;
use arch::ArchMemoryInfo;
#[cfg(feature = "tee")]
use arch::InitrdConfig;
#[cfg(feature = "tee")]
use kbs_types::Tee;
#[cfg(feature = "tee")]
use kvm_bindings::KVM_MAX_CPUID_ENTRIES;
use libc::{STDERR_FILENO, STDIN_FILENO, STDOUT_FILENO};
use nix::unistd::isatty;
Expand All @@ -68,7 +70,9 @@ use vm_memory::mmap::MmapRegion;
#[cfg(any(target_arch = "aarch64", feature = "tee"))]
use vm_memory::Bytes;
use vm_memory::GuestMemory;
use vm_memory::{GuestAddress, GuestMemoryMmap};
use vm_memory::{Address, GuestAddress, GuestMemoryMmap, GuestMemoryRegion};

use kvm_bindings::KVM_ARM_VCPU_REC;

#[cfg(feature = "efi")]
static EDK2_BINARY: &[u8] = include_bytes!("../../../edk2/KRUN_EFI.silent.fd");
Expand Down Expand Up @@ -433,19 +437,49 @@ pub fn build_microvm(
m
};

#[cfg(feature = "cca")]
// TODO: to fix the regions that require measurement
let measured_regions = {
let m = vec![
MeasuredRegion {
guest_addr: kernel_bundle.guest_addr,
// TODO: remove host_addr
host_addr: guest_memory
.get_host_address(GuestAddress(kernel_bundle.guest_addr))
.unwrap() as u64,
size: vm_resources.vm_config().mem_size_mib.unwrap() << 20,
populate: true,
},
/*
MeasuredRegion {
guest_addr: kernel_bundle.guest_addr + kernel_bundle.size as u64,
host_addr: guest_memory
.get_host_address(GuestAddress(kernel_bundle.guest_addr + kernel_bundle.size as u64))
.unwrap() as u64,
// this is probably wrong
size: vm_resources.vm_config().mem_size_mib.unwrap() << 20 - kernel_bundle.size,
populate: false
},
*/
];

m
};

// On x86_64 always create a serial device,
// while on aarch64 only create it if 'console=' is specified in the boot args.
let serial_device = if cfg!(feature = "efi") {
// TODO: to comment this
let serial_device = //if cfg!(feature = "efi") {
Some(setup_serial_device(
event_manager,
None,
None,
//None,
// Uncomment this to get EFI output when debugging EDK2.
// Some(Box::new(io::stdout())),
)?)
} else {
None
};
Some(Box::new(io::stdout())),
)?);
//} else {
// None
//};

let exit_evt = EventFd::new(utils::eventfd::EFD_NONBLOCK)
.map_err(Error::EventFd)
Expand Down Expand Up @@ -559,7 +593,7 @@ pub fn build_microvm(
)?;
}

#[cfg(not(feature = "tee"))]
#[cfg(all(not(feature = "tee"), not(feature = "cca")))]
let _shm_region = Some(VirtioShmRegion {
host_addr: guest_memory
.get_host_address(GuestAddress(arch_memory_info.shm_start_addr))
Expand Down Expand Up @@ -683,6 +717,52 @@ pub fn build_microvm(
println!("Starting TEE/microVM.");
}

// after this point guest memory and regs are not accesible anymore
#[cfg(feature = "cca")]
{
let _ = vmm
.kvm_vm()
.realm
.configure_measurement(vmm.kvm_vm().fd(), Algo::AlgoSha256);

vmm.kvm_vm()
.realm
.create_realm_descriptor(vmm.kvm_vm().fd())
.unwrap();

println!("Injecting and measuring memory regions. This may take a while.");

for region in measured_regions.iter() {
if region.populate {
vmm.kvm_vm()
.realm
.populate(
vmm.kvm_vm().fd(),
region.guest_addr,
region.size.try_into().unwrap(),
)
.unwrap();
} else {
vmm.kvm_vm()
.realm
.initiate(
vmm.kvm_vm().fd(),
region.guest_addr,
region.size.try_into().unwrap(),
)
.unwrap();
}
}

let feature = KVM_ARM_VCPU_REC as i32;

for vcpu in vcpus.iter() {
vcpu.fd.vcpu_finalize(&feature).unwrap();
}

vmm.kvm_vm().realm.activate(vmm.kvm_vm().fd()).unwrap();
}

vmm.start_vcpus(vcpus)
.map_err(StartMicrovmError::Internal)?;

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

#[cfg(all(target_os = "linux", not(feature = "tee")))]
#[cfg(all(target_os = "linux", not(feature = "tee"), not(feature = "cca")))]
pub(crate) fn setup_vm(
guest_memory: &GuestMemoryMmap,
) -> std::result::Result<Vm, StartMicrovmError> {
Expand All @@ -824,6 +904,29 @@ pub(crate) fn setup_vm(
.map_err(StartMicrovmError::Internal)?;
Ok(vm)
}
#[cfg(all(target_os = "linux", feature = "cca"))]
pub(crate) fn setup_vm(
guest_memory: &GuestMemoryMmap,
) -> std::result::Result<Vm, StartMicrovmError> {
let kvm = KvmContext::new()
.map_err(Error::KvmContext)
.map_err(StartMicrovmError::Internal)?;

// calculate max_addr for max_ipa
let mut max_addr = 0;
for (_index, region) in guest_memory.iter().enumerate() {
max_addr = max(max_addr, region.start_addr().raw_value() + region.len() - 1);
}

let mut vm = Vm::new(kvm.fd(), max_addr as usize)
.map_err(Error::Vm)
.map_err(StartMicrovmError::Internal)?;

vm.memory_init(guest_memory, kvm.max_memslots(), true)
.map_err(Error::Vm)
.map_err(StartMicrovmError::Internal)?;
Ok(vm)
}
#[cfg(all(target_os = "linux", feature = "tee"))]
pub(crate) fn setup_vm(
kvm: &KvmContext,
Expand Down Expand Up @@ -1021,7 +1124,7 @@ fn create_vcpus_aarch64(
) -> super::Result<Vec<Vcpu>> {
let mut vcpus = Vec::with_capacity(vcpu_config.vcpu_count as usize);
for cpu_index in 0..vcpu_config.vcpu_count {
let mut vcpu = Vcpu::new_aarch64(
let mut vcpu: Vcpu = Vcpu::new_aarch64(
cpu_index,
vm.fd(),
exit_evt.try_clone().map_err(Error::EventFd)?,
Expand Down
5 changes: 5 additions & 0 deletions src/vmm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,20 @@ use crate::vstate::{Vcpu, VcpuHandle, VcpuResponse, Vm};
use arch::ArchMemoryInfo;
use arch::DeviceType;
use arch::InitrdConfig;
use cca::Algo;
#[cfg(target_os = "macos")]
use crossbeam_channel::Sender;
use devices::virtio::VmmExitObserver;
use devices::BusDevice;
use kernel::cmdline::Cmdline as KernelCmdline;
use kvm_bindings::KVM_ARM_VCPU_REC;
use polly::event_manager::{self, EventManager, Subscriber};
use utils::epoll::{EpollEvent, EventSet};
use utils::eventfd::EventFd;
use vm_memory::Address;
use vm_memory::GuestMemory;
use vm_memory::GuestMemoryMmap;
use vm_memory::GuestMemoryRegion;

/// Success exit code.
pub const FC_EXIT_CODE_OK: u8 = 0;
Expand Down
Loading

0 comments on commit 4a0e61b

Please sign in to comment.