diff --git a/Makefile b/Makefile index 5906d7a..e8edf0b 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 @@ -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) @@ -84,3 +87,5 @@ clean: mrproper: clean cargo clean +re: mrproper + make all 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] diff --git a/src/ferramenta.rs b/src/ferramenta.rs index bab46f9..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) @@ -190,6 +190,29 @@ 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; + + 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 +271,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/malloc.rs b/src/memory/malloc.rs new file mode 100644 index 0000000..bdd6058 --- /dev/null +++ b/src/memory/malloc.rs @@ -0,0 +1,364 @@ +use core::cmp::max; +use core::ffi::c_void; +use super::pageframe; +use super::pagetable; +use super::PAGE_SIZE; +use super::PT_MANAGER; +use super::MemorySpace; +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 start = pt_manager.memory_start + PAGE_SIZE * (pt_manager.page_count / 1024 + 2); + let address = next_available_space(start, size, MemorySpace::Kernel); + + if address == 0 + { + crate::oops!("kernel space out of memory"); + return core::ptr::null_mut::(); + } + create_header(address, size); + (address + core::mem::size_of::()) as *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::() + { + unsafe + { + libc::memset(address, 0, size); + } + } + address +} + +pub fn kfree(address: *mut c_void) +{ + free(address, MemorySpace::Kernel); +} + +pub fn ksize(address: *mut c_void) -> usize +{ + size_of(address, MemorySpace::Kernel) +} + +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, MemorySpace::User); + + 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::(); + } + } + create_header(address, size); + (address + core::mem::size_of::()) as *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::() + { + unsafe + { + libc::memset(address, 0, size); + } + } + address +} + +pub fn vfree(address: *mut c_void) +{ + free(address, MemorySpace::User); +} + +pub fn vsize(address: *mut c_void) -> usize +{ + size_of(address, MemorySpace::User) +} + +// Private functions + +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 limit = match memory_space + { + 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 start = 0x0; + + loop + { + if memory_space == MemorySpace::Kernel && start + total_size > limit + { + return 0; + } + else + { + expand_heap_if_needed(start, total_size, limit); + } + unsafe + { + let header: *mut AllocHeader = (address + start) as *mut _; + + if (*header).magic == 0x4242 + { + if (*header).freed + { + if use_freed_block(address + start, size, memory_space) + { + return header as usize; + } + } + } + else + { + 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; + } + } + else if (*header).size == size + { + return true; + } + false + } +} + +fn free(address: *mut c_void, memory_space: MemorySpace) +{ + if address != core::ptr::null_mut::() + { + if let Some(header) = get_header_for(address, memory_space) + { + if header.freed + { + crate::oops!("double free"); + } + else + { + header.freed = true; + merge_next_blocks(address, memory_space); + } + } + } +} + +fn size_of(address: *mut c_void, memory_space: MemorySpace) -> usize +{ + if let Some(header) = get_header_for(address, memory_space) + { + header.size + } + else + { + 0 + } +} + +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 = match memory_space + { + MemorySpace::Kernel => pt_manager.memory_start + core::mem::size_of::(), + MemorySpace::User => pt_manager.heap_start + core::mem::size_of::() + }; + let highest_address = match memory_space + { + 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 + { + 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), MemorySpace::User); + + 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, memory_space: MemorySpace) -> bool +{ + if let Some(header) = get_header_for(address, memory_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, memory_space: MemorySpace) +{ + if let Some(header) = get_header_for(address, memory_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 53c9a2f..bb5f12a 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -1,11 +1,27 @@ +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(); + +#[derive(Copy, Clone, PartialEq)] +pub enum MemorySpace +{ + Kernel, + User +} pub fn get_mem_size(mmap: *const MultibootTagMmap, mmap_size: usize) -> usize { @@ -34,9 +50,10 @@ 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; id_map(&mut pt_manager); alloc.print_memusage(1); unsafe @@ -45,9 +62,18 @@ pub fn init(mmap: *const MultibootTagMmap, mmap_size: usize) enable_paging(); 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 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 + { + libc::memset(virtual_page as *mut _, 0, PAGE_SIZE); + } + + unsafe + { + PT_MANAGER = pt_manager; + } } fn id_map(pt_manager: &mut pagetable::Manager) @@ -56,11 +82,20 @@ 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); + } + for i in pt_manager.page_count / 1024 + 2 + memory_start / PAGE_SIZE..KERNEL_SPACE_START + KERNEL_SPACE_RANGE + { + alloc.lock_page(i); + } } extern "C" diff --git a/src/memory/pageframe.rs b/src/memory/pageframe.rs index a4e371d..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::PAGE_SIZE; +use super::{KERNEL_SPACE_START, KERNEL_SPACE_RANGE, PAGE_SIZE, MemorySpace}; 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,24 +83,53 @@ 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, memory_space: MemorySpace) -> usize { - for i in 0..self.bitmap.size + let mut first_page = 0; + let start = match memory_space + { + MemorySpace::Kernel => 0, + MemorySpace::User => KERNEL_SPACE_START + KERNEL_SPACE_RANGE + }; + let end = match memory_space + { + MemorySpace::Kernel => KERNEL_SPACE_START + KERNEL_SPACE_RANGE - 1, + MemorySpace::User => self.bitmap.size + }; + + let mut i = start; + while i < end { - if !kernel_space && ferramenta::in_range(i, KERNEL_SPACE_START, KERNEL_SPACE_RANGE) + 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::logln!("locking page {}", i); - self.lock_page(i); - return i * 0x1000; + i = next_i } } - 0 + first_page + } + + pub fn request_free_page(&mut self, memory_space: MemorySpace) -> usize + { + 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 75bf404..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 @@ -32,10 +33,28 @@ pub struct Manager pub page_directory: &'static mut [page::DirectoryEntry], paging_enabled: bool, flags: usize, + pub memory_start: usize, + pub page_count: 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, + page_count: 0, + heap_start: 0, + last_mapped: 0 + } + } + pub fn new(addr: usize, flags: usize) -> Manager { unsafe @@ -46,6 +65,10 @@ impl Manager page_directory: core::slice::from_raw_parts_mut(addr as *mut page::DirectoryEntry, 1024), paging_enabled: false, flags: flags, + memory_start: 0, + page_count: 0, + heap_start: 0, + last_mapped: 0 }; manager.page_directory[1023].set_addr(addr as u32); manager.page_directory[1023].set_rw(true); @@ -73,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 @@ -104,6 +127,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 @@ -118,4 +150,9 @@ impl Manager page_directory_entry.get_addr() } } + + pub fn heap_size(&self) -> usize + { + self.last_mapped + 0xfff - self.heap_start + } } diff --git a/src/tty/basic_commands.rs b/src/tty/basic_commands.rs index 990829e..a6a2ba2 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" | "pk" | "pv" | "km" | "vm" | "kfree" | "vfree" => { let address = u32::from_str_radix(arg, 16) .unwrap_or_else(|_| @@ -38,6 +40,12 @@ 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), + "vfree" => free(address as *mut c_void, false), _ => {} }; } @@ -100,11 +108,71 @@ 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 + { + 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