From ede360d67e736f97eae24433f51efdfd6b9bed15 Mon Sep 17 00:00:00 2001 From: afrangio Date: Thu, 24 Feb 2022 15:00:18 +0100 Subject: [PATCH 01/19] mem: decoding multiboot memmap --- src/multiboot.rs | 63 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/src/multiboot.rs b/src/multiboot.rs index f28af67..58184a9 100644 --- a/src/multiboot.rs +++ b/src/multiboot.rs @@ -2,6 +2,8 @@ use crate::log; use crate::logln; use crate::utilities; use crate::ok_fail; +use core::slice; +use core::mem::size_of; const BOOTLOADER_MAGIC: u32 = 0x36d76289; @@ -61,6 +63,52 @@ impl MultibootTagString } } +struct MultibootTagBasicMeminfo +{ + tag_type: u32, + size: u32, + mem_lower: u32, + mem_upper: u32 +} + +// constants for the type inside MultiBootMmapEntry struct +const MULTIBOOT_MEMORY_AVAILABLE: u32 = 1; +const MULTIBOOT_MEMORY_RESERVED: u32 = 2; +const MULTIBOOT_MEMORY_ACPI_RECLAIMABLE: u32 = 3; +const MULTIBOOT_MEMORY_NVS: u32 = 4; +const MULTIBOOT_MEMORY_BADRAM: u32 = 5; +#[repr(C)] +#[derive(Debug)] +struct MultibootMmapEntry +{ + addr: u64, + len: u64, + tag_type: u32, + zero: u32 +} + +#[repr(C)] +struct MultibootTagMmap +{ + + tag_type: u32, + size: u32, + entry_size: u32, + entry_version: u32, + entries_ptr: &'static [MultibootMmapEntry]//u32, // struct *MultibootMmapEntry +} + +impl MultibootTagMmap +{ + fn entries(&self, number: usize) -> &'static [MultibootMmapEntry] + { + unsafe + { + slice::from_raw_parts((&self.entries_ptr as *const _) as *const MultibootMmapEntry, number) + } + } +} + pub fn check_magic(magic: u32) -> bool { let magic_ok = magic == BOOTLOADER_MAGIC; @@ -186,7 +234,20 @@ pub fn parse(address: u32) -> bool logln!("[INFO] end of multiboot2 information structure"); break }, - _ => {}//println!("found tag of type {} and size {}", type_name((*tag).tag_type), (*tag).size) + MULTIBOOT_TAG_TYPE_BASIC_MEMINFO => + { + let meminfo = tag as *const MultibootTagBasicMeminfo; + crate::logln!("\x1B[33mupper: {:#}\nlower:{:#}\x1B[39m", (*meminfo).mem_upper, (*meminfo).mem_lower); + } + MULTIBOOT_TAG_TYPE_MMAP => + { + let mmap = tag as *const MultibootTagMmap; + + let number: usize = (*tag).size as usize / size_of::(); + + crate::logln!("\x1B[33mmmap: {:?}\x1B[39m", (*mmap).entries(number)); + } + _ => {}//crate::println!("found tag of type {} and size {}", type_name((*tag).tag_type), (*tag).size) }; address += ((*tag).size + 7) & !7; From 67a1d1b3b5f8d87904db8608b185b5f12f9030bc Mon Sep 17 00:00:00 2001 From: afrangio Date: Thu, 3 Mar 2022 22:31:33 +0100 Subject: [PATCH 02/19] linker: align 4K, add kernel start/end variables --- src/arch/i686/linker.ld | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/arch/i686/linker.ld b/src/arch/i686/linker.ld index 44038fe..9130f48 100644 --- a/src/arch/i686/linker.ld +++ b/src/arch/i686/linker.ld @@ -1,17 +1,33 @@ ENTRY(_start) -SECTIONS { - . = 1M; - - .boot : +SECTIONS +{ + . = 0x00100000; + .boot BLOCK(4K) : ALIGN(4K) { /* ensure that the multiboot header is at the beginning */ KEEP(*(.multiboot_header)) } - - .text : + .text BLOCK(4K) : ALIGN(4K) { + _kernel_start = .; *(.text) } + /* Read-only data. */ + .rodata BLOCK(4K) : ALIGN(4K) + { + *(.rodata) + } + + /* Read-write data (initialized) */ + .data BLOCK(4K) : ALIGN(4K) + { + *(.data) + } + .bss BLOCK(4K) : ALIGN(4K) + { + *(COMMON) + *(.bss) + } + _kernel_end = .; } - From a582db907b4999cfb169dd297d19d65c36afb338 Mon Sep 17 00:00:00 2001 From: afrangio Date: Sat, 5 Mar 2022 20:42:40 +0100 Subject: [PATCH 03/19] utilities: add bitmap implementation --- src/utilities.rs | 91 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 73 insertions(+), 18 deletions(-) diff --git a/src/utilities.rs b/src/utilities.rs index b0ed081..477e0c1 100644 --- a/src/utilities.rs +++ b/src/utilities.rs @@ -9,40 +9,40 @@ pub fn shutdown_qemu() #[inline(always)] pub fn outw(port: u32, value: u16) { - unsafe - { - asm!("out dx, ax", in("dx") port, in("ax") value, - options(nomem, nostack, preserves_flags)); - } + unsafe + { + asm!("out dx, ax", in("dx") port, in("ax") value, + options(nomem, nostack, preserves_flags)); + } } #[inline(always)] pub fn inb(port: u32) -> u8 { - let ret: u8; - unsafe - { - asm!("in al, dx", out("al") ret, in("dx") port, - options(nomem, nostack, preserves_flags)); - } - ret + let ret: u8; + unsafe + { + asm!("in al, dx", out("al") ret, in("dx") port, + options(nomem, nostack, preserves_flags)); + } + ret } #[inline(always)] pub fn outb(port: u32, value: u8) { - unsafe - { - asm!("out dx, al", in("dx") port, in("al") value, - options(nomem, nostack, preserves_flags)); - } + unsafe + { + asm!("out dx, al", in("dx") port, in("al") value, + options(nomem, nostack, preserves_flags)); + } } pub fn get_bit_at(input: u8, n: u8) -> bool { if n < 8 { - return input & (1 << n) != 0; + return input & (1 << n) != 0; } false } @@ -64,6 +64,7 @@ pub unsafe fn from_c_str(ptr: *const u8) -> &'static [u8] slice::from_raw_parts(ptr, strlen(ptr) + 1) } +<<<<<<< HEAD pub unsafe fn print_memory(ptr: *const u8, n: usize) { let mut i: usize = 0; @@ -124,4 +125,58 @@ macro_rules! get_reg core::arch::asm!(concat!("mov {}, ", $reg), out(reg) val); val }} + +} + +pub fn pow(n1: u64, n2: u64) -> u64 +{ + let mut r = n1; + + for _ in 1..n2 + { + r = r * n1; + } + + r +} + +pub struct Bitmap +{ + pub buffer: &'static mut[u8], + pub size: usize, +} + +impl Bitmap +{ + pub fn get(&self, index: usize) -> bool + { + let byte_index: usize = index / 8; + let bit_index: u8 = (index % 8).try_into().unwrap(); + let bit_indexer: u8 = 0b10000000 >> bit_index; + + if self.buffer[byte_index] & bit_indexer > 0 + { + return true; + } + return false; + } + pub fn set(&mut self, index: usize, value: bool) + { + let byte_index: usize = index / 8; + let bit_index: u8 = (index % 8).try_into().unwrap(); + let bit_indexer: u8 = 0b10000000 >> bit_index; + + self.buffer[byte_index] &= !bit_indexer; + if value + { + self.buffer[byte_index] |= bit_indexer; + } + } + pub fn debug_print(&self) + { + for i in 0..self.size + { + crate::logln!("{}", self.get(i)); + } + } } From da9c55024cf258288c0e99f148b1ff18ab1b213b Mon Sep 17 00:00:00 2001 From: afrangio Date: Sat, 5 Mar 2022 20:46:38 +0100 Subject: [PATCH 04/19] rename utilities to tools to be shorter --- src/elsos.rs | 2 +- src/keyboard/mod.rs | 4 ++-- src/multiboot.rs | 4 ++-- src/serial.rs | 2 +- src/{utilities.rs => tools.rs} | 1 - src/tty/basic_commands.rs | 10 +++++----- src/vga/cursor.rs | 2 +- 7 files changed, 12 insertions(+), 13 deletions(-) rename src/{utilities.rs => tools.rs} (99%) diff --git a/src/elsos.rs b/src/elsos.rs index 16172dd..1ea535b 100644 --- a/src/elsos.rs +++ b/src/elsos.rs @@ -5,7 +5,7 @@ #![no_std] #![no_main] -mod utilities; +mod tools; mod vga; mod keyboard; mod tty; diff --git a/src/keyboard/mod.rs b/src/keyboard/mod.rs index c30b97e..56d5bb2 100644 --- a/src/keyboard/mod.rs +++ b/src/keyboard/mod.rs @@ -1,5 +1,5 @@ use crate::tty; -use crate::utilities; +use crate::tools; mod azerty; mod qwerty; @@ -54,7 +54,7 @@ pub fn get_scancodes() let mut scancode: u8 = 0; loop { - let new_scancode = utilities::inb(KEYBOARD_DATA); + let new_scancode = tools::inb(KEYBOARD_DATA); if new_scancode == scancode { diff --git a/src/multiboot.rs b/src/multiboot.rs index 58184a9..8c39c03 100644 --- a/src/multiboot.rs +++ b/src/multiboot.rs @@ -1,6 +1,6 @@ use crate::log; use crate::logln; -use crate::utilities; +use crate::tools; use crate::ok_fail; use core::slice; use core::mem::size_of; @@ -58,7 +58,7 @@ impl MultibootTagString { unsafe { - utilities::from_c_str((&self.str_ptr as *const _) as *const u8) + tools::from_c_str((&self.str_ptr as *const _) as *const u8) } } } diff --git a/src/serial.rs b/src/serial.rs index 4cc3a17..164172c 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -1,5 +1,5 @@ use core::fmt; -use crate::utilities::{inb, outb}; +use crate::tools::{inb, outb}; #[macro_export] macro_rules! serial_print diff --git a/src/utilities.rs b/src/tools.rs similarity index 99% rename from src/utilities.rs rename to src/tools.rs index 477e0c1..24d82ea 100644 --- a/src/utilities.rs +++ b/src/tools.rs @@ -64,7 +64,6 @@ pub unsafe fn from_c_str(ptr: *const u8) -> &'static [u8] slice::from_raw_parts(ptr, strlen(ptr) + 1) } -<<<<<<< HEAD pub unsafe fn print_memory(ptr: *const u8, n: usize) { let mut i: usize = 0; diff --git a/src/tty/basic_commands.rs b/src/tty/basic_commands.rs index b9a3696..c1de7a0 100644 --- a/src/tty/basic_commands.rs +++ b/src/tty/basic_commands.rs @@ -1,5 +1,5 @@ use core::arch::asm; -use crate::utilities; +use crate::tools; use crate::vga; pub fn execute(command: &str) @@ -60,7 +60,7 @@ fn clear() fn halt() { - utilities::shutdown_qemu(); + tools::shutdown_qemu(); } fn reboot() @@ -96,11 +96,11 @@ fn printmem_at(address: *const u8, binary: bool) { if binary { - utilities::print_memory_bin(address, 256); + tools::print_memory_bin(address, 256); } else { - utilities::print_memory(address, 256); + tools::print_memory(address, 256); } } } @@ -109,7 +109,7 @@ fn print_stack() { unsafe { - utilities::print_memory(crate::get_reg!("esp") as *const u8, 10 * 16); + tools::print_memory(crate::get_reg!("esp") as *const u8, 10 * 16); } } diff --git a/src/vga/cursor.rs b/src/vga/cursor.rs index fe7c587..14c2465 100644 --- a/src/vga/cursor.rs +++ b/src/vga/cursor.rs @@ -1,4 +1,4 @@ -use crate::utilities::{inb, outb}; +use crate::tools::{inb, outb}; use crate::vga::BUFFER_WIDTH; const CRT_ADDR_REG: u32 = 0x3D4; From 7eeddf922383c63363f0f16d704b04fda454c6b3 Mon Sep 17 00:00:00 2001 From: afrangio Date: Sat, 5 Mar 2022 20:52:00 +0100 Subject: [PATCH 05/19] cleaning: convert all spaced tabs to tabs --- src/gdt.rs | 156 ++++++++++++++++++++++++------------------------ src/libc/libc.h | 8 +-- 2 files changed, 82 insertions(+), 82 deletions(-) diff --git a/src/gdt.rs b/src/gdt.rs index 667fe73..2dc50c5 100644 --- a/src/gdt.rs +++ b/src/gdt.rs @@ -5,62 +5,62 @@ use core::mem::size_of; #[repr(C, packed)] struct gdt_ptr { - limit: u16, - base: u32 + limit: u16, + base: u32 } #[repr(C, packed)] struct gdt_entry { - limit0: u16, - base0: u16, - base1: u8, - access_byte: u8, - limit1_flags: u8, - base2: u8 + limit0: u16, + base0: u16, + base1: u8, + access_byte: u8, + limit1_flags: u8, + base2: u8 } #[repr(C, packed)] struct gdt { - null: gdt_entry, - kernel_code: gdt_entry, - kernel_data: gdt_entry, + null: gdt_entry, + kernel_code: gdt_entry, + kernel_data: gdt_entry, kernel_stack: gdt_entry, - user_code: gdt_entry, - user_data: gdt_entry, + user_code: gdt_entry, + user_data: gdt_entry, user_stack: gdt_entry, } static mut GDT_TABLE: gdt = gdt { - null: gdt_entry - { - limit0: 0, - base0: 0, - base1: 0, - access_byte: 0x00, - limit1_flags: 0x00, - base2: 0 - }, - kernel_code: gdt_entry - { - limit0: 0xffff, - base0: 0, - base1: 0, - access_byte: 0b1001_1010, - limit1_flags: 0xcf, - base2: 0 - }, - kernel_data: gdt_entry - { - limit0: 0xffff, - base0: 0, - base1: 0, - access_byte: 0b1001_0010, - limit1_flags: 0xcf, - base2: 0 - }, + null: gdt_entry + { + limit0: 0, + base0: 0, + base1: 0, + access_byte: 0x00, + limit1_flags: 0x00, + base2: 0 + }, + kernel_code: gdt_entry + { + limit0: 0xffff, + base0: 0, + base1: 0, + access_byte: 0b1001_1010, + limit1_flags: 0xcf, + base2: 0 + }, + kernel_data: gdt_entry + { + limit0: 0xffff, + base0: 0, + base1: 0, + access_byte: 0b1001_0010, + limit1_flags: 0xcf, + base2: 0 + }, kernel_stack: gdt_entry { limit0: 0xffff, @@ -70,56 +70,56 @@ static mut GDT_TABLE: gdt = gdt limit1_flags: 0xcf, base2: 0 }, - user_code: gdt_entry - { - limit0: 0xffff, - base0: 0, - base1: 0, - access_byte: 0b1111_1010, - limit1_flags: 0xcf, - base2: 0 - }, - user_data: gdt_entry - { - limit0: 0xffff, - base0: 0, - base1: 0, - access_byte: 0b1111_0010, - limit1_flags: 0xcf, - base2: 0 - }, - user_stack: gdt_entry - { - limit0: 0xffff, - base0: 0, - base1: 0, - access_byte: 0b1111_0110, - limit1_flags: 0xcf, - base2: 0 - }, + user_code: gdt_entry + { + limit0: 0xffff, + base0: 0, + base1: 0, + access_byte: 0b1111_1010, + limit1_flags: 0xcf, + base2: 0 + }, + user_data: gdt_entry + { + limit0: 0xffff, + base0: 0, + base1: 0, + access_byte: 0b1111_0010, + limit1_flags: 0xcf, + base2: 0 + }, + user_stack: gdt_entry + { + limit0: 0xffff, + base0: 0, + base1: 0, + access_byte: 0b1111_0110, + limit1_flags: 0xcf, + base2: 0 + }, }; extern "C" { - fn _gdt_flush(); - fn memcpy(dst: *const u8, src: *const u8, size: usize); + fn _gdt_flush(); + fn memcpy(dst: *const u8, src: *const u8, size: usize); } #[no_mangle] static mut _gp: gdt_ptr = gdt_ptr { - limit: 0, - base: 0x800 + limit: 0, + base: 0x800 }; pub fn init_gdt() { - let size = size_of::() - 1; - unsafe - { - memcpy(0x800 as *const u8, (&GDT_TABLE as *const _) as *const u8, size); - _gp.limit = size as u16; - _gdt_flush(); - } + let size = size_of::() - 1; + unsafe + { + memcpy(0x800 as *const u8, (&GDT_TABLE as *const _) as *const u8, size); + _gp.limit = size as u16; + _gdt_flush(); + } } diff --git a/src/libc/libc.h b/src/libc/libc.h index abdba9b..995f146 100644 --- a/src/libc/libc.h +++ b/src/libc/libc.h @@ -1,9 +1,9 @@ #ifndef LIBC_H # define LIBC_H -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); +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); #endif From 6c0567f2413ee162758c608907a0c613eee0af79 Mon Sep 17 00:00:00 2001 From: afrangio Date: Sat, 5 Mar 2022 22:45:35 +0100 Subject: [PATCH 06/19] mem: adding functions to get memory/kernel size adapting the multiboot structures by setting some values to public --- src/memory/mod.rs | 51 +++++++++++++++++++++++++++++++++++++++++++++++ src/multiboot.rs | 26 +++++++++++------------- 2 files changed, 63 insertions(+), 14 deletions(-) create mode 100644 src/memory/mod.rs diff --git a/src/memory/mod.rs b/src/memory/mod.rs new file mode 100644 index 0000000..8716236 --- /dev/null +++ b/src/memory/mod.rs @@ -0,0 +1,51 @@ +use core::ffi::c_void; +use crate::multiboot::MultibootTagMmap; + +extern "C" +{ + static _kernel_start: c_void; + static _kernel_end: c_void; +} + +pub struct MemoryUsage +{ + pub free_mem: u32, + pub locked_mem: u32, + pub reserved_mem: u32, + pub unusable_mem: u32 +} + +pub fn get_mem_size(mmap: *const MultibootTagMmap, mmap_size: usize) -> u64 +{ + static mut MEM_SIZE_BYTES: u64 = 0; + unsafe + { + if MEM_SIZE_BYTES > 0 + { + return MEM_SIZE_BYTES; + } + // crate::logln!("\x1B[33mmmap: {:#x?}\x1B[39m", (*mmap).entries(size)); + for mmap_entry in (*mmap).entries(mmap_size) + { + MEM_SIZE_BYTES += mmap_entry.len as u64; + } + 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); + } + return MEM_SIZE_BYTES; + } +} + +pub fn get_kernel_size() -> usize +{ + let kernel_start: usize; + let kernel_end: usize; + unsafe + { + kernel_start = &_kernel_start as *const _ as usize; + kernel_end = &_kernel_end as *const _ as usize; + } + let kernel_size = kernel_end - kernel_start; + return kernel_size; +} \ No newline at end of file diff --git a/src/multiboot.rs b/src/multiboot.rs index 8c39c03..9df51e5 100644 --- a/src/multiboot.rs +++ b/src/multiboot.rs @@ -5,6 +5,8 @@ use crate::ok_fail; use core::slice; use core::mem::size_of; +use crate::memory; + const BOOTLOADER_MAGIC: u32 = 0x36d76289; const MULTIBOOT_TAG_TYPE_END: u32 = 0; @@ -78,17 +80,18 @@ const MULTIBOOT_MEMORY_ACPI_RECLAIMABLE: u32 = 3; const MULTIBOOT_MEMORY_NVS: u32 = 4; const MULTIBOOT_MEMORY_BADRAM: u32 = 5; #[repr(C)] -#[derive(Debug)] -struct MultibootMmapEntry +#[derive(Debug, Copy, Clone)] +pub struct MultibootMmapEntry { - addr: u64, - len: u64, + pub addr: u64, + pub len: u64, tag_type: u32, zero: u32 } #[repr(C)] -struct MultibootTagMmap +#[derive(Debug)] +pub struct MultibootTagMmap { tag_type: u32, @@ -100,7 +103,7 @@ struct MultibootTagMmap impl MultibootTagMmap { - fn entries(&self, number: usize) -> &'static [MultibootMmapEntry] + pub fn entries(&self, number: usize) -> &'static [MultibootMmapEntry] { unsafe { @@ -234,18 +237,13 @@ pub fn parse(address: u32) -> bool logln!("[INFO] end of multiboot2 information structure"); break }, - MULTIBOOT_TAG_TYPE_BASIC_MEMINFO => - { - let meminfo = tag as *const MultibootTagBasicMeminfo; - crate::logln!("\x1B[33mupper: {:#}\nlower:{:#}\x1B[39m", (*meminfo).mem_upper, (*meminfo).mem_lower); - } MULTIBOOT_TAG_TYPE_MMAP => { let mmap = tag as *const MultibootTagMmap; + let number = (*tag).size as usize / size_of::(); + let memsize = memory::get_mem_size(mmap, number); - let number: usize = (*tag).size as usize / size_of::(); - - crate::logln!("\x1B[33mmmap: {:?}\x1B[39m", (*mmap).entries(number)); + crate::logln!("mem size: {}Mo", (memsize / 1024) / 1024); } _ => {}//crate::println!("found tag of type {} and size {}", type_name((*tag).tag_type), (*tag).size) }; From e2f52fc8c7861f22768d21cef38a5c05b553d883 Mon Sep 17 00:00:00 2001 From: afrangio Date: Sun, 6 Mar 2022 23:42:31 +0100 Subject: [PATCH 07/19] mem: initialize the bitmap in the PageFrameAlloc This is the very begining of the PFA, the PFA is in charge of mapping the memory into pages, and keep track of free pages. To archieve this it uses an internal bitmap, set to 1 if a page is in use or reserved, to 0 if the page is free. --- src/arch/i686/linker.ld | 2 +- src/elsos.rs | 6 ++++ src/memory/mod.rs | 15 +++----- src/memory/pageframe.rs | 79 +++++++++++++++++++++++++++++++++++++++++ src/multiboot.rs | 10 +++--- src/tools.rs | 7 ++++ 6 files changed, 102 insertions(+), 17 deletions(-) create mode 100644 src/memory/pageframe.rs diff --git a/src/arch/i686/linker.ld b/src/arch/i686/linker.ld index 9130f48..a9401ba 100644 --- a/src/arch/i686/linker.ld +++ b/src/arch/i686/linker.ld @@ -2,12 +2,12 @@ ENTRY(_start) SECTIONS { - . = 0x00100000; .boot BLOCK(4K) : ALIGN(4K) { /* ensure that the multiboot header is at the beginning */ KEEP(*(.multiboot_header)) } + . = 0x00100000; .text BLOCK(4K) : ALIGN(4K) { _kernel_start = .; diff --git a/src/elsos.rs b/src/elsos.rs index 1ea535b..00d9511 100644 --- a/src/elsos.rs +++ b/src/elsos.rs @@ -12,6 +12,7 @@ mod tty; mod multiboot; mod serial; mod gdt; +mod memory; use core::panic::PanicInfo; @@ -20,6 +21,9 @@ static PATCHLEVEL: &str = env!("PATCHLEVEL"); static SUBLEVEL: &str = env!("SUBLEVEL"); static EXTRAVERSION: &str = env!("EXTRAVERSION"); +use crate::multiboot::MULTIBOOT_MMAP; +use crate::multiboot::MULTIBOOT_MMAP_ENTRIES; + pub struct Settings { has_serial: bool, @@ -50,6 +54,8 @@ pub extern "C" fn kernel_main(magic: u32, address: u32) logln!(" #+# #+# :` .'._.'. `; Willkumme uf elsOS {}.{}.{}{}", VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION); logln!(" ### ######### '-`'.___.'`-' Hello, kernel world !"); logln!(); + let mut alloc: memory::pageframe::PageFrameAllocator = memory::pageframe::PageFrameAllocator::new(); + unsafe { alloc.read_grub_mmap(MULTIBOOT_MMAP, MULTIBOOT_MMAP_ENTRIES); } tty::prompt(); keyboard::get_scancodes(); } diff --git a/src/memory/mod.rs b/src/memory/mod.rs index 8716236..2c5b06f 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -1,3 +1,5 @@ +pub mod pageframe; + use core::ffi::c_void; use crate::multiboot::MultibootTagMmap; @@ -7,14 +9,6 @@ extern "C" static _kernel_end: c_void; } -pub struct MemoryUsage -{ - pub free_mem: u32, - pub locked_mem: u32, - pub reserved_mem: u32, - pub unusable_mem: u32 -} - pub fn get_mem_size(mmap: *const MultibootTagMmap, mmap_size: usize) -> u64 { static mut MEM_SIZE_BYTES: u64 = 0; @@ -24,7 +18,7 @@ pub fn get_mem_size(mmap: *const MultibootTagMmap, mmap_size: usize) -> u64 { return MEM_SIZE_BYTES; } - // crate::logln!("\x1B[33mmmap: {:#x?}\x1B[39m", (*mmap).entries(size)); + // crate::logln!("\x1B[33mmmap: {:#x?}\x1B[39m", (*mmap).entries(mmap_size)); for mmap_entry in (*mmap).entries(mmap_size) { MEM_SIZE_BYTES += mmap_entry.len as u64; @@ -47,5 +41,6 @@ pub fn get_kernel_size() -> usize kernel_end = &_kernel_end as *const _ as usize; } let kernel_size = kernel_end - kernel_start; + crate::logln!("{:#x?} {:#x?}", kernel_start, kernel_end); return kernel_size; -} \ No newline at end of file +} diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs new file mode 100644 index 0000000..1957219 --- /dev/null +++ b/src/memory/pageframe.rs @@ -0,0 +1,79 @@ +use crate::multiboot::MultibootTagMmap; +use crate::tools; + +use core::ffi::c_void; + +extern "C" +{ + static _kernel_start: c_void; + static _kernel_end: c_void; +} + +pub struct PageFrameAllocator +{ + pub free_mem: u64, + pub locked_mem: u32, + pub reserved_mem: u32, + pub unusable_mem: u32, + initialized: bool, + bitmap: tools::Bitmap, +} + +impl PageFrameAllocator +{ + pub fn new() -> PageFrameAllocator + { + PageFrameAllocator + { + free_mem: 0, + locked_mem: 0, + reserved_mem: 0, + unusable_mem: 0, + initialized: false, + bitmap: tools::Bitmap {buffer: &mut[] as &'static mut[u8], size: 0}, + + } + } + + pub fn read_grub_mmap(&mut self, mmap: *const MultibootTagMmap, mmap_size: usize) + { + let mut largest_free_mem_seg: u64 = 0; + let mut largest_free_mem_seg_size: u64 = 0; + + if self.initialized + { + return ; + } + self.initialized = true; + unsafe + { + for entry in (*mmap).entries(mmap_size) + { + if entry.len > largest_free_mem_seg_size + { + largest_free_mem_seg_size = entry.len; + largest_free_mem_seg = entry.addr; + } + } + self.free_mem = crate::memory::get_mem_size(mmap, mmap_size); + self.init_bitmap(&_kernel_end as *const _ as usize + largest_free_mem_seg as usize + 1); + } + } + + fn init_bitmap(&mut self, b: usize) + { + let bitmap_size = self.free_mem / 4096; + + unsafe + { + self.bitmap = tools::Bitmap + { + buffer: core::slice::from_raw_parts_mut (b as *mut u8, (bitmap_size / 8) as usize + 1), + size: bitmap_size as usize + 1, + }; + self.bitmap.erase(); + crate::logln!("{}", self.bitmap.size); + self.bitmap.debug_print(); + } + } +} diff --git a/src/multiboot.rs b/src/multiboot.rs index 9df51e5..d264dd0 100644 --- a/src/multiboot.rs +++ b/src/multiboot.rs @@ -5,7 +5,8 @@ use crate::ok_fail; use core::slice; use core::mem::size_of; -use crate::memory; +pub static mut MULTIBOOT_MMAP: *const MultibootTagMmap = core::ptr::null(); +pub static mut MULTIBOOT_MMAP_ENTRIES: usize = 0; const BOOTLOADER_MAGIC: u32 = 0x36d76289; @@ -239,11 +240,8 @@ pub fn parse(address: u32) -> bool }, MULTIBOOT_TAG_TYPE_MMAP => { - let mmap = tag as *const MultibootTagMmap; - let number = (*tag).size as usize / size_of::(); - let memsize = memory::get_mem_size(mmap, number); - - crate::logln!("mem size: {}Mo", (memsize / 1024) / 1024); + MULTIBOOT_MMAP = tag as *const MultibootTagMmap; + MULTIBOOT_MMAP_ENTRIES = (*tag).size as usize / size_of::(); } _ => {}//crate::println!("found tag of type {} and size {}", type_name((*tag).tag_type), (*tag).size) }; diff --git a/src/tools.rs b/src/tools.rs index 24d82ea..2320ff8 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -178,4 +178,11 @@ impl Bitmap crate::logln!("{}", self.get(i)); } } + pub fn erase(&mut self) + { + for i in 0..self.size + { + self.set(i, false); + } + } } From 1a2e0e87737e9ad27f1a3122d33b9f155cbd4440 Mon Sep 17 00:00:00 2001 From: afrangio Date: Tue, 8 Mar 2022 13:26:46 +0100 Subject: [PATCH 08/19] mem: marking reserved pages as reserved in bitmap The page frame allocator does now mark as "reserved" (set bit to 1 on bitmap) The reserved pages include grub marked as reserved and the kernel in memory and finally the bitmap itself. --- src/elsos.rs | 4 ++-- src/memory/mod.rs | 38 ++++++++++++++--------------- src/memory/pageframe.rs | 53 ++++++++++++++++++++++++++++------------- src/multiboot.rs | 8 ++++--- src/tools.rs | 22 +++++++++++++---- 5 files changed, 81 insertions(+), 44 deletions(-) diff --git a/src/elsos.rs b/src/elsos.rs index 00d9511..54a2db8 100644 --- a/src/elsos.rs +++ b/src/elsos.rs @@ -44,6 +44,8 @@ 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::PageFrameAllocator = memory::pageframe::PageFrameAllocator::new(); + unsafe { alloc.read_grub_mmap(MULTIBOOT_MMAP, MULTIBOOT_MMAP_ENTRIES); } init_serial(); logln!("\n"); logln!(" ::: :::::::: __ __ __ _ ____ ____ "); @@ -54,8 +56,6 @@ pub extern "C" fn kernel_main(magic: u32, address: u32) logln!(" #+# #+# :` .'._.'. `; Willkumme uf elsOS {}.{}.{}{}", VERSION, PATCHLEVEL, SUBLEVEL, EXTRAVERSION); logln!(" ### ######### '-`'.___.'`-' Hello, kernel world !"); logln!(); - let mut alloc: memory::pageframe::PageFrameAllocator = memory::pageframe::PageFrameAllocator::new(); - unsafe { alloc.read_grub_mmap(MULTIBOOT_MMAP, MULTIBOOT_MMAP_ENTRIES); } tty::prompt(); keyboard::get_scancodes(); } diff --git a/src/memory/mod.rs b/src/memory/mod.rs index 2c5b06f..fc0544e 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -9,38 +9,38 @@ extern "C" static _kernel_end: c_void; } -pub fn get_mem_size(mmap: *const MultibootTagMmap, mmap_size: usize) -> u64 +pub fn get_mem_size(mmap: *const MultibootTagMmap, mmap_size: usize) -> usize { - static mut MEM_SIZE_BYTES: u64 = 0; + let mut mem_size_bytes: u64 = 0; unsafe { - if MEM_SIZE_BYTES > 0 - { - return MEM_SIZE_BYTES; - } - // crate::logln!("\x1B[33mmmap: {:#x?}\x1B[39m", (*mmap).entries(mmap_size)); + crate::logln!("\x1B[33mmmap: {:#x?}\x1B[39m", (*mmap).entries(mmap_size)); for mmap_entry in (*mmap).entries(mmap_size) { - MEM_SIZE_BYTES += mmap_entry.len as u64; + mem_size_bytes += mmap_entry.len as u64; } - if MEM_SIZE_BYTES > usize::MAX as u64 + 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 {}Mo of RAM, you have {}Mo installed", (usize::MAX / 1024) / 1024, (mem_size_bytes / 1024) / 1024); } - return MEM_SIZE_BYTES; + return mem_size_bytes as usize; } } -pub fn get_kernel_size() -> usize +pub fn get_largest_mem_seg(mmap: *const MultibootTagMmap, mmap_size: usize) -> usize { - let kernel_start: usize; - let kernel_end: usize; + let mut largest_free_mem_seg: usize = 0; + let mut largest_free_mem_seg_size: usize = 0; unsafe { - kernel_start = &_kernel_start as *const _ as usize; - kernel_end = &_kernel_end as *const _ as usize; + 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; + } + } } - let kernel_size = kernel_end - kernel_start; - crate::logln!("{:#x?} {:#x?}", kernel_start, kernel_end); - return kernel_size; + largest_free_mem_seg } diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index 1957219..5bd1578 100644 --- a/src/memory/pageframe.rs +++ b/src/memory/pageframe.rs @@ -1,5 +1,6 @@ use crate::multiboot::MultibootTagMmap; use crate::tools; +use crate::page_index; use core::ffi::c_void; @@ -11,10 +12,10 @@ extern "C" pub struct PageFrameAllocator { - pub free_mem: u64, - pub locked_mem: u32, - pub reserved_mem: u32, - pub unusable_mem: u32, + pub free_mem: usize, + pub locked_mem: usize, + pub reserved_mem: usize, + pub unusable_mem: u64, initialized: bool, bitmap: tools::Bitmap, } @@ -37,43 +38,63 @@ impl PageFrameAllocator pub fn read_grub_mmap(&mut self, mmap: *const MultibootTagMmap, mmap_size: usize) { - let mut largest_free_mem_seg: u64 = 0; - let mut largest_free_mem_seg_size: u64 = 0; + let kernel_start: usize; + let kernel_end: usize; if self.initialized { return ; } self.initialized = true; + + crate::logln!("[INFO] initializing memory map..."); + unsafe + { + kernel_start = &_kernel_start as *const _ as usize; + kernel_end = &_kernel_end as *const _ as usize; + } + self.free_mem = crate::memory::get_mem_size(mmap, mmap_size); + crate::logln!("[INFO] found {}Ko of memory", self.free_mem / 1024); + self.init_bitmap(kernel_end + 1); + crate::logln!("[INFO] assigned {} pages to bitmap", self.bitmap.size); unsafe { for entry in (*mmap).entries(mmap_size) { - if entry.len > largest_free_mem_seg_size + if entry.tag_type != 1 { - largest_free_mem_seg_size = entry.len; - largest_free_mem_seg = entry.addr; + self.reserve_mem(page_index!(entry.addr as usize), page_index!(entry.len as usize)); } } - self.free_mem = crate::memory::get_mem_size(mmap, mmap_size); - self.init_bitmap(&_kernel_end as *const _ as usize + largest_free_mem_seg as usize + 1); } + self.reserve_mem(page_index!(kernel_start), page_index!(kernel_end - kernel_start)); + self.reserve_mem(page_index!(kernel_end), page_index!(self.bitmap.size) / 8); + crate::logln!("[INFO] reserved pages: {} pages", self.reserved_mem / 4096); + crate::logln!("[INFO] reserved mem: {}Ko", self.reserved_mem / 1024); } + fn reserve_mem(&mut self, index: usize, len: usize) + { + for i in 0..len + { + self.bitmap.set((index + i) as usize, true); + self.reserved_mem += 4096; + } + } fn init_bitmap(&mut self, b: usize) { - let bitmap_size = self.free_mem / 4096; + let bitmap_size = usize::MAX / 4096; unsafe { self.bitmap = tools::Bitmap { - buffer: core::slice::from_raw_parts_mut (b as *mut u8, (bitmap_size / 8) as usize + 1), - size: bitmap_size as usize + 1, + buffer: core::slice::from_raw_parts_mut (b as *mut u8, (bitmap_size / 8) + 8), + size: bitmap_size + 1, }; + self.bitmap.erase(); - crate::logln!("{}", self.bitmap.size); - self.bitmap.debug_print(); + // self.bitmap.debug_print(); } } } diff --git a/src/multiboot.rs b/src/multiboot.rs index d264dd0..c85b0bb 100644 --- a/src/multiboot.rs +++ b/src/multiboot.rs @@ -84,9 +84,11 @@ const MULTIBOOT_MEMORY_BADRAM: u32 = 5; #[derive(Debug, Copy, Clone)] pub struct MultibootMmapEntry { - pub addr: u64, - pub len: u64, - tag_type: u32, + pub addr: u32, + addr_upper: u32, + pub len: u32, + len_upper: u32, + pub tag_type: u32, zero: u32 } diff --git a/src/tools.rs b/src/tools.rs index 2320ff8..fffca0f 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -127,7 +127,16 @@ macro_rules! get_reg } -pub fn pow(n1: u64, n2: u64) -> u64 +#[macro_export] +macro_rules! page_index +{ + ($reg:expr) => + {{ + tools::divide_up($reg, 4096) + }} +} + +pub fn pow(n1: usize, n2: usize) -> usize { let mut r = n1; @@ -139,10 +148,15 @@ pub fn pow(n1: u64, n2: u64) -> u64 r } +pub fn divide_up(dividend: usize, divisor: usize) -> usize +{ + (dividend + divisor - 1) / divisor +} + pub struct Bitmap { pub buffer: &'static mut[u8], - pub size: usize, + pub size: usize, // represents the number of bits, one byte = 8 bits } impl Bitmap @@ -150,7 +164,7 @@ impl Bitmap pub fn get(&self, index: usize) -> bool { let byte_index: usize = index / 8; - let bit_index: u8 = (index % 8).try_into().unwrap(); + let bit_index: u8 = (index % 8) as u8; let bit_indexer: u8 = 0b10000000 >> bit_index; if self.buffer[byte_index] & bit_indexer > 0 @@ -162,7 +176,7 @@ impl Bitmap pub fn set(&mut self, index: usize, value: bool) { let byte_index: usize = index / 8; - let bit_index: u8 = (index % 8).try_into().unwrap(); + let bit_index: u8 = (index % 8) as u8; let bit_indexer: u8 = 0b10000000 >> bit_index; self.buffer[byte_index] &= !bit_indexer; From 61ca725bcfcd480f53bf5122c9b7ef255454696d Mon Sep 17 00:00:00 2001 From: afrangio Date: Tue, 8 Mar 2022 19:59:42 +0100 Subject: [PATCH 09/19] bitmap: allow debug_print to have a lenght --- src/memory/pageframe.rs | 2 +- src/tools.rs | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index 5bd1578..6a02fba 100644 --- a/src/memory/pageframe.rs +++ b/src/memory/pageframe.rs @@ -94,7 +94,7 @@ impl PageFrameAllocator }; self.bitmap.erase(); - // self.bitmap.debug_print(); + // self.bitmap.debug_print(0); } } } diff --git a/src/tools.rs b/src/tools.rs index fffca0f..8dd4ba2 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -185,12 +185,22 @@ impl Bitmap self.buffer[byte_index] |= bit_indexer; } } - pub fn debug_print(&self) + pub fn debug_print(&self, len: usize) { + if len == 0 + { for i in 0..self.size { crate::logln!("{}", self.get(i)); } + } + else + { + for i in 0..len + { + crate::logln!("{}", self.get(i)); + } + } } pub fn erase(&mut self) { From 790bd54f43ef61574f2601f6bbc83d32df979f09 Mon Sep 17 00:00:00 2001 From: afrangio Date: Tue, 8 Mar 2022 20:42:14 +0100 Subject: [PATCH 10/19] mem: allocate bitmap according to memory size --- src/memory/mod.rs | 14 +++++++++----- src/memory/pageframe.rs | 11 ++++++----- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/memory/mod.rs b/src/memory/mod.rs index fc0544e..3589c21 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -11,19 +11,23 @@ extern "C" pub fn get_mem_size(mmap: *const MultibootTagMmap, mmap_size: usize) -> usize { - let mut mem_size_bytes: u64 = 0; + static mut MEM_SIZE_BYTES: u64 = 0; unsafe { + if MEM_SIZE_BYTES > 0 + { + return MEM_SIZE_BYTES as usize; + } crate::logln!("\x1B[33mmmap: {:#x?}\x1B[39m", (*mmap).entries(mmap_size)); for mmap_entry in (*mmap).entries(mmap_size) { - mem_size_bytes += mmap_entry.len as u64; + MEM_SIZE_BYTES += mmap_entry.len as u64; } - if mem_size_bytes > usize::MAX as u64 + 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 {}Mo of RAM, you have {}Mo installed", (usize::MAX / 1024) / 1024, (MEM_SIZE_BYTES / 1024) / 1024); } - return mem_size_bytes as usize; + return MEM_SIZE_BYTES as usize; } } diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index 6a02fba..afcb38f 100644 --- a/src/memory/pageframe.rs +++ b/src/memory/pageframe.rs @@ -1,6 +1,7 @@ use crate::multiboot::MultibootTagMmap; use crate::tools; use crate::page_index; +use crate::memory::get_mem_size; use core::ffi::c_void; @@ -32,7 +33,6 @@ impl PageFrameAllocator unusable_mem: 0, initialized: false, bitmap: tools::Bitmap {buffer: &mut[] as &'static mut[u8], size: 0}, - } } @@ -55,20 +55,21 @@ impl PageFrameAllocator } self.free_mem = crate::memory::get_mem_size(mmap, mmap_size); crate::logln!("[INFO] found {}Ko of memory", self.free_mem / 1024); - self.init_bitmap(kernel_end + 1); + self.init_bitmap(kernel_end + 16384); crate::logln!("[INFO] assigned {} pages to bitmap", self.bitmap.size); unsafe { for entry in (*mmap).entries(mmap_size) { - if entry.tag_type != 1 + if entry.tag_type != 1 && entry.addr < get_mem_size(mmap, mmap_size) as u32 { self.reserve_mem(page_index!(entry.addr as usize), page_index!(entry.len as usize)); } } } self.reserve_mem(page_index!(kernel_start), page_index!(kernel_end - kernel_start)); - self.reserve_mem(page_index!(kernel_end), page_index!(self.bitmap.size) / 8); + self.reserve_mem(page_index!(kernel_end), page_index!(16384)); + self.reserve_mem(page_index!(kernel_end + 16384), page_index!(self.bitmap.size / 8)); crate::logln!("[INFO] reserved pages: {} pages", self.reserved_mem / 4096); crate::logln!("[INFO] reserved mem: {}Ko", self.reserved_mem / 1024); } @@ -83,7 +84,7 @@ impl PageFrameAllocator } fn init_bitmap(&mut self, b: usize) { - let bitmap_size = usize::MAX / 4096; + let bitmap_size = page_index!(self.free_mem); unsafe { From 30e7e5f07050f2914654421d6d0c380869a6f506 Mon Sep 17 00:00:00 2001 From: afrangio Date: Thu, 10 Mar 2022 12:34:46 +0100 Subject: [PATCH 11/19] bitmap: implement core::ops::Index --- src/tools.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/tools.rs b/src/tools.rs index 8dd4ba2..82d4da6 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -159,6 +159,22 @@ pub struct Bitmap pub size: usize, // represents the number of bits, one byte = 8 bits } +impl core::ops::Index for Bitmap +{ + type Output = bool; + fn index<'a>(&'a self, index: usize) -> &'a bool + { + if self.get(index) + { + return &true; + } + else + { + return &false; + } + } +} + impl Bitmap { pub fn get(&self, index: usize) -> bool @@ -173,6 +189,7 @@ impl Bitmap } return false; } + pub fn set(&mut self, index: usize, value: bool) { let byte_index: usize = index / 8; From 90c085f0501dc4ebc8dbf43a874c21739bc87b6f Mon Sep 17 00:00:00 2001 From: afrangio Date: Thu, 10 Mar 2022 17:46:33 +0100 Subject: [PATCH 12/19] linker: add debug sections to reflect real kernel end --- src/arch/i686/linker.ld | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/arch/i686/linker.ld b/src/arch/i686/linker.ld index a9401ba..d0bd6a8 100644 --- a/src/arch/i686/linker.ld +++ b/src/arch/i686/linker.ld @@ -29,5 +29,21 @@ SECTIONS *(COMMON) *(.bss) } + .stab BLOCK(4K) : ALIGN(4K) + { + *(.stab) + } + .stabstr BLOCK(4K) : ALIGN(4K) + { + *(.stabstr) + } + .note BLOCK(4K) : ALIGN(4K) + { + *(.note) + } + .comment BLOCK(4K) : ALIGN(4K) + { + *(.comment) + } _kernel_end = .; } From bfeb1ee7d87720cd2d0d4e837d847817ab5657bc Mon Sep 17 00:00:00 2001 From: afrangio Date: Thu, 10 Mar 2022 17:47:17 +0100 Subject: [PATCH 13/19] mem: fix memory reservation according to new linker script --- src/memory/pageframe.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index afcb38f..14611a0 100644 --- a/src/memory/pageframe.rs +++ b/src/memory/pageframe.rs @@ -55,7 +55,7 @@ impl PageFrameAllocator } self.free_mem = crate::memory::get_mem_size(mmap, mmap_size); crate::logln!("[INFO] found {}Ko of memory", self.free_mem / 1024); - self.init_bitmap(kernel_end + 16384); + self.init_bitmap(kernel_end); crate::logln!("[INFO] assigned {} pages to bitmap", self.bitmap.size); unsafe { @@ -63,15 +63,17 @@ impl PageFrameAllocator { if entry.tag_type != 1 && entry.addr < get_mem_size(mmap, mmap_size) as u32 { + // reserve grub memmap entries marked as reserved self.reserve_mem(page_index!(entry.addr as usize), page_index!(entry.len as usize)); } } } + // reserve kernel space self.reserve_mem(page_index!(kernel_start), page_index!(kernel_end - kernel_start)); - self.reserve_mem(page_index!(kernel_end), page_index!(16384)); - self.reserve_mem(page_index!(kernel_end + 16384), page_index!(self.bitmap.size / 8)); + // reserve bitmap + self.reserve_mem(page_index!(kernel_end), page_index!(self.bitmap.size / 8)); crate::logln!("[INFO] reserved pages: {} pages", self.reserved_mem / 4096); - crate::logln!("[INFO] reserved mem: {}Ko", self.reserved_mem / 1024); + crate::logln!("[INFO] reserved mem: {}KiB", self.reserved_mem / 1024); } fn reserve_mem(&mut self, index: usize, len: usize) From a3694c5e93d14904d3d21a91457165f21c588c78 Mon Sep 17 00:00:00 2001 From: afrangio Date: Fri, 11 Mar 2022 15:02:43 +0100 Subject: [PATCH 14/19] mem: mark every page as reserved before unreserving Changes how the bitmap reserving works. Because GRUB does not give us the whole memory we have to mark usable memory only with hose that grub excplicitly marks as usable. And we have to keep the lower memory reserved. --- src/memory/pageframe.rs | 32 ++++++++++++++++++++++++-------- src/tools.rs | 2 +- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index 14611a0..bf35f6a 100644 --- a/src/memory/pageframe.rs +++ b/src/memory/pageframe.rs @@ -53,18 +53,20 @@ impl PageFrameAllocator kernel_start = &_kernel_start as *const _ as usize; kernel_end = &_kernel_end as *const _ as usize; } - self.free_mem = crate::memory::get_mem_size(mmap, mmap_size); - crate::logln!("[INFO] found {}Ko of memory", self.free_mem / 1024); + 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); crate::logln!("[INFO] assigned {} pages to bitmap", self.bitmap.size); unsafe { for entry in (*mmap).entries(mmap_size) { - if entry.tag_type != 1 && entry.addr < get_mem_size(mmap, mmap_size) as u32 + if (entry.tag_type == 1 && entry.addr < get_mem_size(mmap, mmap_size) as u32) && entry.addr != 0 { - // reserve grub memmap entries marked as reserved - self.reserve_mem(page_index!(entry.addr as usize), page_index!(entry.len as usize)); + // unreserve grub memmap entries marked as free except lower memory + crate::logln!("unreserving {} pages", page_index!(entry.len as usize)); + self.unreserve_mem(page_index!(entry.addr as usize), page_index!(entry.len as usize)); } } } @@ -80,13 +82,27 @@ impl PageFrameAllocator { for i in 0..len { - self.bitmap.set((index + i) as usize, true); - self.reserved_mem += 4096; + if self.bitmap[index + i] == false + { + self.bitmap.set(index + i, true); + self.reserved_mem += 4096; + self.free_mem -= 4096; + } + } + } + + fn unreserve_mem(&mut self, index: usize, len: usize) + { + for i in 0..len + { + self.bitmap.set(index + i, false); + self.reserved_mem -= 4096; + self.free_mem += 4096; } } fn init_bitmap(&mut self, b: usize) { - let bitmap_size = page_index!(self.free_mem); + let bitmap_size = self.reserved_mem / 4096; unsafe { diff --git a/src/tools.rs b/src/tools.rs index 82d4da6..f0c0254 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -223,7 +223,7 @@ impl Bitmap { for i in 0..self.size { - self.set(i, false); + self.set(i, true); } } } From 82f2d434f31679435a6cb4e390e531cbde02029f Mon Sep 17 00:00:00 2001 From: afrangio Date: Fri, 11 Mar 2022 15:08:26 +0100 Subject: [PATCH 15/19] mem: print some more information to the screen --- src/memory/pageframe.rs | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index bf35f6a..be0c190 100644 --- a/src/memory/pageframe.rs +++ b/src/memory/pageframe.rs @@ -71,11 +71,33 @@ impl PageFrameAllocator } } // reserve kernel space + 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); // 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!("[INFO] reserved pages: {} pages", self.reserved_mem / 4096); - crate::logln!("[INFO] reserved mem: {}KiB", self.reserved_mem / 1024); + } + + pub fn print_memusage(&self, level: usize) + { + + crate::logln!("[INFO] free mem: {}KiB", self.free_mem / 1024); + crate::logln!("[INFO] used mem: {}KiB", self.locked_mem / 1024); + if level >= 1 + { + crate::logln!("[INFO] reserved mem: {}KiB", self.reserved_mem / 1024); + } + if level >= 2 + { + crate::logln!("[INFO] reserved pages: {} pages", self.reserved_mem / 4096); + crate::logln!("[INFO] used pages: {} pages", self.locked_mem / 4096); + } + if level >= 3 + { + crate::logln!("excepted levels for print_memusage() are 0, 1 or 2."); + } } fn reserve_mem(&mut self, index: usize, len: usize) @@ -103,6 +125,7 @@ impl PageFrameAllocator fn init_bitmap(&mut self, b: usize) { let bitmap_size = self.reserved_mem / 4096; + crate::logln!("[INFO] bitmap location: {:#x}", b); unsafe { @@ -113,7 +136,7 @@ impl PageFrameAllocator }; self.bitmap.erase(); - // self.bitmap.debug_print(0); + // self.bitmap.debug_print(256); } } } From 33bc230077f001a22bc55d183dc428d86386463f Mon Sep 17 00:00:00 2001 From: afrangio Date: Fri, 11 Mar 2022 15:09:02 +0100 Subject: [PATCH 16/19] mem: fix bitmap size --- src/memory/pageframe.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index be0c190..5fa709c 100644 --- a/src/memory/pageframe.rs +++ b/src/memory/pageframe.rs @@ -132,7 +132,7 @@ impl PageFrameAllocator self.bitmap = tools::Bitmap { buffer: core::slice::from_raw_parts_mut (b as *mut u8, (bitmap_size / 8) + 8), - size: bitmap_size + 1, + size: bitmap_size, }; self.bitmap.erase(); From 7cc235fd26188b2ae526a923052c81570588e052 Mon Sep 17 00:00:00 2001 From: afrangio Date: Fri, 11 Mar 2022 15:09:16 +0100 Subject: [PATCH 17/19] mem: add ability to request, free and lock a page --- src/memory/pageframe.rs | 52 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index 5fa709c..52c260f 100644 --- a/src/memory/pageframe.rs +++ b/src/memory/pageframe.rs @@ -80,6 +80,20 @@ impl PageFrameAllocator self.reserve_mem(page_index!(kernel_end), page_index!(self.bitmap.size / 8)); } + pub fn request_free_page(&mut self) -> usize + { + for i in 0..self.bitmap.size + { + if self.bitmap.get(i) == false + { + crate::logln!("locking page {}", i); + self.lock_page(i); + return i * 0x1000; + } + } + 0 + } + pub fn print_memusage(&self, level: usize) { @@ -122,6 +136,44 @@ impl PageFrameAllocator self.free_mem += 4096; } } + fn lock_pages(&mut self, index: usize, len: usize) + { + for i in 0..len + { + self.lock_page(index + i); + } + } + + fn lock_page(&mut self, index: usize) + { + self.bitmap.set(index, true); + self.locked_mem += 4096; + self.free_mem -= 4096; + } + + pub fn unlock_page(&mut self, index: usize) + { + if self.bitmap[index] == true + { + crate::logln!("unlocking page {}", index); + self.bitmap.set(index, false); + self.free_mem += 4096; + self.locked_mem -= 4096; + } + else + { + crate::logln!("page {} already unlocked", index); + } + } + + fn unlock_pages(&mut self, index: usize, len: usize) + { + for i in 0..len + { + self.unlock_page(index + i); + } + } + fn init_bitmap(&mut self, b: usize) { let bitmap_size = self.reserved_mem / 4096; From 760c4762fbf8e697286b7d5392f98dddde28ca2e Mon Sep 17 00:00:00 2001 From: afrangio Date: Sun, 13 Mar 2022 17:57:36 +0100 Subject: [PATCH 18/19] mem: add free_page function that unlock a page from address --- src/memory/pageframe.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index 52c260f..94b687f 100644 --- a/src/memory/pageframe.rs +++ b/src/memory/pageframe.rs @@ -94,6 +94,19 @@ impl PageFrameAllocator 0 } + pub fn free_page(&mut self, address: usize) + { + let index = address / 0x1000; + if self.bitmap[index] + { + self.unlock_page(index); + } + else + { + crate::logln!("page at address {:#x} already freed", address); + } + } + pub fn print_memusage(&self, level: usize) { @@ -151,7 +164,7 @@ impl PageFrameAllocator self.free_mem -= 4096; } - pub fn unlock_page(&mut self, index: usize) + fn unlock_page(&mut self, index: usize) { if self.bitmap[index] == true { From 2d471beb6f8f2c8e12af5798c1efb3632e26045e Mon Sep 17 00:00:00 2001 From: afrangio Date: Mon, 14 Mar 2022 12:10:48 +0100 Subject: [PATCH 19/19] mem: rename PageFrameAllocator to Allocator Since the mod is already named pageframe, allocator is enough to be called pageframe::Allocator --- src/elsos.rs | 2 +- src/memory/pageframe.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/elsos.rs b/src/elsos.rs index 54a2db8..a622959 100644 --- a/src/elsos.rs +++ b/src/elsos.rs @@ -44,7 +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::PageFrameAllocator = memory::pageframe::PageFrameAllocator::new(); + let mut alloc: memory::pageframe::Allocator = memory::pageframe::Allocator::new(); unsafe { alloc.read_grub_mmap(MULTIBOOT_MMAP, MULTIBOOT_MMAP_ENTRIES); } init_serial(); logln!("\n"); diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index 94b687f..772f045 100644 --- a/src/memory/pageframe.rs +++ b/src/memory/pageframe.rs @@ -11,7 +11,7 @@ extern "C" static _kernel_end: c_void; } -pub struct PageFrameAllocator +pub struct Allocator { pub free_mem: usize, pub locked_mem: usize, @@ -21,11 +21,11 @@ pub struct PageFrameAllocator bitmap: tools::Bitmap, } -impl PageFrameAllocator +impl Allocator { - pub fn new() -> PageFrameAllocator + pub fn new() -> Allocator { - PageFrameAllocator + Allocator { free_mem: 0, locked_mem: 0,