Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 添加新代码时内核中断(从未运行)_C_Assembly_Linux Kernel_Arm - Fatal编程技术网

C 添加新代码时内核中断(从未运行)

C 添加新代码时内核中断(从未运行),c,assembly,linux-kernel,arm,C,Assembly,Linux Kernel,Arm,我试图在用户空间和内核空间之间添加一些逻辑,特别是在ARM架构上 一个这样的边界似乎是在arch/arm/kernel/entry common.S中实现的vector\u swi例程。现在,我的大部分代码都是用C函数编写的,我想在vector\u swi的开头调用它 因此,我做了以下工作: ENTRY(vector_swi) sub sp, sp, #S_FRAME_SIZE stmia sp, {r0 - r12}

我试图在用户空间和内核空间之间添加一些逻辑,特别是在ARM架构上

一个这样的边界似乎是在
arch/arm/kernel/entry common.S
中实现的
vector\u swi
例程。现在,我的大部分代码都是用C函数编写的,我想在
vector\u swi
的开头调用它

因此,我做了以下工作:

ENTRY(vector_swi)
        sub     sp, sp, #S_FRAME_SIZE
        stmia   sp, {r0 - r12}                  @ Calling r0 - r12
 ARM(   add     r8, sp, #S_PC           )
 ARM(   stmdb   r8, {sp, lr}^           )       @ Calling sp, lr
 THUMB( mov     r8, sp                  ) 
 THUMB( store_user_sp_lr r8, r10, S_SP  )       @ calling sp, lr
        mrs     r8, spsr                        @ called from non-FIQ mode, so ok.
        str     lr, [sp, #S_PC]                 @ Save calling PC
        str     r8, [sp, #S_PSR]                @ Save CPSR
        str     r0, [sp, #S_OLD_R0]             @ Save OLD_R0
        zero_fp

#ifdef CONFIG_BTM_BOUNDARIES
        bl btm_entering_kernelspace    @ <--- My function
#endif
然而,当我添加一些额外的代码时,内核会进入崩溃重启循环

static int btm_enabled = 0;
asmlinkage inline void btm_entering_kernelspace(void)
{
        int cpu;
        int freq;
        struct acpu_level *level;
        if(!btm_enabled) {
                return;
        }
        cpu = smp_processor_id();
        freq = acpuclk_krait_get_rate(cpu);
        (void) cpu;
        (void) freq;
        (void) level;
        // --------- Added code ----------
        for (level = drv.acpu_freq_tbl; level->speed.khz != 0; level++) {
                if(level->speed.khz == freq) {
                        break;
                }
        }
}
尽管第一反应是责备添加代码的逻辑,但请注意,由于
btm_enabled
0
,因此不应执行任何代码

我通过添加
sysfs
条目来打印变量的值(删除添加的代码),进行了双重检查和三重检查,以确保启用了
btm_
0


有人能解释一下这里发生了什么或者我做错了什么吗?

第一个版本可能会编译成一条返回指令,因为它没有副作用。第二个需要加载
btm_enabled
,并在此过程中覆盖一个或两个系统调用参数

从汇编语言调用C函数时,需要确保可能修改的寄存器不包含所需的信息

要解决您的特定问题,您可以将代码更新为:

#ifdef CONFIG_BTM_BOUNDARIES
        stmdb   sp!, {r0-r3, r12, lr}  @ <--- New instruction
        bl btm_entering_kernelspace    @ <--- My function
        ldmia   sp!, {r0-r3, r12, lr}  @ <--- New instruction
#endif
#ifdef配置_BTM_边界

stmdb sp!,{r0-r3,r12,lr}@新代码可能会更改早期代码的寄存器分配,和/或编译器决定在检查/返回之前乐观地处理寄存器。或者简单地将一些寄存器保存/恢复到堆栈中,因为函数现在需要跨调用保存一些参数。如果在
vector_swi
中的该点上,关闭r0..r3和堆栈指针下的内存不是真正安全的,那么带有函数调用的第一个版本只是偶然工作的。我对Linux的ARM入口点还不太熟悉,无法判断ABI Compileiant函数调用在那里是否安全。啊,是的,所以我的猜测是对的,在那一点上,被调用的寄存器仍然保存着一些重要的东西?入口点已经将它们保存到堆栈中,但它使用它们而不重新加载,对吗?是的,大多数系统调用都使用它们而不重新加载。C函数不是自动生成用于保存和恢复寄存器的程序集吗?我查看了
objdump
中的10-15个函数,它们都是从
movip,sp开始的;按{r3,r4,…}
并以
ldmsp,{r3,r4,…}
结束。我猜我应该做的是将寄存器保存到堆栈上,调用我的函数,然后重新加载它们。由于我对汇编没有很好的理解,有没有办法让编译器为我生成这个汇编,这样我就可以查找它并将它手工写入
vector_swi
?只需在生成的vmlinux上使用
objdump-S
,或者使用任何您的输出即可。
#ifdef CONFIG_BTM_BOUNDARIES
        stmdb   sp!, {r0-r3, r12, lr}  @ <--- New instruction
        bl btm_entering_kernelspace    @ <--- My function
        ldmia   sp!, {r0-r3, r12, lr}  @ <--- New instruction
#endif