fix runs
This commit is contained in:
parent
7ba36c7041
commit
a5250bda6d
|
@ -1,7 +1,6 @@
|
||||||
use crate::println;
|
|
||||||
use alloc::alloc::{GlobalAlloc, Layout};
|
use alloc::alloc::{GlobalAlloc, Layout};
|
||||||
use bootloader::BootInfo;
|
|
||||||
use core::ptr::null_mut;
|
use core::ptr::null_mut;
|
||||||
|
use fixed_size_block::FixedSizeBlockAllocator;
|
||||||
use x86_64::{
|
use x86_64::{
|
||||||
structures::paging::{
|
structures::paging::{
|
||||||
mapper::MapToError, FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB,
|
mapper::MapToError, FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB,
|
||||||
|
@ -13,26 +12,12 @@ pub mod bump;
|
||||||
pub mod fixed_size_block;
|
pub mod fixed_size_block;
|
||||||
pub mod linked_list;
|
pub mod linked_list;
|
||||||
|
|
||||||
use fixed_size_block::FixedSizeBlockAllocator;
|
pub const HEAP_START: usize = 0x_4444_4444_0000;
|
||||||
|
pub const HEAP_SIZE: usize = 4 * 1024 * 1024; // 4 MiB
|
||||||
|
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static ALLOCATOR: Locked<FixedSizeBlockAllocator> = Locked::new(FixedSizeBlockAllocator::new());
|
static ALLOCATOR: Locked<FixedSizeBlockAllocator> = Locked::new(FixedSizeBlockAllocator::new());
|
||||||
|
|
||||||
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 be never called")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const HEAP_START: usize = 0x_4444_4444_0000;
|
|
||||||
pub const HEAP_SIZE: usize = 4 * 1024 * 1024; // 4 MiB
|
|
||||||
|
|
||||||
pub fn init_heap(
|
pub fn init_heap(
|
||||||
mapper: &mut impl Mapper<Size4KiB>,
|
mapper: &mut impl Mapper<Size4KiB>,
|
||||||
frame_allocator: &mut impl FrameAllocator<Size4KiB>,
|
frame_allocator: &mut impl FrameAllocator<Size4KiB>,
|
||||||
|
@ -53,17 +38,23 @@ pub fn init_heap(
|
||||||
mapper.map_to(page, frame, flags, frame_allocator)?.flush();
|
mapper.map_to(page, frame, flags, frame_allocator)?.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ALLOCATOR.lock().init(HEAP_START, HEAP_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(boot_info: &'static BootInfo) {
|
pub struct Dummy;
|
||||||
use crate::memory::{self, BootInfoFrameAllocator};
|
|
||||||
|
|
||||||
let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset);
|
unsafe impl GlobalAlloc for Dummy {
|
||||||
let mut mapper = unsafe { memory::init(phys_mem_offset) };
|
unsafe fn alloc(&self, _layout: Layout) -> *mut u8 {
|
||||||
let mut frame_allocator = unsafe { BootInfoFrameAllocator::init(&boot_info.memory_map) };
|
null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
init_heap(&mut mapper, &mut frame_allocator).expect("heap initialization failed");
|
unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {
|
||||||
|
panic!("dealloc should be never called")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A wrapper around spin::Mutex to permit trait implementations.
|
/// A wrapper around spin::Mutex to permit trait implementations.
|
||||||
|
|
|
@ -26,7 +26,7 @@ impl BumpAllocator {
|
||||||
/// memory range is unused. Also, this method must be called only once.
|
/// memory range is unused. Also, this method must be called only once.
|
||||||
pub unsafe fn init(&mut self, heap_start: usize, heap_size: usize) {
|
pub unsafe fn init(&mut self, heap_start: usize, heap_size: usize) {
|
||||||
self.heap_start = heap_start;
|
self.heap_start = heap_start;
|
||||||
self.heap_end = heap_start + heap_size;
|
self.heap_end = heap_start.saturating_add(heap_size);
|
||||||
self.next = heap_start;
|
self.next = heap_start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,16 +5,24 @@ use core::{
|
||||||
ptr::{self, NonNull},
|
ptr::{self, NonNull},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ListNode {
|
|
||||||
next: Option<&'static mut ListNode>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The block sizes to use.
|
/// The block sizes to use.
|
||||||
///
|
///
|
||||||
/// The sizes must each be power of 2 because they are also used as
|
/// The sizes must each be power of 2 because they are also used as
|
||||||
/// the block alignment (alignments must be always powers of 2).
|
/// the block alignment (alignments must be always powers of 2).
|
||||||
const BLOCK_SIZES: &[usize] = &[8, 16, 32, 64, 128, 256, 512, 1024, 2048];
|
const BLOCK_SIZES: &[usize] = &[8, 16, 32, 64, 128, 256, 512, 1024, 2048];
|
||||||
|
|
||||||
|
/// Choose an appropriate block size for the given layout.
|
||||||
|
///
|
||||||
|
/// Returns an index into the `BLOCK_SIZES` array.
|
||||||
|
fn list_index(layout: &Layout) -> Option<usize> {
|
||||||
|
let required_block_size = layout.size().max(layout.align());
|
||||||
|
BLOCK_SIZES.iter().position(|&s| s >= required_block_size)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ListNode {
|
||||||
|
next: Option<&'static mut ListNode>,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct FixedSizeBlockAllocator {
|
pub struct FixedSizeBlockAllocator {
|
||||||
list_heads: [Option<&'static mut ListNode>; BLOCK_SIZES.len()],
|
list_heads: [Option<&'static mut ListNode>; BLOCK_SIZES.len()],
|
||||||
fallback_allocator: linked_list_allocator::Heap,
|
fallback_allocator: linked_list_allocator::Heap,
|
||||||
|
@ -47,14 +55,6 @@ impl FixedSizeBlockAllocator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Choose an appropriate block size for the given layout.
|
|
||||||
///
|
|
||||||
/// Returns an index into the `BLOCK_SIZES` array.
|
|
||||||
fn list_index(layout: &Layout) -> Option<usize> {
|
|
||||||
let required_block_size = layout.size().max(layout.align());
|
|
||||||
BLOCK_SIZES.iter().position(|&s| s >= required_block_size)
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl GlobalAlloc for Locked<FixedSizeBlockAllocator> {
|
unsafe impl GlobalAlloc for Locked<FixedSizeBlockAllocator> {
|
||||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||||
let mut allocator = self.lock();
|
let mut allocator = self.lock();
|
||||||
|
|
|
@ -81,8 +81,7 @@ impl LinkedListAllocator {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Try to use the given region for an allocation with given size and
|
/// Try to use the given region for an allocation with given size and alignment.
|
||||||
/// alignment.
|
|
||||||
///
|
///
|
||||||
/// Returns the allocation start address on success.
|
/// Returns the allocation start address on success.
|
||||||
fn alloc_from_region(region: &ListNode, size: usize, align: usize) -> Result<usize, ()> {
|
fn alloc_from_region(region: &ListNode, size: usize, align: usize) -> Result<usize, ()> {
|
||||||
|
|
10
src/lib.rs
10
src/lib.rs
|
@ -31,12 +31,20 @@ use bootloader::BootInfo;
|
||||||
use core::panic::PanicInfo;
|
use core::panic::PanicInfo;
|
||||||
|
|
||||||
pub fn init(boot_info: &'static BootInfo) {
|
pub fn init(boot_info: &'static BootInfo) {
|
||||||
|
use x86_64::VirtAddr;
|
||||||
|
use self::memory::{self, BootInfoFrameAllocator};
|
||||||
|
|
||||||
println!("XeOS booting:");
|
println!("XeOS booting:");
|
||||||
gdt::init();
|
gdt::init();
|
||||||
interrupts::init_idt();
|
interrupts::init_idt();
|
||||||
unsafe { interrupts::PICS.lock().initialize() };
|
unsafe { interrupts::PICS.lock().initialize() };
|
||||||
x86_64::instructions::interrupts::enable();
|
x86_64::instructions::interrupts::enable();
|
||||||
allocator::init(&boot_info);
|
|
||||||
|
let phys_mem_offset = VirtAddr::new(boot_info.physical_memory_offset);
|
||||||
|
let mut mapper = unsafe { memory::init(phys_mem_offset) };
|
||||||
|
let mut frame_allocator = unsafe { BootInfoFrameAllocator::init(&boot_info.memory_map) };
|
||||||
|
|
||||||
|
allocator::init_heap(&mut mapper, &mut frame_allocator).expect("heap initialization failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hlt_loop() -> ! {
|
pub fn hlt_loop() -> ! {
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
use bootloader::bootinfo::{MemoryMap, MemoryRegionType};
|
use bootloader::bootinfo::{MemoryMap, MemoryRegionType};
|
||||||
use x86_64::{
|
use x86_64::{
|
||||||
structures::paging::{
|
structures::paging::{
|
||||||
FrameAllocator, Mapper, OffsetPageTable, Page, PageTable, PhysFrame, Size4KiB, UnusedPhysFrame,
|
FrameAllocator, Mapper, OffsetPageTable, Page, PageTable, PhysFrame, Size4KiB,
|
||||||
|
UnusedPhysFrame,
|
||||||
},
|
},
|
||||||
PhysAddr, VirtAddr,
|
PhysAddr, VirtAddr,
|
||||||
};
|
};
|
||||||
|
@ -35,6 +36,32 @@ unsafe fn active_level_4_table(physical_memory_offset: VirtAddr) -> &'static mut
|
||||||
&mut *page_table_ptr // unsafe
|
&mut *page_table_ptr // unsafe
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates an example mapping for the given page to frame `0xb8000`.
|
||||||
|
pub fn create_example_mapping(
|
||||||
|
page: Page,
|
||||||
|
mapper: &mut OffsetPageTable,
|
||||||
|
frame_allocator: &mut impl FrameAllocator<Size4KiB>,
|
||||||
|
) {
|
||||||
|
use x86_64::structures::paging::PageTableFlags as Flags;
|
||||||
|
|
||||||
|
let frame = PhysFrame::containing_address(PhysAddr::new(0xb8000));
|
||||||
|
// FIXME: ONLY FOR TEMPORARY TESTING
|
||||||
|
let unused_frame = unsafe { UnusedPhysFrame::new(frame) };
|
||||||
|
let flags = Flags::PRESENT | Flags::WRITABLE;
|
||||||
|
|
||||||
|
let map_to_result = mapper.map_to(page, unused_frame, flags, frame_allocator);
|
||||||
|
map_to_result.expect("map_to failed").flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A FrameAllocator that always returns `None`.
|
||||||
|
pub struct EmptyFrameAllocator;
|
||||||
|
|
||||||
|
unsafe impl FrameAllocator<Size4KiB> for EmptyFrameAllocator {
|
||||||
|
fn allocate_frame(&mut self) -> Option<UnusedPhysFrame> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A FrameAllocator that returns usable frames from the bootloader's memory map.
|
/// A FrameAllocator that returns usable frames from the bootloader's memory map.
|
||||||
pub struct BootInfoFrameAllocator {
|
pub struct BootInfoFrameAllocator {
|
||||||
memory_map: &'static MemoryMap,
|
memory_map: &'static MemoryMap,
|
||||||
|
@ -53,18 +80,14 @@ impl BootInfoFrameAllocator {
|
||||||
next: 0,
|
next: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl BootInfoFrameAllocator {
|
|
||||||
/// Returns an iterator over the usable frames specified in the memory map.
|
/// Returns an iterator over the usable frames specified in the memory map.
|
||||||
fn usable_frames(&self) -> impl Iterator<Item = UnusedPhysFrame> {
|
fn usable_frames(&self) -> impl Iterator<Item = UnusedPhysFrame> {
|
||||||
// get usable regions from memory map
|
// get usable regions from memory map
|
||||||
let regions = self.memory_map.iter();
|
let regions = self.memory_map.iter();
|
||||||
let usable_regions = regions
|
let usable_regions = regions.filter(|r| r.region_type == MemoryRegionType::Usable);
|
||||||
.filter(|r| r.region_type == MemoryRegionType::Usable);
|
|
||||||
// map each region to its address range
|
// map each region to its address range
|
||||||
let addr_ranges = usable_regions
|
let addr_ranges = usable_regions.map(|r| r.range.start_addr()..r.range.end_addr());
|
||||||
.map(|r| r.range.start_addr()..r.range.end_addr());
|
|
||||||
// transform to an iterator of frame start addresses
|
// transform to an iterator of frame start addresses
|
||||||
let frame_addresses = addr_ranges.flat_map(|r| r.step_by(4096));
|
let frame_addresses = addr_ranges.flat_map(|r| r.step_by(4096));
|
||||||
// create `PhysFrame` types from the start addresses
|
// create `PhysFrame` types from the start addresses
|
||||||
|
@ -81,4 +104,3 @@ unsafe impl FrameAllocator<Size4KiB> for BootInfoFrameAllocator {
|
||||||
frame
|
frame
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue