mirror of
https://github.com/redox-os/kernel.git
synced 2026-09-09 00:07:34 +08:00
AArch64: Allow GICv2 initialization on uniprocessor systems
Treat a zero GICD_ITARGETSR target mask as valid during BSP initialization because GICv2 target registers may be RAZ/WI on uniprocessor implementations, while retaining fail-closed SMP behavior by requiring a valid target mask before starting secondary CPUs and after each AP initializes its local GIC interface. Signed-off-by: Luiz Fernando Becher de Araujo <luiz.becher.araujo@gmail.com>
This commit is contained in:
@@ -478,6 +478,10 @@ pub(super) fn start_secondaries() {
|
||||
);
|
||||
return;
|
||||
}
|
||||
if crate::arch::device::irqchip::current_cpu_target_mask().is_none() {
|
||||
error!("CPU activation unavailable: BSP has no directed-SGI target mask");
|
||||
return;
|
||||
}
|
||||
if !crate::arch::device::generic_timer::ready() {
|
||||
error!("CPU activation unavailable: architected timer is not initialized");
|
||||
return;
|
||||
|
||||
@@ -55,6 +55,14 @@ pub(crate) fn cpu_capacity() -> Option<usize> {
|
||||
(count != 0).then_some(count)
|
||||
}
|
||||
|
||||
pub(crate) fn current_cpu_target_mask() -> Option<u8> {
|
||||
let target_mask = crate::percpu::PercpuBlock::current()
|
||||
.misc_arch_info
|
||||
.gic_target_mask
|
||||
.load(Ordering::Acquire);
|
||||
(target_mask != 0).then_some(target_mask)
|
||||
}
|
||||
|
||||
pub(crate) fn init_current_cpu() -> Result<()> {
|
||||
let dist = GICD_BASE.load(Ordering::Acquire);
|
||||
let cpu = GICC_BASE.load(Ordering::Acquire);
|
||||
@@ -79,11 +87,9 @@ pub(crate) fn init_current_cpu() -> Result<()> {
|
||||
write32(cpu, GICC_CTLR, 1);
|
||||
|
||||
// ITARGETSR0 is banked for SGIs/PPIs and exposes the target bit assigned
|
||||
// to the current GICv2 CPU interface.
|
||||
// to the current GICv2 CPU interface. On a uniprocessor GIC the target
|
||||
// registers are RAZ/WI, so zero is valid until directed SGIs are needed.
|
||||
let target_mask = (read32(dist, GICD_ITARGETSR) & 0xff) as u8;
|
||||
if target_mask == 0 {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
crate::percpu::PercpuBlock::current()
|
||||
.misc_arch_info
|
||||
.gic_target_mask
|
||||
|
||||
@@ -42,7 +42,10 @@ pub(crate) fn ic_for_chip(fdt: &Fdt, node: &FdtNode) -> Option<usize> {
|
||||
|
||||
pub(crate) fn init_ap() -> syscall::Result<()> {
|
||||
if gic::active() {
|
||||
gic::init_current_cpu()
|
||||
gic::init_current_cpu()?;
|
||||
gic::current_cpu_target_mask()
|
||||
.map(|_| ())
|
||||
.ok_or_else(|| syscall::Error::new(syscall::error::EINVAL))
|
||||
} else {
|
||||
Err(syscall::Error::new(syscall::error::ENODEV))
|
||||
}
|
||||
@@ -52,6 +55,10 @@ pub(crate) fn cpu_capacity() -> Option<usize> {
|
||||
gic::cpu_capacity()
|
||||
}
|
||||
|
||||
pub(crate) fn current_cpu_target_mask() -> Option<u8> {
|
||||
gic::active().then(gic::current_cpu_target_mask).flatten()
|
||||
}
|
||||
|
||||
pub(crate) fn enable_local_irq(hwirq: u32) -> syscall::Result<()> {
|
||||
if gic::active() {
|
||||
gic::enable_local_irq(hwirq)
|
||||
|
||||
Reference in New Issue
Block a user