diff --git a/kernel/src/platform/mod.rs b/kernel/src/platform/mod.rs index 8e24265203..1edb77472d 100644 --- a/kernel/src/platform/mod.rs +++ b/kernel/src/platform/mod.rs @@ -20,6 +20,7 @@ use tdp::TdpPlatform; use core::arch::asm; use core::fmt::Debug; +use core::mem::MaybeUninit; use crate::address::{PhysAddr, VirtAddr}; use crate::config::SvsmConfig; @@ -224,9 +225,13 @@ pub trait SvsmPlatform: Sync { /// /// # Safety /// - /// Caller must ensure that `pa` points to a properly aligned memory location and the + /// Caller must ensure that `paddr` points to a properly aligned memory location and the /// memory accessed is part of a valid MMIO range. - unsafe fn mmio_read(&self, _paddr: PhysAddr, _data: &mut [u8]) -> Result<(), SvsmError>; + unsafe fn mmio_read( + &self, + paddr: PhysAddr, + data: &mut [MaybeUninit], + ) -> Result<(), SvsmError>; } //FIXME - remove Copy trait diff --git a/kernel/src/platform/native.rs b/kernel/src/platform/native.rs index 069422f458..8aa6137d0a 100644 --- a/kernel/src/platform/native.rs +++ b/kernel/src/platform/native.rs @@ -237,7 +237,11 @@ impl SvsmPlatform for NativePlatform { unimplemented!() } - unsafe fn mmio_read(&self, _paddr: PhysAddr, _data: &mut [u8]) -> Result<(), SvsmError> { + unsafe fn mmio_read( + &self, + _paddr: PhysAddr, + _data: &mut [MaybeUninit], + ) -> Result<(), SvsmError> { unimplemented!() } } diff --git a/kernel/src/platform/snp.rs b/kernel/src/platform/snp.rs index 0404cc3d1a..303bb64a07 100644 --- a/kernel/src/platform/snp.rs +++ b/kernel/src/platform/snp.rs @@ -38,6 +38,7 @@ use crate::utils::immut_after_init::ImmutAfterInitCell; use crate::utils::MemoryRegion; use syscall::GlobalFeatureFlags; +use core::mem::MaybeUninit; use core::sync::atomic::{AtomicU32, Ordering}; #[cfg(test)] @@ -393,7 +394,11 @@ impl SvsmPlatform for SnpPlatform { /// /// Caller must ensure that `paddr` points to a properly aligned memory location and the /// memory accessed is part of a valid MMIO range. - unsafe fn mmio_read(&self, paddr: PhysAddr, data: &mut [u8]) -> Result<(), SvsmError> { + unsafe fn mmio_read( + &self, + paddr: PhysAddr, + data: &mut [MaybeUninit], + ) -> Result<(), SvsmError> { // SAFETY: We are trusting the caller to ensure validity of `paddr` and alignment of data. unsafe { crate::cpu::percpu::current_ghcb().mmio_read(paddr, data) } } diff --git a/kernel/src/platform/tdp.rs b/kernel/src/platform/tdp.rs index 19d0dd3bb4..61792947f5 100644 --- a/kernel/src/platform/tdp.rs +++ b/kernel/src/platform/tdp.rs @@ -284,7 +284,11 @@ impl SvsmPlatform for TdpPlatform { unimplemented!() } - unsafe fn mmio_read(&self, _paddr: PhysAddr, _data: &mut [u8]) -> Result<(), SvsmError> { + unsafe fn mmio_read( + &self, + _paddr: PhysAddr, + _data: &mut [MaybeUninit], + ) -> Result<(), SvsmError> { unimplemented!() } } diff --git a/kernel/src/sev/ghcb.rs b/kernel/src/sev/ghcb.rs index fd4d25cedb..b355d6011b 100644 --- a/kernel/src/sev/ghcb.rs +++ b/kernel/src/sev/ghcb.rs @@ -22,7 +22,7 @@ use crate::utils::MemoryRegion; use crate::mm::PageBox; use core::arch::global_asm; -use core::mem::{self, offset_of}; +use core::mem::{self, offset_of, MaybeUninit}; use core::ops::Deref; use core::ptr; use core::sync::atomic::{AtomicU16, AtomicU32, AtomicU64, AtomicU8, Ordering}; @@ -548,7 +548,11 @@ impl GHCB { Ok(()) } - fn read_buffer_slice(&self, data: &mut [u8], offset: usize) -> Result<(), GhcbError> { + fn read_buffer_slice( + &self, + data: &mut [MaybeUninit], + offset: usize, + ) -> Result<(), GhcbError> { let src = &self .buffer .get(offset..) @@ -556,7 +560,7 @@ impl GHCB { .get(..data.len()) .ok_or(GhcbError::InvalidOffset)?; for (d, s) in data.iter_mut().zip(src.iter()) { - *d = s.load(Ordering::Relaxed); + d.write(s.load(Ordering::Relaxed)); } Ok(()) } @@ -587,7 +591,11 @@ impl GHCB { /// /// Caller must ensure that `pa` points to a properly aligned memory location and the /// memory accessed is part of a valid MMIO range. - pub unsafe fn mmio_read(&self, pa: PhysAddr, value: &mut [u8]) -> Result<(), SvsmError> { + pub unsafe fn mmio_read( + &self, + pa: PhysAddr, + value: &mut [MaybeUninit], + ) -> Result<(), SvsmError> { self.clear(); self.pepare_buffer(); self.vmgexit(GHCBExitCode::MMIO_READ, u64::from(pa), value.len() as u64)?; diff --git a/kernel/src/virtio/hal.rs b/kernel/src/virtio/hal.rs index cdf662a141..b3868b4b52 100644 --- a/kernel/src/virtio/hal.rs +++ b/kernel/src/virtio/hal.rs @@ -9,6 +9,7 @@ use crate::{locking::SpinLock, platform::SVSM_PLATFORM}; use alloc::vec::Vec; use core::{ cell::OnceCell, + mem::{size_of, MaybeUninit}, ptr::{addr_of, NonNull}, }; use zerocopy::{FromBytes, Immutable, IntoBytes}; @@ -202,13 +203,21 @@ unsafe impl virtio_drivers::Hal for SvsmHal { .phys_addr(VirtAddr::from(addr_of!(*src))) .unwrap(); - let mut b = alloc::vec![0; size_of::()]; + let mut b = MaybeUninit::::uninit(); // SAFETY: We are trusting the caller (the virtio driver) to ensure `src` is a valid MMIO - // address and that it is alinged properly. + // address and that it is aligned properly. If SVSM_PLATFORM.mmio_read() doesn't fail + // we can assume that all the bytes are read from the device. unsafe { - SVSM_PLATFORM.mmio_read(paddr, &mut b).unwrap(); + // MaybeUninit::as_bytes_mut() can avoid this, but it's still + // unstable. When it will be stabilized, we can simply use + // `b.as_bytes_mut()` instead of creating `b_slice`. + let b_slice = core::slice::from_raw_parts_mut( + b.as_mut_ptr().cast::>(), + size_of::(), + ); + SVSM_PLATFORM.mmio_read(paddr, b_slice).unwrap(); + b.assume_init() } - T::try_read_from_bytes(b.as_slice()).unwrap() } /// Performs memory mapped write of `value` to the location of `dst`.