Cleanup, use spinlock for allocator
This commit is contained in:
parent
cc8fe85e6a
commit
2a66a84a50
|
@ -1,3 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "bump_allocator"
|
name = "bump_allocator"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
"spin" = "*"
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
//! A simple allocator that never frees, for testing
|
//! A simple allocator that never frees, for testing
|
||||||
|
//! Some code borrowed from [Phil Opp's Blog](http://os.phil-opp.com/kernel-heap.html)
|
||||||
|
|
||||||
#![feature(allocator)]
|
#![feature(allocator)]
|
||||||
|
#![feature(const_fn)]
|
||||||
#![allocator]
|
#![allocator]
|
||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
pub static mut HEAP: usize = 10*1024*1024;
|
use spin::Mutex;
|
||||||
|
|
||||||
|
extern crate spin;
|
||||||
|
|
||||||
|
pub const HEAP_START: usize = 0o_000_001_000_000_0000;
|
||||||
|
pub const HEAP_SIZE: usize = 100 * 1024; // 100 KiB
|
||||||
|
|
||||||
|
static BUMP_ALLOCATOR: Mutex<BumpAllocator> = Mutex::new(BumpAllocator::new(HEAP_START, HEAP_SIZE));
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
|
pub extern fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
|
||||||
unsafe {
|
BUMP_ALLOCATOR.lock().allocate(size, align).expect("out of memory")
|
||||||
let mut ret = HEAP;
|
|
||||||
if align.is_power_of_two() {
|
|
||||||
ret += (align - 1);
|
|
||||||
ret &= !(align - 1);
|
|
||||||
} else {
|
|
||||||
assert_eq!(align, 0);
|
|
||||||
}
|
|
||||||
HEAP = ret + size;
|
|
||||||
ret as *mut u8
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -45,3 +44,53 @@ pub extern fn __rust_reallocate(ptr: *mut u8, size: usize, new_size: usize, alig
|
||||||
pub extern fn __rust_reallocate_inplace(ptr: *mut u8, size: usize, new_size: usize, align: usize) -> usize {
|
pub extern fn __rust_reallocate_inplace(ptr: *mut u8, size: usize, new_size: usize, align: usize) -> usize {
|
||||||
size
|
size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Align downwards. Returns the greatest x with alignment `align`
|
||||||
|
/// so that x <= addr. The alignment must be a power of 2.
|
||||||
|
pub fn align_down(addr: usize, align: usize) -> usize {
|
||||||
|
if align.is_power_of_two() {
|
||||||
|
addr & !(align - 1)
|
||||||
|
} else if align == 0 {
|
||||||
|
addr
|
||||||
|
} else {
|
||||||
|
panic!("`align` must be a power of 2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Align upwards. Returns the smallest x with alignment `align`
|
||||||
|
/// so that x >= addr. The alignment must be a power of 2.
|
||||||
|
pub fn align_up(addr: usize, align: usize) -> usize {
|
||||||
|
align_down(addr + align - 1, align)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct BumpAllocator {
|
||||||
|
heap_start: usize,
|
||||||
|
heap_size: usize,
|
||||||
|
next: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BumpAllocator {
|
||||||
|
/// Create a new allocator, which uses the memory in the
|
||||||
|
/// range [heap_start, heap_start + heap_size).
|
||||||
|
const fn new(heap_start: usize, heap_size: usize) -> BumpAllocator {
|
||||||
|
BumpAllocator {
|
||||||
|
heap_start: heap_start,
|
||||||
|
heap_size: heap_size,
|
||||||
|
next: heap_start,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Allocates a block of memory with the given size and alignment.
|
||||||
|
fn allocate(&mut self, size: usize, align: usize) -> Option<*mut u8> {
|
||||||
|
let alloc_start = align_up(self.next, align);
|
||||||
|
let alloc_end = alloc_start + size;
|
||||||
|
|
||||||
|
if alloc_end <= self.heap_start + self.heap_size {
|
||||||
|
self.next = alloc_end;
|
||||||
|
Some(alloc_start as *mut u8)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ version = "0.1.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "*"
|
bitflags = "*"
|
||||||
|
bump_allocator = { path = "../../alloc/bump_allocator"}
|
||||||
|
|
||||||
[dependencies.x86]
|
[dependencies.x86]
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate bitflags;
|
extern crate bitflags;
|
||||||
|
extern crate bump_allocator;
|
||||||
extern crate x86;
|
extern crate x86;
|
||||||
|
|
||||||
/// Print to console
|
/// Print to console
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
/// It must create the IDT with the correct entries, those entries are
|
/// It must create the IDT with the correct entries, those entries are
|
||||||
/// defined in other files inside of the `arch` module
|
/// defined in other files inside of the `arch` module
|
||||||
|
|
||||||
|
use bump_allocator::{HEAP_START, HEAP_SIZE};
|
||||||
use externs::memset;
|
use externs::memset;
|
||||||
use gdt;
|
use gdt;
|
||||||
use idt;
|
use idt;
|
||||||
use memory::{self, Frame};
|
use memory;
|
||||||
use paging::{self, entry, Page, PhysicalAddress};
|
use paging::{self, Page, VirtualAddress};
|
||||||
|
|
||||||
/// Test of zero values in BSS.
|
/// Test of zero values in BSS.
|
||||||
static BSS_TEST_ZERO: usize = 0;
|
static BSS_TEST_ZERO: usize = 0;
|
||||||
|
@ -54,6 +55,14 @@ pub unsafe extern fn kstart() -> ! {
|
||||||
// Initialize paging
|
// Initialize paging
|
||||||
let mut active_table = paging::init(&mut allocator);
|
let mut active_table = paging::init(&mut allocator);
|
||||||
|
|
||||||
|
// Initialize heap
|
||||||
|
let heap_start_page = Page::containing_address(VirtualAddress::new(HEAP_START));
|
||||||
|
let heap_end_page = Page::containing_address(VirtualAddress::new(HEAP_START + HEAP_SIZE-1));
|
||||||
|
|
||||||
|
for page in Page::range_inclusive(heap_start_page, heap_end_page) {
|
||||||
|
active_table.map(page, paging::entry::WRITABLE, &mut allocator);
|
||||||
|
}
|
||||||
|
|
||||||
asm!("xchg bx, bx" : : : : "intel", "volatile");
|
asm!("xchg bx, bx" : : : : "intel", "volatile");
|
||||||
kmain();
|
kmain();
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,13 +84,6 @@ pub struct Frame {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Frame {
|
impl Frame {
|
||||||
/// Create a frame containing `address`
|
|
||||||
pub fn containing_address(address: PhysicalAddress) -> Frame {
|
|
||||||
Frame {
|
|
||||||
number: address.get() / PAGE_SIZE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the address of this frame
|
/// Get the address of this frame
|
||||||
pub fn start_address(&self) -> PhysicalAddress {
|
pub fn start_address(&self) -> PhysicalAddress {
|
||||||
PhysicalAddress::new(self.number * PAGE_SIZE)
|
PhysicalAddress::new(self.number * PAGE_SIZE)
|
||||||
|
@ -102,8 +95,42 @@ impl Frame {
|
||||||
number: self.number
|
number: self.number
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a frame containing `address`
|
||||||
|
pub fn containing_address(address: PhysicalAddress) -> Frame {
|
||||||
|
Frame {
|
||||||
|
number: address.get() / PAGE_SIZE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Set private
|
||||||
|
pub fn range_inclusive(start: Frame, end: Frame) -> FrameIter {
|
||||||
|
FrameIter {
|
||||||
|
start: start,
|
||||||
|
end: end,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct FrameIter {
|
||||||
|
start: Frame,
|
||||||
|
end: Frame,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for FrameIter {
|
||||||
|
type Item = Frame;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Frame> {
|
||||||
|
if self.start <= self.end {
|
||||||
|
let frame = self.start.clone();
|
||||||
|
self.start.number += 1;
|
||||||
|
Some(frame)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait FrameAllocator {
|
pub trait FrameAllocator {
|
||||||
fn allocate_frame(&mut self) -> Option<Frame>;
|
fn allocate_frame(&mut self) -> Option<Frame>;
|
||||||
fn deallocate_frame(&mut self, frame: Frame);
|
fn deallocate_frame(&mut self, frame: Frame);
|
||||||
|
|
|
@ -5,9 +5,8 @@ use core::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
use memory::{Frame, FrameAllocator};
|
use memory::{Frame, FrameAllocator};
|
||||||
|
|
||||||
use self::entry::{PRESENT, WRITABLE, EntryFlags};
|
use self::entry::{PRESENT, WRITABLE};
|
||||||
use self::mapper::Mapper;
|
use self::mapper::Mapper;
|
||||||
use self::table::{Table, Level4};
|
|
||||||
use self::temporary_page::TemporaryPage;
|
use self::temporary_page::TemporaryPage;
|
||||||
|
|
||||||
pub mod entry;
|
pub mod entry;
|
||||||
|
@ -44,7 +43,7 @@ pub unsafe fn init<A>(allocator: &mut A) -> ActivePageTable where A: FrameAlloca
|
||||||
|
|
||||||
let mut active_table = ActivePageTable::new();
|
let mut active_table = ActivePageTable::new();
|
||||||
|
|
||||||
let mut temporary_page = TemporaryPage::new(Page { number: 0xcafebabe },
|
let mut temporary_page = TemporaryPage::new(Page { number: 0x80000000 },
|
||||||
allocator);
|
allocator);
|
||||||
|
|
||||||
let mut new_table = {
|
let mut new_table = {
|
||||||
|
@ -54,6 +53,11 @@ pub unsafe fn init<A>(allocator: &mut A) -> ActivePageTable where A: FrameAlloca
|
||||||
|
|
||||||
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
|
active_table.with(&mut new_table, &mut temporary_page, |mapper| {
|
||||||
let mut remap = |start: usize, end: usize, flags: entry::EntryFlags| {
|
let mut remap = |start: usize, end: usize, flags: entry::EntryFlags| {
|
||||||
|
/* TODO
|
||||||
|
let start_frame = Frame::containing_address(PhysicalAddress::new(start));
|
||||||
|
let end_frame = Frame::containing_address(PhysicalAddress::new(end));
|
||||||
|
for frame in Frame::range_inclusive(start_frame, end_frame) {}
|
||||||
|
*/
|
||||||
for i in 0..(end - start + PAGE_SIZE - 1)/PAGE_SIZE {
|
for i in 0..(end - start + PAGE_SIZE - 1)/PAGE_SIZE {
|
||||||
let frame = Frame::containing_address(PhysicalAddress::new(start + i * PAGE_SIZE));
|
let frame = Frame::containing_address(PhysicalAddress::new(start + i * PAGE_SIZE));
|
||||||
mapper.identity_map(frame, flags, allocator);
|
mapper.identity_map(frame, flags, allocator);
|
||||||
|
@ -197,7 +201,7 @@ impl VirtualAddress {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Page
|
/// Page
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct Page {
|
pub struct Page {
|
||||||
number: usize
|
number: usize
|
||||||
}
|
}
|
||||||
|
@ -228,4 +232,30 @@ impl Page {
|
||||||
"invalid address: 0x{:x}", address.get());
|
"invalid address: 0x{:x}", address.get());
|
||||||
Page { number: address.get() / PAGE_SIZE }
|
Page { number: address.get() / PAGE_SIZE }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn range_inclusive(start: Page, end: Page) -> PageIter {
|
||||||
|
PageIter {
|
||||||
|
start: start,
|
||||||
|
end: end,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PageIter {
|
||||||
|
start: Page,
|
||||||
|
end: Page,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for PageIter {
|
||||||
|
type Item = Page;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Page> {
|
||||||
|
if self.start <= self.end {
|
||||||
|
let page = self.start;
|
||||||
|
self.start.number += 1;
|
||||||
|
Some(page)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ extern "C" fn panic_fmt(fmt: ::core::fmt::Arguments, file: &str, line: u32) -> !
|
||||||
println!("LINE: {}", line);
|
println!("LINE: {}", line);
|
||||||
|
|
||||||
println!("TRACE: {:>016X}", rbp);
|
println!("TRACE: {:>016X}", rbp);
|
||||||
for i in 0..10 {
|
for _frame in 0..16 { //Maximum 16 frames
|
||||||
unsafe {
|
unsafe {
|
||||||
let rip = *(rbp as *const usize).offset(1);
|
let rip = *(rbp as *const usize).offset(1);
|
||||||
println!(" {:>016X}: {:>016X}", rbp, rip);
|
println!(" {:>016X}: {:>016X}", rbp, rip);
|
||||||
|
|
|
@ -85,10 +85,6 @@ extern crate arch_test as arch;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate arch_x86_64 as arch;
|
extern crate arch_x86_64 as arch;
|
||||||
|
|
||||||
/// Bump allocator
|
|
||||||
#[cfg(all(not(test), target_arch = "x86_64"))]
|
|
||||||
extern crate bump_allocator;
|
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate collections;
|
extern crate collections;
|
||||||
|
|
Loading…
Reference in a new issue