Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update SEV-SNP implementation to run on upstream kernels #243

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 32 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions src/vmm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ polly = { path = "../polly" }

# Dependencies for amd-sev
codicon = { version = "3.0.0", optional = true }
kbs-types = { version = "0.8.0", features = ["tee-sev", "tee-snp"], optional = true }
kbs-types = { version = "0.9.2", features = ["tee-sev", "tee-snp"], optional = true }
procfs = { version = "0.12", optional = true }
rdrand = { version = "^0.8", optional = true }
serde = { version = "1.0.125", optional = true }
serde_json = { version = "1.0.64", optional = true }
sev = { version = "4.0.0", features = ["openssl"], optional = true }
sev = { version = "5.0.0", features = ["openssl"], optional = true }
curl = { version = "0.4", optional = true }
nix = "0.24.1"

Expand Down
45 changes: 15 additions & 30 deletions src/vmm/src/linux/tee/amdsnp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@ use std::{
use crate::vstate::MeasuredRegion;
use arch::x86_64::layout::*;

use sev::firmware::{guest::GuestPolicy, host::Firmware};
use sev::launch::snp::*;
use sev::{
error::FirmwareError as SevFirmwareError,
firmware::{guest::GuestPolicy, host::Firmware},
};

use kvm_bindings::{kvm_enc_region, CpuId, KVM_CPUID_FLAG_SIGNIFCANT_INDEX};
use kvm_bindings::{CpuId, KVM_CPUID_FLAG_SIGNIFCANT_INDEX};
use kvm_ioctls::VmFd;
use vm_memory::{
Bytes, GuestAddress, GuestMemory, GuestMemoryMmap, GuestMemoryRegion, GuestRegionMmap,
Expand All @@ -19,12 +22,12 @@ use vm_memory::{
pub enum Error {
CpuIdWrite,
CpuIdFull,
CreateLauncher(std::io::Error),
CreateLauncher(SevFirmwareError),
GuestMemoryWrite(vm_memory::GuestMemoryError),
GuestMemoryRead(vm_memory::GuestMemoryError),
LaunchStart(std::io::Error),
LaunchUpdate(std::io::Error),
LaunchFinish(std::io::Error),
LaunchStart(SevFirmwareError),
LaunchUpdate(SevFirmwareError),
LaunchFinish(SevFirmwareError),
MemoryEncryptRegion,
OpenFirmware(std::io::Error),
}
Expand Down Expand Up @@ -84,30 +87,17 @@ impl AmdSnp {
pub fn vm_prepare(
&self,
vm_fd: &VmFd,
guest_mem: &GuestMemoryMmap,
_guest_mem: &GuestMemoryMmap,
) -> Result<Launcher<Started, RawFd, RawFd>, Error> {
let vm_rfd = vm_fd.as_raw_fd();
let fw_rfd = self.fw.as_raw_fd();

let launcher = Launcher::new(vm_rfd, fw_rfd).map_err(Error::CreateLauncher)?;

for region in guest_mem.iter() {
// It's safe to unwrap because the guest address is valid.
let host_addr = guest_mem.get_host_address(region.start_addr()).unwrap();
let enc_region = kvm_enc_region {
addr: host_addr as u64,
size: region.len(),
};

vm_fd
.register_enc_memory_region(&enc_region)
.map_err(|_| Error::MemoryEncryptRegion)?;
}

let mut policy = GuestPolicy(0);
policy.set_smt_allowed(1);

let start = Start::new(None, policy, false, [0; 16]);
let start = Start::new(policy, [0; 16]);

let launcher = launcher.start(start).map_err(Error::LaunchStart)?;

Expand Down Expand Up @@ -281,7 +271,6 @@ impl AmdSnp {
launcher: &mut Launcher<Started, RawFd, RawFd>,
page_type: PageType,
) -> Result<(), Error> {
let dp = VmplPerms::empty();
let ga = GuestAddress(region.guest_addr);

/*
Expand All @@ -296,15 +285,11 @@ impl AmdSnp {
let ptr = bytes.ptr_guard().as_ptr();
let slice: &[u8] = unsafe { slice::from_raw_parts(ptr, region.size) };

let update = Update::new(
region.guest_addr >> 12,
slice,
false,
page_type,
(dp, dp, dp),
);
let update = Update::new(region.guest_addr >> 12, slice, page_type);

launcher.update_data(update).map_err(Error::LaunchUpdate)
launcher
.update_data(update, ga.0, region.size.try_into().unwrap())
.map_err(Error::LaunchUpdate)
}

pub fn vm_measure(
Expand Down
74 changes: 72 additions & 2 deletions src/vmm/src/linux/vstate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,23 @@ use crate::vmm_config::machine_config::CpuFeaturesTemplate;
use arch::aarch64::gic::GICDevice;
#[cfg(target_arch = "x86_64")]
use cpuid::{c3, filter_cpuid, t2, VmSpec};
#[cfg(not(feature = "amd-sev"))]
use kvm_bindings::kvm_userspace_memory_region;
#[cfg(target_arch = "x86_64")]
use kvm_bindings::{
kvm_clock_data, kvm_debugregs, kvm_irqchip, kvm_lapic_state, kvm_mp_state, kvm_pit_config,
kvm_pit_state2, kvm_regs, kvm_sregs, kvm_vcpu_events, kvm_xcrs, kvm_xsave, CpuId, MsrList,
Msrs, KVM_CLOCK_TSC_STABLE, KVM_IRQCHIP_IOAPIC, KVM_IRQCHIP_PIC_MASTER, KVM_IRQCHIP_PIC_SLAVE,
KVM_MAX_CPUID_ENTRIES, KVM_PIT_SPEAKER_DUMMY,
};
use kvm_bindings::{kvm_userspace_memory_region, KVM_API_VERSION};

#[cfg(feature = "amd-sev")]
use kvm_bindings::{
kvm_create_guest_memfd, kvm_memory_attributes, kvm_userspace_memory_region2,
KVM_MEM_GUEST_MEMFD,
};

use kvm_bindings::KVM_API_VERSION;
use kvm_ioctls::*;
use utils::eventfd::EventFd;
use utils::signal::{register_signal_handler, sigrtmin, Killable};
Expand Down Expand Up @@ -113,6 +122,9 @@ pub enum Error {
/// Error creating memory map for SHM region.
ShmMmap(io::Error),
#[cfg(feature = "amd-sev")]
/// Error setting KVM memory attributes of a region.
SetMemoryAttributes(kvm_ioctls::Error),
#[cfg(feature = "amd-sev")]
/// Error initializing the Secure Virtualization Backend (SEV).
SevSecVirtInit(SevError),
#[cfg(feature = "amd-sev")]
Expand Down Expand Up @@ -272,6 +284,10 @@ impl Display for Error {
),
SetUserMemoryRegion(e) => write!(f, "Cannot set the memory regions: {e}"),
ShmMmap(e) => write!(f, "Error creating memory map for SHM region: {e}"),
#[cfg(feature = "amd-sev")]
SetMemoryAttributes(e) => {
write!(f, "Error setting KVM memory attributes of a region: {e}")
}
#[cfg(feature = "tee")]
SevSecVirtInit(e) => {
write!(
Expand Down Expand Up @@ -507,8 +523,12 @@ impl Vm {

#[cfg(feature = "amd-sev")]
pub fn new(kvm: &Kvm, tee_config: &TeeConfig) -> Result<Self> {
const KVM_X86_SNP_VM: u64 = 4;

//create fd for interacting with kvm-vm specific functions
let vm_fd = kvm.create_vm().map_err(Error::VmFd)?;
let vm_fd = kvm
.create_vm_with_type(KVM_X86_SNP_VM)
.map_err(Error::VmFd)?;

let supported_cpuid = kvm
.get_supported_cpuid(KVM_MAX_CPUID_ENTRIES)
Expand Down Expand Up @@ -558,6 +578,8 @@ impl Vm {
if guest_mem.num_regions() > kvm_max_memslots {
return Err(Error::NotEnoughMemorySlots);
}

#[cfg(not(feature = "amd-sev"))]
for region in guest_mem.iter() {
// It's safe to unwrap because the guest address is valid.
let host_addr = guest_mem.get_host_address(region.start_addr()).unwrap();
Expand All @@ -579,6 +601,54 @@ impl Vm {
self.next_mem_slot += 1;
}

#[cfg(feature = "amd-sev")]
tylerfanelli marked this conversation as resolved.
Show resolved Hide resolved
for region in guest_mem.iter() {
// It's safe to unwrap because the guest address is valid.
let host_addr = guest_mem.get_host_address(region.start_addr()).unwrap();

// Create guest_memfd struct.
let gmem = kvm_create_guest_memfd {
size: region.len(),
flags: 0, // Unused.
reserved: [0; 6],
};

// Create KVM guest_memfd.
let guest_memfd = self.fd.create_guest_memfd(gmem).unwrap();

// Create memory region.
let memory_region = kvm_userspace_memory_region2 {
slot: self.next_mem_slot,
flags: KVM_MEM_GUEST_MEMFD,
guest_phys_addr: region.start_addr().raw_value(),
memory_size: region.len(),
userspace_addr: host_addr as u64,
guest_memfd_offset: 0,
guest_memfd: guest_memfd as u32,
pad1: 0,
pad2: [0; 14],
};

// Set the memory region.
unsafe {
self.fd.set_user_memory_region2(memory_region).unwrap();
}

let attr = kvm_memory_attributes {
address: region.start_addr().raw_value(),
size: region.len(),
// KVM_MEMORY_ATTRIBUTE_PRIVATE,
attributes: 1 << 3,
flags: 0,
};

self.fd
.set_memory_attributes(attr)
.map_err(Error::SetMemoryAttributes)?;

self.next_mem_slot += 1;
}

#[cfg(target_arch = "x86_64")]
self.fd
.set_tss_address(arch::x86_64::layout::KVM_TSS_ADDRESS as usize)
Expand Down
Loading