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
diff --git a/bl1/bl1.mk b/bl1/bl1.mk
index d11b4ab..8f44151 100644
--- a/bl1/bl1.mk
+++ b/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 \
diff --git a/docs/components/xlat-tables-lib-v2-design.rst b/docs/components/xlat-tables-lib-v2-design.rst
index af5151f..cac32f5 100644
--- a/docs/components/xlat-tables-lib-v2-design.rst
+++ b/docs/components/xlat-tables-lib-v2-design.rst
@@ -10,7 +10,7 @@
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 @@
#. 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 @@
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 @@
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 @@
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 @@
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 @@
--------------
-*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
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index d260ecf..1b3ae02 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -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)
diff --git a/include/arch/aarch64/el2_common_macros.S b/include/arch/aarch64/el2_common_macros.S
new file mode 100644
index 0000000..c57a1ec
--- /dev/null
+++ b/include/arch/aarch64/el2_common_macros.S
@@ -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 */
diff --git a/include/plat/arm/board/common/v2m_def.h b/include/plat/arm/board/common/v2m_def.h
index 6a6979c..cb11dac 100644
--- a/include/plat/arm/board/common/v2m_def.h
+++ b/include/plat/arm/board/common/v2m_def.h
@@ -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)
diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h
index 9d47b90..08f7ff9 100644
--- a/include/plat/arm/common/arm_def.h
+++ b/include/plat/arm/common/arm_def.h
@@ -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) */
diff --git a/lib/xlat_mpu/aarch64/enable_mpu.S b/lib/xlat_mpu/aarch64/enable_mpu.S
new file mode 100644
index 0000000..3791f2d
--- /dev/null
+++ b/lib/xlat_mpu/aarch64/enable_mpu.S
@@ -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
diff --git a/lib/xlat_mpu/aarch64/xlat_mpu_arch.c b/lib/xlat_mpu/aarch64/xlat_mpu_arch.c
new file mode 100644
index 0000000..5068eb8
--- /dev/null
+++ b/lib/xlat_mpu/aarch64/xlat_mpu_arch.c
@@ -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;
+}
+
diff --git a/lib/xlat_mpu/ro_xlat_mpu.mk b/lib/xlat_mpu/ro_xlat_mpu.mk
new file mode 100644
index 0000000..23f1d46
--- /dev/null
+++ b/lib/xlat_mpu/ro_xlat_mpu.mk
@@ -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
diff --git a/lib/xlat_mpu/xlat_mpu.h b/lib/xlat_mpu/xlat_mpu.h
new file mode 100644
index 0000000..f46805a
--- /dev/null
+++ b/lib/xlat_mpu/xlat_mpu.h
@@ -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 */
diff --git a/lib/xlat_mpu/xlat_mpu.mk b/lib/xlat_mpu/xlat_mpu.mk
new file mode 100644
index 0000000..041b91c
--- /dev/null
+++ b/lib/xlat_mpu/xlat_mpu.mk
@@ -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
diff --git a/lib/xlat_mpu/xlat_mpu_context.c b/lib/xlat_mpu/xlat_mpu_context.c
new file mode 100644
index 0000000..7cb19db
--- /dev/null
+++ b/lib/xlat_mpu/xlat_mpu_context.c
@@ -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);
+}
diff --git a/lib/xlat_mpu/xlat_mpu_core.c b/lib/xlat_mpu/xlat_mpu_core.c
new file mode 100644
index 0000000..6b4b0c2
--- /dev/null
+++ b/lib/xlat_mpu/xlat_mpu_core.c
@@ -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();
+ }
+}
diff --git a/lib/xlat_mpu/xlat_mpu_private.h b/lib/xlat_mpu/xlat_mpu_private.h
new file mode 100644
index 0000000..e0e479d
--- /dev/null
+++ b/lib/xlat_mpu/xlat_mpu_private.h
@@ -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 */
diff --git a/lib/xlat_mpu/xlat_mpu_utils.c b/lib/xlat_mpu/xlat_mpu_utils.c
new file mode 100644
index 0000000..f305632
--- /dev/null
+++ b/lib/xlat_mpu/xlat_mpu_utils.c
@@ -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 */
diff --git a/lib/xlat_tables/aarch64/xlat_tables.c b/lib/xlat_tables/aarch64/xlat_tables.c
index c86412c..dc167e3 100644
--- a/lib/xlat_tables/aarch64/xlat_tables.c
+++ b/lib/xlat_tables/aarch64/xlat_tables.c
@@ -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 @@
* 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; \
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c b/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c
new file mode 100644
index 0000000..ae6af6c
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c
@@ -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);
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_context_mgmt.c b/plat/arm/board/fvp_r/fvp_r_bl1_context_mgmt.c
new file mode 100644
index 0000000..1a18517
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_context_mgmt.c
@@ -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);
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S b/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S
new file mode 100644
index 0000000..d2e8ac8
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S
@@ -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
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S b/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S
new file mode 100644
index 0000000..43c2e01
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S
@@ -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.
+ * -----------------------------------------------------
+ */
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_main.c b/plat/arm/board/fvp_r/fvp_r_bl1_main.c
new file mode 100644
index 0000000..b13ce9f
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_main.c
@@ -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
+
diff --git a/plat/arm/board/fvp_r/fvp_r_bl1_setup.c b/plat/arm/board/fvp_r/fvp_r_bl1_setup.c
index 91709d8..c6fb25f 100644
--- a/plat/arm/board/fvp_r/fvp_r_bl1_setup.c
+++ b/plat/arm/board/fvp_r/fvp_r_bl1_setup.c
@@ -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 @@
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);
diff --git a/plat/arm/board/fvp_r/fvp_r_common.c b/plat/arm/board/fvp_r/fvp_r_common.c
index 693a6d7..a9316a1 100644
--- a/plat/arm/board/fvp_r/fvp_r_common.c
+++ b/plat/arm/board/fvp_r/fvp_r_common.c
@@ -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 @@
******************************************************************************/
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
diff --git a/plat/arm/board/fvp_r/fvp_r_context.S b/plat/arm/board/fvp_r/fvp_r_context.S
new file mode 100644
index 0000000..2746c2e
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_context.S
@@ -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
diff --git a/plat/arm/board/fvp_r/fvp_r_context_mgmt.c b/plat/arm/board/fvp_r/fvp_r_context_mgmt.c
new file mode 100644
index 0000000..678b879
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_context_mgmt.c
@@ -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);
+}
diff --git a/plat/arm/board/fvp_r/fvp_r_debug.S b/plat/arm/board/fvp_r/fvp_r_debug.S
new file mode 100644
index 0000000..8db1b09
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_debug.S
@@ -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
diff --git a/plat/arm/board/fvp_r/fvp_r_def.h b/plat/arm/board/fvp_r/fvp_r_def.h
index 587832f..b9f6989 100644
--- a/plat/arm/board/fvp_r/fvp_r_def.h
+++ b/plat/arm/board/fvp_r/fvp_r_def.h
@@ -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))
diff --git a/plat/arm/board/fvp_r/fvp_r_misc_helpers.S b/plat/arm/board/fvp_r/fvp_r_misc_helpers.S
new file mode 100644
index 0000000..67ad164
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_misc_helpers.S
@@ -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
diff --git a/plat/arm/board/fvp_r/fvp_r_pauth_helpers.S b/plat/arm/board/fvp_r/fvp_r_pauth_helpers.S
new file mode 100644
index 0000000..7e6bc3d
--- /dev/null
+++ b/plat/arm/board/fvp_r/fvp_r_pauth_helpers.S
@@ -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
diff --git a/plat/arm/board/fvp_r/fvp_r_stack_protector.c b/plat/arm/board/fvp_r/fvp_r_stack_protector.c
index 5922a98..69b6312 100644
--- a/plat/arm/board/fvp_r/fvp_r_stack_protector.c
+++ b/plat/arm/board/fvp_r/fvp_r_stack_protector.c
@@ -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)
diff --git a/plat/arm/board/fvp_r/fvp_r_trusted_boot.c b/plat/arm/board/fvp_r/fvp_r_trusted_boot.c
index f304e3e..de0b28f 100644
--- a/plat/arm/board/fvp_r/fvp_r_trusted_boot.c
+++ b/plat/arm/board/fvp_r/fvp_r_trusted_boot.c
@@ -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,
diff --git a/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h b/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h
new file mode 100644
index 0000000..92bf484
--- /dev/null
+++ b/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h
@@ -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 */
diff --git a/plat/arm/board/fvp_r/include/platform_def.h b/plat/arm/board/fvp_r/include/platform_def.h
index 4586681..725d131 100644
--- a/plat/arm/board/fvp_r/include/platform_def.h
+++ b/plat/arm/board/fvp_r/include/platform_def.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 */
diff --git a/plat/arm/board/fvp_r/platform.mk b/plat/arm/board/fvp_r/platform.mk
index 1387ae7..a755432 100644
--- a/plat/arm/board/fvp_r/platform.mk
+++ b/plat/arm/board/fvp_r/platform.mk
@@ -22,6 +22,9 @@
# 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 @@
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 @@
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 =
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index 4b2a062..dd8f13b 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -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, \
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 58060db..4304db4 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -206,12 +206,16 @@
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 @@
# 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