From 95f863c59daa468a43d83b2592a2c17489b28330 Mon Sep 17 00:00:00 2001 From: afrangio Date: Mon, 14 Mar 2022 14:26:08 +0100 Subject: [PATCH 01/19] mem: add page directory and page table Implement also the Get function for each flag/value --- src/memory/mod.rs | 2 + src/memory/pagedirectory.rs | 97 +++++++++++++++++++++++++++++++++ src/memory/pagetable.rs | 106 ++++++++++++++++++++++++++++++++++++ 3 files changed, 205 insertions(+) create mode 100644 src/memory/pagedirectory.rs create mode 100644 src/memory/pagetable.rs diff --git a/src/memory/mod.rs b/src/memory/mod.rs index 3589c21..d20f7f4 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -1,4 +1,6 @@ pub mod pageframe; +mod pagedirectory; +mod pagetable; use core::ffi::c_void; use crate::multiboot::MultibootTagMmap; diff --git a/src/memory/pagedirectory.rs b/src/memory/pagedirectory.rs new file mode 100644 index 0000000..b20b4a4 --- /dev/null +++ b/src/memory/pagedirectory.rs @@ -0,0 +1,97 @@ +pub struct PageDirectoryEntry +{ + pub value: u32 +} + +impl PageDirectoryEntry +{ + // Bits 31-12 represents the address to the PageTableDirectory. + pub fn get_addr(&self) -> u32 + { + self.value >> 12 + } + + // Bits 11-8 are available for us to do whatever we want. + pub fn get_flags(&self) -> u8 + { + ((self.value << 20) >> 28) as u8 + } + + // Bit 7 + // PS, or 'Page Size' stores t-he page size for that specific entry. + // If the bit is set, then the PDE maps to a page that is 4 MiB in size. + // Otherwise, it maps to a 4 KiB page table. Please note that 4-MiB pages + // require PSE to be enabled. In our case, it will be 0. + pub fn get_ps(&self) -> bool + { + ((self.value << 24) >> 31) != 0 + } + + // Bit 6 is available for us to do whatever we want. + pub fn get_flag2(&self) -> bool + { + ((self.value << 25) >> 31) != 0 + } + + // Bit 5 + // 'Accessed' is used to discover whether a PDE or PTE was read during + // virtual address translation. If it has, then the bit is set, otherwise, + // it is not. Note that, this bit will not be cleared by the CPU, + // so that burden falls on the OS (if it needs this bit at all). + pub fn get_accessed(&self) -> bool + { + ((self.value << 26) >> 31) != 0 + } + + // Bit 4 + // PCD, is the 'Cache Disable' bit. If the bit is set, the page will not be + // cached. Otherwise, it will be. + pub fn get_pcd(&self) -> bool + { + ((self.value << 27) >> 31) != 0 + } + + // Bit 3 + // PWT, controls Write-Through' abilities of the page. If the bit is set, + // write-through caching is enabled. If not, then write-back is enabled + // instead. + pub fn get_pwt(&self) -> bool + { + ((self.value << 28) >> 31) != 0 + } + + // Bit 2 + // The 'User/Supervisor' bit, controls access to the page based on privilege + // level. If the bit is set, then the page may be accessed by all; + // if the bit is not set, however, only the supervisor can access it. + // For a page directory entry, the user bit controls access to all the pages + // referenced by the page directory entry. T + // herefore if you wish to make a page a user page, you must set the user + // bit in the relevant page directory entry as well as the page table entry + pub fn get_us(&self) -> bool + { + ((self.value << 29) >> 31) != 0 + } + + // Bit 1 + // The 'Read/Write' permissions flag. If the bit is set, the page is + // read/write. Otherwise when it is not set, the page is read-only. + // The WP bit in CR0 determines if this is only applied to userland, + // always giving the kernel write access (the default) or both userland and + // the kernel (see Intel Manuals 3A 2-20). + pub fn get_rw(&self) -> bool + { + ((self.value << 30) >> 31) != 0 + } + + // Bit 0 + // If the bit is set, the page is actually in physical memory at the moment. + // For example, when a page is swapped out, it is not in physical memory and + // therefore not 'Present'. + // If a page is called, but not present, a page fault will occur, + // and the OS should handle it. + pub fn get_present(&self) -> bool + { + ((self.value << 31) >> 31) != 0 + } +} diff --git a/src/memory/pagetable.rs b/src/memory/pagetable.rs new file mode 100644 index 0000000..aa855ec --- /dev/null +++ b/src/memory/pagetable.rs @@ -0,0 +1,106 @@ +pub struct PageTableEntry +{ + pub value: u32 +} + +impl PageTableEntry +{ + // Bits 31-12 represents the address to the PageTableEntry. + pub fn get_addr(&self) -> u32 + { + self.value >> 12 + } + + // Bits 11-9 are available for us to do whatever we want. + pub fn get_flags(&self) -> u8 + { + ((self.value << 20) >> 29) as u8 + } + + // Bit 8 + // Global tells the processor not to invalidate the TLB entry corresponding + // to the page upon a MOV to CR3 instruction. Bit 7 (PGE) in CR4 must be set + // to enable global pages. + pub fn get_global(&self) -> bool + { + ((self.value << 23) >> 31) != 0 + } + + // Bit 7 + // PAT, or Page Attribute Table. If PAT is supported, then PAT along with + // PCD and PWT shall indicate the memory caching type. Otherwise, + // it is reserved and must be set to 0. + pub fn get_pat(&self) -> bool + { + ((self.value << 24) >> 31) != 0 + } + + // Bit 6 + // 'Dirty' is used to determine whether a page has been written to. + pub fn get_dirty(&self) -> bool + { + ((self.value << 25) >> 31) != 0 + } + + // Bit 5 + // 'Accessed' is used to discover whether a PDE or PTE was read during + // virtual address translation. If it has, then the bit is set, otherwise, + // it is not. Note that, this bit will not be cleared by the CPU, + // so that burden falls on the OS (if it needs this bit at all). + pub fn get_accessed(&self) -> bool + { + ((self.value << 26) >> 31) != 0 + } + + // Bit 4 + // PCD, is the 'Cache Disable' bit. If the bit is set, the page will not be + // cached. Otherwise, it will be. + pub fn get_pcd(&self) -> bool + { + ((self.value << 27) >> 31) != 0 + } + + // Bit 3 + // PWT, controls Write-Through' abilities of the page. If the bit is set, + // write-through caching is enabled. If not, then write-back is enabled + // instead. + pub fn get_pwt(&self) -> bool + { + ((self.value << 28) >> 31) != 0 + } + + // Bit 2 + // The 'User/Supervisor' bit, controls access to the page based on privilege + // level. If the bit is set, then the page may be accessed by all; + // if the bit is not set, however, only the supervisor can access it. + // For a page directory entry, the user bit controls access to all the pages + // referenced by the page directory entry. T + // herefore if you wish to make a page a user page, you must set the user + // bit in the relevant page directory entry as well as the page table entry + pub fn get_us(&self) -> bool + { + ((self.value << 29) >> 31) != 0 + } + + // Bit 1 + // The 'Read/Write' permissions flag. If the bit is set, the page is + // read/write. Otherwise when it is not set, the page is read-only. + // The WP bit in CR0 determines if this is only applied to userland, + // always giving the kernel write access (the default) or both userland and + // the kernel (see Intel Manuals 3A 2-20). + pub fn get_rw(&self) -> bool + { + ((self.value << 30) >> 31) != 0 + } + + // Bit 0 + // If the bit is set, the page is actually in physical memory at the moment. + // For example, when a page is swapped out, it is not in physical memory and + // therefore not 'Present'. + // If a page is called, but not present, a page fault will occur, + // and the OS should handle it. + pub fn get_present(&self) -> bool + { + ((self.value << 31) >> 31) != 0 + } +} From 726e7e9e4c39c9ae639dc4ee208040f3ff2f12ec Mon Sep 17 00:00:00 2001 From: Angelo FRANGIONE Date: Mon, 14 Mar 2022 16:46:25 +0100 Subject: [PATCH 02/19] mem: add debug trait to PD and PT --- src/memory/pagedirectory.rs | 19 +++++++++++++++++++ src/memory/pagetable.rs | 20 ++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/memory/pagedirectory.rs b/src/memory/pagedirectory.rs index b20b4a4..10e7acb 100644 --- a/src/memory/pagedirectory.rs +++ b/src/memory/pagedirectory.rs @@ -3,6 +3,25 @@ pub struct PageDirectoryEntry pub value: u32 } +impl core::fmt::Debug for PageDirectoryEntry +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result + { + f.debug_struct("PageDirectoryEntry") + .field("addr", &self.get_addr()) + .field("flags", &self.get_flags()) + .field("ps", &self.get_ps()) + .field("flag2", &self.get_flag2()) + .field("accessed", &self.get_accessed()) + .field("pcd", &self.get_pcd()) + .field("pwt", &self.get_pwt()) + .field("us", &self.get_us()) + .field("rw", &self.get_rw()) + .field("present", &self.get_present()) + .finish() + } +} + impl PageDirectoryEntry { // Bits 31-12 represents the address to the PageTableDirectory. diff --git a/src/memory/pagetable.rs b/src/memory/pagetable.rs index aa855ec..9be3cd7 100644 --- a/src/memory/pagetable.rs +++ b/src/memory/pagetable.rs @@ -3,6 +3,26 @@ pub struct PageTableEntry pub value: u32 } +impl core::fmt::Debug for PageTableEntry +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result + { + f.debug_struct("PageDirectoryEntry") + .field("addr", &self.get_addr()) + .field("flags", &self.get_flags()) + .field("global", &self.get_global()) + .field("pat", &self.get_pat()) + .field("dirty", &self.get_dirty()) + .field("accessed", &self.get_accessed()) + .field("pcd", &self.get_pcd()) + .field("pwt", &self.get_pwt()) + .field("us", &self.get_us()) + .field("rw", &self.get_rw()) + .field("present", &self.get_present()) + .finish() + } +} + impl PageTableEntry { // Bits 31-12 represents the address to the PageTableEntry. From 967225189c50f554341d7c3bb254db566a5ae3c8 Mon Sep 17 00:00:00 2001 From: Angelo FRANGIONE Date: Mon, 14 Mar 2022 16:47:52 +0100 Subject: [PATCH 03/19] mem: add setter functions to the PD and PT --- src/memory/pagedirectory.rs | 47 +++++++++++++++++++++++++++++++- src/memory/pagetable.rs | 53 +++++++++++++++++++++++++++++++++++-- src/tools.rs | 12 +++++++++ 3 files changed, 109 insertions(+), 3 deletions(-) diff --git a/src/memory/pagedirectory.rs b/src/memory/pagedirectory.rs index 10e7acb..865df47 100644 --- a/src/memory/pagedirectory.rs +++ b/src/memory/pagedirectory.rs @@ -1,3 +1,5 @@ +use crate::tools; + pub struct PageDirectoryEntry { pub value: u32 @@ -29,12 +31,22 @@ impl PageDirectoryEntry { self.value >> 12 } + pub fn set_addr(&mut self, addr: u32) + { + self.value &= 0xfff; + self.value |= addr; + } // Bits 11-8 are available for us to do whatever we want. pub fn get_flags(&self) -> u8 { ((self.value << 20) >> 28) as u8 } + pub fn set_flags(&mut self, flags: u8) + { + self.value &= 0xffff_f0ff; + self.value |= (flags as u32) << 8; + } // Bit 7 // PS, or 'Page Size' stores t-he page size for that specific entry. @@ -45,12 +57,21 @@ impl PageDirectoryEntry { ((self.value << 24) >> 31) != 0 } + pub fn set_ps(&mut self, value: bool) + { + tools::set_bit(&mut self.value, value, 7); + } + // Bit 6 is available for us to do whatever we want. pub fn get_flag2(&self) -> bool { ((self.value << 25) >> 31) != 0 } + pub fn set_flag2(&mut self, value: bool) + { + tools::set_bit(&mut self.value, value, 6); + } // Bit 5 // 'Accessed' is used to discover whether a PDE or PTE was read during @@ -61,6 +82,10 @@ impl PageDirectoryEntry { ((self.value << 26) >> 31) != 0 } + pub fn set_accessed(&mut self, value: bool) + { + tools::set_bit(&mut self.value, value, 5); + } // Bit 4 // PCD, is the 'Cache Disable' bit. If the bit is set, the page will not be @@ -69,6 +94,10 @@ impl PageDirectoryEntry { ((self.value << 27) >> 31) != 0 } + pub fn set_pcd(&mut self, value: bool) + { + tools::set_bit(&mut self.value, value, 4); + } // Bit 3 // PWT, controls Write-Through' abilities of the page. If the bit is set, @@ -76,7 +105,11 @@ impl PageDirectoryEntry // instead. pub fn get_pwt(&self) -> bool { - ((self.value << 28) >> 31) != 0 + ((self.value << 28) >> 31) != 0 + } + pub fn set_pwt(&mut self, value: bool) + { + tools::set_bit(&mut self.value, value, 3); } // Bit 2 @@ -91,6 +124,10 @@ impl PageDirectoryEntry { ((self.value << 29) >> 31) != 0 } + pub fn set_us(&mut self, value: bool) + { + tools::set_bit(&mut self.value, value, 2); + } // Bit 1 // The 'Read/Write' permissions flag. If the bit is set, the page is @@ -102,6 +139,10 @@ impl PageDirectoryEntry { ((self.value << 30) >> 31) != 0 } + pub fn set_rw(&mut self, value: bool) + { + tools::set_bit(&mut self.value, value, 1); + } // Bit 0 // If the bit is set, the page is actually in physical memory at the moment. @@ -113,4 +154,8 @@ impl PageDirectoryEntry { ((self.value << 31) >> 31) != 0 } + pub fn set_present(&mut self, value: bool) + { + tools::set_bit(&mut self.value, value, 0); + } } diff --git a/src/memory/pagetable.rs b/src/memory/pagetable.rs index 9be3cd7..6d5f1fa 100644 --- a/src/memory/pagetable.rs +++ b/src/memory/pagetable.rs @@ -1,3 +1,5 @@ +use crate::tools; + pub struct PageTableEntry { pub value: u32 @@ -31,11 +33,22 @@ impl PageTableEntry self.value >> 12 } + pub fn set_addr(&mut self, addr: u32) + { + self.value &= 0xfff; + self.value |= addr; + } + // Bits 11-9 are available for us to do whatever we want. pub fn get_flags(&self) -> u8 { ((self.value << 20) >> 29) as u8 } + pub fn set_flags(&mut self, flags: u8) + { + self.value &= 0b1111_1111_1111_1111_1111_1000_1111_1111; + self.value |= (flags as u32) << 8; + } // Bit 8 // Global tells the processor not to invalidate the TLB entry corresponding @@ -43,7 +56,11 @@ impl PageTableEntry // to enable global pages. pub fn get_global(&self) -> bool { - ((self.value << 23) >> 31) != 0 + ((self.value << 23) >> 31) != 0 + } + pub fn set_global(&mut self, value: bool) + { + tools::set_bit(&mut self.value, value, 8); } // Bit 7 @@ -54,6 +71,10 @@ impl PageTableEntry { ((self.value << 24) >> 31) != 0 } + pub fn set_pat(&mut self, value: bool) + { + tools::set_bit(&mut self.value, value, 7); + } // Bit 6 // 'Dirty' is used to determine whether a page has been written to. @@ -61,6 +82,10 @@ impl PageTableEntry { ((self.value << 25) >> 31) != 0 } + pub fn set_dirty(&mut self, value: bool) + { + tools::set_bit(&mut self.value, value, 6); + } // Bit 5 // 'Accessed' is used to discover whether a PDE or PTE was read during @@ -69,7 +94,11 @@ impl PageTableEntry // so that burden falls on the OS (if it needs this bit at all). pub fn get_accessed(&self) -> bool { - ((self.value << 26) >> 31) != 0 + ((self.value << 26) >> 31) != 0 + } + pub fn set_accessed(&mut self, value: bool) + { + tools::set_bit(&mut self.value, value, 5); } // Bit 4 @@ -79,6 +108,10 @@ impl PageTableEntry { ((self.value << 27) >> 31) != 0 } + pub fn set_pcd(&mut self, value: bool) + { + tools::set_bit(&mut self.value, value, 4); + } // Bit 3 // PWT, controls Write-Through' abilities of the page. If the bit is set, @@ -88,6 +121,10 @@ impl PageTableEntry { ((self.value << 28) >> 31) != 0 } + pub fn set_pwt(&mut self, value: bool) + { + tools::set_bit(&mut self.value, value, 3); + } // Bit 2 // The 'User/Supervisor' bit, controls access to the page based on privilege @@ -101,6 +138,10 @@ impl PageTableEntry { ((self.value << 29) >> 31) != 0 } + pub fn set_us(&mut self, value: bool) + { + tools::set_bit(&mut self.value, value, 2); + } // Bit 1 // The 'Read/Write' permissions flag. If the bit is set, the page is @@ -112,6 +153,10 @@ impl PageTableEntry { ((self.value << 30) >> 31) != 0 } + pub fn set_rw(&mut self, value: bool) + { + tools::set_bit(&mut self.value, value, 1); + } // Bit 0 // If the bit is set, the page is actually in physical memory at the moment. @@ -123,4 +168,8 @@ impl PageTableEntry { ((self.value << 31) >> 31) != 0 } + pub fn set_present(&mut self, value: bool) + { + tools::set_bit(&mut self.value, value, 0); + } } diff --git a/src/tools.rs b/src/tools.rs index f0c0254..47946c0 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -227,3 +227,15 @@ impl Bitmap } } } + +pub fn set_bit(var: &mut u32, value: bool, bit: u8) +{ + if value + { + *var |= (value as u32) << bit; + } + else + { + *var &= !(!value as u32) << bit; + } +} \ No newline at end of file From 989e249a35b7f12c75d1345cd67e1da8bcc105d9 Mon Sep 17 00:00:00 2001 From: Angelo FRANGIONE Date: Mon, 14 Mar 2022 18:27:47 +0100 Subject: [PATCH 04/19] mem: use get_at_bit function to get bit in PD and PT --- src/memory/pagedirectory.rs | 16 ++++++++-------- src/memory/pagetable.rs | 18 +++++++++--------- src/tools.rs | 4 ++-- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/memory/pagedirectory.rs b/src/memory/pagedirectory.rs index 865df47..bac7e5a 100644 --- a/src/memory/pagedirectory.rs +++ b/src/memory/pagedirectory.rs @@ -55,7 +55,7 @@ impl PageDirectoryEntry // require PSE to be enabled. In our case, it will be 0. pub fn get_ps(&self) -> bool { - ((self.value << 24) >> 31) != 0 + tools::get_bit_at(self.value, 7) } pub fn set_ps(&mut self, value: bool) { @@ -66,7 +66,7 @@ impl PageDirectoryEntry // Bit 6 is available for us to do whatever we want. pub fn get_flag2(&self) -> bool { - ((self.value << 25) >> 31) != 0 + tools::get_bit_at(self.value, 6) } pub fn set_flag2(&mut self, value: bool) { @@ -80,7 +80,7 @@ impl PageDirectoryEntry // so that burden falls on the OS (if it needs this bit at all). pub fn get_accessed(&self) -> bool { - ((self.value << 26) >> 31) != 0 + tools::get_bit_at(self.value, 5) } pub fn set_accessed(&mut self, value: bool) { @@ -92,7 +92,7 @@ impl PageDirectoryEntry // cached. Otherwise, it will be. pub fn get_pcd(&self) -> bool { - ((self.value << 27) >> 31) != 0 + tools::get_bit_at(self.value, 4) } pub fn set_pcd(&mut self, value: bool) { @@ -105,7 +105,7 @@ impl PageDirectoryEntry // instead. pub fn get_pwt(&self) -> bool { - ((self.value << 28) >> 31) != 0 + tools::get_bit_at(self.value, 3) } pub fn set_pwt(&mut self, value: bool) { @@ -122,7 +122,7 @@ impl PageDirectoryEntry // bit in the relevant page directory entry as well as the page table entry pub fn get_us(&self) -> bool { - ((self.value << 29) >> 31) != 0 + tools::get_bit_at(self.value, 2) } pub fn set_us(&mut self, value: bool) { @@ -137,7 +137,7 @@ impl PageDirectoryEntry // the kernel (see Intel Manuals 3A 2-20). pub fn get_rw(&self) -> bool { - ((self.value << 30) >> 31) != 0 + tools::get_bit_at(self.value, 1) } pub fn set_rw(&mut self, value: bool) { @@ -152,7 +152,7 @@ impl PageDirectoryEntry // and the OS should handle it. pub fn get_present(&self) -> bool { - ((self.value << 31) >> 31) != 0 + tools::get_bit_at(self.value, 0) } pub fn set_present(&mut self, value: bool) { diff --git a/src/memory/pagetable.rs b/src/memory/pagetable.rs index 6d5f1fa..0e7b236 100644 --- a/src/memory/pagetable.rs +++ b/src/memory/pagetable.rs @@ -56,7 +56,7 @@ impl PageTableEntry // to enable global pages. pub fn get_global(&self) -> bool { - ((self.value << 23) >> 31) != 0 + tools::get_bit_at(self.value, 8) } pub fn set_global(&mut self, value: bool) { @@ -69,7 +69,7 @@ impl PageTableEntry // it is reserved and must be set to 0. pub fn get_pat(&self) -> bool { - ((self.value << 24) >> 31) != 0 + tools::get_bit_at(self.value, 7) } pub fn set_pat(&mut self, value: bool) { @@ -80,7 +80,7 @@ impl PageTableEntry // 'Dirty' is used to determine whether a page has been written to. pub fn get_dirty(&self) -> bool { - ((self.value << 25) >> 31) != 0 + tools::get_bit_at(self.value, 6) } pub fn set_dirty(&mut self, value: bool) { @@ -94,7 +94,7 @@ impl PageTableEntry // so that burden falls on the OS (if it needs this bit at all). pub fn get_accessed(&self) -> bool { - ((self.value << 26) >> 31) != 0 + tools::get_bit_at(self.value, 5) } pub fn set_accessed(&mut self, value: bool) { @@ -106,7 +106,7 @@ impl PageTableEntry // cached. Otherwise, it will be. pub fn get_pcd(&self) -> bool { - ((self.value << 27) >> 31) != 0 + tools::get_bit_at(self.value, 4) } pub fn set_pcd(&mut self, value: bool) { @@ -119,7 +119,7 @@ impl PageTableEntry // instead. pub fn get_pwt(&self) -> bool { - ((self.value << 28) >> 31) != 0 + tools::get_bit_at(self.value, 3) } pub fn set_pwt(&mut self, value: bool) { @@ -136,7 +136,7 @@ impl PageTableEntry // bit in the relevant page directory entry as well as the page table entry pub fn get_us(&self) -> bool { - ((self.value << 29) >> 31) != 0 + tools::get_bit_at(self.value, 2) } pub fn set_us(&mut self, value: bool) { @@ -151,7 +151,7 @@ impl PageTableEntry // the kernel (see Intel Manuals 3A 2-20). pub fn get_rw(&self) -> bool { - ((self.value << 30) >> 31) != 0 + tools::get_bit_at(self.value, 1) } pub fn set_rw(&mut self, value: bool) { @@ -166,7 +166,7 @@ impl PageTableEntry // and the OS should handle it. pub fn get_present(&self) -> bool { - ((self.value << 31) >> 31) != 0 + tools::get_bit_at(self.value, 0) } pub fn set_present(&mut self, value: bool) { diff --git a/src/tools.rs b/src/tools.rs index 47946c0..42f4ed1 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -38,9 +38,9 @@ pub fn outb(port: u32, value: u8) } } -pub fn get_bit_at(input: u8, n: u8) -> bool +pub fn get_bit_at(input: u32, n: u8) -> bool { - if n < 8 + if n < 32 { return input & (1 << n) != 0; } From a90315e81fd0f76f132a46ff09ddbd881ffb3fda Mon Sep 17 00:00:00 2001 From: afrangio Date: Tue, 15 Mar 2022 14:11:23 +0100 Subject: [PATCH 05/19] mem: add value to the debug fields for PD and PT --- src/memory/pagedirectory.rs | 1 + src/memory/pagetable.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/memory/pagedirectory.rs b/src/memory/pagedirectory.rs index bac7e5a..e08375c 100644 --- a/src/memory/pagedirectory.rs +++ b/src/memory/pagedirectory.rs @@ -10,6 +10,7 @@ impl core::fmt::Debug for PageDirectoryEntry fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("PageDirectoryEntry") + .field("value", &self.value) .field("addr", &self.get_addr()) .field("flags", &self.get_flags()) .field("ps", &self.get_ps()) diff --git a/src/memory/pagetable.rs b/src/memory/pagetable.rs index 0e7b236..aa15ff8 100644 --- a/src/memory/pagetable.rs +++ b/src/memory/pagetable.rs @@ -10,6 +10,7 @@ impl core::fmt::Debug for PageTableEntry fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("PageDirectoryEntry") + .field("value", &self.value) .field("addr", &self.get_addr()) .field("flags", &self.get_flags()) .field("global", &self.get_global()) From 9928ed048f1ca0550122c5bb99f59ced944efcfc Mon Sep 17 00:00:00 2001 From: afrangio Date: Tue, 15 Mar 2022 14:15:14 +0100 Subject: [PATCH 06/19] mem: add PD and PT initialisation --- src/elsos.rs | 3 +-- src/memory/mod.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/elsos.rs b/src/elsos.rs index a622959..5ccfd2d 100644 --- a/src/elsos.rs +++ b/src/elsos.rs @@ -44,8 +44,7 @@ pub extern "C" fn kernel_main(magic: u32, address: u32) vga::cursor::Cursor::init(0, 15); if multiboot::check_magic(magic) && multiboot::parse(address) { - let mut alloc: memory::pageframe::Allocator = memory::pageframe::Allocator::new(); - unsafe { alloc.read_grub_mmap(MULTIBOOT_MMAP, MULTIBOOT_MMAP_ENTRIES); } + unsafe { crate::memory::init(MULTIBOOT_MMAP, MULTIBOOT_MMAP_ENTRIES); } init_serial(); logln!("\n"); logln!(" ::: :::::::: __ __ __ _ ____ ____ "); diff --git a/src/memory/mod.rs b/src/memory/mod.rs index d20f7f4..37a6e86 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -50,3 +50,34 @@ pub fn get_largest_mem_seg(mmap: *const MultibootTagMmap, mmap_size: usize) -> u } largest_free_mem_seg } + +pub fn init(mmap: *const MultibootTagMmap, mmap_size: usize) +{ + let pd_ptr: usize; + let pt1_ptr: usize; + let mut alloc: pageframe::Allocator = pageframe::Allocator::new(); + + alloc.read_grub_mmap(mmap, mmap_size); + pd_ptr = alloc.request_free_page(); + pt1_ptr = alloc.request_free_page(); + create_pd(pd_ptr, pt1_ptr); +} + +fn create_pd(addr: usize, pt1_addr: usize) +{ + let pd: &'static mut [pagedirectory::PageDirectoryEntry]; + let pt1: &'static mut [pagetable::PageTableEntry]; + + pd = unsafe{ core::slice::from_raw_parts_mut(addr as *mut pagedirectory::PageDirectoryEntry, 1024) }; + pt1 = unsafe{ core::slice::from_raw_parts_mut(pt1_addr as *mut pagetable::PageTableEntry, 1024) }; + for d in &mut *pd + { + d.value = 0x00000002; + } + for (i, t) in &mut (*pt1).iter_mut().enumerate() + { + t.value = ((i * 0x1000) | 3) as u32; + } + pd[0].set_addr(pt1_addr as u32); + crate::logln!("\x1b[31m{:#x?}\x1b[39m", pt1[0]); +} \ No newline at end of file From b94b7aae90640983c1be964c7f3a5be926dfcfba Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Tue, 15 Mar 2022 14:51:48 +0100 Subject: [PATCH 07/19] tools: add align function --- src/memory/pageframe.rs | 4 ++-- src/multiboot.rs | 2 +- src/tools.rs | 7 ++++++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index 772f045..df09958 100644 --- a/src/memory/pageframe.rs +++ b/src/memory/pageframe.rs @@ -56,7 +56,7 @@ impl Allocator self.reserved_mem = crate::memory::get_mem_size(mmap, mmap_size); crate::logln!("[INFO] found {}KiB of memory", self.reserved_mem / 1024); // initialise the bitmap according to mem size, and set every page as reserved - self.init_bitmap(kernel_end); + self.init_bitmap(tools::align(kernel_end, 0x1000)); crate::logln!("[INFO] assigned {} pages to bitmap", self.bitmap.size); unsafe { @@ -74,7 +74,7 @@ impl Allocator crate::logln!("reserving {} pages for kernel", page_index!(kernel_end - kernel_start)); self.reserve_mem(page_index!(kernel_start), page_index!(kernel_end - kernel_start)); crate::logln!("kernel end {:#x}", kernel_end); - crate::logln!("memory start {:#x}", kernel_end + self.bitmap.size / 8); + crate::logln!("memory start {:#x}", (self.bitmap.buffer as *const _ as *const usize as usize) + self.bitmap.buffer.len()); // reserve bitmap crate::logln!("reserving {} pages for bitmap", page_index!(self.bitmap.size / 8)); self.reserve_mem(page_index!(kernel_end), page_index!(self.bitmap.size / 8)); diff --git a/src/multiboot.rs b/src/multiboot.rs index c85b0bb..28fd276 100644 --- a/src/multiboot.rs +++ b/src/multiboot.rs @@ -248,7 +248,7 @@ pub fn parse(address: u32) -> bool _ => {}//crate::println!("found tag of type {} and size {}", type_name((*tag).tag_type), (*tag).size) }; - address += ((*tag).size + 7) & !7; + address += tools::align((*tag).size as usize, 8) as u32; } } diff --git a/src/tools.rs b/src/tools.rs index 42f4ed1..474f41b 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -238,4 +238,9 @@ pub fn set_bit(var: &mut u32, value: bool, bit: u8) { *var &= !(!value as u32) << bit; } -} \ No newline at end of file +} + +pub fn align(val: usize, bound: usize) -> usize +{ + val + bound - 1 & !(bound - 1) +} From 7929e3f6ca672191c04e70b8c8336f947789ec54 Mon Sep 17 00:00:00 2001 From: Angelo FRANGIONE Date: Tue, 15 Mar 2022 15:16:08 +0100 Subject: [PATCH 08/19] tools: rename to ferramenta ferramenta aka hardware store is a store in italy were you can find everything. --- src/elsos.rs | 2 +- src/{tools.rs => ferramenta.rs} | 2 +- src/keyboard/mod.rs | 4 ++-- src/memory/pagedirectory.rs | 34 ++++++++++++++--------------- src/memory/pageframe.rs | 10 ++++----- src/memory/pagetable.rs | 38 ++++++++++++++++----------------- src/multiboot.rs | 6 +++--- src/serial.rs | 2 +- src/tty/basic_commands.rs | 10 ++++----- src/vga/cursor.rs | 2 +- 10 files changed, 55 insertions(+), 55 deletions(-) rename src/{tools.rs => ferramenta.rs} (99%) diff --git a/src/elsos.rs b/src/elsos.rs index 5ccfd2d..5dfaafc 100644 --- a/src/elsos.rs +++ b/src/elsos.rs @@ -5,7 +5,7 @@ #![no_std] #![no_main] -mod tools; +mod ferramenta; mod vga; mod keyboard; mod tty; diff --git a/src/tools.rs b/src/ferramenta.rs similarity index 99% rename from src/tools.rs rename to src/ferramenta.rs index 474f41b..031ef4d 100644 --- a/src/tools.rs +++ b/src/ferramenta.rs @@ -132,7 +132,7 @@ macro_rules! page_index { ($reg:expr) => {{ - tools::divide_up($reg, 4096) + ferramenta::divide_up($reg, 4096) }} } diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index 56d5bb2..0778487 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -1,5 +1,5 @@ use crate::tty; -use crate::tools; +use crate::ferramenta; mod azerty; mod qwerty; @@ -54,7 +54,7 @@ pub fn get_scancodes() let mut scancode: u8 = 0; loop { - let new_scancode = tools::inb(KEYBOARD_DATA); + let new_scancode = ferramenta::inb(KEYBOARD_DATA); if new_scancode == scancode { diff --git a/src/memory/pagedirectory.rs b/src/memory/pagedirectory.rs index e08375c..e126ecd 100644 --- a/src/memory/pagedirectory.rs +++ b/src/memory/pagedirectory.rs @@ -1,4 +1,4 @@ -use crate::tools; +use crate::ferramenta; pub struct PageDirectoryEntry { @@ -56,22 +56,22 @@ impl PageDirectoryEntry // require PSE to be enabled. In our case, it will be 0. pub fn get_ps(&self) -> bool { - tools::get_bit_at(self.value, 7) + ferramenta::get_bit_at(self.value, 7) } pub fn set_ps(&mut self, value: bool) { - tools::set_bit(&mut self.value, value, 7); + ferramenta::set_bit(&mut self.value, value, 7); } // Bit 6 is available for us to do whatever we want. pub fn get_flag2(&self) -> bool { - tools::get_bit_at(self.value, 6) + ferramenta::get_bit_at(self.value, 6) } pub fn set_flag2(&mut self, value: bool) { - tools::set_bit(&mut self.value, value, 6); + ferramenta::set_bit(&mut self.value, value, 6); } // Bit 5 @@ -81,11 +81,11 @@ impl PageDirectoryEntry // so that burden falls on the OS (if it needs this bit at all). pub fn get_accessed(&self) -> bool { - tools::get_bit_at(self.value, 5) + ferramenta::get_bit_at(self.value, 5) } pub fn set_accessed(&mut self, value: bool) { - tools::set_bit(&mut self.value, value, 5); + ferramenta::set_bit(&mut self.value, value, 5); } // Bit 4 @@ -93,11 +93,11 @@ impl PageDirectoryEntry // cached. Otherwise, it will be. pub fn get_pcd(&self) -> bool { - tools::get_bit_at(self.value, 4) + ferramenta::get_bit_at(self.value, 4) } pub fn set_pcd(&mut self, value: bool) { - tools::set_bit(&mut self.value, value, 4); + ferramenta::set_bit(&mut self.value, value, 4); } // Bit 3 @@ -106,11 +106,11 @@ impl PageDirectoryEntry // instead. pub fn get_pwt(&self) -> bool { - tools::get_bit_at(self.value, 3) + ferramenta::get_bit_at(self.value, 3) } pub fn set_pwt(&mut self, value: bool) { - tools::set_bit(&mut self.value, value, 3); + ferramenta::set_bit(&mut self.value, value, 3); } // Bit 2 @@ -123,11 +123,11 @@ impl PageDirectoryEntry // bit in the relevant page directory entry as well as the page table entry pub fn get_us(&self) -> bool { - tools::get_bit_at(self.value, 2) + ferramenta::get_bit_at(self.value, 2) } pub fn set_us(&mut self, value: bool) { - tools::set_bit(&mut self.value, value, 2); + ferramenta::set_bit(&mut self.value, value, 2); } // Bit 1 @@ -138,11 +138,11 @@ impl PageDirectoryEntry // the kernel (see Intel Manuals 3A 2-20). pub fn get_rw(&self) -> bool { - tools::get_bit_at(self.value, 1) + ferramenta::get_bit_at(self.value, 1) } pub fn set_rw(&mut self, value: bool) { - tools::set_bit(&mut self.value, value, 1); + ferramenta::set_bit(&mut self.value, value, 1); } // Bit 0 @@ -153,10 +153,10 @@ impl PageDirectoryEntry // and the OS should handle it. pub fn get_present(&self) -> bool { - tools::get_bit_at(self.value, 0) + ferramenta::get_bit_at(self.value, 0) } pub fn set_present(&mut self, value: bool) { - tools::set_bit(&mut self.value, value, 0); + ferramenta::set_bit(&mut self.value, value, 0); } } diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index df09958..64fd25e 100644 --- a/src/memory/pageframe.rs +++ b/src/memory/pageframe.rs @@ -1,5 +1,5 @@ use crate::multiboot::MultibootTagMmap; -use crate::tools; +use crate::ferramenta; use crate::page_index; use crate::memory::get_mem_size; @@ -18,7 +18,7 @@ pub struct Allocator pub reserved_mem: usize, pub unusable_mem: u64, initialized: bool, - bitmap: tools::Bitmap, + bitmap: ferramenta::Bitmap, } impl Allocator @@ -32,7 +32,7 @@ impl Allocator reserved_mem: 0, unusable_mem: 0, initialized: false, - bitmap: tools::Bitmap {buffer: &mut[] as &'static mut[u8], size: 0}, + bitmap: ferramenta::Bitmap {buffer: &mut[] as &'static mut[u8], size: 0}, } } @@ -56,7 +56,7 @@ impl Allocator self.reserved_mem = crate::memory::get_mem_size(mmap, mmap_size); crate::logln!("[INFO] found {}KiB of memory", self.reserved_mem / 1024); // initialise the bitmap according to mem size, and set every page as reserved - self.init_bitmap(tools::align(kernel_end, 0x1000)); + self.init_bitmap(ferramenta::align(kernel_end, 0x1000)); crate::logln!("[INFO] assigned {} pages to bitmap", self.bitmap.size); unsafe { @@ -194,7 +194,7 @@ impl Allocator unsafe { - self.bitmap = tools::Bitmap + self.bitmap = ferramenta::Bitmap { buffer: core::slice::from_raw_parts_mut (b as *mut u8, (bitmap_size / 8) + 8), size: bitmap_size, diff --git a/src/memory/pagetable.rs b/src/memory/pagetable.rs index aa15ff8..d46f471 100644 --- a/src/memory/pagetable.rs +++ b/src/memory/pagetable.rs @@ -1,4 +1,4 @@ -use crate::tools; +use crate::ferramenta; pub struct PageTableEntry { @@ -57,11 +57,11 @@ impl PageTableEntry // to enable global pages. pub fn get_global(&self) -> bool { - tools::get_bit_at(self.value, 8) + ferramenta::get_bit_at(self.value, 8) } pub fn set_global(&mut self, value: bool) { - tools::set_bit(&mut self.value, value, 8); + ferramenta::set_bit(&mut self.value, value, 8); } // Bit 7 @@ -70,22 +70,22 @@ impl PageTableEntry // it is reserved and must be set to 0. pub fn get_pat(&self) -> bool { - tools::get_bit_at(self.value, 7) + ferramenta::get_bit_at(self.value, 7) } pub fn set_pat(&mut self, value: bool) { - tools::set_bit(&mut self.value, value, 7); + ferramenta::set_bit(&mut self.value, value, 7); } // Bit 6 // 'Dirty' is used to determine whether a page has been written to. pub fn get_dirty(&self) -> bool { - tools::get_bit_at(self.value, 6) + ferramenta::get_bit_at(self.value, 6) } pub fn set_dirty(&mut self, value: bool) { - tools::set_bit(&mut self.value, value, 6); + ferramenta::set_bit(&mut self.value, value, 6); } // Bit 5 @@ -95,11 +95,11 @@ impl PageTableEntry // so that burden falls on the OS (if it needs this bit at all). pub fn get_accessed(&self) -> bool { - tools::get_bit_at(self.value, 5) + ferramenta::get_bit_at(self.value, 5) } pub fn set_accessed(&mut self, value: bool) { - tools::set_bit(&mut self.value, value, 5); + ferramenta::set_bit(&mut self.value, value, 5); } // Bit 4 @@ -107,11 +107,11 @@ impl PageTableEntry // cached. Otherwise, it will be. pub fn get_pcd(&self) -> bool { - tools::get_bit_at(self.value, 4) + ferramenta::get_bit_at(self.value, 4) } pub fn set_pcd(&mut self, value: bool) { - tools::set_bit(&mut self.value, value, 4); + ferramenta::set_bit(&mut self.value, value, 4); } // Bit 3 @@ -120,11 +120,11 @@ impl PageTableEntry // instead. pub fn get_pwt(&self) -> bool { - tools::get_bit_at(self.value, 3) + ferramenta::get_bit_at(self.value, 3) } pub fn set_pwt(&mut self, value: bool) { - tools::set_bit(&mut self.value, value, 3); + ferramenta::set_bit(&mut self.value, value, 3); } // Bit 2 @@ -137,11 +137,11 @@ impl PageTableEntry // bit in the relevant page directory entry as well as the page table entry pub fn get_us(&self) -> bool { - tools::get_bit_at(self.value, 2) + ferramenta::get_bit_at(self.value, 2) } pub fn set_us(&mut self, value: bool) { - tools::set_bit(&mut self.value, value, 2); + ferramenta::set_bit(&mut self.value, value, 2); } // Bit 1 @@ -152,11 +152,11 @@ impl PageTableEntry // the kernel (see Intel Manuals 3A 2-20). pub fn get_rw(&self) -> bool { - tools::get_bit_at(self.value, 1) + ferramenta::get_bit_at(self.value, 1) } pub fn set_rw(&mut self, value: bool) { - tools::set_bit(&mut self.value, value, 1); + ferramenta::set_bit(&mut self.value, value, 1); } // Bit 0 @@ -167,10 +167,10 @@ impl PageTableEntry // and the OS should handle it. pub fn get_present(&self) -> bool { - tools::get_bit_at(self.value, 0) + ferramenta::get_bit_at(self.value, 0) } pub fn set_present(&mut self, value: bool) { - tools::set_bit(&mut self.value, value, 0); + ferramenta::set_bit(&mut self.value, value, 0); } } diff --git a/src/multiboot.rs b/src/multiboot.rs index 28fd276..07d1c62 100644 --- a/src/multiboot.rs +++ b/src/multiboot.rs @@ -1,6 +1,6 @@ use crate::log; use crate::logln; -use crate::tools; +use crate::ferramenta; use crate::ok_fail; use core::slice; use core::mem::size_of; @@ -61,7 +61,7 @@ impl MultibootTagString { unsafe { - tools::from_c_str((&self.str_ptr as *const _) as *const u8) + ferramenta::from_c_str((&self.str_ptr as *const _) as *const u8) } } } @@ -248,7 +248,7 @@ pub fn parse(address: u32) -> bool _ => {}//crate::println!("found tag of type {} and size {}", type_name((*tag).tag_type), (*tag).size) }; - address += tools::align((*tag).size as usize, 8) as u32; + address += ferramenta::align((*tag).size as usize, 8) as u32; } } diff --git a/src/serial.rs b/src/serial.rs index 164172c..79558b5 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -1,5 +1,5 @@ use core::fmt; -use crate::tools::{inb, outb}; +use crate::ferramenta::{inb, outb}; #[macro_export] macro_rules! serial_print diff --git a/src/tty/basic_commands.rs b/src/tty/basic_commands.rs index c1de7a0..990829e 100644 --- a/src/tty/basic_commands.rs +++ b/src/tty/basic_commands.rs @@ -1,5 +1,5 @@ use core::arch::asm; -use crate::tools; +use crate::ferramenta; use crate::vga; pub fn execute(command: &str) @@ -60,7 +60,7 @@ fn clear() fn halt() { - tools::shutdown_qemu(); + ferramenta::shutdown_qemu(); } fn reboot() @@ -96,11 +96,11 @@ fn printmem_at(address: *const u8, binary: bool) { if binary { - tools::print_memory_bin(address, 256); + ferramenta::print_memory_bin(address, 256); } else { - tools::print_memory(address, 256); + ferramenta::print_memory(address, 256); } } } @@ -109,7 +109,7 @@ fn print_stack() { unsafe { - tools::print_memory(crate::get_reg!("esp") as *const u8, 10 * 16); + ferramenta::print_memory(crate::get_reg!("esp") as *const u8, 10 * 16); } } diff --git a/src/vga/cursor.rs b/src/vga/cursor.rs index 14c2465..0768387 100644 --- a/src/vga/cursor.rs +++ b/src/vga/cursor.rs @@ -1,4 +1,4 @@ -use crate::tools::{inb, outb}; +use crate::ferramenta::{inb, outb}; use crate::vga::BUFFER_WIDTH; const CRT_ADDR_REG: u32 = 0x3D4; From fb105318b767e1b5431879ba5144e62ac341c77b Mon Sep 17 00:00:00 2001 From: afrangio Date: Sun, 20 Mar 2022 00:16:56 +0100 Subject: [PATCH 09/19] paging: fixing PD and PT get_addr When requesting the address from the PD or PT struct, it should match the value, but without the flags. So hiding it with a binary operation is the right way to do it. Also adding repr C, to avoid problems in future loading the PD into the CR3 register. --- src/memory/pagedirectory.rs | 3 ++- src/memory/pagetable.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/memory/pagedirectory.rs b/src/memory/pagedirectory.rs index e126ecd..efad1f9 100644 --- a/src/memory/pagedirectory.rs +++ b/src/memory/pagedirectory.rs @@ -1,5 +1,6 @@ use crate::ferramenta; +#[repr(C)] pub struct PageDirectoryEntry { pub value: u32 @@ -30,7 +31,7 @@ impl PageDirectoryEntry // Bits 31-12 represents the address to the PageTableDirectory. pub fn get_addr(&self) -> u32 { - self.value >> 12 + self.value & 0xfffff000 } pub fn set_addr(&mut self, addr: u32) { diff --git a/src/memory/pagetable.rs b/src/memory/pagetable.rs index d46f471..e8e9706 100644 --- a/src/memory/pagetable.rs +++ b/src/memory/pagetable.rs @@ -1,5 +1,6 @@ use crate::ferramenta; +#[repr(C)] pub struct PageTableEntry { pub value: u32 @@ -31,7 +32,7 @@ impl PageTableEntry // Bits 31-12 represents the address to the PageTableEntry. pub fn get_addr(&self) -> u32 { - self.value >> 12 + self.value & 0xfffff000 } pub fn set_addr(&mut self, addr: u32) From 07d6d7b38a8182735d63c02f94e32d41e3c5b560 Mon Sep 17 00:00:00 2001 From: afrangio Date: Sun, 20 Mar 2022 00:19:35 +0100 Subject: [PATCH 10/19] paging: setting up id page mapping mapping the first 4MiB of virtual address space to the equivalent physical addresses to continue using lower level memory function such as the VGA buffer. --- src/memory/mod.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/memory/mod.rs b/src/memory/mod.rs index 37a6e86..5a0c9ed 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -79,5 +79,17 @@ fn create_pd(addr: usize, pt1_addr: usize) t.value = ((i * 0x1000) | 3) as u32; } pd[0].set_addr(pt1_addr as u32); + id_paging(pt1); crate::logln!("\x1b[31m{:#x?}\x1b[39m", pt1[0]); -} \ No newline at end of file +} + +// mapping the first page table to physical memory. +fn id_paging(start: &mut [pagetable::PageTableEntry]) +{ + let mut block: usize = 0; + for table in start + { + table.set_addr((block) as u32); + block += 0x1000; + } +} From 3fa7c358c64f36c23c54a8408a096624eae641df Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Wed, 16 Mar 2022 16:53:40 +0100 Subject: [PATCH 11/19] PAGE_SIZE: add constant PAGE_SIZE --- src/memory/pageframe.rs | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index 64fd25e..a0b82bb 100644 --- a/src/memory/pageframe.rs +++ b/src/memory/pageframe.rs @@ -11,6 +11,8 @@ extern "C" static _kernel_end: c_void; } +static PAGE_SIZE: usize = 4096; + pub struct Allocator { pub free_mem: usize, @@ -118,8 +120,8 @@ impl Allocator } if level >= 2 { - crate::logln!("[INFO] reserved pages: {} pages", self.reserved_mem / 4096); - crate::logln!("[INFO] used pages: {} pages", self.locked_mem / 4096); + crate::logln!("[INFO] reserved pages: {} pages", self.reserved_mem / PAGE_SIZE); + crate::logln!("[INFO] used pages: {} pages", self.locked_mem / PAGE_SIZE); } if level >= 3 { @@ -134,8 +136,8 @@ impl Allocator if self.bitmap[index + i] == false { self.bitmap.set(index + i, true); - self.reserved_mem += 4096; - self.free_mem -= 4096; + self.reserved_mem += PAGE_SIZE; + self.free_mem -= PAGE_SIZE; } } } @@ -145,8 +147,8 @@ impl Allocator for i in 0..len { self.bitmap.set(index + i, false); - self.reserved_mem -= 4096; - self.free_mem += 4096; + self.reserved_mem -= PAGE_SIZE; + self.free_mem += PAGE_SIZE; } } fn lock_pages(&mut self, index: usize, len: usize) @@ -159,9 +161,12 @@ impl Allocator fn lock_page(&mut self, index: usize) { - self.bitmap.set(index, true); - self.locked_mem += 4096; - self.free_mem -= 4096; + if self.bitmap[index] == false + { + self.bitmap.set(index, true); + self.locked_mem += PAGE_SIZE; + self.free_mem -= PAGE_SIZE; + } } fn unlock_page(&mut self, index: usize) @@ -170,8 +175,8 @@ impl Allocator { crate::logln!("unlocking page {}", index); self.bitmap.set(index, false); - self.free_mem += 4096; - self.locked_mem -= 4096; + self.free_mem += PAGE_SIZE; + self.locked_mem -= PAGE_SIZE; } else { @@ -189,7 +194,7 @@ impl Allocator fn init_bitmap(&mut self, b: usize) { - let bitmap_size = self.reserved_mem / 4096; + let bitmap_size = self.reserved_mem / PAGE_SIZE; crate::logln!("[INFO] bitmap location: {:#x}", b); unsafe From b1279780c3d5af9e03da3b900897d879f0e6d65d Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Thu, 17 Mar 2022 22:11:41 +0100 Subject: [PATCH 12/19] mem: load page directory into CR3 and enable paging --- src/arch/i686/paging.asm | 24 ++++++++++++++++++++++++ src/memory/mod.rs | 14 ++++++++++++++ src/memory/pageframe.rs | 1 + 3 files changed, 39 insertions(+) create mode 100644 src/arch/i686/paging.asm diff --git a/src/arch/i686/paging.asm b/src/arch/i686/paging.asm new file mode 100644 index 0000000..a7c18de --- /dev/null +++ b/src/arch/i686/paging.asm @@ -0,0 +1,24 @@ +global load_page_directory +load_page_directory: + push ebp + mov ebp, esp + + mov eax, [8+esp] + mov cr3, eax + + mov esp, ebp + pop ebp + ret + +global enable_paging +enable_paging: + push ebp + mov ebp, esp + + mov eax, cr0 + or eax, 0x80000000 + mov cr0, eax + + mov esp, ebp + pop ebp + ret diff --git a/src/memory/mod.rs b/src/memory/mod.rs index 5a0c9ed..c5eeea1 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -61,6 +61,14 @@ pub fn init(mmap: *const MultibootTagMmap, mmap_size: usize) pd_ptr = alloc.request_free_page(); pt1_ptr = alloc.request_free_page(); create_pd(pd_ptr, pt1_ptr); + crate::logln!("test"); +} + + +extern "C" +{ + fn load_page_directory(address: *const u8); + fn enable_paging(); } fn create_pd(addr: usize, pt1_addr: usize) @@ -81,6 +89,12 @@ fn create_pd(addr: usize, pt1_addr: usize) pd[0].set_addr(pt1_addr as u32); id_paging(pt1); crate::logln!("\x1b[31m{:#x?}\x1b[39m", pt1[0]); + unsafe + { + crate::logln!("{:?}", &pd as *const _ as *const u8); + load_page_directory(&pd as *const _ as *const u8); + enable_paging(); + } } // mapping the first page table to physical memory. diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index a0b82bb..10c115d 100644 --- a/src/memory/pageframe.rs +++ b/src/memory/pageframe.rs @@ -80,6 +80,7 @@ impl Allocator // reserve bitmap crate::logln!("reserving {} pages for bitmap", page_index!(self.bitmap.size / 8)); self.reserve_mem(page_index!(kernel_end), page_index!(self.bitmap.size / 8)); + crate::logln!("free {}KiB used {}KiB reserved {}KiB", self.free_mem / 1024, self.locked_mem / 1024, self.reserved_mem / 1024); } pub fn request_free_page(&mut self) -> usize From 63f8ac22c56d41392b868daf6f4c34f703c3f746 Mon Sep 17 00:00:00 2001 From: afrangio Date: Mon, 21 Mar 2022 11:28:08 +0100 Subject: [PATCH 13/19] mem: set first PD as present, and use "passed by" addr --- src/memory/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/memory/mod.rs b/src/memory/mod.rs index c5eeea1..0410fe6 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -88,11 +88,12 @@ fn create_pd(addr: usize, pt1_addr: usize) } pd[0].set_addr(pt1_addr as u32); id_paging(pt1); + pd[0].set_present(true); crate::logln!("\x1b[31m{:#x?}\x1b[39m", pt1[0]); unsafe { - crate::logln!("{:?}", &pd as *const _ as *const u8); - load_page_directory(&pd as *const _ as *const u8); + crate::logln!("{:?}", addr as *const u8); + load_page_directory(addr as *const u8); enable_paging(); } } From 37307488054bb4f610e482f36d35f962ddc74be0 Mon Sep 17 00:00:00 2001 From: afrangio Date: Mon, 21 Mar 2022 11:53:36 +0100 Subject: [PATCH 14/19] mem: combine PD and PT in single page.rs file Cleaning up some things: - removed unused get_largest_mem_segment() function - using ptr to DirectoryEntry instead of u8 when calling loadPageDirectory() --- src/memory/mod.rs | 47 ++------ src/memory/{pagetable.rs => page.rs} | 168 ++++++++++++++++++++++++++- src/memory/pagedirectory.rs | 163 -------------------------- 3 files changed, 175 insertions(+), 203 deletions(-) rename src/memory/{pagetable.rs => page.rs} (51%) delete mode 100644 src/memory/pagedirectory.rs diff --git a/src/memory/mod.rs b/src/memory/mod.rs index 0410fe6..f09f891 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -1,16 +1,8 @@ -pub mod pageframe; -mod pagedirectory; -mod pagetable; +mod pageframe; +mod page; -use core::ffi::c_void; use crate::multiboot::MultibootTagMmap; -extern "C" -{ - static _kernel_start: c_void; - static _kernel_end: c_void; -} - pub fn get_mem_size(mmap: *const MultibootTagMmap, mmap_size: usize) -> usize { static mut MEM_SIZE_BYTES: u64 = 0; @@ -33,24 +25,6 @@ pub fn get_mem_size(mmap: *const MultibootTagMmap, mmap_size: usize) -> usize } } -pub fn get_largest_mem_seg(mmap: *const MultibootTagMmap, mmap_size: usize) -> usize -{ - let mut largest_free_mem_seg: usize = 0; - let mut largest_free_mem_seg_size: usize = 0; - unsafe - { - for entry in (*mmap).entries(mmap_size) - { - if entry.len as usize > largest_free_mem_seg_size - { - largest_free_mem_seg_size = entry.len as usize; - largest_free_mem_seg = entry.addr as usize; - } - } - } - largest_free_mem_seg -} - pub fn init(mmap: *const MultibootTagMmap, mmap_size: usize) { let pd_ptr: usize; @@ -64,20 +38,19 @@ pub fn init(mmap: *const MultibootTagMmap, mmap_size: usize) crate::logln!("test"); } - extern "C" { - fn load_page_directory(address: *const u8); + fn load_page_directory(address: *const page::DirectoryEntry); fn enable_paging(); } fn create_pd(addr: usize, pt1_addr: usize) { - let pd: &'static mut [pagedirectory::PageDirectoryEntry]; - let pt1: &'static mut [pagetable::PageTableEntry]; + let pd: &'static mut [page::DirectoryEntry]; + let pt1: &'static mut [page::TableEntry]; - pd = unsafe{ core::slice::from_raw_parts_mut(addr as *mut pagedirectory::PageDirectoryEntry, 1024) }; - pt1 = unsafe{ core::slice::from_raw_parts_mut(pt1_addr as *mut pagetable::PageTableEntry, 1024) }; + pd = unsafe{ core::slice::from_raw_parts_mut(addr as *mut page::DirectoryEntry, 1024) }; + pt1 = unsafe{ core::slice::from_raw_parts_mut(pt1_addr as *mut page::TableEntry, 1024) }; for d in &mut *pd { d.value = 0x00000002; @@ -92,14 +65,14 @@ fn create_pd(addr: usize, pt1_addr: usize) crate::logln!("\x1b[31m{:#x?}\x1b[39m", pt1[0]); unsafe { - crate::logln!("{:?}", addr as *const u8); - load_page_directory(addr as *const u8); + crate::logln!("{:?}", addr as *const page::DirectoryEntry); + load_page_directory(addr as *const page::DirectoryEntry); enable_paging(); } } // mapping the first page table to physical memory. -fn id_paging(start: &mut [pagetable::PageTableEntry]) +fn id_paging(start: &mut [page::TableEntry]) { let mut block: usize = 0; for table in start diff --git a/src/memory/pagetable.rs b/src/memory/page.rs similarity index 51% rename from src/memory/pagetable.rs rename to src/memory/page.rs index e8e9706..ca852d4 100644 --- a/src/memory/pagetable.rs +++ b/src/memory/page.rs @@ -1,12 +1,174 @@ use crate::ferramenta; #[repr(C)] -pub struct PageTableEntry +pub struct DirectoryEntry { pub value: u32 } -impl core::fmt::Debug for PageTableEntry +impl core::fmt::Debug for DirectoryEntry +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result + { + f.debug_struct("PageDirectoryEntry") + .field("value", &self.value) + .field("addr", &self.get_addr()) + .field("flags", &self.get_flags()) + .field("ps", &self.get_ps()) + .field("flag2", &self.get_flag2()) + .field("accessed", &self.get_accessed()) + .field("pcd", &self.get_pcd()) + .field("pwt", &self.get_pwt()) + .field("us", &self.get_us()) + .field("rw", &self.get_rw()) + .field("present", &self.get_present()) + .finish() + } +} + +impl DirectoryEntry +{ + // Bits 31-12 represents the address to the PageTableDirectory. + pub fn get_addr(&self) -> u32 + { + self.value & 0xfffff000 + } + pub fn set_addr(&mut self, addr: u32) + { + self.value &= 0xfff; + self.value |= addr; + } + + // Bits 11-8 are available for us to do whatever we want. + pub fn get_flags(&self) -> u8 + { + ((self.value << 20) >> 28) as u8 + } + pub fn set_flags(&mut self, flags: u8) + { + self.value &= 0xffff_f0ff; + self.value |= (flags as u32) << 8; + } + + // Bit 7 + // PS, or 'Page Size' stores t-he page size for that specific entry. + // If the bit is set, then the PDE maps to a page that is 4 MiB in size. + // Otherwise, it maps to a 4 KiB page table. Please note that 4-MiB pages + // require PSE to be enabled. In our case, it will be 0. + pub fn get_ps(&self) -> bool + { + ferramenta::get_bit_at(self.value, 7) + } + pub fn set_ps(&mut self, value: bool) + { + ferramenta::set_bit(&mut self.value, value, 7); + } + + + // Bit 6 is available for us to do whatever we want. + pub fn get_flag2(&self) -> bool + { + ferramenta::get_bit_at(self.value, 6) + } + pub fn set_flag2(&mut self, value: bool) + { + ferramenta::set_bit(&mut self.value, value, 6); + } + + // Bit 5 + // 'Accessed' is used to discover whether a PDE or PTE was read during + // virtual address translation. If it has, then the bit is set, otherwise, + // it is not. Note that, this bit will not be cleared by the CPU, + // so that burden falls on the OS (if it needs this bit at all). + pub fn get_accessed(&self) -> bool + { + ferramenta::get_bit_at(self.value, 5) + } + pub fn set_accessed(&mut self, value: bool) + { + ferramenta::set_bit(&mut self.value, value, 5); + } + + // Bit 4 + // PCD, is the 'Cache Disable' bit. If the bit is set, the page will not be + // cached. Otherwise, it will be. + pub fn get_pcd(&self) -> bool + { + ferramenta::get_bit_at(self.value, 4) + } + pub fn set_pcd(&mut self, value: bool) + { + ferramenta::set_bit(&mut self.value, value, 4); + } + + // Bit 3 + // PWT, controls Write-Through' abilities of the page. If the bit is set, + // write-through caching is enabled. If not, then write-back is enabled + // instead. + pub fn get_pwt(&self) -> bool + { + ferramenta::get_bit_at(self.value, 3) + } + pub fn set_pwt(&mut self, value: bool) + { + ferramenta::set_bit(&mut self.value, value, 3); + } + + // Bit 2 + // The 'User/Supervisor' bit, controls access to the page based on privilege + // level. If the bit is set, then the page may be accessed by all; + // if the bit is not set, however, only the supervisor can access it. + // For a page directory entry, the user bit controls access to all the pages + // referenced by the page directory entry. T + // herefore if you wish to make a page a user page, you must set the user + // bit in the relevant page directory entry as well as the page table entry + pub fn get_us(&self) -> bool + { + ferramenta::get_bit_at(self.value, 2) + } + pub fn set_us(&mut self, value: bool) + { + ferramenta::set_bit(&mut self.value, value, 2); + } + + // Bit 1 + // The 'Read/Write' permissions flag. If the bit is set, the page is + // read/write. Otherwise when it is not set, the page is read-only. + // The WP bit in CR0 determines if this is only applied to userland, + // always giving the kernel write access (the default) or both userland and + // the kernel (see Intel Manuals 3A 2-20). + pub fn get_rw(&self) -> bool + { + ferramenta::get_bit_at(self.value, 1) + } + pub fn set_rw(&mut self, value: bool) + { + ferramenta::set_bit(&mut self.value, value, 1); + } + + // Bit 0 + // If the bit is set, the page is actually in physical memory at the moment. + // For example, when a page is swapped out, it is not in physical memory and + // therefore not 'Present'. + // If a page is called, but not present, a page fault will occur, + // and the OS should handle it. + pub fn get_present(&self) -> bool + { + ferramenta::get_bit_at(self.value, 0) + } + pub fn set_present(&mut self, value: bool) + { + ferramenta::set_bit(&mut self.value, value, 0); + } +} + +#[repr(C)] +pub struct TableEntry +{ + pub value: u32 +} + +impl core::fmt::Debug for TableEntry { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { @@ -27,7 +189,7 @@ impl core::fmt::Debug for PageTableEntry } } -impl PageTableEntry +impl TableEntry { // Bits 31-12 represents the address to the PageTableEntry. pub fn get_addr(&self) -> u32 diff --git a/src/memory/pagedirectory.rs b/src/memory/pagedirectory.rs deleted file mode 100644 index efad1f9..0000000 --- a/src/memory/pagedirectory.rs +++ /dev/null @@ -1,163 +0,0 @@ -use crate::ferramenta; - -#[repr(C)] -pub struct PageDirectoryEntry -{ - pub value: u32 -} - -impl core::fmt::Debug for PageDirectoryEntry -{ - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result - { - f.debug_struct("PageDirectoryEntry") - .field("value", &self.value) - .field("addr", &self.get_addr()) - .field("flags", &self.get_flags()) - .field("ps", &self.get_ps()) - .field("flag2", &self.get_flag2()) - .field("accessed", &self.get_accessed()) - .field("pcd", &self.get_pcd()) - .field("pwt", &self.get_pwt()) - .field("us", &self.get_us()) - .field("rw", &self.get_rw()) - .field("present", &self.get_present()) - .finish() - } -} - -impl PageDirectoryEntry -{ - // Bits 31-12 represents the address to the PageTableDirectory. - pub fn get_addr(&self) -> u32 - { - self.value & 0xfffff000 - } - pub fn set_addr(&mut self, addr: u32) - { - self.value &= 0xfff; - self.value |= addr; - } - - // Bits 11-8 are available for us to do whatever we want. - pub fn get_flags(&self) -> u8 - { - ((self.value << 20) >> 28) as u8 - } - pub fn set_flags(&mut self, flags: u8) - { - self.value &= 0xffff_f0ff; - self.value |= (flags as u32) << 8; - } - - // Bit 7 - // PS, or 'Page Size' stores t-he page size for that specific entry. - // If the bit is set, then the PDE maps to a page that is 4 MiB in size. - // Otherwise, it maps to a 4 KiB page table. Please note that 4-MiB pages - // require PSE to be enabled. In our case, it will be 0. - pub fn get_ps(&self) -> bool - { - ferramenta::get_bit_at(self.value, 7) - } - pub fn set_ps(&mut self, value: bool) - { - ferramenta::set_bit(&mut self.value, value, 7); - } - - - // Bit 6 is available for us to do whatever we want. - pub fn get_flag2(&self) -> bool - { - ferramenta::get_bit_at(self.value, 6) - } - pub fn set_flag2(&mut self, value: bool) - { - ferramenta::set_bit(&mut self.value, value, 6); - } - - // Bit 5 - // 'Accessed' is used to discover whether a PDE or PTE was read during - // virtual address translation. If it has, then the bit is set, otherwise, - // it is not. Note that, this bit will not be cleared by the CPU, - // so that burden falls on the OS (if it needs this bit at all). - pub fn get_accessed(&self) -> bool - { - ferramenta::get_bit_at(self.value, 5) - } - pub fn set_accessed(&mut self, value: bool) - { - ferramenta::set_bit(&mut self.value, value, 5); - } - - // Bit 4 - // PCD, is the 'Cache Disable' bit. If the bit is set, the page will not be - // cached. Otherwise, it will be. - pub fn get_pcd(&self) -> bool - { - ferramenta::get_bit_at(self.value, 4) - } - pub fn set_pcd(&mut self, value: bool) - { - ferramenta::set_bit(&mut self.value, value, 4); - } - - // Bit 3 - // PWT, controls Write-Through' abilities of the page. If the bit is set, - // write-through caching is enabled. If not, then write-back is enabled - // instead. - pub fn get_pwt(&self) -> bool - { - ferramenta::get_bit_at(self.value, 3) - } - pub fn set_pwt(&mut self, value: bool) - { - ferramenta::set_bit(&mut self.value, value, 3); - } - - // Bit 2 - // The 'User/Supervisor' bit, controls access to the page based on privilege - // level. If the bit is set, then the page may be accessed by all; - // if the bit is not set, however, only the supervisor can access it. - // For a page directory entry, the user bit controls access to all the pages - // referenced by the page directory entry. T - // herefore if you wish to make a page a user page, you must set the user - // bit in the relevant page directory entry as well as the page table entry - pub fn get_us(&self) -> bool - { - ferramenta::get_bit_at(self.value, 2) - } - pub fn set_us(&mut self, value: bool) - { - ferramenta::set_bit(&mut self.value, value, 2); - } - - // Bit 1 - // The 'Read/Write' permissions flag. If the bit is set, the page is - // read/write. Otherwise when it is not set, the page is read-only. - // The WP bit in CR0 determines if this is only applied to userland, - // always giving the kernel write access (the default) or both userland and - // the kernel (see Intel Manuals 3A 2-20). - pub fn get_rw(&self) -> bool - { - ferramenta::get_bit_at(self.value, 1) - } - pub fn set_rw(&mut self, value: bool) - { - ferramenta::set_bit(&mut self.value, value, 1); - } - - // Bit 0 - // If the bit is set, the page is actually in physical memory at the moment. - // For example, when a page is swapped out, it is not in physical memory and - // therefore not 'Present'. - // If a page is called, but not present, a page fault will occur, - // and the OS should handle it. - pub fn get_present(&self) -> bool - { - ferramenta::get_bit_at(self.value, 0) - } - pub fn set_present(&mut self, value: bool) - { - ferramenta::set_bit(&mut self.value, value, 0); - } -} From 7d700fa6496aa7626a725d9ea1e8311969ced20a Mon Sep 17 00:00:00 2001 From: afrangio Date: Mon, 4 Apr 2022 13:04:08 +0200 Subject: [PATCH 15/19] mem: introduce memory map function prototype --- src/memory/mod.rs | 9 +++++++++ src/memory/pagetable.rs | 42 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 src/memory/pagetable.rs diff --git a/src/memory/mod.rs b/src/memory/mod.rs index f09f891..ce26d0b 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -1,4 +1,5 @@ mod pageframe; +mod pagetable; mod page; use crate::multiboot::MultibootTagMmap; @@ -81,3 +82,11 @@ fn id_paging(start: &mut [page::TableEntry]) block += 0x1000; } } + +pub fn page_map_indexer(v_addr: usize) -> (usize, usize) +{ + let pdindex = v_addr >> 22; + let ptindex = v_addr >> 12 & 0x03FF; + + return (pdindex, ptindex); +} \ No newline at end of file diff --git a/src/memory/pagetable.rs b/src/memory/pagetable.rs new file mode 100644 index 0000000..176cdfb --- /dev/null +++ b/src/memory/pagetable.rs @@ -0,0 +1,42 @@ +use crate::memory::page; +use crate::memory::page_map_indexer; + +struct Manager +{ + pub pd_addr: &'static mut [page::DirectoryEntry], +} + +impl Manager +{ + pub fn new(&mut self, addr: usize) + { + self.pd_addr = unsafe{ core::slice::from_raw_parts_mut(addr as *mut page::DirectoryEntry, 1024) }; + } + + pub fn memory_map(&self, v_addr: usize, phys_addr: usize) + { + let pdi : usize; + let pti : usize; + + (pdi, pti) = page_map_indexer(v_addr); + let pd = &self.pd_addr[pdi]; + if !pd.get_present() + { + // create entry + // request page + // memset to 0 + // set flags + } + + let pt = unsafe{ core::slice::from_raw_parts_mut(pd.get_addr() as *mut page::TableEntry, 1024) }; + let pte = &mut pt[pti]; + if !pte.get_present() + { + // create entry + // request page + // memset to 0 + // set flags + } + pte.set_addr(phys_addr as u32); + } +} \ No newline at end of file From e173eee3900bd4f53ad0043a826f13da084f9000 Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Mon, 4 Apr 2022 15:34:30 +0200 Subject: [PATCH 16/19] libc: update prototypes --- src/elsos.rs | 1 + src/gdt.rs | 5 +++-- src/libc/libc.h | 2 +- src/libc/mod.rs | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/elsos.rs b/src/elsos.rs index 5dfaafc..82e28ee 100644 --- a/src/elsos.rs +++ b/src/elsos.rs @@ -13,6 +13,7 @@ mod multiboot; mod serial; mod gdt; mod memory; +mod libc; use core::panic::PanicInfo; diff --git a/src/gdt.rs b/src/gdt.rs index 2dc50c5..3392b7c 100644 --- a/src/gdt.rs +++ b/src/gdt.rs @@ -1,6 +1,8 @@ // using https://wiki.osdev.org/Global_Descriptor_Table#Segment_Descriptor to fill the values use core::mem::size_of; +use core::ffi::c_void; +use crate::libc; #[repr(C, packed)] struct gdt_ptr @@ -102,7 +104,6 @@ static mut GDT_TABLE: gdt = gdt extern "C" { fn _gdt_flush(); - fn memcpy(dst: *const u8, src: *const u8, size: usize); } #[no_mangle] @@ -117,7 +118,7 @@ pub fn init_gdt() let size = size_of::() - 1; unsafe { - memcpy(0x800 as *const u8, (&GDT_TABLE as *const _) as *const u8, size); + libc::memcpy(0x800 as *mut c_void, (&GDT_TABLE as *const _) as *const c_void, size); _gp.limit = size as u16; _gdt_flush(); } diff --git a/src/libc/libc.h b/src/libc/libc.h index 995f146..b07b659 100644 --- a/src/libc/libc.h +++ b/src/libc/libc.h @@ -4,6 +4,6 @@ void *memset(void *b, int c, size_t len); void *memcpy(void *dst, const void *src, size_t n); void *memmove(void *dst, const void *src, size_t len); -int memcmp(const void *s1, const void *s2, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); #endif diff --git a/src/libc/mod.rs b/src/libc/mod.rs index 5cff0ba..708a828 100644 --- a/src/libc/mod.rs +++ b/src/libc/mod.rs @@ -4,4 +4,5 @@ extern "C" { pub fn memcpy(dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void; pub fn memmove(dest: *mut c_void, src: *const c_void, n: usize) -> *mut c_void; + pub fn memset(dest: *mut c_void, val: usize, len: usize) -> *mut c_void; } From cd55e2705edc79de1058c58bb99da354794888ce Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Mon, 4 Apr 2022 17:13:41 +0200 Subject: [PATCH 17/19] PAGE_SIZE: move constant --- src/memory/mod.rs | 2 ++ src/memory/pageframe.rs | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/memory/mod.rs b/src/memory/mod.rs index ce26d0b..68a82ce 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -4,6 +4,8 @@ mod page; use crate::multiboot::MultibootTagMmap; +static PAGE_SIZE: usize = 4096; + pub fn get_mem_size(mmap: *const MultibootTagMmap, mmap_size: usize) -> usize { static mut MEM_SIZE_BYTES: u64 = 0; diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index 10c115d..6452d43 100644 --- a/src/memory/pageframe.rs +++ b/src/memory/pageframe.rs @@ -2,6 +2,7 @@ use crate::multiboot::MultibootTagMmap; use crate::ferramenta; use crate::page_index; use crate::memory::get_mem_size; +use super::PAGE_SIZE; use core::ffi::c_void; @@ -11,8 +12,6 @@ extern "C" static _kernel_end: c_void; } -static PAGE_SIZE: usize = 4096; - pub struct Allocator { pub free_mem: usize, From e8959e317c50b7322c49ca48e25865f99489af7b Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Mon, 4 Apr 2022 17:13:56 +0200 Subject: [PATCH 18/19] misc: fix Ko to KiB --- src/memory/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/memory/mod.rs b/src/memory/mod.rs index 68a82ce..ddb4285 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -22,7 +22,7 @@ pub fn get_mem_size(mmap: *const MultibootTagMmap, mmap_size: usize) -> usize } if MEM_SIZE_BYTES > usize::MAX as u64 { - panic!("This version of ElsOS is in 32 bit, it only supports {}Mo of RAM, you have {}Mo installed", (usize::MAX / 1024) / 1024, (MEM_SIZE_BYTES / 1024) / 1024); + panic!("This version of elsOS is in 32 bit, it only supports {}MiB of RAM, you have {}MiB installed", (usize::MAX / 1024) / 1024, (MEM_SIZE_BYTES / 1024) / 1024); } return MEM_SIZE_BYTES as usize; } From a333a6635572318c1f48c0439b8c9557a86f00f2 Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Mon, 4 Apr 2022 17:14:36 +0200 Subject: [PATCH 19/19] memory: add mapping and move id mapping to new functions --- src/memory/mod.rs | 58 +++++++++----------------------- src/memory/pageframe.rs | 10 ++++-- src/memory/pagetable.rs | 73 ++++++++++++++++++++++++++++------------- 3 files changed, 73 insertions(+), 68 deletions(-) diff --git a/src/memory/mod.rs b/src/memory/mod.rs index ddb4285..8129775 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -30,65 +30,39 @@ pub fn get_mem_size(mmap: *const MultibootTagMmap, mmap_size: usize) -> usize pub fn init(mmap: *const MultibootTagMmap, mmap_size: usize) { - let pd_ptr: usize; - let pt1_ptr: usize; - let mut alloc: pageframe::Allocator = pageframe::Allocator::new(); - + let alloc: &mut pageframe::Allocator = pageframe::Allocator::shared(); alloc.read_grub_mmap(mmap, mmap_size); - pd_ptr = alloc.request_free_page(); - pt1_ptr = alloc.request_free_page(); - create_pd(pd_ptr, pt1_ptr); - crate::logln!("test"); -} - -extern "C" -{ - fn load_page_directory(address: *const page::DirectoryEntry); - fn enable_paging(); -} -fn create_pd(addr: usize, pt1_addr: usize) -{ - let pd: &'static mut [page::DirectoryEntry]; - let pt1: &'static mut [page::TableEntry]; + let page_directory_addr = alloc.request_free_page(); + let mut pt_manager = pagetable::Manager::new(page_directory_addr); - pd = unsafe{ core::slice::from_raw_parts_mut(addr as *mut page::DirectoryEntry, 1024) }; - pt1 = unsafe{ core::slice::from_raw_parts_mut(pt1_addr as *mut page::TableEntry, 1024) }; - for d in &mut *pd - { - d.value = 0x00000002; - } - for (i, t) in &mut (*pt1).iter_mut().enumerate() - { - t.value = ((i * 0x1000) | 3) as u32; - } - pd[0].set_addr(pt1_addr as u32); - id_paging(pt1); - pd[0].set_present(true); - crate::logln!("\x1b[31m{:#x?}\x1b[39m", pt1[0]); + id_map(&mut pt_manager); unsafe { - crate::logln!("{:?}", addr as *const page::DirectoryEntry); - load_page_directory(addr as *const page::DirectoryEntry); + load_page_directory(page_directory_addr as *const page::DirectoryEntry); enable_paging(); } } -// mapping the first page table to physical memory. -fn id_paging(start: &mut [page::TableEntry]) +fn id_map(pt_manager: &mut pagetable::Manager) { - let mut block: usize = 0; - for table in start + for i in 0..1024 { - table.set_addr((block) as u32); - block += 0x1000; + pt_manager.memory_map(i * PAGE_SIZE, i * PAGE_SIZE); + pageframe::Allocator::shared().lock_page(i); } } +extern "C" +{ + fn load_page_directory(address: *const page::DirectoryEntry); + fn enable_paging(); +} + pub fn page_map_indexer(v_addr: usize) -> (usize, usize) { let pdindex = v_addr >> 22; let ptindex = v_addr >> 12 & 0x03FF; return (pdindex, ptindex); -} \ No newline at end of file +} diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index 6452d43..f9d9bae 100644 --- a/src/memory/pageframe.rs +++ b/src/memory/pageframe.rs @@ -24,9 +24,9 @@ pub struct Allocator impl Allocator { - pub fn new() -> Allocator + pub fn shared() -> &'static mut Allocator { - Allocator + static mut ALLOC: Allocator = Allocator { free_mem: 0, locked_mem: 0, @@ -34,6 +34,10 @@ impl Allocator unusable_mem: 0, initialized: false, bitmap: ferramenta::Bitmap {buffer: &mut[] as &'static mut[u8], size: 0}, + }; + unsafe + { + &mut ALLOC } } @@ -159,7 +163,7 @@ impl Allocator } } - fn lock_page(&mut self, index: usize) + pub fn lock_page(&mut self, index: usize) { if self.bitmap[index] == false { diff --git a/src/memory/pagetable.rs b/src/memory/pagetable.rs index 176cdfb..756d566 100644 --- a/src/memory/pagetable.rs +++ b/src/memory/pagetable.rs @@ -1,42 +1,69 @@ +use crate::libc; +use crate::memory::PAGE_SIZE; use crate::memory::page; +use crate::memory::pageframe; use crate::memory::page_map_indexer; +use core::ffi::c_void; -struct Manager +pub struct Manager { - pub pd_addr: &'static mut [page::DirectoryEntry], + pub page_directory: &'static mut [page::DirectoryEntry], } impl Manager { - pub fn new(&mut self, addr: usize) + pub fn new(addr: usize) -> Manager { - self.pd_addr = unsafe{ core::slice::from_raw_parts_mut(addr as *mut page::DirectoryEntry, 1024) }; + unsafe + { + libc::memset(addr as *mut c_void, 0, PAGE_SIZE); + Manager + { + page_directory: core::slice::from_raw_parts_mut(addr as *mut page::DirectoryEntry, 1024) + } + } } - pub fn memory_map(&self, v_addr: usize, phys_addr: usize) + fn create_page_directory_entry(&mut self, index: usize) { - let pdi : usize; - let pti : usize; + let page_directory_entry = &mut self.page_directory[index]; - (pdi, pti) = page_map_indexer(v_addr); - let pd = &self.pd_addr[pdi]; - if !pd.get_present() + if !page_directory_entry.get_present() { - // create entry - // request page - // memset to 0 - // set flags + let alloc = pageframe::Allocator::shared(); + let page_table_addr = alloc.request_free_page(); + unsafe + { + libc::memset(page_table_addr as *mut c_void, 0, PAGE_SIZE); + } + page_directory_entry.set_addr(page_table_addr as u32); + page_directory_entry.set_rw(true); + page_directory_entry.set_present(true); } + } + + fn create_page_table_entry(&mut self, page_directory_index: usize, page_table_index: usize, physical_address: usize) + { + let page_directory_entry = &mut self.page_directory[page_directory_index]; + let page_table = unsafe + { + core::slice::from_raw_parts_mut(page_directory_entry.get_addr() as *mut page::TableEntry, 1024) + }; + let page_table_entry = &mut page_table[page_table_index]; - let pt = unsafe{ core::slice::from_raw_parts_mut(pd.get_addr() as *mut page::TableEntry, 1024) }; - let pte = &mut pt[pti]; - if !pte.get_present() + if !page_table_entry.get_present() { - // create entry - // request page - // memset to 0 - // set flags + page_table_entry.set_addr(physical_address as u32); + page_table_entry.set_rw(true); + page_table_entry.set_present(true); } - pte.set_addr(phys_addr as u32); } -} \ No newline at end of file + + pub fn memory_map(&mut self, v_addr: usize, phys_addr: usize) + { + let (pdi, pti): (usize, usize) = page_map_indexer(v_addr); + + self.create_page_directory_entry(pdi); + self.create_page_table_entry(pdi, pti, phys_addr); + } +}