compiles. In progress new custom allocator

This commit is contained in:
mtgmonkey 2025-05-13 13:38:57 -04:00
parent a46f795b5a
commit b2475a7b27
16 changed files with 763 additions and 23 deletions

View file

@ -1,6 +1,6 @@
[unstable]
build-std = ["core", "compiler_builtins"] # recompile these
build-std-features = ["compiler-builtins-mem"]
build-std = ["alloc", "core", "compiler_builtins"] # recompile these
build-std-features = [ "compiler-builtins-mem" ]
[build]
target = "x86_64-rustboot.json" # target OS specifications

160
Cargo.lock generated
View file

@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
version = 4
[[package]]
name = "autocfg"
@ -20,6 +20,27 @@ version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
[[package]]
name = "derive_more"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05"
dependencies = [
"derive_more-impl",
]
[[package]]
name = "derive_more-impl"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.101",
"unicode-xid",
]
[[package]]
name = "lazy_static"
version = "1.5.0"
@ -39,6 +60,89 @@ dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
[[package]]
name = "multiboot2"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43fcee184de68e344a888bc4f2b9d6b2f2f527cae8cedbb4d62a4df727d1ceae"
dependencies = [
"bitflags",
"derive_more",
"log",
"multiboot2-common",
"ptr_meta",
"uefi-raw",
]
[[package]]
name = "multiboot2-common"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbabf8d9980d55576ba487924fa0b9a467fc0012b996b93d2319904f168ed8ab"
dependencies = [
"derive_more",
"ptr_meta",
]
[[package]]
name = "pc-keyboard"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0ca629cbb3f0d5b699c338f0129ff78c9bfd7ea8b1258ad529bff490dc8ed5a"
[[package]]
name = "pic8259"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62d9a86c292b165f757e47e7fd66855def189b2564609bc4203727b27c33db22"
dependencies = [
"x86_64",
]
[[package]]
name = "proc-macro2"
version = "1.0.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
dependencies = [
"unicode-ident",
]
[[package]]
name = "ptr_meta"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcada80daa06c42ed5f48c9a043865edea5dc44cbf9ac009fda3b89526e28607"
dependencies = [
"ptr_meta_derive",
]
[[package]]
name = "ptr_meta_derive"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bca9224df2e20e7c5548aeb5f110a0f3b77ef05f8585139b7148b59056168ed2"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rlibc"
version = "1.0.0"
@ -50,6 +154,9 @@ name = "rustboot"
version = "0.1.0"
dependencies = [
"lazy_static",
"multiboot2",
"pc-keyboard",
"pic8259",
"rlibc",
"spin 0.10.0",
"volatile 0.3.0",
@ -83,6 +190,57 @@ dependencies = [
"lock_api",
]
[[package]]
name = "syn"
version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "uefi-raw"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b463030b802e1265a3800fab24df95d3229c202c2e408832a206f05b4d1496ca"
dependencies = [
"bitflags",
"ptr_meta",
"uguid",
]
[[package]]
name = "uguid"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c8352f8c05e47892e7eaf13b34abd76a7f4aeaf817b716e88789381927f199c"
[[package]]
name = "unicode-ident"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
[[package]]
name = "unicode-xid"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
[[package]]
name = "volatile"
version = "0.3.0"

View file

@ -16,17 +16,14 @@ test-timeout = 30 # in seconds
crate-type = ["staticlib"] # library that contains all dependencies
[dependencies]
multiboot2 = "0.23"
pc-keyboard = "0.8"
pic8259 = "0.11"
rlibc = "1.0"
spin = "0.10"
volatile = "0.3" # newest functional version
x86_64 = "0.15"
volatile = "0.3" # 0.3 is newest functional version
x86_64 = "0.15" # 0.14 is newest functional version
[dependencies.lazy_static]
version = "1.5"
features = ["spin_no_std"]
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"

Binary file not shown.

6
flake.lock generated
View file

@ -2,11 +2,11 @@
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1746576598,
"narHash": "sha256-FshoQvr6Aor5SnORVvh/ZdJ1Sa2U4ZrIMwKBX5k2wu0=",
"lastModified": 1747060738,
"narHash": "sha256-ByfPRQuqj+nhtVV0koinEpmJw0KLzNbgcgi9EF+NVow=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b3582c75c7f21ce0b429898980eddbbf05c68e55",
"rev": "eaeed9530c76ce5f1d2d8232e08bec5e26f18ec1",
"type": "github"
},
"original": {

View file

@ -1,5 +1,7 @@
all: setup asm rust link image clean
mkrun: all run
setup:
mkdir temp

View file

@ -7,6 +7,14 @@ SECTIONS {
}
.text :
{
*(.text)
*(.text .text.*)
}
.rodata :
{
*(.rodata .rodata.*)
}
.data.rel.ro :
{
*(.data.rel.ro.local*) *(.data.rel.ro .data.rel.ro.*)
}
}

56
src/' Normal file
View file

@ -0,0 +1,56 @@
#![no_std]
#![feature(abi_x86_interrupt)]
extern crate alloc;
extern crate multiboot2;
extern crate rlibc;
mod allocator;
mod gdt;
mod interrupt;
mod vga_buffer;
use core::panic::PanicInfo;
use multiboot2::{BootInformation, BootInformationHeader};
#[unsafe(no_mangle)]
pub extern "C" fn rust_main(multiboot_information_address: usize) {
println!("Hello World!");
// println!(
// "This program booted itself from assembly. This println function manipulates individual bytes in a vga buffer. My power is beyond your understanding\n0\n1\n2\n3\n4\n5\n6\n7\n8\n9"
// );
let boot_info = unsafe {
BootInformation::load(multiboot_information_address as *const BootInformationHeader)
.unwrap()
};
let memory_map_tag = boot_info.memory_map_tag().expect("Memory map tag required");
init();
println!("Got past");
halt()
}
pub fn init() {
allocator::init_heap
println!("got to gdt::init()");
gdt::init();
println!("got to interrupt::init_idt();");
interrupt::init_idt();
println!("got to PICS.lock()");
unsafe { interrupt::PICS.lock().initialize() };
println!("got to enable inst");
x86_64::instructions::interrupts::enable();
}
#[panic_handler]
pub fn panic(info: &PanicInfo) -> ! {
println!("Panic happened: {}", info);
halt()
}
pub fn halt() -> ! {
println!("we've halted");
loop {
x86_64::instructions::hlt();
}
}

View file

@ -0,0 +1,114 @@
use super::{Locked, align_up};
use alloc::alloc::{GlobalAlloc, Layout};
use core::{mem, ptr};
pub struct LinkedListAllocator {
head: ListNode,
}
impl LinkedListAllocator {
pub const fn new() -> Self {
Self {
head: ListNode::new(0),
}
}
pub unsafe fn init(&mut self, heap_start: usize, heap_size: usize) {
unsafe { self.add_free_region(heap_start, heap_size) };
}
unsafe fn add_free_region(&mut self, addr: usize, size: usize) {
assert_eq!(align_up(addr, mem::align_of::<ListNode>()), addr);
assert!(size >= mem::size_of::<ListNode>());
let mut node = ListNode::new(size);
node.next = self.head.next.take();
let node_ptr = addr as *mut ListNode;
unsafe {
node_ptr.write(node);
self.head.next = Some(&mut *node_ptr)
}
}
fn alloc_from_region(region: &ListNode, size: usize, align: usize) -> Result<usize, ()> {
let alloc_start = align_up(region.start_addr(), align);
let alloc_end = alloc_start.checked_add(size).ok_or(())?;
if alloc_end > region.end_addr() {
return Err(());
}
let excess_size = region.end_addr() - alloc_end;
if excess_size > 0 && excess_size < mem::size_of::<ListNode>() {
return Err(());
}
Ok(alloc_start)
}
fn find_region(&mut self, size: usize, align: usize) -> Option<(&'static mut ListNode, usize)> {
let mut current = &mut self.head;
while let Some(ref mut region) = current.next {
if let Ok(alloc_start) = Self::alloc_from_region(&region, size, align) {
let next = region.next.take();
let ret = Some((current.next.take().unwrap(), alloc_start));
current.next = next;
return ret;
} else {
current = current.next.as_mut().unwrap();
}
}
None
}
fn size_align(layout: Layout) -> (usize, usize) {
let layout = layout
.align_to(mem::align_of::<ListNode>())
.expect("adjusting alignment failed")
.pad_to_align();
let size = layout.size().max(mem::align_of::<ListNode>());
(size, layout.align())
}
}
unsafe impl GlobalAlloc for Locked<LinkedListAllocator> {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let (size, align) = LinkedListAllocator::size_align(layout);
let mut allocator = self.lock();
if let Some((region, alloc_start)) = allocator.find_region(size, align) {
let alloc_end = alloc_start.checked_add(size).expect("overflow");
let excess_size = region.end_addr() - alloc_end;
if excess_size > 0 {
unsafe {
allocator.add_free_region(alloc_end, excess_size);
}
}
alloc_start as *mut u8
} else {
ptr::null_mut()
}
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
let (size, _) = LinkedListAllocator::size_align(layout);
unsafe { self.lock().add_free_region(ptr as usize, size) }
}
}
struct ListNode {
size: usize,
next: Option<&'static mut ListNode>,
}
impl ListNode {
const fn new(size: usize) -> Self {
ListNode { size, next: None }
}
fn start_addr(&self) -> usize {
self as *const Self as usize
}
fn end_addr(&self) -> usize {
self.start_addr() + self.size
}
}

62
src/allocator/mod.rs Normal file
View file

@ -0,0 +1,62 @@
use crate::memory::area_frame_allocator;
use linked_list::LinkedListAllocator;
use x86_64::VirtAddr;
use x86_64::structures::paging::mapper::MapToError;
use x86_64::structures::paging::{FrameAllocator, Mapper, Page, PageTableFlags, Size4KiB};
pub mod linked_list;
pub const HEAP_START: usize = 0x_4444_4444_0000;
pub const HEAP_SIZE: usize = 100 * 1024; // 100KiB
#[global_allocator]
static ALLOCATOR: Locked<LinkedListAllocator> = Locked::new(LinkedListAllocator::new());
pub struct Locked<A> {
inner: spin::Mutex<A>,
}
impl<A> Locked<A> {
pub const fn new(inner: A) -> Self {
Locked {
inner: spin::Mutex::new(inner),
}
}
pub fn lock(&self) -> spin::MutexGuard<A> {
self.inner.lock()
}
}
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 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)
};
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, HEAP_SIZE);
}
Ok(())
}
fn align_up(addr: usize, align: usize) -> usize {
let remainder = addr % align;
if remainder == 0 {
addr
} else {
addr - remainder + align
}
}

52
src/gdt/mod.rs Normal file
View file

@ -0,0 +1,52 @@
use lazy_static::lazy_static;
use x86_64::VirtAddr;
use x86_64::structures::gdt::{Descriptor, GlobalDescriptorTable, SegmentSelector};
use x86_64::structures::tss::TaskStateSegment;
// selector returned by GDT
// code_selector: where CS register goes in case of DF
// tss_selector: where TSS starts in case of DF
struct Selectors {
code_selector: SegmentSelector,
tss_selector: SegmentSelector,
}
// location of double fault emergency stac
pub const DOUBLE_FAULT_1ST_INDEX: u16 = 0;
pub fn init() {
use x86_64::instructions::segmentation::{CS, Segment};
use x86_64::instructions::tables::load_tss;
GDT.0.load();
unsafe {
CS::set_reg(GDT.1.code_selector);
load_tss(GDT.1.tss_selector);
}
}
lazy_static! {
static ref GDT: (GlobalDescriptorTable, Selectors) = {
let mut gdt = GlobalDescriptorTable::new();
let code_selector = gdt.append(Descriptor::kernel_code_segment());
let tss_selector = gdt.append(Descriptor::tss_segment(&TSS));
(
gdt,
Selectors {
code_selector,
tss_selector,
},
)
};
static ref TSS: TaskStateSegment = {
let mut tss = TaskStateSegment::new();
tss.interrupt_stack_table[DOUBLE_FAULT_1ST_INDEX as usize] = {
const STACK_SIZE: usize = 4096 * 5;
static mut STACK: [u8; STACK_SIZE] = [0; STACK_SIZE]; // TODO make real stack
let stack_start = VirtAddr::from_ptr(&raw const STACK);
stack_start + STACK_SIZE as u64 // end of stack
};
tss
};
}

110
src/interrupt/mod.rs Normal file
View file

@ -0,0 +1,110 @@
use crate::{print, println};
use lazy_static::lazy_static;
use pic8259::ChainedPics;
use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame, PageFaultErrorCode};
pub fn init_idt() {
IDT.load();
}
pub const PIC_1_OFFSET: u8 = 32;
pub const PIC_2_OFFSET: u8 = PIC_1_OFFSET + 8;
pub static PICS: spin::Mutex<ChainedPics> =
spin::Mutex::new(unsafe { ChainedPics::new(PIC_1_OFFSET, PIC_2_OFFSET) });
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
pub enum InterruptIndex {
Timer = PIC_1_OFFSET,
Keyboard,
}
impl InterruptIndex {
fn as_u8(self) -> u8 {
self as u8
}
fn as_usize(self) -> usize {
usize::from(self.as_u8())
}
}
lazy_static! {
static ref IDT: InterruptDescriptorTable = {
let mut idt = InterruptDescriptorTable::new();
idt.breakpoint.set_handler_fn(breakpoint_handler);
unsafe {
idt.double_fault
.set_handler_fn(double_fault_handler)
.set_stack_index(crate::gdt::DOUBLE_FAULT_1ST_INDEX);
}
idt[InterruptIndex::Timer.as_u8()].set_handler_fn(timer_interrupt_handler);
idt[InterruptIndex::Keyboard.as_u8()].set_handler_fn(keyboard_interrupt_handler);
idt.page_fault.set_handler_fn(page_fault_handler);
idt
};
}
extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) {
println!("EXCEPTION: BREAKPOINT\n{:#?}", stack_frame);
}
extern "x86-interrupt" fn double_fault_handler(
stack_frame: InterruptStackFrame,
_error_code: u64,
) -> ! {
panic!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame);
}
extern "x86-interrupt" fn keyboard_interrupt_handler(_keyboard_stack_frame: InterruptStackFrame) {
use pc_keyboard::{DecodedKey, HandleControl, Keyboard, ScancodeSet1, layouts};
use spin::Mutex;
use x86_64::instructions::port::Port;
lazy_static! {
static ref KEYBOARD: Mutex<Keyboard<layouts::Us104Key, ScancodeSet1>> =
Mutex::new(Keyboard::new(
ScancodeSet1::new(),
layouts::Us104Key,
HandleControl::Ignore
));
}
let mut keyboard = KEYBOARD.lock();
let mut port = Port::new(0x60);
let scancode: u8 = unsafe { port.read() };
if let Ok(Some(key_event)) = keyboard.add_byte(scancode) {
if let Some(key) = keyboard.process_keyevent(key_event) {
match key {
DecodedKey::Unicode(character) => print!("{}", character),
DecodedKey::RawKey(key) => print!("{:?}", key),
}
}
}
unsafe {
PICS.lock()
.notify_end_of_interrupt(InterruptIndex::Keyboard.as_u8());
}
}
extern "x86-interrupt" fn page_fault_handler(
stack_frame: InterruptStackFrame,
error_code: PageFaultErrorCode,
) {
use x86_64::registers::control::Cr2;
println!("EXCEPTION: PAGE FAULT");
println!("Accessed Address: {:?}", Cr2::read());
println!("Error Code: {:?}?", error_code);
println!("{:#?}", stack_frame);
crate::halt();
}
extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: InterruptStackFrame) {
print!(".");
unsafe {
PICS.lock()
.notify_end_of_interrupt(InterruptIndex::Timer.as_u8());
}
}

View file

@ -1,26 +1,93 @@
#![no_std]
#![feature(abi_x86_interrupt)]
extern crate alloc;
extern crate multiboot2;
extern crate rlibc;
mod allocator;
mod gdt;
mod interrupt;
mod memory;
mod vga_buffer;
use core::panic::PanicInfo;
pub fn halt() -> ! {
println!("we've halted");
loop {
x86_64::instructions::hlt();
}
}
use multiboot2::{BootInformation, BootInformationHeader};
#[unsafe(no_mangle)]
pub extern "C" fn rust_main(_multiboot_information_address: usize) {
pub extern "C" fn rust_main(multiboot_information_address: usize) {
println!("Hello World!");
// get multiboot info
let boot_info = unsafe {
BootInformation::load(multiboot_information_address as *const BootInformationHeader)
.unwrap()
};
let memory_map_tag = boot_info.memory_map_tag().expect("Memory map tag required");
println!("memory areas:");
for area in memory_map_tag.memory_areas() {
println!(
" start: 0x{:x}, length: 0x{:x}",
area.start_address(),
area.size()
);
}
let elf_sections_tag = boot_info
.elf_sections_tag()
.expect("Elf sections tag required");
println!("kernel sections:");
for section in elf_sections_tag.sections() {
println!(
" addr: 0x{:x}, size: 0x{:x}, flags: 0x{:x}",
section.start_address(),
section.size(),
section.flags()
);
}
let kernel_start = elf_sections_tag
.sections()
.map(|s| s.start_address())
.min()
.unwrap();
let kernel_end = elf_sections_tag
.sections()
.map(|s| s.end_address())
.max()
.unwrap();
let multiboot_start = multiboot_information_address;
let multiboot_end = multiboot_start + boot_info.total_size() as usize;
println!(
"kernel_start: 0x{:x} kernel_end: 0x{:x} kernel_size: {}B\nmultiboot_start: 0x{:x} multiboot_end: 0x{:x} multiboot_size: {}B",
kernel_start,
kernel_end,
kernel_end - kernel_start,
multiboot_start,
multiboot_end,
multiboot_end - multiboot_start
);
//init();
halt()
}
pub fn init() {
gdt::init();
interrupt::init_idt();
unsafe { interrupt::PICS.lock().initialize() };
x86_64::instructions::interrupts::enable();
}
#[panic_handler]
pub fn panic(info: &PanicInfo) -> ! {
println!("Panic happened: {}", info);
halt()
}
pub fn halt() -> ! {
println!("we've halted");
loop {
x86_64::instructions::hlt();
}
}

View file

@ -0,0 +1,95 @@
use core::alloc::{GlobalAlloc, Layout};
use core::{mem, ptr};
use multiboot2::{BootInformation, BootInformationHeader};
use super::{Frame, PAGE_SIZE};
use crate::allocator::{HEAP_SIZE, HEAP_START, Locked};
pub struct AreaFrameAllocator {
next_free_frame: Frame,
kernel_start: Frame,
kernel_end: Frame,
multiboot_start: Frame,
multiboot_end: Frame,
}
impl AreaFrameAllocator {
pub const fn new() -> Self {
Self {
next_free_frame: Frame::new(),
kernel_start: Frame::new(),
kernel_end: Frame::new(),
multiboot_start: Frame::new(),
multiboot_end: Frame::new(),
}
}
pub unsafe fn init(&mut self, multiboot_information_address: usize) -> Self {
let boot_info = unsafe {
BootInformation::load(multiboot_information_address as *const BootInformationHeader)
.unwrap()
};
//let memory_map_tag = boot_info.memory_map_tag().expect("Memory map tag required");
let elf_sections_tag = boot_info
.elf_sections_tag()
.expect("Elf sections tag required");
let kernel_start = elf_sections_tag
.sections()
.map(|s| s.start_address())
.min()
.unwrap();
let kernel_end = elf_sections_tag
.sections()
.map(|s| s.end_address())
.max()
.unwrap();
let multiboot_start = multiboot_information_address;
let multiboot_end = multiboot_start + boot_info.total_size();
AreaFrameAllocator {
next_free_frame: Frame { number: 0 },
kernel_start: Frame {
number: kernel_start as usize,
},
kernel_end: Frame {
number: kernel_end as usize,
},
multiboot_start: Frame {
number: multiboot_start,
},
multiboot_end: Frame {
number: multiboot_end,
},
}
}
fn find_frame(&mut self, size: usize, align: usize) -> Option<(Frame, usize)> {
let next_addr = self.next_free_frame.number * PAGE_SIZE + HEAP_START;
if &next_addr + core::mem::align_of::<Frame>() <= PAGE_SIZE + HEAP_START {
Some((Frame::containing_address(next_addr), next_addr))
} else {
None
}
}
fn size_align(layout: Layout) -> (usize, usize) {
let layout = layout
.align_to(mem::align_of::<Frame>())
.expect("adjusting alignment failed")
.pad_to_align();
let size = layout.size().max(mem::align_of::<Frame>());
(size, layout.align())
}
}
unsafe impl GlobalAlloc for Locked<AreaFrameAllocator> {
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
let (size, align) = AreaFrameAllocator::size_align(layout);
let mut allocator = self.lock();
match allocator.find_frame(size, align) {
Some((_, addr)) => addr as *mut u8,
None => ptr::null_mut(),
}
}
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {}
}

19
src/memory/mod.rs Normal file
View file

@ -0,0 +1,19 @@
pub mod area_frame_allocator;
pub const PAGE_SIZE: usize = 4096;
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Frame {
number: usize,
}
impl Frame {
pub const fn new() -> Self {
Self { number: 0 }
}
fn containing_address(address: usize) -> Frame {
Frame {
number: address / PAGE_SIZE,
}
}
}