a7e84ccccbd8ee47ff0cdba63b4f5a6f4c647fed
[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, va_pa_offset
44         ld.w    a2, (a2, 0)
45         subu    r6, a2
46         bseti   r6, 31
47
48         mov     a2, a3
49         lsri    a2, _PGDIR_SHIFT
50         lsli    a2, 2
51         addu    r6, a2
52         ldw     r6, (r6)
53
54         lrw     a2, va_pa_offset
55         ld.w    a2, (a2, 0)
56         subu    r6, a2
57         bseti   r6, 31
58
59         lsri    a3, PTE_INDX_SHIFT
60         lrw     a2, PTE_INDX_MSK
61         and     a3, a2
62         addu    r6, a3
63         ldw     a3, (r6)
64
65         movi    a2, (_PAGE_PRESENT | \val0)
66         and     a3, a2
67         cmpne   a3, a2
68         bt      \name
69
70         /* First read/write the page, just update the flags */
71         ldw     a3, (r6)
72         bgeni   a2, PAGE_VALID_BIT
73         bseti   a2, PAGE_ACCESSED_BIT
74         bseti   a2, \val1
75         bseti   a2, \val2
76         or      a3, a2
77         stw     a3, (r6)
78
79         /* Some cpu tlb-hardrefill bypass the cache */
80 #ifdef CONFIG_CPU_NEED_TLBSYNC
81         movi    a2, 0x22
82         bseti   a2, 6
83         mtcr    r6, cr22
84         mtcr    a2, cr17
85         sync
86 #endif
87
88         mfcr    a3, ss2
89         mfcr    r6, ss3
90         mfcr    a2, ss4
91         rte
92 \name:
93         mfcr    a3, ss2
94         mfcr    r6, ss3
95         mfcr    a2, ss4
96         SAVE_ALL 0
97 .endm
98 .macro tlbop_end is_write
99         RD_MEH  a2
100         psrset  ee, ie
101         mov     a0, sp
102         movi    a1, \is_write
103         jbsr    do_page_fault
104         jmpi    ret_from_exception
105 .endm
106
107 .text
108
109 tlbop_begin tlbinvalidl, _PAGE_READ, PAGE_VALID_BIT, PAGE_ACCESSED_BIT
110 tlbop_end 0
111
112 tlbop_begin tlbinvalids, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT
113 tlbop_end 1
114
115 tlbop_begin tlbmodified, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT
116 #ifndef CONFIG_CPU_HAS_LDSTEX
117 jbsr csky_cmpxchg_fixup
118 #endif
119 tlbop_end 1
120
121 ENTRY(csky_systemcall)
122         SAVE_ALL TRAP0_SIZE
123
124         psrset  ee, ie
125
126         lrw     r11, __NR_syscalls
127         cmphs   syscallid, r11          /* Check nr of syscall */
128         bt      ret_from_exception
129
130         lrw     r13, sys_call_table
131         ixw     r13, syscallid
132         ldw     r11, (r13)
133         cmpnei  r11, 0
134         bf      ret_from_exception
135
136         mov     r9, sp
137         bmaski  r10, THREAD_SHIFT
138         andn    r9, r10
139         ldw     r8, (r9, TINFO_FLAGS)
140         ANDI_R3 r8, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT)
141         cmpnei  r8, 0
142         bt      csky_syscall_trace
143 #if defined(__CSKYABIV2__)
144         subi    sp, 8
145         stw     r5, (sp, 0x4)
146         stw     r4, (sp, 0x0)
147         jsr     r11                      /* Do system call */
148         addi    sp, 8
149 #else
150         jsr     r11
151 #endif
152         stw     a0, (sp, LSAVE_A0)      /* Save return value */
153         jmpi    ret_from_exception
154
155 csky_syscall_trace:
156         mov     a0, sp                  /* sp = pt_regs pointer */
157         jbsr    syscall_trace_enter
158         /* Prepare args before do system call */
159         ldw     a0, (sp, LSAVE_A0)
160         ldw     a1, (sp, LSAVE_A1)
161         ldw     a2, (sp, LSAVE_A2)
162         ldw     a3, (sp, LSAVE_A3)
163 #if defined(__CSKYABIV2__)
164         subi    sp, 8
165         stw     r5, (sp, 0x4)
166         stw     r4, (sp, 0x0)
167 #else
168         ldw     r6, (sp, LSAVE_A4)
169         ldw     r7, (sp, LSAVE_A5)
170 #endif
171         jsr     r11                     /* Do system call */
172 #if defined(__CSKYABIV2__)
173         addi    sp, 8
174 #endif
175         stw     a0, (sp, LSAVE_A0)      /* Save return value */
176
177         mov     a0, sp                  /* right now, sp --> pt_regs */
178         jbsr    syscall_trace_exit
179         br      ret_from_exception
180
181 ENTRY(ret_from_kernel_thread)
182         jbsr    schedule_tail
183         mov     a0, r8
184         jsr     r9
185         jbsr    ret_from_exception
186
187 ENTRY(ret_from_fork)
188         jbsr    schedule_tail
189         mov     r9, sp
190         bmaski  r10, THREAD_SHIFT
191         andn    r9, r10
192         ldw     r8, (r9, TINFO_FLAGS)
193         ANDI_R3 r8, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT)
194         cmpnei  r8, 0
195         bf      ret_from_exception
196         mov     a0, sp                  /* sp = pt_regs pointer */
197         jbsr    syscall_trace_exit
198
199 ret_from_exception:
200         ld      syscallid, (sp, LSAVE_PSR)
201         btsti   syscallid, 31
202         bt      1f
203
204         /*
205          * Load address of current->thread_info, Then get address of task_struct
206          * Get task_needreshed in task_struct
207          */
208         mov     r9, sp
209         bmaski  r10, THREAD_SHIFT
210         andn    r9, r10
211
212         ldw     r8, (r9, TINFO_FLAGS)
213         andi    r8, (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED)
214         cmpnei  r8, 0
215         bt      exit_work
216 1:
217         RESTORE_ALL
218
219 exit_work:
220         lrw     syscallid, ret_from_exception
221         mov     lr, syscallid
222
223         btsti   r8, TIF_NEED_RESCHED
224         bt      work_resched
225
226         mov     a0, sp
227         mov     a1, r8
228         jmpi    do_notify_resume
229
230 work_resched:
231         jmpi    schedule
232
233 ENTRY(csky_trap)
234         SAVE_ALL 0
235         psrset  ee
236         mov     a0, sp                 /* Push Stack pointer arg */
237         jbsr    trap_c                 /* Call C-level trap handler */
238         jmpi    ret_from_exception
239
240 /*
241  * Prototype from libc for abiv1:
242  * register unsigned int __result asm("a0");
243  * asm( "trap 3" :"=r"(__result)::);
244  */
245 ENTRY(csky_get_tls)
246         USPTOKSP
247
248         /* increase epc for continue */
249         mfcr    a0, epc
250         addi    a0, TRAP0_SIZE
251         mtcr    a0, epc
252
253         /* get current task thread_info with kernel 8K stack */
254         bmaski  a0, THREAD_SHIFT
255         not     a0
256         subi    sp, 1
257         and     a0, sp
258         addi    sp, 1
259
260         /* get tls */
261         ldw     a0, (a0, TINFO_TP_VALUE)
262
263         KSPTOUSP
264         rte
265
266 ENTRY(csky_irq)
267         SAVE_ALL 0
268         psrset  ee
269
270 #ifdef CONFIG_PREEMPT
271         mov     r9, sp                  /* Get current stack  pointer */
272         bmaski  r10, THREAD_SHIFT
273         andn    r9, r10                 /* Get thread_info */
274
275         /*
276          * Get task_struct->stack.preempt_count for current,
277          * and increase 1.
278          */
279         ldw     r8, (r9, TINFO_PREEMPT)
280         addi    r8, 1
281         stw     r8, (r9, TINFO_PREEMPT)
282 #endif
283
284         mov     a0, sp
285         jbsr    csky_do_IRQ
286
287 #ifdef CONFIG_PREEMPT
288         subi    r8, 1
289         stw     r8, (r9, TINFO_PREEMPT)
290         cmpnei  r8, 0
291         bt      2f
292         ldw     r8, (r9, TINFO_FLAGS)
293         btsti   r8, TIF_NEED_RESCHED
294         bf      2f
295 1:
296         jbsr    preempt_schedule_irq    /* irq en/disable is done inside */
297         ldw     r7, (r9, TINFO_FLAGS)   /* get new tasks TI_FLAGS */
298         btsti   r7, TIF_NEED_RESCHED
299         bt      1b                      /* go again */
300 #endif
301 2:
302         jmpi    ret_from_exception
303
304 /*
305  * a0 =  prev task_struct *
306  * a1 =  next task_struct *
307  * a0 =  return next
308  */
309 ENTRY(__switch_to)
310         lrw     a3, TASK_THREAD
311         addu    a3, a0
312
313         mfcr    a2, psr                 /* Save PSR value */
314         stw     a2, (a3, THREAD_SR)     /* Save PSR in task struct */
315         bclri   a2, 6                   /* Disable interrupts */
316         mtcr    a2, psr
317
318         SAVE_SWITCH_STACK
319
320         stw     sp, (a3, THREAD_KSP)
321
322         /* Set up next process to run */
323         lrw     a3, TASK_THREAD
324         addu    a3, a1
325
326         ldw     sp, (a3, THREAD_KSP)    /* Set next kernel sp */
327
328         ldw     a2, (a3, THREAD_SR)     /* Set next PSR */
329         mtcr    a2, psr
330
331 #if  defined(__CSKYABIV2__)
332         addi    r7, a1, TASK_THREAD_INFO
333         ldw     tls, (r7, TINFO_TP_VALUE)
334 #endif
335
336         RESTORE_SWITCH_STACK
337
338         rts
339 ENDPROC(__switch_to)