powerpc/64: Build with PC-Relative addressing
Subsystems (7)
Nicholas Piggin
reviewercover powerpc/64: Build with PC-Relative addressing
This won't see a lot of real use until POWER10 is the oldest supported CPU for distros, but being as we're quite a unique user of toolchain I'd like to start ironing things out earlier rather than later. I'm making a list of observations here, https://github.com/linuxppc/issues/issues/455
and will take them to toolchan developers after the kernel work is a bit further along.
The series is working pretty well for me on pseries and powernv systems. Since RFC I've tidied things a bit and fixed the remaining hacks and known issues, mainly in the module loader.
The first two patches are already posted to the list, boot code changes that aren't too interesting to toolchain.
Thanks,
Nick
Nicholas Piggin (6):
powerpc/64: Move initial base and TOC pointer calculation powerpc/64s: Run at the kernel virtual address earlier in boot powerpc/64: Add support to build with prefixed instructions
powerpc: add CFUNC assembly label annotation powerpc/64: vmlinux support building with PCREL addresing powerpc/64: modules support building with PCREL addresing
arch/powerpc/Kconfig | 6 + arch/powerpc/Makefile | 10 + arch/powerpc/include/asm/atomic.h | 24 +- arch/powerpc/include/asm/io.h | 37 +++ arch/powerpc/include/asm/module.h | 10 +- arch/powerpc/include/asm/paca.h | 2 + arch/powerpc/include/asm/ppc-opcode.h | 8 + arch/powerpc/include/asm/ppc_asm.h | 24 ++ arch/powerpc/include/asm/sections.h | 5 + arch/powerpc/include/asm/uaccess.h | 28 +- arch/powerpc/include/uapi/asm/elf.h | 4 + arch/powerpc/kernel/asm-offsets.c | 2 + arch/powerpc/kernel/exceptions-64s.S | 112 +++---- arch/powerpc/kernel/head_64.S | 130 ++++---- arch/powerpc/kernel/interrupt_64.S | 28 +- arch/powerpc/kernel/irq.c | 8 + arch/powerpc/kernel/misc_64.S | 2 +- arch/powerpc/kernel/module_64.c | 376 +++++++++++++++++++++--- arch/powerpc/kernel/paca.c | 2 + arch/powerpc/kernel/trace/ftrace.c | 52 +++- arch/powerpc/kernel/vdso/gettimeofday.S | 6 +- arch/powerpc/kernel/vector.S | 6 + arch/powerpc/kernel/vmlinux.lds.S | 6 + arch/powerpc/kvm/book3s_hv_rmhandlers.S | 16 +- arch/powerpc/lib/copypage_64.S | 10 + arch/powerpc/lib/copypage_power7.S | 4 +- arch/powerpc/lib/copyuser_power7.S | 8 +- arch/powerpc/lib/hweight_64.S | 8 +- arch/powerpc/lib/memcmp_64.S | 4 +- arch/powerpc/lib/memcpy_power7.S | 6 +- arch/powerpc/net/bpf_jit.h | 10 +- arch/powerpc/net/bpf_jit_comp64.c | 35 ++- arch/powerpc/platforms/Kconfig.cputype | 38 +++ arch/powerpc/platforms/pseries/hvCall.S | 4 +- arch/powerpc/xmon/xmon.c | 2 + 35 files changed, 814 insertions(+), 219 deletions(-)
Signature · 1 line
2.40.0
Nicholas Piggin
reviewerPATCH 1/6 powerpc/64: Move initial base and TOC pointer calculation
A later change moves the non-prom case to run at the virtual address earlier, which calls for virtual TOC and kernel base. Split these two calculations for prom and non-prom to make that change simpler.
Signed: Nicholas Piggin <[email protected]>
--- arch/powerpc/kernel/head_64.S | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-)
arch/powerpc/kernel/head_64.S +19 -9
@@ -515,15 +515,6 @@ __start_initialization_multiplatform: /* Zero r13 (paca) so early program check / mce don't use it */ li r13,0 - /* Get TOC pointer (current runtime address) */ - bl relative_toc - - /* find out where we are now */ - bcl 20,31,$+4 -0: mflr r26 /* r26 = runtime addr here */ - addis r26,r26,(_stext - 0b)@ha - addi r26,r26,(_stext - 0b)@l /* current runtime base addr */ - /* * Are we booted from a PROM Of-type client-interface ? */
@@ -545,11 +536,30 @@ __start_initialization_multiplatform: #else bl start_initialization_book3s #endif /* CONFIG_PPC_BOOK3E_64 */ + + /* Get TOC pointer */ + bl relative_toc + + /* find out where we are now */ + bcl 20,31,$+4 +0: mflr r26 /* r26 = runtime addr here */ + addis r26,r26,(_stext - 0b)@ha + addi r26,r26,(_stext - 0b)@l /* current runtime base addr */ + b __after_prom_start __REF __boot_from_prom: #ifdef CONFIG_PPC_OF_BOOT_TRAMPOLINE + /* Get TOC pointer */ + bl relative_toc + + /* find out where we are now */ + bcl 20,31,$+4 +0: mflr r26 /* r26 = runtime addr here */ + addis r26,r26,(_stext - 0b)@ha + addi r26,r26,(_stext - 0b)@l /* current runtime base addr */ + /* Save parameters */ mr r31,r3 mr r30,r4
Signature · 1 line
2.40.0
Nicholas Piggin
reviewerPATCH 2/6 powerpc/64s: Run at the kernel virtual address earlier in boot
In reply to Nicholas PigginThis mostly consolidates the Book3E and Book3S behaviour in boot WRT executing from the physical or virtual address.
Book3E sets up kernel virtual linear map in start_initialization_book3e and runs from the virtual linear alias after that. This change makes Book3S begin to execute from the virtual alias at the same point. Book3S can not use its MMU for that at this point, but when the MMU is disabled, the virtual linear address correctly aliases to physical memory because the top bits of the address are ignored with MMU disabled.
Secondaries execute from the virtual address similarly early.
This reduces the differences between subarchs, but the main motivation was to enable the PC-relative addressing ABI for Book3S, where pointer calculations must execute from the virtual address or the top bits of the pointer will be lost. This is similar to the requirement the TOC relative addressing already has that the TOC pointer use its virtual address.
--- arch/powerpc/kernel/head_64.S | 82 +++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 38 deletions(-)
arch/powerpc/kernel/head_64.S +44 -38
@@ -76,6 +76,13 @@ * 2. The kernel is entered at __start */ +/* + * boot_from_prom and prom_init run at the physical address. Everything + * after prom and kexec entry run at the virtual address (PAGE_OFFSET). + * Secondaries run at the virtual address from generic_secondary_common_init + * onward. + */ + OPEN_FIXED_SECTION(first_256B, 0x0, 0x100) USE_FIXED_SECTION(first_256B) /*
@@ -303,13 +310,11 @@ _GLOBAL(fsl_secondary_thread_init) /* turn on 64-bit mode */ bl enable_64b_mode - /* get a valid TOC pointer, wherever we're mapped at */ - bl relative_toc - tovirt(r2,r2) - /* Book3E initialization */ mr r3,r24 bl book3e_secondary_thread_init + bl relative_toc + b generic_secondary_common_init #endif /* CONFIG_PPC_BOOK3E_64 */
@@ -331,16 +336,12 @@ _GLOBAL(generic_secondary_smp_init) /* turn on 64-bit mode */ bl enable_64b_mode - /* get a valid TOC pointer, wherever we're mapped at */ - bl relative_toc - tovirt(r2,r2) - #ifdef CONFIG_PPC_BOOK3E_64 /* Book3E initialization */ mr r3,r24 mr r4,r25 bl book3e_secondary_core_init - + /* Now NIA and r2 are relocated to PAGE_OFFSET if not already */ /* * After common core init has finished, check if the current thread is the * one we wanted to boot. If not, start the specified thread and stop the
@@ -378,6 +379,16 @@ _GLOBAL(generic_secondary_smp_init) 10: b 10b 20: +#else + /* Now the MMU is off, can branch to our PAGE_OFFSET address */ + bcl 20,31,$+4 +1: mflr r11 + addi r11,r11,(2f - 1b) + tovirt(r11, r11) + mtctr r11 + bctr +2: + bl relative_toc #endif generic_secondary_common_init:
@@ -492,6 +503,8 @@ SYM_FUNC_START_LOCAL(start_initialization_book3s) /* Switch off MMU if not already off */ bl __mmu_off + /* Now the MMU is off, can return to our PAGE_OFFSET address */ + tovirt(r25,r25) mtlr r25 blr SYM_FUNC_END(start_initialization_book3s)
@@ -531,16 +544,19 @@ __start_initialization_multiplatform: mr r29,r9 #endif + /* These functions return to the virtual (PAGE_OFFSET) address */ #ifdef CONFIG_PPC_BOOK3E_64 bl start_initialization_book3e #else bl start_initialization_book3s #endif /* CONFIG_PPC_BOOK3E_64 */ - /* Get TOC pointer */ + /* Get TOC pointer, virtual */ bl relative_toc /* find out where we are now */ + + /* OPAL doesn't pass base address in r4, have to derive it. */ bcl 20,31,$+4 0: mflr r26 /* r26 = runtime addr here */ addis r26,r26,(_stext - 0b)@ha
@@ -551,7 +567,7 @@ __start_initialization_multiplatform: __REF __boot_from_prom: #ifdef CONFIG_PPC_OF_BOOT_TRAMPOLINE - /* Get TOC pointer */ + /* Get TOC pointer, non-virtual */ bl relative_toc /* find out where we are now */
@@ -600,18 +616,11 @@ __boot_from_prom: __after_prom_start: #ifdef CONFIG_RELOCATABLE /* process relocations for the final address of the kernel */ - lis r25,PAGE_OFFSET@highest /* compute virtual base of kernel */ - sldi r25,r25,32 -#if defined(CONFIG_PPC_BOOK3E_64) - tovirt(r26,r26) /* on booke, we already run at PAGE_OFFSET */ -#endif lwz r7,(FIXED_SYMBOL_ABS_ADDR(__run_at_load))(r26) -#if defined(CONFIG_PPC_BOOK3E_64) - tophys(r26,r26) -#endif cmplwi cr0,r7,1 /* flagged to stay where we are ? */ - bne 1f - add r25,r25,r26 + mr r25,r26 /* then use current kernel base */ + beq 1f + LOAD_REG_IMMEDIATE(r25, PAGE_OFFSET) /* else use static kernel base */ 1: mr r3,r25 bl relocate #if defined(CONFIG_PPC_BOOK3E_64)
@@ -627,14 +636,8 @@ __after_prom_start: * * Note: This process overwrites the OF exception vectors. */ - li r3,0 /* target addr */ -#ifdef CONFIG_PPC_BOOK3E_64 - tovirt(r3,r3) /* on booke, we already run at PAGE_OFFSET */ -#endif + LOAD_REG_IMMEDIATE(r3, PAGE_OFFSET) mr. r4,r26 /* In some cases the loader may */ -#if defined(CONFIG_PPC_BOOK3E_64) - tovirt(r4,r4) -#endif beq 9f /* have already put us at zero */ li r6,0x100 /* Start offset, the first 0x100 */ /* bytes were copied earlier. */
@@ -645,9 +648,6 @@ __after_prom_start: * variable __run_at_load, if it is set the kernel is treated as relocatable * kernel, otherwise it will be moved to PHYSICAL_START */ -#if defined(CONFIG_PPC_BOOK3E_64) - tovirt(r26,r26) /* on booke, we already run at PAGE_OFFSET */ -#endif lwz r7,(FIXED_SYMBOL_ABS_ADDR(__run_at_load))(r26) cmplwi cr0,r7,1 bne 3f
@@ -766,9 +766,15 @@ _GLOBAL(pmac_secondary_start) sync slbia - /* get TOC pointer (real address) */ + /* Branch to our PAGE_OFFSET address */ + bcl 20,31,$+4 +1: mflr r11 + addi r11,r11,(2f - 1b) + tovirt(r11, r11) + mtctr r11 + bctr +2: bl relative_toc - tovirt(r2,r2) /* Copy some CPU settings from CPU 0 */ bl __restore_cpu_ppc970
@@ -907,8 +913,9 @@ SYM_FUNC_END(enable_64b_mode) * TOC in -mcmodel=medium mode. After we relocate to 0 but before * the MMU is on we need our TOC to be a virtual address otherwise * these pointers will be real addresses which may get stored and - * accessed later with the MMU on. We use tovirt() at the call - * sites to handle this. + * accessed later with the MMU on. We branch to the virtual address + * while still in real mode then call relative_toc again to handle + * this. */ _GLOBAL(relative_toc) mflr r0
@@ -927,9 +934,8 @@ p_toc: .8byte .TOC. - 0b */ __REF start_here_multiplatform: - /* set up the TOC */ - bl relative_toc - tovirt(r2,r2) + /* Adjust TOC for moved kernel. Could adjust when moving it instead. */ + bl relative_toc /* Clear out the BSS. It may have been done in prom_init, * already but that's irrelevant since prom_init will soon
Signature · 1 line
2.40.0
Nicholas Piggin
reviewerPATCH 3/6 powerpc/64: Add support to build with prefixed instructions
In reply to Nicholas PigginAdd an option to build kernel and module with prefixed instructions if the CPU and toolchain support it.
This is not related to kernel support for userspace execution of prefixed instructions.
Building with prefixed instructions breaks some extended inline asm memory addressing, for example it will provide immediates that exceed the range of simple load/store displacement. Whether this is a toolchain or a kernel asm problem remains to be seen. For now, these are replaced with simpler and less efficient direct register addressing when compiling with prefixed.
--- arch/powerpc/Kconfig | 3 +++ arch/powerpc/Makefile | 4 +++ arch/powerpc/include/asm/atomic.h | 24 ++++++++++++++--- arch/powerpc/include/asm/io.h | 37 ++++++++++++++++++++++++++ arch/powerpc/include/asm/uaccess.h | 28 +++++++++++++++++-- arch/powerpc/kernel/trace/ftrace.c | 2 ++ arch/powerpc/platforms/Kconfig.cputype | 20 ++++++++++++++ 7 files changed, 112 insertions(+), 6 deletions(-)
arch/powerpc/Kconfig +3 -0
@@ -4,6 +4,9 @@ source "arch/powerpc/platforms/Kconfig.cputype" config CC_HAS_ELFV2 def_bool PPC64 && $(cc-option, -mabi=elfv2) +config CC_HAS_PREFIXED + def_bool PPC64 && $(cc-option, -mcpu=power10 -mprefixed) + config 32BIT bool default y if PPC32
arch/powerpc/Makefile +4 -0
@@ -181,7 +181,11 @@ ifdef CONFIG_476FPE_ERR46 endif # No prefix or pcrel +ifdef CONFIG_PPC_KERNEL_PREFIXED +KBUILD_CFLAGS += $(call cc-option,-mprefixed) +else KBUILD_CFLAGS += $(call cc-option,-mno-prefixed) +endif KBUILD_CFLAGS += $(call cc-option,-mno-pcrel) # No AltiVec or VSX or MMA instructions when building kernel
arch/powerpc/include/asm/atomic.h +20 -4
@@ -27,14 +27,22 @@ static __inline__ int arch_atomic_read(const atomic_t *v) {int t; - __asm__ __volatile__("lwz%U1%X1 %0,%1" :"=r" (t) :"m<>" (v->counter)); +/* -mprefixed can generate offsets beyond range, fall back hack */ +if (IS_ENABLED (CONFIG_PPC_KERNEL_PREFIXED )) + __asm__ __volatile__("lwz %0,0(%1)" :"=r" (t) :"b" (&v->counter)); +else + __asm__ __volatile__("lwz%U1%X1 %0,%1" :"=r" (t) :"m<>" (v->counter));return t; }static __inline__void arch_atomic_set (atomic_t *v,int i) { - __asm__ __volatile__("stw%U0%X0 %1,%0" :"=m<>" (v->counter) :"r" (i)); +/* -mprefixed can generate offsets beyond range, fall back hack */ +if (IS_ENABLED (CONFIG_PPC_KERNEL_PREFIXED )) + __asm__ __volatile__("stw %1,0(%2)" :"=m" (v->counter) :"r" (i),"b" (&v->counter)); +else + __asm__ __volatile__("stw%U0%X0 %1,%0" :"=m<>" (v->counter) :"r" (i)); }#define ATOMIC_OP (op, asm_op, suffix, sign, ...) \
@@ -226,14 +234,22 @@ static __inline__ s64 arch_atomic64_read(const atomic64_t *v) {s64 t; - __asm__ __volatile__("ld%U1%X1 %0,%1" :"=r" (t) :"m<>" (v->counter)); +/* -mprefixed can generate offsets beyond range, fall back hack */ +if (IS_ENABLED (CONFIG_PPC_KERNEL_PREFIXED )) + __asm__ __volatile__("ld %0,0(%1)" :"=r" (t) :"b" (&v->counter)); +else + __asm__ __volatile__("ld%U1%X1 %0,%1" :"=r" (t) :"m<>" (v->counter));return t; }static __inline__void arch_atomic64_set (atomic64_t *v,s64 i) { - __asm__ __volatile__("std%U0%X0 %1,%0" :"=m<>" (v->counter) :"r" (i)); +/* -mprefixed can generate offsets beyond range, fall back hack */ +if (IS_ENABLED (CONFIG_PPC_KERNEL_PREFIXED )) + __asm__ __volatile__("std %1,0(%2)" :"=m" (v->counter) :"r" (i),"b" (&v->counter)); +else + __asm__ __volatile__("std%U0%X0 %1,%0" :"=m<>" (v->counter) :"r" (i)); }#define ATOMIC64_OP (op, asm_op) \
arch/powerpc/include/asm/io.h +37 -0
@@ -97,6 +97,42 @@ extern bool isa_io_special;* */ +/* -mprefixed can generate offsets beyond range, fall back hack */ +#ifdef CONFIG_PPC_KERNEL_PREFIXED +#define DEF_MMIO_IN_X (name, size, insn) \ +static inline u##size name(const volatile u##size __iomem *addr) \ +{ \ + u##size ret; \ + __asm__ __volatile__("sync;"#insn" %0,0,%1;twi 0,%0,0;isync" \ + : "=r" (ret) : "r" (addr) : "memory"); \ + return ret; \ +} + +#define DEF_MMIO_OUT_X (name, size, insn) \ +static inline void name(volatile u##size __iomem *addr, u##size val) \ +{ \ + __asm__ __volatile__("sync;"#insn" %1,0,%0" \ + : : "r" (addr), "r" (val) : "memory"); \ + mmiowb_set_pending(); \ +} + +#define DEF_MMIO_IN_D (name, size, insn) \ +static inline u##size name(const volatile u##size __iomem *addr) \ +{ \ + u##size ret; \ + __asm__ __volatile__("sync;"#insn" %0,0(%1);twi 0,%0,0;isync"\ + : "=r" (ret) : "b" (addr) : "memory"); \ + return ret; \ +} + +#define DEF_MMIO_OUT_D (name, size, insn) \ +static inline void name(volatile u##size __iomem *addr, u##size val) \ +{ \ + __asm__ __volatile__("sync;"#insn" %1,0(%0)" \ + : : "b" (addr), "r" (val) : "memory"); \ + mmiowb_set_pending(); \ +} +#else #define DEF_MMIO_IN_X (name, size, insn) \ static inline u##size name(const volatile u##size __iomem *addr) \ { \
@@ -130,6 +166,7 @@ static inline void name(volatile u##size __iomem *addr, u##size val) \ : "=m<>" (*addr) : "r" (val) : "memory"); \ mmiowb_set_pending(); \ } +#endif DEF_MMIO_IN_D (in_8,8 , lbz);DEF_MMIO_OUT_D (out_8,8 , stb);
arch/powerpc/include/asm/uaccess.h +26 -2
@@ -71,14 +71,26 @@ __pu_failed: \* because we do not write to any memory gcc knows about, so there * are no aliasing issues. */ +/* -mprefixed can generate offsets beyond range, fall back hack */ +#ifdef CONFIG_PPC_KERNEL_PREFIXED +#define __put_user_asm_goto (x, addr, label, op) \ + asm_volatile_goto( \ + "1: " op " %0,0(%1) # put_user\n" \ + EX_TABLE(1b, %l2) \ + : \ + : "r" (x), "b" (addr) \ + : \ + : label) +#else #define __put_user_asm_goto (x, addr, label, op) \ asm_volatile_goto( \ "1: " op "%U1%X1 %0,%1 # put_user\n" \ EX_TABLE(1b, %l2) \ : \ - : "r" (x), "m<>" (*addr) \ + : "r" (x), "m<>" (*addr) \ : \ : label) +#endif #ifdef __powerpc64__#define __put_user_asm2_goto (x, ptr, label) \
@@ -131,14 +143,26 @@ do { \#ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT +/* -mprefixed can generate offsets beyond range, fall back hack */ +#ifdef CONFIG_PPC_KERNEL_PREFIXED +#define __get_user_asm_goto (x, addr, label, op) \ + asm_volatile_goto( \ + "1: "op" %0,0(%1) # get_user\n" \ + EX_TABLE(1b, %l2) \ + : "=r" (x) \ + : "b" (addr) \ + : \ + : label) +#else #define __get_user_asm_goto (x, addr, label, op) \ asm_volatile_goto( \ "1: "op"%U1%X1 %0, %1 # get_user\n" \ EX_TABLE(1b, %l2) \ : "=r" (x) \ - : "m<>" (*addr) \ + : "m<>" (*addr) \ : \ : label) +#endif #ifdef __powerpc64__#define __get_user_asm2_goto (x, addr, label) \
arch/powerpc/kernel/trace/ftrace.c +2 -0
@@ -194,6 +194,8 @@ __ftrace_make_nop(struct module *mod,* get corrupted. * * Use a b +8 to jump over the load. +* XXX: could make PCREL depend on MPROFILE_KERNEL +* XXX: check PCREL && MPROFILE_KERNEL calling sequence */ if (IS_ENABLED (CONFIG_MPROFILE_KERNEL ) ||IS_ENABLED (CONFIG_PPC32 )) pop =ppc_inst (PPC_RAW_NOP ());
arch/powerpc/platforms/Kconfig.cputype +20 -0
@@ -180,6 +180,7 @@ config POWER10_CPU bool "POWER10" depends on PPC_BOOK3S_64 select ARCH_HAS_FAST_MULTIPLIER + select PPC_HAVE_PREFIXED_SUPPORT config E5500_CPU bool "Freescale e5500"
@@ -454,6 +455,22 @@ config PPC_RADIX_MMU_DEFAULT If you're unsure, say Y. +config PPC_KERNEL_PREFIXED + depends on PPC_HAVE_PREFIXED_SUPPORT + depends on CC_HAS_PREFIXED + default n + bool "Build Kernel with Prefixed Instructions" + help + POWER10 and later CPUs support prefixed instructions, 8 byte + instructions that include large immediate, pc relative addressing, + and various floating point, vector, MMA. + + This option builds the kernel with prefixed instructions, and + allows a pc relative addressing option to be selected. + + Kernel support for prefixed instructions in applications and guests + is not affected by this option. + config PPC_KUEP bool "Kernel Userspace Execution Prevention" if !40x default y if !40x
@@ -490,6 +507,9 @@ config PPC_MMU_NOHASH config PPC_HAVE_PMU_SUPPORT bool +config PPC_HAVE_PREFIXED_SUPPORT + bool + config PMU_SYSFS bool "Create PMU SPRs sysfs file" default n
Signature · 1 line
2.40.0
Nicholas Piggin
reviewerPATCH 4/6 powerpc: add CFUNC assembly label annotation
In reply to Nicholas PigginThis macro is to be used in assembly where C functions are called. pcrel addressing mode requires branches to functions with a localentry value of 1 to have either a trailing nop or @notoc. This macro permits the latter without changing callers.
--- arch/powerpc/include/asm/ppc_asm.h | 5 ++ arch/powerpc/kernel/exceptions-64s.S | 112 ++++++++++++------------ arch/powerpc/kernel/head_64.S | 12 +-- arch/powerpc/kernel/interrupt_64.S | 28 +++--- arch/powerpc/kernel/misc_64.S | 2 +- arch/powerpc/kernel/vdso/gettimeofday.S | 6 +- arch/powerpc/kvm/book3s_hv_rmhandlers.S | 16 ++-- arch/powerpc/lib/copypage_power7.S | 4 +- arch/powerpc/lib/copyuser_power7.S | 8 +- arch/powerpc/lib/hweight_64.S | 8 +- arch/powerpc/lib/memcmp_64.S | 4 +- arch/powerpc/lib/memcpy_power7.S | 6 +- arch/powerpc/platforms/pseries/hvCall.S | 4 +- 13 files changed, 112 insertions(+), 103 deletions(-)
arch/powerpc/include/asm/ppc_asm.h +5 -0
@@ -180,6 +180,11 @@#ifdef __KERNEL__ +/* +* Used to name C functions called from asm +*/ +#define CFUNC (name) name +/* * We use __powerpc64__ here because we want the compat VDSO to use the 32-bit * version below in the else case of the ifdef.
arch/powerpc/kernel/exceptions-64s.S +56 -56
395 lines not on this page · raw message
arch/powerpc/kernel/head_64.S +6 -6
@@ -605,7 +605,7 @@ __boot_from_prom: /* Do all of the interaction with OF client interface */ mr r8,r26 - bl prom_init + bl CFUNC(prom_init) #endif /* #CONFIG_PPC_OF_BOOT_TRAMPOLINE */ /* We never return. We also hit that trap if trying to boot
@@ -833,7 +833,7 @@ __secondary_start: * can turn it on below. This is a call to C, which is OK, we're still * running on the emergency stack. */ - bl early_setup_secondary + bl CFUNC(early_setup_secondary) /* * The primary has initialized our kernel stack for us in the paca, grab
@@ -872,7 +872,7 @@ start_secondary_prolog: LOAD_PACA_TOC() li r3,0 std r3,0(r1) /* Zero the stack frame pointer */ - bl start_secondary + bl CFUNC(start_secondary) b . /* * Reset stack pointer and call start_secondary
@@ -883,7 +883,7 @@ _GLOBAL(start_secondary_resume) ld r1,PACAKSAVE(r13) /* Reload kernel stack pointer */ li r3,0 std r3,0(r1) /* Zero the stack frame pointer */ - bl start_secondary + bl CFUNC(start_secondary) b . #endif
@@ -988,7 +988,7 @@ start_here_multiplatform: */ #ifdef CONFIG_KASAN - bl kasan_early_init + bl CFUNC(kasan_early_init) #endif /* Restore parameters passed from prom_init/kexec */ mr r3,r31
@@ -1021,7 +1021,7 @@ start_here_common: stb r0,PACAIRQHAPPENED(r13) /* Generic kernel entry */ - bl start_kernel + bl CFUNC(start_kernel) /* Not reached */ 0: trap
arch/powerpc/kernel/interrupt_64.S +14 -14
@@ -101,12 +101,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) * state of kernel code. */ SANITIZE_SYSCALL_GPRS() - bl system_call_exception + bl CFUNC(system_call_exception) .Lsyscall_vectored_\name\()_exit: addi r4,r1,STACK_INT_FRAME_REGS li r5,1 /* scv */ - bl syscall_exit_prepare + bl CFUNC(syscall_exit_prepare) std r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */ .Lsyscall_vectored_\name\()_rst_start: lbz r11,PACAIRQHAPPENED(r13)
@@ -185,7 +185,7 @@ _ASM_NOKPROBE_SYMBOL(syscall_vectored_\name\()_restart) addi r4,r1,STACK_INT_FRAME_REGS li r11,IRQS_ALL_DISABLED stb r11,PACAIRQSOFTMASK(r13) - bl syscall_exit_restart + bl CFUNC(syscall_exit_restart) std r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */ b .Lsyscall_vectored_\name\()_rst_start 1:
@@ -286,12 +286,12 @@ END_BTB_FLUSH_SECTION * state of kernel code. */ SANITIZE_SYSCALL_GPRS() - bl system_call_exception + bl CFUNC(system_call_exception) .Lsyscall_exit: addi r4,r1,STACK_INT_FRAME_REGS li r5,0 /* !scv */ - bl syscall_exit_prepare + bl CFUNC(syscall_exit_prepare) std r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */ #ifdef CONFIG_PPC_BOOK3S .Lsyscall_rst_start:
@@ -372,7 +372,7 @@ _ASM_NOKPROBE_SYMBOL(syscall_restart) addi r4,r1,STACK_INT_FRAME_REGS li r11,IRQS_ALL_DISABLED stb r11,PACAIRQSOFTMASK(r13) - bl syscall_exit_restart + bl CFUNC(syscall_exit_restart) std r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */ b .Lsyscall_rst_start 1:
@@ -401,7 +401,7 @@ _ASM_NOKPROBE_SYMBOL(fast_interrupt_return_srr) li r3,0 /* 0 return value, no EMULATE_STACK_STORE */ bne+ .Lfast_kernel_interrupt_return_srr addi r3,r1,STACK_INT_FRAME_REGS - bl unrecoverable_exception + bl CFUNC(unrecoverable_exception) b . /* should not get here */ #else bne .Lfast_user_interrupt_return_srr
@@ -419,7 +419,7 @@ _ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()) interrupt_return_\srr\()_user: /* make backtraces match the _kernel variant */ _ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_user) addi r3,r1,STACK_INT_FRAME_REGS - bl interrupt_exit_user_prepare + bl CFUNC(interrupt_exit_user_prepare) #ifndef CONFIG_INTERRUPT_SANITIZE_REGISTERS cmpdi r3,0 bne- .Lrestore_nvgprs_\srr
@@ -523,7 +523,7 @@ _ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_user_restart) addi r3,r1,STACK_INT_FRAME_REGS li r11,IRQS_ALL_DISABLED stb r11,PACAIRQSOFTMASK(r13) - bl interrupt_exit_user_restart + bl CFUNC(interrupt_exit_user_restart) std r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */ b .Linterrupt_return_\srr\()_user_rst_start 1:
@@ -536,7 +536,7 @@ RESTART_TABLE(.Linterrupt_return_\srr\()_user_rst_start, .Linterrupt_return_\srr interrupt_return_\srr\()_kernel: _ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_kernel) addi r3,r1,STACK_INT_FRAME_REGS - bl interrupt_exit_kernel_prepare + bl CFUNC(interrupt_exit_kernel_prepare) std r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */ .Linterrupt_return_\srr\()_kernel_rst_start:
@@ -705,7 +705,7 @@ _ASM_NOKPROBE_SYMBOL(interrupt_return_\srr\()_kernel_restart) addi r3,r1,STACK_INT_FRAME_REGS li r11,IRQS_ALL_DISABLED stb r11,PACAIRQSOFTMASK(r13) - bl interrupt_exit_kernel_restart + bl CFUNC(interrupt_exit_kernel_restart) std r1,PACA_EXIT_SAVE_R1(r13) /* save r1 for restart */ b .Linterrupt_return_\srr\()_kernel_rst_start 1:
@@ -727,20 +727,20 @@ DEFINE_FIXED_SYMBOL(__end_soft_masked, text) #ifdef CONFIG_PPC_BOOK3S _GLOBAL(ret_from_fork_scv) - bl schedule_tail + bl CFUNC(schedule_tail) REST_NVGPRS(r1) li r3,0 /* fork() return value */ b .Lsyscall_vectored_common_exit #endif _GLOBAL(ret_from_fork) - bl schedule_tail + bl CFUNC(schedule_tail) REST_NVGPRS(r1) li r3,0 /* fork() return value */ b .Lsyscall_exit _GLOBAL(ret_from_kernel_thread) - bl schedule_tail + bl CFUNC(schedule_tail) REST_NVGPRS(r1) mtctr r14 mr r3,r15
arch/powerpc/kernel/misc_64.S +1 -1
@@ -432,7 +432,7 @@ _GLOBAL(kexec_sequence) 1: /* copy dest pages, flush whole dest image */ mr r3,r29 - bl kexec_copy_flush /* (image) */ + bl CFUNC(kexec_copy_flush) /* (image) */ /* turn off mmu now if not done earlier */ cmpdi r26,0
arch/powerpc/kernel/vdso/gettimeofday.S +5 -1
@@ -38,7 +38,11 @@ .else addi r4, r5, VDSO_DATA_OFFSET .endif - bl DOTSYM(\funct) +#ifdef __powerpc64__ + bl CFUNC(DOTSYM(\funct)) +#else + bl \funct +#endif PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1) #ifdef __powerpc64__ PPC_LL r2, PPC_MIN_STKFRM + STK_GOT(r1)
arch/powerpc/kvm/book3s_hv_rmhandlers.S +8 -8
@@ -381,7 +381,7 @@ kvm_secondary_got_guest: bne kvm_no_guest li r3,0 /* NULL argument */ - bl hmi_exception_realmode + bl CFUNC(hmi_exception_realmode) /* * At this point we have finished executing in the guest. * We need to wait for hwthread_req to become zero, since
@@ -458,7 +458,7 @@ kvm_unsplit_nap: cmpwi r12, BOOK3S_INTERRUPT_HMI bne 55f li r3, 0 /* NULL argument */ - bl hmi_exception_realmode + bl CFUNC(hmi_exception_realmode) 55: /* * Ensure that secondary doesn't nap when it has
@@ -859,7 +859,7 @@ deliver_guest_interrupt: /* r4 = vcpu, r13 = paca */ cmpdi r0, 0 beq 71f mr r3, r4 - bl kvmppc_guest_entry_inject_int + bl CFUNC(kvmppc_guest_entry_inject_int) ld r4, HSTATE_KVM_VCPU(r13) 71: ld r6, VCPU_SRR0(r4)
@@ -1544,7 +1544,7 @@ kvmppc_guest_external: /* External interrupt, first check for host_ipi. If this is * set, we know the host wants us out so let's do it now */ - bl kvmppc_read_intr + bl CFUNC(kvmppc_read_intr) /* * Restore the active volatile registers after returning from
@@ -1626,7 +1626,7 @@ kvmppc_hdsi: /* Search the hash table. */ mr r3, r9 /* vcpu pointer */ li r7, 1 /* data fault */ - bl kvmppc_hpte_hv_fault + bl CFUNC(kvmppc_hpte_hv_fault) ld r9, HSTATE_KVM_VCPU(r13) ld r10, VCPU_PC(r9) ld r11, VCPU_MSR(r9)
@@ -1702,7 +1702,7 @@ kvmppc_hisi: mr r4, r10 mr r6, r11 li r7, 0 /* instruction fault */ - bl kvmppc_hpte_hv_fault + bl CFUNC(kvmppc_hpte_hv_fault) ld r9, HSTATE_KVM_VCPU(r13) ld r10, VCPU_PC(r9) ld r11, VCPU_MSR(r9)
@@ -2342,7 +2342,7 @@ hmi_realmode: lbz r0, HSTATE_PTID(r13) cmpwi r0, 0 bne guest_exit_cont - bl kvmppc_realmode_hmi_handler + bl CFUNC(kvmppc_realmode_hmi_handler) ld r9, HSTATE_KVM_VCPU(r13) li r12, BOOK3S_INTERRUPT_HMI b guest_exit_cont
@@ -2413,7 +2413,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) 7: mflr r0 std r0, PPC_LR_STKOFF(r1) stdu r1, -PPC_MIN_STKFRM(r1) - bl kvmppc_read_intr + bl CFUNC(kvmppc_read_intr) nop li r12, BOOK3S_INTERRUPT_EXTERNAL cmpdi r3, 1
arch/powerpc/lib/copypage_power7.S +2 -2
@@ -45,7 +45,7 @@ _GLOBAL(copypage_power7) std r4,-STACKFRAMESIZE+STK_REG(R30)(r1) std r0,16(r1) stdu r1,-STACKFRAMESIZE(r1) - bl enter_vmx_ops + bl CFUNC(enter_vmx_ops) cmpwi r3,0 ld r0,STACKFRAMESIZE+16(r1) ld r3,STK_REG(R31)(r1)
@@ -88,7 +88,7 @@ _GLOBAL(copypage_power7) addi r3,r3,128 bdnz 1b - b exit_vmx_ops /* tail call optimise */ + b CFUNC(exit_vmx_ops) /* tail call optimise */ #else li r0,(PAGE_SIZE/128)
arch/powerpc/lib/copyuser_power7.S +4 -4
@@ -47,7 +47,7 @@ ld r15,STK_REG(R15)(r1) ld r14,STK_REG(R14)(r1) .Ldo_err3: - bl exit_vmx_usercopy + bl CFUNC(exit_vmx_usercopy) ld r0,STACKFRAMESIZE+16(r1) mtlr r0 b .Lexit
@@ -272,7 +272,7 @@ err1; stb r0,0(r3) mflr r0 std r0,16(r1) stdu r1,-STACKFRAMESIZE(r1) - bl enter_vmx_usercopy + bl CFUNC(enter_vmx_usercopy) cmpwi cr1,r3,0 ld r0,STACKFRAMESIZE+16(r1) ld r3,STK_REG(R31)(r1)
@@ -488,7 +488,7 @@ err3; lbz r0,0(r4) err3; stb r0,0(r3) 15: addi r1,r1,STACKFRAMESIZE - b exit_vmx_usercopy /* tail call optimise */ + b CFUNC(exit_vmx_usercopy) /* tail call optimise */ .Lvmx_unaligned_copy: /* Get the destination 16B aligned */
@@ -691,5 +691,5 @@ err3; lbz r0,0(r4) err3; stb r0,0(r3) 15: addi r1,r1,STACKFRAMESIZE - b exit_vmx_usercopy /* tail call optimise */ + b CFUNC(exit_vmx_usercopy) /* tail call optimise */ #endif /* CONFIG_ALTIVEC */
arch/powerpc/lib/hweight_64.S +4 -4
@@ -14,7 +14,7 @@ _GLOBAL(__arch_hweight8) BEGIN_FTR_SECTION - b __sw_hweight8 + b CFUNC(__sw_hweight8) nop nop FTR_SECTION_ELSE
@@ -26,7 +26,7 @@ EXPORT_SYMBOL(__arch_hweight8) _GLOBAL(__arch_hweight16) BEGIN_FTR_SECTION - b __sw_hweight16 + b CFUNC(__sw_hweight16) nop nop nop
@@ -49,7 +49,7 @@ EXPORT_SYMBOL(__arch_hweight16) _GLOBAL(__arch_hweight32) BEGIN_FTR_SECTION - b __sw_hweight32 + b CFUNC(__sw_hweight32) nop nop nop
@@ -75,7 +75,7 @@ EXPORT_SYMBOL(__arch_hweight32) _GLOBAL(__arch_hweight64) BEGIN_FTR_SECTION - b __sw_hweight64 + b CFUNC(__sw_hweight64) nop nop nop
arch/powerpc/lib/memcmp_64.S +2 -2
@@ -44,7 +44,7 @@ std r5,-STACKFRAMESIZE+STK_REG(R29)(r1); \ std r0,16(r1); \ stdu r1,-STACKFRAMESIZE(r1); \ - bl enter_vmx_ops; \ + bl CFUNC(enter_vmx_ops); \ cmpwi cr1,r3,0; \ ld r0,STACKFRAMESIZE+16(r1); \ ld r3,STK_REG(R31)(r1); \
@@ -60,7 +60,7 @@ std r5,-STACKFRAMESIZE+STK_REG(R29)(r1); \ std r0,16(r1); \ stdu r1,-STACKFRAMESIZE(r1); \ - bl exit_vmx_ops; \ + bl CFUNC(exit_vmx_ops); \ ld r0,STACKFRAMESIZE+16(r1); \ ld r3,STK_REG(R31)(r1); \ ld r4,STK_REG(R30)(r1); \
arch/powerpc/lib/memcpy_power7.S +3 -3
@@ -218,7 +218,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) std r5,-STACKFRAMESIZE+STK_REG(R29)(r1) std r0,16(r1) stdu r1,-STACKFRAMESIZE(r1) - bl enter_vmx_ops + bl CFUNC(enter_vmx_ops) cmpwi cr1,r3,0 ld r0,STACKFRAMESIZE+16(r1) ld r3,STK_REG(R31)(r1)
@@ -433,7 +433,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) 15: addi r1,r1,STACKFRAMESIZE ld r3,-STACKFRAMESIZE+STK_REG(R31)(r1) - b exit_vmx_ops /* tail call optimise */ + b CFUNC(exit_vmx_ops) /* tail call optimise */ .Lvmx_unaligned_copy: /* Get the destination 16B aligned */
@@ -637,5 +637,5 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) 15: addi r1,r1,STACKFRAMESIZE ld r3,-STACKFRAMESIZE+STK_REG(R31)(r1) - b exit_vmx_ops /* tail call optimise */ + b CFUNC(exit_vmx_ops) /* tail call optimise */ #endif /* CONFIG_ALTIVEC */
arch/powerpc/platforms/pseries/hvCall.S +2 -2
@@ -44,7 +44,7 @@ hcall_tracepoint_refcount: std r0,16(r1); \ addi r4,r1,STK_PARAM(FIRST_REG); \ stdu r1,-STACK_FRAME_MIN_SIZE(r1); \ - bl __trace_hcall_entry; \ + bl CFUNC(__trace_hcall_entry); \ ld r3,STACK_FRAME_MIN_SIZE+STK_PARAM(R3)(r1); \ ld r4,STACK_FRAME_MIN_SIZE+STK_PARAM(R4)(r1); \ ld r5,STACK_FRAME_MIN_SIZE+STK_PARAM(R5)(r1); \
@@ -63,7 +63,7 @@ hcall_tracepoint_refcount: std r3,STACK_FRAME_MIN_SIZE+STK_PARAM(R3)(r1); \ mr r4,r3; \ mr r3,r0; \ - bl __trace_hcall_exit; \ + bl CFUNC(__trace_hcall_exit); \ ld r0,STACK_FRAME_MIN_SIZE+16(r1); \ addi r1,r1,STACK_FRAME_MIN_SIZE; \ ld r3,STK_PARAM(R3)(r1); \
Signature · 1 line
2.40.0
Nicholas Piggin
reviewerPATCH 5/6 powerpc/64: vmlinux support building with PCREL addresing
In reply to Nicholas PigginPC-Relative or PCREL addressing is an extension to the ELF ABI which uses Power ISA v3.1 PC-relative instructions to calculate addresses, rather than the traditional TOC scheme.
Add an option to build vmlinux using pcrel addressing. Modules continue to use TOC addressing.
- TOC address helpers and r2 are poisoned with -1 when running vmlinux. r2 could be used for something useful once things are ironed out.
- Assembly must call C functions with @notoc annotation, or the linker complains aobut a missing nop after the call. This is done with the CFUNC macro introduced earlier.
- Boot: with the exception of prom_init, the execution branches to the kernel virtual address early in boot, before any addresses are generated, which ensures 34-bit pcrel addressing does not miss the high PAGE_OFFSET bits. TOC relative addressing has a similar requirement. prom_init does not go to the virtual address and its addresses should not carry over to the post-prom kernel.
- Ftrace trampolines are converted from TOC addressing to pcrel addressing, including module ftrace trampolines that currently use the kernel TOC to find ftrace target functions.
- BPF function prologue and function calling generation are converted from TOC to pcrel.
- copypage_64.S has an interesting problem, prefixed instructions have alignment restrictions so the linker can add padding, which makes the assembler treat the difference between two local labels as non-constant even if alignment is arranged so padding is not required. This may need toolchain help to solve nicely, for now move the prefix instruction out of the alternate patch section to work around it.
This reduces kernel text size by about 6%.
--- arch/powerpc/Kconfig | 3 ++ arch/powerpc/Makefile | 7 +++ arch/powerpc/include/asm/paca.h | 2 + arch/powerpc/include/asm/ppc-opcode.h | 8 ++++ arch/powerpc/include/asm/ppc_asm.h | 19 ++++++++ arch/powerpc/include/asm/sections.h | 5 +++ arch/powerpc/kernel/asm-offsets.c | 2 + arch/powerpc/kernel/head_64.S | 14 ++++++ arch/powerpc/kernel/irq.c | 8 ++++ arch/powerpc/kernel/module_64.c | 60 +++++++++++++++++++------- arch/powerpc/kernel/paca.c | 2 + arch/powerpc/kernel/trace/ftrace.c | 50 ++++++++++++++++----- arch/powerpc/kernel/vector.S | 6 +++ arch/powerpc/kernel/vmlinux.lds.S | 6 +++ arch/powerpc/lib/copypage_64.S | 10 +++++ arch/powerpc/net/bpf_jit.h | 10 +++-- arch/powerpc/net/bpf_jit_comp64.c | 35 +++++++++++---- arch/powerpc/platforms/Kconfig.cputype | 18 ++++++++ arch/powerpc/xmon/xmon.c | 2 + 19 files changed, 228 insertions(+), 39 deletions(-)
arch/powerpc/Kconfig +3 -0
@@ -7,6 +7,9 @@ config CC_HAS_ELFV2 config CC_HAS_PREFIXED def_bool PPC64 && $(cc-option, -mcpu=power10 -mprefixed) +config CC_HAS_PCREL + def_bool PPC64 && $(cc-option, -mcpu=power10 -mpcrel) + config 32BIT bool default y if PPC32
arch/powerpc/Makefile +7 -0
@@ -107,6 +107,9 @@ LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) += -z notext LDFLAGS_vmlinux := $(LDFLAGS_vmlinux-y) ifdef CONFIG_PPC64 +ifdef CONFIG_PPC_KERNEL_PCREL + KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-pcrel) +endif ifeq ($(call cc-option-yn,-mcmodel=medium),y) # -mcmodel=medium breaks modules because it uses 32bit offsets from # the TOC pointer to create pointers where possible. Pointers into the
@@ -186,7 +189,11 @@ KBUILD_CFLAGS += $(call cc-option,-mprefixed) else KBUILD_CFLAGS += $(call cc-option,-mno-prefixed) endif +ifdef CONFIG_PPC_KERNEL_PCREL +KBUILD_CFLAGS += $(call cc-option,-mpcrel) +else KBUILD_CFLAGS += $(call cc-option,-mno-pcrel) +endif # No AltiVec or VSX or MMA instructions when building kernel KBUILD_CFLAGS += $(call cc-option,-mno-altivec)
arch/powerpc/include/asm/paca.h +2 -0
@@ -88,7 +88,9 @@ struct paca_struct {u16 lock_token;/* Constant 0x8000, used in locks */ #endif +#ifndef CONFIG_PPC_KERNEL_PCREL u64 kernel_toc;/* Kernel TOC address */ +#endif u64 kernelbase;/* Base address of kernel */ u64 kernel_msr;/* MSR while running in kernel */ void *emergency_sp;/* pointer to emergency stack */
arch/powerpc/include/asm/ppc-opcode.h +8 -0
@@ -120,11 +120,18 @@* 16-bit immediate helper macros: HA() is for use with sign-extending instrs * (e.g. LD, ADDI). If the bottom 16 bits is "-ve", add another bit into the * top half to negate the effect (i.e. 0xffff + 1 = 0x(1)0000). +* +* XXX: should these mask out possible sign bits? */ #define IMM_H (i) ((uintptr_t)(i)>>16)#define IMM_HA (i) (((uintptr_t)(i)>>16) + \ (((uintptr_t)(i) & 0x8000) >> 15)) +/* +* 18-bit immediate helper for prefix 18-bit upper immediate si0 field. +*/ +#define IMM_H18 (i) (((uintptr_t)(i)>>16) & 0x3ffff) +/* opcode and xopcode for instructions */ #define OP_PREFIX 1
@@ -306,6 +313,7 @@#define PPC_PREFIX_8LS 0x04000000/* Prefixed instructions */ +#define PPC_INST_PADDI 0x38000000#define PPC_INST_PLD 0xe4000000#define PPC_INST_PSTD 0xf4000000
arch/powerpc/include/asm/ppc_asm.h +19 -0
@@ -183,7 +183,11 @@/* * Used to name C functions called from asm */ +#if defined(CONFIG_PPC_KERNEL_PCREL ) && !defined(MODULE ) +#define CFUNC (name) name@notoc +#else #define CFUNC (name) name +#endif /* * We use __powerpc64__ here because we want the compat VDSO to use the 32-bit
@@ -212,6 +216,9 @@ .globl name; \ name: +#if defined(CONFIG_PPC_KERNEL_PCREL ) && !defined(MODULE ) +#define _GLOBAL_TOC _GLOBAL +#else #define _GLOBAL_TOC (name) \ .align 2 ; \ .type name,@function; \
@@ -220,6 +227,7 @@ name: \ 0: addis r2,r12,(.TOC.-0b)@ha; \ addi r2,r2,(.TOC.-0b)@l; \ .localentry name,.-name +#endif#define DOTSYM (a) a
@@ -351,8 +359,13 @@ GLUE(.,name):#ifdef __powerpc64__ +#ifdef CONFIG_PPC_KERNEL_PCREL +#define __LOAD_PACA_TOC (reg) \ + li reg,-1 +#else #define __LOAD_PACA_TOC (reg) \ ld reg,PACATOC(r13) +#endif #define LOAD_PACA_TOC () \ __LOAD_PACA_TOC(r2)
@@ -366,9 +379,15 @@ GLUE(.,name): ori reg, reg, (expr)@l; \ rldimi reg, tmp, 32, 0 +#if defined(CONFIG_PPC_KERNEL_PCREL ) && !defined(MODULE ) +#define LOAD_REG_ADDR (reg,name) \ + pla reg,name@pcrel + +#else #define LOAD_REG_ADDR (reg,name) \ addis reg,r2,name@toc@ha; \ addi reg,reg,name@toc@l +#endif #ifdef CONFIG_PPC_BOOK3E_64 /*
arch/powerpc/include/asm/sections.h +5 -0
@@ -46,10 +46,15 @@ extern char end_virt_trampolines[];*/ static inline unsigned long kernel_toc_addr (void ) { +#ifdef CONFIG_PPC_KERNEL_PCREL +BUILD_BUG (); +return -1UL ; +#else unsigned long toc_ptr; asmvolatile ("mr %0, 2" :"=r" (toc_ptr));return toc_ptr; +#endif } static inline int overlaps_interrupt_vector_text(unsigned long start,
arch/powerpc/kernel/asm-offsets.c +2 -0
@@ -185,7 +185,9 @@ int main(void) offsetof(struct task_struct, thread_info));OFFSET (PACASAVEDMSR , paca_struct, saved_msr);OFFSET (PACAR1 , paca_struct, saved_r1); +#ifndef CONFIG_PPC_KERNEL_PCREL OFFSET (PACATOC , paca_struct, kernel_toc); +#endif OFFSET (PACAKBASE , paca_struct, kernelbase);OFFSET (PACAKMSR , paca_struct, kernel_msr);#ifdef CONFIG_PPC_BOOK3S_64
arch/powerpc/kernel/head_64.S +14 -0
@@ -330,6 +330,12 @@ _GLOBAL(fsl_secondary_thread_init) */ _GLOBAL(generic_secondary_smp_init) FIXUP_ENDIAN + + li r13,0 + + /* Poison TOC */ + li r2,-1 + mr r24,r3 mr r25,r4
@@ -528,6 +534,9 @@ __start_initialization_multiplatform: /* Zero r13 (paca) so early program check / mce don't use it */ li r13,0 + /* Poison TOC */ + li r2,-1 + /* * Are we booted from a PROM Of-type client-interface ? */
@@ -918,6 +927,10 @@ SYM_FUNC_END(enable_64b_mode) * this. */ _GLOBAL(relative_toc) +#ifdef CONFIG_PPC_KERNEL_PCREL + tdnei r2,-1 + blr +#else mflr r0 bcl 20,31,$+4 0: mflr r11
@@ -928,6 +941,7 @@ _GLOBAL(relative_toc) .balign 8 p_toc: .8byte .TOC. - 0b +#endif /* * This is where the main kernel code starts.
arch/powerpc/kernel/irq.c +8 -0
@@ -206,7 +206,11 @@ static __always_inline void call_do_softirq(const void *sp) asmvolatile ( PPC_STLU " %%r1, %[offset](%[sp]) ;" "mr %%r1, %[sp] ;" +#ifdef CONFIG_PPC_KERNEL_PCREL + "bl %[callee]@notoc ;" +#else"bl %[callee] ;" +#endifPPC_LL " %%r1, 0(%%r1) ;" :// Outputs : // Inputs
@@ -259,7 +263,11 @@ static __always_inline void call_do_irq(struct pt_regs *regs, void *sp)PPC_STLU " %%r1, %[offset](%[sp]) ;" "mr %%r4, %%r1 ;" "mr %%r1, %[sp] ;" +#ifdef CONFIG_PPC_KERNEL_PCREL +"bl %[callee]@notoc ;" +#else "bl %[callee] ;" +#endif PPC_LL " %%r1, 0(%%r1) ;" : // Outputs"+r" (r3)
arch/powerpc/kernel/module_64.c +45 -15
91 lines not on this page · raw message
arch/powerpc/kernel/paca.c +2 -0
@@ -191,7 +191,9 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu)#endif new_paca->lock_token =0x8000 ; new_paca->paca_index = cpu; +#ifndef CONFIG_PPC_KERNEL_PCREL new_paca->kernel_toc =kernel_toc_addr (); +#endif new_paca->kernelbase = (unsigned long ) _stext;/* Only set MSR:IR/DR when MMU is initialized */ new_paca->kernel_msr =MSR_KERNEL & ~(MSR_IR |MSR_DR );
arch/powerpc/kernel/trace/ftrace.c +39 -11
70 lines not on this page · raw message
arch/powerpc/kernel/vector.S +6 -0
@@ -177,9 +177,15 @@ fpone: fphalf: .quad 0x3fe0000000000000 /* 0.5 */ +#ifdef CONFIG_PPC_KERNEL_PCREL +#define LDCONST(fr, name) \ + pla r11,name@pcrel; \ + lfd fr,0(r11) +#else #define LDCONST(fr, name) \ addis r11,r2,name@toc@ha; \ lfd fr,name@toc@l(r11) +#endif #endif .text /*
arch/powerpc/kernel/vmlinux.lds.S +6 -0
@@ -169,12 +169,18 @@ SECTIONS } #else /* CONFIG_PPC32 */ +#ifndef CONFIG_PPC_KERNEL_PCREL .toc1 : AT(ADDR(.toc1) - LOAD_OFFSET) { *(.toc1) } +#endif .got : AT(ADDR(.got) - LOAD_OFFSET) ALIGN(256) { +#ifdef CONFIG_PPC_KERNEL_PCREL + *(.got) +#else *(.got .toc) +#endif } SOFT_MASK_TABLE(8)
arch/powerpc/lib/copypage_64.S +10 -0
@@ -18,8 +18,18 @@ FTR_SECTION_ELSE #endif ALT_FTR_SECTION_END_IFCLR(CPU_FTR_VMX_COPY) ori r5,r5,PAGE_SIZE@l +#ifdef CONFIG_PPC_KERNEL_PCREL + /* + * Hack for toolchain - prefixed instructions cause label difference to + * be non-constant even if 8 byte alignment is known, so they can not + * be put in FTR sections. + */ + LOAD_REG_ADDR(r10, ppc64_caches) +BEGIN_FTR_SECTION +#else BEGIN_FTR_SECTION LOAD_REG_ADDR(r10, ppc64_caches) +#endif lwz r11,DCACHEL1LOGBLOCKSIZE(r10) /* log2 of cache block size */ lwz r12,DCACHEL1BLOCKSIZE(r10) /* get cache block size */ li r9,0
arch/powerpc/net/bpf_jit.h +6 -4
@@ -19,6 +19,8 @@#define FUNCTION_DESCR_SIZE 0#endif +#define CTX_NIA (ctx) ((unsigned long)ctx->idx * 4) +#define PLANT_INSTR (d, idx, instr) \ do { if (d) { (d)[idx] = instr; } idx++; } while (0)#define EMIT (instr) PLANT_INSTR(image, ctx->idx, instr)
@@ -26,7 +28,7 @@/* Long jump; (unconditional 'branch') */ #define PPC_JMP (dest) \ do { \ - long offset = (long)(dest) - (ctx->idx * 4); \ + long offset = (long)(dest) - CTX_NIA(ctx); \ if ((dest) != 0 && !is_offset_in_branch_range(offset)) { \ pr_err_ratelimited("Branch offset 0x%lx (@%u) out of range\n", offset, ctx->idx); \ return -ERANGE; \
@@ -40,7 +42,7 @@/* "cond" here covers BO:BI fields. */ #define PPC_BCC_SHORT (cond, dest) \ do { \ - long offset = (long)(dest) - (ctx->idx * 4); \ + long offset = (long)(dest) - CTX_NIA(ctx); \ if ((dest) != 0 && !is_offset_in_cond_branch_range(offset)) { \ pr_err_ratelimited("Conditional branch offset 0x%lx (@%u) out of range\n", offset, ctx->idx); \ return -ERANGE; \
@@ -92,12 +94,12 @@* state. */ #define PPC_BCC (cond, dest) do { \ - if (is_offset_in_cond_branch_range((long)(dest) - (ctx->idx * 4))) { \ + if (is_offset_in_cond_branch_range((long)(dest) - CTX_NIA(ctx))) { \ PPC_BCC_SHORT(cond, dest); \ EMIT(PPC_RAW_NOP()); \ } else { \/* Flip the 'T or F' bit to invert comparison */ \ -PPC_BCC_SHORT (cond ^COND_CMP_TRUE , (ctx->idx+2 )*4 ); \ +PPC_BCC_SHORT (cond ^COND_CMP_TRUE ,CTX_NIA (ctx) +2 *4 ); \PPC_JMP (dest); \ } } while(0)
arch/powerpc/net/bpf_jit_comp64.c +26 -9
@@ -126,8 +126,10 @@ void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx) {int i; +#ifndef CONFIG_PPC_KERNEL_PCREL if (IS_ENABLED (CONFIG_PPC64_ELF_ABI_V2 ))EMIT (PPC_RAW_LD (_R2, _R13, offsetof(struct paca_struct , kernel_toc))); +#endif /* * Initialize tail_call_cnt if we do tail calls.
@@ -208,16 +210,31 @@ static int bpf_jit_emit_func_call_hlp(u32 *image, struct codegen_context *ctx, uif (WARN_ON_ONCE (!core_kernel_text (func_addr)))return -EINVAL ; - reladdr = func_addr -kernel_toc_addr (); -if (reladdr >0x7FFFFFFF || reladdr < -(0x80000000L )) { -pr_err ("eBPF: address of %ps out of range of kernel_toc.\n" , (void *)func); -return -ERANGE ; - } +if (IS_ENABLED (CONFIG_PPC_KERNEL_PCREL )) { + reladdr = func_addr -CTX_NIA (ctx); -EMIT (PPC_RAW_ADDIS (_R12, _R2,PPC_HA (reladdr))); -EMIT (PPC_RAW_ADDI (_R12, _R12,PPC_LO (reladdr))); -EMIT (PPC_RAW_MTCTR (_R12)); -EMIT (PPC_RAW_BCTRL ()); +if (reladdr >= (long )SZ_8G || reladdr < -(long )SZ_8G ) { +pr_err ("eBPF: address of %ps out of range of pcrel address.\n" , (void *)func); +return -ERANGE ; + } +/* pla r12,addr */ +EMIT (PPC_PREFIX_MLS |__PPC_PRFX_R (1 ) |IMM_H18 (reladdr)); +EMIT (PPC_INST_PADDI |___PPC_RT (_R12) |IMM_L (reladdr)); +EMIT (PPC_RAW_MTCTR (_R12)); +EMIT (PPC_RAW_BCTR ()); + + }else { + reladdr = func_addr -kernel_toc_addr (); +if (reladdr >0x7FFFFFFF || reladdr < -(0x80000000L )) { +pr_err ("eBPF: address of %ps out of range of kernel_toc.\n" , (void *)func); +return -ERANGE ; + } + +EMIT (PPC_RAW_ADDIS (_R12, _R2,PPC_HA (reladdr))); +EMIT (PPC_RAW_ADDI (_R12, _R12,PPC_LO (reladdr))); +EMIT (PPC_RAW_MTCTR (_R12)); +EMIT (PPC_RAW_BCTRL ()); + }return 0 ; }
arch/powerpc/platforms/Kconfig.cputype +18 -0
@@ -181,6 +181,7 @@ config POWER10_CPU depends on PPC_BOOK3S_64 select ARCH_HAS_FAST_MULTIPLIER select PPC_HAVE_PREFIXED_SUPPORT + select PPC_HAVE_PCREL_SUPPORT config E5500_CPU bool "Freescale e5500"
@@ -471,6 +472,20 @@ config PPC_KERNEL_PREFIXED Kernel support for prefixed instructions in applications and guests is not affected by this option. +config PPC_KERNEL_PCREL + depends on PPC_HAVE_PCREL_SUPPORT + depends on PPC_HAVE_PREFIXED_SUPPORT + depends on CC_HAS_PCREL + default n + select PPC_KERNEL_PREFIXED + bool "Build Kernel with PC-Relative addressing model" + help + POWER10 and later CPUs support pc relative addressing. Recent + compilers have support for an ELF ABI extension for a pc relative + ABI. + + This option builds the kernel with the pc relative ABI model. + config PPC_KUEP bool "Kernel Userspace Execution Prevention" if !40x default y if !40x
@@ -510,6 +525,9 @@ config PPC_HAVE_PMU_SUPPORT config PPC_HAVE_PREFIXED_SUPPORT bool +config PPC_HAVE_PCREL_SUPPORT + bool + config PMU_SYSFS bool "Create PMU SPRs sysfs file" default n
arch/powerpc/xmon/xmon.c +2 -0
@@ -2634,7 +2634,9 @@ static void dump_one_paca(int cpu)DUMP (p, lock_token,"%#-*x" );DUMP (p, paca_index,"%#-*x" ); +#ifndef CONFIG_PPC_KERNEL_PCREL DUMP (p, kernel_toc,"%#-*llx" ); +#endif DUMP (p, kernelbase,"%#-*llx" );DUMP (p, kernel_msr,"%#-*llx" );DUMP (p, emergency_sp,"%-*px" );
Signature · 1 line
2.40.0
Nicholas Piggin
reviewerPATCH 6/6 powerpc/64: modules support building with PCREL addresing
In reply to Nicholas PigginBuild modules using PCREL addressing when CONFIG_PPC_KERNEL_PCREL=y.
- The module loader must handle several new relocation types:
* R_PPC64_REL24_NOTOC is a function call handled like R_PPC_REL24, but does not restore r2 upon return. The external function call stub is changed to use pcrel addressing to load the function pointer rather than based on the module TOC.
* R_PPC64_GOT_PCREL34 is a reference to external data. A GOT table must be built by hand, because the linker adds this during the final link (which is not done for kernel modules). The GOT table is built similarly to the way the external function call stub table is. This section is called .mygot because .got has a special meaning for the linker and can become upset.
* R_PPC64_PCREL34 is used for local data addressing, but there is a special case where the percpu section is moved at load-time to the percpu area which is out of range of this relocation. This requires the PCREL34 relocations are converted to use GOT_PCREL34 addressing.
--- arch/powerpc/Makefile | 5 +- arch/powerpc/include/asm/module.h | 10 +- arch/powerpc/include/asm/ppc_asm.h | 6 +- arch/powerpc/include/uapi/asm/elf.h | 4 + arch/powerpc/kernel/module_64.c | 318 +++++++++++++++++++++++++--- 5 files changed, 309 insertions(+), 34 deletions(-)
arch/powerpc/Makefile +2 -3
@@ -107,9 +107,7 @@ LDFLAGS_vmlinux-$(CONFIG_RELOCATABLE) += -z notext LDFLAGS_vmlinux := $(LDFLAGS_vmlinux-y) ifdef CONFIG_PPC64 -ifdef CONFIG_PPC_KERNEL_PCREL - KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-pcrel) -endif +ifndef CONFIG_PPC_KERNEL_PCREL ifeq ($(call cc-option-yn,-mcmodel=medium),y) # -mcmodel=medium breaks modules because it uses 32bit offsets from # the TOC pointer to create pointers where possible. Pointers into the
@@ -124,6 +122,7 @@ else export NO_MINIMAL_TOC := -mno-minimal-toc endif endif +endif CFLAGS-$(CONFIG_PPC64) := $(call cc-option,-mtraceback=no) ifndef CONFIG_CC_IS_CLANG
arch/powerpc/include/asm/module.h +9 -1
@@ -27,8 +27,13 @@ struct ppc_plt_entry {struct mod_arch_specific {#ifdef __powerpc64__unsigned int stubs_section;/* Index of stubs section in module */ +#ifdef CONFIG_PPC_KERNEL_PCREL +unsigned int got_section;/* What section is the GOT? */ +unsigned int pcpu_section;/* .data..percpu section */ +#else unsigned int toc_section;/* What section is the TOC? */ bool toc_fixed;/* Have we fixed up .TOC.? */ +#endif /* For module function descriptor dereference */ unsigned long start_opd;
@@ -52,12 +57,15 @@ struct mod_arch_specific {/* * Select ELF headers. -* Make empty section for module_frob_arch_sections to expand. +* Make empty sections for module_frob_arch_sections to expand. */ #ifdef __powerpc64__# ifdef MODULE asm(".section .stubs,\"ax\",@nobits; .align 3; .previous" ); +# ifdef CONFIG_PPC_KERNEL_PCREL + asm(".section .mygot,\"a\",@nobits; .align 3; .previous" ); +# endif # endif #else # ifdef MODULE
arch/powerpc/include/asm/ppc_asm.h +3 -3
@@ -183,7 +183,7 @@/* * Used to name C functions called from asm */ -#if defined(CONFIG_PPC_KERNEL_PCREL ) && !defined(MODULE ) +#ifdef CONFIG_PPC_KERNEL_PCREL #define CFUNC (name) name@notoc#else #define CFUNC (name) name
@@ -216,7 +216,7 @@ .globl name; \ name: -#if defined(CONFIG_PPC_KERNEL_PCREL ) && !defined(MODULE ) +#ifdef CONFIG_PPC_KERNEL_PCREL #define _GLOBAL_TOC _GLOBAL#else #define _GLOBAL_TOC (name) \
@@ -379,7 +379,7 @@ GLUE(.,name): ori reg, reg, (expr)@l; \ rldimi reg, tmp, 32, 0 -#if defined(CONFIG_PPC_KERNEL_PCREL ) && !defined(MODULE ) +#ifdef CONFIG_PPC_KERNEL_PCREL #define LOAD_REG_ADDR(reg,name) \ pla reg,name@pcrel
arch/powerpc/include/uapi/asm/elf.h +4 -0
@@ -279,8 +279,12 @@ typedef elf_fpreg_t elf_vsrreghalf_t32[ELF_NVSRHALFREG];#define R_PPC64_TLSLD 108#define R_PPC64_TOCSAVE 109 +#define R_PPC64_REL24_NOTOC 116#define R_PPC64_ENTRY 118 +#define R_PPC64_PCREL34 132 +#define R_PPC64_GOT_PCREL34 133 +#define R_PPC64_REL16 249#define R_PPC64_REL16_LO 250#define R_PPC64_REL16_HI 251
arch/powerpc/kernel/module_64.c +291 -27
473 lines not on this page · raw message
Signature · 1 line
2.40.0
Michael Ellerman
AppliedQuoted 8 lines · Nicholas Piggin
This won't see a lot of real use until POWER10 is the oldest supported CPU for distros, but being as we're quite a unique user of toolchain I'd like to start ironing things out earlier rather than later. I'm making a list of observations here, https://github.com/linuxppc/issues/issues/455
and will take them to toolchan developers after the kernel work is a bit further along.[...]
Applied to powerpc/next.
[1/6] powerpc/64: Move initial base and TOC pointer calculation
https://git.kernel.org/powerpc/c/4f18b9e6ca58440394e86a53bf1be0d8a1920bcd [2/6] powerpc/64s: Run at the kernel virtual address earlier in boot https://git.kernel.org/powerpc/c/b270bebd34e36fb69363d65e24b00a9d148903e8 [3/6] powerpc/64: Add support to build with prefixed instructions https://git.kernel.org/powerpc/c/dc5dac748af9087e9240bd2ae6ae7db48d5360ae [4/6] powerpc: add CFUNC assembly label annotation https://git.kernel.org/powerpc/c/4e991e3c16a350d1eeffc100ce3fb25292596d03 [5/6] powerpc/64: vmlinux support building with PCREL addresing https://git.kernel.org/powerpc/c/7e3a68be42e10f5fa5890e97afc0afd992355bc3 [6/6] powerpc/64: modules support building with PCREL addresing https://git.kernel.org/powerpc/c/77e69ee7ce0715c39b9a0cde68ff44fe467435ef
cheers