`
xiaoer_1982
  • 浏览: 1811472 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

三读内核中断处理(3):中断处理流程

阅读更多

快乐虾

http://blog.csdn.net/lights_joy/

lights@hb165.com

本文适用于

ADSP-BF561

优视BF561EVB开发板

uclinux-2008r1.5-rc3(smp patch)

Visual DSP++5.0(update 5)

欢迎转载,但请保留作者信息

1.1 evt_nmi

这个代码是用汇编写的,其实现在arch/blackfin/mach-common/interrupt.s中,用于处理nmi中断:

/* Interrupt routine for evt2 (NMI).

* We don't actually use this, so just return.

* For inner circle type details, please see:

* http://docs.blackfin.uclinux.org/doku.php?id=linux:nmi

*/

ENTRY(_evt_nmi)

.weak _evt_nmi

rtn;

ENDPROC(_evt_nmi)

空语句,没什么可说的。

1.2 trap

这部分代码用于处理Exception中断,对于内核而言是相当重要的,其实现在arch\blackfin\mach-common\entry.S文件中

ENTRY(_trap) /* Exception: 4th entry into system event table(supervisor mode)*/

/* Since the kernel stack can be anywhere, it's not guaranteed to be

* covered by a CPLB. Switch to an exception stack; use RETN as a

* scratch register (for want of a better option).

*/

EX_SCRATCH_REG = sp;

//GET_PDA_SAFE(sp);

sp.l = lo(DSPID);

sp.h = hi(DSPID);

sp = [sp];

sp = sp << 2;

sp = sp << 2;

sp = sp << 2;

sp = sp << 2;

sp = sp << 2;

sp = sp << 2;

sp = sp << 2;

sp = sp << 2;

sp = sp << 2;

sp = sp << 2;

sp = sp << 2;

sp = sp << 2;

if cc jump _trap_3;

cc = sp == 0x0;

if !cc jump _trap_4;

_trap_1:

/* sp = 0x0; */

cc = !cc; /* restore cc to 0 */

_trap_2:

sp.l = lo(L1_SCRATCH_COREA);

sp.h = hi(L1_SCRATCH_COREA);

jump _trap_5;

_trap_3:

cc = sp == 0x0;

if cc jump _trap_2;

/* sp = 0x1000000; */

cc = !cc; /* restore cc to 1 */

_trap_4:

sp.l = lo(L1_SCRATCH_COREB);

sp.h = hi(L1_SCRATCH_COREB);

_trap_5:

//GET_PDA_SAFE(sp); end

sp = [sp + PDA_EXSTACK];

/* Try to deal with syscalls quickly. */

[--sp] = ASTAT;

[--sp] = (R7:6, P5:4);

DEBUG_STOP_HWTRACE(p5, r7)

r7 = SEQSTAT; /* reason code is in bit 5:0 */

r6.l = lo(SEQSTAT_EXCAUSE);

r6.h = hi(SEQSTAT_EXCAUSE);

r7 = r7 & r6;

p5.h = _ex_table;

p5.l = _ex_table;

p4 = r7;

p5 = p5 + (p4 << 2);

p4 = [p5];

jump (p4);

.Lbadsys:

r7 = -ENOSYS; /* signextending enough */

[sp + PT_R0] = r7; /* return value from system call */

jump .Lsyscall_really_exit;

ENDPROC(_trap)

在这里EX_SCRATCH_REG定义成RETN这个寄存器。

SMP版本中,每个核都使用了自身的scratch pad sram做为其私有数据区,因而在这段代码的开头就判断DSPID并设置正确的SP指针,使其指向各自内部的SCRATCH PAD SRAM在原有的代码中,使用了GET_SAFE_PDA(sp)这个宏来达到目的,但移植到VDSP时,由于汇编语法方面的差异,将这个宏展开并进行了适当修改。

_ex_table是在本文件中定义的函数指针的数组,它指明了所有可能的64种异常的入口:

ENTRY(_ex_table)

/* entry for each EXCAUSE[5:0]

* This table must be in sync with the table in ./kernel/traps.c

* EXCPT instruction can provide 4 bits of EXCAUSE, allowing 16 to be user defined

*/

.long _ex_syscall /* 0x00 - User Defined - Linux Syscall */

.long _ex_soft_bp /* 0x01 - User Defined - Software breakpoint */

.long _ex_replaceable /* 0x02 - User Defined */

.long _ex_trap_c /* 0x03 - User Defined - userspace stack overflow */

.long _ex_spinlock /* 0x04 - User Defined - dump trace buffer */

.long _ex_replaceable /* 0x05 - User Defined */

.long _ex_replaceable /* 0x06 - User Defined */

.long _ex_replaceable /* 0x07 - User Defined */

.long _ex_replaceable /* 0x08 - User Defined */

.long _ex_replaceable /* 0x09 - User Defined */

.long _ex_replaceable /* 0x0A - User Defined */

.long _ex_replaceable /* 0x0B - User Defined */

.long _ex_replaceable /* 0x0C - User Defined */

.long _ex_replaceable /* 0x0D - User Defined */

.long _ex_replaceable /* 0x0E - User Defined */

.long _ex_replaceable /* 0x0F - User Defined */

.long _ex_single_step /* 0x10 - HW Single step */

#ifdef CONFIG_DEBUG_BFIN_HWTRACE_EXPAND

.long _ex_trace_buff_full /* 0x11 - Trace Buffer Full */

#else

.long _ex_trap_c /* 0x11 - Trace Buffer Full */

#endif

.long _ex_trap_c /* 0x12 - Reserved */

.long _ex_trap_c /* 0x13 - Reserved */

.long _ex_trap_c /* 0x14 - Reserved */

.long _ex_trap_c /* 0x15 - Reserved */

.long _ex_trap_c /* 0x16 - Reserved */

.long _ex_trap_c /* 0x17 - Reserved */

.long _ex_trap_c /* 0x18 - Reserved */

.long _ex_trap_c /* 0x19 - Reserved */

.long _ex_trap_c /* 0x1A - Reserved */

.long _ex_trap_c /* 0x1B - Reserved */

.long _ex_trap_c /* 0x1C - Reserved */

.long _ex_trap_c /* 0x1D - Reserved */

.long _ex_trap_c /* 0x1E - Reserved */

.long _ex_trap_c /* 0x1F - Reserved */

.long _ex_trap_c /* 0x20 - Reserved */

.long _ex_trap_c /* 0x21 - Undefined Instruction */

.long _ex_trap_c /* 0x22 - Illegal Instruction Combination */

.long _ex_dviol /* 0x23 - Data CPLB Protection Violation */

.long _ex_trap_c /* 0x24 - Data access misaligned */

.long _ex_trap_c /* 0x25 - Unrecoverable Event */

.long _ex_dmiss /* 0x26 - Data CPLB Miss */

.long _ex_dmult /* 0x27 - Data CPLB Multiple Hits - Linux Trap Zero */

.long _ex_trap_c /* 0x28 - Emulation Watchpoint */

.long _ex_trap_c /* 0x29 - Instruction fetch access error (535 only) */

.long _ex_trap_c /* 0x2A - Instruction fetch misaligned */

.long _ex_trap_c /* 0x2B - Instruction CPLB protection Violation */

.long _ex_icplb_miss /* 0x2C - Instruction CPLB miss */

.long _ex_trap_c /* 0x2D - Instruction CPLB Multiple Hits */

.long _ex_trap_c /* 0x2E - Illegal use of Supervisor Resource */

.long _ex_trap_c /* 0x2E - Illegal use of Supervisor Resource */

.long _ex_trap_c /* 0x2F - Reserved */

.long _ex_trap_c /* 0x30 - Reserved */

.long _ex_trap_c /* 0x31 - Reserved */

.long _ex_trap_c /* 0x32 - Reserved */

.long _ex_trap_c /* 0x33 - Reserved */

.long _ex_trap_c /* 0x34 - Reserved */

.long _ex_trap_c /* 0x35 - Reserved */

.long _ex_trap_c /* 0x36 - Reserved */

.long _ex_trap_c /* 0x37 - Reserved */

.long _ex_trap_c /* 0x38 - Reserved */

.long _ex_trap_c /* 0x39 - Reserved */

.long _ex_trap_c /* 0x3A - Reserved */

.long _ex_trap_c /* 0x3B - Reserved */

.long _ex_trap_c /* 0x3C - Reserved */

.long _ex_trap_c /* 0x3D - Reserved */

.long _ex_trap_c /* 0x3E - Reserved */

.long _ex_trap_c /* 0x3F - Reserved */

_ex_table.end:

//END(_ex_table)

因而,这一段程序就是根据不同的EXCEPTION的类型,调用相应的入口函数进行处理。可以看到,对于大部分的异常,都是通过ex_trap_c这个函数来处理的。

1.3 _evt_ivhw

这部分代码在arch\blackfin\mach-common\interrupt.S中,用于处理Hardware Error InterruptVDSP文档对此的解释是:

The Hardware Error Interrupt is generated by:

Bus parity errors

Internal error conditions within the core, such as Performance Monitor overflow

Peripheral errors

Bus timeout errors

看看uclinux的处理:

/* interrupt routine for ivhw - 5 */

ENTRY(_evt_ivhw)

SAVE_ALL_SYS

#ifdef CONFIG_FRAME_POINTER

fp = 0;

#endif

#if ANOMALY_05000283

cc = r7 == r7;

p5.h = HI(CHIPID);

p5.l = LO(CHIPID);

if cc jump _evt_ivhw_1;

r7.l = W[p5];

_evt_ivhw_1:

#endif

#ifdef CONFIG_HARDWARE_PM

r7 = [sp + PT_SEQSTAT];

r7 = r7 >>> 0xe;

r6 = 0x1F;

r7 = r7 & r6;

r5 = 0x12;

cc = r7 == r5;

if cc jump .Lcall_do_ovf; /* deal with performance counter overflow */

#endif

//# We are going to dump something out, so make sure we print IPEND properly

p2.l = lo(IPEND);

p2.h = hi(IPEND);

r0 = [p2];

[sp + PT_IPEND] = r0;

/* set the EXCAUSE to HWERR for trap_c */

r0 = [sp + PT_SEQSTAT];

R1.L = LO(VEC_HWERR);

R1.H = HI(VEC_HWERR);

R0 = R0 | R1;

[sp + PT_SEQSTAT] = R0;

r0 = sp; /* stack frame pt_regs pointer argument ==> r0 */

SP += -12;

call _trap_c;

SP += 12;

call _ret_from_exception;

.Lcommon_restore_all_sys:

RESTORE_ALL_SYS

rti;

#ifdef CONFIG_HARDWARE_PM

.Lcall_do_ovf:

SP += -12;

call _pm_overflow;

SP += 12;

jump .Lcommon_restore_all_sys;

#endif

ENDPROC(_evt_ivhw)

在这里,SAVE_ALL_SYS将系统的大部分寄存器的值都压到栈中,且入栈的顺序是和pt_regs这个结构体的成员一一对应的,因此最后可以将此结构体的指针传给函数trap_c。需要注意的是,这个中断处理代码并未重新设置SP的值,也就是说它将使用发生错误的线程的SP

PT_IPENDPT_SEQSTAT分别定义了保存IPENDSEQSTAT这两个寄存器值的成员相应于pt_regs这个结构体的偏移量,因而使用[sp + PT_IPEND]这样的方式可以取得相应寄存器的值。

VEC_HWERR则是定义好的一个常数:

/* The hardware reserves (63) for future use - we use it to tell our

* normal exception handling code we have a hardware error

*/

#define VEC_HWERR (63)

因为出错的原因保存在SEQSTAT寄存器的低5位中,因此通过取或的方式将pt_regs->seqstat的值设置为EXCAUSE,而不是原来的32位整数。

然后调用trap_c进行处理,此函数将决定输出错误信息后返回原位置执行,或者中止执行。

1.4 _ret_from_exception

这个函数将由_evt_ivhw在返回时调用,其实现在arch\blackfin\mach-common\entry.S中:

ENTRY(_ret_from_exception)

p2.l = lo(IPEND);

p2.h = hi(IPEND);

csync;

r0 = [p2];

[sp + PT_IPEND] = r0;

_ret_from_exception_1:

r2 = LO(~0x37) (Z);

r0 = r2 & r0;

cc = r0 == 0;

if !cc jump _ret_from_exception_4; /* if not return to user mode, get out */

/* Make sure any pending system call or deferred exception

* return in ILAT for this process to get executed, otherwise

* in case context switch happens, system call of

* first process (i.e in ILAT) will be carried

* forward to the switched process

*/

p2.l = lo(ILAT);

p2.h = hi(ILAT);

r0 = [p2];

r1 = (EVT_IVG14 | EVT_IVG15) (z);

r0 = r0 & r1;

cc = r0 == 0;

if !cc jump _ret_from_exception_5;

/* Set the stack for the current process */

r7 = sp;

r4.l = lo(ALIGN_PAGE_MASK);

r4.h = hi(ALIGN_PAGE_MASK);

r7 = r7 & r4; /* thread_info->flags */

p5 = r7;

r7 = [p5 + TI_FLAGS];

r4.l = lo(_TIF_WORK_MASK);

r4.h = hi(_TIF_WORK_MASK);

r7 = </

分享到:
评论

相关推荐

    linux内核中断处理流程

    把内核中断的流程说的很清楚,学习Linux的必备资料

    Linux内核的中断机制

    本文主要从内核实现的角度分析了Linux 2.4.0内核的设备中断流程。本文是为那些想要了解Linux I/O子系统的读者和Linux驱动程序开发人员而写的。

    深入剖析Linux中断机制

    Linux 处理异常和中断的基本流程, 在此基础上分析了中断处理的详细流程, 包括保存现场、 中断处理、中断退出时的软中断执行及中断返回时的进程切换等问题。最后介绍了中断相关 的 API,包括中断注册和释放、中断...

    Linux软中断softirq机制流程图

    这个流程图粗略地描述了softirq, tasklet, bottomhalt, task queue这些对象之间的联系及调用流程。 主要依据:《Linux内核的Softirq机制》和《软中断概况》 图中可能存在错误,希望您的指正!

    Linux的内核软中断(softirq)执行分析.zip_leavinghzf_linux_theory989

    linux软中断,分析内核中中断的流程以及怎样修改这部分内容,经过调试可以使用

    嵌入式系统/ARM技术中的计算机操作系统内核的中断和中断处理

     计算机技术中,由于某种异步事件的发生而迫使程序执行流程发生转移的现象叫做中断。  产生异步事件的原因叫做中断源。凡是中断源在发生异步事件时,都会向处理器发出一个通知信号,由于这个信号具有请处理器中止...

    深入分析Linux内核源码

    3.4.1中断和异常处理的硬件处理 3.4.2 Linux对异常和中断的处理 3.4.3 与堆栈有关的常量、数据结构及宏 3.4.4 中断处理程序的执行 3.4.5 从中断返回 3.5中断的后半部分处理机制 3.5.1 为什么把中断分为两部分...

    LS2K中断.svg

    内容是一张ls2k 中断整体流程框架矢量图,详细描述了龙芯处理器中断初始化、中断注册以及中断触发过程流程,从整体认识中断触发后如何准确找到设备注册的中断处理函数。

    嵌入式系统/ARM技术中的基于ARM9芯片S3C2410异常中断程序设计

    验证的代码详细分析了基于ARM嵌入式系统的异常处理流程,本文结合经过实际验证的代码对ARM9中断处理流程进行分析,并设计出基于S3C2410芯片的外部中断处理程序。 Arm9 arm9处理器 arm处理器 嵌入式系统 嵌入式  S3...

    深入分析Linux内核源码.chm

    第三章中断机制 3.1 中断基本知识 3.2中断描述符表的初始化 3.3异常处理 3.4 中断处理 3.5中断的后半部分处理机制 第四章 进程描述 4.1 进程和程序(Process and Program) 4.2 Linux中的进程概述 4.3 task_struct...

    myExpOS

    阶段9:处理内核堆栈 阶段10:控制台输出 阶段11:ExpL简介 阶段12:多程序介绍 中级阶段 阶段13:启动模块 阶段14:循环调度程序 阶段15:资源管理器模块 第十六阶段:控制台输入 阶段17:程序加载器 ...

    嵌入式系统/ARM技术中的ARM中断处理类型

    在正常的程序执行流程发生暂时的停止时,称为中断,例如,处理一个外部的中断请求。在处理异常之前,当前处理器的状态必须保留,这样当异常处理完成之后,当前程序可以继续执行。处理器允许多个异常同时发生,它们将...

    嵌入式系统实验四 GPIO中断实验

    1、仅作学习交流使用,切勿直接生搬硬套,要以真正学到...3、资源内容包含报告和代码,报告中详细说明了实验的流程、结果、遇到的问题等; 4、资源使用的方式:具体流程不清楚可查阅,遇到卡顿导致实验无法继续可查阅。

    linux0.0.1内核学习pdf

    主要分析了linux 0.0.1内核,包括以下内容: ...Linux0.0.1中断处理机制.pdf Linux键盘流程分析.pdf Memory.c注释.pdf RS_IO.S注解.pdf System_call.s简要注释.pdf 启动部分简介.pdf 文件系统部分代码分析(I).pdf

    进程信号的处理过程.docx

    进程信号的处理过程:(1)在...进程注销信号后,目的进程根据当前进程对此信号设置的处理方式,暂时终止当前代码的执行,保护上下文,转而执行信号处理函数,即捕获该信号,执行完成后再恢复到被中断的位置继续执行。

    简单谈谈Linux内核定时器

    软件意义上的定时器最终依赖硬件定时器来实现, 内核在时钟中断发生后检测各定时器是否到期 , 到期后的定时器处理函数将作为软中断在底半部执行 。实质上,时钟中断处理程序会 换起TIMER_SOFTIRQ软中断 ,运行当前...

    STM32F4-Free-Fall-Detection:自由落体检测驱动程序,基于中断,用于 LIS3DSH 加速度计(STM32F4-Discovery 板)

    STM32F4-Discovery 板的自由落体检测自由落体检测驱动程序,基于中断,用于 LIS3DSH 加速度计(STM32F4-Discovery 板)。 该项目在 Miosix 内核 ( ) 上运行。 ============================ 您可以在以下 URL 中找到...

    Rootkit的学习与研究

    2)通过中断门访问内核 3)通过任务门访问内核 4)通过陷阱门访问内核 3。保护模式篇章第二部分:windows分页机制 1)windows分页机制 4。保护模式篇章第三部分:直接访问硬件 1)修改iopl,ring3直接访问硬件 ...

    ROOTKIT专题的研究

    2)通过中断门访问内核 3)通过任务门访问内核 4)通过陷阱门访问内核 3。保护模式篇章第二部分:windows分页机制 1)windows分页机制 4。保护模式篇章第三部分:直接访问硬件 1)修改iopl,ring3直接访问硬件...

    韦东山视频目录+链接整合-1 视频目录

    第10课第3节 内核启动流程分析之Makefile 第10课第4节 内核启动流程分析之内核启动 第11课第1节 构建根文件系统之启动第1个程序 第11课第2节 构建根文件系统之init进程分析 第11课第3节 构建根文件系统之...

Global site tag (gtag.js) - Google Analytics