diff --git a/src/arch/aarch64/device/irqchip/gic.rs b/src/arch/aarch64/device/irqchip/gic.rs index d5aef88c95..d79ed945a2 100644 --- a/src/arch/aarch64/device/irqchip/gic.rs +++ b/src/arch/aarch64/device/irqchip/gic.rs @@ -1,8 +1,8 @@ use super::InterruptController; use crate::{ dtb::{ - get_mmio_address, irqchip::{InterruptHandler, IrqCell, IrqDesc}, + translate_mmio_address, }, sync::CleanLockToken, }; @@ -60,7 +60,7 @@ impl GenericInterruptController { if chunk.size.is_none() { break; } - let addr = get_mmio_address(fdt, node, &chunk).unwrap(); + let addr = translate_mmio_address(fdt, node, &chunk).unwrap(); match idx { 0 => (regs.0, regs.1) = (addr, chunk.size.unwrap()), 2 => (regs.2, regs.3) = (addr, chunk.size.unwrap()), diff --git a/src/arch/aarch64/device/irqchip/gicv3.rs b/src/arch/aarch64/device/irqchip/gicv3.rs index 9d8a0d5211..77d42a35df 100644 --- a/src/arch/aarch64/device/irqchip/gicv3.rs +++ b/src/arch/aarch64/device/irqchip/gicv3.rs @@ -5,8 +5,8 @@ use fdt::{node::NodeProperty, Fdt}; use super::{gic::GicDistIf, InterruptController}; use crate::{ dtb::{ - get_mmio_address, irqchip::{InterruptHandler, IrqCell, IrqDesc}, + translate_mmio_address, }, sync::CleanLockToken, }; @@ -53,7 +53,7 @@ impl GicV3 { // Read registers let mut chunks = node.reg().unwrap(); if let Some(gicd) = chunks.next() - && let Some(addr) = get_mmio_address(fdt, &node, &gicd) + && let Some(addr) = translate_mmio_address(fdt, &node, &gicd) { unsafe { self.gic_dist_if.init(crate::PHYS_OFFSET + addr); @@ -62,7 +62,7 @@ impl GicV3 { for _ in 0..gicrs { if let Some(gicr) = chunks.next() { self.gicrs.push(( - get_mmio_address(fdt, &node, &gicr).unwrap(), + translate_mmio_address(fdt, &node, &gicr).unwrap(), gicr.size.unwrap(), )); } diff --git a/src/dtb/mod.rs b/src/dtb/mod.rs index 22b2aa797e..26a3b292da 100644 --- a/src/dtb/mod.rs +++ b/src/dtb/mod.rs @@ -102,48 +102,87 @@ pub fn register_dev_memory_ranges(dt: &Fdt) { } } - let Some(soc_node) = dt.find_node("/soc") else { - warn!("failed to find /soc in devicetree"); - return; - }; - let Some(reg) = soc_node.ranges() else { - warn!("devicetree /soc has no ranges"); - return; - }; - for chunk in reg { - debug!( - "dev mem 0x{:08x} 0x{:08x} 0x{:08x} 0x{:08x}", - chunk.child_bus_address_hi, - chunk.child_bus_address, - chunk.parent_bus_address, - chunk.size - ); + if let Some(soc_node) = dt.find_node("/soc") { + if let Some(reg) = soc_node.ranges() { + for chunk in reg { + debug!( + "dev mem 0x{:08x} 0x{:08x} 0x{:08x} 0x{:08x}", + chunk.child_bus_address_hi, + chunk.child_bus_address, + chunk.parent_bus_address, + chunk.size + ); - /*TODO: soc memory may contain all free memory! - register_memory_region( - chunk.parent_bus_address, - chunk.size, - BootloaderMemoryKind::Device, - );*/ - } + /*TODO: soc memory may contain all free memory! + register_memory_region( + chunk.parent_bus_address, + chunk.size, + BootloaderMemoryKind::Device, + );*/ + } + } else { + warn!("devicetree /soc has no ranges"); + } - // also add all soc-internal devices because they might not be shown in ranges - // (identity-mapped soc bus may have empty ranges) - for device in soc_node.children() { - if let Some(reg) = device.reg() { - for entry in reg { - if let Some(size) = entry.size { - let addr = entry.starting_address as usize; - if let Some(mapped_addr) = get_mmio_address(dt, &device, &entry) { - debug!( - "soc device {} 0x{:08x} -> 0x{:08x} size 0x{:08x}", - device.name, addr, mapped_addr, size - ); - register_memory_region(mapped_addr, size, BootloaderMemoryKind::Device); + // also add direct /soc children because they might not be shown in + // ranges (an identity-mapped bus may have empty ranges) + for device in soc_node.children() { + if let Some(reg) = device.reg() { + for entry in reg { + if let Some(size) = entry.size { + let addr = entry.starting_address as usize; + if let Some(mapped_addr) = get_mmio_address(dt, &device, &entry) { + debug!( + "soc device {} 0x{:08x} -> 0x{:08x} size 0x{:08x}", + device.name, addr, mapped_addr, size + ); + register_memory_region(mapped_addr, size, BootloaderMemoryKind::Device); + } } } } } + } else { + warn!("failed to find /soc in devicetree"); + } + + // The selected console may be below a nested bus whose own `reg` range + // does not cover all children. Register the exact translated range so it + // remains mapped after the boot-time identity map is replaced. + if let Some((address, size, _, _, _)) = diag_uart_range(dt) { + debug!( + "diagnostic UART 0x{:08x} size 0x{:08x}", + address.data(), + size + ); + register_memory_region(address.data(), size, BootloaderMemoryKind::Device); + } + + // Interrupt controllers are not required to live below /soc. Some + // devicetrees place the primary GIC directly below the root node, so its + // register ranges would otherwise be absent from the kernel physmap. + if let Some(root) = dt.find_node("/") { + for controller in root + .children() + .filter(|node| node.property("interrupt-controller").is_some()) + { + let Some(regions) = controller.reg() else { + continue; + }; + for region in regions { + let Some(size) = region.size else { + continue; + }; + let Some(address) = translate_mmio_address(dt, &controller, ®ion) else { + continue; + }; + debug!( + "root interrupt controller {} 0x{:08x} size 0x{:08x}", + controller.name, address, size + ); + register_memory_region(address, size, BootloaderMemoryKind::Device); + } + } } }