Skip to content

Commit 00b752b

Browse files
committed
fix(aarch64): migrate to fdt crate and remove hermit-dtb
1 parent 65e25be commit 00b752b

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
@@ -174,7 +174,6 @@ memory_addresses = { version = "0.2.3", default-features = false, features = [
174174
[target.'cfg(target_arch = "aarch64")'.dependencies]
175175
aarch64 = { version = "0.0.14", default-features = false }
176176
arm-gic = { version = "0.6" }
177-
hermit-dtb = { version = "0.1" }
178177
semihosting = { version = "0.1", optional = true }
179178
memory_addresses = { version = "0.2.3", default-features = false, features = [
180179
"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
@@ -66,20 +66,9 @@ pub fn get_limit() -> usize {
6666

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

8574
#[cfg(feature = "smp")]
@@ -147,8 +136,6 @@ pub fn boot_next_processor() {
147136
use core::arch::asm;
148137
use core::hint::spin_loop;
149138

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

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

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

182162
let ttbr0: *mut u8;
183163
unsafe {

0 commit comments

Comments
 (0)