275 lines
4.9 KiB
ArmAsm
275 lines
4.9 KiB
ArmAsm
|
/* SPDX-License-Identifier: GPL-2.0 */
|
|||
|
// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
|
|||
|
|
|||
|
#include <linux/linkage.h>
|
|||
|
#include <abi/entry.h>
|
|||
|
#include <abi/pgtable-bits.h>
|
|||
|
#include <asm/errno.h>
|
|||
|
#include <asm/setup.h>
|
|||
|
#include <asm/unistd.h>
|
|||
|
#include <asm/asm-offsets.h>
|
|||
|
#include <linux/threads.h>
|
|||
|
#include <asm/page.h>
|
|||
|
#include <asm/thread_info.h>
|
|||
|
|
|||
|
.macro zero_fp
|
|||
|
#ifdef CONFIG_STACKTRACE
|
|||
|
movi r8, 0
|
|||
|
#endif
|
|||
|
.endm
|
|||
|
|
|||
|
.macro context_tracking
|
|||
|
#ifdef CONFIG_CONTEXT_TRACKING_USER
|
|||
|
mfcr a0, epsr
|
|||
|
btsti a0, 31
|
|||
|
bt 1f
|
|||
|
jbsr user_exit_callable
|
|||
|
ldw a0, (sp, LSAVE_A0)
|
|||
|
ldw a1, (sp, LSAVE_A1)
|
|||
|
ldw a2, (sp, LSAVE_A2)
|
|||
|
ldw a3, (sp, LSAVE_A3)
|
|||
|
#if defined(__CSKYABIV1__)
|
|||
|
ldw r6, (sp, LSAVE_A4)
|
|||
|
ldw r7, (sp, LSAVE_A5)
|
|||
|
#endif
|
|||
|
1:
|
|||
|
#endif
|
|||
|
.endm
|
|||
|
|
|||
|
.text
|
|||
|
ENTRY(csky_pagefault)
|
|||
|
SAVE_ALL 0
|
|||
|
zero_fp
|
|||
|
context_tracking
|
|||
|
psrset ee
|
|||
|
mov a0, sp
|
|||
|
jbsr do_page_fault
|
|||
|
jmpi ret_from_exception
|
|||
|
|
|||
|
ENTRY(csky_systemcall)
|
|||
|
SAVE_ALL TRAP0_SIZE
|
|||
|
zero_fp
|
|||
|
context_tracking
|
|||
|
psrset ee, ie
|
|||
|
|
|||
|
lrw r9, __NR_syscalls
|
|||
|
cmphs syscallid, r9 /* Check nr of syscall */
|
|||
|
bt ret_from_exception
|
|||
|
|
|||
|
lrw r9, sys_call_table
|
|||
|
ixw r9, syscallid
|
|||
|
ldw syscallid, (r9)
|
|||
|
cmpnei syscallid, 0
|
|||
|
bf ret_from_exception
|
|||
|
|
|||
|
mov r9, sp
|
|||
|
bmaski r10, THREAD_SHIFT
|
|||
|
andn r9, r10
|
|||
|
ldw r10, (r9, TINFO_FLAGS)
|
|||
|
lrw r9, _TIF_SYSCALL_WORK
|
|||
|
and r10, r9
|
|||
|
cmpnei r10, 0
|
|||
|
bt csky_syscall_trace
|
|||
|
#if defined(__CSKYABIV2__)
|
|||
|
subi sp, 8
|
|||
|
stw r5, (sp, 0x4)
|
|||
|
stw r4, (sp, 0x0)
|
|||
|
jsr syscallid /* Do system call */
|
|||
|
addi sp, 8
|
|||
|
#else
|
|||
|
jsr syscallid
|
|||
|
#endif
|
|||
|
stw a0, (sp, LSAVE_A0) /* Save return value */
|
|||
|
jmpi ret_from_exception
|
|||
|
|
|||
|
csky_syscall_trace:
|
|||
|
mov a0, sp /* sp = pt_regs pointer */
|
|||
|
jbsr syscall_trace_enter
|
|||
|
cmpnei a0, 0
|
|||
|
bt 1f
|
|||
|
/* Prepare args before do system call */
|
|||
|
ldw a0, (sp, LSAVE_A0)
|
|||
|
ldw a1, (sp, LSAVE_A1)
|
|||
|
ldw a2, (sp, LSAVE_A2)
|
|||
|
ldw a3, (sp, LSAVE_A3)
|
|||
|
#if defined(__CSKYABIV2__)
|
|||
|
subi sp, 8
|
|||
|
ldw r9, (sp, LSAVE_A4)
|
|||
|
stw r9, (sp, 0x0)
|
|||
|
ldw r9, (sp, LSAVE_A5)
|
|||
|
stw r9, (sp, 0x4)
|
|||
|
jsr syscallid /* Do system call */
|
|||
|
addi sp, 8
|
|||
|
#else
|
|||
|
ldw r6, (sp, LSAVE_A4)
|
|||
|
ldw r7, (sp, LSAVE_A5)
|
|||
|
jsr syscallid /* Do system call */
|
|||
|
#endif
|
|||
|
stw a0, (sp, LSAVE_A0) /* Save return value */
|
|||
|
|
|||
|
1:
|
|||
|
mov a0, sp /* right now, sp --> pt_regs */
|
|||
|
jbsr syscall_trace_exit
|
|||
|
br ret_from_exception
|
|||
|
|
|||
|
ENTRY(ret_from_kernel_thread)
|
|||
|
jbsr schedule_tail
|
|||
|
mov a0, r10
|
|||
|
jsr r9
|
|||
|
jbsr ret_from_exception
|
|||
|
|
|||
|
ENTRY(ret_from_fork)
|
|||
|
jbsr schedule_tail
|
|||
|
mov r9, sp
|
|||
|
bmaski r10, THREAD_SHIFT
|
|||
|
andn r9, r10
|
|||
|
ldw r10, (r9, TINFO_FLAGS)
|
|||
|
lrw r9, _TIF_SYSCALL_WORK
|
|||
|
and r10, r9
|
|||
|
cmpnei r10, 0
|
|||
|
bf ret_from_exception
|
|||
|
mov a0, sp /* sp = pt_regs pointer */
|
|||
|
jbsr syscall_trace_exit
|
|||
|
|
|||
|
ret_from_exception:
|
|||
|
psrclr ie
|
|||
|
ld r9, (sp, LSAVE_PSR)
|
|||
|
btsti r9, 31
|
|||
|
|
|||
|
bt 1f
|
|||
|
/*
|
|||
|
* Load address of current->thread_info, Then get address of task_struct
|
|||
|
* Get task_needreshed in task_struct
|
|||
|
*/
|
|||
|
mov r9, sp
|
|||
|
bmaski r10, THREAD_SHIFT
|
|||
|
andn r9, r10
|
|||
|
|
|||
|
ldw r10, (r9, TINFO_FLAGS)
|
|||
|
lrw r9, _TIF_WORK_MASK
|
|||
|
and r10, r9
|
|||
|
cmpnei r10, 0
|
|||
|
bt exit_work
|
|||
|
#ifdef CONFIG_CONTEXT_TRACKING_USER
|
|||
|
jbsr user_enter_callable
|
|||
|
#endif
|
|||
|
1:
|
|||
|
#ifdef CONFIG_PREEMPTION
|
|||
|
mov r9, sp
|
|||
|
bmaski r10, THREAD_SHIFT
|
|||
|
andn r9, r10
|
|||
|
|
|||
|
ldw r10, (r9, TINFO_PREEMPT)
|
|||
|
cmpnei r10, 0
|
|||
|
bt 2f
|
|||
|
jbsr preempt_schedule_irq /* irq en/disable is done inside */
|
|||
|
2:
|
|||
|
#endif
|
|||
|
|
|||
|
#ifdef CONFIG_TRACE_IRQFLAGS
|
|||
|
ld r10, (sp, LSAVE_PSR)
|
|||
|
btsti r10, 6
|
|||
|
bf 2f
|
|||
|
jbsr trace_hardirqs_on
|
|||
|
2:
|
|||
|
#endif
|
|||
|
RESTORE_ALL
|
|||
|
|
|||
|
exit_work:
|
|||
|
lrw r9, ret_from_exception
|
|||
|
mov lr, r9
|
|||
|
|
|||
|
btsti r10, TIF_NEED_RESCHED
|
|||
|
bt work_resched
|
|||
|
|
|||
|
psrset ie
|
|||
|
mov a0, sp
|
|||
|
mov a1, r10
|
|||
|
jmpi do_notify_resume
|
|||
|
|
|||
|
work_resched:
|
|||
|
jmpi schedule
|
|||
|
|
|||
|
ENTRY(csky_trap)
|
|||
|
SAVE_ALL 0
|
|||
|
zero_fp
|
|||
|
context_tracking
|
|||
|
psrset ee
|
|||
|
mov a0, sp /* Push Stack pointer arg */
|
|||
|
jbsr trap_c /* Call C-level trap handler */
|
|||
|
jmpi ret_from_exception
|
|||
|
|
|||
|
/*
|
|||
|
* Prototype from libc for abiv1:
|
|||
|
* register unsigned int __result asm("a0");
|
|||
|
* asm( "trap 3" :"=r"(__result)::);
|
|||
|
*/
|
|||
|
ENTRY(csky_get_tls)
|
|||
|
USPTOKSP
|
|||
|
|
|||
|
RD_MEH a0
|
|||
|
WR_MEH a0
|
|||
|
|
|||
|
/* increase epc for continue */
|
|||
|
mfcr a0, epc
|
|||
|
addi a0, TRAP0_SIZE
|
|||
|
mtcr a0, epc
|
|||
|
|
|||
|
/* get current task thread_info with kernel 8K stack */
|
|||
|
bmaski a0, THREAD_SHIFT
|
|||
|
not a0
|
|||
|
subi sp, 1
|
|||
|
and a0, sp
|
|||
|
addi sp, 1
|
|||
|
|
|||
|
/* get tls */
|
|||
|
ldw a0, (a0, TINFO_TP_VALUE)
|
|||
|
|
|||
|
KSPTOUSP
|
|||
|
rte
|
|||
|
|
|||
|
ENTRY(csky_irq)
|
|||
|
SAVE_ALL 0
|
|||
|
zero_fp
|
|||
|
context_tracking
|
|||
|
psrset ee
|
|||
|
|
|||
|
#ifdef CONFIG_TRACE_IRQFLAGS
|
|||
|
jbsr trace_hardirqs_off
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
mov a0, sp
|
|||
|
jbsr generic_handle_arch_irq
|
|||
|
|
|||
|
jmpi ret_from_exception
|
|||
|
|
|||
|
/*
|
|||
|
* a0 = prev task_struct *
|
|||
|
* a1 = next task_struct *
|
|||
|
* a0 = return next
|
|||
|
*/
|
|||
|
ENTRY(__switch_to)
|
|||
|
lrw a3, TASK_THREAD
|
|||
|
addu a3, a0
|
|||
|
|
|||
|
SAVE_SWITCH_STACK
|
|||
|
|
|||
|
stw sp, (a3, THREAD_KSP)
|
|||
|
|
|||
|
/* Set up next process to run */
|
|||
|
lrw a3, TASK_THREAD
|
|||
|
addu a3, a1
|
|||
|
|
|||
|
ldw sp, (a3, THREAD_KSP) /* Set next kernel sp */
|
|||
|
|
|||
|
#if defined(__CSKYABIV2__)
|
|||
|
addi a3, a1, TASK_THREAD_INFO
|
|||
|
ldw tls, (a3, TINFO_TP_VALUE)
|
|||
|
#endif
|
|||
|
|
|||
|
RESTORE_SWITCH_STACK
|
|||
|
|
|||
|
rts
|
|||
|
ENDPROC(__switch_to)
|