diff --git a/litebox_platform_lvbs/src/mshv/error.rs b/litebox_platform_lvbs/src/mshv/error.rs index 5d6274be5..9c32c6816 100644 --- a/litebox_platform_lvbs/src/mshv/error.rs +++ b/litebox_platform_lvbs/src/mshv/error.rs @@ -127,7 +127,9 @@ pub enum VsmError { #[error("discontiguous memory range")] DiscontiguousMemoryRange, - + + #[error("failed to map VTL0 physical memory range")] + MapVtl0PhysRangeFailed, // Symbol Table Errors #[error("symbol table data empty")] SymbolTableEmpty, @@ -172,6 +174,7 @@ impl From for Errno { | VsmError::BootSignalWriteFailed | VsmError::CpuOnlineMaskCopyFailed | VsmError::HekiPagesCopyFailed + | VsmError::MapVtl0PhysRangeFailed | VsmError::Vtl0CopyFailed => Errno::EFAULT, // Not found errors diff --git a/litebox_platform_lvbs/src/mshv/ringbuffer.rs b/litebox_platform_lvbs/src/mshv/ringbuffer.rs index 92a75da26..c49d6467b 100644 --- a/litebox_platform_lvbs/src/mshv/ringbuffer.rs +++ b/litebox_platform_lvbs/src/mshv/ringbuffer.rs @@ -5,18 +5,17 @@ use core::fmt; use spin::{Mutex, Once}; -use x86_64::PhysAddr; -pub struct RingBuffer { - rb_pa: PhysAddr, +pub struct RingBuffer{ + rb_va: *mut u8, write_offset: usize, size: usize, } impl RingBuffer { - pub fn new(phys_addr: PhysAddr, requested_size: usize) -> Self { + pub fn new(virt_addr: *mut u8 , requested_size: usize) -> Self { RingBuffer { - rb_pa: phys_addr, + rb_va: virt_addr, write_offset: 0, size: requested_size, } @@ -28,7 +27,11 @@ impl RingBuffer { if buf.len() >= self.size { let single_slice = &buf[(buf.len() - self.size)..]; unsafe { - crate::platform_low().copy_slice_to_vtl0_phys(self.rb_pa, single_slice); + let _ = litebox::mm::exception_table::memcpy_fallible( + self.rb_va, + single_slice.as_ptr(), + self.size); + } self.write_offset = 0; return; @@ -40,24 +43,35 @@ impl RingBuffer { let first_slice = &buf[..space_remaining]; let wraparound_slice = &buf[space_remaining..]; unsafe { - crate::platform_low() - .copy_slice_to_vtl0_phys(self.rb_pa + self.write_offset as u64, first_slice); - crate::platform_low().copy_slice_to_vtl0_phys(self.rb_pa, wraparound_slice); + let _ = litebox::mm::exception_table::memcpy_fallible( + self.rb_va.add(self.write_offset), + first_slice.as_ptr(), + first_slice.len()); + let _ = litebox::mm::exception_table::memcpy_fallible( + self.rb_va, + wraparound_slice.as_ptr(), + wraparound_slice.len()); } } else { unsafe { - crate::platform_low() - .copy_slice_to_vtl0_phys(self.rb_pa + self.write_offset as u64, buf); + let _ = litebox::mm::exception_table::memcpy_fallible( + self.rb_va.add(self.write_offset), + buf.as_ptr(), + buf.len()); } } self.write_offset = (self.write_offset + buf.len()) % self.size; } } +// SAFETY: RingBuffer is only accessed through a Mutex, and rb_va is a valid +// pointer to mapped memory that outlives the RingBuffer. +unsafe impl Send for RingBuffer {} + static RINGBUFFER_ONCE: Once> = Once::new(); -pub(crate) fn set_ringbuffer(pa: PhysAddr, size: usize) -> &'static Mutex { +pub(crate) fn set_ringbuffer(va: *mut u8, size: usize) -> &'static Mutex { RINGBUFFER_ONCE.call_once(|| { - let ring_buffer = RingBuffer::new(pa, size); + let ring_buffer = RingBuffer::new(va, size); Mutex::new(ring_buffer) }) } diff --git a/litebox_platform_lvbs/src/mshv/vsm.rs b/litebox_platform_lvbs/src/mshv/vsm.rs index f66989fa3..2dffbec1a 100644 --- a/litebox_platform_lvbs/src/mshv/vsm.rs +++ b/litebox_platform_lvbs/src/mshv/vsm.rs @@ -52,7 +52,7 @@ use spin::Once; use thiserror::Error; use x86_64::{ PhysAddr, VirtAddr, - structures::paging::{PageSize, PhysFrame, Size4KiB, frame::PhysFrameRange}, + structures::paging::{PageSize, PageTableFlags, PhysFrame, Size4KiB, frame::PhysFrameRange}, }; use x509_cert::{Certificate, der::Decode}; use zerocopy::{FromBytes, FromZeros, Immutable, IntoBytes, KnownLayout}; @@ -882,15 +882,24 @@ fn apply_vtl0_text_patch(heki_patch: HekiPatch) -> Result<(), VsmError> { } fn mshv_vsm_allocate_ringbuffer_memory(phys_addr: u64, size: usize) -> Result { - set_ringbuffer(PhysAddr::new(phys_addr), size); + let phys_addr = PhysAddr::new(phys_addr); protect_physical_memory_range( PhysFrame::range( - PhysFrame::containing_address(PhysAddr::new(phys_addr)), - PhysFrame::containing_address(PhysAddr::new(phys_addr + (size as u64))), + PhysFrame::containing_address(phys_addr), + PhysFrame::containing_address(phys_addr + (size as u64)), ), MemAttr::MEM_ATTR_READ, )?; - debug_serial_println!("VSM: Ring buffer allocated"); + if let Ok((page_addr, _)) = + crate::platform_low().map_vtl0_phys_range( + phys_addr, + phys_addr + size.try_into().unwrap(), + PageTableFlags::PRESENT | PageTableFlags::WRITABLE | PageTableFlags::NO_EXECUTE) { + set_ringbuffer(page_addr, size); + } else { + return Err(VsmError::MapVtl0PhysRangeFailed); + } + debug_serial_println!("VSM: Ringbuffer initialized"); Ok(0) }