qemu-system-aarch64 总是进入异常级别 2,并在切换到 EL1 时挂起。为什么?

qemu-system-aarch64 always entering exception level 2 and hangs when switching to EL1. Why?

我正在使用 qemu-system-aarch64 在 x86 主机上模拟 raspi3 (ARM Cortex A-53)。这是我用来启动裸机映像的命令:

$ 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

$ qemu-system-aarch64 -M raspi3 -kernel kernel8.img -serial null -serial stdio -display none

kernel8.img 的代码取自此处:https://github.com/s-matyukevich/raspberry-pi-os/tree/master/src/lesson02/src。以下函数用于获取当前异常级别:

.globl get_el
get_el:
    mrs x0, CurrentEL
    lsr x0, x0, #2
    ret

以下代码试图在启动时切换到 EL1,我不得不将其注释掉,否则这段代码将无限期挂起:

master:
    ldr x0, =SCTLR_VALUE_MMU_DISABLED
    msr sctlr_el1, x0       

    ldr x0, =HCR_VALUE
    msr hcr_el2, x0

    ldr x0, =SCR_VALUE
    msr scr_el3, x0

    ldr x0, =SPSR_VALUE
    msr spsr_el3, x0

    adr x0, el1_entry       
    msr elr_el3, x0

    eret        

上面这段代码被注释后,我的程序至少运行了,但是打印的Exception level为2。

我有以下两个问题:

  1. 根据相应的 repo docs, when we are using a hypervisor, EL2 is used by the host OS so that the guest OS uses EL1 or EL0. But why my baremetal guest OS is entering EL2 by default? It should have been EL1 as per my understanding. Also, 也有 EL1 启动。不确定是否发生了变化,或者我是否遗漏了什么。
  2. 为什么切换到 EL1 的代码挂在第 msr scr_el3, x0 行?

您正在 运行 学习 EL2。指令“msr scr_el3, x0”试图写入一个 EL3-only 寄存器,如果您从较低的 EL 尝试它,它将导致 UNDEF 异常。换句话说,您尝试使用的代码片段在 EL3 中写入 运行,如果您想在 EL2 中 运行 则需要进行更改。

你的代码在 EL2 上 运行ning 的原因是因为你使用了 QEMU 的“-kernel”参数并传递给它一个二进制 (non-ELF) 文件,它告诉 QEMU “你应该以 Linux 内核启动协议记录应启动 Linux 内核的方式启动我”。该协议说“在 EL2 或 EL1 中启动我,推荐使用 EL2”,这就是 QEMU 所做的。

有关 QEMU 提供的用于加载访客代码的各种选项的更多信息,请参阅 this answer。请注意,QEMU 提供“以 Raspberry PI bootrom 代码启动它的方式启动此映像或 ELF 文件”:您可能必须调整旨在 运行 在真正的 bare-metal 板上一点点。