mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-08 05:43:53 +00:00
chore: fvp_r: Initial No-EL3 and MPU Implementation
For v8-R64, especially R82, creating code to run BL1 at EL2, using MPU. Signed-off-by: Gary Morrison <gary.morrison@arm.com> Change-Id: I439ac3915b982ad1e61d24365bdd1584b3070425
This commit is contained in:
parent
03b201c0fb
commit
5fb061e761
36 changed files with 2356 additions and 78 deletions
10
bl1/bl1.mk
10
bl1/bl1.mk
|
@ -1,15 +1,17 @@
|
|||
#
|
||||
# Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
|
||||
# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
BL1_SOURCES += bl1/bl1_main.c \
|
||||
bl1/${ARCH}/bl1_arch_setup.c \
|
||||
ifneq (${PLAT},fvp_r)
|
||||
BL1_SOURCES += bl1/${ARCH}/bl1_arch_setup.c \
|
||||
bl1/${ARCH}/bl1_context_mgmt.c \
|
||||
bl1/${ARCH}/bl1_entrypoint.S \
|
||||
bl1/${ARCH}/bl1_exceptions.S \
|
||||
lib/cpus/${ARCH}/cpu_helpers.S \
|
||||
bl1/bl1_main.c
|
||||
endif
|
||||
BL1_SOURCES += lib/cpus/${ARCH}/cpu_helpers.S \
|
||||
lib/cpus/errata_report.c \
|
||||
lib/el3_runtime/${ARCH}/context_mgmt.c \
|
||||
plat/common/plat_bl1_common.c \
|
||||
|
|
|
@ -10,7 +10,7 @@ required Translation Lookaside Buffer (TLB) maintenance operations.
|
|||
More specifically, some use cases that this library aims to support are:
|
||||
|
||||
#. Statically allocate translation tables and populate them (at run-time) based
|
||||
on a description of the memory layout. The memory layout is typically
|
||||
upon a description of the memory layout. The memory layout is typically
|
||||
provided by the platform port as a list of memory regions;
|
||||
|
||||
#. Support for generating translation tables pertaining to a different
|
||||
|
@ -26,22 +26,28 @@ More specifically, some use cases that this library aims to support are:
|
|||
#. Support for changing memory attributes of memory regions at run-time.
|
||||
|
||||
|
||||
About version 1 and version 2
|
||||
-----------------------------
|
||||
About version 1, version 2 and MPU libraries
|
||||
--------------------------------------------
|
||||
|
||||
This document focuses on version 2 of the library, whose sources are available
|
||||
in the ``lib/xlat_tables_v2`` directory. Version 1 of the library can still be
|
||||
found in ``lib/xlat_tables`` directory but it is less flexible and doesn't
|
||||
support dynamic mapping. Although potential bug fixes will be applied to both
|
||||
versions, future features enhancements will focus on version 2 and might not be
|
||||
back-ported to version 1. Therefore, it is recommended to use version 2,
|
||||
especially for new platform ports.
|
||||
support dynamic mapping. ``lib/xlat_mpu``, which configures Arm's MPU
|
||||
equivalently, is also addressed here. The ``lib/xlat_mpu`` is experimental,
|
||||
meaning that its API may change. It currently strives for consistency and
|
||||
code-reuse with xlat_tables_v2. Future versions may be more MPU-specific (e.g.,
|
||||
removing all mentions of virtual addresses). Although potential bug fixes will
|
||||
be applied to all versions of the xlat_* libs, future feature enhancements will
|
||||
focus on version 2 and might not be back-ported to version 1 and MPU versions.
|
||||
Therefore, it is recommended to use version 2, especially for new platform
|
||||
ports (unless the platform uses an MPU).
|
||||
|
||||
However, please note that version 2 is still in active development and is not
|
||||
considered stable yet. Hence, compatibility breaks might be introduced.
|
||||
However, please note that version 2 and the MPU version are still in active
|
||||
development and is not considered stable yet. Hence, compatibility breaks might
|
||||
be introduced.
|
||||
|
||||
From this point onwards, this document will implicitly refer to version 2 of the
|
||||
library.
|
||||
library, unless stated otherwise.
|
||||
|
||||
|
||||
Design concepts and interfaces
|
||||
|
@ -102,6 +108,16 @@ The region's granularity is an optional field; if it is not specified the
|
|||
library will choose the mapping granularity for this region as it sees fit (more
|
||||
details can be found in `The memory mapping algorithm`_ section below).
|
||||
|
||||
The MPU library also uses ``struct mmap_region`` to specify translations, but
|
||||
the MPU's translations are limited to specification of valid addresses and
|
||||
access permissions. If the requested virtual and physical addresses mismatch
|
||||
the system will panic. Being register-based for deterministic memory-reference
|
||||
timing, the MPU hardware does not involve memory-resident translation tables.
|
||||
|
||||
Currently, the MPU library is also limited to MPU translation at EL2 with no
|
||||
MMU translation at other ELs. These limitations, however, are expected to be
|
||||
overcome in future library versions.
|
||||
|
||||
Translation Context
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -215,7 +231,8 @@ future.
|
|||
The ``MAP_REGION()`` and ``MAP_REGION_FLAT()`` macros do not allow specifying a
|
||||
mapping granularity, which leaves the library implementation free to choose
|
||||
it. However, in cases where a specific granularity is required, the
|
||||
``MAP_REGION2()`` macro might be used instead.
|
||||
``MAP_REGION2()`` macro might be used instead. Using ``MAP_REGION_FLAT()`` only
|
||||
to define regions for the MPU library is strongly recommended.
|
||||
|
||||
As explained earlier in this document, when the dynamic mapping feature is
|
||||
disabled, there is no notion of dynamic regions. Conceptually, there are only
|
||||
|
@ -374,6 +391,9 @@ entries in the translation tables are checked to ensure consistency. Please
|
|||
refer to the comments in the source code of the core module for more details
|
||||
about the sorting algorithm in use.
|
||||
|
||||
This mapping algorithm does not apply to the MPU library, since the MPU hardware
|
||||
directly maps regions by "base" and "limit" (bottom and top) addresses.
|
||||
|
||||
TLB maintenance operations
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -390,6 +410,11 @@ address translation at reset [#tlb-reset-ref]_. Therefore, the TLBs invalidation
|
|||
is deferred to the ``enable_mmu*()`` family of functions, just before the MMU is
|
||||
turned on.
|
||||
|
||||
Regarding enabling and disabling memory management, for the MPU library, to
|
||||
reduce confusion, calls to enable or disable the MPU use ``mpu`` in their names
|
||||
in place of ``mmu``. For example, the ``enable_mmu_el2()`` call is changed to
|
||||
``enable_mpu_el2()``.
|
||||
|
||||
TLB invalidation is not required when adding dynamic regions either. Dynamic
|
||||
regions are not allowed to overlap existing memory region. Therefore, if the
|
||||
dynamic mapping request is deemed legitimate, it automatically concerns memory
|
||||
|
@ -412,6 +437,6 @@ mapping cannot be cached in the TLBs.
|
|||
|
||||
--------------
|
||||
|
||||
*Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.*
|
||||
*Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.*
|
||||
|
||||
.. |Alignment Example| image:: ../resources/diagrams/xlat_align.png
|
||||
|
|
|
@ -522,13 +522,18 @@
|
|||
#define VTTBR_BADDR_SHIFT U(0)
|
||||
|
||||
/* HCR definitions */
|
||||
#define HCR_RESET_VAL ULL(0x0)
|
||||
#define HCR_AMVOFFEN_BIT (ULL(1) << 51)
|
||||
#define HCR_TEA_BIT (ULL(1) << 47)
|
||||
#define HCR_API_BIT (ULL(1) << 41)
|
||||
#define HCR_APK_BIT (ULL(1) << 40)
|
||||
#define HCR_E2H_BIT (ULL(1) << 34)
|
||||
#define HCR_HCD_BIT (ULL(1) << 29)
|
||||
#define HCR_TGE_BIT (ULL(1) << 27)
|
||||
#define HCR_RW_SHIFT U(31)
|
||||
#define HCR_RW_BIT (ULL(1) << HCR_RW_SHIFT)
|
||||
#define HCR_TWE_BIT (ULL(1) << 14)
|
||||
#define HCR_TWI_BIT (ULL(1) << 13)
|
||||
#define HCR_AMO_BIT (ULL(1) << 5)
|
||||
#define HCR_IMO_BIT (ULL(1) << 4)
|
||||
#define HCR_FMO_BIT (ULL(1) << 3)
|
||||
|
|
448
include/arch/aarch64/el2_common_macros.S
Normal file
448
include/arch/aarch64/el2_common_macros.S
Normal file
|
@ -0,0 +1,448 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef EL2_COMMON_MACROS_S
|
||||
#define EL2_COMMON_MACROS_S
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <context.h>
|
||||
#include <lib/xlat_tables/xlat_tables_defs.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
/*
|
||||
* Helper macro to initialise system registers at EL2.
|
||||
*/
|
||||
.macro el2_arch_init_common
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* SCTLR_EL2 has already been initialised - read current value before
|
||||
* modifying.
|
||||
*
|
||||
* SCTLR_EL2.I: Enable the instruction cache.
|
||||
*
|
||||
* SCTLR_EL2.SA: Enable Stack Alignment check. A SP alignment fault
|
||||
* exception is generated if a load or store instruction executed at
|
||||
* EL2 uses the SP as the base address and the SP is not aligned to a
|
||||
* 16-byte boundary.
|
||||
*
|
||||
* SCTLR_EL2.A: Enable Alignment fault checking. All instructions that
|
||||
* load or store one or more registers have an alignment check that the
|
||||
* address being accessed is aligned to the size of the data element(s)
|
||||
* being accessed.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT)
|
||||
mrs x0, sctlr_el2
|
||||
orr x0, x0, x1
|
||||
msr sctlr_el2, x0
|
||||
isb
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Initialise HCR_EL2, setting all fields rather than relying on HW.
|
||||
* All fields are architecturally UNKNOWN on reset. The following fields
|
||||
* do not change during the TF lifetime. The remaining fields are set to
|
||||
* zero here but are updated ahead of transitioning to a lower EL in the
|
||||
* function cm_init_context_common().
|
||||
*
|
||||
* HCR_EL2.TWE: Set to zero so that execution of WFE instructions at
|
||||
* EL2, EL1 and EL0 are not trapped to EL2.
|
||||
*
|
||||
* HCR_EL2.TWI: Set to zero so that execution of WFI instructions at
|
||||
* EL2, EL1 and EL0 are not trapped to EL2.
|
||||
*
|
||||
* HCR_EL2.HCD: Set to zero to enable HVC calls at EL1 and above,
|
||||
* from both Security states and both Execution states.
|
||||
*
|
||||
* HCR_EL2.TEA: Set to one to route External Aborts and SError
|
||||
* Interrupts to EL2 when executing at any EL.
|
||||
*
|
||||
* HCR_EL2.{API,APK}: For Armv8.3 pointer authentication feature,
|
||||
* disable traps to EL2 when accessing key registers or using
|
||||
* pointer authentication instructions from lower ELs.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
mov_imm x0, ((HCR_RESET_VAL | HCR_TEA_BIT) \
|
||||
& ~(HCR_TWE_BIT | HCR_TWI_BIT | HCR_HCD_BIT))
|
||||
#if CTX_INCLUDE_PAUTH_REGS
|
||||
/*
|
||||
* If the pointer authentication registers are saved during world
|
||||
* switches, enable pointer authentication everywhere, as it is safe to
|
||||
* do so.
|
||||
*/
|
||||
orr x0, x0, #(HCR_API_BIT | HCR_APK_BIT)
|
||||
#endif /* CTX_INCLUDE_PAUTH_REGS */
|
||||
msr hcr_el2, x0
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Initialise MDCR_EL2, setting all fields rather than relying on
|
||||
* hw. Some fields are architecturally UNKNOWN on reset.
|
||||
*
|
||||
* MDCR_EL2.SDD: Set to one to disable AArch64 Secure self-hosted
|
||||
* debug. Debug exceptions, other than Breakpoint Instruction
|
||||
* exceptions, are disabled from all ELs in Secure state.
|
||||
*
|
||||
* MDCR_EL2.TDOSA: Set to zero so that EL2 and EL2 System register
|
||||
* access to the powerdown debug registers do not trap to EL2.
|
||||
*
|
||||
* MDCR_EL2.TDA: Set to zero to allow EL0, EL1 and EL2 access to the
|
||||
* debug registers, other than those registers that are controlled by
|
||||
* MDCR_EL2.TDOSA.
|
||||
*
|
||||
* MDCR_EL2.TPM: Set to zero so that EL0, EL1, and EL2 System
|
||||
* register accesses to all Performance Monitors registers do not trap
|
||||
* to EL2.
|
||||
*
|
||||
* MDCR_EL2.SCCD: Set to one so that cycle counting by PMCCNTR_EL0
|
||||
* is prohibited in Secure state. This bit is RES0 in versions of the
|
||||
* architecture with FEAT_PMUv3p5 not implemented, setting it to 1
|
||||
* doesn't have any effect on them.
|
||||
*
|
||||
* MDCR_EL2.MCCD: Set to one so that cycle counting by PMCCNTR_EL0
|
||||
* is prohibited in EL2. This bit is RES0 in versions of the
|
||||
* architecture with FEAT_PMUv3p7 not implemented, setting it to 1
|
||||
* doesn't have any effect on them.
|
||||
*
|
||||
* MDCR_EL2.SPME: Set to zero so that event counting by the program-
|
||||
* mable counters PMEVCNTR<n>_EL0 is prohibited in Secure state. If
|
||||
* ARMv8.2 Debug is not implemented this bit does not have any effect
|
||||
* on the counters unless there is support for the implementation
|
||||
* defined authentication interface
|
||||
* ExternalSecureNoninvasiveDebugEnabled().
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
mov_imm x0, ((MDCR_EL2_RESET_VAL | MDCR_SDD_BIT | \
|
||||
MDCR_SPD32(MDCR_SPD32_DISABLE) | MDCR_SCCD_BIT | \
|
||||
MDCR_MCCD_BIT) & ~(MDCR_SPME_BIT | MDCR_TDOSA_BIT | \
|
||||
MDCR_TDA_BIT | MDCR_TPM_BIT))
|
||||
|
||||
msr mdcr_el2, x0
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Initialise PMCR_EL0 setting all fields rather than relying
|
||||
* on hw. Some fields are architecturally UNKNOWN on reset.
|
||||
*
|
||||
* PMCR_EL0.LP: Set to one so that event counter overflow, that
|
||||
* is recorded in PMOVSCLR_EL0[0-30], occurs on the increment
|
||||
* that changes PMEVCNTR<n>_EL0[63] from 1 to 0, when ARMv8.5-PMU
|
||||
* is implemented. This bit is RES0 in versions of the architecture
|
||||
* earlier than ARMv8.5, setting it to 1 doesn't have any effect
|
||||
* on them.
|
||||
*
|
||||
* PMCR_EL0.LC: Set to one so that cycle counter overflow, that
|
||||
* is recorded in PMOVSCLR_EL0[31], occurs on the increment
|
||||
* that changes PMCCNTR_EL0[63] from 1 to 0.
|
||||
*
|
||||
* PMCR_EL0.DP: Set to one so that the cycle counter,
|
||||
* PMCCNTR_EL0 does not count when event counting is prohibited.
|
||||
*
|
||||
* PMCR_EL0.X: Set to zero to disable export of events.
|
||||
*
|
||||
* PMCR_EL0.D: Set to zero so that, when enabled, PMCCNTR_EL0
|
||||
* counts on every clock cycle.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
mov_imm x0, ((PMCR_EL0_RESET_VAL | PMCR_EL0_LP_BIT | \
|
||||
PMCR_EL0_LC_BIT | PMCR_EL0_DP_BIT) & \
|
||||
~(PMCR_EL0_X_BIT | PMCR_EL0_D_BIT))
|
||||
|
||||
msr pmcr_el0, x0
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Enable External Aborts and SError Interrupts now that the exception
|
||||
* vectors have been setup.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
msr daifclr, #DAIF_ABT_BIT
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Initialise CPTR_EL2, setting all fields rather than relying on hw.
|
||||
* All fields are architecturally UNKNOWN on reset.
|
||||
*
|
||||
* CPTR_EL2.TCPAC: Set to zero so that any accesses to CPACR_EL1 do
|
||||
* not trap to EL2.
|
||||
*
|
||||
* CPTR_EL2.TTA: Set to zero so that System register accesses to the
|
||||
* trace registers do not trap to EL2.
|
||||
*
|
||||
* CPTR_EL2.TFP: Set to zero so that accesses to the V- or Z- registers
|
||||
* by Advanced SIMD, floating-point or SVE instructions (if implemented)
|
||||
* do not trap to EL2.
|
||||
*/
|
||||
|
||||
mov_imm x0, (CPTR_EL2_RESET_VAL & ~(TCPAC_BIT | TTA_BIT | TFP_BIT))
|
||||
msr cptr_el2, x0
|
||||
|
||||
/*
|
||||
* If Data Independent Timing (DIT) functionality is implemented,
|
||||
* always enable DIT in EL2
|
||||
*/
|
||||
mrs x0, id_aa64pfr0_el1
|
||||
ubfx x0, x0, #ID_AA64PFR0_DIT_SHIFT, #ID_AA64PFR0_DIT_LENGTH
|
||||
cmp x0, #ID_AA64PFR0_DIT_SUPPORTED
|
||||
bne 1f
|
||||
mov x0, #DIT_BIT
|
||||
msr DIT, x0
|
||||
1:
|
||||
.endm
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* This is the super set of actions that need to be performed during a cold boot
|
||||
* or a warm boot in EL2. This code is shared by BL1 and BL31.
|
||||
*
|
||||
* This macro will always perform reset handling, architectural initialisations
|
||||
* and stack setup. The rest of the actions are optional because they might not
|
||||
* be needed, depending on the context in which this macro is called. This is
|
||||
* why this macro is parameterised ; each parameter allows to enable/disable
|
||||
* some actions.
|
||||
*
|
||||
* _init_sctlr:
|
||||
* Whether the macro needs to initialise SCTLR_EL2, including configuring
|
||||
* the endianness of data accesses.
|
||||
*
|
||||
* _warm_boot_mailbox:
|
||||
* Whether the macro needs to detect the type of boot (cold/warm). The
|
||||
* detection is based on the platform entrypoint address : if it is zero
|
||||
* then it is a cold boot, otherwise it is a warm boot. In the latter case,
|
||||
* this macro jumps on the platform entrypoint address.
|
||||
*
|
||||
* _secondary_cold_boot:
|
||||
* Whether the macro needs to identify the CPU that is calling it: primary
|
||||
* CPU or secondary CPU. The primary CPU will be allowed to carry on with
|
||||
* the platform initialisations, while the secondaries will be put in a
|
||||
* platform-specific state in the meantime.
|
||||
*
|
||||
* If the caller knows this macro will only be called by the primary CPU
|
||||
* then this parameter can be defined to 0 to skip this step.
|
||||
*
|
||||
* _init_memory:
|
||||
* Whether the macro needs to initialise the memory.
|
||||
*
|
||||
* _init_c_runtime:
|
||||
* Whether the macro needs to initialise the C runtime environment.
|
||||
*
|
||||
* _exception_vectors:
|
||||
* Address of the exception vectors to program in the VBAR_EL2 register.
|
||||
*
|
||||
* _pie_fixup_size:
|
||||
* Size of memory region to fixup Global Descriptor Table (GDT).
|
||||
*
|
||||
* A non-zero value is expected when firmware needs GDT to be fixed-up.
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
.macro el2_entrypoint_common \
|
||||
_init_sctlr, _warm_boot_mailbox, _secondary_cold_boot, \
|
||||
_init_memory, _init_c_runtime, _exception_vectors, \
|
||||
_pie_fixup_size
|
||||
|
||||
.if \_init_sctlr
|
||||
/* -------------------------------------------------------------
|
||||
* This is the initialisation of SCTLR_EL2 and so must ensure
|
||||
* that all fields are explicitly set rather than relying on hw.
|
||||
* Some fields reset to an IMPLEMENTATION DEFINED value and
|
||||
* others are architecturally UNKNOWN on reset.
|
||||
*
|
||||
* SCTLR.EE: Set the CPU endianness before doing anything that
|
||||
* might involve memory reads or writes. Set to zero to select
|
||||
* Little Endian.
|
||||
*
|
||||
* SCTLR_EL2.WXN: For the EL2 translation regime, this field can
|
||||
* force all memory regions that are writeable to be treated as
|
||||
* XN (Execute-never). Set to zero so that this control has no
|
||||
* effect on memory access permissions.
|
||||
*
|
||||
* SCTLR_EL2.SA: Set to zero to disable Stack Alignment check.
|
||||
*
|
||||
* SCTLR_EL2.A: Set to zero to disable Alignment fault checking.
|
||||
*
|
||||
* SCTLR.DSSBS: Set to zero to disable speculation store bypass
|
||||
* safe behaviour upon exception entry to EL2.
|
||||
* -------------------------------------------------------------
|
||||
*/
|
||||
mov_imm x0, (SCTLR_RESET_VAL & ~(SCTLR_EE_BIT | SCTLR_WXN_BIT \
|
||||
| SCTLR_SA_BIT | SCTLR_A_BIT | SCTLR_DSSBS_BIT))
|
||||
msr sctlr_el2, x0
|
||||
isb
|
||||
.endif /* _init_sctlr */
|
||||
|
||||
#if DISABLE_MTPMU
|
||||
bl mtpmu_disable
|
||||
#endif
|
||||
|
||||
.if \_warm_boot_mailbox
|
||||
/* -------------------------------------------------------------
|
||||
* This code will be executed for both warm and cold resets.
|
||||
* Now is the time to distinguish between the two.
|
||||
* Query the platform entrypoint address and if it is not zero
|
||||
* then it means it is a warm boot so jump to this address.
|
||||
* -------------------------------------------------------------
|
||||
*/
|
||||
bl plat_get_my_entrypoint
|
||||
cbz x0, do_cold_boot
|
||||
br x0
|
||||
|
||||
do_cold_boot:
|
||||
.endif /* _warm_boot_mailbox */
|
||||
|
||||
.if \_pie_fixup_size
|
||||
#if ENABLE_PIE
|
||||
/*
|
||||
* ------------------------------------------------------------
|
||||
* If PIE is enabled fixup the Global descriptor Table only
|
||||
* once during primary core cold boot path.
|
||||
*
|
||||
* Compile time base address, required for fixup, is calculated
|
||||
* using "pie_fixup" label present within first page.
|
||||
* ------------------------------------------------------------
|
||||
*/
|
||||
pie_fixup:
|
||||
ldr x0, =pie_fixup
|
||||
and x0, x0, #~(PAGE_SIZE_MASK)
|
||||
mov_imm x1, \_pie_fixup_size
|
||||
add x1, x1, x0
|
||||
bl fixup_gdt_reloc
|
||||
#endif /* ENABLE_PIE */
|
||||
.endif /* _pie_fixup_size */
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Set the exception vectors.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
adr x0, \_exception_vectors
|
||||
msr vbar_el2, x0
|
||||
isb
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* It is a cold boot.
|
||||
* Perform any processor specific actions upon reset e.g. cache, TLB
|
||||
* invalidations etc.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
bl reset_handler
|
||||
|
||||
el2_arch_init_common
|
||||
|
||||
.if \_secondary_cold_boot
|
||||
/* -------------------------------------------------------------
|
||||
* Check if this is a primary or secondary CPU cold boot.
|
||||
* The primary CPU will set up the platform while the
|
||||
* secondaries are placed in a platform-specific state until the
|
||||
* primary CPU performs the necessary actions to bring them out
|
||||
* of that state and allows entry into the OS.
|
||||
* -------------------------------------------------------------
|
||||
*/
|
||||
bl plat_is_my_cpu_primary
|
||||
cbnz w0, do_primary_cold_boot
|
||||
|
||||
/* This is a cold boot on a secondary CPU */
|
||||
bl plat_secondary_cold_boot_setup
|
||||
/* plat_secondary_cold_boot_setup() is not supposed to return */
|
||||
bl el2_panic
|
||||
do_primary_cold_boot:
|
||||
.endif /* _secondary_cold_boot */
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Initialize memory now. Secondary CPU initialization won't get to this
|
||||
* point.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.if \_init_memory
|
||||
bl platform_mem_init
|
||||
.endif /* _init_memory */
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Init C runtime environment:
|
||||
* - Zero-initialise the NOBITS sections. There are 2 of them:
|
||||
* - the .bss section;
|
||||
* - the coherent memory section (if any).
|
||||
* - Relocate the data section from ROM to RAM, if required.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
.if \_init_c_runtime
|
||||
adrp x0, __BSS_START__
|
||||
add x0, x0, :lo12:__BSS_START__
|
||||
|
||||
adrp x1, __BSS_END__
|
||||
add x1, x1, :lo12:__BSS_END__
|
||||
sub x1, x1, x0
|
||||
bl zeromem
|
||||
|
||||
#if defined(IMAGE_BL1) || (defined(IMAGE_BL2) && BL2_AT_EL3 && BL2_IN_XIP_MEM)
|
||||
adrp x0, __DATA_RAM_START__
|
||||
add x0, x0, :lo12:__DATA_RAM_START__
|
||||
adrp x1, __DATA_ROM_START__
|
||||
add x1, x1, :lo12:__DATA_ROM_START__
|
||||
adrp x2, __DATA_RAM_END__
|
||||
add x2, x2, :lo12:__DATA_RAM_END__
|
||||
sub x2, x2, x0
|
||||
bl memcpy16
|
||||
#endif
|
||||
.endif /* _init_c_runtime */
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Use SP_EL0 for the C runtime stack.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
msr spsel, #0
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Allocate a stack whose memory will be marked as Normal-IS-WBWA when
|
||||
* the MMU is enabled. There is no risk of reading stale stack memory
|
||||
* after enabling the MMU as only the primary CPU is running at the
|
||||
* moment.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
bl plat_set_my_stack
|
||||
|
||||
#if STACK_PROTECTOR_ENABLED
|
||||
.if \_init_c_runtime
|
||||
bl update_stack_protector_canary
|
||||
.endif /* _init_c_runtime */
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro apply_at_speculative_wa
|
||||
#if ERRATA_SPECULATIVE_AT
|
||||
/*
|
||||
* Explicitly save x30 so as to free up a register and to enable
|
||||
* branching and also, save x29 which will be used in the called
|
||||
* function
|
||||
*/
|
||||
stp x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29]
|
||||
bl save_and_update_ptw_el1_sys_regs
|
||||
ldp x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29]
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro restore_ptw_el1_sys_regs
|
||||
#if ERRATA_SPECULATIVE_AT
|
||||
/* -----------------------------------------------------------
|
||||
* In case of ERRATA_SPECULATIVE_AT, must follow below order
|
||||
* to ensure that page table walk is not enabled until
|
||||
* restoration of all EL1 system registers. TCR_EL1 register
|
||||
* should be updated at the end which restores previous page
|
||||
* table walk setting of stage1 i.e.(TCR_EL1.EPDx) bits. ISB
|
||||
* ensures that CPU does below steps in order.
|
||||
*
|
||||
* 1. Ensure all other system registers are written before
|
||||
* updating SCTLR_EL1 using ISB.
|
||||
* 2. Restore SCTLR_EL1 register.
|
||||
* 3. Ensure SCTLR_EL1 written successfully using ISB.
|
||||
* 4. Restore TCR_EL1 register.
|
||||
* -----------------------------------------------------------
|
||||
*/
|
||||
isb
|
||||
ldp x28, x29, [sp, #CTX_EL1_SYSREGS_OFFSET + CTX_SCTLR_EL1]
|
||||
msr sctlr_el1, x28
|
||||
isb
|
||||
msr tcr_el1, x29
|
||||
#endif
|
||||
.endm
|
||||
|
||||
#endif /* EL2_COMMON_MACROS_S */
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -8,6 +8,13 @@
|
|||
|
||||
#include <lib/utils_def.h>
|
||||
|
||||
/* Base address of all V2M */
|
||||
#ifdef PLAT_V2M_OFFSET
|
||||
#define V2M_OFFSET PLAT_V2M_OFFSET
|
||||
#else
|
||||
#define V2M_OFFSET UL(0)
|
||||
#endif
|
||||
|
||||
/* V2M motherboard system registers & offsets */
|
||||
#define V2M_SYSREGS_BASE UL(0x1c010000)
|
||||
#define V2M_SYS_ID UL(0x0)
|
||||
|
@ -69,18 +76,18 @@
|
|||
|
||||
|
||||
/* NOR Flash */
|
||||
#define V2M_FLASH0_BASE UL(0x08000000)
|
||||
#define V2M_FLASH0_BASE (V2M_OFFSET + UL(0x08000000))
|
||||
#define V2M_FLASH0_SIZE UL(0x04000000)
|
||||
#define V2M_FLASH_BLOCK_SIZE UL(0x00040000) /* 256 KB */
|
||||
#define V2M_FLASH_BLOCK_SIZE UL(0x00040000) /* 256 KB */
|
||||
|
||||
#define V2M_IOFPGA_BASE UL(0x1c000000)
|
||||
#define V2M_IOFPGA_BASE (V2M_OFFSET + UL(0x1c000000))
|
||||
#define V2M_IOFPGA_SIZE UL(0x03000000)
|
||||
|
||||
/* PL011 UART related constants */
|
||||
#define V2M_IOFPGA_UART0_BASE UL(0x1c090000)
|
||||
#define V2M_IOFPGA_UART1_BASE UL(0x1c0a0000)
|
||||
#define V2M_IOFPGA_UART2_BASE UL(0x1c0b0000)
|
||||
#define V2M_IOFPGA_UART3_BASE UL(0x1c0c0000)
|
||||
#define V2M_IOFPGA_UART0_BASE (V2M_OFFSET + UL(0x1c090000))
|
||||
#define V2M_IOFPGA_UART1_BASE (V2M_OFFSET + UL(0x1c0a0000))
|
||||
#define V2M_IOFPGA_UART2_BASE (V2M_OFFSET + UL(0x1c0b0000))
|
||||
#define V2M_IOFPGA_UART3_BASE (V2M_OFFSET + UL(0x1c0c0000))
|
||||
|
||||
#define V2M_IOFPGA_UART0_CLK_IN_HZ 24000000
|
||||
#define V2M_IOFPGA_UART1_CLK_IN_HZ 24000000
|
||||
|
@ -88,11 +95,11 @@
|
|||
#define V2M_IOFPGA_UART3_CLK_IN_HZ 24000000
|
||||
|
||||
/* SP804 timer related constants */
|
||||
#define V2M_SP804_TIMER0_BASE UL(0x1C110000)
|
||||
#define V2M_SP804_TIMER1_BASE UL(0x1C120000)
|
||||
#define V2M_SP804_TIMER0_BASE (V2M_OFFSET + UL(0x1C110000))
|
||||
#define V2M_SP804_TIMER1_BASE (V2M_OFFSET + UL(0x1C120000))
|
||||
|
||||
/* SP810 controller */
|
||||
#define V2M_SP810_BASE UL(0x1c020000)
|
||||
#define V2M_SP810_BASE (V2M_OFFSET + UL(0x1c020000))
|
||||
#define V2M_SP810_CTRL_TIM0_SEL BIT_32(15)
|
||||
#define V2M_SP810_CTRL_TIM1_SEL BIT_32(17)
|
||||
#define V2M_SP810_CTRL_TIM2_SEL BIT_32(19)
|
||||
|
|
|
@ -58,12 +58,11 @@
|
|||
#define ARM_TRUSTED_DRAM_ID 1
|
||||
#define ARM_DRAM_ID 2
|
||||
|
||||
/* The first 4KB of Trusted SRAM are used as shared memory */
|
||||
#ifdef __PLAT_ARM_TRUSTED_SRAM_BASE__
|
||||
#ifdef PLAT_ARM_TRUSTED_SRAM_BASE
|
||||
#define ARM_TRUSTED_SRAM_BASE PLAT_ARM_TRUSTED_SRAM_BASE
|
||||
#else
|
||||
#define ARM_TRUSTED_SRAM_BASE UL(0x04000000)
|
||||
#endif /* __PLAT_ARM_TRUSTED_SRAM_BASE__ */
|
||||
#endif /* PLAT_ARM_TRUSTED_SRAM_BASE */
|
||||
|
||||
#define ARM_SHARED_RAM_BASE ARM_TRUSTED_SRAM_BASE
|
||||
#define ARM_SHARED_RAM_SIZE UL(0x00001000) /* 4 KB */
|
||||
|
@ -154,11 +153,11 @@
|
|||
ARM_TZC_DRAM1_SIZE)
|
||||
#define ARM_NS_DRAM1_END (ARM_NS_DRAM1_BASE + \
|
||||
ARM_NS_DRAM1_SIZE - 1U)
|
||||
#ifdef __PLAT_ARM_DRAM1_BASE__
|
||||
#ifdef PLAT_ARM_DRAM1_BASE
|
||||
#define ARM_DRAM1_BASE PLAT_ARM_DRAM1_BASE
|
||||
#else
|
||||
#define ARM_DRAM1_BASE ULL(0x80000000)
|
||||
#endif /* __PLAT_ARM_DRAM1_BASE__ */
|
||||
#endif /* PLAT_ARM_DRAM1_BASE */
|
||||
|
||||
#define ARM_DRAM1_SIZE ULL(0x80000000)
|
||||
#define ARM_DRAM1_END (ARM_DRAM1_BASE + \
|
||||
|
@ -321,16 +320,44 @@
|
|||
ARM_BL_REGIONS)
|
||||
|
||||
/* Memory mapped Generic timer interfaces */
|
||||
#ifdef PLAT_ARM_SYS_CNTCTL_BASE
|
||||
#define ARM_SYS_CNTCTL_BASE PLAT_ARM_SYS_CNTCTL_BASE
|
||||
#else
|
||||
#define ARM_SYS_CNTCTL_BASE UL(0x2a430000)
|
||||
#endif
|
||||
|
||||
#ifdef PLAT_ARM_SYS_CNTREAD_BASE
|
||||
#define ARM_SYS_CNTREAD_BASE PLAT_ARM_SYS_CNTREAD_BASE
|
||||
#else
|
||||
#define ARM_SYS_CNTREAD_BASE UL(0x2a800000)
|
||||
#endif
|
||||
|
||||
#ifdef PLAT_ARM_SYS_TIMCTL_BASE
|
||||
#define ARM_SYS_TIMCTL_BASE PLAT_ARM_SYS_TIMCTL_BASE
|
||||
#else
|
||||
#define ARM_SYS_TIMCTL_BASE UL(0x2a810000)
|
||||
#endif
|
||||
|
||||
#ifdef PLAT_ARM_SYS_CNT_BASE_S
|
||||
#define ARM_SYS_CNT_BASE_S PLAT_ARM_SYS_CNT_BASE_S
|
||||
#else
|
||||
#define ARM_SYS_CNT_BASE_S UL(0x2a820000)
|
||||
#endif
|
||||
|
||||
#ifdef PLAT_ARM_SYS_CNT_BASE_NS
|
||||
#define ARM_SYS_CNT_BASE_NS PLAT_ARM_SYS_CNT_BASE_NS
|
||||
#else
|
||||
#define ARM_SYS_CNT_BASE_NS UL(0x2a830000)
|
||||
#endif
|
||||
|
||||
#define ARM_CONSOLE_BAUDRATE 115200
|
||||
|
||||
/* Trusted Watchdog constants */
|
||||
#ifdef PLAT_ARM_SP805_TWDG_BASE
|
||||
#define ARM_SP805_TWDG_BASE PLAT_ARM_SP805_TWDG_BASE
|
||||
#else
|
||||
#define ARM_SP805_TWDG_BASE UL(0x2a490000)
|
||||
#endif
|
||||
#define ARM_SP805_TWDG_CLK_HZ 32768
|
||||
/* The TBBR document specifies a watchdog timeout of 256 seconds. SP805
|
||||
* asserts reset after two consecutive countdowns (2 x 128 = 256 sec) */
|
||||
|
|
53
lib/xlat_mpu/aarch64/enable_mpu.S
Normal file
53
lib/xlat_mpu/aarch64/enable_mpu.S
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <asm_macros.S>
|
||||
#include <assert_macros.S>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
.global enable_mpu_direct_el2
|
||||
|
||||
/* void enable_mmu_direct_el2(unsigned int flags) */
|
||||
func enable_mpu_direct_el2
|
||||
#if ENABLE_ASSERTIONS
|
||||
mrs x1, sctlr_el2
|
||||
tst x1, #SCTLR_M_BIT
|
||||
ASM_ASSERT(eq)
|
||||
#endif
|
||||
mov x7, x0
|
||||
adrp x0, mmu_cfg_params
|
||||
add x0, x0, :lo12:mmu_cfg_params
|
||||
|
||||
/* (MAIRs are already set up) */
|
||||
|
||||
/* TCR */
|
||||
ldr x2, [x0, #(MMU_CFG_TCR << 3)]
|
||||
msr tcr_el2, x2
|
||||
|
||||
/*
|
||||
* Ensure all translation table writes have drained into memory, the TLB
|
||||
* invalidation is complete, and translation register writes are
|
||||
* committed before enabling the MMU
|
||||
*/
|
||||
dsb ish
|
||||
isb
|
||||
|
||||
/* Set and clear required fields of SCTLR */
|
||||
mrs x4, sctlr_el2
|
||||
mov_imm x5, SCTLR_WXN_BIT | SCTLR_C_BIT | SCTLR_M_BIT
|
||||
orr x4, x4, x5
|
||||
|
||||
/* Additionally, amend SCTLR fields based on flags */
|
||||
bic x5, x4, #SCTLR_C_BIT
|
||||
tst x7, #DISABLE_DCACHE
|
||||
csel x4, x5, x4, ne
|
||||
|
||||
msr sctlr_el2, x4
|
||||
isb
|
||||
|
||||
ret
|
||||
endfunc enable_mpu_direct_el2
|
69
lib/xlat_mpu/aarch64/xlat_mpu_arch.c
Normal file
69
lib/xlat_mpu/aarch64/xlat_mpu_arch.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../xlat_mpu_private.h"
|
||||
#include <arch.h>
|
||||
#include <arch_features.h>
|
||||
#include <lib/cassert.h>
|
||||
#include <lib/utils_def.h>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
|
||||
#include <fvp_r_arch_helpers.h>
|
||||
|
||||
#warning "xlat_mpu library is currently experimental and its API may change in future."
|
||||
|
||||
#if ENABLE_ASSERTIONS
|
||||
/*
|
||||
* Return minimum virtual address space size supported by the architecture
|
||||
*/
|
||||
uintptr_t xlat_get_min_virt_addr_space_size(void)
|
||||
{
|
||||
uintptr_t ret;
|
||||
|
||||
if (is_armv8_4_ttst_present()) {
|
||||
ret = MIN_VIRT_ADDR_SPACE_SIZE_TTST;
|
||||
} else {
|
||||
ret = MIN_VIRT_ADDR_SPACE_SIZE;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif /* ENABLE_ASSERTIONS*/
|
||||
|
||||
bool is_mpu_enabled_ctx(const xlat_ctx_t *ctx)
|
||||
{
|
||||
if (ctx->xlat_regime == EL1_EL0_REGIME) {
|
||||
assert(xlat_arch_current_el() >= 1U);
|
||||
return (read_sctlr_el1() & SCTLR_M_BIT) != 0U;
|
||||
} else {
|
||||
assert(xlat_arch_current_el() >= 2U);
|
||||
return (read_sctlr_el2() & SCTLR_M_BIT) != 0U;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_dcache_enabled(void)
|
||||
{
|
||||
unsigned int el = get_current_el();
|
||||
|
||||
if (el == 1U) {
|
||||
return (read_sctlr_el1() & SCTLR_C_BIT) != 0U;
|
||||
} else { /* must be EL2 */
|
||||
return (read_sctlr_el2() & SCTLR_C_BIT) != 0U;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int xlat_arch_current_el(void)
|
||||
{
|
||||
unsigned int el = (unsigned int)GET_EL(read_CurrentEl());
|
||||
|
||||
assert(el > 0U);
|
||||
|
||||
return el;
|
||||
}
|
||||
|
14
lib/xlat_mpu/ro_xlat_mpu.mk
Normal file
14
lib/xlat_mpu/ro_xlat_mpu.mk
Normal file
|
@ -0,0 +1,14 @@
|
|||
#
|
||||
# Copyright (c) 2021, ARM Limited. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
ifeq (${USE_DEBUGFS}, 1)
|
||||
$(error "Debugfs requires functionality from the dynamic translation \
|
||||
library and is incompatible with ALLOW_RO_XLAT_TABLES.")
|
||||
endif
|
||||
|
||||
ifeq (${ARCH},aarch32)
|
||||
$(error "The xlat_mpu library does not currently support AArch32.")
|
||||
endif
|
22
lib/xlat_mpu/xlat_mpu.h
Normal file
22
lib/xlat_mpu/xlat_mpu.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef XLAT_MPU_H
|
||||
#define XLAT_MPU_H
|
||||
|
||||
#define XLAT_TABLES_LIB_V2 1
|
||||
|
||||
void enable_mpu_el2(unsigned int flags);
|
||||
void enable_mpu_direct_el2(unsigned int flags);
|
||||
|
||||
/*
|
||||
* Function to wipe clean and disable all MPU regions. This function expects
|
||||
* that the MPU has already been turned off, and caching concerns addressed,
|
||||
* but it nevertheless also explicitly turns off the MPU.
|
||||
*/
|
||||
void clear_all_mpu_regions(void);
|
||||
|
||||
#endif /* XLAT_MPU_H */
|
19
lib/xlat_mpu/xlat_mpu.mk
Normal file
19
lib/xlat_mpu/xlat_mpu.mk
Normal file
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
XLAT_MPU_LIB_V1_SRCS := $(addprefix lib/xlat_mpu/, \
|
||||
${ARCH}/enable_mpu.S \
|
||||
${ARCH}/xlat_mpu_arch.c \
|
||||
xlat_mpu_context.c \
|
||||
xlat_mpu_core.c \
|
||||
xlat_mpu_utils.c)
|
||||
|
||||
XLAT_MPU_LIB_V1 := 1
|
||||
$(eval $(call add_define,XLAT_MPU_LIB_V1))
|
||||
|
||||
ifeq (${ALLOW_XLAT_MPU}, 1)
|
||||
include lib/xlat_mpu_v2/ro_xlat_mpu.mk
|
||||
endif
|
65
lib/xlat_mpu/xlat_mpu_context.c
Normal file
65
lib/xlat_mpu/xlat_mpu_context.c
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
|
||||
#include <lib/xlat_tables/xlat_tables_defs.h>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
#include "xlat_mpu.h"
|
||||
#include "xlat_mpu_private.h"
|
||||
|
||||
#include <fvp_r_arch_helpers.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#warning "xlat_mpu library is currently experimental and its API may change in future."
|
||||
|
||||
|
||||
/*
|
||||
* MMU configuration register values for the active translation context. Used
|
||||
* from the MMU assembly helpers.
|
||||
*/
|
||||
uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
|
||||
|
||||
/*
|
||||
* Allocate and initialise the default translation context for the BL image
|
||||
* currently executing.
|
||||
*/
|
||||
REGISTER_XLAT_CONTEXT(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES,
|
||||
PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE);
|
||||
|
||||
void mmap_add(const mmap_region_t *mm)
|
||||
{
|
||||
mmap_add_ctx(&tf_xlat_ctx, mm);
|
||||
}
|
||||
|
||||
void __init init_xlat_tables(void)
|
||||
{
|
||||
assert(tf_xlat_ctx.xlat_regime == EL_REGIME_INVALID);
|
||||
|
||||
unsigned int current_el = xlat_arch_current_el();
|
||||
|
||||
if (current_el == 1U) {
|
||||
tf_xlat_ctx.xlat_regime = EL1_EL0_REGIME;
|
||||
} else {
|
||||
assert(current_el == 2U);
|
||||
tf_xlat_ctx.xlat_regime = EL2_REGIME;
|
||||
}
|
||||
/* Note: If EL3 is supported in future v8-R64, add EL3 assignment */
|
||||
init_xlat_tables_ctx(&tf_xlat_ctx);
|
||||
}
|
||||
|
||||
int xlat_get_mem_attributes(uintptr_t base_va, uint32_t *attr)
|
||||
{
|
||||
return xlat_get_mem_attributes_ctx(&tf_xlat_ctx, base_va, attr);
|
||||
}
|
||||
|
||||
void enable_mpu_el2(unsigned int flags)
|
||||
{
|
||||
/* EL2 is strictly MPU on v8-R64, so no need for setup_mpu_cfg() */
|
||||
enable_mpu_direct_el2(flags);
|
||||
}
|
408
lib/xlat_mpu/xlat_mpu_core.c
Normal file
408
lib/xlat_mpu/xlat_mpu_core.c
Normal file
|
@ -0,0 +1,408 @@
|
|||
/*
|
||||
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <arch_features.h>
|
||||
#include <common/debug.h>
|
||||
#include <lib/utils_def.h>
|
||||
#include <lib/xlat_tables/xlat_tables_defs.h>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
#include "xlat_mpu_private.h"
|
||||
|
||||
#include <fvp_r_arch_helpers.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#warning "xlat_mpu library is currently experimental and its API may change in future."
|
||||
|
||||
|
||||
/* Helper function that cleans the data cache only if it is enabled. */
|
||||
static inline __attribute__((unused))
|
||||
void xlat_clean_dcache_range(uintptr_t addr, size_t size)
|
||||
{
|
||||
if (is_dcache_enabled()) {
|
||||
clean_dcache_range(addr, size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Calculate region-attributes byte for PRBAR part of MPU-region descriptor: */
|
||||
uint64_t prbar_attr_value(uint32_t attr)
|
||||
{
|
||||
uint64_t retValue = UL(0);
|
||||
uint64_t extract; /* temp var holding bit extracted from attr */
|
||||
|
||||
/* Extract and stuff SH: */
|
||||
extract = (uint64_t) ((attr >> MT_SHAREABILITY_SHIFT)
|
||||
& MT_SHAREABILITY_MASK);
|
||||
retValue |= (extract << PRBAR_SH_SHIFT);
|
||||
|
||||
/* Extract and stuff AP: */
|
||||
extract = (uint64_t) ((attr >> MT_PERM_SHIFT) & MT_PERM_MASK);
|
||||
if (extract == 0U) {
|
||||
retValue |= (UL(2) << PRBAR_AP_SHIFT);
|
||||
} else /* extract == 1 */ {
|
||||
retValue |= (UL(0) << PRBAR_AP_SHIFT);
|
||||
}
|
||||
|
||||
/* Extract and stuff XN: */
|
||||
extract = (uint64_t) ((attr >> MT_EXECUTE_SHIFT) & MT_EXECUTE_MASK);
|
||||
retValue |= (extract << PRBAR_XN_SHIFT);
|
||||
/* However, also don't execute in peripheral space: */
|
||||
extract = (uint64_t) ((attr >> MT_TYPE_SHIFT) & MT_TYPE_MASK);
|
||||
if (extract == 0U) {
|
||||
retValue |= (UL(1) << PRBAR_XN_SHIFT);
|
||||
}
|
||||
return retValue;
|
||||
}
|
||||
|
||||
/* Calculate region-attributes byte for PRLAR part of MPU-region descriptor: */
|
||||
uint64_t prlar_attr_value(uint32_t attr)
|
||||
{
|
||||
uint64_t retValue = UL(0);
|
||||
uint64_t extract; /* temp var holding bit extracted from attr */
|
||||
|
||||
/* Extract and stuff AttrIndx: */
|
||||
extract = (uint64_t) ((attr >> MT_TYPE_SHIFT)
|
||||
& MT_TYPE_MASK);
|
||||
switch (extract) {
|
||||
case UL(0):
|
||||
retValue |= (UL(1) << PRLAR_ATTR_SHIFT);
|
||||
break;
|
||||
case UL(2):
|
||||
/* 0, so OR in nothing */
|
||||
break;
|
||||
case UL(3):
|
||||
retValue |= (UL(2) << PRLAR_ATTR_SHIFT);
|
||||
break;
|
||||
default:
|
||||
retValue |= (extract << PRLAR_ATTR_SHIFT);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Stuff EN: */
|
||||
retValue |= (UL(1) << PRLAR_EN_SHIFT);
|
||||
|
||||
/* Force NS to 0 (Secure); v8-R64 only supports Secure: */
|
||||
extract = ~(1U << PRLAR_NS_SHIFT);
|
||||
retValue &= extract;
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function that writes an MPU "translation" into the MPU registers. If not
|
||||
* possible (e.g., if no more MPU regions available) boot is aborted.
|
||||
*/
|
||||
static void mpu_map_region(mmap_region_t *mm)
|
||||
{
|
||||
uint64_t prenr_el2_value = 0UL;
|
||||
uint64_t prbar_attrs = 0UL;
|
||||
uint64_t prlar_attrs = 0UL;
|
||||
int region_to_use = 0;
|
||||
|
||||
/* If all MPU regions in use, then abort boot: */
|
||||
prenr_el2_value = read_prenr_el2();
|
||||
assert(prenr_el2_value != 0xffffffff);
|
||||
|
||||
/* Find and select first-available MPU region (PRENR has an enable bit
|
||||
* for each MPU region, 1 for in-use or 0 for unused):
|
||||
*/
|
||||
for (region_to_use = 0; region_to_use < N_MPU_REGIONS;
|
||||
region_to_use++) {
|
||||
if (((prenr_el2_value >> region_to_use) & 1) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
write_prselr_el2((uint64_t) (region_to_use));
|
||||
isb();
|
||||
|
||||
/* Set base and limit addresses: */
|
||||
write_prbar_el2(mm->base_pa & PRBAR_PRLAR_ADDR_MASK);
|
||||
write_prlar_el2((mm->base_pa + mm->size - 1UL)
|
||||
& PRBAR_PRLAR_ADDR_MASK);
|
||||
dsbsy();
|
||||
isb();
|
||||
|
||||
/* Set attributes: */
|
||||
prbar_attrs = prbar_attr_value(mm->attr);
|
||||
write_prbar_el2(read_prbar_el2() | prbar_attrs);
|
||||
prlar_attrs = prlar_attr_value(mm->attr);
|
||||
write_prlar_el2(read_prlar_el2() | prlar_attrs);
|
||||
dsbsy();
|
||||
isb();
|
||||
|
||||
/* Mark this MPU region as used: */
|
||||
prenr_el2_value |= (1 << region_to_use);
|
||||
write_prenr_el2(prenr_el2_value);
|
||||
isb();
|
||||
}
|
||||
|
||||
/*
|
||||
* Function that verifies that a region can be mapped.
|
||||
* Returns:
|
||||
* 0: Success, the mapping is allowed.
|
||||
* EINVAL: Invalid values were used as arguments.
|
||||
* ERANGE: The memory limits were surpassed.
|
||||
* ENOMEM: There is not enough memory in the mmap array.
|
||||
* EPERM: Region overlaps another one in an invalid way.
|
||||
*/
|
||||
static int mmap_add_region_check(const xlat_ctx_t *ctx, const mmap_region_t *mm)
|
||||
{
|
||||
unsigned long long base_pa = mm->base_pa;
|
||||
uintptr_t base_va = mm->base_va;
|
||||
size_t size = mm->size;
|
||||
|
||||
unsigned long long end_pa = base_pa + size - 1U;
|
||||
uintptr_t end_va = base_va + size - 1U;
|
||||
|
||||
if (base_pa != base_va) {
|
||||
return -EINVAL; /* MPU does not perform address translation */
|
||||
}
|
||||
if ((base_pa % 64ULL) != 0ULL) {
|
||||
return -EINVAL; /* MPU requires 64-byte alignment */
|
||||
}
|
||||
/* Check for overflows */
|
||||
if ((base_pa > end_pa) || (base_va > end_va)) {
|
||||
return -ERANGE;
|
||||
}
|
||||
if (end_pa > ctx->pa_max_address) {
|
||||
return -ERANGE;
|
||||
}
|
||||
/* Check that there is space in the ctx->mmap array */
|
||||
if (ctx->mmap[ctx->mmap_num - 1].size != 0U) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
/* Check for PAs and VAs overlaps with all other regions */
|
||||
for (const mmap_region_t *mm_cursor = ctx->mmap;
|
||||
mm_cursor->size != 0U; ++mm_cursor) {
|
||||
|
||||
uintptr_t mm_cursor_end_va =
|
||||
mm_cursor->base_va + mm_cursor->size - 1U;
|
||||
|
||||
/*
|
||||
* Check if one of the regions is completely inside the other
|
||||
* one.
|
||||
*/
|
||||
bool fully_overlapped_va =
|
||||
((base_va >= mm_cursor->base_va) &&
|
||||
(end_va <= mm_cursor_end_va)) ||
|
||||
((mm_cursor->base_va >= base_va) &&
|
||||
(mm_cursor_end_va <= end_va));
|
||||
|
||||
/*
|
||||
* Full VA overlaps are only allowed if both regions are
|
||||
* identity mapped (zero offset) or have the same VA to PA
|
||||
* offset. Also, make sure that it's not the exact same area.
|
||||
* This can only be done with static regions.
|
||||
*/
|
||||
if (fully_overlapped_va) {
|
||||
|
||||
#if PLAT_XLAT_TABLES_DYNAMIC
|
||||
if (((mm->attr & MT_DYNAMIC) != 0U) ||
|
||||
((mm_cursor->attr & MT_DYNAMIC) != 0U)) {
|
||||
return -EPERM;
|
||||
}
|
||||
#endif /* PLAT_XLAT_TABLES_DYNAMIC */
|
||||
if ((mm_cursor->base_va - mm_cursor->base_pa)
|
||||
!= (base_va - base_pa)) {
|
||||
return -EPERM;
|
||||
}
|
||||
if ((base_va == mm_cursor->base_va) &&
|
||||
(size == mm_cursor->size)) {
|
||||
return -EPERM;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* If the regions do not have fully overlapping VAs,
|
||||
* then they must have fully separated VAs and PAs.
|
||||
* Partial overlaps are not allowed
|
||||
*/
|
||||
|
||||
unsigned long long mm_cursor_end_pa =
|
||||
mm_cursor->base_pa + mm_cursor->size - 1U;
|
||||
|
||||
bool separated_pa = (end_pa < mm_cursor->base_pa) ||
|
||||
(base_pa > mm_cursor_end_pa);
|
||||
bool separated_va = (end_va < mm_cursor->base_va) ||
|
||||
(base_va > mm_cursor_end_va);
|
||||
|
||||
if (!separated_va || !separated_pa) {
|
||||
return -EPERM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm)
|
||||
{
|
||||
mmap_region_t *mm_cursor = ctx->mmap, *mm_destination;
|
||||
const mmap_region_t *mm_end = ctx->mmap + ctx->mmap_num;
|
||||
const mmap_region_t *mm_last;
|
||||
unsigned long long end_pa = mm->base_pa + mm->size - 1U;
|
||||
uintptr_t end_va = mm->base_va + mm->size - 1U;
|
||||
int ret;
|
||||
|
||||
/* Ignore empty regions */
|
||||
if (mm->size == 0U) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Static regions must be added before initializing the xlat tables. */
|
||||
assert(!ctx->initialized);
|
||||
|
||||
ret = mmap_add_region_check(ctx, mm);
|
||||
if (ret != 0) {
|
||||
ERROR("mmap_add_region_check() failed. error %d\n", ret);
|
||||
assert(false);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the last entry marker in the mmap
|
||||
*/
|
||||
mm_last = ctx->mmap;
|
||||
while ((mm_last->size != 0U) && (mm_last < mm_end)) {
|
||||
++mm_last;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if we have enough space in the memory mapping table.
|
||||
* This shouldn't happen as we have checked in mmap_add_region_check
|
||||
* that there is free space.
|
||||
*/
|
||||
assert(mm_last->size == 0U);
|
||||
|
||||
/* Make room for new region by moving other regions up by one place */
|
||||
mm_destination = mm_cursor + 1;
|
||||
(void)memmove(mm_destination, mm_cursor,
|
||||
(uintptr_t)mm_last - (uintptr_t)mm_cursor);
|
||||
|
||||
/*
|
||||
* Check we haven't lost the empty sentinel from the end of the array.
|
||||
* This shouldn't happen as we have checked in mmap_add_region_check
|
||||
* that there is free space.
|
||||
*/
|
||||
assert(mm_end->size == 0U);
|
||||
|
||||
*mm_cursor = *mm;
|
||||
|
||||
if (end_pa > ctx->max_pa) {
|
||||
ctx->max_pa = end_pa;
|
||||
}
|
||||
if (end_va > ctx->max_va) {
|
||||
ctx->max_va = end_va;
|
||||
}
|
||||
}
|
||||
|
||||
void mmap_add_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm)
|
||||
{
|
||||
const mmap_region_t *mm_cursor = mm;
|
||||
|
||||
while (mm_cursor->granularity != 0U) {
|
||||
mmap_add_region_ctx(ctx, mm_cursor);
|
||||
mm_cursor++;
|
||||
}
|
||||
}
|
||||
|
||||
void __init init_xlat_tables_ctx(xlat_ctx_t *ctx)
|
||||
{
|
||||
uint64_t mair = UL(0);
|
||||
|
||||
assert(ctx != NULL);
|
||||
assert(!ctx->initialized);
|
||||
assert((ctx->xlat_regime == EL2_REGIME) ||
|
||||
(ctx->xlat_regime == EL1_EL0_REGIME));
|
||||
/* Note: Add EL3_REGIME if EL3 is supported in future v8-R64 cores. */
|
||||
assert(!is_mpu_enabled_ctx(ctx));
|
||||
|
||||
mmap_region_t *mm = ctx->mmap;
|
||||
|
||||
assert(ctx->va_max_address >=
|
||||
(xlat_get_min_virt_addr_space_size() - 1U));
|
||||
assert(ctx->va_max_address <= (MAX_VIRT_ADDR_SPACE_SIZE - 1U));
|
||||
assert(IS_POWER_OF_TWO(ctx->va_max_address + 1U));
|
||||
|
||||
xlat_mmap_print(mm);
|
||||
|
||||
/* All tables must be zeroed before mapping any region. */
|
||||
|
||||
for (unsigned int i = 0U; i < ctx->base_table_entries; i++)
|
||||
ctx->base_table[i] = INVALID_DESC;
|
||||
|
||||
/* Also mark all MPU regions as invalid in the MPU hardware itself: */
|
||||
write_prenr_el2(0);
|
||||
/* Sufficient for current, max-32-region implementations. */
|
||||
dsbsy();
|
||||
isb();
|
||||
while (mm->size != 0U) {
|
||||
if (read_prenr_el2() == ALL_MPU_EL2_REGIONS_USED) {
|
||||
ERROR("Not enough MPU regions to map region:\n"
|
||||
" VA:0x%lx PA:0x%llx size:0x%zx attr:0x%x\n",
|
||||
mm->base_va, mm->base_pa, mm->size, mm->attr);
|
||||
panic();
|
||||
} else {
|
||||
#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY)
|
||||
xlat_clean_dcache_range((uintptr_t)mm->base_va,
|
||||
mm->size);
|
||||
#endif
|
||||
mpu_map_region(mm);
|
||||
}
|
||||
mm++;
|
||||
}
|
||||
|
||||
ctx->initialized = true;
|
||||
|
||||
xlat_tables_print(ctx);
|
||||
|
||||
/* Set attributes in the right indices of the MAIR */
|
||||
mair = MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX);
|
||||
mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR,
|
||||
ATTR_IWBWA_OWBWA_NTR_INDEX);
|
||||
mair |= MAIR_ATTR_SET(ATTR_NON_CACHEABLE,
|
||||
ATTR_NON_CACHEABLE_INDEX);
|
||||
write_mair_el2(mair);
|
||||
dsbsy();
|
||||
isb();
|
||||
}
|
||||
|
||||
/*
|
||||
* Function to wipe clean and disable all MPU regions. This function expects
|
||||
* that the MPU has already been turned off, and caching concerns addressed,
|
||||
* but it nevertheless also explicitly turns off the MPU.
|
||||
*/
|
||||
void clear_all_mpu_regions(void)
|
||||
{
|
||||
uint64_t sctlr_el2_value = 0UL;
|
||||
uint64_t region_n = 0UL;
|
||||
|
||||
/*
|
||||
* MPU should already be disabled, but explicitly disable it
|
||||
* nevertheless:
|
||||
*/
|
||||
sctlr_el2_value = read_sctlr_el2() & ~(1UL);
|
||||
write_sctlr_el2(sctlr_el2_value);
|
||||
|
||||
/* Disable all regions: */
|
||||
write_prenr_el2(0UL);
|
||||
|
||||
/* Sequence through all regions, zeroing them out and turning off: */
|
||||
for (region_n = 0UL; region_n < N_MPU_REGIONS; region_n++) {
|
||||
write_prselr_el2(region_n);
|
||||
isb();
|
||||
write_prbar_el2((uint64_t) 0);
|
||||
write_prlar_el2((uint64_t) 0);
|
||||
dsbsy();
|
||||
isb();
|
||||
}
|
||||
}
|
103
lib/xlat_mpu/xlat_mpu_private.h
Normal file
103
lib/xlat_mpu/xlat_mpu_private.h
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef XLAT_MPU_PRIVATE_H
|
||||
#define XLAT_MPU_PRIVATE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <lib/xlat_tables/xlat_tables_defs.h>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#if PLAT_XLAT_TABLES_DYNAMIC
|
||||
/*
|
||||
* Private shifts and masks to access fields of an mmap attribute
|
||||
*/
|
||||
/* Dynamic or static */
|
||||
#define MT_DYN_SHIFT U(31)
|
||||
|
||||
/*
|
||||
* Memory mapping private attributes
|
||||
*
|
||||
* Private attributes not exposed in the public header.
|
||||
*/
|
||||
|
||||
#endif /* PLAT_XLAT_TABLES_DYNAMIC */
|
||||
|
||||
/* Calculate region-attributes byte for PRBAR part of MPU-region descriptor: */
|
||||
uint64_t prbar_attr_value(uint32_t attr);
|
||||
/* Calculate region-attributes byte for PRLAR part of MPU-region descriptor: */
|
||||
uint64_t prlar_attr_value(uint32_t attr);
|
||||
/* Calculates the attr value for a given PRBAR and PRLAR entry value: */
|
||||
uint32_t region_attr(uint64_t prbar_attr, uint64_t prlar_attr);
|
||||
|
||||
#define PRBAR_PRLAR_ADDR_MASK UL(0xffffffffffc0)
|
||||
/* mask for PRBAR & PRLAR MPU-region field */
|
||||
/* MPU region attribute bit fields: */
|
||||
#define PRBAR_SH_SHIFT UL(4)
|
||||
#define PRBAR_SH_MASK UL(0x3)
|
||||
#define PRBAR_AP_SHIFT UL(2)
|
||||
#define PRBAR_AP_MASK UL(0x3)
|
||||
#define PRBAR_XN_SHIFT UL(1)
|
||||
#define PRBAR_XN_MASK UL(0x3)
|
||||
#define PRLAR_NS_SHIFT UL(4)
|
||||
#define PRLAR_NS_MASK UL(0x3)
|
||||
#define PRBAR_ATTR_SHIFT UL(0)
|
||||
#define PRBAR_ATTR_MASK UL(0x3f)
|
||||
#define PRLAR_ATTR_SHIFT UL(1)
|
||||
#define PRLAR_ATTR_MASK UL(0x7)
|
||||
#define PRLAR_EN_SHIFT UL(0)
|
||||
#define PRLAR_EN_MASK UL(0x1)
|
||||
/* Aspects of the source attributes not defined elsewhere: */
|
||||
#define MT_PERM_MASK UL(0x1)
|
||||
#define MT_SEC_MASK UL(0x1)
|
||||
#define MT_EXECUTE_MASK UL(0x3)
|
||||
#define MT_TYPE_SHIFT UL(0)
|
||||
|
||||
extern uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
|
||||
|
||||
/*
|
||||
* Return the execute-never mask that will prevent instruction fetch at the
|
||||
* given translation regime.
|
||||
*/
|
||||
uint64_t xlat_arch_regime_get_xn_desc(int xlat_regime);
|
||||
|
||||
/* Print VA, PA, size and attributes of all regions in the mmap array. */
|
||||
void xlat_mmap_print(const mmap_region_t *mmap);
|
||||
|
||||
/*
|
||||
* Print the current state of the translation tables by reading them from
|
||||
* memory.
|
||||
*/
|
||||
void xlat_tables_print(xlat_ctx_t *ctx);
|
||||
|
||||
/*
|
||||
* Returns a block/page table descriptor for the given level and attributes.
|
||||
*/
|
||||
uint64_t xlat_desc(const xlat_ctx_t *ctx, uint32_t attr,
|
||||
unsigned long long addr_pa, unsigned int level);
|
||||
|
||||
/*
|
||||
* Architecture-specific initialization code.
|
||||
*/
|
||||
|
||||
/* Returns the current Exception Level. The returned EL must be 1 or higher. */
|
||||
unsigned int xlat_arch_current_el(void);
|
||||
|
||||
/*
|
||||
* Returns true if the MMU of the translation regime managed by the given
|
||||
* xlat_ctx_t is enabled, false otherwise.
|
||||
*/
|
||||
bool is_mpu_enabled_ctx(const xlat_ctx_t *ctx);
|
||||
|
||||
/*
|
||||
* Returns minimum virtual address space size supported by the architecture
|
||||
*/
|
||||
uintptr_t xlat_get_min_virt_addr_space_size(void);
|
||||
|
||||
#endif /* XLAT_MPU_PRIVATE_H */
|
71
lib/xlat_mpu/xlat_mpu_utils.c
Normal file
71
lib/xlat_mpu/xlat_mpu_utils.c
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <lib/utils_def.h>
|
||||
#include <lib/xlat_tables/xlat_tables_defs.h>
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
#include "xlat_mpu_private.h"
|
||||
|
||||
#include <fvp_r_arch_helpers.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#warning "xlat_mpu library is currently experimental and its API may change in future."
|
||||
|
||||
|
||||
#if LOG_LEVEL < LOG_LEVEL_VERBOSE
|
||||
|
||||
void xlat_mmap_print(__unused const mmap_region_t *mmap)
|
||||
{
|
||||
/* Empty */
|
||||
}
|
||||
|
||||
void xlat_tables_print(__unused xlat_ctx_t *ctx)
|
||||
{
|
||||
/* Empty */
|
||||
}
|
||||
|
||||
#else /* if LOG_LEVEL >= LOG_LEVEL_VERBOSE */
|
||||
|
||||
static const char *invalid_descriptors_ommited =
|
||||
"%s(%d invalid descriptors omitted)\n";
|
||||
|
||||
void xlat_tables_print(xlat_ctx_t *ctx)
|
||||
{
|
||||
const char *xlat_regime_str;
|
||||
int used_page_tables;
|
||||
|
||||
if (ctx->xlat_regime == EL1_EL0_REGIME) {
|
||||
xlat_regime_str = "1&0";
|
||||
} else if (ctx->xlat_regime == EL2_REGIME) {
|
||||
xlat_regime_str = "2";
|
||||
} else {
|
||||
assert(ctx->xlat_regime == EL3_REGIME);
|
||||
xlat_regime_str = "3";
|
||||
/* If no EL3 and EL3 tables generated, then need to know. */
|
||||
}
|
||||
VERBOSE("Translation tables state:\n");
|
||||
VERBOSE(" Xlat regime: EL%s\n", xlat_regime_str);
|
||||
VERBOSE(" Max allowed PA: 0x%llx\n", ctx->pa_max_address);
|
||||
VERBOSE(" Max allowed VA: 0x%lx\n", ctx->va_max_address);
|
||||
VERBOSE(" Max mapped PA: 0x%llx\n", ctx->max_pa);
|
||||
VERBOSE(" Max mapped VA: 0x%lx\n", ctx->max_va);
|
||||
|
||||
VERBOSE(" Initial lookup level: %u\n", ctx->base_level);
|
||||
VERBOSE(" Entries @initial lookup level: %u\n",
|
||||
ctx->base_table_entries);
|
||||
|
||||
xlat_tables_print_internal(ctx, 0U, ctx->base_table,
|
||||
ctx->base_table_entries, ctx->base_level);
|
||||
}
|
||||
|
||||
#endif /* LOG_LEVEL >= LOG_LEVEL_VERBOSE */
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -147,7 +147,7 @@ void init_xlat_tables(void)
|
|||
* exception level
|
||||
******************************************************************************/
|
||||
#define DEFINE_ENABLE_MMU_EL(_el, _tcr_extra, _tlbi_fct) \
|
||||
void enable_mmu_el##_el(unsigned int flags) \
|
||||
void enable_mmu_el##_el(unsigned int flags) \
|
||||
{ \
|
||||
uint64_t mair, tcr, ttbr; \
|
||||
uint32_t sctlr; \
|
||||
|
|
35
plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c
Normal file
35
plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include "../../../../bl1/bl1_private.h"
|
||||
#include <arch.h>
|
||||
|
||||
#include <fvp_r_arch_helpers.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Function that does the first bit of architectural setup that affects
|
||||
* execution in the non-secure address space.
|
||||
******************************************************************************/
|
||||
void bl1_arch_setup(void)
|
||||
{
|
||||
/* v8-R64 does not include SCRs. */
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Set the Secure EL1 required architectural state
|
||||
******************************************************************************/
|
||||
void bl1_arch_next_el_setup(void)
|
||||
{
|
||||
u_register_t next_sctlr;
|
||||
|
||||
/* Use the same endianness than the current BL */
|
||||
next_sctlr = (read_sctlr_el2() & SCTLR_EE_BIT);
|
||||
|
||||
/* Set SCTLR Secure EL1 */
|
||||
next_sctlr |= SCTLR_EL1_RES1;
|
||||
|
||||
write_sctlr_el1(next_sctlr);
|
||||
}
|
96
plat/arm/board/fvp_r/fvp_r_bl1_context_mgmt.c
Normal file
96
plat/arm/board/fvp_r/fvp_r_bl1_context_mgmt.c
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../../../../bl1/bl1_private.h"
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <context.h>
|
||||
#include <lib/el3_runtime/context_mgmt.h>
|
||||
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
|
||||
void cm_prepare_el2_exit(uint32_t security_state);
|
||||
|
||||
/* Following contains the cpu context pointers. */
|
||||
static void *bl1_cpu_context_ptr[2];
|
||||
|
||||
void *cm_get_context(uint32_t security_state)
|
||||
{
|
||||
assert(sec_state_is_valid(security_state));
|
||||
return bl1_cpu_context_ptr[security_state];
|
||||
}
|
||||
|
||||
void cm_set_context(void *context, uint32_t security_state)
|
||||
{
|
||||
assert(sec_state_is_valid(security_state));
|
||||
bl1_cpu_context_ptr[security_state] = context;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function prepares the context for Secure/Normal world images.
|
||||
* Normal world images are transitioned to EL2(if supported) else EL1.
|
||||
******************************************************************************/
|
||||
void bl1_prepare_next_image(unsigned int image_id)
|
||||
{
|
||||
/*
|
||||
* Following array will be used for context management.
|
||||
* There are 2 instances, for the Secure and Non-Secure contexts.
|
||||
*/
|
||||
static cpu_context_t bl1_cpu_context[2];
|
||||
|
||||
unsigned int security_state, mode = MODE_EL1;
|
||||
image_desc_t *desc;
|
||||
entry_point_info_t *next_bl_ep;
|
||||
|
||||
#if CTX_INCLUDE_AARCH32_REGS
|
||||
/*
|
||||
* Ensure that the build flag to save AArch32 system registers in CPU
|
||||
* context is not set for AArch64-only platforms.
|
||||
*/
|
||||
if (el_implemented(1) == EL_IMPL_A64ONLY) {
|
||||
ERROR("EL1 supports AArch64-only. Please set build flag %s",
|
||||
"CTX_INCLUDE_AARCH32_REGS = 0\n");
|
||||
panic();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get the image descriptor. */
|
||||
desc = bl1_plat_get_image_desc(image_id);
|
||||
assert(desc != NULL);
|
||||
|
||||
/* Get the entry point info. */
|
||||
next_bl_ep = &desc->ep_info;
|
||||
|
||||
/* Get the image security state. */
|
||||
security_state = GET_SECURITY_STATE(next_bl_ep->h.attr);
|
||||
|
||||
/* Setup the Secure/Non-Secure context if not done already. */
|
||||
if (cm_get_context(security_state) == NULL) {
|
||||
cm_set_context(&bl1_cpu_context[security_state], security_state);
|
||||
}
|
||||
/* Prepare the SPSR for the next BL image. */
|
||||
if ((security_state != SECURE) && (el_implemented(2) != EL_IMPL_NONE)) {
|
||||
mode = MODE_EL2;
|
||||
}
|
||||
|
||||
next_bl_ep->spsr = (uint32_t)SPSR_64((uint64_t) mode,
|
||||
(uint64_t)MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS);
|
||||
|
||||
/* Allow platform to make change */
|
||||
bl1_plat_set_ep_info(image_id, next_bl_ep);
|
||||
|
||||
/* Prepare the context for the next BL image. */
|
||||
cm_init_my_context(next_bl_ep);
|
||||
cm_prepare_el2_exit(security_state);
|
||||
|
||||
/* Indicate that image is in execution state. */
|
||||
desc->state = IMAGE_STATE_EXECUTED;
|
||||
|
||||
print_entry_point_info(next_bl_ep);
|
||||
}
|
70
plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S
Normal file
70
plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S
Normal file
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <el2_common_macros.S>
|
||||
|
||||
.globl bl1_entrypoint
|
||||
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* bl1_entrypoint() is the entry point into the trusted
|
||||
* firmware code when a cpu is released from warm or
|
||||
* cold reset.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
|
||||
func bl1_entrypoint
|
||||
/* ---------------------------------------------------------------------
|
||||
* If the reset address is programmable then bl1_entrypoint() is
|
||||
* executed only on the cold boot path. Therefore, we can skip the warm
|
||||
* boot mailbox mechanism.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
el2_entrypoint_common \
|
||||
_init_sctlr=1 \
|
||||
_warm_boot_mailbox=!PROGRAMMABLE_RESET_ADDRESS \
|
||||
_secondary_cold_boot=!COLD_BOOT_SINGLE_CPU \
|
||||
_init_memory=1 \
|
||||
_init_c_runtime=1 \
|
||||
_exception_vectors=bl1_exceptions \
|
||||
_pie_fixup_size=0
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Perform BL1 setup
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
bl bl1_setup
|
||||
|
||||
#if ENABLE_PAUTH
|
||||
/* --------------------------------------------------------------------
|
||||
* Program APIAKey_EL1 and enable pointer authentication.
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
bl pauth_init_enable_el2
|
||||
#endif /* ENABLE_PAUTH */
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* Initialize platform and jump to our c-entry point
|
||||
* for this type of reset.
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
bl bl1_main
|
||||
|
||||
#if ENABLE_PAUTH
|
||||
/* --------------------------------------------------------------------
|
||||
* Disable pointer authentication before jumping to next boot image.
|
||||
* --------------------------------------------------------------------
|
||||
*/
|
||||
bl pauth_disable_el2
|
||||
#endif /* ENABLE_PAUTH */
|
||||
|
||||
/* --------------------------------------------------
|
||||
* Do the transition to next boot image.
|
||||
* --------------------------------------------------
|
||||
*/
|
||||
b el2_exit
|
||||
endfunc bl1_entrypoint
|
120
plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S
Normal file
120
plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <bl1/bl1.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <context.h>
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* File contains an EL2 equivalent of the EL3 vector table from:
|
||||
* .../bl1/aarch64/bl1_exceptions.S
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Very simple stackless exception handlers used by BL1.
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
.globl bl1_exceptions
|
||||
|
||||
vector_base bl1_exceptions
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Current EL with SP0 : 0x0 - 0x200
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_entry SynchronousExceptionSP0
|
||||
mov x0, #SYNC_EXCEPTION_SP_EL0
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
end_vector_entry SynchronousExceptionSP0
|
||||
|
||||
vector_entry IrqSP0
|
||||
mov x0, #IRQ_SP_EL0
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
end_vector_entry IrqSP0
|
||||
|
||||
vector_entry FiqSP0
|
||||
mov x0, #FIQ_SP_EL0
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
end_vector_entry FiqSP0
|
||||
|
||||
vector_entry SErrorSP0
|
||||
mov x0, #SERROR_SP_EL0
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
end_vector_entry SErrorSP0
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Current EL with SPx: 0x200 - 0x400
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_entry SynchronousExceptionSPx
|
||||
mov x0, #SYNC_EXCEPTION_SP_ELX
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
end_vector_entry SynchronousExceptionSPx
|
||||
|
||||
vector_entry IrqSPx
|
||||
mov x0, #IRQ_SP_ELX
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
end_vector_entry IrqSPx
|
||||
|
||||
vector_entry FiqSPx
|
||||
mov x0, #FIQ_SP_ELX
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
end_vector_entry FiqSPx
|
||||
|
||||
vector_entry SErrorSPx
|
||||
mov x0, #SERROR_SP_ELX
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
end_vector_entry SErrorSPx
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Lower EL using AArch64 : 0x400 - 0x600
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
vector_entry SynchronousExceptionA64
|
||||
/* The current v8-R64 implementation does not support conduit calls */
|
||||
b el2_panic
|
||||
end_vector_entry SynchronousExceptionA64
|
||||
|
||||
vector_entry IrqA64
|
||||
mov x0, #IRQ_AARCH64
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
end_vector_entry IrqA64
|
||||
|
||||
vector_entry FiqA64
|
||||
mov x0, #FIQ_AARCH64
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
end_vector_entry FiqA64
|
||||
|
||||
vector_entry SErrorA64
|
||||
mov x0, #SERROR_AARCH64
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
end_vector_entry SErrorA64
|
||||
|
||||
|
||||
unexpected_sync_exception:
|
||||
mov x0, #SYNC_EXCEPTION_AARCH64
|
||||
bl plat_report_exception
|
||||
no_ret plat_panic_handler
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* Save Secure/Normal world context and jump to
|
||||
* BL1 SMC handler.
|
||||
* -----------------------------------------------------
|
||||
*/
|
213
plat/arm/board/fvp_r/fvp_r_bl1_main.c
Normal file
213
plat/arm/board/fvp_r/fvp_r_bl1_main.c
Normal file
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../../../../bl1/bl1_private.h"
|
||||
#include <arch.h>
|
||||
#include <arch_features.h>
|
||||
#include <arch_helpers.h>
|
||||
#include <bl1/bl1.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/auth/auth_mod.h>
|
||||
#include <drivers/console.h>
|
||||
#include <lib/cpus/errata_report.h>
|
||||
#include <lib/utils.h>
|
||||
#include <smccc_helpers.h>
|
||||
#include <tools_share/uuid.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
|
||||
static void bl1_load_bl2(void);
|
||||
|
||||
#if ENABLE_PAUTH
|
||||
uint64_t bl1_apiakey[2];
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Helper utility to calculate the BL2 memory layout taking into consideration
|
||||
* the BL1 RW data assuming that it is at the top of the memory layout.
|
||||
******************************************************************************/
|
||||
void bl1_calc_bl2_mem_layout(const meminfo_t *bl1_mem_layout,
|
||||
meminfo_t *bl2_mem_layout)
|
||||
{
|
||||
assert(bl1_mem_layout != NULL);
|
||||
assert(bl2_mem_layout != NULL);
|
||||
|
||||
/*
|
||||
* Remove BL1 RW data from the scope of memory visible to BL2.
|
||||
* This is assuming BL1 RW data is at the top of bl1_mem_layout.
|
||||
*/
|
||||
assert(bl1_mem_layout->total_base < BL1_RW_BASE);
|
||||
bl2_mem_layout->total_base = bl1_mem_layout->total_base;
|
||||
bl2_mem_layout->total_size = BL1_RW_BASE - bl1_mem_layout->total_base;
|
||||
|
||||
flush_dcache_range((uintptr_t)bl2_mem_layout, sizeof(meminfo_t));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Setup function for BL1.
|
||||
******************************************************************************/
|
||||
void bl1_setup(void)
|
||||
{
|
||||
/* Perform early platform-specific setup */
|
||||
bl1_early_platform_setup();
|
||||
|
||||
/* Perform late platform-specific setup */
|
||||
bl1_plat_arch_setup();
|
||||
|
||||
#if CTX_INCLUDE_PAUTH_REGS
|
||||
/*
|
||||
* Assert that the ARMv8.3-PAuth registers are present or an access
|
||||
* fault will be triggered when they are being saved or restored.
|
||||
*/
|
||||
assert(is_armv8_3_pauth_present());
|
||||
#endif /* CTX_INCLUDE_PAUTH_REGS */
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function to perform late architectural and platform specific initialization.
|
||||
* It also queries the platform to load and run next BL image. Only called
|
||||
* by the primary cpu after a cold boot.
|
||||
******************************************************************************/
|
||||
void bl1_main(void)
|
||||
{
|
||||
unsigned int image_id;
|
||||
|
||||
/* Announce our arrival */
|
||||
NOTICE(FIRMWARE_WELCOME_STR);
|
||||
NOTICE("BL1: %s\n", version_string);
|
||||
NOTICE("BL1: %s\n", build_message);
|
||||
|
||||
INFO("BL1: RAM %p - %p\n", (void *)BL1_RAM_BASE, (void *)BL1_RAM_LIMIT);
|
||||
|
||||
print_errata_status();
|
||||
|
||||
#if ENABLE_ASSERTIONS
|
||||
u_register_t val;
|
||||
/*
|
||||
* Ensure that MMU/Caches and coherency are turned on
|
||||
*/
|
||||
val = read_sctlr_el2();
|
||||
|
||||
assert((val & SCTLR_M_BIT) != 0U);
|
||||
assert((val & SCTLR_C_BIT) != 0U);
|
||||
assert((val & SCTLR_I_BIT) != 0U);
|
||||
/*
|
||||
* Check that Cache Writeback Granule (CWG) in CTR_EL0 matches the
|
||||
* provided platform value
|
||||
*/
|
||||
val = (read_ctr_el0() >> CTR_CWG_SHIFT) & CTR_CWG_MASK;
|
||||
/*
|
||||
* If CWG is zero, then no CWG information is available but we can
|
||||
* at least check the platform value is less than the architectural
|
||||
* maximum.
|
||||
*/
|
||||
if (val != 0) {
|
||||
assert(SIZE_FROM_LOG2_WORDS(val) == CACHE_WRITEBACK_GRANULE);
|
||||
} else {
|
||||
assert(CACHE_WRITEBACK_GRANULE <= MAX_CACHE_LINE_SIZE);
|
||||
}
|
||||
#endif /* ENABLE_ASSERTIONS */
|
||||
|
||||
/* Perform remaining generic architectural setup from EL2 */
|
||||
bl1_arch_setup();
|
||||
|
||||
#if TRUSTED_BOARD_BOOT
|
||||
/* Initialize authentication module */
|
||||
auth_mod_init();
|
||||
#endif /* TRUSTED_BOARD_BOOT */
|
||||
|
||||
/* Perform platform setup in BL1. */
|
||||
bl1_platform_setup();
|
||||
|
||||
#if ENABLE_PAUTH
|
||||
/* Store APIAKey_EL1 key */
|
||||
bl1_apiakey[0] = read_apiakeylo_el1();
|
||||
bl1_apiakey[1] = read_apiakeyhi_el1();
|
||||
#endif /* ENABLE_PAUTH */
|
||||
|
||||
/* Get the image id of next image to load and run. */
|
||||
image_id = bl1_plat_get_next_image_id();
|
||||
|
||||
/*
|
||||
* We currently interpret any image id other than
|
||||
* BL2_IMAGE_ID as the start of firmware update.
|
||||
*/
|
||||
if (image_id == BL2_IMAGE_ID) {
|
||||
bl1_load_bl2();
|
||||
} else {
|
||||
NOTICE("BL1-FWU: *******FWU Process Started*******\n");
|
||||
}
|
||||
bl1_prepare_next_image(image_id);
|
||||
|
||||
console_flush();
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* This function locates and loads the BL2 raw binary image in the trusted SRAM.
|
||||
* Called by the primary cpu after a cold boot.
|
||||
* TODO: Add support for alternative image load mechanism e.g using virtio/elf
|
||||
* loader etc.
|
||||
******************************************************************************/
|
||||
static void bl1_load_bl2(void)
|
||||
{
|
||||
image_desc_t *desc;
|
||||
image_info_t *info;
|
||||
int err;
|
||||
|
||||
/* Get the image descriptor */
|
||||
desc = bl1_plat_get_image_desc(BL2_IMAGE_ID);
|
||||
assert(desc != NULL);
|
||||
|
||||
/* Get the image info */
|
||||
info = &desc->image_info;
|
||||
INFO("BL1: Loading BL2\n");
|
||||
|
||||
err = bl1_plat_handle_pre_image_load(BL2_IMAGE_ID);
|
||||
if (err != 0) {
|
||||
ERROR("Failure in pre image load handling of BL2 (%d)\n", err);
|
||||
plat_error_handler(err);
|
||||
}
|
||||
|
||||
err = load_auth_image(BL2_IMAGE_ID, info);
|
||||
if (err != 0) {
|
||||
ERROR("Failed to load BL2 firmware.\n");
|
||||
plat_error_handler(err);
|
||||
}
|
||||
|
||||
/* Allow platform to handle image information. */
|
||||
err = bl1_plat_handle_post_image_load(BL2_IMAGE_ID);
|
||||
if (err != 0) {
|
||||
ERROR("Failure in post image load handling of BL2 (%d)\n", err);
|
||||
plat_error_handler(err);
|
||||
}
|
||||
|
||||
NOTICE("BL1: Booting BL2\n");
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function called just before handing over to the next BL to inform the user
|
||||
* about the boot progress. In debug mode, also print details about the BL
|
||||
* image's execution context.
|
||||
******************************************************************************/
|
||||
void bl1_print_next_bl_ep_info(const entry_point_info_t *bl_ep_info)
|
||||
{
|
||||
NOTICE("BL1: Booting BL31\n");
|
||||
print_entry_point_info(bl_ep_info);
|
||||
}
|
||||
|
||||
#if SPIN_ON_BL1_EXIT
|
||||
void print_debug_loop_message(void)
|
||||
{
|
||||
NOTICE("BL1: Debug loop, spinning forever\n");
|
||||
NOTICE("BL1: Please connect the debugger to continue\n");
|
||||
}
|
||||
#endif
|
||||
|
|
@ -4,8 +4,12 @@
|
|||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/* Use the xlat_tables_v2 data structures: */
|
||||
#define XLAT_TABLES_LIB_V2 1
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "../../../../lib/xlat_mpu/xlat_mpu.h"
|
||||
#include <bl1/bl1.h>
|
||||
#include <common/tbbr/tbbr_img_def.h>
|
||||
#include <drivers/arm/sp805.h>
|
||||
|
@ -16,6 +20,56 @@
|
|||
#include <plat/arm/common/plat_arm.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#define MAP_BL1_TOTAL MAP_REGION_FLAT( \
|
||||
bl1_tzram_layout.total_base, \
|
||||
bl1_tzram_layout.total_size, \
|
||||
MT_MEMORY | MT_RW | MT_SECURE)
|
||||
/*
|
||||
* If SEPARATE_CODE_AND_RODATA=1 we define a region for each section
|
||||
* otherwise one region is defined containing both
|
||||
*/
|
||||
#if SEPARATE_CODE_AND_RODATA
|
||||
#define MAP_BL1_RO MAP_REGION_FLAT( \
|
||||
BL_CODE_BASE, \
|
||||
BL1_CODE_END - BL_CODE_BASE, \
|
||||
MT_CODE | MT_SECURE), \
|
||||
MAP_REGION_FLAT( \
|
||||
BL1_RO_DATA_BASE, \
|
||||
BL1_RO_DATA_END \
|
||||
- BL_RO_DATA_BASE, \
|
||||
MT_RO_DATA | MT_SECURE)
|
||||
#else
|
||||
#define MAP_BL1_RO MAP_REGION_FLAT( \
|
||||
BL_CODE_BASE, \
|
||||
BL1_CODE_END - BL_CODE_BASE, \
|
||||
MT_CODE | MT_SECURE)
|
||||
#endif
|
||||
|
||||
/* Data structure which holds the extents of the trusted SRAM for BL1*/
|
||||
static meminfo_t bl1_tzram_layout;
|
||||
|
||||
struct meminfo *bl1_plat_sec_mem_layout(void)
|
||||
{
|
||||
return &bl1_tzram_layout;
|
||||
}
|
||||
|
||||
void arm_bl1_early_platform_setup(void)
|
||||
{
|
||||
|
||||
#if !ARM_DISABLE_TRUSTED_WDOG
|
||||
/* Enable watchdog */
|
||||
plat_arm_secure_wdt_start();
|
||||
#endif
|
||||
|
||||
/* Initialize the console to provide early debug support */
|
||||
arm_console_boot_init();
|
||||
|
||||
/* Allow BL1 to see the whole Trusted RAM */
|
||||
bl1_tzram_layout.total_base = ARM_BL_RAM_BASE;
|
||||
bl1_tzram_layout.total_size = ARM_BL_RAM_SIZE;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Perform any BL1 specific platform actions.
|
||||
|
@ -38,6 +92,34 @@ void bl1_early_platform_setup(void)
|
|||
fvp_interconnect_enable();
|
||||
}
|
||||
|
||||
void arm_bl1_plat_arch_setup(void)
|
||||
{
|
||||
const mmap_region_t bl_regions[] = {
|
||||
MAP_BL1_TOTAL,
|
||||
MAP_BL1_RO,
|
||||
#if USE_ROMLIB
|
||||
ARM_MAP_ROMLIB_CODE,
|
||||
ARM_MAP_ROMLIB_DATA,
|
||||
#endif
|
||||
#if ARM_CRYPTOCELL_INTEG
|
||||
ARM_MAP_BL_COHERENT_RAM,
|
||||
#endif
|
||||
/* DRAM1_region: */
|
||||
MAP_REGION_FLAT( \
|
||||
PLAT_ARM_DRAM1_BASE, \
|
||||
PLAT_ARM_DRAM1_SIZE, \
|
||||
MT_MEMORY | MT_SECURE | MT_EXECUTE \
|
||||
| MT_RW | MT_NON_CACHEABLE),
|
||||
/* NULL terminator: */
|
||||
{0}
|
||||
};
|
||||
|
||||
setup_page_tables(bl_regions, plat_arm_get_mmap());
|
||||
enable_mpu_el2(0);
|
||||
|
||||
arm_setup_romlib();
|
||||
}
|
||||
|
||||
void plat_arm_secure_wdt_start(void)
|
||||
{
|
||||
sp805_start(ARM_SP805_TWDG_BASE, ARM_TWDG_LOAD_VAL);
|
||||
|
|
|
@ -4,9 +4,12 @@
|
|||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
/* This uses xlat_mpu, but tables are set up using V2 mmap_region_t */
|
||||
#define XLAT_TABLES_LIB_V2 1
|
||||
|
||||
#include <assert.h>
|
||||
#include <common/debug.h>
|
||||
|
||||
#include <drivers/arm/cci.h>
|
||||
#include <drivers/arm/ccn.h>
|
||||
#include <drivers/arm/gicv2.h>
|
||||
|
@ -109,7 +112,80 @@ static unsigned int get_interconnect_master(void)
|
|||
******************************************************************************/
|
||||
void __init fvp_config_setup(void)
|
||||
{
|
||||
unsigned int rev, hbi, bld, arch, sys_id;
|
||||
|
||||
arm_config.flags |= ARM_CONFIG_BASE_MMAP;
|
||||
sys_id = mmio_read_32(V2M_FVP_R_SYSREGS_BASE + V2M_SYS_ID);
|
||||
rev = (sys_id >> V2M_SYS_ID_REV_SHIFT) & V2M_SYS_ID_REV_MASK;
|
||||
hbi = (sys_id >> V2M_SYS_ID_HBI_SHIFT) & V2M_SYS_ID_HBI_MASK;
|
||||
bld = (sys_id >> V2M_SYS_ID_BLD_SHIFT) & V2M_SYS_ID_BLD_MASK;
|
||||
arch = (sys_id >> V2M_SYS_ID_ARCH_SHIFT) & V2M_SYS_ID_ARCH_MASK;
|
||||
|
||||
if (arch != ARCH_MODEL) {
|
||||
ERROR("This firmware is for FVP_R models\n");
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* The build field in the SYS_ID tells which variant of the GIC
|
||||
* memory is implemented by the model.
|
||||
*/
|
||||
switch (bld) {
|
||||
case BLD_GIC_VE_MMAP:
|
||||
ERROR("Legacy Versatile Express memory map for GIC %s",
|
||||
"peripheral is not supported\n");
|
||||
panic();
|
||||
break;
|
||||
case BLD_GIC_A53A57_MMAP:
|
||||
break;
|
||||
default:
|
||||
ERROR("Unsupported board build %x\n", bld);
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* The hbi field in the SYS_ID is 0x020 for the Base FVP_R & 0x010
|
||||
* for the Foundation FVP_R.
|
||||
*/
|
||||
switch (hbi) {
|
||||
case HBI_FOUNDATION_FVP_R:
|
||||
arm_config.flags = 0;
|
||||
|
||||
/*
|
||||
* Check for supported revisions of Foundation FVP_R
|
||||
* Allow future revisions to run but emit warning diagnostic
|
||||
*/
|
||||
switch (rev) {
|
||||
case REV_FOUNDATION_FVP_R_V2_0:
|
||||
case REV_FOUNDATION_FVP_R_V2_1:
|
||||
case REV_FOUNDATION_FVP_R_v9_1:
|
||||
case REV_FOUNDATION_FVP_R_v9_6:
|
||||
break;
|
||||
default:
|
||||
WARN("Unrecognized Foundation FVP_R revision %x\n", rev);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case HBI_BASE_FVP_R:
|
||||
arm_config.flags |= (ARM_CONFIG_BASE_MMAP | ARM_CONFIG_HAS_TZC);
|
||||
|
||||
/*
|
||||
* Check for supported revisions
|
||||
* Allow future revisions to run but emit warning diagnostic
|
||||
*/
|
||||
switch (rev) {
|
||||
case REV_BASE_FVP_R_V0:
|
||||
arm_config.flags |= ARM_CONFIG_FVP_HAS_CCI400;
|
||||
break;
|
||||
default:
|
||||
WARN("Unrecognized Base FVP_R revision %x\n", rev);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR("Unsupported board HBI number 0x%x\n", hbi);
|
||||
panic();
|
||||
}
|
||||
|
||||
/*
|
||||
* We assume that the presence of MT bit, and therefore shifted
|
||||
|
|
17
plat/arm/board/fvp_r/fvp_r_context.S
Normal file
17
plat/arm/board/fvp_r/fvp_r_context.S
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <asm_macros.S>
|
||||
|
||||
.global el2_exit
|
||||
|
||||
/* ------------------------------------------------------------------
|
||||
* The mechanism, from el3_exit, is not used in this v8-R64 implementation.
|
||||
* ------------------------------------------------------------------
|
||||
*/
|
||||
func el2_exit
|
||||
exception_return
|
||||
endfunc el2_exit
|
28
plat/arm/board/fvp_r/fvp_r_context_mgmt.c
Normal file
28
plat/arm/board/fvp_r/fvp_r_context_mgmt.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <lib/el3_runtime/context_mgmt.h>
|
||||
#include <lib/el3_runtime/pubsub_events.h>
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* File contains EL2 equivalents of EL3 functions from
|
||||
* .../lib/el3_runtime/aarch64/context_mgmt.c
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* Prepare the CPU system registers for first entry into secure or normal world
|
||||
*
|
||||
* The majority of the work needed is only for switching to non-secure, which
|
||||
* is not available on v8-R64 cores, so this function is very simple.
|
||||
******************************************************************************/
|
||||
void cm_prepare_el2_exit(uint32_t security_state)
|
||||
{
|
||||
cm_el1_sysregs_context_restore(security_state);
|
||||
cm_set_next_eret_context(security_state);
|
||||
}
|
46
plat/arm/board/fvp_r/fvp_r_debug.S
Normal file
46
plat/arm/board/fvp_r/fvp_r_debug.S
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <common/debug.h>
|
||||
|
||||
.globl el2_panic
|
||||
|
||||
/***********************************************************
|
||||
* The common implementation of do_panic for all BL stages
|
||||
***********************************************************/
|
||||
|
||||
.section .rodata.panic_str, "aS"
|
||||
panic_msg: .asciz "PANIC at PC : 0x"
|
||||
|
||||
/*
|
||||
* el2_panic will be redefined by the
|
||||
* crash reporting mechanism (if enabled)
|
||||
*/
|
||||
el2_panic:
|
||||
mov x6, x30
|
||||
bl plat_crash_console_init
|
||||
|
||||
/* Check if the console is initialized */
|
||||
cbz x0, _panic_handler
|
||||
|
||||
/* The console is initialized */
|
||||
adr x4, panic_msg
|
||||
bl asm_print_str
|
||||
mov x4, x6
|
||||
|
||||
/* The panic location is lr -4 */
|
||||
sub x4, x4, #4
|
||||
bl asm_print_hex
|
||||
|
||||
bl plat_crash_console_flush
|
||||
|
||||
_panic_handler:
|
||||
/* Pass to plat_panic_handler the address from where el2_panic was
|
||||
* called, not the address of the call from el2_panic. */
|
||||
mov x30, x6
|
||||
b plat_panic_handler
|
|
@ -36,40 +36,44 @@
|
|||
* FVP_R memory map related constants
|
||||
******************************************************************************/
|
||||
|
||||
#define FLASH1_BASE UL(0x0c000000)
|
||||
#define FLASH1_BASE UL(0x8c000000)
|
||||
#define FLASH1_SIZE UL(0x04000000)
|
||||
|
||||
#define PSRAM_BASE UL(0x14000000)
|
||||
#define PSRAM_BASE UL(0x94000000)
|
||||
#define PSRAM_SIZE UL(0x04000000)
|
||||
|
||||
#define VRAM_BASE UL(0x18000000)
|
||||
#define VRAM_BASE UL(0x98000000)
|
||||
#define VRAM_SIZE UL(0x02000000)
|
||||
|
||||
/* Aggregate of all devices in the first GB */
|
||||
#define DEVICE0_BASE UL(0x20000000)
|
||||
#define DEVICE0_BASE UL(0xa0000000)
|
||||
#define DEVICE0_SIZE UL(0x0c200000)
|
||||
|
||||
/*
|
||||
* In case of FVP_R models with CCN, the CCN register space overlaps into
|
||||
* the NSRAM area.
|
||||
*/
|
||||
#define DEVICE1_BASE UL(0x2e000000)
|
||||
#define DEVICE1_BASE UL(0xae000000)
|
||||
#define DEVICE1_SIZE UL(0x1A00000)
|
||||
#define NSRAM_BASE UL(0x2e000000)
|
||||
|
||||
#define NSRAM_BASE UL(0xae000000)
|
||||
#define NSRAM_SIZE UL(0x10000)
|
||||
/* Devices in the second GB */
|
||||
#define DEVICE2_BASE UL(0x7fe00000)
|
||||
#define DEVICE2_BASE UL(0xffe00000)
|
||||
#define DEVICE2_SIZE UL(0x00200000)
|
||||
|
||||
#define PCIE_EXP_BASE UL(0xc0000000)
|
||||
#define TZRNG_BASE UL(0x7fe60000)
|
||||
|
||||
/* Non-volatile counters */
|
||||
#define TRUSTED_NVCTR_BASE UL(0x7fe70000)
|
||||
#define TRUSTED_NVCTR_BASE UL(0xffe70000)
|
||||
#define TFW_NVCTR_BASE (TRUSTED_NVCTR_BASE + UL(0x0000))
|
||||
#define TFW_NVCTR_SIZE UL(4)
|
||||
#define NTFW_CTR_BASE (TRUSTED_NVCTR_BASE + UL(0x0004))
|
||||
#define NTFW_CTR_SIZE UL(4)
|
||||
|
||||
/* Keys */
|
||||
#define SOC_KEYS_BASE UL(0x7fe80000)
|
||||
#define SOC_KEYS_BASE UL(0xffe80000)
|
||||
#define TZ_PUB_KEY_HASH_BASE (SOC_KEYS_BASE + UL(0x0000))
|
||||
#define TZ_PUB_KEY_HASH_SIZE UL(32)
|
||||
#define HU_KEY_BASE (SOC_KEYS_BASE + UL(0x0020))
|
||||
|
|
32
plat/arm/board/fvp_r/fvp_r_misc_helpers.S
Normal file
32
plat/arm/board/fvp_r/fvp_r_misc_helpers.S
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <asm_macros.S>
|
||||
|
||||
.globl disable_mpu_el2
|
||||
.globl disable_mpu_icache_el2
|
||||
|
||||
/* ---------------------------------------------------------------------------
|
||||
* Disable the MPU at EL2.
|
||||
* ---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
func disable_mpu_el2
|
||||
mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT)
|
||||
do_disable_mpu_el2:
|
||||
mrs x0, sctlr_el2
|
||||
bic x0, x0, x1
|
||||
msr sctlr_el2, x0
|
||||
isb /* ensure MMU is off */
|
||||
dsb sy
|
||||
ret
|
||||
endfunc disable_mpu_el2
|
||||
|
||||
|
||||
func disable_mpu_icache_el2
|
||||
mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT)
|
||||
b do_disable_mpu_el2
|
||||
endfunc disable_mpu_icache_el2
|
59
plat/arm/board/fvp_r/fvp_r_pauth_helpers.S
Normal file
59
plat/arm/board/fvp_r/fvp_r_pauth_helpers.S
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <lib/el3_runtime/cpu_data.h>
|
||||
|
||||
.global pauth_init_enable_el2
|
||||
.global pauth_disable_el2
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
* File contains EL2 versions of EL3 funcs in:
|
||||
* .../lib/extensions/pauth/pauth_helpers.S
|
||||
* -------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
* Program APIAKey_EL1 and enable pointer authentication in EL2
|
||||
* -------------------------------------------------------------
|
||||
*/
|
||||
func pauth_init_enable_el2
|
||||
stp x29, x30, [sp, #-16]!
|
||||
|
||||
/* Initialize platform key */
|
||||
bl plat_init_apkey
|
||||
|
||||
/* Program instruction key A used by the Trusted Firmware */
|
||||
msr APIAKeyLo_EL1, x0
|
||||
msr APIAKeyHi_EL1, x1
|
||||
|
||||
/* Enable pointer authentication */
|
||||
mrs x0, sctlr_el2
|
||||
orr x0, x0, #SCTLR_EnIA_BIT
|
||||
|
||||
#if ENABLE_BTI
|
||||
/* Enable PAC branch type compatibility */
|
||||
bic x0, x0, #SCTLR_BT_BIT
|
||||
#endif
|
||||
msr sctlr_el2, x0
|
||||
isb
|
||||
|
||||
ldp x29, x30, [sp], #16
|
||||
ret
|
||||
endfunc pauth_init_enable_el2
|
||||
|
||||
/* -------------------------------------------------------------
|
||||
* Disable pointer authentication in EL2
|
||||
* -------------------------------------------------------------
|
||||
*/
|
||||
func pauth_disable_el2
|
||||
mrs x0, sctlr_el2
|
||||
bic x0, x0, #SCTLR_EnIA_BIT
|
||||
msr sctlr_el2, x0
|
||||
isb
|
||||
ret
|
||||
endfunc pauth_disable_el2
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <fvp_r_arch_helpers.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#define RANDOM_CANARY_VALUE ((u_register_t) 8092347823957523895ULL)
|
||||
|
|
|
@ -22,13 +22,13 @@
|
|||
* Return the ROTPK hash in the following ASN.1 structure in DER format:
|
||||
*
|
||||
* AlgorithmIdentifier ::= SEQUENCE {
|
||||
* algorithm OBJECT IDENTIFIER,
|
||||
* parameters ANY DEFINED BY algorithm OPTIONAL
|
||||
* algorithm OBJECT IDENTIFIER,
|
||||
* parameters ANY DEFINED BY algorithm OPTIONAL
|
||||
* }
|
||||
*
|
||||
* DigestInfo ::= SEQUENCE {
|
||||
* digestAlgorithm AlgorithmIdentifier,
|
||||
* digest OCTET STRING
|
||||
* digestAlgorithm AlgorithmIdentifier,
|
||||
* digest OCTET STRING
|
||||
* }
|
||||
*/
|
||||
int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
|
||||
|
|
28
plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h
Normal file
28
plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef FVP_R_ARCH_HELPERS_H
|
||||
#define FVP_R_ARCH_HELPERS_H
|
||||
|
||||
#include <arch_helpers.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* MPU register definitions
|
||||
******************************************************************************/
|
||||
#define MPUIR_EL2 S3_4_C0_C0_4
|
||||
#define PRBAR_EL2 S3_4_C6_C8_0
|
||||
#define PRLAR_EL2 S3_4_C6_C8_1
|
||||
#define PRSELR_EL2 S3_4_C6_C2_1
|
||||
#define PRENR_EL2 S3_4_C6_C1_1
|
||||
|
||||
/* v8-R64 MPU registers */
|
||||
DEFINE_RENAME_SYSREG_RW_FUNCS(mpuir_el2, MPUIR_EL2)
|
||||
DEFINE_RENAME_SYSREG_RW_FUNCS(prenr_el2, PRENR_EL2)
|
||||
DEFINE_RENAME_SYSREG_RW_FUNCS(prselr_el2, PRSELR_EL2)
|
||||
DEFINE_RENAME_SYSREG_RW_FUNCS(prbar_el2, PRBAR_EL2)
|
||||
DEFINE_RENAME_SYSREG_RW_FUNCS(prlar_el2, PRLAR_EL2)
|
||||
|
||||
#endif /* FVP_R_ARCH_HELPERS_H */
|
|
@ -4,19 +4,37 @@
|
|||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_DEF_H
|
||||
#define PLATFORM_DEF_H
|
||||
#ifndef FVP_R_PLATFORM_DEF_H
|
||||
#define FVP_R_PLATFORM_DEF_H
|
||||
|
||||
#define PLAT_V2M_OFFSET 0x80000000
|
||||
|
||||
#include "../fvp_r_def.h"
|
||||
#include <drivers/arm/tzc400.h>
|
||||
#include <lib/utils_def.h>
|
||||
#include <plat/arm/board/common/v2m_def.h>
|
||||
|
||||
/* These are referenced by arm_def.h #included next, so #define first. */
|
||||
#define PLAT_ARM_TRUSTED_ROM_BASE UL(0x80000000)
|
||||
#define PLAT_ARM_TRUSTED_SRAM_BASE UL(0x84000000)
|
||||
#define PLAT_ARM_TRUSTED_DRAM_BASE UL(0x86000000)
|
||||
#define PLAT_ARM_DRAM1_BASE ULL(0x0)
|
||||
#define PLAT_ARM_DRAM2_BASE ULL(0x080000000)
|
||||
|
||||
#define PLAT_HW_CONFIG_DTB_BASE ULL(0x12000000)
|
||||
#define PLAT_ARM_SYS_CNTCTL_BASE UL(0xaa430000)
|
||||
#define PLAT_ARM_SYS_CNTREAD_BASE UL(0xaa800000)
|
||||
#define PLAT_ARM_SYS_TIMCTL_BASE UL(0xaa810000)
|
||||
#define PLAT_ARM_SYS_CNT_BASE_S UL(0xaa820000)
|
||||
#define PLAT_ARM_SYS_CNT_BASE_NS UL(0xaa830000)
|
||||
#define PLAT_ARM_SP805_TWDG_BASE UL(0xaa490000)
|
||||
|
||||
#include <plat/arm/common/arm_def.h>
|
||||
#include <plat/common/common_def.h>
|
||||
|
||||
|
||||
#define NO_EL3 1
|
||||
/* Required to create plat_regions: */
|
||||
#define MIN_LVL_BLOCK_DESC U(1)
|
||||
|
||||
/* Required platform porting definitions */
|
||||
#define PLATFORM_CORE_COUNT (U(FVP_R_CLUSTER_COUNT) * \
|
||||
|
@ -36,34 +54,35 @@
|
|||
* Required ARM standard platform porting definitions
|
||||
*/
|
||||
#define PLAT_ARM_CLUSTER_COUNT U(FVP_R_CLUSTER_COUNT)
|
||||
|
||||
#define PLAT_ARM_DRAM1_BASE ULL(0x0)
|
||||
|
||||
#define PLAT_ARM_TRUSTED_ROM_BASE UL(0x80000000)
|
||||
#define PLAT_ARM_TRUSTED_ROM_SIZE UL(0x04000000) /* 64 MB */
|
||||
|
||||
#define PLAT_ARM_TRUSTED_SRAM_BASE UL(0x84000000)
|
||||
#define PLAT_ARM_DRAM1_SIZE ULL(0x7fffffff)
|
||||
#define PLAT_ARM_TRUSTED_SRAM_SIZE UL(0x00040000) /* 256 KB */
|
||||
|
||||
#define PLAT_ARM_TRUSTED_DRAM_BASE UL(0x86000000)
|
||||
#define PLAT_ARM_TRUSTED_ROM_SIZE UL(0x04000000) /* 64 MB */
|
||||
#define PLAT_ARM_TRUSTED_DRAM_SIZE UL(0x02000000) /* 32 MB */
|
||||
|
||||
/* These two are defined thus in arm_def.h, but doesn't seem to see it... */
|
||||
#undef BL1_RO_BASE
|
||||
#define BL1_RO_BASE PLAT_ARM_TRUSTED_ROM_BASE
|
||||
#undef BL1_RO_LIMIT
|
||||
#define BL1_RO_LIMIT (BL1_RO_BASE \
|
||||
+ PLAT_ARM_TRUSTED_ROM_SIZE)
|
||||
|
||||
/* virtual address used by dynamic mem_protect for chunk_base */
|
||||
#define PLAT_ARM_MEM_PROTEC_VA_FRAME UL(0xc0000000)
|
||||
|
||||
/* No SCP in FVP_R */
|
||||
#define PLAT_ARM_SCP_TZC_DRAM1_SIZE UL(0x0)
|
||||
|
||||
#define PLAT_ARM_DRAM2_BASE ULL(0x080000000)
|
||||
#define PLAT_ARM_DRAM2_SIZE UL(0x80000000)
|
||||
|
||||
#define PLAT_HW_CONFIG_DTB_BASE ULL(0x12000000)
|
||||
#define PLAT_HW_CONFIG_DTB_SIZE ULL(0x8000)
|
||||
|
||||
#define ARM_DTB_DRAM_NS MAP_REGION_FLAT( \
|
||||
PLAT_HW_CONFIG_DTB_BASE, \
|
||||
PLAT_HW_CONFIG_DTB_SIZE, \
|
||||
MT_MEMORY | MT_RO | MT_NS)
|
||||
|
||||
#define V2M_FVP_R_SYSREGS_BASE UL(0x9c010000)
|
||||
|
||||
/*
|
||||
* Load address of BL33 for this platform port
|
||||
*/
|
||||
|
@ -80,6 +99,9 @@
|
|||
# define PLAT_ARM_MMAP_ENTRIES 12
|
||||
# define MAX_XLAT_TABLES 6
|
||||
#endif
|
||||
# define N_MPU_REGIONS 16 /* number of MPU regions */
|
||||
# define ALL_MPU_EL2_REGIONS_USED 0xffffffff
|
||||
/* this is the PRENR_EL2 value if all MPU regions are in use */
|
||||
|
||||
/*
|
||||
* These nominally reserve the last block of flash for PSCI MEM PROTECT flag,
|
||||
|
@ -228,15 +250,10 @@
|
|||
/*
|
||||
* Physical and virtual address space limits for MPU in AARCH64 & AARCH32 modes
|
||||
*/
|
||||
#ifdef __aarch64__
|
||||
#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 36)
|
||||
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 36)
|
||||
#else
|
||||
#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32)
|
||||
#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32)
|
||||
#endif
|
||||
|
||||
#define ARM_SOC_CONTINUATION_SHIFT U(24)
|
||||
#define ARM_SOC_IDENTIFICATION_SHIFT U(16)
|
||||
|
||||
#endif /* PLATFORM_DEF_H */
|
||||
#endif /* FVP_R_PLATFORM_DEF_H */
|
||||
|
|
|
@ -22,6 +22,9 @@ FVP_R_MAX_CPUS_PER_CLUSTER := 4
|
|||
# Default number of threads per CPU on FVP_R
|
||||
FVP_R_MAX_PE_PER_CPU := 1
|
||||
|
||||
# Use MPU-based memory management:
|
||||
XLAT_MPU_LIB_V1 := 1
|
||||
|
||||
# Need to revisit this for FVP_R
|
||||
FVP_R_DT_PREFIX := fvp-base-gicv3-psci
|
||||
|
||||
|
@ -76,10 +79,20 @@ BL1_SOURCES += drivers/arm/sp805/sp805.c \
|
|||
drivers/io/io_semihosting.c \
|
||||
lib/semihosting/semihosting.c \
|
||||
lib/semihosting/${ARCH}/semihosting_call.S \
|
||||
plat/arm/board/fvp_r/fvp_r_helpers.S \
|
||||
plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c \
|
||||
plat/arm/board/fvp_r/fvp_r_bl1_setup.c \
|
||||
plat/arm/board/fvp_r/fvp_r_context_mgmt.c \
|
||||
plat/arm/board/fvp_r/fvp_r_err.c \
|
||||
plat/arm/board/fvp_r/fvp_r_io_storage.c \
|
||||
plat/arm/board/fvp_r/fvp_r_bl1_context_mgmt.c \
|
||||
plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S \
|
||||
plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S \
|
||||
plat/arm/board/fvp_r/fvp_r_bl1_main.c \
|
||||
plat/arm/board/fvp_r/fvp_r_context.S \
|
||||
plat/arm/board/fvp_r/fvp_r_debug.S \
|
||||
plat/arm/board/fvp_r/fvp_r_helpers.S \
|
||||
plat/arm/board/fvp_r/fvp_r_misc_helpers.S \
|
||||
plat/arm/board/fvp_r/fvp_r_pauth_helpers.S \
|
||||
${FVP_R_CPU_LIBS} \
|
||||
${FVP_R_INTERCONNECT_SOURCES}
|
||||
|
||||
|
@ -96,9 +109,7 @@ ifneq (${ENABLE_STACK_PROTECTOR},0)
|
|||
PLAT_BL_COMMON_SOURCES += plat/arm/board/fvp_r/fvp_r_stack_protector.c
|
||||
endif
|
||||
|
||||
ifeq (${ARCH},aarch32)
|
||||
NEED_BL32 := yes
|
||||
endif
|
||||
NEED_BL32 := no
|
||||
|
||||
ifneq (${BL2_AT_EL3}, 0)
|
||||
override BL1_SOURCES =
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -22,9 +22,11 @@
|
|||
#pragma weak bl1_early_platform_setup
|
||||
#pragma weak bl1_plat_arch_setup
|
||||
#pragma weak bl1_plat_sec_mem_layout
|
||||
#pragma weak arm_bl1_early_platform_setup
|
||||
#pragma weak bl1_plat_prepare_exit
|
||||
#pragma weak bl1_plat_get_next_image_id
|
||||
#pragma weak plat_arm_bl1_fwu_needed
|
||||
#pragma weak arm_bl1_plat_arch_setup
|
||||
|
||||
#define MAP_BL1_TOTAL MAP_REGION_FLAT( \
|
||||
bl1_tzram_layout.total_base, \
|
||||
|
|
|
@ -206,12 +206,16 @@ PLAT_BL_COMMON_SOURCES += plat/arm/common/${ARCH}/arm_helpers.S \
|
|||
plat/arm/common/arm_console.c
|
||||
|
||||
ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1)
|
||||
PLAT_BL_COMMON_SOURCES += lib/xlat_tables/xlat_tables_common.c \
|
||||
PLAT_BL_COMMON_SOURCES += lib/xlat_tables/xlat_tables_common.c \
|
||||
lib/xlat_tables/${ARCH}/xlat_tables.c
|
||||
else
|
||||
ifeq (${XLAT_MPU_LIB_V1}, 1)
|
||||
include lib/xlat_mpu/xlat_mpu.mk
|
||||
PLAT_BL_COMMON_SOURCES += ${XLAT_MPU_LIB_V1_SRCS}
|
||||
else
|
||||
include lib/xlat_tables_v2/xlat_tables.mk
|
||||
|
||||
PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS}
|
||||
PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS}
|
||||
endif
|
||||
endif
|
||||
|
||||
ARM_IO_SOURCES += plat/arm/common/arm_io_storage.c \
|
||||
|
@ -351,7 +355,7 @@ ifneq (${TRUSTED_BOARD_BOOT},0)
|
|||
|
||||
# Include the selected chain of trust sources.
|
||||
ifeq (${COT},tbbr)
|
||||
BL1_SOURCES += drivers/auth/tbbr/tbbr_cot_common.c \
|
||||
BL1_SOURCES += drivers/auth/tbbr/tbbr_cot_common.c \
|
||||
drivers/auth/tbbr/tbbr_cot_bl1.c
|
||||
ifneq (${COT_DESC_IN_DTB},0)
|
||||
BL2_SOURCES += lib/fconf/fconf_cot_getter.c
|
||||
|
|
Loading…
Add table
Reference in a new issue