1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4  */
5 
6 #ifndef APP_FW_STRUCTURES_H
7 #define APP_FW_STRUCTURES_H
8 
9 #include <utils_def.h>
10 #include <xlat_high_va.h>
11 
12 #define APP_SAVED_GEN_REG_COUNT		U(31)
13 
14 #define APP_XLAT_TABLE_COUNT		U(1)
15 
16 #define APP_TTBR1_EL2_OFFSET		UL(0)
17 #define RMM_TTBR1_EL2_OFFSET		UL(8)
18 #define RMM_VBAR_EL2_OFFSET		UL(16)
19 #define RMM_TPIDR_EL0_OFFSET		UL(24)
20 #define RMM_TPIDRRO_EL0_OFFSET		UL(32)
21 #define PC_OFFSET			UL(40)
22 #define PSTATE_OFFSET			UL(48)
23 #define APP_SAVED_REGS_OFFSET		UL(56)
24 #define SP_EL0_OFFSET			UL(304)
25 
26 #ifndef __ASSEMBLER__
27 
28 /* This structure must always be aligned to page boundary as it is mapped into
29  * the app VA space.
30  */
31 struct app_reg_ctx {
32 	/*
33 	 * Members are defined with macros to make sure that the member offsets
34 	 * that are used by the assembly code are aligned with the structure
35 	 * definition.
36 	 */
37 	SET_MEMBER(uint64_t app_ttbr1_el2, APP_TTBR1_EL2_OFFSET, RMM_TTBR1_EL2_OFFSET);
38 	SET_MEMBER(uint64_t rmm_ttbr1_el2, RMM_TTBR1_EL2_OFFSET, RMM_VBAR_EL2_OFFSET);
39 	SET_MEMBER(uint64_t rmm_vbar_el2, RMM_VBAR_EL2_OFFSET, RMM_TPIDR_EL0_OFFSET);
40 	SET_MEMBER(uint64_t rmm_tpidr_el0, RMM_TPIDR_EL0_OFFSET, RMM_TPIDRRO_EL0_OFFSET);
41 	SET_MEMBER(uint64_t rmm_tpidrro_el0, RMM_TPIDRRO_EL0_OFFSET, PC_OFFSET);
42 	SET_MEMBER(uint64_t pc, PC_OFFSET, PSTATE_OFFSET);
43 	SET_MEMBER(uint64_t pstate, PSTATE_OFFSET, APP_SAVED_REGS_OFFSET);
44 	SET_MEMBER(uint64_t app_regs[APP_SAVED_GEN_REG_COUNT],
45 		APP_SAVED_REGS_OFFSET, SP_EL0_OFFSET);
46 	SET_MEMBER(uint64_t sp_el0, SP_EL0_OFFSET, GRANULE_SIZE);
47 } __aligned(GRANULE_SIZE);
48 COMPILER_ASSERT(sizeof(struct app_reg_ctx) == GRANULE_SIZE);
49 COMPILER_ASSERT(SIZEOF_MEMBER(struct app_reg_ctx, app_regs) ==
50 			(sizeof(unsigned long) * APP_SAVED_GEN_REG_COUNT));
51 /*
52  * NS_TPIDR[RO]_EL0_OFFSET registers are saved/restored with a single stp/ldr
53  * instruction, so they must be close.
54  */
55 COMPILER_ASSERT((RMM_TPIDR_EL0_OFFSET + sizeof(unsigned long)) == RMM_TPIDRRO_EL0_OFFSET);
56 /*
57  * The code entering and exiting from EL0 app assumes that sp_el0 is
58  * right after the `regs` array.
59  */
60 COMPILER_ASSERT(U(offsetof(struct app_reg_ctx, sp_el0)) ==
61 	(U(offsetof(struct app_reg_ctx, app_regs)) +
62 		(APP_SAVED_GEN_REG_COUNT * sizeof(unsigned long))));
63 /* Make sure that the last member in the list is at the desired offset */
64 COMPILER_ASSERT(U(offsetof(struct app_reg_ctx, sp_el0)) == SP_EL0_OFFSET);
65 
66 struct app_data_cfg {
67 	/* Structures for setting up and storing app translation related data */
68 	struct xlat_ctx_cfg app_va_xlat_ctx_cfg;
69 	struct xlat_ctx app_va_xlat_ctx;
70 	struct xlat_ctx_tbls app_va_tbls;
71 	struct xlat_mmu_cfg mmu_config;
72 	struct xlat_llt_info cached_app_llt_info;
73 	uintptr_t app_reg_ctx_pa;
74 
75 	uintptr_t shared_page_pa;
76 	uintptr_t el0_shared_page_va;
77 	void *el2_shared_page; /* Is NULL while the shared page is not mapped */
78 	void *el2_heap_start; /* The start VA in the EL2 VA space of the app heap area */
79 	uintptr_t heap_va; /* this VA address is valid in the EL0 VA space */
80 	uintptr_t heap_size;
81 	uintptr_t stack_buf_start_va;
82 	uintptr_t stack_top; /* Initial value of the stack pointer */
83 
84 	/* App entry point VA */
85 	uintptr_t entry_point;
86 
87 	bool app_entered;
88 	uint32_t exit_flag; /* App Exit Flag */
89 };
90 COMPILER_ASSERT((XLAT_TABLE_ENTRIES * APP_XLAT_TABLE_COUNT) <= GRANULE_SIZE);
91 
92 #endif /* __ASSEMBLER__ */
93 #endif /* APP_FW_STRUCTURES_H */
94