feat(heap): refacto memory init and add heap simple allocation
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
Signed-off-by: Julien CLEMENT <julien.clement@epita.fr>
This commit is contained in:
parent
2433d99bc7
commit
37432ef902
@ -3,4 +3,4 @@ target = "x86_64-julios.json"
|
|||||||
|
|
||||||
[unstable]
|
[unstable]
|
||||||
build-std-features = ["compiler-builtins-mem"]
|
build-std-features = ["compiler-builtins-mem"]
|
||||||
build-std = ["core", "compiler_builtins"]
|
build-std = ["core", "compiler_builtins", "alloc"]
|
||||||
|
34
Cargo.lock
generated
34
Cargo.lock
generated
@ -25,6 +25,7 @@ name = "julios"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
|
"linked_list_allocator",
|
||||||
"multiboot2",
|
"multiboot2",
|
||||||
"pc-keyboard",
|
"pc-keyboard",
|
||||||
"pic8259",
|
"pic8259",
|
||||||
@ -42,6 +43,24 @@ dependencies = [
|
|||||||
"spin",
|
"spin",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linked_list_allocator"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "549ce1740e46b291953c4340adcd74c59bcf4308f4cac050fd33ba91b7168f4a"
|
||||||
|
dependencies = [
|
||||||
|
"spinning_top",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lock_api"
|
||||||
|
version = "0.4.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
|
||||||
|
dependencies = [
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "multiboot2"
|
name = "multiboot2"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -66,12 +85,27 @@ dependencies = [
|
|||||||
"x86_64",
|
"x86_64",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
version = "0.5.2"
|
version = "0.5.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spinning_top"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75adad84ee84b521fb2cca2d4fd0f1dab1d8d026bda3c5bea4ca63b5f9f9293c"
|
||||||
|
dependencies = [
|
||||||
|
"lock_api",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "volatile"
|
name = "volatile"
|
||||||
version = "0.2.7"
|
version = "0.2.7"
|
||||||
|
@ -15,6 +15,7 @@ x86_64 = "0.14.2"
|
|||||||
pic8259 = "0.10.1"
|
pic8259 = "0.10.1"
|
||||||
pc-keyboard = "0.5.0"
|
pc-keyboard = "0.5.0"
|
||||||
multiboot2 = "0.1.0"
|
multiboot2 = "0.1.0"
|
||||||
|
linked_list_allocator = "0.9.0"
|
||||||
|
|
||||||
[dependencies.lazy_static]
|
[dependencies.lazy_static]
|
||||||
version = "1.0"
|
version = "1.0"
|
||||||
|
65
src/lib.rs
65
src/lib.rs
@ -1,6 +1,7 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![feature(abi_x86_interrupt)]
|
#![feature(abi_x86_interrupt)]
|
||||||
|
#![feature(alloc_error_handler)]
|
||||||
|
|
||||||
mod gdt;
|
mod gdt;
|
||||||
mod interrupts;
|
mod interrupts;
|
||||||
@ -8,13 +9,19 @@ mod memory;
|
|||||||
mod serial;
|
mod serial;
|
||||||
mod vga;
|
mod vga;
|
||||||
|
|
||||||
|
//#[macro_use]
|
||||||
|
extern crate alloc;
|
||||||
extern crate multiboot2;
|
extern crate multiboot2;
|
||||||
|
|
||||||
use core::panic::PanicInfo;
|
use core::panic::PanicInfo;
|
||||||
use memory::paging::{FrameAllocator, Size4KiB};
|
|
||||||
use multiboot2::BootInformation;
|
use multiboot2::BootInformation;
|
||||||
use vga::{Color, ColorCode};
|
use vga::{Color, ColorCode};
|
||||||
|
|
||||||
|
#[alloc_error_handler]
|
||||||
|
fn alloc_error_handler(layout: alloc::alloc::Layout) -> ! {
|
||||||
|
panic!("Allocation error: {:?}", layout)
|
||||||
|
}
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic_handler(info: &PanicInfo) -> ! {
|
fn panic_handler(info: &PanicInfo) -> ! {
|
||||||
vga::change_color(ColorCode::new(Color::LightRed, Color::Black));
|
vga::change_color(ColorCode::new(Color::LightRed, Color::Black));
|
||||||
@ -28,68 +35,26 @@ pub fn hlt_loop() -> ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init<A>(frame_allocator: &mut A, boot_info: &BootInformation)
|
pub fn init(boot_info: &BootInformation)
|
||||||
where
|
|
||||||
A: FrameAllocator<Size4KiB>,
|
|
||||||
{
|
{
|
||||||
vga::change_color(ColorCode::new(Color::LightCyan, Color::Black));
|
vga::change_color(ColorCode::new(Color::LightCyan, Color::Black));
|
||||||
println!("Starting init");
|
println!("Starting init");
|
||||||
enable_nxe_bit();
|
memory::init(boot_info);
|
||||||
enable_write_protect_bit();
|
|
||||||
memory::kernel_remap(frame_allocator, boot_info);
|
|
||||||
gdt::init_gdt();
|
gdt::init_gdt();
|
||||||
interrupts::init_idt();
|
interrupts::init_idt();
|
||||||
vga::change_color(ColorCode::new(Color::LightGreen, Color::Black));
|
vga::change_color(ColorCode::new(Color::LightGreen, Color::Black));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn enable_nxe_bit() {
|
|
||||||
println!("Enabling nxe bit");
|
|
||||||
use x86_64::registers::control::{Efer, EferFlags};
|
|
||||||
unsafe { Efer::update(|efer| *efer |= EferFlags::NO_EXECUTE_ENABLE) }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn enable_write_protect_bit() {
|
|
||||||
println!("Enabling write protection bit");
|
|
||||||
use x86_64::registers::control::{Cr0, Cr0Flags};
|
|
||||||
|
|
||||||
unsafe { Cr0::write(Cr0::read() | Cr0Flags::WRITE_PROTECT) };
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_frame_allocator(multiboot_info_addr: usize) -> memory::AreaFrameAllocator {
|
|
||||||
let boot_info = unsafe { multiboot2::load(multiboot_info_addr) };
|
|
||||||
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: u64 = elf_sections_tag.sections().map(|s| s.addr).min().unwrap();
|
|
||||||
let kernel_end: u64 = elf_sections_tag
|
|
||||||
.sections()
|
|
||||||
.map(|s| s.addr + s.size)
|
|
||||||
.max()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let multiboot_start: u64 = multiboot_info_addr as u64;
|
|
||||||
let multiboot_end: u64 = multiboot_start + (boot_info.total_size as u64);
|
|
||||||
|
|
||||||
memory::AreaFrameAllocator::new(
|
|
||||||
kernel_start,
|
|
||||||
kernel_end,
|
|
||||||
multiboot_start,
|
|
||||||
multiboot_end,
|
|
||||||
memory_map_tag.memory_areas(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub extern "C" fn julios_main(multiboot_info_addr: usize) -> ! {
|
pub extern "C" fn julios_main(multiboot_info_addr: usize) -> ! {
|
||||||
let boot_info = unsafe { multiboot2::load(multiboot_info_addr) };
|
let boot_info = unsafe { multiboot2::load(multiboot_info_addr) };
|
||||||
|
|
||||||
let mut frame_allocator = get_frame_allocator(multiboot_info_addr);
|
init(&boot_info);
|
||||||
|
|
||||||
init(&mut frame_allocator, &boot_info);
|
|
||||||
println!("***JuliOS V0.1.0***");
|
println!("***JuliOS V0.1.0***");
|
||||||
serial_println!("Hello serial");
|
serial_println!("Hello serial");
|
||||||
|
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
let x = Box::new(41);
|
||||||
|
|
||||||
panic!("Kernel end of flow");
|
panic!("Kernel end of flow");
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ ENTRY(_start)
|
|||||||
SECTIONS {
|
SECTIONS {
|
||||||
. = 1M;
|
. = 1M;
|
||||||
|
|
||||||
|
. = ALIGN(4K);
|
||||||
.rodata :
|
.rodata :
|
||||||
{
|
{
|
||||||
/* ensure that the multiboot header is at the beginning */
|
/* ensure that the multiboot header is at the beginning */
|
||||||
@ -10,6 +11,12 @@ SECTIONS {
|
|||||||
. = ALIGN(4K);
|
. = ALIGN(4K);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
. = ALIGN(4K);
|
||||||
|
.eh_frame :
|
||||||
|
{
|
||||||
|
*(.eh_frame .eh_frame.*)
|
||||||
|
. = ALIGN(4K);
|
||||||
|
}
|
||||||
. = ALIGN(4K);
|
. = ALIGN(4K);
|
||||||
.text :
|
.text :
|
||||||
{
|
{
|
||||||
|
8
src/memory/heap_alloc/mod.rs
Normal file
8
src/memory/heap_alloc/mod.rs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
use super::PAGE_SIZE;
|
||||||
|
use linked_list_allocator::LockedHeap;
|
||||||
|
|
||||||
|
pub const HEAP_START: u64 = 0x4444_4444_0000;
|
||||||
|
pub const HEAP_SIZE: u64 = PAGE_SIZE as u64 * 25;
|
||||||
|
|
||||||
|
#[global_allocator]
|
||||||
|
pub static ALLOCATOR: LockedHeap = LockedHeap::empty();
|
@ -1,7 +1,92 @@
|
|||||||
pub use self::frame_allocator::AreaFrameAllocator;
|
pub use self::frame_allocator::AreaFrameAllocator;
|
||||||
pub use paging::kernel_remap;
|
pub use paging::kernel_remap;
|
||||||
|
use crate::println;
|
||||||
|
use multiboot2::BootInformation;
|
||||||
|
use paging::{Size4KiB, RecursivePageTable, FrameAllocator, Page, Flags, Mapper};
|
||||||
|
use heap_alloc::{HEAP_START, HEAP_SIZE, ALLOCATOR};
|
||||||
|
use x86_64::VirtAddr;
|
||||||
|
use x86_64::structures::paging::{mapper::MapToError, page::PageRangeInclusive};
|
||||||
|
|
||||||
pub mod frame_allocator;
|
pub mod frame_allocator;
|
||||||
pub mod paging;
|
pub mod paging;
|
||||||
|
pub mod heap_alloc;
|
||||||
|
|
||||||
pub const PAGE_SIZE: usize = 4096;
|
pub const PAGE_SIZE: usize = 4096;
|
||||||
|
|
||||||
|
pub fn init(boot_info: &BootInformation) {
|
||||||
|
enable_nxe_bit();
|
||||||
|
enable_write_protect_bit();
|
||||||
|
let mut frame_allocator = get_frame_allocator(boot_info.start_address());
|
||||||
|
let mut active_table = kernel_remap(&mut frame_allocator, boot_info);
|
||||||
|
init_heap(&mut active_table, &mut frame_allocator)
|
||||||
|
.expect("Heap initialization failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_heap<A>(active_table: &mut RecursivePageTable, frame_allocator: &mut A)
|
||||||
|
-> Result<(), MapToError<Size4KiB>>
|
||||||
|
where A: FrameAllocator<Size4KiB>
|
||||||
|
{
|
||||||
|
let page_range: PageRangeInclusive<Size4KiB> = {
|
||||||
|
let heap_start = VirtAddr::new(HEAP_START);
|
||||||
|
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 = Flags::PRESENT | Flags::WRITABLE;
|
||||||
|
unsafe {
|
||||||
|
active_table.map_to(page, frame, flags, frame_allocator)?.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
ALLOCATOR.lock().init(HEAP_START as usize, HEAP_SIZE as usize);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_frame_allocator(multiboot_info_addr: usize) -> AreaFrameAllocator {
|
||||||
|
let boot_info = unsafe { multiboot2::load(multiboot_info_addr) };
|
||||||
|
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: u64 = elf_sections_tag.sections().map(|s| s.addr).min().unwrap();
|
||||||
|
let kernel_end: u64 = elf_sections_tag
|
||||||
|
.sections()
|
||||||
|
.map(|s| s.addr + s.size)
|
||||||
|
.max()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let multiboot_start: u64 = multiboot_info_addr as u64;
|
||||||
|
let multiboot_end: u64 = multiboot_start + (boot_info.total_size as u64);
|
||||||
|
|
||||||
|
AreaFrameAllocator::new(
|
||||||
|
kernel_start,
|
||||||
|
kernel_end,
|
||||||
|
multiboot_start,
|
||||||
|
multiboot_end,
|
||||||
|
memory_map_tag.memory_areas(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enable_nxe_bit() {
|
||||||
|
println!("Enabling nxe bit");
|
||||||
|
use x86_64::registers::control::{Efer, EferFlags};
|
||||||
|
unsafe { Efer::update(|efer| *efer |= EferFlags::NO_EXECUTE_ENABLE) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enable_write_protect_bit() {
|
||||||
|
println!("Enabling write protection bit");
|
||||||
|
use x86_64::registers::control::{Cr0, Cr0Flags};
|
||||||
|
|
||||||
|
unsafe { Cr0::write(Cr0::read() | Cr0Flags::WRITE_PROTECT) };
|
||||||
|
}
|
||||||
|
@ -13,6 +13,7 @@ mod temporary_page;
|
|||||||
|
|
||||||
pub const P4: *mut PageTable = 0o177777_777_777_777_777_0000 as *mut _;
|
pub const P4: *mut PageTable = 0o177777_777_777_777_777_0000 as *mut _;
|
||||||
|
|
||||||
|
|
||||||
fn get_flags_from_elf_section(section: &ElfSection) -> Flags {
|
fn get_flags_from_elf_section(section: &ElfSection) -> Flags {
|
||||||
use multiboot2::{ELF_SECTION_ALLOCATED, ELF_SECTION_EXECUTABLE, ELF_SECTION_WRITABLE};
|
use multiboot2::{ELF_SECTION_ALLOCATED, ELF_SECTION_EXECUTABLE, ELF_SECTION_WRITABLE};
|
||||||
|
|
||||||
@ -31,17 +32,16 @@ fn get_flags_from_elf_section(section: &ElfSection) -> Flags {
|
|||||||
flags
|
flags
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kernel_remap<A>(allocator: &mut A, boot_info: &BootInformation)
|
pub fn kernel_remap<'a, A>(allocator: &mut A, boot_info: & BootInformation) -> RecursivePageTable<'a>
|
||||||
where
|
where A: FrameAllocator<Size4KiB>,
|
||||||
A: FrameAllocator<Size4KiB>,
|
|
||||||
{
|
{
|
||||||
println!("Remapping kernel");
|
println!("Remapping kernel");
|
||||||
let mut temporary_page = TemporaryPage::new(
|
let mut temporary_page = TemporaryPage::new(
|
||||||
Page::containing_address(VirtAddr::new(0xcafebabe)),
|
Page::containing_address(VirtAddr::new(0xcafebabe)),
|
||||||
allocator,
|
allocator,
|
||||||
);
|
);
|
||||||
let mut active_table = get_active_page_table();
|
let mut active_table: RecursivePageTable = get_active_page_table();
|
||||||
let mut new_table = {
|
let mut new_table: InactivePageTable = {
|
||||||
let frame = allocator.allocate_frame().expect("No more frames");
|
let frame = allocator.allocate_frame().expect("No more frames");
|
||||||
InactivePageTable::new(frame, &mut active_table, &mut temporary_page)
|
InactivePageTable::new(frame, &mut active_table, &mut temporary_page)
|
||||||
};
|
};
|
||||||
@ -109,6 +109,7 @@ where
|
|||||||
));
|
));
|
||||||
active_table.unmap(old_p4_page).expect("Failed to unmap old P4").1.flush();
|
active_table.unmap(old_p4_page).expect("Failed to unmap old P4").1.flush();
|
||||||
println!("Stack guard page at {:#x}", old_p4_page.start_address());
|
println!("Stack guard page at {:#x}", old_p4_page.start_address());
|
||||||
|
active_table
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InactivePageTable {
|
struct InactivePageTable {
|
||||||
|
Loading…
Reference in New Issue
Block a user