Skip to content

Commit

Permalink
platform/tdp: Implement start_cpu()
Browse files Browse the repository at this point in the history
Use the same bring-up logic as the implementation in native.rs. In place
of an INIT/SIPI protocol, a software-based mailbox is used.

Signed-off-by: Peter Fang <[email protected]>
  • Loading branch information
peterfang committed Jan 23, 2025
1 parent 000870a commit de805ba
Showing 1 changed file with 45 additions and 3 deletions.
48 changes: 45 additions & 3 deletions kernel/src/platform/tdp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ use crate::address::{Address, PhysAddr, VirtAddr};
use crate::console::init_svsm_console;
use crate::cpu::cpuid::CpuidResult;
use crate::cpu::percpu::PerCpu;
use crate::cpu::smp::create_ap_start_context;
use crate::error::SvsmError;
use crate::hyperv;
use crate::io::IOPort;
use crate::mm::PerCPUPageMappingGuard;
use crate::platform::{PageEncryptionMasks, PageStateChangeOp, PageValidateOp, SvsmPlatform};
use crate::tdx::tdcall::{
td_accept_physical_memory, td_accept_virtual_memory, tdvmcall_halt, tdvmcall_io_read,
Expand All @@ -20,6 +22,9 @@ use crate::tdx::TdxError;
use crate::types::{PageSize, PAGE_SIZE};
use crate::utils::immut_after_init::ImmutAfterInitCell;
use crate::utils::{is_aligned, MemoryRegion};
use bootlib::kernel_launch::{ApStartContext, SIPI_STUB_GPA};
use core::arch::x86_64::_mm_sfence;
use core::{mem, ptr};

#[cfg(test)]
use bootlib::platform::SvsmPlatformType;
Expand All @@ -34,6 +39,22 @@ pub struct TdMailbox {
pub apic_id: u32,
}

// Both structures must fit in a page
const _: () = assert!(mem::size_of::<TdMailbox>() + mem::size_of::<ApStartContext>() <= PAGE_SIZE);

// SAFETY: caller must ensure `mailbox` points to a valid memory address.
unsafe fn wakeup_ap(mailbox: *mut TdMailbox, apic_id: u32) {
// SAFETY: caller must ensure the address is valid and not aliased.
unsafe {
(*mailbox).apic_id = 0;
(*mailbox).command = 0;
_mm_sfence();
(*mailbox).apic_id = apic_id;
_mm_sfence();
(*mailbox).command = 1;
}
}

#[derive(Clone, Copy, Debug)]
pub struct TdpPlatform {}

Expand Down Expand Up @@ -187,10 +208,31 @@ impl SvsmPlatform for TdpPlatform {

fn start_cpu(
&self,
_cpu: &PerCpu,
_context: &hyperv::HvInitialVpContext,
cpu: &PerCpu,
context: &hyperv::HvInitialVpContext,
) -> Result<(), SvsmError> {
todo!();
// Translate this context into an AP start context and place it in the
// AP startup transition page.
//
// transition_cr3 is not needed since all TD APs are using the stage2
// page table set up by the BSP.
let ap_context = create_ap_start_context(context, 0);

// The mailbox page was already accepted by the BSP in stage2 and
// therefore it's been initialized as a zero page.
let context_pa = PhysAddr::new(SIPI_STUB_GPA as usize);
let context_mapping = PerCPUPageMappingGuard::create_4k(context_pa)?;
let mbx_va = context_mapping.virt_addr();

// SAFETY: the address of the mailbox page was made valid when the
// `PerCPUPageMappingGuard` was created.
unsafe {
let size = mem::size_of::<ApStartContext>();
let context_ptr = (mbx_va + PAGE_SIZE - size).as_mut_ptr::<ApStartContext>();
ptr::copy_nonoverlapping(&ap_context, context_ptr, 1);
wakeup_ap(mbx_va.as_mut_ptr::<TdMailbox>(), cpu.get_apic_id());
}
Ok(())
}
}

Expand Down

0 comments on commit de805ba

Please sign in to comment.