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 132 psrset ee, ie 133 134 lrw r11, __NR_syscalls 135 cmphs syscallid, r11 /* Check nr of syscall */ 136 bt ret_from_exception 137 138 lrw r13, sys_call_table 139 ixw r13, syscallid 140 ldw r11, (r13) 141 cmpnei r11, 0 142 bf ret_from_exception 143 144 mov r9, sp 145 bmaski r10, THREAD_SHIFT 146 andn r9, r10 147 ldw r12, (r9, TINFO_FLAGS) 148 ANDI_R3 r12, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT) 149 cmpnei r12, 0 150 bt csky_syscall_trace 151#if defined(__CSKYABIV2__) 152 subi sp, 8 153 stw r5, (sp, 0x4) 154 stw r4, (sp, 0x0) 155 jsr r11 /* Do system call */ 156 addi sp, 8 157#else 158 jsr r11 159#endif 160 stw a0, (sp, LSAVE_A0) /* Save return value */ 161 jmpi ret_from_exception 162 163csky_syscall_trace: 164 mov a0, sp /* sp = pt_regs pointer */ 165 jbsr syscall_trace_enter 166 /* Prepare args before do system call */ 167 ldw a0, (sp, LSAVE_A0) 168 ldw a1, (sp, LSAVE_A1) 169 ldw a2, (sp, LSAVE_A2) 170 ldw a3, (sp, LSAVE_A3) 171#if defined(__CSKYABIV2__) 172 subi sp, 8 173 ldw r9, (sp, LSAVE_A4) 174 stw r9, (sp, 0x0) 175 ldw r9, (sp, LSAVE_A5) 176 stw r9, (sp, 0x4) 177#else 178 ldw r6, (sp, LSAVE_A4) 179 ldw r7, (sp, LSAVE_A5) 180#endif 181 jsr r11 /* Do system call */ 182#if defined(__CSKYABIV2__) 183 addi sp, 8 184#endif 185 stw a0, (sp, LSAVE_A0) /* Save return value */ 186 187 mov a0, sp /* right now, sp --> pt_regs */ 188 jbsr syscall_trace_exit 189 br ret_from_exception 190 191ENTRY(ret_from_kernel_thread) 192 jbsr schedule_tail 193 mov a0, r10 194 jsr r9 195 jbsr ret_from_exception 196 197ENTRY(ret_from_fork) 198 jbsr schedule_tail 199 mov r9, sp 200 bmaski r10, THREAD_SHIFT 201 andn r9, r10 202 ldw r12, (r9, TINFO_FLAGS) 203 ANDI_R3 r12, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT) 204 cmpnei r12, 0 205 bf ret_from_exception 206 mov a0, sp /* sp = pt_regs pointer */ 207 jbsr syscall_trace_exit 208 209ret_from_exception: 210 ld syscallid, (sp, LSAVE_PSR) 211 btsti syscallid, 31 212 bt 1f 213 214 /* 215 * Load address of current->thread_info, Then get address of task_struct 216 * Get task_needreshed in task_struct 217 */ 218 mov r9, sp 219 bmaski r10, THREAD_SHIFT 220 andn r9, r10 221 222 ldw r12, (r9, TINFO_FLAGS) 223 andi r12, (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED) 224 cmpnei r12, 0 225 bt exit_work 2261: 227 RESTORE_ALL 228 229exit_work: 230 lrw syscallid, ret_from_exception 231 mov lr, syscallid 232 233 btsti r12, TIF_NEED_RESCHED 234 bt work_resched 235 236 mov a0, sp 237 mov a1, r12 238 jmpi do_notify_resume 239 240work_resched: 241 jmpi schedule 242 243ENTRY(csky_trap) 244 SAVE_ALL 0 245 zero_fp 246 psrset ee 247 mov a0, sp /* Push Stack pointer arg */ 248 jbsr trap_c /* Call C-level trap handler */ 249 jmpi ret_from_exception 250 251/* 252 * Prototype from libc for abiv1: 253 * register unsigned int __result asm("a0"); 254 * asm( "trap 3" :"=r"(__result)::); 255 */ 256ENTRY(csky_get_tls) 257 USPTOKSP 258 259 /* increase epc for continue */ 260 mfcr a0, epc 261 addi a0, TRAP0_SIZE 262 mtcr a0, epc 263 264 /* get current task thread_info with kernel 8K stack */ 265 bmaski a0, THREAD_SHIFT 266 not a0 267 subi sp, 1 268 and a0, sp 269 addi sp, 1 270 271 /* get tls */ 272 ldw a0, (a0, TINFO_TP_VALUE) 273 274 KSPTOUSP 275 rte 276 277ENTRY(csky_irq) 278 SAVE_ALL 0 279 zero_fp 280 psrset ee 281 282#ifdef CONFIG_PREEMPT 283 mov r9, sp /* Get current stack pointer */ 284 bmaski r10, THREAD_SHIFT 285 andn r9, r10 /* Get thread_info */ 286 287 /* 288 * Get task_struct->stack.preempt_count for current, 289 * and increase 1. 290 */ 291 ldw r12, (r9, TINFO_PREEMPT) 292 addi r12, 1 293 stw r12, (r9, TINFO_PREEMPT) 294#endif 295 296 mov a0, sp 297 jbsr csky_do_IRQ 298 299#ifdef CONFIG_PREEMPT 300 subi r12, 1 301 stw r12, (r9, TINFO_PREEMPT) 302 cmpnei r12, 0 303 bt 2f 304 ldw r12, (r9, TINFO_FLAGS) 305 btsti r12, TIF_NEED_RESCHED 306 bf 2f 307 jbsr preempt_schedule_irq /* irq en/disable is done inside */ 308#endif 3092: 310 jmpi ret_from_exception 311 312/* 313 * a0 = prev task_struct * 314 * a1 = next task_struct * 315 * a0 = return next 316 */ 317ENTRY(__switch_to) 318 lrw a3, TASK_THREAD 319 addu a3, a0 320 321 mfcr a2, psr /* Save PSR value */ 322 stw a2, (a3, THREAD_SR) /* Save PSR in task struct */ 323 324 SAVE_SWITCH_STACK 325 326 stw sp, (a3, THREAD_KSP) 327 328 /* Set up next process to run */ 329 lrw a3, TASK_THREAD 330 addu a3, a1 331 332 ldw sp, (a3, THREAD_KSP) /* Set next kernel sp */ 333 334 ldw a2, (a3, THREAD_SR) /* Set next PSR */ 335 mtcr a2, psr 336 337#if defined(__CSKYABIV2__) 338 addi r7, a1, TASK_THREAD_INFO 339 ldw tls, (r7, TINFO_TP_VALUE) 340#endif 341 342 RESTORE_SWITCH_STACK 343 344 rts 345ENDPROC(__switch_to) 346