@@ -446,106 +446,32 @@ ENDPROC(__irq_usr)
446446__und_usr:
447447 usr_entry uaccess= 0
448448
449- mov r2 , r4
450- mov r3 , r5
451-
452- @ r2 = regs - >ARM_pc , which is either 2 or 4 bytes ahead of the
453- @ faulting instruction depending on Thumb mode.
454- @ r3 = regs - >ARM_cpsr
455- @
456- @ The emulation code returns using r9 if it has emulated the
457- @ instruction , or the more conventional lr if we are to tre at
458- @ this as a real undefined instruction
459- @
460- badr r9 , ret_from_exception
461-
462449 @ IRQs must be enabled before attempting to read the instruction from
463450 @ user space since th at could cause a page/translation fault if the
464451 @ page table was modified by another CPU .
465452 enable_irq
466453
467- tst r3 , #PSR_T_BIT @ Thumb mode?
468- bne __und_usr_thumb
469- sub r4 , r2 , # 4 @ ARM instr at LR - 4
470- 1 : ldrt r0 , [ r4 ]
471- ARM_BE8(rev r0 , r0) @ little endian instruction
472-
454+ tst r5 , #PSR_T_BIT @ Thumb mode?
455+ mov r1 , # 2 @ set insn size to 2 for Thumb
456+ bne 0f @ handle as Thumb undef exception
457+ adr r9 , ret_from_exception
458+ bl call_fpe @ returns via R9 on success
459+ mov r1 , # 4 @ set insn size to 4 for ARM
460+ 0 : mov r0 , sp
473461 uaccess_disable ip
474-
475- @ r0 = 32 - bit ARM instruction which caused the exception
476- @ r2 = PC value for the following instruction (:= regs - >ARM_pc)
477- @ r4 = PC value for the faulting instruction
478- @ lr = 32 - bit undefined instruction function
479- badr lr , __und_usr_fault_32
480- b call_fpe
481-
482- __und_usr_thumb:
483- @ Thumb instruction
484- sub r4 , r2 , # 2 @ First half of thumb instr at LR - 2
485- #if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7
486- / *
487- * Thumb - 2 instruction handling. Note th at because pre - v6 and >= v6 platforms
488- * can never be supported in a single kernel , this code is not applicable at
489- * all when __LINUX_ARM_ARCH__ < 6 . This allows simplifying assumptions to be
490- * made about .arch directives.
491- * /
492- #if __LINUX_ARM_ARCH__ < 7
493- / * If the target CPU may not be Thumb - 2 - capable , a run - time check is needed: * /
494- ldr_va r5 , cpu_architecture
495- cmp r5 , #CPU_ARCH_ARMv7
496- blo __und_usr_fault_16 @ 16bit undefined instruction
497- / *
498- * The following code won't get run unless the running CPU really is v7 , so
499- * coding round the lack of ldrht on older arches is pointless. Temporarily
500- * override the assembler target arch with the minimum required instead:
501- * /
502- .arch armv6t2
503- #endif
504- 2 : ldrht r5 , [ r4 ]
505- ARM_BE8(rev16 r5 , r5) @ little endian instruction
506- cmp r5 , # 0xe800 @ 32bit instruction if xx != 0
507- blo __und_usr_fault_16_pan @ 16bit undefined instruction
508- 3 : ldrht r0 , [ r2 ]
509- ARM_BE8(rev16 r0 , r0) @ little endian instruction
510- uaccess_disable ip
511- add r2 , r2 , # 2 @ r2 is PC + 2 , make it PC + 4
512- str r2 , [ sp , #S_PC ] @ it's a 2x16bit instr , update
513- orr r0 , r0 , r5 , lsl # 16
514- badr lr , __und_usr_fault_32
515- @ r0 = the two 16 - bit Thumb instructions which caused the exception
516- @ r2 = PC value for the following Thumb instruction (:= regs - >ARM_pc)
517- @ r4 = PC value for the first 16 - bit Thumb instruction
518- @ lr = 32bit undefined instruction function
519-
520- #if __LINUX_ARM_ARCH__ < 7
521- / * If the target arch was overridden , change it back: * /
522- #ifdef CONFIG_CPU_32v6K
523- .arch armv6k
524- #else
525- .arch armv6
526- #endif
527- #endif / * __LINUX_ARM_ARCH__ < 7 * /
528- #else / * !(CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7) * /
529- b __und_usr_fault_16
530- #endif
462+ bl __und_fault
463+ b ret_from_exception
531464 UNWIND(.fnend)
532465ENDPROC(__und_usr)
533466
534467/ *
535- * The out of line fixup for the ldrt instructions above .
468+ * The out of line fixup for the ldrt instruction below .
536469 * /
537470 .pushsection .text.fixup , "ax"
538471 . align 2
5394724 : str r4 , [ sp , #S_PC ] @ retry current instruction
540473 ret r9
541474 .popsection
542- .pushsection __ex_table , "a"
543- .long 1b , 4b
544- #if CONFIG_ARM_THUMB && __LINUX_ARM_ARCH__ >= 6 && CONFIG_CPU_V7
545- .long 2b , 4b
546- .long 3b , 4b
547- #endif
548- .popsection
549475
550476/ *
551477 * Check whether the instruction is a co - processor instruction.
@@ -558,20 +484,22 @@ ENDPROC(__und_usr)
558484 * for the ARM6/ARM7 SWI bug.
559485 *
560486 * Emulators may wish to make use of the following registers:
561- * r0 = instruction opcode ( 32 - bit ARM or two 16 - bit Thumb)
562- * r2 = PC value to resume execution after successful emulation
487+ * r4 = PC value to resume execution after successful emulation
563488 * r9 = normal "successful" return address
564489 * r10 = this threads thread_info structure
565490 * lr = unrecognised instruction return address
566491 * IRQs enabled , FIQs enabled.
567492 * /
568- @
569- @ Fall - through from Thumb - 2 __und_usr
570- @
571493call_fpe:
494+ mov r2 , r4
495+ sub r4 , r4 , # 4 @ ARM instruction at user PC - 4
496+ USERL( 4b , ldrt r0 , [ r4 ] ) @ load opcode from user space
497+ ARM_BE8(rev r0 , r0) @ little endian instruction
498+
499+ uaccess_disable ip
500+
572501 get_thread_info r10 @ get current thread
573502 tst r0 , # 0x08000000 @ only CDP/CPRT/LDC/ STC have bit 27
574- tstne r0 , # 0x04000000 @ bit 26 set on both ARM and Thumb - 2
575503 reteq lr
576504 and r8 , r0 , # 0x00000f00 @ mask out CP number
577505#ifdef CONFIG_IWMMXT
@@ -626,19 +554,6 @@ ENTRY(no_fp)
626554 ret lr
627555ENDPROC(no_fp)
628556
629- __und_usr_fault_32:
630- mov r1 , # 4
631- b 1f
632- __und_usr_fault_16_pan:
633- uaccess_disable ip
634- __und_usr_fault_16:
635- mov r1 , # 2
636- 1 : mov r0 , sp
637- badr lr , ret_from_exception
638- b __und_fault
639- ENDPROC(__und_usr_fault_32)
640- ENDPROC(__und_usr_fault_16)
641-
642557 . align 5
643558__pabt_usr:
644559 usr_entry
0 commit comments