Skip to content

Commit 6580d1a

Browse files
authored
Merge pull request #1888 from hermit-os/rm-hermit_dtb
fix(aarch64): migrate to fdt crate and remove hermit-dtb
2 parents 8903cd8 + 00b752b commit 6580d1a

File tree

7 files changed

+241
-355
lines changed

7 files changed

+241
-355
lines changed

Cargo.lock

Lines changed: 0 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,6 @@ memory_addresses = { version = "0.2.3", default-features = false, features = [
177177
[target.'cfg(target_arch = "aarch64")'.dependencies]
178178
aarch64 = { version = "0.0.14", default-features = false }
179179
arm-gic = { version = "0.6" }
180-
hermit-dtb = { version = "0.1" }
181180
semihosting = { version = "0.1", optional = true }
182181
memory_addresses = { version = "0.2.3", default-features = false, features = [
183182
"aarch64",

src/arch/aarch64/kernel/interrupts.rs

Lines changed: 81 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
use alloc::collections::{BTreeMap, VecDeque};
2-
use alloc::vec::Vec;
32
use core::arch::asm;
4-
use core::ptr;
53
use core::sync::atomic::{AtomicU64, Ordering};
64

75
use aarch64::regs::*;
86
use ahash::RandomState;
97
use arm_gic::gicv3::{GicV3, InterruptGroup, SgiTarget, SgiTargetGroup};
108
use arm_gic::{IntId, Trigger};
9+
use fdt::standard_nodes::Compatible;
1110
use free_list::PageLayout;
1211
use hashbrown::HashMap;
13-
use hermit_dtb::Dtb;
1412
use hermit_sync::{InterruptSpinMutex, InterruptTicketMutex, OnceCell, SpinMutex};
1513
use memory_addresses::VirtAddr;
1614
use memory_addresses::arch::aarch64::PhysAddr;
@@ -268,35 +266,25 @@ pub fn wakeup_core(core_id: CoreId) {
268266
pub(crate) fn init() {
269267
info!("Initialize generic interrupt controller");
270268

271-
let dtb = unsafe {
272-
Dtb::from_raw(ptr::with_exposed_provenance(
273-
env::boot_info().hardware_info.device_tree.unwrap().get() as usize,
274-
))
275-
.expect(".dtb file has invalid header")
276-
};
269+
let fdt = env::fdt().unwrap();
270+
271+
let intc_node = fdt.find_node("/intc").unwrap();
272+
let mut reg_iter = intc_node.reg().unwrap();
273+
let gicd_reg = reg_iter.next().unwrap();
274+
let gicr_reg = reg_iter.next().unwrap();
275+
let gicd_start = PhysAddr::from(gicd_reg.starting_address.addr());
276+
let gicr_start = PhysAddr::from(gicr_reg.starting_address.addr());
277+
let gicd_size = u64::try_from(gicd_reg.size.unwrap()).unwrap();
278+
let gicr_size = u64::try_from(gicr_reg.size.unwrap()).unwrap();
279+
280+
let num_cpus = fdt.cpus().count();
277281

278-
let reg = dtb.get_property("/intc", "reg").unwrap();
279-
let (slice, residual_slice) = reg.split_at(core::mem::size_of::<u64>());
280-
let gicd_start = PhysAddr::new(u64::from_be_bytes(slice.try_into().unwrap()));
281-
let (slice, residual_slice) = residual_slice.split_at(core::mem::size_of::<u64>());
282-
let gicd_size = u64::from_be_bytes(slice.try_into().unwrap());
283-
let (slice, residual_slice) = residual_slice.split_at(core::mem::size_of::<u64>());
284-
let gicr_start = PhysAddr::new(u64::from_be_bytes(slice.try_into().unwrap()));
285-
let (slice, _residual_slice) = residual_slice.split_at(core::mem::size_of::<u64>());
286-
let gicr_size = u64::from_be_bytes(slice.try_into().unwrap());
287-
288-
let num_cpus = dtb
289-
.enum_subnodes("/cpus")
290-
.filter(|name| name.contains("cpu@"))
291-
.count();
292282
let cpu_id: usize = core_id().try_into().unwrap();
293283

294-
let compatible = core::str::from_utf8(
295-
dtb.get_property("/intc", "compatible")
296-
.unwrap_or(b"unknown"),
297-
)
298-
.unwrap()
299-
.replace('\0', "");
284+
let compatible = intc_node
285+
.compatible()
286+
.map(Compatible::first)
287+
.unwrap_or("unknown");
300288
let is_gic_v4 = if compatible == "arm,gic-v4" {
301289
info!("Found GIC v4 with {num_cpus} cpus");
302290
true
@@ -348,15 +336,71 @@ pub(crate) fn init() {
348336
gic.setup(cpu_id);
349337
GicV3::set_priority_mask(0xff);
350338

351-
for node in dtb.enum_subnodes("/") {
352-
let parts: Vec<_> = node.split('@').collect();
339+
if let Some(timer_node) = fdt.find_compatible(&["arm,armv8-timer", "arm,armv7-timer"]) {
340+
let irq_slice = timer_node.property("interrupts").unwrap().value;
341+
342+
/* Secure Phys IRQ */
343+
let (_irqtype, irq_slice) = irq_slice.split_at(core::mem::size_of::<u32>());
344+
let (_irq, irq_slice) = irq_slice.split_at(core::mem::size_of::<u32>());
345+
let (_irqflags, irq_slice) = irq_slice.split_at(core::mem::size_of::<u32>());
346+
/* Non-secure Phys IRQ */
347+
let (irqtype, irq_slice) = irq_slice.split_at(core::mem::size_of::<u32>());
348+
let (irq, irq_slice) = irq_slice.split_at(core::mem::size_of::<u32>());
349+
let (irqflags, _irq_slice) = irq_slice.split_at(core::mem::size_of::<u32>());
350+
let irqtype = u32::from_be_bytes(irqtype.try_into().unwrap());
351+
let irq = u32::from_be_bytes(irq.try_into().unwrap());
352+
let irqflags = u32::from_be_bytes(irqflags.try_into().unwrap());
353+
unsafe {
354+
TIMER_INTERRUPT = irq;
355+
}
356+
357+
debug!("Timer interrupt: {irq}, type {irqtype}, flags {irqflags}");
353358

354-
if let Some(compatible) = dtb.get_property(parts.first().unwrap(), "compatible")
355-
&& core::str::from_utf8(compatible).unwrap().contains("timer")
356-
{
357-
let irq_slice = dtb
358-
.get_property(parts.first().unwrap(), "interrupts")
359-
.unwrap();
359+
IRQ_NAMES
360+
.lock()
361+
.insert(u8::try_from(irq).unwrap() + PPI_START, "Timer");
362+
363+
// enable timer interrupt
364+
let timer_irqid = if irqtype == 1 {
365+
IntId::ppi(irq)
366+
} else if irqtype == 0 {
367+
IntId::spi(irq)
368+
} else {
369+
panic!("Invalid interrupt type");
370+
};
371+
gic.set_interrupt_priority(timer_irqid, Some(cpu_id), 0x00);
372+
if (irqflags & 0xf) == 4 || (irqflags & 0xf) == 8 {
373+
gic.set_trigger(timer_irqid, Some(cpu_id), Trigger::Level);
374+
} else if (irqflags & 0xf) == 2 || (irqflags & 0xf) == 1 {
375+
gic.set_trigger(timer_irqid, Some(cpu_id), Trigger::Edge);
376+
} else {
377+
panic!("Invalid interrupt level!");
378+
}
379+
gic.enable_interrupt(timer_irqid, Some(cpu_id), true);
380+
}
381+
382+
let reschedid = IntId::sgi(SGI_RESCHED.into());
383+
gic.set_interrupt_priority(reschedid, Some(cpu_id), 0x01);
384+
gic.enable_interrupt(reschedid, Some(cpu_id), true);
385+
IRQ_NAMES.lock().insert(SGI_RESCHED, "Reschedule");
386+
387+
*GIC.lock() = Some(gic);
388+
}
389+
390+
// marks the given CPU core as awake
391+
pub fn init_cpu() {
392+
let cpu_id: usize = core_id().try_into().unwrap();
393+
394+
if let Some(ref mut gic) = *GIC.lock() {
395+
debug!("Mark cpu {cpu_id} as awake");
396+
397+
gic.setup(cpu_id);
398+
GicV3::set_priority_mask(0xff);
399+
400+
let fdt = env::fdt().unwrap();
401+
402+
if let Some(timer_node) = fdt.find_compatible(&["arm,armv8-timer", "arm,armv7-timer"]) {
403+
let irq_slice = timer_node.property("interrupts").unwrap().value;
360404
/* Secure Phys IRQ */
361405
let (_irqtype, irq_slice) = irq_slice.split_at(core::mem::size_of::<u32>());
362406
let (_irq, irq_slice) = irq_slice.split_at(core::mem::size_of::<u32>());
@@ -368,15 +412,6 @@ pub(crate) fn init() {
368412
let irqtype = u32::from_be_bytes(irqtype.try_into().unwrap());
369413
let irq = u32::from_be_bytes(irq.try_into().unwrap());
370414
let irqflags = u32::from_be_bytes(irqflags.try_into().unwrap());
371-
unsafe {
372-
TIMER_INTERRUPT = irq;
373-
}
374-
375-
debug!("Timer interrupt: {irq}, type {irqtype}, flags {irqflags}");
376-
377-
IRQ_NAMES
378-
.lock()
379-
.insert(u8::try_from(irq).unwrap() + PPI_START, "Timer");
380415

381416
// enable timer interrupt
382417
let timer_irqid = if irqtype == 1 {
@@ -396,73 +431,6 @@ pub(crate) fn init() {
396431
}
397432
gic.enable_interrupt(timer_irqid, Some(cpu_id), true);
398433
}
399-
}
400-
401-
let reschedid = IntId::sgi(SGI_RESCHED.into());
402-
gic.set_interrupt_priority(reschedid, Some(cpu_id), 0x01);
403-
gic.enable_interrupt(reschedid, Some(cpu_id), true);
404-
IRQ_NAMES.lock().insert(SGI_RESCHED, "Reschedule");
405-
406-
*GIC.lock() = Some(gic);
407-
}
408-
409-
// marks the given CPU core as awake
410-
pub fn init_cpu() {
411-
let cpu_id: usize = core_id().try_into().unwrap();
412-
413-
if let Some(ref mut gic) = *GIC.lock() {
414-
debug!("Mark cpu {cpu_id} as awake");
415-
416-
gic.setup(cpu_id);
417-
GicV3::set_priority_mask(0xff);
418-
419-
let dtb = unsafe {
420-
Dtb::from_raw(ptr::with_exposed_provenance(
421-
env::boot_info().hardware_info.device_tree.unwrap().get() as usize,
422-
))
423-
.expect(".dtb file has invalid header")
424-
};
425-
426-
for node in dtb.enum_subnodes("/") {
427-
let parts: Vec<_> = node.split('@').collect();
428-
429-
if let Some(compatible) = dtb.get_property(parts.first().unwrap(), "compatible")
430-
&& core::str::from_utf8(compatible).unwrap().contains("timer")
431-
{
432-
let irq_slice = dtb
433-
.get_property(parts.first().unwrap(), "interrupts")
434-
.unwrap();
435-
/* Secure Phys IRQ */
436-
let (_irqtype, irq_slice) = irq_slice.split_at(core::mem::size_of::<u32>());
437-
let (_irq, irq_slice) = irq_slice.split_at(core::mem::size_of::<u32>());
438-
let (_irqflags, irq_slice) = irq_slice.split_at(core::mem::size_of::<u32>());
439-
/* Non-secure Phys IRQ */
440-
let (irqtype, irq_slice) = irq_slice.split_at(core::mem::size_of::<u32>());
441-
let (irq, irq_slice) = irq_slice.split_at(core::mem::size_of::<u32>());
442-
let (irqflags, _irq_slice) = irq_slice.split_at(core::mem::size_of::<u32>());
443-
let irqtype = u32::from_be_bytes(irqtype.try_into().unwrap());
444-
let irq = u32::from_be_bytes(irq.try_into().unwrap());
445-
let irqflags = u32::from_be_bytes(irqflags.try_into().unwrap());
446-
447-
// enable timer interrupt
448-
let timer_irqid = if irqtype == 1 {
449-
IntId::ppi(irq)
450-
} else if irqtype == 0 {
451-
IntId::spi(irq)
452-
} else {
453-
panic!("Invalid interrupt type");
454-
};
455-
gic.set_interrupt_priority(timer_irqid, Some(cpu_id), 0x00);
456-
if (irqflags & 0xf) == 4 || (irqflags & 0xf) == 8 {
457-
gic.set_trigger(timer_irqid, Some(cpu_id), Trigger::Level);
458-
} else if (irqflags & 0xf) == 2 || (irqflags & 0xf) == 1 {
459-
gic.set_trigger(timer_irqid, Some(cpu_id), Trigger::Edge);
460-
} else {
461-
panic!("Invalid interrupt level!");
462-
}
463-
gic.enable_interrupt(timer_irqid, Some(cpu_id), true);
464-
}
465-
}
466434

467435
let reschedid = IntId::sgi(SGI_RESCHED.into());
468436
gic.set_interrupt_priority(reschedid, Some(cpu_id), 0x01);

src/arch/aarch64/kernel/mod.rs

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -67,20 +67,9 @@ pub fn get_limit() -> usize {
6767

6868
#[cfg(feature = "smp")]
6969
pub fn get_possible_cpus() -> u32 {
70-
use hermit_dtb::Dtb;
71-
72-
let dtb = unsafe {
73-
Dtb::from_raw(core::ptr::with_exposed_provenance(
74-
env::boot_info().hardware_info.device_tree.unwrap().get() as usize,
75-
))
76-
.expect(".dtb file has invalid header")
77-
};
78-
79-
dtb.enum_subnodes("/cpus")
80-
.filter(|name| name.contains("cpu@"))
81-
.count()
82-
.try_into()
83-
.unwrap()
70+
let fdt = env::fdt().unwrap();
71+
let cpu_count = fdt.cpus().count();
72+
u32::try_from(cpu_count).unwrap()
8473
}
8574

8675
#[cfg(feature = "smp")]
@@ -148,8 +137,6 @@ pub fn boot_next_processor() {
148137
use core::arch::asm;
149138
use core::hint::spin_loop;
150139

151-
use hermit_dtb::Dtb;
152-
153140
use crate::kernel::start::{TTBR0, smp_start};
154141
use crate::mm::virtual_to_physical;
155142

@@ -161,24 +148,17 @@ pub fn boot_next_processor() {
161148
trace!("Virtual address of smp_start 0x{virt_start:x}");
162149
trace!("Physical address of smp_start 0x{phys_start:x}");
163150

164-
let dtb = unsafe {
165-
Dtb::from_raw(core::ptr::with_exposed_provenance(
166-
env::boot_info().hardware_info.device_tree.unwrap().get() as usize,
167-
))
168-
.expect(".dtb file has invalid header")
169-
};
170-
171-
let cpu_on = u32::from_be_bytes(
172-
dtb.get_property("/psci", "cpu_on")
173-
.unwrap()
174-
.try_into()
175-
.unwrap(),
176-
);
151+
let fdt = env::fdt().unwrap();
152+
let psci_node = fdt.find_node("/psci").unwrap();
153+
154+
let cpu_on = psci_node.property("cpu_on").unwrap().as_usize().unwrap();
155+
let cpu_on = u32::try_from(cpu_on).unwrap();
177156
trace!("CPU_ON: 0x{cpu_on:x}");
178-
let method =
179-
core::str::from_utf8(dtb.get_property("/psci", "method").unwrap_or(b"unknown"))
180-
.unwrap()
181-
.replace('\0', "");
157+
158+
let method = psci_node
159+
.property("method")
160+
.map(|node| node.as_str().unwrap())
161+
.unwrap_or("unknown");
182162

183163
let ttbr0: *mut u8;
184164
unsafe {

0 commit comments

Comments
 (0)