修改代码内存和让处理器执行新指令,是两件有关联但不等价的事。软件断点、动态代码与热补丁都会遇到这个问题。
数据写入与指令获取是两条路径
处理器通过数据访问路径写入指令字节,再通过指令获取路径执行代码。根据架构能力、缓存属性与系统配置,写入后可能需要数据缓存清理、指令缓存失效以及相应同步操作。不能从普通数据读回正确,直接推导出所有 CPU 都将执行新指令。
区分可见性、完成性与执行上下文
缓存维护和屏障分别解决不同的问题。DSB 与 ISB 的含义不同,不能互相替代。具体维护范围、共享域与操作顺序应依据架构手册和操作系统提供的代码同步接口,而不是复制一段汇编就认为适用于所有系统。
修改代码字节
↓
按架构要求完成缓存维护与屏障
↓
协调可能执行该代码的其他 CPU
↓
在正确的上下文中恢复执行SMP 还需要考虑远端 CPU
在多核环境里,本核完成同步并不自动证明远端核已丢弃先前获取的指令。系统可能通过核间中断、上下文同步事件或暂停相关 CPU 的机制来协调。某些实现并不要求每个核重复完全相同的缓存维护序列,关键是满足架构要求的跨核保证。
调试路径与普通更新路径可能不同
如果调试模式已经控制了其他 CPU,代码更新可能在恢复阶段统一同步;普通运行态的更新接口则可能主动协调其他核。比较两条路径时,应追踪完整的停止到恢复过程,不要只检查写内存的那一处。
看见新字节,不代表已经建立执行新指令所需的全部条件。