Page 1 of 1

FPU and Timer on RPi3 / Aarch64

Posted: Mon May 20, 2019 1:35 am
by lpoulain
Hello all,

I am trying to use both the FPU and a timer, but cannot get everything to work despite reading previous responses on these forums.

My environment: emulating a RPi3 using QEMU and compiling with Aarch64.

By default the Pi starts in EL2 (hypervisor mode). In this mode I can use the FPU, but was not able setup exceptions. I am also not sure this is the right execution level if I want to write my own OS.

If I try to use some code given in this forum to switch to EL1 and use a timer ( ... i3/timer01):
  • Interrupts work - kinda. I can catch a divide by zero, but trying to set the timer leads to a constant IRQ #0 generation - and nothing else gets executed
  • The FPU doesn't work.Trying to use floats generates an exception. I tried using solutions provided in this forum to no avail, e.g. the aarch64 compiler doesn't seem to support flags such as -mfpu
Any tip will be appreciated

Re: FPU and Timer on RPi3 / Aarch64

Posted: Mon May 20, 2019 9:33 am
by LdB
Usually the OS is EL1, EL2 is for hypervisor as you noted.

To turn the FPU on disable the EL2 traps and turn it on

Code: Select all

mov	x0, #0x33ff
msr	cptr_el2, x0	// Disable coprocessor traps to EL2
msr	hstr_el2, xzr	// Disable coprocessor traps to EL2
mov	x0, #3 << 20
msr cpacr_el1, x0 // Enable FP/SIMD at EL1 
That is it nothing complex

In AARCH64 compiling the FPU is mandatory ON you can't do soft float at all so there are no switches for it.
AARCH64 basic conventions
>>> No soft-float option anymore (since VFP/SIMD is mandatory). <<<<

To get to EL1 is just as easy .. I assume you want 64bit (you can have 32 or 64)

Code: Select all

//  Initialize HCR_EL2 so EL1 is 64 bits for a Core
	mov	x0, #(1 << 31) // 64bit EL1
	msr	hcr_el2, x0
//  Return to the EL1_SP1 mode from EL2 for a Core
	mov	x0, #0x3c5	 // EL1_SP1 | D | A | I | F all off
	msr	spsr_el2, x0	// Set spsr_el2 with settings
	adr	x0, exit_el1		// Address to exit EL2
	msr	elr_el2, x0	// Set elevated return register
	eret				// Call elevated return
exit_el1:                                 // You will exit here in EL1
The thing to remember is you have a hell of a lot of stack pointers to set before you go crazy and try and do anything.

Re: FPU and Timer on RPi3 / Aarch64

Posted: Tue May 21, 2019 12:37 am
by lpoulain
Thank you for your response.

I tried adding both code sniplets in my start.S, but it's still starting in EL2. Am I missing something?

As far as stacks, I set sp to _start]. I understand I will need to setup other stacks once I implement multiple processes (I wrote my hobby OS for x86 in the past so a familiar with the concept) but I'm not there yet. Unless there are other stack pointers I should be aware of?

Re: FPU and Timer on RPi3 / Aarch64

Posted: Tue May 21, 2019 1:56 am
by LdB
I would suggest it is something with QEMU because all the code works on real hardware from a real example ... /myBlinker

The code if you want to find it is in the boot code here ... tStart64.S

The code is correct you need to sort out what the problem is with QEMU. Does QEMU park the other 3 cores
like the real hardware or do you have to put a park stub at the top of the code?

FYI there is a stack for each EL and for each core ... have you set the stack on the EL and core you are using?

Re: FPU and Timer on RPi3 / Aarch64

Posted: Tue May 21, 2019 2:23 am
by lpoulain
If I copy the .S file (and associated .ld file) as is, then it works. OK, the timer doesn't work yet, but I run in EL1, get interrupt handling and can use the FPU. Thanks a lot.

Now, my next step is to try to understand the code ;-)