微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 arm64 GICv3 中捕获 IRQ 的步骤?

如何解决在 arm64 GICv3 中捕获 IRQ 的步骤?

我正在研究一个裸机中断控制器,GIC 版本 3。底层架构是 Virt,带有 QEMU,和一个 cpu Arm Cortex-72,aarch64:

qemu-system-aarch64 -machine virt,gic-version=3 -cpu cortex-a72 -nographic -kernel kernel.elf

根据ARMv8-A guide,Interrupt Group 1 Enable register,寄存器0的位ICC_IGRPEN1_EL1负责IRQ的激活。这是其中的摘录:

enter image description here

我指定我在非安全模式下工作。

我想从时序上下文生成一个 IRQ。计时器运行良好,但由于任何原因,即使 0ICC_IGRPEN1_EL1 位设置为 1,也未捕获 IRQ。

由于我使用了多个标头,因此无法为您提供最小示例。我没有办法,如果你能建议我怎么做,请做。不过,我已经尽力提出了一个明确的问题,所以我真的希望你能帮上忙。

这是生成 IRQ 的函数的摘录:

 void timer_init(void)
{
    uint64_t ticks,current_cnt;
 
    // disable the timer
    disable_cntv();

    //read system frequency
    cntfrq = raw_read_cntfrq_el0();

    // Next timer IRQ is after 3 sec(s).
    ticks = 3 * cntfrq;
    
    // Get value of the current timer
    current_cnt = raw_read_cntvct_el0();
        
    // Set the interrupt in Current Time + TimerTick
    raw_write_cntv_cval_el0(current_cnt + ticks);

    // Enable the timer
    enable_cntv();

    // Enable IRQ   
    enable_irqs();
    
    while(1){
        wfi();  
    }
}

函数 enable_irqs 的定义如下:

void enable_irqs(void) {
    set_gic_gicc_igrpen1_el1(0x1);
}

反过来,函数 set_gic_gicc_igrpen1_el1 是:

void set_gic_gicc_igrpen1_el1(uint64_t value)
{
    __asm__ __volatile__("msr s3_0_c12_c12_7,%0" : : "r" (value));
}

我使用 gdb 验证了所有值:定时器有效并且寄存器 ICC_IGRPEN1_EL1 的最后一位设置为 1。您是否注意到此代码中存在任何我未收到任何 IRQ 的错误

不完全,我提到的其他功能实现如下:

void disable_cntv(void)
{
    uint32_t cntv_ctl;

    cntv_ctl = raw_read_cntv_ctl();
    cntv_ctl &= ~CNTV_CTL_ENABLE;
    __asm__ __volatile__("msr CNTV_CTL_EL0,%0\n\t" : : "r" (cntv_ctl) : "memory");
}

void enable_cntv(void)
{
    uint32_t cntv_ctl;

    cntv_ctl = raw_read_cntv_ctl();
    cntv_ctl |= CNTV_CTL_ENABLE;
    __asm__ __volatile__("msr CNTV_CTL_EL0,%0\n\t" : : "r" (cntv_ctl) : "memory");
}

uint32_t raw_read_cntfrq_el0(void)
{
    uint32_t cntfrq_el0;

    __asm__ __volatile__("mrs %0,CNTFRQ_EL0\n\t" : "=r" (cntfrq_el0) : : "memory");
    return cntfrq_el0;
}

void raw_write_cntv_cval_el0(uint64_t cntv_cval_el0)
{
    __asm__ __volatile__("msr CNTV_CVAL_EL0,%0\n\t" : : "r" (cntv_cval_el0) : "memory");
}

    uint64_t raw_read_cntvct_el0(void)
{
    uint64_t cntvct_el0;
        __asm__ __volatile__("mrs %0,CNTVCT_EL0\n\t" : "=r" (cntvct_el0) : : "memory");
        return cntvct_el0;
}

/* Wait For Interrupt */
#define wfi()       asm volatile("wfi" : : : "memory")

CNTV_CTL_ENABLE 的定义如下:

#define CNTV_CTL_ENABLE     (1 << 0)    /* Enables the timer */ 

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。