From 31ecc242abc9627a28282f2f765d31377668a28a Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Thu, 14 Apr 2022 00:02:05 +0200 Subject: [PATCH 01/16] makefile: add revision to version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5906d7a..8db2634 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ VERSION=0 PATCHLEVEL=0 SUBLEVEL=3 -EXTRAVERSION= +EXTRAVERSION=-$(shell git rev-parse HEAD | head -c 7) export VERSION PATCHLEVEL SUBLEVEL EXTRAVERSION From 33826877ba747c726485968f83a8bc8be5dcf3c9 Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Thu, 14 Apr 2022 00:03:02 +0200 Subject: [PATCH 02/16] bitmap: check free pages 32bits at once --- src/ferramenta.rs | 13 ++++++++++++- src/memory/pageframe.rs | 16 +++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/ferramenta.rs b/src/ferramenta.rs index bab46f9..94f3452 100644 --- a/src/ferramenta.rs +++ b/src/ferramenta.rs @@ -190,6 +190,17 @@ impl Bitmap return false; } + pub fn get_chunk32(&self, index: usize) -> u32 + { + let mut chunk: u32 = 0; + + for i in 0..4 + { + chunk += self.buffer[index * 4 + i] as u32; + } + chunk + } + pub fn set(&mut self, index: usize, value: bool) { let byte_index: usize = index / 8; @@ -248,4 +259,4 @@ pub fn align(val: usize, bound: usize) -> usize pub fn in_range(input: usize, start: usize, range: usize) -> bool { input >= start && input < start + range -} \ No newline at end of file +} diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index a4e371d..1730244 100644 --- a/src/memory/pageframe.rs +++ b/src/memory/pageframe.rs @@ -90,7 +90,21 @@ impl Allocator pub fn request_free_page(&mut self, kernel_space: bool) -> usize { - for i in 0..self.bitmap.size + let mut occupied_chunks = 0; + + for i in 0..self.bitmap.size / 32 + { + if !kernel_space && ferramenta::in_range(i * 32, KERNEL_SPACE_START, KERNEL_SPACE_RANGE) + { + continue; + } + if self.bitmap.get_chunk32(i) != 0xffff_ffff + { + occupied_chunks = i; + break; + } + } + for i in (occupied_chunks as usize * 32)..self.bitmap.size { if !kernel_space && ferramenta::in_range(i, KERNEL_SPACE_START, KERNEL_SPACE_RANGE) { From 4b0ed2621a7d66dcd91ec97d0d84f2a5951a012e Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Thu, 14 Apr 2022 14:17:09 +0200 Subject: [PATCH 03/16] panic: add oops --- src/elsos.rs | 47 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/src/elsos.rs b/src/elsos.rs index 82e28ee..270bc60 100644 --- a/src/elsos.rs +++ b/src/elsos.rs @@ -86,6 +86,14 @@ fn panic(info: &PanicInfo) -> ! vga::panic(); logln!("\n\x1B[31;49m{}\x1B[39;49m\n", info); + print_memory_state(false); + + logln!(""); + loop {} +} + +fn print_memory_state(serial_only: bool) +{ let eax: u32; let ebx: u32; let ecx: u32; @@ -109,24 +117,49 @@ fn panic(info: &PanicInfo) -> ! ebp = crate::get_reg!("ebp"); } - logln!("eax: {:08x} ebx: {:08x} ecx: {:08x} edx: {:08x}", eax, ebx, ecx, edx); - logln!("esi: {:08x} edi: {:08x} esp: {:08x} ebp: {:08x}", esi, edi, esp, ebp); + if !serial_only + { + crate::vga_println!("eax: {:08x} ebx: {:08x} ecx: {:08x} edx: {:08x}", eax, ebx, ecx, edx); + crate::vga_println!("esi: {:08x} edi: {:08x} esp: {:08x} ebp: {:08x}", esi, edi, esp, ebp); + } + crate::serial_println!("eax: {:08x} ebx: {:08x} ecx: {:08x} edx: {:08x}", eax, ebx, ecx, edx); + crate::serial_println!("esi: {:08x} edi: {:08x} esp: {:08x} ebp: {:08x}", esi, edi, esp, ebp); - log!("\nstack: "); + if !serial_only + { + crate::vga_print!("\nstack: "); + } + crate::serial_print!("\nstack: "); for i in 0..24 { unsafe { - log!("{:08x} ", *(esp as *const u32).add(i * 4)); + if !serial_only + { + crate::vga_print!("{:08x} ", *(esp as *const u32).add(i * 4)); + } + crate::serial_print!("{:08x} ", *(esp as *const u32).add(i * 4)); if (i + 1) % 8 == 0 { - log!("\n "); + if !serial_only + { + crate::vga_print!("\n "); + } + crate::serial_print!("\n "); } } } +} - logln!(""); - loop {} +#[macro_export] +macro_rules! oops +{ + ($($arg:tt)*) => + { + $crate::logln!("\x1B[33;49moops at '{}', {}:{}:{}\x1B[39;49m\n", format_args!($($arg)*), file!(), line!(), column!()); + $crate::print_memory_state(true); + $crate::serial_println!(""); + } } #[macro_export] From a8a848f55d0d19ce9c001f84f1a7890a14104ae6 Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Thu, 14 Apr 2022 23:18:45 +0200 Subject: [PATCH 04/16] pagetable: create global PT manager with last_mapped and heap_start --- src/memory/pageframe.rs | 2 +- src/memory/pagetable.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index 1730244..ee4daf7 100644 --- a/src/memory/pageframe.rs +++ b/src/memory/pageframe.rs @@ -112,7 +112,7 @@ impl Allocator } if self.bitmap.get(i) == false { - crate::logln!("locking page {}", i); + crate::serial_println!("locking page {}", i); self.lock_page(i); return i * 0x1000; } diff --git a/src/memory/pagetable.rs b/src/memory/pagetable.rs index 75bf404..8fc8c83 100644 --- a/src/memory/pagetable.rs +++ b/src/memory/pagetable.rs @@ -32,10 +32,26 @@ pub struct Manager pub page_directory: &'static mut [page::DirectoryEntry], paging_enabled: bool, flags: usize, + pub memory_start: usize, + pub heap_start: usize, + pub last_mapped: usize } impl Manager { + pub const fn uninitialized() -> Manager + { + Manager + { + page_directory: &mut [], + paging_enabled: false, + flags: 0, + memory_start: 0, + heap_start: 0, + last_mapped: 0 + } + } + pub fn new(addr: usize, flags: usize) -> Manager { unsafe @@ -46,6 +62,9 @@ impl Manager page_directory: core::slice::from_raw_parts_mut(addr as *mut page::DirectoryEntry, 1024), paging_enabled: false, flags: flags, + memory_start: 0, + heap_start: 0, + last_mapped: 0 }; manager.page_directory[1023].set_addr(addr as u32); manager.page_directory[1023].set_rw(true); @@ -104,6 +123,15 @@ impl Manager 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); + if v_addr != phys_addr + { + if self.heap_start == 0 + { + self.heap_start = v_addr; + crate::serial_println!("[INFO] heap start at {:#08x}", self.heap_start); + } + self.last_mapped = v_addr; + } } fn address(&self, page_directory_index: usize) -> u32 From 39291c909a7df009357ae67b40e158f95f4b1e6e Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Thu, 14 Apr 2022 23:23:34 +0200 Subject: [PATCH 05/16] bitmap: search for n contiguous pages at once --- src/ferramenta.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/ferramenta.rs b/src/ferramenta.rs index 94f3452..f1bbf5f 100644 --- a/src/ferramenta.rs +++ b/src/ferramenta.rs @@ -190,6 +190,18 @@ impl Bitmap return false; } + pub fn get_n_pages(&self, index: usize, n: usize) -> usize + { + for i in index..index + n + { + if self.get(i) + { + return i; + } + } + 0 + } + pub fn get_chunk32(&self, index: usize) -> u32 { let mut chunk: u32 = 0; From 964106218d5b02b8eb5fcd691140d795d9a27eb2 Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Thu, 14 Apr 2022 18:04:07 +0200 Subject: [PATCH 06/16] pageframe: allocate n contiguous pages --- src/memory/mod.rs | 4 +++ src/memory/pageframe.rs | 68 ++++++++++++++++++++++++++--------------- 2 files changed, 47 insertions(+), 25 deletions(-) diff --git a/src/memory/mod.rs b/src/memory/mod.rs index 53c9a2f..7047c95 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -5,6 +5,10 @@ mod page; use crate::multiboot::MultibootTagMmap; use pagetable::flags::*; +// In pages, * PAGE_SIZE to get memory sizes +const KERNEL_SPACE_START: usize = 0x0000_0000; +const KERNEL_SPACE_RANGE: usize = 0x0000_2000; + static PAGE_SIZE: usize = 4096; pub fn get_mem_size(mmap: *const MultibootTagMmap, mmap_size: usize) -> usize diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index ee4daf7..f8171f6 100644 --- a/src/memory/pageframe.rs +++ b/src/memory/pageframe.rs @@ -2,7 +2,7 @@ use crate::multiboot::MultibootTagMmap; use crate::ferramenta; use crate::page_index; use crate::memory::get_mem_size; -use super::PAGE_SIZE; +use super::{KERNEL_SPACE_START, KERNEL_SPACE_RANGE, PAGE_SIZE}; use core::ffi::c_void; @@ -12,9 +12,6 @@ extern "C" static _kernel_end: c_void; } -const KERNEL_SPACE_START: usize = 0x0000_0000; -const KERNEL_SPACE_RANGE: usize = 0x0000_2000; - pub struct Allocator { pub free_mem: usize, @@ -86,38 +83,59 @@ 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!("[INFO] kernel space : {:#08x} - {:#08x}", PAGE_SIZE * KERNEL_SPACE_START, PAGE_SIZE * (KERNEL_SPACE_START + KERNEL_SPACE_RANGE)); } - pub fn request_free_page(&mut self, kernel_space: bool) -> usize + pub fn request_free_pages(&mut self, n: usize, kernel_space: bool) -> usize { - let mut occupied_chunks = 0; - - for i in 0..self.bitmap.size / 32 + let mut first_page = 0; + let start = if kernel_space { - if !kernel_space && ferramenta::in_range(i * 32, KERNEL_SPACE_START, KERNEL_SPACE_RANGE) - { - continue; - } - if self.bitmap.get_chunk32(i) != 0xffff_ffff - { - occupied_chunks = i; - break; - } + 0 } - for i in (occupied_chunks as usize * 32)..self.bitmap.size + else + { + KERNEL_SPACE_START + KERNEL_SPACE_RANGE + }; + let end = if kernel_space { - if !kernel_space && ferramenta::in_range(i, KERNEL_SPACE_START, KERNEL_SPACE_RANGE) + KERNEL_SPACE_START + KERNEL_SPACE_RANGE - 1 + } + else + { + self.bitmap.size + }; + + let mut i = start; + while i < end + { + i += 1; + + let next_i = self.bitmap.get_n_pages(i, n); + if next_i == 0 { - continue; + for j in i..i + n + { + crate::serial_println!("locking page {}", j); + self.lock_page(j); + if first_page == 0 + { + first_page = j * 0x1000; + } + } + break } - if self.bitmap.get(i) == false + else { - crate::serial_println!("locking page {}", i); - self.lock_page(i); - return i * 0x1000; + i = next_i } } - 0 + first_page + } + + pub fn request_free_page(&mut self, kernel_space: bool) -> usize + { + self.request_free_pages(1, kernel_space) } pub fn free_page(&mut self, address: usize) From 3c6094f1f481b9bf519b4645bc1baacaf66da1fe Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Thu, 14 Apr 2022 23:19:21 +0200 Subject: [PATCH 07/16] malloc: initial k/vmalloc, free and size_of --- src/memory/malloc.rs | 340 +++++++++++++++++++++++++++++++++++++++++++ src/memory/mod.rs | 24 ++- 2 files changed, 362 insertions(+), 2 deletions(-) create mode 100644 src/memory/malloc.rs diff --git a/src/memory/malloc.rs b/src/memory/malloc.rs new file mode 100644 index 0000000..503b964 --- /dev/null +++ b/src/memory/malloc.rs @@ -0,0 +1,340 @@ +use core::cmp::max; +use core::ffi::c_void; +use super::pageframe; +use super::pagetable; +use super::PAGE_SIZE; +use super::PT_MANAGER; +use crate::ferramenta; +use crate::libc; + +#[repr(align(0x10))] +struct AllocHeader +{ + magic: u16, + size: usize, + freed: bool +} + +pub fn kmalloc(size: usize) -> *mut c_void +{ + let size = ferramenta::align(size, 0x10); + let pt_manager: &mut pagetable::Manager = unsafe + { + &mut PT_MANAGER + }; + + let address = next_available_space(pt_manager.memory_start, size, true); + + if address == 0 + { + crate::oops!("kernel space out of memory"); + return core::ptr::null_mut::(); + } + let header: *mut AllocHeader = address as *mut _; + + unsafe + { + (*header).magic = 0x4242; + (*header).size = size; + (*header).freed = false; + } + (address + core::mem::size_of::()) as *mut c_void +} + +pub fn kzalloc(size: usize) -> *mut c_void +{ + let address = kmalloc(size); + + if address != core::ptr::null_mut::() + { + unsafe + { + libc::memset(address, 0, size); + } + } + address +} + +pub fn kfree(address: *mut c_void) +{ + free(address, true); +} + +pub fn ksize(address: *mut c_void) -> usize +{ + size_of(address, true) +} + +pub fn vmalloc(size: usize) -> *mut c_void +{ + let size = ferramenta::align(size, 0x10); + let pt_manager: &mut pagetable::Manager = unsafe + { + &mut PT_MANAGER + }; + + let mut address = next_available_space(pt_manager.heap_start, size, false); + + if address == 0 + { + if let Some(new_address) = expand_heap(200) + { + address = new_address as usize; + } + else + { + crate::oops!("virtual memory out of memory"); + return core::ptr::null_mut::(); + } + } + let header: *mut AllocHeader = address as *mut _; + + unsafe + { + (*header).magic = 0x4242; + (*header).size = size; + (*header).freed = false; + } + (address + core::mem::size_of::()) as *mut c_void +} + +pub fn vzalloc(size: usize) -> *mut c_void +{ + let address = vmalloc(size); + + if address != core::ptr::null_mut::() + { + unsafe + { + libc::memset(address, 0, size); + } + } + address +} + +pub fn vfree(address: *mut c_void) +{ + free(address, false); +} + +pub fn vsize(address: *mut c_void) -> usize +{ + size_of(address, false) +} + +// Private functions + +fn next_available_space(address: usize, size: usize, kernel_space: bool) -> usize +{ + let pt_manager: &mut pagetable::Manager = unsafe + { + &mut PT_MANAGER + }; + let total_size = size + core::mem::size_of::(); + let mut max_i = if kernel_space + { + super::KERNEL_SPACE_START * PAGE_SIZE + super::KERNEL_SPACE_RANGE * PAGE_SIZE - pt_manager.memory_start + } + else + { + pt_manager.last_mapped + 0x1000 - pt_manager.heap_start + }; + let mut i = 0x0; + + loop + { + while i + total_size > max_i + { + let pages = max(total_size / PAGE_SIZE, 1); + crate::logln!("trying to get {} pages", pages); + if let Some(_) = expand_heap(pages) + { + max_i = pt_manager.last_mapped + 0x1000 - pt_manager.heap_start; + } + else + { + return 0; + } + } + unsafe + { + let header: *mut AllocHeader = (address + i) as *mut _; + + if (*header).magic == 0x4242 + { + if (*header).freed + { + merge_next_blocks(get_block_for(&*header), kernel_space); + if (*header).size > size + { + let new_address = address + i + core::mem::size_of::(); + let could_break = break_block(new_address as *mut c_void, size, kernel_space); + + if could_break + { + return header as usize; + } + } + else if (*header).size == size + { + return header as usize; + } + } + } + else + { + return address + i; + } + i += (*header).size + core::mem::size_of::(); + } + } +} + +fn free(address: *mut c_void, kernel_space: bool) +{ + if address != core::ptr::null_mut::() + { + if let Some(header) = get_header_for(address, kernel_space) + { + if header.freed + { + crate::oops!("double free"); + } + else + { + header.freed = true; + merge_next_blocks(address, kernel_space); + } + } + } +} + +fn size_of(address: *mut c_void, kernel_space: bool) -> usize +{ + if let Some(header) = get_header_for(address, kernel_space) + { + header.size + } + else + { + 0 + } +} + +fn get_header_for(address: *mut c_void, kernel_space: bool) -> Option<&'static mut AllocHeader> +{ + let pt_manager: &mut pagetable::Manager = unsafe + { + &mut PT_MANAGER + }; + let lowest_address = if kernel_space + { + pt_manager.memory_start + core::mem::size_of::() + } + else + { + pt_manager.heap_start + core::mem::size_of::() + }; + let highest_address = if kernel_space + { + PAGE_SIZE * (super::KERNEL_SPACE_START + super::KERNEL_SPACE_RANGE) + } + else + { + pt_manager.last_mapped + PAGE_SIZE + }; + if (address as usize) < lowest_address + { + crate::oops!("cannot get memory header under heap_start ({:#08x}) (address: {:#08x})", lowest_address, address as usize); + return None; + } + if (address as usize) > highest_address + { + crate::oops!("cannot get memory over memory end ({:#08x}) (address: {:#08x})", highest_address, address as usize); + return None; + } + unsafe + { + Some(&mut *((address as usize - core::mem::size_of::()) as *mut _)) + } +} + +fn get_block_for(header_address: &AllocHeader) -> *mut c_void +{ + (header_address as *const _ as usize + core::mem::size_of::()) as *mut c_void +} + +fn expand_heap(pages: usize) -> Option<*mut c_void> +{ + let pt_manager = unsafe + { + &mut PT_MANAGER + }; + let alloc = pageframe::Allocator::shared(); + let new_page = alloc.request_free_pages(max(pages, 1), false); + + if new_page != 0 + { + for i in 0..pages + { + pt_manager.memory_map(pt_manager.last_mapped + PAGE_SIZE, new_page + i * PAGE_SIZE); + unsafe + { + libc::memset((pt_manager.last_mapped) as *mut c_void, 0, PAGE_SIZE); + } + } + return Some(new_page as *mut c_void); + } + None +} + +fn break_block(address: *mut c_void, new_size: usize, kernel_space: bool) -> bool +{ + if let Some(header) = get_header_for(address, kernel_space) + { + let old_size = header.size; + + if old_size - new_size > core::mem::size_of::() + { + let new_header: &'static mut AllocHeader = unsafe + { + &mut *((address as usize + new_size) as *mut _) + }; + + header.size = new_size; + new_header.magic = 0x4242; + new_header.size = old_size - new_size - core::mem::size_of::(); + new_header.freed = true; + + return true; + } + } + false +} + +fn merge_next_blocks(address: *mut c_void, kernel_space: bool) +{ + if let Some(header) = get_header_for(address, kernel_space) + { + loop + { + let size = header.size; + let next_header: &'static mut AllocHeader = unsafe + { + &mut *((address as usize + size) as *mut _) + }; + + if next_header.magic == 0x4242 && next_header.freed + { + header.size += core::mem::size_of::() + next_header.size; + next_header.magic = 0; + next_header.size = 0; + next_header.freed = false; + } + else + { + break; + } + } + } +} diff --git a/src/memory/mod.rs b/src/memory/mod.rs index 7047c95..9bcfe72 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -1,15 +1,20 @@ +pub mod malloc; mod pageframe; mod pagetable; mod page; use crate::multiboot::MultibootTagMmap; +use crate::libc; +use crate::ferramenta; use pagetable::flags::*; +pub use malloc::*; // In pages, * PAGE_SIZE to get memory sizes const KERNEL_SPACE_START: usize = 0x0000_0000; const KERNEL_SPACE_RANGE: usize = 0x0000_2000; static PAGE_SIZE: usize = 4096; +static mut PT_MANAGER: pagetable::Manager = pagetable::Manager::uninitialized(); pub fn get_mem_size(mmap: *const MultibootTagMmap, mmap_size: usize) -> usize { @@ -50,8 +55,17 @@ pub fn init(mmap: *const MultibootTagMmap, mmap_size: usize) pt_manager.enable_paging(); } let page = alloc.request_free_page(false); - crate::logln!("requested page userspace: {:#0X}", page); - pt_manager.memory_map(0x150000, page); + let virtual_page = PAGE_SIZE * (KERNEL_SPACE_START + KERNEL_SPACE_RANGE); + pt_manager.memory_map(virtual_page, page); + unsafe + { + libc::memset(virtual_page as *mut _, 0, PAGE_SIZE); + } + + unsafe + { + PT_MANAGER = pt_manager; + } } fn id_map(pt_manager: &mut pagetable::Manager) @@ -60,11 +74,17 @@ fn id_map(pt_manager: &mut pagetable::Manager) let mut memory_start = alloc.bitmap.buffer as *const _ as *const usize as usize; memory_start += alloc.bitmap.buffer.len(); + pt_manager.memory_start = ferramenta::align(memory_start, PAGE_SIZE); for i in 0..memory_start / PAGE_SIZE { pt_manager.memory_map(i * PAGE_SIZE, i * PAGE_SIZE); alloc.lock_page(i); } + for i in memory_start / PAGE_SIZE..KERNEL_SPACE_START + KERNEL_SPACE_RANGE + { + pt_manager.memory_map(i * PAGE_SIZE, i * PAGE_SIZE); + alloc.lock_page(i); + } } extern "C" From 68ec7d497026ddf923933b6e1508138c4da0a777 Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Thu, 14 Apr 2022 00:04:33 +0200 Subject: [PATCH 08/16] commands: add km (arbitrary kmalloc) and free --- src/tty/basic_commands.rs | 51 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/src/tty/basic_commands.rs b/src/tty/basic_commands.rs index 990829e..735d8d9 100644 --- a/src/tty/basic_commands.rs +++ b/src/tty/basic_commands.rs @@ -1,6 +1,8 @@ use core::arch::asm; +use core::ffi::c_void; use crate::ferramenta; use crate::vga; +use crate::memory; pub fn execute(command: &str) { @@ -25,7 +27,7 @@ pub fn execute(command: &str) let command = &command[..command_end]; match command { - "pm" | "pb" => + "pm" | "pb" | "km" | "vm" | "kfree" | "vfree" => { let address = u32::from_str_radix(arg, 16) .unwrap_or_else(|_| @@ -38,6 +40,10 @@ pub fn execute(command: &str) { "pm" => printmem_at(address as *const u8, false), "pb" => printmem_at(address as *const u8, true), + "km" => allocate(address as usize, true), + "vm" => allocate(address as usize, false), + "kfree" => free(address as *mut c_void, true), + "vfree" => free(address as *mut c_void, false), _ => {} }; } @@ -105,6 +111,49 @@ fn printmem_at(address: *const u8, binary: bool) } } +fn allocate(size: usize, kernel_space: bool) +{ + let address = if kernel_space + { + memory::kmalloc(size) + } + else + { + memory::vmalloc(size) + }; + + let size = if kernel_space + { + memory::ksize(address) + } + else + { + memory::vsize(address) + }; + crate::logln!("allocated {} ({:#0x}) bytes at {:#08x}", size, size, address as usize); +} + +fn free(address: *mut c_void, kernel_space: bool) +{ + let size = if kernel_space + { + memory::ksize(address) + } + else + { + memory::vsize(address) + }; + if kernel_space + { + memory::kfree(address); + } + else + { + memory::vfree(address); + } + crate::logln!("freeed {} ({:#0x}) bytes at {:#08x}", size, size, address as usize); +} + fn print_stack() { unsafe From 699194c9cd67f4bece4c2a37e92996c0e09d3a7f Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Sat, 23 Apr 2022 19:02:33 +0200 Subject: [PATCH 09/16] makefile: update qemu commands --- Makefile | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 8db2634..37a924d 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,9 @@ RUST_KERNEL=target/$(TARGET)/$(DEBUG_RELEASE)/libelsos.a LD=$(ARCH)-elf-ld CC=$(ARCH)-elf-gcc AR=$(ARCH)-elf-ar +QEMU=qemu-system-i386 +QEMU_ARGS=-drive format=raw,file=$(ISO) -serial stdio +QEMU_MEMORY=-m 500M CFLAGS=-m32 -std=gnu99 -ffreestanding -Wall -Wextra -c ARFLAGS=rcs @@ -37,13 +40,13 @@ LIBC_A=build/libc/libc.a all: $(KERNEL) run: $(ISO) - qemu-system-i386 -drive format=raw,file=$(ISO) -serial stdio + $(QEMU) $(QEMU_ARGS) $(QEMU_MEMORY) rund: $(ISO) - qemu-system-i386 -drive format=raw,file=$(ISO) -serial stdio -d int + $(QEMU) $(QEMU_ARGS) $(QEMU_MEMORY) -d int rundd: $(ISO) - qemu-system-i386 -drive format=raw,file=$(ISO) -serial stdio -d int -s -S + $(QEMU) $(QEMU_ARGS) $(QEMU_MEMORY) -d int -s -S iso: $(ISO) From 3f103160ecc819889e6fde91dd9de158d32c7826 Mon Sep 17 00:00:00 2001 From: afrangio Date: Mon, 25 Apr 2022 17:46:15 +0200 Subject: [PATCH 10/16] malloc: fix zalloc alignment --- src/memory/malloc.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/memory/malloc.rs b/src/memory/malloc.rs index 503b964..7b2eef2 100644 --- a/src/memory/malloc.rs +++ b/src/memory/malloc.rs @@ -43,6 +43,7 @@ pub fn kmalloc(size: usize) -> *mut c_void pub fn kzalloc(size: usize) -> *mut c_void { + let size = ferramenta::align(size, 0x10); let address = kmalloc(size); if address != core::ptr::null_mut::() @@ -100,6 +101,7 @@ pub fn vmalloc(size: usize) -> *mut c_void pub fn vzalloc(size: usize) -> *mut c_void { + let size = ferramenta::align(size, 0x10); let address = vmalloc(size); if address != core::ptr::null_mut::() From 29b0b215f0ac5bc05f417dc388363469b8d10a17 Mon Sep 17 00:00:00 2001 From: afrangio Date: Mon, 25 Apr 2022 17:47:53 +0200 Subject: [PATCH 11/16] pagetable: reserve PD and PT pages in kernel space --- src/memory/mod.rs | 4 ++++ src/memory/pagetable.rs | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/memory/mod.rs b/src/memory/mod.rs index 9bcfe72..f993db1 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -46,6 +46,7 @@ pub fn init(mmap: *const MultibootTagMmap, mmap_size: usize) let page_directory_addr = alloc.request_free_page(true); let mut pt_manager = pagetable::Manager::new(page_directory_addr, PDE_RW); + pt_manager.page_count = alloc.bitmap.size; id_map(&mut pt_manager); alloc.print_memusage(1); unsafe @@ -83,6 +84,9 @@ fn id_map(pt_manager: &mut pagetable::Manager) for i in memory_start / PAGE_SIZE..KERNEL_SPACE_START + KERNEL_SPACE_RANGE { pt_manager.memory_map(i * PAGE_SIZE, i * PAGE_SIZE); + } + for i in pt_manager.page_count / 1024 + 2 + memory_start / PAGE_SIZE..KERNEL_SPACE_START + KERNEL_SPACE_RANGE + { alloc.lock_page(i); } } diff --git a/src/memory/pagetable.rs b/src/memory/pagetable.rs index 8fc8c83..75afec5 100644 --- a/src/memory/pagetable.rs +++ b/src/memory/pagetable.rs @@ -33,6 +33,7 @@ pub struct Manager paging_enabled: bool, flags: usize, pub memory_start: usize, + pub page_count: usize, pub heap_start: usize, pub last_mapped: usize } @@ -47,6 +48,7 @@ impl Manager paging_enabled: false, flags: 0, memory_start: 0, + page_count: 0, heap_start: 0, last_mapped: 0 } @@ -63,6 +65,7 @@ impl Manager paging_enabled: false, flags: flags, memory_start: 0, + page_count: 0, heap_start: 0, last_mapped: 0 }; From 776fa71a1ecea9efee965e25a4cd2491fecd0ff1 Mon Sep 17 00:00:00 2001 From: afrangio Date: Mon, 25 Apr 2022 17:48:42 +0200 Subject: [PATCH 12/16] malloc: start kmalloc after PD and PT pages --- src/memory/malloc.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/memory/malloc.rs b/src/memory/malloc.rs index 7b2eef2..997ee02 100644 --- a/src/memory/malloc.rs +++ b/src/memory/malloc.rs @@ -23,7 +23,8 @@ pub fn kmalloc(size: usize) -> *mut c_void &mut PT_MANAGER }; - let address = next_available_space(pt_manager.memory_start, size, true); + let start = pt_manager.memory_start + PAGE_SIZE * (pt_manager.page_count / 1024 + 2); + let address = next_available_space(start, size, true); if address == 0 { From 728bb378bea1d3bfb2fc8fe86f781fba47a0a3a5 Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Mon, 2 May 2022 17:24:12 +0200 Subject: [PATCH 13/16] makefile: add re rule --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index 37a924d..e8edf0b 100644 --- a/Makefile +++ b/Makefile @@ -87,3 +87,5 @@ clean: mrproper: clean cargo clean +re: mrproper + make all From 63e59268e9f743ad19276fa44d21a66482cb8b8e Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Wed, 27 Apr 2022 15:58:02 +0200 Subject: [PATCH 14/16] memory: rework malloc code structure --- src/memory/malloc.rs | 179 ++++++++++++++++++++++------------------ src/memory/mod.rs | 11 ++- src/memory/pageframe.rs | 26 +++--- src/memory/pagetable.rs | 8 +- 4 files changed, 126 insertions(+), 98 deletions(-) diff --git a/src/memory/malloc.rs b/src/memory/malloc.rs index 997ee02..bdd6058 100644 --- a/src/memory/malloc.rs +++ b/src/memory/malloc.rs @@ -4,6 +4,7 @@ use super::pageframe; use super::pagetable; use super::PAGE_SIZE; use super::PT_MANAGER; +use super::MemorySpace; use crate::ferramenta; use crate::libc; @@ -24,21 +25,14 @@ pub fn kmalloc(size: usize) -> *mut c_void }; let start = pt_manager.memory_start + PAGE_SIZE * (pt_manager.page_count / 1024 + 2); - let address = next_available_space(start, size, true); + let address = next_available_space(start, size, MemorySpace::Kernel); if address == 0 { crate::oops!("kernel space out of memory"); return core::ptr::null_mut::(); } - let header: *mut AllocHeader = address as *mut _; - - unsafe - { - (*header).magic = 0x4242; - (*header).size = size; - (*header).freed = false; - } + create_header(address, size); (address + core::mem::size_of::()) as *mut c_void } @@ -59,12 +53,12 @@ pub fn kzalloc(size: usize) -> *mut c_void pub fn kfree(address: *mut c_void) { - free(address, true); + free(address, MemorySpace::Kernel); } pub fn ksize(address: *mut c_void) -> usize { - size_of(address, true) + size_of(address, MemorySpace::Kernel) } pub fn vmalloc(size: usize) -> *mut c_void @@ -75,7 +69,7 @@ pub fn vmalloc(size: usize) -> *mut c_void &mut PT_MANAGER }; - let mut address = next_available_space(pt_manager.heap_start, size, false); + let mut address = next_available_space(pt_manager.heap_start, size, MemorySpace::User); if address == 0 { @@ -89,14 +83,7 @@ pub fn vmalloc(size: usize) -> *mut c_void return core::ptr::null_mut::(); } } - let header: *mut AllocHeader = address as *mut _; - - unsafe - { - (*header).magic = 0x4242; - (*header).size = size; - (*header).freed = false; - } + create_header(address, size); (address + core::mem::size_of::()) as *mut c_void } @@ -117,68 +104,61 @@ pub fn vzalloc(size: usize) -> *mut c_void pub fn vfree(address: *mut c_void) { - free(address, false); + free(address, MemorySpace::User); } pub fn vsize(address: *mut c_void) -> usize { - size_of(address, false) + size_of(address, MemorySpace::User) } // Private functions -fn next_available_space(address: usize, size: usize, kernel_space: bool) -> usize +fn create_header(address: usize, size: usize) +{ + let header: *mut AllocHeader = address as *mut _; + + unsafe + { + (*header).magic = 0x4242; + (*header).size = size; + (*header).freed = false; + } +} + +fn next_available_space(address: usize, size: usize, memory_space: MemorySpace) -> usize { let pt_manager: &mut pagetable::Manager = unsafe { &mut PT_MANAGER }; let total_size = size + core::mem::size_of::(); - let mut max_i = if kernel_space - { - super::KERNEL_SPACE_START * PAGE_SIZE + super::KERNEL_SPACE_RANGE * PAGE_SIZE - pt_manager.memory_start - } - else + let limit = match memory_space { - pt_manager.last_mapped + 0x1000 - pt_manager.heap_start + MemorySpace::Kernel => super::KERNEL_SPACE_START * PAGE_SIZE + super::KERNEL_SPACE_RANGE * PAGE_SIZE - pt_manager.memory_start, + MemorySpace::User => pt_manager.heap_size() }; - let mut i = 0x0; + let mut start = 0x0; loop { - while i + total_size > max_i + if memory_space == MemorySpace::Kernel && start + total_size > limit { - let pages = max(total_size / PAGE_SIZE, 1); - crate::logln!("trying to get {} pages", pages); - if let Some(_) = expand_heap(pages) - { - max_i = pt_manager.last_mapped + 0x1000 - pt_manager.heap_start; - } - else - { - return 0; - } + return 0; + } + else + { + expand_heap_if_needed(start, total_size, limit); } unsafe { - let header: *mut AllocHeader = (address + i) as *mut _; + let header: *mut AllocHeader = (address + start) as *mut _; if (*header).magic == 0x4242 { if (*header).freed { - merge_next_blocks(get_block_for(&*header), kernel_space); - if (*header).size > size - { - let new_address = address + i + core::mem::size_of::(); - let could_break = break_block(new_address as *mut c_void, size, kernel_space); - - if could_break - { - return header as usize; - } - } - else if (*header).size == size + if use_freed_block(address + start, size, memory_space) { return header as usize; } @@ -186,18 +166,65 @@ fn next_available_space(address: usize, size: usize, kernel_space: bool) -> usiz } else { - return address + i; + return address + start; + } + start += (*header).size + core::mem::size_of::(); + } + } +} + +fn expand_heap_if_needed(start: usize, size: usize, heap_size: usize) +{ + let mut heap_size = heap_size; + let pt_manager: &mut pagetable::Manager = unsafe + { + &mut PT_MANAGER + }; + + while start + size > heap_size + { + let pages = max(size / PAGE_SIZE, 1); + if let Some(_) = expand_heap(pages) + { + heap_size = pt_manager.heap_size(); + } + else + { + return; + } + } +} + +fn use_freed_block(address: usize, size: usize, memory_space: MemorySpace) -> bool +{ + unsafe + { + let header: *mut AllocHeader = address as *mut _; + merge_next_blocks(get_block_for(&*header), memory_space); + + if (*header).size > size + { + let new_address = address + core::mem::size_of::(); + let could_break = break_block(new_address as *mut c_void, size, memory_space); + + if could_break + { + return true; } - i += (*header).size + core::mem::size_of::(); } + else if (*header).size == size + { + return true; + } + false } } -fn free(address: *mut c_void, kernel_space: bool) +fn free(address: *mut c_void, memory_space: MemorySpace) { if address != core::ptr::null_mut::() { - if let Some(header) = get_header_for(address, kernel_space) + if let Some(header) = get_header_for(address, memory_space) { if header.freed { @@ -206,15 +233,15 @@ fn free(address: *mut c_void, kernel_space: bool) else { header.freed = true; - merge_next_blocks(address, kernel_space); + merge_next_blocks(address, memory_space); } } } } -fn size_of(address: *mut c_void, kernel_space: bool) -> usize +fn size_of(address: *mut c_void, memory_space: MemorySpace) -> usize { - if let Some(header) = get_header_for(address, kernel_space) + if let Some(header) = get_header_for(address, memory_space) { header.size } @@ -224,27 +251,21 @@ fn size_of(address: *mut c_void, kernel_space: bool) -> usize } } -fn get_header_for(address: *mut c_void, kernel_space: bool) -> Option<&'static mut AllocHeader> +fn get_header_for(address: *mut c_void, memory_space: MemorySpace) -> Option<&'static mut AllocHeader> { let pt_manager: &mut pagetable::Manager = unsafe { &mut PT_MANAGER }; - let lowest_address = if kernel_space + let lowest_address = match memory_space { - pt_manager.memory_start + core::mem::size_of::() - } - else - { - pt_manager.heap_start + core::mem::size_of::() + MemorySpace::Kernel => pt_manager.memory_start + core::mem::size_of::(), + MemorySpace::User => pt_manager.heap_start + core::mem::size_of::() }; - let highest_address = if kernel_space - { - PAGE_SIZE * (super::KERNEL_SPACE_START + super::KERNEL_SPACE_RANGE) - } - else + let highest_address = match memory_space { - pt_manager.last_mapped + PAGE_SIZE + MemorySpace::Kernel => PAGE_SIZE * (super::KERNEL_SPACE_START + super::KERNEL_SPACE_RANGE), + MemorySpace::User => pt_manager.last_mapped + PAGE_SIZE }; if (address as usize) < lowest_address { @@ -274,7 +295,7 @@ fn expand_heap(pages: usize) -> Option<*mut c_void> &mut PT_MANAGER }; let alloc = pageframe::Allocator::shared(); - let new_page = alloc.request_free_pages(max(pages, 1), false); + let new_page = alloc.request_free_pages(max(pages, 1), MemorySpace::User); if new_page != 0 { @@ -291,9 +312,9 @@ fn expand_heap(pages: usize) -> Option<*mut c_void> None } -fn break_block(address: *mut c_void, new_size: usize, kernel_space: bool) -> bool +fn break_block(address: *mut c_void, new_size: usize, memory_space: MemorySpace) -> bool { - if let Some(header) = get_header_for(address, kernel_space) + if let Some(header) = get_header_for(address, memory_space) { let old_size = header.size; @@ -315,9 +336,9 @@ fn break_block(address: *mut c_void, new_size: usize, kernel_space: bool) -> boo false } -fn merge_next_blocks(address: *mut c_void, kernel_space: bool) +fn merge_next_blocks(address: *mut c_void, memory_space: MemorySpace) { - if let Some(header) = get_header_for(address, kernel_space) + if let Some(header) = get_header_for(address, memory_space) { loop { diff --git a/src/memory/mod.rs b/src/memory/mod.rs index f993db1..bb5f12a 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -16,6 +16,13 @@ const KERNEL_SPACE_RANGE: usize = 0x0000_2000; static PAGE_SIZE: usize = 4096; static mut PT_MANAGER: pagetable::Manager = pagetable::Manager::uninitialized(); +#[derive(Copy, Clone, PartialEq)] +pub enum MemorySpace +{ + Kernel, + User +} + pub fn get_mem_size(mmap: *const MultibootTagMmap, mmap_size: usize) -> usize { static mut MEM_SIZE_BYTES: u64 = 0; @@ -43,7 +50,7 @@ pub fn init(mmap: *const MultibootTagMmap, mmap_size: usize) let alloc: &mut pageframe::Allocator = pageframe::Allocator::shared(); alloc.read_grub_mmap(mmap, mmap_size); - let page_directory_addr = alloc.request_free_page(true); + let page_directory_addr = alloc.request_free_page(MemorySpace::Kernel); let mut pt_manager = pagetable::Manager::new(page_directory_addr, PDE_RW); pt_manager.page_count = alloc.bitmap.size; @@ -55,7 +62,7 @@ pub fn init(mmap: *const MultibootTagMmap, mmap_size: usize) enable_paging(); pt_manager.enable_paging(); } - let page = alloc.request_free_page(false); + let page = alloc.request_free_page(MemorySpace::User); let virtual_page = PAGE_SIZE * (KERNEL_SPACE_START + KERNEL_SPACE_RANGE); pt_manager.memory_map(virtual_page, page); unsafe diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index f8171f6..cc29363 100644 --- a/src/memory/pageframe.rs +++ b/src/memory/pageframe.rs @@ -2,7 +2,7 @@ use crate::multiboot::MultibootTagMmap; use crate::ferramenta; use crate::page_index; use crate::memory::get_mem_size; -use super::{KERNEL_SPACE_START, KERNEL_SPACE_RANGE, PAGE_SIZE}; +use super::{KERNEL_SPACE_START, KERNEL_SPACE_RANGE, PAGE_SIZE, MemorySpace}; use core::ffi::c_void; @@ -86,24 +86,18 @@ impl Allocator crate::logln!("[INFO] kernel space : {:#08x} - {:#08x}", PAGE_SIZE * KERNEL_SPACE_START, PAGE_SIZE * (KERNEL_SPACE_START + KERNEL_SPACE_RANGE)); } - pub fn request_free_pages(&mut self, n: usize, kernel_space: bool) -> usize + pub fn request_free_pages(&mut self, n: usize, memory_space: MemorySpace) -> usize { let mut first_page = 0; - let start = if kernel_space + let start = match memory_space { - 0 - } - else - { - KERNEL_SPACE_START + KERNEL_SPACE_RANGE + MemorySpace::Kernel => 0, + MemorySpace::User => KERNEL_SPACE_START + KERNEL_SPACE_RANGE }; - let end = if kernel_space - { - KERNEL_SPACE_START + KERNEL_SPACE_RANGE - 1 - } - else + let end = match memory_space { - self.bitmap.size + MemorySpace::Kernel => KERNEL_SPACE_START + KERNEL_SPACE_RANGE - 1, + MemorySpace::User => self.bitmap.size }; let mut i = start; @@ -133,9 +127,9 @@ impl Allocator first_page } - pub fn request_free_page(&mut self, kernel_space: bool) -> usize + pub fn request_free_page(&mut self, memory_space: MemorySpace) -> usize { - self.request_free_pages(1, kernel_space) + self.request_free_pages(1, memory_space) } pub fn free_page(&mut self, address: usize) diff --git a/src/memory/pagetable.rs b/src/memory/pagetable.rs index 75afec5..b8b2f14 100644 --- a/src/memory/pagetable.rs +++ b/src/memory/pagetable.rs @@ -3,6 +3,7 @@ use crate::memory::PAGE_SIZE; use crate::memory::page; use crate::memory::pageframe; use crate::memory::page_map_indexer; +use super::MemorySpace; use core::ffi::c_void; pub mod flags @@ -95,7 +96,7 @@ impl Manager { let alloc = pageframe::Allocator::shared(); page_directory_entry.reset(); - page_directory_entry.set_addr(alloc.request_free_page(true) as u32); + page_directory_entry.set_addr(alloc.request_free_page(MemorySpace::Kernel) as u32); page_directory_entry.value |= self.flags as u32 & 0xFFF; page_directory_entry.set_present(true); unsafe @@ -149,4 +150,9 @@ impl Manager page_directory_entry.get_addr() } } + + pub fn heap_size(&self) -> usize + { + self.last_mapped + 0xfff - self.heap_start + } } From e68e42e40efa18ecf8e43d57b891bf3b922bd0a2 Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Tue, 3 May 2022 16:14:43 +0200 Subject: [PATCH 15/16] commands: add print var --- src/tty/basic_commands.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/tty/basic_commands.rs b/src/tty/basic_commands.rs index 735d8d9..a6a2ba2 100644 --- a/src/tty/basic_commands.rs +++ b/src/tty/basic_commands.rs @@ -27,7 +27,7 @@ pub fn execute(command: &str) let command = &command[..command_end]; match command { - "pm" | "pb" | "km" | "vm" | "kfree" | "vfree" => + "pm" | "pb" | "pk" | "pv" | "km" | "vm" | "kfree" | "vfree" => { let address = u32::from_str_radix(arg, 16) .unwrap_or_else(|_| @@ -40,6 +40,8 @@ pub fn execute(command: &str) { "pm" => printmem_at(address as *const u8, false), "pb" => printmem_at(address as *const u8, true), + "pk" => print_var(address as *const u8, true), + "pv" => print_var(address as *const u8, false), "km" => allocate(address as usize, true), "vm" => allocate(address as usize, false), "kfree" => free(address as *mut c_void, true), @@ -106,11 +108,28 @@ fn printmem_at(address: *const u8, binary: bool) } else { - ferramenta::print_memory(address, 256); + ferramenta::print_memory(address, 0x1000); } } } +fn print_var(address: *const u8, kernel_space: bool) +{ + unsafe + { + let size = if kernel_space + { + memory::ksize(address as *mut c_void) + } + else + { + memory::vsize(address as *mut c_void) + }; + let address = (address as usize - 0x10) as *const u8; + ferramenta::print_memory(address, size); + } +} + fn allocate(size: usize, kernel_space: bool) { let address = if kernel_space From 6e662cbfa4fedddad20a9a2c785ef329f7f692cf Mon Sep 17 00:00:00 2001 From: Edgar Fouillet Date: Tue, 3 May 2022 16:38:46 +0200 Subject: [PATCH 16/16] print memory: move prints to serial only for speed --- src/ferramenta.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ferramenta.rs b/src/ferramenta.rs index f1bbf5f..24c7b15 100644 --- a/src/ferramenta.rs +++ b/src/ferramenta.rs @@ -72,27 +72,27 @@ pub unsafe fn print_memory(ptr: *const u8, n: usize) { if i % 16 == 0 { - crate::log!("{:08x}: ", ptr.add(i) as u32); + crate::serial_print!("{:08x}: ", ptr.add(i) as u32); } - crate::log!("{:02x?} ", *ptr.add(i)); + crate::serial_print!("{:02x?} ", *ptr.add(i)); i += 1; if i % 16 == 0 { - crate::log!(" |"); + crate::serial_print!(" |"); for i in i - 16..i { let chr = *ptr.add(i); - crate::log!("{}", if chr > 0x1f && chr < 0x7f {chr as char } else { '.' }); + crate::serial_print!("{}", if chr > 0x1f && chr < 0x7f {chr as char } else { '.' }); } - crate::log!("|"); - crate::logln!(); + crate::serial_print!("|"); + crate::serial_println!(); } else if i % 8 == 0 { - crate::log!(" "); + crate::serial_print!(" "); } } - crate::logln!(); + crate::serial_println!(); } pub unsafe fn print_memory_bin(ptr: *const u8, n: usize)