From 3391d3cb65ad2a1165a9b508f5d9a8a83567178d Mon Sep 17 00:00:00 2001 From: Moysan Gabriel Date: Mon, 13 Mar 2023 22:52:27 +0100 Subject: [PATCH] impl translation table + debut impl mmu --- src/simulator/machine.rs | 2 + src/simulator/mmu.rs | 50 +++++++++++ src/simulator/mod.rs | 2 + src/simulator/translationtable.rs | 145 ++++++++++++++++++++++++++---- 4 files changed, 184 insertions(+), 15 deletions(-) diff --git a/src/simulator/machine.rs b/src/simulator/machine.rs index c8ac6fd..9177d48 100644 --- a/src/simulator/machine.rs +++ b/src/simulator/machine.rs @@ -36,6 +36,8 @@ pub const NUM_FP_REGS: usize = 32; /// doit disparaitre const MEM_SIZE : usize = 0x500000; +//doit etre une puissance de deux +pub const PAGE_SIZE : u64 = 128; pub trait RegisterNum: Add + Sub + PartialEq + Copy {} diff --git a/src/simulator/mmu.rs b/src/simulator/mmu.rs index e69de29..5ad8d36 100644 --- a/src/simulator/mmu.rs +++ b/src/simulator/mmu.rs @@ -0,0 +1,50 @@ +use crate::simulator::translationtable::*; +use crate::simulator::machine::*; + +use super::machine::ExceptionType; + +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 + } + } + + fn translate(mmu : &mut MMU, virtAddr : u64, physAddr : &mut u64, size : usize, writing : bool) -> ExceptionType { + + let virtual_page_index : u64 = virtAddr/PAGE_SIZE; + let offset : u64 = virtAddr%PAGE_SIZE; + + + + match &mmu.translationTable { + None => { + println!("Error from translate : MMU refers to None (No page Table)"); + return ExceptionType::ADDRESSERROR_EXCEPTION; + } + + Some(table_ref) => { + + //On verifie que notre index est valide + if virtual_page_index >= table_ref.get_max_num_pages(){ + + } + + //is the page correctyl mapped ? + //if table_ref.pageTable.get + } + } + + ExceptionType::NO_EXCEPTION + } + } \ No newline at end of file diff --git a/src/simulator/mod.rs b/src/simulator/mod.rs index 85a7d51..8626048 100644 --- a/src/simulator/mod.rs +++ b/src/simulator/mod.rs @@ -4,6 +4,8 @@ pub mod print; pub mod mem_cmp; pub mod loader; pub mod interrupt; +pub mod translationtable; +pub mod mmu; pub mod global { diff --git a/src/simulator/translationtable.rs b/src/simulator/translationtable.rs index d0d8fc2..f0d7091 100644 --- a/src/simulator/translationtable.rs +++ b/src/simulator/translationtable.rs @@ -4,26 +4,141 @@ const MaxVirtPages : u64 = 200000; /* Une table de correspondance propre à un processus +* Une variable de type TranslationTable devra etre possédée par un objet de type Process */ -struct TranslationTable{ +pub struct TranslationTable{ //capacité de cette table <=> nombre de correspondances possibles - maxNumPages : u64, + //A voir si cette donnée doit etre immuable + pub maxNumPages : u64, //la table en question //Vec implemente le trait Index, donc un bon choix - pageTable : Vec + pub pageTable : Vec } impl TranslationTable { - fn create() -> TranslationTable { + pub fn create() -> TranslationTable { + + let mut tmp_vec : Vec = Vec::new(); + + for i in 0..MaxVirtPages { + tmp_vec.push(PageTableEntry::create()); + } TranslationTable{ maxNumPages : MaxVirtPages, - page + pageTable : tmp_vec } } + //vpn = virtual page number, c'est un index dans la table des page + //Assert a mettre dans chacune des fonctions suivantes + + pub fn get_max_num_pages(&self) -> u64{ + return self.maxNumPages; + } + + pub fn set_physical_page(&mut self, vpn : u64, physical_page : i32){ + self.pageTable[vpn as usize].physical_page = physical_page; + } + + pub fn get_physical_page(&self, vpn : u64) -> i32{ + self.pageTable[vpn as usize].physical_page + } + + pub fn set_addr_disk(&mut self, vpn : u64, addr_disk : i32){ + self.pageTable[vpn as usize].addr_disk = addr_disk; + } + + pub fn get_addr_disk(&self, vpn : u64) -> i32 { + self.pageTable[vpn as usize].addr_disk + } + + pub fn set_bit_valid(&mut self, vpn : u64){ + self.pageTable[vpn as usize].valid = true; + } + + pub fn clear_bit_valid(&mut self, vpn : u64){ + self.pageTable[vpn as usize].valid = false; + } + + pub fn get_bit_valid(&self, vpn : u64) -> bool{ + self.pageTable[vpn as usize].valid + } + + pub fn set_bit_io(&mut self, vpn : u64){ + self.pageTable[vpn as usize].io = true; + } + + pub fn clear_bit_io(&mut self, vpn : u64){ + self.pageTable[vpn as usize].io = false; + } + + pub fn get_bit_io(&self, vpn : u64) -> bool{ + self.pageTable[vpn as usize].io + } + + pub fn set_bit_swap(&mut self, vpn : u64){ + self.pageTable[vpn as usize].swap = true; + } + + pub fn clear_bit_swap(&mut self, vpn : u64){ + self.pageTable[vpn as usize].swap = false; + } + + pub fn get_bit_swap(&self, vpn : u64) -> bool{ + self.pageTable[vpn as usize].swap + } + + pub fn set_bit_write(&mut self, vpn : u64){ + self.pageTable[vpn as usize].write_allowed = true; + } + + pub fn clear_bit_write(&mut self, vpn : u64){ + self.pageTable[vpn as usize].write_allowed = false; + } + + pub fn get_bit_write(&self, vpn : u64) -> bool{ + self.pageTable[vpn as usize].write_allowed + } + + pub fn set_bit_read(&mut self, vpn : u64){ + self.pageTable[vpn as usize].read_allowed = true; + } + + pub fn clear_bit_read(&mut self, vpn : u64){ + self.pageTable[vpn as usize].read_allowed = false; + } + + pub fn get_bit_read(&self, vpn : u64) -> bool{ + self.pageTable[vpn as usize].read_allowed + } + + pub fn set_bit_U(&mut self, vpn : u64){ + self.pageTable[vpn as usize].U = true; + } + + pub fn clear_bit_U(&mut self, vpn : u64){ + self.pageTable[vpn as usize].U = false; + } + + pub fn get_bit_U(&self, vpn : u64) -> bool{ + self.pageTable[vpn as usize].U + } + + pub fn set_bit_M(&mut self, vpn : u64){ + self.pageTable[vpn as usize].M = true; + } + + pub fn clear_bit_M(&mut self, vpn : u64){ + self.pageTable[vpn as usize].M = false; + } + + pub fn get_bit_M(&self, vpn : u64) -> bool{ + self.pageTable[vpn as usize].M + } + } @@ -31,7 +146,7 @@ impl TranslationTable { /* Une correspondance + données sur cette correspondance */ -struct PageTableEntry{ +pub struct PageTableEntry{ //true <=> la correspondance est valide et la page est présente dans la ram valid : bool, @@ -42,17 +157,17 @@ struct PageTableEntry{ M : bool, //droits d'accès sur cette page - readAllowed : bool, - writeAllowed : bool, + read_allowed : bool, + write_allowed : bool, //numero de page physique <=> c'est notre correspondance - physicalPage : i32, + physical_page : i32, //true <=> cette page doit etre chargée depuis la swap zone du disque swap : bool, //a définir plus tard, en relation avec swap - addrDisk : i32, + addr_disk : i32, //mis à 1 par le système quand cette page est impliquée dans une opération d'IO io : bool @@ -61,16 +176,16 @@ struct PageTableEntry{ impl PageTableEntry{ //Default PageTableEntry Constructor - fn create() -> PageTableEntry { + pub fn create() -> PageTableEntry { PageTableEntry { valid : false, U : false, M : false, - readAllowed : false, - writeAllowed : false, - physicalPage : -1i32, + read_allowed : false, + write_allowed : false, + physical_page : -1i32, swap : false, - addrDisk : -1i32, + addr_disk : -1i32, io : false } }