Linux kernel PSCI驱动10分钟讲清楚

Linuxkernel中,PSCI其实是一个容易被误认成内核模块的接口规范 ------它既不是硬件模块,也不是内核里的某个 .ko,而是 ARM 官方定义的电源管理接口标准(Power State Coordination Interface) ,本质上是一份"合同":规定非安全世界(Linux 内核跑在 EL1)如何通过 SMC 指令去调用运行在 EL3 安全监控模式下的固件(典型就是 ARM Trusted Firmware,ATF),由固件代理执行真正触碰硬件寄存器的电源操作。

一、PSCI 到底是个什么东西

ARM 官方文档 DEN0022 对它的定位是:为多监督系统(OS、Hypervisor、Trusted OS 并存)之间协调电源控制提供标准接口。它要解决的核心痛点是:

  • 多核 SoC 里,谁来负责把某个核真正断电?OS 不能直接写电源控制寄存器(那些寄存器在 EL3 安全世界)

  • 不同 SoC 厂商各自实现一套 CPU 启停逻辑,导致 OS 移植困难

  • 系统级关机/复位需要协调所有核进入已知状态

PSCI 给出的答案是:统一函数 ID + SMC 指令。OS 只需要调用标准函数,不用关心底层是 ATF 直接操作硬件,还是通过 SCP(System Control Processor)间接操作。

规范定义的主要函数:

函数 功能
PSCI_CPU_ON 启动一个从核(secondary boot / hotplug 上线)
PSCI_CPU_OFF 关闭调用者所在核(hotplug 下线)
PSCI_CPU_SUSPEND 把核放入深睡/retention 状态(cpuidle 用)
PSCI_SYSTEM_OFF 系统关机 (对应 poweroff
PSCI_SYSTEM_RESET 系统复位 (对应 reboot
PSCI_MIGRATE 迁移 Trusted OS 上下文

💡 关键点:PSCI 不负责 DVFS(调频调压)和外设电源管理,那些归 SCMI 或其他框架管。

二、它是怎么被调用的:SMC 指令跨异常级

PSCI 调用本质上是一次跨异常级别的上下文切换

复制代码
Linux 内核 (EL1)
   │ 执行 smc #0 指令
   ▼
触发同步异常,CPU 切换到 EL3
   │
   ▼
Secure Monitor (EL3, 常驻固件 ATF BL31)
   │ 解析 x0 中的 Function ID
   │ 路由到 PSCI 服务处理
   ▼
执行平台特定的断电/复位操作
   │
   ▼
返回到调用者(PSCI_SYSTEM_OFF 不返回)

调用约定(SMCCC):

  • x0 :Function ID,比如 PSCI_0_2_FN_SYSTEM_OFF = 0x84000008

  • x1~x3:参数

  • x0(返回):状态码

内核里发起调用的代码非常直白(drivers/firmware/psci/psci.c):

复制代码
#define PSCI_0_2_FN_SYSTEM_OFF   PSCI_0_2_FN(8)

static void psci_sys_poweroff(void)
{
    invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
}

invoke_psci_fn 根据设备树里 "method" 属性决定是用 smc #0 还是 hvc #0 陷入 EL3。

三、ZynqMP:完整链路

Xilinx 官方 wiki 明确说明:ZynqMP 的 ATF 实现了 PSCI 1.0 标准 ,并且所有 PSCI 电源管理操作最终都通过 **IPI(Inter-Processor Interrupt)转发给 PMU Firmware(PMUFW)**​ 执行。

具体到 SYSTEM_OFF,ATF 这边的实现在 plat/xilinx/zynqmp/plat_psci.c

复制代码
zynqmp_system_off()                    // ATF 里的 PSCI 平台回调
   │
   ▼
pm_system_shutdown(PMF_SHUTDOWN_TYPE_SHUTDOWN,
                   pm_get_shutdown_scope())   // 通过 IPI 发到 PMU
   │
   ▼
PMU Firmware                            // 运行在 ZynqMP 内置的 PMU 上
   │
   ▼
实际操作硬件:拉低 PMIC 使能脚 / 切断 PS 域电源

所以当用户敲下命令: shutdown -h now时,在 ZynqMP 上的精确表述应该是:

复制代码
shutdown -h now
   ↓
reboot(LINUX_REBOOT_CMD_POWER_OFF)          [kernel/reboot.c]
   ↓
kernel_power_off()
   ↓
machine_power_off()                         [arch/arm64/kernel/reboot.c]
   ↓
psci_sys_poweroff()                         [drivers/firmware/psci/psci.c]
   ↓  smc #0
   ↓
ATF BL31 的 PSCI 服务 (EL3)                 [arm-trusted-firmware]
   ↓  zynqmp_system_off()
   ↓  通过 IPI 发送 PMU 命令
   ↓
PMU Firmware                                [ZynqMP 内置 PMU 上运行]
   ↓
操作 PMIC / 电源域 → 整机断电

五、实际意义

理解了 PSCI 是"接口"而非"模块",对我们开发有几个直接指导:

  1. 你想在关机时保存配置到 EEPROM :仍然应该挂 reboot_notifier 或驱动的 .shutdown 回调(上一轮讲的),不要试图在 PSCI 层做------PSCI 已经陷入 EL3,回到 Linux 上下文时系统马上就断电了,没有机会写 I2C

  2. ZynqMP 上真正的"断电动作"在 PMUFW 里 :如果你的设备关机后没有完全断电(比如只是 PS 域下了但 PL 还在跑),要去看 PMUFW 的配置和 zynqmp_system_off() 的实现,确认 shutdown scope 是否设对了。Xilinx 在 2018 年的提交里允许通过 pm_system_shutdown() API 动态设置 shutdown scope(默认是 system 级)

  3. 调试 PSCI 调用 :可以在 ATF 里开启 PSCI 的 log,或者在 Linux 侧 cat /sys/firmware/devicetree/base/psci/ 查看 PSCI 版本和方法(smc/hvc)

  4. ATF 源码位置 :Xilinx 的 ATF 在 GitHub - Xilinx/arm-trusted-firmware: ARM Trusted Firmware · GitHub ,ZynqMP 平台 PSCI 实现集中在 plat/xilinx/zynqmp/plat_psci.cplat/xilinx/zynqmp/pm_service/ 目录下


简单收一句:PSCI 是 ARM 定的"电源操作合同",Linux 是客户端,ATF 是服务端,PMUFW 是 ZynqMP 上的最终执行者。你做关机流程定制时,写配置保存逻辑在内核侧(reboot notifier),真正的断电动作是 PMUFW 通过 IPI 触发的------这两层不要搞混。

相关推荐
琥珀色糖4 小时前
Linux守护进程
linux·终端·守护进程·会话·进程组
开心大爆炸7 小时前
xrdp 连接 登录对话框输入密码后闪退
linux·运维·服务器
oushaojun28 小时前
大厂 C++ 面试:深度剖析 Linux Signal 信号机制(转)
linux
苏生Susheng9 小时前
【软件实施】Linux系统Shell脚本教程
linux·运维·服务器·chrome·spring boot·学习·实施
Ruiery9 小时前
Linux 6.6内核 IOMMU 深度解析(七):DMA API 与 IOMMU 集成 — 从 dma_map_single 到 iommu_map
linux·运维·服务器
分支预测失败9 小时前
RISC-V AIA 中断架构实战:从 PLIC 到 APLIC 与 IMSIC 的迁移
linux·后端
GeW9 小时前
RHCE学习拿证计划:锁定核心考点,实现备考效率最大化
linux
snow@li9 小时前
服务器运维:Alibaba Cloud Linux 4 LTS 64位 根目录全景深度解析文章
linux·运维·服务器
苏生Susheng10 小时前
【软件实施】Linux企业运维常用命令手册
java·linux·运维·服务器·springboot·springcloud·软件实施
额额额对了10 小时前
Linux 进程间通信(IPC)核心机制:消息队列、共享内存与信号量详解
linux·网络·网络协议