Merge branch 'smack-for-4.17' of git://github.com/cschaufler/next-smack into next...
[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 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 1:
98         /* Set trap vector to spin forever to help debug */
99         la a0, .Lsecondary_park
100         csrw stvec, a0
101
102         /* Reload the global pointer */
103 .option push
104 .option norelax
105         la gp, __global_pointer$
106 .option pop
107
108         /* Switch to kernel page tables */
109         csrw sptbr, a2
110
111         ret
112
113 .Lsecondary_start:
114 #ifdef CONFIG_SMP
115         li a1, CONFIG_NR_CPUS
116         bgeu a0, a1, .Lsecondary_park
117
118         /* Set trap vector to spin forever to help debug */
119         la a3, .Lsecondary_park
120         csrw stvec, a3
121
122         slli a3, a0, LGREG
123         la a1, __cpu_up_stack_pointer
124         la a2, __cpu_up_task_pointer
125         add a1, a3, a1
126         add a2, a3, a2
127
128         /*
129          * This hart didn't win the lottery, so we wait for the winning hart to
130          * get far enough along the boot process that it should continue.
131          */
132 .Lwait_for_cpu_up:
133         /* FIXME: We should WFI to save some energy here. */
134         REG_L sp, (a1)
135         REG_L tp, (a2)
136         beqz sp, .Lwait_for_cpu_up
137         beqz tp, .Lwait_for_cpu_up
138         fence
139
140         /* Enable virtual memory and relocate to virtual address */
141         call relocate
142
143         tail smp_callin
144 #endif
145
146 .Lsecondary_park:
147         /* We lack SMP support or have too many harts, so park this hart */
148         wfi
149         j .Lsecondary_park
150 END(_start)
151
152 __PAGE_ALIGNED_BSS
153         /* Empty zero page */
154         .balign PAGE_SIZE