From 332031a57b5bf52a87025f199379dd05320da1d2 Mon Sep 17 00:00:00 2001 From: Jason Davis Date: Thu, 19 Dec 2024 08:14:20 -0600 Subject: [PATCH] Converted StableVec to use u64 virtual addresses rather than physical (#13) * Converted StableVec to use u64 virtual addresses rather than physical * Removed an extraneous comment * Cleaned up the use statement --- program-runtime/src/invoke_context.rs | 2 +- programs/bpf_loader/src/syscalls/cpi.rs | 8 ++-- sdk/stable-layout/src/stable_vec.rs | 57 +++++++++++++++---------- 3 files changed, 40 insertions(+), 27 deletions(-) diff --git a/program-runtime/src/invoke_context.rs b/program-runtime/src/invoke_context.rs index a54e0839ab8036..2afee6954bd013 100644 --- a/program-runtime/src/invoke_context.rs +++ b/program-runtime/src/invoke_context.rs @@ -339,7 +339,7 @@ impl<'a> InvokeContext<'a> { // but performed on a very small slice and requires no heap allocations. let instruction_context = self.transaction_context.get_current_instruction_context()?; let mut deduplicated_instruction_accounts: Vec = Vec::new(); - let mut duplicate_indicies = Vec::with_capacity(instruction.accounts.len()); + let mut duplicate_indicies = Vec::with_capacity(instruction.accounts.len() as usize); for (instruction_account_index, account_meta) in instruction.accounts.iter().enumerate() { let index_in_transaction = self .transaction_context diff --git a/programs/bpf_loader/src/syscalls/cpi.rs b/programs/bpf_loader/src/syscalls/cpi.rs index b9d0651db76dfa..540127fea57acb 100644 --- a/programs/bpf_loader/src/syscalls/cpi.rs +++ b/programs/bpf_loader/src/syscalls/cpi.rs @@ -424,14 +424,14 @@ impl SyscallInvokeSigned for SyscallInvokeSignedRust { )?; let account_metas = translate_slice::( memory_mapping, - ix.accounts.as_ptr() as u64, - ix.accounts.len() as u64, + ix.accounts.as_vaddr(), + ix.accounts.len(), invoke_context.get_check_aligned(), )?; let data = translate_slice::( memory_mapping, - ix.data.as_ptr() as u64, - ix.data.len() as u64, + ix.data.as_vaddr(), + ix.data.len(), invoke_context.get_check_aligned(), )? .to_vec(); diff --git a/sdk/stable-layout/src/stable_vec.rs b/sdk/stable-layout/src/stable_vec.rs index 5596ab08775e6d..81d270a7e9f893 100644 --- a/sdk/stable-layout/src/stable_vec.rs +++ b/sdk/stable-layout/src/stable_vec.rs @@ -1,6 +1,10 @@ //! `Vec`, with a stable memory layout -use std::{marker::PhantomData, mem::ManuallyDrop, ptr::NonNull}; +use std::{ + marker::PhantomData, + mem::ManuallyDrop, + ops::{Deref, DerefMut}, +}; /// `Vec`, with a stable memory layout /// @@ -24,9 +28,9 @@ use std::{marker::PhantomData, mem::ManuallyDrop, ptr::NonNull}; /// ``` #[repr(C)] pub struct StableVec { - pub ptr: NonNull, - pub cap: usize, - pub len: usize, + pub addr: u64, + pub cap: u64, + pub len: u64, _marker: PhantomData, } @@ -34,17 +38,12 @@ pub struct StableVec { // `deref`, which creates an intermediate reference. impl StableVec { #[inline] - pub fn as_ptr(&self) -> *const T { - self.ptr.as_ptr() + pub fn as_vaddr(&self) -> u64 { + self.addr } #[inline] - pub fn as_mut_ptr(&mut self) -> *mut T { - self.ptr.as_ptr() - } - - #[inline] - pub fn len(&self) -> usize { + pub fn len(&self) -> u64 { self.len } @@ -56,13 +55,13 @@ impl StableVec { impl AsRef<[T]> for StableVec { fn as_ref(&self) -> &[T] { - self + self.deref() } } impl AsMut<[T]> for StableVec { fn as_mut(&mut self) -> &mut [T] { - self + self.deref_mut() } } @@ -71,14 +70,14 @@ impl std::ops::Deref for StableVec { #[inline] fn deref(&self) -> &[T] { - unsafe { core::slice::from_raw_parts(self.as_ptr(), self.len) } + unsafe { core::slice::from_raw_parts(self.addr as usize as *mut T, self.len as usize) } } } impl std::ops::DerefMut for StableVec { #[inline] fn deref_mut(&mut self) -> &mut [T] { - unsafe { core::slice::from_raw_parts_mut(self.as_mut_ptr(), self.len) } + unsafe { core::slice::from_raw_parts_mut(self.addr as usize as *mut T, self.len as usize) } } } @@ -121,9 +120,9 @@ impl From> for StableVec { let mut other = ManuallyDrop::new(other); Self { // SAFETY: We have a valid Vec, so its ptr is non-null. - ptr: unsafe { NonNull::new_unchecked(other.as_mut_ptr()) }, - cap: other.capacity(), - len: other.len(), + addr: other.as_mut_ptr() as u64, // Problematic if other is in 32-bit physical address space + cap: other.capacity() as u64, + len: other.len() as u64, _marker: PhantomData, } } @@ -135,8 +134,16 @@ impl From> for Vec { // out of scope. let other = ManuallyDrop::new(other); // SAFETY: We have a valid StableVec, which we can only get from a Vec. Therefore it is - // safe to convert back to Vec. - unsafe { Vec::from_raw_parts(other.ptr.as_ptr(), other.len, other.cap) } + // safe to convert back to Vec. Assuming we're not starting with a vector in 64-bit virtual + // address space while building the app in 32-bit, and this vector is in that 32-bit physical + // space. + unsafe { + Vec::from_raw_parts( + other.addr as usize as *mut T, + other.len as usize, + other.cap as usize, + ) + } } } @@ -147,7 +154,13 @@ impl Drop for StableVec { // // SAFETY: We have a valid StableVec, which we can only get from a Vec. Therefore it is // safe to convert back to Vec. - let _vec = unsafe { Vec::from_raw_parts(self.ptr.as_ptr(), self.len, self.cap) }; + let _vec = unsafe { + Vec::from_raw_parts( + self.addr as usize as *mut T, + self.len as usize, + self.cap as usize, + ) + }; } }