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

Merge tag 'powerpc-5.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux

Pull powerpc updates from Michael Ellerman:
"Livepatch support for 32-bit is probably the standout new feature,
otherwise mostly just lots of bits and pieces all over the board.

There's a series of commits cleaning up function descriptor handling,
which touches a few other arches as well as LKDTM. It has acks from
Arnd, Kees and Helge.

Summary:

- Enforce kernel RO, and implement STRICT_MODULE_RWX for 603.

- Add support for livepatch to 32-bit.

- Implement CONFIG_DYNAMIC_FTRACE_WITH_ARGS.

- Merge vdso64 and vdso32 into a single directory.

- Fix build errors with newer binutils.

- Add support for UADDR64 relocations, which are emitted by some
toolchains. This allows powerpc to build with the latest lld.

- Fix (another) potential userspace r13 corruption in transactional
memory handling.

- Cleanups of function descriptor handling & related fixes to LKDTM.

Thanks to Abdul Haleem, Alexey Kardashevskiy, Anders Roxell, Aneesh
Kumar K.V, Anton Blanchard, Arnd Bergmann, Athira Rajeev, Bhaskar
Chowdhury, Cédric Le Goater, Chen Jingwen, Christophe JAILLET,
Christophe Leroy, Corentin Labbe, Daniel Axtens, Daniel Henrique
Barboza, David Dai, Fabiano Rosas, Ganesh Goudar, Guo Zhengkui, Hangyu
Hua, Haren Myneni, Hari Bathini, Igor Zhbanov, Jakob Koschel, Jason
Wang, Jeremy Kerr, Joachim Wiberg, Jordan Niethe, Julia Lawall, Kajol
Jain, Kees Cook, Laurent Dufour, Madhavan Srinivasan, Mamatha Inamdar,
Maxime Bizon, Maxim Kiselev, Maxim Kochetkov, Michal Suchanek,
Nageswara R Sastry, Nathan Lynch, Naveen N. Rao, Nicholas Piggin,
Nour-eddine Taleb, Paul Menzel, Ping Fang, Pratik R. Sampat, Randy
Dunlap, Ritesh Harjani, Rohan McLure, Russell Currey, Sachin Sant,
Segher Boessenkool, Shivaprasad G Bhat, Sourabh Jain, Thierry Reding,
Tobias Waldekranz, Tyrel Datwyler, Vaibhav Jain, Vladimir Oltean,
Wedson Almeida Filho, and YueHaibing"

* tag 'powerpc-5.18-1' of git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux: (179 commits)
powerpc/pseries: Fix use after free in remove_phb_dynamic()
powerpc/time: improve decrementer clockevent processing
powerpc/time: Fix KVM host re-arming a timer beyond decrementer range
powerpc/tm: Fix more userspace r13 corruption
powerpc/xive: fix return value of __setup handler
powerpc/64: Add UADDR64 relocation support
powerpc: 8xx: fix a return value error in mpc8xx_pic_init
powerpc/ps3: remove unneeded semicolons
powerpc/64: Force inlining of prevent_user_access() and set_kuap()
powerpc/bitops: Force inlining of fls()
powerpc: declare unmodified attribute_group usages const
powerpc/spufs: Fix build warning when CONFIG_PROC_FS=n
powerpc/secvar: fix refcount leak in format_show()
powerpc/64e: Tie PPC_BOOK3E_64 to PPC_FSL_BOOK3E
powerpc: Move C prototypes out of asm-prototypes.h
powerpc/kexec: Declare kexec_paca static
powerpc/smp: Declare current_set static
powerpc: Cleanup asm-prototypes.c
powerpc/ftrace: Use STK_GOT in ftrace_mprofile.S
powerpc/ftrace: Regroup PPC64 specific operations in ftrace_mprofile.S
...

+4963 -2268
+12
Documentation/ABI/testing/sysfs-bus-papr-pmem
··· 61 61 * "CchRHCnt" : Cache Read Hit Count 62 62 * "CchWHCnt" : Cache Write Hit Count 63 63 * "FastWCnt" : Fast Write Count 64 + 65 + What: /sys/bus/nd/devices/nmemX/papr/health_bitmap_inject 66 + Date: Jan, 2022 67 + KernelVersion: v5.17 68 + Contact: linuxppc-dev <linuxppc-dev@lists.ozlabs.org>, nvdimm@lists.linux.dev, 69 + Description: 70 + (RO) Reports the health bitmap inject bitmap that is applied to 71 + bitmap received from PowerVM via the H_SCM_HEALTH. This is used 72 + to forcibly set specific bits returned from Hcall. These is then 73 + used to simulate various health or shutdown states for an nvdimm 74 + and are set by user-space tools like ndctl by issuing a PAPR DSM. 75 +
+29
Documentation/ABI/testing/sysfs-firmware-papr-energy-scale-info
··· 1 + What: /sys/firmware/papr/energy_scale_info 2 + Date: February 2022 3 + Contact: Linux for PowerPC mailing list <linuxppc-dev@ozlabs.org> 4 + Description: Directory hosting a set of platform attributes like 5 + energy/frequency on Linux running as a PAPR guest. 6 + 7 + Each file in a directory contains a platform 8 + attribute hierarchy pertaining to performance/ 9 + energy-savings mode and processor frequency. 10 + 11 + What: /sys/firmware/papr/energy_scale_info/<id> 12 + Date: February 2022 13 + Contact: Linux for PowerPC mailing list <linuxppc-dev@ozlabs.org> 14 + Description: Energy, frequency attributes directory for POWERVM servers 15 + 16 + What: /sys/firmware/papr/energy_scale_info/<id>/desc 17 + Date: February 2022 18 + Contact: Linux for PowerPC mailing list <linuxppc-dev@ozlabs.org> 19 + Description: String description of the energy attribute of <id> 20 + 21 + What: /sys/firmware/papr/energy_scale_info/<id>/value 22 + Date: February 2022 23 + Contact: Linux for PowerPC mailing list <linuxppc-dev@ozlabs.org> 24 + Description: Numeric value of the energy attribute of <id> 25 + 26 + What: /sys/firmware/papr/energy_scale_info/<id>/value_desc 27 + Date: February 2022 28 + Contact: Linux for PowerPC mailing list <linuxppc-dev@ozlabs.org> 29 + Description: String value of the energy attribute of <id>
+3
arch/Kconfig
··· 202 202 config HAVE_NMI 203 203 bool 204 204 205 + config HAVE_FUNCTION_DESCRIPTORS 206 + bool 207 + 205 208 config TRACE_IRQFLAGS_SUPPORT 206 209 bool 207 210
+1
arch/ia64/Kconfig
··· 36 36 select HAVE_SETUP_PER_CPU_AREA 37 37 select TTY 38 38 select HAVE_ARCH_TRACEHOOK 39 + select HAVE_FUNCTION_DESCRIPTORS 39 40 select HAVE_VIRT_CPU_ACCOUNTING 40 41 select HUGETLB_PAGE_SIZE_VARIABLE if HUGETLB_PAGE 41 42 select VIRT_TO_BUS
+1 -1
arch/ia64/include/asm/elf.h
··· 226 226 * Layout of the Function Descriptor 227 227 */ 228 228 struct fdesc { 229 - uint64_t ip; 229 + uint64_t addr; 230 230 uint64_t gp; 231 231 }; 232 232
+3 -21
arch/ia64/include/asm/sections.h
··· 9 9 10 10 #include <linux/elf.h> 11 11 #include <linux/uaccess.h> 12 + 13 + typedef struct fdesc func_desc_t; 14 + 12 15 #include <asm-generic/sections.h> 13 16 14 17 extern char __phys_per_cpu_start[]; ··· 29 26 extern char __start_gate_brl_fsys_bubble_down_patchlist[], __end_gate_brl_fsys_bubble_down_patchlist[]; 30 27 extern char __start_unwind[], __end_unwind[]; 31 28 extern char __start_ivt_text[], __end_ivt_text[]; 32 - 33 - #define HAVE_DEREFERENCE_FUNCTION_DESCRIPTOR 1 34 - 35 - #undef dereference_function_descriptor 36 - static inline void *dereference_function_descriptor(void *ptr) 37 - { 38 - struct fdesc *desc = ptr; 39 - void *p; 40 - 41 - if (!get_kernel_nofault(p, (void *)&desc->ip)) 42 - ptr = p; 43 - return ptr; 44 - } 45 - 46 - #undef dereference_kernel_function_descriptor 47 - static inline void *dereference_kernel_function_descriptor(void *ptr) 48 - { 49 - if (ptr < (void *)__start_opd || ptr >= (void *)__end_opd) 50 - return ptr; 51 - return dereference_function_descriptor(ptr); 52 - } 53 29 54 30 #endif /* _ASM_IA64_SECTIONS_H */
+3 -3
arch/ia64/kernel/module.c
··· 602 602 return value; 603 603 604 604 /* Look for existing function descriptor. */ 605 - while (fdesc->ip) { 606 - if (fdesc->ip == value) 605 + while (fdesc->addr) { 606 + if (fdesc->addr == value) 607 607 return (uint64_t)fdesc; 608 608 if ((uint64_t) ++fdesc >= mod->arch.opd->sh_addr + mod->arch.opd->sh_size) 609 609 BUG(); 610 610 } 611 611 612 612 /* Create new one */ 613 - fdesc->ip = value; 613 + fdesc->addr = value; 614 614 fdesc->gp = mod->arch.gp; 615 615 return (uint64_t) fdesc; 616 616 }
+1
arch/parisc/Kconfig
··· 72 72 select HAVE_DYNAMIC_FTRACE_WITH_REGS 73 73 select HAVE_SOFTIRQ_ON_OWN_STACK if IRQSTACKS 74 74 select TRACE_IRQFLAGS_SUPPORT 75 + select HAVE_FUNCTION_DESCRIPTORS if 64BIT 75 76 76 77 help 77 78 The PA-RISC microprocessor is designed by Hewlett-Packard and used
+5 -11
arch/parisc/include/asm/sections.h
··· 2 2 #ifndef _PARISC_SECTIONS_H 3 3 #define _PARISC_SECTIONS_H 4 4 5 + #ifdef CONFIG_HAVE_FUNCTION_DESCRIPTORS 6 + #include <asm/elf.h> 7 + typedef Elf64_Fdesc func_desc_t; 8 + #endif 9 + 5 10 /* nothing to see, move along */ 6 11 #include <asm-generic/sections.h> 7 12 8 13 extern char __alt_instructions[], __alt_instructions_end[]; 9 - 10 - #ifdef CONFIG_64BIT 11 - 12 - #define HAVE_DEREFERENCE_FUNCTION_DESCRIPTOR 1 13 - 14 - #undef dereference_function_descriptor 15 - void *dereference_function_descriptor(void *); 16 - 17 - #undef dereference_kernel_function_descriptor 18 - void *dereference_kernel_function_descriptor(void *); 19 - #endif 20 14 21 15 #endif
-21
arch/parisc/kernel/process.c
··· 263 263 return 0; 264 264 } 265 265 266 - #ifdef CONFIG_64BIT 267 - void *dereference_function_descriptor(void *ptr) 268 - { 269 - Elf64_Fdesc *desc = ptr; 270 - void *p; 271 - 272 - if (!get_kernel_nofault(p, (void *)&desc->addr)) 273 - ptr = p; 274 - return ptr; 275 - } 276 - 277 - void *dereference_kernel_function_descriptor(void *ptr) 278 - { 279 - if (ptr < (void *)__start_opd || 280 - ptr >= (void *)__end_opd) 281 - return ptr; 282 - 283 - return dereference_function_descriptor(ptr); 284 - } 285 - #endif 286 - 287 266 static inline unsigned long brk_rnd(void) 288 267 { 289 268 return (get_random_int() & BRK_RND_MASK) << PAGE_SHIFT;
+8 -2
arch/powerpc/Kconfig
··· 9 9 bool 10 10 default y if PPC64 11 11 12 + config LIVEPATCH_64 13 + def_bool PPC64 14 + depends on LIVEPATCH 15 + 12 16 config MMU 13 17 bool 14 18 default y ··· 136 132 select ARCH_HAS_SET_MEMORY 137 133 select ARCH_HAS_STRICT_KERNEL_RWX if (PPC_BOOK3S || PPC_8xx || 40x) && !HIBERNATION 138 134 select ARCH_HAS_STRICT_KERNEL_RWX if FSL_BOOKE && !HIBERNATION && !RANDOMIZE_BASE 139 - select ARCH_HAS_STRICT_MODULE_RWX if ARCH_HAS_STRICT_KERNEL_RWX && !PPC_BOOK3S_32 135 + select ARCH_HAS_STRICT_MODULE_RWX if ARCH_HAS_STRICT_KERNEL_RWX 140 136 select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST 141 137 select ARCH_HAS_UACCESS_FLUSHCACHE 142 138 select ARCH_HAS_UBSAN_SANITIZE_ALL ··· 202 198 select HAVE_DEBUG_KMEMLEAK 203 199 select HAVE_DEBUG_STACKOVERFLOW 204 200 select HAVE_DYNAMIC_FTRACE 201 + select HAVE_DYNAMIC_FTRACE_WITH_ARGS if MPROFILE_KERNEL || PPC32 205 202 select HAVE_DYNAMIC_FTRACE_WITH_REGS if MPROFILE_KERNEL || PPC32 206 203 select HAVE_EBPF_JIT 207 204 select HAVE_EFFICIENT_UNALIGNED_ACCESS if !(CPU_LITTLE_ENDIAN && POWER7_CPU) 208 205 select HAVE_FAST_GUP 209 206 select HAVE_FTRACE_MCOUNT_RECORD 207 + select HAVE_FUNCTION_DESCRIPTORS if PPC64 && !CPU_LITTLE_ENDIAN 210 208 select HAVE_FUNCTION_ERROR_INJECTION 211 209 select HAVE_FUNCTION_GRAPH_TRACER 212 210 select HAVE_FUNCTION_TRACER ··· 228 222 select HAVE_KPROBES_ON_FTRACE 229 223 select HAVE_KRETPROBES 230 224 select HAVE_LD_DEAD_CODE_DATA_ELIMINATION 231 - select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS && PPC64 225 + select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS 232 226 select HAVE_MOD_ARCH_SPECIFIC 233 227 select HAVE_NMI if PERF_EVENTS || (PPC64 && PPC_BOOK3S) 234 228 select HAVE_OPTPROBES
+4 -4
arch/powerpc/Makefile
··· 171 171 CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power7,$(call cc-option,-mtune=power5)) 172 172 CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mcpu=power5,-mcpu=power4) 173 173 endif 174 - else 174 + else ifdef CONFIG_PPC_BOOK3E_64 175 175 CFLAGS-$(CONFIG_GENERIC_CPU) += -mcpu=powerpc64 176 176 endif 177 177 ··· 213 213 ifdef CONFIG_CPU_BIG_ENDIAN 214 214 CHECKFLAGS += -D__BIG_ENDIAN__ 215 215 else 216 - CHECKFLAGS += -D__LITTLE_ENDIAN__ 216 + CHECKFLAGS += -D__LITTLE_ENDIAN__ -D_CALL_ELF=2 217 217 endif 218 218 219 219 ifdef CONFIG_476FPE_ERR46 ··· 421 421 prepare: vdso_prepare 422 422 vdso_prepare: prepare0 423 423 $(if $(CONFIG_VDSO32),$(Q)$(MAKE) \ 424 - $(build)=arch/powerpc/kernel/vdso32 include/generated/vdso32-offsets.h) 424 + $(build)=arch/powerpc/kernel/vdso include/generated/vdso32-offsets.h) 425 425 $(if $(CONFIG_PPC64),$(Q)$(MAKE) \ 426 - $(build)=arch/powerpc/kernel/vdso64 include/generated/vdso64-offsets.h) 426 + $(build)=arch/powerpc/kernel/vdso include/generated/vdso64-offsets.h) 427 427 endif 428 428 429 429 archprepare: checkbin
+1
arch/powerpc/boot/.gitignore
··· 16 16 kernel-vmlinux.strip.gz 17 17 mktree 18 18 otheros.bld 19 + otheros-too-big.bld 19 20 uImage 20 21 cuImage.* 21 22 dtbImage.*
+30
arch/powerpc/boot/dts/fsl/t1040rdb-rev-a.dts
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * T1040RDB-REV-A Device Tree Source 4 + * 5 + * Copyright 2014 - 2015 Freescale Semiconductor Inc. 6 + * 7 + */ 8 + 9 + #include "t1040rdb.dts" 10 + 11 + / { 12 + model = "fsl,T1040RDB-REV-A"; 13 + compatible = "fsl,T1040RDB-REV-A"; 14 + }; 15 + 16 + &seville_port0 { 17 + label = "ETH5"; 18 + }; 19 + 20 + &seville_port2 { 21 + label = "ETH7"; 22 + }; 23 + 24 + &seville_port4 { 25 + label = "ETH9"; 26 + }; 27 + 28 + &seville_port6 { 29 + label = "ETH11"; 30 + };
+4 -4
arch/powerpc/boot/dts/fsl/t1040rdb.dts
··· 119 119 managed = "in-band-status"; 120 120 phy-handle = <&phy_qsgmii_0>; 121 121 phy-mode = "qsgmii"; 122 - label = "ETH5"; 122 + label = "ETH3"; 123 123 status = "okay"; 124 124 }; 125 125 ··· 135 135 managed = "in-band-status"; 136 136 phy-handle = <&phy_qsgmii_2>; 137 137 phy-mode = "qsgmii"; 138 - label = "ETH7"; 138 + label = "ETH5"; 139 139 status = "okay"; 140 140 }; 141 141 ··· 151 151 managed = "in-band-status"; 152 152 phy-handle = <&phy_qsgmii_4>; 153 153 phy-mode = "qsgmii"; 154 - label = "ETH9"; 154 + label = "ETH7"; 155 155 status = "okay"; 156 156 }; 157 157 ··· 167 167 managed = "in-band-status"; 168 168 phy-handle = <&phy_qsgmii_6>; 169 169 phy-mode = "qsgmii"; 170 - label = "ETH11"; 170 + label = "ETH9"; 171 171 status = "okay"; 172 172 }; 173 173
+2 -2
arch/powerpc/boot/dts/fsl/t104xrdb.dtsi
··· 139 139 fman@400000 { 140 140 ethernet@e6000 { 141 141 phy-handle = <&phy_rgmii_0>; 142 - phy-connection-type = "rgmii"; 142 + phy-connection-type = "rgmii-id"; 143 143 }; 144 144 145 145 ethernet@e8000 { 146 146 phy-handle = <&phy_rgmii_1>; 147 - phy-connection-type = "rgmii"; 147 + phy-connection-type = "rgmii-id"; 148 148 }; 149 149 150 150 mdio0: mdio@fc000 {
+1 -1
arch/powerpc/boot/dts/xpedite5200.dts
··· 132 132 reg = <0x68>; 133 133 }; 134 134 135 - dtt@48 { 135 + dtt@34 { 136 136 compatible = "maxim,max1237"; 137 137 reg = <0x34>; 138 138 };
+1 -1
arch/powerpc/boot/dts/xpedite5200_xmon.dts
··· 136 136 reg = <0x68>; 137 137 }; 138 138 139 - dtt@48 { 139 + dtt@34 { 140 140 compatible = "maxim,max1237"; 141 141 reg = <0x34>; 142 142 };
+2
arch/powerpc/include/asm/asm-compat.h
··· 21 21 #define PPC_STLCX stringify_in_c(stdcx.) 22 22 #define PPC_CNTLZL stringify_in_c(cntlzd) 23 23 #define PPC_MTOCRF(FXM, RS) MTOCRF((FXM), RS) 24 + #define PPC_SRL stringify_in_c(srd) 24 25 #define PPC_LR_STKOFF 16 25 26 #define PPC_MIN_STKFRM 112 26 27 ··· 55 54 #define PPC_STLCX stringify_in_c(stwcx.) 56 55 #define PPC_CNTLZL stringify_in_c(cntlzw) 57 56 #define PPC_MTOCRF stringify_in_c(mtcrf) 57 + #define PPC_SRL stringify_in_c(srw) 58 58 #define PPC_LR_STKOFF 4 59 59 #define PPC_MIN_STKFRM 16 60 60
-58
arch/powerpc/include/asm/asm-prototypes.h
··· 19 19 20 20 #include <uapi/asm/ucontext.h> 21 21 22 - /* SMP */ 23 - extern struct task_struct *current_set[NR_CPUS]; 24 - extern struct task_struct *secondary_current; 25 - void start_secondary(void *unused); 26 - 27 - /* kexec */ 28 - struct paca_struct; 29 - struct kimage; 30 - extern struct paca_struct kexec_paca; 31 - void kexec_copy_flush(struct kimage *image); 32 - 33 - /* pseries hcall tracing */ 34 - extern struct static_key hcall_tracepoint_key; 35 - void __trace_hcall_entry(unsigned long opcode, unsigned long *args); 36 - void __trace_hcall_exit(long opcode, long retval, unsigned long *retbuf); 37 - 38 22 /* Ultravisor */ 39 23 #if defined(CONFIG_PPC_POWERNV) || defined(CONFIG_PPC_SVM) 40 24 long ucall_norets(unsigned long opcode, ...); ··· 34 50 int64_t a4, int64_t a5, int64_t a6, int64_t a7, 35 51 int64_t opcode, uint64_t msr); 36 52 37 - /* VMX copying */ 38 - int enter_vmx_usercopy(void); 39 - int exit_vmx_usercopy(void); 40 - int enter_vmx_ops(void); 41 - void *exit_vmx_ops(void *dest); 42 - 43 - /* signals, syscalls and interrupts */ 44 - long sys_swapcontext(struct ucontext __user *old_ctx, 45 - struct ucontext __user *new_ctx, 46 - long ctx_size); 47 - #ifdef CONFIG_PPC32 48 - long sys_debug_setcontext(struct ucontext __user *ctx, 49 - int ndbg, struct sig_dbg_op __user *dbg); 50 - int 51 - ppc_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, 52 - struct __kernel_old_timeval __user *tvp); 53 - unsigned long __init early_init(unsigned long dt_ptr); 54 - void __init machine_init(u64 dt_ptr); 55 - #endif 56 - long system_call_exception(long r3, long r4, long r5, long r6, long r7, long r8, unsigned long r0, struct pt_regs *regs); 57 - notrace unsigned long syscall_exit_prepare(unsigned long r3, struct pt_regs *regs, long scv); 58 - notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs); 59 - notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs); 60 - #ifdef CONFIG_PPC64 61 - unsigned long syscall_exit_restart(unsigned long r3, struct pt_regs *regs); 62 - unsigned long interrupt_exit_user_restart(struct pt_regs *regs); 63 - unsigned long interrupt_exit_kernel_restart(struct pt_regs *regs); 64 - #endif 65 - 66 - long ppc_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low, 67 - u32 len_high, u32 len_low); 68 - long sys_switch_endian(void); 69 - 70 53 /* prom_init (OpenFirmware) */ 71 54 unsigned long __init prom_init(unsigned long r3, unsigned long r4, 72 55 unsigned long pp, 73 56 unsigned long r6, unsigned long r7, 74 57 unsigned long kbase); 75 - 76 - /* setup */ 77 - void __init early_setup(unsigned long dt_ptr); 78 - void early_setup_secondary(void); 79 58 80 59 /* misc runtime */ 81 60 extern u64 __bswapdi2(u64); ··· 50 103 51 104 /* tracing */ 52 105 void _mcount(void); 53 - unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip, 54 - unsigned long sp); 55 - 56 - void pnv_power9_force_smt4_catch(void); 57 - void pnv_power9_force_smt4_release(void); 58 106 59 107 /* Transaction memory related */ 60 108 void tm_enable(void);
+2 -2
arch/powerpc/include/asm/bitops.h
··· 287 287 * fls: find last (most-significant) bit set. 288 288 * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32. 289 289 */ 290 - static inline int fls(unsigned int x) 290 + static __always_inline int fls(unsigned int x) 291 291 { 292 292 int lz; 293 293 ··· 305 305 * 32-bit fls calls. 306 306 */ 307 307 #ifdef CONFIG_PPC64 308 - static inline int fls64(__u64 x) 308 + static __always_inline int fls64(__u64 x) 309 309 { 310 310 int lz; 311 311
+22 -15
arch/powerpc/include/asm/book3s/32/pgtable.h
··· 298 298 unsigned long clr, unsigned long set, int huge) 299 299 { 300 300 pte_basic_t old; 301 - unsigned long tmp; 302 301 303 - __asm__ __volatile__( 302 + if (mmu_has_feature(MMU_FTR_HPTE_TABLE)) { 303 + unsigned long tmp; 304 + 305 + asm volatile( 304 306 #ifndef CONFIG_PTE_64BIT 305 - "1: lwarx %0, 0, %3\n" 306 - " andc %1, %0, %4\n" 307 + "1: lwarx %0, 0, %3\n" 308 + " andc %1, %0, %4\n" 307 309 #else 308 - "1: lwarx %L0, 0, %3\n" 309 - " lwz %0, -4(%3)\n" 310 - " andc %1, %L0, %4\n" 310 + "1: lwarx %L0, 0, %3\n" 311 + " lwz %0, -4(%3)\n" 312 + " andc %1, %L0, %4\n" 311 313 #endif 312 - " or %1, %1, %5\n" 313 - " stwcx. %1, 0, %3\n" 314 - " bne- 1b" 315 - : "=&r" (old), "=&r" (tmp), "=m" (*p) 314 + " or %1, %1, %5\n" 315 + " stwcx. %1, 0, %3\n" 316 + " bne- 1b" 317 + : "=&r" (old), "=&r" (tmp), "=m" (*p) 316 318 #ifndef CONFIG_PTE_64BIT 317 - : "r" (p), 319 + : "r" (p), 318 320 #else 319 - : "b" ((unsigned long)(p) + 4), 321 + : "b" ((unsigned long)(p) + 4), 320 322 #endif 321 - "r" (clr), "r" (set), "m" (*p) 322 - : "cc" ); 323 + "r" (clr), "r" (set), "m" (*p) 324 + : "cc" ); 325 + } else { 326 + old = pte_val(*p); 327 + 328 + *p = __pte((old & ~(pte_basic_t)clr) | set); 329 + } 323 330 324 331 return old; 325 332 }
+2 -2
arch/powerpc/include/asm/book3s/64/kup.h
··· 328 328 return mfspr(SPRN_AMR); 329 329 } 330 330 331 - static inline void set_kuap(unsigned long value) 331 + static __always_inline void set_kuap(unsigned long value) 332 332 { 333 333 if (!mmu_has_feature(MMU_FTR_BOOK3S_KUAP)) 334 334 return; ··· 398 398 399 399 #endif /* !CONFIG_PPC_KUAP */ 400 400 401 - static inline void prevent_user_access(unsigned long dir) 401 + static __always_inline void prevent_user_access(unsigned long dir) 402 402 { 403 403 set_kuap(AMR_KUAP_BLOCKED); 404 404 if (static_branch_unlikely(&uaccess_flush_key))
+10 -3
arch/powerpc/include/asm/bug.h
··· 11 11 #ifdef __ASSEMBLY__ 12 12 #include <asm/asm-offsets.h> 13 13 #ifdef CONFIG_DEBUG_BUGVERBOSE 14 - .macro EMIT_BUG_ENTRY addr,file,line,flags 14 + .macro __EMIT_BUG_ENTRY addr,file,line,flags 15 15 .section __bug_table,"aw" 16 16 5001: .4byte \addr - 5001b, 5002f - 5001b 17 17 .short \line, \flags ··· 22 22 .previous 23 23 .endm 24 24 #else 25 - .macro EMIT_BUG_ENTRY addr,file,line,flags 25 + .macro __EMIT_BUG_ENTRY addr,file,line,flags 26 26 .section __bug_table,"aw" 27 27 5001: .4byte \addr - 5001b 28 28 .short \flags ··· 33 33 34 34 .macro EMIT_WARN_ENTRY addr,file,line,flags 35 35 EX_TABLE(\addr,\addr+4) 36 - EMIT_BUG_ENTRY \addr,\file,\line,\flags 36 + __EMIT_BUG_ENTRY \addr,\file,\line,\flags 37 + .endm 38 + 39 + .macro EMIT_BUG_ENTRY addr,file,line,flags 40 + .if \flags & 1 /* BUGFLAG_WARNING */ 41 + .err /* Use EMIT_WARN_ENTRY for warnings */ 42 + .endif 43 + __EMIT_BUG_ENTRY \addr,\file,\line,\flags 37 44 .endm 38 45 39 46 #else /* !__ASSEMBLY__ */
+1 -1
arch/powerpc/include/asm/code-patching.h
··· 118 118 * function's descriptor. The first entry in the descriptor is the 119 119 * address of the function text. 120 120 */ 121 - return ((func_descr_t *)func)->entry; 121 + return ((struct func_desc *)func)->addr; 122 122 #else 123 123 return (unsigned long)func; 124 124 #endif
+6
arch/powerpc/include/asm/elf.h
··· 176 176 /* Relocate the kernel image to @final_address */ 177 177 void relocate(unsigned long final_address); 178 178 179 + struct func_desc { 180 + unsigned long addr; 181 + unsigned long toc; 182 + unsigned long env; 183 + }; 184 + 179 185 #endif /* _ASM_POWERPC_ELF_H */
+1 -1
arch/powerpc/include/asm/epapr_hcalls.h
··· 65 65 * but the gcc inline assembly syntax does not allow us to specify registers 66 66 * on the clobber list that are also on the input/output list. Therefore, 67 67 * the lists of clobbered registers depends on the number of register 68 - * parmeters ("+r" and "=r") passed to the hypercall. 68 + * parameters ("+r" and "=r") passed to the hypercall. 69 69 * 70 70 * Each assembly block should use one of the HCALL_CLOBBERSx macros. As a 71 71 * general rule, 'x' is the number of parameters passed to the assembly
+3 -1
arch/powerpc/include/asm/firmware.h
··· 54 54 #define FW_FEATURE_STUFF_TCE ASM_CONST(0x0000008000000000) 55 55 #define FW_FEATURE_RPT_INVALIDATE ASM_CONST(0x0000010000000000) 56 56 #define FW_FEATURE_FORM2_AFFINITY ASM_CONST(0x0000020000000000) 57 + #define FW_FEATURE_ENERGY_SCALE_INFO ASM_CONST(0x0000040000000000) 57 58 58 59 #ifndef __ASSEMBLY__ 59 60 ··· 75 74 FW_FEATURE_HPT_RESIZE | FW_FEATURE_DRMEM_V2 | 76 75 FW_FEATURE_DRC_INFO | FW_FEATURE_BLOCK_REMOVE | 77 76 FW_FEATURE_PAPR_SCM | FW_FEATURE_ULTRAVISOR | 78 - FW_FEATURE_RPT_INVALIDATE | FW_FEATURE_FORM2_AFFINITY, 77 + FW_FEATURE_RPT_INVALIDATE | FW_FEATURE_FORM2_AFFINITY | 78 + FW_FEATURE_ENERGY_SCALE_INFO, 79 79 FW_FEATURE_PSERIES_ALWAYS = 0, 80 80 FW_FEATURE_POWERNV_POSSIBLE = FW_FEATURE_OPAL | FW_FEATURE_ULTRAVISOR, 81 81 FW_FEATURE_POWERNV_ALWAYS = 0,
+28 -38
arch/powerpc/include/asm/ftrace.h
··· 10 10 11 11 #define HAVE_FUNCTION_GRAPH_RET_ADDR_PTR 12 12 13 - #ifdef __ASSEMBLY__ 14 - 15 - /* Based off of objdump output from glibc */ 16 - 17 - #define MCOUNT_SAVE_FRAME \ 18 - stwu r1,-48(r1); \ 19 - stw r3, 12(r1); \ 20 - stw r4, 16(r1); \ 21 - stw r5, 20(r1); \ 22 - stw r6, 24(r1); \ 23 - mflr r3; \ 24 - lwz r4, 52(r1); \ 25 - mfcr r5; \ 26 - stw r7, 28(r1); \ 27 - stw r8, 32(r1); \ 28 - stw r9, 36(r1); \ 29 - stw r10,40(r1); \ 30 - stw r3, 44(r1); \ 31 - stw r5, 8(r1) 32 - 33 - #define MCOUNT_RESTORE_FRAME \ 34 - lwz r6, 8(r1); \ 35 - lwz r0, 44(r1); \ 36 - lwz r3, 12(r1); \ 37 - mtctr r0; \ 38 - lwz r4, 16(r1); \ 39 - mtcr r6; \ 40 - lwz r5, 20(r1); \ 41 - lwz r6, 24(r1); \ 42 - lwz r0, 52(r1); \ 43 - lwz r7, 28(r1); \ 44 - lwz r8, 32(r1); \ 45 - mtlr r0; \ 46 - lwz r9, 36(r1); \ 47 - lwz r10,40(r1); \ 48 - addi r1, r1, 48 49 - 50 - #else /* !__ASSEMBLY__ */ 13 + #ifndef __ASSEMBLY__ 51 14 extern void _mcount(void); 52 15 53 16 static inline unsigned long ftrace_call_adjust(unsigned long addr) ··· 19 56 return addr; 20 57 } 21 58 59 + unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip, 60 + unsigned long sp); 61 + 22 62 struct dyn_arch_ftrace { 23 63 struct module *mod; 24 64 }; 65 + 66 + #ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS 67 + struct ftrace_regs { 68 + struct pt_regs regs; 69 + }; 70 + 71 + static __always_inline struct pt_regs *arch_ftrace_get_regs(struct ftrace_regs *fregs) 72 + { 73 + /* We clear regs.msr in ftrace_call */ 74 + return fregs->regs.msr ? &fregs->regs : NULL; 75 + } 76 + 77 + static __always_inline void ftrace_instruction_pointer_set(struct ftrace_regs *fregs, 78 + unsigned long ip) 79 + { 80 + regs_set_return_ip(&fregs->regs, ip); 81 + } 82 + 83 + struct ftrace_ops; 84 + 85 + #define ftrace_graph_func ftrace_graph_func 86 + void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, 87 + struct ftrace_ops *op, struct ftrace_regs *fregs); 88 + #endif 25 89 #endif /* __ASSEMBLY__ */ 26 90 27 91 #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS
+4 -1
arch/powerpc/include/asm/hugetlb.h
··· 15 15 16 16 extern bool hugetlb_disabled; 17 17 18 - void __init hugetlbpage_init_default(void); 18 + void __init hugetlbpage_init_defaultsize(void); 19 19 20 20 int slice_is_hugepage_only_range(struct mm_struct *mm, unsigned long addr, 21 21 unsigned long len); ··· 76 76 { 77 77 } 78 78 79 + static inline void __init hugetlbpage_init_defaultsize(void) 80 + { 81 + } 79 82 #endif /* CONFIG_HUGETLB_PAGE */ 80 83 81 84 #endif /* _ASM_POWERPC_HUGETLB_H */
+7 -1
arch/powerpc/include/asm/hvcall.h
··· 323 323 #define H_SCM_PERFORMANCE_STATS 0x418 324 324 #define H_RPT_INVALIDATE 0x448 325 325 #define H_SCM_FLUSH 0x44C 326 - #define MAX_HCALL_OPCODE H_SCM_FLUSH 326 + #define H_GET_ENERGY_SCALE_INFO 0x450 327 + #define MAX_HCALL_OPCODE H_GET_ENERGY_SCALE_INFO 327 328 328 329 /* Scope args for H_SCM_UNBIND_ALL */ 329 330 #define H_UNBIND_SCOPE_ALL (0x1) ··· 500 499 #define PLPAR_HCALL9_BUFSIZE 9 501 500 long plpar_hcall9(unsigned long opcode, unsigned long *retbuf, ...); 502 501 long plpar_hcall9_raw(unsigned long opcode, unsigned long *retbuf, ...); 502 + 503 + /* pseries hcall tracing */ 504 + extern struct static_key hcall_tracepoint_key; 505 + void __trace_hcall_entry(unsigned long opcode, unsigned long *args); 506 + void __trace_hcall_exit(long opcode, long retval, unsigned long *retbuf); 503 507 504 508 struct hvcall_mpp_data { 505 509 unsigned long entitled_mem;
+24 -21
arch/powerpc/include/asm/interrupt.h
··· 123 123 #endif 124 124 } 125 125 126 - struct interrupt_state { 127 - }; 128 - 129 126 static inline void booke_restore_dbcr0(void) 130 127 { 131 128 #ifdef CONFIG_PPC_ADV_DEBUG_REGS ··· 135 138 #endif 136 139 } 137 140 138 - static inline void interrupt_enter_prepare(struct pt_regs *regs, struct interrupt_state *state) 141 + static inline void interrupt_enter_prepare(struct pt_regs *regs) 139 142 { 140 143 #ifdef CONFIG_PPC32 141 144 if (!arch_irq_disabled_regs(regs)) ··· 225 228 * However interrupt_nmi_exit_prepare does return directly to regs, because 226 229 * NMIs do not do "exit work" or replay soft-masked interrupts. 227 230 */ 228 - static inline void interrupt_exit_prepare(struct pt_regs *regs, struct interrupt_state *state) 231 + static inline void interrupt_exit_prepare(struct pt_regs *regs) 229 232 { 230 233 } 231 234 232 - static inline void interrupt_async_enter_prepare(struct pt_regs *regs, struct interrupt_state *state) 235 + static inline void interrupt_async_enter_prepare(struct pt_regs *regs) 233 236 { 234 237 #ifdef CONFIG_PPC64 235 238 /* Ensure interrupt_enter_prepare does not enable MSR[EE] */ 236 239 local_paca->irq_happened |= PACA_IRQ_HARD_DIS; 237 240 #endif 238 - interrupt_enter_prepare(regs, state); 241 + interrupt_enter_prepare(regs); 239 242 #ifdef CONFIG_PPC_BOOK3S_64 240 243 /* 241 244 * RI=1 is set by interrupt_enter_prepare, so this thread flags access ··· 248 251 irq_enter(); 249 252 } 250 253 251 - static inline void interrupt_async_exit_prepare(struct pt_regs *regs, struct interrupt_state *state) 254 + static inline void interrupt_async_exit_prepare(struct pt_regs *regs) 252 255 { 253 256 /* 254 257 * Adjust at exit so the main handler sees the true NIA. This must ··· 259 262 nap_adjust_return(regs); 260 263 261 264 irq_exit(); 262 - interrupt_exit_prepare(regs, state); 265 + interrupt_exit_prepare(regs); 263 266 } 264 267 265 268 struct interrupt_nmi_state { ··· 444 447 \ 445 448 interrupt_handler void func(struct pt_regs *regs) \ 446 449 { \ 447 - struct interrupt_state state; \ 448 - \ 449 - interrupt_enter_prepare(regs, &state); \ 450 + interrupt_enter_prepare(regs); \ 450 451 \ 451 452 ____##func (regs); \ 452 453 \ 453 - interrupt_exit_prepare(regs, &state); \ 454 + interrupt_exit_prepare(regs); \ 454 455 } \ 455 456 NOKPROBE_SYMBOL(func); \ 456 457 \ ··· 477 482 \ 478 483 interrupt_handler long func(struct pt_regs *regs) \ 479 484 { \ 480 - struct interrupt_state state; \ 481 485 long ret; \ 482 486 \ 483 - interrupt_enter_prepare(regs, &state); \ 487 + interrupt_enter_prepare(regs); \ 484 488 \ 485 489 ret = ____##func (regs); \ 486 490 \ 487 - interrupt_exit_prepare(regs, &state); \ 491 + interrupt_exit_prepare(regs); \ 488 492 \ 489 493 return ret; \ 490 494 } \ ··· 512 518 \ 513 519 interrupt_handler void func(struct pt_regs *regs) \ 514 520 { \ 515 - struct interrupt_state state; \ 516 - \ 517 - interrupt_async_enter_prepare(regs, &state); \ 521 + interrupt_async_enter_prepare(regs); \ 518 522 \ 519 523 ____##func (regs); \ 520 524 \ 521 - interrupt_async_exit_prepare(regs, &state); \ 525 + interrupt_async_exit_prepare(regs); \ 522 526 } \ 523 527 NOKPROBE_SYMBOL(func); \ 524 528 \ ··· 604 612 DECLARE_INTERRUPT_HANDLER(do_bad_segment_interrupt); 605 613 606 614 /* hash_utils.c */ 607 - DECLARE_INTERRUPT_HANDLER_RAW(do_hash_fault); 615 + DECLARE_INTERRUPT_HANDLER(do_hash_fault); 608 616 609 617 /* fault.c */ 610 618 DECLARE_INTERRUPT_HANDLER(do_page_fault); ··· 635 643 if (!arch_irq_disabled_regs(regs)) 636 644 local_irq_enable(); 637 645 } 646 + 647 + long system_call_exception(long r3, long r4, long r5, long r6, long r7, long r8, 648 + unsigned long r0, struct pt_regs *regs); 649 + notrace unsigned long syscall_exit_prepare(unsigned long r3, struct pt_regs *regs, long scv); 650 + notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs); 651 + notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs); 652 + #ifdef CONFIG_PPC64 653 + unsigned long syscall_exit_restart(unsigned long r3, struct pt_regs *regs); 654 + unsigned long interrupt_exit_user_restart(struct pt_regs *regs); 655 + unsigned long interrupt_exit_kernel_restart(struct pt_regs *regs); 656 + #endif 638 657 639 658 #endif /* __ASSEMBLY__ */ 640 659
+32 -8
arch/powerpc/include/asm/io.h
··· 359 359 */ 360 360 static inline void __raw_rm_writeb(u8 val, volatile void __iomem *paddr) 361 361 { 362 - __asm__ __volatile__("stbcix %0,0,%1" 362 + __asm__ __volatile__(".machine push; \ 363 + .machine power6; \ 364 + stbcix %0,0,%1; \ 365 + .machine pop;" 363 366 : : "r" (val), "r" (paddr) : "memory"); 364 367 } 365 368 366 369 static inline void __raw_rm_writew(u16 val, volatile void __iomem *paddr) 367 370 { 368 - __asm__ __volatile__("sthcix %0,0,%1" 371 + __asm__ __volatile__(".machine push; \ 372 + .machine power6; \ 373 + sthcix %0,0,%1; \ 374 + .machine pop;" 369 375 : : "r" (val), "r" (paddr) : "memory"); 370 376 } 371 377 372 378 static inline void __raw_rm_writel(u32 val, volatile void __iomem *paddr) 373 379 { 374 - __asm__ __volatile__("stwcix %0,0,%1" 380 + __asm__ __volatile__(".machine push; \ 381 + .machine power6; \ 382 + stwcix %0,0,%1; \ 383 + .machine pop;" 375 384 : : "r" (val), "r" (paddr) : "memory"); 376 385 } 377 386 378 387 static inline void __raw_rm_writeq(u64 val, volatile void __iomem *paddr) 379 388 { 380 - __asm__ __volatile__("stdcix %0,0,%1" 389 + __asm__ __volatile__(".machine push; \ 390 + .machine power6; \ 391 + stdcix %0,0,%1; \ 392 + .machine pop;" 381 393 : : "r" (val), "r" (paddr) : "memory"); 382 394 } 383 395 ··· 401 389 static inline u8 __raw_rm_readb(volatile void __iomem *paddr) 402 390 { 403 391 u8 ret; 404 - __asm__ __volatile__("lbzcix %0,0, %1" 392 + __asm__ __volatile__(".machine push; \ 393 + .machine power6; \ 394 + lbzcix %0,0, %1; \ 395 + .machine pop;" 405 396 : "=r" (ret) : "r" (paddr) : "memory"); 406 397 return ret; 407 398 } ··· 412 397 static inline u16 __raw_rm_readw(volatile void __iomem *paddr) 413 398 { 414 399 u16 ret; 415 - __asm__ __volatile__("lhzcix %0,0, %1" 400 + __asm__ __volatile__(".machine push; \ 401 + .machine power6; \ 402 + lhzcix %0,0, %1; \ 403 + .machine pop;" 416 404 : "=r" (ret) : "r" (paddr) : "memory"); 417 405 return ret; 418 406 } ··· 423 405 static inline u32 __raw_rm_readl(volatile void __iomem *paddr) 424 406 { 425 407 u32 ret; 426 - __asm__ __volatile__("lwzcix %0,0, %1" 408 + __asm__ __volatile__(".machine push; \ 409 + .machine power6; \ 410 + lwzcix %0,0, %1; \ 411 + .machine pop;" 427 412 : "=r" (ret) : "r" (paddr) : "memory"); 428 413 return ret; 429 414 } ··· 434 413 static inline u64 __raw_rm_readq(volatile void __iomem *paddr) 435 414 { 436 415 u64 ret; 437 - __asm__ __volatile__("ldcix %0,0, %1" 416 + __asm__ __volatile__(".machine push; \ 417 + .machine power6; \ 418 + ldcix %0,0, %1; \ 419 + .machine pop;" 438 420 : "=r" (ret) : "r" (paddr) : "memory"); 439 421 return ret; 440 422 }
+2
arch/powerpc/include/asm/kexec.h
··· 96 96 void relocate_new_kernel(unsigned long indirection_page, unsigned long reboot_code_buffer, 97 97 unsigned long start_address) __noreturn; 98 98 99 + void kexec_copy_flush(struct kimage *image); 100 + 99 101 #ifdef CONFIG_KEXEC_FILE 100 102 extern const struct kexec_file_ops kexec_elf64_ops; 101 103
+2 -4
arch/powerpc/include/asm/kvm_host.h
··· 26 26 #include <asm/hvcall.h> 27 27 #include <asm/mce.h> 28 28 29 + #define __KVM_HAVE_ARCH_VCPU_DEBUGFS 30 + 29 31 #define KVM_MAX_VCPUS NR_CPUS 30 32 #define KVM_MAX_VCORES NR_CPUS 31 33 ··· 297 295 bool dawr1_enabled; 298 296 pgd_t *pgtable; 299 297 u64 process_table; 300 - struct dentry *debugfs_dir; 301 298 struct kvm_resize_hpt *resize_hpt; /* protected by kvm->lock */ 302 299 #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */ 303 300 #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE ··· 674 673 u64 timing_min_duration[__NUMBER_OF_KVM_EXIT_TYPES]; 675 674 u64 timing_max_duration[__NUMBER_OF_KVM_EXIT_TYPES]; 676 675 u64 timing_last_exit; 677 - struct dentry *debugfs_exit_timing; 678 676 #endif 679 677 680 678 #ifdef CONFIG_PPC_BOOK3S ··· 831 831 struct kvmhv_tb_accumulator rm_exit; /* real-mode exit code */ 832 832 struct kvmhv_tb_accumulator guest_time; /* guest execution */ 833 833 struct kvmhv_tb_accumulator cede_time; /* time napping inside guest */ 834 - 835 - struct dentry *debugfs_dir; 836 834 #endif /* CONFIG_KVM_BOOK3S_HV_EXIT_TIMING */ 837 835 }; 838 836
+2
arch/powerpc/include/asm/kvm_ppc.h
··· 314 314 int (*svm_off)(struct kvm *kvm); 315 315 int (*enable_dawr1)(struct kvm *kvm); 316 316 bool (*hash_v3_possible)(void); 317 + int (*create_vm_debugfs)(struct kvm *kvm); 318 + int (*create_vcpu_debugfs)(struct kvm_vcpu *vcpu, struct dentry *debugfs_dentry); 317 319 }; 318 320 319 321 extern struct kvmppc_ops *kvmppc_hv_ops;
+6 -6
arch/powerpc/include/asm/livepatch.h
··· 14 14 #ifdef CONFIG_LIVEPATCH 15 15 static inline void klp_arch_set_pc(struct ftrace_regs *fregs, unsigned long ip) 16 16 { 17 - struct pt_regs *regs = ftrace_get_regs(fregs); 18 - 19 - regs_set_return_ip(regs, ip); 17 + ftrace_instruction_pointer_set(fregs, ip); 20 18 } 21 19 22 20 #define klp_get_ftrace_location klp_get_ftrace_location 23 21 static inline unsigned long klp_get_ftrace_location(unsigned long faddr) 24 22 { 25 23 /* 26 - * Live patch works only with -mprofile-kernel on PPC. In this case, 27 - * the ftrace location is always within the first 16 bytes. 24 + * Live patch works on PPC32 and only with -mprofile-kernel on PPC64. In 25 + * both cases, the ftrace location is always within the first 16 bytes. 28 26 */ 29 27 return ftrace_location_range(faddr, faddr + 16); 30 28 } 29 + #endif /* CONFIG_LIVEPATCH */ 31 30 31 + #ifdef CONFIG_LIVEPATCH_64 32 32 static inline void klp_init_thread_info(struct task_struct *p) 33 33 { 34 34 /* + 1 to account for STACK_END_MAGIC */ ··· 36 36 } 37 37 #else 38 38 static inline void klp_init_thread_info(struct task_struct *p) { } 39 - #endif /* CONFIG_LIVEPATCH */ 39 + #endif 40 40 41 41 #endif /* _ASM_POWERPC_LIVEPATCH_H */
+2 -20
arch/powerpc/include/asm/machdep.h
··· 10 10 11 11 #include <asm/setup.h> 12 12 13 - /* We export this macro for external modules like Alsa to know if 14 - * ppc_md.feature_call is implemented or not 15 - */ 16 - #define CONFIG_PPC_HAS_FEATURE_CALLS 17 - 18 13 struct pt_regs; 19 14 struct pci_bus; 20 15 struct device_node; ··· 93 98 94 99 /* Called during machine check exception to retrive fixup address. */ 95 100 bool (*mce_check_early_recovery)(struct pt_regs *regs); 101 + 102 + void (*machine_check_log_err)(void); 96 103 97 104 /* Motherboard/chipset features. This is a kind of general purpose 98 105 * hook used to control some machine specific features (like reset ··· 231 234 __attribute__((weak)); \ 232 235 machine_id == &mach_##name; \ 233 236 }) 234 - 235 - #ifdef CONFIG_PPC_PMAC 236 - /* 237 - * Power macintoshes have either a CUDA, PMU or SMU controlling 238 - * system reset, power, NVRAM, RTC. 239 - */ 240 - typedef enum sys_ctrler_kind { 241 - SYS_CTRLER_UNKNOWN = 0, 242 - SYS_CTRLER_CUDA = 1, 243 - SYS_CTRLER_PMU = 2, 244 - SYS_CTRLER_SMU = 3, 245 - } sys_ctrler_t; 246 - extern sys_ctrler_t sys_ctrler; 247 - 248 - #endif /* CONFIG_PPC_PMAC */ 249 237 250 238 static inline void log_error(char *buf, unsigned int err_type, int fatal) 251 239 {
+13
arch/powerpc/include/asm/mce.h
··· 235 235 unsigned long addr_to_pfn(struct pt_regs *regs, unsigned long addr); 236 236 extern void mce_common_process_ue(struct pt_regs *regs, 237 237 struct mce_error_info *mce_err); 238 + void mce_irq_work_queue(void); 238 239 int mce_register_notifier(struct notifier_block *nb); 239 240 int mce_unregister_notifier(struct notifier_block *nb); 241 + 242 + #ifdef CONFIG_PPC_BOOK3S_64 243 + void mce_run_irq_context_handlers(void); 244 + #else 245 + static inline void mce_run_irq_context_handlers(void) { }; 246 + #endif /* CONFIG_PPC_BOOK3S_64 */ 247 + 248 + #ifdef CONFIG_PPC_BOOK3S_64 249 + void set_mce_pending_irq_work(void); 250 + void clear_mce_pending_irq_work(void); 251 + #endif /* CONFIG_PPC_BOOK3S_64 */ 252 + 240 253 #ifdef CONFIG_PPC_BOOK3S_64 241 254 void flush_and_reload_slb(void); 242 255 void flush_erat(void);
-3
arch/powerpc/include/asm/nohash/32/pgtable.h
··· 338 338 return pte_val(pte) & _PAGE_ACCESSED; 339 339 } 340 340 341 - #define __HAVE_ARCH_PTE_SAME 342 - #define pte_same(A,B) ((pte_val(A) ^ pte_val(B)) == 0) 343 - 344 341 /* 345 342 * Note that on Book E processors, the pmd contains the kernel virtual 346 343 * (lowmem) address of the pte page. The physical address is less useful
-3
arch/powerpc/include/asm/nohash/64/pgtable.h
··· 282 282 flush_tlb_page(vma, address); 283 283 } 284 284 285 - #define __HAVE_ARCH_PTE_SAME 286 - #define pte_same(A,B) ((pte_val(A) ^ pte_val(B)) == 0) 287 - 288 285 #define pte_ERROR(e) \ 289 286 pr_err("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) 290 287 #define pmd_ERROR(e) \
+1
arch/powerpc/include/asm/paca.h
··· 288 288 #endif 289 289 #ifdef CONFIG_PPC_BOOK3S_64 290 290 struct mce_info *mce_info; 291 + u8 mce_pending_irq_work; 291 292 #endif /* CONFIG_PPC_BOOK3S_64 */ 292 293 } ____cacheline_aligned; 293 294
+12
arch/powerpc/include/asm/pmac_feature.h
··· 401 401 */ 402 402 extern int pmac_get_uninorth_variant(void); 403 403 404 + /* 405 + * Power macintoshes have either a CUDA, PMU or SMU controlling 406 + * system reset, power, NVRAM, RTC. 407 + */ 408 + typedef enum sys_ctrler_kind { 409 + SYS_CTRLER_UNKNOWN = 0, 410 + SYS_CTRLER_CUDA = 1, 411 + SYS_CTRLER_PMU = 2, 412 + SYS_CTRLER_SMU = 3, 413 + } sys_ctrler_t; 414 + extern sys_ctrler_t sys_ctrler; 415 + 404 416 #endif /* __ASM_POWERPC_PMAC_FEATURE_H */ 405 417 #endif /* __KERNEL__ */
+2
arch/powerpc/include/asm/ppc-opcode.h
··· 262 262 #define PPC_INST_MFSPR_PVR 0x7c1f42a6 263 263 #define PPC_INST_MFSPR_PVR_MASK 0xfc1ffffe 264 264 #define PPC_INST_MTMSRD 0x7c000164 265 + #define PPC_INST_PASTE 0x7c20070d 266 + #define PPC_INST_PASTE_MASK 0xfc2007ff 265 267 #define PPC_INST_POPCNTB 0x7c0000f4 266 268 #define PPC_INST_POPCNTB_MASK 0xfc0007fe 267 269 #define PPC_INST_RFEBB 0x4c000124
-11
arch/powerpc/include/asm/ppc_asm.h
··· 203 203 204 204 #else /* 32-bit */ 205 205 206 - #define _ENTRY(n) \ 207 - .globl n; \ 208 - n: 209 - 210 206 #define _GLOBAL(n) \ 211 - .stabs __stringify(n:F-1),N_FUN,0,0,n;\ 212 207 .globl n; \ 213 208 n: 214 209 ··· 691 696 #define evr29 29 692 697 #define evr30 30 693 698 #define evr31 31 694 - 695 - /* some stab codes */ 696 - #define N_FUN 36 697 - #define N_RSYM 64 698 - #define N_SLINE 68 699 - #define N_SO 100 700 699 701 700 #define RFSCV .long 0x4c0000a4 702 701
+8
arch/powerpc/include/asm/processor.h
··· 411 411 extern void power7_idle_type(unsigned long type); 412 412 extern void arch300_idle_type(unsigned long stop_psscr_val, 413 413 unsigned long stop_psscr_mask); 414 + void pnv_power9_force_smt4_catch(void); 415 + void pnv_power9_force_smt4_release(void); 414 416 415 417 extern int fix_alignment(struct pt_regs *); 416 418 ··· 428 426 #endif 429 427 430 428 int do_mathemu(struct pt_regs *regs); 429 + 430 + /* VMX copying */ 431 + int enter_vmx_usercopy(void); 432 + int exit_vmx_usercopy(void); 433 + int enter_vmx_ops(void); 434 + void *exit_vmx_ops(void *dest); 431 435 432 436 #endif /* __KERNEL__ */ 433 437 #endif /* __ASSEMBLY__ */
-1
arch/powerpc/include/asm/rtas.h
··· 274 274 #ifdef CONFIG_PPC_PSERIES 275 275 extern time64_t last_rtas_event; 276 276 extern int clobbering_unread_rtas_event(void); 277 - extern int pseries_devicetree_update(s32 scope); 278 277 extern void post_mobility_fixup(void); 279 278 int rtas_syscall_dispatch_ibm_suspend_me(u64 handle); 280 279 #else
+4 -25
arch/powerpc/include/asm/sections.h
··· 6 6 #include <linux/elf.h> 7 7 #include <linux/uaccess.h> 8 8 9 + #ifdef CONFIG_HAVE_FUNCTION_DESCRIPTORS 10 + typedef struct func_desc func_desc_t; 11 + #endif 12 + 9 13 #include <asm-generic/sections.h> 10 14 11 15 extern char __head_end[]; ··· 57 53 return start < (unsigned long)__init_end && 58 54 (unsigned long)_stext < end; 59 55 } 60 - 61 - #ifdef PPC64_ELF_ABI_v1 62 - 63 - #define HAVE_DEREFERENCE_FUNCTION_DESCRIPTOR 1 64 - 65 - #undef dereference_function_descriptor 66 - static inline void *dereference_function_descriptor(void *ptr) 67 - { 68 - struct ppc64_opd_entry *desc = ptr; 69 - void *p; 70 - 71 - if (!get_kernel_nofault(p, (void *)&desc->funcaddr)) 72 - ptr = p; 73 - return ptr; 74 - } 75 - 76 - #undef dereference_kernel_function_descriptor 77 - static inline void *dereference_kernel_function_descriptor(void *ptr) 78 - { 79 - if (ptr < (void *)__start_opd || ptr >= (void *)__end_opd) 80 - return ptr; 81 - 82 - return dereference_function_descriptor(ptr); 83 - } 84 - #endif /* PPC64_ELF_ABI_v1 */ 85 56 86 57 #endif 87 58
+11 -1
arch/powerpc/include/asm/set_memory.h
··· 6 6 #define SET_MEMORY_RW 1 7 7 #define SET_MEMORY_NX 2 8 8 #define SET_MEMORY_X 3 9 + #define SET_MEMORY_NP 4 /* Set memory non present */ 10 + #define SET_MEMORY_P 5 /* Set memory present */ 9 11 10 12 int change_memory_attr(unsigned long addr, int numpages, long action); 11 13 ··· 31 29 return change_memory_attr(addr, numpages, SET_MEMORY_X); 32 30 } 33 31 34 - int set_memory_attr(unsigned long addr, int numpages, pgprot_t prot); 32 + static inline int set_memory_np(unsigned long addr, int numpages) 33 + { 34 + return change_memory_attr(addr, numpages, SET_MEMORY_NP); 35 + } 36 + 37 + static inline int set_memory_p(unsigned long addr, int numpages) 38 + { 39 + return change_memory_attr(addr, numpages, SET_MEMORY_P); 40 + } 35 41 36 42 #endif
+7
arch/powerpc/include/asm/setup.h
··· 76 76 #endif 77 77 void __init do_btb_flush_fixups(void); 78 78 79 + #ifdef CONFIG_PPC32 80 + unsigned long __init early_init(unsigned long dt_ptr); 81 + void __init machine_init(u64 dt_ptr); 82 + #endif 83 + void __init early_setup(unsigned long dt_ptr); 84 + void early_setup_secondary(void); 85 + 79 86 #endif /* !__ASSEMBLY__ */ 80 87 81 88 #endif /* _ASM_POWERPC_SETUP_H */
+3
arch/powerpc/include/asm/smp.h
··· 60 60 #endif 61 61 }; 62 62 63 + extern struct task_struct *secondary_current; 64 + 65 + void start_secondary(void *unused); 63 66 extern int smp_send_nmi_ipi(int cpu, void (*fn)(struct pt_regs *), u64 delay_us); 64 67 extern int smp_send_safe_nmi_ipi(int cpu, void (*fn)(struct pt_regs *), u64 delay_us); 65 68 extern void smp_send_debugger_break(void);
+2 -2
arch/powerpc/include/asm/spu.h
··· 249 249 int spu_add_dev_attr(struct device_attribute *attr); 250 250 void spu_remove_dev_attr(struct device_attribute *attr); 251 251 252 - int spu_add_dev_attr_group(struct attribute_group *attrs); 253 - void spu_remove_dev_attr_group(struct attribute_group *attrs); 252 + int spu_add_dev_attr_group(const struct attribute_group *attrs); 253 + void spu_remove_dev_attr_group(const struct attribute_group *attrs); 254 254 255 255 extern void notify_spus_active(void); 256 256 extern void do_notify_spus_active(void);
+4
arch/powerpc/include/asm/syscalls.h
··· 18 18 unsigned long fd, unsigned long pgoff); 19 19 asmlinkage long ppc64_personality(unsigned long personality); 20 20 asmlinkage long sys_rtas(struct rtas_args __user *uargs); 21 + int ppc_select(int n, fd_set __user *inp, fd_set __user *outp, 22 + fd_set __user *exp, struct __kernel_old_timeval __user *tvp); 23 + long ppc_fadvise64_64(int fd, int advice, u32 offset_high, u32 offset_low, 24 + u32 len_high, u32 len_low); 21 25 22 26 #ifdef CONFIG_COMPAT 23 27 unsigned long compat_sys_mmap2(unsigned long addr, size_t len,
+1 -1
arch/powerpc/include/asm/thread_info.h
··· 51 51 unsigned int cpu; 52 52 #endif 53 53 unsigned long local_flags; /* private flags for thread */ 54 - #ifdef CONFIG_LIVEPATCH 54 + #ifdef CONFIG_LIVEPATCH_64 55 55 unsigned long *livepatch_sp; 56 56 #endif 57 57 #if defined(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE) && defined(CONFIG_PPC32)
+2 -8
arch/powerpc/include/asm/types.h
··· 13 13 14 14 #ifdef __powerpc64__ 15 15 #if defined(_CALL_ELF) && _CALL_ELF == 2 16 - #define PPC64_ELF_ABI_v2 16 + #define PPC64_ELF_ABI_v2 1 17 17 #else 18 - #define PPC64_ELF_ABI_v1 18 + #define PPC64_ELF_ABI_v1 1 19 19 #endif 20 20 #endif /* __powerpc64__ */ 21 21 22 22 #ifndef __ASSEMBLY__ 23 23 24 24 typedef __vector128 vector128; 25 - 26 - typedef struct { 27 - unsigned long entry; 28 - unsigned long toc; 29 - unsigned long env; 30 - } func_descr_t; 31 25 32 26 #endif /* __ASSEMBLY__ */ 33 27
+3
arch/powerpc/include/asm/uaccess.h
··· 116 116 */ 117 117 #define __get_user_atomic_128_aligned(kaddr, uaddr, err) \ 118 118 __asm__ __volatile__( \ 119 + ".machine push\n" \ 120 + ".machine altivec\n" \ 119 121 "1: lvx 0,0,%1 # get user\n" \ 120 122 " stvx 0,0,%2 # put kernel\n" \ 123 + ".machine pop\n" \ 121 124 "2:\n" \ 122 125 ".section .fixup,\"ax\"\n" \ 123 126 "3: li %0,%3\n" \
+14
arch/powerpc/include/asm/vas.h
··· 30 30 #define VAS_THRESH_FIFO_GT_EIGHTH_FULL 3 31 31 32 32 /* 33 + * VAS window Linux status bits 34 + */ 35 + #define VAS_WIN_ACTIVE 0x0 /* Used in platform independent */ 36 + /* vas mmap() */ 37 + /* Window is closed in the hypervisor due to lost credit */ 38 + #define VAS_WIN_NO_CRED_CLOSE 0x00000001 39 + /* Window is closed due to migration */ 40 + #define VAS_WIN_MIGRATE_CLOSE 0x00000002 41 + 42 + /* 33 43 * Get/Set bit fields 34 44 */ 35 45 #define GET_FIELD(m, v) (((v) & (m)) >> MASK_LSH(m)) ··· 69 59 struct pid *pid; /* PID of owner */ 70 60 struct pid *tgid; /* Thread group ID of owner */ 71 61 struct mm_struct *mm; /* Linux process mm_struct */ 62 + struct mutex mmap_mutex; /* protects paste address mmap() */ 63 + /* with DLPAR close/open windows */ 64 + struct vm_area_struct *vma; /* Save VMA and used in DLPAR ops */ 72 65 }; 73 66 74 67 /* ··· 80 67 struct vas_window { 81 68 u32 winid; 82 69 u32 wcreds_max; /* Window credits */ 70 + u32 status; /* Window status used in OS */ 83 71 enum vas_cop_type cop; 84 72 struct vas_user_win_ref task_ref; 85 73 char *dbgname;
+2 -67
arch/powerpc/include/asm/vdso/gettimeofday.h
··· 2 2 #ifndef _ASM_POWERPC_VDSO_GETTIMEOFDAY_H 3 3 #define _ASM_POWERPC_VDSO_GETTIMEOFDAY_H 4 4 5 + #ifndef __ASSEMBLY__ 6 + 5 7 #include <asm/page.h> 6 - 7 - #ifdef __ASSEMBLY__ 8 - 9 - #include <asm/ppc_asm.h> 10 - 11 - /* 12 - * The macros sets two stack frames, one for the caller and one for the callee 13 - * because there are no requirement for the caller to set a stack frame when 14 - * calling VDSO so it may have omitted to set one, especially on PPC64 15 - */ 16 - 17 - .macro cvdso_call funct 18 - .cfi_startproc 19 - PPC_STLU r1, -PPC_MIN_STKFRM(r1) 20 - mflr r0 21 - .cfi_register lr, r0 22 - PPC_STLU r1, -PPC_MIN_STKFRM(r1) 23 - PPC_STL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1) 24 - #ifdef __powerpc64__ 25 - PPC_STL r2, PPC_MIN_STKFRM + STK_GOT(r1) 26 - #endif 27 - get_datapage r5 28 - addi r5, r5, VDSO_DATA_OFFSET 29 - bl DOTSYM(\funct) 30 - PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1) 31 - #ifdef __powerpc64__ 32 - PPC_LL r2, PPC_MIN_STKFRM + STK_GOT(r1) 33 - #endif 34 - cmpwi r3, 0 35 - mtlr r0 36 - .cfi_restore lr 37 - addi r1, r1, 2 * PPC_MIN_STKFRM 38 - crclr so 39 - beqlr+ 40 - crset so 41 - neg r3, r3 42 - blr 43 - .cfi_endproc 44 - .endm 45 - 46 - .macro cvdso_call_time funct 47 - .cfi_startproc 48 - PPC_STLU r1, -PPC_MIN_STKFRM(r1) 49 - mflr r0 50 - .cfi_register lr, r0 51 - PPC_STLU r1, -PPC_MIN_STKFRM(r1) 52 - PPC_STL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1) 53 - #ifdef __powerpc64__ 54 - PPC_STL r2, PPC_MIN_STKFRM + STK_GOT(r1) 55 - #endif 56 - get_datapage r4 57 - addi r4, r4, VDSO_DATA_OFFSET 58 - bl DOTSYM(\funct) 59 - PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1) 60 - #ifdef __powerpc64__ 61 - PPC_LL r2, PPC_MIN_STKFRM + STK_GOT(r1) 62 - #endif 63 - crclr so 64 - mtlr r0 65 - .cfi_restore lr 66 - addi r1, r1, 2 * PPC_MIN_STKFRM 67 - blr 68 - .cfi_endproc 69 - .endm 70 - 71 - #else 72 - 73 8 #include <asm/vdso/timebase.h> 74 9 #include <asm/barrier.h> 75 10 #include <asm/unistd.h>
-8
arch/powerpc/include/uapi/asm/elf.h
··· 289 289 /* Keep this the last entry. */ 290 290 #define R_PPC64_NUM 253 291 291 292 - /* There's actually a third entry here, but it's unused */ 293 - struct ppc64_opd_entry 294 - { 295 - unsigned long funcaddr; 296 - unsigned long r2; 297 - }; 298 - 299 - 300 292 #endif /* _UAPI_ASM_POWERPC_ELF_H */
+18
arch/powerpc/include/uapi/asm/papr_pdsm.h
··· 116 116 }; 117 117 }; 118 118 119 + /* Flags for injecting specific smart errors */ 120 + #define PDSM_SMART_INJECT_HEALTH_FATAL (1 << 0) 121 + #define PDSM_SMART_INJECT_BAD_SHUTDOWN (1 << 1) 122 + 123 + struct nd_papr_pdsm_smart_inject { 124 + union { 125 + struct { 126 + /* One or more of PDSM_SMART_INJECT_ */ 127 + __u32 flags; 128 + __u8 fatal_enable; 129 + __u8 unsafe_shutdown_enable; 130 + }; 131 + __u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE]; 132 + }; 133 + }; 134 + 119 135 /* 120 136 * Methods to be embedded in ND_CMD_CALL request. These are sent to the kernel 121 137 * via 'nd_cmd_pkg.nd_command' member of the ioctl struct ··· 139 123 enum papr_pdsm { 140 124 PAPR_PDSM_MIN = 0x0, 141 125 PAPR_PDSM_HEALTH, 126 + PAPR_PDSM_SMART_INJECT, 142 127 PAPR_PDSM_MAX, 143 128 }; 144 129 145 130 /* Maximal union that can hold all possible payload types */ 146 131 union nd_pdsm_payload { 147 132 struct nd_papr_pdsm_health health; 133 + struct nd_papr_pdsm_smart_inject smart_inject; 148 134 __u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE]; 149 135 } __packed; 150 136
+3 -3
arch/powerpc/kernel/Makefile
··· 194 194 clean-files := vmlinux.lds 195 195 196 196 # Force dependency (incbin is bad) 197 - $(obj)/vdso32_wrapper.o : $(obj)/vdso32/vdso32.so.dbg 198 - $(obj)/vdso64_wrapper.o : $(obj)/vdso64/vdso64.so.dbg 197 + $(obj)/vdso32_wrapper.o : $(obj)/vdso/vdso32.so.dbg 198 + $(obj)/vdso64_wrapper.o : $(obj)/vdso/vdso64.so.dbg 199 199 200 200 # for cleaning 201 - subdir- += vdso32 vdso64 201 + subdir- += vdso
+1 -1
arch/powerpc/kernel/asm-offsets.c
··· 94 94 OFFSET(TASK_CPU, task_struct, thread_info.cpu); 95 95 #endif 96 96 97 - #ifdef CONFIG_LIVEPATCH 97 + #ifdef CONFIG_LIVEPATCH_64 98 98 OFFSET(TI_livepatch_sp, thread_info, livepatch_sp); 99 99 #endif 100 100
-1
arch/powerpc/kernel/early_32.c
··· 8 8 #include <linux/kernel.h> 9 9 #include <asm/setup.h> 10 10 #include <asm/sections.h> 11 - #include <asm/asm-prototypes.h> 12 11 13 12 /* 14 13 * We're called here very early in the boot.
+10 -3
arch/powerpc/kernel/fadump.c
··· 1643 1643 if (fw_dump.ops->fadump_process(&fw_dump) < 0) 1644 1644 fadump_invalidate_release_mem(); 1645 1645 } 1646 - /* Initialize the kernel dump memory structure for FAD registration. */ 1647 - else if (fw_dump.reserve_dump_area_size) 1646 + /* Initialize the kernel dump memory structure and register with f/w */ 1647 + else if (fw_dump.reserve_dump_area_size) { 1648 1648 fw_dump.ops->fadump_init_mem_struct(&fw_dump); 1649 + register_fadump(); 1650 + } 1649 1651 1650 1652 /* 1651 1653 * In case of panic, fadump is triggered via ppc_panic_event() ··· 1659 1657 1660 1658 return 1; 1661 1659 } 1662 - subsys_initcall(setup_fadump); 1660 + /* 1661 + * Use subsys_initcall_sync() here because there is dependency with 1662 + * crash_save_vmcoreinfo_init(), which mush run first to ensure vmcoreinfo initialization 1663 + * is done before regisering with f/w. 1664 + */ 1665 + subsys_initcall_sync(setup_fadump); 1663 1666 #else /* !CONFIG_PRESERVE_FA_DUMP */ 1664 1667 1665 1668 /* Scan the Firmware Assisted dump configuration details. */
+9 -9
arch/powerpc/kernel/head_40x.S
··· 53 53 * This is all going to change RSN when we add bi_recs....... -- Dan 54 54 */ 55 55 __HEAD 56 - _ENTRY(_stext); 57 - _ENTRY(_start); 56 + _GLOBAL(_stext); 57 + _GLOBAL(_start); 58 58 59 59 mr r31,r3 /* save device tree ptr */ 60 60 ··· 82 82 */ 83 83 . = 0xc0 84 84 crit_save: 85 - _ENTRY(crit_r10) 85 + _GLOBAL(crit_r10) 86 86 .space 4 87 - _ENTRY(crit_r11) 87 + _GLOBAL(crit_r11) 88 88 .space 4 89 - _ENTRY(crit_srr0) 89 + _GLOBAL(crit_srr0) 90 90 .space 4 91 - _ENTRY(crit_srr1) 91 + _GLOBAL(crit_srr1) 92 92 .space 4 93 - _ENTRY(crit_r1) 93 + _GLOBAL(crit_r1) 94 94 .space 4 95 - _ENTRY(crit_dear) 95 + _GLOBAL(crit_dear) 96 96 .space 4 97 - _ENTRY(crit_esr) 97 + _GLOBAL(crit_esr) 98 98 .space 4 99 99 100 100 /*
+2 -2
arch/powerpc/kernel/head_44x.S
··· 52 52 * 53 53 */ 54 54 __HEAD 55 - _ENTRY(_stext); 56 - _ENTRY(_start); 55 + _GLOBAL(_stext); 56 + _GLOBAL(_start); 57 57 /* 58 58 * Reserve a word at a fixed location to store the address 59 59 * of abatron_pteptrs
+2 -2
arch/powerpc/kernel/head_8xx.S
··· 53 53 #define PAGE_SHIFT_8M 23 54 54 55 55 __HEAD 56 - _ENTRY(_stext); 57 - _ENTRY(_start); 56 + _GLOBAL(_stext); 57 + _GLOBAL(_start); 58 58 59 59 /* MPC8xx 60 60 * This port was done on an MBX board with an 860. Right now I only
+6 -15
arch/powerpc/kernel/head_book3s_32.S
··· 50 50 mtspr SPRN_DBAT##n##L,RB 51 51 52 52 __HEAD 53 - .stabs "arch/powerpc/kernel/",N_SO,0,0,0f 54 - .stabs "head_book3s_32.S",N_SO,0,0,0f 55 - 0: 56 - _ENTRY(_stext); 53 + _GLOBAL(_stext); 57 54 58 55 /* 59 56 * _start is defined this way because the XCOFF loader in the OpenFirmware 60 57 * on the powermac expects the entry point to be a procedure descriptor. 61 58 */ 62 - _ENTRY(_start); 59 + _GLOBAL(_start); 63 60 /* 64 61 * These are here for legacy reasons, the kernel used to 65 62 * need to look like a coff function entry for the pmac ··· 501 504 lwz r0,0(r2) /* get linux-style pte */ 502 505 andc. r1,r1,r0 /* check access & ~permission */ 503 506 bne- DataAddressInvalid /* return if access not permitted */ 504 - /* 505 - * NOTE! We are assuming this is not an SMP system, otherwise 506 - * we would need to update the pte atomically with lwarx/stwcx. 507 - */ 508 507 /* Convert linux-style PTE to low word of PPC-style PTE */ 509 508 rlwinm r1,r0,32-9,30,30 /* _PAGE_RW -> PP msb */ 510 509 rlwimi r0,r0,32-1,30,30 /* _PAGE_USER -> PP msb */ 510 + rlwimi r1,r0,32-3,24,24 /* _PAGE_RW -> _PAGE_DIRTY */ 511 511 rlwimi r0,r0,32-1,31,31 /* _PAGE_USER -> PP lsb */ 512 + xori r1,r1,_PAGE_DIRTY /* clear dirty when not rw */ 512 513 ori r1,r1,0xe04 /* clear out reserved bits */ 513 514 andc r1,r0,r1 /* PP = user? rw? 1: 3: 0 */ 514 515 BEGIN_FTR_SECTION ··· 581 586 lwz r0,0(r2) /* get linux-style pte */ 582 587 andc. r1,r1,r0 /* check access & ~permission */ 583 588 bne- DataAddressInvalid /* return if access not permitted */ 584 - /* 585 - * NOTE! We are assuming this is not an SMP system, otherwise 586 - * we would need to update the pte atomically with lwarx/stwcx. 587 - */ 588 589 /* Convert linux-style PTE to low word of PPC-style PTE */ 589 590 rlwimi r0,r0,32-2,31,31 /* _PAGE_USER -> PP lsb */ 590 591 li r1,0xe06 /* clear out reserved bits & PP msb */ ··· 775 784 * r3 = dest addr, r4 = source addr, r5 = copy limit, r6 = start offset 776 785 * on exit, r3, r4, r5 are unchanged, r6 is updated to be >= r5. 777 786 */ 778 - _ENTRY(copy_and_flush) 787 + _GLOBAL(copy_and_flush) 779 788 addi r5,r5,-4 780 789 addi r6,r6,-4 781 790 4: li r0,L1_CACHE_BYTES/4 ··· 1073 1082 END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS) 1074 1083 blr 1075 1084 1076 - _ENTRY(update_bats) 1085 + _GLOBAL(update_bats) 1077 1086 lis r4, 1f@h 1078 1087 ori r4, r4, 1f@l 1079 1088 tophys(r4, r4)
+3 -3
arch/powerpc/kernel/head_fsl_booke.S
··· 54 54 * 55 55 */ 56 56 __HEAD 57 - _ENTRY(_stext); 58 - _ENTRY(_start); 57 + _GLOBAL(_stext); 58 + _GLOBAL(_start); 59 59 /* 60 60 * Reserve a word at a fixed location to store the address 61 61 * of abatron_pteptrs ··· 154 154 * if needed 155 155 */ 156 156 157 - _ENTRY(__early_start) 157 + _GLOBAL(__early_start) 158 158 LOAD_REG_ADDR_PIC(r20, kernstart_virt_addr) 159 159 lwz r20,0(r20) 160 160
-1
arch/powerpc/kernel/interrupt.c
··· 5 5 #include <linux/compat.h> 6 6 #include <linux/sched/debug.h> /* for show_regs */ 7 7 8 - #include <asm/asm-prototypes.h> 9 8 #include <asm/kup.h> 10 9 #include <asm/cputime.h> 11 10 #include <asm/hw_irq.h>
-1
arch/powerpc/kernel/irq.c
··· 64 64 #include <asm/udbg.h> 65 65 #include <asm/smp.h> 66 66 #include <asm/livepatch.h> 67 - #include <asm/asm-prototypes.h> 68 67 #include <asm/hw_irq.h> 69 68 #include <asm/softirq_stack.h> 70 69
+36 -33
arch/powerpc/kernel/mce.c
··· 24 24 #include <asm/machdep.h> 25 25 #include <asm/mce.h> 26 26 #include <asm/nmi.h> 27 - #include <asm/asm-prototypes.h> 28 27 29 28 #include "setup.h" 30 29 31 - static void machine_check_process_queued_event(struct irq_work *work); 32 - static void machine_check_ue_irq_work(struct irq_work *work); 33 30 static void machine_check_ue_event(struct machine_check_event *evt); 34 31 static void machine_process_ue_event(struct work_struct *work); 35 - 36 - static struct irq_work mce_event_process_work = { 37 - .func = machine_check_process_queued_event, 38 - }; 39 - 40 - static struct irq_work mce_ue_event_irq_work = { 41 - .func = machine_check_ue_irq_work, 42 - }; 43 32 44 33 static DECLARE_WORK(mce_ue_event_work, machine_process_ue_event); 45 34 ··· 76 87 default: 77 88 break; 78 89 } 90 + } 91 + 92 + void mce_irq_work_queue(void) 93 + { 94 + /* Raise decrementer interrupt */ 95 + arch_irq_work_raise(); 96 + set_mce_pending_irq_work(); 79 97 } 80 98 81 99 /* ··· 213 217 get_mce_event(NULL, true); 214 218 } 215 219 216 - static void machine_check_ue_irq_work(struct irq_work *work) 220 + static void machine_check_ue_work(void) 217 221 { 218 222 schedule_work(&mce_ue_event_work); 219 223 } ··· 235 239 evt, sizeof(*evt)); 236 240 237 241 /* Queue work to process this event later. */ 238 - irq_work_queue(&mce_ue_event_irq_work); 242 + mce_irq_work_queue(); 239 243 } 240 244 241 245 /* ··· 245 249 { 246 250 int index; 247 251 struct machine_check_event evt; 248 - unsigned long msr; 249 252 250 253 if (!get_mce_event(&evt, MCE_EVENT_RELEASE)) 251 254 return; ··· 258 263 memcpy(&local_paca->mce_info->mce_event_queue[index], 259 264 &evt, sizeof(evt)); 260 265 261 - /* 262 - * Queue irq work to process this event later. Before 263 - * queuing the work enable translation for non radix LPAR, 264 - * as irq_work_queue may try to access memory outside RMO 265 - * region. 266 - */ 267 - if (!radix_enabled() && firmware_has_feature(FW_FEATURE_LPAR)) { 268 - msr = mfmsr(); 269 - mtmsr(msr | MSR_IR | MSR_DR); 270 - irq_work_queue(&mce_event_process_work); 271 - mtmsr(msr); 272 - } else { 273 - irq_work_queue(&mce_event_process_work); 274 - } 266 + mce_irq_work_queue(); 275 267 } 276 268 277 269 void mce_common_process_ue(struct pt_regs *regs, ··· 320 338 * process pending MCE event from the mce event queue. This function will be 321 339 * called during syscall exit. 322 340 */ 323 - static void machine_check_process_queued_event(struct irq_work *work) 341 + static void machine_check_process_queued_event(void) 324 342 { 325 343 int index; 326 344 struct machine_check_event *evt; ··· 342 360 } 343 361 machine_check_print_event_info(evt, false, false); 344 362 local_paca->mce_info->mce_queue_count--; 363 + } 364 + } 365 + 366 + void set_mce_pending_irq_work(void) 367 + { 368 + local_paca->mce_pending_irq_work = 1; 369 + } 370 + 371 + void clear_mce_pending_irq_work(void) 372 + { 373 + local_paca->mce_pending_irq_work = 0; 374 + } 375 + 376 + void mce_run_irq_context_handlers(void) 377 + { 378 + if (unlikely(local_paca->mce_pending_irq_work)) { 379 + if (ppc_md.machine_check_log_err) 380 + ppc_md.machine_check_log_err(); 381 + machine_check_process_queued_event(); 382 + machine_check_ue_work(); 383 + clear_mce_pending_irq_work(); 345 384 } 346 385 } 347 386 ··· 404 401 static const char *mc_ra_types[] = { 405 402 "Indeterminate", 406 403 "Instruction fetch (bad)", 407 - "Instruction fetch (foreign)", 404 + "Instruction fetch (foreign/control memory)", 408 405 "Page table walk ifetch (bad)", 409 - "Page table walk ifetch (foreign)", 406 + "Page table walk ifetch (foreign/control memory)", 410 407 "Load (bad)", 411 408 "Store (bad)", 412 409 "Page table walk Load/Store (bad)", 413 - "Page table walk Load/Store (foreign)", 414 - "Load/Store (foreign)", 410 + "Page table walk Load/Store (foreign/control memory)", 411 + "Load/Store (foreign/control memory)", 415 412 }; 416 413 static const char *mc_link_types[] = { 417 414 "Indeterminate",
+30 -14
arch/powerpc/kernel/module_32.c
··· 18 18 #include <linux/bug.h> 19 19 #include <linux/sort.h> 20 20 #include <asm/setup.h> 21 + #include <asm/code-patching.h> 21 22 22 23 /* Count how many different relocations (different symbol, different 23 24 addend) */ ··· 175 174 entry++; 176 175 } 177 176 178 - entry->jump[0] = PPC_RAW_LIS(_R12, PPC_HA(val)); 179 - entry->jump[1] = PPC_RAW_ADDI(_R12, _R12, PPC_LO(val)); 180 - entry->jump[2] = PPC_RAW_MTCTR(_R12); 181 - entry->jump[3] = PPC_RAW_BCTR(); 177 + if (patch_instruction(&entry->jump[0], ppc_inst(PPC_RAW_LIS(_R12, PPC_HA(val))))) 178 + return 0; 179 + if (patch_instruction(&entry->jump[1], ppc_inst(PPC_RAW_ADDI(_R12, _R12, PPC_LO(val))))) 180 + return 0; 181 + if (patch_instruction(&entry->jump[2], ppc_inst(PPC_RAW_MTCTR(_R12)))) 182 + return 0; 183 + if (patch_instruction(&entry->jump[3], ppc_inst(PPC_RAW_BCTR()))) 184 + return 0; 182 185 183 186 pr_debug("Initialized plt for 0x%x at %p\n", val, entry); 184 187 return (uint32_t)entry; 188 + } 189 + 190 + static int patch_location_16(uint32_t *loc, u16 value) 191 + { 192 + loc = PTR_ALIGN_DOWN(loc, sizeof(u32)); 193 + return patch_instruction(loc, ppc_inst((*loc & 0xffff0000) | value)); 185 194 } 186 195 187 196 int apply_relocate_add(Elf32_Shdr *sechdrs, ··· 227 216 228 217 case R_PPC_ADDR16_LO: 229 218 /* Low half of the symbol */ 230 - *(uint16_t *)location = value; 219 + if (patch_location_16(location, PPC_LO(value))) 220 + return -EFAULT; 231 221 break; 232 222 233 223 case R_PPC_ADDR16_HI: 234 224 /* Higher half of the symbol */ 235 - *(uint16_t *)location = (value >> 16); 225 + if (patch_location_16(location, PPC_HI(value))) 226 + return -EFAULT; 236 227 break; 237 228 238 229 case R_PPC_ADDR16_HA: 239 - /* Sign-adjusted lower 16 bits: PPC ELF ABI says: 240 - (((x >> 16) + ((x & 0x8000) ? 1 : 0))) & 0xFFFF. 241 - This is the same, only sane. 242 - */ 243 - *(uint16_t *)location = (value + 0x8000) >> 16; 230 + if (patch_location_16(location, PPC_HA(value))) 231 + return -EFAULT; 244 232 break; 245 233 246 234 case R_PPC_REL24: 247 235 if ((int)(value - (uint32_t)location) < -0x02000000 248 - || (int)(value - (uint32_t)location) >= 0x02000000) 236 + || (int)(value - (uint32_t)location) >= 0x02000000) { 249 237 value = do_plt_call(location, value, 250 238 sechdrs, module); 239 + if (!value) 240 + return -EFAULT; 241 + } 251 242 252 243 /* Only replace bits 2 through 26 */ 253 244 pr_debug("REL24 value = %08X. location = %08X\n", 254 245 value, (uint32_t)location); 255 246 pr_debug("Location before: %08X.\n", 256 247 *(uint32_t *)location); 257 - *(uint32_t *)location 258 - = (*(uint32_t *)location & ~0x03fffffc) 248 + value = (*(uint32_t *)location & ~0x03fffffc) 259 249 | ((value - (uint32_t)location) 260 250 & 0x03fffffc); 251 + 252 + if (patch_instruction(location, ppc_inst(value))) 253 + return -EFAULT; 254 + 261 255 pr_debug("Location after: %08X.\n", 262 256 *(uint32_t *)location); 263 257 pr_debug("ie. jump to %08X+%08X = %08X\n",
+25 -31
arch/powerpc/kernel/module_64.c
··· 14 14 #include <linux/ftrace.h> 15 15 #include <linux/bug.h> 16 16 #include <linux/uaccess.h> 17 + #include <linux/kernel.h> 17 18 #include <asm/module.h> 18 19 #include <asm/firmware.h> 19 20 #include <asm/code-patching.h> ··· 33 32 34 33 #ifdef PPC64_ELF_ABI_v2 35 34 36 - /* An address is simply the address of the function. */ 37 - typedef unsigned long func_desc_t; 38 - 39 35 static func_desc_t func_desc(unsigned long addr) 40 36 { 41 - return addr; 42 - } 43 - static unsigned long func_addr(unsigned long addr) 44 - { 45 - return addr; 46 - } 47 - static unsigned long stub_func_addr(func_desc_t func) 48 - { 49 - return func; 37 + func_desc_t desc = { 38 + .addr = addr, 39 + }; 40 + 41 + return desc; 50 42 } 51 43 52 44 /* PowerPC64 specific values for the Elf64_Sym st_other field. */ ··· 57 63 } 58 64 #else 59 65 60 - /* An address is address of the OPD entry, which contains address of fn. */ 61 - typedef struct ppc64_opd_entry func_desc_t; 62 - 63 66 static func_desc_t func_desc(unsigned long addr) 64 67 { 65 - return *(struct ppc64_opd_entry *)addr; 66 - } 67 - static unsigned long func_addr(unsigned long addr) 68 - { 69 - return func_desc(addr).funcaddr; 70 - } 71 - static unsigned long stub_func_addr(func_desc_t func) 72 - { 73 - return func.funcaddr; 68 + return *(struct func_desc *)addr; 74 69 } 75 70 static unsigned int local_entry_offset(const Elf64_Sym *sym) 76 71 { ··· 75 92 return dereference_function_descriptor(ptr); 76 93 } 77 94 #endif 95 + 96 + static unsigned long func_addr(unsigned long addr) 97 + { 98 + return func_desc(addr).addr; 99 + } 100 + 101 + static unsigned long stub_func_addr(func_desc_t func) 102 + { 103 + return func.addr; 104 + } 78 105 79 106 #define STUB_MAGIC 0x73747562 /* stub */ 80 107 ··· 180 187 static unsigned long get_stubs_size(const Elf64_Ehdr *hdr, 181 188 const Elf64_Shdr *sechdrs) 182 189 { 183 - /* One extra reloc so it's always 0-funcaddr terminated */ 190 + /* One extra reloc so it's always 0-addr terminated */ 184 191 unsigned long relocs = 1; 185 192 unsigned i; 186 193 ··· 270 277 return NULL; 271 278 } 272 279 280 + bool module_init_section(const char *name) 281 + { 282 + /* We don't handle .init for the moment: always return false. */ 283 + return false; 284 + } 285 + 273 286 int module_frob_arch_sections(Elf64_Ehdr *hdr, 274 287 Elf64_Shdr *sechdrs, 275 288 char *secstrings, ··· 285 286 286 287 /* Find .toc and .stubs sections, symtab and strtab */ 287 288 for (i = 1; i < hdr->e_shnum; i++) { 288 - char *p; 289 289 if (strcmp(secstrings + sechdrs[i].sh_name, ".stubs") == 0) 290 290 me->arch.stubs_section = i; 291 291 else if (strcmp(secstrings + sechdrs[i].sh_name, ".toc") == 0) { ··· 295 297 else if (strcmp(secstrings+sechdrs[i].sh_name,"__versions")==0) 296 298 dedotify_versions((void *)hdr + sechdrs[i].sh_offset, 297 299 sechdrs[i].sh_size); 298 - 299 - /* We don't handle .init for the moment: rename to _init */ 300 - while ((p = strstr(secstrings + sechdrs[i].sh_name, ".init"))) 301 - p[0] = '_'; 302 300 303 301 if (sechdrs[i].sh_type == SHT_SYMTAB) 304 302 dedotify((void *)hdr + sechdrs[i].sh_offset, ··· 422 428 if (is_mprofile_ftrace_call(name)) 423 429 return create_ftrace_stub(entry, addr, me); 424 430 425 - for (i = 0; i < sizeof(ppc64_stub_insns) / sizeof(u32); i++) { 431 + for (i = 0; i < ARRAY_SIZE(ppc64_stub_insns); i++) { 426 432 if (patch_instruction(&entry->jump[i], 427 433 ppc_inst(ppc64_stub_insns[i]))) 428 434 return 0;
+10 -5
arch/powerpc/kernel/prom.c
··· 352 352 be32_to_cpu(intserv[found_thread])); 353 353 boot_cpuid = found; 354 354 355 + // Pass the boot CPU's hard CPU id back to our caller 356 + *((u32 *)data) = be32_to_cpu(intserv[found_thread]); 357 + 355 358 /* 356 359 * PAPR defines "logical" PVR values for cpus that 357 360 * meet various levels of the architecture: ··· 391 388 cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; 392 389 else if (!dt_cpu_ftrs_in_use()) 393 390 cur_cpu_spec->cpu_features |= CPU_FTR_SMT; 394 - allocate_paca(boot_cpuid); 395 391 #endif 396 - set_hard_smp_processor_id(found, be32_to_cpu(intserv[found_thread])); 397 392 398 393 return 0; 399 394 } ··· 715 714 716 715 void __init early_init_devtree(void *params) 717 716 { 717 + u32 boot_cpu_hwid; 718 718 phys_addr_t limit; 719 719 720 720 DBG(" -> early_init_devtree(%px)\n", params); ··· 792 790 * FIXME .. and the initrd too? */ 793 791 move_device_tree(); 794 792 795 - allocate_paca_ptrs(); 796 - 797 793 DBG("Scanning CPUs ...\n"); 798 794 799 795 dt_cpu_ftrs_scan(); ··· 799 799 /* Retrieve CPU related informations from the flat tree 800 800 * (altivec support, boot CPU ID, ...) 801 801 */ 802 - of_scan_flat_dt(early_init_dt_scan_cpus, NULL); 802 + of_scan_flat_dt(early_init_dt_scan_cpus, &boot_cpu_hwid); 803 803 if (boot_cpuid < 0) { 804 804 printk("Failed to identify boot CPU !\n"); 805 805 BUG(); ··· 815 815 #endif 816 816 817 817 mmu_early_init_devtree(); 818 + 819 + // NB. paca is not installed until later in early_setup() 820 + allocate_paca_ptrs(); 821 + allocate_paca(boot_cpuid); 822 + set_hard_smp_processor_id(boot_cpuid, boot_cpu_hwid); 818 823 819 824 #ifdef CONFIG_PPC_POWERNV 820 825 /* Scan and build the list of machine check recoverable ranges */
+1 -1
arch/powerpc/kernel/ptrace/ptrace-view.c
··· 841 841 842 842 const struct user_regset_view *task_user_regset_view(struct task_struct *task) 843 843 { 844 - if (IS_ENABLED(CONFIG_PPC64) && test_tsk_thread_flag(task, TIF_32BIT)) 844 + if (IS_ENABLED(CONFIG_COMPAT) && is_tsk_32bit_task(task)) 845 845 return &user_ppc_compat_view; 846 846 return &user_ppc_native_view; 847 847 }
+6 -1
arch/powerpc/kernel/ptrace/ptrace.c
··· 22 22 #include <linux/syscalls.h> 23 23 24 24 #include <asm/switch_to.h> 25 - #include <asm/asm-prototypes.h> 26 25 #include <asm/debug.h> 27 26 28 27 #define CREATE_TRACE_POINTS ··· 444 445 * real registers. 445 446 */ 446 447 BUILD_BUG_ON(PT_DSCR < sizeof(struct user_pt_regs) / sizeof(unsigned long)); 448 + 449 + #ifdef PPC64_ELF_ABI_v1 450 + BUILD_BUG_ON(!IS_ENABLED(CONFIG_HAVE_FUNCTION_DESCRIPTORS)); 451 + #else 452 + BUILD_BUG_ON(IS_ENABLED(CONFIG_HAVE_FUNCTION_DESCRIPTORS)); 453 + #endif 447 454 }
+47 -20
arch/powerpc/kernel/reloc_64.S
··· 8 8 #include <asm/ppc_asm.h> 9 9 10 10 RELA = 7 11 - RELACOUNT = 0x6ffffff9 11 + RELASZ = 8 12 + RELAENT = 9 12 13 R_PPC64_RELATIVE = 22 14 + R_PPC64_UADDR64 = 43 13 15 14 16 /* 15 17 * r3 = desired final address of kernel ··· 27 25 add r9,r9,r12 /* r9 has runtime addr of .rela.dyn section */ 28 26 ld r10,(p_st - 0b)(r12) 29 27 add r10,r10,r12 /* r10 has runtime addr of _stext */ 28 + ld r13,(p_sym - 0b)(r12) 29 + add r13,r13,r12 /* r13 has runtime addr of .dynsym */ 30 30 31 31 /* 32 - * Scan the dynamic section for the RELA and RELACOUNT entries. 32 + * Scan the dynamic section for the RELA, RELASZ and RELAENT entries. 33 33 */ 34 34 li r7,0 35 35 li r8,0 36 - 1: ld r6,0(r11) /* get tag */ 36 + .Ltags: 37 + ld r6,0(r11) /* get tag */ 37 38 cmpdi r6,0 38 - beq 4f /* end of list */ 39 + beq .Lend_of_list /* end of list */ 39 40 cmpdi r6,RELA 40 41 bne 2f 41 42 ld r7,8(r11) /* get RELA pointer in r7 */ 42 - b 3f 43 - 2: addis r6,r6,(-RELACOUNT)@ha 44 - cmpdi r6,RELACOUNT@l 43 + b 4f 44 + 2: cmpdi r6,RELASZ 45 45 bne 3f 46 - ld r8,8(r11) /* get RELACOUNT value in r8 */ 47 - 3: addi r11,r11,16 48 - b 1b 49 - 4: cmpdi r7,0 /* check we have both RELA and RELACOUNT */ 46 + ld r8,8(r11) /* get RELASZ value in r8 */ 47 + b 4f 48 + 3: cmpdi r6,RELAENT 49 + bne 4f 50 + ld r12,8(r11) /* get RELAENT value in r12 */ 51 + 4: addi r11,r11,16 52 + b .Ltags 53 + .Lend_of_list: 54 + cmpdi r7,0 /* check we have RELA, RELASZ, RELAENT */ 50 55 cmpdi cr1,r8,0 51 - beq 6f 52 - beq cr1,6f 56 + beq .Lout 57 + beq cr1,.Lout 58 + cmpdi r12,0 59 + beq .Lout 53 60 54 61 /* 55 62 * Work out linktime address of _stext and hence the ··· 73 62 74 63 /* 75 64 * Run through the list of relocations and process the 76 - * R_PPC64_RELATIVE ones. 65 + * R_PPC64_RELATIVE and R_PPC64_UADDR64 ones. 77 66 */ 67 + divd r8,r8,r12 /* RELASZ / RELAENT */ 78 68 mtctr r8 79 - 5: ld r0,8(9) /* ELF64_R_TYPE(reloc->r_info) */ 69 + .Lrels: ld r0,8(r9) /* ELF64_R_TYPE(reloc->r_info) */ 80 70 cmpdi r0,R_PPC64_RELATIVE 81 - bne 6f 71 + bne .Luaddr64 82 72 ld r6,0(r9) /* reloc->r_offset */ 83 73 ld r0,16(r9) /* reloc->r_addend */ 74 + b .Lstore 75 + .Luaddr64: 76 + srdi r14,r0,32 /* ELF64_R_SYM(reloc->r_info) */ 77 + clrldi r0,r0,32 78 + cmpdi r0,R_PPC64_UADDR64 79 + bne .Lnext 80 + ld r6,0(r9) 81 + ld r0,16(r9) 82 + mulli r14,r14,24 /* 24 == sizeof(elf64_sym) */ 83 + add r14,r14,r13 /* elf64_sym[ELF64_R_SYM] */ 84 + ld r14,8(r14) 85 + add r0,r0,r14 86 + .Lstore: 84 87 add r0,r0,r3 85 88 stdx r0,r7,r6 86 - addi r9,r9,24 87 - bdnz 5b 88 - 89 - 6: blr 89 + .Lnext: 90 + add r9,r9,r12 91 + bdnz .Lrels 92 + .Lout: 93 + blr 90 94 91 95 .balign 8 92 96 p_dyn: .8byte __dynamic_start - 0b 93 97 p_rela: .8byte __rela_dyn_start - 0b 98 + p_sym: .8byte __dynamic_symtab - 0b 94 99 p_st: .8byte _stext - 0b 95 100
+6
arch/powerpc/kernel/rtas.c
··· 1313 1313 entryp = of_get_flat_dt_prop(node, "linux,rtas-entry", NULL); 1314 1314 sizep = of_get_flat_dt_prop(node, "rtas-size", NULL); 1315 1315 1316 + #ifdef CONFIG_PPC64 1317 + /* need this feature to decide the crashkernel offset */ 1318 + if (of_get_flat_dt_prop(node, "ibm,hypertas-functions", NULL)) 1319 + powerpc_firmware_features |= FW_FEATURE_LPAR; 1320 + #endif 1321 + 1316 1322 if (basep && entryp && sizep) { 1317 1323 rtas.base = *basep; 1318 1324 rtas.entry = *entryp;
+15
arch/powerpc/kernel/security.c
··· 747 747 return 0; 748 748 } 749 749 750 + static int link_stack_flush_get(void *data, u64 *val) 751 + { 752 + if (link_stack_flush_type == BRANCH_CACHE_FLUSH_NONE) 753 + *val = 0; 754 + else 755 + *val = 1; 756 + 757 + return 0; 758 + } 759 + 750 760 DEFINE_DEBUGFS_ATTRIBUTE(fops_count_cache_flush, count_cache_flush_get, 761 + count_cache_flush_set, "%llu\n"); 762 + DEFINE_DEBUGFS_ATTRIBUTE(fops_link_stack_flush, link_stack_flush_get, 751 763 count_cache_flush_set, "%llu\n"); 752 764 753 765 static __init int count_cache_flush_debugfs_init(void) ··· 767 755 debugfs_create_file_unsafe("count_cache_flush", 0600, 768 756 arch_debugfs_dir, NULL, 769 757 &fops_count_cache_flush); 758 + debugfs_create_file_unsafe("link_stack_flush", 0600, 759 + arch_debugfs_dir, NULL, 760 + &fops_link_stack_flush); 770 761 return 0; 771 762 } 772 763 device_initcall(count_cache_flush_debugfs_init);
+6 -3
arch/powerpc/kernel/secvar-sysfs.c
··· 26 26 const char *format; 27 27 28 28 node = of_find_compatible_node(NULL, NULL, "ibm,secvar-backend"); 29 - if (!of_device_is_available(node)) 30 - return -ENODEV; 29 + if (!of_device_is_available(node)) { 30 + rc = -ENODEV; 31 + goto out; 32 + } 31 33 32 34 rc = of_property_read_string(node, "format", &format); 33 35 if (rc) 34 - return rc; 36 + goto out; 35 37 36 38 rc = sprintf(buf, "%s\n", format); 37 39 40 + out: 38 41 of_node_put(node); 39 42 40 43 return rc;
+2 -2
arch/powerpc/kernel/setup-common.c
··· 456 456 intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", 457 457 &len); 458 458 if (intserv) { 459 - DBG(" ibm,ppc-interrupt-server#s -> %d threads\n", 460 - nthreads); 459 + DBG(" ibm,ppc-interrupt-server#s -> %lu threads\n", 460 + (len / sizeof(int))); 461 461 } else { 462 462 DBG(" no ibm,ppc-interrupt-server#s -> 1 thread\n"); 463 463 intserv = of_get_property(dn, "reg", &len);
-1
arch/powerpc/kernel/setup_64.c
··· 67 67 #include <asm/kup.h> 68 68 #include <asm/early_ioremap.h> 69 69 #include <asm/pgalloc.h> 70 - #include <asm/asm-prototypes.h> 71 70 72 71 #include "setup.h" 73 72
+4 -4
arch/powerpc/kernel/signal_64.c
··· 936 936 * descriptor is the entry address of signal and the second 937 937 * entry is the TOC value we need to use. 938 938 */ 939 - func_descr_t __user *funct_desc_ptr = 940 - (func_descr_t __user *) ksig->ka.sa.sa_handler; 939 + struct func_desc __user *ptr = 940 + (struct func_desc __user *)ksig->ka.sa.sa_handler; 941 941 942 - err |= get_user(regs->ctr, &funct_desc_ptr->entry); 943 - err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); 942 + err |= get_user(regs->ctr, &ptr->addr); 943 + err |= get_user(regs->gpr[2], &ptr->toc); 944 944 } 945 945 946 946 /* enter the signal handler in native-endian mode */
+1 -2
arch/powerpc/kernel/smp.c
··· 57 57 #include <asm/vdso.h> 58 58 #include <asm/debug.h> 59 59 #include <asm/kexec.h> 60 - #include <asm/asm-prototypes.h> 61 60 #include <asm/cpu_has_feature.h> 62 61 #include <asm/ftrace.h> 63 62 #include <asm/kup.h> ··· 715 716 } 716 717 #endif /* CONFIG_NMI_IPI */ 717 718 718 - struct task_struct *current_set[NR_CPUS]; 719 + static struct task_struct *current_set[NR_CPUS]; 719 720 720 721 static void smp_store_cpu_info(int id) 721 722 {
-1
arch/powerpc/kernel/syscalls.c
··· 35 35 #include <asm/syscalls.h> 36 36 #include <asm/time.h> 37 37 #include <asm/unistd.h> 38 - #include <asm/asm-prototypes.h> 39 38 40 39 static inline long do_mmap2(unsigned long addr, size_t len, 41 40 unsigned long prot, unsigned long flags,
-1
arch/powerpc/kernel/tau_6xx.c
··· 29 29 #include <asm/cache.h> 30 30 #include <asm/8xx_immap.h> 31 31 #include <asm/machdep.h> 32 - #include <asm/asm-prototypes.h> 33 32 34 33 #include "setup.h" 35 34
+15 -11
arch/powerpc/kernel/time.c
··· 69 69 #include <asm/smp.h> 70 70 #include <asm/vdso_datapage.h> 71 71 #include <asm/firmware.h> 72 - #include <asm/asm-prototypes.h> 72 + #include <asm/mce.h> 73 73 74 74 /* powerpc clocksource/clockevent code */ 75 75 ··· 107 107 }; 108 108 EXPORT_SYMBOL(decrementer_clockevent); 109 109 110 - DEFINE_PER_CPU(u64, decrementers_next_tb); 110 + /* 111 + * This always puts next_tb beyond now, so the clock event will never fire 112 + * with the usual comparison, no need for a separate test for stopped. 113 + */ 114 + #define DEC_CLOCKEVENT_STOPPED ~0ULL 115 + DEFINE_PER_CPU(u64, decrementers_next_tb) = DEC_CLOCKEVENT_STOPPED; 111 116 EXPORT_SYMBOL_GPL(decrementers_next_tb); 112 117 static DEFINE_PER_CPU(struct clock_event_device, decrementers); 113 118 ··· 587 582 local_paca->irq_happened |= PACA_IRQ_DEC; 588 583 } else { 589 584 now = *next_tb - now; 590 - if (now <= decrementer_max) 591 - set_dec_or_work(now); 585 + if (now > decrementer_max) 586 + now = decrementer_max; 587 + set_dec_or_work(now); 592 588 } 593 589 } 594 590 EXPORT_SYMBOL_GPL(timer_rearm_host_dec); ··· 644 638 645 639 if (test_irq_work_pending()) { 646 640 clear_irq_work_pending(); 641 + mce_run_irq_context_handlers(); 647 642 irq_work_run(); 648 643 } 649 644 650 645 now = get_tb(); 651 646 if (now >= *next_tb) { 652 - *next_tb = ~(u64)0; 653 - if (evt->event_handler) 654 - evt->event_handler(evt); 647 + evt->event_handler(evt); 655 648 __this_cpu_inc(irq_stat.timer_irqs_event); 656 649 } else { 657 650 now = *next_tb - now; ··· 669 664 #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST 670 665 void timer_broadcast_interrupt(void) 671 666 { 672 - u64 *next_tb = this_cpu_ptr(&decrementers_next_tb); 673 - 674 - *next_tb = ~(u64)0; 675 667 tick_receive_broadcast(); 676 668 __this_cpu_inc(irq_stat.broadcast_irqs_event); 677 669 } ··· 894 892 895 893 static int decrementer_shutdown(struct clock_event_device *dev) 896 894 { 897 - decrementer_set_next_event(decrementer_max, dev); 895 + __this_cpu_write(decrementers_next_tb, DEC_CLOCKEVENT_STOPPED); 896 + set_dec_or_work(decrementer_max); 897 + 898 898 return 0; 899 899 } 900 900
+16 -9
arch/powerpc/kernel/tm.S
··· 443 443 444 444 REST_GPR(0, r7) /* GPR0 */ 445 445 REST_GPRS(2, 4, r7) /* GPR2-4 */ 446 - REST_GPRS(8, 31, r7) /* GPR8-31 */ 446 + REST_GPRS(8, 12, r7) /* GPR8-12 */ 447 + REST_GPRS(14, 31, r7) /* GPR14-31 */ 447 448 448 449 /* Load up PPR and DSCR here so we don't run with user values for long */ 449 450 mtspr SPRN_DSCR, r5 ··· 480 479 REST_GPR(6, r7) 481 480 482 481 /* 483 - * Store r1 and r5 on the stack so that we can access them after we 484 - * clear MSR RI. 482 + * Store user r1 and r5 and r13 on the stack (in the unused save 483 + * areas / compiler reserved areas), so that we can access them after 484 + * we clear MSR RI. 485 485 */ 486 486 487 487 REST_GPR(5, r7) 488 488 std r5, -8(r1) 489 - ld r5, GPR1(r7) 489 + ld r5, GPR13(r7) 490 490 std r5, -16(r1) 491 + ld r5, GPR1(r7) 492 + std r5, -24(r1) 491 493 492 494 REST_GPR(7, r7) 493 495 494 - /* Clear MSR RI since we are about to use SCRATCH0. EE is already off */ 496 + /* Stash the stack pointer away for use after recheckpoint */ 497 + std r1, PACAR1(r13) 498 + 499 + /* Clear MSR RI since we are about to clobber r13. EE is already off */ 495 500 li r5, 0 496 501 mtmsrd r5, 1 497 502 ··· 508 501 * until we turn MSR RI back on. 509 502 */ 510 503 511 - SET_SCRATCH0(r1) 512 504 ld r5, -8(r1) 513 - ld r1, -16(r1) 505 + ld r13, -16(r1) 506 + ld r1, -24(r1) 514 507 515 508 /* Commit register state as checkpointed state: */ 516 509 TRECHKPT ··· 526 519 */ 527 520 528 521 GET_PACA(r13) 529 - GET_SCRATCH0(r1) 522 + ld r1, PACAR1(r13) 530 523 531 - /* R1 is restored, so we are recoverable again. EE is still off */ 524 + /* R13, R1 is restored, so we are recoverable again. EE is still off */ 532 525 li r4, MSR_RI 533 526 mtmsrd r4, 1 534 527
+3 -3
arch/powerpc/kernel/trace/Makefile
··· 8 8 CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE) 9 9 endif 10 10 11 - obj32-$(CONFIG_FUNCTION_TRACER) += ftrace_32.o 12 - obj64-$(CONFIG_FUNCTION_TRACER) += ftrace_64.o 11 + obj32-$(CONFIG_FUNCTION_TRACER) += ftrace_mprofile.o 13 12 ifdef CONFIG_MPROFILE_KERNEL 14 - obj64-$(CONFIG_FUNCTION_TRACER) += ftrace_64_mprofile.o 13 + obj64-$(CONFIG_FUNCTION_TRACER) += ftrace_mprofile.o 15 14 else 16 15 obj64-$(CONFIG_FUNCTION_TRACER) += ftrace_64_pg.o 17 16 endif 17 + obj-$(CONFIG_FUNCTION_TRACER) += ftrace_low.o 18 18 obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o 19 19 obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o 20 20 obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o
+27 -13
arch/powerpc/kernel/trace/ftrace.c
··· 22 22 #include <linux/init.h> 23 23 #include <linux/list.h> 24 24 25 - #include <asm/asm-prototypes.h> 26 25 #include <asm/cacheflush.h> 27 26 #include <asm/code-patching.h> 28 27 #include <asm/ftrace.h> ··· 909 910 extern void ftrace_graph_call(void); 910 911 extern void ftrace_graph_stub(void); 911 912 912 - int ftrace_enable_ftrace_graph_caller(void) 913 + static int ftrace_modify_ftrace_graph_caller(bool enable) 913 914 { 914 915 unsigned long ip = (unsigned long)(&ftrace_graph_call); 915 916 unsigned long addr = (unsigned long)(&ftrace_graph_caller); 916 917 unsigned long stub = (unsigned long)(&ftrace_graph_stub); 917 918 ppc_inst_t old, new; 918 919 919 - old = ftrace_call_replace(ip, stub, 0); 920 - new = ftrace_call_replace(ip, addr, 0); 920 + if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_ARGS)) 921 + return 0; 922 + 923 + old = ftrace_call_replace(ip, enable ? stub : addr, 0); 924 + new = ftrace_call_replace(ip, enable ? addr : stub, 0); 921 925 922 926 return ftrace_modify_code(ip, old, new); 923 927 } 924 928 929 + int ftrace_enable_ftrace_graph_caller(void) 930 + { 931 + return ftrace_modify_ftrace_graph_caller(true); 932 + } 933 + 925 934 int ftrace_disable_ftrace_graph_caller(void) 926 935 { 927 - unsigned long ip = (unsigned long)(&ftrace_graph_call); 928 - unsigned long addr = (unsigned long)(&ftrace_graph_caller); 929 - unsigned long stub = (unsigned long)(&ftrace_graph_stub); 930 - ppc_inst_t old, new; 931 - 932 - old = ftrace_call_replace(ip, addr, 0); 933 - new = ftrace_call_replace(ip, stub, 0); 934 - 935 - return ftrace_modify_code(ip, old, new); 936 + return ftrace_modify_ftrace_graph_caller(false); 936 937 } 937 938 938 939 /* ··· 943 944 unsigned long sp) 944 945 { 945 946 unsigned long return_hooker; 947 + int bit; 946 948 947 949 if (unlikely(ftrace_graph_is_dead())) 948 950 goto out; ··· 951 951 if (unlikely(atomic_read(&current->tracing_graph_pause))) 952 952 goto out; 953 953 954 + bit = ftrace_test_recursion_trylock(ip, parent); 955 + if (bit < 0) 956 + goto out; 957 + 954 958 return_hooker = ppc_function_entry(return_to_handler); 955 959 956 960 if (!function_graph_enter(parent, ip, 0, (unsigned long *)sp)) 957 961 parent = return_hooker; 962 + 963 + ftrace_test_recursion_unlock(bit); 958 964 out: 959 965 return parent; 960 966 } 967 + 968 + #ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS 969 + void ftrace_graph_func(unsigned long ip, unsigned long parent_ip, 970 + struct ftrace_ops *op, struct ftrace_regs *fregs) 971 + { 972 + fregs->regs.link = prepare_ftrace_return(parent_ip, ip, fregs->regs.gpr[1]); 973 + } 974 + #endif 961 975 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 962 976 963 977 #ifdef PPC64_ELF_ABI_v1
-187
arch/powerpc/kernel/trace/ftrace_32.S
··· 1 - /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 - /* 3 - * Split from entry_32.S 4 - */ 5 - 6 - #include <linux/magic.h> 7 - #include <asm/reg.h> 8 - #include <asm/ppc_asm.h> 9 - #include <asm/asm-offsets.h> 10 - #include <asm/ftrace.h> 11 - #include <asm/export.h> 12 - #include <asm/ptrace.h> 13 - 14 - _GLOBAL(mcount) 15 - _GLOBAL(_mcount) 16 - /* 17 - * It is required that _mcount on PPC32 must preserve the 18 - * link register. But we have r12 to play with. We use r12 19 - * to push the return address back to the caller of mcount 20 - * into the ctr register, restore the link register and 21 - * then jump back using the ctr register. 22 - */ 23 - mflr r12 24 - mtctr r12 25 - mtlr r0 26 - bctr 27 - EXPORT_SYMBOL(_mcount) 28 - 29 - _GLOBAL(ftrace_caller) 30 - MCOUNT_SAVE_FRAME 31 - /* r3 ends up with link register */ 32 - subi r3, r3, MCOUNT_INSN_SIZE 33 - lis r5,function_trace_op@ha 34 - lwz r5,function_trace_op@l(r5) 35 - li r6, 0 36 - .globl ftrace_call 37 - ftrace_call: 38 - bl ftrace_stub 39 - nop 40 - MCOUNT_RESTORE_FRAME 41 - ftrace_caller_common: 42 - #ifdef CONFIG_FUNCTION_GRAPH_TRACER 43 - .globl ftrace_graph_call 44 - ftrace_graph_call: 45 - b ftrace_graph_stub 46 - _GLOBAL(ftrace_graph_stub) 47 - #endif 48 - /* old link register ends up in ctr reg */ 49 - bctr 50 - 51 - 52 - _GLOBAL(ftrace_stub) 53 - blr 54 - 55 - _GLOBAL(ftrace_regs_caller) 56 - /* Save the original return address in A's stack frame */ 57 - stw r0,LRSAVE(r1) 58 - 59 - /* Create our stack frame + pt_regs */ 60 - stwu r1,-INT_FRAME_SIZE(r1) 61 - 62 - /* Save all gprs to pt_regs */ 63 - stw r0, GPR0(r1) 64 - stmw r2, GPR2(r1) 65 - 66 - /* Save previous stack pointer (r1) */ 67 - addi r8, r1, INT_FRAME_SIZE 68 - stw r8, GPR1(r1) 69 - 70 - /* Load special regs for save below */ 71 - mfmsr r8 72 - mfctr r9 73 - mfxer r10 74 - mfcr r11 75 - 76 - /* Get the _mcount() call site out of LR */ 77 - mflr r7 78 - /* Save it as pt_regs->nip */ 79 - stw r7, _NIP(r1) 80 - /* Save the read LR in pt_regs->link */ 81 - stw r0, _LINK(r1) 82 - 83 - lis r3,function_trace_op@ha 84 - lwz r5,function_trace_op@l(r3) 85 - 86 - /* Calculate ip from nip-4 into r3 for call below */ 87 - subi r3, r7, MCOUNT_INSN_SIZE 88 - 89 - /* Put the original return address in r4 as parent_ip */ 90 - mr r4, r0 91 - 92 - /* Save special regs */ 93 - stw r8, _MSR(r1) 94 - stw r9, _CTR(r1) 95 - stw r10, _XER(r1) 96 - stw r11, _CCR(r1) 97 - 98 - /* Load &pt_regs in r6 for call below */ 99 - addi r6, r1, STACK_FRAME_OVERHEAD 100 - 101 - /* ftrace_call(r3, r4, r5, r6) */ 102 - .globl ftrace_regs_call 103 - ftrace_regs_call: 104 - bl ftrace_stub 105 - nop 106 - 107 - /* Load ctr with the possibly modified NIP */ 108 - lwz r3, _NIP(r1) 109 - mtctr r3 110 - 111 - /* Restore gprs */ 112 - lmw r2, GPR2(r1) 113 - 114 - /* Restore possibly modified LR */ 115 - lwz r0, _LINK(r1) 116 - mtlr r0 117 - 118 - /* Pop our stack frame */ 119 - addi r1, r1, INT_FRAME_SIZE 120 - 121 - b ftrace_caller_common 122 - 123 - #ifdef CONFIG_FUNCTION_GRAPH_TRACER 124 - _GLOBAL(ftrace_graph_caller) 125 - stwu r1,-48(r1) 126 - stw r3, 12(r1) 127 - stw r4, 16(r1) 128 - stw r5, 20(r1) 129 - stw r6, 24(r1) 130 - stw r7, 28(r1) 131 - stw r8, 32(r1) 132 - stw r9, 36(r1) 133 - stw r10,40(r1) 134 - 135 - addi r5, r1, 48 136 - mfctr r4 /* ftrace_caller has moved local addr here */ 137 - stw r4, 44(r1) 138 - mflr r3 /* ftrace_caller has restored LR from stack */ 139 - subi r4, r4, MCOUNT_INSN_SIZE 140 - 141 - bl prepare_ftrace_return 142 - nop 143 - 144 - /* 145 - * prepare_ftrace_return gives us the address we divert to. 146 - * Change the LR in the callers stack frame to this. 147 - */ 148 - stw r3,52(r1) 149 - mtlr r3 150 - lwz r0,44(r1) 151 - mtctr r0 152 - 153 - lwz r3, 12(r1) 154 - lwz r4, 16(r1) 155 - lwz r5, 20(r1) 156 - lwz r6, 24(r1) 157 - lwz r7, 28(r1) 158 - lwz r8, 32(r1) 159 - lwz r9, 36(r1) 160 - lwz r10,40(r1) 161 - 162 - addi r1, r1, 48 163 - 164 - bctr 165 - 166 - _GLOBAL(return_to_handler) 167 - /* need to save return values */ 168 - stwu r1, -32(r1) 169 - stw r3, 20(r1) 170 - stw r4, 16(r1) 171 - stw r31, 12(r1) 172 - mr r31, r1 173 - 174 - bl ftrace_return_to_handler 175 - nop 176 - 177 - /* return value has real return address */ 178 - mtlr r3 179 - 180 - lwz r3, 20(r1) 181 - lwz r4, 16(r1) 182 - lwz r31,12(r1) 183 - lwz r1, 0(r1) 184 - 185 - /* Jump back to real return address */ 186 - blr 187 - #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+14
arch/powerpc/kernel/trace/ftrace_64.S arch/powerpc/kernel/trace/ftrace_low.S
··· 10 10 #include <asm/ppc-opcode.h> 11 11 #include <asm/export.h> 12 12 13 + #ifdef CONFIG_PPC64 13 14 .pushsection ".tramp.ftrace.text","aw",@progbits; 14 15 .globl ftrace_tramp_text 15 16 ftrace_tramp_text: ··· 22 21 ftrace_tramp_init: 23 22 .space 64 24 23 .popsection 24 + #endif 25 25 26 26 _GLOBAL(mcount) 27 27 _GLOBAL(_mcount) ··· 35 33 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 36 34 _GLOBAL(return_to_handler) 37 35 /* need to save return values */ 36 + #ifdef CONFIG_PPC64 38 37 std r4, -32(r1) 39 38 std r3, -24(r1) 40 39 /* save TOC */ ··· 49 46 * Switch to our TOC to run inside the core kernel. 50 47 */ 51 48 ld r2, PACATOC(r13) 49 + #else 50 + stwu r1, -16(r1) 51 + stw r3, 8(r1) 52 + stw r4, 12(r1) 53 + #endif 52 54 53 55 bl ftrace_return_to_handler 54 56 nop ··· 61 53 /* return value has real return address */ 62 54 mtlr r3 63 55 56 + #ifdef CONFIG_PPC64 64 57 ld r1, 0(r1) 65 58 ld r4, -32(r1) 66 59 ld r3, -24(r1) 67 60 ld r2, -16(r1) 68 61 ld r31, -8(r1) 62 + #else 63 + lwz r3, 8(r1) 64 + lwz r4, 12(r1) 65 + addi r1, r1, 16 66 + #endif 69 67 70 68 /* Jump back to real return address */ 71 69 blr
+93 -167
arch/powerpc/kernel/trace/ftrace_64_mprofile.S arch/powerpc/kernel/trace/ftrace_mprofile.S
··· 32 32 * Our job is to save the register state into a struct pt_regs (on the stack) 33 33 * and then arrange for the ftrace function to be called. 34 34 */ 35 - _GLOBAL(ftrace_regs_caller) 36 - /* Save the original return address in A's stack frame */ 37 - std r0,LRSAVE(r1) 38 - 35 + .macro ftrace_regs_entry allregs 39 36 /* Create our stack frame + pt_regs */ 40 - stdu r1,-SWITCH_FRAME_SIZE(r1) 37 + PPC_STLU r1,-SWITCH_FRAME_SIZE(r1) 41 38 42 39 /* Save all gprs to pt_regs */ 43 40 SAVE_GPR(0, r1) 44 - SAVE_GPRS(2, 11, r1) 41 + SAVE_GPRS(3, 10, r1) 45 42 43 + #ifdef CONFIG_PPC64 44 + /* Save the original return address in A's stack frame */ 45 + std r0, LRSAVE+SWITCH_FRAME_SIZE(r1) 46 46 /* Ok to continue? */ 47 47 lbz r3, PACA_FTRACE_ENABLED(r13) 48 48 cmpdi r3, 0 49 49 beq ftrace_no_trace 50 + #endif 50 51 51 - SAVE_GPRS(12, 31, r1) 52 + .if \allregs == 1 53 + SAVE_GPR(2, r1) 54 + SAVE_GPRS(11, 31, r1) 55 + .else 56 + #ifdef CONFIG_LIVEPATCH_64 57 + SAVE_GPR(14, r1) 58 + #endif 59 + .endif 52 60 53 61 /* Save previous stack pointer (r1) */ 54 62 addi r8, r1, SWITCH_FRAME_SIZE 55 - std r8, GPR1(r1) 63 + PPC_STL r8, GPR1(r1) 56 64 65 + .if \allregs == 1 57 66 /* Load special regs for save below */ 58 67 mfmsr r8 59 68 mfctr r9 60 69 mfxer r10 61 70 mfcr r11 71 + .else 72 + /* Clear MSR to flag as ftrace_caller versus frace_regs_caller */ 73 + li r8, 0 74 + .endif 62 75 63 76 /* Get the _mcount() call site out of LR */ 64 77 mflr r7 65 78 /* Save it as pt_regs->nip */ 66 - std r7, _NIP(r1) 79 + PPC_STL r7, _NIP(r1) 67 80 /* Save the read LR in pt_regs->link */ 68 - std r0, _LINK(r1) 81 + PPC_STL r0, _LINK(r1) 69 82 83 + #ifdef CONFIG_PPC64 70 84 /* Save callee's TOC in the ABI compliant location */ 71 - std r2, 24(r1) 85 + std r2, STK_GOT(r1) 72 86 ld r2,PACATOC(r13) /* get kernel TOC in r2 */ 73 87 74 88 addis r3,r2,function_trace_op@toc@ha 75 89 addi r3,r3,function_trace_op@toc@l 76 90 ld r5,0(r3) 77 - 78 - #ifdef CONFIG_LIVEPATCH 79 - mr r14,r7 /* remember old NIP */ 91 + #else 92 + lis r3,function_trace_op@ha 93 + lwz r5,function_trace_op@l(r3) 80 94 #endif 95 + 96 + #ifdef CONFIG_LIVEPATCH_64 97 + mr r14, r7 /* remember old NIP */ 98 + #endif 99 + 81 100 /* Calculate ip from nip-4 into r3 for call below */ 82 101 subi r3, r7, MCOUNT_INSN_SIZE 83 102 ··· 104 85 mr r4, r0 105 86 106 87 /* Save special regs */ 107 - std r8, _MSR(r1) 108 - std r9, _CTR(r1) 109 - std r10, _XER(r1) 110 - std r11, _CCR(r1) 88 + PPC_STL r8, _MSR(r1) 89 + .if \allregs == 1 90 + PPC_STL r9, _CTR(r1) 91 + PPC_STL r10, _XER(r1) 92 + PPC_STL r11, _CCR(r1) 93 + .endif 111 94 112 95 /* Load &pt_regs in r6 for call below */ 113 - addi r6, r1 ,STACK_FRAME_OVERHEAD 96 + addi r6, r1, STACK_FRAME_OVERHEAD 97 + .endm 114 98 99 + .macro ftrace_regs_exit allregs 100 + /* Load ctr with the possibly modified NIP */ 101 + PPC_LL r3, _NIP(r1) 102 + mtctr r3 103 + 104 + #ifdef CONFIG_LIVEPATCH_64 105 + cmpd r14, r3 /* has NIP been altered? */ 106 + #endif 107 + 108 + /* Restore gprs */ 109 + .if \allregs == 1 110 + REST_GPRS(2, 31, r1) 111 + .else 112 + REST_GPRS(3, 10, r1) 113 + #ifdef CONFIG_LIVEPATCH_64 114 + REST_GPR(14, r1) 115 + #endif 116 + .endif 117 + 118 + /* Restore possibly modified LR */ 119 + PPC_LL r0, _LINK(r1) 120 + mtlr r0 121 + 122 + #ifdef CONFIG_PPC64 123 + /* Restore callee's TOC */ 124 + ld r2, STK_GOT(r1) 125 + #endif 126 + 127 + /* Pop our stack frame */ 128 + addi r1, r1, SWITCH_FRAME_SIZE 129 + 130 + #ifdef CONFIG_LIVEPATCH_64 131 + /* Based on the cmpd above, if the NIP was altered handle livepatch */ 132 + bne- livepatch_handler 133 + #endif 134 + bctr /* jump after _mcount site */ 135 + .endm 136 + 137 + _GLOBAL(ftrace_regs_caller) 138 + ftrace_regs_entry 1 115 139 /* ftrace_call(r3, r4, r5, r6) */ 116 140 .globl ftrace_regs_call 117 141 ftrace_regs_call: 118 142 bl ftrace_stub 119 143 nop 144 + ftrace_regs_exit 1 120 145 121 - /* Load ctr with the possibly modified NIP */ 122 - ld r3, _NIP(r1) 123 - mtctr r3 124 - #ifdef CONFIG_LIVEPATCH 125 - cmpd r14, r3 /* has NIP been altered? */ 126 - #endif 127 - 128 - /* Restore gprs */ 129 - REST_GPR(0, r1) 130 - REST_GPRS(2, 31, r1) 131 - 132 - /* Restore possibly modified LR */ 133 - ld r0, _LINK(r1) 134 - mtlr r0 135 - 136 - /* Restore callee's TOC */ 137 - ld r2, 24(r1) 138 - 139 - /* Pop our stack frame */ 140 - addi r1, r1, SWITCH_FRAME_SIZE 141 - 142 - #ifdef CONFIG_LIVEPATCH 143 - /* Based on the cmpd above, if the NIP was altered handle livepatch */ 144 - bne- livepatch_handler 145 - #endif 146 - 147 - ftrace_caller_common: 148 - #ifdef CONFIG_FUNCTION_GRAPH_TRACER 149 - .globl ftrace_graph_call 150 - ftrace_graph_call: 151 - b ftrace_graph_stub 152 - _GLOBAL(ftrace_graph_stub) 153 - #endif 154 - 155 - bctr /* jump after _mcount site */ 146 + _GLOBAL(ftrace_caller) 147 + ftrace_regs_entry 0 148 + /* ftrace_call(r3, r4, r5, r6) */ 149 + .globl ftrace_call 150 + ftrace_call: 151 + bl ftrace_stub 152 + nop 153 + ftrace_regs_exit 0 156 154 157 155 _GLOBAL(ftrace_stub) 158 156 blr 159 157 158 + #ifdef CONFIG_PPC64 160 159 ftrace_no_trace: 161 160 mflr r3 162 161 mtctr r3 ··· 182 145 addi r1, r1, SWITCH_FRAME_SIZE 183 146 mtlr r0 184 147 bctr 148 + #endif 185 149 186 - _GLOBAL(ftrace_caller) 187 - /* Save the original return address in A's stack frame */ 188 - std r0, LRSAVE(r1) 189 - 190 - /* Create our stack frame + pt_regs */ 191 - stdu r1, -SWITCH_FRAME_SIZE(r1) 192 - 193 - /* Save all gprs to pt_regs */ 194 - SAVE_GPRS(3, 10, r1) 195 - 196 - lbz r3, PACA_FTRACE_ENABLED(r13) 197 - cmpdi r3, 0 198 - beq ftrace_no_trace 199 - 200 - /* Get the _mcount() call site out of LR */ 201 - mflr r7 202 - std r7, _NIP(r1) 203 - 204 - /* Save callee's TOC in the ABI compliant location */ 205 - std r2, 24(r1) 206 - ld r2, PACATOC(r13) /* get kernel TOC in r2 */ 207 - 208 - addis r3, r2, function_trace_op@toc@ha 209 - addi r3, r3, function_trace_op@toc@l 210 - ld r5, 0(r3) 211 - 212 - /* Calculate ip from nip-4 into r3 for call below */ 213 - subi r3, r7, MCOUNT_INSN_SIZE 214 - 215 - /* Put the original return address in r4 as parent_ip */ 216 - mr r4, r0 217 - 218 - /* Set pt_regs to NULL */ 219 - li r6, 0 220 - 221 - /* ftrace_call(r3, r4, r5, r6) */ 222 - .globl ftrace_call 223 - ftrace_call: 224 - bl ftrace_stub 225 - nop 226 - 227 - ld r3, _NIP(r1) 228 - mtctr r3 229 - 230 - /* Restore gprs */ 231 - REST_GPRS(3, 10, r1) 232 - 233 - /* Restore callee's TOC */ 234 - ld r2, 24(r1) 235 - 236 - /* Pop our stack frame */ 237 - addi r1, r1, SWITCH_FRAME_SIZE 238 - 239 - /* Reload original LR */ 240 - ld r0, LRSAVE(r1) 241 - mtlr r0 242 - 243 - /* Handle function_graph or go back */ 244 - b ftrace_caller_common 245 - 246 - #ifdef CONFIG_LIVEPATCH 150 + #ifdef CONFIG_LIVEPATCH_64 247 151 /* 248 152 * This function runs in the mcount context, between two functions. As 249 153 * such it can only clobber registers which are volatile and used in ··· 251 273 /* Return to original caller of live patched function */ 252 274 blr 253 275 #endif /* CONFIG_LIVEPATCH */ 254 - 255 - #ifdef CONFIG_FUNCTION_GRAPH_TRACER 256 - _GLOBAL(ftrace_graph_caller) 257 - stdu r1, -112(r1) 258 - /* with -mprofile-kernel, parameter regs are still alive at _mcount */ 259 - std r10, 104(r1) 260 - std r9, 96(r1) 261 - std r8, 88(r1) 262 - std r7, 80(r1) 263 - std r6, 72(r1) 264 - std r5, 64(r1) 265 - std r4, 56(r1) 266 - std r3, 48(r1) 267 - 268 - /* Save callee's TOC in the ABI compliant location */ 269 - std r2, 24(r1) 270 - ld r2, PACATOC(r13) /* get kernel TOC in r2 */ 271 - 272 - addi r5, r1, 112 273 - mfctr r4 /* ftrace_caller has moved local addr here */ 274 - std r4, 40(r1) 275 - mflr r3 /* ftrace_caller has restored LR from stack */ 276 - subi r4, r4, MCOUNT_INSN_SIZE 277 - 278 - bl prepare_ftrace_return 279 - nop 280 - 281 - /* 282 - * prepare_ftrace_return gives us the address we divert to. 283 - * Change the LR to this. 284 - */ 285 - mtlr r3 286 - 287 - ld r0, 40(r1) 288 - mtctr r0 289 - ld r10, 104(r1) 290 - ld r9, 96(r1) 291 - ld r8, 88(r1) 292 - ld r7, 80(r1) 293 - ld r6, 72(r1) 294 - ld r5, 64(r1) 295 - ld r4, 56(r1) 296 - ld r3, 48(r1) 297 - 298 - /* Restore callee's TOC */ 299 - ld r2, 24(r1) 300 - 301 - addi r1, r1, 112 302 - mflr r0 303 - std r0, LRSAVE(r1) 304 - bctr 305 - #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+103
arch/powerpc/kernel/vdso/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + 3 + # List of files in the vdso, has to be asm only for now 4 + 5 + ARCH_REL_TYPE_ABS := R_PPC_JUMP_SLOT|R_PPC_GLOB_DAT|R_PPC_ADDR32|R_PPC_ADDR24|R_PPC_ADDR16|R_PPC_ADDR16_LO|R_PPC_ADDR16_HI|R_PPC_ADDR16_HA|R_PPC_ADDR14|R_PPC_ADDR14_BRTAKEN|R_PPC_ADDR14_BRNTAKEN|R_PPC_REL24 6 + include $(srctree)/lib/vdso/Makefile 7 + 8 + obj-vdso32 = sigtramp32-32.o gettimeofday-32.o datapage-32.o cacheflush-32.o note-32.o getcpu-32.o 9 + obj-vdso64 = sigtramp64-64.o gettimeofday-64.o datapage-64.o cacheflush-64.o note-64.o getcpu-64.o 10 + 11 + ifneq ($(c-gettimeofday-y),) 12 + CFLAGS_vgettimeofday-32.o += -include $(c-gettimeofday-y) 13 + CFLAGS_vgettimeofday-32.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) 14 + CFLAGS_vgettimeofday-32.o += $(call cc-option, -fno-stack-protector) 15 + CFLAGS_vgettimeofday-32.o += -DDISABLE_BRANCH_PROFILING 16 + CFLAGS_vgettimeofday-32.o += -ffreestanding -fasynchronous-unwind-tables 17 + CFLAGS_REMOVE_vgettimeofday-32.o = $(CC_FLAGS_FTRACE) 18 + CFLAGS_REMOVE_vgettimeofday-32.o += -mcmodel=medium -mabi=elfv1 -mabi=elfv2 -mcall-aixdesc 19 + CFLAGS_vgettimeofday-64.o += -include $(c-gettimeofday-y) 20 + CFLAGS_vgettimeofday-64.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) 21 + CFLAGS_vgettimeofday-64.o += $(call cc-option, -fno-stack-protector) 22 + CFLAGS_vgettimeofday-64.o += -DDISABLE_BRANCH_PROFILING 23 + CFLAGS_vgettimeofday-64.o += -ffreestanding -fasynchronous-unwind-tables 24 + CFLAGS_REMOVE_vgettimeofday-64.o = $(CC_FLAGS_FTRACE) 25 + # Go prior to 1.16.x assumes r30 is not clobbered by any VDSO code. That used to be true 26 + # by accident when the VDSO was hand-written asm code, but may not be now that the VDSO is 27 + # compiler generated. To avoid breaking Go tell GCC not to use r30. Impact on code 28 + # generation is minimal, it will just use r29 instead. 29 + CFLAGS_vgettimeofday-64.o += $(call cc-option, -ffixed-r30) 30 + endif 31 + 32 + # Build rules 33 + 34 + ifdef CROSS32_COMPILE 35 + VDSOCC := $(CROSS32_COMPILE)gcc 36 + else 37 + VDSOCC := $(CC) 38 + endif 39 + 40 + targets := $(obj-vdso32) vdso32.so.dbg vgettimeofday-32.o 41 + obj-vdso32 := $(addprefix $(obj)/, $(obj-vdso32)) 42 + targets += $(obj-vdso64) vdso64.so.dbg vgettimeofday-64.o 43 + obj-vdso64 := $(addprefix $(obj)/, $(obj-vdso64)) 44 + 45 + GCOV_PROFILE := n 46 + KCOV_INSTRUMENT := n 47 + UBSAN_SANITIZE := n 48 + KASAN_SANITIZE := n 49 + 50 + ccflags-y := -shared -fno-common -fno-builtin -nostdlib -Wl,--hash-style=both 51 + 52 + CC32FLAGS := -Wl,-soname=linux-vdso32.so.1 -m32 53 + AS32FLAGS := -D__VDSO32__ -s 54 + 55 + CC64FLAGS := -Wl,-soname=linux-vdso64.so.1 56 + AS64FLAGS := -D__VDSO64__ -s 57 + 58 + targets += vdso32.lds 59 + CPPFLAGS_vdso32.lds += -P -C -Upowerpc 60 + targets += vdso64.lds 61 + CPPFLAGS_vdso64.lds += -P -C -U$(ARCH) 62 + 63 + # link rule for the .so file, .lds has to be first 64 + $(obj)/vdso32.so.dbg: $(src)/vdso32.lds $(obj-vdso32) $(obj)/vgettimeofday-32.o FORCE 65 + $(call if_changed,vdso32ld_and_check) 66 + $(obj)/vdso64.so.dbg: $(src)/vdso64.lds $(obj-vdso64) $(obj)/vgettimeofday-64.o FORCE 67 + $(call if_changed,vdso64ld_and_check) 68 + 69 + # assembly rules for the .S files 70 + $(obj-vdso32): %-32.o: %.S FORCE 71 + $(call if_changed_dep,vdso32as) 72 + $(obj)/vgettimeofday-32.o: %-32.o: %.c FORCE 73 + $(call if_changed_dep,vdso32cc) 74 + $(obj-vdso64): %-64.o: %.S FORCE 75 + $(call if_changed_dep,vdso64as) 76 + $(obj)/vgettimeofday-64.o: %-64.o: %.c FORCE 77 + $(call if_changed_dep,cc_o_c) 78 + 79 + # Generate VDSO offsets using helper script 80 + gen-vdso32sym := $(srctree)/$(src)/gen_vdso32_offsets.sh 81 + quiet_cmd_vdso32sym = VDSO32SYM $@ 82 + cmd_vdso32sym = $(NM) $< | $(gen-vdso32sym) | LC_ALL=C sort > $@ 83 + gen-vdso64sym := $(srctree)/$(src)/gen_vdso64_offsets.sh 84 + quiet_cmd_vdso64sym = VDSO64SYM $@ 85 + cmd_vdso64sym = $(NM) $< | $(gen-vdso64sym) | LC_ALL=C sort > $@ 86 + 87 + include/generated/vdso32-offsets.h: $(obj)/vdso32.so.dbg FORCE 88 + $(call if_changed,vdso32sym) 89 + include/generated/vdso64-offsets.h: $(obj)/vdso64.so.dbg FORCE 90 + $(call if_changed,vdso64sym) 91 + 92 + # actual build commands 93 + quiet_cmd_vdso32ld_and_check = VDSO32L $@ 94 + cmd_vdso32ld_and_check = $(VDSOCC) $(c_flags) $(CC32FLAGS) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^) ; $(cmd_vdso_check) 95 + quiet_cmd_vdso32as = VDSO32A $@ 96 + cmd_vdso32as = $(VDSOCC) $(a_flags) $(CC32FLAGS) $(AS32FLAGS) -c -o $@ $< 97 + quiet_cmd_vdso32cc = VDSO32C $@ 98 + cmd_vdso32cc = $(VDSOCC) $(c_flags) $(CC32FLAGS) -c -o $@ $< 99 + 100 + quiet_cmd_vdso64ld_and_check = VDSO64L $@ 101 + cmd_vdso64ld_and_check = $(VDSOCC) $(c_flags) $(CC64FLAGS) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^) ; $(cmd_vdso_check) 102 + quiet_cmd_vdso64as = VDSO64A $@ 103 + cmd_vdso64as = $(VDSOCC) $(a_flags) $(CC64FLAGS) $(AS64FLAGS) -c -o $@ $<
+1 -2
arch/powerpc/kernel/vdso32/.gitignore tools/testing/selftests/powerpc/papr_attributes/.gitignore
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 - vdso32.lds 3 - vdso32.so.dbg 2 + attr_test
-73
arch/powerpc/kernel/vdso32/Makefile
··· 1 - # SPDX-License-Identifier: GPL-2.0 2 - 3 - # List of files in the vdso, has to be asm only for now 4 - 5 - ARCH_REL_TYPE_ABS := R_PPC_JUMP_SLOT|R_PPC_GLOB_DAT|R_PPC_ADDR32|R_PPC_ADDR24|R_PPC_ADDR16|R_PPC_ADDR16_LO|R_PPC_ADDR16_HI|R_PPC_ADDR16_HA|R_PPC_ADDR14|R_PPC_ADDR14_BRTAKEN|R_PPC_ADDR14_BRNTAKEN|R_PPC_REL24 6 - include $(srctree)/lib/vdso/Makefile 7 - 8 - obj-vdso32 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o getcpu.o 9 - 10 - ifneq ($(c-gettimeofday-y),) 11 - CFLAGS_vgettimeofday.o += -include $(c-gettimeofday-y) 12 - CFLAGS_vgettimeofday.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) 13 - CFLAGS_vgettimeofday.o += $(call cc-option, -fno-stack-protector) 14 - CFLAGS_vgettimeofday.o += -DDISABLE_BRANCH_PROFILING 15 - CFLAGS_vgettimeofday.o += -ffreestanding -fasynchronous-unwind-tables 16 - CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) 17 - endif 18 - 19 - # Build rules 20 - 21 - ifdef CROSS32_COMPILE 22 - VDSOCC := $(CROSS32_COMPILE)gcc 23 - else 24 - VDSOCC := $(CC) 25 - endif 26 - 27 - CC32FLAGS := 28 - ifdef CONFIG_PPC64 29 - CC32FLAGS += -m32 30 - KBUILD_CFLAGS := $(filter-out -mcmodel=medium -mabi=elfv1 -mabi=elfv2 -mcall-aixdesc,$(KBUILD_CFLAGS)) 31 - endif 32 - 33 - targets := $(obj-vdso32) vdso32.so.dbg vgettimeofday.o 34 - obj-vdso32 := $(addprefix $(obj)/, $(obj-vdso32)) 35 - 36 - GCOV_PROFILE := n 37 - KCOV_INSTRUMENT := n 38 - UBSAN_SANITIZE := n 39 - KASAN_SANITIZE := n 40 - 41 - ccflags-y := -shared -fno-common -fno-builtin -nostdlib \ 42 - -Wl,-soname=linux-vdso32.so.1 -Wl,--hash-style=both 43 - asflags-y := -D__VDSO32__ -s 44 - 45 - obj-y += vdso32_wrapper.o 46 - targets += vdso32.lds 47 - CPPFLAGS_vdso32.lds += -P -C -Upowerpc 48 - 49 - # link rule for the .so file, .lds has to be first 50 - $(obj)/vdso32.so.dbg: $(src)/vdso32.lds $(obj-vdso32) $(obj)/vgettimeofday.o FORCE 51 - $(call if_changed,vdso32ld_and_check) 52 - 53 - # assembly rules for the .S files 54 - $(obj-vdso32): %.o: %.S FORCE 55 - $(call if_changed_dep,vdso32as) 56 - $(obj)/vgettimeofday.o: %.o: %.c FORCE 57 - $(call if_changed_dep,vdso32cc) 58 - 59 - # Generate VDSO offsets using helper script 60 - gen-vdsosym := $(srctree)/$(src)/gen_vdso_offsets.sh 61 - quiet_cmd_vdsosym = VDSOSYM $@ 62 - cmd_vdsosym = $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ 63 - 64 - include/generated/vdso32-offsets.h: $(obj)/vdso32.so.dbg FORCE 65 - $(call if_changed,vdsosym) 66 - 67 - # actual build commands 68 - quiet_cmd_vdso32ld_and_check = VDSO32L $@ 69 - cmd_vdso32ld_and_check = $(VDSOCC) $(c_flags) $(CC32FLAGS) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^) ; $(cmd_vdso_check) 70 - quiet_cmd_vdso32as = VDSO32A $@ 71 - cmd_vdso32as = $(VDSOCC) $(a_flags) $(CC32FLAGS) -c -o $@ $< 72 - quiet_cmd_vdso32cc = VDSO32C $@ 73 - cmd_vdso32cc = $(VDSOCC) $(c_flags) $(CC32FLAGS) -c -o $@ $<
-98
arch/powerpc/kernel/vdso32/cacheflush.S
··· 1 - /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 - /* 3 - * vDSO provided cache flush routines 4 - * 5 - * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org), 6 - * IBM Corp. 7 - */ 8 - #include <asm/processor.h> 9 - #include <asm/ppc_asm.h> 10 - #include <asm/vdso.h> 11 - #include <asm/vdso_datapage.h> 12 - #include <asm/asm-offsets.h> 13 - #include <asm/cache.h> 14 - 15 - .text 16 - 17 - /* 18 - * Default "generic" version of __kernel_sync_dicache. 19 - * 20 - * void __kernel_sync_dicache(unsigned long start, unsigned long end) 21 - * 22 - * Flushes the data cache & invalidate the instruction cache for the 23 - * provided range [start, end[ 24 - */ 25 - V_FUNCTION_BEGIN(__kernel_sync_dicache) 26 - .cfi_startproc 27 - BEGIN_FTR_SECTION 28 - b 3f 29 - END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) 30 - #ifdef CONFIG_PPC64 31 - mflr r12 32 - .cfi_register lr,r12 33 - get_datapage r10 34 - mtlr r12 35 - .cfi_restore lr 36 - #endif 37 - 38 - #ifdef CONFIG_PPC64 39 - lwz r7,CFG_DCACHE_BLOCKSZ(r10) 40 - addi r5,r7,-1 41 - #else 42 - li r5, L1_CACHE_BYTES - 1 43 - #endif 44 - andc r6,r3,r5 /* round low to line bdy */ 45 - subf r8,r6,r4 /* compute length */ 46 - add r8,r8,r5 /* ensure we get enough */ 47 - #ifdef CONFIG_PPC64 48 - lwz r9,CFG_DCACHE_LOGBLOCKSZ(r10) 49 - srw. r8,r8,r9 /* compute line count */ 50 - #else 51 - srwi. r8, r8, L1_CACHE_SHIFT 52 - mr r7, r6 53 - #endif 54 - crclr cr0*4+so 55 - beqlr /* nothing to do? */ 56 - mtctr r8 57 - 1: dcbst 0,r6 58 - #ifdef CONFIG_PPC64 59 - add r6,r6,r7 60 - #else 61 - addi r6, r6, L1_CACHE_BYTES 62 - #endif 63 - bdnz 1b 64 - sync 65 - 66 - /* Now invalidate the instruction cache */ 67 - 68 - #ifdef CONFIG_PPC64 69 - lwz r7,CFG_ICACHE_BLOCKSZ(r10) 70 - addi r5,r7,-1 71 - andc r6,r3,r5 /* round low to line bdy */ 72 - subf r8,r6,r4 /* compute length */ 73 - add r8,r8,r5 74 - lwz r9,CFG_ICACHE_LOGBLOCKSZ(r10) 75 - srw. r8,r8,r9 /* compute line count */ 76 - crclr cr0*4+so 77 - beqlr /* nothing to do? */ 78 - #endif 79 - mtctr r8 80 - #ifdef CONFIG_PPC64 81 - 2: icbi 0,r6 82 - add r6,r6,r7 83 - #else 84 - 2: icbi 0, r7 85 - addi r7, r7, L1_CACHE_BYTES 86 - #endif 87 - bdnz 2b 88 - isync 89 - li r3,0 90 - blr 91 - 3: 92 - crclr cr0*4+so 93 - sync 94 - isync 95 - li r3,0 96 - blr 97 - .cfi_endproc 98 - V_FUNCTION_END(__kernel_sync_dicache)
-58
arch/powerpc/kernel/vdso32/datapage.S
··· 1 - /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 - /* 3 - * Access to the shared data page by the vDSO & syscall map 4 - * 5 - * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org), IBM Corp. 6 - */ 7 - 8 - #include <asm/processor.h> 9 - #include <asm/ppc_asm.h> 10 - #include <asm/asm-offsets.h> 11 - #include <asm/unistd.h> 12 - #include <asm/vdso.h> 13 - #include <asm/vdso_datapage.h> 14 - 15 - .text 16 - 17 - /* 18 - * void *__kernel_get_syscall_map(unsigned int *syscall_count) ; 19 - * 20 - * returns a pointer to the syscall map. the map is agnostic to the 21 - * size of "long", unlike kernel bitops, it stores bits from top to 22 - * bottom so that memory actually contains a linear bitmap 23 - * check for syscall N by testing bit (0x80000000 >> (N & 0x1f)) of 24 - * 32 bits int at N >> 5. 25 - */ 26 - V_FUNCTION_BEGIN(__kernel_get_syscall_map) 27 - .cfi_startproc 28 - mflr r12 29 - .cfi_register lr,r12 30 - mr. r4,r3 31 - get_datapage r3 32 - mtlr r12 33 - addi r3,r3,CFG_SYSCALL_MAP32 34 - beqlr 35 - li r0,NR_syscalls 36 - stw r0,0(r4) 37 - crclr cr0*4+so 38 - blr 39 - .cfi_endproc 40 - V_FUNCTION_END(__kernel_get_syscall_map) 41 - 42 - /* 43 - * void unsigned long long __kernel_get_tbfreq(void); 44 - * 45 - * returns the timebase frequency in HZ 46 - */ 47 - V_FUNCTION_BEGIN(__kernel_get_tbfreq) 48 - .cfi_startproc 49 - mflr r12 50 - .cfi_register lr,r12 51 - get_datapage r3 52 - lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3) 53 - lwz r3,CFG_TB_TICKS_PER_SEC(r3) 54 - mtlr r12 55 - crclr cr0*4+so 56 - blr 57 - .cfi_endproc 58 - V_FUNCTION_END(__kernel_get_tbfreq)
arch/powerpc/kernel/vdso32/gen_vdso_offsets.sh arch/powerpc/kernel/vdso/gen_vdso32_offsets.sh
-50
arch/powerpc/kernel/vdso32/getcpu.S
··· 1 - /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 - /* 3 - * 4 - * Copyright (C) IBM Corporation, 2012 5 - * 6 - * Author: Anton Blanchard <anton@au.ibm.com> 7 - */ 8 - #include <asm/ppc_asm.h> 9 - #include <asm/vdso.h> 10 - 11 - .text 12 - /* 13 - * Exact prototype of getcpu 14 - * 15 - * int __kernel_getcpu(unsigned *cpu, unsigned *node); 16 - * 17 - */ 18 - #if defined(CONFIG_PPC64) 19 - V_FUNCTION_BEGIN(__kernel_getcpu) 20 - .cfi_startproc 21 - mfspr r5,SPRN_SPRG_VDSO_READ 22 - cmpwi cr0,r3,0 23 - cmpwi cr1,r4,0 24 - clrlwi r6,r5,16 25 - rlwinm r7,r5,16,31-15,31-0 26 - beq cr0,1f 27 - stw r6,0(r3) 28 - 1: crclr cr0*4+so 29 - li r3,0 /* always success */ 30 - beqlr cr1 31 - stw r7,0(r4) 32 - blr 33 - .cfi_endproc 34 - V_FUNCTION_END(__kernel_getcpu) 35 - #elif !defined(CONFIG_SMP) 36 - V_FUNCTION_BEGIN(__kernel_getcpu) 37 - .cfi_startproc 38 - cmpwi cr0, r3, 0 39 - cmpwi cr1, r4, 0 40 - li r5, 0 41 - beq cr0, 1f 42 - stw r5, 0(r3) 43 - 1: li r3, 0 /* always success */ 44 - crclr cr0*4+so 45 - beqlr cr1 46 - stw r5, 0(r4) 47 - blr 48 - .cfi_endproc 49 - V_FUNCTION_END(__kernel_getcpu) 50 - #endif
+50 -4
arch/powerpc/kernel/vdso32/gettimeofday.S arch/powerpc/kernel/vdso/gettimeofday.S
··· 1 1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 2 /* 3 - * Userland implementation of gettimeofday() for 32 bits processes in a 4 - * ppc64 kernel for use in the vDSO 3 + * Userland implementation of gettimeofday() for processes 4 + * for use in the vDSO 5 5 * 6 6 * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org, 7 7 * IBM Corp. ··· 12 12 #include <asm/vdso_datapage.h> 13 13 #include <asm/asm-offsets.h> 14 14 #include <asm/unistd.h> 15 - #include <asm/vdso/gettimeofday.h> 15 + 16 + /* 17 + * The macro sets two stack frames, one for the caller and one for the callee 18 + * because there are no requirement for the caller to set a stack frame when 19 + * calling VDSO so it may have omitted to set one, especially on PPC64 20 + */ 21 + 22 + .macro cvdso_call funct call_time=0 23 + .cfi_startproc 24 + PPC_STLU r1, -PPC_MIN_STKFRM(r1) 25 + mflr r0 26 + .cfi_register lr, r0 27 + PPC_STLU r1, -PPC_MIN_STKFRM(r1) 28 + PPC_STL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1) 29 + #ifdef __powerpc64__ 30 + PPC_STL r2, PPC_MIN_STKFRM + STK_GOT(r1) 31 + #endif 32 + get_datapage r5 33 + .ifeq \call_time 34 + addi r5, r5, VDSO_DATA_OFFSET 35 + .else 36 + addi r4, r5, VDSO_DATA_OFFSET 37 + .endif 38 + bl DOTSYM(\funct) 39 + PPC_LL r0, PPC_MIN_STKFRM + PPC_LR_STKOFF(r1) 40 + #ifdef __powerpc64__ 41 + PPC_LL r2, PPC_MIN_STKFRM + STK_GOT(r1) 42 + #endif 43 + .ifeq \call_time 44 + cmpwi r3, 0 45 + .endif 46 + mtlr r0 47 + .cfi_restore lr 48 + addi r1, r1, 2 * PPC_MIN_STKFRM 49 + crclr so 50 + .ifeq \call_time 51 + beqlr+ 52 + crset so 53 + neg r3, r3 54 + .endif 55 + blr 56 + .cfi_endproc 57 + .endm 16 58 17 59 .text 18 60 /* ··· 83 41 * int __kernel_clock_gettime64(clockid_t clock_id, struct __timespec64 *ts); 84 42 * 85 43 */ 44 + #ifndef __powerpc64__ 86 45 V_FUNCTION_BEGIN(__kernel_clock_gettime64) 87 46 cvdso_call __c_kernel_clock_gettime64 88 47 V_FUNCTION_END(__kernel_clock_gettime64) 48 + #endif 89 49 90 50 /* 91 51 * Exact prototype of clock_getres() ··· 107 63 * 108 64 */ 109 65 V_FUNCTION_BEGIN(__kernel_time) 110 - cvdso_call_time __c_kernel_time 66 + cvdso_call __c_kernel_time call_time=1 111 67 V_FUNCTION_END(__kernel_time) 112 68 113 69 /* Routines for restoring integer registers, called by the compiler. */ 114 70 /* Called with r11 pointing to the stack header word of the caller of the */ 115 71 /* function, just beyond the end of the integer restore area. */ 72 + #ifndef __powerpc64__ 116 73 _GLOBAL(_restgpr_31_x) 117 74 _GLOBAL(_rest32gpr_31_x) 118 75 lwz r0,4(r11) ··· 121 76 mtlr r0 122 77 mr r1,r11 123 78 blr 79 + #endif
arch/powerpc/kernel/vdso32/note.S arch/powerpc/kernel/vdso/note.S
arch/powerpc/kernel/vdso32/sigtramp.S arch/powerpc/kernel/vdso/sigtramp32.S
arch/powerpc/kernel/vdso32/vdso32.lds.S arch/powerpc/kernel/vdso/vdso32.lds.S
+21 -6
arch/powerpc/kernel/vdso32/vgettimeofday.c arch/powerpc/kernel/vdso/vgettimeofday.c
··· 2 2 /* 3 3 * Powerpc userspace implementations of gettimeofday() and similar. 4 4 */ 5 + #include <linux/time.h> 5 6 #include <linux/types.h> 6 7 8 + #ifdef __powerpc64__ 9 + int __c_kernel_clock_gettime(clockid_t clock, struct __kernel_timespec *ts, 10 + const struct vdso_data *vd) 11 + { 12 + return __cvdso_clock_gettime_data(vd, clock, ts); 13 + } 14 + 15 + int __c_kernel_clock_getres(clockid_t clock_id, struct __kernel_timespec *res, 16 + const struct vdso_data *vd) 17 + { 18 + return __cvdso_clock_getres_data(vd, clock_id, res); 19 + } 20 + #else 7 21 int __c_kernel_clock_gettime(clockid_t clock, struct old_timespec32 *ts, 8 22 const struct vdso_data *vd) 9 23 { ··· 30 16 return __cvdso_clock_gettime_data(vd, clock, ts); 31 17 } 32 18 33 - int __c_kernel_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz, 34 - const struct vdso_data *vd) 35 - { 36 - return __cvdso_gettimeofday_data(vd, tv, tz); 37 - } 38 - 39 19 int __c_kernel_clock_getres(clockid_t clock_id, struct old_timespec32 *res, 40 20 const struct vdso_data *vd) 41 21 { 42 22 return __cvdso_clock_getres_time32_data(vd, clock_id, res); 23 + } 24 + #endif 25 + 26 + int __c_kernel_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz, 27 + const struct vdso_data *vd) 28 + { 29 + return __cvdso_gettimeofday_data(vd, tv, tz); 43 30 } 44 31 45 32 __kernel_old_time_t __c_kernel_time(__kernel_old_time_t *time, const struct vdso_data *vd)
+1 -1
arch/powerpc/kernel/vdso32_wrapper.S
··· 7 7 .globl vdso32_start, vdso32_end 8 8 .balign PAGE_SIZE 9 9 vdso32_start: 10 - .incbin "arch/powerpc/kernel/vdso32/vdso32.so.dbg" 10 + .incbin "arch/powerpc/kernel/vdso/vdso32.so.dbg" 11 11 .balign PAGE_SIZE 12 12 vdso32_end: 13 13
+2
arch/powerpc/kernel/vdso64/.gitignore arch/powerpc/kernel/vdso/.gitignore
··· 1 1 # SPDX-License-Identifier: GPL-2.0-only 2 + vdso32.lds 3 + vdso32.so.dbg 2 4 vdso64.lds 3 5 vdso64.so.dbg
-56
arch/powerpc/kernel/vdso64/Makefile
··· 1 - # SPDX-License-Identifier: GPL-2.0 2 - # List of files in the vdso, has to be asm only for now 3 - 4 - ARCH_REL_TYPE_ABS := R_PPC_JUMP_SLOT|R_PPC_GLOB_DAT|R_PPC_ADDR32|R_PPC_ADDR24|R_PPC_ADDR16|R_PPC_ADDR16_LO|R_PPC_ADDR16_HI|R_PPC_ADDR16_HA|R_PPC_ADDR14|R_PPC_ADDR14_BRTAKEN|R_PPC_ADDR14_BRNTAKEN|R_PPC_REL24 5 - include $(srctree)/lib/vdso/Makefile 6 - 7 - obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o getcpu.o 8 - 9 - ifneq ($(c-gettimeofday-y),) 10 - CFLAGS_vgettimeofday.o += -include $(c-gettimeofday-y) 11 - CFLAGS_vgettimeofday.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) 12 - CFLAGS_vgettimeofday.o += $(call cc-option, -fno-stack-protector) 13 - CFLAGS_vgettimeofday.o += -DDISABLE_BRANCH_PROFILING 14 - CFLAGS_vgettimeofday.o += -ffreestanding -fasynchronous-unwind-tables 15 - CFLAGS_REMOVE_vgettimeofday.o = $(CC_FLAGS_FTRACE) 16 - endif 17 - 18 - # Build rules 19 - 20 - targets := $(obj-vdso64) vdso64.so.dbg vgettimeofday.o 21 - obj-vdso64 := $(addprefix $(obj)/, $(obj-vdso64)) 22 - 23 - GCOV_PROFILE := n 24 - KCOV_INSTRUMENT := n 25 - UBSAN_SANITIZE := n 26 - KASAN_SANITIZE := n 27 - 28 - ccflags-y := -shared -fno-common -fno-builtin -nostdlib \ 29 - -Wl,-soname=linux-vdso64.so.1 -Wl,--hash-style=both 30 - 31 - # Go prior to 1.16.x assumes r30 is not clobbered by any VDSO code. That used to be true 32 - # by accident when the VDSO was hand-written asm code, but may not be now that the VDSO is 33 - # compiler generated. To avoid breaking Go tell GCC not to use r30. Impact on code 34 - # generation is minimal, it will just use r29 instead. 35 - ccflags-y += $(call cc-option, -ffixed-r30) 36 - 37 - asflags-y := -D__VDSO64__ -s 38 - 39 - targets += vdso64.lds 40 - CPPFLAGS_vdso64.lds += -P -C -U$(ARCH) 41 - 42 - # link rule for the .so file, .lds has to be first 43 - $(obj)/vdso64.so.dbg: $(src)/vdso64.lds $(obj-vdso64) $(obj)/vgettimeofday.o FORCE 44 - $(call if_changed,vdso64ld_and_check) 45 - 46 - # Generate VDSO offsets using helper script 47 - gen-vdsosym := $(srctree)/$(src)/gen_vdso_offsets.sh 48 - quiet_cmd_vdsosym = VDSOSYM $@ 49 - cmd_vdsosym = $(NM) $< | $(gen-vdsosym) | LC_ALL=C sort > $@ 50 - 51 - include/generated/vdso64-offsets.h: $(obj)/vdso64.so.dbg FORCE 52 - $(call if_changed,vdsosym) 53 - 54 - # actual build commands 55 - quiet_cmd_vdso64ld_and_check = VDSO64L $@ 56 - cmd_vdso64ld_and_check = $(CC) $(c_flags) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^); $(cmd_vdso_check)
+26 -3
arch/powerpc/kernel/vdso64/cacheflush.S arch/powerpc/kernel/vdso/cacheflush.S
··· 10 10 #include <asm/vdso.h> 11 11 #include <asm/vdso_datapage.h> 12 12 #include <asm/asm-offsets.h> 13 + #include <asm/cache.h> 13 14 14 15 .text 15 16 ··· 27 26 BEGIN_FTR_SECTION 28 27 b 3f 29 28 END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) 29 + #ifdef CONFIG_PPC64 30 30 mflr r12 31 31 .cfi_register lr,r12 32 32 get_datapage r10 33 33 mtlr r12 34 - .cfi_restore lr 34 + .cfi_restore lr 35 + #endif 35 36 37 + #ifdef CONFIG_PPC64 36 38 lwz r7,CFG_DCACHE_BLOCKSZ(r10) 37 39 addi r5,r7,-1 40 + #else 41 + li r5, L1_CACHE_BYTES - 1 42 + #endif 38 43 andc r6,r3,r5 /* round low to line bdy */ 39 44 subf r8,r6,r4 /* compute length */ 40 45 add r8,r8,r5 /* ensure we get enough */ 46 + #ifdef CONFIG_PPC64 41 47 lwz r9,CFG_DCACHE_LOGBLOCKSZ(r10) 42 - srd. r8,r8,r9 /* compute line count */ 48 + PPC_SRL. r8,r8,r9 /* compute line count */ 49 + #else 50 + srwi. r8, r8, L1_CACHE_SHIFT 51 + mr r7, r6 52 + #endif 43 53 crclr cr0*4+so 44 54 beqlr /* nothing to do? */ 45 55 mtctr r8 46 56 1: dcbst 0,r6 57 + #ifdef CONFIG_PPC64 47 58 add r6,r6,r7 59 + #else 60 + addi r6, r6, L1_CACHE_BYTES 61 + #endif 48 62 bdnz 1b 49 63 sync 50 64 51 65 /* Now invalidate the instruction cache */ 52 66 67 + #ifdef CONFIG_PPC64 53 68 lwz r7,CFG_ICACHE_BLOCKSZ(r10) 54 69 addi r5,r7,-1 55 70 andc r6,r3,r5 /* round low to line bdy */ 56 71 subf r8,r6,r4 /* compute length */ 57 72 add r8,r8,r5 58 73 lwz r9,CFG_ICACHE_LOGBLOCKSZ(r10) 59 - srd. r8,r8,r9 /* compute line count */ 74 + PPC_SRL. r8,r8,r9 /* compute line count */ 60 75 crclr cr0*4+so 61 76 beqlr /* nothing to do? */ 77 + #endif 62 78 mtctr r8 79 + #ifdef CONFIG_PPC64 63 80 2: icbi 0,r6 64 81 add r6,r6,r7 82 + #else 83 + 2: icbi 0, r7 84 + addi r7, r7, L1_CACHE_BYTES 85 + #endif 65 86 bdnz 2b 66 87 isync 67 88 li r3,0
+10 -5
arch/powerpc/kernel/vdso64/datapage.S arch/powerpc/kernel/vdso/datapage.S
··· 27 27 .cfi_startproc 28 28 mflr r12 29 29 .cfi_register lr,r12 30 - mr r4,r3 30 + mr. r4,r3 31 31 get_datapage r3 32 32 mtlr r12 33 + #ifdef __powerpc64__ 33 34 addi r3,r3,CFG_SYSCALL_MAP64 34 - cmpldi cr0,r4,0 35 + #else 36 + addi r3,r3,CFG_SYSCALL_MAP32 37 + #endif 35 38 crclr cr0*4+so 36 39 beqlr 37 40 li r0,NR_syscalls ··· 43 40 .cfi_endproc 44 41 V_FUNCTION_END(__kernel_get_syscall_map) 45 42 46 - 47 43 /* 48 - * void unsigned long __kernel_get_tbfreq(void); 44 + * void unsigned long long __kernel_get_tbfreq(void); 49 45 * 50 46 * returns the timebase frequency in HZ 51 47 */ ··· 53 51 mflr r12 54 52 .cfi_register lr,r12 55 53 get_datapage r3 56 - ld r3,CFG_TB_TICKS_PER_SEC(r3) 54 + #ifndef __powerpc64__ 55 + lwz r4,(CFG_TB_TICKS_PER_SEC + 4)(r3) 56 + #endif 57 + PPC_LL r3,CFG_TB_TICKS_PER_SEC(r3) 57 58 mtlr r12 58 59 crclr cr0*4+so 59 60 blr
arch/powerpc/kernel/vdso64/gen_vdso_offsets.sh arch/powerpc/kernel/vdso/gen_vdso64_offsets.sh
+22 -5
arch/powerpc/kernel/vdso64/getcpu.S arch/powerpc/kernel/vdso/getcpu.S
··· 15 15 * int __kernel_getcpu(unsigned *cpu, unsigned *node); 16 16 * 17 17 */ 18 + #if defined(CONFIG_PPC64) 18 19 V_FUNCTION_BEGIN(__kernel_getcpu) 19 20 .cfi_startproc 20 21 mfspr r5,SPRN_SPRG_VDSO_READ 21 - cmpdi cr0,r3,0 22 - cmpdi cr1,r4,0 22 + PPC_LCMPI cr0,r3,0 23 + PPC_LCMPI cr1,r4,0 23 24 clrlwi r6,r5,16 24 25 rlwinm r7,r5,16,31-15,31-0 25 26 beq cr0,1f 26 27 stw r6,0(r3) 27 - 1: beq cr1,2f 28 - stw r7,0(r4) 29 - 2: crclr cr0*4+so 28 + 1: crclr cr0*4+so 30 29 li r3,0 /* always success */ 30 + beqlr cr1 31 + stw r7,0(r4) 31 32 blr 32 33 .cfi_endproc 33 34 V_FUNCTION_END(__kernel_getcpu) 35 + #elif !defined(CONFIG_SMP) 36 + V_FUNCTION_BEGIN(__kernel_getcpu) 37 + .cfi_startproc 38 + cmpwi cr0, r3, 0 39 + cmpwi cr1, r4, 0 40 + li r5, 0 41 + beq cr0, 1f 42 + stw r5, 0(r3) 43 + 1: li r3, 0 /* always success */ 44 + crclr cr0*4+so 45 + beqlr cr1 46 + stw r5, 0(r4) 47 + blr 48 + .cfi_endproc 49 + V_FUNCTION_END(__kernel_getcpu) 50 + #endif
-58
arch/powerpc/kernel/vdso64/gettimeofday.S
··· 1 - /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 - /* 3 - * Userland implementation of gettimeofday() for 64 bits processes in a 4 - * ppc64 kernel for use in the vDSO 5 - * 6 - * Copyright (C) 2004 Benjamin Herrenschmuidt (benh@kernel.crashing.org), 7 - * IBM Corp. 8 - */ 9 - #include <asm/processor.h> 10 - #include <asm/ppc_asm.h> 11 - #include <asm/vdso.h> 12 - #include <asm/vdso_datapage.h> 13 - #include <asm/asm-offsets.h> 14 - #include <asm/unistd.h> 15 - #include <asm/vdso/gettimeofday.h> 16 - 17 - .text 18 - /* 19 - * Exact prototype of gettimeofday 20 - * 21 - * int __kernel_gettimeofday(struct timeval *tv, struct timezone *tz); 22 - * 23 - */ 24 - V_FUNCTION_BEGIN(__kernel_gettimeofday) 25 - cvdso_call __c_kernel_gettimeofday 26 - V_FUNCTION_END(__kernel_gettimeofday) 27 - 28 - 29 - /* 30 - * Exact prototype of clock_gettime() 31 - * 32 - * int __kernel_clock_gettime(clockid_t clock_id, struct timespec *tp); 33 - * 34 - */ 35 - V_FUNCTION_BEGIN(__kernel_clock_gettime) 36 - cvdso_call __c_kernel_clock_gettime 37 - V_FUNCTION_END(__kernel_clock_gettime) 38 - 39 - 40 - /* 41 - * Exact prototype of clock_getres() 42 - * 43 - * int __kernel_clock_getres(clockid_t clock_id, struct timespec *res); 44 - * 45 - */ 46 - V_FUNCTION_BEGIN(__kernel_clock_getres) 47 - cvdso_call __c_kernel_clock_getres 48 - V_FUNCTION_END(__kernel_clock_getres) 49 - 50 - /* 51 - * Exact prototype of time() 52 - * 53 - * time_t time(time *t); 54 - * 55 - */ 56 - V_FUNCTION_BEGIN(__kernel_time) 57 - cvdso_call_time __c_kernel_time 58 - V_FUNCTION_END(__kernel_time)
-1
arch/powerpc/kernel/vdso64/note.S
··· 1 - #include "../vdso32/note.S"
arch/powerpc/kernel/vdso64/sigtramp.S arch/powerpc/kernel/vdso/sigtramp64.S
arch/powerpc/kernel/vdso64/vdso64.lds.S arch/powerpc/kernel/vdso/vdso64.lds.S
-29
arch/powerpc/kernel/vdso64/vgettimeofday.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * Powerpc userspace implementations of gettimeofday() and similar. 4 - */ 5 - #include <linux/time.h> 6 - #include <linux/types.h> 7 - 8 - int __c_kernel_clock_gettime(clockid_t clock, struct __kernel_timespec *ts, 9 - const struct vdso_data *vd) 10 - { 11 - return __cvdso_clock_gettime_data(vd, clock, ts); 12 - } 13 - 14 - int __c_kernel_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz, 15 - const struct vdso_data *vd) 16 - { 17 - return __cvdso_gettimeofday_data(vd, tv, tz); 18 - } 19 - 20 - int __c_kernel_clock_getres(clockid_t clock_id, struct __kernel_timespec *res, 21 - const struct vdso_data *vd) 22 - { 23 - return __cvdso_clock_getres_data(vd, clock_id, res); 24 - } 25 - 26 - __kernel_old_time_t __c_kernel_time(__kernel_old_time_t *time, const struct vdso_data *vd) 27 - { 28 - return __cvdso_time_data(vd, time); 29 - }
+1 -1
arch/powerpc/kernel/vdso64_wrapper.S
··· 7 7 .globl vdso64_start, vdso64_end 8 8 .balign PAGE_SIZE 9 9 vdso64_start: 10 - .incbin "arch/powerpc/kernel/vdso64/vdso64.so.dbg" 10 + .incbin "arch/powerpc/kernel/vdso/vdso64.so.dbg" 11 11 .balign PAGE_SIZE 12 12 vdso64_end: 13 13
-2
arch/powerpc/kernel/vmlinux.lds.S
··· 281 281 . = ALIGN(8); 282 282 .dynsym : AT(ADDR(.dynsym) - LOAD_OFFSET) 283 283 { 284 - #ifdef CONFIG_PPC32 285 284 __dynamic_symtab = .; 286 - #endif 287 285 *(.dynsym) 288 286 } 289 287 .dynstr : AT(ADDR(.dynstr) - LOAD_OFFSET) { *(.dynstr) }
+11 -4
arch/powerpc/kexec/core.c
··· 134 134 if (!crashk_res.start) { 135 135 #ifdef CONFIG_PPC64 136 136 /* 137 - * On 64bit we split the RMO in half but cap it at half of 138 - * a small SLB (128MB) since the crash kernel needs to place 139 - * itself and some stacks to be in the first segment. 137 + * On the LPAR platform place the crash kernel to mid of 138 + * RMA size (512MB or more) to ensure the crash kernel 139 + * gets enough space to place itself and some stack to be 140 + * in the first segment. At the same time normal kernel 141 + * also get enough space to allocate memory for essential 142 + * system resource in the first segment. Keep the crash 143 + * kernel starts at 128MB offset on other platforms. 140 144 */ 141 - crashk_res.start = min(0x8000000ULL, (ppc64_rma_size / 2)); 145 + if (firmware_has_feature(FW_FEATURE_LPAR)) 146 + crashk_res.start = ppc64_rma_size / 2; 147 + else 148 + crashk_res.start = min(0x8000000ULL, (ppc64_rma_size / 2)); 142 149 #else 143 150 crashk_res.start = KDUMP_KERNELBASE; 144 151 #endif
+1 -2
arch/powerpc/kexec/core_64.c
··· 28 28 #include <asm/prom.h> 29 29 #include <asm/smp.h> 30 30 #include <asm/hw_breakpoint.h> 31 - #include <asm/asm-prototypes.h> 32 31 #include <asm/svm.h> 33 32 #include <asm/ultravisor.h> 34 33 ··· 290 291 * For similar reasons to the stack above, the kexecing CPU needs to be on a 291 292 * static PACA; we switch to kexec_paca. 292 293 */ 293 - struct paca_struct kexec_paca; 294 + static struct paca_struct kexec_paca; 294 295 295 296 /* Our assembly helper, in misc_64.S */ 296 297 extern void kexec_sequence(void *newstack, unsigned long start,
+1 -1
arch/powerpc/kvm/book3s_64_mmu_host.c
··· 228 228 struct kvmppc_sid_map *map; 229 229 struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); 230 230 u16 sid_map_mask; 231 - static int backwards_map = 0; 231 + static int backwards_map; 232 232 233 233 if (kvmppc_get_msr(vcpu) & MSR_PR) 234 234 gvsid |= VSID_PR;
+1 -1
arch/powerpc/kvm/book3s_64_mmu_hv.c
··· 2112 2112 2113 2113 void kvmppc_mmu_debugfs_init(struct kvm *kvm) 2114 2114 { 2115 - debugfs_create_file("htab", 0400, kvm->arch.debugfs_dir, kvm, 2115 + debugfs_create_file("htab", 0400, kvm->debugfs_dentry, kvm, 2116 2116 &debugfs_htab_fops); 2117 2117 } 2118 2118
+1 -1
arch/powerpc/kvm/book3s_64_mmu_radix.c
··· 1454 1454 1455 1455 void kvmhv_radix_debugfs_init(struct kvm *kvm) 1456 1456 { 1457 - debugfs_create_file("radix", 0400, kvm->arch.debugfs_dir, kvm, 1457 + debugfs_create_file("radix", 0400, kvm->debugfs_dentry, kvm, 1458 1458 &debugfs_radix_fops); 1459 1459 } 1460 1460
+32 -27
arch/powerpc/kvm/book3s_hv.c
··· 2767 2767 }; 2768 2768 2769 2769 /* Create a debugfs directory for the vcpu */ 2770 - static void debugfs_vcpu_init(struct kvm_vcpu *vcpu, unsigned int id) 2770 + static int kvmppc_arch_create_vcpu_debugfs_hv(struct kvm_vcpu *vcpu, struct dentry *debugfs_dentry) 2771 2771 { 2772 - char buf[16]; 2773 - struct kvm *kvm = vcpu->kvm; 2774 - 2775 - snprintf(buf, sizeof(buf), "vcpu%u", id); 2776 - vcpu->arch.debugfs_dir = debugfs_create_dir(buf, kvm->arch.debugfs_dir); 2777 - debugfs_create_file("timings", 0444, vcpu->arch.debugfs_dir, vcpu, 2772 + debugfs_create_file("timings", 0444, debugfs_dentry, vcpu, 2778 2773 &debugfs_timings_ops); 2774 + return 0; 2779 2775 } 2780 2776 2781 2777 #else /* CONFIG_KVM_BOOK3S_HV_EXIT_TIMING */ 2782 - static void debugfs_vcpu_init(struct kvm_vcpu *vcpu, unsigned int id) 2778 + static int kvmppc_arch_create_vcpu_debugfs_hv(struct kvm_vcpu *vcpu, struct dentry *debugfs_dentry) 2783 2779 { 2780 + return 0; 2784 2781 } 2785 2782 #endif /* CONFIG_KVM_BOOK3S_HV_EXIT_TIMING */ 2786 2783 ··· 2899 2902 2900 2903 vcpu->arch.cpu_type = KVM_CPU_3S_64; 2901 2904 kvmppc_sanity_check(vcpu); 2902 - 2903 - debugfs_vcpu_init(vcpu, id); 2904 2905 2905 2906 return 0; 2906 2907 } ··· 5218 5223 static int kvmppc_core_init_vm_hv(struct kvm *kvm) 5219 5224 { 5220 5225 unsigned long lpcr, lpid; 5221 - char buf[32]; 5222 5226 int ret; 5223 5227 5224 5228 mutex_init(&kvm->arch.uvmem_lock); ··· 5350 5356 kvm->arch.smt_mode = 1; 5351 5357 kvm->arch.emul_smt_mode = 1; 5352 5358 5353 - /* 5354 - * Create a debugfs directory for the VM 5355 - */ 5356 - snprintf(buf, sizeof(buf), "vm%d", current->pid); 5357 - kvm->arch.debugfs_dir = debugfs_create_dir(buf, kvm_debugfs_dir); 5359 + return 0; 5360 + } 5361 + 5362 + static int kvmppc_arch_create_vm_debugfs_hv(struct kvm *kvm) 5363 + { 5358 5364 kvmppc_mmu_debugfs_init(kvm); 5359 5365 if (radix_enabled()) 5360 5366 kvmhv_radix_debugfs_init(kvm); 5361 - 5362 5367 return 0; 5363 5368 } 5364 5369 ··· 5372 5379 5373 5380 static void kvmppc_core_destroy_vm_hv(struct kvm *kvm) 5374 5381 { 5375 - debugfs_remove_recursive(kvm->arch.debugfs_dir); 5376 - 5377 5382 if (!cpu_has_feature(CPU_FTR_ARCH_300)) 5378 5383 kvm_hv_vm_deactivated(); 5379 5384 ··· 6033 6042 .svm_off = kvmhv_svm_off, 6034 6043 .enable_dawr1 = kvmhv_enable_dawr1, 6035 6044 .hash_v3_possible = kvmppc_hash_v3_possible, 6045 + .create_vcpu_debugfs = kvmppc_arch_create_vcpu_debugfs_hv, 6046 + .create_vm_debugfs = kvmppc_arch_create_vm_debugfs_hv, 6036 6047 }; 6037 6048 6038 6049 static int kvm_init_subcore_bitmap(void) ··· 6096 6103 if (!cpu_has_feature(CPU_FTR_ARCH_300)) { 6097 6104 r = kvm_init_subcore_bitmap(); 6098 6105 if (r) 6099 - return r; 6106 + goto err; 6100 6107 } 6101 6108 6102 6109 /* ··· 6112 6119 np = of_find_compatible_node(NULL, NULL, "ibm,opal-intc"); 6113 6120 if (!np) { 6114 6121 pr_err("KVM-HV: Cannot determine method for accessing XICS\n"); 6115 - return -ENODEV; 6122 + r = -ENODEV; 6123 + goto err; 6116 6124 } 6117 6125 /* presence of intc confirmed - node can be dropped again */ 6118 6126 of_node_put(np); 6119 6127 } 6120 6128 #endif 6121 - 6122 - kvm_ops_hv.owner = THIS_MODULE; 6123 - kvmppc_hv_ops = &kvm_ops_hv; 6124 6129 6125 6130 init_default_hcalls(); 6126 6131 ··· 6126 6135 6127 6136 r = kvmppc_mmu_hv_init(); 6128 6137 if (r) 6129 - return r; 6138 + goto err; 6130 6139 6131 - if (kvmppc_radix_possible()) 6140 + if (kvmppc_radix_possible()) { 6132 6141 r = kvmppc_radix_init(); 6142 + if (r) 6143 + goto err; 6144 + } 6133 6145 6134 6146 r = kvmppc_uvmem_init(); 6135 - if (r < 0) 6147 + if (r < 0) { 6136 6148 pr_err("KVM-HV: kvmppc_uvmem_init failed %d\n", r); 6149 + return r; 6150 + } 6151 + 6152 + kvm_ops_hv.owner = THIS_MODULE; 6153 + kvmppc_hv_ops = &kvm_ops_hv; 6154 + 6155 + return 0; 6156 + 6157 + err: 6158 + kvmhv_nested_exit(); 6159 + kvmppc_radix_exit(); 6137 6160 6138 6161 return r; 6139 6162 }
-1
arch/powerpc/kvm/book3s_hv_builtin.c
··· 15 15 #include <linux/cma.h> 16 16 #include <linux/bitops.h> 17 17 18 - #include <asm/asm-prototypes.h> 19 18 #include <asm/cputable.h> 20 19 #include <asm/interrupt.h> 21 20 #include <asm/kvm_ppc.h>
-1
arch/powerpc/kvm/book3s_hv_rm_xive.c
··· 16 16 #include <asm/pnv-pci.h> 17 17 #include <asm/opal.h> 18 18 #include <asm/smp.h> 19 - #include <asm/asm-prototypes.h> 20 19 #include <asm/xive.h> 21 20 #include <asm/xive-regs.h> 22 21
+3 -12
arch/powerpc/kvm/book3s_xics.c
··· 1016 1016 1017 1017 static void xics_debugfs_init(struct kvmppc_xics *xics) 1018 1018 { 1019 - char *name; 1020 - 1021 - name = kasprintf(GFP_KERNEL, "kvm-xics-%p", xics); 1022 - if (!name) { 1023 - pr_err("%s: no memory for name\n", __func__); 1024 - return; 1025 - } 1026 - 1027 - xics->dentry = debugfs_create_file(name, 0444, arch_debugfs_dir, 1019 + xics->dentry = debugfs_create_file("xics", 0444, xics->kvm->debugfs_dentry, 1028 1020 xics, &xics_debug_fops); 1029 1021 1030 - pr_debug("%s: created %s\n", __func__, name); 1031 - kfree(name); 1022 + pr_debug("%s: created\n", __func__); 1032 1023 } 1033 1024 1034 1025 static struct kvmppc_ics *kvmppc_xics_create_ics(struct kvm *kvm, ··· 1431 1440 1432 1441 static void kvmppc_xics_init(struct kvm_device *dev) 1433 1442 { 1434 - struct kvmppc_xics *xics = (struct kvmppc_xics *)dev->private; 1443 + struct kvmppc_xics *xics = dev->private; 1435 1444 1436 1445 xics_debugfs_init(xics); 1437 1446 }
+3 -12
arch/powerpc/kvm/book3s_xive.c
··· 2354 2354 2355 2355 static void xive_debugfs_init(struct kvmppc_xive *xive) 2356 2356 { 2357 - char *name; 2358 - 2359 - name = kasprintf(GFP_KERNEL, "kvm-xive-%p", xive); 2360 - if (!name) { 2361 - pr_err("%s: no memory for name\n", __func__); 2362 - return; 2363 - } 2364 - 2365 - xive->dentry = debugfs_create_file(name, S_IRUGO, arch_debugfs_dir, 2357 + xive->dentry = debugfs_create_file("xive", S_IRUGO, xive->kvm->debugfs_dentry, 2366 2358 xive, &xive_debug_fops); 2367 2359 2368 - pr_debug("%s: created %s\n", __func__, name); 2369 - kfree(name); 2360 + pr_debug("%s: created\n", __func__); 2370 2361 } 2371 2362 2372 2363 static void kvmppc_xive_init(struct kvm_device *dev) 2373 2364 { 2374 - struct kvmppc_xive *xive = (struct kvmppc_xive *)dev->private; 2365 + struct kvmppc_xive *xive = dev->private; 2375 2366 2376 2367 /* Register some debug interfaces */ 2377 2368 xive_debugfs_init(xive);
+3 -12
arch/powerpc/kvm/book3s_xive_native.c
··· 1259 1259 1260 1260 static void xive_native_debugfs_init(struct kvmppc_xive *xive) 1261 1261 { 1262 - char *name; 1263 - 1264 - name = kasprintf(GFP_KERNEL, "kvm-xive-%p", xive); 1265 - if (!name) { 1266 - pr_err("%s: no memory for name\n", __func__); 1267 - return; 1268 - } 1269 - 1270 - xive->dentry = debugfs_create_file(name, 0444, arch_debugfs_dir, 1262 + xive->dentry = debugfs_create_file("xive", 0444, xive->kvm->debugfs_dentry, 1271 1263 xive, &xive_native_debug_fops); 1272 1264 1273 - pr_debug("%s: created %s\n", __func__, name); 1274 - kfree(name); 1265 + pr_debug("%s: created\n", __func__); 1275 1266 } 1276 1267 1277 1268 static void kvmppc_xive_native_init(struct kvm_device *dev) 1278 1269 { 1279 - struct kvmppc_xive *xive = (struct kvmppc_xive *)dev->private; 1270 + struct kvmppc_xive *xive = dev->private; 1280 1271 1281 1272 /* Register some debug interfaces */ 1282 1273 xive_native_debugfs_init(xive);
+1
arch/powerpc/kvm/e500.c
··· 495 495 .emulate_op = kvmppc_core_emulate_op_e500, 496 496 .emulate_mtspr = kvmppc_core_emulate_mtspr_e500, 497 497 .emulate_mfspr = kvmppc_core_emulate_mfspr_e500, 498 + .create_vcpu_debugfs = kvmppc_create_vcpu_debugfs_e500, 498 499 }; 499 500 500 501 static int __init kvmppc_e500_init(void)
+1
arch/powerpc/kvm/e500mc.c
··· 381 381 .emulate_op = kvmppc_core_emulate_op_e500, 382 382 .emulate_mtspr = kvmppc_core_emulate_mtspr_e500, 383 383 .emulate_mfspr = kvmppc_core_emulate_mfspr_e500, 384 + .create_vcpu_debugfs = kvmppc_create_vcpu_debugfs_e500, 384 385 }; 385 386 386 387 static int __init kvmppc_e500mc_init(void)
+3 -7
arch/powerpc/kvm/emulate_loadstore.c
··· 73 73 { 74 74 u32 inst; 75 75 enum emulation_result emulated = EMULATE_FAIL; 76 - int advance = 1; 77 76 struct instruction_op op; 78 77 79 78 /* this default type might be overwritten by subcategories */ ··· 96 97 if (analyse_instr(&op, &vcpu->arch.regs, ppc_inst(inst)) == 0) { 97 98 int type = op.type & INSTR_TYPE_MASK; 98 99 int size = GETSIZE(op.type); 100 + 101 + vcpu->mmio_is_write = OP_IS_STORE(type); 99 102 100 103 switch (type) { 101 104 case LOAD: { ··· 356 355 } 357 356 } 358 357 359 - if (emulated == EMULATE_FAIL) { 360 - advance = 0; 361 - kvmppc_core_queue_program(vcpu, 0); 362 - } 363 - 364 358 trace_kvm_ppc_instr(inst, kvmppc_get_pc(vcpu), emulated); 365 359 366 360 /* Advance past emulated instruction. */ 367 - if (advance) 361 + if (emulated != EMULATE_FAIL) 368 362 kvmppc_set_pc(vcpu, kvmppc_get_pc(vcpu) + 4); 369 363 370 364 return emulated;
+60 -21
arch/powerpc/kvm/powerpc.c
··· 307 307 u32 last_inst; 308 308 309 309 kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst); 310 - /* XXX Deliver Program interrupt to guest. */ 311 - pr_emerg("%s: emulation failed (%08x)\n", __func__, last_inst); 312 - r = RESUME_HOST; 310 + kvm_debug_ratelimited("Guest access to device memory using unsupported instruction (opcode: %#08x)\n", 311 + last_inst); 312 + 313 + /* 314 + * Injecting a Data Storage here is a bit more 315 + * accurate since the instruction that caused the 316 + * access could still be a valid one. 317 + */ 318 + if (!IS_ENABLED(CONFIG_BOOKE)) { 319 + ulong dsisr = DSISR_BADACCESS; 320 + 321 + if (vcpu->mmio_is_write) 322 + dsisr |= DSISR_ISSTORE; 323 + 324 + kvmppc_core_queue_data_storage(vcpu, vcpu->arch.vaddr_accessed, dsisr); 325 + } else { 326 + /* 327 + * BookE does not send a SIGBUS on a bad 328 + * fault, so use a Program interrupt instead 329 + * to avoid a fault loop. 330 + */ 331 + kvmppc_core_queue_program(vcpu, 0); 332 + } 333 + 334 + r = RESUME_GUEST; 313 335 break; 314 336 } 315 337 default: ··· 453 431 int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) 454 432 { 455 433 struct kvmppc_ops *kvm_ops = NULL; 434 + int r; 435 + 456 436 /* 457 437 * if we have both HV and PR enabled, default is HV 458 438 */ ··· 476 452 } else 477 453 goto err_out; 478 454 479 - if (kvm_ops->owner && !try_module_get(kvm_ops->owner)) 455 + if (!try_module_get(kvm_ops->owner)) 480 456 return -ENOENT; 481 457 482 458 kvm->arch.kvm_ops = kvm_ops; 483 - return kvmppc_core_init_vm(kvm); 459 + r = kvmppc_core_init_vm(kvm); 460 + if (r) 461 + module_put(kvm_ops->owner); 462 + return r; 484 463 err_out: 485 464 return -EINVAL; 486 465 } ··· 782 755 783 756 rcuwait_init(&vcpu->arch.wait); 784 757 vcpu->arch.waitp = &vcpu->arch.wait; 785 - kvmppc_create_vcpu_debugfs(vcpu, vcpu->vcpu_id); 786 758 return 0; 787 759 788 760 out_vcpu_uninit: ··· 797 771 { 798 772 /* Make sure we're not using the vcpu anymore */ 799 773 hrtimer_cancel(&vcpu->arch.dec_timer); 800 - 801 - kvmppc_remove_vcpu_debugfs(vcpu); 802 774 803 775 switch (vcpu->arch.irq_type) { 804 776 case KVMPPC_IRQ_MPIC: ··· 1138 1114 struct kvm_run *run = vcpu->run; 1139 1115 u64 gpr; 1140 1116 1141 - if (run->mmio.len > sizeof(gpr)) { 1142 - printk(KERN_ERR "bad MMIO length: %d\n", run->mmio.len); 1117 + if (run->mmio.len > sizeof(gpr)) 1143 1118 return; 1144 - } 1145 1119 1146 1120 if (!vcpu->arch.mmio_host_swabbed) { 1147 1121 switch (run->mmio.len) { ··· 1258 1236 host_swabbed = !is_default_endian; 1259 1237 } 1260 1238 1261 - if (bytes > sizeof(run->mmio.data)) { 1262 - printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__, 1263 - run->mmio.len); 1264 - } 1239 + if (bytes > sizeof(run->mmio.data)) 1240 + return EMULATE_FAIL; 1265 1241 1266 1242 run->mmio.phys_addr = vcpu->arch.paddr_accessed; 1267 1243 run->mmio.len = bytes; ··· 1345 1325 host_swabbed = !is_default_endian; 1346 1326 } 1347 1327 1348 - if (bytes > sizeof(run->mmio.data)) { 1349 - printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__, 1350 - run->mmio.len); 1351 - } 1328 + if (bytes > sizeof(run->mmio.data)) 1329 + return EMULATE_FAIL; 1352 1330 1353 1331 run->mmio.phys_addr = vcpu->arch.paddr_accessed; 1354 1332 run->mmio.len = bytes; ··· 1517 1499 { 1518 1500 enum emulation_result emulated = EMULATE_DONE; 1519 1501 1520 - if (vcpu->arch.mmio_vsx_copy_nums > 2) 1502 + if (vcpu->arch.mmio_vmx_copy_nums > 2) 1521 1503 return EMULATE_FAIL; 1522 1504 1523 1505 while (vcpu->arch.mmio_vmx_copy_nums) { ··· 1614 1596 unsigned int index = rs & KVM_MMIO_REG_MASK; 1615 1597 enum emulation_result emulated = EMULATE_DONE; 1616 1598 1617 - if (vcpu->arch.mmio_vsx_copy_nums > 2) 1599 + if (vcpu->arch.mmio_vmx_copy_nums > 2) 1618 1600 return EMULATE_FAIL; 1619 1601 1620 1602 vcpu->arch.io_gpr = rs; ··· 1859 1841 #ifdef CONFIG_ALTIVEC 1860 1842 out: 1861 1843 #endif 1844 + 1845 + /* 1846 + * We're already returning to userspace, don't pass the 1847 + * RESUME_HOST flags along. 1848 + */ 1849 + if (r > 0) 1850 + r = 0; 1851 + 1862 1852 vcpu_put(vcpu); 1863 1853 return r; 1864 1854 } ··· 2523 2497 } 2524 2498 2525 2499 EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_ppc_instr); 2500 + 2501 + void kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu, struct dentry *debugfs_dentry) 2502 + { 2503 + if (vcpu->kvm->arch.kvm_ops->create_vcpu_debugfs) 2504 + vcpu->kvm->arch.kvm_ops->create_vcpu_debugfs(vcpu, debugfs_dentry); 2505 + } 2506 + 2507 + int kvm_arch_create_vm_debugfs(struct kvm *kvm) 2508 + { 2509 + if (kvm->arch.kvm_ops->create_vm_debugfs) 2510 + kvm->arch.kvm_ops->create_vm_debugfs(kvm); 2511 + return 0; 2512 + }
+5 -16
arch/powerpc/kvm/timing.c
··· 204 204 .release = single_release, 205 205 }; 206 206 207 - void kvmppc_create_vcpu_debugfs(struct kvm_vcpu *vcpu, unsigned int id) 207 + int kvmppc_create_vcpu_debugfs_e500(struct kvm_vcpu *vcpu, 208 + struct dentry *debugfs_dentry) 208 209 { 209 - static char dbg_fname[50]; 210 - struct dentry *debugfs_file; 211 - 212 - snprintf(dbg_fname, sizeof(dbg_fname), "vm%u_vcpu%u_timing", 213 - current->pid, id); 214 - debugfs_file = debugfs_create_file(dbg_fname, 0666, kvm_debugfs_dir, 215 - vcpu, &kvmppc_exit_timing_fops); 216 - 217 - vcpu->arch.debugfs_exit_timing = debugfs_file; 218 - } 219 - 220 - void kvmppc_remove_vcpu_debugfs(struct kvm_vcpu *vcpu) 221 - { 222 - debugfs_remove(vcpu->arch.debugfs_exit_timing); 223 - vcpu->arch.debugfs_exit_timing = NULL; 210 + debugfs_create_file("timing", 0666, debugfs_dentry, 211 + vcpu, &kvmppc_exit_timing_fops); 212 + return 0; 224 213 }
+7 -5
arch/powerpc/kvm/timing.h
··· 14 14 #ifdef CONFIG_KVM_EXIT_TIMING 15 15 void kvmppc_init_timing_stats(struct kvm_vcpu *vcpu); 16 16 void kvmppc_update_timing_stats(struct kvm_vcpu *vcpu); 17 - void kvmppc_create_vcpu_debugfs(struct kvm_vcpu *vcpu, unsigned int id); 18 - void kvmppc_remove_vcpu_debugfs(struct kvm_vcpu *vcpu); 17 + int kvmppc_create_vcpu_debugfs_e500(struct kvm_vcpu *vcpu, 18 + struct dentry *debugfs_dentry); 19 19 20 20 static inline void kvmppc_set_exit_type(struct kvm_vcpu *vcpu, int type) 21 21 { ··· 26 26 /* if exit timing is not configured there is no need to build the c file */ 27 27 static inline void kvmppc_init_timing_stats(struct kvm_vcpu *vcpu) {} 28 28 static inline void kvmppc_update_timing_stats(struct kvm_vcpu *vcpu) {} 29 - static inline void kvmppc_create_vcpu_debugfs(struct kvm_vcpu *vcpu, 30 - unsigned int id) {} 31 - static inline void kvmppc_remove_vcpu_debugfs(struct kvm_vcpu *vcpu) {} 29 + static inline int kvmppc_create_vcpu_debugfs_e500(struct kvm_vcpu *vcpu, 30 + struct dentry *debugfs_dentry) 31 + { 32 + return 0; 33 + } 32 34 static inline void kvmppc_set_exit_type(struct kvm_vcpu *vcpu, int type) {} 33 35 #endif /* CONFIG_KVM_EXIT_TIMING */ 34 36
+1
arch/powerpc/kvm/trace_hv.h
··· 115 115 {H_VASI_STATE, "H_VASI_STATE"}, \ 116 116 {H_ENABLE_CRQ, "H_ENABLE_CRQ"}, \ 117 117 {H_GET_EM_PARMS, "H_GET_EM_PARMS"}, \ 118 + {H_GET_ENERGY_SCALE_INFO, "H_GET_ENERGY_SCALE_INFO"}, \ 118 119 {H_SET_MPP, "H_SET_MPP"}, \ 119 120 {H_GET_MPP, "H_GET_MPP"}, \ 120 121 {H_HOME_NODE_ASSOCIATIVITY, "H_HOME_NODE_ASSOCIATIVITY"}, \
-3
arch/powerpc/lib/checksum_32.S
··· 116 116 EX_TABLE(8 ## n ## 7b, fault); 117 117 118 118 .text 119 - .stabs "arch/powerpc/lib/",N_SO,0,0,0f 120 - .stabs "checksum_32.S",N_SO,0,0,0f 121 - 0: 122 119 123 120 CACHELINE_BYTES = L1_CACHE_BYTES 124 121 LG_CACHELINE_BYTES = L1_CACHE_SHIFT
+14
arch/powerpc/lib/code-patching.c
··· 43 43 #ifdef CONFIG_STRICT_KERNEL_RWX 44 44 static DEFINE_PER_CPU(struct vm_struct *, text_poke_area); 45 45 46 + static int map_patch_area(void *addr, unsigned long text_poke_addr); 47 + static void unmap_patch_area(unsigned long addr); 48 + 46 49 static int text_area_cpu_up(unsigned int cpu) 47 50 { 48 51 struct vm_struct *area; 52 + unsigned long addr; 53 + int err; 49 54 50 55 area = get_vm_area(PAGE_SIZE, VM_ALLOC); 51 56 if (!area) { ··· 58 53 cpu); 59 54 return -1; 60 55 } 56 + 57 + // Map/unmap the area to ensure all page tables are pre-allocated 58 + addr = (unsigned long)area->addr; 59 + err = map_patch_area(empty_zero_page, addr); 60 + if (err) 61 + return err; 62 + 63 + unmap_patch_area(addr); 64 + 61 65 this_cpu_write(text_poke_area, area); 62 66 63 67 return 0;
-3
arch/powerpc/lib/copy_32.S
··· 57 57 EX_TABLE(8 ## n ## 7b,9 ## n ## 1b) 58 58 59 59 .text 60 - .stabs "arch/powerpc/lib/",N_SO,0,0,0f 61 - .stabs "copy_32.S",N_SO,0,0,0f 62 - 0: 63 60 64 61 CACHELINE_BYTES = L1_CACHE_BYTES 65 62 LG_CACHELINE_BYTES = L1_CACHE_SHIFT
+11 -19
arch/powerpc/lib/sstep.c
··· 75 75 static nokprobe_inline unsigned long truncate_if_32bit(unsigned long msr, 76 76 unsigned long val) 77 77 { 78 - #ifdef __powerpc64__ 79 78 if ((msr & MSR_64BIT) == 0) 80 79 val &= 0xffffffffUL; 81 - #endif 82 80 return val; 83 81 } 84 82 ··· 1063 1065 int emulate_dcbz(unsigned long ea, struct pt_regs *regs) 1064 1066 { 1065 1067 int err; 1066 - unsigned long size; 1068 + unsigned long size = l1_dcache_bytes(); 1067 1069 1068 - #ifdef __powerpc64__ 1069 - size = ppc64_caches.l1d.block_size; 1070 - if (!(regs->msr & MSR_64BIT)) 1071 - ea &= 0xffffffffUL; 1072 - #else 1073 - size = L1_CACHE_BYTES; 1074 - #endif 1070 + ea = truncate_if_32bit(regs->msr, ea); 1075 1071 ea &= ~(size - 1); 1076 1072 if (!address_ok(regs, ea, size)) 1077 1073 return -EFAULT; ··· 1089 1097 1090 1098 #define __put_user_asmx(x, addr, err, op, cr) \ 1091 1099 __asm__ __volatile__( \ 1100 + ".machine push\n" \ 1101 + ".machine power8\n" \ 1092 1102 "1: " op " %2,0,%3\n" \ 1103 + ".machine pop\n" \ 1093 1104 " mfcr %1\n" \ 1094 1105 "2:\n" \ 1095 1106 ".section .fixup,\"ax\"\n" \ ··· 1105 1110 1106 1111 #define __get_user_asmx(x, addr, err, op) \ 1107 1112 __asm__ __volatile__( \ 1113 + ".machine push\n" \ 1114 + ".machine power8\n" \ 1108 1115 "1: "op" %1,0,%2\n" \ 1116 + ".machine pop\n" \ 1109 1117 "2:\n" \ 1110 1118 ".section .fixup,\"ax\"\n" \ 1111 1119 "3: li %0,%3\n" \ ··· 1137 1139 1138 1140 op->type |= SETCC; 1139 1141 op->ccval = (regs->ccr & 0x0fffffff) | ((regs->xer >> 3) & 0x10000000); 1140 - #ifdef __powerpc64__ 1141 1142 if (!(regs->msr & MSR_64BIT)) 1142 1143 val = (int) val; 1143 - #endif 1144 1144 if (val < 0) 1145 1145 op->ccval |= 0x80000000; 1146 1146 else if (val > 0) ··· 1169 1173 op->type = COMPUTE + SETREG + SETXER; 1170 1174 op->reg = rd; 1171 1175 op->val = val; 1172 - #ifdef __powerpc64__ 1173 - if (!(regs->msr & MSR_64BIT)) { 1174 - val = (unsigned int) val; 1175 - val1 = (unsigned int) val1; 1176 - } 1177 - #endif 1176 + val = truncate_if_32bit(regs->msr, val); 1177 + val1 = truncate_if_32bit(regs->msr, val1); 1178 1178 op->xerval = regs->xer; 1179 1179 if (val < val1 || (carry_in && val == val1)) 1180 1180 op->xerval |= XER_CA; ··· 3381 3389 __put_user_asmx(op->val, ea, err, "stbcx.", cr); 3382 3390 break; 3383 3391 case 2: 3384 - __put_user_asmx(op->val, ea, err, "stbcx.", cr); 3392 + __put_user_asmx(op->val, ea, err, "sthcx.", cr); 3385 3393 break; 3386 3394 #endif 3387 3395 case 4:
-1
arch/powerpc/lib/vmx-helper.c
··· 9 9 #include <linux/uaccess.h> 10 10 #include <linux/hardirq.h> 11 11 #include <asm/switch_to.h> 12 - #include <asm/asm-prototypes.h> 13 12 14 13 int enter_vmx_usercopy(void) 15 14 {
+8 -46
arch/powerpc/mm/book3s64/hash_utils.c
··· 1621 1621 } 1622 1622 EXPORT_SYMBOL_GPL(hash_page); 1623 1623 1624 - DECLARE_INTERRUPT_HANDLER(__do_hash_fault); 1625 - DEFINE_INTERRUPT_HANDLER(__do_hash_fault) 1624 + DEFINE_INTERRUPT_HANDLER(do_hash_fault) 1626 1625 { 1627 1626 unsigned long ea = regs->dar; 1628 1627 unsigned long dsisr = regs->dsisr; ··· 1678 1679 } else if (err) { 1679 1680 hash__do_page_fault(regs); 1680 1681 } 1681 - } 1682 - 1683 - /* 1684 - * The _RAW interrupt entry checks for the in_nmi() case before 1685 - * running the full handler. 1686 - */ 1687 - DEFINE_INTERRUPT_HANDLER_RAW(do_hash_fault) 1688 - { 1689 - /* 1690 - * If we are in an "NMI" (e.g., an interrupt when soft-disabled), then 1691 - * don't call hash_page, just fail the fault. This is required to 1692 - * prevent re-entrancy problems in the hash code, namely perf 1693 - * interrupts hitting while something holds H_PAGE_BUSY, and taking a 1694 - * hash fault. See the comment in hash_preload(). 1695 - * 1696 - * We come here as a result of a DSI at a point where we don't want 1697 - * to call hash_page, such as when we are accessing memory (possibly 1698 - * user memory) inside a PMU interrupt that occurred while interrupts 1699 - * were soft-disabled. We want to invoke the exception handler for 1700 - * the access, or panic if there isn't a handler. 1701 - */ 1702 - if (unlikely(in_nmi())) { 1703 - do_bad_page_fault_segv(regs); 1704 - return 0; 1705 - } 1706 - 1707 - __do_hash_fault(regs); 1708 - 1709 - return 0; 1710 1682 } 1711 1683 1712 1684 #ifdef CONFIG_PPC_MM_SLICES ··· 1746 1776 #endif /* CONFIG_PPC_64K_PAGES */ 1747 1777 1748 1778 /* 1749 - * __hash_page_* must run with interrupts off, as it sets the 1750 - * H_PAGE_BUSY bit. It's possible for perf interrupts to hit at any 1751 - * time and may take a hash fault reading the user stack, see 1752 - * read_user_stack_slow() in the powerpc/perf code. 1779 + * __hash_page_* must run with interrupts off, including PMI interrupts 1780 + * off, as it sets the H_PAGE_BUSY bit. 1753 1781 * 1754 - * If that takes a hash fault on the same page as we lock here, it 1755 - * will bail out when seeing H_PAGE_BUSY set, and retry the access 1756 - * leading to an infinite loop. 1757 - * 1758 - * Disabling interrupts here does not prevent perf interrupts, but it 1759 - * will prevent them taking hash faults (see the NMI test in 1760 - * do_hash_page), then read_user_stack's copy_from_user_nofault will 1761 - * fail and perf will fall back to read_user_stack_slow(), which 1762 - * walks the Linux page tables. 1782 + * It's otherwise possible for perf interrupts to hit at any time and 1783 + * may take a hash fault reading the user stack, which could take a 1784 + * hash miss and deadlock on the same H_PAGE_BUSY bit. 1763 1785 * 1764 1786 * Interrupts must also be off for the duration of the 1765 1787 * mm_is_thread_local test and update, to prevent preempt running the 1766 1788 * mm on another CPU (XXX: this may be racy vs kthread_use_mm). 1767 1789 */ 1768 - local_irq_save(flags); 1790 + powerpc_local_irq_pmu_save(flags); 1769 1791 1770 1792 /* Is that local to this CPU ? */ 1771 1793 if (mm_is_thread_local(mm)) ··· 1782 1820 mm_ctx_user_psize(&mm->context), 1783 1821 pte_val(*ptep)); 1784 1822 1785 - local_irq_restore(flags); 1823 + powerpc_local_irq_pmu_restore(flags); 1786 1824 } 1787 1825 1788 1826 /*
+1 -1
arch/powerpc/mm/book3s64/hugetlbpage.c
··· 150 150 set_huge_pte_at(vma->vm_mm, addr, ptep, pte); 151 151 } 152 152 153 - void __init hugetlbpage_init_default(void) 153 + void __init hugetlbpage_init_defaultsize(void) 154 154 { 155 155 /* Set default large page size. Currently, we pick 16M or 1M 156 156 * depending on what is available
-1
arch/powerpc/mm/book3s64/slb.c
··· 9 9 * Copyright (C) 2002 Anton Blanchard <anton@au.ibm.com>, IBM 10 10 */ 11 11 12 - #include <asm/asm-prototypes.h> 13 12 #include <asm/interrupt.h> 14 13 #include <asm/mmu.h> 15 14 #include <asm/mmu_context.h>
+10 -5
arch/powerpc/mm/fault.c
··· 35 35 #include <linux/kfence.h> 36 36 #include <linux/pkeys.h> 37 37 38 - #include <asm/asm-prototypes.h> 39 38 #include <asm/firmware.h> 40 39 #include <asm/interrupt.h> 41 40 #include <asm/page.h> ··· 566 567 static void __bad_page_fault(struct pt_regs *regs, int sig) 567 568 { 568 569 int is_write = page_fault_is_write(regs->dsisr); 570 + const char *msg; 569 571 570 572 /* kernel has accessed a bad area */ 571 573 574 + if (regs->dar < PAGE_SIZE) 575 + msg = "Kernel NULL pointer dereference"; 576 + else 577 + msg = "Unable to handle kernel data access"; 578 + 572 579 switch (TRAP(regs)) { 573 580 case INTERRUPT_DATA_STORAGE: 574 - case INTERRUPT_DATA_SEGMENT: 575 581 case INTERRUPT_H_DATA_STORAGE: 576 - pr_alert("BUG: %s on %s at 0x%08lx\n", 577 - regs->dar < PAGE_SIZE ? "Kernel NULL pointer dereference" : 578 - "Unable to handle kernel data access", 582 + pr_alert("BUG: %s on %s at 0x%08lx\n", msg, 579 583 is_write ? "write" : "read", regs->dar); 584 + break; 585 + case INTERRUPT_DATA_SEGMENT: 586 + pr_alert("BUG: %s at 0x%08lx\n", msg, regs->dar); 580 587 break; 581 588 case INTERRUPT_INST_STORAGE: 582 589 case INTERRUPT_INST_SEGMENT:
+1 -4
arch/powerpc/mm/hugetlbpage.c
··· 664 664 configured = true; 665 665 } 666 666 667 - if (configured) { 668 - if (IS_ENABLED(CONFIG_HUGETLB_PAGE_SIZE_VARIABLE)) 669 - hugetlbpage_init_default(); 670 - } else 667 + if (!configured) 671 668 pr_info("Failed to initialize. Disabling HugeTLB"); 672 669 673 670 return 0;
+4
arch/powerpc/mm/init_64.c
··· 59 59 #include <asm/sections.h> 60 60 #include <asm/iommu.h> 61 61 #include <asm/vdso.h> 62 + #include <asm/hugetlb.h> 62 63 63 64 #include <mm/mmu_decl.h> 64 65 ··· 513 512 memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE); 514 513 } else 515 514 hash__early_init_devtree(); 515 + 516 + if (IS_ENABLED(CONFIG_HUGETLB_PAGE_SIZE_VARIABLE)) 517 + hugetlbpage_init_defaultsize(); 516 518 517 519 if (!(cur_cpu_spec->mmu_features & MMU_FTR_HPTE_TABLE) && 518 520 !(cur_cpu_spec->mmu_features & MMU_FTR_TYPE_RADIX))
+1 -2
arch/powerpc/mm/kasan/kasan_init_32.c
··· 83 83 kasan_update_early_region(unsigned long k_start, unsigned long k_end, pte_t pte) 84 84 { 85 85 unsigned long k_cur; 86 - phys_addr_t pa = __pa(kasan_early_shadow_page); 87 86 88 87 for (k_cur = k_start; k_cur != k_end; k_cur += PAGE_SIZE) { 89 88 pmd_t *pmd = pmd_off_k(k_cur); 90 89 pte_t *ptep = pte_offset_kernel(pmd, k_cur); 91 90 92 - if ((pte_val(*ptep) & PTE_RPN_MASK) != pa) 91 + if (pte_page(*ptep) != virt_to_page(lm_alias(kasan_early_shadow_page))) 93 92 continue; 94 93 95 94 __set_pte_at(&init_mm, k_cur, ptep, pte, 0);
+3 -1
arch/powerpc/mm/numa.c
··· 956 956 of_node_put(cpu); 957 957 } 958 958 959 - node_set_online(nid); 959 + /* node_set_online() is an UB if 'nid' is negative */ 960 + if (likely(nid >= 0)) 961 + node_set_online(nid); 960 962 } 961 963 962 964 get_n_mem_cells(&n_mem_addr_cells, &n_mem_size_cells);
+19 -52
arch/powerpc/mm/pageattr.c
··· 15 15 #include <asm/pgtable.h> 16 16 17 17 18 + static pte_basic_t pte_update_delta(pte_t *ptep, unsigned long addr, 19 + unsigned long old, unsigned long new) 20 + { 21 + return pte_update(&init_mm, addr, ptep, old & ~new, new & ~old, 0); 22 + } 23 + 18 24 /* 19 - * Updates the attributes of a page in three steps: 20 - * 21 - * 1. take the page_table_lock 22 - * 2. install the new entry with the updated attributes 23 - * 3. flush the TLB 25 + * Updates the attributes of a page atomically. 24 26 * 25 27 * This sequence is safe against concurrent updates, and also allows updating the 26 28 * attributes of a page currently being executed or accessed. ··· 30 28 static int change_page_attr(pte_t *ptep, unsigned long addr, void *data) 31 29 { 32 30 long action = (long)data; 33 - pte_t pte; 34 31 35 - spin_lock(&init_mm.page_table_lock); 36 - 37 - pte = ptep_get(ptep); 38 - 39 - /* modify the PTE bits as desired, then apply */ 32 + /* modify the PTE bits as desired */ 40 33 switch (action) { 41 34 case SET_MEMORY_RO: 42 - pte = pte_wrprotect(pte); 35 + /* Don't clear DIRTY bit */ 36 + pte_update_delta(ptep, addr, _PAGE_KERNEL_RW & ~_PAGE_DIRTY, _PAGE_KERNEL_RO); 43 37 break; 44 38 case SET_MEMORY_RW: 45 - pte = pte_mkwrite(pte_mkdirty(pte)); 39 + pte_update_delta(ptep, addr, _PAGE_KERNEL_RO, _PAGE_KERNEL_RW); 46 40 break; 47 41 case SET_MEMORY_NX: 48 - pte = pte_exprotect(pte); 42 + pte_update_delta(ptep, addr, _PAGE_KERNEL_ROX, _PAGE_KERNEL_RO); 49 43 break; 50 44 case SET_MEMORY_X: 51 - pte = pte_mkexec(pte); 45 + pte_update_delta(ptep, addr, _PAGE_KERNEL_RO, _PAGE_KERNEL_ROX); 46 + break; 47 + case SET_MEMORY_NP: 48 + pte_update(&init_mm, addr, ptep, _PAGE_PRESENT, 0, 0); 49 + break; 50 + case SET_MEMORY_P: 51 + pte_update(&init_mm, addr, ptep, 0, _PAGE_PRESENT, 0); 52 52 break; 53 53 default: 54 54 WARN_ON_ONCE(1); 55 55 break; 56 56 } 57 57 58 - pte_update(&init_mm, addr, ptep, ~0UL, pte_val(pte), 0); 59 - 60 58 /* See ptesync comment in radix__set_pte_at() */ 61 59 if (radix_enabled()) 62 60 asm volatile("ptesync": : :"memory"); 63 61 64 62 flush_tlb_kernel_range(addr, addr + PAGE_SIZE); 65 - 66 - spin_unlock(&init_mm.page_table_lock); 67 63 68 64 return 0; 69 65 } ··· 95 95 96 96 return apply_to_existing_page_range(&init_mm, start, size, 97 97 change_page_attr, (void *)action); 98 - } 99 - 100 - /* 101 - * Set the attributes of a page: 102 - * 103 - * This function is used by PPC32 at the end of init to set final kernel memory 104 - * protection. It includes changing the maping of the page it is executing from 105 - * and data pages it is using. 106 - */ 107 - static int set_page_attr(pte_t *ptep, unsigned long addr, void *data) 108 - { 109 - pgprot_t prot = __pgprot((unsigned long)data); 110 - 111 - spin_lock(&init_mm.page_table_lock); 112 - 113 - set_pte_at(&init_mm, addr, ptep, pte_modify(*ptep, prot)); 114 - flush_tlb_kernel_range(addr, addr + PAGE_SIZE); 115 - 116 - spin_unlock(&init_mm.page_table_lock); 117 - 118 - return 0; 119 - } 120 - 121 - int set_memory_attr(unsigned long addr, int numpages, pgprot_t prot) 122 - { 123 - unsigned long start = ALIGN_DOWN(addr, PAGE_SIZE); 124 - unsigned long sz = numpages * PAGE_SIZE; 125 - 126 - if (numpages <= 0) 127 - return 0; 128 - 129 - return apply_to_existing_page_range(&init_mm, start, sz, set_page_attr, 130 - (void *)pgprot_val(prot)); 131 98 }
+14 -13
arch/powerpc/mm/pgtable_32.c
··· 135 135 unsigned long numpages = PFN_UP((unsigned long)_einittext) - 136 136 PFN_DOWN((unsigned long)_sinittext); 137 137 138 - if (v_block_mapped((unsigned long)_sinittext)) 138 + if (v_block_mapped((unsigned long)_sinittext)) { 139 139 mmu_mark_initmem_nx(); 140 - else 141 - set_memory_attr((unsigned long)_sinittext, numpages, PAGE_KERNEL); 140 + } else { 141 + set_memory_nx((unsigned long)_sinittext, numpages); 142 + set_memory_rw((unsigned long)_sinittext, numpages); 143 + } 142 144 } 143 145 144 146 #ifdef CONFIG_STRICT_KERNEL_RWX ··· 148 146 { 149 147 unsigned long numpages; 150 148 149 + if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX) && mmu_has_feature(MMU_FTR_HPTE_TABLE)) 150 + pr_warn("This platform has HASH MMU, STRICT_MODULE_RWX won't work\n"); 151 + 151 152 if (v_block_mapped((unsigned long)_stext + 1)) { 152 153 mmu_mark_rodata_ro(); 153 154 ptdump_check_wx(); 154 155 return; 155 156 } 156 157 157 - numpages = PFN_UP((unsigned long)_etext) - 158 - PFN_DOWN((unsigned long)_stext); 159 - 160 - set_memory_attr((unsigned long)_stext, numpages, PAGE_KERNEL_ROX); 161 158 /* 162 - * mark .rodata as read only. Use __init_begin rather than __end_rodata 163 - * to cover NOTES and EXCEPTION_TABLE. 159 + * mark .text and .rodata as read only. Use __init_begin rather than 160 + * __end_rodata to cover NOTES and EXCEPTION_TABLE. 164 161 */ 165 162 numpages = PFN_UP((unsigned long)__init_begin) - 166 - PFN_DOWN((unsigned long)__start_rodata); 163 + PFN_DOWN((unsigned long)_stext); 167 164 168 - set_memory_attr((unsigned long)__start_rodata, numpages, PAGE_KERNEL_RO); 165 + set_memory_ro((unsigned long)_stext, numpages); 169 166 170 167 // mark_initmem_nx() should have already run by now 171 168 ptdump_check_wx(); ··· 180 179 return; 181 180 182 181 if (enable) 183 - set_memory_attr(addr, numpages, PAGE_KERNEL); 182 + set_memory_p(addr, numpages); 184 183 else 185 - set_memory_attr(addr, numpages, __pgprot(0)); 184 + set_memory_np(addr, numpages); 186 185 } 187 186 #endif /* CONFIG_DEBUG_PAGEALLOC */
+4 -1
arch/powerpc/mm/ptdump/hashpagetable.c
··· 238 238 239 239 static int pseries_find(unsigned long ea, int psize, bool primary, u64 *v, u64 *r) 240 240 { 241 - struct hash_pte ptes[4]; 241 + struct { 242 + unsigned long v; 243 + unsigned long r; 244 + } ptes[4]; 242 245 unsigned long vsid, vpn, hash, hpte_group, want_v; 243 246 int i, j, ssize = mmu_kernel_ssize; 244 247 long lpar_rc = 0;
+13 -25
arch/powerpc/net/bpf_jit.h
··· 27 27 #define PPC_JMP(dest) \ 28 28 do { \ 29 29 long offset = (long)(dest) - (ctx->idx * 4); \ 30 - if (!is_offset_in_branch_range(offset)) { \ 30 + if ((dest) != 0 && !is_offset_in_branch_range(offset)) { \ 31 31 pr_err_ratelimited("Branch offset 0x%lx (@%u) out of range\n", offset, ctx->idx); \ 32 32 return -ERANGE; \ 33 33 } \ 34 34 EMIT(PPC_RAW_BRANCH(offset)); \ 35 35 } while (0) 36 36 37 - /* blr; (unconditional 'branch' with link) to absolute address */ 38 - #define PPC_BL_ABS(dest) EMIT(PPC_INST_BL | \ 39 - (((dest) - (unsigned long)(image + ctx->idx)) & 0x03fffffc)) 37 + /* bl (unconditional 'branch' with link) */ 38 + #define PPC_BL(dest) EMIT(PPC_INST_BL | (((dest) - (unsigned long)(image + ctx->idx)) & 0x03fffffc)) 39 + 40 40 /* "cond" here covers BO:BI fields. */ 41 41 #define PPC_BCC_SHORT(cond, dest) \ 42 42 do { \ 43 43 long offset = (long)(dest) - (ctx->idx * 4); \ 44 - if (!is_offset_in_cond_branch_range(offset)) { \ 44 + if ((dest) != 0 && !is_offset_in_cond_branch_range(offset)) { \ 45 45 pr_err_ratelimited("Conditional branch offset 0x%lx (@%u) out of range\n", offset, ctx->idx); \ 46 46 return -ERANGE; \ 47 47 } \ ··· 59 59 EMIT(PPC_RAW_ORI(d, d, IMM_L(i))); \ 60 60 } } while(0) 61 61 62 - #ifdef CONFIG_PPC32 63 - #define PPC_EX32(r, i) EMIT(PPC_RAW_LI((r), (i) < 0 ? -1 : 0)) 64 - #endif 65 - 62 + #ifdef CONFIG_PPC64 66 63 #define PPC_LI64(d, i) do { \ 67 64 if ((long)(i) >= -2147483648 && \ 68 65 (long)(i) < 2147483648) \ ··· 82 85 EMIT(PPC_RAW_ORI(d, d, (uintptr_t)(i) & \ 83 86 0xffff)); \ 84 87 } } while (0) 85 - 86 - #ifdef CONFIG_PPC64 87 - #define PPC_FUNC_ADDR(d,i) do { PPC_LI64(d, i); } while(0) 88 - #else 89 - #define PPC_FUNC_ADDR(d,i) do { PPC_LI32(d, i); } while(0) 90 88 #endif 91 89 92 90 /* ··· 119 127 #define SEEN_FUNC 0x20000000 /* might call external helpers */ 120 128 #define SEEN_TAILCALL 0x40000000 /* uses tail calls */ 121 129 122 - #define SEEN_VREG_MASK 0x1ff80000 /* Volatile registers r3-r12 */ 123 - #define SEEN_NVREG_MASK 0x0003ffff /* Non volatile registers r14-r31 */ 124 - 125 - #ifdef CONFIG_PPC64 126 - extern const int b2p[MAX_BPF_JIT_REG + 2]; 127 - #else 128 - extern const int b2p[MAX_BPF_JIT_REG + 1]; 129 - #endif 130 - 131 130 struct codegen_context { 132 131 /* 133 132 * This is used to track register usage as well ··· 132 149 unsigned int seen; 133 150 unsigned int idx; 134 151 unsigned int stack_size; 135 - int b2p[ARRAY_SIZE(b2p)]; 152 + int b2p[MAX_BPF_JIT_REG + 2]; 136 153 unsigned int exentry_idx; 154 + unsigned int alt_exit_addr; 137 155 }; 156 + 157 + #define bpf_to_ppc(r) (ctx->b2p[r]) 138 158 139 159 #ifdef CONFIG_PPC32 140 160 #define BPF_FIXUP_LEN 3 /* Three instructions => 12 bytes */ ··· 166 180 ctx->seen &= ~(1 << (31 - i)); 167 181 } 168 182 169 - void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func); 183 + void bpf_jit_init_reg_mapping(struct codegen_context *ctx); 184 + int bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func); 170 185 int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, struct codegen_context *ctx, 171 186 u32 *addrs, int pass); 172 187 void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx); 173 188 void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx); 174 189 void bpf_jit_realloc_regs(struct codegen_context *ctx); 190 + int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg, long exit_addr); 175 191 176 192 int bpf_add_extable_entry(struct bpf_prog *fp, u32 *image, int pass, struct codegen_context *ctx, 177 193 int insn_idx, int jmp_off, int dst_reg);
-91
arch/powerpc/net/bpf_jit64.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0-only */ 2 - /* 3 - * bpf_jit64.h: BPF JIT compiler for PPC64 4 - * 5 - * Copyright 2016 Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> 6 - * IBM Corporation 7 - */ 8 - #ifndef _BPF_JIT64_H 9 - #define _BPF_JIT64_H 10 - 11 - #include "bpf_jit.h" 12 - 13 - /* 14 - * Stack layout: 15 - * Ensure the top half (upto local_tmp_var) stays consistent 16 - * with our redzone usage. 17 - * 18 - * [ prev sp ] <------------- 19 - * [ nv gpr save area ] 5*8 | 20 - * [ tail_call_cnt ] 8 | 21 - * [ local_tmp_var ] 16 | 22 - * fp (r31) --> [ ebpf stack space ] upto 512 | 23 - * [ frame header ] 32/112 | 24 - * sp (r1) ---> [ stack pointer ] -------------- 25 - */ 26 - 27 - /* for gpr non volatile registers BPG_REG_6 to 10 */ 28 - #define BPF_PPC_STACK_SAVE (5*8) 29 - /* for bpf JIT code internal usage */ 30 - #define BPF_PPC_STACK_LOCALS 24 31 - /* stack frame excluding BPF stack, ensure this is quadword aligned */ 32 - #define BPF_PPC_STACKFRAME (STACK_FRAME_MIN_SIZE + \ 33 - BPF_PPC_STACK_LOCALS + BPF_PPC_STACK_SAVE) 34 - 35 - #ifndef __ASSEMBLY__ 36 - 37 - /* BPF register usage */ 38 - #define TMP_REG_1 (MAX_BPF_JIT_REG + 0) 39 - #define TMP_REG_2 (MAX_BPF_JIT_REG + 1) 40 - 41 - /* BPF to ppc register mappings */ 42 - const int b2p[MAX_BPF_JIT_REG + 2] = { 43 - /* function return value */ 44 - [BPF_REG_0] = 8, 45 - /* function arguments */ 46 - [BPF_REG_1] = 3, 47 - [BPF_REG_2] = 4, 48 - [BPF_REG_3] = 5, 49 - [BPF_REG_4] = 6, 50 - [BPF_REG_5] = 7, 51 - /* non volatile registers */ 52 - [BPF_REG_6] = 27, 53 - [BPF_REG_7] = 28, 54 - [BPF_REG_8] = 29, 55 - [BPF_REG_9] = 30, 56 - /* frame pointer aka BPF_REG_10 */ 57 - [BPF_REG_FP] = 31, 58 - /* eBPF jit internal registers */ 59 - [BPF_REG_AX] = 2, 60 - [TMP_REG_1] = 9, 61 - [TMP_REG_2] = 10 62 - }; 63 - 64 - /* PPC NVR range -- update this if we ever use NVRs below r27 */ 65 - #define BPF_PPC_NVR_MIN 27 66 - 67 - /* 68 - * WARNING: These can use TMP_REG_2 if the offset is not at word boundary, 69 - * so ensure that it isn't in use already. 70 - */ 71 - #define PPC_BPF_LL(r, base, i) do { \ 72 - if ((i) % 4) { \ 73 - EMIT(PPC_RAW_LI(b2p[TMP_REG_2], (i)));\ 74 - EMIT(PPC_RAW_LDX(r, base, \ 75 - b2p[TMP_REG_2])); \ 76 - } else \ 77 - EMIT(PPC_RAW_LD(r, base, i)); \ 78 - } while(0) 79 - #define PPC_BPF_STL(r, base, i) do { \ 80 - if ((i) % 4) { \ 81 - EMIT(PPC_RAW_LI(b2p[TMP_REG_2], (i)));\ 82 - EMIT(PPC_RAW_STDX(r, base, \ 83 - b2p[TMP_REG_2])); \ 84 - } else \ 85 - EMIT(PPC_RAW_STD(r, base, i)); \ 86 - } while(0) 87 - #define PPC_BPF_STLU(r, base, i) do { EMIT(PPC_RAW_STDU(r, base, i)); } while(0) 88 - 89 - #endif /* !__ASSEMBLY__ */ 90 - 91 - #endif
+28 -6
arch/powerpc/net/bpf_jit_comp.c
··· 59 59 */ 60 60 tmp_idx = ctx->idx; 61 61 ctx->idx = addrs[i] / 4; 62 - bpf_jit_emit_func_call_rel(image, ctx, func_addr); 62 + ret = bpf_jit_emit_func_call_rel(image, ctx, func_addr); 63 + if (ret) 64 + return ret; 63 65 64 66 /* 65 67 * Restore ctx->idx here. This is safe as the length ··· 72 70 tmp_idx = ctx->idx; 73 71 ctx->idx = addrs[i] / 4; 74 72 #ifdef CONFIG_PPC32 75 - PPC_LI32(ctx->b2p[insn[i].dst_reg] - 1, (u32)insn[i + 1].imm); 76 - PPC_LI32(ctx->b2p[insn[i].dst_reg], (u32)insn[i].imm); 73 + PPC_LI32(bpf_to_ppc(insn[i].dst_reg) - 1, (u32)insn[i + 1].imm); 74 + PPC_LI32(bpf_to_ppc(insn[i].dst_reg), (u32)insn[i].imm); 77 75 for (j = ctx->idx - addrs[i] / 4; j < 4; j++) 78 76 EMIT(PPC_RAW_NOP()); 79 77 #else 80 78 func_addr = ((u64)(u32)insn[i].imm) | (((u64)(u32)insn[i + 1].imm) << 32); 81 - PPC_LI64(b2p[insn[i].dst_reg], func_addr); 79 + PPC_LI64(bpf_to_ppc(insn[i].dst_reg), func_addr); 82 80 /* overwrite rest with nops */ 83 81 for (j = ctx->idx - addrs[i] / 4; j < 5; j++) 84 82 EMIT(PPC_RAW_NOP()); ··· 86 84 ctx->idx = tmp_idx; 87 85 i++; 88 86 } 87 + } 88 + 89 + return 0; 90 + } 91 + 92 + int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg, long exit_addr) 93 + { 94 + if (!exit_addr || is_offset_in_branch_range(exit_addr - (ctx->idx * 4))) { 95 + PPC_JMP(exit_addr); 96 + } else if (ctx->alt_exit_addr) { 97 + if (WARN_ON(!is_offset_in_branch_range((long)ctx->alt_exit_addr - (ctx->idx * 4)))) 98 + return -1; 99 + PPC_JMP(ctx->alt_exit_addr); 100 + } else { 101 + ctx->alt_exit_addr = ctx->idx * 4; 102 + bpf_jit_build_epilogue(image, ctx); 89 103 } 90 104 91 105 return 0; ··· 179 161 } 180 162 181 163 memset(&cgctx, 0, sizeof(struct codegen_context)); 182 - memcpy(cgctx.b2p, b2p, sizeof(cgctx.b2p)); 164 + bpf_jit_init_reg_mapping(&cgctx); 183 165 184 166 /* Make sure that the stack is quadword aligned. */ 185 167 cgctx.stack_size = round_up(fp->aux->stack_depth, 16); ··· 195 177 * If we have seen a tail call, we need a second pass. 196 178 * This is because bpf_jit_emit_common_epilogue() is called 197 179 * from bpf_jit_emit_tail_call() with a not yet stable ctx->seen. 180 + * We also need a second pass if we ended up with too large 181 + * a program so as to ensure BPF_EXIT branches are in range. 198 182 */ 199 - if (cgctx.seen & SEEN_TAILCALL) { 183 + if (cgctx.seen & SEEN_TAILCALL || !is_offset_in_branch_range((long)cgctx.idx * 4)) { 200 184 cgctx.idx = 0; 201 185 if (bpf_jit_build_body(fp, 0, &cgctx, addrs, 0)) { 202 186 fp = org_fp; ··· 213 193 * calculate total size from idx. 214 194 */ 215 195 bpf_jit_build_prologue(0, &cgctx); 196 + addrs[fp->len] = cgctx.idx * 4; 216 197 bpf_jit_build_epilogue(0, &cgctx); 217 198 218 199 fixup_len = fp->aux->num_exentries * BPF_FIXUP_LEN * 4; ··· 254 233 for (pass = 1; pass < 3; pass++) { 255 234 /* Now build the prologue, body code & epilogue for real. */ 256 235 cgctx.idx = 0; 236 + cgctx.alt_exit_addr = 0; 257 237 bpf_jit_build_prologue(code_base, &cgctx); 258 238 if (bpf_jit_build_body(fp, code_base, &cgctx, addrs, pass)) { 259 239 bpf_jit_binary_free(bpf_hdr);
+78 -65
arch/powerpc/net/bpf_jit_comp32.c
··· 33 33 /* stack frame, ensure this is quadword aligned */ 34 34 #define BPF_PPC_STACKFRAME(ctx) (STACK_FRAME_MIN_SIZE + BPF_PPC_STACK_SAVE + (ctx)->stack_size) 35 35 36 - /* BPF register usage */ 37 - #define TMP_REG (MAX_BPF_JIT_REG + 0) 38 - 39 - /* BPF to ppc register mappings */ 40 - const int b2p[MAX_BPF_JIT_REG + 1] = { 41 - /* function return value */ 42 - [BPF_REG_0] = 12, 43 - /* function arguments */ 44 - [BPF_REG_1] = 4, 45 - [BPF_REG_2] = 6, 46 - [BPF_REG_3] = 8, 47 - [BPF_REG_4] = 10, 48 - [BPF_REG_5] = 22, 49 - /* non volatile registers */ 50 - [BPF_REG_6] = 24, 51 - [BPF_REG_7] = 26, 52 - [BPF_REG_8] = 28, 53 - [BPF_REG_9] = 30, 54 - /* frame pointer aka BPF_REG_10 */ 55 - [BPF_REG_FP] = 18, 56 - /* eBPF jit internal registers */ 57 - [BPF_REG_AX] = 20, 58 - [TMP_REG] = 31, /* 32 bits */ 59 - }; 60 - 61 - static int bpf_to_ppc(struct codegen_context *ctx, int reg) 62 - { 63 - return ctx->b2p[reg]; 64 - } 36 + #define PPC_EX32(r, i) EMIT(PPC_RAW_LI((r), (i) < 0 ? -1 : 0)) 65 37 66 38 /* PPC NVR range -- update this if we ever use NVRs below r17 */ 67 - #define BPF_PPC_NVR_MIN 17 68 - #define BPF_PPC_TC 16 39 + #define BPF_PPC_NVR_MIN _R17 40 + #define BPF_PPC_TC _R16 41 + 42 + /* BPF register usage */ 43 + #define TMP_REG (MAX_BPF_JIT_REG + 0) 44 + 45 + /* BPF to ppc register mappings */ 46 + void bpf_jit_init_reg_mapping(struct codegen_context *ctx) 47 + { 48 + /* function return value */ 49 + ctx->b2p[BPF_REG_0] = _R12; 50 + /* function arguments */ 51 + ctx->b2p[BPF_REG_1] = _R4; 52 + ctx->b2p[BPF_REG_2] = _R6; 53 + ctx->b2p[BPF_REG_3] = _R8; 54 + ctx->b2p[BPF_REG_4] = _R10; 55 + ctx->b2p[BPF_REG_5] = _R22; 56 + /* non volatile registers */ 57 + ctx->b2p[BPF_REG_6] = _R24; 58 + ctx->b2p[BPF_REG_7] = _R26; 59 + ctx->b2p[BPF_REG_8] = _R28; 60 + ctx->b2p[BPF_REG_9] = _R30; 61 + /* frame pointer aka BPF_REG_10 */ 62 + ctx->b2p[BPF_REG_FP] = _R18; 63 + /* eBPF jit internal registers */ 64 + ctx->b2p[BPF_REG_AX] = _R20; 65 + ctx->b2p[TMP_REG] = _R31; /* 32 bits */ 66 + } 69 67 70 68 static int bpf_jit_stack_offsetof(struct codegen_context *ctx, int reg) 71 69 { ··· 75 77 return BPF_PPC_STACKFRAME(ctx) - 4; 76 78 } 77 79 80 + #define SEEN_VREG_MASK 0x1ff80000 /* Volatile registers r3-r12 */ 81 + #define SEEN_NVREG_FULL_MASK 0x0003ffff /* Non volatile registers r14-r31 */ 82 + #define SEEN_NVREG_TEMP_MASK 0x00001e01 /* BPF_REG_5, BPF_REG_AX, TMP_REG */ 83 + 78 84 void bpf_jit_realloc_regs(struct codegen_context *ctx) 79 85 { 80 - if (ctx->seen & SEEN_FUNC) 81 - return; 86 + unsigned int nvreg_mask; 82 87 83 - while (ctx->seen & SEEN_NVREG_MASK && 88 + if (ctx->seen & SEEN_FUNC) 89 + nvreg_mask = SEEN_NVREG_TEMP_MASK; 90 + else 91 + nvreg_mask = SEEN_NVREG_FULL_MASK; 92 + 93 + while (ctx->seen & nvreg_mask && 84 94 (ctx->seen & SEEN_VREG_MASK) != SEEN_VREG_MASK) { 85 - int old = 32 - fls(ctx->seen & (SEEN_NVREG_MASK & 0xaaaaaaab)); 95 + int old = 32 - fls(ctx->seen & (nvreg_mask & 0xaaaaaaab)); 86 96 int new = 32 - fls(~ctx->seen & (SEEN_VREG_MASK & 0xaaaaaaaa)); 87 97 int i; 88 98 ··· 114 108 int i; 115 109 116 110 /* First arg comes in as a 32 bits pointer. */ 117 - EMIT(PPC_RAW_MR(bpf_to_ppc(ctx, BPF_REG_1), _R3)); 118 - EMIT(PPC_RAW_LI(bpf_to_ppc(ctx, BPF_REG_1) - 1, 0)); 111 + EMIT(PPC_RAW_MR(bpf_to_ppc(BPF_REG_1), _R3)); 112 + EMIT(PPC_RAW_LI(bpf_to_ppc(BPF_REG_1) - 1, 0)); 119 113 EMIT(PPC_RAW_STWU(_R1, _R1, -BPF_PPC_STACKFRAME(ctx))); 120 114 121 115 /* ··· 124 118 * invoked through a tail call. 125 119 */ 126 120 if (ctx->seen & SEEN_TAILCALL) 127 - EMIT(PPC_RAW_STW(bpf_to_ppc(ctx, BPF_REG_1) - 1, _R1, 121 + EMIT(PPC_RAW_STW(bpf_to_ppc(BPF_REG_1) - 1, _R1, 128 122 bpf_jit_stack_offsetof(ctx, BPF_PPC_TC))); 129 123 else 130 124 EMIT(PPC_RAW_NOP()); ··· 146 140 EMIT(PPC_RAW_STW(i, _R1, bpf_jit_stack_offsetof(ctx, i))); 147 141 148 142 /* If needed retrieve arguments 9 and 10, ie 5th 64 bits arg.*/ 149 - if (bpf_is_seen_register(ctx, bpf_to_ppc(ctx, BPF_REG_5))) { 150 - EMIT(PPC_RAW_LWZ(bpf_to_ppc(ctx, BPF_REG_5) - 1, _R1, BPF_PPC_STACKFRAME(ctx)) + 8); 151 - EMIT(PPC_RAW_LWZ(bpf_to_ppc(ctx, BPF_REG_5), _R1, BPF_PPC_STACKFRAME(ctx)) + 12); 143 + if (bpf_is_seen_register(ctx, bpf_to_ppc(BPF_REG_5))) { 144 + EMIT(PPC_RAW_LWZ(bpf_to_ppc(BPF_REG_5) - 1, _R1, BPF_PPC_STACKFRAME(ctx)) + 8); 145 + EMIT(PPC_RAW_LWZ(bpf_to_ppc(BPF_REG_5), _R1, BPF_PPC_STACKFRAME(ctx)) + 12); 152 146 } 153 147 154 148 /* Setup frame pointer to point to the bpf stack area */ 155 - if (bpf_is_seen_register(ctx, bpf_to_ppc(ctx, BPF_REG_FP))) { 156 - EMIT(PPC_RAW_LI(bpf_to_ppc(ctx, BPF_REG_FP) - 1, 0)); 157 - EMIT(PPC_RAW_ADDI(bpf_to_ppc(ctx, BPF_REG_FP), _R1, 149 + if (bpf_is_seen_register(ctx, bpf_to_ppc(BPF_REG_FP))) { 150 + EMIT(PPC_RAW_LI(bpf_to_ppc(BPF_REG_FP) - 1, 0)); 151 + EMIT(PPC_RAW_ADDI(bpf_to_ppc(BPF_REG_FP), _R1, 158 152 STACK_FRAME_MIN_SIZE + ctx->stack_size)); 159 153 } 160 154 ··· 174 168 175 169 void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx) 176 170 { 177 - EMIT(PPC_RAW_MR(_R3, bpf_to_ppc(ctx, BPF_REG_0))); 171 + EMIT(PPC_RAW_MR(_R3, bpf_to_ppc(BPF_REG_0))); 178 172 179 173 bpf_jit_emit_common_epilogue(image, ctx); 180 174 ··· 191 185 EMIT(PPC_RAW_BLR()); 192 186 } 193 187 194 - void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func) 188 + int bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func) 195 189 { 196 190 s32 rel = (s32)func - (s32)(image + ctx->idx); 197 191 198 192 if (image && rel < 0x2000000 && rel >= -0x2000000) { 199 - PPC_BL_ABS(func); 193 + PPC_BL(func); 200 194 EMIT(PPC_RAW_NOP()); 201 195 EMIT(PPC_RAW_NOP()); 202 196 EMIT(PPC_RAW_NOP()); ··· 207 201 EMIT(PPC_RAW_MTCTR(_R0)); 208 202 EMIT(PPC_RAW_BCTRL()); 209 203 } 204 + 205 + return 0; 210 206 } 211 207 212 208 static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out) ··· 219 211 * r5-r6/BPF_REG_2 - pointer to bpf_array 220 212 * r7-r8/BPF_REG_3 - index in bpf_array 221 213 */ 222 - int b2p_bpf_array = bpf_to_ppc(ctx, BPF_REG_2); 223 - int b2p_index = bpf_to_ppc(ctx, BPF_REG_3); 214 + int b2p_bpf_array = bpf_to_ppc(BPF_REG_2); 215 + int b2p_index = bpf_to_ppc(BPF_REG_3); 224 216 225 217 /* 226 218 * if (index >= array->map.max_entries) ··· 229 221 EMIT(PPC_RAW_LWZ(_R0, b2p_bpf_array, offsetof(struct bpf_array, map.max_entries))); 230 222 EMIT(PPC_RAW_CMPLW(b2p_index, _R0)); 231 223 EMIT(PPC_RAW_LWZ(_R0, _R1, bpf_jit_stack_offsetof(ctx, BPF_PPC_TC))); 232 - PPC_BCC(COND_GE, out); 224 + PPC_BCC_SHORT(COND_GE, out); 233 225 234 226 /* 235 227 * if (tail_call_cnt >= MAX_TAIL_CALL_CNT) ··· 238 230 EMIT(PPC_RAW_CMPLWI(_R0, MAX_TAIL_CALL_CNT)); 239 231 /* tail_call_cnt++; */ 240 232 EMIT(PPC_RAW_ADDIC(_R0, _R0, 1)); 241 - PPC_BCC(COND_GE, out); 233 + PPC_BCC_SHORT(COND_GE, out); 242 234 243 235 /* prog = array->ptrs[index]; */ 244 236 EMIT(PPC_RAW_RLWINM(_R3, b2p_index, 2, 0, 29)); ··· 251 243 * goto out; 252 244 */ 253 245 EMIT(PPC_RAW_CMPLWI(_R3, 0)); 254 - PPC_BCC(COND_EQ, out); 246 + PPC_BCC_SHORT(COND_EQ, out); 255 247 256 248 /* goto *(prog->bpf_func + prologue_size); */ 257 249 EMIT(PPC_RAW_LWZ(_R3, _R3, offsetof(struct bpf_prog, bpf_func))); ··· 266 258 267 259 EMIT(PPC_RAW_MTCTR(_R3)); 268 260 269 - EMIT(PPC_RAW_MR(_R3, bpf_to_ppc(ctx, BPF_REG_1))); 261 + EMIT(PPC_RAW_MR(_R3, bpf_to_ppc(BPF_REG_1))); 270 262 271 263 /* tear restore NVRs, ... */ 272 264 bpf_jit_emit_common_epilogue(image, ctx); ··· 290 282 291 283 for (i = 0; i < flen; i++) { 292 284 u32 code = insn[i].code; 293 - u32 dst_reg = bpf_to_ppc(ctx, insn[i].dst_reg); 285 + u32 dst_reg = bpf_to_ppc(insn[i].dst_reg); 294 286 u32 dst_reg_h = dst_reg - 1; 295 - u32 src_reg = bpf_to_ppc(ctx, insn[i].src_reg); 287 + u32 src_reg = bpf_to_ppc(insn[i].src_reg); 296 288 u32 src_reg_h = src_reg - 1; 297 - u32 tmp_reg = bpf_to_ppc(ctx, TMP_REG); 289 + u32 tmp_reg = bpf_to_ppc(TMP_REG); 298 290 u32 size = BPF_SIZE(code); 299 291 s16 off = insn[i].off; 300 292 s32 imm = insn[i].imm; ··· 842 834 if (BPF_MODE(code) == BPF_PROBE_MEM) { 843 835 PPC_LI32(_R0, TASK_SIZE - off); 844 836 EMIT(PPC_RAW_CMPLW(src_reg, _R0)); 845 - PPC_BCC(COND_GT, (ctx->idx + 5) * 4); 837 + PPC_BCC_SHORT(COND_GT, (ctx->idx + 4) * 4); 846 838 EMIT(PPC_RAW_LI(dst_reg, 0)); 847 839 /* 848 840 * For BPF_DW case, "li reg_h,0" would be needed when ··· 937 929 * the epilogue. If we _are_ the last instruction, 938 930 * we'll just fall through to the epilogue. 939 931 */ 940 - if (i != flen - 1) 941 - PPC_JMP(exit_addr); 932 + if (i != flen - 1) { 933 + ret = bpf_jit_emit_exit_insn(image, ctx, _R0, exit_addr); 934 + if (ret) 935 + return ret; 936 + } 942 937 /* else fall through to the epilogue */ 943 938 break; 944 939 ··· 956 945 if (ret < 0) 957 946 return ret; 958 947 959 - if (bpf_is_seen_register(ctx, bpf_to_ppc(ctx, BPF_REG_5))) { 960 - EMIT(PPC_RAW_STW(bpf_to_ppc(ctx, BPF_REG_5) - 1, _R1, 8)); 961 - EMIT(PPC_RAW_STW(bpf_to_ppc(ctx, BPF_REG_5), _R1, 12)); 948 + if (bpf_is_seen_register(ctx, bpf_to_ppc(BPF_REG_5))) { 949 + EMIT(PPC_RAW_STW(bpf_to_ppc(BPF_REG_5) - 1, _R1, 8)); 950 + EMIT(PPC_RAW_STW(bpf_to_ppc(BPF_REG_5), _R1, 12)); 962 951 } 963 952 964 - bpf_jit_emit_func_call_rel(image, ctx, func_addr); 953 + ret = bpf_jit_emit_func_call_rel(image, ctx, func_addr); 954 + if (ret) 955 + return ret; 965 956 966 - EMIT(PPC_RAW_MR(bpf_to_ppc(ctx, BPF_REG_0) - 1, _R3)); 967 - EMIT(PPC_RAW_MR(bpf_to_ppc(ctx, BPF_REG_0), _R4)); 957 + EMIT(PPC_RAW_MR(bpf_to_ppc(BPF_REG_0) - 1, _R3)); 958 + EMIT(PPC_RAW_MR(bpf_to_ppc(BPF_REG_0), _R4)); 968 959 break; 969 960 970 961 /*
+238 -202
arch/powerpc/net/bpf_jit_comp64.c
··· 17 17 #include <linux/bpf.h> 18 18 #include <asm/security_features.h> 19 19 20 - #include "bpf_jit64.h" 20 + #include "bpf_jit.h" 21 + 22 + /* 23 + * Stack layout: 24 + * Ensure the top half (upto local_tmp_var) stays consistent 25 + * with our redzone usage. 26 + * 27 + * [ prev sp ] <------------- 28 + * [ nv gpr save area ] 5*8 | 29 + * [ tail_call_cnt ] 8 | 30 + * [ local_tmp_var ] 16 | 31 + * fp (r31) --> [ ebpf stack space ] upto 512 | 32 + * [ frame header ] 32/112 | 33 + * sp (r1) ---> [ stack pointer ] -------------- 34 + */ 35 + 36 + /* for gpr non volatile registers BPG_REG_6 to 10 */ 37 + #define BPF_PPC_STACK_SAVE (5*8) 38 + /* for bpf JIT code internal usage */ 39 + #define BPF_PPC_STACK_LOCALS 24 40 + /* stack frame excluding BPF stack, ensure this is quadword aligned */ 41 + #define BPF_PPC_STACKFRAME (STACK_FRAME_MIN_SIZE + \ 42 + BPF_PPC_STACK_LOCALS + BPF_PPC_STACK_SAVE) 43 + 44 + /* BPF register usage */ 45 + #define TMP_REG_1 (MAX_BPF_JIT_REG + 0) 46 + #define TMP_REG_2 (MAX_BPF_JIT_REG + 1) 47 + 48 + /* BPF to ppc register mappings */ 49 + void bpf_jit_init_reg_mapping(struct codegen_context *ctx) 50 + { 51 + /* function return value */ 52 + ctx->b2p[BPF_REG_0] = _R8; 53 + /* function arguments */ 54 + ctx->b2p[BPF_REG_1] = _R3; 55 + ctx->b2p[BPF_REG_2] = _R4; 56 + ctx->b2p[BPF_REG_3] = _R5; 57 + ctx->b2p[BPF_REG_4] = _R6; 58 + ctx->b2p[BPF_REG_5] = _R7; 59 + /* non volatile registers */ 60 + ctx->b2p[BPF_REG_6] = _R27; 61 + ctx->b2p[BPF_REG_7] = _R28; 62 + ctx->b2p[BPF_REG_8] = _R29; 63 + ctx->b2p[BPF_REG_9] = _R30; 64 + /* frame pointer aka BPF_REG_10 */ 65 + ctx->b2p[BPF_REG_FP] = _R31; 66 + /* eBPF jit internal registers */ 67 + ctx->b2p[BPF_REG_AX] = _R12; 68 + ctx->b2p[TMP_REG_1] = _R9; 69 + ctx->b2p[TMP_REG_2] = _R10; 70 + } 71 + 72 + /* PPC NVR range -- update this if we ever use NVRs below r27 */ 73 + #define BPF_PPC_NVR_MIN _R27 21 74 22 75 static inline bool bpf_has_stack_frame(struct codegen_context *ctx) 23 76 { ··· 80 27 * - the bpf program uses its stack area 81 28 * The latter condition is deduced from the usage of BPF_REG_FP 82 29 */ 83 - return ctx->seen & SEEN_FUNC || bpf_is_seen_register(ctx, b2p[BPF_REG_FP]); 30 + return ctx->seen & SEEN_FUNC || bpf_is_seen_register(ctx, bpf_to_ppc(BPF_REG_FP)); 84 31 } 85 32 86 33 /* ··· 126 73 { 127 74 int i; 128 75 76 + if (__is_defined(PPC64_ELF_ABI_v2)) 77 + EMIT(PPC_RAW_LD(_R2, _R13, offsetof(struct paca_struct, kernel_toc))); 78 + 129 79 /* 130 80 * Initialize tail_call_cnt if we do tail calls. 131 81 * Otherwise, put in NOPs so that it can be skipped when we are 132 82 * invoked through a tail call. 133 83 */ 134 84 if (ctx->seen & SEEN_TAILCALL) { 135 - EMIT(PPC_RAW_LI(b2p[TMP_REG_1], 0)); 85 + EMIT(PPC_RAW_LI(bpf_to_ppc(TMP_REG_1), 0)); 136 86 /* this goes in the redzone */ 137 - PPC_BPF_STL(b2p[TMP_REG_1], 1, -(BPF_PPC_STACK_SAVE + 8)); 87 + EMIT(PPC_RAW_STD(bpf_to_ppc(TMP_REG_1), _R1, -(BPF_PPC_STACK_SAVE + 8))); 138 88 } else { 139 89 EMIT(PPC_RAW_NOP()); 140 90 EMIT(PPC_RAW_NOP()); 141 91 } 142 - 143 - #define BPF_TAILCALL_PROLOGUE_SIZE 8 144 92 145 93 if (bpf_has_stack_frame(ctx)) { 146 94 /* ··· 150 96 */ 151 97 if (ctx->seen & SEEN_FUNC) { 152 98 EMIT(PPC_RAW_MFLR(_R0)); 153 - PPC_BPF_STL(0, 1, PPC_LR_STKOFF); 99 + EMIT(PPC_RAW_STD(_R0, _R1, PPC_LR_STKOFF)); 154 100 } 155 101 156 - PPC_BPF_STLU(1, 1, -(BPF_PPC_STACKFRAME + ctx->stack_size)); 102 + EMIT(PPC_RAW_STDU(_R1, _R1, -(BPF_PPC_STACKFRAME + ctx->stack_size))); 157 103 } 158 104 159 105 /* ··· 162 108 * in the protected zone below the previous stack frame 163 109 */ 164 110 for (i = BPF_REG_6; i <= BPF_REG_10; i++) 165 - if (bpf_is_seen_register(ctx, b2p[i])) 166 - PPC_BPF_STL(b2p[i], 1, bpf_jit_stack_offsetof(ctx, b2p[i])); 111 + if (bpf_is_seen_register(ctx, bpf_to_ppc(i))) 112 + EMIT(PPC_RAW_STD(bpf_to_ppc(i), _R1, bpf_jit_stack_offsetof(ctx, bpf_to_ppc(i)))); 167 113 168 114 /* Setup frame pointer to point to the bpf stack area */ 169 - if (bpf_is_seen_register(ctx, b2p[BPF_REG_FP])) 170 - EMIT(PPC_RAW_ADDI(b2p[BPF_REG_FP], 1, 115 + if (bpf_is_seen_register(ctx, bpf_to_ppc(BPF_REG_FP))) 116 + EMIT(PPC_RAW_ADDI(bpf_to_ppc(BPF_REG_FP), _R1, 171 117 STACK_FRAME_MIN_SIZE + ctx->stack_size)); 172 118 } 173 119 ··· 177 123 178 124 /* Restore NVRs */ 179 125 for (i = BPF_REG_6; i <= BPF_REG_10; i++) 180 - if (bpf_is_seen_register(ctx, b2p[i])) 181 - PPC_BPF_LL(b2p[i], 1, bpf_jit_stack_offsetof(ctx, b2p[i])); 126 + if (bpf_is_seen_register(ctx, bpf_to_ppc(i))) 127 + EMIT(PPC_RAW_LD(bpf_to_ppc(i), _R1, bpf_jit_stack_offsetof(ctx, bpf_to_ppc(i)))); 182 128 183 129 /* Tear down our stack frame */ 184 130 if (bpf_has_stack_frame(ctx)) { 185 - EMIT(PPC_RAW_ADDI(1, 1, BPF_PPC_STACKFRAME + ctx->stack_size)); 131 + EMIT(PPC_RAW_ADDI(_R1, _R1, BPF_PPC_STACKFRAME + ctx->stack_size)); 186 132 if (ctx->seen & SEEN_FUNC) { 187 - PPC_BPF_LL(0, 1, PPC_LR_STKOFF); 188 - EMIT(PPC_RAW_MTLR(0)); 133 + EMIT(PPC_RAW_LD(_R0, _R1, PPC_LR_STKOFF)); 134 + EMIT(PPC_RAW_MTLR(_R0)); 189 135 } 190 136 } 191 137 } ··· 195 141 bpf_jit_emit_common_epilogue(image, ctx); 196 142 197 143 /* Move result to r3 */ 198 - EMIT(PPC_RAW_MR(3, b2p[BPF_REG_0])); 144 + EMIT(PPC_RAW_MR(_R3, bpf_to_ppc(BPF_REG_0))); 199 145 200 146 EMIT(PPC_RAW_BLR()); 201 147 } 202 148 203 - static void bpf_jit_emit_func_call_hlp(u32 *image, struct codegen_context *ctx, 204 - u64 func) 149 + static int bpf_jit_emit_func_call_hlp(u32 *image, struct codegen_context *ctx, u64 func) 205 150 { 206 - #ifdef PPC64_ELF_ABI_v1 207 - /* func points to the function descriptor */ 208 - PPC_LI64(b2p[TMP_REG_2], func); 209 - /* Load actual entry point from function descriptor */ 210 - PPC_BPF_LL(b2p[TMP_REG_1], b2p[TMP_REG_2], 0); 211 - /* ... and move it to CTR */ 212 - EMIT(PPC_RAW_MTCTR(b2p[TMP_REG_1])); 213 - /* 214 - * Load TOC from function descriptor at offset 8. 215 - * We can clobber r2 since we get called through a 216 - * function pointer (so caller will save/restore r2) 217 - * and since we don't use a TOC ourself. 218 - */ 219 - PPC_BPF_LL(2, b2p[TMP_REG_2], 8); 220 - #else 221 - /* We can clobber r12 */ 222 - PPC_FUNC_ADDR(12, func); 223 - EMIT(PPC_RAW_MTCTR(12)); 224 - #endif 151 + unsigned long func_addr = func ? ppc_function_entry((void *)func) : 0; 152 + long reladdr; 153 + 154 + if (WARN_ON_ONCE(!core_kernel_text(func_addr))) 155 + return -EINVAL; 156 + 157 + reladdr = func_addr - kernel_toc_addr(); 158 + if (reladdr > 0x7FFFFFFF || reladdr < -(0x80000000L)) { 159 + pr_err("eBPF: address of %ps out of range of kernel_toc.\n", (void *)func); 160 + return -ERANGE; 161 + } 162 + 163 + EMIT(PPC_RAW_ADDIS(_R12, _R2, PPC_HA(reladdr))); 164 + EMIT(PPC_RAW_ADDI(_R12, _R12, PPC_LO(reladdr))); 165 + EMIT(PPC_RAW_MTCTR(_R12)); 225 166 EMIT(PPC_RAW_BCTRL()); 167 + 168 + return 0; 226 169 } 227 170 228 - void bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func) 171 + int bpf_jit_emit_func_call_rel(u32 *image, struct codegen_context *ctx, u64 func) 229 172 { 230 173 unsigned int i, ctx_idx = ctx->idx; 231 174 175 + if (WARN_ON_ONCE(func && is_module_text_address(func))) 176 + return -EINVAL; 177 + 178 + /* skip past descriptor if elf v1 */ 179 + func += FUNCTION_DESCR_SIZE; 180 + 232 181 /* Load function address into r12 */ 233 - PPC_LI64(12, func); 182 + PPC_LI64(_R12, func); 234 183 235 184 /* For bpf-to-bpf function calls, the callee's address is unknown 236 185 * until the last extra pass. As seen above, we use PPC_LI64() to ··· 248 191 for (i = ctx->idx - ctx_idx; i < 5; i++) 249 192 EMIT(PPC_RAW_NOP()); 250 193 251 - #ifdef PPC64_ELF_ABI_v1 252 - /* 253 - * Load TOC from function descriptor at offset 8. 254 - * We can clobber r2 since we get called through a 255 - * function pointer (so caller will save/restore r2) 256 - * and since we don't use a TOC ourself. 257 - */ 258 - PPC_BPF_LL(2, 12, 8); 259 - /* Load actual entry point from function descriptor */ 260 - PPC_BPF_LL(12, 12, 0); 261 - #endif 262 - 263 - EMIT(PPC_RAW_MTCTR(12)); 194 + EMIT(PPC_RAW_MTCTR(_R12)); 264 195 EMIT(PPC_RAW_BCTRL()); 196 + 197 + return 0; 265 198 } 266 199 267 200 static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out) ··· 262 215 * r4/BPF_REG_2 - pointer to bpf_array 263 216 * r5/BPF_REG_3 - index in bpf_array 264 217 */ 265 - int b2p_bpf_array = b2p[BPF_REG_2]; 266 - int b2p_index = b2p[BPF_REG_3]; 218 + int b2p_bpf_array = bpf_to_ppc(BPF_REG_2); 219 + int b2p_index = bpf_to_ppc(BPF_REG_3); 220 + int bpf_tailcall_prologue_size = 8; 221 + 222 + if (__is_defined(PPC64_ELF_ABI_v2)) 223 + bpf_tailcall_prologue_size += 4; /* skip past the toc load */ 267 224 268 225 /* 269 226 * if (index >= array->map.max_entries) 270 227 * goto out; 271 228 */ 272 - EMIT(PPC_RAW_LWZ(b2p[TMP_REG_1], b2p_bpf_array, offsetof(struct bpf_array, map.max_entries))); 229 + EMIT(PPC_RAW_LWZ(bpf_to_ppc(TMP_REG_1), b2p_bpf_array, offsetof(struct bpf_array, map.max_entries))); 273 230 EMIT(PPC_RAW_RLWINM(b2p_index, b2p_index, 0, 0, 31)); 274 - EMIT(PPC_RAW_CMPLW(b2p_index, b2p[TMP_REG_1])); 275 - PPC_BCC(COND_GE, out); 231 + EMIT(PPC_RAW_CMPLW(b2p_index, bpf_to_ppc(TMP_REG_1))); 232 + PPC_BCC_SHORT(COND_GE, out); 276 233 277 234 /* 278 235 * if (tail_call_cnt >= MAX_TAIL_CALL_CNT) 279 236 * goto out; 280 237 */ 281 - PPC_BPF_LL(b2p[TMP_REG_1], 1, bpf_jit_stack_tailcallcnt(ctx)); 282 - EMIT(PPC_RAW_CMPLWI(b2p[TMP_REG_1], MAX_TAIL_CALL_CNT)); 283 - PPC_BCC(COND_GE, out); 238 + EMIT(PPC_RAW_LD(bpf_to_ppc(TMP_REG_1), _R1, bpf_jit_stack_tailcallcnt(ctx))); 239 + EMIT(PPC_RAW_CMPLWI(bpf_to_ppc(TMP_REG_1), MAX_TAIL_CALL_CNT)); 240 + PPC_BCC_SHORT(COND_GE, out); 284 241 285 242 /* 286 243 * tail_call_cnt++; 287 244 */ 288 - EMIT(PPC_RAW_ADDI(b2p[TMP_REG_1], b2p[TMP_REG_1], 1)); 289 - PPC_BPF_STL(b2p[TMP_REG_1], 1, bpf_jit_stack_tailcallcnt(ctx)); 245 + EMIT(PPC_RAW_ADDI(bpf_to_ppc(TMP_REG_1), bpf_to_ppc(TMP_REG_1), 1)); 246 + EMIT(PPC_RAW_STD(bpf_to_ppc(TMP_REG_1), _R1, bpf_jit_stack_tailcallcnt(ctx))); 290 247 291 248 /* prog = array->ptrs[index]; */ 292 - EMIT(PPC_RAW_MULI(b2p[TMP_REG_1], b2p_index, 8)); 293 - EMIT(PPC_RAW_ADD(b2p[TMP_REG_1], b2p[TMP_REG_1], b2p_bpf_array)); 294 - PPC_BPF_LL(b2p[TMP_REG_1], b2p[TMP_REG_1], offsetof(struct bpf_array, ptrs)); 249 + EMIT(PPC_RAW_MULI(bpf_to_ppc(TMP_REG_1), b2p_index, 8)); 250 + EMIT(PPC_RAW_ADD(bpf_to_ppc(TMP_REG_1), bpf_to_ppc(TMP_REG_1), b2p_bpf_array)); 251 + EMIT(PPC_RAW_LD(bpf_to_ppc(TMP_REG_1), bpf_to_ppc(TMP_REG_1), offsetof(struct bpf_array, ptrs))); 295 252 296 253 /* 297 254 * if (prog == NULL) 298 255 * goto out; 299 256 */ 300 - EMIT(PPC_RAW_CMPLDI(b2p[TMP_REG_1], 0)); 301 - PPC_BCC(COND_EQ, out); 257 + EMIT(PPC_RAW_CMPLDI(bpf_to_ppc(TMP_REG_1), 0)); 258 + PPC_BCC_SHORT(COND_EQ, out); 302 259 303 260 /* goto *(prog->bpf_func + prologue_size); */ 304 - PPC_BPF_LL(b2p[TMP_REG_1], b2p[TMP_REG_1], offsetof(struct bpf_prog, bpf_func)); 305 - #ifdef PPC64_ELF_ABI_v1 306 - /* skip past the function descriptor */ 307 - EMIT(PPC_RAW_ADDI(b2p[TMP_REG_1], b2p[TMP_REG_1], 308 - FUNCTION_DESCR_SIZE + BPF_TAILCALL_PROLOGUE_SIZE)); 309 - #else 310 - EMIT(PPC_RAW_ADDI(b2p[TMP_REG_1], b2p[TMP_REG_1], BPF_TAILCALL_PROLOGUE_SIZE)); 311 - #endif 312 - EMIT(PPC_RAW_MTCTR(b2p[TMP_REG_1])); 261 + EMIT(PPC_RAW_LD(bpf_to_ppc(TMP_REG_1), bpf_to_ppc(TMP_REG_1), offsetof(struct bpf_prog, bpf_func))); 262 + EMIT(PPC_RAW_ADDI(bpf_to_ppc(TMP_REG_1), bpf_to_ppc(TMP_REG_1), 263 + FUNCTION_DESCR_SIZE + bpf_tailcall_prologue_size)); 264 + EMIT(PPC_RAW_MTCTR(bpf_to_ppc(TMP_REG_1))); 313 265 314 266 /* tear down stack, restore NVRs, ... */ 315 267 bpf_jit_emit_common_epilogue(image, ctx); ··· 355 309 356 310 for (i = 0; i < flen; i++) { 357 311 u32 code = insn[i].code; 358 - u32 dst_reg = b2p[insn[i].dst_reg]; 359 - u32 src_reg = b2p[insn[i].src_reg]; 312 + u32 dst_reg = bpf_to_ppc(insn[i].dst_reg); 313 + u32 src_reg = bpf_to_ppc(insn[i].src_reg); 360 314 u32 size = BPF_SIZE(code); 315 + u32 tmp1_reg = bpf_to_ppc(TMP_REG_1); 316 + u32 tmp2_reg = bpf_to_ppc(TMP_REG_2); 361 317 s16 off = insn[i].off; 362 318 s32 imm = insn[i].imm; 363 319 bool func_addr_fixed; ··· 410 362 } else if (imm >= -32768 && imm < 32768) { 411 363 EMIT(PPC_RAW_ADDI(dst_reg, dst_reg, IMM_L(imm))); 412 364 } else { 413 - PPC_LI32(b2p[TMP_REG_1], imm); 414 - EMIT(PPC_RAW_ADD(dst_reg, dst_reg, b2p[TMP_REG_1])); 365 + PPC_LI32(tmp1_reg, imm); 366 + EMIT(PPC_RAW_ADD(dst_reg, dst_reg, tmp1_reg)); 415 367 } 416 368 goto bpf_alu32_trunc; 417 369 case BPF_ALU | BPF_SUB | BPF_K: /* (u32) dst -= (u32) imm */ ··· 421 373 } else if (imm > -32768 && imm <= 32768) { 422 374 EMIT(PPC_RAW_ADDI(dst_reg, dst_reg, IMM_L(-imm))); 423 375 } else { 424 - PPC_LI32(b2p[TMP_REG_1], imm); 425 - EMIT(PPC_RAW_SUB(dst_reg, dst_reg, b2p[TMP_REG_1])); 376 + PPC_LI32(tmp1_reg, imm); 377 + EMIT(PPC_RAW_SUB(dst_reg, dst_reg, tmp1_reg)); 426 378 } 427 379 goto bpf_alu32_trunc; 428 380 case BPF_ALU | BPF_MUL | BPF_X: /* (u32) dst *= (u32) src */ ··· 437 389 if (imm >= -32768 && imm < 32768) 438 390 EMIT(PPC_RAW_MULI(dst_reg, dst_reg, IMM_L(imm))); 439 391 else { 440 - PPC_LI32(b2p[TMP_REG_1], imm); 392 + PPC_LI32(tmp1_reg, imm); 441 393 if (BPF_CLASS(code) == BPF_ALU) 442 - EMIT(PPC_RAW_MULW(dst_reg, dst_reg, 443 - b2p[TMP_REG_1])); 394 + EMIT(PPC_RAW_MULW(dst_reg, dst_reg, tmp1_reg)); 444 395 else 445 - EMIT(PPC_RAW_MULD(dst_reg, dst_reg, 446 - b2p[TMP_REG_1])); 396 + EMIT(PPC_RAW_MULD(dst_reg, dst_reg, tmp1_reg)); 447 397 } 448 398 goto bpf_alu32_trunc; 449 399 case BPF_ALU | BPF_DIV | BPF_X: /* (u32) dst /= (u32) src */ 450 400 case BPF_ALU | BPF_MOD | BPF_X: /* (u32) dst %= (u32) src */ 451 401 if (BPF_OP(code) == BPF_MOD) { 452 - EMIT(PPC_RAW_DIVWU(b2p[TMP_REG_1], dst_reg, src_reg)); 453 - EMIT(PPC_RAW_MULW(b2p[TMP_REG_1], src_reg, 454 - b2p[TMP_REG_1])); 455 - EMIT(PPC_RAW_SUB(dst_reg, dst_reg, b2p[TMP_REG_1])); 402 + EMIT(PPC_RAW_DIVWU(tmp1_reg, dst_reg, src_reg)); 403 + EMIT(PPC_RAW_MULW(tmp1_reg, src_reg, tmp1_reg)); 404 + EMIT(PPC_RAW_SUB(dst_reg, dst_reg, tmp1_reg)); 456 405 } else 457 406 EMIT(PPC_RAW_DIVWU(dst_reg, dst_reg, src_reg)); 458 407 goto bpf_alu32_trunc; 459 408 case BPF_ALU64 | BPF_DIV | BPF_X: /* dst /= src */ 460 409 case BPF_ALU64 | BPF_MOD | BPF_X: /* dst %= src */ 461 410 if (BPF_OP(code) == BPF_MOD) { 462 - EMIT(PPC_RAW_DIVDU(b2p[TMP_REG_1], dst_reg, src_reg)); 463 - EMIT(PPC_RAW_MULD(b2p[TMP_REG_1], src_reg, 464 - b2p[TMP_REG_1])); 465 - EMIT(PPC_RAW_SUB(dst_reg, dst_reg, b2p[TMP_REG_1])); 411 + EMIT(PPC_RAW_DIVDU(tmp1_reg, dst_reg, src_reg)); 412 + EMIT(PPC_RAW_MULD(tmp1_reg, src_reg, tmp1_reg)); 413 + EMIT(PPC_RAW_SUB(dst_reg, dst_reg, tmp1_reg)); 466 414 } else 467 415 EMIT(PPC_RAW_DIVDU(dst_reg, dst_reg, src_reg)); 468 416 break; ··· 477 433 } 478 434 } 479 435 480 - PPC_LI32(b2p[TMP_REG_1], imm); 436 + PPC_LI32(tmp1_reg, imm); 481 437 switch (BPF_CLASS(code)) { 482 438 case BPF_ALU: 483 439 if (BPF_OP(code) == BPF_MOD) { 484 - EMIT(PPC_RAW_DIVWU(b2p[TMP_REG_2], 485 - dst_reg, 486 - b2p[TMP_REG_1])); 487 - EMIT(PPC_RAW_MULW(b2p[TMP_REG_1], 488 - b2p[TMP_REG_1], 489 - b2p[TMP_REG_2])); 490 - EMIT(PPC_RAW_SUB(dst_reg, dst_reg, 491 - b2p[TMP_REG_1])); 440 + EMIT(PPC_RAW_DIVWU(tmp2_reg, dst_reg, tmp1_reg)); 441 + EMIT(PPC_RAW_MULW(tmp1_reg, tmp1_reg, tmp2_reg)); 442 + EMIT(PPC_RAW_SUB(dst_reg, dst_reg, tmp1_reg)); 492 443 } else 493 - EMIT(PPC_RAW_DIVWU(dst_reg, dst_reg, 494 - b2p[TMP_REG_1])); 444 + EMIT(PPC_RAW_DIVWU(dst_reg, dst_reg, tmp1_reg)); 495 445 break; 496 446 case BPF_ALU64: 497 447 if (BPF_OP(code) == BPF_MOD) { 498 - EMIT(PPC_RAW_DIVDU(b2p[TMP_REG_2], 499 - dst_reg, 500 - b2p[TMP_REG_1])); 501 - EMIT(PPC_RAW_MULD(b2p[TMP_REG_1], 502 - b2p[TMP_REG_1], 503 - b2p[TMP_REG_2])); 504 - EMIT(PPC_RAW_SUB(dst_reg, dst_reg, 505 - b2p[TMP_REG_1])); 448 + EMIT(PPC_RAW_DIVDU(tmp2_reg, dst_reg, tmp1_reg)); 449 + EMIT(PPC_RAW_MULD(tmp1_reg, tmp1_reg, tmp2_reg)); 450 + EMIT(PPC_RAW_SUB(dst_reg, dst_reg, tmp1_reg)); 506 451 } else 507 - EMIT(PPC_RAW_DIVDU(dst_reg, dst_reg, 508 - b2p[TMP_REG_1])); 452 + EMIT(PPC_RAW_DIVDU(dst_reg, dst_reg, tmp1_reg)); 509 453 break; 510 454 } 511 455 goto bpf_alu32_trunc; ··· 515 483 EMIT(PPC_RAW_ANDI(dst_reg, dst_reg, IMM_L(imm))); 516 484 else { 517 485 /* Sign-extended */ 518 - PPC_LI32(b2p[TMP_REG_1], imm); 519 - EMIT(PPC_RAW_AND(dst_reg, dst_reg, b2p[TMP_REG_1])); 486 + PPC_LI32(tmp1_reg, imm); 487 + EMIT(PPC_RAW_AND(dst_reg, dst_reg, tmp1_reg)); 520 488 } 521 489 goto bpf_alu32_trunc; 522 490 case BPF_ALU | BPF_OR | BPF_X: /* dst = (u32) dst | (u32) src */ ··· 527 495 case BPF_ALU64 | BPF_OR | BPF_K:/* dst = dst | imm */ 528 496 if (imm < 0 && BPF_CLASS(code) == BPF_ALU64) { 529 497 /* Sign-extended */ 530 - PPC_LI32(b2p[TMP_REG_1], imm); 531 - EMIT(PPC_RAW_OR(dst_reg, dst_reg, b2p[TMP_REG_1])); 498 + PPC_LI32(tmp1_reg, imm); 499 + EMIT(PPC_RAW_OR(dst_reg, dst_reg, tmp1_reg)); 532 500 } else { 533 501 if (IMM_L(imm)) 534 502 EMIT(PPC_RAW_ORI(dst_reg, dst_reg, IMM_L(imm))); ··· 544 512 case BPF_ALU64 | BPF_XOR | BPF_K: /* dst ^= imm */ 545 513 if (imm < 0 && BPF_CLASS(code) == BPF_ALU64) { 546 514 /* Sign-extended */ 547 - PPC_LI32(b2p[TMP_REG_1], imm); 548 - EMIT(PPC_RAW_XOR(dst_reg, dst_reg, b2p[TMP_REG_1])); 515 + PPC_LI32(tmp1_reg, imm); 516 + EMIT(PPC_RAW_XOR(dst_reg, dst_reg, tmp1_reg)); 549 517 } else { 550 518 if (IMM_L(imm)) 551 519 EMIT(PPC_RAW_XORI(dst_reg, dst_reg, IMM_L(imm))); ··· 646 614 switch (imm) { 647 615 case 16: 648 616 /* Rotate 8 bits left & mask with 0x0000ff00 */ 649 - EMIT(PPC_RAW_RLWINM(b2p[TMP_REG_1], dst_reg, 8, 16, 23)); 617 + EMIT(PPC_RAW_RLWINM(tmp1_reg, dst_reg, 8, 16, 23)); 650 618 /* Rotate 8 bits right & insert LSB to reg */ 651 - EMIT(PPC_RAW_RLWIMI(b2p[TMP_REG_1], dst_reg, 24, 24, 31)); 619 + EMIT(PPC_RAW_RLWIMI(tmp1_reg, dst_reg, 24, 24, 31)); 652 620 /* Move result back to dst_reg */ 653 - EMIT(PPC_RAW_MR(dst_reg, b2p[TMP_REG_1])); 621 + EMIT(PPC_RAW_MR(dst_reg, tmp1_reg)); 654 622 break; 655 623 case 32: 656 624 /* ··· 658 626 * 2 bytes are already in their final position 659 627 * -- byte 2 and 4 (of bytes 1, 2, 3 and 4) 660 628 */ 661 - EMIT(PPC_RAW_RLWINM(b2p[TMP_REG_1], dst_reg, 8, 0, 31)); 629 + EMIT(PPC_RAW_RLWINM(tmp1_reg, dst_reg, 8, 0, 31)); 662 630 /* Rotate 24 bits and insert byte 1 */ 663 - EMIT(PPC_RAW_RLWIMI(b2p[TMP_REG_1], dst_reg, 24, 0, 7)); 631 + EMIT(PPC_RAW_RLWIMI(tmp1_reg, dst_reg, 24, 0, 7)); 664 632 /* Rotate 24 bits and insert byte 3 */ 665 - EMIT(PPC_RAW_RLWIMI(b2p[TMP_REG_1], dst_reg, 24, 16, 23)); 666 - EMIT(PPC_RAW_MR(dst_reg, b2p[TMP_REG_1])); 633 + EMIT(PPC_RAW_RLWIMI(tmp1_reg, dst_reg, 24, 16, 23)); 634 + EMIT(PPC_RAW_MR(dst_reg, tmp1_reg)); 667 635 break; 668 636 case 64: 669 637 /* Store the value to stack and then use byte-reverse loads */ 670 - PPC_BPF_STL(dst_reg, 1, bpf_jit_stack_local(ctx)); 671 - EMIT(PPC_RAW_ADDI(b2p[TMP_REG_1], 1, bpf_jit_stack_local(ctx))); 638 + EMIT(PPC_RAW_STD(dst_reg, _R1, bpf_jit_stack_local(ctx))); 639 + EMIT(PPC_RAW_ADDI(tmp1_reg, _R1, bpf_jit_stack_local(ctx))); 672 640 if (cpu_has_feature(CPU_FTR_ARCH_206)) { 673 - EMIT(PPC_RAW_LDBRX(dst_reg, 0, b2p[TMP_REG_1])); 641 + EMIT(PPC_RAW_LDBRX(dst_reg, 0, tmp1_reg)); 674 642 } else { 675 - EMIT(PPC_RAW_LWBRX(dst_reg, 0, b2p[TMP_REG_1])); 643 + EMIT(PPC_RAW_LWBRX(dst_reg, 0, tmp1_reg)); 676 644 if (IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN)) 677 645 EMIT(PPC_RAW_SLDI(dst_reg, dst_reg, 32)); 678 - EMIT(PPC_RAW_LI(b2p[TMP_REG_2], 4)); 679 - EMIT(PPC_RAW_LWBRX(b2p[TMP_REG_2], b2p[TMP_REG_2], b2p[TMP_REG_1])); 646 + EMIT(PPC_RAW_LI(tmp2_reg, 4)); 647 + EMIT(PPC_RAW_LWBRX(tmp2_reg, tmp2_reg, tmp1_reg)); 680 648 if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) 681 - EMIT(PPC_RAW_SLDI(b2p[TMP_REG_2], b2p[TMP_REG_2], 32)); 682 - EMIT(PPC_RAW_OR(dst_reg, dst_reg, b2p[TMP_REG_2])); 649 + EMIT(PPC_RAW_SLDI(tmp2_reg, tmp2_reg, 32)); 650 + EMIT(PPC_RAW_OR(dst_reg, dst_reg, tmp2_reg)); 683 651 } 684 652 break; 685 653 } ··· 718 686 break; 719 687 case STF_BARRIER_SYNC_ORI: 720 688 EMIT(PPC_RAW_SYNC()); 721 - EMIT(PPC_RAW_LD(b2p[TMP_REG_1], _R13, 0)); 689 + EMIT(PPC_RAW_LD(tmp1_reg, _R13, 0)); 722 690 EMIT(PPC_RAW_ORI(_R31, _R31, 0)); 723 691 break; 724 692 case STF_BARRIER_FALLBACK: 725 - EMIT(PPC_RAW_MFLR(b2p[TMP_REG_1])); 726 - PPC_LI64(12, dereference_kernel_function_descriptor(bpf_stf_barrier)); 727 - EMIT(PPC_RAW_MTCTR(12)); 693 + ctx->seen |= SEEN_FUNC; 694 + PPC_LI64(_R12, dereference_kernel_function_descriptor(bpf_stf_barrier)); 695 + EMIT(PPC_RAW_MTCTR(_R12)); 728 696 EMIT(PPC_RAW_BCTRL()); 729 - EMIT(PPC_RAW_MTLR(b2p[TMP_REG_1])); 730 697 break; 731 698 case STF_BARRIER_NONE: 732 699 break; ··· 738 707 case BPF_STX | BPF_MEM | BPF_B: /* *(u8 *)(dst + off) = src */ 739 708 case BPF_ST | BPF_MEM | BPF_B: /* *(u8 *)(dst + off) = imm */ 740 709 if (BPF_CLASS(code) == BPF_ST) { 741 - EMIT(PPC_RAW_LI(b2p[TMP_REG_1], imm)); 742 - src_reg = b2p[TMP_REG_1]; 710 + EMIT(PPC_RAW_LI(tmp1_reg, imm)); 711 + src_reg = tmp1_reg; 743 712 } 744 713 EMIT(PPC_RAW_STB(src_reg, dst_reg, off)); 745 714 break; 746 715 case BPF_STX | BPF_MEM | BPF_H: /* (u16 *)(dst + off) = src */ 747 716 case BPF_ST | BPF_MEM | BPF_H: /* (u16 *)(dst + off) = imm */ 748 717 if (BPF_CLASS(code) == BPF_ST) { 749 - EMIT(PPC_RAW_LI(b2p[TMP_REG_1], imm)); 750 - src_reg = b2p[TMP_REG_1]; 718 + EMIT(PPC_RAW_LI(tmp1_reg, imm)); 719 + src_reg = tmp1_reg; 751 720 } 752 721 EMIT(PPC_RAW_STH(src_reg, dst_reg, off)); 753 722 break; 754 723 case BPF_STX | BPF_MEM | BPF_W: /* *(u32 *)(dst + off) = src */ 755 724 case BPF_ST | BPF_MEM | BPF_W: /* *(u32 *)(dst + off) = imm */ 756 725 if (BPF_CLASS(code) == BPF_ST) { 757 - PPC_LI32(b2p[TMP_REG_1], imm); 758 - src_reg = b2p[TMP_REG_1]; 726 + PPC_LI32(tmp1_reg, imm); 727 + src_reg = tmp1_reg; 759 728 } 760 729 EMIT(PPC_RAW_STW(src_reg, dst_reg, off)); 761 730 break; 762 731 case BPF_STX | BPF_MEM | BPF_DW: /* (u64 *)(dst + off) = src */ 763 732 case BPF_ST | BPF_MEM | BPF_DW: /* *(u64 *)(dst + off) = imm */ 764 733 if (BPF_CLASS(code) == BPF_ST) { 765 - PPC_LI32(b2p[TMP_REG_1], imm); 766 - src_reg = b2p[TMP_REG_1]; 734 + PPC_LI32(tmp1_reg, imm); 735 + src_reg = tmp1_reg; 767 736 } 768 - PPC_BPF_STL(src_reg, dst_reg, off); 737 + if (off % 4) { 738 + EMIT(PPC_RAW_LI(tmp2_reg, off)); 739 + EMIT(PPC_RAW_STDX(src_reg, dst_reg, tmp2_reg)); 740 + } else { 741 + EMIT(PPC_RAW_STD(src_reg, dst_reg, off)); 742 + } 769 743 break; 770 744 771 745 /* ··· 787 751 /* *(u32 *)(dst + off) += src */ 788 752 789 753 /* Get EA into TMP_REG_1 */ 790 - EMIT(PPC_RAW_ADDI(b2p[TMP_REG_1], dst_reg, off)); 754 + EMIT(PPC_RAW_ADDI(tmp1_reg, dst_reg, off)); 791 755 tmp_idx = ctx->idx * 4; 792 756 /* load value from memory into TMP_REG_2 */ 793 - EMIT(PPC_RAW_LWARX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1], 0)); 757 + EMIT(PPC_RAW_LWARX(tmp2_reg, 0, tmp1_reg, 0)); 794 758 /* add value from src_reg into this */ 795 - EMIT(PPC_RAW_ADD(b2p[TMP_REG_2], b2p[TMP_REG_2], src_reg)); 759 + EMIT(PPC_RAW_ADD(tmp2_reg, tmp2_reg, src_reg)); 796 760 /* store result back */ 797 - EMIT(PPC_RAW_STWCX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1])); 761 + EMIT(PPC_RAW_STWCX(tmp2_reg, 0, tmp1_reg)); 798 762 /* we're done if this succeeded */ 799 763 PPC_BCC_SHORT(COND_NE, tmp_idx); 800 764 break; ··· 807 771 } 808 772 /* *(u64 *)(dst + off) += src */ 809 773 810 - EMIT(PPC_RAW_ADDI(b2p[TMP_REG_1], dst_reg, off)); 774 + EMIT(PPC_RAW_ADDI(tmp1_reg, dst_reg, off)); 811 775 tmp_idx = ctx->idx * 4; 812 - EMIT(PPC_RAW_LDARX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1], 0)); 813 - EMIT(PPC_RAW_ADD(b2p[TMP_REG_2], b2p[TMP_REG_2], src_reg)); 814 - EMIT(PPC_RAW_STDCX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1])); 776 + EMIT(PPC_RAW_LDARX(tmp2_reg, 0, tmp1_reg, 0)); 777 + EMIT(PPC_RAW_ADD(tmp2_reg, tmp2_reg, src_reg)); 778 + EMIT(PPC_RAW_STDCX(tmp2_reg, 0, tmp1_reg)); 815 779 PPC_BCC_SHORT(COND_NE, tmp_idx); 816 780 break; 817 781 ··· 837 801 * set dst_reg=0 and move on. 838 802 */ 839 803 if (BPF_MODE(code) == BPF_PROBE_MEM) { 840 - EMIT(PPC_RAW_ADDI(b2p[TMP_REG_1], src_reg, off)); 804 + EMIT(PPC_RAW_ADDI(tmp1_reg, src_reg, off)); 841 805 if (IS_ENABLED(CONFIG_PPC_BOOK3E_64)) 842 - PPC_LI64(b2p[TMP_REG_2], 0x8000000000000000ul); 806 + PPC_LI64(tmp2_reg, 0x8000000000000000ul); 843 807 else /* BOOK3S_64 */ 844 - PPC_LI64(b2p[TMP_REG_2], PAGE_OFFSET); 845 - EMIT(PPC_RAW_CMPLD(b2p[TMP_REG_1], b2p[TMP_REG_2])); 846 - PPC_BCC(COND_GT, (ctx->idx + 4) * 4); 808 + PPC_LI64(tmp2_reg, PAGE_OFFSET); 809 + EMIT(PPC_RAW_CMPLD(tmp1_reg, tmp2_reg)); 810 + PPC_BCC_SHORT(COND_GT, (ctx->idx + 3) * 4); 847 811 EMIT(PPC_RAW_LI(dst_reg, 0)); 848 812 /* 849 - * Check if 'off' is word aligned because PPC_BPF_LL() 850 - * (BPF_DW case) generates two instructions if 'off' is not 851 - * word-aligned and one instruction otherwise. 813 + * Check if 'off' is word aligned for BPF_DW, because 814 + * we might generate two instructions. 852 815 */ 853 816 if (BPF_SIZE(code) == BPF_DW && (off & 3)) 854 817 PPC_JMP((ctx->idx + 3) * 4); ··· 866 831 EMIT(PPC_RAW_LWZ(dst_reg, src_reg, off)); 867 832 break; 868 833 case BPF_DW: 869 - PPC_BPF_LL(dst_reg, src_reg, off); 834 + if (off % 4) { 835 + EMIT(PPC_RAW_LI(tmp1_reg, off)); 836 + EMIT(PPC_RAW_LDX(dst_reg, src_reg, tmp1_reg)); 837 + } else { 838 + EMIT(PPC_RAW_LD(dst_reg, src_reg, off)); 839 + } 870 840 break; 871 841 } 872 842 ··· 911 871 * the epilogue. If we _are_ the last instruction, 912 872 * we'll just fall through to the epilogue. 913 873 */ 914 - if (i != flen - 1) 915 - PPC_JMP(exit_addr); 874 + if (i != flen - 1) { 875 + ret = bpf_jit_emit_exit_insn(image, ctx, tmp1_reg, exit_addr); 876 + if (ret) 877 + return ret; 878 + } 916 879 /* else fall through to the epilogue */ 917 880 break; 918 881 ··· 931 888 return ret; 932 889 933 890 if (func_addr_fixed) 934 - bpf_jit_emit_func_call_hlp(image, ctx, func_addr); 891 + ret = bpf_jit_emit_func_call_hlp(image, ctx, func_addr); 935 892 else 936 - bpf_jit_emit_func_call_rel(image, ctx, func_addr); 893 + ret = bpf_jit_emit_func_call_rel(image, ctx, func_addr); 894 + 895 + if (ret) 896 + return ret; 897 + 937 898 /* move return value from r3 to BPF_REG_0 */ 938 - EMIT(PPC_RAW_MR(b2p[BPF_REG_0], 3)); 899 + EMIT(PPC_RAW_MR(bpf_to_ppc(BPF_REG_0), _R3)); 939 900 break; 940 901 941 902 /* ··· 1045 998 case BPF_JMP | BPF_JSET | BPF_X: 1046 999 case BPF_JMP32 | BPF_JSET | BPF_X: 1047 1000 if (BPF_CLASS(code) == BPF_JMP) { 1048 - EMIT(PPC_RAW_AND_DOT(b2p[TMP_REG_1], dst_reg, 1049 - src_reg)); 1001 + EMIT(PPC_RAW_AND_DOT(tmp1_reg, dst_reg, src_reg)); 1050 1002 } else { 1051 - int tmp_reg = b2p[TMP_REG_1]; 1052 - 1053 - EMIT(PPC_RAW_AND(tmp_reg, dst_reg, src_reg)); 1054 - EMIT(PPC_RAW_RLWINM_DOT(tmp_reg, tmp_reg, 0, 0, 1055 - 31)); 1003 + EMIT(PPC_RAW_AND(tmp1_reg, dst_reg, src_reg)); 1004 + EMIT(PPC_RAW_RLWINM_DOT(tmp1_reg, tmp1_reg, 0, 0, 31)); 1056 1005 } 1057 1006 break; 1058 1007 case BPF_JMP | BPF_JNE | BPF_K: ··· 1077 1034 EMIT(PPC_RAW_CMPLDI(dst_reg, imm)); 1078 1035 } else { 1079 1036 /* sign-extending load */ 1080 - PPC_LI32(b2p[TMP_REG_1], imm); 1037 + PPC_LI32(tmp1_reg, imm); 1081 1038 /* ... but unsigned comparison */ 1082 1039 if (is_jmp32) 1083 - EMIT(PPC_RAW_CMPLW(dst_reg, 1084 - b2p[TMP_REG_1])); 1040 + EMIT(PPC_RAW_CMPLW(dst_reg, tmp1_reg)); 1085 1041 else 1086 - EMIT(PPC_RAW_CMPLD(dst_reg, 1087 - b2p[TMP_REG_1])); 1042 + EMIT(PPC_RAW_CMPLD(dst_reg, tmp1_reg)); 1088 1043 } 1089 1044 break; 1090 1045 } ··· 1107 1066 else 1108 1067 EMIT(PPC_RAW_CMPDI(dst_reg, imm)); 1109 1068 } else { 1110 - PPC_LI32(b2p[TMP_REG_1], imm); 1069 + PPC_LI32(tmp1_reg, imm); 1111 1070 if (is_jmp32) 1112 - EMIT(PPC_RAW_CMPW(dst_reg, 1113 - b2p[TMP_REG_1])); 1071 + EMIT(PPC_RAW_CMPW(dst_reg, tmp1_reg)); 1114 1072 else 1115 - EMIT(PPC_RAW_CMPD(dst_reg, 1116 - b2p[TMP_REG_1])); 1073 + EMIT(PPC_RAW_CMPD(dst_reg, tmp1_reg)); 1117 1074 } 1118 1075 break; 1119 1076 } ··· 1120 1081 /* andi does not sign-extend the immediate */ 1121 1082 if (imm >= 0 && imm < 32768) 1122 1083 /* PPC_ANDI is _only/always_ dot-form */ 1123 - EMIT(PPC_RAW_ANDI(b2p[TMP_REG_1], dst_reg, imm)); 1084 + EMIT(PPC_RAW_ANDI(tmp1_reg, dst_reg, imm)); 1124 1085 else { 1125 - int tmp_reg = b2p[TMP_REG_1]; 1126 - 1127 - PPC_LI32(tmp_reg, imm); 1086 + PPC_LI32(tmp1_reg, imm); 1128 1087 if (BPF_CLASS(code) == BPF_JMP) { 1129 - EMIT(PPC_RAW_AND_DOT(tmp_reg, dst_reg, 1130 - tmp_reg)); 1088 + EMIT(PPC_RAW_AND_DOT(tmp1_reg, dst_reg, 1089 + tmp1_reg)); 1131 1090 } else { 1132 - EMIT(PPC_RAW_AND(tmp_reg, dst_reg, 1133 - tmp_reg)); 1134 - EMIT(PPC_RAW_RLWINM_DOT(tmp_reg, tmp_reg, 1135 - 0, 0, 31)); 1091 + EMIT(PPC_RAW_AND(tmp1_reg, dst_reg, tmp1_reg)); 1092 + EMIT(PPC_RAW_RLWINM_DOT(tmp1_reg, tmp1_reg, 1093 + 0, 0, 31)); 1136 1094 } 1137 1095 } 1138 1096 break;
+1 -8
arch/powerpc/perf/callchain.h
··· 2 2 #ifndef _POWERPC_PERF_CALLCHAIN_H 3 3 #define _POWERPC_PERF_CALLCHAIN_H 4 4 5 - int read_user_stack_slow(const void __user *ptr, void *buf, int nb); 6 5 void perf_callchain_user_64(struct perf_callchain_entry_ctx *entry, 7 6 struct pt_regs *regs); 8 7 void perf_callchain_user_32(struct perf_callchain_entry_ctx *entry, ··· 25 26 size_t size) 26 27 { 27 28 unsigned long addr = (unsigned long)ptr; 28 - int rc; 29 29 30 30 if (addr > TASK_SIZE - size || (addr & (size - 1))) 31 31 return -EFAULT; 32 32 33 - rc = copy_from_user_nofault(ret, ptr, size); 34 - 35 - if (IS_ENABLED(CONFIG_PPC64) && !radix_enabled() && rc) 36 - return read_user_stack_slow(ptr, ret, size); 37 - 38 - return rc; 33 + return copy_from_user_nofault(ret, ptr, size); 39 34 } 40 35 41 36 #endif /* _POWERPC_PERF_CALLCHAIN_H */
-27
arch/powerpc/perf/callchain_64.c
··· 18 18 19 19 #include "callchain.h" 20 20 21 - /* 22 - * On 64-bit we don't want to invoke hash_page on user addresses from 23 - * interrupt context, so if the access faults, we read the page tables 24 - * to find which page (if any) is mapped and access it directly. Radix 25 - * has no need for this so it doesn't use read_user_stack_slow. 26 - */ 27 - int read_user_stack_slow(const void __user *ptr, void *buf, int nb) 28 - { 29 - 30 - unsigned long addr = (unsigned long) ptr; 31 - unsigned long offset; 32 - struct page *page; 33 - void *kaddr; 34 - 35 - if (get_user_page_fast_only(addr, FOLL_WRITE, &page)) { 36 - kaddr = page_address(page); 37 - 38 - /* align address to page boundary */ 39 - offset = addr & ~PAGE_MASK; 40 - 41 - memcpy(buf, kaddr + offset, nb); 42 - put_page(page); 43 - return 0; 44 - } 45 - return -EFAULT; 46 - } 47 - 48 21 static int read_user_stack_64(const unsigned long __user *ptr, unsigned long *ret) 49 22 { 50 23 return __read_user_stack(ptr, ret, sizeof(*ret));
+2 -2
arch/powerpc/perf/generic-compat-pmu.c
··· 130 130 NULL 131 131 }; 132 132 133 - static struct attribute_group generic_compat_pmu_events_group = { 133 + static const struct attribute_group generic_compat_pmu_events_group = { 134 134 .name = "events", 135 135 .attrs = generic_compat_events_attr, 136 136 }; ··· 146 146 NULL, 147 147 }; 148 148 149 - static struct attribute_group generic_compat_pmu_format_group = { 149 + static const struct attribute_group generic_compat_pmu_format_group = { 150 150 .name = "format", 151 151 .attrs = generic_compat_pmu_format_attr, 152 152 };
+3 -3
arch/powerpc/perf/hv-24x7.c
··· 204 204 NULL, 205 205 }; 206 206 207 - static struct attribute_group format_group = { 207 + static const struct attribute_group format_group = { 208 208 .name = "format", 209 209 .attrs = format_attrs, 210 210 }; ··· 1148 1148 NULL, 1149 1149 }; 1150 1150 1151 - static struct attribute_group cpumask_attr_group = { 1151 + static const struct attribute_group cpumask_attr_group = { 1152 1152 .attrs = cpumask_attrs, 1153 1153 }; 1154 1154 ··· 1162 1162 NULL, 1163 1163 }; 1164 1164 1165 - static struct attribute_group if_group = { 1165 + static const struct attribute_group if_group = { 1166 1166 .name = "interface", 1167 1167 .bin_attrs = if_bin_attrs, 1168 1168 .attrs = if_attrs,
+4 -4
arch/powerpc/perf/hv-gpci.c
··· 65 65 NULL, 66 66 }; 67 67 68 - static struct attribute_group format_group = { 68 + static const struct attribute_group format_group = { 69 69 .name = "format", 70 70 .attrs = format_attrs, 71 71 }; 72 72 73 - static struct attribute_group event_group = { 73 + static const struct attribute_group event_group = { 74 74 .name = "events", 75 75 .attrs = hv_gpci_event_attrs, 76 76 }; ··· 126 126 NULL, 127 127 }; 128 128 129 - static struct attribute_group cpumask_attr_group = { 129 + static const struct attribute_group cpumask_attr_group = { 130 130 .attrs = cpumask_attrs, 131 131 }; 132 132 133 - static struct attribute_group interface_group = { 133 + static const struct attribute_group interface_group = { 134 134 .name = "interface", 135 135 .attrs = interface_attrs, 136 136 };
+8 -4
arch/powerpc/perf/imc-pmu.c
··· 71 71 NULL, 72 72 }; 73 73 74 - static struct attribute_group imc_format_group = { 74 + static const struct attribute_group imc_format_group = { 75 75 .name = "format", 76 76 .attrs = imc_format_attrs, 77 77 }; ··· 90 90 NULL, 91 91 }; 92 92 93 - static struct attribute_group trace_imc_format_group = { 93 + static const struct attribute_group trace_imc_format_group = { 94 94 .name = "format", 95 95 .attrs = trace_imc_format_attrs, 96 96 }; ··· 125 125 NULL, 126 126 }; 127 127 128 - static struct attribute_group imc_pmu_cpumask_attr_group = { 128 + static const struct attribute_group imc_pmu_cpumask_attr_group = { 129 129 .attrs = imc_pmu_cpumask_attrs, 130 130 }; 131 131 ··· 1457 1457 1458 1458 event->hw.idx = -1; 1459 1459 1460 - event->pmu->task_ctx_nr = perf_hw_context; 1460 + /* 1461 + * There can only be a single PMU for perf_hw_context events which is assigned to 1462 + * core PMU. Hence use "perf_sw_context" for trace_imc. 1463 + */ 1464 + event->pmu->task_ctx_nr = perf_sw_context; 1461 1465 event->destroy = reset_global_refc; 1462 1466 return 0; 1463 1467 }
+1 -1
arch/powerpc/perf/isa207-common.c
··· 37 37 NULL, 38 38 }; 39 39 40 - struct attribute_group isa207_pmu_format_group = { 40 + const struct attribute_group isa207_pmu_format_group = { 41 41 .name = "format", 42 42 .attrs = isa207_pmu_format_attr, 43 43 };
+3 -5
arch/powerpc/perf/perf_regs.c
··· 134 134 135 135 u64 perf_reg_abi(struct task_struct *task) 136 136 { 137 - #ifdef CONFIG_PPC64 138 - if (!test_tsk_thread_flag(task, TIF_32BIT)) 139 - return PERF_SAMPLE_REGS_ABI_64; 137 + if (is_tsk_32bit_task(task)) 138 + return PERF_SAMPLE_REGS_ABI_32; 140 139 else 141 - #endif 142 - return PERF_SAMPLE_REGS_ABI_32; 140 + return PERF_SAMPLE_REGS_ABI_64; 143 141 } 144 142 145 143 void perf_get_regs_user(struct perf_regs *regs_user,
+3 -3
arch/powerpc/perf/power10-pmu.c
··· 200 200 NULL 201 201 }; 202 202 203 - static struct attribute_group power10_pmu_events_group_dd1 = { 203 + static const struct attribute_group power10_pmu_events_group_dd1 = { 204 204 .name = "events", 205 205 .attrs = power10_events_attr_dd1, 206 206 }; 207 207 208 - static struct attribute_group power10_pmu_events_group = { 208 + static const struct attribute_group power10_pmu_events_group = { 209 209 .name = "events", 210 210 .attrs = power10_events_attr, 211 211 }; ··· 253 253 NULL, 254 254 }; 255 255 256 - static struct attribute_group power10_pmu_format_group = { 256 + static const struct attribute_group power10_pmu_format_group = { 257 257 .name = "format", 258 258 .attrs = power10_pmu_format_attr, 259 259 };
+2 -2
arch/powerpc/perf/power7-pmu.c
··· 405 405 NULL 406 406 }; 407 407 408 - static struct attribute_group power7_pmu_events_group = { 408 + static const struct attribute_group power7_pmu_events_group = { 409 409 .name = "events", 410 410 .attrs = power7_events_attr, 411 411 }; ··· 417 417 NULL, 418 418 }; 419 419 420 - static struct attribute_group power7_pmu_format_group = { 420 + static const struct attribute_group power7_pmu_format_group = { 421 421 .name = "format", 422 422 .attrs = power7_pmu_format_attr, 423 423 };
+2 -2
arch/powerpc/perf/power8-pmu.c
··· 92 92 */ 93 93 94 94 /* PowerISA v2.07 format attribute structure*/ 95 - extern struct attribute_group isa207_pmu_format_group; 95 + extern const struct attribute_group isa207_pmu_format_group; 96 96 97 97 /* Table of alternatives, sorted by column 0 */ 98 98 static const unsigned int event_alternatives[][MAX_ALT] = { ··· 182 182 NULL 183 183 }; 184 184 185 - static struct attribute_group power8_pmu_events_group = { 185 + static const struct attribute_group power8_pmu_events_group = { 186 186 .name = "events", 187 187 .attrs = power8_events_attr, 188 188 };
+3 -3
arch/powerpc/perf/power9-pmu.c
··· 96 96 #define PVR_POWER9_CUMULUS 0x00002000 97 97 98 98 /* PowerISA v2.07 format attribute structure*/ 99 - extern struct attribute_group isa207_pmu_format_group; 99 + extern const struct attribute_group isa207_pmu_format_group; 100 100 101 101 int p9_dd21_bl_ev[] = { 102 102 PM_MRK_ST_DONE_L2, ··· 217 217 NULL 218 218 }; 219 219 220 - static struct attribute_group power9_pmu_events_group = { 220 + static const struct attribute_group power9_pmu_events_group = { 221 221 .name = "events", 222 222 .attrs = power9_events_attr, 223 223 }; ··· 253 253 NULL, 254 254 }; 255 255 256 - static struct attribute_group power9_pmu_format_group = { 256 + static const struct attribute_group power9_pmu_format_group = { 257 257 .name = "format", 258 258 .attrs = power9_pmu_format_attr, 259 259 };
+1 -1
arch/powerpc/platforms/85xx/corenet_generic.c
··· 37 37 unsigned int flags = MPIC_BIG_ENDIAN | MPIC_SINGLE_DEST_CPU | 38 38 MPIC_NO_RESET; 39 39 40 - if (ppc_md.get_irq == mpic_get_coreint_irq) 40 + if (!IS_ENABLED(CONFIG_HOTPLUG_CPU) && !IS_ENABLED(CONFIG_KEXEC_CORE)) 41 41 flags |= MPIC_ENABLE_COREINT; 42 42 43 43 mpic = mpic_alloc(NULL, 0, flags, 0, 512, " OpenPIC ");
+5
arch/powerpc/platforms/85xx/qemu_e500.c
··· 67 67 .get_irq = mpic_get_coreint_irq, 68 68 .calibrate_decr = generic_calibrate_decr, 69 69 .progress = udbg_progress, 70 + #ifdef CONFIG_PPC64 71 + .power_save = book3e_idle, 72 + #else 73 + .power_save = e500_idle, 74 + #endif 70 75 };
-6
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
··· 95 95 if (of_machine_is_compatible("fsl,mpc8641hpcn")) 96 96 return 1; /* Looks good */ 97 97 98 - /* Be nice and don't give silent boot death. Delete this in 2.6.27 */ 99 - if (of_machine_is_compatible("mpc86xx")) { 100 - pr_warn("WARNING: your dts/dtb is old. You must update before the next kernel release.\n"); 101 - return 1; 102 - } 103 - 104 98 return 0; 105 99 } 106 100
+1
arch/powerpc/platforms/8xx/pic.c
··· 153 153 if (mpc8xx_pic_host == NULL) { 154 154 printk(KERN_ERR "MPC8xx PIC: failed to allocate irq host!\n"); 155 155 ret = -ENOMEM; 156 + goto out; 156 157 } 157 158 158 159 ret = 0;
+2 -1
arch/powerpc/platforms/Kconfig.cputype
··· 107 107 108 108 config PPC_BOOK3E_64 109 109 bool "Embedded processors" 110 + select PPC_FSL_BOOK3E 110 111 select PPC_FPU # Make it a choice ? 111 112 select PPC_SMP_MUXED_IPI 112 113 select PPC_DOORBELL ··· 296 295 config PPC_FSL_BOOK3E 297 296 bool 298 297 select ARCH_SUPPORTS_HUGETLBFS if PHYS_64BIT || PPC64 299 - select FSL_EMB_PERFMON 298 + imply FSL_EMB_PERFMON 300 299 select PPC_SMP_MUXED_IPI 301 300 select PPC_DOORBELL 302 301 select PPC_KUEP
+144 -1
arch/powerpc/platforms/book3s/vas-api.c
··· 316 316 return PTR_ERR(txwin); 317 317 } 318 318 319 + mutex_init(&txwin->task_ref.mmap_mutex); 319 320 cp_inst->txwin = txwin; 320 321 321 322 return 0; ··· 351 350 return 0; 352 351 } 353 352 353 + /* 354 + * If the executed instruction that caused the fault was a paste, then 355 + * clear regs CR0[EQ], advance NIP, and return 0. Else return error code. 356 + */ 357 + static int do_fail_paste(void) 358 + { 359 + struct pt_regs *regs = current->thread.regs; 360 + u32 instword; 361 + 362 + if (WARN_ON_ONCE(!regs)) 363 + return -EINVAL; 364 + 365 + if (WARN_ON_ONCE(!user_mode(regs))) 366 + return -EINVAL; 367 + 368 + /* 369 + * If we couldn't translate the instruction, the driver should 370 + * return success without handling the fault, it will be retried 371 + * or the instruction fetch will fault. 372 + */ 373 + if (get_user(instword, (u32 __user *)(regs->nip))) 374 + return -EAGAIN; 375 + 376 + /* 377 + * Not a paste instruction, driver may fail the fault. 378 + */ 379 + if ((instword & PPC_INST_PASTE_MASK) != PPC_INST_PASTE) 380 + return -ENOENT; 381 + 382 + regs->ccr &= ~0xe0000000; /* Clear CR0[0-2] to fail paste */ 383 + regs_add_return_ip(regs, 4); /* Emulate the paste */ 384 + 385 + return 0; 386 + } 387 + 388 + /* 389 + * This fault handler is invoked when the core generates page fault on 390 + * the paste address. Happens if the kernel closes window in hypervisor 391 + * (on pseries) due to lost credit or the paste address is not mapped. 392 + */ 393 + static vm_fault_t vas_mmap_fault(struct vm_fault *vmf) 394 + { 395 + struct vm_area_struct *vma = vmf->vma; 396 + struct file *fp = vma->vm_file; 397 + struct coproc_instance *cp_inst = fp->private_data; 398 + struct vas_window *txwin; 399 + vm_fault_t fault; 400 + u64 paste_addr; 401 + int ret; 402 + 403 + /* 404 + * window is not opened. Shouldn't expect this error. 405 + */ 406 + if (!cp_inst || !cp_inst->txwin) { 407 + pr_err("%s(): Unexpected fault on paste address with TX window closed\n", 408 + __func__); 409 + return VM_FAULT_SIGBUS; 410 + } 411 + 412 + txwin = cp_inst->txwin; 413 + /* 414 + * When the LPAR lost credits due to core removal or during 415 + * migration, invalidate the existing mapping for the current 416 + * paste addresses and set windows in-active (zap_page_range in 417 + * reconfig_close_windows()). 418 + * New mapping will be done later after migration or new credits 419 + * available. So continue to receive faults if the user space 420 + * issue NX request. 421 + */ 422 + if (txwin->task_ref.vma != vmf->vma) { 423 + pr_err("%s(): No previous mapping with paste address\n", 424 + __func__); 425 + return VM_FAULT_SIGBUS; 426 + } 427 + 428 + mutex_lock(&txwin->task_ref.mmap_mutex); 429 + /* 430 + * The window may be inactive due to lost credit (Ex: core 431 + * removal with DLPAR). If the window is active again when 432 + * the credit is available, map the new paste address at the 433 + * the window virtual address. 434 + */ 435 + if (txwin->status == VAS_WIN_ACTIVE) { 436 + paste_addr = cp_inst->coproc->vops->paste_addr(txwin); 437 + if (paste_addr) { 438 + fault = vmf_insert_pfn(vma, vma->vm_start, 439 + (paste_addr >> PAGE_SHIFT)); 440 + mutex_unlock(&txwin->task_ref.mmap_mutex); 441 + return fault; 442 + } 443 + } 444 + mutex_unlock(&txwin->task_ref.mmap_mutex); 445 + 446 + /* 447 + * Received this fault due to closing the actual window. 448 + * It can happen during migration or lost credits. 449 + * Since no mapping, return the paste instruction failure 450 + * to the user space. 451 + */ 452 + ret = do_fail_paste(); 453 + /* 454 + * The user space can retry several times until success (needed 455 + * for migration) or should fallback to SW compression or 456 + * manage with the existing open windows if available. 457 + * Looking at sysfs interface, it can determine whether these 458 + * failures are coming during migration or core removal: 459 + * nr_used_credits > nr_total_credits when lost credits 460 + */ 461 + if (!ret || (ret == -EAGAIN)) 462 + return VM_FAULT_NOPAGE; 463 + 464 + return VM_FAULT_SIGBUS; 465 + } 466 + 467 + static const struct vm_operations_struct vas_vm_ops = { 468 + .fault = vas_mmap_fault, 469 + }; 470 + 354 471 static int coproc_mmap(struct file *fp, struct vm_area_struct *vma) 355 472 { 356 473 struct coproc_instance *cp_inst = fp->private_data; ··· 497 378 return -EACCES; 498 379 } 499 380 381 + /* 382 + * The initial mmap is done after the window is opened 383 + * with ioctl. But before mmap(), this window can be closed in 384 + * the hypervisor due to lost credit (core removal on pseries). 385 + * So if the window is not active, return mmap() failure with 386 + * -EACCES and expects the user space reissue mmap() when it 387 + * is active again or open new window when the credit is available. 388 + * mmap_mutex protects the paste address mmap() with DLPAR 389 + * close/open event and allows mmap() only when the window is 390 + * active. 391 + */ 392 + mutex_lock(&txwin->task_ref.mmap_mutex); 393 + if (txwin->status != VAS_WIN_ACTIVE) { 394 + pr_err("%s(): Window is not active\n", __func__); 395 + rc = -EACCES; 396 + goto out; 397 + } 398 + 500 399 paste_addr = cp_inst->coproc->vops->paste_addr(txwin); 501 400 if (!paste_addr) { 502 401 pr_err("%s(): Window paste address failed\n", __func__); 503 - return -EINVAL; 402 + rc = -EINVAL; 403 + goto out; 504 404 } 505 405 506 406 pfn = paste_addr >> PAGE_SHIFT; ··· 536 398 pr_devel("%s(): paste addr %llx at %lx, rc %d\n", __func__, 537 399 paste_addr, vma->vm_start, rc); 538 400 401 + txwin->task_ref.vma = vma; 402 + vma->vm_ops = &vas_vm_ops; 403 + 404 + out: 405 + mutex_unlock(&txwin->task_ref.mmap_mutex); 539 406 return rc; 540 407 } 541 408
+1 -1
arch/powerpc/platforms/cell/cbe_thermal.c
··· 255 255 NULL, 256 256 }; 257 257 258 - static struct attribute_group spu_attribute_group = { 258 + static const struct attribute_group spu_attribute_group = { 259 259 .name = "thermal", 260 260 .attrs = spu_attributes, 261 261 };
+2 -2
arch/powerpc/platforms/cell/spu_base.c
··· 490 490 } 491 491 EXPORT_SYMBOL_GPL(spu_add_dev_attr); 492 492 493 - int spu_add_dev_attr_group(struct attribute_group *attrs) 493 + int spu_add_dev_attr_group(const struct attribute_group *attrs) 494 494 { 495 495 struct spu *spu; 496 496 int rc = 0; ··· 529 529 } 530 530 EXPORT_SYMBOL_GPL(spu_remove_dev_attr); 531 531 532 - void spu_remove_dev_attr_group(struct attribute_group *attrs) 532 + void spu_remove_dev_attr_group(const struct attribute_group *attrs) 533 533 { 534 534 struct spu *spu; 535 535
+4 -3
arch/powerpc/platforms/cell/spufs/sched.c
··· 340 340 static void aff_set_ref_point_location(struct spu_gang *gang) 341 341 { 342 342 int mem_aff, gs, lowest_offset; 343 - struct spu_context *ctx; 344 - struct spu *tmp; 343 + struct spu_context *tmp, *ctx; 345 344 346 345 mem_aff = gang->aff_ref_ctx->flags & SPU_CREATE_AFFINITY_MEM; 347 346 lowest_offset = 0; ··· 1052 1053 } 1053 1054 } 1054 1055 1056 + #ifdef CONFIG_PROC_FS 1055 1057 static int show_spu_loadavg(struct seq_file *s, void *private) 1056 1058 { 1057 1059 int a, b, c; ··· 1074 1074 atomic_read(&nr_spu_contexts), 1075 1075 idr_get_cursor(&task_active_pid_ns(current)->idr) - 1); 1076 1076 return 0; 1077 - }; 1077 + } 1078 + #endif 1078 1079 1079 1080 int __init spu_sched_init(void) 1080 1081 {
+2
arch/powerpc/platforms/powermac/pmac.h
··· 5 5 #include <linux/pci.h> 6 6 #include <linux/irq.h> 7 7 8 + #include <asm/pmac_feature.h> 9 + 8 10 /* 9 11 * Declaration for the various functions exported by the 10 12 * pmac_* files. Mostly for use by pmac_setup
-1
arch/powerpc/platforms/powernv/idle.c
··· 12 12 #include <linux/device.h> 13 13 #include <linux/cpu.h> 14 14 15 - #include <asm/asm-prototypes.h> 16 15 #include <asm/firmware.h> 17 16 #include <asm/interrupt.h> 18 17 #include <asm/machdep.h>
+1 -1
arch/powerpc/platforms/powernv/opal-core.c
··· 603 603 604 604 }; 605 605 606 - static struct attribute_group mpipl_group = { 606 + static const struct attribute_group mpipl_group = { 607 607 .attrs = mpipl_attr, 608 608 .bin_attrs = mpipl_bin_attr, 609 609 };
+1 -1
arch/powerpc/platforms/powernv/opal-dump.c
··· 150 150 NULL, 151 151 }; 152 152 153 - static struct attribute_group initiate_attr_group = { 153 + static const struct attribute_group initiate_attr_group = { 154 154 .attrs = initiate_attrs, 155 155 }; 156 156
+1 -1
arch/powerpc/platforms/powernv/opal-flash.c
··· 512 512 NULL /* need to NULL terminate the list of attributes */ 513 513 }; 514 514 515 - static struct attribute_group image_op_attr_group = { 515 + static const struct attribute_group image_op_attr_group = { 516 516 .attrs = image_op_attrs, 517 517 }; 518 518
-1
arch/powerpc/platforms/powernv/opal-tracepoints.c
··· 2 2 #include <linux/percpu.h> 3 3 #include <linux/jump_label.h> 4 4 #include <asm/trace.h> 5 - #include <asm/asm-prototypes.h> 6 5 7 6 #ifdef CONFIG_JUMP_LABEL 8 7 struct static_key opal_tracepoint_key = STATIC_KEY_INIT;
+5 -1
arch/powerpc/platforms/powernv/rng.c
··· 43 43 unsigned long parity; 44 44 45 45 /* Calculate the parity of the value */ 46 - asm ("popcntd %0,%1" : "=r" (parity) : "r" (val)); 46 + asm (".machine push; \ 47 + .machine power7; \ 48 + popcntd %0,%1; \ 49 + .machine pop;" 50 + : "=r" (parity) : "r" (val)); 47 51 48 52 /* xor our value with the previous mask */ 49 53 val ^= rng->mask;
+2 -2
arch/powerpc/platforms/ps3/system-bus.c
··· 603 603 default: 604 604 /* not happned */ 605 605 BUG(); 606 - }; 606 + } 607 607 result = ps3_dma_map(dev->d_region, (unsigned long)ptr, size, 608 608 &bus_addr, iopte_flag); 609 609 ··· 762 762 break; 763 763 default: 764 764 BUG(); 765 - }; 765 + } 766 766 767 767 dev->core.of_node = NULL; 768 768 set_dev_node(&dev->core, 0);
+3 -2
arch/powerpc/platforms/pseries/Makefile
··· 6 6 of_helpers.o \ 7 7 setup.o iommu.o event_sources.o ras.o \ 8 8 firmware.o power.o dlpar.o mobility.o rng.o \ 9 - pci.o pci_dlpar.o eeh_pseries.o msi.o 9 + pci.o pci_dlpar.o eeh_pseries.o msi.o \ 10 + papr_platform_attributes.o 10 11 obj-$(CONFIG_SMP) += smp.o 11 12 obj-$(CONFIG_KEXEC_CORE) += kexec.o 12 13 obj-$(CONFIG_PSERIES_ENERGY) += pseries_energy.o ··· 30 29 obj-$(CONFIG_FA_DUMP) += rtas-fadump.o 31 30 32 31 obj-$(CONFIG_SUSPEND) += suspend.o 33 - obj-$(CONFIG_PPC_VAS) += vas.o 32 + obj-$(CONFIG_PPC_VAS) += vas.o vas-sysfs.o 34 33 35 34 obj-$(CONFIG_ARCH_HAS_CC_PLATFORM) += cc_platform.o
+1
arch/powerpc/platforms/pseries/firmware.c
··· 66 66 {FW_FEATURE_BLOCK_REMOVE, "hcall-block-remove"}, 67 67 {FW_FEATURE_PAPR_SCM, "hcall-scm"}, 68 68 {FW_FEATURE_RPT_INVALIDATE, "hcall-rpt-invalidate"}, 69 + {FW_FEATURE_ENERGY_SCALE_INFO, "hcall-energy-scale-info"}, 69 70 }; 70 71 71 72 /* Build up the firmware features bitmask using the contents of
-1
arch/powerpc/platforms/pseries/lpar.c
··· 40 40 #include <asm/plpar_wrappers.h> 41 41 #include <asm/kexec.h> 42 42 #include <asm/fadump.h> 43 - #include <asm/asm-prototypes.h> 44 43 #include <asm/dtl.h> 45 44 46 45 #include "pseries.h"
+87
arch/powerpc/platforms/pseries/lparcfg.c
··· 311 311 seq_printf(m, "coalesce_pool_spurr=%ld\n", mpp_x_data.pool_spurr_cycles); 312 312 } 313 313 314 + /* 315 + * PAPR defines, in section "7.3.16 System Parameters Option", the token 55 to 316 + * read the LPAR name, and the largest output data to 4000 + 2 bytes length. 317 + */ 318 + #define SPLPAR_LPAR_NAME_TOKEN 55 319 + #define GET_SYS_PARM_BUF_SIZE 4002 320 + #if GET_SYS_PARM_BUF_SIZE > RTAS_DATA_BUF_SIZE 321 + #error "GET_SYS_PARM_BUF_SIZE is larger than RTAS_DATA_BUF_SIZE" 322 + #endif 323 + 324 + /* 325 + * Read the lpar name using the RTAS ibm,get-system-parameter call. 326 + * 327 + * The name read through this call is updated if changes are made by the end 328 + * user on the hypervisor side. 329 + * 330 + * Some hypervisor (like Qemu) may not provide this value. In that case, a non 331 + * null value is returned. 332 + */ 333 + static int read_rtas_lpar_name(struct seq_file *m) 334 + { 335 + int rc, len, token; 336 + union { 337 + char raw_buffer[GET_SYS_PARM_BUF_SIZE]; 338 + struct { 339 + __be16 len; 340 + char name[GET_SYS_PARM_BUF_SIZE-2]; 341 + }; 342 + } *local_buffer; 343 + 344 + token = rtas_token("ibm,get-system-parameter"); 345 + if (token == RTAS_UNKNOWN_SERVICE) 346 + return -EINVAL; 347 + 348 + local_buffer = kmalloc(sizeof(*local_buffer), GFP_KERNEL); 349 + if (!local_buffer) 350 + return -ENOMEM; 351 + 352 + do { 353 + spin_lock(&rtas_data_buf_lock); 354 + memset(rtas_data_buf, 0, sizeof(*local_buffer)); 355 + rc = rtas_call(token, 3, 1, NULL, SPLPAR_LPAR_NAME_TOKEN, 356 + __pa(rtas_data_buf), sizeof(*local_buffer)); 357 + if (!rc) 358 + memcpy(local_buffer->raw_buffer, rtas_data_buf, 359 + sizeof(local_buffer->raw_buffer)); 360 + spin_unlock(&rtas_data_buf_lock); 361 + } while (rtas_busy_delay(rc)); 362 + 363 + if (!rc) { 364 + /* Force end of string */ 365 + len = min((int) be16_to_cpu(local_buffer->len), 366 + (int) sizeof(local_buffer->name)-1); 367 + local_buffer->name[len] = '\0'; 368 + 369 + seq_printf(m, "partition_name=%s\n", local_buffer->name); 370 + } else 371 + rc = -ENODATA; 372 + 373 + kfree(local_buffer); 374 + return rc; 375 + } 376 + 377 + /* 378 + * Read the LPAR name from the Device Tree. 379 + * 380 + * The value read in the DT is not updated if the end-user is touching the LPAR 381 + * name on the hypervisor side. 382 + */ 383 + static int read_dt_lpar_name(struct seq_file *m) 384 + { 385 + const char *name; 386 + 387 + if (of_property_read_string(of_root, "ibm,partition-name", &name)) 388 + return -ENOENT; 389 + 390 + seq_printf(m, "partition_name=%s\n", name); 391 + return 0; 392 + } 393 + 394 + static void read_lpar_name(struct seq_file *m) 395 + { 396 + if (read_rtas_lpar_name(m) && read_dt_lpar_name(m)) 397 + pr_err_once("Error can't get the LPAR name"); 398 + } 399 + 314 400 #define SPLPAR_CHARACTERISTICS_TOKEN 20 315 401 #define SPLPAR_MAXLENGTH 1026*(sizeof(char)) 316 402 ··· 582 496 583 497 if (firmware_has_feature(FW_FEATURE_SPLPAR)) { 584 498 /* this call handles the ibm,get-system-parameter contents */ 499 + read_lpar_name(m); 585 500 parse_system_parameter_string(m); 586 501 parse_ppp_data(m); 587 502 parse_mpp_data(m);
+6 -1
arch/powerpc/platforms/pseries/mobility.c
··· 26 26 #include <asm/machdep.h> 27 27 #include <asm/rtas.h> 28 28 #include "pseries.h" 29 + #include "vas.h" /* vas_migration_handler() */ 29 30 #include "../../kernel/cacheinfo.h" 30 31 31 32 static struct kobject *mobility_kobj; ··· 266 265 return rc; 267 266 } 268 267 269 - int pseries_devicetree_update(s32 scope) 268 + static int pseries_devicetree_update(s32 scope) 270 269 { 271 270 char *rtas_buf; 272 271 __be32 *data; ··· 670 669 if (ret) 671 670 return ret; 672 671 672 + vas_migration_handler(VAS_SUSPEND); 673 + 673 674 ret = pseries_suspend(handle); 674 675 if (ret == 0) 675 676 post_mobility_fixup(); 676 677 else 677 678 pseries_cancel_migration(handle, ret); 679 + 680 + vas_migration_handler(VAS_RESUME); 678 681 679 682 return ret; 680 683 }
+361
arch/powerpc/platforms/pseries/papr_platform_attributes.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Platform energy and frequency attributes driver 4 + * 5 + * This driver creates a sys file at /sys/firmware/papr/ which encapsulates a 6 + * directory structure containing files in keyword - value pairs that specify 7 + * energy and frequency configuration of the system. 8 + * 9 + * The format of exposing the sysfs information is as follows: 10 + * /sys/firmware/papr/energy_scale_info/ 11 + * |-- <id>/ 12 + * |-- desc 13 + * |-- value 14 + * |-- value_desc (if exists) 15 + * |-- <id>/ 16 + * |-- desc 17 + * |-- value 18 + * |-- value_desc (if exists) 19 + * 20 + * Copyright 2022 IBM Corp. 21 + */ 22 + 23 + #include <asm/hvcall.h> 24 + #include <asm/machdep.h> 25 + 26 + #include "pseries.h" 27 + 28 + /* 29 + * Flag attributes to fetch either all or one attribute from the HCALL 30 + * flag = BE(0) => fetch all attributes with firstAttributeId = 0 31 + * flag = BE(1) => fetch a single attribute with firstAttributeId = id 32 + */ 33 + #define ESI_FLAGS_ALL 0 34 + #define ESI_FLAGS_SINGLE (1ull << 63) 35 + 36 + #define KOBJ_MAX_ATTRS 3 37 + 38 + #define ESI_HDR_SIZE sizeof(struct h_energy_scale_info_hdr) 39 + #define ESI_ATTR_SIZE sizeof(struct energy_scale_attribute) 40 + #define CURR_MAX_ESI_ATTRS 8 41 + 42 + struct energy_scale_attribute { 43 + __be64 id; 44 + __be64 val; 45 + u8 desc[64]; 46 + u8 value_desc[64]; 47 + } __packed; 48 + 49 + struct h_energy_scale_info_hdr { 50 + __be64 num_attrs; 51 + __be64 array_offset; 52 + u8 data_header_version; 53 + } __packed; 54 + 55 + struct papr_attr { 56 + u64 id; 57 + struct kobj_attribute kobj_attr; 58 + }; 59 + 60 + struct papr_group { 61 + struct attribute_group pg; 62 + struct papr_attr pgattrs[KOBJ_MAX_ATTRS]; 63 + }; 64 + 65 + static struct papr_group *papr_groups; 66 + /* /sys/firmware/papr */ 67 + static struct kobject *papr_kobj; 68 + /* /sys/firmware/papr/energy_scale_info */ 69 + static struct kobject *esi_kobj; 70 + 71 + /* 72 + * Energy modes can change dynamically hence making a new hcall each time the 73 + * information needs to be retrieved 74 + */ 75 + static int papr_get_attr(u64 id, struct energy_scale_attribute *esi) 76 + { 77 + int esi_buf_size = ESI_HDR_SIZE + (CURR_MAX_ESI_ATTRS * ESI_ATTR_SIZE); 78 + int ret, max_esi_attrs = CURR_MAX_ESI_ATTRS; 79 + struct energy_scale_attribute *curr_esi; 80 + struct h_energy_scale_info_hdr *hdr; 81 + char *buf; 82 + 83 + buf = kmalloc(esi_buf_size, GFP_KERNEL); 84 + if (buf == NULL) 85 + return -ENOMEM; 86 + 87 + retry: 88 + ret = plpar_hcall_norets(H_GET_ENERGY_SCALE_INFO, ESI_FLAGS_SINGLE, 89 + id, virt_to_phys(buf), 90 + esi_buf_size); 91 + 92 + /* 93 + * If the hcall fails with not enough memory for either the 94 + * header or data, attempt to allocate more 95 + */ 96 + if (ret == H_PARTIAL || ret == H_P4) { 97 + char *temp_buf; 98 + 99 + max_esi_attrs += 4; 100 + esi_buf_size = ESI_HDR_SIZE + (CURR_MAX_ESI_ATTRS * max_esi_attrs); 101 + 102 + temp_buf = krealloc(buf, esi_buf_size, GFP_KERNEL); 103 + if (temp_buf) 104 + buf = temp_buf; 105 + else 106 + return -ENOMEM; 107 + 108 + goto retry; 109 + } 110 + 111 + if (ret != H_SUCCESS) { 112 + pr_warn("hcall failed: H_GET_ENERGY_SCALE_INFO"); 113 + ret = -EIO; 114 + goto out_buf; 115 + } 116 + 117 + hdr = (struct h_energy_scale_info_hdr *) buf; 118 + curr_esi = (struct energy_scale_attribute *) 119 + (buf + be64_to_cpu(hdr->array_offset)); 120 + 121 + if (esi_buf_size < 122 + be64_to_cpu(hdr->array_offset) + (be64_to_cpu(hdr->num_attrs) 123 + * sizeof(struct energy_scale_attribute))) { 124 + ret = -EIO; 125 + goto out_buf; 126 + } 127 + 128 + *esi = *curr_esi; 129 + 130 + out_buf: 131 + kfree(buf); 132 + 133 + return ret; 134 + } 135 + 136 + /* 137 + * Extract and export the description of the energy scale attributes 138 + */ 139 + static ssize_t desc_show(struct kobject *kobj, 140 + struct kobj_attribute *kobj_attr, 141 + char *buf) 142 + { 143 + struct papr_attr *pattr = container_of(kobj_attr, struct papr_attr, 144 + kobj_attr); 145 + struct energy_scale_attribute esi; 146 + int ret; 147 + 148 + ret = papr_get_attr(pattr->id, &esi); 149 + if (ret) 150 + return ret; 151 + 152 + return sysfs_emit(buf, "%s\n", esi.desc); 153 + } 154 + 155 + /* 156 + * Extract and export the numeric value of the energy scale attributes 157 + */ 158 + static ssize_t val_show(struct kobject *kobj, 159 + struct kobj_attribute *kobj_attr, 160 + char *buf) 161 + { 162 + struct papr_attr *pattr = container_of(kobj_attr, struct papr_attr, 163 + kobj_attr); 164 + struct energy_scale_attribute esi; 165 + int ret; 166 + 167 + ret = papr_get_attr(pattr->id, &esi); 168 + if (ret) 169 + return ret; 170 + 171 + return sysfs_emit(buf, "%llu\n", be64_to_cpu(esi.val)); 172 + } 173 + 174 + /* 175 + * Extract and export the value description in string format of the energy 176 + * scale attributes 177 + */ 178 + static ssize_t val_desc_show(struct kobject *kobj, 179 + struct kobj_attribute *kobj_attr, 180 + char *buf) 181 + { 182 + struct papr_attr *pattr = container_of(kobj_attr, struct papr_attr, 183 + kobj_attr); 184 + struct energy_scale_attribute esi; 185 + int ret; 186 + 187 + ret = papr_get_attr(pattr->id, &esi); 188 + if (ret) 189 + return ret; 190 + 191 + return sysfs_emit(buf, "%s\n", esi.value_desc); 192 + } 193 + 194 + static struct papr_ops_info { 195 + const char *attr_name; 196 + ssize_t (*show)(struct kobject *kobj, struct kobj_attribute *kobj_attr, 197 + char *buf); 198 + } ops_info[KOBJ_MAX_ATTRS] = { 199 + { "desc", desc_show }, 200 + { "value", val_show }, 201 + { "value_desc", val_desc_show }, 202 + }; 203 + 204 + static void add_attr(u64 id, int index, struct papr_attr *attr) 205 + { 206 + attr->id = id; 207 + sysfs_attr_init(&attr->kobj_attr.attr); 208 + attr->kobj_attr.attr.name = ops_info[index].attr_name; 209 + attr->kobj_attr.attr.mode = 0444; 210 + attr->kobj_attr.show = ops_info[index].show; 211 + } 212 + 213 + static int add_attr_group(u64 id, struct papr_group *pg, bool show_val_desc) 214 + { 215 + int i; 216 + 217 + for (i = 0; i < KOBJ_MAX_ATTRS; i++) { 218 + if (!strcmp(ops_info[i].attr_name, "value_desc") && 219 + !show_val_desc) { 220 + continue; 221 + } 222 + add_attr(id, i, &pg->pgattrs[i]); 223 + pg->pg.attrs[i] = &pg->pgattrs[i].kobj_attr.attr; 224 + } 225 + 226 + return sysfs_create_group(esi_kobj, &pg->pg); 227 + } 228 + 229 + 230 + static int __init papr_init(void) 231 + { 232 + int esi_buf_size = ESI_HDR_SIZE + (CURR_MAX_ESI_ATTRS * ESI_ATTR_SIZE); 233 + int ret, idx, i, max_esi_attrs = CURR_MAX_ESI_ATTRS; 234 + struct h_energy_scale_info_hdr *esi_hdr; 235 + struct energy_scale_attribute *esi_attrs; 236 + uint64_t num_attrs; 237 + char *esi_buf; 238 + 239 + if (!firmware_has_feature(FW_FEATURE_LPAR) || 240 + !firmware_has_feature(FW_FEATURE_ENERGY_SCALE_INFO)) { 241 + return -ENXIO; 242 + } 243 + 244 + esi_buf = kmalloc(esi_buf_size, GFP_KERNEL); 245 + if (esi_buf == NULL) 246 + return -ENOMEM; 247 + /* 248 + * hcall( 249 + * uint64 H_GET_ENERGY_SCALE_INFO, // Get energy scale info 250 + * uint64 flags, // Per the flag request 251 + * uint64 firstAttributeId, // The attribute id 252 + * uint64 bufferAddress, // Guest physical address of the output buffer 253 + * uint64 bufferSize); // The size in bytes of the output buffer 254 + */ 255 + retry: 256 + 257 + ret = plpar_hcall_norets(H_GET_ENERGY_SCALE_INFO, ESI_FLAGS_ALL, 0, 258 + virt_to_phys(esi_buf), esi_buf_size); 259 + 260 + /* 261 + * If the hcall fails with not enough memory for either the 262 + * header or data, attempt to allocate more 263 + */ 264 + if (ret == H_PARTIAL || ret == H_P4) { 265 + char *temp_esi_buf; 266 + 267 + max_esi_attrs += 4; 268 + esi_buf_size = ESI_HDR_SIZE + (CURR_MAX_ESI_ATTRS * max_esi_attrs); 269 + 270 + temp_esi_buf = krealloc(esi_buf, esi_buf_size, GFP_KERNEL); 271 + if (temp_esi_buf) 272 + esi_buf = temp_esi_buf; 273 + else 274 + return -ENOMEM; 275 + 276 + goto retry; 277 + } 278 + 279 + if (ret != H_SUCCESS) { 280 + pr_warn("hcall failed: H_GET_ENERGY_SCALE_INFO, ret: %d\n", ret); 281 + goto out_free_esi_buf; 282 + } 283 + 284 + esi_hdr = (struct h_energy_scale_info_hdr *) esi_buf; 285 + num_attrs = be64_to_cpu(esi_hdr->num_attrs); 286 + esi_attrs = (struct energy_scale_attribute *) 287 + (esi_buf + be64_to_cpu(esi_hdr->array_offset)); 288 + 289 + if (esi_buf_size < 290 + be64_to_cpu(esi_hdr->array_offset) + 291 + (num_attrs * sizeof(struct energy_scale_attribute))) { 292 + goto out_free_esi_buf; 293 + } 294 + 295 + papr_groups = kcalloc(num_attrs, sizeof(*papr_groups), GFP_KERNEL); 296 + if (!papr_groups) 297 + goto out_free_esi_buf; 298 + 299 + papr_kobj = kobject_create_and_add("papr", firmware_kobj); 300 + if (!papr_kobj) { 301 + pr_warn("kobject_create_and_add papr failed\n"); 302 + goto out_papr_groups; 303 + } 304 + 305 + esi_kobj = kobject_create_and_add("energy_scale_info", papr_kobj); 306 + if (!esi_kobj) { 307 + pr_warn("kobject_create_and_add energy_scale_info failed\n"); 308 + goto out_kobj; 309 + } 310 + 311 + /* Allocate the groups before registering */ 312 + for (idx = 0; idx < num_attrs; idx++) { 313 + papr_groups[idx].pg.attrs = kcalloc(KOBJ_MAX_ATTRS + 1, 314 + sizeof(*papr_groups[idx].pg.attrs), 315 + GFP_KERNEL); 316 + if (!papr_groups[idx].pg.attrs) 317 + goto out_pgattrs; 318 + 319 + papr_groups[idx].pg.name = kasprintf(GFP_KERNEL, "%lld", 320 + be64_to_cpu(esi_attrs[idx].id)); 321 + if (papr_groups[idx].pg.name == NULL) 322 + goto out_pgattrs; 323 + } 324 + 325 + for (idx = 0; idx < num_attrs; idx++) { 326 + bool show_val_desc = true; 327 + 328 + /* Do not add the value desc attr if it does not exist */ 329 + if (strnlen(esi_attrs[idx].value_desc, 330 + sizeof(esi_attrs[idx].value_desc)) == 0) 331 + show_val_desc = false; 332 + 333 + if (add_attr_group(be64_to_cpu(esi_attrs[idx].id), 334 + &papr_groups[idx], 335 + show_val_desc)) { 336 + pr_warn("Failed to create papr attribute group %s\n", 337 + papr_groups[idx].pg.name); 338 + idx = num_attrs; 339 + goto out_pgattrs; 340 + } 341 + } 342 + 343 + kfree(esi_buf); 344 + return 0; 345 + out_pgattrs: 346 + for (i = 0; i < idx ; i++) { 347 + kfree(papr_groups[i].pg.attrs); 348 + kfree(papr_groups[i].pg.name); 349 + } 350 + kobject_put(esi_kobj); 351 + out_kobj: 352 + kobject_put(papr_kobj); 353 + out_papr_groups: 354 + kfree(papr_groups); 355 + out_free_esi_buf: 356 + kfree(esi_buf); 357 + 358 + return -ENOMEM; 359 + } 360 + 361 + machine_device_initcall(pseries, papr_init);
+88 -4
arch/powerpc/platforms/pseries/papr_scm.c
··· 120 120 121 121 /* length of the stat buffer as expected by phyp */ 122 122 size_t stat_buffer_len; 123 + 124 + /* The bits which needs to be overridden */ 125 + u64 health_bitmap_inject_mask; 126 + 123 127 }; 124 128 125 129 static int papr_scm_pmem_flush(struct nd_region *nd_region, ··· 351 347 static int __drc_pmem_query_health(struct papr_scm_priv *p) 352 348 { 353 349 unsigned long ret[PLPAR_HCALL_BUFSIZE]; 350 + u64 bitmap = 0; 354 351 long rc; 355 352 356 353 /* issue the hcall */ 357 354 rc = plpar_hcall(H_SCM_HEALTH, ret, p->drc_index); 358 - if (rc != H_SUCCESS) { 355 + if (rc == H_SUCCESS) 356 + bitmap = ret[0] & ret[1]; 357 + else if (rc == H_FUNCTION) 358 + dev_info_once(&p->pdev->dev, 359 + "Hcall H_SCM_HEALTH not implemented, assuming empty health bitmap"); 360 + else { 361 + 359 362 dev_err(&p->pdev->dev, 360 363 "Failed to query health information, Err:%ld\n", rc); 361 364 return -ENXIO; 362 365 } 363 366 364 367 p->lasthealth_jiffies = jiffies; 365 - p->health_bitmap = ret[0] & ret[1]; 366 - 368 + /* Allow injecting specific health bits via inject mask. */ 369 + if (p->health_bitmap_inject_mask) 370 + bitmap = (bitmap & ~p->health_bitmap_inject_mask) | 371 + p->health_bitmap_inject_mask; 372 + WRITE_ONCE(p->health_bitmap, bitmap); 367 373 dev_dbg(&p->pdev->dev, 368 374 "Queried dimm health info. Bitmap:0x%016lx Mask:0x%016lx\n", 369 375 ret[0], ret[1]); ··· 683 669 return rc; 684 670 } 685 671 672 + /* Inject a smart error Add the dirty-shutdown-counter value to the pdsm */ 673 + static int papr_pdsm_smart_inject(struct papr_scm_priv *p, 674 + union nd_pdsm_payload *payload) 675 + { 676 + int rc; 677 + u32 supported_flags = 0; 678 + u64 inject_mask = 0, clear_mask = 0; 679 + u64 mask; 680 + 681 + /* Check for individual smart error flags and update inject/clear masks */ 682 + if (payload->smart_inject.flags & PDSM_SMART_INJECT_HEALTH_FATAL) { 683 + supported_flags |= PDSM_SMART_INJECT_HEALTH_FATAL; 684 + if (payload->smart_inject.fatal_enable) 685 + inject_mask |= PAPR_PMEM_HEALTH_FATAL; 686 + else 687 + clear_mask |= PAPR_PMEM_HEALTH_FATAL; 688 + } 689 + 690 + if (payload->smart_inject.flags & PDSM_SMART_INJECT_BAD_SHUTDOWN) { 691 + supported_flags |= PDSM_SMART_INJECT_BAD_SHUTDOWN; 692 + if (payload->smart_inject.unsafe_shutdown_enable) 693 + inject_mask |= PAPR_PMEM_SHUTDOWN_DIRTY; 694 + else 695 + clear_mask |= PAPR_PMEM_SHUTDOWN_DIRTY; 696 + } 697 + 698 + dev_dbg(&p->pdev->dev, "[Smart-inject] inject_mask=%#llx clear_mask=%#llx\n", 699 + inject_mask, clear_mask); 700 + 701 + /* Prevent concurrent access to dimm health bitmap related members */ 702 + rc = mutex_lock_interruptible(&p->health_mutex); 703 + if (rc) 704 + return rc; 705 + 706 + /* Use inject/clear masks to set health_bitmap_inject_mask */ 707 + mask = READ_ONCE(p->health_bitmap_inject_mask); 708 + mask = (mask & ~clear_mask) | inject_mask; 709 + WRITE_ONCE(p->health_bitmap_inject_mask, mask); 710 + 711 + /* Invalidate cached health bitmap */ 712 + p->lasthealth_jiffies = 0; 713 + 714 + mutex_unlock(&p->health_mutex); 715 + 716 + /* Return the supported flags back to userspace */ 717 + payload->smart_inject.flags = supported_flags; 718 + 719 + return sizeof(struct nd_papr_pdsm_health); 720 + } 721 + 686 722 /* 687 723 * 'struct pdsm_cmd_desc' 688 724 * Identifies supported PDSMs' expected length of in/out payloads ··· 765 701 .size_in = 0, 766 702 .size_out = sizeof(struct nd_papr_pdsm_health), 767 703 .service = papr_pdsm_health, 704 + }, 705 + 706 + [PAPR_PDSM_SMART_INJECT] = { 707 + .size_in = sizeof(struct nd_papr_pdsm_smart_inject), 708 + .size_out = sizeof(struct nd_papr_pdsm_smart_inject), 709 + .service = papr_pdsm_smart_inject, 768 710 }, 769 711 /* Empty */ 770 712 [PAPR_PDSM_MAX] = { ··· 908 838 return 0; 909 839 } 910 840 841 + static ssize_t health_bitmap_inject_show(struct device *dev, 842 + struct device_attribute *attr, 843 + char *buf) 844 + { 845 + struct nvdimm *dimm = to_nvdimm(dev); 846 + struct papr_scm_priv *p = nvdimm_provider_data(dimm); 847 + 848 + return sprintf(buf, "%#llx\n", 849 + READ_ONCE(p->health_bitmap_inject_mask)); 850 + } 851 + 852 + static DEVICE_ATTR_ADMIN_RO(health_bitmap_inject); 853 + 911 854 static ssize_t perf_stats_show(struct device *dev, 912 855 struct device_attribute *attr, char *buf) 913 856 { ··· 1035 952 &dev_attr_flags.attr, 1036 953 &dev_attr_perf_stats.attr, 1037 954 &dev_attr_dirty_shutdown.attr, 955 + &dev_attr_health_bitmap_inject.attr, 1038 956 NULL, 1039 957 }; 1040 958 1041 - static struct attribute_group papr_nd_attribute_group = { 959 + static const struct attribute_group papr_nd_attribute_group = { 1042 960 .name = "papr", 1043 961 .is_visible = papr_nd_attribute_visible, 1044 962 .attrs = papr_nd_attributes,
+4
arch/powerpc/platforms/pseries/pci_dlpar.c
··· 78 78 79 79 pseries_msi_free_domains(phb); 80 80 81 + /* Keep a reference so phb isn't freed yet */ 82 + get_device(&host_bridge->dev); 83 + 81 84 /* Remove the PCI bus and unregister the bridge device from sysfs */ 82 85 phb->bus = NULL; 83 86 pci_remove_bus(b); ··· 104 101 * the pcibios_free_controller_deferred() callback; 105 102 * see pseries_root_bridge_prepare(). 106 103 */ 104 + put_device(&host_bridge->dev); 107 105 108 106 return 0; 109 107 }
+1 -1
arch/powerpc/platforms/pseries/power.c
··· 51 51 NULL, 52 52 }; 53 53 54 - static struct attribute_group attr_group = { 54 + static const struct attribute_group attr_group = { 55 55 .attrs = g, 56 56 }; 57 57
+1
arch/powerpc/platforms/pseries/pseries.h
··· 21 21 extern int pSeries_system_reset_exception(struct pt_regs *regs); 22 22 extern int pSeries_machine_check_exception(struct pt_regs *regs); 23 23 extern long pseries_machine_check_realmode(struct pt_regs *regs); 24 + void pSeries_machine_check_log_err(void); 24 25 25 26 #ifdef CONFIG_SMP 26 27 extern void smp_init_pseries(void);
+33 -35
arch/powerpc/platforms/pseries/ras.c
··· 23 23 24 24 static int ras_check_exception_token; 25 25 26 - static void mce_process_errlog_event(struct irq_work *work); 27 - static struct irq_work mce_errlog_process_work = { 28 - .func = mce_process_errlog_event, 29 - }; 30 - 31 26 #define EPOW_SENSOR_TOKEN 9 32 27 #define EPOW_SENSOR_INDEX 0 33 28 ··· 55 60 * XX 2: Reserved. 56 61 * XXX 3: Type of UE error. 57 62 * 58 - * For error_type != MC_ERROR_TYPE_UE 63 + * For error_type == MC_ERROR_TYPE_SLB/ERAT/TLB 59 64 * XXXXXXXX 60 65 * X 1: Effective address provided. 61 66 * XXXXX 5: Reserved. 62 67 * XX 2: Type of SLB/ERAT/TLB error. 68 + * 69 + * For error_type == MC_ERROR_TYPE_CTRL_MEM_ACCESS 70 + * XXXXXXXX 71 + * X 1: Error causing address provided. 72 + * XXX 3: Type of error. 73 + * XXXX 4: Reserved. 63 74 */ 64 75 u8 sub_err_type; 65 76 u8 reserved_1[6]; ··· 81 80 #define MC_ERROR_TYPE_TLB 0x04 82 81 #define MC_ERROR_TYPE_D_CACHE 0x05 83 82 #define MC_ERROR_TYPE_I_CACHE 0x07 83 + #define MC_ERROR_TYPE_CTRL_MEM_ACCESS 0x08 84 84 85 85 /* RTAS pseries MCE error sub types */ 86 86 #define MC_ERROR_UE_INDETERMINATE 0 ··· 92 90 93 91 #define UE_EFFECTIVE_ADDR_PROVIDED 0x40 94 92 #define UE_LOGICAL_ADDR_PROVIDED 0x20 93 + #define MC_EFFECTIVE_ADDR_PROVIDED 0x80 95 94 96 95 #define MC_ERROR_SLB_PARITY 0 97 96 #define MC_ERROR_SLB_MULTIHIT 1 ··· 106 103 #define MC_ERROR_TLB_MULTIHIT 2 107 104 #define MC_ERROR_TLB_INDETERMINATE 3 108 105 106 + #define MC_ERROR_CTRL_MEM_ACCESS_PTABLE_WALK 0 107 + #define MC_ERROR_CTRL_MEM_ACCESS_OP_ACCESS 1 108 + 109 109 static inline u8 rtas_mc_error_sub_type(const struct pseries_mc_errorlog *mlog) 110 110 { 111 111 switch (mlog->error_type) { ··· 118 112 case MC_ERROR_TYPE_ERAT: 119 113 case MC_ERROR_TYPE_TLB: 120 114 return (mlog->sub_err_type & 0x03); 115 + case MC_ERROR_TYPE_CTRL_MEM_ACCESS: 116 + return (mlog->sub_err_type & 0x70) >> 4; 121 117 default: 122 118 return 0; 123 119 } ··· 666 658 mce_err.u.slb_error_type = MCE_SLB_ERROR_INDETERMINATE; 667 659 break; 668 660 } 669 - if (mce_log->sub_err_type & 0x80) 661 + if (mce_log->sub_err_type & MC_EFFECTIVE_ADDR_PROVIDED) 670 662 eaddr = be64_to_cpu(mce_log->effective_address); 671 663 break; 672 664 case MC_ERROR_TYPE_ERAT: ··· 683 675 mce_err.u.erat_error_type = MCE_ERAT_ERROR_INDETERMINATE; 684 676 break; 685 677 } 686 - if (mce_log->sub_err_type & 0x80) 678 + if (mce_log->sub_err_type & MC_EFFECTIVE_ADDR_PROVIDED) 687 679 eaddr = be64_to_cpu(mce_log->effective_address); 688 680 break; 689 681 case MC_ERROR_TYPE_TLB: ··· 700 692 mce_err.u.tlb_error_type = MCE_TLB_ERROR_INDETERMINATE; 701 693 break; 702 694 } 703 - if (mce_log->sub_err_type & 0x80) 695 + if (mce_log->sub_err_type & MC_EFFECTIVE_ADDR_PROVIDED) 704 696 eaddr = be64_to_cpu(mce_log->effective_address); 705 697 break; 706 698 case MC_ERROR_TYPE_D_CACHE: ··· 708 700 break; 709 701 case MC_ERROR_TYPE_I_CACHE: 710 702 mce_err.error_type = MCE_ERROR_TYPE_ICACHE; 703 + break; 704 + case MC_ERROR_TYPE_CTRL_MEM_ACCESS: 705 + mce_err.error_type = MCE_ERROR_TYPE_RA; 706 + switch (err_sub_type) { 707 + case MC_ERROR_CTRL_MEM_ACCESS_PTABLE_WALK: 708 + mce_err.u.ra_error_type = 709 + MCE_RA_ERROR_PAGE_TABLE_WALK_LOAD_STORE_FOREIGN; 710 + break; 711 + case MC_ERROR_CTRL_MEM_ACCESS_OP_ACCESS: 712 + mce_err.u.ra_error_type = 713 + MCE_RA_ERROR_LOAD_STORE_FOREIGN; 714 + break; 715 + } 716 + if (mce_log->sub_err_type & MC_EFFECTIVE_ADDR_PROVIDED) 717 + eaddr = be64_to_cpu(mce_log->effective_address); 711 718 break; 712 719 case MC_ERROR_TYPE_UNKNOWN: 713 720 default: ··· 740 717 struct pseries_errorlog *pseries_log; 741 718 struct pseries_mc_errorlog *mce_log = NULL; 742 719 int disposition = rtas_error_disposition(errp); 743 - unsigned long msr; 744 720 u8 error_type; 745 721 746 722 if (!rtas_error_extended(errp)) ··· 753 731 error_type = mce_log->error_type; 754 732 755 733 disposition = mce_handle_err_realmode(disposition, error_type); 756 - 757 - /* 758 - * Enable translation as we will be accessing per-cpu variables 759 - * in save_mce_event() which may fall outside RMO region, also 760 - * leave it enabled because subsequently we will be queuing work 761 - * to workqueues where again per-cpu variables accessed, besides 762 - * fwnmi_release_errinfo() crashes when called in realmode on 763 - * pseries. 764 - * Note: All the realmode handling like flushing SLB entries for 765 - * SLB multihit is done by now. 766 - */ 767 734 out: 768 - msr = mfmsr(); 769 - mtmsr(msr | MSR_IR | MSR_DR); 770 - 771 735 disposition = mce_handle_err_virtmode(regs, errp, mce_log, 772 736 disposition); 773 - 774 - /* 775 - * Queue irq work to log this rtas event later. 776 - * irq_work_queue uses per-cpu variables, so do this in virt 777 - * mode as well. 778 - */ 779 - irq_work_queue(&mce_errlog_process_work); 780 - 781 - mtmsr(msr); 782 - 783 737 return disposition; 784 738 } 785 739 786 740 /* 787 741 * Process MCE rtas errlog event. 788 742 */ 789 - static void mce_process_errlog_event(struct irq_work *work) 743 + void pSeries_machine_check_log_err(void) 790 744 { 791 745 struct rtas_error_log *err; 792 746
+1
arch/powerpc/platforms/pseries/setup.c
··· 1086 1086 .system_reset_exception = pSeries_system_reset_exception, 1087 1087 .machine_check_early = pseries_machine_check_realmode, 1088 1088 .machine_check_exception = pSeries_machine_check_exception, 1089 + .machine_check_log_err = pSeries_machine_check_log_err, 1089 1090 #ifdef CONFIG_KEXEC_CORE 1090 1091 .machine_kexec = pSeries_machine_kexec, 1091 1092 .kexec_cpu_down = pseries_kexec_cpu_down,
+268
arch/powerpc/platforms/pseries/vas-sysfs.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Copyright 2022-23 IBM Corp. 4 + */ 5 + 6 + #define pr_fmt(fmt) "vas: " fmt 7 + 8 + #include <linux/module.h> 9 + #include <linux/kernel.h> 10 + #include <linux/miscdevice.h> 11 + #include <linux/kobject.h> 12 + #include <linux/slab.h> 13 + #include <linux/mm.h> 14 + 15 + #include "vas.h" 16 + 17 + #ifdef CONFIG_SYSFS 18 + static struct kobject *pseries_vas_kobj; 19 + static struct kobject *gzip_caps_kobj; 20 + 21 + struct vas_caps_entry { 22 + struct kobject kobj; 23 + struct vas_cop_feat_caps *caps; 24 + }; 25 + 26 + #define to_caps_entry(entry) container_of(entry, struct vas_caps_entry, kobj) 27 + 28 + /* 29 + * This function is used to get the notification from the drmgr when 30 + * QoS credits are changed. Though receiving the target total QoS 31 + * credits here, get the official QoS capabilities from the hypervisor. 32 + */ 33 + static ssize_t update_total_credits_trigger(struct vas_cop_feat_caps *caps, 34 + const char *buf, size_t count) 35 + { 36 + int err; 37 + u16 creds; 38 + 39 + err = kstrtou16(buf, 0, &creds); 40 + if (!err) 41 + err = vas_reconfig_capabilties(caps->win_type); 42 + 43 + if (err) 44 + return -EINVAL; 45 + 46 + return count; 47 + } 48 + 49 + #define sysfs_caps_entry_read(_name) \ 50 + static ssize_t _name##_show(struct vas_cop_feat_caps *caps, char *buf) \ 51 + { \ 52 + return sprintf(buf, "%d\n", atomic_read(&caps->_name)); \ 53 + } 54 + 55 + struct vas_sysfs_entry { 56 + struct attribute attr; 57 + ssize_t (*show)(struct vas_cop_feat_caps *, char *); 58 + ssize_t (*store)(struct vas_cop_feat_caps *, const char *, size_t); 59 + }; 60 + 61 + #define VAS_ATTR_RO(_name) \ 62 + sysfs_caps_entry_read(_name); \ 63 + static struct vas_sysfs_entry _name##_attribute = __ATTR(_name, \ 64 + 0444, _name##_show, NULL); 65 + 66 + /* 67 + * Create sysfs interface: 68 + * /sys/devices/vas/vas0/gzip/default_capabilities 69 + * This directory contains the following VAS GZIP capabilities 70 + * for the defaule credit type. 71 + * /sys/devices/vas/vas0/gzip/default_capabilities/nr_total_credits 72 + * Total number of default credits assigned to the LPAR which 73 + * can be changed with DLPAR operation. 74 + * /sys/devices/vas/vas0/gzip/default_capabilities/nr_used_credits 75 + * Number of credits used by the user space. One credit will 76 + * be assigned for each window open. 77 + * 78 + * /sys/devices/vas/vas0/gzip/qos_capabilities 79 + * This directory contains the following VAS GZIP capabilities 80 + * for the Quality of Service (QoS) credit type. 81 + * /sys/devices/vas/vas0/gzip/qos_capabilities/nr_total_credits 82 + * Total number of QoS credits assigned to the LPAR. The user 83 + * has to define this value using HMC interface. It can be 84 + * changed dynamically by the user. 85 + * /sys/devices/vas/vas0/gzip/qos_capabilities/nr_used_credits 86 + * Number of credits used by the user space. 87 + * /sys/devices/vas/vas0/gzip/qos_capabilities/update_total_credits 88 + * Update total QoS credits dynamically 89 + */ 90 + 91 + VAS_ATTR_RO(nr_total_credits); 92 + VAS_ATTR_RO(nr_used_credits); 93 + 94 + static struct vas_sysfs_entry update_total_credits_attribute = 95 + __ATTR(update_total_credits, 0200, NULL, update_total_credits_trigger); 96 + 97 + static struct attribute *vas_def_capab_attrs[] = { 98 + &nr_total_credits_attribute.attr, 99 + &nr_used_credits_attribute.attr, 100 + NULL, 101 + }; 102 + 103 + static struct attribute *vas_qos_capab_attrs[] = { 104 + &nr_total_credits_attribute.attr, 105 + &nr_used_credits_attribute.attr, 106 + &update_total_credits_attribute.attr, 107 + NULL, 108 + }; 109 + 110 + static ssize_t vas_type_show(struct kobject *kobj, struct attribute *attr, 111 + char *buf) 112 + { 113 + struct vas_caps_entry *centry; 114 + struct vas_cop_feat_caps *caps; 115 + struct vas_sysfs_entry *entry; 116 + 117 + centry = to_caps_entry(kobj); 118 + caps = centry->caps; 119 + entry = container_of(attr, struct vas_sysfs_entry, attr); 120 + 121 + if (!entry->show) 122 + return -EIO; 123 + 124 + return entry->show(caps, buf); 125 + } 126 + 127 + static ssize_t vas_type_store(struct kobject *kobj, struct attribute *attr, 128 + const char *buf, size_t count) 129 + { 130 + struct vas_caps_entry *centry; 131 + struct vas_cop_feat_caps *caps; 132 + struct vas_sysfs_entry *entry; 133 + 134 + centry = to_caps_entry(kobj); 135 + caps = centry->caps; 136 + entry = container_of(attr, struct vas_sysfs_entry, attr); 137 + if (!entry->store) 138 + return -EIO; 139 + 140 + return entry->store(caps, buf, count); 141 + } 142 + 143 + static void vas_type_release(struct kobject *kobj) 144 + { 145 + struct vas_caps_entry *centry = to_caps_entry(kobj); 146 + kfree(centry); 147 + } 148 + 149 + static const struct sysfs_ops vas_sysfs_ops = { 150 + .show = vas_type_show, 151 + .store = vas_type_store, 152 + }; 153 + 154 + static struct kobj_type vas_def_attr_type = { 155 + .release = vas_type_release, 156 + .sysfs_ops = &vas_sysfs_ops, 157 + .default_attrs = vas_def_capab_attrs, 158 + }; 159 + 160 + static struct kobj_type vas_qos_attr_type = { 161 + .release = vas_type_release, 162 + .sysfs_ops = &vas_sysfs_ops, 163 + .default_attrs = vas_qos_capab_attrs, 164 + }; 165 + 166 + static char *vas_caps_kobj_name(struct vas_caps_entry *centry, 167 + struct kobject **kobj) 168 + { 169 + struct vas_cop_feat_caps *caps = centry->caps; 170 + 171 + if (caps->descriptor == VAS_GZIP_QOS_CAPABILITIES) { 172 + kobject_init(&centry->kobj, &vas_qos_attr_type); 173 + *kobj = gzip_caps_kobj; 174 + return "qos_capabilities"; 175 + } else if (caps->descriptor == VAS_GZIP_DEFAULT_CAPABILITIES) { 176 + kobject_init(&centry->kobj, &vas_def_attr_type); 177 + *kobj = gzip_caps_kobj; 178 + return "default_capabilities"; 179 + } else 180 + return "Unknown"; 181 + } 182 + 183 + /* 184 + * Add feature specific capability dir entry. 185 + * Ex: VDefGzip or VQosGzip 186 + */ 187 + int sysfs_add_vas_caps(struct vas_cop_feat_caps *caps) 188 + { 189 + struct vas_caps_entry *centry; 190 + struct kobject *kobj = NULL; 191 + int ret = 0; 192 + char *name; 193 + 194 + centry = kzalloc(sizeof(*centry), GFP_KERNEL); 195 + if (!centry) 196 + return -ENOMEM; 197 + 198 + centry->caps = caps; 199 + name = vas_caps_kobj_name(centry, &kobj); 200 + 201 + if (kobj) { 202 + ret = kobject_add(&centry->kobj, kobj, "%s", name); 203 + 204 + if (ret) { 205 + pr_err("VAS: sysfs kobject add / event failed %d\n", 206 + ret); 207 + kobject_put(&centry->kobj); 208 + } 209 + } 210 + 211 + return ret; 212 + } 213 + 214 + static struct miscdevice vas_miscdev = { 215 + .minor = MISC_DYNAMIC_MINOR, 216 + .name = "vas", 217 + }; 218 + 219 + /* 220 + * Add VAS and VasCaps (overall capabilities) dir entries. 221 + */ 222 + int __init sysfs_pseries_vas_init(struct vas_all_caps *vas_caps) 223 + { 224 + int ret; 225 + 226 + ret = misc_register(&vas_miscdev); 227 + if (ret < 0) { 228 + pr_err("%s: register vas misc device failed\n", __func__); 229 + return ret; 230 + } 231 + 232 + /* 233 + * The hypervisor does not expose multiple VAS instances, but can 234 + * see multiple VAS instances on PowerNV. So create 'vas0' directory 235 + * on pseries. 236 + */ 237 + pseries_vas_kobj = kobject_create_and_add("vas0", 238 + &vas_miscdev.this_device->kobj); 239 + if (!pseries_vas_kobj) { 240 + pr_err("Failed to create VAS sysfs entry\n"); 241 + return -ENOMEM; 242 + } 243 + 244 + if ((vas_caps->feat_type & VAS_GZIP_QOS_FEAT_BIT) || 245 + (vas_caps->feat_type & VAS_GZIP_DEF_FEAT_BIT)) { 246 + gzip_caps_kobj = kobject_create_and_add("gzip", 247 + pseries_vas_kobj); 248 + if (!gzip_caps_kobj) { 249 + pr_err("Failed to create VAS GZIP capability entry\n"); 250 + kobject_put(pseries_vas_kobj); 251 + return -ENOMEM; 252 + } 253 + } 254 + 255 + return 0; 256 + } 257 + 258 + #else 259 + int sysfs_add_vas_caps(struct vas_cop_feat_caps *caps) 260 + { 261 + return 0; 262 + } 263 + 264 + int __init sysfs_pseries_vas_init(struct vas_all_caps *vas_caps) 265 + { 266 + return 0; 267 + } 268 + #endif
+465 -35
arch/powerpc/platforms/pseries/vas.c
··· 26 26 27 27 static struct vas_all_caps caps_all; 28 28 static bool copypaste_feat; 29 + static struct hv_vas_cop_feat_caps hv_cop_caps; 29 30 30 31 static struct vas_caps vascaps[VAS_MAX_FEAT_TYPE]; 31 32 static DEFINE_MUTEX(vas_pseries_mutex); 33 + static bool migration_in_progress; 32 34 33 35 static long hcall_return_busy_check(long rc) 34 36 { ··· 109 107 static int h_modify_vas_window(struct pseries_vas_window *win) 110 108 { 111 109 long rc; 112 - u32 lpid = mfspr(SPRN_PID); 113 110 114 111 /* 115 112 * AMR value is not supported in Linux VAS implementation. ··· 116 115 */ 117 116 do { 118 117 rc = plpar_hcall_norets(H_MODIFY_VAS_WINDOW, 119 - win->vas_win.winid, lpid, 0, 118 + win->vas_win.winid, win->pid, 0, 120 119 VAS_MOD_WIN_FLAGS, 0); 121 120 122 121 rc = hcall_return_busy_check(rc); ··· 125 124 if (rc == H_SUCCESS) 126 125 return 0; 127 126 128 - pr_err("H_MODIFY_VAS_WINDOW error: %ld, winid %u lpid %u\n", 129 - rc, win->vas_win.winid, lpid); 127 + pr_err("H_MODIFY_VAS_WINDOW error: %ld, winid %u pid %u\n", 128 + rc, win->vas_win.winid, win->pid); 130 129 return -EIO; 131 130 } 132 131 ··· 311 310 312 311 cop_feat_caps = &caps->caps; 313 312 314 - if (atomic_inc_return(&cop_feat_caps->used_lpar_creds) > 315 - atomic_read(&cop_feat_caps->target_lpar_creds)) { 313 + if (atomic_inc_return(&cop_feat_caps->nr_used_credits) > 314 + atomic_read(&cop_feat_caps->nr_total_credits)) { 316 315 pr_err("Credits are not available to allocate window\n"); 317 316 rc = -EINVAL; 318 317 goto out; ··· 339 338 } 340 339 } 341 340 341 + txwin->pid = mfspr(SPRN_PID); 342 + 342 343 /* 343 344 * Allocate / Deallocate window hcalls and setup / free IRQs 344 345 * have to be protected with mutex. ··· 357 354 * same fault IRQ is not freed by the OS before. 358 355 */ 359 356 mutex_lock(&vas_pseries_mutex); 360 - rc = allocate_setup_window(txwin, (u64 *)&domain[0], 357 + if (migration_in_progress) 358 + rc = -EBUSY; 359 + else 360 + rc = allocate_setup_window(txwin, (u64 *)&domain[0], 361 361 cop_feat_caps->win_type); 362 362 mutex_unlock(&vas_pseries_mutex); 363 363 if (rc) ··· 375 369 if (rc) 376 370 goto out_free; 377 371 378 - vas_user_win_add_mm_context(&txwin->vas_win.task_ref); 379 372 txwin->win_type = cop_feat_caps->win_type; 380 373 mutex_lock(&vas_pseries_mutex); 381 - list_add(&txwin->win_list, &caps->list); 374 + /* 375 + * Possible to lose the acquired credit with DLPAR core 376 + * removal after the window is opened. So if there are any 377 + * closed windows (means with lost credits), do not give new 378 + * window to user space. New windows will be opened only 379 + * after the existing windows are reopened when credits are 380 + * available. 381 + */ 382 + if (!caps->nr_close_wins) { 383 + list_add(&txwin->win_list, &caps->list); 384 + caps->nr_open_windows++; 385 + mutex_unlock(&vas_pseries_mutex); 386 + vas_user_win_add_mm_context(&txwin->vas_win.task_ref); 387 + return &txwin->vas_win; 388 + } 382 389 mutex_unlock(&vas_pseries_mutex); 383 390 384 - return &txwin->vas_win; 391 + put_vas_user_win_ref(&txwin->vas_win.task_ref); 392 + rc = -EBUSY; 393 + pr_err("No credit is available to allocate window\n"); 385 394 386 395 out_free: 387 396 /* ··· 406 385 free_irq_setup(txwin); 407 386 h_deallocate_vas_window(txwin->vas_win.winid); 408 387 out: 409 - atomic_dec(&cop_feat_caps->used_lpar_creds); 388 + atomic_dec(&cop_feat_caps->nr_used_credits); 410 389 kfree(txwin); 411 390 return ERR_PTR(rc); 412 391 } ··· 459 438 460 439 caps = &vascaps[win->win_type].caps; 461 440 mutex_lock(&vas_pseries_mutex); 462 - rc = deallocate_free_window(win); 463 - if (rc) { 464 - mutex_unlock(&vas_pseries_mutex); 465 - return rc; 466 - } 441 + /* 442 + * VAS window is already closed in the hypervisor when 443 + * lost the credit or with migration. So just remove the entry 444 + * from the list, remove task references and free vas_window 445 + * struct. 446 + */ 447 + if (!(win->vas_win.status & VAS_WIN_NO_CRED_CLOSE) && 448 + !(win->vas_win.status & VAS_WIN_MIGRATE_CLOSE)) { 449 + rc = deallocate_free_window(win); 450 + if (rc) { 451 + mutex_unlock(&vas_pseries_mutex); 452 + return rc; 453 + } 454 + } else 455 + vascaps[win->win_type].nr_close_wins--; 467 456 468 457 list_del(&win->win_list); 469 - atomic_dec(&caps->used_lpar_creds); 458 + atomic_dec(&caps->nr_used_credits); 459 + vascaps[win->win_type].nr_open_windows--; 470 460 mutex_unlock(&vas_pseries_mutex); 471 461 472 462 put_vas_user_win_ref(&vwin->task_ref); ··· 532 500 memset(vcaps, 0, sizeof(*vcaps)); 533 501 INIT_LIST_HEAD(&vcaps->list); 534 502 503 + vcaps->feat = feat; 535 504 caps = &vcaps->caps; 536 505 537 506 rc = h_query_vas_capabilities(H_QUERY_VAS_CAPABILITIES, feat, ··· 554 521 } 555 522 caps->max_lpar_creds = be16_to_cpu(hv_caps->max_lpar_creds); 556 523 caps->max_win_creds = be16_to_cpu(hv_caps->max_win_creds); 557 - atomic_set(&caps->target_lpar_creds, 524 + atomic_set(&caps->nr_total_credits, 558 525 be16_to_cpu(hv_caps->target_lpar_creds)); 559 526 if (feat == VAS_GZIP_DEF_FEAT) { 560 527 caps->def_lpar_creds = be16_to_cpu(hv_caps->def_lpar_creds); ··· 566 533 } 567 534 } 568 535 536 + rc = sysfs_add_vas_caps(caps); 537 + if (rc) 538 + return rc; 539 + 569 540 copypaste_feat = true; 570 541 571 542 return 0; 572 543 } 573 544 545 + /* 546 + * VAS windows can be closed due to lost credits when the core is 547 + * removed. So reopen them if credits are available due to DLPAR 548 + * core add and set the window active status. When NX sees the page 549 + * fault on the unmapped paste address, the kernel handles the fault 550 + * by setting the remapping to new paste address if the window is 551 + * active. 552 + */ 553 + static int reconfig_open_windows(struct vas_caps *vcaps, int creds, 554 + bool migrate) 555 + { 556 + long domain[PLPAR_HCALL9_BUFSIZE] = {VAS_DEFAULT_DOMAIN_ID}; 557 + struct vas_cop_feat_caps *caps = &vcaps->caps; 558 + struct pseries_vas_window *win = NULL, *tmp; 559 + int rc, mv_ents = 0; 560 + int flag; 561 + 562 + /* 563 + * Nothing to do if there are no closed windows. 564 + */ 565 + if (!vcaps->nr_close_wins) 566 + return 0; 567 + 568 + /* 569 + * For the core removal, the hypervisor reduces the credits 570 + * assigned to the LPAR and the kernel closes VAS windows 571 + * in the hypervisor depends on reduced credits. The kernel 572 + * uses LIFO (the last windows that are opened will be closed 573 + * first) and expects to open in the same order when credits 574 + * are available. 575 + * For example, 40 windows are closed when the LPAR lost 2 cores 576 + * (dedicated). If 1 core is added, this LPAR can have 20 more 577 + * credits. It means the kernel can reopen 20 windows. So move 578 + * 20 entries in the VAS windows lost and reopen next 20 windows. 579 + * For partition migration, reopen all windows that are closed 580 + * during resume. 581 + */ 582 + if ((vcaps->nr_close_wins > creds) && !migrate) 583 + mv_ents = vcaps->nr_close_wins - creds; 584 + 585 + list_for_each_entry_safe(win, tmp, &vcaps->list, win_list) { 586 + if (!mv_ents) 587 + break; 588 + 589 + mv_ents--; 590 + } 591 + 592 + /* 593 + * Open windows if they are closed only with migration or 594 + * DLPAR (lost credit) before. 595 + */ 596 + if (migrate) 597 + flag = VAS_WIN_MIGRATE_CLOSE; 598 + else 599 + flag = VAS_WIN_NO_CRED_CLOSE; 600 + 601 + list_for_each_entry_safe_from(win, tmp, &vcaps->list, win_list) { 602 + /* 603 + * This window is closed with DLPAR and migration events. 604 + * So reopen the window with the last event. 605 + * The user space is not suspended with the current 606 + * migration notifier. So the user space can issue DLPAR 607 + * CPU hotplug while migration in progress. In this case 608 + * this window will be opened with the last event. 609 + */ 610 + if ((win->vas_win.status & VAS_WIN_NO_CRED_CLOSE) && 611 + (win->vas_win.status & VAS_WIN_MIGRATE_CLOSE)) { 612 + win->vas_win.status &= ~flag; 613 + continue; 614 + } 615 + 616 + /* 617 + * Nothing to do on this window if it is not closed 618 + * with this flag 619 + */ 620 + if (!(win->vas_win.status & flag)) 621 + continue; 622 + 623 + rc = allocate_setup_window(win, (u64 *)&domain[0], 624 + caps->win_type); 625 + if (rc) 626 + return rc; 627 + 628 + rc = h_modify_vas_window(win); 629 + if (rc) 630 + goto out; 631 + 632 + mutex_lock(&win->vas_win.task_ref.mmap_mutex); 633 + /* 634 + * Set window status to active 635 + */ 636 + win->vas_win.status &= ~flag; 637 + mutex_unlock(&win->vas_win.task_ref.mmap_mutex); 638 + win->win_type = caps->win_type; 639 + if (!--vcaps->nr_close_wins) 640 + break; 641 + } 642 + 643 + return 0; 644 + out: 645 + /* 646 + * Window modify HCALL failed. So close the window to the 647 + * hypervisor and return. 648 + */ 649 + free_irq_setup(win); 650 + h_deallocate_vas_window(win->vas_win.winid); 651 + return rc; 652 + } 653 + 654 + /* 655 + * The hypervisor reduces the available credits if the LPAR lost core. It 656 + * means the excessive windows should not be active and the user space 657 + * should not be using these windows to send compression requests to NX. 658 + * So the kernel closes the excessive windows and unmap the paste address 659 + * such that the user space receives paste instruction failure. Then up to 660 + * the user space to fall back to SW compression and manage with the 661 + * existing windows. 662 + */ 663 + static int reconfig_close_windows(struct vas_caps *vcap, int excess_creds, 664 + bool migrate) 665 + { 666 + struct pseries_vas_window *win, *tmp; 667 + struct vas_user_win_ref *task_ref; 668 + struct vm_area_struct *vma; 669 + int rc = 0, flag; 670 + 671 + if (migrate) 672 + flag = VAS_WIN_MIGRATE_CLOSE; 673 + else 674 + flag = VAS_WIN_NO_CRED_CLOSE; 675 + 676 + list_for_each_entry_safe(win, tmp, &vcap->list, win_list) { 677 + /* 678 + * This window is already closed due to lost credit 679 + * or for migration before. Go for next window. 680 + * For migration, nothing to do since this window 681 + * closed for DLPAR and will be reopened even on 682 + * the destination system with other DLPAR operation. 683 + */ 684 + if ((win->vas_win.status & VAS_WIN_MIGRATE_CLOSE) || 685 + (win->vas_win.status & VAS_WIN_NO_CRED_CLOSE)) { 686 + win->vas_win.status |= flag; 687 + continue; 688 + } 689 + 690 + task_ref = &win->vas_win.task_ref; 691 + mutex_lock(&task_ref->mmap_mutex); 692 + vma = task_ref->vma; 693 + /* 694 + * Number of available credits are reduced, So select 695 + * and close windows. 696 + */ 697 + win->vas_win.status |= flag; 698 + 699 + mmap_write_lock(task_ref->mm); 700 + /* 701 + * vma is set in the original mapping. But this mapping 702 + * is done with mmap() after the window is opened with ioctl. 703 + * so we may not see the original mapping if the core remove 704 + * is done before the original mmap() and after the ioctl. 705 + */ 706 + if (vma) 707 + zap_page_range(vma, vma->vm_start, 708 + vma->vm_end - vma->vm_start); 709 + 710 + mmap_write_unlock(task_ref->mm); 711 + mutex_unlock(&task_ref->mmap_mutex); 712 + /* 713 + * Close VAS window in the hypervisor, but do not 714 + * free vas_window struct since it may be reused 715 + * when the credit is available later (DLPAR with 716 + * adding cores). This struct will be used 717 + * later when the process issued with close(FD). 718 + */ 719 + rc = deallocate_free_window(win); 720 + /* 721 + * This failure is from the hypervisor. 722 + * No way to stop migration for these failures. 723 + * So ignore error and continue closing other windows. 724 + */ 725 + if (rc && !migrate) 726 + return rc; 727 + 728 + vcap->nr_close_wins++; 729 + 730 + /* 731 + * For migration, do not depend on lpar_creds in case if 732 + * mismatch with the hypervisor value (should not happen). 733 + * So close all active windows in the list and will be 734 + * reopened windows based on the new lpar_creds on the 735 + * destination system during resume. 736 + */ 737 + if (!migrate && !--excess_creds) 738 + break; 739 + } 740 + 741 + return 0; 742 + } 743 + 744 + /* 745 + * Get new VAS capabilities when the core add/removal configuration 746 + * changes. Reconfig window configurations based on the credits 747 + * availability from this new capabilities. 748 + */ 749 + int vas_reconfig_capabilties(u8 type) 750 + { 751 + struct vas_cop_feat_caps *caps; 752 + int old_nr_creds, new_nr_creds; 753 + struct vas_caps *vcaps; 754 + int rc = 0, nr_active_wins; 755 + 756 + if (type >= VAS_MAX_FEAT_TYPE) { 757 + pr_err("Invalid credit type %d\n", type); 758 + return -EINVAL; 759 + } 760 + 761 + vcaps = &vascaps[type]; 762 + caps = &vcaps->caps; 763 + 764 + mutex_lock(&vas_pseries_mutex); 765 + rc = h_query_vas_capabilities(H_QUERY_VAS_CAPABILITIES, vcaps->feat, 766 + (u64)virt_to_phys(&hv_cop_caps)); 767 + if (rc) 768 + goto out; 769 + 770 + new_nr_creds = be16_to_cpu(hv_cop_caps.target_lpar_creds); 771 + 772 + old_nr_creds = atomic_read(&caps->nr_total_credits); 773 + 774 + atomic_set(&caps->nr_total_credits, new_nr_creds); 775 + /* 776 + * The total number of available credits may be decreased or 777 + * inceased with DLPAR operation. Means some windows have to be 778 + * closed / reopened. Hold the vas_pseries_mutex so that the 779 + * the user space can not open new windows. 780 + */ 781 + if (old_nr_creds < new_nr_creds) { 782 + /* 783 + * If the existing target credits is less than the new 784 + * target, reopen windows if they are closed due to 785 + * the previous DLPAR (core removal). 786 + */ 787 + rc = reconfig_open_windows(vcaps, new_nr_creds - old_nr_creds, 788 + false); 789 + } else { 790 + /* 791 + * # active windows is more than new LPAR available 792 + * credits. So close the excessive windows. 793 + * On pseries, each window will have 1 credit. 794 + */ 795 + nr_active_wins = vcaps->nr_open_windows - vcaps->nr_close_wins; 796 + if (nr_active_wins > new_nr_creds) 797 + rc = reconfig_close_windows(vcaps, 798 + nr_active_wins - new_nr_creds, 799 + false); 800 + } 801 + 802 + out: 803 + mutex_unlock(&vas_pseries_mutex); 804 + return rc; 805 + } 806 + /* 807 + * Total number of default credits available (target_credits) 808 + * in LPAR depends on number of cores configured. It varies based on 809 + * whether processors are in shared mode or dedicated mode. 810 + * Get the notifier when CPU configuration is changed with DLPAR 811 + * operation so that get the new target_credits (vas default capabilities) 812 + * and then update the existing windows usage if needed. 813 + */ 814 + static int pseries_vas_notifier(struct notifier_block *nb, 815 + unsigned long action, void *data) 816 + { 817 + struct of_reconfig_data *rd = data; 818 + struct device_node *dn = rd->dn; 819 + const __be32 *intserv = NULL; 820 + int len, rc = 0; 821 + 822 + if ((action == OF_RECONFIG_ATTACH_NODE) || 823 + (action == OF_RECONFIG_DETACH_NODE)) 824 + intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", 825 + &len); 826 + /* 827 + * Processor config is not changed 828 + */ 829 + if (!intserv) 830 + return NOTIFY_OK; 831 + 832 + rc = vas_reconfig_capabilties(VAS_GZIP_DEF_FEAT_TYPE); 833 + if (rc) 834 + pr_err("Failed reconfig VAS capabilities with DLPAR\n"); 835 + 836 + return rc; 837 + } 838 + 839 + static struct notifier_block pseries_vas_nb = { 840 + .notifier_call = pseries_vas_notifier, 841 + }; 842 + 843 + /* 844 + * For LPM, all windows have to be closed on the source partition 845 + * before migration and reopen them on the destination partition 846 + * after migration. So closing windows during suspend and 847 + * reopen them during resume. 848 + */ 849 + int vas_migration_handler(int action) 850 + { 851 + struct vas_cop_feat_caps *caps; 852 + int old_nr_creds, new_nr_creds = 0; 853 + struct vas_caps *vcaps; 854 + int i, rc = 0; 855 + 856 + /* 857 + * NX-GZIP is not enabled. Nothing to do for migration. 858 + */ 859 + if (!copypaste_feat) 860 + return rc; 861 + 862 + mutex_lock(&vas_pseries_mutex); 863 + 864 + if (action == VAS_SUSPEND) 865 + migration_in_progress = true; 866 + else 867 + migration_in_progress = false; 868 + 869 + for (i = 0; i < VAS_MAX_FEAT_TYPE; i++) { 870 + vcaps = &vascaps[i]; 871 + caps = &vcaps->caps; 872 + old_nr_creds = atomic_read(&caps->nr_total_credits); 873 + 874 + rc = h_query_vas_capabilities(H_QUERY_VAS_CAPABILITIES, 875 + vcaps->feat, 876 + (u64)virt_to_phys(&hv_cop_caps)); 877 + if (!rc) { 878 + new_nr_creds = be16_to_cpu(hv_cop_caps.target_lpar_creds); 879 + /* 880 + * Should not happen. But incase print messages, close 881 + * all windows in the list during suspend and reopen 882 + * windows based on new lpar_creds on the destination 883 + * system. 884 + */ 885 + if (old_nr_creds != new_nr_creds) { 886 + pr_err("Target credits mismatch with the hypervisor\n"); 887 + pr_err("state(%d): lpar creds: %d HV lpar creds: %d\n", 888 + action, old_nr_creds, new_nr_creds); 889 + pr_err("Used creds: %d, Active creds: %d\n", 890 + atomic_read(&caps->nr_used_credits), 891 + vcaps->nr_open_windows - vcaps->nr_close_wins); 892 + } 893 + } else { 894 + pr_err("state(%d): Get VAS capabilities failed with %d\n", 895 + action, rc); 896 + /* 897 + * We can not stop migration with the current lpm 898 + * implementation. So continue closing all windows in 899 + * the list (during suspend) and return without 900 + * opening windows (during resume) if VAS capabilities 901 + * HCALL failed. 902 + */ 903 + if (action == VAS_RESUME) 904 + goto out; 905 + } 906 + 907 + switch (action) { 908 + case VAS_SUSPEND: 909 + rc = reconfig_close_windows(vcaps, vcaps->nr_open_windows, 910 + true); 911 + break; 912 + case VAS_RESUME: 913 + atomic_set(&caps->nr_total_credits, new_nr_creds); 914 + rc = reconfig_open_windows(vcaps, new_nr_creds, true); 915 + break; 916 + default: 917 + /* should not happen */ 918 + pr_err("Invalid migration action %d\n", action); 919 + rc = -EINVAL; 920 + goto out; 921 + } 922 + 923 + /* 924 + * Ignore errors during suspend and return for resume. 925 + */ 926 + if (rc && (action == VAS_RESUME)) 927 + goto out; 928 + } 929 + 930 + out: 931 + mutex_unlock(&vas_pseries_mutex); 932 + return rc; 933 + } 934 + 574 935 static int __init pseries_vas_init(void) 575 936 { 576 - struct hv_vas_cop_feat_caps *hv_cop_caps; 577 937 struct hv_vas_all_caps *hv_caps; 578 - int rc; 938 + int rc = 0; 579 939 580 940 /* 581 941 * Linux supports user space COPY/PASTE only with Radix ··· 992 566 caps_all.descriptor = be64_to_cpu(hv_caps->descriptor); 993 567 caps_all.feat_type = be64_to_cpu(hv_caps->feat_type); 994 568 995 - hv_cop_caps = kmalloc(sizeof(*hv_cop_caps), GFP_KERNEL); 996 - if (!hv_cop_caps) { 997 - rc = -ENOMEM; 998 - goto out; 999 - } 569 + sysfs_pseries_vas_init(&caps_all); 570 + 1000 571 /* 1001 572 * QOS capabilities available 1002 573 */ 1003 574 if (caps_all.feat_type & VAS_GZIP_QOS_FEAT_BIT) { 1004 575 rc = get_vas_capabilities(VAS_GZIP_QOS_FEAT, 1005 - VAS_GZIP_QOS_FEAT_TYPE, hv_cop_caps); 576 + VAS_GZIP_QOS_FEAT_TYPE, &hv_cop_caps); 1006 577 1007 578 if (rc) 1008 - goto out_cop; 579 + goto out; 1009 580 } 1010 581 /* 1011 582 * Default capabilities available 1012 583 */ 1013 - if (caps_all.feat_type & VAS_GZIP_DEF_FEAT_BIT) { 584 + if (caps_all.feat_type & VAS_GZIP_DEF_FEAT_BIT) 1014 585 rc = get_vas_capabilities(VAS_GZIP_DEF_FEAT, 1015 - VAS_GZIP_DEF_FEAT_TYPE, hv_cop_caps); 1016 - if (rc) 1017 - goto out_cop; 586 + VAS_GZIP_DEF_FEAT_TYPE, &hv_cop_caps); 587 + 588 + if (!rc && copypaste_feat) { 589 + if (firmware_has_feature(FW_FEATURE_LPAR)) 590 + of_reconfig_notifier_register(&pseries_vas_nb); 591 + 592 + pr_info("GZIP feature is available\n"); 593 + } else { 594 + /* 595 + * Should not happen, but only when get default 596 + * capabilities HCALL failed. So disable copy paste 597 + * feature. 598 + */ 599 + copypaste_feat = false; 1018 600 } 1019 601 1020 - pr_info("GZIP feature is available\n"); 1021 - 1022 - out_cop: 1023 - kfree(hv_cop_caps); 1024 602 out: 1025 603 kfree(hv_caps); 1026 604 return rc;
+27 -3
arch/powerpc/platforms/pseries/vas.h
··· 30 30 #define VAS_COPY_PASTE_USER_MODE 0x00000001 31 31 #define VAS_COP_OP_USER_MODE 0x00000010 32 32 33 + #define VAS_GZIP_QOS_CAPABILITIES 0x56516F73477A6970 34 + #define VAS_GZIP_DEFAULT_CAPABILITIES 0x56446566477A6970 35 + 36 + enum vas_migrate_action { 37 + VAS_SUSPEND, 38 + VAS_RESUME, 39 + }; 40 + 33 41 /* 34 42 * Co-processor feature - GZIP QoS windows or GZIP default windows 35 43 */ ··· 80 72 }; 81 73 /* Total LPAR available credits. Can be different from max LPAR */ 82 74 /* credits due to DLPAR operation */ 83 - atomic_t target_lpar_creds; 84 - atomic_t used_lpar_creds; /* Used credits so far */ 85 - u16 avail_lpar_creds; /* Remaining available credits */ 75 + atomic_t nr_total_credits; /* Total credits assigned to LPAR */ 76 + atomic_t nr_used_credits; /* Used credits so far */ 86 77 }; 87 78 88 79 /* ··· 91 84 struct vas_caps { 92 85 struct vas_cop_feat_caps caps; 93 86 struct list_head list; /* List of open windows */ 87 + int nr_close_wins; /* closed windows in the hypervisor for DLPAR */ 88 + int nr_open_windows; /* Number of successful open windows */ 89 + u8 feat; /* Feature type */ 94 90 }; 95 91 96 92 /* ··· 125 115 u64 domain[6]; /* Associativity domain Ids */ 126 116 /* this window is allocated */ 127 117 u64 util; 118 + u32 pid; /* PID associated with this window */ 128 119 129 120 /* List of windows opened which is used for LPM */ 130 121 struct list_head win_list; ··· 133 122 char *name; 134 123 int fault_virq; 135 124 }; 125 + 126 + int sysfs_add_vas_caps(struct vas_cop_feat_caps *caps); 127 + int vas_reconfig_capabilties(u8 type); 128 + int __init sysfs_pseries_vas_init(struct vas_all_caps *vas_caps); 129 + 130 + #ifdef CONFIG_PPC_VAS 131 + int vas_migration_handler(int action); 132 + #else 133 + static inline int vas_migration_handler(int action) 134 + { 135 + return 0; 136 + } 137 + #endif 136 138 #endif /* _VAS_H */
+2 -2
arch/powerpc/sysdev/fsl_gtm.c
··· 86 86 */ 87 87 struct gtm_timer *gtm_get_timer16(void) 88 88 { 89 - struct gtm *gtm = NULL; 89 + struct gtm *gtm; 90 90 int i; 91 91 92 92 list_for_each_entry(gtm, &gtms, list_node) { ··· 103 103 spin_unlock_irq(&gtm->lock); 104 104 } 105 105 106 - if (gtm) 106 + if (!list_empty(&gtms)) 107 107 return ERR_PTR(-EBUSY); 108 108 return ERR_PTR(-ENODEV); 109 109 }
+1 -3
arch/powerpc/sysdev/mpic.c
··· 1404 1404 * with device trees generated by older versions of QEMU. 1405 1405 * fsl_version will be zero if MPIC_FSL is not set. 1406 1406 */ 1407 - if (fsl_version < 0x400 && (flags & MPIC_ENABLE_COREINT)) { 1408 - WARN_ON(ppc_md.get_irq != mpic_get_coreint_irq); 1407 + if (fsl_version < 0x400 && (flags & MPIC_ENABLE_COREINT)) 1409 1408 ppc_md.get_irq = mpic_get_irq; 1410 - } 1411 1409 1412 1410 /* Reset */ 1413 1411
+4 -4
arch/powerpc/sysdev/xive/common.c
··· 1708 1708 static int __init xive_off(char *arg) 1709 1709 { 1710 1710 xive_cmdline_disabled = true; 1711 - return 0; 1711 + return 1; 1712 1712 } 1713 1713 __setup("xive=off", xive_off); 1714 1714 1715 1715 static int __init xive_store_eoi_cmdline(char *arg) 1716 1716 { 1717 1717 if (!arg) 1718 - return -EINVAL; 1718 + return 1; 1719 1719 1720 1720 if (strncmp(arg, "off", 3) == 0) { 1721 1721 pr_info("StoreEOI disabled on kernel command line\n"); 1722 1722 xive_store_eoi = false; 1723 1723 } 1724 - return 0; 1724 + return 1; 1725 1725 } 1726 1726 __setup("xive.store-eoi=", xive_store_eoi_cmdline); 1727 1727 ··· 1791 1791 if (xive_ops->debug_show) 1792 1792 xive_ops->debug_show(m, private); 1793 1793 1794 - for_each_possible_cpu(cpu) 1794 + for_each_online_cpu(cpu) 1795 1795 xive_debug_show_ipi(m, cpu); 1796 1796 return 0; 1797 1797 }
+28 -8
arch/powerpc/sysdev/xive/spapr.c
··· 67 67 return 0; 68 68 } 69 69 70 + static void xive_irq_bitmap_remove_all(void) 71 + { 72 + struct xive_irq_bitmap *xibm, *tmp; 73 + 74 + list_for_each_entry_safe(xibm, tmp, &xive_irq_bitmaps, list) { 75 + list_del(&xibm->list); 76 + kfree(xibm->bitmap); 77 + kfree(xibm); 78 + } 79 + } 80 + 70 81 static int __xive_irq_bitmap_alloc(struct xive_irq_bitmap *xibm) 71 82 { 72 83 int irq; ··· 814 803 u32 val; 815 804 u32 len; 816 805 const __be32 *reg; 817 - int i; 806 + int i, err; 818 807 819 808 if (xive_spapr_disabled()) 820 809 return false; ··· 839 828 } 840 829 841 830 if (!xive_get_max_prio(&max_prio)) 842 - return false; 831 + goto err_unmap; 843 832 844 833 /* Feed the IRQ number allocator with the ranges given in the DT */ 845 834 reg = of_get_property(np, "ibm,xive-lisn-ranges", &len); 846 835 if (!reg) { 847 836 pr_err("Failed to read 'ibm,xive-lisn-ranges' property\n"); 848 - return false; 837 + goto err_unmap; 849 838 } 850 839 851 840 if (len % (2 * sizeof(u32)) != 0) { 852 841 pr_err("invalid 'ibm,xive-lisn-ranges' property\n"); 853 - return false; 842 + goto err_unmap; 854 843 } 855 844 856 - for (i = 0; i < len / (2 * sizeof(u32)); i++, reg += 2) 857 - xive_irq_bitmap_add(be32_to_cpu(reg[0]), 858 - be32_to_cpu(reg[1])); 845 + for (i = 0; i < len / (2 * sizeof(u32)); i++, reg += 2) { 846 + err = xive_irq_bitmap_add(be32_to_cpu(reg[0]), 847 + be32_to_cpu(reg[1])); 848 + if (err < 0) 849 + goto err_mem_free; 850 + } 859 851 860 852 /* Iterate the EQ sizes and pick one */ 861 853 of_property_for_each_u32(np, "ibm,xive-eq-sizes", prop, reg, val) { ··· 869 855 870 856 /* Initialize XIVE core with our backend */ 871 857 if (!xive_core_init(np, &xive_spapr_ops, tima, TM_QW1_OS, max_prio)) 872 - return false; 858 + goto err_mem_free; 873 859 874 860 pr_info("Using %dkB queues\n", 1 << (xive_queue_shift - 10)); 875 861 return true; 862 + 863 + err_mem_free: 864 + xive_irq_bitmap_remove_all(); 865 + err_unmap: 866 + iounmap(tima); 867 + return false; 876 868 } 877 869 878 870 machine_arch_initcall(pseries, xive_core_debug_init);
+1 -6
arch/powerpc/tools/relocs_check.sh
··· 39 39 # R_PPC_NONE 40 40 grep -F -w -v 'R_PPC64_RELATIVE 41 41 R_PPC64_NONE 42 + R_PPC64_UADDR64 42 43 R_PPC_ADDR16_LO 43 44 R_PPC_ADDR16_HI 44 45 R_PPC_ADDR16_HA ··· 55 54 num_bad=$(echo "$bad_relocs" | wc -l) 56 55 echo "WARNING: $num_bad bad relocations" 57 56 echo "$bad_relocs" 58 - 59 - # If we see this type of relocation it's an idication that 60 - # we /may/ be using an old version of binutils. 61 - if echo "$bad_relocs" | grep -q -F -w R_PPC64_UADDR64; then 62 - echo "WARNING: You need at least binutils >= 2.19 to build a CONFIG_RELOCATABLE kernel" 63 - fi
+1 -1
drivers/macintosh/macio_asic.c
··· 756 756 757 757 /* pci driver glue; this is a "new style" PCI driver module */ 758 758 static struct pci_driver macio_pci_driver = { 759 - .name = (char *) "macio", 759 + .name = "macio", 760 760 .id_table = pci_ids, 761 761 762 762 .probe = macio_pci_probe,
+1
drivers/macintosh/via-cuda.c
··· 21 21 #ifdef CONFIG_PPC 22 22 #include <asm/prom.h> 23 23 #include <asm/machdep.h> 24 + #include <asm/pmac_feature.h> 24 25 #else 25 26 #include <asm/macintosh.h> 26 27 #include <asm/macints.h>
+1
drivers/misc/lkdtm/core.c
··· 149 149 CRASHTYPE(WRITE_RO), 150 150 CRASHTYPE(WRITE_RO_AFTER_INIT), 151 151 CRASHTYPE(WRITE_KERN), 152 + CRASHTYPE(WRITE_OPD), 152 153 CRASHTYPE(REFCOUNT_INC_OVERFLOW), 153 154 CRASHTYPE(REFCOUNT_ADD_OVERFLOW), 154 155 CRASHTYPE(REFCOUNT_INC_NOT_ZERO_OVERFLOW),
+1
drivers/misc/lkdtm/lkdtm.h
··· 106 106 void lkdtm_WRITE_RO(void); 107 107 void lkdtm_WRITE_RO_AFTER_INIT(void); 108 108 void lkdtm_WRITE_KERN(void); 109 + void lkdtm_WRITE_OPD(void); 109 110 void lkdtm_EXEC_DATA(void); 110 111 void lkdtm_EXEC_STACK(void); 111 112 void lkdtm_EXEC_KMALLOC(void);
+57 -14
drivers/misc/lkdtm/perms.c
··· 10 10 #include <linux/mman.h> 11 11 #include <linux/uaccess.h> 12 12 #include <asm/cacheflush.h> 13 + #include <asm/sections.h> 13 14 14 15 /* Whether or not to fill the target memory area with do_nothing(). */ 15 16 #define CODE_WRITE true ··· 22 21 /* This is non-const, so it will end up in the .data section. */ 23 22 static u8 data_area[EXEC_SIZE]; 24 23 25 - /* This is cost, so it will end up in the .rodata section. */ 24 + /* This is const, so it will end up in the .rodata section. */ 26 25 static const unsigned long rodata = 0xAA55AA55; 27 26 28 27 /* This is marked __ro_after_init, so it should ultimately be .rodata. */ ··· 32 31 * This just returns to the caller. It is designed to be copied into 33 32 * non-executable memory regions. 34 33 */ 35 - static void do_nothing(void) 34 + static noinline void do_nothing(void) 36 35 { 37 36 return; 38 37 } 39 38 40 39 /* Must immediately follow do_nothing for size calculuations to work out. */ 41 - static void do_overwritten(void) 40 + static noinline void do_overwritten(void) 42 41 { 43 42 pr_info("do_overwritten wasn't overwritten!\n"); 44 43 return; 45 44 } 46 45 46 + static noinline void do_almost_nothing(void) 47 + { 48 + pr_info("do_nothing was hijacked!\n"); 49 + } 50 + 51 + static void *setup_function_descriptor(func_desc_t *fdesc, void *dst) 52 + { 53 + if (!have_function_descriptors()) 54 + return dst; 55 + 56 + memcpy(fdesc, do_nothing, sizeof(*fdesc)); 57 + fdesc->addr = (unsigned long)dst; 58 + barrier(); 59 + 60 + return fdesc; 61 + } 62 + 47 63 static noinline void execute_location(void *dst, bool write) 48 64 { 49 - void (*func)(void) = dst; 65 + void (*func)(void); 66 + func_desc_t fdesc; 67 + void *do_nothing_text = dereference_function_descriptor(do_nothing); 50 68 51 - pr_info("attempting ok execution at %px\n", do_nothing); 69 + pr_info("attempting ok execution at %px\n", do_nothing_text); 52 70 do_nothing(); 53 71 54 72 if (write == CODE_WRITE) { 55 - memcpy(dst, do_nothing, EXEC_SIZE); 73 + memcpy(dst, do_nothing_text, EXEC_SIZE); 56 74 flush_icache_range((unsigned long)dst, 57 75 (unsigned long)dst + EXEC_SIZE); 58 76 } 59 - pr_info("attempting bad execution at %px\n", func); 77 + pr_info("attempting bad execution at %px\n", dst); 78 + func = setup_function_descriptor(&fdesc, dst); 60 79 func(); 61 80 pr_err("FAIL: func returned\n"); 62 81 } ··· 86 65 int copied; 87 66 88 67 /* Intentionally crossing kernel/user memory boundary. */ 89 - void (*func)(void) = dst; 68 + void (*func)(void); 69 + func_desc_t fdesc; 70 + void *do_nothing_text = dereference_function_descriptor(do_nothing); 90 71 91 - pr_info("attempting ok execution at %px\n", do_nothing); 72 + pr_info("attempting ok execution at %px\n", do_nothing_text); 92 73 do_nothing(); 93 74 94 - copied = access_process_vm(current, (unsigned long)dst, do_nothing, 75 + copied = access_process_vm(current, (unsigned long)dst, do_nothing_text, 95 76 EXEC_SIZE, FOLL_WRITE); 96 77 if (copied < EXEC_SIZE) 97 78 return; 98 - pr_info("attempting bad execution at %px\n", func); 79 + pr_info("attempting bad execution at %px\n", dst); 80 + func = setup_function_descriptor(&fdesc, dst); 99 81 func(); 100 82 pr_err("FAIL: func returned\n"); 101 83 } ··· 137 113 size_t size; 138 114 volatile unsigned char *ptr; 139 115 140 - size = (unsigned long)do_overwritten - (unsigned long)do_nothing; 141 - ptr = (unsigned char *)do_overwritten; 116 + size = (unsigned long)dereference_function_descriptor(do_overwritten) - 117 + (unsigned long)dereference_function_descriptor(do_nothing); 118 + ptr = dereference_function_descriptor(do_overwritten); 142 119 143 120 pr_info("attempting bad %zu byte write at %px\n", size, ptr); 144 121 memcpy((void *)ptr, (unsigned char *)do_nothing, size); ··· 147 122 pr_err("FAIL: survived bad write\n"); 148 123 149 124 do_overwritten(); 125 + } 126 + 127 + void lkdtm_WRITE_OPD(void) 128 + { 129 + size_t size = sizeof(func_desc_t); 130 + void (*func)(void) = do_nothing; 131 + 132 + if (!have_function_descriptors()) { 133 + pr_info("XFAIL: Platform doesn't use function descriptors.\n"); 134 + return; 135 + } 136 + pr_info("attempting bad %zu bytes write at %px\n", size, do_nothing); 137 + memcpy(do_nothing, do_almost_nothing, size); 138 + pr_err("FAIL: survived bad write\n"); 139 + 140 + asm("" : "=m"(func)); 141 + func(); 150 142 } 151 143 152 144 void lkdtm_EXEC_DATA(void) ··· 193 151 194 152 void lkdtm_EXEC_RODATA(void) 195 153 { 196 - execute_location(lkdtm_rodata_do_nothing, CODE_AS_IS); 154 + execute_location(dereference_function_descriptor(lkdtm_rodata_do_nothing), 155 + CODE_AS_IS); 197 156 } 198 157 199 158 void lkdtm_EXEC_USERSPACE(void)
+1
drivers/pci/hotplug/rpadlpar_core.c
··· 478 478 module_init(rpadlpar_io_init); 479 479 module_exit(rpadlpar_io_exit); 480 480 MODULE_LICENSE("GPL"); 481 + MODULE_DESCRIPTION("RPA Dynamic Logical Partitioning driver for I/O slots");
+14 -1
include/asm-generic/sections.h
··· 59 59 extern __visible const void __nosave_begin, __nosave_end; 60 60 61 61 /* Function descriptor handling (if any). Override in asm/sections.h */ 62 - #ifndef dereference_function_descriptor 62 + #ifdef CONFIG_HAVE_FUNCTION_DESCRIPTORS 63 + void *dereference_function_descriptor(void *ptr); 64 + void *dereference_kernel_function_descriptor(void *ptr); 65 + #else 63 66 #define dereference_function_descriptor(p) ((void *)(p)) 64 67 #define dereference_kernel_function_descriptor(p) ((void *)(p)) 68 + 69 + /* An address is simply the address of the function. */ 70 + typedef struct { 71 + unsigned long addr; 72 + } func_desc_t; 65 73 #endif 74 + 75 + static inline bool have_function_descriptors(void) 76 + { 77 + return IS_ENABLED(CONFIG_HAVE_FUNCTION_DESCRIPTORS); 78 + } 66 79 67 80 /** 68 81 * memory_contains - checks if an object is contained within a memory region
+1 -1
include/linux/kallsyms.h
··· 48 48 49 49 static inline void *dereference_symbol_descriptor(void *ptr) 50 50 { 51 - #ifdef HAVE_DEREFERENCE_FUNCTION_DESCRIPTOR 51 + #ifdef CONFIG_HAVE_FUNCTION_DESCRIPTORS 52 52 struct module *mod; 53 53 54 54 ptr = dereference_kernel_function_descriptor(ptr);
+23 -1
kernel/extable.c
··· 3 3 Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM. 4 4 5 5 */ 6 + #include <linux/elf.h> 6 7 #include <linux/ftrace.h> 7 8 #include <linux/memory.h> 8 9 #include <linux/extable.h> ··· 133 132 } 134 133 135 134 /* 136 - * On some architectures (PPC64, IA64) function pointers 135 + * On some architectures (PPC64, IA64, PARISC) function pointers 137 136 * are actually only tokens to some data that then holds the 138 137 * real function address. As a result, to find if a function 139 138 * pointer is part of the kernel text, we need to do some 140 139 * special dereferencing first. 141 140 */ 141 + #ifdef CONFIG_HAVE_FUNCTION_DESCRIPTORS 142 + void *dereference_function_descriptor(void *ptr) 143 + { 144 + func_desc_t *desc = ptr; 145 + void *p; 146 + 147 + if (!get_kernel_nofault(p, (void *)&desc->addr)) 148 + ptr = p; 149 + return ptr; 150 + } 151 + EXPORT_SYMBOL_GPL(dereference_function_descriptor); 152 + 153 + void *dereference_kernel_function_descriptor(void *ptr) 154 + { 155 + if (ptr < (void *)__start_opd || ptr >= (void *)__end_opd) 156 + return ptr; 157 + 158 + return dereference_function_descriptor(ptr); 159 + } 160 + #endif 161 + 142 162 int func_ptr_is_kernel_text(void *ptr) 143 163 { 144 164 unsigned long addr;
+2 -2
kernel/livepatch/core.c
··· 190 190 return -EINVAL; 191 191 } 192 192 193 - static int klp_resolve_symbols(Elf64_Shdr *sechdrs, const char *strtab, 193 + static int klp_resolve_symbols(Elf_Shdr *sechdrs, const char *strtab, 194 194 unsigned int symndx, Elf_Shdr *relasec, 195 195 const char *sec_objname) 196 196 { ··· 218 218 relas = (Elf_Rela *) relasec->sh_addr; 219 219 /* For each rela in this klp relocation section */ 220 220 for (i = 0; i < relasec->sh_size / sizeof(Elf_Rela); i++) { 221 - sym = (Elf64_Sym *)sechdrs[symndx].sh_addr + ELF_R_SYM(relas[i].r_info); 221 + sym = (Elf_Sym *)sechdrs[symndx].sh_addr + ELF_R_SYM(relas[i].r_info); 222 222 if (sym->st_shndx != SHN_LIVEPATCH) { 223 223 pr_err("symbol %s is not marked as a livepatch symbol\n", 224 224 strtab + sym->st_name);
+1
sound/ppc/pmac.h
··· 26 26 #include <asm/dbdma.h> 27 27 #include <asm/prom.h> 28 28 #include <asm/machdep.h> 29 + #include <asm/pmac_feature.h> 29 30 30 31 /* maximum number of fragments */ 31 32 #define PMAC_MAX_FRAGS 32
+1
tools/testing/selftests/lkdtm/tests.txt
··· 44 44 WRITE_RO 45 45 WRITE_RO_AFTER_INIT 46 46 WRITE_KERN 47 + WRITE_OPD 47 48 REFCOUNT_INC_OVERFLOW 48 49 REFCOUNT_ADD_OVERFLOW 49 50 REFCOUNT_INC_NOT_ZERO_OVERFLOW
+3 -1
tools/testing/selftests/powerpc/Makefile
··· 30 30 eeh \ 31 31 vphn \ 32 32 math \ 33 + papr_attributes \ 33 34 ptrace \ 34 - security 35 + security \ 36 + mce 35 37 36 38 endif 37 39
+1
tools/testing/selftests/powerpc/copyloops/.gitignore
··· 13 13 copyuser_64_exc_t1 14 14 copyuser_64_exc_t2 15 15 copy_mc_64 16 + memmove_64
+8 -1
tools/testing/selftests/powerpc/copyloops/Makefile
··· 13 13 copyuser_p7_t0 copyuser_p7_t1 \ 14 14 memcpy_64_t0 memcpy_64_t1 memcpy_64_t2 \ 15 15 memcpy_p7_t0 memcpy_p7_t1 copy_mc_64 \ 16 - copyuser_64_exc_t0 copyuser_64_exc_t1 copyuser_64_exc_t2 16 + copyuser_64_exc_t0 copyuser_64_exc_t1 copyuser_64_exc_t2 \ 17 + memmove_64 17 18 18 19 EXTRA_SOURCES := validate.c ../harness.c stubs.S 19 20 ··· 56 55 $(CC) $(CPPFLAGS) $(CFLAGS) \ 57 56 -D COPY_LOOP=test___copy_tofrom_user_base \ 58 57 -D SELFTEST_CASE=$(subst copyuser_64_exc_t,,$(notdir $@)) \ 58 + -o $@ $^ 59 + 60 + $(OUTPUT)/memmove_64: mem_64.S memcpy_64.S memmove_validate.c ../harness.c \ 61 + memcpy_stubs.S 62 + $(CC) $(CPPFLAGS) $(CFLAGS) \ 63 + -D TEST_MEMMOVE=test_memmove \ 59 64 -o $@ $^
+1
tools/testing/selftests/powerpc/copyloops/asm/ppc_asm.h
··· 26 26 #define _GLOBAL(A) FUNC_START(test_ ## A) 27 27 #define _GLOBAL_TOC(A) _GLOBAL(A) 28 28 #define _GLOBAL_TOC_KASAN(A) _GLOBAL(A) 29 + #define _GLOBAL_KASAN(A) _GLOBAL(A) 29 30 30 31 #define PPC_MTOCRF(A, B) mtocrf A, B 31 32
+8
tools/testing/selftests/powerpc/copyloops/memcpy_stubs.S
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + #include <asm/ppc_asm.h> 3 + 4 + FUNC_START(memcpy) 5 + b test_memcpy 6 + 7 + FUNC_START(backwards_memcpy) 8 + b test_backwards_memcpy
+58
tools/testing/selftests/powerpc/copyloops/memmove_validate.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <malloc.h> 3 + #include <stdlib.h> 4 + #include <string.h> 5 + #include <assert.h> 6 + #include "utils.h" 7 + 8 + void *TEST_MEMMOVE(const void *s1, const void *s2, size_t n); 9 + 10 + #define BUF_LEN 65536 11 + #define MAX_OFFSET 512 12 + 13 + size_t max(size_t a, size_t b) 14 + { 15 + if (a >= b) 16 + return a; 17 + return b; 18 + } 19 + 20 + static int testcase_run(void) 21 + { 22 + size_t i, src_off, dst_off, len; 23 + 24 + char *usermap = memalign(BUF_LEN, BUF_LEN); 25 + char *kernelmap = memalign(BUF_LEN, BUF_LEN); 26 + 27 + assert(usermap != NULL); 28 + assert(kernelmap != NULL); 29 + 30 + memset(usermap, 0, BUF_LEN); 31 + memset(kernelmap, 0, BUF_LEN); 32 + 33 + for (i = 0; i < BUF_LEN; i++) { 34 + usermap[i] = i & 0xff; 35 + kernelmap[i] = i & 0xff; 36 + } 37 + 38 + for (src_off = 0; src_off < MAX_OFFSET; src_off++) { 39 + for (dst_off = 0; dst_off < MAX_OFFSET; dst_off++) { 40 + for (len = 1; len < MAX_OFFSET - max(src_off, dst_off); len++) { 41 + 42 + memmove(usermap + dst_off, usermap + src_off, len); 43 + TEST_MEMMOVE(kernelmap + dst_off, kernelmap + src_off, len); 44 + if (memcmp(usermap, kernelmap, MAX_OFFSET) != 0) { 45 + printf("memmove failed at %ld %ld %ld\n", 46 + src_off, dst_off, len); 47 + abort(); 48 + } 49 + } 50 + } 51 + } 52 + return 0; 53 + } 54 + 55 + int main(void) 56 + { 57 + return test_harness(testcase_run, "memmove"); 58 + }
+4
tools/testing/selftests/powerpc/include/reg.h
··· 52 52 #define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */ 53 53 #define SPRN_TAR 0x32f /* Target Address Register */ 54 54 55 + #define PVR_VER(pvr) (((pvr) >> 16) & 0xFFFF) 56 + #define SPRN_PVR 0x11F 57 + 55 58 #define SPRN_DSCR_PRIV 0x11 /* Privilege State DSCR */ 56 59 #define SPRN_DSCR 0x03 /* Data Stream Control Register */ 57 60 #define SPRN_PPR 896 /* Program Priority Register */ ··· 87 84 #define TEXASR_ROT 0x0000000002000000 88 85 89 86 /* MSR register bits */ 87 + #define MSR_HV (1ul << 60) /* Hypervisor state */ 90 88 #define MSR_TS_S_LG 33 /* Trans Mem state: Suspended */ 91 89 #define MSR_TS_T_LG 34 /* Trans Mem state: Active */ 92 90
+7
tools/testing/selftests/powerpc/mce/Makefile
··· 1 + #SPDX-License-Identifier: GPL-2.0-or-later 2 + 3 + TEST_GEN_PROGS := inject-ra-err 4 + 5 + include ../../lib.mk 6 + 7 + $(TEST_GEN_PROGS): ../harness.c
+65
tools/testing/selftests/powerpc/mce/inject-ra-err.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + 3 + #include <errno.h> 4 + #include <fcntl.h> 5 + #include <signal.h> 6 + #include <stdio.h> 7 + #include <string.h> 8 + #include <sys/ioctl.h> 9 + #include <sys/mman.h> 10 + #include <sys/stat.h> 11 + #include <sys/types.h> 12 + #include <unistd.h> 13 + 14 + #include "vas-api.h" 15 + #include "utils.h" 16 + 17 + static bool faulted; 18 + 19 + static void sigbus_handler(int n, siginfo_t *info, void *ctxt_v) 20 + { 21 + ucontext_t *ctxt = (ucontext_t *)ctxt_v; 22 + struct pt_regs *regs = ctxt->uc_mcontext.regs; 23 + 24 + faulted = true; 25 + regs->nip += 4; 26 + } 27 + 28 + static int test_ra_error(void) 29 + { 30 + struct vas_tx_win_open_attr attr; 31 + int fd, *paste_addr; 32 + char *devname = "/dev/crypto/nx-gzip"; 33 + struct sigaction act = { 34 + .sa_sigaction = sigbus_handler, 35 + .sa_flags = SA_SIGINFO, 36 + }; 37 + 38 + memset(&attr, 0, sizeof(attr)); 39 + attr.version = 1; 40 + attr.vas_id = 0; 41 + 42 + SKIP_IF(access(devname, F_OK)); 43 + 44 + fd = open(devname, O_RDWR); 45 + FAIL_IF(fd < 0); 46 + FAIL_IF(ioctl(fd, VAS_TX_WIN_OPEN, &attr) < 0); 47 + FAIL_IF(sigaction(SIGBUS, &act, NULL) != 0); 48 + 49 + paste_addr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0ULL); 50 + 51 + /* The following assignment triggers exception */ 52 + mb(); 53 + *paste_addr = 1; 54 + mb(); 55 + 56 + FAIL_IF(!faulted); 57 + 58 + return 0; 59 + } 60 + 61 + int main(void) 62 + { 63 + return test_harness(test_ra_error, "inject-ra-err"); 64 + } 65 +
+7
tools/testing/selftests/powerpc/papr_attributes/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + TEST_GEN_PROGS := attr_test 3 + 4 + top_srcdir = ../../../../.. 5 + include ../../lib.mk 6 + 7 + $(TEST_GEN_PROGS): ../harness.c ../utils.c
+107
tools/testing/selftests/powerpc/papr_attributes/attr_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * PAPR Energy attributes sniff test 4 + * This checks if the papr folders and contents are populated relating to 5 + * the energy and frequency attributes 6 + * 7 + * Copyright 2022, Pratik Rajesh Sampat, IBM Corp. 8 + */ 9 + 10 + #include <stdio.h> 11 + #include <string.h> 12 + #include <dirent.h> 13 + #include <sys/types.h> 14 + #include <sys/stat.h> 15 + #include <unistd.h> 16 + #include <stdlib.h> 17 + 18 + #include "utils.h" 19 + 20 + enum energy_freq_attrs { 21 + POWER_PERFORMANCE_MODE = 1, 22 + IDLE_POWER_SAVER_STATUS = 2, 23 + MIN_FREQ = 3, 24 + STAT_FREQ = 4, 25 + MAX_FREQ = 6, 26 + PROC_FOLDING_STATUS = 8 27 + }; 28 + 29 + enum type { 30 + INVALID, 31 + STR_VAL, 32 + NUM_VAL 33 + }; 34 + 35 + int value_type(int id) 36 + { 37 + int val_type; 38 + 39 + switch (id) { 40 + case POWER_PERFORMANCE_MODE: 41 + case IDLE_POWER_SAVER_STATUS: 42 + val_type = STR_VAL; 43 + break; 44 + case MIN_FREQ: 45 + case STAT_FREQ: 46 + case MAX_FREQ: 47 + case PROC_FOLDING_STATUS: 48 + val_type = NUM_VAL; 49 + break; 50 + default: 51 + val_type = INVALID; 52 + } 53 + 54 + return val_type; 55 + } 56 + 57 + int verify_energy_info(void) 58 + { 59 + const char *path = "/sys/firmware/papr/energy_scale_info"; 60 + struct dirent *entry; 61 + struct stat s; 62 + DIR *dirp; 63 + 64 + if (stat(path, &s) || !S_ISDIR(s.st_mode)) 65 + return -1; 66 + dirp = opendir(path); 67 + 68 + while ((entry = readdir(dirp)) != NULL) { 69 + char file_name[64]; 70 + int id, attr_type; 71 + FILE *f; 72 + 73 + if (strcmp(entry->d_name, ".") == 0 || 74 + strcmp(entry->d_name, "..") == 0) 75 + continue; 76 + 77 + id = atoi(entry->d_name); 78 + attr_type = value_type(id); 79 + if (attr_type == INVALID) 80 + return -1; 81 + 82 + /* Check if the files exist and have data in them */ 83 + sprintf(file_name, "%s/%d/desc", path, id); 84 + f = fopen(file_name, "r"); 85 + if (!f || fgetc(f) == EOF) 86 + return -1; 87 + 88 + sprintf(file_name, "%s/%d/value", path, id); 89 + f = fopen(file_name, "r"); 90 + if (!f || fgetc(f) == EOF) 91 + return -1; 92 + 93 + if (attr_type == STR_VAL) { 94 + sprintf(file_name, "%s/%d/value_desc", path, id); 95 + f = fopen(file_name, "r"); 96 + if (!f || fgetc(f) == EOF) 97 + return -1; 98 + } 99 + } 100 + 101 + return 0; 102 + } 103 + 104 + int main(void) 105 + { 106 + return test_harness(verify_energy_info, "papr_attributes"); 107 + }
+9 -2
tools/testing/selftests/powerpc/pmu/Makefile
··· 8 8 top_srcdir = ../../../../.. 9 9 include ../../lib.mk 10 10 11 - all: $(TEST_GEN_PROGS) ebb 11 + all: $(TEST_GEN_PROGS) ebb sampling_tests 12 12 13 13 $(TEST_GEN_PROGS): $(EXTRA_SOURCES) 14 14 ··· 26 26 override define RUN_TESTS 27 27 $(DEFAULT_RUN_TESTS) 28 28 TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET run_tests 29 + TARGET=sampling_tests; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET run_tests 29 30 endef 30 31 31 32 DEFAULT_EMIT_TESTS := $(EMIT_TESTS) 32 33 override define EMIT_TESTS 33 34 $(DEFAULT_EMIT_TESTS) 34 35 TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -s -C $$TARGET emit_tests 36 + TARGET=sampling_tests; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -s -C $$TARGET emit_tests 35 37 endef 36 38 37 39 DEFAULT_INSTALL_RULE := $(INSTALL_RULE) 38 40 override define INSTALL_RULE 39 41 $(DEFAULT_INSTALL_RULE) 40 42 TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET install 43 + TARGET=sampling_tests; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET install 41 44 endef 42 45 43 46 clean: 44 47 $(RM) $(TEST_GEN_PROGS) $(OUTPUT)/loop.o 45 48 TARGET=ebb; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET clean 49 + TARGET=sampling_tests; BUILD_TARGET=$$OUTPUT/$$TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET clean 46 50 47 51 ebb: 48 52 TARGET=$@; BUILD_TARGET=$$OUTPUT/$$TARGET; mkdir -p $$BUILD_TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -k -C $$TARGET all 49 53 50 - .PHONY: all run_tests clean ebb 54 + sampling_tests: 55 + TARGET=$@; BUILD_TARGET=$$OUTPUT/$$TARGET; mkdir -p $$BUILD_TARGET; $(MAKE) OUTPUT=$$BUILD_TARGET -k -C $$TARGET all 56 + 57 + .PHONY: all run_tests clean ebb sampling_tests
+18 -1
tools/testing/selftests/powerpc/pmu/event.c
··· 8 8 #include <sys/syscall.h> 9 9 #include <string.h> 10 10 #include <stdio.h> 11 + #include <stdbool.h> 11 12 #include <sys/ioctl.h> 12 13 13 14 #include "event.h" ··· 21 20 group_fd, flags); 22 21 } 23 22 24 - void event_init_opts(struct event *e, u64 config, int type, char *name) 23 + static void __event_init_opts(struct event *e, u64 config, 24 + int type, char *name, bool sampling) 25 25 { 26 26 memset(e, 0, sizeof(*e)); 27 27 ··· 34 32 /* This has to match the structure layout in the header */ 35 33 e->attr.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | \ 36 34 PERF_FORMAT_TOTAL_TIME_RUNNING; 35 + if (sampling) { 36 + e->attr.sample_period = 1000; 37 + e->attr.sample_type = PERF_SAMPLE_REGS_INTR; 38 + e->attr.disabled = 1; 39 + } 40 + } 41 + 42 + void event_init_opts(struct event *e, u64 config, int type, char *name) 43 + { 44 + __event_init_opts(e, config, type, name, false); 37 45 } 38 46 39 47 void event_init_named(struct event *e, u64 config, char *name) ··· 54 42 void event_init(struct event *e, u64 config) 55 43 { 56 44 event_init_opts(e, config, PERF_TYPE_RAW, "event"); 45 + } 46 + 47 + void event_init_sampling(struct event *e, u64 config) 48 + { 49 + __event_init_opts(e, config, PERF_TYPE_RAW, "event", true); 57 50 } 58 51 59 52 #define PERF_CURRENT_PID 0
+6
tools/testing/selftests/powerpc/pmu/event.h
··· 22 22 u64 running; 23 23 u64 enabled; 24 24 } result; 25 + /* 26 + * mmap buffer used while recording sample. 27 + * Accessed as "struct perf_event_mmap_page" 28 + */ 29 + void *mmap_buffer; 25 30 }; 26 31 27 32 void event_init(struct event *e, u64 config); 28 33 void event_init_named(struct event *e, u64 config, char *name); 29 34 void event_init_opts(struct event *e, u64 config, int type, char *name); 35 + void event_init_sampling(struct event *e, u64 config); 30 36 int event_open_with_options(struct event *e, pid_t pid, int cpu, int group_fd); 31 37 int event_open_with_group(struct event *e, int group_fd); 32 38 int event_open_with_pid(struct event *e, pid_t pid);
+11
tools/testing/selftests/powerpc/pmu/sampling_tests/.gitignore
··· 1 + mmcr0_exceptionbits_test 2 + mmcr0_cc56run_test 3 + mmcr0_pmccext_test 4 + mmcr0_pmcjce_test 5 + mmcr0_fc56_pmc1ce_test 6 + mmcr0_fc56_pmc56_test 7 + mmcr1_comb_test 8 + mmcr2_l2l3_test 9 + mmcr2_fcs_fch_test 10 + mmcr3_src_test 11 + mmcra_thresh_marked_sample_test
+12
tools/testing/selftests/powerpc/pmu/sampling_tests/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0 2 + CFLAGS += -m64 3 + 4 + TEST_GEN_PROGS := mmcr0_exceptionbits_test mmcr0_cc56run_test mmcr0_pmccext_test \ 5 + mmcr0_pmcjce_test mmcr0_fc56_pmc1ce_test mmcr0_fc56_pmc56_test \ 6 + mmcr1_comb_test mmcr2_l2l3_test mmcr2_fcs_fch_test \ 7 + mmcr3_src_test mmcra_thresh_marked_sample_test 8 + 9 + top_srcdir = ../../../../../.. 10 + include ../../../lib.mk 11 + 12 + $(TEST_GEN_PROGS): ../../harness.c ../../utils.c ../event.c ../lib.c misc.c misc.h ../loop.S
+412
tools/testing/selftests/powerpc/pmu/sampling_tests/misc.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright 2022, Athira Rajeev, IBM Corp. 4 + * Copyright 2022, Madhavan Srinivasan, IBM Corp. 5 + * Copyright 2022, Kajol Jain, IBM Corp. 6 + */ 7 + 8 + #include <unistd.h> 9 + #include <sys/syscall.h> 10 + #include <string.h> 11 + #include <stdio.h> 12 + #include <sys/ioctl.h> 13 + #include <sys/mman.h> 14 + #include <stdlib.h> 15 + #include <ctype.h> 16 + 17 + #include "misc.h" 18 + 19 + #define PAGE_SIZE sysconf(_SC_PAGESIZE) 20 + 21 + /* Storage for platform version */ 22 + int pvr; 23 + u64 platform_extended_mask; 24 + 25 + /* Mask and Shift for Event code fields */ 26 + int ev_mask_pmcxsel, ev_shift_pmcxsel; //pmcxsel field 27 + int ev_mask_marked, ev_shift_marked; //marked filed 28 + int ev_mask_comb, ev_shift_comb; //combine field 29 + int ev_mask_unit, ev_shift_unit; //unit field 30 + int ev_mask_pmc, ev_shift_pmc; //pmc field 31 + int ev_mask_cache, ev_shift_cache; //Cache sel field 32 + int ev_mask_sample, ev_shift_sample; //Random sampling field 33 + int ev_mask_thd_sel, ev_shift_thd_sel; //thresh_sel field 34 + int ev_mask_thd_start, ev_shift_thd_start; //thresh_start field 35 + int ev_mask_thd_stop, ev_shift_thd_stop; //thresh_stop field 36 + int ev_mask_thd_cmp, ev_shift_thd_cmp; //thresh cmp field 37 + int ev_mask_sm, ev_shift_sm; //SDAR mode field 38 + int ev_mask_rsq, ev_shift_rsq; //radix scope qual field 39 + int ev_mask_l2l3, ev_shift_l2l3; //l2l3 sel field 40 + int ev_mask_mmcr3_src, ev_shift_mmcr3_src; //mmcr3 field 41 + 42 + static void init_ev_encodes(void) 43 + { 44 + ev_mask_pmcxsel = 0xff; 45 + ev_shift_pmcxsel = 0; 46 + ev_mask_marked = 1; 47 + ev_shift_marked = 8; 48 + ev_mask_unit = 0xf; 49 + ev_shift_unit = 12; 50 + ev_mask_pmc = 0xf; 51 + ev_shift_pmc = 16; 52 + ev_mask_sample = 0x1f; 53 + ev_shift_sample = 24; 54 + ev_mask_thd_sel = 0x7; 55 + ev_shift_thd_sel = 29; 56 + ev_mask_thd_start = 0xf; 57 + ev_shift_thd_start = 36; 58 + ev_mask_thd_stop = 0xf; 59 + ev_shift_thd_stop = 32; 60 + 61 + switch (pvr) { 62 + case POWER10: 63 + ev_mask_rsq = 1; 64 + ev_shift_rsq = 9; 65 + ev_mask_comb = 3; 66 + ev_shift_comb = 10; 67 + ev_mask_cache = 3; 68 + ev_shift_cache = 20; 69 + ev_mask_sm = 0x3; 70 + ev_shift_sm = 22; 71 + ev_mask_l2l3 = 0x1f; 72 + ev_shift_l2l3 = 40; 73 + ev_mask_mmcr3_src = 0x7fff; 74 + ev_shift_mmcr3_src = 45; 75 + break; 76 + case POWER9: 77 + ev_mask_comb = 3; 78 + ev_shift_comb = 10; 79 + ev_mask_cache = 0xf; 80 + ev_shift_cache = 20; 81 + ev_mask_thd_cmp = 0x3ff; 82 + ev_shift_thd_cmp = 40; 83 + ev_mask_sm = 0x3; 84 + ev_shift_sm = 50; 85 + break; 86 + default: 87 + FAIL_IF_EXIT(1); 88 + } 89 + } 90 + 91 + /* Return the extended regs mask value */ 92 + static u64 perf_get_platform_reg_mask(void) 93 + { 94 + if (have_hwcap2(PPC_FEATURE2_ARCH_3_1)) 95 + return PERF_POWER10_MASK; 96 + if (have_hwcap2(PPC_FEATURE2_ARCH_3_00)) 97 + return PERF_POWER9_MASK; 98 + 99 + return -1; 100 + } 101 + 102 + int check_extended_regs_support(void) 103 + { 104 + int fd; 105 + struct event event; 106 + 107 + event_init(&event, 0x1001e); 108 + 109 + event.attr.type = 4; 110 + event.attr.sample_period = 1; 111 + event.attr.disabled = 1; 112 + event.attr.sample_type = PERF_SAMPLE_REGS_INTR; 113 + event.attr.sample_regs_intr = platform_extended_mask; 114 + 115 + fd = event_open(&event); 116 + if (fd != -1) 117 + return 0; 118 + 119 + return -1; 120 + } 121 + 122 + int check_pvr_for_sampling_tests(void) 123 + { 124 + pvr = PVR_VER(mfspr(SPRN_PVR)); 125 + 126 + platform_extended_mask = perf_get_platform_reg_mask(); 127 + 128 + /* 129 + * Check for supported platforms 130 + * for sampling test 131 + */ 132 + if ((pvr != POWER10) && (pvr != POWER9)) 133 + goto out; 134 + 135 + /* 136 + * Check PMU driver registered by looking for 137 + * PPC_FEATURE2_EBB bit in AT_HWCAP2 138 + */ 139 + if (!have_hwcap2(PPC_FEATURE2_EBB)) 140 + goto out; 141 + 142 + /* check if platform supports extended regs */ 143 + if (check_extended_regs_support()) 144 + goto out; 145 + 146 + init_ev_encodes(); 147 + return 0; 148 + out: 149 + printf("%s: Sampling tests un-supported\n", __func__); 150 + return -1; 151 + } 152 + /* 153 + * Allocate mmap buffer of "mmap_pages" number of 154 + * pages. 155 + */ 156 + void *event_sample_buf_mmap(int fd, int mmap_pages) 157 + { 158 + size_t page_size = sysconf(_SC_PAGESIZE); 159 + size_t mmap_size; 160 + void *buff; 161 + 162 + if (mmap_pages <= 0) 163 + return NULL; 164 + 165 + if (fd <= 0) 166 + return NULL; 167 + 168 + mmap_size = page_size * (1 + mmap_pages); 169 + buff = mmap(NULL, mmap_size, 170 + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 171 + 172 + if (buff == MAP_FAILED) { 173 + perror("mmap() failed."); 174 + return NULL; 175 + } 176 + return buff; 177 + } 178 + 179 + /* 180 + * Post process the mmap buffer. 181 + * - If sample_count != NULL then return count of total 182 + * number of samples present in the mmap buffer. 183 + * - If sample_count == NULL then return the address 184 + * of first sample from the mmap buffer 185 + */ 186 + void *__event_read_samples(void *sample_buff, size_t *size, u64 *sample_count) 187 + { 188 + size_t page_size = sysconf(_SC_PAGESIZE); 189 + struct perf_event_header *header = sample_buff + page_size; 190 + struct perf_event_mmap_page *metadata_page = sample_buff; 191 + unsigned long data_head, data_tail; 192 + 193 + /* 194 + * PERF_RECORD_SAMPLE: 195 + * struct { 196 + * struct perf_event_header hdr; 197 + * u64 data[]; 198 + * }; 199 + */ 200 + 201 + data_head = metadata_page->data_head; 202 + /* sync memory before reading sample */ 203 + mb(); 204 + data_tail = metadata_page->data_tail; 205 + 206 + /* Check for sample_count */ 207 + if (sample_count) 208 + *sample_count = 0; 209 + 210 + while (1) { 211 + /* 212 + * Reads the mmap data buffer by moving 213 + * the data_tail to know the last read data. 214 + * data_head points to head in data buffer. 215 + * refer "struct perf_event_mmap_page" in 216 + * "include/uapi/linux/perf_event.h". 217 + */ 218 + if (data_head - data_tail < sizeof(header)) 219 + return NULL; 220 + 221 + data_tail += sizeof(header); 222 + if (header->type == PERF_RECORD_SAMPLE) { 223 + *size = (header->size - sizeof(header)); 224 + if (!sample_count) 225 + return sample_buff + page_size + data_tail; 226 + data_tail += *size; 227 + *sample_count += 1; 228 + } else { 229 + *size = (header->size - sizeof(header)); 230 + if ((metadata_page->data_tail + *size) > metadata_page->data_head) 231 + data_tail = metadata_page->data_head; 232 + else 233 + data_tail += *size; 234 + } 235 + header = (struct perf_event_header *)((void *)header + header->size); 236 + } 237 + return NULL; 238 + } 239 + 240 + int collect_samples(void *sample_buff) 241 + { 242 + u64 sample_count; 243 + size_t size = 0; 244 + 245 + __event_read_samples(sample_buff, &size, &sample_count); 246 + return sample_count; 247 + } 248 + 249 + static void *perf_read_first_sample(void *sample_buff, size_t *size) 250 + { 251 + return __event_read_samples(sample_buff, size, NULL); 252 + } 253 + 254 + u64 *get_intr_regs(struct event *event, void *sample_buff) 255 + { 256 + u64 type = event->attr.sample_type; 257 + u64 *intr_regs; 258 + size_t size = 0; 259 + 260 + if ((type ^ PERF_SAMPLE_REGS_INTR)) 261 + return NULL; 262 + 263 + intr_regs = (u64 *)perf_read_first_sample(sample_buff, &size); 264 + if (!intr_regs) 265 + return NULL; 266 + 267 + /* 268 + * First entry in the sample buffer used to specify 269 + * PERF_SAMPLE_REGS_ABI_64, skip perf regs abi to access 270 + * interrupt registers. 271 + */ 272 + ++intr_regs; 273 + 274 + return intr_regs; 275 + } 276 + 277 + static const unsigned int __perf_reg_mask(const char *register_name) 278 + { 279 + if (!strcmp(register_name, "R0")) 280 + return 0; 281 + else if (!strcmp(register_name, "R1")) 282 + return 1; 283 + else if (!strcmp(register_name, "R2")) 284 + return 2; 285 + else if (!strcmp(register_name, "R3")) 286 + return 3; 287 + else if (!strcmp(register_name, "R4")) 288 + return 4; 289 + else if (!strcmp(register_name, "R5")) 290 + return 5; 291 + else if (!strcmp(register_name, "R6")) 292 + return 6; 293 + else if (!strcmp(register_name, "R7")) 294 + return 7; 295 + else if (!strcmp(register_name, "R8")) 296 + return 8; 297 + else if (!strcmp(register_name, "R9")) 298 + return 9; 299 + else if (!strcmp(register_name, "R10")) 300 + return 10; 301 + else if (!strcmp(register_name, "R11")) 302 + return 11; 303 + else if (!strcmp(register_name, "R12")) 304 + return 12; 305 + else if (!strcmp(register_name, "R13")) 306 + return 13; 307 + else if (!strcmp(register_name, "R14")) 308 + return 14; 309 + else if (!strcmp(register_name, "R15")) 310 + return 15; 311 + else if (!strcmp(register_name, "R16")) 312 + return 16; 313 + else if (!strcmp(register_name, "R17")) 314 + return 17; 315 + else if (!strcmp(register_name, "R18")) 316 + return 18; 317 + else if (!strcmp(register_name, "R19")) 318 + return 19; 319 + else if (!strcmp(register_name, "R20")) 320 + return 20; 321 + else if (!strcmp(register_name, "R21")) 322 + return 21; 323 + else if (!strcmp(register_name, "R22")) 324 + return 22; 325 + else if (!strcmp(register_name, "R23")) 326 + return 23; 327 + else if (!strcmp(register_name, "R24")) 328 + return 24; 329 + else if (!strcmp(register_name, "R25")) 330 + return 25; 331 + else if (!strcmp(register_name, "R26")) 332 + return 26; 333 + else if (!strcmp(register_name, "R27")) 334 + return 27; 335 + else if (!strcmp(register_name, "R28")) 336 + return 28; 337 + else if (!strcmp(register_name, "R29")) 338 + return 29; 339 + else if (!strcmp(register_name, "R30")) 340 + return 30; 341 + else if (!strcmp(register_name, "R31")) 342 + return 31; 343 + else if (!strcmp(register_name, "NIP")) 344 + return 32; 345 + else if (!strcmp(register_name, "MSR")) 346 + return 33; 347 + else if (!strcmp(register_name, "ORIG_R3")) 348 + return 34; 349 + else if (!strcmp(register_name, "CTR")) 350 + return 35; 351 + else if (!strcmp(register_name, "LINK")) 352 + return 36; 353 + else if (!strcmp(register_name, "XER")) 354 + return 37; 355 + else if (!strcmp(register_name, "CCR")) 356 + return 38; 357 + else if (!strcmp(register_name, "SOFTE")) 358 + return 39; 359 + else if (!strcmp(register_name, "TRAP")) 360 + return 40; 361 + else if (!strcmp(register_name, "DAR")) 362 + return 41; 363 + else if (!strcmp(register_name, "DSISR")) 364 + return 42; 365 + else if (!strcmp(register_name, "SIER")) 366 + return 43; 367 + else if (!strcmp(register_name, "MMCRA")) 368 + return 44; 369 + else if (!strcmp(register_name, "MMCR0")) 370 + return 45; 371 + else if (!strcmp(register_name, "MMCR1")) 372 + return 46; 373 + else if (!strcmp(register_name, "MMCR2")) 374 + return 47; 375 + else if (!strcmp(register_name, "MMCR3")) 376 + return 48; 377 + else if (!strcmp(register_name, "SIER2")) 378 + return 49; 379 + else if (!strcmp(register_name, "SIER3")) 380 + return 50; 381 + else if (!strcmp(register_name, "PMC1")) 382 + return 51; 383 + else if (!strcmp(register_name, "PMC2")) 384 + return 52; 385 + else if (!strcmp(register_name, "PMC3")) 386 + return 53; 387 + else if (!strcmp(register_name, "PMC4")) 388 + return 54; 389 + else if (!strcmp(register_name, "PMC5")) 390 + return 55; 391 + else if (!strcmp(register_name, "PMC6")) 392 + return 56; 393 + else if (!strcmp(register_name, "SDAR")) 394 + return 57; 395 + else if (!strcmp(register_name, "SIAR")) 396 + return 58; 397 + else 398 + return -1; 399 + } 400 + 401 + u64 get_reg_value(u64 *intr_regs, char *register_name) 402 + { 403 + int register_bit_position; 404 + 405 + register_bit_position = __perf_reg_mask(register_name); 406 + 407 + if (register_bit_position < 0 || (!((platform_extended_mask >> 408 + (register_bit_position - 1)) & 1))) 409 + return -1; 410 + 411 + return *(intr_regs + register_bit_position); 412 + }
+227
tools/testing/selftests/powerpc/pmu/sampling_tests/misc.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-only */ 2 + /* 3 + * Copyright 2022, Athira Rajeev, IBM Corp. 4 + * Copyright 2022, Madhavan Srinivasan, IBM Corp. 5 + * Copyright 2022, Kajol Jain, IBM Corp. 6 + */ 7 + 8 + #include "../event.h" 9 + 10 + #define POWER10 0x80 11 + #define POWER9 0x4e 12 + #define PERF_POWER9_MASK 0x7f8ffffffffffff 13 + #define PERF_POWER10_MASK 0x7ffffffffffffff 14 + 15 + #define MMCR0_FC56 0x00000010UL /* freeze counters 5 and 6 */ 16 + #define MMCR0_PMCCEXT 0x00000200UL /* PMCCEXT control */ 17 + #define MMCR1_RSQ 0x200000000000ULL /* radix scope qual field */ 18 + #define BHRB_DISABLE 0x2000000000ULL /* MMCRA BHRB DISABLE bit */ 19 + 20 + extern int ev_mask_pmcxsel, ev_shift_pmcxsel; 21 + extern int ev_mask_marked, ev_shift_marked; 22 + extern int ev_mask_comb, ev_shift_comb; 23 + extern int ev_mask_unit, ev_shift_unit; 24 + extern int ev_mask_pmc, ev_shift_pmc; 25 + extern int ev_mask_cache, ev_shift_cache; 26 + extern int ev_mask_sample, ev_shift_sample; 27 + extern int ev_mask_thd_sel, ev_shift_thd_sel; 28 + extern int ev_mask_thd_start, ev_shift_thd_start; 29 + extern int ev_mask_thd_stop, ev_shift_thd_stop; 30 + extern int ev_mask_thd_cmp, ev_shift_thd_cmp; 31 + extern int ev_mask_sm, ev_shift_sm; 32 + extern int ev_mask_rsq, ev_shift_rsq; 33 + extern int ev_mask_l2l3, ev_shift_l2l3; 34 + extern int ev_mask_mmcr3_src, ev_shift_mmcr3_src; 35 + extern int pvr; 36 + extern u64 platform_extended_mask; 37 + extern int check_pvr_for_sampling_tests(void); 38 + 39 + /* 40 + * Event code field extraction macro. 41 + * Raw event code is combination of multiple 42 + * fields. Macro to extract individual fields 43 + * 44 + * x - Raw event code value 45 + * y - Field to extract 46 + */ 47 + #define EV_CODE_EXTRACT(x, y) \ 48 + ((x >> ev_shift_##y) & ev_mask_##y) 49 + 50 + void *event_sample_buf_mmap(int fd, int mmap_pages); 51 + void *__event_read_samples(void *sample_buff, size_t *size, u64 *sample_count); 52 + int collect_samples(void *sample_buff); 53 + u64 *get_intr_regs(struct event *event, void *sample_buff); 54 + u64 get_reg_value(u64 *intr_regs, char *register_name); 55 + 56 + static inline int get_mmcr0_fc56(u64 mmcr0, int pmc) 57 + { 58 + return (mmcr0 & MMCR0_FC56); 59 + } 60 + 61 + static inline int get_mmcr0_pmccext(u64 mmcr0, int pmc) 62 + { 63 + return (mmcr0 & MMCR0_PMCCEXT); 64 + } 65 + 66 + static inline int get_mmcr0_pmao(u64 mmcr0, int pmc) 67 + { 68 + return ((mmcr0 >> 7) & 0x1); 69 + } 70 + 71 + static inline int get_mmcr0_cc56run(u64 mmcr0, int pmc) 72 + { 73 + return ((mmcr0 >> 8) & 0x1); 74 + } 75 + 76 + static inline int get_mmcr0_pmcjce(u64 mmcr0, int pmc) 77 + { 78 + return ((mmcr0 >> 14) & 0x1); 79 + } 80 + 81 + static inline int get_mmcr0_pmc1ce(u64 mmcr0, int pmc) 82 + { 83 + return ((mmcr0 >> 15) & 0x1); 84 + } 85 + 86 + static inline int get_mmcr0_pmae(u64 mmcr0, int pmc) 87 + { 88 + return ((mmcr0 >> 27) & 0x1); 89 + } 90 + 91 + static inline int get_mmcr1_pmcxsel(u64 mmcr1, int pmc) 92 + { 93 + return ((mmcr1 >> ((24 - (((pmc) - 1) * 8))) & 0xff)); 94 + } 95 + 96 + static inline int get_mmcr1_unit(u64 mmcr1, int pmc) 97 + { 98 + return ((mmcr1 >> ((60 - (4 * ((pmc) - 1))))) & 0xf); 99 + } 100 + 101 + static inline int get_mmcr1_comb(u64 mmcr1, int pmc) 102 + { 103 + return ((mmcr1 >> (38 - ((pmc - 1) * 2))) & 0x3); 104 + } 105 + 106 + static inline int get_mmcr1_cache(u64 mmcr1, int pmc) 107 + { 108 + return ((mmcr1 >> 46) & 0x3); 109 + } 110 + 111 + static inline int get_mmcr1_rsq(u64 mmcr1, int pmc) 112 + { 113 + return mmcr1 & MMCR1_RSQ; 114 + } 115 + 116 + static inline int get_mmcr2_fcs(u64 mmcr2, int pmc) 117 + { 118 + return ((mmcr2 & (1ull << (63 - (((pmc) - 1) * 9)))) >> (63 - (((pmc) - 1) * 9))); 119 + } 120 + 121 + static inline int get_mmcr2_fcp(u64 mmcr2, int pmc) 122 + { 123 + return ((mmcr2 & (1ull << (62 - (((pmc) - 1) * 9)))) >> (62 - (((pmc) - 1) * 9))); 124 + } 125 + 126 + static inline int get_mmcr2_fcpc(u64 mmcr2, int pmc) 127 + { 128 + return ((mmcr2 & (1ull << (61 - (((pmc) - 1) * 9)))) >> (61 - (((pmc) - 1) * 9))); 129 + } 130 + 131 + static inline int get_mmcr2_fcm1(u64 mmcr2, int pmc) 132 + { 133 + return ((mmcr2 & (1ull << (60 - (((pmc) - 1) * 9)))) >> (60 - (((pmc) - 1) * 9))); 134 + } 135 + 136 + static inline int get_mmcr2_fcm0(u64 mmcr2, int pmc) 137 + { 138 + return ((mmcr2 & (1ull << (59 - (((pmc) - 1) * 9)))) >> (59 - (((pmc) - 1) * 9))); 139 + } 140 + 141 + static inline int get_mmcr2_fcwait(u64 mmcr2, int pmc) 142 + { 143 + return ((mmcr2 & (1ull << (58 - (((pmc) - 1) * 9)))) >> (58 - (((pmc) - 1) * 9))); 144 + } 145 + 146 + static inline int get_mmcr2_fch(u64 mmcr2, int pmc) 147 + { 148 + return ((mmcr2 & (1ull << (57 - (((pmc) - 1) * 9)))) >> (57 - (((pmc) - 1) * 9))); 149 + } 150 + 151 + static inline int get_mmcr2_fcti(u64 mmcr2, int pmc) 152 + { 153 + return ((mmcr2 & (1ull << (56 - (((pmc) - 1) * 9)))) >> (56 - (((pmc) - 1) * 9))); 154 + } 155 + 156 + static inline int get_mmcr2_fcta(u64 mmcr2, int pmc) 157 + { 158 + return ((mmcr2 & (1ull << (55 - (((pmc) - 1) * 9)))) >> (55 - (((pmc) - 1) * 9))); 159 + } 160 + 161 + static inline int get_mmcr2_l2l3(u64 mmcr2, int pmc) 162 + { 163 + if (pvr == POWER10) 164 + return ((mmcr2 & 0xf8) >> 3); 165 + return 0; 166 + } 167 + 168 + static inline int get_mmcr3_src(u64 mmcr3, int pmc) 169 + { 170 + if (pvr != POWER10) 171 + return 0; 172 + return ((mmcr3 >> ((49 - (15 * ((pmc) - 1))))) & 0x7fff); 173 + } 174 + 175 + static inline int get_mmcra_thd_cmp(u64 mmcra, int pmc) 176 + { 177 + if (pvr == POWER10) 178 + return ((mmcra >> 45) & 0x7ff); 179 + return ((mmcra >> 45) & 0x3ff); 180 + } 181 + 182 + static inline int get_mmcra_sm(u64 mmcra, int pmc) 183 + { 184 + return ((mmcra >> 42) & 0x3); 185 + } 186 + 187 + static inline int get_mmcra_bhrb_disable(u64 mmcra, int pmc) 188 + { 189 + if (pvr == POWER10) 190 + return mmcra & BHRB_DISABLE; 191 + return 0; 192 + } 193 + 194 + static inline int get_mmcra_ifm(u64 mmcra, int pmc) 195 + { 196 + return ((mmcra >> 30) & 0x3); 197 + } 198 + 199 + static inline int get_mmcra_thd_sel(u64 mmcra, int pmc) 200 + { 201 + return ((mmcra >> 16) & 0x7); 202 + } 203 + 204 + static inline int get_mmcra_thd_start(u64 mmcra, int pmc) 205 + { 206 + return ((mmcra >> 12) & 0xf); 207 + } 208 + 209 + static inline int get_mmcra_thd_stop(u64 mmcra, int pmc) 210 + { 211 + return ((mmcra >> 8) & 0xf); 212 + } 213 + 214 + static inline int get_mmcra_rand_samp_elig(u64 mmcra, int pmc) 215 + { 216 + return ((mmcra >> 4) & 0x7); 217 + } 218 + 219 + static inline int get_mmcra_sample_mode(u64 mmcra, int pmc) 220 + { 221 + return ((mmcra >> 1) & 0x3); 222 + } 223 + 224 + static inline int get_mmcra_marked(u64 mmcra, int pmc) 225 + { 226 + return mmcra & 0x1; 227 + }
+59
tools/testing/selftests/powerpc/pmu/sampling_tests/mmcr0_cc56run_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright 2022, Athira Rajeev, IBM Corp. 4 + */ 5 + 6 + #include <stdio.h> 7 + #include <stdlib.h> 8 + 9 + #include "../event.h" 10 + #include "misc.h" 11 + #include "utils.h" 12 + 13 + extern void thirty_two_instruction_loop(int loops); 14 + 15 + /* 16 + * A perf sampling test for mmcr0 17 + * field: cc56run. 18 + */ 19 + static int mmcr0_cc56run(void) 20 + { 21 + struct event event; 22 + u64 *intr_regs; 23 + 24 + /* Check for platform support for the test */ 25 + SKIP_IF(check_pvr_for_sampling_tests()); 26 + SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1)); 27 + 28 + /* Init the event for the sampling test */ 29 + event_init_sampling(&event, 0x500fa); 30 + event.attr.sample_regs_intr = platform_extended_mask; 31 + FAIL_IF(event_open(&event)); 32 + event.mmap_buffer = event_sample_buf_mmap(event.fd, 1); 33 + 34 + FAIL_IF(event_enable(&event)); 35 + 36 + /* workload to make the event overflow */ 37 + thirty_two_instruction_loop(10000); 38 + 39 + FAIL_IF(event_disable(&event)); 40 + 41 + /* Check for sample count */ 42 + FAIL_IF(!collect_samples(event.mmap_buffer)); 43 + 44 + intr_regs = get_intr_regs(&event, event.mmap_buffer); 45 + 46 + /* Check for intr_regs */ 47 + FAIL_IF(!intr_regs); 48 + 49 + /* Verify that cc56run bit is set in MMCR0 */ 50 + FAIL_IF(!get_mmcr0_cc56run(get_reg_value(intr_regs, "MMCR0"), 5)); 51 + 52 + event_close(&event); 53 + return 0; 54 + } 55 + 56 + int main(void) 57 + { 58 + return test_harness(mmcr0_cc56run, "mmcr0_cc56run"); 59 + }
+59
tools/testing/selftests/powerpc/pmu/sampling_tests/mmcr0_exceptionbits_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright 2022, Athira Rajeev, IBM Corp. 4 + */ 5 + 6 + #include <stdio.h> 7 + #include <stdlib.h> 8 + 9 + #include "../event.h" 10 + #include "misc.h" 11 + #include "utils.h" 12 + 13 + extern void thirty_two_instruction_loop(int loops); 14 + 15 + /* 16 + * A perf sampling test for mmcr0 17 + * fields : pmae, pmao. 18 + */ 19 + static int mmcr0_exceptionbits(void) 20 + { 21 + struct event event; 22 + u64 *intr_regs; 23 + 24 + /* Check for platform support for the test */ 25 + SKIP_IF(check_pvr_for_sampling_tests()); 26 + 27 + /* Init the event for the sampling test */ 28 + event_init_sampling(&event, 0x500fa); 29 + event.attr.sample_regs_intr = platform_extended_mask; 30 + FAIL_IF(event_open(&event)); 31 + event.mmap_buffer = event_sample_buf_mmap(event.fd, 1); 32 + 33 + FAIL_IF(event_enable(&event)); 34 + 35 + /* workload to make the event overflow */ 36 + thirty_two_instruction_loop(10000); 37 + 38 + FAIL_IF(event_disable(&event)); 39 + 40 + /* Check for sample count */ 41 + FAIL_IF(!collect_samples(event.mmap_buffer)); 42 + 43 + intr_regs = get_intr_regs(&event, event.mmap_buffer); 44 + 45 + /* Check for intr_regs */ 46 + FAIL_IF(!intr_regs); 47 + 48 + /* Verify that pmae is cleared and pmao is set in MMCR0 */ 49 + FAIL_IF(get_mmcr0_pmae(get_reg_value(intr_regs, "MMCR0"), 5)); 50 + FAIL_IF(!get_mmcr0_pmao(get_reg_value(intr_regs, "MMCR0"), 5)); 51 + 52 + event_close(&event); 53 + return 0; 54 + } 55 + 56 + int main(void) 57 + { 58 + return test_harness(mmcr0_exceptionbits, "mmcr0_exceptionbits"); 59 + }
+59
tools/testing/selftests/powerpc/pmu/sampling_tests/mmcr0_fc56_pmc1ce_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright 2022, Athira Rajeev, IBM Corp. 4 + */ 5 + 6 + #include <stdio.h> 7 + #include <stdlib.h> 8 + 9 + #include "../event.h" 10 + #include "misc.h" 11 + #include "utils.h" 12 + 13 + extern void thirty_two_instruction_loop(int loops); 14 + 15 + /* 16 + * A perf sampling test for mmcr0 17 + * fields: fc56, pmc1ce. 18 + */ 19 + static int mmcr0_fc56_pmc1ce(void) 20 + { 21 + struct event event; 22 + u64 *intr_regs; 23 + 24 + /* Check for platform support for the test */ 25 + SKIP_IF(check_pvr_for_sampling_tests()); 26 + 27 + /* Init the event for the sampling test */ 28 + event_init_sampling(&event, 0x1001e); 29 + event.attr.sample_regs_intr = platform_extended_mask; 30 + FAIL_IF(event_open(&event)); 31 + event.mmap_buffer = event_sample_buf_mmap(event.fd, 1); 32 + 33 + FAIL_IF(event_enable(&event)); 34 + 35 + /* workload to make the event overflow */ 36 + thirty_two_instruction_loop(10000); 37 + 38 + FAIL_IF(event_disable(&event)); 39 + 40 + /* Check for sample count */ 41 + FAIL_IF(!collect_samples(event.mmap_buffer)); 42 + 43 + intr_regs = get_intr_regs(&event, event.mmap_buffer); 44 + 45 + /* Check for intr_regs */ 46 + FAIL_IF(!intr_regs); 47 + 48 + /* Verify that fc56, pmc1ce fields are set in MMCR0 */ 49 + FAIL_IF(!get_mmcr0_fc56(get_reg_value(intr_regs, "MMCR0"), 1)); 50 + FAIL_IF(!get_mmcr0_pmc1ce(get_reg_value(intr_regs, "MMCR0"), 1)); 51 + 52 + event_close(&event); 53 + return 0; 54 + } 55 + 56 + int main(void) 57 + { 58 + return test_harness(mmcr0_fc56_pmc1ce, "mmcr0_fc56_pmc1ce"); 59 + }
+58
tools/testing/selftests/powerpc/pmu/sampling_tests/mmcr0_fc56_pmc56_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright 2022, Athira Rajeev, IBM Corp. 4 + */ 5 + 6 + #include <stdio.h> 7 + #include <stdlib.h> 8 + 9 + #include "../event.h" 10 + #include "misc.h" 11 + #include "utils.h" 12 + 13 + extern void thirty_two_instruction_loop(int loops); 14 + 15 + /* 16 + * A perf sampling test for mmcr0 17 + * fields: fc56_pmc56 18 + */ 19 + static int mmcr0_fc56_pmc56(void) 20 + { 21 + struct event event; 22 + u64 *intr_regs; 23 + 24 + /* Check for platform support for the test */ 25 + SKIP_IF(check_pvr_for_sampling_tests()); 26 + 27 + /* Init the event for the sampling test */ 28 + event_init_sampling(&event, 0x500fa); 29 + event.attr.sample_regs_intr = platform_extended_mask; 30 + FAIL_IF(event_open(&event)); 31 + event.mmap_buffer = event_sample_buf_mmap(event.fd, 1); 32 + 33 + FAIL_IF(event_enable(&event)); 34 + 35 + /* workload to make the event overflow */ 36 + thirty_two_instruction_loop(10000); 37 + 38 + FAIL_IF(event_disable(&event)); 39 + 40 + /* Check for sample count */ 41 + FAIL_IF(!collect_samples(event.mmap_buffer)); 42 + 43 + intr_regs = get_intr_regs(&event, event.mmap_buffer); 44 + 45 + /* Check for intr_regs */ 46 + FAIL_IF(!intr_regs); 47 + 48 + /* Verify that fc56 is not set in MMCR0 when using PMC5 */ 49 + FAIL_IF(get_mmcr0_fc56(get_reg_value(intr_regs, "MMCR0"), 5)); 50 + 51 + event_close(&event); 52 + return 0; 53 + } 54 + 55 + int main(void) 56 + { 57 + return test_harness(mmcr0_fc56_pmc56, "mmcr0_fc56_pmc56"); 58 + }
+59
tools/testing/selftests/powerpc/pmu/sampling_tests/mmcr0_pmccext_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright 2022, Athira Rajeev, IBM Corp. 4 + */ 5 + 6 + #include <stdio.h> 7 + #include <stdlib.h> 8 + 9 + #include "../event.h" 10 + #include "misc.h" 11 + #include "utils.h" 12 + 13 + extern void thirty_two_instruction_loop(int loops); 14 + 15 + /* 16 + * A perf sampling test for mmcr0 17 + * field: pmccext 18 + */ 19 + static int mmcr0_pmccext(void) 20 + { 21 + struct event event; 22 + u64 *intr_regs; 23 + 24 + /* Check for platform support for the test */ 25 + SKIP_IF(check_pvr_for_sampling_tests()); 26 + SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1)); 27 + 28 + /* Init the event for the sampling test */ 29 + event_init_sampling(&event, 0x4001e); 30 + event.attr.sample_regs_intr = platform_extended_mask; 31 + FAIL_IF(event_open(&event)); 32 + event.mmap_buffer = event_sample_buf_mmap(event.fd, 1); 33 + 34 + FAIL_IF(event_enable(&event)); 35 + 36 + /* workload to make the event overflow */ 37 + thirty_two_instruction_loop(10000); 38 + 39 + FAIL_IF(event_disable(&event)); 40 + 41 + /* Check for sample count */ 42 + FAIL_IF(!collect_samples(event.mmap_buffer)); 43 + 44 + intr_regs = get_intr_regs(&event, event.mmap_buffer); 45 + 46 + /* Check for intr_regs */ 47 + FAIL_IF(!intr_regs); 48 + 49 + /* Verify that pmccext field is set in MMCR0 */ 50 + FAIL_IF(!get_mmcr0_pmccext(get_reg_value(intr_regs, "MMCR0"), 4)); 51 + 52 + event_close(&event); 53 + return 0; 54 + } 55 + 56 + int main(void) 57 + { 58 + return test_harness(mmcr0_pmccext, "mmcr0_pmccext"); 59 + }
+58
tools/testing/selftests/powerpc/pmu/sampling_tests/mmcr0_pmcjce_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright 2022, Athira Rajeev, IBM Corp. 4 + */ 5 + 6 + #include <stdio.h> 7 + #include <stdlib.h> 8 + 9 + #include "../event.h" 10 + #include "misc.h" 11 + #include "utils.h" 12 + 13 + extern void thirty_two_instruction_loop(int loops); 14 + 15 + /* 16 + * A perf sampling test for mmcr0 17 + * field: pmcjce 18 + */ 19 + static int mmcr0_pmcjce(void) 20 + { 21 + struct event event; 22 + u64 *intr_regs; 23 + 24 + /* Check for platform support for the test */ 25 + SKIP_IF(check_pvr_for_sampling_tests()); 26 + 27 + /* Init the event for the sampling test */ 28 + event_init_sampling(&event, 0x500fa); 29 + event.attr.sample_regs_intr = platform_extended_mask; 30 + FAIL_IF(event_open(&event)); 31 + event.mmap_buffer = event_sample_buf_mmap(event.fd, 1); 32 + 33 + FAIL_IF(event_enable(&event)); 34 + 35 + /* workload to make the event overflow */ 36 + thirty_two_instruction_loop(10000); 37 + 38 + FAIL_IF(event_disable(&event)); 39 + 40 + /* Check for sample count */ 41 + FAIL_IF(!collect_samples(event.mmap_buffer)); 42 + 43 + intr_regs = get_intr_regs(&event, event.mmap_buffer); 44 + 45 + /* Check for intr_regs */ 46 + FAIL_IF(!intr_regs); 47 + 48 + /* Verify that pmcjce field is set in MMCR0 */ 49 + FAIL_IF(!get_mmcr0_pmcjce(get_reg_value(intr_regs, "MMCR0"), 5)); 50 + 51 + event_close(&event); 52 + return 0; 53 + } 54 + 55 + int main(void) 56 + { 57 + return test_harness(mmcr0_pmcjce, "mmcr0_pmcjce"); 58 + }
+66
tools/testing/selftests/powerpc/pmu/sampling_tests/mmcr1_comb_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright 2022, Athira Rajeev, IBM Corp. 4 + */ 5 + 6 + #include <stdio.h> 7 + #include <stdlib.h> 8 + 9 + #include "../event.h" 10 + #include "misc.h" 11 + #include "utils.h" 12 + 13 + /* All successful D-side store dispatches for this thread that were L2 Miss */ 14 + #define EventCode 0x46880 15 + 16 + extern void thirty_two_instruction_loop_with_ll_sc(u64 loops, u64 *ll_sc_target); 17 + 18 + /* 19 + * A perf sampling test for mmcr1 20 + * fields : comb. 21 + */ 22 + static int mmcr1_comb(void) 23 + { 24 + struct event event; 25 + u64 *intr_regs; 26 + u64 dummy; 27 + 28 + /* Check for platform support for the test */ 29 + SKIP_IF(check_pvr_for_sampling_tests()); 30 + 31 + /* Init the event for the sampling test */ 32 + event_init_sampling(&event, EventCode); 33 + event.attr.sample_regs_intr = platform_extended_mask; 34 + FAIL_IF(event_open(&event)); 35 + event.mmap_buffer = event_sample_buf_mmap(event.fd, 1); 36 + 37 + FAIL_IF(event_enable(&event)); 38 + 39 + /* workload to make the event overflow */ 40 + thirty_two_instruction_loop_with_ll_sc(10000000, &dummy); 41 + 42 + FAIL_IF(event_disable(&event)); 43 + 44 + /* Check for sample count */ 45 + FAIL_IF(!collect_samples(event.mmap_buffer)); 46 + 47 + intr_regs = get_intr_regs(&event, event.mmap_buffer); 48 + 49 + /* Check for intr_regs */ 50 + FAIL_IF(!intr_regs); 51 + 52 + /* 53 + * Verify that comb field match with 54 + * corresponding event code fields 55 + */ 56 + FAIL_IF(EV_CODE_EXTRACT(event.attr.config, comb) != 57 + get_mmcr1_comb(get_reg_value(intr_regs, "MMCR1"), 4)); 58 + 59 + event_close(&event); 60 + return 0; 61 + } 62 + 63 + int main(void) 64 + { 65 + return test_harness(mmcr1_comb, "mmcr1_comb"); 66 + }
+85
tools/testing/selftests/powerpc/pmu/sampling_tests/mmcr2_fcs_fch_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright 2022, Madhavan Srinivasan, IBM Corp. 4 + */ 5 + 6 + #include <signal.h> 7 + #include <stdio.h> 8 + #include <stdlib.h> 9 + #include <sys/types.h> 10 + 11 + #include "../event.h" 12 + #include "misc.h" 13 + #include "utils.h" 14 + 15 + extern void thirty_two_instruction_loop(int loops); 16 + 17 + static bool is_hv; 18 + 19 + static void sig_usr2_handler(int signum, siginfo_t *info, void *data) 20 + { 21 + ucontext_t *uctx = data; 22 + 23 + is_hv = !!(uctx->uc_mcontext.gp_regs[PT_MSR] & MSR_HV); 24 + } 25 + 26 + /* 27 + * A perf sampling test for mmcr2 28 + * fields : fcs, fch. 29 + */ 30 + static int mmcr2_fcs_fch(void) 31 + { 32 + struct sigaction sigact = { 33 + .sa_sigaction = sig_usr2_handler, 34 + .sa_flags = SA_SIGINFO 35 + }; 36 + struct event event; 37 + u64 *intr_regs; 38 + 39 + FAIL_IF(sigaction(SIGUSR2, &sigact, NULL)); 40 + FAIL_IF(kill(getpid(), SIGUSR2)); 41 + 42 + /* Check for platform support for the test */ 43 + SKIP_IF(check_pvr_for_sampling_tests()); 44 + 45 + /* Init the event for the sampling test */ 46 + event_init_sampling(&event, 0x1001e); 47 + event.attr.sample_regs_intr = platform_extended_mask; 48 + event.attr.exclude_kernel = 1; 49 + FAIL_IF(event_open(&event)); 50 + event.mmap_buffer = event_sample_buf_mmap(event.fd, 1); 51 + 52 + FAIL_IF(event_enable(&event)); 53 + 54 + /* workload to make the event overflow */ 55 + thirty_two_instruction_loop(10000); 56 + 57 + FAIL_IF(event_disable(&event)); 58 + 59 + /* Check for sample count */ 60 + FAIL_IF(!collect_samples(event.mmap_buffer)); 61 + 62 + intr_regs = get_intr_regs(&event, event.mmap_buffer); 63 + 64 + /* Check for intr_regs */ 65 + FAIL_IF(!intr_regs); 66 + 67 + /* 68 + * Verify that fcs and fch field of MMCR2 match 69 + * with corresponding modifier fields. 70 + */ 71 + if (is_hv) 72 + FAIL_IF(event.attr.exclude_kernel != 73 + get_mmcr2_fch(get_reg_value(intr_regs, "MMCR2"), 1)); 74 + else 75 + FAIL_IF(event.attr.exclude_kernel != 76 + get_mmcr2_fcs(get_reg_value(intr_regs, "MMCR2"), 1)); 77 + 78 + event_close(&event); 79 + return 0; 80 + } 81 + 82 + int main(void) 83 + { 84 + return test_harness(mmcr2_fcs_fch, "mmcr2_fcs_fch"); 85 + }
+74
tools/testing/selftests/powerpc/pmu/sampling_tests/mmcr2_l2l3_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright 2022, Madhavan Srinivasan, IBM Corp. 4 + */ 5 + 6 + #include <stdio.h> 7 + #include <stdlib.h> 8 + 9 + #include "../event.h" 10 + #include "misc.h" 11 + #include "utils.h" 12 + 13 + /* All successful D-side store dispatches for this thread */ 14 + #define EventCode 0x010000046080 15 + 16 + #define MALLOC_SIZE (0x10000 * 10) /* Ought to be enough .. */ 17 + 18 + /* 19 + * A perf sampling test for mmcr2 20 + * fields : l2l3 21 + */ 22 + static int mmcr2_l2l3(void) 23 + { 24 + struct event event; 25 + u64 *intr_regs; 26 + char *p; 27 + int i; 28 + 29 + /* Check for platform support for the test */ 30 + SKIP_IF(check_pvr_for_sampling_tests()); 31 + SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1)); 32 + 33 + /* Init the event for the sampling test */ 34 + event_init_sampling(&event, EventCode); 35 + event.attr.sample_regs_intr = platform_extended_mask; 36 + FAIL_IF(event_open(&event)); 37 + event.mmap_buffer = event_sample_buf_mmap(event.fd, 1); 38 + 39 + FAIL_IF(event_enable(&event)); 40 + 41 + /* workload to make the event overflow */ 42 + p = malloc(MALLOC_SIZE); 43 + FAIL_IF(!p); 44 + 45 + for (i = 0; i < MALLOC_SIZE; i += 0x10000) 46 + p[i] = i; 47 + 48 + FAIL_IF(event_disable(&event)); 49 + 50 + /* Check for sample count */ 51 + FAIL_IF(!collect_samples(event.mmap_buffer)); 52 + 53 + intr_regs = get_intr_regs(&event, event.mmap_buffer); 54 + 55 + /* Check for intr_regs */ 56 + FAIL_IF(!intr_regs); 57 + 58 + /* 59 + * Verify that l2l3 field of MMCR2 match with 60 + * corresponding event code field 61 + */ 62 + FAIL_IF(EV_CODE_EXTRACT(event.attr.config, l2l3) != 63 + get_mmcr2_l2l3(get_reg_value(intr_regs, "MMCR2"), 4)); 64 + 65 + event_close(&event); 66 + free(p); 67 + 68 + return 0; 69 + } 70 + 71 + int main(void) 72 + { 73 + return test_harness(mmcr2_l2l3, "mmcr2_l2l3"); 74 + }
+67
tools/testing/selftests/powerpc/pmu/sampling_tests/mmcr3_src_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright 2022, Kajol Jain, IBM Corp. 4 + */ 5 + 6 + #include <stdio.h> 7 + #include <stdlib.h> 8 + 9 + #include "../event.h" 10 + #include "misc.h" 11 + #include "utils.h" 12 + 13 + extern void thirty_two_instruction_loop_with_ll_sc(u64 loops, u64 *ll_sc_target); 14 + 15 + /* The data cache was reloaded from local core's L3 due to a demand load */ 16 + #define EventCode 0x1340000001c040 17 + 18 + /* 19 + * A perf sampling test for mmcr3 20 + * fields. 21 + */ 22 + static int mmcr3_src(void) 23 + { 24 + struct event event; 25 + u64 *intr_regs; 26 + u64 dummy; 27 + 28 + /* Check for platform support for the test */ 29 + SKIP_IF(check_pvr_for_sampling_tests()); 30 + SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_1)); 31 + 32 + /* Init the event for the sampling test */ 33 + event_init_sampling(&event, EventCode); 34 + event.attr.sample_regs_intr = platform_extended_mask; 35 + FAIL_IF(event_open(&event)); 36 + event.mmap_buffer = event_sample_buf_mmap(event.fd, 1); 37 + 38 + FAIL_IF(event_enable(&event)); 39 + 40 + /* workload to make event overflow */ 41 + thirty_two_instruction_loop_with_ll_sc(1000000, &dummy); 42 + 43 + FAIL_IF(event_disable(&event)); 44 + 45 + /* Check for sample count */ 46 + FAIL_IF(!collect_samples(event.mmap_buffer)); 47 + 48 + intr_regs = get_intr_regs(&event, event.mmap_buffer); 49 + 50 + /* Check for intr_regs */ 51 + FAIL_IF(!intr_regs); 52 + 53 + /* 54 + * Verify that src field of MMCR3 match with 55 + * corresponding event code field 56 + */ 57 + FAIL_IF(EV_CODE_EXTRACT(event.attr.config, mmcr3_src) != 58 + get_mmcr3_src(get_reg_value(intr_regs, "MMCR3"), 1)); 59 + 60 + event_close(&event); 61 + return 0; 62 + } 63 + 64 + int main(void) 65 + { 66 + return test_harness(mmcr3_src, "mmcr3_src"); 67 + }
+80
tools/testing/selftests/powerpc/pmu/sampling_tests/mmcra_thresh_marked_sample_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright 2022, Kajol Jain, IBM Corp. 4 + */ 5 + 6 + #include <stdio.h> 7 + #include <stdlib.h> 8 + 9 + #include "../event.h" 10 + #include "misc.h" 11 + #include "utils.h" 12 + 13 + /* 14 + * Primary PMU event used here is PM_MRK_INST_CMPL (0x401e0) 15 + * Threshold event selection used is issue to complete for cycles 16 + * Sampling criteria is Load only sampling 17 + */ 18 + #define EventCode 0x35340401e0 19 + 20 + extern void thirty_two_instruction_loop_with_ll_sc(u64 loops, u64 *ll_sc_target); 21 + 22 + /* A perf sampling test to test mmcra fields */ 23 + static int mmcra_thresh_marked_sample(void) 24 + { 25 + struct event event; 26 + u64 *intr_regs; 27 + u64 dummy; 28 + 29 + /* Check for platform support for the test */ 30 + SKIP_IF(check_pvr_for_sampling_tests()); 31 + 32 + /* Init the event for the sampling test */ 33 + event_init_sampling(&event, EventCode); 34 + event.attr.sample_regs_intr = platform_extended_mask; 35 + FAIL_IF(event_open(&event)); 36 + event.mmap_buffer = event_sample_buf_mmap(event.fd, 1); 37 + 38 + FAIL_IF(event_enable(&event)); 39 + 40 + /* workload to make the event overflow */ 41 + thirty_two_instruction_loop_with_ll_sc(1000000, &dummy); 42 + 43 + FAIL_IF(event_disable(&event)); 44 + 45 + /* Check for sample count */ 46 + FAIL_IF(!collect_samples(event.mmap_buffer)); 47 + 48 + intr_regs = get_intr_regs(&event, event.mmap_buffer); 49 + 50 + /* Check for intr_regs */ 51 + FAIL_IF(!intr_regs); 52 + 53 + /* 54 + * Verify that thresh sel/start/stop, marked, random sample 55 + * eligibility, sdar mode and sample mode fields match with 56 + * the corresponding event code fields 57 + */ 58 + FAIL_IF(EV_CODE_EXTRACT(event.attr.config, thd_sel) != 59 + get_mmcra_thd_sel(get_reg_value(intr_regs, "MMCRA"), 4)); 60 + FAIL_IF(EV_CODE_EXTRACT(event.attr.config, thd_start) != 61 + get_mmcra_thd_start(get_reg_value(intr_regs, "MMCRA"), 4)); 62 + FAIL_IF(EV_CODE_EXTRACT(event.attr.config, thd_stop) != 63 + get_mmcra_thd_stop(get_reg_value(intr_regs, "MMCRA"), 4)); 64 + FAIL_IF(EV_CODE_EXTRACT(event.attr.config, marked) != 65 + get_mmcra_marked(get_reg_value(intr_regs, "MMCRA"), 4)); 66 + FAIL_IF(EV_CODE_EXTRACT(event.attr.config, sample >> 2) != 67 + get_mmcra_rand_samp_elig(get_reg_value(intr_regs, "MMCRA"), 4)); 68 + FAIL_IF(EV_CODE_EXTRACT(event.attr.config, sample & 0x3) != 69 + get_mmcra_sample_mode(get_reg_value(intr_regs, "MMCRA"), 4)); 70 + FAIL_IF(EV_CODE_EXTRACT(event.attr.config, sm) != 71 + get_mmcra_sm(get_reg_value(intr_regs, "MMCRA"), 4)); 72 + 73 + event_close(&event); 74 + return 0; 75 + } 76 + 77 + int main(void) 78 + { 79 + return test_harness(mmcra_thresh_marked_sample, "mmcra_thresh_marked_sample"); 80 + }
-2
tools/testing/selftests/powerpc/security/spectre_v2.c
··· 125 125 #define PM_BR_PRED_PCACHE 0x048a0 // P9 only 126 126 #define PM_BR_MPRED_PCACHE 0x048b0 // P9 only 127 127 128 - #define SPRN_PVR 287 129 - 130 128 int spectre_v2_test(void) 131 129 { 132 130 enum spectre_v2_state state;