use serde::{Deserialize, Serialize}; use crate::{ memory::{mainstore::RandomAccessMemory, mmu::MMU}, processor::processor::Emulator, }; mod cache; pub mod mainstore; pub mod mmu; mod tlb; pub type VirtAddr = u32; pub type PhysAddr = u32; pub enum FaultInfo { PageFault, } #[repr(u32)] #[derive(Serialize, Deserialize, Clone, Copy, Debug)] enum RegionType { Reserved, Bootloader, Kernel, KernelTables, Usable, MMIO, } #[derive(Serialize, Deserialize, Debug, Clone, Copy)] pub struct Region { base: PhysAddr, size: u32, region_type: RegionType, // flags for the emulator #[serde(default)] identity_map_on_boot: bool, } #[derive(Serialize, Deserialize, Debug, Clone)] pub struct MemoryMap { table_addr: PhysAddr, pub regions: Vec, } impl MemoryMap { pub const DEFAULT_MEMORY_MAP_ADDR: PhysAddr = 0x1000; pub fn new() -> Self { MemoryMap { table_addr: Self::DEFAULT_MEMORY_MAP_ADDR, regions: Vec::new(), } } pub fn apply(&self, cpu: &mut Emulator) { for reg in &self.regions { if reg.identity_map_on_boot { Self::identity_map(cpu.mmu_mut(), reg); } } let mem = cpu.memory_mut(); let mut offset = self.table_addr; for region in &self.regions { println!("Wrote entry: {region:?} to page table"); mem.write_word(offset, region.base); mem.write_word(offset + 4, region.size); mem.write_word(offset + 8, region.region_type as u32); offset += 12; } } pub fn identity_map(mmu: &mut MMU, region: &Region) { let first_page = region.base >> 12; let page_count = (region.size >> 12); for page in (first_page..first_page + page_count).map(|p| p << 12) { mmu.create_mapping(page, page); } } } impl Default for MemoryMap { fn default() -> Self { ron::from_str(include_str!("../config/dsa.mmap.default.ron")).unwrap() } }