corevm_host/
page.rs

1use codec::{ConstEncodedLen, Decode, Encode, MaxEncodedLen};
2use jam_types::{Segment, SEGMENT_LEN};
3
4/// Inner VM page size.
5pub const PAGE_SIZE: u64 = 4096;
6
7/// Page address.
8#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encode, Decode, MaxEncodedLen)]
9pub struct PageAddr(pub u64);
10
11impl core::fmt::Debug for PageAddr {
12	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
13		let page = self.0 / PAGE_SIZE;
14		write!(f, "{page}/{:#x}", self.0)
15	}
16}
17
18impl core::fmt::Display for PageAddr {
19	fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
20		core::fmt::Debug::fmt(self, f)
21	}
22}
23
24impl ConstEncodedLen for PageAddr {}
25
26/// An import/export segment that stores an inner VM page and its address.
27///
28/// The page is stored in the first 4096 bytes,
29/// the address is encoded using little-endian format in the last 8 bytes of the segment.
30///
31/// `[ page(4096) | address(8) ]`
32pub trait PageSegmentOps {
33	/// Get immutable reference to the page contents (excluding the address).
34	fn page(&self) -> &[u8];
35
36	/// Get mutable reference to the page contents (excluding the address).
37	fn page_mut(&mut self) -> &mut [u8];
38
39	/// Get the address.
40	fn page_address(&self) -> u64;
41
42	/// Set the address.
43	fn set_page_address(&mut self, address: u64);
44}
45
46impl PageSegmentOps for [u8] {
47	fn page(&self) -> &[u8] {
48		debug_assert_eq!(SEGMENT_LEN, self.len());
49		&self[..PAGE_SIZE as usize]
50	}
51
52	fn page_mut(&mut self) -> &mut [u8] {
53		debug_assert_eq!(SEGMENT_LEN, self.len());
54		&mut self[..PAGE_SIZE as usize]
55	}
56
57	fn page_address(&self) -> u64 {
58		debug_assert_eq!(SEGMENT_LEN, self.len());
59		let a = &self[PAGE_SIZE as usize..];
60		u64::from_le_bytes([a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]])
61	}
62
63	fn set_page_address(&mut self, address: u64) {
64		debug_assert_eq!(SEGMENT_LEN, self.len());
65		self[PAGE_SIZE as usize..].copy_from_slice(&address.to_le_bytes()[..]);
66	}
67}
68
69impl PageSegmentOps for Segment {
70	fn page(&self) -> &[u8] {
71		self.as_ref().page()
72	}
73
74	fn page_mut(&mut self) -> &mut [u8] {
75		self.as_mut().page_mut()
76	}
77
78	fn page_address(&self) -> u64 {
79		self.as_ref().page_address()
80	}
81
82	fn set_page_address(&mut self, address: u64) {
83		self.as_mut().set_page_address(address)
84	}
85}