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 23 mfcr a0, epsr 24 btsti a0, 31 25 bt 1f 26 jbsr context_tracking_user_exit 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 1f 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 */ 831: 84#ifdef CONFIG_DEBUG_RSEQ 85 mov a0, sp 86 jbsr rseq_syscall 87#endif 88 jmpi ret_from_exception 89 90csky_syscall_trace: 91 mov a0, sp /* sp = pt_regs pointer */ 92 jbsr syscall_trace_enter 93 cmpnei a0, 0 94 bt 1f 95 /* Prepare args before do system call */ 96 ldw a0, (sp, LSAVE_A0) 97 ldw a1, (sp, LSAVE_A1) 98 ldw a2, (sp, LSAVE_A2) 99 ldw a3, (sp, LSAVE_A3) 100#if defined(__CSKYABIV2__) 101 subi sp, 8 102 ldw r9, (sp, LSAVE_A4) 103 stw r9, (sp, 0x0) 104 ldw r9, (sp, LSAVE_A5) 105 stw r9, (sp, 0x4) 106 jsr syscallid /* Do system call */ 107 addi sp, 8 108#else 109 ldw r6, (sp, LSAVE_A4) 110 ldw r7, (sp, LSAVE_A5) 111 jsr syscallid /* Do system call */ 112#endif 113 stw a0, (sp, LSAVE_A0) /* Save return value */ 114 1151: 116#ifdef CONFIG_DEBUG_RSEQ 117 mov a0, sp 118 jbsr rseq_syscall 119#endif 120 mov a0, sp /* right now, sp --> pt_regs */ 121 jbsr syscall_trace_exit 122 br ret_from_exception 123 124ENTRY(ret_from_kernel_thread) 125 jbsr schedule_tail 126 mov a0, r10 127 jsr r9 128 jbsr ret_from_exception 129 130ENTRY(ret_from_fork) 131 jbsr schedule_tail 132 mov r9, sp 133 bmaski r10, THREAD_SHIFT 134 andn r9, r10 135 ldw r10, (r9, TINFO_FLAGS) 136 lrw r9, _TIF_SYSCALL_WORK 137 and r10, r9 138 cmpnei r10, 0 139 bf ret_from_exception 140 mov a0, sp /* sp = pt_regs pointer */ 141 jbsr syscall_trace_exit 142 143ret_from_exception: 144 psrclr ie 145 ld r9, (sp, LSAVE_PSR) 146 btsti r9, 31 147 148 bt 1f 149 /* 150 * Load address of current->thread_info, Then get address of task_struct 151 * Get task_needreshed in task_struct 152 */ 153 mov r9, sp 154 bmaski r10, THREAD_SHIFT 155 andn r9, r10 156 157 ldw r10, (r9, TINFO_FLAGS) 158 lrw r9, _TIF_WORK_MASK 159 and r10, r9 160 cmpnei r10, 0 161 bt exit_work 162#ifdef CONFIG_CONTEXT_TRACKING 163 jbsr context_tracking_user_enter 164#endif 1651: 166#ifdef CONFIG_PREEMPTION 167 mov r9, sp 168 bmaski r10, THREAD_SHIFT 169 andn r9, r10 170 171 ldw r10, (r9, TINFO_PREEMPT) 172 cmpnei r10, 0 173 bt 2f 174 jbsr preempt_schedule_irq /* irq en/disable is done inside */ 1752: 176#endif 177 178#ifdef CONFIG_TRACE_IRQFLAGS 179 ld r10, (sp, LSAVE_PSR) 180 btsti r10, 6 181 bf 2f 182 jbsr trace_hardirqs_on 1832: 184#endif 185 RESTORE_ALL 186 187exit_work: 188 lrw r9, ret_from_exception 189 mov lr, r9 190 191 btsti r10, TIF_NEED_RESCHED 192 bt work_resched 193 194 psrset ie 195 mov a0, sp 196 mov a1, r10 197 jmpi do_notify_resume 198 199work_resched: 200 jmpi schedule 201 202ENTRY(csky_trap) 203 SAVE_ALL 0 204 zero_fp 205 context_tracking 206 psrset ee 207 mov a0, sp /* Push Stack pointer arg */ 208 jbsr trap_c /* Call C-level trap handler */ 209 jmpi ret_from_exception 210 211/* 212 * Prototype from libc for abiv1: 213 * register unsigned int __result asm("a0"); 214 * asm( "trap 3" :"=r"(__result)::); 215 */ 216ENTRY(csky_get_tls) 217 USPTOKSP 218 219 RD_MEH a0 220 WR_MEH a0 221 222 /* increase epc for continue */ 223 mfcr a0, epc 224 addi a0, TRAP0_SIZE 225 mtcr a0, epc 226 227 /* get current task thread_info with kernel 8K stack */ 228 bmaski a0, THREAD_SHIFT 229 not a0 230 subi sp, 1 231 and a0, sp 232 addi sp, 1 233 234 /* get tls */ 235 ldw a0, (a0, TINFO_TP_VALUE) 236 237 KSPTOUSP 238 rte 239 240ENTRY(csky_irq) 241 SAVE_ALL 0 242 zero_fp 243 context_tracking 244 psrset ee 245 246#ifdef CONFIG_TRACE_IRQFLAGS 247 jbsr trace_hardirqs_off 248#endif 249 250 251 mov a0, sp 252 jbsr csky_do_IRQ 253 254 jmpi ret_from_exception 255 256/* 257 * a0 = prev task_struct * 258 * a1 = next task_struct * 259 * a0 = return next 260 */ 261ENTRY(__switch_to) 262 lrw a3, TASK_THREAD 263 addu a3, a0 264 265 SAVE_SWITCH_STACK 266 267 stw sp, (a3, THREAD_KSP) 268 269 /* Set up next process to run */ 270 lrw a3, TASK_THREAD 271 addu a3, a1 272 273 ldw sp, (a3, THREAD_KSP) /* Set next kernel sp */ 274 275#if defined(__CSKYABIV2__) 276 addi a3, a1, TASK_THREAD_INFO 277 ldw tls, (a3, TINFO_TP_VALUE) 278#endif 279 280 RESTORE_SWITCH_STACK 281 282 rts 283ENDPROC(__switch_to) 284