Arm 在用户模式下恢复Thumb状态

Arm 在用户模式下恢复Thumb状态,arm,thumb,Arm,Thumb,我正在编写线程切换代码,内核将相关状态转储到内存中,但实际的线程切换完全发生在用户模式下 这很好,除非抢占点出现在Thumb If-Then(IT)块中。在这种情况下,我无法确定如何恢复ITSTATE(即CPSR的位[15:10]和[26:25]),因为这些位是用户RAZ/WI,并且在任何情况下,考虑到ITSTATE的语义,它可能没有意义 在不陷入内核的情况下,恢复这种状态的正确方法是什么(如果有的话) 我曾考虑过倒带执行并继续执行IT指令,但除了非常沉重之外,我不确定这是否总是可能的 编辑:对

我正在编写线程切换代码,内核将相关状态转储到内存中,但实际的线程切换完全发生在用户模式下

这很好,除非抢占点出现在Thumb If-Then(IT)块中。在这种情况下,我无法确定如何恢复ITSTATE(即CPSR的位[15:10]和[26:25]),因为这些位是用户RAZ/WI,并且在任何情况下,考虑到ITSTATE的语义,它可能没有意义

在不陷入内核的情况下,恢复这种状态的正确方法是什么(如果有的话)

我曾考虑过倒带执行并继续执行IT指令,但除了非常沉重之外,我不确定这是否总是可能的

编辑:对ARMv7-A

架构感兴趣*,CPSR中的任何执行状态位都不能在任何模式下读取或写入(只有特权模式下的CPSR.E位除外,甚至不推荐使用)。在正常执行之外修改它们的唯一方法是通过异常返回中的SPSR,它预期直接返回到IT块内的相关指令

正如您所提到的,重新启动整个IT块既不实用也不安全,这主要是由于内存访问——而在大多数情况下,您可能会静态分析指令以反转任何寄存器修改,任何共享内存都可能意味着重复加载会返回不同的值,或者一个重复的存储可能会破坏另一个同时读取和修改原始值的进程。对于内存映射的I/O,由于各种原因,意外地重复任何访问都可能是危险的

另一个可能的想法是基于SPSR的ITSTATE和返回地址的剩余指令JIT新的IT块,因为Thumb-2意味着您有
LDR PC,
从任何地方返回原始代码,寄存器保持完整。然而,即使这样,如果条件指令执行任何与PC相关的计算,也会破坏一些东西


*在任何具有CPSR并支持Thumb-2的设备上,无论如何,CPSR在异常条目时自动存储在堆栈上,并在异常返回时从堆栈恢复。我可能看不出您的确切问题,但通常情况下,您不需要为该上下文切换工作而做任何事情-假设它是在异常中完成的,您只需在堆栈上存储剩余寄存器,切换堆栈指针,取消堆栈剩余寄存器,然后从异常返回即可。。。我也不知道您使用的确切体系结构是什么,但这里有一个用于ARMv7-M(Cortex-M3/M4)的非常简单的上下文切换:

除了内存之外,您还必须撤消任何寄存器操作,因为它们将保存在它的中间块中。即使这样似乎也很困难。特别是当寄存器可能被mid IT块破坏,而您不知道它是什么时。我不认为破坏寄存器是一个问题,因为您不需要精确地重建原始寄存器状态,而是任何状态,当应用IT指令时,生成当前状态。可能在内存访问的情况下,最好是向前滚动。在这两种情况下,这都需要一个ISA模拟器,但这并不理想。他试图从用户空间实现这一点。我想你说的是异常模式。我想知道
setjmp/longjmp
如何在Cortex-M上工作?我猜函数调用永远不会出现在条件块的中间。我认为只有协作调度才能在Cortex-M上工作。setjmp()和.longjmp()的工作原理与异常几乎相同,但在异常情况下自动完成的寄存器堆叠/取消堆叠是手动完成的。这是来自newlib的代码——CPSR没有修改。Cortex-M可以有先发制人的调度——我链接的项目是一个完全先发制人的调度程序,用于这种芯片(是的,我的问题是一种陈述。你需要处理
CPSR
(或者Cortex-M称它为什么)对于抢占式调度程序,因此不能使用用户模式。对于协作式调度,您可以按
setjmp/longjmp
执行,并将上下文切换限制为非IT块,以避免出现问题。