Skip to content

Commit f063f3b

Browse files
gmacddancrossnyc
authored andcommitted
Use dt to get physical memory, fix some FDT code
Signed-off-by: Graham MacDonald <[email protected]>
1 parent 3ddc887 commit f063f3b

File tree

6 files changed

+68
-29
lines changed

6 files changed

+68
-29
lines changed

aarch64/src/mailbox.rs

+2
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ pub struct MemoryInfo {
194194
pub end: u32,
195195
}
196196

197+
#[allow(dead_code)]
197198
pub fn get_arm_memory() -> PhysRange {
198199
let tags = Tag::<EmptyRequest> {
199200
tag_id0: TagId::GetArmMemory,
@@ -210,6 +211,7 @@ pub fn get_arm_memory() -> PhysRange {
210211
PhysRange::new(PhysAddr::new(start as u64), PhysAddr::new(end as u64))
211212
}
212213

214+
#[allow(dead_code)]
213215
pub fn get_vc_memory() -> PhysRange {
214216
let tags = Tag::<EmptyRequest> {
215217
tag_id0: TagId::GetVcMemory,

aarch64/src/main.rs

+1-14
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,6 @@ fn print_binary_sections() {
5757
}
5858
}
5959

60-
fn print_physical_memory_info() {
61-
println!("Physical memory map:");
62-
let arm_mem = mailbox::get_arm_memory();
63-
println!(" Memory:\t{arm_mem} ({:#x})", arm_mem.size());
64-
let vc_mem = mailbox::get_vc_memory();
65-
println!(" Video:\t{vc_mem} ({:#x})", vc_mem.size());
66-
}
67-
6860
fn print_memory_info() {
6961
println!("Memory usage:");
7062
let (used, total) = pagealloc::usage_bytes();
@@ -118,19 +110,14 @@ pub extern "C" fn main9(dtb_va: usize) {
118110
println!("midr_el1: {:?}", registers::MidrEl1::read());
119111

120112
print_binary_sections();
121-
print_physical_memory_info();
122113
print_board_info();
123114

124115
pagealloc::init_page_allocator();
125116

126117
// Map address space accurately using rust VM code to manage page tables
127118
unsafe {
128119
let dtb_range = PhysRange::with_len(from_virt_to_physaddr(dtb_va).addr(), dt.size());
129-
vm::init_kernel_page_tables(
130-
&mut *ptr::addr_of_mut!(KERNEL_PAGETABLE),
131-
dtb_range,
132-
mailbox::get_arm_memory(),
133-
);
120+
vm::init_kernel_page_tables(&dt, &mut *ptr::addr_of_mut!(KERNEL_PAGETABLE), dtb_range);
134121
vm::switch(&*ptr::addr_of!(KERNEL_PAGETABLE), RootPageTableType::Kernel);
135122

136123
vm::init_user_page_tables(&mut *ptr::addr_of_mut!(USER_PAGETABLE));

aarch64/src/vm.rs

+13-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use core::fmt;
1717
use core::ptr::write_volatile;
1818
use num_enum::{FromPrimitive, IntoPrimitive};
1919
use port::{
20+
fdt::DeviceTree,
2021
mem::{PAGE_SIZE_1G, PAGE_SIZE_2M, PAGE_SIZE_4K, PhysAddr, PhysRange},
2122
pagealloc::PageAllocError,
2223
};
@@ -509,9 +510,9 @@ pub fn root_page_table(pgtype: RootPageTableType) -> &'static mut RootPageTable
509510
}
510511

511512
pub unsafe fn init_kernel_page_tables(
513+
dt: &DeviceTree,
512514
new_kernel_root_page_table: &mut RootPageTable,
513515
dtb_range: PhysRange,
514-
available_mem: PhysRange,
515516
) {
516517
// We use recursive page tables, but we have to be careful in the init call,
517518
// since the kpage_table is not currently pointed to by ttbr1_el1. Any
@@ -520,6 +521,17 @@ pub unsafe fn init_kernel_page_tables(
520521
// because kpage_table hasn't been switched to yet.
521522
unsafe { init_empty_root_page_table(new_kernel_root_page_table) };
522523

524+
// We only use the first memory range for now.
525+
// TODO Handle multiple memory ranges
526+
let available_mem = dt
527+
.find_device_type("memory")
528+
.flat_map(|memory| dt.property_translated_reg_iter(memory).flat_map(|r| r.regblock()))
529+
.map(|memory| PhysRange::from(&memory))
530+
.next()
531+
.expect("No memory range found in device tree");
532+
println!("Physical Memory:");
533+
println!(" {}", &available_mem);
534+
523535
// TODO leave the first page unmapped to catch null pointer dereferences in unsafe code
524536
let custom_map = {
525537
// The DTB range might not end on a page boundary, so round up.

port/src/fdt.rs

+17-3
Original file line numberDiff line numberDiff line change
@@ -104,15 +104,19 @@ impl<'a> DeviceTree<'a> {
104104
self.node_from_index(0, 0)
105105
}
106106

107-
pub fn children(&self, parent: &Node) -> impl Iterator<Item = Node> + '_ {
107+
pub fn children<'b>(&'b self, parent: &'b Node) -> impl Iterator<Item = Node> + 'b {
108108
// Start searching linearly after node.start (which points to the start of the parent)
109109
let mut i = parent.next_token_start;
110110
let child_depth = parent.depth + 1;
111111

112112
core::iter::from_fn(move || {
113113
let child = self.node_from_index(i, child_depth)?;
114-
i = child.start + child.total_len;
115-
Some(child)
114+
if parent.encloses(&child) {
115+
i = child.start + child.total_len;
116+
Some(child)
117+
} else {
118+
None
119+
}
116120
})
117121
}
118122

@@ -394,6 +398,16 @@ impl<'a> DeviceTree<'a> {
394398
})
395399
}
396400

401+
/// Return iterator of nodes matching the device_type string 'device_type'
402+
pub fn find_device_type(&'a self, device_type: &'a str) -> impl Iterator<Item = Node> + 'a {
403+
self.nodes().filter(|n| {
404+
if let Some(prop) = self.property(n, "device_type") {
405+
return self.property_value_contains(&prop, device_type);
406+
}
407+
false
408+
})
409+
}
410+
397411
fn inline_str(bytes: &[mem::MaybeUninit<u8>], start: usize) -> Option<&str> {
398412
let maybe_uninit_bytes = bytes.get(start..)?;
399413
let init_bytes = unsafe { maybe_uninit_bytes.assume_init_ref() };

port/src/mem.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ impl From<&RegBlock> for VirtRange {
3939
}
4040
}
4141

42+
impl fmt::Display for VirtRange {
43+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44+
write!(f, "{:#018x}..{:#018x}", self.0.start, self.0.end)
45+
}
46+
}
47+
4248
#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord)]
4349
#[repr(transparent)]
4450
pub struct PhysAddr(pub u64);
@@ -154,7 +160,7 @@ impl PhysRange {
154160

155161
impl fmt::Display for PhysRange {
156162
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157-
write!(f, "{:#016x}..{:#016x}", self.0.start.addr(), self.0.end.addr())
163+
write!(f, "{:#018x}..{:#018x}", self.0.start.addr(), self.0.end.addr())
158164
}
159165
}
160166

port/tests/fdt_test.rs

+28-10
Original file line numberDiff line numberDiff line change
@@ -75,18 +75,14 @@ fn find_compatible() {
7575
);
7676

7777
// Doesn't find substrings
78-
assert!(dt
79-
.find_compatible("arm")
80-
.flat_map(|n| dt.node_name(&n))
81-
.collect::<Vec<&str>>()
82-
.is_empty());
78+
assert!(
79+
dt.find_compatible("arm").flat_map(|n| dt.node_name(&n)).collect::<Vec<&str>>().is_empty()
80+
);
8381

8482
// No match
85-
assert!(dt
86-
.find_compatible("xxxx")
87-
.flat_map(|n| dt.node_name(&n))
88-
.collect::<Vec<&str>>()
89-
.is_empty());
83+
assert!(
84+
dt.find_compatible("xxxx").flat_map(|n| dt.node_name(&n)).collect::<Vec<&str>>().is_empty()
85+
);
9086
}
9187

9288
#[test]
@@ -114,6 +110,28 @@ fn get_cells() {
114110
);
115111
}
116112

113+
#[test]
114+
fn iterate_over_children() {
115+
let dt = DeviceTree::new(TEST1_DTB).unwrap();
116+
117+
let children = dt
118+
.find_by_path("/thermal-zones")
119+
.iter()
120+
.flat_map(|resmem| dt.children(resmem))
121+
.flat_map(|n| dt.node_name(&n))
122+
.collect::<Vec<&str>>();
123+
124+
assert_eq!(children, vec!["cpu-thermal"]);
125+
}
126+
127+
#[test]
128+
fn iterate_over_device_types() {
129+
let dt = DeviceTree::new(TEST1_DTB).unwrap();
130+
131+
let cpus = dt.find_device_type("cpu").flat_map(|n| dt.node_name(&n)).collect::<Vec<&str>>();
132+
assert_eq!(cpus, vec!["cpu@0", "cpu@1", "cpu@2", "cpu@3"]);
133+
}
134+
117135
#[test]
118136
fn get_reg() {
119137
let dt = DeviceTree::new(TEST1_DTB).unwrap();

0 commit comments

Comments
 (0)