Reputation: 155
I am learning armv8 assembly program for my project. I wrote a simple program which tries to modify value of SCTLR_EL1 register. Unfortunately this code is not working. I am enabling I-cache, but the only thing I see is 0x0 in SCTLR_EL1.
.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
memmap
MEMORY
{
rom : ORIGIN = 0x00010000, LENGTH = 32K
}
SECTIONS
{
.text : { *(.text*) } > rom
}
QEMU command used is as follows:
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
Output I see in console is:
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 did not show anything:
(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
How can i modify CurrentEL and SCTLR_EL1? and how can I see those register value using GDB? Can someone please help? Thank you.
Upvotes: 1
Views: 116
Reputation: 66
The QEMU output what you see is caused from an exception. As @Jester mentioned this is because you are enabling -machine secure=on
. This option enables the ARM TrustZone extension. Use a higher program entry point address. An entry point at 0x40000000
should work.
You also have forgotten the isb
instruction after writing to SCTLR_EL1
. When you read directly SCTLR_EL1
after the write-back without isb
instruction, the content from SCTLR_EL1
is the old one (content before 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
To display the registers values with GDB you can use the command info registers
or info all-registers
. These should also include the SCTLR
register.
CurrentEL
can be extracted from the current program status register (cpsr
) in the output from GDB.
For changing/switching to a lower exception levels there you can find enough samples here on SO on other sites.
Upvotes: 2