summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pagano <mpagano@gentoo.org>2023-01-18 06:08:25 -0500
committerMike Pagano <mpagano@gentoo.org>2023-01-18 06:08:25 -0500
commit4372be492234c190d9860788db21f2c0870ae8e9 (patch)
treeb46618c007609c4cd45b909d1bc5a34b615edd62
parentLinux patch 5.15.88 (diff)
downloadlinux-patches-4372be492234c190d9860788db21f2c0870ae8e9.tar.gz
linux-patches-4372be492234c190d9860788db21f2c0870ae8e9.tar.bz2
linux-patches-4372be492234c190d9860788db21f2c0870ae8e9.zip
Linux patch 5.15.895.15-93
Signed-off-by: Mike Pagano <mpagano@gentoo.org>
-rw-r--r--0000_README4
-rw-r--r--1088_linux-5.15.89.patch6178
2 files changed, 6182 insertions, 0 deletions
diff --git a/0000_README b/0000_README
index 3f36a0d8..151d7604 100644
--- a/0000_README
+++ b/0000_README
@@ -395,6 +395,10 @@ Patch: 1087_linux-5.15.88.patch
From: http://www.kernel.org
Desc: Linux 5.15.88
+Patch: 1088_linux-5.15.89.patch
+From: http://www.kernel.org
+Desc: Linux 5.15.89
+
Patch: 1500_XATTR_USER_PREFIX.patch
From: https://bugs.gentoo.org/show_bug.cgi?id=470644
Desc: Support for namespace user.pax.* on tmpfs.
diff --git a/1088_linux-5.15.89.patch b/1088_linux-5.15.89.patch
new file mode 100644
index 00000000..8822b4b0
--- /dev/null
+++ b/1088_linux-5.15.89.patch
@@ -0,0 +1,6178 @@
+diff --git a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
+index 35426fde86106..283a12cd3e144 100644
+--- a/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
++++ b/Documentation/devicetree/bindings/display/msm/dsi-controller-main.yaml
+@@ -31,7 +31,7 @@ properties:
+ - description: Display byte clock
+ - description: Display byte interface clock
+ - description: Display pixel clock
+- - description: Display escape clock
++ - description: Display core clock
+ - description: Display AHB clock
+ - description: Display AXI clock
+
+@@ -135,8 +135,6 @@ required:
+ - phy-names
+ - assigned-clocks
+ - assigned-clock-parents
+- - power-domains
+- - operating-points-v2
+ - ports
+
+ additionalProperties: false
+diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml b/Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml
+index 4399715953e1a..4dd5eed50506a 100644
+--- a/Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml
++++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-10nm.yaml
+@@ -39,7 +39,6 @@ required:
+ - compatible
+ - reg
+ - reg-names
+- - vdds-supply
+
+ unevaluatedProperties: false
+
+diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml b/Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml
+index 064df50e21a5c..23355ac67d3d1 100644
+--- a/Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml
++++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-14nm.yaml
+@@ -37,7 +37,6 @@ required:
+ - compatible
+ - reg
+ - reg-names
+- - vcca-supply
+
+ unevaluatedProperties: false
+
+diff --git a/Documentation/devicetree/bindings/display/msm/dsi-phy-28nm.yaml b/Documentation/devicetree/bindings/display/msm/dsi-phy-28nm.yaml
+index 69eecaa64b187..ddb0ac4c29d44 100644
+--- a/Documentation/devicetree/bindings/display/msm/dsi-phy-28nm.yaml
++++ b/Documentation/devicetree/bindings/display/msm/dsi-phy-28nm.yaml
+@@ -34,6 +34,10 @@ properties:
+ vddio-supply:
+ description: Phandle to vdd-io regulator device node.
+
++ qcom,dsi-phy-regulator-ldo-mode:
++ type: boolean
++ description: Indicates if the LDO mode PHY regulator is wanted.
++
+ required:
+ - compatible
+ - reg
+diff --git a/Documentation/sphinx/load_config.py b/Documentation/sphinx/load_config.py
+index eeb394b39e2cc..8b416bfd75ac1 100644
+--- a/Documentation/sphinx/load_config.py
++++ b/Documentation/sphinx/load_config.py
+@@ -3,7 +3,7 @@
+
+ import os
+ import sys
+-from sphinx.util.pycompat import execfile_
++from sphinx.util.osutil import fs_encoding
+
+ # ------------------------------------------------------------------------------
+ def loadConfig(namespace):
+@@ -48,7 +48,9 @@ def loadConfig(namespace):
+ sys.stdout.write("load additional sphinx-config: %s\n" % config_file)
+ config = namespace.copy()
+ config['__file__'] = config_file
+- execfile_(config_file, config)
++ with open(config_file, 'rb') as f:
++ code = compile(f.read(), fs_encoding, 'exec')
++ exec(code, config)
+ del config['__file__']
+ namespace.update(config)
+ else:
+diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
+index a6729c8cf0634..b550f43214c79 100644
+--- a/Documentation/virt/kvm/api.rst
++++ b/Documentation/virt/kvm/api.rst
+@@ -7265,3 +7265,63 @@ The argument to KVM_ENABLE_CAP is also a bitmask, and must be a subset
+ of the result of KVM_CHECK_EXTENSION. KVM will forward to userspace
+ the hypercalls whose corresponding bit is in the argument, and return
+ ENOSYS for the others.
++
++9. Known KVM API problems
++=========================
++
++In some cases, KVM's API has some inconsistencies or common pitfalls
++that userspace need to be aware of. This section details some of
++these issues.
++
++Most of them are architecture specific, so the section is split by
++architecture.
++
++9.1. x86
++--------
++
++``KVM_GET_SUPPORTED_CPUID`` issues
++^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
++
++In general, ``KVM_GET_SUPPORTED_CPUID`` is designed so that it is possible
++to take its result and pass it directly to ``KVM_SET_CPUID2``. This section
++documents some cases in which that requires some care.
++
++Local APIC features
++~~~~~~~~~~~~~~~~~~~
++
++CPU[EAX=1]:ECX[21] (X2APIC) is reported by ``KVM_GET_SUPPORTED_CPUID``,
++but it can only be enabled if ``KVM_CREATE_IRQCHIP`` or
++``KVM_ENABLE_CAP(KVM_CAP_IRQCHIP_SPLIT)`` are used to enable in-kernel emulation of
++the local APIC.
++
++The same is true for the ``KVM_FEATURE_PV_UNHALT`` paravirtualized feature.
++
++CPU[EAX=1]:ECX[24] (TSC_DEADLINE) is not reported by ``KVM_GET_SUPPORTED_CPUID``.
++It can be enabled if ``KVM_CAP_TSC_DEADLINE_TIMER`` is present and the kernel
++has enabled in-kernel emulation of the local APIC.
++
++CPU topology
++~~~~~~~~~~~~
++
++Several CPUID values include topology information for the host CPU:
++0x0b and 0x1f for Intel systems, 0x8000001e for AMD systems. Different
++versions of KVM return different values for this information and userspace
++should not rely on it. Currently they return all zeroes.
++
++If userspace wishes to set up a guest topology, it should be careful that
++the values of these three leaves differ for each CPU. In particular,
++the APIC ID is found in EDX for all subleaves of 0x0b and 0x1f, and in EAX
++for 0x8000001e; the latter also encodes the core id and node id in bits
++7:0 of EBX and ECX respectively.
++
++Obsolete ioctls and capabilities
++^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
++
++KVM_CAP_DISABLE_QUIRKS does not let userspace know which quirks are actually
++available. Use ``KVM_CHECK_EXTENSION(KVM_CAP_DISABLE_QUIRKS2)`` instead if
++available.
++
++Ordering of KVM_GET_*/KVM_SET_* ioctls
++^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
++
++TBD
+diff --git a/Makefile b/Makefile
+index f7ff35b0cf6fc..9ebe9ddb8641d 100644
+--- a/Makefile
++++ b/Makefile
+@@ -1,7 +1,7 @@
+ # SPDX-License-Identifier: GPL-2.0
+ VERSION = 5
+ PATCHLEVEL = 15
+-SUBLEVEL = 88
++SUBLEVEL = 89
+ EXTRAVERSION =
+ NAME = Trick or Treat
+
+diff --git a/arch/arm64/include/asm/atomic_ll_sc.h b/arch/arm64/include/asm/atomic_ll_sc.h
+index 13869b76b58cd..abd302e521c06 100644
+--- a/arch/arm64/include/asm/atomic_ll_sc.h
++++ b/arch/arm64/include/asm/atomic_ll_sc.h
+@@ -12,19 +12,6 @@
+
+ #include <linux/stringify.h>
+
+-#ifdef CONFIG_ARM64_LSE_ATOMICS
+-#define __LL_SC_FALLBACK(asm_ops) \
+-" b 3f\n" \
+-" .subsection 1\n" \
+-"3:\n" \
+-asm_ops "\n" \
+-" b 4f\n" \
+-" .previous\n" \
+-"4:\n"
+-#else
+-#define __LL_SC_FALLBACK(asm_ops) asm_ops
+-#endif
+-
+ #ifndef CONFIG_CC_HAS_K_CONSTRAINT
+ #define K
+ #endif
+@@ -43,12 +30,11 @@ __ll_sc_atomic_##op(int i, atomic_t *v) \
+ int result; \
+ \
+ asm volatile("// atomic_" #op "\n" \
+- __LL_SC_FALLBACK( \
+-" prfm pstl1strm, %2\n" \
+-"1: ldxr %w0, %2\n" \
+-" " #asm_op " %w0, %w0, %w3\n" \
+-" stxr %w1, %w0, %2\n" \
+-" cbnz %w1, 1b\n") \
++ " prfm pstl1strm, %2\n" \
++ "1: ldxr %w0, %2\n" \
++ " " #asm_op " %w0, %w0, %w3\n" \
++ " stxr %w1, %w0, %2\n" \
++ " cbnz %w1, 1b\n" \
+ : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \
+ : __stringify(constraint) "r" (i)); \
+ }
+@@ -61,13 +47,12 @@ __ll_sc_atomic_##op##_return##name(int i, atomic_t *v) \
+ int result; \
+ \
+ asm volatile("// atomic_" #op "_return" #name "\n" \
+- __LL_SC_FALLBACK( \
+-" prfm pstl1strm, %2\n" \
+-"1: ld" #acq "xr %w0, %2\n" \
+-" " #asm_op " %w0, %w0, %w3\n" \
+-" st" #rel "xr %w1, %w0, %2\n" \
+-" cbnz %w1, 1b\n" \
+-" " #mb ) \
++ " prfm pstl1strm, %2\n" \
++ "1: ld" #acq "xr %w0, %2\n" \
++ " " #asm_op " %w0, %w0, %w3\n" \
++ " st" #rel "xr %w1, %w0, %2\n" \
++ " cbnz %w1, 1b\n" \
++ " " #mb \
+ : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \
+ : __stringify(constraint) "r" (i) \
+ : cl); \
+@@ -83,13 +68,12 @@ __ll_sc_atomic_fetch_##op##name(int i, atomic_t *v) \
+ int val, result; \
+ \
+ asm volatile("// atomic_fetch_" #op #name "\n" \
+- __LL_SC_FALLBACK( \
+-" prfm pstl1strm, %3\n" \
+-"1: ld" #acq "xr %w0, %3\n" \
+-" " #asm_op " %w1, %w0, %w4\n" \
+-" st" #rel "xr %w2, %w1, %3\n" \
+-" cbnz %w2, 1b\n" \
+-" " #mb ) \
++ " prfm pstl1strm, %3\n" \
++ "1: ld" #acq "xr %w0, %3\n" \
++ " " #asm_op " %w1, %w0, %w4\n" \
++ " st" #rel "xr %w2, %w1, %3\n" \
++ " cbnz %w2, 1b\n" \
++ " " #mb \
+ : "=&r" (result), "=&r" (val), "=&r" (tmp), "+Q" (v->counter) \
+ : __stringify(constraint) "r" (i) \
+ : cl); \
+@@ -142,12 +126,11 @@ __ll_sc_atomic64_##op(s64 i, atomic64_t *v) \
+ unsigned long tmp; \
+ \
+ asm volatile("// atomic64_" #op "\n" \
+- __LL_SC_FALLBACK( \
+-" prfm pstl1strm, %2\n" \
+-"1: ldxr %0, %2\n" \
+-" " #asm_op " %0, %0, %3\n" \
+-" stxr %w1, %0, %2\n" \
+-" cbnz %w1, 1b") \
++ " prfm pstl1strm, %2\n" \
++ "1: ldxr %0, %2\n" \
++ " " #asm_op " %0, %0, %3\n" \
++ " stxr %w1, %0, %2\n" \
++ " cbnz %w1, 1b" \
+ : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \
+ : __stringify(constraint) "r" (i)); \
+ }
+@@ -160,13 +143,12 @@ __ll_sc_atomic64_##op##_return##name(s64 i, atomic64_t *v) \
+ unsigned long tmp; \
+ \
+ asm volatile("// atomic64_" #op "_return" #name "\n" \
+- __LL_SC_FALLBACK( \
+-" prfm pstl1strm, %2\n" \
+-"1: ld" #acq "xr %0, %2\n" \
+-" " #asm_op " %0, %0, %3\n" \
+-" st" #rel "xr %w1, %0, %2\n" \
+-" cbnz %w1, 1b\n" \
+-" " #mb ) \
++ " prfm pstl1strm, %2\n" \
++ "1: ld" #acq "xr %0, %2\n" \
++ " " #asm_op " %0, %0, %3\n" \
++ " st" #rel "xr %w1, %0, %2\n" \
++ " cbnz %w1, 1b\n" \
++ " " #mb \
+ : "=&r" (result), "=&r" (tmp), "+Q" (v->counter) \
+ : __stringify(constraint) "r" (i) \
+ : cl); \
+@@ -176,19 +158,18 @@ __ll_sc_atomic64_##op##_return##name(s64 i, atomic64_t *v) \
+
+ #define ATOMIC64_FETCH_OP(name, mb, acq, rel, cl, op, asm_op, constraint)\
+ static inline long \
+-__ll_sc_atomic64_fetch_##op##name(s64 i, atomic64_t *v) \
++__ll_sc_atomic64_fetch_##op##name(s64 i, atomic64_t *v) \
+ { \
+ s64 result, val; \
+ unsigned long tmp; \
+ \
+ asm volatile("// atomic64_fetch_" #op #name "\n" \
+- __LL_SC_FALLBACK( \
+-" prfm pstl1strm, %3\n" \
+-"1: ld" #acq "xr %0, %3\n" \
+-" " #asm_op " %1, %0, %4\n" \
+-" st" #rel "xr %w2, %1, %3\n" \
+-" cbnz %w2, 1b\n" \
+-" " #mb ) \
++ " prfm pstl1strm, %3\n" \
++ "1: ld" #acq "xr %0, %3\n" \
++ " " #asm_op " %1, %0, %4\n" \
++ " st" #rel "xr %w2, %1, %3\n" \
++ " cbnz %w2, 1b\n" \
++ " " #mb \
+ : "=&r" (result), "=&r" (val), "=&r" (tmp), "+Q" (v->counter) \
+ : __stringify(constraint) "r" (i) \
+ : cl); \
+@@ -240,15 +221,14 @@ __ll_sc_atomic64_dec_if_positive(atomic64_t *v)
+ unsigned long tmp;
+
+ asm volatile("// atomic64_dec_if_positive\n"
+- __LL_SC_FALLBACK(
+-" prfm pstl1strm, %2\n"
+-"1: ldxr %0, %2\n"
+-" subs %0, %0, #1\n"
+-" b.lt 2f\n"
+-" stlxr %w1, %0, %2\n"
+-" cbnz %w1, 1b\n"
+-" dmb ish\n"
+-"2:")
++ " prfm pstl1strm, %2\n"
++ "1: ldxr %0, %2\n"
++ " subs %0, %0, #1\n"
++ " b.lt 2f\n"
++ " stlxr %w1, %0, %2\n"
++ " cbnz %w1, 1b\n"
++ " dmb ish\n"
++ "2:"
+ : "=&r" (result), "=&r" (tmp), "+Q" (v->counter)
+ :
+ : "cc", "memory");
+@@ -274,7 +254,6 @@ __ll_sc__cmpxchg_case_##name##sz(volatile void *ptr, \
+ old = (u##sz)old; \
+ \
+ asm volatile( \
+- __LL_SC_FALLBACK( \
+ " prfm pstl1strm, %[v]\n" \
+ "1: ld" #acq "xr" #sfx "\t%" #w "[oldval], %[v]\n" \
+ " eor %" #w "[tmp], %" #w "[oldval], %" #w "[old]\n" \
+@@ -282,7 +261,7 @@ __ll_sc__cmpxchg_case_##name##sz(volatile void *ptr, \
+ " st" #rel "xr" #sfx "\t%w[tmp], %" #w "[new], %[v]\n" \
+ " cbnz %w[tmp], 1b\n" \
+ " " #mb "\n" \
+- "2:") \
++ "2:" \
+ : [tmp] "=&r" (tmp), [oldval] "=&r" (oldval), \
+ [v] "+Q" (*(u##sz *)ptr) \
+ : [old] __stringify(constraint) "r" (old), [new] "r" (new) \
+@@ -326,7 +305,6 @@ __ll_sc__cmpxchg_double##name(unsigned long old1, \
+ unsigned long tmp, ret; \
+ \
+ asm volatile("// __cmpxchg_double" #name "\n" \
+- __LL_SC_FALLBACK( \
+ " prfm pstl1strm, %2\n" \
+ "1: ldxp %0, %1, %2\n" \
+ " eor %0, %0, %3\n" \
+@@ -336,8 +314,8 @@ __ll_sc__cmpxchg_double##name(unsigned long old1, \
+ " st" #rel "xp %w0, %5, %6, %2\n" \
+ " cbnz %w0, 1b\n" \
+ " " #mb "\n" \
+- "2:") \
+- : "=&r" (tmp), "=&r" (ret), "+Q" (*(unsigned long *)ptr) \
++ "2:" \
++ : "=&r" (tmp), "=&r" (ret), "+Q" (*(__uint128_t *)ptr) \
+ : "r" (old1), "r" (old2), "r" (new1), "r" (new2) \
+ : cl); \
+ \
+diff --git a/arch/arm64/include/asm/atomic_lse.h b/arch/arm64/include/asm/atomic_lse.h
+index da3280f639cd7..28e96118c1e5a 100644
+--- a/arch/arm64/include/asm/atomic_lse.h
++++ b/arch/arm64/include/asm/atomic_lse.h
+@@ -11,11 +11,11 @@
+ #define __ASM_ATOMIC_LSE_H
+
+ #define ATOMIC_OP(op, asm_op) \
+-static inline void __lse_atomic_##op(int i, atomic_t *v) \
++static inline void __lse_atomic_##op(int i, atomic_t *v) \
+ { \
+ asm volatile( \
+ __LSE_PREAMBLE \
+-" " #asm_op " %w[i], %[v]\n" \
++ " " #asm_op " %w[i], %[v]\n" \
+ : [i] "+r" (i), [v] "+Q" (v->counter) \
+ : "r" (v)); \
+ }
+@@ -32,7 +32,7 @@ static inline int __lse_atomic_fetch_##op##name(int i, atomic_t *v) \
+ { \
+ asm volatile( \
+ __LSE_PREAMBLE \
+-" " #asm_op #mb " %w[i], %w[i], %[v]" \
++ " " #asm_op #mb " %w[i], %w[i], %[v]" \
+ : [i] "+r" (i), [v] "+Q" (v->counter) \
+ : "r" (v) \
+ : cl); \
+@@ -130,7 +130,7 @@ static inline int __lse_atomic_sub_return##name(int i, atomic_t *v) \
+ " add %w[i], %w[i], %w[tmp]" \
+ : [i] "+&r" (i), [v] "+Q" (v->counter), [tmp] "=&r" (tmp) \
+ : "r" (v) \
+- : cl); \
++ : cl); \
+ \
+ return i; \
+ }
+@@ -168,7 +168,7 @@ static inline void __lse_atomic64_##op(s64 i, atomic64_t *v) \
+ { \
+ asm volatile( \
+ __LSE_PREAMBLE \
+-" " #asm_op " %[i], %[v]\n" \
++ " " #asm_op " %[i], %[v]\n" \
+ : [i] "+r" (i), [v] "+Q" (v->counter) \
+ : "r" (v)); \
+ }
+@@ -185,7 +185,7 @@ static inline long __lse_atomic64_fetch_##op##name(s64 i, atomic64_t *v)\
+ { \
+ asm volatile( \
+ __LSE_PREAMBLE \
+-" " #asm_op #mb " %[i], %[i], %[v]" \
++ " " #asm_op #mb " %[i], %[i], %[v]" \
+ : [i] "+r" (i), [v] "+Q" (v->counter) \
+ : "r" (v) \
+ : cl); \
+@@ -272,7 +272,7 @@ static inline void __lse_atomic64_sub(s64 i, atomic64_t *v)
+ }
+
+ #define ATOMIC64_OP_SUB_RETURN(name, mb, cl...) \
+-static inline long __lse_atomic64_sub_return##name(s64 i, atomic64_t *v) \
++static inline long __lse_atomic64_sub_return##name(s64 i, atomic64_t *v)\
+ { \
+ unsigned long tmp; \
+ \
+@@ -403,7 +403,7 @@ __lse__cmpxchg_double##name(unsigned long old1, \
+ " eor %[old2], %[old2], %[oldval2]\n" \
+ " orr %[old1], %[old1], %[old2]" \
+ : [old1] "+&r" (x0), [old2] "+&r" (x1), \
+- [v] "+Q" (*(unsigned long *)ptr) \
++ [v] "+Q" (*(__uint128_t *)ptr) \
+ : [new1] "r" (x2), [new2] "r" (x3), [ptr] "r" (x4), \
+ [oldval1] "r" (oldval1), [oldval2] "r" (oldval2) \
+ : cl); \
+diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
+index fd418955e31e6..64f8a90d33277 100644
+--- a/arch/arm64/include/asm/kvm_emulate.h
++++ b/arch/arm64/include/asm/kvm_emulate.h
+@@ -366,8 +366,26 @@ static __always_inline int kvm_vcpu_sys_get_rt(struct kvm_vcpu *vcpu)
+
+ static inline bool kvm_is_write_fault(struct kvm_vcpu *vcpu)
+ {
+- if (kvm_vcpu_abt_iss1tw(vcpu))
+- return true;
++ if (kvm_vcpu_abt_iss1tw(vcpu)) {
++ /*
++ * Only a permission fault on a S1PTW should be
++ * considered as a write. Otherwise, page tables baked
++ * in a read-only memslot will result in an exception
++ * being delivered in the guest.
++ *
++ * The drawback is that we end-up faulting twice if the
++ * guest is using any of HW AF/DB: a translation fault
++ * to map the page containing the PT (read only at
++ * first), then a permission fault to allow the flags
++ * to be set.
++ */
++ switch (kvm_vcpu_trap_get_fault_type(vcpu)) {
++ case ESR_ELx_FSC_PERM:
++ return true;
++ default:
++ return false;
++ }
++ }
+
+ if (kvm_vcpu_trap_is_iabt(vcpu))
+ return false;
+diff --git a/arch/arm64/kvm/hyp/nvhe/Makefile b/arch/arm64/kvm/hyp/nvhe/Makefile
+index 8d741f71377f4..964c2134ea1e5 100644
+--- a/arch/arm64/kvm/hyp/nvhe/Makefile
++++ b/arch/arm64/kvm/hyp/nvhe/Makefile
+@@ -83,6 +83,10 @@ quiet_cmd_hypcopy = HYPCOPY $@
+ # Remove ftrace, Shadow Call Stack, and CFI CFLAGS.
+ # This is equivalent to the 'notrace', '__noscs', and '__nocfi' annotations.
+ KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_FTRACE) $(CC_FLAGS_SCS) $(CC_FLAGS_CFI), $(KBUILD_CFLAGS))
++# Starting from 13.0.0 llvm emits SHT_REL section '.llvm.call-graph-profile'
++# when profile optimization is applied. gen-hyprel does not support SHT_REL and
++# causes a build failure. Remove profile optimization flags.
++KBUILD_CFLAGS := $(filter-out -fprofile-sample-use=% -fprofile-use=%, $(KBUILD_CFLAGS))
+
+ # KVM nVHE code is run at a different exception code with a different map, so
+ # compiler instrumentation that inserts callbacks or checks into the code may
+diff --git a/arch/powerpc/include/asm/imc-pmu.h b/arch/powerpc/include/asm/imc-pmu.h
+index 4f897993b7107..699a88584ae16 100644
+--- a/arch/powerpc/include/asm/imc-pmu.h
++++ b/arch/powerpc/include/asm/imc-pmu.h
+@@ -137,7 +137,7 @@ struct imc_pmu {
+ * are inited.
+ */
+ struct imc_pmu_ref {
+- struct mutex lock;
++ spinlock_t lock;
+ unsigned int id;
+ int refc;
+ };
+diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c
+index e7583fbcc8fa1..6ec93eec03ea2 100644
+--- a/arch/powerpc/perf/imc-pmu.c
++++ b/arch/powerpc/perf/imc-pmu.c
+@@ -13,6 +13,7 @@
+ #include <asm/cputhreads.h>
+ #include <asm/smp.h>
+ #include <linux/string.h>
++#include <linux/spinlock.h>
+
+ /* Nest IMC data structures and variables */
+
+@@ -20,7 +21,7 @@
+ * Used to avoid races in counting the nest-pmu units during hotplug
+ * register and unregister
+ */
+-static DEFINE_MUTEX(nest_init_lock);
++static DEFINE_SPINLOCK(nest_init_lock);
+ static DEFINE_PER_CPU(struct imc_pmu_ref *, local_nest_imc_refc);
+ static struct imc_pmu **per_nest_pmu_arr;
+ static cpumask_t nest_imc_cpumask;
+@@ -49,7 +50,7 @@ static int trace_imc_mem_size;
+ * core and trace-imc
+ */
+ static struct imc_pmu_ref imc_global_refc = {
+- .lock = __MUTEX_INITIALIZER(imc_global_refc.lock),
++ .lock = __SPIN_LOCK_INITIALIZER(imc_global_refc.lock),
+ .id = 0,
+ .refc = 0,
+ };
+@@ -393,7 +394,7 @@ static int ppc_nest_imc_cpu_offline(unsigned int cpu)
+ get_hard_smp_processor_id(cpu));
+ /*
+ * If this is the last cpu in this chip then, skip the reference
+- * count mutex lock and make the reference count on this chip zero.
++ * count lock and make the reference count on this chip zero.
+ */
+ ref = get_nest_pmu_ref(cpu);
+ if (!ref)
+@@ -455,15 +456,15 @@ static void nest_imc_counters_release(struct perf_event *event)
+ /*
+ * See if we need to disable the nest PMU.
+ * If no events are currently in use, then we have to take a
+- * mutex to ensure that we don't race with another task doing
++ * lock to ensure that we don't race with another task doing
+ * enable or disable the nest counters.
+ */
+ ref = get_nest_pmu_ref(event->cpu);
+ if (!ref)
+ return;
+
+- /* Take the mutex lock for this node and then decrement the reference count */
+- mutex_lock(&ref->lock);
++ /* Take the lock for this node and then decrement the reference count */
++ spin_lock(&ref->lock);
+ if (ref->refc == 0) {
+ /*
+ * The scenario where this is true is, when perf session is
+@@ -475,7 +476,7 @@ static void nest_imc_counters_release(struct perf_event *event)
+ * an OPAL call to disable the engine in that node.
+ *
+ */
+- mutex_unlock(&ref->lock);
++ spin_unlock(&ref->lock);
+ return;
+ }
+ ref->refc--;
+@@ -483,7 +484,7 @@ static void nest_imc_counters_release(struct perf_event *event)
+ rc = opal_imc_counters_stop(OPAL_IMC_COUNTERS_NEST,
+ get_hard_smp_processor_id(event->cpu));
+ if (rc) {
+- mutex_unlock(&ref->lock);
++ spin_unlock(&ref->lock);
+ pr_err("nest-imc: Unable to stop the counters for core %d\n", node_id);
+ return;
+ }
+@@ -491,7 +492,7 @@ static void nest_imc_counters_release(struct perf_event *event)
+ WARN(1, "nest-imc: Invalid event reference count\n");
+ ref->refc = 0;
+ }
+- mutex_unlock(&ref->lock);
++ spin_unlock(&ref->lock);
+ }
+
+ static int nest_imc_event_init(struct perf_event *event)
+@@ -550,26 +551,25 @@ static int nest_imc_event_init(struct perf_event *event)
+
+ /*
+ * Get the imc_pmu_ref struct for this node.
+- * Take the mutex lock and then increment the count of nest pmu events
+- * inited.
++ * Take the lock and then increment the count of nest pmu events inited.
+ */
+ ref = get_nest_pmu_ref(event->cpu);
+ if (!ref)
+ return -EINVAL;
+
+- mutex_lock(&ref->lock);
++ spin_lock(&ref->lock);
+ if (ref->refc == 0) {
+ rc = opal_imc_counters_start(OPAL_IMC_COUNTERS_NEST,
+ get_hard_smp_processor_id(event->cpu));
+ if (rc) {
+- mutex_unlock(&ref->lock);
++ spin_unlock(&ref->lock);
+ pr_err("nest-imc: Unable to start the counters for node %d\n",
+ node_id);
+ return rc;
+ }
+ }
+ ++ref->refc;
+- mutex_unlock(&ref->lock);
++ spin_unlock(&ref->lock);
+
+ event->destroy = nest_imc_counters_release;
+ return 0;
+@@ -605,9 +605,8 @@ static int core_imc_mem_init(int cpu, int size)
+ return -ENOMEM;
+ mem_info->vbase = page_address(page);
+
+- /* Init the mutex */
+ core_imc_refc[core_id].id = core_id;
+- mutex_init(&core_imc_refc[core_id].lock);
++ spin_lock_init(&core_imc_refc[core_id].lock);
+
+ rc = opal_imc_counters_init(OPAL_IMC_COUNTERS_CORE,
+ __pa((void *)mem_info->vbase),
+@@ -696,9 +695,8 @@ static int ppc_core_imc_cpu_offline(unsigned int cpu)
+ perf_pmu_migrate_context(&core_imc_pmu->pmu, cpu, ncpu);
+ } else {
+ /*
+- * If this is the last cpu in this core then, skip taking refernce
+- * count mutex lock for this core and directly zero "refc" for
+- * this core.
++ * If this is the last cpu in this core then skip taking reference
++ * count lock for this core and directly zero "refc" for this core.
+ */
+ opal_imc_counters_stop(OPAL_IMC_COUNTERS_CORE,
+ get_hard_smp_processor_id(cpu));
+@@ -713,11 +711,11 @@ static int ppc_core_imc_cpu_offline(unsigned int cpu)
+ * last cpu in this core and core-imc event running
+ * in this cpu.
+ */
+- mutex_lock(&imc_global_refc.lock);
++ spin_lock(&imc_global_refc.lock);
+ if (imc_global_refc.id == IMC_DOMAIN_CORE)
+ imc_global_refc.refc--;
+
+- mutex_unlock(&imc_global_refc.lock);
++ spin_unlock(&imc_global_refc.lock);
+ }
+ return 0;
+ }
+@@ -732,7 +730,7 @@ static int core_imc_pmu_cpumask_init(void)
+
+ static void reset_global_refc(struct perf_event *event)
+ {
+- mutex_lock(&imc_global_refc.lock);
++ spin_lock(&imc_global_refc.lock);
+ imc_global_refc.refc--;
+
+ /*
+@@ -744,7 +742,7 @@ static void reset_global_refc(struct perf_event *event)
+ imc_global_refc.refc = 0;
+ imc_global_refc.id = 0;
+ }
+- mutex_unlock(&imc_global_refc.lock);
++ spin_unlock(&imc_global_refc.lock);
+ }
+
+ static void core_imc_counters_release(struct perf_event *event)
+@@ -757,17 +755,17 @@ static void core_imc_counters_release(struct perf_event *event)
+ /*
+ * See if we need to disable the IMC PMU.
+ * If no events are currently in use, then we have to take a
+- * mutex to ensure that we don't race with another task doing
++ * lock to ensure that we don't race with another task doing
+ * enable or disable the core counters.
+ */
+ core_id = event->cpu / threads_per_core;
+
+- /* Take the mutex lock and decrement the refernce count for this core */
++ /* Take the lock and decrement the refernce count for this core */
+ ref = &core_imc_refc[core_id];
+ if (!ref)
+ return;
+
+- mutex_lock(&ref->lock);
++ spin_lock(&ref->lock);
+ if (ref->refc == 0) {
+ /*
+ * The scenario where this is true is, when perf session is
+@@ -779,7 +777,7 @@ static void core_imc_counters_release(struct perf_event *event)
+ * an OPAL call to disable the engine in that core.
+ *
+ */
+- mutex_unlock(&ref->lock);
++ spin_unlock(&ref->lock);
+ return;
+ }
+ ref->refc--;
+@@ -787,7 +785,7 @@ static void core_imc_counters_release(struct perf_event *event)
+ rc = opal_imc_counters_stop(OPAL_IMC_COUNTERS_CORE,
+ get_hard_smp_processor_id(event->cpu));
+ if (rc) {
+- mutex_unlock(&ref->lock);
++ spin_unlock(&ref->lock);
+ pr_err("IMC: Unable to stop the counters for core %d\n", core_id);
+ return;
+ }
+@@ -795,7 +793,7 @@ static void core_imc_counters_release(struct perf_event *event)
+ WARN(1, "core-imc: Invalid event reference count\n");
+ ref->refc = 0;
+ }
+- mutex_unlock(&ref->lock);
++ spin_unlock(&ref->lock);
+
+ reset_global_refc(event);
+ }
+@@ -833,7 +831,6 @@ static int core_imc_event_init(struct perf_event *event)
+ if ((!pcmi->vbase))
+ return -ENODEV;
+
+- /* Get the core_imc mutex for this core */
+ ref = &core_imc_refc[core_id];
+ if (!ref)
+ return -EINVAL;
+@@ -841,22 +838,22 @@ static int core_imc_event_init(struct perf_event *event)
+ /*
+ * Core pmu units are enabled only when it is used.
+ * See if this is triggered for the first time.
+- * If yes, take the mutex lock and enable the core counters.
++ * If yes, take the lock and enable the core counters.
+ * If not, just increment the count in core_imc_refc struct.
+ */
+- mutex_lock(&ref->lock);
++ spin_lock(&ref->lock);
+ if (ref->refc == 0) {
+ rc = opal_imc_counters_start(OPAL_IMC_COUNTERS_CORE,
+ get_hard_smp_processor_id(event->cpu));
+ if (rc) {
+- mutex_unlock(&ref->lock);
++ spin_unlock(&ref->lock);
+ pr_err("core-imc: Unable to start the counters for core %d\n",
+ core_id);
+ return rc;
+ }
+ }
+ ++ref->refc;
+- mutex_unlock(&ref->lock);
++ spin_unlock(&ref->lock);
+
+ /*
+ * Since the system can run either in accumulation or trace-mode
+@@ -867,7 +864,7 @@ static int core_imc_event_init(struct perf_event *event)
+ * to know whether any other trace/thread imc
+ * events are running.
+ */
+- mutex_lock(&imc_global_refc.lock);
++ spin_lock(&imc_global_refc.lock);
+ if (imc_global_refc.id == 0 || imc_global_refc.id == IMC_DOMAIN_CORE) {
+ /*
+ * No other trace/thread imc events are running in
+@@ -876,10 +873,10 @@ static int core_imc_event_init(struct perf_event *event)
+ imc_global_refc.id = IMC_DOMAIN_CORE;
+ imc_global_refc.refc++;
+ } else {
+- mutex_unlock(&imc_global_refc.lock);
++ spin_unlock(&imc_global_refc.lock);
+ return -EBUSY;
+ }
+- mutex_unlock(&imc_global_refc.lock);
++ spin_unlock(&imc_global_refc.lock);
+
+ event->hw.event_base = (u64)pcmi->vbase + (config & IMC_EVENT_OFFSET_MASK);
+ event->destroy = core_imc_counters_release;
+@@ -951,10 +948,10 @@ static int ppc_thread_imc_cpu_offline(unsigned int cpu)
+ mtspr(SPRN_LDBAR, (mfspr(SPRN_LDBAR) & (~(1UL << 63))));
+
+ /* Reduce the refc if thread-imc event running on this cpu */
+- mutex_lock(&imc_global_refc.lock);
++ spin_lock(&imc_global_refc.lock);
+ if (imc_global_refc.id == IMC_DOMAIN_THREAD)
+ imc_global_refc.refc--;
+- mutex_unlock(&imc_global_refc.lock);
++ spin_unlock(&imc_global_refc.lock);
+
+ return 0;
+ }
+@@ -994,7 +991,7 @@ static int thread_imc_event_init(struct perf_event *event)
+ if (!target)
+ return -EINVAL;
+
+- mutex_lock(&imc_global_refc.lock);
++ spin_lock(&imc_global_refc.lock);
+ /*
+ * Check if any other trace/core imc events are running in the
+ * system, if not set the global id to thread-imc.
+@@ -1003,10 +1000,10 @@ static int thread_imc_event_init(struct perf_event *event)
+ imc_global_refc.id = IMC_DOMAIN_THREAD;
+ imc_global_refc.refc++;
+ } else {
+- mutex_unlock(&imc_global_refc.lock);
++ spin_unlock(&imc_global_refc.lock);
+ return -EBUSY;
+ }
+- mutex_unlock(&imc_global_refc.lock);
++ spin_unlock(&imc_global_refc.lock);
+
+ event->pmu->task_ctx_nr = perf_sw_context;
+ event->destroy = reset_global_refc;
+@@ -1128,25 +1125,25 @@ static int thread_imc_event_add(struct perf_event *event, int flags)
+ /*
+ * imc pmus are enabled only when it is used.
+ * See if this is triggered for the first time.
+- * If yes, take the mutex lock and enable the counters.
++ * If yes, take the lock and enable the counters.
+ * If not, just increment the count in ref count struct.
+ */
+ ref = &core_imc_refc[core_id];
+ if (!ref)
+ return -EINVAL;
+
+- mutex_lock(&ref->lock);
++ spin_lock(&ref->lock);
+ if (ref->refc == 0) {
+ if (opal_imc_counters_start(OPAL_IMC_COUNTERS_CORE,
+ get_hard_smp_processor_id(smp_processor_id()))) {
+- mutex_unlock(&ref->lock);
++ spin_unlock(&ref->lock);
+ pr_err("thread-imc: Unable to start the counter\
+ for core %d\n", core_id);
+ return -EINVAL;
+ }
+ }
+ ++ref->refc;
+- mutex_unlock(&ref->lock);
++ spin_unlock(&ref->lock);
+ return 0;
+ }
+
+@@ -1163,12 +1160,12 @@ static void thread_imc_event_del(struct perf_event *event, int flags)
+ return;
+ }
+
+- mutex_lock(&ref->lock);
++ spin_lock(&ref->lock);
+ ref->refc--;
+ if (ref->refc == 0) {
+ if (opal_imc_counters_stop(OPAL_IMC_COUNTERS_CORE,
+ get_hard_smp_processor_id(smp_processor_id()))) {
+- mutex_unlock(&ref->lock);
++ spin_unlock(&ref->lock);
+ pr_err("thread-imc: Unable to stop the counters\
+ for core %d\n", core_id);
+ return;
+@@ -1176,7 +1173,7 @@ static void thread_imc_event_del(struct perf_event *event, int flags)
+ } else if (ref->refc < 0) {
+ ref->refc = 0;
+ }
+- mutex_unlock(&ref->lock);
++ spin_unlock(&ref->lock);
+
+ /* Set bit 0 of LDBAR to zero, to stop posting updates to memory */
+ mtspr(SPRN_LDBAR, (mfspr(SPRN_LDBAR) & (~(1UL << 63))));
+@@ -1217,9 +1214,8 @@ static int trace_imc_mem_alloc(int cpu_id, int size)
+ }
+ }
+
+- /* Init the mutex, if not already */
+ trace_imc_refc[core_id].id = core_id;
+- mutex_init(&trace_imc_refc[core_id].lock);
++ spin_lock_init(&trace_imc_refc[core_id].lock);
+
+ mtspr(SPRN_LDBAR, 0);
+ return 0;
+@@ -1239,10 +1235,10 @@ static int ppc_trace_imc_cpu_offline(unsigned int cpu)
+ * Reduce the refc if any trace-imc event running
+ * on this cpu.
+ */
+- mutex_lock(&imc_global_refc.lock);
++ spin_lock(&imc_global_refc.lock);
+ if (imc_global_refc.id == IMC_DOMAIN_TRACE)
+ imc_global_refc.refc--;
+- mutex_unlock(&imc_global_refc.lock);
++ spin_unlock(&imc_global_refc.lock);
+
+ return 0;
+ }
+@@ -1364,17 +1360,17 @@ static int trace_imc_event_add(struct perf_event *event, int flags)
+ }
+
+ mtspr(SPRN_LDBAR, ldbar_value);
+- mutex_lock(&ref->lock);
++ spin_lock(&ref->lock);
+ if (ref->refc == 0) {
+ if (opal_imc_counters_start(OPAL_IMC_COUNTERS_TRACE,
+ get_hard_smp_processor_id(smp_processor_id()))) {
+- mutex_unlock(&ref->lock);
++ spin_unlock(&ref->lock);
+ pr_err("trace-imc: Unable to start the counters for core %d\n", core_id);
+ return -EINVAL;
+ }
+ }
+ ++ref->refc;
+- mutex_unlock(&ref->lock);
++ spin_unlock(&ref->lock);
+ return 0;
+ }
+
+@@ -1407,19 +1403,19 @@ static void trace_imc_event_del(struct perf_event *event, int flags)
+ return;
+ }
+
+- mutex_lock(&ref->lock);
++ spin_lock(&ref->lock);
+ ref->refc--;
+ if (ref->refc == 0) {
+ if (opal_imc_counters_stop(OPAL_IMC_COUNTERS_TRACE,
+ get_hard_smp_processor_id(smp_processor_id()))) {
+- mutex_unlock(&ref->lock);
++ spin_unlock(&ref->lock);
+ pr_err("trace-imc: Unable to stop the counters for core %d\n", core_id);
+ return;
+ }
+ } else if (ref->refc < 0) {
+ ref->refc = 0;
+ }
+- mutex_unlock(&ref->lock);
++ spin_unlock(&ref->lock);
+
+ trace_imc_event_stop(event, flags);
+ }
+@@ -1441,7 +1437,7 @@ static int trace_imc_event_init(struct perf_event *event)
+ * no other thread is running any core/thread imc
+ * events
+ */
+- mutex_lock(&imc_global_refc.lock);
++ spin_lock(&imc_global_refc.lock);
+ if (imc_global_refc.id == 0 || imc_global_refc.id == IMC_DOMAIN_TRACE) {
+ /*
+ * No core/thread imc events are running in the
+@@ -1450,10 +1446,10 @@ static int trace_imc_event_init(struct perf_event *event)
+ imc_global_refc.id = IMC_DOMAIN_TRACE;
+ imc_global_refc.refc++;
+ } else {
+- mutex_unlock(&imc_global_refc.lock);
++ spin_unlock(&imc_global_refc.lock);
+ return -EBUSY;
+ }
+- mutex_unlock(&imc_global_refc.lock);
++ spin_unlock(&imc_global_refc.lock);
+
+ event->hw.idx = -1;
+
+@@ -1526,10 +1522,10 @@ static int init_nest_pmu_ref(void)
+ i = 0;
+ for_each_node(nid) {
+ /*
+- * Mutex lock to avoid races while tracking the number of
++ * Take the lock to avoid races while tracking the number of
+ * sessions using the chip's nest pmu units.
+ */
+- mutex_init(&nest_imc_refc[i].lock);
++ spin_lock_init(&nest_imc_refc[i].lock);
+
+ /*
+ * Loop to init the "id" with the node_id. Variable "i" initialized to
+@@ -1626,7 +1622,7 @@ static void imc_common_mem_free(struct imc_pmu *pmu_ptr)
+ static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr)
+ {
+ if (pmu_ptr->domain == IMC_DOMAIN_NEST) {
+- mutex_lock(&nest_init_lock);
++ spin_lock(&nest_init_lock);
+ if (nest_pmus == 1) {
+ cpuhp_remove_state(CPUHP_AP_PERF_POWERPC_NEST_IMC_ONLINE);
+ kfree(nest_imc_refc);
+@@ -1636,7 +1632,7 @@ static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr)
+
+ if (nest_pmus > 0)
+ nest_pmus--;
+- mutex_unlock(&nest_init_lock);
++ spin_unlock(&nest_init_lock);
+ }
+
+ /* Free core_imc memory */
+@@ -1793,11 +1789,11 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
+ * rest. To handle the cpuhotplug callback unregister, we track
+ * the number of nest pmus in "nest_pmus".
+ */
+- mutex_lock(&nest_init_lock);
++ spin_lock(&nest_init_lock);
+ if (nest_pmus == 0) {
+ ret = init_nest_pmu_ref();
+ if (ret) {
+- mutex_unlock(&nest_init_lock);
++ spin_unlock(&nest_init_lock);
+ kfree(per_nest_pmu_arr);
+ per_nest_pmu_arr = NULL;
+ goto err_free_mem;
+@@ -1805,7 +1801,7 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
+ /* Register for cpu hotplug notification. */
+ ret = nest_pmu_cpumask_init();
+ if (ret) {
+- mutex_unlock(&nest_init_lock);
++ spin_unlock(&nest_init_lock);
+ kfree(nest_imc_refc);
+ kfree(per_nest_pmu_arr);
+ per_nest_pmu_arr = NULL;
+@@ -1813,7 +1809,7 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
+ }
+ }
+ nest_pmus++;
+- mutex_unlock(&nest_init_lock);
++ spin_unlock(&nest_init_lock);
+ break;
+ case IMC_DOMAIN_CORE:
+ ret = core_imc_pmu_cpumask_init();
+diff --git a/arch/s390/include/asm/cpu_mf.h b/arch/s390/include/asm/cpu_mf.h
+index 0d90cbeb89b43..a0914bc6c9bdd 100644
+--- a/arch/s390/include/asm/cpu_mf.h
++++ b/arch/s390/include/asm/cpu_mf.h
+@@ -128,19 +128,21 @@ struct hws_combined_entry {
+ struct hws_diag_entry diag; /* Diagnostic-sampling data entry */
+ } __packed;
+
+-struct hws_trailer_entry {
+- union {
+- struct {
+- unsigned int f:1; /* 0 - Block Full Indicator */
+- unsigned int a:1; /* 1 - Alert request control */
+- unsigned int t:1; /* 2 - Timestamp format */
+- unsigned int :29; /* 3 - 31: Reserved */
+- unsigned int bsdes:16; /* 32-47: size of basic SDE */
+- unsigned int dsdes:16; /* 48-63: size of diagnostic SDE */
+- };
+- unsigned long long flags; /* 0 - 63: All indicators */
++union hws_trailer_header {
++ struct {
++ unsigned int f:1; /* 0 - Block Full Indicator */
++ unsigned int a:1; /* 1 - Alert request control */
++ unsigned int t:1; /* 2 - Timestamp format */
++ unsigned int :29; /* 3 - 31: Reserved */
++ unsigned int bsdes:16; /* 32-47: size of basic SDE */
++ unsigned int dsdes:16; /* 48-63: size of diagnostic SDE */
++ unsigned long long overflow; /* 64 - Overflow Count */
+ };
+- unsigned long long overflow; /* 64 - sample Overflow count */
++ __uint128_t val;
++};
++
++struct hws_trailer_entry {
++ union hws_trailer_header header; /* 0 - 15 Flags + Overflow Count */
+ unsigned char timestamp[16]; /* 16 - 31 timestamp */
+ unsigned long long reserved1; /* 32 -Reserved */
+ unsigned long long reserved2; /* */
+@@ -287,14 +289,11 @@ static inline unsigned long sample_rate_to_freq(struct hws_qsi_info_block *qsi,
+ return USEC_PER_SEC * qsi->cpu_speed / rate;
+ }
+
+-#define SDB_TE_ALERT_REQ_MASK 0x4000000000000000UL
+-#define SDB_TE_BUFFER_FULL_MASK 0x8000000000000000UL
+-
+ /* Return TOD timestamp contained in an trailer entry */
+ static inline unsigned long long trailer_timestamp(struct hws_trailer_entry *te)
+ {
+ /* TOD in STCKE format */
+- if (te->t)
++ if (te->header.t)
+ return *((unsigned long long *) &te->timestamp[1]);
+
+ /* TOD in STCK format */
+diff --git a/arch/s390/include/asm/percpu.h b/arch/s390/include/asm/percpu.h
+index cb5fc06904354..081837b391e35 100644
+--- a/arch/s390/include/asm/percpu.h
++++ b/arch/s390/include/asm/percpu.h
+@@ -31,7 +31,7 @@
+ pcp_op_T__ *ptr__; \
+ preempt_disable_notrace(); \
+ ptr__ = raw_cpu_ptr(&(pcp)); \
+- prev__ = *ptr__; \
++ prev__ = READ_ONCE(*ptr__); \
+ do { \
+ old__ = prev__; \
+ new__ = old__ op (val); \
+diff --git a/arch/s390/kernel/machine_kexec_file.c b/arch/s390/kernel/machine_kexec_file.c
+index 3459362c54ac3..c7fd818512890 100644
+--- a/arch/s390/kernel/machine_kexec_file.c
++++ b/arch/s390/kernel/machine_kexec_file.c
+@@ -185,8 +185,6 @@ static int kexec_file_add_ipl_report(struct kimage *image,
+
+ data->memsz = ALIGN(data->memsz, PAGE_SIZE);
+ buf.mem = data->memsz;
+- if (image->type == KEXEC_TYPE_CRASH)
+- buf.mem += crashk_res.start;
+
+ ptr = (void *)ipl_cert_list_addr;
+ end = ptr + ipl_cert_list_size;
+@@ -223,6 +221,9 @@ static int kexec_file_add_ipl_report(struct kimage *image,
+ data->kernel_buf + offsetof(struct lowcore, ipl_parmblock_ptr);
+ *lc_ipl_parmblock_ptr = (__u32)buf.mem;
+
++ if (image->type == KEXEC_TYPE_CRASH)
++ buf.mem += crashk_res.start;
++
+ ret = kexec_add_buffer(&buf);
+ out:
+ return ret;
+diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c
+index db62def4ef28e..4e6fadaeaa1a6 100644
+--- a/arch/s390/kernel/perf_cpum_sf.c
++++ b/arch/s390/kernel/perf_cpum_sf.c
+@@ -163,14 +163,15 @@ static void free_sampling_buffer(struct sf_buffer *sfb)
+
+ static int alloc_sample_data_block(unsigned long *sdbt, gfp_t gfp_flags)
+ {
+- unsigned long sdb, *trailer;
++ struct hws_trailer_entry *te;
++ unsigned long sdb;
+
+ /* Allocate and initialize sample-data-block */
+ sdb = get_zeroed_page(gfp_flags);
+ if (!sdb)
+ return -ENOMEM;
+- trailer = trailer_entry_ptr(sdb);
+- *trailer = SDB_TE_ALERT_REQ_MASK;
++ te = (struct hws_trailer_entry *)trailer_entry_ptr(sdb);
++ te->header.a = 1;
+
+ /* Link SDB into the sample-data-block-table */
+ *sdbt = sdb;
+@@ -1206,7 +1207,7 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt,
+ "%s: Found unknown"
+ " sampling data entry: te->f %i"
+ " basic.def %#4x (%p)\n", __func__,
+- te->f, sample->def, sample);
++ te->header.f, sample->def, sample);
+ /* Sample slot is not yet written or other record.
+ *
+ * This condition can occur if the buffer was reused
+@@ -1217,7 +1218,7 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt,
+ * that are not full. Stop processing if the first
+ * invalid format was detected.
+ */
+- if (!te->f)
++ if (!te->header.f)
+ break;
+ }
+
+@@ -1227,6 +1228,16 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt,
+ }
+ }
+
++static inline __uint128_t __cdsg(__uint128_t *ptr, __uint128_t old, __uint128_t new)
++{
++ asm volatile(
++ " cdsg %[old],%[new],%[ptr]\n"
++ : [old] "+d" (old), [ptr] "+QS" (*ptr)
++ : [new] "d" (new)
++ : "memory", "cc");
++ return old;
++}
++
+ /* hw_perf_event_update() - Process sampling buffer
+ * @event: The perf event
+ * @flush_all: Flag to also flush partially filled sample-data-blocks
+@@ -1243,10 +1254,11 @@ static void hw_collect_samples(struct perf_event *event, unsigned long *sdbt,
+ */
+ static void hw_perf_event_update(struct perf_event *event, int flush_all)
+ {
++ unsigned long long event_overflow, sampl_overflow, num_sdb;
++ union hws_trailer_header old, prev, new;
+ struct hw_perf_event *hwc = &event->hw;
+ struct hws_trailer_entry *te;
+ unsigned long *sdbt;
+- unsigned long long event_overflow, sampl_overflow, num_sdb, te_flags;
+ int done;
+
+ /*
+@@ -1266,25 +1278,25 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all)
+ te = (struct hws_trailer_entry *) trailer_entry_ptr(*sdbt);
+
+ /* Leave loop if no more work to do (block full indicator) */
+- if (!te->f) {
++ if (!te->header.f) {
+ done = 1;
+ if (!flush_all)
+ break;
+ }
+
+ /* Check the sample overflow count */
+- if (te->overflow)
++ if (te->header.overflow)
+ /* Account sample overflows and, if a particular limit
+ * is reached, extend the sampling buffer.
+ * For details, see sfb_account_overflows().
+ */
+- sampl_overflow += te->overflow;
++ sampl_overflow += te->header.overflow;
+
+ /* Timestamps are valid for full sample-data-blocks only */
+ debug_sprintf_event(sfdbg, 6, "%s: sdbt %#lx "
+ "overflow %llu timestamp %#llx\n",
+- __func__, (unsigned long)sdbt, te->overflow,
+- (te->f) ? trailer_timestamp(te) : 0ULL);
++ __func__, (unsigned long)sdbt, te->header.overflow,
++ (te->header.f) ? trailer_timestamp(te) : 0ULL);
+
+ /* Collect all samples from a single sample-data-block and
+ * flag if an (perf) event overflow happened. If so, the PMU
+@@ -1294,12 +1306,16 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all)
+ num_sdb++;
+
+ /* Reset trailer (using compare-double-and-swap) */
++ /* READ_ONCE() 16 byte header */
++ prev.val = __cdsg(&te->header.val, 0, 0);
+ do {
+- te_flags = te->flags & ~SDB_TE_BUFFER_FULL_MASK;
+- te_flags |= SDB_TE_ALERT_REQ_MASK;
+- } while (!cmpxchg_double(&te->flags, &te->overflow,
+- te->flags, te->overflow,
+- te_flags, 0ULL));
++ old.val = prev.val;
++ new.val = prev.val;
++ new.f = 0;
++ new.a = 1;
++ new.overflow = 0;
++ prev.val = __cdsg(&te->header.val, old.val, new.val);
++ } while (prev.val != old.val);
+
+ /* Advance to next sample-data-block */
+ sdbt++;
+@@ -1384,7 +1400,7 @@ static void aux_output_end(struct perf_output_handle *handle)
+ range_scan = AUX_SDB_NUM_ALERT(aux);
+ for (i = 0, idx = aux->head; i < range_scan; i++, idx++) {
+ te = aux_sdb_trailer(aux, idx);
+- if (!(te->flags & SDB_TE_BUFFER_FULL_MASK))
++ if (!te->header.f)
+ break;
+ }
+ /* i is num of SDBs which are full */
+@@ -1392,7 +1408,7 @@ static void aux_output_end(struct perf_output_handle *handle)
+
+ /* Remove alert indicators in the buffer */
+ te = aux_sdb_trailer(aux, aux->alert_mark);
+- te->flags &= ~SDB_TE_ALERT_REQ_MASK;
++ te->header.a = 0;
+
+ debug_sprintf_event(sfdbg, 6, "%s: SDBs %ld range %ld head %ld\n",
+ __func__, i, range_scan, aux->head);
+@@ -1437,9 +1453,9 @@ static int aux_output_begin(struct perf_output_handle *handle,
+ idx = aux->empty_mark + 1;
+ for (i = 0; i < range_scan; i++, idx++) {
+ te = aux_sdb_trailer(aux, idx);
+- te->flags &= ~(SDB_TE_BUFFER_FULL_MASK |
+- SDB_TE_ALERT_REQ_MASK);
+- te->overflow = 0;
++ te->header.f = 0;
++ te->header.a = 0;
++ te->header.overflow = 0;
+ }
+ /* Save the position of empty SDBs */
+ aux->empty_mark = aux->head + range - 1;
+@@ -1448,7 +1464,7 @@ static int aux_output_begin(struct perf_output_handle *handle,
+ /* Set alert indicator */
+ aux->alert_mark = aux->head + range/2 - 1;
+ te = aux_sdb_trailer(aux, aux->alert_mark);
+- te->flags = te->flags | SDB_TE_ALERT_REQ_MASK;
++ te->header.a = 1;
+
+ /* Reset hardware buffer head */
+ head = AUX_SDB_INDEX(aux, aux->head);
+@@ -1475,14 +1491,17 @@ static int aux_output_begin(struct perf_output_handle *handle,
+ static bool aux_set_alert(struct aux_buffer *aux, unsigned long alert_index,
+ unsigned long long *overflow)
+ {
+- unsigned long long orig_overflow, orig_flags, new_flags;
++ union hws_trailer_header old, prev, new;
+ struct hws_trailer_entry *te;
+
+ te = aux_sdb_trailer(aux, alert_index);
++ /* READ_ONCE() 16 byte header */
++ prev.val = __cdsg(&te->header.val, 0, 0);
+ do {
+- orig_flags = te->flags;
+- *overflow = orig_overflow = te->overflow;
+- if (orig_flags & SDB_TE_BUFFER_FULL_MASK) {
++ old.val = prev.val;
++ new.val = prev.val;
++ *overflow = old.overflow;
++ if (old.f) {
+ /*
+ * SDB is already set by hardware.
+ * Abort and try to set somewhere
+@@ -1490,10 +1509,10 @@ static bool aux_set_alert(struct aux_buffer *aux, unsigned long alert_index,
+ */
+ return false;
+ }
+- new_flags = orig_flags | SDB_TE_ALERT_REQ_MASK;
+- } while (!cmpxchg_double(&te->flags, &te->overflow,
+- orig_flags, orig_overflow,
+- new_flags, 0ULL));
++ new.a = 1;
++ new.overflow = 0;
++ prev.val = __cdsg(&te->header.val, old.val, new.val);
++ } while (prev.val != old.val);
+ return true;
+ }
+
+@@ -1522,8 +1541,9 @@ static bool aux_set_alert(struct aux_buffer *aux, unsigned long alert_index,
+ static bool aux_reset_buffer(struct aux_buffer *aux, unsigned long range,
+ unsigned long long *overflow)
+ {
+- unsigned long long orig_overflow, orig_flags, new_flags;
+ unsigned long i, range_scan, idx, idx_old;
++ union hws_trailer_header old, prev, new;
++ unsigned long long orig_overflow;
+ struct hws_trailer_entry *te;
+
+ debug_sprintf_event(sfdbg, 6, "%s: range %ld head %ld alert %ld "
+@@ -1554,17 +1574,20 @@ static bool aux_reset_buffer(struct aux_buffer *aux, unsigned long range,
+ idx_old = idx = aux->empty_mark + 1;
+ for (i = 0; i < range_scan; i++, idx++) {
+ te = aux_sdb_trailer(aux, idx);
++ /* READ_ONCE() 16 byte header */
++ prev.val = __cdsg(&te->header.val, 0, 0);
+ do {
+- orig_flags = te->flags;
+- orig_overflow = te->overflow;
+- new_flags = orig_flags & ~SDB_TE_BUFFER_FULL_MASK;
++ old.val = prev.val;
++ new.val = prev.val;
++ orig_overflow = old.overflow;
++ new.f = 0;
++ new.overflow = 0;
+ if (idx == aux->alert_mark)
+- new_flags |= SDB_TE_ALERT_REQ_MASK;
++ new.a = 1;
+ else
+- new_flags &= ~SDB_TE_ALERT_REQ_MASK;
+- } while (!cmpxchg_double(&te->flags, &te->overflow,
+- orig_flags, orig_overflow,
+- new_flags, 0ULL));
++ new.a = 0;
++ prev.val = __cdsg(&te->header.val, old.val, new.val);
++ } while (prev.val != old.val);
+ *overflow += orig_overflow;
+ }
+
+diff --git a/arch/x86/boot/bioscall.S b/arch/x86/boot/bioscall.S
+index 5521ea12f44e0..aa9b964575843 100644
+--- a/arch/x86/boot/bioscall.S
++++ b/arch/x86/boot/bioscall.S
+@@ -32,7 +32,7 @@ intcall:
+ movw %dx, %si
+ movw %sp, %di
+ movw $11, %cx
+- rep; movsd
++ rep; movsl
+
+ /* Pop full state from the stack */
+ popal
+@@ -67,7 +67,7 @@ intcall:
+ jz 4f
+ movw %sp, %si
+ movw $11, %cx
+- rep; movsd
++ rep; movsl
+ 4: addw $44, %sp
+
+ /* Restore state and return */
+diff --git a/arch/x86/kernel/cpu/resctrl/rdtgroup.c b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
+index b57b3db9a6a78..4f5d79e658cd3 100644
+--- a/arch/x86/kernel/cpu/resctrl/rdtgroup.c
++++ b/arch/x86/kernel/cpu/resctrl/rdtgroup.c
+@@ -580,8 +580,10 @@ static int __rdtgroup_move_task(struct task_struct *tsk,
+ /*
+ * Ensure the task's closid and rmid are written before determining if
+ * the task is current that will decide if it will be interrupted.
++ * This pairs with the full barrier between the rq->curr update and
++ * resctrl_sched_in() during context switch.
+ */
+- barrier();
++ smp_mb();
+
+ /*
+ * By now, the task's closid and rmid are set. If the task is current
+@@ -2363,6 +2365,14 @@ static void rdt_move_group_tasks(struct rdtgroup *from, struct rdtgroup *to,
+ WRITE_ONCE(t->closid, to->closid);
+ WRITE_ONCE(t->rmid, to->mon.rmid);
+
++ /*
++ * Order the closid/rmid stores above before the loads
++ * in task_curr(). This pairs with the full barrier
++ * between the rq->curr update and resctrl_sched_in()
++ * during context switch.
++ */
++ smp_mb();
++
+ /*
+ * If the task is on a CPU, set the CPU in the mask.
+ * The detection is inaccurate as tasks might move or
+diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
+index 05b27b4a54c9d..528437e3e2f3f 100644
+--- a/arch/x86/kvm/cpuid.c
++++ b/arch/x86/kvm/cpuid.c
+@@ -567,16 +567,22 @@ struct kvm_cpuid_array {
+ int nent;
+ };
+
++static struct kvm_cpuid_entry2 *get_next_cpuid(struct kvm_cpuid_array *array)
++{
++ if (array->nent >= array->maxnent)
++ return NULL;
++
++ return &array->entries[array->nent++];
++}
++
+ static struct kvm_cpuid_entry2 *do_host_cpuid(struct kvm_cpuid_array *array,
+ u32 function, u32 index)
+ {
+- struct kvm_cpuid_entry2 *entry;
++ struct kvm_cpuid_entry2 *entry = get_next_cpuid(array);
+
+- if (array->nent >= array->maxnent)
++ if (!entry)
+ return NULL;
+
+- entry = &array->entries[array->nent++];
+-
+ entry->function = function;
+ entry->index = index;
+ entry->flags = 0;
+@@ -755,22 +761,13 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
+ entry->edx = edx.full;
+ break;
+ }
+- /*
+- * Per Intel's SDM, the 0x1f is a superset of 0xb,
+- * thus they can be handled by common code.
+- */
+ case 0x1f:
+ case 0xb:
+ /*
+- * Populate entries until the level type (ECX[15:8]) of the
+- * previous entry is zero. Note, CPUID EAX.{0x1f,0xb}.0 is
+- * the starting entry, filled by the primary do_host_cpuid().
++ * No topology; a valid topology is indicated by the presence
++ * of subleaf 1.
+ */
+- for (i = 1; entry->ecx & 0xff00; ++i) {
+- entry = do_host_cpuid(array, function, i);
+- if (!entry)
+- goto out;
+- }
++ entry->eax = entry->ebx = entry->ecx = 0;
+ break;
+ case 0xd:
+ entry->eax &= supported_xcr0;
+@@ -962,6 +959,9 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
+ entry->ebx = entry->ecx = entry->edx = 0;
+ break;
+ case 0x8000001e:
++ /* Do not return host topology information. */
++ entry->eax = entry->ebx = entry->ecx = 0;
++ entry->edx = 0; /* reserved */
+ break;
+ case 0x8000001F:
+ if (!kvm_cpu_cap_has(X86_FEATURE_SEV)) {
+diff --git a/block/blk-merge.c b/block/blk-merge.c
+index bb26db93ad1de..d1435b6572977 100644
+--- a/block/blk-merge.c
++++ b/block/blk-merge.c
+@@ -348,11 +348,13 @@ void __blk_queue_split(struct bio **bio, unsigned int *nr_segs)
+ break;
+ }
+ split = blk_bio_segment_split(q, *bio, &q->bio_split, nr_segs);
++ if (IS_ERR(split))
++ *bio = split = NULL;
+ break;
+ }
+
+ if (split) {
+- /* there isn't chance to merge the splitted bio */
++ /* there isn't chance to merge the split bio */
+ split->bi_opf |= REQ_NOMERGE;
+
+ bio_chain(split, *bio);
+diff --git a/block/blk-mq.c b/block/blk-mq.c
+index 1a28ba9017edb..9f53b4caf9772 100644
+--- a/block/blk-mq.c
++++ b/block/blk-mq.c
+@@ -2193,6 +2193,8 @@ blk_qc_t blk_mq_submit_bio(struct bio *bio)
+
+ blk_queue_bounce(q, &bio);
+ __blk_queue_split(&bio, &nr_segs);
++ if (!bio)
++ goto queue_exit;
+
+ if (!bio_integrity_prep(bio))
+ goto queue_exit;
+diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
+index 47e0d105b462e..4281dc847bc22 100644
+--- a/drivers/block/drbd/drbd_req.c
++++ b/drivers/block/drbd/drbd_req.c
+@@ -1602,6 +1602,8 @@ blk_qc_t drbd_submit_bio(struct bio *bio)
+ struct drbd_device *device = bio->bi_bdev->bd_disk->private_data;
+
+ blk_queue_split(&bio);
++ if (!bio)
++ return BLK_QC_T_NONE;
+
+ /*
+ * what we "blindly" assume:
+diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
+index 0f26b2510a756..ca2ab977ef8ef 100644
+--- a/drivers/block/pktcdvd.c
++++ b/drivers/block/pktcdvd.c
+@@ -2407,6 +2407,8 @@ static blk_qc_t pkt_submit_bio(struct bio *bio)
+ struct bio *split;
+
+ blk_queue_split(&bio);
++ if (!bio)
++ return BLK_QC_T_NONE;
+
+ pd = bio->bi_bdev->bd_disk->queue->queuedata;
+ if (!pd) {
+diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c
+index c7b19e128b03c..c79aa4d8ccf73 100644
+--- a/drivers/block/ps3vram.c
++++ b/drivers/block/ps3vram.c
+@@ -587,6 +587,8 @@ static blk_qc_t ps3vram_submit_bio(struct bio *bio)
+ dev_dbg(&dev->core, "%s\n", __func__);
+
+ blk_queue_split(&bio);
++ if (!bio)
++ return BLK_QC_T_NONE;
+
+ spin_lock_irq(&priv->lock);
+ busy = !bio_list_empty(&priv->list);
+diff --git a/drivers/block/rsxx/dev.c b/drivers/block/rsxx/dev.c
+index 1cc40b0ea7619..6b253d99bc48d 100644
+--- a/drivers/block/rsxx/dev.c
++++ b/drivers/block/rsxx/dev.c
+@@ -127,6 +127,8 @@ static blk_qc_t rsxx_submit_bio(struct bio *bio)
+ blk_status_t st = BLK_STS_IOERR;
+
+ blk_queue_split(&bio);
++ if (!bio)
++ return BLK_QC_T_NONE;
+
+ might_sleep();
+
+diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/core/pm.c
+index 1020268a075a5..1a87b9c6c2f89 100644
+--- a/drivers/bus/mhi/core/pm.c
++++ b/drivers/bus/mhi/core/pm.c
+@@ -297,7 +297,8 @@ int mhi_pm_m0_transition(struct mhi_controller *mhi_cntrl)
+ read_lock_irq(&mhi_chan->lock);
+
+ /* Only ring DB if ring is not empty */
+- if (tre_ring->base && tre_ring->wp != tre_ring->rp)
++ if (tre_ring->base && tre_ring->wp != tre_ring->rp &&
++ mhi_chan->ch_state == MHI_CH_STATE_ENABLED)
+ mhi_ring_chan_db(mhi_cntrl, mhi_chan);
+ read_unlock_irq(&mhi_chan->lock);
+ }
+diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c
+index 8c4d947fb8486..8220ce5b87ca0 100644
+--- a/drivers/edac/edac_device.c
++++ b/drivers/edac/edac_device.c
+@@ -424,17 +424,16 @@ static void edac_device_workq_teardown(struct edac_device_ctl_info *edac_dev)
+ * Then restart the workq on the new delay
+ */
+ void edac_device_reset_delay_period(struct edac_device_ctl_info *edac_dev,
+- unsigned long value)
++ unsigned long msec)
+ {
+- unsigned long jiffs = msecs_to_jiffies(value);
+-
+- if (value == 1000)
+- jiffs = round_jiffies_relative(value);
+-
+- edac_dev->poll_msec = value;
+- edac_dev->delay = jiffs;
++ edac_dev->poll_msec = msec;
++ edac_dev->delay = msecs_to_jiffies(msec);
+
+- edac_mod_work(&edac_dev->work, jiffs);
++ /* See comment in edac_device_workq_setup() above */
++ if (edac_dev->poll_msec == 1000)
++ edac_mod_work(&edac_dev->work, round_jiffies_relative(edac_dev->delay));
++ else
++ edac_mod_work(&edac_dev->work, edac_dev->delay);
+ }
+
+ int edac_device_alloc_index(void)
+diff --git a/drivers/edac/edac_module.h b/drivers/edac/edac_module.h
+index aa1f91688eb8e..841d238bc3f18 100644
+--- a/drivers/edac/edac_module.h
++++ b/drivers/edac/edac_module.h
+@@ -56,7 +56,7 @@ bool edac_stop_work(struct delayed_work *work);
+ bool edac_mod_work(struct delayed_work *work, unsigned long delay);
+
+ extern void edac_device_reset_delay_period(struct edac_device_ctl_info
+- *edac_dev, unsigned long value);
++ *edac_dev, unsigned long msec);
+ extern void edac_mc_reset_delay_period(unsigned long value);
+
+ extern void *edac_align_ptr(void **p, unsigned size, int n_elems);
+diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
+index ba03f5a4b30ce..a2765d668856e 100644
+--- a/drivers/firmware/efi/efi.c
++++ b/drivers/firmware/efi/efi.c
+@@ -385,8 +385,8 @@ static int __init efisubsys_init(void)
+ efi_kobj = kobject_create_and_add("efi", firmware_kobj);
+ if (!efi_kobj) {
+ pr_err("efi: Firmware registration failed.\n");
+- destroy_workqueue(efi_rts_wq);
+- return -ENOMEM;
++ error = -ENOMEM;
++ goto err_destroy_wq;
+ }
+
+ if (efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE |
+@@ -429,7 +429,10 @@ err_unregister:
+ generic_ops_unregister();
+ err_put:
+ kobject_put(efi_kobj);
+- destroy_workqueue(efi_rts_wq);
++err_destroy_wq:
++ if (efi_rts_wq)
++ destroy_workqueue(efi_rts_wq);
++
+ return error;
+ }
+
+diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c
+index 18b0e57c58c1e..9dc244b70ce4b 100644
+--- a/drivers/gpu/drm/i915/gt/intel_reset.c
++++ b/drivers/gpu/drm/i915/gt/intel_reset.c
+@@ -271,6 +271,7 @@ out:
+ static int gen6_hw_domain_reset(struct intel_gt *gt, u32 hw_domain_mask)
+ {
+ struct intel_uncore *uncore = gt->uncore;
++ int loops = 2;
+ int err;
+
+ /*
+@@ -278,18 +279,39 @@ static int gen6_hw_domain_reset(struct intel_gt *gt, u32 hw_domain_mask)
+ * for fifo space for the write or forcewake the chip for
+ * the read
+ */
+- intel_uncore_write_fw(uncore, GEN6_GDRST, hw_domain_mask);
++ do {
++ intel_uncore_write_fw(uncore, GEN6_GDRST, hw_domain_mask);
+
+- /* Wait for the device to ack the reset requests */
+- err = __intel_wait_for_register_fw(uncore,
+- GEN6_GDRST, hw_domain_mask, 0,
+- 500, 0,
+- NULL);
++ /*
++ * Wait for the device to ack the reset requests.
++ *
++ * On some platforms, e.g. Jasperlake, we see that the
++ * engine register state is not cleared until shortly after
++ * GDRST reports completion, causing a failure as we try
++ * to immediately resume while the internal state is still
++ * in flux. If we immediately repeat the reset, the second
++ * reset appears to serialise with the first, and since
++ * it is a no-op, the registers should retain their reset
++ * value. However, there is still a concern that upon
++ * leaving the second reset, the internal engine state
++ * is still in flux and not ready for resuming.
++ */
++ err = __intel_wait_for_register_fw(uncore, GEN6_GDRST,
++ hw_domain_mask, 0,
++ 2000, 0,
++ NULL);
++ } while (err == 0 && --loops);
+ if (err)
+ GT_TRACE(gt,
+ "Wait for 0x%08x engines reset failed\n",
+ hw_domain_mask);
+
++ /*
++ * As we have observed that the engine state is still volatile
++ * after GDRST is acked, impose a small delay to let everything settle.
++ */
++ udelay(50);
++
+ return err;
+ }
+
+diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+index 225c277a6223e..588722e824f6f 100644
+--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
++++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+@@ -29,11 +29,9 @@ enum {
+ ADRENO_FW_MAX,
+ };
+
+-enum adreno_quirks {
+- ADRENO_QUIRK_TWO_PASS_USE_WFI = 1,
+- ADRENO_QUIRK_FAULT_DETECT_MASK = 2,
+- ADRENO_QUIRK_LMLOADKILL_DISABLE = 3,
+-};
++#define ADRENO_QUIRK_TWO_PASS_USE_WFI BIT(0)
++#define ADRENO_QUIRK_FAULT_DETECT_MASK BIT(1)
++#define ADRENO_QUIRK_LMLOADKILL_DISABLE BIT(2)
+
+ struct adreno_rev {
+ uint8_t core;
+@@ -65,7 +63,7 @@ struct adreno_info {
+ const char *name;
+ const char *fw[ADRENO_FW_MAX];
+ uint32_t gmem;
+- enum adreno_quirks quirks;
++ u64 quirks;
+ struct msm_gpu *(*init)(struct drm_device *dev);
+ const char *zapfw;
+ u32 inactive_period;
+diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
+index 6d36f63c33388..7b8d4ba868eb7 100644
+--- a/drivers/gpu/drm/msm/dp/dp_aux.c
++++ b/drivers/gpu/drm/msm/dp/dp_aux.c
+@@ -406,6 +406,10 @@ void dp_aux_isr(struct drm_dp_aux *dp_aux)
+
+ isr = dp_catalog_aux_get_irq(aux->catalog);
+
++ /* no interrupts pending, return immediately */
++ if (!isr)
++ return;
++
+ if (!aux->cmd_busy)
+ return;
+
+diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
+index 15c3e63db396d..3c750ba6ba1fe 100644
+--- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c
++++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
+@@ -292,10 +292,18 @@ static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data,
+ drm_gem_object_release(obj);
+ return ret;
+ }
+- drm_gem_object_put(obj);
+
+ rc->res_handle = qobj->hw_res_handle; /* similiar to a VM address */
+ rc->bo_handle = handle;
++
++ /*
++ * The handle owns the reference now. But we must drop our
++ * remaining reference *after* we no longer need to dereference
++ * the obj. Otherwise userspace could guess the handle and
++ * race closing it from another thread.
++ */
++ drm_gem_object_put(obj);
++
+ return 0;
+ }
+
+@@ -656,11 +664,18 @@ static int virtio_gpu_resource_create_blob_ioctl(struct drm_device *dev,
+ drm_gem_object_release(obj);
+ return ret;
+ }
+- drm_gem_object_put(obj);
+
+ rc_blob->res_handle = bo->hw_res_handle;
+ rc_blob->bo_handle = handle;
+
++ /*
++ * The handle owns the reference now. But we must drop our
++ * remaining reference *after* we no longer need to dereference
++ * the obj. Otherwise userspace could guess the handle and
++ * race closing it from another thread.
++ */
++ drm_gem_object_put(obj);
++
+ return 0;
+ }
+
+diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
+index cae5a73ff518c..0835f32e040ad 100644
+--- a/drivers/iommu/iova.c
++++ b/drivers/iommu/iova.c
+@@ -252,7 +252,7 @@ static int __alloc_and_insert_iova_range(struct iova_domain *iovad,
+
+ curr = __get_cached_rbnode(iovad, limit_pfn);
+ curr_iova = to_iova(curr);
+- retry_pfn = curr_iova->pfn_hi + 1;
++ retry_pfn = curr_iova->pfn_hi;
+
+ retry:
+ do {
+@@ -266,7 +266,7 @@ retry:
+ if (high_pfn < size || new_pfn < low_pfn) {
+ if (low_pfn == iovad->start_pfn && retry_pfn < limit_pfn) {
+ high_pfn = limit_pfn;
+- low_pfn = retry_pfn;
++ low_pfn = retry_pfn + 1;
+ curr = iova_find_limit(iovad, limit_pfn);
+ curr_iova = to_iova(curr);
+ goto retry;
+diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
+index 254530ad6c488..fe1c3123a7e77 100644
+--- a/drivers/iommu/mtk_iommu_v1.c
++++ b/drivers/iommu/mtk_iommu_v1.c
+@@ -655,7 +655,7 @@ static int mtk_iommu_probe(struct platform_device *pdev)
+ ret = iommu_device_sysfs_add(&data->iommu, &pdev->dev, NULL,
+ dev_name(&pdev->dev));
+ if (ret)
+- return ret;
++ goto out_clk_unprepare;
+
+ ret = iommu_device_register(&data->iommu, &mtk_iommu_ops, dev);
+ if (ret)
+@@ -678,6 +678,8 @@ out_dev_unreg:
+ iommu_device_unregister(&data->iommu);
+ out_sysfs_remove:
+ iommu_device_sysfs_remove(&data->iommu);
++out_clk_unprepare:
++ clk_disable_unprepare(data->bclk);
+ return ret;
+ }
+
+diff --git a/drivers/md/md.c b/drivers/md/md.c
+index 59ab99844df8e..9e54b865f30da 100644
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -458,6 +458,8 @@ static blk_qc_t md_submit_bio(struct bio *bio)
+ }
+
+ blk_queue_split(&bio);
++ if (!bio)
++ return BLK_QC_T_NONE;
+
+ if (mddev->ro == 1 && unlikely(rw == WRITE)) {
+ if (bio_sectors(bio) != 0)
+diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h
+index f171bc99e58ca..60d0ca69ceca9 100644
+--- a/drivers/net/ethernet/intel/igc/igc_defines.h
++++ b/drivers/net/ethernet/intel/igc/igc_defines.h
+@@ -469,7 +469,9 @@
+ #define IGC_TSAUXC_EN_TT0 BIT(0) /* Enable target time 0. */
+ #define IGC_TSAUXC_EN_TT1 BIT(1) /* Enable target time 1. */
+ #define IGC_TSAUXC_EN_CLK0 BIT(2) /* Enable Configurable Frequency Clock 0. */
++#define IGC_TSAUXC_ST0 BIT(4) /* Start Clock 0 Toggle on Target Time 0. */
+ #define IGC_TSAUXC_EN_CLK1 BIT(5) /* Enable Configurable Frequency Clock 1. */
++#define IGC_TSAUXC_ST1 BIT(7) /* Start Clock 1 Toggle on Target Time 1. */
+ #define IGC_TSAUXC_EN_TS0 BIT(8) /* Enable hardware timestamp 0. */
+ #define IGC_TSAUXC_AUTT0 BIT(9) /* Auxiliary Timestamp Taken. */
+ #define IGC_TSAUXC_EN_TS1 BIT(10) /* Enable hardware timestamp 0. */
+diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c
+index 8e521f99b80ae..fbde7826927b3 100644
+--- a/drivers/net/ethernet/intel/igc/igc_ptp.c
++++ b/drivers/net/ethernet/intel/igc/igc_ptp.c
+@@ -323,7 +323,7 @@ static int igc_ptp_feature_enable_i225(struct ptp_clock_info *ptp,
+ ts = ns_to_timespec64(ns);
+ if (rq->perout.index == 1) {
+ if (use_freq) {
+- tsauxc_mask = IGC_TSAUXC_EN_CLK1;
++ tsauxc_mask = IGC_TSAUXC_EN_CLK1 | IGC_TSAUXC_ST1;
+ tsim_mask = 0;
+ } else {
+ tsauxc_mask = IGC_TSAUXC_EN_TT1;
+@@ -334,7 +334,7 @@ static int igc_ptp_feature_enable_i225(struct ptp_clock_info *ptp,
+ freqout = IGC_FREQOUT1;
+ } else {
+ if (use_freq) {
+- tsauxc_mask = IGC_TSAUXC_EN_CLK0;
++ tsauxc_mask = IGC_TSAUXC_EN_CLK0 | IGC_TSAUXC_ST0;
+ tsim_mask = 0;
+ } else {
+ tsauxc_mask = IGC_TSAUXC_EN_TT0;
+@@ -348,10 +348,12 @@ static int igc_ptp_feature_enable_i225(struct ptp_clock_info *ptp,
+ tsauxc = rd32(IGC_TSAUXC);
+ tsim = rd32(IGC_TSIM);
+ if (rq->perout.index == 1) {
+- tsauxc &= ~(IGC_TSAUXC_EN_TT1 | IGC_TSAUXC_EN_CLK1);
++ tsauxc &= ~(IGC_TSAUXC_EN_TT1 | IGC_TSAUXC_EN_CLK1 |
++ IGC_TSAUXC_ST1);
+ tsim &= ~IGC_TSICR_TT1;
+ } else {
+- tsauxc &= ~(IGC_TSAUXC_EN_TT0 | IGC_TSAUXC_EN_CLK0);
++ tsauxc &= ~(IGC_TSAUXC_EN_TT0 | IGC_TSAUXC_EN_CLK0 |
++ IGC_TSAUXC_ST0);
+ tsim &= ~IGC_TSICR_TT0;
+ }
+ if (on) {
+diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
+index 24aa97f993ca1..123dca9ce4683 100644
+--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
++++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
+@@ -855,9 +855,11 @@ static struct pci_dev *ixgbe_get_first_secondary_devfn(unsigned int devfn)
+ rp_pdev = pci_get_domain_bus_and_slot(0, 0, devfn);
+ if (rp_pdev && rp_pdev->subordinate) {
+ bus = rp_pdev->subordinate->number;
++ pci_dev_put(rp_pdev);
+ return pci_get_domain_bus_and_slot(0, bus, 0);
+ }
+
++ pci_dev_put(rp_pdev);
+ return NULL;
+ }
+
+@@ -874,6 +876,7 @@ static bool ixgbe_x550em_a_has_mii(struct ixgbe_hw *hw)
+ struct ixgbe_adapter *adapter = hw->back;
+ struct pci_dev *pdev = adapter->pdev;
+ struct pci_dev *func0_pdev;
++ bool has_mii = false;
+
+ /* For the C3000 family of SoCs (x550em_a) the internal ixgbe devices
+ * are always downstream of root ports @ 0000:00:16.0 & 0000:00:17.0
+@@ -884,15 +887,16 @@ static bool ixgbe_x550em_a_has_mii(struct ixgbe_hw *hw)
+ func0_pdev = ixgbe_get_first_secondary_devfn(PCI_DEVFN(0x16, 0));
+ if (func0_pdev) {
+ if (func0_pdev == pdev)
+- return true;
+- else
+- return false;
++ has_mii = true;
++ goto out;
+ }
+ func0_pdev = ixgbe_get_first_secondary_devfn(PCI_DEVFN(0x17, 0));
+ if (func0_pdev == pdev)
+- return true;
++ has_mii = true;
+
+- return false;
++out:
++ pci_dev_put(func0_pdev);
++ return has_mii;
+ }
+
+ /**
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+index 6b335139abe7f..fd0a31bf94fea 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.c
+@@ -695,9 +695,9 @@ int cgx_lmac_rx_tx_enable(void *cgxd, int lmac_id, bool enable)
+
+ cfg = cgx_read(cgx, lmac_id, CGXX_CMRX_CFG);
+ if (enable)
+- cfg |= CMR_EN | DATA_PKT_RX_EN | DATA_PKT_TX_EN;
++ cfg |= DATA_PKT_RX_EN | DATA_PKT_TX_EN;
+ else
+- cfg &= ~(CMR_EN | DATA_PKT_RX_EN | DATA_PKT_TX_EN);
++ cfg &= ~(DATA_PKT_RX_EN | DATA_PKT_TX_EN);
+ cgx_write(cgx, lmac_id, CGXX_CMRX_CFG, cfg);
+ return 0;
+ }
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
+index ab1e4abdea38b..5714280a4252d 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
++++ b/drivers/net/ethernet/marvell/octeontx2/af/cgx.h
+@@ -30,7 +30,6 @@
+ #define CMR_P2X_SEL_SHIFT 59ULL
+ #define CMR_P2X_SEL_NIX0 1ULL
+ #define CMR_P2X_SEL_NIX1 2ULL
+-#define CMR_EN BIT_ULL(55)
+ #define DATA_PKT_TX_EN BIT_ULL(53)
+ #define DATA_PKT_RX_EN BIT_ULL(54)
+ #define CGX_LMAC_TYPE_SHIFT 40
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c
+index 4267f3a1059e7..78b1a6ddd9675 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c
+@@ -88,6 +88,8 @@ static int mlx5e_gen_ip_tunnel_header_vxlan(char buf[],
+ struct udphdr *udp = (struct udphdr *)(buf);
+ struct vxlanhdr *vxh;
+
++ if (tun_key->tun_flags & TUNNEL_VXLAN_OPT)
++ return -EOPNOTSUPP;
+ vxh = (struct vxlanhdr *)((char *)udp + sizeof(struct udphdr));
+ *ip_proto = IPPROTO_UDP;
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+index 8f2f99689abac..9ea4281a55b81 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+@@ -3597,7 +3597,8 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv,
+ if (err)
+ return err;
+
+- action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
++ action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
++ MLX5_FLOW_CONTEXT_ACTION_COUNT;
+ attr->dest_chain = act->chain_index;
+ break;
+ case FLOW_ACTION_CT:
+@@ -3632,12 +3633,9 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv,
+
+ attr->action = action;
+
+- if (attr->dest_chain) {
+- if (attr->action & MLX5_FLOW_CONTEXT_ACTION_FWD_DEST) {
+- NL_SET_ERR_MSG(extack, "Mirroring goto chain rules isn't supported");
+- return -EOPNOTSUPP;
+- }
+- attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
++ if (attr->dest_chain && parse_attr->mirred_ifindex[0]) {
++ NL_SET_ERR_MSG(extack, "Mirroring goto chain rules isn't supported");
++ return -EOPNOTSUPP;
+ }
+
+ if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
+@@ -4146,7 +4144,8 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
+ if (err)
+ return err;
+
+- action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
++ action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
++ MLX5_FLOW_CONTEXT_ACTION_COUNT;
+ attr->dest_chain = act->chain_index;
+ break;
+ case FLOW_ACTION_CT:
+@@ -4218,24 +4217,18 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
+ if (!actions_match_supported(priv, flow_action, parse_attr, flow, extack))
+ return -EOPNOTSUPP;
+
+- if (attr->dest_chain) {
+- if (decap) {
+- /* It can be supported if we'll create a mapping for
+- * the tunnel device only (without tunnel), and set
+- * this tunnel id with this decap flow.
+- *
+- * On restore (miss), we'll just set this saved tunnel
+- * device.
+- */
+-
+- NL_SET_ERR_MSG(extack,
+- "Decap with goto isn't supported");
+- netdev_warn(priv->netdev,
+- "Decap with goto isn't supported");
+- return -EOPNOTSUPP;
+- }
++ if (attr->dest_chain && decap) {
++ /* It can be supported if we'll create a mapping for
++ * the tunnel device only (without tunnel), and set
++ * this tunnel id with this decap flow.
++ *
++ * On restore (miss), we'll just set this saved tunnel
++ * device.
++ */
+
+- attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
++ NL_SET_ERR_MSG(extack, "Decap with goto isn't supported");
++ netdev_warn(priv->netdev, "Decap with goto isn't supported");
++ return -EOPNOTSUPP;
+ }
+
+ if (esw_attr->split_count > 0 && !mlx5_esw_has_fwd_fdb(priv->mdev)) {
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
+index 91e806c1aa211..8490c0cf80a8c 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
+@@ -599,7 +599,7 @@ static int mlx5_ptp_verify(struct ptp_clock_info *ptp, unsigned int pin,
+ static const struct ptp_clock_info mlx5_ptp_clock_info = {
+ .owner = THIS_MODULE,
+ .name = "mlx5_ptp",
+- .max_adj = 100000000,
++ .max_adj = 50000000,
+ .n_alarm = 0,
+ .n_ext_ts = 0,
+ .n_per_out = 0,
+diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
+index ac8bc1c8614d3..487418ef9b4f8 100644
+--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
++++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
+@@ -229,7 +229,10 @@ static int stmmac_enable(struct ptp_clock_info *ptp,
+ }
+ writel(acr_value, ptpaddr + PTP_ACR);
+ mutex_unlock(&priv->aux_ts_lock);
+- ret = 0;
++ /* wait for auxts fifo clear to finish */
++ ret = readl_poll_timeout(ptpaddr + PTP_ACR, acr_value,
++ !(acr_value & PTP_ACR_ATSFC),
++ 10, 10000);
+ break;
+
+ default:
+diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c
+index bd7f7478d1892..62ad26e4299d1 100644
+--- a/drivers/nfc/pn533/usb.c
++++ b/drivers/nfc/pn533/usb.c
+@@ -153,10 +153,17 @@ static int pn533_usb_send_ack(struct pn533 *dev, gfp_t flags)
+ return usb_submit_urb(phy->ack_urb, flags);
+ }
+
++struct pn533_out_arg {
++ struct pn533_usb_phy *phy;
++ struct completion done;
++};
++
+ static int pn533_usb_send_frame(struct pn533 *dev,
+ struct sk_buff *out)
+ {
+ struct pn533_usb_phy *phy = dev->phy;
++ struct pn533_out_arg arg;
++ void *cntx;
+ int rc;
+
+ if (phy->priv == NULL)
+@@ -168,10 +175,17 @@ static int pn533_usb_send_frame(struct pn533 *dev,
+ print_hex_dump_debug("PN533 TX: ", DUMP_PREFIX_NONE, 16, 1,
+ out->data, out->len, false);
+
++ init_completion(&arg.done);
++ cntx = phy->out_urb->context;
++ phy->out_urb->context = &arg;
++
+ rc = usb_submit_urb(phy->out_urb, GFP_KERNEL);
+ if (rc)
+ return rc;
+
++ wait_for_completion(&arg.done);
++ phy->out_urb->context = cntx;
++
+ if (dev->protocol_type == PN533_PROTO_REQ_RESP) {
+ /* request for response for sent packet directly */
+ rc = pn533_submit_urb_for_response(phy, GFP_KERNEL);
+@@ -408,7 +422,31 @@ static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy)
+ return arg.rc;
+ }
+
+-static void pn533_send_complete(struct urb *urb)
++static void pn533_out_complete(struct urb *urb)
++{
++ struct pn533_out_arg *arg = urb->context;
++ struct pn533_usb_phy *phy = arg->phy;
++
++ switch (urb->status) {
++ case 0:
++ break; /* success */
++ case -ECONNRESET:
++ case -ENOENT:
++ dev_dbg(&phy->udev->dev,
++ "The urb has been stopped (status %d)\n",
++ urb->status);
++ break;
++ case -ESHUTDOWN:
++ default:
++ nfc_err(&phy->udev->dev,
++ "Urb failure (status %d)\n",
++ urb->status);
++ }
++
++ complete(&arg->done);
++}
++
++static void pn533_ack_complete(struct urb *urb)
+ {
+ struct pn533_usb_phy *phy = urb->context;
+
+@@ -496,10 +534,10 @@ static int pn533_usb_probe(struct usb_interface *interface,
+
+ usb_fill_bulk_urb(phy->out_urb, phy->udev,
+ usb_sndbulkpipe(phy->udev, out_endpoint),
+- NULL, 0, pn533_send_complete, phy);
++ NULL, 0, pn533_out_complete, phy);
+ usb_fill_bulk_urb(phy->ack_urb, phy->udev,
+ usb_sndbulkpipe(phy->udev, out_endpoint),
+- NULL, 0, pn533_send_complete, phy);
++ NULL, 0, pn533_ack_complete, phy);
+
+ switch (id->driver_info) {
+ case PN533_DEVICE_STD:
+diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
+index fe199d568a4a8..8d97b942de01f 100644
+--- a/drivers/nvme/host/multipath.c
++++ b/drivers/nvme/host/multipath.c
+@@ -329,6 +329,8 @@ static blk_qc_t nvme_ns_head_submit_bio(struct bio *bio)
+ * pool from the original queue to allocate the bvecs from.
+ */
+ blk_queue_split(&bio);
++ if (!bio)
++ return BLK_QC_T_NONE;
+
+ srcu_idx = srcu_read_lock(&head->srcu);
+ ns = nvme_find_path(head);
+diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c
+index 5c4acf2308d4f..52d1fe5ec3e74 100644
+--- a/drivers/pinctrl/pinctrl-amd.c
++++ b/drivers/pinctrl/pinctrl-amd.c
+@@ -627,13 +627,15 @@ static bool do_amd_gpio_irq_handler(int irq, void *dev_id)
+ /* Each status bit covers four pins */
+ for (i = 0; i < 4; i++) {
+ regval = readl(regs + i);
+- /* caused wake on resume context for shared IRQ */
+- if (irq < 0 && (regval & BIT(WAKE_STS_OFF))) {
++
++ if (regval & PIN_IRQ_PENDING)
+ dev_dbg(&gpio_dev->pdev->dev,
+- "Waking due to GPIO %d: 0x%x",
++ "GPIO %d is active: 0x%x",
+ irqnr + i, regval);
++
++ /* caused wake on resume context for shared IRQ */
++ if (irq < 0 && (regval & BIT(WAKE_STS_OFF)))
+ return true;
+- }
+
+ if (!(regval & PIN_IRQ_PENDING) ||
+ !(regval & BIT(INTERRUPT_MASK_OFF)))
+diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c
+index b8c377b3f9321..f23f7128cf2b4 100644
+--- a/drivers/platform/surface/aggregator/controller.c
++++ b/drivers/platform/surface/aggregator/controller.c
+@@ -1700,8 +1700,10 @@ int ssam_request_sync(struct ssam_controller *ctrl,
+ return status;
+
+ status = ssam_request_sync_init(rqst, spec->flags);
+- if (status)
++ if (status) {
++ ssam_request_sync_free(rqst);
+ return status;
++ }
+
+ ssam_request_sync_set_resp(rqst, rsp);
+
+diff --git a/drivers/platform/surface/aggregator/ssh_request_layer.c b/drivers/platform/surface/aggregator/ssh_request_layer.c
+index 790f7f0eee98b..7c0b637c91fc8 100644
+--- a/drivers/platform/surface/aggregator/ssh_request_layer.c
++++ b/drivers/platform/surface/aggregator/ssh_request_layer.c
+@@ -916,6 +916,20 @@ static void ssh_rtl_rx_command(struct ssh_ptl *p, const struct ssam_span *data)
+ if (sshp_parse_command(dev, data, &command, &command_data))
+ return;
+
++ /*
++ * Check if the message was intended for us. If not, drop it.
++ *
++ * Note: We will need to change this to handle debug messages. On newer
++ * generation devices, these seem to be sent to tid_out=0x03. We as
++ * host can still receive them as they can be forwarded via an override
++ * option on SAM, but doing so does not change tid_out=0x00.
++ */
++ if (command->tid_out != 0x00) {
++ rtl_warn(rtl, "rtl: dropping message not intended for us (tid = %#04x)\n",
++ command->tid_out);
++ return;
++ }
++
+ if (ssh_rqid_is_event(get_unaligned_le16(&command->rqid)))
+ ssh_rtl_rx_event(rtl, command, &command_data);
+ else
+diff --git a/drivers/platform/x86/dell/dell-wmi-privacy.c b/drivers/platform/x86/dell/dell-wmi-privacy.c
+index 074b7e68c227c..7b79e987ca088 100644
+--- a/drivers/platform/x86/dell/dell-wmi-privacy.c
++++ b/drivers/platform/x86/dell/dell-wmi-privacy.c
+@@ -61,7 +61,7 @@ static const struct key_entry dell_wmi_keymap_type_0012[] = {
+ /* privacy mic mute */
+ { KE_KEY, 0x0001, { KEY_MICMUTE } },
+ /* privacy camera mute */
+- { KE_SW, 0x0002, { SW_CAMERA_LENS_COVER } },
++ { KE_VSW, 0x0002, { SW_CAMERA_LENS_COVER } },
+ { KE_END, 0},
+ };
+
+@@ -115,11 +115,15 @@ bool dell_privacy_process_event(int type, int code, int status)
+
+ switch (code) {
+ case DELL_PRIVACY_AUDIO_EVENT: /* Mic mute */
+- case DELL_PRIVACY_CAMERA_EVENT: /* Camera mute */
+ priv->last_status = status;
+ sparse_keymap_report_entry(priv->input_dev, key, 1, true);
+ ret = true;
+ break;
++ case DELL_PRIVACY_CAMERA_EVENT: /* Camera mute */
++ priv->last_status = status;
++ sparse_keymap_report_entry(priv->input_dev, key, !(status & CAMERA_STATUS), false);
++ ret = true;
++ break;
+ default:
+ dev_dbg(&priv->wdev->dev, "unknown event type 0x%04x 0x%04x\n", type, code);
+ }
+@@ -295,7 +299,7 @@ static int dell_privacy_wmi_probe(struct wmi_device *wdev, const void *context)
+ {
+ struct privacy_wmi_data *priv;
+ struct key_entry *keymap;
+- int ret, i;
++ int ret, i, j;
+
+ ret = wmi_has_guid(DELL_PRIVACY_GUID);
+ if (!ret)
+@@ -307,6 +311,11 @@ static int dell_privacy_wmi_probe(struct wmi_device *wdev, const void *context)
+
+ dev_set_drvdata(&wdev->dev, priv);
+ priv->wdev = wdev;
++
++ ret = get_current_status(priv->wdev);
++ if (ret)
++ return ret;
++
+ /* create evdev passing interface */
+ priv->input_dev = devm_input_allocate_device(&wdev->dev);
+ if (!priv->input_dev)
+@@ -321,9 +330,20 @@ static int dell_privacy_wmi_probe(struct wmi_device *wdev, const void *context)
+ /* remap the keymap code with Dell privacy key type 0x12 as prefix
+ * KEY_MICMUTE scancode will be reported as 0x120001
+ */
+- for (i = 0; i < ARRAY_SIZE(dell_wmi_keymap_type_0012); i++) {
+- keymap[i] = dell_wmi_keymap_type_0012[i];
+- keymap[i].code |= (0x0012 << 16);
++ for (i = 0, j = 0; i < ARRAY_SIZE(dell_wmi_keymap_type_0012); i++) {
++ /*
++ * Unlike keys where only presses matter, userspace may act
++ * on switches in both of their positions. Only register
++ * SW_CAMERA_LENS_COVER if it is actually there.
++ */
++ if (dell_wmi_keymap_type_0012[i].type == KE_VSW &&
++ dell_wmi_keymap_type_0012[i].sw.code == SW_CAMERA_LENS_COVER &&
++ !(priv->features_present & BIT(DELL_PRIVACY_TYPE_CAMERA)))
++ continue;
++
++ keymap[j] = dell_wmi_keymap_type_0012[i];
++ keymap[j].code |= (0x0012 << 16);
++ j++;
+ }
+ ret = sparse_keymap_setup(priv->input_dev, keymap, NULL);
+ kfree(keymap);
+@@ -334,11 +354,12 @@ static int dell_privacy_wmi_probe(struct wmi_device *wdev, const void *context)
+ priv->input_dev->name = "Dell Privacy Driver";
+ priv->input_dev->id.bustype = BUS_HOST;
+
+- ret = input_register_device(priv->input_dev);
+- if (ret)
+- return ret;
++ /* Report initial camera-cover status */
++ if (priv->features_present & BIT(DELL_PRIVACY_TYPE_CAMERA))
++ input_report_switch(priv->input_dev, SW_CAMERA_LENS_COVER,
++ !(priv->last_status & CAMERA_STATUS));
+
+- ret = get_current_status(priv->wdev);
++ ret = input_register_device(priv->input_dev);
+ if (ret)
+ return ret;
+
+diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
+index 7c553581e8708..e75b09a144a32 100644
+--- a/drivers/platform/x86/ideapad-laptop.c
++++ b/drivers/platform/x86/ideapad-laptop.c
+@@ -1493,6 +1493,12 @@ static const struct dmi_system_id set_fn_lock_led_list[] = {
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Legion R7000P2020H"),
+ }
+ },
++ {
++ .matches = {
++ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
++ DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Legion 5 15ARH05"),
++ }
++ },
+ {}
+ };
+
+diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
+index 7048133749221..336dee9485d4b 100644
+--- a/drivers/platform/x86/sony-laptop.c
++++ b/drivers/platform/x86/sony-laptop.c
+@@ -1892,14 +1892,21 @@ static int sony_nc_kbd_backlight_setup(struct platform_device *pd,
+ break;
+ }
+
+- ret = sony_call_snc_handle(handle, probe_base, &result);
+- if (ret)
+- return ret;
++ /*
++ * Only probe if there is a separate probe_base, otherwise the probe call
++ * is equivalent to __sony_nc_kbd_backlight_mode_set(0), resulting in
++ * the keyboard backlight being turned off.
++ */
++ if (probe_base) {
++ ret = sony_call_snc_handle(handle, probe_base, &result);
++ if (ret)
++ return ret;
+
+- if ((handle == 0x0137 && !(result & 0x02)) ||
+- !(result & 0x01)) {
+- dprintk("no backlight keyboard found\n");
+- return 0;
++ if ((handle == 0x0137 && !(result & 0x02)) ||
++ !(result & 0x01)) {
++ dprintk("no backlight keyboard found\n");
++ return 0;
++ }
+ }
+
+ kbdbl_ctl = kzalloc(sizeof(*kbdbl_ctl), GFP_KERNEL);
+diff --git a/drivers/regulator/da9211-regulator.c b/drivers/regulator/da9211-regulator.c
+index e01b32d1fa17d..00828f5baa972 100644
+--- a/drivers/regulator/da9211-regulator.c
++++ b/drivers/regulator/da9211-regulator.c
+@@ -498,6 +498,12 @@ static int da9211_i2c_probe(struct i2c_client *i2c)
+
+ chip->chip_irq = i2c->irq;
+
++ ret = da9211_regulator_init(chip);
++ if (ret < 0) {
++ dev_err(chip->dev, "Failed to initialize regulator: %d\n", ret);
++ return ret;
++ }
++
+ if (chip->chip_irq != 0) {
+ ret = devm_request_threaded_irq(chip->dev, chip->chip_irq, NULL,
+ da9211_irq_handler,
+@@ -512,11 +518,6 @@ static int da9211_i2c_probe(struct i2c_client *i2c)
+ dev_warn(chip->dev, "No IRQ configured\n");
+ }
+
+- ret = da9211_regulator_init(chip);
+-
+- if (ret < 0)
+- dev_err(chip->dev, "Failed to initialize regulator: %d\n", ret);
+-
+ return ret;
+ }
+
+diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c
+index 5be3d1c39a78e..54176c073547b 100644
+--- a/drivers/s390/block/dcssblk.c
++++ b/drivers/s390/block/dcssblk.c
+@@ -866,6 +866,8 @@ dcssblk_submit_bio(struct bio *bio)
+ unsigned long bytes_done;
+
+ blk_queue_split(&bio);
++ if (!bio)
++ return BLK_QC_T_NONE;
+
+ bytes_done = 0;
+ dev_info = bio->bi_bdev->bd_disk->private_data;
+diff --git a/drivers/scsi/mpi3mr/Makefile b/drivers/scsi/mpi3mr/Makefile
+index 7c2063e04c818..7ebca0ba538da 100644
+--- a/drivers/scsi/mpi3mr/Makefile
++++ b/drivers/scsi/mpi3mr/Makefile
+@@ -1,4 +1,4 @@
+ # mpi3mr makefile
+-obj-m += mpi3mr.o
++obj-$(CONFIG_SCSI_MPI3MR) += mpi3mr.o
+ mpi3mr-y += mpi3mr_os.o \
+ mpi3mr_fw.o \
+diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
+index be024b2b6bd43..766c3a59a900a 100644
+--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
++++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
+@@ -2594,12 +2594,8 @@ _base_check_pcie_native_sgl(struct MPT3SAS_ADAPTER *ioc,
+
+ /* Get the SG list pointer and info. */
+ sges_left = scsi_dma_map(scmd);
+- if (sges_left < 0) {
+- sdev_printk(KERN_ERR, scmd->device,
+- "scsi_dma_map failed: request for %d bytes!\n",
+- scsi_bufflen(scmd));
++ if (sges_left < 0)
+ return 1;
+- }
+
+ /* Check if we need to build a native SG list. */
+ if (!base_is_prp_possible(ioc, pcie_device,
+@@ -2706,12 +2702,8 @@ _base_build_sg_scmd(struct MPT3SAS_ADAPTER *ioc,
+
+ sg_scmd = scsi_sglist(scmd);
+ sges_left = scsi_dma_map(scmd);
+- if (sges_left < 0) {
+- sdev_printk(KERN_ERR, scmd->device,
+- "scsi_dma_map failed: request for %d bytes!\n",
+- scsi_bufflen(scmd));
++ if (sges_left < 0)
+ return -ENOMEM;
+- }
+
+ sg_local = &mpi_request->SGL;
+ sges_in_segment = ioc->max_sges_in_main_message;
+@@ -2854,12 +2846,8 @@ _base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc,
+
+ sg_scmd = scsi_sglist(scmd);
+ sges_left = scsi_dma_map(scmd);
+- if (sges_left < 0) {
+- sdev_printk(KERN_ERR, scmd->device,
+- "scsi_dma_map failed: request for %d bytes!\n",
+- scsi_bufflen(scmd));
++ if (sges_left < 0)
+ return -ENOMEM;
+- }
+
+ sg_local = &mpi_request->SGL;
+ sges_in_segment = (ioc->request_sz -
+diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
+index a428b8145dcc2..0b06223f5714a 100644
+--- a/drivers/scsi/ufs/ufshcd.c
++++ b/drivers/scsi/ufs/ufshcd.c
+@@ -2700,6 +2700,12 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
+ if (!down_read_trylock(&hba->clk_scaling_lock))
+ return SCSI_MLQUEUE_HOST_BUSY;
+
++ /*
++ * Allows the UFS error handler to wait for prior ufshcd_queuecommand()
++ * calls.
++ */
++ rcu_read_lock();
++
+ switch (hba->ufshcd_state) {
+ case UFSHCD_STATE_OPERATIONAL:
+ case UFSHCD_STATE_EH_SCHEDULED_NON_FATAL:
+@@ -2766,7 +2772,10 @@ static int ufshcd_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
+ }
+
+ ufshcd_send_command(hba, tag);
++
+ out:
++ rcu_read_unlock();
++
+ up_read(&hba->clk_scaling_lock);
+
+ if (ufs_trigger_eh()) {
+@@ -5900,6 +5909,14 @@ static inline void ufshcd_schedule_eh_work(struct ufs_hba *hba)
+ }
+ }
+
++static void ufshcd_force_error_recovery(struct ufs_hba *hba)
++{
++ spin_lock_irq(hba->host->host_lock);
++ hba->force_reset = true;
++ ufshcd_schedule_eh_work(hba);
++ spin_unlock_irq(hba->host->host_lock);
++}
++
+ static void ufshcd_clk_scaling_allow(struct ufs_hba *hba, bool allow)
+ {
+ down_write(&hba->clk_scaling_lock);
+@@ -5952,8 +5969,7 @@ static void ufshcd_err_handling_prepare(struct ufs_hba *hba)
+ }
+ ufshcd_scsi_block_requests(hba);
+ /* Drain ufshcd_queuecommand() */
+- down_write(&hba->clk_scaling_lock);
+- up_write(&hba->clk_scaling_lock);
++ synchronize_rcu();
+ cancel_work_sync(&hba->eeh_work);
+ }
+
+@@ -8767,6 +8783,15 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
+
+ if (!hba->dev_info.b_rpm_dev_flush_capable) {
+ ret = ufshcd_set_dev_pwr_mode(hba, req_dev_pwr_mode);
++ if (ret && pm_op != UFS_SHUTDOWN_PM) {
++ /*
++ * If return err in suspend flow, IO will hang.
++ * Trigger error handler and break suspend for
++ * error recovery.
++ */
++ ufshcd_force_error_recovery(hba);
++ ret = -EBUSY;
++ }
+ if (ret)
+ goto enable_scaling;
+ }
+@@ -8778,6 +8803,15 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
+ */
+ check_for_bkops = !ufshcd_is_ufs_dev_deepsleep(hba);
+ ret = ufshcd_link_state_transition(hba, req_link_state, check_for_bkops);
++ if (ret && pm_op != UFS_SHUTDOWN_PM) {
++ /*
++ * If return err in suspend flow, IO will hang.
++ * Trigger error handler and break suspend for
++ * error recovery.
++ */
++ ufshcd_force_error_recovery(hba);
++ ret = -EBUSY;
++ }
+ if (ret)
+ goto set_dev_active;
+
+diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
+index 8ee7ce1206925..609a51137e96f 100644
+--- a/drivers/tty/hvc/hvc_xen.c
++++ b/drivers/tty/hvc/hvc_xen.c
+@@ -52,17 +52,22 @@ static DEFINE_SPINLOCK(xencons_lock);
+
+ static struct xencons_info *vtermno_to_xencons(int vtermno)
+ {
+- struct xencons_info *entry, *n, *ret = NULL;
++ struct xencons_info *entry, *ret = NULL;
++ unsigned long flags;
+
+- if (list_empty(&xenconsoles))
+- return NULL;
++ spin_lock_irqsave(&xencons_lock, flags);
++ if (list_empty(&xenconsoles)) {
++ spin_unlock_irqrestore(&xencons_lock, flags);
++ return NULL;
++ }
+
+- list_for_each_entry_safe(entry, n, &xenconsoles, list) {
++ list_for_each_entry(entry, &xenconsoles, list) {
+ if (entry->vtermno == vtermno) {
+ ret = entry;
+ break;
+ }
+ }
++ spin_unlock_irqrestore(&xencons_lock, flags);
+
+ return ret;
+ }
+@@ -223,7 +228,7 @@ static int xen_hvm_console_init(void)
+ {
+ int r;
+ uint64_t v = 0;
+- unsigned long gfn;
++ unsigned long gfn, flags;
+ struct xencons_info *info;
+
+ if (!xen_hvm_domain())
+@@ -258,9 +263,9 @@ static int xen_hvm_console_init(void)
+ goto err;
+ info->vtermno = HVC_COOKIE;
+
+- spin_lock(&xencons_lock);
++ spin_lock_irqsave(&xencons_lock, flags);
+ list_add_tail(&info->list, &xenconsoles);
+- spin_unlock(&xencons_lock);
++ spin_unlock_irqrestore(&xencons_lock, flags);
+
+ return 0;
+ err:
+@@ -283,6 +288,7 @@ static int xencons_info_pv_init(struct xencons_info *info, int vtermno)
+ static int xen_pv_console_init(void)
+ {
+ struct xencons_info *info;
++ unsigned long flags;
+
+ if (!xen_pv_domain())
+ return -ENODEV;
+@@ -299,9 +305,9 @@ static int xen_pv_console_init(void)
+ /* already configured */
+ return 0;
+ }
+- spin_lock(&xencons_lock);
++ spin_lock_irqsave(&xencons_lock, flags);
+ xencons_info_pv_init(info, HVC_COOKIE);
+- spin_unlock(&xencons_lock);
++ spin_unlock_irqrestore(&xencons_lock, flags);
+
+ return 0;
+ }
+@@ -309,6 +315,7 @@ static int xen_pv_console_init(void)
+ static int xen_initial_domain_console_init(void)
+ {
+ struct xencons_info *info;
++ unsigned long flags;
+
+ if (!xen_initial_domain())
+ return -ENODEV;
+@@ -323,9 +330,9 @@ static int xen_initial_domain_console_init(void)
+ info->irq = bind_virq_to_irq(VIRQ_CONSOLE, 0, false);
+ info->vtermno = HVC_COOKIE;
+
+- spin_lock(&xencons_lock);
++ spin_lock_irqsave(&xencons_lock, flags);
+ list_add_tail(&info->list, &xenconsoles);
+- spin_unlock(&xencons_lock);
++ spin_unlock_irqrestore(&xencons_lock, flags);
+
+ return 0;
+ }
+@@ -380,10 +387,12 @@ static void xencons_free(struct xencons_info *info)
+
+ static int xen_console_remove(struct xencons_info *info)
+ {
++ unsigned long flags;
++
+ xencons_disconnect_backend(info);
+- spin_lock(&xencons_lock);
++ spin_lock_irqsave(&xencons_lock, flags);
+ list_del(&info->list);
+- spin_unlock(&xencons_lock);
++ spin_unlock_irqrestore(&xencons_lock, flags);
+ if (info->xbdev != NULL)
+ xencons_free(info);
+ else {
+@@ -464,6 +473,7 @@ static int xencons_probe(struct xenbus_device *dev,
+ {
+ int ret, devid;
+ struct xencons_info *info;
++ unsigned long flags;
+
+ devid = dev->nodename[strlen(dev->nodename) - 1] - '0';
+ if (devid == 0)
+@@ -482,9 +492,9 @@ static int xencons_probe(struct xenbus_device *dev,
+ ret = xencons_connect_backend(dev, info);
+ if (ret < 0)
+ goto error;
+- spin_lock(&xencons_lock);
++ spin_lock_irqsave(&xencons_lock, flags);
+ list_add_tail(&info->list, &xenconsoles);
+- spin_unlock(&xencons_lock);
++ spin_unlock_irqrestore(&xencons_lock, flags);
+
+ return 0;
+
+@@ -583,10 +593,12 @@ static int __init xen_hvc_init(void)
+
+ info->hvc = hvc_alloc(HVC_COOKIE, info->irq, ops, 256);
+ if (IS_ERR(info->hvc)) {
++ unsigned long flags;
++
+ r = PTR_ERR(info->hvc);
+- spin_lock(&xencons_lock);
++ spin_lock_irqsave(&xencons_lock, flags);
+ list_del(&info->list);
+- spin_unlock(&xencons_lock);
++ spin_unlock_irqrestore(&xencons_lock, flags);
+ if (info->irq)
+ unbind_from_irqhandler(info->irq, NULL);
+ kfree(info);
+diff --git a/fs/cifs/link.c b/fs/cifs/link.c
+index bbdf3281559c8..4308b27ba3464 100644
+--- a/fs/cifs/link.c
++++ b/fs/cifs/link.c
+@@ -459,6 +459,7 @@ smb3_create_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
+ oparms.disposition = FILE_CREATE;
+ oparms.fid = &fid;
+ oparms.reconnect = false;
++ oparms.mode = 0644;
+
+ rc = SMB2_open(xid, &oparms, utf16_path, &oplock, NULL, NULL,
+ NULL, NULL);
+diff --git a/include/linux/tpm_eventlog.h b/include/linux/tpm_eventlog.h
+index 20c0ff54b7a0d..7d68a5cc58816 100644
+--- a/include/linux/tpm_eventlog.h
++++ b/include/linux/tpm_eventlog.h
+@@ -198,8 +198,8 @@ static __always_inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *ev
+ * The loop below will unmap these fields if the log is larger than
+ * one page, so save them here for reference:
+ */
+- count = READ_ONCE(event->count);
+- event_type = READ_ONCE(event->event_type);
++ count = event->count;
++ event_type = event->event_type;
+
+ /* Verify that it's the log header */
+ if (event_header->pcr_idx != 0 ||
+diff --git a/io_uring/io-wq.c b/io_uring/io-wq.c
+index 6031fb319d878..87bc38b471037 100644
+--- a/io_uring/io-wq.c
++++ b/io_uring/io-wq.c
+@@ -1217,6 +1217,12 @@ static void io_wq_cancel_tw_create(struct io_wq *wq)
+
+ worker = container_of(cb, struct io_worker, create_work);
+ io_worker_cancel_cb(worker);
++ /*
++ * Only the worker continuation helper has worker allocated and
++ * hence needs freeing.
++ */
++ if (cb->func == create_worker_cont)
++ kfree(worker);
+ }
+ }
+
+diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
+index c587221a289c1..9a01188ff45a8 100644
+--- a/io_uring/io_uring.c
++++ b/io_uring/io_uring.c
+@@ -2477,12 +2477,26 @@ static void io_iopoll_complete(struct io_ring_ctx *ctx, unsigned int *nr_events,
+
+ io_init_req_batch(&rb);
+ while (!list_empty(done)) {
++ struct io_uring_cqe *cqe;
++ unsigned cflags;
++
+ req = list_first_entry(done, struct io_kiocb, inflight_entry);
+ list_del(&req->inflight_entry);
+-
+- io_fill_cqe_req(req, req->result, io_put_rw_kbuf(req));
++ cflags = io_put_rw_kbuf(req);
+ (*nr_events)++;
+
++ cqe = io_get_cqe(ctx);
++ if (cqe) {
++ WRITE_ONCE(cqe->user_data, req->user_data);
++ WRITE_ONCE(cqe->res, req->result);
++ WRITE_ONCE(cqe->flags, cflags);
++ } else {
++ spin_lock(&ctx->completion_lock);
++ io_cqring_event_overflow(ctx, req->user_data,
++ req->result, cflags);
++ spin_unlock(&ctx->completion_lock);
++ }
++
+ if (req_ref_put_and_test(req))
+ io_req_free_batch(&rb, req, &ctx->submit_state);
+ }
+diff --git a/kernel/sched/core.c b/kernel/sched/core.c
+index bb684fe1b96ed..2bd5e235d0781 100644
+--- a/kernel/sched/core.c
++++ b/kernel/sched/core.c
+@@ -2501,14 +2501,43 @@ void do_set_cpus_allowed(struct task_struct *p, const struct cpumask *new_mask)
+ int dup_user_cpus_ptr(struct task_struct *dst, struct task_struct *src,
+ int node)
+ {
+- if (!src->user_cpus_ptr)
++ cpumask_t *user_mask;
++ unsigned long flags;
++
++ /*
++ * Always clear dst->user_cpus_ptr first as their user_cpus_ptr's
++ * may differ by now due to racing.
++ */
++ dst->user_cpus_ptr = NULL;
++
++ /*
++ * This check is racy and losing the race is a valid situation.
++ * It is not worth the extra overhead of taking the pi_lock on
++ * every fork/clone.
++ */
++ if (data_race(!src->user_cpus_ptr))
+ return 0;
+
+- dst->user_cpus_ptr = kmalloc_node(cpumask_size(), GFP_KERNEL, node);
+- if (!dst->user_cpus_ptr)
++ user_mask = kmalloc_node(cpumask_size(), GFP_KERNEL, node);
++ if (!user_mask)
+ return -ENOMEM;
+
+- cpumask_copy(dst->user_cpus_ptr, src->user_cpus_ptr);
++ /*
++ * Use pi_lock to protect content of user_cpus_ptr
++ *
++ * Though unlikely, user_cpus_ptr can be reset to NULL by a concurrent
++ * do_set_cpus_allowed().
++ */
++ raw_spin_lock_irqsave(&src->pi_lock, flags);
++ if (src->user_cpus_ptr) {
++ swap(dst->user_cpus_ptr, user_mask);
++ cpumask_copy(dst->user_cpus_ptr, src->user_cpus_ptr);
++ }
++ raw_spin_unlock_irqrestore(&src->pi_lock, flags);
++
++ if (unlikely(user_mask))
++ kfree(user_mask);
++
+ return 0;
+ }
+
+diff --git a/mm/memblock.c b/mm/memblock.c
+index 2b7397781c99a..838d59a74c65e 100644
+--- a/mm/memblock.c
++++ b/mm/memblock.c
+@@ -1615,7 +1615,13 @@ void __init __memblock_free_late(phys_addr_t base, phys_addr_t size)
+ end = PFN_DOWN(base + size);
+
+ for (; cursor < end; cursor++) {
+- memblock_free_pages(pfn_to_page(cursor), cursor, 0);
++ /*
++ * Reserved pages are always initialized by the end of
++ * memblock_free_all() (by memmap_init() and, if deferred
++ * initialization is enabled, memmap_init_reserved_pages()), so
++ * these pages can be released directly to the buddy allocator.
++ */
++ __free_pages_core(pfn_to_page(cursor), 0);
+ totalram_pages_inc();
+ }
+ }
+diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
+index c51d5ce3711c2..c68020b8de89e 100644
+--- a/net/ipv6/raw.c
++++ b/net/ipv6/raw.c
+@@ -539,6 +539,7 @@ csum_copy_err:
+ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
+ struct raw6_sock *rp)
+ {
++ struct ipv6_txoptions *opt;
+ struct sk_buff *skb;
+ int err = 0;
+ int offset;
+@@ -556,6 +557,9 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
+
+ offset = rp->offset;
+ total_len = inet_sk(sk)->cork.base.length;
++ opt = inet6_sk(sk)->cork.opt;
++ total_len -= opt ? opt->opt_flen : 0;
++
+ if (offset >= total_len - 1) {
+ err = -EINVAL;
+ ip6_flush_pending_frames(sk);
+diff --git a/net/netfilter/ipset/ip_set_bitmap_ip.c b/net/netfilter/ipset/ip_set_bitmap_ip.c
+index a8ce04a4bb72a..e4fa00abde6a2 100644
+--- a/net/netfilter/ipset/ip_set_bitmap_ip.c
++++ b/net/netfilter/ipset/ip_set_bitmap_ip.c
+@@ -308,8 +308,8 @@ bitmap_ip_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
+ return -IPSET_ERR_BITMAP_RANGE;
+
+ pr_debug("mask_bits %u, netmask %u\n", mask_bits, netmask);
+- hosts = 2 << (32 - netmask - 1);
+- elements = 2 << (netmask - mask_bits - 1);
++ hosts = 2U << (32 - netmask - 1);
++ elements = 2UL << (netmask - mask_bits - 1);
+ }
+ if (elements > IPSET_BITMAP_MAX_RANGE + 1)
+ return -IPSET_ERR_BITMAP_RANGE_SIZE;
+diff --git a/net/netfilter/nft_payload.c b/net/netfilter/nft_payload.c
+index da652c21368e1..208a6f59281db 100644
+--- a/net/netfilter/nft_payload.c
++++ b/net/netfilter/nft_payload.c
+@@ -63,7 +63,7 @@ nft_payload_copy_vlan(u32 *d, const struct sk_buff *skb, u8 offset, u8 len)
+ return false;
+
+ if (offset + len > VLAN_ETH_HLEN + vlan_hlen)
+- ethlen -= offset + len - VLAN_ETH_HLEN + vlan_hlen;
++ ethlen -= offset + len - VLAN_ETH_HLEN - vlan_hlen;
+
+ memcpy(dst_u8, vlanh + offset - vlan_hlen, ethlen);
+
+diff --git a/net/sched/act_mpls.c b/net/sched/act_mpls.c
+index e4529b428cf44..db0ef0486309b 100644
+--- a/net/sched/act_mpls.c
++++ b/net/sched/act_mpls.c
+@@ -133,6 +133,11 @@ static int valid_label(const struct nlattr *attr,
+ {
+ const u32 *label = nla_data(attr);
+
++ if (nla_len(attr) != sizeof(*label)) {
++ NL_SET_ERR_MSG_MOD(extack, "Invalid MPLS label length");
++ return -EINVAL;
++ }
++
+ if (*label & ~MPLS_LABEL_MASK || *label == MPLS_LABEL_IMPLNULL) {
+ NL_SET_ERR_MSG_MOD(extack, "MPLS label out of range");
+ return -EINVAL;
+@@ -144,7 +149,8 @@ static int valid_label(const struct nlattr *attr,
+ static const struct nla_policy mpls_policy[TCA_MPLS_MAX + 1] = {
+ [TCA_MPLS_PARMS] = NLA_POLICY_EXACT_LEN(sizeof(struct tc_mpls)),
+ [TCA_MPLS_PROTO] = { .type = NLA_U16 },
+- [TCA_MPLS_LABEL] = NLA_POLICY_VALIDATE_FN(NLA_U32, valid_label),
++ [TCA_MPLS_LABEL] = NLA_POLICY_VALIDATE_FN(NLA_BINARY,
++ valid_label),
+ [TCA_MPLS_TC] = NLA_POLICY_RANGE(NLA_U8, 0, 7),
+ [TCA_MPLS_TTL] = NLA_POLICY_MIN(NLA_U8, 1),
+ [TCA_MPLS_BOS] = NLA_POLICY_RANGE(NLA_U8, 0, 1),
+diff --git a/net/tipc/node.c b/net/tipc/node.c
+index 49ddc484c4fe7..5e000fde80676 100644
+--- a/net/tipc/node.c
++++ b/net/tipc/node.c
+@@ -1179,8 +1179,9 @@ void tipc_node_check_dest(struct net *net, u32 addr,
+ bool addr_match = false;
+ bool sign_match = false;
+ bool link_up = false;
++ bool link_is_reset = false;
+ bool accept_addr = false;
+- bool reset = true;
++ bool reset = false;
+ char *if_name;
+ unsigned long intv;
+ u16 session;
+@@ -1200,14 +1201,14 @@ void tipc_node_check_dest(struct net *net, u32 addr,
+ /* Prepare to validate requesting node's signature and media address */
+ l = le->link;
+ link_up = l && tipc_link_is_up(l);
++ link_is_reset = l && tipc_link_is_reset(l);
+ addr_match = l && !memcmp(&le->maddr, maddr, sizeof(*maddr));
+ sign_match = (signature == n->signature);
+
+ /* These three flags give us eight permutations: */
+
+ if (sign_match && addr_match && link_up) {
+- /* All is fine. Do nothing. */
+- reset = false;
++ /* All is fine. Ignore requests. */
+ /* Peer node is not a container/local namespace */
+ if (!n->peer_hash_mix)
+ n->peer_hash_mix = hash_mixes;
+@@ -1232,6 +1233,7 @@ void tipc_node_check_dest(struct net *net, u32 addr,
+ */
+ accept_addr = true;
+ *respond = true;
++ reset = true;
+ } else if (!sign_match && addr_match && link_up) {
+ /* Peer node rebooted. Two possibilities:
+ * - Delayed re-discovery; this link endpoint has already
+@@ -1263,6 +1265,7 @@ void tipc_node_check_dest(struct net *net, u32 addr,
+ n->signature = signature;
+ accept_addr = true;
+ *respond = true;
++ reset = true;
+ }
+
+ if (!accept_addr)
+@@ -1291,6 +1294,7 @@ void tipc_node_check_dest(struct net *net, u32 addr,
+ tipc_link_fsm_evt(l, LINK_RESET_EVT);
+ if (n->state == NODE_FAILINGOVER)
+ tipc_link_fsm_evt(l, LINK_FAILOVER_BEGIN_EVT);
++ link_is_reset = tipc_link_is_reset(l);
+ le->link = l;
+ n->link_cnt++;
+ tipc_node_calculate_timer(n, l);
+@@ -1303,7 +1307,7 @@ void tipc_node_check_dest(struct net *net, u32 addr,
+ memcpy(&le->maddr, maddr, sizeof(*maddr));
+ exit:
+ tipc_node_write_unlock(n);
+- if (reset && l && !tipc_link_is_reset(l))
++ if (reset && !link_is_reset)
+ tipc_node_link_down(n, b->identity, false);
+ tipc_node_put(n);
+ }
+diff --git a/sound/core/control_led.c b/sound/core/control_led.c
+index a95332b2b90b0..3eb1c5af82ad1 100644
+--- a/sound/core/control_led.c
++++ b/sound/core/control_led.c
+@@ -530,12 +530,11 @@ static ssize_t set_led_id(struct snd_ctl_led_card *led_card, const char *buf, si
+ bool attach)
+ {
+ char buf2[256], *s, *os;
+- size_t len = max(sizeof(s) - 1, count);
+ struct snd_ctl_elem_id id;
+ int err;
+
+- strncpy(buf2, buf, len);
+- buf2[len] = '\0';
++ if (strscpy(buf2, buf, sizeof(buf2)) < 0)
++ return -E2BIG;
+ memset(&id, 0, sizeof(id));
+ id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+ s = buf2;
+diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
+index 47fdf7dc24723..c7321f5842b3d 100644
+--- a/sound/pci/hda/patch_realtek.c
++++ b/sound/pci/hda/patch_realtek.c
+@@ -3558,6 +3558,15 @@ static void alc256_init(struct hda_codec *codec)
+ hda_nid_t hp_pin = alc_get_hp_pin(spec);
+ bool hp_pin_sense;
+
++ if (spec->ultra_low_power) {
++ alc_update_coef_idx(codec, 0x03, 1<<1, 1<<1);
++ alc_update_coef_idx(codec, 0x08, 3<<2, 3<<2);
++ alc_update_coef_idx(codec, 0x08, 7<<4, 0);
++ alc_update_coef_idx(codec, 0x3b, 1<<15, 0);
++ alc_update_coef_idx(codec, 0x0e, 7<<6, 7<<6);
++ msleep(30);
++ }
++
+ if (!hp_pin)
+ hp_pin = 0x21;
+
+@@ -3569,14 +3578,6 @@ static void alc256_init(struct hda_codec *codec)
+ msleep(2);
+
+ alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
+- if (spec->ultra_low_power) {
+- alc_update_coef_idx(codec, 0x03, 1<<1, 1<<1);
+- alc_update_coef_idx(codec, 0x08, 3<<2, 3<<2);
+- alc_update_coef_idx(codec, 0x08, 7<<4, 0);
+- alc_update_coef_idx(codec, 0x3b, 1<<15, 0);
+- alc_update_coef_idx(codec, 0x0e, 7<<6, 7<<6);
+- msleep(30);
+- }
+
+ snd_hda_codec_write(codec, hp_pin, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
+@@ -3707,6 +3708,13 @@ static void alc225_init(struct hda_codec *codec)
+ hda_nid_t hp_pin = alc_get_hp_pin(spec);
+ bool hp1_pin_sense, hp2_pin_sense;
+
++ if (spec->ultra_low_power) {
++ alc_update_coef_idx(codec, 0x08, 0x0f << 2, 3<<2);
++ alc_update_coef_idx(codec, 0x0e, 7<<6, 7<<6);
++ alc_update_coef_idx(codec, 0x33, 1<<11, 0);
++ msleep(30);
++ }
++
+ if (spec->codec_variant != ALC269_TYPE_ALC287 &&
+ spec->codec_variant != ALC269_TYPE_ALC245)
+ /* required only at boot or S3 and S4 resume time */
+@@ -3728,12 +3736,6 @@ static void alc225_init(struct hda_codec *codec)
+ msleep(2);
+
+ alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
+- if (spec->ultra_low_power) {
+- alc_update_coef_idx(codec, 0x08, 0x0f << 2, 3<<2);
+- alc_update_coef_idx(codec, 0x0e, 7<<6, 7<<6);
+- alc_update_coef_idx(codec, 0x33, 1<<11, 0);
+- msleep(30);
+- }
+
+ if (hp1_pin_sense || spec->ultra_low_power)
+ snd_hda_codec_write(codec, hp_pin, 0,
+@@ -4637,6 +4639,16 @@ static void alc285_fixup_hp_coef_micmute_led(struct hda_codec *codec,
+ }
+ }
+
++static void alc285_fixup_hp_gpio_micmute_led(struct hda_codec *codec,
++ const struct hda_fixup *fix, int action)
++{
++ struct alc_spec *spec = codec->spec;
++
++ if (action == HDA_FIXUP_ACT_PRE_PROBE)
++ spec->micmute_led_polarity = 1;
++ alc_fixup_hp_gpio_led(codec, action, 0, 0x04);
++}
++
+ static void alc236_fixup_hp_coef_micmute_led(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+ {
+@@ -4658,6 +4670,13 @@ static void alc285_fixup_hp_mute_led(struct hda_codec *codec,
+ alc285_fixup_hp_coef_micmute_led(codec, fix, action);
+ }
+
++static void alc285_fixup_hp_spectre_x360_mute_led(struct hda_codec *codec,
++ const struct hda_fixup *fix, int action)
++{
++ alc285_fixup_hp_mute_led_coefbit(codec, fix, action);
++ alc285_fixup_hp_gpio_micmute_led(codec, fix, action);
++}
++
+ static void alc236_fixup_hp_mute_led(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+ {
+@@ -6911,6 +6930,7 @@ enum {
+ ALC285_FIXUP_ASUS_G533Z_PINS,
+ ALC285_FIXUP_HP_GPIO_LED,
+ ALC285_FIXUP_HP_MUTE_LED,
++ ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED,
+ ALC236_FIXUP_HP_GPIO_LED,
+ ALC236_FIXUP_HP_MUTE_LED,
+ ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF,
+@@ -8280,6 +8300,10 @@ static const struct hda_fixup alc269_fixups[] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc285_fixup_hp_mute_led,
+ },
++ [ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED] = {
++ .type = HDA_FIXUP_FUNC,
++ .v.func = alc285_fixup_hp_spectre_x360_mute_led,
++ },
+ [ALC236_FIXUP_HP_GPIO_LED] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc236_fixup_hp_gpio_led,
+@@ -8998,6 +9022,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO),
+ SND_PCI_QUIRK(0x103c, 0x86e7, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
+ SND_PCI_QUIRK(0x103c, 0x86e8, "HP Spectre x360 15-eb0xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
++ SND_PCI_QUIRK(0x103c, 0x86f9, "HP Spectre x360 13-aw0xxx", ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED),
+ SND_PCI_QUIRK(0x103c, 0x8716, "HP Elite Dragonfly G2 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
+ SND_PCI_QUIRK(0x103c, 0x8720, "HP EliteBook x360 1040 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
+ SND_PCI_QUIRK(0x103c, 0x8724, "HP EliteBook 850 G7", ALC285_FIXUP_HP_GPIO_LED),
+diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
+index a02a77fef360b..6759ce7e09ff4 100644
+--- a/sound/soc/codecs/wm8904.c
++++ b/sound/soc/codecs/wm8904.c
+@@ -697,6 +697,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
+ int dcs_mask;
+ int dcs_l, dcs_r;
+ int dcs_l_reg, dcs_r_reg;
++ int an_out_reg;
+ int timeout;
+ int pwr_reg;
+
+@@ -712,6 +713,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
+ dcs_mask = WM8904_DCS_ENA_CHAN_0 | WM8904_DCS_ENA_CHAN_1;
+ dcs_r_reg = WM8904_DC_SERVO_8;
+ dcs_l_reg = WM8904_DC_SERVO_9;
++ an_out_reg = WM8904_ANALOGUE_OUT1_LEFT;
+ dcs_l = 0;
+ dcs_r = 1;
+ break;
+@@ -720,6 +722,7 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
+ dcs_mask = WM8904_DCS_ENA_CHAN_2 | WM8904_DCS_ENA_CHAN_3;
+ dcs_r_reg = WM8904_DC_SERVO_6;
+ dcs_l_reg = WM8904_DC_SERVO_7;
++ an_out_reg = WM8904_ANALOGUE_OUT2_LEFT;
+ dcs_l = 2;
+ dcs_r = 3;
+ break;
+@@ -792,6 +795,10 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
+ snd_soc_component_update_bits(component, reg,
+ WM8904_HPL_ENA_OUTP | WM8904_HPR_ENA_OUTP,
+ WM8904_HPL_ENA_OUTP | WM8904_HPR_ENA_OUTP);
++
++ /* Update volume, requires PGA to be powered */
++ val = snd_soc_component_read(component, an_out_reg);
++ snd_soc_component_write(component, an_out_reg, val);
+ break;
+
+ case SND_SOC_DAPM_POST_PMU:
+diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c
+index 5e8d045c1a069..9f5e3e1dfd947 100644
+--- a/sound/soc/qcom/lpass-cpu.c
++++ b/sound/soc/qcom/lpass-cpu.c
+@@ -851,10 +851,11 @@ static void of_lpass_cpu_parse_dai_data(struct device *dev,
+ struct lpass_data *data)
+ {
+ struct device_node *node;
+- int ret, id;
++ int ret, i, id;
+
+ /* Allow all channels by default for backwards compatibility */
+- for (id = 0; id < data->variant->num_dai; id++) {
++ for (i = 0; i < data->variant->num_dai; i++) {
++ id = data->variant->dai_driver[i].id;
+ data->mi2s_playback_sd_mode[id] = LPAIF_I2SCTL_MODE_8CH;
+ data->mi2s_capture_sd_mode[id] = LPAIF_I2SCTL_MODE_8CH;
+ }
+diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
+index b6cd43c5ea3e6..87a30be643242 100644
+--- a/sound/usb/pcm.c
++++ b/sound/usb/pcm.c
+@@ -525,6 +525,8 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
+ if (snd_usb_endpoint_compatible(chip, subs->data_endpoint,
+ fmt, hw_params))
+ goto unlock;
++ if (stop_endpoints(subs, false))
++ sync_pending_stops(subs);
+ close_endpoints(chip, subs);
+ }
+
+@@ -907,8 +909,13 @@ get_sync_ep_from_substream(struct snd_usb_substream *subs)
+ continue;
+ /* for the implicit fb, check the sync ep as well */
+ ep = snd_usb_get_endpoint(chip, fp->sync_ep);
+- if (ep && ep->cur_audiofmt)
+- return ep;
++ if (ep && ep->cur_audiofmt) {
++ /* ditto, if the sync (data) ep is used by others,
++ * this stream is restricted by the sync ep
++ */
++ if (ep != subs->sync_endpoint || ep->opened > 1)
++ return ep;
++ }
+ }
+ return NULL;
+ }
+diff --git a/tools/include/nolibc/arch-aarch64.h b/tools/include/nolibc/arch-aarch64.h
+new file mode 100644
+index 0000000000000..2dbd80d633cbb
+--- /dev/null
++++ b/tools/include/nolibc/arch-aarch64.h
+@@ -0,0 +1,199 @@
++/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
++/*
++ * AARCH64 specific definitions for NOLIBC
++ * Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu>
++ */
++
++#ifndef _NOLIBC_ARCH_AARCH64_H
++#define _NOLIBC_ARCH_AARCH64_H
++
++/* O_* macros for fcntl/open are architecture-specific */
++#define O_RDONLY 0
++#define O_WRONLY 1
++#define O_RDWR 2
++#define O_CREAT 0x40
++#define O_EXCL 0x80
++#define O_NOCTTY 0x100
++#define O_TRUNC 0x200
++#define O_APPEND 0x400
++#define O_NONBLOCK 0x800
++#define O_DIRECTORY 0x4000
++
++/* The struct returned by the newfstatat() syscall. Differs slightly from the
++ * x86_64's stat one by field ordering, so be careful.
++ */
++struct sys_stat_struct {
++ unsigned long st_dev;
++ unsigned long st_ino;
++ unsigned int st_mode;
++ unsigned int st_nlink;
++ unsigned int st_uid;
++ unsigned int st_gid;
++
++ unsigned long st_rdev;
++ unsigned long __pad1;
++ long st_size;
++ int st_blksize;
++ int __pad2;
++
++ long st_blocks;
++ long st_atime;
++ unsigned long st_atime_nsec;
++ long st_mtime;
++
++ unsigned long st_mtime_nsec;
++ long st_ctime;
++ unsigned long st_ctime_nsec;
++ unsigned int __unused[2];
++};
++
++/* Syscalls for AARCH64 :
++ * - registers are 64-bit
++ * - stack is 16-byte aligned
++ * - syscall number is passed in x8
++ * - arguments are in x0, x1, x2, x3, x4, x5
++ * - the system call is performed by calling svc 0
++ * - syscall return comes in x0.
++ * - the arguments are cast to long and assigned into the target registers
++ * which are then simply passed as registers to the asm code, so that we
++ * don't have to experience issues with register constraints.
++ *
++ * On aarch64, select() is not implemented so we have to use pselect6().
++ */
++#define __ARCH_WANT_SYS_PSELECT6
++
++#define my_syscall0(num) \
++({ \
++ register long _num asm("x8") = (num); \
++ register long _arg1 asm("x0"); \
++ \
++ asm volatile ( \
++ "svc #0\n" \
++ : "=r"(_arg1) \
++ : "r"(_num) \
++ : "memory", "cc" \
++ ); \
++ _arg1; \
++})
++
++#define my_syscall1(num, arg1) \
++({ \
++ register long _num asm("x8") = (num); \
++ register long _arg1 asm("x0") = (long)(arg1); \
++ \
++ asm volatile ( \
++ "svc #0\n" \
++ : "=r"(_arg1) \
++ : "r"(_arg1), \
++ "r"(_num) \
++ : "memory", "cc" \
++ ); \
++ _arg1; \
++})
++
++#define my_syscall2(num, arg1, arg2) \
++({ \
++ register long _num asm("x8") = (num); \
++ register long _arg1 asm("x0") = (long)(arg1); \
++ register long _arg2 asm("x1") = (long)(arg2); \
++ \
++ asm volatile ( \
++ "svc #0\n" \
++ : "=r"(_arg1) \
++ : "r"(_arg1), "r"(_arg2), \
++ "r"(_num) \
++ : "memory", "cc" \
++ ); \
++ _arg1; \
++})
++
++#define my_syscall3(num, arg1, arg2, arg3) \
++({ \
++ register long _num asm("x8") = (num); \
++ register long _arg1 asm("x0") = (long)(arg1); \
++ register long _arg2 asm("x1") = (long)(arg2); \
++ register long _arg3 asm("x2") = (long)(arg3); \
++ \
++ asm volatile ( \
++ "svc #0\n" \
++ : "=r"(_arg1) \
++ : "r"(_arg1), "r"(_arg2), "r"(_arg3), \
++ "r"(_num) \
++ : "memory", "cc" \
++ ); \
++ _arg1; \
++})
++
++#define my_syscall4(num, arg1, arg2, arg3, arg4) \
++({ \
++ register long _num asm("x8") = (num); \
++ register long _arg1 asm("x0") = (long)(arg1); \
++ register long _arg2 asm("x1") = (long)(arg2); \
++ register long _arg3 asm("x2") = (long)(arg3); \
++ register long _arg4 asm("x3") = (long)(arg4); \
++ \
++ asm volatile ( \
++ "svc #0\n" \
++ : "=r"(_arg1) \
++ : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
++ "r"(_num) \
++ : "memory", "cc" \
++ ); \
++ _arg1; \
++})
++
++#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
++({ \
++ register long _num asm("x8") = (num); \
++ register long _arg1 asm("x0") = (long)(arg1); \
++ register long _arg2 asm("x1") = (long)(arg2); \
++ register long _arg3 asm("x2") = (long)(arg3); \
++ register long _arg4 asm("x3") = (long)(arg4); \
++ register long _arg5 asm("x4") = (long)(arg5); \
++ \
++ asm volatile ( \
++ "svc #0\n" \
++ : "=r" (_arg1) \
++ : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
++ "r"(_num) \
++ : "memory", "cc" \
++ ); \
++ _arg1; \
++})
++
++#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
++({ \
++ register long _num asm("x8") = (num); \
++ register long _arg1 asm("x0") = (long)(arg1); \
++ register long _arg2 asm("x1") = (long)(arg2); \
++ register long _arg3 asm("x2") = (long)(arg3); \
++ register long _arg4 asm("x3") = (long)(arg4); \
++ register long _arg5 asm("x4") = (long)(arg5); \
++ register long _arg6 asm("x5") = (long)(arg6); \
++ \
++ asm volatile ( \
++ "svc #0\n" \
++ : "=r" (_arg1) \
++ : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
++ "r"(_arg6), "r"(_num) \
++ : "memory", "cc" \
++ ); \
++ _arg1; \
++})
++
++/* startup code */
++asm(".section .text\n"
++ ".weak _start\n"
++ "_start:\n"
++ "ldr x0, [sp]\n" // argc (x0) was in the stack
++ "add x1, sp, 8\n" // argv (x1) = sp
++ "lsl x2, x0, 3\n" // envp (x2) = 8*argc ...
++ "add x2, x2, 8\n" // + 8 (skip null)
++ "add x2, x2, x1\n" // + argv
++ "and sp, x1, -16\n" // sp must be 16-byte aligned in the callee
++ "bl main\n" // main() returns the status code, we'll exit with it.
++ "mov x8, 93\n" // NR_exit == 93
++ "svc #0\n"
++ "");
++
++#endif // _NOLIBC_ARCH_AARCH64_H
+diff --git a/tools/include/nolibc/arch-arm.h b/tools/include/nolibc/arch-arm.h
+new file mode 100644
+index 0000000000000..1191395b5acd9
+--- /dev/null
++++ b/tools/include/nolibc/arch-arm.h
+@@ -0,0 +1,204 @@
++/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
++/*
++ * ARM specific definitions for NOLIBC
++ * Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu>
++ */
++
++#ifndef _NOLIBC_ARCH_ARM_H
++#define _NOLIBC_ARCH_ARM_H
++
++/* O_* macros for fcntl/open are architecture-specific */
++#define O_RDONLY 0
++#define O_WRONLY 1
++#define O_RDWR 2
++#define O_CREAT 0x40
++#define O_EXCL 0x80
++#define O_NOCTTY 0x100
++#define O_TRUNC 0x200
++#define O_APPEND 0x400
++#define O_NONBLOCK 0x800
++#define O_DIRECTORY 0x4000
++
++/* The struct returned by the stat() syscall, 32-bit only, the syscall returns
++ * exactly 56 bytes (stops before the unused array). In big endian, the format
++ * differs as devices are returned as short only.
++ */
++struct sys_stat_struct {
++#if defined(__ARMEB__)
++ unsigned short st_dev;
++ unsigned short __pad1;
++#else
++ unsigned long st_dev;
++#endif
++ unsigned long st_ino;
++ unsigned short st_mode;
++ unsigned short st_nlink;
++ unsigned short st_uid;
++ unsigned short st_gid;
++
++#if defined(__ARMEB__)
++ unsigned short st_rdev;
++ unsigned short __pad2;
++#else
++ unsigned long st_rdev;
++#endif
++ unsigned long st_size;
++ unsigned long st_blksize;
++ unsigned long st_blocks;
++
++ unsigned long st_atime;
++ unsigned long st_atime_nsec;
++ unsigned long st_mtime;
++ unsigned long st_mtime_nsec;
++
++ unsigned long st_ctime;
++ unsigned long st_ctime_nsec;
++ unsigned long __unused[2];
++};
++
++/* Syscalls for ARM in ARM or Thumb modes :
++ * - registers are 32-bit
++ * - stack is 8-byte aligned
++ * ( http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4127.html)
++ * - syscall number is passed in r7
++ * - arguments are in r0, r1, r2, r3, r4, r5
++ * - the system call is performed by calling svc #0
++ * - syscall return comes in r0.
++ * - only lr is clobbered.
++ * - the arguments are cast to long and assigned into the target registers
++ * which are then simply passed as registers to the asm code, so that we
++ * don't have to experience issues with register constraints.
++ * - the syscall number is always specified last in order to allow to force
++ * some registers before (gcc refuses a %-register at the last position).
++ *
++ * Also, ARM supports the old_select syscall if newselect is not available
++ */
++#define __ARCH_WANT_SYS_OLD_SELECT
++
++#define my_syscall0(num) \
++({ \
++ register long _num asm("r7") = (num); \
++ register long _arg1 asm("r0"); \
++ \
++ asm volatile ( \
++ "svc #0\n" \
++ : "=r"(_arg1) \
++ : "r"(_num) \
++ : "memory", "cc", "lr" \
++ ); \
++ _arg1; \
++})
++
++#define my_syscall1(num, arg1) \
++({ \
++ register long _num asm("r7") = (num); \
++ register long _arg1 asm("r0") = (long)(arg1); \
++ \
++ asm volatile ( \
++ "svc #0\n" \
++ : "=r"(_arg1) \
++ : "r"(_arg1), \
++ "r"(_num) \
++ : "memory", "cc", "lr" \
++ ); \
++ _arg1; \
++})
++
++#define my_syscall2(num, arg1, arg2) \
++({ \
++ register long _num asm("r7") = (num); \
++ register long _arg1 asm("r0") = (long)(arg1); \
++ register long _arg2 asm("r1") = (long)(arg2); \
++ \
++ asm volatile ( \
++ "svc #0\n" \
++ : "=r"(_arg1) \
++ : "r"(_arg1), "r"(_arg2), \
++ "r"(_num) \
++ : "memory", "cc", "lr" \
++ ); \
++ _arg1; \
++})
++
++#define my_syscall3(num, arg1, arg2, arg3) \
++({ \
++ register long _num asm("r7") = (num); \
++ register long _arg1 asm("r0") = (long)(arg1); \
++ register long _arg2 asm("r1") = (long)(arg2); \
++ register long _arg3 asm("r2") = (long)(arg3); \
++ \
++ asm volatile ( \
++ "svc #0\n" \
++ : "=r"(_arg1) \
++ : "r"(_arg1), "r"(_arg2), "r"(_arg3), \
++ "r"(_num) \
++ : "memory", "cc", "lr" \
++ ); \
++ _arg1; \
++})
++
++#define my_syscall4(num, arg1, arg2, arg3, arg4) \
++({ \
++ register long _num asm("r7") = (num); \
++ register long _arg1 asm("r0") = (long)(arg1); \
++ register long _arg2 asm("r1") = (long)(arg2); \
++ register long _arg3 asm("r2") = (long)(arg3); \
++ register long _arg4 asm("r3") = (long)(arg4); \
++ \
++ asm volatile ( \
++ "svc #0\n" \
++ : "=r"(_arg1) \
++ : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
++ "r"(_num) \
++ : "memory", "cc", "lr" \
++ ); \
++ _arg1; \
++})
++
++#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
++({ \
++ register long _num asm("r7") = (num); \
++ register long _arg1 asm("r0") = (long)(arg1); \
++ register long _arg2 asm("r1") = (long)(arg2); \
++ register long _arg3 asm("r2") = (long)(arg3); \
++ register long _arg4 asm("r3") = (long)(arg4); \
++ register long _arg5 asm("r4") = (long)(arg5); \
++ \
++ asm volatile ( \
++ "svc #0\n" \
++ : "=r" (_arg1) \
++ : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
++ "r"(_num) \
++ : "memory", "cc", "lr" \
++ ); \
++ _arg1; \
++})
++
++/* startup code */
++asm(".section .text\n"
++ ".weak _start\n"
++ "_start:\n"
++#if defined(__THUMBEB__) || defined(__THUMBEL__)
++ /* We enter here in 32-bit mode but if some previous functions were in
++ * 16-bit mode, the assembler cannot know, so we need to tell it we're in
++ * 32-bit now, then switch to 16-bit (is there a better way to do it than
++ * adding 1 by hand ?) and tell the asm we're now in 16-bit mode so that
++ * it generates correct instructions. Note that we do not support thumb1.
++ */
++ ".code 32\n"
++ "add r0, pc, #1\n"
++ "bx r0\n"
++ ".code 16\n"
++#endif
++ "pop {%r0}\n" // argc was in the stack
++ "mov %r1, %sp\n" // argv = sp
++ "add %r2, %r1, %r0, lsl #2\n" // envp = argv + 4*argc ...
++ "add %r2, %r2, $4\n" // ... + 4
++ "and %r3, %r1, $-8\n" // AAPCS : sp must be 8-byte aligned in the
++ "mov %sp, %r3\n" // callee, an bl doesn't push (lr=pc)
++ "bl main\n" // main() returns the status code, we'll exit with it.
++ "movs r7, $1\n" // NR_exit == 1
++ "svc $0x00\n"
++ "");
++
++#endif // _NOLIBC_ARCH_ARM_H
+diff --git a/tools/include/nolibc/arch-i386.h b/tools/include/nolibc/arch-i386.h
+new file mode 100644
+index 0000000000000..125a691fc631e
+--- /dev/null
++++ b/tools/include/nolibc/arch-i386.h
+@@ -0,0 +1,196 @@
++/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
++/*
++ * i386 specific definitions for NOLIBC
++ * Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu>
++ */
++
++#ifndef _NOLIBC_ARCH_I386_H
++#define _NOLIBC_ARCH_I386_H
++
++/* O_* macros for fcntl/open are architecture-specific */
++#define O_RDONLY 0
++#define O_WRONLY 1
++#define O_RDWR 2
++#define O_CREAT 0x40
++#define O_EXCL 0x80
++#define O_NOCTTY 0x100
++#define O_TRUNC 0x200
++#define O_APPEND 0x400
++#define O_NONBLOCK 0x800
++#define O_DIRECTORY 0x10000
++
++/* The struct returned by the stat() syscall, 32-bit only, the syscall returns
++ * exactly 56 bytes (stops before the unused array).
++ */
++struct sys_stat_struct {
++ unsigned long st_dev;
++ unsigned long st_ino;
++ unsigned short st_mode;
++ unsigned short st_nlink;
++ unsigned short st_uid;
++ unsigned short st_gid;
++
++ unsigned long st_rdev;
++ unsigned long st_size;
++ unsigned long st_blksize;
++ unsigned long st_blocks;
++
++ unsigned long st_atime;
++ unsigned long st_atime_nsec;
++ unsigned long st_mtime;
++ unsigned long st_mtime_nsec;
++
++ unsigned long st_ctime;
++ unsigned long st_ctime_nsec;
++ unsigned long __unused[2];
++};
++
++/* Syscalls for i386 :
++ * - mostly similar to x86_64
++ * - registers are 32-bit
++ * - syscall number is passed in eax
++ * - arguments are in ebx, ecx, edx, esi, edi, ebp respectively
++ * - all registers are preserved (except eax of course)
++ * - the system call is performed by calling int $0x80
++ * - syscall return comes in eax
++ * - the arguments are cast to long and assigned into the target registers
++ * which are then simply passed as registers to the asm code, so that we
++ * don't have to experience issues with register constraints.
++ * - the syscall number is always specified last in order to allow to force
++ * some registers before (gcc refuses a %-register at the last position).
++ *
++ * Also, i386 supports the old_select syscall if newselect is not available
++ */
++#define __ARCH_WANT_SYS_OLD_SELECT
++
++#define my_syscall0(num) \
++({ \
++ long _ret; \
++ register long _num asm("eax") = (num); \
++ \
++ asm volatile ( \
++ "int $0x80\n" \
++ : "=a" (_ret) \
++ : "0"(_num) \
++ : "memory", "cc" \
++ ); \
++ _ret; \
++})
++
++#define my_syscall1(num, arg1) \
++({ \
++ long _ret; \
++ register long _num asm("eax") = (num); \
++ register long _arg1 asm("ebx") = (long)(arg1); \
++ \
++ asm volatile ( \
++ "int $0x80\n" \
++ : "=a" (_ret) \
++ : "r"(_arg1), \
++ "0"(_num) \
++ : "memory", "cc" \
++ ); \
++ _ret; \
++})
++
++#define my_syscall2(num, arg1, arg2) \
++({ \
++ long _ret; \
++ register long _num asm("eax") = (num); \
++ register long _arg1 asm("ebx") = (long)(arg1); \
++ register long _arg2 asm("ecx") = (long)(arg2); \
++ \
++ asm volatile ( \
++ "int $0x80\n" \
++ : "=a" (_ret) \
++ : "r"(_arg1), "r"(_arg2), \
++ "0"(_num) \
++ : "memory", "cc" \
++ ); \
++ _ret; \
++})
++
++#define my_syscall3(num, arg1, arg2, arg3) \
++({ \
++ long _ret; \
++ register long _num asm("eax") = (num); \
++ register long _arg1 asm("ebx") = (long)(arg1); \
++ register long _arg2 asm("ecx") = (long)(arg2); \
++ register long _arg3 asm("edx") = (long)(arg3); \
++ \
++ asm volatile ( \
++ "int $0x80\n" \
++ : "=a" (_ret) \
++ : "r"(_arg1), "r"(_arg2), "r"(_arg3), \
++ "0"(_num) \
++ : "memory", "cc" \
++ ); \
++ _ret; \
++})
++
++#define my_syscall4(num, arg1, arg2, arg3, arg4) \
++({ \
++ long _ret; \
++ register long _num asm("eax") = (num); \
++ register long _arg1 asm("ebx") = (long)(arg1); \
++ register long _arg2 asm("ecx") = (long)(arg2); \
++ register long _arg3 asm("edx") = (long)(arg3); \
++ register long _arg4 asm("esi") = (long)(arg4); \
++ \
++ asm volatile ( \
++ "int $0x80\n" \
++ : "=a" (_ret) \
++ : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
++ "0"(_num) \
++ : "memory", "cc" \
++ ); \
++ _ret; \
++})
++
++#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
++({ \
++ long _ret; \
++ register long _num asm("eax") = (num); \
++ register long _arg1 asm("ebx") = (long)(arg1); \
++ register long _arg2 asm("ecx") = (long)(arg2); \
++ register long _arg3 asm("edx") = (long)(arg3); \
++ register long _arg4 asm("esi") = (long)(arg4); \
++ register long _arg5 asm("edi") = (long)(arg5); \
++ \
++ asm volatile ( \
++ "int $0x80\n" \
++ : "=a" (_ret) \
++ : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
++ "0"(_num) \
++ : "memory", "cc" \
++ ); \
++ _ret; \
++})
++
++/* startup code */
++/*
++ * i386 System V ABI mandates:
++ * 1) last pushed argument must be 16-byte aligned.
++ * 2) The deepest stack frame should be set to zero
++ *
++ */
++asm(".section .text\n"
++ ".weak _start\n"
++ "_start:\n"
++ "pop %eax\n" // argc (first arg, %eax)
++ "mov %esp, %ebx\n" // argv[] (second arg, %ebx)
++ "lea 4(%ebx,%eax,4),%ecx\n" // then a NULL then envp (third arg, %ecx)
++ "xor %ebp, %ebp\n" // zero the stack frame
++ "and $-16, %esp\n" // x86 ABI : esp must be 16-byte aligned before
++ "sub $4, %esp\n" // the call instruction (args are aligned)
++ "push %ecx\n" // push all registers on the stack so that we
++ "push %ebx\n" // support both regparm and plain stack modes
++ "push %eax\n"
++ "call main\n" // main() returns the status code in %eax
++ "mov %eax, %ebx\n" // retrieve exit code (32-bit int)
++ "movl $1, %eax\n" // NR_exit == 1
++ "int $0x80\n" // exit now
++ "hlt\n" // ensure it does not
++ "");
++
++#endif // _NOLIBC_ARCH_I386_H
+diff --git a/tools/include/nolibc/arch-mips.h b/tools/include/nolibc/arch-mips.h
+new file mode 100644
+index 0000000000000..5d647afa42e68
+--- /dev/null
++++ b/tools/include/nolibc/arch-mips.h
+@@ -0,0 +1,217 @@
++/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
++/*
++ * MIPS specific definitions for NOLIBC
++ * Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu>
++ */
++
++#ifndef _NOLIBC_ARCH_MIPS_H
++#define _NOLIBC_ARCH_MIPS_H
++
++/* O_* macros for fcntl/open are architecture-specific */
++#define O_RDONLY 0
++#define O_WRONLY 1
++#define O_RDWR 2
++#define O_APPEND 0x0008
++#define O_NONBLOCK 0x0080
++#define O_CREAT 0x0100
++#define O_TRUNC 0x0200
++#define O_EXCL 0x0400
++#define O_NOCTTY 0x0800
++#define O_DIRECTORY 0x10000
++
++/* The struct returned by the stat() syscall. 88 bytes are returned by the
++ * syscall.
++ */
++struct sys_stat_struct {
++ unsigned int st_dev;
++ long st_pad1[3];
++ unsigned long st_ino;
++ unsigned int st_mode;
++ unsigned int st_nlink;
++ unsigned int st_uid;
++ unsigned int st_gid;
++ unsigned int st_rdev;
++ long st_pad2[2];
++ long st_size;
++ long st_pad3;
++
++ long st_atime;
++ long st_atime_nsec;
++ long st_mtime;
++ long st_mtime_nsec;
++
++ long st_ctime;
++ long st_ctime_nsec;
++ long st_blksize;
++ long st_blocks;
++ long st_pad4[14];
++};
++
++/* Syscalls for MIPS ABI O32 :
++ * - WARNING! there's always a delayed slot!
++ * - WARNING again, the syntax is different, registers take a '$' and numbers
++ * do not.
++ * - registers are 32-bit
++ * - stack is 8-byte aligned
++ * - syscall number is passed in v0 (starts at 0xfa0).
++ * - arguments are in a0, a1, a2, a3, then the stack. The caller needs to
++ * leave some room in the stack for the callee to save a0..a3 if needed.
++ * - Many registers are clobbered, in fact only a0..a2 and s0..s8 are
++ * preserved. See: https://www.linux-mips.org/wiki/Syscall as well as
++ * scall32-o32.S in the kernel sources.
++ * - the system call is performed by calling "syscall"
++ * - syscall return comes in v0, and register a3 needs to be checked to know
++ * if an error occurred, in which case errno is in v0.
++ * - the arguments are cast to long and assigned into the target registers
++ * which are then simply passed as registers to the asm code, so that we
++ * don't have to experience issues with register constraints.
++ */
++
++#define my_syscall0(num) \
++({ \
++ register long _num asm("v0") = (num); \
++ register long _arg4 asm("a3"); \
++ \
++ asm volatile ( \
++ "addiu $sp, $sp, -32\n" \
++ "syscall\n" \
++ "addiu $sp, $sp, 32\n" \
++ : "=r"(_num), "=r"(_arg4) \
++ : "r"(_num) \
++ : "memory", "cc", "at", "v1", "hi", "lo", \
++ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
++ ); \
++ _arg4 ? -_num : _num; \
++})
++
++#define my_syscall1(num, arg1) \
++({ \
++ register long _num asm("v0") = (num); \
++ register long _arg1 asm("a0") = (long)(arg1); \
++ register long _arg4 asm("a3"); \
++ \
++ asm volatile ( \
++ "addiu $sp, $sp, -32\n" \
++ "syscall\n" \
++ "addiu $sp, $sp, 32\n" \
++ : "=r"(_num), "=r"(_arg4) \
++ : "0"(_num), \
++ "r"(_arg1) \
++ : "memory", "cc", "at", "v1", "hi", "lo", \
++ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
++ ); \
++ _arg4 ? -_num : _num; \
++})
++
++#define my_syscall2(num, arg1, arg2) \
++({ \
++ register long _num asm("v0") = (num); \
++ register long _arg1 asm("a0") = (long)(arg1); \
++ register long _arg2 asm("a1") = (long)(arg2); \
++ register long _arg4 asm("a3"); \
++ \
++ asm volatile ( \
++ "addiu $sp, $sp, -32\n" \
++ "syscall\n" \
++ "addiu $sp, $sp, 32\n" \
++ : "=r"(_num), "=r"(_arg4) \
++ : "0"(_num), \
++ "r"(_arg1), "r"(_arg2) \
++ : "memory", "cc", "at", "v1", "hi", "lo", \
++ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
++ ); \
++ _arg4 ? -_num : _num; \
++})
++
++#define my_syscall3(num, arg1, arg2, arg3) \
++({ \
++ register long _num asm("v0") = (num); \
++ register long _arg1 asm("a0") = (long)(arg1); \
++ register long _arg2 asm("a1") = (long)(arg2); \
++ register long _arg3 asm("a2") = (long)(arg3); \
++ register long _arg4 asm("a3"); \
++ \
++ asm volatile ( \
++ "addiu $sp, $sp, -32\n" \
++ "syscall\n" \
++ "addiu $sp, $sp, 32\n" \
++ : "=r"(_num), "=r"(_arg4) \
++ : "0"(_num), \
++ "r"(_arg1), "r"(_arg2), "r"(_arg3) \
++ : "memory", "cc", "at", "v1", "hi", "lo", \
++ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
++ ); \
++ _arg4 ? -_num : _num; \
++})
++
++#define my_syscall4(num, arg1, arg2, arg3, arg4) \
++({ \
++ register long _num asm("v0") = (num); \
++ register long _arg1 asm("a0") = (long)(arg1); \
++ register long _arg2 asm("a1") = (long)(arg2); \
++ register long _arg3 asm("a2") = (long)(arg3); \
++ register long _arg4 asm("a3") = (long)(arg4); \
++ \
++ asm volatile ( \
++ "addiu $sp, $sp, -32\n" \
++ "syscall\n" \
++ "addiu $sp, $sp, 32\n" \
++ : "=r" (_num), "=r"(_arg4) \
++ : "0"(_num), \
++ "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4) \
++ : "memory", "cc", "at", "v1", "hi", "lo", \
++ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
++ ); \
++ _arg4 ? -_num : _num; \
++})
++
++#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
++({ \
++ register long _num asm("v0") = (num); \
++ register long _arg1 asm("a0") = (long)(arg1); \
++ register long _arg2 asm("a1") = (long)(arg2); \
++ register long _arg3 asm("a2") = (long)(arg3); \
++ register long _arg4 asm("a3") = (long)(arg4); \
++ register long _arg5 = (long)(arg5); \
++ \
++ asm volatile ( \
++ "addiu $sp, $sp, -32\n" \
++ "sw %7, 16($sp)\n" \
++ "syscall\n " \
++ "addiu $sp, $sp, 32\n" \
++ : "=r" (_num), "=r"(_arg4) \
++ : "0"(_num), \
++ "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5) \
++ : "memory", "cc", "at", "v1", "hi", "lo", \
++ "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
++ ); \
++ _arg4 ? -_num : _num; \
++})
++
++/* startup code, note that it's called __start on MIPS */
++asm(".section .text\n"
++ ".weak __start\n"
++ ".set nomips16\n"
++ ".set push\n"
++ ".set noreorder\n"
++ ".option pic0\n"
++ ".ent __start\n"
++ "__start:\n"
++ "lw $a0,($sp)\n" // argc was in the stack
++ "addiu $a1, $sp, 4\n" // argv = sp + 4
++ "sll $a2, $a0, 2\n" // a2 = argc * 4
++ "add $a2, $a2, $a1\n" // envp = argv + 4*argc ...
++ "addiu $a2, $a2, 4\n" // ... + 4
++ "li $t0, -8\n"
++ "and $sp, $sp, $t0\n" // sp must be 8-byte aligned
++ "addiu $sp,$sp,-16\n" // the callee expects to save a0..a3 there!
++ "jal main\n" // main() returns the status code, we'll exit with it.
++ "nop\n" // delayed slot
++ "move $a0, $v0\n" // retrieve 32-bit exit code from v0
++ "li $v0, 4001\n" // NR_exit == 4001
++ "syscall\n"
++ ".end __start\n"
++ ".set pop\n"
++ "");
++
++#endif // _NOLIBC_ARCH_MIPS_H
+diff --git a/tools/include/nolibc/arch-riscv.h b/tools/include/nolibc/arch-riscv.h
+new file mode 100644
+index 0000000000000..8c0cb1abb29f7
+--- /dev/null
++++ b/tools/include/nolibc/arch-riscv.h
+@@ -0,0 +1,204 @@
++/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
++/*
++ * RISCV (32 and 64) specific definitions for NOLIBC
++ * Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu>
++ */
++
++#ifndef _NOLIBC_ARCH_RISCV_H
++#define _NOLIBC_ARCH_RISCV_H
++
++/* O_* macros for fcntl/open are architecture-specific */
++#define O_RDONLY 0
++#define O_WRONLY 1
++#define O_RDWR 2
++#define O_CREAT 0x40
++#define O_EXCL 0x80
++#define O_NOCTTY 0x100
++#define O_TRUNC 0x200
++#define O_APPEND 0x400
++#define O_NONBLOCK 0x800
++#define O_DIRECTORY 0x10000
++
++struct sys_stat_struct {
++ unsigned long st_dev; /* Device. */
++ unsigned long st_ino; /* File serial number. */
++ unsigned int st_mode; /* File mode. */
++ unsigned int st_nlink; /* Link count. */
++ unsigned int st_uid; /* User ID of the file's owner. */
++ unsigned int st_gid; /* Group ID of the file's group. */
++ unsigned long st_rdev; /* Device number, if device. */
++ unsigned long __pad1;
++ long st_size; /* Size of file, in bytes. */
++ int st_blksize; /* Optimal block size for I/O. */
++ int __pad2;
++ long st_blocks; /* Number 512-byte blocks allocated. */
++ long st_atime; /* Time of last access. */
++ unsigned long st_atime_nsec;
++ long st_mtime; /* Time of last modification. */
++ unsigned long st_mtime_nsec;
++ long st_ctime; /* Time of last status change. */
++ unsigned long st_ctime_nsec;
++ unsigned int __unused4;
++ unsigned int __unused5;
++};
++
++#if __riscv_xlen == 64
++#define PTRLOG "3"
++#define SZREG "8"
++#elif __riscv_xlen == 32
++#define PTRLOG "2"
++#define SZREG "4"
++#endif
++
++/* Syscalls for RISCV :
++ * - stack is 16-byte aligned
++ * - syscall number is passed in a7
++ * - arguments are in a0, a1, a2, a3, a4, a5
++ * - the system call is performed by calling ecall
++ * - syscall return comes in a0
++ * - the arguments are cast to long and assigned into the target
++ * registers which are then simply passed as registers to the asm code,
++ * so that we don't have to experience issues with register constraints.
++ *
++ * On riscv, select() is not implemented so we have to use pselect6().
++ */
++#define __ARCH_WANT_SYS_PSELECT6
++
++#define my_syscall0(num) \
++({ \
++ register long _num asm("a7") = (num); \
++ register long _arg1 asm("a0"); \
++ \
++ asm volatile ( \
++ "ecall\n\t" \
++ : "=r"(_arg1) \
++ : "r"(_num) \
++ : "memory", "cc" \
++ ); \
++ _arg1; \
++})
++
++#define my_syscall1(num, arg1) \
++({ \
++ register long _num asm("a7") = (num); \
++ register long _arg1 asm("a0") = (long)(arg1); \
++ \
++ asm volatile ( \
++ "ecall\n" \
++ : "+r"(_arg1) \
++ : "r"(_num) \
++ : "memory", "cc" \
++ ); \
++ _arg1; \
++})
++
++#define my_syscall2(num, arg1, arg2) \
++({ \
++ register long _num asm("a7") = (num); \
++ register long _arg1 asm("a0") = (long)(arg1); \
++ register long _arg2 asm("a1") = (long)(arg2); \
++ \
++ asm volatile ( \
++ "ecall\n" \
++ : "+r"(_arg1) \
++ : "r"(_arg2), \
++ "r"(_num) \
++ : "memory", "cc" \
++ ); \
++ _arg1; \
++})
++
++#define my_syscall3(num, arg1, arg2, arg3) \
++({ \
++ register long _num asm("a7") = (num); \
++ register long _arg1 asm("a0") = (long)(arg1); \
++ register long _arg2 asm("a1") = (long)(arg2); \
++ register long _arg3 asm("a2") = (long)(arg3); \
++ \
++ asm volatile ( \
++ "ecall\n\t" \
++ : "+r"(_arg1) \
++ : "r"(_arg2), "r"(_arg3), \
++ "r"(_num) \
++ : "memory", "cc" \
++ ); \
++ _arg1; \
++})
++
++#define my_syscall4(num, arg1, arg2, arg3, arg4) \
++({ \
++ register long _num asm("a7") = (num); \
++ register long _arg1 asm("a0") = (long)(arg1); \
++ register long _arg2 asm("a1") = (long)(arg2); \
++ register long _arg3 asm("a2") = (long)(arg3); \
++ register long _arg4 asm("a3") = (long)(arg4); \
++ \
++ asm volatile ( \
++ "ecall\n" \
++ : "+r"(_arg1) \
++ : "r"(_arg2), "r"(_arg3), "r"(_arg4), \
++ "r"(_num) \
++ : "memory", "cc" \
++ ); \
++ _arg1; \
++})
++
++#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
++({ \
++ register long _num asm("a7") = (num); \
++ register long _arg1 asm("a0") = (long)(arg1); \
++ register long _arg2 asm("a1") = (long)(arg2); \
++ register long _arg3 asm("a2") = (long)(arg3); \
++ register long _arg4 asm("a3") = (long)(arg4); \
++ register long _arg5 asm("a4") = (long)(arg5); \
++ \
++ asm volatile ( \
++ "ecall\n" \
++ : "+r"(_arg1) \
++ : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
++ "r"(_num) \
++ : "memory", "cc" \
++ ); \
++ _arg1; \
++})
++
++#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
++({ \
++ register long _num asm("a7") = (num); \
++ register long _arg1 asm("a0") = (long)(arg1); \
++ register long _arg2 asm("a1") = (long)(arg2); \
++ register long _arg3 asm("a2") = (long)(arg3); \
++ register long _arg4 asm("a3") = (long)(arg4); \
++ register long _arg5 asm("a4") = (long)(arg5); \
++ register long _arg6 asm("a5") = (long)(arg6); \
++ \
++ asm volatile ( \
++ "ecall\n" \
++ : "+r"(_arg1) \
++ : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \
++ "r"(_num) \
++ : "memory", "cc" \
++ ); \
++ _arg1; \
++})
++
++/* startup code */
++asm(".section .text\n"
++ ".weak _start\n"
++ "_start:\n"
++ ".option push\n"
++ ".option norelax\n"
++ "lla gp, __global_pointer$\n"
++ ".option pop\n"
++ "ld a0, 0(sp)\n" // argc (a0) was in the stack
++ "add a1, sp, "SZREG"\n" // argv (a1) = sp
++ "slli a2, a0, "PTRLOG"\n" // envp (a2) = SZREG*argc ...
++ "add a2, a2, "SZREG"\n" // + SZREG (skip null)
++ "add a2,a2,a1\n" // + argv
++ "andi sp,a1,-16\n" // sp must be 16-byte aligned
++ "call main\n" // main() returns the status code, we'll exit with it.
++ "li a7, 93\n" // NR_exit == 93
++ "ecall\n"
++ "");
++
++#endif // _NOLIBC_ARCH_RISCV_H
+diff --git a/tools/include/nolibc/arch-x86_64.h b/tools/include/nolibc/arch-x86_64.h
+new file mode 100644
+index 0000000000000..b1af63ce1cb0b
+--- /dev/null
++++ b/tools/include/nolibc/arch-x86_64.h
+@@ -0,0 +1,215 @@
++/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
++/*
++ * x86_64 specific definitions for NOLIBC
++ * Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu>
++ */
++
++#ifndef _NOLIBC_ARCH_X86_64_H
++#define _NOLIBC_ARCH_X86_64_H
++
++/* O_* macros for fcntl/open are architecture-specific */
++#define O_RDONLY 0
++#define O_WRONLY 1
++#define O_RDWR 2
++#define O_CREAT 0x40
++#define O_EXCL 0x80
++#define O_NOCTTY 0x100
++#define O_TRUNC 0x200
++#define O_APPEND 0x400
++#define O_NONBLOCK 0x800
++#define O_DIRECTORY 0x10000
++
++/* The struct returned by the stat() syscall, equivalent to stat64(). The
++ * syscall returns 116 bytes and stops in the middle of __unused.
++ */
++struct sys_stat_struct {
++ unsigned long st_dev;
++ unsigned long st_ino;
++ unsigned long st_nlink;
++ unsigned int st_mode;
++ unsigned int st_uid;
++
++ unsigned int st_gid;
++ unsigned int __pad0;
++ unsigned long st_rdev;
++ long st_size;
++ long st_blksize;
++
++ long st_blocks;
++ unsigned long st_atime;
++ unsigned long st_atime_nsec;
++ unsigned long st_mtime;
++
++ unsigned long st_mtime_nsec;
++ unsigned long st_ctime;
++ unsigned long st_ctime_nsec;
++ long __unused[3];
++};
++
++/* Syscalls for x86_64 :
++ * - registers are 64-bit
++ * - syscall number is passed in rax
++ * - arguments are in rdi, rsi, rdx, r10, r8, r9 respectively
++ * - the system call is performed by calling the syscall instruction
++ * - syscall return comes in rax
++ * - rcx and r11 are clobbered, others are preserved.
++ * - the arguments are cast to long and assigned into the target registers
++ * which are then simply passed as registers to the asm code, so that we
++ * don't have to experience issues with register constraints.
++ * - the syscall number is always specified last in order to allow to force
++ * some registers before (gcc refuses a %-register at the last position).
++ * - see also x86-64 ABI section A.2 AMD64 Linux Kernel Conventions, A.2.1
++ * Calling Conventions.
++ *
++ * Link x86-64 ABI: https://gitlab.com/x86-psABIs/x86-64-ABI/-/wikis/x86-64-psABI
++ *
++ */
++
++#define my_syscall0(num) \
++({ \
++ long _ret; \
++ register long _num asm("rax") = (num); \
++ \
++ asm volatile ( \
++ "syscall\n" \
++ : "=a"(_ret) \
++ : "0"(_num) \
++ : "rcx", "r11", "memory", "cc" \
++ ); \
++ _ret; \
++})
++
++#define my_syscall1(num, arg1) \
++({ \
++ long _ret; \
++ register long _num asm("rax") = (num); \
++ register long _arg1 asm("rdi") = (long)(arg1); \
++ \
++ asm volatile ( \
++ "syscall\n" \
++ : "=a"(_ret) \
++ : "r"(_arg1), \
++ "0"(_num) \
++ : "rcx", "r11", "memory", "cc" \
++ ); \
++ _ret; \
++})
++
++#define my_syscall2(num, arg1, arg2) \
++({ \
++ long _ret; \
++ register long _num asm("rax") = (num); \
++ register long _arg1 asm("rdi") = (long)(arg1); \
++ register long _arg2 asm("rsi") = (long)(arg2); \
++ \
++ asm volatile ( \
++ "syscall\n" \
++ : "=a"(_ret) \
++ : "r"(_arg1), "r"(_arg2), \
++ "0"(_num) \
++ : "rcx", "r11", "memory", "cc" \
++ ); \
++ _ret; \
++})
++
++#define my_syscall3(num, arg1, arg2, arg3) \
++({ \
++ long _ret; \
++ register long _num asm("rax") = (num); \
++ register long _arg1 asm("rdi") = (long)(arg1); \
++ register long _arg2 asm("rsi") = (long)(arg2); \
++ register long _arg3 asm("rdx") = (long)(arg3); \
++ \
++ asm volatile ( \
++ "syscall\n" \
++ : "=a"(_ret) \
++ : "r"(_arg1), "r"(_arg2), "r"(_arg3), \
++ "0"(_num) \
++ : "rcx", "r11", "memory", "cc" \
++ ); \
++ _ret; \
++})
++
++#define my_syscall4(num, arg1, arg2, arg3, arg4) \
++({ \
++ long _ret; \
++ register long _num asm("rax") = (num); \
++ register long _arg1 asm("rdi") = (long)(arg1); \
++ register long _arg2 asm("rsi") = (long)(arg2); \
++ register long _arg3 asm("rdx") = (long)(arg3); \
++ register long _arg4 asm("r10") = (long)(arg4); \
++ \
++ asm volatile ( \
++ "syscall\n" \
++ : "=a"(_ret) \
++ : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
++ "0"(_num) \
++ : "rcx", "r11", "memory", "cc" \
++ ); \
++ _ret; \
++})
++
++#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
++({ \
++ long _ret; \
++ register long _num asm("rax") = (num); \
++ register long _arg1 asm("rdi") = (long)(arg1); \
++ register long _arg2 asm("rsi") = (long)(arg2); \
++ register long _arg3 asm("rdx") = (long)(arg3); \
++ register long _arg4 asm("r10") = (long)(arg4); \
++ register long _arg5 asm("r8") = (long)(arg5); \
++ \
++ asm volatile ( \
++ "syscall\n" \
++ : "=a"(_ret) \
++ : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
++ "0"(_num) \
++ : "rcx", "r11", "memory", "cc" \
++ ); \
++ _ret; \
++})
++
++#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
++({ \
++ long _ret; \
++ register long _num asm("rax") = (num); \
++ register long _arg1 asm("rdi") = (long)(arg1); \
++ register long _arg2 asm("rsi") = (long)(arg2); \
++ register long _arg3 asm("rdx") = (long)(arg3); \
++ register long _arg4 asm("r10") = (long)(arg4); \
++ register long _arg5 asm("r8") = (long)(arg5); \
++ register long _arg6 asm("r9") = (long)(arg6); \
++ \
++ asm volatile ( \
++ "syscall\n" \
++ : "=a"(_ret) \
++ : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
++ "r"(_arg6), "0"(_num) \
++ : "rcx", "r11", "memory", "cc" \
++ ); \
++ _ret; \
++})
++
++/* startup code */
++/*
++ * x86-64 System V ABI mandates:
++ * 1) %rsp must be 16-byte aligned right before the function call.
++ * 2) The deepest stack frame should be zero (the %rbp).
++ *
++ */
++asm(".section .text\n"
++ ".weak _start\n"
++ "_start:\n"
++ "pop %rdi\n" // argc (first arg, %rdi)
++ "mov %rsp, %rsi\n" // argv[] (second arg, %rsi)
++ "lea 8(%rsi,%rdi,8),%rdx\n" // then a NULL then envp (third arg, %rdx)
++ "xor %ebp, %ebp\n" // zero the stack frame
++ "and $-16, %rsp\n" // x86 ABI : esp must be 16-byte aligned before call
++ "call main\n" // main() returns the status code, we'll exit with it.
++ "mov %eax, %edi\n" // retrieve exit code (32 bit)
++ "mov $60, %eax\n" // NR_exit == 60
++ "syscall\n" // really exit
++ "hlt\n" // ensure it does not return
++ "");
++
++#endif // _NOLIBC_ARCH_X86_64_H
+diff --git a/tools/include/nolibc/arch.h b/tools/include/nolibc/arch.h
+new file mode 100644
+index 0000000000000..4c6992321b0d6
+--- /dev/null
++++ b/tools/include/nolibc/arch.h
+@@ -0,0 +1,32 @@
++/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
++/*
++ * Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu>
++ */
++
++/* Below comes the architecture-specific code. For each architecture, we have
++ * the syscall declarations and the _start code definition. This is the only
++ * global part. On all architectures the kernel puts everything in the stack
++ * before jumping to _start just above us, without any return address (_start
++ * is not a function but an entry pint). So at the stack pointer we find argc.
++ * Then argv[] begins, and ends at the first NULL. Then we have envp which
++ * starts and ends with a NULL as well. So envp=argv+argc+1.
++ */
++
++#ifndef _NOLIBC_ARCH_H
++#define _NOLIBC_ARCH_H
++
++#if defined(__x86_64__)
++#include "arch-x86_64.h"
++#elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
++#include "arch-i386.h"
++#elif defined(__ARM_EABI__)
++#include "arch-arm.h"
++#elif defined(__aarch64__)
++#include "arch-aarch64.h"
++#elif defined(__mips__) && defined(_ABIO32)
++#include "arch-mips.h"
++#elif defined(__riscv)
++#include "arch-riscv.h"
++#endif
++
++#endif /* _NOLIBC_ARCH_H */
+diff --git a/tools/include/nolibc/nolibc.h b/tools/include/nolibc/nolibc.h
+index d64020c1922c2..d272b721dc519 100644
+--- a/tools/include/nolibc/nolibc.h
++++ b/tools/include/nolibc/nolibc.h
+@@ -81,13 +81,21 @@
+ *
+ */
+
++/* standard type definitions */
++#include "std.h"
++
++/* system includes */
+ #include <asm/unistd.h>
++#include <asm/signal.h> // for SIGCHLD
+ #include <asm/ioctls.h>
+ #include <asm/errno.h>
+ #include <linux/fs.h>
+ #include <linux/loop.h>
+ #include <linux/time.h>
++#include "arch.h"
++#include "types.h"
+
++/* Used by programs to avoid std includes */
+ #define NOLIBC
+
+ /* this way it will be removed if unused */
+@@ -104,1329 +112,6 @@ static int errno;
+ */
+ #define MAX_ERRNO 4095
+
+-/* Declare a few quite common macros and types that usually are in stdlib.h,
+- * stdint.h, ctype.h, unistd.h and a few other common locations.
+- */
+-
+-#define NULL ((void *)0)
+-
+-/* stdint types */
+-typedef unsigned char uint8_t;
+-typedef signed char int8_t;
+-typedef unsigned short uint16_t;
+-typedef signed short int16_t;
+-typedef unsigned int uint32_t;
+-typedef signed int int32_t;
+-typedef unsigned long long uint64_t;
+-typedef signed long long int64_t;
+-typedef unsigned long size_t;
+-typedef signed long ssize_t;
+-typedef unsigned long uintptr_t;
+-typedef signed long intptr_t;
+-typedef signed long ptrdiff_t;
+-
+-/* for stat() */
+-typedef unsigned int dev_t;
+-typedef unsigned long ino_t;
+-typedef unsigned int mode_t;
+-typedef signed int pid_t;
+-typedef unsigned int uid_t;
+-typedef unsigned int gid_t;
+-typedef unsigned long nlink_t;
+-typedef signed long off_t;
+-typedef signed long blksize_t;
+-typedef signed long blkcnt_t;
+-typedef signed long time_t;
+-
+-/* for poll() */
+-struct pollfd {
+- int fd;
+- short int events;
+- short int revents;
+-};
+-
+-/* for getdents64() */
+-struct linux_dirent64 {
+- uint64_t d_ino;
+- int64_t d_off;
+- unsigned short d_reclen;
+- unsigned char d_type;
+- char d_name[];
+-};
+-
+-/* commonly an fd_set represents 256 FDs */
+-#define FD_SETSIZE 256
+-typedef struct { uint32_t fd32[FD_SETSIZE/32]; } fd_set;
+-
+-/* needed by wait4() */
+-struct rusage {
+- struct timeval ru_utime;
+- struct timeval ru_stime;
+- long ru_maxrss;
+- long ru_ixrss;
+- long ru_idrss;
+- long ru_isrss;
+- long ru_minflt;
+- long ru_majflt;
+- long ru_nswap;
+- long ru_inblock;
+- long ru_oublock;
+- long ru_msgsnd;
+- long ru_msgrcv;
+- long ru_nsignals;
+- long ru_nvcsw;
+- long ru_nivcsw;
+-};
+-
+-/* stat flags (WARNING, octal here) */
+-#define S_IFDIR 0040000
+-#define S_IFCHR 0020000
+-#define S_IFBLK 0060000
+-#define S_IFREG 0100000
+-#define S_IFIFO 0010000
+-#define S_IFLNK 0120000
+-#define S_IFSOCK 0140000
+-#define S_IFMT 0170000
+-
+-#define S_ISDIR(mode) (((mode) & S_IFDIR) == S_IFDIR)
+-#define S_ISCHR(mode) (((mode) & S_IFCHR) == S_IFCHR)
+-#define S_ISBLK(mode) (((mode) & S_IFBLK) == S_IFBLK)
+-#define S_ISREG(mode) (((mode) & S_IFREG) == S_IFREG)
+-#define S_ISFIFO(mode) (((mode) & S_IFIFO) == S_IFIFO)
+-#define S_ISLNK(mode) (((mode) & S_IFLNK) == S_IFLNK)
+-#define S_ISSOCK(mode) (((mode) & S_IFSOCK) == S_IFSOCK)
+-
+-#define DT_UNKNOWN 0
+-#define DT_FIFO 1
+-#define DT_CHR 2
+-#define DT_DIR 4
+-#define DT_BLK 6
+-#define DT_REG 8
+-#define DT_LNK 10
+-#define DT_SOCK 12
+-
+-/* all the *at functions */
+-#ifndef AT_FDCWD
+-#define AT_FDCWD -100
+-#endif
+-
+-/* lseek */
+-#define SEEK_SET 0
+-#define SEEK_CUR 1
+-#define SEEK_END 2
+-
+-/* reboot */
+-#define LINUX_REBOOT_MAGIC1 0xfee1dead
+-#define LINUX_REBOOT_MAGIC2 0x28121969
+-#define LINUX_REBOOT_CMD_HALT 0xcdef0123
+-#define LINUX_REBOOT_CMD_POWER_OFF 0x4321fedc
+-#define LINUX_REBOOT_CMD_RESTART 0x01234567
+-#define LINUX_REBOOT_CMD_SW_SUSPEND 0xd000fce2
+-
+-
+-/* The format of the struct as returned by the libc to the application, which
+- * significantly differs from the format returned by the stat() syscall flavours.
+- */
+-struct stat {
+- dev_t st_dev; /* ID of device containing file */
+- ino_t st_ino; /* inode number */
+- mode_t st_mode; /* protection */
+- nlink_t st_nlink; /* number of hard links */
+- uid_t st_uid; /* user ID of owner */
+- gid_t st_gid; /* group ID of owner */
+- dev_t st_rdev; /* device ID (if special file) */
+- off_t st_size; /* total size, in bytes */
+- blksize_t st_blksize; /* blocksize for file system I/O */
+- blkcnt_t st_blocks; /* number of 512B blocks allocated */
+- time_t st_atime; /* time of last access */
+- time_t st_mtime; /* time of last modification */
+- time_t st_ctime; /* time of last status change */
+-};
+-
+-#define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
+-#define WIFEXITED(status) (((status) & 0x7f) == 0)
+-
+-/* for SIGCHLD */
+-#include <asm/signal.h>
+-
+-/* Below comes the architecture-specific code. For each architecture, we have
+- * the syscall declarations and the _start code definition. This is the only
+- * global part. On all architectures the kernel puts everything in the stack
+- * before jumping to _start just above us, without any return address (_start
+- * is not a function but an entry pint). So at the stack pointer we find argc.
+- * Then argv[] begins, and ends at the first NULL. Then we have envp which
+- * starts and ends with a NULL as well. So envp=argv+argc+1.
+- */
+-
+-#if defined(__x86_64__)
+-/* Syscalls for x86_64 :
+- * - registers are 64-bit
+- * - syscall number is passed in rax
+- * - arguments are in rdi, rsi, rdx, r10, r8, r9 respectively
+- * - the system call is performed by calling the syscall instruction
+- * - syscall return comes in rax
+- * - rcx and r8..r11 may be clobbered, others are preserved.
+- * - the arguments are cast to long and assigned into the target registers
+- * which are then simply passed as registers to the asm code, so that we
+- * don't have to experience issues with register constraints.
+- * - the syscall number is always specified last in order to allow to force
+- * some registers before (gcc refuses a %-register at the last position).
+- */
+-
+-#define my_syscall0(num) \
+-({ \
+- long _ret; \
+- register long _num asm("rax") = (num); \
+- \
+- asm volatile ( \
+- "syscall\n" \
+- : "=a" (_ret) \
+- : "0"(_num) \
+- : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \
+- ); \
+- _ret; \
+-})
+-
+-#define my_syscall1(num, arg1) \
+-({ \
+- long _ret; \
+- register long _num asm("rax") = (num); \
+- register long _arg1 asm("rdi") = (long)(arg1); \
+- \
+- asm volatile ( \
+- "syscall\n" \
+- : "=a" (_ret) \
+- : "r"(_arg1), \
+- "0"(_num) \
+- : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \
+- ); \
+- _ret; \
+-})
+-
+-#define my_syscall2(num, arg1, arg2) \
+-({ \
+- long _ret; \
+- register long _num asm("rax") = (num); \
+- register long _arg1 asm("rdi") = (long)(arg1); \
+- register long _arg2 asm("rsi") = (long)(arg2); \
+- \
+- asm volatile ( \
+- "syscall\n" \
+- : "=a" (_ret) \
+- : "r"(_arg1), "r"(_arg2), \
+- "0"(_num) \
+- : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \
+- ); \
+- _ret; \
+-})
+-
+-#define my_syscall3(num, arg1, arg2, arg3) \
+-({ \
+- long _ret; \
+- register long _num asm("rax") = (num); \
+- register long _arg1 asm("rdi") = (long)(arg1); \
+- register long _arg2 asm("rsi") = (long)(arg2); \
+- register long _arg3 asm("rdx") = (long)(arg3); \
+- \
+- asm volatile ( \
+- "syscall\n" \
+- : "=a" (_ret) \
+- : "r"(_arg1), "r"(_arg2), "r"(_arg3), \
+- "0"(_num) \
+- : "rcx", "r8", "r9", "r10", "r11", "memory", "cc" \
+- ); \
+- _ret; \
+-})
+-
+-#define my_syscall4(num, arg1, arg2, arg3, arg4) \
+-({ \
+- long _ret; \
+- register long _num asm("rax") = (num); \
+- register long _arg1 asm("rdi") = (long)(arg1); \
+- register long _arg2 asm("rsi") = (long)(arg2); \
+- register long _arg3 asm("rdx") = (long)(arg3); \
+- register long _arg4 asm("r10") = (long)(arg4); \
+- \
+- asm volatile ( \
+- "syscall\n" \
+- : "=a" (_ret), "=r"(_arg4) \
+- : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
+- "0"(_num) \
+- : "rcx", "r8", "r9", "r11", "memory", "cc" \
+- ); \
+- _ret; \
+-})
+-
+-#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
+-({ \
+- long _ret; \
+- register long _num asm("rax") = (num); \
+- register long _arg1 asm("rdi") = (long)(arg1); \
+- register long _arg2 asm("rsi") = (long)(arg2); \
+- register long _arg3 asm("rdx") = (long)(arg3); \
+- register long _arg4 asm("r10") = (long)(arg4); \
+- register long _arg5 asm("r8") = (long)(arg5); \
+- \
+- asm volatile ( \
+- "syscall\n" \
+- : "=a" (_ret), "=r"(_arg4), "=r"(_arg5) \
+- : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
+- "0"(_num) \
+- : "rcx", "r9", "r11", "memory", "cc" \
+- ); \
+- _ret; \
+-})
+-
+-#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
+-({ \
+- long _ret; \
+- register long _num asm("rax") = (num); \
+- register long _arg1 asm("rdi") = (long)(arg1); \
+- register long _arg2 asm("rsi") = (long)(arg2); \
+- register long _arg3 asm("rdx") = (long)(arg3); \
+- register long _arg4 asm("r10") = (long)(arg4); \
+- register long _arg5 asm("r8") = (long)(arg5); \
+- register long _arg6 asm("r9") = (long)(arg6); \
+- \
+- asm volatile ( \
+- "syscall\n" \
+- : "=a" (_ret), "=r"(_arg4), "=r"(_arg5) \
+- : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
+- "r"(_arg6), "0"(_num) \
+- : "rcx", "r11", "memory", "cc" \
+- ); \
+- _ret; \
+-})
+-
+-/* startup code */
+-/*
+- * x86-64 System V ABI mandates:
+- * 1) %rsp must be 16-byte aligned right before the function call.
+- * 2) The deepest stack frame should be zero (the %rbp).
+- *
+- */
+-asm(".section .text\n"
+- ".global _start\n"
+- "_start:\n"
+- "pop %rdi\n" // argc (first arg, %rdi)
+- "mov %rsp, %rsi\n" // argv[] (second arg, %rsi)
+- "lea 8(%rsi,%rdi,8),%rdx\n" // then a NULL then envp (third arg, %rdx)
+- "xor %ebp, %ebp\n" // zero the stack frame
+- "and $-16, %rsp\n" // x86 ABI : esp must be 16-byte aligned before call
+- "call main\n" // main() returns the status code, we'll exit with it.
+- "mov %eax, %edi\n" // retrieve exit code (32 bit)
+- "mov $60, %rax\n" // NR_exit == 60
+- "syscall\n" // really exit
+- "hlt\n" // ensure it does not return
+- "");
+-
+-/* fcntl / open */
+-#define O_RDONLY 0
+-#define O_WRONLY 1
+-#define O_RDWR 2
+-#define O_CREAT 0x40
+-#define O_EXCL 0x80
+-#define O_NOCTTY 0x100
+-#define O_TRUNC 0x200
+-#define O_APPEND 0x400
+-#define O_NONBLOCK 0x800
+-#define O_DIRECTORY 0x10000
+-
+-/* The struct returned by the stat() syscall, equivalent to stat64(). The
+- * syscall returns 116 bytes and stops in the middle of __unused.
+- */
+-struct sys_stat_struct {
+- unsigned long st_dev;
+- unsigned long st_ino;
+- unsigned long st_nlink;
+- unsigned int st_mode;
+- unsigned int st_uid;
+-
+- unsigned int st_gid;
+- unsigned int __pad0;
+- unsigned long st_rdev;
+- long st_size;
+- long st_blksize;
+-
+- long st_blocks;
+- unsigned long st_atime;
+- unsigned long st_atime_nsec;
+- unsigned long st_mtime;
+-
+- unsigned long st_mtime_nsec;
+- unsigned long st_ctime;
+- unsigned long st_ctime_nsec;
+- long __unused[3];
+-};
+-
+-#elif defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__)
+-/* Syscalls for i386 :
+- * - mostly similar to x86_64
+- * - registers are 32-bit
+- * - syscall number is passed in eax
+- * - arguments are in ebx, ecx, edx, esi, edi, ebp respectively
+- * - all registers are preserved (except eax of course)
+- * - the system call is performed by calling int $0x80
+- * - syscall return comes in eax
+- * - the arguments are cast to long and assigned into the target registers
+- * which are then simply passed as registers to the asm code, so that we
+- * don't have to experience issues with register constraints.
+- * - the syscall number is always specified last in order to allow to force
+- * some registers before (gcc refuses a %-register at the last position).
+- *
+- * Also, i386 supports the old_select syscall if newselect is not available
+- */
+-#define __ARCH_WANT_SYS_OLD_SELECT
+-
+-#define my_syscall0(num) \
+-({ \
+- long _ret; \
+- register long _num asm("eax") = (num); \
+- \
+- asm volatile ( \
+- "int $0x80\n" \
+- : "=a" (_ret) \
+- : "0"(_num) \
+- : "memory", "cc" \
+- ); \
+- _ret; \
+-})
+-
+-#define my_syscall1(num, arg1) \
+-({ \
+- long _ret; \
+- register long _num asm("eax") = (num); \
+- register long _arg1 asm("ebx") = (long)(arg1); \
+- \
+- asm volatile ( \
+- "int $0x80\n" \
+- : "=a" (_ret) \
+- : "r"(_arg1), \
+- "0"(_num) \
+- : "memory", "cc" \
+- ); \
+- _ret; \
+-})
+-
+-#define my_syscall2(num, arg1, arg2) \
+-({ \
+- long _ret; \
+- register long _num asm("eax") = (num); \
+- register long _arg1 asm("ebx") = (long)(arg1); \
+- register long _arg2 asm("ecx") = (long)(arg2); \
+- \
+- asm volatile ( \
+- "int $0x80\n" \
+- : "=a" (_ret) \
+- : "r"(_arg1), "r"(_arg2), \
+- "0"(_num) \
+- : "memory", "cc" \
+- ); \
+- _ret; \
+-})
+-
+-#define my_syscall3(num, arg1, arg2, arg3) \
+-({ \
+- long _ret; \
+- register long _num asm("eax") = (num); \
+- register long _arg1 asm("ebx") = (long)(arg1); \
+- register long _arg2 asm("ecx") = (long)(arg2); \
+- register long _arg3 asm("edx") = (long)(arg3); \
+- \
+- asm volatile ( \
+- "int $0x80\n" \
+- : "=a" (_ret) \
+- : "r"(_arg1), "r"(_arg2), "r"(_arg3), \
+- "0"(_num) \
+- : "memory", "cc" \
+- ); \
+- _ret; \
+-})
+-
+-#define my_syscall4(num, arg1, arg2, arg3, arg4) \
+-({ \
+- long _ret; \
+- register long _num asm("eax") = (num); \
+- register long _arg1 asm("ebx") = (long)(arg1); \
+- register long _arg2 asm("ecx") = (long)(arg2); \
+- register long _arg3 asm("edx") = (long)(arg3); \
+- register long _arg4 asm("esi") = (long)(arg4); \
+- \
+- asm volatile ( \
+- "int $0x80\n" \
+- : "=a" (_ret) \
+- : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
+- "0"(_num) \
+- : "memory", "cc" \
+- ); \
+- _ret; \
+-})
+-
+-#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
+-({ \
+- long _ret; \
+- register long _num asm("eax") = (num); \
+- register long _arg1 asm("ebx") = (long)(arg1); \
+- register long _arg2 asm("ecx") = (long)(arg2); \
+- register long _arg3 asm("edx") = (long)(arg3); \
+- register long _arg4 asm("esi") = (long)(arg4); \
+- register long _arg5 asm("edi") = (long)(arg5); \
+- \
+- asm volatile ( \
+- "int $0x80\n" \
+- : "=a" (_ret) \
+- : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
+- "0"(_num) \
+- : "memory", "cc" \
+- ); \
+- _ret; \
+-})
+-
+-/* startup code */
+-/*
+- * i386 System V ABI mandates:
+- * 1) last pushed argument must be 16-byte aligned.
+- * 2) The deepest stack frame should be set to zero
+- *
+- */
+-asm(".section .text\n"
+- ".global _start\n"
+- "_start:\n"
+- "pop %eax\n" // argc (first arg, %eax)
+- "mov %esp, %ebx\n" // argv[] (second arg, %ebx)
+- "lea 4(%ebx,%eax,4),%ecx\n" // then a NULL then envp (third arg, %ecx)
+- "xor %ebp, %ebp\n" // zero the stack frame
+- "and $-16, %esp\n" // x86 ABI : esp must be 16-byte aligned before
+- "sub $4, %esp\n" // the call instruction (args are aligned)
+- "push %ecx\n" // push all registers on the stack so that we
+- "push %ebx\n" // support both regparm and plain stack modes
+- "push %eax\n"
+- "call main\n" // main() returns the status code in %eax
+- "mov %eax, %ebx\n" // retrieve exit code (32-bit int)
+- "movl $1, %eax\n" // NR_exit == 1
+- "int $0x80\n" // exit now
+- "hlt\n" // ensure it does not
+- "");
+-
+-/* fcntl / open */
+-#define O_RDONLY 0
+-#define O_WRONLY 1
+-#define O_RDWR 2
+-#define O_CREAT 0x40
+-#define O_EXCL 0x80
+-#define O_NOCTTY 0x100
+-#define O_TRUNC 0x200
+-#define O_APPEND 0x400
+-#define O_NONBLOCK 0x800
+-#define O_DIRECTORY 0x10000
+-
+-/* The struct returned by the stat() syscall, 32-bit only, the syscall returns
+- * exactly 56 bytes (stops before the unused array).
+- */
+-struct sys_stat_struct {
+- unsigned long st_dev;
+- unsigned long st_ino;
+- unsigned short st_mode;
+- unsigned short st_nlink;
+- unsigned short st_uid;
+- unsigned short st_gid;
+-
+- unsigned long st_rdev;
+- unsigned long st_size;
+- unsigned long st_blksize;
+- unsigned long st_blocks;
+-
+- unsigned long st_atime;
+- unsigned long st_atime_nsec;
+- unsigned long st_mtime;
+- unsigned long st_mtime_nsec;
+-
+- unsigned long st_ctime;
+- unsigned long st_ctime_nsec;
+- unsigned long __unused[2];
+-};
+-
+-#elif defined(__ARM_EABI__)
+-/* Syscalls for ARM in ARM or Thumb modes :
+- * - registers are 32-bit
+- * - stack is 8-byte aligned
+- * ( http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka4127.html)
+- * - syscall number is passed in r7
+- * - arguments are in r0, r1, r2, r3, r4, r5
+- * - the system call is performed by calling svc #0
+- * - syscall return comes in r0.
+- * - only lr is clobbered.
+- * - the arguments are cast to long and assigned into the target registers
+- * which are then simply passed as registers to the asm code, so that we
+- * don't have to experience issues with register constraints.
+- * - the syscall number is always specified last in order to allow to force
+- * some registers before (gcc refuses a %-register at the last position).
+- *
+- * Also, ARM supports the old_select syscall if newselect is not available
+- */
+-#define __ARCH_WANT_SYS_OLD_SELECT
+-
+-#define my_syscall0(num) \
+-({ \
+- register long _num asm("r7") = (num); \
+- register long _arg1 asm("r0"); \
+- \
+- asm volatile ( \
+- "svc #0\n" \
+- : "=r"(_arg1) \
+- : "r"(_num) \
+- : "memory", "cc", "lr" \
+- ); \
+- _arg1; \
+-})
+-
+-#define my_syscall1(num, arg1) \
+-({ \
+- register long _num asm("r7") = (num); \
+- register long _arg1 asm("r0") = (long)(arg1); \
+- \
+- asm volatile ( \
+- "svc #0\n" \
+- : "=r"(_arg1) \
+- : "r"(_arg1), \
+- "r"(_num) \
+- : "memory", "cc", "lr" \
+- ); \
+- _arg1; \
+-})
+-
+-#define my_syscall2(num, arg1, arg2) \
+-({ \
+- register long _num asm("r7") = (num); \
+- register long _arg1 asm("r0") = (long)(arg1); \
+- register long _arg2 asm("r1") = (long)(arg2); \
+- \
+- asm volatile ( \
+- "svc #0\n" \
+- : "=r"(_arg1) \
+- : "r"(_arg1), "r"(_arg2), \
+- "r"(_num) \
+- : "memory", "cc", "lr" \
+- ); \
+- _arg1; \
+-})
+-
+-#define my_syscall3(num, arg1, arg2, arg3) \
+-({ \
+- register long _num asm("r7") = (num); \
+- register long _arg1 asm("r0") = (long)(arg1); \
+- register long _arg2 asm("r1") = (long)(arg2); \
+- register long _arg3 asm("r2") = (long)(arg3); \
+- \
+- asm volatile ( \
+- "svc #0\n" \
+- : "=r"(_arg1) \
+- : "r"(_arg1), "r"(_arg2), "r"(_arg3), \
+- "r"(_num) \
+- : "memory", "cc", "lr" \
+- ); \
+- _arg1; \
+-})
+-
+-#define my_syscall4(num, arg1, arg2, arg3, arg4) \
+-({ \
+- register long _num asm("r7") = (num); \
+- register long _arg1 asm("r0") = (long)(arg1); \
+- register long _arg2 asm("r1") = (long)(arg2); \
+- register long _arg3 asm("r2") = (long)(arg3); \
+- register long _arg4 asm("r3") = (long)(arg4); \
+- \
+- asm volatile ( \
+- "svc #0\n" \
+- : "=r"(_arg1) \
+- : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
+- "r"(_num) \
+- : "memory", "cc", "lr" \
+- ); \
+- _arg1; \
+-})
+-
+-#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
+-({ \
+- register long _num asm("r7") = (num); \
+- register long _arg1 asm("r0") = (long)(arg1); \
+- register long _arg2 asm("r1") = (long)(arg2); \
+- register long _arg3 asm("r2") = (long)(arg3); \
+- register long _arg4 asm("r3") = (long)(arg4); \
+- register long _arg5 asm("r4") = (long)(arg5); \
+- \
+- asm volatile ( \
+- "svc #0\n" \
+- : "=r" (_arg1) \
+- : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
+- "r"(_num) \
+- : "memory", "cc", "lr" \
+- ); \
+- _arg1; \
+-})
+-
+-/* startup code */
+-asm(".section .text\n"
+- ".global _start\n"
+- "_start:\n"
+-#if defined(__THUMBEB__) || defined(__THUMBEL__)
+- /* We enter here in 32-bit mode but if some previous functions were in
+- * 16-bit mode, the assembler cannot know, so we need to tell it we're in
+- * 32-bit now, then switch to 16-bit (is there a better way to do it than
+- * adding 1 by hand ?) and tell the asm we're now in 16-bit mode so that
+- * it generates correct instructions. Note that we do not support thumb1.
+- */
+- ".code 32\n"
+- "add r0, pc, #1\n"
+- "bx r0\n"
+- ".code 16\n"
+-#endif
+- "pop {%r0}\n" // argc was in the stack
+- "mov %r1, %sp\n" // argv = sp
+- "add %r2, %r1, %r0, lsl #2\n" // envp = argv + 4*argc ...
+- "add %r2, %r2, $4\n" // ... + 4
+- "and %r3, %r1, $-8\n" // AAPCS : sp must be 8-byte aligned in the
+- "mov %sp, %r3\n" // callee, an bl doesn't push (lr=pc)
+- "bl main\n" // main() returns the status code, we'll exit with it.
+- "movs r7, $1\n" // NR_exit == 1
+- "svc $0x00\n"
+- "");
+-
+-/* fcntl / open */
+-#define O_RDONLY 0
+-#define O_WRONLY 1
+-#define O_RDWR 2
+-#define O_CREAT 0x40
+-#define O_EXCL 0x80
+-#define O_NOCTTY 0x100
+-#define O_TRUNC 0x200
+-#define O_APPEND 0x400
+-#define O_NONBLOCK 0x800
+-#define O_DIRECTORY 0x4000
+-
+-/* The struct returned by the stat() syscall, 32-bit only, the syscall returns
+- * exactly 56 bytes (stops before the unused array). In big endian, the format
+- * differs as devices are returned as short only.
+- */
+-struct sys_stat_struct {
+-#if defined(__ARMEB__)
+- unsigned short st_dev;
+- unsigned short __pad1;
+-#else
+- unsigned long st_dev;
+-#endif
+- unsigned long st_ino;
+- unsigned short st_mode;
+- unsigned short st_nlink;
+- unsigned short st_uid;
+- unsigned short st_gid;
+-#if defined(__ARMEB__)
+- unsigned short st_rdev;
+- unsigned short __pad2;
+-#else
+- unsigned long st_rdev;
+-#endif
+- unsigned long st_size;
+- unsigned long st_blksize;
+- unsigned long st_blocks;
+- unsigned long st_atime;
+- unsigned long st_atime_nsec;
+- unsigned long st_mtime;
+- unsigned long st_mtime_nsec;
+- unsigned long st_ctime;
+- unsigned long st_ctime_nsec;
+- unsigned long __unused[2];
+-};
+-
+-#elif defined(__aarch64__)
+-/* Syscalls for AARCH64 :
+- * - registers are 64-bit
+- * - stack is 16-byte aligned
+- * - syscall number is passed in x8
+- * - arguments are in x0, x1, x2, x3, x4, x5
+- * - the system call is performed by calling svc 0
+- * - syscall return comes in x0.
+- * - the arguments are cast to long and assigned into the target registers
+- * which are then simply passed as registers to the asm code, so that we
+- * don't have to experience issues with register constraints.
+- *
+- * On aarch64, select() is not implemented so we have to use pselect6().
+- */
+-#define __ARCH_WANT_SYS_PSELECT6
+-
+-#define my_syscall0(num) \
+-({ \
+- register long _num asm("x8") = (num); \
+- register long _arg1 asm("x0"); \
+- \
+- asm volatile ( \
+- "svc #0\n" \
+- : "=r"(_arg1) \
+- : "r"(_num) \
+- : "memory", "cc" \
+- ); \
+- _arg1; \
+-})
+-
+-#define my_syscall1(num, arg1) \
+-({ \
+- register long _num asm("x8") = (num); \
+- register long _arg1 asm("x0") = (long)(arg1); \
+- \
+- asm volatile ( \
+- "svc #0\n" \
+- : "=r"(_arg1) \
+- : "r"(_arg1), \
+- "r"(_num) \
+- : "memory", "cc" \
+- ); \
+- _arg1; \
+-})
+-
+-#define my_syscall2(num, arg1, arg2) \
+-({ \
+- register long _num asm("x8") = (num); \
+- register long _arg1 asm("x0") = (long)(arg1); \
+- register long _arg2 asm("x1") = (long)(arg2); \
+- \
+- asm volatile ( \
+- "svc #0\n" \
+- : "=r"(_arg1) \
+- : "r"(_arg1), "r"(_arg2), \
+- "r"(_num) \
+- : "memory", "cc" \
+- ); \
+- _arg1; \
+-})
+-
+-#define my_syscall3(num, arg1, arg2, arg3) \
+-({ \
+- register long _num asm("x8") = (num); \
+- register long _arg1 asm("x0") = (long)(arg1); \
+- register long _arg2 asm("x1") = (long)(arg2); \
+- register long _arg3 asm("x2") = (long)(arg3); \
+- \
+- asm volatile ( \
+- "svc #0\n" \
+- : "=r"(_arg1) \
+- : "r"(_arg1), "r"(_arg2), "r"(_arg3), \
+- "r"(_num) \
+- : "memory", "cc" \
+- ); \
+- _arg1; \
+-})
+-
+-#define my_syscall4(num, arg1, arg2, arg3, arg4) \
+-({ \
+- register long _num asm("x8") = (num); \
+- register long _arg1 asm("x0") = (long)(arg1); \
+- register long _arg2 asm("x1") = (long)(arg2); \
+- register long _arg3 asm("x2") = (long)(arg3); \
+- register long _arg4 asm("x3") = (long)(arg4); \
+- \
+- asm volatile ( \
+- "svc #0\n" \
+- : "=r"(_arg1) \
+- : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), \
+- "r"(_num) \
+- : "memory", "cc" \
+- ); \
+- _arg1; \
+-})
+-
+-#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
+-({ \
+- register long _num asm("x8") = (num); \
+- register long _arg1 asm("x0") = (long)(arg1); \
+- register long _arg2 asm("x1") = (long)(arg2); \
+- register long _arg3 asm("x2") = (long)(arg3); \
+- register long _arg4 asm("x3") = (long)(arg4); \
+- register long _arg5 asm("x4") = (long)(arg5); \
+- \
+- asm volatile ( \
+- "svc #0\n" \
+- : "=r" (_arg1) \
+- : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
+- "r"(_num) \
+- : "memory", "cc" \
+- ); \
+- _arg1; \
+-})
+-
+-#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
+-({ \
+- register long _num asm("x8") = (num); \
+- register long _arg1 asm("x0") = (long)(arg1); \
+- register long _arg2 asm("x1") = (long)(arg2); \
+- register long _arg3 asm("x2") = (long)(arg3); \
+- register long _arg4 asm("x3") = (long)(arg4); \
+- register long _arg5 asm("x4") = (long)(arg5); \
+- register long _arg6 asm("x5") = (long)(arg6); \
+- \
+- asm volatile ( \
+- "svc #0\n" \
+- : "=r" (_arg1) \
+- : "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
+- "r"(_arg6), "r"(_num) \
+- : "memory", "cc" \
+- ); \
+- _arg1; \
+-})
+-
+-/* startup code */
+-asm(".section .text\n"
+- ".global _start\n"
+- "_start:\n"
+- "ldr x0, [sp]\n" // argc (x0) was in the stack
+- "add x1, sp, 8\n" // argv (x1) = sp
+- "lsl x2, x0, 3\n" // envp (x2) = 8*argc ...
+- "add x2, x2, 8\n" // + 8 (skip null)
+- "add x2, x2, x1\n" // + argv
+- "and sp, x1, -16\n" // sp must be 16-byte aligned in the callee
+- "bl main\n" // main() returns the status code, we'll exit with it.
+- "mov x8, 93\n" // NR_exit == 93
+- "svc #0\n"
+- "");
+-
+-/* fcntl / open */
+-#define O_RDONLY 0
+-#define O_WRONLY 1
+-#define O_RDWR 2
+-#define O_CREAT 0x40
+-#define O_EXCL 0x80
+-#define O_NOCTTY 0x100
+-#define O_TRUNC 0x200
+-#define O_APPEND 0x400
+-#define O_NONBLOCK 0x800
+-#define O_DIRECTORY 0x4000
+-
+-/* The struct returned by the newfstatat() syscall. Differs slightly from the
+- * x86_64's stat one by field ordering, so be careful.
+- */
+-struct sys_stat_struct {
+- unsigned long st_dev;
+- unsigned long st_ino;
+- unsigned int st_mode;
+- unsigned int st_nlink;
+- unsigned int st_uid;
+- unsigned int st_gid;
+-
+- unsigned long st_rdev;
+- unsigned long __pad1;
+- long st_size;
+- int st_blksize;
+- int __pad2;
+-
+- long st_blocks;
+- long st_atime;
+- unsigned long st_atime_nsec;
+- long st_mtime;
+-
+- unsigned long st_mtime_nsec;
+- long st_ctime;
+- unsigned long st_ctime_nsec;
+- unsigned int __unused[2];
+-};
+-
+-#elif defined(__mips__) && defined(_ABIO32)
+-/* Syscalls for MIPS ABI O32 :
+- * - WARNING! there's always a delayed slot!
+- * - WARNING again, the syntax is different, registers take a '$' and numbers
+- * do not.
+- * - registers are 32-bit
+- * - stack is 8-byte aligned
+- * - syscall number is passed in v0 (starts at 0xfa0).
+- * - arguments are in a0, a1, a2, a3, then the stack. The caller needs to
+- * leave some room in the stack for the callee to save a0..a3 if needed.
+- * - Many registers are clobbered, in fact only a0..a2 and s0..s8 are
+- * preserved. See: https://www.linux-mips.org/wiki/Syscall as well as
+- * scall32-o32.S in the kernel sources.
+- * - the system call is performed by calling "syscall"
+- * - syscall return comes in v0, and register a3 needs to be checked to know
+- * if an error occurred, in which case errno is in v0.
+- * - the arguments are cast to long and assigned into the target registers
+- * which are then simply passed as registers to the asm code, so that we
+- * don't have to experience issues with register constraints.
+- */
+-
+-#define my_syscall0(num) \
+-({ \
+- register long _num asm("v0") = (num); \
+- register long _arg4 asm("a3"); \
+- \
+- asm volatile ( \
+- "addiu $sp, $sp, -32\n" \
+- "syscall\n" \
+- "addiu $sp, $sp, 32\n" \
+- : "=r"(_num), "=r"(_arg4) \
+- : "r"(_num) \
+- : "memory", "cc", "at", "v1", "hi", "lo", \
+- "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
+- ); \
+- _arg4 ? -_num : _num; \
+-})
+-
+-#define my_syscall1(num, arg1) \
+-({ \
+- register long _num asm("v0") = (num); \
+- register long _arg1 asm("a0") = (long)(arg1); \
+- register long _arg4 asm("a3"); \
+- \
+- asm volatile ( \
+- "addiu $sp, $sp, -32\n" \
+- "syscall\n" \
+- "addiu $sp, $sp, 32\n" \
+- : "=r"(_num), "=r"(_arg4) \
+- : "0"(_num), \
+- "r"(_arg1) \
+- : "memory", "cc", "at", "v1", "hi", "lo", \
+- "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
+- ); \
+- _arg4 ? -_num : _num; \
+-})
+-
+-#define my_syscall2(num, arg1, arg2) \
+-({ \
+- register long _num asm("v0") = (num); \
+- register long _arg1 asm("a0") = (long)(arg1); \
+- register long _arg2 asm("a1") = (long)(arg2); \
+- register long _arg4 asm("a3"); \
+- \
+- asm volatile ( \
+- "addiu $sp, $sp, -32\n" \
+- "syscall\n" \
+- "addiu $sp, $sp, 32\n" \
+- : "=r"(_num), "=r"(_arg4) \
+- : "0"(_num), \
+- "r"(_arg1), "r"(_arg2) \
+- : "memory", "cc", "at", "v1", "hi", "lo", \
+- "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
+- ); \
+- _arg4 ? -_num : _num; \
+-})
+-
+-#define my_syscall3(num, arg1, arg2, arg3) \
+-({ \
+- register long _num asm("v0") = (num); \
+- register long _arg1 asm("a0") = (long)(arg1); \
+- register long _arg2 asm("a1") = (long)(arg2); \
+- register long _arg3 asm("a2") = (long)(arg3); \
+- register long _arg4 asm("a3"); \
+- \
+- asm volatile ( \
+- "addiu $sp, $sp, -32\n" \
+- "syscall\n" \
+- "addiu $sp, $sp, 32\n" \
+- : "=r"(_num), "=r"(_arg4) \
+- : "0"(_num), \
+- "r"(_arg1), "r"(_arg2), "r"(_arg3) \
+- : "memory", "cc", "at", "v1", "hi", "lo", \
+- "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
+- ); \
+- _arg4 ? -_num : _num; \
+-})
+-
+-#define my_syscall4(num, arg1, arg2, arg3, arg4) \
+-({ \
+- register long _num asm("v0") = (num); \
+- register long _arg1 asm("a0") = (long)(arg1); \
+- register long _arg2 asm("a1") = (long)(arg2); \
+- register long _arg3 asm("a2") = (long)(arg3); \
+- register long _arg4 asm("a3") = (long)(arg4); \
+- \
+- asm volatile ( \
+- "addiu $sp, $sp, -32\n" \
+- "syscall\n" \
+- "addiu $sp, $sp, 32\n" \
+- : "=r" (_num), "=r"(_arg4) \
+- : "0"(_num), \
+- "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4) \
+- : "memory", "cc", "at", "v1", "hi", "lo", \
+- "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
+- ); \
+- _arg4 ? -_num : _num; \
+-})
+-
+-#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
+-({ \
+- register long _num asm("v0") = (num); \
+- register long _arg1 asm("a0") = (long)(arg1); \
+- register long _arg2 asm("a1") = (long)(arg2); \
+- register long _arg3 asm("a2") = (long)(arg3); \
+- register long _arg4 asm("a3") = (long)(arg4); \
+- register long _arg5 = (long)(arg5); \
+- \
+- asm volatile ( \
+- "addiu $sp, $sp, -32\n" \
+- "sw %7, 16($sp)\n" \
+- "syscall\n " \
+- "addiu $sp, $sp, 32\n" \
+- : "=r" (_num), "=r"(_arg4) \
+- : "0"(_num), \
+- "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5) \
+- : "memory", "cc", "at", "v1", "hi", "lo", \
+- "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9" \
+- ); \
+- _arg4 ? -_num : _num; \
+-})
+-
+-/* startup code, note that it's called __start on MIPS */
+-asm(".section .text\n"
+- ".set nomips16\n"
+- ".global __start\n"
+- ".set noreorder\n"
+- ".option pic0\n"
+- ".ent __start\n"
+- "__start:\n"
+- "lw $a0,($sp)\n" // argc was in the stack
+- "addiu $a1, $sp, 4\n" // argv = sp + 4
+- "sll $a2, $a0, 2\n" // a2 = argc * 4
+- "add $a2, $a2, $a1\n" // envp = argv + 4*argc ...
+- "addiu $a2, $a2, 4\n" // ... + 4
+- "li $t0, -8\n"
+- "and $sp, $sp, $t0\n" // sp must be 8-byte aligned
+- "addiu $sp,$sp,-16\n" // the callee expects to save a0..a3 there!
+- "jal main\n" // main() returns the status code, we'll exit with it.
+- "nop\n" // delayed slot
+- "move $a0, $v0\n" // retrieve 32-bit exit code from v0
+- "li $v0, 4001\n" // NR_exit == 4001
+- "syscall\n"
+- ".end __start\n"
+- "");
+-
+-/* fcntl / open */
+-#define O_RDONLY 0
+-#define O_WRONLY 1
+-#define O_RDWR 2
+-#define O_APPEND 0x0008
+-#define O_NONBLOCK 0x0080
+-#define O_CREAT 0x0100
+-#define O_TRUNC 0x0200
+-#define O_EXCL 0x0400
+-#define O_NOCTTY 0x0800
+-#define O_DIRECTORY 0x10000
+-
+-/* The struct returned by the stat() syscall. 88 bytes are returned by the
+- * syscall.
+- */
+-struct sys_stat_struct {
+- unsigned int st_dev;
+- long st_pad1[3];
+- unsigned long st_ino;
+- unsigned int st_mode;
+- unsigned int st_nlink;
+- unsigned int st_uid;
+- unsigned int st_gid;
+- unsigned int st_rdev;
+- long st_pad2[2];
+- long st_size;
+- long st_pad3;
+- long st_atime;
+- long st_atime_nsec;
+- long st_mtime;
+- long st_mtime_nsec;
+- long st_ctime;
+- long st_ctime_nsec;
+- long st_blksize;
+- long st_blocks;
+- long st_pad4[14];
+-};
+-
+-#elif defined(__riscv)
+-
+-#if __riscv_xlen == 64
+-#define PTRLOG "3"
+-#define SZREG "8"
+-#elif __riscv_xlen == 32
+-#define PTRLOG "2"
+-#define SZREG "4"
+-#endif
+-
+-/* Syscalls for RISCV :
+- * - stack is 16-byte aligned
+- * - syscall number is passed in a7
+- * - arguments are in a0, a1, a2, a3, a4, a5
+- * - the system call is performed by calling ecall
+- * - syscall return comes in a0
+- * - the arguments are cast to long and assigned into the target
+- * registers which are then simply passed as registers to the asm code,
+- * so that we don't have to experience issues with register constraints.
+- */
+-
+-#define my_syscall0(num) \
+-({ \
+- register long _num asm("a7") = (num); \
+- register long _arg1 asm("a0"); \
+- \
+- asm volatile ( \
+- "ecall\n\t" \
+- : "=r"(_arg1) \
+- : "r"(_num) \
+- : "memory", "cc" \
+- ); \
+- _arg1; \
+-})
+-
+-#define my_syscall1(num, arg1) \
+-({ \
+- register long _num asm("a7") = (num); \
+- register long _arg1 asm("a0") = (long)(arg1); \
+- \
+- asm volatile ( \
+- "ecall\n" \
+- : "+r"(_arg1) \
+- : "r"(_num) \
+- : "memory", "cc" \
+- ); \
+- _arg1; \
+-})
+-
+-#define my_syscall2(num, arg1, arg2) \
+-({ \
+- register long _num asm("a7") = (num); \
+- register long _arg1 asm("a0") = (long)(arg1); \
+- register long _arg2 asm("a1") = (long)(arg2); \
+- \
+- asm volatile ( \
+- "ecall\n" \
+- : "+r"(_arg1) \
+- : "r"(_arg2), \
+- "r"(_num) \
+- : "memory", "cc" \
+- ); \
+- _arg1; \
+-})
+-
+-#define my_syscall3(num, arg1, arg2, arg3) \
+-({ \
+- register long _num asm("a7") = (num); \
+- register long _arg1 asm("a0") = (long)(arg1); \
+- register long _arg2 asm("a1") = (long)(arg2); \
+- register long _arg3 asm("a2") = (long)(arg3); \
+- \
+- asm volatile ( \
+- "ecall\n\t" \
+- : "+r"(_arg1) \
+- : "r"(_arg2), "r"(_arg3), \
+- "r"(_num) \
+- : "memory", "cc" \
+- ); \
+- _arg1; \
+-})
+-
+-#define my_syscall4(num, arg1, arg2, arg3, arg4) \
+-({ \
+- register long _num asm("a7") = (num); \
+- register long _arg1 asm("a0") = (long)(arg1); \
+- register long _arg2 asm("a1") = (long)(arg2); \
+- register long _arg3 asm("a2") = (long)(arg3); \
+- register long _arg4 asm("a3") = (long)(arg4); \
+- \
+- asm volatile ( \
+- "ecall\n" \
+- : "+r"(_arg1) \
+- : "r"(_arg2), "r"(_arg3), "r"(_arg4), \
+- "r"(_num) \
+- : "memory", "cc" \
+- ); \
+- _arg1; \
+-})
+-
+-#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
+-({ \
+- register long _num asm("a7") = (num); \
+- register long _arg1 asm("a0") = (long)(arg1); \
+- register long _arg2 asm("a1") = (long)(arg2); \
+- register long _arg3 asm("a2") = (long)(arg3); \
+- register long _arg4 asm("a3") = (long)(arg4); \
+- register long _arg5 asm("a4") = (long)(arg5); \
+- \
+- asm volatile ( \
+- "ecall\n" \
+- : "+r"(_arg1) \
+- : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
+- "r"(_num) \
+- : "memory", "cc" \
+- ); \
+- _arg1; \
+-})
+-
+-#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
+-({ \
+- register long _num asm("a7") = (num); \
+- register long _arg1 asm("a0") = (long)(arg1); \
+- register long _arg2 asm("a1") = (long)(arg2); \
+- register long _arg3 asm("a2") = (long)(arg3); \
+- register long _arg4 asm("a3") = (long)(arg4); \
+- register long _arg5 asm("a4") = (long)(arg5); \
+- register long _arg6 asm("a5") = (long)(arg6); \
+- \
+- asm volatile ( \
+- "ecall\n" \
+- : "+r"(_arg1) \
+- : "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \
+- "r"(_num) \
+- : "memory", "cc" \
+- ); \
+- _arg1; \
+-})
+-
+-/* startup code */
+-asm(".section .text\n"
+- ".global _start\n"
+- "_start:\n"
+- ".option push\n"
+- ".option norelax\n"
+- "lla gp, __global_pointer$\n"
+- ".option pop\n"
+- "ld a0, 0(sp)\n" // argc (a0) was in the stack
+- "add a1, sp, "SZREG"\n" // argv (a1) = sp
+- "slli a2, a0, "PTRLOG"\n" // envp (a2) = SZREG*argc ...
+- "add a2, a2, "SZREG"\n" // + SZREG (skip null)
+- "add a2,a2,a1\n" // + argv
+- "andi sp,a1,-16\n" // sp must be 16-byte aligned
+- "call main\n" // main() returns the status code, we'll exit with it.
+- "li a7, 93\n" // NR_exit == 93
+- "ecall\n"
+- "");
+-
+-/* fcntl / open */
+-#define O_RDONLY 0
+-#define O_WRONLY 1
+-#define O_RDWR 2
+-#define O_CREAT 0x100
+-#define O_EXCL 0x200
+-#define O_NOCTTY 0x400
+-#define O_TRUNC 0x1000
+-#define O_APPEND 0x2000
+-#define O_NONBLOCK 0x4000
+-#define O_DIRECTORY 0x200000
+-
+-struct sys_stat_struct {
+- unsigned long st_dev; /* Device. */
+- unsigned long st_ino; /* File serial number. */
+- unsigned int st_mode; /* File mode. */
+- unsigned int st_nlink; /* Link count. */
+- unsigned int st_uid; /* User ID of the file's owner. */
+- unsigned int st_gid; /* Group ID of the file's group. */
+- unsigned long st_rdev; /* Device number, if device. */
+- unsigned long __pad1;
+- long st_size; /* Size of file, in bytes. */
+- int st_blksize; /* Optimal block size for I/O. */
+- int __pad2;
+- long st_blocks; /* Number 512-byte blocks allocated. */
+- long st_atime; /* Time of last access. */
+- unsigned long st_atime_nsec;
+- long st_mtime; /* Time of last modification. */
+- unsigned long st_mtime_nsec;
+- long st_ctime; /* Time of last status change. */
+- unsigned long st_ctime_nsec;
+- unsigned int __unused4;
+- unsigned int __unused5;
+-};
+-
+-#endif
+-
+
+ /* Below are the C functions used to declare the raw syscalls. They try to be
+ * architecture-agnostic, and return either a success or -errno. Declaring them
+diff --git a/tools/include/nolibc/std.h b/tools/include/nolibc/std.h
+new file mode 100644
+index 0000000000000..1747ae1253920
+--- /dev/null
++++ b/tools/include/nolibc/std.h
+@@ -0,0 +1,49 @@
++/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
++/*
++ * Standard definitions and types for NOLIBC
++ * Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
++ */
++
++#ifndef _NOLIBC_STD_H
++#define _NOLIBC_STD_H
++
++/* Declare a few quite common macros and types that usually are in stdlib.h,
++ * stdint.h, ctype.h, unistd.h and a few other common locations. Please place
++ * integer type definitions and generic macros here, but avoid OS-specific and
++ * syscall-specific stuff, as this file is expected to be included very early.
++ */
++
++/* note: may already be defined */
++#ifndef NULL
++#define NULL ((void *)0)
++#endif
++
++/* stdint types */
++typedef unsigned char uint8_t;
++typedef signed char int8_t;
++typedef unsigned short uint16_t;
++typedef signed short int16_t;
++typedef unsigned int uint32_t;
++typedef signed int int32_t;
++typedef unsigned long long uint64_t;
++typedef signed long long int64_t;
++typedef unsigned long size_t;
++typedef signed long ssize_t;
++typedef unsigned long uintptr_t;
++typedef signed long intptr_t;
++typedef signed long ptrdiff_t;
++
++/* those are commonly provided by sys/types.h */
++typedef unsigned int dev_t;
++typedef unsigned long ino_t;
++typedef unsigned int mode_t;
++typedef signed int pid_t;
++typedef unsigned int uid_t;
++typedef unsigned int gid_t;
++typedef unsigned long nlink_t;
++typedef signed long off_t;
++typedef signed long blksize_t;
++typedef signed long blkcnt_t;
++typedef signed long time_t;
++
++#endif /* _NOLIBC_STD_H */
+diff --git a/tools/include/nolibc/types.h b/tools/include/nolibc/types.h
+new file mode 100644
+index 0000000000000..2f09abaf95f19
+--- /dev/null
++++ b/tools/include/nolibc/types.h
+@@ -0,0 +1,133 @@
++/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
++/*
++ * Special types used by various syscalls for NOLIBC
++ * Copyright (C) 2017-2021 Willy Tarreau <w@1wt.eu>
++ */
++
++#ifndef _NOLIBC_TYPES_H
++#define _NOLIBC_TYPES_H
++
++#include "std.h"
++#include <linux/time.h>
++
++
++/* Only the generic macros and types may be defined here. The arch-specific
++ * ones such as the O_RDONLY and related macros used by fcntl() and open(), or
++ * the layout of sys_stat_struct must not be defined here.
++ */
++
++/* stat flags (WARNING, octal here) */
++#define S_IFDIR 0040000
++#define S_IFCHR 0020000
++#define S_IFBLK 0060000
++#define S_IFREG 0100000
++#define S_IFIFO 0010000
++#define S_IFLNK 0120000
++#define S_IFSOCK 0140000
++#define S_IFMT 0170000
++
++#define S_ISDIR(mode) (((mode) & S_IFDIR) == S_IFDIR)
++#define S_ISCHR(mode) (((mode) & S_IFCHR) == S_IFCHR)
++#define S_ISBLK(mode) (((mode) & S_IFBLK) == S_IFBLK)
++#define S_ISREG(mode) (((mode) & S_IFREG) == S_IFREG)
++#define S_ISFIFO(mode) (((mode) & S_IFIFO) == S_IFIFO)
++#define S_ISLNK(mode) (((mode) & S_IFLNK) == S_IFLNK)
++#define S_ISSOCK(mode) (((mode) & S_IFSOCK) == S_IFSOCK)
++
++/* dirent types */
++#define DT_UNKNOWN 0x0
++#define DT_FIFO 0x1
++#define DT_CHR 0x2
++#define DT_DIR 0x4
++#define DT_BLK 0x6
++#define DT_REG 0x8
++#define DT_LNK 0xa
++#define DT_SOCK 0xc
++
++/* commonly an fd_set represents 256 FDs */
++#define FD_SETSIZE 256
++
++/* Special FD used by all the *at functions */
++#ifndef AT_FDCWD
++#define AT_FDCWD (-100)
++#endif
++
++/* whence values for lseek() */
++#define SEEK_SET 0
++#define SEEK_CUR 1
++#define SEEK_END 2
++
++/* cmd for reboot() */
++#define LINUX_REBOOT_MAGIC1 0xfee1dead
++#define LINUX_REBOOT_MAGIC2 0x28121969
++#define LINUX_REBOOT_CMD_HALT 0xcdef0123
++#define LINUX_REBOOT_CMD_POWER_OFF 0x4321fedc
++#define LINUX_REBOOT_CMD_RESTART 0x01234567
++#define LINUX_REBOOT_CMD_SW_SUSPEND 0xd000fce2
++
++/* Macros used on waitpid()'s return status */
++#define WEXITSTATUS(status) (((status) & 0xff00) >> 8)
++#define WIFEXITED(status) (((status) & 0x7f) == 0)
++
++
++/* for select() */
++typedef struct {
++ uint32_t fd32[FD_SETSIZE / 32];
++} fd_set;
++
++/* for poll() */
++struct pollfd {
++ int fd;
++ short int events;
++ short int revents;
++};
++
++/* for getdents64() */
++struct linux_dirent64 {
++ uint64_t d_ino;
++ int64_t d_off;
++ unsigned short d_reclen;
++ unsigned char d_type;
++ char d_name[];
++};
++
++/* needed by wait4() */
++struct rusage {
++ struct timeval ru_utime;
++ struct timeval ru_stime;
++ long ru_maxrss;
++ long ru_ixrss;
++ long ru_idrss;
++ long ru_isrss;
++ long ru_minflt;
++ long ru_majflt;
++ long ru_nswap;
++ long ru_inblock;
++ long ru_oublock;
++ long ru_msgsnd;
++ long ru_msgrcv;
++ long ru_nsignals;
++ long ru_nvcsw;
++ long ru_nivcsw;
++};
++
++/* The format of the struct as returned by the libc to the application, which
++ * significantly differs from the format returned by the stat() syscall flavours.
++ */
++struct stat {
++ dev_t st_dev; /* ID of device containing file */
++ ino_t st_ino; /* inode number */
++ mode_t st_mode; /* protection */
++ nlink_t st_nlink; /* number of hard links */
++ uid_t st_uid; /* user ID of owner */
++ gid_t st_gid; /* group ID of owner */
++ dev_t st_rdev; /* device ID (if special file) */
++ off_t st_size; /* total size, in bytes */
++ blksize_t st_blksize; /* blocksize for file system I/O */
++ blkcnt_t st_blocks; /* number of 512B blocks allocated */
++ time_t st_atime; /* time of last access */
++ time_t st_mtime; /* time of last modification */
++ time_t st_ctime; /* time of last status change */
++};
++
++#endif /* _NOLIBC_TYPES_H */
+diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
+index 2fea9952818f5..d9ea546850cd6 100644
+--- a/tools/perf/builtin-trace.c
++++ b/tools/perf/builtin-trace.c
+@@ -17,7 +17,9 @@
+ #include "util/record.h"
+ #include <traceevent/event-parse.h>
+ #include <api/fs/tracing_path.h>
++#ifdef HAVE_LIBBPF_SUPPORT
+ #include <bpf/bpf.h>
++#endif
+ #include "util/bpf_map.h"
+ #include "util/rlimit.h"
+ #include "builtin.h"
+diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
+index c7f78d589e1cc..0ef4cbf21e627 100644
+--- a/tools/perf/util/auxtrace.c
++++ b/tools/perf/util/auxtrace.c
+@@ -2545,7 +2545,7 @@ static int find_dso_sym(struct dso *dso, const char *sym_name, u64 *start,
+ *size = sym->start - *start;
+ if (idx > 0) {
+ if (*size)
+- return 1;
++ return 0;
+ } else if (dso_sym_match(sym, sym_name, &cnt, idx)) {
+ print_duplicate_syms(dso, sym_name);
+ return -EINVAL;
+diff --git a/tools/perf/util/bpf_counter.h b/tools/perf/util/bpf_counter.h
+index 65ebaa6694fbd..4b5dda7530c4d 100644
+--- a/tools/perf/util/bpf_counter.h
++++ b/tools/perf/util/bpf_counter.h
+@@ -4,9 +4,12 @@
+
+ #include <linux/list.h>
+ #include <sys/resource.h>
++
++#ifdef HAVE_LIBBPF_SUPPORT
+ #include <bpf/bpf.h>
+ #include <bpf/btf.h>
+ #include <bpf/libbpf.h>
++#endif
+
+ struct evsel;
+ struct target;
+@@ -87,6 +90,8 @@ static inline void set_max_rlimit(void)
+ setrlimit(RLIMIT_MEMLOCK, &rinf);
+ }
+
++#ifdef HAVE_BPF_SKEL
++
+ static inline __u32 bpf_link_get_id(int fd)
+ {
+ struct bpf_link_info link_info = { .id = 0, };
+@@ -127,5 +132,6 @@ static inline int bperf_trigger_reading(int prog_fd, int cpu)
+
+ return bpf_prog_test_run_opts(prog_fd, &opts);
+ }
++#endif /* HAVE_BPF_SKEL */
+
+ #endif /* __PERF_BPF_COUNTER_H */
+diff --git a/tools/testing/selftests/kvm/rseq_test.c b/tools/testing/selftests/kvm/rseq_test.c
+index 2237d1aac8014..d7a7e760adc80 100644
+--- a/tools/testing/selftests/kvm/rseq_test.c
++++ b/tools/testing/selftests/kvm/rseq_test.c
+@@ -233,7 +233,7 @@ int main(int argc, char *argv[])
+ ucall_init(vm, NULL);
+
+ pthread_create(&migration_thread, NULL, migration_worker,
+- (void *)(unsigned long)gettid());
++ (void *)(unsigned long)syscall(SYS_gettid));
+
+ for (i = 0; !done; i++) {
+ vcpu_run(vm, VCPU_ID);
+diff --git a/tools/testing/selftests/net/af_unix/test_unix_oob.c b/tools/testing/selftests/net/af_unix/test_unix_oob.c
+index b57e91e1c3f28..532459a15067c 100644
+--- a/tools/testing/selftests/net/af_unix/test_unix_oob.c
++++ b/tools/testing/selftests/net/af_unix/test_unix_oob.c
+@@ -124,7 +124,7 @@ void producer(struct sockaddr_un *consumer_addr)
+
+ wait_for_signal(pipefd[0]);
+ if (connect(cfd, (struct sockaddr *)consumer_addr,
+- sizeof(struct sockaddr)) != 0) {
++ sizeof(*consumer_addr)) != 0) {
+ perror("Connect failed");
+ kill(0, SIGTERM);
+ exit(1);