Paging works, can now run main from virtual(ish) memory
This commit is contained in:
@@ -11,7 +11,7 @@ use kernel::{
|
|||||||
},
|
},
|
||||||
print,
|
print,
|
||||||
};
|
};
|
||||||
use x86_drivers::gdt::{DPL, GdtEntry, GdtPointer, GdtSelector};
|
use x86_drivers::{gdt::{DPL, GdtEntry, GdtPointer, GdtSelector}, paging::PageMapLevel4};
|
||||||
pub use x86_drivers::prelude::*;
|
pub use x86_drivers::prelude::*;
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[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));
|
let res = alloc.request_pages(&RegionRequest::new(2));
|
||||||
print!("Region request returned ({res:?})\r\n");
|
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");
|
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)]
|
unsafe fn specify_kernel(sp: *const u8, plm4_phys: *const PageMapLevel4) -> ! {
|
||||||
loop {}
|
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] = [
|
static GDT_TABLE: [GdtEntry; 3] = [
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
use core::{
|
use core::sync::atomic::AtomicU8;
|
||||||
char::MAX,
|
|
||||||
sync::atomic::{AtomicBool, AtomicU8},
|
|
||||||
};
|
|
||||||
|
|
||||||
use x86_drivers::paging::{
|
use x86_drivers::paging::{
|
||||||
BanExecution, Cache, CacheWriteThrough, KernelMode, Page, PageAttributeTable, PageDirectory,
|
BanExecution, Cache, CacheWriteThrough, KernelMode, Page, PageAttributeTable, PageDirectory,
|
||||||
@@ -40,72 +37,58 @@ pub fn reserve_kernel_pages<const MAX_REGIONS: usize>(
|
|||||||
app_size: u64,
|
app_size: u64,
|
||||||
stack_size: usize,
|
stack_size: usize,
|
||||||
allocator: &mut RegionAllocator<MAX_REGIONS>,
|
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.
|
// 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 page_ptr =
|
||||||
let pages = app_size as usize / PAGE_SIZE;
|
(app_ptr as u64 & (!(M2_PAGE_SIZE - 1))) as *const [u8; { M2_PAGE_SIZE as usize }];
|
||||||
for page in 0..pages {
|
let page_2m_idx = (page_ptr as u64 / M2_PAGE_SIZE);
|
||||||
unsafe {
|
let app_pages = (app_size / M2_PAGE_SIZE) + 1;
|
||||||
KERNEL_PAGE_TABLE
|
|
||||||
.register(
|
unsafe {
|
||||||
page as usize,
|
KERNEL_PHYSMAP_PAGE_DIRECTORY
|
||||||
Page::new(
|
.register_page(
|
||||||
page_ptr.add(page) as *const _,
|
page_2m_idx as usize,
|
||||||
x86_drivers::paging::Mutable::Yes,
|
Page::new(
|
||||||
// Think this is a good idea, we should keep memory in sync?
|
page_ptr as *const _,
|
||||||
CacheWriteThrough::On,
|
x86_drivers::paging::Mutable::Yes,
|
||||||
// Generally we do not
|
// Think this is a good idea, we should keep memory in sync?
|
||||||
Cache::On,
|
CacheWriteThrough::Off,
|
||||||
PageAttributeTable::On,
|
// Generally we do not
|
||||||
get_max_addr().into(),
|
Cache::On,
|
||||||
BanExecution::No,
|
PageAttributeTable::Off,
|
||||||
),
|
get_max_addr().into(),
|
||||||
)
|
BanExecution::No,
|
||||||
.unwrap();
|
),
|
||||||
}
|
)
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
let stack_pages = stack_size / PAGE_SIZE;
|
let stack_pages = stack_size / PAGE_SIZE;
|
||||||
|
|
||||||
// TODO: Make some better upper bound here :(
|
// TODO: Make some better upper bound here :(
|
||||||
let result = allocator.request_pages(&super::RegionRequest::new_with_address_filter(
|
let result = allocator.request_pages(&super::RegionRequest::new_with_address_filter(
|
||||||
stack_pages,
|
stack_pages,
|
||||||
unsafe { page_ptr.add(pages) as u64 },
|
unsafe { page_ptr.add(app_pages as usize + 1) as u64 },
|
||||||
u64::MAX / 2,
|
u64::MAX / 2,
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
for page in 0..stack_pages {
|
let page_2m_idx = (result.start as u64 / M2_PAGE_SIZE);
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
KERNEL_PHYSMAP_PAGE_DIRECTORY
|
KERNEL_PHYSMAP_PAGE_DIRECTORY
|
||||||
.register_nested(
|
.register_page(
|
||||||
0,
|
page_2m_idx as usize,
|
||||||
PdEntry::new(
|
Page::new(
|
||||||
core::ptr::addr_of!(KERNEL_PAGE_TABLE).cast(),
|
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,
|
CacheWriteThrough::Off,
|
||||||
Cache::On,
|
Cache::On,
|
||||||
|
PageAttributeTable::Off,
|
||||||
get_max_addr().into(),
|
get_max_addr().into(),
|
||||||
|
BanExecution::Yes,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@@ -116,7 +99,7 @@ pub fn reserve_kernel_pages<const MAX_REGIONS: usize>(
|
|||||||
.register_nested(
|
.register_nested(
|
||||||
0,
|
0,
|
||||||
PdptEntry::new(
|
PdptEntry::new(
|
||||||
core::ptr::addr_of!(KERNEL_PAGE_TABLE).cast(),
|
core::ptr::addr_of!(KERNEL_PHYSMAP_PAGE_DIRECTORY),
|
||||||
CacheWriteThrough::Off,
|
CacheWriteThrough::Off,
|
||||||
Cache::On,
|
Cache::On,
|
||||||
get_max_addr().into(),
|
get_max_addr().into(),
|
||||||
@@ -127,9 +110,9 @@ pub fn reserve_kernel_pages<const MAX_REGIONS: usize>(
|
|||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
PML4.register(
|
PML4.register(
|
||||||
511,
|
0,
|
||||||
Pml4Entry::<KernelMode>::new(
|
Pml4Entry::new(
|
||||||
core::ptr::addr_of!(KERNEL_PAGE_TABLE).cast(),
|
core::ptr::addr_of!(KERNEL_PHYSMAP_PDPT),
|
||||||
CacheWriteThrough::Off,
|
CacheWriteThrough::Off,
|
||||||
Cache::On,
|
Cache::On,
|
||||||
get_max_addr().into(),
|
get_max_addr().into(),
|
||||||
@@ -137,5 +120,5 @@ pub fn reserve_kernel_pages<const MAX_REGIONS: usize>(
|
|||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
Ok(result.start)
|
unsafe { Ok((result.start.cast(), core::ptr::addr_of!(PML4))) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -320,8 +320,8 @@ impl PageMapLevel4 {
|
|||||||
return Err(RegisterError::IndexOutOfBounds);
|
return Err(RegisterError::IndexOutOfBounds);
|
||||||
};
|
};
|
||||||
match (M::MODE, offset) {
|
match (M::MODE, offset) {
|
||||||
(UserOrSupervisor::Supervisor, 256..) => (),
|
(UserOrSupervisor::User, 256..) => (),
|
||||||
(UserOrSupervisor::User, ..256) => (),
|
(UserOrSupervisor::Supervisor, ..256) => (),
|
||||||
_ => return Err(RegisterError::InvalidIndexForPrivilegeLevel),
|
_ => return Err(RegisterError::InvalidIndexForPrivilegeLevel),
|
||||||
}
|
}
|
||||||
*val = page.0;
|
*val = page.0;
|
||||||
|
|||||||
Reference in New Issue
Block a user