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 43*683fafebSGuo Ren lrw a2, va_pa_offset 44f62e3162SGuo Ren ld.w a2, (a2, 0) 45081860b9SGuo Ren subu r6, a2 46081860b9SGuo Ren bseti r6, 31 47081860b9SGuo Ren 48081860b9SGuo Ren mov a2, a3 49081860b9SGuo Ren lsri a2, _PGDIR_SHIFT 50081860b9SGuo Ren lsli a2, 2 51081860b9SGuo Ren addu r6, a2 52081860b9SGuo Ren ldw r6, (r6) 53081860b9SGuo Ren 54*683fafebSGuo Ren lrw a2, va_pa_offset 55f62e3162SGuo Ren ld.w a2, (a2, 0) 56081860b9SGuo Ren subu r6, a2 57081860b9SGuo Ren bseti r6, 31 58081860b9SGuo Ren 59081860b9SGuo Ren lsri a3, PTE_INDX_SHIFT 60081860b9SGuo Ren lrw a2, PTE_INDX_MSK 61081860b9SGuo Ren and a3, a2 62081860b9SGuo Ren addu r6, a3 63081860b9SGuo Ren ldw a3, (r6) 64081860b9SGuo Ren 65081860b9SGuo Ren movi a2, (_PAGE_PRESENT | \val0) 66081860b9SGuo Ren and a3, a2 67081860b9SGuo Ren cmpne a3, a2 68081860b9SGuo Ren bt \name 69081860b9SGuo Ren 70081860b9SGuo Ren /* First read/write the page, just update the flags */ 71081860b9SGuo Ren ldw a3, (r6) 72081860b9SGuo Ren bgeni a2, PAGE_VALID_BIT 73081860b9SGuo Ren bseti a2, PAGE_ACCESSED_BIT 74081860b9SGuo Ren bseti a2, \val1 75081860b9SGuo Ren bseti a2, \val2 76081860b9SGuo Ren or a3, a2 77081860b9SGuo Ren stw a3, (r6) 78081860b9SGuo Ren 79081860b9SGuo Ren /* Some cpu tlb-hardrefill bypass the cache */ 80081860b9SGuo Ren#ifdef CONFIG_CPU_NEED_TLBSYNC 81081860b9SGuo Ren movi a2, 0x22 82081860b9SGuo Ren bseti a2, 6 83081860b9SGuo Ren mtcr r6, cr22 84081860b9SGuo Ren mtcr a2, cr17 85081860b9SGuo Ren sync 86081860b9SGuo Ren#endif 87081860b9SGuo Ren 88081860b9SGuo Ren mfcr a3, ss2 89081860b9SGuo Ren mfcr r6, ss3 90081860b9SGuo Ren mfcr a2, ss4 91081860b9SGuo Ren rte 92081860b9SGuo Ren\name: 93081860b9SGuo Ren mfcr a3, ss2 94081860b9SGuo Ren mfcr r6, ss3 95081860b9SGuo Ren mfcr a2, ss4 96bf241682SGuo Ren SAVE_ALL 0 97081860b9SGuo Ren.endm 98081860b9SGuo Ren.macro tlbop_end is_write 99081860b9SGuo Ren RD_MEH a2 100081860b9SGuo Ren psrset ee, ie 101081860b9SGuo Ren mov a0, sp 102081860b9SGuo Ren movi a1, \is_write 103081860b9SGuo Ren jbsr do_page_fault 104081860b9SGuo Ren jmpi ret_from_exception 105081860b9SGuo Ren.endm 106081860b9SGuo Ren 107081860b9SGuo Ren.text 108081860b9SGuo Ren 109081860b9SGuo Rentlbop_begin tlbinvalidl, _PAGE_READ, PAGE_VALID_BIT, PAGE_ACCESSED_BIT 110081860b9SGuo Rentlbop_end 0 111081860b9SGuo Ren 112081860b9SGuo Rentlbop_begin tlbinvalids, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT 113081860b9SGuo Rentlbop_end 1 114081860b9SGuo Ren 115081860b9SGuo Rentlbop_begin tlbmodified, _PAGE_WRITE, PAGE_DIRTY_BIT, PAGE_MODIFIED_BIT 116081860b9SGuo Ren#ifndef CONFIG_CPU_HAS_LDSTEX 117081860b9SGuo Renjbsr csky_cmpxchg_fixup 118081860b9SGuo Ren#endif 119081860b9SGuo Rentlbop_end 1 120081860b9SGuo Ren 121081860b9SGuo RenENTRY(csky_systemcall) 122bf241682SGuo Ren SAVE_ALL TRAP0_SIZE 123081860b9SGuo Ren 124081860b9SGuo Ren psrset ee, ie 125081860b9SGuo Ren 126081860b9SGuo Ren lrw r11, __NR_syscalls 127081860b9SGuo Ren cmphs syscallid, r11 /* Check nr of syscall */ 128081860b9SGuo Ren bt ret_from_exception 129081860b9SGuo Ren 130081860b9SGuo Ren lrw r13, sys_call_table 131081860b9SGuo Ren ixw r13, syscallid 132081860b9SGuo Ren ldw r11, (r13) 133081860b9SGuo Ren cmpnei r11, 0 134081860b9SGuo Ren bf ret_from_exception 135081860b9SGuo Ren 136081860b9SGuo Ren mov r9, sp 137081860b9SGuo Ren bmaski r10, THREAD_SHIFT 138081860b9SGuo Ren andn r9, r10 139081860b9SGuo Ren ldw r8, (r9, TINFO_FLAGS) 1402f7932b0SGuo Ren ANDI_R3 r8, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT) 1412f7932b0SGuo Ren cmpnei r8, 0 1422f7932b0SGuo Ren bt csky_syscall_trace 143081860b9SGuo Ren#if defined(__CSKYABIV2__) 144081860b9SGuo Ren subi sp, 8 145081860b9SGuo Ren stw r5, (sp, 0x4) 146081860b9SGuo Ren stw r4, (sp, 0x0) 147081860b9SGuo Ren jsr r11 /* Do system call */ 148081860b9SGuo Ren addi sp, 8 149081860b9SGuo Ren#else 150081860b9SGuo Ren jsr r11 151081860b9SGuo Ren#endif 152081860b9SGuo Ren stw a0, (sp, LSAVE_A0) /* Save return value */ 153081860b9SGuo Ren jmpi ret_from_exception 154081860b9SGuo Ren 1552f7932b0SGuo Rencsky_syscall_trace: 1562f7932b0SGuo Ren mov a0, sp /* sp = pt_regs pointer */ 1572f7932b0SGuo Ren jbsr syscall_trace_enter 158081860b9SGuo Ren /* Prepare args before do system call */ 159081860b9SGuo Ren ldw a0, (sp, LSAVE_A0) 160081860b9SGuo Ren ldw a1, (sp, LSAVE_A1) 161081860b9SGuo Ren ldw a2, (sp, LSAVE_A2) 162081860b9SGuo Ren ldw a3, (sp, LSAVE_A3) 163081860b9SGuo Ren#if defined(__CSKYABIV2__) 164081860b9SGuo Ren subi sp, 8 165081860b9SGuo Ren stw r5, (sp, 0x4) 166081860b9SGuo Ren stw r4, (sp, 0x0) 167081860b9SGuo Ren#else 168081860b9SGuo Ren ldw r6, (sp, LSAVE_A4) 169081860b9SGuo Ren ldw r7, (sp, LSAVE_A5) 170081860b9SGuo Ren#endif 171081860b9SGuo Ren jsr r11 /* Do system call */ 172081860b9SGuo Ren#if defined(__CSKYABIV2__) 173081860b9SGuo Ren addi sp, 8 174081860b9SGuo Ren#endif 175081860b9SGuo Ren stw a0, (sp, LSAVE_A0) /* Save return value */ 176081860b9SGuo Ren 1772f7932b0SGuo Ren mov a0, sp /* right now, sp --> pt_regs */ 1782f7932b0SGuo Ren jbsr syscall_trace_exit 17931295a72SGuo Ren br ret_from_exception 180081860b9SGuo Ren 181081860b9SGuo RenENTRY(ret_from_kernel_thread) 182081860b9SGuo Ren jbsr schedule_tail 183081860b9SGuo Ren mov a0, r8 184081860b9SGuo Ren jsr r9 185081860b9SGuo Ren jbsr ret_from_exception 186081860b9SGuo Ren 187081860b9SGuo RenENTRY(ret_from_fork) 188081860b9SGuo Ren jbsr schedule_tail 189081860b9SGuo Ren mov r9, sp 190081860b9SGuo Ren bmaski r10, THREAD_SHIFT 191081860b9SGuo Ren andn r9, r10 192081860b9SGuo Ren ldw r8, (r9, TINFO_FLAGS) 1932f7932b0SGuo Ren ANDI_R3 r8, (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT) 1942f7932b0SGuo Ren cmpnei r8, 0 195bf241682SGuo Ren bf ret_from_exception 1962f7932b0SGuo Ren mov a0, sp /* sp = pt_regs pointer */ 1972f7932b0SGuo Ren jbsr syscall_trace_exit 198081860b9SGuo Ren 199081860b9SGuo Renret_from_exception: 200081860b9SGuo Ren ld syscallid, (sp, LSAVE_PSR) 201081860b9SGuo Ren btsti syscallid, 31 202081860b9SGuo Ren bt 1f 203081860b9SGuo Ren 204081860b9SGuo Ren /* 205081860b9SGuo Ren * Load address of current->thread_info, Then get address of task_struct 206081860b9SGuo Ren * Get task_needreshed in task_struct 207081860b9SGuo Ren */ 208081860b9SGuo Ren mov r9, sp 209081860b9SGuo Ren bmaski r10, THREAD_SHIFT 210081860b9SGuo Ren andn r9, r10 211081860b9SGuo Ren 212081860b9SGuo Ren ldw r8, (r9, TINFO_FLAGS) 213081860b9SGuo Ren andi r8, (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED) 214081860b9SGuo Ren cmpnei r8, 0 215081860b9SGuo Ren bt exit_work 216bf241682SGuo Ren1: 217bf241682SGuo Ren RESTORE_ALL 218081860b9SGuo Ren 219081860b9SGuo Renexit_work: 220bf241682SGuo Ren lrw syscallid, ret_from_exception 221bf241682SGuo Ren mov lr, syscallid 222bf241682SGuo Ren 223081860b9SGuo Ren btsti r8, TIF_NEED_RESCHED 224081860b9SGuo Ren bt work_resched 225bf241682SGuo Ren 226bf241682SGuo Ren mov a0, sp 227bf241682SGuo Ren mov a1, r8 228bf241682SGuo Ren jmpi do_notify_resume 229081860b9SGuo Ren 230081860b9SGuo Renwork_resched: 231081860b9SGuo Ren jmpi schedule 232081860b9SGuo Ren 233081860b9SGuo RenENTRY(csky_trap) 234bf241682SGuo Ren SAVE_ALL 0 235081860b9SGuo Ren psrset ee 236081860b9SGuo Ren mov a0, sp /* Push Stack pointer arg */ 237081860b9SGuo Ren jbsr trap_c /* Call C-level trap handler */ 238081860b9SGuo Ren jmpi ret_from_exception 239081860b9SGuo Ren 240081860b9SGuo Ren/* 241081860b9SGuo Ren * Prototype from libc for abiv1: 242081860b9SGuo Ren * register unsigned int __result asm("a0"); 243081860b9SGuo Ren * asm( "trap 3" :"=r"(__result)::); 244081860b9SGuo Ren */ 245081860b9SGuo RenENTRY(csky_get_tls) 246081860b9SGuo Ren USPTOKSP 247081860b9SGuo Ren 248081860b9SGuo Ren /* increase epc for continue */ 249081860b9SGuo Ren mfcr a0, epc 250bf241682SGuo Ren addi a0, TRAP0_SIZE 251081860b9SGuo Ren mtcr a0, epc 252081860b9SGuo Ren 253081860b9SGuo Ren /* get current task thread_info with kernel 8K stack */ 254081860b9SGuo Ren bmaski a0, THREAD_SHIFT 255081860b9SGuo Ren not a0 256081860b9SGuo Ren subi sp, 1 257081860b9SGuo Ren and a0, sp 258081860b9SGuo Ren addi sp, 1 259081860b9SGuo Ren 260081860b9SGuo Ren /* get tls */ 261081860b9SGuo Ren ldw a0, (a0, TINFO_TP_VALUE) 262081860b9SGuo Ren 263081860b9SGuo Ren KSPTOUSP 264081860b9SGuo Ren rte 265081860b9SGuo Ren 266081860b9SGuo RenENTRY(csky_irq) 267bf241682SGuo Ren SAVE_ALL 0 268081860b9SGuo Ren psrset ee 269081860b9SGuo Ren 270081860b9SGuo Ren#ifdef CONFIG_PREEMPT 271081860b9SGuo Ren mov r9, sp /* Get current stack pointer */ 272081860b9SGuo Ren bmaski r10, THREAD_SHIFT 273081860b9SGuo Ren andn r9, r10 /* Get thread_info */ 274081860b9SGuo Ren 275081860b9SGuo Ren /* 276081860b9SGuo Ren * Get task_struct->stack.preempt_count for current, 277081860b9SGuo Ren * and increase 1. 278081860b9SGuo Ren */ 279081860b9SGuo Ren ldw r8, (r9, TINFO_PREEMPT) 280081860b9SGuo Ren addi r8, 1 281081860b9SGuo Ren stw r8, (r9, TINFO_PREEMPT) 282081860b9SGuo Ren#endif 283081860b9SGuo Ren 284081860b9SGuo Ren mov a0, sp 285081860b9SGuo Ren jbsr csky_do_IRQ 286081860b9SGuo Ren 287081860b9SGuo Ren#ifdef CONFIG_PREEMPT 288081860b9SGuo Ren subi r8, 1 289081860b9SGuo Ren stw r8, (r9, TINFO_PREEMPT) 290081860b9SGuo Ren cmpnei r8, 0 291081860b9SGuo Ren bt 2f 292081860b9SGuo Ren ldw r8, (r9, TINFO_FLAGS) 293081860b9SGuo Ren btsti r8, TIF_NEED_RESCHED 294081860b9SGuo Ren bf 2f 295081860b9SGuo Ren1: 296081860b9SGuo Ren jbsr preempt_schedule_irq /* irq en/disable is done inside */ 297081860b9SGuo Ren ldw r7, (r9, TINFO_FLAGS) /* get new tasks TI_FLAGS */ 298081860b9SGuo Ren btsti r7, TIF_NEED_RESCHED 299081860b9SGuo Ren bt 1b /* go again */ 300081860b9SGuo Ren#endif 301081860b9SGuo Ren2: 302081860b9SGuo Ren jmpi ret_from_exception 303081860b9SGuo Ren 304081860b9SGuo Ren/* 305081860b9SGuo Ren * a0 = prev task_struct * 306081860b9SGuo Ren * a1 = next task_struct * 307081860b9SGuo Ren * a0 = return next 308081860b9SGuo Ren */ 309081860b9SGuo RenENTRY(__switch_to) 310081860b9SGuo Ren lrw a3, TASK_THREAD 311081860b9SGuo Ren addu a3, a0 312081860b9SGuo Ren 313081860b9SGuo Ren mfcr a2, psr /* Save PSR value */ 314081860b9SGuo Ren stw a2, (a3, THREAD_SR) /* Save PSR in task struct */ 315081860b9SGuo Ren bclri a2, 6 /* Disable interrupts */ 316081860b9SGuo Ren mtcr a2, psr 317081860b9SGuo Ren 318081860b9SGuo Ren SAVE_SWITCH_STACK 319081860b9SGuo Ren 320081860b9SGuo Ren stw sp, (a3, THREAD_KSP) 321081860b9SGuo Ren 322081860b9SGuo Ren /* Set up next process to run */ 323081860b9SGuo Ren lrw a3, TASK_THREAD 324081860b9SGuo Ren addu a3, a1 325081860b9SGuo Ren 326081860b9SGuo Ren ldw sp, (a3, THREAD_KSP) /* Set next kernel sp */ 327081860b9SGuo Ren 328081860b9SGuo Ren ldw a2, (a3, THREAD_SR) /* Set next PSR */ 329081860b9SGuo Ren mtcr a2, psr 330081860b9SGuo Ren 331081860b9SGuo Ren#if defined(__CSKYABIV2__) 332081860b9SGuo Ren addi r7, a1, TASK_THREAD_INFO 333081860b9SGuo Ren ldw tls, (r7, TINFO_TP_VALUE) 334081860b9SGuo Ren#endif 335081860b9SGuo Ren 336081860b9SGuo Ren RESTORE_SWITCH_STACK 337081860b9SGuo Ren 338081860b9SGuo Ren rts 339081860b9SGuo RenENDPROC(__switch_to) 340