PowerPC处理器上vxWorks 异常和中断处理过程解析
2015-04-20 17:06
417 查看
异常和中断处理过程是每个体系结构和OS都要面对的重要问题,本文从硬件角度以及软件角度来分析PowerPc这个过程,文字水平有限,将就着看。
PowerPC定义了十几种异常,其中常见的如DataTLB miss, Instruction TLB miss, external input....每一个都有固定的地址(ivorn),从物理地址0x100开始.0x500是中断入口,0xe00是DTLBmiss,0xf00是itlbmiss入口.首先整体了解一下中断发生时硬件/软件处理流程,硬件会做什么,OS软件要做什么。
PowerPC 中断的硬件处理流程:(ePAPR第四章)
1. 把正在执行的指令序列下一条指令地址保存到中断寄存器SRR0(Save/RestoreRegiser 0)。
2. 把当前 MSR 的内容保存到 SRR1。
3. 把 MSR 某些比特置为 0,如MSR[SPE,WE,EE,PR,FP,FE0,FE1,IS,DS]are 0 by all interrupts.
【注】:PowerPC有两种执行模式,分别为用户模式(UserMode) 和特权模式(SupervisorMode), MSR[PR]=0 表示特权模式。Linux内核运行在特权模式,而普通程序运行在用户模式。vxWorks全部运行在特权模式。
1. 在新的 MSR 状态下,从中断向量偏移处开始指令读取和执行。
2. 外部中断处理结束时,必须通过 rfi 指令返回。
3. rfi 的执行,会把 SRR1 的内容恢复到 MSR, 并从 SRR0 所保存的地址处继续执行。
PowerPC Linux (软件)中断处理程序
异常向量ExternalInput处的处理程序主要分为以下几个步骤:
1. NORMAL_EXCEPTION_PROLOG宏
建立用户中断处理程序的栈帧,并把一些寄存器的值保存在栈帧中,它们在栈帧中布局由structpt_regs 定义。
2. 执行 do_IRQ
在irq_enter()函数中更新preempt_count。 读MPIC的IACK寄存器,通知MPIC开始处理该中断,同时获取MPIC中断号,映射为软件中断号,找到并运行注册在该软件中断号上的用户中断处理程序,最后写MPIC的EOI寄存器,通知MPIC中断处理结束。
在irq_exit()中更新preempt_count,调用invoke_softirq()处理pending的软中断。
3. ret_from_except
某些条件满足时,进行进程调度和信号处理,最后调用rfi指令返回。
PowerPC vxWorks(软件)中断处理程序
VxWorks的处理流程大体上与linux一样,只是在代码实现细节上存在些区别。
代码的调用路径:usrInit ->excVecInit ->excVecConnectCommon
代码实现过程:
把一段机器码excConnectCode[]拷贝到每个异常vector的入口地址处(excVecConnectCommon里实现),再重新计算异常处理函数的地址并覆盖通用处理函数地址。
整个过程中最关键的就是这段机器码数组,一共12条指令。
首先清MSR[CE],防止在保存中断context时被CE中断打断
xxxEnt是intEntorexcEnt.
xxxHandler是 excIntHandle or excExcHandle
xxxExit是intExitor excExit.
其中intEnt/intExit,excEnt/excExit是通用中断/异常入口和出口函数,中断进前者,异常进后者,主要作用是保存context以及恢复context,设置中断栈,保存易失的寄存器变量。。。。。
excIntHandle/excExcHandle也是通用处理函数,主要作用是打印下异常信息,对于关键异常或者中断的话,都有自己单独的处理函数,会在接下来的初始化过程中逐个把xxxHandler换成专用的处理函数,实现的方法是直接修改机器码后16bit。
MMU初始化的时候替换excExcHandle为mmuPpcDataTlbMissHandler/mmuPpcInstTlbMissHandler
MPIC初始化的时候会用vxbMpicIntHandler替换excIntHandle来调用ISR
WD/Timer初始化的时候也会替换成自己的Handler
至此,真正中断/异常来的时候会执行intEnt->vxbMpicIntHandler->intExit
下面的代码实现是intEnt,可以看看里面都做了哪些事情
PowerPC定义了十几种异常,其中常见的如DataTLB miss, Instruction TLB miss, external input....每一个都有固定的地址(ivorn),从物理地址0x100开始.0x500是中断入口,0xe00是DTLBmiss,0xf00是itlbmiss入口.首先整体了解一下中断发生时硬件/软件处理流程,硬件会做什么,OS软件要做什么。
PowerPC 中断的硬件处理流程:(ePAPR第四章)
1. 把正在执行的指令序列下一条指令地址保存到中断寄存器SRR0(Save/RestoreRegiser 0)。
2. 把当前 MSR 的内容保存到 SRR1。
3. 把 MSR 某些比特置为 0,如MSR[SPE,WE,EE,PR,FP,FE0,FE1,IS,DS]are 0 by all interrupts.
【注】:PowerPC有两种执行模式,分别为用户模式(UserMode) 和特权模式(SupervisorMode), MSR[PR]=0 表示特权模式。Linux内核运行在特权模式,而普通程序运行在用户模式。vxWorks全部运行在特权模式。
1. 在新的 MSR 状态下,从中断向量偏移处开始指令读取和执行。
2. 外部中断处理结束时,必须通过 rfi 指令返回。
3. rfi 的执行,会把 SRR1 的内容恢复到 MSR, 并从 SRR0 所保存的地址处继续执行。
PowerPC Linux (软件)中断处理程序
异常向量ExternalInput处的处理程序主要分为以下几个步骤:
1. NORMAL_EXCEPTION_PROLOG宏
建立用户中断处理程序的栈帧,并把一些寄存器的值保存在栈帧中,它们在栈帧中布局由structpt_regs 定义。
2. 执行 do_IRQ
在irq_enter()函数中更新preempt_count。 读MPIC的IACK寄存器,通知MPIC开始处理该中断,同时获取MPIC中断号,映射为软件中断号,找到并运行注册在该软件中断号上的用户中断处理程序,最后写MPIC的EOI寄存器,通知MPIC中断处理结束。
在irq_exit()中更新preempt_count,调用invoke_softirq()处理pending的软中断。
3. ret_from_except
某些条件满足时,进行进程调度和信号处理,最后调用rfi指令返回。
PowerPC vxWorks(软件)中断处理程序
VxWorks的处理流程大体上与linux一样,只是在代码实现细节上存在些区别。
代码的调用路径:usrInit ->excVecInit ->excVecConnectCommon
代码实现过程:
把一段机器码excConnectCode[]拷贝到每个异常vector的入口地址处(excVecConnectCommon里实现),再重新计算异常处理函数的地址并覆盖通用处理函数地址。
LOCAL INSTR excConnectCode[]= { /* data word byte opcode operands */ 0x7c7343a6, /* 0 0x00 mtspr SPRG3, p0 */ 0x7c6000a6, /* 1 0x04 mfmsr p0 */ 0x546303da, /* 2 0x08 rlwinm p0,p0,0,15,13 clear MSR[CE] */ 0x7c600124, /* 3 0x0c mtmsr p0 */ 0x60000000, /* 4 0x10 nop */ /* If either ofthe above, add 4 words/0x10bytes to following offsets */ 0x7c6802a6, /* 1 0x04 mflr p0 */ 0x48000001, /* 2(6) 0x08/18 bl xxxEnt */ 0x38610000, /* 3 0x0c addi r3, sp, 0 */ 0x9421fff0, /* 4 0x10 stwu sp, -FRAMEBASESZ(sp) */ 0x48000001, /* 5(9) 0x14/24 bl xxxHandler */ 0x38210010, /* 6 0x18 addi sp, sp, FRAMEBASESZ */ 0x48000001 /* 7(11) 0x1c/2c bl xxxExit */ };
整个过程中最关键的就是这段机器码数组,一共12条指令。
0x7c7343a6, /* 0 0x00 mtspr SPRG3, p0 */ 0x7c6000a6, /* 1 0x04 mfmsr p0 */ 0x546303da, /* 2 0x08 rlwinm p0,p0,0,15,13 clear MSR[CE] */ 0x7c600124, /* 3 0x0c mtmsr p0 */ 0x60000000, /* 4 0x10 nop
首先清MSR[CE],防止在保存中断context时被CE中断打断
0x7c6802a6, /* 1 0x04 mflr p0 */ 0x48000001, /* 2(6) 0x08/18 bl xxxEnt */ 0x38610000, /* 3 0x0c addi r3, sp, 0 */ 0x9421fff0, /* 4 0x10 stwu sp, -FRAMEBASESZ(sp) */ 0x48000001, /* 5(9) 0x14/24 bl xxxHandler */ 0x38210010, /* 6 0x18 addi sp, sp, FRAMEBASESZ */ 0x48000001 /* 7(11) 0x1c/2c bl xxxExit */
xxxEnt是intEntorexcEnt.
xxxHandler是 excIntHandle or excExcHandle
xxxExit是intExitor excExit.
其中intEnt/intExit,excEnt/excExit是通用中断/异常入口和出口函数,中断进前者,异常进后者,主要作用是保存context以及恢复context,设置中断栈,保存易失的寄存器变量。。。。。
excIntHandle/excExcHandle也是通用处理函数,主要作用是打印下异常信息,对于关键异常或者中断的话,都有自己单独的处理函数,会在接下来的初始化过程中逐个把xxxHandler换成专用的处理函数,实现的方法是直接修改机器码后16bit。
MMU初始化的时候替换excExcHandle为mmuPpcDataTlbMissHandler/mmuPpcInstTlbMissHandler
MPIC初始化的时候会用vxbMpicIntHandler替换excIntHandle来调用ISR
WD/Timer初始化的时候也会替换成自己的Handler
至此,真正中断/异常来的时候会执行intEnt->vxbMpicIntHandler->intExit
下面的代码实现是intEnt,可以看看里面都做了哪些事情
864 /* 865 *ThePowerPC Family doesn't support the notion of an interrupt 866 * stackinhardware. To avoid having to allowspacefor interrupt 867 *handlingin each task stack, this stub switches from the task 868 * stacktothe interrupt stack by changing the value of the SP(R1). 869 * Iftheinterrupt is nested, we don't need to switch stacks but 870 * wedoneed to check for overflow. 871 */ 893 _PPC_PER_CPU_VALUE_GET(p0,vxIntStackBase) 894 stwu sp, -_PPC_ESF_STK_SIZE(p0) /* carve stack */ 895 mr sp, p0 /* switch tointerruptstack */ /* 1251 * The critical status are saved atthisstage. The interrupt should 1252 *beenabled as soon as possible to reduce the interrupt latency. 1253 *However,there is only one mask bit on PowerPC. It is at the 1254 *interruptcontroller level to set mask for each individual 1255 *interrupt. 1256 * Thus,wesave task's register first, then call interrupt controller 1257 *routineto decide if the interrupt should be re-enabled or not. 1258 */ mfspr p0, XER /* load XER to P0 */ 1261 stw p0, _PPC_ESF_XER(sp) /* save XER to the stack */ 1262 1263 mfspr p0, CTR /* load CTR to P0 */ 1264 stw p0, _PPC_ESF_CTR(sp) /* save CTR to the stack */ 1265 1266#if (CPU==PPC601) 1267 mfspr p0, MQ /* load MQ to P0 */ 1268 stw p0, _PPC_ESF_MQ(sp) /* save MQ to the stack */ 1269#endif /*(CPU==PPC601)*/ 1270#if (defined(_WRS_CONFIG_PPC_E500)) 1271#ifdef _WRS_SPE_SUPPORT 1272 mfspr p0, SPEFSCR /* load SPEFSCR to P0 */ 1273 stw p0, _PPC_ESF_SPEFSCR(sp) /* save SPEFSCR to the stack */ 1274#endif /*_WRS_SPE_SUPPORT */ 1275#endif /*(defined(_WRS_CONFIG_PPC_E500)) */ 1276 1277 stw r0, _PPC_ESF_R0(sp) /* save general register 0 */ 1278 stw r2, _PPC_ESF_R2(sp) /* save general register 2 */ 1279 1280 stw p2, _PPC_ESF_P2(sp) /* save general register 5 */ 1281 stw p3, _PPC_ESF_P3(sp) /* save general register 6 */ 1282 stw p4, _PPC_ESF_P4(sp) /* save general register 7 */ 1283 stw p5, _PPC_ESF_P5(sp) /* save general register 8 */ 1284 stw p6, _PPC_ESF_P6(sp) /* save general register 9 */ 1285 stw p7, _PPC_ESF_P7(sp) /* save general register 10 */ 1286 1287 stw r11,_PPC_ESF_R11(sp) /* savegeneral register 11 */ 1288 stw r12, _PPC_ESF_R12(sp) /* save general register 12 */ 1289 stw r13, _PPC_ESF_R13(sp) /* save general register 13 */ 1290 beqlr+ cr4 /* return to vector unlessstackoverflow */
相关文章推荐
- AT91SAM9261中断处理过程解析
- linux中断(与异常)处理过程
- SDE数据编辑过程中异常中断后产生错误的处理
- mysql存储过程中的异常处理解析
- AT91SAM9261中断处理过程解析
- ARM异常---一个Uart中断的触发处理过程:
- system_call中断处理过程分析
- 分析system_call中断处理过程
- SQL Server中使用异常处理调试存储过程
- 《深入理解linux内核》学习笔记2 --- 图解外部中断处理过程
- 硬中断完全处理过程
- 【Linux操作系统分析】中断和异常(1)——中断描述符表IDT,I/O中断处理,中断向量
- map-reduce处理过程解析
- Linux系统内核分析实验——system_call中断处理过程
- 【ARM】arm异常中断处理知识点
- 一个硬中断的完整处理过程(2.4.24版本)
- Node.js 异步异常的处理与domain模块解析
- MYSQL 存储过程异常处理 报错 错误代码: 1337
- Linux内核中断处理过程分析-基于arm平台
- 缺页中断处理过程