xref: /openbmc/linux/arch/csky/kernel/entry.S (revision 7ae9fb1b7ecbb5d85d07857943f677fd1a559b18)
1081860b9SGuo Ren/* SPDX-License-Identifier: GPL-2.0 */
2081860b9SGuo Ren// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
3081860b9SGuo Ren
4081860b9SGuo Ren#include <linux/linkage.h>
5081860b9SGuo Ren#include <abi/entry.h>
6081860b9SGuo Ren#include <abi/pgtable-bits.h>
7081860b9SGuo Ren#include <asm/errno.h>
8081860b9SGuo Ren#include <asm/setup.h>
9081860b9SGuo Ren#include <asm/unistd.h>
10081860b9SGuo Ren#include <asm/asm-offsets.h>
11081860b9SGuo Ren#include <linux/threads.h>
12081860b9SGuo Ren#include <asm/page.h>
13081860b9SGuo Ren#include <asm/thread_info.h>
14081860b9SGuo Ren
1548ede51fSGuo Ren.macro	zero_fp
1648ede51fSGuo Ren#ifdef CONFIG_STACKTRACE
1748ede51fSGuo Ren	movi	r8, 0
1848ede51fSGuo Ren#endif
1948ede51fSGuo Ren.endm
2048ede51fSGuo Ren
21bdcd93efSGuo Ren.macro	context_tracking
2224a9c541SFrederic Weisbecker#ifdef CONFIG_CONTEXT_TRACKING_USER
23bdcd93efSGuo Ren	mfcr	a0, epsr
24bdcd93efSGuo Ren	btsti	a0, 31
25bdcd93efSGuo Ren	bt	1f
26f163f030SFrederic Weisbecker	jbsr	user_exit_callable
27bdcd93efSGuo Ren	ldw	a0, (sp, LSAVE_A0)
28bdcd93efSGuo Ren	ldw	a1, (sp, LSAVE_A1)
29bdcd93efSGuo Ren	ldw	a2, (sp, LSAVE_A2)
30bdcd93efSGuo Ren	ldw	a3, (sp, LSAVE_A3)
31bdcd93efSGuo Ren#if defined(__CSKYABIV1__)
32bdcd93efSGuo Ren	ldw	r6, (sp, LSAVE_A4)
33bdcd93efSGuo Ren	ldw	r7, (sp, LSAVE_A5)
34bdcd93efSGuo Ren#endif
35bdcd93efSGuo Ren1:
36bdcd93efSGuo Ren#endif
37bdcd93efSGuo Ren.endm
38bdcd93efSGuo Ren
39b0ae5e26SGuo Ren.text
40b0ae5e26SGuo RenENTRY(csky_pagefault)
41bf241682SGuo Ren	SAVE_ALL 0
4248ede51fSGuo Ren	zero_fp
43bdcd93efSGuo Ren	context_tracking
440f7e8efaSGuo Ren	psrset  ee
45081860b9SGuo Ren	mov     a0, sp
46081860b9SGuo Ren	jbsr    do_page_fault
47081860b9SGuo Ren	jmpi    ret_from_exception
48081860b9SGuo Ren
49081860b9SGuo RenENTRY(csky_systemcall)
50bf241682SGuo Ren	SAVE_ALL TRAP0_SIZE
5148ede51fSGuo Ren	zero_fp
52bdcd93efSGuo Ren	context_tracking
53081860b9SGuo Ren	psrset  ee, ie
54081860b9SGuo Ren
5520f69538SGuo Ren	lrw     r9, __NR_syscalls
5620f69538SGuo Ren	cmphs   syscallid, r9		/* Check nr of syscall */
57*c5e7ee72SMathieu Desnoyers	bt      ret_from_exception
58081860b9SGuo Ren
5920f69538SGuo Ren	lrw     r9, sys_call_table
6020f69538SGuo Ren	ixw     r9, syscallid
6120f69538SGuo Ren	ldw     syscallid, (r9)
6220f69538SGuo Ren	cmpnei  syscallid, 0
63081860b9SGuo Ren	bf      ret_from_exception
64081860b9SGuo Ren
65081860b9SGuo Ren	mov     r9, sp
66081860b9SGuo Ren	bmaski  r10, THREAD_SHIFT
67081860b9SGuo Ren	andn    r9, r10
6820f69538SGuo Ren	ldw     r10, (r9, TINFO_FLAGS)
6920f69538SGuo Ren	lrw	r9, _TIF_SYSCALL_WORK
7020f69538SGuo Ren	and	r10, r9
7120f69538SGuo Ren	cmpnei	r10, 0
722f7932b0SGuo Ren	bt      csky_syscall_trace
73081860b9SGuo Ren#if defined(__CSKYABIV2__)
74081860b9SGuo Ren	subi    sp, 8
75081860b9SGuo Ren	stw  	r5, (sp, 0x4)
76081860b9SGuo Ren	stw  	r4, (sp, 0x0)
7720f69538SGuo Ren	jsr     syscallid                      /* Do system call */
78081860b9SGuo Ren	addi 	sp, 8
79081860b9SGuo Ren#else
8020f69538SGuo Ren	jsr     syscallid
81081860b9SGuo Ren#endif
82081860b9SGuo Ren	stw     a0, (sp, LSAVE_A0)      /* Save return value */
83081860b9SGuo Ren	jmpi    ret_from_exception
84081860b9SGuo Ren
852f7932b0SGuo Rencsky_syscall_trace:
862f7932b0SGuo Ren	mov	a0, sp                  /* sp = pt_regs pointer */
872f7932b0SGuo Ren	jbsr	syscall_trace_enter
88e95a4f8cSGuo Ren	cmpnei	a0, 0
89e95a4f8cSGuo Ren	bt	1f
90081860b9SGuo Ren	/* Prepare args before do system call */
91081860b9SGuo Ren	ldw	a0, (sp, LSAVE_A0)
92081860b9SGuo Ren	ldw	a1, (sp, LSAVE_A1)
93081860b9SGuo Ren	ldw	a2, (sp, LSAVE_A2)
94081860b9SGuo Ren	ldw	a3, (sp, LSAVE_A3)
95081860b9SGuo Ren#if defined(__CSKYABIV2__)
96081860b9SGuo Ren	subi	sp, 8
97e0bbb538SGuo Ren	ldw	r9, (sp, LSAVE_A4)
98e0bbb538SGuo Ren	stw	r9, (sp, 0x0)
99e0bbb538SGuo Ren	ldw	r9, (sp, LSAVE_A5)
100e0bbb538SGuo Ren	stw	r9, (sp, 0x4)
10120f69538SGuo Ren	jsr	syscallid                     /* Do system call */
10220f69538SGuo Ren	addi	sp, 8
103081860b9SGuo Ren#else
104081860b9SGuo Ren	ldw	r6, (sp, LSAVE_A4)
105081860b9SGuo Ren	ldw	r7, (sp, LSAVE_A5)
10620f69538SGuo Ren	jsr	syscallid                     /* Do system call */
107081860b9SGuo Ren#endif
108081860b9SGuo Ren	stw	a0, (sp, LSAVE_A0)	/* Save return value */
109081860b9SGuo Ren
110e95a4f8cSGuo Ren1:
1112f7932b0SGuo Ren	mov     a0, sp                  /* right now, sp --> pt_regs */
1122f7932b0SGuo Ren	jbsr    syscall_trace_exit
11331295a72SGuo Ren	br	ret_from_exception
114081860b9SGuo Ren
115081860b9SGuo RenENTRY(ret_from_kernel_thread)
116081860b9SGuo Ren	jbsr	schedule_tail
11748ede51fSGuo Ren	mov	a0, r10
118081860b9SGuo Ren	jsr	r9
119081860b9SGuo Ren	jbsr	ret_from_exception
120081860b9SGuo Ren
121081860b9SGuo RenENTRY(ret_from_fork)
122081860b9SGuo Ren	jbsr	schedule_tail
123081860b9SGuo Ren	mov	r9, sp
124081860b9SGuo Ren	bmaski	r10, THREAD_SHIFT
125081860b9SGuo Ren	andn	r9, r10
12620f69538SGuo Ren	ldw	r10, (r9, TINFO_FLAGS)
12720f69538SGuo Ren	lrw	r9, _TIF_SYSCALL_WORK
12820f69538SGuo Ren	and	r10, r9
12920f69538SGuo Ren	cmpnei	r10, 0
130bf241682SGuo Ren	bf	ret_from_exception
1312f7932b0SGuo Ren	mov	a0, sp			/* sp = pt_regs pointer */
1322f7932b0SGuo Ren	jbsr	syscall_trace_exit
133081860b9SGuo Ren
134081860b9SGuo Renret_from_exception:
13590089759SGuo Ren	psrclr	ie
13620f69538SGuo Ren	ld	r9, (sp, LSAVE_PSR)
13720f69538SGuo Ren	btsti	r9, 31
138081860b9SGuo Ren
13920f69538SGuo Ren	bt	1f
140081860b9SGuo Ren	/*
141081860b9SGuo Ren	 * Load address of current->thread_info, Then get address of task_struct
142081860b9SGuo Ren	 * Get task_needreshed in task_struct
143081860b9SGuo Ren	 */
144081860b9SGuo Ren	mov	r9, sp
145081860b9SGuo Ren	bmaski	r10, THREAD_SHIFT
146081860b9SGuo Ren	andn	r9, r10
147081860b9SGuo Ren
14820f69538SGuo Ren	ldw	r10, (r9, TINFO_FLAGS)
14920f69538SGuo Ren	lrw	r9, _TIF_WORK_MASK
15020f69538SGuo Ren	and	r10, r9
15120f69538SGuo Ren	cmpnei	r10, 0
152081860b9SGuo Ren	bt	exit_work
15324a9c541SFrederic Weisbecker#ifdef CONFIG_CONTEXT_TRACKING_USER
154f163f030SFrederic Weisbecker	jbsr	user_enter_callable
155bdcd93efSGuo Ren#endif
156bf241682SGuo Ren1:
15790089759SGuo Ren#ifdef CONFIG_PREEMPTION
15820f69538SGuo Ren	mov	r9, sp
15920f69538SGuo Ren	bmaski	r10, THREAD_SHIFT
16020f69538SGuo Ren	andn	r9, r10
16120f69538SGuo Ren
16220f69538SGuo Ren	ldw	r10, (r9, TINFO_PREEMPT)
16320f69538SGuo Ren	cmpnei	r10, 0
16490089759SGuo Ren	bt	2f
16590089759SGuo Ren	jbsr	preempt_schedule_irq	/* irq en/disable is done inside */
16690089759SGuo Ren2:
16790089759SGuo Ren#endif
16890089759SGuo Ren
169000591f1SGuo Ren#ifdef CONFIG_TRACE_IRQFLAGS
170000591f1SGuo Ren	ld	r10, (sp, LSAVE_PSR)
171000591f1SGuo Ren	btsti	r10, 6
172000591f1SGuo Ren	bf	2f
173000591f1SGuo Ren	jbsr	trace_hardirqs_on
174000591f1SGuo Ren2:
175000591f1SGuo Ren#endif
176bf241682SGuo Ren	RESTORE_ALL
177081860b9SGuo Ren
178081860b9SGuo Renexit_work:
17920f69538SGuo Ren	lrw	r9, ret_from_exception
18020f69538SGuo Ren	mov	lr, r9
181bf241682SGuo Ren
18220f69538SGuo Ren	btsti	r10, TIF_NEED_RESCHED
183081860b9SGuo Ren	bt	work_resched
184bf241682SGuo Ren
18590089759SGuo Ren	psrset	ie
186bf241682SGuo Ren	mov	a0, sp
18720f69538SGuo Ren	mov	a1, r10
188bf241682SGuo Ren	jmpi	do_notify_resume
189081860b9SGuo Ren
190081860b9SGuo Renwork_resched:
191081860b9SGuo Ren	jmpi	schedule
192081860b9SGuo Ren
193081860b9SGuo RenENTRY(csky_trap)
194bf241682SGuo Ren	SAVE_ALL 0
19548ede51fSGuo Ren	zero_fp
196bdcd93efSGuo Ren	context_tracking
197081860b9SGuo Ren	psrset	ee
198081860b9SGuo Ren	mov	a0, sp                 /* Push Stack pointer arg */
199081860b9SGuo Ren	jbsr	trap_c                 /* Call C-level trap handler */
200081860b9SGuo Ren	jmpi	ret_from_exception
201081860b9SGuo Ren
202081860b9SGuo Ren/*
203081860b9SGuo Ren * Prototype from libc for abiv1:
204081860b9SGuo Ren * register unsigned int __result asm("a0");
205081860b9SGuo Ren * asm( "trap 3" :"=r"(__result)::);
206081860b9SGuo Ren */
207081860b9SGuo RenENTRY(csky_get_tls)
208081860b9SGuo Ren	USPTOKSP
209081860b9SGuo Ren
2100c8a32eeSGuo Ren	RD_MEH	a0
2110c8a32eeSGuo Ren	WR_MEH	a0
2120c8a32eeSGuo Ren
213081860b9SGuo Ren	/* increase epc for continue */
214081860b9SGuo Ren	mfcr	a0, epc
215bf241682SGuo Ren	addi	a0, TRAP0_SIZE
216081860b9SGuo Ren	mtcr	a0, epc
217081860b9SGuo Ren
218081860b9SGuo Ren	/* get current task thread_info with kernel 8K stack */
219081860b9SGuo Ren	bmaski	a0, THREAD_SHIFT
220081860b9SGuo Ren	not	a0
221081860b9SGuo Ren	subi	sp, 1
222081860b9SGuo Ren	and	a0, sp
223081860b9SGuo Ren	addi	sp, 1
224081860b9SGuo Ren
225081860b9SGuo Ren	/* get tls */
226081860b9SGuo Ren	ldw	a0, (a0, TINFO_TP_VALUE)
227081860b9SGuo Ren
228081860b9SGuo Ren	KSPTOUSP
229081860b9SGuo Ren	rte
230081860b9SGuo Ren
231081860b9SGuo RenENTRY(csky_irq)
232bf241682SGuo Ren	SAVE_ALL 0
23348ede51fSGuo Ren	zero_fp
234bdcd93efSGuo Ren	context_tracking
235081860b9SGuo Ren	psrset	ee
236081860b9SGuo Ren
237000591f1SGuo Ren#ifdef CONFIG_TRACE_IRQFLAGS
238000591f1SGuo Ren	jbsr	trace_hardirqs_off
239000591f1SGuo Ren#endif
240000591f1SGuo Ren
241081860b9SGuo Ren
242081860b9SGuo Ren	mov	a0, sp
24328723298SMark Rutland	jbsr	generic_handle_arch_irq
244081860b9SGuo Ren
245081860b9SGuo Ren	jmpi	ret_from_exception
246081860b9SGuo Ren
247081860b9SGuo Ren/*
248081860b9SGuo Ren * a0 =  prev task_struct *
249081860b9SGuo Ren * a1 =  next task_struct *
250081860b9SGuo Ren * a0 =  return next
251081860b9SGuo Ren */
252081860b9SGuo RenENTRY(__switch_to)
253081860b9SGuo Ren	lrw	a3, TASK_THREAD
254081860b9SGuo Ren	addu	a3, a0
255081860b9SGuo Ren
256081860b9SGuo Ren	SAVE_SWITCH_STACK
257081860b9SGuo Ren
258081860b9SGuo Ren	stw	sp, (a3, THREAD_KSP)
259081860b9SGuo Ren
260081860b9SGuo Ren	/* Set up next process to run */
261081860b9SGuo Ren	lrw	a3, TASK_THREAD
262081860b9SGuo Ren	addu	a3, a1
263081860b9SGuo Ren
264081860b9SGuo Ren	ldw	sp, (a3, THREAD_KSP)	/* Set next kernel sp */
265081860b9SGuo Ren
266081860b9SGuo Ren#if  defined(__CSKYABIV2__)
2679e2ca153SGuo Ren	addi	a3, a1, TASK_THREAD_INFO
2689e2ca153SGuo Ren	ldw	tls, (a3, TINFO_TP_VALUE)
269081860b9SGuo Ren#endif
270081860b9SGuo Ren
271081860b9SGuo Ren	RESTORE_SWITCH_STACK
272081860b9SGuo Ren
273081860b9SGuo Ren	rts
274081860b9SGuo RenENDPROC(__switch_to)
275