Loading arch/arm/Kconfig +1 −1 Original line number Diff line number Diff line Loading @@ -244,7 +244,7 @@ config ARM_PATCH_PHYS_VIRT kernel in system memory. This can only be used with non-XIP MMU kernels where the base of physical memory is at a 16MB boundary. of physical memory is at a 2 MiB boundary. Only disable this option if you know that you do not require this feature (eg, building a kernel for a single machine) and Loading arch/arm/boot/compressed/head.S +3 −15 Original line number Diff line number Diff line Loading @@ -468,15 +468,10 @@ dtb_check_done: /* * Compute the address of the hyp vectors after relocation. * This requires some arithmetic since we cannot directly * reference __hyp_stub_vectors in a PC-relative way. * Call __hyp_set_vectors with the new address so that we * can HVC again after the copy. */ 0: adr r0, 0b movw r1, #:lower16:__hyp_stub_vectors - 0b movt r1, #:upper16:__hyp_stub_vectors - 0b add r0, r0, r1 adr_l r0, __hyp_stub_vectors sub r0, r0, r5 add r0, r0, r10 bl __hyp_set_vectors Loading Loading @@ -627,17 +622,11 @@ not_relocated: mov r0, #0 cmp r0, #HYP_MODE @ if not booted in HYP mode... bne __enter_kernel @ boot kernel directly adr r12, .L__hyp_reentry_vectors_offset ldr r0, [r12] add r0, r0, r12 adr_l r0, __hyp_reentry_vectors bl __hyp_set_vectors __HVC(0) @ otherwise bounce to hyp mode b . @ should never be reached .align 2 .L__hyp_reentry_vectors_offset: .long __hyp_reentry_vectors - . #else b __enter_kernel #endif Loading Loading @@ -1440,8 +1429,7 @@ ENTRY(efi_enter_kernel) mov r4, r0 @ preserve image base mov r8, r1 @ preserve DT pointer ARM( adrl r0, call_cache_fn ) THUMB( adr r0, call_cache_fn ) adr_l r0, call_cache_fn adr r1, 0f @ clean the region of code we bl cache_clean_flush @ may run with the MMU off Loading arch/arm/include/asm/assembler.h +86 −2 Original line number Diff line number Diff line Loading @@ -259,7 +259,7 @@ */ #define ALT_UP(instr...) \ .pushsection ".alt.smp.init", "a" ;\ .long 9998b ;\ .long 9998b - . ;\ 9997: instr ;\ .if . - 9997b == 2 ;\ nop ;\ Loading @@ -270,7 +270,7 @@ .popsection #define ALT_UP_B(label) \ .pushsection ".alt.smp.init", "a" ;\ .long 9998b ;\ .long 9998b - . ;\ W(b) . + (label - 9998b) ;\ .popsection #else Loading Loading @@ -494,4 +494,88 @@ THUMB( orr \reg , \reg , #PSR_T_BIT ) #define _ASM_NOKPROBE(entry) #endif .macro __adldst_l, op, reg, sym, tmp, c .if __LINUX_ARM_ARCH__ < 7 ldr\c \tmp, .La\@ .subsection 1 .align 2 .La\@: .long \sym - .Lpc\@ .previous .else .ifnb \c THUMB( ittt \c ) .endif movw\c \tmp, #:lower16:\sym - .Lpc\@ movt\c \tmp, #:upper16:\sym - .Lpc\@ .endif #ifndef CONFIG_THUMB2_KERNEL .set .Lpc\@, . + 8 // PC bias .ifc \op, add add\c \reg, \tmp, pc .else \op\c \reg, [pc, \tmp] .endif #else .Lb\@: add\c \tmp, \tmp, pc /* * In Thumb-2 builds, the PC bias depends on whether we are currently * emitting into a .arm or a .thumb section. The size of the add opcode * above will be 2 bytes when emitting in Thumb mode and 4 bytes when * emitting in ARM mode, so let's use this to account for the bias. */ .set .Lpc\@, . + (. - .Lb\@) .ifnc \op, add \op\c \reg, [\tmp] .endif #endif .endm /* * mov_l - move a constant value or [relocated] address into a register */ .macro mov_l, dst:req, imm:req .if __LINUX_ARM_ARCH__ < 7 ldr \dst, =\imm .else movw \dst, #:lower16:\imm movt \dst, #:upper16:\imm .endif .endm /* * adr_l - adr pseudo-op with unlimited range * * @dst: destination register * @sym: name of the symbol * @cond: conditional opcode suffix */ .macro adr_l, dst:req, sym:req, cond __adldst_l add, \dst, \sym, \dst, \cond .endm /* * ldr_l - ldr <literal> pseudo-op with unlimited range * * @dst: destination register * @sym: name of the symbol * @cond: conditional opcode suffix */ .macro ldr_l, dst:req, sym:req, cond __adldst_l ldr, \dst, \sym, \dst, \cond .endm /* * str_l - str <literal> pseudo-op with unlimited range * * @src: source register * @sym: name of the symbol * @tmp: mandatory scratch register * @cond: conditional opcode suffix */ .macro str_l, src:req, sym:req, tmp:req, cond __adldst_l str, \src, \sym, \tmp, \cond .endm #endif /* __ASM_ASSEMBLER_H__ */ arch/arm/include/asm/elf.h +5 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ typedef struct user_fp elf_fpregset_t; #define R_ARM_NONE 0 #define R_ARM_PC24 1 #define R_ARM_ABS32 2 #define R_ARM_REL32 3 #define R_ARM_CALL 28 #define R_ARM_JUMP24 29 #define R_ARM_TARGET1 38 Loading @@ -58,11 +59,15 @@ typedef struct user_fp elf_fpregset_t; #define R_ARM_PREL31 42 #define R_ARM_MOVW_ABS_NC 43 #define R_ARM_MOVT_ABS 44 #define R_ARM_MOVW_PREL_NC 45 #define R_ARM_MOVT_PREL 46 #define R_ARM_THM_CALL 10 #define R_ARM_THM_JUMP24 30 #define R_ARM_THM_MOVW_ABS_NC 47 #define R_ARM_THM_MOVT_ABS 48 #define R_ARM_THM_MOVW_PREL_NC 49 #define R_ARM_THM_MOVT_PREL 50 /* * These are used to set parameters in the core dumps. Loading arch/arm/include/asm/memory.h +40 −17 Original line number Diff line number Diff line Loading @@ -183,6 +183,7 @@ extern unsigned long vectors_base; * so that all we need to do is modify the 8-bit constant field. */ #define __PV_BITS_31_24 0x81000000 #define __PV_BITS_23_16 0x810000 #define __PV_BITS_7_0 0x81 extern unsigned long __pv_phys_pfn_offset; Loading @@ -193,43 +194,65 @@ extern const void *__pv_table_begin, *__pv_table_end; #define PHYS_OFFSET ((phys_addr_t)__pv_phys_pfn_offset << PAGE_SHIFT) #define PHYS_PFN_OFFSET (__pv_phys_pfn_offset) #define __pv_stub(from,to,instr,type) \ #ifndef CONFIG_THUMB2_KERNEL #define __pv_stub(from,to,instr) \ __asm__("@ __pv_stub\n" \ "1: " instr " %0, %1, %2\n" \ "2: " instr " %0, %0, %3\n" \ " .pushsection .pv_table,\"a\"\n" \ " .long 1b\n" \ " .long 1b - ., 2b - .\n" \ " .popsection\n" \ : "=r" (to) \ : "r" (from), "I" (type)) : "r" (from), "I" (__PV_BITS_31_24), \ "I"(__PV_BITS_23_16)) #define __pv_add_carry_stub(x, y) \ __asm__("@ __pv_add_carry_stub\n" \ "0: movw %R0, #0\n" \ " adds %Q0, %1, %R0, lsl #20\n" \ "1: mov %R0, %2\n" \ " adc %R0, %R0, #0\n" \ " .pushsection .pv_table,\"a\"\n" \ " .long 0b - ., 1b - .\n" \ " .popsection\n" \ : "=&r" (y) \ : "r" (x), "I" (__PV_BITS_7_0) \ : "cc") #define __pv_stub_mov_hi(t) \ __asm__ volatile("@ __pv_stub_mov\n" \ "1: mov %R0, %1\n" \ #else #define __pv_stub(from,to,instr) \ __asm__("@ __pv_stub\n" \ "0: movw %0, #0\n" \ " lsl %0, #21\n" \ " " instr " %0, %1, %0\n" \ " .pushsection .pv_table,\"a\"\n" \ " .long 1b\n" \ " .long 0b - .\n" \ " .popsection\n" \ : "=r" (t) \ : "I" (__PV_BITS_7_0)) : "=&r" (to) \ : "r" (from)) #define __pv_add_carry_stub(x, y) \ __asm__ volatile("@ __pv_add_carry_stub\n" \ "1: adds %Q0, %1, %2\n" \ __asm__("@ __pv_add_carry_stub\n" \ "0: movw %R0, #0\n" \ " lsls %R0, #21\n" \ " adds %Q0, %1, %R0\n" \ "1: mvn %R0, #0\n" \ " adc %R0, %R0, #0\n" \ " .pushsection .pv_table,\"a\"\n" \ " .long 1b\n" \ " .long 0b - ., 1b - .\n" \ " .popsection\n" \ : "+r" (y) \ : "r" (x), "I" (__PV_BITS_31_24) \ : "=&r" (y) \ : "r" (x) \ : "cc") #endif static inline phys_addr_t __virt_to_phys_nodebug(unsigned long x) { phys_addr_t t; if (sizeof(phys_addr_t) == 4) { __pv_stub(x, t, "add", __PV_BITS_31_24); __pv_stub(x, t, "add"); } else { __pv_stub_mov_hi(t); __pv_add_carry_stub(x, t); } return t; Loading @@ -245,7 +268,7 @@ static inline unsigned long __phys_to_virt(phys_addr_t x) * assembler expression receives 32 bit argument * in place where 'r' 32 bit operand is expected. */ __pv_stub((unsigned long) x, t, "sub", __PV_BITS_31_24); __pv_stub((unsigned long) x, t, "sub"); return t; } Loading Loading
arch/arm/Kconfig +1 −1 Original line number Diff line number Diff line Loading @@ -244,7 +244,7 @@ config ARM_PATCH_PHYS_VIRT kernel in system memory. This can only be used with non-XIP MMU kernels where the base of physical memory is at a 16MB boundary. of physical memory is at a 2 MiB boundary. Only disable this option if you know that you do not require this feature (eg, building a kernel for a single machine) and Loading
arch/arm/boot/compressed/head.S +3 −15 Original line number Diff line number Diff line Loading @@ -468,15 +468,10 @@ dtb_check_done: /* * Compute the address of the hyp vectors after relocation. * This requires some arithmetic since we cannot directly * reference __hyp_stub_vectors in a PC-relative way. * Call __hyp_set_vectors with the new address so that we * can HVC again after the copy. */ 0: adr r0, 0b movw r1, #:lower16:__hyp_stub_vectors - 0b movt r1, #:upper16:__hyp_stub_vectors - 0b add r0, r0, r1 adr_l r0, __hyp_stub_vectors sub r0, r0, r5 add r0, r0, r10 bl __hyp_set_vectors Loading Loading @@ -627,17 +622,11 @@ not_relocated: mov r0, #0 cmp r0, #HYP_MODE @ if not booted in HYP mode... bne __enter_kernel @ boot kernel directly adr r12, .L__hyp_reentry_vectors_offset ldr r0, [r12] add r0, r0, r12 adr_l r0, __hyp_reentry_vectors bl __hyp_set_vectors __HVC(0) @ otherwise bounce to hyp mode b . @ should never be reached .align 2 .L__hyp_reentry_vectors_offset: .long __hyp_reentry_vectors - . #else b __enter_kernel #endif Loading Loading @@ -1440,8 +1429,7 @@ ENTRY(efi_enter_kernel) mov r4, r0 @ preserve image base mov r8, r1 @ preserve DT pointer ARM( adrl r0, call_cache_fn ) THUMB( adr r0, call_cache_fn ) adr_l r0, call_cache_fn adr r1, 0f @ clean the region of code we bl cache_clean_flush @ may run with the MMU off Loading
arch/arm/include/asm/assembler.h +86 −2 Original line number Diff line number Diff line Loading @@ -259,7 +259,7 @@ */ #define ALT_UP(instr...) \ .pushsection ".alt.smp.init", "a" ;\ .long 9998b ;\ .long 9998b - . ;\ 9997: instr ;\ .if . - 9997b == 2 ;\ nop ;\ Loading @@ -270,7 +270,7 @@ .popsection #define ALT_UP_B(label) \ .pushsection ".alt.smp.init", "a" ;\ .long 9998b ;\ .long 9998b - . ;\ W(b) . + (label - 9998b) ;\ .popsection #else Loading Loading @@ -494,4 +494,88 @@ THUMB( orr \reg , \reg , #PSR_T_BIT ) #define _ASM_NOKPROBE(entry) #endif .macro __adldst_l, op, reg, sym, tmp, c .if __LINUX_ARM_ARCH__ < 7 ldr\c \tmp, .La\@ .subsection 1 .align 2 .La\@: .long \sym - .Lpc\@ .previous .else .ifnb \c THUMB( ittt \c ) .endif movw\c \tmp, #:lower16:\sym - .Lpc\@ movt\c \tmp, #:upper16:\sym - .Lpc\@ .endif #ifndef CONFIG_THUMB2_KERNEL .set .Lpc\@, . + 8 // PC bias .ifc \op, add add\c \reg, \tmp, pc .else \op\c \reg, [pc, \tmp] .endif #else .Lb\@: add\c \tmp, \tmp, pc /* * In Thumb-2 builds, the PC bias depends on whether we are currently * emitting into a .arm or a .thumb section. The size of the add opcode * above will be 2 bytes when emitting in Thumb mode and 4 bytes when * emitting in ARM mode, so let's use this to account for the bias. */ .set .Lpc\@, . + (. - .Lb\@) .ifnc \op, add \op\c \reg, [\tmp] .endif #endif .endm /* * mov_l - move a constant value or [relocated] address into a register */ .macro mov_l, dst:req, imm:req .if __LINUX_ARM_ARCH__ < 7 ldr \dst, =\imm .else movw \dst, #:lower16:\imm movt \dst, #:upper16:\imm .endif .endm /* * adr_l - adr pseudo-op with unlimited range * * @dst: destination register * @sym: name of the symbol * @cond: conditional opcode suffix */ .macro adr_l, dst:req, sym:req, cond __adldst_l add, \dst, \sym, \dst, \cond .endm /* * ldr_l - ldr <literal> pseudo-op with unlimited range * * @dst: destination register * @sym: name of the symbol * @cond: conditional opcode suffix */ .macro ldr_l, dst:req, sym:req, cond __adldst_l ldr, \dst, \sym, \dst, \cond .endm /* * str_l - str <literal> pseudo-op with unlimited range * * @src: source register * @sym: name of the symbol * @tmp: mandatory scratch register * @cond: conditional opcode suffix */ .macro str_l, src:req, sym:req, tmp:req, cond __adldst_l str, \src, \sym, \tmp, \cond .endm #endif /* __ASM_ASSEMBLER_H__ */
arch/arm/include/asm/elf.h +5 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ typedef struct user_fp elf_fpregset_t; #define R_ARM_NONE 0 #define R_ARM_PC24 1 #define R_ARM_ABS32 2 #define R_ARM_REL32 3 #define R_ARM_CALL 28 #define R_ARM_JUMP24 29 #define R_ARM_TARGET1 38 Loading @@ -58,11 +59,15 @@ typedef struct user_fp elf_fpregset_t; #define R_ARM_PREL31 42 #define R_ARM_MOVW_ABS_NC 43 #define R_ARM_MOVT_ABS 44 #define R_ARM_MOVW_PREL_NC 45 #define R_ARM_MOVT_PREL 46 #define R_ARM_THM_CALL 10 #define R_ARM_THM_JUMP24 30 #define R_ARM_THM_MOVW_ABS_NC 47 #define R_ARM_THM_MOVT_ABS 48 #define R_ARM_THM_MOVW_PREL_NC 49 #define R_ARM_THM_MOVT_PREL 50 /* * These are used to set parameters in the core dumps. Loading
arch/arm/include/asm/memory.h +40 −17 Original line number Diff line number Diff line Loading @@ -183,6 +183,7 @@ extern unsigned long vectors_base; * so that all we need to do is modify the 8-bit constant field. */ #define __PV_BITS_31_24 0x81000000 #define __PV_BITS_23_16 0x810000 #define __PV_BITS_7_0 0x81 extern unsigned long __pv_phys_pfn_offset; Loading @@ -193,43 +194,65 @@ extern const void *__pv_table_begin, *__pv_table_end; #define PHYS_OFFSET ((phys_addr_t)__pv_phys_pfn_offset << PAGE_SHIFT) #define PHYS_PFN_OFFSET (__pv_phys_pfn_offset) #define __pv_stub(from,to,instr,type) \ #ifndef CONFIG_THUMB2_KERNEL #define __pv_stub(from,to,instr) \ __asm__("@ __pv_stub\n" \ "1: " instr " %0, %1, %2\n" \ "2: " instr " %0, %0, %3\n" \ " .pushsection .pv_table,\"a\"\n" \ " .long 1b\n" \ " .long 1b - ., 2b - .\n" \ " .popsection\n" \ : "=r" (to) \ : "r" (from), "I" (type)) : "r" (from), "I" (__PV_BITS_31_24), \ "I"(__PV_BITS_23_16)) #define __pv_add_carry_stub(x, y) \ __asm__("@ __pv_add_carry_stub\n" \ "0: movw %R0, #0\n" \ " adds %Q0, %1, %R0, lsl #20\n" \ "1: mov %R0, %2\n" \ " adc %R0, %R0, #0\n" \ " .pushsection .pv_table,\"a\"\n" \ " .long 0b - ., 1b - .\n" \ " .popsection\n" \ : "=&r" (y) \ : "r" (x), "I" (__PV_BITS_7_0) \ : "cc") #define __pv_stub_mov_hi(t) \ __asm__ volatile("@ __pv_stub_mov\n" \ "1: mov %R0, %1\n" \ #else #define __pv_stub(from,to,instr) \ __asm__("@ __pv_stub\n" \ "0: movw %0, #0\n" \ " lsl %0, #21\n" \ " " instr " %0, %1, %0\n" \ " .pushsection .pv_table,\"a\"\n" \ " .long 1b\n" \ " .long 0b - .\n" \ " .popsection\n" \ : "=r" (t) \ : "I" (__PV_BITS_7_0)) : "=&r" (to) \ : "r" (from)) #define __pv_add_carry_stub(x, y) \ __asm__ volatile("@ __pv_add_carry_stub\n" \ "1: adds %Q0, %1, %2\n" \ __asm__("@ __pv_add_carry_stub\n" \ "0: movw %R0, #0\n" \ " lsls %R0, #21\n" \ " adds %Q0, %1, %R0\n" \ "1: mvn %R0, #0\n" \ " adc %R0, %R0, #0\n" \ " .pushsection .pv_table,\"a\"\n" \ " .long 1b\n" \ " .long 0b - ., 1b - .\n" \ " .popsection\n" \ : "+r" (y) \ : "r" (x), "I" (__PV_BITS_31_24) \ : "=&r" (y) \ : "r" (x) \ : "cc") #endif static inline phys_addr_t __virt_to_phys_nodebug(unsigned long x) { phys_addr_t t; if (sizeof(phys_addr_t) == 4) { __pv_stub(x, t, "add", __PV_BITS_31_24); __pv_stub(x, t, "add"); } else { __pv_stub_mov_hi(t); __pv_add_carry_stub(x, t); } return t; Loading @@ -245,7 +268,7 @@ static inline unsigned long __phys_to_virt(phys_addr_t x) * assembler expression receives 32 bit argument * in place where 'r' 32 bit operand is expected. */ __pv_stub((unsigned long) x, t, "sub", __PV_BITS_31_24); __pv_stub((unsigned long) x, t, "sub"); return t; } Loading