读取 ICC_IAR1_EL1 寄存器会导致几个异常?
Posted
技术标签:
【中文标题】读取 ICC_IAR1_EL1 寄存器会导致几个异常?【英文标题】:Reading ICC_IAR1_EL1 register causes several exceptions? 【发布时间】:2021-02-27 21:23:23 【问题描述】:我正在开发一个裸机中断控制器。底层架构是 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 没有帮助我
【问题讨论】:
【参考方案1】:您需要指定您希望您的 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 ?? ()
【讨论】:
感谢您提供有趣的反馈。我正在使用我提供的确切命令从源代码编译的 vanilla qemu 5.2.0。使用-machine virt,gic_version=3
在我的系统上会出现以下错误消息:Property 'virt-5.2-machine.gic_version' not found
。您可能使用了不同的版本,这可以解释这些差异。 documentation 也在使用 '-'
'。
gic-version
使用下划线而不是插入符号的风格在 2016 年关于 Ubuntu Wiki 的文章中被引用。直到最近,这可能是一种公认的语法。再次感谢。
除了阅读ICC_IAR1_EL1
,你还在做什么?我需要您使用的确切操作顺序。您是否设想打开一个新问题,并提供我使用的最小测试程序,并通过您正在使用的确切操作顺序进行扩充?我绝对愿意调查您的问题,其他人也可以。
嗨乔,我不这么认为,因为CurrentEL
与GIC
子系统无关,并且始终存在于armv8-a
处理器上。我的理解是,只有在实现GICv3
(或GICv4
)时,处理器中才会出现与GIC相关的寄存器。情况并非总是如此:您可以通过阅读ID_AA64PFR0_EL1
了解 GIC 寄存器接口是否可用 - 请参阅ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture profile
的D12.2.56 ID_AA64PFR0_EL1, AArch64 Processor Feature Register 0
部分。
mrs x0, ID_AA64PFR0_EL1
将x0
设置为0x00002222
和-machine virt,gic-version=2
,并设置0x01002222
和-machine virt,gic-version=3
。根据文档:GIC,[27:24] GIC CPU 接口:0x0 GIC CPU 接口被禁用,GICCDISABLE 为高,或未实现。 0x1 GIC CPU 接口已实现并启用,GICCDISABLE 为低。以上是关于读取 ICC_IAR1_EL1 寄存器会导致几个异常?的主要内容,如果未能解决你的问题,请参考以下文章