如何解决读取ICC_IAR1_EL1寄存器导致几个异常?
我正在研究裸机中断控制器。底层架构是Virt,带QEMU,cpu Arm Cortex-72,aarch64。例如,我为您提供 Makefile 的摘录:
run:
$(MAKE) kernel.elf
qemu-system-aarch64 -machine virt -cpu cortex-a72 -nographic -kernel kernel.elf
我定义了一个异常处理程序,每次发生异常时都会调用它。这是摘录(输出写在 UART 上):
void common_trap_handler(exception_frame *exc)
{
uart_puts("\nException Handler! (");
uint32_t val = raw_read_current_el();
uart_puts("\n\tCurrent EL = ");
uart_puthex(val);
uart_puts("\t");
uart_puts("exc_type : ");
uart_puthex(exc->exc_type);
val = raw_read_icc_iar1_el1();
uart_puts("\n\tICC IAR1 EL1 = ");
uart_puthex(val);
// rest of the exception handler
}
对寄存器的访问是通过汇编代码完成的。读取当前异常级别有效:
uint32_t raw_read_current_el(void)
{
uint32_t current_el;
__asm__ __volatile__("mrs %0,CurrentEL\n\t" : "=r" (current_el) : : "memory");
return current_el;
}
读取 ICC_IAR1_EL1
寄存器不会(更多详情如下):
uint32_t raw_read_icc_iar1_el1(void)
{
uint32_t icc_iar1_el1 = 0;
__asm__ __volatile__("mrs %0,s3_0_c12_c12_0\n\t" : "=r" (icc_iar1_el1) : : "memory");
return icc_iar1_el1;
}
其中 s3_0_c12_c12_0
是根据 arm 规范的 ICC_IAR1_EL1
的 ID,因为它被定义为“没有架构名称的寄存器”。
访问 ICC_IAR1_EL1
会触发无数其他异常。这是输出的摘录(重复多次):
Exception Handler! (
Current EL = 0x00000000 00000004 exc_type : 0x00000000 00000011
Exception Handler! (
Current EL = 0x00000000 00000004 exc_type : 0x00000000 00000011
Exception Handler! (
Current EL = 0x00000000 00000004 exc_type : 0x00000000 00000011
我不明白为什么。根据寄存器 ICC_IAR1_EL1
的名称,应该以最低权限 EL1 访问该寄存器。这由输出 Current EL = 0x00000000 00000004
验证。你知道如何读取ICC_IAR1_EL1
寄存器的内容吗?不幸的是,the official ARM guide 没有帮助我
解决方法
您需要指定您希望 qemu-virt 机器使用 GICv3 以便能够使用 GIC 的注册接口,而不是具有内存映射接口的 GICv2,这是qem-virt 机器默认使用 GIC。
以下命令工作正常:
qemu-system-aarch64 -machine virt,gic-version=3 -cpu cortex-a72 -nographic -kernel kernel.elf
我的测试程序:
.title minimal-aarch64.s
.arch armv8-a
.text
.section .text.startup,"ax"
.globl _start
.weak test
_start:
ldr x0,=__StackTop
mov sp,x0
bl test
wait: wfe
b wait
test:
mrs x0,s3_0_c12_c12_0
ret
.end
使用您的命令或
qemu-system-aarch64 -machine virt,gic-version=2 -cpu cortex-a72 -nographic -kernel kernel.elf
是否会在程序从 test
子例程返回之前引发异常,这是您观察到的行为:
Breakpoint 2,test () at minimal-aarch64.s:15
0x0000000000000200 in ?? ()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。