在 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肯定实现了这个设备。
我正在学习使用 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肯定实现了这个设备。