历史上的今天
返回首页

历史上的今天

今天是: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 是一个宏,见上面定义

推荐阅读

史海拾趣

Digilent公司的发展小趣事

作为电子行业的领军企业之一,DIALIGHT始终将技术创新作为公司发展的核心驱动力。公司拥有一支高素质的研发团队和先进的研发设施,不断推出具有创新性和竞争力的LED产品。同时,DIALIGHT还积极与高校、科研机构等合作,共同推动LED照明技术的进步和应用。

Aeroflex公司的发展小趣事

DIALIGHT在全球范围内不断拓展业务,目前在美国、英国、丹麦、德国、马来西亚、新加坡、澳大利亚、墨西哥和巴西等地设有业务。公司的LED产品广泛应用于各种工业场所,包括石油和天然气、矿业、化工、制造业等。通过提供定制化的照明解决方案,DIALIGHT赢得了众多客户的信赖和好评。

Firadec公司的发展小趣事

背景:随着电子行业竞争的日益激烈,成本控制成为了企业生存发展的关键。Firadec公司意识到优化供应链的重要性。

发展:公司开始与上游供应商建立长期稳定的合作关系,通过集中采购、共享库存等方式降低采购成本。同时,Firadec还加强了对生产过程的精细化管理,提高了生产效率和产品质量。

影响:供应链的优化和成本的有效控制,使Firadec公司在激烈的市场竞争中保持了较强的盈利能力。这也为公司后续的研发和市场拓展提供了有力的支持。

Everspin公司的发展小趣事

尽管Everspin在初期经历了亏损,但随着时间的推移,其财务状况逐渐改善。特别是在XXXX年和XXXX年,Everspin的总收入和净利润均实现了显著增长。这一财务表现证明了Everspin在MRAM领域的领先地位和持续盈利能力。

百事通科技(BUDDIES)公司的发展小趣事

随着技术的不断成熟,百事通科技(BUDDIES)开始将目光投向更广阔的市场。公司制定了详细的市场拓展计划,通过参加国际电子展、与海外企业建立合作关系等方式,逐步打开了国际市场。同时,公司还注重品牌建设,通过精心设计的品牌形象和广告宣传,提升了品牌知名度和美誉度。

台湾第一电阻(Firstohm)公司的发展小趣事
电冰箱发出异常声音可能是由多种原因引起的,如压缩机工作声音、制冷剂流动声音、风扇转动声音等。如果声音过大或异常,可能是部件松动、磨损或故障等原因引起的。此时应停止使用电冰箱,并请专业人员进行检查和维修。

问答坊 | AI 解惑

Crossing clock domains - Flag

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, ...…

查看全部问答>

wince 按键控制系统菜单实现问题

哪位用过ZLG7290这款芯片,我现在也在使用。 我想请教大家个问题:如何写驱动实现控制wince的系统菜单的?比如打开左下角的菜单,上下移动菜单,或者关闭任意程序等。谢谢…

查看全部问答>

我不理解这么牛B的汇编语言

IF {FALSE}         mov     r0, r4         mov     r1, #256                 ...…

查看全部问答>

编译EVC出错

orelibc.lib(pegwmain.obj) : error LNK2019: unresolved external symbol WinMain referenced in function WinMainCRTStartup ARMV4IDbg/SPLLoaderDlg.exe : fatal error LNK1120: 1 unresolved externals 开始错误是这样的 后来按照这样改 Pr ...…

查看全部问答>

EVC4.0编译出错,求助!

EVC4.0编译程序的时候,会出现Error spawning cl.exe的错误,是怎么回事啊?…

查看全部问答>

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? 还是还要修改注册表其他地方??…

查看全部问答>

直插式LED封装制程容易出现的问题与排解

  1、环氧树脂 Epoxy Resin   2、硅胶 Silicone   3、胶饼 Molding Compound   4、硅树脂 Hybrid   根据分子结构,环氧树脂大体上可分为五大类:   1、 缩水甘油醚类环氧树脂   2、 缩水甘油酯类环氧树脂   3、 缩水甘油胺 ...…

查看全部问答>

大城市VS小城市,电子工程师何去何从?

今天又遭鄙视了,之前听说泰克的春季创新论坛扩展到15个城市,本想报名泰克创新论坛了解一哈功率测量、高精度功率分析、EMI诊断等方面的测试技术呢,网上资料虽然一大堆但面对面的教学让人更易接受,不懂还可以请教泰克的专家。但是,在巡展的15个 ...…

查看全部问答>