]> Git Repo - linux.git/blob - arch/riscv/kernel/head.S
enetc: Migrate to PHYLINK and PCS_LYNX
[linux.git] / arch / riscv / kernel / head.S
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (C) 2012 Regents of the University of California
4  */
5
6 #include <asm/thread_info.h>
7 #include <asm/asm-offsets.h>
8 #include <asm/asm.h>
9 #include <linux/init.h>
10 #include <linux/linkage.h>
11 #include <asm/thread_info.h>
12 #include <asm/page.h>
13 #include <asm/csr.h>
14 #include <asm/hwcap.h>
15 #include <asm/image.h>
16
17 __HEAD
18 ENTRY(_start)
19         /*
20          * Image header expected by Linux boot-loaders. The image header data
21          * structure is described in asm/image.h.
22          * Do not modify it without modifying the structure and all bootloaders
23          * that expects this header format!!
24          */
25         /* jump to start kernel */
26         j _start_kernel
27         /* reserved */
28         .word 0
29         .balign 8
30 #if __riscv_xlen == 64
31         /* Image load offset(2MB) from start of RAM */
32         .dword 0x200000
33 #else
34         /* Image load offset(4MB) from start of RAM */
35         .dword 0x400000
36 #endif
37         /* Effective size of kernel image */
38         .dword _end - _start
39         .dword __HEAD_FLAGS
40         .word RISCV_HEADER_VERSION
41         .word 0
42         .dword 0
43         .ascii RISCV_IMAGE_MAGIC
44         .balign 4
45         .ascii RISCV_IMAGE_MAGIC2
46         .word 0
47
48 .align 2
49 #ifdef CONFIG_MMU
50 relocate:
51         /* Relocate return address */
52         li a1, PAGE_OFFSET
53         la a2, _start
54         sub a1, a1, a2
55         add ra, ra, a1
56
57         /* Point stvec to virtual address of intruction after satp write */
58         la a2, 1f
59         add a2, a2, a1
60         csrw CSR_TVEC, a2
61
62         /* Compute satp for kernel page tables, but don't load it yet */
63         srl a2, a0, PAGE_SHIFT
64         li a1, SATP_MODE
65         or a2, a2, a1
66
67         /*
68          * Load trampoline page directory, which will cause us to trap to
69          * stvec if VA != PA, or simply fall through if VA == PA.  We need a
70          * full fence here because setup_vm() just wrote these PTEs and we need
71          * to ensure the new translations are in use.
72          */
73         la a0, trampoline_pg_dir
74         srl a0, a0, PAGE_SHIFT
75         or a0, a0, a1
76         sfence.vma
77         csrw CSR_SATP, a0
78 .align 2
79 1:
80         /* Set trap vector to spin forever to help debug */
81         la a0, .Lsecondary_park
82         csrw CSR_TVEC, a0
83
84         /* Reload the global pointer */
85 .option push
86 .option norelax
87         la gp, __global_pointer$
88 .option pop
89
90         /*
91          * Switch to kernel page tables.  A full fence is necessary in order to
92          * avoid using the trampoline translations, which are only correct for
93          * the first superpage.  Fetching the fence is guarnteed to work
94          * because that first superpage is translated the same way.
95          */
96         csrw CSR_SATP, a2
97         sfence.vma
98
99         ret
100 #endif /* CONFIG_MMU */
101 #ifdef CONFIG_SMP
102         .global secondary_start_sbi
103 secondary_start_sbi:
104         /* Mask all interrupts */
105         csrw CSR_IE, zero
106         csrw CSR_IP, zero
107
108         /* Load the global pointer */
109         .option push
110         .option norelax
111                 la gp, __global_pointer$
112         .option pop
113
114         /*
115          * Disable FPU to detect illegal usage of
116          * floating point in kernel space
117          */
118         li t0, SR_FS
119         csrc CSR_STATUS, t0
120
121         /* Set trap vector to spin forever to help debug */
122         la a3, .Lsecondary_park
123         csrw CSR_TVEC, a3
124
125         slli a3, a0, LGREG
126         la a4, __cpu_up_stack_pointer
127         la a5, __cpu_up_task_pointer
128         add a4, a3, a4
129         add a5, a3, a5
130         REG_L sp, (a4)
131         REG_L tp, (a5)
132
133         .global secondary_start_common
134 secondary_start_common:
135
136 #ifdef CONFIG_MMU
137         /* Enable virtual memory and relocate to virtual address */
138         la a0, swapper_pg_dir
139         call relocate
140 #endif
141         call setup_trap_vector
142         tail smp_callin
143 #endif /* CONFIG_SMP */
144
145 .align 2
146 setup_trap_vector:
147         /* Set trap vector to exception handler */
148         la a0, handle_exception
149         csrw CSR_TVEC, a0
150
151         /*
152          * Set sup0 scratch register to 0, indicating to exception vector that
153          * we are presently executing in kernel.
154          */
155         csrw CSR_SCRATCH, zero
156         ret
157
158 .Lsecondary_park:
159         /* We lack SMP support or have too many harts, so park this hart */
160         wfi
161         j .Lsecondary_park
162
163 END(_start)
164
165         __INIT
166 ENTRY(_start_kernel)
167         /* Mask all interrupts */
168         csrw CSR_IE, zero
169         csrw CSR_IP, zero
170
171 #ifdef CONFIG_RISCV_M_MODE
172         /* flush the instruction cache */
173         fence.i
174
175         /* Reset all registers except ra, a0, a1 */
176         call reset_regs
177
178         /*
179          * Setup a PMP to permit access to all of memory.  Some machines may
180          * not implement PMPs, so we set up a quick trap handler to just skip
181          * touching the PMPs on any trap.
182          */
183         la a0, pmp_done
184         csrw CSR_TVEC, a0
185
186         li a0, -1
187         csrw CSR_PMPADDR0, a0
188         li a0, (PMP_A_NAPOT | PMP_R | PMP_W | PMP_X)
189         csrw CSR_PMPCFG0, a0
190 .align 2
191 pmp_done:
192
193         /*
194          * The hartid in a0 is expected later on, and we have no firmware
195          * to hand it to us.
196          */
197         csrr a0, CSR_MHARTID
198 #endif /* CONFIG_RISCV_M_MODE */
199
200         /* Load the global pointer */
201 .option push
202 .option norelax
203         la gp, __global_pointer$
204 .option pop
205
206         /*
207          * Disable FPU to detect illegal usage of
208          * floating point in kernel space
209          */
210         li t0, SR_FS
211         csrc CSR_STATUS, t0
212
213 #ifdef CONFIG_SMP
214         li t0, CONFIG_NR_CPUS
215         blt a0, t0, .Lgood_cores
216         tail .Lsecondary_park
217 .Lgood_cores:
218 #endif
219
220         /* Pick one hart to run the main boot sequence */
221         la a3, hart_lottery
222         li a2, 1
223         amoadd.w a3, a2, (a3)
224         bnez a3, .Lsecondary_start
225
226         /* Clear BSS for flat non-ELF images */
227         la a3, __bss_start
228         la a4, __bss_stop
229         ble a4, a3, clear_bss_done
230 clear_bss:
231         REG_S zero, (a3)
232         add a3, a3, RISCV_SZPTR
233         blt a3, a4, clear_bss
234 clear_bss_done:
235
236         /* Save hart ID and DTB physical address */
237         mv s0, a0
238         mv s1, a1
239         la a2, boot_cpu_hartid
240         REG_S a0, (a2)
241
242         /* Initialize page tables and relocate to virtual addresses */
243         la sp, init_thread_union + THREAD_SIZE
244         mv a0, s1
245         call setup_vm
246 #ifdef CONFIG_MMU
247         la a0, early_pg_dir
248         call relocate
249 #endif /* CONFIG_MMU */
250
251         call setup_trap_vector
252         /* Restore C environment */
253         la tp, init_task
254         sw zero, TASK_TI_CPU(tp)
255         la sp, init_thread_union + THREAD_SIZE
256
257 #ifdef CONFIG_KASAN
258         call kasan_early_init
259 #endif
260         /* Start the kernel */
261         call soc_early_init
262         call parse_dtb
263         tail start_kernel
264
265 .Lsecondary_start:
266 #ifdef CONFIG_SMP
267         /* Set trap vector to spin forever to help debug */
268         la a3, .Lsecondary_park
269         csrw CSR_TVEC, a3
270
271         slli a3, a0, LGREG
272         la a1, __cpu_up_stack_pointer
273         la a2, __cpu_up_task_pointer
274         add a1, a3, a1
275         add a2, a3, a2
276
277         /*
278          * This hart didn't win the lottery, so we wait for the winning hart to
279          * get far enough along the boot process that it should continue.
280          */
281 .Lwait_for_cpu_up:
282         /* FIXME: We should WFI to save some energy here. */
283         REG_L sp, (a1)
284         REG_L tp, (a2)
285         beqz sp, .Lwait_for_cpu_up
286         beqz tp, .Lwait_for_cpu_up
287         fence
288
289         tail secondary_start_common
290 #endif
291
292 END(_start_kernel)
293
294 #ifdef CONFIG_RISCV_M_MODE
295 ENTRY(reset_regs)
296         li      sp, 0
297         li      gp, 0
298         li      tp, 0
299         li      t0, 0
300         li      t1, 0
301         li      t2, 0
302         li      s0, 0
303         li      s1, 0
304         li      a2, 0
305         li      a3, 0
306         li      a4, 0
307         li      a5, 0
308         li      a6, 0
309         li      a7, 0
310         li      s2, 0
311         li      s3, 0
312         li      s4, 0
313         li      s5, 0
314         li      s6, 0
315         li      s7, 0
316         li      s8, 0
317         li      s9, 0
318         li      s10, 0
319         li      s11, 0
320         li      t3, 0
321         li      t4, 0
322         li      t5, 0
323         li      t6, 0
324         csrw    CSR_SCRATCH, 0
325
326 #ifdef CONFIG_FPU
327         csrr    t0, CSR_MISA
328         andi    t0, t0, (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D)
329         beqz    t0, .Lreset_regs_done
330
331         li      t1, SR_FS
332         csrs    CSR_STATUS, t1
333         fmv.s.x f0, zero
334         fmv.s.x f1, zero
335         fmv.s.x f2, zero
336         fmv.s.x f3, zero
337         fmv.s.x f4, zero
338         fmv.s.x f5, zero
339         fmv.s.x f6, zero
340         fmv.s.x f7, zero
341         fmv.s.x f8, zero
342         fmv.s.x f9, zero
343         fmv.s.x f10, zero
344         fmv.s.x f11, zero
345         fmv.s.x f12, zero
346         fmv.s.x f13, zero
347         fmv.s.x f14, zero
348         fmv.s.x f15, zero
349         fmv.s.x f16, zero
350         fmv.s.x f17, zero
351         fmv.s.x f18, zero
352         fmv.s.x f19, zero
353         fmv.s.x f20, zero
354         fmv.s.x f21, zero
355         fmv.s.x f22, zero
356         fmv.s.x f23, zero
357         fmv.s.x f24, zero
358         fmv.s.x f25, zero
359         fmv.s.x f26, zero
360         fmv.s.x f27, zero
361         fmv.s.x f28, zero
362         fmv.s.x f29, zero
363         fmv.s.x f30, zero
364         fmv.s.x f31, zero
365         csrw    fcsr, 0
366         /* note that the caller must clear SR_FS */
367 #endif /* CONFIG_FPU */
368 .Lreset_regs_done:
369         ret
370 END(reset_regs)
371 #endif /* CONFIG_RISCV_M_MODE */
372
373 __PAGE_ALIGNED_BSS
374         /* Empty zero page */
375         .balign PAGE_SIZE
This page took 0.052547 seconds and 4 git commands to generate.