ls2k1000在linux3.10内核下的中断分析

目录

1 基本知识

1.1 ls2k1000的中断组成

1.2 GS264中断相关的寄存器

2 ls2K1000 在 linux3.10 内核下的中断初始化过程

2.1 大致过程

2.2 函数具体分析:trap_init();

2.2.1 函数说明

2.2.2 trap_init()函数关键代码

2.3 函数具体分析:early_irq_init();

2.3.1 函数说明

2.3.2 early_irq_init()函数的代码

2.4 函数具体分析:init_IRQ();

2.4.1 函数说明

2.4.2 init_IRQ()函数的代码

2.4.3 arch_init_irq()——平台中断初始化函数

2.4.4 mips_cpu_irq_init()——设置IP0~IP7的irq_chip和irq_desc->handler_irq

2.4.5 setup_irq_default()——设置64个I/O中断的irq_chip和irq_desc->handle_irq

2.5 PCIE MSI中断的初始化设置

2.5.1 说明

2.5.2 MSI初始化代码

2.6 初始化过程总结

2.6.1 每个中断的irq_desc和irq_chip的设置

2.6.2 ls2k1000的64个I/O中断的路由设置

3 ls2k1000在linux3.10内核下的中断的处理过程

3.1 主要流程

参考资料



1 基本知识

1.1 ls2k1000的中断组成

龙芯 2K1000 处理器片内集成 2 个 GS264 处理器核。

GS264处理器核支持32种异常,其中0号异常用来处理中断。而GS264有8个中断(IP0~IP7)。

ls2k1000的中断控制器支持64个I/O中断,这64个I/O中断对应64个中断路由寄存器,可以单独控制每个外部中断路由到GS264的IP2~IP5。

龙芯 2K1000 的 PCIE 控制器支持 MSI 中断类型。分 配 给 MSI 的 地 址 有 两 个 , 分 别 对 应 寄 存 器INT_MSI_ADDR_0 (0x1fe114b0)和 INT_MSI_ADDR_1(0x1fe114f0),每个地址可以接受 32 个中断消息,分别与现有的中断引脚低 32 位和高 32 位复用(通过变量ls_msi_irq_mask决定复用功能,ls_msi_irq_mask的值在dts文件里设置,请看2.5.2小节

GS264的0号异常GS264的  IP7 
GS264的  IP6 
GS264的  IP2~IP5LS2K1000的64个I/O中断
GS264的  IP0~IP1 

1.2 GS264中断相关的寄存器

EBase 寄存器 (CP0 Register 15, Select 1):例外入口地址

Cause.IP:待处理软件中断标识

Status.IM:中断屏蔽位

Cause.ExcCode:例外编码

 

2 ls2K1000 在 linux3.10 内核下的中断初始化过程

2.1 大致过程

start_kernel();				        //init/main.c
    -> trap_init();				//arch/mips/kernel/traps.c
        -> set_handler();			//arch/mips/kernel/traps.c
        -> set_except_vector();			//arch/mips/kernel/traps.c
    -> early_irq_init();			//kernel/irq/irqdesc.c
    -> init_IRQ();				//arch/mips/kernel/irq.c
        -> arch_init_irq();			//arch/mips/loongson2/irq.c
            -> mips_cpu_irq_init();			//arch/mips/kernel/irq_cpu.c
                -> irq_set_chip_and_handler();		//include/linux/irq.h
            -> setup_irq_default();			//arch/mips/loongson2/irq.c
                -> irq_set_chip_and_handler();		//include/linux/irq.h
            -> setup_irq_mode();			//arch/mips/loongson2/irq.c

2.2 函数具体分析:trap_init();

2.2.1 函数说明

        体系相关,将异常向量处理函数except_vec3_generic加载到地址BASE+0x180处,并为exception_handles[]中的32种异常设置处理函数。

        其中,0号异常是所有中断的入口。在trap_init()函数中,将0号异常的处理函数设置为handle_init()函数,这是一个汇编函数。handle_init()函数的代码请看3.1小节。

2.2.2 trap_init()函数关键代码

//arch/mips/kernel/traps.c
void __init trap_init(void)
{
    ......
    set_except_vector(0, using_rollback_handler() ? 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);
    ......
}

2.3 函数具体分析:early_irq_init();

2.3.1 函数说明

体系平台无关,主要用来设置每个中断默认的irq_desc。

2.3.2 early_irq_init()函数的代码

//kernel/irq/irqdesc.c
int __init early_irq_init(void)
{
    int count, i, node = first_online_node;
    struct irq_desc *desc;

    init_irq_default_affinity();

    printk(KERN_INFO "NR_IRQS:%d\n", NR_IRQS);

    desc = irq_desc;
    count = ARRAY_SIZE(irq_desc);

    for (i = 0; i < count; i++) {
        desc[i].kstat_irqs = alloc_percpu(unsigned int);
        alloc_masks(&desc[i], GFP_KERNEL, node);
        raw_spin_lock_init(&desc[i].lock);
        lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
        desc_set_defaults(i, &desc[i], node, NULL);
    }
    return arch_early_irq_init();
}

2.4 函数具体分析:init_IRQ();

2.4.1 函数说明

init_IRQ()函数的主要功能是调用平台相关的中断初始化函数:arch_init_irq();

2.4.2 init_IRQ()函数的代码

//arch/mips/kernel/irq.c
void __init init_IRQ(void)
{
    int i;

#ifdef CONFIG_KGDB
    if (kgdb_early_setup)
        return;
#endif

    for (i = 0; i < NR_IRQS; i++)
        irq_set_noprobe(i);

    arch_init_irq();			//

#ifdef CONFIG_KGDB
    if (!kgdb_early_setup)
        kgdb_early_setup = 1;
#endif
}

2.4.3 arch_init_irq()——平台中断初始化函数

//arch/mips/loongson2/irq.c
void  __init arch_init_irq(void)
{
    mips_cpu_irq_init();
    set_c0_status(STATUSF_IP4 | STATUSF_IP5 | STATUSF_IP6);	//使能GS264的4、5和6号中断。
    setup_irq_default();
    setup_irq_mode();
}

2.4.4 mips_cpu_irq_init()——设置IP0~IP7的irq_chip和irq_desc->handler_irq

GS264处理器核的IP0~IP7中断的处理函数(irq_desc->handler_irq)都是handle_percpu_irq();

//arch/mips/kernel/irq_cpu.c
void __init mips_cpu_irq_init(void)
{
    int irq_base = MIPS_CPU_IRQ_BASE;
    int i;

    /* Mask interrupts. */
    clear_c0_status(ST0_IM);
    clear_c0_cause(CAUSEF_IP);

    /* Software interrupts are used for MT/CMT IPI */
    for (i = irq_base; i < irq_base + 2; i++)
        irq_set_chip_and_handler(i, cpu_has_mipsmt ?
                     &mips_mt_cpu_irq_controller :
                     &mips_cpu_irq_controller,
                     handle_percpu_irq);

    for (i = irq_base + 2; i < irq_base + 8; i++)
        irq_set_chip_and_handler(i, &mips_cpu_irq_controller,
                     handle_percpu_irq);
}

2.4.5 setup_irq_default()——设置64个I/O中断的irq_chip和irq_desc->handle_irq

ls2k1000的64个I/O中断的处理函数(irq_desc->handler_irq)都是handle_level_irq();

//arch/mips/loongson2/irq.c
void __init setup_irq_default(void)
{
    unsigned int i;
    int core_id = (read_c0_ebase() & 0x3ff);

    for (i = LS2K_IRQ_BASE; i < LS2K_IRQ_BASE + 64; i++) {
        irq_set_chip_and_handler(i, &ls64_irq_chip, handle_level_irq);
        set_irq_attr(i, 1 << (STATUSB_IP4 - 10), 1 << core_id, 0);	       //set_irq_attr ()函数设置中断路由到core_id决定的处理器的IP4,同时设置路由模式。
    }

    ls64_conf_write32(ls_msi_irq_mask, (void *)(CKSEG1ADDR(CONF_BASE) + INT_LO_OFF + INT_EDG_OFF ));
    ls64_conf_write32((ls_msi_irq_mask >> 32)|(0x1f << 12), (void *)(CKSEG1ADDR(CONF_BASE) + INT_LO_OFF + INT_EDG_OFF + 0x40));
}

2.5 PCIE MSI中断的初始化设置

2.5.1 说明

龙芯 2K1000 的 PCIE 控制器支持 MSI 中断类型。分 配 给 MSI 的 地 址 有 两 个 , 分 别 对 应 寄 存 器INT_MSI_ADDR_0 (0x1fe114b0)和 INT_MSI_ADDR_1(0x1fe114f0),每个地址可以接受 32 个中断消息,分别与现有的中断引脚低 32 位和高 32 位复用

2.5.2 MSI初始化代码

从dts文件里获取ls_msi_irq_mask的值,并设置MSI中断路由到GS264处理器核的IP5。

//arch/mips/loongson2/pci_msi.c
static int ls_pci_msi_probe(struct platform_device *dev)
{
    ......
    mask_p = (__be32 *)of_get_property(np, "msi-mask", NULL);
    if (mask_p == NULL){
            pr_info("No msi-mask property !\n");
            return -ENXIO;
    }else{
            ls_msi_irq_mask = of_read_number(mask_p,2);
    }   
    ......
    for (i = LS64_MSI_IRQ_BASE ; i < LS64_MSI_IRQ_BASE + 64; i++) {
            if((1UL << (i - LS64_MSI_IRQ_BASE)) & ls_msi_irq_mask){
                    set_irq_attr(i, 1 << (STATUSB_IP5 - 10), 1 << core_id, 0); 
            }   
    }
    ......
}

 

2.6 初始化过程总结

2.6.1 每个中断的irq_desc和irq_chip的设置

每个中断的初始irq_desc变量在kernel/irq/irqdesc.c 文件的early_irq_init()函数里设置,

GS264处理器核的8个中断(IP0~IP7)最后在arch/mips/kernel/irq_cpu.c 文件的mips_cpu_irq_init()函数里通过函数irq_set_chip_and_handler()来设置最终的irq_chip和irq_desc->handle_irq。8个中断(IP0~IP7)设置的irq_desc->handle_irq都是handle_percpu_irq();

ls2k1000的64个I/O中断最后在arch/mips/loongson2/irq.c文件的setup_irq_default()函数里通过函数irq_set_chip_and_handler()来设置最终的irq_chip和irq_desc->handle_irq。64个I/O中断设置的irq_desc->handle_irq都是handle_level_irq();

 

2.6.2 ls2k1000的64个I/O中断的路由设置

ls2k1000的64个I/O中断和64个MSI中断复用中断线。

当作为I/O中断时,被路由到GS264处理器核的IP4。设置过程如下:

start_kernel();				        //init/main.c
    -> init_IRQ();				//arch/mips/kernel/irq.c
        -> arch_init_irq();			//arch/mips/loongson2/irq.c
            -> setup_irq_default();		//arch/mips/loongson2/irq.c
                -> set_irq_attr();		//arch/mips/loongson2/irq.c

当作为MSI中断时,被路由到GS264处理器核的IP5。设置过程如下:

ls_pci_msi_probe();				//arch/mips/loongson2/pci_msi.c
    -> set_irq_attr();

 

3 ls2k1000在linux3.10内核下的中断的处理过程

3.1 主要流程

handle_int();				//arch/mips/kernel/genex.S
    -> plat_irq_dispatch();		//arch/mips/loongson2/irq.c
        -> ip7_dispatch();		//arch/mips/loongson2/irq.c	计时器中断和性能计数器中断
            -> do_IRQ();		//arch/mips/kernel/irq.c
        -> ip6_dispatch();		//arch/mips/loongson2/irq.c	处理IPI中断
            -> ls64_ipi_interrupt();	//arch/mips/loongson2/smp.c
        -> ip5_dispatch();		//arch/mips/loongson2/irq.c;	处理MSI中断
            -> do_IRQ;			//arch/mips/kernel/irq.c
        -> ip4_dispatch();		//arch/mips/loongson2/irq.c	处理I/O中断
            -> do_IRQ;			//arch/mips/kernel/irq.c

 

参考资料

LoongsonGS264_user(2018年7月,http://www.loongson.cn/product/dc/)

Loongson2K1000_user(2020年4月,http://www.loongson.cn/product/dc/)

 

 

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值