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