freedomtan / aarch64-bare-metal-qemu

aarch64 bare metal test on qemu
GNU General Public License v3.0
92 stars 31 forks source link

Quad instructions throw exceptions #1

Open ilg-ul opened 2 years ago

ilg-ul commented 2 years ago

Hi @freedomtan,

I did some tests with this code, aiming to use a similar approach in other projects. The initial tests were successful, but when trying to use printf(), the code crashed.

After some more tests, I found the crash to happen at the first quad store instruction: str q0, ....

I'm not yet very familiar with AArch64 modes, but it looks like quad instructions are not enabled.

If you want to reproduce the issue, change the kernel.c code to use:

int my_printf(const char *format, ...);

int main(void)
{
  // exception_svc_test();
  my_printf("baburiba");
  timer_test();
}

#include <stdarg.h>

int my_printf(const char *format, ...)
{
  va_list arguments;
  va_start(arguments, format);

  int ret = my_vprintf(format, arguments);

  va_end(arguments);
  return ret;
}

int my_vprintf(const char *format, va_list arguments)
{
  return 42;
}

int _write(char *buf, int num) { return num; }

void *
_sbrk(int incr) { return 0; }

The exception displayed was:

Exception Handler! (AARCH64_EXC_SYNC_SPX)
An exception occur:
exc_type: 0x00000000 00000011
ESR: 0x00000000 1FE00000  SP: 0x00000000 40FFFEC0 ELR: 0x00000000 40001910 SPSR: 0x00000000 600003C5
 x0: 0x00000000 40002960  x1: 0x00000000 40000000  x2: 0x00000000 00000000  x3: 0x00000000 00000000
 x4: 0x00000000 00000000  x5: 0x00000000 00000000  x6: 0x00000000 00000000  x7: 0x00000000 00000000
 x8: 0x00000000 00000000  x9: 0x00000000 00000000 x10: 0x00000000 00000000 x11: 0x00000000 00000000
x12: 0x00000000 00000000 x13: 0x00000000 00000000 x14: 0x00000000 00000000 x15: 0x00000000 00000000
x16: 0x00000000 00000000 x17: 0x00000000 00000000 x18: 0x00000000 00000000 x19: 0x00000000 00000000
x20: 0x00000000 00000000 x21: 0x00000000 00000000 x22: 0x00000000 00000000 x23: 0x00000000 00000000
x24: 0x00000000 00000000 x25: 0x00000000 00000000 x26: 0x00000000 00000000 x27: 0x00000000 00000000
x28: 0x00000000 00000000 x29: 0x00000000 40FFFEC0 x30: 0x00000000 400018D8

The suspected code is:

00000000400018e8 <my_printf>:
    400018e8:   a9ad7bfd    stp x29, x30, [sp, #-304]!
    400018ec:   910003fd    mov x29, sp
    400018f0:   f9001fe0    str x0, [sp, #56]
    400018f4:   f9007fe1    str x1, [sp, #248]
    400018f8:   f90083e2    str x2, [sp, #256]
    400018fc:   f90087e3    str x3, [sp, #264]
    40001900:   f9008be4    str x4, [sp, #272]
    40001904:   f9008fe5    str x5, [sp, #280]
    40001908:   f90093e6    str x6, [sp, #288]
    4000190c:   f90097e7    str x7, [sp, #296]
    40001910:   3d801fe0    str q0, [sp, #112] <--- first quad store!
    40001914:   3d8023e1    str q1, [sp, #128]
    40001918:   3d8027e2    str q2, [sp, #144]
    4000191c:   3d802be3    str q3, [sp, #160]
    40001920:   3d802fe4    str q4, [sp, #176]
    40001924:   3d8033e5    str q5, [sp, #192]
    40001928:   3d8037e6    str q6, [sp, #208]
    4000192c:   3d803be7    str q7, [sp, #224]
    40001930:   9104c3e0    add x0, sp, #0x130
    40001934:   f90027e0    str x0, [sp, #72]
    40001938:   9104c3e0    add x0, sp, #0x130
    4000193c:   f9002be0    str x0, [sp, #80]
    40001940:   9103c3e0    add x0, sp, #0xf0
    40001944:   f9002fe0    str x0, [sp, #88]
    40001948:   128006e0    mov w0, #0xffffffc8             // #-56
    4000194c:   b90063e0    str w0, [sp, #96]
    40001950:   12800fe0    mov w0, #0xffffff80             // #-128
    40001954:   b90067e0    str w0, [sp, #100]
    40001958:   910043e0    add x0, sp, #0x10
    4000195c:   910123e1    add x1, sp, #0x48
    40001960:   ad400420    ldp q0, q1, [x1]
    40001964:   ad000400    stp q0, q1, [x0]
    40001968:   910043e0    add x0, sp, #0x10
    4000196c:   aa0003e1    mov x1, x0
    40001970:   f9401fe0    ldr x0, [sp, #56]
    40001974:   94000005    bl  40001988 <my_vprintf>
    40001978:   b9006fe0    str w0, [sp, #108]
    4000197c:   b9406fe0    ldr w0, [sp, #108]
    40001980:   a8d37bfd    ldp x29, x30, [sp], #304
    40001984:   d65f03c0    ret

My guess is that some initialisation code is missing.

Any idea how to fix it?

ilg-ul commented 2 years ago

For completeness, I used the aarch64-none-elf toolchain provided by Arm, version 11.2-2022.02:

ilg-ul commented 2 years ago

The exception class EC == 0b000111 in ESR means _Access to SME, SVE, Advanced SIMD or floating-point functionality trapped by CPACR_EL1.FPEN, CPTR_EL2.FPEN, CPTR_EL2.TFP, or CPTREL3.TFP control..

In other words, the Advanced SIMD and VFP extensions which are not enabled.

A possible workaround is to ask the compiler not to use these instructions via -mgeneral-regs-only.

The solution is to enable them via the FPEN bit 31:20 in the CPACR_EL1 register.

  mrs    x1, cpacr_el1
  mov    x0, #(3 << 20)
  orr    x0, x1, x0
  msr    cpacr_el1, x0
freedomtan commented 2 years ago

The exception class EC == 0b000111 in ESR means _Access to SME, SVE, Advanced SIMD or floating-point functionality trapped by CPACR_EL1.FPEN, CPTR_EL2.FPEN, CPTR_EL2.TFP, or CPTREL3.TFP control..

In other words, the Advanced SIMD and VFP extensions which are not enabled.

A possible workaround is to ask the compiler not to use these instructions via -mgeneral-regs-only.

The solution is to enable them via the FPEN bit 31:20 in the CPACR_EL1 register.

  mrs    x1, cpacr_el1
  mov    x0, #(3 << 20)
  orr    x0, x1, x0
  msr    cpacr_el1, x0

Thanks. Another way I can think of is to handle the exception by implementing an exception handler (changing the vector table, adding handling code, etc).

ilg-ul commented 2 years ago

Another way I can think of is to handle the exception

If you know how to do it, yes, but I guess it is not easy, plus that it adds some run-time overhead, the exception will trigger for each quad instruction, and in printf() there are a lot.

Enabling SMD during startup is much simpler.

Also to be noted that -mgeneral-regs-only is effective only for the application code, the printf() in the library still makes use of quad instructions and crashes.