Skip to content

Commit d2ed7ac

Browse files
Introduce aarch64 board-specific config, plus GIC fixes (#915)
* New `arm_boards` crate: per-board definitions for aarch64 builds * The default is for QEMU's basic `virt` machine spec. * Currently, this specifies the number of CPUs, their IDs, and the interrupt controller configuration including one GIC redistributor base address per core. * The `gic` crate now uses this instead of defining its own internal configuration values specific to QEMU. * `multicore_bringup` now uses the list of `CpuId`s from the selected ARM board configuration. * The redistributor initialization routine code now enables the dispatch of "1 of N"-distributed SPIs. * All CPUs' redistributors are now initialized by the bootstrap processor as part of `interrupts::init()`. * Incorporates two fixes from #910: * Fix a bug in `get_spi_target` & `set_spi_target` where an atomic u32 read/write was used to manipulate a u64 MMIO register. * Introduce `Offset32` and `Offset64` types to distinguish 32-bit and 64-bit registers more clearly. Co-authored-by: Kevin Boos <kevinaboos@gmail.com>
1 parent 41160ce commit d2ed7ac

File tree

18 files changed

+447
-210
lines changed

18 files changed

+447
-210
lines changed

Cargo.lock

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

kernel/arm_boards/Cargo.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
authors = ["Nathan Royer <nathan.royer.pro@gmail.com>"]
3+
name = "arm_boards"
4+
description = "Board-specific configuration and definitions for aarch64 systems"
5+
version = "0.1.0"
6+
edition = "2021"
7+
8+
[dependencies]
9+
cfg-if = "1.0.0"
10+
memory_structs = { path = "../memory_structs" }
11+
derive_more = "0.99.0"
12+
13+
[features]
14+
default = [ "qemu_virt" ]
15+
qemu_virt = []
16+
17+
[lib]
18+
crate-type = ["rlib"]
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//! Board configuration for QEMU's basic `virt` machine with 4 CPUs.
2+
3+
use super::{
4+
InterruptControllerConfig::GicV3, GicV3InterruptControllerConfig,
5+
BoardConfig, mpidr::DefinedMpidrValue,
6+
};
7+
use memory_structs::PhysicalAddress;
8+
9+
/// Generates an MPIDR value from a CPU's 0th affinity level.
10+
const fn cpu_id(aff0: u8) -> DefinedMpidrValue {
11+
DefinedMpidrValue::new(0, 0, 0, aff0)
12+
}
13+
14+
/// Generates a Redistributor base address from a CPU's 0th affinity level.
15+
const fn redist(aff0: usize) -> PhysicalAddress {
16+
PhysicalAddress::new_canonical(0x080A0000 + 0x20000 * aff0)
17+
}
18+
19+
pub const NUM_CPUS: usize = 4;
20+
pub static BOARD_CONFIG: BoardConfig = BoardConfig {
21+
cpu_ids: [
22+
cpu_id(0),
23+
cpu_id(1),
24+
cpu_id(2),
25+
cpu_id(3),
26+
],
27+
interrupt_controller: GicV3(GicV3InterruptControllerConfig {
28+
distributor_base_address: PhysicalAddress::new_canonical(0x08000000),
29+
redistributor_base_addresses: [
30+
redist(0),
31+
redist(1),
32+
redist(2),
33+
redist(3),
34+
],
35+
}),
36+
};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
//! Invalid board config file that throws a compile error if a board config wasn't selected.
2+
3+
compile_error!("Please select a board config feature in the arm_boards crate");

kernel/arm_boards/src/lib.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//! Configuration and definitions for specific boards on aarch64 systems.
2+
//!
3+
//! | Board Name | Num CPUs | Interrupt Controller | Secondary CPU Startup Method |
4+
//! | ---------- | --------- | -------------------- | ---------------------------- |
5+
//! | qemu_virt | 4 | GICv3 | PSCI |
6+
//!
7+
8+
#![no_std]
9+
#![feature(const_trait_impl)]
10+
11+
cfg_if::cfg_if! {
12+
if #[cfg(target_arch = "aarch64")] {
13+
14+
use memory_structs::PhysicalAddress;
15+
16+
#[derive(Debug, Copy, Clone)]
17+
pub struct GicV3InterruptControllerConfig {
18+
pub distributor_base_address: PhysicalAddress,
19+
pub redistributor_base_addresses: [PhysicalAddress; board::NUM_CPUS],
20+
}
21+
22+
#[derive(Debug, Copy, Clone)]
23+
pub enum InterruptControllerConfig {
24+
GicV3(GicV3InterruptControllerConfig),
25+
}
26+
27+
/*
28+
TODO: multicore_bringup: wake secondary cores based on this:
29+
pub enum SecondaryCoresStartup {
30+
Psci,
31+
}
32+
*/
33+
34+
#[derive(Debug, Clone)]
35+
pub struct BoardConfig {
36+
pub cpu_ids: [mpidr::DefinedMpidrValue; board::NUM_CPUS],
37+
pub interrupt_controller: InterruptControllerConfig,
38+
}
39+
40+
// by default & on x86_64, the default.rs file is used
41+
#[cfg_attr(feature = "qemu_virt", path = "boards/qemu_virt.rs")]
42+
#[cfg_attr(not(any(
43+
feature = "qemu_virt",
44+
)), path = "boards/unselected.rs")]
45+
mod board;
46+
47+
pub mod mpidr;
48+
49+
pub use board::{NUM_CPUS, BOARD_CONFIG};
50+
51+
52+
} // end of cfg(target_arch = "aarch64")
53+
} // end of cfg_if

kernel/arm_boards/src/mpidr.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use derive_more::{Display, Binary, Octal, LowerHex, UpperHex};
2+
3+
/// A unique identifier for a CPU, hardcoded in `arm_boards`.
4+
#[derive(
5+
Clone, Copy, Debug, Display, PartialEq, Eq, PartialOrd, Ord,
6+
Hash, Binary, Octal, LowerHex, UpperHex,
7+
)]
8+
#[repr(transparent)]
9+
pub struct DefinedMpidrValue(u64);
10+
11+
impl DefinedMpidrValue {
12+
/// Returns the contained value
13+
pub fn value(self) -> u64 {
14+
self.0
15+
}
16+
17+
/// Create an `MpidrValue` from its four affinity numbers
18+
pub(crate) const fn new(aff3: u8, aff2: u8, aff1: u8, aff0: u8) -> Self {
19+
let aff3 = (aff3 as u64) << 32;
20+
let aff2 = (aff2 as u64) << 16;
21+
let aff1 = (aff1 as u64) << 8;
22+
let aff0 = (aff0 as u64) << 0;
23+
Self(aff3 | aff2 | aff1 | aff0)
24+
}
25+
}

kernel/cpu/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ edition = "2021"
88
[dependencies]
99
derive_more = "0.99.0"
1010

11-
1211
[target.'cfg(target_arch = "x86_64")'.dependencies]
1312
apic = { path = "../apic" }
1413

1514
[target.'cfg(target_arch = "aarch64")'.dependencies]
15+
irq_safety = { git = "https://github.com/theseus-os/irq_safety" }
16+
arm_boards = { path = "../arm_boards" }
1617
tock-registers = "0.7.0"
1718
cortex-a = "7.5.0"
18-
irq_safety = { git = "https://github.com/theseus-os/irq_safety" }
1919

2020
[lib]
2121
crate-type = ["rlib"]

kernel/cpu/src/aarch64.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use derive_more::{Display, Binary, Octal, LowerHex, UpperHex};
66
use irq_safety::RwLockIrqSafe;
77
use core::fmt;
88
use alloc::vec::Vec;
9+
use arm_boards::mpidr::DefinedMpidrValue;
910

1011
use super::CpuId;
1112

@@ -89,14 +90,17 @@ impl MpidrValue {
8990
};
9091
(self.0 >> shift) as u8
9192
}
93+
}
94+
95+
impl From<DefinedMpidrValue> for MpidrValue {
96+
fn from(def_mpidr: DefinedMpidrValue) -> Self {
97+
Self(def_mpidr.value())
98+
}
99+
}
92100

93-
/// Create an `MpidrValue` from its four affinity numbers
94-
pub fn new(aff3: u8, aff2: u8, aff1: u8, aff0: u8) -> Self {
95-
let aff3 = (aff3 as u64) << 32;
96-
let aff2 = (aff2 as u64) << 16;
97-
let aff1 = (aff1 as u64) << 8;
98-
let aff0 = (aff0 as u64) << 0;
99-
Self(aff3 | aff2 | aff1 | aff0)
101+
impl From<DefinedMpidrValue> for CpuId {
102+
fn from(def_mpidr: DefinedMpidrValue) -> Self {
103+
Self::from(MpidrValue::from(def_mpidr))
100104
}
101105
}
102106

kernel/gic/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ zerocopy = "0.5.0"
1212
log = "0.4.8"
1313

1414
memory = { path = "../memory" }
15+
cpu = { path = "../cpu" }
16+
arm_boards = { path = "../arm_boards" }

kernel/gic/src/gic/cpu_interface_gicv2.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,16 @@
77
//! - Sending End-Of-Interrupts signals
88
99
use super::GicRegisters;
10-
use super::U32BYTES;
1110
use super::Priority;
1211
use super::InterruptNumber;
1312

1413
mod offset {
15-
use super::U32BYTES;
16-
pub const CTLR: usize = 0x00 / U32BYTES;
17-
pub const PMR: usize = 0x04 / U32BYTES;
18-
pub const IAR: usize = 0x0C / U32BYTES;
19-
pub const RPR: usize = 0x14 / U32BYTES;
20-
pub const EOIR: usize = 0x10 / U32BYTES;
14+
use crate::Offset32;
15+
pub(crate) const CTLR: Offset32 = Offset32::from_byte_offset(0x00);
16+
pub(crate) const PMR: Offset32 = Offset32::from_byte_offset(0x04);
17+
pub(crate) const IAR: Offset32 = Offset32::from_byte_offset(0x0C);
18+
pub(crate) const RPR: Offset32 = Offset32::from_byte_offset(0x14);
19+
pub(crate) const EOIR: Offset32 = Offset32::from_byte_offset(0x10);
2120
}
2221

2322
// enable group 0

0 commit comments

Comments
 (0)