添加新代码(从未运行)的内核中断
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了添加新代码(从未运行)的内核中断相关的知识,希望对你有一定的参考价值。
我试图在用户空间和内核空间之间的边界添加一些逻辑,特别是在ARM体系结构上。
其中一个边界似乎是在vector_swi
实施的arch/arm/kernel/entry-common.S
例程。现在,我的大部分代码都是用C函数编写的,我想在vector_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;
}
但是,当我添加一些额外的代码时,内核进入崩溃重启循环。
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
,因此不应执行任何操作。
我进行了双重检查和三重检查以确保btm_enabled
是0
,通过添加一个sysfs
条目来打印出变量的值(删除了添加的代码)。
有人可以解释这里发生了什么,或者我做错了什么?
答案
第一个版本可能只编译为返回指令,因为它没有副作用。第二个需要加载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
新指令存储将r0-r3,r12和lr寄存到堆栈中,并在函数调用后恢复它们。这些是C函数允许修改的唯一寄存器,这里保存r12是不必要的,因为它没有使用它的值,但这样做可以保持堆栈按照ABI的要求进行8字节对齐。
以上是关于添加新代码(从未运行)的内核中断的主要内容,如果未能解决你的问题,请参考以下文章
结合中断上下文切换和进程上下文切换分析Linux内核的一般执行过程