历史上的今天
今天是:2025年01月20日(星期一)
2020年01月20日 | ARMv8 Linux内核异常处理过程分析
2020-01-20 来源:eefocus
1.1 Linux内核异常处理相关文件
Linux内核中,异常处理主要由两个文件完成,entry.S和traps.c,当然还有一些其它异常处理函数分布于fault.c, memory.c等等。entry.S包含异常的入口、进入异常处理C函数前的压栈、退出C函数前的出栈、一些fork函数相关的处理代码(暂不分析)、任务切换汇编处理过程(cpu_switch_to函数,暂不分析)。traps.c主要包含异常处理C函数。
本文主要分析entry.S,对于traps.c作简要介绍。
1.2 执行kernel_entry之前的栈

1.3 执行kernel_entry时的栈

1.4 执行kernel_exit 时的栈

1.5 entry.s代码分析
/*
* Low-level exception handling code
*
* Copyright (C) 2012 ARM Ltd.
* Authors: CatalinMarinas * WillDeacon * * This program is free software; you canredistribute it and/or modify * it under the terms of the GNU General PublicLicense version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope thatit will be useful, * but WITHOUT ANY WARRANTY; without even theimplied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULARPURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNUGeneral Public License * along with this program. If not, see */ #include #include #include #include #include #include #include #include /* * Bad Abort numbers *----------------- */ #defineBAD_SYNC 0 #defineBAD_IRQ 1 #defineBAD_FIQ 2 #defineBAD_ERROR 3 //根据该结构体内容 /* structpt_regs { union { struct user_pt_regs user_regs;//结构体user_pt_regs和结构体pt_regs内容一样 struct { //共用体存储31个通用寄存器,外加sp,pc,pstate三个特殊寄存器 //该结构体用于异常处理的压栈弹栈操作 u64 regs[31]; u64 sp; u64 pc; u64 pstate; }; }; u64 orig_x0; u64 syscallno; }; */ //S_FRAME_SIZE定义在asm-offsets.c中,DEFINE(S_FRAME_SIZE,sizeof(structpt_regs)); //即结构体pt_regs的大小,结构体pt_regs的定义见上面 //S_LR定义:DEFINE(S_LR,offsetof(structpt_regs, regs[30])); //即31号寄存器在结构体pt_regs中的偏移量 //阅读以下内容请参考图1 和图2 .macro kernel_entry,el, regsize = 64 sub sp,sp, #S_FRAME_SIZE - S_LR // room for LR,SP, SPSR, ELR,见图2中sp'指向的位置 .if regsize== 32 mov w0,w0 // zero upper 32bits of x0 .endif /* *.macro push,xreg1, xreg2 //压栈两个寄存器 *stp xreg1,xreg2, [sp, #-16]! //注意!!!push指令也改变sp的值!!! *.endm */ push x28,x29 //进行压栈操作,push也是一个宏定义,因为ARMv8没有push指令,用stp代替 push x26,x27 push x24,x25 push x22,x23 push x20,x21 push x18,x19 push x16,x17 push x14,x15 push x12,x13 push x10,x11 push x8,x9 push x6,x7 push x4,x5 push x2,x3 push x0,x1 //此时sp指向位置见图2中sp'' .if el== 0 //如果异常级是el0,把el0的sp栈指针给x21寄存器 mrs x21,sp_el0 .else add x21,sp, #S_FRAME_SIZE //如果异常级不是el0,把sp指针指向的地方加上pt_regs大小后的地址放入x21, //即指向没进入kernel_entry函数钱的sp指向的位置,见图2中x21指向的地址 .endif mrs x22,elr_el1 //把el1的lr寄存器给x22 mrs x23,spsr_el1 //把spsr给x23 stp lr,x21, [sp, #S_LR] //把lr,x21寄存器存入sp+S_LR指向的地方 stp x22,x23, [sp, #S_PC] //把lr,存入sp+s_PC指向的位置,用于异常返回 /* *Set syscallno to -1 by default (overridden later if real syscall). */ .if el== 0 mvn x21,xzr str x21,[sp, #S_SYSCALLNO] .endif /* *Registers that may be useful after this macro is invoked: * *x21 - aborted SP *x22 - aborted PC *x23 - aborted PSTATE */ .endm .macro kernel_exit,el, ret = 0 //把此时sp(即图2中sp'')+S_PC位置处开始的16字节内容分别给x21,x22 //即把栈中存的x21和x22内容取出来 ldp x21,x22, [sp, #S_PC] // load ELR,SPSR .if el== 0 ldr x23,[sp, #S_SP] // load return stackpointer,取出 .endif .if ret ldr x1,[sp, #S_X1] // preserve x0(syscall return),如果ret=1,则保存x0,用于系统调用,暂不分析 add sp,sp, S_X2 .else pop x0,x1 //如果ret=0,弹出x0,x1 .endif pop x2,x3 // load therest of the registers pop x4,x5 pop x6,x7 pop x8,x9 msr elr_el1,x21 // set up the returndata,把前面弹出的x21,x22分别赋值给elr_el1,spsr_el1 msr spsr_el1,x22 .if el== 0 msr sp_el0,x23 .endif pop x10,x11 pop x12,x13 pop x14,x15 pop x16,x17 pop x18,x19 pop x20,x21 pop x22,x23 pop x24,x25 pop x26,x27 pop x28,x29 ldr lr,[sp], #S_FRAME_SIZE - S_LR // load LR andrestore SP,把lr弹出 eret //return to kernel,异常返回,该指令会把lr给pc,完成跳转 .endm .macro get_thread_info,rd mov rd,sp and rd,rd, #~((1 << 13) - 1) // top of 8Kstack .endm /* * These are the registers used in the syscallhandler, and allow us to * have in theory up to 7 arguments to afunction - x0 to x6. * * x7 is reserved for the system call number in32-bit mode. */ sc_nr .req x25 // number of system calls scno .req x26 // syscall number stbl .req x27 // syscall table pointer tsk .req x28 // current thread_info /* * Interrupt handling. */ .macro irq_handler ldr x1,handle_arch_irq mov x0,sp blr x1 .endm .text /* * Exception vectors. */ .macro ventry label //这里是2^7对齐,即对齐到内存地址的0x80 .align 7 b label .endm .align 11 /*ENTRY也是一个宏,定义在include/linkage.h中 *#ifndef ENTRY *#define ENTRY(name) *.globl name; *ALIGN; *name: *#endif */ ENTRY(vectors) ventry el1_sync_invalid // Synchronous EL1t,ventry 是一个宏,见上面定义
史海拾趣
|
A flag to another clock domain If the signal that needs to cross the clock domains is just a pulse (i.e. it lasts just one clock cycle), we call it a \"flag\". The previous design usually doesn\'t work (the flag might be missed, ...… 查看全部问答> |
|
哪位用过ZLG7290这款芯片,我现在也在使用。 我想请教大家个问题:如何写驱动实现控制wince的系统菜单的?比如打开左下角的菜单,上下移动菜单,或者关闭任意程序等。谢谢… 查看全部问答> |
|
wince5.0 window media player 6.4 支持标准RTSP 要让wince5.0 window media player 6.4 支持标准RTSP,所以要写一个RTSP 的filter, 我的问题是,只要注册了这个rtsp的filter ,用media player6.4接收rtsp的流就会直接调用我这个RTSP 的filter? 还是还要修改注册表其他地方??… 查看全部问答> |
|
1、环氧树脂 Epoxy Resin 2、硅胶 Silicone 3、胶饼 Molding Compound 4、硅树脂 Hybrid 根据分子结构,环氧树脂大体上可分为五大类: 1、 缩水甘油醚类环氧树脂 2、 缩水甘油酯类环氧树脂 3、 缩水甘油胺 ...… 查看全部问答> |
|
今天又遭鄙视了,之前听说泰克的春季创新论坛扩展到15个城市,本想报名泰克创新论坛了解一哈功率测量、高精度功率分析、EMI诊断等方面的测试技术呢,网上资料虽然一大堆但面对面的教学让人更易接受,不懂还可以请教泰克的专家。但是,在巡展的15个 ...… 查看全部问答> |




