Implement memory allocation
This commit is contained in:
parent
8b3a4b4b9a
commit
bfeafc9892
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -42,6 +42,7 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bootloader 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"bootloader 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"linked_list_allocator 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"polling_serial 0.1.0",
|
"polling_serial 0.1.0",
|
||||||
"vga_buffer 0.1.0",
|
"vga_buffer 0.1.0",
|
||||||
"volatile 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"volatile 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
@ -56,6 +57,14 @@ dependencies = [
|
|||||||
"spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linked_list_allocator"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nodrop"
|
name = "nodrop"
|
||||||
version = "0.1.13"
|
version = "0.1.13"
|
||||||
@ -114,6 +123,7 @@ dependencies = [
|
|||||||
"checksum bootloader 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abfbe6cdea6367860818facc8e4a184f003cb83d7d004acaaf57baebf1949da0"
|
"checksum bootloader 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abfbe6cdea6367860818facc8e4a184f003cb83d7d004acaaf57baebf1949da0"
|
||||||
"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427"
|
"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427"
|
||||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
"checksum linked_list_allocator 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "47314ec1d29aa869ee7cb5a5be57be9b1055c56567d59c3fb6689926743e0bea"
|
||||||
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
|
"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945"
|
||||||
"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||||
"checksum ux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dfeb711b61ce620c0cb6fd9f8e3e678622f0c971da2a63c4b3e25e88ed012f"
|
"checksum ux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dfeb711b61ce620c0cb6fd9f8e3e678622f0c971da2a63c4b3e25e88ed012f"
|
||||||
|
@ -27,6 +27,7 @@ x86_64 = "0.7.5"
|
|||||||
vga_buffer = { path = "vga_buffer" }
|
vga_buffer = { path = "vga_buffer" }
|
||||||
polling_serial = { path = "polling_serial" }
|
polling_serial = { path = "polling_serial" }
|
||||||
volatile = "0.2.6"
|
volatile = "0.2.6"
|
||||||
|
linked_list_allocator = "0.6.4"
|
||||||
|
|
||||||
[dependencies.lazy_static]
|
[dependencies.lazy_static]
|
||||||
version = "1.0"
|
version = "1.0"
|
||||||
|
58
src/allocator.rs
Normal file
58
src/allocator.rs
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
use alloc::alloc::{GlobalAlloc, Layout};
|
||||||
|
use core::ptr::null_mut;
|
||||||
|
use polling_serial::serial_println;
|
||||||
|
use x86_64::instructions::bochs_breakpoint;
|
||||||
|
use x86_64::structures::paging::mapper::MapToError::PageAlreadyMapped;
|
||||||
|
use x86_64::{
|
||||||
|
structures::paging::{
|
||||||
|
mapper::MapToError, FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB,
|
||||||
|
},
|
||||||
|
VirtAddr,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const HEAP_START: usize = 0x4444_4444_0000;
|
||||||
|
pub const HEAP_SIZE: usize = 0x1 << 20; // 1MB Heap
|
||||||
|
|
||||||
|
pub struct Dummy;
|
||||||
|
|
||||||
|
unsafe impl GlobalAlloc for Dummy {
|
||||||
|
unsafe fn alloc(&self, _layout: Layout) -> *mut u8 {
|
||||||
|
null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
|
||||||
|
panic!("dealloc should never be called");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_heap(
|
||||||
|
mapper: &mut impl Mapper<Size4KiB>,
|
||||||
|
frame_allocator: &mut impl FrameAllocator<Size4KiB>,
|
||||||
|
) -> Result<(), MapToError> {
|
||||||
|
let page_range = {
|
||||||
|
let heap_start = VirtAddr::new(HEAP_START as u64);
|
||||||
|
let heap_end = heap_start + HEAP_SIZE as u64 - 1u64;
|
||||||
|
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)
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut i = 0;
|
||||||
|
for page in page_range {
|
||||||
|
let frame = frame_allocator
|
||||||
|
.allocate_frame()
|
||||||
|
.ok_or(MapToError::FrameAllocationFailed)?;
|
||||||
|
let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE;
|
||||||
|
unsafe { mapper.map_to(page, frame, flags, frame_allocator)?.flush() };
|
||||||
|
if i == 0 {
|
||||||
|
serial_println!("Mapped {:?} at {:?}", page, frame);
|
||||||
|
}
|
||||||
|
i = i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
super::ALLOCATOR.lock().init(HEAP_START, HEAP_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
37
src/lib.rs
37
src/lib.rs
@ -5,24 +5,20 @@
|
|||||||
#![reexport_test_harness_main = "test_main"]
|
#![reexport_test_harness_main = "test_main"]
|
||||||
#![feature(abi_x86_interrupt)]
|
#![feature(abi_x86_interrupt)]
|
||||||
#![feature(asm)]
|
#![feature(asm)]
|
||||||
|
#![feature(alloc_error_handler)]
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
use core::panic::PanicInfo;
|
pub mod allocator;
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
use vga_buffer::print;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
use polling_serial::serial_print;
|
|
||||||
|
|
||||||
use polling_serial::serial_println;
|
|
||||||
|
|
||||||
use vga_buffer::println;
|
|
||||||
use x86_64::instructions::bochs_breakpoint;
|
|
||||||
|
|
||||||
pub mod gdt;
|
pub mod gdt;
|
||||||
pub mod interrupts;
|
pub mod interrupts;
|
||||||
pub mod memory;
|
pub mod memory;
|
||||||
|
|
||||||
|
use core::panic::PanicInfo;
|
||||||
|
use linked_list_allocator::LockedHeap;
|
||||||
|
use polling_serial::serial_println;
|
||||||
|
use vga_buffer::println;
|
||||||
|
use x86_64::instructions::bochs_breakpoint;
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
pub enum QemuExitCode {
|
pub enum QemuExitCode {
|
||||||
@ -30,8 +26,15 @@ pub enum QemuExitCode {
|
|||||||
Failed = 0x11,
|
Failed = 0x11,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom panic handler, required for freestanding program
|
#[global_allocator]
|
||||||
|
static ALLOCATOR: LockedHeap = LockedHeap::empty();
|
||||||
|
|
||||||
|
#[alloc_error_handler]
|
||||||
|
fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! {
|
||||||
|
panic!("allocation error: {:?}", layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom panic handler, required for freestanding program
|
||||||
pub fn test_panic_handler(info: &PanicInfo) -> ! {
|
pub fn test_panic_handler(info: &PanicInfo) -> ! {
|
||||||
serial_println!("[failed]\n");
|
serial_println!("[failed]\n");
|
||||||
serial_println!("Error: {}\n", info);
|
serial_println!("Error: {}\n", info);
|
||||||
@ -73,6 +76,12 @@ pub fn hlt_loop() -> ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use vga_buffer::print;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use polling_serial::serial_print;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use bootloader::{entry_point, BootInfo};
|
use bootloader::{entry_point, BootInfo};
|
||||||
|
|
||||||
|
32
src/main.rs
32
src/main.rs
@ -6,24 +6,24 @@
|
|||||||
#![feature(custom_test_frameworks)]
|
#![feature(custom_test_frameworks)]
|
||||||
#![test_runner(dendrobates_tinctoreus_azureus::test_runner)]
|
#![test_runner(dendrobates_tinctoreus_azureus::test_runner)]
|
||||||
#![reexport_test_harness_main = "test_main"]
|
#![reexport_test_harness_main = "test_main"]
|
||||||
|
extern crate alloc;
|
||||||
use polling_serial::serial_println;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use polling_serial::serial_print;
|
use polling_serial::serial_print;
|
||||||
|
|
||||||
use vga_buffer::println;
|
use alloc::boxed::Box;
|
||||||
|
|
||||||
use core::panic::PanicInfo;
|
|
||||||
use vga_buffer; // required for custom panic handler
|
|
||||||
|
|
||||||
use x86_64;
|
|
||||||
|
|
||||||
use bootloader::{entry_point, BootInfo};
|
use bootloader::{entry_point, BootInfo};
|
||||||
|
use core::panic::PanicInfo;
|
||||||
|
use dendrobates_tinctoreus_azureus::allocator;
|
||||||
|
use polling_serial::serial_println;
|
||||||
|
use vga_buffer; // required for custom panic handler
|
||||||
|
use vga_buffer::println;
|
||||||
|
use x86_64;
|
||||||
|
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
use dendrobates_tinctoreus_azureus::hlt_loop;
|
use dendrobates_tinctoreus_azureus::hlt_loop;
|
||||||
|
|
||||||
|
use dendrobates_tinctoreus_azureus::memory::create_example_mapping;
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
use vga_buffer::{set_colors, Color, ForegroundColor};
|
use vga_buffer::{set_colors, Color, ForegroundColor};
|
||||||
|
|
||||||
@ -59,6 +59,9 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! {
|
|||||||
|
|
||||||
let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset);
|
let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset);
|
||||||
// new: initialize a mapper
|
// new: initialize a mapper
|
||||||
|
let mut frame_allocator =
|
||||||
|
unsafe { memory::BootInfoFrameAllocator::init(&boot_info.memory_map) };
|
||||||
|
|
||||||
let mut mapper = unsafe { memory::init(phys_mem_offset) };
|
let mut mapper = unsafe { memory::init(phys_mem_offset) };
|
||||||
|
|
||||||
let addresses = [
|
let addresses = [
|
||||||
@ -79,16 +82,9 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! {
|
|||||||
serial_println!("{:?} -> {:?}", virt, phys);
|
serial_println!("{:?} -> {:?}", virt, phys);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut frame_allocator =
|
allocator::init_heap(&mut mapper, &mut frame_allocator).expect("heap initialization failed");
|
||||||
unsafe { memory::BootInfoFrameAllocator::init(&boot_info.memory_map) };
|
|
||||||
|
|
||||||
// map an unused page
|
let x = Box::new(41);
|
||||||
let page = Page::containing_address(VirtAddr::new(0));
|
|
||||||
memory::create_example_mapping(page, &mut mapper, &mut frame_allocator);
|
|
||||||
|
|
||||||
// write the string `New!` to the screen through the new mapping
|
|
||||||
let page_ptr: *mut u64 = page.start_address().as_mut_ptr();
|
|
||||||
unsafe { page_ptr.offset(400).write_volatile(0x_f021_f077_f065_f04e) };
|
|
||||||
|
|
||||||
serial_println!("Preparing nasty fault...");
|
serial_println!("Preparing nasty fault...");
|
||||||
unsafe {
|
unsafe {
|
||||||
|
Loading…
Reference in New Issue
Block a user