在 QEMU aarch64 仿真上没有得到系统定时器中断

Not getting system timer interrupts on QEMU aarch64 emulation

我正在学习使用 QEMU 作为模拟器的 ARM 裸机开发。我以 this github repo 为例。

向量是为 EL1 定义的:

vectors:
    ventry  sync_invalid_el1t           // Synchronous EL1t
    ventry  irq_invalid_el1t            // IRQ EL1t
    ventry  fiq_invalid_el1t            // FIQ EL1t
    ventry  error_invalid_el1t          // Error EL1t

    ventry  sync_invalid_el1h           // Synchronous EL1h
    ventry  el1_irq                 // IRQ EL1h
    ventry  fiq_invalid_el1h            // FIQ EL1h
    ventry  error_invalid_el1h          // Error EL1h

    ventry  sync_invalid_el0_64         // Synchronous 64-bit EL0
    ventry  irq_invalid_el0_64          // IRQ 64-bit EL0
    ventry  fiq_invalid_el0_64          // FIQ 64-bit EL0
    ventry  error_invalid_el0_64            // Error 64-bit EL0

    ventry  sync_invalid_el0_32         // Synchronous 32-bit EL0
    ventry  irq_invalid_el0_32          // IRQ 32-bit EL0
    ventry  fiq_invalid_el0_32          // FIQ 32-bit EL0
    ventry  error_invalid_el0_32            // Error 32-bit EL0

.globl irq_vector_init
irq_vector_init:
    adr x0, vectors     // load VBAR_EL1 with virtual
    msr vbar_el1, x0        // vector table address
    ret

并设置好:

void enable_interrupt_controller()
{
    put32(ENABLE_IRQS_1, SYSTEM_TIMER_IRQ_1);
}

处理程序是这样定义的:

el1_irq:
    kernel_entry 
    bl  handle_irq
    kernel_exit 

以下是定时器处理程序:

void handle_irq(void)
{
    unsigned int irq = get32(IRQ_PENDING_1);
    switch (irq) {
        case (SYSTEM_TIMER_IRQ_1):
            handle_timer_irq();
            break;
        default:
            printf("Unknown pending irq: %x\r\n", irq);
    }
}

我正在使用以下命令启动二进制文件,但我没有得到计时器处理程序打印,尽管其他打印正在工作并且二进制文件对我来说工作正常:

$ qemu-system-aarch64 -M raspi3 -device loader,file=./kernel8.img,addr=0x0 -serial null -serial stdio -display none

编辑

环境详细信息:

naveen@workstation:~$ qemu-system-aarch64 --version
QEMU emulator version 4.2.1 (Debian 1:4.2-3ubuntu6.18)
Copyright (c) 2003-2019 Fabrice Bellard and the QEMU Project developers
naveen@workstation:~$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.3 LTS
Release:    20.04
Codename:   focal

调试的第一步是在 QEMU 中打开与 bcm2835 系统计时器相关的事件跟踪,我认为您的代码正在使用它。您可以使用命令行选项 -d trace:bcm2835_systmr* 来做到这一点。特别是“timer #1 expired”(或任何计时器编号)消息表明计时器已引发其中断。如果计时器没有引发中断,那么您对计时器的编程有误;如果是,那么你可能没有正确设置中断控制器。

您可能还应该 double-check 您确实按照预期在 EL1 中执行。

旧版本的 QEMU 支持 raspi3 板但没有实现这个特定的系统定时器设备;因此,如果您没有看到计时器过期跟踪,则值得检查您的 QEMU 是否足够新。 6.2.0肯定实现了这个设备。