硬件上:
armv6 有 6个 R13
R13_usr 和 R13_sys 是同一个
还有 R13_svc R13_abt R13_und R13_irq R13_fiq
软件上
linux boot时有一个栈
linux 各种异常处理有栈(5个异常模式,1个system模式)
对应多少个栈?
svc mode 对应每个进程有一个栈?
irq mode 是固定的栈?
abort 呢? und 呢 ? fiq 呢?
system mode 呢?
linux 在 user mode 时 有栈 , (应用程序的栈,每个应用程序有一个栈,有N个应用程序)
boot的栈不管,没啥意思
从线程和异常来说事
1. 线程分类
2. 异常分类
每个线程有两个栈,一个内核(svc)栈,一个用户栈。
异常时,有临时栈(12字节)(irq und abt fiq),然后有长期栈(svc,即用户的内核栈)
临时栈
临时栈的地址及大小
地址 : 位于 全局变量 static struct stack stacks[NR_CPUS]; 中
大小 :12 字节
BOOT过程
boot时的栈
boot栈的地址及大小
地址 : init_stack - init_stack+0x1000
大小 : 4KB
从stext到start_kernel , 没用栈???
从start_kernel 开始, 走在 svc mode???,
start_kernel 运行时的栈, 是 链接出来的(和init_stack 有关),4KB大小
https://blog.csdn.net/u011011827/article/details/116056620
线程分类
idle 内核线程的一个内核栈
内核栈的地址及大小
栈位置: X - X+0x2000 // "slab task_struct" 中的 stack成员的值为X
栈大小: 8KB
idle 进程的 TCB 分成了 两块
struct task_struct init_task
void *stack; // 用于存放 对应的 thread_info 的 地址
struct thread_info init_thread_info
.task = &init_task // 对于存放 对应的 task_struct 的地址
栈位置: slab task_struct 中的 stack成员的值为栈顶X(X->X+STACK_SIZE为整个栈)
栈大小: 由 arch/arm/include/asm/thread_info.h 中的 THREAD_SIZE 决定 // 8KB 或者16KB
// CONFIG_KASAN=n : 8KB
// CONFIG_KASAN=y : 16KB
init 内核线程的一个内核栈及init用户线程的一个用户栈和内核栈
内核栈的地址及大小
栈位置: X - X+0x2000 // "slab task_struct" 中的 stack成员的值为X
栈大小: 8KB
用户栈的地址及大小
栈位置: 0xBE80 0000 - 0xBF00 0000
栈大小: 8MB
用户栈的伸缩对于应用程序来说是透明的,应用程序不需要自己去管理栈,这是操作系统提供的功能。
应用程序在刚刚启动的时候(由fork()系统调用复制出新的进程),新的进程其实并不占有任何栈的空间。
当应用程序中调用了函数需要压栈时,会触发一个page fault,内核在处理这个异常里会发现进程需要新的栈空间,于是建立新的VMA并映射内存给用户栈
https://www.tiehichi.site/2020/10/22/Linux%E8%BF%9B%E7%A8%8B%E6%A0%88%E7%A9%BA%E9%97%B4%E5%A4%A7%E5%B0%8F/
栈位置: 0xC0000000-0x01000000 ( 最高处)
load_elf_binary
retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP), executable_stack);
#define CONFIG_PAGE_OFFSET 0xC0000000
#define SZ_16M 0x01000000
#define TASK_SIZE (UL(CONFIG_PAGE_OFFSET) - UL(SZ_16M))
#define TASK_SIZE_26 (UL(1) << 26)
#define STACK_TOP ((current->personality & ADDR_LIMIT_32BIT) ? TASK_SIZE : TASK_SIZE_26)
栈位置: 0xC0000000-0x01000000 ( 最高处)
栈大小: 8MB
ulimit -a看到系统对当前进程的栈size进行了限制,大部分是8M的限制
ulimit -s来修改栈的大小,可以扩充到100M的大小
init_task->signal->rlim
[RLIMIT_STACK] = { _STK_LIM, RLIM_INFINITY },
_STK_LIM即为当前系统中,进程用户栈的虚拟地址空间上限
#define _STK_LIM (8*1024*1024)
异常分类
异常有7个
5+1(rst)+1(swi)
5:
vector_stub 中使用临时栈,然后切换到 swi mode , 使用 swi的栈
1(rst):
直接swi err0
1(swi):
直接使用 swi 的栈
arch/arm/kernel/setup.c
136 /*
137 * Cached cpu_architecture() result for use by assembler code.
138 * C code should use the cpu_architecture() function instead of accessing this
139 * variable directly.
140 */
141 int __cpu_architecture __read_mostly = CPU_ARCH_UNKNOWN;
142
143 struct stack {
144 u32 irq[3];
145 u32 abt[3]; //对应 dabt 和 pabt 异常
146 u32 und[3];
147 u32 fiq[3];
148 } ____cacheline_aligned; // 对应5个异常及其对应的 vector_stub , vector_stub 中 这12个字节 用于 临时 stack .
149
150 #ifndef CONFIG_CPU_V7M
151 static struct stack stacks[NR_CPUS];
152 #endif
start_kernel
setup_arch
setup_processor
cpu_init
setup stacks for re-entrant exception handlers
struct stack *stk = &stacks[cpu];
556 __asm__ (
557 "msr cpsr_c, %1nt"
558 "add r14, %0, %2nt"
559 "mov sp, r14nt"
560 "msr cpsr_c, %3nt"
561 "add r14, %0, %4nt"
562 "mov sp, r14nt"
563 "msr cpsr_c, %5nt"
564 "add r14, %0, %6nt"
565 "mov sp, r14nt"
566 "msr cpsr_c, %7nt"
567 "add r14, %0, %8nt"
568 "mov sp, r14nt"
上一篇:OK6410A 开发板 (八) 120 linux-5.11 OK6410A cache 配置
下一篇:OK6410A 开发板 (八) 118 linux-5.11 OK6410A arm异常原因及linux应用场景及结果
推荐阅读最新更新时间:2024-11-08 22:30
设计资源 培训 开发板 精华推荐
- AM1/4S-4812SH30Z 12V 0.25 瓦 DC/DC 转换器的典型应用
- EP5358HUI 600mA 同步降压稳压器集成电感器的典型应用
- 使用 Analog Devices 的 LT1357 的参考设计
- Spark Analyzer :开源的无线USB PD电源、具备功耗分析
- EV-ADUCM320QSPZ,基于 ADuCM320 双芯片堆栈片上系统的开发系统,专为固定波长激光光学模块应用的诊断控制而设计
- 使用 Analog Devices 的 LTC2862ACS8-1 的参考设计
- 使用 ON Semiconductor 的 LC7958NC 的参考设计
- 用于基本连接的 LT6656BIDC-2.5、2.5V 电压基准的典型应用
- 使用 Analog Devices 的 LTC3803ES6-5 的参考设计
- 使用 Silicon Labs 的 Si2704-A10-GM 的参考设计