如何使用C程序将ARM处理器置于不同模式?

Rah*_*hul 1 arm device-driver linux-kernel

我正在经历不同的ARM处理器模式.我想在处于不同模式时检查处理器状态(例如:寄存器值).

那么有人可以帮我找出样本代码以使处理器处于不同的模式吗?

例如,我找到了未定义模式的代码: asm volatile (".short 0xffff\n");

art*_*ise 7

如果您希望从用户空间测试模式,这是一个难题.如果系统中没有FIQ外围设备,则可能无法进入FIQ模式.您的系统可能根本不使用监控模式等.要进入中止模式,您可以使用无效指针或使用.但是,如果没有内核的帮助,从用户空间回答所有模式切换将是书本(或不可能).使用/ proc/ sys文件创建测试模块并使用以下技术实现内核代码将是最直接的方法.mmap

您应该知道并非所有模式切换都允许.例如,除非通过异常机制,否则您可能永远不会从用户模式切换到任何其他模式.另一个问题是每个ARM模式都有寄存器.其中一个是非常重要的sp(或堆栈指针)和lr(或链接寄存器),它们是'C'代码的基础.

使用内联汇编程序的宏来绑定测试片段通常比使用函数调用更安全.测试代码不得调用外部例程.这可能很困难,因为使用浮点等可能导致编译器插入隐藏的子例程调用.您应该检查生成的汇编程序并为其他人提供注释.

 /* Get the current mode for restoration. */
 static inline unsigned int get_cpsr(void)
 {
     unsigned int rval;
     asm (" mrs %0, cpsr\n" : "=r" (rval));
     return rval;
 }
Run Code Online (Sandbox Code Playgroud)

您可以将其放在头文件中.编译器将内联代码,因此,您只需将msr指令放在例程中.

要更改模式,请使用定义,

 /* Change the mode */
 #define change_mode(mode) asm("cps %0" : : "I"(mode))
Run Code Online (Sandbox Code Playgroud)

Tangr有正确的模式定义,

#define MODE_USR        0x10   /* Never use this one, as there is no way back! */
#define MODE_FIQ        0x11   /* banked r8-r14 */
#define MODE_IRQ        0x12
#define MODE_SVC        0x13
#define MODE_MON        0x16
#define MODE_ABT        0x17
#define MODE_UND        0x1B
#define MODE_SYS        0x1F   /* Same as user... */
Run Code Online (Sandbox Code Playgroud)

您还需要恢复以前的模式,

#define restore_mode(mode) \
     mode &= 0x1f; \
     asm(" msr cpsr, %0\n" : : "r"(mode) : "cc")
Run Code Online (Sandbox Code Playgroud)

把它放在一起如下,

  void test_abort(void)
  {
     unsigned int old_mode = get_cpsr() & 0x1f;
     change_mode(MODE_ABT);
     /* Your test code here... must not call functions. */
     restore_mode(old_mode);
  }
Run Code Online (Sandbox Code Playgroud)

这直接回答了你的问题.但是,由于所有困难,编写汇编程序以实现测试通常更容易.我相信您正在尝试利用现有的Linux代码来测试所有模式.这不是ARM-Linux的设计目标,如果没有修改源代码,将很难实现,并且如果是这样的话,将非常难以实现系统特定的.