Merge branch 'akpm' (patches from Andrew)
[sfrench/cifs-2.6.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 tlbop_begin name, val0, val1, val2
21 ENTRY(csky_\name)
22         mtcr    a3, ss2
23         mtcr    r6, ss3
24         mtcr    a2, ss4
25
26         RD_PGDR r6
27         RD_MEH  a3
28 #ifdef CONFIG_CPU_HAS_TLBI
29         tlbi.vaas a3
30         sync.is
31
32         btsti   a3, 31
33         bf      1f
34         RD_PGDR_K r6
35 1:
36 #else
37         bgeni   a2, 31
38         WR_MCIR a2
39         bgeni   a2, 25
40         WR_MCIR a2
41 #endif
42         bclri   r6, 0
43         lrw     a2, PHYS_OFFSET
44         subu    r6, a2
45         bseti   r6, 31
46
47         mov     a2, a3
48         lsri    a2, _PGDIR_SHIFT
49         lsli    a2, 2
50         addu    r6, a2
51         ldw     r6, (r6)
52
53         lrw     a2, PHYS_OFFSET
54         subu    r6, a2
55         bseti   r6, 31
56
57         lsri    a3, PTE_INDX_SHIFT
58         lrw     a2, PTE_INDX_MSK
59         and     a3, a2
60         addu    r6, a3
61         ldw     a3, (r6)
62
63         movi    a2, (_PAGE_PRESENT | \val0)
64         and     a3, a2
65         cmpne   a3, a2
66         bt      \name
67
68         /* First read/write the page, just update the flags */
69         ldw     a3, (r6)
70         bgeni   a2, PAGE_VALID_BIT
71         bseti   a2, PAGE_ACCESSED_BIT
72         bseti   a2, \val1
73         bseti   a2, \val2
74         or      a3, a2
75         stw     a3, (r6)
76
77         /* Some cpu tlb-hardrefill bypass the cache */
78 #ifdef CONFIG_CPU_NEED_TLBSYNC
79         movi    a2, 0x22
80         bseti   a2, 6
81         mtcr    r6, cr22
82         mtcr    a2, cr17
83         sync
84 #endif
85
86         mfcr    a3, ss2
87         mfcr    r6, ss3
88         mfcr    a2, ss4
89         rte
90 \name:
91         mfcr    a3, ss2
92         mfcr    r6, ss3
93         mfcr    a2, ss4
94         SAVE_ALL EPC_KEEP
95 .endm
96 .macro tlbop_end is_write
97         RD_MEH  a2
98         psrset  ee, ie
99         mov     a0, sp
100         movi    a1, \is_write
101         jbsr    do_page_fault
102         movi    r11_sig, 0             /* r11 = 0, Not a syscall. */
103         jmpi    ret_from_exception
104 .endm
105
106 .text
107
108 tlbop_begin tlbinvalidl, _PAGE_READ, PAGE_VALID_BIT, PAGE_ACCESSED_BIT
109 tlbop_end 0
110
111 tlbop_begin tlbinvalids, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT
112 tlbop_end 1
113
114 tlbop_begin tlbmodified, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT
115 #ifndef CONFIG_CPU_HAS_LDSTEX
116 jbsr csky_cmpxchg_fixup
117 #endif
118 tlbop_end 1
119
120 ENTRY(csky_systemcall)
121         SAVE_ALL EPC_INCREASE
122
123         psrset  ee, ie
124
125         /* Stack frame for syscall, origin call set_esp0 */
126         mov     r12, sp
127
128         bmaski  r11, 13
129         andn    r12, r11
130         bgeni   r11, 9
131         addi    r11, 32
132         addu    r12, r11
133         st      sp, (r12, 0)
134
135         lrw     r11, __NR_syscalls
136         cmphs   syscallid, r11          /* Check nr of syscall */
137         bt      ret_from_exception
138
139         lrw     r13, sys_call_table
140         ixw     r13, syscallid
141         ldw     r11, (r13)
142         cmpnei  r11, 0
143         bf      ret_from_exception
144
145         mov     r9, sp
146         bmaski  r10, THREAD_SHIFT
147         andn    r9, r10
148         ldw     r8, (r9, TINFO_FLAGS)
149         btsti   r8, TIF_SYSCALL_TRACE
150         bt      1f
151 #if defined(__CSKYABIV2__)
152         subi    sp, 8
153         stw     r5, (sp, 0x4)
154         stw     r4, (sp, 0x0)
155         jsr     r11                      /* Do system call */
156         addi    sp, 8
157 #else
158         jsr     r11
159 #endif
160         stw     a0, (sp, LSAVE_A0)      /* Save return value */
161         jmpi    ret_from_exception
162
163 1:
164         movi    a0, 0                   /* enter system call */
165         mov     a1, sp                  /* sp = pt_regs pointer */
166         jbsr    syscall_trace
167         /* Prepare args before do system call */
168         ldw     a0, (sp, LSAVE_A0)
169         ldw     a1, (sp, LSAVE_A1)
170         ldw     a2, (sp, LSAVE_A2)
171         ldw     a3, (sp, LSAVE_A3)
172 #if defined(__CSKYABIV2__)
173         subi    sp, 8
174         stw     r5, (sp, 0x4)
175         stw     r4, (sp, 0x0)
176 #else
177         ldw     r6, (sp, LSAVE_A4)
178         ldw     r7, (sp, LSAVE_A5)
179 #endif
180         jsr     r11                     /* Do system call */
181 #if defined(__CSKYABIV2__)
182         addi    sp, 8
183 #endif
184         stw     a0, (sp, LSAVE_A0)      /* Save return value */
185
186         movi    a0, 1                   /* leave system call */
187         mov     a1, sp                  /* sp = pt_regs pointer */
188         jbsr    syscall_trace
189
190 syscall_exit_work:
191         ld      syscallid, (sp, LSAVE_PSR)
192         btsti   syscallid, 31
193         bt      2f
194
195         jmpi    resume_userspace
196
197 2:      RESTORE_ALL
198
199 ENTRY(ret_from_kernel_thread)
200         jbsr    schedule_tail
201         mov     a0, r8
202         jsr     r9
203         jbsr    ret_from_exception
204
205 ENTRY(ret_from_fork)
206         jbsr    schedule_tail
207         mov     r9, sp
208         bmaski  r10, THREAD_SHIFT
209         andn    r9, r10
210         ldw     r8, (r9, TINFO_FLAGS)
211         movi    r11_sig, 1
212         btsti   r8, TIF_SYSCALL_TRACE
213         bf      3f
214         movi    a0, 1
215         mov     a1, sp                  /* sp = pt_regs pointer */
216         jbsr    syscall_trace
217 3:
218         jbsr    ret_from_exception
219
220 ret_from_exception:
221         ld      syscallid, (sp, LSAVE_PSR)
222         btsti   syscallid, 31
223         bt      1f
224
225         /*
226          * Load address of current->thread_info, Then get address of task_struct
227          * Get task_needreshed in task_struct
228          */
229         mov     r9, sp
230         bmaski  r10, THREAD_SHIFT
231         andn    r9, r10
232
233 resume_userspace:
234         ldw     r8, (r9, TINFO_FLAGS)
235         andi    r8, (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED)
236         cmpnei  r8, 0
237         bt      exit_work
238 1:  RESTORE_ALL
239
240 exit_work:
241         mov     a0, sp                  /* Stack address is arg[0] */
242         jbsr    set_esp0                /* Call C level */
243         btsti   r8, TIF_NEED_RESCHED
244         bt      work_resched
245         /* If thread_info->flag is empty, RESTORE_ALL */
246         cmpnei  r8, 0
247         bf      1b
248         mov     a1, sp
249         mov     a0, r8
250         mov     a2, r11_sig             /* syscall? */
251         btsti   r8, TIF_SIGPENDING      /* delivering a signal? */
252         /* prevent further restarts(set r11 = 0) */
253         clrt    r11_sig
254         jbsr    do_notify_resume        /* do signals */
255         br      resume_userspace
256
257 work_resched:
258         lrw     syscallid, ret_from_exception
259         mov     r15, syscallid          /* Return address in link */
260         jmpi    schedule
261
262 ENTRY(sys_rt_sigreturn)
263         movi    r11_sig, 0
264         jmpi    do_rt_sigreturn
265
266 ENTRY(csky_trap)
267         SAVE_ALL EPC_KEEP
268         psrset  ee
269         movi    r11_sig, 0             /* r11 = 0, Not a syscall. */
270         mov     a0, sp                 /* Push Stack pointer arg */
271         jbsr    trap_c                 /* Call C-level trap handler */
272         jmpi    ret_from_exception
273
274 /*
275  * Prototype from libc for abiv1:
276  * register unsigned int __result asm("a0");
277  * asm( "trap 3" :"=r"(__result)::);
278  */
279 ENTRY(csky_get_tls)
280         USPTOKSP
281
282         /* increase epc for continue */
283         mfcr    a0, epc
284         INCTRAP a0
285         mtcr    a0, epc
286
287         /* get current task thread_info with kernel 8K stack */
288         bmaski  a0, THREAD_SHIFT
289         not     a0
290         subi    sp, 1
291         and     a0, sp
292         addi    sp, 1
293
294         /* get tls */
295         ldw     a0, (a0, TINFO_TP_VALUE)
296
297         KSPTOUSP
298         rte
299
300 ENTRY(csky_irq)
301         SAVE_ALL EPC_KEEP
302         psrset  ee
303         movi    r11_sig, 0              /* r11 = 0, Not a syscall. */
304
305 #ifdef CONFIG_PREEMPT
306         mov     r9, sp                  /* Get current stack  pointer */
307         bmaski  r10, THREAD_SHIFT
308         andn    r9, r10                 /* Get thread_info */
309
310         /*
311          * Get task_struct->stack.preempt_count for current,
312          * and increase 1.
313          */
314         ldw     r8, (r9, TINFO_PREEMPT)
315         addi    r8, 1
316         stw     r8, (r9, TINFO_PREEMPT)
317 #endif
318
319         mov     a0, sp
320         jbsr    csky_do_IRQ
321
322 #ifdef CONFIG_PREEMPT
323         subi    r8, 1
324         stw     r8, (r9, TINFO_PREEMPT)
325         cmpnei  r8, 0
326         bt      2f
327         ldw     r8, (r9, TINFO_FLAGS)
328         btsti   r8, TIF_NEED_RESCHED
329         bf      2f
330 1:
331         jbsr    preempt_schedule_irq    /* irq en/disable is done inside */
332         ldw     r7, (r9, TINFO_FLAGS)   /* get new tasks TI_FLAGS */
333         btsti   r7, TIF_NEED_RESCHED
334         bt      1b                      /* go again */
335 #endif
336 2:
337         jmpi    ret_from_exception
338
339 /*
340  * a0 =  prev task_struct *
341  * a1 =  next task_struct *
342  * a0 =  return next
343  */
344 ENTRY(__switch_to)
345         lrw     a3, TASK_THREAD
346         addu    a3, a0
347
348         mfcr    a2, psr                 /* Save PSR value */
349         stw     a2, (a3, THREAD_SR)     /* Save PSR in task struct */
350         bclri   a2, 6                   /* Disable interrupts */
351         mtcr    a2, psr
352
353         SAVE_SWITCH_STACK
354
355         stw     sp, (a3, THREAD_KSP)
356
357 #ifdef CONFIG_CPU_HAS_HILO
358         lrw     r10, THREAD_DSPHI
359         add     r10, a3
360         mfhi    r6
361         mflo    r7
362         stw     r6, (r10, 0)            /* THREAD_DSPHI */
363         stw     r7, (r10, 4)            /* THREAD_DSPLO */
364         mfcr    r6, cr14
365         stw     r6, (r10, 8)            /* THREAD_DSPCSR */
366 #endif
367
368         /* Set up next process to run */
369         lrw     a3, TASK_THREAD
370         addu    a3, a1
371
372         ldw     sp, (a3, THREAD_KSP)    /* Set next kernel sp */
373
374 #ifdef CONFIG_CPU_HAS_HILO
375         lrw     r10, THREAD_DSPHI
376         add     r10, a3
377         ldw     r6, (r10, 8)            /* THREAD_DSPCSR */
378         mtcr    r6, cr14
379         ldw     r6, (r10, 0)            /* THREAD_DSPHI */
380         ldw     r7, (r10, 4)            /* THREAD_DSPLO */
381         mthi    r6
382         mtlo    r7
383 #endif
384
385         ldw     a2, (a3, THREAD_SR)     /* Set next PSR */
386         mtcr    a2, psr
387
388 #if  defined(__CSKYABIV2__)
389         addi    r7, a1, TASK_THREAD_INFO
390         ldw     tls, (r7, TINFO_TP_VALUE)
391 #endif
392
393         RESTORE_SWITCH_STACK
394
395         rts
396 ENDPROC(__switch_to)