2023-07-18 18:03:45 +03:00
|
|
|
//! AArch64 architecture and platforms implementation
|
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
pub mod mem;
|
|
|
|
|
2023-07-18 18:03:45 +03:00
|
|
|
use core::sync::atomic::Ordering;
|
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
use aarch64_cpu::registers::{CNTP_CTL_EL0, CNTP_TVAL_EL0, DAIF};
|
2023-07-18 18:03:45 +03:00
|
|
|
use abi::error::Error;
|
2023-08-13 21:23:58 +03:00
|
|
|
use device_api::{
|
2024-02-03 20:44:04 +02:00
|
|
|
interrupt::{
|
|
|
|
ExternalInterruptController, IpiDeliveryTarget, LocalInterruptController,
|
|
|
|
MessageInterruptController,
|
|
|
|
},
|
2023-08-13 21:23:58 +03:00
|
|
|
timer::MonotonicTimestampProviderDevice,
|
2023-08-18 22:53:58 +03:00
|
|
|
ResetDevice,
|
2023-08-13 21:23:58 +03:00
|
|
|
};
|
2024-02-04 15:18:34 +02:00
|
|
|
use device_tree::dt::{DevTreeIndexPropExt, DevTreeNodeInfo, DeviceTree, FdtMemoryRegionIter};
|
2023-08-13 21:23:58 +03:00
|
|
|
use git_version::git_version;
|
2024-02-04 21:13:40 +02:00
|
|
|
use libk::{
|
2024-01-04 23:04:34 +02:00
|
|
|
mem::{
|
|
|
|
address::{FromRaw, IntoRaw, PhysicalAddress},
|
2024-02-03 20:44:04 +02:00
|
|
|
device::{DeviceMemoryAttributes, RawDeviceMemoryMapping},
|
2024-02-04 15:18:34 +02:00
|
|
|
phys::PhysicalMemoryRegion,
|
2024-01-04 23:04:34 +02:00
|
|
|
pointer::PhysicalRef,
|
|
|
|
table::{EntryLevel, EntryLevelExt},
|
|
|
|
},
|
|
|
|
util::OneTimeInit,
|
|
|
|
};
|
2023-07-18 18:03:45 +03:00
|
|
|
use tock_registers::interfaces::{ReadWriteable, Readable, Writeable};
|
2024-02-03 20:44:04 +02:00
|
|
|
use ygg_driver_pci::PciBusManager;
|
2023-07-18 18:03:45 +03:00
|
|
|
|
|
|
|
use crate::{
|
2023-11-16 00:16:38 +02:00
|
|
|
arch::aarch64::{
|
|
|
|
cpu::Cpu,
|
|
|
|
mem::table::{L2, L3},
|
|
|
|
},
|
2023-08-21 17:26:44 +03:00
|
|
|
debug,
|
2024-02-04 15:18:34 +02:00
|
|
|
device::{self, power::arm_psci::Psci},
|
2023-12-05 10:27:56 +02:00
|
|
|
fs::{Initrd, INITRD_DATA},
|
2023-07-18 18:03:45 +03:00
|
|
|
mem::{
|
2023-11-16 00:16:38 +02:00
|
|
|
heap,
|
2024-02-04 15:18:34 +02:00
|
|
|
phys::{self, reserved::reserve_region},
|
2023-07-18 18:03:45 +03:00
|
|
|
},
|
|
|
|
};
|
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
use self::mem::{table::L1, EarlyMapping};
|
2023-07-18 18:03:45 +03:00
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
use super::{Architecture, CpuMessage};
|
2023-07-18 18:03:45 +03:00
|
|
|
|
|
|
|
pub mod boot;
|
|
|
|
pub mod context;
|
|
|
|
pub mod cpu;
|
|
|
|
pub mod exception;
|
|
|
|
pub mod gic;
|
|
|
|
pub mod smp;
|
|
|
|
pub mod timer;
|
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
const BOOT_STACK_SIZE: usize = 4096 * 32;
|
2023-07-18 18:03:45 +03:00
|
|
|
|
|
|
|
#[derive(Clone, Copy)]
|
|
|
|
#[repr(C, align(0x20))]
|
2023-11-16 00:16:38 +02:00
|
|
|
struct BootStack {
|
2023-07-18 18:03:45 +03:00
|
|
|
data: [u8; BOOT_STACK_SIZE],
|
|
|
|
}
|
|
|
|
|
2023-12-07 12:50:54 +02:00
|
|
|
/// AArch64 architecture implementation
|
2023-07-18 18:03:45 +03:00
|
|
|
pub struct AArch64 {
|
|
|
|
dt: OneTimeInit<DeviceTree<'static>>,
|
2023-08-13 21:23:58 +03:00
|
|
|
|
2023-12-07 12:50:54 +02:00
|
|
|
/// Optional instance of PSCI on this platform
|
2023-08-13 21:23:58 +03:00
|
|
|
pub psci: OneTimeInit<&'static Psci>,
|
2023-11-16 00:16:38 +02:00
|
|
|
reset: OneTimeInit<&'static dyn ResetDevice>,
|
2023-07-18 18:03:45 +03:00
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
lintc: OneTimeInit<&'static dyn LocalInterruptController<IpiMessage = CpuMessage>>,
|
|
|
|
xintc: OneTimeInit<&'static dyn ExternalInterruptController<IrqNumber = IrqNumber>>,
|
2024-02-03 20:44:04 +02:00
|
|
|
msi_intc: OneTimeInit<&'static dyn MessageInterruptController>,
|
2023-08-13 21:23:58 +03:00
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
mtimer: OneTimeInit<&'static dyn MonotonicTimestampProviderDevice>,
|
2023-07-18 18:03:45 +03:00
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
initrd: OneTimeInit<PhysicalRef<'static, [u8]>>,
|
|
|
|
}
|
2023-08-21 17:26:44 +03:00
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
impl Architecture for AArch64 {
|
2023-07-18 18:03:45 +03:00
|
|
|
const KERNEL_VIRT_OFFSET: usize = 0xFFFFFF8000000000;
|
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
type IrqNumber = IrqNumber;
|
2023-07-18 18:03:45 +03:00
|
|
|
|
2024-01-04 23:04:34 +02:00
|
|
|
type L3 = L3;
|
|
|
|
|
2023-08-18 22:53:58 +03:00
|
|
|
unsafe fn start_application_processors(&self) {
|
|
|
|
let dt = self.dt.get();
|
2023-11-16 00:16:38 +02:00
|
|
|
if let Err(error) = smp::start_ap_cores(dt) {
|
|
|
|
errorln!("Could not initialize AP CPUs: {:?}", error);
|
2023-08-18 22:53:58 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
fn cpu_count() -> usize {
|
|
|
|
smp::CPU_COUNT.load(Ordering::Acquire)
|
2023-07-18 18:03:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
unsafe fn set_interrupt_mask(mask: bool) {
|
|
|
|
if mask {
|
|
|
|
DAIF.modify(DAIF::I::SET);
|
|
|
|
} else {
|
|
|
|
DAIF.modify(DAIF::I::CLEAR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn interrupt_mask() -> bool {
|
|
|
|
DAIF.read(DAIF::I) != 0
|
|
|
|
}
|
2023-08-07 10:28:04 +03:00
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
fn wait_for_interrupt() {
|
|
|
|
aarch64_cpu::asm::wfi();
|
2023-08-07 10:28:04 +03:00
|
|
|
}
|
2023-08-13 21:23:58 +03:00
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
unsafe fn map_device_memory(
|
2023-08-13 21:23:58 +03:00
|
|
|
&self,
|
2023-11-16 00:16:38 +02:00
|
|
|
base: PhysicalAddress,
|
|
|
|
size: usize,
|
2024-02-03 20:44:04 +02:00
|
|
|
attrs: DeviceMemoryAttributes,
|
2023-11-16 00:16:38 +02:00
|
|
|
) -> Result<RawDeviceMemoryMapping, Error> {
|
2024-02-03 20:44:04 +02:00
|
|
|
mem::map_device_memory(base, size, attrs)
|
2023-08-13 21:23:58 +03:00
|
|
|
}
|
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
unsafe fn unmap_device_memory(&self, map: &RawDeviceMemoryMapping) {
|
|
|
|
mem::unmap_device_memory(map)
|
2023-08-13 21:23:58 +03:00
|
|
|
}
|
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
fn map_physical_memory<I: Iterator<Item = PhysicalMemoryRegion> + Clone>(
|
2023-08-13 21:23:58 +03:00
|
|
|
&self,
|
2023-11-16 00:16:38 +02:00
|
|
|
_it: I,
|
|
|
|
_memory_start: PhysicalAddress,
|
|
|
|
memory_end: PhysicalAddress,
|
2023-08-13 21:23:58 +03:00
|
|
|
) -> Result<(), Error> {
|
2024-01-04 23:04:34 +02:00
|
|
|
let end_l1i = memory_end.page_align_up::<L1>().page_index::<L1>();
|
2023-11-16 00:16:38 +02:00
|
|
|
if end_l1i > mem::RAM_MAPPING_L1_COUNT {
|
2023-11-16 11:11:10 +02:00
|
|
|
todo!()
|
2023-11-16 00:16:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Map 1GiB chunks
|
|
|
|
for index in 0..end_l1i {
|
|
|
|
unsafe {
|
|
|
|
mem::map_ram_l1(index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mem::MEMORY_LIMIT.init(memory_end.into_raw());
|
|
|
|
|
2023-08-13 21:23:58 +03:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2024-01-04 23:04:34 +02:00
|
|
|
fn virtualize(address: u64) -> usize {
|
|
|
|
let address = address as usize;
|
|
|
|
if address < *mem::MEMORY_LIMIT.get() {
|
|
|
|
address + mem::RAM_MAPPING_OFFSET
|
2023-11-16 00:16:38 +02:00
|
|
|
} else {
|
2024-01-04 23:04:34 +02:00
|
|
|
panic!("Invalid physical address: {:#x}", address);
|
2023-11-16 00:16:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-04 23:04:34 +02:00
|
|
|
fn physicalize(address: usize) -> u64 {
|
2023-11-16 00:16:38 +02:00
|
|
|
if address < mem::RAM_MAPPING_OFFSET
|
|
|
|
|| address - mem::RAM_MAPPING_OFFSET >= *mem::MEMORY_LIMIT.get()
|
|
|
|
{
|
2024-01-04 23:04:34 +02:00
|
|
|
panic!("Not a virtualized physical address: {:#x}", address);
|
2023-11-16 00:16:38 +02:00
|
|
|
}
|
|
|
|
|
2024-01-04 23:04:34 +02:00
|
|
|
(address - mem::RAM_MAPPING_OFFSET) as _
|
2023-11-16 00:16:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fn local_interrupt_controller(
|
|
|
|
&'static self,
|
|
|
|
) -> &'static dyn LocalInterruptController<IpiMessage = super::CpuMessage> {
|
|
|
|
*self.lintc.get()
|
2023-08-15 18:38:54 +03:00
|
|
|
}
|
|
|
|
|
2023-08-21 17:26:44 +03:00
|
|
|
fn external_interrupt_controller(
|
2023-11-16 00:16:38 +02:00
|
|
|
&'static self,
|
2023-08-21 17:26:44 +03:00
|
|
|
) -> &'static dyn ExternalInterruptController<IrqNumber = Self::IrqNumber> {
|
2023-11-16 00:16:38 +02:00
|
|
|
*self.xintc.get()
|
2023-08-13 21:23:58 +03:00
|
|
|
}
|
|
|
|
|
2024-02-03 20:44:04 +02:00
|
|
|
fn message_interrupt_controller(&'static self) -> &'static dyn MessageInterruptController {
|
|
|
|
*self.msi_intc.get()
|
|
|
|
}
|
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
fn register_local_interrupt_controller(
|
2023-08-13 21:23:58 +03:00
|
|
|
&self,
|
2023-11-16 00:16:38 +02:00
|
|
|
intc: &'static dyn LocalInterruptController<IpiMessage = super::CpuMessage>,
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
self.lintc.init(intc);
|
|
|
|
Ok(())
|
2023-08-13 21:23:58 +03:00
|
|
|
}
|
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
fn register_external_interrupt_controller(
|
|
|
|
&self,
|
|
|
|
intc: &'static dyn ExternalInterruptController<IrqNumber = Self::IrqNumber>,
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
self.xintc.init(intc);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2024-02-03 20:44:04 +02:00
|
|
|
fn register_message_interrupt_controller(
|
|
|
|
&self,
|
|
|
|
intc: &'static dyn MessageInterruptController,
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
self.msi_intc.init(intc);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
fn monotonic_timer(&'static self) -> &'static dyn MonotonicTimestampProviderDevice {
|
2023-08-13 21:23:58 +03:00
|
|
|
*self.mtimer.get()
|
|
|
|
}
|
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
fn register_monotonic_timer(
|
|
|
|
&self,
|
|
|
|
timer: &'static dyn MonotonicTimestampProviderDevice,
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
self.mtimer.init(timer);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-08-13 21:23:58 +03:00
|
|
|
unsafe fn send_ipi(&self, target: IpiDeliveryTarget, msg: CpuMessage) -> Result<(), Error> {
|
2023-11-16 00:16:38 +02:00
|
|
|
if let Some(local_intc) = self.lintc.try_get() {
|
2023-08-13 21:23:58 +03:00
|
|
|
local_intc.send_ipi(target, msg)
|
|
|
|
} else {
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
fn register_reset_device(&self, reset: &'static dyn ResetDevice) -> Result<(), Error> {
|
|
|
|
self.reset.init(reset);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-08-13 21:23:58 +03:00
|
|
|
unsafe fn reset(&self) -> ! {
|
2023-08-18 09:58:56 +03:00
|
|
|
if let Some(reset) = self.reset.try_get() {
|
2023-11-16 00:16:38 +02:00
|
|
|
reset.reset()
|
2023-08-18 09:58:56 +03:00
|
|
|
} else {
|
|
|
|
let psci = self.psci.get();
|
2023-11-16 00:16:38 +02:00
|
|
|
psci.reset()
|
2023-08-18 09:58:56 +03:00
|
|
|
}
|
2023-08-13 21:23:58 +03:00
|
|
|
}
|
2023-07-18 18:03:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
impl AArch64 {
|
2023-11-16 00:16:38 +02:00
|
|
|
fn extract_initrd_from_dt(
|
|
|
|
&self,
|
|
|
|
dt: &DeviceTree,
|
|
|
|
) -> Option<(PhysicalAddress, PhysicalAddress)> {
|
|
|
|
let chosen = dt.node_by_path("/chosen")?;
|
2024-02-04 15:18:34 +02:00
|
|
|
let initrd_start = device_tree::find_prop(&chosen, "linux,initrd-start")?;
|
|
|
|
let initrd_end = device_tree::find_prop(&chosen, "linux,initrd-end")?;
|
2023-11-16 00:16:38 +02:00
|
|
|
|
|
|
|
let address_cells = dt.address_cells();
|
2023-07-18 18:03:45 +03:00
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
let initrd_start = initrd_start.cell1_array_item(0, address_cells)?;
|
|
|
|
let initrd_end = initrd_end.cell1_array_item(0, address_cells)?;
|
|
|
|
|
|
|
|
let initrd_start = PhysicalAddress::from_raw(initrd_start);
|
|
|
|
let initrd_end = PhysicalAddress::from_raw(initrd_end);
|
|
|
|
|
|
|
|
Some((initrd_start, initrd_end))
|
2023-07-18 18:03:45 +03:00
|
|
|
}
|
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
unsafe fn init_memory_management(&'static self, dtb: PhysicalAddress) -> Result<(), Error> {
|
|
|
|
// 16x2MiB
|
|
|
|
const HEAP_PAGES: usize = 16;
|
|
|
|
|
|
|
|
// Initialize the runtime mappings
|
|
|
|
mem::init_fixed_tables();
|
|
|
|
|
|
|
|
// Extract the size of the device tree
|
|
|
|
let dtb_size = {
|
2024-02-04 15:18:34 +02:00
|
|
|
let dtb_header = EarlyMapping::<u8>::map_slice(dtb, DeviceTree::MIN_HEADER_SIZE)?;
|
|
|
|
DeviceTree::read_totalsize(dtb_header.as_ref()).unwrap()
|
2023-11-16 00:16:38 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
reserve_region(
|
|
|
|
"dtb",
|
|
|
|
PhysicalMemoryRegion {
|
|
|
|
base: dtb,
|
|
|
|
size: (dtb_size + 0xFFF) & !0xFFF,
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
|
|
|
let dtb_slice = EarlyMapping::<u8>::map_slice(dtb, dtb_size)?;
|
|
|
|
|
|
|
|
let dt = DeviceTree::from_addr(dtb_slice.as_ptr() as usize);
|
|
|
|
|
|
|
|
// Setup initrd from the dt
|
|
|
|
let initrd = self.extract_initrd_from_dt(&dt);
|
2023-07-18 18:03:45 +03:00
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
if let Some((start, end)) = initrd {
|
|
|
|
let aligned_start = start.page_align_down::<L3>();
|
|
|
|
let aligned_end = end.page_align_up::<L3>();
|
|
|
|
|
|
|
|
let size = aligned_end - aligned_start;
|
2023-07-19 21:58:59 +03:00
|
|
|
reserve_region(
|
|
|
|
"initrd",
|
|
|
|
PhysicalMemoryRegion {
|
2023-11-16 00:16:38 +02:00
|
|
|
base: aligned_start,
|
|
|
|
size,
|
2023-07-19 21:58:59 +03:00
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
// Initialize the physical memory
|
|
|
|
let regions = FdtMemoryRegionIter::new(&dt);
|
2023-07-18 18:03:45 +03:00
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
phys::init_from_iter(regions)?;
|
2023-08-08 20:00:24 +03:00
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
// Setup the heap
|
|
|
|
for i in 0..HEAP_PAGES {
|
|
|
|
let l2_page = phys::alloc_2m_page()?;
|
|
|
|
mem::map_heap_l2(i, l2_page);
|
|
|
|
}
|
2023-08-13 21:23:58 +03:00
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
heap::init_heap(mem::HEAP_MAPPING_OFFSET, HEAP_PAGES * L2::SIZE);
|
|
|
|
|
|
|
|
// EarlyMapping for DTB no longer needed, it lives in physical memory and can be obtained
|
|
|
|
// through PhysicalRef
|
|
|
|
let dtb_slice: PhysicalRef<'static, [u8]> = PhysicalRef::map_slice(dtb, dtb_size);
|
|
|
|
let dt = DeviceTree::from_addr(dtb_slice.as_ptr() as usize);
|
|
|
|
|
|
|
|
self.dt.init(dt);
|
|
|
|
|
|
|
|
// Setup initrd
|
|
|
|
if let Some((initrd_start, initrd_end)) = initrd {
|
|
|
|
let aligned_start = initrd_start.page_align_down::<L3>();
|
|
|
|
let aligned_end = initrd_end.page_align_up::<L3>();
|
|
|
|
let len = initrd_end - initrd_start;
|
|
|
|
|
|
|
|
let data = unsafe { PhysicalRef::map_slice(initrd_start, len) };
|
|
|
|
self.initrd.init(data);
|
|
|
|
|
2023-12-05 10:27:56 +02:00
|
|
|
INITRD_DATA.init(Initrd {
|
|
|
|
phys_page_start: aligned_start,
|
|
|
|
phys_page_len: aligned_end - aligned_start,
|
|
|
|
data: self.initrd.get().as_ref(),
|
|
|
|
});
|
2023-11-16 00:16:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
2023-08-13 21:23:58 +03:00
|
|
|
}
|
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
unsafe fn init_platform(&self, is_bsp: bool) -> Result<(), Error> {
|
|
|
|
Cpu::init_local();
|
|
|
|
|
|
|
|
if is_bsp {
|
2024-02-03 20:44:04 +02:00
|
|
|
ygg_driver_pci::register_vendor_driver(
|
|
|
|
"Virtio PCI Network Device",
|
|
|
|
0x1AF4,
|
|
|
|
0x1000,
|
|
|
|
ygg_driver_virtio_net::probe,
|
|
|
|
);
|
2024-02-04 13:15:18 +02:00
|
|
|
ygg_driver_pci::register_class_driver(
|
|
|
|
"AHCI SATA Controller",
|
|
|
|
0x01,
|
|
|
|
Some(0x06),
|
|
|
|
Some(0x01),
|
|
|
|
ygg_driver_ahci::probe,
|
|
|
|
);
|
2024-02-03 20:44:04 +02:00
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
let dt = self.dt.get();
|
2023-08-13 21:23:58 +03:00
|
|
|
|
|
|
|
let address_cells = dt.address_cells();
|
|
|
|
let size_cells = dt.size_cells();
|
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
// Setup /chosen.stdout-path to get early debug printing
|
|
|
|
let chosen_stdout_path = dt.chosen_stdout_path();
|
2023-08-13 21:23:58 +03:00
|
|
|
let chosen_stdout = chosen_stdout_path.and_then(|path| dt.node_by_path(path));
|
|
|
|
|
|
|
|
if let Some(node) = chosen_stdout.clone() {
|
|
|
|
let probe = DevTreeNodeInfo {
|
|
|
|
address_cells,
|
|
|
|
size_cells,
|
|
|
|
node,
|
|
|
|
};
|
|
|
|
|
2024-02-04 15:18:34 +02:00
|
|
|
if let Some((device, _)) =
|
|
|
|
device_tree::driver::probe_dt_node(&probe, device::register_device)
|
|
|
|
{
|
2023-11-16 00:16:38 +02:00
|
|
|
device.init()?;
|
2023-08-13 21:23:58 +03:00
|
|
|
}
|
2023-11-16 00:16:38 +02:00
|
|
|
}
|
2023-08-13 21:23:58 +03:00
|
|
|
|
2023-11-16 00:16:38 +02:00
|
|
|
debug::init();
|
2023-08-13 21:23:58 +03:00
|
|
|
|
|
|
|
infoln!(
|
|
|
|
"Yggdrasil v{} ({})",
|
|
|
|
env!("CARGO_PKG_VERSION"),
|
|
|
|
git_version!()
|
|
|
|
);
|
|
|
|
infoln!("Initializing aarch64 platform");
|
|
|
|
|
|
|
|
let nodes = dt.root().children();
|
2024-01-04 23:04:34 +02:00
|
|
|
if let Err(error) =
|
2024-02-04 15:18:34 +02:00
|
|
|
device_tree::driver::enumerate_dt(address_cells, size_cells, nodes, |_, probe| {
|
2023-11-16 00:16:38 +02:00
|
|
|
// Skip chosen-stdout, already initialized
|
2024-01-04 23:04:34 +02:00
|
|
|
if let Some(ref chosen_stdout) = chosen_stdout
|
|
|
|
&& chosen_stdout.name() == probe.node.name()
|
|
|
|
{
|
|
|
|
return Ok(());
|
|
|
|
}
|
2023-08-13 21:23:58 +03:00
|
|
|
|
2024-02-04 15:18:34 +02:00
|
|
|
if let Some((device, _)) =
|
|
|
|
device_tree::driver::probe_dt_node(&probe, device::register_device)
|
|
|
|
{
|
2023-11-16 00:16:38 +02:00
|
|
|
device.init()?;
|
2023-08-13 21:23:58 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
2024-01-04 23:04:34 +02:00
|
|
|
})
|
|
|
|
{
|
2023-08-13 21:23:58 +03:00
|
|
|
warnln!(
|
|
|
|
"{} errors encountered when initializing platform devices",
|
|
|
|
error
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize IRQs for the devices
|
|
|
|
device::manager_lock().devices().for_each(|dev| unsafe {
|
|
|
|
if let Err(error) = dev.init_irq() {
|
2023-11-16 00:16:38 +02:00
|
|
|
warnln!(
|
|
|
|
"Could not init IRQs for {:?}: {:?}",
|
2023-08-13 21:23:58 +03:00
|
|
|
dev.display_name(),
|
|
|
|
error
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
infoln!("Enumerated devices:");
|
|
|
|
device::manager_lock().devices().for_each(|dev| {
|
|
|
|
infoln!("* {:?}", dev.display_name());
|
|
|
|
});
|
2024-02-03 20:44:04 +02:00
|
|
|
|
|
|
|
PciBusManager::setup_bus_devices()?;
|
2023-08-13 21:23:58 +03:00
|
|
|
} else {
|
|
|
|
// BSP already initialized everything needed
|
|
|
|
// Setup timer and local interrupt controller
|
2023-11-16 00:16:38 +02:00
|
|
|
let intc = self.lintc.get();
|
2023-08-13 21:23:58 +03:00
|
|
|
|
|
|
|
unsafe {
|
|
|
|
intc.init_ap().unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO device-tree initialization for this
|
|
|
|
CNTP_CTL_EL0.write(CNTP_CTL_EL0::ENABLE::SET + CNTP_CTL_EL0::IMASK::CLEAR);
|
|
|
|
CNTP_TVAL_EL0.set(10000000);
|
2023-11-16 00:16:38 +02:00
|
|
|
self.xintc.get().enable_irq(IrqNumber::Private(14)).unwrap();
|
2023-08-13 21:23:58 +03:00
|
|
|
}
|
2023-11-16 00:16:38 +02:00
|
|
|
|
|
|
|
Ok(())
|
2023-08-13 21:23:58 +03:00
|
|
|
}
|
2023-07-18 18:03:45 +03:00
|
|
|
}
|
|
|
|
|
2023-12-07 12:50:54 +02:00
|
|
|
/// AArch64 implementation value
|
2023-11-16 00:16:38 +02:00
|
|
|
pub static ARCHITECTURE: AArch64 = AArch64 {
|
|
|
|
dt: OneTimeInit::new(),
|
|
|
|
initrd: OneTimeInit::new(),
|
|
|
|
|
|
|
|
psci: OneTimeInit::new(),
|
|
|
|
reset: OneTimeInit::new(),
|
|
|
|
|
|
|
|
lintc: OneTimeInit::new(),
|
|
|
|
xintc: OneTimeInit::new(),
|
2024-02-03 20:44:04 +02:00
|
|
|
msi_intc: OneTimeInit::new(),
|
2023-11-16 00:16:38 +02:00
|
|
|
|
|
|
|
mtimer: OneTimeInit::new(),
|
|
|
|
};
|
|
|
|
|
2023-12-07 12:50:54 +02:00
|
|
|
/// AArch64-specific interrupt number
|
2023-11-16 00:16:38 +02:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
|
|
pub enum IrqNumber {
|
2023-12-07 12:50:54 +02:00
|
|
|
/// CPU-private interrupt
|
2023-11-16 00:16:38 +02:00
|
|
|
Private(u32),
|
2023-12-07 12:50:54 +02:00
|
|
|
/// Shared interrupt
|
2023-11-16 00:16:38 +02:00
|
|
|
Shared(u32),
|
2023-07-19 21:58:59 +03:00
|
|
|
}
|