Difference between revisions of "Unit BootRPi4"
Line 10: | Line 10: | ||
R0 - Zero | R0 - Zero | ||
− | R1 - Machine Type (Raspberry Pi 4 or BCM2711 = 0x0C42) | + | |
+ | R1 - Machine Type (Raspberry Pi 4 or BCM2711 = 0x0C42) | ||
+ | |||
R2 - Address of the ARM Tags structure (Normally 0x0100) | R2 - Address of the ARM Tags structure (Normally 0x0100) | ||
Line 16: | Line 18: | ||
World - Non Secure (Firmware causes a switch to Non Secure before jumping to Startup code) | World - Non Secure (Firmware causes a switch to Non Secure before jumping to Startup code) | ||
+ | |||
+ | |||
Mode - Hypervisor (ARM_MODE_HYP) | Mode - Hypervisor (ARM_MODE_HYP) | ||
+ | |||
MMU - Disabled | MMU - Disabled | ||
+ | |||
FPU - Disabled | FPU - Disabled | ||
+ | |||
Data Cache - Disabled | Data Cache - Disabled | ||
+ | |||
Instruction Cache - Enabled (Firmware enabled during boot) | Instruction Cache - Enabled (Firmware enabled during boot) | ||
+ | |||
Branch Predication - Disabled | Branch Predication - Disabled | ||
+ | |||
Unaligned Data Access - Enabled (Always enabled on ARMv8) | Unaligned Data Access - Enabled (Always enabled on ARMv8) | ||
+ | |||
SMP Coherence - Enabled (Firmware enabled during boot) | SMP Coherence - Enabled (Firmware enabled during boot) | ||
Line 28: | Line 39: | ||
Distributor interface enabled for Group 0 and Group 1 interrupts | Distributor interface enabled for Group 0 and Group 1 interrupts | ||
+ | |||
CPU interface enabled for Group 1 interrupts | CPU interface enabled for Group 1 interrupts | ||
+ | |||
All interrupts routed to Group 1 | All interrupts routed to Group 1 | ||
Line 50: | Line 63: | ||
X0 - Address of the ARM Tags or Device Tree structure | X0 - Address of the ARM Tags or Device Tree structure | ||
+ | |||
X1 - Zero | X1 - Zero | ||
+ | |||
X2 - Zero | X2 - Zero | ||
+ | |||
X3 - Zero | X3 - Zero | ||
Line 57: | Line 73: | ||
World - Non Secure (Firmware causes a switch to Non Secure before jumping to Startup code) | World - Non Secure (Firmware causes a switch to Non Secure before jumping to Startup code) | ||
+ | |||
Mode - EL2 (Hypervisor) | Mode - EL2 (Hypervisor) | ||
+ | |||
MMU - Disabled | MMU - Disabled | ||
+ | |||
FPU - Disabled | FPU - Disabled | ||
+ | |||
Data Cache - Disabled | Data Cache - Disabled | ||
+ | |||
Instruction Cache - Enabled (Firmware enabled during boot) | Instruction Cache - Enabled (Firmware enabled during boot) | ||
+ | |||
Branch Predication - Disabled | Branch Predication - Disabled | ||
+ | |||
Unaligned Data Access - Enabled (Always enabled on ARMv8) | Unaligned Data Access - Enabled (Always enabled on ARMv8) | ||
+ | |||
SMP Coherence - Enabled (Firmware enabled during boot) | SMP Coherence - Enabled (Firmware enabled during boot) | ||
Line 79: | Line 103: | ||
a) Reset CNTVOFF (Virtual Offset register) to zero | a) Reset CNTVOFF (Virtual Offset register) to zero | ||
+ | |||
b) Switch to Hypervisor mode (Firmware later than 2/10/2015) | b) Switch to Hypervisor mode (Firmware later than 2/10/2015) | ||
Line 86: | Line 111: | ||
-Install a new Secure Monitor Call vector at the appropriate point in the vector table | -Install a new Secure Monitor Call vector at the appropriate point in the vector table | ||
+ | |||
-Clean the data cache by Modified Virtual Address at address 0x00000000 | -Clean the data cache by Modified Virtual Address at address 0x00000000 | ||
+ | |||
-Perform a data synchronisation barrier | -Perform a data synchronisation barrier | ||
+ | |||
-Invalidate the entire instruction cache | -Invalidate the entire instruction cache | ||
+ | |||
-Perform a data synchronisation barrier | -Perform a data synchronisation barrier | ||
+ | |||
-Perform an instruction synchronisation barrier | -Perform an instruction synchronisation barrier | ||
+ | |||
-Perform a Secure Monitor Call (SMC) | -Perform a Secure Monitor Call (SMC) | ||
+ | |||
-From within the newly installed Secure Monitor Call read the Secure Configuration Register (SCR) mask off the Non Secure (NS) bit, rewrite the SCR and then return to Supervisor mode | -From within the newly installed Secure Monitor Call read the Secure Configuration Register (SCR) mask off the Non Secure (NS) bit, rewrite the SCR and then return to Supervisor mode | ||
Revision as of 03:06, 19 June 2021
Return to Unit Reference
Description
Ultibo Initialization code for Raspberry Pi 4
The boot loader on the Raspberry Pi 4 will load this code at address 0x00008000 onwards and set the following registers before jumping to this code.
R0 - Zero
R1 - Machine Type (Raspberry Pi 4 or BCM2711 = 0x0C42)
R2 - Address of the ARM Tags structure (Normally 0x0100)
On entry to this code the processor will be in the following state:
World - Non Secure (Firmware causes a switch to Non Secure before jumping to Startup code)
Mode - Hypervisor (ARM_MODE_HYP)
MMU - Disabled
FPU - Disabled
Data Cache - Disabled
Instruction Cache - Enabled (Firmware enabled during boot)
Branch Predication - Disabled
Unaligned Data Access - Enabled (Always enabled on ARMv8)
SMP Coherence - Enabled (Firmware enabled during boot)
The firmware also does initial configuration of the GIC as follows:
Distributor interface enabled for Group 0 and Group 1 interrupts
CPU interface enabled for Group 1 interrupts
All interrupts routed to Group 1
All secondary CPUs will be executing a loop reading their designated local peripherals mailbox0 and waiting for a start address to begin execution.
Ultibo switches from Hypervisor mode to Supervisor mode during initial boot.
If the configuration option ARMSecureBoot is set to 1 then Ultibo switches the processor back to Secure world during initial boot (see note below).
Ultibo then switches the processor to System mode for all operations and remains in either the Secure or Non Secure World as per the option above.
The initialization process enables the MMU, FPU, L1 Cache and other performance optimizations.
Note that this code is currently almost identical to the Raspberry Pi 2 and 3 boot code but has been separated to allow for supporting 64 bit mode on the ARMv8 in future. Ultibo currently runs the RPi4 in 32 bit mode which is almost identical to ARMv7.
ARM64 support on Raspberry Pi 4
A 64 bit loader is included in the firmware and if the file kernel8.img exists in the boot partition the firmware will attempt to boot this image in 64 bit mode.
The boot loader on the Raspberry Pi 4 will load this code at address 0x00080000 onwards and set the following registers before jumping to this code.
X0 - Address of the ARM Tags or Device Tree structure
X1 - Zero
X2 - Zero
X3 - Zero
On entry to this code in 64 bit mode the processor will be in the following state:
World - Non Secure (Firmware causes a switch to Non Secure before jumping to Startup code)
Mode - EL2 (Hypervisor)
MMU - Disabled
FPU - Disabled
Data Cache - Disabled
Instruction Cache - Enabled (Firmware enabled during boot)
Branch Predication - Disabled
Unaligned Data Access - Enabled (Always enabled on ARMv8)
SMP Coherence - Enabled (Firmware enabled during boot)
The boot loader also does initial configuration of the GIC as follows:
Distributor interface enabled for Group 0 and Group 1 interrupts CPU interface enabled for Group 1 interrupts All interrupts routed to Group 1
All secondary CPUs will be executing a loop reading a memory address at 0xd8/e0/e8/f0 and waiting for a start address to begin execution.
Returning to Secure World:
The Raspberry Pi 4 firmware always switches to Non Secure world in order to:
a) Reset CNTVOFF (Virtual Offset register) to zero
b) Switch to Hypervisor mode (Firmware later than 2/10/2015)
It is not normally possible (by design) to return from the Non Secure world to the Secure world except by invoking the Secure Monitor which then handles any requests in the Secure world.
However due to the fact that this switch is performed by the boot loader code (loaded between 0x00000000 and 0x000000FF by the firmware) and that the code appears to set the secure, non secure and monitor vector base addresses to 0x00000000 and because all memory is writable from non secure at boot (the MMU is disabled) then the option exists to return to the Secure world as follows:
-Install a new Secure Monitor Call vector at the appropriate point in the vector table
-Clean the data cache by Modified Virtual Address at address 0x00000000
-Perform a data synchronisation barrier
-Invalidate the entire instruction cache
-Perform a data synchronisation barrier
-Perform an instruction synchronisation barrier
-Perform a Secure Monitor Call (SMC)
-From within the newly installed Secure Monitor Call read the Secure Configuration Register (SCR) mask off the Non Secure (NS) bit, rewrite the SCR and then return to Supervisor mode
Secondary cores also switch back to the Secure world using the same technique however they do not need to install the new SMC vector and instead use the one installed by the primary core.
Firmware changes from October 2020 disable the ability to perform the SMC instruction from non secure mode which means this technique will no longer work with the default firmware. To allow continued support for returning to the Secure world a custom ARM boot stub is now included with Ultibo that allows the SMC instruction to be performed.
This custom stub contains a marker that allows the boot process to detect it and disable the attempt to switch back to the Secure world if the default boot stub is used instead.
As the default boot stub continues to evolve in response to demands from the Linux community this technique will allow Ultibo to continue to provide the features we want without having to make frequent changes to combat items that are beyond our control.
Thanks to the Circle project for introducing the custom boot stub technique to work around these changes.
Constants
None defined
Type definitions
None defined
Public variables
None defined
Function declarations
To be documented
Return to Unit Reference