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#define PTE_INDX_MSK 0xffc 17#define PTE_INDX_SHIFT 10 18#define _PGDIR_SHIFT 22 19 20.macro zero_fp 21#ifdef CONFIG_STACKTRACE 22 movi r8, 0 23#endif 24.endm 25 26.macro tlbop_begin name, val0, val1, val2 27ENTRY(csky_\name) 28 mtcr a3, ss2 29 mtcr r6, ss3 30 mtcr a2, ss4 31 32 RD_PGDR r6 33 RD_MEH a3 34#ifdef CONFIG_CPU_HAS_TLBI 35 tlbi.vaas a3 36 sync.is 37 38 btsti a3, 31 39 bf 1f 40 RD_PGDR_K r6 411: 42#else 43 bgeni a2, 31 44 WR_MCIR a2 45 bgeni a2, 25 46 WR_MCIR a2 47#endif 48 bclri r6, 0 49 lrw a2, va_pa_offset 50 ld.w a2, (a2, 0) 51 subu r6, a2 52 bseti r6, 31 53 54 mov a2, a3 55 lsri a2, _PGDIR_SHIFT 56 lsli a2, 2 57 addu r6, a2 58 ldw r6, (r6) 59 60 lrw a2, va_pa_offset 61 ld.w a2, (a2, 0) 62 subu r6, a2 63 bseti r6, 31 64 65 lsri a3, PTE_INDX_SHIFT 66 lrw a2, PTE_INDX_MSK 67 and a3, a2 68 addu r6, a3 69 ldw a3, (r6) 70 71 movi a2, (_PAGE_PRESENT | \val0) 72 and a3, a2 73 cmpne a3, a2 74 bt \name 75 76 /* First read/write the page, just update the flags */ 77 ldw a3, (r6) 78 bgeni a2, PAGE_VALID_BIT 79 bseti a2, PAGE_ACCESSED_BIT 80 bseti a2, \val1 81 bseti a2, \val2 82 or a3, a2 83 stw a3, (r6) 84 85 /* Some cpu tlb-hardrefill bypass the cache */ 86#ifdef CONFIG_CPU_NEED_TLBSYNC 87 movi a2, 0x22 88 bseti a2, 6 89 mtcr r6, cr22 90 mtcr a2, cr17 91 sync 92#endif 93 94 mfcr a3, ss2 95 mfcr r6, ss3 96 mfcr a2, ss4 97 rte 98\name: 99 mfcr a3, ss2 100 mfcr r6, ss3 101 mfcr a2, ss4 102 SAVE_ALL 0 103.endm 104.macro tlbop_end is_write 105 zero_fp 106 RD_MEH a2 107 psrset ee, ie 108 mov a0, sp 109 movi a1, \is_write 110 jbsr do_page_fault 111 jmpi ret_from_exception 112.endm 113 114.text 115 116tlbop_begin tlbinvalidl, _PAGE_READ, PAGE_VALID_BIT, PAGE_ACCESSED_BIT 117tlbop_end 0 118 119tlbop_begin tlbinvalids, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT 120tlbop_end 1 121 122tlbop_begin tlbmodified, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT 123#ifndef CONFIG_CPU_HAS_LDSTEX 124jbsr csky_cmpxchg_fixup 125#endif 126tlbop_end 1 127 128ENTRY(csky_systemcall) 129 SAVE_ALL TRAP0_SIZE 130 zero_fp 131#ifdef CONFIG_RSEQ_DEBUG 132 mov a0, sp 133 jbsr rseq_syscall 134#endif 135 psrset ee, ie 136 137 lrw r11, __NR_syscalls 138 cmphs syscallid, r11 /* Check nr of syscall */ 139 bt ret_from_exception 140 141 lrw r13, sys_call_table 142 ixw r13, syscallid 143 ldw r11, (r13) 144 cmpnei r11, 0 145 bf ret_from_exception 146 147 mov r9, sp 148 bmaski r10, THREAD_SHIFT 149 andn r9, r10 150 ldw r12, (r9, TINFO_FLAGS) 151 ANDI_R3 r12, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT) 152 cmpnei r12, 0 153 bt csky_syscall_trace 154#if defined(__CSKYABIV2__) 155 subi sp, 8 156 stw r5, (sp, 0x4) 157 stw r4, (sp, 0x0) 158 jsr r11 /* Do system call */ 159 addi sp, 8 160#else 161 jsr r11 162#endif 163 stw a0, (sp, LSAVE_A0) /* Save return value */ 164 jmpi ret_from_exception 165 166csky_syscall_trace: 167 mov a0, sp /* sp = pt_regs pointer */ 168 jbsr syscall_trace_enter 169 /* Prepare args before do system call */ 170 ldw a0, (sp, LSAVE_A0) 171 ldw a1, (sp, LSAVE_A1) 172 ldw a2, (sp, LSAVE_A2) 173 ldw a3, (sp, LSAVE_A3) 174#if defined(__CSKYABIV2__) 175 subi sp, 8 176 stw r5, (sp, 0x4) 177 stw r4, (sp, 0x0) 178#else 179 ldw r6, (sp, LSAVE_A4) 180 ldw r7, (sp, LSAVE_A5) 181#endif 182 jsr r11 /* Do system call */ 183#if defined(__CSKYABIV2__) 184 addi sp, 8 185#endif 186 stw a0, (sp, LSAVE_A0) /* Save return value */ 187 188 mov a0, sp /* right now, sp --> pt_regs */ 189 jbsr syscall_trace_exit 190 br ret_from_exception 191 192ENTRY(ret_from_kernel_thread) 193 jbsr schedule_tail 194 mov a0, r10 195 jsr r9 196 jbsr ret_from_exception 197 198ENTRY(ret_from_fork) 199 jbsr schedule_tail 200 mov r9, sp 201 bmaski r10, THREAD_SHIFT 202 andn r9, r10 203 ldw r12, (r9, TINFO_FLAGS) 204 ANDI_R3 r12, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT) 205 cmpnei r12, 0 206 bf ret_from_exception 207 mov a0, sp /* sp = pt_regs pointer */ 208 jbsr syscall_trace_exit 209 210ret_from_exception: 211 ld syscallid, (sp, LSAVE_PSR) 212 btsti syscallid, 31 213 bt 1f 214 215 /* 216 * Load address of current->thread_info, Then get address of task_struct 217 * Get task_needreshed in task_struct 218 */ 219 mov r9, sp 220 bmaski r10, THREAD_SHIFT 221 andn r9, r10 222 223 ldw r12, (r9, TINFO_FLAGS) 224 andi r12, (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | _TIF_UPROBE) 225 cmpnei r12, 0 226 bt exit_work 2271: 228#ifdef CONFIG_TRACE_IRQFLAGS 229 ld r10, (sp, LSAVE_PSR) 230 btsti r10, 6 231 bf 2f 232 jbsr trace_hardirqs_on 2332: 234#endif 235 RESTORE_ALL 236 237exit_work: 238 lrw syscallid, ret_from_exception 239 mov lr, syscallid 240 241 btsti r12, TIF_NEED_RESCHED 242 bt work_resched 243 244 mov a0, sp 245 mov a1, r12 246 jmpi do_notify_resume 247 248work_resched: 249 jmpi schedule 250 251ENTRY(csky_trap) 252 SAVE_ALL 0 253 zero_fp 254 psrset ee 255 mov a0, sp /* Push Stack pointer arg */ 256 jbsr trap_c /* Call C-level trap handler */ 257 jmpi ret_from_exception 258 259/* 260 * Prototype from libc for abiv1: 261 * register unsigned int __result asm("a0"); 262 * asm( "trap 3" :"=r"(__result)::); 263 */ 264ENTRY(csky_get_tls) 265 USPTOKSP 266 267 /* increase epc for continue */ 268 mfcr a0, epc 269 addi a0, TRAP0_SIZE 270 mtcr a0, epc 271 272 /* get current task thread_info with kernel 8K stack */ 273 bmaski a0, THREAD_SHIFT 274 not a0 275 subi sp, 1 276 and a0, sp 277 addi sp, 1 278 279 /* get tls */ 280 ldw a0, (a0, TINFO_TP_VALUE) 281 282 KSPTOUSP 283 rte 284 285ENTRY(csky_irq) 286 SAVE_ALL 0 287 zero_fp 288 psrset ee 289 290#ifdef CONFIG_TRACE_IRQFLAGS 291 jbsr trace_hardirqs_off 292#endif 293 294#ifdef CONFIG_PREEMPTION 295 mov r9, sp /* Get current stack pointer */ 296 bmaski r10, THREAD_SHIFT 297 andn r9, r10 /* Get thread_info */ 298 299 /* 300 * Get task_struct->stack.preempt_count for current, 301 * and increase 1. 302 */ 303 ldw r12, (r9, TINFO_PREEMPT) 304 addi r12, 1 305 stw r12, (r9, TINFO_PREEMPT) 306#endif 307 308 mov a0, sp 309 jbsr csky_do_IRQ 310 311#ifdef CONFIG_PREEMPTION 312 subi r12, 1 313 stw r12, (r9, TINFO_PREEMPT) 314 cmpnei r12, 0 315 bt 2f 316 ldw r12, (r9, TINFO_FLAGS) 317 btsti r12, TIF_NEED_RESCHED 318 bf 2f 319 jbsr preempt_schedule_irq /* irq en/disable is done inside */ 320#endif 3212: 322 jmpi ret_from_exception 323 324/* 325 * a0 = prev task_struct * 326 * a1 = next task_struct * 327 * a0 = return next 328 */ 329ENTRY(__switch_to) 330 lrw a3, TASK_THREAD 331 addu a3, a0 332 333 mfcr a2, psr /* Save PSR value */ 334 stw a2, (a3, THREAD_SR) /* Save PSR in task struct */ 335 bclri a2, 6 /* Disable interrupts */ 336 mtcr a2, psr 337 338 SAVE_SWITCH_STACK 339 340 stw sp, (a3, THREAD_KSP) 341 342 /* Set up next process to run */ 343 lrw a3, TASK_THREAD 344 addu a3, a1 345 346 ldw sp, (a3, THREAD_KSP) /* Set next kernel sp */ 347 348 ldw a2, (a3, THREAD_SR) /* Set next PSR */ 349 mtcr a2, psr 350 351#if defined(__CSKYABIV2__) 352 addi r7, a1, TASK_THREAD_INFO 353 ldw tls, (r7, TINFO_TP_VALUE) 354#endif 355 356 RESTORE_SWITCH_STACK 357 358 rts 359ENDPROC(__switch_to) 360