11da177e4SLinus Torvalds/* 21da177e4SLinus Torvalds * This file is subject to the terms and conditions of the GNU General Public 31da177e4SLinus Torvalds * License. See the file "COPYING" in the main directory of this archive 41da177e4SLinus Torvalds * for more details. 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Copyright (C) 1994 - 2000, 2001, 2003 Ralf Baechle 71da177e4SLinus Torvalds * Copyright (C) 1999, 2000 Silicon Graphics, Inc. 8619b6e18SMaciej W. Rozycki * Copyright (C) 2002, 2007 Maciej W. Rozycki 92a0b24f5SSteven J. Hill * Copyright (C) 2001, 2012 MIPS Technologies, Inc. All rights reserved. 101da177e4SLinus Torvalds */ 111da177e4SLinus Torvalds#include <linux/init.h> 121da177e4SLinus Torvalds 131da177e4SLinus Torvalds#include <asm/asm.h> 1441c594abSRalf Baechle#include <asm/asmmacro.h> 151da177e4SLinus Torvalds#include <asm/cacheops.h> 16192ef366SRalf Baechle#include <asm/irqflags.h> 171da177e4SLinus Torvalds#include <asm/regdef.h> 181da177e4SLinus Torvalds#include <asm/fpregdef.h> 191da177e4SLinus Torvalds#include <asm/mipsregs.h> 201da177e4SLinus Torvalds#include <asm/stackframe.h> 2112dbb04fSPaul Burton#include <asm/sync.h> 22c65a5480SAtsushi Nemoto#include <asm/thread_info.h> 231da177e4SLinus Torvalds 241da177e4SLinus Torvalds __INIT 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds/* 271da177e4SLinus Torvalds * General exception vector for all other CPUs. 281da177e4SLinus Torvalds * 291da177e4SLinus Torvalds * Be careful when changing this, it has to be at most 128 bytes 301da177e4SLinus Torvalds * to fit into space reserved for the exception handler. 311da177e4SLinus Torvalds */ 321da177e4SLinus TorvaldsNESTED(except_vec3_generic, 0, sp) 331da177e4SLinus Torvalds .set push 341da177e4SLinus Torvalds .set noat 351da177e4SLinus Torvalds mfc0 k1, CP0_CAUSE 361da177e4SLinus Torvalds andi k1, k1, 0x7c 37875d43e7SRalf Baechle#ifdef CONFIG_64BIT 381da177e4SLinus Torvalds dsll k1, k1, 1 391da177e4SLinus Torvalds#endif 401da177e4SLinus Torvalds PTR_L k0, exception_handlers(k1) 411da177e4SLinus Torvalds jr k0 421da177e4SLinus Torvalds .set pop 431da177e4SLinus Torvalds END(except_vec3_generic) 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds/* 461da177e4SLinus Torvalds * General exception handler for CPUs with virtual coherency exception. 471da177e4SLinus Torvalds * 481da177e4SLinus Torvalds * Be careful when changing this, it has to be at most 256 (as a special 491da177e4SLinus Torvalds * exception) bytes to fit into space reserved for the exception handler. 501da177e4SLinus Torvalds */ 511da177e4SLinus TorvaldsNESTED(except_vec3_r4000, 0, sp) 521da177e4SLinus Torvalds .set push 53a809d460SRalf Baechle .set arch=r4000 541da177e4SLinus Torvalds .set noat 551da177e4SLinus Torvalds mfc0 k1, CP0_CAUSE 561da177e4SLinus Torvalds li k0, 31<<2 571da177e4SLinus Torvalds andi k1, k1, 0x7c 581da177e4SLinus Torvalds .set push 591da177e4SLinus Torvalds .set noreorder 601da177e4SLinus Torvalds .set nomacro 611da177e4SLinus Torvalds beq k1, k0, handle_vced 621da177e4SLinus Torvalds li k0, 14<<2 631da177e4SLinus Torvalds beq k1, k0, handle_vcei 64875d43e7SRalf Baechle#ifdef CONFIG_64BIT 651da177e4SLinus Torvalds dsll k1, k1, 1 661da177e4SLinus Torvalds#endif 671da177e4SLinus Torvalds .set pop 681da177e4SLinus Torvalds PTR_L k0, exception_handlers(k1) 691da177e4SLinus Torvalds jr k0 701da177e4SLinus Torvalds 711da177e4SLinus Torvalds /* 721da177e4SLinus Torvalds * Big shit, we now may have two dirty primary cache lines for the same 7369903d65SThiemo Seufer * physical address. We can safely invalidate the line pointed to by 741da177e4SLinus Torvalds * c0_badvaddr because after return from this exception handler the 751da177e4SLinus Torvalds * load / store will be re-executed. 761da177e4SLinus Torvalds */ 771da177e4SLinus Torvaldshandle_vced: 7869903d65SThiemo Seufer MFC0 k0, CP0_BADVADDR 791da177e4SLinus Torvalds li k1, -4 # Is this ... 801da177e4SLinus Torvalds and k0, k1 # ... really needed? 811da177e4SLinus Torvalds mtc0 zero, CP0_TAGLO 821da177e4SLinus Torvalds cache Index_Store_Tag_D, (k0) 831da177e4SLinus Torvalds cache Hit_Writeback_Inv_SD, (k0) 841da177e4SLinus Torvalds#ifdef CONFIG_PROC_FS 851da177e4SLinus Torvalds PTR_LA k0, vced_count 861da177e4SLinus Torvalds lw k1, (k0) 871da177e4SLinus Torvalds addiu k1, 1 881da177e4SLinus Torvalds sw k1, (k0) 891da177e4SLinus Torvalds#endif 901da177e4SLinus Torvalds eret 911da177e4SLinus Torvalds 921da177e4SLinus Torvaldshandle_vcei: 931da177e4SLinus Torvalds MFC0 k0, CP0_BADVADDR 941da177e4SLinus Torvalds cache Hit_Writeback_Inv_SD, (k0) # also cleans pi 951da177e4SLinus Torvalds#ifdef CONFIG_PROC_FS 961da177e4SLinus Torvalds PTR_LA k0, vcei_count 971da177e4SLinus Torvalds lw k1, (k0) 981da177e4SLinus Torvalds addiu k1, 1 991da177e4SLinus Torvalds sw k1, (k0) 1001da177e4SLinus Torvalds#endif 1011da177e4SLinus Torvalds eret 1021da177e4SLinus Torvalds .set pop 1031da177e4SLinus Torvalds END(except_vec3_r4000) 1041da177e4SLinus Torvalds 105e4ac58afSRalf Baechle __FINIT 106e4ac58afSRalf Baechle 107c65a5480SAtsushi Nemoto .align 5 /* 32 byte rollback region */ 108087d990bSRalf BaechleLEAF(__r4k_wait) 109c65a5480SAtsushi Nemoto .set push 110c65a5480SAtsushi Nemoto .set noreorder 111c65a5480SAtsushi Nemoto /* start of rollback region */ 112c65a5480SAtsushi Nemoto LONG_L t0, TI_FLAGS($28) 113c65a5480SAtsushi Nemoto nop 114c65a5480SAtsushi Nemoto andi t0, _TIF_NEED_RESCHED 115c65a5480SAtsushi Nemoto bnez t0, 1f 116c65a5480SAtsushi Nemoto nop 117c65a5480SAtsushi Nemoto nop 118c65a5480SAtsushi Nemoto nop 1192a0b24f5SSteven J. Hill#ifdef CONFIG_CPU_MICROMIPS 1202a0b24f5SSteven J. Hill nop 1212a0b24f5SSteven J. Hill nop 1222a0b24f5SSteven J. Hill nop 1232a0b24f5SSteven J. Hill nop 1242a0b24f5SSteven J. Hill#endif 125938c1282SMarkos Chandras .set MIPS_ISA_ARCH_LEVEL_RAW 126c65a5480SAtsushi Nemoto wait 127c65a5480SAtsushi Nemoto /* end of rollback region (the region size must be power of two) */ 128c65a5480SAtsushi Nemoto1: 129c65a5480SAtsushi Nemoto jr ra 1302a0b24f5SSteven J. Hill nop 1312a0b24f5SSteven J. Hill .set pop 132087d990bSRalf Baechle END(__r4k_wait) 133c65a5480SAtsushi Nemoto 134c65a5480SAtsushi Nemoto .macro BUILD_ROLLBACK_PROLOGUE handler 135c65a5480SAtsushi Nemoto FEXPORT(rollback_\handler) 136c65a5480SAtsushi Nemoto .set push 137c65a5480SAtsushi Nemoto .set noat 138c65a5480SAtsushi Nemoto MFC0 k0, CP0_EPC 139087d990bSRalf Baechle PTR_LA k1, __r4k_wait 140c65a5480SAtsushi Nemoto ori k0, 0x1f /* 32 byte rollback region */ 141c65a5480SAtsushi Nemoto xori k0, 0x1f 1421eefcbc8SPaul Burton bne k0, k1, \handler 143c65a5480SAtsushi Nemoto MTC0 k0, CP0_EPC 144c65a5480SAtsushi Nemoto .set pop 145c65a5480SAtsushi Nemoto .endm 146c65a5480SAtsushi Nemoto 147e4ac58afSRalf Baechle .align 5 148c65a5480SAtsushi NemotoBUILD_ROLLBACK_PROLOGUE handle_int 149e4ac58afSRalf BaechleNESTED(handle_int, PT_SIZE, sp) 150866b6a89SCorey Minyard .cfi_signal_frame 151fe99f1b1SChris Dearman#ifdef CONFIG_TRACE_IRQFLAGS 152fe99f1b1SChris Dearman /* 153fe99f1b1SChris Dearman * Check to see if the interrupted code has just disabled 154fe99f1b1SChris Dearman * interrupts and ignore this interrupt for now if so. 155fe99f1b1SChris Dearman * 156fe99f1b1SChris Dearman * local_irq_disable() disables interrupts and then calls 157fe99f1b1SChris Dearman * trace_hardirqs_off() to track the state. If an interrupt is taken 158fe99f1b1SChris Dearman * after interrupts are disabled but before the state is updated 159fe99f1b1SChris Dearman * it will appear to restore_all that it is incorrectly returning with 160fe99f1b1SChris Dearman * interrupts disabled 161fe99f1b1SChris Dearman */ 162fe99f1b1SChris Dearman .set push 163fe99f1b1SChris Dearman .set noat 164fe99f1b1SChris Dearman mfc0 k0, CP0_STATUS 165455481fcSThomas Bogendoerfer#if defined(CONFIG_CPU_R3000) 166fe99f1b1SChris Dearman and k0, ST0_IEP 167fe99f1b1SChris Dearman bnez k0, 1f 168fe99f1b1SChris Dearman 169c6563e85SAtsushi Nemoto mfc0 k0, CP0_EPC 170fe99f1b1SChris Dearman .set noreorder 171fe99f1b1SChris Dearman j k0 172fe99f1b1SChris Dearman rfe 173fe99f1b1SChris Dearman#else 174fe99f1b1SChris Dearman and k0, ST0_IE 175fe99f1b1SChris Dearman bnez k0, 1f 176fe99f1b1SChris Dearman 177fe99f1b1SChris Dearman eret 178fe99f1b1SChris Dearman#endif 179fe99f1b1SChris Dearman1: 180fe99f1b1SChris Dearman .set pop 181fe99f1b1SChris Dearman#endif 182866b6a89SCorey Minyard SAVE_ALL docfi=1 183e4ac58afSRalf Baechle CLI 184192ef366SRalf Baechle TRACE_IRQS_OFF 185e4ac58afSRalf Baechle 186937a8015SRalf Baechle LONG_L s0, TI_REGS($28) 187937a8015SRalf Baechle LONG_S sp, TI_REGS($28) 188dda45f70SMatt Redfearn 189dda45f70SMatt Redfearn /* 190dda45f70SMatt Redfearn * SAVE_ALL ensures we are using a valid kernel stack for the thread. 191dda45f70SMatt Redfearn * Check if we are already using the IRQ stack. 192dda45f70SMatt Redfearn */ 193dda45f70SMatt Redfearn move s1, sp # Preserve the sp 194dda45f70SMatt Redfearn 195dda45f70SMatt Redfearn /* Get IRQ stack for this CPU */ 196dda45f70SMatt Redfearn ASM_CPUID_MFC0 k0, ASM_SMP_CPUID_REG 197dda45f70SMatt Redfearn#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32) 198dda45f70SMatt Redfearn lui k1, %hi(irq_stack) 199dda45f70SMatt Redfearn#else 200dda45f70SMatt Redfearn lui k1, %highest(irq_stack) 201dda45f70SMatt Redfearn daddiu k1, %higher(irq_stack) 202dda45f70SMatt Redfearn dsll k1, 16 203dda45f70SMatt Redfearn daddiu k1, %hi(irq_stack) 204dda45f70SMatt Redfearn dsll k1, 16 205dda45f70SMatt Redfearn#endif 206dda45f70SMatt Redfearn LONG_SRL k0, SMP_CPUID_PTRSHIFT 207dda45f70SMatt Redfearn LONG_ADDU k1, k0 208dda45f70SMatt Redfearn LONG_L t0, %lo(irq_stack)(k1) 209dda45f70SMatt Redfearn 210dda45f70SMatt Redfearn # Check if already on IRQ stack 211dda45f70SMatt Redfearn PTR_LI t1, ~(_THREAD_SIZE-1) 212dda45f70SMatt Redfearn and t1, t1, sp 213dda45f70SMatt Redfearn beq t0, t1, 2f 214dda45f70SMatt Redfearn 215dda45f70SMatt Redfearn /* Switch to IRQ stack */ 216db8466c5SMatt Redfearn li t1, _IRQ_STACK_START 217dda45f70SMatt Redfearn PTR_ADD sp, t0, t1 218dda45f70SMatt Redfearn 219db8466c5SMatt Redfearn /* Save task's sp on IRQ stack so that unwinding can follow it */ 220db8466c5SMatt Redfearn LONG_S s1, 0(sp) 221dda45f70SMatt Redfearn2: 222dda45f70SMatt Redfearn jal plat_irq_dispatch 223dda45f70SMatt Redfearn 224dda45f70SMatt Redfearn /* Restore sp */ 225dda45f70SMatt Redfearn move sp, s1 226dda45f70SMatt Redfearn 227dda45f70SMatt Redfearn j ret_from_irq 2282a0b24f5SSteven J. Hill#ifdef CONFIG_CPU_MICROMIPS 2292a0b24f5SSteven J. Hill nop 2302a0b24f5SSteven J. Hill#endif 231e4ac58afSRalf Baechle END(handle_int) 232e4ac58afSRalf Baechle 233e4ac58afSRalf Baechle __INIT 234e4ac58afSRalf Baechle 2351da177e4SLinus Torvalds/* 2361da177e4SLinus Torvalds * Special interrupt vector for MIPS64 ISA & embedded MIPS processors. 2371da177e4SLinus Torvalds * This is a dedicated interrupt exception vector which reduces the 2381da177e4SLinus Torvalds * interrupt processing overhead. The jump instruction will be replaced 2391da177e4SLinus Torvalds * at the initialization time. 2401da177e4SLinus Torvalds * 2411da177e4SLinus Torvalds * Be careful when changing this, it has to be at most 128 bytes 2421da177e4SLinus Torvalds * to fit into space reserved for the exception handler. 2431da177e4SLinus Torvalds */ 2441da177e4SLinus TorvaldsNESTED(except_vec4, 0, sp) 2451da177e4SLinus Torvalds1: j 1b /* Dummy, will be replaced */ 2461da177e4SLinus Torvalds END(except_vec4) 2471da177e4SLinus Torvalds 2481da177e4SLinus Torvalds/* 2491da177e4SLinus Torvalds * EJTAG debug exception handler. 2501da177e4SLinus Torvalds * The EJTAG debug exception entry point is 0xbfc00480, which 2512a0b24f5SSteven J. Hill * normally is in the boot PROM, so the boot PROM must do an 2521da177e4SLinus Torvalds * unconditional jump to this vector. 2531da177e4SLinus Torvalds */ 2541da177e4SLinus TorvaldsNESTED(except_vec_ejtag_debug, 0, sp) 2551da177e4SLinus Torvalds j ejtag_debug_handler 2562a0b24f5SSteven J. Hill#ifdef CONFIG_CPU_MICROMIPS 2572a0b24f5SSteven J. Hill nop 2582a0b24f5SSteven J. Hill#endif 2591da177e4SLinus Torvalds END(except_vec_ejtag_debug) 2601da177e4SLinus Torvalds 2611da177e4SLinus Torvalds __FINIT 2621da177e4SLinus Torvalds 2631da177e4SLinus Torvalds/* 264e01402b1SRalf Baechle * Vectored interrupt handler. 265e01402b1SRalf Baechle * This prototype is copied to ebase + n*IntCtl.VS and patched 266e01402b1SRalf Baechle * to invoke the handler 267e01402b1SRalf Baechle */ 268c65a5480SAtsushi NemotoBUILD_ROLLBACK_PROLOGUE except_vec_vi 269e01402b1SRalf BaechleNESTED(except_vec_vi, 0, sp) 270866b6a89SCorey Minyard SAVE_SOME docfi=1 271866b6a89SCorey Minyard SAVE_AT docfi=1 272e01402b1SRalf Baechle .set push 273e01402b1SRalf Baechle .set noreorder 2742a0b24f5SSteven J. Hill PTR_LA v1, except_vec_vi_handler 2757df42461SRalf BaechleFEXPORT(except_vec_vi_lui) 276e01402b1SRalf Baechle lui v0, 0 /* Patched */ 2772a0b24f5SSteven J. Hill jr v1 2787df42461SRalf BaechleFEXPORT(except_vec_vi_ori) 279e01402b1SRalf Baechle ori v0, 0 /* Patched */ 280e01402b1SRalf Baechle .set pop 281e01402b1SRalf Baechle END(except_vec_vi) 282e01402b1SRalf BaechleEXPORT(except_vec_vi_end) 283e01402b1SRalf Baechle 284e01402b1SRalf Baechle/* 285e01402b1SRalf Baechle * Common Vectored Interrupt code 286e01402b1SRalf Baechle * Complete the register saves and invoke the handler which is passed in $v0 287e01402b1SRalf Baechle */ 288e01402b1SRalf BaechleNESTED(except_vec_vi_handler, 0, sp) 289e01402b1SRalf Baechle SAVE_TEMP 290e01402b1SRalf Baechle SAVE_STATIC 291e01402b1SRalf Baechle CLI 2928c364435SRalf Baechle#ifdef CONFIG_TRACE_IRQFLAGS 2938c364435SRalf Baechle move s0, v0 294192ef366SRalf Baechle TRACE_IRQS_OFF 2958c364435SRalf Baechle move v0, s0 2968c364435SRalf Baechle#endif 297937a8015SRalf Baechle 298937a8015SRalf Baechle LONG_L s0, TI_REGS($28) 299937a8015SRalf Baechle LONG_S sp, TI_REGS($28) 300dda45f70SMatt Redfearn 301dda45f70SMatt Redfearn /* 302dda45f70SMatt Redfearn * SAVE_ALL ensures we are using a valid kernel stack for the thread. 303dda45f70SMatt Redfearn * Check if we are already using the IRQ stack. 304dda45f70SMatt Redfearn */ 305dda45f70SMatt Redfearn move s1, sp # Preserve the sp 306dda45f70SMatt Redfearn 307dda45f70SMatt Redfearn /* Get IRQ stack for this CPU */ 308dda45f70SMatt Redfearn ASM_CPUID_MFC0 k0, ASM_SMP_CPUID_REG 309dda45f70SMatt Redfearn#if defined(CONFIG_32BIT) || defined(KBUILD_64BIT_SYM32) 310dda45f70SMatt Redfearn lui k1, %hi(irq_stack) 311dda45f70SMatt Redfearn#else 312dda45f70SMatt Redfearn lui k1, %highest(irq_stack) 313dda45f70SMatt Redfearn daddiu k1, %higher(irq_stack) 314dda45f70SMatt Redfearn dsll k1, 16 315dda45f70SMatt Redfearn daddiu k1, %hi(irq_stack) 316dda45f70SMatt Redfearn dsll k1, 16 317dda45f70SMatt Redfearn#endif 318dda45f70SMatt Redfearn LONG_SRL k0, SMP_CPUID_PTRSHIFT 319dda45f70SMatt Redfearn LONG_ADDU k1, k0 320dda45f70SMatt Redfearn LONG_L t0, %lo(irq_stack)(k1) 321dda45f70SMatt Redfearn 322dda45f70SMatt Redfearn # Check if already on IRQ stack 323dda45f70SMatt Redfearn PTR_LI t1, ~(_THREAD_SIZE-1) 324dda45f70SMatt Redfearn and t1, t1, sp 325dda45f70SMatt Redfearn beq t0, t1, 2f 326dda45f70SMatt Redfearn 327dda45f70SMatt Redfearn /* Switch to IRQ stack */ 328db8466c5SMatt Redfearn li t1, _IRQ_STACK_START 329dda45f70SMatt Redfearn PTR_ADD sp, t0, t1 330dda45f70SMatt Redfearn 331db8466c5SMatt Redfearn /* Save task's sp on IRQ stack so that unwinding can follow it */ 332db8466c5SMatt Redfearn LONG_S s1, 0(sp) 333dda45f70SMatt Redfearn2: 334c25f8064SMatt Redfearn jalr v0 335dda45f70SMatt Redfearn 336dda45f70SMatt Redfearn /* Restore sp */ 337dda45f70SMatt Redfearn move sp, s1 338dda45f70SMatt Redfearn 339dda45f70SMatt Redfearn j ret_from_irq 340e01402b1SRalf Baechle END(except_vec_vi_handler) 341e01402b1SRalf Baechle 342e01402b1SRalf Baechle/* 3431da177e4SLinus Torvalds * EJTAG debug exception handler. 3441da177e4SLinus Torvalds */ 3451da177e4SLinus TorvaldsNESTED(ejtag_debug_handler, PT_SIZE, sp) 3461da177e4SLinus Torvalds .set push 3471da177e4SLinus Torvalds .set noat 3481da177e4SLinus Torvalds MTC0 k0, CP0_DESAVE 3491da177e4SLinus Torvalds mfc0 k0, CP0_DEBUG 3501da177e4SLinus Torvalds 351ee54d379STiezhu Yang andi k0, k0, MIPS_DEBUG_DBP # Check for SDBBP. 352ee54d379STiezhu Yang beqz k0, ejtag_return 3531da177e4SLinus Torvalds 354c8bf3805SHeiher#ifdef CONFIG_SMP 355c8bf3805SHeiher1: PTR_LA k0, ejtag_debug_buffer_spinlock 35612dbb04fSPaul Burton __SYNC(full, loongson3_war) 3574dee90d7SPaul Burton2: ll k0, 0(k0) 3584dee90d7SPaul Burton bnez k0, 2b 359c8bf3805SHeiher PTR_LA k0, ejtag_debug_buffer_spinlock 360c8bf3805SHeiher sc k0, 0(k0) 361c8bf3805SHeiher beqz k0, 1b 362c8bf3805SHeiher# ifdef CONFIG_WEAK_REORDERING_BEYOND_LLSC 363c8bf3805SHeiher sync 364c8bf3805SHeiher# endif 365c8bf3805SHeiher 3661da177e4SLinus Torvalds PTR_LA k0, ejtag_debug_buffer 3671da177e4SLinus Torvalds LONG_S k1, 0(k0) 368c8bf3805SHeiher 369c8bf3805SHeiher ASM_CPUID_MFC0 k1, ASM_SMP_CPUID_REG 370c8bf3805SHeiher PTR_SRL k1, SMP_CPUID_PTRSHIFT 371c8bf3805SHeiher PTR_SLL k1, LONGLOG 372c8bf3805SHeiher PTR_LA k0, ejtag_debug_buffer_per_cpu 373c8bf3805SHeiher PTR_ADDU k0, k1 374c8bf3805SHeiher 375c8bf3805SHeiher PTR_LA k1, ejtag_debug_buffer 376c8bf3805SHeiher LONG_L k1, 0(k1) 377c8bf3805SHeiher LONG_S k1, 0(k0) 378c8bf3805SHeiher 379c8bf3805SHeiher PTR_LA k0, ejtag_debug_buffer_spinlock 380c8bf3805SHeiher sw zero, 0(k0) 381c8bf3805SHeiher#else 382c8bf3805SHeiher PTR_LA k0, ejtag_debug_buffer 383c8bf3805SHeiher LONG_S k1, 0(k0) 384c8bf3805SHeiher#endif 385c8bf3805SHeiher 3861da177e4SLinus Torvalds SAVE_ALL 3871da177e4SLinus Torvalds move a0, sp 3881da177e4SLinus Torvalds jal ejtag_exception_handler 3891da177e4SLinus Torvalds RESTORE_ALL 390c8bf3805SHeiher 391c8bf3805SHeiher#ifdef CONFIG_SMP 392c8bf3805SHeiher ASM_CPUID_MFC0 k1, ASM_SMP_CPUID_REG 393c8bf3805SHeiher PTR_SRL k1, SMP_CPUID_PTRSHIFT 394c8bf3805SHeiher PTR_SLL k1, LONGLOG 395c8bf3805SHeiher PTR_LA k0, ejtag_debug_buffer_per_cpu 396c8bf3805SHeiher PTR_ADDU k0, k1 397c8bf3805SHeiher LONG_L k1, 0(k0) 398c8bf3805SHeiher#else 3991da177e4SLinus Torvalds PTR_LA k0, ejtag_debug_buffer 4001da177e4SLinus Torvalds LONG_L k1, 0(k0) 401c8bf3805SHeiher#endif 4021da177e4SLinus Torvalds 4031da177e4SLinus Torvaldsejtag_return: 404c8bf3805SHeiher back_to_back_c0_hazard 4051da177e4SLinus Torvalds MFC0 k0, CP0_DESAVE 4061da177e4SLinus Torvalds .set mips32 4071da177e4SLinus Torvalds deret 4081da177e4SLinus Torvalds .set pop 4091da177e4SLinus Torvalds END(ejtag_debug_handler) 4101da177e4SLinus Torvalds 4111da177e4SLinus Torvalds/* 4121da177e4SLinus Torvalds * This buffer is reserved for the use of the EJTAG debug 4131da177e4SLinus Torvalds * handler. 4141da177e4SLinus Torvalds */ 4151da177e4SLinus Torvalds .data 4161da177e4SLinus TorvaldsEXPORT(ejtag_debug_buffer) 4171da177e4SLinus Torvalds .fill LONGSIZE 418c8bf3805SHeiher#ifdef CONFIG_SMP 419c8bf3805SHeiherEXPORT(ejtag_debug_buffer_spinlock) 420c8bf3805SHeiher .fill LONGSIZE 421c8bf3805SHeiherEXPORT(ejtag_debug_buffer_per_cpu) 422c8bf3805SHeiher .fill LONGSIZE * NR_CPUS 423c8bf3805SHeiher#endif 4241da177e4SLinus Torvalds .previous 4251da177e4SLinus Torvalds 4261da177e4SLinus Torvalds __INIT 4271da177e4SLinus Torvalds 4281da177e4SLinus Torvalds/* 4291da177e4SLinus Torvalds * NMI debug exception handler for MIPS reference boards. 4301da177e4SLinus Torvalds * The NMI debug exception entry point is 0xbfc00000, which 4311da177e4SLinus Torvalds * normally is in the boot PROM, so the boot PROM must do a 4321da177e4SLinus Torvalds * unconditional jump to this vector. 4331da177e4SLinus Torvalds */ 4341da177e4SLinus TorvaldsNESTED(except_vec_nmi, 0, sp) 4351da177e4SLinus Torvalds j nmi_handler 4362a0b24f5SSteven J. Hill#ifdef CONFIG_CPU_MICROMIPS 4372a0b24f5SSteven J. Hill nop 4382a0b24f5SSteven J. Hill#endif 4391da177e4SLinus Torvalds END(except_vec_nmi) 4401da177e4SLinus Torvalds 4411da177e4SLinus Torvalds __FINIT 4421da177e4SLinus Torvalds 4431da177e4SLinus TorvaldsNESTED(nmi_handler, PT_SIZE, sp) 444866b6a89SCorey Minyard .cfi_signal_frame 4451da177e4SLinus Torvalds .set push 4461da177e4SLinus Torvalds .set noat 44783e4da1eSLeonid Yegoshin /* 44883e4da1eSLeonid Yegoshin * Clear ERL - restore segment mapping 44983e4da1eSLeonid Yegoshin * Clear BEV - required for page fault exception handler to work 45083e4da1eSLeonid Yegoshin */ 45183e4da1eSLeonid Yegoshin mfc0 k0, CP0_STATUS 45283e4da1eSLeonid Yegoshin ori k0, k0, ST0_EXL 45383e4da1eSLeonid Yegoshin li k1, ~(ST0_BEV | ST0_ERL) 45483e4da1eSLeonid Yegoshin and k0, k0, k1 45583e4da1eSLeonid Yegoshin mtc0 k0, CP0_STATUS 45683e4da1eSLeonid Yegoshin _ehb 4571da177e4SLinus Torvalds SAVE_ALL 4581da177e4SLinus Torvalds move a0, sp 4591da177e4SLinus Torvalds jal nmi_exception_handler 46083e4da1eSLeonid Yegoshin /* nmi_exception_handler never returns */ 4611da177e4SLinus Torvalds .set pop 4621da177e4SLinus Torvalds END(nmi_handler) 4631da177e4SLinus Torvalds 4641da177e4SLinus Torvalds .macro __build_clear_none 4651da177e4SLinus Torvalds .endm 4661da177e4SLinus Torvalds 4671da177e4SLinus Torvalds .macro __build_clear_sti 468192ef366SRalf Baechle TRACE_IRQS_ON 4691da177e4SLinus Torvalds STI 4701da177e4SLinus Torvalds .endm 4711da177e4SLinus Torvalds 4721da177e4SLinus Torvalds .macro __build_clear_cli 4731da177e4SLinus Torvalds CLI 474192ef366SRalf Baechle TRACE_IRQS_OFF 4751da177e4SLinus Torvalds .endm 4761da177e4SLinus Torvalds 4771da177e4SLinus Torvalds .macro __build_clear_fpe 47831e1b3efSYuanJunQing CLI 47931e1b3efSYuanJunQing TRACE_IRQS_OFF 48025c30003SDavid Daney .set push 48125c30003SDavid Daney /* gas fails to assemble cfc1 for some archs (octeon).*/ \ 48225c30003SDavid Daney .set mips1 483*80a20d2fSNathan Chancellor .set hardfloat 4841da177e4SLinus Torvalds cfc1 a1, fcr31 48525c30003SDavid Daney .set pop 4861da177e4SLinus Torvalds .endm 4871da177e4SLinus Torvalds 488091be550SPaul Burton .macro __build_clear_msa_fpe 48964bedffeSJames Hogan CLI 49064bedffeSJames Hogan TRACE_IRQS_OFF 49131e1b3efSYuanJunQing _cfcmsa a1, MSA_CSR 492091be550SPaul Burton .endm 493091be550SPaul Burton 4941da177e4SLinus Torvalds .macro __build_clear_ade 4951da177e4SLinus Torvalds MFC0 t0, CP0_BADVADDR 4961da177e4SLinus Torvalds PTR_S t0, PT_BVADDR(sp) 4971da177e4SLinus Torvalds KMODE 4981da177e4SLinus Torvalds .endm 4991da177e4SLinus Torvalds 500bc6e8dc1SWANG Xuerui .macro __build_clear_gsexc 501bc6e8dc1SWANG Xuerui .set push 502bc6e8dc1SWANG Xuerui /* 503bc6e8dc1SWANG Xuerui * We need to specify a selector to access the CP0.Diag1 (GSCause) 504bc6e8dc1SWANG Xuerui * register. All GSExc-equipped processors have MIPS32. 505bc6e8dc1SWANG Xuerui */ 506bc6e8dc1SWANG Xuerui .set mips32 507bc6e8dc1SWANG Xuerui mfc0 a1, CP0_DIAGNOSTIC1 508bc6e8dc1SWANG Xuerui .set pop 509bc6e8dc1SWANG Xuerui TRACE_IRQS_ON 510bc6e8dc1SWANG Xuerui STI 511bc6e8dc1SWANG Xuerui .endm 512bc6e8dc1SWANG Xuerui 5131da177e4SLinus Torvalds .macro __BUILD_silent exception 5141da177e4SLinus Torvalds .endm 5151da177e4SLinus Torvalds 516da706e50SHuacai Chen /* Gas tries to parse the ASM_PRINT argument as a string containing 5171da177e4SLinus Torvalds string escapes and emits bogus warnings if it believes to 5181da177e4SLinus Torvalds recognize an unknown escape code. So make the arguments 5191da177e4SLinus Torvalds start with an n and gas will believe \n is ok ... */ 5201da177e4SLinus Torvalds .macro __BUILD_verbose nexception 5211da177e4SLinus Torvalds LONG_L a1, PT_EPC(sp) 522766160c2SYoichi Yuasa#ifdef CONFIG_32BIT 523da706e50SHuacai Chen ASM_PRINT("Got \nexception at %08lx\012") 5241da177e4SLinus Torvalds#endif 525766160c2SYoichi Yuasa#ifdef CONFIG_64BIT 526da706e50SHuacai Chen ASM_PRINT("Got \nexception at %016lx\012") 5271da177e4SLinus Torvalds#endif 5281da177e4SLinus Torvalds .endm 5291da177e4SLinus Torvalds 5301da177e4SLinus Torvalds .macro __BUILD_count exception 5311da177e4SLinus Torvalds LONG_L t0,exception_count_\exception 5321da177e4SLinus Torvalds LONG_ADDIU t0, 1 5331da177e4SLinus Torvalds LONG_S t0,exception_count_\exception 5341da177e4SLinus Torvalds .comm exception_count\exception, 8, 8 5351da177e4SLinus Torvalds .endm 5361da177e4SLinus Torvalds 5371da177e4SLinus Torvalds .macro __BUILD_HANDLER exception handler clear verbose ext 5381da177e4SLinus Torvalds .align 5 5391da177e4SLinus Torvalds NESTED(handle_\exception, PT_SIZE, sp) 540866b6a89SCorey Minyard .cfi_signal_frame 5411da177e4SLinus Torvalds .set noat 5421da177e4SLinus Torvalds SAVE_ALL 5431da177e4SLinus Torvalds FEXPORT(handle_\exception\ext) 544158d3b2aSRalf Baechle __build_clear_\clear 5451da177e4SLinus Torvalds .set at 5461da177e4SLinus Torvalds __BUILD_\verbose \exception 5471da177e4SLinus Torvalds move a0, sp 548866b6a89SCorey Minyard jal do_\handler 549866b6a89SCorey Minyard j ret_from_exception 5501da177e4SLinus Torvalds END(handle_\exception) 5511da177e4SLinus Torvalds .endm 5521da177e4SLinus Torvalds 5531da177e4SLinus Torvalds .macro BUILD_HANDLER exception handler clear verbose 5541da177e4SLinus Torvalds __BUILD_HANDLER \exception \handler \clear \verbose _int 5551da177e4SLinus Torvalds .endm 5561da177e4SLinus Torvalds 5571da177e4SLinus Torvalds BUILD_HANDLER adel ade ade silent /* #4 */ 5581da177e4SLinus Torvalds BUILD_HANDLER ades ade ade silent /* #5 */ 5591da177e4SLinus Torvalds BUILD_HANDLER ibe be cli silent /* #6 */ 5601da177e4SLinus Torvalds BUILD_HANDLER dbe be cli silent /* #7 */ 5611da177e4SLinus Torvalds BUILD_HANDLER bp bp sti silent /* #9 */ 5621da177e4SLinus Torvalds BUILD_HANDLER ri ri sti silent /* #10 */ 5631da177e4SLinus Torvalds BUILD_HANDLER cpu cpu sti silent /* #11 */ 5641da177e4SLinus Torvalds BUILD_HANDLER ov ov sti silent /* #12 */ 5651da177e4SLinus Torvalds BUILD_HANDLER tr tr sti silent /* #13 */ 566091be550SPaul Burton BUILD_HANDLER msa_fpe msa_fpe msa_fpe silent /* #14 */ 5675328f742SPaul Burton#ifdef CONFIG_MIPS_FP_SUPPORT 5681da177e4SLinus Torvalds BUILD_HANDLER fpe fpe fpe silent /* #15 */ 5695328f742SPaul Burton#endif 57075b5b5e0SLeonid Yegoshin BUILD_HANDLER ftlb ftlb none silent /* #16 */ 571bc6e8dc1SWANG Xuerui BUILD_HANDLER gsexc gsexc gsexc silent /* #16 */ 5721db1af84SPaul Burton BUILD_HANDLER msa msa sti silent /* #21 */ 5731da177e4SLinus Torvalds BUILD_HANDLER mdmx mdmx sti silent /* #22 */ 574b67b2b70SDavid Daney#ifdef CONFIG_HARDWARE_WATCHPOINTS 5758bc6d05bSDavid Daney /* 5768bc6d05bSDavid Daney * For watch, interrupts will be enabled after the watch 5778bc6d05bSDavid Daney * registers are read. 5788bc6d05bSDavid Daney */ 5798bc6d05bSDavid Daney BUILD_HANDLER watch watch cli silent /* #23 */ 580b67b2b70SDavid Daney#else 5811da177e4SLinus Torvalds BUILD_HANDLER watch watch sti verbose /* #23 */ 582b67b2b70SDavid Daney#endif 5831da177e4SLinus Torvalds BUILD_HANDLER mcheck mcheck cli verbose /* #24 */ 584e35a5e35SChris Dearman BUILD_HANDLER mt mt sti silent /* #25 */ 585e50c0a8fSRalf Baechle BUILD_HANDLER dsp dsp sti silent /* #26 */ 5861da177e4SLinus Torvalds BUILD_HANDLER reserved reserved sti verbose /* others */ 5871da177e4SLinus Torvalds 5885b10496bSAtsushi Nemoto .align 5 5895a341331SHuacai Chen LEAF(handle_ri_rdhwr_tlbp) 5905b10496bSAtsushi Nemoto .set push 5915b10496bSAtsushi Nemoto .set noat 5925b10496bSAtsushi Nemoto .set noreorder 5935b10496bSAtsushi Nemoto /* check if TLB contains a entry for EPC */ 5945b10496bSAtsushi Nemoto MFC0 k1, CP0_ENTRYHI 5952db003a5SPaul Burton andi k1, MIPS_ENTRYHI_ASID | MIPS_ENTRYHI_ASIDX 5965b10496bSAtsushi Nemoto MFC0 k0, CP0_EPC 597bef9ae3dSRalf Baechle PTR_SRL k0, _PAGE_SHIFT + 1 598bef9ae3dSRalf Baechle PTR_SLL k0, _PAGE_SHIFT + 1 5995b10496bSAtsushi Nemoto or k1, k0 6005b10496bSAtsushi Nemoto MTC0 k1, CP0_ENTRYHI 6015b10496bSAtsushi Nemoto mtc0_tlbw_hazard 6025b10496bSAtsushi Nemoto tlbp 6035b10496bSAtsushi Nemoto tlb_probe_hazard 6045b10496bSAtsushi Nemoto mfc0 k1, CP0_INDEX 6055b10496bSAtsushi Nemoto .set pop 6065b10496bSAtsushi Nemoto bltz k1, handle_ri /* slow path */ 6075b10496bSAtsushi Nemoto /* fall thru */ 6085a341331SHuacai Chen END(handle_ri_rdhwr_tlbp) 6095b10496bSAtsushi Nemoto 6105b10496bSAtsushi Nemoto LEAF(handle_ri_rdhwr) 6115b10496bSAtsushi Nemoto .set push 6125b10496bSAtsushi Nemoto .set noat 6135b10496bSAtsushi Nemoto .set noreorder 6142a0b24f5SSteven J. Hill /* MIPS32: 0x7c03e83b: rdhwr v1,$29 */ 6152a0b24f5SSteven J. Hill /* microMIPS: 0x007d6b3c: rdhwr v1,$29 */ 6165b10496bSAtsushi Nemoto MFC0 k1, CP0_EPC 6172a0b24f5SSteven J. Hill#if defined(CONFIG_CPU_MICROMIPS) || defined(CONFIG_CPU_MIPS32_R2) || defined(CONFIG_CPU_MIPS64_R2) 6182a0b24f5SSteven J. Hill and k0, k1, 1 6192a0b24f5SSteven J. Hill beqz k0, 1f 6202a0b24f5SSteven J. Hill xor k1, k0 6212a0b24f5SSteven J. Hill lhu k0, (k1) 6222a0b24f5SSteven J. Hill lhu k1, 2(k1) 6232a0b24f5SSteven J. Hill ins k1, k0, 16, 16 6242a0b24f5SSteven J. Hill lui k0, 0x007d 6252a0b24f5SSteven J. Hill b docheck 6262a0b24f5SSteven J. Hill ori k0, 0x6b3c 6272a0b24f5SSteven J. Hill1: 6285b10496bSAtsushi Nemoto lui k0, 0x7c03 6295b10496bSAtsushi Nemoto lw k1, (k1) 6305b10496bSAtsushi Nemoto ori k0, 0xe83b 6312a0b24f5SSteven J. Hill#else 6322a0b24f5SSteven J. Hill andi k0, k1, 1 6332a0b24f5SSteven J. Hill bnez k0, handle_ri 6342a0b24f5SSteven J. Hill lui k0, 0x7c03 6352a0b24f5SSteven J. Hill lw k1, (k1) 6362a0b24f5SSteven J. Hill ori k0, 0xe83b 6372a0b24f5SSteven J. Hill#endif 6385b10496bSAtsushi Nemoto .set reorder 6392a0b24f5SSteven J. Hilldocheck: 6405b10496bSAtsushi Nemoto bne k0, k1, handle_ri /* if not ours */ 6412a0b24f5SSteven J. Hill 6422a0b24f5SSteven J. Hillisrdhwr: 6435b10496bSAtsushi Nemoto /* The insn is rdhwr. No need to check CAUSE.BD here. */ 6445b10496bSAtsushi Nemoto get_saved_sp /* k1 := current_thread_info */ 6455b10496bSAtsushi Nemoto .set noreorder 6465b10496bSAtsushi Nemoto MFC0 k0, CP0_EPC 647455481fcSThomas Bogendoerfer#if defined(CONFIG_CPU_R3000) 6485b10496bSAtsushi Nemoto ori k1, _THREAD_MASK 6495b10496bSAtsushi Nemoto xori k1, _THREAD_MASK 6505b10496bSAtsushi Nemoto LONG_L v1, TI_TP_VALUE(k1) 6515b10496bSAtsushi Nemoto LONG_ADDIU k0, 4 6525b10496bSAtsushi Nemoto jr k0 6535b10496bSAtsushi Nemoto rfe 6545b10496bSAtsushi Nemoto#else 655619b6e18SMaciej W. Rozycki#ifndef CONFIG_CPU_DADDI_WORKAROUNDS 6565b10496bSAtsushi Nemoto LONG_ADDIU k0, 4 /* stall on $k0 */ 657619b6e18SMaciej W. Rozycki#else 658619b6e18SMaciej W. Rozycki .set at=v1 659619b6e18SMaciej W. Rozycki LONG_ADDIU k0, 4 660619b6e18SMaciej W. Rozycki .set noat 661619b6e18SMaciej W. Rozycki#endif 6625b10496bSAtsushi Nemoto MTC0 k0, CP0_EPC 6635b10496bSAtsushi Nemoto /* I hope three instructions between MTC0 and ERET are enough... */ 6645b10496bSAtsushi Nemoto ori k1, _THREAD_MASK 6655b10496bSAtsushi Nemoto xori k1, _THREAD_MASK 6665b10496bSAtsushi Nemoto LONG_L v1, TI_TP_VALUE(k1) 667378ed6f0SPaul Burton .set push 668a809d460SRalf Baechle .set arch=r4000 6695b10496bSAtsushi Nemoto eret 670378ed6f0SPaul Burton .set pop 6715b10496bSAtsushi Nemoto#endif 6725b10496bSAtsushi Nemoto .set pop 6735b10496bSAtsushi Nemoto END(handle_ri_rdhwr) 6745b10496bSAtsushi Nemoto 675071d2f0bSPaul Burton#ifdef CONFIG_CPU_R4X00_BUGS64 6761da177e4SLinus Torvalds/* A temporary overflow handler used by check_daddi(). */ 6771da177e4SLinus Torvalds 6781da177e4SLinus Torvalds __INIT 6791da177e4SLinus Torvalds 6801da177e4SLinus Torvalds BUILD_HANDLER daddi_ov daddi_ov none silent /* #12 */ 6811da177e4SLinus Torvalds#endif 682