aboutsummaryrefslogtreecommitdiff
path: root/el3/arm/el3_init.S
blob: 97762ec93ee9160e75ab220d26473b782c95e1a7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
#define __ASSEMBLY__
#include "memory.h"
#include "register.h"
#include "vmsa.h"
#include "platform.h"
#undef __ASSEMBLY__

.arch_extension sec

#define INIT_STACK EL3_INIT_STACK

.section .init
monitor_init:
    cps #CPSR_M_MON

init_uart:
	/* UART initialisation (38400 8N1) */
	ldr	r0,	=UART0_BASE     // UART base (Versatile Express)
	mov	r1, #0x10			// ibrd
	str	r1, [r0, #0x24]
	mov	r1, #0xc300
	orr	r1, #0x0001			// cr
	str	r1, [r0, #0x30]

    /* Disable interrupts for now */
    mrs r10, cpsr
    orr r10, r10, #0xc0     /* Mask IRQ and FIQ */
    msr cpsr, r10

    /* Set-up the monitor vbar
     * During startup, before the MMU is enabled we'll set-up the vecs in low
     * mem.
     */
    ldr r10, =el3_vectors
    mcr p15, 0, r10, c12, c0, 1         /* MVBAR */

    /* The stack still needs to be allocated and mapped so we set up a
     * temporary stack for the time being.
     */
    ldr r10, =INIT_STACK
	mov sp, r10

    /* Use the top of the stack to track our PA pool pointer */
    ldr r11, =EL3_PA_POOL_BASE
    ldr r10, =EL3_PTE_POOL_BASE
    push {r10, r11}

monitor_mmu_init:
    /* Disable data and instruction caches */
    mrc p15, 0, r10, c1, c0, 0
    bic r10, r10, #0x0004
    bic r10, r10, #0x1000
    bic r10, r10, #0x20000000   /* Enable the simplified access model AFE=1 */
    mcr p15, 0, r10, c1, c0, 0

    /* Set domain 0 & 1 for client access */
    mov r10, #0x5
    mcr p15, 0, r10, c3, c0, 0

    /* Set TTBR0 to the initialized address plus enable shareable write-back
     * write-allocate.
     */
    ldr r10, =EL3_PGTBL_BASE
    orr r10, r10, #0xB
    mcr p15, 0, r10, c2, c0, 0

    /* Set-up the table base control to split between TTBR0/1 (N = 0) */
    mov r10, #0x0
    mcr p15, 0, r10, c2, c0, 2

    /* Clear the page table pages */
    ldr r10, =EL3_PGTBL_BASE
    ldr r11, =EL3_PGTBL_SIZE
    mov r0, #0
monitor_pt_clear:
    cmp r11, #0
    beq monitor_map_init
    str r0, [r10], #4
    sub r11, r11, #4
    b monitor_pt_clear

monitor_map_init:
    /* Direct map the init code */
    ldr r0, =_EL3_INIT_BASE
    movw r1, #PTE_PRIV_RO
    ldr r2, =_EL3_INIT_SIZE
    bl map_pa_range

monitor_map_flash:
    /* Direct map the EL3 flash sections so we can copy from them once
     * the MMU has been enabled.
     */
    ldr r0, =_EL3_FLASH_TEXT
    mov r1, #PTE_PRIV_RO
    ldr r2, =_EL3_TEXT_SIZE
    bl map_pa_range

    ldr r0, =_EL3_FLASH_DATA
    mov r1, #PTE_PRIV_RO
    ldr r2, =_EL3_DATA_SIZE
    bl map_pa_range

monitor_map_text:
    /* Map the EL3 text address range.  Initially this needs to be RW so we can
     * copy in the text from flash.
     */
    ldr r0, =_EL3_TEXT_BASE
    mov r1, #PTE_PRIV_RW
    ldr r2, =_EL3_TEXT_SIZE
    bl map_va_range

monitor_map_data:
    /* Map the EL3 data address range. */
    ldr r0, =_EL3_DATA_BASE
    mov r1, #PTE_PRIV_RW
    ldr r2, =_EL3_DATA_SIZE
    bl map_va_range

monitor_map_stack:
    /* Map the first page of the stack so we can get off the ground */
    ldr r0, =0x7FFEF000   // EL3_STACK_BASE-0x1000
    mov r1, #PTE_PRIV_RW
    bl map_va

/* Map the PT page pool so we can access the PT after the MMU is enabled.
 * We only allcoate EL3_PGTBL_SIZE pages for PT use which consists of the
 * 2^(2-N) TTBR pages and the rest are PT page pool
 */
monitor_map_pt:
    /* Direct map the page table pool */
    ldr r0, =EL3_PGTBL_BASE
    mov r1, #PTE_PRIV_RW
    ldr r2, =0x4000
    bl map_pa_range

    ldr r0, =EL3_PTE_POOL_BASE
    mov r1, #PTE_PRIV_RW
    ldr r2, =0x3C000
    bl map_pa_range

monitor_map_uart:
    ldr r0, =UART0_BASE
    mov r1, #PTE_USER_RW
    bl map_pa

monitor_map_sysreg:
    ldr r0, =SYSREG_BASE;
    mov r1, #PTE_PRIV_RW
    bl map_pa

/* We need to map the first page of secure EL1 as we will be doing an exception
 * return to it in order to initialize it.  We only map the first page as this
 * is enough to get it off the ground.
 */
monitor_map_el1:
    /* Direct map the init code */
    ldr r0, =EL1_S_FLASH_BASE
    mov r1, #PTE_PRIV_RO
    bl map_pa

save_last_pa:
    pop {r8, r9}

monitor_mmu_enable:
    /* Enable the mmu */
    mcr p15, 0, r10, c8, c7, 0
    mrc p15, 0, r10, c1, c0, 0
    orr r10, r10, #0x1
    mcr p15, 0, r10, c1, c0, 0
    isb
    dsb

monitor_init_stack:
    /* Set-up the monitor SVC stack */
	ldr sp, =EL3_STACK_BASE

    /* Migrate the next PA to the new stack we should not use it again until
     * after we transition to start.
     */
    push {r8, r9}

/* The EL3 address space is set-up and the MMU is started so it is safe to copy
 * the text and data sections in.
 */
monitor_copy_text:
    ldr r0, =_EL3_TEXT_BASE
    ldr r1, =_EL3_FLASH_TEXT
    ldr r2, =_EL3_TEXT_SIZE
    bl memcpy

monitor_copy_data:
    ldr r0, =_EL3_DATA_BASE
    ldr r1, =_EL3_FLASH_DATA
    ldr r2, =_EL3_DATA_SIZE
    bl memcpy

monitor_init_start:
    pop {r8, r9}
    ldr r10, =mem_next_pa
    str r9, [r10]
    ldr r10, =mem_next_l1_page
    str r8, [r10]

    ldr r0, =_EL3_INIT_BASE
    ldr r1, =_EL3_INIT_SIZE
    ldr r2, =el3_start
    blx r2

/* We should never get here */
monitor_init_end:
    b monitor_init_end

#include "init_util.S"