GNU Linux-libre 5.10.217-gnu1
[releases.git] / arch / csky / kernel / entry.S
1 /* SPDX-License-Identifier: GPL-2.0 */
2 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
3
4 #include <linux/linkage.h>
5 #include <abi/entry.h>
6 #include <abi/pgtable-bits.h>
7 #include <asm/errno.h>
8 #include <asm/setup.h>
9 #include <asm/unistd.h>
10 #include <asm/asm-offsets.h>
11 #include <linux/threads.h>
12 #include <asm/setup.h>
13 #include <asm/page.h>
14 #include <asm/thread_info.h>
15
16 #define PTE_INDX_MSK    0xffc
17 #define PTE_INDX_SHIFT  10
18 #define _PGDIR_SHIFT    22
19
20 .macro  zero_fp
21 #ifdef CONFIG_STACKTRACE
22         movi    r8, 0
23 #endif
24 .endm
25
26 .macro  context_tracking
27 #ifdef CONFIG_CONTEXT_TRACKING
28         mfcr    a0, epsr
29         btsti   a0, 31
30         bt      1f
31         jbsr    context_tracking_user_exit
32         ldw     a0, (sp, LSAVE_A0)
33         ldw     a1, (sp, LSAVE_A1)
34         ldw     a2, (sp, LSAVE_A2)
35         ldw     a3, (sp, LSAVE_A3)
36 #if defined(__CSKYABIV1__)
37         ldw     r6, (sp, LSAVE_A4)
38         ldw     r7, (sp, LSAVE_A5)
39 #endif
40 1:
41 #endif
42 .endm
43
44 .macro tlbop_begin name, val0, val1, val2
45 ENTRY(csky_\name)
46         mtcr    a3, ss2
47         mtcr    r6, ss3
48         mtcr    a2, ss4
49
50         RD_PGDR r6
51         RD_MEH  a3
52 #ifdef CONFIG_CPU_HAS_TLBI
53         tlbi.vaas a3
54         sync.is
55
56         btsti   a3, 31
57         bf      1f
58         RD_PGDR_K r6
59 1:
60 #else
61         bgeni   a2, 31
62         WR_MCIR a2
63         bgeni   a2, 25
64         WR_MCIR a2
65 #endif
66         bclri   r6, 0
67         lrw     a2, va_pa_offset
68         ld.w    a2, (a2, 0)
69         subu    r6, a2
70         bseti   r6, 31
71
72         mov     a2, a3
73         lsri    a2, _PGDIR_SHIFT
74         lsli    a2, 2
75         addu    r6, a2
76         ldw     r6, (r6)
77
78         lrw     a2, va_pa_offset
79         ld.w    a2, (a2, 0)
80         subu    r6, a2
81         bseti   r6, 31
82
83         lsri    a3, PTE_INDX_SHIFT
84         lrw     a2, PTE_INDX_MSK
85         and     a3, a2
86         addu    r6, a3
87         ldw     a3, (r6)
88
89         movi    a2, (_PAGE_PRESENT | \val0)
90         and     a3, a2
91         cmpne   a3, a2
92         bt      \name
93
94         /* First read/write the page, just update the flags */
95         ldw     a3, (r6)
96         bgeni   a2, PAGE_VALID_BIT
97         bseti   a2, PAGE_ACCESSED_BIT
98         bseti   a2, \val1
99         bseti   a2, \val2
100         or      a3, a2
101         stw     a3, (r6)
102
103         /* Some cpu tlb-hardrefill bypass the cache */
104 #ifdef CONFIG_CPU_NEED_TLBSYNC
105         movi    a2, 0x22
106         bseti   a2, 6
107         mtcr    r6, cr22
108         mtcr    a2, cr17
109         sync
110 #endif
111
112         mfcr    a3, ss2
113         mfcr    r6, ss3
114         mfcr    a2, ss4
115         rte
116 \name:
117         mfcr    a3, ss2
118         mfcr    r6, ss3
119         mfcr    a2, ss4
120         SAVE_ALL 0
121 .endm
122 .macro tlbop_end is_write
123         zero_fp
124         context_tracking
125         RD_MEH  a2
126         psrset  ee, ie
127         mov     a0, sp
128         movi    a1, \is_write
129         jbsr    do_page_fault
130         jmpi    ret_from_exception
131 .endm
132
133 .text
134
135 tlbop_begin tlbinvalidl, _PAGE_READ, PAGE_VALID_BIT, PAGE_ACCESSED_BIT
136 tlbop_end 0
137
138 tlbop_begin tlbinvalids, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT
139 tlbop_end 1
140
141 tlbop_begin tlbmodified, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT
142 #ifndef CONFIG_CPU_HAS_LDSTEX
143 jbsr csky_cmpxchg_fixup
144 #endif
145 tlbop_end 1
146
147 ENTRY(csky_systemcall)
148         SAVE_ALL TRAP0_SIZE
149         zero_fp
150         context_tracking
151         psrset  ee, ie
152
153         lrw     r9, __NR_syscalls
154         cmphs   syscallid, r9           /* Check nr of syscall */
155         bt      1f
156
157         lrw     r9, sys_call_table
158         ixw     r9, syscallid
159         ldw     syscallid, (r9)
160         cmpnei  syscallid, 0
161         bf      ret_from_exception
162
163         mov     r9, sp
164         bmaski  r10, THREAD_SHIFT
165         andn    r9, r10
166         ldw     r10, (r9, TINFO_FLAGS)
167         lrw     r9, _TIF_SYSCALL_WORK
168         and     r10, r9
169         cmpnei  r10, 0
170         bt      csky_syscall_trace
171 #if defined(__CSKYABIV2__)
172         subi    sp, 8
173         stw     r5, (sp, 0x4)
174         stw     r4, (sp, 0x0)
175         jsr     syscallid                      /* Do system call */
176         addi    sp, 8
177 #else
178         jsr     syscallid
179 #endif
180         stw     a0, (sp, LSAVE_A0)      /* Save return value */
181 1:
182 #ifdef CONFIG_DEBUG_RSEQ
183         mov     a0, sp
184         jbsr    rseq_syscall
185 #endif
186         jmpi    ret_from_exception
187
188 csky_syscall_trace:
189         mov     a0, sp                  /* sp = pt_regs pointer */
190         jbsr    syscall_trace_enter
191         cmpnei  a0, 0
192         bt      1f
193         /* Prepare args before do system call */
194         ldw     a0, (sp, LSAVE_A0)
195         ldw     a1, (sp, LSAVE_A1)
196         ldw     a2, (sp, LSAVE_A2)
197         ldw     a3, (sp, LSAVE_A3)
198 #if defined(__CSKYABIV2__)
199         subi    sp, 8
200         ldw     r9, (sp, LSAVE_A4)
201         stw     r9, (sp, 0x0)
202         ldw     r9, (sp, LSAVE_A5)
203         stw     r9, (sp, 0x4)
204         jsr     syscallid                     /* Do system call */
205         addi    sp, 8
206 #else
207         ldw     r6, (sp, LSAVE_A4)
208         ldw     r7, (sp, LSAVE_A5)
209         jsr     syscallid                     /* Do system call */
210 #endif
211         stw     a0, (sp, LSAVE_A0)      /* Save return value */
212
213 1:
214 #ifdef CONFIG_DEBUG_RSEQ
215         mov     a0, sp
216         jbsr    rseq_syscall
217 #endif
218         mov     a0, sp                  /* right now, sp --> pt_regs */
219         jbsr    syscall_trace_exit
220         br      ret_from_exception
221
222 ENTRY(ret_from_kernel_thread)
223         jbsr    schedule_tail
224         mov     a0, r10
225         jsr     r9
226         jbsr    ret_from_exception
227
228 ENTRY(ret_from_fork)
229         jbsr    schedule_tail
230         mov     r9, sp
231         bmaski  r10, THREAD_SHIFT
232         andn    r9, r10
233         ldw     r10, (r9, TINFO_FLAGS)
234         lrw     r9, _TIF_SYSCALL_WORK
235         and     r10, r9
236         cmpnei  r10, 0
237         bf      ret_from_exception
238         mov     a0, sp                  /* sp = pt_regs pointer */
239         jbsr    syscall_trace_exit
240
241 ret_from_exception:
242         psrclr  ie
243         ld      r9, (sp, LSAVE_PSR)
244         btsti   r9, 31
245
246         bt      1f
247         /*
248          * Load address of current->thread_info, Then get address of task_struct
249          * Get task_needreshed in task_struct
250          */
251         mov     r9, sp
252         bmaski  r10, THREAD_SHIFT
253         andn    r9, r10
254
255         ldw     r10, (r9, TINFO_FLAGS)
256         lrw     r9, _TIF_WORK_MASK
257         and     r10, r9
258         cmpnei  r10, 0
259         bt      exit_work
260 #ifdef CONFIG_CONTEXT_TRACKING
261         jbsr    context_tracking_user_enter
262 #endif
263 1:
264 #ifdef CONFIG_PREEMPTION
265         mov     r9, sp
266         bmaski  r10, THREAD_SHIFT
267         andn    r9, r10
268
269         ldw     r10, (r9, TINFO_PREEMPT)
270         cmpnei  r10, 0
271         bt      2f
272         jbsr    preempt_schedule_irq    /* irq en/disable is done inside */
273 2:
274 #endif
275
276 #ifdef CONFIG_TRACE_IRQFLAGS
277         ld      r10, (sp, LSAVE_PSR)
278         btsti   r10, 6
279         bf      2f
280         jbsr    trace_hardirqs_on
281 2:
282 #endif
283         RESTORE_ALL
284
285 exit_work:
286         lrw     r9, ret_from_exception
287         mov     lr, r9
288
289         btsti   r10, TIF_NEED_RESCHED
290         bt      work_resched
291
292         psrset  ie
293         mov     a0, sp
294         mov     a1, r10
295         jmpi    do_notify_resume
296
297 work_resched:
298         jmpi    schedule
299
300 ENTRY(csky_trap)
301         SAVE_ALL 0
302         zero_fp
303         context_tracking
304         psrset  ee
305         mov     a0, sp                 /* Push Stack pointer arg */
306         jbsr    trap_c                 /* Call C-level trap handler */
307         jmpi    ret_from_exception
308
309 /*
310  * Prototype from libc for abiv1:
311  * register unsigned int __result asm("a0");
312  * asm( "trap 3" :"=r"(__result)::);
313  */
314 ENTRY(csky_get_tls)
315         USPTOKSP
316
317         /* increase epc for continue */
318         mfcr    a0, epc
319         addi    a0, TRAP0_SIZE
320         mtcr    a0, epc
321
322         /* get current task thread_info with kernel 8K stack */
323         bmaski  a0, THREAD_SHIFT
324         not     a0
325         subi    sp, 1
326         and     a0, sp
327         addi    sp, 1
328
329         /* get tls */
330         ldw     a0, (a0, TINFO_TP_VALUE)
331
332         KSPTOUSP
333         rte
334
335 ENTRY(csky_irq)
336         SAVE_ALL 0
337         zero_fp
338         context_tracking
339         psrset  ee
340
341 #ifdef CONFIG_TRACE_IRQFLAGS
342         jbsr    trace_hardirqs_off
343 #endif
344
345
346         mov     a0, sp
347         jbsr    csky_do_IRQ
348
349         jmpi    ret_from_exception
350
351 /*
352  * a0 =  prev task_struct *
353  * a1 =  next task_struct *
354  * a0 =  return next
355  */
356 ENTRY(__switch_to)
357         lrw     a3, TASK_THREAD
358         addu    a3, a0
359
360         SAVE_SWITCH_STACK
361
362         stw     sp, (a3, THREAD_KSP)
363
364         /* Set up next process to run */
365         lrw     a3, TASK_THREAD
366         addu    a3, a1
367
368         ldw     sp, (a3, THREAD_KSP)    /* Set next kernel sp */
369
370 #if  defined(__CSKYABIV2__)
371         addi    a3, a1, TASK_THREAD_INFO
372         ldw     tls, (a3, TINFO_TP_VALUE)
373 #endif
374
375         RESTORE_SWITCH_STACK
376
377         rts
378 ENDPROC(__switch_to)