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