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