1/* 2 * arch/sh/kernel/cpu/sh5/entry.S 3 * 4 * Copyright (C) 2000, 2001 Paolo Alberelli 5 * Copyright (C) 2004 - 2008 Paul Mundt 6 * Copyright (C) 2003, 2004 Richard Curnow 7 * 8 * This file is subject to the terms and conditions of the GNU General Public 9 * License. See the file "COPYING" in the main directory of this archive 10 * for more details. 11 */ 12#include <linux/errno.h> 13#include <linux/init.h> 14#include <linux/sys.h> 15#include <cpu/registers.h> 16#include <asm/processor.h> 17#include <asm/unistd.h> 18#include <asm/thread_info.h> 19#include <asm/asm-offsets.h> 20 21/* 22 * SR fields. 23 */ 24#define SR_ASID_MASK 0x00ff0000 25#define SR_FD_MASK 0x00008000 26#define SR_SS 0x08000000 27#define SR_BL 0x10000000 28#define SR_MD 0x40000000 29 30/* 31 * Event code. 32 */ 33#define EVENT_INTERRUPT 0 34#define EVENT_FAULT_TLB 1 35#define EVENT_FAULT_NOT_TLB 2 36#define EVENT_DEBUG 3 37 38/* EXPEVT values */ 39#define RESET_CAUSE 0x20 40#define DEBUGSS_CAUSE 0x980 41 42/* 43 * Frame layout. Quad index. 44 */ 45#define FRAME_T(x) FRAME_TBASE+(x*8) 46#define FRAME_R(x) FRAME_RBASE+(x*8) 47#define FRAME_S(x) FRAME_SBASE+(x*8) 48#define FSPC 0 49#define FSSR 1 50#define FSYSCALL_ID 2 51 52/* Arrange the save frame to be a multiple of 32 bytes long */ 53#define FRAME_SBASE 0 54#define FRAME_RBASE (FRAME_SBASE+(3*8)) /* SYSCALL_ID - SSR - SPC */ 55#define FRAME_TBASE (FRAME_RBASE+(63*8)) /* r0 - r62 */ 56#define FRAME_PBASE (FRAME_TBASE+(8*8)) /* tr0 -tr7 */ 57#define FRAME_SIZE (FRAME_PBASE+(2*8)) /* pad0-pad1 */ 58 59#define FP_FRAME_SIZE FP_FRAME_BASE+(33*8) /* dr0 - dr31 + fpscr */ 60#define FP_FRAME_BASE 0 61 62#define SAVED_R2 0*8 63#define SAVED_R3 1*8 64#define SAVED_R4 2*8 65#define SAVED_R5 3*8 66#define SAVED_R18 4*8 67#define SAVED_R6 5*8 68#define SAVED_TR0 6*8 69 70/* These are the registers saved in the TLB path that aren't saved in the first 71 level of the normal one. */ 72#define TLB_SAVED_R25 7*8 73#define TLB_SAVED_TR1 8*8 74#define TLB_SAVED_TR2 9*8 75#define TLB_SAVED_TR3 10*8 76#define TLB_SAVED_TR4 11*8 77/* Save R0/R1 : PT-migrating compiler currently dishounours -ffixed-r0 and -ffixed-r1 causing 78 breakage otherwise. */ 79#define TLB_SAVED_R0 12*8 80#define TLB_SAVED_R1 13*8 81 82#define CLI() \ 83 getcon SR, r6; \ 84 ori r6, 0xf0, r6; \ 85 putcon r6, SR; 86 87#define STI() \ 88 getcon SR, r6; \ 89 andi r6, ~0xf0, r6; \ 90 putcon r6, SR; 91 92#ifdef CONFIG_PREEMPT 93# define preempt_stop() CLI() 94#else 95# define preempt_stop() 96# define resume_kernel restore_all 97#endif 98 99 .section .data, "aw" 100 101#define FAST_TLBMISS_STACK_CACHELINES 4 102#define FAST_TLBMISS_STACK_QUADWORDS (4*FAST_TLBMISS_STACK_CACHELINES) 103 104/* Register back-up area for all exceptions */ 105 .balign 32 106 /* Allow for 16 quadwords to be pushed by fast tlbmiss handling 107 * register saves etc. */ 108 .fill FAST_TLBMISS_STACK_QUADWORDS, 8, 0x0 109/* This is 32 byte aligned by construction */ 110/* Register back-up area for all exceptions */ 111reg_save_area: 112 .quad 0 113 .quad 0 114 .quad 0 115 .quad 0 116 117 .quad 0 118 .quad 0 119 .quad 0 120 .quad 0 121 122 .quad 0 123 .quad 0 124 .quad 0 125 .quad 0 126 127 .quad 0 128 .quad 0 129 130/* Save area for RESVEC exceptions. We cannot use reg_save_area because of 131 * reentrancy. Note this area may be accessed via physical address. 132 * Align so this fits a whole single cache line, for ease of purging. 133 */ 134 .balign 32,0,32 135resvec_save_area: 136 .quad 0 137 .quad 0 138 .quad 0 139 .quad 0 140 .quad 0 141 .balign 32,0,32 142 143/* Jump table of 3rd level handlers */ 144trap_jtable: 145 .long do_exception_error /* 0x000 */ 146 .long do_exception_error /* 0x020 */ 147#ifdef CONFIG_MMU 148 .long tlb_miss_load /* 0x040 */ 149 .long tlb_miss_store /* 0x060 */ 150#else 151 .long do_exception_error 152 .long do_exception_error 153#endif 154 ! ARTIFICIAL pseudo-EXPEVT setting 155 .long do_debug_interrupt /* 0x080 */ 156#ifdef CONFIG_MMU 157 .long tlb_miss_load /* 0x0A0 */ 158 .long tlb_miss_store /* 0x0C0 */ 159#else 160 .long do_exception_error 161 .long do_exception_error 162#endif 163 .long do_address_error_load /* 0x0E0 */ 164 .long do_address_error_store /* 0x100 */ 165#ifdef CONFIG_SH_FPU 166 .long do_fpu_error /* 0x120 */ 167#else 168 .long do_exception_error /* 0x120 */ 169#endif 170 .long do_exception_error /* 0x140 */ 171 .long system_call /* 0x160 */ 172 .long do_reserved_inst /* 0x180 */ 173 .long do_illegal_slot_inst /* 0x1A0 */ 174 .long do_exception_error /* 0x1C0 - NMI */ 175 .long do_exception_error /* 0x1E0 */ 176 .rept 15 177 .long do_IRQ /* 0x200 - 0x3C0 */ 178 .endr 179 .long do_exception_error /* 0x3E0 */ 180 .rept 32 181 .long do_IRQ /* 0x400 - 0x7E0 */ 182 .endr 183 .long fpu_error_or_IRQA /* 0x800 */ 184 .long fpu_error_or_IRQB /* 0x820 */ 185 .long do_IRQ /* 0x840 */ 186 .long do_IRQ /* 0x860 */ 187 .rept 6 188 .long do_exception_error /* 0x880 - 0x920 */ 189 .endr 190 .long breakpoint_trap_handler /* 0x940 */ 191 .long do_exception_error /* 0x960 */ 192 .long do_single_step /* 0x980 */ 193 194 .rept 3 195 .long do_exception_error /* 0x9A0 - 0x9E0 */ 196 .endr 197 .long do_IRQ /* 0xA00 */ 198 .long do_IRQ /* 0xA20 */ 199#ifdef CONFIG_MMU 200 .long itlb_miss_or_IRQ /* 0xA40 */ 201#else 202 .long do_IRQ 203#endif 204 .long do_IRQ /* 0xA60 */ 205 .long do_IRQ /* 0xA80 */ 206#ifdef CONFIG_MMU 207 .long itlb_miss_or_IRQ /* 0xAA0 */ 208#else 209 .long do_IRQ 210#endif 211 .long do_exception_error /* 0xAC0 */ 212 .long do_address_error_exec /* 0xAE0 */ 213 .rept 8 214 .long do_exception_error /* 0xB00 - 0xBE0 */ 215 .endr 216 .rept 18 217 .long do_IRQ /* 0xC00 - 0xE20 */ 218 .endr 219 220 .section .text64, "ax" 221 222/* 223 * --- Exception/Interrupt/Event Handling Section 224 */ 225 226/* 227 * VBR and RESVEC blocks. 228 * 229 * First level handler for VBR-based exceptions. 230 * 231 * To avoid waste of space, align to the maximum text block size. 232 * This is assumed to be at most 128 bytes or 32 instructions. 233 * DO NOT EXCEED 32 instructions on the first level handlers ! 234 * 235 * Also note that RESVEC is contained within the VBR block 236 * where the room left (1KB - TEXT_SIZE) allows placing 237 * the RESVEC block (at most 512B + TEXT_SIZE). 238 * 239 * So first (and only) level handler for RESVEC-based exceptions. 240 * 241 * Where the fault/interrupt is handled (not_a_tlb_miss, tlb_miss 242 * and interrupt) we are a lot tight with register space until 243 * saving onto the stack frame, which is done in handle_exception(). 244 * 245 */ 246 247#define TEXT_SIZE 128 248#define BLOCK_SIZE 1664 /* Dynamic check, 13*128 */ 249 250 .balign TEXT_SIZE 251LVBR_block: 252 .space 256, 0 /* Power-on class handler, */ 253 /* not required here */ 254not_a_tlb_miss: 255 synco /* TAKum03020 (but probably a good idea anyway.) */ 256 /* Save original stack pointer into KCR1 */ 257 putcon SP, KCR1 258 259 /* Save other original registers into reg_save_area */ 260 movi reg_save_area, SP 261 st.q SP, SAVED_R2, r2 262 st.q SP, SAVED_R3, r3 263 st.q SP, SAVED_R4, r4 264 st.q SP, SAVED_R5, r5 265 st.q SP, SAVED_R6, r6 266 st.q SP, SAVED_R18, r18 267 gettr tr0, r3 268 st.q SP, SAVED_TR0, r3 269 270 /* Set args for Non-debug, Not a TLB miss class handler */ 271 getcon EXPEVT, r2 272 movi ret_from_exception, r3 273 ori r3, 1, r3 274 movi EVENT_FAULT_NOT_TLB, r4 275 or SP, ZERO, r5 276 getcon KCR1, SP 277 pta handle_exception, tr0 278 blink tr0, ZERO 279 280 .balign 256 281 ! VBR+0x200 282 nop 283 .balign 256 284 ! VBR+0x300 285 nop 286 .balign 256 287 /* 288 * Instead of the natural .balign 1024 place RESVEC here 289 * respecting the final 1KB alignment. 290 */ 291 .balign TEXT_SIZE 292 /* 293 * Instead of '.space 1024-TEXT_SIZE' place the RESVEC 294 * block making sure the final alignment is correct. 295 */ 296#ifdef CONFIG_MMU 297tlb_miss: 298 synco /* TAKum03020 (but probably a good idea anyway.) */ 299 putcon SP, KCR1 300 movi reg_save_area, SP 301 /* SP is guaranteed 32-byte aligned. */ 302 st.q SP, TLB_SAVED_R0 , r0 303 st.q SP, TLB_SAVED_R1 , r1 304 st.q SP, SAVED_R2 , r2 305 st.q SP, SAVED_R3 , r3 306 st.q SP, SAVED_R4 , r4 307 st.q SP, SAVED_R5 , r5 308 st.q SP, SAVED_R6 , r6 309 st.q SP, SAVED_R18, r18 310 311 /* Save R25 for safety; as/ld may want to use it to achieve the call to 312 * the code in mm/tlbmiss.c */ 313 st.q SP, TLB_SAVED_R25, r25 314 gettr tr0, r2 315 gettr tr1, r3 316 gettr tr2, r4 317 gettr tr3, r5 318 gettr tr4, r18 319 st.q SP, SAVED_TR0 , r2 320 st.q SP, TLB_SAVED_TR1 , r3 321 st.q SP, TLB_SAVED_TR2 , r4 322 st.q SP, TLB_SAVED_TR3 , r5 323 st.q SP, TLB_SAVED_TR4 , r18 324 325 pt do_fast_page_fault, tr0 326 getcon SSR, r2 327 getcon EXPEVT, r3 328 getcon TEA, r4 329 shlri r2, 30, r2 330 andi r2, 1, r2 /* r2 = SSR.MD */ 331 blink tr0, LINK 332 333 pt fixup_to_invoke_general_handler, tr1 334 335 /* If the fast path handler fixed the fault, just drop through quickly 336 to the restore code right away to return to the excepting context. 337 */ 338 bnei/u r2, 0, tr1 339 340fast_tlb_miss_restore: 341 ld.q SP, SAVED_TR0, r2 342 ld.q SP, TLB_SAVED_TR1, r3 343 ld.q SP, TLB_SAVED_TR2, r4 344 345 ld.q SP, TLB_SAVED_TR3, r5 346 ld.q SP, TLB_SAVED_TR4, r18 347 348 ptabs r2, tr0 349 ptabs r3, tr1 350 ptabs r4, tr2 351 ptabs r5, tr3 352 ptabs r18, tr4 353 354 ld.q SP, TLB_SAVED_R0, r0 355 ld.q SP, TLB_SAVED_R1, r1 356 ld.q SP, SAVED_R2, r2 357 ld.q SP, SAVED_R3, r3 358 ld.q SP, SAVED_R4, r4 359 ld.q SP, SAVED_R5, r5 360 ld.q SP, SAVED_R6, r6 361 ld.q SP, SAVED_R18, r18 362 ld.q SP, TLB_SAVED_R25, r25 363 364 getcon KCR1, SP 365 rte 366 nop /* for safety, in case the code is run on sh5-101 cut1.x */ 367 368fixup_to_invoke_general_handler: 369 370 /* OK, new method. Restore stuff that's not expected to get saved into 371 the 'first-level' reg save area, then just fall through to setting 372 up the registers and calling the second-level handler. */ 373 374 /* 2nd level expects r2,3,4,5,6,18,tr0 to be saved. So we must restore 375 r25,tr1-4 and save r6 to get into the right state. */ 376 377 ld.q SP, TLB_SAVED_TR1, r3 378 ld.q SP, TLB_SAVED_TR2, r4 379 ld.q SP, TLB_SAVED_TR3, r5 380 ld.q SP, TLB_SAVED_TR4, r18 381 ld.q SP, TLB_SAVED_R25, r25 382 383 ld.q SP, TLB_SAVED_R0, r0 384 ld.q SP, TLB_SAVED_R1, r1 385 386 ptabs/u r3, tr1 387 ptabs/u r4, tr2 388 ptabs/u r5, tr3 389 ptabs/u r18, tr4 390 391 /* Set args for Non-debug, TLB miss class handler */ 392 getcon EXPEVT, r2 393 movi ret_from_exception, r3 394 ori r3, 1, r3 395 movi EVENT_FAULT_TLB, r4 396 or SP, ZERO, r5 397 getcon KCR1, SP 398 pta handle_exception, tr0 399 blink tr0, ZERO 400#else /* CONFIG_MMU */ 401 .balign 256 402#endif 403 404/* NB TAKE GREAT CARE HERE TO ENSURE THAT THE INTERRUPT CODE 405 DOES END UP AT VBR+0x600 */ 406 nop 407 nop 408 nop 409 nop 410 nop 411 nop 412 413 .balign 256 414 /* VBR + 0x600 */ 415 416interrupt: 417 synco /* TAKum03020 (but probably a good idea anyway.) */ 418 /* Save original stack pointer into KCR1 */ 419 putcon SP, KCR1 420 421 /* Save other original registers into reg_save_area */ 422 movi reg_save_area, SP 423 st.q SP, SAVED_R2, r2 424 st.q SP, SAVED_R3, r3 425 st.q SP, SAVED_R4, r4 426 st.q SP, SAVED_R5, r5 427 st.q SP, SAVED_R6, r6 428 st.q SP, SAVED_R18, r18 429 gettr tr0, r3 430 st.q SP, SAVED_TR0, r3 431 432 /* Set args for interrupt class handler */ 433 getcon INTEVT, r2 434 movi ret_from_irq, r3 435 ori r3, 1, r3 436 movi EVENT_INTERRUPT, r4 437 or SP, ZERO, r5 438 getcon KCR1, SP 439 pta handle_exception, tr0 440 blink tr0, ZERO 441 .balign TEXT_SIZE /* let's waste the bare minimum */ 442 443LVBR_block_end: /* Marker. Used for total checking */ 444 445 .balign 256 446LRESVEC_block: 447 /* Panic handler. Called with MMU off. Possible causes/actions: 448 * - Reset: Jump to program start. 449 * - Single Step: Turn off Single Step & return. 450 * - Others: Call panic handler, passing PC as arg. 451 * (this may need to be extended...) 452 */ 453reset_or_panic: 454 synco /* TAKum03020 (but probably a good idea anyway.) */ 455 putcon SP, DCR 456 /* First save r0-1 and tr0, as we need to use these */ 457 movi resvec_save_area-CONFIG_PAGE_OFFSET, SP 458 st.q SP, 0, r0 459 st.q SP, 8, r1 460 gettr tr0, r0 461 st.q SP, 32, r0 462 463 /* Check cause */ 464 getcon EXPEVT, r0 465 movi RESET_CAUSE, r1 466 sub r1, r0, r1 /* r1=0 if reset */ 467 movi _stext-CONFIG_PAGE_OFFSET, r0 468 ori r0, 1, r0 469 ptabs r0, tr0 470 beqi r1, 0, tr0 /* Jump to start address if reset */ 471 472 getcon EXPEVT, r0 473 movi DEBUGSS_CAUSE, r1 474 sub r1, r0, r1 /* r1=0 if single step */ 475 pta single_step_panic, tr0 476 beqi r1, 0, tr0 /* jump if single step */ 477 478 /* Now jump to where we save the registers. */ 479 movi panic_stash_regs-CONFIG_PAGE_OFFSET, r1 480 ptabs r1, tr0 481 blink tr0, r63 482 483single_step_panic: 484 /* We are in a handler with Single Step set. We need to resume the 485 * handler, by turning on MMU & turning off Single Step. */ 486 getcon SSR, r0 487 movi SR_MMU, r1 488 or r0, r1, r0 489 movi ~SR_SS, r1 490 and r0, r1, r0 491 putcon r0, SSR 492 /* Restore EXPEVT, as the rte won't do this */ 493 getcon PEXPEVT, r0 494 putcon r0, EXPEVT 495 /* Restore regs */ 496 ld.q SP, 32, r0 497 ptabs r0, tr0 498 ld.q SP, 0, r0 499 ld.q SP, 8, r1 500 getcon DCR, SP 501 synco 502 rte 503 504 505 .balign 256 506debug_exception: 507 synco /* TAKum03020 (but probably a good idea anyway.) */ 508 /* 509 * Single step/software_break_point first level handler. 510 * Called with MMU off, so the first thing we do is enable it 511 * by doing an rte with appropriate SSR. 512 */ 513 putcon SP, DCR 514 /* Save SSR & SPC, together with R0 & R1, as we need to use 2 regs. */ 515 movi resvec_save_area-CONFIG_PAGE_OFFSET, SP 516 517 /* With the MMU off, we are bypassing the cache, so purge any 518 * data that will be made stale by the following stores. 519 */ 520 ocbp SP, 0 521 synco 522 523 st.q SP, 0, r0 524 st.q SP, 8, r1 525 getcon SPC, r0 526 st.q SP, 16, r0 527 getcon SSR, r0 528 st.q SP, 24, r0 529 530 /* Enable MMU, block exceptions, set priv mode, disable single step */ 531 movi SR_MMU | SR_BL | SR_MD, r1 532 or r0, r1, r0 533 movi ~SR_SS, r1 534 and r0, r1, r0 535 putcon r0, SSR 536 /* Force control to debug_exception_2 when rte is executed */ 537 movi debug_exeception_2, r0 538 ori r0, 1, r0 /* force SHmedia, just in case */ 539 putcon r0, SPC 540 getcon DCR, SP 541 synco 542 rte 543debug_exeception_2: 544 /* Restore saved regs */ 545 putcon SP, KCR1 546 movi resvec_save_area, SP 547 ld.q SP, 24, r0 548 putcon r0, SSR 549 ld.q SP, 16, r0 550 putcon r0, SPC 551 ld.q SP, 0, r0 552 ld.q SP, 8, r1 553 554 /* Save other original registers into reg_save_area */ 555 movi reg_save_area, SP 556 st.q SP, SAVED_R2, r2 557 st.q SP, SAVED_R3, r3 558 st.q SP, SAVED_R4, r4 559 st.q SP, SAVED_R5, r5 560 st.q SP, SAVED_R6, r6 561 st.q SP, SAVED_R18, r18 562 gettr tr0, r3 563 st.q SP, SAVED_TR0, r3 564 565 /* Set args for debug class handler */ 566 getcon EXPEVT, r2 567 movi ret_from_exception, r3 568 ori r3, 1, r3 569 movi EVENT_DEBUG, r4 570 or SP, ZERO, r5 571 getcon KCR1, SP 572 pta handle_exception, tr0 573 blink tr0, ZERO 574 575 .balign 256 576debug_interrupt: 577 /* !!! WE COME HERE IN REAL MODE !!! */ 578 /* Hook-up debug interrupt to allow various debugging options to be 579 * hooked into its handler. */ 580 /* Save original stack pointer into KCR1 */ 581 synco 582 putcon SP, KCR1 583 movi resvec_save_area-CONFIG_PAGE_OFFSET, SP 584 ocbp SP, 0 585 ocbp SP, 32 586 synco 587 588 /* Save other original registers into reg_save_area thru real addresses */ 589 st.q SP, SAVED_R2, r2 590 st.q SP, SAVED_R3, r3 591 st.q SP, SAVED_R4, r4 592 st.q SP, SAVED_R5, r5 593 st.q SP, SAVED_R6, r6 594 st.q SP, SAVED_R18, r18 595 gettr tr0, r3 596 st.q SP, SAVED_TR0, r3 597 598 /* move (spc,ssr)->(pspc,pssr). The rte will shift 599 them back again, so that they look like the originals 600 as far as the real handler code is concerned. */ 601 getcon spc, r6 602 putcon r6, pspc 603 getcon ssr, r6 604 putcon r6, pssr 605 606 ! construct useful SR for handle_exception 607 movi 3, r6 608 shlli r6, 30, r6 609 getcon sr, r18 610 or r18, r6, r6 611 putcon r6, ssr 612 613 ! SSR is now the current SR with the MD and MMU bits set 614 ! i.e. the rte will switch back to priv mode and put 615 ! the mmu back on 616 617 ! construct spc 618 movi handle_exception, r18 619 ori r18, 1, r18 ! for safety (do we need this?) 620 putcon r18, spc 621 622 /* Set args for Non-debug, Not a TLB miss class handler */ 623 624 ! EXPEVT==0x80 is unused, so 'steal' this value to put the 625 ! debug interrupt handler in the vectoring table 626 movi 0x80, r2 627 movi ret_from_exception, r3 628 ori r3, 1, r3 629 movi EVENT_FAULT_NOT_TLB, r4 630 631 or SP, ZERO, r5 632 movi CONFIG_PAGE_OFFSET, r6 633 add r6, r5, r5 634 getcon KCR1, SP 635 636 synco ! for safety 637 rte ! -> handle_exception, switch back to priv mode again 638 639LRESVEC_block_end: /* Marker. Unused. */ 640 641 .balign TEXT_SIZE 642 643/* 644 * Second level handler for VBR-based exceptions. Pre-handler. 645 * In common to all stack-frame sensitive handlers. 646 * 647 * Inputs: 648 * (KCR0) Current [current task union] 649 * (KCR1) Original SP 650 * (r2) INTEVT/EXPEVT 651 * (r3) appropriate return address 652 * (r4) Event (0 = interrupt, 1 = TLB miss fault, 2 = Not TLB miss fault, 3=debug) 653 * (r5) Pointer to reg_save_area 654 * (SP) Original SP 655 * 656 * Available registers: 657 * (r6) 658 * (r18) 659 * (tr0) 660 * 661 */ 662handle_exception: 663 /* Common 2nd level handler. */ 664 665 /* First thing we need an appropriate stack pointer */ 666 getcon SSR, r6 667 shlri r6, 30, r6 668 andi r6, 1, r6 669 pta stack_ok, tr0 670 bne r6, ZERO, tr0 /* Original stack pointer is fine */ 671 672 /* Set stack pointer for user fault */ 673 getcon KCR0, SP 674 movi THREAD_SIZE, r6 /* Point to the end */ 675 add SP, r6, SP 676 677stack_ok: 678 679/* DEBUG : check for underflow/overflow of the kernel stack */ 680 pta no_underflow, tr0 681 getcon KCR0, r6 682 movi 1024, r18 683 add r6, r18, r6 684 bge SP, r6, tr0 ! ? below 1k from bottom of stack : danger zone 685 686/* Just panic to cause a crash. */ 687bad_sp: 688 ld.b r63, 0, r6 689 nop 690 691no_underflow: 692 pta bad_sp, tr0 693 getcon kcr0, r6 694 movi THREAD_SIZE, r18 695 add r18, r6, r6 696 bgt SP, r6, tr0 ! sp above the stack 697 698 /* Make some room for the BASIC frame. */ 699 movi -(FRAME_SIZE), r6 700 add SP, r6, SP 701 702/* Could do this with no stalling if we had another spare register, but the 703 code below will be OK. */ 704 ld.q r5, SAVED_R2, r6 705 ld.q r5, SAVED_R3, r18 706 st.q SP, FRAME_R(2), r6 707 ld.q r5, SAVED_R4, r6 708 st.q SP, FRAME_R(3), r18 709 ld.q r5, SAVED_R5, r18 710 st.q SP, FRAME_R(4), r6 711 ld.q r5, SAVED_R6, r6 712 st.q SP, FRAME_R(5), r18 713 ld.q r5, SAVED_R18, r18 714 st.q SP, FRAME_R(6), r6 715 ld.q r5, SAVED_TR0, r6 716 st.q SP, FRAME_R(18), r18 717 st.q SP, FRAME_T(0), r6 718 719 /* Keep old SP around */ 720 getcon KCR1, r6 721 722 /* Save the rest of the general purpose registers */ 723 st.q SP, FRAME_R(0), r0 724 st.q SP, FRAME_R(1), r1 725 st.q SP, FRAME_R(7), r7 726 st.q SP, FRAME_R(8), r8 727 st.q SP, FRAME_R(9), r9 728 st.q SP, FRAME_R(10), r10 729 st.q SP, FRAME_R(11), r11 730 st.q SP, FRAME_R(12), r12 731 st.q SP, FRAME_R(13), r13 732 st.q SP, FRAME_R(14), r14 733 734 /* SP is somewhere else */ 735 st.q SP, FRAME_R(15), r6 736 737 st.q SP, FRAME_R(16), r16 738 st.q SP, FRAME_R(17), r17 739 /* r18 is saved earlier. */ 740 st.q SP, FRAME_R(19), r19 741 st.q SP, FRAME_R(20), r20 742 st.q SP, FRAME_R(21), r21 743 st.q SP, FRAME_R(22), r22 744 st.q SP, FRAME_R(23), r23 745 st.q SP, FRAME_R(24), r24 746 st.q SP, FRAME_R(25), r25 747 st.q SP, FRAME_R(26), r26 748 st.q SP, FRAME_R(27), r27 749 st.q SP, FRAME_R(28), r28 750 st.q SP, FRAME_R(29), r29 751 st.q SP, FRAME_R(30), r30 752 st.q SP, FRAME_R(31), r31 753 st.q SP, FRAME_R(32), r32 754 st.q SP, FRAME_R(33), r33 755 st.q SP, FRAME_R(34), r34 756 st.q SP, FRAME_R(35), r35 757 st.q SP, FRAME_R(36), r36 758 st.q SP, FRAME_R(37), r37 759 st.q SP, FRAME_R(38), r38 760 st.q SP, FRAME_R(39), r39 761 st.q SP, FRAME_R(40), r40 762 st.q SP, FRAME_R(41), r41 763 st.q SP, FRAME_R(42), r42 764 st.q SP, FRAME_R(43), r43 765 st.q SP, FRAME_R(44), r44 766 st.q SP, FRAME_R(45), r45 767 st.q SP, FRAME_R(46), r46 768 st.q SP, FRAME_R(47), r47 769 st.q SP, FRAME_R(48), r48 770 st.q SP, FRAME_R(49), r49 771 st.q SP, FRAME_R(50), r50 772 st.q SP, FRAME_R(51), r51 773 st.q SP, FRAME_R(52), r52 774 st.q SP, FRAME_R(53), r53 775 st.q SP, FRAME_R(54), r54 776 st.q SP, FRAME_R(55), r55 777 st.q SP, FRAME_R(56), r56 778 st.q SP, FRAME_R(57), r57 779 st.q SP, FRAME_R(58), r58 780 st.q SP, FRAME_R(59), r59 781 st.q SP, FRAME_R(60), r60 782 st.q SP, FRAME_R(61), r61 783 st.q SP, FRAME_R(62), r62 784 785 /* 786 * Save the S* registers. 787 */ 788 getcon SSR, r61 789 st.q SP, FRAME_S(FSSR), r61 790 getcon SPC, r62 791 st.q SP, FRAME_S(FSPC), r62 792 movi -1, r62 /* Reset syscall_nr */ 793 st.q SP, FRAME_S(FSYSCALL_ID), r62 794 795 /* Save the rest of the target registers */ 796 gettr tr1, r6 797 st.q SP, FRAME_T(1), r6 798 gettr tr2, r6 799 st.q SP, FRAME_T(2), r6 800 gettr tr3, r6 801 st.q SP, FRAME_T(3), r6 802 gettr tr4, r6 803 st.q SP, FRAME_T(4), r6 804 gettr tr5, r6 805 st.q SP, FRAME_T(5), r6 806 gettr tr6, r6 807 st.q SP, FRAME_T(6), r6 808 gettr tr7, r6 809 st.q SP, FRAME_T(7), r6 810 811 ! setup FP so that unwinder can wind back through nested kernel mode 812 ! exceptions 813 add SP, ZERO, r14 814 815 /* For syscall and debug race condition, get TRA now */ 816 getcon TRA, r5 817 818 /* We are in a safe position to turn SR.BL off, but set IMASK=0xf 819 * Also set FD, to catch FPU usage in the kernel. 820 * 821 * benedict.gaster@superh.com 29/07/2002 822 * 823 * On all SH5-101 revisions it is unsafe to raise the IMASK and at the 824 * same time change BL from 1->0, as any pending interrupt of a level 825 * higher than he previous value of IMASK will leak through and be 826 * taken unexpectedly. 827 * 828 * To avoid this we raise the IMASK and then issue another PUTCON to 829 * enable interrupts. 830 */ 831 getcon SR, r6 832 movi SR_IMASK | SR_FD, r7 833 or r6, r7, r6 834 putcon r6, SR 835 movi SR_UNBLOCK_EXC, r7 836 and r6, r7, r6 837 putcon r6, SR 838 839 840 /* Now call the appropriate 3rd level handler */ 841 or r3, ZERO, LINK 842 movi trap_jtable, r3 843 shlri r2, 3, r2 844 ldx.l r2, r3, r3 845 shlri r2, 2, r2 846 ptabs r3, tr0 847 or SP, ZERO, r3 848 blink tr0, ZERO 849 850/* 851 * Second level handler for VBR-based exceptions. Post-handlers. 852 * 853 * Post-handlers for interrupts (ret_from_irq), exceptions 854 * (ret_from_exception) and common reentrance doors (restore_all 855 * to get back to the original context, ret_from_syscall loop to 856 * check kernel exiting). 857 * 858 * ret_with_reschedule and work_notifysig are an inner lables of 859 * the ret_from_syscall loop. 860 * 861 * In common to all stack-frame sensitive handlers. 862 * 863 * Inputs: 864 * (SP) struct pt_regs *, original register's frame pointer (basic) 865 * 866 */ 867 .global ret_from_irq 868ret_from_irq: 869 ld.q SP, FRAME_S(FSSR), r6 870 shlri r6, 30, r6 871 andi r6, 1, r6 872 pta resume_kernel, tr0 873 bne r6, ZERO, tr0 /* no further checks */ 874 STI() 875 pta ret_with_reschedule, tr0 876 blink tr0, ZERO /* Do not check softirqs */ 877 878 .global ret_from_exception 879ret_from_exception: 880 preempt_stop() 881 882 ld.q SP, FRAME_S(FSSR), r6 883 shlri r6, 30, r6 884 andi r6, 1, r6 885 pta resume_kernel, tr0 886 bne r6, ZERO, tr0 /* no further checks */ 887 888 /* Check softirqs */ 889 890#ifdef CONFIG_PREEMPT 891 pta ret_from_syscall, tr0 892 blink tr0, ZERO 893 894resume_kernel: 895 CLI() 896 897 pta restore_all, tr0 898 899 getcon KCR0, r6 900 ld.l r6, TI_PRE_COUNT, r7 901 beq/u r7, ZERO, tr0 902 903need_resched: 904 ld.l r6, TI_FLAGS, r7 905 movi (1 << TIF_NEED_RESCHED), r8 906 and r8, r7, r8 907 bne r8, ZERO, tr0 908 909 getcon SR, r7 910 andi r7, 0xf0, r7 911 bne r7, ZERO, tr0 912 913 movi preempt_schedule_irq, r7 914 ori r7, 1, r7 915 ptabs r7, tr1 916 blink tr1, LINK 917 918 pta need_resched, tr1 919 blink tr1, ZERO 920#endif 921 922 .global ret_from_syscall 923ret_from_syscall: 924 925ret_with_reschedule: 926 getcon KCR0, r6 ! r6 contains current_thread_info 927 ld.l r6, TI_FLAGS, r7 ! r7 contains current_thread_info->flags 928 929 movi _TIF_NEED_RESCHED, r8 930 and r8, r7, r8 931 pta work_resched, tr0 932 bne r8, ZERO, tr0 933 934 pta restore_all, tr1 935 936 movi (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME), r8 937 and r8, r7, r8 938 pta work_notifysig, tr0 939 bne r8, ZERO, tr0 940 941 blink tr1, ZERO 942 943work_resched: 944 pta ret_from_syscall, tr0 945 gettr tr0, LINK 946 movi schedule, r6 947 ptabs r6, tr0 948 blink tr0, ZERO /* Call schedule(), return on top */ 949 950work_notifysig: 951 gettr tr1, LINK 952 953 movi do_notify_resume, r6 954 ptabs r6, tr0 955 or SP, ZERO, r2 956 or r7, ZERO, r3 957 blink tr0, LINK /* Call do_notify_resume(regs, current_thread_info->flags), return here */ 958 959restore_all: 960 /* Do prefetches */ 961 962 ld.q SP, FRAME_T(0), r6 963 ld.q SP, FRAME_T(1), r7 964 ld.q SP, FRAME_T(2), r8 965 ld.q SP, FRAME_T(3), r9 966 ptabs r6, tr0 967 ptabs r7, tr1 968 ptabs r8, tr2 969 ptabs r9, tr3 970 ld.q SP, FRAME_T(4), r6 971 ld.q SP, FRAME_T(5), r7 972 ld.q SP, FRAME_T(6), r8 973 ld.q SP, FRAME_T(7), r9 974 ptabs r6, tr4 975 ptabs r7, tr5 976 ptabs r8, tr6 977 ptabs r9, tr7 978 979 ld.q SP, FRAME_R(0), r0 980 ld.q SP, FRAME_R(1), r1 981 ld.q SP, FRAME_R(2), r2 982 ld.q SP, FRAME_R(3), r3 983 ld.q SP, FRAME_R(4), r4 984 ld.q SP, FRAME_R(5), r5 985 ld.q SP, FRAME_R(6), r6 986 ld.q SP, FRAME_R(7), r7 987 ld.q SP, FRAME_R(8), r8 988 ld.q SP, FRAME_R(9), r9 989 ld.q SP, FRAME_R(10), r10 990 ld.q SP, FRAME_R(11), r11 991 ld.q SP, FRAME_R(12), r12 992 ld.q SP, FRAME_R(13), r13 993 ld.q SP, FRAME_R(14), r14 994 995 ld.q SP, FRAME_R(16), r16 996 ld.q SP, FRAME_R(17), r17 997 ld.q SP, FRAME_R(18), r18 998 ld.q SP, FRAME_R(19), r19 999 ld.q SP, FRAME_R(20), r20 1000 ld.q SP, FRAME_R(21), r21 1001 ld.q SP, FRAME_R(22), r22 1002 ld.q SP, FRAME_R(23), r23 1003 ld.q SP, FRAME_R(24), r24 1004 ld.q SP, FRAME_R(25), r25 1005 ld.q SP, FRAME_R(26), r26 1006 ld.q SP, FRAME_R(27), r27 1007 ld.q SP, FRAME_R(28), r28 1008 ld.q SP, FRAME_R(29), r29 1009 ld.q SP, FRAME_R(30), r30 1010 ld.q SP, FRAME_R(31), r31 1011 ld.q SP, FRAME_R(32), r32 1012 ld.q SP, FRAME_R(33), r33 1013 ld.q SP, FRAME_R(34), r34 1014 ld.q SP, FRAME_R(35), r35 1015 ld.q SP, FRAME_R(36), r36 1016 ld.q SP, FRAME_R(37), r37 1017 ld.q SP, FRAME_R(38), r38 1018 ld.q SP, FRAME_R(39), r39 1019 ld.q SP, FRAME_R(40), r40 1020 ld.q SP, FRAME_R(41), r41 1021 ld.q SP, FRAME_R(42), r42 1022 ld.q SP, FRAME_R(43), r43 1023 ld.q SP, FRAME_R(44), r44 1024 ld.q SP, FRAME_R(45), r45 1025 ld.q SP, FRAME_R(46), r46 1026 ld.q SP, FRAME_R(47), r47 1027 ld.q SP, FRAME_R(48), r48 1028 ld.q SP, FRAME_R(49), r49 1029 ld.q SP, FRAME_R(50), r50 1030 ld.q SP, FRAME_R(51), r51 1031 ld.q SP, FRAME_R(52), r52 1032 ld.q SP, FRAME_R(53), r53 1033 ld.q SP, FRAME_R(54), r54 1034 ld.q SP, FRAME_R(55), r55 1035 ld.q SP, FRAME_R(56), r56 1036 ld.q SP, FRAME_R(57), r57 1037 ld.q SP, FRAME_R(58), r58 1038 1039 getcon SR, r59 1040 movi SR_BLOCK_EXC, r60 1041 or r59, r60, r59 1042 putcon r59, SR /* SR.BL = 1, keep nesting out */ 1043 ld.q SP, FRAME_S(FSSR), r61 1044 ld.q SP, FRAME_S(FSPC), r62 1045 movi SR_ASID_MASK, r60 1046 and r59, r60, r59 1047 andc r61, r60, r61 /* Clear out older ASID */ 1048 or r59, r61, r61 /* Retain current ASID */ 1049 putcon r61, SSR 1050 putcon r62, SPC 1051 1052 /* Ignore FSYSCALL_ID */ 1053 1054 ld.q SP, FRAME_R(59), r59 1055 ld.q SP, FRAME_R(60), r60 1056 ld.q SP, FRAME_R(61), r61 1057 ld.q SP, FRAME_R(62), r62 1058 1059 /* Last touch */ 1060 ld.q SP, FRAME_R(15), SP 1061 rte 1062 nop 1063 1064/* 1065 * Third level handlers for VBR-based exceptions. Adapting args to 1066 * and/or deflecting to fourth level handlers. 1067 * 1068 * Fourth level handlers interface. 1069 * Most are C-coded handlers directly pointed by the trap_jtable. 1070 * (Third = Fourth level) 1071 * Inputs: 1072 * (r2) fault/interrupt code, entry number (e.g. NMI = 14, 1073 * IRL0-3 (0000) = 16, RTLBMISS = 2, SYSCALL = 11, etc ...) 1074 * (r3) struct pt_regs *, original register's frame pointer 1075 * (r4) Event (0 = interrupt, 1 = TLB miss fault, 2 = Not TLB miss fault) 1076 * (r5) TRA control register (for syscall/debug benefit only) 1077 * (LINK) return address 1078 * (SP) = r3 1079 * 1080 * Kernel TLB fault handlers will get a slightly different interface. 1081 * (r2) struct pt_regs *, original register's frame pointer 1082 * (r3) page fault error code (see asm/thread_info.h) 1083 * (r4) Effective Address of fault 1084 * (LINK) return address 1085 * (SP) = r2 1086 * 1087 * fpu_error_or_IRQ? is a helper to deflect to the right cause. 1088 * 1089 */ 1090#ifdef CONFIG_MMU 1091tlb_miss_load: 1092 or SP, ZERO, r2 1093 or ZERO, ZERO, r3 /* Read */ 1094 getcon TEA, r4 1095 pta call_do_page_fault, tr0 1096 beq ZERO, ZERO, tr0 1097 1098tlb_miss_store: 1099 or SP, ZERO, r2 1100 movi FAULT_CODE_WRITE, r3 /* Write */ 1101 getcon TEA, r4 1102 pta call_do_page_fault, tr0 1103 beq ZERO, ZERO, tr0 1104 1105itlb_miss_or_IRQ: 1106 pta its_IRQ, tr0 1107 beqi/u r4, EVENT_INTERRUPT, tr0 1108 1109 /* ITLB miss */ 1110 or SP, ZERO, r2 1111 movi FAULT_CODE_ITLB, r3 1112 getcon TEA, r4 1113 /* Fall through */ 1114 1115call_do_page_fault: 1116 movi do_page_fault, r6 1117 ptabs r6, tr0 1118 blink tr0, ZERO 1119#endif /* CONFIG_MMU */ 1120 1121fpu_error_or_IRQA: 1122 pta its_IRQ, tr0 1123 beqi/l r4, EVENT_INTERRUPT, tr0 1124#ifdef CONFIG_SH_FPU 1125 movi fpu_state_restore_trap_handler, r6 1126#else 1127 movi do_exception_error, r6 1128#endif 1129 ptabs r6, tr0 1130 blink tr0, ZERO 1131 1132fpu_error_or_IRQB: 1133 pta its_IRQ, tr0 1134 beqi/l r4, EVENT_INTERRUPT, tr0 1135#ifdef CONFIG_SH_FPU 1136 movi fpu_state_restore_trap_handler, r6 1137#else 1138 movi do_exception_error, r6 1139#endif 1140 ptabs r6, tr0 1141 blink tr0, ZERO 1142 1143its_IRQ: 1144 movi do_IRQ, r6 1145 ptabs r6, tr0 1146 blink tr0, ZERO 1147 1148/* 1149 * system_call/unknown_trap third level handler: 1150 * 1151 * Inputs: 1152 * (r2) fault/interrupt code, entry number (TRAP = 11) 1153 * (r3) struct pt_regs *, original register's frame pointer 1154 * (r4) Not used. Event (0=interrupt, 1=TLB miss fault, 2=Not TLB miss fault) 1155 * (r5) TRA Control Reg (0x00xyzzzz: x=1 SYSCALL, y = #args, z=nr) 1156 * (SP) = r3 1157 * (LINK) return address: ret_from_exception 1158 * (*r3) Syscall parms: SC#, arg0, arg1, ..., arg5 in order (Saved r2/r7) 1159 * 1160 * Outputs: 1161 * (*r3) Syscall reply (Saved r2) 1162 * (LINK) In case of syscall only it can be scrapped. 1163 * Common second level post handler will be ret_from_syscall. 1164 * Common (non-trace) exit point to that is syscall_ret (saving 1165 * result to r2). Common bad exit point is syscall_bad (returning 1166 * ENOSYS then saved to r2). 1167 * 1168 */ 1169 1170unknown_trap: 1171 /* Unknown Trap or User Trace */ 1172 movi do_unknown_trapa, r6 1173 ptabs r6, tr0 1174 ld.q r3, FRAME_R(9), r2 /* r2 = #arg << 16 | syscall # */ 1175 andi r2, 0x1ff, r2 /* r2 = syscall # */ 1176 blink tr0, LINK 1177 1178 pta syscall_ret, tr0 1179 blink tr0, ZERO 1180 1181 /* New syscall implementation*/ 1182system_call: 1183 pta unknown_trap, tr0 1184 or r5, ZERO, r4 /* TRA (=r5) -> r4 */ 1185 shlri r4, 20, r4 1186 bnei r4, 1, tr0 /* unknown_trap if not 0x1yzzzz */ 1187 1188 /* It's a system call */ 1189 st.q r3, FRAME_S(FSYSCALL_ID), r5 /* ID (0x1yzzzz) -> stack */ 1190 andi r5, 0x1ff, r5 /* syscall # -> r5 */ 1191 1192 STI() 1193 1194 pta syscall_allowed, tr0 1195 movi NR_syscalls - 1, r4 /* Last valid */ 1196 bgeu/l r4, r5, tr0 1197 1198syscall_bad: 1199 /* Return ENOSYS ! */ 1200 movi -(ENOSYS), r2 /* Fall-through */ 1201 1202 .global syscall_ret 1203syscall_ret: 1204 st.q SP, FRAME_R(9), r2 /* Expecting SP back to BASIC frame */ 1205 ld.q SP, FRAME_S(FSPC), r2 1206 addi r2, 4, r2 /* Move PC, being pre-execution event */ 1207 st.q SP, FRAME_S(FSPC), r2 1208 pta ret_from_syscall, tr0 1209 blink tr0, ZERO 1210 1211 1212/* A different return path for ret_from_fork, because we now need 1213 * to call schedule_tail with the later kernels. Because prev is 1214 * loaded into r2 by switch_to() means we can just call it straight away 1215 */ 1216 1217.global ret_from_fork 1218ret_from_fork: 1219 1220 movi schedule_tail,r5 1221 ori r5, 1, r5 1222 ptabs r5, tr0 1223 blink tr0, LINK 1224 1225 ld.q SP, FRAME_S(FSPC), r2 1226 addi r2, 4, r2 /* Move PC, being pre-execution event */ 1227 st.q SP, FRAME_S(FSPC), r2 1228 pta ret_from_syscall, tr0 1229 blink tr0, ZERO 1230 1231.global ret_from_kernel_thread 1232ret_from_kernel_thread: 1233 1234 movi schedule_tail,r5 1235 ori r5, 1, r5 1236 ptabs r5, tr0 1237 blink tr0, LINK 1238 1239 ld.q SP, FRAME_R(2), r2 1240 ld.q SP, FRAME_R(3), r3 1241 ptabs r3, tr0 1242 blink tr0, LINK 1243 1244 ld.q SP, FRAME_S(FSPC), r2 1245 addi r2, 4, r2 /* Move PC, being pre-execution event */ 1246 st.q SP, FRAME_S(FSPC), r2 1247 pta ret_from_syscall, tr0 1248 blink tr0, ZERO 1249 1250syscall_allowed: 1251 /* Use LINK to deflect the exit point, default is syscall_ret */ 1252 pta syscall_ret, tr0 1253 gettr tr0, LINK 1254 pta syscall_notrace, tr0 1255 1256 getcon KCR0, r2 1257 ld.l r2, TI_FLAGS, r4 1258 movi _TIF_WORK_SYSCALL_MASK, r6 1259 and r6, r4, r6 1260 beq/l r6, ZERO, tr0 1261 1262 /* Trace it by calling syscall_trace before and after */ 1263 movi do_syscall_trace_enter, r4 1264 or SP, ZERO, r2 1265 ptabs r4, tr0 1266 blink tr0, LINK 1267 1268 /* Save the retval */ 1269 st.q SP, FRAME_R(2), r2 1270 1271 /* Reload syscall number as r5 is trashed by do_syscall_trace_enter */ 1272 ld.q SP, FRAME_S(FSYSCALL_ID), r5 1273 andi r5, 0x1ff, r5 1274 1275 pta syscall_ret_trace, tr0 1276 gettr tr0, LINK 1277 1278syscall_notrace: 1279 /* Now point to the appropriate 4th level syscall handler */ 1280 movi sys_call_table, r4 1281 shlli r5, 2, r5 1282 ldx.l r4, r5, r5 1283 ptabs r5, tr0 1284 1285 /* Prepare original args */ 1286 ld.q SP, FRAME_R(2), r2 1287 ld.q SP, FRAME_R(3), r3 1288 ld.q SP, FRAME_R(4), r4 1289 ld.q SP, FRAME_R(5), r5 1290 ld.q SP, FRAME_R(6), r6 1291 ld.q SP, FRAME_R(7), r7 1292 1293 /* And now the trick for those syscalls requiring regs * ! */ 1294 or SP, ZERO, r8 1295 1296 /* Call it */ 1297 blink tr0, ZERO /* LINK is already properly set */ 1298 1299syscall_ret_trace: 1300 /* We get back here only if under trace */ 1301 st.q SP, FRAME_R(9), r2 /* Save return value */ 1302 1303 movi do_syscall_trace_leave, LINK 1304 or SP, ZERO, r2 1305 ptabs LINK, tr0 1306 blink tr0, LINK 1307 1308 /* This needs to be done after any syscall tracing */ 1309 ld.q SP, FRAME_S(FSPC), r2 1310 addi r2, 4, r2 /* Move PC, being pre-execution event */ 1311 st.q SP, FRAME_S(FSPC), r2 1312 1313 pta ret_from_syscall, tr0 1314 blink tr0, ZERO /* Resume normal return sequence */ 1315 1316/* 1317 * --- Switch to running under a particular ASID and return the previous ASID value 1318 * --- The caller is assumed to have done a cli before calling this. 1319 * 1320 * Input r2 : new ASID 1321 * Output r2 : old ASID 1322 */ 1323 1324 .global switch_and_save_asid 1325switch_and_save_asid: 1326 getcon sr, r0 1327 movi 255, r4 1328 shlli r4, 16, r4 /* r4 = mask to select ASID */ 1329 and r0, r4, r3 /* r3 = shifted old ASID */ 1330 andi r2, 255, r2 /* mask down new ASID */ 1331 shlli r2, 16, r2 /* align new ASID against SR.ASID */ 1332 andc r0, r4, r0 /* efface old ASID from SR */ 1333 or r0, r2, r0 /* insert the new ASID */ 1334 putcon r0, ssr 1335 movi 1f, r0 1336 putcon r0, spc 1337 rte 1338 nop 13391: 1340 ptabs LINK, tr0 1341 shlri r3, 16, r2 /* r2 = old ASID */ 1342 blink tr0, r63 1343 1344 .global route_to_panic_handler 1345route_to_panic_handler: 1346 /* Switch to real mode, goto panic_handler, don't return. Useful for 1347 last-chance debugging, e.g. if no output wants to go to the console. 1348 */ 1349 1350 movi panic_handler - CONFIG_PAGE_OFFSET, r1 1351 ptabs r1, tr0 1352 pta 1f, tr1 1353 gettr tr1, r0 1354 putcon r0, spc 1355 getcon sr, r0 1356 movi 1, r1 1357 shlli r1, 31, r1 1358 andc r0, r1, r0 1359 putcon r0, ssr 1360 rte 1361 nop 13621: /* Now in real mode */ 1363 blink tr0, r63 1364 nop 1365 1366 .global peek_real_address_q 1367peek_real_address_q: 1368 /* Two args: 1369 r2 : real mode address to peek 1370 r2(out) : result quadword 1371 1372 This is provided as a cheapskate way of manipulating device 1373 registers for debugging (to avoid the need to ioremap the debug 1374 module, and to avoid the need to ioremap the watchpoint 1375 controller in a way that identity maps sufficient bits to avoid the 1376 SH5-101 cut2 silicon defect). 1377 1378 This code is not performance critical 1379 */ 1380 1381 add.l r2, r63, r2 /* sign extend address */ 1382 getcon sr, r0 /* r0 = saved original SR */ 1383 movi 1, r1 1384 shlli r1, 28, r1 1385 or r0, r1, r1 /* r0 with block bit set */ 1386 putcon r1, sr /* now in critical section */ 1387 movi 1, r36 1388 shlli r36, 31, r36 1389 andc r1, r36, r1 /* turn sr.mmu off in real mode section */ 1390 1391 putcon r1, ssr 1392 movi .peek0 - CONFIG_PAGE_OFFSET, r36 /* real mode target address */ 1393 movi 1f, r37 /* virtual mode return addr */ 1394 putcon r36, spc 1395 1396 synco 1397 rte 1398 nop 1399 1400.peek0: /* come here in real mode, don't touch caches!! 1401 still in critical section (sr.bl==1) */ 1402 putcon r0, ssr 1403 putcon r37, spc 1404 /* Here's the actual peek. If the address is bad, all bets are now off 1405 * what will happen (handlers invoked in real-mode = bad news) */ 1406 ld.q r2, 0, r2 1407 synco 1408 rte /* Back to virtual mode */ 1409 nop 1410 14111: 1412 ptabs LINK, tr0 1413 blink tr0, r63 1414 1415 .global poke_real_address_q 1416poke_real_address_q: 1417 /* Two args: 1418 r2 : real mode address to poke 1419 r3 : quadword value to write. 1420 1421 This is provided as a cheapskate way of manipulating device 1422 registers for debugging (to avoid the need to ioremap the debug 1423 module, and to avoid the need to ioremap the watchpoint 1424 controller in a way that identity maps sufficient bits to avoid the 1425 SH5-101 cut2 silicon defect). 1426 1427 This code is not performance critical 1428 */ 1429 1430 add.l r2, r63, r2 /* sign extend address */ 1431 getcon sr, r0 /* r0 = saved original SR */ 1432 movi 1, r1 1433 shlli r1, 28, r1 1434 or r0, r1, r1 /* r0 with block bit set */ 1435 putcon r1, sr /* now in critical section */ 1436 movi 1, r36 1437 shlli r36, 31, r36 1438 andc r1, r36, r1 /* turn sr.mmu off in real mode section */ 1439 1440 putcon r1, ssr 1441 movi .poke0-CONFIG_PAGE_OFFSET, r36 /* real mode target address */ 1442 movi 1f, r37 /* virtual mode return addr */ 1443 putcon r36, spc 1444 1445 synco 1446 rte 1447 nop 1448 1449.poke0: /* come here in real mode, don't touch caches!! 1450 still in critical section (sr.bl==1) */ 1451 putcon r0, ssr 1452 putcon r37, spc 1453 /* Here's the actual poke. If the address is bad, all bets are now off 1454 * what will happen (handlers invoked in real-mode = bad news) */ 1455 st.q r2, 0, r3 1456 synco 1457 rte /* Back to virtual mode */ 1458 nop 1459 14601: 1461 ptabs LINK, tr0 1462 blink tr0, r63 1463 1464#ifdef CONFIG_MMU 1465/* 1466 * --- User Access Handling Section 1467 */ 1468 1469/* 1470 * User Access support. It all moved to non inlined Assembler 1471 * functions in here. 1472 * 1473 * __kernel_size_t __copy_user(void *__to, const void *__from, 1474 * __kernel_size_t __n) 1475 * 1476 * Inputs: 1477 * (r2) target address 1478 * (r3) source address 1479 * (r4) size in bytes 1480 * 1481 * Ouputs: 1482 * (*r2) target data 1483 * (r2) non-copied bytes 1484 * 1485 * If a fault occurs on the user pointer, bail out early and return the 1486 * number of bytes not copied in r2. 1487 * Strategy : for large blocks, call a real memcpy function which can 1488 * move >1 byte at a time using unaligned ld/st instructions, and can 1489 * manipulate the cache using prefetch + alloco to improve the speed 1490 * further. If a fault occurs in that function, just revert to the 1491 * byte-by-byte approach used for small blocks; this is rare so the 1492 * performance hit for that case does not matter. 1493 * 1494 * For small blocks it's not worth the overhead of setting up and calling 1495 * the memcpy routine; do the copy a byte at a time. 1496 * 1497 */ 1498 .global __copy_user 1499__copy_user: 1500 pta __copy_user_byte_by_byte, tr1 1501 movi 16, r0 ! this value is a best guess, should tune it by benchmarking 1502 bge/u r0, r4, tr1 1503 pta copy_user_memcpy, tr0 1504 addi SP, -32, SP 1505 /* Save arguments in case we have to fix-up unhandled page fault */ 1506 st.q SP, 0, r2 1507 st.q SP, 8, r3 1508 st.q SP, 16, r4 1509 st.q SP, 24, r35 ! r35 is callee-save 1510 /* Save LINK in a register to reduce RTS time later (otherwise 1511 ld SP,*,LINK;ptabs LINK;trn;blink trn,r63 becomes a critical path) */ 1512 ori LINK, 0, r35 1513 blink tr0, LINK 1514 1515 /* Copy completed normally if we get back here */ 1516 ptabs r35, tr0 1517 ld.q SP, 24, r35 1518 /* don't restore r2-r4, pointless */ 1519 /* set result=r2 to zero as the copy must have succeeded. */ 1520 or r63, r63, r2 1521 addi SP, 32, SP 1522 blink tr0, r63 ! RTS 1523 1524 .global __copy_user_fixup 1525__copy_user_fixup: 1526 /* Restore stack frame */ 1527 ori r35, 0, LINK 1528 ld.q SP, 24, r35 1529 ld.q SP, 16, r4 1530 ld.q SP, 8, r3 1531 ld.q SP, 0, r2 1532 addi SP, 32, SP 1533 /* Fall through to original code, in the 'same' state we entered with */ 1534 1535/* The slow byte-by-byte method is used if the fast copy traps due to a bad 1536 user address. In that rare case, the speed drop can be tolerated. */ 1537__copy_user_byte_by_byte: 1538 pta ___copy_user_exit, tr1 1539 pta ___copy_user1, tr0 1540 beq/u r4, r63, tr1 /* early exit for zero length copy */ 1541 sub r2, r3, r0 1542 addi r0, -1, r0 1543 1544___copy_user1: 1545 ld.b r3, 0, r5 /* Fault address 1 */ 1546 1547 /* Could rewrite this to use just 1 add, but the second comes 'free' 1548 due to load latency */ 1549 addi r3, 1, r3 1550 addi r4, -1, r4 /* No real fixup required */ 1551___copy_user2: 1552 stx.b r3, r0, r5 /* Fault address 2 */ 1553 bne r4, ZERO, tr0 1554 1555___copy_user_exit: 1556 or r4, ZERO, r2 1557 ptabs LINK, tr0 1558 blink tr0, ZERO 1559 1560/* 1561 * __kernel_size_t __clear_user(void *addr, __kernel_size_t size) 1562 * 1563 * Inputs: 1564 * (r2) target address 1565 * (r3) size in bytes 1566 * 1567 * Ouputs: 1568 * (*r2) zero-ed target data 1569 * (r2) non-zero-ed bytes 1570 */ 1571 .global __clear_user 1572__clear_user: 1573 pta ___clear_user_exit, tr1 1574 pta ___clear_user1, tr0 1575 beq/u r3, r63, tr1 1576 1577___clear_user1: 1578 st.b r2, 0, ZERO /* Fault address */ 1579 addi r2, 1, r2 1580 addi r3, -1, r3 /* No real fixup required */ 1581 bne r3, ZERO, tr0 1582 1583___clear_user_exit: 1584 or r3, ZERO, r2 1585 ptabs LINK, tr0 1586 blink tr0, ZERO 1587 1588#endif /* CONFIG_MMU */ 1589 1590/* 1591 * extern long __get_user_asm_?(void *val, long addr) 1592 * 1593 * Inputs: 1594 * (r2) dest address 1595 * (r3) source address (in User Space) 1596 * 1597 * Ouputs: 1598 * (r2) -EFAULT (faulting) 1599 * 0 (not faulting) 1600 */ 1601 .global __get_user_asm_b 1602__get_user_asm_b: 1603 or r2, ZERO, r4 1604 movi -(EFAULT), r2 /* r2 = reply, no real fixup */ 1605 1606___get_user_asm_b1: 1607 ld.b r3, 0, r5 /* r5 = data */ 1608 st.b r4, 0, r5 1609 or ZERO, ZERO, r2 1610 1611___get_user_asm_b_exit: 1612 ptabs LINK, tr0 1613 blink tr0, ZERO 1614 1615 1616 .global __get_user_asm_w 1617__get_user_asm_w: 1618 or r2, ZERO, r4 1619 movi -(EFAULT), r2 /* r2 = reply, no real fixup */ 1620 1621___get_user_asm_w1: 1622 ld.w r3, 0, r5 /* r5 = data */ 1623 st.w r4, 0, r5 1624 or ZERO, ZERO, r2 1625 1626___get_user_asm_w_exit: 1627 ptabs LINK, tr0 1628 blink tr0, ZERO 1629 1630 1631 .global __get_user_asm_l 1632__get_user_asm_l: 1633 or r2, ZERO, r4 1634 movi -(EFAULT), r2 /* r2 = reply, no real fixup */ 1635 1636___get_user_asm_l1: 1637 ld.l r3, 0, r5 /* r5 = data */ 1638 st.l r4, 0, r5 1639 or ZERO, ZERO, r2 1640 1641___get_user_asm_l_exit: 1642 ptabs LINK, tr0 1643 blink tr0, ZERO 1644 1645 1646 .global __get_user_asm_q 1647__get_user_asm_q: 1648 or r2, ZERO, r4 1649 movi -(EFAULT), r2 /* r2 = reply, no real fixup */ 1650 1651___get_user_asm_q1: 1652 ld.q r3, 0, r5 /* r5 = data */ 1653 st.q r4, 0, r5 1654 or ZERO, ZERO, r2 1655 1656___get_user_asm_q_exit: 1657 ptabs LINK, tr0 1658 blink tr0, ZERO 1659 1660/* 1661 * extern long __put_user_asm_?(void *pval, long addr) 1662 * 1663 * Inputs: 1664 * (r2) kernel pointer to value 1665 * (r3) dest address (in User Space) 1666 * 1667 * Ouputs: 1668 * (r2) -EFAULT (faulting) 1669 * 0 (not faulting) 1670 */ 1671 .global __put_user_asm_b 1672__put_user_asm_b: 1673 ld.b r2, 0, r4 /* r4 = data */ 1674 movi -(EFAULT), r2 /* r2 = reply, no real fixup */ 1675 1676___put_user_asm_b1: 1677 st.b r3, 0, r4 1678 or ZERO, ZERO, r2 1679 1680___put_user_asm_b_exit: 1681 ptabs LINK, tr0 1682 blink tr0, ZERO 1683 1684 1685 .global __put_user_asm_w 1686__put_user_asm_w: 1687 ld.w r2, 0, r4 /* r4 = data */ 1688 movi -(EFAULT), r2 /* r2 = reply, no real fixup */ 1689 1690___put_user_asm_w1: 1691 st.w r3, 0, r4 1692 or ZERO, ZERO, r2 1693 1694___put_user_asm_w_exit: 1695 ptabs LINK, tr0 1696 blink tr0, ZERO 1697 1698 1699 .global __put_user_asm_l 1700__put_user_asm_l: 1701 ld.l r2, 0, r4 /* r4 = data */ 1702 movi -(EFAULT), r2 /* r2 = reply, no real fixup */ 1703 1704___put_user_asm_l1: 1705 st.l r3, 0, r4 1706 or ZERO, ZERO, r2 1707 1708___put_user_asm_l_exit: 1709 ptabs LINK, tr0 1710 blink tr0, ZERO 1711 1712 1713 .global __put_user_asm_q 1714__put_user_asm_q: 1715 ld.q r2, 0, r4 /* r4 = data */ 1716 movi -(EFAULT), r2 /* r2 = reply, no real fixup */ 1717 1718___put_user_asm_q1: 1719 st.q r3, 0, r4 1720 or ZERO, ZERO, r2 1721 1722___put_user_asm_q_exit: 1723 ptabs LINK, tr0 1724 blink tr0, ZERO 1725 1726panic_stash_regs: 1727 /* The idea is : when we get an unhandled panic, we dump the registers 1728 to a known memory location, the just sit in a tight loop. 1729 This allows the human to look at the memory region through the GDB 1730 session (assuming the debug module's SHwy initiator isn't locked up 1731 or anything), to hopefully analyze the cause of the panic. */ 1732 1733 /* On entry, former r15 (SP) is in DCR 1734 former r0 is at resvec_saved_area + 0 1735 former r1 is at resvec_saved_area + 8 1736 former tr0 is at resvec_saved_area + 32 1737 DCR is the only register whose value is lost altogether. 1738 */ 1739 1740 movi 0xffffffff80000000, r0 ! phy of dump area 1741 ld.q SP, 0x000, r1 ! former r0 1742 st.q r0, 0x000, r1 1743 ld.q SP, 0x008, r1 ! former r1 1744 st.q r0, 0x008, r1 1745 st.q r0, 0x010, r2 1746 st.q r0, 0x018, r3 1747 st.q r0, 0x020, r4 1748 st.q r0, 0x028, r5 1749 st.q r0, 0x030, r6 1750 st.q r0, 0x038, r7 1751 st.q r0, 0x040, r8 1752 st.q r0, 0x048, r9 1753 st.q r0, 0x050, r10 1754 st.q r0, 0x058, r11 1755 st.q r0, 0x060, r12 1756 st.q r0, 0x068, r13 1757 st.q r0, 0x070, r14 1758 getcon dcr, r14 1759 st.q r0, 0x078, r14 1760 st.q r0, 0x080, r16 1761 st.q r0, 0x088, r17 1762 st.q r0, 0x090, r18 1763 st.q r0, 0x098, r19 1764 st.q r0, 0x0a0, r20 1765 st.q r0, 0x0a8, r21 1766 st.q r0, 0x0b0, r22 1767 st.q r0, 0x0b8, r23 1768 st.q r0, 0x0c0, r24 1769 st.q r0, 0x0c8, r25 1770 st.q r0, 0x0d0, r26 1771 st.q r0, 0x0d8, r27 1772 st.q r0, 0x0e0, r28 1773 st.q r0, 0x0e8, r29 1774 st.q r0, 0x0f0, r30 1775 st.q r0, 0x0f8, r31 1776 st.q r0, 0x100, r32 1777 st.q r0, 0x108, r33 1778 st.q r0, 0x110, r34 1779 st.q r0, 0x118, r35 1780 st.q r0, 0x120, r36 1781 st.q r0, 0x128, r37 1782 st.q r0, 0x130, r38 1783 st.q r0, 0x138, r39 1784 st.q r0, 0x140, r40 1785 st.q r0, 0x148, r41 1786 st.q r0, 0x150, r42 1787 st.q r0, 0x158, r43 1788 st.q r0, 0x160, r44 1789 st.q r0, 0x168, r45 1790 st.q r0, 0x170, r46 1791 st.q r0, 0x178, r47 1792 st.q r0, 0x180, r48 1793 st.q r0, 0x188, r49 1794 st.q r0, 0x190, r50 1795 st.q r0, 0x198, r51 1796 st.q r0, 0x1a0, r52 1797 st.q r0, 0x1a8, r53 1798 st.q r0, 0x1b0, r54 1799 st.q r0, 0x1b8, r55 1800 st.q r0, 0x1c0, r56 1801 st.q r0, 0x1c8, r57 1802 st.q r0, 0x1d0, r58 1803 st.q r0, 0x1d8, r59 1804 st.q r0, 0x1e0, r60 1805 st.q r0, 0x1e8, r61 1806 st.q r0, 0x1f0, r62 1807 st.q r0, 0x1f8, r63 ! bogus, but for consistency's sake... 1808 1809 ld.q SP, 0x020, r1 ! former tr0 1810 st.q r0, 0x200, r1 1811 gettr tr1, r1 1812 st.q r0, 0x208, r1 1813 gettr tr2, r1 1814 st.q r0, 0x210, r1 1815 gettr tr3, r1 1816 st.q r0, 0x218, r1 1817 gettr tr4, r1 1818 st.q r0, 0x220, r1 1819 gettr tr5, r1 1820 st.q r0, 0x228, r1 1821 gettr tr6, r1 1822 st.q r0, 0x230, r1 1823 gettr tr7, r1 1824 st.q r0, 0x238, r1 1825 1826 getcon sr, r1 1827 getcon ssr, r2 1828 getcon pssr, r3 1829 getcon spc, r4 1830 getcon pspc, r5 1831 getcon intevt, r6 1832 getcon expevt, r7 1833 getcon pexpevt, r8 1834 getcon tra, r9 1835 getcon tea, r10 1836 getcon kcr0, r11 1837 getcon kcr1, r12 1838 getcon vbr, r13 1839 getcon resvec, r14 1840 1841 st.q r0, 0x240, r1 1842 st.q r0, 0x248, r2 1843 st.q r0, 0x250, r3 1844 st.q r0, 0x258, r4 1845 st.q r0, 0x260, r5 1846 st.q r0, 0x268, r6 1847 st.q r0, 0x270, r7 1848 st.q r0, 0x278, r8 1849 st.q r0, 0x280, r9 1850 st.q r0, 0x288, r10 1851 st.q r0, 0x290, r11 1852 st.q r0, 0x298, r12 1853 st.q r0, 0x2a0, r13 1854 st.q r0, 0x2a8, r14 1855 1856 getcon SPC,r2 1857 getcon SSR,r3 1858 getcon EXPEVT,r4 1859 /* Prepare to jump to C - physical address */ 1860 movi panic_handler-CONFIG_PAGE_OFFSET, r1 1861 ori r1, 1, r1 1862 ptabs r1, tr0 1863 getcon DCR, SP 1864 blink tr0, ZERO 1865 nop 1866 nop 1867 nop 1868 nop 1869 1870 1871 1872 1873/* 1874 * --- Signal Handling Section 1875 */ 1876 1877/* 1878 * extern long long _sa_default_rt_restorer 1879 * extern long long _sa_default_restorer 1880 * 1881 * or, better, 1882 * 1883 * extern void _sa_default_rt_restorer(void) 1884 * extern void _sa_default_restorer(void) 1885 * 1886 * Code prototypes to do a sys_rt_sigreturn() or sys_sysreturn() 1887 * from user space. Copied into user space by signal management. 1888 * Both must be quad aligned and 2 quad long (4 instructions). 1889 * 1890 */ 1891 .balign 8 1892 .global sa_default_rt_restorer 1893sa_default_rt_restorer: 1894 movi 0x10, r9 1895 shori __NR_rt_sigreturn, r9 1896 trapa r9 1897 nop 1898 1899 .balign 8 1900 .global sa_default_restorer 1901sa_default_restorer: 1902 movi 0x10, r9 1903 shori __NR_sigreturn, r9 1904 trapa r9 1905 nop 1906 1907/* 1908 * --- __ex_table Section 1909 */ 1910 1911/* 1912 * User Access Exception Table. 1913 */ 1914 .section __ex_table, "a" 1915 1916 .global asm_uaccess_start /* Just a marker */ 1917asm_uaccess_start: 1918 1919#ifdef CONFIG_MMU 1920 .long ___copy_user1, ___copy_user_exit 1921 .long ___copy_user2, ___copy_user_exit 1922 .long ___clear_user1, ___clear_user_exit 1923#endif 1924 .long ___get_user_asm_b1, ___get_user_asm_b_exit 1925 .long ___get_user_asm_w1, ___get_user_asm_w_exit 1926 .long ___get_user_asm_l1, ___get_user_asm_l_exit 1927 .long ___get_user_asm_q1, ___get_user_asm_q_exit 1928 .long ___put_user_asm_b1, ___put_user_asm_b_exit 1929 .long ___put_user_asm_w1, ___put_user_asm_w_exit 1930 .long ___put_user_asm_l1, ___put_user_asm_l_exit 1931 .long ___put_user_asm_q1, ___put_user_asm_q_exit 1932 1933 .global asm_uaccess_end /* Just a marker */ 1934asm_uaccess_end: 1935 1936 1937 1938 1939/* 1940 * --- .init.text Section 1941 */ 1942 1943 __INIT 1944 1945/* 1946 * void trap_init (void) 1947 * 1948 */ 1949 .global trap_init 1950trap_init: 1951 addi SP, -24, SP /* Room to save r28/r29/r30 */ 1952 st.q SP, 0, r28 1953 st.q SP, 8, r29 1954 st.q SP, 16, r30 1955 1956 /* Set VBR and RESVEC */ 1957 movi LVBR_block, r19 1958 andi r19, -4, r19 /* reset MMUOFF + reserved */ 1959 /* For RESVEC exceptions we force the MMU off, which means we need the 1960 physical address. */ 1961 movi LRESVEC_block-CONFIG_PAGE_OFFSET, r20 1962 andi r20, -4, r20 /* reset reserved */ 1963 ori r20, 1, r20 /* set MMUOFF */ 1964 putcon r19, VBR 1965 putcon r20, RESVEC 1966 1967 /* Sanity check */ 1968 movi LVBR_block_end, r21 1969 andi r21, -4, r21 1970 movi BLOCK_SIZE, r29 /* r29 = expected size */ 1971 or r19, ZERO, r30 1972 add r19, r29, r19 1973 1974 /* 1975 * Ugly, but better loop forever now than crash afterwards. 1976 * We should print a message, but if we touch LVBR or 1977 * LRESVEC blocks we should not be surprised if we get stuck 1978 * in trap_init(). 1979 */ 1980 pta trap_init_loop, tr1 1981 gettr tr1, r28 /* r28 = trap_init_loop */ 1982 sub r21, r30, r30 /* r30 = actual size */ 1983 1984 /* 1985 * VBR/RESVEC handlers overlap by being bigger than 1986 * allowed. Very bad. Just loop forever. 1987 * (r28) panic/loop address 1988 * (r29) expected size 1989 * (r30) actual size 1990 */ 1991trap_init_loop: 1992 bne r19, r21, tr1 1993 1994 /* Now that exception vectors are set up reset SR.BL */ 1995 getcon SR, r22 1996 movi SR_UNBLOCK_EXC, r23 1997 and r22, r23, r22 1998 putcon r22, SR 1999 2000 addi SP, 24, SP 2001 ptabs LINK, tr0 2002 blink tr0, ZERO 2003 2004