Merge pull request #1450 from MISL-EBU-System-SW/marvell-support-v6
Marvell support for Armada 8K SoC family
diff --git a/Makefile b/Makefile
index f230f4a..533cb8a 100644
--- a/Makefile
+++ b/Makefile
@@ -85,7 +85,13 @@
ifneq (${DEBUG}, 0)
BUILD_TYPE := debug
TF_CFLAGS += -g
- ASFLAGS += -g -Wa,--gdwarf-2
+
+ ifneq ($(findstring clang,$(notdir $(CC))),)
+ ASFLAGS += -g
+ else
+ ASFLAGS += -g -Wa,--gdwarf-2
+ endif
+
# Use LOG_LEVEL_INFO by default for debug builds
LOG_LEVEL := 40
else
@@ -119,7 +125,7 @@
CPP := ${CROSS_COMPILE}cpp
AS := ${CROSS_COMPILE}gcc
AR := ${CROSS_COMPILE}ar
-LD := ${CROSS_COMPILE}ld
+LINKER := ${CROSS_COMPILE}ld
OC := ${CROSS_COMPILE}objcopy
OD := ${CROSS_COMPILE}objdump
NM := ${CROSS_COMPILE}nm
@@ -128,8 +134,8 @@
# Use ${LD}.bfd instead if it exists (as absolute path or together with $PATH).
ifneq ($(strip $(wildcard ${LD}.bfd) \
- $(foreach dir,$(subst :, ,${PATH}),$(wildcard ${dir}/${LD}.bfd))),)
-LD := ${LD}.bfd
+ $(foreach dir,$(subst :, ,${PATH}),$(wildcard ${dir}/${LINKER}.bfd))),)
+LINKER := ${LINKER}.bfd
endif
ifeq (${ARM_ARCH_MAJOR},7)
@@ -143,14 +149,24 @@
ifeq ($(notdir $(CC)),armclang)
TF_CFLAGS_aarch32 = -target arm-arm-none-eabi $(march32-directive)
TF_CFLAGS_aarch64 = -target aarch64-arm-none-eabi -march=armv8-a
+LD = $(LINKER)
+AS = $(CC) -c -x assembler-with-cpp $(TF_CFLAGS_$(ARCH))
+CPP = $(CC) -E $(TF_CFLAGS_$(ARCH))
+PP = $(CC) -E $(TF_CFLAGS_$(ARCH))
else ifneq ($(findstring clang,$(notdir $(CC))),)
TF_CFLAGS_aarch32 = $(target32-directive)
TF_CFLAGS_aarch64 = -target aarch64-elf
+LD = $(LINKER)
+AS = $(CC) -c -x assembler-with-cpp $(TF_CFLAGS_$(ARCH))
+CPP = $(CC) -E
+PP = $(CC) -E
else
TF_CFLAGS_aarch32 = $(march32-directive)
TF_CFLAGS_aarch64 = -march=armv8-a
+LD = $(LINKER)
endif
+TF_CFLAGS_aarch32 += -mno-unaligned-access
TF_CFLAGS_aarch64 += -mgeneral-regs-only -mstrict-align
ASFLAGS_aarch32 = $(march32-directive)
diff --git a/bl1/aarch64/bl1_exceptions.S b/bl1/aarch64/bl1_exceptions.S
index 7ac028a..cf8a6a7 100644
--- a/bl1/aarch64/bl1_exceptions.S
+++ b/bl1/aarch64/bl1_exceptions.S
@@ -26,25 +26,25 @@
mov x0, #SYNC_EXCEPTION_SP_EL0
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SynchronousExceptionSP0
+end_vector_entry SynchronousExceptionSP0
vector_entry IrqSP0
mov x0, #IRQ_SP_EL0
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size IrqSP0
+end_vector_entry IrqSP0
vector_entry FiqSP0
mov x0, #FIQ_SP_EL0
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size FiqSP0
+end_vector_entry FiqSP0
vector_entry SErrorSP0
mov x0, #SERROR_SP_EL0
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SErrorSP0
+end_vector_entry SErrorSP0
/* -----------------------------------------------------
* Current EL with SPx: 0x200 - 0x400
@@ -54,25 +54,25 @@
mov x0, #SYNC_EXCEPTION_SP_ELX
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SynchronousExceptionSPx
+end_vector_entry SynchronousExceptionSPx
vector_entry IrqSPx
mov x0, #IRQ_SP_ELX
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size IrqSPx
+end_vector_entry IrqSPx
vector_entry FiqSPx
mov x0, #FIQ_SP_ELX
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size FiqSPx
+end_vector_entry FiqSPx
vector_entry SErrorSPx
mov x0, #SERROR_SP_ELX
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SErrorSPx
+end_vector_entry SErrorSPx
/* -----------------------------------------------------
* Lower EL using AArch64 : 0x400 - 0x600
@@ -91,25 +91,25 @@
b.ne unexpected_sync_exception
b smc_handler64
- check_vector_size SynchronousExceptionA64
+end_vector_entry SynchronousExceptionA64
vector_entry IrqA64
mov x0, #IRQ_AARCH64
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size IrqA64
+end_vector_entry IrqA64
vector_entry FiqA64
mov x0, #FIQ_AARCH64
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size FiqA64
+end_vector_entry FiqA64
vector_entry SErrorA64
mov x0, #SERROR_AARCH64
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SErrorA64
+end_vector_entry SErrorA64
/* -----------------------------------------------------
* Lower EL using AArch32 : 0x600 - 0x800
@@ -119,25 +119,25 @@
mov x0, #SYNC_EXCEPTION_AARCH32
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SynchronousExceptionA32
+end_vector_entry SynchronousExceptionA32
vector_entry IrqA32
mov x0, #IRQ_AARCH32
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size IrqA32
+end_vector_entry IrqA32
vector_entry FiqA32
mov x0, #FIQ_AARCH32
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size FiqA32
+end_vector_entry FiqA32
vector_entry SErrorA32
mov x0, #SERROR_AARCH32
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SErrorA32
+end_vector_entry SErrorA32
func smc_handler64
diff --git a/bl1/bl1.ld.S b/bl1/bl1.ld.S
index 26c0ae4..fabe3ef 100644
--- a/bl1/bl1.ld.S
+++ b/bl1/bl1.ld.S
@@ -28,10 +28,19 @@
*bl1_entrypoint.o(.text*)
*(.text*)
*(.vectors)
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__TEXT_END__ = .;
} >ROM
+ /* .ARM.extab and .ARM.exidx are only added because Clang need them */
+ .ARM.extab . : {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } >ROM
+
+ .ARM.exidx . : {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ } >ROM
+
.rodata . : {
__RODATA_START__ = .;
*(.rodata*)
@@ -152,7 +161,7 @@
* as device memory. No other unexpected data must creep in.
* Ensure the rest of the current memory page is unused.
*/
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__COHERENT_RAM_END__ = .;
} >RAM
#endif
diff --git a/bl1/bl1_main.c b/bl1/bl1_main.c
index 64b363c..047cd6f 100644
--- a/bl1/bl1_main.c
+++ b/bl1/bl1_main.c
@@ -74,8 +74,8 @@
* populates a new memory layout for BL2 that ensures that BL1's data sections
* resident in secure RAM are not visible to BL2.
******************************************************************************/
-void bl1_init_bl2_mem_layout(const meminfo_t *bl1_mem_layout,
- meminfo_t *bl2_mem_layout)
+void bl1_init_bl2_mem_layout(const struct meminfo *bl1_mem_layout,
+ struct meminfo *bl2_mem_layout)
{
bl1_calc_bl2_mem_layout(bl1_mem_layout, bl2_mem_layout);
}
diff --git a/bl2/aarch64/bl2_el3_exceptions.S b/bl2/aarch64/bl2_el3_exceptions.S
index 987f6e3..07d1040 100644
--- a/bl2/aarch64/bl2_el3_exceptions.S
+++ b/bl2/aarch64/bl2_el3_exceptions.S
@@ -26,25 +26,25 @@
mov x0, #SYNC_EXCEPTION_SP_EL0
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SynchronousExceptionSP0
+end_vector_entry SynchronousExceptionSP0
vector_entry IrqSP0
mov x0, #IRQ_SP_EL0
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size IrqSP0
+end_vector_entry IrqSP0
vector_entry FiqSP0
mov x0, #FIQ_SP_EL0
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size FiqSP0
+end_vector_entry FiqSP0
vector_entry SErrorSP0
mov x0, #SERROR_SP_EL0
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SErrorSP0
+end_vector_entry SErrorSP0
/* -----------------------------------------------------
* Current EL with SPx: 0x200 - 0x400
@@ -54,25 +54,25 @@
mov x0, #SYNC_EXCEPTION_SP_ELX
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SynchronousExceptionSPx
+end_vector_entry SynchronousExceptionSPx
vector_entry IrqSPx
mov x0, #IRQ_SP_ELX
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size IrqSPx
+end_vector_entry IrqSPx
vector_entry FiqSPx
mov x0, #FIQ_SP_ELX
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size FiqSPx
+end_vector_entry FiqSPx
vector_entry SErrorSPx
mov x0, #SERROR_SP_ELX
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SErrorSPx
+end_vector_entry SErrorSPx
/* -----------------------------------------------------
* Lower EL using AArch64 : 0x400 - 0x600
@@ -82,25 +82,25 @@
mov x0, #SYNC_EXCEPTION_AARCH64
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SynchronousExceptionA64
+end_vector_entry SynchronousExceptionA64
vector_entry IrqA64
mov x0, #IRQ_AARCH64
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size IrqA64
+end_vector_entry IrqA64
vector_entry FiqA64
mov x0, #FIQ_AARCH64
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size FiqA64
+end_vector_entry FiqA64
vector_entry SErrorA64
mov x0, #SERROR_AARCH64
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SErrorA64
+end_vector_entry SErrorA64
/* -----------------------------------------------------
* Lower EL using AArch32 : 0x600 - 0x800
@@ -110,22 +110,22 @@
mov x0, #SYNC_EXCEPTION_AARCH32
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SynchronousExceptionA32
+end_vector_entry SynchronousExceptionA32
vector_entry IrqA32
mov x0, #IRQ_AARCH32
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size IrqA32
+end_vector_entry IrqA32
vector_entry FiqA32
mov x0, #FIQ_AARCH32
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size FiqA32
+end_vector_entry FiqA32
vector_entry SErrorA32
mov x0, #SERROR_AARCH32
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SErrorA32
+end_vector_entry SErrorA32
diff --git a/bl2/bl2.ld.S b/bl2/bl2.ld.S
index 69c22eb..6d26cdb 100644
--- a/bl2/bl2.ld.S
+++ b/bl2/bl2.ld.S
@@ -28,10 +28,19 @@
*bl2_entrypoint.o(.text*)
*(.text*)
*(.vectors)
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__TEXT_END__ = .;
} >RAM
+ /* .ARM.extab and .ARM.exidx are only added because Clang need them */
+ .ARM.extab . : {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } >RAM
+
+ .ARM.exidx . : {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ } >RAM
+
.rodata . : {
__RODATA_START__ = .;
*(.rodata*)
@@ -42,7 +51,7 @@
KEEP(*(.img_parser_lib_descs))
__PARSER_LIB_DESCS_END__ = .;
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__RODATA_END__ = .;
} >RAM
#else
@@ -65,7 +74,7 @@
* read-only, executable. No RW data from the next section must
* creep in. Ensure the rest of the current memory page is unused.
*/
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__RO_END__ = .;
} >RAM
#endif
@@ -131,7 +140,7 @@
* as device memory. No other unexpected data must creep in.
* Ensure the rest of the current memory page is unused.
*/
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__COHERENT_RAM_END__ = .;
} >RAM
#endif
diff --git a/bl2/bl2_el3.ld.S b/bl2/bl2_el3.ld.S
index 0f91edc..82ab427 100644
--- a/bl2/bl2_el3.ld.S
+++ b/bl2/bl2_el3.ld.S
@@ -42,7 +42,7 @@
__TEXT_RESIDENT_END__ = .;
*(.text*)
*(.vectors)
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__TEXT_END__ = .;
#if BL2_IN_XIP_MEM
} >ROM
@@ -69,7 +69,7 @@
KEEP(*(cpu_ops))
__CPU_OPS_END__ = .;
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__RODATA_END__ = .;
#if BL2_IN_XIP_MEM
} >ROM
@@ -111,7 +111,7 @@
* read-only, executable. No RW data from the next section must
* creep in. Ensure the rest of the current memory page is unused.
*/
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__RO_END__ = .;
#if BL2_IN_XIP_MEM
@@ -195,7 +195,7 @@
* as device memory. No other unexpected data must creep in.
* Ensure the rest of the current memory page is unused.
*/
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__COHERENT_RAM_END__ = .;
} >RAM
#endif
diff --git a/bl2u/bl2u.ld.S b/bl2u/bl2u.ld.S
index 7b97758..3db5f89 100644
--- a/bl2u/bl2u.ld.S
+++ b/bl2u/bl2u.ld.S
@@ -28,14 +28,23 @@
*bl2u_entrypoint.o(.text*)
*(.text*)
*(.vectors)
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__TEXT_END__ = .;
} >RAM
+ /* .ARM.extab and .ARM.exidx are only added because Clang need them */
+ .ARM.extab . : {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } >RAM
+
+ .ARM.exidx . : {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ } >RAM
+
.rodata . : {
__RODATA_START__ = .;
*(.rodata*)
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__RODATA_END__ = .;
} >RAM
#else
@@ -52,7 +61,7 @@
* read-only, executable. No RW data from the next section must
* creep in. Ensure the rest of the current memory page is unused.
*/
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__RO_END__ = .;
} >RAM
#endif
@@ -118,7 +127,7 @@
* as device memory. No other unexpected data must creep in.
* Ensure the rest of the current memory page is unused.
*/
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__COHERENT_RAM_END__ = .;
} >RAM
#endif
diff --git a/bl31/aarch64/runtime_exceptions.S b/bl31/aarch64/runtime_exceptions.S
index 346cd3b..12f9f10 100644
--- a/bl31/aarch64/runtime_exceptions.S
+++ b/bl31/aarch64/runtime_exceptions.S
@@ -233,7 +233,7 @@
vector_entry sync_exception_sp_el0
/* We don't expect any synchronous exceptions from EL3 */
b report_unhandled_exception
- check_vector_size sync_exception_sp_el0
+end_vector_entry sync_exception_sp_el0
vector_entry irq_sp_el0
/*
@@ -241,17 +241,17 @@
* error. Loop infinitely.
*/
b report_unhandled_interrupt
- check_vector_size irq_sp_el0
+end_vector_entry irq_sp_el0
vector_entry fiq_sp_el0
b report_unhandled_interrupt
- check_vector_size fiq_sp_el0
+end_vector_entry fiq_sp_el0
vector_entry serror_sp_el0
b report_unhandled_exception
- check_vector_size serror_sp_el0
+end_vector_entry serror_sp_el0
/* ---------------------------------------------------------------------
* Current EL with SP_ELx: 0x200 - 0x400
@@ -265,19 +265,19 @@
* corrupted.
*/
b report_unhandled_exception
- check_vector_size sync_exception_sp_elx
+end_vector_entry sync_exception_sp_elx
vector_entry irq_sp_elx
b report_unhandled_interrupt
- check_vector_size irq_sp_elx
+end_vector_entry irq_sp_elx
vector_entry fiq_sp_elx
b report_unhandled_interrupt
- check_vector_size fiq_sp_elx
+end_vector_entry fiq_sp_elx
vector_entry serror_sp_elx
b report_unhandled_exception
- check_vector_size serror_sp_elx
+end_vector_entry serror_sp_elx
/* ---------------------------------------------------------------------
* Lower EL using AArch64 : 0x400 - 0x600
@@ -292,17 +292,17 @@
*/
check_and_unmask_ea
handle_sync_exception
- check_vector_size sync_exception_aarch64
+end_vector_entry sync_exception_aarch64
vector_entry irq_aarch64
check_and_unmask_ea
handle_interrupt_exception irq_aarch64
- check_vector_size irq_aarch64
+end_vector_entry irq_aarch64
vector_entry fiq_aarch64
check_and_unmask_ea
handle_interrupt_exception fiq_aarch64
- check_vector_size fiq_aarch64
+end_vector_entry fiq_aarch64
vector_entry serror_aarch64
msr daifclr, #DAIF_ABT_BIT
@@ -313,7 +313,7 @@
*/
str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
handle_ea #ERROR_EA_ASYNC
- check_vector_size serror_aarch64
+end_vector_entry serror_aarch64
/* ---------------------------------------------------------------------
* Lower EL using AArch32 : 0x600 - 0x800
@@ -328,17 +328,17 @@
*/
check_and_unmask_ea
handle_sync_exception
- check_vector_size sync_exception_aarch32
+end_vector_entry sync_exception_aarch32
vector_entry irq_aarch32
check_and_unmask_ea
handle_interrupt_exception irq_aarch32
- check_vector_size irq_aarch32
+end_vector_entry irq_aarch32
vector_entry fiq_aarch32
check_and_unmask_ea
handle_interrupt_exception fiq_aarch32
- check_vector_size fiq_aarch32
+end_vector_entry fiq_aarch32
vector_entry serror_aarch32
msr daifclr, #DAIF_ABT_BIT
@@ -349,7 +349,7 @@
*/
str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR]
handle_ea #ERROR_EA_ASYNC
- check_vector_size serror_aarch32
+end_vector_entry serror_aarch32
/* ---------------------------------------------------------------------
diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S
index 59df9b8..66cb3f3 100644
--- a/bl31/bl31.ld.S
+++ b/bl31/bl31.ld.S
@@ -32,7 +32,7 @@
*bl31_entrypoint.o(.text*)
*(.text*)
*(.vectors)
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__TEXT_END__ = .;
} >RAM
@@ -67,7 +67,7 @@
. = ALIGN(8);
#include <pubsub_events.h>
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__RODATA_END__ = .;
} >RAM
#else
@@ -111,7 +111,7 @@
* executable. No RW data from the next section must creep in.
* Ensure the rest of the current memory page is unused.
*/
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__RO_END__ = .;
} >RAM
#endif
@@ -131,7 +131,7 @@
spm_shim_exceptions : ALIGN(PAGE_SIZE) {
__SPM_SHIM_EXCEPTIONS_START__ = .;
*(.spm_shim_exceptions)
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__SPM_SHIM_EXCEPTIONS_END__ = .;
} >RAM
#endif
@@ -246,7 +246,7 @@
* as device memory. No other unexpected data must creep in.
* Ensure the rest of the current memory page is unused.
*/
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__COHERENT_RAM_END__ = .;
} >RAM
#endif
diff --git a/bl32/sp_min/sp_min.ld.S b/bl32/sp_min/sp_min.ld.S
index 71de883..ce6c954 100644
--- a/bl32/sp_min/sp_min.ld.S
+++ b/bl32/sp_min/sp_min.ld.S
@@ -28,10 +28,19 @@
*entrypoint.o(.text*)
*(.text*)
*(.vectors)
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__TEXT_END__ = .;
} >RAM
+ /* .ARM.extab and .ARM.exidx are only added because Clang need them */
+ .ARM.extab . : {
+ *(.ARM.extab* .gnu.linkonce.armextab.*)
+ } >RAM
+
+ .ARM.exidx . : {
+ *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+ } >RAM
+
.rodata . : {
__RODATA_START__ = .;
*(.rodata*)
@@ -55,7 +64,7 @@
. = ALIGN(8);
#include <pubsub_events.h>
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__RODATA_END__ = .;
} >RAM
#else
@@ -92,7 +101,7 @@
* read-only, executable. No RW data from the next section must
* creep in. Ensure the rest of the current memory block is unused.
*/
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__RO_END__ = .;
} >RAM
#endif
@@ -207,7 +216,7 @@
* as device memory. No other unexpected data must creep in.
* Ensure the rest of the current memory page is unused.
*/
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__COHERENT_RAM_END__ = .;
} >RAM
diff --git a/bl32/sp_min/sp_min_main.c b/bl32/sp_min/sp_min_main.c
index 8e891b7..f06a48b 100644
--- a/bl32/sp_min/sp_min_main.c
+++ b/bl32/sp_min/sp_min_main.c
@@ -20,6 +20,7 @@
#include <smccc_helpers.h>
#include <stddef.h>
#include <stdint.h>
+#include <std_svc.h>
#include <string.h>
#include <types.h>
#include <utils.h>
diff --git a/bl32/tsp/aarch64/tsp_exceptions.S b/bl32/tsp/aarch64/tsp_exceptions.S
index 4b2ad75..48e358a 100644
--- a/bl32/tsp/aarch64/tsp_exceptions.S
+++ b/bl32/tsp/aarch64/tsp_exceptions.S
@@ -82,19 +82,19 @@
*/
vector_entry sync_exception_sp_el0
b plat_panic_handler
- check_vector_size sync_exception_sp_el0
+end_vector_entry sync_exception_sp_el0
vector_entry irq_sp_el0
b plat_panic_handler
- check_vector_size irq_sp_el0
+end_vector_entry irq_sp_el0
vector_entry fiq_sp_el0
b plat_panic_handler
- check_vector_size fiq_sp_el0
+end_vector_entry fiq_sp_el0
vector_entry serror_sp_el0
b plat_panic_handler
- check_vector_size serror_sp_el0
+end_vector_entry serror_sp_el0
/* -----------------------------------------------------
@@ -104,19 +104,19 @@
*/
vector_entry sync_exception_sp_elx
b plat_panic_handler
- check_vector_size sync_exception_sp_elx
+end_vector_entry sync_exception_sp_elx
vector_entry irq_sp_elx
handle_tsp_interrupt irq_sp_elx
- check_vector_size irq_sp_elx
+end_vector_entry irq_sp_elx
vector_entry fiq_sp_elx
handle_tsp_interrupt fiq_sp_elx
- check_vector_size fiq_sp_elx
+end_vector_entry fiq_sp_elx
vector_entry serror_sp_elx
b plat_panic_handler
- check_vector_size serror_sp_elx
+end_vector_entry serror_sp_elx
/* -----------------------------------------------------
@@ -126,19 +126,19 @@
*/
vector_entry sync_exception_aarch64
b plat_panic_handler
- check_vector_size sync_exception_aarch64
+end_vector_entry sync_exception_aarch64
vector_entry irq_aarch64
b plat_panic_handler
- check_vector_size irq_aarch64
+end_vector_entry irq_aarch64
vector_entry fiq_aarch64
b plat_panic_handler
- check_vector_size fiq_aarch64
+end_vector_entry fiq_aarch64
vector_entry serror_aarch64
b plat_panic_handler
- check_vector_size serror_aarch64
+end_vector_entry serror_aarch64
/* -----------------------------------------------------
@@ -148,16 +148,16 @@
*/
vector_entry sync_exception_aarch32
b plat_panic_handler
- check_vector_size sync_exception_aarch32
+end_vector_entry sync_exception_aarch32
vector_entry irq_aarch32
b plat_panic_handler
- check_vector_size irq_aarch32
+end_vector_entry irq_aarch32
vector_entry fiq_aarch32
b plat_panic_handler
- check_vector_size fiq_aarch32
+end_vector_entry fiq_aarch32
vector_entry serror_aarch32
b plat_panic_handler
- check_vector_size serror_aarch32
+end_vector_entry serror_aarch32
diff --git a/bl32/tsp/tsp.ld.S b/bl32/tsp/tsp.ld.S
index 31c5a67..97b12ce 100644
--- a/bl32/tsp/tsp.ld.S
+++ b/bl32/tsp/tsp.ld.S
@@ -29,14 +29,14 @@
*tsp_entrypoint.o(.text*)
*(.text*)
*(.vectors)
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__TEXT_END__ = .;
} >RAM
.rodata . : {
__RODATA_START__ = .;
*(.rodata*)
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__RODATA_END__ = .;
} >RAM
#else
@@ -52,7 +52,7 @@
* read-only, executable. No RW data from the next section must
* creep in. Ensure the rest of the current memory page is unused.
*/
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__RO_END__ = .;
} >RAM
#endif
@@ -117,7 +117,7 @@
* as device memory. No other unexpected data must creep in.
* Ensure the rest of the current memory page is unused.
*/
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__COHERENT_RAM_END__ = .;
} >RAM
#endif
diff --git a/common/aarch64/early_exceptions.S b/common/aarch64/early_exceptions.S
index 19cc35d..ba94f6c 100644
--- a/common/aarch64/early_exceptions.S
+++ b/common/aarch64/early_exceptions.S
@@ -24,25 +24,25 @@
mov x0, #SYNC_EXCEPTION_SP_EL0
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SynchronousExceptionSP0
+end_vector_entry SynchronousExceptionSP0
vector_entry IrqSP0
mov x0, #IRQ_SP_EL0
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size IrqSP0
+end_vector_entry IrqSP0
vector_entry FiqSP0
mov x0, #FIQ_SP_EL0
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size FiqSP0
+end_vector_entry FiqSP0
vector_entry SErrorSP0
mov x0, #SERROR_SP_EL0
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SErrorSP0
+end_vector_entry SErrorSP0
/* -----------------------------------------------------
* Current EL with SPx: 0x200 - 0x400
@@ -52,25 +52,25 @@
mov x0, #SYNC_EXCEPTION_SP_ELX
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SynchronousExceptionSPx
+end_vector_entry SynchronousExceptionSPx
vector_entry IrqSPx
mov x0, #IRQ_SP_ELX
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size IrqSPx
+end_vector_entry IrqSPx
vector_entry FiqSPx
mov x0, #FIQ_SP_ELX
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size FiqSPx
+end_vector_entry FiqSPx
vector_entry SErrorSPx
mov x0, #SERROR_SP_ELX
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SErrorSPx
+end_vector_entry SErrorSPx
/* -----------------------------------------------------
* Lower EL using AArch64 : 0x400 - 0x600
@@ -80,25 +80,25 @@
mov x0, #SYNC_EXCEPTION_AARCH64
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SynchronousExceptionA64
+end_vector_entry SynchronousExceptionA64
vector_entry IrqA64
mov x0, #IRQ_AARCH64
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size IrqA64
+end_vector_entry IrqA64
vector_entry FiqA64
mov x0, #FIQ_AARCH64
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size FiqA64
+end_vector_entry FiqA64
vector_entry SErrorA64
mov x0, #SERROR_AARCH64
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SErrorA64
+end_vector_entry SErrorA64
/* -----------------------------------------------------
* Lower EL using AArch32 : 0x600 - 0x800
@@ -108,22 +108,22 @@
mov x0, #SYNC_EXCEPTION_AARCH32
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SynchronousExceptionA32
+end_vector_entry SynchronousExceptionA32
vector_entry IrqA32
mov x0, #IRQ_AARCH32
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size IrqA32
+end_vector_entry IrqA32
vector_entry FiqA32
mov x0, #FIQ_AARCH32
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size FiqA32
+end_vector_entry FiqA32
vector_entry SErrorA32
mov x0, #SERROR_AARCH32
bl plat_report_exception
no_ret plat_panic_handler
- check_vector_size SErrorA32
+end_vector_entry SErrorA32
diff --git a/docs/plat/allwinner.rst b/docs/plat/allwinner.rst
index a7e84a3..140edf5 100644
--- a/docs/plat/allwinner.rst
+++ b/docs/plat/allwinner.rst
@@ -4,9 +4,11 @@
Trusted Firmware-A (TF-A) implements the EL3 firmware layer for Allwinner
SoCs with ARMv8 cores. Only BL31 is used to provide proper EL3 setup and
PSCI runtime services.
+
U-Boot's SPL acts as a loader, loading both BL31 and BL33 (typically U-Boot).
Loading is done from SD card, eMMC or SPI flash, also via an USB debug
interface (FEL).
+
BL31 lives in SRAM A2, which is documented to be accessible from secure
world only.
@@ -20,10 +22,26 @@
or the environment variable BL31 must contain the binary's path.
See the respective `U-Boot documentation`_ for more details.
-To build:
+To build for machines with an A64 or H5 SoC:
::
make CROSS_COMPILE=aarch64-linux-gnu- PLAT=sun50i_a64 DEBUG=1 bl31
+To build for machines with an H6 SoC:
+
+::
+
+ make CROSS_COMPILE=aarch64-linux-gnu- PLAT=sun50i_h6 DEBUG=1 bl31
+
.. _U-Boot documentation: http://git.denx.de/?p=u-boot.git;f=board/sunxi/README.sunxi64;hb=HEAD
+
+Trusted OS dispatcher
+=====================
+
+One can boot Trusted OS(OP-TEE OS, bl32 image) along side bl31 image on Allwinner A64.
+
+In order to include the 'opteed' dispatcher in the image, pass 'SPD=opteed' on the command line
+while compiling the bl31 image and make sure the loader (SPL) loads the Trusted OS binary to
+the beginning of DRAM (0x40000000).
+
diff --git a/docs/plat/rpi3.rst b/docs/plat/rpi3.rst
index 554c9a1..fbf753b 100644
--- a/docs/plat/rpi3.rst
+++ b/docs/plat/rpi3.rst
@@ -7,8 +7,7 @@
.. contents::
The `Raspberry Pi 3`_ is an inexpensive single-board computer that contains four
-Arm Cortex-A53 cores, which makes it possible to have a port of Trusted
-Firmware-A (TF-A).
+Arm Cortex-A53 cores.
The following instructions explain how to use this port of the TF-A with the
default distribution of `Raspbian`_ because that's the distribution officially
@@ -66,7 +65,7 @@
The file ``armstub8.bin`` contains BL1 and the FIP. It is needed to add padding
between them so that the addresses they are loaded to match the ones specified
-when compiling TF-A.
+when compiling TF-A. This is done automatically by the build system.
The device tree block is loaded by the VideoCore loader from an appropriate
file, but we can specify the address it is loaded to in ``config.txt``.
@@ -101,20 +100,20 @@
0x00000000 +-----------------+
| ROM | BL1
- 0x00010000 +-----------------+
+ 0x00020000 +-----------------+
| FIP |
0x00200000 +-----------------+
| |
| ... |
| |
0x01000000 +-----------------+
- | Kernel |
+ | DTB | (Loaded by the VideoCore)
+-----------------+
| |
| ... |
| |
0x02000000 +-----------------+
- | DTB |
+ | Kernel | (Loaded by the VideoCore)
+-----------------+
| |
| ... |
@@ -123,9 +122,9 @@
| Secure SRAM | BL2, BL31
0x10100000 +-----------------+
| Secure DRAM | BL32 (Secure payload)
- 0x10300000 +-----------------+
- | Non-secure DRAM | BL33
0x11000000 +-----------------+
+ | Non-secure DRAM | BL33
+ +-----------------+
| |
| ... |
| |
@@ -133,10 +132,10 @@
| I/O |
0x40000000 +-----------------+
-The area between **0x10000000** and **0x11000000** has to be protected so that
-the kernel doesn't use it. That is done by adding ``memmap=16M$256M`` to the
-command line passed to the kernel. See the `Setup SD card`_ instructions to see
-how to do it.
+The area between **0x10000000** and **0x11000000** has to be manually protected
+so that the kernel doesn't use it. That is done by adding ``memmap=16M$256M`` to
+the command line passed to the kernel. See the `Setup SD card`_ instructions to
+see how to do it.
The last 16 MiB of DRAM can only be accessed by the VideoCore, that has
different mappings than the Arm cores in which the I/O addresses don't overlap
@@ -159,14 +158,24 @@
in ``Documentation/arm/Booting`` and ``Documentation/arm64/booting.txt``. The
bootstrap should take care of this.
+This port support a direct boot of the Linux kernel from the firmware (as a BL33
+image). Alternatively, U-Boot or other bootloaders may be used.
+
Secondary cores
~~~~~~~~~~~~~~~
+This port of the Trusted Firmware-A supports ``PSCI_CPU_ON``,
+`PSCI_SYSTEM_RESET`` and ``PSCI_SYSTEM_OFF``. The last one doesn't really turn
+the system off, it simply reboots it and asks the VideoCore firmware to keep it
+in a low power mode permanently.
+
The kernel used by `Raspbian`_ doesn't have support for PSCI, so it is needed to
use mailboxes to trap the secondary cores until they are ready to jump to the
kernel. This mailbox is located at a different address in the AArch32 default
kernel than in the AArch64 kernel.
+Kernels with PSCI support can use the PSCI calls instead for a cleaner boot.
+
Also, this port of TF-A has another Trusted Mailbox in Shared BL RAM. During
cold boot, all secondary cores wait in a loop until they are given given an
address to jump to in this Mailbox (``bl31_warm_entrypoint``).
@@ -187,62 +196,61 @@
AArch32 toolchain is needed for the AArch32 bootstrap needed to load a 32-bit
kernel.
-First, clone and compile `Raspberry Pi 3 TF-A bootstrap`_. Choose the one
-needed for the architecture of your kernel.
-
-Then compile TF-A. For a AArch32 kernel, use the following command line:
-
-.. code:: shell
-
- CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \
- RPI3_BL33_IN_AARCH32=1 \
- BL33=../rpi3-arm-tf-bootstrap/aarch32/el2-bootstrap.bin \
- all fip
-
-For a AArch64 kernel, use this other command line:
-
-.. code:: shell
-
- CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \
- BL33=../rpi3-arm-tf-bootstrap/aarch64/el2-bootstrap.bin \
- all fip
-
-Then, join BL1 and the FIP with the following instructions (replace ``release``
-by ``debug`` if you set the build option ``DEBUG=1``):
-
-.. code:: shell
-
- cp build/rpi3/release/bl1.bin bl1.pad.bin
- truncate --size=65536 bl1.pad.bin
- cat bl1.pad.bin build/rpi3/release/fip.bin > armstub8.bin
-
-The resulting file, ``armstub8.bin``, contains BL1 and the FIP in the place they
-need to be for TF-A to boot correctly. Now, follow the instructions in
-`Setup SD card`_.
+The build system concatenates BL1 and the FIP so that the addresses match the
+ones in the memory map. The resulting file is ``armstub8.bin``, located in the
+build folder (e.g. ``build/rpi3/debug/armstub8.bin``). To know how to use this
+file, follow the instructions in `Setup SD card`_.
The following build options are supported:
-- ``PRELOADED_BL33_BASE``: Specially useful because the file ``kernel8.img`` can
- be loaded anywhere by modifying the file ``config.txt``. It doesn't have to
- contain a kernel, it could have any arbitrary payload.
-
-- ``RESET_TO_BL31``: Set to 1 by default. If using a 32-bit kernel like
- `Raspbian`_, the space used by BL1 can overwritten by the kernel when it is
- being loaded. Even when using a AArch64 kernel the region used by
- BL1 isn't protected and the kernel could overwrite it. The space used by BL31
- is reserved by the command line passed to the kernel.
-
- ``RPI3_BL33_IN_AARCH32``: This port can load a AArch64 or AArch32 BL33 image.
By default this option is 0, which means that TF-A will jump to BL33 in EL2
in AArch64 mode. If set to 1, it will jump to BL33 in Hypervisor in AArch32
mode.
+- ``PRELOADED_BL33_BASE``: Used to specify the address of a BL33 binary that has
+ been preloaded by any other system than using the firmware. ``BL33`` isn't
+ needed in the build command line if this option is used. Specially useful
+ because the file ``kernel8.img`` can be loaded anywhere by modifying the file
+ ``config.txt``. It doesn't have to contain a kernel, it could have any
+ arbitrary payload.
+
+- ``RPI3_DIRECT_LINUX_BOOT``: Disabled by default. Set to 1 to enable the direct
+ boot of the Linux kernel from the firmware. Option ``RPI3_PRELOADED_DTB_BASE``
+ is mandatory when the direct Linux kernel boot is used. Options
+ ``PRELOADED_BL33_BASE`` will most likely be needed as well because it is
+ unlikely that the kernel image will fit in the space reserved for BL33 images.
+ This option can be combined with ``RPI3_BL33_IN_AARCH32`` in order to boot a
+ 32-bit kernel. The only thing this option does is to set the arguments in
+ registers x0-x3 or r0-r2 as expected by the kernel.
+
+- ``RPI3_PRELOADED_DTB_BASE``: Auxiliary build option needed when using
+ ``RPI3_DIRECT_LINUX_BOOT=1``. This option allows to specify the location of a
+ DTB in memory.
+
- ``BL32``: This port can load and run OP-TEE. The OP-TEE image is optional.
Please use the code from `here <https://github.com/OP-TEE/optee_os>`__.
Build the Trusted Firmware with option ``BL32=tee-header_v2.bin
BL32_EXTRA1=tee-pager_v2.bin BL32_EXTRA2=tee-pageable_v2.bin``
to put the binaries into the FIP.
+ Note: If OP-TEE is used it may be needed to add the following options to the
+ Linux command line so that the USB driver doesn't use FIQs:
+ ``dwc_otg.fiq_enable=0 dwc_otg.fiq_fsm_enable=0 dwc_otg.nak_holdoff=0``.
+ This will unfortunately reduce the performance of the USB driver. It is needed
+ when using Raspbian, for example.
+
+- ``TRUSTED_BOARD_BOOT``: This port supports TBB. Set this option to 1 to enable
+ it. In order to use TBB, you might want to set ``GENERATE_COT=1`` to let the
+ contents of the FIP automatically signed by the build process. The ROT key
+ will be generated and output to ``rot_key.pem`` in the build directory. It is
+ able to set ROT_KEY to your own key in PEM format. Also in order to build,
+ you need to clone mbed TLS from `here <https://github.com/ARMmbed/mbedtls>`__.
+ ``MBEDTLS_DIR`` must point at the mbed TLS source directory.
+
+- ``ENABLE_STACK_PROTECTOR``: Disabled by default. It uses the hardware RNG of
+ the board.
+
The following is not currently supported:
- AArch32 for TF-A itself.
@@ -251,13 +259,65 @@
address by changing the file ``armstub8.bin``, so there's no point in using
TF-A in this case.
-- ``LOAD_IMAGE_V2=0``: Only version 2 is supported.
-
- ``MULTI_CONSOLE_API=0``: The multi console API must be enabled. Note that the
crash console uses the internal 16550 driver functions directly in order to be
able to print error messages during early crashes before setting up the
multi console API.
+Building the firmware for kernels that don't support PSCI
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+This is the case for the 32-bit image of Raspbian, for example. 64-bit kernels
+always support PSCI, but they may not know that the system understands PSCI due
+to an incorrect DTB file.
+
+First, clone and compile the 32-bit version of the `Raspberry Pi 3 TF-A
+bootstrap`_. Choose the one needed for the architecture of your kernel.
+
+Then compile TF-A. For a 32-bit kernel, use the following command line:
+
+.. code:: shell
+
+ CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \
+ RPI3_BL33_IN_AARCH32=1 \
+ BL33=../rpi3-arm-tf-bootstrap/aarch32/el2-bootstrap.bin
+
+For a 64-bit kernel, use this other command line:
+
+.. code:: shell
+
+ CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \
+ BL33=../rpi3-arm-tf-bootstrap/aarch64/el2-bootstrap.bin
+
+However, enabling PSCI support in a 64-bit kernel is really easy. In the
+repository `Raspberry Pi 3 TF-A bootstrap`_ there is a patch that can be applied
+to the Linux kernel tree maintained by the Raspberry Pi foundation. It modifes
+the DTS to tell the kernel to use PSCI. Once this patch is applied, follow the
+instructions in `AArch64 kernel build instructions`_ to get a working 64-bit
+kernel image and supporting files.
+
+Building the firmware for kernels that support PSCI
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For a 64-bit kernel:
+
+.. code:: shell
+
+ CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \
+ PRELOADED_BL33_BASE=0x02000000 \
+ RPI3_PRELOADED_DTB_BASE=0x01000000 \
+ RPI3_DIRECT_LINUX_BOOT=1
+
+For a 32-bit kernel:
+
+.. code:: shell
+
+ CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \
+ PRELOADED_BL33_BASE=0x02000000 \
+ RPI3_PRELOADED_DTB_BASE=0x01000000 \
+ RPI3_DIRECT_LINUX_BOOT=1 \
+ RPI3_BL33_IN_AARCH32=1
+
AArch64 kernel build instructions
---------------------------------
@@ -274,7 +334,7 @@
.. code:: shell
- git clone --depth=1 -b rpi-4.14.y https://github.com/raspberrypi/linux
+ git clone --depth=1 -b rpi-4.18.y https://github.com/raspberrypi/linux
cd linux
2. Configure and compile the kernel. Adapt the number after ``-j`` so that it is
@@ -294,6 +354,7 @@
cp arch/arm64/boot/Image /path/to/boot/kernel8.img
cp arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dtb /path/to/boot/
+ cp arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b-plus.dtb /path/to/boot/
4. Install the kernel modules. Replace the path by the corresponding path to the
filesystem partition of the SD card on your computer.
@@ -337,8 +398,8 @@
::
enable_uart=1
- kernel_address=0x01000000
- device_tree_address=0x02000000
+ kernel_address=0x02000000
+ device_tree_address=0x01000000
If you connect a serial cable to the Mini UART and your computer, and connect
to it (for example, with ``screen /dev/ttyUSB0 115200``) you should see some
diff --git a/docs/user-guide.rst b/docs/user-guide.rst
index 68a74ed..da26026 100644
--- a/docs/user-guide.rst
+++ b/docs/user-guide.rst
@@ -52,7 +52,7 @@
::
- sudo apt-get install build-essential gcc make git libssl-dev
+ sudo apt-get install device-tree-compiler build-essential gcc make git libssl-dev
TF-A has been tested with `Linaro Release 17.10`_.
@@ -62,8 +62,8 @@
guidance and a script, which can be used to download Linaro deliverables
automatically.
-Optionally, TF-A can be built using clang or Arm Compiler 6.
-See instructions below on how to switch the default compiler.
+Optionally, TF-A can be built using clang version 4.0 or newer or Arm
+Compiler 6. See instructions below on how to switch the default compiler.
In addition, the following optional packages and tools may be needed:
@@ -103,10 +103,14 @@
export CROSS_COMPILE=<path-to-aarch32-gcc>/bin/arm-linux-gnueabihf-
- It is possible to build TF-A using clang or Arm Compiler 6. To do so
- ``CC`` needs to point to the clang or armclang binary. Only the compiler
- is switched; the assembler and linker need to be provided by the GNU
- toolchain, thus ``CROSS_COMPILE`` should be set as described above.
+ It is possible to build TF-A using Clang or Arm Compiler 6. To do so
+ ``CC`` needs to point to the clang or armclang binary, which will
+ also select the clang or armclang assembler. Be aware that the
+ GNU linker is used by default. In case of being needed the linker
+ can be overriden using the ``LD`` variable. Clang linker version 6 is
+ known to work with TF-A.
+
+ In both cases ``CROSS_COMPILE`` should be set as described above.
Arm Compiler 6 will be selected when the base name of the path assigned
to ``CC`` matches the string 'armclang'.
diff --git a/docs/xlat-tables-lib-v2-design.rst b/docs/xlat-tables-lib-v2-design.rst
index d207f30..f07dfab 100644
--- a/docs/xlat-tables-lib-v2-design.rst
+++ b/docs/xlat-tables-lib-v2-design.rst
@@ -282,31 +282,49 @@
Code structure
~~~~~~~~~~~~~~
-The library is divided into 2 modules:
+The library is divided into 4 modules:
-The core module
- Provides the main functionality of the library.
+- **Core module**
- See `xlat\_tables\_internal.c`_.
+ Provides the main functionality of the library, such as the initialization of
+ translation tables contexts and mapping/unmapping memory regions. This module
+ provides functions such as ``mmap_add_region_ctx`` that let the caller specify
+ the translation tables context affected by them.
-The architectural module
- Provides functions that are dependent on the current execution state
- (AArch32/AArch64), such as the functions used for TLB invalidation or MMU
- setup.
+ See `xlat\_tables\_core.c`_.
- See `aarch32/xlat\_tables\_arch.c`_ and `aarch64/xlat\_tables\_arch.c`_.
+- **Active context module**
-Core module
-~~~~~~~~~~~
+ Instantiates the context that is used by the current BL image and provides
+ helpers to manipulate it, abstracting it from the rest of the code.
+ This module provides functions such as ``mmap_add_region``, that directly
+ affect the BL image using them.
+
+ See `xlat\_tables\_context.c`_.
+
+- **Utilities module**
+
+ Provides additional functionality like debug print of the current state of the
+ translation tables and helpers to query memory attributes and to modify them.
+
+ See `xlat\_tables\_utils.c`_.
+
+- **Architectural module**
+
+ Provides functions that are dependent on the current execution state
+ (AArch32/AArch64), such as the functions used for TLB invalidation, setup the
+ MMU, or calculate the Physical Address Space size. They do not need a
+ translation context to work on.
+
+ See `aarch32/xlat\_tables\_arch.c`_ and `aarch64/xlat\_tables\_arch.c`_.
From mmap regions to translation tables
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-All the APIs in this module work on a translation context. The translation
-context contains the list of ``mmap_region``, which holds the information of all
-the regions that are mapped at any given time. Whenever there is a request to
-map (resp. unmap) a memory region, it is added to (resp. removed from) the
-``mmap_region`` list.
+A translation context contains a list of ``mmap_region_t``, which holds the
+information of all the regions that are mapped at any given time. Whenever there
+is a request to map (resp. unmap) a memory region, it is added to (resp. removed
+from) the ``mmap_region_t`` list.
The mmap regions list is a conceptual way to represent the memory layout. At
some point, the library has to convert this information into actual translation
@@ -326,7 +344,7 @@
will take effect immediately.
The memory mapping algorithm
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The mapping function is implemented as a recursive algorithm. It is however
bound by the level of depth of the translation tables (the Armv8-A architecture
@@ -367,7 +385,7 @@
granularity.
TLB maintenance operations
-^^^^^^^^^^^^^^^^^^^^^^^^^^
+~~~~~~~~~~~~~~~~~~~~~~~~~~
The library takes care of performing TLB maintenance operations when required.
For example, when the user requests removing a dynamic region, the library
@@ -391,17 +409,8 @@
invalid translation table entry [#tlb-no-invalid-entry]_, this means that this
mapping cannot be cached in the TLBs.
-.. [#tlb-reset-ref] See section D4.8 `Translation Lookaside Buffers (TLBs)`, subsection `TLB behavior at reset` in Armv8-A, rev B.a.
-
-.. [#tlb-no-invalid-entry] See section D4.9.1 `General TLB maintenance requirements` in Armv8-A, rev B.a.
-
-Architectural module
-~~~~~~~~~~~~~~~~~~~~
-
-This module contains functions that have different implementations for AArch32
-and AArch64. For example, it provides APIs to perform TLB maintenance operations,
-enable the MMU or calculate the Physical Address Space size. They do not need a
-translation context to work on.
+.. [#tlb-reset-ref] See section D4.9 `Translation Lookaside Buffers (TLBs)`, subsection `TLB behavior at reset` in Armv8-A, rev C.a.
+.. [#tlb-no-invalid-entry] See section D4.10.1 `General TLB maintenance requirements` in Armv8-A, rev C.a.
--------------
@@ -410,7 +419,9 @@
.. _lib/xlat\_tables\_v2: ../lib/xlat_tables_v2
.. _lib/xlat\_tables: ../lib/xlat_tables
.. _xlat\_tables\_v2.h: ../include/lib/xlat_tables/xlat_tables_v2.h
-.. _xlat\_tables\_internal.c: ../lib/xlat_tables_v2/xlat_tables_internal.c
+.. _xlat\_tables\_context.c: ../lib/xlat_tables_v2/xlat_tables_context.c
+.. _xlat\_tables\_core.c: ../lib/xlat_tables_v2/xlat_tables_core.c
+.. _xlat\_tables\_utils.c: ../lib/xlat_tables_v2/xlat_tables_utils.c
.. _aarch32/xlat\_tables\_arch.c: ../lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
.. _aarch64/xlat\_tables\_arch.c: ../lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
.. _Porting Guide: porting-guide.rst
diff --git a/drivers/io/io_fip.c b/drivers/io/io_fip.c
index c5ee6a4..9d6c763 100644
--- a/drivers/io/io_fip.c
+++ b/drivers/io/io_fip.c
@@ -19,6 +19,10 @@
#include <utils.h>
#include <uuid.h>
+#ifndef MAX_FIP_DEVICES
+#define MAX_FIP_DEVICES 1
+#endif
+
/* Useful for printing UUIDs when debugging.*/
#define PRINT_UUID2(x) \
"%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx", \
@@ -32,11 +36,33 @@
fip_toc_entry_t entry;
} file_state_t;
+/*
+ * Maintain dev_spec per FIP Device
+ * TODO - Add backend handles and file state
+ * per FIP device here once backends like io_memmap
+ * can support multiple open files
+ */
+typedef struct {
+ uintptr_t dev_spec;
+} fip_dev_state_t;
+
static const uuid_t uuid_null = { {0} };
+/*
+ * Only one file can be open across all FIP device
+ * as backends like io_memmap don't support
+ * multiple open files. The file state and
+ * backend handle should be maintained per FIP device
+ * if the same support is available in the backend
+ */
static file_state_t current_file = {0};
static uintptr_t backend_dev_handle;
static uintptr_t backend_image_spec;
+static fip_dev_state_t state_pool[MAX_FIP_DEVICES];
+static io_dev_info_t dev_info_pool[MAX_FIP_DEVICES];
+
+/* Track number of allocated fip devices */
+static unsigned int fip_dev_count;
/* Firmware Image Package driver functions */
static int fip_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info);
@@ -92,20 +118,94 @@
.dev_close = fip_dev_close,
};
+/* Locate a file state in the pool, specified by address */
+static int find_first_fip_state(const uintptr_t dev_spec,
+ unsigned int *index_out)
+{
+ int result = -ENOENT;
+ unsigned int index;
-/* No state associated with this device so structure can be const */
-static const io_dev_info_t fip_dev_info = {
- .funcs = &fip_dev_funcs,
- .info = (uintptr_t)NULL
-};
+ for (index = 0; index < (unsigned int)MAX_FIP_DEVICES; ++index) {
+ /* dev_spec is used as identifier since it's unique */
+ if (state_pool[index].dev_spec == dev_spec) {
+ result = 0;
+ *index_out = index;
+ break;
+ }
+ }
+ return result;
+}
-/* Open a connection to the FIP device */
-static int fip_dev_open(const uintptr_t dev_spec __unused,
+/* Allocate a device info from the pool and return a pointer to it */
+static int allocate_dev_info(io_dev_info_t **dev_info)
+{
+ int result = -ENOMEM;
+
+ assert(dev_info != NULL);
+
+ if (fip_dev_count < (unsigned int)MAX_FIP_DEVICES) {
+ unsigned int index = 0;
+
+ result = find_first_fip_state(0, &index);
+ assert(result == 0);
+ /* initialize dev_info */
+ dev_info_pool[index].funcs = &fip_dev_funcs;
+ dev_info_pool[index].info =
+ (uintptr_t)&state_pool[index];
+ *dev_info = &dev_info_pool[index];
+ ++fip_dev_count;
+ }
+
+ return result;
+}
+
+/* Release a device info to the pool */
+static int free_dev_info(io_dev_info_t *dev_info)
+{
+ int result;
+ unsigned int index = 0;
+ fip_dev_state_t *state;
+
+ assert(dev_info != NULL);
+
+ state = (fip_dev_state_t *)dev_info->info;
+ result = find_first_fip_state(state->dev_spec, &index);
+ if (result == 0) {
+ /* free if device info is valid */
+ zeromem(state, sizeof(fip_dev_state_t));
+ --fip_dev_count;
+ }
+
+ return result;
+}
+
+/*
+ * Multiple FIP devices can be opened depending on the value of
+ * MAX_FIP_DEVICES. Given that there is only one backend, only a
+ * single file can be open at a time by any FIP device.
+ */
+static int fip_dev_open(const uintptr_t dev_spec,
io_dev_info_t **dev_info)
{
+ int result;
+ io_dev_info_t *info;
+ fip_dev_state_t *state;
+
assert(dev_info != NULL);
- *dev_info = (io_dev_info_t *)&fip_dev_info; /* cast away const */
+#if MAX_FIP_DEVICES > 1
+ assert(dev_spec != (uintptr_t)NULL);
+#endif
+
+ result = allocate_dev_info(&info);
+ if (result != 0)
+ return -ENOMEM;
+
+ state = (fip_dev_state_t *)info->info;
+
+ state->dev_spec = dev_spec;
+
+ *dev_info = info;
return 0;
}
@@ -165,7 +265,7 @@
backend_dev_handle = (uintptr_t)NULL;
backend_image_spec = (uintptr_t)NULL;
- return 0;
+ return free_dev_info(dev_info);
}
@@ -340,7 +440,11 @@
int result;
assert(dev_con != NULL);
- result = io_register_device(&fip_dev_info);
+ /*
+ * Since dev_info isn't really used in io_register_device, always
+ * use the same device info at here instead.
+ */
+ result = io_register_device(&dev_info_pool[0]);
if (result == 0)
*dev_con = &fip_dev_connector;
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c
new file mode 100644
index 0000000..8fe3239
--- /dev/null
+++ b/drivers/mmc/mmc.c
@@ -0,0 +1,714 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+/* Define a simple and generic interface to access eMMC and SD-card devices. */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <errno.h>
+#include <mmc.h>
+#include <stdbool.h>
+#include <string.h>
+#include <utils.h>
+
+#define MMC_DEFAULT_MAX_RETRIES 5
+#define SEND_OP_COND_MAX_RETRIES 100
+
+#define MULT_BY_512K_SHIFT 19
+
+static const struct mmc_ops *ops;
+static unsigned int mmc_ocr_value;
+static struct mmc_csd_emmc mmc_csd;
+static unsigned char mmc_ext_csd[512] __aligned(4);
+static unsigned int mmc_flags;
+static struct mmc_device_info *mmc_dev_info;
+static unsigned int rca;
+
+static const unsigned char tran_speed_base[16] = {
+ 0, 10, 12, 13, 15, 20, 26, 30, 35, 40, 45, 52, 55, 60, 70, 80
+};
+
+static const unsigned char sd_tran_speed_base[16] = {
+ 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80
+};
+
+static bool is_cmd23_enabled(void)
+{
+ return ((mmc_flags & MMC_FLAG_CMD23) != 0U);
+}
+
+static int mmc_send_cmd(unsigned int idx, unsigned int arg,
+ unsigned int r_type, unsigned int *r_data)
+{
+ struct mmc_cmd cmd;
+ int ret;
+
+ zeromem(&cmd, sizeof(struct mmc_cmd));
+
+ cmd.cmd_idx = idx;
+ cmd.cmd_arg = arg;
+ cmd.resp_type = r_type;
+
+ ret = ops->send_cmd(&cmd);
+
+ if ((ret == 0) && (r_data != NULL)) {
+ int i;
+
+ for (i = 0; i < 4; i++) {
+ *r_data = cmd.resp_data[i];
+ r_data++;
+ }
+ }
+
+ if (ret != 0) {
+ VERBOSE("Send command %u error: %d\n", idx, ret);
+ }
+
+ return ret;
+}
+
+static int mmc_device_state(void)
+{
+ int retries = MMC_DEFAULT_MAX_RETRIES;
+ unsigned int resp_data[4];
+
+ do {
+ int ret;
+
+ if (retries == 0) {
+ ERROR("CMD13 failed after %d retries\n",
+ MMC_DEFAULT_MAX_RETRIES);
+ return -EIO;
+ }
+
+ ret = mmc_send_cmd(MMC_CMD(13), rca << RCA_SHIFT_OFFSET,
+ MMC_RESPONSE_R(1), &resp_data[0]);
+ if (ret != 0) {
+ return ret;
+ }
+
+ if ((resp_data[0] & STATUS_SWITCH_ERROR) != 0U) {
+ return -EIO;
+ }
+
+ retries--;
+ } while ((resp_data[0] & STATUS_READY_FOR_DATA) == 0U);
+
+ return MMC_GET_STATE(resp_data[0]);
+}
+
+static int mmc_set_ext_csd(unsigned int ext_cmd, unsigned int value)
+{
+ int ret;
+
+ ret = mmc_send_cmd(MMC_CMD(6),
+ EXTCSD_WRITE_BYTES | EXTCSD_CMD(ext_cmd) |
+ EXTCSD_VALUE(value) | EXTCSD_CMD_SET_NORMAL,
+ 0, NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ do {
+ ret = mmc_device_state();
+ if (ret < 0) {
+ return ret;
+ }
+ } while (ret == MMC_STATE_PRG);
+
+ return 0;
+}
+
+static int mmc_sd_switch(unsigned int bus_width)
+{
+ int ret;
+ int retries = MMC_DEFAULT_MAX_RETRIES;
+ unsigned int scr[2] = { 0 };
+ unsigned int bus_width_arg = 0;
+
+ ret = ops->prepare(0, (uintptr_t)&scr, sizeof(scr));
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* CMD55: Application Specific Command */
+ ret = mmc_send_cmd(MMC_CMD(55), rca << RCA_SHIFT_OFFSET,
+ MMC_RESPONSE_R(1), NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* ACMD51: SEND_SCR */
+ do {
+ ret = mmc_send_cmd(MMC_ACMD(51), 0, MMC_RESPONSE_R(1), NULL);
+ if ((ret != 0) && (retries == 0)) {
+ ERROR("ACMD51 failed after %d retries (ret=%d)\n",
+ MMC_DEFAULT_MAX_RETRIES, ret);
+ return ret;
+ }
+
+ retries--;
+ } while (ret != 0);
+
+ ret = ops->read(0, (uintptr_t)&scr, sizeof(scr));
+ if (ret != 0) {
+ return ret;
+ }
+
+ if (((scr[0] & SD_SCR_BUS_WIDTH_4) != 0U) &&
+ (bus_width == MMC_BUS_WIDTH_4)) {
+ bus_width_arg = 2;
+ }
+
+ /* CMD55: Application Specific Command */
+ ret = mmc_send_cmd(MMC_CMD(55), rca << RCA_SHIFT_OFFSET,
+ MMC_RESPONSE_R(1), NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* ACMD6: SET_BUS_WIDTH */
+ ret = mmc_send_cmd(MMC_ACMD(6), bus_width_arg, MMC_RESPONSE_R(1), NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ do {
+ ret = mmc_device_state();
+ if (ret < 0) {
+ return ret;
+ }
+ } while (ret == MMC_STATE_PRG);
+
+ return 0;
+}
+
+static int mmc_set_ios(unsigned int clk, unsigned int bus_width)
+{
+ int ret;
+ unsigned int width = bus_width;
+
+ if (mmc_dev_info->mmc_dev_type != MMC_IS_EMMC) {
+ if (width == MMC_BUS_WIDTH_8) {
+ WARN("Wrong bus config for SD-card, force to 4\n");
+ width = MMC_BUS_WIDTH_4;
+ }
+ ret = mmc_sd_switch(width);
+ if (ret != 0) {
+ return ret;
+ }
+ } else if (mmc_csd.spec_vers == 4U) {
+ ret = mmc_set_ext_csd(CMD_EXTCSD_BUS_WIDTH,
+ (unsigned int)width);
+ if (ret != 0) {
+ return ret;
+ }
+ } else {
+ VERBOSE("Wrong MMC type or spec version\n");
+ }
+
+ return ops->set_ios(clk, width);
+}
+
+static int mmc_fill_device_info(void)
+{
+ unsigned long long c_size;
+ unsigned int speed_idx;
+ unsigned int nb_blocks;
+ unsigned int freq_unit;
+ int ret;
+ struct mmc_csd_sd_v2 *csd_sd_v2;
+
+ switch (mmc_dev_info->mmc_dev_type) {
+ case MMC_IS_EMMC:
+ mmc_dev_info->block_size = MMC_BLOCK_SIZE;
+
+ ret = ops->prepare(0, (uintptr_t)&mmc_ext_csd,
+ sizeof(mmc_ext_csd));
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* MMC CMD8: SEND_EXT_CSD */
+ ret = mmc_send_cmd(MMC_CMD(8), 0, MMC_RESPONSE_R(1), NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ ret = ops->read(0, (uintptr_t)&mmc_ext_csd,
+ sizeof(mmc_ext_csd));
+ if (ret != 0) {
+ return ret;
+ }
+
+ nb_blocks = (mmc_ext_csd[CMD_EXTCSD_SEC_CNT] << 0) |
+ (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 1] << 8) |
+ (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 2] << 16) |
+ (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 3] << 24);
+
+ mmc_dev_info->device_size = (unsigned long long)nb_blocks *
+ mmc_dev_info->block_size;
+
+ break;
+
+ case MMC_IS_SD:
+ /*
+ * Use the same mmc_csd struct, as required fields here
+ * (READ_BL_LEN, C_SIZE, CSIZE_MULT) are common with eMMC.
+ */
+ mmc_dev_info->block_size = BIT_32(mmc_csd.read_bl_len);
+
+ c_size = ((unsigned long long)mmc_csd.c_size_high << 2U) |
+ (unsigned long long)mmc_csd.c_size_low;
+ assert(c_size != 0xFFFU);
+
+ mmc_dev_info->device_size = (c_size + 1U) *
+ BIT_64(mmc_csd.c_size_mult + 2U) *
+ mmc_dev_info->block_size;
+
+ break;
+
+ case MMC_IS_SD_HC:
+ assert(mmc_csd.csd_structure == 1U);
+
+ mmc_dev_info->block_size = MMC_BLOCK_SIZE;
+
+ /* Need to use mmc_csd_sd_v2 struct */
+ csd_sd_v2 = (struct mmc_csd_sd_v2 *)&mmc_csd;
+ c_size = ((unsigned long long)csd_sd_v2->c_size_high << 16) |
+ (unsigned long long)csd_sd_v2->c_size_low;
+
+ mmc_dev_info->device_size = (c_size + 1U) << MULT_BY_512K_SHIFT;
+
+ break;
+
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ if (ret != 0) {
+ return ret;
+ }
+
+ speed_idx = (mmc_csd.tran_speed & CSD_TRAN_SPEED_MULT_MASK) >>
+ CSD_TRAN_SPEED_MULT_SHIFT;
+
+ assert(speed_idx > 0U);
+
+ if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) {
+ mmc_dev_info->max_bus_freq = tran_speed_base[speed_idx];
+ } else {
+ mmc_dev_info->max_bus_freq = sd_tran_speed_base[speed_idx];
+ }
+
+ freq_unit = mmc_csd.tran_speed & CSD_TRAN_SPEED_UNIT_MASK;
+ while (freq_unit != 0U) {
+ mmc_dev_info->max_bus_freq *= 10U;
+ --freq_unit;
+ }
+
+ mmc_dev_info->max_bus_freq *= 10000U;
+
+ return 0;
+}
+
+static int sd_send_op_cond(void)
+{
+ int retries = SEND_OP_COND_MAX_RETRIES;
+ unsigned int resp_data[4];
+
+ do {
+ int ret;
+
+ if (retries == 0) {
+ ERROR("ACMD41 failed after %d retries\n",
+ SEND_OP_COND_MAX_RETRIES);
+ return -EIO;
+ }
+
+ /* CMD55: Application Specific Command */
+ ret = mmc_send_cmd(MMC_CMD(55), 0, MMC_RESPONSE_R(1), NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* ACMD41: SD_SEND_OP_COND */
+ ret = mmc_send_cmd(MMC_ACMD(41), OCR_HCS, MMC_RESPONSE_R(3),
+ &resp_data[0]);
+ if (ret != 0) {
+ return ret;
+ }
+
+ retries--;
+ } while ((resp_data[0] & OCR_POWERUP) == 0U);
+
+ mmc_ocr_value = resp_data[0];
+
+ if ((mmc_ocr_value & OCR_HCS) != 0U) {
+ mmc_dev_info->mmc_dev_type = MMC_IS_SD_HC;
+ } else {
+ mmc_dev_info->mmc_dev_type = MMC_IS_SD;
+ }
+
+ return 0;
+}
+
+static int mmc_send_op_cond(void)
+{
+ int ret;
+ int retries = SEND_OP_COND_MAX_RETRIES;
+ unsigned int resp_data[4];
+
+ /* CMD0: reset to IDLE */
+ ret = mmc_send_cmd(MMC_CMD(0), 0, 0, NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ do {
+ if (retries == 0) {
+ ERROR("CMD1 failed after %d retries\n",
+ SEND_OP_COND_MAX_RETRIES);
+ return -EIO;
+ }
+
+ /* CMD1: get OCR register (SEND_OP_COND) */
+ ret = mmc_send_cmd(MMC_CMD(1), OCR_SECTOR_MODE |
+ OCR_VDD_MIN_2V7 | OCR_VDD_MIN_1V7,
+ MMC_RESPONSE_R(3), &resp_data[0]);
+ if (ret != 0) {
+ return ret;
+ }
+
+ retries--;
+ } while ((resp_data[0] & OCR_POWERUP) == 0U);
+
+ mmc_ocr_value = resp_data[0];
+
+ return 0;
+}
+
+static int mmc_enumerate(unsigned int clk, unsigned int bus_width)
+{
+ int ret;
+ unsigned int resp_data[4];
+
+ ops->init();
+
+ /* CMD0: reset to IDLE */
+ ret = mmc_send_cmd(MMC_CMD(0), 0, 0, NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* CMD8: Send Interface Condition Command */
+ ret = mmc_send_cmd(MMC_CMD(8), VHS_2_7_3_6_V | CMD8_CHECK_PATTERN,
+ MMC_RESPONSE_R(7), &resp_data[0]);
+
+ if ((ret == 0) && ((resp_data[0] & 0xffU) == CMD8_CHECK_PATTERN)) {
+ ret = sd_send_op_cond();
+ } else {
+ ret = mmc_send_op_cond();
+ }
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* CMD2: Card Identification */
+ ret = mmc_send_cmd(MMC_CMD(2), 0, MMC_RESPONSE_R(2), NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ /* CMD3: Set Relative Address */
+ if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) {
+ rca = MMC_FIX_RCA;
+ ret = mmc_send_cmd(MMC_CMD(3), rca << RCA_SHIFT_OFFSET,
+ MMC_RESPONSE_R(1), NULL);
+ if (ret != 0) {
+ return ret;
+ }
+ } else {
+ ret = mmc_send_cmd(MMC_CMD(3), 0,
+ MMC_RESPONSE_R(6), &resp_data[0]);
+ if (ret != 0) {
+ return ret;
+ }
+
+ rca = (resp_data[0] & 0xFFFF0000U) >> 16;
+ }
+
+ /* CMD9: CSD Register */
+ ret = mmc_send_cmd(MMC_CMD(9), rca << RCA_SHIFT_OFFSET,
+ MMC_RESPONSE_R(2), &resp_data[0]);
+ if (ret != 0) {
+ return ret;
+ }
+
+ memcpy(&mmc_csd, &resp_data, sizeof(resp_data));
+
+ /* CMD7: Select Card */
+ ret = mmc_send_cmd(MMC_CMD(7), rca << RCA_SHIFT_OFFSET,
+ MMC_RESPONSE_R(1), NULL);
+ if (ret != 0) {
+ return ret;
+ }
+
+ do {
+ ret = mmc_device_state();
+ if (ret < 0) {
+ return ret;
+ }
+ } while (ret != MMC_STATE_TRAN);
+
+ ret = mmc_fill_device_info();
+ if (ret != 0) {
+ return ret;
+ }
+
+ return mmc_set_ios(clk, bus_width);
+}
+
+size_t mmc_read_blocks(unsigned int lba, uintptr_t buf, size_t size)
+{
+ int ret;
+ unsigned int cmd_idx, cmd_arg;
+
+ assert((ops != NULL) &&
+ (ops->read != NULL) &&
+ (size != 0U) &&
+ ((size & MMC_BLOCK_MASK) == 0U));
+
+ ret = ops->prepare(lba, buf, size);
+ if (ret != 0) {
+ return 0;
+ }
+
+ if (is_cmd23_enabled()) {
+ /* Set block count */
+ ret = mmc_send_cmd(MMC_CMD(23), size / MMC_BLOCK_SIZE,
+ MMC_RESPONSE_R(1), NULL);
+ if (ret != 0) {
+ return 0;
+ }
+
+ cmd_idx = MMC_CMD(18);
+ } else {
+ if (size > MMC_BLOCK_SIZE) {
+ cmd_idx = MMC_CMD(18);
+ } else {
+ cmd_idx = MMC_CMD(17);
+ }
+ }
+
+ if (((mmc_ocr_value & OCR_ACCESS_MODE_MASK) == OCR_BYTE_MODE) &&
+ (mmc_dev_info->mmc_dev_type != MMC_IS_SD_HC)) {
+ cmd_arg = lba * MMC_BLOCK_SIZE;
+ } else {
+ cmd_arg = lba;
+ }
+
+ ret = mmc_send_cmd(cmd_idx, cmd_arg, MMC_RESPONSE_R(1), NULL);
+ if (ret != 0) {
+ return 0;
+ }
+
+ ret = ops->read(lba, buf, size);
+ if (ret != 0) {
+ return 0;
+ }
+
+ /* Wait buffer empty */
+ do {
+ ret = mmc_device_state();
+ if (ret < 0) {
+ return 0;
+ }
+ } while ((ret != MMC_STATE_TRAN) && (ret != MMC_STATE_DATA));
+
+ if (!is_cmd23_enabled() && (size > MMC_BLOCK_SIZE)) {
+ ret = mmc_send_cmd(MMC_CMD(12), 0, 0, NULL);
+ if (ret != 0) {
+ return 0;
+ }
+ }
+
+ return size;
+}
+
+size_t mmc_write_blocks(unsigned int lba, const uintptr_t buf, size_t size)
+{
+ int ret;
+ unsigned int cmd_idx, cmd_arg;
+
+ assert((ops != NULL) &&
+ (ops->write != NULL) &&
+ (size != 0U) &&
+ ((buf & MMC_BLOCK_MASK) == 0U) &&
+ ((size & MMC_BLOCK_MASK) == 0U));
+
+ ret = ops->prepare(lba, buf, size);
+ if (ret != 0) {
+ return 0;
+ }
+
+ if (is_cmd23_enabled()) {
+ /* Set block count */
+ ret = mmc_send_cmd(MMC_CMD(23), size / MMC_BLOCK_SIZE,
+ MMC_RESPONSE_R(1), NULL);
+ if (ret != 0) {
+ return 0;
+ }
+
+ cmd_idx = MMC_CMD(25);
+ } else {
+ if (size > MMC_BLOCK_SIZE) {
+ cmd_idx = MMC_CMD(25);
+ } else {
+ cmd_idx = MMC_CMD(24);
+ }
+ }
+
+ if ((mmc_ocr_value & OCR_ACCESS_MODE_MASK) == OCR_BYTE_MODE) {
+ cmd_arg = lba * MMC_BLOCK_SIZE;
+ } else {
+ cmd_arg = lba;
+ }
+
+ ret = mmc_send_cmd(cmd_idx, cmd_arg, MMC_RESPONSE_R(1), NULL);
+ if (ret != 0) {
+ return 0;
+ }
+
+ ret = ops->write(lba, buf, size);
+ if (ret != 0) {
+ return 0;
+ }
+
+ /* Wait buffer empty */
+ do {
+ ret = mmc_device_state();
+ if (ret < 0) {
+ return 0;
+ }
+ } while ((ret != MMC_STATE_TRAN) && (ret != MMC_STATE_RCV));
+
+ if (!is_cmd23_enabled() && (size > MMC_BLOCK_SIZE)) {
+ ret = mmc_send_cmd(MMC_CMD(12), 0, 0, NULL);
+ if (ret != 0) {
+ return 0;
+ }
+ }
+
+ return size;
+}
+
+size_t mmc_erase_blocks(unsigned int lba, size_t size)
+{
+ int ret;
+
+ assert(ops != NULL);
+ assert((size != 0U) && ((size & MMC_BLOCK_MASK) == 0U));
+
+ ret = mmc_send_cmd(MMC_CMD(35), lba, MMC_RESPONSE_R(1), NULL);
+ if (ret != 0) {
+ return 0;
+ }
+
+ ret = mmc_send_cmd(MMC_CMD(36), lba + (size / MMC_BLOCK_SIZE) - 1U,
+ MMC_RESPONSE_R(1), NULL);
+ if (ret != 0) {
+ return 0;
+ }
+
+ ret = mmc_send_cmd(MMC_CMD(38), lba, MMC_RESPONSE_R(0x1B), NULL);
+ if (ret != 0) {
+ return 0;
+ }
+
+ do {
+ ret = mmc_device_state();
+ if (ret < 0) {
+ return 0;
+ }
+ } while (ret != MMC_STATE_TRAN);
+
+ return size;
+}
+
+static inline void mmc_rpmb_enable(void)
+{
+ mmc_set_ext_csd(CMD_EXTCSD_PARTITION_CONFIG,
+ PART_CFG_BOOT_PARTITION1_ENABLE |
+ PART_CFG_PARTITION1_ACCESS);
+}
+
+static inline void mmc_rpmb_disable(void)
+{
+ mmc_set_ext_csd(CMD_EXTCSD_PARTITION_CONFIG,
+ PART_CFG_BOOT_PARTITION1_ENABLE);
+}
+
+size_t mmc_rpmb_read_blocks(unsigned int lba, uintptr_t buf, size_t size)
+{
+ size_t size_read;
+
+ mmc_rpmb_enable();
+ size_read = mmc_read_blocks(lba, buf, size);
+ mmc_rpmb_disable();
+
+ return size_read;
+}
+
+size_t mmc_rpmb_write_blocks(unsigned int lba, const uintptr_t buf, size_t size)
+{
+ size_t size_written;
+
+ mmc_rpmb_enable();
+ size_written = mmc_write_blocks(lba, buf, size);
+ mmc_rpmb_disable();
+
+ return size_written;
+}
+
+size_t mmc_rpmb_erase_blocks(unsigned int lba, size_t size)
+{
+ size_t size_erased;
+
+ mmc_rpmb_enable();
+ size_erased = mmc_erase_blocks(lba, size);
+ mmc_rpmb_disable();
+
+ return size_erased;
+}
+
+int mmc_init(const struct mmc_ops *ops_ptr, unsigned int clk,
+ unsigned int width, unsigned int flags,
+ struct mmc_device_info *device_info)
+{
+ assert((ops_ptr != NULL) &&
+ (ops_ptr->init != NULL) &&
+ (ops_ptr->send_cmd != NULL) &&
+ (ops_ptr->set_ios != NULL) &&
+ (ops_ptr->prepare != NULL) &&
+ (ops_ptr->read != NULL) &&
+ (ops_ptr->write != NULL) &&
+ (device_info != NULL) &&
+ (clk != 0) &&
+ ((width == MMC_BUS_WIDTH_1) ||
+ (width == MMC_BUS_WIDTH_4) ||
+ (width == MMC_BUS_WIDTH_8) ||
+ (width == MMC_BUS_WIDTH_DDR_4) ||
+ (width == MMC_BUS_WIDTH_DDR_8)));
+
+ ops = ops_ptr;
+ mmc_flags = flags;
+ mmc_dev_info = device_info;
+
+ return mmc_enumerate(clk, width);
+}
diff --git a/include/common/aarch64/asm_macros.S b/include/common/aarch64/asm_macros.S
index 5b05045..6e66ea9 100644
--- a/include/common/aarch64/asm_macros.S
+++ b/include/common/aarch64/asm_macros.S
@@ -83,23 +83,31 @@
.section \section_name, "ax"
.align 7, 0
.type \label, %function
- .func \label
.cfi_startproc
\label:
.endm
/*
+ * Add the bytes until fill the full exception vector, whose size is always
+ * 32 instructions. If there are more than 32 instructions in the
+ * exception vector then an error is emitted.
+ */
+ .macro end_vector_entry label
+ .cfi_endproc
+ .fill \label + (32 * 4) - .
+ .endm
+
+ /*
* This macro verifies that the given vector doesn't exceed the
* architectural limit of 32 instructions. This is meant to be placed
* immediately after the last instruction in the vector. It takes the
* vector entry as the parameter
*/
.macro check_vector_size since
- .endfunc
- .cfi_endproc
- .if (. - \since) > (32 * 4)
- .error "Vector exceeds 32 instructions"
- .endif
+#if ERROR_DEPRECATED
+ .error "check_vector_size must not be used. Use end_vector_entry instead"
+#endif
+ end_vector_entry \since
.endm
#if ENABLE_PLAT_COMPAT
diff --git a/include/common/asm_macros_common.S b/include/common/asm_macros_common.S
index ca8c1ad..081addc 100644
--- a/include/common/asm_macros_common.S
+++ b/include/common/asm_macros_common.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -31,7 +31,6 @@
.cfi_sections .debug_frame
.section .text.asm.\_name, "ax"
.type \_name, %function
- .func \_name
/*
* .cfi_startproc and .cfi_endproc are needed to output entries in
* .debug_frame
@@ -45,7 +44,6 @@
* This macro is used to mark the end of a function.
*/
.macro endfunc _name
- .endfunc
.cfi_endproc
.size \_name, . - \_name
.endm
diff --git a/include/common/debug.h b/include/common/debug.h
index 3f0f84a..99f402c 100644
--- a/include/common/debug.h
+++ b/include/common/debug.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,10 +7,12 @@
#ifndef __DEBUG_H__
#define __DEBUG_H__
-/* The log output macros print output to the console. These macros produce
+/*
+ * The log output macros print output to the console. These macros produce
* compiled log output only if the LOG_LEVEL defined in the makefile (or the
* make command line) is greater or equal than the level required for that
* type of log output.
+ *
* The format expected is the same as for printf(). For example:
* INFO("Info %s.\n", "message") -> INFO: Info message.
* WARN("Warning %s.\n", "message") -> WARNING: Warning message.
@@ -38,34 +40,46 @@
#define LOG_MARKER_INFO "\x28" /* 40 */
#define LOG_MARKER_VERBOSE "\x32" /* 50 */
+/*
+ * If the log output is too low then this macro is used in place of tf_log()
+ * below. The intent is to get the compiler to evaluate the function call for
+ * type checking and format specifier correctness but let it optimize it out.
+ */
+#define no_tf_log(fmt, ...) \
+ do { \
+ if (0) { \
+ tf_log(fmt, ##__VA_ARGS__); \
+ } \
+ } while (0)
+
#if LOG_LEVEL >= LOG_LEVEL_NOTICE
# define NOTICE(...) tf_log(LOG_MARKER_NOTICE __VA_ARGS__)
#else
-# define NOTICE(...)
+# define NOTICE(...) no_tf_log(LOG_MARKER_NOTICE __VA_ARGS__)
#endif
#if LOG_LEVEL >= LOG_LEVEL_ERROR
# define ERROR(...) tf_log(LOG_MARKER_ERROR __VA_ARGS__)
#else
-# define ERROR(...)
+# define ERROR(...) no_tf_log(LOG_MARKER_ERROR __VA_ARGS__)
#endif
#if LOG_LEVEL >= LOG_LEVEL_WARNING
# define WARN(...) tf_log(LOG_MARKER_WARNING __VA_ARGS__)
#else
-# define WARN(...)
+# define WARN(...) no_tf_log(LOG_MARKER_WARNING __VA_ARGS__)
#endif
#if LOG_LEVEL >= LOG_LEVEL_INFO
# define INFO(...) tf_log(LOG_MARKER_INFO __VA_ARGS__)
#else
-# define INFO(...)
+# define INFO(...) no_tf_log(LOG_MARKER_INFO __VA_ARGS__)
#endif
#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
# define VERBOSE(...) tf_log(LOG_MARKER_VERBOSE __VA_ARGS__)
#else
-# define VERBOSE(...)
+# define VERBOSE(...) no_tf_log(LOG_MARKER_VERBOSE __VA_ARGS__)
#endif
void __dead2 do_panic(void);
diff --git a/include/drivers/mmc.h b/include/drivers/mmc.h
new file mode 100644
index 0000000..65f4bbd
--- /dev/null
+++ b/include/drivers/mmc.h
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __MMC_H__
+#define __MMC_H__
+
+#include <stdint.h>
+#include <utils_def.h>
+
+#define MMC_BLOCK_SIZE U(512)
+#define MMC_BLOCK_MASK (MMC_BLOCK_SIZE - U(1))
+#define MMC_BOOT_CLK_RATE (400 * 1000)
+
+#define MMC_CMD(_x) U(_x)
+
+#define MMC_ACMD(_x) U(_x)
+
+#define OCR_POWERUP BIT(31)
+#define OCR_HCS BIT(30)
+#define OCR_BYTE_MODE (U(0) << 29)
+#define OCR_SECTOR_MODE (U(2) << 29)
+#define OCR_ACCESS_MODE_MASK (U(3) << 29)
+#define OCR_3_5_3_6 BIT(23)
+#define OCR_3_4_3_5 BIT(22)
+#define OCR_3_3_3_4 BIT(21)
+#define OCR_3_2_3_3 BIT(20)
+#define OCR_3_1_3_2 BIT(19)
+#define OCR_3_0_3_1 BIT(18)
+#define OCR_2_9_3_0 BIT(17)
+#define OCR_2_8_2_9 BIT(16)
+#define OCR_2_7_2_8 BIT(15)
+#define OCR_VDD_MIN_2V7 GENMASK(23, 15)
+#define OCR_VDD_MIN_2V0 GENMASK(14, 8)
+#define OCR_VDD_MIN_1V7 BIT(7)
+
+#define MMC_RESPONSE_R(_x) U(_x)
+
+/* Value randomly chosen for eMMC RCA, it should be > 1 */
+#define MMC_FIX_RCA 6
+#define RCA_SHIFT_OFFSET 16
+
+#define CMD_EXTCSD_PARTITION_CONFIG 179
+#define CMD_EXTCSD_BUS_WIDTH 183
+#define CMD_EXTCSD_HS_TIMING 185
+#define CMD_EXTCSD_SEC_CNT 212
+
+#define PART_CFG_BOOT_PARTITION1_ENABLE (U(1) << 3)
+#define PART_CFG_PARTITION1_ACCESS (U(1) << 0)
+
+/* Values in EXT CSD register */
+#define MMC_BUS_WIDTH_1 U(0)
+#define MMC_BUS_WIDTH_4 U(1)
+#define MMC_BUS_WIDTH_8 U(2)
+#define MMC_BUS_WIDTH_DDR_4 U(5)
+#define MMC_BUS_WIDTH_DDR_8 U(6)
+#define MMC_BOOT_MODE_BACKWARD (U(0) << 3)
+#define MMC_BOOT_MODE_HS_TIMING (U(1) << 3)
+#define MMC_BOOT_MODE_DDR (U(2) << 3)
+
+#define EXTCSD_SET_CMD (U(0) << 24)
+#define EXTCSD_SET_BITS (U(1) << 24)
+#define EXTCSD_CLR_BITS (U(2) << 24)
+#define EXTCSD_WRITE_BYTES (U(3) << 24)
+#define EXTCSD_CMD(x) (((x) & 0xff) << 16)
+#define EXTCSD_VALUE(x) (((x) & 0xff) << 8)
+#define EXTCSD_CMD_SET_NORMAL U(1)
+
+#define CSD_TRAN_SPEED_UNIT_MASK GENMASK(2, 0)
+#define CSD_TRAN_SPEED_MULT_MASK GENMASK(6, 3)
+#define CSD_TRAN_SPEED_MULT_SHIFT 3
+
+#define STATUS_CURRENT_STATE(x) (((x) & 0xf) << 9)
+#define STATUS_READY_FOR_DATA BIT(8)
+#define STATUS_SWITCH_ERROR BIT(7)
+#define MMC_GET_STATE(x) (((x) >> 9) & 0xf)
+#define MMC_STATE_IDLE 0
+#define MMC_STATE_READY 1
+#define MMC_STATE_IDENT 2
+#define MMC_STATE_STBY 3
+#define MMC_STATE_TRAN 4
+#define MMC_STATE_DATA 5
+#define MMC_STATE_RCV 6
+#define MMC_STATE_PRG 7
+#define MMC_STATE_DIS 8
+#define MMC_STATE_BTST 9
+#define MMC_STATE_SLP 10
+
+#define MMC_FLAG_CMD23 (U(1) << 0)
+
+#define CMD8_CHECK_PATTERN U(0xAA)
+#define VHS_2_7_3_6_V BIT(8)
+
+#define SD_SCR_BUS_WIDTH_1 BIT(8)
+#define SD_SCR_BUS_WIDTH_4 BIT(10)
+
+struct mmc_cmd {
+ unsigned int cmd_idx;
+ unsigned int cmd_arg;
+ unsigned int resp_type;
+ unsigned int resp_data[4];
+};
+
+struct mmc_ops {
+ void (*init)(void);
+ int (*send_cmd)(struct mmc_cmd *cmd);
+ int (*set_ios)(unsigned int clk, unsigned int width);
+ int (*prepare)(int lba, uintptr_t buf, size_t size);
+ int (*read)(int lba, uintptr_t buf, size_t size);
+ int (*write)(int lba, const uintptr_t buf, size_t size);
+};
+
+struct mmc_csd_emmc {
+ unsigned int not_used: 1;
+ unsigned int crc: 7;
+ unsigned int ecc: 2;
+ unsigned int file_format: 2;
+ unsigned int tmp_write_protect: 1;
+ unsigned int perm_write_protect: 1;
+ unsigned int copy: 1;
+ unsigned int file_format_grp: 1;
+
+ unsigned int reserved_1: 5;
+ unsigned int write_bl_partial: 1;
+ unsigned int write_bl_len: 4;
+ unsigned int r2w_factor: 3;
+ unsigned int default_ecc: 2;
+ unsigned int wp_grp_enable: 1;
+
+ unsigned int wp_grp_size: 5;
+ unsigned int erase_grp_mult: 5;
+ unsigned int erase_grp_size: 5;
+ unsigned int c_size_mult: 3;
+ unsigned int vdd_w_curr_max: 3;
+ unsigned int vdd_w_curr_min: 3;
+ unsigned int vdd_r_curr_max: 3;
+ unsigned int vdd_r_curr_min: 3;
+ unsigned int c_size_low: 2;
+
+ unsigned int c_size_high: 10;
+ unsigned int reserved_2: 2;
+ unsigned int dsr_imp: 1;
+ unsigned int read_blk_misalign: 1;
+ unsigned int write_blk_misalign: 1;
+ unsigned int read_bl_partial: 1;
+ unsigned int read_bl_len: 4;
+ unsigned int ccc: 12;
+
+ unsigned int tran_speed: 8;
+ unsigned int nsac: 8;
+ unsigned int taac: 8;
+ unsigned int reserved_3: 2;
+ unsigned int spec_vers: 4;
+ unsigned int csd_structure: 2;
+};
+
+struct mmc_csd_sd_v2 {
+ unsigned int not_used: 1;
+ unsigned int crc: 7;
+ unsigned int reserved_1: 2;
+ unsigned int file_format: 2;
+ unsigned int tmp_write_protect: 1;
+ unsigned int perm_write_protect: 1;
+ unsigned int copy: 1;
+ unsigned int file_format_grp: 1;
+
+ unsigned int reserved_2: 5;
+ unsigned int write_bl_partial: 1;
+ unsigned int write_bl_len: 4;
+ unsigned int r2w_factor: 3;
+ unsigned int reserved_3: 2;
+ unsigned int wp_grp_enable: 1;
+
+ unsigned int wp_grp_size: 7;
+ unsigned int sector_size: 7;
+ unsigned int erase_block_en: 1;
+ unsigned int reserved_4: 1;
+ unsigned int c_size_low: 16;
+
+ unsigned int c_size_high: 6;
+ unsigned int reserved_5: 6;
+ unsigned int dsr_imp: 1;
+ unsigned int read_blk_misalign: 1;
+ unsigned int write_blk_misalign: 1;
+ unsigned int read_bl_partial: 1;
+ unsigned int read_bl_len: 4;
+ unsigned int ccc: 12;
+
+ unsigned int tran_speed: 8;
+ unsigned int nsac: 8;
+ unsigned int taac: 8;
+ unsigned int reserved_6: 6;
+ unsigned int csd_structure: 2;
+};
+
+enum mmc_device_type {
+ MMC_IS_EMMC,
+ MMC_IS_SD,
+ MMC_IS_SD_HC,
+};
+
+struct mmc_device_info {
+ unsigned long long device_size; /* Size of device in bytes */
+ unsigned int block_size; /* Block size in bytes */
+ unsigned int max_bus_freq; /* Max bus freq in Hz */
+ enum mmc_device_type mmc_dev_type; /* Type of MMC */
+};
+
+size_t mmc_read_blocks(unsigned int lba, uintptr_t buf, size_t size);
+size_t mmc_write_blocks(unsigned int lba, const uintptr_t buf, size_t size);
+size_t mmc_erase_blocks(unsigned int lba, size_t size);
+size_t mmc_rpmb_read_blocks(unsigned int lba, uintptr_t buf, size_t size);
+size_t mmc_rpmb_write_blocks(unsigned int lba, const uintptr_t buf,
+ size_t size);
+size_t mmc_rpmb_erase_blocks(unsigned int lba, size_t size);
+int mmc_init(const struct mmc_ops *ops_ptr, unsigned int clk,
+ unsigned int width, unsigned int flags,
+ struct mmc_device_info *device_info);
+
+#endif /* __MMC_H__ */
diff --git a/include/lib/aarch32/arch.h b/include/lib/aarch32/arch.h
index a940b63..a536649 100644
--- a/include/lib/aarch32/arch.h
+++ b/include/lib/aarch32/arch.h
@@ -12,31 +12,31 @@
/*******************************************************************************
* MIDR bit definitions
******************************************************************************/
-#define MIDR_IMPL_MASK 0xff
-#define MIDR_IMPL_SHIFT 24
-#define MIDR_VAR_SHIFT 20
-#define MIDR_VAR_BITS 4
-#define MIDR_REV_SHIFT 0
-#define MIDR_REV_BITS 4
-#define MIDR_PN_MASK 0xfff
-#define MIDR_PN_SHIFT 4
+#define MIDR_IMPL_MASK U(0xff)
+#define MIDR_IMPL_SHIFT U(24)
+#define MIDR_VAR_SHIFT U(20)
+#define MIDR_VAR_BITS U(4)
+#define MIDR_REV_SHIFT U(0)
+#define MIDR_REV_BITS U(4)
+#define MIDR_PN_MASK U(0xfff)
+#define MIDR_PN_SHIFT U(4)
/*******************************************************************************
* MPIDR macros
******************************************************************************/
-#define MPIDR_MT_MASK (1 << 24)
+#define MPIDR_MT_MASK (U(1) << 24)
#define MPIDR_CPU_MASK MPIDR_AFFLVL_MASK
#define MPIDR_CLUSTER_MASK (MPIDR_AFFLVL_MASK << MPIDR_AFFINITY_BITS)
-#define MPIDR_AFFINITY_BITS 8
-#define MPIDR_AFFLVL_MASK 0xff
-#define MPIDR_AFFLVL_SHIFT 3
-#define MPIDR_AFF0_SHIFT 0
-#define MPIDR_AFF1_SHIFT 8
-#define MPIDR_AFF2_SHIFT 16
-#define MPIDR_AFFINITY_MASK 0x00ffffff
-#define MPIDR_AFFLVL0 0
-#define MPIDR_AFFLVL1 1
-#define MPIDR_AFFLVL2 2
+#define MPIDR_AFFINITY_BITS U(8)
+#define MPIDR_AFFLVL_MASK U(0xff)
+#define MPIDR_AFFLVL_SHIFT U(3)
+#define MPIDR_AFF0_SHIFT U(0)
+#define MPIDR_AFF1_SHIFT U(8)
+#define MPIDR_AFF2_SHIFT U(16)
+#define MPIDR_AFFINITY_MASK U(0x00ffffff)
+#define MPIDR_AFFLVL0 U(0)
+#define MPIDR_AFFLVL1 U(1)
+#define MPIDR_AFFLVL2 U(2)
#define MPIDR_AFFLVL0_VAL(mpidr) \
(((mpidr) >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK)
@@ -44,39 +44,39 @@
(((mpidr) >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK)
#define MPIDR_AFFLVL2_VAL(mpidr) \
(((mpidr) >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK)
-#define MPIDR_AFFLVL3_VAL(mpidr) 0
+#define MPIDR_AFFLVL3_VAL(mpidr) U(0)
/*
* The MPIDR_MAX_AFFLVL count starts from 0. Take care to
* add one while using this macro to define array sizes.
*/
-#define MPIDR_MAX_AFFLVL 2
+#define MPIDR_MAX_AFFLVL U(2)
/* Data Cache set/way op type defines */
-#define DC_OP_ISW 0x0
-#define DC_OP_CISW 0x1
-#define DC_OP_CSW 0x2
+#define DC_OP_ISW U(0x0)
+#define DC_OP_CISW U(0x1)
+#define DC_OP_CSW U(0x2)
/*******************************************************************************
* Generic timer memory mapped registers & offsets
******************************************************************************/
-#define CNTCR_OFF 0x000
-#define CNTFID_OFF 0x020
+#define CNTCR_OFF U(0x000)
+#define CNTFID_OFF U(0x020)
-#define CNTCR_EN (1 << 0)
-#define CNTCR_HDBG (1 << 1)
+#define CNTCR_EN (U(1) << 0)
+#define CNTCR_HDBG (U(1) << 1)
#define CNTCR_FCREQ(x) ((x) << 8)
/*******************************************************************************
* System register bit definitions
******************************************************************************/
/* CLIDR definitions */
-#define LOUIS_SHIFT 21
-#define LOC_SHIFT 24
-#define CLIDR_FIELD_WIDTH 3
+#define LOUIS_SHIFT U(21)
+#define LOC_SHIFT U(24)
+#define CLIDR_FIELD_WIDTH U(3)
/* CSSELR definitions */
-#define LEVEL_SHIFT 1
+#define LEVEL_SHIFT U(1)
/* ID_PFR0 definitions */
#define ID_PFR0_AMU_SHIFT U(20)
@@ -84,184 +84,185 @@
#define ID_PFR0_AMU_MASK U(0xf)
/* ID_PFR1 definitions */
-#define ID_PFR1_VIRTEXT_SHIFT 12
-#define ID_PFR1_VIRTEXT_MASK 0xf
+#define ID_PFR1_VIRTEXT_SHIFT U(12)
+#define ID_PFR1_VIRTEXT_MASK U(0xf)
#define GET_VIRT_EXT(id) (((id) >> ID_PFR1_VIRTEXT_SHIFT) \
& ID_PFR1_VIRTEXT_MASK)
-#define ID_PFR1_GIC_SHIFT 28
-#define ID_PFR1_GIC_MASK 0xf
+#define ID_PFR1_GIC_SHIFT U(28)
+#define ID_PFR1_GIC_MASK U(0xf)
/* SCTLR definitions */
-#define SCTLR_RES1_DEF ((1 << 23) | (1 << 22) | (1 << 4) | (1 << 3))
+#define SCTLR_RES1_DEF ((U(1) << 23) | (U(1) << 22) | (U(1) << 4) | \
+ (U(1) << 3))
#if ARM_ARCH_MAJOR == 7
#define SCTLR_RES1 SCTLR_RES1_DEF
#else
-#define SCTLR_RES1 (SCTLR_RES1_DEF | (1 << 11))
+#define SCTLR_RES1 (SCTLR_RES1_DEF | (U(1) << 11))
#endif
-#define SCTLR_M_BIT (1 << 0)
-#define SCTLR_A_BIT (1 << 1)
-#define SCTLR_C_BIT (1 << 2)
-#define SCTLR_CP15BEN_BIT (1 << 5)
-#define SCTLR_ITD_BIT (1 << 7)
-#define SCTLR_Z_BIT (1 << 11)
-#define SCTLR_I_BIT (1 << 12)
-#define SCTLR_V_BIT (1 << 13)
-#define SCTLR_RR_BIT (1 << 14)
-#define SCTLR_NTWI_BIT (1 << 16)
-#define SCTLR_NTWE_BIT (1 << 18)
-#define SCTLR_WXN_BIT (1 << 19)
-#define SCTLR_UWXN_BIT (1 << 20)
-#define SCTLR_EE_BIT (1 << 25)
-#define SCTLR_TRE_BIT (1 << 28)
-#define SCTLR_AFE_BIT (1 << 29)
-#define SCTLR_TE_BIT (1 << 30)
+#define SCTLR_M_BIT (U(1) << 0)
+#define SCTLR_A_BIT (U(1) << 1)
+#define SCTLR_C_BIT (U(1) << 2)
+#define SCTLR_CP15BEN_BIT (U(1) << 5)
+#define SCTLR_ITD_BIT (U(1) << 7)
+#define SCTLR_Z_BIT (U(1) << 11)
+#define SCTLR_I_BIT (U(1) << 12)
+#define SCTLR_V_BIT (U(1) << 13)
+#define SCTLR_RR_BIT (U(1) << 14)
+#define SCTLR_NTWI_BIT (U(1) << 16)
+#define SCTLR_NTWE_BIT (U(1) << 18)
+#define SCTLR_WXN_BIT (U(1) << 19)
+#define SCTLR_UWXN_BIT (U(1) << 20)
+#define SCTLR_EE_BIT (U(1) << 25)
+#define SCTLR_TRE_BIT (U(1) << 28)
+#define SCTLR_AFE_BIT (U(1) << 29)
+#define SCTLR_TE_BIT (U(1) << 30)
#define SCTLR_RESET_VAL (SCTLR_RES1 | SCTLR_NTWE_BIT | \
SCTLR_NTWI_BIT | SCTLR_CP15BEN_BIT)
/* SDCR definitions */
#define SDCR_SPD(x) ((x) << 14)
-#define SDCR_SPD_LEGACY 0x0
-#define SDCR_SPD_DISABLE 0x2
-#define SDCR_SPD_ENABLE 0x3
-#define SDCR_RESET_VAL 0x0
+#define SDCR_SPD_LEGACY U(0x0)
+#define SDCR_SPD_DISABLE U(0x2)
+#define SDCR_SPD_ENABLE U(0x3)
+#define SDCR_RESET_VAL U(0x0)
#if !ERROR_DEPRECATED
#define SDCR_DEF_VAL SDCR_SPD(SDCR_SPD_DISABLE)
#endif
/* HSCTLR definitions */
-#define HSCTLR_RES1 ((1 << 29) | (1 << 28) | (1 << 23) | (1 << 22) \
- | (1 << 18) | (1 << 16) | (1 << 11) | (1 << 4) \
- | (1 << 3))
-#define HSCTLR_M_BIT (1 << 0)
-#define HSCTLR_A_BIT (1 << 1)
-#define HSCTLR_C_BIT (1 << 2)
-#define HSCTLR_CP15BEN_BIT (1 << 5)
-#define HSCTLR_ITD_BIT (1 << 7)
-#define HSCTLR_SED_BIT (1 << 8)
-#define HSCTLR_I_BIT (1 << 12)
-#define HSCTLR_WXN_BIT (1 << 19)
-#define HSCTLR_EE_BIT (1 << 25)
-#define HSCTLR_TE_BIT (1 << 30)
+#define HSCTLR_RES1 ((U(1) << 29) | (U(1) << 28) | (U(1) << 23) | \
+ (U(1) << 22) | (U(1) << 18) | (U(1) << 16) | \
+ (U(1) << 11) | (U(1) << 4) | (U(1) << 3))
+
+#define HSCTLR_M_BIT (U(1) << 0)
+#define HSCTLR_A_BIT (U(1) << 1)
+#define HSCTLR_C_BIT (U(1) << 2)
+#define HSCTLR_CP15BEN_BIT (U(1) << 5)
+#define HSCTLR_ITD_BIT (U(1) << 7)
+#define HSCTLR_SED_BIT (U(1) << 8)
+#define HSCTLR_I_BIT (U(1) << 12)
+#define HSCTLR_WXN_BIT (U(1) << 19)
+#define HSCTLR_EE_BIT (U(1) << 25)
+#define HSCTLR_TE_BIT (U(1) << 30)
/* CPACR definitions */
-#define CPACR_FPEN(x) ((x) << 20)
-#define CPACR_FP_TRAP_PL0 0x1
-#define CPACR_FP_TRAP_ALL 0x2
-#define CPACR_FP_TRAP_NONE 0x3
+#define CPACR_FPEN(x) ((x) << 20)
+#define CPACR_FP_TRAP_PL0 U(0x1)
+#define CPACR_FP_TRAP_ALL U(0x2)
+#define CPACR_FP_TRAP_NONE U(0x3)
/* SCR definitions */
-#define SCR_TWE_BIT (1 << 13)
-#define SCR_TWI_BIT (1 << 12)
-#define SCR_SIF_BIT (1 << 9)
-#define SCR_HCE_BIT (1 << 8)
-#define SCR_SCD_BIT (1 << 7)
-#define SCR_NET_BIT (1 << 6)
-#define SCR_AW_BIT (1 << 5)
-#define SCR_FW_BIT (1 << 4)
-#define SCR_EA_BIT (1 << 3)
-#define SCR_FIQ_BIT (1 << 2)
-#define SCR_IRQ_BIT (1 << 1)
-#define SCR_NS_BIT (1 << 0)
-#define SCR_VALID_BIT_MASK 0x33ff
-#define SCR_RESET_VAL 0x0
+#define SCR_TWE_BIT (U(1) << 13)
+#define SCR_TWI_BIT (U(1) << 12)
+#define SCR_SIF_BIT (U(1) << 9)
+#define SCR_HCE_BIT (U(1) << 8)
+#define SCR_SCD_BIT (U(1) << 7)
+#define SCR_NET_BIT (U(1) << 6)
+#define SCR_AW_BIT (U(1) << 5)
+#define SCR_FW_BIT (U(1) << 4)
+#define SCR_EA_BIT (U(1) << 3)
+#define SCR_FIQ_BIT (U(1) << 2)
+#define SCR_IRQ_BIT (U(1) << 1)
+#define SCR_NS_BIT (U(1) << 0)
+#define SCR_VALID_BIT_MASK U(0x33ff)
+#define SCR_RESET_VAL U(0x0)
#define GET_NS_BIT(scr) ((scr) & SCR_NS_BIT)
/* HCR definitions */
-#define HCR_AMO_BIT (1 << 5)
-#define HCR_IMO_BIT (1 << 4)
-#define HCR_FMO_BIT (1 << 3)
-#define HCR_RESET_VAL 0x0
+#define HCR_AMO_BIT (U(1) << 5)
+#define HCR_IMO_BIT (U(1) << 4)
+#define HCR_FMO_BIT (U(1) << 3)
+#define HCR_RESET_VAL U(0x0)
/* CNTHCTL definitions */
-#define CNTHCTL_RESET_VAL 0x0
-#define PL1PCEN_BIT (1 << 1)
-#define PL1PCTEN_BIT (1 << 0)
+#define CNTHCTL_RESET_VAL U(0x0)
+#define PL1PCEN_BIT (U(1) << 1)
+#define PL1PCTEN_BIT (U(1) << 0)
/* CNTKCTL definitions */
-#define PL0PTEN_BIT (1 << 9)
-#define PL0VTEN_BIT (1 << 8)
-#define PL0PCTEN_BIT (1 << 0)
-#define PL0VCTEN_BIT (1 << 1)
-#define EVNTEN_BIT (1 << 2)
-#define EVNTDIR_BIT (1 << 3)
-#define EVNTI_SHIFT 4
-#define EVNTI_MASK 0xf
+#define PL0PTEN_BIT (U(1) << 9)
+#define PL0VTEN_BIT (U(1) << 8)
+#define PL0PCTEN_BIT (U(1) << 0)
+#define PL0VCTEN_BIT (U(1) << 1)
+#define EVNTEN_BIT (U(1) << 2)
+#define EVNTDIR_BIT (U(1) << 3)
+#define EVNTI_SHIFT U(4)
+#define EVNTI_MASK U(0xf)
/* HCPTR definitions */
-#define HCPTR_RES1 ((1 << 13) | (1<<12) | 0x3ff)
-#define TCPAC_BIT (1 << 31)
-#define TAM_BIT (1 << 30)
-#define TTA_BIT (1 << 20)
-#define TCP11_BIT (1 << 10)
-#define TCP10_BIT (1 << 10)
+#define HCPTR_RES1 ((U(1) << 13) | (U(1) << 12) | U(0x3ff))
+#define TCPAC_BIT (U(1) << 31)
+#define TAM_BIT (U(1) << 30)
+#define TTA_BIT (U(1) << 20)
+#define TCP11_BIT (U(1) << 11)
+#define TCP10_BIT (U(1) << 10)
#define HCPTR_RESET_VAL HCPTR_RES1
/* VTTBR defintions */
#define VTTBR_RESET_VAL ULL(0x0)
#define VTTBR_VMID_MASK ULL(0xff)
-#define VTTBR_VMID_SHIFT 48
-#define VTTBR_BADDR_MASK 0xffffffffffff
-#define VTTBR_BADDR_SHIFT 0
+#define VTTBR_VMID_SHIFT U(48)
+#define VTTBR_BADDR_MASK ULL(0xffffffffffff)
+#define VTTBR_BADDR_SHIFT U(0)
/* HDCR definitions */
-#define HDCR_RESET_VAL 0x0
+#define HDCR_RESET_VAL U(0x0)
/* HSTR definitions */
-#define HSTR_RESET_VAL 0x0
+#define HSTR_RESET_VAL U(0x0)
/* CNTHP_CTL definitions */
-#define CNTHP_CTL_RESET_VAL 0x0
+#define CNTHP_CTL_RESET_VAL U(0x0)
/* NASCR definitions */
-#define NSASEDIS_BIT (1 << 15)
-#define NSTRCDIS_BIT (1 << 20)
+#define NSASEDIS_BIT (U(1) << 15)
+#define NSTRCDIS_BIT (U(1) << 20)
/* NOTE: correct typo in the definitions */
#if !ERROR_DEPRECATED
-#define NASCR_CP11_BIT (1 << 11)
-#define NASCR_CP10_BIT (1 << 10)
+#define NASCR_CP11_BIT (U(1) << 11)
+#define NASCR_CP10_BIT (U(1) << 10)
#endif
-#define NSACR_CP11_BIT (1 << 11)
-#define NSACR_CP10_BIT (1 << 10)
-#define NSACR_IMP_DEF_MASK (0x7 << 16)
+#define NSACR_CP11_BIT (U(1) << 11)
+#define NSACR_CP10_BIT (U(1) << 10)
+#define NSACR_IMP_DEF_MASK (U(0x7) << 16)
#define NSACR_ENABLE_FP_ACCESS (NSACR_CP11_BIT | NSACR_CP10_BIT)
-#define NSACR_RESET_VAL 0x0
+#define NSACR_RESET_VAL U(0x0)
/* CPACR definitions */
-#define ASEDIS_BIT (1 << 31)
-#define TRCDIS_BIT (1 << 28)
-#define CPACR_CP11_SHIFT 22
-#define CPACR_CP10_SHIFT 20
-#define CPACR_ENABLE_FP_ACCESS (0x3 << CPACR_CP11_SHIFT |\
- 0x3 << CPACR_CP10_SHIFT)
-#define CPACR_RESET_VAL 0x0
+#define ASEDIS_BIT (U(1) << 31)
+#define TRCDIS_BIT (U(1) << 28)
+#define CPACR_CP11_SHIFT U(22)
+#define CPACR_CP10_SHIFT U(20)
+#define CPACR_ENABLE_FP_ACCESS ((U(0x3) << CPACR_CP11_SHIFT) |\
+ (U(0x3) << CPACR_CP10_SHIFT))
+#define CPACR_RESET_VAL U(0x0)
/* FPEXC definitions */
-#define FPEXC_RES1 ((1 << 10) | (1 << 9) | (1 << 8))
-#define FPEXC_EN_BIT (1 << 30)
+#define FPEXC_RES1 ((U(1) << 10) | (U(1) << 9) | (U(1) << 8))
+#define FPEXC_EN_BIT (U(1) << 30)
#define FPEXC_RESET_VAL FPEXC_RES1
/* SPSR/CPSR definitions */
-#define SPSR_FIQ_BIT (1 << 0)
-#define SPSR_IRQ_BIT (1 << 1)
-#define SPSR_ABT_BIT (1 << 2)
-#define SPSR_AIF_SHIFT 6
-#define SPSR_AIF_MASK 0x7
+#define SPSR_FIQ_BIT (U(1) << 0)
+#define SPSR_IRQ_BIT (U(1) << 1)
+#define SPSR_ABT_BIT (U(1) << 2)
+#define SPSR_AIF_SHIFT U(6)
+#define SPSR_AIF_MASK U(0x7)
-#define SPSR_E_SHIFT 9
-#define SPSR_E_MASK 0x1
-#define SPSR_E_LITTLE 0
-#define SPSR_E_BIG 1
+#define SPSR_E_SHIFT U(9)
+#define SPSR_E_MASK U(0x1)
+#define SPSR_E_LITTLE U(0)
+#define SPSR_E_BIG U(1)
-#define SPSR_T_SHIFT 5
-#define SPSR_T_MASK 0x1
-#define SPSR_T_ARM 0
-#define SPSR_T_THUMB 1
+#define SPSR_T_SHIFT U(5)
+#define SPSR_T_MASK U(0x1)
+#define SPSR_T_ARM U(0)
+#define SPSR_T_THUMB U(1)
-#define SPSR_MODE_SHIFT 0
-#define SPSR_MODE_MASK 0x7
-
+#define SPSR_MODE_SHIFT U(0)
+#define SPSR_MODE_MASK U(0x7)
#define DISABLE_ALL_EXCEPTIONS \
(SPSR_FIQ_BIT | SPSR_IRQ_BIT | SPSR_ABT_BIT)
@@ -270,63 +271,63 @@
* TTBCR definitions
*/
/* The ARM Trusted Firmware uses the long descriptor format */
-#define TTBCR_EAE_BIT (1 << 31)
+#define TTBCR_EAE_BIT (U(1) << 31)
-#define TTBCR_SH1_NON_SHAREABLE (0x0 << 28)
-#define TTBCR_SH1_OUTER_SHAREABLE (0x2 << 28)
-#define TTBCR_SH1_INNER_SHAREABLE (0x3 << 28)
+#define TTBCR_SH1_NON_SHAREABLE (U(0x0) << 28)
+#define TTBCR_SH1_OUTER_SHAREABLE (U(0x2) << 28)
+#define TTBCR_SH1_INNER_SHAREABLE (U(0x3) << 28)
-#define TTBCR_RGN1_OUTER_NC (0x0 << 26)
-#define TTBCR_RGN1_OUTER_WBA (0x1 << 26)
-#define TTBCR_RGN1_OUTER_WT (0x2 << 26)
-#define TTBCR_RGN1_OUTER_WBNA (0x3 << 26)
+#define TTBCR_RGN1_OUTER_NC (U(0x0) << 26)
+#define TTBCR_RGN1_OUTER_WBA (U(0x1) << 26)
+#define TTBCR_RGN1_OUTER_WT (U(0x2) << 26)
+#define TTBCR_RGN1_OUTER_WBNA (U(0x3) << 26)
-#define TTBCR_RGN1_INNER_NC (0x0 << 24)
-#define TTBCR_RGN1_INNER_WBA (0x1 << 24)
-#define TTBCR_RGN1_INNER_WT (0x2 << 24)
-#define TTBCR_RGN1_INNER_WBNA (0x3 << 24)
+#define TTBCR_RGN1_INNER_NC (U(0x0) << 24)
+#define TTBCR_RGN1_INNER_WBA (U(0x1) << 24)
+#define TTBCR_RGN1_INNER_WT (U(0x2) << 24)
+#define TTBCR_RGN1_INNER_WBNA (U(0x3) << 24)
-#define TTBCR_EPD1_BIT (1 << 23)
-#define TTBCR_A1_BIT (1 << 22)
+#define TTBCR_EPD1_BIT (U(1) << 23)
+#define TTBCR_A1_BIT (U(1) << 22)
-#define TTBCR_T1SZ_SHIFT 16
-#define TTBCR_T1SZ_MASK (0x7)
-#define TTBCR_TxSZ_MIN 0
-#define TTBCR_TxSZ_MAX 7
+#define TTBCR_T1SZ_SHIFT U(16)
+#define TTBCR_T1SZ_MASK U(0x7)
+#define TTBCR_TxSZ_MIN U(0)
+#define TTBCR_TxSZ_MAX U(7)
-#define TTBCR_SH0_NON_SHAREABLE (0x0 << 12)
-#define TTBCR_SH0_OUTER_SHAREABLE (0x2 << 12)
-#define TTBCR_SH0_INNER_SHAREABLE (0x3 << 12)
+#define TTBCR_SH0_NON_SHAREABLE (U(0x0) << 12)
+#define TTBCR_SH0_OUTER_SHAREABLE (U(0x2) << 12)
+#define TTBCR_SH0_INNER_SHAREABLE (U(0x3) << 12)
-#define TTBCR_RGN0_OUTER_NC (0x0 << 10)
-#define TTBCR_RGN0_OUTER_WBA (0x1 << 10)
-#define TTBCR_RGN0_OUTER_WT (0x2 << 10)
-#define TTBCR_RGN0_OUTER_WBNA (0x3 << 10)
+#define TTBCR_RGN0_OUTER_NC (U(0x0) << 10)
+#define TTBCR_RGN0_OUTER_WBA (U(0x1) << 10)
+#define TTBCR_RGN0_OUTER_WT (U(0x2) << 10)
+#define TTBCR_RGN0_OUTER_WBNA (U(0x3) << 10)
-#define TTBCR_RGN0_INNER_NC (0x0 << 8)
-#define TTBCR_RGN0_INNER_WBA (0x1 << 8)
-#define TTBCR_RGN0_INNER_WT (0x2 << 8)
-#define TTBCR_RGN0_INNER_WBNA (0x3 << 8)
+#define TTBCR_RGN0_INNER_NC (U(0x0) << 8)
+#define TTBCR_RGN0_INNER_WBA (U(0x1) << 8)
+#define TTBCR_RGN0_INNER_WT (U(0x2) << 8)
+#define TTBCR_RGN0_INNER_WBNA (U(0x3) << 8)
-#define TTBCR_EPD0_BIT (1 << 7)
-#define TTBCR_T0SZ_SHIFT 0
-#define TTBCR_T0SZ_MASK (0x7)
+#define TTBCR_EPD0_BIT (U(1) << 7)
+#define TTBCR_T0SZ_SHIFT U(0)
+#define TTBCR_T0SZ_MASK U(0x7)
-#define MODE_RW_SHIFT 0x4
-#define MODE_RW_MASK 0x1
-#define MODE_RW_32 0x1
+#define MODE_RW_SHIFT U(0x4)
+#define MODE_RW_MASK U(0x1)
+#define MODE_RW_32 U(0x1)
-#define MODE32_SHIFT 0
-#define MODE32_MASK 0x1f
-#define MODE32_usr 0x10
-#define MODE32_fiq 0x11
-#define MODE32_irq 0x12
-#define MODE32_svc 0x13
-#define MODE32_mon 0x16
-#define MODE32_abt 0x17
-#define MODE32_hyp 0x1a
-#define MODE32_und 0x1b
-#define MODE32_sys 0x1f
+#define MODE32_SHIFT U(0)
+#define MODE32_MASK U(0x1f)
+#define MODE32_usr U(0x10)
+#define MODE32_fiq U(0x11)
+#define MODE32_irq U(0x12)
+#define MODE32_svc U(0x13)
+#define MODE32_mon U(0x16)
+#define MODE32_abt U(0x17)
+#define MODE32_hyp U(0x1a)
+#define MODE32_und U(0x1b)
+#define MODE32_sys U(0x1f)
#define GET_M32(mode) (((mode) >> MODE32_SHIFT) & MODE32_MASK)
@@ -340,39 +341,39 @@
/*
* TTBR definitions
*/
-#define TTBR_CNP_BIT U(0x1)
+#define TTBR_CNP_BIT ULL(0x1)
/*
* CTR definitions
*/
-#define CTR_CWG_SHIFT 24
-#define CTR_CWG_MASK 0xf
-#define CTR_ERG_SHIFT 20
-#define CTR_ERG_MASK 0xf
-#define CTR_DMINLINE_SHIFT 16
-#define CTR_DMINLINE_WIDTH 4
-#define CTR_DMINLINE_MASK ((1 << 4) - 1)
-#define CTR_L1IP_SHIFT 14
-#define CTR_L1IP_MASK 0x3
-#define CTR_IMINLINE_SHIFT 0
-#define CTR_IMINLINE_MASK 0xf
+#define CTR_CWG_SHIFT U(24)
+#define CTR_CWG_MASK U(0xf)
+#define CTR_ERG_SHIFT U(20)
+#define CTR_ERG_MASK U(0xf)
+#define CTR_DMINLINE_SHIFT U(16)
+#define CTR_DMINLINE_WIDTH U(4)
+#define CTR_DMINLINE_MASK ((U(1) << 4) - U(1))
+#define CTR_L1IP_SHIFT U(14)
+#define CTR_L1IP_MASK U(0x3)
+#define CTR_IMINLINE_SHIFT U(0)
+#define CTR_IMINLINE_MASK U(0xf)
-#define MAX_CACHE_LINE_SIZE 0x800 /* 2KB */
+#define MAX_CACHE_LINE_SIZE U(0x800) /* 2KB */
/* PMCR definitions */
-#define PMCR_N_SHIFT 11
-#define PMCR_N_MASK 0x1f
+#define PMCR_N_SHIFT U(11)
+#define PMCR_N_MASK U(0x1f)
#define PMCR_N_BITS (PMCR_N_MASK << PMCR_N_SHIFT)
-#define PMCR_LC_BIT (1 << 6)
-#define PMCR_DP_BIT (1 << 5)
+#define PMCR_LC_BIT (U(1) << 6)
+#define PMCR_DP_BIT (U(1) << 5)
/*******************************************************************************
* Definitions of register offsets, fields and macros for CPU system
* instructions.
******************************************************************************/
-#define TLBI_ADDR_SHIFT 0
-#define TLBI_ADDR_MASK 0xFFFFF000
+#define TLBI_ADDR_SHIFT U(0)
+#define TLBI_ADDR_MASK U(0xFFFFF000)
#define TLBI_ADDR(x) (((x) >> TLBI_ADDR_SHIFT) & TLBI_ADDR_MASK)
/*******************************************************************************
@@ -380,16 +381,16 @@
* system level implementation of the Generic Timer.
******************************************************************************/
#define CNTCTLBASE_CNTFRQ U(0x0)
-#define CNTNSAR 0x4
+#define CNTNSAR U(0x4)
#define CNTNSAR_NS_SHIFT(x) (x)
-#define CNTACR_BASE(x) (0x40 + ((x) << 2))
-#define CNTACR_RPCT_SHIFT 0x0
-#define CNTACR_RVCT_SHIFT 0x1
-#define CNTACR_RFRQ_SHIFT 0x2
-#define CNTACR_RVOFF_SHIFT 0x3
-#define CNTACR_RWVT_SHIFT 0x4
-#define CNTACR_RWPT_SHIFT 0x5
+#define CNTACR_BASE(x) (U(0x40) + ((x) << 2))
+#define CNTACR_RPCT_SHIFT U(0x0)
+#define CNTACR_RVCT_SHIFT U(0x1)
+#define CNTACR_RFRQ_SHIFT U(0x2)
+#define CNTACR_RVOFF_SHIFT U(0x3)
+#define CNTACR_RWVT_SHIFT U(0x4)
+#define CNTACR_RWPT_SHIFT U(0x5)
/*******************************************************************************
* Definitions of register offsets in the CNTBaseN Frame of the
@@ -399,7 +400,7 @@
/* MAIR macros */
#define MAIR0_ATTR_SET(attr, index) ((attr) << ((index) << 3))
-#define MAIR1_ATTR_SET(attr, index) ((attr) << (((index) - 3) << 3))
+#define MAIR1_ATTR_SET(attr, index) ((attr) << (((index) - U(3)) << 3))
/* System register defines The format is: coproc, opt1, CRn, CRm, opt2 */
#define SCR p15, 0, c1, c1, 0
@@ -537,9 +538,10 @@
#define MAIR_NORM_WB_NTR_RA U(0xe)
#define MAIR_NORM_WB_NTR_RWA U(0xf)
-#define MAIR_NORM_OUTER_SHIFT 4
+#define MAIR_NORM_OUTER_SHIFT U(4)
-#define MAKE_MAIR_NORMAL_MEMORY(inner, outer) ((inner) | ((outer) << MAIR_NORM_OUTER_SHIFT))
+#define MAKE_MAIR_NORMAL_MEMORY(inner, outer) \
+ ((inner) | ((outer) << MAIR_NORM_OUTER_SHIFT))
/*******************************************************************************
* Definitions for system register interface to AMU for ARMv8.4 onwards
diff --git a/include/lib/aarch32/smccc_helpers.h b/include/lib/aarch32/smccc_helpers.h
index 240dd13..731c26f 100644
--- a/include/lib/aarch32/smccc_helpers.h
+++ b/include/lib/aarch32/smccc_helpers.h
@@ -129,13 +129,6 @@
SMC_RET3(_h, (_r0), (_r1), (_r2)); \
}
-/* Return a UUID in the SMC return registers */
-#define SMC_UUID_RET(_h, _uuid) \
- SMC_RET4(handle, ((const uint32_t *) &(_uuid))[0], \
- ((const uint32_t *) &(_uuid))[1], \
- ((const uint32_t *) &(_uuid))[2], \
- ((const uint32_t *) &(_uuid))[3])
-
/*
* Helper macro to retrieve the SMC parameters from smc_ctx_t.
*/
diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h
index 7cc4b23..7385b5d 100644
--- a/include/lib/aarch64/arch.h
+++ b/include/lib/aarch64/arch.h
@@ -26,29 +26,29 @@
/*******************************************************************************
* MPIDR macros
******************************************************************************/
-#define MPIDR_MT_MASK (U(1) << 24)
+#define MPIDR_MT_MASK (ULL(1) << 24)
#define MPIDR_CPU_MASK MPIDR_AFFLVL_MASK
#define MPIDR_CLUSTER_MASK (MPIDR_AFFLVL_MASK << MPIDR_AFFINITY_BITS)
#define MPIDR_AFFINITY_BITS U(8)
-#define MPIDR_AFFLVL_MASK U(0xff)
+#define MPIDR_AFFLVL_MASK ULL(0xff)
#define MPIDR_AFF0_SHIFT U(0)
#define MPIDR_AFF1_SHIFT U(8)
#define MPIDR_AFF2_SHIFT U(16)
#define MPIDR_AFF3_SHIFT U(32)
-#define MPIDR_AFFINITY_MASK U(0xff00ffffff)
+#define MPIDR_AFFINITY_MASK ULL(0xff00ffffff)
#define MPIDR_AFFLVL_SHIFT U(3)
-#define MPIDR_AFFLVL0 U(0)
-#define MPIDR_AFFLVL1 U(1)
-#define MPIDR_AFFLVL2 U(2)
-#define MPIDR_AFFLVL3 U(3)
+#define MPIDR_AFFLVL0 ULL(0x0)
+#define MPIDR_AFFLVL1 ULL(0x1)
+#define MPIDR_AFFLVL2 ULL(0x2)
+#define MPIDR_AFFLVL3 ULL(0x3)
#define MPIDR_AFFLVL0_VAL(mpidr) \
- ((mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK)
+ (((mpidr) >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK)
#define MPIDR_AFFLVL1_VAL(mpidr) \
- ((mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK)
+ (((mpidr) >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK)
#define MPIDR_AFFLVL2_VAL(mpidr) \
- ((mpidr >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK)
+ (((mpidr) >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK)
#define MPIDR_AFFLVL3_VAL(mpidr) \
- ((mpidr >> MPIDR_AFF3_SHIFT) & MPIDR_AFFLVL_MASK)
+ (((mpidr) >> MPIDR_AFF3_SHIFT) & MPIDR_AFFLVL_MASK)
/*
* The MPIDR_MAX_AFFLVL count starts from 0. Take care to
* add one while using this macro to define array sizes.
@@ -57,7 +57,7 @@
#define MPIDR_MAX_AFFLVL U(2)
/* Constant to highlight the assumption that MPIDR allocation starts from 0 */
-#define FIRST_MPIDR U(0)
+#define FIRST_MPIDR ULL(0)
/*******************************************************************************
* Definitions for CPU system register interface to GICv3
@@ -100,7 +100,7 @@
/* CSSELR definitions */
#define LEVEL_SHIFT U(1)
-/* D$ set/way op type defines */
+/* Data cache set/way op type defines */
#define DCISW U(0x0)
#define DCCISW U(0x1)
#define DCCSW U(0x2)
@@ -112,31 +112,31 @@
#define ID_AA64PFR0_EL3_SHIFT U(12)
#define ID_AA64PFR0_AMU_SHIFT U(44)
#define ID_AA64PFR0_AMU_LENGTH U(4)
-#define ID_AA64PFR0_AMU_MASK U(0xf)
-#define ID_AA64PFR0_ELX_MASK U(0xf)
+#define ID_AA64PFR0_AMU_MASK ULL(0xf)
+#define ID_AA64PFR0_ELX_MASK ULL(0xf)
#define ID_AA64PFR0_SVE_SHIFT U(32)
-#define ID_AA64PFR0_SVE_MASK U(0xf)
+#define ID_AA64PFR0_SVE_MASK ULL(0xf)
#define ID_AA64PFR0_SVE_LENGTH U(4)
#define ID_AA64PFR0_CSV2_SHIFT U(56)
-#define ID_AA64PFR0_CSV2_MASK U(0xf)
+#define ID_AA64PFR0_CSV2_MASK ULL(0xf)
#define ID_AA64PFR0_CSV2_LENGTH U(4)
/* ID_AA64DFR0_EL1.PMS definitions (for ARMv8.2+) */
#define ID_AA64DFR0_PMS_SHIFT U(32)
#define ID_AA64DFR0_PMS_LENGTH U(4)
-#define ID_AA64DFR0_PMS_MASK U(0xf)
+#define ID_AA64DFR0_PMS_MASK ULL(0xf)
-#define EL_IMPL_NONE U(0)
-#define EL_IMPL_A64ONLY U(1)
-#define EL_IMPL_A64_A32 U(2)
+#define EL_IMPL_NONE ULL(0)
+#define EL_IMPL_A64ONLY ULL(1)
+#define EL_IMPL_A64_A32 ULL(2)
#define ID_AA64PFR0_GIC_SHIFT U(24)
#define ID_AA64PFR0_GIC_WIDTH U(4)
-#define ID_AA64PFR0_GIC_MASK ((U(1) << ID_AA64PFR0_GIC_WIDTH) - 1)
+#define ID_AA64PFR0_GIC_MASK ((ULL(1) << ID_AA64PFR0_GIC_WIDTH) - ULL(1))
/* ID_AA64MMFR0_EL1 definitions */
#define ID_AA64MMFR0_EL1_PARANGE_SHIFT U(0)
-#define ID_AA64MMFR0_EL1_PARANGE_MASK U(0xf)
+#define ID_AA64MMFR0_EL1_PARANGE_MASK ULL(0xf)
#define PARANGE_0000 U(32)
#define PARANGE_0001 U(36)
@@ -147,24 +147,24 @@
#define PARANGE_0110 U(52)
#define ID_AA64MMFR0_EL1_TGRAN4_SHIFT U(28)
-#define ID_AA64MMFR0_EL1_TGRAN4_MASK U(0xf)
-#define ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED U(0x0)
-#define ID_AA64MMFR0_EL1_TGRAN4_NOT_SUPPORTED U(0xf)
+#define ID_AA64MMFR0_EL1_TGRAN4_MASK ULL(0xf)
+#define ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED ULL(0x0)
+#define ID_AA64MMFR0_EL1_TGRAN4_NOT_SUPPORTED ULL(0xf)
#define ID_AA64MMFR0_EL1_TGRAN64_SHIFT U(24)
-#define ID_AA64MMFR0_EL1_TGRAN64_MASK U(0xf)
-#define ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED U(0x0)
-#define ID_AA64MMFR0_EL1_TGRAN64_NOT_SUPPORTED U(0xf)
+#define ID_AA64MMFR0_EL1_TGRAN64_MASK ULL(0xf)
+#define ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED ULL(0x0)
+#define ID_AA64MMFR0_EL1_TGRAN64_NOT_SUPPORTED ULL(0xf)
#define ID_AA64MMFR0_EL1_TGRAN16_SHIFT U(20)
-#define ID_AA64MMFR0_EL1_TGRAN16_MASK U(0xf)
-#define ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED U(0x1)
-#define ID_AA64MMFR0_EL1_TGRAN16_NOT_SUPPORTED U(0x0)
+#define ID_AA64MMFR0_EL1_TGRAN16_MASK ULL(0xf)
+#define ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED ULL(0x1)
+#define ID_AA64MMFR0_EL1_TGRAN16_NOT_SUPPORTED ULL(0x0)
/* ID_PFR1_EL1 definitions */
#define ID_PFR1_VIRTEXT_SHIFT U(12)
#define ID_PFR1_VIRTEXT_MASK U(0xf)
-#define GET_VIRT_EXT(id) ((id >> ID_PFR1_VIRTEXT_SHIFT) \
+#define GET_VIRT_EXT(id) (((id) >> ID_PFR1_VIRTEXT_SHIFT) \
& ID_PFR1_VIRTEXT_MASK)
/* SCTLR definitions */
@@ -278,9 +278,9 @@
/* HCR definitions */
#define HCR_RW_SHIFT U(31)
#define HCR_RW_BIT (ULL(1) << HCR_RW_SHIFT)
-#define HCR_AMO_BIT (U(1) << 5)
-#define HCR_IMO_BIT (U(1) << 4)
-#define HCR_FMO_BIT (U(1) << 3)
+#define HCR_AMO_BIT (ULL(1) << 5)
+#define HCR_IMO_BIT (ULL(1) << 4)
+#define HCR_FMO_BIT (ULL(1) << 3)
/* ISR definitions */
#define ISR_A_SHIFT U(8)
@@ -367,16 +367,16 @@
#define TCR_EL1_IPS_SHIFT U(32)
#define TCR_EL3_PS_SHIFT U(16)
-#define TCR_TxSZ_MIN U(16)
-#define TCR_TxSZ_MAX U(39)
+#define TCR_TxSZ_MIN ULL(16)
+#define TCR_TxSZ_MAX ULL(39)
/* (internal) physical address size bits in EL3/EL1 */
-#define TCR_PS_BITS_4GB U(0x0)
-#define TCR_PS_BITS_64GB U(0x1)
-#define TCR_PS_BITS_1TB U(0x2)
-#define TCR_PS_BITS_4TB U(0x3)
-#define TCR_PS_BITS_16TB U(0x4)
-#define TCR_PS_BITS_256TB U(0x5)
+#define TCR_PS_BITS_4GB ULL(0x0)
+#define TCR_PS_BITS_64GB ULL(0x1)
+#define TCR_PS_BITS_1TB ULL(0x2)
+#define TCR_PS_BITS_4TB ULL(0x3)
+#define TCR_PS_BITS_16TB ULL(0x4)
+#define TCR_PS_BITS_256TB ULL(0x5)
#define ADDR_MASK_48_TO_63 ULL(0xFFFF000000000000)
#define ADDR_MASK_44_TO_47 ULL(0x0000F00000000000)
@@ -385,28 +385,28 @@
#define ADDR_MASK_36_TO_39 ULL(0x000000F000000000)
#define ADDR_MASK_32_TO_35 ULL(0x0000000F00000000)
-#define TCR_RGN_INNER_NC (U(0x0) << 8)
-#define TCR_RGN_INNER_WBA (U(0x1) << 8)
-#define TCR_RGN_INNER_WT (U(0x2) << 8)
-#define TCR_RGN_INNER_WBNA (U(0x3) << 8)
+#define TCR_RGN_INNER_NC (ULL(0x0) << 8)
+#define TCR_RGN_INNER_WBA (ULL(0x1) << 8)
+#define TCR_RGN_INNER_WT (ULL(0x2) << 8)
+#define TCR_RGN_INNER_WBNA (ULL(0x3) << 8)
-#define TCR_RGN_OUTER_NC (U(0x0) << 10)
-#define TCR_RGN_OUTER_WBA (U(0x1) << 10)
-#define TCR_RGN_OUTER_WT (U(0x2) << 10)
-#define TCR_RGN_OUTER_WBNA (U(0x3) << 10)
+#define TCR_RGN_OUTER_NC (ULL(0x0) << 10)
+#define TCR_RGN_OUTER_WBA (ULL(0x1) << 10)
+#define TCR_RGN_OUTER_WT (ULL(0x2) << 10)
+#define TCR_RGN_OUTER_WBNA (ULL(0x3) << 10)
-#define TCR_SH_NON_SHAREABLE (U(0x0) << 12)
-#define TCR_SH_OUTER_SHAREABLE (U(0x2) << 12)
-#define TCR_SH_INNER_SHAREABLE (U(0x3) << 12)
+#define TCR_SH_NON_SHAREABLE (ULL(0x0) << 12)
+#define TCR_SH_OUTER_SHAREABLE (ULL(0x2) << 12)
+#define TCR_SH_INNER_SHAREABLE (ULL(0x3) << 12)
#define TCR_TG0_SHIFT U(14)
-#define TCR_TG0_MASK U(3)
+#define TCR_TG0_MASK ULL(3)
#define TCR_TG0_4K (ULL(0) << TCR_TG0_SHIFT)
#define TCR_TG0_64K (ULL(1) << TCR_TG0_SHIFT)
#define TCR_TG0_16K (ULL(2) << TCR_TG0_SHIFT)
-#define TCR_EPD0_BIT (U(1) << 7)
-#define TCR_EPD1_BIT (U(1) << 23)
+#define TCR_EPD0_BIT (ULL(1) << 7)
+#define TCR_EPD1_BIT (ULL(1) << 23)
#define MODE_SP_SHIFT U(0x0)
#define MODE_SP_MASK U(0x1)
@@ -458,7 +458,7 @@
/*
* TTBR Definitions
*/
-#define TTBR_CNP_BIT 0x1
+#define TTBR_CNP_BIT ULL(0x1)
/*
* CTR_EL0 definitions
@@ -639,15 +639,16 @@
#define MAIR_NORM_WB_NTR_RA ULL(0xe)
#define MAIR_NORM_WB_NTR_RWA ULL(0xf)
-#define MAIR_NORM_OUTER_SHIFT 4
+#define MAIR_NORM_OUTER_SHIFT U(4)
-#define MAKE_MAIR_NORMAL_MEMORY(inner, outer) ((inner) | ((outer) << MAIR_NORM_OUTER_SHIFT))
+#define MAKE_MAIR_NORMAL_MEMORY(inner, outer) \
+ ((inner) | ((outer) << MAIR_NORM_OUTER_SHIFT))
/* PAR_EL1 fields */
-#define PAR_F_SHIFT 0
-#define PAR_F_MASK 1
-#define PAR_ADDR_SHIFT 12
-#define PAR_ADDR_MASK (BIT(40) - 1) /* 40-bits-wide page address */
+#define PAR_F_SHIFT U(0)
+#define PAR_F_MASK ULL(0x1)
+#define PAR_ADDR_SHIFT U(12)
+#define PAR_ADDR_MASK (BIT(40) - ULL(1)) /* 40-bits-wide page address */
/*******************************************************************************
* Definitions for system register interface to SPE
@@ -723,10 +724,10 @@
* RAS system registers
*******************************************************************************/
#define DISR_EL1 S3_0_C12_C1_1
-#define DISR_A_BIT 31
+#define DISR_A_BIT U(31)
#define ERRIDR_EL1 S3_0_C5_C3_0
-#define ERRIDR_MASK 0xffff
+#define ERRIDR_MASK U(0xffff)
#define ERRSELR_EL1 S3_0_C5_C3_1
diff --git a/include/lib/aarch64/smccc_helpers.h b/include/lib/aarch64/smccc_helpers.h
index 1b33a0d..4d9217b 100644
--- a/include/lib/aarch64/smccc_helpers.h
+++ b/include/lib/aarch64/smccc_helpers.h
@@ -67,13 +67,6 @@
#define SMC_SET_EL3(_h, _e, _v) \
write_ctx_reg((get_el3state_ctx(_h)), (_e), (_v))
-/* Return a UUID in the SMC return registers */
-#define SMC_UUID_RET(_h, _uuid) \
- SMC_RET4(handle, ((const uint32_t *) &(_uuid))[0], \
- ((const uint32_t *) &(_uuid))[1], \
- ((const uint32_t *) &(_uuid))[2], \
- ((const uint32_t *) &(_uuid))[3])
-
/*
* Helper macro to retrieve the SMC parameters from cpu_context_t.
*/
diff --git a/include/lib/cpus/aarch32/cpu_macros.S b/include/lib/cpus/aarch32/cpu_macros.S
index 0f3a572..7703be3 100644
--- a/include/lib/cpus/aarch32/cpu_macros.S
+++ b/include/lib/cpus/aarch32/cpu_macros.S
@@ -35,38 +35,47 @@
# define REPORT_ERRATA 0
#endif
- /*
- * Define the offsets to the fields in cpu_ops structure.
- */
- .struct 0
-CPU_MIDR: /* cpu_ops midr */
- .space 4
-/* Reset fn is needed during reset */
-#if defined(IMAGE_AT_EL3)
-CPU_RESET_FUNC: /* cpu_ops reset_func */
- .space 4
+
+ .equ CPU_MIDR_SIZE, CPU_WORD_SIZE
+ .equ CPU_RESET_FUNC_SIZE, CPU_WORD_SIZE
+ .equ CPU_PWR_DWN_OPS_SIZE, CPU_WORD_SIZE * CPU_MAX_PWR_DWN_OPS
+ .equ CPU_ERRATA_FUNC_SIZE, CPU_WORD_SIZE
+ .equ CPU_ERRATA_LOCK_SIZE, CPU_WORD_SIZE
+ .equ CPU_ERRATA_PRINTED_SIZE, CPU_WORD_SIZE
+
+#ifndef IMAGE_AT_EL3
+ .equ CPU_RESET_FUNC_SIZE, 0
#endif
-#ifdef IMAGE_BL32 /* The power down core and cluster is needed only in BL32 */
-CPU_PWR_DWN_OPS: /* cpu_ops power down functions */
- .space (4 * CPU_MAX_PWR_DWN_OPS)
+
+/* The power down core and cluster is needed only in BL32 */
+#ifndef IMAGE_BL32
+ .equ CPU_PWR_DWN_OPS_SIZE, 0
#endif
+/* Fields required to print errata status */
+#if !REPORT_ERRATA
+ .equ CPU_ERRATA_FUNC_SIZE, 0
+#endif
+
+/* Only BL32 requires mutual exclusion and printed flag. */
+#if !(REPORT_ERRATA && defined(IMAGE_BL32))
+ .equ CPU_ERRATA_LOCK_SIZE, 0
+ .equ CPU_ERRATA_PRINTED_SIZE, 0
+#endif
+
+
/*
- * Fields required to print errata status. Only in BL32 that the printing
- * require mutual exclusion and printed flag.
+ * Define the offsets to the fields in cpu_ops structure.
+ * Every offset is defined based on the offset and size of the previous
+ * field.
*/
-#if REPORT_ERRATA
-CPU_ERRATA_FUNC: /* CPU errata status printing function */
- .space 4
-#if defined(IMAGE_BL32)
-CPU_ERRATA_LOCK:
- .space 4
-CPU_ERRATA_PRINTED:
- .space 4
-#endif
-#endif
-
-CPU_OPS_SIZE = .
+ .equ CPU_MIDR, 0
+ .equ CPU_RESET_FUNC, CPU_MIDR + CPU_MIDR_SIZE
+ .equ CPU_PWR_DWN_OPS, CPU_RESET_FUNC + CPU_RESET_FUNC_SIZE
+ .equ CPU_ERRATA_FUNC, CPU_PWR_DWN_OPS + CPU_PWR_DWN_OPS_SIZE
+ .equ CPU_ERRATA_LOCK, CPU_ERRATA_FUNC + CPU_ERRATA_FUNC_SIZE
+ .equ CPU_ERRATA_PRINTED, CPU_ERRATA_LOCK + CPU_ERRATA_LOCK_SIZE
+ .equ CPU_OPS_SIZE, CPU_ERRATA_PRINTED + CPU_ERRATA_PRINTED_SIZE
/*
* Write given expressions as words
@@ -128,21 +137,8 @@
.word \_resetfunc
#endif
#ifdef IMAGE_BL32
-1:
/* Insert list of functions */
fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops
-2:
- /*
- * Error if no or more than CPU_MAX_PWR_DWN_OPS were specified in the
- * list
- */
- .ifeq 2b - 1b
- .error "At least one power down function must be specified"
- .else
- .iflt 2b - 1b - (CPU_MAX_PWR_DWN_OPS * CPU_WORD_SIZE)
- .error "More than CPU_MAX_PWR_DWN_OPS functions specified"
- .endif
- .endif
#endif
#if REPORT_ERRATA
diff --git a/include/lib/cpus/aarch64/cortex_deimos.h b/include/lib/cpus/aarch64/cortex_deimos.h
new file mode 100644
index 0000000..3c36567
--- /dev/null
+++ b/include/lib/cpus/aarch64/cortex_deimos.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __CORTEX_DEIMOS_H__
+#define __CORTEX_DEIMOS_H__
+
+#define CORTEX_DEIMOS_MIDR U(0x410FD0D0)
+
+/*******************************************************************************
+ * CPU Extended Control register specific definitions.
+ ******************************************************************************/
+#define CORTEX_DEIMOS_CPUECTLR_EL1 S3_0_C15_C1_4
+
+/*******************************************************************************
+ * CPU Power Control register specific definitions.
+ ******************************************************************************/
+#define CORTEX_DEIMOS_CPUPWRCTLR_EL1 S3_0_C15_C2_7
+#define CORTEX_DEIMOS_CPUPWRCTLR_EL1_CORE_PWRDN_BIT (U(1) << 0)
+
+#endif /* __CORTEX_DEIMOS_H__ */
diff --git a/include/lib/cpus/aarch64/cortex_helios.h b/include/lib/cpus/aarch64/cortex_helios.h
new file mode 100644
index 0000000..1098a12
--- /dev/null
+++ b/include/lib/cpus/aarch64/cortex_helios.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __CORTEX_HELIOS_H__
+#define __CORTEX_HELIOS_H__
+
+#define CORTEX_HELIOS_MIDR U(0x410FD060)
+
+/*******************************************************************************
+ * CPU Extended Control register specific definitions.
+ ******************************************************************************/
+#define CORTEX_HELIOS_ECTLR_EL1 S3_0_C15_C1_4
+
+/*******************************************************************************
+ * CPU Auxiliary Control register specific definitions.
+ ******************************************************************************/
+#define CORTEX_HELIOS_CPUACTLR_EL1 S3_0_C15_C1_0
+
+/*******************************************************************************
+ * CPU Power Control register specific definitions.
+ ******************************************************************************/
+
+#define CORTEX_HELIOS_CPUPWRCTLR_EL1 S3_0_C15_C2_7
+#define CORTEX_HELIOS_CPUPWRCTLR_EL1_CORE_PWRDN_BIT (U(1) << 0)
+
+#endif /* __CORTEX_HELIOS_H__ */
diff --git a/include/lib/cpus/aarch64/cpu_macros.S b/include/lib/cpus/aarch64/cpu_macros.S
index cd8f3e8..026a48e 100644
--- a/include/lib/cpus/aarch64/cpu_macros.S
+++ b/include/lib/cpus/aarch64/cpu_macros.S
@@ -38,46 +38,56 @@
# define REPORT_ERRATA 0
#endif
- /*
- * Define the offsets to the fields in cpu_ops structure.
- */
- .struct 0
-CPU_MIDR: /* cpu_ops midr */
- .space 8
-/* Reset fn is needed in BL at reset vector */
-#if defined(IMAGE_AT_EL3)
-CPU_RESET_FUNC: /* cpu_ops reset_func */
- .space 8
+
+ .equ CPU_MIDR_SIZE, CPU_WORD_SIZE
+ .equ CPU_EXTRA1_FUNC_SIZE, CPU_WORD_SIZE
+ .equ CPU_EXTRA2_FUNC_SIZE, CPU_WORD_SIZE
+ .equ CPU_RESET_FUNC_SIZE, CPU_WORD_SIZE
+ .equ CPU_PWR_DWN_OPS_SIZE, CPU_WORD_SIZE * CPU_MAX_PWR_DWN_OPS
+ .equ CPU_ERRATA_FUNC_SIZE, CPU_WORD_SIZE
+ .equ CPU_ERRATA_LOCK_SIZE, CPU_WORD_SIZE
+ .equ CPU_ERRATA_PRINTED_SIZE, CPU_WORD_SIZE
+ .equ CPU_REG_DUMP_SIZE, CPU_WORD_SIZE
+
+#ifndef IMAGE_AT_EL3
+ .equ CPU_RESET_FUNC_SIZE, 0
#endif
-CPU_EXTRA1_FUNC:
- .space 8
-CPU_EXTRA2_FUNC:
- .space 8
-#ifdef IMAGE_BL31 /* The power down core and cluster is needed only in BL31 */
-CPU_PWR_DWN_OPS: /* cpu_ops power down functions */
- .space (8 * CPU_MAX_PWR_DWN_OPS)
+
+/* The power down core and cluster is needed only in BL31 */
+#ifndef IMAGE_BL31
+ .equ CPU_PWR_DWN_OPS_SIZE, 0
+#endif
+
+/* Fields required to print errata status. */
+#if !REPORT_ERRATA
+ .equ CPU_ERRATA_FUNC_SIZE, 0
+#endif
+
+/* Only BL31 requieres mutual exclusion and printed flag. */
+#if !(REPORT_ERRATA && defined(IMAGE_BL31))
+ .equ CPU_ERRATA_LOCK_SIZE, 0
+ .equ CPU_ERRATA_PRINTED_SIZE, 0
+#endif
+
+#if !defined(IMAGE_BL31) || !CRASH_REPORTING
+ .equ CPU_REG_DUMP_SIZE, 0
#endif
/*
- * Fields required to print errata status. Only in BL31 that the printing
- * require mutual exclusion and printed flag.
+ * Define the offsets to the fields in cpu_ops structure.
+ * Every offset is defined based in the offset and size of the previous
+ * field.
*/
-#if REPORT_ERRATA
-CPU_ERRATA_FUNC:
- .space 8
-#if defined(IMAGE_BL31)
-CPU_ERRATA_LOCK:
- .space 8
-CPU_ERRATA_PRINTED:
- .space 8
-#endif
-#endif
-
-#if defined(IMAGE_BL31) && CRASH_REPORTING
-CPU_REG_DUMP: /* cpu specific register dump for crash reporting */
- .space 8
-#endif
-CPU_OPS_SIZE = .
+ .equ CPU_MIDR, 0
+ .equ CPU_RESET_FUNC, CPU_MIDR + CPU_MIDR_SIZE
+ .equ CPU_EXTRA1_FUNC, CPU_RESET_FUNC + CPU_RESET_FUNC_SIZE
+ .equ CPU_EXTRA2_FUNC, CPU_EXTRA1_FUNC + CPU_EXTRA1_FUNC_SIZE
+ .equ CPU_PWR_DWN_OPS, CPU_EXTRA2_FUNC + CPU_EXTRA2_FUNC_SIZE
+ .equ CPU_ERRATA_FUNC, CPU_PWR_DWN_OPS + CPU_PWR_DWN_OPS_SIZE
+ .equ CPU_ERRATA_LOCK, CPU_ERRATA_FUNC + CPU_ERRATA_FUNC_SIZE
+ .equ CPU_ERRATA_PRINTED, CPU_ERRATA_LOCK + CPU_ERRATA_LOCK_SIZE
+ .equ CPU_REG_DUMP, CPU_ERRATA_PRINTED + CPU_ERRATA_PRINTED_SIZE
+ .equ CPU_OPS_SIZE, CPU_REG_DUMP + CPU_REG_DUMP_SIZE
/*
* Write given expressions as quad words
@@ -149,21 +159,8 @@
.quad \_extra1
.quad \_extra2
#ifdef IMAGE_BL31
-1:
/* Insert list of functions */
fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops
-2:
- /*
- * Error if no or more than CPU_MAX_PWR_DWN_OPS were specified in the
- * list
- */
- .ifeq 2b - 1b
- .error "At least one power down function must be specified"
- .else
- .iflt 2b - 1b - (CPU_MAX_PWR_DWN_OPS * CPU_WORD_SIZE)
- .error "More than CPU_MAX_PWR_DWN_OPS functions specified"
- .endif
- .endif
#endif
#if REPORT_ERRATA
diff --git a/include/lib/smccc.h b/include/lib/smccc.h
index cb722b0..a07e510 100644
--- a/include/lib/smccc.h
+++ b/include/lib/smccc.h
@@ -84,5 +84,32 @@
{ _n0, _n1, _n2, _n3, _n4, _n5 } \
}
+/*
+ * Return a UUID in the SMC return registers.
+ *
+ * Acccording to section 5.3 of the SMCCC, UUIDs are returned as a single
+ * 128-bit value using the SMC32 calling convention. This value is mapped to
+ * argument registers x0-x3 on AArch64 (resp. r0-r3 on AArch32). x0 for example
+ * shall hold bytes 0 to 3, with byte 0 in the low-order bits.
+ */
+static inline uint32_t smc_uuid_word(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3)
+{
+ return ((uint32_t) b0) | (((uint32_t) b1) << 8) |
+ (((uint32_t) b2) << 16) | (((uint32_t) b3) << 24);
+}
+
+#define SMC_UUID_RET(_h, _uuid) \
+ SMC_RET4(handle, \
+ smc_uuid_word((_uuid).time_low[0], (_uuid).time_low[1], \
+ (_uuid).time_low[2], (_uuid).time_low[3]), \
+ smc_uuid_word((_uuid).time_mid[0], (_uuid).time_mid[1], \
+ (_uuid).time_hi_and_version[0], \
+ (_uuid).time_hi_and_version[1]), \
+ smc_uuid_word((_uuid).clock_seq_hi_and_reserved, \
+ (_uuid).clock_seq_low, (_uuid).node[0], \
+ (_uuid).node[1]), \
+ smc_uuid_word((_uuid).node[2], (_uuid).node[3], \
+ (_uuid).node[4], (_uuid).node[5]))
+
#endif /*__ASSEMBLY__*/
#endif /* __SMCCC_H__ */
diff --git a/include/lib/utils.h b/include/lib/utils.h
index f367a1f..5f13e99 100644
--- a/include/lib/utils.h
+++ b/include/lib/utils.h
@@ -37,10 +37,10 @@
* in a way that they minimize the number of entries used in the
* translation tables.
*/
-void clear_map_dyn_mem_regions(mem_region_t *region,
+void clear_map_dyn_mem_regions(struct mem_region *regions,
size_t nregions,
uintptr_t va,
- size_t chunk_size);
+ size_t chunk);
/*
* checks that a region (addr + nbytes-1) of memory is totally covered by
diff --git a/include/lib/xlat_tables/xlat_mmu_helpers.h b/include/lib/xlat_tables/xlat_mmu_helpers.h
index b6c53e2..a290a92 100644
--- a/include/lib/xlat_tables/xlat_mmu_helpers.h
+++ b/include/lib/xlat_tables/xlat_mmu_helpers.h
@@ -41,10 +41,28 @@
*/
#define XLAT_TABLE_NC (U(1) << 1)
+/*
+ * Offsets into a mmu_cfg_params array generated by setup_mmu_cfg(). All
+ * parameters are 64 bits wide.
+ */
+#define MMU_CFG_MAIR 0
+#define MMU_CFG_TCR 1
+#define MMU_CFG_TTBR0 2
+#define MMU_CFG_PARAM_MAX 3
+
#ifndef __ASSEMBLY__
#include <sys/types.h>
+/*
+ * Return the values that the MMU configuration registers must contain for the
+ * specified translation context. `params` must be a pointer to array of size
+ * MMU_CFG_PARAM_MAX.
+ */
+void setup_mmu_cfg(uint64_t *params, unsigned int flags,
+ const uint64_t *base_table, unsigned long long max_pa,
+ uintptr_t max_va, int xlat_regime);
+
#ifdef AARCH32
/* AArch32 specific translation table API */
void enable_mmu_secure(unsigned int flags);
diff --git a/include/lib/xlat_tables/xlat_tables_defs.h b/include/lib/xlat_tables/xlat_tables_defs.h
index 5eb1d30..c9d5417 100644
--- a/include/lib/xlat_tables/xlat_tables_defs.h
+++ b/include/lib/xlat_tables/xlat_tables_defs.h
@@ -62,7 +62,7 @@
/*
* The ARMv8-A architecture allows translation granule sizes of 4KB, 16KB or
- * 64KB. However, TF only supports the 4KB case at the moment.
+ * 64KB. However, only 4KB are supported at the moment.
*/
#define PAGE_SIZE_SHIFT FOUR_KB_SHIFT
#define PAGE_SIZE (U(1) << PAGE_SIZE_SHIFT)
diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h
index 4dc2c5e..2e5aba5 100644
--- a/include/lib/xlat_tables/xlat_tables_v2.h
+++ b/include/lib/xlat_tables/xlat_tables_v2.h
@@ -121,12 +121,12 @@
} mmap_region_t;
/*
- * Translation regimes supported by this library.
+ * Translation regimes supported by this library. EL_REGIME_INVALID tells the
+ * library to detect it at runtime.
*/
-typedef enum xlat_regime {
- EL1_EL0_REGIME,
- EL3_REGIME,
-} xlat_regime_t;
+#define EL1_EL0_REGIME 1
+#define EL3_REGIME 3
+#define EL_REGIME_INVALID -1
/*
* Declare the translation context type.
@@ -161,34 +161,33 @@
* (resp. PLAT_PHY_ADDR_SPACE_SIZE) for the translation context describing the
* BL image currently executing.
*/
-#define REGISTER_XLAT_CONTEXT(_ctx_name, _mmap_count, _xlat_tables_count, \
- _virt_addr_space_size, _phy_addr_space_size) \
- _REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count, \
- _xlat_tables_count, \
- _virt_addr_space_size, \
- _phy_addr_space_size, \
- IMAGE_XLAT_DEFAULT_REGIME, \
- "xlat_table")
+#define REGISTER_XLAT_CONTEXT(_ctx_name, _mmap_count, _xlat_tables_count, \
+ _virt_addr_space_size, _phy_addr_space_size) \
+ _REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, (_mmap_count), \
+ (_xlat_tables_count), \
+ (_virt_addr_space_size), \
+ (_phy_addr_space_size), \
+ EL_REGIME_INVALID, "xlat_table")
/*
* Same as REGISTER_XLAT_CONTEXT plus the additional parameters:
*
* _xlat_regime:
* Specify the translation regime managed by this xlat_ctx_t instance. The
- * values are the one from xlat_regime_t enumeration.
+ * values are the one from the EL*_REGIME definitions.
*
* _section_name:
* Specify the name of the section where the translation tables have to be
* placed by the linker.
*/
-#define REGISTER_XLAT_CONTEXT2(_ctx_name, _mmap_count, _xlat_tables_count, \
- _virt_addr_space_size, _phy_addr_space_size, \
- _xlat_regime, _section_name) \
- _REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count, \
- _xlat_tables_count, \
- _virt_addr_space_size, \
- _phy_addr_space_size, \
- _xlat_regime, _section_name)
+#define REGISTER_XLAT_CONTEXT2(_ctx_name, _mmap_count, _xlat_tables_count, \
+ _virt_addr_space_size, _phy_addr_space_size, \
+ _xlat_regime, _section_name) \
+ _REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, (_mmap_count), \
+ (_xlat_tables_count), \
+ (_virt_addr_space_size), \
+ (_phy_addr_space_size), \
+ (_xlat_regime), (_section_name))
/******************************************************************************
* Generic translation table APIs.
diff --git a/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
index e1ea2b6..82d96e7 100644
--- a/include/lib/xlat_tables/xlat_tables_v2_helpers.h
+++ b/include/lib/xlat_tables/xlat_tables_v2_helpers.h
@@ -16,13 +16,6 @@
#error "Do not include this header file directly. Include xlat_tables_v2.h instead."
#endif
-/* Offsets into mmu_cfg_params array. All parameters are 32 bits wide. */
-#define MMU_CFG_MAIR0 0
-#define MMU_CFG_TCR 1
-#define MMU_CFG_TTBR0_LO 2
-#define MMU_CFG_TTBR0_HI 3
-#define MMU_CFG_PARAM_MAX 4
-
#ifndef __ASSEMBLY__
#include <cassert.h>
@@ -31,9 +24,6 @@
#include <xlat_tables_arch.h>
#include <xlat_tables_defs.h>
-/* Parameters of register values required when enabling MMU */
-extern uint32_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
-
/* Forward declaration */
struct mmap_region;
@@ -109,10 +99,8 @@
unsigned int initialized;
/*
- * Translation regime managed by this xlat_ctx_t. It takes the values of
- * the enumeration xlat_regime_t. The type is "int" to avoid a circular
- * dependency on xlat_tables_v2.h, but this member must be treated as
- * xlat_regime_t.
+ * Translation regime managed by this xlat_ctx_t. It should be one of
+ * the EL*_REGIME defines.
*/
int xlat_regime;
};
@@ -157,7 +145,7 @@
.va_max_address = (_virt_addr_space_size) - 1, \
.pa_max_address = (_phy_addr_space_size) - 1, \
.mmap = _ctx_name##_mmap, \
- .mmap_num = _mmap_count, \
+ .mmap_num = (_mmap_count), \
.base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size), \
.base_table = _ctx_name##_base_xlat_table, \
.base_table_entries = \
@@ -174,29 +162,4 @@
#endif /*__ASSEMBLY__*/
-#if AARCH64
-
-/*
- * This IMAGE_EL macro must not to be used outside the library, and it is only
- * used in AArch64.
- */
-#if defined(IMAGE_BL1) || defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3)
-# define IMAGE_EL 3
-# define IMAGE_XLAT_DEFAULT_REGIME EL3_REGIME
-#else
-# define IMAGE_EL 1
-# define IMAGE_XLAT_DEFAULT_REGIME EL1_EL0_REGIME
-#endif
-
-#else /* if AARCH32 */
-
-/*
- * The PL1&0 translation regime in AArch32 behaves like the EL1&0 regime in
- * AArch64 except for the XN bits, but we set and unset them at the same time,
- * so there's no difference in practice.
- */
-#define IMAGE_XLAT_DEFAULT_REGIME EL1_EL0_REGIME
-
-#endif /* AARCH64 */
-
#endif /* __XLAT_TABLES_V2_HELPERS_H__ */
diff --git a/include/plat/arm/common/aarch64/arm_macros.S b/include/plat/arm/common/aarch64/arm_macros.S
index 12bf734..7953d7e 100644
--- a/include/plat/arm/common/aarch64/arm_macros.S
+++ b/include/plat/arm/common/aarch64/arm_macros.S
@@ -22,8 +22,7 @@
/* Registers common to both GICv2 and GICv3 */
gicd_pend_reg:
- .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n" \
- " Offset:\t\t\tvalue\n"
+ .asciz "gicd_ispendr regs (Offsets 0x200 - 0x278)\n Offset:\t\t\tvalue\n"
newline:
.asciz "\n"
spacer:
diff --git a/include/plat/arm/common/arm_common.ld.S b/include/plat/arm/common/arm_common.ld.S
index 6edfa09..3f6e29b 100644
--- a/include/plat/arm/common/arm_common.ld.S
+++ b/include/plat/arm/common/arm_common.ld.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -22,7 +22,7 @@
*(arm_el3_tzc_dram)
__EL3_SEC_DRAM_UNALIGNED_END__ = .;
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__EL3_SEC_DRAM_END__ = .;
} >EL3_SEC_DRAM
}
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index 33f2c7d..42bbf38 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -86,7 +86,7 @@
* Use this macro to instantiate lock before it is used in below
* arm_lock_xxx() macros
*/
-#define ARM_INSTANTIATE_LOCK DEFINE_BAKERY_LOCK(arm_lock)
+#define ARM_INSTANTIATE_LOCK static DEFINE_BAKERY_LOCK(arm_lock)
#define ARM_LOCK_GET_INSTANCE (&arm_lock)
/*
* These are wrapper macros to the Coherent Memory Bakery Lock API.
@@ -171,7 +171,6 @@
int arm_validate_ns_entrypoint(uintptr_t entrypoint);
void arm_system_pwr_domain_save(void);
void arm_system_pwr_domain_resume(void);
-void arm_program_trusted_mailbox(uintptr_t address);
int arm_psci_read_mem_protect(int *enabled);
int arm_nor_psci_write_mem_protect(int val);
void arm_nor_psci_do_static_mem_protect(void);
@@ -250,6 +249,7 @@
void plat_arm_interconnect_init(void);
void plat_arm_interconnect_enter_coherency(void);
void plat_arm_interconnect_exit_coherency(void);
+void plat_arm_program_trusted_mailbox(uintptr_t address);
#if ARM_PLAT_MT
unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr);
diff --git a/lib/cpus/aarch64/cortex_a76.S b/lib/cpus/aarch64/cortex_a76.S
index 14705d7..51d0b15 100644
--- a/lib/cpus/aarch64/cortex_a76.S
+++ b/lib/cpus/aarch64/cortex_a76.S
@@ -107,19 +107,19 @@
*/
vector_entry cortex_a76_sync_exception_sp_el0
b sync_exception_sp_el0
- check_vector_size cortex_a76_sync_exception_sp_el0
+end_vector_entry cortex_a76_sync_exception_sp_el0
vector_entry cortex_a76_irq_sp_el0
b irq_sp_el0
- check_vector_size cortex_a76_irq_sp_el0
+end_vector_entry cortex_a76_irq_sp_el0
vector_entry cortex_a76_fiq_sp_el0
b fiq_sp_el0
- check_vector_size cortex_a76_fiq_sp_el0
+end_vector_entry cortex_a76_fiq_sp_el0
vector_entry cortex_a76_serror_sp_el0
b serror_sp_el0
- check_vector_size cortex_a76_serror_sp_el0
+end_vector_entry cortex_a76_serror_sp_el0
/* ---------------------------------------------------------------------
* Current EL with SP_ELx: 0x200 - 0x400
@@ -127,19 +127,19 @@
*/
vector_entry cortex_a76_sync_exception_sp_elx
b sync_exception_sp_elx
- check_vector_size cortex_a76_sync_exception_sp_elx
+end_vector_entry cortex_a76_sync_exception_sp_elx
vector_entry cortex_a76_irq_sp_elx
b irq_sp_elx
- check_vector_size cortex_a76_irq_sp_elx
+end_vector_entry cortex_a76_irq_sp_elx
vector_entry cortex_a76_fiq_sp_elx
b fiq_sp_elx
- check_vector_size cortex_a76_fiq_sp_elx
+end_vector_entry cortex_a76_fiq_sp_elx
vector_entry cortex_a76_serror_sp_elx
b serror_sp_elx
- check_vector_size cortex_a76_serror_sp_elx
+end_vector_entry cortex_a76_serror_sp_elx
/* ---------------------------------------------------------------------
* Lower EL using AArch64 : 0x400 - 0x600
@@ -148,22 +148,22 @@
vector_entry cortex_a76_sync_exception_aarch64
apply_cve_2018_3639_wa _is_sync_exception=1 _esr_el3_val=ESR_EL3_A64_SMC0
b sync_exception_aarch64
- check_vector_size cortex_a76_sync_exception_aarch64
+end_vector_entry cortex_a76_sync_exception_aarch64
vector_entry cortex_a76_irq_aarch64
apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0
b irq_aarch64
- check_vector_size cortex_a76_irq_aarch64
+end_vector_entry cortex_a76_irq_aarch64
vector_entry cortex_a76_fiq_aarch64
apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0
b fiq_aarch64
- check_vector_size cortex_a76_fiq_aarch64
+end_vector_entry cortex_a76_fiq_aarch64
vector_entry cortex_a76_serror_aarch64
apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0
b serror_aarch64
- check_vector_size cortex_a76_serror_aarch64
+end_vector_entry cortex_a76_serror_aarch64
/* ---------------------------------------------------------------------
* Lower EL using AArch32 : 0x600 - 0x800
@@ -172,22 +172,22 @@
vector_entry cortex_a76_sync_exception_aarch32
apply_cve_2018_3639_wa _is_sync_exception=1 _esr_el3_val=ESR_EL3_A32_SMC0
b sync_exception_aarch32
- check_vector_size cortex_a76_sync_exception_aarch32
+end_vector_entry cortex_a76_sync_exception_aarch32
vector_entry cortex_a76_irq_aarch32
apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0
b irq_aarch32
- check_vector_size cortex_a76_irq_aarch32
+end_vector_entry cortex_a76_irq_aarch32
vector_entry cortex_a76_fiq_aarch32
apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0
b fiq_aarch32
- check_vector_size cortex_a76_fiq_aarch32
+end_vector_entry cortex_a76_fiq_aarch32
vector_entry cortex_a76_serror_aarch32
apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0
b serror_aarch32
- check_vector_size cortex_a76_serror_aarch32
+end_vector_entry cortex_a76_serror_aarch32
func check_errata_cve_2018_3639
#if WORKAROUND_CVE_2018_3639
diff --git a/lib/cpus/aarch64/cortex_deimos.S b/lib/cpus/aarch64/cortex_deimos.S
new file mode 100644
index 0000000..aec62a2
--- /dev/null
+++ b/lib/cpus/aarch64/cortex_deimos.S
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl_common.h>
+#include <cortex_deimos.h>
+#include <cpu_macros.S>
+#include <plat_macros.S>
+
+ /* ---------------------------------------------
+ * HW will do the cache maintenance while powering down
+ * ---------------------------------------------
+ */
+func cortex_deimos_core_pwr_dwn
+ /* ---------------------------------------------
+ * Enable CPU power down bit in power control register
+ * ---------------------------------------------
+ */
+ mrs x0, CORTEX_DEIMOS_CPUPWRCTLR_EL1
+ orr x0, x0, #CORTEX_DEIMOS_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
+ msr CORTEX_DEIMOS_CPUPWRCTLR_EL1, x0
+ isb
+ ret
+endfunc cortex_deimos_core_pwr_dwn
+
+ /* ---------------------------------------------
+ * This function provides Cortex-Deimos specific
+ * register information for crash reporting.
+ * It needs to return with x6 pointing to
+ * a list of register names in ascii and
+ * x8 - x15 having values of registers to be
+ * reported.
+ * ---------------------------------------------
+ */
+.section .rodata.cortex_deimos_regs, "aS"
+cortex_deimos_regs: /* The ascii list of register names to be reported */
+ .asciz "cpuectlr_el1", ""
+
+func cortex_deimos_cpu_reg_dump
+ adr x6, cortex_deimos_regs
+ mrs x8, CORTEX_DEIMOS_CPUECTLR_EL1
+ ret
+endfunc cortex_deimos_cpu_reg_dump
+
+declare_cpu_ops cortex_deimos, CORTEX_DEIMOS_MIDR, \
+ CPU_NO_RESET_FUNC, \
+ cortex_deimos_core_pwr_dwn
diff --git a/lib/cpus/aarch64/cortex_helios.S b/lib/cpus/aarch64/cortex_helios.S
new file mode 100644
index 0000000..bcda741
--- /dev/null
+++ b/lib/cpus/aarch64/cortex_helios.S
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <arch.h>
+#include <asm_macros.S>
+#include <bl_common.h>
+#include <cortex_helios.h>
+#include <cpu_macros.S>
+#include <debug.h>
+#include <plat_macros.S>
+
+func cortex_helios_cpu_pwr_dwn
+ mrs x0, CORTEX_HELIOS_CPUPWRCTLR_EL1
+ orr x0, x0, #CORTEX_HELIOS_CPUPWRCTLR_EL1_CORE_PWRDN_BIT
+ msr CORTEX_HELIOS_CPUPWRCTLR_EL1, x0
+ isb
+ ret
+endfunc cortex_helios_cpu_pwr_dwn
+
+.section .rodata.cortex_helios_regs, "aS"
+cortex_helios_regs: /* The ascii list of register names to be reported */
+ .asciz "cpuectlr_el1", ""
+
+func cortex_helios_cpu_reg_dump
+ adr x6, cortex_helios_regs
+ mrs x8, CORTEX_HELIOS_ECTLR_EL1
+ ret
+endfunc cortex_helios_cpu_reg_dump
+
+declare_cpu_ops cortex_helios, CORTEX_HELIOS_MIDR, \
+ CPU_NO_RESET_FUNC, \
+ cortex_helios_cpu_pwr_dwn
diff --git a/lib/cpus/aarch64/denver.S b/lib/cpus/aarch64/denver.S
index aee4fee..f04dbd6 100644
--- a/lib/cpus/aarch64/denver.S
+++ b/lib/cpus/aarch64/denver.S
@@ -55,19 +55,19 @@
*/
vector_entry workaround_bpflush_sync_exception_sp_el0
b sync_exception_sp_el0
- check_vector_size workaround_bpflush_sync_exception_sp_el0
+end_vector_entry workaround_bpflush_sync_exception_sp_el0
vector_entry workaround_bpflush_irq_sp_el0
b irq_sp_el0
- check_vector_size workaround_bpflush_irq_sp_el0
+end_vector_entry workaround_bpflush_irq_sp_el0
vector_entry workaround_bpflush_fiq_sp_el0
b fiq_sp_el0
- check_vector_size workaround_bpflush_fiq_sp_el0
+end_vector_entry workaround_bpflush_fiq_sp_el0
vector_entry workaround_bpflush_serror_sp_el0
b serror_sp_el0
- check_vector_size workaround_bpflush_serror_sp_el0
+end_vector_entry workaround_bpflush_serror_sp_el0
/* ---------------------------------------------------------------------
* Current EL with SP_ELx: 0x200 - 0x400
@@ -75,19 +75,19 @@
*/
vector_entry workaround_bpflush_sync_exception_sp_elx
b sync_exception_sp_elx
- check_vector_size workaround_bpflush_sync_exception_sp_elx
+end_vector_entry workaround_bpflush_sync_exception_sp_elx
vector_entry workaround_bpflush_irq_sp_elx
b irq_sp_elx
- check_vector_size workaround_bpflush_irq_sp_elx
+end_vector_entry workaround_bpflush_irq_sp_elx
vector_entry workaround_bpflush_fiq_sp_elx
b fiq_sp_elx
- check_vector_size workaround_bpflush_fiq_sp_elx
+end_vector_entry workaround_bpflush_fiq_sp_elx
vector_entry workaround_bpflush_serror_sp_elx
b serror_sp_elx
- check_vector_size workaround_bpflush_serror_sp_elx
+end_vector_entry workaround_bpflush_serror_sp_elx
/* ---------------------------------------------------------------------
* Lower EL using AArch64 : 0x400 - 0x600
@@ -96,22 +96,22 @@
vector_entry workaround_bpflush_sync_exception_aarch64
apply_workaround
b sync_exception_aarch64
- check_vector_size workaround_bpflush_sync_exception_aarch64
+end_vector_entry workaround_bpflush_sync_exception_aarch64
vector_entry workaround_bpflush_irq_aarch64
apply_workaround
b irq_aarch64
- check_vector_size workaround_bpflush_irq_aarch64
+end_vector_entry workaround_bpflush_irq_aarch64
vector_entry workaround_bpflush_fiq_aarch64
apply_workaround
b fiq_aarch64
- check_vector_size workaround_bpflush_fiq_aarch64
+end_vector_entry workaround_bpflush_fiq_aarch64
vector_entry workaround_bpflush_serror_aarch64
apply_workaround
b serror_aarch64
- check_vector_size workaround_bpflush_serror_aarch64
+end_vector_entry workaround_bpflush_serror_aarch64
/* ---------------------------------------------------------------------
* Lower EL using AArch32 : 0x600 - 0x800
@@ -120,22 +120,22 @@
vector_entry workaround_bpflush_sync_exception_aarch32
apply_workaround
b sync_exception_aarch32
- check_vector_size workaround_bpflush_sync_exception_aarch32
+end_vector_entry workaround_bpflush_sync_exception_aarch32
vector_entry workaround_bpflush_irq_aarch32
apply_workaround
b irq_aarch32
- check_vector_size workaround_bpflush_irq_aarch32
+end_vector_entry workaround_bpflush_irq_aarch32
vector_entry workaround_bpflush_fiq_aarch32
apply_workaround
b fiq_aarch32
- check_vector_size workaround_bpflush_fiq_aarch32
+end_vector_entry workaround_bpflush_fiq_aarch32
vector_entry workaround_bpflush_serror_aarch32
apply_workaround
b serror_aarch32
- check_vector_size workaround_bpflush_serror_aarch32
+end_vector_entry workaround_bpflush_serror_aarch32
.global denver_disable_dco
diff --git a/lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S b/lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S
index 8437155..c613ebd 100644
--- a/lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S
+++ b/lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S
@@ -114,19 +114,19 @@
.word EMIT_BPIALL
.word EMIT_SMC
- check_vector_size bpiall_sync_exception_sp_el0
+end_vector_entry bpiall_sync_exception_sp_el0
vector_entry bpiall_irq_sp_el0
b irq_sp_el0
- check_vector_size bpiall_irq_sp_el0
+end_vector_entry bpiall_irq_sp_el0
vector_entry bpiall_fiq_sp_el0
b fiq_sp_el0
- check_vector_size bpiall_fiq_sp_el0
+end_vector_entry bpiall_fiq_sp_el0
vector_entry bpiall_serror_sp_el0
b serror_sp_el0
- check_vector_size bpiall_serror_sp_el0
+end_vector_entry bpiall_serror_sp_el0
/* ---------------------------------------------------------------------
* Current EL with SP_ELx: 0x200 - 0x400
@@ -134,19 +134,19 @@
*/
vector_entry bpiall_sync_exception_sp_elx
b sync_exception_sp_elx
- check_vector_size bpiall_sync_exception_sp_elx
+end_vector_entry bpiall_sync_exception_sp_elx
vector_entry bpiall_irq_sp_elx
b irq_sp_elx
- check_vector_size bpiall_irq_sp_elx
+end_vector_entry bpiall_irq_sp_elx
vector_entry bpiall_fiq_sp_elx
b fiq_sp_elx
- check_vector_size bpiall_fiq_sp_elx
+end_vector_entry bpiall_fiq_sp_elx
vector_entry bpiall_serror_sp_elx
b serror_sp_elx
- check_vector_size bpiall_serror_sp_elx
+end_vector_entry bpiall_serror_sp_elx
/* ---------------------------------------------------------------------
* Lower EL using AArch64 : 0x400 - 0x600
@@ -154,19 +154,19 @@
*/
vector_entry bpiall_sync_exception_aarch64
apply_cve_2017_5715_wa 1
- check_vector_size bpiall_sync_exception_aarch64
+end_vector_entry bpiall_sync_exception_aarch64
vector_entry bpiall_irq_aarch64
apply_cve_2017_5715_wa 2
- check_vector_size bpiall_irq_aarch64
+end_vector_entry bpiall_irq_aarch64
vector_entry bpiall_fiq_aarch64
apply_cve_2017_5715_wa 4
- check_vector_size bpiall_fiq_aarch64
+end_vector_entry bpiall_fiq_aarch64
vector_entry bpiall_serror_aarch64
apply_cve_2017_5715_wa 8
- check_vector_size bpiall_serror_aarch64
+end_vector_entry bpiall_serror_aarch64
/* ---------------------------------------------------------------------
* Lower EL using AArch32 : 0x600 - 0x800
@@ -174,19 +174,19 @@
*/
vector_entry bpiall_sync_exception_aarch32
apply_cve_2017_5715_wa 1
- check_vector_size bpiall_sync_exception_aarch32
+end_vector_entry bpiall_sync_exception_aarch32
vector_entry bpiall_irq_aarch32
apply_cve_2017_5715_wa 2
- check_vector_size bpiall_irq_aarch32
+end_vector_entry bpiall_irq_aarch32
vector_entry bpiall_fiq_aarch32
apply_cve_2017_5715_wa 4
- check_vector_size bpiall_fiq_aarch32
+end_vector_entry bpiall_fiq_aarch32
vector_entry bpiall_serror_aarch32
apply_cve_2017_5715_wa 8
- check_vector_size bpiall_serror_aarch32
+end_vector_entry bpiall_serror_aarch32
/* ---------------------------------------------------------------------
* This vector table is used while the workaround is executing. It
@@ -203,19 +203,19 @@
*/
vector_entry bpiall_ret_sync_exception_sp_el0
b report_unhandled_exception
- check_vector_size bpiall_ret_sync_exception_sp_el0
+end_vector_entry bpiall_ret_sync_exception_sp_el0
vector_entry bpiall_ret_irq_sp_el0
b report_unhandled_interrupt
- check_vector_size bpiall_ret_irq_sp_el0
+end_vector_entry bpiall_ret_irq_sp_el0
vector_entry bpiall_ret_fiq_sp_el0
b report_unhandled_interrupt
- check_vector_size bpiall_ret_fiq_sp_el0
+end_vector_entry bpiall_ret_fiq_sp_el0
vector_entry bpiall_ret_serror_sp_el0
b report_unhandled_exception
- check_vector_size bpiall_ret_serror_sp_el0
+end_vector_entry bpiall_ret_serror_sp_el0
/* ---------------------------------------------------------------------
* Current EL with SP_ELx: 0x200 - 0x400 (UNUSED)
@@ -223,19 +223,19 @@
*/
vector_entry bpiall_ret_sync_exception_sp_elx
b report_unhandled_exception
- check_vector_size bpiall_ret_sync_exception_sp_elx
+end_vector_entry bpiall_ret_sync_exception_sp_elx
vector_entry bpiall_ret_irq_sp_elx
b report_unhandled_interrupt
- check_vector_size bpiall_ret_irq_sp_elx
+end_vector_entry bpiall_ret_irq_sp_elx
vector_entry bpiall_ret_fiq_sp_elx
b report_unhandled_interrupt
- check_vector_size bpiall_ret_fiq_sp_elx
+end_vector_entry bpiall_ret_fiq_sp_elx
vector_entry bpiall_ret_serror_sp_elx
b report_unhandled_exception
- check_vector_size bpiall_ret_serror_sp_elx
+end_vector_entry bpiall_ret_serror_sp_elx
/* ---------------------------------------------------------------------
* Lower EL using AArch64 : 0x400 - 0x600 (UNUSED)
@@ -243,19 +243,19 @@
*/
vector_entry bpiall_ret_sync_exception_aarch64
b report_unhandled_exception
- check_vector_size bpiall_ret_sync_exception_aarch64
+end_vector_entry bpiall_ret_sync_exception_aarch64
vector_entry bpiall_ret_irq_aarch64
b report_unhandled_interrupt
- check_vector_size bpiall_ret_irq_aarch64
+end_vector_entry bpiall_ret_irq_aarch64
vector_entry bpiall_ret_fiq_aarch64
b report_unhandled_interrupt
- check_vector_size bpiall_ret_fiq_aarch64
+end_vector_entry bpiall_ret_fiq_aarch64
vector_entry bpiall_ret_serror_aarch64
b report_unhandled_exception
- check_vector_size bpiall_ret_serror_aarch64
+end_vector_entry bpiall_ret_serror_aarch64
/* ---------------------------------------------------------------------
* Lower EL using AArch32 : 0x600 - 0x800
@@ -324,7 +324,7 @@
1:
ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
b sync_exception_aarch64
- check_vector_size bpiall_ret_sync_exception_aarch32
+end_vector_entry bpiall_ret_sync_exception_aarch32
vector_entry bpiall_ret_irq_aarch32
b report_unhandled_interrupt
@@ -346,12 +346,12 @@
bpiall_ret_serror:
ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2]
b serror_aarch64
- check_vector_size bpiall_ret_irq_aarch32
+end_vector_entry bpiall_ret_irq_aarch32
vector_entry bpiall_ret_fiq_aarch32
b report_unhandled_interrupt
- check_vector_size bpiall_ret_fiq_aarch32
+end_vector_entry bpiall_ret_fiq_aarch32
vector_entry bpiall_ret_serror_aarch32
b report_unhandled_exception
- check_vector_size bpiall_ret_serror_aarch32
+end_vector_entry bpiall_ret_serror_aarch32
diff --git a/lib/cpus/aarch64/wa_cve_2017_5715_mmu.S b/lib/cpus/aarch64/wa_cve_2017_5715_mmu.S
index a556d1f..d7b6e26 100644
--- a/lib/cpus/aarch64/wa_cve_2017_5715_mmu.S
+++ b/lib/cpus/aarch64/wa_cve_2017_5715_mmu.S
@@ -66,19 +66,19 @@
*/
vector_entry mmu_sync_exception_sp_el0
b sync_exception_sp_el0
- check_vector_size mmu_sync_exception_sp_el0
+end_vector_entry mmu_sync_exception_sp_el0
vector_entry mmu_irq_sp_el0
b irq_sp_el0
- check_vector_size mmu_irq_sp_el0
+end_vector_entry mmu_irq_sp_el0
vector_entry mmu_fiq_sp_el0
b fiq_sp_el0
- check_vector_size mmu_fiq_sp_el0
+end_vector_entry mmu_fiq_sp_el0
vector_entry mmu_serror_sp_el0
b serror_sp_el0
- check_vector_size mmu_serror_sp_el0
+end_vector_entry mmu_serror_sp_el0
/* ---------------------------------------------------------------------
* Current EL with SP_ELx: 0x200 - 0x400
@@ -86,19 +86,19 @@
*/
vector_entry mmu_sync_exception_sp_elx
b sync_exception_sp_elx
- check_vector_size mmu_sync_exception_sp_elx
+end_vector_entry mmu_sync_exception_sp_elx
vector_entry mmu_irq_sp_elx
b irq_sp_elx
- check_vector_size mmu_irq_sp_elx
+end_vector_entry mmu_irq_sp_elx
vector_entry mmu_fiq_sp_elx
b fiq_sp_elx
- check_vector_size mmu_fiq_sp_elx
+end_vector_entry mmu_fiq_sp_elx
vector_entry mmu_serror_sp_elx
b serror_sp_elx
- check_vector_size mmu_serror_sp_elx
+end_vector_entry mmu_serror_sp_elx
/* ---------------------------------------------------------------------
* Lower EL using AArch64 : 0x400 - 0x600
@@ -107,22 +107,22 @@
vector_entry mmu_sync_exception_aarch64
apply_cve_2017_5715_wa _is_sync_exception=1 _esr_el3_val=ESR_EL3_A64_SMC0
b sync_exception_aarch64
- check_vector_size mmu_sync_exception_aarch64
+end_vector_entry mmu_sync_exception_aarch64
vector_entry mmu_irq_aarch64
apply_cve_2017_5715_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0
b irq_aarch64
- check_vector_size mmu_irq_aarch64
+end_vector_entry mmu_irq_aarch64
vector_entry mmu_fiq_aarch64
apply_cve_2017_5715_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0
b fiq_aarch64
- check_vector_size mmu_fiq_aarch64
+end_vector_entry mmu_fiq_aarch64
vector_entry mmu_serror_aarch64
apply_cve_2017_5715_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0
b serror_aarch64
- check_vector_size mmu_serror_aarch64
+end_vector_entry mmu_serror_aarch64
/* ---------------------------------------------------------------------
* Lower EL using AArch32 : 0x600 - 0x800
@@ -131,19 +131,19 @@
vector_entry mmu_sync_exception_aarch32
apply_cve_2017_5715_wa _is_sync_exception=1 _esr_el3_val=ESR_EL3_A32_SMC0
b sync_exception_aarch32
- check_vector_size mmu_sync_exception_aarch32
+end_vector_entry mmu_sync_exception_aarch32
vector_entry mmu_irq_aarch32
apply_cve_2017_5715_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0
b irq_aarch32
- check_vector_size mmu_irq_aarch32
+end_vector_entry mmu_irq_aarch32
vector_entry mmu_fiq_aarch32
apply_cve_2017_5715_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0
b fiq_aarch32
- check_vector_size mmu_fiq_aarch32
+end_vector_entry mmu_fiq_aarch32
vector_entry mmu_serror_aarch32
apply_cve_2017_5715_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0
b serror_aarch32
- check_vector_size mmu_serror_aarch32
+end_vector_entry mmu_serror_aarch32
diff --git a/lib/utils/mem_region.c b/lib/utils/mem_region.c
index e9541ba..a5c3c61 100644
--- a/lib/utils/mem_region.c
+++ b/lib/utils/mem_region.c
@@ -50,7 +50,7 @@
* be cleared, and chunk is the amount of memory mapped and
* cleared in every iteration.
*/
-void clear_map_dyn_mem_regions(mem_region_t *regions,
+void clear_map_dyn_mem_regions(struct mem_region *regions,
size_t nregions,
uintptr_t va,
size_t chunk)
diff --git a/lib/xlat_tables/xlat_tables_common.c b/lib/xlat_tables/xlat_tables_common.c
index b42cd68..ce6e341 100644
--- a/lib/xlat_tables/xlat_tables_common.c
+++ b/lib/xlat_tables/xlat_tables_common.c
@@ -195,6 +195,10 @@
desc |= (level == XLAT_TABLE_LEVEL_MAX) ? PAGE_DESC : BLOCK_DESC;
desc |= (attr & MT_NS) ? LOWER_ATTRS(NS) : 0;
desc |= (attr & MT_RW) ? LOWER_ATTRS(AP_RW) : LOWER_ATTRS(AP_RO);
+ /*
+ * Always set the access flag, as this library assumes access flag
+ * faults aren't managed.
+ */
desc |= LOWER_ATTRS(ACCESS_FLAG);
desc |= ap1_mask;
@@ -222,9 +226,10 @@
} else { /* Normal memory */
/*
* Always map read-write normal memory as execute-never.
- * (Trusted Firmware doesn't self-modify its code, therefore
- * R/W memory is reserved for data storage, which must not be
- * executable.)
+ * This library assumes that it is used by software that does
+ * not self-modify its code, therefore R/W memory is reserved
+ * for data storage, which must not be executable.
+ *
* Note that setting the XN bit here is for consistency only.
* The function that enables the MMU sets the SCTLR_ELx.WXN bit,
* which makes any writable memory region to be treated as
diff --git a/lib/xlat_tables_v2/aarch32/enable_mmu.S b/lib/xlat_tables_v2/aarch32/enable_mmu.S
index 97cdde7..99cf088 100644
--- a/lib/xlat_tables_v2/aarch32/enable_mmu.S
+++ b/lib/xlat_tables_v2/aarch32/enable_mmu.S
@@ -24,17 +24,17 @@
mov r3, r0
ldr r0, =mmu_cfg_params
- /* MAIR0 */
- ldr r1, [r0, #(MMU_CFG_MAIR0 << 2)]
+ /* MAIR0. Only the lower 32 bits are used. */
+ ldr r1, [r0, #(MMU_CFG_MAIR << 3)]
stcopr r1, MAIR0
- /* TTBCR */
- ldr r2, [r0, #(MMU_CFG_TCR << 2)]
+ /* TTBCR. Only the lower 32 bits are used. */
+ ldr r2, [r0, #(MMU_CFG_TCR << 3)]
stcopr r2, TTBCR
/* TTBR0 */
- ldr r1, [r0, #(MMU_CFG_TTBR0_LO << 2)]
- ldr r2, [r0, #(MMU_CFG_TTBR0_HI << 2)]
+ ldr r1, [r0, #(MMU_CFG_TTBR0 << 3)]
+ ldr r2, [r0, #((MMU_CFG_TTBR0 << 3) + 4)]
stcopr16 r1, r2, TTBR0_64
/* TTBR1 is unused right now; set it to 0. */
diff --git a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
index 94dcf57..5e3220c 100644
--- a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
@@ -18,16 +18,14 @@
#error ARMv7 target does not support LPAE MMU descriptors
#endif
-uint32_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
-
/*
* Returns 1 if the provided granule size is supported, 0 otherwise.
*/
int xlat_arch_is_granule_size_supported(size_t size)
{
/*
- * The Trusted Firmware uses long descriptor translation table format,
- * which supports 4 KiB pages only.
+ * The library uses the long descriptor translation table format, which
+ * supports 4 KiB pages only.
*/
return (size == (4U * 1024U));
}
@@ -50,18 +48,12 @@
return (read_sctlr() & SCTLR_M_BIT) != 0;
}
-void xlat_arch_tlbi_va(uintptr_t va)
+uint64_t xlat_arch_regime_get_xn_desc(int xlat_regime __unused)
{
- /*
- * Ensure the translation table write has drained into memory before
- * invalidating the TLB entry.
- */
- dsbishst();
-
- tlbimvaais(TLBI_ADDR(va));
+ return UPPER_ATTRS(XN);
}
-void xlat_arch_tlbi_va_regime(uintptr_t va, xlat_regime_t xlat_regime __unused)
+void xlat_arch_tlbi_va(uintptr_t va, int xlat_regime __unused)
{
/*
* Ensure the translation table write has drained into memory before
@@ -103,29 +95,32 @@
/*
* If EL3 is in AArch32 mode, all secure PL1 modes (Monitor, System,
* SVC, Abort, UND, IRQ and FIQ modes) execute at EL3.
+ *
+ * The PL1&0 translation regime in AArch32 behaves like the EL1&0 regime
+ * in AArch64 except for the XN bits, but we set and unset them at the
+ * same time, so there's no difference in practice.
*/
- return 3;
+ return 1;
}
/*******************************************************************************
* Function for enabling the MMU in Secure PL1, assuming that the page tables
* have already been created.
******************************************************************************/
-void setup_mmu_cfg(unsigned int flags,
- const uint64_t *base_table,
- unsigned long long max_pa,
- uintptr_t max_va)
+void setup_mmu_cfg(uint64_t *params, unsigned int flags,
+ const uint64_t *base_table, unsigned long long max_pa,
+ uintptr_t max_va, __unused int xlat_regime)
{
- u_register_t mair0, ttbcr;
- uint64_t ttbr0;
+ uint64_t mair, ttbr0;
+ uint32_t ttbcr;
assert(IS_IN_SECURE());
/* Set attributes in the right indices of the MAIR */
- mair0 = MAIR0_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX);
- mair0 |= MAIR0_ATTR_SET(ATTR_IWBWA_OWBWA_NTR,
+ mair = MAIR0_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX);
+ mair |= MAIR0_ATTR_SET(ATTR_IWBWA_OWBWA_NTR,
ATTR_IWBWA_OWBWA_NTR_INDEX);
- mair0 |= MAIR0_ATTR_SET(ATTR_NON_CACHEABLE,
+ mair |= MAIR0_ATTR_SET(ATTR_NON_CACHEABLE,
ATTR_NON_CACHEABLE_INDEX);
/*
@@ -173,17 +168,17 @@
/* Set TTBR0 bits as well */
ttbr0 = (uint64_t)(uintptr_t) base_table;
+
#if ARM_ARCH_AT_LEAST(8, 2)
/*
- * Enable CnP bit so as to share page tables with all PEs.
- * Mandatory for ARMv8.2 implementations.
+ * Enable CnP bit so as to share page tables with all PEs. This
+ * is mandatory for ARMv8.2 implementations.
*/
ttbr0 |= TTBR_CNP_BIT;
#endif
/* Now populate MMU configuration */
- mmu_cfg_params[MMU_CFG_MAIR0] = mair0;
- mmu_cfg_params[MMU_CFG_TCR] = ttbcr;
- mmu_cfg_params[MMU_CFG_TTBR0_LO] = (uint32_t) ttbr0;
- mmu_cfg_params[MMU_CFG_TTBR0_HI] = ttbr0 >> 32;
+ params[MMU_CFG_MAIR] = mair;
+ params[MMU_CFG_TCR] = (uint64_t) ttbcr;
+ params[MMU_CFG_TTBR0] = ttbr0;
}
diff --git a/lib/xlat_tables_v2/aarch32/xlat_tables_arch_private.h b/lib/xlat_tables_v2/aarch32/xlat_tables_arch_private.h
deleted file mode 100644
index 509395d..0000000
--- a/lib/xlat_tables_v2/aarch32/xlat_tables_arch_private.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef __XLAT_TABLES_ARCH_PRIVATE_H__
-#define __XLAT_TABLES_ARCH_PRIVATE_H__
-
-#include <xlat_tables_defs.h>
-#include <xlat_tables_v2.h>
-
-/*
- * Return the execute-never mask that will prevent instruction fetch at the
- * given translation regime.
- */
-static inline uint64_t xlat_arch_regime_get_xn_desc(xlat_regime_t regime __unused)
-{
- return UPPER_ATTRS(XN);
-}
-
-#endif /* __XLAT_TABLES_ARCH_PRIVATE_H__ */
diff --git a/lib/xlat_tables_v2/aarch64/enable_mmu.S b/lib/xlat_tables_v2/aarch64/enable_mmu.S
index a72c7fa..5c5a2a9 100644
--- a/lib/xlat_tables_v2/aarch64/enable_mmu.S
+++ b/lib/xlat_tables_v2/aarch64/enable_mmu.S
@@ -43,17 +43,15 @@
ldr x0, =mmu_cfg_params
/* MAIR */
- ldr w1, [x0, #(MMU_CFG_MAIR0 << 2)]
+ ldr x1, [x0, #(MMU_CFG_MAIR << 3)]
_msr mair, \el, x1
/* TCR */
- ldr w2, [x0, #(MMU_CFG_TCR << 2)]
+ ldr x2, [x0, #(MMU_CFG_TCR << 3)]
_msr tcr, \el, x2
/* TTBR */
- ldr w3, [x0, #(MMU_CFG_TTBR0_LO << 2)]
- ldr w4, [x0, #(MMU_CFG_TTBR0_HI << 2)]
- orr x3, x3, x4, lsl #32
+ ldr x3, [x0, #(MMU_CFG_TTBR0 << 3)]
_msr ttbr0, \el, x3
/*
diff --git a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
index 71b9c8f..0f289e2 100644
--- a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
+++ b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c
@@ -7,17 +7,12 @@
#include <arch.h>
#include <arch_helpers.h>
#include <assert.h>
-#include <bl_common.h>
#include <cassert.h>
-#include <common_def.h>
#include <sys/types.h>
-#include <utils.h>
#include <utils_def.h>
#include <xlat_tables_v2.h>
#include "../xlat_tables_private.h"
-uint32_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
-
/*
* Returns 1 if the provided granule size is supported, 0 otherwise.
*/
@@ -116,19 +111,17 @@
}
}
-
-void xlat_arch_tlbi_va(uintptr_t va)
+uint64_t xlat_arch_regime_get_xn_desc(int xlat_regime)
{
-#if IMAGE_EL == 1
- assert(IS_IN_EL(1));
- xlat_arch_tlbi_va_regime(va, EL1_EL0_REGIME);
-#elif IMAGE_EL == 3
- assert(IS_IN_EL(3));
- xlat_arch_tlbi_va_regime(va, EL3_REGIME);
-#endif
+ if (xlat_regime == EL1_EL0_REGIME) {
+ return UPPER_ATTRS(UXN) | UPPER_ATTRS(PXN);
+ } else {
+ assert(xlat_regime == EL3_REGIME);
+ return UPPER_ATTRS(XN);
+ }
}
-void xlat_arch_tlbi_va_regime(uintptr_t va, xlat_regime_t xlat_regime)
+void xlat_arch_tlbi_va(uintptr_t va, int xlat_regime)
{
/*
* Ensure the translation table write has drained into memory before
@@ -185,12 +178,11 @@
return el;
}
-void setup_mmu_cfg(unsigned int flags,
- const uint64_t *base_table,
- unsigned long long max_pa,
- uintptr_t max_va)
+void setup_mmu_cfg(uint64_t *params, unsigned int flags,
+ const uint64_t *base_table, unsigned long long max_pa,
+ uintptr_t max_va, int xlat_regime)
{
- uint64_t mair, ttbr, tcr;
+ uint64_t mair, ttbr0, tcr;
uintptr_t virtual_addr_space_size;
/* Set attributes in the right indices of the MAIR. */
@@ -198,8 +190,6 @@
mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, ATTR_IWBWA_OWBWA_NTR_INDEX);
mair |= MAIR_ATTR_SET(ATTR_NON_CACHEABLE, ATTR_NON_CACHEABLE_INDEX);
- ttbr = (uint64_t) base_table;
-
/*
* Limit the input address ranges and memory region sizes translated
* using TTBR0 to the given virtual address space size.
@@ -235,30 +225,29 @@
*/
unsigned long long tcr_ps_bits = tcr_physical_addr_size_bits(max_pa);
-#if IMAGE_EL == 1
- assert(IS_IN_EL(1));
- /*
- * TCR_EL1.EPD1: Disable translation table walk for addresses that are
- * translated using TTBR1_EL1.
- */
- tcr |= TCR_EPD1_BIT | (tcr_ps_bits << TCR_EL1_IPS_SHIFT);
-#elif IMAGE_EL == 3
- assert(IS_IN_EL(3));
- tcr |= TCR_EL3_RES1 | (tcr_ps_bits << TCR_EL3_PS_SHIFT);
-#endif
-
- mmu_cfg_params[MMU_CFG_MAIR0] = (uint32_t) mair;
- mmu_cfg_params[MMU_CFG_TCR] = (uint32_t) tcr;
-
- /* Set TTBR bits as well */
- if (ARM_ARCH_AT_LEAST(8, 2)) {
+ if (xlat_regime == EL1_EL0_REGIME) {
/*
- * Enable CnP bit so as to share page tables with all PEs. This
- * is mandatory for ARMv8.2 implementations.
+ * TCR_EL1.EPD1: Disable translation table walk for addresses
+ * that are translated using TTBR1_EL1.
*/
- ttbr |= TTBR_CNP_BIT;
+ tcr |= TCR_EPD1_BIT | (tcr_ps_bits << TCR_EL1_IPS_SHIFT);
+ } else {
+ assert(xlat_regime == EL3_REGIME);
+ tcr |= TCR_EL3_RES1 | (tcr_ps_bits << TCR_EL3_PS_SHIFT);
}
- mmu_cfg_params[MMU_CFG_TTBR0_LO] = (uint32_t) ttbr;
- mmu_cfg_params[MMU_CFG_TTBR0_HI] = (uint32_t) (ttbr >> 32);
+ /* Set TTBR bits as well */
+ ttbr0 = (uint64_t) base_table;
+
+#if ARM_ARCH_AT_LEAST(8, 2)
+ /*
+ * Enable CnP bit so as to share page tables with all PEs. This
+ * is mandatory for ARMv8.2 implementations.
+ */
+ ttbr0 |= TTBR_CNP_BIT;
+#endif
+
+ params[MMU_CFG_MAIR] = mair;
+ params[MMU_CFG_TCR] = tcr;
+ params[MMU_CFG_TTBR0] = ttbr0;
}
diff --git a/lib/xlat_tables_v2/aarch64/xlat_tables_arch_private.h b/lib/xlat_tables_v2/aarch64/xlat_tables_arch_private.h
deleted file mode 100644
index d201590..0000000
--- a/lib/xlat_tables_v2/aarch64/xlat_tables_arch_private.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef __XLAT_TABLES_ARCH_PRIVATE_H__
-#define __XLAT_TABLES_ARCH_PRIVATE_H__
-
-#include <assert.h>
-#include <xlat_tables_defs.h>
-#include <xlat_tables_v2.h>
-
-/*
- * Return the execute-never mask that will prevent instruction fetch at all ELs
- * that are part of the given translation regime.
- */
-static inline uint64_t xlat_arch_regime_get_xn_desc(xlat_regime_t regime)
-{
- if (regime == EL1_EL0_REGIME) {
- return UPPER_ATTRS(UXN) | UPPER_ATTRS(PXN);
- } else {
- assert(regime == EL3_REGIME);
- return UPPER_ATTRS(XN);
- }
-}
-
-#endif /* __XLAT_TABLES_ARCH_PRIVATE_H__ */
diff --git a/lib/xlat_tables_v2/xlat_tables.mk b/lib/xlat_tables_v2/xlat_tables.mk
index 1e70f37..9507ad7 100644
--- a/lib/xlat_tables_v2/xlat_tables.mk
+++ b/lib/xlat_tables_v2/xlat_tables.mk
@@ -7,6 +7,6 @@
XLAT_TABLES_LIB_SRCS := $(addprefix lib/xlat_tables_v2/, \
${ARCH}/enable_mmu.S \
${ARCH}/xlat_tables_arch.c \
- xlat_tables_internal.c)
-
-INCLUDES += -Ilib/xlat_tables_v2/${ARCH}
+ xlat_tables_context.c \
+ xlat_tables_core.c \
+ xlat_tables_utils.c)
diff --git a/lib/xlat_tables_v2/xlat_tables_context.c b/lib/xlat_tables_v2/xlat_tables_context.c
new file mode 100644
index 0000000..76c429d
--- /dev/null
+++ b/lib/xlat_tables_v2/xlat_tables_context.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <platform_def.h>
+#include <xlat_tables_defs.h>
+#include <xlat_tables_v2.h>
+
+#include "xlat_tables_private.h"
+
+/*
+ * MMU configuration register values for the active translation context. Used
+ * from the MMU assembly helpers.
+ */
+uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
+
+/*
+ * Each platform can define the size of its physical and virtual address spaces.
+ * If the platform hasn't defined one or both of them, default to
+ * ADDR_SPACE_SIZE. The latter is deprecated, though.
+ */
+#if ERROR_DEPRECATED
+# ifdef ADDR_SPACE_SIZE
+# error "ADDR_SPACE_SIZE is deprecated. Use PLAT_xxx_ADDR_SPACE_SIZE instead."
+# endif
+#elif defined(ADDR_SPACE_SIZE)
+# ifndef PLAT_PHY_ADDR_SPACE_SIZE
+# define PLAT_PHY_ADDR_SPACE_SIZE ADDR_SPACE_SIZE
+# endif
+# ifndef PLAT_VIRT_ADDR_SPACE_SIZE
+# define PLAT_VIRT_ADDR_SPACE_SIZE ADDR_SPACE_SIZE
+# endif
+#endif
+
+/*
+ * 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_region(unsigned long long base_pa, uintptr_t base_va, size_t size,
+ unsigned int attr)
+{
+ mmap_region_t mm = MAP_REGION(base_pa, base_va, size, attr);
+
+ mmap_add_region_ctx(&tf_xlat_ctx, &mm);
+}
+
+void mmap_add(const mmap_region_t *mm)
+{
+ mmap_add_ctx(&tf_xlat_ctx, mm);
+}
+
+#if PLAT_XLAT_TABLES_DYNAMIC
+
+int mmap_add_dynamic_region(unsigned long long base_pa, uintptr_t base_va,
+ size_t size, unsigned int attr)
+{
+ mmap_region_t mm = MAP_REGION(base_pa, base_va, size, attr);
+
+ return mmap_add_dynamic_region_ctx(&tf_xlat_ctx, &mm);
+}
+
+int mmap_remove_dynamic_region(uintptr_t base_va, size_t size)
+{
+ return mmap_remove_dynamic_region_ctx(&tf_xlat_ctx,
+ base_va, size);
+}
+
+#endif /* PLAT_XLAT_TABLES_DYNAMIC */
+
+void init_xlat_tables(void)
+{
+ assert(tf_xlat_ctx.xlat_regime == EL_REGIME_INVALID);
+
+ int current_el = xlat_arch_current_el();
+
+ if (current_el == 1) {
+ tf_xlat_ctx.xlat_regime = EL1_EL0_REGIME;
+ } else {
+ assert(current_el == 3);
+ tf_xlat_ctx.xlat_regime = EL3_REGIME;
+ }
+
+ init_xlat_tables_ctx(&tf_xlat_ctx);
+}
+
+/*
+ * If dynamic allocation of new regions is disabled then by the time we call the
+ * function enabling the MMU, we'll have registered all the memory regions to
+ * map for the system's lifetime. Therefore, at this point we know the maximum
+ * physical address that will ever be mapped.
+ *
+ * If dynamic allocation is enabled then we can't make any such assumption
+ * because the maximum physical address could get pushed while adding a new
+ * region. Therefore, in this case we have to assume that the whole address
+ * space size might be mapped.
+ */
+#ifdef PLAT_XLAT_TABLES_DYNAMIC
+#define MAX_PHYS_ADDR tf_xlat_ctx.pa_max_address
+#else
+#define MAX_PHYS_ADDR tf_xlat_ctx.max_pa
+#endif
+
+#ifdef AARCH32
+
+void enable_mmu_secure(unsigned int flags)
+{
+ setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags,
+ tf_xlat_ctx.base_table, MAX_PHYS_ADDR,
+ tf_xlat_ctx.va_max_address, EL1_EL0_REGIME);
+ enable_mmu_direct(flags);
+}
+
+#else
+
+void enable_mmu_el1(unsigned int flags)
+{
+ setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags,
+ tf_xlat_ctx.base_table, MAX_PHYS_ADDR,
+ tf_xlat_ctx.va_max_address, EL1_EL0_REGIME);
+ enable_mmu_direct_el1(flags);
+}
+
+void enable_mmu_el3(unsigned int flags)
+{
+ setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags,
+ tf_xlat_ctx.base_table, MAX_PHYS_ADDR,
+ tf_xlat_ctx.va_max_address, EL3_REGIME);
+ enable_mmu_direct_el3(flags);
+}
+
+#endif /* AARCH32 */
diff --git a/lib/xlat_tables_v2/xlat_tables_core.c b/lib/xlat_tables_v2/xlat_tables_core.c
new file mode 100644
index 0000000..e3306e6
--- /dev/null
+++ b/lib/xlat_tables_v2/xlat_tables_core.c
@@ -0,0 +1,1015 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <errno.h>
+#include <platform_def.h>
+#include <string.h>
+#include <types.h>
+#include <utils_def.h>
+#include <xlat_tables_defs.h>
+#include <xlat_tables_v2.h>
+
+#include "xlat_tables_private.h"
+
+#if PLAT_XLAT_TABLES_DYNAMIC
+
+/*
+ * The following functions assume that they will be called using subtables only.
+ * The base table can't be unmapped, so it is not needed to do any special
+ * handling for it.
+ */
+
+/*
+ * Returns the index of the array corresponding to the specified translation
+ * table.
+ */
+static int xlat_table_get_index(xlat_ctx_t *ctx, const uint64_t *table)
+{
+ for (unsigned int i = 0; i < ctx->tables_num; i++)
+ if (ctx->tables[i] == table)
+ return i;
+
+ /*
+ * Maybe we were asked to get the index of the base level table, which
+ * should never happen.
+ */
+ assert(0);
+
+ return -1;
+}
+
+/* Returns a pointer to an empty translation table. */
+static uint64_t *xlat_table_get_empty(xlat_ctx_t *ctx)
+{
+ for (unsigned int i = 0; i < ctx->tables_num; i++)
+ if (ctx->tables_mapped_regions[i] == 0)
+ return ctx->tables[i];
+
+ return NULL;
+}
+
+/* Increments region count for a given table. */
+static void xlat_table_inc_regions_count(xlat_ctx_t *ctx, const uint64_t *table)
+{
+ ctx->tables_mapped_regions[xlat_table_get_index(ctx, table)]++;
+}
+
+/* Decrements region count for a given table. */
+static void xlat_table_dec_regions_count(xlat_ctx_t *ctx, const uint64_t *table)
+{
+ ctx->tables_mapped_regions[xlat_table_get_index(ctx, table)]--;
+}
+
+/* Returns 0 if the specified table isn't empty, otherwise 1. */
+static int xlat_table_is_empty(xlat_ctx_t *ctx, const uint64_t *table)
+{
+ return !ctx->tables_mapped_regions[xlat_table_get_index(ctx, table)];
+}
+
+#else /* PLAT_XLAT_TABLES_DYNAMIC */
+
+/* Returns a pointer to the first empty translation table. */
+static uint64_t *xlat_table_get_empty(xlat_ctx_t *ctx)
+{
+ assert(ctx->next_table < ctx->tables_num);
+
+ return ctx->tables[ctx->next_table++];
+}
+
+#endif /* PLAT_XLAT_TABLES_DYNAMIC */
+
+/*
+ * 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, int level)
+{
+ uint64_t desc;
+ int mem_type;
+
+ /* Make sure that the granularity is fine enough to map this address. */
+ assert((addr_pa & XLAT_BLOCK_MASK(level)) == 0);
+
+ desc = addr_pa;
+ /*
+ * There are different translation table descriptors for level 3 and the
+ * rest.
+ */
+ desc |= (level == XLAT_TABLE_LEVEL_MAX) ? PAGE_DESC : BLOCK_DESC;
+ /*
+ * Always set the access flag, as this library assumes access flag
+ * faults aren't managed.
+ */
+ desc |= LOWER_ATTRS(ACCESS_FLAG);
+ /*
+ * Deduce other fields of the descriptor based on the MT_NS and MT_RW
+ * memory region attributes.
+ */
+ desc |= (attr & MT_NS) ? LOWER_ATTRS(NS) : 0;
+ desc |= (attr & MT_RW) ? LOWER_ATTRS(AP_RW) : LOWER_ATTRS(AP_RO);
+
+ /*
+ * Do not allow unprivileged access when the mapping is for a privileged
+ * EL. For translation regimes that do not have mappings for access for
+ * lower exception levels, set AP[2] to AP_NO_ACCESS_UNPRIVILEGED.
+ */
+ if (ctx->xlat_regime == EL1_EL0_REGIME) {
+ if (attr & MT_USER) {
+ /* EL0 mapping requested, so we give User access */
+ desc |= LOWER_ATTRS(AP_ACCESS_UNPRIVILEGED);
+ } else {
+ /* EL1 mapping requested, no User access granted */
+ desc |= LOWER_ATTRS(AP_NO_ACCESS_UNPRIVILEGED);
+ }
+ } else {
+ assert(ctx->xlat_regime == EL3_REGIME);
+ desc |= LOWER_ATTRS(AP_ONE_VA_RANGE_RES1);
+ }
+
+ /*
+ * Deduce shareability domain and executability of the memory region
+ * from the memory type of the attributes (MT_TYPE).
+ *
+ * Data accesses to device memory and non-cacheable normal memory are
+ * coherent for all observers in the system, and correspondingly are
+ * always treated as being Outer Shareable. Therefore, for these 2 types
+ * of memory, it is not strictly needed to set the shareability field
+ * in the translation tables.
+ */
+ mem_type = MT_TYPE(attr);
+ if (mem_type == MT_DEVICE) {
+ desc |= LOWER_ATTRS(ATTR_DEVICE_INDEX | OSH);
+ /*
+ * Always map device memory as execute-never.
+ * This is to avoid the possibility of a speculative instruction
+ * fetch, which could be an issue if this memory region
+ * corresponds to a read-sensitive peripheral.
+ */
+ desc |= xlat_arch_regime_get_xn_desc(ctx->xlat_regime);
+
+ } else { /* Normal memory */
+ /*
+ * Always map read-write normal memory as execute-never.
+ * This library assumes that it is used by software that does
+ * not self-modify its code, therefore R/W memory is reserved
+ * for data storage, which must not be executable.
+ *
+ * Note that setting the XN bit here is for consistency only.
+ * The function that enables the MMU sets the SCTLR_ELx.WXN bit,
+ * which makes any writable memory region to be treated as
+ * execute-never, regardless of the value of the XN bit in the
+ * translation table.
+ *
+ * For read-only memory, rely on the MT_EXECUTE/MT_EXECUTE_NEVER
+ * attribute to figure out the value of the XN bit. The actual
+ * XN bit(s) to set in the descriptor depends on the context's
+ * translation regime and the policy applied in
+ * xlat_arch_regime_get_xn_desc().
+ */
+ if ((attr & MT_RW) || (attr & MT_EXECUTE_NEVER)) {
+ desc |= xlat_arch_regime_get_xn_desc(ctx->xlat_regime);
+ }
+
+ if (mem_type == MT_MEMORY) {
+ desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX | ISH);
+ } else {
+ assert(mem_type == MT_NON_CACHEABLE);
+ desc |= LOWER_ATTRS(ATTR_NON_CACHEABLE_INDEX | OSH);
+ }
+ }
+
+ return desc;
+}
+
+/*
+ * Enumeration of actions that can be made when mapping table entries depending
+ * on the previous value in that entry and information about the region being
+ * mapped.
+ */
+typedef enum {
+
+ /* Do nothing */
+ ACTION_NONE,
+
+ /* Write a block (or page, if in level 3) entry. */
+ ACTION_WRITE_BLOCK_ENTRY,
+
+ /*
+ * Create a new table and write a table entry pointing to it. Recurse
+ * into it for further processing.
+ */
+ ACTION_CREATE_NEW_TABLE,
+
+ /*
+ * There is a table descriptor in this entry, read it and recurse into
+ * that table for further processing.
+ */
+ ACTION_RECURSE_INTO_TABLE,
+
+} action_t;
+
+#if PLAT_XLAT_TABLES_DYNAMIC
+
+/*
+ * Recursive function that writes to the translation tables and unmaps the
+ * specified region.
+ */
+static void xlat_tables_unmap_region(xlat_ctx_t *ctx, mmap_region_t *mm,
+ const uintptr_t table_base_va,
+ uint64_t *const table_base,
+ const int table_entries,
+ const unsigned int level)
+{
+ assert(level >= ctx->base_level && level <= XLAT_TABLE_LEVEL_MAX);
+
+ uint64_t *subtable;
+ uint64_t desc;
+
+ uintptr_t table_idx_va;
+ uintptr_t table_idx_end_va; /* End VA of this entry */
+
+ uintptr_t region_end_va = mm->base_va + mm->size - 1;
+
+ int table_idx;
+
+ if (mm->base_va > table_base_va) {
+ /* Find the first index of the table affected by the region. */
+ table_idx_va = mm->base_va & ~XLAT_BLOCK_MASK(level);
+
+ table_idx = (table_idx_va - table_base_va) >>
+ XLAT_ADDR_SHIFT(level);
+
+ assert(table_idx < table_entries);
+ } else {
+ /* Start from the beginning of the table. */
+ table_idx_va = table_base_va;
+ table_idx = 0;
+ }
+
+ while (table_idx < table_entries) {
+
+ table_idx_end_va = table_idx_va + XLAT_BLOCK_SIZE(level) - 1;
+
+ desc = table_base[table_idx];
+ uint64_t desc_type = desc & DESC_MASK;
+
+ action_t action = ACTION_NONE;
+
+ if ((mm->base_va <= table_idx_va) &&
+ (region_end_va >= table_idx_end_va)) {
+
+ /* Region covers all block */
+
+ if (level == 3) {
+ /*
+ * Last level, only page descriptors allowed,
+ * erase it.
+ */
+ assert(desc_type == PAGE_DESC);
+
+ action = ACTION_WRITE_BLOCK_ENTRY;
+ } else {
+ /*
+ * Other levels can have table descriptors. If
+ * so, recurse into it and erase descriptors
+ * inside it as needed. If there is a block
+ * descriptor, just erase it. If an invalid
+ * descriptor is found, this table isn't
+ * actually mapped, which shouldn't happen.
+ */
+ if (desc_type == TABLE_DESC) {
+ action = ACTION_RECURSE_INTO_TABLE;
+ } else {
+ assert(desc_type == BLOCK_DESC);
+ action = ACTION_WRITE_BLOCK_ENTRY;
+ }
+ }
+
+ } else if ((mm->base_va <= table_idx_end_va) ||
+ (region_end_va >= table_idx_va)) {
+
+ /*
+ * Region partially covers block.
+ *
+ * It can't happen in level 3.
+ *
+ * There must be a table descriptor here, if not there
+ * was a problem when mapping the region.
+ */
+
+ assert(level < 3);
+
+ assert(desc_type == TABLE_DESC);
+
+ action = ACTION_RECURSE_INTO_TABLE;
+ }
+
+ if (action == ACTION_WRITE_BLOCK_ENTRY) {
+
+ table_base[table_idx] = INVALID_DESC;
+ xlat_arch_tlbi_va(table_idx_va, ctx->xlat_regime);
+
+ } else if (action == ACTION_RECURSE_INTO_TABLE) {
+
+ subtable = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK);
+
+ /* Recurse to write into subtable */
+ xlat_tables_unmap_region(ctx, mm, table_idx_va,
+ subtable, XLAT_TABLE_ENTRIES,
+ level + 1);
+
+ /*
+ * If the subtable is now empty, remove its reference.
+ */
+ if (xlat_table_is_empty(ctx, subtable)) {
+ table_base[table_idx] = INVALID_DESC;
+ xlat_arch_tlbi_va(table_idx_va,
+ ctx->xlat_regime);
+ }
+
+ } else {
+ assert(action == ACTION_NONE);
+ }
+
+ table_idx++;
+ table_idx_va += XLAT_BLOCK_SIZE(level);
+
+ /* If reached the end of the region, exit */
+ if (region_end_va <= table_idx_va)
+ break;
+ }
+
+ if (level > ctx->base_level)
+ xlat_table_dec_regions_count(ctx, table_base);
+}
+
+#endif /* PLAT_XLAT_TABLES_DYNAMIC */
+
+/*
+ * From the given arguments, it decides which action to take when mapping the
+ * specified region.
+ */
+static action_t xlat_tables_map_region_action(const mmap_region_t *mm,
+ const int desc_type, const unsigned long long dest_pa,
+ const uintptr_t table_entry_base_va, const unsigned int level)
+{
+ uintptr_t mm_end_va = mm->base_va + mm->size - 1;
+ uintptr_t table_entry_end_va =
+ table_entry_base_va + XLAT_BLOCK_SIZE(level) - 1;
+
+ /*
+ * The descriptor types allowed depend on the current table level.
+ */
+
+ if ((mm->base_va <= table_entry_base_va) &&
+ (mm_end_va >= table_entry_end_va)) {
+
+ /*
+ * Table entry is covered by region
+ * --------------------------------
+ *
+ * This means that this table entry can describe the whole
+ * translation with this granularity in principle.
+ */
+
+ if (level == 3) {
+ /*
+ * Last level, only page descriptors are allowed.
+ */
+ if (desc_type == PAGE_DESC) {
+ /*
+ * There's another region mapped here, don't
+ * overwrite.
+ */
+ return ACTION_NONE;
+ } else {
+ assert(desc_type == INVALID_DESC);
+ return ACTION_WRITE_BLOCK_ENTRY;
+ }
+
+ } else {
+
+ /*
+ * Other levels. Table descriptors are allowed. Block
+ * descriptors too, but they have some limitations.
+ */
+
+ if (desc_type == TABLE_DESC) {
+ /* There's already a table, recurse into it. */
+ return ACTION_RECURSE_INTO_TABLE;
+
+ } else if (desc_type == INVALID_DESC) {
+ /*
+ * There's nothing mapped here, create a new
+ * entry.
+ *
+ * Check if the destination granularity allows
+ * us to use a block descriptor or we need a
+ * finer table for it.
+ *
+ * Also, check if the current level allows block
+ * descriptors. If not, create a table instead.
+ */
+ if ((dest_pa & XLAT_BLOCK_MASK(level)) ||
+ (level < MIN_LVL_BLOCK_DESC) ||
+ (mm->granularity < XLAT_BLOCK_SIZE(level)))
+ return ACTION_CREATE_NEW_TABLE;
+ else
+ return ACTION_WRITE_BLOCK_ENTRY;
+
+ } else {
+ /*
+ * There's another region mapped here, don't
+ * overwrite.
+ */
+ assert(desc_type == BLOCK_DESC);
+
+ return ACTION_NONE;
+ }
+ }
+
+ } else if ((mm->base_va <= table_entry_end_va) ||
+ (mm_end_va >= table_entry_base_va)) {
+
+ /*
+ * Region partially covers table entry
+ * -----------------------------------
+ *
+ * This means that this table entry can't describe the whole
+ * translation, a finer table is needed.
+
+ * There cannot be partial block overlaps in level 3. If that
+ * happens, some of the preliminary checks when adding the
+ * mmap region failed to detect that PA and VA must at least be
+ * aligned to PAGE_SIZE.
+ */
+ assert(level < 3);
+
+ if (desc_type == INVALID_DESC) {
+ /*
+ * The block is not fully covered by the region. Create
+ * a new table, recurse into it and try to map the
+ * region with finer granularity.
+ */
+ return ACTION_CREATE_NEW_TABLE;
+
+ } else {
+ assert(desc_type == TABLE_DESC);
+ /*
+ * The block is not fully covered by the region, but
+ * there is already a table here. Recurse into it and
+ * try to map with finer granularity.
+ *
+ * PAGE_DESC for level 3 has the same value as
+ * TABLE_DESC, but this code can't run on a level 3
+ * table because there can't be overlaps in level 3.
+ */
+ return ACTION_RECURSE_INTO_TABLE;
+ }
+ }
+
+ /*
+ * This table entry is outside of the region specified in the arguments,
+ * don't write anything to it.
+ */
+ return ACTION_NONE;
+}
+
+/*
+ * Recursive function that writes to the translation tables and maps the
+ * specified region. On success, it returns the VA of the last byte that was
+ * successfully mapped. On error, it returns the VA of the next entry that
+ * should have been mapped.
+ */
+static uintptr_t xlat_tables_map_region(xlat_ctx_t *ctx, mmap_region_t *mm,
+ const uintptr_t table_base_va,
+ uint64_t *const table_base,
+ const int table_entries,
+ const unsigned int level)
+{
+ assert(level >= ctx->base_level && level <= XLAT_TABLE_LEVEL_MAX);
+
+ uintptr_t mm_end_va = mm->base_va + mm->size - 1;
+
+ uintptr_t table_idx_va;
+ unsigned long long table_idx_pa;
+
+ uint64_t *subtable;
+ uint64_t desc;
+
+ int table_idx;
+
+ if (mm->base_va > table_base_va) {
+ /* Find the first index of the table affected by the region. */
+ table_idx_va = mm->base_va & ~XLAT_BLOCK_MASK(level);
+
+ table_idx = (table_idx_va - table_base_va) >>
+ XLAT_ADDR_SHIFT(level);
+
+ assert(table_idx < table_entries);
+ } else {
+ /* Start from the beginning of the table. */
+ table_idx_va = table_base_va;
+ table_idx = 0;
+ }
+
+#if PLAT_XLAT_TABLES_DYNAMIC
+ if (level > ctx->base_level)
+ xlat_table_inc_regions_count(ctx, table_base);
+#endif
+
+ while (table_idx < table_entries) {
+
+ desc = table_base[table_idx];
+
+ table_idx_pa = mm->base_pa + table_idx_va - mm->base_va;
+
+ action_t action = xlat_tables_map_region_action(mm,
+ desc & DESC_MASK, table_idx_pa, table_idx_va, level);
+
+ if (action == ACTION_WRITE_BLOCK_ENTRY) {
+
+ table_base[table_idx] =
+ xlat_desc(ctx, (uint32_t)mm->attr, table_idx_pa,
+ level);
+
+ } else if (action == ACTION_CREATE_NEW_TABLE) {
+
+ subtable = xlat_table_get_empty(ctx);
+ if (subtable == NULL) {
+ /* Not enough free tables to map this region */
+ return table_idx_va;
+ }
+
+ /* Point to new subtable from this one. */
+ table_base[table_idx] = TABLE_DESC | (unsigned long)subtable;
+
+ /* Recurse to write into subtable */
+ uintptr_t end_va = xlat_tables_map_region(ctx, mm, table_idx_va,
+ subtable, XLAT_TABLE_ENTRIES,
+ level + 1);
+ if (end_va != table_idx_va + XLAT_BLOCK_SIZE(level) - 1)
+ return end_va;
+
+ } else if (action == ACTION_RECURSE_INTO_TABLE) {
+
+ subtable = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK);
+ /* Recurse to write into subtable */
+ uintptr_t end_va = xlat_tables_map_region(ctx, mm, table_idx_va,
+ subtable, XLAT_TABLE_ENTRIES,
+ level + 1);
+ if (end_va != table_idx_va + XLAT_BLOCK_SIZE(level) - 1)
+ return end_va;
+
+ } else {
+
+ assert(action == ACTION_NONE);
+
+ }
+
+ table_idx++;
+ table_idx_va += XLAT_BLOCK_SIZE(level);
+
+ /* If reached the end of the region, exit */
+ if (mm_end_va <= table_idx_va)
+ break;
+ }
+
+ return table_idx_va - 1;
+}
+
+/*
+ * 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(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;
+ size_t granularity = mm->granularity;
+
+ unsigned long long end_pa = base_pa + size - 1;
+ uintptr_t end_va = base_va + size - 1;
+
+ if (!IS_PAGE_ALIGNED(base_pa) || !IS_PAGE_ALIGNED(base_va) ||
+ !IS_PAGE_ALIGNED(size))
+ return -EINVAL;
+
+ if ((granularity != XLAT_BLOCK_SIZE(1)) &&
+ (granularity != XLAT_BLOCK_SIZE(2)) &&
+ (granularity != XLAT_BLOCK_SIZE(3))) {
+ return -EINVAL;
+ }
+
+ /* Check for overflows */
+ if ((base_pa > end_pa) || (base_va > end_va))
+ return -ERANGE;
+
+ if ((base_va + (uintptr_t)size - (uintptr_t)1) > ctx->va_max_address)
+ return -ERANGE;
+
+ if ((base_pa + (unsigned long long)size - 1ULL) > ctx->pa_max_address)
+ return -ERANGE;
+
+ /* Check that there is space in the ctx->mmap array */
+ if (ctx->mmap[ctx->mmap_num - 1].size != 0)
+ return -ENOMEM;
+
+ /* Check for PAs and VAs overlaps with all other regions */
+ for (mmap_region_t *mm_cursor = ctx->mmap;
+ mm_cursor->size; ++mm_cursor) {
+
+ uintptr_t mm_cursor_end_va = mm_cursor->base_va
+ + mm_cursor->size - 1;
+
+ /*
+ * Check if one of the regions is completely inside the other
+ * one.
+ */
+ int 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) ||
+ (mm_cursor->attr & MT_DYNAMIC))
+ 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 - 1;
+
+ int separated_pa =
+ (end_pa < mm_cursor->base_pa) ||
+ (base_pa > mm_cursor_end_pa);
+ int 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;
+ mmap_region_t *mm_last;
+ unsigned long long end_pa = mm->base_pa + mm->size - 1;
+ uintptr_t end_va = mm->base_va + mm->size - 1;
+ int ret;
+
+ /* Ignore empty regions */
+ if (!mm->size)
+ 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(0);
+ return;
+ }
+
+ /*
+ * Find correct place in mmap to insert new region.
+ *
+ * 1 - Lower region VA end first.
+ * 2 - Smaller region size first.
+ *
+ * VA 0 0xFF
+ *
+ * 1st |------|
+ * 2nd |------------|
+ * 3rd |------|
+ * 4th |---|
+ * 5th |---|
+ * 6th |----------|
+ * 7th |-------------------------------------|
+ *
+ * This is required for overlapping regions only. It simplifies adding
+ * regions with the loop in xlat_tables_init_internal because the outer
+ * ones won't overwrite block or page descriptors of regions added
+ * previously.
+ *
+ * Overlapping is only allowed for static regions.
+ */
+
+ while ((mm_cursor->base_va + mm_cursor->size - 1) < end_va
+ && mm_cursor->size)
+ ++mm_cursor;
+
+ while ((mm_cursor->base_va + mm_cursor->size - 1 == end_va) &&
+ (mm_cursor->size != 0U) && (mm_cursor->size < mm->size))
+ ++mm_cursor;
+
+ /*
+ * 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;
+ 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)
+{
+ while (mm->size) {
+ mmap_add_region_ctx(ctx, mm);
+ mm++;
+ }
+}
+
+#if PLAT_XLAT_TABLES_DYNAMIC
+
+int mmap_add_dynamic_region_ctx(xlat_ctx_t *ctx, mmap_region_t *mm)
+{
+ mmap_region_t *mm_cursor = ctx->mmap;
+ mmap_region_t *mm_last = mm_cursor + ctx->mmap_num;
+ unsigned long long end_pa = mm->base_pa + mm->size - 1;
+ uintptr_t end_va = mm->base_va + mm->size - 1;
+ int ret;
+
+ /* Nothing to do */
+ if (!mm->size)
+ return 0;
+
+ /* Now this region is a dynamic one */
+ mm->attr |= MT_DYNAMIC;
+
+ ret = mmap_add_region_check(ctx, mm);
+ if (ret != 0)
+ return ret;
+
+ /*
+ * Find the adequate entry in the mmap array in the same way done for
+ * static regions in mmap_add_region_ctx().
+ */
+
+ while ((mm_cursor->base_va + mm_cursor->size - 1)
+ < end_va && mm_cursor->size)
+ ++mm_cursor;
+
+ while ((mm_cursor->base_va + mm_cursor->size - 1 == end_va)
+ && (mm_cursor->size < mm->size))
+ ++mm_cursor;
+
+ /* Make room for new region by moving other regions up by one place */
+ memmove(mm_cursor + 1, mm_cursor,
+ (uintptr_t)mm_last - (uintptr_t)mm_cursor);
+
+ /*
+ * Check we haven't lost the empty sentinal 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_last->size == 0);
+
+ *mm_cursor = *mm;
+
+ /*
+ * Update the translation tables if the xlat tables are initialized. If
+ * not, this region will be mapped when they are initialized.
+ */
+ if (ctx->initialized) {
+ uintptr_t end_va = xlat_tables_map_region(ctx, mm_cursor,
+ 0, ctx->base_table, ctx->base_table_entries,
+ ctx->base_level);
+
+ /* Failed to map, remove mmap entry, unmap and return error. */
+ if (end_va != mm_cursor->base_va + mm_cursor->size - 1) {
+ memmove(mm_cursor, mm_cursor + 1,
+ (uintptr_t)mm_last - (uintptr_t)mm_cursor);
+
+ /*
+ * Check if the mapping function actually managed to map
+ * anything. If not, just return now.
+ */
+ if (mm->base_va >= end_va)
+ return -ENOMEM;
+
+ /*
+ * Something went wrong after mapping some table
+ * entries, undo every change done up to this point.
+ */
+ mmap_region_t unmap_mm = {
+ .base_pa = 0,
+ .base_va = mm->base_va,
+ .size = end_va - mm->base_va,
+ .attr = 0
+ };
+ xlat_tables_unmap_region(ctx, &unmap_mm, 0, ctx->base_table,
+ ctx->base_table_entries, ctx->base_level);
+
+ return -ENOMEM;
+ }
+
+ /*
+ * Make sure that all entries are written to the memory. There
+ * is no need to invalidate entries when mapping dynamic regions
+ * because new table/block/page descriptors only replace old
+ * invalid descriptors, that aren't TLB cached.
+ */
+ dsbishst();
+ }
+
+ if (end_pa > ctx->max_pa)
+ ctx->max_pa = end_pa;
+ if (end_va > ctx->max_va)
+ ctx->max_va = end_va;
+
+ return 0;
+}
+
+/*
+ * Removes the region with given base Virtual Address and size from the given
+ * context.
+ *
+ * Returns:
+ * 0: Success.
+ * EINVAL: Invalid values were used as arguments (region not found).
+ * EPERM: Tried to remove a static region.
+ */
+int mmap_remove_dynamic_region_ctx(xlat_ctx_t *ctx, uintptr_t base_va,
+ size_t size)
+{
+ mmap_region_t *mm = ctx->mmap;
+ mmap_region_t *mm_last = mm + ctx->mmap_num;
+ int update_max_va_needed = 0;
+ int update_max_pa_needed = 0;
+
+ /* Check sanity of mmap array. */
+ assert(mm[ctx->mmap_num].size == 0);
+
+ while (mm->size) {
+ if ((mm->base_va == base_va) && (mm->size == size))
+ break;
+ ++mm;
+ }
+
+ /* Check that the region was found */
+ if (mm->size == 0)
+ return -EINVAL;
+
+ /* If the region is static it can't be removed */
+ if (!(mm->attr & MT_DYNAMIC))
+ return -EPERM;
+
+ /* Check if this region is using the top VAs or PAs. */
+ if ((mm->base_va + mm->size - 1) == ctx->max_va)
+ update_max_va_needed = 1;
+ if ((mm->base_pa + mm->size - 1) == ctx->max_pa)
+ update_max_pa_needed = 1;
+
+ /* Update the translation tables if needed */
+ if (ctx->initialized) {
+ xlat_tables_unmap_region(ctx, mm, 0, ctx->base_table,
+ ctx->base_table_entries,
+ ctx->base_level);
+ xlat_arch_tlbi_va_sync();
+ }
+
+ /* Remove this region by moving the rest down by one place. */
+ memmove(mm, mm + 1, (uintptr_t)mm_last - (uintptr_t)mm);
+
+ /* Check if we need to update the max VAs and PAs */
+ if (update_max_va_needed) {
+ ctx->max_va = 0;
+ mm = ctx->mmap;
+ while (mm->size) {
+ if ((mm->base_va + mm->size - 1) > ctx->max_va)
+ ctx->max_va = mm->base_va + mm->size - 1;
+ ++mm;
+ }
+ }
+
+ if (update_max_pa_needed) {
+ ctx->max_pa = 0;
+ mm = ctx->mmap;
+ while (mm->size) {
+ if ((mm->base_pa + mm->size - 1) > ctx->max_pa)
+ ctx->max_pa = mm->base_pa + mm->size - 1;
+ ++mm;
+ }
+ }
+
+ return 0;
+}
+
+#endif /* PLAT_XLAT_TABLES_DYNAMIC */
+
+void init_xlat_tables_ctx(xlat_ctx_t *ctx)
+{
+ assert(ctx != NULL);
+ assert(!ctx->initialized);
+ assert(ctx->xlat_regime == EL3_REGIME || ctx->xlat_regime == EL1_EL0_REGIME);
+ assert(!is_mmu_enabled_ctx(ctx));
+
+ mmap_region_t *mm = ctx->mmap;
+
+ xlat_mmap_print(mm);
+
+ /* All tables must be zeroed before mapping any region. */
+
+ for (unsigned int i = 0; i < ctx->base_table_entries; i++)
+ ctx->base_table[i] = INVALID_DESC;
+
+ for (unsigned int j = 0; j < ctx->tables_num; j++) {
+#if PLAT_XLAT_TABLES_DYNAMIC
+ ctx->tables_mapped_regions[j] = 0;
+#endif
+ for (unsigned int i = 0; i < XLAT_TABLE_ENTRIES; i++)
+ ctx->tables[j][i] = INVALID_DESC;
+ }
+
+ while (mm->size) {
+ uintptr_t end_va = xlat_tables_map_region(ctx, mm, 0, ctx->base_table,
+ ctx->base_table_entries, ctx->base_level);
+
+ if (end_va != mm->base_va + mm->size - 1) {
+ ERROR("Not enough memory to map region:\n"
+ " VA:%p PA:0x%llx size:0x%zx attr:0x%x\n",
+ (void *)mm->base_va, mm->base_pa, mm->size, mm->attr);
+ panic();
+ }
+
+ mm++;
+ }
+
+ assert(ctx->pa_max_address <= xlat_arch_get_max_supported_pa());
+ assert(ctx->max_va <= ctx->va_max_address);
+ assert(ctx->max_pa <= ctx->pa_max_address);
+
+ ctx->initialized = 1;
+
+ xlat_tables_print(ctx);
+}
diff --git a/lib/xlat_tables_v2/xlat_tables_internal.c b/lib/xlat_tables_v2/xlat_tables_internal.c
deleted file mode 100644
index 7f1d395..0000000
--- a/lib/xlat_tables_v2/xlat_tables_internal.c
+++ /dev/null
@@ -1,1682 +0,0 @@
-/*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <arch.h>
-#include <arch_helpers.h>
-#include <assert.h>
-#include <common_def.h>
-#include <debug.h>
-#include <errno.h>
-#include <platform_def.h>
-#include <string.h>
-#include <types.h>
-#include <utils.h>
-#include <xlat_tables_arch_private.h>
-#include <xlat_tables_defs.h>
-#include <xlat_tables_v2.h>
-
-#include "xlat_tables_private.h"
-
-/*
- * Each platform can define the size of its physical and virtual address spaces.
- * If the platform hasn't defined one or both of them, default to
- * ADDR_SPACE_SIZE. The latter is deprecated, though.
- */
-#if ERROR_DEPRECATED
-# ifdef ADDR_SPACE_SIZE
-# error "ADDR_SPACE_SIZE is deprecated. Use PLAT_xxx_ADDR_SPACE_SIZE instead."
-# endif
-#elif defined(ADDR_SPACE_SIZE)
-# ifndef PLAT_PHY_ADDR_SPACE_SIZE
-# define PLAT_PHY_ADDR_SPACE_SIZE ADDR_SPACE_SIZE
-# endif
-# ifndef PLAT_VIRT_ADDR_SPACE_SIZE
-# define PLAT_VIRT_ADDR_SPACE_SIZE ADDR_SPACE_SIZE
-# endif
-#endif
-
-/*
- * 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);
-
-#if PLAT_XLAT_TABLES_DYNAMIC
-
-/*
- * The following functions assume that they will be called using subtables only.
- * The base table can't be unmapped, so it is not needed to do any special
- * handling for it.
- */
-
-/*
- * Returns the index of the array corresponding to the specified translation
- * table.
- */
-static int xlat_table_get_index(xlat_ctx_t *ctx, const uint64_t *table)
-{
- for (unsigned int i = 0; i < ctx->tables_num; i++)
- if (ctx->tables[i] == table)
- return i;
-
- /*
- * Maybe we were asked to get the index of the base level table, which
- * should never happen.
- */
- assert(0);
-
- return -1;
-}
-
-/* Returns a pointer to an empty translation table. */
-static uint64_t *xlat_table_get_empty(xlat_ctx_t *ctx)
-{
- for (unsigned int i = 0; i < ctx->tables_num; i++)
- if (ctx->tables_mapped_regions[i] == 0)
- return ctx->tables[i];
-
- return NULL;
-}
-
-/* Increments region count for a given table. */
-static void xlat_table_inc_regions_count(xlat_ctx_t *ctx, const uint64_t *table)
-{
- ctx->tables_mapped_regions[xlat_table_get_index(ctx, table)]++;
-}
-
-/* Decrements region count for a given table. */
-static void xlat_table_dec_regions_count(xlat_ctx_t *ctx, const uint64_t *table)
-{
- ctx->tables_mapped_regions[xlat_table_get_index(ctx, table)]--;
-}
-
-/* Returns 0 if the speficied table isn't empty, otherwise 1. */
-static int xlat_table_is_empty(xlat_ctx_t *ctx, const uint64_t *table)
-{
- return !ctx->tables_mapped_regions[xlat_table_get_index(ctx, table)];
-}
-
-#else /* PLAT_XLAT_TABLES_DYNAMIC */
-
-/* Returns a pointer to the first empty translation table. */
-static uint64_t *xlat_table_get_empty(xlat_ctx_t *ctx)
-{
- assert(ctx->next_table < ctx->tables_num);
-
- return ctx->tables[ctx->next_table++];
-}
-
-#endif /* PLAT_XLAT_TABLES_DYNAMIC */
-
-/*
- * Returns a block/page table descriptor for the given level and attributes.
- */
-static uint64_t xlat_desc(const xlat_ctx_t *ctx, uint32_t attr,
- unsigned long long addr_pa, int level)
-{
- uint64_t desc;
- int mem_type;
-
- /* Make sure that the granularity is fine enough to map this address. */
- assert((addr_pa & XLAT_BLOCK_MASK(level)) == 0);
-
- desc = addr_pa;
- /*
- * There are different translation table descriptors for level 3 and the
- * rest.
- */
- desc |= (level == XLAT_TABLE_LEVEL_MAX) ? PAGE_DESC : BLOCK_DESC;
- /*
- * Always set the access flag, as TF doesn't manage access flag faults.
- * Deduce other fields of the descriptor based on the MT_NS and MT_RW
- * memory region attributes.
- */
- desc |= LOWER_ATTRS(ACCESS_FLAG);
-
- desc |= (attr & MT_NS) ? LOWER_ATTRS(NS) : 0;
- desc |= (attr & MT_RW) ? LOWER_ATTRS(AP_RW) : LOWER_ATTRS(AP_RO);
-
- /*
- * Do not allow unprivileged access when the mapping is for a privileged
- * EL. For translation regimes that do not have mappings for access for
- * lower exception levels, set AP[2] to AP_NO_ACCESS_UNPRIVILEGED.
- */
- if (ctx->xlat_regime == EL1_EL0_REGIME) {
- if (attr & MT_USER) {
- /* EL0 mapping requested, so we give User access */
- desc |= LOWER_ATTRS(AP_ACCESS_UNPRIVILEGED);
- } else {
- /* EL1 mapping requested, no User access granted */
- desc |= LOWER_ATTRS(AP_NO_ACCESS_UNPRIVILEGED);
- }
- } else {
- assert(ctx->xlat_regime == EL3_REGIME);
- desc |= LOWER_ATTRS(AP_ONE_VA_RANGE_RES1);
- }
-
- /*
- * Deduce shareability domain and executability of the memory region
- * from the memory type of the attributes (MT_TYPE).
- *
- * Data accesses to device memory and non-cacheable normal memory are
- * coherent for all observers in the system, and correspondingly are
- * always treated as being Outer Shareable. Therefore, for these 2 types
- * of memory, it is not strictly needed to set the shareability field
- * in the translation tables.
- */
- mem_type = MT_TYPE(attr);
- if (mem_type == MT_DEVICE) {
- desc |= LOWER_ATTRS(ATTR_DEVICE_INDEX | OSH);
- /*
- * Always map device memory as execute-never.
- * This is to avoid the possibility of a speculative instruction
- * fetch, which could be an issue if this memory region
- * corresponds to a read-sensitive peripheral.
- */
- desc |= xlat_arch_regime_get_xn_desc(ctx->xlat_regime);
-
- } else { /* Normal memory */
- /*
- * Always map read-write normal memory as execute-never.
- * (Trusted Firmware doesn't self-modify its code, therefore
- * R/W memory is reserved for data storage, which must not be
- * executable.)
- * Note that setting the XN bit here is for consistency only.
- * The function that enables the MMU sets the SCTLR_ELx.WXN bit,
- * which makes any writable memory region to be treated as
- * execute-never, regardless of the value of the XN bit in the
- * translation table.
- *
- * For read-only memory, rely on the MT_EXECUTE/MT_EXECUTE_NEVER
- * attribute to figure out the value of the XN bit. The actual
- * XN bit(s) to set in the descriptor depends on the context's
- * translation regime and the policy applied in
- * xlat_arch_regime_get_xn_desc().
- */
- if ((attr & MT_RW) || (attr & MT_EXECUTE_NEVER)) {
- desc |= xlat_arch_regime_get_xn_desc(ctx->xlat_regime);
- }
-
- if (mem_type == MT_MEMORY) {
- desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX | ISH);
- } else {
- assert(mem_type == MT_NON_CACHEABLE);
- desc |= LOWER_ATTRS(ATTR_NON_CACHEABLE_INDEX | OSH);
- }
- }
-
- return desc;
-}
-
-/*
- * Enumeration of actions that can be made when mapping table entries depending
- * on the previous value in that entry and information about the region being
- * mapped.
- */
-typedef enum {
-
- /* Do nothing */
- ACTION_NONE,
-
- /* Write a block (or page, if in level 3) entry. */
- ACTION_WRITE_BLOCK_ENTRY,
-
- /*
- * Create a new table and write a table entry pointing to it. Recurse
- * into it for further processing.
- */
- ACTION_CREATE_NEW_TABLE,
-
- /*
- * There is a table descriptor in this entry, read it and recurse into
- * that table for further processing.
- */
- ACTION_RECURSE_INTO_TABLE,
-
-} action_t;
-
-#if PLAT_XLAT_TABLES_DYNAMIC
-
-/*
- * Recursive function that writes to the translation tables and unmaps the
- * specified region.
- */
-static void xlat_tables_unmap_region(xlat_ctx_t *ctx, mmap_region_t *mm,
- const uintptr_t table_base_va,
- uint64_t *const table_base,
- const int table_entries,
- const unsigned int level)
-{
- assert(level >= ctx->base_level && level <= XLAT_TABLE_LEVEL_MAX);
-
- uint64_t *subtable;
- uint64_t desc;
-
- uintptr_t table_idx_va;
- uintptr_t table_idx_end_va; /* End VA of this entry */
-
- uintptr_t region_end_va = mm->base_va + mm->size - 1;
-
- int table_idx;
-
- if (mm->base_va > table_base_va) {
- /* Find the first index of the table affected by the region. */
- table_idx_va = mm->base_va & ~XLAT_BLOCK_MASK(level);
-
- table_idx = (table_idx_va - table_base_va) >>
- XLAT_ADDR_SHIFT(level);
-
- assert(table_idx < table_entries);
- } else {
- /* Start from the beginning of the table. */
- table_idx_va = table_base_va;
- table_idx = 0;
- }
-
- while (table_idx < table_entries) {
-
- table_idx_end_va = table_idx_va + XLAT_BLOCK_SIZE(level) - 1;
-
- desc = table_base[table_idx];
- uint64_t desc_type = desc & DESC_MASK;
-
- action_t action = ACTION_NONE;
-
- if ((mm->base_va <= table_idx_va) &&
- (region_end_va >= table_idx_end_va)) {
-
- /* Region covers all block */
-
- if (level == 3) {
- /*
- * Last level, only page descriptors allowed,
- * erase it.
- */
- assert(desc_type == PAGE_DESC);
-
- action = ACTION_WRITE_BLOCK_ENTRY;
- } else {
- /*
- * Other levels can have table descriptors. If
- * so, recurse into it and erase descriptors
- * inside it as needed. If there is a block
- * descriptor, just erase it. If an invalid
- * descriptor is found, this table isn't
- * actually mapped, which shouldn't happen.
- */
- if (desc_type == TABLE_DESC) {
- action = ACTION_RECURSE_INTO_TABLE;
- } else {
- assert(desc_type == BLOCK_DESC);
- action = ACTION_WRITE_BLOCK_ENTRY;
- }
- }
-
- } else if ((mm->base_va <= table_idx_end_va) ||
- (region_end_va >= table_idx_va)) {
-
- /*
- * Region partially covers block.
- *
- * It can't happen in level 3.
- *
- * There must be a table descriptor here, if not there
- * was a problem when mapping the region.
- */
-
- assert(level < 3);
-
- assert(desc_type == TABLE_DESC);
-
- action = ACTION_RECURSE_INTO_TABLE;
- }
-
- if (action == ACTION_WRITE_BLOCK_ENTRY) {
-
- table_base[table_idx] = INVALID_DESC;
- xlat_arch_tlbi_va_regime(table_idx_va, ctx->xlat_regime);
-
- } else if (action == ACTION_RECURSE_INTO_TABLE) {
-
- subtable = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK);
-
- /* Recurse to write into subtable */
- xlat_tables_unmap_region(ctx, mm, table_idx_va,
- subtable, XLAT_TABLE_ENTRIES,
- level + 1);
-
- /*
- * If the subtable is now empty, remove its reference.
- */
- if (xlat_table_is_empty(ctx, subtable)) {
- table_base[table_idx] = INVALID_DESC;
- xlat_arch_tlbi_va_regime(table_idx_va,
- ctx->xlat_regime);
- }
-
- } else {
- assert(action == ACTION_NONE);
- }
-
- table_idx++;
- table_idx_va += XLAT_BLOCK_SIZE(level);
-
- /* If reached the end of the region, exit */
- if (region_end_va <= table_idx_va)
- break;
- }
-
- if (level > ctx->base_level)
- xlat_table_dec_regions_count(ctx, table_base);
-}
-
-#endif /* PLAT_XLAT_TABLES_DYNAMIC */
-
-/*
- * From the given arguments, it decides which action to take when mapping the
- * specified region.
- */
-static action_t xlat_tables_map_region_action(const mmap_region_t *mm,
- const int desc_type, const unsigned long long dest_pa,
- const uintptr_t table_entry_base_va, const unsigned int level)
-{
- uintptr_t mm_end_va = mm->base_va + mm->size - 1;
- uintptr_t table_entry_end_va =
- table_entry_base_va + XLAT_BLOCK_SIZE(level) - 1;
-
- /*
- * The descriptor types allowed depend on the current table level.
- */
-
- if ((mm->base_va <= table_entry_base_va) &&
- (mm_end_va >= table_entry_end_va)) {
-
- /*
- * Table entry is covered by region
- * --------------------------------
- *
- * This means that this table entry can describe the whole
- * translation with this granularity in principle.
- */
-
- if (level == 3) {
- /*
- * Last level, only page descriptors are allowed.
- */
- if (desc_type == PAGE_DESC) {
- /*
- * There's another region mapped here, don't
- * overwrite.
- */
- return ACTION_NONE;
- } else {
- assert(desc_type == INVALID_DESC);
- return ACTION_WRITE_BLOCK_ENTRY;
- }
-
- } else {
-
- /*
- * Other levels. Table descriptors are allowed. Block
- * descriptors too, but they have some limitations.
- */
-
- if (desc_type == TABLE_DESC) {
- /* There's already a table, recurse into it. */
- return ACTION_RECURSE_INTO_TABLE;
-
- } else if (desc_type == INVALID_DESC) {
- /*
- * There's nothing mapped here, create a new
- * entry.
- *
- * Check if the destination granularity allows
- * us to use a block descriptor or we need a
- * finer table for it.
- *
- * Also, check if the current level allows block
- * descriptors. If not, create a table instead.
- */
- if ((dest_pa & XLAT_BLOCK_MASK(level)) ||
- (level < MIN_LVL_BLOCK_DESC) ||
- (mm->granularity < XLAT_BLOCK_SIZE(level)))
- return ACTION_CREATE_NEW_TABLE;
- else
- return ACTION_WRITE_BLOCK_ENTRY;
-
- } else {
- /*
- * There's another region mapped here, don't
- * overwrite.
- */
- assert(desc_type == BLOCK_DESC);
-
- return ACTION_NONE;
- }
- }
-
- } else if ((mm->base_va <= table_entry_end_va) ||
- (mm_end_va >= table_entry_base_va)) {
-
- /*
- * Region partially covers table entry
- * -----------------------------------
- *
- * This means that this table entry can't describe the whole
- * translation, a finer table is needed.
-
- * There cannot be partial block overlaps in level 3. If that
- * happens, some of the preliminary checks when adding the
- * mmap region failed to detect that PA and VA must at least be
- * aligned to PAGE_SIZE.
- */
- assert(level < 3);
-
- if (desc_type == INVALID_DESC) {
- /*
- * The block is not fully covered by the region. Create
- * a new table, recurse into it and try to map the
- * region with finer granularity.
- */
- return ACTION_CREATE_NEW_TABLE;
-
- } else {
- assert(desc_type == TABLE_DESC);
- /*
- * The block is not fully covered by the region, but
- * there is already a table here. Recurse into it and
- * try to map with finer granularity.
- *
- * PAGE_DESC for level 3 has the same value as
- * TABLE_DESC, but this code can't run on a level 3
- * table because there can't be overlaps in level 3.
- */
- return ACTION_RECURSE_INTO_TABLE;
- }
- }
-
- /*
- * This table entry is outside of the region specified in the arguments,
- * don't write anything to it.
- */
- return ACTION_NONE;
-}
-
-/*
- * Recursive function that writes to the translation tables and maps the
- * specified region. On success, it returns the VA of the last byte that was
- * succesfully mapped. On error, it returns the VA of the next entry that
- * should have been mapped.
- */
-static uintptr_t xlat_tables_map_region(xlat_ctx_t *ctx, mmap_region_t *mm,
- const uintptr_t table_base_va,
- uint64_t *const table_base,
- const int table_entries,
- const unsigned int level)
-{
- assert(level >= ctx->base_level && level <= XLAT_TABLE_LEVEL_MAX);
-
- uintptr_t mm_end_va = mm->base_va + mm->size - 1;
-
- uintptr_t table_idx_va;
- unsigned long long table_idx_pa;
-
- uint64_t *subtable;
- uint64_t desc;
-
- int table_idx;
-
- if (mm->base_va > table_base_va) {
- /* Find the first index of the table affected by the region. */
- table_idx_va = mm->base_va & ~XLAT_BLOCK_MASK(level);
-
- table_idx = (table_idx_va - table_base_va) >>
- XLAT_ADDR_SHIFT(level);
-
- assert(table_idx < table_entries);
- } else {
- /* Start from the beginning of the table. */
- table_idx_va = table_base_va;
- table_idx = 0;
- }
-
-#if PLAT_XLAT_TABLES_DYNAMIC
- if (level > ctx->base_level)
- xlat_table_inc_regions_count(ctx, table_base);
-#endif
-
- while (table_idx < table_entries) {
-
- desc = table_base[table_idx];
-
- table_idx_pa = mm->base_pa + table_idx_va - mm->base_va;
-
- action_t action = xlat_tables_map_region_action(mm,
- desc & DESC_MASK, table_idx_pa, table_idx_va, level);
-
- if (action == ACTION_WRITE_BLOCK_ENTRY) {
-
- table_base[table_idx] =
- xlat_desc(ctx, (uint32_t)mm->attr, table_idx_pa,
- level);
-
- } else if (action == ACTION_CREATE_NEW_TABLE) {
-
- subtable = xlat_table_get_empty(ctx);
- if (subtable == NULL) {
- /* Not enough free tables to map this region */
- return table_idx_va;
- }
-
- /* Point to new subtable from this one. */
- table_base[table_idx] = TABLE_DESC | (unsigned long)subtable;
-
- /* Recurse to write into subtable */
- uintptr_t end_va = xlat_tables_map_region(ctx, mm, table_idx_va,
- subtable, XLAT_TABLE_ENTRIES,
- level + 1);
- if (end_va != table_idx_va + XLAT_BLOCK_SIZE(level) - 1)
- return end_va;
-
- } else if (action == ACTION_RECURSE_INTO_TABLE) {
-
- subtable = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK);
- /* Recurse to write into subtable */
- uintptr_t end_va = xlat_tables_map_region(ctx, mm, table_idx_va,
- subtable, XLAT_TABLE_ENTRIES,
- level + 1);
- if (end_va != table_idx_va + XLAT_BLOCK_SIZE(level) - 1)
- return end_va;
-
- } else {
-
- assert(action == ACTION_NONE);
-
- }
-
- table_idx++;
- table_idx_va += XLAT_BLOCK_SIZE(level);
-
- /* If reached the end of the region, exit */
- if (mm_end_va <= table_idx_va)
- break;
- }
-
- return table_idx_va - 1;
-}
-
-void print_mmap(mmap_region_t *const mmap)
-{
-#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
- tf_printf("mmap:\n");
- mmap_region_t *mm = mmap;
-
- while (mm->size) {
- tf_printf(" VA:%p PA:0x%llx size:0x%zx attr:0x%x",
- (void *)mm->base_va, mm->base_pa,
- mm->size, mm->attr);
- tf_printf(" granularity:0x%zx\n", mm->granularity);
- ++mm;
- };
- tf_printf("\n");
-#endif
-}
-
-/*
- * 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(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;
- size_t granularity = mm->granularity;
-
- unsigned long long end_pa = base_pa + size - 1;
- uintptr_t end_va = base_va + size - 1;
-
- if (!IS_PAGE_ALIGNED(base_pa) || !IS_PAGE_ALIGNED(base_va) ||
- !IS_PAGE_ALIGNED(size))
- return -EINVAL;
-
- if ((granularity != XLAT_BLOCK_SIZE(1)) &&
- (granularity != XLAT_BLOCK_SIZE(2)) &&
- (granularity != XLAT_BLOCK_SIZE(3))) {
- return -EINVAL;
- }
-
- /* Check for overflows */
- if ((base_pa > end_pa) || (base_va > end_va))
- return -ERANGE;
-
- if ((base_va + (uintptr_t)size - (uintptr_t)1) > ctx->va_max_address)
- return -ERANGE;
-
- if ((base_pa + (unsigned long long)size - 1ULL) > ctx->pa_max_address)
- return -ERANGE;
-
- /* Check that there is space in the ctx->mmap array */
- if (ctx->mmap[ctx->mmap_num - 1].size != 0)
- return -ENOMEM;
-
- /* Check for PAs and VAs overlaps with all other regions */
- for (mmap_region_t *mm_cursor = ctx->mmap;
- mm_cursor->size; ++mm_cursor) {
-
- uintptr_t mm_cursor_end_va = mm_cursor->base_va
- + mm_cursor->size - 1;
-
- /*
- * Check if one of the regions is completely inside the other
- * one.
- */
- int 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) ||
- (mm_cursor->attr & MT_DYNAMIC))
- 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 - 1;
-
- int separated_pa =
- (end_pa < mm_cursor->base_pa) ||
- (base_pa > mm_cursor_end_pa);
- int 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;
- mmap_region_t *mm_last;
- unsigned long long end_pa = mm->base_pa + mm->size - 1;
- uintptr_t end_va = mm->base_va + mm->size - 1;
- int ret;
-
- /* Ignore empty regions */
- if (!mm->size)
- 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(0);
- return;
- }
-
- /*
- * Find correct place in mmap to insert new region.
- *
- * 1 - Lower region VA end first.
- * 2 - Smaller region size first.
- *
- * VA 0 0xFF
- *
- * 1st |------|
- * 2nd |------------|
- * 3rd |------|
- * 4th |---|
- * 5th |---|
- * 6th |----------|
- * 7th |-------------------------------------|
- *
- * This is required for overlapping regions only. It simplifies adding
- * regions with the loop in xlat_tables_init_internal because the outer
- * ones won't overwrite block or page descriptors of regions added
- * previously.
- *
- * Overlapping is only allowed for static regions.
- */
-
- while ((mm_cursor->base_va + mm_cursor->size - 1) < end_va
- && mm_cursor->size)
- ++mm_cursor;
-
- while ((mm_cursor->base_va + mm_cursor->size - 1 == end_va) &&
- (mm_cursor->size != 0U) && (mm_cursor->size < mm->size))
- ++mm_cursor;
-
- /*
- * 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;
- 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_region(unsigned long long base_pa, uintptr_t base_va, size_t size,
- unsigned int attr)
-{
- mmap_region_t mm = MAP_REGION(base_pa, base_va, size, attr);
- mmap_add_region_ctx(&tf_xlat_ctx, &mm);
-}
-
-
-void mmap_add_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm)
-{
- while (mm->size) {
- mmap_add_region_ctx(ctx, mm);
- mm++;
- }
-}
-
-void mmap_add(const mmap_region_t *mm)
-{
- mmap_add_ctx(&tf_xlat_ctx, mm);
-}
-
-#if PLAT_XLAT_TABLES_DYNAMIC
-
-int mmap_add_dynamic_region_ctx(xlat_ctx_t *ctx, mmap_region_t *mm)
-{
- mmap_region_t *mm_cursor = ctx->mmap;
- mmap_region_t *mm_last = mm_cursor + ctx->mmap_num;
- unsigned long long end_pa = mm->base_pa + mm->size - 1;
- uintptr_t end_va = mm->base_va + mm->size - 1;
- int ret;
-
- /* Nothing to do */
- if (!mm->size)
- return 0;
-
- /* Now this region is a dynamic one */
- mm->attr |= MT_DYNAMIC;
-
- ret = mmap_add_region_check(ctx, mm);
- if (ret != 0)
- return ret;
-
- /*
- * Find the adequate entry in the mmap array in the same way done for
- * static regions in mmap_add_region_ctx().
- */
-
- while ((mm_cursor->base_va + mm_cursor->size - 1)
- < end_va && mm_cursor->size)
- ++mm_cursor;
-
- while ((mm_cursor->base_va + mm_cursor->size - 1 == end_va)
- && (mm_cursor->size < mm->size))
- ++mm_cursor;
-
- /* Make room for new region by moving other regions up by one place */
- memmove(mm_cursor + 1, mm_cursor,
- (uintptr_t)mm_last - (uintptr_t)mm_cursor);
-
- /*
- * Check we haven't lost the empty sentinal 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_last->size == 0);
-
- *mm_cursor = *mm;
-
- /*
- * Update the translation tables if the xlat tables are initialized. If
- * not, this region will be mapped when they are initialized.
- */
- if (ctx->initialized) {
- uintptr_t end_va = xlat_tables_map_region(ctx, mm_cursor,
- 0, ctx->base_table, ctx->base_table_entries,
- ctx->base_level);
-
- /* Failed to map, remove mmap entry, unmap and return error. */
- if (end_va != mm_cursor->base_va + mm_cursor->size - 1) {
- memmove(mm_cursor, mm_cursor + 1,
- (uintptr_t)mm_last - (uintptr_t)mm_cursor);
-
- /*
- * Check if the mapping function actually managed to map
- * anything. If not, just return now.
- */
- if (mm->base_va >= end_va)
- return -ENOMEM;
-
- /*
- * Something went wrong after mapping some table
- * entries, undo every change done up to this point.
- */
- mmap_region_t unmap_mm = {
- .base_pa = 0,
- .base_va = mm->base_va,
- .size = end_va - mm->base_va,
- .attr = 0
- };
- xlat_tables_unmap_region(ctx, &unmap_mm, 0, ctx->base_table,
- ctx->base_table_entries, ctx->base_level);
-
- return -ENOMEM;
- }
-
- /*
- * Make sure that all entries are written to the memory. There
- * is no need to invalidate entries when mapping dynamic regions
- * because new table/block/page descriptors only replace old
- * invalid descriptors, that aren't TLB cached.
- */
- dsbishst();
- }
-
- if (end_pa > ctx->max_pa)
- ctx->max_pa = end_pa;
- if (end_va > ctx->max_va)
- ctx->max_va = end_va;
-
- return 0;
-}
-
-int mmap_add_dynamic_region(unsigned long long base_pa, uintptr_t base_va,
- size_t size, unsigned int attr)
-{
- mmap_region_t mm = MAP_REGION(base_pa, base_va, size, attr);
- return mmap_add_dynamic_region_ctx(&tf_xlat_ctx, &mm);
-}
-
-/*
- * Removes the region with given base Virtual Address and size from the given
- * context.
- *
- * Returns:
- * 0: Success.
- * EINVAL: Invalid values were used as arguments (region not found).
- * EPERM: Tried to remove a static region.
- */
-int mmap_remove_dynamic_region_ctx(xlat_ctx_t *ctx, uintptr_t base_va,
- size_t size)
-{
- mmap_region_t *mm = ctx->mmap;
- mmap_region_t *mm_last = mm + ctx->mmap_num;
- int update_max_va_needed = 0;
- int update_max_pa_needed = 0;
-
- /* Check sanity of mmap array. */
- assert(mm[ctx->mmap_num].size == 0);
-
- while (mm->size) {
- if ((mm->base_va == base_va) && (mm->size == size))
- break;
- ++mm;
- }
-
- /* Check that the region was found */
- if (mm->size == 0)
- return -EINVAL;
-
- /* If the region is static it can't be removed */
- if (!(mm->attr & MT_DYNAMIC))
- return -EPERM;
-
- /* Check if this region is using the top VAs or PAs. */
- if ((mm->base_va + mm->size - 1) == ctx->max_va)
- update_max_va_needed = 1;
- if ((mm->base_pa + mm->size - 1) == ctx->max_pa)
- update_max_pa_needed = 1;
-
- /* Update the translation tables if needed */
- if (ctx->initialized) {
- xlat_tables_unmap_region(ctx, mm, 0, ctx->base_table,
- ctx->base_table_entries,
- ctx->base_level);
- xlat_arch_tlbi_va_sync();
- }
-
- /* Remove this region by moving the rest down by one place. */
- memmove(mm, mm + 1, (uintptr_t)mm_last - (uintptr_t)mm);
-
- /* Check if we need to update the max VAs and PAs */
- if (update_max_va_needed) {
- ctx->max_va = 0;
- mm = ctx->mmap;
- while (mm->size) {
- if ((mm->base_va + mm->size - 1) > ctx->max_va)
- ctx->max_va = mm->base_va + mm->size - 1;
- ++mm;
- }
- }
-
- if (update_max_pa_needed) {
- ctx->max_pa = 0;
- mm = ctx->mmap;
- while (mm->size) {
- if ((mm->base_pa + mm->size - 1) > ctx->max_pa)
- ctx->max_pa = mm->base_pa + mm->size - 1;
- ++mm;
- }
- }
-
- return 0;
-}
-
-int mmap_remove_dynamic_region(uintptr_t base_va, size_t size)
-{
- return mmap_remove_dynamic_region_ctx(&tf_xlat_ctx,
- base_va, size);
-}
-
-#endif /* PLAT_XLAT_TABLES_DYNAMIC */
-
-#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
-
-/* Print the attributes of the specified block descriptor. */
-static void xlat_desc_print(const xlat_ctx_t *ctx, uint64_t desc)
-{
- int mem_type_index = ATTR_INDEX_GET(desc);
- xlat_regime_t xlat_regime = ctx->xlat_regime;
-
- if (mem_type_index == ATTR_IWBWA_OWBWA_NTR_INDEX) {
- tf_printf("MEM");
- } else if (mem_type_index == ATTR_NON_CACHEABLE_INDEX) {
- tf_printf("NC");
- } else {
- assert(mem_type_index == ATTR_DEVICE_INDEX);
- tf_printf("DEV");
- }
-
- const char *priv_str = "(PRIV)";
- const char *user_str = "(USER)";
-
- /*
- * Showing Privileged vs Unprivileged only makes sense for EL1&0
- * mappings
- */
- const char *ro_str = "-RO";
- const char *rw_str = "-RW";
- const char *no_access_str = "-NOACCESS";
-
- if (xlat_regime == EL3_REGIME) {
- /* For EL3, the AP[2] bit is all what matters */
- tf_printf("%s", (desc & LOWER_ATTRS(AP_RO)) ? ro_str : rw_str);
- } else {
- const char *ap_str = (desc & LOWER_ATTRS(AP_RO)) ? ro_str : rw_str;
- tf_printf("%s", ap_str);
- tf_printf("%s", priv_str);
- /*
- * EL0 can only have the same permissions as EL1 or no
- * permissions at all.
- */
- tf_printf("%s",
- (desc & LOWER_ATTRS(AP_ACCESS_UNPRIVILEGED))
- ? ap_str : no_access_str);
- tf_printf("%s", user_str);
- }
-
- const char *xn_str = "-XN";
- const char *exec_str = "-EXEC";
-
- if (xlat_regime == EL3_REGIME) {
- /* For EL3, the XN bit is all what matters */
- tf_printf("%s", (UPPER_ATTRS(XN) & desc) ? xn_str : exec_str);
- } else {
- /* For EL0 and EL1, we need to know who has which rights */
- tf_printf("%s", (UPPER_ATTRS(PXN) & desc) ? xn_str : exec_str);
- tf_printf("%s", priv_str);
-
- tf_printf("%s", (UPPER_ATTRS(UXN) & desc) ? xn_str : exec_str);
- tf_printf("%s", user_str);
- }
-
- tf_printf(LOWER_ATTRS(NS) & desc ? "-NS" : "-S");
-}
-
-static const char * const level_spacers[] = {
- "[LV0] ",
- " [LV1] ",
- " [LV2] ",
- " [LV3] "
-};
-
-static const char *invalid_descriptors_ommited =
- "%s(%d invalid descriptors omitted)\n";
-
-/*
- * Recursive function that reads the translation tables passed as an argument
- * and prints their status.
- */
-static void xlat_tables_print_internal(xlat_ctx_t *ctx,
- const uintptr_t table_base_va,
- uint64_t *const table_base, const int table_entries,
- const unsigned int level)
-{
- assert(level <= XLAT_TABLE_LEVEL_MAX);
-
- uint64_t desc;
- uintptr_t table_idx_va = table_base_va;
- int table_idx = 0;
-
- size_t level_size = XLAT_BLOCK_SIZE(level);
-
- /*
- * Keep track of how many invalid descriptors are counted in a row.
- * Whenever multiple invalid descriptors are found, only the first one
- * is printed, and a line is added to inform about how many descriptors
- * have been omitted.
- */
- int invalid_row_count = 0;
-
- while (table_idx < table_entries) {
-
- desc = table_base[table_idx];
-
- if ((desc & DESC_MASK) == INVALID_DESC) {
-
- if (invalid_row_count == 0) {
- tf_printf("%sVA:%p size:0x%zx\n",
- level_spacers[level],
- (void *)table_idx_va, level_size);
- }
- invalid_row_count++;
-
- } else {
-
- if (invalid_row_count > 1) {
- tf_printf(invalid_descriptors_ommited,
- level_spacers[level],
- invalid_row_count - 1);
- }
- invalid_row_count = 0;
-
- /*
- * Check if this is a table or a block. Tables are only
- * allowed in levels other than 3, but DESC_PAGE has the
- * same value as DESC_TABLE, so we need to check.
- */
- if (((desc & DESC_MASK) == TABLE_DESC) &&
- (level < XLAT_TABLE_LEVEL_MAX)) {
- /*
- * Do not print any PA for a table descriptor,
- * as it doesn't directly map physical memory
- * but instead points to the next translation
- * table in the translation table walk.
- */
- tf_printf("%sVA:%p size:0x%zx\n",
- level_spacers[level],
- (void *)table_idx_va, level_size);
-
- uintptr_t addr_inner = desc & TABLE_ADDR_MASK;
-
- xlat_tables_print_internal(ctx, table_idx_va,
- (uint64_t *)addr_inner,
- XLAT_TABLE_ENTRIES, level + 1);
- } else {
- tf_printf("%sVA:%p PA:0x%llx size:0x%zx ",
- level_spacers[level],
- (void *)table_idx_va,
- (unsigned long long)(desc & TABLE_ADDR_MASK),
- level_size);
- xlat_desc_print(ctx, desc);
- tf_printf("\n");
- }
- }
-
- table_idx++;
- table_idx_va += level_size;
- }
-
- if (invalid_row_count > 1) {
- tf_printf(invalid_descriptors_ommited,
- level_spacers[level], invalid_row_count - 1);
- }
-}
-
-#endif /* LOG_LEVEL >= LOG_LEVEL_VERBOSE */
-
-void xlat_tables_print(xlat_ctx_t *ctx)
-{
-#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
- const char *xlat_regime_str;
- if (ctx->xlat_regime == EL1_EL0_REGIME) {
- xlat_regime_str = "1&0";
- } else {
- assert(ctx->xlat_regime == EL3_REGIME);
- xlat_regime_str = "3";
- }
- 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: %p\n", (void *) ctx->va_max_address);
- VERBOSE(" Max mapped PA: 0x%llx\n", ctx->max_pa);
- VERBOSE(" Max mapped VA: %p\n", (void *) ctx->max_va);
-
- VERBOSE(" Initial lookup level: %i\n", ctx->base_level);
- VERBOSE(" Entries @initial lookup level: %i\n",
- ctx->base_table_entries);
-
- int used_page_tables;
-#if PLAT_XLAT_TABLES_DYNAMIC
- used_page_tables = 0;
- for (unsigned int i = 0; i < ctx->tables_num; ++i) {
- if (ctx->tables_mapped_regions[i] != 0)
- ++used_page_tables;
- }
-#else
- used_page_tables = ctx->next_table;
-#endif
- VERBOSE(" Used %i sub-tables out of %i (spare: %i)\n",
- used_page_tables, ctx->tables_num,
- ctx->tables_num - used_page_tables);
-
- xlat_tables_print_internal(ctx, 0, ctx->base_table,
- ctx->base_table_entries, ctx->base_level);
-#endif /* LOG_LEVEL >= LOG_LEVEL_VERBOSE */
-}
-
-void init_xlat_tables_ctx(xlat_ctx_t *ctx)
-{
- assert(ctx != NULL);
- assert(!ctx->initialized);
- assert(ctx->xlat_regime == EL3_REGIME || ctx->xlat_regime == EL1_EL0_REGIME);
- assert(!is_mmu_enabled_ctx(ctx));
-
- mmap_region_t *mm = ctx->mmap;
-
- print_mmap(mm);
-
- /* All tables must be zeroed before mapping any region. */
-
- for (unsigned int i = 0; i < ctx->base_table_entries; i++)
- ctx->base_table[i] = INVALID_DESC;
-
- for (unsigned int j = 0; j < ctx->tables_num; j++) {
-#if PLAT_XLAT_TABLES_DYNAMIC
- ctx->tables_mapped_regions[j] = 0;
-#endif
- for (unsigned int i = 0; i < XLAT_TABLE_ENTRIES; i++)
- ctx->tables[j][i] = INVALID_DESC;
- }
-
- while (mm->size) {
- uintptr_t end_va = xlat_tables_map_region(ctx, mm, 0, ctx->base_table,
- ctx->base_table_entries, ctx->base_level);
-
- if (end_va != mm->base_va + mm->size - 1) {
- ERROR("Not enough memory to map region:\n"
- " VA:%p PA:0x%llx size:0x%zx attr:0x%x\n",
- (void *)mm->base_va, mm->base_pa, mm->size, mm->attr);
- panic();
- }
-
- mm++;
- }
-
- assert(ctx->pa_max_address <= xlat_arch_get_max_supported_pa());
- assert(ctx->max_va <= ctx->va_max_address);
- assert(ctx->max_pa <= ctx->pa_max_address);
-
- ctx->initialized = 1;
-
- xlat_tables_print(ctx);
-}
-
-void init_xlat_tables(void)
-{
- init_xlat_tables_ctx(&tf_xlat_ctx);
-}
-
-/*
- * If dynamic allocation of new regions is disabled then by the time we call the
- * function enabling the MMU, we'll have registered all the memory regions to
- * map for the system's lifetime. Therefore, at this point we know the maximum
- * physical address that will ever be mapped.
- *
- * If dynamic allocation is enabled then we can't make any such assumption
- * because the maximum physical address could get pushed while adding a new
- * region. Therefore, in this case we have to assume that the whole address
- * space size might be mapped.
- */
-#ifdef PLAT_XLAT_TABLES_DYNAMIC
-#define MAX_PHYS_ADDR tf_xlat_ctx.pa_max_address
-#else
-#define MAX_PHYS_ADDR tf_xlat_ctx.max_pa
-#endif
-
-#ifdef AARCH32
-
-void enable_mmu_secure(unsigned int flags)
-{
- setup_mmu_cfg(flags, tf_xlat_ctx.base_table, MAX_PHYS_ADDR,
- tf_xlat_ctx.va_max_address);
- enable_mmu_direct(flags);
-}
-
-#else
-
-void enable_mmu_el1(unsigned int flags)
-{
- setup_mmu_cfg(flags, tf_xlat_ctx.base_table, MAX_PHYS_ADDR,
- tf_xlat_ctx.va_max_address);
- enable_mmu_direct_el1(flags);
-}
-
-void enable_mmu_el3(unsigned int flags)
-{
- setup_mmu_cfg(flags, tf_xlat_ctx.base_table, MAX_PHYS_ADDR,
- tf_xlat_ctx.va_max_address);
- enable_mmu_direct_el3(flags);
-}
-
-#endif /* AARCH32 */
-
-/*
- * Do a translation table walk to find the block or page descriptor that maps
- * virtual_addr.
- *
- * On success, return the address of the descriptor within the translation
- * table. Its lookup level is stored in '*out_level'.
- * On error, return NULL.
- *
- * xlat_table_base
- * Base address for the initial lookup level.
- * xlat_table_base_entries
- * Number of entries in the translation table for the initial lookup level.
- * virt_addr_space_size
- * Size in bytes of the virtual address space.
- */
-static uint64_t *find_xlat_table_entry(uintptr_t virtual_addr,
- void *xlat_table_base,
- int xlat_table_base_entries,
- unsigned long long virt_addr_space_size,
- int *out_level)
-{
- unsigned int start_level;
- uint64_t *table;
- int entries;
-
- VERBOSE("%s(%p)\n", __func__, (void *)virtual_addr);
-
- start_level = GET_XLAT_TABLE_LEVEL_BASE(virt_addr_space_size);
- VERBOSE("Starting translation table walk from level %i\n", start_level);
-
- table = xlat_table_base;
- entries = xlat_table_base_entries;
-
- for (unsigned int level = start_level;
- level <= XLAT_TABLE_LEVEL_MAX;
- ++level) {
- int idx;
- uint64_t desc;
- uint64_t desc_type;
-
- VERBOSE("Table address: %p\n", (void *)table);
-
- idx = XLAT_TABLE_IDX(virtual_addr, level);
- VERBOSE("Index into level %i table: %i\n", level, idx);
- if (idx >= entries) {
- VERBOSE("Invalid address\n");
- return NULL;
- }
-
- desc = table[idx];
- desc_type = desc & DESC_MASK;
- VERBOSE("Descriptor at level %i: 0x%llx\n", level,
- (unsigned long long)desc);
-
- if (desc_type == INVALID_DESC) {
- VERBOSE("Invalid entry (memory not mapped)\n");
- return NULL;
- }
-
- if (level == XLAT_TABLE_LEVEL_MAX) {
- /*
- * There can't be table entries at the final lookup
- * level.
- */
- assert(desc_type == PAGE_DESC);
- VERBOSE("Descriptor mapping a memory page (size: 0x%llx)\n",
- (unsigned long long)XLAT_BLOCK_SIZE(XLAT_TABLE_LEVEL_MAX));
- *out_level = level;
- return &table[idx];
- }
-
- if (desc_type == BLOCK_DESC) {
- VERBOSE("Descriptor mapping a memory block (size: 0x%llx)\n",
- (unsigned long long)XLAT_BLOCK_SIZE(level));
- *out_level = level;
- return &table[idx];
- }
-
- assert(desc_type == TABLE_DESC);
- VERBOSE("Table descriptor, continuing xlat table walk...\n");
- table = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK);
- entries = XLAT_TABLE_ENTRIES;
- }
-
- /*
- * This shouldn't be reached, the translation table walk should end at
- * most at level XLAT_TABLE_LEVEL_MAX and return from inside the loop.
- */
- assert(0);
-
- return NULL;
-}
-
-
-static int get_mem_attributes_internal(const xlat_ctx_t *ctx, uintptr_t base_va,
- uint32_t *attributes, uint64_t **table_entry,
- unsigned long long *addr_pa, int *table_level)
-{
- uint64_t *entry;
- uint64_t desc;
- int level;
- unsigned long long virt_addr_space_size;
-
- /*
- * Sanity-check arguments.
- */
- assert(ctx != NULL);
- assert(ctx->initialized);
- assert(ctx->xlat_regime == EL1_EL0_REGIME || ctx->xlat_regime == EL3_REGIME);
-
- virt_addr_space_size = (unsigned long long)ctx->va_max_address + 1;
- assert(virt_addr_space_size > 0);
-
- entry = find_xlat_table_entry(base_va,
- ctx->base_table,
- ctx->base_table_entries,
- virt_addr_space_size,
- &level);
- if (entry == NULL) {
- WARN("Address %p is not mapped.\n", (void *)base_va);
- return -EINVAL;
- }
-
- if (addr_pa != NULL) {
- *addr_pa = *entry & TABLE_ADDR_MASK;
- }
-
- if (table_entry != NULL) {
- *table_entry = entry;
- }
-
- if (table_level != NULL) {
- *table_level = level;
- }
-
- desc = *entry;
-
-#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
- VERBOSE("Attributes: ");
- xlat_desc_print(ctx, desc);
- tf_printf("\n");
-#endif /* LOG_LEVEL >= LOG_LEVEL_VERBOSE */
-
- assert(attributes != NULL);
- *attributes = 0;
-
- int attr_index = (desc >> ATTR_INDEX_SHIFT) & ATTR_INDEX_MASK;
-
- if (attr_index == ATTR_IWBWA_OWBWA_NTR_INDEX) {
- *attributes |= MT_MEMORY;
- } else if (attr_index == ATTR_NON_CACHEABLE_INDEX) {
- *attributes |= MT_NON_CACHEABLE;
- } else {
- assert(attr_index == ATTR_DEVICE_INDEX);
- *attributes |= MT_DEVICE;
- }
-
- int ap2_bit = (desc >> AP2_SHIFT) & 1;
-
- if (ap2_bit == AP2_RW)
- *attributes |= MT_RW;
-
- if (ctx->xlat_regime == EL1_EL0_REGIME) {
- int ap1_bit = (desc >> AP1_SHIFT) & 1;
- if (ap1_bit == AP1_ACCESS_UNPRIVILEGED)
- *attributes |= MT_USER;
- }
-
- int ns_bit = (desc >> NS_SHIFT) & 1;
-
- if (ns_bit == 1)
- *attributes |= MT_NS;
-
- uint64_t xn_mask = xlat_arch_regime_get_xn_desc(ctx->xlat_regime);
-
- if ((desc & xn_mask) == xn_mask) {
- *attributes |= MT_EXECUTE_NEVER;
- } else {
- assert((desc & xn_mask) == 0);
- }
-
- return 0;
-}
-
-
-int get_mem_attributes(const xlat_ctx_t *ctx, uintptr_t base_va,
- uint32_t *attributes)
-{
- return get_mem_attributes_internal(ctx, base_va, attributes,
- NULL, NULL, NULL);
-}
-
-
-int change_mem_attributes(xlat_ctx_t *ctx,
- uintptr_t base_va,
- size_t size,
- uint32_t attr)
-{
- /* Note: This implementation isn't optimized. */
-
- assert(ctx != NULL);
- assert(ctx->initialized);
-
- unsigned long long virt_addr_space_size =
- (unsigned long long)ctx->va_max_address + 1;
- assert(virt_addr_space_size > 0);
-
- if (!IS_PAGE_ALIGNED(base_va)) {
- WARN("%s: Address %p is not aligned on a page boundary.\n",
- __func__, (void *)base_va);
- return -EINVAL;
- }
-
- if (size == 0) {
- WARN("%s: Size is 0.\n", __func__);
- return -EINVAL;
- }
-
- if ((size % PAGE_SIZE) != 0) {
- WARN("%s: Size 0x%zx is not a multiple of a page size.\n",
- __func__, size);
- return -EINVAL;
- }
-
- if (((attr & MT_EXECUTE_NEVER) == 0) && ((attr & MT_RW) != 0)) {
- WARN("%s() doesn't allow to remap memory as read-write and executable.\n",
- __func__);
- return -EINVAL;
- }
-
- int pages_count = size / PAGE_SIZE;
-
- VERBOSE("Changing memory attributes of %i pages starting from address %p...\n",
- pages_count, (void *)base_va);
-
- uintptr_t base_va_original = base_va;
-
- /*
- * Sanity checks.
- */
- for (int i = 0; i < pages_count; ++i) {
- uint64_t *entry;
- uint64_t desc;
- int level;
-
- entry = find_xlat_table_entry(base_va,
- ctx->base_table,
- ctx->base_table_entries,
- virt_addr_space_size,
- &level);
- if (entry == NULL) {
- WARN("Address %p is not mapped.\n", (void *)base_va);
- return -EINVAL;
- }
-
- desc = *entry;
-
- /*
- * Check that all the required pages are mapped at page
- * granularity.
- */
- if (((desc & DESC_MASK) != PAGE_DESC) ||
- (level != XLAT_TABLE_LEVEL_MAX)) {
- WARN("Address %p is not mapped at the right granularity.\n",
- (void *)base_va);
- WARN("Granularity is 0x%llx, should be 0x%x.\n",
- (unsigned long long)XLAT_BLOCK_SIZE(level), PAGE_SIZE);
- return -EINVAL;
- }
-
- /*
- * If the region type is device, it shouldn't be executable.
- */
- int attr_index = (desc >> ATTR_INDEX_SHIFT) & ATTR_INDEX_MASK;
- if (attr_index == ATTR_DEVICE_INDEX) {
- if ((attr & MT_EXECUTE_NEVER) == 0) {
- WARN("Setting device memory as executable at address %p.",
- (void *)base_va);
- return -EINVAL;
- }
- }
-
- base_va += PAGE_SIZE;
- }
-
- /* Restore original value. */
- base_va = base_va_original;
-
- VERBOSE("%s: All pages are mapped, now changing their attributes...\n",
- __func__);
-
- for (int i = 0; i < pages_count; ++i) {
-
- uint32_t old_attr, new_attr;
- uint64_t *entry;
- int level;
- unsigned long long addr_pa;
-
- get_mem_attributes_internal(ctx, base_va, &old_attr,
- &entry, &addr_pa, &level);
-
- VERBOSE("Old attributes: 0x%x\n", old_attr);
-
- /*
- * From attr, only MT_RO/MT_RW, MT_EXECUTE/MT_EXECUTE_NEVER and
- * MT_USER/MT_PRIVILEGED are taken into account. Any other
- * information is ignored.
- */
-
- /* Clean the old attributes so that they can be rebuilt. */
- new_attr = old_attr & ~(MT_RW|MT_EXECUTE_NEVER|MT_USER);
-
- /*
- * Update attributes, but filter out the ones this function
- * isn't allowed to change.
- */
- new_attr |= attr & (MT_RW|MT_EXECUTE_NEVER|MT_USER);
-
- VERBOSE("New attributes: 0x%x\n", new_attr);
-
- /*
- * The break-before-make sequence requires writing an invalid
- * descriptor and making sure that the system sees the change
- * before writing the new descriptor.
- */
- *entry = INVALID_DESC;
-
- /* Invalidate any cached copy of this mapping in the TLBs. */
- xlat_arch_tlbi_va_regime(base_va, ctx->xlat_regime);
-
- /* Ensure completion of the invalidation. */
- xlat_arch_tlbi_va_sync();
-
- /* Write new descriptor */
- *entry = xlat_desc(ctx, new_attr, addr_pa, level);
-
- base_va += PAGE_SIZE;
- }
-
- /* Ensure that the last descriptor writen is seen by the system. */
- dsbish();
-
- return 0;
-}
diff --git a/lib/xlat_tables_v2/xlat_tables_private.h b/lib/xlat_tables_v2/xlat_tables_private.h
index 777189f..93640dd 100644
--- a/lib/xlat_tables_v2/xlat_tables_private.h
+++ b/lib/xlat_tables_v2/xlat_tables_private.h
@@ -36,21 +36,23 @@
#endif /* PLAT_XLAT_TABLES_DYNAMIC */
/*
+ * 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);
+
+/*
* Invalidate all TLB entries that match the given virtual address. This
* operation applies to all PEs in the same Inner Shareable domain as the PE
* that executes this function. This functions must be called for every
- * translation table entry that is modified.
- *
- * xlat_arch_tlbi_va() applies the invalidation to the exception level of the
- * current translation regime, whereas xlat_arch_tlbi_va_regime() applies it to
- * the given translation regime.
+ * translation table entry that is modified. It only affects the specified
+ * translation regime.
*
* Note, however, that it is architecturally UNDEFINED to invalidate TLB entries
* pertaining to a higher exception level, e.g. invalidating EL3 entries from
* S-EL1.
*/
-void xlat_arch_tlbi_va(uintptr_t va);
-void xlat_arch_tlbi_va_regime(uintptr_t va, xlat_regime_t xlat_regime);
+void xlat_arch_tlbi_va(uintptr_t va, int xlat_regime);
/*
* This function has to be called at the end of any code that uses the function
@@ -59,7 +61,7 @@
void xlat_arch_tlbi_va_sync(void);
/* Print VA, PA, size and attributes of all regions in the mmap array. */
-void print_mmap(mmap_region_t *const mmap);
+void xlat_mmap_print(mmap_region_t *const mmap);
/*
* Print the current state of the translation tables by reading them from
@@ -68,6 +70,12 @@
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, int level);
+
+/*
* Architecture-specific initialization code.
*/
@@ -80,10 +88,6 @@
*/
unsigned long long xlat_arch_get_max_supported_pa(void);
-/* Enable MMU and configure it to use the specified translation tables. */
-void setup_mmu_cfg(unsigned int flags, const uint64_t *base_table,
- unsigned long long max_pa, uintptr_t max_va);
-
/*
* Return 1 if the MMU of the translation regime managed by the given xlat_ctx_t
* is enabled, 0 otherwise.
diff --git a/lib/xlat_tables_v2/xlat_tables_utils.c b/lib/xlat_tables_v2/xlat_tables_utils.c
new file mode 100644
index 0000000..90a0a86
--- /dev/null
+++ b/lib/xlat_tables_v2/xlat_tables_utils.c
@@ -0,0 +1,561 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <errno.h>
+#include <platform_def.h>
+#include <types.h>
+#include <utils_def.h>
+#include <xlat_tables_defs.h>
+#include <xlat_tables_v2.h>
+
+#include "xlat_tables_private.h"
+
+#if LOG_LEVEL < LOG_LEVEL_VERBOSE
+
+void xlat_mmap_print(__unused mmap_region_t *const mmap)
+{
+ /* Empty */
+}
+
+void xlat_tables_print(__unused xlat_ctx_t *ctx)
+{
+ /* Empty */
+}
+
+#else /* if LOG_LEVEL >= LOG_LEVEL_VERBOSE */
+
+void xlat_mmap_print(mmap_region_t *const mmap)
+{
+ tf_printf("mmap:\n");
+ const mmap_region_t *mm = mmap;
+
+ while (mm->size != 0U) {
+ tf_printf(" VA:0x%lx PA:0x%llx size:0x%zx attr:0x%x "
+ "granularity:0x%zx\n", mm->base_va, mm->base_pa,
+ mm->size, mm->attr, mm->granularity);
+ ++mm;
+ };
+ tf_printf("\n");
+}
+
+/* Print the attributes of the specified block descriptor. */
+static void xlat_desc_print(const xlat_ctx_t *ctx, uint64_t desc)
+{
+ int mem_type_index = ATTR_INDEX_GET(desc);
+ int xlat_regime = ctx->xlat_regime;
+
+ if (mem_type_index == ATTR_IWBWA_OWBWA_NTR_INDEX) {
+ tf_printf("MEM");
+ } else if (mem_type_index == ATTR_NON_CACHEABLE_INDEX) {
+ tf_printf("NC");
+ } else {
+ assert(mem_type_index == ATTR_DEVICE_INDEX);
+ tf_printf("DEV");
+ }
+
+ if (xlat_regime == EL3_REGIME) {
+ /* For EL3 only check the AP[2] and XN bits. */
+ tf_printf((desc & LOWER_ATTRS(AP_RO)) ? "-RO" : "-RW");
+ tf_printf((desc & UPPER_ATTRS(XN)) ? "-XN" : "-EXEC");
+ } else {
+ assert(xlat_regime == EL1_EL0_REGIME);
+ /*
+ * For EL0 and EL1:
+ * - In AArch64 PXN and UXN can be set independently but in
+ * AArch32 there is no UXN (XN affects both privilege levels).
+ * For consistency, we set them simultaneously in both cases.
+ * - RO and RW permissions must be the same in EL1 and EL0. If
+ * EL0 can access that memory region, so can EL1, with the
+ * same permissions.
+ */
+#if ENABLE_ASSERTIONS
+ uint64_t xn_mask = xlat_arch_regime_get_xn_desc(EL1_EL0_REGIME);
+ uint64_t xn_perm = desc & xn_mask;
+
+ assert((xn_perm == xn_mask) || (xn_perm == 0ULL));
+#endif
+ tf_printf((desc & LOWER_ATTRS(AP_RO)) ? "-RO" : "-RW");
+ /* Only check one of PXN and UXN, the other one is the same. */
+ tf_printf((desc & UPPER_ATTRS(PXN)) ? "-XN" : "-EXEC");
+ /*
+ * Privileged regions can only be accessed from EL1, user
+ * regions can be accessed from EL1 and EL0.
+ */
+ tf_printf((desc & LOWER_ATTRS(AP_ACCESS_UNPRIVILEGED))
+ ? "-USER" : "-PRIV");
+ }
+
+ tf_printf(LOWER_ATTRS(NS) & desc ? "-NS" : "-S");
+}
+
+static const char * const level_spacers[] = {
+ "[LV0] ",
+ " [LV1] ",
+ " [LV2] ",
+ " [LV3] "
+};
+
+static const char *invalid_descriptors_ommited =
+ "%s(%d invalid descriptors omitted)\n";
+
+/*
+ * Recursive function that reads the translation tables passed as an argument
+ * and prints their status.
+ */
+static void xlat_tables_print_internal(xlat_ctx_t *ctx,
+ const uintptr_t table_base_va,
+ uint64_t *const table_base, const int table_entries,
+ const unsigned int level)
+{
+ assert(level <= XLAT_TABLE_LEVEL_MAX);
+
+ uint64_t desc;
+ uintptr_t table_idx_va = table_base_va;
+ int table_idx = 0;
+
+ size_t level_size = XLAT_BLOCK_SIZE(level);
+
+ /*
+ * Keep track of how many invalid descriptors are counted in a row.
+ * Whenever multiple invalid descriptors are found, only the first one
+ * is printed, and a line is added to inform about how many descriptors
+ * have been omitted.
+ */
+ int invalid_row_count = 0;
+
+ while (table_idx < table_entries) {
+
+ desc = table_base[table_idx];
+
+ if ((desc & DESC_MASK) == INVALID_DESC) {
+
+ if (invalid_row_count == 0) {
+ tf_printf("%sVA:%p size:0x%zx\n",
+ level_spacers[level],
+ (void *)table_idx_va, level_size);
+ }
+ invalid_row_count++;
+
+ } else {
+
+ if (invalid_row_count > 1) {
+ tf_printf(invalid_descriptors_ommited,
+ level_spacers[level],
+ invalid_row_count - 1);
+ }
+ invalid_row_count = 0;
+
+ /*
+ * Check if this is a table or a block. Tables are only
+ * allowed in levels other than 3, but DESC_PAGE has the
+ * same value as DESC_TABLE, so we need to check.
+ */
+ if (((desc & DESC_MASK) == TABLE_DESC) &&
+ (level < XLAT_TABLE_LEVEL_MAX)) {
+ /*
+ * Do not print any PA for a table descriptor,
+ * as it doesn't directly map physical memory
+ * but instead points to the next translation
+ * table in the translation table walk.
+ */
+ tf_printf("%sVA:%p size:0x%zx\n",
+ level_spacers[level],
+ (void *)table_idx_va, level_size);
+
+ uintptr_t addr_inner = desc & TABLE_ADDR_MASK;
+
+ xlat_tables_print_internal(ctx, table_idx_va,
+ (uint64_t *)addr_inner,
+ XLAT_TABLE_ENTRIES, level + 1);
+ } else {
+ tf_printf("%sVA:%p PA:0x%llx size:0x%zx ",
+ level_spacers[level],
+ (void *)table_idx_va,
+ (unsigned long long)(desc & TABLE_ADDR_MASK),
+ level_size);
+ xlat_desc_print(ctx, desc);
+ tf_printf("\n");
+ }
+ }
+
+ table_idx++;
+ table_idx_va += level_size;
+ }
+
+ if (invalid_row_count > 1) {
+ tf_printf(invalid_descriptors_ommited,
+ level_spacers[level], invalid_row_count - 1);
+ }
+}
+
+void xlat_tables_print(xlat_ctx_t *ctx)
+{
+ const char *xlat_regime_str;
+ if (ctx->xlat_regime == EL1_EL0_REGIME) {
+ xlat_regime_str = "1&0";
+ } else {
+ assert(ctx->xlat_regime == EL3_REGIME);
+ xlat_regime_str = "3";
+ }
+ 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: %p\n", (void *) ctx->va_max_address);
+ VERBOSE(" Max mapped PA: 0x%llx\n", ctx->max_pa);
+ VERBOSE(" Max mapped VA: %p\n", (void *) ctx->max_va);
+
+ VERBOSE(" Initial lookup level: %i\n", ctx->base_level);
+ VERBOSE(" Entries @initial lookup level: %i\n",
+ ctx->base_table_entries);
+
+ int used_page_tables;
+#if PLAT_XLAT_TABLES_DYNAMIC
+ used_page_tables = 0;
+ for (unsigned int i = 0; i < ctx->tables_num; ++i) {
+ if (ctx->tables_mapped_regions[i] != 0)
+ ++used_page_tables;
+ }
+#else
+ used_page_tables = ctx->next_table;
+#endif
+ VERBOSE(" Used %i sub-tables out of %i (spare: %i)\n",
+ used_page_tables, ctx->tables_num,
+ ctx->tables_num - used_page_tables);
+
+ xlat_tables_print_internal(ctx, 0, ctx->base_table,
+ ctx->base_table_entries, ctx->base_level);
+}
+
+#endif /* LOG_LEVEL >= LOG_LEVEL_VERBOSE */
+
+/*
+ * Do a translation table walk to find the block or page descriptor that maps
+ * virtual_addr.
+ *
+ * On success, return the address of the descriptor within the translation
+ * table. Its lookup level is stored in '*out_level'.
+ * On error, return NULL.
+ *
+ * xlat_table_base
+ * Base address for the initial lookup level.
+ * xlat_table_base_entries
+ * Number of entries in the translation table for the initial lookup level.
+ * virt_addr_space_size
+ * Size in bytes of the virtual address space.
+ */
+static uint64_t *find_xlat_table_entry(uintptr_t virtual_addr,
+ void *xlat_table_base,
+ int xlat_table_base_entries,
+ unsigned long long virt_addr_space_size,
+ int *out_level)
+{
+ unsigned int start_level;
+ uint64_t *table;
+ int entries;
+
+ start_level = GET_XLAT_TABLE_LEVEL_BASE(virt_addr_space_size);
+
+ table = xlat_table_base;
+ entries = xlat_table_base_entries;
+
+ for (unsigned int level = start_level;
+ level <= XLAT_TABLE_LEVEL_MAX;
+ ++level) {
+ int idx;
+ uint64_t desc;
+ uint64_t desc_type;
+
+ idx = XLAT_TABLE_IDX(virtual_addr, level);
+ if (idx >= entries) {
+ WARN("Missing xlat table entry at address 0x%lx\n",
+ virtual_addr);
+ return NULL;
+ }
+
+ desc = table[idx];
+ desc_type = desc & DESC_MASK;
+
+ if (desc_type == INVALID_DESC) {
+ VERBOSE("Invalid entry (memory not mapped)\n");
+ return NULL;
+ }
+
+ if (level == XLAT_TABLE_LEVEL_MAX) {
+ /*
+ * Only page descriptors allowed at the final lookup
+ * level.
+ */
+ assert(desc_type == PAGE_DESC);
+ *out_level = level;
+ return &table[idx];
+ }
+
+ if (desc_type == BLOCK_DESC) {
+ *out_level = level;
+ return &table[idx];
+ }
+
+ assert(desc_type == TABLE_DESC);
+ table = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK);
+ entries = XLAT_TABLE_ENTRIES;
+ }
+
+ /*
+ * This shouldn't be reached, the translation table walk should end at
+ * most at level XLAT_TABLE_LEVEL_MAX and return from inside the loop.
+ */
+ assert(0);
+
+ return NULL;
+}
+
+
+static int get_mem_attributes_internal(const xlat_ctx_t *ctx, uintptr_t base_va,
+ uint32_t *attributes, uint64_t **table_entry,
+ unsigned long long *addr_pa, int *table_level)
+{
+ uint64_t *entry;
+ uint64_t desc;
+ int level;
+ unsigned long long virt_addr_space_size;
+
+ /*
+ * Sanity-check arguments.
+ */
+ assert(ctx != NULL);
+ assert(ctx->initialized);
+ assert(ctx->xlat_regime == EL1_EL0_REGIME || ctx->xlat_regime == EL3_REGIME);
+
+ virt_addr_space_size = (unsigned long long)ctx->va_max_address + 1;
+ assert(virt_addr_space_size > 0);
+
+ entry = find_xlat_table_entry(base_va,
+ ctx->base_table,
+ ctx->base_table_entries,
+ virt_addr_space_size,
+ &level);
+ if (entry == NULL) {
+ WARN("Address %p is not mapped.\n", (void *)base_va);
+ return -EINVAL;
+ }
+
+ if (addr_pa != NULL) {
+ *addr_pa = *entry & TABLE_ADDR_MASK;
+ }
+
+ if (table_entry != NULL) {
+ *table_entry = entry;
+ }
+
+ if (table_level != NULL) {
+ *table_level = level;
+ }
+
+ desc = *entry;
+
+#if LOG_LEVEL >= LOG_LEVEL_VERBOSE
+ VERBOSE("Attributes: ");
+ xlat_desc_print(ctx, desc);
+ tf_printf("\n");
+#endif /* LOG_LEVEL >= LOG_LEVEL_VERBOSE */
+
+ assert(attributes != NULL);
+ *attributes = 0;
+
+ int attr_index = (desc >> ATTR_INDEX_SHIFT) & ATTR_INDEX_MASK;
+
+ if (attr_index == ATTR_IWBWA_OWBWA_NTR_INDEX) {
+ *attributes |= MT_MEMORY;
+ } else if (attr_index == ATTR_NON_CACHEABLE_INDEX) {
+ *attributes |= MT_NON_CACHEABLE;
+ } else {
+ assert(attr_index == ATTR_DEVICE_INDEX);
+ *attributes |= MT_DEVICE;
+ }
+
+ int ap2_bit = (desc >> AP2_SHIFT) & 1;
+
+ if (ap2_bit == AP2_RW)
+ *attributes |= MT_RW;
+
+ if (ctx->xlat_regime == EL1_EL0_REGIME) {
+ int ap1_bit = (desc >> AP1_SHIFT) & 1;
+ if (ap1_bit == AP1_ACCESS_UNPRIVILEGED)
+ *attributes |= MT_USER;
+ }
+
+ int ns_bit = (desc >> NS_SHIFT) & 1;
+
+ if (ns_bit == 1)
+ *attributes |= MT_NS;
+
+ uint64_t xn_mask = xlat_arch_regime_get_xn_desc(ctx->xlat_regime);
+
+ if ((desc & xn_mask) == xn_mask) {
+ *attributes |= MT_EXECUTE_NEVER;
+ } else {
+ assert((desc & xn_mask) == 0);
+ }
+
+ return 0;
+}
+
+
+int get_mem_attributes(const xlat_ctx_t *ctx, uintptr_t base_va,
+ uint32_t *attributes)
+{
+ return get_mem_attributes_internal(ctx, base_va, attributes,
+ NULL, NULL, NULL);
+}
+
+
+int change_mem_attributes(xlat_ctx_t *ctx,
+ uintptr_t base_va,
+ size_t size,
+ uint32_t attr)
+{
+ /* Note: This implementation isn't optimized. */
+
+ assert(ctx != NULL);
+ assert(ctx->initialized);
+
+ unsigned long long virt_addr_space_size =
+ (unsigned long long)ctx->va_max_address + 1;
+ assert(virt_addr_space_size > 0);
+
+ if (!IS_PAGE_ALIGNED(base_va)) {
+ WARN("%s: Address %p is not aligned on a page boundary.\n",
+ __func__, (void *)base_va);
+ return -EINVAL;
+ }
+
+ if (size == 0) {
+ WARN("%s: Size is 0.\n", __func__);
+ return -EINVAL;
+ }
+
+ if ((size % PAGE_SIZE) != 0) {
+ WARN("%s: Size 0x%zx is not a multiple of a page size.\n",
+ __func__, size);
+ return -EINVAL;
+ }
+
+ if (((attr & MT_EXECUTE_NEVER) == 0) && ((attr & MT_RW) != 0)) {
+ WARN("%s: Mapping memory as read-write and executable not allowed.\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ int pages_count = size / PAGE_SIZE;
+
+ VERBOSE("Changing memory attributes of %i pages starting from address %p...\n",
+ pages_count, (void *)base_va);
+
+ uintptr_t base_va_original = base_va;
+
+ /*
+ * Sanity checks.
+ */
+ for (int i = 0; i < pages_count; ++i) {
+ uint64_t *entry;
+ uint64_t desc;
+ int level;
+
+ entry = find_xlat_table_entry(base_va,
+ ctx->base_table,
+ ctx->base_table_entries,
+ virt_addr_space_size,
+ &level);
+ if (entry == NULL) {
+ WARN("Address %p is not mapped.\n", (void *)base_va);
+ return -EINVAL;
+ }
+
+ desc = *entry;
+
+ /*
+ * Check that all the required pages are mapped at page
+ * granularity.
+ */
+ if (((desc & DESC_MASK) != PAGE_DESC) ||
+ (level != XLAT_TABLE_LEVEL_MAX)) {
+ WARN("Address %p is not mapped at the right granularity.\n",
+ (void *)base_va);
+ WARN("Granularity is 0x%llx, should be 0x%x.\n",
+ (unsigned long long)XLAT_BLOCK_SIZE(level), PAGE_SIZE);
+ return -EINVAL;
+ }
+
+ /*
+ * If the region type is device, it shouldn't be executable.
+ */
+ int attr_index = (desc >> ATTR_INDEX_SHIFT) & ATTR_INDEX_MASK;
+ if (attr_index == ATTR_DEVICE_INDEX) {
+ if ((attr & MT_EXECUTE_NEVER) == 0) {
+ WARN("Setting device memory as executable at address %p.",
+ (void *)base_va);
+ return -EINVAL;
+ }
+ }
+
+ base_va += PAGE_SIZE;
+ }
+
+ /* Restore original value. */
+ base_va = base_va_original;
+
+ for (int i = 0; i < pages_count; ++i) {
+
+ uint32_t old_attr, new_attr;
+ uint64_t *entry;
+ int level;
+ unsigned long long addr_pa;
+
+ get_mem_attributes_internal(ctx, base_va, &old_attr,
+ &entry, &addr_pa, &level);
+
+ /*
+ * From attr, only MT_RO/MT_RW, MT_EXECUTE/MT_EXECUTE_NEVER and
+ * MT_USER/MT_PRIVILEGED are taken into account. Any other
+ * information is ignored.
+ */
+
+ /* Clean the old attributes so that they can be rebuilt. */
+ new_attr = old_attr & ~(MT_RW | MT_EXECUTE_NEVER | MT_USER);
+
+ /*
+ * Update attributes, but filter out the ones this function
+ * isn't allowed to change.
+ */
+ new_attr |= attr & (MT_RW | MT_EXECUTE_NEVER | MT_USER);
+
+ /*
+ * The break-before-make sequence requires writing an invalid
+ * descriptor and making sure that the system sees the change
+ * before writing the new descriptor.
+ */
+ *entry = INVALID_DESC;
+
+ /* Invalidate any cached copy of this mapping in the TLBs. */
+ xlat_arch_tlbi_va(base_va, ctx->xlat_regime);
+
+ /* Ensure completion of the invalidation. */
+ xlat_arch_tlbi_va_sync();
+
+ /* Write new descriptor */
+ *entry = xlat_desc(ctx, new_attr, addr_pa, level);
+
+ base_va += PAGE_SIZE;
+ }
+
+ /* Ensure that the last descriptor writen is seen by the system. */
+ dsbish();
+
+ return 0;
+}
diff --git a/maintainers.rst b/maintainers.rst
index 702bbad..76fede8 100644
--- a/maintainers.rst
+++ b/maintainers.rst
@@ -20,6 +20,8 @@
-----------------------------
:M: Andre Przywara <andre.przywara@arm.com>
:G: `Andre-ARM`_
+:M: Samuel Holland <samuel@sholland.org>
+:G: `smaeul`_
:F: docs/plat/allwinner.rst
:F: plat/allwinner/
@@ -178,6 +180,7 @@
.. _rockchip-linux: https://github.com/rockchip-linux
.. _shawnguo2: https://github.com/shawnguo2
.. _sivadur: https://github.com/sivadur
+.. _smaeul: https://github.com/smaeul
.. _soby-mathew: https://github.com/soby-mathew
.. _TonyXie06: https://github.com/TonyXie06
.. _vwadekar: https://github.com/vwadekar
diff --git a/plat/allwinner/common/include/platform_def.h b/plat/allwinner/common/include/platform_def.h
index ca7db2f..d039188 100644
--- a/plat/allwinner/common/include/platform_def.h
+++ b/plat/allwinner/common/include/platform_def.h
@@ -39,7 +39,13 @@
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER_COUNT * \
PLATFORM_MAX_CPUS_PER_CLUSTER)
#define PLATFORM_MAX_CPUS_PER_CLUSTER 4
-#define PLATFORM_MMAP_REGIONS 4
+#define PLATFORM_MMAP_REGIONS 3
#define PLATFORM_STACK_SIZE (0x1000 / PLATFORM_CORE_COUNT)
+#ifndef SPD_none
+#ifndef BL32_BASE
+#define BL32_BASE SUNXI_DRAM_BASE
+#endif
+#endif
+
#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/allwinner/common/sunxi_bl31_setup.c b/plat/allwinner/common/sunxi_bl31_setup.c
index d1f1aa1..8ecf490 100644
--- a/plat/allwinner/common/sunxi_bl31_setup.c
+++ b/plat/allwinner/common/sunxi_bl31_setup.c
@@ -18,6 +18,7 @@
#include "sunxi_private.h"
+static entry_point_info_t bl32_image_ep_info;
static entry_point_info_t bl33_image_ep_info;
static console_16550_t console;
@@ -34,6 +35,13 @@
console_16550_register(SUNXI_UART0_BASE, SUNXI_UART0_CLK_IN_HZ,
SUNXI_UART0_BAUDRATE, &console);
+#ifdef BL32_BASE
+ /* Populate entry point information for BL32 */
+ SET_PARAM_HEAD(&bl32_image_ep_info, PARAM_EP, VERSION_1, 0);
+ SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
+ bl32_image_ep_info.pc = BL32_BASE;
+#endif
+
/* Populate entry point information for BL33 */
SET_PARAM_HEAD(&bl33_image_ep_info, PARAM_EP, VERSION_1, 0);
/*
@@ -56,6 +64,25 @@
void bl31_platform_setup(void)
{
+ const char *soc_name;
+ uint16_t soc_id = sunxi_read_soc_id();
+
+ switch (soc_id) {
+ case 0x1689:
+ soc_name = "A64/H64/R18";
+ break;
+ case 0x1718:
+ soc_name = "H5";
+ break;
+ case 0x1728:
+ soc_name = "H6";
+ break;
+ default:
+ soc_name = "unknown";
+ break;
+ }
+ NOTICE("BL31: Detected Allwinner %s SoC (%04x)\n", soc_name, soc_id);
+
generic_delay_timer_init();
/* Configure the interrupt controller */
@@ -72,7 +99,12 @@
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
{
assert(sec_state_is_valid(type) != 0);
- assert(type == NON_SECURE);
- return &bl33_image_ep_info;
+ if (type == NON_SECURE)
+ return &bl33_image_ep_info;
+
+ if ((type == SECURE) && bl32_image_ep_info.pc)
+ return &bl32_image_ep_info;
+
+ return NULL;
}
diff --git a/plat/allwinner/common/sunxi_common.c b/plat/allwinner/common/sunxi_common.c
index e36c8b0..fc9bf20 100644
--- a/plat/allwinner/common/sunxi_common.c
+++ b/plat/allwinner/common/sunxi_common.c
@@ -4,14 +4,15 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <mmio.h>
#include <platform.h>
#include <platform_def.h>
#include <sunxi_def.h>
#include <xlat_tables_v2.h>
+#include "sunxi_private.h"
+
static mmap_region_t sunxi_mmap[PLATFORM_MMAP_REGIONS + 1] = {
- MAP_REGION_FLAT(SUNXI_ROM_BASE, SUNXI_ROM_SIZE,
- MT_MEMORY | MT_RO | MT_SECURE),
MAP_REGION_FLAT(SUNXI_SRAM_BASE, SUNXI_SRAM_SIZE,
MT_MEMORY | MT_RW | MT_SECURE),
MAP_REGION_FLAT(SUNXI_DEV_BASE, SUNXI_DEV_SIZE,
@@ -54,3 +55,19 @@
enable_mmu_el3(0);
}
+
+#define SRAM_VER_REG (SUNXI_SYSCON_BASE + 0x24)
+uint16_t sunxi_read_soc_id(void)
+{
+ uint32_t reg = mmio_read_32(SRAM_VER_REG);
+
+ /* Set bit 15 to prepare for the SOCID read. */
+ mmio_write_32(SRAM_VER_REG, reg | BIT(15));
+
+ reg = mmio_read_32(SRAM_VER_REG);
+
+ /* deactivate the SOCID access again */
+ mmio_write_32(SRAM_VER_REG, reg & ~BIT(15));
+
+ return reg >> 16;
+}
diff --git a/plat/allwinner/common/sunxi_cpu_ops.c b/plat/allwinner/common/sunxi_cpu_ops.c
index be72dee..aaee65c 100644
--- a/plat/allwinner/common/sunxi_cpu_ops.c
+++ b/plat/allwinner/common/sunxi_cpu_ops.c
@@ -18,7 +18,7 @@
if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0xff)
return;
- INFO("PSCI: Disabling power to cluster %d core %d\n", cluster, core);
+ VERBOSE("PSCI: Disabling power to cluster %d core %d\n", cluster, core);
mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xff);
}
@@ -28,7 +28,7 @@
if (mmio_read_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core)) == 0)
return;
- INFO("PSCI: Enabling power to cluster %d core %d\n", cluster, core);
+ VERBOSE("PSCI: Enabling power to cluster %d core %d\n", cluster, core);
/* Power enable sequence from original Allwinner sources */
mmio_write_32(SUNXI_CPU_POWER_CLAMP_REG(cluster, core), 0xfe);
@@ -40,7 +40,7 @@
void sunxi_cpu_off(unsigned int cluster, unsigned int core)
{
- INFO("PSCI: Powering off cluster %d core %d\n", cluster, core);
+ VERBOSE("PSCI: Powering off cluster %d core %d\n", cluster, core);
/* Deassert DBGPWRDUP */
mmio_clrbits_32(SUNXI_CPUCFG_DBG_REG0, BIT(core));
@@ -54,7 +54,7 @@
void sunxi_cpu_on(unsigned int cluster, unsigned int core)
{
- INFO("PSCI: Powering on cluster %d core %d\n", cluster, core);
+ VERBOSE("PSCI: Powering on cluster %d core %d\n", cluster, core);
/* Assert CPU core reset */
mmio_clrbits_32(SUNXI_CPUCFG_RST_CTRL_REG(cluster), BIT(core));
diff --git a/plat/allwinner/common/sunxi_pm.c b/plat/allwinner/common/sunxi_pm.c
index fcab130..2a1f223 100644
--- a/plat/allwinner/common/sunxi_pm.c
+++ b/plat/allwinner/common/sunxi_pm.c
@@ -76,8 +76,7 @@
static int sunxi_validate_ns_entrypoint(uintptr_t ns_entrypoint)
{
/* The non-secure entry point must be in DRAM */
- if (ns_entrypoint >= SUNXI_DRAM_BASE &&
- ns_entrypoint < SUNXI_DRAM_BASE + SUNXI_DRAM_SIZE)
+ if (ns_entrypoint >= SUNXI_DRAM_BASE)
return PSCI_E_SUCCESS;
return PSCI_E_INVALID_ADDRESS;
diff --git a/plat/allwinner/common/sunxi_private.h b/plat/allwinner/common/sunxi_private.h
index b9f0fb4..e45f494 100644
--- a/plat/allwinner/common/sunxi_private.h
+++ b/plat/allwinner/common/sunxi_private.h
@@ -12,6 +12,7 @@
void sunxi_cpu_on(unsigned int cluster, unsigned int core);
void sunxi_disable_secondary_cpus(unsigned int primary_cpu);
+uint16_t sunxi_read_soc_id(void);
void sunxi_security_setup(void);
#endif /* __SUNXI_PRIVATE_H__ */
diff --git a/plat/allwinner/common/sunxi_security.c b/plat/allwinner/common/sunxi_security.c
index e760072..80fed6a 100644
--- a/plat/allwinner/common/sunxi_security.c
+++ b/plat/allwinner/common/sunxi_security.c
@@ -25,9 +25,9 @@
*/
void sunxi_security_setup(void)
{
+#ifdef SUNXI_SPC_BASE
int i;
-#ifdef SUNXI_SPC_BASE
INFO("Configuring SPC Controller\n");
/* SPC setup: set all devices to non-secure */
for (i = 0; i < 6; i++)
diff --git a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
index cb202a8..7d46487 100644
--- a/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
+++ b/plat/allwinner/sun50i_a64/include/sunxi_mmap.h
@@ -27,7 +27,6 @@
#define SUNXI_CPU_MBIST_BASE 0x01502000
#define SUNXI_CPUCFG_BASE 0x01700000
#define SUNXI_SYSCON_BASE 0x01c00000
-#define SUNXI_SRAM_VER_REG (SUNXI_SYSCON_BASE + 0x24)
#define SUNXI_DMA_BASE 0x01c02000
#define SUNXI_KEYMEM_BASE 0x01c0b000
#define SUNXI_SMHC0_BASE 0x01c0f000
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h b/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h
new file mode 100644
index 0000000..e061b89
--- /dev/null
+++ b/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SUNXI_CPUCFG_H__
+#define __SUNXI_CPUCFG_H__
+
+#include <sunxi_mmap.h>
+
+/* c = cluster, n = core */
+#define SUNXI_CPUCFG_CLS_CTRL_REG0(c) (SUNXI_CPUCFG_BASE + 0x0010 + (c) * 0x10)
+#define SUNXI_CPUCFG_CLS_CTRL_REG1(c) (SUNXI_CPUCFG_BASE + 0x0014 + (c) * 0x10)
+#define SUNXI_CPUCFG_CACHE_CFG_REG (SUNXI_CPUCFG_BASE + 0x0024)
+#define SUNXI_CPUCFG_DBG_REG0 (SUNXI_CPUCFG_BASE + 0x00c0)
+
+#define SUNXI_CPUCFG_RST_CTRL_REG(c) (SUNXI_CPUCFG_BASE + 0x0000 + (c) * 4)
+#define SUNXI_CPUCFG_RVBAR_LO_REG(n) (SUNXI_CPUCFG_BASE + 0x0040 + (n) * 8)
+#define SUNXI_CPUCFG_RVBAR_HI_REG(n) (SUNXI_CPUCFG_BASE + 0x0044 + (n) * 8)
+
+#define SUNXI_POWERON_RST_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0040 + (c) * 4)
+#define SUNXI_POWEROFF_GATING_REG(c) (SUNXI_R_CPUCFG_BASE + 0x0044 + (c) * 4)
+#define SUNXI_CPU_POWER_CLAMP_REG(c, n) (SUNXI_R_CPUCFG_BASE + 0x0050 + \
+ (c) * 0x10 + (n) * 4)
+
+#endif /* __SUNXI_CPUCFG_H__ */
diff --git a/plat/allwinner/sun50i_h6/include/sunxi_mmap.h b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
new file mode 100644
index 0000000..f2d5aed
--- /dev/null
+++ b/plat/allwinner/sun50i_h6/include/sunxi_mmap.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SUNXI_MMAP_H__
+#define __SUNXI_MMAP_H__
+
+/* Memory regions */
+#define SUNXI_ROM_BASE 0x00000000
+#define SUNXI_ROM_SIZE 0x00010000
+#define SUNXI_SRAM_BASE 0x00020000
+#define SUNXI_SRAM_SIZE 0x00098000
+#define SUNXI_SRAM_A1_BASE 0x00020000
+#define SUNXI_SRAM_A1_SIZE 0x00008000
+#define SUNXI_SRAM_A2_BASE 0x00104000
+#define SUNXI_SRAM_A2_SIZE 0x00014000
+#define SUNXI_SRAM_C_BASE 0x00028000
+#define SUNXI_SRAM_C_SIZE 0x0001e000
+#define SUNXI_DEV_BASE 0x01000000
+#define SUNXI_DEV_SIZE 0x09000000
+#define SUNXI_DRAM_BASE 0x40000000
+#define SUNXI_DRAM_SIZE 0xc0000000
+
+/* Memory-mapped devices */
+#define SUNXI_SYSCON_BASE 0x03000000
+#define SUNXI_CPUCFG_BASE 0x09010000
+#define SUNXI_SID_BASE 0x03006000
+#define SUNXI_DMA_BASE 0x03002000
+#define SUNXI_MSGBOX_BASE 0x03003000
+#define SUNXI_CCU_BASE 0x03010000
+#define SUNXI_CCU_SEC_SWITCH_REG (SUNXI_CCU_BASE + 0xf00)
+#define SUNXI_PIO_BASE 0x030b0000
+#define SUNXI_TIMER_BASE 0x03009000
+#define SUNXI_WDOG_BASE 0x030090a0
+#define SUNXI_THS_BASE 0x05070400
+#define SUNXI_UART0_BASE 0x05000000
+#define SUNXI_UART1_BASE 0x05000400
+#define SUNXI_UART2_BASE 0x05000800
+#define SUNXI_UART3_BASE 0x05000c00
+#define SUNXI_I2C0_BASE 0x05002000
+#define SUNXI_I2C1_BASE 0x05002400
+#define SUNXI_I2C2_BASE 0x05002800
+#define SUNXI_I2C3_BASE 0x05002c00
+#define SUNXI_SPI0_BASE 0x05010000
+#define SUNXI_SPI1_BASE 0x05011000
+#define SUNXI_SCU_BASE 0x03020000
+#define SUNXI_GICD_BASE 0x03021000
+#define SUNXI_GICC_BASE 0x03022000
+#define SUNXI_R_TIMER_BASE 0x07020000
+#define SUNXI_R_INTC_BASE 0x07021000
+#define SUNXI_R_WDOG_BASE 0x07020400
+#define SUNXI_R_PRCM_BASE 0x07010000
+#define SUNXI_R_TWD_BASE 0x07020800
+#define SUNXI_R_CPUCFG_BASE 0x07000400
+#define SUNXI_R_I2C_BASE 0x07081400
+#define SUNXI_R_UART_BASE 0x07080000
+#define SUNXI_R_PIO_BASE 0x07022000
+
+#endif /* __SUNXI_MMAP_H__ */
diff --git a/plat/allwinner/sun50i_h6/platform.mk b/plat/allwinner/sun50i_h6/platform.mk
new file mode 100644
index 0000000..c1b26fa
--- /dev/null
+++ b/plat/allwinner/sun50i_h6/platform.mk
@@ -0,0 +1,59 @@
+#
+# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+include lib/xlat_tables_v2/xlat_tables.mk
+
+AW_PLAT := plat/allwinner
+
+PLAT_INCLUDES := -Iinclude/plat/arm/common \
+ -Iinclude/plat/arm/common/aarch64 \
+ -I${AW_PLAT}/common/include \
+ -I${AW_PLAT}/${PLAT}/include
+
+PLAT_BL_COMMON_SOURCES := drivers/console/${ARCH}/console.S \
+ drivers/ti/uart/${ARCH}/16550_console.S \
+ ${XLAT_TABLES_LIB_SRCS} \
+ ${AW_PLAT}/common/plat_helpers.S \
+ ${AW_PLAT}/common/sunxi_common.c
+
+BL31_SOURCES += drivers/arm/gic/common/gic_common.c \
+ drivers/arm/gic/v2/gicv2_helpers.c \
+ drivers/arm/gic/v2/gicv2_main.c \
+ drivers/delay_timer/delay_timer.c \
+ drivers/delay_timer/generic_delay_timer.c \
+ lib/cpus/${ARCH}/cortex_a53.S \
+ plat/common/plat_gicv2.c \
+ plat/common/plat_psci_common.c \
+ ${AW_PLAT}/common/sunxi_bl31_setup.c \
+ ${AW_PLAT}/common/sunxi_cpu_ops.c \
+ ${AW_PLAT}/common/sunxi_pm.c \
+ ${AW_PLAT}/common/sunxi_security.c \
+ ${AW_PLAT}/common/sunxi_topology.c
+
+# The bootloader is guaranteed to only run on CPU 0 by the boot ROM.
+COLD_BOOT_SINGLE_CPU := 1
+
+# Enable workarounds for Cortex-A53 errata. Allwinner uses at least r0p4.
+ERRATA_A53_835769 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 1
+
+# Disable the PSCI platform compatibility layer.
+ENABLE_PLAT_COMPAT := 0
+
+MULTI_CONSOLE_API := 1
+
+# Prohibit using deprecated interfaces. We rely on this for this platform.
+ERROR_DEPRECATED := 1
+
+# The reset vector can be changed for each CPU.
+PROGRAMMABLE_RESET_ADDRESS := 1
+
+# Allow mapping read-only data as execute-never.
+SEPARATE_CODE_AND_RODATA := 1
+
+# BL31 gets loaded alongside BL33 (U-Boot) by U-Boot's SPL
+RESET_TO_BL31 := 1
diff --git a/plat/arm/board/fvp/fvp_bl2u_setup.c b/plat/arm/board/fvp/fvp_bl2u_setup.c
index 361e84d..b9ab3f3 100644
--- a/plat/arm/board/fvp/fvp_bl2u_setup.c
+++ b/plat/arm/board/fvp/fvp_bl2u_setup.c
@@ -9,7 +9,7 @@
#include "fvp_def.h"
#include "fvp_private.h"
-void bl2u_early_platform_setup(meminfo_t *mem_layout, void *plat_info)
+void bl2u_early_platform_setup(struct meminfo *mem_layout, void *plat_info)
{
arm_bl2u_early_platform_setup(mem_layout, plat_info);
diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk
index ed41d4c..2b1e0ac 100644
--- a/plat/arm/board/fvp/platform.mk
+++ b/plat/arm/board/fvp/platform.mk
@@ -116,7 +116,8 @@
lib/cpus/aarch64/cortex_a73.S \
lib/cpus/aarch64/cortex_a75.S \
lib/cpus/aarch64/cortex_a76.S \
- lib/cpus/aarch64/cortex_ares.S
+ lib/cpus/aarch64/cortex_ares.S \
+ lib/cpus/aarch64/cortex_deimos.S
else
FVP_CPU_LIBS += lib/cpus/aarch32/cortex_a32.S
endif
diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c
index d141f64..c9b1a68 100644
--- a/plat/arm/common/arm_bl1_setup.c
+++ b/plat/arm/common/arm_bl1_setup.c
@@ -27,7 +27,7 @@
/* Data structure which holds the extents of the trusted SRAM for BL1*/
static meminfo_t bl1_tzram_layout;
-meminfo_t *bl1_plat_sec_mem_layout(void)
+struct meminfo *bl1_plat_sec_mem_layout(void)
{
return &bl1_tzram_layout;
}
@@ -144,7 +144,7 @@
* in order to release secondary CPUs from their holding pen and make
* them jump there.
*/
- arm_program_trusted_mailbox(ep_info->pc);
+ plat_arm_program_trusted_mailbox(ep_info->pc);
dsbsy();
sev();
#endif
diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c
index 3aa99f8..33c2fe8 100644
--- a/plat/arm/common/arm_bl2_setup.c
+++ b/plat/arm/common/arm_bl2_setup.c
@@ -172,7 +172,8 @@
* in x0. This memory layout is sitting at the base of the free trusted SRAM.
* Copy it to a safe location before its reclaimed by later BL2 functionality.
******************************************************************************/
-void arm_bl2_early_platform_setup(uintptr_t tb_fw_config, meminfo_t *mem_layout)
+void arm_bl2_early_platform_setup(uintptr_t tb_fw_config,
+ struct meminfo *mem_layout)
{
/* Initialize the console to provide early debug support */
arm_console_boot_init();
diff --git a/plat/arm/common/arm_bl2u_setup.c b/plat/arm/common/arm_bl2u_setup.c
index cd691e5..dce00e5 100644
--- a/plat/arm/common/arm_bl2u_setup.c
+++ b/plat/arm/common/arm_bl2u_setup.c
@@ -32,7 +32,7 @@
arm_bl2u_platform_setup();
}
-void arm_bl2u_early_platform_setup(meminfo_t *mem_layout, void *plat_info)
+void arm_bl2u_early_platform_setup(struct meminfo *mem_layout, void *plat_info)
{
/* Initialize the console to provide early debug support */
arm_console_boot_init();
@@ -46,7 +46,7 @@
* In case of ARM FVP platforms x1 is not used.
* In both cases, x0 contains the extents of the memory available to BL2U
******************************************************************************/
-void bl2u_early_platform_setup(meminfo_t *mem_layout, void *plat_info)
+void bl2u_early_platform_setup(struct meminfo *mem_layout, void *plat_info)
{
arm_bl2u_early_platform_setup(mem_layout, plat_info);
}
diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c
index 6346f0f..b1f95c9 100644
--- a/plat/arm/common/arm_bl31_setup.c
+++ b/plat/arm/common/arm_bl31_setup.c
@@ -44,7 +44,7 @@
* while BL32 corresponds to the secure image type. A NULL pointer is returned
* if the image does not exist.
******************************************************************************/
-entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
+struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type)
{
entry_point_info_t *next_image_info;
diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c
index 32fd9ee..270abb2 100644
--- a/plat/arm/common/arm_common.c
+++ b/plat/arm/common/arm_common.c
@@ -14,8 +14,6 @@
#include <platform.h>
#include <secure_partition.h>
-extern const mmap_region_t plat_arm_mmap[];
-
/* Weak definitions may be overridden in specific ARM standard platform */
#pragma weak plat_get_ns_image_entrypoint
#pragma weak plat_arm_get_mmap
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index 5330847..67b574d 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -166,7 +166,7 @@
plat/arm/common/arm_err.c \
plat/arm/common/arm_io_storage.c
ifdef EL3_PAYLOAD_BASE
-# Need the arm_program_trusted_mailbox() function to release secondary CPUs from
+# Need the plat_arm_program_trusted_mailbox() function to release secondary CPUs from
# their holding pen
BL1_SOURCES += plat/arm/common/arm_pm.c
endif
diff --git a/plat/arm/common/arm_image_load.c b/plat/arm/common/arm_image_load.c
index 916fa8d..4f86efd 100644
--- a/plat/arm/common/arm_image_load.c
+++ b/plat/arm/common/arm_image_load.c
@@ -28,7 +28,7 @@
/*******************************************************************************
* This function returns the list of loadable images.
******************************************************************************/
-bl_load_info_t *plat_get_bl_image_load_info(void)
+struct bl_load_info *plat_get_bl_image_load_info(void)
{
return get_bl_load_info_from_mem_params_desc();
}
@@ -36,7 +36,7 @@
/*******************************************************************************
* This function returns the list of executable images.
******************************************************************************/
-bl_params_t *plat_get_next_bl_params(void)
+struct bl_params *plat_get_next_bl_params(void)
{
bl_params_t *next_bl_params = get_next_bl_params_from_mem_params_desc();
diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c
index 4632099..d0350d6 100644
--- a/plat/arm/common/arm_pm.c
+++ b/plat/arm/common/arm_pm.c
@@ -14,11 +14,9 @@
#include <platform_def.h>
#include <psci.h>
-/* Allow ARM Standard platforms to override this function */
+/* Allow ARM Standard platforms to override these functions */
#pragma weak plat_arm_psci_override_pm_ops
-
-/* Standard ARM platforms are expected to export plat_arm_psci_pm_ops */
-extern plat_psci_ops_t plat_arm_psci_pm_ops;
+#pragma weak plat_arm_program_trusted_mailbox
#if ARM_RECOM_STATE_ID_ENC
extern unsigned int arm_pm_idle_states[];
@@ -192,11 +190,11 @@
}
/*******************************************************************************
- * Private function to program the mailbox for a cpu before it is released
+ * ARM platform function to program the mailbox for a cpu before it is released
* from reset. This function assumes that the Trusted mail box base is within
* the ARM_SHARED_RAM region
******************************************************************************/
-void arm_program_trusted_mailbox(uintptr_t address)
+void plat_arm_program_trusted_mailbox(uintptr_t address)
{
uintptr_t *mailbox = (void *) PLAT_ARM_TRUSTED_MAILBOX_BASE;
@@ -221,6 +219,6 @@
*psci_ops = plat_arm_psci_override_pm_ops(&plat_arm_psci_pm_ops);
/* Setup mailbox with entry point. */
- arm_program_trusted_mailbox(sec_entrypoint);
+ plat_arm_program_trusted_mailbox(sec_entrypoint);
return 0;
}
diff --git a/plat/arm/css/common/css_common.mk b/plat/arm/css/common/css_common.mk
index 72d5527..29dd01d 100644
--- a/plat/arm/css/common/css_common.mk
+++ b/plat/arm/css/common/css_common.mk
@@ -32,6 +32,7 @@
plat/arm/css/drivers/scpi/css_scpi.c
else
BL31_SOURCES += plat/arm/css/drivers/scp/css_pm_scmi.c \
+ plat/arm/css/drivers/scmi/scmi_ap_core_proto.c \
plat/arm/css/drivers/scmi/scmi_common.c \
plat/arm/css/drivers/scmi/scmi_pwr_dmn_proto.c \
plat/arm/css/drivers/scmi/scmi_sys_pwr_proto.c \
diff --git a/plat/arm/css/drivers/mhu/css_mhu_doorbell.c b/plat/arm/css/drivers/mhu/css_mhu_doorbell.c
index b9faf67..54f3e05 100644
--- a/plat/arm/css/drivers/mhu/css_mhu_doorbell.c
+++ b/plat/arm/css/drivers/mhu/css_mhu_doorbell.c
@@ -9,7 +9,7 @@
#include "css_mhu_doorbell.h"
#include "../scmi/scmi.h"
-void mhu_ring_doorbell(scmi_channel_plat_info_t *plat_info)
+void mhu_ring_doorbell(struct scmi_channel_plat_info *plat_info)
{
MHU_RING_DOORBELL(plat_info->db_reg_addr,
plat_info->db_modify_mask,
@@ -17,7 +17,7 @@
return;
}
-void mhuv2_ring_doorbell(scmi_channel_plat_info_t *plat_info)
+void mhuv2_ring_doorbell(struct scmi_channel_plat_info *plat_info)
{
/* wake receiver */
MHU_V2_ACCESS_REQUEST(MHUV2_BASE_ADDR);
diff --git a/plat/arm/css/drivers/scmi/scmi.h b/plat/arm/css/drivers/scmi/scmi.h
index cf9ef5e..723fd06 100644
--- a/plat/arm/css/drivers/scmi/scmi.h
+++ b/plat/arm/css/drivers/scmi/scmi.h
@@ -12,6 +12,7 @@
#include <stdint.h>
/* Supported SCMI Protocol Versions */
+#define SCMI_AP_CORE_PROTO_VER MAKE_SCMI_VERSION(1, 0)
#define SCMI_PWR_DMN_PROTO_VER MAKE_SCMI_VERSION(1, 0)
#define SCMI_SYS_PWR_PROTO_VER MAKE_SCMI_VERSION(1, 0)
@@ -29,6 +30,8 @@
/* SCMI Protocol identifiers */
#define SCMI_PWR_DMN_PROTO_ID 0x11
#define SCMI_SYS_PWR_PROTO_ID 0x12
+/* The AP core protocol is a CSS platform-specific extension */
+#define SCMI_AP_CORE_PROTO_ID 0x90
/* Mandatory messages IDs for all SCMI protocols */
#define SCMI_PROTO_VERSION_MSG 0x0
@@ -43,6 +46,10 @@
#define SCMI_SYS_PWR_STATE_SET_MSG 0x3
#define SCMI_SYS_PWR_STATE_GET_MSG 0x4
+/* SCMI AP core protocol message IDs */
+#define SCMI_AP_CORE_RESET_ADDR_SET_MSG 0x3
+#define SCMI_AP_CORE_RESET_ADDR_GET_MSG 0x4
+
/* Helper macros for system power management protocol commands */
/*
@@ -73,6 +80,13 @@
#define SCMI_SYS_PWR_POWER_UP 0x3
#define SCMI_SYS_PWR_SUSPEND 0x4
+/*
+ * Macros to describe the bit-fields of the `attribute` of AP core protocol
+ * AP_CORE_RESET_ADDR set/get messages.
+ */
+#define SCMI_AP_CORE_LOCK_ATTR_SHIFT 0x0
+#define SCMI_AP_CORE_LOCK_ATTR (1U << SCMI_AP_CORE_LOCK_ATTR_SHIFT)
+
/* SCMI Error code definitions */
#define SCMI_E_QUEUED 1
#define SCMI_E_SUCCESS 0
@@ -133,4 +147,8 @@
int scmi_sys_pwr_state_set(void *p, uint32_t flags, uint32_t system_state);
int scmi_sys_pwr_state_get(void *p, uint32_t *system_state);
+/* SCMI AP core configuration protocol commands. */
+int scmi_ap_core_set_reset_addr(void *p, uint64_t reset_addr, uint32_t attr);
+int scmi_ap_core_get_reset_addr(void *p, uint64_t *reset_addr, uint32_t *attr);
+
#endif /* __CSS_SCMI_H__ */
diff --git a/plat/arm/css/drivers/scmi/scmi_ap_core_proto.c b/plat/arm/css/drivers/scmi/scmi_ap_core_proto.c
new file mode 100644
index 0000000..1438cba
--- /dev/null
+++ b/plat/arm/css/drivers/scmi/scmi_ap_core_proto.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include "scmi.h"
+#include "scmi_private.h"
+
+/*
+ * API to set the SCMI AP core reset address and attributes
+ */
+int scmi_ap_core_set_reset_addr(void *p, uint64_t reset_addr, uint32_t attr)
+{
+ mailbox_mem_t *mbx_mem;
+ int token = 0, ret;
+ scmi_channel_t *ch = (scmi_channel_t *)p;
+
+ validate_scmi_channel(ch);
+
+ scmi_get_channel(ch);
+
+ mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem);
+ mbx_mem->msg_header = SCMI_MSG_CREATE(SCMI_AP_CORE_PROTO_ID,
+ SCMI_AP_CORE_RESET_ADDR_SET_MSG, token);
+ mbx_mem->len = SCMI_AP_CORE_RESET_ADDR_SET_MSG_LEN;
+ mbx_mem->flags = SCMI_FLAG_RESP_POLL;
+ SCMI_PAYLOAD_ARG3(mbx_mem->payload, reset_addr & 0xffffffff,
+ reset_addr >> 32, attr);
+
+ scmi_send_sync_command(ch);
+
+ /* Get the return values */
+ SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret);
+ assert(mbx_mem->len == SCMI_AP_CORE_RESET_ADDR_SET_RESP_LEN);
+ assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header));
+
+ scmi_put_channel(ch);
+
+ return ret;
+}
+
+/*
+ * API to get the SCMI AP core reset address and attributes
+ */
+int scmi_ap_core_get_reset_addr(void *p, uint64_t *reset_addr, uint32_t *attr)
+{
+ mailbox_mem_t *mbx_mem;
+ int token = 0, ret;
+ scmi_channel_t *ch = (scmi_channel_t *)p;
+ uint32_t lo_addr, hi_addr;
+
+ validate_scmi_channel(ch);
+
+ scmi_get_channel(ch);
+
+ mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem);
+ mbx_mem->msg_header = SCMI_MSG_CREATE(SCMI_AP_CORE_PROTO_ID,
+ SCMI_AP_CORE_RESET_ADDR_GET_MSG, token);
+ mbx_mem->len = SCMI_AP_CORE_RESET_ADDR_GET_MSG_LEN;
+ mbx_mem->flags = SCMI_FLAG_RESP_POLL;
+
+ scmi_send_sync_command(ch);
+
+ /* Get the return values */
+ SCMI_PAYLOAD_RET_VAL4(mbx_mem->payload, ret, lo_addr, hi_addr, *attr);
+ *reset_addr = lo_addr | (uint64_t)hi_addr << 32;
+ assert(mbx_mem->len == SCMI_AP_CORE_RESET_ADDR_GET_RESP_LEN);
+ assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header));
+
+ scmi_put_channel(ch);
+
+ return ret;
+}
diff --git a/plat/arm/css/drivers/scmi/scmi_private.h b/plat/arm/css/drivers/scmi/scmi_private.h
index 67fe748..39bc8cc 100644
--- a/plat/arm/css/drivers/scmi/scmi_private.h
+++ b/plat/arm/css/drivers/scmi/scmi_private.h
@@ -18,6 +18,12 @@
#define SCMI_PROTO_MSG_ATTR_MSG_LEN 8
#define SCMI_PROTO_MSG_ATTR_RESP_LEN 12
+#define SCMI_AP_CORE_RESET_ADDR_SET_MSG_LEN 16
+#define SCMI_AP_CORE_RESET_ADDR_SET_RESP_LEN 8
+
+#define SCMI_AP_CORE_RESET_ADDR_GET_MSG_LEN 4
+#define SCMI_AP_CORE_RESET_ADDR_GET_RESP_LEN 20
+
#define SCMI_PWR_STATE_SET_MSG_LEN 16
#define SCMI_PWR_STATE_SET_RESP_LEN 8
@@ -113,6 +119,11 @@
(val3) = mmio_read_32((uintptr_t)&payld_arr[2]); \
} while (0)
+#define SCMI_PAYLOAD_RET_VAL4(payld_arr, val1, val2, val3, val4) do { \
+ SCMI_PAYLOAD_RET_VAL3(payld_arr, val1, val2, val3); \
+ (val4) = mmio_read_32((uintptr_t)&payld_arr[3]); \
+ } while (0)
+
/*
* Private data structure for representing the mailbox memory layout. Refer
* the SCMI specification for more details.
diff --git a/plat/arm/css/drivers/scp/css_pm_scmi.c b/plat/arm/css/drivers/scp/css_pm_scmi.c
index 91ea63a..7032267 100644
--- a/plat/arm/css/drivers/scp/css_pm_scmi.c
+++ b/plat/arm/css/drivers/scp/css_pm_scmi.c
@@ -142,7 +142,7 @@
* Helper function to turn off a CPU power domain and its parent power domains
* if applicable.
*/
-void css_scp_off(const psci_power_state_t *target_state)
+void css_scp_off(const struct psci_power_state *target_state)
{
int lvl = 0, ret;
uint32_t scmi_pwr_state = 0;
@@ -298,7 +298,7 @@
css_scp_system_off(SCMI_SYS_PWR_COLD_RESET);
}
-scmi_channel_plat_info_t plat_css_scmi_plat_info = {
+static scmi_channel_plat_info_t plat_css_scmi_plat_info = {
.scmi_mbx_mem = CSS_SCMI_PAYLOAD_BASE,
.db_reg_addr = PLAT_CSS_MHU_BASE + CSS_SCMI_MHU_DB_REG_OFF,
.db_preserve_mask = 0xfffffffe,
@@ -306,6 +306,28 @@
.ring_doorbell = &mhu_ring_doorbell,
};
+static int scmi_ap_core_init(scmi_channel_t *ch)
+{
+#if PROGRAMMABLE_RESET_ADDRESS
+ uint32_t version;
+ int ret;
+
+ ret = scmi_proto_version(ch, SCMI_AP_CORE_PROTO_ID, &version);
+ if (ret != SCMI_E_SUCCESS) {
+ WARN("SCMI AP core protocol version message failed\n");
+ return -1;
+ }
+
+ if (!is_scmi_version_compatible(SCMI_AP_CORE_PROTO_VER, version)) {
+ WARN("SCMI AP core protocol version 0x%x incompatible with driver version 0x%x\n",
+ version, SCMI_AP_CORE_PROTO_VER);
+ return -1;
+ }
+ INFO("SCMI AP core protocol version 0x%x detected\n", version);
+#endif
+ return 0;
+}
+
void plat_arm_pwrc_setup(void)
{
channel.info = &plat_css_scmi_plat_info;
@@ -315,6 +337,10 @@
ERROR("SCMI Initialization failed\n");
panic();
}
+ if (scmi_ap_core_init(&channel) < 0) {
+ ERROR("SCMI AP core protocol initialization failed\n");
+ panic();
+ }
}
/******************************************************************************
@@ -386,3 +412,18 @@
*/
return 0;
}
+
+#if PROGRAMMABLE_RESET_ADDRESS
+void plat_arm_program_trusted_mailbox(uintptr_t address)
+{
+ int ret;
+
+ assert(scmi_handle);
+ ret = scmi_ap_core_set_reset_addr(scmi_handle, address,
+ SCMI_AP_CORE_LOCK_ATTR);
+ if (ret != SCMI_E_SUCCESS) {
+ ERROR("CSS: Failed to program reset address: %d\n", ret);
+ panic();
+ }
+}
+#endif
diff --git a/plat/arm/css/drivers/scp/css_pm_scpi.c b/plat/arm/css/drivers/scp/css_pm_scpi.c
index 18e71f6..123d54f 100644
--- a/plat/arm/css/drivers/scp/css_pm_scpi.c
+++ b/plat/arm/css/drivers/scp/css_pm_scpi.c
@@ -47,7 +47,7 @@
* if applicable. Since SCPI doesn't differentiate between OFF and suspend, we
* call the suspend helper here.
*/
-void css_scp_off(const psci_power_state_t *target_state)
+void css_scp_off(const struct psci_power_state *target_state)
{
css_scp_suspend(target_state);
}
diff --git a/plat/arm/css/drivers/scp/css_sds.c b/plat/arm/css/drivers/scp/css_sds.c
index a7a51ba..561e97b 100644
--- a/plat/arm/css/drivers/scp/css_sds.c
+++ b/plat/arm/css/drivers/scp/css_sds.c
@@ -11,6 +11,7 @@
#include <delay_timer.h>
#include <platform.h>
#include <stdint.h>
+#include "css_scp.h"
#include "../sds/sds.h"
int css_scp_boot_image_xfer(void *image, unsigned int image_size)
diff --git a/plat/arm/css/drivers/sds/sds.h b/plat/arm/css/drivers/sds/sds.h
index ff3787d..4aef0df 100644
--- a/plat/arm/css/drivers/sds/sds.h
+++ b/plat/arm/css/drivers/sds/sds.h
@@ -80,7 +80,7 @@
} sds_access_mode_t;
int sds_init(void);
-int sds_struct_exists(uint32_t structure_id);
+int sds_struct_exists(unsigned int structure_id);
int sds_struct_read(uint32_t structure_id, unsigned int fld_off, void *data,
size_t size, sds_access_mode_t mode);
int sds_struct_write(uint32_t structure_id, unsigned int fld_off, void *data,
diff --git a/plat/common/plat_bl1_common.c b/plat/common/plat_bl1_common.c
index c5bbe74..6777979 100644
--- a/plat/common/plat_bl1_common.c
+++ b/plat/common/plat_bl1_common.c
@@ -34,7 +34,7 @@
}
void bl1_plat_set_ep_info(unsigned int image_id,
- entry_point_info_t *ep_info)
+ struct entry_point_info *ep_info)
{
}
@@ -48,7 +48,7 @@
* Following is the default definition that always
* returns BL2 image details.
*/
-image_desc_t *bl1_plat_get_image_desc(unsigned int image_id)
+struct image_desc *bl1_plat_get_image_desc(unsigned int image_id)
{
static image_desc_t bl2_img_desc = BL2_IMAGE_DESC;
return &bl2_img_desc;
diff --git a/plat/hisilicon/hikey/hikey_io_storage.c b/plat/hisilicon/hikey/hikey_io_storage.c
index 90c2f81..ef55224 100644
--- a/plat/hisilicon/hikey/hikey_io_storage.c
+++ b/plat/hisilicon/hikey/hikey_io_storage.c
@@ -89,6 +89,44 @@
.uuid = UUID_SCP_FIRMWARE_SCP_BL2,
};
+#if TRUSTED_BOARD_BOOT
+static const io_uuid_spec_t trusted_key_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_KEY_CERT,
+};
+
+static const io_uuid_spec_t scp_fw_key_cert_uuid_spec = {
+ .uuid = UUID_SCP_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = {
+ .uuid = UUID_SOC_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
+};
+
+static const io_uuid_spec_t scp_fw_cert_uuid_spec = {
+ .uuid = UUID_SCP_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t soc_fw_cert_uuid_spec = {
+ .uuid = UUID_SOC_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t tos_fw_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
+};
+
+static const io_uuid_spec_t nt_fw_cert_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT,
+};
+#endif /* TRUSTED_BOARD_BOOT */
+
static const struct plat_io_policy policies[] = {
[FIP_IMAGE_ID] = {
&emmc_dev_handle,
@@ -124,7 +162,54 @@
&fip_dev_handle,
(uintptr_t)&bl33_uuid_spec,
check_fip
- }
+ },
+#if TRUSTED_BOARD_BOOT
+ [TRUSTED_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&trusted_key_cert_uuid_spec,
+ check_fip
+ },
+ [SCP_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&scp_fw_key_cert_uuid_spec,
+ check_fip
+ },
+ [SOC_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&soc_fw_key_cert_uuid_spec,
+ check_fip
+ },
+ [TRUSTED_OS_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tos_fw_key_cert_uuid_spec,
+ check_fip
+ },
+ [NON_TRUSTED_FW_KEY_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&nt_fw_key_cert_uuid_spec,
+ check_fip
+ },
+ [SCP_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&scp_fw_cert_uuid_spec,
+ check_fip
+ },
+ [SOC_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&soc_fw_cert_uuid_spec,
+ check_fip
+ },
+ [TRUSTED_OS_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&tos_fw_cert_uuid_spec,
+ check_fip
+ },
+ [NON_TRUSTED_FW_CONTENT_CERT_ID] = {
+ &fip_dev_handle,
+ (uintptr_t)&nt_fw_cert_uuid_spec,
+ check_fip
+ },
+#endif /* TRUSTED_BOARD_BOOT */
};
static int check_emmc(const uintptr_t spec)
diff --git a/plat/hisilicon/hikey/hikey_rotpk.S b/plat/hisilicon/hikey/hikey_rotpk.S
new file mode 100644
index 0000000..f308eee
--- /dev/null
+++ b/plat/hisilicon/hikey/hikey_rotpk.S
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ .global hikey_rotpk_hash
+ .global hikey_rotpk_hash_end
+ .section .rodata.hikey_rotpk_hash, "a"
+hikey_rotpk_hash:
+ /* DER header */
+ .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
+ .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+ /* SHA256 */
+ .incbin ROTPK_HASH
+hikey_rotpk_hash_end:
diff --git a/plat/hisilicon/hikey/hikey_tbbr.c b/plat/hisilicon/hikey/hikey_tbbr.c
new file mode 100644
index 0000000..20eda36
--- /dev/null
+++ b/plat/hisilicon/hikey/hikey_tbbr.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform.h>
+
+extern char hikey_rotpk_hash[], hikey_rotpk_hash_end[];
+
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ *key_ptr = hikey_rotpk_hash;
+ *key_len = hikey_rotpk_hash_end - hikey_rotpk_hash;
+ *flags = ROTPK_IS_HASH;
+
+ return 0;
+}
+
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ *nv_ctr = 0;
+
+ return 0;
+}
+
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ return 1;
+}
diff --git a/plat/hisilicon/hikey/include/hikey_layout.h b/plat/hisilicon/hikey/include/hikey_layout.h
index 637a1c9..5c593fc 100644
--- a/plat/hisilicon/hikey/include/hikey_layout.h
+++ b/plat/hisilicon/hikey/include/hikey_layout.h
@@ -58,10 +58,10 @@
* + loader +
* ++++++++++ 0xF980_1000
* + BL2 +
- * ++++++++++ 0xF981_8000
+ * ++++++++++ 0xF983_0000
*/
#define BL2_BASE (BL1_RO_BASE) /* 0xf980_1000 */
-#define BL2_LIMIT (0xF9818000) /* 0xf981_8000 */
+#define BL2_LIMIT (0xF9830000) /* 0xf983_0000 */
/*
* SCP_BL2 specific defines.
diff --git a/plat/hisilicon/hikey/include/platform_def.h b/plat/hisilicon/hikey/include/platform_def.h
index 8c56004..b240448 100644
--- a/plat/hisilicon/hikey/include/platform_def.h
+++ b/plat/hisilicon/hikey/include/platform_def.h
@@ -21,7 +21,7 @@
*/
/* Size of cacheable stacks */
-#define PLATFORM_STACK_SIZE 0x800
+#define PLATFORM_STACK_SIZE 0x1000
#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n"
diff --git a/plat/hisilicon/hikey/platform.mk b/plat/hisilicon/hikey/platform.mk
index 38eb148..acd1e62 100644
--- a/plat/hisilicon/hikey/platform.mk
+++ b/plat/hisilicon/hikey/platform.mk
@@ -122,6 +122,42 @@
lib/pmf/pmf_smc.c
endif
+ifneq (${TRUSTED_BOARD_BOOT},0)
+
+include drivers/auth/mbedtls/mbedtls_crypto.mk
+include drivers/auth/mbedtls/mbedtls_x509.mk
+
+USE_TBBR_DEFS := 1
+
+AUTH_SOURCES := drivers/auth/auth_mod.c \
+ drivers/auth/crypto_mod.c \
+ drivers/auth/img_parser_mod.c \
+ drivers/auth/tbbr/tbbr_cot.c
+
+BL2_SOURCES += ${AUTH_SOURCES} \
+ plat/common/tbbr/plat_tbbr.c \
+ plat/hisilicon/hikey/hikey_tbbr.c \
+ plat/hisilicon/hikey/hikey_rotpk.S
+
+ROT_KEY = $(BUILD_PLAT)/rot_key.pem
+ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin
+
+$(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
+$(BUILD_PLAT)/bl2/hikey_rotpk.o: $(ROTPK_HASH)
+
+certificates: $(ROT_KEY)
+$(ROT_KEY): | $(BUILD_PLAT)
+ @echo " OPENSSL $@"
+ $(Q)openssl genrsa 2048 > $@ 2>/dev/null
+
+$(ROTPK_HASH): $(ROT_KEY)
+ @echo " OPENSSL $@"
+ $(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\
+ openssl dgst -sha256 -binary > $@ 2>/dev/null
+
+override BL1_SOURCES =
+endif
+
# Enable workarounds for selected Cortex-A53 errata.
ERRATA_A53_836870 := 1
ERRATA_A53_843419 := 1
diff --git a/plat/imx/common/imx8_psci.c b/plat/imx/common/imx8_psci.c
new file mode 100644
index 0000000..22a531b
--- /dev/null
+++ b/plat/imx/common/imx8_psci.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <debug.h>
+#include <plat_imx8.h>
+#include <sci/sci.h>
+#include <stdbool.h>
+
+void __dead2 imx_system_off(void)
+{
+ sc_pm_set_sys_power_mode(ipc_handle, SC_PM_PW_MODE_OFF);
+ wfi();
+ ERROR("power off failed.\n");
+ panic();
+}
+
+void __dead2 imx_system_reset(void)
+{
+ sc_pm_reset(ipc_handle, SC_PM_RESET_TYPE_BOARD);
+ wfi();
+ ERROR("system reset failed.\n");
+ panic();
+}
+
+int imx_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state)
+{
+ /* TODO */
+ return PSCI_E_INVALID_PARAMS;
+}
+
+void imx_get_sys_suspend_power_state(psci_power_state_t *req_state)
+{
+ unsigned int i;
+
+ /* CPU & cluster off, system in retention */
+ for (i = MPIDR_AFFLVL0; i < PLAT_MAX_PWR_LVL; i++)
+ req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE;
+ req_state->pwr_domain_state[PLAT_MAX_PWR_LVL] = PLAT_MAX_RET_STATE;
+}
+
diff --git a/plat/imx/common/imx8_topology.c b/plat/imx/common/imx8_topology.c
index bcb7d59..64145c4 100644
--- a/plat/imx/common/imx8_topology.c
+++ b/plat/imx/common/imx8_topology.c
@@ -11,7 +11,8 @@
const unsigned char imx_power_domain_tree_desc[] = {
PWR_DOMAIN_AT_MAX_LVL,
PLATFORM_CLUSTER_COUNT,
- PLATFORM_CORE_COUNT,
+ PLATFORM_CLUSTER0_CORE_COUNT,
+ PLATFORM_CLUSTER1_CORE_COUNT,
};
const unsigned char *plat_get_power_domain_tree_desc(void)
diff --git a/plat/imx/common/include/plat_imx8.h b/plat/imx/common/include/plat_imx8.h
index 27d4c37..a333bfb 100644
--- a/plat/imx/common/include/plat_imx8.h
+++ b/plat/imx/common/include/plat_imx8.h
@@ -8,6 +8,7 @@
#define __PLAT_IMX8_H__
#include <gicv3.h>
+#include <psci.h>
unsigned int plat_calc_core_pos(uint64_t mpidr);
void imx_mailbox_init(uintptr_t base_addr);
@@ -17,4 +18,9 @@
void plat_gic_cpuif_disable(void);
void plat_gic_pcpu_init(void);
+void __dead2 imx_system_off(void);
+void __dead2 imx_system_reset(void);
+int imx_validate_power_state(unsigned int power_state,
+ psci_power_state_t *req_state);
+void imx_get_sys_suspend_power_state(psci_power_state_t *req_state);
#endif /*__PLAT_IMX8_H__ */
diff --git a/plat/imx/imx8qm/imx8qm_psci.c b/plat/imx/imx8qm/imx8qm_psci.c
index b9b794b..c37c39c 100644
--- a/plat/imx/imx8qm/imx8qm_psci.c
+++ b/plat/imx/imx8qm/imx8qm_psci.c
@@ -15,17 +15,18 @@
#include <sci/sci.h>
#include <stdbool.h>
+#define CORE_PWR_STATE(state) \
+ ((state)->pwr_domain_state[MPIDR_AFFLVL0])
+#define CLUSTER_PWR_STATE(state) \
+ ((state)->pwr_domain_state[MPIDR_AFFLVL1])
+#define SYSTEM_PWR_STATE(state) \
+ ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL])
+
const static int ap_core_index[PLATFORM_CORE_COUNT] = {
SC_R_A53_0, SC_R_A53_1, SC_R_A53_2,
SC_R_A53_3, SC_R_A72_0, SC_R_A72_1,
};
-/* need to enable USE_COHERENT_MEM to avoid coherence issue */
-#if USE_COHERENT_MEM
-static unsigned int a53_cpu_on_number __section("tzfw_coherent_mem");
-static unsigned int a72_cpu_on_number __section("tzfw_coherent_mem");
-#endif
-
int imx_pwr_domain_on(u_register_t mpidr)
{
int ret = PSCI_E_SUCCESS;
@@ -37,9 +38,8 @@
tf_printf("imx_pwr_domain_on cluster_id %d, cpu_id %d\n", cluster_id, cpu_id);
if (cluster_id == 0) {
- if (a53_cpu_on_number == 0)
- sc_pm_set_resource_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_ON);
-
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_A53,
+ SC_PM_PW_MODE_ON);
if (sc_pm_set_resource_power_mode(ipc_handle, ap_core_index[cpu_id],
SC_PM_PW_MODE_ON) != SC_ERR_NONE) {
ERROR("cluster0 core %d power on failed!\n", cpu_id);
@@ -52,9 +52,8 @@
ret = PSCI_E_INTERN_FAIL;
}
} else {
- if (a72_cpu_on_number == 0)
- sc_pm_set_resource_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_ON);
-
+ sc_pm_set_resource_power_mode(ipc_handle, SC_R_A72,
+ SC_PM_PW_MODE_ON);
if (sc_pm_set_resource_power_mode(ipc_handle, ap_core_index[cpu_id + 4],
SC_PM_PW_MODE_ON) != SC_ERR_NONE) {
ERROR(" cluster1 core %d power on failed!\n", cpu_id);
@@ -74,17 +73,56 @@
void imx_pwr_domain_on_finish(const psci_power_state_t *target_state)
{
uint64_t mpidr = read_mpidr_el1();
- unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
- if (cluster_id == 0 && a53_cpu_on_number++ == 0)
- cci_enable_snoop_dvm_reqs(0);
- if (cluster_id == 1 && a72_cpu_on_number++ == 0)
- cci_enable_snoop_dvm_reqs(1);
+ if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
plat_gic_pcpu_init();
plat_gic_cpuif_enable();
}
+void imx_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+ unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ plat_gic_cpuif_disable();
+ sc_pm_req_cpu_low_power_mode(ipc_handle,
+ ap_core_index[cpu_id + cluster_id * 4],
+ SC_PM_PW_MODE_OFF,
+ SC_PM_WAKE_SRC_NONE);
+ if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE)
+ cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+ tf_printf("turn off cluster:%d core:%d\n", cluster_id, cpu_id);
+}
+
+void imx_domain_suspend(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
+ unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ plat_gic_cpuif_disable();
+
+ cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+
+ sc_pm_set_cpu_resume_addr(ipc_handle,
+ ap_core_index[cpu_id + cluster_id * 4], BL31_BASE);
+ sc_pm_req_cpu_low_power_mode(ipc_handle,
+ ap_core_index[cpu_id + cluster_id * 4],
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_GIC);
+}
+
+void imx_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+
+ cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(mpidr));
+
+ plat_gic_cpuif_enable();
+}
+
int imx_validate_ns_entrypoint(uintptr_t ns_entrypoint)
{
return PSCI_E_SUCCESS;
@@ -93,22 +131,42 @@
static const plat_psci_ops_t imx_plat_psci_ops = {
.pwr_domain_on = imx_pwr_domain_on,
.pwr_domain_on_finish = imx_pwr_domain_on_finish,
+ .pwr_domain_off = imx_pwr_domain_off,
+ .pwr_domain_suspend = imx_domain_suspend,
+ .pwr_domain_suspend_finish = imx_domain_suspend_finish,
+ .get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
+ .validate_power_state = imx_validate_power_state,
.validate_ns_entrypoint = imx_validate_ns_entrypoint,
+ .system_off = imx_system_off,
+ .system_reset = imx_system_reset,
};
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
const plat_psci_ops_t **psci_ops)
{
- uint64_t mpidr = read_mpidr_el1();
- unsigned int cluster_id = MPIDR_AFFLVL1_VAL(mpidr);
-
imx_mailbox_init(sec_entrypoint);
*psci_ops = &imx_plat_psci_ops;
- if (cluster_id == 0)
- a53_cpu_on_number++;
- else
- a72_cpu_on_number++;
+ /* Request low power mode for cluster/cci, only need to do once */
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A72, SC_PM_PW_MODE_OFF);
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A53, SC_PM_PW_MODE_OFF);
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_CCI, SC_PM_PW_MODE_OFF);
+
+ /* Request RUN and LP modes for DDR, system interconnect etc. */
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53,
+ SC_PM_SYS_IF_DDR, SC_PM_PW_MODE_ON, SC_PM_PW_MODE_STBY);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72,
+ SC_PM_SYS_IF_DDR, SC_PM_PW_MODE_ON, SC_PM_PW_MODE_STBY);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53,
+ SC_PM_SYS_IF_MU, SC_PM_PW_MODE_ON, SC_PM_PW_MODE_STBY);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72,
+ SC_PM_SYS_IF_MU, SC_PM_PW_MODE_ON, SC_PM_PW_MODE_STBY);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A53,
+ SC_PM_SYS_IF_INTERCONNECT, SC_PM_PW_MODE_ON,
+ SC_PM_PW_MODE_STBY);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A72,
+ SC_PM_SYS_IF_INTERCONNECT, SC_PM_PW_MODE_ON,
+ SC_PM_PW_MODE_STBY);
return 0;
}
diff --git a/plat/imx/imx8qm/platform.mk b/plat/imx/imx8qm/platform.mk
index c295e14..022ad99 100644
--- a/plat/imx/imx8qm/platform.mk
+++ b/plat/imx/imx8qm/platform.mk
@@ -21,6 +21,7 @@
plat/imx/imx8qm/imx8qm_bl31_setup.c \
plat/imx/imx8qm/imx8qm_psci.c \
plat/imx/common/imx8_topology.c \
+ plat/imx/common/imx8_psci.c \
lib/xlat_tables/aarch64/xlat_tables.c \
lib/xlat_tables/xlat_tables_common.c \
lib/cpus/aarch64/cortex_a53.S \
diff --git a/plat/imx/imx8qx/imx8qx_psci.c b/plat/imx/imx8qx/imx8qx_psci.c
index 47233dc..f1df267 100644
--- a/plat/imx/imx8qx/imx8qx_psci.c
+++ b/plat/imx/imx8qx/imx8qx_psci.c
@@ -18,13 +18,6 @@
SC_R_A35_0, SC_R_A35_1, SC_R_A35_2, SC_R_A35_3
};
-plat_local_state_t plat_get_target_pwr_state(unsigned int lvl,
- const plat_local_state_t *target_state,
- unsigned int ncpu)
-{
- return 0;
-}
-
int imx_pwr_domain_on(u_register_t mpidr)
{
int ret = PSCI_E_SUCCESS;
@@ -60,10 +53,51 @@
return PSCI_E_SUCCESS;
}
+void imx_pwr_domain_off(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ plat_gic_cpuif_disable();
+ sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_NONE);
+ tf_printf("turn off core:%d\n", cpu_id);
+}
+
+void imx_domain_suspend(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ plat_gic_cpuif_disable();
+
+ sc_pm_set_cpu_resume_addr(ipc_handle, ap_core_index[cpu_id], BL31_BASE);
+ sc_pm_req_cpu_low_power_mode(ipc_handle, ap_core_index[cpu_id],
+ SC_PM_PW_MODE_OFF, SC_PM_WAKE_SRC_GIC);
+}
+
+void imx_domain_suspend_finish(const psci_power_state_t *target_state)
+{
+ u_register_t mpidr = read_mpidr_el1();
+ unsigned int cpu_id = MPIDR_AFFLVL0_VAL(mpidr);
+
+ sc_pm_req_low_power_mode(ipc_handle, ap_core_index[cpu_id],
+ SC_PM_PW_MODE_ON);
+
+ plat_gic_cpuif_enable();
+}
+
static const plat_psci_ops_t imx_plat_psci_ops = {
.pwr_domain_on = imx_pwr_domain_on,
.pwr_domain_on_finish = imx_pwr_domain_on_finish,
.validate_ns_entrypoint = imx_validate_ns_entrypoint,
+ .system_off = imx_system_off,
+ .system_reset = imx_system_reset,
+ .pwr_domain_off = imx_pwr_domain_off,
+ .pwr_domain_suspend = imx_domain_suspend,
+ .pwr_domain_suspend_finish = imx_domain_suspend_finish,
+ .get_sys_suspend_power_state = imx_get_sys_suspend_power_state,
+ .validate_power_state = imx_validate_power_state,
};
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
@@ -72,5 +106,17 @@
imx_mailbox_init(sec_entrypoint);
*psci_ops = &imx_plat_psci_ops;
+ /* Request low power mode for A35 cluster, only need to do once */
+ sc_pm_req_low_power_mode(ipc_handle, SC_R_A35, SC_PM_PW_MODE_OFF);
+
+ /* Request RUN and LP modes for DDR, system interconnect etc. */
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35,
+ SC_PM_SYS_IF_DDR, SC_PM_PW_MODE_ON, SC_PM_PW_MODE_STBY);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35,
+ SC_PM_SYS_IF_MU, SC_PM_PW_MODE_ON, SC_PM_PW_MODE_STBY);
+ sc_pm_req_sys_if_power_mode(ipc_handle, SC_R_A35,
+ SC_PM_SYS_IF_INTERCONNECT, SC_PM_PW_MODE_ON,
+ SC_PM_PW_MODE_STBY);
+
return 0;
}
diff --git a/plat/imx/imx8qx/include/platform_def.h b/plat/imx/imx8qx/include/platform_def.h
index 2cd1400..8c86174 100644
--- a/plat/imx/imx8qx/include/platform_def.h
+++ b/plat/imx/imx8qx/include/platform_def.h
@@ -17,6 +17,8 @@
#define PLATFORM_MAX_CPU_PER_CLUSTER 4
#define PLATFORM_CLUSTER_COUNT 1
#define PLATFORM_CORE_COUNT 4
+#define PLATFORM_CLUSTER0_CORE_COUNT 4
+#define PLATFORM_CLUSTER1_CORE_COUNT 0
#define PWR_DOMAIN_AT_MAX_LVL 1
#define PLAT_MAX_PWR_LVL 2
diff --git a/plat/imx/imx8qx/platform.mk b/plat/imx/imx8qx/platform.mk
index c16ce6e..0676618 100644
--- a/plat/imx/imx8qx/platform.mk
+++ b/plat/imx/imx8qx/platform.mk
@@ -20,6 +20,8 @@
plat/imx/imx8qx/imx8qx_bl31_setup.c \
plat/imx/imx8qx/imx8qx_psci.c \
plat/imx/common/imx8_topology.c \
+ plat/imx/common/imx8_psci.c \
+ plat/common/plat_psci_common.c \
lib/xlat_tables/xlat_tables_common.c \
lib/xlat_tables/aarch64/xlat_tables.c \
lib/cpus/aarch64/cortex_a35.S \
diff --git a/plat/mediatek/mt6795/bl31.ld.S b/plat/mediatek/mt6795/bl31.ld.S
index 0fbd3f7..8f391df 100644
--- a/plat/mediatek/mt6795/bl31.ld.S
+++ b/plat/mediatek/mt6795/bl31.ld.S
@@ -59,7 +59,7 @@
* executable. No RW data from the next section must creep in.
* Ensure the rest of the current memory page is unused.
*/
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__RO_END__ = .;
} >RAM
@@ -161,7 +161,7 @@
* as device memory. No other unexpected data must creep in.
* Ensure the rest of the current memory page is unused.
*/
- . = NEXT(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
__COHERENT_RAM_END__ = .;
} >RAM2
#endif
diff --git a/plat/mediatek/mt6795/power_tracer.c b/plat/mediatek/mt6795/power_tracer.c
index f5208d0..56e2240 100644
--- a/plat/mediatek/mt6795/power_tracer.c
+++ b/plat/mediatek/mt6795/power_tracer.c
@@ -14,30 +14,30 @@
{
switch (mode) {
case CPU_UP:
- trace_log("core %ld:%ld ON\n",
+ trace_log("core %lld:%lld ON\n",
(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS,
(mpidr & MPIDR_CPU_MASK));
break;
case CPU_DOWN:
- trace_log("core %ld:%ld OFF\n",
+ trace_log("core %lld:%lld OFF\n",
(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS,
(mpidr & MPIDR_CPU_MASK));
break;
case CPU_SUSPEND:
- trace_log("core %ld:%ld SUSPEND\n",
+ trace_log("core %lld:%lld SUSPEND\n",
(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS,
(mpidr & MPIDR_CPU_MASK));
break;
case CLUSTER_UP:
- trace_log("cluster %ld ON\n",
+ trace_log("cluster %lld ON\n",
(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS);
break;
case CLUSTER_DOWN:
- trace_log("cluster %ld OFF\n",
+ trace_log("cluster %lld OFF\n",
(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS);
break;
case CLUSTER_SUSPEND:
- trace_log("cluster %ld SUSPEND\n",
+ trace_log("cluster %lld SUSPEND\n",
(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS);
break;
default:
diff --git a/plat/mediatek/mt8173/power_tracer.c b/plat/mediatek/mt8173/power_tracer.c
index 5c0a468..787dad1 100644
--- a/plat/mediatek/mt8173/power_tracer.c
+++ b/plat/mediatek/mt8173/power_tracer.c
@@ -14,30 +14,30 @@
{
switch (mode) {
case CPU_UP:
- trace_log("core %ld:%ld ON\n",
+ trace_log("core %lld:%lld ON\n",
(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS,
(mpidr & MPIDR_CPU_MASK));
break;
case CPU_DOWN:
- trace_log("core %ld:%ld OFF\n",
+ trace_log("core %lld:%lld OFF\n",
(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS,
(mpidr & MPIDR_CPU_MASK));
break;
case CPU_SUSPEND:
- trace_log("core %ld:%ld SUSPEND\n",
+ trace_log("core %lld:%lld SUSPEND\n",
(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS,
(mpidr & MPIDR_CPU_MASK));
break;
case CLUSTER_UP:
- trace_log("cluster %ld ON\n",
+ trace_log("cluster %lld ON\n",
(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS);
break;
case CLUSTER_DOWN:
- trace_log("cluster %ld OFF\n",
+ trace_log("cluster %lld OFF\n",
(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS);
break;
case CLUSTER_SUSPEND:
- trace_log("cluster %ld SUSPEND\n",
+ trace_log("cluster %lld SUSPEND\n",
(mpidr & MPIDR_CLUSTER_MASK) >> MPIDR_AFFINITY_BITS);
break;
default:
diff --git a/plat/nvidia/tegra/common/tegra_bl31_setup.c b/plat/nvidia/tegra/common/tegra_bl31_setup.c
index 2fe4e7d..f0a7036 100644
--- a/plat/nvidia/tegra/common/tegra_bl31_setup.c
+++ b/plat/nvidia/tegra/common/tegra_bl31_setup.c
@@ -116,9 +116,6 @@
{
plat_params_from_bl2_t *plat_params =
(plat_params_from_bl2_t *)plat_params_from_bl2;
-#if LOG_LEVEL >= LOG_LEVEL_INFO
- int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
-#endif
image_info_t bl32_img_info = { {0} };
uint64_t tzdram_start, tzdram_end, bl32_start, bl32_end;
@@ -227,8 +224,9 @@
/* Early platform setup for Tegra SoCs */
plat_early_platform_setup();
- INFO("BL3-1: Boot CPU: %s Processor [%lx]\n", (impl == DENVER_IMPL) ?
- "Denver" : "ARM", read_mpidr());
+ INFO("BL3-1: Boot CPU: %s Processor [%lx]\n",
+ (((read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK)
+ == DENVER_IMPL) ? "Denver" : "ARM", read_mpidr());
}
#ifdef SPD_trusty
diff --git a/plat/rockchip/common/pmusram/pmu_sram_cpus_on.S b/plat/rockchip/common/pmusram/pmu_sram_cpus_on.S
index 5a1854b..991fe6c 100644
--- a/plat/rockchip/common/pmusram/pmu_sram_cpus_on.S
+++ b/plat/rockchip/common/pmusram/pmu_sram_cpus_on.S
@@ -12,7 +12,6 @@
.macro pmusram_entry_func _name
.section .pmusram.entry, "ax"
.type \_name, %function
- .func \_name
.cfi_startproc
\_name:
.endm
diff --git a/plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S b/plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S
index 70fd9bf..546c09a 100644
--- a/plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S
+++ b/plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S
@@ -15,7 +15,6 @@
.cfi_sections .debug_frame
.section .sram.text, "ax"
.type \_name, %function
- .func \_name
.cfi_startproc
\_name:
.endm
diff --git a/plat/rpi3/aarch64/plat_helpers.S b/plat/rpi3/aarch64/plat_helpers.S
index 65c1bf2..7974b60 100644
--- a/plat/rpi3/aarch64/plat_helpers.S
+++ b/plat/rpi3/aarch64/plat_helpers.S
@@ -175,9 +175,5 @@
mov w1, #0x80000000
str wzr, [x0, #RPI3_INTC_CONTROL_OFFSET]
str w1, [x0, #RPI3_INTC_PRESCALER_OFFSET]
-
- /* wire mailbox 3 to the FIQ line */
- mov w1, RPI3_INTC_MBOX_CONTROL_SLOT3_FIQ
- str w1, [x0, #RPI3_INTC_MBOX_CONTROL_OFFSET]
ret
endfunc plat_reset_handler
diff --git a/plat/rpi3/include/platform_def.h b/plat/rpi3/include/platform_def.h
index ebd77cd..4674bfb 100644
--- a/plat/rpi3/include/platform_def.h
+++ b/plat/rpi3/include/platform_def.h
@@ -64,23 +64,23 @@
* there is no Secure RAM in the Raspberry Pi 3.
*/
#define SEC_ROM_BASE ULL(0x00000000)
-#define SEC_ROM_SIZE ULL(0x00010000)
+#define SEC_ROM_SIZE ULL(0x00020000)
/* FIP placed after ROM to append it to BL1 with very little padding. */
-#define PLAT_RPI3_FIP_BASE ULL(0x00010000)
-#define PLAT_RPI3_FIP_MAX_SIZE ULL(0x001F0000)
+#define PLAT_RPI3_FIP_BASE ULL(0x00020000)
+#define PLAT_RPI3_FIP_MAX_SIZE ULL(0x001E0000)
-/* We have 16M of memory reserved at at 256M */
+/* We have 16M of memory reserved starting at 256M */
#define SEC_SRAM_BASE ULL(0x10000000)
#define SEC_SRAM_SIZE ULL(0x00100000)
#define SEC_DRAM0_BASE ULL(0x10100000)
-#define SEC_DRAM0_SIZE ULL(0x00200000)
-
-#define NS_DRAM0_BASE ULL(0x10300000)
-#define NS_DRAM0_SIZE ULL(0x00D00000)
+#define SEC_DRAM0_SIZE ULL(0x00F00000)
/* End of reserved memory */
+#define NS_DRAM0_BASE ULL(0x11000000)
+#define NS_DRAM0_SIZE ULL(0x01000000)
+
/*
* BL33 entrypoint.
*/
@@ -117,9 +117,11 @@
*/
#define PLAT_RPI3_TRUSTED_MAILBOX_BASE SHARED_RAM_BASE
+/* The secure entry point to be used on warm reset by all CPUs. */
#define PLAT_RPI3_TM_ENTRYPOINT PLAT_RPI3_TRUSTED_MAILBOX_BASE
#define PLAT_RPI3_TM_ENTRYPOINT_SIZE ULL(8)
+/* Hold entries for each CPU. */
#define PLAT_RPI3_TM_HOLD_BASE (PLAT_RPI3_TM_ENTRYPOINT + \
PLAT_RPI3_TM_ENTRYPOINT_SIZE)
#define PLAT_RPI3_TM_HOLD_ENTRY_SIZE ULL(8)
diff --git a/plat/rpi3/platform.mk b/plat/rpi3/platform.mk
index 2aaf406..4276c84 100644
--- a/plat/rpi3/platform.mk
+++ b/plat/rpi3/platform.mk
@@ -20,7 +20,8 @@
plat/common/aarch64/platform_mp_stack.S \
plat/rpi3/aarch64/plat_helpers.S \
plat/rpi3/rpi3_bl1_setup.c \
- plat/rpi3/rpi3_io_storage.c
+ plat/rpi3/rpi3_io_storage.c \
+ plat/rpi3/rpi3_mbox.c
BL2_SOURCES += common/desc_image_load.c \
drivers/io/io_fip.c \
@@ -54,6 +55,26 @@
TF_CFLAGS_aarch64 += -mtune=cortex-a53
endif
+# Platform Makefile target
+# ------------------------
+
+RPI3_BL1_PAD_BIN := ${BUILD_PLAT}/bl1_pad.bin
+RPI3_ARMSTUB8_BIN := ${BUILD_PLAT}/armstub8.bin
+
+# Add new default target when compiling this platform
+all: armstub
+
+# This target concatenates BL1 and the FIP so that the base addresses match the
+# ones defined in the memory map
+armstub: bl1 fip
+ @echo " CAT $@"
+ ${Q}cp ${BUILD_PLAT}/bl1.bin ${RPI3_BL1_PAD_BIN}
+ ${Q}truncate --size=131072 ${RPI3_BL1_PAD_BIN}
+ ${Q}cat ${RPI3_BL1_PAD_BIN} ${BUILD_PLAT}/fip.bin > ${RPI3_ARMSTUB8_BIN}
+ @${ECHO_BLANK_LINE}
+ @echo "Built $@ successfully"
+ @${ECHO_BLANK_LINE}
+
# Build config flags
# ------------------
@@ -69,8 +90,11 @@
# Disable the PSCI platform compatibility layer by default
ENABLE_PLAT_COMPAT := 0
-# Enable reset to BL31 by default
-RESET_TO_BL31 := 1
+# Disable stack protector by default
+ENABLE_STACK_PROTECTOR := 0
+
+# Reset to BL31 isn't supported
+RESET_TO_BL31 := 0
# Have different sections for code and rodata
SEPARATE_CODE_AND_RODATA := 1
@@ -90,6 +114,9 @@
# BL33 images are in AArch64 by default
RPI3_BL33_IN_AARCH32 := 0
+# Assume that BL33 isn't the Linux kernel by default
+RPI3_DIRECT_LINUX_BOOT := 0
+
# BL32 location
RPI3_BL32_RAM_LOCATION := tdram
ifeq (${RPI3_BL32_RAM_LOCATION}, tsram)
@@ -105,9 +132,17 @@
$(eval $(call add_define,RPI3_BL32_RAM_LOCATION_ID))
$(eval $(call add_define,RPI3_BL33_IN_AARCH32))
+$(eval $(call add_define,RPI3_DIRECT_LINUX_BOOT))
+$(eval $(call add_define,RPI3_PRELOADED_DTB_BASE))
# Verify build config
# -------------------
+#
+ifneq (${RPI3_DIRECT_LINUX_BOOT}, 0)
+ ifndef RPI3_PRELOADED_DTB_BASE
+ $(error Error: RPI3_PRELOADED_DTB_BASE needed if RPI3_DIRECT_LINUX_BOOT=1)
+ endif
+endif
ifneq (${LOAD_IMAGE_V2}, 1)
$(error Error: rpi3 needs LOAD_IMAGE_V2=1)
@@ -117,10 +152,19 @@
$(error Error: rpi3 needs MULTI_CONSOLE_API=1)
endif
+ifneq (${RESET_TO_BL31}, 0)
+ $(error Error: rpi3 needs RESET_TO_BL31=0)
+endif
+
ifeq (${ARCH},aarch32)
$(error Error: AArch32 not supported on rpi3)
endif
+ifneq ($(ENABLE_STACK_PROTECTOR), 0)
+PLAT_BL_COMMON_SOURCES += plat/rpi3/rpi3_rng.c \
+ plat/rpi3/rpi3_stack_protector.c
+endif
+
ifeq (${SPD},opteed)
BL2_SOURCES += \
lib/optee/optee_utils.c
@@ -134,3 +178,48 @@
ifneq ($(BL32_EXTRA2),)
$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2))
endif
+
+ifneq (${TRUSTED_BOARD_BOOT},0)
+
+ include drivers/auth/mbedtls/mbedtls_crypto.mk
+ include drivers/auth/mbedtls/mbedtls_x509.mk
+
+ USE_TBBR_DEFS := 1
+
+ AUTH_SOURCES := drivers/auth/auth_mod.c \
+ drivers/auth/crypto_mod.c \
+ drivers/auth/img_parser_mod.c \
+ drivers/auth/tbbr/tbbr_cot.c
+
+ PLAT_INCLUDES += -Iinclude/bl1/tbbr
+
+ BL1_SOURCES += ${AUTH_SOURCES} \
+ bl1/tbbr/tbbr_img_desc.c \
+ plat/common/tbbr/plat_tbbr.c \
+ plat/rpi3/rpi3_trusted_boot.c \
+ plat/rpi3/rpi3_rotpk.S
+
+ BL2_SOURCES += ${AUTH_SOURCES} \
+ plat/common/tbbr/plat_tbbr.c \
+ plat/rpi3/rpi3_trusted_boot.c \
+ plat/rpi3/rpi3_rotpk.S
+
+ ROT_KEY = $(BUILD_PLAT)/rot_key.pem
+ ROTPK_HASH = $(BUILD_PLAT)/rotpk_sha256.bin
+
+ $(eval $(call add_define_val,ROTPK_HASH,'"$(ROTPK_HASH)"'))
+
+ $(BUILD_PLAT)/bl1/rpi3_rotpk.o: $(ROTPK_HASH)
+ $(BUILD_PLAT)/bl2/rpi3_rotpk.o: $(ROTPK_HASH)
+
+ certificates: $(ROT_KEY)
+
+ $(ROT_KEY):
+ @echo " OPENSSL $@"
+ $(Q)openssl genrsa 2048 > $@ 2>/dev/null
+
+ $(ROTPK_HASH): $(ROT_KEY)
+ @echo " OPENSSL $@"
+ $(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\
+ openssl dgst -sha256 -binary > $@ 2>/dev/null
+endif
diff --git a/plat/rpi3/rpi3_bl1_setup.c b/plat/rpi3/rpi3_bl1_setup.c
index c98715b..39bb332 100644
--- a/plat/rpi3/rpi3_bl1_setup.c
+++ b/plat/rpi3/rpi3_bl1_setup.c
@@ -7,6 +7,7 @@
#include <arch.h>
#include <arch_helpers.h>
#include <bl_common.h>
+#include <debug.h>
#include <platform_def.h>
#include <xlat_mmu_helpers.h>
#include <xlat_tables_defs.h>
@@ -56,6 +57,39 @@
void bl1_platform_setup(void)
{
+ uint32_t __unused rev;
+ int __unused rc;
+
+ rc = rpi3_vc_hardware_get_board_revision(&rev);
+
+ if (rc == 0) {
+ const char __unused *model, __unused *info;
+
+ switch (rev) {
+ case 0xA02082:
+ model = "Raspberry Pi 3 Model B";
+ info = "(1GB, Sony, UK)";
+ break;
+ case 0xA22082:
+ model = "Raspberry Pi 3 Model B";
+ info = "(1GB, Embest, China)";
+ break;
+ case 0xA020D3:
+ model = "Raspberry Pi 3 Model B+";
+ info = "(1GB, Sony, UK)";
+ break;
+ default:
+ model = "Unknown";
+ info = "(Unknown)";
+ ERROR("rpi3: Unknown board revision 0x%08x\n", rev);
+ break;
+ }
+
+ NOTICE("rpi3: Detected: %s %s [0x%08x]\n", model, info, rev);
+ } else {
+ ERROR("rpi3: Unable to detect board revision\n");
+ }
+
/* Initialise the IO layer and register platform IO devices */
plat_rpi3_io_setup();
}
diff --git a/plat/rpi3/rpi3_bl31_setup.c b/plat/rpi3/rpi3_bl31_setup.c
index 58344ae..5bbb13c 100644
--- a/plat/rpi3/rpi3_bl31_setup.c
+++ b/plat/rpi3/rpi3_bl31_setup.c
@@ -59,39 +59,6 @@
/* Initialize the console to provide early debug support */
rpi3_console_init();
-#if RESET_TO_BL31
-
- /* There are no parameters from BL2 if BL31 is a reset vector */
- assert(from_bl2 == NULL);
- assert(plat_params_from_bl2 == NULL);
-
-#ifdef BL32_BASE
- /* Populate entry point information for BL32 */
- SET_PARAM_HEAD(&bl32_image_ep_info,
- PARAM_EP,
- VERSION_1,
- 0);
- SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE);
- bl32_image_ep_info.pc = BL32_BASE;
- bl32_image_ep_info.spsr = rpi3_get_spsr_for_bl32_entry();
-#endif /* BL32_BASE */
-
- /* Populate entry point information for BL33 */
- SET_PARAM_HEAD(&bl33_image_ep_info,
- PARAM_EP,
- VERSION_1,
- 0);
- /*
- * Tell BL31 where the non-trusted software image
- * is located and the entry state information
- */
- bl33_image_ep_info.pc = plat_get_ns_image_entrypoint();
-
- bl33_image_ep_info.spsr = rpi3_get_spsr_for_bl33_entry();
- SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE);
-
-#else /* RESET_TO_BL31 */
-
/*
* In debug builds, we pass a special value in 'plat_params_from_bl2'
* to verify platform parameters from BL2 to BL31.
@@ -130,7 +97,33 @@
panic();
}
-#endif /* RESET_TO_BL31 */
+#if RPI3_DIRECT_LINUX_BOOT
+# if RPI3_BL33_IN_AARCH32
+ /*
+ * According to the file ``Documentation/arm/Booting`` of the Linux
+ * kernel tree, Linux expects:
+ * r0 = 0
+ * r1 = machine type number, optional in DT-only platforms (~0 if so)
+ * r2 = Physical address of the device tree blob
+ */
+ VERBOSE("rpi3: Preparing to boot 32-bit Linux kernel\n");
+ bl33_image_ep_info.args.arg0 = 0U;
+ bl33_image_ep_info.args.arg1 = ~0U;
+ bl33_image_ep_info.args.arg2 = (u_register_t) RPI3_PRELOADED_DTB_BASE;
+# else
+ /*
+ * According to the file ``Documentation/arm64/booting.txt`` of the
+ * Linux kernel tree, Linux expects the physical address of the device
+ * tree blob (DTB) in x0, while x1-x3 are reserved for future use and
+ * must be 0.
+ */
+ VERBOSE("rpi3: Preparing to boot 64-bit Linux kernel\n");
+ bl33_image_ep_info.args.arg0 = (u_register_t) RPI3_PRELOADED_DTB_BASE;
+ bl33_image_ep_info.args.arg1 = 0ULL;
+ bl33_image_ep_info.args.arg2 = 0ULL;
+ bl33_image_ep_info.args.arg3 = 0ULL;
+# endif /* RPI3_BL33_IN_AARCH32 */
+#endif /* RPI3_DIRECT_LINUX_BOOT */
}
void bl31_plat_arch_setup(void)
@@ -148,12 +141,10 @@
void bl31_platform_setup(void)
{
-#if RESET_TO_BL31
/*
* Do initial security configuration to allow DRAM/device access
* (if earlier BL has not already done so).
*/
-#endif /* RESET_TO_BL31 */
return;
}
diff --git a/plat/rpi3/rpi3_common.c b/plat/rpi3/rpi3_common.c
index 65f5e7a..98cf534 100644
--- a/plat/rpi3/rpi3_common.c
+++ b/plat/rpi3/rpi3_common.c
@@ -5,6 +5,7 @@
*/
#include <arch_helpers.h>
+#include <assert.h>
#include <bl_common.h>
#include <console.h>
#include <debug.h>
@@ -198,15 +199,21 @@
uint32_t plat_ic_get_pending_interrupt_type(void)
{
+ ERROR("rpi3: Interrupt routed to EL3.\n");
return INTR_TYPE_INVAL;
}
-uint32_t plat_interrupt_type_to_line(uint32_t type,
- uint32_t security_state)
+uint32_t plat_interrupt_type_to_line(uint32_t type, uint32_t security_state)
{
- /* It is not expected to receive an interrupt route to EL3.
- * Hence panic() to flag error.
- */
- ERROR("Interrupt not expected to be routed to EL3");
- panic();
+ assert((type == INTR_TYPE_S_EL1) || (type == INTR_TYPE_EL3) ||
+ (type == INTR_TYPE_NS));
+
+ assert(sec_state_is_valid(security_state));
+
+ /* Non-secure interrupts are signalled on the IRQ line always. */
+ if (type == INTR_TYPE_NS)
+ return __builtin_ctz(SCR_IRQ_BIT);
+
+ /* Secure interrupts are signalled on the FIQ line always. */
+ return __builtin_ctz(SCR_FIQ_BIT);
}
diff --git a/plat/rpi3/rpi3_hw.h b/plat/rpi3/rpi3_hw.h
index 70272e0..1a26053 100644
--- a/plat/rpi3/rpi3_hw.h
+++ b/plat/rpi3/rpi3_hw.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -17,11 +17,25 @@
#define RPI3_IO_SIZE ULL(0x01000000)
/*
- * Serial port (called 'Mini UART' in the BCM docucmentation).
+ * ARM <-> VideoCore mailboxes
*/
-#define RPI3_IO_MINI_UART_OFFSET ULL(0x00215040)
-#define RPI3_MINI_UART_BASE (RPI3_IO_BASE + RPI3_IO_MINI_UART_OFFSET)
-#define RPI3_MINI_UART_CLK_IN_HZ ULL(500000000)
+#define RPI3_MBOX_OFFSET ULL(0x0000B880)
+#define RPI3_MBOX_BASE (RPI3_IO_BASE + RPI3_MBOX_OFFSET)
+/* VideoCore -> ARM */
+#define RPI3_MBOX0_READ_OFFSET ULL(0x00000000)
+#define RPI3_MBOX0_PEEK_OFFSET ULL(0x00000010)
+#define RPI3_MBOX0_SENDER_OFFSET ULL(0x00000014)
+#define RPI3_MBOX0_STATUS_OFFSET ULL(0x00000018)
+#define RPI3_MBOX0_CONFIG_OFFSET ULL(0x0000001C)
+/* ARM -> VideoCore */
+#define RPI3_MBOX1_WRITE_OFFSET ULL(0x00000020)
+#define RPI3_MBOX1_PEEK_OFFSET ULL(0x00000030)
+#define RPI3_MBOX1_SENDER_OFFSET ULL(0x00000034)
+#define RPI3_MBOX1_STATUS_OFFSET ULL(0x00000038)
+#define RPI3_MBOX1_CONFIG_OFFSET ULL(0x0000003C)
+/* Mailbox status constants */
+#define RPI3_MBOX_STATUS_FULL_MASK U(0x80000000) /* Set if full */
+#define RPI3_MBOX_STATUS_EMPTY_MASK U(0x40000000) /* Set if empty */
/*
* Power management, reset controller, watchdog.
@@ -30,11 +44,44 @@
#define RPI3_PM_BASE (RPI3_IO_BASE + RPI3_IO_PM_OFFSET)
/* Registers on top of RPI3_PM_BASE. */
#define RPI3_PM_RSTC_OFFSET ULL(0x0000001C)
+#define RPI3_PM_RSTS_OFFSET ULL(0x00000020)
#define RPI3_PM_WDOG_OFFSET ULL(0x00000024)
/* Watchdog constants */
-#define RPI3_PM_PASSWORD ULL(0x5A000000)
-#define RPI3_PM_RSTC_WRCFG_MASK ULL(0x00000030)
-#define RPI3_PM_RSTC_WRCFG_FULL_RESET ULL(0x00000020)
+#define RPI3_PM_PASSWORD U(0x5A000000)
+#define RPI3_PM_RSTC_WRCFG_MASK U(0x00000030)
+#define RPI3_PM_RSTC_WRCFG_FULL_RESET U(0x00000020)
+/*
+ * The RSTS register is used by the VideoCore firmware when booting the
+ * Raspberry Pi to know which partition to boot from. The partition value is
+ * formed by bits 0, 2, 4, 6, 8 and 10. Partition 63 is used by said firmware
+ * to indicate halt.
+ */
+#define RPI3_PM_RSTS_WRCFG_HALT U(0x00000555)
+
+/*
+ * Hardware random number generator.
+ */
+#define RPI3_IO_RNG_OFFSET ULL(0x00104000)
+#define RPI3_RNG_BASE (RPI3_IO_BASE + RPI3_IO_RNG_OFFSET)
+#define RPI3_RNG_CTRL_OFFSET ULL(0x00000000)
+#define RPI3_RNG_STATUS_OFFSET ULL(0x00000004)
+#define RPI3_RNG_DATA_OFFSET ULL(0x00000008)
+#define RPI3_RNG_INT_MASK_OFFSET ULL(0x00000010)
+/* Enable/disable RNG */
+#define RPI3_RNG_CTRL_ENABLE U(0x1)
+#define RPI3_RNG_CTRL_DISABLE U(0x0)
+/* Number of currently available words */
+#define RPI3_RNG_STATUS_NUM_WORDS_SHIFT U(24)
+#define RPI3_RNG_STATUS_NUM_WORDS_MASK U(0xFF)
+/* Value to mask interrupts caused by the RNG */
+#define RPI3_RNG_INT_MASK_DISABLE U(0x1)
+
+/*
+ * Serial port (called 'Mini UART' in the BCM docucmentation).
+ */
+#define RPI3_IO_MINI_UART_OFFSET ULL(0x00215040)
+#define RPI3_MINI_UART_BASE (RPI3_IO_BASE + RPI3_IO_MINI_UART_OFFSET)
+#define RPI3_MINI_UART_CLK_IN_HZ ULL(500000000)
/*
* Local interrupt controller
diff --git a/plat/rpi3/rpi3_io_storage.c b/plat/rpi3/rpi3_io_storage.c
index e090b2b..cafcf6d 100644
--- a/plat/rpi3/rpi3_io_storage.c
+++ b/plat/rpi3/rpi3_io_storage.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -21,14 +21,14 @@
#define BL33_IMAGE_NAME "bl33.bin"
#if TRUSTED_BOARD_BOOT
-#define BL2_CERT_NAME "bl2.crt"
+#define TRUSTED_BOOT_FW_CERT_NAME "tb_fw.crt"
#define TRUSTED_KEY_CERT_NAME "trusted_key.crt"
-#define BL31_KEY_CERT_NAME "bl31_key.crt"
-#define BL32_KEY_CERT_NAME "bl32_key.crt"
-#define BL33_KEY_CERT_NAME "bl33_key.crt"
-#define BL31_CERT_NAME "bl31.crt"
-#define BL32_CERT_NAME "bl32.crt"
-#define BL33_CERT_NAME "bl33.crt"
+#define SOC_FW_KEY_CERT_NAME "soc_fw_key.crt"
+#define TOS_FW_KEY_CERT_NAME "tos_fw_key.crt"
+#define NT_FW_KEY_CERT_NAME "nt_fw_key.crt"
+#define SOC_FW_CONTENT_CERT_NAME "soc_fw_content.crt"
+#define TOS_FW_CONTENT_CERT_NAME "tos_fw_content.crt"
+#define NT_FW_CONTENT_CERT_NAME "nt_fw_content.crt"
#endif /* TRUSTED_BOARD_BOOT */
/* IO devices */
@@ -67,36 +67,36 @@
};
#if TRUSTED_BOARD_BOOT
-static const io_uuid_spec_t bl2_cert_uuid_spec = {
- .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2_CERT,
+static const io_uuid_spec_t tb_fw_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_BOOT_FW_CERT,
};
static const io_uuid_spec_t trusted_key_cert_uuid_spec = {
.uuid = UUID_TRUSTED_KEY_CERT,
};
-static const io_uuid_spec_t bl31_key_cert_uuid_spec = {
- .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31_KEY_CERT,
+static const io_uuid_spec_t soc_fw_key_cert_uuid_spec = {
+ .uuid = UUID_SOC_FW_KEY_CERT,
};
-static const io_uuid_spec_t bl32_key_cert_uuid_spec = {
- .uuid = UUID_SECURE_PAYLOAD_BL32_KEY_CERT,
+static const io_uuid_spec_t tos_fw_key_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_KEY_CERT,
};
-static const io_uuid_spec_t bl33_key_cert_uuid_spec = {
- .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33_KEY_CERT,
+static const io_uuid_spec_t nt_fw_key_cert_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_KEY_CERT,
};
-static const io_uuid_spec_t bl31_cert_uuid_spec = {
- .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31_CERT,
+static const io_uuid_spec_t soc_fw_cert_uuid_spec = {
+ .uuid = UUID_SOC_FW_CONTENT_CERT,
};
-static const io_uuid_spec_t bl32_cert_uuid_spec = {
- .uuid = UUID_SECURE_PAYLOAD_BL32_CERT,
+static const io_uuid_spec_t tos_fw_cert_uuid_spec = {
+ .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT,
};
-static const io_uuid_spec_t bl33_cert_uuid_spec = {
- .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33_CERT,
+static const io_uuid_spec_t nt_fw_cert_uuid_spec = {
+ .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT,
};
#endif /* TRUSTED_BOARD_BOOT */
@@ -152,9 +152,9 @@
open_fip
},
#if TRUSTED_BOARD_BOOT
- [BL2_CERT_ID] = {
+ [TRUSTED_BOOT_FW_CERT_ID] = {
&fip_dev_handle,
- (uintptr_t)&bl2_cert_uuid_spec,
+ (uintptr_t)&tb_fw_cert_uuid_spec,
open_fip
},
[TRUSTED_KEY_CERT_ID] = {
@@ -162,34 +162,34 @@
(uintptr_t)&trusted_key_cert_uuid_spec,
open_fip
},
- [BL31_KEY_CERT_ID] = {
+ [SOC_FW_KEY_CERT_ID] = {
&fip_dev_handle,
- (uintptr_t)&bl31_key_cert_uuid_spec,
+ (uintptr_t)&soc_fw_key_cert_uuid_spec,
open_fip
},
- [BL32_KEY_CERT_ID] = {
+ [TRUSTED_OS_FW_KEY_CERT_ID] = {
&fip_dev_handle,
- (uintptr_t)&bl32_key_cert_uuid_spec,
+ (uintptr_t)&tos_fw_key_cert_uuid_spec,
open_fip
},
- [BL33_KEY_CERT_ID] = {
+ [NON_TRUSTED_FW_KEY_CERT_ID] = {
&fip_dev_handle,
- (uintptr_t)&bl33_key_cert_uuid_spec,
+ (uintptr_t)&nt_fw_key_cert_uuid_spec,
open_fip
},
- [BL31_CERT_ID] = {
+ [SOC_FW_CONTENT_CERT_ID] = {
&fip_dev_handle,
- (uintptr_t)&bl31_cert_uuid_spec,
+ (uintptr_t)&soc_fw_cert_uuid_spec,
open_fip
},
- [BL32_CERT_ID] = {
+ [TRUSTED_OS_FW_CONTENT_CERT_ID] = {
&fip_dev_handle,
- (uintptr_t)&bl32_cert_uuid_spec,
+ (uintptr_t)&tos_fw_cert_uuid_spec,
open_fip
},
- [BL33_CERT_ID] = {
+ [NON_TRUSTED_FW_CONTENT_CERT_ID] = {
&fip_dev_handle,
- (uintptr_t)&bl33_cert_uuid_spec,
+ (uintptr_t)&nt_fw_cert_uuid_spec,
open_fip
},
#endif /* TRUSTED_BOARD_BOOT */
diff --git a/plat/rpi3/rpi3_mbox.c b/plat/rpi3/rpi3_mbox.c
new file mode 100644
index 0000000..77e17af
--- /dev/null
+++ b/plat/rpi3/rpi3_mbox.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <arch_helpers.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform_def.h>
+
+#include "rpi3_hw.h"
+
+/* This struct must be aligned to 16 bytes */
+typedef struct __packed __aligned(16) rpi3_mbox_request {
+ uint32_t size; /* Buffer size in bytes */
+ uint32_t code; /* Request/response code */
+ uint32_t tags[0];
+} rpi3_mbox_request_t;
+
+#define RPI3_MBOX_BUFFER_SIZE U(256)
+static uint8_t __aligned(16) rpi3_mbox_buffer[RPI3_MBOX_BUFFER_SIZE];
+
+/* Constants to perform a request/check the status of a request. */
+#define RPI3_MBOX_PROCESS_REQUEST U(0x00000000)
+#define RPI3_MBOX_REQUEST_SUCCESSFUL U(0x80000000)
+#define RPI3_MBOX_REQUEST_ERROR U(0x80000001)
+
+/* Command constants */
+#define RPI3_TAG_HARDWARE_GET_BOARD_REVISION U(0x00010002)
+#define RPI3_TAG_END U(0x00000000)
+
+#define RPI3_TAG_REQUEST U(0x00000000)
+#define RPI3_TAG_IS_RESPONSE U(0x80000000) /* Set if response */
+#define RPI3_TAG_RESPONSE_LENGTH_MASK U(0x7FFFFFFF)
+
+#define RPI3_CHANNEL_ARM_TO_VC U(0x8)
+#define RPI3_CHANNEL_MASK U(0xF)
+
+#define RPI3_MAILBOX_MAX_RETRIES U(1000000)
+
+/*******************************************************************************
+ * Helpers to send requests to the VideoCore using the mailboxes.
+ ******************************************************************************/
+static void rpi3_vc_mailbox_request_send(void)
+{
+ uint32_t st, data;
+ uintptr_t resp_addr, addr;
+ unsigned int retries;
+
+ /* This is the location of the request buffer */
+ addr = (uintptr_t) &rpi3_mbox_buffer;
+
+ /* Make sure that the changes are seen by the VideoCore */
+ flush_dcache_range(addr, RPI3_MBOX_BUFFER_SIZE);
+
+ /* Wait until the outbound mailbox is empty */
+ retries = 0U;
+
+ do {
+ st = mmio_read_32(RPI3_MBOX_BASE + RPI3_MBOX1_STATUS_OFFSET);
+
+ retries++;
+ if (retries == RPI3_MAILBOX_MAX_RETRIES) {
+ ERROR("rpi3: mbox: Send request timeout\n");
+ return;
+ }
+
+ } while ((st & RPI3_MBOX_STATUS_EMPTY_MASK) == 0U);
+
+ /* Send base address of this message to start request */
+ mmio_write_32(RPI3_MBOX_BASE + RPI3_MBOX1_WRITE_OFFSET,
+ RPI3_CHANNEL_ARM_TO_VC | (uint32_t) addr);
+
+ /* Wait until the inbound mailbox isn't empty */
+ retries = 0U;
+
+ do {
+ st = mmio_read_32(RPI3_MBOX_BASE + RPI3_MBOX0_STATUS_OFFSET);
+
+ retries++;
+ if (retries == RPI3_MAILBOX_MAX_RETRIES) {
+ ERROR("rpi3: mbox: Receive response timeout\n");
+ return;
+ }
+
+ } while ((st & RPI3_MBOX_STATUS_EMPTY_MASK) != 0U);
+
+ /* Get location and channel */
+ data = mmio_read_32(RPI3_MBOX_BASE + RPI3_MBOX0_READ_OFFSET);
+
+ if ((data & RPI3_CHANNEL_MASK) != RPI3_CHANNEL_ARM_TO_VC) {
+ ERROR("rpi3: mbox: Wrong channel: 0x%08x\n", data);
+ panic();
+ }
+
+ resp_addr = (uintptr_t)(data & ~RPI3_CHANNEL_MASK);
+ if (addr != resp_addr) {
+ ERROR("rpi3: mbox: Unexpected address: 0x%08x\n", data);
+ panic();
+ }
+
+ /* Make sure that the data seen by the CPU is up to date */
+ inv_dcache_range(addr, RPI3_MBOX_BUFFER_SIZE);
+}
+
+/*******************************************************************************
+ * Request board revision. Returns the revision and 0 on success, -1 on error.
+ ******************************************************************************/
+int rpi3_vc_hardware_get_board_revision(uint32_t *revision)
+{
+ uint32_t tag_request_size = sizeof(uint32_t);
+ rpi3_mbox_request_t *req = (rpi3_mbox_request_t *) rpi3_mbox_buffer;
+
+ assert(revision != NULL);
+
+ VERBOSE("rpi3: mbox: Sending request at %p\n", (void *)req);
+
+ req->size = sizeof(rpi3_mbox_buffer);
+ req->code = RPI3_MBOX_PROCESS_REQUEST;
+
+ req->tags[0] = RPI3_TAG_HARDWARE_GET_BOARD_REVISION;
+ req->tags[1] = tag_request_size; /* Space available for the response */
+ req->tags[2] = RPI3_TAG_REQUEST;
+ req->tags[3] = 0; /* Placeholder for the response */
+
+ req->tags[4] = RPI3_TAG_END;
+
+ rpi3_vc_mailbox_request_send();
+
+ if (req->code != RPI3_MBOX_REQUEST_SUCCESSFUL) {
+ ERROR("rpi3: mbox: Code = 0x%08x\n", req->code);
+ return -1;
+ }
+
+ if (req->tags[2] != (RPI3_TAG_IS_RESPONSE | tag_request_size)) {
+ ERROR("rpi3: mbox: get board revision failed (0x%08x)\n",
+ req->tags[2]);
+ return -1;
+ }
+
+ *revision = req->tags[3];
+
+ return 0;
+}
diff --git a/plat/rpi3/rpi3_pm.c b/plat/rpi3/rpi3_pm.c
index 1d067fb..b6adc8a 100644
--- a/plat/rpi3/rpi3_pm.c
+++ b/plat/rpi3/rpi3_pm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -15,11 +15,6 @@
#include "rpi3_hw.h"
-/*
- * The secure entry point to be used on warm reset.
- */
-static uintptr_t secure_entrypoint;
-
/* Make composite power state parameter till power level 0 */
#if PSCI_EXTENDED_STATE_ID
@@ -150,41 +145,61 @@
}
/*******************************************************************************
- * Platform handler to reboot the system
+ * Platform handlers for system reset and system off.
******************************************************************************/
-#define RESET_TIMEOUT 10
-static void __dead2 rpi3_system_reset(void)
+/* 10 ticks (Watchdog timer = Timer clock / 16) */
+#define RESET_TIMEOUT U(10)
+
+static void __dead2 rpi3_watchdog_reset(void)
{
- /* Setup watchdog for reset */
-
- static const uintptr_t base = RPI3_PM_BASE;
uint32_t rstc;
- INFO("rpi3: PSCI System Reset: invoking watchdog reset\n");
-
console_flush();
- rstc = mmio_read_32(base + RPI3_PM_RSTC_OFFSET);
- rstc &= ~RPI3_PM_RSTC_WRCFG_MASK;
- rstc |= RPI3_PM_RSTC_WRCFG_FULL_RESET;
+ dsbsy();
+ isb();
- dmbst();
-
- /*
- * Watchdog timer = Timer clock / 16
- * Password (31:16) | Value (11:0)
- */
- mmio_write_32(base + RPI3_PM_WDOG_OFFSET,
+ mmio_write_32(RPI3_PM_BASE + RPI3_PM_WDOG_OFFSET,
RPI3_PM_PASSWORD | RESET_TIMEOUT);
- mmio_write_32(base + RPI3_PM_RSTC_OFFSET,
- RPI3_PM_PASSWORD | rstc);
+
+ rstc = mmio_read_32(RPI3_PM_BASE + RPI3_PM_RSTC_OFFSET);
+ rstc &= ~RPI3_PM_RSTC_WRCFG_MASK;
+ rstc |= RPI3_PM_PASSWORD | RPI3_PM_RSTC_WRCFG_FULL_RESET;
+ mmio_write_32(RPI3_PM_BASE + RPI3_PM_RSTC_OFFSET, rstc);
for (;;) {
wfi();
}
}
+static void __dead2 rpi3_system_reset(void)
+{
+ INFO("rpi3: PSCI_SYSTEM_RESET: Invoking watchdog reset\n");
+
+ rpi3_watchdog_reset();
+}
+
+static void __dead2 rpi3_system_off(void)
+{
+ uint32_t rsts;
+
+ INFO("rpi3: PSCI_SYSTEM_OFF: Invoking watchdog reset\n");
+
+ /*
+ * This function doesn't actually make the Raspberry Pi turn itself off,
+ * the hardware doesn't allow it. It simply reboots it and the RSTS
+ * value tells the bootcode.bin firmware not to continue the regular
+ * bootflow and to stay in a low power mode.
+ */
+
+ rsts = mmio_read_32(RPI3_PM_BASE + RPI3_PM_RSTS_OFFSET);
+ rsts |= RPI3_PM_PASSWORD | RPI3_PM_RSTS_WRCFG_HALT;
+ mmio_write_32(RPI3_PM_BASE + RPI3_PM_RSTS_OFFSET, rsts);
+
+ rpi3_watchdog_reset();
+}
+
/*******************************************************************************
* Platform handlers and setup function.
******************************************************************************/
@@ -192,6 +207,7 @@
.cpu_standby = rpi3_cpu_standby,
.pwr_domain_on = rpi3_pwr_domain_on,
.pwr_domain_on_finish = rpi3_pwr_domain_on_finish,
+ .system_off = rpi3_system_off,
.system_reset = rpi3_system_reset,
.validate_power_state = rpi3_validate_power_state,
};
@@ -199,10 +215,9 @@
int plat_setup_psci_ops(uintptr_t sec_entrypoint,
const plat_psci_ops_t **psci_ops)
{
- uintptr_t *mailbox = (void *)PLAT_RPI3_TRUSTED_MAILBOX_BASE;
+ uintptr_t *entrypoint = (void *) PLAT_RPI3_TM_ENTRYPOINT;
- *mailbox = sec_entrypoint;
- secure_entrypoint = (uintptr_t)sec_entrypoint;
+ *entrypoint = sec_entrypoint;
*psci_ops = &plat_rpi3_psci_pm_ops;
return 0;
diff --git a/plat/rpi3/rpi3_private.h b/plat/rpi3/rpi3_private.h
index a9fbfe4..91b7add 100644
--- a/plat/rpi3/rpi3_private.h
+++ b/plat/rpi3/rpi3_private.h
@@ -33,4 +33,10 @@
/* IO storage utility functions */
void plat_rpi3_io_setup(void);
+/* Hardware RNG functions */
+void rpi3_rng_read(void *buf, size_t len);
+
+/* VideoCore firmware commands */
+int rpi3_vc_hardware_get_board_revision(uint32_t *revision);
+
#endif /*__RPI3_PRIVATE_H__ */
diff --git a/plat/rpi3/rpi3_rng.c b/plat/rpi3/rpi3_rng.c
new file mode 100644
index 0000000..111b3b6
--- /dev/null
+++ b/plat/rpi3/rpi3_rng.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <mmio.h>
+#include <string.h>
+
+#include "rpi3_hw.h"
+
+/* Initial amount of values to discard */
+#define RNG_WARMUP_COUNT U(0x40000)
+
+static void rpi3_rng_initialize(void)
+{
+ uint32_t int_mask, ctrl;
+
+ /* Return if it is already enabled */
+ ctrl = mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_CTRL_OFFSET);
+ if ((ctrl & RPI3_RNG_CTRL_ENABLE) != 0U) {
+ return;
+ }
+
+ /* Mask interrupts */
+ int_mask = mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_INT_MASK_OFFSET);
+ int_mask |= RPI3_RNG_INT_MASK_DISABLE;
+ mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_INT_MASK_OFFSET, int_mask);
+
+ /* Discard several values when initializing to give it time to warmup */
+ mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_STATUS_OFFSET, RNG_WARMUP_COUNT);
+
+ mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_CTRL_OFFSET,
+ RPI3_RNG_CTRL_ENABLE);
+}
+
+static uint32_t rpi3_rng_get_word(void)
+{
+ size_t nwords;
+
+ do {
+ /* Get number of available words to read */
+ nwords = (mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_STATUS_OFFSET)
+ >> RPI3_RNG_STATUS_NUM_WORDS_SHIFT)
+ & RPI3_RNG_STATUS_NUM_WORDS_MASK;
+ } while (nwords == 0U);
+
+ return mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_DATA_OFFSET);
+}
+
+void rpi3_rng_read(void *buf, size_t len)
+{
+ uint32_t data;
+ size_t left = len;
+ uint32_t *dst = buf;
+
+ assert(buf != NULL);
+ assert(len != 0U);
+ assert(check_uptr_overflow((uintptr_t) buf, (uintptr_t) len) == 0);
+
+ rpi3_rng_initialize();
+
+ while (left >= sizeof(uint32_t)) {
+ data = rpi3_rng_get_word();
+ *dst++ = data;
+ left -= sizeof(uint32_t);
+ }
+
+ if (left > 0U) {
+ data = rpi3_rng_get_word();
+ memcpy(dst, &data, left);
+ }
+}
diff --git a/plat/rpi3/rpi3_rotpk.S b/plat/rpi3/rpi3_rotpk.S
new file mode 100644
index 0000000..1c17b21
--- /dev/null
+++ b/plat/rpi3/rpi3_rotpk.S
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ .global rpi3_rotpk_hash
+ .global rpi3_rotpk_hash_end
+rpi3_rotpk_hash:
+ /* DER header */
+ .byte 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48
+ .byte 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20
+ /* SHA256 */
+ .incbin ROTPK_HASH
+rpi3_rotpk_hash_end:
diff --git a/plat/rpi3/rpi3_stack_protector.c b/plat/rpi3/rpi3_stack_protector.c
new file mode 100644
index 0000000..d939cd3
--- /dev/null
+++ b/plat/rpi3/rpi3_stack_protector.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <sys/types.h>
+#include <utils.h>
+
+#include "rpi3_private.h"
+
+/* Get 128 bits of entropy and fuse the values together to form the canary. */
+#define TRNG_NBYTES 16U
+
+u_register_t plat_get_stack_protector_canary(void)
+{
+ size_t i;
+ u_register_t buf[TRNG_NBYTES / sizeof(u_register_t)];
+ u_register_t ret = 0U;
+
+ rpi3_rng_read(buf, sizeof(buf));
+
+ for (i = 0U; i < ARRAY_SIZE(buf); i++)
+ ret ^= buf[i];
+
+ return ret;
+}
diff --git a/plat/rpi3/rpi3_trusted_boot.c b/plat/rpi3/rpi3_trusted_boot.c
new file mode 100644
index 0000000..2f528fc
--- /dev/null
+++ b/plat/rpi3/rpi3_trusted_boot.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform.h>
+
+extern char rpi3_rotpk_hash[], rpi3_rotpk_hash_end[];
+
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ *key_ptr = rpi3_rotpk_hash;
+ *key_len = rpi3_rotpk_hash_end - rpi3_rotpk_hash;
+ *flags = ROTPK_IS_HASH;
+
+ return 0;
+}
+
+int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
+{
+ *nv_ctr = 0;
+
+ return 0;
+}
+
+int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
+{
+ return 1;
+}
diff --git a/plat/ti/k3/common/k3_psci.c b/plat/ti/k3/common/k3_psci.c
index 91602c8..4d6428b 100644
--- a/plat/ti/k3/common/k3_psci.c
+++ b/plat/ti/k3/common/k3_psci.c
@@ -17,12 +17,18 @@
static void k3_cpu_standby(plat_local_state_t cpu_state)
{
- /*
- * Enter standby state
- * dsb is good practice before using wfi to enter low power states
- */
+ unsigned int scr;
+
+ scr = read_scr_el3();
+ /* Enable the Non secure interrupt to wake the CPU */
+ write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT);
+ isb();
+ /* dsb is good practice before using wfi to enter low power states */
dsb();
+ /* Enter standby state */
wfi();
+ /* Restore SCR */
+ write_scr_el3(scr);
}
static int k3_pwr_domain_on(u_register_t mpidr)
diff --git a/plat/ti/k3/common/k3_topology.c b/plat/ti/k3/common/k3_topology.c
index a77c8f3..d7ac0a5 100644
--- a/plat/ti/k3/common/k3_topology.c
+++ b/plat/ti/k3/common/k3_topology.c
@@ -9,6 +9,7 @@
/* The power domain tree descriptor */
static unsigned char power_domain_tree_desc[] = {
+ PLATFORM_SYSTEM_COUNT,
PLATFORM_CLUSTER_COUNT,
K3_CLUSTER0_CORE_COUNT,
#if K3_CLUSTER1_MSMC_PORT != UNUSED
diff --git a/plat/ti/k3/include/platform_def.h b/plat/ti/k3/include/platform_def.h
index 8856af2..ebc9c47 100644
--- a/plat/ti/k3/include/platform_def.h
+++ b/plat/ti/k3/include/platform_def.h
@@ -62,9 +62,10 @@
#define PLATFORM_CLUSTER_OFFSET K3_CLUSTER0_MSMC_PORT
-#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \
+#define PLAT_NUM_PWR_DOMAINS (PLATFORM_SYSTEM_COUNT + \
+ PLATFORM_CLUSTER_COUNT + \
PLATFORM_CORE_COUNT)
-#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1
+#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2
/*******************************************************************************
* Memory layout constants
diff --git a/services/spd/opteed/opteed_main.c b/services/spd/opteed/opteed_main.c
index 01ec2a2..59d6ed2 100644
--- a/services/spd/opteed/opteed_main.c
+++ b/services/spd/opteed/opteed_main.c
@@ -34,7 +34,7 @@
* Address of the entrypoint vector table in OPTEE. It is
* initialised once on the primary core after a cold boot.
******************************************************************************/
-optee_vectors_t *optee_vector_table;
+struct optee_vectors *optee_vector_table;
/*******************************************************************************
* Array to keep track of per-cpu OPTEE state
diff --git a/services/spd/opteed/opteed_private.h b/services/spd/opteed/opteed_private.h
index b77b6d3..a5f0a41 100644
--- a/services/spd/opteed/opteed_private.h
+++ b/services/spd/opteed/opteed_private.h
@@ -144,7 +144,7 @@
void __dead2 opteed_exit_sp(uint64_t c_rt_ctx, uint64_t ret);
uint64_t opteed_synchronous_sp_entry(optee_context_t *optee_ctx);
void __dead2 opteed_synchronous_sp_exit(optee_context_t *optee_ctx, uint64_t ret);
-void opteed_init_optee_ep_state(struct entry_point_info *optee_ep,
+void opteed_init_optee_ep_state(struct entry_point_info *optee_entry_point,
uint32_t rw,
uint64_t pc,
uint64_t pageable_part,
diff --git a/services/std_svc/sdei/sdei_main.c b/services/std_svc/sdei/sdei_main.c
index d6d092d..28afc1d 100644
--- a/services/std_svc/sdei/sdei_main.c
+++ b/services/std_svc/sdei/sdei_main.c
@@ -932,43 +932,43 @@
case SDEI_VERSION:
SDEI_LOG("> VER\n");
ret = sdei_version();
- SDEI_LOG("< VER:%lx\n", ret);
+ SDEI_LOG("< VER:%llx\n", ret);
SMC_RET1(handle, ret);
case SDEI_EVENT_REGISTER:
x5 = SMC_GET_GP(handle, CTX_GPREG_X5);
- SDEI_LOG("> REG(n:%d e:%lx a:%lx f:%x m:%lx)\n", (int) x1,
+ SDEI_LOG("> REG(n:%d e:%llx a:%llx f:%x m:%llx)\n", (int) x1,
x2, x3, (int) x4, x5);
ret = sdei_event_register(x1, x2, x3, x4, x5);
- SDEI_LOG("< REG:%ld\n", ret);
+ SDEI_LOG("< REG:%lld\n", ret);
SMC_RET1(handle, ret);
case SDEI_EVENT_ENABLE:
SDEI_LOG("> ENABLE(n:%d)\n", (int) x1);
ret = sdei_event_enable(x1);
- SDEI_LOG("< ENABLE:%ld\n", ret);
+ SDEI_LOG("< ENABLE:%lld\n", ret);
SMC_RET1(handle, ret);
case SDEI_EVENT_DISABLE:
SDEI_LOG("> DISABLE(n:%d)\n", (int) x1);
ret = sdei_event_disable(x1);
- SDEI_LOG("< DISABLE:%ld\n", ret);
+ SDEI_LOG("< DISABLE:%lld\n", ret);
SMC_RET1(handle, ret);
case SDEI_EVENT_CONTEXT:
SDEI_LOG("> CTX(p:%d):%lx\n", (int) x1, read_mpidr_el1());
ret = sdei_event_context(handle, x1);
- SDEI_LOG("< CTX:%ld\n", ret);
+ SDEI_LOG("< CTX:%lld\n", ret);
SMC_RET1(handle, ret);
case SDEI_EVENT_COMPLETE_AND_RESUME:
resume = 1;
case SDEI_EVENT_COMPLETE:
- SDEI_LOG("> COMPLETE(r:%d sta/ep:%lx):%lx\n", resume, x1,
+ SDEI_LOG("> COMPLETE(r:%d sta/ep:%llx):%lx\n", resume, x1,
read_mpidr_el1());
ret = sdei_event_complete(resume, x1);
- SDEI_LOG("< COMPLETE:%lx\n", ret);
+ SDEI_LOG("< COMPLETE:%llx\n", ret);
/*
* Set error code only if the call failed. If the call
@@ -985,19 +985,19 @@
case SDEI_EVENT_STATUS:
SDEI_LOG("> STAT(n:%d)\n", (int) x1);
ret = sdei_event_status(x1);
- SDEI_LOG("< STAT:%ld\n", ret);
+ SDEI_LOG("< STAT:%lld\n", ret);
SMC_RET1(handle, ret);
case SDEI_EVENT_GET_INFO:
SDEI_LOG("> INFO(n:%d, %d)\n", (int) x1, (int) x2);
ret = sdei_event_get_info(x1, x2);
- SDEI_LOG("< INFO:%ld\n", ret);
+ SDEI_LOG("< INFO:%lld\n", ret);
SMC_RET1(handle, ret);
case SDEI_EVENT_UNREGISTER:
SDEI_LOG("> UNREG(n:%d)\n", (int) x1);
ret = sdei_event_unregister(x1);
- SDEI_LOG("< UNREG:%ld\n", ret);
+ SDEI_LOG("< UNREG:%lld\n", ret);
SMC_RET1(handle, ret);
case SDEI_PE_UNMASK:
@@ -1009,49 +1009,49 @@
case SDEI_PE_MASK:
SDEI_LOG("> MASK:%lx\n", read_mpidr_el1());
ret = sdei_pe_mask();
- SDEI_LOG("< MASK:%ld\n", ret);
+ SDEI_LOG("< MASK:%lld\n", ret);
SMC_RET1(handle, ret);
case SDEI_INTERRUPT_BIND:
SDEI_LOG("> BIND(%d)\n", (int) x1);
ret = sdei_interrupt_bind(x1);
- SDEI_LOG("< BIND:%ld\n", ret);
+ SDEI_LOG("< BIND:%lld\n", ret);
SMC_RET1(handle, ret);
case SDEI_INTERRUPT_RELEASE:
SDEI_LOG("> REL(%d)\n", (int) x1);
ret = sdei_interrupt_release(x1);
- SDEI_LOG("< REL:%ld\n", ret);
+ SDEI_LOG("< REL:%lld\n", ret);
SMC_RET1(handle, ret);
case SDEI_SHARED_RESET:
SDEI_LOG("> S_RESET():%lx\n", read_mpidr_el1());
ret = sdei_shared_reset();
- SDEI_LOG("< S_RESET:%ld\n", ret);
+ SDEI_LOG("< S_RESET:%lld\n", ret);
SMC_RET1(handle, ret);
case SDEI_PRIVATE_RESET:
SDEI_LOG("> P_RESET():%lx\n", read_mpidr_el1());
ret = sdei_private_reset();
- SDEI_LOG("< P_RESET:%ld\n", ret);
+ SDEI_LOG("< P_RESET:%lld\n", ret);
SMC_RET1(handle, ret);
case SDEI_EVENT_ROUTING_SET:
- SDEI_LOG("> ROUTE_SET(n:%d f:%lx aff:%lx)\n", (int) x1, x2, x3);
+ SDEI_LOG("> ROUTE_SET(n:%d f:%llx aff:%llx)\n", (int) x1, x2, x3);
ret = sdei_event_routing_set(x1, x2, x3);
- SDEI_LOG("< ROUTE_SET:%ld\n", ret);
+ SDEI_LOG("< ROUTE_SET:%lld\n", ret);
SMC_RET1(handle, ret);
case SDEI_FEATURES:
- SDEI_LOG("> FTRS(f:%lx)\n", x1);
+ SDEI_LOG("> FTRS(f:%llx)\n", x1);
ret = sdei_features(x1);
- SDEI_LOG("< FTRS:%lx\n", ret);
+ SDEI_LOG("< FTRS:%llx\n", ret);
SMC_RET1(handle, ret);
case SDEI_EVENT_SIGNAL:
- SDEI_LOG("> SIGNAL(e:%lx t:%lx)\n", x1, x2);
+ SDEI_LOG("> SIGNAL(e:%llx t:%llx)\n", x1, x2);
ret = sdei_signal(x1, x2);
- SDEI_LOG("< SIGNAL:%ld\n", ret);
+ SDEI_LOG("< SIGNAL:%lld\n", ret);
SMC_RET1(handle, ret);
default:
diff --git a/services/std_svc/spm/aarch64/spm_shim_exceptions.S b/services/std_svc/spm/aarch64/spm_shim_exceptions.S
index 218245d..9c218df 100644
--- a/services/std_svc/spm/aarch64/spm_shim_exceptions.S
+++ b/services/std_svc/spm/aarch64/spm_shim_exceptions.S
@@ -23,19 +23,19 @@
*/
vector_entry SynchronousExceptionSP0, .spm_shim_exceptions
b .
- check_vector_size SynchronousExceptionSP0
+end_vector_entry SynchronousExceptionSP0
vector_entry IrqSP0, .spm_shim_exceptions
b .
- check_vector_size IrqSP0
+end_vector_entry IrqSP0
vector_entry FiqSP0, .spm_shim_exceptions
b .
- check_vector_size FiqSP0
+end_vector_entry FiqSP0
vector_entry SErrorSP0, .spm_shim_exceptions
b .
- check_vector_size SErrorSP0
+end_vector_entry SErrorSP0
/* -----------------------------------------------------
* Current EL with SPx: 0x200 - 0x400
@@ -43,19 +43,19 @@
*/
vector_entry SynchronousExceptionSPx, .spm_shim_exceptions
b .
- check_vector_size SynchronousExceptionSPx
+end_vector_entry SynchronousExceptionSPx
vector_entry IrqSPx, .spm_shim_exceptions
b .
- check_vector_size IrqSPx
+end_vector_entry IrqSPx
vector_entry FiqSPx, .spm_shim_exceptions
b .
- check_vector_size FiqSPx
+end_vector_entry FiqSPx
vector_entry SErrorSPx, .spm_shim_exceptions
b .
- check_vector_size SErrorSPx
+end_vector_entry SErrorSPx
/* -----------------------------------------------------
* Lower EL using AArch64 : 0x400 - 0x600. No exceptions
@@ -93,19 +93,19 @@
handle_sys_trap:
panic:
b panic
- check_vector_size SynchronousExceptionA64
+end_vector_entry SynchronousExceptionA64
vector_entry IrqA64, .spm_shim_exceptions
b .
- check_vector_size IrqA64
+end_vector_entry IrqA64
vector_entry FiqA64, .spm_shim_exceptions
b .
- check_vector_size FiqA64
+end_vector_entry FiqA64
vector_entry SErrorA64, .spm_shim_exceptions
b .
- check_vector_size SErrorA64
+end_vector_entry SErrorA64
/* -----------------------------------------------------
* Lower EL using AArch32 : 0x600 - 0x800
@@ -113,16 +113,16 @@
*/
vector_entry SynchronousExceptionA32, .spm_shim_exceptions
b .
- check_vector_size SynchronousExceptionA32
+end_vector_entry SynchronousExceptionA32
vector_entry IrqA32, .spm_shim_exceptions
b .
- check_vector_size IrqA32
+end_vector_entry IrqA32
vector_entry FiqA32, .spm_shim_exceptions
b .
- check_vector_size FiqA32
+end_vector_entry FiqA32
vector_entry SErrorA32, .spm_shim_exceptions
b .
- check_vector_size SErrorA32
+end_vector_entry SErrorA32
diff --git a/services/std_svc/spm/sp_setup.c b/services/std_svc/spm/sp_setup.c
index b9b67f7..0d61306 100644
--- a/services/std_svc/spm/sp_setup.c
+++ b/services/std_svc/spm/sp_setup.c
@@ -107,38 +107,22 @@
* MMU-related registers
* ---------------------
*/
+ xlat_ctx_t *xlat_ctx = sp_ctx->xlat_ctx_handle;
- /* Set attributes in the right indices of the MAIR */
- u_register_t mair_el1 =
- MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX) |
- MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, ATTR_IWBWA_OWBWA_NTR_INDEX) |
- MAIR_ATTR_SET(ATTR_NON_CACHEABLE, ATTR_NON_CACHEABLE_INDEX);
+ uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
- write_ctx_reg(get_sysregs_ctx(ctx), CTX_MAIR_EL1, mair_el1);
+ setup_mmu_cfg((uint64_t *)&mmu_cfg_params, 0, xlat_ctx->base_table,
+ xlat_ctx->pa_max_address, xlat_ctx->va_max_address,
+ EL1_EL0_REGIME);
- /* Setup TCR_EL1. */
- u_register_t tcr_ps_bits = tcr_physical_addr_size_bits(PLAT_PHY_ADDR_SPACE_SIZE);
+ write_ctx_reg(get_sysregs_ctx(ctx), CTX_MAIR_EL1,
+ mmu_cfg_params[MMU_CFG_MAIR]);
- u_register_t tcr_el1 =
- /* Size of region addressed by TTBR0_EL1 = 2^(64-T0SZ) bytes. */
- (64 - __builtin_ctzl(PLAT_VIRT_ADDR_SPACE_SIZE)) |
- /* Inner and outer WBWA, shareable. */
- TCR_SH_INNER_SHAREABLE | TCR_RGN_OUTER_WBA | TCR_RGN_INNER_WBA |
- /* Set the granularity to 4KB. */
- TCR_TG0_4K |
- /* Limit Intermediate Physical Address Size. */
- tcr_ps_bits << TCR_EL1_IPS_SHIFT |
- /* Disable translations using TBBR1_EL1. */
- TCR_EPD1_BIT
- /* The remaining fields related to TBBR1_EL1 are left as zero. */
- ;
+ write_ctx_reg(get_sysregs_ctx(ctx), CTX_TCR_EL1,
+ mmu_cfg_params[MMU_CFG_TCR]);
- tcr_el1 &= ~(
- /* Enable translations using TBBR0_EL1 */
- TCR_EPD0_BIT
- );
-
- write_ctx_reg(get_sysregs_ctx(ctx), CTX_TCR_EL1, tcr_el1);
+ write_ctx_reg(get_sysregs_ctx(ctx), CTX_TTBR0_EL1,
+ mmu_cfg_params[MMU_CFG_TTBR0]);
/* Setup SCTLR_EL1 */
u_register_t sctlr_el1 = read_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1);
@@ -174,13 +158,6 @@
write_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1);
- uint64_t *xlat_base =
- ((xlat_ctx_t *)sp_ctx->xlat_ctx_handle)->base_table;
-
- /* Point TTBR0_EL1 at the tables of the context created for the SP. */
- write_ctx_reg(get_sysregs_ctx(ctx), CTX_TTBR0_EL1,
- (u_register_t)xlat_base);
-
/*
* Setup other system registers
* ----------------------------
diff --git a/tools/cert_create/Makefile b/tools/cert_create/Makefile
index 8a1958f..7b10e3e 100644
--- a/tools/cert_create/Makefile
+++ b/tools/cert_create/Makefile
@@ -75,7 +75,7 @@
@echo " LD $@"
@echo 'const char build_msg[] = "Built : "__TIME__", "__DATE__; \
const char platform_msg[] = "${PLAT_MSG}";' | \
- ${CC} -c ${CFLAGS} -xc - -o src/build_msg.o
+ ${HOSTCC} -c ${CFLAGS} -xc - -o src/build_msg.o
${Q}${HOSTCC} src/build_msg.o ${OBJECTS} ${LIB_DIR} ${LIB} -o $@
%.o: %.c
diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c
index 4abfe6d..ed56620 100644
--- a/tools/cert_create/src/main.c
+++ b/tools/cert_create/src/main.c
@@ -140,8 +140,6 @@
i++;
}
printf("\n");
-
- exit(0);
}
static int get_key_alg(const char *key_alg_str)
@@ -334,7 +332,7 @@
break;
case 'h':
print_help(argv[0], cmd_opt);
- break;
+ exit(0);
case 'k':
save_keys = 1;
break;