Cleanup, use spinlock for allocator
This commit is contained in:
parent
cc8fe85e6a
commit
2a66a84a50
|
@ -1,3 +1,6 @@
|
|||
[package]
|
||||
name = "bump_allocator"
|
||||
version = "0.1.0"
|
||||
|
||||
[dependencies]
|
||||
"spin" = "*"
|
||||
|
|
|
@ -1,24 +1,23 @@
|
|||
//! 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(const_fn)]
|
||||
#![allocator]
|
||||
#![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]
|
||||
pub extern fn __rust_allocate(size: usize, align: usize) -> *mut u8 {
|
||||
unsafe {
|
||||
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
|
||||
}
|
||||
BUMP_ALLOCATOR.lock().allocate(size, align).expect("out of memory")
|
||||
}
|
||||
|
||||
#[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 {
|
||||
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]
|
||||
bitflags = "*"
|
||||
bump_allocator = { path = "../../alloc/bump_allocator"}
|
||||
|
||||
[dependencies.x86]
|
||||
default-features = false
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#[macro_use]
|
||||
extern crate bitflags;
|
||||
extern crate bump_allocator;
|
||||
extern crate x86;
|
||||
|
||||
/// Print to console
|
||||
|
|
|
@ -3,11 +3,12 @@
|
|||
/// It must create the IDT with the correct entries, those entries are
|
||||
/// defined in other files inside of the `arch` module
|
||||
|
||||
use bump_allocator::{HEAP_START, HEAP_SIZE};
|
||||
use externs::memset;
|
||||
use gdt;
|
||||
use idt;
|
||||
use memory::{self, Frame};
|
||||
use paging::{self, entry, Page, PhysicalAddress};
|
||||
use memory;
|
||||
use paging::{self, Page, VirtualAddress};
|
||||
|
||||
/// Test of zero values in BSS.
|
||||
static BSS_TEST_ZERO: usize = 0;
|
||||
|
@ -54,6 +55,14 @@ pub unsafe extern fn kstart() -> ! {
|
|||
// Initialize paging
|
||||
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");
|
||||
kmain();
|
||||
}
|
||||
|
|
|
@ -84,13 +84,6 @@ pub struct 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
|
||||
pub fn start_address(&self) -> PhysicalAddress {
|
||||
PhysicalAddress::new(self.number * PAGE_SIZE)
|
||||
|
@ -102,8 +95,42 @@ impl Frame {
|
|||
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 {
|
||||
fn allocate_frame(&mut self) -> Option<Frame>;
|
||||
fn deallocate_frame(&mut self, frame: Frame);
|
||||
|
|
|
@ -5,9 +5,8 @@ use core::ops::{Deref, DerefMut};
|
|||
|
||||
use memory::{Frame, FrameAllocator};
|
||||
|
||||
use self::entry::{PRESENT, WRITABLE, EntryFlags};
|
||||
use self::entry::{PRESENT, WRITABLE};
|
||||
use self::mapper::Mapper;
|
||||
use self::table::{Table, Level4};
|
||||
use self::temporary_page::TemporaryPage;
|
||||
|
||||
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 temporary_page = TemporaryPage::new(Page { number: 0xcafebabe },
|
||||
let mut temporary_page = TemporaryPage::new(Page { number: 0x80000000 },
|
||||
allocator);
|
||||
|
||||
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| {
|
||||
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 {
|
||||
let frame = Frame::containing_address(PhysicalAddress::new(start + i * PAGE_SIZE));
|
||||
mapper.identity_map(frame, flags, allocator);
|
||||
|
@ -197,7 +201,7 @@ impl VirtualAddress {
|
|||
}
|
||||
|
||||
/// Page
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct Page {
|
||||
number: usize
|
||||
}
|
||||
|
@ -228,4 +232,30 @@ impl Page {
|
|||
"invalid address: 0x{:x}", address.get());
|
||||
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!("TRACE: {:>016X}", rbp);
|
||||
for i in 0..10 {
|
||||
for _frame in 0..16 { //Maximum 16 frames
|
||||
unsafe {
|
||||
let rip = *(rbp as *const usize).offset(1);
|
||||
println!(" {:>016X}: {:>016X}", rbp, rip);
|
||||
|
|
|
@ -85,10 +85,6 @@ extern crate arch_test as arch;
|
|||
#[macro_use]
|
||||
extern crate arch_x86_64 as arch;
|
||||
|
||||
/// Bump allocator
|
||||
#[cfg(all(not(test), target_arch = "x86_64"))]
|
||||
extern crate bump_allocator;
|
||||
|
||||
extern crate alloc;
|
||||
#[macro_use]
|
||||
extern crate collections;
|
||||
|
|
Loading…
Reference in a new issue