Skip to main content

hermit/arch/x86_64/mm/
mod.rs

1pub(crate) mod paging;
2
3#[cfg(feature = "common-os")]
4use core::slice;
5
6use memory_addresses::arch::x86_64::{PhysAddr, VirtAddr};
7#[cfg(feature = "common-os")]
8use x86_64::structures::paging::{PageSize, Size4KiB as BasePageSize};
9
10#[cfg(feature = "common-os")]
11use crate::arch::mm::paging::{PageTableEntryFlags, PageTableEntryFlagsExt};
12use crate::mm::{FrameAlloc, PageAlloc, PageRangeAllocator};
13
14#[cfg(feature = "common-os")]
15pub fn create_new_root_page_table() -> usize {
16	use free_list::PageLayout;
17	use x86_64::registers::control::Cr3;
18
19	use crate::mm::{FrameAlloc, PageBox, PageRangeAllocator};
20
21	let layout = PageLayout::from_size(BasePageSize::SIZE as usize).unwrap();
22	let frame_range = FrameAlloc::allocate(layout).unwrap();
23	let physaddr = PhysAddr::from(frame_range.start());
24
25	let layout = PageLayout::from_size(2 * BasePageSize::SIZE as usize).unwrap();
26	let page_range = PageBox::new(layout).unwrap();
27	let virtaddr = VirtAddr::from(page_range.start());
28	let mut flags = PageTableEntryFlags::empty();
29	flags.normal().writable();
30
31	let entry: u64 = unsafe {
32		let (frame, _flags) = Cr3::read();
33		paging::map::<BasePageSize>(virtaddr, frame.start_address().into(), 1, flags);
34		let entry: &u64 = &*virtaddr.as_ptr();
35
36		*entry
37	};
38
39	let slice_addr = virtaddr + BasePageSize::SIZE;
40	paging::map::<BasePageSize>(slice_addr, physaddr, 1, flags);
41
42	unsafe {
43		let pml4 = slice::from_raw_parts_mut(slice_addr.as_mut_ptr(), 512);
44
45		// clear PML4
46		for elem in pml4.iter_mut() {
47			*elem = 0;
48		}
49
50		// copy first element and the self reference
51		pml4[0] = entry;
52		// create self reference
53		pml4[511] = physaddr.as_u64() + 0x3; // PG_PRESENT | PG_RW
54	};
55
56	paging::unmap::<BasePageSize>(virtaddr, 2);
57
58	physaddr.as_usize()
59}
60
61pub unsafe fn init() {
62	paging::init();
63	unsafe {
64		FrameAlloc::init();
65	}
66	unsafe {
67		paging::log_page_tables();
68	}
69	unsafe {
70		PageAlloc::init();
71	}
72
73	#[cfg(feature = "common-os")]
74	{
75		use x86_64::registers::control::Cr3;
76
77		let (frame, _flags) = Cr3::read();
78		crate::scheduler::BOOT_ROOT_PAGE_TABLE
79			.set(frame.start_address().as_u64().try_into().unwrap())
80			.unwrap();
81	}
82}