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