dt-bindings: reset: imx7: Fix the spelling of 'indices'
[sfrench/cifs-2.6.git] / arch / riscv / kernel / head.S
1 /*
2  * Copyright (C) 2012 Regents of the University of California
3  *
4  *   This program is free software; you can redistribute it and/or
5  *   modify it under the terms of the GNU General Public License
6  *   as published by the Free Software Foundation, version 2.
7  *
8  *   This program is distributed in the hope that it will be useful,
9  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  *   GNU General Public License for more details.
12  */
13
14 #include <asm/thread_info.h>
15 #include <asm/asm-offsets.h>
16 #include <asm/asm.h>
17 #include <linux/init.h>
18 #include <linux/linkage.h>
19 #include <asm/thread_info.h>
20 #include <asm/page.h>
21 #include <asm/csr.h>
22
23 __INIT
24 ENTRY(_start)
25         /* Mask all interrupts */
26         csrw CSR_SIE, zero
27         csrw CSR_SIP, zero
28
29         /* Load the global pointer */
30 .option push
31 .option norelax
32         la gp, __global_pointer$
33 .option pop
34
35         /*
36          * Disable FPU to detect illegal usage of
37          * floating point in kernel space
38          */
39         li t0, SR_FS
40         csrc sstatus, t0
41
42         /* Pick one hart to run the main boot sequence */
43         la a3, hart_lottery
44         li a2, 1
45         amoadd.w a3, a2, (a3)
46         bnez a3, .Lsecondary_start
47
48         /* Clear BSS for flat non-ELF images */
49         la a3, __bss_start
50         la a4, __bss_stop
51         ble a4, a3, clear_bss_done
52 clear_bss:
53         REG_S zero, (a3)
54         add a3, a3, RISCV_SZPTR
55         blt a3, a4, clear_bss
56 clear_bss_done:
57
58         /* Save hart ID and DTB physical address */
59         mv s0, a0
60         mv s1, a1
61         la a2, boot_cpu_hartid
62         REG_S a0, (a2)
63
64         /* Initialize page tables and relocate to virtual addresses */
65         la sp, init_thread_union + THREAD_SIZE
66         call setup_vm
67         call relocate
68
69         /* Restore C environment */
70         la tp, init_task
71         sw zero, TASK_TI_CPU(tp)
72         la sp, init_thread_union + THREAD_SIZE
73
74         /* Start the kernel */
75         mv a0, s1
76         call parse_dtb
77         tail start_kernel
78
79 relocate:
80         /* Relocate return address */
81         li a1, PAGE_OFFSET
82         la a0, _start
83         sub a1, a1, a0
84         add ra, ra, a1
85
86         /* Point stvec to virtual address of intruction after satp write */
87         la a0, 1f
88         add a0, a0, a1
89         csrw CSR_STVEC, a0
90
91         /* Compute satp for kernel page tables, but don't load it yet */
92         la a2, swapper_pg_dir
93         srl a2, a2, PAGE_SHIFT
94         li a1, SATP_MODE
95         or a2, a2, a1
96
97         /*
98          * Load trampoline page directory, which will cause us to trap to
99          * stvec if VA != PA, or simply fall through if VA == PA.  We need a
100          * full fence here because setup_vm() just wrote these PTEs and we need
101          * to ensure the new translations are in use.
102          */
103         la a0, trampoline_pg_dir
104         srl a0, a0, PAGE_SHIFT
105         or a0, a0, a1
106         sfence.vma
107         csrw CSR_SATP, a0
108 .align 2
109 1:
110         /* Set trap vector to spin forever to help debug */
111         la a0, .Lsecondary_park
112         csrw CSR_STVEC, a0
113
114         /* Reload the global pointer */
115 .option push
116 .option norelax
117         la gp, __global_pointer$
118 .option pop
119
120         /*
121          * Switch to kernel page tables.  A full fence is necessary in order to
122          * avoid using the trampoline translations, which are only correct for
123          * the first superpage.  Fetching the fence is guarnteed to work
124          * because that first superpage is translated the same way.
125          */
126         csrw CSR_SATP, a2
127         sfence.vma
128
129         ret
130
131 .Lsecondary_start:
132 #ifdef CONFIG_SMP
133         li a1, CONFIG_NR_CPUS
134         bgeu a0, a1, .Lsecondary_park
135
136         /* Set trap vector to spin forever to help debug */
137         la a3, .Lsecondary_park
138         csrw CSR_STVEC, a3
139
140         slli a3, a0, LGREG
141         la a1, __cpu_up_stack_pointer
142         la a2, __cpu_up_task_pointer
143         add a1, a3, a1
144         add a2, a3, a2
145
146         /*
147          * This hart didn't win the lottery, so we wait for the winning hart to
148          * get far enough along the boot process that it should continue.
149          */
150 .Lwait_for_cpu_up:
151         /* FIXME: We should WFI to save some energy here. */
152         REG_L sp, (a1)
153         REG_L tp, (a2)
154         beqz sp, .Lwait_for_cpu_up
155         beqz tp, .Lwait_for_cpu_up
156         fence
157
158         /* Enable virtual memory and relocate to virtual address */
159         call relocate
160
161         tail smp_callin
162 #endif
163
164 .align 2
165 .Lsecondary_park:
166         /* We lack SMP support or have too many harts, so park this hart */
167         wfi
168         j .Lsecondary_park
169 END(_start)
170
171 __PAGE_ALIGNED_BSS
172         /* Empty zero page */
173         .balign PAGE_SIZE