1use super::super::{Error, Register, RISCV_MAX_MEMORY, RISCV_PAGESIZE};
2use super::{
3 check_permission, get_page_indices, round_page_down, round_page_up, Memory, FLAG_EXECUTABLE,
4 FLAG_FREEZED, FLAG_WRITABLE,
5};
6
7use bytes::Bytes;
8
9pub struct WXorXMemory<M: Memory> {
10 inner: M,
11}
12
13impl<M: Memory> WXorXMemory<M> {
14 pub fn inner_mut(&mut self) -> &mut M {
15 &mut self.inner
16 }
17}
18
19impl<M: Memory> Memory for WXorXMemory<M> {
20 type REG = M::REG;
21
22 fn new() -> Self {
23 Self::new_with_memory(RISCV_MAX_MEMORY)
24 }
25
26 fn new_with_memory(memory_size: usize) -> Self {
27 Self {
28 inner: M::new_with_memory(memory_size),
29 }
30 }
31
32 fn init_pages(
33 &mut self,
34 addr: u64,
35 size: u64,
36 flags: u8,
37 source: Option<Bytes>,
38 offset_from_addr: u64,
39 ) -> Result<(), Error> {
40 if round_page_down(addr) != addr || round_page_up(size) != size {
41 return Err(Error::MemPageUnalignedAccess);
42 }
43
44 if addr > self.memory_size() as u64
45 || size > self.memory_size() as u64
46 || addr + size > self.memory_size() as u64
47 || offset_from_addr > size
48 {
49 return Err(Error::MemOutOfBound);
50 }
51 for page_addr in (addr..addr + size).step_by(RISCV_PAGESIZE) {
52 let page = page_addr / RISCV_PAGESIZE as u64;
53 if self.fetch_flag(page)? & FLAG_FREEZED != 0 {
54 return Err(Error::MemWriteOnFreezedPage);
55 }
56 self.set_flag(page, flags)?;
57 }
58 self.inner
59 .init_pages(addr, size, flags, source, offset_from_addr)
60 }
61
62 fn fetch_flag(&mut self, page: u64) -> Result<u8, Error> {
63 self.inner.fetch_flag(page)
64 }
65
66 fn set_flag(&mut self, page: u64, flag: u8) -> Result<(), Error> {
67 self.inner.set_flag(page, flag)
68 }
69
70 fn clear_flag(&mut self, page: u64, flag: u8) -> Result<(), Error> {
71 self.inner.clear_flag(page, flag)
72 }
73
74 fn memory_size(&self) -> usize {
75 self.inner.memory_size()
76 }
77
78 fn execute_load16(&mut self, addr: u64) -> Result<u16, Error> {
79 let page_indices = get_page_indices(addr, 2)?;
80 check_permission(self, &page_indices, FLAG_EXECUTABLE)?;
81 self.inner.execute_load16(addr)
82 }
83
84 fn execute_load32(&mut self, addr: u64) -> Result<u32, Error> {
85 let page_indices = get_page_indices(addr, 4)?;
86 check_permission(self, &page_indices, FLAG_EXECUTABLE)?;
87 self.inner.execute_load32(addr)
88 }
89
90 fn load8(&mut self, addr: &Self::REG) -> Result<Self::REG, Error> {
91 self.inner.load8(addr)
92 }
93
94 fn load16(&mut self, addr: &Self::REG) -> Result<Self::REG, Error> {
95 self.inner.load16(addr)
96 }
97
98 fn load32(&mut self, addr: &Self::REG) -> Result<Self::REG, Error> {
99 self.inner.load32(addr)
100 }
101
102 fn load64(&mut self, addr: &Self::REG) -> Result<Self::REG, Error> {
103 self.inner.load64(addr)
104 }
105
106 fn store8(&mut self, addr: &Self::REG, value: &Self::REG) -> Result<(), Error> {
107 let page_indices = get_page_indices(addr.to_u64(), 1)?;
108 check_permission(self, &page_indices, FLAG_WRITABLE)?;
109 self.inner.store8(addr, value)
110 }
111
112 fn store16(&mut self, addr: &Self::REG, value: &Self::REG) -> Result<(), Error> {
113 let page_indices = get_page_indices(addr.to_u64(), 2)?;
114 check_permission(self, &page_indices, FLAG_WRITABLE)?;
115 self.inner.store16(addr, value)
116 }
117
118 fn store32(&mut self, addr: &Self::REG, value: &Self::REG) -> Result<(), Error> {
119 let page_indices = get_page_indices(addr.to_u64(), 4)?;
120 check_permission(self, &page_indices, FLAG_WRITABLE)?;
121 self.inner.store32(addr, value)
122 }
123
124 fn store64(&mut self, addr: &Self::REG, value: &Self::REG) -> Result<(), Error> {
125 let page_indices = get_page_indices(addr.to_u64(), 8)?;
126 check_permission(self, &page_indices, FLAG_WRITABLE)?;
127 self.inner.store64(addr, value)
128 }
129
130 fn store_bytes(&mut self, addr: u64, value: &[u8]) -> Result<(), Error> {
131 if value.is_empty() {
132 return Ok(());
133 }
134 let page_indices = get_page_indices(addr, value.len() as u64)?;
135 check_permission(self, &page_indices, FLAG_WRITABLE)?;
136 self.inner.store_bytes(addr, value)
137 }
138
139 fn store_byte(&mut self, addr: u64, size: u64, value: u8) -> Result<(), Error> {
140 if size == 0 {
141 return Ok(());
142 }
143 let page_indices = get_page_indices(addr, size)?;
144 check_permission(self, &page_indices, FLAG_WRITABLE)?;
145 self.inner.store_byte(addr, size, value)
146 }
147
148 fn load_bytes(&mut self, addr: u64, size: u64) -> Result<Bytes, Error> {
149 self.inner.load_bytes(addr, size)
151 }
152
153 fn lr(&self) -> &Self::REG {
154 self.inner.lr()
155 }
156
157 fn set_lr(&mut self, value: &Self::REG) {
158 self.inner.set_lr(value);
159 }
160}