Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quad instructions throw exceptions #1

Open
ilg-ul opened this issue May 25, 2022 · 4 comments
Open

Quad instructions throw exceptions #1

ilg-ul opened this issue May 25, 2022 · 4 comments

Comments

@ilg-ul
Copy link

ilg-ul commented May 25, 2022

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
Copy link
Author

ilg-ul commented May 25, 2022

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

@ilg-ul
Copy link
Author

ilg-ul commented May 25, 2022

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 CPTR_EL3.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
Copy link
Owner

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 CPTR_EL3.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
Copy link
Author

ilg-ul commented May 26, 2022

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants