2021-07-16 08:19:18 +00:00
|
|
|
use crate::sys;
|
2022-06-09 20:59:33 +00:00
|
|
|
|
2020-02-05 18:32:40 +00:00
|
|
|
use alloc::slice::SliceIndex;
|
2020-10-31 22:20:41 +00:00
|
|
|
use alloc::sync::Arc;
|
2021-07-25 10:41:44 +00:00
|
|
|
use alloc::vec;
|
2020-02-05 18:32:40 +00:00
|
|
|
use alloc::vec::Vec;
|
2021-10-04 19:37:47 +00:00
|
|
|
use core::cmp;
|
2020-02-05 18:32:40 +00:00
|
|
|
use core::ops::{Index, IndexMut};
|
2020-01-18 19:48:01 +00:00
|
|
|
use linked_list_allocator::LockedHeap;
|
2020-10-31 22:20:41 +00:00
|
|
|
use spin::Mutex;
|
2020-02-05 18:32:40 +00:00
|
|
|
use x86_64::structures::paging::mapper::MapToError;
|
2020-07-11 18:33:55 +00:00
|
|
|
use x86_64::structures::paging::{FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB};
|
|
|
|
use x86_64::VirtAddr;
|
2020-01-18 19:48:01 +00:00
|
|
|
|
2021-09-26 20:50:45 +00:00
|
|
|
pub const HEAP_START: usize = 0x4444_4444_0000;
|
2020-01-18 19:48:01 +00:00
|
|
|
|
|
|
|
#[global_allocator]
|
|
|
|
static ALLOCATOR: LockedHeap = LockedHeap::empty();
|
|
|
|
|
2020-04-13 11:14:04 +00:00
|
|
|
pub fn init_heap(mapper: &mut impl Mapper<Size4KiB>, frame_allocator: &mut impl FrameAllocator<Size4KiB>) -> Result<(), MapToError<Size4KiB>> {
|
2021-10-24 16:23:01 +00:00
|
|
|
// Use half of the memory for the heap, caped to 16 MB because the allocator is too slow
|
2021-10-04 19:37:47 +00:00
|
|
|
let heap_size = cmp::min(sys::mem::memory_size() / 2, 16 << 20);
|
|
|
|
|
2021-10-14 07:49:30 +00:00
|
|
|
let pages = {
|
2020-01-18 19:48:01 +00:00
|
|
|
let heap_start = VirtAddr::new(HEAP_START as u64);
|
2021-10-04 19:37:47 +00:00
|
|
|
let heap_end = heap_start + heap_size - 1u64;
|
2020-01-18 19:48:01 +00:00
|
|
|
let heap_start_page = Page::containing_address(heap_start);
|
|
|
|
let heap_end_page = Page::containing_address(heap_end);
|
|
|
|
Page::range_inclusive(heap_start_page, heap_end_page)
|
|
|
|
};
|
|
|
|
|
2021-08-07 09:29:45 +00:00
|
|
|
let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE;
|
2021-10-14 07:49:30 +00:00
|
|
|
for page in pages {
|
2020-01-18 19:48:01 +00:00
|
|
|
let frame = frame_allocator.allocate_frame().ok_or(MapToError::FrameAllocationFailed)?;
|
2020-04-13 11:14:04 +00:00
|
|
|
unsafe {
|
|
|
|
mapper.map_to(page, frame, flags, frame_allocator)?.flush();
|
|
|
|
}
|
2020-01-18 19:48:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
unsafe {
|
2021-10-04 19:37:47 +00:00
|
|
|
ALLOCATOR.lock().init(HEAP_START, heap_size as usize);
|
2020-01-18 19:48:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2020-02-05 18:32:40 +00:00
|
|
|
|
2022-06-14 20:43:33 +00:00
|
|
|
pub fn alloc_pages(addr: u64, size: usize) {
|
|
|
|
//debug!("Alloc pages (addr={:#x}, size={})", addr, size);
|
2021-11-27 08:56:52 +00:00
|
|
|
let mut mapper = unsafe { sys::mem::mapper(VirtAddr::new(sys::mem::PHYS_MEM_OFFSET)) };
|
|
|
|
let mut frame_allocator = unsafe { sys::mem::BootInfoFrameAllocator::init(sys::mem::MEMORY_MAP.unwrap()) };
|
|
|
|
let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE | PageTableFlags::USER_ACCESSIBLE;
|
|
|
|
let pages = {
|
|
|
|
let start_page = Page::containing_address(VirtAddr::new(addr));
|
2022-06-14 20:43:33 +00:00
|
|
|
let end_page = Page::containing_address(VirtAddr::new(addr + (size as u64) - 1));
|
2021-11-27 08:56:52 +00:00
|
|
|
Page::range_inclusive(start_page, end_page)
|
|
|
|
};
|
|
|
|
for page in pages {
|
2022-06-14 20:43:33 +00:00
|
|
|
//debug!("Alloc page {:?}", page);
|
2022-06-06 13:53:45 +00:00
|
|
|
if let Some(frame) = frame_allocator.allocate_frame() {
|
|
|
|
unsafe {
|
|
|
|
if let Ok(mapping) = mapper.map_to(page, frame, flags, &mut frame_allocator) {
|
|
|
|
mapping.flush();
|
|
|
|
} else {
|
|
|
|
//debug!("Could not map {:?}", page);
|
|
|
|
}
|
2021-11-27 08:56:52 +00:00
|
|
|
}
|
2022-06-06 13:53:45 +00:00
|
|
|
} else {
|
|
|
|
//debug!("Could not allocate frame for {:?}", page);
|
2021-11-27 08:56:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
use x86_64::structures::paging::page::PageRangeInclusive;
|
|
|
|
|
|
|
|
// TODO: Replace `free` by `dealloc`
|
2022-06-14 20:43:33 +00:00
|
|
|
pub fn free_pages(addr: u64, size: usize) {
|
2021-11-27 08:56:52 +00:00
|
|
|
let mut mapper = unsafe { sys::mem::mapper(VirtAddr::new(sys::mem::PHYS_MEM_OFFSET)) };
|
|
|
|
let pages: PageRangeInclusive<Size4KiB> = {
|
|
|
|
let start_page = Page::containing_address(VirtAddr::new(addr));
|
2022-06-14 20:43:33 +00:00
|
|
|
let end_page = Page::containing_address(VirtAddr::new(addr + (size as u64) - 1));
|
2021-11-27 08:56:52 +00:00
|
|
|
Page::range_inclusive(start_page, end_page)
|
|
|
|
};
|
|
|
|
for page in pages {
|
|
|
|
if let Ok((_frame, mapping)) = mapper.unmap(page) {
|
|
|
|
mapping.flush();
|
|
|
|
} else {
|
|
|
|
//debug!("Could not unmap {:?}", page);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-31 22:20:41 +00:00
|
|
|
#[derive(Clone)]
|
2020-02-05 18:32:40 +00:00
|
|
|
pub struct PhysBuf {
|
2020-10-31 22:20:41 +00:00
|
|
|
buf: Arc<Mutex<Vec<u8>>>,
|
2020-02-05 18:32:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl PhysBuf {
|
|
|
|
pub fn new(len: usize) -> Self {
|
2021-07-25 10:41:44 +00:00
|
|
|
Self::from(vec![0; len])
|
2020-02-05 18:32:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Realloc vec until it uses a chunk of contiguous physical memory
|
|
|
|
fn from(vec: Vec<u8>) -> Self {
|
|
|
|
let buffer_len = vec.len() - 1;
|
|
|
|
let memory_len = phys_addr(&vec[buffer_len]) - phys_addr(&vec[0]);
|
|
|
|
if buffer_len == memory_len as usize {
|
2020-10-31 22:20:41 +00:00
|
|
|
Self { buf: Arc::new(Mutex::new(vec)) }
|
2020-02-05 18:32:40 +00:00
|
|
|
} else {
|
2021-07-25 10:41:44 +00:00
|
|
|
Self::from(vec.clone()) // Clone vec and try again
|
2020-02-05 18:32:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn addr(&self) -> u64 {
|
2020-10-31 22:20:41 +00:00
|
|
|
phys_addr(&self.buf.lock()[0])
|
2020-02-05 18:32:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-11 17:06:16 +00:00
|
|
|
pub fn phys_addr(ptr: *const u8) -> u64 {
|
|
|
|
let virt_addr = VirtAddr::new(ptr as u64);
|
2021-07-16 08:19:18 +00:00
|
|
|
let phys_addr = sys::mem::virt_to_phys(virt_addr).unwrap();
|
2020-02-05 18:32:40 +00:00
|
|
|
phys_addr.as_u64()
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<I: SliceIndex<[u8]>> Index<I> for PhysBuf {
|
|
|
|
type Output = I::Output;
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
fn index(&self, index: I) -> &Self::Output {
|
|
|
|
Index::index(&**self, index)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<I: SliceIndex<[u8]>> IndexMut<I> for PhysBuf {
|
|
|
|
#[inline]
|
|
|
|
fn index_mut(&mut self, index: I) -> &mut Self::Output {
|
|
|
|
IndexMut::index_mut(&mut **self, index)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl core::ops::Deref for PhysBuf {
|
|
|
|
type Target = [u8];
|
|
|
|
|
|
|
|
fn deref(&self) -> &[u8] {
|
2020-10-31 22:20:41 +00:00
|
|
|
let vec = self.buf.lock();
|
|
|
|
unsafe { alloc::slice::from_raw_parts(vec.as_ptr(), vec.len()) }
|
2020-02-05 18:32:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl core::ops::DerefMut for PhysBuf {
|
|
|
|
fn deref_mut(&mut self) -> &mut [u8] {
|
2020-10-31 22:20:41 +00:00
|
|
|
let mut vec = self.buf.lock();
|
|
|
|
unsafe { alloc::slice::from_raw_parts_mut(vec.as_mut_ptr(), vec.len()) }
|
2020-02-05 18:32:40 +00:00
|
|
|
}
|
|
|
|
}
|
2020-11-10 21:11:33 +00:00
|
|
|
|
2021-08-07 09:29:45 +00:00
|
|
|
pub fn memory_size() -> usize {
|
2020-11-10 21:11:33 +00:00
|
|
|
ALLOCATOR.lock().size()
|
|
|
|
}
|
|
|
|
|
2021-08-07 09:29:45 +00:00
|
|
|
pub fn memory_used() -> usize {
|
2020-11-10 21:11:33 +00:00
|
|
|
ALLOCATOR.lock().used()
|
|
|
|
}
|
|
|
|
|
2021-08-07 09:29:45 +00:00
|
|
|
pub fn memory_free() -> usize {
|
2020-11-10 21:11:33 +00:00
|
|
|
ALLOCATOR.lock().free()
|
|
|
|
}
|
2020-11-14 20:52:07 +00:00
|
|
|
|
|
|
|
#[test_case]
|
|
|
|
fn many_boxes() {
|
|
|
|
use alloc::boxed::Box;
|
|
|
|
|
|
|
|
let heap_value_1 = Box::new(42);
|
|
|
|
let heap_value_2 = Box::new(1337);
|
|
|
|
assert_eq!(*heap_value_1, 42);
|
|
|
|
assert_eq!(*heap_value_2, 1337);
|
|
|
|
|
|
|
|
for i in 0..1000 {
|
|
|
|
let x = Box::new(i);
|
|
|
|
assert_eq!(*x, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test_case]
|
|
|
|
fn large_vec() {
|
|
|
|
let n = 1000;
|
|
|
|
let mut vec = Vec::new();
|
|
|
|
for i in 0..n {
|
|
|
|
vec.push(i);
|
|
|
|
}
|
|
|
|
assert_eq!(vec.iter().sum::<u64>(), (n - 1) * n / 2);
|
|
|
|
}
|