Spaces:
Runtime error
Runtime error
mod ext { | |
extern "C" { | |
pub fn mmap_read8(addr: u32) -> i32; | |
pub fn mmap_read16(addr: u32) -> i32; | |
pub fn mmap_read32(addr: u32) -> i32; | |
pub fn mmap_write8(addr: u32, value: i32); | |
pub fn mmap_write16(addr: u32, value: i32); | |
pub fn mmap_write32(addr: u32, value: i32); | |
pub fn mmap_write64(addr: u32, v0: i32, v1: i32); | |
pub fn mmap_write128(addr: u32, v0: i32, v1: i32, v2: i32, v3: i32); | |
} | |
} | |
use crate::cpu::apic; | |
use crate::cpu::cpu::{ | |
handle_irqs, reg128, APIC_MEM_ADDRESS, APIC_MEM_SIZE, IOAPIC_MEM_ADDRESS, IOAPIC_MEM_SIZE, | |
}; | |
use crate::cpu::global_pointers::memory_size; | |
use crate::cpu::ioapic; | |
use crate::cpu::vga; | |
use crate::jit; | |
use crate::page::Page; | |
use std::alloc; | |
use std::ptr; | |
pub static mut mem8: *mut u8 = ptr::null_mut(); | |
pub fn allocate_memory(size: u32) -> u32 { | |
unsafe { | |
dbg_assert!(mem8.is_null()); | |
}; | |
dbg_log!("Allocate memory size={}m", size >> 20); | |
let layout = alloc::Layout::from_size_align(size as usize, 0x1000).unwrap(); | |
let ptr = unsafe { alloc::alloc(layout) as u32 }; | |
unsafe { | |
mem8 = ptr as *mut u8; | |
}; | |
ptr | |
} | |
pub unsafe fn zero_memory(addr: u32, size: u32) { | |
ptr::write_bytes(mem8.offset(addr as isize), 0, size as usize); | |
} | |
pub static mut vga_mem8: *mut u8 = ptr::null_mut(); | |
pub static mut vga_memory_size: u32 = 0; | |
pub fn svga_allocate_memory(size: u32) -> u32 { | |
unsafe { | |
dbg_assert!(vga_mem8.is_null()); | |
}; | |
let layout = alloc::Layout::from_size_align(size as usize, 0x1000).unwrap(); | |
let ptr = unsafe { alloc::alloc(layout) }; | |
dbg_assert!( | |
size & (1 << 12 << 6) == 0, | |
"size not aligned to dirty_bitmap" | |
); | |
unsafe { | |
vga_mem8 = ptr; | |
vga_memory_size = size; | |
vga::set_dirty_bitmap_size(size >> 12 >> 6); | |
}; | |
ptr as u32 | |
} | |
pub fn in_mapped_range(addr: u32) -> bool { | |
return addr >= 0xA0000 && addr < 0xC0000 || addr >= unsafe { *memory_size }; | |
} | |
pub const VGA_LFB_ADDRESS: u32 = 0xE0000000; | |
pub fn in_svga_lfb(addr: u32) -> bool { | |
addr >= VGA_LFB_ADDRESS && addr <= unsafe { VGA_LFB_ADDRESS + (vga_memory_size - 1) } | |
} | |
pub fn read8(addr: u32) -> i32 { | |
if in_mapped_range(addr) { | |
if in_svga_lfb(addr) { | |
unsafe { *vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as i32 } | |
} | |
else { | |
unsafe { ext::mmap_read8(addr) } | |
} | |
} | |
else { | |
read8_no_mmap_check(addr) | |
} | |
} | |
pub fn read8_no_mmap_check(addr: u32) -> i32 { unsafe { *mem8.offset(addr as isize) as i32 } } | |
pub fn read16(addr: u32) -> i32 { | |
if in_mapped_range(addr) { | |
if in_svga_lfb(addr) { | |
unsafe { | |
ptr::read_unaligned(vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *const u16) | |
as i32 | |
} | |
} | |
else { | |
unsafe { ext::mmap_read16(addr) } | |
} | |
} | |
else { | |
read16_no_mmap_check(addr) | |
} | |
} | |
pub fn read16_no_mmap_check(addr: u32) -> i32 { | |
unsafe { ptr::read_unaligned(mem8.offset(addr as isize) as *const u16) as i32 } | |
} | |
pub fn read32s(addr: u32) -> i32 { | |
if in_mapped_range(addr) { | |
if in_svga_lfb(addr) { | |
unsafe { | |
ptr::read_unaligned(vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *const i32) | |
} // XXX | |
} | |
else if addr >= APIC_MEM_ADDRESS && addr < APIC_MEM_ADDRESS + APIC_MEM_SIZE { | |
apic::read32(addr - APIC_MEM_ADDRESS) as i32 | |
} | |
else if addr >= IOAPIC_MEM_ADDRESS && addr < IOAPIC_MEM_ADDRESS + IOAPIC_MEM_SIZE { | |
ioapic::read32(addr - IOAPIC_MEM_ADDRESS) as i32 | |
} | |
else { | |
unsafe { ext::mmap_read32(addr) } | |
} | |
} | |
else { | |
read32_no_mmap_check(addr) | |
} | |
} | |
pub fn read32_no_mmap_check(addr: u32) -> i32 { | |
unsafe { ptr::read_unaligned(mem8.offset(addr as isize) as *const i32) } | |
} | |
pub unsafe fn read64s(addr: u32) -> i64 { | |
if in_mapped_range(addr) { | |
if in_svga_lfb(addr) { | |
ptr::read_unaligned(vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *const i64) | |
} | |
else { | |
ext::mmap_read32(addr) as i64 | (ext::mmap_read32(addr + 4) as i64) << 32 | |
} | |
} | |
else { | |
ptr::read_unaligned(mem8.offset(addr as isize) as *const i64) | |
} | |
} | |
pub unsafe fn read128(addr: u32) -> reg128 { | |
if in_mapped_range(addr) { | |
if in_svga_lfb(addr) { | |
ptr::read_unaligned(vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *const reg128) | |
} | |
else { | |
reg128 { | |
i32: [ | |
ext::mmap_read32(addr + 0), | |
ext::mmap_read32(addr + 4), | |
ext::mmap_read32(addr + 8), | |
ext::mmap_read32(addr + 12), | |
], | |
} | |
} | |
} | |
else { | |
ptr::read_unaligned(mem8.offset(addr as isize) as *const reg128) | |
} | |
} | |
pub unsafe fn write8(addr: u32, value: i32) { | |
if in_mapped_range(addr) { | |
mmap_write8(addr, value & 0xFF); | |
} | |
else { | |
jit::jit_dirty_page(Page::page_of(addr)); | |
write8_no_mmap_or_dirty_check(addr, value); | |
}; | |
} | |
pub unsafe fn write8_no_mmap_or_dirty_check(addr: u32, value: i32) { | |
*mem8.offset(addr as isize) = value as u8 | |
} | |
pub unsafe fn write16(addr: u32, value: i32) { | |
if in_mapped_range(addr) { | |
mmap_write16(addr, value & 0xFFFF); | |
} | |
else { | |
jit::jit_dirty_cache_small(addr, addr + 2); | |
write16_no_mmap_or_dirty_check(addr, value); | |
}; | |
} | |
pub unsafe fn write16_no_mmap_or_dirty_check(addr: u32, value: i32) { | |
ptr::write_unaligned(mem8.offset(addr as isize) as *mut u16, value as u16) | |
} | |
pub unsafe fn write32(addr: u32, value: i32) { | |
if in_mapped_range(addr) { | |
mmap_write32(addr, value); | |
} | |
else { | |
jit::jit_dirty_cache_small(addr, addr + 4); | |
write32_no_mmap_or_dirty_check(addr, value); | |
} | |
} | |
pub unsafe fn write32_no_mmap_or_dirty_check(addr: u32, value: i32) { | |
ptr::write_unaligned(mem8.offset(addr as isize) as *mut i32, value) | |
} | |
pub unsafe fn write64_no_mmap_or_dirty_check(addr: u32, value: u64) { | |
ptr::write_unaligned(mem8.offset(addr as isize) as *mut u64, value) | |
} | |
pub unsafe fn write128_no_mmap_or_dirty_check(addr: u32, value: reg128) { | |
ptr::write_unaligned(mem8.offset(addr as isize) as *mut reg128, value) | |
} | |
pub unsafe fn memset_no_mmap_or_dirty_check(addr: u32, value: u8, count: u32) { | |
ptr::write_bytes(mem8.offset(addr as isize), value, count as usize); | |
} | |
pub unsafe fn memcpy_no_mmap_or_dirty_check(src_addr: u32, dst_addr: u32, count: u32) { | |
dbg_assert!(src_addr < *memory_size); | |
dbg_assert!(dst_addr < *memory_size); | |
ptr::copy( | |
mem8.offset(src_addr as isize), | |
mem8.offset(dst_addr as isize), | |
count as usize, | |
) | |
} | |
pub unsafe fn memcpy_into_svga_lfb(src_addr: u32, dst_addr: u32, count: u32) { | |
dbg_assert!(src_addr < *memory_size); | |
dbg_assert!(in_svga_lfb(dst_addr)); | |
dbg_assert!(Page::page_of(dst_addr) == Page::page_of(dst_addr + count - 1)); | |
vga::mark_dirty(dst_addr); | |
ptr::copy_nonoverlapping( | |
mem8.offset(src_addr as isize), | |
vga_mem8.offset((dst_addr - VGA_LFB_ADDRESS) as isize), | |
count as usize, | |
) | |
} | |
pub unsafe fn mmap_write8(addr: u32, value: i32) { | |
if in_svga_lfb(addr) { | |
vga::mark_dirty(addr); | |
*vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) = value as u8 | |
} | |
else { | |
ext::mmap_write8(addr, value) | |
} | |
} | |
pub unsafe fn mmap_write16(addr: u32, value: i32) { | |
if in_svga_lfb(addr) { | |
vga::mark_dirty(addr); | |
ptr::write_unaligned( | |
vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *mut u16, | |
value as u16, | |
) | |
} | |
else { | |
ext::mmap_write16(addr, value) | |
} | |
} | |
pub unsafe fn mmap_write32(addr: u32, value: i32) { | |
if in_svga_lfb(addr) { | |
vga::mark_dirty(addr); | |
ptr::write_unaligned( | |
vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *mut i32, | |
value, | |
) | |
} | |
else if addr >= APIC_MEM_ADDRESS && addr < APIC_MEM_ADDRESS + APIC_MEM_SIZE { | |
apic::write32(addr - APIC_MEM_ADDRESS, value as u32); | |
handle_irqs(); | |
} | |
else if addr >= IOAPIC_MEM_ADDRESS && addr < IOAPIC_MEM_ADDRESS + IOAPIC_MEM_SIZE { | |
ioapic::write32(addr - IOAPIC_MEM_ADDRESS, value as u32); | |
handle_irqs(); | |
} | |
else { | |
ext::mmap_write32(addr, value) | |
} | |
} | |
pub unsafe fn mmap_write64(addr: u32, value: u64) { | |
if in_svga_lfb(addr) { | |
vga::mark_dirty(addr); | |
ptr::write_unaligned( | |
vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *mut u64, | |
value, | |
) | |
} | |
else { | |
ext::mmap_write64(addr, value as i32, (value >> 32) as i32) | |
} | |
} | |
pub unsafe fn mmap_write128(addr: u32, v0: u64, v1: u64) { | |
if in_svga_lfb(addr) { | |
vga::mark_dirty(addr); | |
ptr::write_unaligned( | |
vga_mem8.offset((addr - VGA_LFB_ADDRESS) as isize) as *mut u64, | |
v0, | |
); | |
ptr::write_unaligned( | |
vga_mem8.offset((addr - VGA_LFB_ADDRESS + 8) as isize) as *mut u64, | |
v1, | |
) | |
} | |
else { | |
ext::mmap_write128( | |
addr, | |
v0 as i32, | |
(v0 >> 32) as i32, | |
v1 as i32, | |
(v1 >> 32) as i32, | |
) | |
} | |
} | |
pub unsafe fn is_memory_zeroed(addr: u32, length: u32) -> bool { | |
dbg_assert!(addr % 8 == 0); | |
dbg_assert!(length % 8 == 0); | |
for i in (addr..addr + length).step_by(8) { | |
if *(mem8.offset(i as isize) as *const i64) != 0 { | |
return false; | |
} | |
} | |
return true; | |
} | |