Skip to content

Commit

Permalink
Update aarch64 PSCI
Browse files Browse the repository at this point in the history
  • Loading branch information
equation314 committed Aug 22, 2023
1 parent a133e72 commit 325a09d
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 96 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,9 @@ jobs:
- name: Build fs/shell for aarch64-raspi4
run: make PLATFORM=aarch64-raspi4 A=apps/fs/shell FEATURES=driver-bcm2835-sdhci

- name: Build hello for aarch64-bsta1000b
run: make PLATFORM=aarch64-bsta1000b A=apps/helloworld

build-apps-for-std:
runs-on: ${{ matrix.os }}
strategy:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! snps,dw-apb-uart serial driver

use crate::mem::phys_to_virt;
use dw_apb_uart::dw_apb_uart::DW8250;
use dw_apb_uart::DW8250;
use memory_addr::PhysAddr;
use spinlock::SpinNoIrq;

Expand Down
2 changes: 1 addition & 1 deletion modules/axhal/src/platform/aarch64_bsta1000b/mp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub fn start_secondary_cpu(cpu_id: usize, stack_top: PhysAddr) {
fn _start_secondary();
}
let entry = virt_to_phys(VirtAddr::from(_start_secondary as usize));
crate::platform::aarch64_common::psci::psci_cpu_on(
crate::platform::aarch64_common::psci::cpu_on(
CPU_HWID[cpu_id],
entry.as_usize(),
stack_top.as_usize(),
Expand Down
152 changes: 63 additions & 89 deletions modules/axhal/src/platform/aarch64_common/psci.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
#![allow(dead_code)]
//! ARM Power State Coordination Interface.

/* PSCI v0.2 interface */
#![allow(dead_code)]

pub const PSCI_0_2_FN_BASE: u32 = 0x84000000;
pub const PSCI_0_2_64BIT: u32 = 0x40000000;
pub const PSCI_0_2_FN_PSCI_VERSION: u32 = PSCI_0_2_FN_BASE + 0;
pub const PSCI_0_2_FN_CPU_SUSPEND: u32 = PSCI_0_2_FN_BASE + 1;
pub const PSCI_0_2_FN_CPU_OFF: u32 = PSCI_0_2_FN_BASE + 2;
pub const PSCI_0_2_FN_CPU_ON: u32 = PSCI_0_2_FN_BASE + 3;
Expand All @@ -15,14 +14,47 @@ pub const PSCI_0_2_FN64_CPU_SUSPEND: u32 = PSCI_0_2_FN_BASE + PSCI_0_2_64BIT + 1
pub const PSCI_0_2_FN64_CPU_ON: u32 = PSCI_0_2_FN_BASE + PSCI_0_2_64BIT + 3;
pub const PSCI_0_2_FN64_MIGRATE: u32 = PSCI_0_2_FN_BASE + PSCI_0_2_64BIT + 5;

/// PSCI return values, inclusive of all PSCI versions.
#[derive(PartialEq, Debug)]
#[repr(i32)]
pub enum PsciError {
NotSupported = -1,
InvalidParams = -2,
Denied = -3,
AlreadyOn = -4,
OnPending = -5,
InternalFailure = -6,
NotPresent = -7,
Disabled = -8,
InvalidAddress = -9,
}

impl From<i32> for PsciError {
fn from(code: i32) -> PsciError {
use PsciError::*;
match code {
-1 => NotSupported,
-2 => InvalidParams,
-3 => Denied,
-4 => AlreadyOn,
-5 => OnPending,
-6 => InternalFailure,
-7 => NotPresent,
-8 => Disabled,
-9 => InvalidAddress,
_ => panic!("Unknown PSCI error code: {}", code),
}
}
}

/// arm,psci method: smc
/// when SMCCC_CONDUIT_SMC = 1
fn arm_smccc_smc(fn_id: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
fn arm_smccc_smc(func: u32, arg0: usize, arg1: usize, arg2: usize) -> usize {
let mut ret;
unsafe {
core::arch::asm!(
"smc #0",
inlateout("x0") fn_id => ret,
inlateout("x0") func as usize => ret,
in("x1") arg0,
in("x2") arg1,
in("x3") arg2,
Expand All @@ -32,7 +64,7 @@ fn arm_smccc_smc(fn_id: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
}

/// psci "hvc" method call
fn psci_hvc_call(func: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
fn psci_hvc_call(func: u32, arg0: usize, arg1: usize, arg2: usize) -> usize {
let ret;
unsafe {
core::arch::asm!(
Expand All @@ -46,110 +78,52 @@ fn psci_hvc_call(func: usize, arg0: usize, arg1: usize, arg2: usize) -> usize {
ret
}

fn psci_call(fn_id: usize, arg0: usize, arg1: usize, arg2: usize) -> Result<i32, PsciRetNo> {
fn psci_call(func: u32, arg0: usize, arg1: usize, arg2: usize) -> Result<(), PsciError> {
let ret = match axconfig::PSCI_METHOD {
"smc" => arm_smccc_smc(fn_id, arg0, arg1, arg2),
"hvc" | _ => psci_hvc_call(fn_id, arg0, arg1, arg2),
"smc" => arm_smccc_smc(func, arg0, arg1, arg2),
"hvc" => psci_hvc_call(func, arg0, arg1, arg2),
_ => panic!("Unknown PSCI method: {}", axconfig::PSCI_METHOD),
};

let retno = psci_errno_tran(ret as i32);
if retno == PsciRetNo::PsciRetSuccess {
Ok(0)
if ret == 0 {
Ok(())
} else {
Err(retno)
Err(PsciError::from(ret as i32))
}
}

/// Shutdown the whole system, including all CPUs.
pub fn system_off() -> ! {
info!("Shutting down...");
let _ = psci_call(PSCI_0_2_FN_SYSTEM_OFF as usize, 0, 0, 0);
psci_call(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0).ok();
warn!("It should shutdown!");
loop {
crate::arch::halt();
}
}

/// Starts a secondary CPU with the given ID.
/// When the CPU is started, it will jump to the given entry and set the
/// corresponding register to the given argument.
/// Power up a core. This call is used to power up cores that either:
///
/// PSCI v0.1
/// cpu entry_point: phys_addr(secondary_entry)
pub fn psci_cpu_on(cpuid: usize, entry_point: usize, arg: usize) -> i32 {
info!("Starting CPU {} ON ...", cpuid);
let err = psci_call(PSCI_0_2_FN64_CPU_ON as usize, cpuid, entry_point, arg);
match err {
Err(e) => {
error!("failed to boot CPU {} ({:?})", cpuid, e);
e as i32
}
Ok(_) => {
info!("Started CPU {}", cpuid);
0
}
/// * Have not yet been booted into the calling supervisory software.
/// * Have been previously powered down with a `cpu_off` call.
///
/// `target_cpu` contains a copy of the affinity fields of the MPIDR register.
/// `entry_point` is the physical address of the secondary CPU's entry point.
/// `arg` will be passed to the `X0` register of the secondary CPU.
pub fn cpu_on(target_cpu: usize, entry_point: usize, arg: usize) {
info!("Starting CPU {} ON ...", target_cpu);
let res = psci_call(PSCI_0_2_FN64_CPU_ON, target_cpu, entry_point, arg);
if let Err(e) = res {
error!("failed to boot CPU {} ({:?})", target_cpu, e);
}
}

pub fn psci_cpu_off(_cpuid: usize) {
/// Power down the calling core. This call is intended for use in hotplug. A
/// core that is powered down by `cpu_off` can only be powered up again in
/// response to a `cpu_on`.
pub fn cpu_off() {
const PSCI_POWER_STATE_TYPE_STANDBY: u32 = 0;
const PSCI_POWER_STATE_TYPE_POWER_DOWN: u32 = 1;
const PSCI_0_2_POWER_STATE_TYPE_SHIFT: u32 = 16;
let state: u32 = PSCI_POWER_STATE_TYPE_POWER_DOWN << PSCI_0_2_POWER_STATE_TYPE_SHIFT;
let _ = psci_call(PSCI_0_2_FN_CPU_OFF as usize, state as usize, 0, 0);
}

pub fn psci_errno_tran(errno: i32) -> PsciRetNo {
//EINVAL
let mut ret = -22;
let errno_tran = match errno {
0 => {
ret = 0;
PsciRetNo::PsciRetSuccess
}
// EOPNOTSUPP
-1 => {
ret = -95;
PsciRetNo::PsciRetNotSupported
}
-2 => {
ret = -22;
PsciRetNo::PsciRetInvalidParams
}
// EPERM
-3 => {
ret = -1;
PsciRetNo::PsciRetDenied
}
-4 => PsciRetNo::PsciRetAlreadyOn,
-5 => PsciRetNo::PsciRetOnPending,
-6 => PsciRetNo::PsciRetInternalFailure,
-7 => PsciRetNo::PsciRetNotPresent,
-8 => PsciRetNo::PsciRetDisabled,
-9 => {
ret = -22;
PsciRetNo::PsciRetInvalidAddress
}
_ => {
warn!("Unknown psci errno: {}", errno);
PsciRetNo::PsciRetInvalidParams
}
};
info!("return={}, {:?}", ret, errno_tran);
errno_tran
}

/// PSCI return values, inclusive of all PSCI versions
#[derive(PartialEq, Debug)]
pub enum PsciRetNo {
PsciRetSuccess = 0,
PsciRetNotSupported = -1,
PsciRetInvalidParams = -2,
PsciRetDenied = -3,
PsciRetAlreadyOn = -4,
PsciRetOnPending = -5,
PsciRetInternalFailure = -6,
PsciRetNotPresent = -7,
PsciRetDisabled = -8,
PsciRetInvalidAddress = -9,
psci_call(PSCI_0_2_FN_CPU_OFF, state as usize, 0, 0).ok();
}
6 changes: 1 addition & 5 deletions modules/axhal/src/platform/aarch64_qemu_virt/mp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,5 @@ pub fn start_secondary_cpu(cpu_id: usize, stack_top: PhysAddr) {
fn _start_secondary();
}
let entry = virt_to_phys(VirtAddr::from(_start_secondary as usize));
crate::platform::aarch64_common::psci::psci_cpu_on(
cpu_id,
entry.as_usize(),
stack_top.as_usize(),
);
crate::platform::aarch64_common::psci::cpu_on(cpu_id, entry.as_usize(), stack_top.as_usize());
}

0 comments on commit 325a09d

Please sign in to comment.