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 } else if addr >= APIC_MEM_ADDRESS && addr < APIC_MEM_ADDRESS + APIC_MEM_SIZE {
90 apic::read32((addr - APIC_MEM_ADDRESS) & !3) as i32 >> 8 * (addr & 3) & 0xFF
91 } else if addr >= IOAPIC_MEM_ADDRESS && addr < IOAPIC_MEM_ADDRESS + IOAPIC_MEM_SIZE {
92 ioapic::read32((addr - IOAPIC_MEM_ADDRESS) & !3) as i32 >> 8 * (addr & 3) & 0xFF
93 } else {
94 unsafe { ext::mmap_read8(addr) }
95 }
96 } else {
97 read8_no_mmap_check(addr)
98 }
99}
100pub fn read8_no_mmap_check(addr: u32) -> i32 {
101 unsafe { *mem8.offset(addr as isize) as i32 }
102}
103
104#[no_mangle]
105pub fn read16(addr: u32) -> i32 {
106 if in_mapped_range(addr) {
107 if in_svga_lfb(addr) {
108 unsafe {
109 ptr::read_unaligned(vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *const u16)
110 as i32
111 }
112 } else {
113 read8(addr) | read8(addr + 1) << 8
114 }
115 } else {
116 read16_no_mmap_check(addr)
117 }
118}
119pub fn read16_no_mmap_check(addr: u32) -> i32 {
120 unsafe { ptr::read_unaligned(mem8.offset(addr as isize) as *const u16) as i32 }
121}
122
123#[no_mangle]
124pub fn read32s(addr: u32) -> i32 {
125 if in_mapped_range(addr) {
126 if in_svga_lfb(addr) {
127 unsafe {
128 ptr::read_unaligned(vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *const i32)
129 } } else if addr >= APIC_MEM_ADDRESS && addr < APIC_MEM_ADDRESS + APIC_MEM_SIZE {
131 apic::read32(addr - APIC_MEM_ADDRESS) as i32
132 } else if addr >= IOAPIC_MEM_ADDRESS && addr < IOAPIC_MEM_ADDRESS + IOAPIC_MEM_SIZE {
133 ioapic::read32(addr - IOAPIC_MEM_ADDRESS) as i32
134 } else {
135 unsafe { ext::mmap_read32(addr) }
136 }
137 } else {
138 read32_no_mmap_check(addr)
139 }
140}
141pub fn read32_no_mmap_check(addr: u32) -> i32 {
142 unsafe { ptr::read_unaligned(mem8.offset(addr as isize) as *const i32) }
143}
144
145pub unsafe fn read64s(addr: u32) -> i64 {
146 if in_mapped_range(addr) {
147 if in_svga_lfb(addr) {
148 ptr::read_unaligned(vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *const i64)
149 } else {
150 read32s(addr) as i64 | (read32s(addr + 4) as i64) << 32
151 }
152 } else {
153 ptr::read_unaligned(mem8.offset(addr as isize) as *const i64)
154 }
155}
156
157pub unsafe fn read128(addr: u32) -> reg128 {
158 if in_mapped_range(addr) {
159 if in_svga_lfb(addr) {
160 ptr::read_unaligned(vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *const reg128)
161 } else {
162 reg128 {
163 i32: [
164 read32s(addr + 0),
165 read32s(addr + 4),
166 read32s(addr + 8),
167 read32s(addr + 12),
168 ],
169 }
170 }
171 } else {
172 ptr::read_unaligned(mem8.offset(addr as isize) as *const reg128)
173 }
174}
175
176#[no_mangle]
177pub unsafe fn write8(addr: u32, value: i32) {
178 if in_mapped_range(addr) {
179 mmap_write8(addr, value & 0xFF);
180 } else {
181 jit::jit_dirty_page(Page::page_of(addr));
182 write8_no_mmap_or_dirty_check(addr, value);
183 };
184}
185
186pub unsafe fn write8_no_mmap_or_dirty_check(addr: u32, value: i32) {
187 *mem8.offset(addr as isize) = value as u8
188}
189
190#[no_mangle]
191pub unsafe fn write16(addr: u32, value: i32) {
192 if in_mapped_range(addr) {
193 mmap_write16(addr, value & 0xFFFF);
194 } else {
195 jit::jit_dirty_cache_small(addr, addr + 2);
196 write16_no_mmap_or_dirty_check(addr, value);
197 };
198}
199pub unsafe fn write16_no_mmap_or_dirty_check(addr: u32, value: i32) {
200 ptr::write_unaligned(mem8.offset(addr as isize) as *mut u16, value as u16)
201}
202
203#[no_mangle]
204pub unsafe fn write32(addr: u32, value: i32) {
205 if in_mapped_range(addr) {
206 mmap_write32(addr, value);
207 } else {
208 jit::jit_dirty_cache_small(addr, addr + 4);
209 write32_no_mmap_or_dirty_check(addr, value);
210 }
211}
212
213pub unsafe fn write32_no_mmap_or_dirty_check(addr: u32, value: i32) {
214 ptr::write_unaligned(mem8.offset(addr as isize) as *mut i32, value)
215}
216
217pub unsafe fn write64_no_mmap_or_dirty_check(addr: u32, value: u64) {
218 ptr::write_unaligned(mem8.offset(addr as isize) as *mut u64, value)
219}
220
221pub unsafe fn write128_no_mmap_or_dirty_check(addr: u32, value: reg128) {
222 ptr::write_unaligned(mem8.offset(addr as isize) as *mut reg128, value)
223}
224
225pub unsafe fn memset_no_mmap_or_dirty_check(addr: u32, value: u8, count: u32) {
226 ptr::write_bytes(mem8.offset(addr as isize), value, count as usize);
227}
228
229pub unsafe fn memcpy_no_mmap_or_dirty_check(src_addr: u32, dst_addr: u32, count: u32) {
230 dbg_assert!(src_addr < *memory_size);
231 dbg_assert!(dst_addr < *memory_size);
232 ptr::copy(
233 mem8.offset(src_addr as isize),
234 mem8.offset(dst_addr as isize),
235 count as usize,
236 )
237}
238
239pub unsafe fn memcpy_into_svga_lfb(src_addr: u32, dst_addr: u32, count: u32) {
240 dbg_assert!(src_addr < *memory_size);
241 dbg_assert!(in_svga_lfb(dst_addr));
242 dbg_assert!(Page::page_of(dst_addr) == Page::page_of(dst_addr + count - 1));
243 vga::mark_dirty(dst_addr);
244 ptr::copy_nonoverlapping(
245 mem8.offset(src_addr as isize),
246 vga_mem8.offset((dst_addr - VGA_LFB_ADDRESS) as isize),
247 count as usize,
248 )
249}
250
251pub unsafe fn mmap_write8(addr: u32, value: i32) {
252 if in_svga_lfb(addr) {
253 vga::mark_dirty(addr);
254 *vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) = value as u8
255 } else {
256 ext::mmap_write8(addr, value)
257 }
258}
259pub unsafe fn mmap_write16(addr: u32, value: i32) {
260 if in_svga_lfb(addr) {
261 vga::mark_dirty(addr);
262 ptr::write_unaligned(
263 vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *mut u16,
264 value as u16,
265 )
266 } else {
267 ext::mmap_write16(addr, value)
268 }
269}
270pub unsafe fn mmap_write32(addr: u32, value: i32) {
271 if in_svga_lfb(addr) {
272 vga::mark_dirty(addr);
273 ptr::write_unaligned(
274 vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *mut i32,
275 value,
276 )
277 } else if addr >= APIC_MEM_ADDRESS && addr < APIC_MEM_ADDRESS + APIC_MEM_SIZE {
278 apic::write32(addr - APIC_MEM_ADDRESS, value as u32);
279 handle_irqs();
280 } else if addr >= IOAPIC_MEM_ADDRESS && addr < IOAPIC_MEM_ADDRESS + IOAPIC_MEM_SIZE {
281 ioapic::write32(addr - IOAPIC_MEM_ADDRESS, value as u32);
282 handle_irqs();
283 } else {
284 ext::mmap_write32(addr, value)
285 }
286}
287pub unsafe fn mmap_write64(addr: u32, value: u64) {
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 u64,
292 value,
293 )
294 } else {
295 ext::mmap_write64(addr, value as i32, (value >> 32) as i32)
296 }
297}
298pub unsafe fn mmap_write128(addr: u32, v0: u64, v1: u64) {
299 if in_svga_lfb(addr) {
300 vga::mark_dirty(addr);
301 ptr::write_unaligned(
302 vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *mut u64,
303 v0,
304 );
305 ptr::write_unaligned(
306 vga_mem8.offset((addr - VGA_LFB_ADDRESS + 8) as isize) as *mut u64,
307 v1,
308 )
309 } else {
310 ext::mmap_write128(
311 addr,
312 v0 as i32,
313 (v0 >> 32) as i32,
314 v1 as i32,
315 (v1 >> 32) as i32,
316 )
317 }
318}
319
320#[no_mangle]
321pub unsafe fn is_memory_zeroed(addr: u32, length: u32) -> bool {
322 dbg_assert!(addr % 8 == 0);
323 dbg_assert!(length % 8 == 0);
324 for i in (addr..addr + length).step_by(8) {
325 if *(mem8.offset(i as isize) as *const i64) != 0 {
326 return false;
327 }
328 }
329 return true;
330}