Add kernel heap
This commit is contained in:
parent
646a4ea2b7
commit
98aaab64d7
10 changed files with 89 additions and 49 deletions
23
kernel/Cargo.lock
generated
23
kernel/Cargo.lock
generated
|
@ -2,12 +2,6 @@
|
|||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "alloc-traits"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b2d54853319fd101b8dd81de382bcbf3e03410a64d8928bbee85a3e7dcde483"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.3.0"
|
||||
|
@ -44,9 +38,9 @@ version = "0.0.1"
|
|||
dependencies = [
|
||||
"bitvec",
|
||||
"kernel-common",
|
||||
"linked_list_allocator",
|
||||
"log",
|
||||
"spin",
|
||||
"static-alloc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -57,6 +51,15 @@ dependencies = [
|
|||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linked_list_allocator"
|
||||
version = "0.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9afa463f5405ee81cdb9cc2baf37e08ec7e4c8209442b5d72c04cfb2cd6e6286"
|
||||
dependencies = [
|
||||
"spinning_top",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.12"
|
||||
|
@ -95,12 +98,12 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "static-alloc"
|
||||
name = "spinning_top"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b2975e035ce16539eecee08d7c6e5626ca26f299c6e90af343b302c6dd2e61e"
|
||||
checksum = "5b9eb1a2f4c41445a3a0ff9abc5221c5fcd28e1f13cd7c0397706f9ac938ddb0"
|
||||
dependencies = [
|
||||
"alloc-traits",
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -6,6 +6,6 @@ edition = "2021"
|
|||
[dependencies]
|
||||
bitvec = {version = "1.0.1", default-features = false, features = ["alloc", "atomic"]}
|
||||
kernel-common = {path = "../lib/kernel-common"}
|
||||
linked_list_allocator = "0.10.5"
|
||||
log = "0.4.22"
|
||||
spin = "0.9.8"
|
||||
static-alloc = "0.2.5"
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
use core::panic;
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use bitvec::{bitvec, order::Lsb0};
|
||||
use bitvec::{bitvec, order::Lsb0, vec::BitVec};
|
||||
use kernel_common::{
|
||||
loader_struct::LoaderStruct,
|
||||
paging::{load_cr3, PageEntry, PageTable, KERNEL_VIRT_START},
|
||||
paging::{load_cr3, PageEntry, PageTable, KERNEL_HEAP_INITIAL_SIZE, KERNEL_HEAP_START, KERNEL_VIRT_START},
|
||||
};
|
||||
use log::info;
|
||||
use spin::{Mutex, Once};
|
||||
|
@ -18,9 +20,19 @@ extern "C" {
|
|||
static _bss_end: u8;
|
||||
}
|
||||
|
||||
static KERNEL_PHYS_START: Once<u64> = Once::new();
|
||||
static HEAP_PHYS_START: Once<u64> = Once::new();
|
||||
static CURRENT_PML4: Mutex<Option<&mut PageTable>> = Mutex::new(None);
|
||||
static PHYSICAL_FRAMES: Mutex<Option<BitVec<u64>>> = Mutex::new(None);
|
||||
|
||||
fn _get_free_frame() -> u64 {
|
||||
let frames_vec = PHYSICAL_FRAMES.lock();
|
||||
for i in 0..frames_vec.as_ref().unwrap().len() {
|
||||
if !frames_vec.as_ref().unwrap()[i] {
|
||||
return i as u64;
|
||||
}
|
||||
}
|
||||
panic!("No free memory left");
|
||||
}
|
||||
fn get_table_entry(table: &mut PageTable, i: usize) -> &mut PageTable {
|
||||
if table.entries_virt[i].is_none() {
|
||||
const NONE: Option<Box<PageTable>> = None;
|
||||
|
@ -60,7 +72,7 @@ fn get_page(pml4: &mut PageTable, virt: u64) -> Option<&mut PageEntry> {
|
|||
fn virt_to_phys(virt: u64) -> u64 {
|
||||
let mut current_pml4 = CURRENT_PML4.lock();
|
||||
match current_pml4.as_mut() {
|
||||
None => virt - KERNEL_VIRT_START + KERNEL_PHYS_START.get().unwrap(),
|
||||
None => virt - KERNEL_HEAP_START + HEAP_PHYS_START.get().unwrap(),
|
||||
Some(pml4) => {
|
||||
let page = get_page(pml4, virt);
|
||||
match page {
|
||||
|
@ -74,6 +86,10 @@ fn map(pml4: &mut PageTable, virt: u64, phys: u64, user: bool, write: bool, exec
|
|||
if virt < 0x1000 {
|
||||
panic!("First page shouldn't be mapped");
|
||||
}
|
||||
{
|
||||
let mut frames_vec = PHYSICAL_FRAMES.lock();
|
||||
frames_vec.as_mut().unwrap().set(phys as usize / 0x1000, true);
|
||||
}
|
||||
let virt_page = virt as usize / 0x1000;
|
||||
let table_i = virt_page % 512;
|
||||
let directory_i = virt_page / 512 % 512;
|
||||
|
@ -88,8 +104,8 @@ fn map(pml4: &mut PageTable, virt: u64, phys: u64, user: bool, write: bool, exec
|
|||
table.entries_phys[table_i].set_execute_disable(!exec as u64);
|
||||
table.entries_phys[table_i].set_present(1);
|
||||
}
|
||||
pub fn setup_paging(loader_struct: &LoaderStruct, phys_start: u64) {
|
||||
KERNEL_PHYS_START.call_once(|| phys_start);
|
||||
pub fn setup_paging(loader_struct: &LoaderStruct, phys_start: u64, heap_start: u64) {
|
||||
HEAP_PHYS_START.call_once(|| heap_start);
|
||||
let mut memory_size = 0;
|
||||
for i in loader_struct.available_memory {
|
||||
if i.initial_page + i.page_count > memory_size {
|
||||
|
@ -97,11 +113,14 @@ pub fn setup_paging(loader_struct: &LoaderStruct, phys_start: u64) {
|
|||
}
|
||||
}
|
||||
info!("Memory size: {} MB", memory_size * 0x1000 / 1024 / 1024);
|
||||
let mut frames_vec = bitvec![u64, Lsb0; 1; memory_size as usize];
|
||||
for i in loader_struct.available_memory {
|
||||
for j in 0..i.page_count {
|
||||
let page = i.initial_page + j;
|
||||
frames_vec.set(page as usize, false);
|
||||
{
|
||||
let mut frames_vec = PHYSICAL_FRAMES.lock();
|
||||
*frames_vec = Some(bitvec![u64, Lsb0; 1; memory_size as usize]);
|
||||
for i in loader_struct.available_memory {
|
||||
for j in 0..i.page_count {
|
||||
let page = i.initial_page + j;
|
||||
frames_vec.as_mut().unwrap().set(page as usize, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
let text_start;
|
||||
|
@ -135,24 +154,19 @@ pub fn setup_paging(loader_struct: &LoaderStruct, phys_start: u64) {
|
|||
}
|
||||
}
|
||||
for i in text_start..text_end {
|
||||
let phys = i * 0x1000 - KERNEL_VIRT_START + phys_start;
|
||||
frames_vec.set(phys as usize / 0x1000, true);
|
||||
map(pml4, i * 0x1000, phys, false, false, true);
|
||||
map(pml4, i * 0x1000, i * 0x1000 - KERNEL_VIRT_START + phys_start, false, false, true);
|
||||
}
|
||||
for i in rodata_start..rodata_end {
|
||||
let phys = i * 0x1000 - KERNEL_VIRT_START + phys_start;
|
||||
frames_vec.set(phys as usize / 0x1000, true);
|
||||
map(pml4, i * 0x1000, phys, false, false, false);
|
||||
map(pml4, i * 0x1000, i * 0x1000 - KERNEL_VIRT_START + phys_start, false, false, false);
|
||||
}
|
||||
for i in data_start..data_end {
|
||||
let phys = i * 0x1000 - KERNEL_VIRT_START + phys_start;
|
||||
frames_vec.set(phys as usize / 0x1000, true);
|
||||
map(pml4, i * 0x1000, phys, false, true, false);
|
||||
map(pml4, i * 0x1000, i * 0x1000 - KERNEL_VIRT_START + phys_start, false, true, false);
|
||||
}
|
||||
for i in bss_start..bss_end {
|
||||
let phys = i * 0x1000 - KERNEL_VIRT_START + phys_start;
|
||||
frames_vec.set(phys as usize / 0x1000, true);
|
||||
map(pml4, i * 0x1000, phys, false, true, false);
|
||||
map(pml4, i * 0x1000, i * 0x1000 - KERNEL_VIRT_START + phys_start, false, true, false);
|
||||
}
|
||||
for i in 0..KERNEL_HEAP_INITIAL_SIZE / 0x1000 {
|
||||
map(pml4, KERNEL_HEAP_START + i as u64 * 0x1000, heap_start + i as u64 * 0x1000, false, true, false);
|
||||
}
|
||||
unsafe {
|
||||
load_cr3(virt_to_phys(pml4 as *const PageTable as u64));
|
||||
|
|
|
@ -3,21 +3,22 @@
|
|||
|
||||
extern crate alloc;
|
||||
|
||||
use core::{arch::global_asm, panic::PanicInfo};
|
||||
use core::{arch::global_asm, mem::MaybeUninit, panic::PanicInfo};
|
||||
|
||||
use cpu::{gdt::setup_gdt, idt::setup_idt, paging::setup_paging};
|
||||
use kernel_common::{
|
||||
instructions::{cli, hlt},
|
||||
loader_struct::{LoaderStruct, LOADER_STRUCT_MAGIC},
|
||||
log::init_logger,
|
||||
paging::{KERNEL_HEAP_INITIAL_SIZE, KERNEL_HEAP_START},
|
||||
};
|
||||
use linked_list_allocator::LockedHeap;
|
||||
use log::{error, info};
|
||||
use static_alloc::Bump;
|
||||
|
||||
mod cpu;
|
||||
|
||||
#[global_allocator]
|
||||
static ALLOC: Bump<[u8; 8 * 1024 * 1024]> = Bump::uninit();
|
||||
static ALLOC: LockedHeap = LockedHeap::empty();
|
||||
|
||||
global_asm!(
|
||||
"
|
||||
|
@ -35,16 +36,23 @@ global_asm!(
|
|||
);
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn main(temp_loader_struct: &LoaderStruct) -> ! {
|
||||
extern "C" fn main(temp_loader_struct: *const LoaderStruct) -> ! {
|
||||
unsafe {
|
||||
ALLOC.lock().init(KERNEL_HEAP_START as *mut u8, KERNEL_HEAP_INITIAL_SIZE);
|
||||
}
|
||||
init_logger();
|
||||
info!("Starting kernel...");
|
||||
let loader_struct = temp_loader_struct.clone();
|
||||
let mut loader_struct: LoaderStruct;
|
||||
unsafe {
|
||||
loader_struct = MaybeUninit::zeroed().assume_init();
|
||||
temp_loader_struct.copy_to(&mut loader_struct, 1);
|
||||
}
|
||||
if loader_struct.magic != LOADER_STRUCT_MAGIC {
|
||||
panic!("Invalid bootloader struct");
|
||||
}
|
||||
setup_gdt();
|
||||
setup_idt();
|
||||
setup_paging(&loader_struct, loader_struct.phys_kernel_start);
|
||||
setup_paging(&loader_struct, loader_struct.phys_kernel_start, loader_struct.phys_heap_start);
|
||||
loop {
|
||||
hlt();
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ pub struct LoaderStructMemoryRegion {
|
|||
pub struct LoaderStruct {
|
||||
pub magic: u64,
|
||||
pub phys_kernel_start: u64,
|
||||
pub phys_heap_start: u64,
|
||||
pub available_memory: [LoaderStructMemoryRegion; 1024],
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ pub struct PageTable {
|
|||
}
|
||||
|
||||
pub const KERNEL_VIRT_START: u64 = 0xffffffff80000000;
|
||||
pub const KERNEL_HEAP_START: u64 = 0xfffffffe00000000;
|
||||
pub const KERNEL_HEAP_INITIAL_SIZE: usize = 16 * 1024 * 1024;
|
||||
|
||||
pub unsafe fn load_cr3(cr3: u64) {
|
||||
asm!("mov cr3, {}", in(reg) cr3);
|
||||
|
|
6
loader/Cargo.lock
generated
6
loader/Cargo.lock
generated
|
@ -123,9 +123,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.68"
|
||||
version = "2.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9"
|
||||
checksum = "201fcda3845c23e8212cd466bfebf0bd20694490fc0356ae8e428e0824a915a6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -165,7 +165,7 @@ checksum = "4f345e42323c05e41e29e409505f5f8e0df7b5743340215d60344dbd79b729f4"
|
|||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.68",
|
||||
"syn 2.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use kernel_common::loader_struct::{LoaderStruct, LoaderStructMemoryRegion, LOADER_STRUCT_MAGIC};
|
||||
use uefi::table::boot::{MemoryMap, MemoryType};
|
||||
|
||||
pub fn generate_loader_struct(memory_map: &MemoryMap, phys_start: u64) -> LoaderStruct {
|
||||
pub fn generate_loader_struct(memory_map: &MemoryMap, phys_start: u64, heap_start: u64) -> LoaderStruct {
|
||||
let mut loader_struct = LoaderStruct {
|
||||
magic: LOADER_STRUCT_MAGIC,
|
||||
phys_kernel_start: phys_start,
|
||||
phys_heap_start: heap_start,
|
||||
available_memory: [LoaderStructMemoryRegion { initial_page: 0, page_count: 0 }; 1024],
|
||||
};
|
||||
let mut next_entry = 0;
|
||||
|
|
|
@ -10,6 +10,7 @@ use kernel_common::{
|
|||
instructions::{cli, hlt},
|
||||
loader_struct::LoaderStruct,
|
||||
log::init_logger,
|
||||
paging::KERNEL_HEAP_INITIAL_SIZE,
|
||||
};
|
||||
use loader_struct::generate_loader_struct;
|
||||
use log::{error, info};
|
||||
|
@ -17,7 +18,10 @@ use paging::setup_paging;
|
|||
use static_alloc::Bump;
|
||||
use uefi::{
|
||||
entry,
|
||||
table::{boot::MemoryType, Boot, SystemTable},
|
||||
table::{
|
||||
boot::{AllocateType, MemoryType},
|
||||
Boot, SystemTable,
|
||||
},
|
||||
Handle, Status,
|
||||
};
|
||||
|
||||
|
@ -36,13 +40,17 @@ fn main(image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
|
|||
info!("Starting bootloader...");
|
||||
uefi::helpers::init(&mut system_table).unwrap();
|
||||
let (kernel_start, kernel_entry) = load_kernel(KERNEL, &system_table);
|
||||
let heap_start = system_table
|
||||
.boot_services()
|
||||
.allocate_pages(AllocateType::AnyPages, MemoryType::LOADER_DATA, KERNEL_HEAP_INITIAL_SIZE / 0x1000)
|
||||
.unwrap();
|
||||
let memory_map;
|
||||
unsafe {
|
||||
memory_map = system_table.exit_boot_services(MemoryType::LOADER_DATA).1;
|
||||
}
|
||||
let pml4 = setup_paging(&memory_map);
|
||||
let pml4 = setup_paging(&memory_map, heap_start);
|
||||
map_kernel(KERNEL, pml4, kernel_start);
|
||||
let loader_struct = generate_loader_struct(&memory_map, kernel_start);
|
||||
let loader_struct = generate_loader_struct(&memory_map, kernel_start, heap_start);
|
||||
info!("Jumping to kernel...");
|
||||
unsafe {
|
||||
(mem::transmute::<_, extern "C" fn(&LoaderStruct) -> !>(kernel_entry))(&loader_struct);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use core::arch::asm;
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use kernel_common::paging::{load_cr3, PageEntry, PageTable};
|
||||
use kernel_common::paging::{load_cr3, PageEntry, PageTable, KERNEL_HEAP_INITIAL_SIZE, KERNEL_HEAP_START};
|
||||
use uefi::table::boot::{MemoryMap, MemoryType};
|
||||
|
||||
fn get_table_entry(table: &mut PageTable, i: usize) -> &mut PageTable {
|
||||
|
@ -32,7 +32,7 @@ pub fn map(pml4: &mut PageTable, virt: u64, phys: u64, write: bool, exec: bool)
|
|||
table.entries_phys[table_i].set_execute_disable(!exec as u64);
|
||||
table.entries_phys[table_i].set_present(1);
|
||||
}
|
||||
pub fn setup_paging(memory_map: &MemoryMap) -> &mut PageTable {
|
||||
pub fn setup_paging(memory_map: &MemoryMap, heap_start: u64) -> &mut PageTable {
|
||||
const NONE: Option<Box<PageTable>> = None;
|
||||
let pml4 = Box::leak(Box::new(PageTable {
|
||||
entries_phys: [PageEntry(0); 512],
|
||||
|
@ -59,6 +59,9 @@ pub fn setup_paging(memory_map: &MemoryMap) -> &mut PageTable {
|
|||
}
|
||||
}
|
||||
}
|
||||
for i in 0..KERNEL_HEAP_INITIAL_SIZE / 0x1000 {
|
||||
map(pml4, KERNEL_HEAP_START + i as u64 * 0x1000, heap_start + i as u64 * 0x1000, true, false);
|
||||
}
|
||||
unsafe {
|
||||
load_cr3(pml4 as *const PageTable as u64);
|
||||
// Write Protect
|
||||
|
|
Loading…
Add table
Reference in a new issue