use crate::simulator::translationtable::*; use crate::simulator::machine::*; pub struct MMU <'a>{ /* Un MMU possède une seule référence vers une table des pages à un instant donné * Cette table est associée au processus courant * Cette référence peut etre mise a jour par exemple lors d'un switchTo */ translationTable : Option<&'a mut TranslationTable> } impl <'a>MMU <'_>{ fn create() -> MMU <'a>{ MMU{ translationTable : None } } pub fn mmu_read_mem(mmu : &mut MMU, machine : &mut Machine, virt_addr : u64, value : &mut u64, size : i32) -> bool { //Pour plus tard eventuellement considerer le boutisme de notre mémoire //Peut etre pas si on fixe cela en BIG ENDIAN (octects poids fort au debut) let mut phy_addr : u64 = 0; let mut phy_addr_double_check : u64 = 0; let exc = MMU::translate(mmu, virt_addr, &mut phy_addr, false); MMU::translate(mmu, virt_addr, &mut phy_addr_double_check, false); match exc { ExceptionType::NoException => { if phy_addr != phy_addr_double_check { //Besoin ici d'une impl pour gestion d'exeption //dans nachos : g-machine->RaiseException(exc, virt_addr); println!("Error from mmu_read_mem :: phy_addr != phy_addr_double_check"); return false; } else { *value = Machine::read_memory(machine, size, phy_addr as usize); return true; } } _ => { //Besoin ici d'une impl pour gestion d'exeption //dans nachos : g-machine->RaiseException(exc, virt_addr); println!("Error from mmu_read_mem :: Exception different from NoException"); return false; } } true } pub fn mmu_write_mem(mmu : &mut MMU, machine : &mut Machine, virt_addr : u64, value : u64, size : i32) -> bool { //Pour plus tard eventuellement considerer le boutisme de notre mémoire //Peut etre pas si on fixe cela en BIG ENDIAN (octects poids fort au debut) let mut phy_addr : u64 = 0; let mut phy_addr_double_check : u64 = 0; let exc = MMU::translate(mmu, virt_addr, &mut phy_addr, true); MMU::translate(mmu, virt_addr, &mut phy_addr_double_check, true); match exc { ExceptionType::NoException => { if phy_addr != phy_addr_double_check { //Besoin ici d'une impl pour gestion d'exeption //dans nachos : g-machine->RaiseException(exc, virt_addr); println!("Error from mmu_write_mem :: phy_addr != phy_addr_double_check"); return false; } else { Machine::write_memory(machine, size, phy_addr as usize, value); return true; } } _ => { //Besoin ici d'une impl pour gestion d'exeption //dans nachos : g-machine->RaiseException(exc, virt_addr); println!("Error from mmu_write_mem :: Exception different from NoException"); return false; } } true } pub fn translate(mmu : &mut MMU, virtAddr : u64, physAddr : &mut u64, writing : bool) -> ExceptionType { let vpn : u64 = virtAddr/PAGE_SIZE; //virtual page index let offset : u64 = virtAddr%PAGE_SIZE; //adresse intra page match &mut mmu.translationTable { None => { println!("Error from translate : MMU refers to None (No page Table)"); return ExceptionType::AddressErrorException; } Some(table_ref) => { //On verifie que notre index est valide if vpn >= table_ref.get_max_num_pages(){ println!("Error from translate :: index is out of bound"); return ExceptionType::AddressErrorException; } /*Doc nachos dit que ce test sert a savoir si la page est mappée *On teste les droit de lecture ecriture sur cette page *A confirmer avc isabelle */ if !table_ref.get_bit_read(vpn) && !table_ref.get_bit_write(vpn) { println!("Error from translate :: virtual page # {} not mapped",vpn); return ExceptionType::AddressErrorException; } //si on souhaite effectuer un acces lecture, on verifie que l'on dispose du droit d'acces sur cette page if writing && !table_ref.get_bit_write(vpn) { println!("Error from translate :: write access on a read only virtual page # {}",vpn); return ExceptionType::AddressErrorException; } //if the page is not yet in main memory, run the page fault manager //Page manager not implemented yet if !table_ref.get_bit_valid(vpn){ println!("Error from translate :: no valid correspondance"); println!("We need to update the page table by raising an exception -> not implemented"); //Ici il faudra reverifier le bit valid apres intervention du page fault manager return ExceptionType::AddressErrorException; } //Make sure that the physical adress is correct if table_ref.get_physical_page(vpn) < 0 || table_ref.get_physical_page(vpn) >= (NUM_PHY_PAGE as i32) { println!("Error from translate :: no valid correspondance"); return ExceptionType::BusErrorException; } //Set U/M bits to 1 if writing { table_ref.set_bit_M(vpn); } table_ref.set_bit_U(vpn); //on se permet ici la conversion du champs physical_page de i32 vers u64 //si cette valeur avait été signée, cela aurait été detecté juste au dessus, renvoyant une BUSERROR_EXCEPTION *physAddr = (table_ref.get_physical_page(vpn) as u64)*PAGE_SIZE + offset; } } ExceptionType::NoException } }