Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/64: Add support to build with prefixed instructions

Add 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.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20230408021752.862660-4-npiggin@gmail.com

authored by

Nicholas Piggin and committed by
Michael Ellerman
dc5dac74 b270bebd

+112 -6
+3
arch/powerpc/Kconfig
··· 4 4 config CC_HAS_ELFV2 5 5 def_bool PPC64 && $(cc-option, -mabi=elfv2) 6 6 7 + config CC_HAS_PREFIXED 8 + def_bool PPC64 && $(cc-option, -mcpu=power10 -mprefixed) 9 + 7 10 config 32BIT 8 11 bool 9 12 default y if PPC32
+4
arch/powerpc/Makefile
··· 180 180 endif 181 181 182 182 # No prefix or pcrel 183 + ifdef CONFIG_PPC_KERNEL_PREFIXED 184 + KBUILD_CFLAGS += $(call cc-option,-mprefixed) 185 + else 183 186 KBUILD_CFLAGS += $(call cc-option,-mno-prefixed) 187 + endif 184 188 KBUILD_CFLAGS += $(call cc-option,-mno-pcrel) 185 189 186 190 # No AltiVec or VSX or MMA instructions when building kernel
+20 -4
arch/powerpc/include/asm/atomic.h
··· 27 27 { 28 28 int t; 29 29 30 - __asm__ __volatile__("lwz%U1%X1 %0,%1" : "=r"(t) : "m<>"(v->counter)); 30 + /* -mprefixed can generate offsets beyond range, fall back hack */ 31 + if (IS_ENABLED(CONFIG_PPC_KERNEL_PREFIXED)) 32 + __asm__ __volatile__("lwz %0,0(%1)" : "=r"(t) : "b"(&v->counter)); 33 + else 34 + __asm__ __volatile__("lwz%U1%X1 %0,%1" : "=r"(t) : "m<>"(v->counter)); 31 35 32 36 return t; 33 37 } 34 38 35 39 static __inline__ void arch_atomic_set(atomic_t *v, int i) 36 40 { 37 - __asm__ __volatile__("stw%U0%X0 %1,%0" : "=m<>"(v->counter) : "r"(i)); 41 + /* -mprefixed can generate offsets beyond range, fall back hack */ 42 + if (IS_ENABLED(CONFIG_PPC_KERNEL_PREFIXED)) 43 + __asm__ __volatile__("stw %1,0(%2)" : "=m"(v->counter) : "r"(i), "b"(&v->counter)); 44 + else 45 + __asm__ __volatile__("stw%U0%X0 %1,%0" : "=m<>"(v->counter) : "r"(i)); 38 46 } 39 47 40 48 #define ATOMIC_OP(op, asm_op, suffix, sign, ...) \ ··· 205 197 { 206 198 s64 t; 207 199 208 - __asm__ __volatile__("ld%U1%X1 %0,%1" : "=r"(t) : "m<>"(v->counter)); 200 + /* -mprefixed can generate offsets beyond range, fall back hack */ 201 + if (IS_ENABLED(CONFIG_PPC_KERNEL_PREFIXED)) 202 + __asm__ __volatile__("ld %0,0(%1)" : "=r"(t) : "b"(&v->counter)); 203 + else 204 + __asm__ __volatile__("ld%U1%X1 %0,%1" : "=r"(t) : "m<>"(v->counter)); 209 205 210 206 return t; 211 207 } 212 208 213 209 static __inline__ void arch_atomic64_set(atomic64_t *v, s64 i) 214 210 { 215 - __asm__ __volatile__("std%U0%X0 %1,%0" : "=m<>"(v->counter) : "r"(i)); 211 + /* -mprefixed can generate offsets beyond range, fall back hack */ 212 + if (IS_ENABLED(CONFIG_PPC_KERNEL_PREFIXED)) 213 + __asm__ __volatile__("std %1,0(%2)" : "=m"(v->counter) : "r"(i), "b"(&v->counter)); 214 + else 215 + __asm__ __volatile__("std%U0%X0 %1,%0" : "=m<>"(v->counter) : "r"(i)); 216 216 } 217 217 218 218 #define ATOMIC64_OP(op, asm_op) \
+37
arch/powerpc/include/asm/io.h
··· 97 97 * 98 98 */ 99 99 100 + /* -mprefixed can generate offsets beyond range, fall back hack */ 101 + #ifdef CONFIG_PPC_KERNEL_PREFIXED 102 + #define DEF_MMIO_IN_X(name, size, insn) \ 103 + static inline u##size name(const volatile u##size __iomem *addr) \ 104 + { \ 105 + u##size ret; \ 106 + __asm__ __volatile__("sync;"#insn" %0,0,%1;twi 0,%0,0;isync" \ 107 + : "=r" (ret) : "r" (addr) : "memory"); \ 108 + return ret; \ 109 + } 110 + 111 + #define DEF_MMIO_OUT_X(name, size, insn) \ 112 + static inline void name(volatile u##size __iomem *addr, u##size val) \ 113 + { \ 114 + __asm__ __volatile__("sync;"#insn" %1,0,%0" \ 115 + : : "r" (addr), "r" (val) : "memory"); \ 116 + mmiowb_set_pending(); \ 117 + } 118 + 119 + #define DEF_MMIO_IN_D(name, size, insn) \ 120 + static inline u##size name(const volatile u##size __iomem *addr) \ 121 + { \ 122 + u##size ret; \ 123 + __asm__ __volatile__("sync;"#insn" %0,0(%1);twi 0,%0,0;isync"\ 124 + : "=r" (ret) : "b" (addr) : "memory"); \ 125 + return ret; \ 126 + } 127 + 128 + #define DEF_MMIO_OUT_D(name, size, insn) \ 129 + static inline void name(volatile u##size __iomem *addr, u##size val) \ 130 + { \ 131 + __asm__ __volatile__("sync;"#insn" %1,0(%0)" \ 132 + : : "b" (addr), "r" (val) : "memory"); \ 133 + mmiowb_set_pending(); \ 134 + } 135 + #else 100 136 #define DEF_MMIO_IN_X(name, size, insn) \ 101 137 static inline u##size name(const volatile u##size __iomem *addr) \ 102 138 { \ ··· 166 130 : "=m<>" (*addr) : "r" (val) : "memory"); \ 167 131 mmiowb_set_pending(); \ 168 132 } 133 + #endif 169 134 170 135 DEF_MMIO_IN_D(in_8, 8, lbz); 171 136 DEF_MMIO_OUT_D(out_8, 8, stb);
+26 -2
arch/powerpc/include/asm/uaccess.h
··· 71 71 * because we do not write to any memory gcc knows about, so there 72 72 * are no aliasing issues. 73 73 */ 74 + /* -mprefixed can generate offsets beyond range, fall back hack */ 75 + #ifdef CONFIG_PPC_KERNEL_PREFIXED 76 + #define __put_user_asm_goto(x, addr, label, op) \ 77 + asm_volatile_goto( \ 78 + "1: " op " %0,0(%1) # put_user\n" \ 79 + EX_TABLE(1b, %l2) \ 80 + : \ 81 + : "r" (x), "b" (addr) \ 82 + : \ 83 + : label) 84 + #else 74 85 #define __put_user_asm_goto(x, addr, label, op) \ 75 86 asm_volatile_goto( \ 76 87 "1: " op "%U1%X1 %0,%1 # put_user\n" \ 77 88 EX_TABLE(1b, %l2) \ 78 89 : \ 79 - : "r" (x), "m<>" (*addr) \ 90 + : "r" (x), "m<>" (*addr) \ 80 91 : \ 81 92 : label) 93 + #endif 82 94 83 95 #ifdef __powerpc64__ 84 96 #define __put_user_asm2_goto(x, ptr, label) \ ··· 143 131 144 132 #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT 145 133 134 + /* -mprefixed can generate offsets beyond range, fall back hack */ 135 + #ifdef CONFIG_PPC_KERNEL_PREFIXED 136 + #define __get_user_asm_goto(x, addr, label, op) \ 137 + asm_volatile_goto( \ 138 + "1: "op" %0,0(%1) # get_user\n" \ 139 + EX_TABLE(1b, %l2) \ 140 + : "=r" (x) \ 141 + : "b" (addr) \ 142 + : \ 143 + : label) 144 + #else 146 145 #define __get_user_asm_goto(x, addr, label, op) \ 147 146 asm_volatile_goto( \ 148 147 "1: "op"%U1%X1 %0, %1 # get_user\n" \ 149 148 EX_TABLE(1b, %l2) \ 150 149 : "=r" (x) \ 151 - : "m<>" (*addr) \ 150 + : "m<>" (*addr) \ 152 151 : \ 153 152 : label) 153 + #endif 154 154 155 155 #ifdef __powerpc64__ 156 156 #define __get_user_asm2_goto(x, addr, label) \
+2
arch/powerpc/kernel/trace/ftrace.c
··· 194 194 * get corrupted. 195 195 * 196 196 * Use a b +8 to jump over the load. 197 + * XXX: could make PCREL depend on MPROFILE_KERNEL 198 + * XXX: check PCREL && MPROFILE_KERNEL calling sequence 197 199 */ 198 200 if (IS_ENABLED(CONFIG_MPROFILE_KERNEL) || IS_ENABLED(CONFIG_PPC32)) 199 201 pop = ppc_inst(PPC_RAW_NOP());
+20
arch/powerpc/platforms/Kconfig.cputype
··· 180 180 bool "POWER10" 181 181 depends on PPC_BOOK3S_64 182 182 select ARCH_HAS_FAST_MULTIPLIER 183 + select PPC_HAVE_PREFIXED_SUPPORT 183 184 184 185 config E5500_CPU 185 186 bool "Freescale e5500" ··· 455 454 456 455 If you're unsure, say Y. 457 456 457 + config PPC_KERNEL_PREFIXED 458 + depends on PPC_HAVE_PREFIXED_SUPPORT 459 + depends on CC_HAS_PREFIXED 460 + default n 461 + bool "Build Kernel with Prefixed Instructions" 462 + help 463 + POWER10 and later CPUs support prefixed instructions, 8 byte 464 + instructions that include large immediate, pc relative addressing, 465 + and various floating point, vector, MMA. 466 + 467 + This option builds the kernel with prefixed instructions, and 468 + allows a pc relative addressing option to be selected. 469 + 470 + Kernel support for prefixed instructions in applications and guests 471 + is not affected by this option. 472 + 458 473 config PPC_KUEP 459 474 bool "Kernel Userspace Execution Prevention" if !40x 460 475 default y if !40x ··· 505 488 depends on !PPC_BOOK3S 506 489 507 490 config PPC_HAVE_PMU_SUPPORT 491 + bool 492 + 493 + config PPC_HAVE_PREFIXED_SUPPORT 508 494 bool 509 495 510 496 config PMU_SYSFS