Skip to content

Commit

Permalink
cpu/percpu: store an immutable reference to the SVSM VMSA
Browse files Browse the repository at this point in the history
The SVSM VMSA only needs to me mutated during initialization. Thus
simply encapsulate that step in a PerCpu method and store an
immutable reference to the VMSA, avoiding the possibility of mutably
aliasing it.

This obsoletes the VmsaRef type.

Signed-off-by: Carlos López <[email protected]>
  • Loading branch information
00xc committed Jun 19, 2024
1 parent 8461fc5 commit f351772
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 48 deletions.
60 changes: 19 additions & 41 deletions kernel/src/cpu/percpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use crate::sev::ghcb::GHCB;
use crate::sev::hv_doorbell::HVDoorbell;
use crate::sev::msr_protocol::{hypervisor_ghcb_features, GHCBHvFeatures};
use crate::sev::utils::RMPFlags;
use crate::sev::vmsa::allocate_new_vmsa;
use crate::sev::vmsa::{allocate_new_vmsa, VMSAControl};
use crate::task::{schedule, schedule_task, RunQueue, Task, TaskPointer, WaitQueue};
use crate::types::{PAGE_SHIFT, PAGE_SHIFT_2M, PAGE_SIZE, PAGE_SIZE_2M, SVSM_TR_FLAGS, SVSM_TSS};
use crate::utils::MemoryRegion;
Expand Down Expand Up @@ -107,36 +107,6 @@ impl PerCpuAreas {
}
}

#[derive(Copy, Clone, Debug, Default)]
pub struct VmsaRef {
pub vaddr: VirtAddr,
pub paddr: PhysAddr,
pub guest_owned: bool,
}

impl VmsaRef {
const fn new(v: VirtAddr, p: PhysAddr, g: bool) -> Self {
VmsaRef {
vaddr: v,
paddr: p,
guest_owned: g,
}
}

pub fn vmsa(&self) -> &VMSA {
let ptr = self.vaddr.as_mut_ptr::<VMSA>();
unsafe { ptr.as_mut().unwrap() }
}

#[allow(clippy::needless_pass_by_ref_mut)]
pub fn vmsa_mut(&mut self) -> &mut VMSA {
let ptr = self.vaddr.as_mut_ptr::<VMSA>();
// SAFETY: this function takes &mut self, so only one mutable
// reference to the underlying VMSA can exist.
unsafe { ptr.as_mut().unwrap() }
}
}

#[derive(Debug)]
struct IstStacks {
double_fault_stack: Cell<Option<VirtAddr>>,
Expand Down Expand Up @@ -328,7 +298,7 @@ pub struct PerCpu {

pgtbl: RefCell<PageTableRef>,
tss: Cell<X86Tss>,
svsm_vmsa: Cell<Option<VmsaRef>>,
svsm_vmsa: Cell<Option<&'static VMSA>>,
reset_ip: Cell<u64>,
apic_emulation: Cell<bool>,
/// PerCpu Virtual Memory Range
Expand Down Expand Up @@ -643,7 +613,10 @@ impl PerCpu {
self.reset_ip.set(reset_ip);
}

pub fn alloc_svsm_vmsa(&self, vtom: u64, start_rip: u64) -> Result<VmsaRef, SvsmError> {
/// Allocates and initializes a new VMSA for this CPU. Returns its
/// physical address and SEV features. Returns an error if allocation
/// fails of this CPU's VMSA was already initialized.
pub fn alloc_svsm_vmsa(&self, vtom: u64, start_rip: u64) -> Result<(PhysAddr, u64), SvsmError> {
if self.svsm_vmsa.get().is_some() {
// FIXME: add a more explicit error variant for this condition
return Err(SvsmError::Mem);
Expand All @@ -652,19 +625,24 @@ impl PerCpu {
let vaddr = allocate_new_vmsa(RMPFlags::GUEST_VMPL)?;
let paddr = virt_to_phys(vaddr);

let mut vmsa = VmsaRef::new(vaddr, paddr, false);
// SAFETY: we have exclusive access to this memory, as we just
// allocated it. allocate_new_vmsa() takes care of allocating
// memory of the right size and alignment for a VMSA.
let vmsa = unsafe { &mut *vaddr.as_mut_ptr::<VMSA>() };

// Initialize VMSA
let vmsa_ref = vmsa.vmsa_mut();
init_svsm_vmsa(vmsa_ref, vtom);
vmsa_ref.tr = self.vmsa_tr_segment();
vmsa_ref.rip = start_rip;
vmsa_ref.rsp = self.get_top_of_stack().into();
vmsa_ref.cr3 = self.get_pgtable().cr3_value().into();
init_svsm_vmsa(vmsa, vtom);
vmsa.tr = self.vmsa_tr_segment();
vmsa.rip = start_rip;
vmsa.rsp = self.get_top_of_stack().into();
vmsa.cr3 = self.get_pgtable().cr3_value().into();
vmsa.enable();

let sev_features = vmsa.sev_features;

self.svsm_vmsa.set(Some(vmsa));

Ok(vmsa)
Ok((paddr, sev_features))
}

pub fn unmap_guest_vmsa(&self) {
Expand Down
8 changes: 1 addition & 7 deletions kernel/src/cpu/smp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ use crate::error::SvsmError;
use crate::platform::SvsmPlatform;
use crate::platform::SVSM_PLATFORM;
use crate::requests::{request_loop, request_processing_main};
use crate::sev::vmsa::VMSAControl;
use crate::task::{create_kernel_task, schedule_init};
use crate::utils::immut_after_init::immut_after_init_set_multithreaded;

Expand All @@ -19,14 +18,9 @@ fn start_cpu(platform: &dyn SvsmPlatform, apic_id: u32, vtom: u64) -> Result<(),
let percpu = PerCpu::alloc(apic_id)?;

percpu.setup(platform)?;
let mut vmsa = percpu.alloc_svsm_vmsa(vtom, start_rip)?;

let sev_features = vmsa.vmsa().sev_features;
let vmsa_pa = vmsa.paddr;

let (vmsa_pa, sev_features) = percpu.alloc_svsm_vmsa(vtom, start_rip)?;
let percpu_shared = percpu.shared();

vmsa.vmsa_mut().enable();
current_ghcb().ap_create(vmsa_pa, apic_id.into(), 0, sev_features)?;
while !percpu_shared.is_online() {}
Ok(())
Expand Down

0 comments on commit f351772

Please sign in to comment.