Improve kernel paging code
This commit is contained in:
parent
5509ec251a
commit
8eba784e7c
4 changed files with 116 additions and 49 deletions
32
kernel/Cargo.lock
generated
32
kernel/Cargo.lock
generated
|
@ -8,6 +8,12 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b2d54853319fd101b8dd81de382bcbf3e03410a64d8928bbee85a3e7dcde483"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||
|
||||
[[package]]
|
||||
name = "bitfield"
|
||||
version = "0.15.0"
|
||||
|
@ -48,9 +54,20 @@ dependencies = [
|
|||
"bitvec",
|
||||
"com_logger",
|
||||
"log",
|
||||
"spin",
|
||||
"static-alloc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.22"
|
||||
|
@ -63,6 +80,21 @@ version = "0.7.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static-alloc"
|
||||
version = "0.2.5"
|
||||
|
|
|
@ -8,4 +8,5 @@ bitfield = "0.15.0"
|
|||
bitvec = {version = "1.0.1", default-features = false, features = ["alloc", "atomic"]}
|
||||
com_logger = { git = "https://git.strypsteen.com/mathieu/com_logger", version = "0.1.1" }
|
||||
log = "0.4.22"
|
||||
spin = "0.9.8"
|
||||
static-alloc = "0.2.5"
|
||||
|
|
|
@ -15,50 +15,44 @@ struct GDTEntry {
|
|||
struct GDT {
|
||||
entries: [GDTEntry; 3],
|
||||
}
|
||||
|
||||
#[repr(C, packed)]
|
||||
struct GDTDescriptor {
|
||||
limit: u16,
|
||||
base: u64,
|
||||
}
|
||||
|
||||
static mut GDT: GDT = GDT {
|
||||
entries: [
|
||||
GDTEntry {
|
||||
limit_low: 0,
|
||||
base_low: 0,
|
||||
base_middle: 0,
|
||||
access: 0,
|
||||
flags: 0,
|
||||
base_high: 0,
|
||||
},
|
||||
GDTEntry {
|
||||
limit_low: 0,
|
||||
base_low: 0,
|
||||
base_middle: 0,
|
||||
access: 0x9a,
|
||||
flags: 0x20,
|
||||
base_high: 0,
|
||||
},
|
||||
GDTEntry {
|
||||
limit_low: 0,
|
||||
base_low: 0,
|
||||
base_middle: 0,
|
||||
access: 0x92,
|
||||
flags: 0,
|
||||
base_high: 0,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
pub fn setup_gdt() {
|
||||
let ptr;
|
||||
unsafe {
|
||||
ptr = GDT.entries.as_ptr() as u64;
|
||||
}
|
||||
let gdt = Box::leak(Box::new(GDT {
|
||||
entries: [
|
||||
GDTEntry {
|
||||
limit_low: 0,
|
||||
base_low: 0,
|
||||
base_middle: 0,
|
||||
access: 0,
|
||||
flags: 0,
|
||||
base_high: 0,
|
||||
},
|
||||
GDTEntry {
|
||||
limit_low: 0,
|
||||
base_low: 0,
|
||||
base_middle: 0,
|
||||
access: 0x9a,
|
||||
flags: 0x20,
|
||||
base_high: 0,
|
||||
},
|
||||
GDTEntry {
|
||||
limit_low: 0,
|
||||
base_low: 0,
|
||||
base_middle: 0,
|
||||
access: 0x92,
|
||||
flags: 0,
|
||||
base_high: 0,
|
||||
},
|
||||
],
|
||||
}));
|
||||
let gdt_descriptor = Box::leak(Box::new(GDTDescriptor {
|
||||
limit: (size_of::<GDT>() - 1) as u16,
|
||||
base: ptr,
|
||||
base: gdt.entries.as_ptr() as u64,
|
||||
}));
|
||||
unsafe {
|
||||
asm!("
|
||||
|
|
|
@ -4,6 +4,7 @@ use alloc::boxed::Box;
|
|||
use bitfield::bitfield;
|
||||
use bitvec::{bitvec, order::Lsb0};
|
||||
use log::info;
|
||||
use spin::{Mutex, Once};
|
||||
|
||||
use crate::misc::loader_struct::LoaderStruct;
|
||||
|
||||
|
@ -41,13 +42,9 @@ extern "C" {
|
|||
}
|
||||
|
||||
const KERNEL_VIRT_START: u64 = 0xffffffff80000000;
|
||||
static mut KERNEL_PHYS_START: u64 = 0;
|
||||
static KERNEL_PHYS_START: Once<u64> = Once::new();
|
||||
static CURRENT_PML4: Mutex<Option<&mut PageTable>> = Mutex::new(None);
|
||||
|
||||
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;
|
||||
|
@ -58,11 +55,46 @@ fn get_table_entry(table: &mut PageTable, i: usize) -> &mut PageTable {
|
|||
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_user(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) {
|
||||
fn get_page(pml4: &mut PageTable, virt: u64) -> Option<&mut PageEntry> {
|
||||
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 = &mut pml4.entries_virt[pml4_i];
|
||||
if pdpt.is_some() {
|
||||
let pdpt = pdpt.as_mut().unwrap();
|
||||
let directory = &mut pdpt.entries_virt[pdpt_i];
|
||||
if directory.is_some() {
|
||||
let directory = directory.as_mut().unwrap();
|
||||
let table = &mut directory.entries_virt[directory_i];
|
||||
if table.is_some() {
|
||||
let table = table.as_mut().unwrap();
|
||||
return Some(&mut table.entries_phys[table_i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
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(),
|
||||
Some(pml4) => {
|
||||
let page = get_page(pml4, virt);
|
||||
match page {
|
||||
None => 0,
|
||||
Some(page) => page.address() * 0x1000 + virt % 0x1000,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn map(pml4: &mut PageTable, virt: u64, phys: u64, user: bool, write: bool, exec: bool) {
|
||||
if virt < 0x1000 {
|
||||
panic!("First page shouldn't be mapped");
|
||||
}
|
||||
|
@ -75,14 +107,13 @@ pub fn map(pml4: &mut PageTable, virt: u64, phys: u64, write: bool, exec: bool)
|
|||
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_user(user as u64);
|
||||
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;
|
||||
}
|
||||
KERNEL_PHYS_START.call_once(|| phys_start);
|
||||
let mut memory_size = 0;
|
||||
for i in loader_struct.available_memory {
|
||||
if i.initial_page + i.page_count > memory_size {
|
||||
|
@ -120,27 +151,36 @@ pub fn setup_paging(loader_struct: &LoaderStruct, phys_start: u64) {
|
|||
entries_phys: [PageEntry(0); 512],
|
||||
entries_virt: [NONE; 512],
|
||||
}));
|
||||
for i in 256..512 {
|
||||
get_table_entry(pml4, i);
|
||||
pml4.entries_phys[i].set_user(0);
|
||||
if i != 511 {
|
||||
pml4.entries_phys[i].set_execute_disable(1);
|
||||
}
|
||||
}
|
||||
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);
|
||||
map(pml4, i * 0x1000, phys, 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);
|
||||
map(pml4, i * 0x1000, phys, 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, true, false);
|
||||
map(pml4, i * 0x1000, phys, 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, true, false);
|
||||
map(pml4, i * 0x1000, phys, false, true, false);
|
||||
}
|
||||
unsafe {
|
||||
asm!("mov cr3, {}", in(reg) virt_to_phys(pml4 as *const PageTable as u64));
|
||||
}
|
||||
let mut current_pml4 = CURRENT_PML4.lock();
|
||||
*current_pml4 = Some(pml4);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue