linux hwspinlock 学习

一、为什么需要 hwspinlock

在传统的 Linux SMP 系统中,自旋锁(spinlock)依赖于 共享内存 + 原子指令 实现,适用于:

  • 同一 OS

  • 同一 cache coherent 域

  • 同一 CPU 集群

然而,在以下场景中,普通 spinlock 已经不再适用:

  • 多 OS(Linux + RTOS / FW / SCP)

  • 多 die / 多 cluster(无 cache coherence)

  • Host CPU 与外设子系统(DSP / MCU)

  • SoC 内部通过 APB / AXI 互联的异构处理单元

这些系统之间 无法共享 Linux 的原子语义 ,但又需要访问 同一块共享资源或 共享内存 。 这正是 hwspinlock(硬件自旋锁) 存在的意义。


二、hwspinlock 的设计目标

Linux hwspinlock 的核心目标可以总结为三点:

  • 提供 OS 无关的互斥原语

  • 基于硬件寄存器实现排他访问

  • 统一 Linux 侧的使用接口

本质上,hwspinlock 是:

Linux 对"硬件互斥单元(Hardware Mutex / Spinlock)"的一层抽象


三、Linux hwspinlock 的整体架构

从软件栈角度看,hwspinlock 位于 设备驱动 层与通用内核接口之间

注册就是上register和unregister


四、hwspinlock 的核心数据结构

4.1 struct hwspinlock

语义说明:

  • lock保护 hwspinlock 内部状态的 Linux 自旋锁 → 注意:不是跨 OS 的锁

  • ops → 硬件相关的操作集(trylock / unlock)

  • priv → 指向 SoC 私有数据(寄存器基址、ID 等)


4.2 struct hwspinlock_ops

这是 hwspinlock 的 关键抽象层

  • Linux 不关心硬件如何实现

  • 只要求:

    • 能不能"抢到锁"

    • 如何"释放锁"


五、Linux 侧的使用接口

5.1 获取 hwspinlock

struct hwspinlock *hwlock;

hwlock = hwspin_lock_request_specific(id);

Linux 通常使用 编号(ID) 来标识一把硬件锁


5.2 加锁与解锁

hwspin_lock_timeout(hwlock, timeout); ``... ``hwspin_unlock(hwlock);

或非阻塞方式:

if (hwspin_trylock(hwlock)) { `` ... `` hwspin_unlock(hwlock); ``}

重要特性

  • hwspinlock 不会睡眠

  • 典型使用场景:

    • 中断上下文

    • 共享内存访问

    • mailbox / rpmsg / IPC 同步


六、hwspinlock 与 Linux spinlock 的本质区别

|----------|----------|--------------|
| 对比项 | spinlock | hwspinlock |
| 实现基础 | 原子指令 | 硬件寄存器 |
| 适用范围 | 单 OS | 多 OS / 多 die |
| cache 依赖 | 强 | 无 |
| 速度 | 极快 | 较慢(MMIO) |
| 典型用途 | 内核同步 | OS 间互斥 |

一句话总结:

hwspinlock 解决的是"系统边界外"的互斥问题


七、APB Spinlock 的硬件实现原理

7.1 APB Spinlock 的基本思想

APB spinlock 通常由一组 内存 映射寄存器 组成,例如:

SPINLOCK_BASE + 0x0 LOCK0 ``SPINLOCK_BASE + 0x4 LOCK1 ``SPINLOCK_BASE + 0x8 LOCK2 ...

每个寄存器代表 一把独立的硬件锁


7.2 加锁(trylock)& 解锁(unlock)机制

writel(0, lock_reg);

释放锁后,其他 master 才能重新获取。

当处理器使用hwspinlock的时候,需要通过SPINLOCK_STATUS_REG寄存器读取hwspinlock状态。

  • 读操作:读SPINLOCK_LOCK_REG返回0时,说明进入locked状态;再次读SPINLOCK_STATUS_REG该状态位,返回1,说明已经成为locked状态

  • 写操作:当spinlock处于locked状态时,写SPINLOCK_LOCK_REG为0可转化为unlocked状态,其他状态写操作均无效

  • reset操作:reset操作后,默认为unlocked

hwspinlock 状态
  • 当spinlock处于unlocked状态时,写0/1均无效

  • 当spinlock处于unlocked状态,读操作,返回0说明进入locked状态

  • 当spinlock处于locked状态时,写0可转换为unlocked状态

  • 当spinlock处于locked状态,写1无效

  • 当spinlock处于locked状态时,再次读该状态位,返回1,说明已经是locked状态

  • reset操作后默认为unlocked状态

当Free lock动作产生(即lock状态由locked变为unlocked时),即可产生中断

切换状态
  • SPINLOCKN_LOCK_REG(0~31)读0,进入locked状态

  • 执行应用代码,当前SPINLOCK_STATUS_REG对应位状态为1

  • SPINLOCKN_LOCK_REG(0~31)写0,进入unlocked状态,释放相应的spinlock


7.4 硬件层保证的是什么?

APB spinlock 硬件通常保证:

  • 同一时刻:

    • 只有一个 bus master 能持有锁
  • 锁状态:

    • 独立于 CPU cache

    • 独立于 OS

不保证

  • 死锁检测

  • owner 身份校验(有些 SoC 支持)


八、Linux hwspinlock 驱动如何对接 APB Spinlock

典型 APB spinlock 驱动做三件事:

  • 解析 设备树

    • 锁数量

    • 寄存器基址

  • 初始化 hwspinlock 实例数组

  • hwspinlock_init(&bank->locks[i]);

  • 实现 ops

  • .trylock = apb_hwspin_trylock, ``.unlock = apb_hwspin_unlock,

Linux hwspinlock core 完全不知道:

  • APB / AXI

  • 寄存器布局

  • SoC 细节

这就是抽象层的价值。


九、hwspinlock 的典型使用场景

  • Linux ↔ RTOS 共享 ringbuf

  • Linux ↔ SCP 共享 mailbox

  • 多 die 共享 SRAM

  • remoteproc / rpmsg 的全局同步

  • 非一致性内存上的 allocator(genpool / bitmap)

hwspinlock 适合"粒度粗、时间短、访问频率低"的互斥


十、总结

Linux hwspinlock 是一种 面向异构系统的同步机制

  • 上层:统一 Linux API

  • 中层:hwspinlock core 框架

  • 底层:SoC 私有硬件实现(如 APB spinlock)

它并不是为了替代 spinlock,而是解决:

Linux 原子语义无法覆盖的系统边界问题

相关推荐
FJW0208142 小时前
使用HAProxy实现动静分离
linux·服务器
近津薪荼2 小时前
优选算法——滑动窗口1(单调性)
c++·学习·算法
头发还没掉光光2 小时前
Linux 高级 IO 深度解析:从 IO 本质到 epoll全面讲解
linux·服务器·c语言·c++
爱装代码的小瓶子2 小时前
【C++与Linux基础】进程如何打开磁盘文件:从open()到文件描述符的奇妙旅程(更多源码讲解)
linux·开发语言·c++
RisunJan2 小时前
Linux命令-logout(安全结束当前登录会话)
linux·运维·安全
2301_815357702 小时前
如何将SSM项目通过tomcat部署到Linux云服务器上?
linux·服务器·tomcat
齐鲁九零2 小时前
【AI推荐】推荐适合学英语的美剧
学习
lxl13072 小时前
学习C++(6)日期类的实现+取地址运算符重载
开发语言·c++·学习
ICT董老师2 小时前
在Linux中,有多种命令可以向指定文件添加文本
linux·运维·服务器