Commit 8bf1a529 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux

Pull arm64 updates from Catalin Marinas:

 - Support for arm64 SME 2 and 2.1. SME2 introduces a new 512-bit
   architectural register (ZT0, for the look-up table feature) that
   Linux needs to save/restore

 - Include TPIDR2 in the signal context and add the corresponding
   kselftests

 - Perf updates: Arm SPEv1.2 support, HiSilicon uncore PMU updates, ACPI
   support to the Marvell DDR and TAD PMU drivers, reset DTM_PMU_CONFIG
   (ARM CMN) at probe time

 - Support for DYNAMIC_FTRACE_WITH_CALL_OPS on arm64

 - Permit EFI boot with MMU and caches on. Instead of cleaning the
   entire loaded kernel image to the PoC and disabling the MMU and
   caches before branching to the kernel bare metal entry point, leave
   the MMU and caches enabled and rely on EFI's cacheable 1:1 mapping of
   all of system RAM to populate the initial page tables

 - Expose the AArch32 (compat) ELF_HWCAP features to user in an arm64
   kernel (the arm32 kernel only defines the values)

 - Harden the arm64 shadow call stack pointer handling: stash the shadow
   stack pointer in the task struct on interrupt, load it directly from
   this structure

 - Signal handling cleanups to remove redundant validation of size
   information and avoid reading the same data from userspace twice

 - Refactor the hwcap macros to make use of the automatically generated
   ID registers. It should make new hwcaps writing less error prone

 - Further arm64 sysreg conversion and some fixes

 - arm64 kselftest fixes and improvements

 - Pointer authentication cleanups: don't sign leaf functions, unify
   asm-arch manipulation

 - Pseudo-NMI code generation optimisations

 - Minor fixes for SME and TPIDR2 handling

 - Miscellaneous updates: ARCH_FORCE_MAX_ORDER is now selectable,
   replace strtobool() to kstrtobool() in the cpufeature.c code, apply
   dynamic shadow call stack in two passes, intercept pfn changes in
   set_pte_at() without the required break-before-make sequence, attempt
   to dump all instructions on unhandled kernel faults

* tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: (130 commits)
  arm64: fix .idmap.text assertion for large kernels
  kselftest/arm64: Don't require FA64 for streaming SVE+ZA tests
  kselftest/arm64: Copy whole EXTRA context
  arm64: kprobes: Drop ID map text from kprobes blacklist
  perf: arm_spe: Print the version of SPE detected
  perf: arm_spe: Add support for SPEv1.2 inverted event filtering
  perf: Add perf_event_attr::config3
  arm64/sme: Fix __finalise_el2 SMEver check
  drivers/perf: fsl_imx8_ddr_perf: Remove set-but-not-used variable
  arm64/signal: Only read new data when parsing the ZT context
  arm64/signal: Only read new data when parsing the ZA context
  arm64/signal: Only read new data when parsing the SVE context
  arm64/signal: Avoid rereading context frame sizes
  arm64/signal: Make interface for restore_fpsimd_context() consistent
  arm64/signal: Remove redundant size validation from parse_user_sigframe()
  arm64/signal: Don't redundantly verify FPSIMD magic
  arm64/cpufeature: Use helper macros to specify hwcaps
  arm64/cpufeature: Always use symbolic name for feature value in hwcaps
  arm64/sysreg: Initial unsigned annotations for ID registers
  arm64/sysreg: Initial annotation of signed ID registers
  ...
parents b327dfe0 d5417081
...@@ -223,7 +223,7 @@ Before jumping into the kernel, the following conditions must be met: ...@@ -223,7 +223,7 @@ Before jumping into the kernel, the following conditions must be met:
For systems with a GICv3 interrupt controller to be used in v3 mode: For systems with a GICv3 interrupt controller to be used in v3 mode:
- If EL3 is present: - If EL3 is present:
- ICC_SRE_EL3.Enable (bit 3) must be initialiased to 0b1. - ICC_SRE_EL3.Enable (bit 3) must be initialised to 0b1.
- ICC_SRE_EL3.SRE (bit 0) must be initialised to 0b1. - ICC_SRE_EL3.SRE (bit 0) must be initialised to 0b1.
- ICC_CTLR_EL3.PMHE (bit 6) must be set to the same value across - ICC_CTLR_EL3.PMHE (bit 6) must be set to the same value across
all CPUs the kernel is executing on, and must stay constant all CPUs the kernel is executing on, and must stay constant
...@@ -369,6 +369,16 @@ Before jumping into the kernel, the following conditions must be met: ...@@ -369,6 +369,16 @@ Before jumping into the kernel, the following conditions must be met:
- HCR_EL2.ATA (bit 56) must be initialised to 0b1. - HCR_EL2.ATA (bit 56) must be initialised to 0b1.
For CPUs with the Scalable Matrix Extension version 2 (FEAT_SME2):
- If EL3 is present:
- SMCR_EL3.EZT0 (bit 30) must be initialised to 0b1.
- If the kernel is entered at EL1 and EL2 is present:
- SMCR_EL2.EZT0 (bit 30) must be initialised to 0b1.
The requirements described above for CPU mode, caches, MMUs, architected The requirements described above for CPU mode, caches, MMUs, architected
timers, coherency and system registers apply to all CPUs. All CPUs must timers, coherency and system registers apply to all CPUs. All CPUs must
enter the kernel in the same exception level. Where the values documented enter the kernel in the same exception level. Where the values documented
......
...@@ -14,7 +14,7 @@ Some hardware or software features are only available on some CPU ...@@ -14,7 +14,7 @@ Some hardware or software features are only available on some CPU
implementations, and/or with certain kernel configurations, but have no implementations, and/or with certain kernel configurations, but have no
architected discovery mechanism available to userspace code at EL0. The architected discovery mechanism available to userspace code at EL0. The
kernel exposes the presence of these features to userspace through a set kernel exposes the presence of these features to userspace through a set
of flags called hwcaps, exposed in the auxilliary vector. of flags called hwcaps, exposed in the auxiliary vector.
Userspace software can test for features by acquiring the AT_HWCAP or Userspace software can test for features by acquiring the AT_HWCAP or
AT_HWCAP2 entry of the auxiliary vector, and testing whether the relevant AT_HWCAP2 entry of the auxiliary vector, and testing whether the relevant
...@@ -284,6 +284,24 @@ HWCAP2_RPRFM ...@@ -284,6 +284,24 @@ HWCAP2_RPRFM
HWCAP2_SVE2P1 HWCAP2_SVE2P1
Functionality implied by ID_AA64ZFR0_EL1.SVEver == 0b0010. Functionality implied by ID_AA64ZFR0_EL1.SVEver == 0b0010.
HWCAP2_SME2
Functionality implied by ID_AA64SMFR0_EL1.SMEver == 0b0001.
HWCAP2_SME2P1
Functionality implied by ID_AA64SMFR0_EL1.SMEver == 0b0010.
HWCAP2_SMEI16I32
Functionality implied by ID_AA64SMFR0_EL1.I16I32 == 0b0101
HWCAP2_SMEBI32I32
Functionality implied by ID_AA64SMFR0_EL1.BI32I32 == 0b1
HWCAP2_SMEB16B16
Functionality implied by ID_AA64SMFR0_EL1.B16B16 == 0b1
HWCAP2_SMEF16F16
Functionality implied by ID_AA64SMFR0_EL1.F16F16 == 0b1
4. Unused AT_HWCAP bits 4. Unused AT_HWCAP bits
----------------------- -----------------------
......
...@@ -18,14 +18,19 @@ model features for SME is included in Appendix A. ...@@ -18,14 +18,19 @@ model features for SME is included in Appendix A.
1. General 1. General
----------- -----------
* PSTATE.SM, PSTATE.ZA, the streaming mode vector length, the ZA * PSTATE.SM, PSTATE.ZA, the streaming mode vector length, the ZA and (when
register state and TPIDR2_EL0 are tracked per thread. present) ZTn register state and TPIDR2_EL0 are tracked per thread.
* The presence of SME is reported to userspace via HWCAP2_SME in the aux vector * The presence of SME is reported to userspace via HWCAP2_SME in the aux vector
AT_HWCAP2 entry. Presence of this flag implies the presence of the SME AT_HWCAP2 entry. Presence of this flag implies the presence of the SME
instructions and registers, and the Linux-specific system interfaces instructions and registers, and the Linux-specific system interfaces
described in this document. SME is reported in /proc/cpuinfo as "sme". described in this document. SME is reported in /proc/cpuinfo as "sme".
* The presence of SME2 is reported to userspace via HWCAP2_SME2 in the
aux vector AT_HWCAP2 entry. Presence of this flag implies the presence of
the SME2 instructions and ZT0, and the Linux-specific system interfaces
described in this document. SME2 is reported in /proc/cpuinfo as "sme2".
* Support for the execution of SME instructions in userspace can also be * Support for the execution of SME instructions in userspace can also be
detected by reading the CPU ID register ID_AA64PFR1_EL1 using an MRS detected by reading the CPU ID register ID_AA64PFR1_EL1 using an MRS
instruction, and checking that the value of the SME field is nonzero. [3] instruction, and checking that the value of the SME field is nonzero. [3]
...@@ -44,6 +49,7 @@ model features for SME is included in Appendix A. ...@@ -44,6 +49,7 @@ model features for SME is included in Appendix A.
HWCAP2_SME_B16F32 HWCAP2_SME_B16F32
HWCAP2_SME_F32F32 HWCAP2_SME_F32F32
HWCAP2_SME_FA64 HWCAP2_SME_FA64
HWCAP2_SME2
This list may be extended over time as the SME architecture evolves. This list may be extended over time as the SME architecture evolves.
...@@ -52,8 +58,8 @@ model features for SME is included in Appendix A. ...@@ -52,8 +58,8 @@ model features for SME is included in Appendix A.
cpu-feature-registers.txt for details. cpu-feature-registers.txt for details.
* Debuggers should restrict themselves to interacting with the target via the * Debuggers should restrict themselves to interacting with the target via the
NT_ARM_SVE, NT_ARM_SSVE and NT_ARM_ZA regsets. The recommended way NT_ARM_SVE, NT_ARM_SSVE, NT_ARM_ZA and NT_ARM_ZT regsets. The recommended
of detecting support for these regsets is to connect to a target process way of detecting support for these regsets is to connect to a target process
first and then attempt a first and then attempt a
ptrace(PTRACE_GETREGSET, pid, NT_ARM_<regset>, &iov). ptrace(PTRACE_GETREGSET, pid, NT_ARM_<regset>, &iov).
...@@ -89,13 +95,13 @@ be zeroed. ...@@ -89,13 +95,13 @@ be zeroed.
------------------------- -------------------------
* On syscall PSTATE.ZA is preserved, if PSTATE.ZA==1 then the contents of the * On syscall PSTATE.ZA is preserved, if PSTATE.ZA==1 then the contents of the
ZA matrix are preserved. ZA matrix and ZTn (if present) are preserved.
* On syscall PSTATE.SM will be cleared and the SVE registers will be handled * On syscall PSTATE.SM will be cleared and the SVE registers will be handled
as per the standard SVE ABI. as per the standard SVE ABI.
* Neither the SVE registers nor ZA are used to pass arguments to or receive * None of the SVE registers, ZA or ZTn are used to pass arguments to
results from any syscall. or receive results from any syscall.
* On process creation (eg, clone()) the newly created process will have * On process creation (eg, clone()) the newly created process will have
PSTATE.SM cleared. PSTATE.SM cleared.
...@@ -111,6 +117,9 @@ be zeroed. ...@@ -111,6 +117,9 @@ be zeroed.
* Signal handlers are invoked with streaming mode and ZA disabled. * Signal handlers are invoked with streaming mode and ZA disabled.
* A new signal frame record TPIDR2_MAGIC is added formatted as a struct
tpidr2_context to allow access to TPIDR2_EL0 from signal handlers.
* A new signal frame record za_context encodes the ZA register contents on * A new signal frame record za_context encodes the ZA register contents on
signal delivery. [1] signal delivery. [1]
...@@ -134,6 +143,14 @@ be zeroed. ...@@ -134,6 +143,14 @@ be zeroed.
__reserved[] referencing this space. za_context is then written in the __reserved[] referencing this space. za_context is then written in the
extra space. Refer to [1] for further details about this mechanism. extra space. Refer to [1] for further details about this mechanism.
* If ZTn is supported and PSTATE.ZA==1 then a signal frame record for ZTn will
be generated.
* The signal record for ZTn has magic ZT_MAGIC (0x5a544e01) and consists of a
standard signal frame header followed by a struct zt_context specifying
the number of ZTn registers supported by the system, then zt_context.nregs
blocks of 64 bytes of data per register.
5. Signal return 5. Signal return
----------------- -----------------
...@@ -151,6 +168,9 @@ When returning from a signal handler: ...@@ -151,6 +168,9 @@ When returning from a signal handler:
the signal frame does not match the current vector length, the signal return the signal frame does not match the current vector length, the signal return
attempt is treated as illegal, resulting in a forced SIGSEGV. attempt is treated as illegal, resulting in a forced SIGSEGV.
* If ZTn is not supported or PSTATE.ZA==0 then it is illegal to have a
signal frame record for ZTn, resulting in a forced SIGSEGV.
6. prctl extensions 6. prctl extensions
-------------------- --------------------
...@@ -214,8 +234,8 @@ prctl(PR_SME_SET_VL, unsigned long arg) ...@@ -214,8 +234,8 @@ prctl(PR_SME_SET_VL, unsigned long arg)
vector length that will be applied at the next execve() by the calling vector length that will be applied at the next execve() by the calling
thread. thread.
* Changing the vector length causes all of ZA, P0..P15, FFR and all bits of * Changing the vector length causes all of ZA, ZTn, P0..P15, FFR and all
Z0..Z31 except for Z0 bits [127:0] .. Z31 bits [127:0] to become bits of Z0..Z31 except for Z0 bits [127:0] .. Z31 bits [127:0] to become
unspecified, including both streaming and non-streaming SVE state. unspecified, including both streaming and non-streaming SVE state.
Calling PR_SME_SET_VL with vl equal to the thread's current vector Calling PR_SME_SET_VL with vl equal to the thread's current vector
length, or calling PR_SME_SET_VL with the PR_SVE_SET_VL_ONEXEC flag, length, or calling PR_SME_SET_VL with the PR_SVE_SET_VL_ONEXEC flag,
...@@ -317,6 +337,15 @@ The regset data starts with struct user_za_header, containing: ...@@ -317,6 +337,15 @@ The regset data starts with struct user_za_header, containing:
* The effect of writing a partial, incomplete payload is unspecified. * The effect of writing a partial, incomplete payload is unspecified.
* A new regset NT_ARM_ZT is defined for access to ZTn state via
PTRACE_GETREGSET and PTRACE_SETREGSET.
* The NT_ARM_ZT regset consists of a single 512 bit register.
* When PSTATE.ZA==0 reads of NT_ARM_ZT will report all bits of ZTn as 0.
* Writes to NT_ARM_ZT will set PSTATE.ZA to 1.
8. ELF coredump extensions 8. ELF coredump extensions
--------------------------- ---------------------------
...@@ -331,6 +360,11 @@ The regset data starts with struct user_za_header, containing: ...@@ -331,6 +360,11 @@ The regset data starts with struct user_za_header, containing:
been read if a PTRACE_GETREGSET of NT_ARM_ZA were executed for each thread been read if a PTRACE_GETREGSET of NT_ARM_ZA were executed for each thread
when the coredump was generated. when the coredump was generated.
* A NT_ARM_ZT note will be added to each coredump for each thread of the
dumped process. The contents will be equivalent to the data that would have
been read if a PTRACE_GETREGSET of NT_ARM_ZT were executed for each thread
when the coredump was generated.
* The NT_ARM_TLS note will be extended to two registers, the second register * The NT_ARM_TLS note will be extended to two registers, the second register
will contain TPIDR2_EL0 on systems that support SME and will be read as will contain TPIDR2_EL0 on systems that support SME and will be read as
zero with writes ignored otherwise. zero with writes ignored otherwise.
...@@ -406,6 +440,9 @@ In A64 state, SME adds the following: ...@@ -406,6 +440,9 @@ In A64 state, SME adds the following:
For best system performance it is strongly encouraged for software to enable For best system performance it is strongly encouraged for software to enable
ZA only when it is actively being used. ZA only when it is actively being used.
* A new ZT0 register is introduced when SME2 is present. This is a 512 bit
register which is accessible when PSTATE.ZA is set, as ZA itself is.
* Two new 1 bit fields in PSTATE which may be controlled via the SMSTART and * Two new 1 bit fields in PSTATE which may be controlled via the SMSTART and
SMSTOP instructions or by access to the SVCR system register: SMSTOP instructions or by access to the SVCR system register:
......
...@@ -175,7 +175,7 @@ the SVE instruction set architecture. ...@@ -175,7 +175,7 @@ the SVE instruction set architecture.
When returning from a signal handler: When returning from a signal handler:
* If there is no sve_context record in the signal frame, or if the record is * If there is no sve_context record in the signal frame, or if the record is
present but contains no register data as desribed in the previous section, present but contains no register data as described in the previous section,
then the SVE registers/bits become non-live and take unspecified values. then the SVE registers/bits become non-live and take unspecified values.
* If sve_context is present in the signal frame and contains full register * If sve_context is present in the signal frame and contains full register
...@@ -223,7 +223,7 @@ prctl(PR_SVE_SET_VL, unsigned long arg) ...@@ -223,7 +223,7 @@ prctl(PR_SVE_SET_VL, unsigned long arg)
Defer the requested vector length change until the next execve() Defer the requested vector length change until the next execve()
performed by this thread. performed by this thread.
The effect is equivalent to implicit exceution of the following The effect is equivalent to implicit execution of the following
call immediately after the next execve() (if any) by the thread: call immediately after the next execve() (if any) by the thread:
prctl(PR_SVE_SET_VL, arg & ~PR_SVE_SET_VL_ONEXEC) prctl(PR_SVE_SET_VL, arg & ~PR_SVE_SET_VL_ONEXEC)
......
...@@ -252,5 +252,10 @@ static inline void gic_arch_enable_irqs(void) ...@@ -252,5 +252,10 @@ static inline void gic_arch_enable_irqs(void)
WARN_ON_ONCE(true); WARN_ON_ONCE(true);
} }
static inline bool gic_has_relaxed_pmr_sync(void)
{
return false;
}
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */
#endif /* !__ASM_ARCH_GICV3_H */ #endif /* !__ASM_ARCH_GICV3_H */
...@@ -123,6 +123,8 @@ config ARM64 ...@@ -123,6 +123,8 @@ config ARM64
select DMA_DIRECT_REMAP select DMA_DIRECT_REMAP
select EDAC_SUPPORT select EDAC_SUPPORT
select FRAME_POINTER select FRAME_POINTER
select FUNCTION_ALIGNMENT_4B
select FUNCTION_ALIGNMENT_8B if DYNAMIC_FTRACE_WITH_CALL_OPS
select GENERIC_ALLOCATOR select GENERIC_ALLOCATOR
select GENERIC_ARCH_TOPOLOGY select GENERIC_ARCH_TOPOLOGY
select GENERIC_CLOCKEVENTS_BROADCAST select GENERIC_CLOCKEVENTS_BROADCAST
...@@ -184,6 +186,8 @@ config ARM64 ...@@ -184,6 +186,8 @@ config ARM64
select HAVE_DEBUG_KMEMLEAK select HAVE_DEBUG_KMEMLEAK
select HAVE_DMA_CONTIGUOUS select HAVE_DMA_CONTIGUOUS
select HAVE_DYNAMIC_FTRACE select HAVE_DYNAMIC_FTRACE
select HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS \
if (DYNAMIC_FTRACE_WITH_ARGS && !CFI_CLANG)
select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY \ select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY \
if DYNAMIC_FTRACE_WITH_ARGS if DYNAMIC_FTRACE_WITH_ARGS
select HAVE_EFFICIENT_UNALIGNED_ACCESS select HAVE_EFFICIENT_UNALIGNED_ACCESS
...@@ -1470,10 +1474,23 @@ config XEN ...@@ -1470,10 +1474,23 @@ config XEN
help help
Say Y if you want to run Linux in a Virtual Machine on Xen on ARM64. Say Y if you want to run Linux in a Virtual Machine on Xen on ARM64.
# include/linux/mmzone.h requires the following to be true:
#
# MAX_ORDER - 1 + PAGE_SHIFT <= SECTION_SIZE_BITS
#
# so the maximum value of MAX_ORDER is SECTION_SIZE_BITS + 1 - PAGE_SHIFT:
#
# | SECTION_SIZE_BITS | PAGE_SHIFT | max MAX_ORDER | default MAX_ORDER |
# ----+-------------------+--------------+-----------------+--------------------+
# 4K | 27 | 12 | 16 | 11 |
# 16K | 27 | 14 | 14 | 12 |
# 64K | 29 | 16 | 14 | 14 |
config ARCH_FORCE_MAX_ORDER config ARCH_FORCE_MAX_ORDER
int int "Maximum zone order" if ARM64_4K_PAGES || ARM64_16K_PAGES
default "14" if ARM64_64K_PAGES default "14" if ARM64_64K_PAGES
range 12 14 if ARM64_16K_PAGES
default "12" if ARM64_16K_PAGES default "12" if ARM64_16K_PAGES
range 11 16 if ARM64_4K_PAGES
default "11" default "11"
help help
The kernel memory allocator divides physically contiguous memory The kernel memory allocator divides physically contiguous memory
...@@ -1486,7 +1503,7 @@ config ARCH_FORCE_MAX_ORDER ...@@ -1486,7 +1503,7 @@ config ARCH_FORCE_MAX_ORDER
This config option is actually maximum order plus one. For example, This config option is actually maximum order plus one. For example,
a value of 11 means that the largest free memory block is 2^10 pages. a value of 11 means that the largest free memory block is 2^10 pages.
We make sure that we can allocate upto a HugePage size for each configuration. We make sure that we can allocate up to a HugePage size for each configuration.
Hence we have : Hence we have :
MAX_ORDER = (PMD_SHIFT - PAGE_SHIFT) + 1 => PAGE_SHIFT - 2 MAX_ORDER = (PMD_SHIFT - PAGE_SHIFT) + 1 => PAGE_SHIFT - 2
...@@ -1832,7 +1849,7 @@ config ARM64_PTR_AUTH_KERNEL ...@@ -1832,7 +1849,7 @@ config ARM64_PTR_AUTH_KERNEL
bool "Use pointer authentication for kernel" bool "Use pointer authentication for kernel"
default y default y
depends on ARM64_PTR_AUTH depends on ARM64_PTR_AUTH
depends on (CC_HAS_SIGN_RETURN_ADDRESS || CC_HAS_BRANCH_PROT_PAC_RET) && AS_HAS_PAC depends on (CC_HAS_SIGN_RETURN_ADDRESS || CC_HAS_BRANCH_PROT_PAC_RET) && AS_HAS_ARMV8_3
# Modern compilers insert a .note.gnu.property section note for PAC # Modern compilers insert a .note.gnu.property section note for PAC
# which is only understood by binutils starting with version 2.33.1. # which is only understood by binutils starting with version 2.33.1.
depends on LD_IS_LLD || LD_VERSION >= 23301 || (CC_IS_GCC && GCC_VERSION < 90100) depends on LD_IS_LLD || LD_VERSION >= 23301 || (CC_IS_GCC && GCC_VERSION < 90100)
...@@ -1857,7 +1874,7 @@ config CC_HAS_SIGN_RETURN_ADDRESS ...@@ -1857,7 +1874,7 @@ config CC_HAS_SIGN_RETURN_ADDRESS
# GCC 7, 8 # GCC 7, 8
def_bool $(cc-option,-msign-return-address=all) def_bool $(cc-option,-msign-return-address=all)
config AS_HAS_PAC config AS_HAS_ARMV8_3
def_bool $(cc-option,-Wa$(comma)-march=armv8.3-a) def_bool $(cc-option,-Wa$(comma)-march=armv8.3-a)
config AS_HAS_CFI_NEGATE_RA_STATE config AS_HAS_CFI_NEGATE_RA_STATE
......
...@@ -187,7 +187,7 @@ config ARCH_MVEBU ...@@ -187,7 +187,7 @@ config ARCH_MVEBU
select PINCTRL_ARMADA_CP110 select PINCTRL_ARMADA_CP110
select PINCTRL_AC5 select PINCTRL_AC5
help help
This enables support for Marvell EBU familly, including: This enables support for Marvell EBU family, including:
- Armada 3700 SoC Family - Armada 3700 SoC Family
- Armada 7K SoC Family - Armada 7K SoC Family
- Armada 8K SoC Family - Armada 8K SoC Family
......
...@@ -63,50 +63,37 @@ stack_protector_prepare: prepare0 ...@@ -63,50 +63,37 @@ stack_protector_prepare: prepare0
include/generated/asm-offsets.h)) include/generated/asm-offsets.h))
endif endif
ifeq ($(CONFIG_AS_HAS_ARMV8_2), y)
# make sure to pass the newest target architecture to -march.
asm-arch := armv8.2-a
endif
# Ensure that if the compiler supports branch protection we default it
# off, this will be overridden if we are using branch protection.
branch-prot-flags-y += $(call cc-option,-mbranch-protection=none)
ifeq ($(CONFIG_ARM64_PTR_AUTH_KERNEL),y)
branch-prot-flags-$(CONFIG_CC_HAS_SIGN_RETURN_ADDRESS) := -msign-return-address=all
# We enable additional protection for leaf functions as there is some
# narrow potential for ROP protection benefits and no substantial
# performance impact has been observed.
PACRET-y := pac-ret+leaf
# Using a shadow call stack in leaf functions is too costly, so avoid PAC there
# as well when we may be patching PAC into SCS
PACRET-$(CONFIG_UNWIND_PATCH_PAC_INTO_SCS) := pac-ret
ifeq ($(CONFIG_ARM64_BTI_KERNEL),y) ifeq ($(CONFIG_ARM64_BTI_KERNEL),y)
branch-prot-flags-$(CONFIG_CC_HAS_BRANCH_PROT_PAC_RET_BTI) := -mbranch-protection=$(PACRET-y)+bti KBUILD_CFLAGS += -mbranch-protection=pac-ret+bti
else ifeq ($(CONFIG_ARM64_PTR_AUTH_KERNEL),y)
ifeq ($(CONFIG_CC_HAS_BRANCH_PROT_PAC_RET),y)
KBUILD_CFLAGS += -mbranch-protection=pac-ret
else
KBUILD_CFLAGS += -msign-return-address=non-leaf
endif
else else
branch-prot-flags-$(CONFIG_CC_HAS_BRANCH_PROT_PAC_RET) := -mbranch-protection=$(PACRET-y) KBUILD_CFLAGS += $(call cc-option,-mbranch-protection=none)
endif
# -march=armv8.3-a enables the non-nops instructions for PAC, to avoid the
# compiler to generate them and consequently to break the single image contract
# we pass it only to the assembler. This option is utilized only in case of non
# integrated assemblers.
ifeq ($(CONFIG_AS_HAS_PAC), y)
asm-arch := armv8.3-a
endif
endif
KBUILD_CFLAGS += $(branch-prot-flags-y)
ifeq ($(CONFIG_AS_HAS_ARMV8_4), y)
# make sure to pass the newest target architecture to -march.
asm-arch := armv8.4-a
endif endif
# Tell the assembler to support instructions from the latest target
# architecture.
#
# For non-integrated assemblers we'll pass this on the command line, and for
# integrated assemblers we'll define ARM64_ASM_ARCH and ARM64_ASM_PREAMBLE for
# inline usage.
#
# We cannot pass the same arch flag to the compiler as this would allow it to
# freely generate instructions which are not supported by earlier architecture
# versions, which would prevent a single kernel image from working on earlier
# hardware.
ifeq ($(CONFIG_AS_HAS_ARMV8_5), y) ifeq ($(CONFIG_AS_HAS_ARMV8_5), y)
# make sure to pass the newest target architecture to -march. asm-arch := armv8.5-a
asm-arch := armv8.5-a else ifeq ($(CONFIG_AS_HAS_ARMV8_4), y)
asm-arch := armv8.4-a
else ifeq ($(CONFIG_AS_HAS_ARMV8_3), y)
asm-arch := armv8.3-a
else ifeq ($(CONFIG_AS_HAS_ARMV8_2), y)
asm-arch := armv8.2-a
endif endif
ifdef asm-arch ifdef asm-arch
...@@ -139,7 +126,10 @@ endif ...@@ -139,7 +126,10 @@ endif
CHECKFLAGS += -D__aarch64__ CHECKFLAGS += -D__aarch64__
ifeq ($(CONFIG_DYNAMIC_FTRACE_WITH_ARGS),y) ifeq ($(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS),y)
KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY
CC_FLAGS_FTRACE := -fpatchable-function-entry=4,2
else ifeq ($(CONFIG_DYNAMIC_FTRACE_WITH_ARGS),y)
KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY
CC_FLAGS_FTRACE := -fpatchable-function-entry=2 CC_FLAGS_FTRACE := -fpatchable-function-entry=2
endif endif
......
...@@ -190,5 +190,10 @@ static inline void gic_arch_enable_irqs(void) ...@@ -190,5 +190,10 @@ static inline void gic_arch_enable_irqs(void)
asm volatile ("msr daifclr, #3" : : : "memory"); asm volatile ("msr daifclr, #3" : : : "memory");
} }
static inline bool gic_has_relaxed_pmr_sync(void)
{
return cpus_have_cap(ARM64_HAS_GIC_PRIO_RELAXED_SYNC);
}
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* __ASM_ARCH_GICV3_H */ #endif /* __ASM_ARCH_GICV3_H */
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include <linux/kasan-checks.h> #include <linux/kasan-checks.h>
#include <asm/alternative-macros.h>
#define __nops(n) ".rept " #n "\nnop\n.endr\n" #define __nops(n) ".rept " #n "\nnop\n.endr\n"
#define nops(n) asm volatile(__nops(n)) #define nops(n) asm volatile(__nops(n))
...@@ -41,10 +43,11 @@ ...@@ -41,10 +43,11 @@
#ifdef CONFIG_ARM64_PSEUDO_NMI #ifdef CONFIG_ARM64_PSEUDO_NMI
#define pmr_sync() \ #define pmr_sync() \
do { \ do { \
extern struct static_key_false gic_pmr_sync; \ asm volatile( \
\ ALTERNATIVE_CB("dsb sy", \
if (static_branch_unlikely(&gic_pmr_sync)) \ ARM64_HAS_GIC_PRIO_RELAXED_SYNC, \
dsb(sy); \ alt_cb_patch_nops) \
); \
} while(0) } while(0)
#else #else
#define pmr_sync() do {} while (0) #define pmr_sync() do {} while (0)
......
...@@ -769,6 +769,12 @@ static __always_inline bool system_supports_sme(void) ...@@ -769,6 +769,12 @@ static __always_inline bool system_supports_sme(void)
cpus_have_const_cap(ARM64_SME); cpus_have_const_cap(ARM64_SME);
} }
static __always_inline bool system_supports_sme2(void)
{
return IS_ENABLED(CONFIG_ARM64_SME) &&
cpus_have_const_cap(ARM64_SME2);
}
static __always_inline bool system_supports_fa64(void) static __always_inline bool system_supports_fa64(void)
{ {
return IS_ENABLED(CONFIG_ARM64_SME) && return IS_ENABLED(CONFIG_ARM64_SME) &&
...@@ -806,7 +812,7 @@ static inline bool system_has_full_ptr_auth(void) ...@@ -806,7 +812,7 @@ static inline bool system_has_full_ptr_auth(void)
static __always_inline bool system_uses_irq_prio_masking(void) static __always_inline bool system_uses_irq_prio_masking(void)
{ {
return IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) && return IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) &&
cpus_have_const_cap(ARM64_HAS_IRQ_PRIO_MASKING); cpus_have_const_cap(ARM64_HAS_GIC_PRIO_MASKING);
} }
static inline bool system_supports_mte(void) static inline bool system_supports_mte(void)
...@@ -864,7 +870,11 @@ static inline bool cpu_has_hw_af(void) ...@@ -864,7 +870,11 @@ static inline bool cpu_has_hw_af(void)
if (!IS_ENABLED(CONFIG_ARM64_HW_AFDBM)) if (!IS_ENABLED(CONFIG_ARM64_HW_AFDBM))
return false; return false;
mmfr1 = read_cpuid(ID_AA64MMFR1_EL1); /*
* Use cached version to avoid emulated msr operation on KVM
* guests.
*/
mmfr1 = read_sanitised_ftr_reg(SYS_ID_AA64MMFR1_EL1);
return cpuid_feature_extract_unsigned_field(mmfr1, return cpuid_feature_extract_unsigned_field(mmfr1,
ID_AA64MMFR1_EL1_HAFDBS_SHIFT); ID_AA64MMFR1_EL1_HAFDBS_SHIFT);
} }
......
...@@ -114,6 +114,8 @@ static inline unsigned long efi_get_kimg_min_align(void) ...@@ -114,6 +114,8 @@ static inline unsigned long efi_get_kimg_min_align(void)
#define EFI_ALLOC_ALIGN SZ_64K #define EFI_ALLOC_ALIGN SZ_64K
#define EFI_ALLOC_LIMIT ((1UL << 48) - 1) #define EFI_ALLOC_LIMIT ((1UL << 48) - 1)
extern unsigned long primary_entry_offset(void);
/* /*
* On ARM systems, virtually remapped UEFI runtime services are set up in two * On ARM systems, virtually remapped UEFI runtime services are set up in two
* distinct stages: * distinct stages:
......
...@@ -53,10 +53,10 @@ ...@@ -53,10 +53,10 @@
cbz x0, .Lskip_spe_\@ // Skip if SPE not present cbz x0, .Lskip_spe_\@ // Skip if SPE not present
mrs_s x0, SYS_PMBIDR_EL1 // If SPE available at EL2, mrs_s x0, SYS_PMBIDR_EL1 // If SPE available at EL2,
and x0, x0, #(1 << SYS_PMBIDR_EL1_P_SHIFT) and x0, x0, #(1 << PMBIDR_EL1_P_SHIFT)
cbnz x0, .Lskip_spe_el2_\@ // then permit sampling of physical cbnz x0, .Lskip_spe_el2_\@ // then permit sampling of physical
mov x0, #(1 << SYS_PMSCR_EL2_PCT_SHIFT | \ mov x0, #(1 << PMSCR_EL2_PCT_SHIFT | \
1 << SYS_PMSCR_EL2_PA_SHIFT) 1 << PMSCR_EL2_PA_SHIFT)
msr_s SYS_PMSCR_EL2, x0 // addresses and physical counter msr_s SYS_PMSCR_EL2, x0 // addresses and physical counter
.Lskip_spe_el2_\@: .Lskip_spe_el2_\@:
mov x0, #(MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT) mov x0, #(MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT)
...@@ -177,7 +177,7 @@ ...@@ -177,7 +177,7 @@
/** /**
* Initialize EL2 registers to sane values. This should be called early on all * Initialize EL2 registers to sane values. This should be called early on all
* cores that were booted in EL2. Note that everything gets initialised as * cores that were booted in EL2. Note that everything gets initialised as
* if VHE was not evailable. The kernel context will be upgraded to VHE * if VHE was not available. The kernel context will be upgraded to VHE
* if possible later on in the boot process * if possible later on in the boot process
* *
* Regs: x0, x1 and x2 are clobbered. * Regs: x0, x1 and x2 are clobbered.
......
...@@ -350,6 +350,7 @@ ...@@ -350,6 +350,7 @@
#define ESR_ELx_SME_ISS_ILL 1 #define ESR_ELx_SME_ISS_ILL 1
#define ESR_ELx_SME_ISS_SM_DISABLED 2 #define ESR_ELx_SME_ISS_SM_DISABLED 2
#define ESR_ELx_SME_ISS_ZA_DISABLED 3 #define ESR_ELx_SME_ISS_ZA_DISABLED 3
#define ESR_ELx_SME_ISS_ZT_DISABLED 4
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <asm/types.h> #include <asm/types.h>
......
...@@ -61,7 +61,7 @@ extern void fpsimd_kvm_prepare(void); ...@@ -61,7 +61,7 @@ extern void fpsimd_kvm_prepare(void);
struct cpu_fp_state { struct cpu_fp_state {
struct user_fpsimd_state *st; struct user_fpsimd_state *st;
void *sve_state; void *sve_state;
void *za_state; void *sme_state;
u64 *svcr; u64 *svcr;
unsigned int sve_vl; unsigned int sve_vl;
unsigned int sme_vl; unsigned int sme_vl;
...@@ -105,6 +105,13 @@ static inline void *sve_pffr(struct thread_struct *thread) ...@@ -105,6 +105,13 @@ static inline void *sve_pffr(struct thread_struct *thread)
return (char *)thread->sve_state + sve_ffr_offset(vl); return (char *)thread->sve_state + sve_ffr_offset(vl);
} }
static inline void *thread_zt_state(struct thread_struct *thread)
{
/* The ZT register state is stored immediately after the ZA state */
unsigned int sme_vq = sve_vq_from_vl(thread_get_sme_vl(thread));
return thread->sme_state + ZA_SIG_REGS_SIZE(sme_vq);
}
extern void sve_save_state(void *state, u32 *pfpsr, int save_ffr); extern void sve_save_state(void *state, u32 *pfpsr, int save_ffr);
extern void sve_load_state(void const *state, u32 const *pfpsr, extern void sve_load_state(void const *state, u32 const *pfpsr,
int restore_ffr); int restore_ffr);
...@@ -112,12 +119,13 @@ extern void sve_flush_live(bool flush_ffr, unsigned long vq_minus_1); ...@@ -112,12 +119,13 @@ extern void sve_flush_live(bool flush_ffr, unsigned long vq_minus_1);
extern unsigned int sve_get_vl(void); extern unsigned int sve_get_vl(void);
extern void sve_set_vq(unsigned long vq_minus_1); extern void sve_set_vq(unsigned long vq_minus_1);
extern void sme_set_vq(unsigned long vq_minus_1); extern void sme_set_vq(unsigned long vq_minus_1);
extern void za_save_state(void *state); extern void sme_save_state(void *state, int zt);
extern void za_load_state(void const *state); extern void sme_load_state(void const *state, int zt);
struct arm64_cpu_capabilities; struct arm64_cpu_capabilities;
extern void sve_kernel_enable(const struct arm64_cpu_capabilities *__unused); extern void sve_kernel_enable(const struct arm64_cpu_capabilities *__unused);
extern void sme_kernel_enable(const struct arm64_cpu_capabilities *__unused); extern void sme_kernel_enable(const struct arm64_cpu_capabilities *__unused);
extern void sme2_kernel_enable(const struct arm64_cpu_capabilities *__unused);
extern void fa64_kernel_enable(const struct arm64_cpu_capabilities *__unused); extern void fa64_kernel_enable(const struct arm64_cpu_capabilities *__unused);
extern u64 read_zcr_features(void); extern u64 read_zcr_features(void);
...@@ -355,14 +363,20 @@ extern int sme_get_current_vl(void); ...@@ -355,14 +363,20 @@ extern int sme_get_current_vl(void);
/* /*
* Return how many bytes of memory are required to store the full SME * Return how many bytes of memory are required to store the full SME
* specific state (currently just ZA) for task, given task's currently * specific state for task, given task's currently configured vector
* configured vector length. * length.
*/ */
static inline size_t za_state_size(struct task_struct const *task) static inline size_t sme_state_size(struct task_struct const *task)
{ {
unsigned int vl = task_get_sme_vl(task); unsigned int vl = task_get_sme_vl(task);
size_t size;
size = ZA_SIG_REGS_SIZE(sve_vq_from_vl(vl));
if (system_supports_sme2())
size += ZT_SIG_REG_SIZE;
return ZA_SIG_REGS_SIZE(sve_vq_from_vl(vl)); return size;
} }
#else #else
...@@ -382,7 +396,7 @@ static inline int sme_max_virtualisable_vl(void) { return 0; } ...@@ -382,7 +396,7 @@ static inline int sme_max_virtualisable_vl(void) { return 0; }
static inline int sme_set_current_vl(unsigned long arg) { return -EINVAL; } static inline int sme_set_current_vl(unsigned long arg) { return -EINVAL; }
static inline int sme_get_current_vl(void) { return -EINVAL; } static inline int sme_get_current_vl(void) { return -EINVAL; }
static inline size_t za_state_size(struct task_struct const *task) static inline size_t sme_state_size(struct task_struct const *task)
{ {
return 0; return 0;
} }
......
...@@ -220,6 +220,28 @@ ...@@ -220,6 +220,28 @@
| ((\offset) & 7) | ((\offset) & 7)
.endm .endm
/*
* LDR (ZT0)
*
* LDR ZT0, nx
*/
.macro _ldr_zt nx
_check_general_reg \nx
.inst 0xe11f8000 \
| (\nx << 5)
.endm
/*
* STR (ZT0)
*
* STR ZT0, nx
*/
.macro _str_zt nx
_check_general_reg \nx
.inst 0xe13f8000 \
| (\nx << 5)
.endm
/* /*
* Zero the entire ZA array * Zero the entire ZA array
* ZERO ZA * ZERO ZA
......
...@@ -62,20 +62,7 @@ extern unsigned long ftrace_graph_call; ...@@ -62,20 +62,7 @@ extern unsigned long ftrace_graph_call;
extern void return_to_handler(void); extern void return_to_handler(void);
static inline unsigned long ftrace_call_adjust(unsigned long addr) unsigned long ftrace_call_adjust(unsigned long addr);
{
/*
* Adjust addr to point at the BL in the callsite.
* See ftrace_init_nop() for the callsite sequence.
*/
if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_ARGS))
return addr + AARCH64_INSN_SIZE;
/*
* addr is the address of the mcount call instruction.
* recordmcount does the necessary offset calculation.
*/
return addr;
}
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS #ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
struct dyn_ftrace; struct dyn_ftrace;
......
...@@ -31,12 +31,20 @@ ...@@ -31,12 +31,20 @@
#define COMPAT_HWCAP_VFPD32 (1 << 19) #define COMPAT_HWCAP_VFPD32 (1 << 19)
#define COMPAT_HWCAP_LPAE (1 << 20) #define COMPAT_HWCAP_LPAE (1 << 20)
#define COMPAT_HWCAP_EVTSTRM (1 << 21) #define COMPAT_HWCAP_EVTSTRM (1 << 21)
#define COMPAT_HWCAP_FPHP (1 << 22)
#define COMPAT_HWCAP_ASIMDHP (1 << 23)
#define COMPAT_HWCAP_ASIMDDP (1 << 24)
#define COMPAT_HWCAP_ASIMDFHM (1 << 25)
#define COMPAT_HWCAP_ASIMDBF16 (1 << 26)
#define COMPAT_HWCAP_I8MM (1 << 27)
#define COMPAT_HWCAP2_AES (1 << 0) #define COMPAT_HWCAP2_AES (1 << 0)
#define COMPAT_HWCAP2_PMULL (1 << 1) #define COMPAT_HWCAP2_PMULL (1 << 1)
#define COMPAT_HWCAP2_SHA1 (1 << 2) #define COMPAT_HWCAP2_SHA1 (1 << 2)
#define COMPAT_HWCAP2_SHA2 (1 << 3) #define COMPAT_HWCAP2_SHA2 (1 << 3)
#define COMPAT_HWCAP2_CRC32 (1 << 4) #define COMPAT_HWCAP2_CRC32 (1 << 4)
#define COMPAT_HWCAP2_SB (1 << 5)
#define COMPAT_HWCAP2_SSBS (1 << 6)
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <linux/log2.h> #include <linux/log2.h>
...@@ -123,6 +131,12 @@ ...@@ -123,6 +131,12 @@
#define KERNEL_HWCAP_CSSC __khwcap2_feature(CSSC) #define KERNEL_HWCAP_CSSC __khwcap2_feature(CSSC)
#define KERNEL_HWCAP_RPRFM __khwcap2_feature(RPRFM) #define KERNEL_HWCAP_RPRFM __khwcap2_feature(RPRFM)
#define KERNEL_HWCAP_SVE2P1 __khwcap2_feature(SVE2P1) #define KERNEL_HWCAP_SVE2P1 __khwcap2_feature(SVE2P1)
#define KERNEL_HWCAP_SME2 __khwcap2_feature(SME2)
#define KERNEL_HWCAP_SME2P1 __khwcap2_feature(SME2P1)
#define KERNEL_HWCAP_SME_I16I32 __khwcap2_feature(SME_I16I32)
#define KERNEL_HWCAP_SME_BI32I32 __khwcap2_feature(SME_BI32I32)
#define KERNEL_HWCAP_SME_B16B16 __khwcap2_feature(SME_B16B16)
#define KERNEL_HWCAP_SME_F16F16 __khwcap2_feature(SME_F16F16)
/* /*
* This yields a mask that user programs can use to figure out what * This yields a mask that user programs can use to figure out what
......
...@@ -420,6 +420,7 @@ __AARCH64_INSN_FUNCS(sb, 0xFFFFFFFF, 0xD50330FF) ...@@ -420,6 +420,7 @@ __AARCH64_INSN_FUNCS(sb, 0xFFFFFFFF, 0xD50330FF)
__AARCH64_INSN_FUNCS(clrex, 0xFFFFF0FF, 0xD503305F) __AARCH64_INSN_FUNCS(clrex, 0xFFFFF0FF, 0xD503305F)
__AARCH64_INSN_FUNCS(ssbb, 0xFFFFFFFF, 0xD503309F) __AARCH64_INSN_FUNCS(ssbb, 0xFFFFFFFF, 0xD503309F)
__AARCH64_INSN_FUNCS(pssbb, 0xFFFFFFFF, 0xD503349F) __AARCH64_INSN_FUNCS(pssbb, 0xFFFFFFFF, 0xD503349F)
__AARCH64_INSN_FUNCS(bti, 0xFFFFFF3F, 0xD503241f)
#undef __AARCH64_INSN_FUNCS #undef __AARCH64_INSN_FUNCS
......
...@@ -21,43 +21,77 @@ ...@@ -21,43 +21,77 @@
* exceptions should be unmasked. * exceptions should be unmasked.
*/ */
/* static __always_inline bool __irqflags_uses_pmr(void)
* CPU interrupt mask handling.
*/
static inline void arch_local_irq_enable(void)
{ {
if (system_has_prio_mask_debugging()) { return IS_ENABLED(CONFIG_ARM64_PSEUDO_NMI) &&
u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1); alternative_has_feature_unlikely(ARM64_HAS_GIC_PRIO_MASKING);
}
static __always_inline void __daif_local_irq_enable(void)
{
barrier();
asm volatile("msr daifclr, #3");
barrier();
}
static __always_inline void __pmr_local_irq_enable(void)
{
if (IS_ENABLED(CONFIG_ARM64_DEBUG_PRIORITY_MASKING)) {
u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1);
WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF); WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF);
} }
asm volatile(ALTERNATIVE( barrier();
"msr daifclr, #3 // arch_local_irq_enable", write_sysreg_s(GIC_PRIO_IRQON, SYS_ICC_PMR_EL1);
__msr_s(SYS_ICC_PMR_EL1, "%0"),
ARM64_HAS_IRQ_PRIO_MASKING)
:
: "r" ((unsigned long) GIC_PRIO_IRQON)
: "memory");
pmr_sync(); pmr_sync();
barrier();
} }
static inline void arch_local_irq_disable(void) static inline void arch_local_irq_enable(void)
{ {
if (system_has_prio_mask_debugging()) { if (__irqflags_uses_pmr()) {
u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1); __pmr_local_irq_enable();
} else {
__daif_local_irq_enable();
}
}
static __always_inline void __daif_local_irq_disable(void)
{
barrier();
asm volatile("msr daifset, #3");
barrier();
}
static __always_inline void __pmr_local_irq_disable(void)
{
if (IS_ENABLED(CONFIG_ARM64_DEBUG_PRIORITY_MASKING)) {
u32 pmr = read_sysreg_s(SYS_ICC_PMR_EL1);
WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF); WARN_ON_ONCE(pmr != GIC_PRIO_IRQON && pmr != GIC_PRIO_IRQOFF);
} }
asm volatile(ALTERNATIVE( barrier();
"msr daifset, #3 // arch_local_irq_disable", write_sysreg_s(GIC_PRIO_IRQOFF, SYS_ICC_PMR_EL1);
__msr_s(SYS_ICC_PMR_EL1, "%0"), barrier();
ARM64_HAS_IRQ_PRIO_MASKING) }
:
: "r" ((unsigned long) GIC_PRIO_IRQOFF) static inline void arch_local_irq_disable(void)
: "memory"); {
if (__irqflags_uses_pmr()) {
__pmr_local_irq_disable();
} else {
__daif_local_irq_disable();
}
}
static __always_inline unsigned long __daif_local_save_flags(void)
{
return read_sysreg(daif);
}
static __always_inline unsigned long __pmr_local_save_flags(void)
{
return read_sysreg_s(SYS_ICC_PMR_EL1);
} }
/* /*
...@@ -65,69 +99,108 @@ static inline void arch_local_irq_disable(void) ...@@ -65,69 +99,108 @@ static inline void arch_local_irq_disable(void)
*/ */
static inline unsigned long arch_local_save_flags(void) static inline unsigned long arch_local_save_flags(void)
{ {
unsigned long flags; if (__irqflags_uses_pmr()) {
return __pmr_local_save_flags();
} else {
return __daif_local_save_flags();
}
}
asm volatile(ALTERNATIVE( static __always_inline bool __daif_irqs_disabled_flags(unsigned long flags)
"mrs %0, daif", {
__mrs_s("%0", SYS_ICC_PMR_EL1), return flags & PSR_I_BIT;
ARM64_HAS_IRQ_PRIO_MASKING) }
: "=&r" (flags)
:
: "memory");
return flags; static __always_inline bool __pmr_irqs_disabled_flags(unsigned long flags)
{
return flags != GIC_PRIO_IRQON;
} }
static inline int arch_irqs_disabled_flags(unsigned long flags) static inline bool arch_irqs_disabled_flags(unsigned long flags)
{ {
int res; if (__irqflags_uses_pmr()) {
return __pmr_irqs_disabled_flags(flags);
} else {
return __daif_irqs_disabled_flags(flags);
}
}
asm volatile(ALTERNATIVE( static __always_inline bool __daif_irqs_disabled(void)
"and %w0, %w1, #" __stringify(PSR_I_BIT), {
"eor %w0, %w1, #" __stringify(GIC_PRIO_IRQON), return __daif_irqs_disabled_flags(__daif_local_save_flags());
ARM64_HAS_IRQ_PRIO_MASKING) }
: "=&r" (res)
: "r" ((int) flags)
: "memory");
return res; static __always_inline bool __pmr_irqs_disabled(void)
{
return __pmr_irqs_disabled_flags(__pmr_local_save_flags());
} }
static inline int arch_irqs_disabled(void) static inline bool arch_irqs_disabled(void)
{ {
return arch_irqs_disabled_flags(arch_local_save_flags()); if (__irqflags_uses_pmr()) {
return __pmr_irqs_disabled();
} else {
return __daif_irqs_disabled();
}
} }
static inline unsigned long arch_local_irq_save(void) static __always_inline unsigned long __daif_local_irq_save(void)
{ {
unsigned long flags; unsigned long flags = __daif_local_save_flags();
__daif_local_irq_disable();
return flags;
}
flags = arch_local_save_flags(); static __always_inline unsigned long __pmr_local_irq_save(void)
{
unsigned long flags = __pmr_local_save_flags();
/* /*
* There are too many states with IRQs disabled, just keep the current * There are too many states with IRQs disabled, just keep the current
* state if interrupts are already disabled/masked. * state if interrupts are already disabled/masked.
*/ */
if (!arch_irqs_disabled_flags(flags)) if (!__pmr_irqs_disabled_flags(flags))
arch_local_irq_disable(); __pmr_local_irq_disable();
return flags; return flags;
} }
static inline unsigned long arch_local_irq_save(void)
{
if (__irqflags_uses_pmr()) {
return __pmr_local_irq_save();
} else {
return __daif_local_irq_save();
}
}
static __always_inline void __daif_local_irq_restore(unsigned long flags)
{
barrier();
write_sysreg(flags, daif);
barrier();
}
static __always_inline void __pmr_local_irq_restore(unsigned long flags)
{
barrier();
write_sysreg_s(flags, SYS_ICC_PMR_EL1);
pmr_sync();
barrier();
}
/* /*
* restore saved IRQ state * restore saved IRQ state
*/ */
static inline void arch_local_irq_restore(unsigned long flags) static inline void arch_local_irq_restore(unsigned long flags)
{ {
asm volatile(ALTERNATIVE( if (__irqflags_uses_pmr()) {
"msr daif, %0", __pmr_local_irq_restore(flags);
__msr_s(SYS_ICC_PMR_EL1, "%0"), } else {
ARM64_HAS_IRQ_PRIO_MASKING) __daif_local_irq_restore(flags);
: }
: "r" (flags)
: "memory");
pmr_sync();
} }
#endif /* __ASM_IRQFLAGS_H */ #endif /* __ASM_IRQFLAGS_H */
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
#include <asm/assembler.h> #include <asm/assembler.h>
#endif #endif
#define __ALIGN .align 2 #define __ALIGN .balign CONFIG_FUNCTION_ALIGNMENT
#define __ALIGN_STR ".align 2" #define __ALIGN_STR ".balign " #CONFIG_FUNCTION_ALIGNMENT
/* /*
* When using in-kernel BTI we need to ensure that PCS-conformant * When using in-kernel BTI we need to ensure that PCS-conformant
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
int aarch64_insn_read(void *addr, u32 *insnp); int aarch64_insn_read(void *addr, u32 *insnp);
int aarch64_insn_write(void *addr, u32 insn); int aarch64_insn_write(void *addr, u32 insn);
int aarch64_insn_write_literal_u64(void *addr, u64 val);
int aarch64_insn_patch_text_nosync(void *addr, u32 insn); int aarch64_insn_patch_text_nosync(void *addr, u32 insn);
int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt); int aarch64_insn_patch_text(void *addrs[], u32 insns[], int cnt);
......
...@@ -275,6 +275,7 @@ static inline void set_pte(pte_t *ptep, pte_t pte) ...@@ -275,6 +275,7 @@ static inline void set_pte(pte_t *ptep, pte_t pte)
} }
extern void __sync_icache_dcache(pte_t pteval); extern void __sync_icache_dcache(pte_t pteval);
bool pgattr_change_is_safe(u64 old, u64 new);
/* /*
* PTE bits configuration in the presence of hardware Dirty Bit Management * PTE bits configuration in the presence of hardware Dirty Bit Management
...@@ -292,7 +293,7 @@ extern void __sync_icache_dcache(pte_t pteval); ...@@ -292,7 +293,7 @@ extern void __sync_icache_dcache(pte_t pteval);
* PTE_DIRTY || (PTE_WRITE && !PTE_RDONLY) * PTE_DIRTY || (PTE_WRITE && !PTE_RDONLY)
*/ */
static inline void __check_racy_pte_update(struct mm_struct *mm, pte_t *ptep, static inline void __check_safe_pte_update(struct mm_struct *mm, pte_t *ptep,
pte_t pte) pte_t pte)
{ {
pte_t old_pte; pte_t old_pte;
...@@ -318,6 +319,9 @@ static inline void __check_racy_pte_update(struct mm_struct *mm, pte_t *ptep, ...@@ -318,6 +319,9 @@ static inline void __check_racy_pte_update(struct mm_struct *mm, pte_t *ptep,
VM_WARN_ONCE(pte_write(old_pte) && !pte_dirty(pte), VM_WARN_ONCE(pte_write(old_pte) && !pte_dirty(pte),
"%s: racy dirty state clearing: 0x%016llx -> 0x%016llx", "%s: racy dirty state clearing: 0x%016llx -> 0x%016llx",
__func__, pte_val(old_pte), pte_val(pte)); __func__, pte_val(old_pte), pte_val(pte));
VM_WARN_ONCE(!pgattr_change_is_safe(pte_val(old_pte), pte_val(pte)),
"%s: unsafe attribute change: 0x%016llx -> 0x%016llx",
__func__, pte_val(old_pte), pte_val(pte));
} }
static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
...@@ -346,7 +350,7 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, ...@@ -346,7 +350,7 @@ static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr,
mte_sync_tags(old_pte, pte); mte_sync_tags(old_pte, pte);
} }
__check_racy_pte_update(mm, ptep, pte); __check_safe_pte_update(mm, ptep, pte);
set_pte(ptep, pte); set_pte(ptep, pte);
} }
......
...@@ -161,7 +161,7 @@ struct thread_struct { ...@@ -161,7 +161,7 @@ struct thread_struct {
enum fp_type fp_type; /* registers FPSIMD or SVE? */ enum fp_type fp_type; /* registers FPSIMD or SVE? */
unsigned int fpsimd_cpu; unsigned int fpsimd_cpu;
void *sve_state; /* SVE registers, if any */ void *sve_state; /* SVE registers, if any */
void *za_state; /* ZA register, if any */ void *sme_state; /* ZA and ZT state, if any */
unsigned int vl[ARM64_VEC_MAX]; /* vector length */ unsigned int vl[ARM64_VEC_MAX]; /* vector length */
unsigned int vl_onexec[ARM64_VEC_MAX]; /* vl after next exec */ unsigned int vl_onexec[ARM64_VEC_MAX]; /* vl after next exec */
unsigned long fault_address; /* fault info */ unsigned long fault_address; /* fault info */
......
...@@ -194,7 +194,7 @@ struct pt_regs { ...@@ -194,7 +194,7 @@ struct pt_regs {
u32 unused2; u32 unused2;
#endif #endif
u64 sdei_ttbr1; u64 sdei_ttbr1;
/* Only valid when ARM64_HAS_IRQ_PRIO_MASKING is enabled. */ /* Only valid when ARM64_HAS_GIC_PRIO_MASKING is enabled. */
u64 pmr_save; u64 pmr_save;
u64 stackframe[2]; u64 stackframe[2];
......
...@@ -10,15 +10,16 @@ ...@@ -10,15 +10,16 @@
#ifdef CONFIG_SHADOW_CALL_STACK #ifdef CONFIG_SHADOW_CALL_STACK
scs_sp .req x18 scs_sp .req x18
.macro scs_load tsk .macro scs_load_current
ldr scs_sp, [\tsk, #TSK_TI_SCS_SP] get_current_task scs_sp
ldr scs_sp, [scs_sp, #TSK_TI_SCS_SP]
.endm .endm
.macro scs_save tsk .macro scs_save tsk
str scs_sp, [\tsk, #TSK_TI_SCS_SP] str scs_sp, [\tsk, #TSK_TI_SCS_SP]
.endm .endm
#else #else
.macro scs_load tsk .macro scs_load_current
.endm .endm
.macro scs_save tsk .macro scs_save tsk
......
...@@ -216,101 +216,22 @@ ...@@ -216,101 +216,22 @@
#define SYS_PAR_EL1_FST GENMASK(6, 1) #define SYS_PAR_EL1_FST GENMASK(6, 1)
/*** Statistical Profiling Extension ***/ /*** Statistical Profiling Extension ***/
/* ID registers */ #define PMSEVFR_EL1_RES0_IMP \
#define SYS_PMSIDR_EL1 sys_reg(3, 0, 9, 9, 7)
#define SYS_PMSIDR_EL1_FE_SHIFT 0
#define SYS_PMSIDR_EL1_FT_SHIFT 1
#define SYS_PMSIDR_EL1_FL_SHIFT 2
#define SYS_PMSIDR_EL1_ARCHINST_SHIFT 3
#define SYS_PMSIDR_EL1_LDS_SHIFT 4
#define SYS_PMSIDR_EL1_ERND_SHIFT 5
#define SYS_PMSIDR_EL1_INTERVAL_SHIFT 8
#define SYS_PMSIDR_EL1_INTERVAL_MASK 0xfUL
#define SYS_PMSIDR_EL1_MAXSIZE_SHIFT 12
#define SYS_PMSIDR_EL1_MAXSIZE_MASK 0xfUL
#define SYS_PMSIDR_EL1_COUNTSIZE_SHIFT 16
#define SYS_PMSIDR_EL1_COUNTSIZE_MASK 0xfUL
#define SYS_PMBIDR_EL1 sys_reg(3, 0, 9, 10, 7)
#define SYS_PMBIDR_EL1_ALIGN_SHIFT 0
#define SYS_PMBIDR_EL1_ALIGN_MASK 0xfU
#define SYS_PMBIDR_EL1_P_SHIFT 4
#define SYS_PMBIDR_EL1_F_SHIFT 5
/* Sampling controls */
#define SYS_PMSCR_EL1 sys_reg(3, 0, 9, 9, 0)
#define SYS_PMSCR_EL1_E0SPE_SHIFT 0
#define SYS_PMSCR_EL1_E1SPE_SHIFT 1
#define SYS_PMSCR_EL1_CX_SHIFT 3
#define SYS_PMSCR_EL1_PA_SHIFT 4
#define SYS_PMSCR_EL1_TS_SHIFT 5
#define SYS_PMSCR_EL1_PCT_SHIFT 6
#define SYS_PMSCR_EL2 sys_reg(3, 4, 9, 9, 0)
#define SYS_PMSCR_EL2_E0HSPE_SHIFT 0
#define SYS_PMSCR_EL2_E2SPE_SHIFT 1
#define SYS_PMSCR_EL2_CX_SHIFT 3
#define SYS_PMSCR_EL2_PA_SHIFT 4
#define SYS_PMSCR_EL2_TS_SHIFT 5
#define SYS_PMSCR_EL2_PCT_SHIFT 6
#define SYS_PMSICR_EL1 sys_reg(3, 0, 9, 9, 2)
#define SYS_PMSIRR_EL1 sys_reg(3, 0, 9, 9, 3)
#define SYS_PMSIRR_EL1_RND_SHIFT 0
#define SYS_PMSIRR_EL1_INTERVAL_SHIFT 8
#define SYS_PMSIRR_EL1_INTERVAL_MASK 0xffffffUL
/* Filtering controls */
#define SYS_PMSNEVFR_EL1 sys_reg(3, 0, 9, 9, 1)
#define SYS_PMSFCR_EL1 sys_reg(3, 0, 9, 9, 4)
#define SYS_PMSFCR_EL1_FE_SHIFT 0
#define SYS_PMSFCR_EL1_FT_SHIFT 1
#define SYS_PMSFCR_EL1_FL_SHIFT 2
#define SYS_PMSFCR_EL1_B_SHIFT 16
#define SYS_PMSFCR_EL1_LD_SHIFT 17
#define SYS_PMSFCR_EL1_ST_SHIFT 18
#define SYS_PMSEVFR_EL1 sys_reg(3, 0, 9, 9, 5)
#define SYS_PMSEVFR_EL1_RES0_8_2 \
(GENMASK_ULL(47, 32) | GENMASK_ULL(23, 16) | GENMASK_ULL(11, 8) |\ (GENMASK_ULL(47, 32) | GENMASK_ULL(23, 16) | GENMASK_ULL(11, 8) |\
BIT_ULL(6) | BIT_ULL(4) | BIT_ULL(2) | BIT_ULL(0)) BIT_ULL(6) | BIT_ULL(4) | BIT_ULL(2) | BIT_ULL(0))
#define SYS_PMSEVFR_EL1_RES0_8_3 \ #define PMSEVFR_EL1_RES0_V1P1 \
(SYS_PMSEVFR_EL1_RES0_8_2 & ~(BIT_ULL(18) | BIT_ULL(17) | BIT_ULL(11))) (PMSEVFR_EL1_RES0_IMP & ~(BIT_ULL(18) | BIT_ULL(17) | BIT_ULL(11)))
#define PMSEVFR_EL1_RES0_V1P2 \
#define SYS_PMSLATFR_EL1 sys_reg(3, 0, 9, 9, 6) (PMSEVFR_EL1_RES0_V1P1 & ~BIT_ULL(6))
#define SYS_PMSLATFR_EL1_MINLAT_SHIFT 0
/* Buffer controls */
#define SYS_PMBLIMITR_EL1 sys_reg(3, 0, 9, 10, 0)
#define SYS_PMBLIMITR_EL1_E_SHIFT 0
#define SYS_PMBLIMITR_EL1_FM_SHIFT 1
#define SYS_PMBLIMITR_EL1_FM_MASK 0x3UL
#define SYS_PMBLIMITR_EL1_FM_STOP_IRQ (0 << SYS_PMBLIMITR_EL1_FM_SHIFT)
#define SYS_PMBPTR_EL1 sys_reg(3, 0, 9, 10, 1)
/* Buffer error reporting */ /* Buffer error reporting */
#define SYS_PMBSR_EL1 sys_reg(3, 0, 9, 10, 3) #define PMBSR_EL1_FAULT_FSC_SHIFT PMBSR_EL1_MSS_SHIFT
#define SYS_PMBSR_EL1_COLL_SHIFT 16 #define PMBSR_EL1_FAULT_FSC_MASK PMBSR_EL1_MSS_MASK
#define SYS_PMBSR_EL1_S_SHIFT 17
#define SYS_PMBSR_EL1_EA_SHIFT 18
#define SYS_PMBSR_EL1_DL_SHIFT 19
#define SYS_PMBSR_EL1_EC_SHIFT 26
#define SYS_PMBSR_EL1_EC_MASK 0x3fUL
#define SYS_PMBSR_EL1_EC_BUF (0x0UL << SYS_PMBSR_EL1_EC_SHIFT)
#define SYS_PMBSR_EL1_EC_FAULT_S1 (0x24UL << SYS_PMBSR_EL1_EC_SHIFT)
#define SYS_PMBSR_EL1_EC_FAULT_S2 (0x25UL << SYS_PMBSR_EL1_EC_SHIFT)
#define SYS_PMBSR_EL1_FAULT_FSC_SHIFT 0
#define SYS_PMBSR_EL1_FAULT_FSC_MASK 0x3fUL
#define SYS_PMBSR_EL1_BUF_BSC_SHIFT 0 #define PMBSR_EL1_BUF_BSC_SHIFT PMBSR_EL1_MSS_SHIFT
#define SYS_PMBSR_EL1_BUF_BSC_MASK 0x3fUL #define PMBSR_EL1_BUF_BSC_MASK PMBSR_EL1_MSS_MASK
#define SYS_PMBSR_EL1_BUF_BSC_FULL (0x1UL << SYS_PMBSR_EL1_BUF_BSC_SHIFT) #define PMBSR_EL1_BUF_BSC_FULL 0x1UL
/*** End of Statistical Profiling Extension ***/ /*** End of Statistical Profiling Extension ***/
...@@ -575,6 +496,7 @@ ...@@ -575,6 +496,7 @@
#define SCTLR_ELx_DSSBS (BIT(44)) #define SCTLR_ELx_DSSBS (BIT(44))
#define SCTLR_ELx_ATA (BIT(43)) #define SCTLR_ELx_ATA (BIT(43))
#define SCTLR_ELx_EE_SHIFT 25
#define SCTLR_ELx_ENIA_SHIFT 31 #define SCTLR_ELx_ENIA_SHIFT 31
#define SCTLR_ELx_ITFSB (BIT(37)) #define SCTLR_ELx_ITFSB (BIT(37))
...@@ -583,7 +505,7 @@ ...@@ -583,7 +505,7 @@
#define SCTLR_ELx_LSMAOE (BIT(29)) #define SCTLR_ELx_LSMAOE (BIT(29))
#define SCTLR_ELx_nTLSMD (BIT(28)) #define SCTLR_ELx_nTLSMD (BIT(28))
#define SCTLR_ELx_ENDA (BIT(27)) #define SCTLR_ELx_ENDA (BIT(27))
#define SCTLR_ELx_EE (BIT(25)) #define SCTLR_ELx_EE (BIT(SCTLR_ELx_EE_SHIFT))
#define SCTLR_ELx_EIS (BIT(22)) #define SCTLR_ELx_EIS (BIT(22))
#define SCTLR_ELx_IESB (BIT(21)) #define SCTLR_ELx_IESB (BIT(21))
#define SCTLR_ELx_TSCXT (BIT(20)) #define SCTLR_ELx_TSCXT (BIT(20))
...@@ -809,8 +731,8 @@ ...@@ -809,8 +731,8 @@
#define ARM64_FEATURE_FIELD_BITS 4 #define ARM64_FEATURE_FIELD_BITS 4
/* Create a mask for the feature bits of the specified feature. */ /* Defined for compatibility only, do not add new users. */
#define ARM64_FEATURE_MASK(x) (GENMASK_ULL(x##_SHIFT + ARM64_FEATURE_FIELD_BITS - 1, x##_SHIFT)) #define ARM64_FEATURE_MASK(x) (x##_MASK)
#ifdef __ASSEMBLY__ #ifdef __ASSEMBLY__
......
...@@ -96,5 +96,11 @@ ...@@ -96,5 +96,11 @@
#define HWCAP2_CSSC (1UL << 34) #define HWCAP2_CSSC (1UL << 34)
#define HWCAP2_RPRFM (1UL << 35) #define HWCAP2_RPRFM (1UL << 35)
#define HWCAP2_SVE2P1 (1UL << 36) #define HWCAP2_SVE2P1 (1UL << 36)
#define HWCAP2_SME2 (1UL << 37)
#define HWCAP2_SME2P1 (1UL << 38)
#define HWCAP2_SME_I16I32 (1UL << 39)
#define HWCAP2_SME_BI32I32 (1UL << 40)
#define HWCAP2_SME_B16B16 (1UL << 41)
#define HWCAP2_SME_F16F16 (1UL << 42)
#endif /* _UAPI__ASM_HWCAP_H */ #endif /* _UAPI__ASM_HWCAP_H */
...@@ -144,6 +144,14 @@ struct sve_context { ...@@ -144,6 +144,14 @@ struct sve_context {
#define SVE_SIG_FLAG_SM 0x1 /* Context describes streaming mode */ #define SVE_SIG_FLAG_SM 0x1 /* Context describes streaming mode */
/* TPIDR2_EL0 context */
#define TPIDR2_MAGIC 0x54504902
struct tpidr2_context {
struct _aarch64_ctx head;
__u64 tpidr2;
};
#define ZA_MAGIC 0x54366345 #define ZA_MAGIC 0x54366345
struct za_context { struct za_context {
...@@ -152,6 +160,14 @@ struct za_context { ...@@ -152,6 +160,14 @@ struct za_context {
__u16 __reserved[3]; __u16 __reserved[3];
}; };
#define ZT_MAGIC 0x5a544e01
struct zt_context {
struct _aarch64_ctx head;
__u16 nregs;
__u16 __reserved[3];
};
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */
#include <asm/sve_context.h> #include <asm/sve_context.h>
...@@ -304,4 +320,15 @@ struct za_context { ...@@ -304,4 +320,15 @@ struct za_context {
#define ZA_SIG_CONTEXT_SIZE(vq) \ #define ZA_SIG_CONTEXT_SIZE(vq) \
(ZA_SIG_REGS_OFFSET + ZA_SIG_REGS_SIZE(vq)) (ZA_SIG_REGS_OFFSET + ZA_SIG_REGS_SIZE(vq))
#define ZT_SIG_REG_SIZE 512
#define ZT_SIG_REG_BYTES (ZT_SIG_REG_SIZE / 8)
#define ZT_SIG_REGS_OFFSET sizeof(struct zt_context)
#define ZT_SIG_REGS_SIZE(n) (ZT_SIG_REG_BYTES * n)
#define ZT_SIG_CONTEXT_SIZE(n) \
(sizeof(struct zt_context) + ZT_SIG_REGS_SIZE(n))
#endif /* _UAPI__ASM_SIGCONTEXT_H */ #endif /* _UAPI__ASM_SIGCONTEXT_H */
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/arm_sdei.h> #include <linux/arm_sdei.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/ftrace.h>
#include <linux/kexec.h> #include <linux/kexec.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/dma-mapping.h> #include <linux/dma-mapping.h>
...@@ -193,6 +194,9 @@ int main(void) ...@@ -193,6 +194,9 @@ int main(void)
DEFINE(KIMAGE_HEAD, offsetof(struct kimage, head)); DEFINE(KIMAGE_HEAD, offsetof(struct kimage, head));
DEFINE(KIMAGE_START, offsetof(struct kimage, start)); DEFINE(KIMAGE_START, offsetof(struct kimage, start));
BLANK(); BLANK();
#endif
#ifdef CONFIG_FUNCTION_TRACER
DEFINE(FTRACE_OPS_FUNC, offsetof(struct ftrace_ops, func));
#endif #endif
return 0; return 0;
} }
This diff is collapsed.
...@@ -119,6 +119,12 @@ static const char *const hwcap_str[] = { ...@@ -119,6 +119,12 @@ static const char *const hwcap_str[] = {
[KERNEL_HWCAP_CSSC] = "cssc", [KERNEL_HWCAP_CSSC] = "cssc",
[KERNEL_HWCAP_RPRFM] = "rprfm", [KERNEL_HWCAP_RPRFM] = "rprfm",
[KERNEL_HWCAP_SVE2P1] = "sve2p1", [KERNEL_HWCAP_SVE2P1] = "sve2p1",
[KERNEL_HWCAP_SME2] = "sme2",
[KERNEL_HWCAP_SME2P1] = "sme2p1",
[KERNEL_HWCAP_SME_I16I32] = "smei16i32",
[KERNEL_HWCAP_SME_BI32I32] = "smebi32i32",
[KERNEL_HWCAP_SME_B16B16] = "smeb16b16",
[KERNEL_HWCAP_SME_F16F16] = "smef16f16",
}; };
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
...@@ -146,6 +152,12 @@ static const char *const compat_hwcap_str[] = { ...@@ -146,6 +152,12 @@ static const char *const compat_hwcap_str[] = {
[COMPAT_KERNEL_HWCAP(VFPD32)] = NULL, /* Not possible on arm64 */ [COMPAT_KERNEL_HWCAP(VFPD32)] = NULL, /* Not possible on arm64 */
[COMPAT_KERNEL_HWCAP(LPAE)] = "lpae", [COMPAT_KERNEL_HWCAP(LPAE)] = "lpae",
[COMPAT_KERNEL_HWCAP(EVTSTRM)] = "evtstrm", [COMPAT_KERNEL_HWCAP(EVTSTRM)] = "evtstrm",
[COMPAT_KERNEL_HWCAP(FPHP)] = "fphp",
[COMPAT_KERNEL_HWCAP(ASIMDHP)] = "asimdhp",
[COMPAT_KERNEL_HWCAP(ASIMDDP)] = "asimddp",
[COMPAT_KERNEL_HWCAP(ASIMDFHM)] = "asimdfhm",
[COMPAT_KERNEL_HWCAP(ASIMDBF16)] = "asimdbf16",
[COMPAT_KERNEL_HWCAP(I8MM)] = "i8mm",
}; };
#define COMPAT_KERNEL_HWCAP2(x) const_ilog2(COMPAT_HWCAP2_ ## x) #define COMPAT_KERNEL_HWCAP2(x) const_ilog2(COMPAT_HWCAP2_ ## x)
...@@ -155,6 +167,8 @@ static const char *const compat_hwcap2_str[] = { ...@@ -155,6 +167,8 @@ static const char *const compat_hwcap2_str[] = {
[COMPAT_KERNEL_HWCAP2(SHA1)] = "sha1", [COMPAT_KERNEL_HWCAP2(SHA1)] = "sha1",
[COMPAT_KERNEL_HWCAP2(SHA2)] = "sha2", [COMPAT_KERNEL_HWCAP2(SHA2)] = "sha2",
[COMPAT_KERNEL_HWCAP2(CRC32)] = "crc32", [COMPAT_KERNEL_HWCAP2(CRC32)] = "crc32",
[COMPAT_KERNEL_HWCAP2(SB)] = "sb",
[COMPAT_KERNEL_HWCAP2(SSBS)] = "ssbs",
}; };
#endif /* CONFIG_COMPAT */ #endif /* CONFIG_COMPAT */
......
...@@ -100,25 +100,35 @@ SYM_FUNC_START(sme_set_vq) ...@@ -100,25 +100,35 @@ SYM_FUNC_START(sme_set_vq)
SYM_FUNC_END(sme_set_vq) SYM_FUNC_END(sme_set_vq)
/* /*
* Save the SME state * Save the ZA and ZT state
* *
* x0 - pointer to buffer for state * x0 - pointer to buffer for state
* x1 - number of ZT registers to save
*/ */
SYM_FUNC_START(za_save_state) SYM_FUNC_START(sme_save_state)
_sme_rdsvl 1, 1 // x1 = VL/8 _sme_rdsvl 2, 1 // x2 = VL/8
sme_save_za 0, x1, 12 sme_save_za 0, x2, 12 // Leaves x0 pointing to the end of ZA
cbz x1, 1f
_str_zt 0
1:
ret ret
SYM_FUNC_END(za_save_state) SYM_FUNC_END(sme_save_state)
/* /*
* Load the SME state * Load the ZA and ZT state
* *
* x0 - pointer to buffer for state * x0 - pointer to buffer for state
* x1 - number of ZT registers to save
*/ */
SYM_FUNC_START(za_load_state) SYM_FUNC_START(sme_load_state)
_sme_rdsvl 1, 1 // x1 = VL/8 _sme_rdsvl 2, 1 // x2 = VL/8
sme_load_za 0, x1, 12 sme_load_za 0, x2, 12 // Leaves x0 pointing to the end of ZA
cbz x1, 1f
_ldr_zt 0
1:
ret ret
SYM_FUNC_END(za_load_state) SYM_FUNC_END(sme_load_state)
#endif /* CONFIG_ARM64_SME */ #endif /* CONFIG_ARM64_SME */
...@@ -65,13 +65,35 @@ SYM_CODE_START(ftrace_caller) ...@@ -65,13 +65,35 @@ SYM_CODE_START(ftrace_caller)
stp x29, x30, [sp, #FREGS_SIZE] stp x29, x30, [sp, #FREGS_SIZE]
add x29, sp, #FREGS_SIZE add x29, sp, #FREGS_SIZE
sub x0, x30, #AARCH64_INSN_SIZE // ip (callsite's BL insn) /* Prepare arguments for the the tracer func */
mov x1, x9 // parent_ip (callsite's LR) sub x0, x30, #AARCH64_INSN_SIZE // ip (callsite's BL insn)
ldr_l x2, function_trace_op // op mov x1, x9 // parent_ip (callsite's LR)
mov x3, sp // regs mov x3, sp // regs
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
/*
* The literal pointer to the ops is at an 8-byte aligned boundary
* which is either 12 or 16 bytes before the BL instruction in the call
* site. See ftrace_call_adjust() for details.
*
* Therefore here the LR points at `literal + 16` or `literal + 20`,
* and we can find the address of the literal in either case by
* aligning to an 8-byte boundary and subtracting 16. We do the
* alignment first as this allows us to fold the subtraction into the
* LDR.
*/
bic x2, x30, 0x7
ldr x2, [x2, #-16] // op
ldr x4, [x2, #FTRACE_OPS_FUNC] // op->func
blr x4 // op->func(ip, parent_ip, op, regs)
#else
ldr_l x2, function_trace_op // op
SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL) SYM_INNER_LABEL(ftrace_call, SYM_L_GLOBAL)
bl ftrace_stub bl ftrace_stub // func(ip, parent_ip, op, regs)
#endif
/* /*
* At the callsite x0-x8 and x19-x30 were live. Any C code will have preserved * At the callsite x0-x8 and x19-x30 were live. Any C code will have preserved
......
...@@ -275,7 +275,7 @@ alternative_if ARM64_HAS_ADDRESS_AUTH ...@@ -275,7 +275,7 @@ alternative_if ARM64_HAS_ADDRESS_AUTH
alternative_else_nop_endif alternative_else_nop_endif
1: 1:
scs_load tsk scs_load_current
.else .else
add x21, sp, #PT_REGS_SIZE add x21, sp, #PT_REGS_SIZE
get_current_task tsk get_current_task tsk
...@@ -311,13 +311,16 @@ alternative_else_nop_endif ...@@ -311,13 +311,16 @@ alternative_else_nop_endif
.endif .endif
#ifdef CONFIG_ARM64_PSEUDO_NMI #ifdef CONFIG_ARM64_PSEUDO_NMI
/* Save pmr */ alternative_if_not ARM64_HAS_GIC_PRIO_MASKING
alternative_if ARM64_HAS_IRQ_PRIO_MASKING b .Lskip_pmr_save\@
alternative_else_nop_endif
mrs_s x20, SYS_ICC_PMR_EL1 mrs_s x20, SYS_ICC_PMR_EL1
str x20, [sp, #S_PMR_SAVE] str x20, [sp, #S_PMR_SAVE]
mov x20, #GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET mov x20, #GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET
msr_s SYS_ICC_PMR_EL1, x20 msr_s SYS_ICC_PMR_EL1, x20
alternative_else_nop_endif
.Lskip_pmr_save\@:
#endif #endif
/* /*
...@@ -336,15 +339,19 @@ alternative_else_nop_endif ...@@ -336,15 +339,19 @@ alternative_else_nop_endif
.endif .endif
#ifdef CONFIG_ARM64_PSEUDO_NMI #ifdef CONFIG_ARM64_PSEUDO_NMI
/* Restore pmr */ alternative_if_not ARM64_HAS_GIC_PRIO_MASKING
alternative_if ARM64_HAS_IRQ_PRIO_MASKING b .Lskip_pmr_restore\@
alternative_else_nop_endif
ldr x20, [sp, #S_PMR_SAVE] ldr x20, [sp, #S_PMR_SAVE]
msr_s SYS_ICC_PMR_EL1, x20 msr_s SYS_ICC_PMR_EL1, x20
mrs_s x21, SYS_ICC_CTLR_EL1
tbz x21, #6, .L__skip_pmr_sync\@ // Check for ICC_CTLR_EL1.PMHE /* Ensure priority change is seen by redistributor */
dsb sy // Ensure priority change is seen by redistributor alternative_if_not ARM64_HAS_GIC_PRIO_RELAXED_SYNC
.L__skip_pmr_sync\@: dsb sy
alternative_else_nop_endif alternative_else_nop_endif
.Lskip_pmr_restore\@:
#endif #endif
ldp x21, x22, [sp, #S_PC] // load ELR, SPSR ldp x21, x22, [sp, #S_PC] // load ELR, SPSR
...@@ -848,7 +855,7 @@ SYM_FUNC_START(cpu_switch_to) ...@@ -848,7 +855,7 @@ SYM_FUNC_START(cpu_switch_to)
msr sp_el0, x1 msr sp_el0, x1
ptrauth_keys_install_kernel x1, x8, x9, x10 ptrauth_keys_install_kernel x1, x8, x9, x10
scs_save x0 scs_save x0
scs_load x1 scs_load_current
ret ret
SYM_FUNC_END(cpu_switch_to) SYM_FUNC_END(cpu_switch_to)
NOKPROBE(cpu_switch_to) NOKPROBE(cpu_switch_to)
...@@ -876,19 +883,19 @@ NOKPROBE(ret_from_fork) ...@@ -876,19 +883,19 @@ NOKPROBE(ret_from_fork)
*/ */
SYM_FUNC_START(call_on_irq_stack) SYM_FUNC_START(call_on_irq_stack)
#ifdef CONFIG_SHADOW_CALL_STACK #ifdef CONFIG_SHADOW_CALL_STACK
stp scs_sp, xzr, [sp, #-16]! get_current_task x16
scs_save x16
ldr_this_cpu scs_sp, irq_shadow_call_stack_ptr, x17 ldr_this_cpu scs_sp, irq_shadow_call_stack_ptr, x17
#endif #endif
/* Create a frame record to save our LR and SP (implicit in FP) */ /* Create a frame record to save our LR and SP (implicit in FP) */
stp x29, x30, [sp, #-16]! stp x29, x30, [sp, #-16]!
mov x29, sp mov x29, sp
ldr_this_cpu x16, irq_stack_ptr, x17 ldr_this_cpu x16, irq_stack_ptr, x17
mov x15, #IRQ_STACK_SIZE
add x16, x16, x15
/* Move to the new stack and call the function there */ /* Move to the new stack and call the function there */
mov sp, x16 add sp, x16, #IRQ_STACK_SIZE
blr x1 blr x1
/* /*
...@@ -897,9 +904,7 @@ SYM_FUNC_START(call_on_irq_stack) ...@@ -897,9 +904,7 @@ SYM_FUNC_START(call_on_irq_stack)
*/ */
mov sp, x29 mov sp, x29
ldp x29, x30, [sp], #16 ldp x29, x30, [sp], #16
#ifdef CONFIG_SHADOW_CALL_STACK scs_load_current
ldp scs_sp, xzr, [sp], #16
#endif
ret ret
SYM_FUNC_END(call_on_irq_stack) SYM_FUNC_END(call_on_irq_stack)
NOKPROBE(call_on_irq_stack) NOKPROBE(call_on_irq_stack)
......
...@@ -299,7 +299,7 @@ void task_set_vl_onexec(struct task_struct *task, enum vec_type type, ...@@ -299,7 +299,7 @@ void task_set_vl_onexec(struct task_struct *task, enum vec_type type,
/* /*
* TIF_SME controls whether a task can use SME without trapping while * TIF_SME controls whether a task can use SME without trapping while
* in userspace, when TIF_SME is set then we must have storage * in userspace, when TIF_SME is set then we must have storage
* alocated in sve_state and za_state to store the contents of both ZA * alocated in sve_state and sme_state to store the contents of both ZA
* and the SVE registers for both streaming and non-streaming modes. * and the SVE registers for both streaming and non-streaming modes.
* *
* If both SVCR.ZA and SVCR.SM are disabled then at any point we * If both SVCR.ZA and SVCR.SM are disabled then at any point we
...@@ -429,7 +429,8 @@ static void task_fpsimd_load(void) ...@@ -429,7 +429,8 @@ static void task_fpsimd_load(void)
write_sysreg_s(current->thread.svcr, SYS_SVCR); write_sysreg_s(current->thread.svcr, SYS_SVCR);
if (thread_za_enabled(&current->thread)) if (thread_za_enabled(&current->thread))
za_load_state(current->thread.za_state); sme_load_state(current->thread.sme_state,
system_supports_sme2());
if (thread_sm_enabled(&current->thread)) if (thread_sm_enabled(&current->thread))
restore_ffr = system_supports_fa64(); restore_ffr = system_supports_fa64();
...@@ -490,7 +491,8 @@ static void fpsimd_save(void) ...@@ -490,7 +491,8 @@ static void fpsimd_save(void)
*svcr = read_sysreg_s(SYS_SVCR); *svcr = read_sysreg_s(SYS_SVCR);
if (*svcr & SVCR_ZA_MASK) if (*svcr & SVCR_ZA_MASK)
za_save_state(last->za_state); sme_save_state(last->sme_state,
system_supports_sme2());
/* If we are in streaming mode override regular SVE. */ /* If we are in streaming mode override regular SVE. */
if (*svcr & SVCR_SM_MASK) { if (*svcr & SVCR_SM_MASK) {
...@@ -1257,30 +1259,30 @@ void fpsimd_release_task(struct task_struct *dead_task) ...@@ -1257,30 +1259,30 @@ void fpsimd_release_task(struct task_struct *dead_task)
#ifdef CONFIG_ARM64_SME #ifdef CONFIG_ARM64_SME
/* /*
* Ensure that task->thread.za_state is allocated and sufficiently large. * Ensure that task->thread.sme_state is allocated and sufficiently large.
* *
* This function should be used only in preparation for replacing * This function should be used only in preparation for replacing
* task->thread.za_state with new data. The memory is always zeroed * task->thread.sme_state with new data. The memory is always zeroed
* here to prevent stale data from showing through: this is done in * here to prevent stale data from showing through: this is done in
* the interest of testability and predictability, the architecture * the interest of testability and predictability, the architecture
* guarantees that when ZA is enabled it will be zeroed. * guarantees that when ZA is enabled it will be zeroed.
*/ */
void sme_alloc(struct task_struct *task) void sme_alloc(struct task_struct *task)
{ {
if (task->thread.za_state) { if (task->thread.sme_state) {
memset(task->thread.za_state, 0, za_state_size(task)); memset(task->thread.sme_state, 0, sme_state_size(task));
return; return;
} }
/* This could potentially be up to 64K. */ /* This could potentially be up to 64K. */
task->thread.za_state = task->thread.sme_state =
kzalloc(za_state_size(task), GFP_KERNEL); kzalloc(sme_state_size(task), GFP_KERNEL);
} }
static void sme_free(struct task_struct *task) static void sme_free(struct task_struct *task)
{ {
kfree(task->thread.za_state); kfree(task->thread.sme_state);
task->thread.za_state = NULL; task->thread.sme_state = NULL;
} }
void sme_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p) void sme_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
...@@ -1298,6 +1300,17 @@ void sme_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p) ...@@ -1298,6 +1300,17 @@ void sme_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
isb(); isb();
} }
/*
* This must be called after sme_kernel_enable(), we rely on the
* feature table being sorted to ensure this.
*/
void sme2_kernel_enable(const struct arm64_cpu_capabilities *__always_unused p)
{
/* Allow use of ZT0 */
write_sysreg_s(read_sysreg_s(SYS_SMCR_EL1) | SMCR_ELx_EZT0_MASK,
SYS_SMCR_EL1);
}
/* /*
* This must be called after sme_kernel_enable(), we rely on the * This must be called after sme_kernel_enable(), we rely on the
* feature table being sorted to ensure this. * feature table being sorted to ensure this.
...@@ -1322,7 +1335,6 @@ u64 read_smcr_features(void) ...@@ -1322,7 +1335,6 @@ u64 read_smcr_features(void)
unsigned int vq_max; unsigned int vq_max;
sme_kernel_enable(NULL); sme_kernel_enable(NULL);
sme_smstart_sm();
/* /*
* Set the maximum possible VL. * Set the maximum possible VL.
...@@ -1332,11 +1344,9 @@ u64 read_smcr_features(void) ...@@ -1332,11 +1344,9 @@ u64 read_smcr_features(void)
smcr = read_sysreg_s(SYS_SMCR_EL1); smcr = read_sysreg_s(SYS_SMCR_EL1);
smcr &= ~(u64)SMCR_ELx_LEN_MASK; /* Only the LEN field */ smcr &= ~(u64)SMCR_ELx_LEN_MASK; /* Only the LEN field */
vq_max = sve_vq_from_vl(sve_get_vl()); vq_max = sve_vq_from_vl(sme_get_vl());
smcr |= vq_max - 1; /* set LEN field to maximum effective value */ smcr |= vq_max - 1; /* set LEN field to maximum effective value */
sme_smstop_sm();
return smcr; return smcr;
} }
...@@ -1488,7 +1498,7 @@ void do_sme_acc(unsigned long esr, struct pt_regs *regs) ...@@ -1488,7 +1498,7 @@ void do_sme_acc(unsigned long esr, struct pt_regs *regs)
sve_alloc(current, false); sve_alloc(current, false);
sme_alloc(current); sme_alloc(current);
if (!current->thread.sve_state || !current->thread.za_state) { if (!current->thread.sve_state || !current->thread.sme_state) {
force_sig(SIGKILL); force_sig(SIGKILL);
return; return;
} }
...@@ -1609,7 +1619,7 @@ static void fpsimd_flush_thread_vl(enum vec_type type) ...@@ -1609,7 +1619,7 @@ static void fpsimd_flush_thread_vl(enum vec_type type)
void fpsimd_flush_thread(void) void fpsimd_flush_thread(void)
{ {
void *sve_state = NULL; void *sve_state = NULL;
void *za_state = NULL; void *sme_state = NULL;
if (!system_supports_fpsimd()) if (!system_supports_fpsimd())
return; return;
...@@ -1634,8 +1644,8 @@ void fpsimd_flush_thread(void) ...@@ -1634,8 +1644,8 @@ void fpsimd_flush_thread(void)
clear_thread_flag(TIF_SME); clear_thread_flag(TIF_SME);
/* Defer kfree() while in atomic context */ /* Defer kfree() while in atomic context */
za_state = current->thread.za_state; sme_state = current->thread.sme_state;
current->thread.za_state = NULL; current->thread.sme_state = NULL;
fpsimd_flush_thread_vl(ARM64_VEC_SME); fpsimd_flush_thread_vl(ARM64_VEC_SME);
current->thread.svcr = 0; current->thread.svcr = 0;
...@@ -1645,7 +1655,7 @@ void fpsimd_flush_thread(void) ...@@ -1645,7 +1655,7 @@ void fpsimd_flush_thread(void)
put_cpu_fpsimd_context(); put_cpu_fpsimd_context();
kfree(sve_state); kfree(sve_state);
kfree(za_state); kfree(sme_state);
} }
/* /*
...@@ -1711,7 +1721,7 @@ static void fpsimd_bind_task_to_cpu(void) ...@@ -1711,7 +1721,7 @@ static void fpsimd_bind_task_to_cpu(void)
WARN_ON(!system_supports_fpsimd()); WARN_ON(!system_supports_fpsimd());
last->st = &current->thread.uw.fpsimd_state; last->st = &current->thread.uw.fpsimd_state;
last->sve_state = current->thread.sve_state; last->sve_state = current->thread.sve_state;
last->za_state = current->thread.za_state; last->sme_state = current->thread.sme_state;
last->sve_vl = task_get_sve_vl(current); last->sve_vl = task_get_sve_vl(current);
last->sme_vl = task_get_sme_vl(current); last->sme_vl = task_get_sme_vl(current);
last->svcr = &current->thread.svcr; last->svcr = &current->thread.svcr;
......
...@@ -60,6 +60,89 @@ int ftrace_regs_query_register_offset(const char *name) ...@@ -60,6 +60,89 @@ int ftrace_regs_query_register_offset(const char *name)
} }
#endif #endif
unsigned long ftrace_call_adjust(unsigned long addr)
{
/*
* When using mcount, addr is the address of the mcount call
* instruction, and no adjustment is necessary.
*/
if (!IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_ARGS))
return addr;
/*
* When using patchable-function-entry without pre-function NOPS, addr
* is the address of the first NOP after the function entry point.
*
* The compiler has either generated:
*
* addr+00: func: NOP // To be patched to MOV X9, LR
* addr+04: NOP // To be patched to BL <caller>
*
* Or:
*
* addr-04: BTI C
* addr+00: func: NOP // To be patched to MOV X9, LR
* addr+04: NOP // To be patched to BL <caller>
*
* We must adjust addr to the address of the NOP which will be patched
* to `BL <caller>`, which is at `addr + 4` bytes in either case.
*
*/
if (!IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS))
return addr + AARCH64_INSN_SIZE;
/*
* When using patchable-function-entry with pre-function NOPs, addr is
* the address of the first pre-function NOP.
*
* Starting from an 8-byte aligned base, the compiler has either
* generated:
*
* addr+00: NOP // Literal (first 32 bits)
* addr+04: NOP // Literal (last 32 bits)
* addr+08: func: NOP // To be patched to MOV X9, LR
* addr+12: NOP // To be patched to BL <caller>
*
* Or:
*
* addr+00: NOP // Literal (first 32 bits)
* addr+04: NOP // Literal (last 32 bits)
* addr+08: func: BTI C
* addr+12: NOP // To be patched to MOV X9, LR
* addr+16: NOP // To be patched to BL <caller>
*
* We must adjust addr to the address of the NOP which will be patched
* to `BL <caller>`, which is at either addr+12 or addr+16 depending on
* whether there is a BTI.
*/
if (!IS_ALIGNED(addr, sizeof(unsigned long))) {
WARN_RATELIMIT(1, "Misaligned patch-site %pS\n",
(void *)(addr + 8));
return 0;
}
/* Skip the NOPs placed before the function entry point */
addr += 2 * AARCH64_INSN_SIZE;
/* Skip any BTI */
if (IS_ENABLED(CONFIG_ARM64_BTI_KERNEL)) {
u32 insn = le32_to_cpu(*(__le32 *)addr);
if (aarch64_insn_is_bti(insn)) {
addr += AARCH64_INSN_SIZE;
} else if (insn != aarch64_insn_gen_nop()) {
WARN_RATELIMIT(1, "unexpected insn in patch-site %pS: 0x%08x\n",
(void *)addr, insn);
}
}
/* Skip the first NOP after function entry */
addr += AARCH64_INSN_SIZE;
return addr;
}
/* /*
* Replace a single instruction, which may be a branch or NOP. * Replace a single instruction, which may be a branch or NOP.
* If @validate == true, a replaced instruction is checked against 'old'. * If @validate == true, a replaced instruction is checked against 'old'.
...@@ -98,6 +181,13 @@ int ftrace_update_ftrace_func(ftrace_func_t func) ...@@ -98,6 +181,13 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
unsigned long pc; unsigned long pc;
u32 new; u32 new;
/*
* When using CALL_OPS, the function to call is associated with the
* call site, and we don't have a global function pointer to update.
*/
if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS))
return 0;
pc = (unsigned long)ftrace_call; pc = (unsigned long)ftrace_call;
new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func, new = aarch64_insn_gen_branch_imm(pc, (unsigned long)func,
AARCH64_INSN_BRANCH_LINK); AARCH64_INSN_BRANCH_LINK);
...@@ -176,6 +266,44 @@ static bool ftrace_find_callable_addr(struct dyn_ftrace *rec, ...@@ -176,6 +266,44 @@ static bool ftrace_find_callable_addr(struct dyn_ftrace *rec,
return true; return true;
} }
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
static const struct ftrace_ops *arm64_rec_get_ops(struct dyn_ftrace *rec)
{
const struct ftrace_ops *ops = NULL;
if (rec->flags & FTRACE_FL_CALL_OPS_EN) {
ops = ftrace_find_unique_ops(rec);
WARN_ON_ONCE(!ops);
}
if (!ops)
ops = &ftrace_list_ops;
return ops;
}
static int ftrace_rec_set_ops(const struct dyn_ftrace *rec,
const struct ftrace_ops *ops)
{
unsigned long literal = ALIGN_DOWN(rec->ip - 12, 8);
return aarch64_insn_write_literal_u64((void *)literal,
(unsigned long)ops);
}
static int ftrace_rec_set_nop_ops(struct dyn_ftrace *rec)
{
return ftrace_rec_set_ops(rec, &ftrace_nop_ops);
}
static int ftrace_rec_update_ops(struct dyn_ftrace *rec)
{
return ftrace_rec_set_ops(rec, arm64_rec_get_ops(rec));
}
#else
static int ftrace_rec_set_nop_ops(struct dyn_ftrace *rec) { return 0; }
static int ftrace_rec_update_ops(struct dyn_ftrace *rec) { return 0; }
#endif
/* /*
* Turn on the call to ftrace_caller() in instrumented function * Turn on the call to ftrace_caller() in instrumented function
*/ */
...@@ -183,6 +311,11 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) ...@@ -183,6 +311,11 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
{ {
unsigned long pc = rec->ip; unsigned long pc = rec->ip;
u32 old, new; u32 old, new;
int ret;
ret = ftrace_rec_update_ops(rec);
if (ret)
return ret;
if (!ftrace_find_callable_addr(rec, NULL, &addr)) if (!ftrace_find_callable_addr(rec, NULL, &addr))
return -EINVAL; return -EINVAL;
...@@ -193,6 +326,19 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) ...@@ -193,6 +326,19 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
return ftrace_modify_code(pc, old, new, true); return ftrace_modify_code(pc, old, new, true);
} }
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS
int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr,
unsigned long addr)
{
if (WARN_ON_ONCE(old_addr != (unsigned long)ftrace_caller))
return -EINVAL;
if (WARN_ON_ONCE(addr != (unsigned long)ftrace_caller))
return -EINVAL;
return ftrace_rec_update_ops(rec);
}
#endif
#ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS #ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
/* /*
* The compiler has inserted two NOPs before the regular function prologue. * The compiler has inserted two NOPs before the regular function prologue.
...@@ -209,7 +355,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) ...@@ -209,7 +355,7 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
* | NOP | MOV X9, LR | MOV X9, LR | * | NOP | MOV X9, LR | MOV X9, LR |
* | NOP | NOP | BL <entry> | * | NOP | NOP | BL <entry> |
* *
* The LR value will be recovered by ftrace_regs_entry, and restored into LR * The LR value will be recovered by ftrace_caller, and restored into LR
* before returning to the regular function prologue. When a function is not * before returning to the regular function prologue. When a function is not
* being traced, the MOV is not harmful given x9 is not live per the AAPCS. * being traced, the MOV is not harmful given x9 is not live per the AAPCS.
* *
...@@ -220,6 +366,11 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec) ...@@ -220,6 +366,11 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
{ {
unsigned long pc = rec->ip - AARCH64_INSN_SIZE; unsigned long pc = rec->ip - AARCH64_INSN_SIZE;
u32 old, new; u32 old, new;
int ret;
ret = ftrace_rec_set_nop_ops(rec);
if (ret)
return ret;
old = aarch64_insn_gen_nop(); old = aarch64_insn_gen_nop();
new = aarch64_insn_gen_move_reg(AARCH64_INSN_REG_9, new = aarch64_insn_gen_move_reg(AARCH64_INSN_REG_9,
...@@ -237,9 +388,14 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, ...@@ -237,9 +388,14 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec,
{ {
unsigned long pc = rec->ip; unsigned long pc = rec->ip;
u32 old = 0, new; u32 old = 0, new;
int ret;
new = aarch64_insn_gen_nop(); new = aarch64_insn_gen_nop();
ret = ftrace_rec_set_nop_ops(rec);
if (ret)
return ret;
/* /*
* When using mcount, callsites in modules may have been initalized to * When using mcount, callsites in modules may have been initalized to
* call an arbitrary module PLT (which redirects to the _mcount stub) * call an arbitrary module PLT (which redirects to the _mcount stub)
......
...@@ -70,13 +70,14 @@ ...@@ -70,13 +70,14 @@
__EFI_PE_HEADER __EFI_PE_HEADER
__INIT .section ".idmap.text","a"
/* /*
* The following callee saved general purpose registers are used on the * The following callee saved general purpose registers are used on the
* primary lowlevel boot path: * primary lowlevel boot path:
* *
* Register Scope Purpose * Register Scope Purpose
* x19 primary_entry() .. start_kernel() whether we entered with the MMU on
* x20 primary_entry() .. __primary_switch() CPU boot mode * x20 primary_entry() .. __primary_switch() CPU boot mode
* x21 primary_entry() .. start_kernel() FDT pointer passed at boot in x0 * x21 primary_entry() .. start_kernel() FDT pointer passed at boot in x0
* x22 create_idmap() .. start_kernel() ID map VA of the DT blob * x22 create_idmap() .. start_kernel() ID map VA of the DT blob
...@@ -86,10 +87,23 @@ ...@@ -86,10 +87,23 @@
* x28 create_idmap() callee preserved temp register * x28 create_idmap() callee preserved temp register
*/ */
SYM_CODE_START(primary_entry) SYM_CODE_START(primary_entry)
bl record_mmu_state
bl preserve_boot_args bl preserve_boot_args
bl create_idmap
/*
* If we entered with the MMU and caches on, clean the ID mapped part
* of the primary boot code to the PoC so we can safely execute it with
* the MMU off.
*/
cbz x19, 0f
adrp x0, __idmap_text_start
adr_l x1, __idmap_text_end
adr_l x2, dcache_clean_poc
blr x2
0: mov x0, x19
bl init_kernel_el // w0=cpu_boot_mode bl init_kernel_el // w0=cpu_boot_mode
mov x20, x0 mov x20, x0
bl create_idmap
/* /*
* The following calls CPU setup code, see arch/arm64/mm/proc.S for * The following calls CPU setup code, see arch/arm64/mm/proc.S for
...@@ -109,6 +123,40 @@ SYM_CODE_START(primary_entry) ...@@ -109,6 +123,40 @@ SYM_CODE_START(primary_entry)
b __primary_switch b __primary_switch
SYM_CODE_END(primary_entry) SYM_CODE_END(primary_entry)
__INIT
SYM_CODE_START_LOCAL(record_mmu_state)
mrs x19, CurrentEL
cmp x19, #CurrentEL_EL2
mrs x19, sctlr_el1
b.ne 0f
mrs x19, sctlr_el2
0:
CPU_LE( tbnz x19, #SCTLR_ELx_EE_SHIFT, 1f )
CPU_BE( tbz x19, #SCTLR_ELx_EE_SHIFT, 1f )
tst x19, #SCTLR_ELx_C // Z := (C == 0)
and x19, x19, #SCTLR_ELx_M // isolate M bit
csel x19, xzr, x19, eq // clear x19 if Z
ret
/*
* Set the correct endianness early so all memory accesses issued
* before init_kernel_el() occur in the correct byte order. Note that
* this means the MMU must be disabled, or the active ID map will end
* up getting interpreted with the wrong byte order.
*/
1: eor x19, x19, #SCTLR_ELx_EE
bic x19, x19, #SCTLR_ELx_M
b.ne 2f
pre_disable_mmu_workaround
msr sctlr_el2, x19
b 3f
pre_disable_mmu_workaround
2: msr sctlr_el1, x19
3: isb
mov x19, xzr
ret
SYM_CODE_END(record_mmu_state)
/* /*
* Preserve the arguments passed by the bootloader in x0 .. x3 * Preserve the arguments passed by the bootloader in x0 .. x3
*/ */
...@@ -119,11 +167,14 @@ SYM_CODE_START_LOCAL(preserve_boot_args) ...@@ -119,11 +167,14 @@ SYM_CODE_START_LOCAL(preserve_boot_args)
stp x21, x1, [x0] // x0 .. x3 at kernel entry stp x21, x1, [x0] // x0 .. x3 at kernel entry
stp x2, x3, [x0, #16] stp x2, x3, [x0, #16]
cbnz x19, 0f // skip cache invalidation if MMU is on
dmb sy // needed before dc ivac with dmb sy // needed before dc ivac with
// MMU off // MMU off
add x1, x0, #0x20 // 4 x 8 bytes add x1, x0, #0x20 // 4 x 8 bytes
b dcache_inval_poc // tail call b dcache_inval_poc // tail call
0: str_l x19, mmu_enabled_at_boot, x0
ret
SYM_CODE_END(preserve_boot_args) SYM_CODE_END(preserve_boot_args)
SYM_FUNC_START_LOCAL(clear_page_tables) SYM_FUNC_START_LOCAL(clear_page_tables)
...@@ -360,12 +411,13 @@ SYM_FUNC_START_LOCAL(create_idmap) ...@@ -360,12 +411,13 @@ SYM_FUNC_START_LOCAL(create_idmap)
* accesses (MMU disabled), invalidate those tables again to * accesses (MMU disabled), invalidate those tables again to
* remove any speculatively loaded cache lines. * remove any speculatively loaded cache lines.
*/ */
cbnz x19, 0f // skip cache invalidation if MMU is on
dmb sy dmb sy
adrp x0, init_idmap_pg_dir adrp x0, init_idmap_pg_dir
adrp x1, init_idmap_pg_end adrp x1, init_idmap_pg_end
bl dcache_inval_poc bl dcache_inval_poc
ret x28 0: ret x28
SYM_FUNC_END(create_idmap) SYM_FUNC_END(create_idmap)
SYM_FUNC_START_LOCAL(create_kernel_mapping) SYM_FUNC_START_LOCAL(create_kernel_mapping)
...@@ -404,7 +456,7 @@ SYM_FUNC_END(create_kernel_mapping) ...@@ -404,7 +456,7 @@ SYM_FUNC_END(create_kernel_mapping)
stp xzr, xzr, [sp, #S_STACKFRAME] stp xzr, xzr, [sp, #S_STACKFRAME]
add x29, sp, #S_STACKFRAME add x29, sp, #S_STACKFRAME
scs_load \tsk scs_load_current
adr_l \tmp1, __per_cpu_offset adr_l \tmp1, __per_cpu_offset
ldr w\tmp2, [\tsk, #TSK_TI_CPU] ldr w\tmp2, [\tsk, #TSK_TI_CPU]
...@@ -476,7 +528,7 @@ SYM_FUNC_END(__primary_switched) ...@@ -476,7 +528,7 @@ SYM_FUNC_END(__primary_switched)
* end early head section, begin head code that is also used for * end early head section, begin head code that is also used for
* hotplug and needs to have the same protections as the text region * hotplug and needs to have the same protections as the text region
*/ */
.section ".idmap.text","awx" .section ".idmap.text","a"
/* /*
* Starting from EL2 or EL1, configure the CPU to execute at the highest * Starting from EL2 or EL1, configure the CPU to execute at the highest
...@@ -489,14 +541,17 @@ SYM_FUNC_END(__primary_switched) ...@@ -489,14 +541,17 @@ SYM_FUNC_END(__primary_switched)
* Returns either BOOT_CPU_MODE_EL1 or BOOT_CPU_MODE_EL2 in x0 if * Returns either BOOT_CPU_MODE_EL1 or BOOT_CPU_MODE_EL2 in x0 if
* booted in EL1 or EL2 respectively, with the top 32 bits containing * booted in EL1 or EL2 respectively, with the top 32 bits containing
* potential context flags. These flags are *not* stored in __boot_cpu_mode. * potential context flags. These flags are *not* stored in __boot_cpu_mode.
*
* x0: whether we are being called from the primary boot path with the MMU on
*/ */
SYM_FUNC_START(init_kernel_el) SYM_FUNC_START(init_kernel_el)
mrs x0, CurrentEL mrs x1, CurrentEL
cmp x0, #CurrentEL_EL2 cmp x1, #CurrentEL_EL2
b.eq init_el2 b.eq init_el2
SYM_INNER_LABEL(init_el1, SYM_L_LOCAL) SYM_INNER_LABEL(init_el1, SYM_L_LOCAL)
mov_q x0, INIT_SCTLR_EL1_MMU_OFF mov_q x0, INIT_SCTLR_EL1_MMU_OFF
pre_disable_mmu_workaround
msr sctlr_el1, x0 msr sctlr_el1, x0
isb isb
mov_q x0, INIT_PSTATE_EL1 mov_q x0, INIT_PSTATE_EL1
...@@ -506,6 +561,15 @@ SYM_INNER_LABEL(init_el1, SYM_L_LOCAL) ...@@ -506,6 +561,15 @@ SYM_INNER_LABEL(init_el1, SYM_L_LOCAL)
eret eret
SYM_INNER_LABEL(init_el2, SYM_L_LOCAL) SYM_INNER_LABEL(init_el2, SYM_L_LOCAL)
msr elr_el2, lr
// clean all HYP code to the PoC if we booted at EL2 with the MMU on
cbz x0, 0f
adrp x0, __hyp_idmap_text_start
adr_l x1, __hyp_text_end
adr_l x2, dcache_clean_poc
blr x2
0:
mov_q x0, HCR_HOST_NVHE_FLAGS mov_q x0, HCR_HOST_NVHE_FLAGS
msr hcr_el2, x0 msr hcr_el2, x0
isb isb
...@@ -529,38 +593,27 @@ SYM_INNER_LABEL(init_el2, SYM_L_LOCAL) ...@@ -529,38 +593,27 @@ SYM_INNER_LABEL(init_el2, SYM_L_LOCAL)
cbz x0, 1f cbz x0, 1f
/* Set a sane SCTLR_EL1, the VHE way */ /* Set a sane SCTLR_EL1, the VHE way */
pre_disable_mmu_workaround
msr_s SYS_SCTLR_EL12, x1 msr_s SYS_SCTLR_EL12, x1
mov x2, #BOOT_CPU_FLAG_E2H mov x2, #BOOT_CPU_FLAG_E2H
b 2f b 2f
1: 1:
pre_disable_mmu_workaround
msr sctlr_el1, x1 msr sctlr_el1, x1
mov x2, xzr mov x2, xzr
2: 2:
msr elr_el2, lr
mov w0, #BOOT_CPU_MODE_EL2 mov w0, #BOOT_CPU_MODE_EL2
orr x0, x0, x2 orr x0, x0, x2
eret eret
SYM_FUNC_END(init_kernel_el) SYM_FUNC_END(init_kernel_el)
/*
* Sets the __boot_cpu_mode flag depending on the CPU boot mode passed
* in w0. See arch/arm64/include/asm/virt.h for more info.
*/
SYM_FUNC_START_LOCAL(set_cpu_boot_mode_flag)
adr_l x1, __boot_cpu_mode
cmp w0, #BOOT_CPU_MODE_EL2
b.ne 1f
add x1, x1, #4
1: str w0, [x1] // Save CPU boot mode
ret
SYM_FUNC_END(set_cpu_boot_mode_flag)
/* /*
* This provides a "holding pen" for platforms to hold all secondary * This provides a "holding pen" for platforms to hold all secondary
* cores are held until we're ready for them to initialise. * cores are held until we're ready for them to initialise.
*/ */
SYM_FUNC_START(secondary_holding_pen) SYM_FUNC_START(secondary_holding_pen)
mov x0, xzr
bl init_kernel_el // w0=cpu_boot_mode bl init_kernel_el // w0=cpu_boot_mode
mrs x2, mpidr_el1 mrs x2, mpidr_el1
mov_q x1, MPIDR_HWID_BITMASK mov_q x1, MPIDR_HWID_BITMASK
...@@ -578,6 +631,7 @@ SYM_FUNC_END(secondary_holding_pen) ...@@ -578,6 +631,7 @@ SYM_FUNC_END(secondary_holding_pen)
* be used where CPUs are brought online dynamically by the kernel. * be used where CPUs are brought online dynamically by the kernel.
*/ */
SYM_FUNC_START(secondary_entry) SYM_FUNC_START(secondary_entry)
mov x0, xzr
bl init_kernel_el // w0=cpu_boot_mode bl init_kernel_el // w0=cpu_boot_mode
b secondary_startup b secondary_startup
SYM_FUNC_END(secondary_entry) SYM_FUNC_END(secondary_entry)
...@@ -587,7 +641,6 @@ SYM_FUNC_START_LOCAL(secondary_startup) ...@@ -587,7 +641,6 @@ SYM_FUNC_START_LOCAL(secondary_startup)
* Common entry point for secondary CPUs. * Common entry point for secondary CPUs.
*/ */
mov x20, x0 // preserve boot mode mov x20, x0 // preserve boot mode
bl finalise_el2
bl __cpu_secondary_check52bitva bl __cpu_secondary_check52bitva
#if VA_BITS > 48 #if VA_BITS > 48
ldr_l x0, vabits_actual ldr_l x0, vabits_actual
...@@ -600,9 +653,14 @@ SYM_FUNC_START_LOCAL(secondary_startup) ...@@ -600,9 +653,14 @@ SYM_FUNC_START_LOCAL(secondary_startup)
br x8 br x8
SYM_FUNC_END(secondary_startup) SYM_FUNC_END(secondary_startup)
.text
SYM_FUNC_START_LOCAL(__secondary_switched) SYM_FUNC_START_LOCAL(__secondary_switched)
mov x0, x20 mov x0, x20
bl set_cpu_boot_mode_flag bl set_cpu_boot_mode_flag
mov x0, x20
bl finalise_el2
str_l xzr, __early_cpu_boot_status, x3 str_l xzr, __early_cpu_boot_status, x3
adr_l x5, vectors adr_l x5, vectors
msr vbar_el1, x5 msr vbar_el1, x5
...@@ -628,6 +686,19 @@ SYM_FUNC_START_LOCAL(__secondary_too_slow) ...@@ -628,6 +686,19 @@ SYM_FUNC_START_LOCAL(__secondary_too_slow)
b __secondary_too_slow b __secondary_too_slow
SYM_FUNC_END(__secondary_too_slow) SYM_FUNC_END(__secondary_too_slow)
/*
* Sets the __boot_cpu_mode flag depending on the CPU boot mode passed
* in w0. See arch/arm64/include/asm/virt.h for more info.
*/
SYM_FUNC_START_LOCAL(set_cpu_boot_mode_flag)
adr_l x1, __boot_cpu_mode
cmp w0, #BOOT_CPU_MODE_EL2
b.ne 1f
add x1, x1, #4
1: str w0, [x1] // Save CPU boot mode
ret
SYM_FUNC_END(set_cpu_boot_mode_flag)
/* /*
* The booting CPU updates the failed status @__early_cpu_boot_status, * The booting CPU updates the failed status @__early_cpu_boot_status,
* with MMU turned off. * with MMU turned off.
...@@ -659,6 +730,7 @@ SYM_FUNC_END(__secondary_too_slow) ...@@ -659,6 +730,7 @@ SYM_FUNC_END(__secondary_too_slow)
* Checks if the selected granule size is supported by the CPU. * Checks if the selected granule size is supported by the CPU.
* If it isn't, park the CPU * If it isn't, park the CPU
*/ */
.section ".idmap.text","a"
SYM_FUNC_START(__enable_mmu) SYM_FUNC_START(__enable_mmu)
mrs x3, ID_AA64MMFR0_EL1 mrs x3, ID_AA64MMFR0_EL1
ubfx x3, x3, #ID_AA64MMFR0_EL1_TGRAN_SHIFT, 4 ubfx x3, x3, #ID_AA64MMFR0_EL1_TGRAN_SHIFT, 4
......
...@@ -132,6 +132,13 @@ SYM_CODE_START_LOCAL(__finalise_el2) ...@@ -132,6 +132,13 @@ SYM_CODE_START_LOCAL(__finalise_el2)
orr x0, x0, SMCR_ELx_FA64_MASK orr x0, x0, SMCR_ELx_FA64_MASK
.Lskip_sme_fa64: .Lskip_sme_fa64:
// ZT0 available?
mrs_s x1, SYS_ID_AA64SMFR0_EL1
__check_override id_aa64smfr0 ID_AA64SMFR0_EL1_SMEver_SHIFT 4 .Linit_sme_zt0 .Lskip_sme_zt0
.Linit_sme_zt0:
orr x0, x0, SMCR_ELx_EZT0_MASK
.Lskip_sme_zt0:
orr x0, x0, #SMCR_ELx_LEN_MASK // Enable full SME vector orr x0, x0, #SMCR_ELx_LEN_MASK // Enable full SME vector
msr_s SYS_SMCR_EL2, x0 // length for EL1. msr_s SYS_SMCR_EL2, x0 // length for EL1.
......
...@@ -131,6 +131,7 @@ static const struct ftr_set_desc smfr0 __initconst = { ...@@ -131,6 +131,7 @@ static const struct ftr_set_desc smfr0 __initconst = {
.name = "id_aa64smfr0", .name = "id_aa64smfr0",
.override = &id_aa64smfr0_override, .override = &id_aa64smfr0_override,
.fields = { .fields = {
FIELD("smever", ID_AA64SMFR0_EL1_SMEver_SHIFT, NULL),
/* FA64 is a one bit field... :-/ */ /* FA64 is a one bit field... :-/ */
{ "fa64", ID_AA64SMFR0_EL1_FA64_SHIFT, 1, }, { "fa64", ID_AA64SMFR0_EL1_FA64_SHIFT, 1, },
{} {}
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#error This file should only be included in vmlinux.lds.S #error This file should only be included in vmlinux.lds.S
#endif #endif
PROVIDE(__efistub_primary_entry_offset = primary_entry - _text); PROVIDE(__efistub_primary_entry = primary_entry);
/* /*
* The EFI stub has its own symbol namespace prefixed by __efistub_, to * The EFI stub has its own symbol namespace prefixed by __efistub_, to
...@@ -21,10 +21,11 @@ PROVIDE(__efistub_primary_entry_offset = primary_entry - _text); ...@@ -21,10 +21,11 @@ PROVIDE(__efistub_primary_entry_offset = primary_entry - _text);
* linked at. The routines below are all implemented in assembler in a * linked at. The routines below are all implemented in assembler in a
* position independent manner * position independent manner
*/ */
PROVIDE(__efistub_dcache_clean_poc = __pi_dcache_clean_poc); PROVIDE(__efistub_caches_clean_inval_pou = __pi_caches_clean_inval_pou);
PROVIDE(__efistub__text = _text); PROVIDE(__efistub__text = _text);
PROVIDE(__efistub__end = _end); PROVIDE(__efistub__end = _end);
PROVIDE(__efistub___inittext_end = __inittext_end);
PROVIDE(__efistub__edata = _edata); PROVIDE(__efistub__edata = _edata);
PROVIDE(__efistub_screen_info = screen_info); PROVIDE(__efistub_screen_info = screen_info);
PROVIDE(__efistub__ctype = _ctype); PROVIDE(__efistub__ctype = _ctype);
...@@ -67,9 +68,7 @@ KVM_NVHE_ALIAS(__hyp_stub_vectors); ...@@ -67,9 +68,7 @@ KVM_NVHE_ALIAS(__hyp_stub_vectors);
KVM_NVHE_ALIAS(vgic_v2_cpuif_trap); KVM_NVHE_ALIAS(vgic_v2_cpuif_trap);
KVM_NVHE_ALIAS(vgic_v3_cpuif_trap); KVM_NVHE_ALIAS(vgic_v3_cpuif_trap);
/* Static key checked in pmr_sync(). */
#ifdef CONFIG_ARM64_PSEUDO_NMI #ifdef CONFIG_ARM64_PSEUDO_NMI
KVM_NVHE_ALIAS(gic_pmr_sync);
/* Static key checked in GIC_PRIO_IRQOFF. */ /* Static key checked in GIC_PRIO_IRQOFF. */
KVM_NVHE_ALIAS(gic_nonsecure_priorities); KVM_NVHE_ALIAS(gic_nonsecure_priorities);
#endif #endif
......
...@@ -130,7 +130,8 @@ struct eh_frame { ...@@ -130,7 +130,8 @@ struct eh_frame {
static int noinstr scs_handle_fde_frame(const struct eh_frame *frame, static int noinstr scs_handle_fde_frame(const struct eh_frame *frame,
bool fde_has_augmentation_data, bool fde_has_augmentation_data,
int code_alignment_factor) int code_alignment_factor,
bool dry_run)
{ {
int size = frame->size - offsetof(struct eh_frame, opcodes) + 4; int size = frame->size - offsetof(struct eh_frame, opcodes) + 4;
u64 loc = (u64)offset_to_ptr(&frame->initial_loc); u64 loc = (u64)offset_to_ptr(&frame->initial_loc);
...@@ -184,7 +185,8 @@ static int noinstr scs_handle_fde_frame(const struct eh_frame *frame, ...@@ -184,7 +185,8 @@ static int noinstr scs_handle_fde_frame(const struct eh_frame *frame,
break; break;
case DW_CFA_negate_ra_state: case DW_CFA_negate_ra_state:
scs_patch_loc(loc - 4); if (!dry_run)
scs_patch_loc(loc - 4);
break; break;
case 0x40 ... 0x7f: case 0x40 ... 0x7f:
...@@ -235,9 +237,12 @@ int noinstr scs_patch(const u8 eh_frame[], int size) ...@@ -235,9 +237,12 @@ int noinstr scs_patch(const u8 eh_frame[], int size)
} else { } else {
ret = scs_handle_fde_frame(frame, ret = scs_handle_fde_frame(frame,
fde_has_augmentation_data, fde_has_augmentation_data,
code_alignment_factor); code_alignment_factor,
true);
if (ret) if (ret)
return ret; return ret;
scs_handle_fde_frame(frame, fde_has_augmentation_data,
code_alignment_factor, false);
} }
p += sizeof(frame->size) + frame->size; p += sizeof(frame->size) + frame->size;
......
...@@ -88,6 +88,23 @@ int __kprobes aarch64_insn_write(void *addr, u32 insn) ...@@ -88,6 +88,23 @@ int __kprobes aarch64_insn_write(void *addr, u32 insn)
return __aarch64_insn_write(addr, cpu_to_le32(insn)); return __aarch64_insn_write(addr, cpu_to_le32(insn));
} }
noinstr int aarch64_insn_write_literal_u64(void *addr, u64 val)
{
u64 *waddr;
unsigned long flags;
int ret;
raw_spin_lock_irqsave(&patch_lock, flags);
waddr = patch_map(addr, FIX_TEXT_POKE0);
ret = copy_to_kernel_nofault(waddr, &val, sizeof(val));
patch_unmap(FIX_TEXT_POKE0);
raw_spin_unlock_irqrestore(&patch_lock, flags);
return ret;
}
int __kprobes aarch64_insn_patch_text_nosync(void *addr, u32 insn) int __kprobes aarch64_insn_patch_text_nosync(void *addr, u32 insn)
{ {
u32 *tp = addr; u32 *tp = addr;
......
...@@ -387,10 +387,6 @@ int __init arch_populate_kprobe_blacklist(void) ...@@ -387,10 +387,6 @@ int __init arch_populate_kprobe_blacklist(void)
(unsigned long)__irqentry_text_end); (unsigned long)__irqentry_text_end);
if (ret) if (ret)
return ret; return ret;
ret = kprobe_add_area_blacklist((unsigned long)__idmap_text_start,
(unsigned long)__idmap_text_end);
if (ret)
return ret;
ret = kprobe_add_area_blacklist((unsigned long)__hyp_text_start, ret = kprobe_add_area_blacklist((unsigned long)__hyp_text_start,
(unsigned long)__hyp_text_end); (unsigned long)__hyp_text_end);
if (ret || is_kernel_in_hyp_mode()) if (ret || is_kernel_in_hyp_mode())
......
...@@ -307,27 +307,28 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) ...@@ -307,27 +307,28 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
/* /*
* In the unlikely event that we create a new thread with ZA * In the unlikely event that we create a new thread with ZA
* enabled we should retain the ZA state so duplicate it here. * enabled we should retain the ZA and ZT state so duplicate
* This may be shortly freed if we exec() or if CLONE_SETTLS * it here. This may be shortly freed if we exec() or if
* but it's simpler to do it here. To avoid confusing the rest * CLONE_SETTLS but it's simpler to do it here. To avoid
* of the code ensure that we have a sve_state allocated * confusing the rest of the code ensure that we have a
* whenever za_state is allocated. * sve_state allocated whenever sme_state is allocated.
*/ */
if (thread_za_enabled(&src->thread)) { if (thread_za_enabled(&src->thread)) {
dst->thread.sve_state = kzalloc(sve_state_size(src), dst->thread.sve_state = kzalloc(sve_state_size(src),
GFP_KERNEL); GFP_KERNEL);
if (!dst->thread.sve_state) if (!dst->thread.sve_state)
return -ENOMEM; return -ENOMEM;
dst->thread.za_state = kmemdup(src->thread.za_state,
za_state_size(src), dst->thread.sme_state = kmemdup(src->thread.sme_state,
GFP_KERNEL); sme_state_size(src),
if (!dst->thread.za_state) { GFP_KERNEL);
if (!dst->thread.sme_state) {
kfree(dst->thread.sve_state); kfree(dst->thread.sve_state);
dst->thread.sve_state = NULL; dst->thread.sve_state = NULL;
return -ENOMEM; return -ENOMEM;
} }
} else { } else {
dst->thread.za_state = NULL; dst->thread.sme_state = NULL;
clear_tsk_thread_flag(dst, TIF_SME); clear_tsk_thread_flag(dst, TIF_SME);
} }
......
...@@ -683,7 +683,7 @@ static int tls_set(struct task_struct *target, const struct user_regset *regset, ...@@ -683,7 +683,7 @@ static int tls_set(struct task_struct *target, const struct user_regset *regset,
unsigned long tls[2]; unsigned long tls[2];
tls[0] = target->thread.uw.tp_value; tls[0] = target->thread.uw.tp_value;
if (system_supports_sme()) if (system_supports_tpidr2())
tls[1] = target->thread.tpidr2_el0; tls[1] = target->thread.tpidr2_el0;
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, tls, 0, count); ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, tls, 0, count);
...@@ -691,7 +691,7 @@ static int tls_set(struct task_struct *target, const struct user_regset *regset, ...@@ -691,7 +691,7 @@ static int tls_set(struct task_struct *target, const struct user_regset *regset,
return ret; return ret;
target->thread.uw.tp_value = tls[0]; target->thread.uw.tp_value = tls[0];
if (system_supports_sme()) if (system_supports_tpidr2())
target->thread.tpidr2_el0 = tls[1]; target->thread.tpidr2_el0 = tls[1];
return ret; return ret;
...@@ -1045,7 +1045,7 @@ static int za_get(struct task_struct *target, ...@@ -1045,7 +1045,7 @@ static int za_get(struct task_struct *target,
if (thread_za_enabled(&target->thread)) { if (thread_za_enabled(&target->thread)) {
start = end; start = end;
end = ZA_PT_SIZE(vq); end = ZA_PT_SIZE(vq);
membuf_write(&to, target->thread.za_state, end - start); membuf_write(&to, target->thread.sme_state, end - start);
} }
/* Zero any trailing padding */ /* Zero any trailing padding */
...@@ -1099,7 +1099,7 @@ static int za_set(struct task_struct *target, ...@@ -1099,7 +1099,7 @@ static int za_set(struct task_struct *target,
/* Allocate/reinit ZA storage */ /* Allocate/reinit ZA storage */
sme_alloc(target); sme_alloc(target);
if (!target->thread.za_state) { if (!target->thread.sme_state) {
ret = -ENOMEM; ret = -ENOMEM;
goto out; goto out;
} }
...@@ -1124,7 +1124,7 @@ static int za_set(struct task_struct *target, ...@@ -1124,7 +1124,7 @@ static int za_set(struct task_struct *target,
start = ZA_PT_ZA_OFFSET; start = ZA_PT_ZA_OFFSET;
end = ZA_PT_SIZE(vq); end = ZA_PT_SIZE(vq);
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
target->thread.za_state, target->thread.sme_state,
start, end); start, end);
if (ret) if (ret)
goto out; goto out;
...@@ -1138,6 +1138,51 @@ static int za_set(struct task_struct *target, ...@@ -1138,6 +1138,51 @@ static int za_set(struct task_struct *target,
return ret; return ret;
} }
static int zt_get(struct task_struct *target,
const struct user_regset *regset,
struct membuf to)
{
if (!system_supports_sme2())
return -EINVAL;
/*
* If PSTATE.ZA is not set then ZT will be zeroed when it is
* enabled so report the current register value as zero.
*/
if (thread_za_enabled(&target->thread))
membuf_write(&to, thread_zt_state(&target->thread),
ZT_SIG_REG_BYTES);
else
membuf_zero(&to, ZT_SIG_REG_BYTES);
return 0;
}
static int zt_set(struct task_struct *target,
const struct user_regset *regset,
unsigned int pos, unsigned int count,
const void *kbuf, const void __user *ubuf)
{
int ret;
if (!system_supports_sme2())
return -EINVAL;
if (!thread_za_enabled(&target->thread)) {
sme_alloc(target);
if (!target->thread.sme_state)
return -ENOMEM;
}
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
thread_zt_state(&target->thread),
0, ZT_SIG_REG_BYTES);
if (ret == 0)
target->thread.svcr |= SVCR_ZA_MASK;
return ret;
}
#endif /* CONFIG_ARM64_SME */ #endif /* CONFIG_ARM64_SME */
#ifdef CONFIG_ARM64_PTR_AUTH #ifdef CONFIG_ARM64_PTR_AUTH
...@@ -1360,6 +1405,7 @@ enum aarch64_regset { ...@@ -1360,6 +1405,7 @@ enum aarch64_regset {
#ifdef CONFIG_ARM64_SME #ifdef CONFIG_ARM64_SME
REGSET_SSVE, REGSET_SSVE,
REGSET_ZA, REGSET_ZA,
REGSET_ZT,
#endif #endif
#ifdef CONFIG_ARM64_PTR_AUTH #ifdef CONFIG_ARM64_PTR_AUTH
REGSET_PAC_MASK, REGSET_PAC_MASK,
...@@ -1467,6 +1513,14 @@ static const struct user_regset aarch64_regsets[] = { ...@@ -1467,6 +1513,14 @@ static const struct user_regset aarch64_regsets[] = {
.regset_get = za_get, .regset_get = za_get,
.set = za_set, .set = za_set,
}, },
[REGSET_ZT] = { /* SME ZT */
.core_note_type = NT_ARM_ZT,
.n = 1,
.size = ZT_SIG_REG_BYTES,
.align = sizeof(u64),
.regset_get = zt_get,
.set = zt_set,
},
#endif #endif
#ifdef CONFIG_ARM64_PTR_AUTH #ifdef CONFIG_ARM64_PTR_AUTH
[REGSET_PAC_MASK] = { [REGSET_PAC_MASK] = {
......
...@@ -58,6 +58,7 @@ static int num_standard_resources; ...@@ -58,6 +58,7 @@ static int num_standard_resources;
static struct resource *standard_resources; static struct resource *standard_resources;
phys_addr_t __fdt_pointer __initdata; phys_addr_t __fdt_pointer __initdata;
u64 mmu_enabled_at_boot __initdata;
/* /*
* Standard memory resources * Standard memory resources
...@@ -332,8 +333,12 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p) ...@@ -332,8 +333,12 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p)
xen_early_init(); xen_early_init();
efi_init(); efi_init();
if (!efi_enabled(EFI_BOOT) && ((u64)_text % MIN_KIMG_ALIGN) != 0) if (!efi_enabled(EFI_BOOT)) {
pr_warn(FW_BUG "Kernel image misaligned at boot, please fix your bootloader!"); if ((u64)_text % MIN_KIMG_ALIGN)
pr_warn(FW_BUG "Kernel image misaligned at boot, please fix your bootloader!");
WARN_TAINT(mmu_enabled_at_boot, TAINT_FIRMWARE_WORKAROUND,
FW_BUG "Booted with MMU enabled!");
}
arm64_memblock_init(); arm64_memblock_init();
...@@ -442,3 +447,11 @@ static int __init register_arm64_panic_block(void) ...@@ -442,3 +447,11 @@ static int __init register_arm64_panic_block(void)
return 0; return 0;
} }
device_initcall(register_arm64_panic_block); device_initcall(register_arm64_panic_block);
static int __init check_mmu_enabled_at_boot(void)
{
if (!efi_enabled(EFI_BOOT) && mmu_enabled_at_boot)
panic("Non-EFI boot detected with MMU and caches enabled");
return 0;
}
device_initcall_sync(check_mmu_enabled_at_boot);
This diff is collapsed.
...@@ -99,8 +99,9 @@ SYM_FUNC_END(__cpu_suspend_enter) ...@@ -99,8 +99,9 @@ SYM_FUNC_END(__cpu_suspend_enter)
.pushsection ".idmap.text", "awx" .pushsection ".idmap.text", "awx"
SYM_CODE_START(cpu_resume) SYM_CODE_START(cpu_resume)
mov x0, xzr
bl init_kernel_el bl init_kernel_el
bl finalise_el2 mov x19, x0 // preserve boot mode
#if VA_BITS > 48 #if VA_BITS > 48
ldr_l x0, vabits_actual ldr_l x0, vabits_actual
#endif #endif
...@@ -116,6 +117,9 @@ SYM_CODE_END(cpu_resume) ...@@ -116,6 +117,9 @@ SYM_CODE_END(cpu_resume)
.popsection .popsection
SYM_FUNC_START(_cpu_resume) SYM_FUNC_START(_cpu_resume)
mov x0, x19
bl finalise_el2
mrs x1, mpidr_el1 mrs x1, mpidr_el1
adr_l x8, mpidr_hash // x8 = struct mpidr_hash virt address adr_l x8, mpidr_hash // x8 = struct mpidr_hash virt address
......
...@@ -173,12 +173,8 @@ static inline void fp_user_discard(void) ...@@ -173,12 +173,8 @@ static inline void fp_user_discard(void)
* register state to track, if this changes the KVM code will * register state to track, if this changes the KVM code will
* need updating. * need updating.
*/ */
if (system_supports_sme() && test_thread_flag(TIF_SME)) { if (system_supports_sme())
u64 svcr = read_sysreg_s(SYS_SVCR); sme_smstop_sm();
if (svcr & SVCR_SM_MASK)
sme_smstop_sm();
}
if (!system_supports_sve()) if (!system_supports_sve())
return; return;
......
...@@ -163,10 +163,8 @@ static void dump_kernel_instr(const char *lvl, struct pt_regs *regs) ...@@ -163,10 +163,8 @@ static void dump_kernel_instr(const char *lvl, struct pt_regs *regs)
if (!bad) if (!bad)
p += sprintf(p, i == 0 ? "(%08x) " : "%08x ", val); p += sprintf(p, i == 0 ? "(%08x) " : "%08x ", val);
else { else
p += sprintf(p, "bad PC value"); p += sprintf(p, i == 0 ? "(????????) " : "???????? ");
break;
}
} }
printk("%sCode: %s\n", lvl, str); printk("%sCode: %s\n", lvl, str);
......
...@@ -93,6 +93,7 @@ jiffies = jiffies_64; ...@@ -93,6 +93,7 @@ jiffies = jiffies_64;
#ifdef CONFIG_HIBERNATION #ifdef CONFIG_HIBERNATION
#define HIBERNATE_TEXT \ #define HIBERNATE_TEXT \
ALIGN_FUNCTION(); \
__hibernate_exit_text_start = .; \ __hibernate_exit_text_start = .; \
*(.hibernate_exit.text) \ *(.hibernate_exit.text) \
__hibernate_exit_text_end = .; __hibernate_exit_text_end = .;
...@@ -102,6 +103,7 @@ jiffies = jiffies_64; ...@@ -102,6 +103,7 @@ jiffies = jiffies_64;
#ifdef CONFIG_KEXEC_CORE #ifdef CONFIG_KEXEC_CORE
#define KEXEC_TEXT \ #define KEXEC_TEXT \
ALIGN_FUNCTION(); \
__relocate_new_kernel_start = .; \ __relocate_new_kernel_start = .; \
*(.kexec_relocate.text) \ *(.kexec_relocate.text) \
__relocate_new_kernel_end = .; __relocate_new_kernel_end = .;
...@@ -178,7 +180,6 @@ SECTIONS ...@@ -178,7 +180,6 @@ SECTIONS
LOCK_TEXT LOCK_TEXT
KPROBES_TEXT KPROBES_TEXT
HYPERVISOR_TEXT HYPERVISOR_TEXT
IDMAP_TEXT
*(.gnu.warning) *(.gnu.warning)
. = ALIGN(16); . = ALIGN(16);
*(.got) /* Global offset table */ *(.got) /* Global offset table */
...@@ -205,6 +206,7 @@ SECTIONS ...@@ -205,6 +206,7 @@ SECTIONS
TRAMP_TEXT TRAMP_TEXT
HIBERNATE_TEXT HIBERNATE_TEXT
KEXEC_TEXT KEXEC_TEXT
IDMAP_TEXT
. = ALIGN(PAGE_SIZE); . = ALIGN(PAGE_SIZE);
} }
...@@ -354,6 +356,8 @@ ASSERT(__idmap_text_end - (__idmap_text_start & ~(SZ_4K - 1)) <= SZ_4K, ...@@ -354,6 +356,8 @@ ASSERT(__idmap_text_end - (__idmap_text_start & ~(SZ_4K - 1)) <= SZ_4K,
#ifdef CONFIG_HIBERNATION #ifdef CONFIG_HIBERNATION
ASSERT(__hibernate_exit_text_end - __hibernate_exit_text_start <= SZ_4K, ASSERT(__hibernate_exit_text_end - __hibernate_exit_text_start <= SZ_4K,
"Hibernate exit text is bigger than 4 KiB") "Hibernate exit text is bigger than 4 KiB")
ASSERT(__hibernate_exit_text_start == swsusp_arch_suspend_exit,
"Hibernate exit text does not start with swsusp_arch_suspend_exit")
#endif #endif
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) <= 3*PAGE_SIZE, ASSERT((__entry_tramp_text_end - __entry_tramp_text_start) <= 3*PAGE_SIZE,
...@@ -380,4 +384,6 @@ ASSERT(swapper_pg_dir - tramp_pg_dir == TRAMP_SWAPPER_OFFSET, ...@@ -380,4 +384,6 @@ ASSERT(swapper_pg_dir - tramp_pg_dir == TRAMP_SWAPPER_OFFSET,
ASSERT(__relocate_new_kernel_end - __relocate_new_kernel_start <= SZ_4K, ASSERT(__relocate_new_kernel_end - __relocate_new_kernel_start <= SZ_4K,
"kexec relocation code is bigger than 4 KiB") "kexec relocation code is bigger than 4 KiB")
ASSERT(KEXEC_CONTROL_PAGE_SIZE >= SZ_4K, "KEXEC_CONTROL_PAGE_SIZE is broken") ASSERT(KEXEC_CONTROL_PAGE_SIZE >= SZ_4K, "KEXEC_CONTROL_PAGE_SIZE is broken")
ASSERT(__relocate_new_kernel_start == arm64_relocate_new_kernel,
"kexec control page does not start with arm64_relocate_new_kernel")
#endif #endif
...@@ -328,7 +328,7 @@ void kvm_arch_vcpu_load_debug_state_flags(struct kvm_vcpu *vcpu) ...@@ -328,7 +328,7 @@ void kvm_arch_vcpu_load_debug_state_flags(struct kvm_vcpu *vcpu)
* we may need to check if the host state needs to be saved. * we may need to check if the host state needs to be saved.
*/ */
if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_PMSVer_SHIFT) && if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_PMSVer_SHIFT) &&
!(read_sysreg_s(SYS_PMBIDR_EL1) & BIT(SYS_PMBIDR_EL1_P_SHIFT))) !(read_sysreg_s(SYS_PMBIDR_EL1) & BIT(PMBIDR_EL1_P_SHIFT)))
vcpu_set_flag(vcpu, DEBUG_STATE_SAVE_SPE); vcpu_set_flag(vcpu, DEBUG_STATE_SAVE_SPE);
/* Check if we have TRBE implemented and available at the host */ /* Check if we have TRBE implemented and available at the host */
......
...@@ -143,7 +143,7 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu) ...@@ -143,7 +143,7 @@ void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
fp_state.st = &vcpu->arch.ctxt.fp_regs; fp_state.st = &vcpu->arch.ctxt.fp_regs;
fp_state.sve_state = vcpu->arch.sve_state; fp_state.sve_state = vcpu->arch.sve_state;
fp_state.sve_vl = vcpu->arch.sve_max_vl; fp_state.sve_vl = vcpu->arch.sve_max_vl;
fp_state.za_state = NULL; fp_state.sme_state = NULL;
fp_state.svcr = &vcpu->arch.svcr; fp_state.svcr = &vcpu->arch.svcr;
fp_state.fp_type = &vcpu->arch.fp_type; fp_state.fp_type = &vcpu->arch.fp_type;
......
...@@ -171,7 +171,7 @@ alternative_else ...@@ -171,7 +171,7 @@ alternative_else
dsb sy // Synchronize against in-flight ld/st dsb sy // Synchronize against in-flight ld/st
isb // Prevent an early read of side-effect free ISR isb // Prevent an early read of side-effect free ISR
mrs x2, isr_el1 mrs x2, isr_el1
tbnz x2, #8, 2f // ISR_EL1.A tbnz x2, #ISR_EL1_A_SHIFT, 2f
ret ret
nop nop
2: 2:
......
...@@ -27,7 +27,7 @@ static void __debug_save_spe(u64 *pmscr_el1) ...@@ -27,7 +27,7 @@ static void __debug_save_spe(u64 *pmscr_el1)
* Check if the host is actually using it ? * Check if the host is actually using it ?
*/ */
reg = read_sysreg_s(SYS_PMBLIMITR_EL1); reg = read_sysreg_s(SYS_PMBLIMITR_EL1);
if (!(reg & BIT(SYS_PMBLIMITR_EL1_E_SHIFT))) if (!(reg & BIT(PMBLIMITR_EL1_E_SHIFT)))
return; return;
/* Yes; save the control register and disable data generation */ /* Yes; save the control register and disable data generation */
......
...@@ -56,6 +56,7 @@ SYM_FUNC_START(caches_clean_inval_pou) ...@@ -56,6 +56,7 @@ SYM_FUNC_START(caches_clean_inval_pou)
caches_clean_inval_pou_macro caches_clean_inval_pou_macro
ret ret
SYM_FUNC_END(caches_clean_inval_pou) SYM_FUNC_END(caches_clean_inval_pou)
SYM_FUNC_ALIAS(__pi_caches_clean_inval_pou, caches_clean_inval_pou)
/* /*
* caches_clean_inval_user_pou(start,end) * caches_clean_inval_user_pou(start,end)
......
...@@ -133,7 +133,7 @@ static phys_addr_t __init early_pgtable_alloc(int shift) ...@@ -133,7 +133,7 @@ static phys_addr_t __init early_pgtable_alloc(int shift)
return phys; return phys;
} }
static bool pgattr_change_is_safe(u64 old, u64 new) bool pgattr_change_is_safe(u64 old, u64 new)
{ {
/* /*
* The following mapping attributes may be updated in live * The following mapping attributes may be updated in live
...@@ -142,9 +142,13 @@ static bool pgattr_change_is_safe(u64 old, u64 new) ...@@ -142,9 +142,13 @@ static bool pgattr_change_is_safe(u64 old, u64 new)
pteval_t mask = PTE_PXN | PTE_RDONLY | PTE_WRITE | PTE_NG; pteval_t mask = PTE_PXN | PTE_RDONLY | PTE_WRITE | PTE_NG;
/* creating or taking down mappings is always safe */ /* creating or taking down mappings is always safe */
if (old == 0 || new == 0) if (!pte_valid(__pte(old)) || !pte_valid(__pte(new)))
return true; return true;
/* A live entry's pfn should not change */
if (pte_pfn(__pte(old)) != pte_pfn(__pte(new)))
return false;
/* live contiguous mappings may not be manipulated at all */ /* live contiguous mappings may not be manipulated at all */
if ((old | new) & PTE_CONT) if ((old | new) & PTE_CONT)
return false; return false;
......
...@@ -110,7 +110,6 @@ SYM_FUNC_END(cpu_do_suspend) ...@@ -110,7 +110,6 @@ SYM_FUNC_END(cpu_do_suspend)
* *
* x0: Address of context pointer * x0: Address of context pointer
*/ */
.pushsection ".idmap.text", "awx"
SYM_FUNC_START(cpu_do_resume) SYM_FUNC_START(cpu_do_resume)
ldp x2, x3, [x0] ldp x2, x3, [x0]
ldp x4, x5, [x0, #16] ldp x4, x5, [x0, #16]
...@@ -166,7 +165,6 @@ alternative_else_nop_endif ...@@ -166,7 +165,6 @@ alternative_else_nop_endif
isb isb
ret ret
SYM_FUNC_END(cpu_do_resume) SYM_FUNC_END(cpu_do_resume)
.popsection
#endif #endif
.pushsection ".idmap.text", "awx" .pushsection ".idmap.text", "awx"
......
...@@ -28,7 +28,9 @@ HAS_GENERIC_AUTH ...@@ -28,7 +28,9 @@ HAS_GENERIC_AUTH
HAS_GENERIC_AUTH_ARCH_QARMA3 HAS_GENERIC_AUTH_ARCH_QARMA3
HAS_GENERIC_AUTH_ARCH_QARMA5 HAS_GENERIC_AUTH_ARCH_QARMA5
HAS_GENERIC_AUTH_IMP_DEF HAS_GENERIC_AUTH_IMP_DEF
HAS_IRQ_PRIO_MASKING HAS_GIC_CPUIF_SYSREGS
HAS_GIC_PRIO_MASKING
HAS_GIC_PRIO_RELAXED_SYNC
HAS_LDAPR HAS_LDAPR
HAS_LSE_ATOMICS HAS_LSE_ATOMICS
HAS_NO_FPSIMD HAS_NO_FPSIMD
...@@ -38,7 +40,6 @@ HAS_RAS_EXTN ...@@ -38,7 +40,6 @@ HAS_RAS_EXTN
HAS_RNG HAS_RNG
HAS_SB HAS_SB
HAS_STAGE2_FWB HAS_STAGE2_FWB
HAS_SYSREG_GIC_CPUIF
HAS_TIDCP1 HAS_TIDCP1
HAS_TLB_RANGE HAS_TLB_RANGE
HAS_VIRT_HOST_EXTN HAS_VIRT_HOST_EXTN
...@@ -50,6 +51,7 @@ MTE ...@@ -50,6 +51,7 @@ MTE
MTE_ASYMM MTE_ASYMM
SME SME
SME_FA64 SME_FA64
SME2
SPECTRE_V2 SPECTRE_V2
SPECTRE_V3A SPECTRE_V3A
SPECTRE_V4 SPECTRE_V4
......
...@@ -44,6 +44,11 @@ function define_field(reg, field, msb, lsb) { ...@@ -44,6 +44,11 @@ function define_field(reg, field, msb, lsb) {
define(reg "_" field "_WIDTH", msb - lsb + 1) define(reg "_" field "_WIDTH", msb - lsb + 1)
} }
# Print a field _SIGNED definition for a field
function define_field_sign(reg, field, sign) {
define(reg "_" field "_SIGNED", sign)
}
# Parse a "<msb>[:<lsb>]" string into the global variables @msb and @lsb # Parse a "<msb>[:<lsb>]" string into the global variables @msb and @lsb
function parse_bitdef(reg, field, bitdef, _bits) function parse_bitdef(reg, field, bitdef, _bits)
{ {
...@@ -233,6 +238,30 @@ END { ...@@ -233,6 +238,30 @@ END {
next next
} }
/^SignedEnum/ {
change_block("Enum<", "Sysreg", "Enum")
expect_fields(3)
field = $3
parse_bitdef(reg, field, $2)
define_field(reg, field, msb, lsb)
define_field_sign(reg, field, "true")
next
}
/^UnsignedEnum/ {
change_block("Enum<", "Sysreg", "Enum")
expect_fields(3)
field = $3
parse_bitdef(reg, field, $2)
define_field(reg, field, msb, lsb)
define_field_sign(reg, field, "false")
next
}
/^Enum/ { /^Enum/ {
change_block("Enum", "Sysreg", "Enum") change_block("Enum", "Sysreg", "Enum")
expect_fields(3) expect_fields(3)
......
This diff is collapsed.
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
# Makefile for ACPICA Core interpreter # Makefile for ACPICA Core interpreter
# #
ccflags-y := -Os -D_LINUX -DBUILDING_ACPICA ccflags-y := -D_LINUX -DBUILDING_ACPICA
ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT
# use acpi.o to put all files here into acpi.o modparam namespace # use acpi.o to put all files here into acpi.o modparam namespace
......
...@@ -87,7 +87,7 @@ lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o \ ...@@ -87,7 +87,7 @@ lib-$(CONFIG_EFI_GENERIC_STUB) += efi-stub.o string.o intrinsics.o systable.o \
screen_info.o efi-stub-entry.o screen_info.o efi-stub-entry.o
lib-$(CONFIG_ARM) += arm32-stub.o lib-$(CONFIG_ARM) += arm32-stub.o
lib-$(CONFIG_ARM64) += arm64.o arm64-stub.o arm64-entry.o smbios.o lib-$(CONFIG_ARM64) += arm64.o arm64-stub.o smbios.o
lib-$(CONFIG_X86) += x86-stub.o lib-$(CONFIG_X86) += x86-stub.o
lib-$(CONFIG_RISCV) += riscv.o riscv-stub.o lib-$(CONFIG_RISCV) += riscv.o riscv-stub.o
lib-$(CONFIG_LOONGARCH) += loongarch.o loongarch-stub.o lib-$(CONFIG_LOONGARCH) += loongarch.o loongarch-stub.o
...@@ -141,7 +141,7 @@ STUBCOPY_RELOC-$(CONFIG_ARM) := R_ARM_ABS ...@@ -141,7 +141,7 @@ STUBCOPY_RELOC-$(CONFIG_ARM) := R_ARM_ABS
# #
STUBCOPY_FLAGS-$(CONFIG_ARM64) += --prefix-alloc-sections=.init \ STUBCOPY_FLAGS-$(CONFIG_ARM64) += --prefix-alloc-sections=.init \
--prefix-symbols=__efistub_ --prefix-symbols=__efistub_
STUBCOPY_RELOC-$(CONFIG_ARM64) := R_AARCH64_ABS64 STUBCOPY_RELOC-$(CONFIG_ARM64) := R_AARCH64_ABS
# For RISC-V, we don't need anything special other than arm64. Keep all the # For RISC-V, we don't need anything special other than arm64. Keep all the
# symbols in .init section and make sure that no absolute symbols references # symbols in .init section and make sure that no absolute symbols references
......
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* EFI entry point.
*
* Copyright (C) 2013, 2014 Red Hat, Inc.
* Author: Mark Salter <msalter@redhat.com>
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
/*
* The entrypoint of a arm64 bare metal image is at offset #0 of the
* image, so this is a reasonable default for primary_entry_offset.
* Only when the EFI stub is integrated into the core kernel, it is not
* guaranteed that the PE/COFF header has been copied to memory too, so
* in this case, primary_entry_offset should be overridden by the
* linker and point to primary_entry() directly.
*/
.weak primary_entry_offset
SYM_CODE_START(efi_enter_kernel)
/*
* efi_pe_entry() will have copied the kernel image if necessary and we
* end up here with device tree address in x1 and the kernel entry
* point stored in x0. Save those values in registers which are
* callee preserved.
*/
ldr w2, =primary_entry_offset
add x19, x0, x2 // relocated Image entrypoint
mov x0, x1 // DTB address
mov x1, xzr
mov x2, xzr
mov x3, xzr
/*
* Clean the remainder of this routine to the PoC
* so that we can safely disable the MMU and caches.
*/
adr x4, 1f
dc civac, x4
dsb sy
/* Turn off Dcache and MMU */
mrs x4, CurrentEL
cmp x4, #CurrentEL_EL2
mrs x4, sctlr_el1
b.ne 0f
mrs x4, sctlr_el2
0: bic x4, x4, #SCTLR_ELx_M
bic x4, x4, #SCTLR_ELx_C
b.eq 1f
b 2f
.balign 32
1: pre_disable_mmu_workaround
msr sctlr_el2, x4
isb
br x19 // jump to kernel entrypoint
2: pre_disable_mmu_workaround
msr sctlr_el1, x4
isb
br x19 // jump to kernel entrypoint
.org 1b + 32
SYM_CODE_END(efi_enter_kernel)
...@@ -58,7 +58,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, ...@@ -58,7 +58,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
efi_handle_t image_handle) efi_handle_t image_handle)
{ {
efi_status_t status; efi_status_t status;
unsigned long kernel_size, kernel_memsize = 0; unsigned long kernel_size, kernel_codesize, kernel_memsize;
u32 phys_seed = 0; u32 phys_seed = 0;
u64 min_kimg_align = efi_get_kimg_min_align(); u64 min_kimg_align = efi_get_kimg_min_align();
...@@ -93,6 +93,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, ...@@ -93,6 +93,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
SEGMENT_ALIGN >> 10); SEGMENT_ALIGN >> 10);
kernel_size = _edata - _text; kernel_size = _edata - _text;
kernel_codesize = __inittext_end - _text;
kernel_memsize = kernel_size + (_end - _edata); kernel_memsize = kernel_size + (_end - _edata);
*reserve_size = kernel_memsize; *reserve_size = kernel_memsize;
...@@ -121,7 +122,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, ...@@ -121,7 +122,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
*/ */
*image_addr = (u64)_text; *image_addr = (u64)_text;
*reserve_size = 0; *reserve_size = 0;
goto clean_image_to_poc; return EFI_SUCCESS;
} }
status = efi_allocate_pages_aligned(*reserve_size, reserve_addr, status = efi_allocate_pages_aligned(*reserve_size, reserve_addr,
...@@ -137,14 +138,21 @@ efi_status_t handle_kernel_image(unsigned long *image_addr, ...@@ -137,14 +138,21 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
*image_addr = *reserve_addr; *image_addr = *reserve_addr;
memcpy((void *)*image_addr, _text, kernel_size); memcpy((void *)*image_addr, _text, kernel_size);
caches_clean_inval_pou(*image_addr, *image_addr + kernel_codesize);
clean_image_to_poc: return EFI_SUCCESS;
}
asmlinkage void primary_entry(void);
unsigned long primary_entry_offset(void)
{
/* /*
* Clean the copied Image to the PoC, and ensure it is not shadowed by * When built as part of the kernel, the EFI stub cannot branch to the
* stale icache entries from before relocation. * kernel proper via the image header, as the PE/COFF header is
* strictly not part of the in-memory presentation of the image, only
* of the file representation. So instead, we need to jump to the
* actual entrypoint in the .text region of the image.
*/ */
dcache_clean_poc(*image_addr, *image_addr + kernel_size); return (char *)primary_entry - _text;
asm("ic ialluis");
return EFI_SUCCESS;
} }
...@@ -59,6 +59,12 @@ efi_status_t check_platform_features(void) ...@@ -59,6 +59,12 @@ efi_status_t check_platform_features(void)
return EFI_SUCCESS; return EFI_SUCCESS;
} }
#ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE
#define DCTYPE "civac"
#else
#define DCTYPE "cvau"
#endif
void efi_cache_sync_image(unsigned long image_base, void efi_cache_sync_image(unsigned long image_base,
unsigned long alloc_size, unsigned long alloc_size,
unsigned long code_size) unsigned long code_size)
...@@ -67,13 +73,38 @@ void efi_cache_sync_image(unsigned long image_base, ...@@ -67,13 +73,38 @@ void efi_cache_sync_image(unsigned long image_base,
u64 lsize = 4 << cpuid_feature_extract_unsigned_field(ctr, u64 lsize = 4 << cpuid_feature_extract_unsigned_field(ctr,
CTR_EL0_DminLine_SHIFT); CTR_EL0_DminLine_SHIFT);
do { /* only perform the cache maintenance if needed for I/D coherency */
asm("dc civac, %0" :: "r"(image_base)); if (!(ctr & BIT(CTR_EL0_IDC_SHIFT))) {
image_base += lsize; do {
alloc_size -= lsize; asm("dc " DCTYPE ", %0" :: "r"(image_base));
} while (alloc_size >= lsize); image_base += lsize;
code_size -= lsize;
} while (code_size >= lsize);
}
asm("ic ialluis"); asm("ic ialluis");
dsb(ish); dsb(ish);
isb(); isb();
} }
unsigned long __weak primary_entry_offset(void)
{
/*
* By default, we can invoke the kernel via the branch instruction in
* the image header, so offset #0. This will be overridden by the EFI
* stub build that is linked into the core kernel, as in that case, the
* image header may not have been loaded into memory, or may be mapped
* with non-executable permissions.
*/
return 0;
}
void __noreturn efi_enter_kernel(unsigned long entrypoint,
unsigned long fdt_addr,
unsigned long fdt_size)
{
void (* __noreturn enter_kernel)(u64, u64, u64, u64);
enter_kernel = (void *)entrypoint + primary_entry_offset();
enter_kernel(fdt_addr, 0, 0, 0);
}
...@@ -89,15 +89,6 @@ static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key); ...@@ -89,15 +89,6 @@ static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);
*/ */
static DEFINE_STATIC_KEY_FALSE(supports_pseudo_nmis); static DEFINE_STATIC_KEY_FALSE(supports_pseudo_nmis);
/*
* Global static key controlling whether an update to PMR allowing more
* interrupts requires to be propagated to the redistributor (DSB SY).
* And this needs to be exported for modules to be able to enable
* interrupts...
*/
DEFINE_STATIC_KEY_FALSE(gic_pmr_sync);
EXPORT_SYMBOL(gic_pmr_sync);
DEFINE_STATIC_KEY_FALSE(gic_nonsecure_priorities); DEFINE_STATIC_KEY_FALSE(gic_nonsecure_priorities);
EXPORT_SYMBOL(gic_nonsecure_priorities); EXPORT_SYMBOL(gic_nonsecure_priorities);
...@@ -1766,16 +1757,8 @@ static void gic_enable_nmi_support(void) ...@@ -1766,16 +1757,8 @@ static void gic_enable_nmi_support(void)
for (i = 0; i < gic_data.ppi_nr; i++) for (i = 0; i < gic_data.ppi_nr; i++)
refcount_set(&ppi_nmi_refs[i], 0); refcount_set(&ppi_nmi_refs[i], 0);
/*
* Linux itself doesn't use 1:N distribution, so has no need to
* set PMHE. The only reason to have it set is if EL3 requires it
* (and we can't change it).
*/
if (gic_read_ctlr() & ICC_CTLR_EL1_PMHE_MASK)
static_branch_enable(&gic_pmr_sync);
pr_info("Pseudo-NMIs enabled using %s ICC_PMR_EL1 synchronisation\n", pr_info("Pseudo-NMIs enabled using %s ICC_PMR_EL1 synchronisation\n",
static_branch_unlikely(&gic_pmr_sync) ? "forced" : "relaxed"); gic_has_relaxed_pmr_sync() ? "relaxed" : "forced");
/* /*
* How priority values are used by the GIC depends on two things: * How priority values are used by the GIC depends on two things:
......
...@@ -54,7 +54,7 @@ ...@@ -54,7 +54,7 @@
static void gic_check_cpu_features(void) static void gic_check_cpu_features(void)
{ {
WARN_TAINT_ONCE(this_cpu_has_cap(ARM64_HAS_SYSREG_GIC_CPUIF), WARN_TAINT_ONCE(this_cpu_has_cap(ARM64_HAS_GIC_CPUIF_SYSREGS),
TAINT_CPU_OUT_OF_SPEC, TAINT_CPU_OUT_OF_SPEC,
"GICv3 system registers enabled, broken firmware!\n"); "GICv3 system registers enabled, broken firmware!\n");
} }
......
...@@ -1870,6 +1870,7 @@ static void arm_cmn_init_dtm(struct arm_cmn_dtm *dtm, struct arm_cmn_node *xp, i ...@@ -1870,6 +1870,7 @@ static void arm_cmn_init_dtm(struct arm_cmn_dtm *dtm, struct arm_cmn_node *xp, i
dtm->base = xp->pmu_base + CMN_DTM_OFFSET(idx); dtm->base = xp->pmu_base + CMN_DTM_OFFSET(idx);
dtm->pmu_config_low = CMN_DTM_PMU_CONFIG_PMU_EN; dtm->pmu_config_low = CMN_DTM_PMU_CONFIG_PMU_EN;
writeq_relaxed(dtm->pmu_config_low, dtm->base + CMN_DTM_PMU_CONFIG);
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
dtm->wp_event[i] = -1; dtm->wp_event[i] = -1;
writeq_relaxed(0, dtm->base + CMN_DTM_WPn_MASK(i)); writeq_relaxed(0, dtm->base + CMN_DTM_WPn_MASK(i));
......
This diff is collapsed.
...@@ -97,7 +97,6 @@ struct ddr_pmu { ...@@ -97,7 +97,6 @@ struct ddr_pmu {
struct hlist_node node; struct hlist_node node;
struct device *dev; struct device *dev;
struct perf_event *events[NUM_COUNTERS]; struct perf_event *events[NUM_COUNTERS];
int active_events;
enum cpuhp_state cpuhp_state; enum cpuhp_state cpuhp_state;
const struct fsl_ddr_devtype_data *devtype_data; const struct fsl_ddr_devtype_data *devtype_data;
int irq; int irq;
...@@ -530,7 +529,6 @@ static int ddr_perf_event_add(struct perf_event *event, int flags) ...@@ -530,7 +529,6 @@ static int ddr_perf_event_add(struct perf_event *event, int flags)
} }
pmu->events[counter] = event; pmu->events[counter] = event;
pmu->active_events++;
hwc->idx = counter; hwc->idx = counter;
hwc->state |= PERF_HES_STOPPED; hwc->state |= PERF_HES_STOPPED;
...@@ -562,7 +560,6 @@ static void ddr_perf_event_del(struct perf_event *event, int flags) ...@@ -562,7 +560,6 @@ static void ddr_perf_event_del(struct perf_event *event, int flags)
ddr_perf_event_stop(event, PERF_EF_UPDATE); ddr_perf_event_stop(event, PERF_EF_UPDATE);
ddr_perf_free_counter(pmu, counter); ddr_perf_free_counter(pmu, counter);
pmu->active_events--;
hwc->idx = -1; hwc->idx = -1;
} }
......
...@@ -316,21 +316,7 @@ static int hisi_cpa_pmu_probe(struct platform_device *pdev) ...@@ -316,21 +316,7 @@ static int hisi_cpa_pmu_probe(struct platform_device *pdev)
if (!name) if (!name)
return -ENOMEM; return -ENOMEM;
cpa_pmu->pmu = (struct pmu) { hisi_pmu_init(cpa_pmu, name, THIS_MODULE);
.name = name,
.module = THIS_MODULE,
.task_ctx_nr = perf_invalid_context,
.event_init = hisi_uncore_pmu_event_init,
.pmu_enable = hisi_uncore_pmu_enable,
.pmu_disable = hisi_uncore_pmu_disable,
.add = hisi_uncore_pmu_add,
.del = hisi_uncore_pmu_del,
.start = hisi_uncore_pmu_start,
.stop = hisi_uncore_pmu_stop,
.read = hisi_uncore_pmu_read,
.attr_groups = cpa_pmu->pmu_events.attr_groups,
.capabilities = PERF_PMU_CAP_NO_EXCLUDE,
};
/* Power Management should be disabled before using CPA PMU. */ /* Power Management should be disabled before using CPA PMU. */
hisi_cpa_pmu_disable_pm(cpa_pmu); hisi_cpa_pmu_disable_pm(cpa_pmu);
......
...@@ -516,7 +516,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev) ...@@ -516,7 +516,7 @@ static int hisi_ddrc_pmu_probe(struct platform_device *pdev)
"hisi_sccl%u_ddrc%u", ddrc_pmu->sccl_id, "hisi_sccl%u_ddrc%u", ddrc_pmu->sccl_id,
ddrc_pmu->index_id); ddrc_pmu->index_id);
hisi_pmu_init(&ddrc_pmu->pmu, name, ddrc_pmu->pmu_events.attr_groups, THIS_MODULE); hisi_pmu_init(ddrc_pmu, name, THIS_MODULE);
ret = perf_pmu_register(&ddrc_pmu->pmu, name, -1); ret = perf_pmu_register(&ddrc_pmu->pmu, name, -1);
if (ret) { if (ret) {
......
...@@ -519,7 +519,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev) ...@@ -519,7 +519,7 @@ static int hisi_hha_pmu_probe(struct platform_device *pdev)
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_hha%u", name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_hha%u",
hha_pmu->sccl_id, hha_pmu->index_id); hha_pmu->sccl_id, hha_pmu->index_id);
hisi_pmu_init(&hha_pmu->pmu, name, hha_pmu->pmu_events.attr_groups, THIS_MODULE); hisi_pmu_init(hha_pmu, name, THIS_MODULE);
ret = perf_pmu_register(&hha_pmu->pmu, name, -1); ret = perf_pmu_register(&hha_pmu->pmu, name, -1);
if (ret) { if (ret) {
......
...@@ -557,7 +557,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev) ...@@ -557,7 +557,7 @@ static int hisi_l3c_pmu_probe(struct platform_device *pdev)
*/ */
name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3c%u", name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "hisi_sccl%u_l3c%u",
l3c_pmu->sccl_id, l3c_pmu->ccl_id); l3c_pmu->sccl_id, l3c_pmu->ccl_id);
hisi_pmu_init(&l3c_pmu->pmu, name, l3c_pmu->pmu_events.attr_groups, THIS_MODULE); hisi_pmu_init(l3c_pmu, name, THIS_MODULE);
ret = perf_pmu_register(&l3c_pmu->pmu, name, -1); ret = perf_pmu_register(&l3c_pmu->pmu, name, -1);
if (ret) { if (ret) {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -434,6 +434,7 @@ typedef struct elf64_shdr { ...@@ -434,6 +434,7 @@ typedef struct elf64_shdr {
#define NT_ARM_PAC_ENABLED_KEYS 0x40a /* arm64 ptr auth enabled keys (prctl()) */ #define NT_ARM_PAC_ENABLED_KEYS 0x40a /* arm64 ptr auth enabled keys (prctl()) */
#define NT_ARM_SSVE 0x40b /* ARM Streaming SVE registers */ #define NT_ARM_SSVE 0x40b /* ARM Streaming SVE registers */
#define NT_ARM_ZA 0x40c /* ARM SME ZA registers */ #define NT_ARM_ZA 0x40c /* ARM SME ZA registers */
#define NT_ARM_ZT 0x40d /* ARM SME ZT registers */
#define NT_ARC_V2 0x600 /* ARCv2 accumulator/extra registers */ #define NT_ARC_V2 0x600 /* ARCv2 accumulator/extra registers */
#define NT_VMCOREDD 0x700 /* Vmcore Device Dump Note */ #define NT_VMCOREDD 0x700 /* Vmcore Device Dump Note */
#define NT_MIPS_DSP 0x800 /* MIPS DSP ASE registers */ #define NT_MIPS_DSP 0x800 /* MIPS DSP ASE registers */
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment