From d790fc20e5418c4fd7df0ae6aa2f49f9e80c80b7 Mon Sep 17 00:00:00 2001 From: Philipp Oppermann Date: Fri, 9 Oct 2015 17:52:00 +0200 Subject: [PATCH] Add an allocator --- Cargo.toml | 3 ++ src/lib.rs | 7 ++- src/memory/alloc/allocator/Cargo.lock | 4 ++ src/memory/alloc/allocator/Cargo.toml | 4 ++ src/memory/alloc/allocator/src/lib.rs | 14 ++++++ src/memory/alloc/mod.rs | 63 +++++++++++++++++++++++++++ src/memory/frame_allocator.rs | 5 ++- src/memory/mod.rs | 5 ++- src/memory/paging/mod.rs | 11 +++-- 9 files changed, 107 insertions(+), 9 deletions(-) create mode 100644 src/memory/alloc/allocator/Cargo.lock create mode 100644 src/memory/alloc/allocator/Cargo.toml create mode 100644 src/memory/alloc/allocator/src/lib.rs create mode 100644 src/memory/alloc/mod.rs diff --git a/Cargo.toml b/Cargo.toml index 8fb41c88..8bf89e50 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,3 +16,6 @@ branch = "no_std" [dependencies.multiboot2] path = "../multiboot2" + +[dependencies.allocator] +path = "src/memory/alloc/allocator" diff --git a/src/lib.rs b/src/lib.rs index 9eaaaab8..5c459a27 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,10 +14,12 @@ #![feature(no_std, lang_items, asm)] #![feature(core_str_ext, const_fn, range_inclusive)] -#![feature(unique, core_intrinsics)] +#![feature(unique, core_intrinsics, alloc)] #![no_std] extern crate rlibc; +extern crate alloc; +extern crate allocator; extern crate multiboot2; #[macro_use] extern crate bitflags; @@ -34,6 +36,7 @@ mod memory; pub extern fn rust_main(multiboot_address: usize) { // ATTENTION: we have a very small stack and no guard page use vga_buffer::{Writer, Color}; + use alloc::boxed::Box; vga_buffer::clear_screen(); if let Some(multiboot) = unsafe{multiboot2::load(multiboot_address)} { @@ -50,6 +53,8 @@ pub extern fn rust_main(multiboot_address: usize) { println!("{} {}", "line", 1); print!("line {}", 2); + Box::new(42); + loop{} } diff --git a/src/memory/alloc/allocator/Cargo.lock b/src/memory/alloc/allocator/Cargo.lock new file mode 100644 index 00000000..65dc3faf --- /dev/null +++ b/src/memory/alloc/allocator/Cargo.lock @@ -0,0 +1,4 @@ +[root] +name = "allocator" +version = "0.1.0" + diff --git a/src/memory/alloc/allocator/Cargo.toml b/src/memory/alloc/allocator/Cargo.toml new file mode 100644 index 00000000..be86c813 --- /dev/null +++ b/src/memory/alloc/allocator/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "allocator" +version = "0.1.0" +authors = ["Philipp Oppermann "] diff --git a/src/memory/alloc/allocator/src/lib.rs b/src/memory/alloc/allocator/src/lib.rs new file mode 100644 index 00000000..72d8f0ab --- /dev/null +++ b/src/memory/alloc/allocator/src/lib.rs @@ -0,0 +1,14 @@ +#![feature(no_std, allocator)] +#![no_std] +#![allocator] +#![allow(improper_ctypes)] + +extern { + fn __rust_allocate(size: usize, align: usize) -> *mut u8; + fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize); + fn __rust_reallocate(ptr: *mut u8, old_size: usize, size: usize, + align: usize) -> *mut u8; + fn __rust_reallocate_inplace(ptr: *mut u8, old_size: usize, size: usize, + align: usize) -> usize; + fn __rust_usable_size(size: usize, align: usize) -> usize; +} diff --git a/src/memory/alloc/mod.rs b/src/memory/alloc/mod.rs new file mode 100644 index 00000000..151583a1 --- /dev/null +++ b/src/memory/alloc/mod.rs @@ -0,0 +1,63 @@ +use memory::paging::{self, Page, Mapper}; +use memory::frame_allocator::{FrameAllocator, DynamicFrameStack}; +use core::iter::range_inclusive; +use rlibc::memcpy; +use spin::Mutex; + +static ALLOCATOR: Mutex>> = Mutex::new(None); + +const HEAD_BOTTOM: usize = 0o_001_000_000_000_0000; + +struct Allocator<'a, T> where T: 'a { + heap_top: usize, + last_mapped_page: Page, + mapper: Mapper<'a, T>, +} + +impl<'a, T> Allocator<'a, T> where T: FrameAllocator { + pub fn allocate(&mut self, size: usize, align: usize) -> *mut u8 { + let start_address = align_up(self.heap_top, align); + let end_address = start_address + size; + let end_page = Page::containing_address(end_address - 1).number; + let last_mapped_page = self.last_mapped_page.number; + + if end_page > last_mapped_page { + for page in range_inclusive(last_mapped_page + 1, end_page).map(|n| Page{number: n}) { + self.mapper.map(page, true, false) + } + self.last_mapped_page.number = end_page; + } + self.heap_top = end_address; + start_address as *mut u8 + } + + pub fn reallocate(&mut self, ptr: *mut u8, old_size: usize, size: usize, + align: usize) -> *mut u8 + { + let new_ptr = self.allocate(size, align); + unsafe{ memcpy(new_ptr, ptr, old_size) }; + new_ptr + } + + pub fn deallocate(&mut self, ptr: *mut u8, old_size: usize, align: usize) { + //TODO + } +} + +fn align_up(addr: usize, align: usize) -> usize { + if addr % align == 0 { + addr + } else { + addr + align - (addr % align) + } +} + +#[no_mangle] +pub extern fn __rust_allocate(size: usize, align: usize) -> *mut u8 { + ALLOCATOR.lock().as_mut().expect("no allocator").allocate(size, align) +} + +#[no_mangle] +pub extern fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize) { + ALLOCATOR.lock().as_mut().expect("no allocator").deallocate(ptr, old_size, align) +} diff --git a/src/memory/frame_allocator.rs b/src/memory/frame_allocator.rs index ea7255d0..5df6d23f 100644 --- a/src/memory/frame_allocator.rs +++ b/src/memory/frame_allocator.rs @@ -69,7 +69,10 @@ impl FrameAllocator for DynamicFrameStack { } else { // frame stack is full, use passed frame to expand it let page_address = unsafe{ offset(*self.head, self.capacity as isize) } as usize; - lock.mapper(self).map_to(Page::containing_address(page_address), frame, true, false); + unsafe { + lock.mapper(self).map_to(Page::containing_address(page_address), frame, + true, false); + } self.capacity += Self::capacity_per_frame(); } } diff --git a/src/memory/mod.rs b/src/memory/mod.rs index b3a1a42c..06b514f4 100644 --- a/src/memory/mod.rs +++ b/src/memory/mod.rs @@ -1,6 +1,7 @@ use multiboot2::Multiboot; use self::paging::Page; +mod alloc; mod paging; mod frame_allocator; mod tlb; @@ -34,7 +35,9 @@ pub fn init(multiboot: &Multiboot) { } -fn identity_map_kernel_sections(multiboot: &Multiboot, mut mapper: paging::Mapper) { +fn identity_map_kernel_sections(multiboot: &Multiboot, mut mapper: paging::Mapper) + where T: frame_allocator::FrameAllocator, +{ use core::iter::range_inclusive; for section in multiboot.elf_tag().expect("no section tag").sections() { diff --git a/src/memory/paging/mod.rs b/src/memory/paging/mod.rs index c81b5ee8..8c4b54c8 100644 --- a/src/memory/paging/mod.rs +++ b/src/memory/paging/mod.rs @@ -54,23 +54,22 @@ pub struct Mapper<'a, A> where A: 'a { } impl<'a, A> Mapper<'a, A> where A: FrameAllocator { - pub fn map_to(&mut self, page: Page, frame: Frame, writable: bool, executable: bool) { - map_to(self.lock, page, frame, writable, executable, self.allocator) - } - pub fn map(&mut self, page: Page, writable: bool, executable: bool) { let frame = self.allocator.allocate_frame(&mut self.lock) .expect("no more frames available"); - self.map_to(page, frame, writable, executable) + unsafe{ self.map_to(page, frame, writable, executable) } } pub fn unmap(&mut self, page: Page) { unmap(self.lock, page, self.allocator) } + pub unsafe fn map_to(&mut self, page: Page, frame: Frame, writable: bool, executable: bool) { + map_to(self.lock, page, frame, writable, executable, self.allocator) + } + pub unsafe fn identity_map(&mut self, page: Page, writable: bool, executable: bool) { let frame = Frame {number: page.number}; self.map_to(page, frame, writable, executable) } - }