Skip to content

Commit b24c58b

Browse files
committed
Make page initialisation and va->pa code more explicit
Signed-off-by: Graham MacDonald <[email protected]>
1 parent db304bf commit b24c58b

File tree

3 files changed

+25
-22
lines changed

3 files changed

+25
-22
lines changed

aarch64/src/kmem.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -98,16 +98,20 @@ pub const fn physaddr_as_virt(pa: PhysAddr) -> usize {
9898
(pa.addr() as usize).wrapping_add(KZERO)
9999
}
100100

101+
// TODO remove?
101102
pub const fn physaddr_as_ptr_mut<T>(pa: PhysAddr) -> *mut T {
102103
physaddr_as_virt(pa) as *mut T
103104
}
104105

106+
// TODO remove?
105107
pub const fn from_virt_to_physaddr(va: usize) -> PhysAddr {
106108
PhysAddr::new((va - KZERO) as u64)
107109
}
108110

109-
pub fn from_ptr_to_physaddr<T>(a: *const T) -> PhysAddr {
110-
from_virt_to_physaddr(a.addr())
111+
/// Given an address, return the physical address. Makes a massive assumption
112+
/// that the code is mapped offset to KZERO, so should be used with extreme care.
113+
pub fn from_ptr_to_physaddr_offset_from_kzero<T>(a: *const T) -> PhysAddr {
114+
PhysAddr::new((a.addr() - KZERO) as u64)
111115
}
112116

113117
pub fn early_pages_range() -> PhysRange {

aarch64/src/main.rs

+2
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ pub extern "C" fn main9(dtb_va: usize) {
119119
print_physical_memory_info();
120120
print_board_info();
121121

122+
pagealloc::init_page_allocator();
123+
122124
// Map address space accurately using rust VM code to manage page tables
123125
unsafe {
124126
let dtb_range = PhysRange::with_len(from_virt_to_physaddr(dtb_va).addr(), dt.size());

aarch64/src/vm.rs

+17-20
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55
/// 4KiB tables here, although it supports various sizes of pages.
66
use crate::{
77
kmem::{
8-
boottext_range, bss_range, data_range, from_ptr_to_physaddr, physaddr_as_ptr_mut,
9-
rodata_range, text_range,
8+
boottext_range, bss_range, data_range, from_ptr_to_physaddr_offset_from_kzero,
9+
physaddr_as_ptr_mut, rodata_range, text_range,
1010
},
1111
pagealloc,
1212
param::KZERO,
@@ -487,7 +487,7 @@ impl RootPageTable {
487487
// TODO Only do this if self != kernel_root()
488488
let old_recursive_entry = root_page_table(pgtype).entries[511];
489489
let temp_recursive_entry = Entry::rw_kernel_data()
490-
.with_phys_addr(from_ptr_to_physaddr(self))
490+
.with_phys_addr(from_ptr_to_physaddr_offset_from_kzero(self))
491491
.with_page_or_table(true);
492492

493493
unsafe {
@@ -680,25 +680,16 @@ fn print_pte_table(indent: usize, i: usize, pte: Entry, table_va: usize) {
680680
}
681681

682682
pub unsafe fn init_kernel_page_tables(
683-
page_table: &mut RootPageTable,
683+
new_kernel_root_page_table: &mut RootPageTable,
684684
dtb_range: PhysRange,
685685
available_mem: PhysRange,
686686
) {
687-
pagealloc::init_page_allocator();
688-
689687
// We use recursive page tables, but we have to be careful in the init call,
690688
// since the kpage_table is not currently pointed to by ttbr1_el1. Any
691689
// recursive addressing of (511, 511, 511, 511) always points to the
692690
// physical address of the root page table, which isn't what we want here
693691
// because kpage_table hasn't been switched to yet.
694-
695-
// Write the recursive entry
696-
unsafe {
697-
let entry = Entry::rw_kernel_data()
698-
.with_phys_addr(from_ptr_to_physaddr(page_table))
699-
.with_page_or_table(true);
700-
write_volatile(&mut page_table.entries[511], entry);
701-
}
692+
unsafe { init_empty_root_page_table(new_kernel_root_page_table) };
702693

703694
// TODO leave the first page unmapped to catch null pointer dereferences in unsafe code
704695
let custom_map = {
@@ -725,7 +716,7 @@ pub unsafe fn init_kernel_page_tables(
725716

726717
println!("Memory map:");
727718
for (name, range, flags, page_size) in custom_map.iter() {
728-
let mapped_range = page_table
719+
let mapped_range = new_kernel_root_page_table
729720
.map_phys_range(
730721
name,
731722
range,
@@ -748,13 +739,19 @@ pub unsafe fn init_kernel_page_tables(
748739
}
749740
}
750741

751-
pub unsafe fn init_user_page_tables(page_table: &mut RootPageTable) {
752-
// Write the recursive entry
742+
pub unsafe fn init_user_page_tables(new_user_root_page_table: &mut RootPageTable) {
743+
unsafe { init_empty_root_page_table(new_user_root_page_table) };
744+
}
745+
746+
/// Given an empty, statically allocated page table. We need to write a
747+
/// recursive entry in the last entry. To do this, we need to know the physical
748+
/// address, but all we have is the virtual address
749+
unsafe fn init_empty_root_page_table(root_page_table: &mut RootPageTable) {
753750
unsafe {
754751
let entry = Entry::rw_kernel_data()
755-
.with_phys_addr(from_ptr_to_physaddr(page_table))
752+
.with_phys_addr(from_ptr_to_physaddr_offset_from_kzero(root_page_table))
756753
.with_page_or_table(true);
757-
write_volatile(&mut page_table.entries[511], entry);
754+
write_volatile(&mut root_page_table.entries[511], entry);
758755
}
759756
}
760757

@@ -797,7 +794,7 @@ fn ttbr1_el1() -> PhysAddr {
797794
pub unsafe fn switch(page_table: &RootPageTable, pgtype: RootPageTableType) {
798795
#[cfg(not(test))]
799796
unsafe {
800-
let pt_phys = from_ptr_to_physaddr(page_table).addr();
797+
let pt_phys = from_ptr_to_physaddr_offset_from_kzero(page_table).addr();
801798
// https://forum.osdev.org/viewtopic.php?t=36412&p=303237
802799
match pgtype {
803800
RootPageTableType::User => {

0 commit comments

Comments
 (0)