1/* SPDX-License-Identifier: GPL-2.0 */ 2// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. 3 4#include <linux/linkage.h> 5#include <abi/entry.h> 6#include <abi/pgtable-bits.h> 7#include <asm/errno.h> 8#include <asm/setup.h> 9#include <asm/unistd.h> 10#include <asm/asm-offsets.h> 11#include <linux/threads.h> 12#include <asm/page.h> 13#include <asm/thread_info.h> 14 15.macro zero_fp 16#ifdef CONFIG_STACKTRACE 17 movi r8, 0 18#endif 19.endm 20 21.macro context_tracking 22#ifdef CONFIG_CONTEXT_TRACKING_USER 23 mfcr a0, epsr 24 btsti a0, 31 25 bt 1f 26 jbsr user_exit_callable 27 ldw a0, (sp, LSAVE_A0) 28 ldw a1, (sp, LSAVE_A1) 29 ldw a2, (sp, LSAVE_A2) 30 ldw a3, (sp, LSAVE_A3) 31#if defined(__CSKYABIV1__) 32 ldw r6, (sp, LSAVE_A4) 33 ldw r7, (sp, LSAVE_A5) 34#endif 351: 36#endif 37.endm 38 39.text 40ENTRY(csky_pagefault) 41 SAVE_ALL 0 42 zero_fp 43 context_tracking 44 psrset ee 45 mov a0, sp 46 jbsr do_page_fault 47 jmpi ret_from_exception 48 49ENTRY(csky_systemcall) 50 SAVE_ALL TRAP0_SIZE 51 zero_fp 52 context_tracking 53 psrset ee, ie 54 55 lrw r9, __NR_syscalls 56 cmphs syscallid, r9 /* Check nr of syscall */ 57 bt ret_from_exception 58 59 lrw r9, sys_call_table 60 ixw r9, syscallid 61 ldw syscallid, (r9) 62 cmpnei syscallid, 0 63 bf ret_from_exception 64 65 mov r9, sp 66 bmaski r10, THREAD_SHIFT 67 andn r9, r10 68 ldw r10, (r9, TINFO_FLAGS) 69 lrw r9, _TIF_SYSCALL_WORK 70 and r10, r9 71 cmpnei r10, 0 72 bt csky_syscall_trace 73#if defined(__CSKYABIV2__) 74 subi sp, 8 75 stw r5, (sp, 0x4) 76 stw r4, (sp, 0x0) 77 jsr syscallid /* Do system call */ 78 addi sp, 8 79#else 80 jsr syscallid 81#endif 82 stw a0, (sp, LSAVE_A0) /* Save return value */ 83 jmpi ret_from_exception 84 85csky_syscall_trace: 86 mov a0, sp /* sp = pt_regs pointer */ 87 jbsr syscall_trace_enter 88 cmpnei a0, 0 89 bt 1f 90 /* Prepare args before do system call */ 91 ldw a0, (sp, LSAVE_A0) 92 ldw a1, (sp, LSAVE_A1) 93 ldw a2, (sp, LSAVE_A2) 94 ldw a3, (sp, LSAVE_A3) 95#if defined(__CSKYABIV2__) 96 subi sp, 8 97 ldw r9, (sp, LSAVE_A4) 98 stw r9, (sp, 0x0) 99 ldw r9, (sp, LSAVE_A5) 100 stw r9, (sp, 0x4) 101 jsr syscallid /* Do system call */ 102 addi sp, 8 103#else 104 ldw r6, (sp, LSAVE_A4) 105 ldw r7, (sp, LSAVE_A5) 106 jsr syscallid /* Do system call */ 107#endif 108 stw a0, (sp, LSAVE_A0) /* Save return value */ 109 1101: 111 mov a0, sp /* right now, sp --> pt_regs */ 112 jbsr syscall_trace_exit 113 br ret_from_exception 114 115ENTRY(ret_from_kernel_thread) 116 jbsr schedule_tail 117 mov a0, r10 118 jsr r9 119 jbsr ret_from_exception 120 121ENTRY(ret_from_fork) 122 jbsr schedule_tail 123 mov r9, sp 124 bmaski r10, THREAD_SHIFT 125 andn r9, r10 126 ldw r10, (r9, TINFO_FLAGS) 127 lrw r9, _TIF_SYSCALL_WORK 128 and r10, r9 129 cmpnei r10, 0 130 bf ret_from_exception 131 mov a0, sp /* sp = pt_regs pointer */ 132 jbsr syscall_trace_exit 133 134ret_from_exception: 135 psrclr ie 136 ld r9, (sp, LSAVE_PSR) 137 btsti r9, 31 138 139 bt 1f 140 /* 141 * Load address of current->thread_info, Then get address of task_struct 142 * Get task_needreshed in task_struct 143 */ 144 mov r9, sp 145 bmaski r10, THREAD_SHIFT 146 andn r9, r10 147 148 ldw r10, (r9, TINFO_FLAGS) 149 lrw r9, _TIF_WORK_MASK 150 and r10, r9 151 cmpnei r10, 0 152 bt exit_work 153#ifdef CONFIG_CONTEXT_TRACKING_USER 154 jbsr user_enter_callable 155#endif 1561: 157#ifdef CONFIG_PREEMPTION 158 mov r9, sp 159 bmaski r10, THREAD_SHIFT 160 andn r9, r10 161 162 ldw r10, (r9, TINFO_PREEMPT) 163 cmpnei r10, 0 164 bt 2f 165 jbsr preempt_schedule_irq /* irq en/disable is done inside */ 1662: 167#endif 168 169#ifdef CONFIG_TRACE_IRQFLAGS 170 ld r10, (sp, LSAVE_PSR) 171 btsti r10, 6 172 bf 2f 173 jbsr trace_hardirqs_on 1742: 175#endif 176 RESTORE_ALL 177 178exit_work: 179 lrw r9, ret_from_exception 180 mov lr, r9 181 182 btsti r10, TIF_NEED_RESCHED 183 bt work_resched 184 185 psrset ie 186 mov a0, sp 187 mov a1, r10 188 jmpi do_notify_resume 189 190work_resched: 191 jmpi schedule 192 193ENTRY(csky_trap) 194 SAVE_ALL 0 195 zero_fp 196 context_tracking 197 psrset ee 198 mov a0, sp /* Push Stack pointer arg */ 199 jbsr trap_c /* Call C-level trap handler */ 200 jmpi ret_from_exception 201 202/* 203 * Prototype from libc for abiv1: 204 * register unsigned int __result asm("a0"); 205 * asm( "trap 3" :"=r"(__result)::); 206 */ 207ENTRY(csky_get_tls) 208 USPTOKSP 209 210 RD_MEH a0 211 WR_MEH a0 212 213 /* increase epc for continue */ 214 mfcr a0, epc 215 addi a0, TRAP0_SIZE 216 mtcr a0, epc 217 218 /* get current task thread_info with kernel 8K stack */ 219 bmaski a0, THREAD_SHIFT 220 not a0 221 subi sp, 1 222 and a0, sp 223 addi sp, 1 224 225 /* get tls */ 226 ldw a0, (a0, TINFO_TP_VALUE) 227 228 KSPTOUSP 229 rte 230 231ENTRY(csky_irq) 232 SAVE_ALL 0 233 zero_fp 234 context_tracking 235 psrset ee 236 237#ifdef CONFIG_TRACE_IRQFLAGS 238 jbsr trace_hardirqs_off 239#endif 240 241 242 mov a0, sp 243 jbsr generic_handle_arch_irq 244 245 jmpi ret_from_exception 246 247/* 248 * a0 = prev task_struct * 249 * a1 = next task_struct * 250 * a0 = return next 251 */ 252ENTRY(__switch_to) 253 lrw a3, TASK_THREAD 254 addu a3, a0 255 256 SAVE_SWITCH_STACK 257 258 stw sp, (a3, THREAD_KSP) 259 260 /* Set up next process to run */ 261 lrw a3, TASK_THREAD 262 addu a3, a1 263 264 ldw sp, (a3, THREAD_KSP) /* Set next kernel sp */ 265 266#if defined(__CSKYABIV2__) 267 addi a3, a1, TASK_THREAD_INFO 268 ldw tls, (a3, TINFO_TP_VALUE) 269#endif 270 271 RESTORE_SWITCH_STACK 272 273 rts 274ENDPROC(__switch_to) 275