Skip to content

Commit d5952be

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

File tree

7 files changed

+131
-11
lines changed

7 files changed

+131
-11
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

+53-4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ use std::io;
1212
use std::os::fd::AsRawFd;
1313
use std::path::PathBuf;
1414
use std::sync::{Arc, Mutex};
15+
use std::cmp::max;
16+
use cca::Algo;
1517

1618
use super::{Error, Vmm};
1719

@@ -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::{GuestAddress, GuestMemoryMmap, GuestMemoryRegion, Address};
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");
@@ -559,7 +563,7 @@ pub fn build_microvm(
559563
)?;
560564
}
561565

562-
#[cfg(not(feature = "tee"))]
566+
#[cfg(all(not(feature = "tee"), not(feature = "cca")))]
563567
let _shm_region = Some(VirtioShmRegion {
564568
host_addr: guest_memory
565569
.get_host_address(GuestAddress(arch_memory_info.shm_start_addr))
@@ -568,6 +572,27 @@ pub fn build_microvm(
568572
size: arch_memory_info.shm_size as usize,
569573
});
570574

575+
// YOU CAN'T ACCESS GUEST MEMORY AT THIS POINT
576+
/*
577+
#[cfg(feature = "cca")]
578+
{
579+
let _ = vm.realm.configure_measurement(vm.fd(), Algo::AlgoSha256);
580+
vm.realm.create_realm_descriptor(vm.fd()).unwrap();
581+
582+
for (_index, region) in guest_memory.iter().enumerate() {
583+
vm.realm.populate(vm.fd(), region.start_addr().raw_value(), region.len()).unwrap();
584+
}
585+
let feature = KVM_ARM_VCPU_REC as i32;
586+
587+
// not really sure if the finalize and the activate should go here
588+
for vcpu in vcpus.iter() {
589+
vcpu.fd.vcpu_finalize(&feature).unwrap();
590+
}
591+
592+
vm.realm.activate(vm.fd()).unwrap();
593+
}
594+
*/
595+
571596
let mut vmm = Vmm {
572597
guest_memory,
573598
arch_memory_info,
@@ -647,6 +672,7 @@ pub fn build_microvm(
647672
#[cfg(not(feature = "tee"))]
648673
let initrd_config = None;
649674

675+
// after this point guest memory and regs are not accesible anymore
650676
vmm.configure_system(
651677
vcpus.as_slice(),
652678
&initrd_config,
@@ -809,7 +835,7 @@ fn load_cmdline(vmm: &Vmm) -> std::result::Result<(), StartMicrovmError> {
809835
.map_err(StartMicrovmError::LoadCommandline)
810836
}
811837

812-
#[cfg(all(target_os = "linux", not(feature = "tee")))]
838+
#[cfg(all(target_os = "linux", not(feature = "tee"), not(feature = "cca")))]
813839
pub(crate) fn setup_vm(
814840
guest_memory: &GuestMemoryMmap,
815841
) -> std::result::Result<Vm, StartMicrovmError> {
@@ -824,6 +850,29 @@ pub(crate) fn setup_vm(
824850
.map_err(StartMicrovmError::Internal)?;
825851
Ok(vm)
826852
}
853+
#[cfg(all(target_os = "linux", feature = "cca"))]
854+
pub(crate) fn setup_vm(
855+
guest_memory: &GuestMemoryMmap,
856+
) -> std::result::Result<Vm, StartMicrovmError> {
857+
let kvm = KvmContext::new()
858+
.map_err(Error::KvmContext)
859+
.map_err(StartMicrovmError::Internal)?;
860+
861+
// calculate max_addr for max_ipa
862+
let mut max_addr = 0;
863+
for (_index, region) in guest_memory.iter().enumerate() {
864+
max_addr = max(max_addr, region.start_addr().raw_value() + region.len() - 1);
865+
}
866+
867+
let mut vm = Vm::new(kvm.fd(), max_addr as usize)
868+
.map_err(Error::Vm)
869+
.map_err(StartMicrovmError::Internal)?;
870+
871+
vm.memory_init(guest_memory, kvm.max_memslots(), true)
872+
.map_err(Error::Vm)
873+
.map_err(StartMicrovmError::Internal)?;
874+
Ok(vm)
875+
}
827876
#[cfg(all(target_os = "linux", feature = "tee"))]
828877
pub(crate) fn setup_vm(
829878
kvm: &KvmContext,
@@ -1021,7 +1070,7 @@ fn create_vcpus_aarch64(
10211070
) -> super::Result<Vec<Vcpu>> {
10221071
let mut vcpus = Vec::with_capacity(vcpu_config.vcpu_count as usize);
10231072
for cpu_index in 0..vcpu_config.vcpu_count {
1024-
let mut vcpu = Vcpu::new_aarch64(
1073+
let mut vcpu: Vcpu = Vcpu::new_aarch64(
10251074
cpu_index,
10261075
vm.fd(),
10271076
exit_evt.try_clone().map_err(Error::EventFd)?,

src/vmm/src/lib.rs

+24
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,11 @@ use polly::event_manager::{self, EventManager, Subscriber};
6464
use utils::epoll::{EpollEvent, EventSet};
6565
use utils::eventfd::EventFd;
6666
use vm_memory::GuestMemoryMmap;
67+
use cca::Algo;
68+
use kvm_bindings::KVM_ARM_VCPU_REC;
69+
use vm_memory::GuestMemory;
70+
use vm_memory::GuestMemoryRegion;
71+
use vm_memory::Address;
6772

6873
/// Success exit code.
6974
pub const FC_EXIT_CODE_OK: u8 = 0;
@@ -299,6 +304,25 @@ impl Vmm {
299304
_smbios_oem_strings,
300305
)
301306
.map_err(Error::ConfigureSystem)?;
307+
308+
// after activation guest not accesible anymore
309+
#[cfg(feature = "cca")]
310+
{
311+
let _ = self.vm.realm.configure_measurement(self.vm.fd(), Algo::AlgoSha256);
312+
self.vm.realm.create_realm_descriptor(self.vm.fd()).unwrap();
313+
314+
for (_index, region) in self.guest_memory.iter().enumerate() {
315+
self.vm.realm.populate(self.vm.fd(), region.start_addr().raw_value(), region.len()).unwrap();
316+
}
317+
let feature = KVM_ARM_VCPU_REC as i32;
318+
319+
// not really sure if the finalize and the activate should go here
320+
for vcpu in vcpus.iter() {
321+
vcpu.fd.vcpu_finalize(&feature).unwrap();
322+
}
323+
324+
self.vm.realm.activate(self.vm.fd()).unwrap();
325+
}
302326
}
303327

304328
#[cfg(all(target_arch = "aarch64", target_os = "macos"))]

src/vmm/src/linux/vstate.rs

+44-5
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use std::cell::Cell;
1111
use std::fmt::{Display, Formatter};
1212
use std::io;
1313
use std::os::fd::RawFd;
14+
use std::cmp::max;
1415

1516
#[cfg(feature = "tee")]
1617
use std::os::unix::io::RawFd;
@@ -48,8 +49,9 @@ use kvm_bindings::{
4849
KVM_MAX_CPUID_ENTRIES, KVM_PIT_SPEAKER_DUMMY,
4950
};
5051
use kvm_bindings::{
51-
kvm_create_guest_memfd, kvm_userspace_memory_region, kvm_userspace_memory_region2,
52-
KVM_API_VERSION, KVM_MEM_GUEST_MEMFD,
52+
kvm_create_guest_memfd, kvm_userspace_memory_region, kvm_userspace_memory_region2, kvm_memory_attributes,
53+
KVM_API_VERSION, KVM_MEM_GUEST_MEMFD, KVM_VM_TYPE_ARM_REALM, KVM_VM_TYPE_ARM_IPA_SIZE_MASK,
54+
KVM_MEMORY_ATTRIBUTE_PRIVATE
5355
};
5456
use kvm_ioctls::*;
5557
use utils::eventfd::EventFd;
@@ -65,6 +67,9 @@ use sev::launch::sev as sev_launch;
6567
#[cfg(feature = "amd-sev")]
6668
use sev::launch::snp;
6769

70+
#[cfg(feature = "cca")]
71+
use cca::Realm;
72+
6873
/// Signal number (SIGRTMIN) used to kick Vcpus.
6974
pub(crate) const VCPU_RTSIG_OFFSET: i32 = 0;
7075

@@ -483,11 +488,14 @@ pub struct Vm {
483488

484489
#[cfg(feature = "amd-sev")]
485490
pub tee: Tee,
491+
492+
#[cfg(feature = "cca")]
493+
pub realm: Realm,
486494
}
487495

488496
impl Vm {
489497
/// Constructs a new `Vm` using the given `Kvm` instance.
490-
#[cfg(not(feature = "tee"))]
498+
#[cfg(all(not(feature = "tee"), not(feature = "cca")))]
491499
pub fn new(kvm: &Kvm) -> Result<Self> {
492500
//create fd for interacting with kvm-vm specific functions
493501
let vm_fd = kvm.create_vm().map_err(Error::VmFd)?;
@@ -511,6 +519,22 @@ impl Vm {
511519
})
512520
}
513521

522+
#[cfg(feature = "cca")]
523+
pub fn new(kvm: &Kvm, max_ipa: usize) -> Result<Self> {
524+
//create fd for interacting with kvm-vm specific functions
525+
let ipa_bits = max(64u32 - max_ipa.leading_zeros()- 1, 32) + 1;
526+
let vm_fd = kvm.create_vm_with_type((KVM_VM_TYPE_ARM_REALM | (ipa_bits & KVM_VM_TYPE_ARM_IPA_SIZE_MASK)).into()).map_err(Error::VmFd)?;
527+
528+
let realm = Realm::new().unwrap();
529+
530+
Ok(Vm {
531+
fd: vm_fd,
532+
#[cfg(target_arch = "aarch64")]
533+
irqchip_handle: None,
534+
realm,
535+
})
536+
}
537+
514538
#[cfg(feature = "amd-sev")]
515539
pub fn new(kvm: &Kvm, tee_config: &TeeConfig) -> Result<Self> {
516540
//create fd for interacting with kvm-vm specific functions
@@ -581,7 +605,7 @@ impl Vm {
581605
.create_guest_memfd(gmem)
582606
.map_err(Error::CreateGuestMemfd)?;
583607

584-
let memory_region = kvm_userspace_memory_region2 {
608+
let memory_region: kvm_userspace_memory_region2 = kvm_userspace_memory_region2 {
585609
slot: index as u32,
586610
flags: KVM_MEM_GUEST_MEMFD,
587611
guest_phys_addr: region.start_addr().raw_value(),
@@ -600,6 +624,14 @@ impl Vm {
600624
.set_user_memory_region2(memory_region)
601625
.map_err(Error::SetUserMemoryRegion2)?;
602626
};
627+
// set private by default when using guestmemfd
628+
let attr = kvm_memory_attributes {
629+
address: region.start_addr().raw_value(),
630+
size: region.len(),
631+
attributes: KVM_MEMORY_ATTRIBUTE_PRIVATE as u64,
632+
flags: 0,
633+
};
634+
self.fd.set_memory_attributes(attr).unwrap();
603635
} else {
604636
let memory_region = kvm_userspace_memory_region {
605637
slot: index as u32,
@@ -808,7 +840,7 @@ type VcpuCell = Cell<Option<*mut Vcpu>>;
808840

809841
/// A wrapper around creating and using a kvm-based VCPU.
810842
pub struct Vcpu {
811-
fd: VcpuFd,
843+
pub fd: VcpuFd,
812844
id: u8,
813845
mmio_bus: Option<devices::Bus>,
814846
#[allow(dead_code)]
@@ -1267,6 +1299,12 @@ impl Vcpu {
12671299
info!("Received KVM_EXIT_SHUTDOWN signal");
12681300
Ok(VcpuEmulation::Stopped)
12691301
}
1302+
VcpuExit::MemoryFault {flags, gpa, size} => {
1303+
println!("ignore memoryfault at {} {}", gpa, size);
1304+
// TODO: To setup the setmemoryproperties I need to have access to vm
1305+
// but vm is not a shared resource
1306+
Ok(VcpuEmulation::Handled)
1307+
}
12701308
// Documentation specifies that below kvm exits are considered
12711309
// errors.
12721310
VcpuExit::FailEntry(reason, vcpu) => {
@@ -1280,6 +1318,7 @@ impl Vcpu {
12801318
r => {
12811319
// TODO: Are we sure we want to finish running a vcpu upon
12821320
// receiving a vm exit that is not necessarily an error?
1321+
println!("error! {:?}", r);
12831322
error!("Unexpected exit reason on vcpu run: {:?}", r);
12841323
Err(Error::VcpuUnhandledKvmExit)
12851324
}

0 commit comments

Comments
 (0)