summaryrefslogtreecommitdiff
path: root/libcpu/risc-v/common64/startup_gcc.S
blob: dde3c092408a79c75d676928e735bbde4046a38f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
/*
 * Copyright (c) 2006-2018, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2018/10/01     Bernard      The first version
 * 2018/12/27     Jesven       Add SMP support
 * 2020/6/12      Xim          Port to QEMU and remove SMP support
 * 2024-06-30     Shell        Support of kernel remapping
 */

#include <encoding.h>
#include <cpuport.h>

    .data
    .global boot_hartid    /* global varible rt_boot_hartid in .data section */
boot_hartid:
    .word 0xdeadbeef

    .global         _start
    .section ".start", "ax"
_start:
    j 1f
    .word 0xdeadbeef
    .align 3
    .global g_wake_up
    g_wake_up:
        .dword 1
        .dword 0
1:
    /* save hartid */
    la t0, boot_hartid                /* global varible rt_boot_hartid */
#ifdef RT_USING_SMP
    lw   t2, (t0)
    li   t3, 0xdeadbeef               /* Sentinel value indicating uninitialized boot_hartid */
    li   t4, 0xffffffff
    and  t2, t2, t4                   /* Extract the lower 32 bits. */
    bne  t2, t3, system_init          /* If the current value is 0xdeadbeef, skip the boot_hartid assignment operation. */
#endif
    mv t1, a0                         /* get hartid in S-mode frome a0 register */
    sw t1, (t0)                       /* store t1 register low 4 bits in memory address which is stored in t0 */

#ifdef RT_USING_SMP
system_init:
#endif

    /*
     * When ARCH_MM_MMU is not enabled or pvoff==0:
     * Store hartid temporarily in the satp register because:
     * 1. satp is not used for address translation when MMU is disabled or pvoff==0.
     * 2. This value will be moved to percpu_hartid once MMU is initialized.
     * This approach avoids using extra memory or registers during the critical boot phase,
     * but developers should be aware that satp is overloaded for this purpose until MMU setup.
     */
    csrw satp, a0

    /* clear Interrupt Registers */
    csrw sie, 0
    csrw sip, 0
    /* set Trap Vector Base Address Register */
    la t0, trap_entry
    csrw stvec, t0

    li x1, 0
    li x2, 0
    li x3, 0
    li x4, 0
    li x5, 0
    li x6, 0
    li x7, 0
    li x8, 0
    li x9, 0
#ifndef RT_USING_SMP
    /* In the SMP architecture, a0 will be used again later */
    li x10,0
#endif
    li x11,0
    li x12,0
    li x13,0
    li x14,0
    li x15,0
    li x16,0
    li x17,0
    li x18,0
    li x19,0
    li x20,0
    li x21,0
    li x22,0
    li x23,0
    li x24,0
    li x25,0
    li x26,0
    li x27,0
    li x28,0
    li x29,0
    li x30,0
    li x31,0

    /* set to disable FPU */
    li t0, SSTATUS_FS + SSTATUS_VS
    csrc sstatus, t0
    li t0, SSTATUS_SUM
    csrs sstatus, t0

.option push
.option norelax
    la gp, __global_pointer$
.option pop

#ifndef RT_USING_SMP
    /* removed SMP support here */
    la   sp, __stack_start__
    li   t0, __STACKSIZE__
    add  sp, sp, t0
#else
    /* Initialize the sp pointer according to different hartids. */
    mv   t0, a0
    /* calculate stack offset: hartid * __STACKSIZE__ */
    li   t1, __STACKSIZE__
    mul  t0, t0, t1        /* t0 = hartid * __STACKSIZE__ */

    /* set stack pointer */
    la   sp, __stack_start__
    add  sp, sp, t0        /* sp = __stack_start__ + hartid * __STACKSIZE__ */
    add  sp, sp, t1        /* sp += __STACKSIZE__ (point to stack top) */

    mv      t0, a0
    lw      t1, boot_hartid
    mv      tp, a0
    bne     t0, t1, early_secondary_cpu_entry
#endif /* RT_USING_SMP */

    /**
     * sscratch is always zero on kernel mode
     */
    csrw sscratch, zero
    call init_bss
early_secondary_cpu_entry:
#ifdef ARCH_MM_MMU
    // Manually manage pages in the early stage
    la      a0, .early_page_array
    call    set_free_page

    la      a0, .early_tbl_page
    mv      a1, tp
    call    rt_hw_mem_setup_early
    call    rt_kmem_pvoff
    /* a0 := pvoff  */
    beq     a0, zero, 1f

    /* relocate pc */
    la      x1, _after_pc_relocation
    sub     x1, x1, a0
    ret
_after_pc_relocation:
#if defined(RT_USING_SMP)
    /* If the MMU is enabled, save the hartid in percpu_hartid.
     * -> .percpu_hartid (hartid_0)
     * ...... align(2MB)
     * -> (hartid_1)
     * ......
    */
    la      a0, .percpu_hartid
    mv      a1, tp
    call    rt_hw_percpu_hartid_init
#endif
    /* relocate gp */
    sub     gp, gp, a0

#ifndef RT_USING_SMP
    /* relocate context: sp */
    la      sp, __stack_start__
    li      t0, __STACKSIZE__
    add     sp, sp, t0
#else
    /* Initialize the sp pointer according to different hartids. */
    mv   t0, tp
    /* calculate stack offset: hartid * __STACKSIZE__ */
    li   t1, __STACKSIZE__
    mul  t0, t0, t1        /* t0 = hartid * __STACKSIZE__ */

    /* set stack pointer */
    la   sp, __stack_start__
    add  sp, sp, t0        /* sp = __stack_start__ + hartid * __STACKSIZE__ */
    add  sp, sp, t1        /* sp += __STACKSIZE__ (point to stack top) */
#endif /* RT_USING_SMP */

    /* reset s0-fp */
    mv      s0, zero

    /* relocate stvec */
    la      t0, trap_entry
    csrw    stvec, t0
1:
#ifdef RT_USING_SMP
    mv      t0, tp
    lw      t1, boot_hartid
    bne     t0, t1, secondary_cpu_entry
#endif
#endif /* ARCH_MM_MMU */
    call    sbi_init
    call    primary_cpu_entry

_never_return_here:
    j       .

.global _start_link_addr
_start_link_addr:
    .dword __text_start

#ifdef ARCH_MM_MMU
#ifdef RT_USING_SMP
/*
 * CPU stack builtin
 */
    .section ".percpu"
.percpu_hartid:
    .space 16
#endif

    .section ".bss"

.equ page_size, 4096
    .balign page_size
.early_tbl_page:
    .space 1 * page_size
#if defined(RT_USING_SMP) && RT_CPUS_NR > 1
    .space (RT_CPUS_NR - 1) * page_size
#endif

.early_page_array:
    .space (8 + 8) * page_size
#ifdef RT_USING_SMP
    .space RT_CPUS_NR * 5 * page_size
#endif

#endif /* ARCH_MM_MMU */