openvm_platform/
memory.rs

1pub const MEM_BITS: usize = 29;
2pub const MEM_SIZE: usize = 1 << MEM_BITS;
3pub const GUEST_MIN_MEM: usize = 0x0000_0400;
4pub const GUEST_MAX_MEM: usize = MEM_SIZE;
5
6/// Top of stack; stack grows down from this location.
7pub const STACK_TOP: u32 = 0x0020_0400;
8/// Program (text followed by data and then bss) gets loaded in
9/// starting at this location.  HEAP begins right afterwards.
10pub const TEXT_START: u32 = 0x0020_0800;
11
12/// Returns whether `addr` is within guest memory bounds.
13pub fn is_guest_memory(addr: u32) -> bool {
14    GUEST_MIN_MEM <= (addr as usize) && (addr as usize) < GUEST_MAX_MEM
15}
16
17/// # Safety
18///
19/// This function should be safe to call, but clippy complains if it is not marked as `unsafe`.
20#[cfg(feature = "rust-runtime")]
21#[no_mangle]
22pub unsafe extern "C" fn sys_alloc_aligned(bytes: usize, align: usize) -> *mut u8 {
23    use crate::print::println;
24
25    #[cfg(target_os = "zkvm")]
26    extern "C" {
27        // This symbol is defined by the loader and marks the end
28        // of all elf sections, so this is where we start our
29        // heap.
30        //
31        // This is generated automatically by the linker; see
32        // https://lld.llvm.org/ELF/linker_script.html#sections-command
33        static _end: u8;
34    }
35
36    // Pointer to next heap address to use, or 0 if the heap has not yet been
37    // initialized.
38    static mut HEAP_POS: usize = 0;
39
40    // SAFETY: Single threaded, so nothing else can touch this while we're working.
41    let mut heap_pos = unsafe { HEAP_POS };
42
43    #[cfg(target_os = "zkvm")]
44    if heap_pos == 0 {
45        heap_pos = unsafe { (&_end) as *const u8 as usize };
46    }
47
48    // Honor requested alignment if larger than word size.
49    // Note: align is typically a power of two.
50    let align = usize::max(align, super::WORD_SIZE);
51
52    let offset = heap_pos & (align - 1);
53    if offset != 0 {
54        heap_pos += align - offset;
55    }
56
57    match heap_pos.checked_add(bytes) {
58        Some(new_heap_pos) if new_heap_pos <= GUEST_MAX_MEM => {
59            // SAFETY: Single threaded, and non-preemptive so modification is safe.
60            unsafe { HEAP_POS = new_heap_pos };
61        }
62        _ => {
63            println("ERROR: Maximum memory exceeded, program terminating.");
64            super::rust_rt::terminate::<1>();
65        }
66    }
67    heap_pos as *mut u8
68}