读ICC_IAR1_EL1寄存器导致几个异常?

Reading ICC_IAR1_EL1 register causes several exceptions?

我正在研究裸机中断控制器。底层架构是 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; 
}

根据 arm 规范,s3_0_c12_c12_0ICC_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 ?? ()