1081860b9SGuo Ren/* SPDX-License-Identifier: GPL-2.0 */ 2081860b9SGuo Ren// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. 3081860b9SGuo Ren 4081860b9SGuo Ren#include <linux/linkage.h> 5081860b9SGuo Ren#include <abi/entry.h> 6081860b9SGuo Ren#include <abi/pgtable-bits.h> 7081860b9SGuo Ren#include <asm/errno.h> 8081860b9SGuo Ren#include <asm/setup.h> 9081860b9SGuo Ren#include <asm/unistd.h> 10081860b9SGuo Ren#include <asm/asm-offsets.h> 11081860b9SGuo Ren#include <linux/threads.h> 12081860b9SGuo Ren#include <asm/setup.h> 13081860b9SGuo Ren#include <asm/page.h> 14081860b9SGuo Ren#include <asm/thread_info.h> 15081860b9SGuo Ren 16081860b9SGuo Ren#define PTE_INDX_MSK 0xffc 17081860b9SGuo Ren#define PTE_INDX_SHIFT 10 18081860b9SGuo Ren#define _PGDIR_SHIFT 22 19081860b9SGuo Ren 20081860b9SGuo Ren.macro tlbop_begin name, val0, val1, val2 21081860b9SGuo RenENTRY(csky_\name) 22081860b9SGuo Ren mtcr a3, ss2 23081860b9SGuo Ren mtcr r6, ss3 24081860b9SGuo Ren mtcr a2, ss4 25081860b9SGuo Ren 26081860b9SGuo Ren RD_PGDR r6 27081860b9SGuo Ren RD_MEH a3 28081860b9SGuo Ren#ifdef CONFIG_CPU_HAS_TLBI 29081860b9SGuo Ren tlbi.vaas a3 30081860b9SGuo Ren sync.is 31081860b9SGuo Ren 32081860b9SGuo Ren btsti a3, 31 33081860b9SGuo Ren bf 1f 34081860b9SGuo Ren RD_PGDR_K r6 35081860b9SGuo Ren1: 36081860b9SGuo Ren#else 37081860b9SGuo Ren bgeni a2, 31 38081860b9SGuo Ren WR_MCIR a2 39081860b9SGuo Ren bgeni a2, 25 40081860b9SGuo Ren WR_MCIR a2 41081860b9SGuo Ren#endif 42081860b9SGuo Ren bclri r6, 0 43081860b9SGuo Ren lrw a2, PHYS_OFFSET 44081860b9SGuo Ren subu r6, a2 45081860b9SGuo Ren bseti r6, 31 46081860b9SGuo Ren 47081860b9SGuo Ren mov a2, a3 48081860b9SGuo Ren lsri a2, _PGDIR_SHIFT 49081860b9SGuo Ren lsli a2, 2 50081860b9SGuo Ren addu r6, a2 51081860b9SGuo Ren ldw r6, (r6) 52081860b9SGuo Ren 53081860b9SGuo Ren lrw a2, PHYS_OFFSET 54081860b9SGuo Ren subu r6, a2 55081860b9SGuo Ren bseti r6, 31 56081860b9SGuo Ren 57081860b9SGuo Ren lsri a3, PTE_INDX_SHIFT 58081860b9SGuo Ren lrw a2, PTE_INDX_MSK 59081860b9SGuo Ren and a3, a2 60081860b9SGuo Ren addu r6, a3 61081860b9SGuo Ren ldw a3, (r6) 62081860b9SGuo Ren 63081860b9SGuo Ren movi a2, (_PAGE_PRESENT | \val0) 64081860b9SGuo Ren and a3, a2 65081860b9SGuo Ren cmpne a3, a2 66081860b9SGuo Ren bt \name 67081860b9SGuo Ren 68081860b9SGuo Ren /* First read/write the page, just update the flags */ 69081860b9SGuo Ren ldw a3, (r6) 70081860b9SGuo Ren bgeni a2, PAGE_VALID_BIT 71081860b9SGuo Ren bseti a2, PAGE_ACCESSED_BIT 72081860b9SGuo Ren bseti a2, \val1 73081860b9SGuo Ren bseti a2, \val2 74081860b9SGuo Ren or a3, a2 75081860b9SGuo Ren stw a3, (r6) 76081860b9SGuo Ren 77081860b9SGuo Ren /* Some cpu tlb-hardrefill bypass the cache */ 78081860b9SGuo Ren#ifdef CONFIG_CPU_NEED_TLBSYNC 79081860b9SGuo Ren movi a2, 0x22 80081860b9SGuo Ren bseti a2, 6 81081860b9SGuo Ren mtcr r6, cr22 82081860b9SGuo Ren mtcr a2, cr17 83081860b9SGuo Ren sync 84081860b9SGuo Ren#endif 85081860b9SGuo Ren 86081860b9SGuo Ren mfcr a3, ss2 87081860b9SGuo Ren mfcr r6, ss3 88081860b9SGuo Ren mfcr a2, ss4 89081860b9SGuo Ren rte 90081860b9SGuo Ren\name: 91081860b9SGuo Ren mfcr a3, ss2 92081860b9SGuo Ren mfcr r6, ss3 93081860b9SGuo Ren mfcr a2, ss4 94081860b9SGuo Ren SAVE_ALL EPC_KEEP 95081860b9SGuo Ren.endm 96081860b9SGuo Ren.macro tlbop_end is_write 97081860b9SGuo Ren RD_MEH a2 98081860b9SGuo Ren psrset ee, ie 99081860b9SGuo Ren mov a0, sp 100081860b9SGuo Ren movi a1, \is_write 101081860b9SGuo Ren jbsr do_page_fault 102081860b9SGuo Ren movi r11_sig, 0 /* r11 = 0, Not a syscall. */ 103081860b9SGuo Ren jmpi ret_from_exception 104081860b9SGuo Ren.endm 105081860b9SGuo Ren 106081860b9SGuo Ren.text 107081860b9SGuo Ren 108081860b9SGuo Rentlbop_begin tlbinvalidl, _PAGE_READ, PAGE_VALID_BIT, PAGE_ACCESSED_BIT 109081860b9SGuo Rentlbop_end 0 110081860b9SGuo Ren 111081860b9SGuo Rentlbop_begin tlbinvalids, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT 112081860b9SGuo Rentlbop_end 1 113081860b9SGuo Ren 114081860b9SGuo Rentlbop_begin tlbmodified, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT 115081860b9SGuo Ren#ifndef CONFIG_CPU_HAS_LDSTEX 116081860b9SGuo Renjbsr csky_cmpxchg_fixup 117081860b9SGuo Ren#endif 118081860b9SGuo Rentlbop_end 1 119081860b9SGuo Ren 120081860b9SGuo RenENTRY(csky_systemcall) 121081860b9SGuo Ren SAVE_ALL EPC_INCREASE 122081860b9SGuo Ren 123081860b9SGuo Ren psrset ee, ie 124081860b9SGuo Ren 125081860b9SGuo Ren /* Stack frame for syscall, origin call set_esp0 */ 126081860b9SGuo Ren mov r12, sp 127081860b9SGuo Ren 128081860b9SGuo Ren bmaski r11, 13 129081860b9SGuo Ren andn r12, r11 130081860b9SGuo Ren bgeni r11, 9 131081860b9SGuo Ren addi r11, 32 132081860b9SGuo Ren addu r12, r11 133081860b9SGuo Ren st sp, (r12, 0) 134081860b9SGuo Ren 135081860b9SGuo Ren lrw r11, __NR_syscalls 136081860b9SGuo Ren cmphs syscallid, r11 /* Check nr of syscall */ 137081860b9SGuo Ren bt ret_from_exception 138081860b9SGuo Ren 139081860b9SGuo Ren lrw r13, sys_call_table 140081860b9SGuo Ren ixw r13, syscallid 141081860b9SGuo Ren ldw r11, (r13) 142081860b9SGuo Ren cmpnei r11, 0 143081860b9SGuo Ren bf ret_from_exception 144081860b9SGuo Ren 145081860b9SGuo Ren mov r9, sp 146081860b9SGuo Ren bmaski r10, THREAD_SHIFT 147081860b9SGuo Ren andn r9, r10 148081860b9SGuo Ren ldw r8, (r9, TINFO_FLAGS) 149081860b9SGuo Ren btsti r8, TIF_SYSCALL_TRACE 150081860b9SGuo Ren bt 1f 151081860b9SGuo Ren#if defined(__CSKYABIV2__) 152081860b9SGuo Ren subi sp, 8 153081860b9SGuo Ren stw r5, (sp, 0x4) 154081860b9SGuo Ren stw r4, (sp, 0x0) 155081860b9SGuo Ren jsr r11 /* Do system call */ 156081860b9SGuo Ren addi sp, 8 157081860b9SGuo Ren#else 158081860b9SGuo Ren jsr r11 159081860b9SGuo Ren#endif 160081860b9SGuo Ren stw a0, (sp, LSAVE_A0) /* Save return value */ 161081860b9SGuo Ren jmpi ret_from_exception 162081860b9SGuo Ren 163081860b9SGuo Ren1: 164081860b9SGuo Ren movi a0, 0 /* enter system call */ 165081860b9SGuo Ren mov a1, sp /* sp = pt_regs pointer */ 166081860b9SGuo Ren jbsr syscall_trace 167081860b9SGuo Ren /* Prepare args before do system call */ 168081860b9SGuo Ren ldw a0, (sp, LSAVE_A0) 169081860b9SGuo Ren ldw a1, (sp, LSAVE_A1) 170081860b9SGuo Ren ldw a2, (sp, LSAVE_A2) 171081860b9SGuo Ren ldw a3, (sp, LSAVE_A3) 172081860b9SGuo Ren#if defined(__CSKYABIV2__) 173081860b9SGuo Ren subi sp, 8 174081860b9SGuo Ren stw r5, (sp, 0x4) 175081860b9SGuo Ren stw r4, (sp, 0x0) 176081860b9SGuo Ren#else 177081860b9SGuo Ren ldw r6, (sp, LSAVE_A4) 178081860b9SGuo Ren ldw r7, (sp, LSAVE_A5) 179081860b9SGuo Ren#endif 180081860b9SGuo Ren jsr r11 /* Do system call */ 181081860b9SGuo Ren#if defined(__CSKYABIV2__) 182081860b9SGuo Ren addi sp, 8 183081860b9SGuo Ren#endif 184081860b9SGuo Ren stw a0, (sp, LSAVE_A0) /* Save return value */ 185081860b9SGuo Ren 186081860b9SGuo Ren movi a0, 1 /* leave system call */ 187*31295a72SGuo Ren mov a1, sp /* right now, sp --> pt_regs */ 188081860b9SGuo Ren jbsr syscall_trace 189*31295a72SGuo Ren br ret_from_exception 190081860b9SGuo Ren 191081860b9SGuo RenENTRY(ret_from_kernel_thread) 192081860b9SGuo Ren jbsr schedule_tail 193081860b9SGuo Ren mov a0, r8 194081860b9SGuo Ren jsr r9 195081860b9SGuo Ren jbsr ret_from_exception 196081860b9SGuo Ren 197081860b9SGuo RenENTRY(ret_from_fork) 198081860b9SGuo Ren jbsr schedule_tail 199081860b9SGuo Ren mov r9, sp 200081860b9SGuo Ren bmaski r10, THREAD_SHIFT 201081860b9SGuo Ren andn r9, r10 202081860b9SGuo Ren ldw r8, (r9, TINFO_FLAGS) 203081860b9SGuo Ren movi r11_sig, 1 204081860b9SGuo Ren btsti r8, TIF_SYSCALL_TRACE 205081860b9SGuo Ren bf 3f 206081860b9SGuo Ren movi a0, 1 207081860b9SGuo Ren mov a1, sp /* sp = pt_regs pointer */ 208081860b9SGuo Ren jbsr syscall_trace 209081860b9SGuo Ren3: 210081860b9SGuo Ren jbsr ret_from_exception 211081860b9SGuo Ren 212081860b9SGuo Renret_from_exception: 213081860b9SGuo Ren ld syscallid, (sp, LSAVE_PSR) 214081860b9SGuo Ren btsti syscallid, 31 215081860b9SGuo Ren bt 1f 216081860b9SGuo Ren 217081860b9SGuo Ren /* 218081860b9SGuo Ren * Load address of current->thread_info, Then get address of task_struct 219081860b9SGuo Ren * Get task_needreshed in task_struct 220081860b9SGuo Ren */ 221081860b9SGuo Ren mov r9, sp 222081860b9SGuo Ren bmaski r10, THREAD_SHIFT 223081860b9SGuo Ren andn r9, r10 224081860b9SGuo Ren 225081860b9SGuo Renresume_userspace: 226081860b9SGuo Ren ldw r8, (r9, TINFO_FLAGS) 227081860b9SGuo Ren andi r8, (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED) 228081860b9SGuo Ren cmpnei r8, 0 229081860b9SGuo Ren bt exit_work 230081860b9SGuo Ren1: RESTORE_ALL 231081860b9SGuo Ren 232081860b9SGuo Renexit_work: 233081860b9SGuo Ren mov a0, sp /* Stack address is arg[0] */ 234081860b9SGuo Ren jbsr set_esp0 /* Call C level */ 235081860b9SGuo Ren btsti r8, TIF_NEED_RESCHED 236081860b9SGuo Ren bt work_resched 237081860b9SGuo Ren /* If thread_info->flag is empty, RESTORE_ALL */ 238081860b9SGuo Ren cmpnei r8, 0 239081860b9SGuo Ren bf 1b 240081860b9SGuo Ren mov a1, sp 241081860b9SGuo Ren mov a0, r8 242081860b9SGuo Ren mov a2, r11_sig /* syscall? */ 243081860b9SGuo Ren btsti r8, TIF_SIGPENDING /* delivering a signal? */ 244081860b9SGuo Ren /* prevent further restarts(set r11 = 0) */ 245081860b9SGuo Ren clrt r11_sig 246081860b9SGuo Ren jbsr do_notify_resume /* do signals */ 247081860b9SGuo Ren br resume_userspace 248081860b9SGuo Ren 249081860b9SGuo Renwork_resched: 250081860b9SGuo Ren lrw syscallid, ret_from_exception 251081860b9SGuo Ren mov r15, syscallid /* Return address in link */ 252081860b9SGuo Ren jmpi schedule 253081860b9SGuo Ren 254081860b9SGuo RenENTRY(sys_rt_sigreturn) 255081860b9SGuo Ren movi r11_sig, 0 256081860b9SGuo Ren jmpi do_rt_sigreturn 257081860b9SGuo Ren 258081860b9SGuo RenENTRY(csky_trap) 259081860b9SGuo Ren SAVE_ALL EPC_KEEP 260081860b9SGuo Ren psrset ee 261081860b9SGuo Ren movi r11_sig, 0 /* r11 = 0, Not a syscall. */ 262081860b9SGuo Ren mov a0, sp /* Push Stack pointer arg */ 263081860b9SGuo Ren jbsr trap_c /* Call C-level trap handler */ 264081860b9SGuo Ren jmpi ret_from_exception 265081860b9SGuo Ren 266081860b9SGuo Ren/* 267081860b9SGuo Ren * Prototype from libc for abiv1: 268081860b9SGuo Ren * register unsigned int __result asm("a0"); 269081860b9SGuo Ren * asm( "trap 3" :"=r"(__result)::); 270081860b9SGuo Ren */ 271081860b9SGuo RenENTRY(csky_get_tls) 272081860b9SGuo Ren USPTOKSP 273081860b9SGuo Ren 274081860b9SGuo Ren /* increase epc for continue */ 275081860b9SGuo Ren mfcr a0, epc 276081860b9SGuo Ren INCTRAP a0 277081860b9SGuo Ren mtcr a0, epc 278081860b9SGuo Ren 279081860b9SGuo Ren /* get current task thread_info with kernel 8K stack */ 280081860b9SGuo Ren bmaski a0, THREAD_SHIFT 281081860b9SGuo Ren not a0 282081860b9SGuo Ren subi sp, 1 283081860b9SGuo Ren and a0, sp 284081860b9SGuo Ren addi sp, 1 285081860b9SGuo Ren 286081860b9SGuo Ren /* get tls */ 287081860b9SGuo Ren ldw a0, (a0, TINFO_TP_VALUE) 288081860b9SGuo Ren 289081860b9SGuo Ren KSPTOUSP 290081860b9SGuo Ren rte 291081860b9SGuo Ren 292081860b9SGuo RenENTRY(csky_irq) 293081860b9SGuo Ren SAVE_ALL EPC_KEEP 294081860b9SGuo Ren psrset ee 295081860b9SGuo Ren movi r11_sig, 0 /* r11 = 0, Not a syscall. */ 296081860b9SGuo Ren 297081860b9SGuo Ren#ifdef CONFIG_PREEMPT 298081860b9SGuo Ren mov r9, sp /* Get current stack pointer */ 299081860b9SGuo Ren bmaski r10, THREAD_SHIFT 300081860b9SGuo Ren andn r9, r10 /* Get thread_info */ 301081860b9SGuo Ren 302081860b9SGuo Ren /* 303081860b9SGuo Ren * Get task_struct->stack.preempt_count for current, 304081860b9SGuo Ren * and increase 1. 305081860b9SGuo Ren */ 306081860b9SGuo Ren ldw r8, (r9, TINFO_PREEMPT) 307081860b9SGuo Ren addi r8, 1 308081860b9SGuo Ren stw r8, (r9, TINFO_PREEMPT) 309081860b9SGuo Ren#endif 310081860b9SGuo Ren 311081860b9SGuo Ren mov a0, sp 312081860b9SGuo Ren jbsr csky_do_IRQ 313081860b9SGuo Ren 314081860b9SGuo Ren#ifdef CONFIG_PREEMPT 315081860b9SGuo Ren subi r8, 1 316081860b9SGuo Ren stw r8, (r9, TINFO_PREEMPT) 317081860b9SGuo Ren cmpnei r8, 0 318081860b9SGuo Ren bt 2f 319081860b9SGuo Ren ldw r8, (r9, TINFO_FLAGS) 320081860b9SGuo Ren btsti r8, TIF_NEED_RESCHED 321081860b9SGuo Ren bf 2f 322081860b9SGuo Ren1: 323081860b9SGuo Ren jbsr preempt_schedule_irq /* irq en/disable is done inside */ 324081860b9SGuo Ren ldw r7, (r9, TINFO_FLAGS) /* get new tasks TI_FLAGS */ 325081860b9SGuo Ren btsti r7, TIF_NEED_RESCHED 326081860b9SGuo Ren bt 1b /* go again */ 327081860b9SGuo Ren#endif 328081860b9SGuo Ren2: 329081860b9SGuo Ren jmpi ret_from_exception 330081860b9SGuo Ren 331081860b9SGuo Ren/* 332081860b9SGuo Ren * a0 = prev task_struct * 333081860b9SGuo Ren * a1 = next task_struct * 334081860b9SGuo Ren * a0 = return next 335081860b9SGuo Ren */ 336081860b9SGuo RenENTRY(__switch_to) 337081860b9SGuo Ren lrw a3, TASK_THREAD 338081860b9SGuo Ren addu a3, a0 339081860b9SGuo Ren 340081860b9SGuo Ren mfcr a2, psr /* Save PSR value */ 341081860b9SGuo Ren stw a2, (a3, THREAD_SR) /* Save PSR in task struct */ 342081860b9SGuo Ren bclri a2, 6 /* Disable interrupts */ 343081860b9SGuo Ren mtcr a2, psr 344081860b9SGuo Ren 345081860b9SGuo Ren SAVE_SWITCH_STACK 346081860b9SGuo Ren 347081860b9SGuo Ren stw sp, (a3, THREAD_KSP) 348081860b9SGuo Ren 349081860b9SGuo Ren#ifdef CONFIG_CPU_HAS_HILO 350081860b9SGuo Ren lrw r10, THREAD_DSPHI 351081860b9SGuo Ren add r10, a3 352081860b9SGuo Ren mfhi r6 353081860b9SGuo Ren mflo r7 354081860b9SGuo Ren stw r6, (r10, 0) /* THREAD_DSPHI */ 355081860b9SGuo Ren stw r7, (r10, 4) /* THREAD_DSPLO */ 356081860b9SGuo Ren mfcr r6, cr14 357081860b9SGuo Ren stw r6, (r10, 8) /* THREAD_DSPCSR */ 358081860b9SGuo Ren#endif 359081860b9SGuo Ren 360081860b9SGuo Ren /* Set up next process to run */ 361081860b9SGuo Ren lrw a3, TASK_THREAD 362081860b9SGuo Ren addu a3, a1 363081860b9SGuo Ren 364081860b9SGuo Ren ldw sp, (a3, THREAD_KSP) /* Set next kernel sp */ 365081860b9SGuo Ren 366081860b9SGuo Ren#ifdef CONFIG_CPU_HAS_HILO 367081860b9SGuo Ren lrw r10, THREAD_DSPHI 368081860b9SGuo Ren add r10, a3 369081860b9SGuo Ren ldw r6, (r10, 8) /* THREAD_DSPCSR */ 370081860b9SGuo Ren mtcr r6, cr14 371081860b9SGuo Ren ldw r6, (r10, 0) /* THREAD_DSPHI */ 372081860b9SGuo Ren ldw r7, (r10, 4) /* THREAD_DSPLO */ 373081860b9SGuo Ren mthi r6 374081860b9SGuo Ren mtlo r7 375081860b9SGuo Ren#endif 376081860b9SGuo Ren 377081860b9SGuo Ren ldw a2, (a3, THREAD_SR) /* Set next PSR */ 378081860b9SGuo Ren mtcr a2, psr 379081860b9SGuo Ren 380081860b9SGuo Ren#if defined(__CSKYABIV2__) 381081860b9SGuo Ren addi r7, a1, TASK_THREAD_INFO 382081860b9SGuo Ren ldw tls, (r7, TINFO_TP_VALUE) 383081860b9SGuo Ren#endif 384081860b9SGuo Ren 385081860b9SGuo Ren RESTORE_SWITCH_STACK 386081860b9SGuo Ren 387081860b9SGuo Ren rts 388081860b9SGuo RenENDPROC(__switch_to) 389