
一、为什么需要 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 原子语义无法覆盖的系统边界问题