Implement paging in kernel
This commit is contained in:
parent
82ebfc839a
commit
5509ec251a
7 changed files with 141 additions and 5 deletions
|
@ -1,16 +1,24 @@
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
. = 0xffffffff80000000;
|
. = 0xffffffff80000000;
|
||||||
.text ALIGN(0x1000) : {
|
.text ALIGN(0x1000) : {
|
||||||
|
_text_start = .;
|
||||||
*(.text*)
|
*(.text*)
|
||||||
|
_text_end = .;
|
||||||
}
|
}
|
||||||
.rodata ALIGN(0x1000) : {
|
.rodata ALIGN(0x1000) : {
|
||||||
|
_rodata_start = .;
|
||||||
*(.rodata*)
|
*(.rodata*)
|
||||||
|
_rodata_end = .;
|
||||||
}
|
}
|
||||||
.data ALIGN(0x1000) : {
|
.data ALIGN(0x1000) : {
|
||||||
|
_data_start = .;
|
||||||
*(.data*)
|
*(.data*)
|
||||||
*(.got)
|
*(.got)
|
||||||
|
_data_end = .;
|
||||||
}
|
}
|
||||||
.bss ALIGN(0x1000) : {
|
.bss ALIGN(0x1000) : {
|
||||||
|
_bss_start = .;
|
||||||
*(.bss*)
|
*(.bss*)
|
||||||
|
_bss_end = .;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,88 @@
|
||||||
|
use core::arch::asm;
|
||||||
|
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
use bitfield::bitfield;
|
||||||
use bitvec::{bitvec, order::Lsb0};
|
use bitvec::{bitvec, order::Lsb0};
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
use crate::misc::loader_struct::LoaderStruct;
|
use crate::misc::loader_struct::LoaderStruct;
|
||||||
|
|
||||||
pub fn setup_paging(loader_struct: &LoaderStruct) {
|
bitfield! {
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
struct PageEntry(u64);
|
||||||
|
present, set_present: 0, 0;
|
||||||
|
write, set_write: 1, 1;
|
||||||
|
user, set_user: 2, 2;
|
||||||
|
write_through, set_write_through: 3, 3;
|
||||||
|
cache_disable, set_cache_disable: 4, 4;
|
||||||
|
accessed, set_accessed: 5, 5;
|
||||||
|
dirty, set_dirty: 6, 6;
|
||||||
|
page_size, set_page_size: 7, 7;
|
||||||
|
global, set_global: 8, 8;
|
||||||
|
available, set_available: 11, 9;
|
||||||
|
address, set_address: 62, 12;
|
||||||
|
execute_disable, set_execute_disable: 63, 63;
|
||||||
|
}
|
||||||
|
#[repr(C, align(0x1000))]
|
||||||
|
pub struct PageTable {
|
||||||
|
entries_phys: [PageEntry; 512],
|
||||||
|
entries_virt: [Option<Box<PageTable>>; 512],
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
static _text_start: u8;
|
||||||
|
static _text_end: u8;
|
||||||
|
static _rodata_start: u8;
|
||||||
|
static _rodata_end: u8;
|
||||||
|
static _data_start: u8;
|
||||||
|
static _data_end: u8;
|
||||||
|
static _bss_start: u8;
|
||||||
|
static _bss_end: u8;
|
||||||
|
}
|
||||||
|
|
||||||
|
const KERNEL_VIRT_START: u64 = 0xffffffff80000000;
|
||||||
|
static mut KERNEL_PHYS_START: u64 = 0;
|
||||||
|
|
||||||
|
fn virt_to_phys(virt: u64) -> u64 {
|
||||||
|
unsafe {
|
||||||
|
return virt - KERNEL_VIRT_START + KERNEL_PHYS_START;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn get_table_entry(table: &mut PageTable, i: usize) -> &mut PageTable {
|
||||||
|
if table.entries_virt[i].is_none() {
|
||||||
|
const NONE: Option<Box<PageTable>> = None;
|
||||||
|
let new_table = Box::new(PageTable {
|
||||||
|
entries_phys: [PageEntry(0); 512],
|
||||||
|
entries_virt: [NONE; 512],
|
||||||
|
});
|
||||||
|
table.entries_phys[i].set_address(virt_to_phys(new_table.as_ref() as *const PageTable as u64) / 0x1000);
|
||||||
|
table.entries_virt[i] = Some(new_table);
|
||||||
|
table.entries_phys[i].set_write(1);
|
||||||
|
table.entries_phys[i].set_present(1);
|
||||||
|
}
|
||||||
|
return table.entries_virt[i].as_mut().unwrap();
|
||||||
|
}
|
||||||
|
pub fn map(pml4: &mut PageTable, virt: u64, phys: u64, write: bool, exec: bool) {
|
||||||
|
if virt < 0x1000 {
|
||||||
|
panic!("First page shouldn't be mapped");
|
||||||
|
}
|
||||||
|
let virt_page = virt as usize / 0x1000;
|
||||||
|
let table_i = virt_page % 512;
|
||||||
|
let directory_i = virt_page / 512 % 512;
|
||||||
|
let pdpt_i = virt_page / 512 / 512 % 512;
|
||||||
|
let pml4_i = virt_page / 512 / 512 / 512 % 512;
|
||||||
|
let pdpt = get_table_entry(pml4, pml4_i);
|
||||||
|
let directory = get_table_entry(pdpt, pdpt_i);
|
||||||
|
let table = get_table_entry(directory, directory_i);
|
||||||
|
table.entries_phys[table_i].set_address(phys / 0x1000);
|
||||||
|
table.entries_phys[table_i].set_write(write as u64);
|
||||||
|
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) {
|
||||||
|
unsafe {
|
||||||
|
KERNEL_PHYS_START = phys_start;
|
||||||
|
}
|
||||||
let mut memory_size = 0;
|
let mut memory_size = 0;
|
||||||
for i in loader_struct.available_memory {
|
for i in loader_struct.available_memory {
|
||||||
if i.initial_page + i.page_count > memory_size {
|
if i.initial_page + i.page_count > memory_size {
|
||||||
|
@ -18,4 +97,50 @@ pub fn setup_paging(loader_struct: &LoaderStruct) {
|
||||||
frames_vec.set(page as usize, false);
|
frames_vec.set(page as usize, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let text_start;
|
||||||
|
let text_end;
|
||||||
|
let rodata_start;
|
||||||
|
let rodata_end;
|
||||||
|
let data_start;
|
||||||
|
let data_end;
|
||||||
|
let bss_start;
|
||||||
|
let bss_end;
|
||||||
|
unsafe {
|
||||||
|
text_start = &_text_start as *const u8 as u64 / 0x1000;
|
||||||
|
text_end = (&_text_end as *const u8 as u64 + 0xfff) / 0x1000;
|
||||||
|
rodata_start = &_rodata_start as *const u8 as u64 / 0x1000;
|
||||||
|
rodata_end = (&_rodata_end as *const u8 as u64 + 0xfff) / 0x1000;
|
||||||
|
data_start = &_data_start as *const u8 as u64 / 0x1000;
|
||||||
|
data_end = (&_data_end as *const u8 as u64 + 0xfff) / 0x1000;
|
||||||
|
bss_start = &_bss_start as *const u8 as u64 / 0x1000;
|
||||||
|
bss_end = (&_bss_end as *const u8 as u64 + 0xfff) / 0x1000;
|
||||||
|
}
|
||||||
|
const NONE: Option<Box<PageTable>> = None;
|
||||||
|
let pml4 = Box::leak(Box::new(PageTable {
|
||||||
|
entries_phys: [PageEntry(0); 512],
|
||||||
|
entries_virt: [NONE; 512],
|
||||||
|
}));
|
||||||
|
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, 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);
|
||||||
|
}
|
||||||
|
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, 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, true, false);
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
asm!("mov cr3, {}", in(reg) virt_to_phys(pml4 as *const PageTable as u64));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ extern "C" fn main(temp_loader_struct: &LoaderStruct) -> ! {
|
||||||
}
|
}
|
||||||
setup_gdt();
|
setup_gdt();
|
||||||
setup_idt();
|
setup_idt();
|
||||||
setup_paging(&loader_struct);
|
setup_paging(&loader_struct, loader_struct.phys_kernel_start);
|
||||||
loop {
|
loop {
|
||||||
unsafe {
|
unsafe {
|
||||||
asm!("hlt");
|
asm!("hlt");
|
||||||
|
|
|
@ -8,5 +8,6 @@ pub struct LoaderStructMemoryRegion {
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct LoaderStruct {
|
pub struct LoaderStruct {
|
||||||
pub magic: u64,
|
pub magic: u64,
|
||||||
|
pub phys_kernel_start: u64,
|
||||||
pub available_memory: [LoaderStructMemoryRegion; 1024],
|
pub available_memory: [LoaderStructMemoryRegion; 1024],
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ use uefi::table::{
|
||||||
|
|
||||||
use crate::paging::{map, PageTable};
|
use crate::paging::{map, PageTable};
|
||||||
|
|
||||||
pub const KERNEL_VIRT_START: u64 = 0xffffffff80000000;
|
const KERNEL_VIRT_START: u64 = 0xffffffff80000000;
|
||||||
|
|
||||||
pub fn load_kernel(kernel: &[u8], system_table: &SystemTable<Boot>) -> (u64, u64) {
|
pub fn load_kernel(kernel: &[u8], system_table: &SystemTable<Boot>) -> (u64, u64) {
|
||||||
let file: ElfBytes<LittleEndian> = ElfBytes::minimal_parse(kernel).unwrap();
|
let file: ElfBytes<LittleEndian> = ElfBytes::minimal_parse(kernel).unwrap();
|
||||||
|
|
|
@ -9,12 +9,14 @@ pub struct LoaderStructMemoryRegion {
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct LoaderStruct {
|
pub struct LoaderStruct {
|
||||||
magic: u64,
|
magic: u64,
|
||||||
|
phys_kernel_start: u64,
|
||||||
available_memory: [LoaderStructMemoryRegion; 1024],
|
available_memory: [LoaderStructMemoryRegion; 1024],
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_loader_struct(memory_map: &MemoryMap) -> LoaderStruct {
|
pub fn generate_loader_struct(memory_map: &MemoryMap, phys_start: u64) -> LoaderStruct {
|
||||||
let mut loader_struct = LoaderStruct {
|
let mut loader_struct = LoaderStruct {
|
||||||
magic: 0x123456789abcdef0,
|
magic: 0x123456789abcdef0,
|
||||||
|
phys_kernel_start: phys_start,
|
||||||
available_memory: [LoaderStructMemoryRegion { initial_page: 0, page_count: 0 }; 1024],
|
available_memory: [LoaderStructMemoryRegion { initial_page: 0, page_count: 0 }; 1024],
|
||||||
};
|
};
|
||||||
let mut next_entry = 0;
|
let mut next_entry = 0;
|
||||||
|
|
|
@ -37,7 +37,7 @@ fn main(image_handle: Handle, mut system_table: SystemTable<Boot>) -> Status {
|
||||||
}
|
}
|
||||||
let pml4 = setup_paging(&memory_map);
|
let pml4 = setup_paging(&memory_map);
|
||||||
map_kernel(KERNEL, pml4, kernel_start);
|
map_kernel(KERNEL, pml4, kernel_start);
|
||||||
let loader_struct = generate_loader_struct(&memory_map);
|
let loader_struct = generate_loader_struct(&memory_map, kernel_start);
|
||||||
info!("Jumping to kernel...");
|
info!("Jumping to kernel...");
|
||||||
unsafe {
|
unsafe {
|
||||||
(mem::transmute::<_, extern "C" fn(&LoaderStruct) -> !>(kernel_entry))(&loader_struct);
|
(mem::transmute::<_, extern "C" fn(&LoaderStruct) -> !>(kernel_entry))(&loader_struct);
|
||||||
|
|
Loading…
Add table
Reference in a new issue