Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
b29102a
Bump vte dependency from 0.10.1 to 0.11.0
NathanRoyer Mar 31, 2023
6fac3fb
Make CpuId conversions and constructions `const`
NathanRoyer Mar 31, 2023
3bb3d3c
Introduce arm_boards crate
NathanRoyer Mar 31, 2023
19b8c66
Use arm_boards in GIC driver
NathanRoyer Mar 31, 2023
dfac795
Use arm_boards in multicore_bringup instead of CpuId bruteforcing
NathanRoyer Mar 31, 2023
f9ab052
Assert that the GIC distributor is allowed to pick a core that is asl…
NathanRoyer Mar 31, 2023
0bc3b7f
Introduce AffinityShift for safer affinity level readings from an Mpi…
NathanRoyer Mar 31, 2023
e7cc06c
Dedicated Offset Types to prevent confusion between 32b & 64b registers
NathanRoyer Mar 31, 2023
e153838
Assert PE selectability policy for "1 of N" interrupts in redistribut…
NathanRoyer Mar 31, 2023
03f05c5
Revert "Introduce AffinityShift for safer affinity level readings fro…
NathanRoyer Mar 31, 2023
d9cfc4e
Fix missing import in gic
NathanRoyer Mar 31, 2023
d7f9267
Fix doc builds
NathanRoyer Mar 31, 2023
d8bf0c6
Remove `arrayvec` dep of `gic` in favor of `core::array::try_from_fn`
NathanRoyer Apr 4, 2023
2903a98
Rename `current_redist_index` as `get_current_cpu_redist_index` and d…
NathanRoyer Apr 4, 2023
0cabe63
Rename default arm_boards file
NathanRoyer Apr 4, 2023
77f5052
Introduce arm_boards::BoardConfig
NathanRoyer Apr 4, 2023
aed9ac0
Rename default arm_boards file to `unselected.rs`
NathanRoyer Apr 4, 2023
baba04c
Introduce `arm_boards::mpidr::DefinedMpidrValue`, a hardcoded equival…
NathanRoyer Apr 4, 2023
76d8678
Fix unselected board file path
NathanRoyer Apr 4, 2023
5f83734
Doc & x86 builds fix
NathanRoyer Apr 4, 2023
605f93a
Fix doc builds by removing the gic crate from them
NathanRoyer Apr 4, 2023
1eb0588
clean up
kevinaboos Apr 4, 2023
f7de8b1
fix gic redistributor timeout
kevinaboos Apr 4, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions kernel/arm_boards/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
authors = ["Nathan Royer <nathan.royer.pro@gmail.com>"]
name = "arm_boards"
description = "Per-board AArch64 configuration"
version = "0.1.0"
edition = "2021"

[dependencies]
memory_structs = { path = "../memory_structs" }
cpu = { path = "../cpu" }

[features]
default = [ "qemu_virt" ]
qemu_virt = []

[lib]
crate-type = ["rlib"]
8 changes: 8 additions & 0 deletions kernel/arm_boards/src/board.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//! Default board config file.
//!
//! This will result in a compile-time error if used in an aarch64 build.

#[cfg(target_arch = "aarch64")]
compile_error!("Please select a board config feature in the arm_boards crate");

pub const CPUS: usize = 0;
35 changes: 35 additions & 0 deletions kernel/arm_boards/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//! Per-board definitions for AArch64 builds
//!
//! | Feature | CPU Cores | Interrupt Controller | Secondary Cores Startup Method |
//! | --- | --- | --- | --- |
//! | qemu_virt | 4 | GICv3 | PSCI |
//!

#![no_std]
#![feature(const_trait_impl)]

use memory_structs::PhysicalAddress;

#[derive(Debug, Copy, Clone)]
pub struct GicV3InterruptControllerConfig {
pub distributor_base_address: PhysicalAddress,
pub redistributor_base_addresses: [PhysicalAddress; board::CPUS],
}

#[derive(Debug, Copy, Clone)]
pub enum InterruptControllerConfig {
GicV3(GicV3InterruptControllerConfig),
}

/*
TODO: multicore_bringup: wake secondary cores based on this:
pub enum SecondaryCoresStartup {
Psci,
}
*/

// by default & on x86_64, the board.rs file is used
#[cfg_attr(all(target_arch = "aarch64", feature = "qemu_virt"), path = "qemu_virt.rs")]
mod board;

pub use board::*;
36 changes: 36 additions & 0 deletions kernel/arm_boards/src/qemu_virt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
//! AArch64 Board Config for the `virt` machine of Qemu

use super::{InterruptControllerConfig::{self, GicV3}, GicV3InterruptControllerConfig};
use cpu::{CpuId, MpidrValue};
use memory_structs::PhysicalAddress;

// local utility function to generate the CPU id from
// the affinity level 0 number of the cpu core
const fn cpu_id(aff0: u8) -> CpuId {
CpuId::from(MpidrValue::new(0, 0, 0, aff0))
}

pub const CPUS: usize = 4;

pub const CPUIDS: [CpuId; CPUS] = [
cpu_id(0),
cpu_id(1),
cpu_id(2),
cpu_id(3),
];

// local utility function to generate the redistributor base
// address from the affinity level 0 number of the cpu core
const fn redist(aff0: usize) -> PhysicalAddress {
PhysicalAddress::new_canonical(0x080A0000 + 0x20000 * aff0)
}

pub const INTERRUPT_CONTROLLER_CONFIG: InterruptControllerConfig = GicV3(GicV3InterruptControllerConfig {
distributor_base_address: PhysicalAddress::new_canonical(0x08000000),
redistributor_base_addresses: [
redist(0),
redist(1),
redist(2),
redist(3),
],
});
1 change: 0 additions & 1 deletion kernel/cpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ edition = "2021"
[dependencies]
derive_more = "0.99.0"


[target.'cfg(target_arch = "x86_64")'.dependencies]
apic = { path = "../apic" }

Expand Down
6 changes: 3 additions & 3 deletions kernel/cpu/src/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ impl MpidrValue {
}

/// Create an `MpidrValue` from its four affinity numbers
pub fn new(aff3: u8, aff2: u8, aff1: u8, aff0: u8) -> Self {
pub const fn new(aff3: u8, aff2: u8, aff1: u8, aff0: u8) -> Self {
let aff3 = (aff3 as u64) << 32;
let aff2 = (aff2 as u64) << 16;
let aff1 = (aff1 as u64) << 8;
Expand All @@ -100,7 +100,7 @@ impl MpidrValue {
}
}

impl From<CpuId> for MpidrValue {
impl const From<CpuId> for MpidrValue {
fn from(cpu_id: CpuId) -> Self {
// move aff3 from bits [24:31] to [32:39]
let aff_3 = ((cpu_id.0 & 0xff000000) as u64) << 8;
Expand All @@ -110,7 +110,7 @@ impl From<CpuId> for MpidrValue {
}
}

impl From<MpidrValue> for CpuId {
impl const From<MpidrValue> for CpuId {
fn from(mpidr: MpidrValue) -> Self {
// move aff3 from bits [32:39] to [24:31]
let aff_3 = ((mpidr.0 & 0xff00000000) >> 8) as u32;
Expand Down
2 changes: 2 additions & 0 deletions kernel/cpu/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

#![no_std]

#![cfg_attr(target_arch = "aarch64", feature(const_trait_impl))]

#[cfg(target_arch = "aarch64")]
extern crate alloc;

Expand Down
3 changes: 3 additions & 0 deletions kernel/gic/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ name = "gic"

[dependencies]
static_assertions = "1.1.0"
arrayvec = { version = "0.7.2", default-features = false }
bitflags = "1.1.0"
zerocopy = "0.5.0"
log = "0.4.8"

memory = { path = "../memory" }
cpu = { path = "../cpu" }
arm_boards = { path = "../arm_boards" }
13 changes: 6 additions & 7 deletions kernel/gic/src/gic/cpu_interface_gicv2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,16 @@
//! - Sending End-Of-Interrupts signals

use super::GicRegisters;
use super::U32BYTES;
use super::Priority;
use super::InterruptNumber;

mod offset {
use super::U32BYTES;
pub const CTLR: usize = 0x00 / U32BYTES;
pub const PMR: usize = 0x04 / U32BYTES;
pub const IAR: usize = 0x0C / U32BYTES;
pub const RPR: usize = 0x14 / U32BYTES;
pub const EOIR: usize = 0x10 / U32BYTES;
use crate::Offset32;
pub(crate) const CTLR: Offset32 = Offset32::from_byte_offset(0x00);
pub(crate) const PMR: Offset32 = Offset32::from_byte_offset(0x04);
pub(crate) const IAR: Offset32 = Offset32::from_byte_offset(0x0C);
pub(crate) const RPR: Offset32 = Offset32::from_byte_offset(0x14);
pub(crate) const EOIR: Offset32 = Offset32::from_byte_offset(0x10);
}

// enable group 0
Expand Down
33 changes: 19 additions & 14 deletions kernel/gic/src/gic/dist_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,21 @@
//! - Generating software interrupts (GICv2 style)

use super::GicRegisters;
use super::U32BYTES;
use super::TargetCpu;
use super::InterruptNumber;
use super::Enabled;
use super::TargetList;

mod offset {
use super::U32BYTES;
pub const CTLR: usize = 0x000 / U32BYTES;
pub const IGROUPR: usize = 0x080 / U32BYTES;
pub const ISENABLER: usize = 0x100 / U32BYTES;
pub const ICENABLER: usize = 0x180 / U32BYTES;
pub const ITARGETSR: usize = 0x800 / U32BYTES;
pub const SGIR: usize = 0xf00 / U32BYTES;
use crate::{Offset32, Offset64};
pub(crate) const CTLR: Offset32 = Offset32::from_byte_offset(0x000);
pub(crate) const IGROUPR: Offset32 = Offset32::from_byte_offset(0x080);
pub(crate) const ISENABLER: Offset32 = Offset32::from_byte_offset(0x100);
pub(crate) const ICENABLER: Offset32 = Offset32::from_byte_offset(0x180);
pub(crate) const ITARGETSR: Offset32 = Offset32::from_byte_offset(0x800);
pub(crate) const SGIR: Offset32 = Offset32::from_byte_offset(0xf00);
/// This one is on the 6th page
pub const P6IROUTER: usize = 0x100 / U32BYTES;
pub(crate) const P6IROUTER: Offset64 = Offset64::from_byte_offset(0x100);
}

// enable group 0
Expand All @@ -37,6 +36,9 @@ mod offset {
// enable group 1
const CTLR_ENGRP1: u32 = 0b10;

// enable 1 of N wakeup functionality
const CTLR_E1NWF: u32 = 1 << 7;

// Affinity Routing Enable, Non-secure state.
const CTLR_ARE_NS: u32 = 1 << 5;

Expand All @@ -48,7 +50,7 @@ const SGIR_TARGET_ALL_OTHER_PE: u32 = 1 << 24;
// bit 31: SPI routing
// 1 = any available PE
// 0 = route to specific PE
const P6IROUTER_ANY_AVAILABLE_PE: u32 = 1 << 31;
const P6IROUTER_ANY_AVAILABLE_PE: u64 = 1 << 31;

// const GROUP_0: u32 = 0;
const GROUP_1: u32 = 1;
Expand All @@ -63,14 +65,16 @@ fn assert_cpu_bounds(target: &TargetCpu) {
}

/// Initializes the distributor by enabling forwarding
/// of group 1 interrupts
/// of group 1 interrupts and allowing the GIC to pick
/// a core that is asleep for "1 of N" interrupts.
///
/// Return value: whether or not affinity routing is
/// currently enabled for both secure and non-secure
/// states.
pub fn init(registers: &mut GicRegisters) -> Enabled {
let mut reg = registers.read_volatile(offset::CTLR);
reg |= CTLR_ENGRP1;
reg |= CTLR_E1NWF;
registers.write_volatile(offset::CTLR, reg);

// Return value: whether or not affinity routing is
Expand Down Expand Up @@ -157,7 +161,7 @@ impl super::ArmGic {
let list = TargetList::from_bits_truncate(flags as u8);
TargetCpu::GICv2TargetList(list)
} else if let Self::V3(v3) = self {
let reg = v3.dist_extended.read_volatile(offset::P6IROUTER);
let reg = v3.dist_extended.read_volatile_64(offset::P6IROUTER);

// bit 31: Interrupt Routing Mode
// value of 1 to target any available cpu
Expand All @@ -167,7 +171,7 @@ impl super::ArmGic {
} else {
let aff3 = (reg >> 8) & 0xff000000;
let aff012 = reg & 0xffffff;
TargetCpu::Specific(aff3 | aff012)
TargetCpu::Specific((aff3 | aff012) as u32)
}
} else {
// If we're on gicv2 then affinity routing is off
Expand Down Expand Up @@ -196,6 +200,7 @@ impl super::ArmGic {
} else if let Self::V3(v3) = self {
let value = match target {
TargetCpu::Specific(cpu) => {
let cpu = cpu as u64;
// shift aff3 8 bits to the left
let aff3 = (cpu & 0xff000000) << 8;
// keep aff 0, 1 & 2 where they are
Expand All @@ -212,7 +217,7 @@ impl super::ArmGic {
},
};

v3.dist_extended.write_volatile(offset::P6IROUTER, value);
v3.dist_extended.write_volatile_64(offset::P6IROUTER, value);
}

// If we're on gicv2 then affinity routing is off
Expand Down
Loading