summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-socfpga/Kconfig2
-rw-r--r--[-rwxr-xr-x]arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dtsi0
-rw-r--r--[-rwxr-xr-x]arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_emmc.dts0
-rw-r--r--arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-an400.dts2
-rw-r--r--arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts113
-rw-r--r--arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi44
-rw-r--r--arch/arm64/boot/dts/renesas/r8a779f0.dtsi1
-rw-r--r--arch/arm64/boot/dts/renesas/r9a09g047.dtsi10
-rw-r--r--arch/arm64/boot/dts/renesas/r9a09g056.dtsi10
-rw-r--r--arch/arm64/boot/dts/renesas/r9a09g057.dtsi10
-rw-r--r--arch/arm64/boot/dts/renesas/r9a09g077.dtsi27
-rw-r--r--arch/arm64/boot/dts/renesas/r9a09g087.dtsi27
-rw-r--r--arch/arm64/include/asm/percpu.h20
-rw-r--r--arch/arm64/kernel/hibernate-asm.S2
-rw-r--r--arch/arm64/kernel/hibernate.c4
-rw-r--r--arch/arm64/kernel/mte.c2
-rw-r--r--arch/arm64/tools/sysreg4
-rw-r--r--arch/mips/Kconfig4
-rw-r--r--arch/mips/cavium-octeon/octeon-platform.c4
-rw-r--r--arch/mips/configs/econet_en751221_defconfig264
-rw-r--r--arch/powerpc/include/asm/entry-common.h2
-rw-r--r--arch/powerpc/kernel/iommu.c2
-rw-r--r--arch/powerpc/kernel/prom.c1
-rw-r--r--arch/powerpc/kexec/elf_64.c2
-rw-r--r--arch/powerpc/kvm/book3s_hv.c4
-rw-r--r--arch/powerpc/kvm/book3s_hv_nested.c2
-rw-r--r--arch/powerpc/kvm/book3s_hv_uvmem.c5
-rw-r--r--arch/powerpc/platforms/pasemi/setup.c2
-rw-r--r--arch/powerpc/platforms/pseries/htmdump.c19
-rw-r--r--arch/riscv/Kconfig2
-rw-r--r--arch/riscv/include/asm/bug.h5
-rw-r--r--arch/riscv/include/asm/switch_to.h4
-rw-r--r--arch/riscv/kernel/cpufeature.c20
-rw-r--r--arch/riscv/kernel/patch.c2
-rw-r--r--arch/riscv/kernel/process.c4
-rw-r--r--arch/riscv/kernel/sys_hwprobe.c5
-rw-r--r--arch/riscv/kernel/usercfi.c5
-rw-r--r--arch/riscv/lib/uaccess.S5
-rw-r--r--arch/riscv/mm/init.c4
-rw-r--r--arch/s390/crypto/Makefile2
-rw-r--r--arch/s390/crypto/aes_s390.c87
-rw-r--r--arch/s390/crypto/paes_s390.c184
-rw-r--r--arch/s390/crypto/phmac_s390.c36
-rw-r--r--arch/s390/include/asm/pai.h1
-rw-r--r--arch/s390/kernel/debug.c54
-rw-r--r--arch/s390/kernel/perf_pai.c196
-rw-r--r--arch/x86/events/intel/core.c33
-rw-r--r--arch/x86/events/intel/ds.c18
-rw-r--r--arch/x86/events/perf_event.h3
-rw-r--r--arch/x86/include/asm/div64.h2
-rw-r--r--arch/x86/include/asm/pgtable.h2
-rw-r--r--arch/x86/kernel/alternative.c111
-rw-r--r--arch/x86/kernel/amd_node.c6
-rw-r--r--arch/x86/mm/mem_encrypt.c3
-rw-r--r--arch/x86/mm/pat/set_memory.c53
55 files changed, 1116 insertions, 320 deletions
diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig
index eb72c240c248..528c5c1368c3 100644
--- a/arch/arm/mach-socfpga/Kconfig
+++ b/arch/arm/mach-socfpga/Kconfig
@@ -16,7 +16,7 @@ menuconfig ARCH_INTEL_SOCFPGA
select ARM_ERRATA_775420
select PL310_ERRATA_588369
select PL310_ERRATA_727915
- select PL310_ERRATA_753970 if PL310
+ select PL310_ERRATA_753970
select PL310_ERRATA_769419
select RESET_CONTROLLER
diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dtsi b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dtsi
index 1d50f7b21160..1d50f7b21160 100755..100644
--- a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dtsi
+++ b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dtsi
diff --git a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_emmc.dts b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_emmc.dts
index b2a3449638dd..b2a3449638dd 100755..100644
--- a/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_emmc.dts
+++ b/arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_emmc.dts
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-an400.dts b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-an400.dts
index cab2ee9ea0d3..ca7536f772ff 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-an400.dts
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-an400.dts
@@ -33,7 +33,7 @@
};
&uart_a {
- clocks = <&xtal>, <&xtal>, <&xtal>;
+ clocks = <&xtal>, <&clkc_periphs CLKID_SYS_UART_A>, <&xtal>;
clock-names = "xtal", "pclk", "baud";
status = "okay";
};
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
index c41525a34b72..77abfd555ec5 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7-a311d2-khadas-vim4.dts
@@ -71,7 +71,6 @@
vin-supply = <&vddao_3v3>;
gpio = <&gpio GPIOD_11 GPIO_ACTIVE_LOW>;
regulator-boot-on;
- regulator-always-on;
};
sdio_pwrseq: sdio-pwrseq {
@@ -105,6 +104,66 @@
enable-active-high;
};
+ vdd_ddr: regulator-vddddr {
+ /*
+ * SY8003ADFC Regulator.
+ */
+ compatible = "pwm-regulator";
+ regulator-name = "VDDDDR";
+ regulator-min-microvolt = <690000>;
+ regulator-max-microvolt = <890000>;
+ pwm-supply = <&dc_in>;
+ pwms = <&pwm_ao_gh 0 1500 0>;
+ pwm-dutycycle-range = <100 0>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vdd_ee: regulator-vddee {
+ /*
+ * MP8756GD Regulator.
+ */
+ compatible = "pwm-regulator";
+ regulator-name = "VDDEE";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <922000>;
+ pwm-supply = <&dc_in>;
+ pwms = <&pwm_ao_ab 0 1500 0>;
+ pwm-dutycycle-range = <100 0>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vdd_gpu: regulator-vddgpu {
+ /*
+ * SY8003ADFC Regulator.
+ */
+ compatible = "pwm-regulator";
+ regulator-name = "VDDGPU";
+ regulator-min-microvolt = <700000>;
+ regulator-max-microvolt = <922000>;
+ pwm-supply = <&dc_in>;
+ pwms = <&pwm_ao_ef 0 1500 0>;
+ pwm-dutycycle-range = <100 0>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vdd_npu: regulator-vddnpu {
+ /*
+ * SY8003ADFC Regulator.
+ */
+ compatible = "pwm-regulator";
+ regulator-name = "VDDNPU";
+ regulator-min-microvolt = <733000>;
+ regulator-max-microvolt = <933000>;
+ pwm-supply = <&dc_in>;
+ pwms = <&pwm_ao_ef 1 1500 0>;
+ pwm-dutycycle-range = <100 0>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
vddao_1v8: regulator-vddao-1v8 {
compatible = "regulator-fixed";
regulator-name = "VDDAO_1V8";
@@ -123,6 +182,36 @@
regulator-always-on;
};
+ vddcpu_a: regulator-vddcpu-a {
+ /*
+ * MP8756GD Regulator.
+ */
+ compatible = "pwm-regulator";
+ regulator-name = "VDDCPU_A";
+ regulator-min-microvolt = <689000>;
+ regulator-max-microvolt = <1049000>;
+ pwm-supply = <&dc_in>;
+ pwms = <&pwm_ao_cd 1 1500 0>;
+ pwm-dutycycle-range = <100 0>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
+ vddcpu_b: regulator-vddcpu-b {
+ /*
+ * MP8756GD Regulator.
+ */
+ compatible = "pwm-regulator";
+ regulator-name = "VDDCPU_B";
+ regulator-min-microvolt = <689000>;
+ regulator-max-microvolt = <1049000>;
+ pwm-supply = <&dc_in>;
+ pwms = <&pwm_ao_ab 1 1500 0>;
+ pwm-dutycycle-range = <100 0>;
+ regulator-boot-on;
+ regulator-always-on;
+ };
+
vddio_1v8: regulator-vddio-1v8 {
compatible = "regulator-fixed";
regulator-name = "VDDIO_1V8";
@@ -173,9 +262,27 @@
pinctrl-names = "default";
};
+&pwm_ao_ab {
+ status = "okay";
+ pinctrl-0 = <&pwm_ao_a_pins>, <&pwm_ao_b_pins>;
+ pinctrl-names = "default";
+};
+
&pwm_ao_cd {
status = "okay";
- pinctrl-0 = <&pwm_ao_c_d_pins>;
+ pinctrl-0 = <&pwm_ao_c_d_pins>, <&pwm_ao_d_pins>;
+ pinctrl-names = "default";
+};
+
+&pwm_ao_ef {
+ status = "okay";
+ pinctrl-0 = <&pwm_ao_e_pins>, <&pwm_ao_f_pins>;
+ pinctrl-names = "default";
+};
+
+&pwm_ao_gh {
+ status = "okay";
+ pinctrl-0 = <&pwm_ao_g_e_pins>;
pinctrl-names = "default";
};
@@ -266,6 +373,6 @@
&uart_a {
status = "okay";
- clocks = <&xtal>, <&xtal>, <&xtal>;
+ clocks = <&xtal>, <&clkc_periphs CLKID_SYS_UART_A>, <&xtal>;
clock-names = "xtal", "pclk", "baud";
};
diff --git a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
index c3dc479b137d..719e111bc3dd 100644
--- a/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
+++ b/arch/arm64/boot/dts/amlogic/amlogic-t7.dtsi
@@ -458,9 +458,25 @@
};
};
- pwm_ao_g_pins: pwm-ao-g {
+ pwm_ao_g_d11_pins: pwm-ao-g-d11 {
mux {
- groups = "pwm_ao_g";
+ groups = "pwm_ao_g_d11";
+ function = "pwm_ao_g";
+ bias-disable;
+ };
+ };
+
+ pwm_ao_g_d7_pins: pwm-ao-g-d7 {
+ mux {
+ groups = "pwm_ao_g_d7";
+ function = "pwm_ao_g";
+ bias-disable;
+ };
+ };
+
+ pwm_ao_g_e_pins: pwm-ao-g-e {
+ mux {
+ groups = "pwm_ao_g_e";
function = "pwm_ao_g";
bias-disable;
};
@@ -474,9 +490,17 @@
};
};
- pwm_ao_h_pins: pwm-ao-h {
+ pwm_ao_h_d5_pins: pwm-ao-h-d5 {
mux {
- groups = "pwm_ao_h";
+ groups = "pwm_ao_h_d5";
+ function = "pwm_ao_h";
+ bias-disable;
+ };
+ };
+
+ pwm_ao_h_d10_pins: pwm-ao-h-d10 {
+ mux {
+ groups = "pwm_ao_h_d10";
function = "pwm_ao_h";
bias-disable;
};
@@ -522,9 +546,17 @@
};
};
- pwm_vs_pins: pwm-vs {
+ pwm_vs_y_pins: pwm-vs-y {
+ mux {
+ groups = "pwm_vs_y";
+ function = "pwm_vs";
+ bias-disable;
+ };
+ };
+
+ pwm_vs_h_pins: pwm-vs-h {
mux {
- groups = "pwm_vs";
+ groups = "pwm_vs_h";
function = "pwm_vs";
bias-disable;
};
diff --git a/arch/arm64/boot/dts/renesas/r8a779f0.dtsi b/arch/arm64/boot/dts/renesas/r8a779f0.dtsi
index cbb161c863ac..a5118c2f2742 100644
--- a/arch/arm64/boot/dts/renesas/r8a779f0.dtsi
+++ b/arch/arm64/boot/dts/renesas/r8a779f0.dtsi
@@ -901,6 +901,7 @@
clocks = <&cpg CPG_MOD 1514>, <&ufs30_clk>;
clock-names = "fck", "ref_clk";
freq-table-hz = <200000000 200000000>, <38400000 38400000>;
+ lanes-per-direction = <1>;
power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>;
resets = <&cpg 1514>;
status = "disabled";
diff --git a/arch/arm64/boot/dts/renesas/r9a09g047.dtsi b/arch/arm64/boot/dts/renesas/r9a09g047.dtsi
index 73757e8e2197..060405d4a2dd 100644
--- a/arch/arm64/boot/dts/renesas/r9a09g047.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a09g047.dtsi
@@ -1913,23 +1913,28 @@
mtl_tx_setup0: tx-queues-config {
snps,tx-queues-to-use = <4>;
+ snps,tx-sched-wrr;
queue0 {
+ snps,weight = <0x10>;
snps,dcb-algorithm;
snps,priority = <0x1>;
};
queue1 {
+ snps,weight = <0x12>;
snps,dcb-algorithm;
snps,priority = <0x2>;
};
queue2 {
+ snps,weight = <0x14>;
snps,dcb-algorithm;
snps,priority = <0x4>;
};
queue3 {
+ snps,weight = <0x18>;
snps,dcb-algorithm;
snps,priority = <0x8>;
};
@@ -2013,23 +2018,28 @@
mtl_tx_setup1: tx-queues-config {
snps,tx-queues-to-use = <4>;
+ snps,tx-sched-wrr;
queue0 {
+ snps,weight = <0x10>;
snps,dcb-algorithm;
snps,priority = <0x1>;
};
queue1 {
+ snps,weight = <0x12>;
snps,dcb-algorithm;
snps,priority = <0x2>;
};
queue2 {
+ snps,weight = <0x14>;
snps,dcb-algorithm;
snps,priority = <0x4>;
};
queue3 {
+ snps,weight = <0x18>;
snps,dcb-algorithm;
snps,priority = <0x8>;
};
diff --git a/arch/arm64/boot/dts/renesas/r9a09g056.dtsi b/arch/arm64/boot/dts/renesas/r9a09g056.dtsi
index 76fa34ff3d07..77c2221a9e2a 100644
--- a/arch/arm64/boot/dts/renesas/r9a09g056.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a09g056.dtsi
@@ -1585,23 +1585,28 @@
mtl_tx_setup0: tx-queues-config {
snps,tx-queues-to-use = <4>;
+ snps,tx-sched-wrr;
queue0 {
+ snps,weight = <0x10>;
snps,dcb-algorithm;
snps,priority = <0x1>;
};
queue1 {
+ snps,weight = <0x12>;
snps,dcb-algorithm;
snps,priority = <0x2>;
};
queue2 {
+ snps,weight = <0x14>;
snps,dcb-algorithm;
snps,priority = <0x4>;
};
queue3 {
+ snps,weight = <0x18>;
snps,dcb-algorithm;
snps,priority = <0x8>;
};
@@ -1686,23 +1691,28 @@
mtl_tx_setup1: tx-queues-config {
snps,tx-queues-to-use = <4>;
+ snps,tx-sched-wrr;
queue0 {
+ snps,weight = <0x10>;
snps,dcb-algorithm;
snps,priority = <0x1>;
};
queue1 {
+ snps,weight = <0x12>;
snps,dcb-algorithm;
snps,priority = <0x2>;
};
queue2 {
+ snps,weight = <0x14>;
snps,dcb-algorithm;
snps,priority = <0x4>;
};
queue3 {
+ snps,weight = <0x18>;
snps,dcb-algorithm;
snps,priority = <0x8>;
};
diff --git a/arch/arm64/boot/dts/renesas/r9a09g057.dtsi b/arch/arm64/boot/dts/renesas/r9a09g057.dtsi
index 639693d464a7..188ce9f9c7c2 100644
--- a/arch/arm64/boot/dts/renesas/r9a09g057.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a09g057.dtsi
@@ -1715,23 +1715,28 @@
mtl_tx_setup0: tx-queues-config {
snps,tx-queues-to-use = <4>;
+ snps,tx-sched-wrr;
queue0 {
+ snps,weight = <0x10>;
snps,dcb-algorithm;
snps,priority = <0x1>;
};
queue1 {
+ snps,weight = <0x12>;
snps,dcb-algorithm;
snps,priority = <0x2>;
};
queue2 {
+ snps,weight = <0x14>;
snps,dcb-algorithm;
snps,priority = <0x4>;
};
queue3 {
+ snps,weight = <0x18>;
snps,dcb-algorithm;
snps,priority = <0x8>;
};
@@ -1816,23 +1821,28 @@
mtl_tx_setup1: tx-queues-config {
snps,tx-queues-to-use = <4>;
+ snps,tx-sched-wrr;
queue0 {
+ snps,weight = <0x10>;
snps,dcb-algorithm;
snps,priority = <0x1>;
};
queue1 {
+ snps,weight = <0x12>;
snps,dcb-algorithm;
snps,priority = <0x2>;
};
queue2 {
+ snps,weight = <0x14>;
snps,dcb-algorithm;
snps,priority = <0x4>;
};
queue3 {
+ snps,weight = <0x18>;
snps,dcb-algorithm;
snps,priority = <0x8>;
};
diff --git a/arch/arm64/boot/dts/renesas/r9a09g077.dtsi b/arch/arm64/boot/dts/renesas/r9a09g077.dtsi
index 40494159831d..bac39390ead7 100644
--- a/arch/arm64/boot/dts/renesas/r9a09g077.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a09g077.dtsi
@@ -642,36 +642,45 @@
mtl_tx_setup0: tx-queues-config {
snps,tx-queues-to-use = <8>;
+ snps,tx-sched-wrr;
queue0 {
+ snps,weight = <0x10>;
snps,dcb-algorithm;
};
queue1 {
+ snps,weight = <0x11>;
snps,dcb-algorithm;
};
queue2 {
+ snps,weight = <0x12>;
snps,dcb-algorithm;
};
queue3 {
+ snps,weight = <0x13>;
snps,dcb-algorithm;
};
queue4 {
+ snps,weight = <0x14>;
snps,dcb-algorithm;
};
queue5 {
+ snps,weight = <0x15>;
snps,dcb-algorithm;
};
queue6 {
+ snps,weight = <0x16>;
snps,dcb-algorithm;
};
queue7 {
+ snps,weight = <0x17>;
snps,dcb-algorithm;
};
};
@@ -788,36 +797,45 @@
mtl_tx_setup1: tx-queues-config {
snps,tx-queues-to-use = <8>;
+ snps,tx-sched-wrr;
queue0 {
+ snps,weight = <0x10>;
snps,dcb-algorithm;
};
queue1 {
+ snps,weight = <0x11>;
snps,dcb-algorithm;
};
queue2 {
+ snps,weight = <0x12>;
snps,dcb-algorithm;
};
queue3 {
+ snps,weight = <0x13>;
snps,dcb-algorithm;
};
queue4 {
+ snps,weight = <0x14>;
snps,dcb-algorithm;
};
queue5 {
+ snps,weight = <0x15>;
snps,dcb-algorithm;
};
queue6 {
+ snps,weight = <0x16>;
snps,dcb-algorithm;
};
queue7 {
+ snps,weight = <0x17>;
snps,dcb-algorithm;
};
};
@@ -934,36 +952,45 @@
mtl_tx_setup2: tx-queues-config {
snps,tx-queues-to-use = <8>;
+ snps,tx-sched-wrr;
queue0 {
+ snps,weight = <0x10>;
snps,dcb-algorithm;
};
queue1 {
+ snps,weight = <0x11>;
snps,dcb-algorithm;
};
queue2 {
+ snps,weight = <0x12>;
snps,dcb-algorithm;
};
queue3 {
+ snps,weight = <0x13>;
snps,dcb-algorithm;
};
queue4 {
+ snps,weight = <0x14>;
snps,dcb-algorithm;
};
queue5 {
+ snps,weight = <0x15>;
snps,dcb-algorithm;
};
queue6 {
+ snps,weight = <0x16>;
snps,dcb-algorithm;
};
queue7 {
+ snps,weight = <0x17>;
snps,dcb-algorithm;
};
};
diff --git a/arch/arm64/boot/dts/renesas/r9a09g087.dtsi b/arch/arm64/boot/dts/renesas/r9a09g087.dtsi
index e8d4f76949cc..03b976d93e10 100644
--- a/arch/arm64/boot/dts/renesas/r9a09g087.dtsi
+++ b/arch/arm64/boot/dts/renesas/r9a09g087.dtsi
@@ -643,36 +643,45 @@
mtl_tx_setup0: tx-queues-config {
snps,tx-queues-to-use = <8>;
+ snps,tx-sched-wrr;
queue0 {
+ snps,weight = <0x10>;
snps,dcb-algorithm;
};
queue1 {
+ snps,weight = <0x11>;
snps,dcb-algorithm;
};
queue2 {
+ snps,weight = <0x12>;
snps,dcb-algorithm;
};
queue3 {
+ snps,weight = <0x13>;
snps,dcb-algorithm;
};
queue4 {
+ snps,weight = <0x14>;
snps,dcb-algorithm;
};
queue5 {
+ snps,weight = <0x15>;
snps,dcb-algorithm;
};
queue6 {
+ snps,weight = <0x16>;
snps,dcb-algorithm;
};
queue7 {
+ snps,weight = <0x17>;
snps,dcb-algorithm;
};
};
@@ -790,36 +799,45 @@
mtl_tx_setup1: tx-queues-config {
snps,tx-queues-to-use = <8>;
+ snps,tx-sched-wrr;
queue0 {
+ snps,weight = <0x10>;
snps,dcb-algorithm;
};
queue1 {
+ snps,weight = <0x11>;
snps,dcb-algorithm;
};
queue2 {
+ snps,weight = <0x12>;
snps,dcb-algorithm;
};
queue3 {
+ snps,weight = <0x13>;
snps,dcb-algorithm;
};
queue4 {
+ snps,weight = <0x14>;
snps,dcb-algorithm;
};
queue5 {
+ snps,weight = <0x15>;
snps,dcb-algorithm;
};
queue6 {
+ snps,weight = <0x16>;
snps,dcb-algorithm;
};
queue7 {
+ snps,weight = <0x17>;
snps,dcb-algorithm;
};
};
@@ -937,36 +955,45 @@
mtl_tx_setup2: tx-queues-config {
snps,tx-queues-to-use = <8>;
+ snps,tx-sched-wrr;
queue0 {
+ snps,weight = <0x10>;
snps,dcb-algorithm;
};
queue1 {
+ snps,weight = <0x11>;
snps,dcb-algorithm;
};
queue2 {
+ snps,weight = <0x12>;
snps,dcb-algorithm;
};
queue3 {
+ snps,weight = <0x13>;
snps,dcb-algorithm;
};
queue4 {
+ snps,weight = <0x14>;
snps,dcb-algorithm;
};
queue5 {
+ snps,weight = <0x15>;
snps,dcb-algorithm;
};
queue6 {
+ snps,weight = <0x16>;
snps,dcb-algorithm;
};
queue7 {
+ snps,weight = <0x17>;
snps,dcb-algorithm;
};
};
diff --git a/arch/arm64/include/asm/percpu.h b/arch/arm64/include/asm/percpu.h
index b57b2bb00967..8cf4068ce1b5 100644
--- a/arch/arm64/include/asm/percpu.h
+++ b/arch/arm64/include/asm/percpu.h
@@ -77,7 +77,7 @@ __percpu_##name##_case_##sz(void *ptr, unsigned long val) \
" stxr" #sfx "\t%w[loop], %" #w "[tmp], %[ptr]\n" \
" cbnz %w[loop], 1b", \
/* LSE atomics */ \
- #op_lse "\t%" #w "[val], %" #w "[tmp], %[ptr]\n" \
+ #op_lse #sfx "\t%" #w "[val], %" #w "[tmp], %[ptr]\n" \
__nops(3)) \
: [loop] "=&r" (loop), [tmp] "=&r" (tmp), \
[ptr] "+Q"(*(u##sz *)ptr) \
@@ -98,7 +98,7 @@ __percpu_##name##_return_case_##sz(void *ptr, unsigned long val) \
" stxr" #sfx "\t%w[loop], %" #w "[ret], %[ptr]\n" \
" cbnz %w[loop], 1b", \
/* LSE atomics */ \
- #op_lse "\t%" #w "[val], %" #w "[ret], %[ptr]\n" \
+ #op_lse #sfx "\t%" #w "[val], %" #w "[ret], %[ptr]\n" \
#op_llsc "\t%" #w "[ret], %" #w "[ret], %" #w "[val]\n" \
__nops(2)) \
: [loop] "=&r" (loop), [ret] "=&r" (ret), \
@@ -179,13 +179,13 @@ PERCPU_RET_OP(add, add, ldadd)
_pcp_protect_return(__percpu_read_64, pcp)
#define this_cpu_write_1(pcp, val) \
- _pcp_protect(__percpu_write_8, pcp, (unsigned long)val)
+ _pcp_protect(__percpu_write_8, pcp, (unsigned long)(val))
#define this_cpu_write_2(pcp, val) \
- _pcp_protect(__percpu_write_16, pcp, (unsigned long)val)
+ _pcp_protect(__percpu_write_16, pcp, (unsigned long)(val))
#define this_cpu_write_4(pcp, val) \
- _pcp_protect(__percpu_write_32, pcp, (unsigned long)val)
+ _pcp_protect(__percpu_write_32, pcp, (unsigned long)(val))
#define this_cpu_write_8(pcp, val) \
- _pcp_protect(__percpu_write_64, pcp, (unsigned long)val)
+ _pcp_protect(__percpu_write_64, pcp, (unsigned long)(val))
#define this_cpu_add_1(pcp, val) \
_pcp_protect(__percpu_add_case_8, pcp, val)
@@ -206,13 +206,13 @@ PERCPU_RET_OP(add, add, ldadd)
_pcp_protect_return(__percpu_add_return_case_64, pcp, val)
#define this_cpu_and_1(pcp, val) \
- _pcp_protect(__percpu_andnot_case_8, pcp, ~val)
+ _pcp_protect(__percpu_andnot_case_8, pcp, ~(u8)(val))
#define this_cpu_and_2(pcp, val) \
- _pcp_protect(__percpu_andnot_case_16, pcp, ~val)
+ _pcp_protect(__percpu_andnot_case_16, pcp, ~(u16)(val))
#define this_cpu_and_4(pcp, val) \
- _pcp_protect(__percpu_andnot_case_32, pcp, ~val)
+ _pcp_protect(__percpu_andnot_case_32, pcp, ~(u32)(val))
#define this_cpu_and_8(pcp, val) \
- _pcp_protect(__percpu_andnot_case_64, pcp, ~val)
+ _pcp_protect(__percpu_andnot_case_64, pcp, ~(u64)(val))
#define this_cpu_or_1(pcp, val) \
_pcp_protect(__percpu_or_case_8, pcp, val)
diff --git a/arch/arm64/kernel/hibernate-asm.S b/arch/arm64/kernel/hibernate-asm.S
index 0e1d9c3c6a93..2baefe7a82d3 100644
--- a/arch/arm64/kernel/hibernate-asm.S
+++ b/arch/arm64/kernel/hibernate-asm.S
@@ -89,6 +89,8 @@ alternative_insn "dc cvau, x4", "dc civac, x4", ARM64_WORKAROUND_CLEAN_CACHE
isb
cbz x24, 3f /* Do we need to re-initialise EL2? */
+ mov x1, x24
+ mov x0, #HVC_SET_VECTORS
hvc #0
3: ret
SYM_CODE_END(swsusp_arch_suspend_exit)
diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c
index 7bf117427777..424291c547f0 100644
--- a/arch/arm64/kernel/hibernate.c
+++ b/arch/arm64/kernel/hibernate.c
@@ -423,8 +423,8 @@ int __nocfi swsusp_arch_resume(void)
* Create a second copy of just the linear map, and use this when
* restoring.
*/
- rc = trans_pgd_create_copy(&trans_info, &tmp_pg_dir, PAGE_OFFSET,
- PAGE_END);
+ rc = trans_pgd_create_copy(&trans_info, &tmp_pg_dir,
+ _PAGE_OFFSET(vabits_actual), PAGE_END);
if (rc)
return rc;
diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
index 1a9aad6ef22a..31f5c6b0510e 100644
--- a/arch/arm64/kernel/mte.c
+++ b/arch/arm64/kernel/mte.c
@@ -476,7 +476,7 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
* was never mapped with PROT_MTE.
*/
if (!(vma->vm_flags & VM_MTE)) {
- err = -EOPNOTSUPP;
+ err = -EIO;
put_page(page);
break;
}
diff --git a/arch/arm64/tools/sysreg b/arch/arm64/tools/sysreg
index 94bf065c8ac7..e2d37ee221b8 100644
--- a/arch/arm64/tools/sysreg
+++ b/arch/arm64/tools/sysreg
@@ -3761,7 +3761,9 @@ Sysreg ICC_CR0_EL1 3 1 12 0 1
Res0 63:39
Field 38 PID
Field 37:32 IPPT
-Res0 31:1
+Res0 31:3
+Field 2 LINK_IDLE
+Field 1 LINK
Field 0 EN
EndSysreg
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index e2eb9627bd14..d7c67cebe065 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -396,10 +396,7 @@ config ECONET
bool "EcoNet MIPS family"
select BOOT_RAW
select DEBUG_ZBOOT if DEBUG_KERNEL
- select EARLY_PRINTK_8250
select ECONET_EN751221_TIMER
- select SERIAL_8250
- select SERIAL_OF_PLATFORM
select SYS_SUPPORTS_BIG_ENDIAN
select SYS_HAS_CPU_MIPS32_R1
select SYS_HAS_CPU_MIPS32_R2
@@ -661,6 +658,7 @@ config EYEQ
select USB_UHCI_BIG_ENDIAN_MMIO if CPU_BIG_ENDIAN
select USE_OF
select HOTPLUG_PARALLEL if HOTPLUG_CPU
+ select WEAK_REORDERING_BEYOND_LLSC
help
Select this to build a kernel supporting EyeQ SoC from Mobileye.
diff --git a/arch/mips/cavium-octeon/octeon-platform.c b/arch/mips/cavium-octeon/octeon-platform.c
index 47677b5d7ed0..f53c98372e0b 100644
--- a/arch/mips/cavium-octeon/octeon-platform.c
+++ b/arch/mips/cavium-octeon/octeon-platform.c
@@ -18,7 +18,7 @@
#include <asm/octeon/octeon.h>
#include <asm/octeon/cvmx-helper-board.h>
-#ifdef CONFIG_USB
+#if IS_ENABLED(CONFIG_USB)
#include <linux/usb/ehci_def.h>
#include <linux/usb/ehci_pdriver.h>
#include <linux/usb/ohci_pdriver.h>
@@ -1080,7 +1080,7 @@ end_led:
;
}
-#ifdef CONFIG_USB
+#if IS_ENABLED(CONFIG_USB)
/* OHCI/UHCI USB */
alias_prop = fdt_getprop(initial_boot_params, aliases,
"uctl", NULL);
diff --git a/arch/mips/configs/econet_en751221_defconfig b/arch/mips/configs/econet_en751221_defconfig
new file mode 100644
index 000000000000..b35d33fe4044
--- /dev/null
+++ b/arch/mips/configs/econet_en751221_defconfig
@@ -0,0 +1,264 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_XZ=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BPF_SYSCALL=y
+CONFIG_BPF_JIT=y
+CONFIG_PREEMPT=y
+CONFIG_CGROUPS=y
+CONFIG_MEMCG=y
+CONFIG_BLK_CGROUP=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_CFS_BANDWIDTH=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_CGROUP_PIDS=y
+CONFIG_CGROUP_RDMA=y
+CONFIG_CPUSETS=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_CGROUP_BPF=y
+CONFIG_NAMESPACES=y
+# CONFIG_TIME_NS is not set
+CONFIG_USER_NS=y
+CONFIG_BLK_DEV_INITRD=y
+# CONFIG_RD_GZIP is not set
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
+# CONFIG_RD_LZ4 is not set
+# CONFIG_RD_ZSTD is not set
+# CONFIG_INITRAMFS_PRESERVE_MTIME is not set
+CONFIG_LD_DEAD_CODE_DATA_ELIMINATION=y
+CONFIG_EXPERT=y
+# CONFIG_SGETMASK_SYSCALL is not set
+# CONFIG_IO_URING is not set
+# CONFIG_RSEQ is not set
+# CONFIG_CACHESTAT_SYSCALL is not set
+CONFIG_ECONET=y
+CONFIG_CPU_MIPS32_R2=y
+CONFIG_ZBOOT_LOAD_ADDRESS=0x80020000
+CONFIG_ARCH_FORCE_MAX_ORDER=11
+# CONFIG_MIPS_FP_SUPPORT is not set
+CONFIG_NR_CPUS=2
+CONFIG_HZ_100=y
+CONFIG_MIPS_RAW_APPENDED_DTB=y
+# CONFIG_SCHED_SMT is not set
+CONFIG_JUMP_LABEL=y
+# CONFIG_STACKPROTECTOR_STRONG is not set
+# CONFIG_GCC_PLUGINS is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLOCK_LEGACY_AUTOLOAD is not set
+CONFIG_BLK_DEV_THROTTLING=y
+# CONFIG_BLK_DEBUG_FS is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_OF_PARTITION=y
+# CONFIG_MQ_IOSCHED_DEADLINE is not set
+# CONFIG_MQ_IOSCHED_KYBER is not set
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_SLAB_FREELIST_RANDOM=y
+CONFIG_SLAB_FREELIST_HARDENED=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_LRU_GEN=y
+CONFIG_LRU_GEN_ENABLED=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_DIAG is not set
+CONFIG_TCP_CONG_ADVANCED=y
+# CONFIG_TCP_CONG_BIC is not set
+# CONFIG_TCP_CONG_WESTWOOD is not set
+# CONFIG_TCP_CONG_HTCP is not set
+# CONFIG_IPV6_SIT is not set
+CONFIG_IPV6_SUBTREES=y
+CONFIG_IPV6_MROUTE=y
+CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y
+CONFIG_IPV6_PIMSM_V2=y
+CONFIG_IPV6_SEG6_LWTUNNEL=y
+CONFIG_MPTCP=y
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_EGRESS is not set
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_MARK=y
+CONFIG_NF_CONNTRACK_ZONES=y
+CONFIG_NF_CONNTRACK_PROCFS=y
+CONFIG_NF_CONNTRACK_TIMEOUT=y
+# CONFIG_NF_CT_PROTO_SCTP is not set
+CONFIG_NF_TABLES=m
+CONFIG_NF_TABLES_INET=y
+CONFIG_NF_TABLES_NETDEV=y
+CONFIG_NFT_NUMGEN=m
+CONFIG_NFT_CT=m
+CONFIG_NFT_FLOW_OFFLOAD=m
+CONFIG_NFT_LOG=m
+CONFIG_NFT_LIMIT=m
+CONFIG_NFT_MASQ=m
+CONFIG_NFT_REDIR=m
+CONFIG_NFT_NAT=m
+CONFIG_NFT_QUOTA=m
+CONFIG_NFT_REJECT=m
+CONFIG_NFT_HASH=m
+CONFIG_NFT_FIB_INET=m
+CONFIG_NF_FLOW_TABLE_INET=m
+CONFIG_NF_FLOW_TABLE=m
+CONFIG_NFT_FIB_IPV4=m
+CONFIG_NF_TABLES_ARP=y
+CONFIG_NF_LOG_IPV4=m
+CONFIG_NFT_FIB_IPV6=m
+CONFIG_NF_LOG_IPV6=m
+CONFIG_NF_TABLES_BRIDGE=m
+CONFIG_BRIDGE=y
+CONFIG_BRIDGE_VLAN_FILTERING=y
+CONFIG_VLAN_8021Q=y
+CONFIG_NET_SCHED=y
+CONFIG_NET_SCH_FQ_CODEL=y
+CONFIG_NET_SCH_DEFAULT=y
+CONFIG_DEFAULT_FQ_CODEL=y
+CONFIG_NET_SWITCHDEV=y
+CONFIG_NET_L3_MASTER_DEV=y
+CONFIG_RFKILL=y
+# CONFIG_LWTUNNEL_BPF is not set
+CONFIG_PCI=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIEAER=y
+# CONFIG_PCIEASPM is not set
+CONFIG_PCI_MSI=y
+# CONFIG_VGA_ARB is not set
+CONFIG_PCIE_MEDIATEK=y
+CONFIG_MTD=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_SPI_NAND=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_BEB_LIMIT=13
+CONFIG_MTD_UBI_BLOCK=y
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_ASIX is not set
+# CONFIG_NET_VENDOR_ENGLEDER is not set
+# CONFIG_NET_VENDOR_FUNGIBLE is not set
+# CONFIG_NET_VENDOR_LITEX is not set
+# CONFIG_NET_VENDOR_MICROSOFT is not set
+# CONFIG_NET_VENDOR_VERTEXCOM is not set
+# CONFIG_NET_VENDOR_WANGXUN is not set
+CONFIG_PPP=m
+CONFIG_PPP_FILTER=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+# CONFIG_WLAN_VENDOR_ADMTEK is not set
+# CONFIG_WLAN_VENDOR_ATH is not set
+# CONFIG_WLAN_VENDOR_ATMEL is not set
+# CONFIG_WLAN_VENDOR_BROADCOM is not set
+# CONFIG_WLAN_VENDOR_INTEL is not set
+# CONFIG_WLAN_VENDOR_INTERSIL is not set
+# CONFIG_WLAN_VENDOR_MARVELL is not set
+# CONFIG_WLAN_VENDOR_MEDIATEK is not set
+# CONFIG_WLAN_VENDOR_MICROCHIP is not set
+# CONFIG_WLAN_VENDOR_PURELIFI is not set
+# CONFIG_WLAN_VENDOR_RALINK is not set
+# CONFIG_WLAN_VENDOR_REALTEK is not set
+# CONFIG_WLAN_VENDOR_RSI is not set
+# CONFIG_WLAN_VENDOR_SILABS is not set
+# CONFIG_WLAN_VENDOR_ST is not set
+# CONFIG_WLAN_VENDOR_TI is not set
+# CONFIG_WLAN_VENDOR_ZYDAS is not set
+# CONFIG_WLAN_VENDOR_QUANTENNA is not set
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_LEGACY_TIOCSTI is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_DEVMEM is not set
+CONFIG_SPI=y
+# CONFIG_PTP_1588_CLOCK is not set
+CONFIG_GPIOLIB=y
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_MFD_SYSCON=y
+# CONFIG_USB_PCI is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_CLASS_MULTICOLOR=y
+CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_LEDS_TRIGGER_NETDEV=y
+CONFIG_STAGING=y
+# CONFIG_MIPS_PLATFORM_DEVICES is not set
+CONFIG_COMMON_CLK_EN7523=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_RESET_CONTROLLER=y
+CONFIG_PHY_ECONET_PCIE=y
+# CONFIG_DNOTIFY is not set
+CONFIG_FANOTIFY=y
+CONFIG_OVERLAY_FS=y
+# CONFIG_OVERLAY_FS_REDIRECT_ALWAYS_FOLLOW is not set
+# CONFIG_PROC_PAGE_MONITOR is not set
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_UBIFS_FS=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_FILE_DIRECT=y
+CONFIG_SQUASHFS_COMPILE_DECOMP_MULTI_PERCPU=y
+# CONFIG_SQUASHFS_ZLIB is not set
+CONFIG_SQUASHFS_XZ=y
+CONFIG_SQUASHFS_EMBEDDED=y
+CONFIG_KEYS=y
+CONFIG_INIT_STACK_NONE=y
+CONFIG_FORTIFY_SOURCE=y
+CONFIG_HARDENED_USERCOPY=y
+CONFIG_LIST_HARDENED=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_CCM=y
+CONFIG_CRYPTO_GCM=y
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_XZ_DEC_X86 is not set
+# CONFIG_XZ_DEC_POWERPC is not set
+# CONFIG_XZ_DEC_ARM is not set
+# CONFIG_XZ_DEC_ARMTHUMB is not set
+# CONFIG_XZ_DEC_ARM64 is not set
+# CONFIG_XZ_DEC_SPARC is not set
+# CONFIG_XZ_DEC_RISCV is not set
+CONFIG_PRINTK_TIME=y
+# CONFIG_DEBUG_MISC is not set
+CONFIG_DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT=y
+CONFIG_DEBUG_INFO_REDUCED=y
+CONFIG_FRAME_WARN=1024
+CONFIG_STRIP_ASM_SYMS=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_MAGIC_SYSRQ_SERIAL is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_SCHED_STACK_END_CHECK=y
+CONFIG_PANIC_ON_OOPS=y
+CONFIG_PANIC_TIMEOUT=1
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+# CONFIG_RCU_TRACE is not set
+# CONFIG_FTRACE is not set
diff --git a/arch/powerpc/include/asm/entry-common.h b/arch/powerpc/include/asm/entry-common.h
index 80b07750b531..8e91489fdf2b 100644
--- a/arch/powerpc/include/asm/entry-common.h
+++ b/arch/powerpc/include/asm/entry-common.h
@@ -222,8 +222,6 @@ static inline void arch_interrupt_enter_prepare(struct pt_regs *regs)
if (user_mode(regs)) {
kuap_lock();
- account_cpu_user_entry();
- account_stolen_time();
} else {
kuap_save_and_lock(regs);
/*
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index ee1b5cb557c9..1ae8384637b5 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -1076,7 +1076,7 @@ int iommu_tce_check_ioba(unsigned long page_shift,
if (ioba < offset)
return -EINVAL;
- if ((ioba + 1) > (offset + size))
+ if ((ioba + npages < ioba) || (ioba - offset + npages > size))
return -EINVAL;
return 0;
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 9ed9dde7d231..d218c8cc1f73 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -824,7 +824,6 @@ void __init early_init_devtree(void *params)
fadump_append_bootargs();
/* Scan memory nodes and rebuild MEMBLOCKs */
- early_init_dt_scan_root();
early_init_dt_scan_memory_ppc();
/*
diff --git a/arch/powerpc/kexec/elf_64.c b/arch/powerpc/kexec/elf_64.c
index ea50a072debf..d9a466cd602e 100644
--- a/arch/powerpc/kexec/elf_64.c
+++ b/arch/powerpc/kexec/elf_64.c
@@ -94,6 +94,8 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
cmdline = modified_cmdline;
}
+ kexec_dprintk("Command line: %s", cmdline ? cmdline : "");
+
if (initrd != NULL) {
kbuf.buffer = initrd;
kbuf.bufsz = kbuf.memsz = initrd_len;
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 0409ac9e7b31..dbac3573b2c8 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -6140,12 +6140,12 @@ static int kvmppc_irq_bypass_add_producer_hv(struct irq_bypass_consumer *cons,
struct kvm_kernel_irqfd *irqfd =
container_of(cons, struct kvm_kernel_irqfd, consumer);
- irqfd->producer = prod;
-
ret = kvmppc_set_passthru_irq(irqfd->kvm, prod->irq, irqfd->gsi);
if (ret)
pr_info("kvmppc_set_passthru_irq (irq %d, gsi %d) fails: %d\n",
prod->irq, irqfd->gsi, ret);
+ else
+ irqfd->producer = prod;
return ret;
}
diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c
index 22e616662255..a6ff42d7666c 100644
--- a/arch/powerpc/kvm/book3s_hv_nested.c
+++ b/arch/powerpc/kvm/book3s_hv_nested.c
@@ -1204,8 +1204,10 @@ static void kvmhv_emulate_tlbie_all_lpid(struct kvm_vcpu *vcpu, int ric)
spin_lock(&kvm->mmu_lock);
idr_for_each_entry(&kvm->arch.kvm_nested_guest_idr, gp, lpid) {
+ ++gp->refcnt;
spin_unlock(&kvm->mmu_lock);
kvmhv_emulate_tlbie_lpid(vcpu, gp, ric);
+ kvmhv_put_nested(gp);
spin_lock(&kvm->mmu_lock);
}
spin_unlock(&kvm->mmu_lock);
diff --git a/arch/powerpc/kvm/book3s_hv_uvmem.c b/arch/powerpc/kvm/book3s_hv_uvmem.c
index 5fbb95d90e99..463aef870c4e 100644
--- a/arch/powerpc/kvm/book3s_hv_uvmem.c
+++ b/arch/powerpc/kvm/book3s_hv_uvmem.c
@@ -779,8 +779,11 @@ static int kvmppc_svm_page_in(struct vm_area_struct *vma,
if (spage) {
ret = uv_page_in(kvm->arch.lpid, pfn << page_shift,
gpa, 0, page_shift);
- if (ret)
+ if (ret) {
+ unlock_page(dpage);
+ put_page(dpage);
goto out_finalize;
+ }
}
}
diff --git a/arch/powerpc/platforms/pasemi/setup.c b/arch/powerpc/platforms/pasemi/setup.c
index d03b41336901..45792ecd5dfd 100644
--- a/arch/powerpc/platforms/pasemi/setup.c
+++ b/arch/powerpc/platforms/pasemi/setup.c
@@ -165,6 +165,8 @@ static int __init pas_setup_mce_regs(void)
while (dev && reg < MAX_MCE_REGS) {
mce_regs[reg].name = kasprintf(GFP_KERNEL,
"mc%d_mcdebug_errsta", reg);
+ if (!mce_regs[reg].name)
+ return -ENOMEM;
mce_regs[reg].addr = pasemi_pci_getcfgaddr(dev, 0x730);
dev = pci_get_device(PCI_VENDOR_ID_PASEMI, 0xa00a, dev);
reg++;
diff --git a/arch/powerpc/platforms/pseries/htmdump.c b/arch/powerpc/platforms/pseries/htmdump.c
index 489a80e87082..f33941b80ada 100644
--- a/arch/powerpc/platforms/pseries/htmdump.c
+++ b/arch/powerpc/platforms/pseries/htmdump.c
@@ -527,28 +527,28 @@ static int htmdump_init_debugfs(void)
htm_status_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!htm_status_buf) {
pr_err("Failed to allocate htmstatus buf\n");
- return -ENOMEM;
+ goto htm_status_buf_err;
}
/* Debugfs interface file to present System Processor Configuration */
htm_info_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!htm_info_buf) {
pr_err("Failed to allocate htm info buf\n");
- return -ENOMEM;
+ goto htm_info_buf_err;
}
/* Debugfs interface file to present HTM capabilities */
htm_caps_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!htm_caps_buf) {
pr_err("Failed to allocate htm caps buf\n");
- return -ENOMEM;
+ goto htm_caps_buf_err;
}
/* Memory to present HTM system memory configuration */
htm_mem_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!htm_mem_buf) {
pr_err("Failed to allocate htm mem buf\n");
- return -ENOMEM;
+ goto htm_mem_buf_err;
}
debugfs_create_file("htmstatus", 0400, htmdump_debugfs_dir, htm_status_buf, &htmstatus_fops);
@@ -557,6 +557,17 @@ static int htmdump_init_debugfs(void)
debugfs_create_file("htmsystem_mem", 0400, htmdump_debugfs_dir, htm_mem_buf, &htmsystem_mem_fops);
return 0;
+
+htm_mem_buf_err:
+ kfree(htm_caps_buf);
+htm_caps_buf_err:
+ kfree(htm_info_buf);
+htm_info_buf_err:
+ kfree(htm_status_buf);
+htm_status_buf_err:
+ debugfs_remove_recursive(htmdump_debugfs_dir);
+ kfree(htm_buf);
+ return -ENOMEM;
}
static int __init htmdump_init(void)
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index f8e26c4bed2b..d6c2dbf8455c 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -326,7 +326,7 @@ config STACKTRACE_SUPPORT
config GENERIC_BUG
def_bool y
depends on BUG
- select GENERIC_BUG_RELATIVE_POINTERS if 64BIT
+ select GENERIC_BUG_RELATIVE_POINTERS
config GENERIC_BUG_RELATIVE_POINTERS
bool
diff --git a/arch/riscv/include/asm/bug.h b/arch/riscv/include/asm/bug.h
index 6f581b84d8fc..699c0cf3e4ef 100644
--- a/arch/riscv/include/asm/bug.h
+++ b/arch/riscv/include/asm/bug.h
@@ -29,13 +29,8 @@
typedef u32 bug_insn_t;
-#ifdef CONFIG_GENERIC_BUG_RELATIVE_POINTERS
#define __BUG_ENTRY_ADDR RISCV_INT " 1b - ."
#define __BUG_ENTRY_FILE(file) RISCV_INT " " file " - ."
-#else
-#define __BUG_ENTRY_ADDR RISCV_PTR " 1b"
-#define __BUG_ENTRY_FILE(file) RISCV_PTR " " file
-#endif
#ifdef CONFIG_DEBUG_BUGVERBOSE
#define __BUG_ENTRY(file, line, flags) \
diff --git a/arch/riscv/include/asm/switch_to.h b/arch/riscv/include/asm/switch_to.h
index 04f10a949066..123c89b694e8 100644
--- a/arch/riscv/include/asm/switch_to.h
+++ b/arch/riscv/include/asm/switch_to.h
@@ -61,8 +61,8 @@ static inline void __switch_to_fpu(struct task_struct *prev,
static __always_inline bool has_fpu(void)
{
- return riscv_has_extension_likely(RISCV_ISA_EXT_F) ||
- riscv_has_extension_likely(RISCV_ISA_EXT_D);
+ /* D extension depends on F, so checking D alone is sufficient. */
+ return riscv_has_extension_likely(RISCV_ISA_EXT_D);
}
#else
static __always_inline bool has_fpu(void) { return false; }
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index d2ec96843456..61d21f714830 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -412,6 +412,19 @@ static const unsigned int riscv_zvbb_exts[] = {
RISCV_ISA_EXT_ZVKB
};
+/*
+ * The RISC-V ISA manual specifies that Zfh implies Zfhmin and Zvfh implies
+ * Zvfhmin. Report the implied subset extensions whenever the supersets are
+ * detected (see https://github.com/riscv/riscv-isa-manual/pull/3070).
+ */
+static const unsigned int riscv_zfh_exts[] = {
+ RISCV_ISA_EXT_ZFHMIN
+};
+
+static const unsigned int riscv_zvfh_exts[] = {
+ RISCV_ISA_EXT_ZVFHMIN
+};
+
#define RISCV_ISA_EXT_ZVE64F_IMPLY_LIST \
RISCV_ISA_EXT_ZVE64X, \
RISCV_ISA_EXT_ZVE32F, \
@@ -550,7 +563,8 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
__RISCV_ISA_EXT_DATA(zawrs, RISCV_ISA_EXT_ZAWRS),
__RISCV_ISA_EXT_DATA_VALIDATE(zfa, RISCV_ISA_EXT_ZFA, riscv_ext_f_depends),
__RISCV_ISA_EXT_DATA_VALIDATE(zfbfmin, RISCV_ISA_EXT_ZFBFMIN, riscv_ext_f_depends),
- __RISCV_ISA_EXT_DATA_VALIDATE(zfh, RISCV_ISA_EXT_ZFH, riscv_ext_f_depends),
+ __RISCV_ISA_EXT_SUPERSET_VALIDATE(zfh, RISCV_ISA_EXT_ZFH,
+ riscv_zfh_exts, riscv_ext_f_depends),
__RISCV_ISA_EXT_DATA_VALIDATE(zfhmin, RISCV_ISA_EXT_ZFHMIN, riscv_ext_f_depends),
__RISCV_ISA_EXT_DATA(zca, RISCV_ISA_EXT_ZCA),
__RISCV_ISA_EXT_DATA_VALIDATE(zcb, RISCV_ISA_EXT_ZCB, riscv_ext_zca_depends),
@@ -586,7 +600,9 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
__RISCV_ISA_EXT_SUPERSET_VALIDATE(zve64x, RISCV_ISA_EXT_ZVE64X, riscv_zve64x_exts, riscv_ext_vector_x_validate),
__RISCV_ISA_EXT_DATA_VALIDATE(zvfbfmin, RISCV_ISA_EXT_ZVFBFMIN, riscv_vector_f_validate),
__RISCV_ISA_EXT_DATA_VALIDATE(zvfbfwma, RISCV_ISA_EXT_ZVFBFWMA, riscv_ext_zvfbfwma_validate),
- __RISCV_ISA_EXT_DATA(zvfh, RISCV_ISA_EXT_ZVFH),
+ __RISCV_ISA_EXT_SUPERSET_VALIDATE(zvfh, RISCV_ISA_EXT_ZVFH,
+ riscv_zvfh_exts,
+ riscv_ext_vector_float_validate),
__RISCV_ISA_EXT_DATA(zvfhmin, RISCV_ISA_EXT_ZVFHMIN),
__RISCV_ISA_EXT_DATA_VALIDATE(zvkb, RISCV_ISA_EXT_ZVKB, riscv_ext_vector_crypto_validate),
__RISCV_ISA_EXT_DATA_VALIDATE(zvkg, RISCV_ISA_EXT_ZVKG, riscv_ext_vector_crypto_validate),
diff --git a/arch/riscv/kernel/patch.c b/arch/riscv/kernel/patch.c
index 16b243376f36..2239c28981bc 100644
--- a/arch/riscv/kernel/patch.c
+++ b/arch/riscv/kernel/patch.c
@@ -45,6 +45,8 @@ static __always_inline void *patch_map(void *addr, const unsigned int fixmap)
phys_addr_t phys;
if (core_kernel_text(uintaddr) || is_kernel_exittext(uintaddr)) {
+ if (!IS_ENABLED(CONFIG_STRICT_KERNEL_RWX))
+ return addr;
phys = __pa_symbol(addr);
} else if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX)) {
struct page *page = vmalloc_to_page(addr);
diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c
index b2df7f72241a..7cc5a6a5c020 100644
--- a/arch/riscv/kernel/process.c
+++ b/arch/riscv/kernel/process.c
@@ -349,10 +349,8 @@ long set_tagged_addr_ctrl(struct task_struct *task, unsigned long arg)
if (arg & PR_TAGGED_ADDR_ENABLE && (tagged_addr_disabled || !pmlen))
return -EINVAL;
- if (!(arg & PR_TAGGED_ADDR_ENABLE)) {
+ if (!(arg & PR_TAGGED_ADDR_ENABLE))
pmlen = PMLEN_0;
- pmm = ENVCFG_PMM_PMLEN_0;
- }
if (mmap_write_lock_killable(mm))
return -EINTR;
diff --git a/arch/riscv/kernel/sys_hwprobe.c b/arch/riscv/kernel/sys_hwprobe.c
index bd6ca7d769da..7818e1d32622 100644
--- a/arch/riscv/kernel/sys_hwprobe.c
+++ b/arch/riscv/kernel/sys_hwprobe.c
@@ -297,6 +297,8 @@ static u64 hwprobe_vec_misaligned(const struct cpumask *cpus)
static void hwprobe_one_pair(struct riscv_hwprobe *pair,
const struct cpumask *cpus)
{
+ pair->value = 0;
+
switch (pair->key) {
case RISCV_HWPROBE_KEY_MVENDORID:
case RISCV_HWPROBE_KEY_MARCHID:
@@ -331,17 +333,14 @@ static void hwprobe_one_pair(struct riscv_hwprobe *pair,
break;
case RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE:
- pair->value = 0;
if (hwprobe_ext0_has(cpus, RISCV_HWPROBE_EXT_ZICBOZ))
pair->value = riscv_cboz_block_size;
break;
case RISCV_HWPROBE_KEY_ZICBOM_BLOCK_SIZE:
- pair->value = 0;
if (hwprobe_ext0_has(cpus, RISCV_HWPROBE_EXT_ZICBOM))
pair->value = riscv_cbom_block_size;
break;
case RISCV_HWPROBE_KEY_ZICBOP_BLOCK_SIZE:
- pair->value = 0;
if (hwprobe_ext0_has(cpus, RISCV_HWPROBE_EXT_ZICBOP))
pair->value = riscv_cbop_block_size;
break;
diff --git a/arch/riscv/kernel/usercfi.c b/arch/riscv/kernel/usercfi.c
index f027e6e05251..dec0ba5eff5e 100644
--- a/arch/riscv/kernel/usercfi.c
+++ b/arch/riscv/kernel/usercfi.c
@@ -525,9 +525,8 @@ static int __init setup_global_riscv_enable(char *str)
if (riscv_nousercfi)
pr_info("RISC-V user CFI disabled via cmdline - shadow stack status : %s, landing pad status : %s\n",
- (riscv_nousercfi & CMDLINE_DISABLE_RISCV_USERCFI_BCFI) ? "disabled" :
- "enabled", (riscv_nousercfi & CMDLINE_DISABLE_RISCV_USERCFI_FCFI) ?
- "disabled" : "enabled");
+ str_disabled_enabled(riscv_nousercfi & CMDLINE_DISABLE_RISCV_USERCFI_BCFI),
+ str_disabled_enabled(riscv_nousercfi & CMDLINE_DISABLE_RISCV_USERCFI_FCFI));
return 1;
}
diff --git a/arch/riscv/lib/uaccess.S b/arch/riscv/lib/uaccess.S
index 4efea1b3326c..cf8586a937de 100644
--- a/arch/riscv/lib/uaccess.S
+++ b/arch/riscv/lib/uaccess.S
@@ -76,6 +76,7 @@ SYM_FUNC_START(fallback_scalar_usercopy_sum_enabled)
li a3, 9*SZREG-1 /* size must >= (word_copy stride + SZREG-1) */
bltu a2, a3, .Lbyte_copy_tail
+#if !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
/*
* Copy first bytes until dst is aligned to word boundary.
* a0 - start of dst
@@ -103,7 +104,7 @@ SYM_FUNC_START(fallback_scalar_usercopy_sum_enabled)
/* a1 - start of src */
andi a3, a1, SZREG-1
bnez a3, .Lshift_copy
-
+#endif
.Lword_copy:
/*
* Both src and dst are aligned, unrolled word copy
@@ -137,6 +138,7 @@ SYM_FUNC_START(fallback_scalar_usercopy_sum_enabled)
addi t0, t0, 8*SZREG /* revert to original value */
j .Lbyte_copy_tail
+#if !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
.Lshift_copy:
/*
@@ -189,6 +191,7 @@ SYM_FUNC_START(fallback_scalar_usercopy_sum_enabled)
/* Revert src to original unaligned value */
add a1, a1, a3
+#endif
.Lbyte_copy_tail:
/*
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index f8994caefc70..fb37b0b67efe 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -1465,7 +1465,9 @@ struct execmem_info __init *execmem_arch_setup(void)
[EXECMEM_KPROBES] = {
.start = VMALLOC_START,
.end = VMALLOC_END,
- .pgprot = PAGE_KERNEL_READ_EXEC,
+ .pgprot = IS_ENABLED(CONFIG_STRICT_MODULE_RWX) ?
+ PAGE_KERNEL_READ_EXEC :
+ PAGE_KERNEL_EXEC,
.alignment = 1,
},
[EXECMEM_BPF] = {
diff --git a/arch/s390/crypto/Makefile b/arch/s390/crypto/Makefile
index 48aeb0c0ffbd..1d6420813935 100644
--- a/arch/s390/crypto/Makefile
+++ b/arch/s390/crypto/Makefile
@@ -3,6 +3,8 @@
# Cryptographic API
#
+CONTEXT_ANALYSIS := y
+
obj-$(CONFIG_CRYPTO_AES_S390) += aes_s390.o
obj-$(CONFIG_CRYPTO_PAES_S390) += paes_s390.o
obj-$(CONFIG_S390_PRNG) += prng.o
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
index 62edc66d5478..0be6fa779d2c 100644
--- a/arch/s390/crypto/aes_s390.c
+++ b/arch/s390/crypto/aes_s390.c
@@ -26,14 +26,14 @@
#include <linux/module.h>
#include <linux/cpufeature.h>
#include <linux/init.h>
-#include <linux/mutex.h>
#include <linux/fips.h>
+#include <linux/semaphore.h>
#include <linux/string.h>
#include <crypto/xts.h>
#include <asm/cpacf.h>
static u8 *ctrblk;
-static DEFINE_MUTEX(ctrblk_lock);
+static DEFINE_SEMAPHORE(ctrblk_sem, 1);
static cpacf_mask_t km_functions, kmc_functions, kmctr_functions,
kma_functions;
@@ -129,7 +129,7 @@ static int ecb_aes_crypt(struct skcipher_request *req, unsigned long modifier)
return fallback_skcipher_crypt(sctx, req, modifier);
ret = skcipher_walk_virt(&walk, req, false);
- while ((nbytes = walk.nbytes) != 0) {
+ while (!ret && ((nbytes = walk.nbytes) != 0)) {
/* only use complete blocks */
n = nbytes & ~(AES_BLOCK_SIZE - 1);
cpacf_km(sctx->fc | modifier, sctx->key,
@@ -233,7 +233,7 @@ static int cbc_aes_crypt(struct skcipher_request *req, unsigned long modifier)
return ret;
memcpy(param.iv, walk.iv, AES_BLOCK_SIZE);
memcpy(param.key, sctx->key, sctx->key_len);
- while ((nbytes = walk.nbytes) != 0) {
+ while (!ret && ((nbytes = walk.nbytes) != 0)) {
/* only use complete blocks */
n = nbytes & ~(AES_BLOCK_SIZE - 1);
cpacf_kmc(sctx->fc | modifier, &param,
@@ -359,7 +359,7 @@ static int xts_aes_crypt(struct skcipher_request *req, unsigned long modifier)
memcpy(xts_param.key + offset, xts_ctx->key, xts_ctx->key_len);
memcpy(xts_param.init, pcc_param.xts, 16);
- while ((nbytes = walk.nbytes) != 0) {
+ while (!ret && ((nbytes = walk.nbytes) != 0)) {
/* only use complete blocks */
n = nbytes & ~(AES_BLOCK_SIZE - 1);
cpacf_km(xts_ctx->fc | modifier, xts_param.key + offset,
@@ -487,7 +487,7 @@ static int fullxts_aes_crypt(struct skcipher_request *req, unsigned long modifi
memcpy(fxts_param.tweak, req->iv, AES_BLOCK_SIZE);
fxts_param.nap[0] = 0x01; /* initial alpha power (1, little-endian) */
- while ((nbytes = walk.nbytes) != 0) {
+ while (!ret && ((nbytes = walk.nbytes) != 0)) {
/* only use complete blocks */
n = nbytes & ~(AES_BLOCK_SIZE - 1);
cpacf_km(xts_ctx->fc | modifier, fxts_param.key + offset,
@@ -562,48 +562,64 @@ static unsigned int __ctrblk_init(u8 *ctrptr, u8 *iv, unsigned int nbytes)
return n;
}
+static int __ctr_aes_crypt(struct s390_aes_ctx *sctx,
+ struct skcipher_walk *walk, bool locked)
+{
+ unsigned int n, nbytes;
+ int ret = 0;
+ u8 *ctrptr;
+
+ while (!ret && ((nbytes = walk->nbytes) >= AES_BLOCK_SIZE)) {
+ n = AES_BLOCK_SIZE;
+ if (nbytes >= 2 * AES_BLOCK_SIZE && locked)
+ n = __ctrblk_init(ctrblk, walk->iv, nbytes);
+ ctrptr = (n > AES_BLOCK_SIZE) ? ctrblk : walk->iv;
+ cpacf_kmctr(sctx->fc, sctx->key, walk->dst.virt.addr,
+ walk->src.virt.addr, n, ctrptr);
+ if (ctrptr == ctrblk)
+ memcpy(walk->iv, ctrptr + n - AES_BLOCK_SIZE,
+ AES_BLOCK_SIZE);
+ crypto_inc(walk->iv, AES_BLOCK_SIZE);
+ ret = skcipher_walk_done(walk, nbytes - n);
+ }
+
+ return ret;
+}
+
static int ctr_aes_crypt(struct skcipher_request *req)
{
struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
struct s390_aes_ctx *sctx = crypto_skcipher_ctx(tfm);
- u8 buf[AES_BLOCK_SIZE], *ctrptr;
struct skcipher_walk walk;
- unsigned int n, nbytes;
- int ret, locked;
+ u8 buf[AES_BLOCK_SIZE];
+ int ret;
if (unlikely(!sctx->fc))
return fallback_skcipher_crypt(sctx, req, 0);
- locked = mutex_trylock(&ctrblk_lock);
-
ret = skcipher_walk_virt(&walk, req, false);
- while ((nbytes = walk.nbytes) >= AES_BLOCK_SIZE) {
- n = AES_BLOCK_SIZE;
+ if (ret)
+ return ret;
- if (nbytes >= 2*AES_BLOCK_SIZE && locked)
- n = __ctrblk_init(ctrblk, walk.iv, nbytes);
- ctrptr = (n > AES_BLOCK_SIZE) ? ctrblk : walk.iv;
- cpacf_kmctr(sctx->fc, sctx->key, walk.dst.virt.addr,
- walk.src.virt.addr, n, ctrptr);
- if (ctrptr == ctrblk)
- memcpy(walk.iv, ctrptr + n - AES_BLOCK_SIZE,
- AES_BLOCK_SIZE);
- crypto_inc(walk.iv, AES_BLOCK_SIZE);
- ret = skcipher_walk_done(&walk, nbytes - n);
+ if (down_trylock(&ctrblk_sem) == 0) {
+ ret = __ctr_aes_crypt(sctx, &walk, true);
+ up(&ctrblk_sem);
+ } else {
+ ret = __ctr_aes_crypt(sctx, &walk, false);
}
- if (locked)
- mutex_unlock(&ctrblk_lock);
+
/*
* final block may be < AES_BLOCK_SIZE, copy only nbytes
*/
- if (nbytes) {
+ if (!ret && walk.nbytes > 0) {
memset(buf, 0, AES_BLOCK_SIZE);
- memcpy(buf, walk.src.virt.addr, nbytes);
+ memcpy(buf, walk.src.virt.addr, walk.nbytes);
cpacf_kmctr(sctx->fc, sctx->key, buf, buf,
AES_BLOCK_SIZE, walk.iv);
- memcpy(walk.dst.virt.addr, buf, nbytes);
+ memcpy(walk.dst.virt.addr, buf, walk.nbytes);
crypto_inc(walk.iv, AES_BLOCK_SIZE);
ret = skcipher_walk_done(&walk, 0);
+ memzero_explicit(buf, sizeof(buf));
}
return ret;
@@ -895,10 +911,14 @@ static int gcm_aes_crypt(struct aead_request *req, unsigned int flags)
gw_in.ptr, aad_bytes);
n = aad_bytes + pc_bytes;
- if (gcm_in_walk_done(&gw_in, n) != n)
- return -ENOMEM;
- if (gcm_out_walk_done(&gw_out, n) != n)
- return -ENOMEM;
+ if (gcm_in_walk_done(&gw_in, n) != n) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ if (gcm_out_walk_done(&gw_out, n) != n) {
+ ret = -ENOMEM;
+ goto out;
+ }
aadlen -= aad_bytes;
pclen -= pc_bytes;
} while (aadlen + pclen > 0);
@@ -910,7 +930,10 @@ static int gcm_aes_crypt(struct aead_request *req, unsigned int flags)
} else
scatterwalk_map_and_copy(param.t, req->dst, len, taglen, 1);
+out:
memzero_explicit(&param, sizeof(param));
+ memzero_explicit(gw_in.buf, sizeof(gw_in.buf));
+ memzero_explicit(gw_out.buf, sizeof(gw_out.buf));
return ret;
}
diff --git a/arch/s390/crypto/paes_s390.c b/arch/s390/crypto/paes_s390.c
index 973436592318..f987bcbe8f35 100644
--- a/arch/s390/crypto/paes_s390.c
+++ b/arch/s390/crypto/paes_s390.c
@@ -19,7 +19,7 @@
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
-#include <linux/mutex.h>
+#include <linux/semaphore.h>
#include <linux/spinlock.h>
#include <crypto/aes.h>
#include <crypto/algapi.h>
@@ -45,7 +45,7 @@ module_param_named(clrkey, pkey_clrkey_allowed, bool, 0444);
MODULE_PARM_DESC(clrkey, "Allow clear key material (default N)");
static u8 *ctrblk;
-static DEFINE_MUTEX(ctrblk_lock);
+static DEFINE_SEMAPHORE(ctrblk_sem, 1);
static cpacf_mask_t km_functions, kmc_functions, kmctr_functions;
@@ -220,6 +220,10 @@ static inline int convert_key(const u8 *key, unsigned int keylen,
xflags);
}
+ /* But finally map -EBUSY to -EIO to indicate an IO failure */
+ if (rc == -EBUSY)
+ rc = -EIO;
+
out:
pr_debug("rc=%d\n", rc);
return rc;
@@ -432,8 +436,11 @@ static int ecb_paes_do_crypt(struct s390_paes_ctx *ctx,
n = nbytes & ~(AES_BLOCK_SIZE - 1);
k = cpacf_km(ctx->fc | req_ctx->modifier, param,
walk->dst.virt.addr, walk->src.virt.addr, n);
- if (k)
+ if (k) {
rc = skcipher_walk_done(walk, nbytes - k);
+ if (rc)
+ goto out;
+ }
if (k < n) {
if (!maysleep) {
rc = -EKEYEXPIRED;
@@ -460,6 +467,7 @@ static int ecb_paes_crypt(struct skcipher_request *req, unsigned long modifier)
struct s390_paes_ctx *ctx = crypto_skcipher_ctx(tfm);
struct skcipher_walk *walk = &req_ctx->walk;
bool tested = crypto_skcipher_tested(tfm);
+ bool cleanup = true;
int rc;
/*
@@ -491,15 +499,17 @@ static int ecb_paes_crypt(struct skcipher_request *req, unsigned long modifier)
if (rc == 0 || rc == -EKEYEXPIRED) {
atomic_inc(&ctx->via_engine_ctr);
rc = crypto_transfer_skcipher_request_to_engine(paes_crypto_engine, req);
- if (rc != -EINPROGRESS)
+ if (rc == -EINPROGRESS || rc == -EBUSY)
+ cleanup = false;
+ else
atomic_dec(&ctx->via_engine_ctr);
}
- if (rc != -EINPROGRESS)
+ if (cleanup && walk->nbytes)
skcipher_walk_done(walk, rc);
out:
- if (rc != -EINPROGRESS)
+ if (cleanup)
memzero_explicit(&req_ctx->param, sizeof(req_ctx->param));
pr_debug("rc=%d\n", rc);
return rc;
@@ -549,7 +559,7 @@ static int ecb_paes_do_one_request(struct crypto_engine *engine, void *areq)
rc = ecb_paes_do_crypt(ctx, req_ctx, tested, true);
if (rc == -EKEYEXPIRED) {
return pkey_handle_expired();
- } else if (rc) {
+ } else if (rc && walk->nbytes) {
skcipher_walk_done(walk, rc);
}
@@ -559,7 +569,7 @@ static int ecb_paes_do_one_request(struct crypto_engine *engine, void *areq)
atomic_dec(&ctx->via_engine_ctr);
crypto_finalize_skcipher_request(engine, req, rc);
local_bh_enable();
- return rc;
+ return 0;
}
static struct skcipher_engine_alg ecb_paes_alg = {
@@ -567,6 +577,7 @@ static struct skcipher_engine_alg ecb_paes_alg = {
.base.cra_name = "ecb(paes)",
.base.cra_driver_name = "ecb-paes-s390",
.base.cra_priority = 401, /* combo: aes + ecb + 1 */
+ .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NO_FALLBACK,
.base.cra_blocksize = AES_BLOCK_SIZE,
.base.cra_ctxsize = sizeof(struct s390_paes_ctx),
.base.cra_module = THIS_MODULE,
@@ -690,6 +701,8 @@ static int cbc_paes_do_crypt(struct s390_paes_ctx *ctx,
if (k) {
memcpy(walk->iv, param->iv, AES_BLOCK_SIZE);
rc = skcipher_walk_done(walk, nbytes - k);
+ if (rc)
+ goto out;
}
if (k < n) {
if (!maysleep) {
@@ -717,6 +730,7 @@ static int cbc_paes_crypt(struct skcipher_request *req, unsigned long modifier)
struct s390_paes_ctx *ctx = crypto_skcipher_ctx(tfm);
struct skcipher_walk *walk = &req_ctx->walk;
bool tested = crypto_skcipher_tested(tfm);
+ bool cleanup = true;
int rc;
/*
@@ -748,15 +762,17 @@ static int cbc_paes_crypt(struct skcipher_request *req, unsigned long modifier)
if (rc == 0 || rc == -EKEYEXPIRED) {
atomic_inc(&ctx->via_engine_ctr);
rc = crypto_transfer_skcipher_request_to_engine(paes_crypto_engine, req);
- if (rc != -EINPROGRESS)
+ if (rc == -EINPROGRESS || rc == -EBUSY)
+ cleanup = false;
+ else
atomic_dec(&ctx->via_engine_ctr);
}
- if (rc != -EINPROGRESS)
+ if (cleanup && walk->nbytes)
skcipher_walk_done(walk, rc);
out:
- if (rc != -EINPROGRESS)
+ if (cleanup)
memzero_explicit(&req_ctx->param, sizeof(req_ctx->param));
pr_debug("rc=%d\n", rc);
return rc;
@@ -806,7 +822,7 @@ static int cbc_paes_do_one_request(struct crypto_engine *engine, void *areq)
rc = cbc_paes_do_crypt(ctx, req_ctx, tested, true);
if (rc == -EKEYEXPIRED) {
return pkey_handle_expired();
- } else if (rc) {
+ } else if (rc && walk->nbytes) {
skcipher_walk_done(walk, rc);
}
@@ -816,7 +832,7 @@ static int cbc_paes_do_one_request(struct crypto_engine *engine, void *areq)
atomic_dec(&ctx->via_engine_ctr);
crypto_finalize_skcipher_request(engine, req, rc);
local_bh_enable();
- return rc;
+ return 0;
}
static struct skcipher_engine_alg cbc_paes_alg = {
@@ -824,6 +840,7 @@ static struct skcipher_engine_alg cbc_paes_alg = {
.base.cra_name = "cbc(paes)",
.base.cra_driver_name = "cbc-paes-s390",
.base.cra_priority = 402, /* cbc-paes-s390 + 1 */
+ .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NO_FALLBACK,
.base.cra_blocksize = AES_BLOCK_SIZE,
.base.cra_ctxsize = sizeof(struct s390_paes_ctx),
.base.cra_module = THIS_MODULE,
@@ -914,41 +931,14 @@ static inline unsigned int __ctrblk_init(u8 *ctrptr, u8 *iv, unsigned int nbytes
return n;
}
-static int ctr_paes_do_crypt(struct s390_paes_ctx *ctx,
- struct s390_pctr_req_ctx *req_ctx,
- bool tested, bool maysleep)
+static int __ctr_paes_do_crypt(struct s390_paes_ctx *ctx,
+ struct ctr_param *param,
+ struct skcipher_walk *walk,
+ bool tested, bool maysleep, bool locked)
{
- struct ctr_param *param = &req_ctx->param;
- struct skcipher_walk *walk = &req_ctx->walk;
- u8 buf[AES_BLOCK_SIZE], *ctrptr;
unsigned int nbytes, n, k;
- int pk_state, locked, rc = 0;
-
- if (!req_ctx->param_init_done) {
- /* fetch and check protected key state */
- spin_lock_bh(&ctx->pk_lock);
- pk_state = ctx->pk_state;
- switch (pk_state) {
- case PK_STATE_NO_KEY:
- rc = -ENOKEY;
- break;
- case PK_STATE_CONVERT_IN_PROGRESS:
- rc = -EKEYEXPIRED;
- break;
- case PK_STATE_VALID:
- memcpy(param->key, ctx->pk.protkey, sizeof(param->key));
- req_ctx->param_init_done = true;
- break;
- default:
- rc = pk_state < 0 ? pk_state : -EIO;
- break;
- }
- spin_unlock_bh(&ctx->pk_lock);
- }
- if (rc)
- goto out;
-
- locked = mutex_trylock(&ctrblk_lock);
+ u8 *ctrptr;
+ int rc = 0;
/*
* Note that in case of partial processing or failure the walk
@@ -968,32 +958,71 @@ static int ctr_paes_do_crypt(struct s390_paes_ctx *ctx,
AES_BLOCK_SIZE);
crypto_inc(walk->iv, AES_BLOCK_SIZE);
rc = skcipher_walk_done(walk, nbytes - k);
+ if (rc)
+ goto out;
}
if (k < n) {
if (!maysleep) {
- if (locked)
- mutex_unlock(&ctrblk_lock);
rc = -EKEYEXPIRED;
goto out;
}
rc = paes_convert_key(ctx, tested);
- if (rc) {
- if (locked)
- mutex_unlock(&ctrblk_lock);
+ if (rc)
goto out;
- }
spin_lock_bh(&ctx->pk_lock);
memcpy(param->key, ctx->pk.protkey, sizeof(param->key));
spin_unlock_bh(&ctx->pk_lock);
}
}
- if (locked)
- mutex_unlock(&ctrblk_lock);
+
+out:
+ return rc;
+}
+
+static int ctr_paes_do_crypt(struct s390_paes_ctx *ctx,
+ struct s390_pctr_req_ctx *req_ctx,
+ bool tested, bool maysleep)
+{
+ struct ctr_param *param = &req_ctx->param;
+ struct skcipher_walk *walk = &req_ctx->walk;
+ u8 buf[AES_BLOCK_SIZE];
+ int pk_state, rc = 0;
+
+ if (!req_ctx->param_init_done) {
+ /* fetch and check protected key state */
+ spin_lock_bh(&ctx->pk_lock);
+ pk_state = ctx->pk_state;
+ switch (pk_state) {
+ case PK_STATE_NO_KEY:
+ rc = -ENOKEY;
+ break;
+ case PK_STATE_CONVERT_IN_PROGRESS:
+ rc = -EKEYEXPIRED;
+ break;
+ case PK_STATE_VALID:
+ memcpy(param->key, ctx->pk.protkey, sizeof(param->key));
+ req_ctx->param_init_done = true;
+ break;
+ default:
+ rc = pk_state < 0 ? pk_state : -EIO;
+ break;
+ }
+ spin_unlock_bh(&ctx->pk_lock);
+ }
+ if (rc)
+ goto out;
+
+ if (down_trylock(&ctrblk_sem) == 0) {
+ rc = __ctr_paes_do_crypt(ctx, param, walk, tested, maysleep, true);
+ up(&ctrblk_sem);
+ } else {
+ rc = __ctr_paes_do_crypt(ctx, param, walk, tested, maysleep, false);
+ }
/* final block may be < AES_BLOCK_SIZE, copy only nbytes */
- if (nbytes) {
+ if (!rc && walk->nbytes > 0) {
memset(buf, 0, AES_BLOCK_SIZE);
- memcpy(buf, walk->src.virt.addr, nbytes);
+ memcpy(buf, walk->src.virt.addr, walk->nbytes);
while (1) {
if (cpacf_kmctr(ctx->fc, param, buf,
buf, AES_BLOCK_SIZE,
@@ -1010,12 +1039,13 @@ static int ctr_paes_do_crypt(struct s390_paes_ctx *ctx,
memcpy(param->key, ctx->pk.protkey, sizeof(param->key));
spin_unlock_bh(&ctx->pk_lock);
}
- memcpy(walk->dst.virt.addr, buf, nbytes);
+ memcpy(walk->dst.virt.addr, buf, walk->nbytes);
crypto_inc(walk->iv, AES_BLOCK_SIZE);
rc = skcipher_walk_done(walk, 0);
}
out:
+ memzero_explicit(buf, sizeof(buf));
pr_debug("rc=%d\n", rc);
return rc;
}
@@ -1027,6 +1057,7 @@ static int ctr_paes_crypt(struct skcipher_request *req)
struct s390_paes_ctx *ctx = crypto_skcipher_ctx(tfm);
struct skcipher_walk *walk = &req_ctx->walk;
bool tested = crypto_skcipher_tested(tfm);
+ bool cleanup = true;
int rc;
/*
@@ -1057,15 +1088,17 @@ static int ctr_paes_crypt(struct skcipher_request *req)
if (rc == 0 || rc == -EKEYEXPIRED) {
atomic_inc(&ctx->via_engine_ctr);
rc = crypto_transfer_skcipher_request_to_engine(paes_crypto_engine, req);
- if (rc != -EINPROGRESS)
+ if (rc == -EINPROGRESS || rc == -EBUSY)
+ cleanup = false;
+ else
atomic_dec(&ctx->via_engine_ctr);
}
- if (rc != -EINPROGRESS)
+ if (cleanup && walk->nbytes)
skcipher_walk_done(walk, rc);
out:
- if (rc != -EINPROGRESS)
+ if (cleanup)
memzero_explicit(&req_ctx->param, sizeof(req_ctx->param));
pr_debug("rc=%d\n", rc);
return rc;
@@ -1105,7 +1138,7 @@ static int ctr_paes_do_one_request(struct crypto_engine *engine, void *areq)
rc = ctr_paes_do_crypt(ctx, req_ctx, tested, true);
if (rc == -EKEYEXPIRED) {
return pkey_handle_expired();
- } else if (rc) {
+ } else if (rc && walk->nbytes) {
skcipher_walk_done(walk, rc);
}
@@ -1115,7 +1148,7 @@ static int ctr_paes_do_one_request(struct crypto_engine *engine, void *areq)
atomic_dec(&ctx->via_engine_ctr);
crypto_finalize_skcipher_request(engine, req, rc);
local_bh_enable();
- return rc;
+ return 0;
}
static struct skcipher_engine_alg ctr_paes_alg = {
@@ -1123,6 +1156,7 @@ static struct skcipher_engine_alg ctr_paes_alg = {
.base.cra_name = "ctr(paes)",
.base.cra_driver_name = "ctr-paes-s390",
.base.cra_priority = 402, /* ecb-paes-s390 + 1 */
+ .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NO_FALLBACK,
.base.cra_blocksize = 1,
.base.cra_ctxsize = sizeof(struct s390_paes_ctx),
.base.cra_module = THIS_MODULE,
@@ -1283,8 +1317,11 @@ static int xts_paes_do_crypt_fullkey(struct s390_pxts_ctx *ctx,
n = nbytes & ~(AES_BLOCK_SIZE - 1);
k = cpacf_km(ctx->fc | req_ctx->modifier, param->key + offset,
walk->dst.virt.addr, walk->src.virt.addr, n);
- if (k)
+ if (k) {
rc = skcipher_walk_done(walk, nbytes - k);
+ if (rc)
+ goto out;
+ }
if (k < n) {
if (!maysleep) {
rc = -EKEYEXPIRED;
@@ -1337,7 +1374,7 @@ static inline int __xts_2keys_prep_param(struct s390_pxts_ctx *ctx,
memcpy(param->init, pcc_param.xts, 16);
}
- memzero_explicit(pcc_param.key, sizeof(pcc_param.key));
+ memzero_explicit(&pcc_param, sizeof(pcc_param));
return rc;
}
@@ -1377,8 +1414,11 @@ static int xts_paes_do_crypt_2keys(struct s390_pxts_ctx *ctx,
n = nbytes & ~(AES_BLOCK_SIZE - 1);
k = cpacf_km(ctx->fc | req_ctx->modifier, param->key + offset,
walk->dst.virt.addr, walk->src.virt.addr, n);
- if (k)
+ if (k) {
rc = skcipher_walk_done(walk, nbytes - k);
+ if (rc)
+ goto out;
+ }
if (k < n) {
if (!maysleep) {
rc = -EKEYEXPIRED;
@@ -1450,6 +1490,7 @@ static inline int xts_paes_crypt(struct skcipher_request *req, unsigned long mod
struct s390_pxts_ctx *ctx = crypto_skcipher_ctx(tfm);
struct skcipher_walk *walk = &req_ctx->walk;
bool tested = crypto_skcipher_tested(tfm);
+ bool cleanup = true;
int rc;
/*
@@ -1481,15 +1522,17 @@ static inline int xts_paes_crypt(struct skcipher_request *req, unsigned long mod
if (rc == 0 || rc == -EKEYEXPIRED) {
atomic_inc(&ctx->via_engine_ctr);
rc = crypto_transfer_skcipher_request_to_engine(paes_crypto_engine, req);
- if (rc != -EINPROGRESS)
+ if (rc == -EINPROGRESS || rc == -EBUSY)
+ cleanup = false;
+ else
atomic_dec(&ctx->via_engine_ctr);
}
- if (rc != -EINPROGRESS)
+ if (cleanup && walk->nbytes)
skcipher_walk_done(walk, rc);
out:
- if (rc != -EINPROGRESS)
+ if (cleanup)
memzero_explicit(&req_ctx->param, sizeof(req_ctx->param));
pr_debug("rc=%d\n", rc);
return rc;
@@ -1539,7 +1582,7 @@ static int xts_paes_do_one_request(struct crypto_engine *engine, void *areq)
rc = xts_paes_do_crypt(ctx, req_ctx, tested, true);
if (rc == -EKEYEXPIRED) {
return pkey_handle_expired();
- } else if (rc) {
+ } else if (rc && walk->nbytes) {
skcipher_walk_done(walk, rc);
}
@@ -1549,7 +1592,7 @@ static int xts_paes_do_one_request(struct crypto_engine *engine, void *areq)
atomic_dec(&ctx->via_engine_ctr);
crypto_finalize_skcipher_request(engine, req, rc);
local_bh_enable();
- return rc;
+ return 0;
}
static struct skcipher_engine_alg xts_paes_alg = {
@@ -1557,6 +1600,7 @@ static struct skcipher_engine_alg xts_paes_alg = {
.base.cra_name = "xts(paes)",
.base.cra_driver_name = "xts-paes-s390",
.base.cra_priority = 402, /* ecb-paes-s390 + 1 */
+ .base.cra_flags = CRYPTO_ALG_ASYNC | CRYPTO_ALG_NO_FALLBACK,
.base.cra_blocksize = AES_BLOCK_SIZE,
.base.cra_ctxsize = sizeof(struct s390_pxts_ctx),
.base.cra_module = THIS_MODULE,
diff --git a/arch/s390/crypto/phmac_s390.c b/arch/s390/crypto/phmac_s390.c
index 020a1beb2e22..bbf8a6809ecb 100644
--- a/arch/s390/crypto/phmac_s390.c
+++ b/arch/s390/crypto/phmac_s390.c
@@ -62,8 +62,10 @@ static inline int hwh_prepare(struct ahash_request *req,
*/
static inline int hwh_advance(struct hash_walk_helper *hwh, int n)
{
- if (n < 0)
+ if (n < 0) {
+ hwh->walkbytes = n;
return crypto_hash_walk_done(&hwh->walk, n);
+ }
hwh->walkbytes -= n;
hwh->walkaddr += n;
@@ -339,6 +341,10 @@ static inline int convert_key(const u8 *key, unsigned int keylen,
xflags);
}
+ /* But finally map -EBUSY to -EIO to indicate an IO failure */
+ if (rc == -EBUSY)
+ rc = -EIO;
+
out:
pr_debug("rc=%d\n", rc);
return rc;
@@ -606,6 +612,7 @@ static int phmac_update(struct ahash_request *req)
struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
struct kmac_sha2_ctx *kmac_ctx = &req_ctx->kmac_ctx;
struct hash_walk_helper *hwh = &req_ctx->hwh;
+ bool cleanup = true;
int rc;
/* prep the walk in the request context */
@@ -629,12 +636,15 @@ static int phmac_update(struct ahash_request *req)
req_ctx->async_op = OP_UPDATE;
atomic_inc(&tfm_ctx->via_engine_ctr);
rc = crypto_transfer_hash_request_to_engine(phmac_crypto_engine, req);
- if (rc != -EINPROGRESS)
+ if (rc == -EINPROGRESS || rc == -EBUSY)
+ cleanup = false;
+ else
atomic_dec(&tfm_ctx->via_engine_ctr);
}
- if (rc != -EINPROGRESS) {
- hwh_advance(hwh, rc);
+ if (cleanup) {
+ if (hwh->walkbytes > 0)
+ hwh_advance(hwh, rc);
memzero_explicit(kmac_ctx, sizeof(*kmac_ctx));
}
@@ -649,6 +659,7 @@ static int phmac_final(struct ahash_request *req)
struct crypto_ahash *tfm = crypto_ahash_reqtfm(req);
struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
struct kmac_sha2_ctx *kmac_ctx = &req_ctx->kmac_ctx;
+ bool cleanup = true;
int rc = 0;
/* Try synchronous operation if no active engine usage */
@@ -667,12 +678,14 @@ static int phmac_final(struct ahash_request *req)
req_ctx->async_op = OP_FINAL;
atomic_inc(&tfm_ctx->via_engine_ctr);
rc = crypto_transfer_hash_request_to_engine(phmac_crypto_engine, req);
- if (rc != -EINPROGRESS)
+ if (rc == -EINPROGRESS || rc == -EBUSY)
+ cleanup = false;
+ else
atomic_dec(&tfm_ctx->via_engine_ctr);
}
out:
- if (rc != -EINPROGRESS)
+ if (cleanup)
memzero_explicit(kmac_ctx, sizeof(*kmac_ctx));
pr_debug("rc=%d\n", rc);
return rc;
@@ -685,6 +698,7 @@ static int phmac_finup(struct ahash_request *req)
struct phmac_tfm_ctx *tfm_ctx = crypto_ahash_ctx(tfm);
struct kmac_sha2_ctx *kmac_ctx = &req_ctx->kmac_ctx;
struct hash_walk_helper *hwh = &req_ctx->hwh;
+ bool cleanup = true;
int rc;
/* prep the walk in the request context */
@@ -716,15 +730,17 @@ static int phmac_finup(struct ahash_request *req)
/* req->async_op has been set to either OP_FINUP or OP_FINAL */
atomic_inc(&tfm_ctx->via_engine_ctr);
rc = crypto_transfer_hash_request_to_engine(phmac_crypto_engine, req);
- if (rc != -EINPROGRESS)
+ if (rc == -EINPROGRESS || rc == -EBUSY)
+ cleanup = false;
+ else
atomic_dec(&tfm_ctx->via_engine_ctr);
}
- if (rc != -EINPROGRESS)
+ if (cleanup && hwh->walkbytes > 0)
hwh_advance(hwh, rc);
out:
- if (rc != -EINPROGRESS)
+ if (cleanup)
memzero_explicit(kmac_ctx, sizeof(*kmac_ctx));
pr_debug("rc=%d\n", rc);
return rc;
@@ -914,7 +930,7 @@ out:
atomic_dec(&tfm_ctx->via_engine_ctr);
crypto_finalize_hash_request(engine, req, rc);
local_bh_enable();
- return rc;
+ return 0;
}
#define S390_ASYNC_PHMAC_ALG(x) \
diff --git a/arch/s390/include/asm/pai.h b/arch/s390/include/asm/pai.h
index 534d0320e2aa..a3456a36aaa7 100644
--- a/arch/s390/include/asm/pai.h
+++ b/arch/s390/include/asm/pai.h
@@ -76,7 +76,6 @@ static __always_inline void pai_kernel_exit(struct pt_regs *regs)
}
#define PAI_SAVE_AREA(x) ((x)->hw.event_base)
-#define PAI_CPU_MASK(x) ((x)->hw.addr_filters)
#define PAI_PMU_IDX(x) ((x)->hw.last_tag)
#define PAI_SWLIST(x) (&(x)->hw.tp_list)
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index 14d2b58ad093..b5bf8284dbfc 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -182,7 +182,7 @@ static struct debug_param_t {
static int debug_param_num;
/* functions */
-static void debug_get_param(const char *name, int *level, int *pages)
+static void debug_get_param(const char *name, int *level, int *pages, bool quiet)
{
struct debug_param_t *p;
int i;
@@ -192,11 +192,13 @@ static void debug_get_param(const char *name, int *level, int *pages)
if (!glob_match(p->name, name))
continue;
if (level && p->level != PARAM_UNSET) {
- pr_info("%s: override level to %d\n", name, p->level);
+ if (!quiet)
+ pr_info("%s: override level to %d\n", name, p->level);
*level = p->level;
}
if (pages && p->pages != PARAM_UNSET) {
- pr_info("%s: override pages to %d\n", name, p->pages);
+ if (!quiet)
+ pr_info("%s: override pages to %d\n", name, p->pages);
*pages = p->pages;
}
}
@@ -251,7 +253,7 @@ static int __init s390dbf_parse(char *arg)
* regular memory allocations are possible.
*/
for (i = 0, id = __s390dbf_info; &id[i] < __s390dbf_info_end; i++)
- debug_get_param(id[i]->name, &id[i]->level, NULL);
+ debug_get_param(id[i]->name, &id[i]->level, NULL, false);
return rc;
}
@@ -395,7 +397,7 @@ static debug_info_t *debug_info_create(const char *name, int pages_per_area,
int level = DEBUG_DEFAULT_LEVEL;
debug_info_t *rc;
- debug_get_param(name, &level, &pages_per_area);
+ debug_get_param(name, &level, &pages_per_area, false);
rc = debug_info_alloc(name, pages_per_area, nr_areas, buf_size, level, ALL_AREAS);
if (!rc)
goto out;
@@ -960,7 +962,7 @@ void debug_register_static(debug_info_t *id, int pages_per_area, int nr_areas)
return;
}
- debug_get_param(id->name, &id->level, &pages_per_area);
+ debug_get_param(id->name, &id->level, &pages_per_area, false);
copy = debug_info_alloc("", pages_per_area, nr_areas, id->buf_size,
id->level, ALL_AREAS);
if (!copy) {
@@ -1074,9 +1076,6 @@ static void _debug_set_level(debug_info_t *id, int new_level)
{
unsigned long flags;
- if (!id)
- return;
-
if (new_level == DEBUG_OFF_LEVEL) {
pr_info("%s: switched off\n", id->name);
} else if ((new_level > DEBUG_MAX_LEVEL) || (new_level < 0)) {
@@ -1101,8 +1100,14 @@ static void _debug_set_level(debug_info_t *id, int new_level)
*/
void debug_set_level(debug_info_t *id, int new_level)
{
- /* Level specified via kernel parameter takes precedence */
- debug_get_param(id->name, &new_level, NULL);
+ if (!id)
+ return;
+
+ /*
+ * Level specified via kernel parameter takes precedence. The override
+ * was already announced during registration, so stay quiet here.
+ */
+ debug_get_param(id->name, &new_level, NULL, true);
_debug_set_level(id, new_level);
}
@@ -1278,7 +1283,7 @@ void debug_set_critical(void)
debug_entry_t *debug_event_common(debug_info_t *id, int level, const void *buf,
int len)
{
- debug_entry_t *active;
+ debug_entry_t *active = NULL;
unsigned long flags;
if (!debug_active || !id->areas)
@@ -1289,6 +1294,8 @@ debug_entry_t *debug_event_common(debug_info_t *id, int level, const void *buf,
} else {
raw_spin_lock_irqsave(&id->lock, flags);
}
+ if (!id->areas)
+ goto out;
do {
active = get_active_entry(id);
memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size));
@@ -1298,7 +1305,7 @@ debug_entry_t *debug_event_common(debug_info_t *id, int level, const void *buf,
len -= id->buf_size;
buf += id->buf_size;
} while (len > 0);
-
+out:
raw_spin_unlock_irqrestore(&id->lock, flags);
return active;
}
@@ -1311,7 +1318,7 @@ EXPORT_SYMBOL(debug_event_common);
debug_entry_t *debug_exception_common(debug_info_t *id, int level,
const void *buf, int len)
{
- debug_entry_t *active;
+ debug_entry_t *active = NULL;
unsigned long flags;
if (!debug_active || !id->areas)
@@ -1322,6 +1329,8 @@ debug_entry_t *debug_exception_common(debug_info_t *id, int level,
} else {
raw_spin_lock_irqsave(&id->lock, flags);
}
+ if (!id->areas)
+ goto out;
do {
active = get_active_entry(id);
memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size));
@@ -1331,7 +1340,7 @@ debug_entry_t *debug_exception_common(debug_info_t *id, int level,
len -= id->buf_size;
buf += id->buf_size;
} while (len > 0);
-
+out:
raw_spin_unlock_irqrestore(&id->lock, flags);
return active;
}
@@ -1357,7 +1366,7 @@ static inline int debug_count_numargs(char *string)
debug_entry_t *__debug_sprintf_event(debug_info_t *id, int level, char *string, ...)
{
debug_sprintf_entry_t *curr_event;
- debug_entry_t *active;
+ debug_entry_t *active = NULL;
unsigned long flags;
int numargs, idx;
va_list ap;
@@ -1372,6 +1381,8 @@ debug_entry_t *__debug_sprintf_event(debug_info_t *id, int level, char *string,
} else {
raw_spin_lock_irqsave(&id->lock, flags);
}
+ if (!id->areas)
+ goto out;
active = get_active_entry(id);
curr_event = (debug_sprintf_entry_t *) DEBUG_DATA(active);
va_start(ap, string);
@@ -1380,6 +1391,7 @@ debug_entry_t *__debug_sprintf_event(debug_info_t *id, int level, char *string,
curr_event->args[idx] = va_arg(ap, long);
va_end(ap);
debug_finish_entry(id, active, level, 0);
+out:
raw_spin_unlock_irqrestore(&id->lock, flags);
return active;
@@ -1392,7 +1404,7 @@ EXPORT_SYMBOL(__debug_sprintf_event);
debug_entry_t *__debug_sprintf_exception(debug_info_t *id, int level, char *string, ...)
{
debug_sprintf_entry_t *curr_event;
- debug_entry_t *active;
+ debug_entry_t *active = NULL;
unsigned long flags;
int numargs, idx;
va_list ap;
@@ -1408,6 +1420,8 @@ debug_entry_t *__debug_sprintf_exception(debug_info_t *id, int level, char *stri
} else {
raw_spin_lock_irqsave(&id->lock, flags);
}
+ if (!id->areas)
+ goto out;
active = get_active_entry(id);
curr_event = (debug_sprintf_entry_t *)DEBUG_DATA(active);
va_start(ap, string);
@@ -1416,6 +1430,7 @@ debug_entry_t *__debug_sprintf_exception(debug_info_t *id, int level, char *stri
curr_event->args[idx] = va_arg(ap, long);
va_end(ap);
debug_finish_entry(id, active, level, 1);
+out:
raw_spin_unlock_irqrestore(&id->lock, flags);
return active;
@@ -1658,9 +1673,11 @@ static void debug_flush(debug_info_t *id, int area)
unsigned long flags;
int i, j;
- if (!id || !id->areas)
+ if (!id)
return;
raw_spin_lock_irqsave(&id->lock, flags);
+ if (!id->areas)
+ goto out;
if (area == DEBUG_FLUSH_ALL) {
id->active_area = 0;
memset(id->active_entries, 0, id->nr_areas * sizeof(int));
@@ -1675,6 +1692,7 @@ static void debug_flush(debug_info_t *id, int area)
for (i = 0; i < id->pages_per_area; i++)
memset(id->areas[area][i], 0, PAGE_SIZE);
}
+out:
raw_spin_unlock_irqrestore(&id->lock, flags);
}
diff --git a/arch/s390/kernel/perf_pai.c b/arch/s390/kernel/perf_pai.c
index 5c18c8b82ab7..013c3dae21ec 100644
--- a/arch/s390/kernel/perf_pai.c
+++ b/arch/s390/kernel/perf_pai.c
@@ -67,6 +67,7 @@ struct pai_mapptr {
static struct pai_root { /* Anchor to per CPU data */
refcount_t refcnt; /* Overall active events */
+ atomic_t tskctx; /* Overall per-task events */
struct pai_mapptr __percpu *mapptr;
} pai_root[PAI_PMU_MAX];
@@ -93,14 +94,15 @@ struct pai_pmu { /* Define PAI PMU characteristics */
static struct pai_pmu pai_pmu[]; /* Forward declaration */
/* Free per CPU data when the last event is removed. */
-static void pai_root_free(int idx)
+static void pai_root_free(int idx, int tasks)
{
- if (refcount_dec_and_test(&pai_root[idx].refcnt)) {
+ if (refcount_sub_and_test(tasks, &pai_root[idx].refcnt)) {
free_percpu(pai_root[idx].mapptr);
pai_root[idx].mapptr = NULL;
}
- debug_sprintf_event(paidbg, 5, "%s root[%d].refcount %d\n", __func__,
- idx, refcount_read(&pai_root[idx].refcnt));
+ debug_sprintf_event(paidbg, 5, "%s root[%d].refcount %d tskctx %d\n",
+ __func__, idx, refcount_read(&pai_root[idx].refcnt),
+ atomic_read(&pai_root[idx].tskctx));
}
/*
@@ -137,40 +139,54 @@ static void pai_free(struct pai_mapptr *mp)
mp->mapptr = NULL;
}
-/* Adjust usage counters and remove allocated memory when all users are
- * gone.
- */
-static void pai_event_destroy_cpu(struct perf_event *event, int cpu)
+/* Called under mutex_lock */
+static void pai_event_destroy_cpu(int idx, int cpu, bool hotplug)
{
- int idx = PAI_PMU_IDX(event);
- struct pai_mapptr *mp = per_cpu_ptr(pai_root[idx].mapptr, cpu);
- struct pai_map *cpump = mp->mapptr;
+ struct pai_mapptr *mp;
+ struct pai_map *cpump;
+ int tasks = 1;
- mutex_lock(&pai_reserve_mutex);
- debug_sprintf_event(paidbg, 5, "%s event %#llx idx %d cpu %d users %d "
- "refcnt %u\n", __func__, event->attr.config, idx,
- event->cpu, cpump->active_events,
- refcount_read(&cpump->refcnt));
- if (refcount_dec_and_test(&cpump->refcnt))
+ /* Check reference count and return when all gone.
+ * 1. An event is installed on online CPU X.
+ * 2. CPU x is offlined and the per-CPU data is removed.
+ * 3. Event is destroyed via close system call.
+ */
+ if (!refcount_read(&pai_root[idx].refcnt))
+ return; /* No events at all */
+ mp = per_cpu_ptr(pai_root[idx].mapptr, cpu);
+ if (!mp || !mp->mapptr) /* No events on that CPU */
+ return;
+
+ /* When hotplug is true, invocation is from CPU hotplug callback.
+ * Delete per-CPU resource and adjust refcnt when per-task events
+ * are currently active. This can be more than one.
+ * In this case adjust counters.
+ */
+ if (hotplug)
+ tasks = atomic_read(&pai_root[idx].tskctx);
+
+ cpump = mp->mapptr;
+ if (refcount_sub_and_test(tasks, &cpump->refcnt))
pai_free(mp);
- pai_root_free(idx);
- mutex_unlock(&pai_reserve_mutex);
+ pai_root_free(idx, tasks);
}
static void pai_event_destroy(struct perf_event *event)
{
- int cpu;
+ int cpu = 0, idx = PAI_PMU_IDX(event);
free_page(PAI_SAVE_AREA(event));
+ cpus_read_lock();
+ mutex_lock(&pai_reserve_mutex);
if (event->cpu == -1) {
- struct cpumask *mask = PAI_CPU_MASK(event);
-
- for_each_cpu(cpu, mask)
- pai_event_destroy_cpu(event, cpu);
- kfree(mask);
+ atomic_dec(&pai_root[idx].tskctx);
+ for_each_online_cpu(cpu)
+ pai_event_destroy_cpu(idx, cpu, false);
} else {
- pai_event_destroy_cpu(event, event->cpu);
+ pai_event_destroy_cpu(idx, event->cpu, false);
}
+ mutex_unlock(&pai_reserve_mutex);
+ cpus_read_unlock();
}
static void paicrypt_event_destroy(struct perf_event *event)
@@ -234,25 +250,30 @@ static u64 paicrypt_getall(struct perf_event *event)
return sum;
}
-/* Check concurrent access of counting and sampling for crypto events.
- * This function is called in process context and it is save to block.
- * When the event initialization functions fails, no other call back will
- * be invoked.
- *
- * Allocate the memory for the event.
- */
-static int pai_alloc_cpu(struct perf_event *event, int cpu)
+/* Called under mutex_lock */
+static int pai_alloc_cpu(int idx, int cpu, bool hotplug)
{
- int rc, idx = PAI_PMU_IDX(event);
struct pai_map *cpump = NULL;
bool need_paiext_cb = false;
struct pai_mapptr *mp;
+ int tasks = 1, rc = 0;
+
+ /* When hotplug is true, invocation is from CPU hotplug callback.
+ * Allocate per-CPU resource when per-task events are currently active.
+ * This can be more than one. In this case adjust all reference
+ * counters. Otherwise return, this ensures memory is only allocated
+ * when needed.
+ */
+ if (hotplug) {
+ tasks = atomic_read(&pai_root[idx].tskctx);
+ if (!tasks)
+ goto out;
+ }
- mutex_lock(&pai_reserve_mutex);
/* Allocate root node */
rc = pai_root_alloc(idx);
if (rc)
- goto unlock;
+ goto out;
/* Allocate node for this event */
mp = per_cpu_ptr(pai_root[idx].mapptr, cpu);
@@ -296,28 +317,45 @@ static int pai_alloc_cpu(struct perf_event *event, int cpu)
goto undo;
}
INIT_LIST_HEAD(&cpump->syswide_list);
- refcount_set(&cpump->refcnt, 1);
+ refcount_set(&cpump->refcnt, tasks);
rc = 0;
} else {
- refcount_inc(&cpump->refcnt);
+ refcount_add(tasks, &cpump->refcnt);
}
+ /* If tasks is greater than 1, we are called from CPU hotplug path
+ * and need to adjust the pai_root[idx].refcnt by the number of
+ * per-process events. Function pai_root_alloc(idx) already
+ * incremented by one. Adjust for the rest.
+ */
+ if (tasks > 1)
+ refcount_add(tasks - 1, &pai_root[idx].refcnt);
undo:
if (rc) {
/* Error in allocation of event, decrement anchor. Since
* the event in not created, its destroy() function is never
* invoked. Adjust the reference counter for the anchor.
+ * The failure happened in the case of variable
+ * cpump == NULL branch above. The pai_root[XXX].refcnt has
+ * been incremented by one. Then the per-CPU allocation
+ * failed, so decrement it by one, regardless of tasks.
*/
- pai_root_free(idx);
+ pai_root_free(idx, 1);
}
-unlock:
- mutex_unlock(&pai_reserve_mutex);
+out:
/* If rc is non-zero, no increment of counter/sampler was done. */
return rc;
}
+/* Check concurrent access of counting and sampling for PAI events.
+ * This function is called in process context and it is safe to block.
+ * When the event initialization functions fails, no other call back will
+ * be invoked.
+ * Called under mutex_lock.
+ */
static int pai_alloc(struct perf_event *event)
{
+ int idx = PAI_PMU_IDX(event);
struct cpumask *maskptr;
int cpu, rc = -ENOMEM;
@@ -326,24 +364,20 @@ static int pai_alloc(struct perf_event *event)
goto out;
for_each_online_cpu(cpu) {
- rc = pai_alloc_cpu(event, cpu);
+ rc = pai_alloc_cpu(idx, cpu, false);
if (rc) {
for_each_cpu(cpu, maskptr)
- pai_event_destroy_cpu(event, cpu);
- kfree(maskptr);
- goto out;
+ pai_event_destroy_cpu(idx, cpu, false);
+ goto undo;
}
cpumask_set_cpu(cpu, maskptr);
}
- /*
- * On error all cpumask are freed and all events have been destroyed.
- * Save of which CPUs data structures have been allocated for.
- * Release them in pai_event_destroy call back function
- * for this event.
- */
- PAI_CPU_MASK(event) = maskptr;
rc = 0;
+ /* Trace per-task events for CPU hotplug. */
+ atomic_inc(&pai_root[idx].tskctx);
+undo:
+ kfree(maskptr);
out:
return rc;
}
@@ -391,10 +425,14 @@ static int pai_event_init(struct perf_event *event, int idx)
}
}
+ cpus_read_lock();
+ mutex_lock(&pai_reserve_mutex);
if (event->cpu >= 0)
- rc = pai_alloc_cpu(event, event->cpu);
+ rc = pai_alloc_cpu(idx, event->cpu, false);
else
rc = pai_alloc(event);
+ mutex_unlock(&pai_reserve_mutex);
+ cpus_read_unlock();
if (rc) {
free_page(PAI_SAVE_AREA(event));
goto out;
@@ -1239,8 +1277,35 @@ static int __init paipmu_setup(void)
return install_ok;
}
+static int pai_online_cpu(unsigned int cpu)
+{
+ int rc;
+
+ mutex_lock(&pai_reserve_mutex);
+ rc = pai_alloc_cpu(PAI_PMU_CRYPTO, cpu, true);
+ if (rc)
+ goto out;
+ rc = pai_alloc_cpu(PAI_PMU_EXT, cpu, true);
+ if (rc)
+ pai_event_destroy_cpu(PAI_PMU_CRYPTO, cpu, true);
+out:
+ mutex_unlock(&pai_reserve_mutex);
+ return rc;
+}
+
+static int pai_offline_cpu(unsigned int cpu)
+{
+ mutex_lock(&pai_reserve_mutex);
+ pai_event_destroy_cpu(PAI_PMU_CRYPTO, cpu, true);
+ pai_event_destroy_cpu(PAI_PMU_EXT, cpu, true);
+ mutex_unlock(&pai_reserve_mutex);
+ return 0;
+}
+
static int __init pai_init(void)
{
+ int state, rc;
+
/* Setup s390dbf facility */
paidbg = debug_register("pai", 1, 1, 128);
if (!paidbg) {
@@ -1249,13 +1314,24 @@ static int __init pai_init(void)
}
debug_register_view(paidbg, &debug_sprintf_view);
- if (!paipmu_setup()) {
- /* No PMU registration, no need for debug buffer */
- debug_unregister_view(paidbg, &debug_sprintf_view);
- debug_unregister(paidbg);
- return -ENODEV;
- }
+ /* CPUHP_BP_PREPARE_DYN --> before CPU is brought online */
+ state = cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "perf/pai:prepare",
+ pai_online_cpu, pai_offline_cpu);
+ rc = state < 0 ? state : 0;
+ if (rc < 0)
+ goto out_debug;
+
+ rc = -ENODEV;
+ if (!paipmu_setup())
+ goto out_cpuhp;
return 0;
+
+out_cpuhp:
+ cpuhp_remove_state(state);
+out_debug:
+ debug_unregister_view(paidbg, &debug_sprintf_view);
+ debug_unregister(paidbg);
+ return rc;
}
device_initcall(pai_init);
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index cc13164d948f..1ac2ca35db53 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -3125,6 +3125,27 @@ static void intel_pmu_del_event(struct perf_event *event)
this_cpu_ptr(&cpu_hw_events)->n_late_setup--;
}
+int __intel_pmu_quiesce(void)
+{
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+ int pmu_enabled = cpuc->enabled;
+
+ cpuc->enabled = 0;
+ if (pmu_enabled)
+ intel_pmu_disable_all();
+
+ return pmu_enabled;
+}
+
+void __intel_pmu_resume(int pmu_enabled)
+{
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+
+ cpuc->enabled = pmu_enabled;
+ if (pmu_enabled)
+ intel_pmu_enable_all(0);
+}
+
static int icl_set_topdown_event_period(struct perf_event *event)
{
struct hw_perf_event *hwc = &event->hw;
@@ -3316,16 +3337,13 @@ static void intel_pmu_read_event(struct perf_event *event)
if (event->hw.flags & (PERF_X86_EVENT_AUTO_RELOAD | PERF_X86_EVENT_TOPDOWN) ||
is_pebs_counter_event_group(event)) {
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
- bool pmu_enabled = cpuc->enabled;
+ int pmu_enabled;
/* Only need to call update_topdown_event() once for group read. */
if (is_metric_event(event) && (cpuc->txn_flags & PERF_PMU_TXN_READ))
return;
- cpuc->enabled = 0;
- if (pmu_enabled)
- intel_pmu_disable_all();
-
+ pmu_enabled = __intel_pmu_quiesce();
/*
* If the PEBS counters snapshotting is enabled,
* the topdown event is available in PEBS records.
@@ -3334,10 +3352,7 @@ static void intel_pmu_read_event(struct perf_event *event)
static_call(intel_pmu_update_topdown_event)(event, NULL);
else
intel_pmu_drain_pebs_buffer();
-
- cpuc->enabled = pmu_enabled;
- if (pmu_enabled)
- intel_pmu_enable_all(0);
+ __intel_pmu_resume(pmu_enabled);
return;
}
diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c
index 8940f0292229..b98029b44052 100644
--- a/arch/x86/events/intel/ds.c
+++ b/arch/x86/events/intel/ds.c
@@ -1242,8 +1242,11 @@ unlock:
void intel_pmu_drain_pebs_buffer(void)
{
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
struct perf_sample_data data;
+ WARN_ON_ONCE(cpuc->enabled);
+
static_call(x86_pmu_drain_pebs)(NULL, &data);
}
@@ -1864,8 +1867,11 @@ static void intel_pmu_pebs_via_pt_enable(struct perf_event *event)
static inline void intel_pmu_drain_large_pebs(struct cpu_hw_events *cpuc)
{
if (cpuc->n_pebs == cpuc->n_large_pebs &&
- cpuc->n_pebs != cpuc->n_pebs_via_pt)
+ cpuc->n_pebs != cpuc->n_pebs_via_pt) {
+ int enabled = __intel_pmu_quiesce();
intel_pmu_drain_pebs_buffer();
+ __intel_pmu_resume(enabled);
+ }
}
static void __intel_pmu_pebs_enable(struct perf_event *event)
@@ -2432,7 +2438,7 @@ static inline void __setup_pebs_basic_group(struct perf_event *event,
{
/* The ip in basic is EventingIP */
set_linear_ip(regs, ip);
- regs->flags = PERF_EFLAGS_EXACT;
+ regs->flags |= PERF_EFLAGS_EXACT;
setup_pebs_time(event, data, tsc);
if (sample_type & PERF_SAMPLE_WEIGHT_STRUCT)
@@ -2444,9 +2450,17 @@ static inline void __setup_pebs_gpr_group(struct perf_event *event,
struct pebs_gprs *gprs,
u64 sample_type)
{
+ /*
+ * Update flags with PEBS data. PERF_EFLAGS_EXACT must be set
+ * in previous basic group handling.
+ */
+ regs->flags = gprs->flags | PERF_EFLAGS_EXACT;
+
if (event->attr.precise_ip < 2) {
set_linear_ip(regs, gprs->ip);
regs->flags &= ~PERF_EFLAGS_EXACT;
+ } else if (regs->flags & X86_VM_MASK) {
+ regs->flags ^= (PERF_EFLAGS_VM | X86_VM_MASK);
}
if (sample_type & (PERF_SAMPLE_REGS_INTR | PERF_SAMPLE_REGS_USER))
diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
index 71ed5b2acea2..4680cba91340 100644
--- a/arch/x86/events/perf_event.h
+++ b/arch/x86/events/perf_event.h
@@ -1638,6 +1638,9 @@ static __always_inline void __intel_pmu_lbr_disable(void)
wrmsrq(MSR_IA32_DEBUGCTLMSR, debugctl);
}
+extern int __intel_pmu_quiesce(void);
+extern void __intel_pmu_resume(int pmu_enabled);
+
int intel_pmu_save_and_restart(struct perf_event *event);
struct event_constraint *
diff --git a/arch/x86/include/asm/div64.h b/arch/x86/include/asm/div64.h
index 30fd06ede751..8a2d343f977e 100644
--- a/arch/x86/include/asm/div64.h
+++ b/arch/x86/include/asm/div64.h
@@ -111,7 +111,7 @@ static inline u64 mul_u64_add_u64_div_u64(u64 rax, u64 mul, u64 add, u64 div)
if (!statically_true(!add))
asm ("addq %[add], %[lo]; adcq $0, %[hi]" :
- [lo] "+r" (rax), [hi] "+r" (rdx) : [add] "irm" (add));
+ [lo] "+r" (rax), [hi] "+r" (rdx) : [add] "erm" (add));
asm ("divq %[div]" : "+a" (rax), "+d" (rdx) : [div] "rm" (div));
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h
index d5f4917c1edc..d551120a7c88 100644
--- a/arch/x86/include/asm/pgtable.h
+++ b/arch/x86/include/asm/pgtable.h
@@ -806,7 +806,7 @@ static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot)
pmdval_t val = pmd_val(pmd), oldval = val;
pmd_t pmd_result;
- val &= (_HPAGE_CHG_MASK & ~_PAGE_DIRTY);
+ val &= _HPAGE_CHG_MASK;
val |= check_pgprot(newprot) & ~_HPAGE_CHG_MASK;
val = flip_protnone_guard(oldval, val, PHYSICAL_PMD_PAGE_MASK);
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c
index 91b1cdd16569..741d8767ddf8 100644
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -6,6 +6,9 @@
#include <linux/vmalloc.h>
#include <linux/memory.h>
#include <linux/execmem.h>
+#include <linux/cleanup.h>
+#include <linux/kgdb.h>
+#include <linux/mmap_lock.h>
#include <asm/text-patching.h>
#include <asm/insn.h>
@@ -1198,6 +1201,41 @@ static bool cfi_debug __ro_after_init;
bool cfi_bhi __ro_after_init = false;
#endif
+#ifdef CONFIG_FINEIBT
+/*
+ * <fineibt_preamble_start>:
+ * 0: f3 0f 1e fa endbr64
+ * 4: 2d 78 56 34 12 sub $0x12345678, %eax
+ * 9: 2e 0f 85 03 00 00 00 jne,pn 13 <fineibt_preamble_start+0x13>
+ * 10: 0f 1f 40 d6 nopl -0x2a(%rax)
+ *
+ * Note that the JNE target is the 0xD6 byte inside the NOPL, this decodes as
+ * UDB on x86_64 and raises #UD.
+ */
+asm( ".pushsection .rodata \n"
+ "fineibt_preamble_start: \n"
+ " endbr64 \n"
+ " subl $0x12345678, %eax \n"
+ "fineibt_preamble_bhi: \n"
+ " cs jne.d32 fineibt_preamble_start+0x13 \n"
+ "#fineibt_func: \n"
+ " nopl -42(%rax) \n"
+ "fineibt_preamble_end: \n"
+ ".popsection\n"
+);
+
+extern u8 fineibt_preamble_start[];
+extern u8 fineibt_preamble_bhi[];
+extern u8 fineibt_preamble_end[];
+
+#define fineibt_preamble_size (fineibt_preamble_end - fineibt_preamble_start)
+#define fineibt_preamble_bhi (fineibt_preamble_bhi - fineibt_preamble_start)
+#define fineibt_preamble_ud 0x13
+#define fineibt_preamble_hash 5
+
+#define fineibt_prefix_size (fineibt_preamble_size - ENDBR_INSN_SIZE)
+#endif /* CONFIG_FINEIBT */
+
#ifdef CONFIG_CFI
u32 cfi_get_func_hash(void *func)
{
@@ -1205,9 +1243,11 @@ u32 cfi_get_func_hash(void *func)
func -= cfi_get_offset();
switch (cfi_mode) {
+#ifdef CONFIG_FINEIBT
case CFI_FINEIBT:
- func += 7;
+ func += fineibt_preamble_hash;
break;
+#endif
case CFI_KCFI:
func += 1;
break;
@@ -1364,39 +1404,6 @@ early_param("cfi", cfi_parse_cmdline);
*/
/*
- * <fineibt_preamble_start>:
- * 0: f3 0f 1e fa endbr64
- * 4: 2d 78 56 34 12 sub $0x12345678, %eax
- * 9: 2e 0f 85 03 00 00 00 jne,pn 13 <fineibt_preamble_start+0x13>
- * 10: 0f 1f 40 d6 nopl -0x2a(%rax)
- *
- * Note that the JNE target is the 0xD6 byte inside the NOPL, this decodes as
- * UDB on x86_64 and raises #UD.
- */
-asm( ".pushsection .rodata \n"
- "fineibt_preamble_start: \n"
- " endbr64 \n"
- " subl $0x12345678, %eax \n"
- "fineibt_preamble_bhi: \n"
- " cs jne.d32 fineibt_preamble_start+0x13 \n"
- "#fineibt_func: \n"
- " nopl -42(%rax) \n"
- "fineibt_preamble_end: \n"
- ".popsection\n"
-);
-
-extern u8 fineibt_preamble_start[];
-extern u8 fineibt_preamble_bhi[];
-extern u8 fineibt_preamble_end[];
-
-#define fineibt_preamble_size (fineibt_preamble_end - fineibt_preamble_start)
-#define fineibt_preamble_bhi (fineibt_preamble_bhi - fineibt_preamble_start)
-#define fineibt_preamble_ud 0x13
-#define fineibt_preamble_hash 5
-
-#define fineibt_prefix_size (fineibt_preamble_size - ENDBR_INSN_SIZE)
-
-/*
* <fineibt_caller_start>:
* 0: b8 78 56 34 12 mov $0x12345678, %eax
* 5: 4d 8d 5b f0 lea -0x10(%r11), %r11
@@ -2372,6 +2379,38 @@ static void text_poke_memset(void *dst, const void *src, size_t len)
typedef void text_poke_f(void *dst, const void *src, size_t len);
+static void __poke_vmalloc_pages(struct page **pages, void *addr,
+ bool cross_page_boundary)
+{
+ pages[0] = vmalloc_to_page(addr);
+ if (cross_page_boundary)
+ pages[1] = vmalloc_to_page(addr + PAGE_SIZE);
+}
+
+static void poke_vmalloc_pages(struct page **pages, void *addr,
+ bool cross_page_boundary)
+{
+ if (in_dbg_master()) {
+ /*
+ * If called from kgdb cannot sleep, but all other CPUs stopped
+ * anyway so safe to proceed without locks
+ */
+ __poke_vmalloc_pages(pages, addr, cross_page_boundary);
+ } else {
+ /*
+ * execmem ROX ranges are shared between modules and can be
+ * collapsed to huge PMD entries, and this collapse can happen
+ * concurrently with a racing set_memory_rox().
+ *
+ * Prevent vmalloc_to_page() from racing by acquiring an
+ * init_mm read lock which pairs with the init_mm write lock in
+ * cpa_collapse_large_pages().
+ */
+ guard(mmap_read_lock)(&init_mm);
+ __poke_vmalloc_pages(pages, addr, cross_page_boundary);
+ }
+}
+
static void *__text_poke(text_poke_f func, void *addr, const void *src, size_t len)
{
bool cross_page_boundary = offset_in_page(addr) + len > PAGE_SIZE;
@@ -2389,9 +2428,7 @@ static void *__text_poke(text_poke_f func, void *addr, const void *src, size_t l
BUG_ON(!after_bootmem);
if (!core_kernel_text((unsigned long)addr)) {
- pages[0] = vmalloc_to_page(addr);
- if (cross_page_boundary)
- pages[1] = vmalloc_to_page(addr + PAGE_SIZE);
+ poke_vmalloc_pages(pages, addr, cross_page_boundary);
} else {
pages[0] = virt_to_page(addr);
WARN_ON(!PageReserved(pages[0]));
diff --git a/arch/x86/kernel/amd_node.c b/arch/x86/kernel/amd_node.c
index 762585775b5a..b7926ba3610a 100644
--- a/arch/x86/kernel/amd_node.c
+++ b/arch/x86/kernel/amd_node.c
@@ -251,7 +251,7 @@ __setup("amd_smn_debugfs_enable", amd_smn_enable_dfs);
static int __init amd_smn_init(void)
{
u16 count, num_roots, roots_per_node, node, num_nodes;
- struct pci_dev *root;
+ struct pci_dev *root __free(pci_dev_put) = NULL;
if (!cpu_feature_enabled(X86_FEATURE_ZEN))
return 0;
@@ -262,7 +262,6 @@ static int __init amd_smn_init(void)
return 0;
num_roots = 0;
- root = NULL;
while ((root = get_next_root(root))) {
pci_dbg(root, "Reserving PCI config space\n");
@@ -299,14 +298,13 @@ static int __init amd_smn_init(void)
count = 0;
node = 0;
- root = NULL;
while (node < num_nodes && (root = get_next_root(root))) {
/* Use one root for each node and skip the rest. */
if (count++ % roots_per_node)
continue;
pci_dbg(root, "is root for AMD node %u\n", node);
- amd_roots[node++] = root;
+ amd_roots[node++] = pci_dev_get(root);
}
if (enable_dfs) {
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 95bae74fdab2..3aefdef5bcb0 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -13,6 +13,7 @@
#include <linux/cc_platform.h>
#include <linux/mem_encrypt.h>
#include <linux/virtio_anchor.h>
+#include <linux/iommu-dma.h>
#include <asm/sev.h>
@@ -30,7 +31,7 @@ bool force_dma_unencrypted(struct device *dev)
* device does not support DMA to addresses that include the
* encryption mask.
*/
- if (cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT)) {
+ if (cc_platform_has(CC_ATTR_HOST_MEM_ENCRYPT) && !use_dma_iommu(dev)) {
u64 dma_enc_mask = DMA_BIT_MASK(__ffs64(sme_me_mask));
u64 dma_dev_mask = min_not_zero(dev->coherent_dma_mask,
dev->bus_dma_limit);
diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
index c38faf39ce15..4652487b5572 100644
--- a/arch/x86/mm/pat/set_memory.c
+++ b/arch/x86/mm/pat/set_memory.c
@@ -22,6 +22,7 @@
#include <linux/cc_platform.h>
#include <linux/set_memory.h>
#include <linux/memregion.h>
+#include <linux/cleanup.h>
#include <asm/e820/api.h>
#include <asm/processor.h>
@@ -49,7 +50,8 @@ struct cpa_data {
unsigned int flags;
unsigned int force_split : 1,
force_static_prot : 1,
- force_flush_all : 1;
+ force_flush_all : 1,
+ init_mm_read_locked : 1;
struct page **pages;
};
@@ -409,7 +411,7 @@ static void __cpa_flush_tlb(void *data)
static int collapse_large_pages(unsigned long addr, struct list_head *pgtables);
-static void cpa_collapse_large_pages(struct cpa_data *cpa)
+static void __cpa_collapse_large_pages(struct cpa_data *cpa)
{
unsigned long start, addr, end;
struct ptdesc *ptdesc, *tmp;
@@ -439,10 +441,30 @@ static void cpa_collapse_large_pages(struct cpa_data *cpa)
list_for_each_entry_safe(ptdesc, tmp, &pgtables, pt_list) {
list_del(&ptdesc->pt_list);
- pagetable_free(ptdesc);
+ /*
+ * Only early alloc'd direct map should not be flagged PG_table
+ * here and those shouldn't be collapsed. However be abundantly
+ * cautious and handle the !PG_table case too.
+ */
+ if (PageTable((ptdesc_page(ptdesc))))
+ pagetable_dtor_free(ptdesc);
+ else
+ pagetable_free(ptdesc);
}
}
+static void cpa_collapse_large_pages(struct cpa_data *cpa)
+{
+ /*
+ * Take the mmap write lock on init_mm to:
+ * - Avoid a use-after-free if raced by ptdump (which takes its own
+ * write lock on init_mm).
+ * - Serialise concurrent CPA walkers.
+ */
+ scoped_guard(mmap_write_lock, &init_mm)
+ __cpa_collapse_large_pages(cpa);
+}
+
static void cpa_flush(struct cpa_data *cpa, int cache)
{
unsigned int i;
@@ -1120,11 +1142,10 @@ set:
static int
__split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
- struct ptdesc *ptdesc)
+ pte_t *pbase)
{
unsigned long lpaddr, lpinc, ref_pfn, pfn, pfninc = 1;
- struct page *base = ptdesc_page(ptdesc);
- pte_t *pbase = (pte_t *)page_address(base);
+ struct page *base = virt_to_page(pbase);
unsigned int i, level;
pgprot_t ref_prot;
bool nx, rw;
@@ -1224,16 +1245,20 @@ __split_large_page(struct cpa_data *cpa, pte_t *kpte, unsigned long address,
static int split_large_page(struct cpa_data *cpa, pte_t *kpte,
unsigned long address)
{
- struct ptdesc *ptdesc;
+ pte_t *pte;
spin_unlock(&cpa_lock);
- ptdesc = pagetable_alloc(GFP_KERNEL, 0);
+ if (cpa->init_mm_read_locked)
+ mmap_read_unlock(&init_mm);
+ pte = pte_alloc_one_kernel(&init_mm);
+ if (cpa->init_mm_read_locked)
+ mmap_read_lock(&init_mm);
spin_lock(&cpa_lock);
- if (!ptdesc)
+ if (!pte)
return -ENOMEM;
- if (__split_large_page(cpa, kpte, address, ptdesc))
- pagetable_free(ptdesc);
+ if (__split_large_page(cpa, kpte, address, pte))
+ pte_free_kernel(&init_mm, pte);
return 0;
}
@@ -2121,7 +2146,11 @@ static int change_page_attr_set_clr(unsigned long *addr, int numpages,
cpa.curpage = 0;
cpa.force_split = force_split;
- ret = __change_page_attr_set_clr(&cpa, 1);
+ /* Avoid race with concurrent CPA collapse. */
+ cpa.init_mm_read_locked = true;
+ scoped_guard(mmap_read_lock, &init_mm)
+ ret = __change_page_attr_set_clr(&cpa, 1);
+ cpa.init_mm_read_locked = false;
/*
* Check whether we really changed something: