我正在为我的项目学习armv8汇编程序。我编写了一个简单的程序,尝试修改 SCTLR_EL1 寄存器的值。不幸的是这个代码不起作用。我正在启用 I-cache,但我唯一看到的是 SCTLR_EL1 中的 0x0。
.section .text
.global _start
_start:
mov x0, xzr // Initialize x0 to zero
// Set SCTLR_EL1 and confirm the modification
mrs x0, SCTLR_EL1 // Read SCTLR_EL1 into x0
orr x0, x0, #(1 << 12) // Enable I-Cache
msr SCTLR_EL1, x0 // Write back to SCTLR_EL1
mrs x0, SCTLR_EL1 // Read the modified SCTLR_EL1 into x0
// Store the value in a known memory location for debugging
ldr x1, =sctlr_el1_val
str x0, [x1]
b loop
loop:
b loop
.data
.align 8
sctlr_el1_val: .quad 0x0100 // Memory location to store the SCTLR_EL1 value
内存映射
MEMORY
{
rom : ORIGIN = 0x00010000, LENGTH = 32K
}
SECTIONS
{
.text : { *(.text*) } > rom
}
QEMU使用命令如下:
qemu-system-aarch64 -M virt -cpu cortex-a57 -m 512M -nographic -machine secure=on \
-S -s -kernel path_to_your_binary.elf -d in_asm,cpu
我在控制台中看到的输出是:
PSTATE=000003cd ---- EL3h
PC=0000000000000200 X00=0000000000000000 X01=0000000000000000
X02=0000000000000000 X03=0000000000000000 X04=0000000000000000
X05=0000000000000000 X06=0000000000000000 X07=0000000000000000
X08=0000000000000000 X09=0000000000000000 X10=0000000000000000
X11=0000000000000000 X12=0000000000000000 X13=0000000000000000
X14=0000000000000000 X15=0000000000000000 X16=0000000000000000
X17=0000000000000000 X18=0000000000000000 X19=0000000000000000
X20=0000000000000000 X21=0000000000000000 X22=0000000000000000
X23=0000000000000000 X24=0000000000000000 X25=0000000000000000
X26=0000000000000000 X27=0000000000000000 X28=0000000000000000
X29=0000000000000000 X30=0000000000000000 SP=0000000000000000
PSTATE=000003cd ---- EL3h
GDB没有显示任何东西:
(gdb) x/x 0x0100
0x100: 0x00000000
(gdb) x/x $SCTLR_EL1
Value can't be converted to integer.
(gdb) p/x $SCTLR_EL1
$1 = void
(gdb) display $SCTLR_EL1
1: $SCTLR_EL1 = void
(gdb) p/x $CurrentEL
$2 = void
如何修改CurrentEL和SCTLR_EL1?我如何使用 GDB 查看这些寄存器值? 有人可以帮忙吗?谢谢。
您看到的 QEMU 输出是由异常引起的。正如 @Jester 提到的,这是因为您正在启用
-machine secure=on
。此选项启用 ARM TrustZone 扩展。使用更高的程序入口点地址。 0x40000000
处的入口点应该可以工作。
写信给
isb
后,您也忘记了SCTLR_EL1
指令。当您回写后直接读取SCTLR_EL1
而没有isb
指令时,SCTLR_EL1
中的内容是旧的(msr SCTLR_EL1, x0
之前的内容)。
.section .text
.func _start,_start
.type _start,%function
.global _start
_start:
mov x0, xzr /* Initialize x0 to zero */
mrs x0, SCTLR_EL1 /* Read SCTLR_EL1 into x0 */
orr x0, x0, #(1 << 12) /* Enable I-Cache */
msr SCTLR_EL1, x0 /* Write back to SCTLR_EL1 */
isb /* Instruction Synchronization barrier */
loop:
b loop
.size _start, . - _start
.endfunc
要使用 GDB 显示寄存器值,您可以使用命令
info registers
或 info all-registers
。这些还应包括 SCTLR
寄存器。
CurrentEL
可以从 GDB 输出中的当前程序状态寄存器 (cpsr
) 中提取。
要更改/切换到较低的异常级别,您可以在其他站点上找到足够的示例。