corevm_host/
page.rs

1use jam_types::Segment;
2
3/// Inner VM page size.
4pub const PAGE_SIZE: u64 = 4096;
5
6/// An import/export segment that stores an inner VM page and its address.
7///
8/// The page is stored in the first 4096 bytes,
9/// the address is encoded using little-endian format in the last 8 bytes of the segment.
10///
11/// `[ page(4096) | address(8) ]`
12#[derive(Clone)]
13pub struct PageSegment(Segment);
14
15impl PageSegment {
16	/// Create page segment from existing import/export segment.
17	pub fn new(segment: Segment) -> Self {
18		Self(segment)
19	}
20
21	/// Create zero-filled page with the supplied `address`.
22	pub fn zero(address: u64) -> Self {
23		let mut segment = Segment::new(0_u8);
24		segment.as_mut()[PAGE_SIZE as usize..].copy_from_slice(&address.to_le_bytes()[..]);
25		Self(segment)
26	}
27
28	/// Create zero-filled page with null address.
29	pub fn null() -> Self {
30		Self(Segment::new(0_u8))
31	}
32
33	/// Get immutable reference to the page contents (excluding the address).
34	pub fn page(&self) -> &[u8] {
35		&self.0.as_ref()[..PAGE_SIZE as usize]
36	}
37
38	/// Get mutable reference to the page contents (excluding the address).
39	pub fn page_mut(&mut self) -> &mut [u8] {
40		&mut self.0.as_mut()[..PAGE_SIZE as usize]
41	}
42
43	/// Get the address.
44	pub fn address(&self) -> u64 {
45		page_address(self.0.as_ref())
46	}
47
48	pub fn into_inner(self) -> Segment {
49		self.0
50	}
51}
52
53impl AsRef<[u8]> for PageSegment {
54	fn as_ref(&self) -> &[u8] {
55		self.0.as_ref()
56	}
57}
58
59impl AsMut<[u8]> for PageSegment {
60	fn as_mut(&mut self) -> &mut [u8] {
61		self.0.as_mut()
62	}
63}
64
65impl From<Segment> for PageSegment {
66	fn from(other: Segment) -> Self {
67		Self::new(other)
68	}
69}
70
71impl From<PageSegment> for Segment {
72	fn from(other: PageSegment) -> Self {
73		other.0
74	}
75}
76
77pub fn page_address(segment: &[u8]) -> u64 {
78	let a = &segment[PAGE_SIZE as usize..];
79	u64::from_le_bytes([a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]])
80}