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