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