mips_linux中断与异常(转)

来源:互联网 发布:新网域名管理登录 编辑:程序博客网 时间:2024/06/05 22:43

1.       中断

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

中断配制成矢量模式,vector offset配置成0x100Int0~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的参数irqirq分配策略有关。

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

 

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

Int2_handler

8045f400:  401a7000   mfc0        k0,c0_epc

8045f404:  3c1b8010   lui         k1,0x8010

8045f408:  277b0640   addiu       k1,k1,1600

8045f40c:  375a001f   ori         k0,k0,0x1f

8045f410:  3b5a001f   xori        k0,k0,0x1f

8045f414:  175b0002   bne         k0,k1,8045f420

8045f418:  00000000   nop

8045f41c:  409a7000   mtc0        k0,c0_epc

8045f420:  401a6000   mfc0        k0,c0_status

8045f424:  001ad0c0   sll         k0,k0,0x3

8045f428:  07400003   bltz        k0,8045f438

8045f42c:  03a0d821   move        k1,sp

8045f430:  3c1b8041   lui         k1,0x8041

8045f434:  8f7be938   lw          k1,-5832(k1)

8045f438:  03a0d021   move        k0,sp

8045f43c:  277dff50   addiu       sp,k1,-176

8045f440:  afba008c   sw          k0,140(sp)

8045f444:  afa30024   sw          v1,36(sp)

8045f448:  afa00018   sw          zero,24(sp)

8045f44c:  40036000   mfc0        v1,c0_status

8045f450:  afa20020   sw          v0,32(sp)

8045f454:  afa30098   sw          v1,152(sp)

8045f458:  afa40028   sw          a0,40(sp)

8045f45c:  40036800   mfc0        v1,c0_cause

8045f460:  afa5002c   sw          a1,44(sp)

8045f464:  afa300a8   sw          v1,168(sp)

8045f468:  afa60030   sw          a2,48(sp)

8045f46c:  40037000   mfc0        v1,c0_epc

8045f470:  afa70034   sw          a3,52(sp)

8045f474:  afa300ac   sw          v1,172(sp)

8045f478:  afb9007c   sw          t9,124(sp)

8045f47c:  afbc0088   sw          gp,136(sp)

8045f480:  afbf0094   sw          ra,148(sp)

8045f484:  37bc1fff   ori         gp,sp,0x1fff

8045f488:  3b9c1fff   xori        gp,gp,0x1fff

8045f48c:  afa1001c   sw          at,28(sp)

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

8045f494:  0804020d   j           80100834       // except_vec_vi_handler

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

 

except_vec_vi_handler

NESTED(except_vec_vi_handler, 0, sp)

    SAVE_TEMP

    SAVE_STATIC

    CLI

    LONG_L  s0, TI_REGS($28)

    LONG_S  sp, TI_REGS($28)

    PTR_LA  ra, ret_from_irq    //中断总出口

    jr  v0  // 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,0x8041
8045f004:  401a4000   mfc0        k0,c0_badvaddr
8045f008:  8f7b3000   lw          k1,12288(k1)   //pgd_current
8045f00c:  001ad582   srl         k0,k0,0x16
8045f010:  001ad080   sll         k0,k0,0x2
8045f014:  037ad821   addu        k1,k1,k0
8045f018:  401a2000   mfc0        k0,c0_context
8045f01c:  8f7b0000   lw          k1,0(k1)
8045f020:  001ad042   srl         k0,k0,0x1
8045f024:  335a0ff8   andi        k0,k0,0xff8
8045f028:  037ad821   addu        k1,k1,k0
8045f02c:  8f7a0000   lw          k0,0(k1)
8045f030:  8f7b0004   lw          k1,4(k1)
8045f034:  001ad182   srl         k0,k0,0x6
8045f038:  409a1000   mtc0        k0,c0_entrylo0
8045f03c:  001bd982   srl         k1,k1,0x6
8045f040:  409b1800   mtc0        k1,c0_entrylo1
8045f044:  000000c0   ehb
8045f048:  42000006   tlbwr
8045f04c:  42000018   eret
8045f050:  00000000   nop

 

b)        general_exception

8045f180:  401b6800   mfc0        k1,c0_cause

8045f184:  337b007c   andi        k1,k1,0x7c

8045f188:  3c1a8041   lui         k0,0x8041

8045f18c:  035bd021   addu        k0,k0,k1

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

8045f194:  03400008   jr          k0

8045f198:  00000000   nop

 

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);

 

原创粉丝点击