GNU Linux-libre 4.19.245-gnu1
[releases.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 sie, zero
27
28         /* Load the global pointer */
29 .option push
30 .option norelax
31         la gp, __global_pointer$
32 .option pop
33
34         /*
35          * Disable FPU to detect illegal usage of
36          * floating point in kernel space
37          */
38         li t0, SR_FS
39         csrc sstatus, t0
40
41         /* Pick one hart to run the main boot sequence */
42         la a3, hart_lottery
43         li a2, 1
44         amoadd.w a3, a2, (a3)
45         bnez a3, .Lsecondary_start
46
47         /* Save hart ID and DTB physical address */
48         mv s0, a0
49         mv s1, a1
50
51         /* Initialize page tables and relocate to virtual addresses */
52         la sp, init_thread_union + THREAD_SIZE
53         call setup_vm
54         call relocate
55
56         /* Restore C environment */
57         la tp, init_task
58         sw s0, TASK_TI_CPU(tp)
59
60         la sp, init_thread_union
61         li a0, ASM_THREAD_SIZE
62         add sp, sp, a0
63
64         /* Start the kernel */
65         mv a0, s0
66         mv a1, s1
67         call parse_dtb
68         tail start_kernel
69
70 relocate:
71         /* Relocate return address */
72         li a1, PAGE_OFFSET
73         la a0, _start
74         sub a1, a1, a0
75         add ra, ra, a1
76
77         /* Point stvec to virtual address of intruction after satp write */
78         la a0, 1f
79         add a0, a0, a1
80         csrw stvec, a0
81
82         /* Compute satp for kernel page tables, but don't load it yet */
83         la a2, swapper_pg_dir
84         srl a2, a2, PAGE_SHIFT
85         li a1, SATP_MODE
86         or a2, a2, a1
87
88         /*
89          * Load trampoline page directory, which will cause us to trap to
90          * stvec if VA != PA, or simply fall through if VA == PA
91          */
92         la a0, trampoline_pg_dir
93         srl a0, a0, PAGE_SHIFT
94         or a0, a0, a1
95         sfence.vma
96         csrw sptbr, a0
97 .align 2
98 1:
99         /* Set trap vector to spin forever to help debug */
100         la a0, .Lsecondary_park
101         csrw stvec, a0
102
103         /* Reload the global pointer */
104 .option push
105 .option norelax
106         la gp, __global_pointer$
107 .option pop
108
109         /* Switch to kernel page tables */
110         csrw sptbr, a2
111
112         ret
113
114 .Lsecondary_start:
115 #ifdef CONFIG_SMP
116         li a1, CONFIG_NR_CPUS
117         bgeu a0, a1, .Lsecondary_park
118
119         /* Set trap vector to spin forever to help debug */
120         la a3, .Lsecondary_park
121         csrw stvec, a3
122
123         slli a3, a0, LGREG
124         la a1, __cpu_up_stack_pointer
125         la a2, __cpu_up_task_pointer
126         add a1, a3, a1
127         add a2, a3, a2
128
129         /*
130          * This hart didn't win the lottery, so we wait for the winning hart to
131          * get far enough along the boot process that it should continue.
132          */
133 .Lwait_for_cpu_up:
134         /* FIXME: We should WFI to save some energy here. */
135         REG_L sp, (a1)
136         REG_L tp, (a2)
137         beqz sp, .Lwait_for_cpu_up
138         beqz tp, .Lwait_for_cpu_up
139         fence
140
141         /* Enable virtual memory and relocate to virtual address */
142         call relocate
143
144         tail smp_callin
145 #endif
146
147 .align 2
148 .Lsecondary_park:
149         /* We lack SMP support or have too many harts, so park this hart */
150         wfi
151         j .Lsecondary_park
152 END(_start)
153
154 __PAGE_ALIGNED_BSS
155         /* Empty zero page */
156         .balign PAGE_SIZE