I have written a simple arm64 bare-metal program to switch between EL2 and EL1. In EL2 and EL1, I am calling sprintf function as shown below.
void EL2Handler()
{
char buffer[100];
sprintf(buffer, "Current Exception Level is 2");
...
}
void EL1Handler()
{
char buffer[100];
sprintf(buffer, "Current Exception Level is 1");
...
}
When the sprintf called from EL1, it throws a synchronous exception. What could be the reason? Could it be related to memory access permissions? I am emulating this code on QEMU using virt machine.
The code is compile using
aarch64-none-elf-gcc -I. -nostartfiles -ffreestanding --specs=rdimon.specs -L. -Wl,-T,qemu-virt-aarch64.ld -o test.elf startup.s test.c
The execute line is
qemu-system-aarch64 -semihosting -m 1024M -nographic -machine virt,gic-version=2,virtualization=on -cpu max -kernel test.elf -S -gdb tcp::9000
This instruction causes the exception,
0x400012cc <sprintf+60> ldp q16, q17, [x1].
(gdb) p /x $x1 $2 = 0x47effdf8
(gdb) p /x $sp $3 = 0x47effdc0
(gdb) p /x $ESR_EL1 $5 = 0x1fe00000
The exception class in ESR_EL1 is 0b000111 "Access to SVE, Advanced SIMD or floating-point functionality trapped by CPACR_EL1.FPEN, CPTR_EL2.FPEN, CPTR_EL2.TFP, or CPTR_EL3.TFP control......". Is there a chance for floating point/sve/simd not implemented in EL1?