|
|
/* 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/setup.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 |
|
|
mfcr a0, epsr |
|
|
btsti a0, 31 |
|
|
bt 1f |
|
|
jbsr context_tracking_user_exit |
|
|
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 1f |
|
|
|
|
|
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 */ |
|
|
1: |
|
|
#ifdef CONFIG_DEBUG_RSEQ |
|
|
mov a0, sp |
|
|
jbsr rseq_syscall |
|
|
#endif |
|
|
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: |
|
|
#ifdef CONFIG_DEBUG_RSEQ |
|
|
mov a0, sp |
|
|
jbsr rseq_syscall |
|
|
#endif |
|
|
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 |
|
|
jbsr context_tracking_user_enter |
|
|
#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 csky_do_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)
|
|
|
|