1mod ext {
2 #[link(wasm_import_module = "env")]
3 extern "C" {
4 pub fn mmap_read8(addr: u32) -> i32;
5 pub fn mmap_read32(addr: u32) -> i32;
6
7 pub fn mmap_write8(addr: u32, value: i32);
8 pub fn mmap_write16(addr: u32, value: i32);
9 pub fn mmap_write32(addr: u32, value: i32);
10 pub fn mmap_write64(addr: u32, v0: i32, v1: i32);
11 pub fn mmap_write128(addr: u32, v0: i32, v1: i32, v2: i32, v3: i32);
12 }
13}
14
15use crate::cpu::apic;
16use crate::cpu::cpu::{
17 handle_irqs, reg128, APIC_MEM_ADDRESS, APIC_MEM_SIZE, IOAPIC_MEM_ADDRESS, IOAPIC_MEM_SIZE,
18};
19use crate::cpu::global_pointers::memory_size;
20use crate::cpu::ioapic;
21use crate::cpu::vga;
22use crate::jit;
23use crate::page::Page;
24
25use std::alloc;
26use std::ptr;
27
28#[allow(non_upper_case_globals)]
29pub static mut mem8: *mut u8 = ptr::null_mut();
30
31#[no_mangle]
32pub fn allocate_memory(size: u32) -> u32 {
33 unsafe {
34 dbg_assert!(mem8.is_null());
35 };
36 dbg_log!("Allocate memory size={}m", size >> 20);
37 let layout = alloc::Layout::from_size_align(size as usize, 0x1000).unwrap();
38 let raw = unsafe { alloc::alloc(layout) };
39 unsafe {
40 mem8 = raw;
41 };
42 raw as u32
43}
44
45#[no_mangle]
46pub unsafe fn zero_memory(addr: u32, size: u32) {
47 ptr::write_bytes(mem8.offset(addr as isize), 0, size as usize);
48}
49
50#[allow(non_upper_case_globals)]
51pub static mut vga_mem8: *mut u8 = ptr::null_mut();
52#[allow(non_upper_case_globals)]
53pub static mut vga_memory_size: u32 = 0;
54
55#[no_mangle]
56pub fn svga_allocate_memory(size: u32) -> u32 {
57 unsafe {
58 dbg_assert!(vga_mem8.is_null());
59 };
60 let layout = alloc::Layout::from_size_align(size as usize, 0x1000).unwrap();
61 let raw = unsafe { alloc::alloc(layout) };
62 dbg_assert!(
63 size & (1 << 12 << 6) == 0,
64 "size not aligned to dirty_bitmap"
65 );
66 unsafe {
67 vga_mem8 = raw;
68 vga_memory_size = size;
69 vga::set_dirty_bitmap_size(size >> 12 >> 6);
70 };
71 raw as u32
72}
73
74#[no_mangle]
75pub fn in_mapped_range(addr: u32) -> bool {
76 return addr >= 0xA0000 && addr < 0xC0000 || addr >= unsafe { *memory_size };
77}
78
79pub const VGA_LFB_ADDRESS: u32 = 0xE0000000;
80pub fn in_svga_lfb(addr: u32) -> bool {
81 addr >= VGA_LFB_ADDRESS && addr <= unsafe { VGA_LFB_ADDRESS + (vga_memory_size - 1) }
82}
83
84#[no_mangle]
85pub fn read8(addr: u32) -> i32 {
86 if in_mapped_range(addr) {
87 if in_svga_lfb(addr) {
88 unsafe { *vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as i32 }
89 }
90 else if addr >= APIC_MEM_ADDRESS && addr < APIC_MEM_ADDRESS + APIC_MEM_SIZE {
91 apic::read32((addr - APIC_MEM_ADDRESS) & !3) as i32 >> 8 * (addr & 3) & 0xFF
92 }
93 else if addr >= IOAPIC_MEM_ADDRESS && addr < IOAPIC_MEM_ADDRESS + IOAPIC_MEM_SIZE {
94 ioapic::read32((addr - IOAPIC_MEM_ADDRESS) & !3) as i32 >> 8 * (addr & 3) & 0xFF
95 }
96 else {
97 unsafe { ext::mmap_read8(addr) }
98 }
99 }
100 else {
101 read8_no_mmap_check(addr)
102 }
103}
104pub fn read8_no_mmap_check(addr: u32) -> i32 { unsafe { *mem8.offset(addr as isize) as i32 } }
105
106#[no_mangle]
107pub fn read16(addr: u32) -> i32 {
108 if in_mapped_range(addr) {
109 if in_svga_lfb(addr) {
110 unsafe {
111 ptr::read_unaligned(vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *const u16)
112 as i32
113 }
114 }
115 else {
116 read8(addr) | read8(addr + 1) << 8
117 }
118 }
119 else {
120 read16_no_mmap_check(addr)
121 }
122}
123pub fn read16_no_mmap_check(addr: u32) -> i32 {
124 unsafe { ptr::read_unaligned(mem8.offset(addr as isize) as *const u16) as i32 }
125}
126
127#[no_mangle]
128pub fn read32s(addr: u32) -> i32 {
129 if in_mapped_range(addr) {
130 if in_svga_lfb(addr) {
131 unsafe {
132 ptr::read_unaligned(vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *const i32)
133 } }
135 else if addr >= APIC_MEM_ADDRESS && addr < APIC_MEM_ADDRESS + APIC_MEM_SIZE {
136 apic::read32(addr - APIC_MEM_ADDRESS) as i32
137 }
138 else if addr >= IOAPIC_MEM_ADDRESS && addr < IOAPIC_MEM_ADDRESS + IOAPIC_MEM_SIZE {
139 ioapic::read32(addr - IOAPIC_MEM_ADDRESS) as i32
140 }
141 else {
142 unsafe { ext::mmap_read32(addr) }
143 }
144 }
145 else {
146 read32_no_mmap_check(addr)
147 }
148}
149pub fn read32_no_mmap_check(addr: u32) -> i32 {
150 unsafe { ptr::read_unaligned(mem8.offset(addr as isize) as *const i32) }
151}
152
153pub unsafe fn read64s(addr: u32) -> i64 {
154 if in_mapped_range(addr) {
155 if in_svga_lfb(addr) {
156 ptr::read_unaligned(vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *const i64)
157 }
158 else {
159 read32s(addr) as i64 | (read32s(addr + 4) as i64) << 32
160 }
161 }
162 else {
163 ptr::read_unaligned(mem8.offset(addr as isize) as *const i64)
164 }
165}
166
167pub unsafe fn read128(addr: u32) -> reg128 {
168 if in_mapped_range(addr) {
169 if in_svga_lfb(addr) {
170 ptr::read_unaligned(vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *const reg128)
171 }
172 else {
173 reg128 {
174 i32: [
175 read32s(addr + 0),
176 read32s(addr + 4),
177 read32s(addr + 8),
178 read32s(addr + 12),
179 ],
180 }
181 }
182 }
183 else {
184 ptr::read_unaligned(mem8.offset(addr as isize) as *const reg128)
185 }
186}
187
188#[no_mangle]
189pub unsafe fn write8(addr: u32, value: i32) {
190 if in_mapped_range(addr) {
191 mmap_write8(addr, value & 0xFF);
192 }
193 else {
194 jit::jit_dirty_page(Page::page_of(addr));
195 write8_no_mmap_or_dirty_check(addr, value);
196 };
197}
198
199pub unsafe fn write8_no_mmap_or_dirty_check(addr: u32, value: i32) {
200 *mem8.offset(addr as isize) = value as u8
201}
202
203#[no_mangle]
204pub unsafe fn write16(addr: u32, value: i32) {
205 if in_mapped_range(addr) {
206 mmap_write16(addr, value & 0xFFFF);
207 }
208 else {
209 jit::jit_dirty_cache_small(addr, addr + 2);
210 write16_no_mmap_or_dirty_check(addr, value);
211 };
212}
213pub unsafe fn write16_no_mmap_or_dirty_check(addr: u32, value: i32) {
214 ptr::write_unaligned(mem8.offset(addr as isize) as *mut u16, value as u16)
215}
216
217#[no_mangle]
218pub unsafe fn write32(addr: u32, value: i32) {
219 if in_mapped_range(addr) {
220 mmap_write32(addr, value);
221 }
222 else {
223 jit::jit_dirty_cache_small(addr, addr + 4);
224 write32_no_mmap_or_dirty_check(addr, value);
225 }
226}
227
228pub unsafe fn write32_no_mmap_or_dirty_check(addr: u32, value: i32) {
229 ptr::write_unaligned(mem8.offset(addr as isize) as *mut i32, value)
230}
231
232pub unsafe fn write64_no_mmap_or_dirty_check(addr: u32, value: u64) {
233 ptr::write_unaligned(mem8.offset(addr as isize) as *mut u64, value)
234}
235
236pub unsafe fn write128_no_mmap_or_dirty_check(addr: u32, value: reg128) {
237 ptr::write_unaligned(mem8.offset(addr as isize) as *mut reg128, value)
238}
239
240pub unsafe fn memset_no_mmap_or_dirty_check(addr: u32, value: u8, count: u32) {
241 ptr::write_bytes(mem8.offset(addr as isize), value, count as usize);
242}
243
244pub unsafe fn memcpy_no_mmap_or_dirty_check(src_addr: u32, dst_addr: u32, count: u32) {
245 dbg_assert!(src_addr < *memory_size);
246 dbg_assert!(dst_addr < *memory_size);
247 ptr::copy(
248 mem8.offset(src_addr as isize),
249 mem8.offset(dst_addr as isize),
250 count as usize,
251 )
252}
253
254pub unsafe fn memcpy_into_svga_lfb(src_addr: u32, dst_addr: u32, count: u32) {
255 dbg_assert!(src_addr < *memory_size);
256 dbg_assert!(in_svga_lfb(dst_addr));
257 dbg_assert!(Page::page_of(dst_addr) == Page::page_of(dst_addr + count - 1));
258 vga::mark_dirty(dst_addr);
259 ptr::copy_nonoverlapping(
260 mem8.offset(src_addr as isize),
261 vga_mem8.offset((dst_addr - VGA_LFB_ADDRESS) as isize),
262 count as usize,
263 )
264}
265
266pub unsafe fn mmap_write8(addr: u32, value: i32) {
267 if in_svga_lfb(addr) {
268 vga::mark_dirty(addr);
269 *vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) = value as u8
270 }
271 else {
272 ext::mmap_write8(addr, value)
273 }
274}
275pub unsafe fn mmap_write16(addr: u32, value: i32) {
276 if in_svga_lfb(addr) {
277 vga::mark_dirty(addr);
278 ptr::write_unaligned(
279 vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *mut u16,
280 value as u16,
281 )
282 }
283 else {
284 ext::mmap_write16(addr, value)
285 }
286}
287pub unsafe fn mmap_write32(addr: u32, value: i32) {
288 if in_svga_lfb(addr) {
289 vga::mark_dirty(addr);
290 ptr::write_unaligned(
291 vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *mut i32,
292 value,
293 )
294 }
295 else if addr >= APIC_MEM_ADDRESS && addr < APIC_MEM_ADDRESS + APIC_MEM_SIZE {
296 apic::write32(addr - APIC_MEM_ADDRESS, value as u32);
297 handle_irqs();
298 }
299 else if addr >= IOAPIC_MEM_ADDRESS && addr < IOAPIC_MEM_ADDRESS + IOAPIC_MEM_SIZE {
300 ioapic::write32(addr - IOAPIC_MEM_ADDRESS, value as u32);
301 handle_irqs();
302 }
303 else {
304 ext::mmap_write32(addr, value)
305 }
306}
307pub unsafe fn mmap_write64(addr: u32, value: u64) {
308 if in_svga_lfb(addr) {
309 vga::mark_dirty(addr);
310 ptr::write_unaligned(
311 vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *mut u64,
312 value,
313 )
314 }
315 else {
316 ext::mmap_write64(addr, value as i32, (value >> 32) as i32)
317 }
318}
319pub unsafe fn mmap_write128(addr: u32, v0: u64, v1: u64) {
320 if in_svga_lfb(addr) {
321 vga::mark_dirty(addr);
322 ptr::write_unaligned(
323 vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *mut u64,
324 v0,
325 );
326 ptr::write_unaligned(
327 vga_mem8.offset((addr - VGA_LFB_ADDRESS + 8) as isize) as *mut u64,
328 v1,
329 )
330 }
331 else {
332 ext::mmap_write128(
333 addr,
334 v0 as i32,
335 (v0 >> 32) as i32,
336 v1 as i32,
337 (v1 >> 32) as i32,
338 )
339 }
340}
341
342#[no_mangle]
343pub unsafe fn is_memory_zeroed(addr: u32, length: u32) -> bool {
344 dbg_assert!(addr % 8 == 0);
345 dbg_assert!(length % 8 == 0);
346 for i in (addr..addr + length).step_by(8) {
347 if *(mem8.offset(i as isize) as *const i64) != 0 {
348 return false;
349 }
350 }
351 return true;
352}