source: mainline/kernel/arch/arm64/src/start.S@ 6de65f3

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 6de65f3 was 84176f3, checked in by Jakub Jermář <jakub@…>, 6 years ago

arm64: Add support for the architecture

This changeset adds basic support to run HelenOS on AArch64, targeting
the QEMU virt platform.

Boot:

  • Boot relies on the EDK II firmware, GRUB2 for EFI and the HelenOS bootloader (UEFI application). EDK II loads GRUB2 from a CD, GRUB2 loads the HelenOS bootloader (via UEFI) which loads OS components.
  • UEFI applications use the PE/COFF format and must be relocatable. The first problem is solved by manually having the PE/COFF headers and tables written in assembler. The relocatable requirement is addressed by compiling the code with -fpic and having the bootloader relocate itself at its startup.

Kernel:

  • Kernel code for AArch64 consists mostly of stubbing out various architecture-specific hooks: virtual memory management, interrupt and exception handling, context switching (including FPU lazy switching), support for virtual timer, atomic sequences and barriers, cache and TLB maintenance, thread and process initialization.
  • The patch adds a kernel driver for GICv2 (interrupt controller).
  • The PL011 kernel driver is extended to allow userspace to take ownership of the console.
  • The current code is not able to dynamically obtain information about available devices on the underlying machine. The port instead implements a machine-func interface similar to the one implemented by arm32. It defines a machine for the QEMU AArch64 virt platform. The configuration (device addresses and IRQ numbers) is then baked into the machine definition.

User space:

  • Uspace code for AArch64 similarly mostly implements architecture-specific hooks: context saving/restoring, syscall support, TLS support.

The patchset allows to boot the system but user interaction with the OS
is not yet possible.

  • Property mode set to 100644
File size: 9.6 KB
Line 
1/*
2 * Copyright (c) 2015 Petr Pavlu
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <abi/asmtool.h>
30#include <arch/boot/boot.h>
31#include <arch/mm/km.h>
32#include <arch/mm/page.h>
33#include <arch/regutils.h>
34
35.section K_TEXT_START, "ax"
36
37SYMBOL(kernel_image_start)
38 /*
39 * Parameters:
40 * x0 is kernel entry point (kernel_image_start).
41 * x1 is pointer to the bootinfo structure.
42 *
43 * MMU must be disabled at this point.
44 */
45
46 /* Get address of the main memory and remember it. */
47 adrp x20, kernel_image_start - BOOT_OFFSET
48 adrp x2, physmem_base
49 /* add x2, x2, #:lo12:physmem_base */
50 str x20, [x2]
51
52 /*
53 * Set up address translation that identity maps the gigabyte area that
54 * is holding the current execution page.
55 */
56
57 /* Prepare the level 0 page table. */
58 adrp x2, lower_page_table_level0
59 lsr x3, x20, #PTL0_VA_SHIFT
60 and x3, x3, #PTL0_VA_MASK
61 add x2, x2, x3, lsl #PTL_ENTRY_SIZE_SHIFT
62 mov x3, #( \
63 1 << PTE_ACCESS_SHIFT | \
64 PTE_L012_TYPE_TABLE << PTE_TYPE_SHIFT | \
65 1 << PTE_PRESENT_SHIFT)
66 adrp x4, lower_page_table_level1
67 lsr x4, x4, #FRAME_WIDTH
68 orr x3, x3, x4, lsl #PTE_NEXT_LEVEL_ADDRESS_SHIFT
69 str x3, [x2]
70
71 /* Prepare the level 1 page table. */
72 adrp x2, lower_page_table_level1
73 lsr x3, x20, #PTL1_VA_SHIFT
74 and x3, x3, #PTL1_VA_MASK
75 add x2, x2, x3, lsl #PTL_ENTRY_SIZE_SHIFT
76 mov x3, #( \
77 1 << PTE_ACCESS_SHIFT | \
78 MAIR_EL1_DEVICE_MEMORY_INDEX << PTE_ATTR_INDEX_SHIFT | \
79 PTE_L012_TYPE_BLOCK << PTE_TYPE_SHIFT | \
80 1 << PTE_PRESENT_SHIFT)
81 lsr x4, x20, #FRAME_WIDTH
82 orr x3, x3, x4, lsl #PTE_OUTPUT_ADDRESS_SHIFT
83 str x3, [x2]
84
85 /*
86 * Set up address translation that maps the first gigabyte of the kernel
87 * identity virtual address space to the first gigabyte of the physical
88 * memory.
89 */
90
91 mov x21, #KM_ARM64_IDENTITY_START
92
93 /* Prepare the level 0 page table. */
94 adrp x2, upper_page_table_level0
95 lsr x3, x21, #PTL0_VA_SHIFT
96 and x3, x3, #PTL0_VA_MASK
97 add x2, x2, x3, lsl #PTL_ENTRY_SIZE_SHIFT
98 mov x3, #( \
99 1 << PTE_ACCESS_SHIFT | \
100 PTE_L012_TYPE_TABLE << PTE_TYPE_SHIFT | \
101 1 << PTE_PRESENT_SHIFT)
102 adrp x4, upper_page_table_level1
103 lsr x4, x4, #FRAME_WIDTH
104 orr x3, x3, x4, lsl #PTE_NEXT_LEVEL_ADDRESS_SHIFT
105 str x3, [x2]
106
107 /* Prepare the level 1 page table. */
108 adrp x2, upper_page_table_level1
109 lsr x3, x21, #PTL1_VA_SHIFT
110 and x3, x3, #PTL1_VA_MASK
111 add x2, x2, x3, lsl #PTL_ENTRY_SIZE_SHIFT
112 mov x3, #( \
113 1 << PTE_ACCESS_SHIFT | \
114 MAIR_EL1_DEVICE_MEMORY_INDEX << PTE_ATTR_INDEX_SHIFT | \
115 PTE_L012_TYPE_BLOCK << PTE_TYPE_SHIFT | \
116 1 << PTE_PRESENT_SHIFT)
117 lsr x4, x20, #FRAME_WIDTH
118 orr x3, x3, x4, lsl #PTE_OUTPUT_ADDRESS_SHIFT
119 str x3, [x2]
120
121 /* Make sure there are not any stale TLB entries. */
122 tlbi vmalle1is
123 dsb ish
124
125 /*
126 * Set TCR_EL1:
127 * [63:39] - Reserved 0.
128 * [38] - TBI1=0, top byte of an address is used in the address
129 * calculation for the TTBR1_EL1 region.
130 * [37] - TBI0=0, top byte of an address is used in the address
131 * calculation for the TTBR0_EL1 region.
132 * [36] - AS=1, the upper 16 bits of TTBR0_EL1 and TTBR1_EL1 are used
133 * for allocation and matching in the TLB.
134 * [35] - Reserved 0.
135 * [34:32] - IPS=101, intermediate physical address size is 48 bits,
136 * 256TB.
137 * [31:30] - TG1=10, TTBR1_EL1 granule size is 4KB.
138 * [29:28] - SH1=11, memory associated with translation table walks
139 * using TTBR1_EL1 is inner shareable.
140 * [27:26] - ORGN1=01, memory associated with translation table walks
141 * using TTBR1_EL1 is normal memory, outer write-through
142 * cacheable.
143 * [25:24] - IRGN1=01, memory associated with translation table walks
144 * using TTBR1_EL1 is normal memory, inner write-back
145 * write-allocate cacheable.
146 * [23] - EPD1=0, perform translation table walks using TTBR1_EL1.
147 * [22] - A1=0, TTBR0_EL1.ASID defines the ASID.
148 * [21:16] - T1SZ=010000, size of the memory region addressed by
149 * TTBR1_EL1 is 2^(64 - 16) bytes.
150 * [15:14] - TG0=00, TTBR0_EL1 granule size is 4KB.
151 * [13:12] - SH0=11, memory associated with translation table walks
152 * using TTBR0_EL1 is inner shareable.
153 * [11:10] - ORGN0=01, memory associated with translation table walks
154 * using TTBR0_EL1 is normal memory, outer write-through
155 * cacheable.
156 * [9:8] - IRGN0=01, memory associated with translation table walks
157 * using TTBR0_EL1 is normal memory, inner write-back
158 * write-allocate cacheable.
159 * [7] - EPD0=0, perform translation table walks using TTBR0.
160 * [6] - Reserved 0.
161 * [5:0] - T0SZ=010000, size of the memory region addressed by
162 * TTBR0_EL1 is 2^(64 - 16) bytes.
163 */
164 ldr x2, =0x00000015b5103510
165 msr tcr_el1, x2
166
167 /* Initialize memory attributes. */
168 ldr x2, =(MAIR_EL1_DEVICE_MEMORY_ATTR << \
169 (MAIR_EL1_DEVICE_MEMORY_INDEX * MAIR_EL1_ATTR_SHIFT) | \
170 MAIR_EL1_NORMAL_MEMORY_ATTR << \
171 (MAIR_EL1_NORMAL_MEMORY_INDEX * MAIR_EL1_ATTR_SHIFT))
172 msr mair_el1, x2
173
174 /* Set translation tables. */
175 adrp x2, lower_page_table_level0
176 msr ttbr0_el1, x2
177 adrp x2, upper_page_table_level0
178 msr ttbr1_el1, x2
179 isb
180
181 /*
182 * Set SCTLR_EL1:
183 * [31:30] - Reserved 0.
184 * [29:28] - Reserved 1.
185 * [27] - Reserved 0.
186 * [26] - UCI=0, any attempt to execute cache maintenance
187 * instructions at EL0 is trapped to EL1.
188 * [25] - EE=0, explicit data accesses at EL1, and stage 1
189 * translation table walks in the EL1&0 translation regime are
190 * little-endian.
191 * [24] - E0E=0, explicit data accesses at EL1 are little-endian.
192 * [23:22] - Reserved 1.
193 * [21] - Reserved 0.
194 * [20] - Reserved 1.
195 * [19] - WXN=0, regions with write permission are not forced to
196 * Execute Never.
197 * [18] - nTWE=0, any attempt to execute WFE at EL0 is trapped to
198 * EL1.
199 * [17] - Reserved 0.
200 * [16] - nTWI=0, any attempt to execute WFI at EL0 is trapped to
201 * EL1.
202 * [15] - UCT=0, accesses to CTR_EL0 from EL0 are trapped to EL1.
203 * [14] - DZE=0, any attempt to execute DC ZVA at EL0 is trapped to
204 * EL1.
205 * [13] - Reserved 0.
206 * [12] - I=1, this control has no effect on the cacheability of
207 * instruction access to normal memory.
208 * [11] - Reserved 1.
209 * [10] - Reserved 0.
210 * [9] - UMA=0, any attempt to execute MSR/MRS that accesses DAIF at
211 * EL0 is trapped to EL1.
212 * [8] - SED=1, SETEND is undefined at EL0 using AArch32.
213 * [7] - ITD=1, disables some uses of IT at EL0 using AArch32.
214 * [6] - Reserved 0.
215 * [5] - CP15BEN=0, CP15DMB/DSB/ISB is undefined at EL0 using
216 * AArch32.
217 * [4] - SA0=1, use of stack pointer with load/store at EL0 must be
218 * aligned to a 16-byte boundary.
219 * [3] - SA=1, use of stack pointer with load/store at EL1 must be
220 * aligned to a 16-byte boundary.
221 * [2] - C=1, this control has no effect on the cacheability of data
222 * access to normal memory from EL0 and EL1, and normal memory
223 * accesses to the EL1&0 stage 1 translation tables.
224 * [1] - A=0, instructions that load/store registers (other than
225 * load/store exclusive and load-acquire/store-release) do not
226 * check that the address being accessed is aligned to the
227 * size of the data element(s) being accessed.
228 * [0] - M=1, EL1 and EL0 stage 1 address translation enabled.
229 */
230 ldr w2, =0x30d0199d
231 msr sctlr_el1, x2
232 isb
233
234 /*
235 * MMU is enabled at this point (SCTLR_EL1.M=1), switch to the kernel
236 * mapping.
237 */
238 ldr x2, =1f
239 br x2
2401:
241
242 /* Disable access to low addresses. */
243 mov x2, #0
244 msr ttbr0_el1, x2
245 isb
246 tlbi vmalle1is
247 dsb ish
248
249 /* Jump on a temporary stack. */
250 ldr x2, =temp_stack
251 mov sp, x2
252
253 /* Create the first stack frame. */
254 mov x29, #0
255 mov x30, #0
256 stp x29, x30, [sp, #-16]!
257 mov x29, sp
258
259 /* PA2KA(bootinfo). */
260 sub x1, x1, x20
261 ldr x2, =KM_ARM64_IDENTITY_START
262 add x1, x1, x2
263
264 bl arm64_pre_main
265 bl main_bsp
266
267.section K_DATA_START, "ax"
268
269 /* Page tables. */
270.align 12
271lower_page_table_level0:
272 .space 4096
273lower_page_table_level1:
274 .space 4096
275upper_page_table_level0:
276 .space 4096
277upper_page_table_level1:
278 .space 4096
279
280 /* Physical memory base address. */
281.align 12
282SYMBOL(physmem_base)
283 .quad 0
284
285 /* Temporary stack. */
286.align 10
287 .space 1024
288temp_stack:
Note: See TracBrowser for help on using the repository browser.