Paging works, can now run main from virtual(ish) memory
This commit is contained in:
@@ -11,7 +11,7 @@ use kernel::{
|
||||
},
|
||||
print,
|
||||
};
|
||||
use x86_drivers::gdt::{DPL, GdtEntry, GdtPointer, GdtSelector};
|
||||
use x86_drivers::{gdt::{DPL, GdtEntry, GdtPointer, GdtSelector}, paging::PageMapLevel4};
|
||||
pub use x86_drivers::prelude::*;
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
@@ -123,11 +123,39 @@ extern "efiapi" fn efi_main(handle: Handle, table: *mut EfiSystemTable) -> UefiS
|
||||
|
||||
let res = alloc.request_pages(&RegionRequest::new(2));
|
||||
print!("Region request returned ({res:?})\r\n");
|
||||
let sp = reserve_kernel_pages(image_info.0, image_info.1, 4096, &mut alloc);
|
||||
let (sp, plm4) = reserve_kernel_pages(image_info.0, image_info.1, 4096, &mut alloc).unwrap();
|
||||
print!("Potential new stack pointer: {sp:?}\r\n");
|
||||
let new_stack_pointer = unsafe { sp.cast::<u8>().add(4096) };
|
||||
unsafe { specify_kernel(sp, plm4) };
|
||||
}
|
||||
|
||||
#[allow(clippy::empty_loop)]
|
||||
loop {}
|
||||
unsafe fn specify_kernel(sp: *const u8, plm4_phys: *const PageMapLevel4) -> ! {
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"mov rsp, {sp}",
|
||||
"mov rbp, {sp}",
|
||||
"mov cr3, {plm4}",
|
||||
"jmp {main}",
|
||||
sp = in(reg) sp,
|
||||
plm4 = in(reg) plm4_phys,
|
||||
main = sym kernel_main,
|
||||
options(nostack,preserves_flags,noreturn))
|
||||
}
|
||||
}
|
||||
|
||||
fn kernel_main() -> ! {
|
||||
let sp:u32;
|
||||
let bp:u32;
|
||||
unsafe {
|
||||
core::arch::asm!(
|
||||
"mov {sp}, rsp",
|
||||
"mov {bp}, rbp",
|
||||
sp = out(reg) sp,
|
||||
bp = out(reg) bp,
|
||||
options(nostack,preserves_flags))
|
||||
}
|
||||
print!("Running from main!, with {sp:#X} {bp:#X} \r\n");
|
||||
todo!();
|
||||
}
|
||||
|
||||
static GDT_TABLE: [GdtEntry; 3] = [
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
use core::{
|
||||
char::MAX,
|
||||
sync::atomic::{AtomicBool, AtomicU8},
|
||||
};
|
||||
use core::sync::atomic::AtomicU8;
|
||||
|
||||
use x86_drivers::paging::{
|
||||
BanExecution, Cache, CacheWriteThrough, KernelMode, Page, PageAttributeTable, PageDirectory,
|
||||
@@ -40,72 +37,58 @@ pub fn reserve_kernel_pages<const MAX_REGIONS: usize>(
|
||||
app_size: u64,
|
||||
stack_size: usize,
|
||||
allocator: &mut RegionAllocator<MAX_REGIONS>,
|
||||
) -> Result<*const super::Page, super::Error> {
|
||||
) -> Result<(*const u8, *const PageMapLevel4), super::Error> {
|
||||
// TODO: This is going to bite me, need to track the addresses in some in memory abstraction.
|
||||
const M2_PAGE_SIZE: u64 = (2 * 1024 * 1024);
|
||||
|
||||
let page_ptr = (app_ptr as u64 % PAGE_SIZE as u64) as *const [u8; PAGE_SIZE];
|
||||
let pages = app_size as usize / PAGE_SIZE;
|
||||
for page in 0..pages {
|
||||
unsafe {
|
||||
KERNEL_PAGE_TABLE
|
||||
.register(
|
||||
page as usize,
|
||||
Page::new(
|
||||
page_ptr.add(page) as *const _,
|
||||
x86_drivers::paging::Mutable::Yes,
|
||||
// Think this is a good idea, we should keep memory in sync?
|
||||
CacheWriteThrough::On,
|
||||
// Generally we do not
|
||||
Cache::On,
|
||||
PageAttributeTable::On,
|
||||
get_max_addr().into(),
|
||||
BanExecution::No,
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
let page_ptr =
|
||||
(app_ptr as u64 & (!(M2_PAGE_SIZE - 1))) as *const [u8; { M2_PAGE_SIZE as usize }];
|
||||
let page_2m_idx = (page_ptr as u64 / M2_PAGE_SIZE);
|
||||
let app_pages = (app_size / M2_PAGE_SIZE) + 1;
|
||||
|
||||
unsafe {
|
||||
KERNEL_PHYSMAP_PAGE_DIRECTORY
|
||||
.register_page(
|
||||
page_2m_idx as usize,
|
||||
Page::new(
|
||||
page_ptr as *const _,
|
||||
x86_drivers::paging::Mutable::Yes,
|
||||
// Think this is a good idea, we should keep memory in sync?
|
||||
CacheWriteThrough::Off,
|
||||
// Generally we do not
|
||||
Cache::On,
|
||||
PageAttributeTable::Off,
|
||||
get_max_addr().into(),
|
||||
BanExecution::No,
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let stack_pages = stack_size / PAGE_SIZE;
|
||||
|
||||
// TODO: Make some better upper bound here :(
|
||||
let result = allocator.request_pages(&super::RegionRequest::new_with_address_filter(
|
||||
stack_pages,
|
||||
unsafe { page_ptr.add(pages) as u64 },
|
||||
unsafe { page_ptr.add(app_pages as usize + 1) as u64 },
|
||||
u64::MAX / 2,
|
||||
))?;
|
||||
|
||||
for page in 0..stack_pages {
|
||||
let offset_in_table = pages + page;
|
||||
print!("IDX {offset_in_table}");
|
||||
|
||||
unsafe {
|
||||
KERNEL_PAGE_TABLE
|
||||
.register(
|
||||
offset_in_table,
|
||||
Page::new(
|
||||
result.start.add(page) as *const _,
|
||||
x86_drivers::paging::Mutable::Yes,
|
||||
// Not sure if we should have write through on here? a bunch of invalidation
|
||||
CacheWriteThrough::On,
|
||||
Cache::On,
|
||||
PageAttributeTable::On,
|
||||
get_max_addr().into(),
|
||||
BanExecution::Yes,
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
let page_2m_idx = (result.start as u64 / M2_PAGE_SIZE);
|
||||
|
||||
unsafe {
|
||||
KERNEL_PHYSMAP_PAGE_DIRECTORY
|
||||
.register_nested(
|
||||
0,
|
||||
PdEntry::new(
|
||||
core::ptr::addr_of!(KERNEL_PAGE_TABLE).cast(),
|
||||
.register_page(
|
||||
page_2m_idx as usize,
|
||||
Page::new(
|
||||
result.start as *const _,
|
||||
x86_drivers::paging::Mutable::Yes,
|
||||
// Not sure if we should have write through on here? a bunch of invalidation
|
||||
CacheWriteThrough::Off,
|
||||
Cache::On,
|
||||
PageAttributeTable::Off,
|
||||
get_max_addr().into(),
|
||||
BanExecution::Yes,
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
@@ -116,7 +99,7 @@ pub fn reserve_kernel_pages<const MAX_REGIONS: usize>(
|
||||
.register_nested(
|
||||
0,
|
||||
PdptEntry::new(
|
||||
core::ptr::addr_of!(KERNEL_PAGE_TABLE).cast(),
|
||||
core::ptr::addr_of!(KERNEL_PHYSMAP_PAGE_DIRECTORY),
|
||||
CacheWriteThrough::Off,
|
||||
Cache::On,
|
||||
get_max_addr().into(),
|
||||
@@ -127,9 +110,9 @@ pub fn reserve_kernel_pages<const MAX_REGIONS: usize>(
|
||||
|
||||
unsafe {
|
||||
PML4.register(
|
||||
511,
|
||||
Pml4Entry::<KernelMode>::new(
|
||||
core::ptr::addr_of!(KERNEL_PAGE_TABLE).cast(),
|
||||
0,
|
||||
Pml4Entry::new(
|
||||
core::ptr::addr_of!(KERNEL_PHYSMAP_PDPT),
|
||||
CacheWriteThrough::Off,
|
||||
Cache::On,
|
||||
get_max_addr().into(),
|
||||
@@ -137,5 +120,5 @@ pub fn reserve_kernel_pages<const MAX_REGIONS: usize>(
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
Ok(result.start)
|
||||
unsafe { Ok((result.start.cast(), core::ptr::addr_of!(PML4))) }
|
||||
}
|
||||
|
||||
@@ -320,8 +320,8 @@ impl PageMapLevel4 {
|
||||
return Err(RegisterError::IndexOutOfBounds);
|
||||
};
|
||||
match (M::MODE, offset) {
|
||||
(UserOrSupervisor::Supervisor, 256..) => (),
|
||||
(UserOrSupervisor::User, ..256) => (),
|
||||
(UserOrSupervisor::User, 256..) => (),
|
||||
(UserOrSupervisor::Supervisor, ..256) => (),
|
||||
_ => return Err(RegisterError::InvalidIndexForPrivilegeLevel),
|
||||
}
|
||||
*val = page.0;
|
||||
|
||||
Reference in New Issue
Block a user