Cod*_*Now 8 c arm linux-kernel
问题:
为什么在创建内核堆栈的"底部"时保留8个字节?
背景:
我们知道struct pt_regs并thread_info共享相同的2个连续页面(8192个字节),pt_reg位于较高端和thread_info较低端.但是,我注意到这两个页面的最高地址保留了8个字节:
在arch/arm/include/asm/threadinfo.h中
#define THREAD_START_SP (THREAD_SIZE - 8)
Run Code Online (Sandbox Code Playgroud)
这样,您thread_info只需通过读取堆栈指针和屏蔽掉THREAD_SIZE位来访问结构(否则SP最初将在下一个THREAD_SIZE块上).
static inline struct thread_info *current_thread_info(void)
{
register unsigned long sp asm ("sp");
return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
}
Run Code Online (Sandbox Code Playgroud)
八个字节来自ARM调用约定,SP需要8字节对齐.
更新: AAPCS 5.2.1.1声明:
进程只能访问(用于读取或写入)由[SP,stack-base-1]分隔的整个堆栈的闭合间隔(其中SP是寄存器r13的值).
由于堆栈是全降序的
THREAD_START_SP (THREAD_SIZE - 8)
Run Code Online (Sandbox Code Playgroud)
可能会通过非法访问下一页(分段错误)来强制执行此要求.
为什么在创建内核堆栈时在“底部”保留8个字节?
堆栈和用户寄存器需要对齐到8字节。这只会使事情变得更加高效,因为许多 ARM 都有 64 位总线,并且内核堆栈上的操作(例如ldrd和strd)可能有这些要求。您可以在宏中看到保护usr_entry。具体来说,
#if defined(CONFIG_AEABI) && (__LINUX_ARM_ARCH__ >= 5) && (S_FRAME_SIZE & 7)
#error "sizeof(struct pt_regs) must be a multiple of 8"
#endif
Run Code Online (Sandbox Code Playgroud)
ARMv5(架构版本5)添加了ldrd和strd指令。这也是 EABI 版本内核(相对于 OABI)的要求。因此,如果我们在堆栈上保留任何内容,它必须是 8 的倍数。
对于最上面的帧,我们可能想看一下以前的数据。为了不经常检查堆栈是否在 8K 范围内,保留了额外的条目。具体来说,我认为信号需要查看堆栈。