1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * linux/arch/m32r/kernel/entry.S 4 * 5 * Copyright (c) 2001, 2002 Hirokazu Takata, Hitoshi Yamamoto, H. Kondo 6 * Copyright (c) 2003 Hitoshi Yamamoto 7 * Copyright (c) 2004 Hirokazu Takata <takata at linux-m32r.org> 8 * 9 * Taken from i386 version. 10 * Copyright (C) 1991, 1992 Linus Torvalds 11 */ 12 13/* 14 * entry.S contains the system-call and fault low-level handling routines. 15 * This also contains the timer-interrupt handler, as well as all interrupts 16 * and faults that can result in a task-switch. 17 * 18 * NOTE: This code handles signal-recognition, which happens every time 19 * after a timer-interrupt and after each system call. 20 * 21 * Stack layout in 'ret_from_system_call': 22 * ptrace needs to have all regs on the stack. 23 * if the order here is changed, it needs to be 24 * updated in fork.c:copy_thread, signal.c:do_signal, 25 * ptrace.c and ptrace.h 26 * 27 * M32R/M32Rx/M32R2 28 * @(sp) - r4 29 * @(0x04,sp) - r5 30 * @(0x08,sp) - r6 31 * @(0x0c,sp) - *pt_regs 32 * @(0x10,sp) - r0 33 * @(0x14,sp) - r1 34 * @(0x18,sp) - r2 35 * @(0x1c,sp) - r3 36 * @(0x20,sp) - r7 37 * @(0x24,sp) - r8 38 * @(0x28,sp) - r9 39 * @(0x2c,sp) - r10 40 * @(0x30,sp) - r11 41 * @(0x34,sp) - r12 42 * @(0x38,sp) - syscall_nr 43 * @(0x3c,sp) - acc0h 44 * @(0x40,sp) - acc0l 45 * @(0x44,sp) - acc1h ; ISA_DSP_LEVEL2 only 46 * @(0x48,sp) - acc1l ; ISA_DSP_LEVEL2 only 47 * @(0x4c,sp) - psw 48 * @(0x50,sp) - bpc 49 * @(0x54,sp) - bbpsw 50 * @(0x58,sp) - bbpc 51 * @(0x5c,sp) - spu (cr3) 52 * @(0x60,sp) - fp (r13) 53 * @(0x64,sp) - lr (r14) 54 * @(0x68,sp) - spi (cr2) 55 * @(0x6c,sp) - orig_r0 56 */ 57 58#include <linux/linkage.h> 59#include <asm/irq.h> 60#include <asm/unistd.h> 61#include <asm/assembler.h> 62#include <asm/thread_info.h> 63#include <asm/errno.h> 64#include <asm/segment.h> 65#include <asm/smp.h> 66#include <asm/page.h> 67#include <asm/m32r.h> 68#include <asm/mmu_context.h> 69#include <asm/asm-offsets.h> 70 71#if !defined(CONFIG_MMU) 72#define sys_madvise sys_ni_syscall 73#define sys_readahead sys_ni_syscall 74#define sys_mprotect sys_ni_syscall 75#define sys_msync sys_ni_syscall 76#define sys_mlock sys_ni_syscall 77#define sys_munlock sys_ni_syscall 78#define sys_mlockall sys_ni_syscall 79#define sys_munlockall sys_ni_syscall 80#define sys_mremap sys_ni_syscall 81#define sys_mincore sys_ni_syscall 82#define sys_remap_file_pages sys_ni_syscall 83#endif /* CONFIG_MMU */ 84 85#define R4(reg) @reg 86#define R5(reg) @(0x04,reg) 87#define R6(reg) @(0x08,reg) 88#define PTREGS(reg) @(0x0C,reg) 89#define R0(reg) @(0x10,reg) 90#define R1(reg) @(0x14,reg) 91#define R2(reg) @(0x18,reg) 92#define R3(reg) @(0x1C,reg) 93#define R7(reg) @(0x20,reg) 94#define R8(reg) @(0x24,reg) 95#define R9(reg) @(0x28,reg) 96#define R10(reg) @(0x2C,reg) 97#define R11(reg) @(0x30,reg) 98#define R12(reg) @(0x34,reg) 99#define SYSCALL_NR(reg) @(0x38,reg) 100#define ACC0H(reg) @(0x3C,reg) 101#define ACC0L(reg) @(0x40,reg) 102#define ACC1H(reg) @(0x44,reg) 103#define ACC1L(reg) @(0x48,reg) 104#define PSW(reg) @(0x4C,reg) 105#define BPC(reg) @(0x50,reg) 106#define BBPSW(reg) @(0x54,reg) 107#define BBPC(reg) @(0x58,reg) 108#define SPU(reg) @(0x5C,reg) 109#define FP(reg) @(0x60,reg) /* FP = R13 */ 110#define LR(reg) @(0x64,reg) 111#define SP(reg) @(0x68,reg) 112#define ORIG_R0(reg) @(0x6C,reg) 113 114#define nr_syscalls ((syscall_table_size)/4) 115 116#ifdef CONFIG_PREEMPT 117#define preempt_stop(x) DISABLE_INTERRUPTS(x) 118#else 119#define preempt_stop(x) 120#define resume_kernel restore_all 121#endif 122 123/* how to get the thread information struct from ASM */ 124#define GET_THREAD_INFO(reg) GET_THREAD_INFO reg 125 .macro GET_THREAD_INFO reg 126 ldi \reg, #-THREAD_SIZE 127 and \reg, sp 128 .endm 129 130ENTRY(ret_from_kernel_thread) 131 pop r0 132 bl schedule_tail 133 GET_THREAD_INFO(r8) 134 ld r0, R0(r8) 135 ld r1, R1(r8) 136 jl r1 137 bra syscall_exit 138 139ENTRY(ret_from_fork) 140 pop r0 141 bl schedule_tail 142 GET_THREAD_INFO(r8) 143 bra syscall_exit 144 145/* 146 * Return to user mode is not as complex as all this looks, 147 * but we want the default path for a system call return to 148 * go as quickly as possible which is why some of this is 149 * less clear than it otherwise should be. 150 */ 151 152 ; userspace resumption stub bypassing syscall exit tracing 153 ALIGN 154ret_from_exception: 155 preempt_stop(r4) 156ret_from_intr: 157 ld r4, PSW(sp) 158#ifdef CONFIG_ISA_M32R2 159 and3 r4, r4, #0x8800 ; check BSM and BPM bits 160#else 161 and3 r4, r4, #0x8000 ; check BSM bit 162#endif 163 beqz r4, resume_kernel 164resume_userspace: 165 DISABLE_INTERRUPTS(r4) ; make sure we don't miss an interrupt 166 ; setting need_resched or sigpending 167 ; between sampling and the iret 168 GET_THREAD_INFO(r8) 169 ld r9, @(TI_FLAGS, r8) 170 and3 r4, r9, #_TIF_WORK_MASK ; is there any work to be done on 171 ; int/exception return? 172 bnez r4, work_pending 173 bra restore_all 174 175#ifdef CONFIG_PREEMPT 176ENTRY(resume_kernel) 177 GET_THREAD_INFO(r8) 178 ld r9, @(TI_PRE_COUNT, r8) ; non-zero preempt_count ? 179 bnez r9, restore_all 180need_resched: 181 ld r9, @(TI_FLAGS, r8) ; need_resched set ? 182 and3 r4, r9, #_TIF_NEED_RESCHED 183 beqz r4, restore_all 184 ld r4, PSW(sp) ; interrupts off (exception path) ? 185 and3 r4, r4, #0x4000 186 beqz r4, restore_all 187 bl preempt_schedule_irq 188 bra need_resched 189#endif 190 191 ; system call handler stub 192ENTRY(system_call) 193 SWITCH_TO_KERNEL_STACK 194 SAVE_ALL 195 ENABLE_INTERRUPTS(r4) ; Enable interrupt 196 st sp, PTREGS(sp) ; implicit pt_regs parameter 197 cmpui r7, #NR_syscalls 198 bnc syscall_badsys 199 st r7, SYSCALL_NR(sp) ; syscall_nr 200 ; system call tracing in operation 201 GET_THREAD_INFO(r8) 202 ld r9, @(TI_FLAGS, r8) 203 and3 r4, r9, #_TIF_SYSCALL_TRACE 204 bnez r4, syscall_trace_entry 205syscall_call: 206 slli r7, #2 ; table jump for the system call 207 LDIMM (r4, sys_call_table) 208 add r7, r4 209 ld r7, @r7 210 jl r7 ; execute system call 211 st r0, R0(sp) ; save the return value 212syscall_exit: 213 DISABLE_INTERRUPTS(r4) ; make sure we don't miss an interrupt 214 ; setting need_resched or sigpending 215 ; between sampling and the iret 216 ld r9, @(TI_FLAGS, r8) 217 and3 r4, r9, #_TIF_ALLWORK_MASK ; current->work 218 bnez r4, syscall_exit_work 219restore_all: 220 RESTORE_ALL 221 222 # perform work that needs to be done immediately before resumption 223 # r9 : flags 224 ALIGN 225work_pending: 226 and3 r4, r9, #_TIF_NEED_RESCHED 227 beqz r4, work_notifysig 228work_resched: 229 bl schedule 230 DISABLE_INTERRUPTS(r4) ; make sure we don't miss an interrupt 231 ; setting need_resched or sigpending 232 ; between sampling and the iret 233 ld r9, @(TI_FLAGS, r8) 234 and3 r4, r9, #_TIF_WORK_MASK ; is there any work to be done other 235 ; than syscall tracing? 236 beqz r4, restore_all 237 and3 r4, r4, #_TIF_NEED_RESCHED 238 bnez r4, work_resched 239 240work_notifysig: ; deal with pending signals and 241 ; notify-resume requests 242 mv r0, sp ; arg1 : struct pt_regs *regs 243 mv r1, r9 ; arg2 : __u32 thread_info_flags 244 bl do_notify_resume 245 bra resume_userspace 246 247 ; perform syscall exit tracing 248 ALIGN 249syscall_trace_entry: 250 ldi r4, #-ENOSYS 251 st r4, R0(sp) 252 bl do_syscall_trace 253 ld r0, ORIG_R0(sp) 254 ld r1, R1(sp) 255 ld r2, R2(sp) 256 ld r3, R3(sp) 257 ld r4, R4(sp) 258 ld r5, R5(sp) 259 ld r6, R6(sp) 260 ld r7, SYSCALL_NR(sp) 261 cmpui r7, #NR_syscalls 262 bc syscall_call 263 bra syscall_exit 264 265 ; perform syscall exit tracing 266 ALIGN 267syscall_exit_work: 268 ld r9, @(TI_FLAGS, r8) 269 and3 r4, r9, #_TIF_SYSCALL_TRACE 270 beqz r4, work_pending 271 ENABLE_INTERRUPTS(r4) ; could let do_syscall_trace() call 272 ; schedule() instead 273 bl do_syscall_trace 274 bra resume_userspace 275 276 ALIGN 277syscall_fault: 278 SAVE_ALL 279 GET_THREAD_INFO(r8) 280 ldi r4, #-EFAULT 281 st r4, R0(sp) 282 bra resume_userspace 283 284 ALIGN 285syscall_badsys: 286 ldi r4, #-ENOSYS 287 st r4, R0(sp) 288 bra resume_userspace 289 290 .global eit_vector 291 292 .equ ei_vec_table, eit_vector + 0x0200 293 294/* 295 * EI handler routine 296 */ 297ENTRY(ei_handler) 298#if defined(CONFIG_CHIP_M32700) 299 ; WORKAROUND: force to clear SM bit and use the kernel stack (SPI). 300 SWITCH_TO_KERNEL_STACK 301#endif 302 SAVE_ALL 303 mv r1, sp ; arg1(regs) 304 ; get ICU status 305 seth r0, #shigh(M32R_ICU_ISTS_ADDR) 306 ld r0, @(low(M32R_ICU_ISTS_ADDR),r0) 307 push r0 308#if defined(CONFIG_SMP) 309 /* 310 * If IRQ == 0 --> Nothing to do, Not write IMASK 311 * If IRQ == IPI --> Do IPI handler, Not write IMASK 312 * If IRQ != 0, IPI --> Do do_IRQ(), Write IMASK 313 */ 314 slli r0, #4 315 srli r0, #24 ; r0(irq_num<<2) 316 ;; IRQ exist check 317#if defined(CONFIG_CHIP_M32700) 318 /* WORKAROUND: IMASK bug M32700-TS1, TS2 chip. */ 319 bnez r0, 0f 320 ld24 r14, #0x00070000 321 seth r0, #shigh(M32R_ICU_IMASK_ADDR) 322 st r14, @(low(M32R_ICU_IMASK_ADDR),r0) 323 bra 1f 324 .fillinsn 3250: 326#endif /* CONFIG_CHIP_M32700 */ 327 beqz r0, 1f ; if (!irq_num) goto exit 328 ;; IPI check 329 cmpi r0, #(M32R_IRQ_IPI0<<2) ; ISN < IPI0 check 330 bc 2f 331 cmpi r0, #((M32R_IRQ_IPI7+1)<<2) ; ISN > IPI7 check 332 bnc 2f 333 LDIMM (r2, ei_vec_table) 334 add r2, r0 335 ld r2, @r2 336 beqz r2, 1f ; if (no IPI handler) goto exit 337 mv r0, r1 ; arg0(regs) 338 jl r2 339 .fillinsn 3401: 341 addi sp, #4 342 bra restore_all 343 .fillinsn 3442: 345 srli r0, #2 346#else /* not CONFIG_SMP */ 347 srli r0, #22 ; r0(irq) 348#endif /* not CONFIG_SMP */ 349 350#if defined(CONFIG_PLAT_HAS_INT1ICU) 351 add3 r2, r0, #-(M32R_IRQ_INT1) ; INT1# interrupt 352 bnez r2, 3f 353 seth r0, #shigh(M32R_INT1ICU_ISTS) 354 lduh r0, @(low(M32R_INT1ICU_ISTS),r0) ; bit10-6 : ISN 355 slli r0, #21 356 srli r0, #27 ; ISN 357 addi r0, #(M32R_INT1ICU_IRQ_BASE) 358 bra check_end 359 .fillinsn 3603: 361#endif /* CONFIG_PLAT_HAS_INT1ICU */ 362#if defined(CONFIG_PLAT_HAS_INT0ICU) 363 add3 r2, r0, #-(M32R_IRQ_INT0) ; INT0# interrupt 364 bnez r2, 4f 365 seth r0, #shigh(M32R_INT0ICU_ISTS) 366 lduh r0, @(low(M32R_INT0ICU_ISTS),r0) ; bit10-6 : ISN 367 slli r0, #21 368 srli r0, #27 ; ISN 369 add3 r0, r0, #(M32R_INT0ICU_IRQ_BASE) 370 bra check_end 371 .fillinsn 3724: 373#endif /* CONFIG_PLAT_HAS_INT0ICU */ 374#if defined(CONFIG_PLAT_HAS_INT2ICU) 375 add3 r2, r0, #-(M32R_IRQ_INT2) ; INT2# interrupt 376 bnez r2, 5f 377 seth r0, #shigh(M32R_INT2ICU_ISTS) 378 lduh r0, @(low(M32R_INT2ICU_ISTS),r0) ; bit10-6 : ISN 379 slli r0, #21 380 srli r0, #27 ; ISN 381 add3 r0, r0, #(M32R_INT2ICU_IRQ_BASE) 382 ; bra check_end 383 .fillinsn 3845: 385#endif /* CONFIG_PLAT_HAS_INT2ICU */ 386 387check_end: 388 bl do_IRQ 389 pop r14 390 seth r0, #shigh(M32R_ICU_IMASK_ADDR) 391 st r14, @(low(M32R_ICU_IMASK_ADDR),r0) 392 bra ret_from_intr 393 394/* 395 * Default EIT handler 396 */ 397 ALIGN 398int_msg: 399 .asciz "Unknown interrupt\n" 400 .byte 0 401 402ENTRY(default_eit_handler) 403 push r0 404 mvfc r0, psw 405 push r1 406 push r2 407 push r3 408 push r0 409 LDIMM (r0, __KERNEL_DS) 410 mv r0, r1 411 mv r0, r2 412 LDIMM (r0, int_msg) 413 bl printk 414 pop r0 415 pop r3 416 pop r2 417 pop r1 418 mvtc r0, psw 419 pop r0 420infinit: 421 bra infinit 422 423#ifdef CONFIG_MMU 424/* 425 * Access Exception handler 426 */ 427ENTRY(ace_handler) 428 SWITCH_TO_KERNEL_STACK 429 SAVE_ALL 430 431 seth r2, #shigh(MMU_REG_BASE) /* Check status register */ 432 ld r4, @(low(MESTS_offset),r2) 433 st r4, @(low(MESTS_offset),r2) 434 srl3 r1, r4, #4 435#ifdef CONFIG_CHIP_M32700 436 and3 r1, r1, #0x0000ffff 437 ; WORKAROUND: ignore TME bit for the M32700(TS1). 438#endif /* CONFIG_CHIP_M32700 */ 439 beqz r1, inst 440oprand: 441 ld r2, @(low(MDEVA_offset),r2) ; set address 442 srli r1, #1 443 bra 1f 444inst: 445 and3 r1, r4, #2 446 srli r1, #1 447 or3 r1, r1, #8 448 mvfc r2, bpc ; set address 449 .fillinsn 4501: 451 mvfc r3, psw 452 mv r0, sp 453 and3 r3, r3, 0x800 454 srli r3, #9 455 or r1, r3 456 /* 457 * do_page_fault(): 458 * r0 : struct pt_regs *regs 459 * r1 : unsigned long error-code 460 * r2 : unsigned long address 461 * error-code: 462 * +------+------+------+------+ 463 * | bit3 | bit2 | bit1 | bit0 | 464 * +------+------+------+------+ 465 * bit 3 == 0:means data, 1:means instruction 466 * bit 2 == 0:means kernel, 1:means user-mode 467 * bit 1 == 0:means read, 1:means write 468 * bit 0 == 0:means no page found 1:means protection fault 469 * 470 */ 471 bl do_page_fault 472 bra ret_from_intr 473#endif /* CONFIG_MMU */ 474 475 476ENTRY(alignment_check) 477 /* void alignment_check(int error_code) */ 478 SWITCH_TO_KERNEL_STACK 479 SAVE_ALL 480 ldi r1, #0x30 ; error_code 481 mv r0, sp ; pt_regs 482 bl do_alignment_check 483error_code: 484 bra ret_from_exception 485 486ENTRY(rie_handler) 487 /* void rie_handler(int error_code) */ 488 SWITCH_TO_KERNEL_STACK 489 SAVE_ALL 490 ldi r1, #0x20 ; error_code 491 mv r0, sp ; pt_regs 492 bl do_rie_handler 493 bra error_code 494 495ENTRY(pie_handler) 496 /* void pie_handler(int error_code) */ 497 SWITCH_TO_KERNEL_STACK 498 SAVE_ALL 499 ldi r1, #0 ; error_code ; FIXME 500 mv r0, sp ; pt_regs 501 bl do_pie_handler 502 bra error_code 503 504ENTRY(debug_trap) 505 /* void debug_trap(void) */ 506 .global withdraw_debug_trap 507 SWITCH_TO_KERNEL_STACK 508 SAVE_ALL 509 mv r0, sp ; pt_regs 510 bl withdraw_debug_trap 511 ldi r1, #0 ; error_code 512 mv r0, sp ; pt_regs 513 bl do_debug_trap 514 bra error_code 515 516ENTRY(ill_trap) 517 /* void ill_trap(void) */ 518 SWITCH_TO_KERNEL_STACK 519 SAVE_ALL 520 ldi r1, #0 ; error_code ; FIXME 521 mv r0, sp ; pt_regs 522 bl do_ill_trap 523 bra error_code 524 525ENTRY(cache_flushing_handler) 526 /* void _flush_cache_all(void); */ 527 .global _flush_cache_all 528 SWITCH_TO_KERNEL_STACK 529 push r0 530 push r1 531 push r2 532 push r3 533 push r4 534 push r5 535 push r6 536 push r7 537 push lr 538 bl _flush_cache_all 539 pop lr 540 pop r7 541 pop r6 542 pop r5 543 pop r4 544 pop r3 545 pop r2 546 pop r1 547 pop r0 548 rte 549 550 .section .rodata,"a" 551#include "syscall_table.S" 552 553syscall_table_size=(.-sys_call_table) 554