Skip to content

Commit

Permalink
Merge pull request #504 from Freax13/enhancement/cell-deref
Browse files Browse the repository at this point in the history
platform: implement Deref{Mut} for SvsmPlatformCell
  • Loading branch information
joergroedel authored Oct 30, 2024
2 parents f49b375 + cbb3dcd commit aba0c0e
Show file tree
Hide file tree
Showing 12 changed files with 46 additions and 47 deletions.
2 changes: 1 addition & 1 deletion kernel/src/cpu/apic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ impl LocalApic {
hv_icr.set_destination_shorthand(IcrDestFmt::AllButSelf);
}

SVSM_PLATFORM.as_dyn_ref().post_irq(hv_icr.into()).unwrap();
SVSM_PLATFORM.post_irq(hv_icr.into()).unwrap();
}
}

Expand Down
6 changes: 3 additions & 3 deletions kernel/src/cpu/idt/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ impl InsnMachineCtx for X86ExceptionContext {
}

fn ioio_in(&self, port: u16, size: Bytes) -> Result<u64, InsnError> {
let io_port = SVSM_PLATFORM.as_dyn_ref().get_io_port();
let io_port = SVSM_PLATFORM.get_io_port();
let data = match size {
Bytes::One => io_port.inb(port) as u64,
Bytes::Two => io_port.inw(port) as u64,
Expand All @@ -168,7 +168,7 @@ impl InsnMachineCtx for X86ExceptionContext {
}

fn ioio_out(&mut self, port: u16, size: Bytes, data: u64) -> Result<(), InsnError> {
let io_port = SVSM_PLATFORM.as_dyn_ref().get_io_port();
let io_port = SVSM_PLATFORM.get_io_port();
match size {
Bytes::One => io_port.outb(port, data as u8),
Bytes::Two => io_port.outw(port, data as u16),
Expand Down Expand Up @@ -415,7 +415,7 @@ impl IdtEventType {
match self {
Self::External => true,
Self::Software => false,
Self::Unknown => SVSM_PLATFORM.as_dyn_ref().is_external_interrupt(vector),
Self::Unknown => SVSM_PLATFORM.is_external_interrupt(vector),
}
}
}
2 changes: 1 addition & 1 deletion kernel/src/cpu/idt/svsm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ pub extern "C" fn common_isr_handler(_vector: usize) {
// simply to ensure an exit from the guest.

// Treat any unhandled interrupt as a spurious interrupt.
SVSM_PLATFORM.as_dyn_ref().eoi();
SVSM_PLATFORM.eoi();
}

global_asm!(
Expand Down
4 changes: 2 additions & 2 deletions kernel/src/cpu/percpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,7 @@ impl PerCpu {

pub fn alloc_guest_vmsa(&self) -> Result<(), SvsmError> {
// Enable alternate injection if the hypervisor supports it.
let use_alternate_injection = SVSM_PLATFORM.as_dyn_ref().query_apic_registration_state();
let use_alternate_injection = SVSM_PLATFORM.query_apic_registration_state();
if use_alternate_injection {
self.apic.replace(Some(LocalApic::new()));

Expand Down Expand Up @@ -831,7 +831,7 @@ impl PerCpu {
// for scheduler initialization so that the first interrupt that can
// be received will always observe that there is a current task and
// not the boot thread.
if SVSM_PLATFORM.as_dyn_ref().use_interrupts() {
if SVSM_PLATFORM.use_interrupts() {
unsafe {
self.irq_state.set_restore_state(true);
}
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/cpu/smp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ pub fn start_secondary_cpus(platform: &dyn SvsmPlatform, cpus: &[ACPICPUInfo]) {
#[no_mangle]
fn start_ap() {
this_cpu()
.setup_on_cpu(SVSM_PLATFORM.as_dyn_ref())
.setup_on_cpu(&**SVSM_PLATFORM)
.expect("setup_on_cpu() failed");

this_cpu()
Expand Down
5 changes: 2 additions & 3 deletions kernel/src/igvm_params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,17 +163,16 @@ impl IgvmParams<'_> {
// host-provided IGVM parameters, which requires the pages to be
// validated. Since the memory was not declared as part of the guest
// firmware image, the pages must be validated here.
let platform = SVSM_PLATFORM.as_dyn_ref();
if self.page_state_change_required() {
platform.page_state_change(
SVSM_PLATFORM.page_state_change(
mem_map_region,
PageSize::Regular,
PageStateChangeOp::Private,
)?;
}

let mem_map_va_region = MemoryRegion::<VirtAddr>::new(mem_map_va, mem_map_region.len());
platform.validate_virtual_page_range(mem_map_va_region, PageValidateOp::Validate)?;
SVSM_PLATFORM.validate_virtual_page_range(mem_map_va_region, PageValidateOp::Validate)?;

// Calculate the maximum number of entries that can be inserted.
let max_entries = fw_info.memory_map_page_count as usize * PAGE_SIZE
Expand Down
12 changes: 4 additions & 8 deletions kernel/src/mm/page_visibility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,8 @@ use zerocopy::{FromBytes, FromZeros};
/// Notably any objects at `vaddr` must tolerate unsynchronized writes of any
/// bit pattern.
unsafe fn make_page_shared(vaddr: VirtAddr) -> Result<(), SvsmError> {
let platform = SVSM_PLATFORM.as_dyn_ref();

// Revoke page validation before changing page state.
platform.validate_virtual_page_range(
SVSM_PLATFORM.validate_virtual_page_range(
MemoryRegion::new(vaddr, PAGE_SIZE),
PageValidateOp::Invalidate,
)?;
Expand All @@ -49,7 +47,7 @@ unsafe fn make_page_shared(vaddr: VirtAddr) -> Result<(), SvsmError> {
}

// Ask the hypervisor to make the page shared.
platform.page_state_change(
SVSM_PLATFORM.page_state_change(
MemoryRegion::new(paddr, PAGE_SIZE),
PageSize::Regular,
PageStateChangeOp::Shared,
Expand All @@ -76,18 +74,16 @@ unsafe fn make_page_private(vaddr: VirtAddr) -> Result<(), SvsmError> {
this_cpu().get_pgtable().set_encrypted_4k(vaddr)?;
flush_tlb_global_sync();

let platform = SVSM_PLATFORM.as_dyn_ref();

// Ask the hypervisor to make the page private.
let paddr = virt_to_phys(vaddr);
platform.page_state_change(
SVSM_PLATFORM.page_state_change(
MemoryRegion::new(paddr, PAGE_SIZE),
PageSize::Regular,
PageStateChangeOp::Private,
)?;

// Validate the page now that it is private again.
platform.validate_virtual_page_range(
SVSM_PLATFORM.validate_virtual_page_range(
MemoryRegion::new(vaddr, PAGE_SIZE),
PageValidateOp::Validate,
)?;
Expand Down
12 changes: 10 additions & 2 deletions kernel/src/platform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
//
// Author: Jon Lange <[email protected]>

use core::ops::{Deref, DerefMut};

use crate::address::{PhysAddr, VirtAddr};
use crate::cpu::cpuid::CpuidResult;
use crate::cpu::percpu::PerCpu;
Expand Down Expand Up @@ -159,16 +161,22 @@ impl SvsmPlatformCell {
SvsmPlatformType::Tdp => SvsmPlatformCell::Tdp(TdpPlatform::new()),
}
}
}

pub fn as_dyn_ref(&self) -> &dyn SvsmPlatform {
impl Deref for SvsmPlatformCell {
type Target = dyn SvsmPlatform;

fn deref(&self) -> &Self::Target {
match self {
SvsmPlatformCell::Native(platform) => platform,
SvsmPlatformCell::Snp(platform) => platform,
SvsmPlatformCell::Tdp(platform) => platform,
}
}
}

pub fn as_mut_dyn_ref(&mut self) -> &mut dyn SvsmPlatform {
impl DerefMut for SvsmPlatformCell {
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
SvsmPlatformCell::Native(platform) => platform,
SvsmPlatformCell::Snp(platform) => platform,
Expand Down
7 changes: 3 additions & 4 deletions kernel/src/protocols/apic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,23 @@ fn apic_query_features(params: &mut RequestParams) -> Result<(), SvsmReqError> {
}

fn apic_configure(params: &RequestParams) -> Result<(), SvsmReqError> {
let platform = SVSM_PLATFORM.as_dyn_ref();
let enabled = match params.rcx {
0b00 => {
// Query the current registration state of APIC emulation to
// determine whether it should be disabled on the current CPU.
platform.query_apic_registration_state()
SVSM_PLATFORM.query_apic_registration_state()
}

0b01 => {
// Deregister APIC emulation if possible, noting whether it is now
// disabled for the platform. This cannot fail.
platform.change_apic_registration_state(false).unwrap()
SVSM_PLATFORM.change_apic_registration_state(false).unwrap()
}

0b10 => {
// Increment the APIC emulation registration count. If successful,
// this will not cause any change to the state of the current CPU.
platform.change_apic_registration_state(true)?;
SVSM_PLATFORM.change_apic_registration_state(true)?;
return Ok(());
}

Expand Down
15 changes: 8 additions & 7 deletions kernel/src/stage2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,12 +348,13 @@ fn prepare_heap(
#[no_mangle]
pub extern "C" fn stage2_main(launch_info: &Stage2LaunchInfo) {
let platform_type = SvsmPlatformType::from(launch_info.platform_type);

init_platform_type(platform_type);
let mut platform_cell = SvsmPlatformCell::new(platform_type);
let platform = platform_cell.as_mut_dyn_ref();
let mut platform = SvsmPlatformCell::new(platform_type);

let config = get_svsm_config(launch_info, platform).expect("Failed to get SVSM configuration");
setup_env(&config, platform, launch_info);
let config =
get_svsm_config(launch_info, &*platform).expect("Failed to get SVSM configuration");
setup_env(&config, &mut *platform, launch_info);

// Get the available physical memory region for the kernel
let kernel_region = config
Expand All @@ -367,7 +368,7 @@ pub extern "C" fn stage2_main(launch_info: &Stage2LaunchInfo) {

// Load first the kernel ELF and update the loaded physical region
let (kernel_entry, mut loaded_kernel_vregion) =
load_kernel_elf(launch_info, &mut loaded_kernel_pregion, platform, &config)
load_kernel_elf(launch_info, &mut loaded_kernel_pregion, &*platform, &config)
.expect("Failed to load kernel ELF");

// Load the IGVM params, if present. Update loaded region accordingly.
Expand All @@ -377,7 +378,7 @@ pub extern "C" fn stage2_main(launch_info: &Stage2LaunchInfo) {
igvm_params,
&loaded_kernel_vregion,
&loaded_kernel_pregion,
platform,
&*platform,
&config,
)
.expect("Failed to load IGVM params");
Expand All @@ -398,7 +399,7 @@ pub extern "C" fn stage2_main(launch_info: &Stage2LaunchInfo) {
kernel_region,
loaded_kernel_pregion,
loaded_kernel_vregion,
platform,
&*platform,
&config,
)
.expect("Failed to map and validate heap");
Expand Down
24 changes: 10 additions & 14 deletions kernel/src/svsm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,7 @@ pub extern "C" fn svsm_start(li: &KernelLaunchInfo, vb_addr: usize) {
.init(li)
.expect("Already initialized launch info");

let mut platform_cell = SvsmPlatformCell::new(li.platform_type);
let platform = platform_cell.as_mut_dyn_ref();
let mut platform = SvsmPlatformCell::new(li.platform_type);

init_cpuid_table(VirtAddr::from(launch_info.cpuid_page));

Expand All @@ -313,7 +312,7 @@ pub extern "C" fn svsm_start(li: &KernelLaunchInfo, vb_addr: usize) {
zero_mem_region(secrets_page_virt, secrets_page_virt + PAGE_SIZE);

cr0_init();
cr4_init(platform);
cr4_init(&*platform);
install_console_logger("SVSM").expect("Console logger already initialized");
platform
.env_setup(debug_serial_port, launch_info.vtom.try_into().unwrap())
Expand All @@ -335,18 +334,18 @@ pub extern "C" fn svsm_start(li: &KernelLaunchInfo, vb_addr: usize) {
Err(e) => panic!("error reading kernel ELF: {}", e),
};

paging_init(platform).expect("Failed to initialize paging");
paging_init(&*platform).expect("Failed to initialize paging");
let init_pgtable =
init_page_table(&launch_info, &kernel_elf).expect("Could not initialize the page table");
init_pgtable.load();

let bsp_percpu = PerCpu::alloc(0).expect("Failed to allocate BSP per-cpu data");

bsp_percpu
.setup(platform, init_pgtable)
.setup(&*platform, init_pgtable)
.expect("Failed to setup BSP per-cpu area");
bsp_percpu
.setup_on_cpu(platform)
.setup_on_cpu(&*platform)
.expect("Failed to run percpu.setup_on_cpu()");
bsp_percpu.load();

Expand Down Expand Up @@ -375,7 +374,7 @@ pub extern "C" fn svsm_start(li: &KernelLaunchInfo, vb_addr: usize) {
.expect("Alternate injection required but not available");

SVSM_PLATFORM
.init(&platform_cell)
.init(&platform)
.expect("Failed to initialize SVSM platform object");

sse_init();
Expand All @@ -386,17 +385,14 @@ pub extern "C" fn svsm_start(li: &KernelLaunchInfo, vb_addr: usize) {

#[no_mangle]
pub extern "C" fn svsm_main() {
let platform = SVSM_PLATFORM.as_dyn_ref();

// If required, the GDB stub can be started earlier, just after the console
// is initialised in svsm_start() above.
gdbstub_start(platform).expect("Could not start GDB stub");
gdbstub_start(&**SVSM_PLATFORM).expect("Could not start GDB stub");
// Uncomment the line below if you want to wait for
// a remote GDB connection
//debug_break();

SVSM_PLATFORM
.as_dyn_ref()
.env_setup_svsm()
.expect("SVSM platform environment setup failed");

Expand All @@ -409,7 +405,7 @@ pub extern "C" fn svsm_main() {
}
SvsmConfig::IgvmConfig(igvm_params)
} else {
SvsmConfig::FirmwareConfig(FwCfg::new(SVSM_PLATFORM.as_dyn_ref().get_io_port()))
SvsmConfig::FirmwareConfig(FwCfg::new(SVSM_PLATFORM.get_io_port()))
};

init_memory_map(&config, &LAUNCH_INFO).expect("Failed to init guest memory map");
Expand All @@ -419,7 +415,7 @@ pub extern "C" fn svsm_main() {
populate_ram_fs(LAUNCH_INFO.kernel_fs_start, LAUNCH_INFO.kernel_fs_end)
.expect("Failed to unpack FS archive");

invalidate_early_boot_memory(platform, &config, launch_info)
invalidate_early_boot_memory(&**SVSM_PLATFORM, &config, launch_info)
.expect("Failed to invalidate early boot memory");

let cpus = config.load_cpu_info().expect("Failed to load ACPI tables");
Expand All @@ -433,7 +429,7 @@ pub extern "C" fn svsm_main() {

log::info!("{} CPU(s) present", nr_cpus);

start_secondary_cpus(platform, &cpus);
start_secondary_cpus(&**SVSM_PLATFORM, &cpus);

let fw_metadata = config.get_fw_metadata();
if let Some(ref fw_meta) = fw_metadata {
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub enum IORequest {
pub fn svsm_test_io() -> LockGuard<'static, Option<SerialPort<'static>>> {
let mut sp = SERIAL_PORT.lock();
if sp.is_none() {
let io_port = SVSM_PLATFORM.as_dyn_ref().get_io_port();
let io_port = SVSM_PLATFORM.get_io_port();
let serial_port = SerialPort::new(io_port, 0x2e8 /*COM4*/);
*sp = Some(serial_port);
serial_port.init();
Expand Down

0 comments on commit aba0c0e

Please sign in to comment.