xref: /openbmc/linux/arch/riscv/kernel/head.S (revision 0da310e8)
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
18ENTRY(_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
96clear_bss:
97	REG_S zero, (a3)
98	add a3, a3, RISCV_SZPTR
99	blt a3, a4, clear_bss
100clear_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#ifdef CONFIG_MMU
113	la a0, early_pg_dir
114	call relocate
115#endif /* CONFIG_MMU */
116
117	/* Restore C environment */
118	la tp, init_task
119	sw zero, TASK_TI_CPU(tp)
120	la sp, init_thread_union + THREAD_SIZE
121
122	/* Start the kernel */
123	call parse_dtb
124	tail start_kernel
125
126#ifdef CONFIG_MMU
127relocate:
128	/* Relocate return address */
129	li a1, PAGE_OFFSET
130	la a2, _start
131	sub a1, a1, a2
132	add ra, ra, a1
133
134	/* Point stvec to virtual address of intruction after satp write */
135	la a2, 1f
136	add a2, a2, a1
137	csrw CSR_TVEC, a2
138
139	/* Compute satp for kernel page tables, but don't load it yet */
140	srl a2, a0, PAGE_SHIFT
141	li a1, SATP_MODE
142	or a2, a2, a1
143
144	/*
145	 * Load trampoline page directory, which will cause us to trap to
146	 * stvec if VA != PA, or simply fall through if VA == PA.  We need a
147	 * full fence here because setup_vm() just wrote these PTEs and we need
148	 * to ensure the new translations are in use.
149	 */
150	la a0, trampoline_pg_dir
151	srl a0, a0, PAGE_SHIFT
152	or a0, a0, a1
153	sfence.vma
154	csrw CSR_SATP, a0
155.align 2
1561:
157	/* Set trap vector to spin forever to help debug */
158	la a0, .Lsecondary_park
159	csrw CSR_TVEC, a0
160
161	/* Reload the global pointer */
162.option push
163.option norelax
164	la gp, __global_pointer$
165.option pop
166
167	/*
168	 * Switch to kernel page tables.  A full fence is necessary in order to
169	 * avoid using the trampoline translations, which are only correct for
170	 * the first superpage.  Fetching the fence is guarnteed to work
171	 * because that first superpage is translated the same way.
172	 */
173	csrw CSR_SATP, a2
174	sfence.vma
175
176	ret
177#endif /* CONFIG_MMU */
178
179.Lsecondary_start:
180#ifdef CONFIG_SMP
181	/* Set trap vector to spin forever to help debug */
182	la a3, .Lsecondary_park
183	csrw CSR_TVEC, a3
184
185	slli a3, a0, LGREG
186	la a1, __cpu_up_stack_pointer
187	la a2, __cpu_up_task_pointer
188	add a1, a3, a1
189	add a2, a3, a2
190
191	/*
192	 * This hart didn't win the lottery, so we wait for the winning hart to
193	 * get far enough along the boot process that it should continue.
194	 */
195.Lwait_for_cpu_up:
196	/* FIXME: We should WFI to save some energy here. */
197	REG_L sp, (a1)
198	REG_L tp, (a2)
199	beqz sp, .Lwait_for_cpu_up
200	beqz tp, .Lwait_for_cpu_up
201	fence
202
203#ifdef CONFIG_MMU
204	/* Enable virtual memory and relocate to virtual address */
205	la a0, swapper_pg_dir
206	call relocate
207#endif
208
209	tail smp_callin
210#endif
211
212.align 2
213.Lsecondary_park:
214	/* We lack SMP support or have too many harts, so park this hart */
215	wfi
216	j .Lsecondary_park
217END(_start)
218
219#ifdef CONFIG_RISCV_M_MODE
220ENTRY(reset_regs)
221	li	sp, 0
222	li	gp, 0
223	li	tp, 0
224	li	t0, 0
225	li	t1, 0
226	li	t2, 0
227	li	s0, 0
228	li	s1, 0
229	li	a2, 0
230	li	a3, 0
231	li	a4, 0
232	li	a5, 0
233	li	a6, 0
234	li	a7, 0
235	li	s2, 0
236	li	s3, 0
237	li	s4, 0
238	li	s5, 0
239	li	s6, 0
240	li	s7, 0
241	li	s8, 0
242	li	s9, 0
243	li	s10, 0
244	li	s11, 0
245	li	t3, 0
246	li	t4, 0
247	li	t5, 0
248	li	t6, 0
249	csrw	CSR_SCRATCH, 0
250
251#ifdef CONFIG_FPU
252	csrr	t0, CSR_MISA
253	andi	t0, t0, (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D)
254	bnez	t0, .Lreset_regs_done
255
256	li	t1, SR_FS
257	csrs	CSR_STATUS, t1
258	fmv.s.x	f0, zero
259	fmv.s.x	f1, zero
260	fmv.s.x	f2, zero
261	fmv.s.x	f3, zero
262	fmv.s.x	f4, zero
263	fmv.s.x	f5, zero
264	fmv.s.x	f6, zero
265	fmv.s.x	f7, zero
266	fmv.s.x	f8, zero
267	fmv.s.x	f9, zero
268	fmv.s.x	f10, zero
269	fmv.s.x	f11, zero
270	fmv.s.x	f12, zero
271	fmv.s.x	f13, zero
272	fmv.s.x	f14, zero
273	fmv.s.x	f15, zero
274	fmv.s.x	f16, zero
275	fmv.s.x	f17, zero
276	fmv.s.x	f18, zero
277	fmv.s.x	f19, zero
278	fmv.s.x	f20, zero
279	fmv.s.x	f21, zero
280	fmv.s.x	f22, zero
281	fmv.s.x	f23, zero
282	fmv.s.x	f24, zero
283	fmv.s.x	f25, zero
284	fmv.s.x	f26, zero
285	fmv.s.x	f27, zero
286	fmv.s.x	f28, zero
287	fmv.s.x	f29, zero
288	fmv.s.x	f30, zero
289	fmv.s.x	f31, zero
290	csrw	fcsr, 0
291	/* note that the caller must clear SR_FS */
292#endif /* CONFIG_FPU */
293.Lreset_regs_done:
294	ret
295END(reset_regs)
296#endif /* CONFIG_RISCV_M_MODE */
297
298__PAGE_ALIGNED_BSS
299	/* Empty zero page */
300	.balign PAGE_SIZE
301