diff --git a/kernel/src/cpu/apic.rs b/kernel/src/cpu/apic.rs index b965c961a..7d65e7e4a 100644 --- a/kernel/src/cpu/apic.rs +++ b/kernel/src/cpu/apic.rs @@ -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(); } } diff --git a/kernel/src/cpu/idt/common.rs b/kernel/src/cpu/idt/common.rs index 3a1754060..f88b72446 100644 --- a/kernel/src/cpu/idt/common.rs +++ b/kernel/src/cpu/idt/common.rs @@ -157,7 +157,7 @@ impl InsnMachineCtx for X86ExceptionContext { } fn ioio_in(&self, port: u16, size: Bytes) -> Result { - 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, @@ -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), @@ -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), } } } diff --git a/kernel/src/cpu/idt/svsm.rs b/kernel/src/cpu/idt/svsm.rs index bcce012bb..d6137ee1f 100644 --- a/kernel/src/cpu/idt/svsm.rs +++ b/kernel/src/cpu/idt/svsm.rs @@ -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!( diff --git a/kernel/src/cpu/percpu.rs b/kernel/src/cpu/percpu.rs index 35510f58f..bf5ea49b8 100644 --- a/kernel/src/cpu/percpu.rs +++ b/kernel/src/cpu/percpu.rs @@ -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())); @@ -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); } diff --git a/kernel/src/cpu/smp.rs b/kernel/src/cpu/smp.rs index 2479756f5..af448aef3 100644 --- a/kernel/src/cpu/smp.rs +++ b/kernel/src/cpu/smp.rs @@ -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() diff --git a/kernel/src/igvm_params.rs b/kernel/src/igvm_params.rs index d6461bbe3..b38376694 100644 --- a/kernel/src/igvm_params.rs +++ b/kernel/src/igvm_params.rs @@ -163,9 +163,8 @@ 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, @@ -173,7 +172,7 @@ impl IgvmParams<'_> { } let mem_map_va_region = MemoryRegion::::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 diff --git a/kernel/src/mm/page_visibility.rs b/kernel/src/mm/page_visibility.rs index 547f9df28..f442cb3d9 100644 --- a/kernel/src/mm/page_visibility.rs +++ b/kernel/src/mm/page_visibility.rs @@ -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, )?; @@ -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, @@ -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, )?; diff --git a/kernel/src/platform/mod.rs b/kernel/src/platform/mod.rs index 46d4bbae1..ae32f9a38 100644 --- a/kernel/src/platform/mod.rs +++ b/kernel/src/platform/mod.rs @@ -4,6 +4,8 @@ // // Author: Jon Lange +use core::ops::{Deref, DerefMut}; + use crate::address::{PhysAddr, VirtAddr}; use crate::cpu::cpuid::CpuidResult; use crate::cpu::percpu::PerCpu; @@ -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, diff --git a/kernel/src/protocols/apic.rs b/kernel/src/protocols/apic.rs index 5bad3ca35..ce44d3a32 100644 --- a/kernel/src/protocols/apic.rs +++ b/kernel/src/protocols/apic.rs @@ -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(()); } diff --git a/kernel/src/stage2.rs b/kernel/src/stage2.rs index 96094c532..988918ceb 100755 --- a/kernel/src/stage2.rs +++ b/kernel/src/stage2.rs @@ -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 @@ -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. @@ -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"); @@ -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"); diff --git a/kernel/src/svsm.rs b/kernel/src/svsm.rs index 5188c2251..9126ee690 100755 --- a/kernel/src/svsm.rs +++ b/kernel/src/svsm.rs @@ -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)); @@ -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()) @@ -335,7 +334,7 @@ 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(); @@ -343,10 +342,10 @@ pub extern "C" fn svsm_start(li: &KernelLaunchInfo, vb_addr: usize) { 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(); @@ -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(); @@ -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"); @@ -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"); @@ -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"); @@ -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 { diff --git a/kernel/src/testing.rs b/kernel/src/testing.rs index 8650e8d16..661924f89 100644 --- a/kernel/src/testing.rs +++ b/kernel/src/testing.rs @@ -47,7 +47,7 @@ pub enum IORequest { pub fn svsm_test_io() -> LockGuard<'static, Option>> { 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();