64eb8beb228ee7884aeae462ee1939deabe296d5
[sfrench/cifs-2.6.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 __INIT
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 .global _start_kernel
49 _start_kernel:
50         /* Mask all interrupts */
51         csrw CSR_IE, zero
52         csrw CSR_IP, zero
53
54 #ifdef CONFIG_RISCV_M_MODE
55         /* flush the instruction cache */
56         fence.i
57
58         /* Reset all registers except ra, a0, a1 */
59         call reset_regs
60
61         /*
62          * The hartid in a0 is expected later on, and we have no firmware
63          * to hand it to us.
64          */
65         csrr a0, CSR_MHARTID
66 #endif /* CONFIG_RISCV_M_MODE */
67
68         /* Load the global pointer */
69 .option push
70 .option norelax
71         la gp, __global_pointer$
72 .option pop
73
74         /*
75          * Disable FPU to detect illegal usage of
76          * floating point in kernel space
77          */
78         li t0, SR_FS
79         csrc CSR_STATUS, t0
80
81 #ifdef CONFIG_SMP
82         li t0, CONFIG_NR_CPUS
83         bgeu a0, t0, .Lsecondary_park
84 #endif
85
86         /* Pick one hart to run the main boot sequence */
87         la a3, hart_lottery
88         li a2, 1
89         amoadd.w a3, a2, (a3)
90         bnez a3, .Lsecondary_start
91
92         /* Clear BSS for flat non-ELF images */
93         la a3, __bss_start
94         la a4, __bss_stop
95         ble a4, a3, clear_bss_done
96 clear_bss:
97         REG_S zero, (a3)
98         add a3, a3, RISCV_SZPTR
99         blt a3, a4, clear_bss
100 clear_bss_done:
101
102         /* Save hart ID and DTB physical address */
103         mv s0, a0
104         mv s1, a1
105         la a2, boot_cpu_hartid
106         REG_S a0, (a2)
107
108         /* Initialize page tables and relocate to virtual addresses */
109         la sp, init_thread_union + THREAD_SIZE
110         mv a0, s1
111         call setup_vm
112         la a0, early_pg_dir
113         call relocate
114
115         /* Restore C environment */
116         la tp, init_task
117         sw zero, TASK_TI_CPU(tp)
118         la sp, init_thread_union + THREAD_SIZE
119
120         /* Start the kernel */
121         call parse_dtb
122         tail start_kernel
123
124 relocate:
125         /* Relocate return address */
126         li a1, PAGE_OFFSET
127         la a2, _start
128         sub a1, a1, a2
129         add ra, ra, a1
130
131         /* Point stvec to virtual address of intruction after satp write */
132         la a2, 1f
133         add a2, a2, a1
134         csrw CSR_TVEC, a2
135
136         /* Compute satp for kernel page tables, but don't load it yet */
137         srl a2, a0, PAGE_SHIFT
138         li a1, SATP_MODE
139         or a2, a2, a1
140
141         /*
142          * Load trampoline page directory, which will cause us to trap to
143          * stvec if VA != PA, or simply fall through if VA == PA.  We need a
144          * full fence here because setup_vm() just wrote these PTEs and we need
145          * to ensure the new translations are in use.
146          */
147         la a0, trampoline_pg_dir
148         srl a0, a0, PAGE_SHIFT
149         or a0, a0, a1
150         sfence.vma
151         csrw CSR_SATP, a0
152 .align 2
153 1:
154         /* Set trap vector to spin forever to help debug */
155         la a0, .Lsecondary_park
156         csrw CSR_TVEC, a0
157
158         /* Reload the global pointer */
159 .option push
160 .option norelax
161         la gp, __global_pointer$
162 .option pop
163
164         /*
165          * Switch to kernel page tables.  A full fence is necessary in order to
166          * avoid using the trampoline translations, which are only correct for
167          * the first superpage.  Fetching the fence is guarnteed to work
168          * because that first superpage is translated the same way.
169          */
170         csrw CSR_SATP, a2
171         sfence.vma
172
173         ret
174
175 .Lsecondary_start:
176 #ifdef CONFIG_SMP
177         /* Set trap vector to spin forever to help debug */
178         la a3, .Lsecondary_park
179         csrw CSR_TVEC, a3
180
181         slli a3, a0, LGREG
182         la a1, __cpu_up_stack_pointer
183         la a2, __cpu_up_task_pointer
184         add a1, a3, a1
185         add a2, a3, a2
186
187         /*
188          * This hart didn't win the lottery, so we wait for the winning hart to
189          * get far enough along the boot process that it should continue.
190          */
191 .Lwait_for_cpu_up:
192         /* FIXME: We should WFI to save some energy here. */
193         REG_L sp, (a1)
194         REG_L tp, (a2)
195         beqz sp, .Lwait_for_cpu_up
196         beqz tp, .Lwait_for_cpu_up
197         fence
198
199         /* Enable virtual memory and relocate to virtual address */
200         la a0, swapper_pg_dir
201         call relocate
202
203         tail smp_callin
204 #endif
205
206 .align 2
207 .Lsecondary_park:
208         /* We lack SMP support or have too many harts, so park this hart */
209         wfi
210         j .Lsecondary_park
211 END(_start)
212
213 #ifdef CONFIG_RISCV_M_MODE
214 ENTRY(reset_regs)
215         li      sp, 0
216         li      gp, 0
217         li      tp, 0
218         li      t0, 0
219         li      t1, 0
220         li      t2, 0
221         li      s0, 0
222         li      s1, 0
223         li      a2, 0
224         li      a3, 0
225         li      a4, 0
226         li      a5, 0
227         li      a6, 0
228         li      a7, 0
229         li      s2, 0
230         li      s3, 0
231         li      s4, 0
232         li      s5, 0
233         li      s6, 0
234         li      s7, 0
235         li      s8, 0
236         li      s9, 0
237         li      s10, 0
238         li      s11, 0
239         li      t3, 0
240         li      t4, 0
241         li      t5, 0
242         li      t6, 0
243         csrw    sscratch, 0
244
245 #ifdef CONFIG_FPU
246         csrr    t0, CSR_MISA
247         andi    t0, t0, (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D)
248         bnez    t0, .Lreset_regs_done
249
250         li      t1, SR_FS
251         csrs    CSR_STATUS, t1
252         fmv.s.x f0, zero
253         fmv.s.x f1, zero
254         fmv.s.x f2, zero
255         fmv.s.x f3, zero
256         fmv.s.x f4, zero
257         fmv.s.x f5, zero
258         fmv.s.x f6, zero
259         fmv.s.x f7, zero
260         fmv.s.x f8, zero
261         fmv.s.x f9, zero
262         fmv.s.x f10, zero
263         fmv.s.x f11, zero
264         fmv.s.x f12, zero
265         fmv.s.x f13, zero
266         fmv.s.x f14, zero
267         fmv.s.x f15, zero
268         fmv.s.x f16, zero
269         fmv.s.x f17, zero
270         fmv.s.x f18, zero
271         fmv.s.x f19, zero
272         fmv.s.x f20, zero
273         fmv.s.x f21, zero
274         fmv.s.x f22, zero
275         fmv.s.x f23, zero
276         fmv.s.x f24, zero
277         fmv.s.x f25, zero
278         fmv.s.x f26, zero
279         fmv.s.x f27, zero
280         fmv.s.x f28, zero
281         fmv.s.x f29, zero
282         fmv.s.x f30, zero
283         fmv.s.x f31, zero
284         csrw    fcsr, 0
285         /* note that the caller must clear SR_FS */
286 #endif /* CONFIG_FPU */
287 .Lreset_regs_done:
288         ret
289 END(reset_regs)
290 #endif /* CONFIG_RISCV_M_MODE */
291
292 __PAGE_ALIGNED_BSS
293         /* Empty zero page */
294         .balign PAGE_SIZE