Commit | Line | Data |
---|---|---|
50acfb2b | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
76d2a049 PD |
2 | /* |
3 | * Copyright (C) 2012 Regents of the University of California | |
76d2a049 PD |
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> | |
0f327f2a | 14 | #include <asm/image.h> |
76d2a049 PD |
15 | |
16 | __INIT | |
17 | ENTRY(_start) | |
0f327f2a AP |
18 | /* |
19 | * Image header expected by Linux boot-loaders. The image header data | |
20 | * structure is described in asm/image.h. | |
21 | * Do not modify it without modifying the structure and all bootloaders | |
22 | * that expects this header format!! | |
23 | */ | |
24 | /* jump to start kernel */ | |
25 | j _start_kernel | |
26 | /* reserved */ | |
27 | .word 0 | |
28 | .balign 8 | |
29 | #if __riscv_xlen == 64 | |
30 | /* Image load offset(2MB) from start of RAM */ | |
31 | .dword 0x200000 | |
32 | #else | |
33 | /* Image load offset(4MB) from start of RAM */ | |
34 | .dword 0x400000 | |
35 | #endif | |
36 | /* Effective size of kernel image */ | |
37 | .dword _end - _start | |
38 | .dword __HEAD_FLAGS | |
39 | .word RISCV_HEADER_VERSION | |
40 | .word 0 | |
41 | .dword 0 | |
474efecb | 42 | .ascii RISCV_IMAGE_MAGIC |
0f327f2a | 43 | .balign 4 |
474efecb | 44 | .ascii RISCV_IMAGE_MAGIC2 |
0f327f2a AP |
45 | .word 0 |
46 | ||
47 | .global _start_kernel | |
48 | _start_kernel: | |
a3182c91 AP |
49 | /* Mask all interrupts */ |
50 | csrw CSR_SIE, zero | |
51 | csrw CSR_SIP, zero | |
76d2a049 PD |
52 | |
53 | /* Load the global pointer */ | |
54 | .option push | |
55 | .option norelax | |
56 | la gp, __global_pointer$ | |
57 | .option pop | |
58 | ||
59 | /* | |
60 | * Disable FPU to detect illegal usage of | |
61 | * floating point in kernel space | |
62 | */ | |
63 | li t0, SR_FS | |
64 | csrc sstatus, t0 | |
65 | ||
66 | /* Pick one hart to run the main boot sequence */ | |
67 | la a3, hart_lottery | |
68 | li a2, 1 | |
69 | amoadd.w a3, a2, (a3) | |
70 | bnez a3, .Lsecondary_start | |
71 | ||
c0fbcd99 AP |
72 | /* Clear BSS for flat non-ELF images */ |
73 | la a3, __bss_start | |
74 | la a4, __bss_stop | |
75 | ble a4, a3, clear_bss_done | |
76 | clear_bss: | |
77 | REG_S zero, (a3) | |
78 | add a3, a3, RISCV_SZPTR | |
79 | blt a3, a4, clear_bss | |
80 | clear_bss_done: | |
81 | ||
76d2a049 PD |
82 | /* Save hart ID and DTB physical address */ |
83 | mv s0, a0 | |
84 | mv s1, a1 | |
f99fb607 AP |
85 | la a2, boot_cpu_hartid |
86 | REG_S a0, (a2) | |
76d2a049 PD |
87 | |
88 | /* Initialize page tables and relocate to virtual addresses */ | |
89 | la sp, init_thread_union + THREAD_SIZE | |
671f9a3e | 90 | mv a0, s1 |
76d2a049 | 91 | call setup_vm |
671f9a3e | 92 | la a0, early_pg_dir |
76d2a049 PD |
93 | call relocate |
94 | ||
95 | /* Restore C environment */ | |
96 | la tp, init_task | |
f99fb607 | 97 | sw zero, TASK_TI_CPU(tp) |
c637b911 | 98 | la sp, init_thread_union + THREAD_SIZE |
76d2a049 PD |
99 | |
100 | /* Start the kernel */ | |
8b08f501 | 101 | call parse_dtb |
76d2a049 PD |
102 | tail start_kernel |
103 | ||
104 | relocate: | |
105 | /* Relocate return address */ | |
106 | li a1, PAGE_OFFSET | |
671f9a3e AP |
107 | la a2, _start |
108 | sub a1, a1, a2 | |
76d2a049 PD |
109 | add ra, ra, a1 |
110 | ||
7549cdf5 | 111 | /* Point stvec to virtual address of intruction after satp write */ |
671f9a3e AP |
112 | la a2, 1f |
113 | add a2, a2, a1 | |
114 | csrw CSR_STVEC, a2 | |
76d2a049 | 115 | |
7549cdf5 | 116 | /* Compute satp for kernel page tables, but don't load it yet */ |
671f9a3e | 117 | srl a2, a0, PAGE_SHIFT |
7549cdf5 | 118 | li a1, SATP_MODE |
76d2a049 PD |
119 | or a2, a2, a1 |
120 | ||
121 | /* | |
122 | * Load trampoline page directory, which will cause us to trap to | |
4c3aeb82 PD |
123 | * stvec if VA != PA, or simply fall through if VA == PA. We need a |
124 | * full fence here because setup_vm() just wrote these PTEs and we need | |
125 | * to ensure the new translations are in use. | |
76d2a049 PD |
126 | */ |
127 | la a0, trampoline_pg_dir | |
128 | srl a0, a0, PAGE_SHIFT | |
129 | or a0, a0, a1 | |
130 | sfence.vma | |
a3182c91 | 131 | csrw CSR_SATP, a0 |
94f592f0 | 132 | .align 2 |
76d2a049 PD |
133 | 1: |
134 | /* Set trap vector to spin forever to help debug */ | |
135 | la a0, .Lsecondary_park | |
a3182c91 | 136 | csrw CSR_STVEC, a0 |
76d2a049 PD |
137 | |
138 | /* Reload the global pointer */ | |
139 | .option push | |
140 | .option norelax | |
141 | la gp, __global_pointer$ | |
142 | .option pop | |
143 | ||
4c3aeb82 PD |
144 | /* |
145 | * Switch to kernel page tables. A full fence is necessary in order to | |
146 | * avoid using the trampoline translations, which are only correct for | |
147 | * the first superpage. Fetching the fence is guarnteed to work | |
148 | * because that first superpage is translated the same way. | |
149 | */ | |
a3182c91 | 150 | csrw CSR_SATP, a2 |
4c3aeb82 | 151 | sfence.vma |
76d2a049 PD |
152 | |
153 | ret | |
154 | ||
155 | .Lsecondary_start: | |
156 | #ifdef CONFIG_SMP | |
157 | li a1, CONFIG_NR_CPUS | |
158 | bgeu a0, a1, .Lsecondary_park | |
159 | ||
160 | /* Set trap vector to spin forever to help debug */ | |
161 | la a3, .Lsecondary_park | |
a3182c91 | 162 | csrw CSR_STVEC, a3 |
76d2a049 PD |
163 | |
164 | slli a3, a0, LGREG | |
165 | la a1, __cpu_up_stack_pointer | |
166 | la a2, __cpu_up_task_pointer | |
167 | add a1, a3, a1 | |
168 | add a2, a3, a2 | |
169 | ||
170 | /* | |
171 | * This hart didn't win the lottery, so we wait for the winning hart to | |
172 | * get far enough along the boot process that it should continue. | |
173 | */ | |
174 | .Lwait_for_cpu_up: | |
175 | /* FIXME: We should WFI to save some energy here. */ | |
176 | REG_L sp, (a1) | |
177 | REG_L tp, (a2) | |
178 | beqz sp, .Lwait_for_cpu_up | |
179 | beqz tp, .Lwait_for_cpu_up | |
180 | fence | |
181 | ||
182 | /* Enable virtual memory and relocate to virtual address */ | |
671f9a3e | 183 | la a0, swapper_pg_dir |
76d2a049 PD |
184 | call relocate |
185 | ||
186 | tail smp_callin | |
187 | #endif | |
188 | ||
94f592f0 | 189 | .align 2 |
76d2a049 PD |
190 | .Lsecondary_park: |
191 | /* We lack SMP support or have too many harts, so park this hart */ | |
192 | wfi | |
193 | j .Lsecondary_park | |
194 | END(_start) | |
195 | ||
196 | __PAGE_ALIGNED_BSS | |
197 | /* Empty zero page */ | |
198 | .balign PAGE_SIZE |