xref: /linux/arch/csky/kernel/entry.S (revision 00f5764dbb040188e5dce2cd9e648360886b045c)
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/setup.h>
13081860b9SGuo Ren#include <asm/page.h>
14081860b9SGuo Ren#include <asm/thread_info.h>
15081860b9SGuo Ren
16081860b9SGuo Ren#define PTE_INDX_MSK    0xffc
17081860b9SGuo Ren#define PTE_INDX_SHIFT  10
18081860b9SGuo Ren#define _PGDIR_SHIFT    22
19081860b9SGuo Ren
20081860b9SGuo Ren.macro tlbop_begin name, val0, val1, val2
21081860b9SGuo RenENTRY(csky_\name)
22081860b9SGuo Ren	mtcr    a3, ss2
23081860b9SGuo Ren	mtcr    r6, ss3
24081860b9SGuo Ren	mtcr    a2, ss4
25081860b9SGuo Ren
26081860b9SGuo Ren	RD_PGDR	r6
27081860b9SGuo Ren	RD_MEH	a3
28081860b9SGuo Ren#ifdef CONFIG_CPU_HAS_TLBI
29081860b9SGuo Ren	tlbi.vaas a3
30081860b9SGuo Ren	sync.is
31081860b9SGuo Ren
32081860b9SGuo Ren	btsti	a3, 31
33081860b9SGuo Ren	bf	1f
34081860b9SGuo Ren	RD_PGDR_K r6
35081860b9SGuo Ren1:
36081860b9SGuo Ren#else
37081860b9SGuo Ren	bgeni	a2, 31
38081860b9SGuo Ren	WR_MCIR	a2
39081860b9SGuo Ren	bgeni	a2, 25
40081860b9SGuo Ren	WR_MCIR	a2
41081860b9SGuo Ren#endif
42081860b9SGuo Ren	bclri   r6, 0
43*683fafebSGuo Ren	lrw	a2, va_pa_offset
44f62e3162SGuo Ren	ld.w	a2, (a2, 0)
45081860b9SGuo Ren	subu	r6, a2
46081860b9SGuo Ren	bseti	r6, 31
47081860b9SGuo Ren
48081860b9SGuo Ren	mov     a2, a3
49081860b9SGuo Ren	lsri    a2, _PGDIR_SHIFT
50081860b9SGuo Ren	lsli    a2, 2
51081860b9SGuo Ren	addu    r6, a2
52081860b9SGuo Ren	ldw     r6, (r6)
53081860b9SGuo Ren
54*683fafebSGuo Ren	lrw	a2, va_pa_offset
55f62e3162SGuo Ren	ld.w	a2, (a2, 0)
56081860b9SGuo Ren	subu	r6, a2
57081860b9SGuo Ren	bseti	r6, 31
58081860b9SGuo Ren
59081860b9SGuo Ren	lsri    a3, PTE_INDX_SHIFT
60081860b9SGuo Ren	lrw     a2, PTE_INDX_MSK
61081860b9SGuo Ren	and     a3, a2
62081860b9SGuo Ren	addu    r6, a3
63081860b9SGuo Ren	ldw     a3, (r6)
64081860b9SGuo Ren
65081860b9SGuo Ren	movi	a2, (_PAGE_PRESENT | \val0)
66081860b9SGuo Ren	and     a3, a2
67081860b9SGuo Ren	cmpne   a3, a2
68081860b9SGuo Ren	bt	\name
69081860b9SGuo Ren
70081860b9SGuo Ren	/* First read/write the page, just update the flags */
71081860b9SGuo Ren	ldw     a3, (r6)
72081860b9SGuo Ren	bgeni   a2, PAGE_VALID_BIT
73081860b9SGuo Ren	bseti   a2, PAGE_ACCESSED_BIT
74081860b9SGuo Ren	bseti   a2, \val1
75081860b9SGuo Ren	bseti   a2, \val2
76081860b9SGuo Ren	or      a3, a2
77081860b9SGuo Ren	stw     a3, (r6)
78081860b9SGuo Ren
79081860b9SGuo Ren	/* Some cpu tlb-hardrefill bypass the cache */
80081860b9SGuo Ren#ifdef CONFIG_CPU_NEED_TLBSYNC
81081860b9SGuo Ren	movi	a2, 0x22
82081860b9SGuo Ren	bseti	a2, 6
83081860b9SGuo Ren	mtcr	r6, cr22
84081860b9SGuo Ren	mtcr	a2, cr17
85081860b9SGuo Ren	sync
86081860b9SGuo Ren#endif
87081860b9SGuo Ren
88081860b9SGuo Ren	mfcr    a3, ss2
89081860b9SGuo Ren	mfcr    r6, ss3
90081860b9SGuo Ren	mfcr    a2, ss4
91081860b9SGuo Ren	rte
92081860b9SGuo Ren\name:
93081860b9SGuo Ren	mfcr    a3, ss2
94081860b9SGuo Ren	mfcr    r6, ss3
95081860b9SGuo Ren	mfcr    a2, ss4
96bf241682SGuo Ren	SAVE_ALL 0
97081860b9SGuo Ren.endm
98081860b9SGuo Ren.macro tlbop_end is_write
99081860b9SGuo Ren	RD_MEH	a2
100081860b9SGuo Ren	psrset  ee, ie
101081860b9SGuo Ren	mov     a0, sp
102081860b9SGuo Ren	movi    a1, \is_write
103081860b9SGuo Ren	jbsr    do_page_fault
104081860b9SGuo Ren	jmpi    ret_from_exception
105081860b9SGuo Ren.endm
106081860b9SGuo Ren
107081860b9SGuo Ren.text
108081860b9SGuo Ren
109081860b9SGuo Rentlbop_begin tlbinvalidl, _PAGE_READ, PAGE_VALID_BIT, PAGE_ACCESSED_BIT
110081860b9SGuo Rentlbop_end 0
111081860b9SGuo Ren
112081860b9SGuo Rentlbop_begin tlbinvalids, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT
113081860b9SGuo Rentlbop_end 1
114081860b9SGuo Ren
115081860b9SGuo Rentlbop_begin tlbmodified, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT
116081860b9SGuo Ren#ifndef CONFIG_CPU_HAS_LDSTEX
117081860b9SGuo Renjbsr csky_cmpxchg_fixup
118081860b9SGuo Ren#endif
119081860b9SGuo Rentlbop_end 1
120081860b9SGuo Ren
121081860b9SGuo RenENTRY(csky_systemcall)
122bf241682SGuo Ren	SAVE_ALL TRAP0_SIZE
123081860b9SGuo Ren
124081860b9SGuo Ren	psrset  ee, ie
125081860b9SGuo Ren
126081860b9SGuo Ren	lrw     r11, __NR_syscalls
127081860b9SGuo Ren	cmphs   syscallid, r11		/* Check nr of syscall */
128081860b9SGuo Ren	bt      ret_from_exception
129081860b9SGuo Ren
130081860b9SGuo Ren	lrw     r13, sys_call_table
131081860b9SGuo Ren	ixw     r13, syscallid
132081860b9SGuo Ren	ldw     r11, (r13)
133081860b9SGuo Ren	cmpnei  r11, 0
134081860b9SGuo Ren	bf      ret_from_exception
135081860b9SGuo Ren
136081860b9SGuo Ren	mov     r9, sp
137081860b9SGuo Ren	bmaski  r10, THREAD_SHIFT
138081860b9SGuo Ren	andn    r9, r10
139081860b9SGuo Ren	ldw     r8, (r9, TINFO_FLAGS)
1402f7932b0SGuo Ren	ANDI_R3	r8, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT)
1412f7932b0SGuo Ren	cmpnei	r8, 0
1422f7932b0SGuo Ren	bt      csky_syscall_trace
143081860b9SGuo Ren#if defined(__CSKYABIV2__)
144081860b9SGuo Ren	subi    sp, 8
145081860b9SGuo Ren	stw  	r5, (sp, 0x4)
146081860b9SGuo Ren	stw  	r4, (sp, 0x0)
147081860b9SGuo Ren	jsr     r11                      /* Do system call */
148081860b9SGuo Ren	addi 	sp, 8
149081860b9SGuo Ren#else
150081860b9SGuo Ren	jsr     r11
151081860b9SGuo Ren#endif
152081860b9SGuo Ren	stw     a0, (sp, LSAVE_A0)      /* Save return value */
153081860b9SGuo Ren	jmpi    ret_from_exception
154081860b9SGuo Ren
1552f7932b0SGuo Rencsky_syscall_trace:
1562f7932b0SGuo Ren	mov	a0, sp                  /* sp = pt_regs pointer */
1572f7932b0SGuo Ren	jbsr	syscall_trace_enter
158081860b9SGuo Ren	/* Prepare args before do system call */
159081860b9SGuo Ren	ldw	a0, (sp, LSAVE_A0)
160081860b9SGuo Ren	ldw	a1, (sp, LSAVE_A1)
161081860b9SGuo Ren	ldw	a2, (sp, LSAVE_A2)
162081860b9SGuo Ren	ldw	a3, (sp, LSAVE_A3)
163081860b9SGuo Ren#if defined(__CSKYABIV2__)
164081860b9SGuo Ren	subi	sp, 8
165081860b9SGuo Ren	stw	r5, (sp, 0x4)
166081860b9SGuo Ren	stw	r4, (sp, 0x0)
167081860b9SGuo Ren#else
168081860b9SGuo Ren	ldw	r6, (sp, LSAVE_A4)
169081860b9SGuo Ren	ldw	r7, (sp, LSAVE_A5)
170081860b9SGuo Ren#endif
171081860b9SGuo Ren	jsr	r11                     /* Do system call */
172081860b9SGuo Ren#if defined(__CSKYABIV2__)
173081860b9SGuo Ren	addi	sp, 8
174081860b9SGuo Ren#endif
175081860b9SGuo Ren	stw	a0, (sp, LSAVE_A0)	/* Save return value */
176081860b9SGuo Ren
1772f7932b0SGuo Ren	mov     a0, sp                  /* right now, sp --> pt_regs */
1782f7932b0SGuo Ren	jbsr    syscall_trace_exit
17931295a72SGuo Ren	br	ret_from_exception
180081860b9SGuo Ren
181081860b9SGuo RenENTRY(ret_from_kernel_thread)
182081860b9SGuo Ren	jbsr	schedule_tail
183081860b9SGuo Ren	mov	a0, r8
184081860b9SGuo Ren	jsr	r9
185081860b9SGuo Ren	jbsr	ret_from_exception
186081860b9SGuo Ren
187081860b9SGuo RenENTRY(ret_from_fork)
188081860b9SGuo Ren	jbsr	schedule_tail
189081860b9SGuo Ren	mov	r9, sp
190081860b9SGuo Ren	bmaski	r10, THREAD_SHIFT
191081860b9SGuo Ren	andn	r9, r10
192081860b9SGuo Ren	ldw	r8, (r9, TINFO_FLAGS)
1932f7932b0SGuo Ren	ANDI_R3	r8, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT)
1942f7932b0SGuo Ren	cmpnei	r8, 0
195bf241682SGuo Ren	bf	ret_from_exception
1962f7932b0SGuo Ren	mov	a0, sp			/* sp = pt_regs pointer */
1972f7932b0SGuo Ren	jbsr	syscall_trace_exit
198081860b9SGuo Ren
199081860b9SGuo Renret_from_exception:
200081860b9SGuo Ren	ld	syscallid, (sp, LSAVE_PSR)
201081860b9SGuo Ren	btsti	syscallid, 31
202081860b9SGuo Ren	bt	1f
203081860b9SGuo Ren
204081860b9SGuo Ren	/*
205081860b9SGuo Ren	 * Load address of current->thread_info, Then get address of task_struct
206081860b9SGuo Ren	 * Get task_needreshed in task_struct
207081860b9SGuo Ren	 */
208081860b9SGuo Ren	mov	r9, sp
209081860b9SGuo Ren	bmaski	r10, THREAD_SHIFT
210081860b9SGuo Ren	andn	r9, r10
211081860b9SGuo Ren
212081860b9SGuo Ren	ldw	r8, (r9, TINFO_FLAGS)
213081860b9SGuo Ren	andi	r8, (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED)
214081860b9SGuo Ren	cmpnei	r8, 0
215081860b9SGuo Ren	bt	exit_work
216bf241682SGuo Ren1:
217bf241682SGuo Ren	RESTORE_ALL
218081860b9SGuo Ren
219081860b9SGuo Renexit_work:
220bf241682SGuo Ren	lrw	syscallid, ret_from_exception
221bf241682SGuo Ren	mov	lr, syscallid
222bf241682SGuo Ren
223081860b9SGuo Ren	btsti	r8, TIF_NEED_RESCHED
224081860b9SGuo Ren	bt	work_resched
225bf241682SGuo Ren
226bf241682SGuo Ren	mov	a0, sp
227bf241682SGuo Ren	mov	a1, r8
228bf241682SGuo Ren	jmpi	do_notify_resume
229081860b9SGuo Ren
230081860b9SGuo Renwork_resched:
231081860b9SGuo Ren	jmpi	schedule
232081860b9SGuo Ren
233081860b9SGuo RenENTRY(csky_trap)
234bf241682SGuo Ren	SAVE_ALL 0
235081860b9SGuo Ren	psrset	ee
236081860b9SGuo Ren	mov	a0, sp                 /* Push Stack pointer arg */
237081860b9SGuo Ren	jbsr	trap_c                 /* Call C-level trap handler */
238081860b9SGuo Ren	jmpi	ret_from_exception
239081860b9SGuo Ren
240081860b9SGuo Ren/*
241081860b9SGuo Ren * Prototype from libc for abiv1:
242081860b9SGuo Ren * register unsigned int __result asm("a0");
243081860b9SGuo Ren * asm( "trap 3" :"=r"(__result)::);
244081860b9SGuo Ren */
245081860b9SGuo RenENTRY(csky_get_tls)
246081860b9SGuo Ren	USPTOKSP
247081860b9SGuo Ren
248081860b9SGuo Ren	/* increase epc for continue */
249081860b9SGuo Ren	mfcr	a0, epc
250bf241682SGuo Ren	addi	a0, TRAP0_SIZE
251081860b9SGuo Ren	mtcr	a0, epc
252081860b9SGuo Ren
253081860b9SGuo Ren	/* get current task thread_info with kernel 8K stack */
254081860b9SGuo Ren	bmaski	a0, THREAD_SHIFT
255081860b9SGuo Ren	not	a0
256081860b9SGuo Ren	subi	sp, 1
257081860b9SGuo Ren	and	a0, sp
258081860b9SGuo Ren	addi	sp, 1
259081860b9SGuo Ren
260081860b9SGuo Ren	/* get tls */
261081860b9SGuo Ren	ldw	a0, (a0, TINFO_TP_VALUE)
262081860b9SGuo Ren
263081860b9SGuo Ren	KSPTOUSP
264081860b9SGuo Ren	rte
265081860b9SGuo Ren
266081860b9SGuo RenENTRY(csky_irq)
267bf241682SGuo Ren	SAVE_ALL 0
268081860b9SGuo Ren	psrset	ee
269081860b9SGuo Ren
270081860b9SGuo Ren#ifdef CONFIG_PREEMPT
271081860b9SGuo Ren	mov	r9, sp			/* Get current stack  pointer */
272081860b9SGuo Ren	bmaski	r10, THREAD_SHIFT
273081860b9SGuo Ren	andn	r9, r10			/* Get thread_info */
274081860b9SGuo Ren
275081860b9SGuo Ren	/*
276081860b9SGuo Ren	 * Get task_struct->stack.preempt_count for current,
277081860b9SGuo Ren	 * and increase 1.
278081860b9SGuo Ren	 */
279081860b9SGuo Ren	ldw	r8, (r9, TINFO_PREEMPT)
280081860b9SGuo Ren	addi	r8, 1
281081860b9SGuo Ren	stw	r8, (r9, TINFO_PREEMPT)
282081860b9SGuo Ren#endif
283081860b9SGuo Ren
284081860b9SGuo Ren	mov	a0, sp
285081860b9SGuo Ren	jbsr	csky_do_IRQ
286081860b9SGuo Ren
287081860b9SGuo Ren#ifdef CONFIG_PREEMPT
288081860b9SGuo Ren	subi	r8, 1
289081860b9SGuo Ren	stw	r8, (r9, TINFO_PREEMPT)
290081860b9SGuo Ren	cmpnei	r8, 0
291081860b9SGuo Ren	bt	2f
292081860b9SGuo Ren	ldw	r8, (r9, TINFO_FLAGS)
293081860b9SGuo Ren	btsti	r8, TIF_NEED_RESCHED
294081860b9SGuo Ren	bf	2f
295081860b9SGuo Ren1:
296081860b9SGuo Ren	jbsr	preempt_schedule_irq	/* irq en/disable is done inside */
297081860b9SGuo Ren	ldw	r7, (r9, TINFO_FLAGS)	/* get new tasks TI_FLAGS */
298081860b9SGuo Ren	btsti	r7, TIF_NEED_RESCHED
299081860b9SGuo Ren	bt	1b			/* go again */
300081860b9SGuo Ren#endif
301081860b9SGuo Ren2:
302081860b9SGuo Ren	jmpi	ret_from_exception
303081860b9SGuo Ren
304081860b9SGuo Ren/*
305081860b9SGuo Ren * a0 =  prev task_struct *
306081860b9SGuo Ren * a1 =  next task_struct *
307081860b9SGuo Ren * a0 =  return next
308081860b9SGuo Ren */
309081860b9SGuo RenENTRY(__switch_to)
310081860b9SGuo Ren	lrw	a3, TASK_THREAD
311081860b9SGuo Ren	addu	a3, a0
312081860b9SGuo Ren
313081860b9SGuo Ren	mfcr	a2, psr			/* Save PSR value */
314081860b9SGuo Ren	stw	a2, (a3, THREAD_SR)	/* Save PSR in task struct */
315081860b9SGuo Ren	bclri	a2, 6			/* Disable interrupts */
316081860b9SGuo Ren	mtcr	a2, psr
317081860b9SGuo Ren
318081860b9SGuo Ren	SAVE_SWITCH_STACK
319081860b9SGuo Ren
320081860b9SGuo Ren	stw	sp, (a3, THREAD_KSP)
321081860b9SGuo Ren
322081860b9SGuo Ren	/* Set up next process to run */
323081860b9SGuo Ren	lrw	a3, TASK_THREAD
324081860b9SGuo Ren	addu	a3, a1
325081860b9SGuo Ren
326081860b9SGuo Ren	ldw	sp, (a3, THREAD_KSP)	/* Set next kernel sp */
327081860b9SGuo Ren
328081860b9SGuo Ren	ldw	a2, (a3, THREAD_SR)	/* Set next PSR */
329081860b9SGuo Ren	mtcr	a2, psr
330081860b9SGuo Ren
331081860b9SGuo Ren#if  defined(__CSKYABIV2__)
332081860b9SGuo Ren	addi	r7, a1, TASK_THREAD_INFO
333081860b9SGuo Ren	ldw	tls, (r7, TINFO_TP_VALUE)
334081860b9SGuo Ren#endif
335081860b9SGuo Ren
336081860b9SGuo Ren	RESTORE_SWITCH_STACK
337081860b9SGuo Ren
338081860b9SGuo Ren	rts
339081860b9SGuo RenENDPROC(__switch_to)
340