summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--MAINTAINERS4
-rw-r--r--arch/powerpc/Kconfig1
-rw-r--r--arch/powerpc/boot/dts/Makefile73
-rw-r--r--arch/powerpc/boot/dts/fsl/Makefile43
-rw-r--r--arch/powerpc/boot/dts/mpc8308_p1m.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8308rdb.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8315erdb.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc836x_rdk.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8377_rdb.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8377_wlan.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8378_rdb.dts1
-rw-r--r--arch/powerpc/boot/dts/mpc8379_rdb.dts1
-rw-r--r--arch/powerpc/boot/hack-coff.c2
-rw-r--r--arch/powerpc/boot/rs6000.h84
-rwxr-xr-xarch/powerpc/boot/wrapper1
-rw-r--r--arch/powerpc/include/asm/entry-common.h534
-rw-r--r--arch/powerpc/include/asm/hw_irq.h4
-rw-r--r--arch/powerpc/include/asm/interrupt.h386
-rw-r--r--arch/powerpc/include/asm/kasan.h15
-rw-r--r--arch/powerpc/include/asm/prom.h4
-rw-r--r--arch/powerpc/include/asm/ptrace.h6
-rw-r--r--arch/powerpc/include/asm/rtas-types.h5
-rw-r--r--arch/powerpc/include/asm/signal.h1
-rw-r--r--arch/powerpc/include/asm/stacktrace.h6
-rw-r--r--arch/powerpc/include/asm/syscall.h5
-rw-r--r--arch/powerpc/include/asm/thread_info.h1
-rw-r--r--arch/powerpc/include/asm/uaccess.h26
-rw-r--r--arch/powerpc/include/uapi/asm/ptrace.h14
-rw-r--r--arch/powerpc/kernel/cacheinfo.c13
-rw-r--r--arch/powerpc/kernel/eeh_sysfs.c8
-rw-r--r--arch/powerpc/kernel/fadump.c14
-rw-r--r--arch/powerpc/kernel/interrupt.c255
-rw-r--r--arch/powerpc/kernel/iommu.c3
-rw-r--r--arch/powerpc/kernel/irq.c5
-rw-r--r--arch/powerpc/kernel/prom_init.c2
-rw-r--r--arch/powerpc/kernel/ptrace/ptrace.c142
-rw-r--r--arch/powerpc/kernel/security.c13
-rw-r--r--arch/powerpc/kernel/setup-common.c15
-rw-r--r--arch/powerpc/kernel/signal.c25
-rw-r--r--arch/powerpc/kernel/syscall.c119
-rw-r--r--arch/powerpc/kernel/sysfs.c23
-rw-r--r--arch/powerpc/kernel/traps.c2
-rw-r--r--arch/powerpc/kernel/watchdog.c2
-rw-r--r--arch/powerpc/kexec/core_64.c4
-rw-r--r--arch/powerpc/mm/book3s64/hash_utils.c4
-rw-r--r--arch/powerpc/net/Makefile4
-rw-r--r--arch/powerpc/net/bpf_jit_comp.c5
-rw-r--r--arch/powerpc/net/bpf_jit_comp64.c62
-rw-r--r--arch/powerpc/net/bpf_timed_may_goto.S57
-rw-r--r--arch/powerpc/perf/core-book3s.c5
-rw-r--r--arch/powerpc/perf/core-fsl-emb.c3
-rw-r--r--arch/powerpc/perf/hv-24x7.c18
-rw-r--r--arch/powerpc/perf/hv-gpci.c5
-rw-r--r--arch/powerpc/perf/imc-pmu.c6
-rw-r--r--arch/powerpc/perf/kvm-hv-pmu.c3
-rw-r--r--arch/powerpc/perf/vpa-pmu.c3
-rw-r--r--arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c3
-rw-r--r--arch/powerpc/platforms/8xx/cpm1.c26
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c5
-rw-r--r--arch/powerpc/platforms/powernv/idle.c3
-rw-r--r--arch/powerpc/platforms/powernv/opal-dump.c11
-rw-r--r--arch/powerpc/platforms/powernv/opal-elog.c9
-rw-r--r--arch/powerpc/platforms/powernv/opal-flash.c4
-rw-r--r--arch/powerpc/platforms/powernv/opal-powercap.c12
-rw-r--r--arch/powerpc/platforms/powernv/opal-psr.c12
-rw-r--r--arch/powerpc/platforms/powernv/setup.c3
-rw-r--r--arch/powerpc/platforms/powernv/subcore.c3
-rw-r--r--arch/powerpc/platforms/ps3/setup.c3
-rw-r--r--arch/powerpc/platforms/pseries/cmm.c5
-rw-r--r--arch/powerpc/platforms/pseries/dlpar.c3
-rw-r--r--arch/powerpc/platforms/pseries/ibmebus.c5
-rw-r--r--arch/powerpc/platforms/pseries/lparcfg.c24
-rw-r--r--arch/powerpc/platforms/pseries/papr_scm.c5
-rw-r--r--arch/powerpc/platforms/pseries/power.c3
-rw-r--r--arch/powerpc/platforms/pseries/pseries_energy.c3
-rw-r--r--arch/powerpc/platforms/pseries/rtas-fadump.c80
-rw-r--r--arch/powerpc/platforms/pseries/rtas-fadump.h6
-rw-r--r--arch/powerpc/platforms/pseries/suspend.c3
-rw-r--r--arch/powerpc/platforms/pseries/vas-sysfs.c3
-rw-r--r--arch/powerpc/platforms/pseries/vio.c29
-rw-r--r--arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c3
-rw-r--r--arch/powerpc/sysdev/xive/common.c1
82 files changed, 1242 insertions, 1068 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 16ce0c0537e8..9f4ddd4c69f8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -12428,13 +12428,13 @@ L: linux-crypto@vger.kernel.org
S: Supported
F: arch/powerpc/crypto/Kconfig
F: arch/powerpc/crypto/Makefile
-F: arch/powerpc/crypto/aes.c
F: arch/powerpc/crypto/aes_cbc.c
F: arch/powerpc/crypto/aes_ctr.c
F: arch/powerpc/crypto/aes_xts.c
-F: arch/powerpc/crypto/aesp8-ppc.*
+F: arch/powerpc/crypto/aesp8-ppc.h
F: arch/powerpc/crypto/ppc-xlate.pl
F: arch/powerpc/crypto/vmx.c
+F: lib/crypto/powerpc/aesp8-ppc.pl
F: lib/crypto/powerpc/gf128hash.h
F: lib/crypto/powerpc/ghashp8-ppc.pl
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index c99fd8335ddc..f7ce5fff81f0 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -206,6 +206,7 @@ config PPC
select GENERIC_CPU_AUTOPROBE
select GENERIC_CPU_VULNERABILITIES if PPC_BARRIER_NOSPEC
select GENERIC_EARLY_IOREMAP
+ select GENERIC_ENTRY
select GENERIC_GETTIMEOFDAY
select GENERIC_IDLE_POLL_SETUP
select GENERIC_IOREMAP
diff --git a/arch/powerpc/boot/dts/Makefile b/arch/powerpc/boot/dts/Makefile
index 0cd0d8558b47..1e61a951cebe 100644
--- a/arch/powerpc/boot/dts/Makefile
+++ b/arch/powerpc/boot/dts/Makefile
@@ -3,3 +3,76 @@
subdir-y += fsl
dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(src)/%.dts,%.dtb, $(wildcard $(src)/*.dts))
+
+# PPC44x platforms
+dtb-$(CONFIG_PPC44x_SIMPLE) += arches.dtb bamboo.dtb bluestone.dtb glacier.dtb
+dtb-$(CONFIG_PPC44x_SIMPLE) += eiger.dtb katmai.dtb rainier.dtb redwood.dtb
+dtb-$(CONFIG_PPC44x_SIMPLE) += sequoia.dtb taishan.dtb yosemite.dtb icon.dtb
+dtb-$(CONFIG_EBONY) += ebony.dtb
+dtb-$(CONFIG_SAM440EP) += sam440ep.dtb
+dtb-$(CONFIG_WARP) += warp.dtb
+dtb-$(CONFIG_ISS4xx) += iss4xx.dtb iss4xx-mpic.dtb
+dtb-$(CONFIG_CANYONLANDS) += canyonlands.dtb
+dtb-$(CONFIG_CURRITUCK) += currituck.dtb
+dtb-$(CONFIG_AKEBONO) += akebono.dtb
+dtb-$(CONFIG_FSP2) += fsp2.dtb
+
+# Embedded 6xx platforms
+dtb-$(CONFIG_LINKSTATION) += kuroboxHG.dtb kuroboxHD.dtb
+dtb-$(CONFIG_STORCENTER) += storcenter.dtb
+dtb-$(CONFIG_PPC_HOLLY) += holly.dtb
+dtb-$(CONFIG_GAMECUBE) += gamecube.dtb
+dtb-$(CONFIG_WII) += wii.dtb
+dtb-$(CONFIG_MVME5100) += mvme5100.dtb
+
+# MPC8xx platforms
+dtb-$(CONFIG_MPC885ADS) += mpc885ads.dtb
+dtb-$(CONFIG_MPC86XADS) += mpc866ads.dtb
+dtb-$(CONFIG_PPC_EP88XC) += ep88xc.dtb
+dtb-$(CONFIG_PPC_ADDER875) += adder875-redboot.dtb adder875-uboot.dtb
+dtb-$(CONFIG_TQM8XX) += tqm8xx.dtb
+
+# MPC512x platforms
+dtb-$(CONFIG_MPC5121_ADS) += mpc5121ads.dtb
+dtb-$(CONFIG_MPC512x_GENERIC) += mpc5125twr.dtb ac14xx.dts
+dtb-$(CONFIG_PDM360NG) += pdm360ng.dtb
+
+# MPC5200 platforms
+dtb-$(CONFIG_PPC_MPC5200_SIMPLE) += a3m071.dtb a4m072.dtb charon.dtb cm5200.dtb
+dtb-$(CONFIG_PPC_MPC5200_SIMPLE) += digsy_mtc.dtb motionpro.dtb mucmc52.dtb
+dtb-$(CONFIG_PPC_MPC5200_SIMPLE) += o2d.dtb o2d300.dtb o2dnt2.dtb o2i.dtb
+dtb-$(CONFIG_PPC_MPC5200_SIMPLE) += o2mnt.dtb o3dnt.dtb pcm030.dtb pcm032.dtb
+dtb-$(CONFIG_PPC_MPC5200_SIMPLE) += tqm5200.dtb uc101.dtb
+dtb-$(CONFIG_PPC_LITE5200) += lite5200.dtb lite5200b.dtb
+dtb-$(CONFIG_PPC_MEDIA5200) += media5200.dtb
+
+# MPC82xx platforms
+dtb-$(CONFIG_EP8248E) += ep8248e.dtb
+dtb-$(CONFIG_MGCOGE) += mgcoge.dtb
+
+# MPC83xx platforms
+dtb-$(CONFIG_MPC830x_RDB) += mpc8308rdb.dtb mpc8308_p1m.dtb
+dtb-$(CONFIG_MPC831x_RDB) += mpc8313erdb.dtb mpc8315erdb.dtb
+dtb-$(CONFIG_MPC832x_RDB) += mpc832x_rdb.dtb
+dtb-$(CONFIG_MPC834x_ITX) += mpc8349emitx.dtb mpc8349emitxgp.dtb
+dtb-$(CONFIG_ASP834x) += asp834x-redboot.dtb
+dtb-$(CONFIG_MPC836x_RDK) += mpc836x_rdk.dtb
+dtb-$(CONFIG_KMETER1) += kmeter1.dtb
+dtb-$(CONFIG_MPC837x_RDB) += mpc8377_rdb.dtb mpc8378_rdb.dtb mpc8379_rdb.dtb
+dtb-$(CONFIG_MPC837x_RDB) += mpc8377_wlan.dtb
+
+# MPC85xx platforms
+dtb-$(CONFIG_STX_GP3) += stx_gp3_8560.dtb stxssa8555.dtb
+dtb-$(CONFIG_TQM85xx) += tqm8540.dtb tqm8541.dtb tqm8548.dtb
+dtb-$(CONFIG_TQM85xx) += tqm8548-bigflash.dtb tqm8555.dtb tqm8560.dtb
+dtb-$(CONFIG_SOCRATES) += socrates.dtb
+dtb-$(CONFIG_KSI8560) += ksi8560.dtb
+dtb-$(CONFIG_XES_MPC85xx) += xcalibur1501.dtb xpedite5200.dtb
+dtb-$(CONFIG_XES_MPC85xx) += xpedite5200_xmon.dtb xpedite5301.dtb
+dtb-$(CONFIG_XES_MPC85xx) += xpedite5330.dtb xpedite5370.dtb
+dtb-$(CONFIG_PPC_P2020) += turris1x.dtb
+
+# Misc. platforms
+dtb-$(CONFIG_PPC_MICROWATT) += microwatt.dtb
+dtb-$(CONFIG_AMIGAONE) += amigaone.dtb
+dtb-$(CONFIG_PPC_PS3) += ps3.dtb
diff --git a/arch/powerpc/boot/dts/fsl/Makefile b/arch/powerpc/boot/dts/fsl/Makefile
index d3ecdf14bc42..d2cc8e1f007e 100644
--- a/arch/powerpc/boot/dts/fsl/Makefile
+++ b/arch/powerpc/boot/dts/fsl/Makefile
@@ -1,3 +1,46 @@
# SPDX-License-Identifier: GPL-2.0
dtb-$(CONFIG_OF_ALL_DTBS) := $(patsubst $(src)/%.dts,%.dtb, $(wildcard $(src)/*.dts))
+
+# MPC85xx platforms
+dtb-$(CONFIG_BSC9131_RDB) += bsc9131rdb.dtb
+dtb-$(CONFIG_BSC9132_QDS) += bsc9132qds.dtb
+dtb-$(CONFIG_C293_PCIE) += c293pcie.dtb
+dtb-$(CONFIG_MPC8536_DS) += mpc8536ds.dtb mpc8536ds_36b.dtb
+dtb-$(CONFIG_MPC85xx_DS) += mpc8544ds.dtb mpc8572ds_camp_core0.dtb
+dtb-$(CONFIG_MPC85xx_DS) += mpc8572ds_camp_core1.dtb mpc8572ds_36b.dtb
+dtb-$(CONFIG_MPC85xx_DS) += mpc8572ds.dtb
+dtb-$(CONFIG_MPC85xx_MDS) += mpc8568mds.dtb mpc8569mds.dtb p1021mds.dtb
+dtb-$(CONFIG_MPC85xx_RDB) += p1020mbg-pc_32b.dtb p1020mbg-pc_36b.dtb
+dtb-$(CONFIG_MPC85xx_RDB) += p1020rdb_36b.dtb p1020rdb.dtb p1020rdb-pc_32b.dtb
+dtb-$(CONFIG_MPC85xx_RDB) += p1020rdb-pc_36b.dtb p1020rdb-pc_camp_core0.dtb
+dtb-$(CONFIG_MPC85xx_RDB) += p1020rdb-pc_camp_core1.dtb p1020rdb-pd.dtb
+dtb-$(CONFIG_MPC85xx_RDB) += p1020utm-pc_32b.dtb p1020utm-pc_36b.dtb
+dtb-$(CONFIG_MPC85xx_RDB) += p1021rdb-pc_32b.dtb p1021rdb-pc_36b.dtb
+dtb-$(CONFIG_MPC85xx_RDB) += p1024rdb_32b.dtb p1024rdb_36b.dtb p1025rdb_32b.dtb
+dtb-$(CONFIG_MPC85xx_RDB) += p1025rdb_36b.dtb
+dtb-$(CONFIG_P1010_RDB) += p1010rdb-pa_36b.dtb p1010rdb-pa.dtb
+dtb-$(CONFIG_P1010_RDB) += p1010rdb-pb_36b.dtb p1010rdb-pb.dtb
+dtb-$(CONFIG_P1022_DS) += p1022ds_32b.dtb p1022ds_36b.dtb
+dtb-$(CONFIG_P1022_RDK) += p1022rdk.dtb
+dtb-$(CONFIG_P1023_RDB) += p1023rdb.dtb
+dtb-$(CONFIG_PPC_P2020) += p2020ds.dtb
+dtb-$(CONFIG_TWR_P102x) += p1025twr.dtb
+dtb-$(CONFIG_CORENET_GENERIC) += b4420qds.dtb b4860qds.dtb cyrus_p5020.dtb
+dtb-$(CONFIG_CORENET_GENERIC) += kmcent2.dtb kmcoge4.dtb oca4080.dtb
+dtb-$(CONFIG_CORENET_GENERIC) += p2041rdb.dtb p3041ds.dtb p4080ds.dtb
+dtb-$(CONFIG_CORENET_GENERIC) += p5020ds.dtb p5040ds.dtb t1023rdb.dtb
+dtb-$(CONFIG_CORENET_GENERIC) += t1024qds.dtb t1024rdb.dtb t1040d4rdb.dtb
+dtb-$(CONFIG_CORENET_GENERIC) += t1040qds.dtb t1040rdb.dtb t1040rdb-rev-a.dtb
+dtb-$(CONFIG_CORENET_GENERIC) += t1042d4rdb.dtb t1042qds.dtb t1042rdb.dtb
+dtb-$(CONFIG_CORENET_GENERIC) += t1042rdb_pi.dtb t2080qds.dtb t2080rdb.dtb
+dtb-$(CONFIG_CORENET_GENERIC) += t2081qds.dtb t4240qds.dtb t4240rdb.dtb
+dtb-$(CONFIG_PPA8548) += ppa8548.dtb
+dtb-$(CONFIG_GE_IMP3A) += ge_imp3a.dtb
+dtb-$(CONFIG_MVME2500) += mvme2500.dtb
+
+# MPC86xx platforms
+dtb-$(CONFIG_GEF_SBC310) += gef_sbc310.dtb
+dtb-$(CONFIG_GEF_SBC610) += gef_sbc610.dtb
+dtb-$(CONFIG_GEF_PPC9A) += gef_ppc9a.dtb
+dtb-$(CONFIG_MVME7100) += mvme7100.dtb
diff --git a/arch/powerpc/boot/dts/mpc8308_p1m.dts b/arch/powerpc/boot/dts/mpc8308_p1m.dts
index 41f917f97dab..5af945e1743c 100644
--- a/arch/powerpc/boot/dts/mpc8308_p1m.dts
+++ b/arch/powerpc/boot/dts/mpc8308_p1m.dts
@@ -9,6 +9,7 @@
/ {
compatible = "denx,mpc8308_p1m";
+ model = "denx,mpc8308_p1m";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc8308rdb.dts b/arch/powerpc/boot/dts/mpc8308rdb.dts
index 39ed26fba410..7b6fd58ffafa 100644
--- a/arch/powerpc/boot/dts/mpc8308rdb.dts
+++ b/arch/powerpc/boot/dts/mpc8308rdb.dts
@@ -10,6 +10,7 @@
/ {
compatible = "fsl,mpc8308rdb";
+ model = "fsl,mpc8308rdb";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc8315erdb.dts b/arch/powerpc/boot/dts/mpc8315erdb.dts
index 7ba1159f8803..4757f0d24a2e 100644
--- a/arch/powerpc/boot/dts/mpc8315erdb.dts
+++ b/arch/powerpc/boot/dts/mpc8315erdb.dts
@@ -10,6 +10,7 @@
/ {
compatible = "fsl,mpc8315erdb";
+ model = "MPC8315E-RDB";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc836x_rdk.dts b/arch/powerpc/boot/dts/mpc836x_rdk.dts
index 4ff38e1a2185..d3d36fbf4e86 100644
--- a/arch/powerpc/boot/dts/mpc836x_rdk.dts
+++ b/arch/powerpc/boot/dts/mpc836x_rdk.dts
@@ -14,6 +14,7 @@
#address-cells = <1>;
#size-cells = <1>;
compatible = "fsl,mpc8360rdk";
+ model = "fsl,mpc8360rdk";
aliases {
serial0 = &serial0;
diff --git a/arch/powerpc/boot/dts/mpc8377_rdb.dts b/arch/powerpc/boot/dts/mpc8377_rdb.dts
index fb311a7eb9f2..f4244a7a3189 100644
--- a/arch/powerpc/boot/dts/mpc8377_rdb.dts
+++ b/arch/powerpc/boot/dts/mpc8377_rdb.dts
@@ -9,6 +9,7 @@
/ {
compatible = "fsl,mpc8377rdb";
+ model = "fsl,mpc8377rdb";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc8377_wlan.dts b/arch/powerpc/boot/dts/mpc8377_wlan.dts
index f736a15cceff..77ee5f8db14e 100644
--- a/arch/powerpc/boot/dts/mpc8377_wlan.dts
+++ b/arch/powerpc/boot/dts/mpc8377_wlan.dts
@@ -10,6 +10,7 @@
/ {
compatible = "fsl,mpc8377wlan";
+ model = "fsl,mpc8377wlan";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc8378_rdb.dts b/arch/powerpc/boot/dts/mpc8378_rdb.dts
index 32c49622b404..9ae4ed5ffcf4 100644
--- a/arch/powerpc/boot/dts/mpc8378_rdb.dts
+++ b/arch/powerpc/boot/dts/mpc8378_rdb.dts
@@ -9,6 +9,7 @@
/ {
compatible = "fsl,mpc8378rdb";
+ model = "fsl,mpc8378rdb";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/powerpc/boot/dts/mpc8379_rdb.dts b/arch/powerpc/boot/dts/mpc8379_rdb.dts
index 07deb89c5a9b..214611dc6da9 100644
--- a/arch/powerpc/boot/dts/mpc8379_rdb.dts
+++ b/arch/powerpc/boot/dts/mpc8379_rdb.dts
@@ -9,6 +9,7 @@
/ {
compatible = "fsl,mpc8379rdb";
+ model = "fsl,mpc8379rdb";
#address-cells = <1>;
#size-cells = <1>;
diff --git a/arch/powerpc/boot/hack-coff.c b/arch/powerpc/boot/hack-coff.c
index a010e124ac4b..6bf0c94302f5 100644
--- a/arch/powerpc/boot/hack-coff.c
+++ b/arch/powerpc/boot/hack-coff.c
@@ -31,7 +31,7 @@ main(int ac, char **av)
int i, nsect;
int aoutsz;
struct external_filehdr fhdr;
- AOUTHDR aout;
+ struct aouthdr aout;
struct external_scnhdr shdr;
if (ac != 2) {
diff --git a/arch/powerpc/boot/rs6000.h b/arch/powerpc/boot/rs6000.h
index 16df8f3c43f1..970754a1f887 100644
--- a/arch/powerpc/boot/rs6000.h
+++ b/arch/powerpc/boot/rs6000.h
@@ -32,32 +32,30 @@ struct external_filehdr {
/********************** AOUT "OPTIONAL HEADER" **********************/
-typedef struct
-{
- unsigned char magic[2]; /* type of file */
- unsigned char vstamp[2]; /* version stamp */
- unsigned char tsize[4]; /* text size in bytes, padded to FW bdry */
- unsigned char dsize[4]; /* initialized data " " */
- unsigned char bsize[4]; /* uninitialized data " " */
- unsigned char entry[4]; /* entry pt. */
- unsigned char text_start[4]; /* base of text used for this file */
- unsigned char data_start[4]; /* base of data used for this file */
- unsigned char o_toc[4]; /* address of TOC */
- unsigned char o_snentry[2]; /* section number of entry point */
- unsigned char o_sntext[2]; /* section number of .text section */
- unsigned char o_sndata[2]; /* section number of .data section */
- unsigned char o_sntoc[2]; /* section number of TOC */
- unsigned char o_snloader[2]; /* section number of .loader section */
- unsigned char o_snbss[2]; /* section number of .bss section */
- unsigned char o_algntext[2]; /* .text alignment */
- unsigned char o_algndata[2]; /* .data alignment */
- unsigned char o_modtype[2]; /* module type (??) */
- unsigned char o_cputype[2]; /* cpu type */
- unsigned char o_maxstack[4]; /* max stack size (??) */
- unsigned char o_maxdata[4]; /* max data size (??) */
- unsigned char o_resv2[12]; /* reserved */
-}
-AOUTHDR;
+struct aouthdr {
+ unsigned char magic[2]; /* type of file */
+ unsigned char vstamp[2]; /* version stamp */
+ unsigned char tsize[4]; /* text size in bytes, padded to FW bdry */
+ unsigned char dsize[4]; /* initialized data " " */
+ unsigned char bsize[4]; /* uninitialized data " " */
+ unsigned char entry[4]; /* entry pt. */
+ unsigned char text_start[4]; /* base of text used for this file */
+ unsigned char data_start[4]; /* base of data used for this file */
+ unsigned char o_toc[4]; /* address of TOC */
+ unsigned char o_snentry[2]; /* section number of entry point */
+ unsigned char o_sntext[2]; /* section number of .text section */
+ unsigned char o_sndata[2]; /* section number of .data section */
+ unsigned char o_sntoc[2]; /* section number of TOC */
+ unsigned char o_snloader[2]; /* section number of .loader section */
+ unsigned char o_snbss[2]; /* section number of .bss section */
+ unsigned char o_algntext[2]; /* .text alignment */
+ unsigned char o_algndata[2]; /* .data alignment */
+ unsigned char o_modtype[2]; /* module type (??) */
+ unsigned char o_cputype[2]; /* cpu type */
+ unsigned char o_maxstack[4]; /* max stack size (??) */
+ unsigned char o_maxdata[4]; /* max data size (??) */
+ unsigned char o_resv2[12]; /* reserved */
+};
#define AOUTSZ 72
#define SMALL_AOUTSZ (28)
@@ -115,10 +113,10 @@ struct external_scnhdr {
*/
struct external_lineno {
union {
- char l_symndx[4]; /* function name symbol index, iff l_lnno == 0*/
+ char l_symndx[4]; /* function name symbol index, iff l_lnno == 0 */
char l_paddr[4]; /* (physical) address of line number */
} l_addr;
- char l_lnno[2]; /* line number */
+ char l_lnno[2]; /* line number */
};
@@ -132,20 +130,19 @@ struct external_lineno {
#define E_FILNMLEN 14 /* # characters in a file name */
#define E_DIMNUM 4 /* # array dimensions in auxiliary entry */
-struct external_syment
-{
- union {
- char e_name[E_SYMNMLEN];
- struct {
- char e_zeroes[4];
- char e_offset[4];
- } e;
- } e;
- char e_value[4];
- char e_scnum[2];
- char e_type[2];
- char e_sclass[1];
- char e_numaux[1];
+struct external_syment {
+ union {
+ char e_name[E_SYMNMLEN];
+ struct {
+ char e_zeroes[4];
+ char e_offset[4];
+ } e;
+ } e;
+ char e_value[4];
+ char e_scnum[2];
+ char e_type[2];
+ char e_sclass[1];
+ char e_numaux[1];
};
@@ -187,7 +184,7 @@ union external_auxent {
} x_file;
struct {
- char x_scnlen[4]; /* section length */
+ char x_scnlen[4]; /* section length */
char x_nreloc[2]; /* # relocation entries */
char x_nlinno[2]; /* # line numbers */
} x_scn;
@@ -207,7 +204,6 @@ union external_auxent {
unsigned char x_stab[4];
unsigned char x_snstab[2];
} x_csect;
-
};
#define SYMENT struct external_syment
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index 1efd1206fcab..25321ce262e8 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -262,6 +262,7 @@ pseries)
if [ "$format" != "elf32ppc" ]; then
link_address=
pie=-pie
+ notext='-z notext'
fi
make_space=n
;;
diff --git a/arch/powerpc/include/asm/entry-common.h b/arch/powerpc/include/asm/entry-common.h
new file mode 100644
index 000000000000..fc636c42e89a
--- /dev/null
+++ b/arch/powerpc/include/asm/entry-common.h
@@ -0,0 +1,534 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _ASM_PPC_ENTRY_COMMON_H
+#define _ASM_PPC_ENTRY_COMMON_H
+
+#include <asm/cputime.h>
+#include <asm/interrupt.h>
+#include <asm/runlatch.h>
+#include <asm/stacktrace.h>
+#include <asm/switch_to.h>
+#include <asm/tm.h>
+
+#ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG
+/*
+ * WARN/BUG is handled with a program interrupt so minimise checks here to
+ * avoid recursion and maximise the chance of getting the first oops handled.
+ */
+#define INT_SOFT_MASK_BUG_ON(regs, cond) \
+do { \
+ if ((user_mode(regs) || (TRAP(regs) != INTERRUPT_PROGRAM))) \
+ BUG_ON(cond); \
+} while (0)
+#else
+#define INT_SOFT_MASK_BUG_ON(regs, cond)
+#endif
+
+#ifdef CONFIG_PPC_BOOK3S_64
+extern char __end_soft_masked[];
+bool search_kernel_soft_mask_table(unsigned long addr);
+unsigned long search_kernel_restart_table(unsigned long addr);
+
+DECLARE_STATIC_KEY_FALSE(interrupt_exit_not_reentrant);
+
+static inline bool is_implicit_soft_masked(struct pt_regs *regs)
+{
+ if (user_mode(regs))
+ return false;
+
+ if (regs->nip >= (unsigned long)__end_soft_masked)
+ return false;
+
+ return search_kernel_soft_mask_table(regs->nip);
+}
+
+static inline void srr_regs_clobbered(void)
+{
+ local_paca->srr_valid = 0;
+ local_paca->hsrr_valid = 0;
+}
+#else
+static inline unsigned long search_kernel_restart_table(unsigned long addr)
+{
+ return 0;
+}
+
+static inline bool is_implicit_soft_masked(struct pt_regs *regs)
+{
+ return false;
+}
+
+static inline void srr_regs_clobbered(void)
+{
+}
+#endif
+
+static inline void nap_adjust_return(struct pt_regs *regs)
+{
+#ifdef CONFIG_PPC_970_NAP
+ if (unlikely(test_thread_local_flags(_TLF_NAPPING))) {
+ /* Can avoid a test-and-clear because NMIs do not call this */
+ clear_thread_local_flags(_TLF_NAPPING);
+ regs_set_return_ip(regs, (unsigned long)power4_idle_nap_return);
+ }
+#endif
+}
+
+static __always_inline void booke_load_dbcr0(void)
+{
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+ unsigned long dbcr0 = current->thread.debug.dbcr0;
+
+ if (likely(!(dbcr0 & DBCR0_IDM)))
+ return;
+
+ /*
+ * Check to see if the dbcr0 register is set up to debug.
+ * Use the internal debug mode bit to do this.
+ */
+ mtmsr(mfmsr() & ~MSR_DE);
+ if (IS_ENABLED(CONFIG_PPC32)) {
+ isync();
+ global_dbcr0[smp_processor_id()] = mfspr(SPRN_DBCR0);
+ }
+ mtspr(SPRN_DBCR0, dbcr0);
+ mtspr(SPRN_DBSR, -1);
+#endif
+}
+
+static inline void booke_restore_dbcr0(void)
+{
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+ unsigned long dbcr0 = current->thread.debug.dbcr0;
+
+ if (IS_ENABLED(CONFIG_PPC32) && unlikely(dbcr0 & DBCR0_IDM)) {
+ mtspr(SPRN_DBSR, -1);
+ mtspr(SPRN_DBCR0, global_dbcr0[smp_processor_id()]);
+ }
+#endif
+}
+
+static inline void check_return_regs_valid(struct pt_regs *regs)
+{
+#ifdef CONFIG_PPC_BOOK3S_64
+ unsigned long trap, srr0, srr1;
+ static bool warned;
+ u8 *validp;
+ char *h;
+
+ if (trap_is_scv(regs))
+ return;
+
+ trap = TRAP(regs);
+ // EE in HV mode sets HSRRs like 0xea0
+ if (cpu_has_feature(CPU_FTR_HVMODE) && trap == INTERRUPT_EXTERNAL)
+ trap = 0xea0;
+
+ switch (trap) {
+ case 0x980:
+ case INTERRUPT_H_DATA_STORAGE:
+ case 0xe20:
+ case 0xe40:
+ case INTERRUPT_HMI:
+ case 0xe80:
+ case 0xea0:
+ case INTERRUPT_H_FAC_UNAVAIL:
+ case 0x1200:
+ case 0x1500:
+ case 0x1600:
+ case 0x1800:
+ validp = &local_paca->hsrr_valid;
+ if (!READ_ONCE(*validp))
+ return;
+
+ srr0 = mfspr(SPRN_HSRR0);
+ srr1 = mfspr(SPRN_HSRR1);
+ h = "H";
+
+ break;
+ default:
+ validp = &local_paca->srr_valid;
+ if (!READ_ONCE(*validp))
+ return;
+
+ srr0 = mfspr(SPRN_SRR0);
+ srr1 = mfspr(SPRN_SRR1);
+ h = "";
+ break;
+ }
+
+ if (srr0 == regs->nip && srr1 == regs->msr)
+ return;
+
+ /*
+ * A NMI / soft-NMI interrupt may have come in after we found
+ * srr_valid and before the SRRs are loaded. The interrupt then
+ * comes in and clobbers SRRs and clears srr_valid. Then we load
+ * the SRRs here and test them above and find they don't match.
+ *
+ * Test validity again after that, to catch such false positives.
+ *
+ * This test in general will have some window for false negatives
+ * and may not catch and fix all such cases if an NMI comes in
+ * later and clobbers SRRs without clearing srr_valid, but hopefully
+ * such things will get caught most of the time, statistically
+ * enough to be able to get a warning out.
+ */
+ if (!READ_ONCE(*validp))
+ return;
+
+ if (!data_race(warned)) {
+ data_race(warned = true);
+ pr_warn("%sSRR0 was: %lx should be: %lx\n", h, srr0, regs->nip);
+ pr_warn("%sSRR1 was: %lx should be: %lx\n", h, srr1, regs->msr);
+ show_regs(regs);
+ }
+
+ WRITE_ONCE(*validp, 0); /* fixup */
+#endif
+}
+
+static inline void arch_interrupt_enter_prepare(struct pt_regs *regs)
+{
+#ifdef CONFIG_PPC64
+ irq_soft_mask_set(IRQS_ALL_DISABLED);
+
+ /*
+ * If the interrupt was taken with HARD_DIS clear, then enable MSR[EE].
+ * Asynchronous interrupts get here with HARD_DIS set (see below), so
+ * this enables MSR[EE] for synchronous interrupts. IRQs remain
+ * soft-masked. The interrupt handler may later call
+ * interrupt_cond_local_irq_enable() to achieve a regular process
+ * context.
+ */
+ if (!(local_paca->irq_happened & PACA_IRQ_HARD_DIS)) {
+ INT_SOFT_MASK_BUG_ON(regs, !(regs->msr & MSR_EE));
+ __hard_irq_enable();
+ } else {
+ __hard_RI_enable();
+ }
+ /* Enable MSR[RI] early, to support kernel SLB and hash faults */
+#endif
+
+ if (!regs_irqs_disabled(regs))
+ trace_hardirqs_off();
+
+ if (user_mode(regs)) {
+ kuap_lock();
+ account_cpu_user_entry();
+ account_stolen_time();
+ } else {
+ kuap_save_and_lock(regs);
+ /*
+ * CT_WARN_ON comes here via program_check_exception,
+ * so avoid recursion.
+ */
+ if (TRAP(regs) != INTERRUPT_PROGRAM)
+ CT_WARN_ON(ct_state() != CT_STATE_KERNEL &&
+ ct_state() != CT_STATE_IDLE);
+ INT_SOFT_MASK_BUG_ON(regs, is_implicit_soft_masked(regs));
+ INT_SOFT_MASK_BUG_ON(regs, regs_irqs_disabled(regs) &&
+ search_kernel_restart_table(regs->nip));
+ }
+ INT_SOFT_MASK_BUG_ON(regs, !regs_irqs_disabled(regs) &&
+ !(regs->msr & MSR_EE));
+
+ booke_restore_dbcr0();
+}
+
+/*
+ * Care should be taken to note that arch_interrupt_exit_prepare and
+ * arch_interrupt_async_exit_prepare do not necessarily return immediately to
+ * regs context (e.g., if regs is usermode, we don't necessarily return to
+ * user mode). Other interrupts might be taken between here and return,
+ * context switch / preemption may occur in the exit path after this, or a
+ * signal may be delivered, etc.
+ *
+ * The real interrupt exit code is platform specific, e.g.,
+ * interrupt_exit_user_prepare / interrupt_exit_kernel_prepare for 64s.
+ *
+ * However arch_interrupt_nmi_exit_prepare does return directly to regs, because
+ * NMIs do not do "exit work" or replay soft-masked interrupts.
+ */
+static inline void arch_interrupt_exit_prepare(struct pt_regs *regs)
+{
+ if (user_mode(regs)) {
+ BUG_ON(regs_is_unrecoverable(regs));
+ BUG_ON(regs_irqs_disabled(regs));
+ /*
+ * We don't need to restore AMR on the way back to userspace for KUAP.
+ * AMR can only have been unlocked if we interrupted the kernel.
+ */
+ kuap_assert_locked();
+ }
+
+ /* irqentry_exit expects to be called with interrupts disabled */
+ local_irq_disable();
+}
+
+static inline void arch_interrupt_async_enter_prepare(struct pt_regs *regs)
+{
+#ifdef CONFIG_PPC64
+ /* Ensure arch_interrupt_enter_prepare does not enable MSR[EE] */
+ local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
+#endif
+ arch_interrupt_enter_prepare(regs);
+#ifdef CONFIG_PPC_BOOK3S_64
+ /*
+ * RI=1 is set by arch_interrupt_enter_prepare, so this thread flags access
+ * has to come afterward (it can cause SLB faults).
+ */
+ if (cpu_has_feature(CPU_FTR_CTRL) &&
+ !test_thread_local_flags(_TLF_RUNLATCH))
+ __ppc64_runlatch_on();
+#endif
+}
+
+static inline void arch_interrupt_async_exit_prepare(struct pt_regs *regs)
+{
+ /*
+ * Adjust at exit so the main handler sees the true NIA. This must
+ * come before irq_exit() because irq_exit can enable interrupts, and
+ * if another interrupt is taken before nap_adjust_return has run
+ * here, then that interrupt would return directly to idle nap return.
+ */
+ nap_adjust_return(regs);
+
+ arch_interrupt_exit_prepare(regs);
+}
+
+struct interrupt_nmi_state {
+#ifdef CONFIG_PPC64
+ u8 irq_soft_mask;
+ u8 irq_happened;
+ u8 ftrace_enabled;
+ u64 softe;
+#endif
+};
+
+static inline bool nmi_disables_ftrace(struct pt_regs *regs)
+{
+ /* Allow DEC and PMI to be traced when they are soft-NMI */
+ if (IS_ENABLED(CONFIG_PPC_BOOK3S_64)) {
+ if (TRAP(regs) == INTERRUPT_DECREMENTER)
+ return false;
+ if (TRAP(regs) == INTERRUPT_PERFMON)
+ return false;
+ }
+ if (IS_ENABLED(CONFIG_PPC_BOOK3E_64)) {
+ if (TRAP(regs) == INTERRUPT_PERFMON)
+ return false;
+ }
+
+ return true;
+}
+
+static inline void arch_interrupt_nmi_enter_prepare(struct pt_regs *regs,
+ struct interrupt_nmi_state *state)
+{
+#ifdef CONFIG_PPC64
+ state->irq_soft_mask = local_paca->irq_soft_mask;
+ state->irq_happened = local_paca->irq_happened;
+ state->softe = regs->softe;
+
+ /*
+ * Set IRQS_ALL_DISABLED unconditionally so irqs_disabled() does
+ * the right thing, and set IRQ_HARD_DIS. We do not want to reconcile
+ * because that goes through irq tracing which we don't want in NMI.
+ */
+ local_paca->irq_soft_mask = IRQS_ALL_DISABLED;
+ local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
+
+ if (!(regs->msr & MSR_EE) || is_implicit_soft_masked(regs)) {
+ /*
+ * Adjust regs->softe to be soft-masked if it had not been
+ * reconcied (e.g., interrupt entry with MSR[EE]=0 but softe
+ * not yet set disabled), or if it was in an implicit soft
+ * masked state. This makes regs_irqs_disabled(regs)
+ * behave as expected.
+ */
+ regs->softe = IRQS_ALL_DISABLED;
+ }
+
+ __hard_RI_enable();
+
+ /* Don't do any per-CPU operations until interrupt state is fixed */
+
+ if (nmi_disables_ftrace(regs)) {
+ state->ftrace_enabled = this_cpu_get_ftrace_enabled();
+ this_cpu_set_ftrace_enabled(0);
+ }
+#endif
+}
+
+static inline void arch_interrupt_nmi_exit_prepare(struct pt_regs *regs,
+ struct interrupt_nmi_state *state)
+{
+ /*
+ * nmi does not call nap_adjust_return because nmi should not create
+ * new work to do (must use irq_work for that).
+ */
+
+#ifdef CONFIG_PPC64
+#ifdef CONFIG_PPC_BOOK3S
+ if (regs_irqs_disabled(regs)) {
+ unsigned long rst = search_kernel_restart_table(regs->nip);
+
+ if (rst)
+ regs_set_return_ip(regs, rst);
+ }
+#endif
+
+ if (nmi_disables_ftrace(regs))
+ this_cpu_set_ftrace_enabled(state->ftrace_enabled);
+
+ /* Check we didn't change the pending interrupt mask. */
+ WARN_ON_ONCE((state->irq_happened | PACA_IRQ_HARD_DIS) != local_paca->irq_happened);
+ regs->softe = state->softe;
+ local_paca->irq_happened = state->irq_happened;
+ local_paca->irq_soft_mask = state->irq_soft_mask;
+#endif
+}
+
+static __always_inline void arch_enter_from_user_mode(struct pt_regs *regs)
+{
+ kuap_lock();
+
+ if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
+ BUG_ON(irq_soft_mask_return() != IRQS_ALL_DISABLED);
+
+ BUG_ON(regs_is_unrecoverable(regs));
+ BUG_ON(!user_mode(regs));
+ BUG_ON(regs_irqs_disabled(regs));
+
+#ifdef CONFIG_PPC_PKEY
+ if (mmu_has_feature(MMU_FTR_PKEY) && trap_is_syscall(regs)) {
+ unsigned long amr, iamr;
+ bool flush_needed = false;
+ /*
+ * When entering from userspace we mostly have the AMR/IAMR
+ * different from kernel default values. Hence don't compare.
+ */
+ amr = mfspr(SPRN_AMR);
+ iamr = mfspr(SPRN_IAMR);
+ regs->amr = amr;
+ regs->iamr = iamr;
+ if (mmu_has_feature(MMU_FTR_KUAP)) {
+ mtspr(SPRN_AMR, AMR_KUAP_BLOCKED);
+ flush_needed = true;
+ }
+ if (mmu_has_feature(MMU_FTR_BOOK3S_KUEP)) {
+ mtspr(SPRN_IAMR, AMR_KUEP_BLOCKED);
+ flush_needed = true;
+ }
+ if (flush_needed)
+ isync();
+ }
+#endif
+ kuap_assert_locked();
+ booke_restore_dbcr0();
+ account_cpu_user_entry();
+ account_stolen_time();
+
+ /*
+ * This is not required for the syscall exit path, but makes the
+ * stack frame look nicer. If this was initialised in the first stack
+ * frame, or if the unwinder was taught the first stack frame always
+ * returns to user with IRQS_ENABLED, this store could be avoided!
+ */
+ irq_soft_mask_regs_set_state(regs, IRQS_ENABLED);
+
+ /*
+ * If system call is called with TM active, set _TIF_RESTOREALL to
+ * prevent RFSCV being used to return to userspace, because POWER9
+ * TM implementation has problems with this instruction returning to
+ * transactional state. Final register values are not relevant because
+ * the transaction will be aborted upon return anyway. Or in the case
+ * of unsupported_scv SIGILL fault, the return state does not much
+ * matter because it's an edge case.
+ */
+ if (IS_ENABLED(CONFIG_PPC_TRANSACTIONAL_MEM) &&
+ unlikely(MSR_TM_TRANSACTIONAL(regs->msr)))
+ set_bits(_TIF_RESTOREALL, &current_thread_info()->flags);
+
+ /*
+ * If the system call was made with a transaction active, doom it and
+ * return without performing the system call. Unless it was an
+ * unsupported scv vector, in which case it's treated like an illegal
+ * instruction.
+ */
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ if (unlikely(MSR_TM_TRANSACTIONAL(regs->msr)) &&
+ !trap_is_unsupported_scv(regs)) {
+ /* Enable TM in the kernel, and disable EE (for scv) */
+ hard_irq_disable();
+ mtmsr(mfmsr() | MSR_TM);
+
+ /* tabort, this dooms the transaction, nothing else */
+ asm volatile(".long 0x7c00071d | ((%0) << 16)"
+ :: "r"(TM_CAUSE_SYSCALL | TM_CAUSE_PERSISTENT));
+
+ /*
+ * Userspace will never see the return value. Execution will
+ * resume after the tbegin. of the aborted transaction with the
+ * checkpointed register state. A context switch could occur
+ * or signal delivered to the process before resuming the
+ * doomed transaction context, but that should all be handled
+ * as expected.
+ */
+ return;
+ }
+#endif /* CONFIG_PPC_TRANSACTIONAL_MEM */
+}
+
+#define arch_enter_from_user_mode arch_enter_from_user_mode
+
+static inline void arch_exit_to_user_mode_prepare(struct pt_regs *regs,
+ unsigned long ti_work)
+{
+ unsigned long mathflags;
+
+ if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && IS_ENABLED(CONFIG_PPC_FPU)) {
+ if (IS_ENABLED(CONFIG_PPC_TRANSACTIONAL_MEM) &&
+ unlikely((ti_work & _TIF_RESTORE_TM))) {
+ restore_tm_state(regs);
+ } else {
+ mathflags = MSR_FP;
+
+ if (cpu_has_feature(CPU_FTR_VSX))
+ mathflags |= MSR_VEC | MSR_VSX;
+ else if (cpu_has_feature(CPU_FTR_ALTIVEC))
+ mathflags |= MSR_VEC;
+
+ /*
+ * If userspace MSR has all available FP bits set,
+ * then they are live and no need to restore. If not,
+ * it means the regs were given up and restore_math
+ * may decide to restore them (to avoid taking an FP
+ * fault).
+ */
+ if ((regs->msr & mathflags) != mathflags)
+ restore_math(regs);
+ }
+ }
+
+ check_return_regs_valid(regs);
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+ local_paca->tm_scratch = regs->msr;
+#endif
+ /* Restore user access locks last */
+ kuap_user_restore(regs);
+}
+
+#define arch_exit_to_user_mode_prepare arch_exit_to_user_mode_prepare
+
+static __always_inline void arch_exit_to_user_mode(void)
+{
+ booke_load_dbcr0();
+
+ account_cpu_user_exit();
+}
+
+#define arch_exit_to_user_mode arch_exit_to_user_mode
+
+#endif /* _ASM_PPC_ENTRY_COMMON_H */
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h
index 9cd945f2acaf..b7eee6385ae5 100644
--- a/arch/powerpc/include/asm/hw_irq.h
+++ b/arch/powerpc/include/asm/hw_irq.h
@@ -393,7 +393,7 @@ static inline void do_hard_irq_enable(void)
__hard_irq_enable();
}
-static inline bool arch_irq_disabled_regs(struct pt_regs *regs)
+static inline bool regs_irqs_disabled(struct pt_regs *regs)
{
return (regs->softe & IRQS_DISABLED);
}
@@ -466,7 +466,7 @@ static inline bool arch_irqs_disabled(void)
#define hard_irq_disable() arch_local_irq_disable()
-static inline bool arch_irq_disabled_regs(struct pt_regs *regs)
+static inline bool regs_irqs_disabled(struct pt_regs *regs)
{
return !(regs->msr & MSR_EE);
}
diff --git a/arch/powerpc/include/asm/interrupt.h b/arch/powerpc/include/asm/interrupt.h
index eb0e4a20b818..fb42a664ae54 100644
--- a/arch/powerpc/include/asm/interrupt.h
+++ b/arch/powerpc/include/asm/interrupt.h
@@ -66,11 +66,9 @@
#ifndef __ASSEMBLER__
-#include <linux/context_tracking.h>
-#include <linux/hardirq.h>
-#include <asm/cputime.h>
-#include <asm/firmware.h>
-#include <asm/ftrace.h>
+#include <linux/sched/debug.h> /* for show_regs */
+#include <linux/irq-entry-common.h>
+
#include <asm/kprobes.h>
#include <asm/runlatch.h>
@@ -88,308 +86,6 @@ do { \
#define INT_SOFT_MASK_BUG_ON(regs, cond)
#endif
-#ifdef CONFIG_PPC_BOOK3S_64
-extern char __end_soft_masked[];
-bool search_kernel_soft_mask_table(unsigned long addr);
-unsigned long search_kernel_restart_table(unsigned long addr);
-
-DECLARE_STATIC_KEY_FALSE(interrupt_exit_not_reentrant);
-
-static inline bool is_implicit_soft_masked(struct pt_regs *regs)
-{
- if (user_mode(regs))
- return false;
-
- if (regs->nip >= (unsigned long)__end_soft_masked)
- return false;
-
- return search_kernel_soft_mask_table(regs->nip);
-}
-
-static inline void srr_regs_clobbered(void)
-{
- local_paca->srr_valid = 0;
- local_paca->hsrr_valid = 0;
-}
-#else
-static inline unsigned long search_kernel_restart_table(unsigned long addr)
-{
- return 0;
-}
-
-static inline bool is_implicit_soft_masked(struct pt_regs *regs)
-{
- return false;
-}
-
-static inline void srr_regs_clobbered(void)
-{
-}
-#endif
-
-static inline void nap_adjust_return(struct pt_regs *regs)
-{
-#ifdef CONFIG_PPC_970_NAP
- if (unlikely(test_thread_local_flags(_TLF_NAPPING))) {
- /* Can avoid a test-and-clear because NMIs do not call this */
- clear_thread_local_flags(_TLF_NAPPING);
- regs_set_return_ip(regs, (unsigned long)power4_idle_nap_return);
- }
-#endif
-}
-
-static inline void booke_restore_dbcr0(void)
-{
-#ifdef CONFIG_PPC_ADV_DEBUG_REGS
- unsigned long dbcr0 = current->thread.debug.dbcr0;
-
- if (IS_ENABLED(CONFIG_PPC32) && unlikely(dbcr0 & DBCR0_IDM)) {
- mtspr(SPRN_DBSR, -1);
- mtspr(SPRN_DBCR0, global_dbcr0[smp_processor_id()]);
- }
-#endif
-}
-
-static inline void interrupt_enter_prepare(struct pt_regs *regs)
-{
-#ifdef CONFIG_PPC64
- irq_soft_mask_set(IRQS_ALL_DISABLED);
-
- /*
- * If the interrupt was taken with HARD_DIS clear, then enable MSR[EE].
- * Asynchronous interrupts get here with HARD_DIS set (see below), so
- * this enables MSR[EE] for synchronous interrupts. IRQs remain
- * soft-masked. The interrupt handler may later call
- * interrupt_cond_local_irq_enable() to achieve a regular process
- * context.
- */
- if (!(local_paca->irq_happened & PACA_IRQ_HARD_DIS)) {
- INT_SOFT_MASK_BUG_ON(regs, !(regs->msr & MSR_EE));
- __hard_irq_enable();
- } else {
- __hard_RI_enable();
- }
- /* Enable MSR[RI] early, to support kernel SLB and hash faults */
-#endif
-
- if (!arch_irq_disabled_regs(regs))
- trace_hardirqs_off();
-
- if (user_mode(regs)) {
- kuap_lock();
- CT_WARN_ON(ct_state() != CT_STATE_USER);
- user_exit_irqoff();
-
- account_cpu_user_entry();
- account_stolen_time();
- } else {
- kuap_save_and_lock(regs);
- /*
- * CT_WARN_ON comes here via program_check_exception,
- * so avoid recursion.
- */
- if (TRAP(regs) != INTERRUPT_PROGRAM)
- CT_WARN_ON(ct_state() != CT_STATE_KERNEL &&
- ct_state() != CT_STATE_IDLE);
- INT_SOFT_MASK_BUG_ON(regs, is_implicit_soft_masked(regs));
- INT_SOFT_MASK_BUG_ON(regs, arch_irq_disabled_regs(regs) &&
- search_kernel_restart_table(regs->nip));
- }
- INT_SOFT_MASK_BUG_ON(regs, !arch_irq_disabled_regs(regs) &&
- !(regs->msr & MSR_EE));
-
- booke_restore_dbcr0();
-}
-
-/*
- * Care should be taken to note that interrupt_exit_prepare and
- * interrupt_async_exit_prepare do not necessarily return immediately to
- * regs context (e.g., if regs is usermode, we don't necessarily return to
- * user mode). Other interrupts might be taken between here and return,
- * context switch / preemption may occur in the exit path after this, or a
- * signal may be delivered, etc.
- *
- * The real interrupt exit code is platform specific, e.g.,
- * interrupt_exit_user_prepare / interrupt_exit_kernel_prepare for 64s.
- *
- * However interrupt_nmi_exit_prepare does return directly to regs, because
- * NMIs do not do "exit work" or replay soft-masked interrupts.
- */
-static inline void interrupt_exit_prepare(struct pt_regs *regs)
-{
-}
-
-static inline void interrupt_async_enter_prepare(struct pt_regs *regs)
-{
-#ifdef CONFIG_PPC64
- /* Ensure interrupt_enter_prepare does not enable MSR[EE] */
- local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
-#endif
- interrupt_enter_prepare(regs);
-#ifdef CONFIG_PPC_BOOK3S_64
- /*
- * RI=1 is set by interrupt_enter_prepare, so this thread flags access
- * has to come afterward (it can cause SLB faults).
- */
- if (cpu_has_feature(CPU_FTR_CTRL) &&
- !test_thread_local_flags(_TLF_RUNLATCH))
- __ppc64_runlatch_on();
-#endif
- irq_enter();
-}
-
-static inline void interrupt_async_exit_prepare(struct pt_regs *regs)
-{
- /*
- * Adjust at exit so the main handler sees the true NIA. This must
- * come before irq_exit() because irq_exit can enable interrupts, and
- * if another interrupt is taken before nap_adjust_return has run
- * here, then that interrupt would return directly to idle nap return.
- */
- nap_adjust_return(regs);
-
- irq_exit();
- interrupt_exit_prepare(regs);
-}
-
-struct interrupt_nmi_state {
-#ifdef CONFIG_PPC64
- u8 irq_soft_mask;
- u8 irq_happened;
- u8 ftrace_enabled;
- u64 softe;
-#endif
-};
-
-static inline bool nmi_disables_ftrace(struct pt_regs *regs)
-{
- /* Allow DEC and PMI to be traced when they are soft-NMI */
- if (IS_ENABLED(CONFIG_PPC_BOOK3S_64)) {
- if (TRAP(regs) == INTERRUPT_DECREMENTER)
- return false;
- if (TRAP(regs) == INTERRUPT_PERFMON)
- return false;
- }
- if (IS_ENABLED(CONFIG_PPC_BOOK3E_64)) {
- if (TRAP(regs) == INTERRUPT_PERFMON)
- return false;
- }
-
- return true;
-}
-
-static inline void interrupt_nmi_enter_prepare(struct pt_regs *regs, struct interrupt_nmi_state *state)
-{
-#ifdef CONFIG_PPC64
- state->irq_soft_mask = local_paca->irq_soft_mask;
- state->irq_happened = local_paca->irq_happened;
- state->softe = regs->softe;
-
- /*
- * Set IRQS_ALL_DISABLED unconditionally so irqs_disabled() does
- * the right thing, and set IRQ_HARD_DIS. We do not want to reconcile
- * because that goes through irq tracing which we don't want in NMI.
- */
- local_paca->irq_soft_mask = IRQS_ALL_DISABLED;
- local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
-
- if (!(regs->msr & MSR_EE) || is_implicit_soft_masked(regs)) {
- /*
- * Adjust regs->softe to be soft-masked if it had not been
- * reconcied (e.g., interrupt entry with MSR[EE]=0 but softe
- * not yet set disabled), or if it was in an implicit soft
- * masked state. This makes arch_irq_disabled_regs(regs)
- * behave as expected.
- */
- regs->softe = IRQS_ALL_DISABLED;
- }
-
- __hard_RI_enable();
-
- /* Don't do any per-CPU operations until interrupt state is fixed */
-
- if (nmi_disables_ftrace(regs)) {
- state->ftrace_enabled = this_cpu_get_ftrace_enabled();
- this_cpu_set_ftrace_enabled(0);
- }
-#endif
-
- /* If data relocations are enabled, it's safe to use nmi_enter() */
- if (mfmsr() & MSR_DR) {
- nmi_enter();
- return;
- }
-
- /*
- * But do not use nmi_enter() for pseries hash guest taking a real-mode
- * NMI because not everything it touches is within the RMA limit.
- */
- if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) &&
- firmware_has_feature(FW_FEATURE_LPAR) &&
- !radix_enabled())
- return;
-
- /*
- * Likewise, don't use it if we have some form of instrumentation (like
- * KASAN shadow) that is not safe to access in real mode (even on radix)
- */
- if (IS_ENABLED(CONFIG_KASAN))
- return;
-
- /*
- * Likewise, do not use it in real mode if percpu first chunk is not
- * embedded. With CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK enabled there
- * are chances where percpu allocation can come from vmalloc area.
- */
- if (percpu_first_chunk_is_paged)
- return;
-
- /* Otherwise, it should be safe to call it */
- nmi_enter();
-}
-
-static inline void interrupt_nmi_exit_prepare(struct pt_regs *regs, struct interrupt_nmi_state *state)
-{
- if (mfmsr() & MSR_DR) {
- // nmi_exit if relocations are on
- nmi_exit();
- } else if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) &&
- firmware_has_feature(FW_FEATURE_LPAR) &&
- !radix_enabled()) {
- // no nmi_exit for a pseries hash guest taking a real mode exception
- } else if (IS_ENABLED(CONFIG_KASAN)) {
- // no nmi_exit for KASAN in real mode
- } else if (percpu_first_chunk_is_paged) {
- // no nmi_exit if percpu first chunk is not embedded
- } else {
- nmi_exit();
- }
-
- /*
- * nmi does not call nap_adjust_return because nmi should not create
- * new work to do (must use irq_work for that).
- */
-
-#ifdef CONFIG_PPC64
-#ifdef CONFIG_PPC_BOOK3S
- if (arch_irq_disabled_regs(regs)) {
- unsigned long rst = search_kernel_restart_table(regs->nip);
- if (rst)
- regs_set_return_ip(regs, rst);
- }
-#endif
-
- if (nmi_disables_ftrace(regs))
- this_cpu_set_ftrace_enabled(state->ftrace_enabled);
-
- /* Check we didn't change the pending interrupt mask. */
- WARN_ON_ONCE((state->irq_happened | PACA_IRQ_HARD_DIS) != local_paca->irq_happened);
- regs->softe = state->softe;
- local_paca->irq_happened = state->irq_happened;
- local_paca->irq_soft_mask = state->irq_soft_mask;
-#endif
-}
-
/*
* Don't use noinstr here like x86, but rather add NOKPROBE_SYMBOL to each
* function definition. The reason for this is the noinstr section is placed
@@ -470,11 +166,14 @@ static __always_inline void ____##func(struct pt_regs *regs); \
\
interrupt_handler void func(struct pt_regs *regs) \
{ \
- interrupt_enter_prepare(regs); \
- \
+ irqentry_state_t state; \
+ arch_interrupt_enter_prepare(regs); \
+ state = irqentry_enter(regs); \
+ instrumentation_begin(); \
____##func (regs); \
- \
- interrupt_exit_prepare(regs); \
+ instrumentation_end(); \
+ arch_interrupt_exit_prepare(regs); \
+ irqentry_exit(regs, state); \
} \
NOKPROBE_SYMBOL(func); \
\
@@ -504,12 +203,15 @@ static __always_inline long ____##func(struct pt_regs *regs); \
interrupt_handler long func(struct pt_regs *regs) \
{ \
long ret; \
+ irqentry_state_t state; \
\
- interrupt_enter_prepare(regs); \
- \
+ arch_interrupt_enter_prepare(regs); \
+ state = irqentry_enter(regs); \
+ instrumentation_begin(); \
ret = ____##func (regs); \
- \
- interrupt_exit_prepare(regs); \
+ instrumentation_end(); \
+ arch_interrupt_exit_prepare(regs); \
+ irqentry_exit(regs, state); \
\
return ret; \
} \
@@ -538,11 +240,16 @@ static __always_inline void ____##func(struct pt_regs *regs); \
\
interrupt_handler void func(struct pt_regs *regs) \
{ \
- interrupt_async_enter_prepare(regs); \
- \
+ irqentry_state_t state; \
+ arch_interrupt_async_enter_prepare(regs); \
+ state = irqentry_enter(regs); \
+ instrumentation_begin(); \
+ irq_enter_rcu(); \
____##func (regs); \
- \
- interrupt_async_exit_prepare(regs); \
+ irq_exit_rcu(); \
+ instrumentation_end(); \
+ arch_interrupt_async_exit_prepare(regs); \
+ irqentry_exit(regs, state); \
} \
NOKPROBE_SYMBOL(func); \
\
@@ -572,14 +279,43 @@ ____##func(struct pt_regs *regs); \
\
interrupt_handler long func(struct pt_regs *regs) \
{ \
- struct interrupt_nmi_state state; \
+ irqentry_state_t state; \
+ struct interrupt_nmi_state nmi_state; \
long ret; \
\
- interrupt_nmi_enter_prepare(regs, &state); \
- \
+ arch_interrupt_nmi_enter_prepare(regs, &nmi_state); \
+ if (mfmsr() & MSR_DR) { \
+ /* nmi_entry if relocations are on */ \
+ state = irqentry_nmi_enter(regs); \
+ } else if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && \
+ firmware_has_feature(FW_FEATURE_LPAR) && \
+ !radix_enabled()) { \
+ /* no nmi_entry for a pseries hash guest \
+ * taking a real mode exception */ \
+ } else if (IS_ENABLED(CONFIG_KASAN)) { \
+ /* no nmi_entry for KASAN in real mode */ \
+ } else if (percpu_first_chunk_is_paged) { \
+ /* no nmi_entry if percpu first chunk is not embedded */\
+ } else { \
+ state = irqentry_nmi_enter(regs); \
+ } \
ret = ____##func (regs); \
- \
- interrupt_nmi_exit_prepare(regs, &state); \
+ arch_interrupt_nmi_exit_prepare(regs, &nmi_state); \
+ if (mfmsr() & MSR_DR) { \
+ /* nmi_exit if relocations are on */ \
+ irqentry_nmi_exit(regs, state); \
+ } else if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && \
+ firmware_has_feature(FW_FEATURE_LPAR) && \
+ !radix_enabled()) { \
+ /* no nmi_exit for a pseries hash guest \
+ * taking a real mode exception */ \
+ } else if (IS_ENABLED(CONFIG_KASAN)) { \
+ /* no nmi_exit for KASAN in real mode */ \
+ } else if (percpu_first_chunk_is_paged) { \
+ /* no nmi_exit if percpu first chunk is not embedded */ \
+ } else { \
+ irqentry_nmi_exit(regs, state); \
+ } \
\
return ret; \
} \
@@ -661,7 +397,7 @@ void replay_soft_interrupts(void);
static inline void interrupt_cond_local_irq_enable(struct pt_regs *regs)
{
- if (!arch_irq_disabled_regs(regs))
+ if (!regs_irqs_disabled(regs))
local_irq_enable();
}
diff --git a/arch/powerpc/include/asm/kasan.h b/arch/powerpc/include/asm/kasan.h
index 045804a86f98..a690e7da53c2 100644
--- a/arch/powerpc/include/asm/kasan.h
+++ b/arch/powerpc/include/asm/kasan.h
@@ -3,14 +3,19 @@
#define __ASM_KASAN_H
#if defined(CONFIG_KASAN) && !defined(CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX)
-#define _GLOBAL_KASAN(fn) _GLOBAL(__##fn)
-#define _GLOBAL_TOC_KASAN(fn) _GLOBAL_TOC(__##fn)
-#define EXPORT_SYMBOL_KASAN(fn) EXPORT_SYMBOL(__##fn)
-#else
+#define _GLOBAL_KASAN(fn) \
+ _GLOBAL(fn); \
+ _GLOBAL(__##fn)
+#define _GLOBAL_TOC_KASAN(fn) \
+ _GLOBAL_TOC(fn); \
+ _GLOBAL_TOC(__##fn)
+#define EXPORT_SYMBOL_KASAN(fn) \
+ EXPORT_SYMBOL(__##fn)
+#else /* CONFIG_KASAN && !CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX */
#define _GLOBAL_KASAN(fn) _GLOBAL(fn)
#define _GLOBAL_TOC_KASAN(fn) _GLOBAL_TOC(fn)
#define EXPORT_SYMBOL_KASAN(fn)
-#endif
+#endif /* CONFIG_KASAN && !CONFIG_CC_HAS_KASAN_MEMINTRINSIC_PREFIX */
#ifndef __ASSEMBLER__
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h
index f679a11a7e7f..f4991d10d89e 100644
--- a/arch/powerpc/include/asm/prom.h
+++ b/arch/powerpc/include/asm/prom.h
@@ -12,12 +12,14 @@
* Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp.
*/
#include <linux/types.h>
+#include <linux/sizes.h>
#include <asm/firmware.h>
struct device_node;
struct property;
-#define MIN_RMA 768 /* Minimum RMA (in MB) for CAS negotiation */
+/* Minimum RMA in bytes for CAS negotiation */
+#define MIN_RMA (768ULL * SZ_1M)
#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
#define OF_DT_END_NODE 0x2 /* End node */
diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h
index 94aa1de2b06e..fdeb97421785 100644
--- a/arch/powerpc/include/asm/ptrace.h
+++ b/arch/powerpc/include/asm/ptrace.h
@@ -53,6 +53,9 @@ struct pt_regs
unsigned long esr;
};
unsigned long result;
+ unsigned long exit_flags;
+ /* Maintain 16 byte interrupt stack alignment */
+ unsigned long __pt_regs_pad[3];
};
};
#if defined(CONFIG_PPC64) || defined(CONFIG_PPC_KUAP)
@@ -174,9 +177,6 @@ extern unsigned long profile_pc(struct pt_regs *regs);
#define profile_pc(regs) instruction_pointer(regs)
#endif
-long do_syscall_trace_enter(struct pt_regs *regs);
-void do_syscall_trace_leave(struct pt_regs *regs);
-
static inline void set_return_regs_changed(void)
{
#ifdef CONFIG_PPC_BOOK3S_64
diff --git a/arch/powerpc/include/asm/rtas-types.h b/arch/powerpc/include/asm/rtas-types.h
index 9d5b16803cbb..5d40d187b965 100644
--- a/arch/powerpc/include/asm/rtas-types.h
+++ b/arch/powerpc/include/asm/rtas-types.h
@@ -42,8 +42,9 @@ struct rtas_error_log {
*/
u8 byte3; /* General event or error*/
__be32 extended_log_length; /* length in bytes */
- unsigned char buffer[1]; /* Start of extended log */
- /* Variable length. */
+
+ /* Start of extended log, variable length */
+ unsigned char buffer[] __counted_by_be(extended_log_length);
};
/* RTAS general extended event log, Version 6. The extended log starts
diff --git a/arch/powerpc/include/asm/signal.h b/arch/powerpc/include/asm/signal.h
index 922d43700fb4..21af92cdb237 100644
--- a/arch/powerpc/include/asm/signal.h
+++ b/arch/powerpc/include/asm/signal.h
@@ -7,7 +7,6 @@
#include <uapi/asm/ptrace.h>
struct pt_regs;
-void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags);
unsigned long get_min_sigframe_size_32(void);
unsigned long get_min_sigframe_size_64(void);
diff --git a/arch/powerpc/include/asm/stacktrace.h b/arch/powerpc/include/asm/stacktrace.h
index 6149b53b3bc8..987f2e996262 100644
--- a/arch/powerpc/include/asm/stacktrace.h
+++ b/arch/powerpc/include/asm/stacktrace.h
@@ -10,4 +10,10 @@
void show_user_instructions(struct pt_regs *regs);
+static __always_inline bool on_thread_stack(void)
+{
+ return !(((unsigned long)(current->stack) ^ current_stack_pointer)
+ & ~(THREAD_SIZE - 1));
+}
+
#endif /* _ASM_POWERPC_STACKTRACE_H */
diff --git a/arch/powerpc/include/asm/syscall.h b/arch/powerpc/include/asm/syscall.h
index 4b3c52ed6e9d..834fcc4f7b54 100644
--- a/arch/powerpc/include/asm/syscall.h
+++ b/arch/powerpc/include/asm/syscall.h
@@ -139,4 +139,9 @@ static inline int syscall_get_arch(struct task_struct *task)
else
return AUDIT_ARCH_PPC64;
}
+
+static inline bool arch_syscall_is_vdso_sigreturn(struct pt_regs *regs)
+{
+ return false;
+}
#endif /* _ASM_SYSCALL_H */
diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h
index 97f35f9b1a96..ee3b9adb5b67 100644
--- a/arch/powerpc/include/asm/thread_info.h
+++ b/arch/powerpc/include/asm/thread_info.h
@@ -57,6 +57,7 @@ struct thread_info {
#ifdef CONFIG_SMP
unsigned int cpu;
#endif
+ unsigned long syscall_work; /* SYSCALL_WORK_ flags */
unsigned long local_flags; /* private flags for thread */
#ifdef CONFIG_LIVEPATCH_64
unsigned long *livepatch_sp;
diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h
index e98c628e3899..7b8c56962c31 100644
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -18,9 +18,35 @@
/* Threshold above which VMX copy path is used */
#define VMX_COPY_THRESHOLD 3328
+#define __access_ok __access_ok
+
#include <asm-generic/access_ok.h>
/*
+ * On powerpc64, TASK_SIZE_MAX is 0x0010000000000000 then even if both ptr and size
+ * are TASK_SIZE_MAX we are still inside the memory gap. So make it simple.
+ */
+static __always_inline int __access_ok(const void __user *ptr, unsigned long size)
+{
+ unsigned long addr = (unsigned long)ptr;
+
+ if (IS_ENABLED(CONFIG_PPC64)) {
+ BUILD_BUG_ON(!is_power_of_2(TASK_SIZE_MAX));
+ BUILD_BUG_ON(TASK_SIZE_MAX > 0x0010000000000000);
+
+ if (statically_true(size > TASK_SIZE_MAX))
+ return false;
+ if (statically_true(size <= TASK_SIZE_MAX))
+ return !(addr & ~(TASK_SIZE_MAX - 1));
+ return !((size | addr) & ~(TASK_SIZE_MAX - 1));
+ } else {
+ if (statically_true(size <= SZ_128K))
+ return addr < TASK_SIZE;
+ return size <= TASK_SIZE && addr <= TASK_SIZE - size;
+ }
+}
+
+/*
* These are the main single-value transfer routines. They automatically
* use the right size if we just have the right pointer type.
*
diff --git a/arch/powerpc/include/uapi/asm/ptrace.h b/arch/powerpc/include/uapi/asm/ptrace.h
index 01e630149d48..a393b7f2760a 100644
--- a/arch/powerpc/include/uapi/asm/ptrace.h
+++ b/arch/powerpc/include/uapi/asm/ptrace.h
@@ -55,6 +55,8 @@ struct pt_regs
unsigned long dar; /* Fault registers */
unsigned long dsisr; /* on 4xx/Book-E used for ESR */
unsigned long result; /* Result of a system call */
+ unsigned long exit_flags; /* System call exit flags */
+ unsigned long __pt_regs_pad[3]; /* Maintain 16 byte interrupt stack alignment */
};
#endif /* __ASSEMBLER__ */
@@ -114,10 +116,12 @@ struct pt_regs
#define PT_DAR 41
#define PT_DSISR 42
#define PT_RESULT 43
-#define PT_DSCR 44
-#define PT_REGS_COUNT 44
+#define PT_EXIT_FLAGS 44
+#define PT_PAD 47 /* 3 times */
+#define PT_DSCR 48
+#define PT_REGS_COUNT 48
-#define PT_FPR0 48 /* each FP reg occupies 2 slots in this space */
+#define PT_FPR0 (PT_REGS_COUNT + 4) /* each FP reg occupies 2 slots in this space */
#ifndef __powerpc64__
@@ -129,7 +133,7 @@ struct pt_regs
#define PT_FPSCR (PT_FPR0 + 32) /* each FP reg occupies 1 slot in 64-bit space */
-#define PT_VR0 82 /* each Vector reg occupies 2 slots in 64-bit */
+#define PT_VR0 (PT_FPSCR + 2) /* <82> each Vector reg occupies 2 slots in 64-bit */
#define PT_VSCR (PT_VR0 + 32*2 + 1)
#define PT_VRSAVE (PT_VR0 + 33*2)
@@ -137,7 +141,7 @@ struct pt_regs
/*
* Only store first 32 VSRs here. The second 32 VSRs in VR0-31
*/
-#define PT_VSR0 150 /* each VSR reg occupies 2 slots in 64-bit */
+#define PT_VSR0 (PT_VRSAVE + 2) /* each VSR reg occupies 2 slots in 64-bit */
#define PT_VSR31 (PT_VSR0 + 2*31)
#endif /* __powerpc64__ */
diff --git a/arch/powerpc/kernel/cacheinfo.c b/arch/powerpc/kernel/cacheinfo.c
index 90d51d9b3ed2..04e5ea38bdc0 100644
--- a/arch/powerpc/kernel/cacheinfo.c
+++ b/arch/powerpc/kernel/cacheinfo.c
@@ -18,6 +18,7 @@
#include <linux/of.h>
#include <linux/percpu.h>
#include <linux/slab.h>
+#include <linux/sysfs.h>
#include <asm/cputhreads.h>
#include <asm/smp.h>
@@ -596,7 +597,7 @@ static ssize_t size_show(struct kobject *k, struct kobj_attribute *attr, char *b
if (cache_size_kb(cache, &size_kb))
return -ENODEV;
- return sprintf(buf, "%uK\n", size_kb);
+ return sysfs_emit(buf, "%uK\n", size_kb);
}
static struct kobj_attribute cache_size_attr =
@@ -613,7 +614,7 @@ static ssize_t line_size_show(struct kobject *k, struct kobj_attribute *attr, ch
if (cache_get_line_size(cache, &line_size))
return -ENODEV;
- return sprintf(buf, "%u\n", line_size);
+ return sysfs_emit(buf, "%u\n", line_size);
}
static struct kobj_attribute cache_line_size_attr =
@@ -629,7 +630,7 @@ static ssize_t nr_sets_show(struct kobject *k, struct kobj_attribute *attr, char
if (cache_nr_sets(cache, &nr_sets))
return -ENODEV;
- return sprintf(buf, "%u\n", nr_sets);
+ return sysfs_emit(buf, "%u\n", nr_sets);
}
static struct kobj_attribute cache_nr_sets_attr =
@@ -645,7 +646,7 @@ static ssize_t associativity_show(struct kobject *k, struct kobj_attribute *attr
if (cache_associativity(cache, &associativity))
return -ENODEV;
- return sprintf(buf, "%u\n", associativity);
+ return sysfs_emit(buf, "%u\n", associativity);
}
static struct kobj_attribute cache_assoc_attr =
@@ -657,7 +658,7 @@ static ssize_t type_show(struct kobject *k, struct kobj_attribute *attr, char *b
cache = index_kobj_to_cache(k);
- return sprintf(buf, "%s\n", cache_type_string(cache));
+ return sysfs_emit(buf, "%s\n", cache_type_string(cache));
}
static struct kobj_attribute cache_type_attr =
@@ -671,7 +672,7 @@ static ssize_t level_show(struct kobject *k, struct kobj_attribute *attr, char *
index = kobj_to_cache_index_dir(k);
cache = index->cache;
- return sprintf(buf, "%d\n", cache->level);
+ return sysfs_emit(buf, "%d\n", cache->level);
}
static struct kobj_attribute cache_level_attr =
diff --git a/arch/powerpc/kernel/eeh_sysfs.c b/arch/powerpc/kernel/eeh_sysfs.c
index 706e1eb95efe..b9785f105f75 100644
--- a/arch/powerpc/kernel/eeh_sysfs.c
+++ b/arch/powerpc/kernel/eeh_sysfs.c
@@ -9,6 +9,7 @@
#include <linux/of.h>
#include <linux/pci.h>
#include <linux/stat.h>
+#include <linux/sysfs.h>
#include <asm/ppc-pci.h>
#include <asm/pci-bridge.h>
@@ -31,7 +32,7 @@ static ssize_t eeh_show_##_name(struct device *dev, \
if (!edev) \
return 0; \
\
- return sprintf(buf, _format "\n", edev->_memb); \
+ return sysfs_emit(buf, _format "\n", edev->_memb); \
} \
static DEVICE_ATTR(_name, 0444, eeh_show_##_name, NULL);
@@ -49,8 +50,7 @@ static ssize_t eeh_pe_state_show(struct device *dev,
return -ENODEV;
state = eeh_ops->get_state(edev->pe, NULL);
- return sprintf(buf, "0x%08x 0x%08x\n",
- state, edev->pe->state);
+ return sysfs_emit(buf, "0x%08x 0x%08x\n", state, edev->pe->state);
}
static ssize_t eeh_pe_state_store(struct device *dev,
@@ -87,7 +87,7 @@ static ssize_t eeh_notify_resume_show(struct device *dev,
if (!edev || !edev->pe)
return -ENODEV;
- return sprintf(buf, "%d\n", pdn->last_allow_rc);
+ return sysfs_emit(buf, "%d\n", pdn->last_allow_rc);
}
static ssize_t eeh_notify_resume_store(struct device *dev,
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index 501d43bf18f3..7f79c9aea4a9 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -1422,7 +1422,7 @@ static ssize_t enabled_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
{
- return sprintf(buf, "%d\n", fw_dump.fadump_enabled);
+ return sysfs_emit(buf, "%d\n", fw_dump.fadump_enabled);
}
/*
@@ -1434,28 +1434,28 @@ static ssize_t hotplug_ready_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
{
- return sprintf(buf, "%d\n", 1);
+ return sysfs_emit(buf, "%d\n", 1);
}
static ssize_t mem_reserved_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
{
- return sprintf(buf, "%ld\n", fw_dump.reserve_dump_area_size);
+ return sysfs_emit(buf, "%ld\n", fw_dump.reserve_dump_area_size);
}
static ssize_t registered_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
{
- return sprintf(buf, "%d\n", fw_dump.dump_registered);
+ return sysfs_emit(buf, "%d\n", fw_dump.dump_registered);
}
static ssize_t bootargs_append_show(struct kobject *kobj,
struct kobj_attribute *attr,
char *buf)
{
- return sprintf(buf, "%s\n", (char *)__va(fw_dump.param_area));
+ return sysfs_emit(buf, "%s\n", (char *)__va(fw_dump.param_area));
}
static ssize_t bootargs_append_store(struct kobject *kobj,
@@ -1759,10 +1759,10 @@ void __init fadump_setup_param_area(void)
* 2. The range should be between MIN_RMA and RMA size (ppc64_rma_size)
* 3. It must not overlap with the fadump reserved area.
*/
- if (ppc64_rma_size < MIN_RMA*1024*1024)
+ if (ppc64_rma_size < MIN_RMA)
return;
- range_start = MIN_RMA * 1024 * 1024;
+ range_start = MIN_RMA;
range_end = min(ppc64_rma_size, fw_dump.boot_mem_top);
}
diff --git a/arch/powerpc/kernel/interrupt.c b/arch/powerpc/kernel/interrupt.c
index e63bfde13e03..f04978080837 100644
--- a/arch/powerpc/kernel/interrupt.c
+++ b/arch/powerpc/kernel/interrupt.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <linux/context_tracking.h>
+#include <linux/entry-common.h>
#include <linux/err.h>
#include <linux/compat.h>
#include <linux/rseq.h>
@@ -25,10 +26,6 @@
unsigned long global_dbcr0[NR_CPUS];
#endif
-#if defined(CONFIG_PREEMPT_DYNAMIC)
-DEFINE_STATIC_KEY_TRUE(sk_dynamic_irqentry_exit_cond_resched);
-#endif
-
#ifdef CONFIG_PPC_BOOK3S_64
DEFINE_STATIC_KEY_FALSE(interrupt_exit_not_reentrant);
static inline bool exit_must_hard_disable(void)
@@ -78,181 +75,6 @@ static notrace __always_inline bool prep_irq_for_enabled_exit(bool restartable)
return true;
}
-static notrace void booke_load_dbcr0(void)
-{
-#ifdef CONFIG_PPC_ADV_DEBUG_REGS
- unsigned long dbcr0 = current->thread.debug.dbcr0;
-
- if (likely(!(dbcr0 & DBCR0_IDM)))
- return;
-
- /*
- * Check to see if the dbcr0 register is set up to debug.
- * Use the internal debug mode bit to do this.
- */
- mtmsr(mfmsr() & ~MSR_DE);
- if (IS_ENABLED(CONFIG_PPC32)) {
- isync();
- global_dbcr0[smp_processor_id()] = mfspr(SPRN_DBCR0);
- }
- mtspr(SPRN_DBCR0, dbcr0);
- mtspr(SPRN_DBSR, -1);
-#endif
-}
-
-static notrace void check_return_regs_valid(struct pt_regs *regs)
-{
-#ifdef CONFIG_PPC_BOOK3S_64
- unsigned long trap, srr0, srr1;
- static bool warned;
- u8 *validp;
- char *h;
-
- if (trap_is_scv(regs))
- return;
-
- trap = TRAP(regs);
- // EE in HV mode sets HSRRs like 0xea0
- if (cpu_has_feature(CPU_FTR_HVMODE) && trap == INTERRUPT_EXTERNAL)
- trap = 0xea0;
-
- switch (trap) {
- case 0x980:
- case INTERRUPT_H_DATA_STORAGE:
- case 0xe20:
- case 0xe40:
- case INTERRUPT_HMI:
- case 0xe80:
- case 0xea0:
- case INTERRUPT_H_FAC_UNAVAIL:
- case 0x1200:
- case 0x1500:
- case 0x1600:
- case 0x1800:
- validp = &local_paca->hsrr_valid;
- if (!READ_ONCE(*validp))
- return;
-
- srr0 = mfspr(SPRN_HSRR0);
- srr1 = mfspr(SPRN_HSRR1);
- h = "H";
-
- break;
- default:
- validp = &local_paca->srr_valid;
- if (!READ_ONCE(*validp))
- return;
-
- srr0 = mfspr(SPRN_SRR0);
- srr1 = mfspr(SPRN_SRR1);
- h = "";
- break;
- }
-
- if (srr0 == regs->nip && srr1 == regs->msr)
- return;
-
- /*
- * A NMI / soft-NMI interrupt may have come in after we found
- * srr_valid and before the SRRs are loaded. The interrupt then
- * comes in and clobbers SRRs and clears srr_valid. Then we load
- * the SRRs here and test them above and find they don't match.
- *
- * Test validity again after that, to catch such false positives.
- *
- * This test in general will have some window for false negatives
- * and may not catch and fix all such cases if an NMI comes in
- * later and clobbers SRRs without clearing srr_valid, but hopefully
- * such things will get caught most of the time, statistically
- * enough to be able to get a warning out.
- */
- if (!READ_ONCE(*validp))
- return;
-
- if (!data_race(warned)) {
- data_race(warned = true);
- printk("%sSRR0 was: %lx should be: %lx\n", h, srr0, regs->nip);
- printk("%sSRR1 was: %lx should be: %lx\n", h, srr1, regs->msr);
- show_regs(regs);
- }
-
- WRITE_ONCE(*validp, 0); /* fixup */
-#endif
-}
-
-static notrace unsigned long
-interrupt_exit_user_prepare_main(unsigned long ret, struct pt_regs *regs)
-{
- unsigned long ti_flags;
-
-again:
- ti_flags = read_thread_flags();
- while (unlikely(ti_flags & (_TIF_USER_WORK_MASK & ~_TIF_RESTORE_TM))) {
- local_irq_enable();
- if (ti_flags & (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY)) {
- schedule();
- } else {
- /*
- * SIGPENDING must restore signal handler function
- * argument GPRs, and some non-volatiles (e.g., r1).
- * Restore all for now. This could be made lighter.
- */
- if (ti_flags & _TIF_SIGPENDING)
- ret |= _TIF_RESTOREALL;
- do_notify_resume(regs, ti_flags);
- }
- local_irq_disable();
- ti_flags = read_thread_flags();
- }
-
- if (IS_ENABLED(CONFIG_PPC_BOOK3S_64) && IS_ENABLED(CONFIG_PPC_FPU)) {
- if (IS_ENABLED(CONFIG_PPC_TRANSACTIONAL_MEM) &&
- unlikely((ti_flags & _TIF_RESTORE_TM))) {
- restore_tm_state(regs);
- } else {
- unsigned long mathflags = MSR_FP;
-
- if (cpu_has_feature(CPU_FTR_VSX))
- mathflags |= MSR_VEC | MSR_VSX;
- else if (cpu_has_feature(CPU_FTR_ALTIVEC))
- mathflags |= MSR_VEC;
-
- /*
- * If userspace MSR has all available FP bits set,
- * then they are live and no need to restore. If not,
- * it means the regs were given up and restore_math
- * may decide to restore them (to avoid taking an FP
- * fault).
- */
- if ((regs->msr & mathflags) != mathflags)
- restore_math(regs);
- }
- }
-
- check_return_regs_valid(regs);
-
- user_enter_irqoff();
- if (!prep_irq_for_enabled_exit(true)) {
- user_exit_irqoff();
- local_irq_enable();
- local_irq_disable();
- goto again;
- }
-
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
- local_paca->tm_scratch = regs->msr;
-#endif
-
- booke_load_dbcr0();
-
- account_cpu_user_exit();
-
- /* Restore user access locks last */
- kuap_user_restore(regs);
-
- return ret;
-}
-
/*
* This should be called after a syscall returns, with r3 the return value
* from the syscall. If this function returns non-zero, the system call
@@ -267,17 +89,12 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3,
long scv)
{
unsigned long ti_flags;
- unsigned long ret = 0;
bool is_not_scv = !IS_ENABLED(CONFIG_PPC_BOOK3S_64) || !scv;
- CT_WARN_ON(ct_state() == CT_STATE_USER);
-
kuap_assert_locked();
regs->result = r3;
-
- /* Check whether the syscall is issued inside a restartable sequence */
- rseq_syscall(regs);
+ regs->exit_flags = 0;
ti_flags = read_thread_flags();
@@ -290,7 +107,7 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3,
if (unlikely(ti_flags & _TIF_PERSYSCALL_MASK)) {
if (ti_flags & _TIF_RESTOREALL)
- ret = _TIF_RESTOREALL;
+ regs->exit_flags = _TIF_RESTOREALL;
else
regs->gpr[3] = r3;
clear_bits(_TIF_PERSYSCALL_MASK, &current_thread_info()->flags);
@@ -299,18 +116,28 @@ notrace unsigned long syscall_exit_prepare(unsigned long r3,
}
if (unlikely(ti_flags & _TIF_SYSCALL_DOTRACE)) {
- do_syscall_trace_leave(regs);
- ret |= _TIF_RESTOREALL;
+ regs->exit_flags |= _TIF_RESTOREALL;
}
- local_irq_disable();
- ret = interrupt_exit_user_prepare_main(ret, regs);
+ syscall_exit_to_user_mode(regs);
+
+again:
+ user_enter_irqoff();
+ if (!prep_irq_for_enabled_exit(true)) {
+ user_exit_irqoff();
+ local_irq_enable();
+ local_irq_disable();
+ goto again;
+ }
+
+ /* Restore user access locks last */
+ kuap_user_restore(regs);
#ifdef CONFIG_PPC64
- regs->exit_result = ret;
+ regs->exit_result = regs->exit_flags;
#endif
- return ret;
+ return regs->exit_flags;
}
#ifdef CONFIG_PPC64
@@ -330,13 +157,17 @@ notrace unsigned long syscall_exit_restart(unsigned long r3, struct pt_regs *reg
set_kuap(AMR_KUAP_BLOCKED);
#endif
- trace_hardirqs_off();
- user_exit_irqoff();
- account_cpu_user_entry();
-
- BUG_ON(!user_mode(regs));
+again:
+ user_enter_irqoff();
+ if (!prep_irq_for_enabled_exit(true)) {
+ user_exit_irqoff();
+ local_irq_enable();
+ local_irq_disable();
+ goto again;
+ }
- regs->exit_result = interrupt_exit_user_prepare_main(regs->exit_result, regs);
+ kuap_user_restore(regs);
+ regs->exit_result |= regs->exit_flags;
return regs->exit_result;
}
@@ -347,8 +178,7 @@ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs)
unsigned long ret;
BUG_ON(regs_is_unrecoverable(regs));
- BUG_ON(arch_irq_disabled_regs(regs));
- CT_WARN_ON(ct_state() == CT_STATE_USER);
+ BUG_ON(regs_irqs_disabled(regs));
/*
* We don't need to restore AMR on the way back to userspace for KUAP.
@@ -357,8 +187,21 @@ notrace unsigned long interrupt_exit_user_prepare(struct pt_regs *regs)
kuap_assert_locked();
local_irq_disable();
+ regs->exit_flags = 0;
+again:
+ check_return_regs_valid(regs);
+ user_enter_irqoff();
+ if (!prep_irq_for_enabled_exit(true)) {
+ user_exit_irqoff();
+ local_irq_enable();
+ local_irq_disable();
+ goto again;
+ }
+
+ /* Restore user access locks last */
+ kuap_user_restore(regs);
- ret = interrupt_exit_user_prepare_main(0, regs);
+ ret = regs->exit_flags;
#ifdef CONFIG_PPC64
regs->exit_result = ret;
@@ -396,17 +239,10 @@ notrace unsigned long interrupt_exit_kernel_prepare(struct pt_regs *regs)
local_irq_disable();
- if (!arch_irq_disabled_regs(regs)) {
+ if (!regs_irqs_disabled(regs)) {
/* Returning to a kernel context with local irqs enabled. */
WARN_ON_ONCE(!(regs->msr & MSR_EE));
again:
- if (need_irq_preemption()) {
- /* Return to preemptible kernel context */
- if (unlikely(read_thread_flags() & _TIF_NEED_RESCHED)) {
- if (preempt_count() == 0)
- preempt_schedule_irq();
- }
- }
check_return_regs_valid(regs);
@@ -479,7 +315,6 @@ notrace unsigned long interrupt_exit_user_restart(struct pt_regs *regs)
#endif
trace_hardirqs_off();
- user_exit_irqoff();
account_cpu_user_entry();
BUG_ON(!user_mode(regs));
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index d122e8447831..ee1b5cb557c9 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -13,6 +13,7 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/slab.h>
+#include <linux/sysfs.h>
#include <linux/mm.h>
#include <linux/spinlock.h>
#include <linux/string.h>
@@ -141,7 +142,7 @@ late_initcall(fail_iommu_debugfs);
static ssize_t fail_iommu_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%d\n", dev->archdata.fail_iommu);
+ return sysfs_emit(buf, "%d\n", dev->archdata.fail_iommu);
}
static ssize_t fail_iommu_store(struct device *dev,
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index a0e8b998c9b5..f69de08ad347 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -370,10 +370,7 @@ int irq_choose_cpu(const struct cpumask *mask)
do_round_robin:
raw_spin_lock_irqsave(&irq_rover_lock, flags);
- irq_rover = cpumask_next(irq_rover, cpu_online_mask);
- if (irq_rover >= nr_cpu_ids)
- irq_rover = cpumask_first(cpu_online_mask);
-
+ irq_rover = cpumask_next_wrap(irq_rover, cpu_online_mask);
cpuid = irq_rover;
raw_spin_unlock_irqrestore(&irq_rover_lock, flags);
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index f26e80cbc615..53503937de0e 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -1061,7 +1061,7 @@ static const struct ibm_arch_vec ibm_architecture_vec_template __initconst = {
.virt_base = cpu_to_be32(0xffffffff),
.virt_size = cpu_to_be32(0xffffffff),
.load_base = cpu_to_be32(0xffffffff),
- .min_rma = cpu_to_be32(MIN_RMA),
+ .min_rma = cpu_to_be32(MIN_RMA / SZ_1M),
.min_load = cpu_to_be32(0xffffffff), /* full client load */
.min_rma_percent = 0, /* min RMA percentage of total RAM */
.max_pft_size = 48, /* max log_2(hash table size) */
diff --git a/arch/powerpc/kernel/ptrace/ptrace.c b/arch/powerpc/kernel/ptrace/ptrace.c
index c6997df63287..316d4f5ead8e 100644
--- a/arch/powerpc/kernel/ptrace/ptrace.c
+++ b/arch/powerpc/kernel/ptrace/ptrace.c
@@ -21,9 +21,6 @@
#include <asm/switch_to.h>
#include <asm/debug.h>
-#define CREATE_TRACE_POINTS
-#include <trace/events/syscalls.h>
-
#include "ptrace-decl.h"
/*
@@ -195,144 +192,6 @@ long arch_ptrace(struct task_struct *child, long request,
return ret;
}
-#ifdef CONFIG_SECCOMP
-static int do_seccomp(struct pt_regs *regs)
-{
- if (!test_thread_flag(TIF_SECCOMP))
- return 0;
-
- /*
- * The ABI we present to seccomp tracers is that r3 contains
- * the syscall return value and orig_gpr3 contains the first
- * syscall parameter. This is different to the ptrace ABI where
- * both r3 and orig_gpr3 contain the first syscall parameter.
- */
- regs->gpr[3] = -ENOSYS;
-
- /*
- * We use the __ version here because we have already checked
- * TIF_SECCOMP. If this fails, there is nothing left to do, we
- * have already loaded -ENOSYS into r3, or seccomp has put
- * something else in r3 (via SECCOMP_RET_ERRNO/TRACE).
- */
- if (__secure_computing())
- return -1;
-
- /*
- * The syscall was allowed by seccomp, restore the register
- * state to what audit expects.
- * Note that we use orig_gpr3, which means a seccomp tracer can
- * modify the first syscall parameter (in orig_gpr3) and also
- * allow the syscall to proceed.
- */
- regs->gpr[3] = regs->orig_gpr3;
-
- return 0;
-}
-#else
-static inline int do_seccomp(struct pt_regs *regs) { return 0; }
-#endif /* CONFIG_SECCOMP */
-
-/**
- * do_syscall_trace_enter() - Do syscall tracing on kernel entry.
- * @regs: the pt_regs of the task to trace (current)
- *
- * Performs various types of tracing on syscall entry. This includes seccomp,
- * ptrace, syscall tracepoints and audit.
- *
- * The pt_regs are potentially visible to userspace via ptrace, so their
- * contents is ABI.
- *
- * One or more of the tracers may modify the contents of pt_regs, in particular
- * to modify arguments or even the syscall number itself.
- *
- * It's also possible that a tracer can choose to reject the system call. In
- * that case this function will return an illegal syscall number, and will put
- * an appropriate return value in regs->r3.
- *
- * Return: the (possibly changed) syscall number.
- */
-long do_syscall_trace_enter(struct pt_regs *regs)
-{
- u32 flags;
-
- flags = read_thread_flags() & (_TIF_SYSCALL_EMU | _TIF_SYSCALL_TRACE);
-
- if (flags) {
- int rc = ptrace_report_syscall_entry(regs);
-
- if (unlikely(flags & _TIF_SYSCALL_EMU)) {
- /*
- * A nonzero return code from
- * ptrace_report_syscall_entry() tells us to prevent
- * the syscall execution, but we are not going to
- * execute it anyway.
- *
- * Returning -1 will skip the syscall execution. We want
- * to avoid clobbering any registers, so we don't goto
- * the skip label below.
- */
- return -1;
- }
-
- if (rc) {
- /*
- * The tracer decided to abort the syscall. Note that
- * the tracer may also just change regs->gpr[0] to an
- * invalid syscall number, that is handled below on the
- * exit path.
- */
- goto skip;
- }
- }
-
- /* Run seccomp after ptrace; allow it to set gpr[3]. */
- if (do_seccomp(regs))
- return -1;
-
- /* Avoid trace and audit when syscall is invalid. */
- if (regs->gpr[0] >= NR_syscalls)
- goto skip;
-
- if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
- trace_sys_enter(regs, regs->gpr[0]);
-
- if (!is_32bit_task())
- audit_syscall_entry(regs->gpr[0], regs->gpr[3], regs->gpr[4],
- regs->gpr[5], regs->gpr[6]);
- else
- audit_syscall_entry(regs->gpr[0],
- regs->gpr[3] & 0xffffffff,
- regs->gpr[4] & 0xffffffff,
- regs->gpr[5] & 0xffffffff,
- regs->gpr[6] & 0xffffffff);
-
- /* Return the possibly modified but valid syscall number */
- return regs->gpr[0];
-
-skip:
- /*
- * If we are aborting explicitly, or if the syscall number is
- * now invalid, set the return value to -ENOSYS.
- */
- regs->gpr[3] = -ENOSYS;
- return -1;
-}
-
-void do_syscall_trace_leave(struct pt_regs *regs)
-{
- int step;
-
- audit_syscall_exit(regs);
-
- if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
- trace_sys_exit(regs, regs->result);
-
- step = test_thread_flag(TIF_SINGLESTEP);
- if (step || test_thread_flag(TIF_SYSCALL_TRACE))
- ptrace_report_syscall_exit(regs, step);
-}
-
void __init pt_regs_check(void);
/*
@@ -432,6 +291,7 @@ void __init pt_regs_check(void)
CHECK_REG(PT_DAR, dar);
CHECK_REG(PT_DSISR, dsisr);
CHECK_REG(PT_RESULT, result);
+ CHECK_REG(PT_EXIT_FLAGS, exit_flags);
#undef CHECK_REG
BUILD_BUG_ON(PT_REGS_COUNT != sizeof(struct user_pt_regs) / sizeof(unsigned long));
diff --git a/arch/powerpc/kernel/security.c b/arch/powerpc/kernel/security.c
index fbb7ebd8aa08..600596cb4ffb 100644
--- a/arch/powerpc/kernel/security.c
+++ b/arch/powerpc/kernel/security.c
@@ -11,6 +11,7 @@
#include <linux/nospec.h>
#include <linux/prctl.h>
#include <linux/seq_buf.h>
+#include <linux/sysfs.h>
#include <linux/debugfs.h>
#include <asm/asm-prototypes.h>
@@ -163,13 +164,13 @@ ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, cha
}
if (thread_priv)
- return sprintf(buf, "Vulnerable: L1D private per thread\n");
+ return sysfs_emit(buf, "Vulnerable: L1D private per thread\n");
if (!security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) &&
!security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR))
- return sprintf(buf, "Not affected\n");
+ return sysfs_emit(buf, "Not affected\n");
- return sprintf(buf, "Vulnerable\n");
+ return sysfs_emit(buf, "Vulnerable\n");
}
ssize_t cpu_show_l1tf(struct device *dev, struct device_attribute *attr, char *buf)
@@ -352,14 +353,14 @@ ssize_t cpu_show_spec_store_bypass(struct device *dev, struct device_attribute *
default:
type = "unknown";
}
- return sprintf(buf, "Mitigation: Kernel entry/exit barrier (%s)\n", type);
+ return sysfs_emit(buf, "Mitigation: Kernel entry/exit barrier (%s)\n", type);
}
if (!security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV) &&
!security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR))
- return sprintf(buf, "Not affected\n");
+ return sysfs_emit(buf, "Not affected\n");
- return sprintf(buf, "Vulnerable\n");
+ return sysfs_emit(buf, "Vulnerable\n");
}
static int ssb_prctl_get(struct task_struct *task)
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 8a86b0efcb1c..67c545f61f0d 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -68,6 +68,7 @@
#include <asm/kasan.h>
#include <asm/mce.h>
#include <asm/systemcfg.h>
+#include <linux/kmsg_dump.h>
#include "setup.h"
@@ -323,7 +324,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
seq_putc(m, '\n');
/* If this is the last cpu, print the summary */
- if (cpumask_next(cpu_id, cpu_online_mask) >= nr_cpu_ids)
+ if (cpu_id == cpumask_last(cpu_online_mask))
show_cpuinfo_summary(m);
return 0;
@@ -331,10 +332,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
static void *c_start(struct seq_file *m, loff_t *pos)
{
- if (*pos == 0) /* just in case, cpu 0 is not the first */
- *pos = cpumask_first(cpu_online_mask);
- else
- *pos = cpumask_next(*pos - 1, cpu_online_mask);
+ *pos = cpumask_next(*pos - 1, cpu_online_mask);
if ((*pos) < nr_cpu_ids)
return (void *)(unsigned long)(*pos + 1);
return NULL;
@@ -745,6 +743,13 @@ static int ppc_panic_fadump_handler(struct notifier_block *this,
hard_irq_disable();
/*
+ * Invoke kmsg_dump (e.g., pstore) before crash_fadump() as fadump
+ * runs before panic()'s kmsg_dump_desc() call.
+ */
+ if (should_fadump_crash())
+ kmsg_dump_desc(KMSG_DUMP_PANIC, (char *)ptr);
+
+ /*
* If firmware-assisted dump has been registered then trigger
* its callback and let the firmware handles everything else.
*/
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c
index aa17e62f3754..bb42a8b6c642 100644
--- a/arch/powerpc/kernel/signal.c
+++ b/arch/powerpc/kernel/signal.c
@@ -6,6 +6,7 @@
* Extracted from signal_32.c and signal_64.c
*/
+#include <linux/entry-common.h>
#include <linux/resume_user_mode.h>
#include <linux/signal.h>
#include <linux/uprobes.h>
@@ -292,23 +293,6 @@ static void do_signal(struct task_struct *tsk)
signal_setup_done(ret, &ksig, test_thread_flag(TIF_SINGLESTEP));
}
-void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
-{
- if (thread_info_flags & _TIF_UPROBE)
- uprobe_notify_resume(regs);
-
- if (thread_info_flags & _TIF_PATCH_PENDING)
- klp_update_patch_state(current);
-
- if (thread_info_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) {
- BUG_ON(regs != current->thread.regs);
- do_signal(current);
- }
-
- if (thread_info_flags & _TIF_NOTIFY_RESUME)
- resume_user_mode_work(regs);
-}
-
static unsigned long get_tm_stackpointer(struct task_struct *tsk)
{
/* When in an active transaction that takes a signal, we need to be
@@ -368,3 +352,10 @@ void signal_fault(struct task_struct *tsk, struct pt_regs *regs,
printk_ratelimited(regs->msr & MSR_64BIT ? fm64 : fm32, tsk->comm,
task_pid_nr(tsk), where, ptr, regs->nip, regs->link);
}
+
+void arch_do_signal_or_restart(struct pt_regs *regs)
+{
+ BUG_ON(regs != current->thread.regs);
+ regs->exit_flags |= _TIF_RESTOREALL;
+ do_signal(current);
+}
diff --git a/arch/powerpc/kernel/syscall.c b/arch/powerpc/kernel/syscall.c
index b762677f8737..a9da2af6efa8 100644
--- a/arch/powerpc/kernel/syscall.c
+++ b/arch/powerpc/kernel/syscall.c
@@ -3,6 +3,7 @@
#include <linux/compat.h>
#include <linux/context_tracking.h>
#include <linux/randomize_kstack.h>
+#include <linux/entry-common.h>
#include <asm/interrupt.h>
#include <asm/kup.h>
@@ -18,124 +19,10 @@ notrace long system_call_exception(struct pt_regs *regs, unsigned long r0)
long ret;
syscall_fn f;
- kuap_lock();
-
- if (IS_ENABLED(CONFIG_PPC_IRQ_SOFT_MASK_DEBUG))
- BUG_ON(irq_soft_mask_return() != IRQS_ALL_DISABLED);
-
- trace_hardirqs_off(); /* finish reconciling */
-
- CT_WARN_ON(ct_state() == CT_STATE_KERNEL);
- user_exit_irqoff();
-
add_random_kstack_offset();
+ r0 = syscall_enter_from_user_mode(regs, r0);
- BUG_ON(regs_is_unrecoverable(regs));
- BUG_ON(!user_mode(regs));
- BUG_ON(arch_irq_disabled_regs(regs));
-
-#ifdef CONFIG_PPC_PKEY
- if (mmu_has_feature(MMU_FTR_PKEY)) {
- unsigned long amr, iamr;
- bool flush_needed = false;
- /*
- * When entering from userspace we mostly have the AMR/IAMR
- * different from kernel default values. Hence don't compare.
- */
- amr = mfspr(SPRN_AMR);
- iamr = mfspr(SPRN_IAMR);
- regs->amr = amr;
- regs->iamr = iamr;
- if (mmu_has_feature(MMU_FTR_KUAP)) {
- mtspr(SPRN_AMR, AMR_KUAP_BLOCKED);
- flush_needed = true;
- }
- if (mmu_has_feature(MMU_FTR_BOOK3S_KUEP)) {
- mtspr(SPRN_IAMR, AMR_KUEP_BLOCKED);
- flush_needed = true;
- }
- if (flush_needed)
- isync();
- } else
-#endif
- kuap_assert_locked();
-
- booke_restore_dbcr0();
-
- account_cpu_user_entry();
-
- account_stolen_time();
-
- /*
- * This is not required for the syscall exit path, but makes the
- * stack frame look nicer. If this was initialised in the first stack
- * frame, or if the unwinder was taught the first stack frame always
- * returns to user with IRQS_ENABLED, this store could be avoided!
- */
- irq_soft_mask_regs_set_state(regs, IRQS_ENABLED);
-
- /*
- * If system call is called with TM active, set _TIF_RESTOREALL to
- * prevent RFSCV being used to return to userspace, because POWER9
- * TM implementation has problems with this instruction returning to
- * transactional state. Final register values are not relevant because
- * the transaction will be aborted upon return anyway. Or in the case
- * of unsupported_scv SIGILL fault, the return state does not much
- * matter because it's an edge case.
- */
- if (IS_ENABLED(CONFIG_PPC_TRANSACTIONAL_MEM) &&
- unlikely(MSR_TM_TRANSACTIONAL(regs->msr)))
- set_bits(_TIF_RESTOREALL, &current_thread_info()->flags);
-
- /*
- * If the system call was made with a transaction active, doom it and
- * return without performing the system call. Unless it was an
- * unsupported scv vector, in which case it's treated like an illegal
- * instruction.
- */
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
- if (unlikely(MSR_TM_TRANSACTIONAL(regs->msr)) &&
- !trap_is_unsupported_scv(regs)) {
- /* Enable TM in the kernel, and disable EE (for scv) */
- hard_irq_disable();
- mtmsr(mfmsr() | MSR_TM);
-
- /* tabort, this dooms the transaction, nothing else */
- asm volatile(".long 0x7c00071d | ((%0) << 16)"
- :: "r"(TM_CAUSE_SYSCALL|TM_CAUSE_PERSISTENT));
-
- /*
- * Userspace will never see the return value. Execution will
- * resume after the tbegin. of the aborted transaction with the
- * checkpointed register state. A context switch could occur
- * or signal delivered to the process before resuming the
- * doomed transaction context, but that should all be handled
- * as expected.
- */
- return -ENOSYS;
- }
-#endif // CONFIG_PPC_TRANSACTIONAL_MEM
-
- local_irq_enable();
-
- if (unlikely(read_thread_flags() & _TIF_SYSCALL_DOTRACE)) {
- if (unlikely(trap_is_unsupported_scv(regs))) {
- /* Unsupported scv vector */
- _exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
- return regs->gpr[3];
- }
- /*
- * We use the return value of do_syscall_trace_enter() as the
- * syscall number. If the syscall was rejected for any reason
- * do_syscall_trace_enter() returns an invalid syscall number
- * and the test against NR_syscalls will fail and the return
- * value to be used is in regs->gpr[3].
- */
- r0 = do_syscall_trace_enter(regs);
- if (unlikely(r0 >= NR_syscalls))
- return regs->gpr[3];
-
- } else if (unlikely(r0 >= NR_syscalls)) {
+ if (unlikely(r0 >= NR_syscalls)) {
if (unlikely(trap_is_unsupported_scv(regs))) {
/* Unsupported scv vector */
_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 6b3dd6decdf9..329c1690b5ed 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -5,6 +5,7 @@
#include <linux/percpu.h>
#include <linux/init.h>
#include <linux/sched.h>
+#include <linux/sysfs.h>
#include <linux/export.h>
#include <linux/nodemask.h>
#include <linux/cpumask.h>
@@ -63,7 +64,7 @@ static ssize_t show_smt_snooze_delay(struct device *dev,
{
pr_warn_once("%s (%d) read from unsupported smt_snooze_delay\n",
current->comm, current->pid);
- return sprintf(buf, "100\n");
+ return sysfs_emit(buf, "100\n");
}
static DEVICE_ATTR(smt_snooze_delay, 0644, show_smt_snooze_delay,
@@ -100,7 +101,7 @@ static ssize_t show_##NAME(struct device *dev, \
struct cpu *cpu = container_of(dev, struct cpu, dev); \
unsigned long val; \
smp_call_function_single(cpu->dev.id, read_##NAME, &val, 1); \
- return sprintf(buf, "%lx\n", val); \
+ return sysfs_emit(buf, "%lx\n", val); \
} \
static ssize_t __used \
store_##NAME(struct device *dev, struct device_attribute *attr, \
@@ -183,7 +184,7 @@ static void add_write_permission_dev_attr(struct device_attribute *attr)
static ssize_t show_dscr_default(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%lx\n", dscr_default);
+ return sysfs_emit(buf, "%lx\n", dscr_default);
}
/**
@@ -272,7 +273,7 @@ static ssize_t show_pw20_state(struct device *dev,
value &= PWRMGTCR0_PW20_WAIT;
- return sprintf(buf, "%u\n", value ? 1 : 0);
+ return sysfs_emit(buf, "%u\n", value ? 1 : 0);
}
static void do_store_pw20_state(void *val)
@@ -337,7 +338,7 @@ static ssize_t show_pw20_wait_time(struct device *dev,
time = pw20_wt;
}
- return sprintf(buf, "%llu\n", time > 0 ? time : 0);
+ return sysfs_emit(buf, "%llu\n", time > 0 ? time : 0);
}
static void set_pw20_wait_entry_bit(void *val)
@@ -394,7 +395,7 @@ static ssize_t show_altivec_idle(struct device *dev,
value &= PWRMGTCR0_AV_IDLE_PD_EN;
- return sprintf(buf, "%u\n", value ? 1 : 0);
+ return sysfs_emit(buf, "%u\n", value ? 1 : 0);
}
static void do_store_altivec_idle(void *val)
@@ -459,7 +460,7 @@ static ssize_t show_altivec_idle_wait_time(struct device *dev,
time = altivec_idle_wt;
}
- return sprintf(buf, "%llu\n", time > 0 ? time : 0);
+ return sysfs_emit(buf, "%llu\n", time > 0 ? time : 0);
}
static void set_altivec_idle_wait_entry_bit(void *val)
@@ -746,7 +747,7 @@ static struct device_attribute pa6t_attrs[] = {
#ifdef CONFIG_PPC_SVM
static ssize_t show_svm(struct device *dev, struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%u\n", is_secure_guest());
+ return sysfs_emit(buf, "%u\n", is_secure_guest());
}
static DEVICE_ATTR(svm, 0444, show_svm, NULL);
@@ -780,7 +781,7 @@ static ssize_t idle_purr_show(struct device *dev,
u64 val;
smp_call_function_single(cpu->dev.id, read_idle_purr, &val, 1);
- return sprintf(buf, "%llx\n", val);
+ return sysfs_emit(buf, "%llx\n", val);
}
static DEVICE_ATTR(idle_purr, 0400, idle_purr_show, NULL);
@@ -810,7 +811,7 @@ static ssize_t idle_spurr_show(struct device *dev,
u64 val;
smp_call_function_single(cpu->dev.id, read_idle_spurr, &val, 1);
- return sprintf(buf, "%llx\n", val);
+ return sysfs_emit(buf, "%llx\n", val);
}
static DEVICE_ATTR(idle_spurr, 0400, idle_spurr_show, NULL);
@@ -1143,7 +1144,7 @@ static ssize_t show_physical_id(struct device *dev,
{
struct cpu *cpu = container_of(dev, struct cpu, dev);
- return sprintf(buf, "%d\n", get_hard_smp_processor_id(cpu->dev.id));
+ return sysfs_emit(buf, "%d\n", get_hard_smp_processor_id(cpu->dev.id));
}
static DEVICE_ATTR(physical_id, 0444, show_physical_id, NULL);
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index cb8e9357383e..629f2a2d4780 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1956,7 +1956,7 @@ DEFINE_INTERRUPT_HANDLER_RAW(performance_monitor_exception)
* prevent hash faults on user addresses when reading callchains (and
* looks better from an irq tracing perspective).
*/
- if (IS_ENABLED(CONFIG_PPC64) && unlikely(arch_irq_disabled_regs(regs)))
+ if (IS_ENABLED(CONFIG_PPC64) && unlikely(regs_irqs_disabled(regs)))
performance_monitor_exception_nmi(regs);
else
performance_monitor_exception_async(regs);
diff --git a/arch/powerpc/kernel/watchdog.c b/arch/powerpc/kernel/watchdog.c
index 764001deb060..c40c69368476 100644
--- a/arch/powerpc/kernel/watchdog.c
+++ b/arch/powerpc/kernel/watchdog.c
@@ -376,7 +376,7 @@ DEFINE_INTERRUPT_HANDLER_NMI(soft_nmi_interrupt)
u64 tb;
/* should only arrive from kernel, with irqs disabled */
- WARN_ON_ONCE(!arch_irq_disabled_regs(regs));
+ WARN_ON_ONCE(!regs_irqs_disabled(regs));
if (!cpumask_test_cpu(cpu, &wd_cpus_enabled))
return 0;
diff --git a/arch/powerpc/kexec/core_64.c b/arch/powerpc/kexec/core_64.c
index 825ab8a88f18..58c13a59b93b 100644
--- a/arch/powerpc/kexec/core_64.c
+++ b/arch/powerpc/kexec/core_64.c
@@ -169,7 +169,7 @@ static void kexec_prepare_cpus_wait(int wait_state)
int my_cpu, i, notified=-1;
hw_breakpoint_disable();
- my_cpu = get_cpu();
+ my_cpu = raw_smp_processor_id();
/* Make sure each CPU has at least made it to the state we need.
*
* FIXME: There is a (slim) chance of a problem if not all of the CPUs
@@ -267,8 +267,6 @@ static void kexec_prepare_cpus(void)
/* after we tell the others to go down */
if (ppc_md.kexec_cpu_down)
ppc_md.kexec_cpu_down(0, 0);
-
- put_cpu();
}
#else /* ! SMP */
diff --git a/arch/powerpc/mm/book3s64/hash_utils.c b/arch/powerpc/mm/book3s64/hash_utils.c
index 9dc5889d6ecb..e4fcf929cb33 100644
--- a/arch/powerpc/mm/book3s64/hash_utils.c
+++ b/arch/powerpc/mm/book3s64/hash_utils.c
@@ -1299,9 +1299,7 @@ static void stress_hpt_timer_fn(struct timer_list *timer)
if (!firmware_has_feature(FW_FEATURE_LPAR))
tlbiel_all();
- next_cpu = cpumask_next(raw_smp_processor_id(), cpu_online_mask);
- if (next_cpu >= nr_cpu_ids)
- next_cpu = cpumask_first(cpu_online_mask);
+ next_cpu = cpumask_next_wrap(raw_smp_processor_id(), cpu_online_mask);
stress_hpt_timer.expires = jiffies + msecs_to_jiffies(10);
add_timer_on(&stress_hpt_timer, next_cpu);
}
diff --git a/arch/powerpc/net/Makefile b/arch/powerpc/net/Makefile
index 8e60af32e51e..7f9339bacef1 100644
--- a/arch/powerpc/net/Makefile
+++ b/arch/powerpc/net/Makefile
@@ -3,3 +3,7 @@
# Arch-specific network modules
#
obj-$(CONFIG_BPF_JIT) += bpf_jit_comp.o bpf_jit_comp$(BITS).o
+
+ifdef CONFIG_PPC64
+obj-$(CONFIG_BPF_JIT) += bpf_timed_may_goto.o
+endif
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index 6351a187ca61..d4a17e18c9fb 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -517,6 +517,11 @@ bool bpf_jit_supports_subprog_tailcalls(void)
return IS_ENABLED(CONFIG_PPC64);
}
+bool bpf_jit_supports_timed_may_goto(void)
+{
+ return IS_ENABLED(CONFIG_PPC64);
+}
+
bool bpf_jit_supports_kfunc_call(void)
{
return IS_ENABLED(CONFIG_PPC64);
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c
index db364d9083e7..dab106cae22b 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -451,10 +451,28 @@ void arch_bpf_stack_walk(bool (*consume_fn)(void *, u64, u64, u64), void *cookie
}
}
+static int bpf_jit_emit_func_call(u32 *image, struct codegen_context *ctx, u64 func_addr, int reg)
+{
+ long reladdr = func_addr - kernel_toc_addr();
+
+ if (reladdr > 0x7FFFFFFF || reladdr < -(0x80000000L)) {
+ pr_err("eBPF: address of %ps out of range of kernel_toc.\n", (void *)func_addr);
+ return -ERANGE;
+ }
+
+ EMIT(PPC_RAW_ADDIS(reg, _R2, PPC_HA(reladdr)));
+ EMIT(PPC_RAW_ADDI(reg, reg, PPC_LO(reladdr)));
+ EMIT(PPC_RAW_MTCTR(reg));
+ EMIT(PPC_RAW_BCTRL());
+
+ return 0;
+}
+
int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func)
{
unsigned long func_addr = func ? ppc_function_entry((void *)func) : 0;
- long reladdr;
+ long __maybe_unused reladdr;
+ int ret;
/* bpf to bpf call, func is not known in the initial pass. Emit 5 nops as a placeholder */
if (!func) {
@@ -507,16 +525,9 @@ int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *
EMIT(PPC_RAW_BCTRL());
#else
if (core_kernel_text(func_addr)) {
- reladdr = func_addr - kernel_toc_addr();
- if (reladdr > 0x7FFFFFFF || reladdr < -(0x80000000L)) {
- pr_err("eBPF: address of %ps out of range of kernel_toc.\n", (void *)func);
- return -ERANGE;
- }
-
- EMIT(PPC_RAW_ADDIS(_R12, _R2, PPC_HA(reladdr)));
- EMIT(PPC_RAW_ADDI(_R12, _R12, PPC_LO(reladdr)));
- EMIT(PPC_RAW_MTCTR(_R12));
- EMIT(PPC_RAW_BCTRL());
+ ret = bpf_jit_emit_func_call(image, ctx, func_addr, _R12);
+ if (ret)
+ return ret;
} else {
if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V1)) {
/* func points to the function descriptor */
@@ -1755,6 +1766,35 @@ emit_clear:
if (ret < 0)
return ret;
+ /*
+ * Call to arch_bpf_timed_may_goto() is emitted by the
+ * verifier and called with custom calling convention with
+ * first argument and return value in BPF_REG_AX (_R12).
+ *
+ * The generic helper or bpf function call emission path
+ * may use the same scratch register as BPF_REG_AX to
+ * materialize the target address. This would clobber AX
+ * and break timed may_goto semantics.
+ *
+ * Emit a minimal indirect call sequence here using a temp
+ * register and skip the normal post-call return-value move.
+ */
+
+ if (func_addr == (u64)arch_bpf_timed_may_goto) {
+ ret = 0;
+ if (!IS_ENABLED(CONFIG_PPC_KERNEL_PCREL))
+ ret = bpf_jit_emit_func_call(image, ctx, func_addr,
+ tmp1_reg);
+
+ if (ret || IS_ENABLED(CONFIG_PPC_KERNEL_PCREL)) {
+ PPC_LI_ADDR(tmp1_reg, func_addr);
+ EMIT(PPC_RAW_MTCTR(tmp1_reg));
+ EMIT(PPC_RAW_BCTRL());
+ }
+
+ break;
+ }
+
/* Take care of powerpc ABI requirements before kfunc call */
if (insn[i].src_reg == BPF_PSEUDO_KFUNC_CALL) {
if (prepare_for_kfunc_call(fp, image, ctx, &insn[i]))
diff --git a/arch/powerpc/net/bpf_timed_may_goto.S b/arch/powerpc/net/bpf_timed_may_goto.S
new file mode 100644
index 000000000000..6fd8b1c9f4ac
--- /dev/null
+++ b/arch/powerpc/net/bpf_timed_may_goto.S
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2025 IBM Corporation, Saket Kumar Bhaskar <skb99@linux.ibm.com> */
+
+#include <linux/linkage.h>
+#include <asm/ppc_asm.h>
+
+/*
+ * arch_bpf_timed_may_goto() trampoline for powerpc64
+ *
+ * Custom BPF convention (verifier/JIT):
+ * - input: stack offset in BPF_REG_AX (r12)
+ * - output: updated count in BPF_REG_AX (r12)
+ *
+ * Call bpf_check_timed_may_goto(ptr) with normal powerpc64 ABI:
+ * - r3 = ptr, return in r3
+ *
+ * Preserve BPF regs R0-R5 (mapping: r8, r3-r7).
+ */
+
+SYM_FUNC_START(arch_bpf_timed_may_goto)
+ /* Prologue: save LR, allocate frame */
+ mflr r0
+ std r0, 16(r1)
+ stdu r1, -112(r1)
+
+ /* Save BPF registers R0 - R5 (r8, r3-r7) */
+ std r3, 32(r1)
+ std r4, 40(r1)
+ std r5, 48(r1)
+ std r6, 56(r1)
+ std r7, 64(r1)
+ std r8, 72(r1)
+
+ /*
+ * r3 = BPF_REG_FP + BPF_REG_AX
+ * BPF_REG_FP is r31; BPF_REG_AX is r12 (stack offset in bytes).
+ */
+ add r3, r31, r12
+ bl bpf_check_timed_may_goto
+
+ /* Put return value back into AX */
+ mr r12, r3
+
+ /* Restore BPF registers R0 - R5 (r8, r3-r7) */
+ ld r3, 32(r1)
+ ld r4, 40(r1)
+ ld r5, 48(r1)
+ ld r6, 56(r1)
+ ld r7, 64(r1)
+ ld r8, 72(r1)
+
+ /* Epilogue: pop frame, restore LR, return */
+ addi r1, r1, 112
+ ld r0, 16(r1)
+ mtlr r0
+ blr
+SYM_FUNC_END(arch_bpf_timed_may_goto)
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c
index 2e6adf5b95c4..720b1a500922 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -10,6 +10,7 @@
#include <linux/perf_event.h>
#include <linux/percpu.h>
#include <linux/hardirq.h>
+#include <linux/sysfs.h>
#include <linux/uaccess.h>
#include <asm/reg.h>
#include <asm/pmc.h>
@@ -2204,7 +2205,7 @@ ssize_t power_events_sysfs_show(struct device *dev,
pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
- return sprintf(page, "event=0x%02llx\n", pmu_attr->id);
+ return sysfs_emit(page, "event=0x%02llx\n", pmu_attr->id);
}
static struct pmu power_pmu = {
@@ -2483,7 +2484,7 @@ static void __perf_event_interrupt(struct pt_regs *regs)
* will trigger a PMI after waking up from idle. Since counter values are _not_
* saved/restored in idle path, can lead to below "Can't find PMC" message.
*/
- if (unlikely(!found) && !arch_irq_disabled_regs(regs))
+ if (unlikely(!found) && !regs_irqs_disabled(regs))
printk_ratelimited(KERN_WARNING "Can't find PMC that caused IRQ\n");
/*
diff --git a/arch/powerpc/perf/core-fsl-emb.c b/arch/powerpc/perf/core-fsl-emb.c
index 7120ab20cbfe..02b5dd74c187 100644
--- a/arch/powerpc/perf/core-fsl-emb.c
+++ b/arch/powerpc/perf/core-fsl-emb.c
@@ -366,9 +366,10 @@ static void fsl_emb_pmu_del(struct perf_event *event, int flags)
cpuhw->n_events--;
+ put_cpu_var(cpu_hw_events);
+
out:
perf_pmu_enable(event->pmu);
- put_cpu_var(cpu_hw_events);
}
static void fsl_emb_pmu_start(struct perf_event *event, int ef_flags)
diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c
index 243c0a1c8cda..abb4cfb11fcc 100644
--- a/arch/powerpc/perf/hv-24x7.c
+++ b/arch/powerpc/perf/hv-24x7.c
@@ -12,6 +12,7 @@
#include <linux/rbtree.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/sysfs.h>
#include <linux/vmalloc.h>
#include <asm/cputhreads.h>
@@ -434,19 +435,19 @@ static ssize_t cpumask_show(struct device *dev,
static ssize_t sockets_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%d\n", phys_sockets);
+ return sysfs_emit(buf, "%d\n", phys_sockets);
}
static ssize_t chipspersocket_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%d\n", phys_chipspersocket);
+ return sysfs_emit(buf, "%d\n", phys_chipspersocket);
}
static ssize_t coresperchip_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%d\n", phys_coresperchip);
+ return sysfs_emit(buf, "%d\n", phys_coresperchip);
}
static struct attribute *device_str_attr_create_(char *name, char *str)
@@ -1061,7 +1062,7 @@ e_free:
static ssize_t domains_show(struct device *dev, struct device_attribute *attr,
char *page)
{
- int d, n, count = 0;
+ int d, count = 0;
const char *str;
for (d = 0; d < HV_PERF_DOMAIN_MAX; d++) {
@@ -1069,12 +1070,7 @@ static ssize_t domains_show(struct device *dev, struct device_attribute *attr,
if (!str)
continue;
- n = sprintf(page, "%d: %s\n", d, str);
- if (n < 0)
- break;
-
- count += n;
- page += n;
+ count += sysfs_emit_at(page, count, "%d: %s\n", d, str);
}
return count;
}
@@ -1095,7 +1091,7 @@ static ssize_t _name##_show(struct device *dev, \
ret = -EIO; \
goto e_free; \
} \
- ret = sprintf(buf, _fmt, _expr); \
+ ret = sysfs_emit(buf, _fmt, _expr); \
e_free: \
kmem_cache_free(hv_page_cache, page); \
return ret; \
diff --git a/arch/powerpc/perf/hv-gpci.c b/arch/powerpc/perf/hv-gpci.c
index 10c82cf8f5b3..7269273d3aa8 100644
--- a/arch/powerpc/perf/hv-gpci.c
+++ b/arch/powerpc/perf/hv-gpci.c
@@ -11,6 +11,7 @@
#include <linux/init.h>
#include <linux/perf_event.h>
+#include <linux/sysfs.h>
#include <asm/firmware.h>
#include <asm/hvcall.h>
#include <asm/io.h>
@@ -85,7 +86,7 @@ static ssize_t _name##_show(struct device *dev, \
if (hret) \
return -EIO; \
\
- return sprintf(page, _format, caps._name); \
+ return sysfs_emit(page, _format, caps._name); \
} \
static struct device_attribute hv_caps_attr_##_name = __ATTR_RO(_name)
@@ -93,7 +94,7 @@ static ssize_t kernel_version_show(struct device *dev,
struct device_attribute *attr,
char *page)
{
- return sprintf(page, "0x%x\n", COUNTER_INFO_VERSION_CURRENT);
+ return sysfs_emit(page, "0x%x\n", COUNTER_INFO_VERSION_CURRENT);
}
static ssize_t cpumask_show(struct device *dev,
diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c
index c1563b4eaa94..e3822f36c419 100644
--- a/arch/powerpc/perf/imc-pmu.c
+++ b/arch/powerpc/perf/imc-pmu.c
@@ -421,7 +421,6 @@ static int ppc_nest_imc_cpu_offline(unsigned int cpu)
static int ppc_nest_imc_cpu_online(unsigned int cpu)
{
const struct cpumask *l_cpumask;
- static struct cpumask tmp_mask;
int res;
/* Get the cpumask of this node */
@@ -431,7 +430,7 @@ static int ppc_nest_imc_cpu_online(unsigned int cpu)
* If this is not the first online CPU on this node, then
* just return.
*/
- if (cpumask_and(&tmp_mask, l_cpumask, &nest_imc_cpumask))
+ if (cpumask_intersects(l_cpumask, &nest_imc_cpumask))
return 0;
/*
@@ -647,14 +646,13 @@ static bool is_core_imc_mem_inited(int cpu)
static int ppc_core_imc_cpu_online(unsigned int cpu)
{
const struct cpumask *l_cpumask;
- static struct cpumask tmp_mask;
int ret = 0;
/* Get the cpumask for this core */
l_cpumask = cpu_sibling_mask(cpu);
/* If a cpu for this core is already set, then, don't do anything */
- if (cpumask_and(&tmp_mask, l_cpumask, &core_imc_cpumask))
+ if (cpumask_intersects(l_cpumask, &core_imc_cpumask))
return 0;
if (!is_core_imc_mem_inited(cpu)) {
diff --git a/arch/powerpc/perf/kvm-hv-pmu.c b/arch/powerpc/perf/kvm-hv-pmu.c
index ae264c9080ef..aa72b96b5a8c 100644
--- a/arch/powerpc/perf/kvm-hv-pmu.c
+++ b/arch/powerpc/perf/kvm-hv-pmu.c
@@ -16,6 +16,7 @@
#include <linux/perf_event.h>
#include <linux/spinlock_types.h>
#include <linux/spinlock.h>
+#include <linux/sysfs.h>
#include <asm/types.h>
#include <asm/kvm_ppc.h>
@@ -48,7 +49,7 @@ static ssize_t kvmppc_events_sysfs_show(struct device *dev,
struct perf_pmu_events_attr *pmu_attr;
pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
- return sprintf(page, "event=0x%02llx\n", pmu_attr->id);
+ return sysfs_emit(page, "event=0x%02llx\n", pmu_attr->id);
}
/* Holds the hostwide stats */
diff --git a/arch/powerpc/perf/vpa-pmu.c b/arch/powerpc/perf/vpa-pmu.c
index 840733468959..bff4cfab7b94 100644
--- a/arch/powerpc/perf/vpa-pmu.c
+++ b/arch/powerpc/perf/vpa-pmu.c
@@ -8,6 +8,7 @@
#include <linux/module.h>
#include <linux/perf_event.h>
+#include <linux/sysfs.h>
#include <asm/kvm_ppc.h>
#include <asm/kvm_book3s_64.h>
@@ -26,7 +27,7 @@ static ssize_t vpa_pmu_events_sysfs_show(struct device *dev,
pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
- return sprintf(page, "event=0x%02llx\n", pmu_attr->id);
+ return sysfs_emit(page, "event=0x%02llx\n", pmu_attr->id);
}
#define VPA_PMU_EVENT_ATTR(_name, _id) \
diff --git a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
index 9b693594a5f7..c3fbec1f1d24 100644
--- a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
+++ b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
@@ -15,6 +15,7 @@
#include <linux/i2c.h>
#include <linux/gpio/driver.h>
#include <linux/slab.h>
+#include <linux/sysfs.h>
#include <linux/kthread.h>
#include <linux/property.h>
#include <linux/reboot.h>
@@ -77,7 +78,7 @@ static ssize_t show_status(struct device *d,
return -ENODEV;
mcu->reg_ctrl = ret;
- return sprintf(buf, "%02x\n", ret);
+ return sysfs_emit(buf, "%02x\n", ret);
}
static DEVICE_ATTR(status, 0444, show_status, NULL);
diff --git a/arch/powerpc/platforms/8xx/cpm1.c b/arch/powerpc/platforms/8xx/cpm1.c
index f00734f0590c..b31376bf6778 100644
--- a/arch/powerpc/platforms/8xx/cpm1.c
+++ b/arch/powerpc/platforms/8xx/cpm1.c
@@ -472,6 +472,18 @@ static int cpm1_gpio16_dir_in(struct gpio_chip *gc, unsigned int gpio)
return 0;
}
+static int cpm1_gpio16_get_direction(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct cpm1_gpio16_chip *cpm1_gc = gpiochip_get_data(gc);
+ struct cpm_ioport16 __iomem *iop = cpm1_gc->regs;
+ u16 pin_mask = 1 << (15 - gpio);
+
+ if (in_be16(&iop->dir) & pin_mask)
+ return GPIO_LINE_DIRECTION_OUT;
+
+ return GPIO_LINE_DIRECTION_IN;
+}
+
int cpm1_gpiochip_add16(struct device *dev)
{
struct device_node *np = dev->of_node;
@@ -498,6 +510,7 @@ int cpm1_gpiochip_add16(struct device *dev)
gc->ngpio = 16;
gc->direction_input = cpm1_gpio16_dir_in;
gc->direction_output = cpm1_gpio16_dir_out;
+ gc->get_direction = cpm1_gpio16_get_direction;
gc->get = cpm1_gpio16_get;
gc->set = cpm1_gpio16_set;
gc->to_irq = cpm1_gpio16_to_irq;
@@ -604,6 +617,18 @@ static int cpm1_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio)
return 0;
}
+static int cpm1_gpio32_get_direction(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct cpm1_gpio32_chip *cpm1_gc = gpiochip_get_data(gc);
+ struct cpm_ioport32b __iomem *iop = cpm1_gc->regs;
+ u32 pin_mask = 1 << (31 - gpio);
+
+ if (in_be32(&iop->dir) & pin_mask)
+ return GPIO_LINE_DIRECTION_OUT;
+
+ return GPIO_LINE_DIRECTION_IN;
+}
+
int cpm1_gpiochip_add32(struct device *dev)
{
struct device_node *np = dev->of_node;
@@ -621,6 +646,7 @@ int cpm1_gpiochip_add32(struct device *dev)
gc->ngpio = 32;
gc->direction_input = cpm1_gpio32_dir_in;
gc->direction_output = cpm1_gpio32_dir_out;
+ gc->get_direction = cpm1_gpio32_get_direction;
gc->get = cpm1_gpio32_get;
gc->set = cpm1_gpio32_set;
gc->parent = dev;
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index 0ec7b3bdda56..8452153d4650 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -20,6 +20,7 @@
#include <linux/mutex.h>
#include <linux/linux_logo.h>
#include <linux/syscore_ops.h>
+#include <linux/sysfs.h>
#include <asm/spu.h>
#include <asm/spu_priv1.h>
#include <asm/spu_csa.h>
@@ -638,8 +639,8 @@ static ssize_t spu_stat_show(struct device *dev,
{
struct spu *spu = container_of(dev, struct spu, dev);
- return sprintf(buf, "%s %llu %llu %llu %llu "
- "%llu %llu %llu %llu %llu %llu %llu %llu\n",
+ return sysfs_emit(buf,
+ "%s %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
spu_state_names[spu->stats.util_state],
spu_acct_time(spu, SPU_UTIL_USER),
spu_acct_time(spu, SPU_UTIL_SYSTEM),
diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c
index 6cd461f82968..33103a98cfd5 100644
--- a/arch/powerpc/platforms/powernv/idle.c
+++ b/arch/powerpc/platforms/powernv/idle.c
@@ -8,6 +8,7 @@
#include <linux/types.h>
#include <linux/mm.h>
#include <linux/slab.h>
+#include <linux/sysfs.h>
#include <linux/of.h>
#include <linux/device.h>
#include <linux/cpu.h>
@@ -171,7 +172,7 @@ static u8 fastsleep_workaround_applyonce;
static ssize_t show_fastsleep_workaround_applyonce(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%u\n", fastsleep_workaround_applyonce);
+ return sysfs_emit(buf, "%u\n", fastsleep_workaround_applyonce);
}
static ssize_t store_fastsleep_workaround_applyonce(struct device *dev,
diff --git a/arch/powerpc/platforms/powernv/opal-dump.c b/arch/powerpc/platforms/powernv/opal-dump.c
index 2e4bffa74163..0586821d7af4 100644
--- a/arch/powerpc/platforms/powernv/opal-dump.c
+++ b/arch/powerpc/platforms/powernv/opal-dump.c
@@ -8,6 +8,7 @@
#include <linux/kobject.h>
#include <linux/mm.h>
#include <linux/slab.h>
+#include <linux/sysfs.h>
#include <linux/vmalloc.h>
#include <linux/pagemap.h>
#include <linux/delay.h>
@@ -40,7 +41,7 @@ static ssize_t dump_id_show(struct dump_obj *dump_obj,
struct dump_attribute *attr,
char *buf)
{
- return sprintf(buf, "0x%x\n", dump_obj->id);
+ return sysfs_emit(buf, "0x%x\n", dump_obj->id);
}
static const char* dump_type_to_string(uint32_t type)
@@ -58,15 +59,15 @@ static ssize_t dump_type_show(struct dump_obj *dump_obj,
char *buf)
{
- return sprintf(buf, "0x%x %s\n", dump_obj->type,
- dump_type_to_string(dump_obj->type));
+ return sysfs_emit(buf, "0x%x %s\n", dump_obj->type,
+ dump_type_to_string(dump_obj->type));
}
static ssize_t dump_ack_show(struct dump_obj *dump_obj,
struct dump_attribute *attr,
char *buf)
{
- return sprintf(buf, "ack - acknowledge dump\n");
+ return sysfs_emit(buf, "ack - acknowledge dump\n");
}
/*
@@ -114,7 +115,7 @@ static ssize_t init_dump_show(struct dump_obj *dump_obj,
struct dump_attribute *attr,
char *buf)
{
- return sprintf(buf, "1 - initiate Service Processor(FSP) dump\n");
+ return sysfs_emit(buf, "1 - initiate Service Processor(FSP) dump\n");
}
static int64_t dump_fips_init(uint8_t type)
diff --git a/arch/powerpc/platforms/powernv/opal-elog.c b/arch/powerpc/platforms/powernv/opal-elog.c
index 2b8331922ab9..6cacd3fd3cd5 100644
--- a/arch/powerpc/platforms/powernv/opal-elog.c
+++ b/arch/powerpc/platforms/powernv/opal-elog.c
@@ -40,7 +40,7 @@ static ssize_t elog_id_show(struct elog_obj *elog_obj,
struct elog_attribute *attr,
char *buf)
{
- return sprintf(buf, "0x%llx\n", elog_obj->id);
+ return sysfs_emit(buf, "0x%llx\n", elog_obj->id);
}
static const char *elog_type_to_string(uint64_t type)
@@ -55,16 +55,15 @@ static ssize_t elog_type_show(struct elog_obj *elog_obj,
struct elog_attribute *attr,
char *buf)
{
- return sprintf(buf, "0x%llx %s\n",
- elog_obj->type,
- elog_type_to_string(elog_obj->type));
+ return sysfs_emit(buf, "0x%llx %s\n", elog_obj->type,
+ elog_type_to_string(elog_obj->type));
}
static ssize_t elog_ack_show(struct elog_obj *elog_obj,
struct elog_attribute *attr,
char *buf)
{
- return sprintf(buf, "ack - acknowledge log message\n");
+ return sysfs_emit(buf, "ack - acknowledge log message\n");
}
static ssize_t elog_ack_store(struct elog_obj *elog_obj,
diff --git a/arch/powerpc/platforms/powernv/opal-flash.c b/arch/powerpc/platforms/powernv/opal-flash.c
index a3f7a2928767..5ca5f6329a2d 100644
--- a/arch/powerpc/platforms/powernv/opal-flash.c
+++ b/arch/powerpc/platforms/powernv/opal-flash.c
@@ -238,7 +238,7 @@ static ssize_t manage_show(struct kobject *kobj,
struct manage_flash_t *const args_buf = &manage_flash_data;
int rc;
- rc = sprintf(buf, "%d\n", args_buf->status);
+ rc = sysfs_emit(buf, "%d\n", args_buf->status);
/* Set status to default*/
args_buf->status = FLASH_NO_OP;
return rc;
@@ -321,7 +321,7 @@ static ssize_t update_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
struct update_flash_t *const args_buf = &update_flash_data;
- return sprintf(buf, "%d\n", args_buf->status);
+ return sysfs_emit(buf, "%d\n", args_buf->status);
}
/*
diff --git a/arch/powerpc/platforms/powernv/opal-powercap.c b/arch/powerpc/platforms/powernv/opal-powercap.c
index 9bb73cb42a65..bf18b333281e 100644
--- a/arch/powerpc/platforms/powernv/opal-powercap.c
+++ b/arch/powerpc/platforms/powernv/opal-powercap.c
@@ -10,6 +10,7 @@
#include <linux/of.h>
#include <linux/kobject.h>
#include <linux/slab.h>
+#include <linux/sysfs.h>
#include <asm/opal.h>
@@ -56,16 +57,11 @@ static ssize_t powercap_show(struct kobject *kobj, struct kobj_attribute *attr,
goto out;
}
ret = opal_error_code(opal_get_async_rc(msg));
- if (!ret) {
- ret = sprintf(buf, "%u\n", be32_to_cpu(pcap));
- if (ret < 0)
- ret = -EIO;
- }
+ if (!ret)
+ ret = sysfs_emit(buf, "%u\n", be32_to_cpu(pcap));
break;
case OPAL_SUCCESS:
- ret = sprintf(buf, "%u\n", be32_to_cpu(pcap));
- if (ret < 0)
- ret = -EIO;
+ ret = sysfs_emit(buf, "%u\n", be32_to_cpu(pcap));
break;
default:
ret = opal_error_code(ret);
diff --git a/arch/powerpc/platforms/powernv/opal-psr.c b/arch/powerpc/platforms/powernv/opal-psr.c
index 24d0a894d965..19228181cb6f 100644
--- a/arch/powerpc/platforms/powernv/opal-psr.c
+++ b/arch/powerpc/platforms/powernv/opal-psr.c
@@ -10,6 +10,7 @@
#include <linux/of.h>
#include <linux/kobject.h>
#include <linux/slab.h>
+#include <linux/sysfs.h>
#include <asm/opal.h>
@@ -50,16 +51,11 @@ static ssize_t psr_show(struct kobject *kobj, struct kobj_attribute *attr,
goto out;
}
ret = opal_error_code(opal_get_async_rc(msg));
- if (!ret) {
- ret = sprintf(buf, "%u\n", be32_to_cpu(psr));
- if (ret < 0)
- ret = -EIO;
- }
+ if (!ret)
+ ret = sysfs_emit(buf, "%u\n", be32_to_cpu(psr));
break;
case OPAL_SUCCESS:
- ret = sprintf(buf, "%u\n", be32_to_cpu(psr));
- if (ret < 0)
- ret = -EIO;
+ ret = sysfs_emit(buf, "%u\n", be32_to_cpu(psr));
break;
default:
ret = opal_error_code(ret);
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index 4dbb47ddbdcc..06ed5e2aa265 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -396,7 +396,8 @@ static void pnv_kexec_wait_secondaries_down(void)
{
int my_cpu, i, notified = -1;
- my_cpu = get_cpu();
+ /* Called with interrupts disabled, so the CPU is pinned. */
+ my_cpu = raw_smp_processor_id();
for_each_online_cpu(i) {
uint8_t status;
diff --git a/arch/powerpc/platforms/powernv/subcore.c b/arch/powerpc/platforms/powernv/subcore.c
index 393e747541fb..f7668ef1ac1f 100644
--- a/arch/powerpc/platforms/powernv/subcore.c
+++ b/arch/powerpc/platforms/powernv/subcore.c
@@ -12,6 +12,7 @@
#include <linux/gfp.h>
#include <linux/smp.h>
#include <linux/stop_machine.h>
+#include <linux/sysfs.h>
#include <asm/cputhreads.h>
#include <asm/cpuidle.h>
@@ -409,7 +410,7 @@ out:
static ssize_t show_subcores_per_core(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%x\n", subcores_per_core);
+ return sysfs_emit(buf, "%x\n", subcores_per_core);
}
static DEVICE_ATTR(subcores_per_core, 0644,
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index 150c09b58ae8..ca2608a70f4d 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -10,6 +10,7 @@
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/root_dev.h>
+#include <linux/sysfs.h>
#include <linux/console.h>
#include <linux/export.h>
#include <linux/memblock.h>
@@ -183,7 +184,7 @@ static int ps3_set_dabr(unsigned long dabr, unsigned long dabrx)
static ssize_t ps3_fw_version_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
- return sprintf(buf, "%s", ps3_firmware_version_str);
+ return sysfs_emit(buf, "%s\n", ps3_firmware_version_str);
}
static int __init ps3_setup_sysfs(void)
diff --git a/arch/powerpc/platforms/pseries/cmm.c b/arch/powerpc/platforms/pseries/cmm.c
index 8d83df12430f..38e22125b96f 100644
--- a/arch/powerpc/platforms/pseries/cmm.c
+++ b/arch/powerpc/platforms/pseries/cmm.c
@@ -18,6 +18,7 @@
#include <linux/sched.h>
#include <linux/stringify.h>
#include <linux/swap.h>
+#include <linux/sysfs.h>
#include <linux/device.h>
#include <linux/balloon.h>
#include <asm/firmware.h>
@@ -333,7 +334,7 @@ static int cmm_thread(void *dummy)
struct device_attribute *attr, \
char *buf) \
{ \
- return sprintf(buf, format, ##args); \
+ return sysfs_emit(buf, format, ##args); \
} \
static DEVICE_ATTR(name, 0444, show_##name, NULL)
@@ -343,7 +344,7 @@ CMM_SHOW(loaned_target_kb, "%lu\n", PAGES2KB(loaned_pages_target));
static ssize_t show_oom_pages(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%lu\n", PAGES2KB(oom_freed_pages));
+ return sysfs_emit(buf, "%lu\n", PAGES2KB(oom_freed_pages));
}
static ssize_t store_oom_pages(struct device *dev,
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index a7c451c2507d..f4d33b8dffd8 100644
--- a/arch/powerpc/platforms/pseries/dlpar.c
+++ b/arch/powerpc/platforms/pseries/dlpar.c
@@ -14,6 +14,7 @@
#include <linux/spinlock.h>
#include <linux/cpu.h>
#include <linux/slab.h>
+#include <linux/sysfs.h>
#include <linux/of.h>
#include "of_helpers.h"
@@ -798,7 +799,7 @@ dlpar_store_out:
static ssize_t dlpar_show(const struct class *class, const struct class_attribute *attr,
char *buf)
{
- return sprintf(buf, "%s\n", "memory,cpu,dt");
+ return sysfs_emit(buf, "%s\n", "memory,cpu,dt");
}
static CLASS_ATTR_RW(dlpar);
diff --git a/arch/powerpc/platforms/pseries/ibmebus.c b/arch/powerpc/platforms/pseries/ibmebus.c
index cad2deb7e70d..2d0f991da2c8 100644
--- a/arch/powerpc/platforms/pseries/ibmebus.c
+++ b/arch/powerpc/platforms/pseries/ibmebus.c
@@ -46,6 +46,7 @@
#include <linux/of.h>
#include <linux/slab.h>
#include <linux/stat.h>
+#include <linux/sysfs.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <asm/ibmebus.h>
@@ -399,7 +400,7 @@ static ssize_t devspec_show(struct device *dev,
struct platform_device *ofdev;
ofdev = to_platform_device(dev);
- return sprintf(buf, "%pOF\n", ofdev->dev.of_node);
+ return sysfs_emit(buf, "%pOF\n", ofdev->dev.of_node);
}
static DEVICE_ATTR_RO(devspec);
@@ -409,7 +410,7 @@ static ssize_t name_show(struct device *dev,
struct platform_device *ofdev;
ofdev = to_platform_device(dev);
- return sprintf(buf, "%pOFn\n", ofdev->dev.of_node);
+ return sysfs_emit(buf, "%pOFn\n", ofdev->dev.of_node);
}
static DEVICE_ATTR_RO(name);
diff --git a/arch/powerpc/platforms/pseries/lparcfg.c b/arch/powerpc/platforms/pseries/lparcfg.c
index 8821c378bfff..54b7ecf375b5 100644
--- a/arch/powerpc/platforms/pseries/lparcfg.c
+++ b/arch/powerpc/platforms/pseries/lparcfg.c
@@ -22,6 +22,7 @@
#include <asm/papr-sysparm.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
+#include <linux/string.h>
#include <linux/uaccess.h>
#include <linux/hugetlb.h>
#include <asm/lppaca.h>
@@ -431,17 +432,18 @@ static void parse_system_parameter_string(struct seq_file *m)
w_idx = 0;
} else if (local_buffer[idx] == '=') {
/* code here to replace workbuffer contents
- with different keyword strings */
- if (0 == strcmp(workbuffer, "MaxEntCap")) {
- strcpy(workbuffer,
- "partition_max_entitled_capacity");
- w_idx = strlen(workbuffer);
- }
- if (0 == strcmp(workbuffer, "MaxPlatProcs")) {
- strcpy(workbuffer,
- "system_potential_processors");
- w_idx = strlen(workbuffer);
- }
+ * with different keyword strings. Truncation
+ * by strscpy is deliberately ignored because
+ * SPLPAR_MAXLENGTH >= maximum string size.
+ */
+ if (!strcmp(workbuffer, "MaxEntCap"))
+ w_idx = strscpy(workbuffer,
+ "partition_max_entitled_capacity",
+ SPLPAR_MAXLENGTH);
+ if (!strcmp(workbuffer, "MaxPlatProcs"))
+ w_idx = strscpy(workbuffer,
+ "system_potential_processors",
+ SPLPAR_MAXLENGTH);
}
}
kfree(workbuffer);
diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index 63eca4ebb5e5..75da96c08cdd 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -8,6 +8,7 @@
#include <linux/ioport.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
+#include <linux/sysfs.h>
#include <linux/ndctl.h>
#include <linux/sched.h>
#include <linux/libnvdimm.h>
@@ -1062,8 +1063,8 @@ static ssize_t health_bitmap_inject_show(struct device *dev,
struct nvdimm *dimm = to_nvdimm(dev);
struct papr_scm_priv *p = nvdimm_provider_data(dimm);
- return sprintf(buf, "%#llx\n",
- READ_ONCE(p->health_bitmap_inject_mask));
+ return sysfs_emit(buf, "%#llx\n",
+ READ_ONCE(p->health_bitmap_inject_mask));
}
static DEVICE_ATTR_ADMIN_RO(health_bitmap_inject);
diff --git a/arch/powerpc/platforms/pseries/power.c b/arch/powerpc/platforms/pseries/power.c
index 3676cb297767..7b9dfe829f25 100644
--- a/arch/powerpc/platforms/pseries/power.c
+++ b/arch/powerpc/platforms/pseries/power.c
@@ -11,6 +11,7 @@
#include <linux/kobject.h>
#include <linux/string.h>
+#include <linux/sysfs.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <asm/machdep.h>
@@ -22,7 +23,7 @@ unsigned long rtas_poweron_auto; /* default and normal state is 0 */
static ssize_t auto_poweron_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
- return sprintf(buf, "%lu\n", rtas_poweron_auto);
+ return sysfs_emit(buf, "%lu\n", rtas_poweron_auto);
}
static ssize_t auto_poweron_store(struct kobject *kobj,
diff --git a/arch/powerpc/platforms/pseries/pseries_energy.c b/arch/powerpc/platforms/pseries/pseries_energy.c
index 2c661b798235..fdaf85ecd39b 100644
--- a/arch/powerpc/platforms/pseries/pseries_energy.c
+++ b/arch/powerpc/platforms/pseries/pseries_energy.c
@@ -12,6 +12,7 @@
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/seq_file.h>
+#include <linux/sysfs.h>
#include <linux/device.h>
#include <linux/cpu.h>
#include <linux/of.h>
@@ -242,7 +243,7 @@ static ssize_t get_best_energy_data(struct device *dev,
if (rc != H_SUCCESS)
return -EINVAL;
- return sprintf(page, "%lu\n", retbuf[1] >> 32);
+ return sysfs_emit(page, "%lu\n", retbuf[1] >> 32);
}
/* Wrapper functions */
diff --git a/arch/powerpc/platforms/pseries/rtas-fadump.c b/arch/powerpc/platforms/pseries/rtas-fadump.c
index eceb3289383e..3bb4ac2ab6cc 100644
--- a/arch/powerpc/platforms/pseries/rtas-fadump.c
+++ b/arch/powerpc/platforms/pseries/rtas-fadump.c
@@ -179,9 +179,42 @@ static u64 rtas_fadump_get_bootmem_min(void)
return RTAS_FADUMP_MIN_BOOT_MEM;
}
+/*
+ * Helper to make an ibm,configure-kernel-dump RTAS call with a bounded
+ * busy-wait loop. Returns the RTAS return code on completion, or
+ * -ETIMEDOUT if firmware keeps returning a busy status beyond
+ * RTAS_FADUMP_MAX_WAIT_MS milliseconds.
+ */
+static int rtas_fadump_call(struct fw_dump *fadump_conf, int operation,
+ void *fdm_ptr, unsigned int fdm_size,
+ const char *op_name)
+{
+ unsigned int wait_time, total_wait = 0;
+ int rc;
+
+ do {
+ rc = rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
+ NULL, operation, fdm_ptr, fdm_size);
+ wait_time = rtas_busy_delay_time(rc);
+ if (wait_time) {
+ pr_debug("Firmware busy during fadump %s, waiting %ums (total %ums)\n",
+ op_name, wait_time, total_wait);
+ if (total_wait >= RTAS_FADUMP_MAX_WAIT_MS) {
+ pr_err("Timed out waiting for firmware to complete fadump %s\n",
+ op_name);
+ return -ETIMEDOUT;
+ }
+ total_wait += wait_time;
+ mdelay(wait_time);
+ }
+ } while (wait_time);
+
+ return rc;
+}
+
static int rtas_fadump_register(struct fw_dump *fadump_conf)
{
- unsigned int wait_time, fdm_size;
+ unsigned int fdm_size;
int rc, err = -EIO;
/*
@@ -192,16 +225,10 @@ static int rtas_fadump_register(struct fw_dump *fadump_conf)
fdm_size = sizeof(struct rtas_fadump_section_header);
fdm_size += be16_to_cpu(fdm.header.dump_num_sections) * sizeof(struct rtas_fadump_section);
- /* TODO: Add upper time limit for the delay */
- do {
- rc = rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
- NULL, FADUMP_REGISTER, &fdm, fdm_size);
-
- wait_time = rtas_busy_delay_time(rc);
- if (wait_time)
- mdelay(wait_time);
-
- } while (wait_time);
+ rc = rtas_fadump_call(fadump_conf, FADUMP_REGISTER, &fdm, fdm_size,
+ "register");
+ if (rc == -ETIMEDOUT)
+ return -ETIMEDOUT;
switch (rc) {
case 0:
@@ -234,19 +261,12 @@ static int rtas_fadump_register(struct fw_dump *fadump_conf)
static int rtas_fadump_unregister(struct fw_dump *fadump_conf)
{
- unsigned int wait_time;
int rc;
- /* TODO: Add upper time limit for the delay */
- do {
- rc = rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
- NULL, FADUMP_UNREGISTER, &fdm,
- sizeof(struct rtas_fadump_mem_struct));
-
- wait_time = rtas_busy_delay_time(rc);
- if (wait_time)
- mdelay(wait_time);
- } while (wait_time);
+ rc = rtas_fadump_call(fadump_conf, FADUMP_UNREGISTER, &fdm,
+ sizeof(struct rtas_fadump_mem_struct), "unregister");
+ if (rc == -ETIMEDOUT)
+ return -ETIMEDOUT;
if (rc) {
pr_err("Failed to un-register - unexpected error(%d).\n", rc);
@@ -259,19 +279,13 @@ static int rtas_fadump_unregister(struct fw_dump *fadump_conf)
static int rtas_fadump_invalidate(struct fw_dump *fadump_conf)
{
- unsigned int wait_time;
int rc;
- /* TODO: Add upper time limit for the delay */
- do {
- rc = rtas_call(fadump_conf->ibm_configure_kernel_dump, 3, 1,
- NULL, FADUMP_INVALIDATE, fdm_active,
- sizeof(struct rtas_fadump_mem_struct));
-
- wait_time = rtas_busy_delay_time(rc);
- if (wait_time)
- mdelay(wait_time);
- } while (wait_time);
+ rc = rtas_fadump_call(fadump_conf, FADUMP_INVALIDATE,
+ (void *)fdm_active,
+ sizeof(struct rtas_fadump_mem_struct), "invalidate");
+ if (rc == -ETIMEDOUT)
+ return -ETIMEDOUT;
if (rc) {
pr_err("Failed to invalidate - unexpected error (%d).\n", rc);
diff --git a/arch/powerpc/platforms/pseries/rtas-fadump.h b/arch/powerpc/platforms/pseries/rtas-fadump.h
index c109abf6befd..65fdab7b5b8d 100644
--- a/arch/powerpc/platforms/pseries/rtas-fadump.h
+++ b/arch/powerpc/platforms/pseries/rtas-fadump.h
@@ -41,6 +41,12 @@
#define MAX_SECTIONS 10
#define RTAS_FADUMP_MAX_BOOT_MEM_REGS 7
+/*
+ * Maximum time to wait for firmware to respond to an
+ * ibm,configure-kernel-dump RTAS call before giving up.
+ */
+#define RTAS_FADUMP_MAX_WAIT_MS 60000U
+
/* Kernel Dump section info */
struct rtas_fadump_section {
__be32 request_flag;
diff --git a/arch/powerpc/platforms/pseries/suspend.c b/arch/powerpc/platforms/pseries/suspend.c
index c51db63d3e88..a9928d75624a 100644
--- a/arch/powerpc/platforms/pseries/suspend.c
+++ b/arch/powerpc/platforms/pseries/suspend.c
@@ -7,6 +7,7 @@
#include <linux/delay.h>
#include <linux/suspend.h>
#include <linux/stat.h>
+#include <linux/sysfs.h>
#include <asm/firmware.h>
#include <asm/hvcall.h>
#include <asm/machdep.h>
@@ -121,7 +122,7 @@ static ssize_t show_hibernate(struct device *dev,
struct device_attribute *attr,
char *buf)
{
- return sprintf(buf, "%d\n", KERN_DT_UPDATE);
+ return sysfs_emit(buf, "%d\n", KERN_DT_UPDATE);
}
static DEVICE_ATTR(hibernate, 0644, show_hibernate, store_hibernate);
diff --git a/arch/powerpc/platforms/pseries/vas-sysfs.c b/arch/powerpc/platforms/pseries/vas-sysfs.c
index 4f6fbbb672ae..00c6ffd3ef39 100644
--- a/arch/powerpc/platforms/pseries/vas-sysfs.c
+++ b/arch/powerpc/platforms/pseries/vas-sysfs.c
@@ -10,6 +10,7 @@
#include <linux/miscdevice.h>
#include <linux/kobject.h>
#include <linux/slab.h>
+#include <linux/sysfs.h>
#include <linux/mm.h>
#include "vas.h"
@@ -58,7 +59,7 @@ static ssize_t update_total_credits_store(struct vas_cop_feat_caps *caps,
#define sysfs_caps_entry_read(_name) \
static ssize_t _name##_show(struct vas_cop_feat_caps *caps, char *buf) \
{ \
- return sprintf(buf, "%d\n", atomic_read(&caps->_name)); \
+ return sysfs_emit(buf, "%d\n", atomic_read(&caps->_name)); \
}
struct vas_sysfs_entry {
diff --git a/arch/powerpc/platforms/pseries/vio.c b/arch/powerpc/platforms/pseries/vio.c
index 08e2add48adb..572bdf42335e 100644
--- a/arch/powerpc/platforms/pseries/vio.c
+++ b/arch/powerpc/platforms/pseries/vio.c
@@ -14,6 +14,7 @@
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/stat.h>
+#include <linux/sysfs.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/slab.h>
@@ -942,14 +943,14 @@ static ssize_t cmo_##name##_show(struct device *dev, \
struct device_attribute *attr, \
char *buf) \
{ \
- return sprintf(buf, "%lu\n", to_vio_dev(dev)->cmo.name); \
+ return sysfs_emit(buf, "%lu\n", to_vio_dev(dev)->cmo.name); \
}
static ssize_t cmo_allocs_failed_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct vio_dev *viodev = to_vio_dev(dev);
- return sprintf(buf, "%d\n", atomic_read(&viodev->cmo.allocs_failed));
+ return sysfs_emit(buf, "%d\n", atomic_read(&viodev->cmo.allocs_failed));
}
static ssize_t cmo_allocs_failed_store(struct device *dev,
@@ -998,7 +999,7 @@ static DEVICE_ATTR_RW(cmo_allocs_failed);
#define viobus_cmo_rd_attr(name) \
static ssize_t cmo_bus_##name##_show(const struct bus_type *bt, char *buf) \
{ \
- return sprintf(buf, "%lu\n", vio_cmo.name); \
+ return sysfs_emit(buf, "%lu\n", vio_cmo.name); \
} \
static struct bus_attribute bus_attr_cmo_bus_##name = \
__ATTR(cmo_##name, S_IRUGO, cmo_bus_##name##_show, NULL)
@@ -1007,7 +1008,7 @@ static struct bus_attribute bus_attr_cmo_bus_##name = \
static ssize_t \
cmo_##name##_##var##_show(const struct bus_type *bt, char *buf) \
{ \
- return sprintf(buf, "%lu\n", vio_cmo.name.var); \
+ return sysfs_emit(buf, "%lu\n", vio_cmo.name.var); \
} \
static BUS_ATTR_RO(cmo_##name##_##var)
@@ -1022,7 +1023,7 @@ viobus_cmo_pool_rd_attr(excess, free);
static ssize_t cmo_high_show(const struct bus_type *bt, char *buf)
{
- return sprintf(buf, "%lu\n", vio_cmo.high);
+ return sysfs_emit(buf, "%lu\n", vio_cmo.high);
}
static ssize_t cmo_high_store(const struct bus_type *bt, const char *buf,
@@ -1535,7 +1536,7 @@ machine_device_initcall(pseries, vio_device_init);
static ssize_t name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- return sprintf(buf, "%s\n", to_vio_dev(dev)->name);
+ return sysfs_emit(buf, "%s\n", to_vio_dev(dev)->name);
}
static DEVICE_ATTR_RO(name);
@@ -1544,7 +1545,7 @@ static ssize_t devspec_show(struct device *dev,
{
struct device_node *of_node = dev->of_node;
- return sprintf(buf, "%pOF\n", of_node);
+ return sysfs_emit(buf, "%pOF\n", of_node);
}
static DEVICE_ATTR_RO(devspec);
@@ -1556,17 +1557,13 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
const char *cp;
dn = dev->of_node;
- if (!dn) {
- strcpy(buf, "\n");
- return strlen(buf);
- }
+ if (!dn)
+ return sysfs_emit(buf, "\n");
cp = of_get_property(dn, "compatible", NULL);
- if (!cp) {
- strcpy(buf, "\n");
- return strlen(buf);
- }
+ if (!cp)
+ return sysfs_emit(buf, "\n");
- return sprintf(buf, "vio:T%sS%s\n", vio_dev->type, cp);
+ return sysfs_emit(buf, "vio:T%sS%s\n", vio_dev->type, cp);
}
static DEVICE_ATTR_RO(modalias);
diff --git a/arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c b/arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c
index f9e64f54dc14..f63b89adf9f3 100644
--- a/arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c
+++ b/arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c
@@ -7,6 +7,7 @@
#include <linux/kernel.h>
#include <linux/slab.h>
+#include <linux/sysfs.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/interrupt.h>
@@ -61,7 +62,7 @@ static ssize_t fsl_timer_wakeup_show(struct device *dev,
}
mutex_unlock(&sysfs_lock);
- return sprintf(buf, "%lld\n", interval);
+ return sysfs_emit(buf, "%lld\n", interval);
}
static ssize_t fsl_timer_wakeup_store(struct device *dev,
diff --git a/arch/powerpc/sysdev/xive/common.c b/arch/powerpc/sysdev/xive/common.c
index c120be73d149..dadd1f46ec93 100644
--- a/arch/powerpc/sysdev/xive/common.c
+++ b/arch/powerpc/sysdev/xive/common.c
@@ -564,6 +564,7 @@ static int xive_find_target_in_mask(const struct cpumask *mask,
return cpu;
}
+ WARN_ONCE(1, "target CPU not found in mask: %*pbl\n", cpumask_pr_args(mask));
return -1;
}