This commit is contained in:
parent
bb6de0ce8d
commit
825ed695e7
3 changed files with 77 additions and 51 deletions
|
@ -28,6 +28,8 @@ extern "C" {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct AddressSpace {
|
pub struct AddressSpace {
|
||||||
|
pub is_kernel: bool,
|
||||||
|
pub pml4_physical_address: u64,
|
||||||
pub pml4: OnceCell<Box<PageTable>>,
|
pub pml4: OnceCell<Box<PageTable>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,6 +43,7 @@ pub const USER_END: u64 = 0x800000000000 - 0x1000; // Avoid accidentally jumping
|
||||||
|
|
||||||
impl AddressSpace {
|
impl AddressSpace {
|
||||||
pub fn get_page(&mut self, virt: u64) -> Option<&mut PageEntry> {
|
pub fn get_page(&mut self, virt: u64) -> Option<&mut PageEntry> {
|
||||||
|
assert!(virt < USER_END || self.is_kernel);
|
||||||
let virt_page = virt as usize / 0x1000;
|
let virt_page = virt as usize / 0x1000;
|
||||||
let table_i = virt_page % 512;
|
let table_i = virt_page % 512;
|
||||||
let directory_i = virt_page / 512 % 512;
|
let directory_i = virt_page / 512 % 512;
|
||||||
|
@ -84,6 +87,7 @@ impl AddressSpace {
|
||||||
assert!(virt >= 0x1000, "First page shouldn't be mapped");
|
assert!(virt >= 0x1000, "First page shouldn't be mapped");
|
||||||
assert!(!write || !exec || virt == 0x1000);
|
assert!(!write || !exec || virt == 0x1000);
|
||||||
assert!(user == (virt < USER_END) || virt == 0x1000);
|
assert!(user == (virt < USER_END) || virt == 0x1000);
|
||||||
|
assert!(virt < USER_END || self.is_kernel);
|
||||||
{
|
{
|
||||||
let mut frames_vec = PHYSICAL_FRAMES.lock();
|
let mut frames_vec = PHYSICAL_FRAMES.lock();
|
||||||
let frame = phys as usize / 0x1000;
|
let frame = phys as usize / 0x1000;
|
||||||
|
@ -96,9 +100,9 @@ impl AddressSpace {
|
||||||
let directory_i = virt_page / 512 % 512;
|
let directory_i = virt_page / 512 % 512;
|
||||||
let pdpt_i = virt_page / 512 / 512 % 512;
|
let pdpt_i = virt_page / 512 / 512 % 512;
|
||||||
let pml4_i = virt_page / 512 / 512 / 512 % 512;
|
let pml4_i = virt_page / 512 / 512 / 512 % 512;
|
||||||
self.create_table_entry(pml4_i as i32, -1, -1, true, true);
|
self.create_table_entry(pml4_i as i32, -1, -1, true, true, false);
|
||||||
self.create_table_entry(pml4_i as i32, pdpt_i as i32, -1, true, true);
|
self.create_table_entry(pml4_i as i32, pdpt_i as i32, -1, true, true, false);
|
||||||
self.create_table_entry(pml4_i as i32, pdpt_i as i32, directory_i as i32, true, true);
|
self.create_table_entry(pml4_i as i32, pdpt_i as i32, directory_i as i32, true, true, false);
|
||||||
let table = self.pml4.get_mut().unwrap().entries_virt[pml4_i].as_mut().unwrap().entries_virt[pdpt_i].as_mut().unwrap().entries_virt[directory_i]
|
let table = self.pml4.get_mut().unwrap().entries_virt[pml4_i].as_mut().unwrap().entries_virt[pdpt_i].as_mut().unwrap().entries_virt[directory_i]
|
||||||
.as_mut()
|
.as_mut()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -173,12 +177,18 @@ impl AddressSpace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub unsafe fn switch(&self) {
|
pub unsafe fn switch(&self) {
|
||||||
let pml4_address = self.pml4.get().unwrap().as_ref() as *const PageTable as u64;
|
|
||||||
unsafe {
|
unsafe {
|
||||||
load_cr3(virt_to_phys(pml4_address));
|
load_cr3(self.pml4_physical_address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn create_table_entry(&mut self, pml4_i: i32, pdpt_i: i32, directory_i: i32, user: bool, exec: bool) {
|
fn create_table_entry(&mut self, pml4_i: i32, pdpt_i: i32, directory_i: i32, user: bool, exec: bool, force_create: bool) {
|
||||||
|
let mut new_table = None;
|
||||||
|
let mut new_table_phys = 0;
|
||||||
|
if force_create {
|
||||||
|
let _new_table = create_page_table();
|
||||||
|
new_table_phys = self.virt_to_phys(_new_table.as_ref() as *const PageTable as u64) / 0x1000;
|
||||||
|
new_table = Some(_new_table);
|
||||||
|
}
|
||||||
let mut table = self.pml4.get_mut().unwrap();
|
let mut table = self.pml4.get_mut().unwrap();
|
||||||
let mut i = pml4_i as usize;
|
let mut i = pml4_i as usize;
|
||||||
if pdpt_i != -1 {
|
if pdpt_i != -1 {
|
||||||
|
@ -189,21 +199,43 @@ impl AddressSpace {
|
||||||
table = table.entries_virt[i].as_mut().unwrap();
|
table = table.entries_virt[i].as_mut().unwrap();
|
||||||
i = directory_i as usize;
|
i = directory_i as usize;
|
||||||
}
|
}
|
||||||
|
let mut retry = false;
|
||||||
if table.entries_virt[i].is_none() {
|
if table.entries_virt[i].is_none() {
|
||||||
let new_table = Box::new(PageTable {
|
if force_create {
|
||||||
entries_phys: [PageEntry(0); 512],
|
table.entries_phys[i].set_address(new_table_phys);
|
||||||
entries_virt: [const { None }; 512],
|
table.entries_virt[i] = new_table;
|
||||||
});
|
|
||||||
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_write(1);
|
||||||
table.entries_phys[i].set_user(user as u64);
|
table.entries_phys[i].set_user(user as u64);
|
||||||
table.entries_phys[i].set_execute_disable(!exec as u64);
|
table.entries_phys[i].set_execute_disable(!exec as u64);
|
||||||
table.entries_phys[i].set_present(1);
|
table.entries_phys[i].set_present(1);
|
||||||
|
} else {
|
||||||
|
retry = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if retry {
|
||||||
|
self.create_table_entry(pml4_i, pdpt_i, directory_i, user, exec, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn virt_to_phys(&mut self, virt: u64) -> u64 {
|
||||||
|
if !self.is_kernel {
|
||||||
|
let kernel_proc = get_kernel_process();
|
||||||
|
return kernel_proc.lock().address_space.virt_to_phys(virt);
|
||||||
|
}
|
||||||
|
if !PAGING_ACTIVE.load(Ordering::SeqCst) {
|
||||||
|
assert!(virt >= KERNEL_HEAP_START);
|
||||||
|
assert!(virt < KERNEL_HEAP_START + KERNEL_HEAP_INITIAL_SIZE as u64);
|
||||||
|
return virt - KERNEL_HEAP_START + HEAP_PHYS_START.load(Ordering::SeqCst);
|
||||||
|
}
|
||||||
|
self.get_page(virt).unwrap().address() * 0x1000 + virt % 0x1000
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_page_table() -> Box<PageTable> {
|
||||||
|
return Box::new(PageTable {
|
||||||
|
entries_phys: [PageEntry(0); 512],
|
||||||
|
entries_virt: [const { None }; 512],
|
||||||
|
});
|
||||||
|
}
|
||||||
fn get_free_frame() -> u64 {
|
fn get_free_frame() -> u64 {
|
||||||
let frames_vec = PHYSICAL_FRAMES.lock();
|
let frames_vec = PHYSICAL_FRAMES.lock();
|
||||||
let frames_vec = frames_vec.get().unwrap();
|
let frames_vec = frames_vec.get().unwrap();
|
||||||
|
@ -220,15 +252,6 @@ fn invlpg(addr: u64) {
|
||||||
}
|
}
|
||||||
smp_invalidate_tlb();
|
smp_invalidate_tlb();
|
||||||
}
|
}
|
||||||
pub fn virt_to_phys(virt: u64) -> u64 {
|
|
||||||
assert!(virt >= KERNEL_HEAP_START);
|
|
||||||
assert!(virt < KERNEL_HEAP_START + KERNEL_HEAP_INITIAL_SIZE as u64);
|
|
||||||
if !PAGING_ACTIVE.load(Ordering::SeqCst) {
|
|
||||||
return virt - KERNEL_HEAP_START + HEAP_PHYS_START.load(Ordering::SeqCst);
|
|
||||||
}
|
|
||||||
let heap_map = HEAP_PHYS_MAPPING.lock();
|
|
||||||
heap_map[(virt as usize - KERNEL_HEAP_START as usize) / 0x1000] + virt % 0x1000
|
|
||||||
}
|
|
||||||
pub fn setup_paging(loader_struct: &LoaderStruct, phys_start: u64, heap_start: u64) {
|
pub fn setup_paging(loader_struct: &LoaderStruct, phys_start: u64, heap_start: u64) {
|
||||||
HEAP_PHYS_START.store(heap_start, Ordering::SeqCst);
|
HEAP_PHYS_START.store(heap_start, Ordering::SeqCst);
|
||||||
let mut memory_size = 0;
|
let mut memory_size = 0;
|
||||||
|
@ -274,18 +297,14 @@ pub fn setup_paging(loader_struct: &LoaderStruct, phys_start: u64, heap_start: u
|
||||||
let kernel_proc = get_kernel_process();
|
let kernel_proc = get_kernel_process();
|
||||||
let mut kernel_proc = kernel_proc.lock();
|
let mut kernel_proc = kernel_proc.lock();
|
||||||
let address_space = &mut kernel_proc.address_space;
|
let address_space = &mut kernel_proc.address_space;
|
||||||
address_space
|
let pml4 = create_page_table();
|
||||||
.pml4
|
address_space.pml4_physical_address = address_space.virt_to_phys(pml4.as_ref() as *const PageTable as u64);
|
||||||
.set(Box::new(PageTable {
|
address_space.pml4.set(pml4).unwrap_or_else(|_| panic!());
|
||||||
entries_phys: [PageEntry(0); 512],
|
|
||||||
entries_virt: [const { None }; 512],
|
|
||||||
}))
|
|
||||||
.unwrap_or_else(|_| panic!());
|
|
||||||
for i in 256..512 {
|
for i in 256..512 {
|
||||||
if i != 511 {
|
if i == 511 {
|
||||||
address_space.create_table_entry(i as i32, -1, -1, false, false);
|
address_space.create_table_entry(i as i32, -1, -1, false, true, false);
|
||||||
} else {
|
} else {
|
||||||
address_space.create_table_entry(i as i32, -1, -1, false, true);
|
address_space.create_table_entry(i as i32, -1, -1, false, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for i in text_start..text_end {
|
for i in text_start..text_end {
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
use core::cell::{LazyCell, OnceCell};
|
use core::cell::{LazyCell, OnceCell};
|
||||||
|
|
||||||
use alloc::{boxed::Box, sync::Arc};
|
use alloc::sync::Arc;
|
||||||
use kernel_common::paging::{PageEntry, PageTable};
|
use kernel_common::paging::PageTable;
|
||||||
|
|
||||||
use crate::{cpu::paging::AddressSpace, misc::elf::load_binary, INIT_BINARY};
|
use crate::{
|
||||||
|
cpu::paging::{create_page_table, AddressSpace},
|
||||||
|
misc::elf::load_binary,
|
||||||
|
INIT_BINARY,
|
||||||
|
};
|
||||||
|
|
||||||
use super::{locks::Spinlock, scheduler::SCHEDULER, task::create_task};
|
use super::{locks::Spinlock, scheduler::SCHEDULER, task::create_task};
|
||||||
|
|
||||||
|
@ -14,7 +18,11 @@ pub struct Process {
|
||||||
|
|
||||||
static KERNEL_PROCESS: Spinlock<LazyCell<Arc<Spinlock<Process>>>> = Spinlock::new(LazyCell::new(|| {
|
static KERNEL_PROCESS: Spinlock<LazyCell<Arc<Spinlock<Process>>>> = Spinlock::new(LazyCell::new(|| {
|
||||||
let process = Process {
|
let process = Process {
|
||||||
address_space: AddressSpace { pml4: OnceCell::new() },
|
address_space: AddressSpace {
|
||||||
|
is_kernel: true,
|
||||||
|
pml4: OnceCell::new(),
|
||||||
|
pml4_physical_address: 0,
|
||||||
|
},
|
||||||
binary: None,
|
binary: None,
|
||||||
};
|
};
|
||||||
Arc::new(Spinlock::new(process))
|
Arc::new(Spinlock::new(process))
|
||||||
|
@ -24,20 +32,22 @@ pub fn get_kernel_process() -> Arc<Spinlock<Process>> {
|
||||||
KERNEL_PROCESS.lock().clone()
|
KERNEL_PROCESS.lock().clone()
|
||||||
}
|
}
|
||||||
pub fn create_process(binary: Option<&'static [u8]>) -> Arc<Spinlock<Process>> {
|
pub fn create_process(binary: Option<&'static [u8]>) -> Arc<Spinlock<Process>> {
|
||||||
let process = Process {
|
let mut process = Process {
|
||||||
address_space: AddressSpace { pml4: OnceCell::new() },
|
address_space: AddressSpace {
|
||||||
|
is_kernel: false,
|
||||||
|
pml4: OnceCell::new(),
|
||||||
|
pml4_physical_address: 0,
|
||||||
|
},
|
||||||
binary,
|
binary,
|
||||||
};
|
};
|
||||||
let mut pml4 = Box::new(PageTable {
|
let mut pml4 = create_page_table();
|
||||||
entries_phys: [PageEntry(0); 512],
|
|
||||||
entries_virt: [const { None }; 512],
|
|
||||||
});
|
|
||||||
let kernel_proc = get_kernel_process();
|
let kernel_proc = get_kernel_process();
|
||||||
let kernel_proc = kernel_proc.lock();
|
let mut kernel_proc = kernel_proc.lock();
|
||||||
let kernel_pml4 = kernel_proc.address_space.pml4.get().unwrap();
|
let kernel_pml4 = kernel_proc.address_space.pml4.get().unwrap();
|
||||||
for i in 256..512 {
|
for i in 256..512 {
|
||||||
pml4.entries_phys[i] = kernel_pml4.entries_phys[i];
|
pml4.entries_phys[i] = kernel_pml4.entries_phys[i];
|
||||||
}
|
}
|
||||||
|
process.address_space.pml4_physical_address = kernel_proc.address_space.virt_to_phys(pml4.as_ref() as *const PageTable as u64);
|
||||||
process.address_space.pml4.set(pml4).unwrap_or_else(|_| panic!());
|
process.address_space.pml4.set(pml4).unwrap_or_else(|_| panic!());
|
||||||
Arc::new(Spinlock::new(process))
|
Arc::new(Spinlock::new(process))
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,7 @@ use core::{ptr::copy, sync::atomic::Ordering};
|
||||||
use alloc::{vec, vec::Vec};
|
use alloc::{vec, vec::Vec};
|
||||||
use kernel_common::{instructions::pause, paging::PageTable};
|
use kernel_common::{instructions::pause, paging::PageTable};
|
||||||
|
|
||||||
use crate::{
|
use crate::{cpu::isr::ISR_INVALIDATE_TLB, BROADCASTED_PANIC};
|
||||||
cpu::{isr::ISR_INVALIDATE_TLB, paging::virt_to_phys},
|
|
||||||
BROADCASTED_PANIC,
|
|
||||||
};
|
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
hpet::sleep,
|
hpet::sleep,
|
||||||
|
@ -36,7 +33,7 @@ pub fn start_aps() {
|
||||||
let mut kernel_proc = kernel_proc.lock();
|
let mut kernel_proc = kernel_proc.lock();
|
||||||
let address_space = &mut kernel_proc.address_space;
|
let address_space = &mut kernel_proc.address_space;
|
||||||
let pml4 = &address_space.pml4;
|
let pml4 = &address_space.pml4;
|
||||||
let pml4_phys_addr_u64 = virt_to_phys(pml4.get().unwrap().as_ref() as *const PageTable as u64);
|
let pml4_phys_addr_u64 = address_space.virt_to_phys(pml4.get().unwrap().as_ref() as *const PageTable as u64);
|
||||||
pml4_phys_addr = u32::try_from(pml4_phys_addr_u64).unwrap();
|
pml4_phys_addr = u32::try_from(pml4_phys_addr_u64).unwrap();
|
||||||
unsafe {
|
unsafe {
|
||||||
address_space.map_range(0x1000, 0x1000, 0x1000, false, true, false, false);
|
address_space.map_range(0x1000, 0x1000, 0x1000, false, true, false, false);
|
||||||
|
|
Loading…
Add table
Reference in a new issue