[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Possible bug in Aarch64 single-stepping
From: |
Chris Howard |
Subject: |
Possible bug in Aarch64 single-stepping |
Date: |
Sat, 7 May 2022 15:42:40 +0200 |
Hi, I’m writing a simple debugger in assembly code for the Raspberry Pi 3B (in
aarch64).
I’m using QEMU 7.0.0. Everything is running in EL1. (I have MDE and KDE set in
MDSCR_EL1).
I’m coming across Unexpected Behaviour when playing with single-stepping:
It appears that single-stepping is enabled (ie. an exception is generated after
every instruction) when the SS bit (bit-0) is set in MDSCR_EL1 and debug events
are enabled in the CPSR (“D” bit clear) *** irrespective of whether the SS bit
(bit-21) is set in CPSR or not ***.
I thought the SS bit (bit-21) needs to be set in CPSR for single-stepping to
occur (and that it gets cleared whenever an exception is taken and needs to be
reset if one wants to single-step again).
Have I misunderstood / misconfigured something, or is this a bug?
Attached is a minimal(ish) example:
Regards,
chris
/*
******************************************************************************************
**** built with ****
aarch64-elf-as -march=armv8-a+crc+crypto -mcpu=cortex-a53 --gstabs minimal.s -o
minimal.o
aarch64-elf-ld minimal.o -T memmap -o minimal.elf
aarch64-elf-objcopy -O binary minimal.elf minimal.img
aarch64-elf-objdump -d -j .text minimal.elf > minimal.list
**** memmap is ****
MEMORY
{
ram : ORIGIN = 0x80000, LENGTH = 0x80000000
}
SECTIONS
{
.init : { *(.init*) } > ram
.text : { *(.text*) } > ram
.data : { *(.data*) } > ram
.bss : { *(.bss*) } > ram
}
**** qemu cmd ****
qemu-7.0.0/build/qemu-system-aarch64 -M raspi3b -kernel minimal.img -serial
null -serial stdio -s -S
**** gdb cmd ****
/opt/local/gnuaarch64/bin/aarch64-none-elf-gdb -x gdb.cmds minimal.elf
**** gdb.cmds is ****
target remote :1234
set $pc = 0x80000
******************************************************************************************
*/
.section .text
.global _start
_start:
mrs x0, mpidr_el1 // x0 = 00000000.8000.0000
and x0, x0, 0b11
cbz x0, 2f // branch fwd if core == 0 ...
1:
wfe // ... else wait for exception (ie
sleep)
b 1b
2:
// mrs x0, scr_el3 // Can't access this from EL2. But gdb
says it's 0x0501
// 0000.0101|0000.0001 10:RW=1
8:HCE=1 0:NS=1
// mrs x0, hcr_el2 // x0 -> 1<<31 (34:E2H=0 31:RW=1
27:TGE=0 2:C=0 1:M=0)
// mrs x0, sctlr_el1 // x0 -> 00c5.0838 =
0000.0000|1100.0101|0000.1000|0011.1000
mov x0, 0x0800 // -SA -SA0, -CP15BEN -nTWE -nTWI
+20:RES1 +28:RES1 +29:RES1
movk x0, 0x30d0, lsl 16 // x0 -> 30d0.0800 =
0011.0000|1101.0000|0000.1000|0000.0000
msr sctlr_el1, x0
adr x0, vectors
msr vbar_el1, x0
adr x0, _start // 0x0008.0000 = 512k
msr sp_el1, x0 // set EL1's SP
mov x0, 0x3c5 // NOTE: bit 21:SS is NOT set
msr spsr_el2, x0 // DAIF exceptions masked. A64 state.
EL1. SP = SP_ELx
adr x0, init
msr elr_el2, x0
eret // We're in EL2. Pretend we're
"returning" to EL1 init:
init:
msr OSLAR_EL1, xzr // unlock OS lock
mov x0, 0b101<<13 // 15:MDE (enable debugging) and 13:KDE
(and kernel debug events)
orr x0, x0, 0b1<<0 // enable SS debug exceptions
msr MDSCR_EL1, x0
mov w0, 0 // these all execute ok
mov w0, 1
b 1f
mov w0, -1
1:
msr daifclr, 0b1111 // enable all interrupts and debugging
exceptions
mov w0, 3 // this causes an exception ESR_EL1 =
0xce000022 (see ARMv8ARM D1-1801)
mov w0, 4 // 0xce = 0b1100.1110|- >> 26 =
0b0011.0011 = 0x33 = exception class
// ie. SS from same EL. ** even though
CPSR was 0x00000005 **
svc 124
mov w0, 5
b 2f
mov w0, -2
2:
mov w0, 6
loop:
b loop
//
******************************************************************************************************
exc_svc:
and w0, w0, 0xffff
cmp w0, 123
beq svc_123
cmp w0, 124
beq svc_124
b exception_return // undefined SVCs ignored
svc_123:
mrs x0, SPSR_EL1
orr x0, x0, 0b1<<21 // (re)enable SS in CPSR
msr SPSR_EL1, x0
b exception_return
svc_124:
mrs x0, SPSR_EL1
bic x0, x0, 0b1<<21 // disable SS in CPSR (not really
necessary since SS gets
msr SPSR_EL1, x0 // cleared when an exception (eg. SVC)
gets taken anyway)
b exception_return
exc_dbg:
mrs x0, elr_el1
mrs x0, SPSR_EL1
bic x0, x0, 0b1<<21 // (re)enable SS in CPSR
msr SPSR_EL1, x0
b exception_return
exception_return:
ldp x2, x3, [sp], 16
ldp x0, x1, [sp], 16
eret
.align 11
vectors:
// ************************ from current EL using SP_EL0
***************************
v0: // Synchronous
b v0
.align 7
v1: // IRQ
b v1
.align 7
v2: // FIQ
b v2
.align 7
v3: // SError
b v3
// ************************ from current EL using SP_EL1+
**************************
.align 7
v10: // Synchronous (SVC, MMU, DEBUG)
stp x0, x1, [sp, -16]!
stp x2, x3, [sp, -16]!
mrs x0, esr_el1 // exception syndrome (ARMv8ARM p.
D1-1801)
mov w1, w0, lsr 26 // w1 -> exception class
cmp w1, 0x15 // SVC
beq exc_svc
b exc_dbg
.align 7
v11: // IRQ
b v11
.align 7
v12: // FIQ
b v12
.align 7
v13: // SError
b v13
// ************************ from lower EL using A64
********************************
.align 7
v20: // Synchronous
b v20
.align 7
v21: // IRQ
b v21
.align 7
v22: // FIQ
b v22
.align 7
v23: // SError
b v23
//
*********************************************************************************
data: