Skip to content

Commit b711ee2

Browse files
876polclaude
andcommitted
feat: seperate vm_read and vm_write into good and bad versions
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent d4d46d7 commit b711ee2

File tree

5 files changed

+79
-2
lines changed

5 files changed

+79
-2
lines changed

crates/vm/src/arch/execution_mode/metered/ctx.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,27 @@ impl<const PAGE_BITS: usize> ExecutionCtxTrait for MeteredCtx<PAGE_BITS> {
235235
}
236236
}
237237

238+
#[inline(always)]
239+
fn on_memory_operation_no_adapter(&mut self, address_space: u32, ptr: u32, size: u32) {
240+
debug_assert!(
241+
address_space != RV32_IMM_AS,
242+
"address space must not be immediate"
243+
);
244+
debug_assert!(size > 0, "size must be greater than 0, got {size}");
245+
debug_assert!(
246+
size.is_power_of_two(),
247+
"size must be a power of 2, got {size}"
248+
);
249+
250+
// No access adapter updates for non-Native extensions
251+
252+
// Handle merkle tree updates
253+
if address_space != RV32_REGISTER_AS {
254+
self.memory_ctx
255+
.update_boundary_merkle_heights(address_space, ptr, size);
256+
}
257+
}
258+
238259
#[inline(always)]
239260
fn should_suspend<F>(exec_state: &mut VmExecState<F, GuestMemory, Self>) -> bool {
240261
// ATTENTION: Please make sure to update the corresponding logic in the

crates/vm/src/arch/execution_mode/metered_cost.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,24 @@ impl ExecutionCtxTrait for MeteredCostCtx {
122122
}
123123
}
124124

125+
#[inline(always)]
126+
fn on_memory_operation_no_adapter(&mut self, address_space: u32, _ptr: u32, size: u32) {
127+
debug_assert!(
128+
address_space != RV32_IMM_AS,
129+
"address space must not be immediate"
130+
);
131+
debug_assert!(size > 0, "size must be greater than 0, got {size}");
132+
debug_assert!(
133+
size.is_power_of_two(),
134+
"size must be a power of 2, got {size}"
135+
);
136+
// Prevent unbounded memory accesses per instruction
137+
if self.cost > 2 * std::cmp::max(self.max_execution_cost, DEFAULT_MAX_COST) {
138+
self.panic_cost_exceeded();
139+
}
140+
// No access adapter updates for non-Native extensions
141+
}
142+
125143
#[inline(always)]
126144
fn should_suspend<F>(exec_state: &mut VmExecState<F, GuestMemory, Self>) -> bool {
127145
if exec_state.ctx.cost > exec_state.ctx.max_execution_cost {

crates/vm/src/arch/execution_mode/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ pub use pure::ExecutionCtx;
1313
pub trait ExecutionCtxTrait: Sized {
1414
fn on_memory_operation(&mut self, address_space: u32, ptr: u32, size: u32);
1515

16+
fn on_memory_operation_no_adapter(&mut self, address_space: u32, ptr: u32, size: u32);
17+
1618
fn should_suspend<F>(exec_state: &mut VmExecState<F, GuestMemory, Self>) -> bool;
1719

1820
fn on_terminate<F>(_exec_state: &mut VmExecState<F, GuestMemory, Self>) {}

crates/vm/src/arch/execution_mode/pure.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ impl ExecutionCtxTrait for ExecutionCtx {
2424
#[inline(always)]
2525
fn on_memory_operation(&mut self, _address_space: u32, _ptr: u32, _size: u32) {}
2626

27+
#[inline(always)]
28+
fn on_memory_operation_no_adapter(&mut self, _address_space: u32, _ptr: u32, _size: u32) {}
29+
2730
#[inline(always)]
2831
fn should_suspend<F>(exec_state: &mut VmExecState<F, GuestMemory, Self>) -> bool {
2932
// ATTENTION: Please make sure to update the corresponding logic in the

crates/vm/src/arch/state.rs

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,6 @@ impl<F, CTX> VmExecState<F, GuestMemory, CTX>
180180
where
181181
CTX: ExecutionCtxTrait,
182182
{
183-
/// Runtime read operation for a block of memory
184183
#[inline(always)]
185184
pub fn vm_read<T: Copy + Debug, const BLOCK_SIZE: usize>(
186185
&mut self,
@@ -192,7 +191,17 @@ where
192191
self.host_read(addr_space, ptr)
193192
}
194193

195-
/// Runtime write operation for a block of memory
194+
#[inline(always)]
195+
pub fn vm_read_no_adapter<T: Copy + Debug, const BLOCK_SIZE: usize>(
196+
&mut self,
197+
addr_space: u32,
198+
ptr: u32,
199+
) -> [T; BLOCK_SIZE] {
200+
self.ctx
201+
.on_memory_operation_no_adapter(addr_space, ptr, BLOCK_SIZE as u32);
202+
self.host_read(addr_space, ptr)
203+
}
204+
196205
#[inline(always)]
197206
pub fn vm_write<T: Copy + Debug, const BLOCK_SIZE: usize>(
198207
&mut self,
@@ -205,6 +214,18 @@ where
205214
self.host_write(addr_space, ptr, data)
206215
}
207216

217+
#[inline(always)]
218+
pub fn vm_write_no_adapter<T: Copy + Debug, const BLOCK_SIZE: usize>(
219+
&mut self,
220+
addr_space: u32,
221+
ptr: u32,
222+
data: &[T; BLOCK_SIZE],
223+
) {
224+
self.ctx
225+
.on_memory_operation_no_adapter(addr_space, ptr, BLOCK_SIZE as u32);
226+
self.host_write(addr_space, ptr, data)
227+
}
228+
208229
#[inline(always)]
209230
pub fn vm_read_slice<T: Copy + Debug>(
210231
&mut self,
@@ -216,6 +237,18 @@ where
216237
self.host_read_slice(addr_space, ptr, len)
217238
}
218239

240+
#[inline(always)]
241+
pub fn vm_read_slice_no_adapter<T: Copy + Debug>(
242+
&mut self,
243+
addr_space: u32,
244+
ptr: u32,
245+
len: usize,
246+
) -> &[T] {
247+
self.ctx
248+
.on_memory_operation_no_adapter(addr_space, ptr, len as u32);
249+
self.host_read_slice(addr_space, ptr, len)
250+
}
251+
219252
#[inline(always)]
220253
pub fn host_read<T: Copy + Debug, const BLOCK_SIZE: usize>(
221254
&self,

0 commit comments

Comments
 (0)