mirror of
https://github.com/realmicrosoft/windows.git
synced 2024-08-14 22:46:44 +00:00
heap
This commit is contained in:
parent
1d810657ff
commit
10df1c6cfa
8 changed files with 149 additions and 27 deletions
|
@ -1,7 +0,0 @@
|
|||
[target.'cfg(target_os = "none")']
|
||||
runner = "cargo run --package simple_boot --"
|
||||
|
||||
[alias]
|
||||
kbuild = "build --target x86_64-custom.json -Zbuild-std=core -Zbuild-std-features=compiler-builtins-mem"
|
||||
kimage = "run --target x86_64-custom.json -Zbuild-std=core -Zbuild-std-features=compiler-builtins-mem -- --no-run"
|
||||
krun = "run --target x86_64-custom.json -Zbuild-std=core -Zbuild-std-features=compiler-builtins-mem"
|
|
@ -11,10 +11,12 @@ spin = "0.9.1"
|
|||
x86_64 = "0.14.10"
|
||||
rlibc = "1.0"
|
||||
multiboot2 = { version = "0.14.0", optional = true }
|
||||
linked_list_allocator = { version = "0.9.0", optional = true }
|
||||
[dependencies.lazy_static]
|
||||
version = "1.4.0"
|
||||
features = ["spin_no_std"]
|
||||
|
||||
[features]
|
||||
default = ["f_multiboot2"]
|
||||
default = ["f_multiboot2", "f_ll_alloc"]
|
||||
f_multiboot2 = ["dep:multiboot2"]
|
||||
f_ll_alloc = ["dep:linked_list_allocator"]
|
2
Makefile
2
Makefile
|
@ -44,7 +44,7 @@ $(final): $(kernel) $(linker_script) $(assembly_object_files)
|
|||
--gc-sections
|
||||
|
||||
$(kernel):
|
||||
@RUST_TARGET_PATH=$(shell pwd) xargo build --target $(target) -Zbuild-std=core --features "f_multiboot2"
|
||||
@RUST_TARGET_PATH=$(shell pwd) xargo build --target $(target) -Zbuild-std=core,alloc --features "f_multiboot2"
|
||||
|
||||
build/arch/$(arch)/%.o: arch/$(arch)/%.asm
|
||||
@mkdir -p $(shell dirname $@)
|
||||
|
|
|
@ -12,5 +12,7 @@ BdsDxe: starting Boot0001 "UEFI QEMU DVD-ROM QM00003 " from PciRoot(0x0)/Pci(0x1
|
|||
|
||||
welcome to wukkOS!
|
||||
(c) 2022 Real Microsoft, LLC
|
||||
initialising memory maps...[OK]
|
||||
L4 entry 0: PageTableEntry { addr: PhysAddr(0x128000), flags: PRESENT | WRITABLE | ACCESSED }
|
||||
initialising mapper...[OK]
|
||||
initialising frame allocator...[OK]
|
||||
initialising heap...[OK]
|
||||
testing heap...[OK]
|
||||
|
|
|
@ -32,6 +32,12 @@ impl KernelInfo {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "f_multiboot2")]
|
||||
pub fn get_memory_tag(&self) -> &MemoryMapTag {
|
||||
let mm_tag = self.boot_info.memory_map_tag().expect("no memory map tag").clone();
|
||||
mm_tag
|
||||
}
|
||||
|
||||
#[cfg(feature = "f_multiboot2")]
|
||||
pub fn memory_areas(&self) -> impl Iterator<Item = &multiboot2::MemoryArea> {
|
||||
let mm_tag = self.boot_info.memory_map_tag().expect("ERR NO MEM MAP TAG!");
|
||||
|
@ -41,4 +47,8 @@ impl KernelInfo {
|
|||
pub fn is_safe_memory(&self, addr: u64) -> bool {
|
||||
addr >= self.safe_mem_start && addr >= self.kernel_end
|
||||
}
|
||||
|
||||
pub fn safe_memory_start(&self) -> u64 {
|
||||
self.safe_mem_start
|
||||
}
|
||||
}
|
41
src/lib.rs
41
src/lib.rs
|
@ -2,19 +2,24 @@
|
|||
#![feature(default_alloc_error_handler)]
|
||||
#![feature(panic_info_message)]
|
||||
#![feature(asm_const)]
|
||||
#![feature(alloc_error_handler)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
extern crate rlibc;
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::rc::Rc;
|
||||
use alloc::vec;
|
||||
use lazy_static::lazy_static;
|
||||
use core::panic::PanicInfo;
|
||||
use multiboot2::MemoryAreaType;
|
||||
use spin::Mutex;
|
||||
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
|
||||
use x86_64::VirtAddr;
|
||||
use x86_64::{PhysAddr, VirtAddr};
|
||||
use x86_64::structures::paging::Translate;
|
||||
use crate::boot::KernelInfo;
|
||||
use crate::internals::WhyDoTheyCallItOvenWhenYouOfInTheColdFoodOfOutHotEatTheFood::*;
|
||||
use crate::memory::active_level_4_table;
|
||||
use crate::serial::terminal::ST;
|
||||
|
||||
mod font;
|
||||
|
@ -38,6 +43,10 @@ lazy_static! {
|
|||
|
||||
const RAINBOW : [Colour; 6] = [Colour{r:255,g:0,b:0}, Colour{r:255,g:127,b:0}, Colour{r:255,g:255,b:0}, Colour{r:0,g:255,b:0}, Colour{r:0,g:255,b:255}, Colour{r:0,g:0,b:255}];
|
||||
|
||||
#[alloc_error_handler]
|
||||
fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! {
|
||||
panic!("allocation error: {:?}", layout)
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(info: &PanicInfo) -> ! {
|
||||
|
@ -89,17 +98,29 @@ pub extern fn kernel_main(args: KernelArgs) -> ! {
|
|||
println!();
|
||||
println!("welcome to wukkOS!");
|
||||
println!("(c) 2022 Real Microsoft, LLC");
|
||||
print!("initialising memory maps...");
|
||||
let kern_info = KernelInfo::init_from_kernel_args(args);
|
||||
let mut mem_areas = kern_info.memory_areas();
|
||||
let kern_info = Mutex::new(KernelInfo::init_from_kernel_args(args));
|
||||
print!("initialising mapper...");
|
||||
let mut mapper = unsafe { memory::init(VirtAddr::new(0)) };
|
||||
println!("[OK]");
|
||||
print!("initialising frame allocator...");
|
||||
let mut frame_allocator = unsafe { memory::BootInfoFrameAllocator::init(kern_info) };
|
||||
println!("[OK]");
|
||||
print!("initialising heap...");
|
||||
memory::allocator::init_heap(&mut mapper, &mut frame_allocator).expect("heap init failed");
|
||||
println!("[OK]");
|
||||
let l4_table = active_level_4_table(VirtAddr::new(0));
|
||||
|
||||
for (i, entry) in l4_table.iter().enumerate() {
|
||||
if !entry.is_unused() {
|
||||
println!("L4 entry {}: {:?}", i, entry);
|
||||
}
|
||||
print!("testing heap...");
|
||||
let reference_counted = Rc::new(vec![1, 2, 3]);
|
||||
let cloned = reference_counted.clone();
|
||||
let test_1 = Rc::strong_count(&reference_counted) == 2;
|
||||
drop(cloned);
|
||||
let test_2 = Rc::strong_count(&reference_counted) == 1;
|
||||
if test_1 && test_2 {
|
||||
println!("[OK]");
|
||||
} else {
|
||||
println!("[FAIL]");
|
||||
}
|
||||
drop(reference_counted);
|
||||
|
||||
loop {}
|
||||
}
|
41
src/memory/allocator.rs
Normal file
41
src/memory/allocator.rs
Normal file
|
@ -0,0 +1,41 @@
|
|||
use x86_64::structures::paging::{FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB};
|
||||
use x86_64::structures::paging::mapper::MapToError;
|
||||
use x86_64::VirtAddr;
|
||||
|
||||
pub const HEAP_START: u64 = 0x_4444_4444_0000;
|
||||
pub const HEAP_SIZE: u64 = 100 * 1024; // 100 KiB
|
||||
|
||||
#[cfg(feature = "f_ll_alloc")]
|
||||
use linked_list_allocator::LockedHeap;
|
||||
|
||||
#[global_allocator]
|
||||
static ALLOCATOR: LockedHeap = LockedHeap::empty();
|
||||
|
||||
pub fn init_heap(
|
||||
mapper: &mut impl Mapper<Size4KiB>,
|
||||
frame_allocator: &mut impl FrameAllocator<Size4KiB>,
|
||||
) -> Result<(), MapToError<Size4KiB>> {
|
||||
let page_range = {
|
||||
let heap_start = VirtAddr::new(HEAP_START as u64);
|
||||
let heap_end = heap_start + HEAP_SIZE - 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)
|
||||
};
|
||||
|
||||
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()
|
||||
};
|
||||
}
|
||||
|
||||
unsafe {
|
||||
ALLOCATOR.lock().init(HEAP_START as usize, HEAP_SIZE as usize);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,15 +1,68 @@
|
|||
use x86_64::registers::control::Cr3;
|
||||
use x86_64::structures::paging::PageTable;
|
||||
use x86_64::VirtAddr;
|
||||
pub mod allocator;
|
||||
|
||||
pub fn active_level_4_table(physical_memory_offset: VirtAddr) -> &'static mut PageTable {
|
||||
use x86_64::structures::paging::{FrameAllocator, OffsetPageTable, PageTable, PhysFrame, Size4KiB};
|
||||
use x86_64::{PhysAddr, VirtAddr};
|
||||
|
||||
pub unsafe fn init(phys_mem_offset: VirtAddr) -> OffsetPageTable<'static> {
|
||||
let level_4_table = active_level_4_table(phys_mem_offset);
|
||||
OffsetPageTable::new(level_4_table, phys_mem_offset)
|
||||
}
|
||||
|
||||
unsafe fn active_level_4_table(phys_mem_offset: VirtAddr) -> &'static mut PageTable {
|
||||
use x86_64::registers::control::Cr3;
|
||||
|
||||
let (level_4_table_frame, _) = Cr3::read();
|
||||
|
||||
let phys = level_4_table_frame.start_address();
|
||||
let virt = physical_memory_offset + phys.as_u64();
|
||||
let virt = phys_mem_offset + phys.as_u64();
|
||||
let page_table_ptr: *mut PageTable = virt.as_mut_ptr();
|
||||
|
||||
unsafe { &mut *page_table_ptr } // unsafe
|
||||
}
|
||||
|
||||
#[cfg(feature = "f_multiboot2")]
|
||||
use multiboot2::{MemoryMapTag, BootInformation};
|
||||
use spin::Mutex;
|
||||
use crate::boot::KernelInfo;
|
||||
|
||||
pub struct BootInfoFrameAllocator {
|
||||
kern_info: Mutex<KernelInfo>,
|
||||
next: usize,
|
||||
}
|
||||
|
||||
impl BootInfoFrameAllocator {
|
||||
#[cfg(feature = "f_multiboot2")]
|
||||
pub unsafe fn init(kern_info: Mutex<crate::boot::KernelInfo>) -> Self {
|
||||
Self {
|
||||
kern_info,
|
||||
next: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl FrameAllocator<Size4KiB> for BootInfoFrameAllocator {
|
||||
fn allocate_frame(&mut self) -> Option<PhysFrame> {
|
||||
#[cfg(feature = "f_multiboot2")] {
|
||||
let mut kern_lock = self.kern_info.lock();
|
||||
let mut usable_frames = kern_lock
|
||||
.memory_areas();
|
||||
let mut usable_frames = usable_frames
|
||||
.map(|area| {
|
||||
let frame_addr = area.start_address();
|
||||
let frame_end = area.end_address();
|
||||
let frame_size = frame_end - frame_addr;
|
||||
let num_frames = frame_size / 4096;
|
||||
let start_frame = PhysFrame::containing_address(PhysAddr::new(frame_addr));
|
||||
(0..num_frames).map(move |i| start_frame + i)
|
||||
})
|
||||
.flatten();
|
||||
let frame = usable_frames.nth(self.next).clone();
|
||||
self.next += 1;
|
||||
|
||||
// ensure unlock
|
||||
unsafe { self.kern_info.force_unlock() };
|
||||
|
||||
frame
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue