mips linux异常中断代码分析,mips_linux中断与异常(转)

1.中断

中断/异常入口基址ebase设置并不在0x80000000,而是其它地址。

中断配制成矢量模式,vector offset配置成0x100。Int0~int7(int0/int1:sw;int2~int7:hw;int7-count/compare)

Ebase:0x8045f000;Int0 entry:0x8045f200;Int2 entry:0x8045f200+(2*0x100)

a)矢量中断入口注册

set_vi_handler(2, mips_int2_handler);

void *set_vi_handler(int n, vi_handler_t addr)

{

return set_vi_srs_handler(n, addr, 0);

}

static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)

{

extern char except_vec_vi, except_vec_vi_lui;

extern char except_vec_vi_ori, except_vec_vi_end;

extern char rollback_except_vec_vi;

char *vec_start = (cpu_wait == r4k_wait) ?

&rollback_except_vec_vi : &except_vec_vi;

const int handler_len = &except_vec_vi_end - vec_start;

const int lui_offset = &except_vec_vi_lui - vec_start;

const int ori_offset = &except_vec_vi_ori - vec_start;

if (handler_len > VECTORSPACING) {

/*

* Sigh... panicing won't help as the console

* is probably not configured :(

*/

panic("VECTORSPACING too small");

}

memcpy(b, vec_start, handler_len);//拷贝一段公用的中断处理入口代码片段

w = (u32 *)(b + lui_offset);//修改中断处理函数的地址

*w = (*w & 0xffff0000) | (((u32)handler >> 16) & 0xffff);

w = (u32 *)(b + ori_offset);//修改中断处理函数的地址

*w = (*w & 0xffff0000) | ((u32)handler & 0xffff);

local_flush_icache_range((unsigned long)b,

(unsigned long)(b+handler_len));//刷icache

}

b)中断处理服务程序注册

setup_irq(MIPS_CPU_IRQ_BASE + 2, &cascade_irqaction);

setup_irq(MIPS_CPU_IRQ_BASE + 3, &dma_irqaction);

setup_irq(ASOC_IRQ_BASE + DMA_INT, &cascade_irqaction);

setup_irq(ASOC_IRQ_BASE + PC_INT, &cascade_irqaction);

#define IRQ_TIMER0 (ASOC_IRQ_BASE+10)//对应irq分配策略

request_irq(IRQ_TIMER0, mips_timer_interrupt, 0, "timer", (void *)0);

int request_irq(unsigned int irq, irq_handler_t handler,

unsigned long irqflags, const char *devname, void *dev_id)

{

setup_irq(irq, action);

}

c)setup_irq的参数irq与irq分配策略有关。

原则上是任意一个硬件中断源可以随意配置到任意一个中断信号上(int0~int7)。每一个中断信号上也都可以挂多个中断源。从实现和效率角度看,将一些优先级高的中断源独立的挂在一个中断信号上,其它都挂载一个公用的中断上是比较合理的。下图是一种分配方式。

d)中断服务程序执行流程

Int2_handler

8045f400:401a7000mfc0k0,c0_epc

8045f404:3c1b8010luik1,0x8010

8045f408:277b0640addiuk1,k1,1600

8045f40c:375a001forik0,k0,0x1f

8045f410:3b5a001fxorik0,k0,0x1f

8045f414:175b0002bnek0,k1,8045f420

8045f418:00000000nop

8045f41c:409a7000mtc0k0,c0_epc

8045f420:401a6000mfc0k0,c0_status

8045f424:001ad0c0sllk0,k0,0x3

8045f428:07400003bltzk0,8045f438

8045f42c:03a0d821movek1,sp

8045f430:3c1b8041luik1,0x8041

8045f434:8f7be938lwk1,-5832(k1)

8045f438:03a0d021movek0,sp

8045f43c:277dff50addiusp,k1,-176

8045f440:afba008cswk0,140(sp)

8045f444:afa30024swv1,36(sp)

8045f448:afa00018swzero,24(sp)

8045f44c:40036000mfc0v1,c0_status

8045f450:afa20020swv0,32(sp)

8045f454:afa30098swv1,152(sp)

8045f458:afa40028swa0,40(sp)

8045f45c:40036800mfc0v1,c0_cause

8045f460:afa5002cswa1,44(sp)

8045f464:afa300a8swv1,168(sp)

8045f468:afa60030swa2,48(sp)

8045f46c:40037000mfc0v1,c0_epc

8045f470:afa70034swa3,52(sp)

8045f474:afa300acswv1,172(sp)

8045f478:afb9007cswt9,124(sp)

8045f47c:afbc0088swgp,136(sp)

8045f480:afbf0094swra,148(sp)

8045f484:37bc1ffforigp,sp,0x1fff

8045f488:3b9c1fffxorigp,gp,0x1fff

8045f48c:afa1001cswat,28(sp)

8045f490:3c028010luiv0,0x8010//对应set_vi_srs_handler中的地址修改(lui)

8045f494:0804020dj80100834//except_vec_vi_handler

8045f498:34428278oriv0,v0,0x8278//对应set_vi_srs_handler中的地址修改(ori)

except_vec_vi_handler

NESTED(except_vec_vi_handler, 0, sp)

SAVE_TEMP

SAVE_STATIC

CLI

LONG_Ls0, TI_REGS($28)

LONG_Ssp, TI_REGS($28)

PTR_LAra, ret_from_irq//中断总出口

jrv0// mips_int2_handler

END(except_vec_vi_handler)

asmlinkage void mips_int2_handler(void)

{

xxx_irqdispatch();

}

static void xxx_irqdispatch(void)

{

int irq;

u32 intc0_pending = readl(IC0_PD);

u32 intc0_mask = readl(IC0_MASK);

u32 intc0_req0 = intc0_pending & intc0_mask;

u32 intc0_ext_int = 0;

if (!intc0_req0) {

spurious_interrupt();

goto exit;

}

irq = ffs(intc0_req0) - 1;

if (irq != EXTERNAL_INT){

do_IRQ(ASOC_IRQ_BASE + irq);//对应irq分配策略

goto exit;

}

else

{

}

exit:

return;

}

2.异常

a)tlb_refill

8045f000:  3c1b8041   lui         k1,0x80418045f004:  401a4000   mfc0        k0,c0_badvaddr8045f008:  8f7b3000   lw          k1,12288(k1)//pgd_current8045f00c:  001ad582   srl         k0,k0,0x168045f010:  001ad080   sll         k0,k0,0x28045f014:  037ad821   addu        k1,k1,k08045f018:  401a2000   mfc0        k0,c0_context8045f01c:  8f7b0000   lw          k1,0(k1)8045f020:  001ad042   srl         k0,k0,0x18045f024:  335a0ff8   andi        k0,k0,0xff88045f028:  037ad821   addu        k1,k1,k08045f02c:  8f7a0000   lw          k0,0(k1)8045f030:  8f7b0004   lw          k1,4(k1)8045f034:  001ad182   srl         k0,k0,0x68045f038:  409a1000   mtc0        k0,c0_entrylo08045f03c:  001bd982   srl         k1,k1,0x68045f040:  409b1800   mtc0        k1,c0_entrylo18045f044:  000000c0   ehb8045f048:  42000006   tlbwr8045f04c:  42000018   eret8045f050:  00000000   nop

b)general_exception

8045f180:401b6800mfc0k1,c0_cause

8045f184:337b007candik1,k1,0x7c

8045f188:3c1a8041luik0,0x8041

8045f18c:035bd021adduk0,k0,k1

8045f190:8f5aeac0lwk0,-5440(k0)//exception_handlers[i]

8045f194:03400008jrk0

8045f198:00000000nop

c)设置异常处理函数入口

void *set_except_vector(int n, void *addr)

set_except_vector(0, rollback ? rollback_handle_int : handle_int);

set_except_vector(1, handle_tlbm);

set_except_vector(2, handle_tlbl);

set_except_vector(3, handle_tlbs);

set_except_vector(4, handle_adel);

set_except_vector(5, handle_ades);

set_except_vector(6, handle_ibe);

set_except_vector(7, handle_dbe);

set_except_vector(8, handle_sys);

set_except_vector(9, handle_bp);

set_except_vector(10, rdhwr_noopt ? handle_ri :(cpu_has_vtag_icache ? handle_ri_rdhwr_vivt : handle_ri_rdhwr));

set_except_vector(11, handle_cpu);

set_except_vector(12, handle_ov);

set_except_vector(13, handle_tr);

set_except_vector(14, handle_mc);

set_except_vector(15, handle_ndc);

set_except_vector(15, handle_fpe);

set_except_vector(22, handle_mdmx);

set_except_vector(24, handle_mcheck);

set_except_vector(25, handle_mt);

set_except_vector(26, handle_dsp);

0818b9ca8b590ca3270a3433284dd417.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值