1/* 2 * linux/arch/arm/kernel/entry-armv.S 3 * 4 * Copyright (C) 1996,1997,1998 Russell King. 5 * ARM700 fix by Matthew Godbolt (linux-user@willothewisp.demon.co.uk) 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * Low-level vector interface routines 12 * 13 * Note: there is a StrongARM bug in the STMIA rn, {regs}^ instruction that causes 14 * it to save wrong values... Be aware! 15 */ 16#include <linux/config.h> 17 18#include <asm/memory.h> 19#include <asm/glue.h> 20#include <asm/vfpmacros.h> 21#include <asm/hardware.h> /* should be moved into entry-macro.S */ 22#include <asm/arch/irqs.h> /* should be moved into entry-macro.S */ 23#include <asm/arch/entry-macro.S> 24 25#include "entry-header.S" 26 27/* 28 * Interrupt handling. Preserves r7, r8, r9 29 */ 30 .macro irq_handler 311: get_irqnr_and_base r0, r6, r5, lr 32 movne r1, sp 33 @ 34 @ routine called with r0 = irq number, r1 = struct pt_regs * 35 @ 36 adrne lr, 1b 37 bne asm_do_IRQ 38 39#ifdef CONFIG_SMP 40 /* 41 * XXX 42 * 43 * this macro assumes that irqstat (r6) and base (r5) are 44 * preserved from get_irqnr_and_base above 45 */ 46 test_for_ipi r0, r6, r5, lr 47 movne r0, sp 48 adrne lr, 1b 49 bne do_IPI 50 51#ifdef CONFIG_LOCAL_TIMERS 52 test_for_ltirq r0, r6, r5, lr 53 movne r0, sp 54 adrne lr, 1b 55 bne do_local_timer 56#endif 57#endif 58 59 .endm 60 61/* 62 * Invalid mode handlers 63 */ 64 .macro inv_entry, reason 65 sub sp, sp, #S_FRAME_SIZE 66 stmib sp, {r1 - lr} 67 mov r1, #\reason 68 .endm 69 70__pabt_invalid: 71 inv_entry BAD_PREFETCH 72 b common_invalid 73 74__dabt_invalid: 75 inv_entry BAD_DATA 76 b common_invalid 77 78__irq_invalid: 79 inv_entry BAD_IRQ 80 b common_invalid 81 82__und_invalid: 83 inv_entry BAD_UNDEFINSTR 84 85 @ 86 @ XXX fall through to common_invalid 87 @ 88 89@ 90@ common_invalid - generic code for failed exception (re-entrant version of handlers) 91@ 92common_invalid: 93 zero_fp 94 95 ldmia r0, {r4 - r6} 96 add r0, sp, #S_PC @ here for interlock avoidance 97 mov r7, #-1 @ "" "" "" "" 98 str r4, [sp] @ save preserved r0 99 stmia r0, {r5 - r7} @ lr_<exception>, 100 @ cpsr_<exception>, "old_r0" 101 102 mov r0, sp 103 and r2, r6, #0x1f 104 b bad_mode 105 106/* 107 * SVC mode handlers 108 */ 109 .macro svc_entry 110 sub sp, sp, #S_FRAME_SIZE 111 stmib sp, {r1 - r12} 112 113 ldmia r0, {r1 - r3} 114 add r5, sp, #S_SP @ here for interlock avoidance 115 mov r4, #-1 @ "" "" "" "" 116 add r0, sp, #S_FRAME_SIZE @ "" "" "" "" 117 str r1, [sp] @ save the "real" r0 copied 118 @ from the exception stack 119 120 mov r1, lr 121 122 @ 123 @ We are now ready to fill in the remaining blanks on the stack: 124 @ 125 @ r0 - sp_svc 126 @ r1 - lr_svc 127 @ r2 - lr_<exception>, already fixed up for correct return/restart 128 @ r3 - spsr_<exception> 129 @ r4 - orig_r0 (see pt_regs definition in ptrace.h) 130 @ 131 stmia r5, {r0 - r4} 132 .endm 133 134 .align 5 135__dabt_svc: 136 svc_entry 137 138 @ 139 @ get ready to re-enable interrupts if appropriate 140 @ 141 mrs r9, cpsr 142 tst r3, #PSR_I_BIT 143 biceq r9, r9, #PSR_I_BIT 144 145 @ 146 @ Call the processor-specific abort handler: 147 @ 148 @ r2 - aborted context pc 149 @ r3 - aborted context cpsr 150 @ 151 @ The abort handler must return the aborted address in r0, and 152 @ the fault status register in r1. r9 must be preserved. 153 @ 154#ifdef MULTI_ABORT 155 ldr r4, .LCprocfns 156 mov lr, pc 157 ldr pc, [r4] 158#else 159 bl CPU_ABORT_HANDLER 160#endif 161 162 @ 163 @ set desired IRQ state, then call main handler 164 @ 165 msr cpsr_c, r9 166 mov r2, sp 167 bl do_DataAbort 168 169 @ 170 @ IRQs off again before pulling preserved data off the stack 171 @ 172 disable_irq 173 174 @ 175 @ restore SPSR and restart the instruction 176 @ 177 ldr r0, [sp, #S_PSR] 178 msr spsr_cxsf, r0 179 ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr 180 181 .align 5 182__irq_svc: 183 svc_entry 184 185#ifdef CONFIG_PREEMPT 186 get_thread_info tsk 187 ldr r8, [tsk, #TI_PREEMPT] @ get preempt count 188 add r7, r8, #1 @ increment it 189 str r7, [tsk, #TI_PREEMPT] 190#endif 191 192 irq_handler 193#ifdef CONFIG_PREEMPT 194 ldr r0, [tsk, #TI_FLAGS] @ get flags 195 tst r0, #_TIF_NEED_RESCHED 196 blne svc_preempt 197preempt_return: 198 ldr r0, [tsk, #TI_PREEMPT] @ read preempt value 199 str r8, [tsk, #TI_PREEMPT] @ restore preempt count 200 teq r0, r7 201 strne r0, [r0, -r0] @ bug() 202#endif 203 ldr r0, [sp, #S_PSR] @ irqs are already disabled 204 msr spsr_cxsf, r0 205 ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr 206 207 .ltorg 208 209#ifdef CONFIG_PREEMPT 210svc_preempt: 211 teq r8, #0 @ was preempt count = 0 212 ldreq r6, .LCirq_stat 213 movne pc, lr @ no 214 ldr r0, [r6, #4] @ local_irq_count 215 ldr r1, [r6, #8] @ local_bh_count 216 adds r0, r0, r1 217 movne pc, lr 218 mov r7, #0 @ preempt_schedule_irq 219 str r7, [tsk, #TI_PREEMPT] @ expects preempt_count == 0 2201: bl preempt_schedule_irq @ irq en/disable is done inside 221 ldr r0, [tsk, #TI_FLAGS] @ get new tasks TI_FLAGS 222 tst r0, #_TIF_NEED_RESCHED 223 beq preempt_return @ go again 224 b 1b 225#endif 226 227 .align 5 228__und_svc: 229 svc_entry 230 231 @ 232 @ call emulation code, which returns using r9 if it has emulated 233 @ the instruction, or the more conventional lr if we are to treat 234 @ this as a real undefined instruction 235 @ 236 @ r0 - instruction 237 @ 238 ldr r0, [r2, #-4] 239 adr r9, 1f 240 bl call_fpe 241 242 mov r0, sp @ struct pt_regs *regs 243 bl do_undefinstr 244 245 @ 246 @ IRQs off again before pulling preserved data off the stack 247 @ 2481: disable_irq 249 250 @ 251 @ restore SPSR and restart the instruction 252 @ 253 ldr lr, [sp, #S_PSR] @ Get SVC cpsr 254 msr spsr_cxsf, lr 255 ldmia sp, {r0 - pc}^ @ Restore SVC registers 256 257 .align 5 258__pabt_svc: 259 svc_entry 260 261 @ 262 @ re-enable interrupts if appropriate 263 @ 264 mrs r9, cpsr 265 tst r3, #PSR_I_BIT 266 biceq r9, r9, #PSR_I_BIT 267 msr cpsr_c, r9 268 269 @ 270 @ set args, then call main handler 271 @ 272 @ r0 - address of faulting instruction 273 @ r1 - pointer to registers on stack 274 @ 275 mov r0, r2 @ address (pc) 276 mov r1, sp @ regs 277 bl do_PrefetchAbort @ call abort handler 278 279 @ 280 @ IRQs off again before pulling preserved data off the stack 281 @ 282 disable_irq 283 284 @ 285 @ restore SPSR and restart the instruction 286 @ 287 ldr r0, [sp, #S_PSR] 288 msr spsr_cxsf, r0 289 ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr 290 291 .align 5 292.LCcralign: 293 .word cr_alignment 294#ifdef MULTI_ABORT 295.LCprocfns: 296 .word processor 297#endif 298.LCfp: 299 .word fp_enter 300#ifdef CONFIG_PREEMPT 301.LCirq_stat: 302 .word irq_stat 303#endif 304 305/* 306 * User mode handlers 307 */ 308 .macro usr_entry 309 sub sp, sp, #S_FRAME_SIZE 310 stmib sp, {r1 - r12} 311 312 ldmia r0, {r1 - r3} 313 add r0, sp, #S_PC @ here for interlock avoidance 314 mov r4, #-1 @ "" "" "" "" 315 316 str r1, [sp] @ save the "real" r0 copied 317 @ from the exception stack 318 319#if __LINUX_ARM_ARCH__ < 6 && !defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) 320 @ make sure our user space atomic helper is aborted 321 cmp r2, #TASK_SIZE 322 bichs r3, r3, #PSR_Z_BIT 323#endif 324 325 @ 326 @ We are now ready to fill in the remaining blanks on the stack: 327 @ 328 @ r2 - lr_<exception>, already fixed up for correct return/restart 329 @ r3 - spsr_<exception> 330 @ r4 - orig_r0 (see pt_regs definition in ptrace.h) 331 @ 332 @ Also, separately save sp_usr and lr_usr 333 @ 334 stmia r0, {r2 - r4} 335 stmdb r0, {sp, lr}^ 336 337 @ 338 @ Enable the alignment trap while in kernel mode 339 @ 340 alignment_trap r0 341 342 @ 343 @ Clear FP to mark the first stack frame 344 @ 345 zero_fp 346 .endm 347 348 .align 5 349__dabt_usr: 350 usr_entry 351 352 @ 353 @ Call the processor-specific abort handler: 354 @ 355 @ r2 - aborted context pc 356 @ r3 - aborted context cpsr 357 @ 358 @ The abort handler must return the aborted address in r0, and 359 @ the fault status register in r1. 360 @ 361#ifdef MULTI_ABORT 362 ldr r4, .LCprocfns 363 mov lr, pc 364 ldr pc, [r4] 365#else 366 bl CPU_ABORT_HANDLER 367#endif 368 369 @ 370 @ IRQs on, then call the main handler 371 @ 372 enable_irq 373 mov r2, sp 374 adr lr, ret_from_exception 375 b do_DataAbort 376 377 .align 5 378__irq_usr: 379 usr_entry 380 381 get_thread_info tsk 382#ifdef CONFIG_PREEMPT 383 ldr r8, [tsk, #TI_PREEMPT] @ get preempt count 384 add r7, r8, #1 @ increment it 385 str r7, [tsk, #TI_PREEMPT] 386#endif 387 388 irq_handler 389#ifdef CONFIG_PREEMPT 390 ldr r0, [tsk, #TI_PREEMPT] 391 str r8, [tsk, #TI_PREEMPT] 392 teq r0, r7 393 strne r0, [r0, -r0] 394#endif 395 396 mov why, #0 397 b ret_to_user 398 399 .ltorg 400 401 .align 5 402__und_usr: 403 usr_entry 404 405 tst r3, #PSR_T_BIT @ Thumb mode? 406 bne fpundefinstr @ ignore FP 407 sub r4, r2, #4 408 409 @ 410 @ fall through to the emulation code, which returns using r9 if 411 @ it has emulated the instruction, or the more conventional lr 412 @ if we are to treat this as a real undefined instruction 413 @ 414 @ r0 - instruction 415 @ 4161: ldrt r0, [r4] 417 adr r9, ret_from_exception 418 adr lr, fpundefinstr 419 @ 420 @ fallthrough to call_fpe 421 @ 422 423/* 424 * The out of line fixup for the ldrt above. 425 */ 426 .section .fixup, "ax" 4272: mov pc, r9 428 .previous 429 .section __ex_table,"a" 430 .long 1b, 2b 431 .previous 432 433/* 434 * Check whether the instruction is a co-processor instruction. 435 * If yes, we need to call the relevant co-processor handler. 436 * 437 * Note that we don't do a full check here for the co-processor 438 * instructions; all instructions with bit 27 set are well 439 * defined. The only instructions that should fault are the 440 * co-processor instructions. However, we have to watch out 441 * for the ARM6/ARM7 SWI bug. 442 * 443 * Emulators may wish to make use of the following registers: 444 * r0 = instruction opcode. 445 * r2 = PC+4 446 * r10 = this threads thread_info structure. 447 */ 448call_fpe: 449 tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27 450#if defined(CONFIG_CPU_ARM610) || defined(CONFIG_CPU_ARM710) 451 and r8, r0, #0x0f000000 @ mask out op-code bits 452 teqne r8, #0x0f000000 @ SWI (ARM6/7 bug)? 453#endif 454 moveq pc, lr 455 get_thread_info r10 @ get current thread 456 and r8, r0, #0x00000f00 @ mask out CP number 457 mov r7, #1 458 add r6, r10, #TI_USED_CP 459 strb r7, [r6, r8, lsr #8] @ set appropriate used_cp[] 460#ifdef CONFIG_IWMMXT 461 @ Test if we need to give access to iWMMXt coprocessors 462 ldr r5, [r10, #TI_FLAGS] 463 rsbs r7, r8, #(1 << 8) @ CP 0 or 1 only 464 movcss r7, r5, lsr #(TIF_USING_IWMMXT + 1) 465 bcs iwmmxt_task_enable 466#endif 467 enable_irq 468 add pc, pc, r8, lsr #6 469 mov r0, r0 470 471 mov pc, lr @ CP#0 472 b do_fpe @ CP#1 (FPE) 473 b do_fpe @ CP#2 (FPE) 474 mov pc, lr @ CP#3 475 mov pc, lr @ CP#4 476 mov pc, lr @ CP#5 477 mov pc, lr @ CP#6 478 mov pc, lr @ CP#7 479 mov pc, lr @ CP#8 480 mov pc, lr @ CP#9 481#ifdef CONFIG_VFP 482 b do_vfp @ CP#10 (VFP) 483 b do_vfp @ CP#11 (VFP) 484#else 485 mov pc, lr @ CP#10 (VFP) 486 mov pc, lr @ CP#11 (VFP) 487#endif 488 mov pc, lr @ CP#12 489 mov pc, lr @ CP#13 490 mov pc, lr @ CP#14 (Debug) 491 mov pc, lr @ CP#15 (Control) 492 493do_fpe: 494 ldr r4, .LCfp 495 add r10, r10, #TI_FPSTATE @ r10 = workspace 496 ldr pc, [r4] @ Call FP module USR entry point 497 498/* 499 * The FP module is called with these registers set: 500 * r0 = instruction 501 * r2 = PC+4 502 * r9 = normal "successful" return address 503 * r10 = FP workspace 504 * lr = unrecognised FP instruction return address 505 */ 506 507 .data 508ENTRY(fp_enter) 509 .word fpundefinstr 510 .text 511 512fpundefinstr: 513 mov r0, sp 514 adr lr, ret_from_exception 515 b do_undefinstr 516 517 .align 5 518__pabt_usr: 519 usr_entry 520 521 enable_irq @ Enable interrupts 522 mov r0, r2 @ address (pc) 523 mov r1, sp @ regs 524 bl do_PrefetchAbort @ call abort handler 525 /* fall through */ 526/* 527 * This is the return code to user mode for abort handlers 528 */ 529ENTRY(ret_from_exception) 530 get_thread_info tsk 531 mov why, #0 532 b ret_to_user 533 534/* 535 * Register switch for ARMv3 and ARMv4 processors 536 * r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info 537 * previous and next are guaranteed not to be the same. 538 */ 539ENTRY(__switch_to) 540 add ip, r1, #TI_CPU_SAVE 541 ldr r3, [r2, #TI_TP_VALUE] 542 stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack 543 ldr r6, [r2, #TI_CPU_DOMAIN]! 544#if __LINUX_ARM_ARCH__ >= 6 545#ifdef CONFIG_CPU_MPCORE 546 clrex 547#else 548 strex r5, r4, [ip] @ Clear exclusive monitor 549#endif 550#endif 551#if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT) 552 mra r4, r5, acc0 553 stmia ip, {r4, r5} 554#endif 555#if defined(CONFIG_HAS_TLS_REG) 556 mcr p15, 0, r3, c13, c0, 3 @ set TLS register 557#elif !defined(CONFIG_TLS_REG_EMUL) 558 mov r4, #0xffff0fff 559 str r3, [r4, #-15] @ TLS val at 0xffff0ff0 560#endif 561 mcr p15, 0, r6, c3, c0, 0 @ Set domain register 562#ifdef CONFIG_VFP 563 @ Always disable VFP so we can lazily save/restore the old 564 @ state. This occurs in the context of the previous thread. 565 VFPFMRX r4, FPEXC 566 bic r4, r4, #FPEXC_ENABLE 567 VFPFMXR FPEXC, r4 568#endif 569#if defined(CONFIG_IWMMXT) 570 bl iwmmxt_task_switch 571#elif defined(CONFIG_CPU_XSCALE) 572 add r4, r2, #40 @ cpu_context_save->extra 573 ldmib r4, {r4, r5} 574 mar acc0, r4, r5 575#endif 576 ldmib r2, {r4 - sl, fp, sp, pc} @ Load all regs saved previously 577 578 __INIT 579 580/* 581 * User helpers. 582 * 583 * These are segment of kernel provided user code reachable from user space 584 * at a fixed address in kernel memory. This is used to provide user space 585 * with some operations which require kernel help because of unimplemented 586 * native feature and/or instructions in many ARM CPUs. The idea is for 587 * this code to be executed directly in user mode for best efficiency but 588 * which is too intimate with the kernel counter part to be left to user 589 * libraries. In fact this code might even differ from one CPU to another 590 * depending on the available instruction set and restrictions like on 591 * SMP systems. In other words, the kernel reserves the right to change 592 * this code as needed without warning. Only the entry points and their 593 * results are guaranteed to be stable. 594 * 595 * Each segment is 32-byte aligned and will be moved to the top of the high 596 * vector page. New segments (if ever needed) must be added in front of 597 * existing ones. This mechanism should be used only for things that are 598 * really small and justified, and not be abused freely. 599 * 600 * User space is expected to implement those things inline when optimizing 601 * for a processor that has the necessary native support, but only if such 602 * resulting binaries are already to be incompatible with earlier ARM 603 * processors due to the use of unsupported instructions other than what 604 * is provided here. In other words don't make binaries unable to run on 605 * earlier processors just for the sake of not using these kernel helpers 606 * if your compiled code is not going to use the new instructions for other 607 * purpose. 608 */ 609 610 .align 5 611 .globl __kuser_helper_start 612__kuser_helper_start: 613 614/* 615 * Reference prototype: 616 * 617 * int __kernel_cmpxchg(int oldval, int newval, int *ptr) 618 * 619 * Input: 620 * 621 * r0 = oldval 622 * r1 = newval 623 * r2 = ptr 624 * lr = return address 625 * 626 * Output: 627 * 628 * r0 = returned value (zero or non-zero) 629 * C flag = set if r0 == 0, clear if r0 != 0 630 * 631 * Clobbered: 632 * 633 * r3, ip, flags 634 * 635 * Definition and user space usage example: 636 * 637 * typedef int (__kernel_cmpxchg_t)(int oldval, int newval, int *ptr); 638 * #define __kernel_cmpxchg (*(__kernel_cmpxchg_t *)0xffff0fc0) 639 * 640 * Atomically store newval in *ptr if *ptr is equal to oldval for user space. 641 * Return zero if *ptr was changed or non-zero if no exchange happened. 642 * The C flag is also set if *ptr was changed to allow for assembly 643 * optimization in the calling code. 644 * 645 * For example, a user space atomic_add implementation could look like this: 646 * 647 * #define atomic_add(ptr, val) \ 648 * ({ register unsigned int *__ptr asm("r2") = (ptr); \ 649 * register unsigned int __result asm("r1"); \ 650 * asm volatile ( \ 651 * "1: @ atomic_add\n\t" \ 652 * "ldr r0, [r2]\n\t" \ 653 * "mov r3, #0xffff0fff\n\t" \ 654 * "add lr, pc, #4\n\t" \ 655 * "add r1, r0, %2\n\t" \ 656 * "add pc, r3, #(0xffff0fc0 - 0xffff0fff)\n\t" \ 657 * "bcc 1b" \ 658 * : "=&r" (__result) \ 659 * : "r" (__ptr), "rIL" (val) \ 660 * : "r0","r3","ip","lr","cc","memory" ); \ 661 * __result; }) 662 */ 663 664__kuser_cmpxchg: @ 0xffff0fc0 665 666#if defined(CONFIG_NEEDS_SYSCALL_FOR_CMPXCHG) 667 668 /* 669 * Poor you. No fast solution possible... 670 * The kernel itself must perform the operation. 671 * A special ghost syscall is used for that (see traps.c). 672 */ 673 swi #0x9ffff0 674 mov pc, lr 675 676#elif __LINUX_ARM_ARCH__ < 6 677 678 /* 679 * Theory of operation: 680 * 681 * We set the Z flag before loading oldval. If ever an exception 682 * occurs we can not be sure the loaded value will still be the same 683 * when the exception returns, therefore the user exception handler 684 * will clear the Z flag whenever the interrupted user code was 685 * actually from the kernel address space (see the usr_entry macro). 686 * 687 * The post-increment on the str is used to prevent a race with an 688 * exception happening just after the str instruction which would 689 * clear the Z flag although the exchange was done. 690 */ 691 teq ip, ip @ set Z flag 692 ldr ip, [r2] @ load current val 693 add r3, r2, #1 @ prepare store ptr 694 teqeq ip, r0 @ compare with oldval if still allowed 695 streq r1, [r3, #-1]! @ store newval if still allowed 696 subs r0, r2, r3 @ if r2 == r3 the str occured 697 mov pc, lr 698 699#else 700 701 ldrex r3, [r2] 702 subs r3, r3, r0 703 strexeq r3, r1, [r2] 704 rsbs r0, r3, #0 705 mov pc, lr 706 707#endif 708 709 .align 5 710 711/* 712 * Reference prototype: 713 * 714 * int __kernel_get_tls(void) 715 * 716 * Input: 717 * 718 * lr = return address 719 * 720 * Output: 721 * 722 * r0 = TLS value 723 * 724 * Clobbered: 725 * 726 * the Z flag might be lost 727 * 728 * Definition and user space usage example: 729 * 730 * typedef int (__kernel_get_tls_t)(void); 731 * #define __kernel_get_tls (*(__kernel_get_tls_t *)0xffff0fe0) 732 * 733 * Get the TLS value as previously set via the __ARM_NR_set_tls syscall. 734 * 735 * This could be used as follows: 736 * 737 * #define __kernel_get_tls() \ 738 * ({ register unsigned int __val asm("r0"); \ 739 * asm( "mov r0, #0xffff0fff; mov lr, pc; sub pc, r0, #31" \ 740 * : "=r" (__val) : : "lr","cc" ); \ 741 * __val; }) 742 */ 743 744__kuser_get_tls: @ 0xffff0fe0 745 746#if !defined(CONFIG_HAS_TLS_REG) && !defined(CONFIG_TLS_REG_EMUL) 747 748 ldr r0, [pc, #(16 - 8)] @ TLS stored at 0xffff0ff0 749 mov pc, lr 750 751#else 752 753 mrc p15, 0, r0, c13, c0, 3 @ read TLS register 754 mov pc, lr 755 756#endif 757 758 .rep 5 759 .word 0 @ pad up to __kuser_helper_version 760 .endr 761 762/* 763 * Reference declaration: 764 * 765 * extern unsigned int __kernel_helper_version; 766 * 767 * Definition and user space usage example: 768 * 769 * #define __kernel_helper_version (*(unsigned int *)0xffff0ffc) 770 * 771 * User space may read this to determine the curent number of helpers 772 * available. 773 */ 774 775__kuser_helper_version: @ 0xffff0ffc 776 .word ((__kuser_helper_end - __kuser_helper_start) >> 5) 777 778 .globl __kuser_helper_end 779__kuser_helper_end: 780 781 782/* 783 * Vector stubs. 784 * 785 * This code is copied to 0xffff0200 so we can use branches in the 786 * vectors, rather than ldr's. Note that this code must not 787 * exceed 0x300 bytes. 788 * 789 * Common stub entry macro: 790 * Enter in IRQ mode, spsr = SVC/USR CPSR, lr = SVC/USR PC 791 * 792 * SP points to a minimal amount of processor-private memory, the address 793 * of which is copied into r0 for the mode specific abort handler. 794 */ 795 .macro vector_stub, name, mode, correction=0 796 .align 5 797 798vector_\name: 799 .if \correction 800 sub lr, lr, #\correction 801 .endif 802 803 @ 804 @ Save r0, lr_<exception> (parent PC) and spsr_<exception> 805 @ (parent CPSR) 806 @ 807 stmia sp, {r0, lr} @ save r0, lr 808 mrs lr, spsr 809 str lr, [sp, #8] @ save spsr 810 811 @ 812 @ Prepare for SVC32 mode. IRQs remain disabled. 813 @ 814 mrs r0, cpsr 815 eor r0, r0, #(\mode ^ SVC_MODE) 816 msr spsr_cxsf, r0 817 818 @ 819 @ the branch table must immediately follow this code 820 @ 821 and lr, lr, #0x0f 822 mov r0, sp 823 ldr lr, [pc, lr, lsl #2] 824 movs pc, lr @ branch to handler in SVC mode 825 .endm 826 827 .globl __stubs_start 828__stubs_start: 829/* 830 * Interrupt dispatcher 831 */ 832 vector_stub irq, IRQ_MODE, 4 833 834 .long __irq_usr @ 0 (USR_26 / USR_32) 835 .long __irq_invalid @ 1 (FIQ_26 / FIQ_32) 836 .long __irq_invalid @ 2 (IRQ_26 / IRQ_32) 837 .long __irq_svc @ 3 (SVC_26 / SVC_32) 838 .long __irq_invalid @ 4 839 .long __irq_invalid @ 5 840 .long __irq_invalid @ 6 841 .long __irq_invalid @ 7 842 .long __irq_invalid @ 8 843 .long __irq_invalid @ 9 844 .long __irq_invalid @ a 845 .long __irq_invalid @ b 846 .long __irq_invalid @ c 847 .long __irq_invalid @ d 848 .long __irq_invalid @ e 849 .long __irq_invalid @ f 850 851/* 852 * Data abort dispatcher 853 * Enter in ABT mode, spsr = USR CPSR, lr = USR PC 854 */ 855 vector_stub dabt, ABT_MODE, 8 856 857 .long __dabt_usr @ 0 (USR_26 / USR_32) 858 .long __dabt_invalid @ 1 (FIQ_26 / FIQ_32) 859 .long __dabt_invalid @ 2 (IRQ_26 / IRQ_32) 860 .long __dabt_svc @ 3 (SVC_26 / SVC_32) 861 .long __dabt_invalid @ 4 862 .long __dabt_invalid @ 5 863 .long __dabt_invalid @ 6 864 .long __dabt_invalid @ 7 865 .long __dabt_invalid @ 8 866 .long __dabt_invalid @ 9 867 .long __dabt_invalid @ a 868 .long __dabt_invalid @ b 869 .long __dabt_invalid @ c 870 .long __dabt_invalid @ d 871 .long __dabt_invalid @ e 872 .long __dabt_invalid @ f 873 874/* 875 * Prefetch abort dispatcher 876 * Enter in ABT mode, spsr = USR CPSR, lr = USR PC 877 */ 878 vector_stub pabt, ABT_MODE, 4 879 880 .long __pabt_usr @ 0 (USR_26 / USR_32) 881 .long __pabt_invalid @ 1 (FIQ_26 / FIQ_32) 882 .long __pabt_invalid @ 2 (IRQ_26 / IRQ_32) 883 .long __pabt_svc @ 3 (SVC_26 / SVC_32) 884 .long __pabt_invalid @ 4 885 .long __pabt_invalid @ 5 886 .long __pabt_invalid @ 6 887 .long __pabt_invalid @ 7 888 .long __pabt_invalid @ 8 889 .long __pabt_invalid @ 9 890 .long __pabt_invalid @ a 891 .long __pabt_invalid @ b 892 .long __pabt_invalid @ c 893 .long __pabt_invalid @ d 894 .long __pabt_invalid @ e 895 .long __pabt_invalid @ f 896 897/* 898 * Undef instr entry dispatcher 899 * Enter in UND mode, spsr = SVC/USR CPSR, lr = SVC/USR PC 900 */ 901 vector_stub und, UND_MODE 902 903 .long __und_usr @ 0 (USR_26 / USR_32) 904 .long __und_invalid @ 1 (FIQ_26 / FIQ_32) 905 .long __und_invalid @ 2 (IRQ_26 / IRQ_32) 906 .long __und_svc @ 3 (SVC_26 / SVC_32) 907 .long __und_invalid @ 4 908 .long __und_invalid @ 5 909 .long __und_invalid @ 6 910 .long __und_invalid @ 7 911 .long __und_invalid @ 8 912 .long __und_invalid @ 9 913 .long __und_invalid @ a 914 .long __und_invalid @ b 915 .long __und_invalid @ c 916 .long __und_invalid @ d 917 .long __und_invalid @ e 918 .long __und_invalid @ f 919 920 .align 5 921 922/*============================================================================= 923 * Undefined FIQs 924 *----------------------------------------------------------------------------- 925 * Enter in FIQ mode, spsr = ANY CPSR, lr = ANY PC 926 * MUST PRESERVE SVC SPSR, but need to switch to SVC mode to show our msg. 927 * Basically to switch modes, we *HAVE* to clobber one register... brain 928 * damage alert! I don't think that we can execute any code in here in any 929 * other mode than FIQ... Ok you can switch to another mode, but you can't 930 * get out of that mode without clobbering one register. 931 */ 932vector_fiq: 933 disable_fiq 934 subs pc, lr, #4 935 936/*============================================================================= 937 * Address exception handler 938 *----------------------------------------------------------------------------- 939 * These aren't too critical. 940 * (they're not supposed to happen, and won't happen in 32-bit data mode). 941 */ 942 943vector_addrexcptn: 944 b vector_addrexcptn 945 946/* 947 * We group all the following data together to optimise 948 * for CPUs with separate I & D caches. 949 */ 950 .align 5 951 952.LCvswi: 953 .word vector_swi 954 955 .globl __stubs_end 956__stubs_end: 957 958 .equ stubs_offset, __vectors_start + 0x200 - __stubs_start 959 960 .globl __vectors_start 961__vectors_start: 962 swi SYS_ERROR0 963 b vector_und + stubs_offset 964 ldr pc, .LCvswi + stubs_offset 965 b vector_pabt + stubs_offset 966 b vector_dabt + stubs_offset 967 b vector_addrexcptn + stubs_offset 968 b vector_irq + stubs_offset 969 b vector_fiq + stubs_offset 970 971 .globl __vectors_end 972__vectors_end: 973 974 .data 975 976 .globl cr_alignment 977 .globl cr_no_alignment 978cr_alignment: 979 .space 4 980cr_no_alignment: 981 .space 4 982