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

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

Pull arm64 updates from Catalin Marinas:
"These are the arm64 updates for 6.19.

The biggest part is the Arm MPAM driver under drivers/resctrl/.
There's a patch touching mm/ to handle spurious faults for huge pmd
(similar to the pte version). The corresponding arm64 part allows us
to avoid the TLB maintenance if a (huge) page is reused after a write
fault. There's EFI refactoring to allow runtime services with
preemption enabled and the rest is the usual perf/PMU updates and
several cleanups/typos.

Summary:

Core features:

- Basic Arm MPAM (Memory system resource Partitioning And Monitoring)
driver under drivers/resctrl/ which makes use of the fs/rectrl/ API

Perf and PMU:

- Avoid cycle counter on multi-threaded CPUs

- Extend CSPMU device probing and add additional filtering support
for NVIDIA implementations

- Add support for the PMUs on the NoC S3 interconnect

- Add additional compatible strings for new Cortex and C1 CPUs

- Add support for data source filtering to the SPE driver

- Add support for i.MX8QM and "DB" PMU in the imx PMU driver

Memory managemennt:

- Avoid broadcast TLBI if page reused in write fault

- Elide TLB invalidation if the old PTE was not valid

- Drop redundant cpu_set_*_tcr_t0sz() macros

- Propagate pgtable_alloc() errors outside of __create_pgd_mapping()

- Propagate return value from __change_memory_common()

ACPI and EFI:

- Call EFI runtime services without disabling preemption

- Remove unused ACPI function

Miscellaneous:

- ptrace support to disable streaming on SME-only systems

- Improve sysreg generation to include a 'Prefix' descriptor

- Replace __ASSEMBLY__ with __ASSEMBLER__

- Align register dumps in the kselftest zt-test

- Remove some no longer used macros/functions

- Various spelling corrections"

* tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: (94 commits)
arm64/mm: Document why linear map split failure upon vm_reset_perms is not problematic
arm64/pageattr: Propagate return value from __change_memory_common
arm64/sysreg: Remove unused define ARM64_FEATURE_FIELD_BITS
KVM: arm64: selftests: Consider all 7 possible levels of cache
KVM: arm64: selftests: Remove ARM64_FEATURE_FIELD_BITS and its last user
arm64: atomics: lse: Remove unused parameters from ATOMIC_FETCH_OP_AND macros
Documentation/arm64: Fix the typo of register names
ACPI: GTDT: Get rid of acpi_arch_timer_mem_init()
perf: arm_spe: Add support for filtering on data source
perf: Add perf_event_attr::config4
perf/imx_ddr: Add support for PMU in DB (system interconnects)
perf/imx_ddr: Get and enable optional clks
perf/imx_ddr: Move ida_alloc() from ddr_perf_init() to ddr_perf_probe()
dt-bindings: perf: fsl-imx-ddr: Add compatible string for i.MX8QM, i.MX8QXP and i.MX8DXL
arm64: remove duplicate ARCH_HAS_MEM_ENCRYPT
arm64: mm: use untagged address to calculate page index
MAINTAINERS: new entry for MPAM Driver
arm_mpam: Add kunit tests for props_mismatch()
arm_mpam: Add kunit test for bitmap reset
arm_mpam: Add helper to reset saved mbwu state
...

+5997 -711
+4 -4
Documentation/arch/arm64/booting.rst
··· 391 391 - SMCR_EL2.LEN must be initialised to the same value for all CPUs the 392 392 kernel will execute on. 393 393 394 - - HWFGRTR_EL2.nTPIDR2_EL0 (bit 55) must be initialised to 0b01. 394 + - HFGRTR_EL2.nTPIDR2_EL0 (bit 55) must be initialised to 0b01. 395 395 396 - - HWFGWTR_EL2.nTPIDR2_EL0 (bit 55) must be initialised to 0b01. 396 + - HFGWTR_EL2.nTPIDR2_EL0 (bit 55) must be initialised to 0b01. 397 397 398 - - HWFGRTR_EL2.nSMPRI_EL1 (bit 54) must be initialised to 0b01. 398 + - HFGRTR_EL2.nSMPRI_EL1 (bit 54) must be initialised to 0b01. 399 399 400 - - HWFGWTR_EL2.nSMPRI_EL1 (bit 54) must be initialised to 0b01. 400 + - HFGWTR_EL2.nSMPRI_EL1 (bit 54) must be initialised to 0b01. 401 401 402 402 For CPUs with the Scalable Matrix Extension FA64 feature (FEAT_SME_FA64): 403 403
+5
Documentation/arch/arm64/sve.rst
··· 402 402 streaming mode and any SETREGSET of NT_ARM_SSVE will enter streaming mode 403 403 if the target was not in streaming mode. 404 404 405 + * On systems that do not support SVE it is permitted to use SETREGSET to 406 + write SVE_PT_REGS_FPSIMD formatted data via NT_ARM_SVE, in this case the 407 + vector length should be specified as 0. This allows streaming mode to be 408 + disabled on systems with SME but not SVE. 409 + 405 410 * If any register data is provided along with SVE_PT_VL_ONEXEC then the 406 411 registers data will be interpreted with the current vector length, not 407 412 the vector length configured for use on exec.
+28 -1
Documentation/devicetree/bindings/perf/fsl-imx-ddr.yaml
··· 14 14 oneOf: 15 15 - enum: 16 16 - fsl,imx8-ddr-pmu 17 + - fsl,imx8dxl-db-pmu 17 18 - fsl,imx8m-ddr-pmu 18 19 - fsl,imx8mq-ddr-pmu 19 20 - fsl,imx8mm-ddr-pmu ··· 29 28 - fsl,imx8mp-ddr-pmu 30 29 - const: fsl,imx8m-ddr-pmu 31 30 - items: 32 - - const: fsl,imx8dxl-ddr-pmu 31 + - enum: 32 + - fsl,imx8dxl-ddr-pmu 33 + - fsl,imx8qm-ddr-pmu 34 + - fsl,imx8qxp-ddr-pmu 33 35 - const: fsl,imx8-ddr-pmu 34 36 - items: 35 37 - enum: ··· 47 43 interrupts: 48 44 maxItems: 1 49 45 46 + clocks: 47 + maxItems: 2 48 + 49 + clock-names: 50 + items: 51 + - const: ipg 52 + - const: cnt 53 + 50 54 required: 51 55 - compatible 52 56 - reg 53 57 - interrupts 54 58 55 59 additionalProperties: false 60 + 61 + allOf: 62 + - if: 63 + properties: 64 + compatible: 65 + contains: 66 + const: fsl,imx8dxl-db-pmu 67 + then: 68 + required: 69 + - clocks 70 + - clock-names 71 + else: 72 + properties: 73 + clocks: false 74 + clock-names: false 56 75 57 76 examples: 58 77 - |
+10
MAINTAINERS
··· 17470 17470 F: Documentation/devicetree/bindings/leds/backlight/mps,mp3309c.yaml 17471 17471 F: drivers/video/backlight/mp3309c.c 17472 17472 17473 + MPAM DRIVER 17474 + M: James Morse <james.morse@arm.com> 17475 + M: Ben Horgan <ben.horgan@arm.com> 17476 + R: Reinette Chatre <reinette.chatre@intel.com> 17477 + R: Fenghua Yu <fenghuay@nvidia.com> 17478 + S: Maintained 17479 + F: drivers/resctrl/mpam_* 17480 + F: drivers/resctrl/test_mpam_* 17481 + F: include/linux/arm_mpam.h 17482 + 17473 17483 MPS MP2869 DRIVER 17474 17484 M: Wensheng Wang <wenswang@yeah.net> 17475 17485 L: linux-hwmon@vger.kernel.org
+25 -1
arch/arm64/Kconfig
··· 47 47 select ARCH_HAS_SETUP_DMA_OPS 48 48 select ARCH_HAS_SET_DIRECT_MAP 49 49 select ARCH_HAS_SET_MEMORY 50 - select ARCH_HAS_MEM_ENCRYPT 51 50 select ARCH_HAS_FORCE_DMA_UNENCRYPTED 52 51 select ARCH_STACKWALK 53 52 select ARCH_HAS_STRICT_KERNEL_RWX ··· 2021 2022 help 2022 2023 ARMv8.4-TLBI provides TLBI invalidation instruction that apply to a 2023 2024 range of input addresses. 2025 + 2026 + config ARM64_MPAM 2027 + bool "Enable support for MPAM" 2028 + select ARM64_MPAM_DRIVER if EXPERT # does nothing yet 2029 + select ACPI_MPAM if ACPI 2030 + help 2031 + Memory System Resource Partitioning and Monitoring (MPAM) is an 2032 + optional extension to the Arm architecture that allows each 2033 + transaction issued to the memory system to be labelled with a 2034 + Partition identifier (PARTID) and Performance Monitoring Group 2035 + identifier (PMG). 2036 + 2037 + Memory system components, such as the caches, can be configured with 2038 + policies to control how much of various physical resources (such as 2039 + memory bandwidth or cache memory) the transactions labelled with each 2040 + PARTID can consume. Depending on the capabilities of the hardware, 2041 + the PARTID and PMG can also be used as filtering criteria to measure 2042 + the memory system resource consumption of different parts of a 2043 + workload. 2044 + 2045 + Use of this extension requires CPU support, support in the 2046 + Memory System Components (MSC), and a description from firmware 2047 + of where the MSCs are in the address space. 2048 + 2049 + MPAM is exposed to user-space via the resctrl pseudo filesystem. 2024 2050 2025 2051 endmenu # "ARMv8.4 architectural features" 2026 2052
+4 -4
arch/arm64/include/asm/alternative-macros.h
··· 19 19 #error "cpucaps have overflown ARM64_CB_BIT" 20 20 #endif 21 21 22 - #ifndef __ASSEMBLY__ 22 + #ifndef __ASSEMBLER__ 23 23 24 24 #include <linux/stringify.h> 25 25 ··· 207 207 #define _ALTERNATIVE_CFG(insn1, insn2, cap, cfg, ...) \ 208 208 alternative_insn insn1, insn2, cap, IS_ENABLED(cfg) 209 209 210 - #endif /* __ASSEMBLY__ */ 210 + #endif /* __ASSEMBLER__ */ 211 211 212 212 /* 213 213 * Usage: asm(ALTERNATIVE(oldinstr, newinstr, cpucap)); ··· 219 219 #define ALTERNATIVE(oldinstr, newinstr, ...) \ 220 220 _ALTERNATIVE_CFG(oldinstr, newinstr, __VA_ARGS__, 1) 221 221 222 - #ifndef __ASSEMBLY__ 222 + #ifndef __ASSEMBLER__ 223 223 224 224 #include <linux/types.h> 225 225 ··· 263 263 return true; 264 264 } 265 265 266 - #endif /* __ASSEMBLY__ */ 266 + #endif /* __ASSEMBLER__ */ 267 267 268 268 #endif /* __ASM_ALTERNATIVE_MACROS_H */
+2 -2
arch/arm64/include/asm/alternative.h
··· 4 4 5 5 #include <asm/alternative-macros.h> 6 6 7 - #ifndef __ASSEMBLY__ 7 + #ifndef __ASSEMBLER__ 8 8 9 9 #include <linux/init.h> 10 10 #include <linux/types.h> ··· 37 37 void alt_cb_patch_nops(struct alt_instr *alt, __le32 *origptr, 38 38 __le32 *updptr, int nr_inst); 39 39 40 - #endif /* __ASSEMBLY__ */ 40 + #endif /* __ASSEMBLER__ */ 41 41 #endif /* __ASM_ALTERNATIVE_H */
+2 -2
arch/arm64/include/asm/arch_gicv3.h
··· 9 9 10 10 #include <asm/sysreg.h> 11 11 12 - #ifndef __ASSEMBLY__ 12 + #ifndef __ASSEMBLER__ 13 13 14 14 #include <linux/irqchip/arm-gic-common.h> 15 15 #include <linux/stringify.h> ··· 188 188 return cpus_have_cap(ARM64_HAS_GIC_PRIO_RELAXED_SYNC); 189 189 } 190 190 191 - #endif /* __ASSEMBLY__ */ 191 + #endif /* __ASSEMBLER__ */ 192 192 #endif /* __ASM_ARCH_GICV3_H */
+3 -3
arch/arm64/include/asm/asm-extable.h
··· 27 27 /* Data fields for EX_TYPE_UACCESS_CPY */ 28 28 #define EX_DATA_UACCESS_WRITE BIT(0) 29 29 30 - #ifdef __ASSEMBLY__ 30 + #ifdef __ASSEMBLER__ 31 31 32 32 #define __ASM_EXTABLE_RAW(insn, fixup, type, data) \ 33 33 .pushsection __ex_table, "a"; \ ··· 77 77 __ASM_EXTABLE_RAW(\insn, \fixup, EX_TYPE_UACCESS_CPY, \uaccess_is_write) 78 78 .endm 79 79 80 - #else /* __ASSEMBLY__ */ 80 + #else /* __ASSEMBLER__ */ 81 81 82 82 #include <linux/stringify.h> 83 83 ··· 132 132 EX_DATA_REG(ADDR, addr) \ 133 133 ")") 134 134 135 - #endif /* __ASSEMBLY__ */ 135 + #endif /* __ASSEMBLER__ */ 136 136 137 137 #endif /* __ASM_ASM_EXTABLE_H */
+6 -6
arch/arm64/include/asm/assembler.h
··· 5 5 * Copyright (C) 1996-2000 Russell King 6 6 * Copyright (C) 2012 ARM Ltd. 7 7 */ 8 - #ifndef __ASSEMBLY__ 8 + #ifndef __ASSEMBLER__ 9 9 #error "Only include this from assembly code" 10 10 #endif 11 11 ··· 325 325 * tcr_set_t0sz - update TCR.T0SZ so that we can load the ID map 326 326 */ 327 327 .macro tcr_set_t0sz, valreg, t0sz 328 - bfi \valreg, \t0sz, #TCR_T0SZ_OFFSET, #TCR_TxSZ_WIDTH 328 + bfi \valreg, \t0sz, #TCR_EL1_T0SZ_SHIFT, #TCR_EL1_T0SZ_WIDTH 329 329 .endm 330 330 331 331 /* 332 332 * tcr_set_t1sz - update TCR.T1SZ 333 333 */ 334 334 .macro tcr_set_t1sz, valreg, t1sz 335 - bfi \valreg, \t1sz, #TCR_T1SZ_OFFSET, #TCR_TxSZ_WIDTH 335 + bfi \valreg, \t1sz, #TCR_EL1_T1SZ_SHIFT, #TCR_EL1_T1SZ_WIDTH 336 336 .endm 337 337 338 338 /* ··· 371 371 * [start, end) with dcache line size explicitly provided. 372 372 * 373 373 * op: operation passed to dc instruction 374 - * domain: domain used in dsb instruciton 374 + * domain: domain used in dsb instruction 375 375 * start: starting virtual address of the region 376 376 * end: end virtual address of the region 377 377 * linesz: dcache line size ··· 412 412 * [start, end) 413 413 * 414 414 * op: operation passed to dc instruction 415 - * domain: domain used in dsb instruciton 415 + * domain: domain used in dsb instruction 416 416 * start: starting virtual address of the region 417 417 * end: end virtual address of the region 418 418 * fixup: optional label to branch to on user fault ··· 589 589 .macro offset_ttbr1, ttbr, tmp 590 590 #if defined(CONFIG_ARM64_VA_BITS_52) && !defined(CONFIG_ARM64_LPA2) 591 591 mrs \tmp, tcr_el1 592 - and \tmp, \tmp, #TCR_T1SZ_MASK 592 + and \tmp, \tmp, #TCR_EL1_T1SZ_MASK 593 593 cmp \tmp, #TCR_T1SZ(VA_BITS_MIN) 594 594 orr \tmp, \ttbr, #TTBR1_BADDR_4852_OFFSET 595 595 csel \ttbr, \tmp, \ttbr, eq
+10 -10
arch/arm64/include/asm/atomic_lse.h
··· 103 103 return __lse_atomic_andnot(~i, v); 104 104 } 105 105 106 - #define ATOMIC_FETCH_OP_AND(name, mb, cl...) \ 106 + #define ATOMIC_FETCH_OP_AND(name) \ 107 107 static __always_inline int \ 108 108 __lse_atomic_fetch_and##name(int i, atomic_t *v) \ 109 109 { \ 110 110 return __lse_atomic_fetch_andnot##name(~i, v); \ 111 111 } 112 112 113 - ATOMIC_FETCH_OP_AND(_relaxed, ) 114 - ATOMIC_FETCH_OP_AND(_acquire, a, "memory") 115 - ATOMIC_FETCH_OP_AND(_release, l, "memory") 116 - ATOMIC_FETCH_OP_AND( , al, "memory") 113 + ATOMIC_FETCH_OP_AND(_relaxed) 114 + ATOMIC_FETCH_OP_AND(_acquire) 115 + ATOMIC_FETCH_OP_AND(_release) 116 + ATOMIC_FETCH_OP_AND( ) 117 117 118 118 #undef ATOMIC_FETCH_OP_AND 119 119 ··· 210 210 return __lse_atomic64_andnot(~i, v); 211 211 } 212 212 213 - #define ATOMIC64_FETCH_OP_AND(name, mb, cl...) \ 213 + #define ATOMIC64_FETCH_OP_AND(name) \ 214 214 static __always_inline long \ 215 215 __lse_atomic64_fetch_and##name(s64 i, atomic64_t *v) \ 216 216 { \ 217 217 return __lse_atomic64_fetch_andnot##name(~i, v); \ 218 218 } 219 219 220 - ATOMIC64_FETCH_OP_AND(_relaxed, ) 221 - ATOMIC64_FETCH_OP_AND(_acquire, a, "memory") 222 - ATOMIC64_FETCH_OP_AND(_release, l, "memory") 223 - ATOMIC64_FETCH_OP_AND( , al, "memory") 220 + ATOMIC64_FETCH_OP_AND(_relaxed) 221 + ATOMIC64_FETCH_OP_AND(_acquire) 222 + ATOMIC64_FETCH_OP_AND(_release) 223 + ATOMIC64_FETCH_OP_AND( ) 224 224 225 225 #undef ATOMIC64_FETCH_OP_AND 226 226
+2 -2
arch/arm64/include/asm/barrier.h
··· 7 7 #ifndef __ASM_BARRIER_H 8 8 #define __ASM_BARRIER_H 9 9 10 - #ifndef __ASSEMBLY__ 10 + #ifndef __ASSEMBLER__ 11 11 12 12 #include <linux/kasan-checks.h> 13 13 ··· 221 221 222 222 #include <asm-generic/barrier.h> 223 223 224 - #endif /* __ASSEMBLY__ */ 224 + #endif /* __ASSEMBLER__ */ 225 225 226 226 #endif /* __ASM_BARRIER_H */
+2 -2
arch/arm64/include/asm/cache.h
··· 35 35 #define ARCH_DMA_MINALIGN (128) 36 36 #define ARCH_KMALLOC_MINALIGN (8) 37 37 38 - #if !defined(__ASSEMBLY__) && !defined(BUILD_VDSO) 38 + #if !defined(__ASSEMBLER__) && !defined(BUILD_VDSO) 39 39 40 40 #include <linux/bitops.h> 41 41 #include <linux/kasan-enabled.h> ··· 135 135 return ctr; 136 136 } 137 137 138 - #endif /* !defined(__ASSEMBLY__) && !defined(BUILD_VDSO) */ 138 + #endif /* !defined(__ASSEMBLER__) && !defined(BUILD_VDSO) */ 139 139 140 140 #endif
+2 -2
arch/arm64/include/asm/cpucaps.h
··· 5 5 6 6 #include <asm/cpucap-defs.h> 7 7 8 - #ifndef __ASSEMBLY__ 8 + #ifndef __ASSEMBLER__ 9 9 #include <linux/types.h> 10 10 /* 11 11 * Check whether a cpucap is possible at compiletime. ··· 77 77 78 78 return true; 79 79 } 80 - #endif /* __ASSEMBLY__ */ 80 + #endif /* __ASSEMBLER__ */ 81 81 82 82 #endif /* __ASM_CPUCAPS_H */
+4 -4
arch/arm64/include/asm/cpufeature.h
··· 19 19 #define ARM64_SW_FEATURE_OVERRIDE_HVHE 4 20 20 #define ARM64_SW_FEATURE_OVERRIDE_RODATA_OFF 8 21 21 22 - #ifndef __ASSEMBLY__ 22 + #ifndef __ASSEMBLER__ 23 23 24 24 #include <linux/bug.h> 25 25 #include <linux/jump_label.h> ··· 199 199 * registers (e.g, SCTLR, TCR etc.) or patching the kernel via 200 200 * alternatives. The kernel patching is batched and performed at later 201 201 * point. The actions are always initiated only after the capability 202 - * is finalised. This is usally denoted by "enabling" the capability. 202 + * is finalised. This is usually denoted by "enabling" the capability. 203 203 * The actions are initiated as follows : 204 204 * a) Action is triggered on all online CPUs, after the capability is 205 205 * finalised, invoked within the stop_machine() context from ··· 251 251 #define ARM64_CPUCAP_SCOPE_LOCAL_CPU ((u16)BIT(0)) 252 252 #define ARM64_CPUCAP_SCOPE_SYSTEM ((u16)BIT(1)) 253 253 /* 254 - * The capabilitiy is detected on the Boot CPU and is used by kernel 254 + * The capability is detected on the Boot CPU and is used by kernel 255 255 * during early boot. i.e, the capability should be "detected" and 256 256 * "enabled" as early as possibly on all booting CPUs. 257 257 */ ··· 1078 1078 #endif 1079 1079 } 1080 1080 1081 - #endif /* __ASSEMBLY__ */ 1081 + #endif /* __ASSEMBLER__ */ 1082 1082 1083 1083 #endif
+3 -3
arch/arm64/include/asm/cputype.h
··· 247 247 /* Fujitsu Erratum 010001 affects A64FX 1.0 and 1.1, (v0r0 and v1r0) */ 248 248 #define MIDR_FUJITSU_ERRATUM_010001 MIDR_FUJITSU_A64FX 249 249 #define MIDR_FUJITSU_ERRATUM_010001_MASK (~MIDR_CPU_VAR_REV(1, 0)) 250 - #define TCR_CLEAR_FUJITSU_ERRATUM_010001 (TCR_NFD1 | TCR_NFD0) 250 + #define TCR_CLEAR_FUJITSU_ERRATUM_010001 (TCR_EL1_NFD1 | TCR_EL1_NFD0) 251 251 252 - #ifndef __ASSEMBLY__ 252 + #ifndef __ASSEMBLER__ 253 253 254 254 #include <asm/sysreg.h> 255 255 ··· 328 328 { 329 329 return read_cpuid(CTR_EL0); 330 330 } 331 - #endif /* __ASSEMBLY__ */ 331 + #endif /* __ASSEMBLER__ */ 332 332 333 333 #endif
+2 -2
arch/arm64/include/asm/current.h
··· 4 4 5 5 #include <linux/compiler.h> 6 6 7 - #ifndef __ASSEMBLY__ 7 + #ifndef __ASSEMBLER__ 8 8 9 9 struct task_struct; 10 10 ··· 23 23 24 24 #define current get_current() 25 25 26 - #endif /* __ASSEMBLY__ */ 26 + #endif /* __ASSEMBLER__ */ 27 27 28 28 #endif /* __ASM_CURRENT_H */ 29 29
+2 -2
arch/arm64/include/asm/debug-monitors.h
··· 48 48 #define AARCH32_BREAK_THUMB2_LO 0xf7f0 49 49 #define AARCH32_BREAK_THUMB2_HI 0xa000 50 50 51 - #ifndef __ASSEMBLY__ 51 + #ifndef __ASSEMBLER__ 52 52 struct task_struct; 53 53 54 54 #define DBG_ARCH_ID_RESERVED 0 /* In case of ptrace ABI updates. */ ··· 88 88 89 89 bool try_handle_aarch32_break(struct pt_regs *regs); 90 90 91 - #endif /* __ASSEMBLY */ 91 + #endif /* __ASSEMBLER__ */ 92 92 #endif /* __ASM_DEBUG_MONITORS_H */
+3 -10
arch/arm64/include/asm/efi.h
··· 126 126 if (mm != current->active_mm) { 127 127 /* 128 128 * Update the current thread's saved ttbr0 since it is 129 - * restored as part of a return from exception. Enable 130 - * access to the valid TTBR0_EL1 and invoke the errata 131 - * workaround directly since there is no return from 132 - * exception when invoking the EFI run-time services. 129 + * restored as part of a return from exception. 133 130 */ 134 131 update_saved_ttbr0(current, mm); 135 - uaccess_ttbr0_enable(); 136 - post_ttbr_update_workaround(); 137 132 } else { 138 133 /* 139 - * Defer the switch to the current thread's TTBR0_EL1 140 - * until uaccess_enable(). Restore the current 141 - * thread's saved ttbr0 corresponding to its active_mm 134 + * Restore the current thread's saved ttbr0 135 + * corresponding to its active_mm 142 136 */ 143 - uaccess_ttbr0_disable(); 144 137 update_saved_ttbr0(current, current->active_mm); 145 138 } 146 139 }
+2 -2
arch/arm64/include/asm/el2_setup.h
··· 7 7 #ifndef __ARM_KVM_INIT_H__ 8 8 #define __ARM_KVM_INIT_H__ 9 9 10 - #ifndef __ASSEMBLY__ 10 + #ifndef __ASSEMBLER__ 11 11 #error Assembly-only header 12 12 #endif 13 13 ··· 24 24 * ID_AA64MMFR4_EL1.E2H0 < 0. On such CPUs HCR_EL2.E2H is RES1, but it 25 25 * can reset into an UNKNOWN state and might not read as 1 until it has 26 26 * been initialized explicitly. 27 - * Initalize HCR_EL2.E2H so that later code can rely upon HCR_EL2.E2H 27 + * Initialize HCR_EL2.E2H so that later code can rely upon HCR_EL2.E2H 28 28 * indicating whether the CPU is running in E2H mode. 29 29 */ 30 30 mrs_s x1, SYS_ID_AA64MMFR4_EL1
+2 -2
arch/arm64/include/asm/elf.h
··· 133 133 #define ELF_ET_DYN_BASE (2 * DEFAULT_MAP_WINDOW_64 / 3) 134 134 #endif /* CONFIG_ARM64_FORCE_52BIT */ 135 135 136 - #ifndef __ASSEMBLY__ 136 + #ifndef __ASSEMBLER__ 137 137 138 138 #include <uapi/linux/elf.h> 139 139 #include <linux/bug.h> ··· 293 293 return 0; 294 294 } 295 295 296 - #endif /* !__ASSEMBLY__ */ 296 + #endif /* !__ASSEMBLER__ */ 297 297 298 298 #endif
+2 -2
arch/arm64/include/asm/esr.h
··· 431 431 #define ESR_ELx_IT_GCSPOPCX 6 432 432 #define ESR_ELx_IT_GCSPOPX 7 433 433 434 - #ifndef __ASSEMBLY__ 434 + #ifndef __ASSEMBLER__ 435 435 #include <asm/types.h> 436 436 437 437 static inline unsigned long esr_brk_comment(unsigned long esr) ··· 534 534 } 535 535 536 536 const char *esr_get_class_string(unsigned long esr); 537 - #endif /* __ASSEMBLY */ 537 + #endif /* __ASSEMBLER__ */ 538 538 539 539 #endif /* __ASM_ESR_H */
+2 -2
arch/arm64/include/asm/fixmap.h
··· 15 15 #ifndef _ASM_ARM64_FIXMAP_H 16 16 #define _ASM_ARM64_FIXMAP_H 17 17 18 - #ifndef __ASSEMBLY__ 18 + #ifndef __ASSEMBLER__ 19 19 #include <linux/kernel.h> 20 20 #include <linux/math.h> 21 21 #include <linux/sizes.h> ··· 117 117 118 118 #include <asm-generic/fixmap.h> 119 119 120 - #endif /* !__ASSEMBLY__ */ 120 + #endif /* !__ASSEMBLER__ */ 121 121 #endif /* _ASM_ARM64_FIXMAP_H */
+1 -1
arch/arm64/include/asm/fpsimd.h
··· 12 12 #include <asm/sigcontext.h> 13 13 #include <asm/sysreg.h> 14 14 15 - #ifndef __ASSEMBLY__ 15 + #ifndef __ASSEMBLER__ 16 16 17 17 #include <linux/bitmap.h> 18 18 #include <linux/build_bug.h>
+3 -3
arch/arm64/include/asm/ftrace.h
··· 37 37 */ 38 38 #define ARCH_FTRACE_SHIFT_STACK_TRACER 1 39 39 40 - #ifndef __ASSEMBLY__ 40 + #ifndef __ASSEMBLER__ 41 41 #include <linux/compat.h> 42 42 43 43 extern void _mcount(unsigned long); ··· 217 217 */ 218 218 return !strcmp(sym + 8, name); 219 219 } 220 - #endif /* ifndef __ASSEMBLY__ */ 220 + #endif /* ifndef __ASSEMBLER__ */ 221 221 222 - #ifndef __ASSEMBLY__ 222 + #ifndef __ASSEMBLER__ 223 223 #ifdef CONFIG_FUNCTION_GRAPH_TRACER 224 224 225 225 void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
+3 -3
arch/arm64/include/asm/gpr-num.h
··· 2 2 #ifndef __ASM_GPR_NUM_H 3 3 #define __ASM_GPR_NUM_H 4 4 5 - #ifdef __ASSEMBLY__ 5 + #ifdef __ASSEMBLER__ 6 6 7 7 .irp num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 8 8 .equ .L__gpr_num_x\num, \num ··· 11 11 .equ .L__gpr_num_xzr, 31 12 12 .equ .L__gpr_num_wzr, 31 13 13 14 - #else /* __ASSEMBLY__ */ 14 + #else /* __ASSEMBLER__ */ 15 15 16 16 #define __DEFINE_ASM_GPR_NUMS \ 17 17 " .irp num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30\n" \ ··· 21 21 " .equ .L__gpr_num_xzr, 31\n" \ 22 22 " .equ .L__gpr_num_wzr, 31\n" 23 23 24 - #endif /* __ASSEMBLY__ */ 24 + #endif /* __ASSEMBLER__ */ 25 25 26 26 #endif /* __ASM_GPR_NUM_H */
+1 -1
arch/arm64/include/asm/hwcap.h
··· 46 46 #define COMPAT_HWCAP2_SB (1 << 5) 47 47 #define COMPAT_HWCAP2_SSBS (1 << 6) 48 48 49 - #ifndef __ASSEMBLY__ 49 + #ifndef __ASSEMBLER__ 50 50 #include <linux/log2.h> 51 51 52 52 /*
+2 -2
arch/arm64/include/asm/image.h
··· 20 20 #define ARM64_IMAGE_FLAG_PAGE_SIZE_64K 3 21 21 #define ARM64_IMAGE_FLAG_PHYS_BASE 1 22 22 23 - #ifndef __ASSEMBLY__ 23 + #ifndef __ASSEMBLER__ 24 24 25 25 #define arm64_image_flag_field(flags, field) \ 26 26 (((flags) >> field##_SHIFT) & field##_MASK) ··· 54 54 __le32 res5; 55 55 }; 56 56 57 - #endif /* __ASSEMBLY__ */ 57 + #endif /* __ASSEMBLER__ */ 58 58 59 59 #endif /* __ASM_IMAGE_H */
+2 -2
arch/arm64/include/asm/insn.h
··· 12 12 13 13 #include <asm/insn-def.h> 14 14 15 - #ifndef __ASSEMBLY__ 15 + #ifndef __ASSEMBLER__ 16 16 17 17 enum aarch64_insn_hint_cr_op { 18 18 AARCH64_INSN_HINT_NOP = 0x0 << 5, ··· 730 730 typedef bool (pstate_check_t)(unsigned long); 731 731 extern pstate_check_t * const aarch32_opcode_cond_checks[16]; 732 732 733 - #endif /* __ASSEMBLY__ */ 733 + #endif /* __ASSEMBLER__ */ 734 734 735 735 #endif /* __ASM_INSN_H */
+2 -2
arch/arm64/include/asm/jump_label.h
··· 8 8 #ifndef __ASM_JUMP_LABEL_H 9 9 #define __ASM_JUMP_LABEL_H 10 10 11 - #ifndef __ASSEMBLY__ 11 + #ifndef __ASSEMBLER__ 12 12 13 13 #include <linux/types.h> 14 14 #include <asm/insn.h> ··· 58 58 return true; 59 59 } 60 60 61 - #endif /* __ASSEMBLY__ */ 61 + #endif /* __ASSEMBLER__ */ 62 62 #endif /* __ASM_JUMP_LABEL_H */
+1 -1
arch/arm64/include/asm/kasan.h
··· 2 2 #ifndef __ASM_KASAN_H 3 3 #define __ASM_KASAN_H 4 4 5 - #ifndef __ASSEMBLY__ 5 + #ifndef __ASSEMBLER__ 6 6 7 7 #include <linux/linkage.h> 8 8 #include <asm/memory.h>
+2 -2
arch/arm64/include/asm/kexec.h
··· 25 25 26 26 #define KEXEC_ARCH KEXEC_ARCH_AARCH64 27 27 28 - #ifndef __ASSEMBLY__ 28 + #ifndef __ASSEMBLER__ 29 29 30 30 /** 31 31 * crash_setup_regs() - save registers for the panic kernel ··· 130 130 char *cmdline); 131 131 #endif 132 132 133 - #endif /* __ASSEMBLY__ */ 133 + #endif /* __ASSEMBLER__ */ 134 134 135 135 #endif
+2 -2
arch/arm64/include/asm/kgdb.h
··· 14 14 #include <linux/ptrace.h> 15 15 #include <asm/debug-monitors.h> 16 16 17 - #ifndef __ASSEMBLY__ 17 + #ifndef __ASSEMBLER__ 18 18 19 19 static inline void arch_kgdb_breakpoint(void) 20 20 { ··· 36 36 } 37 37 #endif 38 38 39 - #endif /* !__ASSEMBLY__ */ 39 + #endif /* !__ASSEMBLER__ */ 40 40 41 41 /* 42 42 * gdb remote procotol (well most versions of it) expects the following
+2 -2
arch/arm64/include/asm/kvm_asm.h
··· 46 46 47 47 #define __KVM_HOST_SMCCC_FUNC___kvm_hyp_init 0 48 48 49 - #ifndef __ASSEMBLY__ 49 + #ifndef __ASSEMBLER__ 50 50 51 51 #include <linux/mm.h> 52 52 ··· 303 303 void __noreturn __cold nvhe_hyp_panic_handler(u64 esr, u64 spsr, u64 elr_virt, 304 304 u64 elr_phys, u64 par, uintptr_t vcpu, u64 far, u64 hpfar); 305 305 306 - #else /* __ASSEMBLY__ */ 306 + #else /* __ASSEMBLER__ */ 307 307 308 308 .macro get_host_ctxt reg, tmp 309 309 adr_this_cpu \reg, kvm_host_data, \tmp
+2 -2
arch/arm64/include/asm/kvm_mmu.h
··· 49 49 * mappings, and none of this applies in that case. 50 50 */ 51 51 52 - #ifdef __ASSEMBLY__ 52 + #ifdef __ASSEMBLER__ 53 53 54 54 #include <asm/alternative.h> 55 55 ··· 396 396 static inline void kvm_s2_ptdump_create_debugfs(struct kvm *kvm) {} 397 397 #endif /* CONFIG_PTDUMP_STAGE2_DEBUGFS */ 398 398 399 - #endif /* __ASSEMBLY__ */ 399 + #endif /* __ASSEMBLER__ */ 400 400 #endif /* __ARM64_KVM_MMU_H__ */
+2 -2
arch/arm64/include/asm/kvm_mte.h
··· 5 5 #ifndef __ASM_KVM_MTE_H 6 6 #define __ASM_KVM_MTE_H 7 7 8 - #ifdef __ASSEMBLY__ 8 + #ifdef __ASSEMBLER__ 9 9 10 10 #include <asm/sysreg.h> 11 11 ··· 62 62 .endm 63 63 64 64 #endif /* CONFIG_ARM64_MTE */ 65 - #endif /* __ASSEMBLY__ */ 65 + #endif /* __ASSEMBLER__ */ 66 66 #endif /* __ASM_KVM_MTE_H */
+3 -3
arch/arm64/include/asm/kvm_ptrauth.h
··· 8 8 #ifndef __ASM_KVM_PTRAUTH_H 9 9 #define __ASM_KVM_PTRAUTH_H 10 10 11 - #ifdef __ASSEMBLY__ 11 + #ifdef __ASSEMBLER__ 12 12 13 13 #include <asm/sysreg.h> 14 14 ··· 100 100 .endm 101 101 #endif /* CONFIG_ARM64_PTR_AUTH */ 102 102 103 - #else /* !__ASSEMBLY */ 103 + #else /* !__ASSEMBLER__ */ 104 104 105 105 #define __ptrauth_save_key(ctxt, key) \ 106 106 do { \ ··· 120 120 __ptrauth_save_key(ctxt, APGA); \ 121 121 } while(0) 122 122 123 - #endif /* __ASSEMBLY__ */ 123 + #endif /* __ASSEMBLER__ */ 124 124 #endif /* __ASM_KVM_PTRAUTH_H */
+1 -1
arch/arm64/include/asm/linkage.h
··· 1 1 #ifndef __ASM_LINKAGE_H 2 2 #define __ASM_LINKAGE_H 3 3 4 - #ifdef __ASSEMBLY__ 4 + #ifdef __ASSEMBLER__ 5 5 #include <asm/assembler.h> 6 6 #endif 7 7
+2 -3
arch/arm64/include/asm/memory.h
··· 207 207 */ 208 208 #define TRAMP_SWAPPER_OFFSET (2 * PAGE_SIZE) 209 209 210 - #ifndef __ASSEMBLY__ 210 + #ifndef __ASSEMBLER__ 211 211 212 212 #include <linux/bitops.h> 213 213 #include <linux/compiler.h> ··· 392 392 * virt_to_page(x) convert a _valid_ virtual address to struct page * 393 393 * virt_addr_valid(x) indicates whether a virtual address is valid 394 394 */ 395 - #define ARCH_PFN_OFFSET ((unsigned long)PHYS_PFN_OFFSET) 396 395 397 396 #if defined(CONFIG_DEBUG_VIRTUAL) 398 397 #define page_to_virt(x) ({ \ ··· 421 422 }) 422 423 423 424 void dump_mem_limit(void); 424 - #endif /* !ASSEMBLY */ 425 + #endif /* !__ASSEMBLER__ */ 425 426 426 427 /* 427 428 * Given that the GIC architecture permits ITS implementations that can only be
+2 -2
arch/arm64/include/asm/mmu.h
··· 12 12 #define USER_ASID_FLAG (UL(1) << USER_ASID_BIT) 13 13 #define TTBR_ASID_MASK (UL(0xffff) << 48) 14 14 15 - #ifndef __ASSEMBLY__ 15 + #ifndef __ASSEMBLER__ 16 16 17 17 #include <linux/refcount.h> 18 18 #include <asm/cpufeature.h> ··· 112 112 static inline void kpti_install_ng_mappings(void) {} 113 113 #endif 114 114 115 - #endif /* !__ASSEMBLY__ */ 115 + #endif /* !__ASSEMBLER__ */ 116 116 #endif
+6 -14
arch/arm64/include/asm/mmu_context.h
··· 8 8 #ifndef __ASM_MMU_CONTEXT_H 9 9 #define __ASM_MMU_CONTEXT_H 10 10 11 - #ifndef __ASSEMBLY__ 11 + #ifndef __ASSEMBLER__ 12 12 13 13 #include <linux/compiler.h> 14 14 #include <linux/sched.h> ··· 62 62 } 63 63 64 64 /* 65 - * TCR.T0SZ value to use when the ID map is active. 66 - */ 67 - #define idmap_t0sz TCR_T0SZ(IDMAP_VA_BITS) 68 - 69 - /* 70 65 * Ensure TCR.T0SZ is set to the provided value. 71 66 */ 72 67 static inline void __cpu_set_tcr_t0sz(unsigned long t0sz) 73 68 { 74 69 unsigned long tcr = read_sysreg(tcr_el1); 75 70 76 - if ((tcr & TCR_T0SZ_MASK) == t0sz) 71 + if ((tcr & TCR_EL1_T0SZ_MASK) == t0sz) 77 72 return; 78 73 79 - tcr &= ~TCR_T0SZ_MASK; 74 + tcr &= ~TCR_EL1_T0SZ_MASK; 80 75 tcr |= t0sz; 81 76 write_sysreg(tcr, tcr_el1); 82 77 isb(); 83 78 } 84 - 85 - #define cpu_set_default_tcr_t0sz() __cpu_set_tcr_t0sz(TCR_T0SZ(vabits_actual)) 86 - #define cpu_set_idmap_tcr_t0sz() __cpu_set_tcr_t0sz(idmap_t0sz) 87 79 88 80 /* 89 81 * Remove the idmap from TTBR0_EL1 and install the pgd of the active mm. ··· 95 103 96 104 cpu_set_reserved_ttbr0(); 97 105 local_flush_tlb_all(); 98 - cpu_set_default_tcr_t0sz(); 106 + __cpu_set_tcr_t0sz(TCR_T0SZ(vabits_actual)); 99 107 100 108 if (mm != &init_mm && !system_uses_ttbr0_pan()) 101 109 cpu_switch_mm(mm->pgd, mm); ··· 105 113 { 106 114 cpu_set_reserved_ttbr0(); 107 115 local_flush_tlb_all(); 108 - cpu_set_idmap_tcr_t0sz(); 116 + __cpu_set_tcr_t0sz(TCR_T0SZ(IDMAP_VA_BITS)); 109 117 110 118 cpu_switch_mm(lm_alias(idmap_pg_dir), &init_mm); 111 119 } ··· 322 330 323 331 #include <asm-generic/mmu_context.h> 324 332 325 - #endif /* !__ASSEMBLY__ */ 333 + #endif /* !__ASSEMBLER__ */ 326 334 327 335 #endif /* !__ASM_MMU_CONTEXT_H */
+2 -2
arch/arm64/include/asm/mte-kasan.h
··· 9 9 #include <asm/cputype.h> 10 10 #include <asm/mte-def.h> 11 11 12 - #ifndef __ASSEMBLY__ 12 + #ifndef __ASSEMBLER__ 13 13 14 14 #include <linux/types.h> 15 15 ··· 259 259 260 260 #endif /* CONFIG_ARM64_MTE */ 261 261 262 - #endif /* __ASSEMBLY__ */ 262 + #endif /* __ASSEMBLER__ */ 263 263 264 264 #endif /* __ASM_MTE_KASAN_H */
+2 -2
arch/arm64/include/asm/mte.h
··· 8 8 #include <asm/compiler.h> 9 9 #include <asm/mte-def.h> 10 10 11 - #ifndef __ASSEMBLY__ 11 + #ifndef __ASSEMBLER__ 12 12 13 13 #include <linux/bitfield.h> 14 14 #include <linux/kasan-enabled.h> ··· 282 282 } 283 283 #endif /* CONFIG_KASAN_HW_TAGS */ 284 284 285 - #endif /* __ASSEMBLY__ */ 285 + #endif /* __ASSEMBLER__ */ 286 286 #endif /* __ASM_MTE_H */
+2 -2
arch/arm64/include/asm/page.h
··· 10 10 11 11 #include <asm/page-def.h> 12 12 13 - #ifndef __ASSEMBLY__ 13 + #ifndef __ASSEMBLER__ 14 14 15 15 #include <linux/personality.h> /* for READ_IMPLIES_EXEC */ 16 16 #include <linux/types.h> /* for gfp_t */ ··· 45 45 46 46 #include <asm/memory.h> 47 47 48 - #endif /* !__ASSEMBLY__ */ 48 + #endif /* !__ASSEMBLER__ */ 49 49 50 50 #define VM_DATA_DEFAULT_FLAGS (VM_DATA_FLAGS_TSK_EXEC | VM_MTE_ALLOWED) 51 51
+38 -87
arch/arm64/include/asm/pgtable-hwdef.h
··· 228 228 /* 229 229 * TCR flags. 230 230 */ 231 - #define TCR_T0SZ_OFFSET 0 232 - #define TCR_T1SZ_OFFSET 16 233 - #define TCR_T0SZ(x) ((UL(64) - (x)) << TCR_T0SZ_OFFSET) 234 - #define TCR_T1SZ(x) ((UL(64) - (x)) << TCR_T1SZ_OFFSET) 235 - #define TCR_TxSZ(x) (TCR_T0SZ(x) | TCR_T1SZ(x)) 236 - #define TCR_TxSZ_WIDTH 6 237 - #define TCR_T0SZ_MASK (((UL(1) << TCR_TxSZ_WIDTH) - 1) << TCR_T0SZ_OFFSET) 238 - #define TCR_T1SZ_MASK (((UL(1) << TCR_TxSZ_WIDTH) - 1) << TCR_T1SZ_OFFSET) 231 + #define TCR_T0SZ(x) ((UL(64) - (x)) << TCR_EL1_T0SZ_SHIFT) 232 + #define TCR_T1SZ(x) ((UL(64) - (x)) << TCR_EL1_T1SZ_SHIFT) 239 233 240 - #define TCR_EPD0_SHIFT 7 241 - #define TCR_EPD0_MASK (UL(1) << TCR_EPD0_SHIFT) 242 - #define TCR_IRGN0_SHIFT 8 243 - #define TCR_IRGN0_MASK (UL(3) << TCR_IRGN0_SHIFT) 244 - #define TCR_IRGN0_NC (UL(0) << TCR_IRGN0_SHIFT) 245 - #define TCR_IRGN0_WBWA (UL(1) << TCR_IRGN0_SHIFT) 246 - #define TCR_IRGN0_WT (UL(2) << TCR_IRGN0_SHIFT) 247 - #define TCR_IRGN0_WBnWA (UL(3) << TCR_IRGN0_SHIFT) 234 + #define TCR_T0SZ_MASK TCR_EL1_T0SZ_MASK 235 + #define TCR_T1SZ_MASK TCR_EL1_T1SZ_MASK 248 236 249 - #define TCR_EPD1_SHIFT 23 250 - #define TCR_EPD1_MASK (UL(1) << TCR_EPD1_SHIFT) 251 - #define TCR_IRGN1_SHIFT 24 252 - #define TCR_IRGN1_MASK (UL(3) << TCR_IRGN1_SHIFT) 253 - #define TCR_IRGN1_NC (UL(0) << TCR_IRGN1_SHIFT) 254 - #define TCR_IRGN1_WBWA (UL(1) << TCR_IRGN1_SHIFT) 255 - #define TCR_IRGN1_WT (UL(2) << TCR_IRGN1_SHIFT) 256 - #define TCR_IRGN1_WBnWA (UL(3) << TCR_IRGN1_SHIFT) 237 + #define TCR_EPD0_MASK TCR_EL1_EPD0_MASK 238 + #define TCR_EPD1_MASK TCR_EL1_EPD1_MASK 257 239 258 - #define TCR_IRGN_NC (TCR_IRGN0_NC | TCR_IRGN1_NC) 259 - #define TCR_IRGN_WBWA (TCR_IRGN0_WBWA | TCR_IRGN1_WBWA) 260 - #define TCR_IRGN_WT (TCR_IRGN0_WT | TCR_IRGN1_WT) 261 - #define TCR_IRGN_WBnWA (TCR_IRGN0_WBnWA | TCR_IRGN1_WBnWA) 262 - #define TCR_IRGN_MASK (TCR_IRGN0_MASK | TCR_IRGN1_MASK) 240 + #define TCR_IRGN0_MASK TCR_EL1_IRGN0_MASK 241 + #define TCR_IRGN0_WBWA (TCR_EL1_IRGN0_WBWA << TCR_EL1_IRGN0_SHIFT) 263 242 243 + #define TCR_ORGN0_MASK TCR_EL1_ORGN0_MASK 244 + #define TCR_ORGN0_WBWA (TCR_EL1_ORGN0_WBWA << TCR_EL1_ORGN0_SHIFT) 264 245 265 - #define TCR_ORGN0_SHIFT 10 266 - #define TCR_ORGN0_MASK (UL(3) << TCR_ORGN0_SHIFT) 267 - #define TCR_ORGN0_NC (UL(0) << TCR_ORGN0_SHIFT) 268 - #define TCR_ORGN0_WBWA (UL(1) << TCR_ORGN0_SHIFT) 269 - #define TCR_ORGN0_WT (UL(2) << TCR_ORGN0_SHIFT) 270 - #define TCR_ORGN0_WBnWA (UL(3) << TCR_ORGN0_SHIFT) 246 + #define TCR_SH0_MASK TCR_EL1_SH0_MASK 247 + #define TCR_SH0_INNER (TCR_EL1_SH0_INNER << TCR_EL1_SH0_SHIFT) 271 248 272 - #define TCR_ORGN1_SHIFT 26 273 - #define TCR_ORGN1_MASK (UL(3) << TCR_ORGN1_SHIFT) 274 - #define TCR_ORGN1_NC (UL(0) << TCR_ORGN1_SHIFT) 275 - #define TCR_ORGN1_WBWA (UL(1) << TCR_ORGN1_SHIFT) 276 - #define TCR_ORGN1_WT (UL(2) << TCR_ORGN1_SHIFT) 277 - #define TCR_ORGN1_WBnWA (UL(3) << TCR_ORGN1_SHIFT) 249 + #define TCR_SH1_MASK TCR_EL1_SH1_MASK 278 250 279 - #define TCR_ORGN_NC (TCR_ORGN0_NC | TCR_ORGN1_NC) 280 - #define TCR_ORGN_WBWA (TCR_ORGN0_WBWA | TCR_ORGN1_WBWA) 281 - #define TCR_ORGN_WT (TCR_ORGN0_WT | TCR_ORGN1_WT) 282 - #define TCR_ORGN_WBnWA (TCR_ORGN0_WBnWA | TCR_ORGN1_WBnWA) 283 - #define TCR_ORGN_MASK (TCR_ORGN0_MASK | TCR_ORGN1_MASK) 251 + #define TCR_TG0_SHIFT TCR_EL1_TG0_SHIFT 252 + #define TCR_TG0_MASK TCR_EL1_TG0_MASK 253 + #define TCR_TG0_4K (TCR_EL1_TG0_4K << TCR_EL1_TG0_SHIFT) 254 + #define TCR_TG0_64K (TCR_EL1_TG0_64K << TCR_EL1_TG0_SHIFT) 255 + #define TCR_TG0_16K (TCR_EL1_TG0_16K << TCR_EL1_TG0_SHIFT) 284 256 285 - #define TCR_SH0_SHIFT 12 286 - #define TCR_SH0_MASK (UL(3) << TCR_SH0_SHIFT) 287 - #define TCR_SH0_INNER (UL(3) << TCR_SH0_SHIFT) 257 + #define TCR_TG1_SHIFT TCR_EL1_TG1_SHIFT 258 + #define TCR_TG1_MASK TCR_EL1_TG1_MASK 259 + #define TCR_TG1_16K (TCR_EL1_TG1_16K << TCR_EL1_TG1_SHIFT) 260 + #define TCR_TG1_4K (TCR_EL1_TG1_4K << TCR_EL1_TG1_SHIFT) 261 + #define TCR_TG1_64K (TCR_EL1_TG1_64K << TCR_EL1_TG1_SHIFT) 288 262 289 - #define TCR_SH1_SHIFT 28 290 - #define TCR_SH1_MASK (UL(3) << TCR_SH1_SHIFT) 291 - #define TCR_SH1_INNER (UL(3) << TCR_SH1_SHIFT) 292 - #define TCR_SHARED (TCR_SH0_INNER | TCR_SH1_INNER) 293 - 294 - #define TCR_TG0_SHIFT 14 295 - #define TCR_TG0_MASK (UL(3) << TCR_TG0_SHIFT) 296 - #define TCR_TG0_4K (UL(0) << TCR_TG0_SHIFT) 297 - #define TCR_TG0_64K (UL(1) << TCR_TG0_SHIFT) 298 - #define TCR_TG0_16K (UL(2) << TCR_TG0_SHIFT) 299 - 300 - #define TCR_TG1_SHIFT 30 301 - #define TCR_TG1_MASK (UL(3) << TCR_TG1_SHIFT) 302 - #define TCR_TG1_16K (UL(1) << TCR_TG1_SHIFT) 303 - #define TCR_TG1_4K (UL(2) << TCR_TG1_SHIFT) 304 - #define TCR_TG1_64K (UL(3) << TCR_TG1_SHIFT) 305 - 306 - #define TCR_IPS_SHIFT 32 307 - #define TCR_IPS_MASK (UL(7) << TCR_IPS_SHIFT) 308 - #define TCR_A1 (UL(1) << 22) 309 - #define TCR_ASID16 (UL(1) << 36) 310 - #define TCR_TBI0 (UL(1) << 37) 311 - #define TCR_TBI1 (UL(1) << 38) 312 - #define TCR_HA (UL(1) << 39) 313 - #define TCR_HD (UL(1) << 40) 314 - #define TCR_HPD0_SHIFT 41 315 - #define TCR_HPD0 (UL(1) << TCR_HPD0_SHIFT) 316 - #define TCR_HPD1_SHIFT 42 317 - #define TCR_HPD1 (UL(1) << TCR_HPD1_SHIFT) 318 - #define TCR_TBID0 (UL(1) << 51) 319 - #define TCR_TBID1 (UL(1) << 52) 320 - #define TCR_NFD0 (UL(1) << 53) 321 - #define TCR_NFD1 (UL(1) << 54) 322 - #define TCR_E0PD0 (UL(1) << 55) 323 - #define TCR_E0PD1 (UL(1) << 56) 324 - #define TCR_TCMA0 (UL(1) << 57) 325 - #define TCR_TCMA1 (UL(1) << 58) 326 - #define TCR_DS (UL(1) << 59) 263 + #define TCR_IPS_SHIFT TCR_EL1_IPS_SHIFT 264 + #define TCR_IPS_MASK TCR_EL1_IPS_MASK 265 + #define TCR_A1 TCR_EL1_A1 266 + #define TCR_ASID16 TCR_EL1_AS 267 + #define TCR_TBI0 TCR_EL1_TBI0 268 + #define TCR_TBI1 TCR_EL1_TBI1 269 + #define TCR_HA TCR_EL1_HA 270 + #define TCR_HD TCR_EL1_HD 271 + #define TCR_HPD0 TCR_EL1_HPD0 272 + #define TCR_HPD1 TCR_EL1_HPD1 273 + #define TCR_TBID0 TCR_EL1_TBID0 274 + #define TCR_TBID1 TCR_EL1_TBID1 275 + #define TCR_E0PD0 TCR_EL1_E0PD0 276 + #define TCR_E0PD1 TCR_EL1_E0PD1 277 + #define TCR_DS TCR_EL1_DS 327 278 328 279 /* 329 280 * TTBR.
+3 -3
arch/arm64/include/asm/pgtable-prot.h
··· 62 62 #define _PAGE_READONLY_EXEC (_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN) 63 63 #define _PAGE_EXECONLY (_PAGE_DEFAULT | PTE_RDONLY | PTE_NG | PTE_PXN) 64 64 65 - #ifndef __ASSEMBLY__ 65 + #ifndef __ASSEMBLER__ 66 66 67 67 #include <asm/cpufeature.h> 68 68 #include <asm/pgtable-types.h> ··· 84 84 #else 85 85 static inline bool __pure lpa2_is_enabled(void) 86 86 { 87 - return read_tcr() & TCR_DS; 87 + return read_tcr() & TCR_EL1_DS; 88 88 } 89 89 90 90 #define PTE_MAYBE_SHARED (lpa2_is_enabled() ? 0 : PTE_SHARED) ··· 127 127 #define PAGE_READONLY_EXEC __pgprot(_PAGE_READONLY_EXEC) 128 128 #define PAGE_EXECONLY __pgprot(_PAGE_EXECONLY) 129 129 130 - #endif /* __ASSEMBLY__ */ 130 + #endif /* __ASSEMBLER__ */ 131 131 132 132 #define pte_pi_index(pte) ( \ 133 133 ((pte & BIT(PTE_PI_IDX_3)) >> (PTE_PI_IDX_3 - 3)) | \
+13 -9
arch/arm64/include/asm/pgtable.h
··· 30 30 31 31 #define vmemmap ((struct page *)VMEMMAP_START - (memstart_addr >> PAGE_SHIFT)) 32 32 33 - #ifndef __ASSEMBLY__ 33 + #ifndef __ASSEMBLER__ 34 34 35 35 #include <asm/cmpxchg.h> 36 36 #include <asm/fixmap.h> ··· 130 130 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ 131 131 132 132 /* 133 - * Outside of a few very special situations (e.g. hibernation), we always 134 - * use broadcast TLB invalidation instructions, therefore a spurious page 135 - * fault on one CPU which has been handled concurrently by another CPU 136 - * does not need to perform additional invalidation. 133 + * We use local TLB invalidation instruction when reusing page in 134 + * write protection fault handler to avoid TLBI broadcast in the hot 135 + * path. This will cause spurious page faults if stale read-only TLB 136 + * entries exist. 137 137 */ 138 - #define flush_tlb_fix_spurious_fault(vma, address, ptep) do { } while (0) 138 + #define flush_tlb_fix_spurious_fault(vma, address, ptep) \ 139 + local_flush_tlb_page_nonotify(vma, address) 140 + 141 + #define flush_tlb_fix_spurious_fault_pmd(vma, address, pmdp) \ 142 + local_flush_tlb_page_nonotify(vma, address) 139 143 140 144 /* 141 145 * ZERO_PAGE is a global shared page that is always zero: used ··· 437 433 * 1 0 | 1 0 1 438 434 * 1 1 | 0 1 x 439 435 * 440 - * When hardware DBM is not present, the sofware PTE_DIRTY bit is updated via 436 + * When hardware DBM is not present, the software PTE_DIRTY bit is updated via 441 437 * the page fault mechanism. Checking the dirty status of a pte becomes: 442 438 * 443 439 * PTE_DIRTY || (PTE_WRITE && !PTE_RDONLY) ··· 603 599 /* 604 600 * pte_present_invalid() tells us that the pte is invalid from HW 605 601 * perspective but present from SW perspective, so the fields are to be 606 - * interpretted as per the HW layout. The second 2 checks are the unique 602 + * interpreted as per the HW layout. The second 2 checks are the unique 607 603 * encoding that we use for PROT_NONE. It is insufficient to only use 608 604 * the first check because we share the same encoding scheme with pmds 609 605 * which support pmd_mkinvalid(), so can be present-invalid without ··· 1953 1949 1954 1950 #endif /* CONFIG_ARM64_CONTPTE */ 1955 1951 1956 - #endif /* !__ASSEMBLY__ */ 1952 + #endif /* !__ASSEMBLER__ */ 1957 1953 1958 1954 #endif /* __ASM_PGTABLE_H */
+2 -2
arch/arm64/include/asm/proc-fns.h
··· 9 9 #ifndef __ASM_PROCFNS_H 10 10 #define __ASM_PROCFNS_H 11 11 12 - #ifndef __ASSEMBLY__ 12 + #ifndef __ASSEMBLER__ 13 13 14 14 #include <asm/page.h> 15 15 ··· 21 21 22 22 #include <asm/memory.h> 23 23 24 - #endif /* __ASSEMBLY__ */ 24 + #endif /* __ASSEMBLER__ */ 25 25 #endif /* __ASM_PROCFNS_H */
+2 -2
arch/arm64/include/asm/processor.h
··· 25 25 26 26 #define MTE_CTRL_STORE_ONLY (1UL << 19) 27 27 28 - #ifndef __ASSEMBLY__ 28 + #ifndef __ASSEMBLER__ 29 29 30 30 #include <linux/build_bug.h> 31 31 #include <linux/cache.h> ··· 437 437 #define GET_TSC_CTL(adr) get_tsc_mode((adr)) 438 438 #define SET_TSC_CTL(val) set_tsc_mode((val)) 439 439 440 - #endif /* __ASSEMBLY__ */ 440 + #endif /* __ASSEMBLER__ */ 441 441 #endif /* __ASM_PROCESSOR_H */
+2 -2
arch/arm64/include/asm/ptrace.h
··· 94 94 */ 95 95 #define NO_SYSCALL (-1) 96 96 97 - #ifndef __ASSEMBLY__ 97 + #ifndef __ASSEMBLER__ 98 98 #include <linux/bug.h> 99 99 #include <linux/types.h> 100 100 ··· 361 361 362 362 extern unsigned long profile_pc(struct pt_regs *regs); 363 363 364 - #endif /* __ASSEMBLY__ */ 364 + #endif /* __ASSEMBLER__ */ 365 365 #endif
+2 -2
arch/arm64/include/asm/rsi_smc.h
··· 122 122 */ 123 123 #define SMC_RSI_ATTESTATION_TOKEN_CONTINUE SMC_RSI_FID(0x195) 124 124 125 - #ifndef __ASSEMBLY__ 125 + #ifndef __ASSEMBLER__ 126 126 127 127 struct realm_config { 128 128 union { ··· 142 142 */ 143 143 } __aligned(0x1000); 144 144 145 - #endif /* __ASSEMBLY__ */ 145 + #endif /* __ASSEMBLER__ */ 146 146 147 147 /* 148 148 * Read configuration for the current Realm.
+2 -2
arch/arm64/include/asm/rwonce.h
··· 5 5 #ifndef __ASM_RWONCE_H 6 6 #define __ASM_RWONCE_H 7 7 8 - #if defined(CONFIG_LTO) && !defined(__ASSEMBLY__) 8 + #if defined(CONFIG_LTO) && !defined(__ASSEMBLER__) 9 9 10 10 #include <linux/compiler_types.h> 11 11 #include <asm/alternative-macros.h> ··· 62 62 }) 63 63 64 64 #endif /* !BUILD_VDSO */ 65 - #endif /* CONFIG_LTO && !__ASSEMBLY__ */ 65 + #endif /* CONFIG_LTO && !__ASSEMBLER__ */ 66 66 67 67 #include <asm-generic/rwonce.h> 68 68
+2 -2
arch/arm64/include/asm/scs.h
··· 2 2 #ifndef _ASM_SCS_H 3 3 #define _ASM_SCS_H 4 4 5 - #ifdef __ASSEMBLY__ 5 + #ifdef __ASSEMBLER__ 6 6 7 7 #include <asm/asm-offsets.h> 8 8 #include <asm/sysreg.h> ··· 55 55 56 56 int __pi_scs_patch(const u8 eh_frame[], int size, bool skip_dry_run); 57 57 58 - #endif /* __ASSEMBLY __ */ 58 + #endif /* __ASSEMBLER__ */ 59 59 60 60 #endif /* _ASM_SCS_H */
+2 -2
arch/arm64/include/asm/sdei.h
··· 9 9 10 10 #define SDEI_STACK_SIZE IRQ_STACK_SIZE 11 11 12 - #ifndef __ASSEMBLY__ 12 + #ifndef __ASSEMBLER__ 13 13 14 14 #include <linux/linkage.h> 15 15 #include <linux/preempt.h> ··· 49 49 unsigned long sdei_arch_get_entry_point(int conduit); 50 50 #define sdei_arch_get_entry_point(x) sdei_arch_get_entry_point(x) 51 51 52 - #endif /* __ASSEMBLY__ */ 52 + #endif /* __ASSEMBLER__ */ 53 53 #endif /* __ASM_SDEI_H */
+1 -1
arch/arm64/include/asm/simd.h
··· 29 29 */ 30 30 return !WARN_ON(!system_capabilities_finalized()) && 31 31 system_supports_fpsimd() && 32 - !in_hardirq() && !irqs_disabled() && !in_nmi(); 32 + !in_hardirq() && !in_nmi(); 33 33 } 34 34 35 35 #else /* ! CONFIG_KERNEL_MODE_NEON */
+2 -2
arch/arm64/include/asm/smp.h
··· 23 23 #define CPU_STUCK_REASON_52_BIT_VA (UL(1) << CPU_STUCK_REASON_SHIFT) 24 24 #define CPU_STUCK_REASON_NO_GRAN (UL(2) << CPU_STUCK_REASON_SHIFT) 25 25 26 - #ifndef __ASSEMBLY__ 26 + #ifndef __ASSEMBLER__ 27 27 28 28 #include <linux/threads.h> 29 29 #include <linux/cpumask.h> ··· 155 155 extern void crash_smp_send_stop(void); 156 156 extern bool smp_crash_stop_failed(void); 157 157 158 - #endif /* ifndef __ASSEMBLY__ */ 158 + #endif /* ifndef __ASSEMBLER__ */ 159 159 160 160 #endif /* ifndef __ASM_SMP_H */
+2 -2
arch/arm64/include/asm/spectre.h
··· 12 12 #define BP_HARDEN_EL2_SLOTS 4 13 13 #define __BP_HARDEN_HYP_VECS_SZ ((BP_HARDEN_EL2_SLOTS - 1) * SZ_2K) 14 14 15 - #ifndef __ASSEMBLY__ 15 + #ifndef __ASSEMBLER__ 16 16 #include <linux/smp.h> 17 17 #include <asm/percpu.h> 18 18 ··· 119 119 __le32 *origptr, __le32 *updptr, int nr_inst); 120 120 void spectre_print_disabled_mitigations(void); 121 121 122 - #endif /* __ASSEMBLY__ */ 122 + #endif /* __ASSEMBLER__ */ 123 123 #endif /* __ASM_SPECTRE_H */
+2 -2
arch/arm64/include/asm/stacktrace/frame.h
··· 25 25 #define FRAME_META_TYPE_FINAL 1 26 26 #define FRAME_META_TYPE_PT_REGS 2 27 27 28 - #ifndef __ASSEMBLY__ 28 + #ifndef __ASSEMBLER__ 29 29 /* 30 30 * A standard AAPCS64 frame record. 31 31 */ ··· 43 43 struct frame_record record; 44 44 u64 type; 45 45 }; 46 - #endif /* __ASSEMBLY */ 46 + #endif /* __ASSEMBLER__ */ 47 47 48 48 #endif /* __ASM_STACKTRACE_FRAME_H */
+1 -1
arch/arm64/include/asm/suspend.h
··· 23 23 * __cpu_suspend_enter()'s caller, and populated by __cpu_suspend_enter(). 24 24 * This data must survive until cpu_resume() is called. 25 25 * 26 - * This struct desribes the size and the layout of the saved cpu state. 26 + * This struct describes the size and the layout of the saved cpu state. 27 27 * The layout of the callee_saved_regs is defined by the implementation 28 28 * of __cpu_suspend_enter(), and cpu_resume(). This struct must be passed 29 29 * in by the caller as __cpu_suspend_enter()'s stack-frame is gone once it
+5 -7
arch/arm64/include/asm/sysreg.h
··· 52 52 53 53 #ifndef CONFIG_BROKEN_GAS_INST 54 54 55 - #ifdef __ASSEMBLY__ 55 + #ifdef __ASSEMBLER__ 56 56 // The space separator is omitted so that __emit_inst(x) can be parsed as 57 57 // either an assembler directive or an assembler macro argument. 58 58 #define __emit_inst(x) .inst(x) ··· 71 71 (((x) >> 24) & 0x000000ff)) 72 72 #endif /* CONFIG_CPU_BIG_ENDIAN */ 73 73 74 - #ifdef __ASSEMBLY__ 74 + #ifdef __ASSEMBLER__ 75 75 #define __emit_inst(x) .long __INSTR_BSWAP(x) 76 - #else /* __ASSEMBLY__ */ 76 + #else /* __ASSEMBLER__ */ 77 77 #define __emit_inst(x) ".long " __stringify(__INSTR_BSWAP(x)) "\n\t" 78 - #endif /* __ASSEMBLY__ */ 78 + #endif /* __ASSEMBLER__ */ 79 79 80 80 #endif /* CONFIG_BROKEN_GAS_INST */ 81 81 ··· 1129 1129 #define gicr_insn(insn) read_sysreg_s(GICV5_OP_GICR_##insn) 1130 1130 #define gic_insn(v, insn) write_sysreg_s(v, GICV5_OP_GIC_##insn) 1131 1131 1132 - #define ARM64_FEATURE_FIELD_BITS 4 1133 - 1134 - #ifdef __ASSEMBLY__ 1132 + #ifdef __ASSEMBLER__ 1135 1133 1136 1134 .macro mrs_s, rt, sreg 1137 1135 __emit_inst(0xd5200000|(\sreg)|(.L__gpr_num_\rt))
+2 -2
arch/arm64/include/asm/system_misc.h
··· 7 7 #ifndef __ASM_SYSTEM_MISC_H 8 8 #define __ASM_SYSTEM_MISC_H 9 9 10 - #ifndef __ASSEMBLY__ 10 + #ifndef __ASSEMBLER__ 11 11 12 12 #include <linux/compiler.h> 13 13 #include <linux/linkage.h> ··· 28 28 struct mm_struct; 29 29 extern void __show_regs(struct pt_regs *); 30 30 31 - #endif /* __ASSEMBLY__ */ 31 + #endif /* __ASSEMBLER__ */ 32 32 33 33 #endif /* __ASM_SYSTEM_MISC_H */
+1 -1
arch/arm64/include/asm/thread_info.h
··· 10 10 11 11 #include <linux/compiler.h> 12 12 13 - #ifndef __ASSEMBLY__ 13 + #ifndef __ASSEMBLER__ 14 14 15 15 struct task_struct; 16 16
+84 -1
arch/arm64/include/asm/tlbflush.h
··· 8 8 #ifndef __ASM_TLBFLUSH_H 9 9 #define __ASM_TLBFLUSH_H 10 10 11 - #ifndef __ASSEMBLY__ 11 + #ifndef __ASSEMBLER__ 12 12 13 13 #include <linux/bitfield.h> 14 14 #include <linux/mm_types.h> ··· 249 249 * cannot be easily determined, the value TLBI_TTL_UNKNOWN will 250 250 * perform a non-hinted invalidation. 251 251 * 252 + * local_flush_tlb_page(vma, addr) 253 + * Local variant of flush_tlb_page(). Stale TLB entries may 254 + * remain in remote CPUs. 255 + * 256 + * local_flush_tlb_page_nonotify(vma, addr) 257 + * Same as local_flush_tlb_page() except MMU notifier will not be 258 + * called. 259 + * 260 + * local_flush_tlb_contpte(vma, addr) 261 + * Invalidate the virtual-address range 262 + * '[addr, addr+CONT_PTE_SIZE)' mapped with contpte on local CPU 263 + * for the user address space corresponding to 'vma->mm'. Stale 264 + * TLB entries may remain in remote CPUs. 252 265 * 253 266 * Finally, take a look at asm/tlb.h to see how tlb_flush() is implemented 254 267 * on top of these routines, since that is our interface to the mmu_gather ··· 293 280 __tlbi_user(aside1is, asid); 294 281 dsb(ish); 295 282 mmu_notifier_arch_invalidate_secondary_tlbs(mm, 0, -1UL); 283 + } 284 + 285 + static inline void __local_flush_tlb_page_nonotify_nosync(struct mm_struct *mm, 286 + unsigned long uaddr) 287 + { 288 + unsigned long addr; 289 + 290 + dsb(nshst); 291 + addr = __TLBI_VADDR(uaddr, ASID(mm)); 292 + __tlbi(vale1, addr); 293 + __tlbi_user(vale1, addr); 294 + } 295 + 296 + static inline void local_flush_tlb_page_nonotify(struct vm_area_struct *vma, 297 + unsigned long uaddr) 298 + { 299 + __local_flush_tlb_page_nonotify_nosync(vma->vm_mm, uaddr); 300 + dsb(nsh); 301 + } 302 + 303 + static inline void local_flush_tlb_page(struct vm_area_struct *vma, 304 + unsigned long uaddr) 305 + { 306 + __local_flush_tlb_page_nonotify_nosync(vma->vm_mm, uaddr); 307 + mmu_notifier_arch_invalidate_secondary_tlbs(vma->vm_mm, uaddr & PAGE_MASK, 308 + (uaddr & PAGE_MASK) + PAGE_SIZE); 309 + dsb(nsh); 296 310 } 297 311 298 312 static inline void __flush_tlb_page_nosync(struct mm_struct *mm, ··· 512 472 dsb(ish); 513 473 } 514 474 475 + static inline void local_flush_tlb_contpte(struct vm_area_struct *vma, 476 + unsigned long addr) 477 + { 478 + unsigned long asid; 479 + 480 + addr = round_down(addr, CONT_PTE_SIZE); 481 + 482 + dsb(nshst); 483 + asid = ASID(vma->vm_mm); 484 + __flush_tlb_range_op(vale1, addr, CONT_PTES, PAGE_SIZE, asid, 485 + 3, true, lpa2_is_enabled()); 486 + mmu_notifier_arch_invalidate_secondary_tlbs(vma->vm_mm, addr, 487 + addr + CONT_PTE_SIZE); 488 + dsb(nsh); 489 + } 490 + 515 491 static inline void flush_tlb_range(struct vm_area_struct *vma, 516 492 unsigned long start, unsigned long end) 517 493 { ··· 580 524 { 581 525 __flush_tlb_range_nosync(mm, start, end, PAGE_SIZE, true, 3); 582 526 } 527 + 528 + static inline bool __pte_flags_need_flush(ptdesc_t oldval, ptdesc_t newval) 529 + { 530 + ptdesc_t diff = oldval ^ newval; 531 + 532 + /* invalid to valid transition requires no flush */ 533 + if (!(oldval & PTE_VALID)) 534 + return false; 535 + 536 + /* Transition in the SW bits requires no flush */ 537 + diff &= ~PTE_SWBITS_MASK; 538 + 539 + return diff; 540 + } 541 + 542 + static inline bool pte_needs_flush(pte_t oldpte, pte_t newpte) 543 + { 544 + return __pte_flags_need_flush(pte_val(oldpte), pte_val(newpte)); 545 + } 546 + #define pte_needs_flush pte_needs_flush 547 + 548 + static inline bool huge_pmd_needs_flush(pmd_t oldpmd, pmd_t newpmd) 549 + { 550 + return __pte_flags_need_flush(pmd_val(oldpmd), pmd_val(newpmd)); 551 + } 552 + #define huge_pmd_needs_flush huge_pmd_needs_flush 553 + 583 554 #endif 584 555 585 556 #endif
+2 -2
arch/arm64/include/asm/vdso.h
··· 7 7 8 8 #define __VDSO_PAGES 4 9 9 10 - #ifndef __ASSEMBLY__ 10 + #ifndef __ASSEMBLER__ 11 11 12 12 #include <generated/vdso-offsets.h> 13 13 ··· 19 19 extern char vdso_start[], vdso_end[]; 20 20 extern char vdso32_start[], vdso32_end[]; 21 21 22 - #endif /* !__ASSEMBLY__ */ 22 + #endif /* !__ASSEMBLER__ */ 23 23 24 24 #endif /* __ASM_VDSO_H */
+2 -2
arch/arm64/include/asm/vdso/compat_barrier.h
··· 5 5 #ifndef __COMPAT_BARRIER_H 6 6 #define __COMPAT_BARRIER_H 7 7 8 - #ifndef __ASSEMBLY__ 8 + #ifndef __ASSEMBLER__ 9 9 /* 10 10 * Warning: This code is meant to be used from the compat vDSO only. 11 11 */ ··· 31 31 #define smp_rmb() aarch32_smp_rmb() 32 32 #define smp_wmb() aarch32_smp_wmb() 33 33 34 - #endif /* !__ASSEMBLY__ */ 34 + #endif /* !__ASSEMBLER__ */ 35 35 36 36 #endif /* __COMPAT_BARRIER_H */
+2 -2
arch/arm64/include/asm/vdso/compat_gettimeofday.h
··· 5 5 #ifndef __ASM_VDSO_COMPAT_GETTIMEOFDAY_H 6 6 #define __ASM_VDSO_COMPAT_GETTIMEOFDAY_H 7 7 8 - #ifndef __ASSEMBLY__ 8 + #ifndef __ASSEMBLER__ 9 9 10 10 #include <asm/barrier.h> 11 11 #include <asm/unistd_compat_32.h> ··· 161 161 } 162 162 #define vdso_clocksource_ok vdso_clocksource_ok 163 163 164 - #endif /* !__ASSEMBLY__ */ 164 + #endif /* !__ASSEMBLER__ */ 165 165 166 166 #endif /* __ASM_VDSO_COMPAT_GETTIMEOFDAY_H */
+2 -2
arch/arm64/include/asm/vdso/getrandom.h
··· 3 3 #ifndef __ASM_VDSO_GETRANDOM_H 4 4 #define __ASM_VDSO_GETRANDOM_H 5 5 6 - #ifndef __ASSEMBLY__ 6 + #ifndef __ASSEMBLER__ 7 7 8 8 #include <asm/unistd.h> 9 9 #include <asm/vdso/vsyscall.h> ··· 33 33 return ret; 34 34 } 35 35 36 - #endif /* !__ASSEMBLY__ */ 36 + #endif /* !__ASSEMBLER__ */ 37 37 38 38 #endif /* __ASM_VDSO_GETRANDOM_H */
+2 -2
arch/arm64/include/asm/vdso/gettimeofday.h
··· 7 7 8 8 #ifdef __aarch64__ 9 9 10 - #ifndef __ASSEMBLY__ 10 + #ifndef __ASSEMBLER__ 11 11 12 12 #include <asm/alternative.h> 13 13 #include <asm/arch_timer.h> ··· 96 96 #define __arch_get_vdso_u_time_data __arch_get_vdso_u_time_data 97 97 #endif /* IS_ENABLED(CONFIG_CC_IS_GCC) && IS_ENABLED(CONFIG_PAGE_SIZE_64KB) */ 98 98 99 - #endif /* !__ASSEMBLY__ */ 99 + #endif /* !__ASSEMBLER__ */ 100 100 101 101 #else /* !__aarch64__ */ 102 102
+2 -2
arch/arm64/include/asm/vdso/processor.h
··· 5 5 #ifndef __ASM_VDSO_PROCESSOR_H 6 6 #define __ASM_VDSO_PROCESSOR_H 7 7 8 - #ifndef __ASSEMBLY__ 8 + #ifndef __ASSEMBLER__ 9 9 10 10 static inline void cpu_relax(void) 11 11 { 12 12 asm volatile("yield" ::: "memory"); 13 13 } 14 14 15 - #endif /* __ASSEMBLY__ */ 15 + #endif /* __ASSEMBLER__ */ 16 16 17 17 #endif /* __ASM_VDSO_PROCESSOR_H */
+2 -2
arch/arm64/include/asm/vdso/vsyscall.h
··· 2 2 #ifndef __ASM_VDSO_VSYSCALL_H 3 3 #define __ASM_VDSO_VSYSCALL_H 4 4 5 - #ifndef __ASSEMBLY__ 5 + #ifndef __ASSEMBLER__ 6 6 7 7 #include <vdso/datapage.h> 8 8 ··· 22 22 /* The asm-generic header needs to be included after the definitions above */ 23 23 #include <asm-generic/vdso/vsyscall.h> 24 24 25 - #endif /* !__ASSEMBLY__ */ 25 + #endif /* !__ASSEMBLER__ */ 26 26 27 27 #endif /* __ASM_VDSO_VSYSCALL_H */
+2 -2
arch/arm64/include/asm/virt.h
··· 56 56 */ 57 57 #define BOOT_CPU_FLAG_E2H BIT_ULL(32) 58 58 59 - #ifndef __ASSEMBLY__ 59 + #ifndef __ASSEMBLER__ 60 60 61 61 #include <asm/ptrace.h> 62 62 #include <asm/sections.h> ··· 161 161 return is_hyp_mode_available() && !is_kernel_in_hyp_mode(); 162 162 } 163 163 164 - #endif /* __ASSEMBLY__ */ 164 + #endif /* __ASSEMBLER__ */ 165 165 166 166 #endif /* ! __ASM__VIRT_H */
-4
arch/arm64/include/asm/vmap_stack.h
··· 3 3 #ifndef __ASM_VMAP_STACK_H 4 4 #define __ASM_VMAP_STACK_H 5 5 6 - #include <linux/bug.h> 7 6 #include <linux/gfp.h> 8 - #include <linux/kconfig.h> 9 7 #include <linux/vmalloc.h> 10 8 #include <linux/pgtable.h> 11 9 #include <asm/memory.h> ··· 16 18 static inline unsigned long *arch_alloc_vmap_stack(size_t stack_size, int node) 17 19 { 18 20 void *p; 19 - 20 - BUILD_BUG_ON(!IS_ENABLED(CONFIG_VMAP_STACK)); 21 21 22 22 p = __vmalloc_node(stack_size, THREAD_ALIGN, THREADINFO_GFP, node, 23 23 __builtin_return_address(0));
+1 -1
arch/arm64/include/uapi/asm/kvm.h
··· 31 31 #define KVM_SPSR_FIQ 4 32 32 #define KVM_NR_SPSR 5 33 33 34 - #ifndef __ASSEMBLY__ 34 + #ifndef __ASSEMBLER__ 35 35 #include <linux/psci.h> 36 36 #include <linux/types.h> 37 37 #include <asm/ptrace.h>
+2 -2
arch/arm64/include/uapi/asm/ptrace.h
··· 80 80 #define PTRACE_PEEKMTETAGS 33 81 81 #define PTRACE_POKEMTETAGS 34 82 82 83 - #ifndef __ASSEMBLY__ 83 + #ifndef __ASSEMBLER__ 84 84 85 85 /* 86 86 * User structures for general purpose, floating point and debug registers. ··· 332 332 __u64 gcspr_el0; 333 333 }; 334 334 335 - #endif /* __ASSEMBLY__ */ 335 + #endif /* __ASSEMBLER__ */ 336 336 337 337 #endif /* _UAPI__ASM_PTRACE_H */
+2 -2
arch/arm64/include/uapi/asm/sigcontext.h
··· 17 17 #ifndef _UAPI__ASM_SIGCONTEXT_H 18 18 #define _UAPI__ASM_SIGCONTEXT_H 19 19 20 - #ifndef __ASSEMBLY__ 20 + #ifndef __ASSEMBLER__ 21 21 22 22 #include <linux/types.h> 23 23 ··· 192 192 __u64 reserved; 193 193 }; 194 194 195 - #endif /* !__ASSEMBLY__ */ 195 + #endif /* !__ASSEMBLER__ */ 196 196 197 197 #include <asm/sve_context.h> 198 198
+2 -2
arch/arm64/kernel/acpi.c
··· 133 133 134 134 /* 135 135 * FADT is required on arm64; retrieve it to check its presence 136 - * and carry out revision and ACPI HW reduced compliancy tests 136 + * and carry out revision and ACPI HW reduced compliance tests 137 137 */ 138 138 status = acpi_get_table(ACPI_SIG_FADT, 0, &table); 139 139 if (ACPI_FAILURE(status)) { ··· 423 423 irq_work_run(); 424 424 __irq_exit(); 425 425 } else { 426 - pr_warn_ratelimited("APEI work queued but not completed"); 426 + pr_warn_ratelimited("APEI work queued but not completed\n"); 427 427 err = -EINPROGRESS; 428 428 } 429 429 }
+3 -3
arch/arm64/kernel/cpufeature.c
··· 1003 1003 1004 1004 /* 1005 1005 * Initialise the CPU feature register from Boot CPU values. 1006 - * Also initiliases the strict_mask for the register. 1006 + * Also initialises the strict_mask for the register. 1007 1007 * Any bits that are not covered by an arm64_ftr_bits entry are considered 1008 1008 * RES0 for the system-wide value, and must strictly match. 1009 1009 */ ··· 1970 1970 1971 1971 static inline void __cpu_enable_hw_dbm(void) 1972 1972 { 1973 - u64 tcr = read_sysreg(tcr_el1) | TCR_HD; 1973 + u64 tcr = read_sysreg(tcr_el1) | TCR_EL1_HD; 1974 1974 1975 1975 write_sysreg(tcr, tcr_el1); 1976 1976 isb(); ··· 2256 2256 static void cpu_enable_e0pd(struct arm64_cpu_capabilities const *cap) 2257 2257 { 2258 2258 if (this_cpu_has_cap(ARM64_HAS_E0PD)) 2259 - sysreg_clear_set(tcr_el1, 0, TCR_E0PD1); 2259 + sysreg_clear_set(tcr_el1, 0, TCR_EL1_E0PD1); 2260 2260 } 2261 2261 #endif /* CONFIG_ARM64_E0PD */ 2262 2262
+40 -6
arch/arm64/kernel/efi.c
··· 10 10 #include <linux/efi.h> 11 11 #include <linux/init.h> 12 12 #include <linux/kmemleak.h> 13 + #include <linux/kthread.h> 13 14 #include <linux/screen_info.h> 14 15 #include <linux/vmalloc.h> 15 16 ··· 166 165 return s; 167 166 } 168 167 169 - static DEFINE_RAW_SPINLOCK(efi_rt_lock); 170 - 171 168 void arch_efi_call_virt_setup(void) 172 169 { 173 - efi_virtmap_load(); 174 - raw_spin_lock(&efi_rt_lock); 170 + efi_runtime_assert_lock_held(); 171 + 172 + if (preemptible() && (current->flags & PF_KTHREAD)) { 173 + /* 174 + * Disable migration to ensure that a preempted EFI runtime 175 + * service call will be resumed on the same CPU. This avoids 176 + * potential issues with EFI runtime calls that are preempted 177 + * while polling for an asynchronous completion of a secure 178 + * firmware call, which may not permit the CPU to change. 179 + */ 180 + migrate_disable(); 181 + kthread_use_mm(&efi_mm); 182 + } else { 183 + efi_virtmap_load(); 184 + } 185 + 186 + /* 187 + * Enable access to the valid TTBR0_EL1 and invoke the errata 188 + * workaround directly since there is no return from exception when 189 + * invoking the EFI run-time services. 190 + */ 191 + uaccess_ttbr0_enable(); 192 + post_ttbr_update_workaround(); 193 + 175 194 __efi_fpsimd_begin(); 176 195 } 177 196 178 197 void arch_efi_call_virt_teardown(void) 179 198 { 180 199 __efi_fpsimd_end(); 181 - raw_spin_unlock(&efi_rt_lock); 182 - efi_virtmap_unload(); 200 + 201 + /* 202 + * Defer the switch to the current thread's TTBR0_EL1 until 203 + * uaccess_enable(). Do so before efi_virtmap_unload() updates the 204 + * saved TTBR0 value, so the userland page tables are not activated 205 + * inadvertently over the back of an exception. 206 + */ 207 + uaccess_ttbr0_disable(); 208 + 209 + if (preemptible() && (current->flags & PF_KTHREAD)) { 210 + kthread_unuse_mm(&efi_mm); 211 + migrate_enable(); 212 + } else { 213 + efi_virtmap_unload(); 214 + } 183 215 } 184 216 185 217 asmlinkage u64 *efi_rt_stack_top __ro_after_init;
+3 -25
arch/arm64/kernel/entry-common.c
··· 34 34 * Handle IRQ/context state management when entering from kernel mode. 35 35 * Before this function is called it is not safe to call regular kernel code, 36 36 * instrumentable code, or any code which may trigger an exception. 37 - * 38 - * This is intended to match the logic in irqentry_enter(), handling the kernel 39 - * mode transitions only. 40 37 */ 41 - static __always_inline irqentry_state_t __enter_from_kernel_mode(struct pt_regs *regs) 42 - { 43 - return irqentry_enter(regs); 44 - } 45 - 46 38 static noinstr irqentry_state_t enter_from_kernel_mode(struct pt_regs *regs) 47 39 { 48 40 irqentry_state_t state; 49 41 50 - state = __enter_from_kernel_mode(regs); 42 + state = irqentry_enter(regs); 51 43 mte_check_tfsr_entry(); 52 44 mte_disable_tco_entry(current); 53 45 ··· 50 58 * Handle IRQ/context state management when exiting to kernel mode. 51 59 * After this function returns it is not safe to call regular kernel code, 52 60 * instrumentable code, or any code which may trigger an exception. 53 - * 54 - * This is intended to match the logic in irqentry_exit(), handling the kernel 55 - * mode transitions only, and with preemption handled elsewhere. 56 61 */ 57 - static __always_inline void __exit_to_kernel_mode(struct pt_regs *regs, 58 - irqentry_state_t state) 59 - { 60 - irqentry_exit(regs, state); 61 - } 62 - 63 62 static void noinstr exit_to_kernel_mode(struct pt_regs *regs, 64 63 irqentry_state_t state) 65 64 { 66 65 mte_check_tfsr_exit(); 67 - __exit_to_kernel_mode(regs, state); 66 + irqentry_exit(regs, state); 68 67 } 69 68 70 69 /* ··· 63 80 * Before this function is called it is not safe to call regular kernel code, 64 81 * instrumentable code, or any code which may trigger an exception. 65 82 */ 66 - static __always_inline void __enter_from_user_mode(struct pt_regs *regs) 83 + static __always_inline void arm64_enter_from_user_mode(struct pt_regs *regs) 67 84 { 68 85 enter_from_user_mode(regs); 69 86 mte_disable_tco_entry(current); 70 - } 71 - 72 - static __always_inline void arm64_enter_from_user_mode(struct pt_regs *regs) 73 - { 74 - __enter_from_user_mode(regs); 75 87 } 76 88 77 89 /*
+1 -1
arch/arm64/kernel/entry-ftrace.S
··· 94 94 stp x29, x30, [sp, #FREGS_SIZE] 95 95 add x29, sp, #FREGS_SIZE 96 96 97 - /* Prepare arguments for the the tracer func */ 97 + /* Prepare arguments for the tracer func */ 98 98 sub x0, x30, #AARCH64_INSN_SIZE // ip (callsite's BL insn) 99 99 mov x1, x9 // parent_ip (callsite's LR) 100 100 mov x3, sp // regs
+21 -8
arch/arm64/kernel/fpsimd.c
··· 225 225 */ 226 226 static void get_cpu_fpsimd_context(void) 227 227 { 228 - if (!IS_ENABLED(CONFIG_PREEMPT_RT)) 229 - local_bh_disable(); 230 - else 228 + if (!IS_ENABLED(CONFIG_PREEMPT_RT)) { 229 + /* 230 + * The softirq subsystem lacks a true unmask/mask API, and 231 + * re-enabling softirq processing using local_bh_enable() will 232 + * not only unmask softirqs, it will also result in immediate 233 + * delivery of any pending softirqs. 234 + * This is undesirable when running with IRQs disabled, but in 235 + * that case, there is no need to mask softirqs in the first 236 + * place, so only bother doing so when IRQs are enabled. 237 + */ 238 + if (!irqs_disabled()) 239 + local_bh_disable(); 240 + } else { 231 241 preempt_disable(); 242 + } 232 243 } 233 244 234 245 /* ··· 251 240 */ 252 241 static void put_cpu_fpsimd_context(void) 253 242 { 254 - if (!IS_ENABLED(CONFIG_PREEMPT_RT)) 255 - local_bh_enable(); 256 - else 243 + if (!IS_ENABLED(CONFIG_PREEMPT_RT)) { 244 + if (!irqs_disabled()) 245 + local_bh_enable(); 246 + } else { 257 247 preempt_enable(); 248 + } 258 249 } 259 250 260 251 unsigned int task_get_vl(const struct task_struct *task, enum vec_type type) ··· 1947 1934 if (!system_supports_fpsimd()) 1948 1935 return; 1949 1936 1950 - WARN_ON(preemptible()); 1951 - 1952 1937 if (may_use_simd()) { 1953 1938 kernel_neon_begin(); 1954 1939 } else { 1940 + WARN_ON(preemptible()); 1941 + 1955 1942 /* 1956 1943 * If !efi_sve_state, SVE can't be in use yet and doesn't need 1957 1944 * preserving:
+1 -1
arch/arm64/kernel/ftrace.c
··· 492 492 return ret; 493 493 494 494 /* 495 - * When using mcount, callsites in modules may have been initalized to 495 + * When using mcount, callsites in modules may have been initialized to 496 496 * call an arbitrary module PLT (which redirects to the _mcount stub) 497 497 * rather than the ftrace PLT we'll use at runtime (which redirects to 498 498 * the ftrace trampoline). We can ignore the old PLT when initializing
+1 -1
arch/arm64/kernel/irq.c
··· 62 62 } 63 63 } 64 64 65 - #ifndef CONFIG_PREEMPT_RT 65 + #ifdef CONFIG_SOFTIRQ_ON_OWN_STACK 66 66 static void ____do_softirq(struct pt_regs *regs) 67 67 { 68 68 __do_softirq();
+1 -1
arch/arm64/kernel/machine_kexec.c
··· 251 251 * marked as Reserved as memory was allocated via memblock_reserve(). 252 252 * 253 253 * In hibernation, the pages which are Reserved and yet "nosave" are excluded 254 - * from the hibernation iamge. crash_is_nosave() does thich check for crash 254 + * from the hibernation image. crash_is_nosave() does thich check for crash 255 255 * dump kernel and will reduce the total size of hibernation image. 256 256 */ 257 257
+4 -4
arch/arm64/kernel/pi/map_kernel.c
··· 141 141 static void noinline __section(".idmap.text") set_ttbr0_for_lpa2(phys_addr_t ttbr) 142 142 { 143 143 u64 sctlr = read_sysreg(sctlr_el1); 144 - u64 tcr = read_sysreg(tcr_el1) | TCR_DS; 144 + u64 tcr = read_sysreg(tcr_el1) | TCR_EL1_DS; 145 145 u64 mmfr0 = read_sysreg(id_aa64mmfr0_el1); 146 146 u64 parange = cpuid_feature_extract_unsigned_field(mmfr0, 147 147 ID_AA64MMFR0_EL1_PARANGE_SHIFT); 148 148 149 - tcr &= ~TCR_IPS_MASK; 150 - tcr |= parange << TCR_IPS_SHIFT; 149 + tcr &= ~TCR_EL1_IPS_MASK; 150 + tcr |= parange << TCR_EL1_IPS_SHIFT; 151 151 152 152 asm(" msr sctlr_el1, %0 ;" 153 153 " isb ;" ··· 263 263 } 264 264 265 265 if (va_bits > VA_BITS_MIN) 266 - sysreg_clear_set(tcr_el1, TCR_T1SZ_MASK, TCR_T1SZ(va_bits)); 266 + sysreg_clear_set(tcr_el1, TCR_EL1_T1SZ_MASK, TCR_T1SZ(va_bits)); 267 267 268 268 /* 269 269 * The virtual KASLR displacement modulo 2MiB is decided by the
+1 -1
arch/arm64/kernel/probes/uprobes.c
··· 131 131 struct uprobe_task *utask = current->utask; 132 132 133 133 /* 134 - * Task has received a fatal signal, so reset back to probbed 134 + * Task has received a fatal signal, so reset back to probed 135 135 * address. 136 136 */ 137 137 instruction_pointer_set(regs, utask->vaddr);
+33 -7
arch/arm64/kernel/ptrace.c
··· 912 912 return -EINVAL; 913 913 914 914 /* 915 - * Apart from SVE_PT_REGS_MASK, all SVE_PT_* flags are consumed by 916 - * vec_set_vector_length(), which will also validate them for us: 915 + * On systems without SVE we accept FPSIMD format writes with 916 + * a VL of 0 to allow exiting streaming mode, otherwise a VL 917 + * is required. 917 918 */ 918 - ret = vec_set_vector_length(target, type, header.vl, 919 - ((unsigned long)header.flags & ~SVE_PT_REGS_MASK) << 16); 920 - if (ret) 921 - return ret; 919 + if (header.vl) { 920 + /* 921 + * If the system does not support SVE we can't 922 + * configure a SVE VL. 923 + */ 924 + if (!system_supports_sve() && type == ARM64_VEC_SVE) 925 + return -EINVAL; 926 + 927 + /* 928 + * Apart from SVE_PT_REGS_MASK, all SVE_PT_* flags are 929 + * consumed by vec_set_vector_length(), which will 930 + * also validate them for us: 931 + */ 932 + ret = vec_set_vector_length(target, type, header.vl, 933 + ((unsigned long)header.flags & ~SVE_PT_REGS_MASK) << 16); 934 + if (ret) 935 + return ret; 936 + } else { 937 + /* If the system supports SVE we require a VL. */ 938 + if (system_supports_sve()) 939 + return -EINVAL; 940 + 941 + /* 942 + * Only FPSIMD formatted data with no flags set is 943 + * supported. 944 + */ 945 + if (header.flags != SVE_PT_REGS_FPSIMD) 946 + return -EINVAL; 947 + } 922 948 923 949 /* Allocate SME storage if necessary, preserving any existing ZA/ZT state */ 924 950 if (type == ARM64_VEC_SME) { ··· 1042 1016 unsigned int pos, unsigned int count, 1043 1017 const void *kbuf, const void __user *ubuf) 1044 1018 { 1045 - if (!system_supports_sve()) 1019 + if (!system_supports_sve() && !system_supports_sme()) 1046 1020 return -EINVAL; 1047 1021 1048 1022 return sve_set_common(target, regset, pos, count, kbuf, ubuf,
+1 -5
arch/arm64/kernel/sdei.c
··· 63 63 { 64 64 int cpu; 65 65 66 - BUILD_BUG_ON(!IS_ENABLED(CONFIG_VMAP_STACK)); 67 - 68 66 for_each_possible_cpu(cpu) { 69 67 _free_sdei_stack(&sdei_stack_normal_ptr, cpu); 70 68 _free_sdei_stack(&sdei_stack_critical_ptr, cpu); ··· 85 87 { 86 88 int cpu; 87 89 int err = 0; 88 - 89 - BUILD_BUG_ON(!IS_ENABLED(CONFIG_VMAP_STACK)); 90 90 91 91 for_each_possible_cpu(cpu) { 92 92 err = _init_sdei_stack(&sdei_stack_normal_ptr, cpu); ··· 198 202 /* 199 203 * do_sdei_event() returns one of: 200 204 * SDEI_EV_HANDLED - success, return to the interrupted context. 201 - * SDEI_EV_FAILED - failure, return this error code to firmare. 205 + * SDEI_EV_FAILED - failure, return this error code to firmware. 202 206 * virtual-address - success, return to this address. 203 207 */ 204 208 unsigned long __kprobes do_sdei_event(struct pt_regs *regs,
+2 -2
arch/arm64/kernel/smp.c
··· 350 350 351 351 /* 352 352 * Now that the dying CPU is beyond the point of no return w.r.t. 353 - * in-kernel synchronisation, try to get the firwmare to help us to 353 + * in-kernel synchronisation, try to get the firmware to help us to 354 354 * verify that it has really left the kernel before we consider 355 355 * clobbering anything it might still be using. 356 356 */ ··· 523 523 524 524 /* 525 525 * Availability of the acpi handle is sufficient to establish 526 - * that _STA has aleady been checked. No need to recheck here. 526 + * that _STA has already been checked. No need to recheck here. 527 527 */ 528 528 c->hotpluggable = arch_cpu_is_hotpluggable(cpu); 529 529
+1 -1
arch/arm64/kernel/syscall.c
··· 96 96 * (Similarly for HVC and SMC elsewhere.) 97 97 */ 98 98 99 - if (flags & _TIF_MTE_ASYNC_FAULT) { 99 + if (unlikely(flags & _TIF_MTE_ASYNC_FAULT)) { 100 100 /* 101 101 * Process the asynchronous tag check fault before the actual 102 102 * syscall. do_notify_resume() will send a signal to userspace
+1 -1
arch/arm64/kernel/traps.c
··· 922 922 __show_regs(regs); 923 923 924 924 /* 925 - * We use nmi_panic to limit the potential for recusive overflows, and 925 + * We use nmi_panic to limit the potential for recursive overflows, and 926 926 * to get a better stack trace. 927 927 */ 928 928 nmi_panic(NULL, "kernel stack overflow");
+1 -1
arch/arm64/kernel/vmcore_info.c
··· 14 14 15 15 static inline u64 get_tcr_el1_t1sz(void) 16 16 { 17 - return (read_sysreg(tcr_el1) & TCR_T1SZ_MASK) >> TCR_T1SZ_OFFSET; 17 + return (read_sysreg(tcr_el1) & TCR_EL1_T1SZ_MASK) >> TCR_EL1_T1SZ_SHIFT; 18 18 } 19 19 20 20 void arch_crash_save_vmcoreinfo(void)
+1 -1
arch/arm64/kvm/arch_timer.c
··· 806 806 tpt = tpc = true; 807 807 808 808 /* 809 - * For the poor sods that could not correctly substract one value 809 + * For the poor sods that could not correctly subtract one value 810 810 * from another, trap the full virtual timer and counter. 811 811 */ 812 812 if (has_broken_cntvoff() && timer_get_offset(map->direct_vtimer))
+1 -1
arch/arm64/kvm/arm.c
··· 2448 2448 kvm_nvhe_sym(__icache_flags) = __icache_flags; 2449 2449 kvm_nvhe_sym(kvm_arm_vmid_bits) = kvm_arm_vmid_bits; 2450 2450 2451 - /* Propagate the FGT state to the the nVHE side */ 2451 + /* Propagate the FGT state to the nVHE side */ 2452 2452 kvm_nvhe_sym(hfgrtr_masks) = hfgrtr_masks; 2453 2453 kvm_nvhe_sym(hfgwtr_masks) = hfgwtr_masks; 2454 2454 kvm_nvhe_sym(hfgitr_masks) = hfgitr_masks;
+1 -1
arch/arm64/kvm/hyp/nvhe/ffa.c
··· 115 115 * 116 116 * FFA-1.3 introduces 64-bit variants of the CPU cycle management 117 117 * interfaces. Moreover, FF-A 1.3 clarifies that SMC32 direct requests 118 - * complete with SMC32 direct reponses which *should* allow us use the 118 + * complete with SMC32 direct responses which *should* allow us use the 119 119 * function ID sent by the caller to determine whether to return x8-x17. 120 120 * 121 121 * Note that we also cannot rely on function IDs in the response.
+1 -1
arch/arm64/kvm/mmu.c
··· 1755 1755 1756 1756 /* 1757 1757 * Check if this is non-struct page memory PFN, and cannot support 1758 - * CMOs. It could potentially be unsafe to access as cachable. 1758 + * CMOs. It could potentially be unsafe to access as cacheable. 1759 1759 */ 1760 1760 if (vm_flags & (VM_PFNMAP | VM_MIXEDMAP) && !pfn_is_map_memory(pfn)) { 1761 1761 if (is_vma_cacheable) {
+1 -1
arch/arm64/kvm/nested.c
··· 85 85 /* 86 86 * Let's treat memory allocation failures as benign: If we fail to 87 87 * allocate anything, return an error and keep the allocated array 88 - * alive. Userspace may try to recover by intializing the vcpu 88 + * alive. Userspace may try to recover by initializing the vcpu 89 89 * again, and there is no reason to affect the whole VM for this. 90 90 */ 91 91 num_mmus = atomic_read(&kvm->online_vcpus) * S2_MMU_PER_VCPU;
+1 -2
arch/arm64/mm/contpte.c
··· 622 622 __ptep_set_access_flags(vma, addr, ptep, entry, 0); 623 623 624 624 if (dirty) 625 - __flush_tlb_range(vma, start_addr, addr, 626 - PAGE_SIZE, true, 3); 625 + local_flush_tlb_contpte(vma, start_addr); 627 626 } else { 628 627 __contpte_try_unfold(vma->vm_mm, addr, ptep, orig_pte); 629 628 __ptep_set_access_flags(vma, addr, ptep, entry, dirty);
+6 -2
arch/arm64/mm/fault.c
··· 233 233 pteval = cmpxchg_relaxed(&pte_val(*ptep), old_pteval, pteval); 234 234 } while (pteval != old_pteval); 235 235 236 - /* Invalidate a stale read-only entry */ 236 + /* 237 + * Invalidate the local stale read-only entry. Remote stale entries 238 + * may still cause page faults and be invalidated via 239 + * flush_tlb_fix_spurious_fault(). 240 + */ 237 241 if (dirty) 238 - flush_tlb_page(vma, address); 242 + local_flush_tlb_page(vma, address); 239 243 return 1; 240 244 } 241 245
+139 -81
arch/arm64/mm/mmu.c
··· 49 49 #define NO_CONT_MAPPINGS BIT(1) 50 50 #define NO_EXEC_MAPPINGS BIT(2) /* assumes FEAT_HPDS is not used */ 51 51 52 + #define INVALID_PHYS_ADDR (-1ULL) 53 + 52 54 DEFINE_STATIC_KEY_FALSE(arm64_ptdump_lock_key); 53 55 54 56 u64 kimage_voffset __ro_after_init; ··· 196 194 } while (ptep++, addr += PAGE_SIZE, addr != end); 197 195 } 198 196 199 - static void alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr, 200 - unsigned long end, phys_addr_t phys, 201 - pgprot_t prot, 202 - phys_addr_t (*pgtable_alloc)(enum pgtable_type), 203 - int flags) 197 + static int alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr, 198 + unsigned long end, phys_addr_t phys, 199 + pgprot_t prot, 200 + phys_addr_t (*pgtable_alloc)(enum pgtable_type), 201 + int flags) 204 202 { 205 203 unsigned long next; 206 204 pmd_t pmd = READ_ONCE(*pmdp); ··· 215 213 pmdval |= PMD_TABLE_PXN; 216 214 BUG_ON(!pgtable_alloc); 217 215 pte_phys = pgtable_alloc(TABLE_PTE); 216 + if (pte_phys == INVALID_PHYS_ADDR) 217 + return -ENOMEM; 218 218 ptep = pte_set_fixmap(pte_phys); 219 219 init_clear_pgtable(ptep); 220 220 ptep += pte_index(addr); ··· 248 244 * walker. 249 245 */ 250 246 pte_clear_fixmap(); 247 + 248 + return 0; 251 249 } 252 250 253 - static void init_pmd(pmd_t *pmdp, unsigned long addr, unsigned long end, 254 - phys_addr_t phys, pgprot_t prot, 255 - phys_addr_t (*pgtable_alloc)(enum pgtable_type), int flags) 251 + static int init_pmd(pmd_t *pmdp, unsigned long addr, unsigned long end, 252 + phys_addr_t phys, pgprot_t prot, 253 + phys_addr_t (*pgtable_alloc)(enum pgtable_type), int flags) 256 254 { 257 255 unsigned long next; 258 256 ··· 275 269 BUG_ON(!pgattr_change_is_safe(pmd_val(old_pmd), 276 270 READ_ONCE(pmd_val(*pmdp)))); 277 271 } else { 278 - alloc_init_cont_pte(pmdp, addr, next, phys, prot, 279 - pgtable_alloc, flags); 272 + int ret; 273 + 274 + ret = alloc_init_cont_pte(pmdp, addr, next, phys, prot, 275 + pgtable_alloc, flags); 276 + if (ret) 277 + return ret; 280 278 281 279 BUG_ON(pmd_val(old_pmd) != 0 && 282 280 pmd_val(old_pmd) != READ_ONCE(pmd_val(*pmdp))); 283 281 } 284 282 phys += next - addr; 285 283 } while (pmdp++, addr = next, addr != end); 284 + 285 + return 0; 286 286 } 287 287 288 - static void alloc_init_cont_pmd(pud_t *pudp, unsigned long addr, 289 - unsigned long end, phys_addr_t phys, 290 - pgprot_t prot, 291 - phys_addr_t (*pgtable_alloc)(enum pgtable_type), 292 - int flags) 288 + static int alloc_init_cont_pmd(pud_t *pudp, unsigned long addr, 289 + unsigned long end, phys_addr_t phys, 290 + pgprot_t prot, 291 + phys_addr_t (*pgtable_alloc)(enum pgtable_type), 292 + int flags) 293 293 { 294 + int ret; 294 295 unsigned long next; 295 296 pud_t pud = READ_ONCE(*pudp); 296 297 pmd_t *pmdp; ··· 314 301 pudval |= PUD_TABLE_PXN; 315 302 BUG_ON(!pgtable_alloc); 316 303 pmd_phys = pgtable_alloc(TABLE_PMD); 304 + if (pmd_phys == INVALID_PHYS_ADDR) 305 + return -ENOMEM; 317 306 pmdp = pmd_set_fixmap(pmd_phys); 318 307 init_clear_pgtable(pmdp); 319 308 pmdp += pmd_index(addr); ··· 335 320 (flags & NO_CONT_MAPPINGS) == 0) 336 321 __prot = __pgprot(pgprot_val(prot) | PTE_CONT); 337 322 338 - init_pmd(pmdp, addr, next, phys, __prot, pgtable_alloc, flags); 323 + ret = init_pmd(pmdp, addr, next, phys, __prot, pgtable_alloc, flags); 324 + if (ret) 325 + goto out; 339 326 340 327 pmdp += pmd_index(next) - pmd_index(addr); 341 328 phys += next - addr; 342 329 } while (addr = next, addr != end); 343 330 331 + out: 344 332 pmd_clear_fixmap(); 333 + 334 + return ret; 345 335 } 346 336 347 - static void alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end, 348 - phys_addr_t phys, pgprot_t prot, 349 - phys_addr_t (*pgtable_alloc)(enum pgtable_type), 350 - int flags) 337 + static int alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end, 338 + phys_addr_t phys, pgprot_t prot, 339 + phys_addr_t (*pgtable_alloc)(enum pgtable_type), 340 + int flags) 351 341 { 342 + int ret = 0; 352 343 unsigned long next; 353 344 p4d_t p4d = READ_ONCE(*p4dp); 354 345 pud_t *pudp; ··· 367 346 p4dval |= P4D_TABLE_PXN; 368 347 BUG_ON(!pgtable_alloc); 369 348 pud_phys = pgtable_alloc(TABLE_PUD); 349 + if (pud_phys == INVALID_PHYS_ADDR) 350 + return -ENOMEM; 370 351 pudp = pud_set_fixmap(pud_phys); 371 352 init_clear_pgtable(pudp); 372 353 pudp += pud_index(addr); ··· 398 375 BUG_ON(!pgattr_change_is_safe(pud_val(old_pud), 399 376 READ_ONCE(pud_val(*pudp)))); 400 377 } else { 401 - alloc_init_cont_pmd(pudp, addr, next, phys, prot, 402 - pgtable_alloc, flags); 378 + ret = alloc_init_cont_pmd(pudp, addr, next, phys, prot, 379 + pgtable_alloc, flags); 380 + if (ret) 381 + goto out; 403 382 404 383 BUG_ON(pud_val(old_pud) != 0 && 405 384 pud_val(old_pud) != READ_ONCE(pud_val(*pudp))); ··· 409 384 phys += next - addr; 410 385 } while (pudp++, addr = next, addr != end); 411 386 387 + out: 412 388 pud_clear_fixmap(); 389 + 390 + return ret; 413 391 } 414 392 415 - static void alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end, 416 - phys_addr_t phys, pgprot_t prot, 417 - phys_addr_t (*pgtable_alloc)(enum pgtable_type), 418 - int flags) 393 + static int alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end, 394 + phys_addr_t phys, pgprot_t prot, 395 + phys_addr_t (*pgtable_alloc)(enum pgtable_type), 396 + int flags) 419 397 { 398 + int ret; 420 399 unsigned long next; 421 400 pgd_t pgd = READ_ONCE(*pgdp); 422 401 p4d_t *p4dp; ··· 433 404 pgdval |= PGD_TABLE_PXN; 434 405 BUG_ON(!pgtable_alloc); 435 406 p4d_phys = pgtable_alloc(TABLE_P4D); 407 + if (p4d_phys == INVALID_PHYS_ADDR) 408 + return -ENOMEM; 436 409 p4dp = p4d_set_fixmap(p4d_phys); 437 410 init_clear_pgtable(p4dp); 438 411 p4dp += p4d_index(addr); ··· 449 418 450 419 next = p4d_addr_end(addr, end); 451 420 452 - alloc_init_pud(p4dp, addr, next, phys, prot, 453 - pgtable_alloc, flags); 421 + ret = alloc_init_pud(p4dp, addr, next, phys, prot, 422 + pgtable_alloc, flags); 423 + if (ret) 424 + goto out; 454 425 455 426 BUG_ON(p4d_val(old_p4d) != 0 && 456 427 p4d_val(old_p4d) != READ_ONCE(p4d_val(*p4dp))); ··· 460 427 phys += next - addr; 461 428 } while (p4dp++, addr = next, addr != end); 462 429 430 + out: 463 431 p4d_clear_fixmap(); 432 + 433 + return ret; 464 434 } 465 435 466 - static void __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys, 467 - unsigned long virt, phys_addr_t size, 468 - pgprot_t prot, 469 - phys_addr_t (*pgtable_alloc)(enum pgtable_type), 470 - int flags) 436 + static int __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys, 437 + unsigned long virt, phys_addr_t size, 438 + pgprot_t prot, 439 + phys_addr_t (*pgtable_alloc)(enum pgtable_type), 440 + int flags) 471 441 { 442 + int ret; 472 443 unsigned long addr, end, next; 473 444 pgd_t *pgdp = pgd_offset_pgd(pgdir, virt); 474 445 ··· 481 444 * within a page, we cannot map the region as the caller expects. 482 445 */ 483 446 if (WARN_ON((phys ^ virt) & ~PAGE_MASK)) 484 - return; 447 + return -EINVAL; 485 448 486 449 phys &= PAGE_MASK; 487 450 addr = virt & PAGE_MASK; ··· 489 452 490 453 do { 491 454 next = pgd_addr_end(addr, end); 492 - alloc_init_p4d(pgdp, addr, next, phys, prot, pgtable_alloc, 493 - flags); 455 + ret = alloc_init_p4d(pgdp, addr, next, phys, prot, pgtable_alloc, 456 + flags); 457 + if (ret) 458 + return ret; 494 459 phys += next - addr; 495 460 } while (pgdp++, addr = next, addr != end); 461 + 462 + return 0; 496 463 } 497 464 498 - static void __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys, 499 - unsigned long virt, phys_addr_t size, 500 - pgprot_t prot, 501 - phys_addr_t (*pgtable_alloc)(enum pgtable_type), 502 - int flags) 465 + static int __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys, 466 + unsigned long virt, phys_addr_t size, 467 + pgprot_t prot, 468 + phys_addr_t (*pgtable_alloc)(enum pgtable_type), 469 + int flags) 503 470 { 471 + int ret; 472 + 504 473 mutex_lock(&fixmap_lock); 505 - __create_pgd_mapping_locked(pgdir, phys, virt, size, prot, 506 - pgtable_alloc, flags); 474 + ret = __create_pgd_mapping_locked(pgdir, phys, virt, size, prot, 475 + pgtable_alloc, flags); 507 476 mutex_unlock(&fixmap_lock); 477 + 478 + return ret; 508 479 } 509 480 510 - #define INVALID_PHYS_ADDR (-1ULL) 481 + static void early_create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys, 482 + unsigned long virt, phys_addr_t size, 483 + pgprot_t prot, 484 + phys_addr_t (*pgtable_alloc)(enum pgtable_type), 485 + int flags) 486 + { 487 + int ret; 488 + 489 + ret = __create_pgd_mapping(pgdir, phys, virt, size, prot, pgtable_alloc, 490 + flags); 491 + if (ret) 492 + panic("Failed to create page tables\n"); 493 + } 511 494 512 495 static phys_addr_t __pgd_pgtable_alloc(struct mm_struct *mm, gfp_t gfp, 513 496 enum pgtable_type pgtable_type) ··· 560 503 } 561 504 562 505 static phys_addr_t 563 - try_pgd_pgtable_alloc_init_mm(enum pgtable_type pgtable_type, gfp_t gfp) 506 + pgd_pgtable_alloc_init_mm_gfp(enum pgtable_type pgtable_type, gfp_t gfp) 564 507 { 565 508 return __pgd_pgtable_alloc(&init_mm, gfp, pgtable_type); 566 509 } ··· 568 511 static phys_addr_t __maybe_unused 569 512 pgd_pgtable_alloc_init_mm(enum pgtable_type pgtable_type) 570 513 { 571 - phys_addr_t pa; 572 - 573 - pa = __pgd_pgtable_alloc(&init_mm, GFP_PGTABLE_KERNEL, pgtable_type); 574 - BUG_ON(pa == INVALID_PHYS_ADDR); 575 - return pa; 514 + return pgd_pgtable_alloc_init_mm_gfp(pgtable_type, GFP_PGTABLE_KERNEL); 576 515 } 577 516 578 517 static phys_addr_t 579 518 pgd_pgtable_alloc_special_mm(enum pgtable_type pgtable_type) 580 519 { 581 - phys_addr_t pa; 582 - 583 - pa = __pgd_pgtable_alloc(NULL, GFP_PGTABLE_KERNEL, pgtable_type); 584 - BUG_ON(pa == INVALID_PHYS_ADDR); 585 - return pa; 520 + return __pgd_pgtable_alloc(NULL, GFP_PGTABLE_KERNEL, pgtable_type); 586 521 } 587 522 588 523 static void split_contpte(pte_t *ptep) ··· 595 546 pte_t *ptep; 596 547 int i; 597 548 598 - pte_phys = try_pgd_pgtable_alloc_init_mm(TABLE_PTE, gfp); 549 + pte_phys = pgd_pgtable_alloc_init_mm_gfp(TABLE_PTE, gfp); 599 550 if (pte_phys == INVALID_PHYS_ADDR) 600 551 return -ENOMEM; 601 552 ptep = (pte_t *)phys_to_virt(pte_phys); ··· 640 591 pmd_t *pmdp; 641 592 int i; 642 593 643 - pmd_phys = try_pgd_pgtable_alloc_init_mm(TABLE_PMD, gfp); 594 + pmd_phys = pgd_pgtable_alloc_init_mm_gfp(TABLE_PMD, gfp); 644 595 if (pmd_phys == INVALID_PHYS_ADDR) 645 596 return -ENOMEM; 646 597 pmdp = (pmd_t *)phys_to_virt(pmd_phys); ··· 984 935 &phys, virt); 985 936 return; 986 937 } 987 - __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, 988 - NO_CONT_MAPPINGS); 938 + early_create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, 939 + NO_CONT_MAPPINGS); 989 940 } 990 941 991 942 void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys, ··· 999 950 if (page_mappings_only) 1000 951 flags = NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS; 1001 952 1002 - __create_pgd_mapping(mm->pgd, phys, virt, size, prot, 1003 - pgd_pgtable_alloc_special_mm, flags); 953 + early_create_pgd_mapping(mm->pgd, phys, virt, size, prot, 954 + pgd_pgtable_alloc_special_mm, flags); 1004 955 } 1005 956 1006 957 static void update_mapping_prot(phys_addr_t phys, unsigned long virt, ··· 1012 963 return; 1013 964 } 1014 965 1015 - __create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, 1016 - NO_CONT_MAPPINGS); 966 + early_create_pgd_mapping(init_mm.pgd, phys, virt, size, prot, NULL, 967 + NO_CONT_MAPPINGS); 1017 968 1018 969 /* flush the TLBs after updating live kernel mappings */ 1019 970 flush_tlb_kernel_range(virt, virt + size); ··· 1022 973 static void __init __map_memblock(pgd_t *pgdp, phys_addr_t start, 1023 974 phys_addr_t end, pgprot_t prot, int flags) 1024 975 { 1025 - __create_pgd_mapping(pgdp, start, __phys_to_virt(start), end - start, 1026 - prot, early_pgtable_alloc, flags); 976 + early_create_pgd_mapping(pgdp, start, __phys_to_virt(start), end - start, 977 + prot, early_pgtable_alloc, flags); 1027 978 } 1028 979 1029 980 void __init mark_linear_text_alias_ro(void) ··· 1256 1207 remap_fn = (void *)__pa_symbol(idmap_kpti_install_ng_mappings); 1257 1208 1258 1209 if (!cpu) { 1210 + int ret; 1211 + 1259 1212 alloc = __get_free_pages(GFP_ATOMIC | __GFP_ZERO, order); 1260 1213 kpti_ng_temp_pgd = (pgd_t *)(alloc + (levels - 1) * PAGE_SIZE); 1261 1214 kpti_ng_temp_alloc = kpti_ng_temp_pgd_pa = __pa(kpti_ng_temp_pgd); ··· 1278 1227 // covers the PTE[] page itself, the remaining entries are free 1279 1228 // to be used as a ad-hoc fixmap. 1280 1229 // 1281 - __create_pgd_mapping_locked(kpti_ng_temp_pgd, __pa(alloc), 1282 - KPTI_NG_TEMP_VA, PAGE_SIZE, PAGE_KERNEL, 1283 - kpti_ng_pgd_alloc, 0); 1230 + ret = __create_pgd_mapping_locked(kpti_ng_temp_pgd, __pa(alloc), 1231 + KPTI_NG_TEMP_VA, PAGE_SIZE, PAGE_KERNEL, 1232 + kpti_ng_pgd_alloc, 0); 1233 + if (ret) 1234 + panic("Failed to create page tables\n"); 1284 1235 } 1285 1236 1286 1237 cpu_install_idmap(); ··· 1335 1282 1336 1283 /* Map only the text into the trampoline page table */ 1337 1284 memset(tramp_pg_dir, 0, PGD_SIZE); 1338 - __create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS, 1339 - entry_tramp_text_size(), prot, 1340 - pgd_pgtable_alloc_init_mm, NO_BLOCK_MAPPINGS); 1285 + early_create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS, 1286 + entry_tramp_text_size(), prot, 1287 + pgd_pgtable_alloc_init_mm, NO_BLOCK_MAPPINGS); 1341 1288 1342 1289 /* Map both the text and data into the kernel page table */ 1343 1290 for (i = 0; i < DIV_ROUND_UP(entry_tramp_text_size(), PAGE_SIZE); i++) ··· 1979 1926 if (force_pte_mapping()) 1980 1927 flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS; 1981 1928 1982 - __create_pgd_mapping(swapper_pg_dir, start, __phys_to_virt(start), 1983 - size, params->pgprot, pgd_pgtable_alloc_init_mm, 1984 - flags); 1929 + ret = __create_pgd_mapping(swapper_pg_dir, start, __phys_to_virt(start), 1930 + size, params->pgprot, pgd_pgtable_alloc_init_mm, 1931 + flags); 1932 + if (ret) 1933 + goto err; 1985 1934 1986 1935 memblock_clear_nomap(start, size); 1987 1936 1988 1937 ret = __add_pages(nid, start >> PAGE_SHIFT, size >> PAGE_SHIFT, 1989 1938 params); 1990 1939 if (ret) 1991 - __remove_pgd_mapping(swapper_pg_dir, 1992 - __phys_to_virt(start), size); 1993 - else { 1994 - /* Address of hotplugged memory can be smaller */ 1995 - max_pfn = max(max_pfn, PFN_UP(start + size)); 1996 - max_low_pfn = max_pfn; 1997 - } 1940 + goto err; 1998 1941 1942 + /* Address of hotplugged memory can be smaller */ 1943 + max_pfn = max(max_pfn, PFN_UP(start + size)); 1944 + max_low_pfn = max_pfn; 1945 + 1946 + return 0; 1947 + 1948 + err: 1949 + __remove_pgd_mapping(swapper_pg_dir, 1950 + __phys_to_virt(start), size); 1999 1951 return ret; 2000 1952 } 2001 1953
+8 -4
arch/arm64/mm/pageattr.c
··· 148 148 unsigned long size = PAGE_SIZE * numpages; 149 149 unsigned long end = start + size; 150 150 struct vm_struct *area; 151 - int i; 151 + int ret; 152 152 153 153 if (!PAGE_ALIGNED(addr)) { 154 154 start &= PAGE_MASK; ··· 184 184 */ 185 185 if (rodata_full && (pgprot_val(set_mask) == PTE_RDONLY || 186 186 pgprot_val(clear_mask) == PTE_RDONLY)) { 187 - for (i = 0; i < area->nr_pages; i++) { 188 - __change_memory_common((u64)page_address(area->pages[i]), 189 - PAGE_SIZE, set_mask, clear_mask); 187 + unsigned long idx = (start - (unsigned long)kasan_reset_tag(area->addr)) 188 + >> PAGE_SHIFT; 189 + for (; numpages; idx++, numpages--) { 190 + ret = __change_memory_common((u64)page_address(area->pages[idx]), 191 + PAGE_SIZE, set_mask, clear_mask); 192 + if (ret) 193 + return ret; 190 194 } 191 195 } 192 196
+1 -1
arch/arm64/mm/pgd.c
··· 56 56 * With 52-bit physical addresses, the architecture requires the 57 57 * top-level table to be aligned to at least 64 bytes. 58 58 */ 59 - BUILD_BUG_ON(PGD_SIZE < 64); 59 + BUILD_BUG_ON(!IS_ALIGNED(PGD_SIZE, 64)); 60 60 #endif 61 61 62 62 /*
+23 -13
arch/arm64/mm/proc.S
··· 23 23 #include <asm/sysreg.h> 24 24 25 25 #ifdef CONFIG_ARM64_64K_PAGES 26 - #define TCR_TG_FLAGS TCR_TG0_64K | TCR_TG1_64K 26 + #define TCR_TG_FLAGS ((TCR_EL1_TG0_64K << TCR_EL1_TG0_SHIFT) |\ 27 + (TCR_EL1_TG1_64K << TCR_EL1_TG1_SHIFT)) 27 28 #elif defined(CONFIG_ARM64_16K_PAGES) 28 - #define TCR_TG_FLAGS TCR_TG0_16K | TCR_TG1_16K 29 + #define TCR_TG_FLAGS ((TCR_EL1_TG0_16K << TCR_EL1_TG0_SHIFT) |\ 30 + (TCR_EL1_TG1_16K << TCR_EL1_TG1_SHIFT)) 29 31 #else /* CONFIG_ARM64_4K_PAGES */ 30 - #define TCR_TG_FLAGS TCR_TG0_4K | TCR_TG1_4K 32 + #define TCR_TG_FLAGS ((TCR_EL1_TG0_4K << TCR_EL1_TG0_SHIFT) |\ 33 + (TCR_EL1_TG1_4K << TCR_EL1_TG1_SHIFT)) 31 34 #endif 32 35 33 36 #ifdef CONFIG_RANDOMIZE_BASE 34 - #define TCR_KASLR_FLAGS TCR_NFD1 37 + #define TCR_KASLR_FLAGS TCR_EL1_NFD1 35 38 #else 36 39 #define TCR_KASLR_FLAGS 0 37 40 #endif ··· 43 40 #define TCR_CACHE_FLAGS TCR_IRGN_WBWA | TCR_ORGN_WBWA 44 41 45 42 #ifdef CONFIG_KASAN_SW_TAGS 46 - #define TCR_KASAN_SW_FLAGS TCR_TBI1 | TCR_TBID1 43 + #define TCR_KASAN_SW_FLAGS TCR_EL1_TBI1 | TCR_EL1_TBID1 47 44 #else 48 45 #define TCR_KASAN_SW_FLAGS 0 49 46 #endif 50 47 51 48 #ifdef CONFIG_KASAN_HW_TAGS 52 - #define TCR_MTE_FLAGS TCR_TCMA1 | TCR_TBI1 | TCR_TBID1 49 + #define TCR_MTE_FLAGS TCR_EL1_TCMA1 | TCR_EL1_TBI1 | TCR_EL1_TBID1 53 50 #elif defined(CONFIG_ARM64_MTE) 54 51 /* 55 52 * The mte_zero_clear_page_tags() implementation uses DC GZVA, which relies on 56 53 * TBI being enabled at EL1. 57 54 */ 58 - #define TCR_MTE_FLAGS TCR_TBI1 | TCR_TBID1 55 + #define TCR_MTE_FLAGS TCR_EL1_TBI1 | TCR_EL1_TBID1 59 56 #else 60 57 #define TCR_MTE_FLAGS 0 61 58 #endif 59 + 60 + #define TCR_IRGN_WBWA ((TCR_EL1_IRGN0_WBWA << TCR_EL1_IRGN0_SHIFT) |\ 61 + (TCR_EL1_IRGN1_WBWA << TCR_EL1_IRGN1_SHIFT)) 62 + #define TCR_ORGN_WBWA ((TCR_EL1_ORGN0_WBWA << TCR_EL1_ORGN0_SHIFT) |\ 63 + (TCR_EL1_ORGN1_WBWA << TCR_EL1_ORGN1_SHIFT)) 64 + #define TCR_SHARED ((TCR_EL1_SH0_INNER << TCR_EL1_SH0_SHIFT) |\ 65 + (TCR_EL1_SH1_INNER << TCR_EL1_SH1_SHIFT)) 62 66 63 67 /* 64 68 * Default MAIR_EL1. MT_NORMAL_TAGGED is initially mapped as Normal memory and ··· 139 129 140 130 /* Don't change t0sz here, mask those bits when restoring */ 141 131 mrs x7, tcr_el1 142 - bfi x8, x7, TCR_T0SZ_OFFSET, TCR_TxSZ_WIDTH 132 + bfi x8, x7, TCR_EL1_T0SZ_SHIFT, TCR_EL1_T0SZ_WIDTH 143 133 144 134 msr tcr_el1, x8 145 135 msr vbar_el1, x9 ··· 491 481 tcr2 .req x15 492 482 mov_q mair, MAIR_EL1_SET 493 483 mov_q tcr, TCR_T0SZ(IDMAP_VA_BITS) | TCR_T1SZ(VA_BITS_MIN) | TCR_CACHE_FLAGS | \ 494 - TCR_SHARED | TCR_TG_FLAGS | TCR_KASLR_FLAGS | TCR_ASID16 | \ 495 - TCR_TBI0 | TCR_A1 | TCR_KASAN_SW_FLAGS | TCR_MTE_FLAGS 484 + TCR_SHARED | TCR_TG_FLAGS | TCR_KASLR_FLAGS | TCR_EL1_AS | \ 485 + TCR_EL1_TBI0 | TCR_EL1_A1 | TCR_KASAN_SW_FLAGS | TCR_MTE_FLAGS 496 486 mov tcr2, xzr 497 487 498 488 tcr_clear_errata_bits tcr, x9, x5 ··· 502 492 alternative_if ARM64_HAS_VA52 503 493 tcr_set_t1sz tcr, x9 504 494 #ifdef CONFIG_ARM64_LPA2 505 - orr tcr, tcr, #TCR_DS 495 + orr tcr, tcr, #TCR_EL1_DS 506 496 #endif 507 497 alternative_else_nop_endif 508 498 #endif ··· 510 500 /* 511 501 * Set the IPS bits in TCR_EL1. 512 502 */ 513 - tcr_compute_pa_size tcr, #TCR_IPS_SHIFT, x5, x6 503 + tcr_compute_pa_size tcr, #TCR_EL1_IPS_SHIFT, x5, x6 514 504 #ifdef CONFIG_ARM64_HW_AFDBM 515 505 /* 516 506 * Enable hardware update of the Access Flags bit. ··· 520 510 mrs x9, ID_AA64MMFR1_EL1 521 511 ubfx x9, x9, ID_AA64MMFR1_EL1_HAFDBS_SHIFT, #4 522 512 cbz x9, 1f 523 - orr tcr, tcr, #TCR_HA // hardware Access flag update 513 + orr tcr, tcr, #TCR_EL1_HA // hardware Access flag update 524 514 #ifdef CONFIG_ARM64_HAFT 525 515 cmp x9, ID_AA64MMFR1_EL1_HAFDBS_HAFT 526 516 b.lt 1f
+1 -1
arch/arm64/net/bpf_jit_comp.c
··· 3054 3054 /* We unwind through both kernel frames starting from within bpf_throw 3055 3055 * call and BPF frames. Therefore we require FP unwinder to be enabled 3056 3056 * to walk kernel frames and reach BPF frames in the stack trace. 3057 - * ARM64 kernel is aways compiled with CONFIG_FRAME_POINTER=y 3057 + * ARM64 kernel is always compiled with CONFIG_FRAME_POINTER=y 3058 3058 */ 3059 3059 return true; 3060 3060 }
+99 -47
arch/arm64/tools/gen-sysreg.awk
··· 44 44 45 45 # Print a CPP macro definition, padded with spaces so that the macro bodies 46 46 # line up in a column 47 - function define(name, val) { 48 - printf "%-56s%s\n", "#define " name, val 47 + function define(prefix, name, val) { 48 + printf "%-56s%s\n", "#define " prefix name, val 49 + } 50 + 51 + # Same as above, but without a prefix 52 + function define_reg(name, val) { 53 + define(null, name, val) 49 54 } 50 55 51 56 # Print standard BITMASK/SHIFT/WIDTH CPP definitions for a field 52 - function define_field(reg, field, msb, lsb) { 53 - define(reg "_" field, "GENMASK(" msb ", " lsb ")") 54 - define(reg "_" field "_MASK", "GENMASK(" msb ", " lsb ")") 55 - define(reg "_" field "_SHIFT", lsb) 56 - define(reg "_" field "_WIDTH", msb - lsb + 1) 57 + function define_field(prefix, reg, field, msb, lsb) { 58 + define(prefix, reg "_" field, "GENMASK(" msb ", " lsb ")") 59 + define(prefix, reg "_" field "_MASK", "GENMASK(" msb ", " lsb ")") 60 + define(prefix, reg "_" field "_SHIFT", lsb) 61 + define(prefix, reg "_" field "_WIDTH", msb - lsb + 1) 57 62 } 58 63 59 64 # Print a field _SIGNED definition for a field 60 - function define_field_sign(reg, field, sign) { 61 - define(reg "_" field "_SIGNED", sign) 65 + function define_field_sign(prefix, reg, field, sign) { 66 + define(prefix, reg "_" field "_SIGNED", sign) 67 + } 68 + 69 + # Print the Res0, Res1, Unkn masks 70 + function define_resx_unkn(prefix, reg, res0, res1, unkn) { 71 + if (res0 != null) 72 + define(prefix, reg "_RES0", "(" res0 ")") 73 + if (res1 != null) 74 + define(prefix, reg "_RES1", "(" res1 ")") 75 + if (unkn != null) 76 + define(prefix, reg "_UNKN", "(" unkn ")") 77 + if (res0 != null || res1 != null || unkn != null) 78 + print "" 62 79 } 63 80 64 81 # Parse a "<msb>[:<lsb>]" string into the global variables @msb and @lsb ··· 145 128 146 129 next_bit = 63 147 130 131 + delete seen_prefixes 132 + 148 133 next 149 134 } 150 135 151 136 $1 == "EndSysregFields" && block_current() == "SysregFields" { 152 137 expect_fields(1) 153 - if (next_bit > 0) 138 + if (next_bit >= 0) 154 139 fatal("Unspecified bits in " reg) 155 140 156 - define(reg "_RES0", "(" res0 ")") 157 - define(reg "_RES1", "(" res1 ")") 158 - define(reg "_UNKN", "(" unkn ")") 159 - print "" 141 + define_resx_unkn(prefix, reg, res0, res1, unkn) 160 142 161 143 reg = null 162 144 res0 = null ··· 186 170 fatal("Duplicate Sysreg definition for " reg) 187 171 defined_regs[reg] = 1 188 172 189 - define("REG_" reg, "S" op0 "_" op1 "_C" crn "_C" crm "_" op2) 190 - define("SYS_" reg, "sys_reg(" op0 ", " op1 ", " crn ", " crm ", " op2 ")") 173 + define_reg("REG_" reg, "S" op0 "_" op1 "_C" crn "_C" crm "_" op2) 174 + define_reg("SYS_" reg, "sys_reg(" op0 ", " op1 ", " crn ", " crm ", " op2 ")") 191 175 192 - define("SYS_" reg "_Op0", op0) 193 - define("SYS_" reg "_Op1", op1) 194 - define("SYS_" reg "_CRn", crn) 195 - define("SYS_" reg "_CRm", crm) 196 - define("SYS_" reg "_Op2", op2) 176 + define_reg("SYS_" reg "_Op0", op0) 177 + define_reg("SYS_" reg "_Op1", op1) 178 + define_reg("SYS_" reg "_CRn", crn) 179 + define_reg("SYS_" reg "_CRm", crm) 180 + define_reg("SYS_" reg "_Op2", op2) 197 181 198 182 print "" 199 183 184 + prefix = null 200 185 next_bit = 63 186 + 187 + delete seen_prefixes 201 188 202 189 next 203 190 } 204 191 205 192 $1 == "EndSysreg" && block_current() == "Sysreg" { 206 193 expect_fields(1) 207 - if (next_bit > 0) 194 + if (next_bit >= 0) 208 195 fatal("Unspecified bits in " reg) 209 196 210 - if (res0 != null) 211 - define(reg "_RES0", "(" res0 ")") 212 - if (res1 != null) 213 - define(reg "_RES1", "(" res1 ")") 214 - if (unkn != null) 215 - define(reg "_UNKN", "(" unkn ")") 216 - if (res0 != null || res1 != null || unkn != null) 217 - print "" 197 + define_resx_unkn(prefix, reg, res0, res1, unkn) 218 198 219 199 reg = null 220 200 op0 = null ··· 221 209 res0 = null 222 210 res1 = null 223 211 unkn = null 212 + prefix = null 224 213 225 214 block_pop() 226 215 next ··· 238 225 print "/* For " reg " fields see " $2 " */" 239 226 print "" 240 227 241 - next_bit = 0 228 + next_bit = -1 242 229 res0 = null 243 230 res1 = null 244 231 unkn = null ··· 246 233 next 247 234 } 248 235 249 - 250 - $1 == "Res0" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 236 + $1 == "Res0" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") { 251 237 expect_fields(2) 252 238 parse_bitdef(reg, "RES0", $2) 253 239 field = "RES0_" msb "_" lsb ··· 256 244 next 257 245 } 258 246 259 - $1 == "Res1" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 247 + $1 == "Res1" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") { 260 248 expect_fields(2) 261 249 parse_bitdef(reg, "RES1", $2) 262 250 field = "RES1_" msb "_" lsb ··· 266 254 next 267 255 } 268 256 269 - $1 == "Unkn" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 257 + $1 == "Unkn" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") { 270 258 expect_fields(2) 271 259 parse_bitdef(reg, "UNKN", $2) 272 260 field = "UNKN_" msb "_" lsb ··· 276 264 next 277 265 } 278 266 279 - $1 == "Field" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 267 + $1 == "Field" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") { 280 268 expect_fields(3) 281 269 field = $3 282 270 parse_bitdef(reg, field, $2) 283 271 284 - define_field(reg, field, msb, lsb) 272 + define_field(prefix, reg, field, msb, lsb) 285 273 print "" 286 274 287 275 next 288 276 } 289 277 290 - $1 == "Raz" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 278 + $1 == "Raz" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") { 291 279 expect_fields(2) 292 280 parse_bitdef(reg, field, $2) 293 281 294 282 next 295 283 } 296 284 297 - $1 == "SignedEnum" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 285 + $1 == "SignedEnum" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") { 298 286 block_push("Enum") 299 287 300 288 expect_fields(3) 301 289 field = $3 302 290 parse_bitdef(reg, field, $2) 303 291 304 - define_field(reg, field, msb, lsb) 305 - define_field_sign(reg, field, "true") 292 + define_field(prefix, reg, field, msb, lsb) 293 + define_field_sign(prefix, reg, field, "true") 306 294 307 295 delete seen_enum_vals 308 296 309 297 next 310 298 } 311 299 312 - $1 == "UnsignedEnum" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 300 + $1 == "UnsignedEnum" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") { 313 301 block_push("Enum") 314 302 315 303 expect_fields(3) 316 304 field = $3 317 305 parse_bitdef(reg, field, $2) 318 306 319 - define_field(reg, field, msb, lsb) 320 - define_field_sign(reg, field, "false") 307 + define_field(prefix, reg, field, msb, lsb) 308 + define_field_sign(prefix, reg, field, "false") 321 309 322 310 delete seen_enum_vals 323 311 324 312 next 325 313 } 326 314 327 - $1 == "Enum" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 315 + $1 == "Enum" && (block_current() == "Sysreg" || block_current() == "SysregFields" || block_current() == "Prefix") { 328 316 block_push("Enum") 329 317 330 318 expect_fields(3) 331 319 field = $3 332 320 parse_bitdef(reg, field, $2) 333 321 334 - define_field(reg, field, msb, lsb) 322 + define_field(prefix, reg, field, msb, lsb) 335 323 336 324 delete seen_enum_vals 337 325 ··· 361 349 fatal("Duplicate Enum value " val " for " name) 362 350 seen_enum_vals[val] = 1 363 351 364 - define(reg "_" field "_" name, "UL(" val ")") 352 + define(prefix, reg "_" field "_" name, "UL(" val ")") 353 + next 354 + } 355 + 356 + $1 == "Prefix" && (block_current() == "Sysreg" || block_current() == "SysregFields") { 357 + block_push("Prefix") 358 + 359 + expect_fields(2) 360 + 361 + if (next_bit < 63) 362 + fatal("Prefixed fields must precede non-prefixed fields (" reg ")") 363 + 364 + prefix = $2 "_" 365 + 366 + if (prefix in seen_prefixes) 367 + fatal("Duplicate prefix " prefix " for " reg) 368 + seen_prefixes[prefix] = 1 369 + 370 + res0 = "UL(0)" 371 + res1 = "UL(0)" 372 + unkn = "UL(0)" 373 + next_bit = 63 374 + 375 + next 376 + } 377 + 378 + $1 == "EndPrefix" && block_current() == "Prefix" { 379 + expect_fields(1) 380 + if (next_bit >= 0) 381 + fatal("Unspecified bits in prefix " prefix " for " reg) 382 + 383 + define_resx_unkn(prefix, reg, res0, res1, unkn) 384 + 385 + prefix = null 386 + res0 = "UL(0)" 387 + res1 = "UL(0)" 388 + unkn = "UL(0)" 389 + next_bit = 63 390 + 391 + block_pop() 392 + 365 393 next 366 394 } 367 395
+21
arch/arm64/tools/sysreg
··· 4669 4669 Field 0 En 4670 4670 EndSysreg 4671 4671 4672 + Sysreg ICH_VMCR_EL2 3 4 12 11 7 4673 + Prefix FEAT_GCIE 4674 + Res0 63:32 4675 + Field 31:27 VPMR 4676 + Res0 26:1 4677 + Field 0 EN 4678 + EndPrefix 4679 + Res0 63:32 4680 + Field 31:24 VPMR 4681 + Field 23:21 VBPR0 4682 + Field 20:18 VBPR1 4683 + Res0 17:10 4684 + Field 9 VEOIM 4685 + Res0 8:5 4686 + Field 4 VCBPR 4687 + Field 3 VFIQEn 4688 + Field 2 VAckCtl 4689 + Field 1 VENG1 4690 + Field 0 VENG0 4691 + EndSysreg 4692 + 4672 4693 Sysreg CONTEXTIDR_EL2 3 4 13 0 1 4673 4694 Fields CONTEXTIDR_ELx 4674 4695 EndSysreg
+2
drivers/Kconfig
··· 251 251 252 252 source "drivers/cdx/Kconfig" 253 253 254 + source "drivers/resctrl/Kconfig" 255 + 254 256 endmenu
+1
drivers/Makefile
··· 194 194 obj-$(CONFIG_DRM_ACCEL) += accel/ 195 195 obj-$(CONFIG_CDX_BUS) += cdx/ 196 196 obj-$(CONFIG_DPLL) += dpll/ 197 + obj-y += resctrl/ 197 198 198 199 obj-$(CONFIG_DIBS) += dibs/ 199 200 obj-$(CONFIG_S390) += s390/
+3
drivers/acpi/arm64/Kconfig
··· 21 21 22 22 config ACPI_APMT 23 23 bool 24 + 25 + config ACPI_MPAM 26 + bool
+1
drivers/acpi/arm64/Makefile
··· 4 4 obj-$(CONFIG_ACPI_FFH) += ffh.o 5 5 obj-$(CONFIG_ACPI_GTDT) += gtdt.o 6 6 obj-$(CONFIG_ACPI_IORT) += iort.o 7 + obj-$(CONFIG_ACPI_MPAM) += mpam.o 7 8 obj-$(CONFIG_ACPI_PROCESSOR_IDLE) += cpuidle.o 8 9 obj-$(CONFIG_ARM_AMBA) += amba.o 9 10 obj-y += dma.o init.o
-34
drivers/acpi/arm64/gtdt.c
··· 303 303 return -EINVAL; 304 304 } 305 305 306 - /** 307 - * acpi_arch_timer_mem_init() - Get the info of all GT blocks in GTDT table. 308 - * @timer_mem: The pointer to the array of struct arch_timer_mem for returning 309 - * the result of parsing. The element number of this array should 310 - * be platform_timer_count(the total number of platform timers). 311 - * @timer_count: It points to a integer variable which is used for storing the 312 - * number of GT blocks we have parsed. 313 - * 314 - * Return: 0 if success, -EINVAL/-ENODEV if error. 315 - */ 316 - int __init acpi_arch_timer_mem_init(struct arch_timer_mem *timer_mem, 317 - int *timer_count) 318 - { 319 - int ret; 320 - void *platform_timer; 321 - 322 - *timer_count = 0; 323 - for_each_platform_timer(platform_timer) { 324 - if (is_timer_block(platform_timer)) { 325 - ret = gtdt_parse_timer_block(platform_timer, timer_mem); 326 - if (ret) 327 - return ret; 328 - timer_mem++; 329 - (*timer_count)++; 330 - } 331 - } 332 - 333 - if (*timer_count) 334 - pr_info("found %d memory-mapped timer block(s).\n", 335 - *timer_count); 336 - 337 - return 0; 338 - } 339 - 340 306 /* 341 307 * Initialize a SBSA generic Watchdog platform device info from GTDT 342 308 */
+411
drivers/acpi/arm64/mpam.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (C) 2025 Arm Ltd. 3 + 4 + /* Parse the MPAM ACPI table feeding the discovered nodes into the driver */ 5 + 6 + #define pr_fmt(fmt) "ACPI MPAM: " fmt 7 + 8 + #include <linux/acpi.h> 9 + #include <linux/arm_mpam.h> 10 + #include <linux/bits.h> 11 + #include <linux/cpu.h> 12 + #include <linux/cpumask.h> 13 + #include <linux/platform_device.h> 14 + 15 + #include <acpi/processor.h> 16 + 17 + /* 18 + * Flags for acpi_table_mpam_msc.*_interrupt_flags. 19 + * See 2.1.1 Interrupt Flags, Table 5, of DEN0065B_MPAM_ACPI_3.0-bet. 20 + */ 21 + #define ACPI_MPAM_MSC_IRQ_MODE BIT(0) 22 + #define ACPI_MPAM_MSC_IRQ_TYPE_MASK GENMASK(2, 1) 23 + #define ACPI_MPAM_MSC_IRQ_TYPE_WIRED 0 24 + #define ACPI_MPAM_MSC_IRQ_AFFINITY_TYPE_MASK BIT(3) 25 + #define ACPI_MPAM_MSC_IRQ_AFFINITY_TYPE_PROCESSOR 0 26 + #define ACPI_MPAM_MSC_IRQ_AFFINITY_TYPE_PROCESSOR_CONTAINER 1 27 + #define ACPI_MPAM_MSC_IRQ_AFFINITY_VALID BIT(4) 28 + 29 + /* 30 + * Encodings for the MSC node body interface type field. 31 + * See 2.1 MPAM MSC node, Table 4 of DEN0065B_MPAM_ACPI_3.0-bet. 32 + */ 33 + #define ACPI_MPAM_MSC_IFACE_MMIO 0x00 34 + #define ACPI_MPAM_MSC_IFACE_PCC 0x0a 35 + 36 + static bool _is_ppi_partition(u32 flags) 37 + { 38 + u32 aff_type, is_ppi; 39 + bool ret; 40 + 41 + is_ppi = FIELD_GET(ACPI_MPAM_MSC_IRQ_AFFINITY_VALID, flags); 42 + if (!is_ppi) 43 + return false; 44 + 45 + aff_type = FIELD_GET(ACPI_MPAM_MSC_IRQ_AFFINITY_TYPE_MASK, flags); 46 + ret = (aff_type == ACPI_MPAM_MSC_IRQ_AFFINITY_TYPE_PROCESSOR_CONTAINER); 47 + if (ret) 48 + pr_err_once("Partitioned interrupts not supported\n"); 49 + 50 + return ret; 51 + } 52 + 53 + static int acpi_mpam_register_irq(struct platform_device *pdev, 54 + u32 intid, u32 flags) 55 + { 56 + int irq; 57 + u32 int_type; 58 + int trigger; 59 + 60 + if (!intid) 61 + return -EINVAL; 62 + 63 + if (_is_ppi_partition(flags)) 64 + return -EINVAL; 65 + 66 + trigger = FIELD_GET(ACPI_MPAM_MSC_IRQ_MODE, flags); 67 + int_type = FIELD_GET(ACPI_MPAM_MSC_IRQ_TYPE_MASK, flags); 68 + if (int_type != ACPI_MPAM_MSC_IRQ_TYPE_WIRED) 69 + return -EINVAL; 70 + 71 + irq = acpi_register_gsi(&pdev->dev, intid, trigger, ACPI_ACTIVE_HIGH); 72 + if (irq < 0) 73 + pr_err_once("Failed to register interrupt 0x%x with ACPI\n", intid); 74 + 75 + return irq; 76 + } 77 + 78 + static void acpi_mpam_parse_irqs(struct platform_device *pdev, 79 + struct acpi_mpam_msc_node *tbl_msc, 80 + struct resource *res, int *res_idx) 81 + { 82 + u32 flags, intid; 83 + int irq; 84 + 85 + intid = tbl_msc->overflow_interrupt; 86 + flags = tbl_msc->overflow_interrupt_flags; 87 + irq = acpi_mpam_register_irq(pdev, intid, flags); 88 + if (irq > 0) 89 + res[(*res_idx)++] = DEFINE_RES_IRQ_NAMED(irq, "overflow"); 90 + 91 + intid = tbl_msc->error_interrupt; 92 + flags = tbl_msc->error_interrupt_flags; 93 + irq = acpi_mpam_register_irq(pdev, intid, flags); 94 + if (irq > 0) 95 + res[(*res_idx)++] = DEFINE_RES_IRQ_NAMED(irq, "error"); 96 + } 97 + 98 + static int acpi_mpam_parse_resource(struct mpam_msc *msc, 99 + struct acpi_mpam_resource_node *res) 100 + { 101 + int level, nid; 102 + u32 cache_id; 103 + 104 + switch (res->locator_type) { 105 + case ACPI_MPAM_LOCATION_TYPE_PROCESSOR_CACHE: 106 + cache_id = res->locator.cache_locator.cache_reference; 107 + level = find_acpi_cache_level_from_id(cache_id); 108 + if (level <= 0) { 109 + pr_err_once("Bad level (%d) for cache with id %u\n", level, cache_id); 110 + return -EINVAL; 111 + } 112 + return mpam_ris_create(msc, res->ris_index, MPAM_CLASS_CACHE, 113 + level, cache_id); 114 + case ACPI_MPAM_LOCATION_TYPE_MEMORY: 115 + nid = pxm_to_node(res->locator.memory_locator.proximity_domain); 116 + if (nid == NUMA_NO_NODE) { 117 + pr_debug("Bad proximity domain %lld, using node 0 instead\n", 118 + res->locator.memory_locator.proximity_domain); 119 + nid = 0; 120 + } 121 + return mpam_ris_create(msc, res->ris_index, MPAM_CLASS_MEMORY, 122 + MPAM_CLASS_ID_DEFAULT, nid); 123 + default: 124 + /* These get discovered later and are treated as unknown */ 125 + return 0; 126 + } 127 + } 128 + 129 + int acpi_mpam_parse_resources(struct mpam_msc *msc, 130 + struct acpi_mpam_msc_node *tbl_msc) 131 + { 132 + int i, err; 133 + char *ptr, *table_end; 134 + struct acpi_mpam_resource_node *resource; 135 + 136 + table_end = (char *)tbl_msc + tbl_msc->length; 137 + ptr = (char *)(tbl_msc + 1); 138 + for (i = 0; i < tbl_msc->num_resource_nodes; i++) { 139 + u64 max_deps, remaining_table; 140 + 141 + if (ptr + sizeof(*resource) > table_end) 142 + return -EINVAL; 143 + 144 + resource = (struct acpi_mpam_resource_node *)ptr; 145 + 146 + remaining_table = table_end - ptr; 147 + max_deps = remaining_table / sizeof(struct acpi_mpam_func_deps); 148 + if (resource->num_functional_deps > max_deps) { 149 + pr_debug("MSC has impossible number of functional dependencies\n"); 150 + return -EINVAL; 151 + } 152 + 153 + err = acpi_mpam_parse_resource(msc, resource); 154 + if (err) 155 + return err; 156 + 157 + ptr += sizeof(*resource); 158 + ptr += resource->num_functional_deps * sizeof(struct acpi_mpam_func_deps); 159 + } 160 + 161 + return 0; 162 + } 163 + 164 + /* 165 + * Creates the device power management link and returns true if the 166 + * acpi id is valid and usable for cpu affinity. This is the case 167 + * when the linked device is a processor or a processor container. 168 + */ 169 + static bool __init parse_msc_pm_link(struct acpi_mpam_msc_node *tbl_msc, 170 + struct platform_device *pdev, 171 + u32 *acpi_id) 172 + { 173 + char hid[sizeof(tbl_msc->hardware_id_linked_device) + 1] = { 0 }; 174 + bool acpi_id_valid = false; 175 + struct acpi_device *buddy; 176 + char uid[11]; 177 + int len; 178 + 179 + memcpy(hid, &tbl_msc->hardware_id_linked_device, 180 + sizeof(tbl_msc->hardware_id_linked_device)); 181 + 182 + if (!strcmp(hid, ACPI_PROCESSOR_CONTAINER_HID)) { 183 + *acpi_id = tbl_msc->instance_id_linked_device; 184 + acpi_id_valid = true; 185 + } 186 + 187 + len = snprintf(uid, sizeof(uid), "%u", 188 + tbl_msc->instance_id_linked_device); 189 + if (len >= sizeof(uid)) { 190 + pr_debug("Failed to convert uid of device for power management."); 191 + return acpi_id_valid; 192 + } 193 + 194 + buddy = acpi_dev_get_first_match_dev(hid, uid, -1); 195 + if (buddy) { 196 + device_link_add(&pdev->dev, &buddy->dev, DL_FLAG_STATELESS); 197 + acpi_dev_put(buddy); 198 + } 199 + 200 + return acpi_id_valid; 201 + } 202 + 203 + static int decode_interface_type(struct acpi_mpam_msc_node *tbl_msc, 204 + enum mpam_msc_iface *iface) 205 + { 206 + switch (tbl_msc->interface_type) { 207 + case ACPI_MPAM_MSC_IFACE_MMIO: 208 + *iface = MPAM_IFACE_MMIO; 209 + return 0; 210 + case ACPI_MPAM_MSC_IFACE_PCC: 211 + *iface = MPAM_IFACE_PCC; 212 + return 0; 213 + default: 214 + return -EINVAL; 215 + } 216 + } 217 + 218 + static struct platform_device * __init acpi_mpam_parse_msc(struct acpi_mpam_msc_node *tbl_msc) 219 + { 220 + struct platform_device *pdev __free(platform_device_put) = 221 + platform_device_alloc("mpam_msc", tbl_msc->identifier); 222 + int next_res = 0, next_prop = 0, err; 223 + /* pcc, nrdy, affinity and a sentinel */ 224 + struct property_entry props[4] = { 0 }; 225 + /* mmio, 2xirq, no sentinel. */ 226 + struct resource res[3] = { 0 }; 227 + struct acpi_device *companion; 228 + enum mpam_msc_iface iface; 229 + char uid[16]; 230 + u32 acpi_id; 231 + 232 + if (!pdev) 233 + return ERR_PTR(-ENOMEM); 234 + 235 + /* Some power management is described in the namespace: */ 236 + err = snprintf(uid, sizeof(uid), "%u", tbl_msc->identifier); 237 + if (err > 0 && err < sizeof(uid)) { 238 + companion = acpi_dev_get_first_match_dev("ARMHAA5C", uid, -1); 239 + if (companion) { 240 + ACPI_COMPANION_SET(&pdev->dev, companion); 241 + acpi_dev_put(companion); 242 + } else { 243 + pr_debug("MSC.%u: missing namespace entry\n", tbl_msc->identifier); 244 + } 245 + } 246 + 247 + if (decode_interface_type(tbl_msc, &iface)) { 248 + pr_debug("MSC.%u: unknown interface type\n", tbl_msc->identifier); 249 + return ERR_PTR(-EINVAL); 250 + } 251 + 252 + if (iface == MPAM_IFACE_MMIO) { 253 + res[next_res++] = DEFINE_RES_MEM_NAMED(tbl_msc->base_address, 254 + tbl_msc->mmio_size, 255 + "MPAM:MSC"); 256 + } else if (iface == MPAM_IFACE_PCC) { 257 + props[next_prop++] = PROPERTY_ENTRY_U32("pcc-channel", 258 + tbl_msc->base_address); 259 + } 260 + 261 + acpi_mpam_parse_irqs(pdev, tbl_msc, res, &next_res); 262 + 263 + WARN_ON_ONCE(next_res > ARRAY_SIZE(res)); 264 + err = platform_device_add_resources(pdev, res, next_res); 265 + if (err) 266 + return ERR_PTR(err); 267 + 268 + props[next_prop++] = PROPERTY_ENTRY_U32("arm,not-ready-us", 269 + tbl_msc->max_nrdy_usec); 270 + 271 + /* 272 + * The MSC's CPU affinity is described via its linked power 273 + * management device, but only if it points at a Processor or 274 + * Processor Container. 275 + */ 276 + if (parse_msc_pm_link(tbl_msc, pdev, &acpi_id)) 277 + props[next_prop++] = PROPERTY_ENTRY_U32("cpu_affinity", acpi_id); 278 + 279 + WARN_ON_ONCE(next_prop > ARRAY_SIZE(props) - 1); 280 + err = device_create_managed_software_node(&pdev->dev, props, NULL); 281 + if (err) 282 + return ERR_PTR(err); 283 + 284 + /* 285 + * Stash the table entry for acpi_mpam_parse_resources() to discover 286 + * what this MSC controls. 287 + */ 288 + err = platform_device_add_data(pdev, tbl_msc, tbl_msc->length); 289 + if (err) 290 + return ERR_PTR(err); 291 + 292 + err = platform_device_add(pdev); 293 + if (err) 294 + return ERR_PTR(err); 295 + 296 + return_ptr(pdev); 297 + } 298 + 299 + static int __init acpi_mpam_parse(void) 300 + { 301 + char *table_end, *table_offset; 302 + struct acpi_mpam_msc_node *tbl_msc; 303 + struct platform_device *pdev; 304 + 305 + if (acpi_disabled || !system_supports_mpam()) 306 + return 0; 307 + 308 + struct acpi_table_header *table __free(acpi_put_table) = 309 + acpi_get_table_pointer(ACPI_SIG_MPAM, 0); 310 + 311 + if (IS_ERR(table)) 312 + return 0; 313 + 314 + if (table->revision < 1) { 315 + pr_debug("MPAM ACPI table revision %d not supported\n", table->revision); 316 + return 0; 317 + } 318 + 319 + table_offset = (char *)(table + 1); 320 + table_end = (char *)table + table->length; 321 + 322 + while (table_offset < table_end) { 323 + tbl_msc = (struct acpi_mpam_msc_node *)table_offset; 324 + if (table_offset + sizeof(*tbl_msc) > table_end || 325 + table_offset + tbl_msc->length > table_end) { 326 + pr_err("MSC entry overlaps end of ACPI table\n"); 327 + return -EINVAL; 328 + } 329 + table_offset += tbl_msc->length; 330 + 331 + /* 332 + * If any of the reserved fields are set, make no attempt to 333 + * parse the MSC structure. This MSC will still be counted by 334 + * acpi_mpam_count_msc(), meaning the MPAM driver can't probe 335 + * against all MSC, and will never be enabled. There is no way 336 + * to enable it safely, because we cannot determine safe 337 + * system-wide partid and pmg ranges in this situation. 338 + */ 339 + if (tbl_msc->reserved || tbl_msc->reserved1 || tbl_msc->reserved2) { 340 + pr_err_once("Unrecognised MSC, MPAM not usable\n"); 341 + pr_debug("MSC.%u: reserved field set\n", tbl_msc->identifier); 342 + continue; 343 + } 344 + 345 + if (!tbl_msc->mmio_size) { 346 + pr_debug("MSC.%u: marked as disabled\n", tbl_msc->identifier); 347 + continue; 348 + } 349 + 350 + pdev = acpi_mpam_parse_msc(tbl_msc); 351 + if (IS_ERR(pdev)) 352 + return PTR_ERR(pdev); 353 + } 354 + 355 + return 0; 356 + } 357 + 358 + /** 359 + * acpi_mpam_count_msc() - Count the number of MSC described by firmware. 360 + * 361 + * Returns the number of MSCs, or zero for an error. 362 + * 363 + * This can be called before or in parallel with acpi_mpam_parse(). 364 + */ 365 + int acpi_mpam_count_msc(void) 366 + { 367 + char *table_end, *table_offset; 368 + struct acpi_mpam_msc_node *tbl_msc; 369 + int count = 0; 370 + 371 + if (acpi_disabled || !system_supports_mpam()) 372 + return 0; 373 + 374 + struct acpi_table_header *table __free(acpi_put_table) = 375 + acpi_get_table_pointer(ACPI_SIG_MPAM, 0); 376 + 377 + if (IS_ERR(table)) 378 + return 0; 379 + 380 + if (table->revision < 1) 381 + return 0; 382 + 383 + table_offset = (char *)(table + 1); 384 + table_end = (char *)table + table->length; 385 + 386 + while (table_offset < table_end) { 387 + tbl_msc = (struct acpi_mpam_msc_node *)table_offset; 388 + 389 + if (table_offset + sizeof(*tbl_msc) > table_end) 390 + return -EINVAL; 391 + if (tbl_msc->length < sizeof(*tbl_msc)) 392 + return -EINVAL; 393 + if (tbl_msc->length > table_end - table_offset) 394 + return -EINVAL; 395 + table_offset += tbl_msc->length; 396 + 397 + if (!tbl_msc->mmio_size) 398 + continue; 399 + 400 + count++; 401 + } 402 + 403 + return count; 404 + } 405 + 406 + /* 407 + * Call after ACPI devices have been created, which happens behind acpi_scan_init() 408 + * called from subsys_initcall(). PCC requires the mailbox driver, which is 409 + * initialised from postcore_initcall(). 410 + */ 411 + subsys_initcall_sync(acpi_mpam_parse);
+263 -17
drivers/acpi/pptt.c
··· 21 21 #include <linux/cacheinfo.h> 22 22 #include <acpi/processor.h> 23 23 24 + /* 25 + * The acpi_pptt_cache_v1 in actbl2.h, which is imported from acpica, 26 + * only contains the cache_id field rather than all the fields of the 27 + * Cache Type Structure. Use this alternative structure until it is 28 + * resolved in acpica. 29 + */ 30 + struct acpi_pptt_cache_v1_full { 31 + struct acpi_subtable_header header; 32 + u16 reserved; 33 + u32 flags; 34 + u32 next_level_of_cache; 35 + u32 size; 36 + u32 number_of_sets; 37 + u8 associativity; 38 + u8 attributes; 39 + u16 line_size; 40 + u32 cache_id; 41 + } __packed; 42 + 24 43 static struct acpi_subtable_header *fetch_pptt_subtable(struct acpi_table_header *table_hdr, 25 44 u32 pptt_ref) 26 45 { ··· 73 54 u32 pptt_ref) 74 55 { 75 56 return (struct acpi_pptt_cache *)fetch_pptt_subtable(table_hdr, pptt_ref); 57 + } 58 + 59 + static struct acpi_pptt_cache_v1_full *upgrade_pptt_cache(struct acpi_pptt_cache *cache) 60 + { 61 + if (cache->header.length < sizeof(struct acpi_pptt_cache_v1_full)) 62 + return NULL; 63 + 64 + /* No use for v1 if the only additional field is invalid */ 65 + if (!(cache->flags & ACPI_PPTT_CACHE_ID_VALID)) 66 + return NULL; 67 + 68 + return (struct acpi_pptt_cache_v1_full *)cache; 76 69 } 77 70 78 71 static struct acpi_subtable_header *acpi_get_pptt_resource(struct acpi_table_header *table_hdr, ··· 208 177 } 209 178 210 179 /** 211 - * acpi_count_levels() - Given a PPTT table, and a CPU node, count the cache 212 - * levels and split cache levels (data/instruction). 180 + * acpi_count_levels() - Given a PPTT table, and a CPU node, count the 181 + * total number of levels and split cache levels (data/instruction). 213 182 * @table_hdr: Pointer to the head of the PPTT table 214 183 * @cpu_node: processor node we wish to count caches for 215 - * @levels: Number of levels if success. 216 184 * @split_levels: Number of split cache levels (data/instruction) if 217 185 * success. Can by NULL. 218 186 * 187 + * Return: number of levels. 219 188 * Given a processor node containing a processing unit, walk into it and count 220 189 * how many levels exist solely for it, and then walk up each level until we hit 221 190 * the root node (ignore the package level because it may be possible to have ··· 223 192 * split cache levels (data/instruction) that exist at each level on the way 224 193 * up. 225 194 */ 226 - static void acpi_count_levels(struct acpi_table_header *table_hdr, 227 - struct acpi_pptt_processor *cpu_node, 228 - unsigned int *levels, unsigned int *split_levels) 195 + static int acpi_count_levels(struct acpi_table_header *table_hdr, 196 + struct acpi_pptt_processor *cpu_node, 197 + unsigned int *split_levels) 229 198 { 199 + int current_level = 0; 200 + 230 201 do { 231 - acpi_find_cache_level(table_hdr, cpu_node, levels, split_levels, 0, 0); 202 + acpi_find_cache_level(table_hdr, cpu_node, &current_level, split_levels, 0, 0); 232 203 cpu_node = fetch_pptt_node(table_hdr, cpu_node->parent); 233 204 } while (cpu_node); 205 + 206 + return current_level; 234 207 } 235 208 236 209 /** ··· 386 351 * @this_leaf: Kernel cache info structure being updated 387 352 * @found_cache: The PPTT node describing this cache instance 388 353 * @cpu_node: A unique reference to describe this cache instance 389 - * @revision: The revision of the PPTT table 390 354 * 391 355 * The ACPI spec implies that the fields in the cache structures are used to 392 356 * extend and correct the information probed from the hardware. Lets only ··· 395 361 */ 396 362 static void update_cache_properties(struct cacheinfo *this_leaf, 397 363 struct acpi_pptt_cache *found_cache, 398 - struct acpi_pptt_processor *cpu_node, 399 - u8 revision) 364 + struct acpi_pptt_processor *cpu_node) 400 365 { 401 - struct acpi_pptt_cache_v1* found_cache_v1; 366 + struct acpi_pptt_cache_v1_full *found_cache_v1; 402 367 403 368 this_leaf->fw_token = cpu_node; 404 369 if (found_cache->flags & ACPI_PPTT_SIZE_PROPERTY_VALID) ··· 447 414 found_cache->flags & ACPI_PPTT_CACHE_TYPE_VALID) 448 415 this_leaf->type = CACHE_TYPE_UNIFIED; 449 416 450 - if (revision >= 3 && (found_cache->flags & ACPI_PPTT_CACHE_ID_VALID)) { 451 - found_cache_v1 = ACPI_ADD_PTR(struct acpi_pptt_cache_v1, 452 - found_cache, sizeof(struct acpi_pptt_cache)); 417 + found_cache_v1 = upgrade_pptt_cache(found_cache); 418 + if (found_cache_v1) { 453 419 this_leaf->id = found_cache_v1->cache_id; 454 420 this_leaf->attributes |= CACHE_ID; 455 421 } ··· 473 441 pr_debug("found = %p %p\n", found_cache, cpu_node); 474 442 if (found_cache) 475 443 update_cache_properties(this_leaf, found_cache, 476 - ACPI_TO_POINTER(ACPI_PTR_DIFF(cpu_node, table)), 477 - table->revision); 444 + ACPI_TO_POINTER(ACPI_PTR_DIFF(cpu_node, table))); 478 445 479 446 index++; 480 447 } ··· 676 645 if (!cpu_node) 677 646 return -ENOENT; 678 647 679 - acpi_count_levels(table, cpu_node, levels, split_levels); 648 + *levels = acpi_count_levels(table, cpu_node, split_levels); 680 649 681 650 pr_debug("Cache Setup: last_level=%d split_levels=%d\n", 682 651 *levels, split_levels ? *split_levels : -1); ··· 847 816 { 848 817 return find_acpi_cpu_topology_tag(cpu, PPTT_ABORT_PACKAGE, 849 818 ACPI_PPTT_ACPI_IDENTICAL); 819 + } 820 + 821 + /** 822 + * acpi_pptt_get_child_cpus() - Find all the CPUs below a PPTT 823 + * processor hierarchy node 824 + * 825 + * @table_hdr: A reference to the PPTT table 826 + * @parent_node: A pointer to the processor hierarchy node in the 827 + * table_hdr 828 + * @cpus: A cpumask to fill with the CPUs below @parent_node 829 + * 830 + * Walks up the PPTT from every possible CPU to find if the provided 831 + * @parent_node is a parent of this CPU. 832 + */ 833 + static void acpi_pptt_get_child_cpus(struct acpi_table_header *table_hdr, 834 + struct acpi_pptt_processor *parent_node, 835 + cpumask_t *cpus) 836 + { 837 + struct acpi_pptt_processor *cpu_node; 838 + u32 acpi_id; 839 + int cpu; 840 + 841 + cpumask_clear(cpus); 842 + 843 + for_each_possible_cpu(cpu) { 844 + acpi_id = get_acpi_id_for_cpu(cpu); 845 + cpu_node = acpi_find_processor_node(table_hdr, acpi_id); 846 + 847 + while (cpu_node) { 848 + if (cpu_node == parent_node) { 849 + cpumask_set_cpu(cpu, cpus); 850 + break; 851 + } 852 + cpu_node = fetch_pptt_node(table_hdr, cpu_node->parent); 853 + } 854 + } 855 + } 856 + 857 + /** 858 + * acpi_pptt_get_cpus_from_container() - Populate a cpumask with all CPUs in a 859 + * processor container 860 + * @acpi_cpu_id: The UID of the processor container 861 + * @cpus: The resulting CPU mask 862 + * 863 + * Find the specified Processor Container, and fill @cpus with all the cpus 864 + * below it. 865 + * 866 + * Not all 'Processor Hierarchy' entries in the PPTT are either a CPU 867 + * or a Processor Container, they may exist purely to describe a 868 + * Private resource. CPUs have to be leaves, so a Processor Container 869 + * is a non-leaf that has the 'ACPI Processor ID valid' flag set. 870 + */ 871 + void acpi_pptt_get_cpus_from_container(u32 acpi_cpu_id, cpumask_t *cpus) 872 + { 873 + struct acpi_table_header *table_hdr; 874 + struct acpi_subtable_header *entry; 875 + unsigned long table_end; 876 + u32 proc_sz; 877 + 878 + cpumask_clear(cpus); 879 + 880 + table_hdr = acpi_get_pptt(); 881 + if (!table_hdr) 882 + return; 883 + 884 + table_end = (unsigned long)table_hdr + table_hdr->length; 885 + entry = ACPI_ADD_PTR(struct acpi_subtable_header, table_hdr, 886 + sizeof(struct acpi_table_pptt)); 887 + proc_sz = sizeof(struct acpi_pptt_processor); 888 + while ((unsigned long)entry + proc_sz <= table_end) { 889 + if (entry->type == ACPI_PPTT_TYPE_PROCESSOR) { 890 + struct acpi_pptt_processor *cpu_node; 891 + 892 + cpu_node = (struct acpi_pptt_processor *)entry; 893 + if (cpu_node->flags & ACPI_PPTT_ACPI_PROCESSOR_ID_VALID && 894 + !acpi_pptt_leaf_node(table_hdr, cpu_node) && 895 + cpu_node->acpi_processor_id == acpi_cpu_id) { 896 + acpi_pptt_get_child_cpus(table_hdr, cpu_node, cpus); 897 + break; 898 + } 899 + } 900 + entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry, 901 + entry->length); 902 + } 903 + } 904 + 905 + /** 906 + * find_acpi_cache_level_from_id() - Get the level of the specified cache 907 + * @cache_id: The id field of the cache 908 + * 909 + * Determine the level relative to any CPU for the cache identified by 910 + * cache_id. This allows the property to be found even if the CPUs are offline. 911 + * 912 + * The returned level can be used to group caches that are peers. 913 + * 914 + * The PPTT table must be rev 3 or later. 915 + * 916 + * If one CPU's L2 is shared with another CPU as L3, this function will return 917 + * an unpredictable value. 918 + * 919 + * Return: -ENOENT if the PPTT doesn't exist, the revision isn't supported or 920 + * the cache cannot be found. 921 + * Otherwise returns a value which represents the level of the specified cache. 922 + */ 923 + int find_acpi_cache_level_from_id(u32 cache_id) 924 + { 925 + int cpu; 926 + struct acpi_table_header *table; 927 + 928 + table = acpi_get_pptt(); 929 + if (!table) 930 + return -ENOENT; 931 + 932 + if (table->revision < 3) 933 + return -ENOENT; 934 + 935 + for_each_possible_cpu(cpu) { 936 + bool empty; 937 + int level = 1; 938 + u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu); 939 + struct acpi_pptt_cache *cache; 940 + struct acpi_pptt_processor *cpu_node; 941 + 942 + cpu_node = acpi_find_processor_node(table, acpi_cpu_id); 943 + if (!cpu_node) 944 + continue; 945 + 946 + do { 947 + int cache_type[] = {CACHE_TYPE_INST, CACHE_TYPE_DATA, CACHE_TYPE_UNIFIED}; 948 + 949 + empty = true; 950 + for (int i = 0; i < ARRAY_SIZE(cache_type); i++) { 951 + struct acpi_pptt_cache_v1_full *cache_v1; 952 + 953 + cache = acpi_find_cache_node(table, acpi_cpu_id, cache_type[i], 954 + level, &cpu_node); 955 + if (!cache) 956 + continue; 957 + 958 + empty = false; 959 + 960 + cache_v1 = upgrade_pptt_cache(cache); 961 + if (cache_v1 && cache_v1->cache_id == cache_id) 962 + return level; 963 + } 964 + level++; 965 + } while (!empty); 966 + } 967 + 968 + return -ENOENT; 969 + } 970 + 971 + /** 972 + * acpi_pptt_get_cpumask_from_cache_id() - Get the cpus associated with the 973 + * specified cache 974 + * @cache_id: The id field of the cache 975 + * @cpus: Where to build the cpumask 976 + * 977 + * Determine which CPUs are below this cache in the PPTT. This allows the property 978 + * to be found even if the CPUs are offline. 979 + * 980 + * The PPTT table must be rev 3 or later, 981 + * 982 + * Return: -ENOENT if the PPTT doesn't exist, or the cache cannot be found. 983 + * Otherwise returns 0 and sets the cpus in the provided cpumask. 984 + */ 985 + int acpi_pptt_get_cpumask_from_cache_id(u32 cache_id, cpumask_t *cpus) 986 + { 987 + int cpu; 988 + struct acpi_table_header *table; 989 + 990 + cpumask_clear(cpus); 991 + 992 + table = acpi_get_pptt(); 993 + if (!table) 994 + return -ENOENT; 995 + 996 + if (table->revision < 3) 997 + return -ENOENT; 998 + 999 + for_each_possible_cpu(cpu) { 1000 + bool empty; 1001 + int level = 1; 1002 + u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu); 1003 + struct acpi_pptt_cache *cache; 1004 + struct acpi_pptt_processor *cpu_node; 1005 + 1006 + cpu_node = acpi_find_processor_node(table, acpi_cpu_id); 1007 + if (!cpu_node) 1008 + continue; 1009 + 1010 + do { 1011 + int cache_type[] = {CACHE_TYPE_INST, CACHE_TYPE_DATA, CACHE_TYPE_UNIFIED}; 1012 + 1013 + empty = true; 1014 + for (int i = 0; i < ARRAY_SIZE(cache_type); i++) { 1015 + struct acpi_pptt_cache_v1_full *cache_v1; 1016 + 1017 + cache = acpi_find_cache_node(table, acpi_cpu_id, cache_type[i], 1018 + level, &cpu_node); 1019 + 1020 + if (!cache) 1021 + continue; 1022 + 1023 + empty = false; 1024 + 1025 + cache_v1 = upgrade_pptt_cache(cache); 1026 + if (cache_v1 && cache_v1->cache_id == cache_id) 1027 + cpumask_set_cpu(cpu, cpus); 1028 + } 1029 + level++; 1030 + } while (!empty); 1031 + } 1032 + 1033 + return 0; 850 1034 }
+1 -1
drivers/acpi/tables.c
··· 408 408 ACPI_SIG_PSDT, ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, 409 409 ACPI_SIG_IORT, ACPI_SIG_NFIT, ACPI_SIG_HMAT, ACPI_SIG_PPTT, 410 410 ACPI_SIG_NHLT, ACPI_SIG_AEST, ACPI_SIG_CEDT, ACPI_SIG_AGDI, 411 - ACPI_SIG_NBFT, ACPI_SIG_SWFT}; 411 + ACPI_SIG_NBFT, ACPI_SIG_SWFT, ACPI_SIG_MPAM}; 412 412 413 413 #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header) 414 414
+3
drivers/firmware/efi/efi.c
··· 74 74 .page_table_lock = __SPIN_LOCK_UNLOCKED(efi_mm.page_table_lock), 75 75 .mmlist = LIST_HEAD_INIT(efi_mm.mmlist), 76 76 .cpu_bitmap = { [BITS_TO_LONGS(NR_CPUS)] = 0}, 77 + #ifdef CONFIG_SCHED_MM_CID 78 + .mm_cid.lock = __RAW_SPIN_LOCK_UNLOCKED(efi_mm.mm_cid.lock), 79 + #endif 77 80 }; 78 81 79 82 struct workqueue_struct *efi_rts_wq;
+16 -1
drivers/firmware/efi/runtime-wrappers.c
··· 202 202 */ 203 203 static DEFINE_SEMAPHORE(efi_runtime_lock, 1); 204 204 205 + static struct task_struct *efi_runtime_lock_owner; 206 + 205 207 /* 206 208 * Expose the EFI runtime lock to the UV platform 207 209 */ ··· 220 218 const union efi_rts_args *args = efi_rts_work.args; 221 219 efi_status_t status = EFI_NOT_FOUND; 222 220 unsigned long flags; 221 + 222 + efi_runtime_lock_owner = current; 223 223 224 224 arch_efi_call_virt_setup(); 225 225 flags = efi_call_virt_save_flags(); ··· 314 310 315 311 efi_rts_work.status = status; 316 312 complete(&efi_rts_work.efi_rts_comp); 313 + efi_runtime_lock_owner = NULL; 317 314 } 318 315 319 316 static efi_status_t __efi_queue_work(enum efi_rts_ids id, ··· 449 444 if (down_trylock(&efi_runtime_lock)) 450 445 return EFI_NOT_READY; 451 446 447 + efi_runtime_lock_owner = current; 452 448 status = efi_call_virt_pointer(efi.runtime, set_variable, name, vendor, 453 449 attr, data_size, data); 450 + efi_runtime_lock_owner = NULL; 454 451 up(&efi_runtime_lock); 455 452 return status; 456 453 } ··· 488 481 if (down_trylock(&efi_runtime_lock)) 489 482 return EFI_NOT_READY; 490 483 484 + efi_runtime_lock_owner = current; 491 485 status = efi_call_virt_pointer(efi.runtime, query_variable_info, attr, 492 486 storage_space, remaining_space, 493 487 max_variable_size); 488 + efi_runtime_lock_owner = NULL; 494 489 up(&efi_runtime_lock); 495 490 return status; 496 491 } ··· 518 509 return; 519 510 } 520 511 512 + efi_runtime_lock_owner = current; 521 513 arch_efi_call_virt_setup(); 522 514 efi_rts_work.efi_rts_id = EFI_RESET_SYSTEM; 523 515 arch_efi_call_virt(efi.runtime, reset_system, reset_type, status, 524 516 data_size, data); 525 517 arch_efi_call_virt_teardown(); 526 - 518 + efi_runtime_lock_owner = NULL; 527 519 up(&efi_runtime_lock); 528 520 } 529 521 ··· 597 587 } 598 588 599 589 #endif 590 + 591 + void efi_runtime_assert_lock_held(void) 592 + { 593 + WARN_ON(efi_runtime_lock_owner != current); 594 + }
+75 -22
drivers/perf/arm-ni.c
··· 21 21 22 22 #define NI_CHILD_NODE_INFO 0x004 23 23 #define NI_CHILD_PTR(n) (0x008 + (n) * 4) 24 + #define NI_NUM_SUB_FEATURES 0x100 25 + #define NI_SUB_FEATURE_TYPE(n) (0x108 + (n) * 8) 26 + #define NI_SUB_FEATURE_PTR(n) (0x10c + (n) * 8) 27 + 28 + #define NI_SUB_FEATURE_TYPE_FCU 0x2 24 29 25 30 #define NI700_PMUSELA 0x00c 26 31 ··· 38 33 #define NI_PIDR2_VERSION GENMASK(7, 4) 39 34 40 35 /* PMU node */ 41 - #define NI_PMEVCNTR(n) (0x008 + (n) * 8) 42 - #define NI_PMCCNTR_L 0x0f8 43 - #define NI_PMCCNTR_U 0x0fc 36 + #define NI700_PMEVCNTR(n) (0x008 + (n) * 8) 37 + #define NI700_PMCCNTR_L 0x0f8 38 + #define NI_PMEVCNTR(n) (0x200 + (n) * 8) 39 + #define NI_PMCCNTR_L 0x2f8 44 40 #define NI_PMEVTYPER(n) (0x400 + (n) * 4) 45 41 #define NI_PMEVTYPER_NODE_TYPE GENMASK(12, 9) 46 42 #define NI_PMEVTYPER_NODE_ID GENMASK(8, 0) ··· 72 66 enum ni_part { 73 67 PART_NI_700 = 0x43b, 74 68 PART_NI_710AE = 0x43d, 69 + PART_NOC_S3 = 0x43f, 70 + PART_SI_L1 = 0x455, 75 71 }; 76 72 77 73 enum ni_node_type { ··· 87 79 NI_HSNI, 88 80 NI_HMNI, 89 81 NI_PMNI, 82 + NI_TSNI, 83 + NI_TMNI, 84 + NI_CMNI = 0x0e, 85 + NI_MCN = 0x63, 90 86 }; 91 87 92 88 struct arm_ni_node { ··· 191 179 NI_EVENT_ATTR(hsni, NI_HSNI), 192 180 NI_EVENT_ATTR(hmni, NI_HMNI), 193 181 NI_EVENT_ATTR(pmni, NI_PMNI), 182 + NI_EVENT_ATTR(tsni, NI_TSNI), 183 + NI_EVENT_ATTR(tmni, NI_TMNI), 184 + NI_EVENT_ATTR(cmni, NI_CMNI), 194 185 NULL 195 186 }; 196 187 ··· 323 308 return 0; 324 309 } 325 310 311 + static bool arm_ni_is_7xx(const struct arm_ni *ni) 312 + { 313 + return ni->part == PART_NI_700 || ni->part == PART_NI_710AE; 314 + } 315 + 326 316 static int arm_ni_event_init(struct perf_event *event) 327 317 { 328 318 struct arm_ni_cd *cd = pmu_to_cd(event->pmu); 319 + struct arm_ni *ni; 329 320 330 321 if (event->attr.type != event->pmu->type) 331 322 return -ENOENT; ··· 339 318 if (is_sampling_event(event)) 340 319 return -EINVAL; 341 320 342 - event->cpu = cd_to_ni(cd)->cpu; 321 + ni = cd_to_ni(cd); 322 + event->cpu = ni->cpu; 323 + event->hw.flags = arm_ni_is_7xx(ni); 324 + 343 325 if (NI_EVENT_TYPE(event) == NI_PMU) 344 326 return arm_ni_validate_group(event); 345 327 ··· 356 332 return -EINVAL; 357 333 } 358 334 359 - static u64 arm_ni_read_ccnt(struct arm_ni_cd *cd) 335 + static u64 arm_ni_read_ccnt(void __iomem *pmccntr) 360 336 { 361 337 u64 l, u_old, u_new; 362 338 int retries = 3; /* 1st time unlucky, 2nd improbable, 3rd just broken */ 363 339 364 - u_new = readl_relaxed(cd->pmu_base + NI_PMCCNTR_U); 340 + u_new = readl_relaxed(pmccntr + 4); 365 341 do { 366 342 u_old = u_new; 367 - l = readl_relaxed(cd->pmu_base + NI_PMCCNTR_L); 368 - u_new = readl_relaxed(cd->pmu_base + NI_PMCCNTR_U); 343 + l = readl_relaxed(pmccntr); 344 + u_new = readl_relaxed(pmccntr + 4); 369 345 } while (u_new != u_old && --retries); 370 346 WARN_ON(!retries); 371 347 ··· 374 350 375 351 static void arm_ni_event_read(struct perf_event *event) 376 352 { 377 - struct arm_ni_cd *cd = pmu_to_cd(event->pmu); 378 353 struct hw_perf_event *hw = &event->hw; 379 354 u64 count, prev; 380 355 bool ccnt = hw->idx == NI_CCNT_IDX; ··· 381 358 do { 382 359 prev = local64_read(&hw->prev_count); 383 360 if (ccnt) 384 - count = arm_ni_read_ccnt(cd); 361 + count = arm_ni_read_ccnt((void __iomem *)event->hw.event_base); 385 362 else 386 - count = readl_relaxed(cd->pmu_base + NI_PMEVCNTR(hw->idx)); 363 + count = readl_relaxed((void __iomem *)event->hw.event_base); 387 364 } while (local64_cmpxchg(&hw->prev_count, prev, count) != prev); 388 365 389 366 count -= prev; ··· 408 385 arm_ni_event_read(event); 409 386 } 410 387 411 - static void arm_ni_init_ccnt(struct arm_ni_cd *cd) 388 + static void arm_ni_init_ccnt(struct hw_perf_event *hw) 412 389 { 413 - local64_set(&cd->ccnt->hw.prev_count, S64_MIN); 414 - lo_hi_writeq_relaxed(S64_MIN, cd->pmu_base + NI_PMCCNTR_L); 390 + local64_set(&hw->prev_count, S64_MIN); 391 + lo_hi_writeq_relaxed(S64_MIN, (void __iomem *)hw->event_base); 415 392 } 416 393 417 - static void arm_ni_init_evcnt(struct arm_ni_cd *cd, int idx) 394 + static void arm_ni_init_evcnt(struct hw_perf_event *hw) 418 395 { 419 - local64_set(&cd->evcnt[idx]->hw.prev_count, S32_MIN); 420 - writel_relaxed(S32_MIN, cd->pmu_base + NI_PMEVCNTR(idx)); 396 + local64_set(&hw->prev_count, S32_MIN); 397 + writel_relaxed(S32_MIN, (void __iomem *)hw->event_base); 421 398 } 422 399 423 400 static int arm_ni_event_add(struct perf_event *event, int flags) ··· 432 409 if (cd->ccnt) 433 410 return -ENOSPC; 434 411 hw->idx = NI_CCNT_IDX; 412 + hw->event_base = (unsigned long)cd->pmu_base + 413 + (hw->flags ? NI700_PMCCNTR_L : NI_PMCCNTR_L); 435 414 cd->ccnt = event; 436 - arm_ni_init_ccnt(cd); 415 + arm_ni_init_ccnt(hw); 437 416 } else { 438 417 hw->idx = 0; 439 418 while (cd->evcnt[hw->idx]) { ··· 445 420 cd->evcnt[hw->idx] = event; 446 421 unit = (void *)hw->config_base; 447 422 unit->event[hw->idx] = NI_EVENT_EVENTID(event); 448 - arm_ni_init_evcnt(cd, hw->idx); 423 + hw->event_base = (unsigned long)cd->pmu_base + 424 + (hw->flags ? NI700_PMEVCNTR(hw->idx) : NI_PMEVCNTR(hw->idx)); 425 + arm_ni_init_evcnt(hw); 449 426 lo_hi_writeq_relaxed(le64_to_cpu(unit->pmusel), unit->pmusela); 450 427 451 428 reg = FIELD_PREP(NI_PMEVTYPER_NODE_TYPE, type) | ··· 484 457 ret = IRQ_HANDLED; 485 458 if (!(WARN_ON(!cd->ccnt))) { 486 459 arm_ni_event_read(cd->ccnt); 487 - arm_ni_init_ccnt(cd); 460 + arm_ni_init_ccnt(&cd->ccnt->hw); 488 461 } 489 462 } 490 463 for (int i = 0; i < NI_NUM_COUNTERS; i++) { ··· 493 466 ret = IRQ_HANDLED; 494 467 if (!(WARN_ON(!cd->evcnt[i]))) { 495 468 arm_ni_event_read(cd->evcnt[i]); 496 - arm_ni_init_evcnt(cd, i); 469 + arm_ni_init_evcnt(&cd->evcnt[i]->hw); 497 470 } 498 471 } 499 472 writel_relaxed(reg, cd->pmu_base + NI_PMOVSCLR); ··· 501 474 return ret; 502 475 cd += cd->irq_friend; 503 476 } 477 + } 478 + 479 + static void __iomem *arm_ni_get_pmusel(struct arm_ni *ni, void __iomem *unit_base) 480 + { 481 + u32 type, ptr, num; 482 + 483 + if (arm_ni_is_7xx(ni)) 484 + return unit_base + NI700_PMUSELA; 485 + 486 + num = readl_relaxed(unit_base + NI_NUM_SUB_FEATURES); 487 + for (int i = 0; i < num; i++) { 488 + type = readl_relaxed(unit_base + NI_SUB_FEATURE_TYPE(i)); 489 + if (type != NI_SUB_FEATURE_TYPE_FCU) 490 + continue; 491 + ptr = readl_relaxed(unit_base + NI_SUB_FEATURE_PTR(i)); 492 + return ni->base + ptr; 493 + } 494 + /* Should be impossible */ 495 + return NULL; 504 496 } 505 497 506 498 static int arm_ni_init_cd(struct arm_ni *ni, struct arm_ni_node *node, u64 res_start) ··· 558 512 case NI_HSNI: 559 513 case NI_HMNI: 560 514 case NI_PMNI: 561 - unit->pmusela = unit_base + NI700_PMUSELA; 515 + case NI_TSNI: 516 + case NI_TMNI: 517 + case NI_CMNI: 518 + unit->pmusela = arm_ni_get_pmusel(ni, unit_base); 562 519 writel_relaxed(1, unit->pmusela); 563 520 if (readl_relaxed(unit->pmusela) != 1) 564 521 dev_info(ni->dev, "No access to node 0x%04x%04x\n", unit->id, unit->type); 565 522 else 566 523 unit->ns = true; 524 + break; 525 + case NI_MCN: 567 526 break; 568 527 default: 569 528 /* ··· 700 649 switch (part) { 701 650 case PART_NI_700: 702 651 case PART_NI_710AE: 652 + case PART_NOC_S3: 653 + case PART_SI_L1: 703 654 break; 704 655 default: 705 656 dev_WARN(&pdev->dev, "Unknown part number: 0x%03x, this may go badly\n", part);
+48 -4
drivers/perf/arm_cspmu/arm_cspmu.c
··· 322 322 { 323 323 .module_name = "nvidia_cspmu", 324 324 .pmiidr_val = ARM_CSPMU_IMPL_ID_NVIDIA, 325 - .pmiidr_mask = ARM_CSPMU_PMIIDR_IMPLEMENTER, 325 + .pmiidr_mask = PMIIDR_IMPLEMENTER, 326 326 .module = NULL, 327 327 .impl_init_ops = NULL, 328 328 }, 329 329 { 330 330 .module_name = "ampere_cspmu", 331 331 .pmiidr_val = ARM_CSPMU_IMPL_ID_AMPERE, 332 - .pmiidr_mask = ARM_CSPMU_PMIIDR_IMPLEMENTER, 332 + .pmiidr_mask = PMIIDR_IMPLEMENTER, 333 333 .module = NULL, 334 334 .impl_init_ops = NULL, 335 335 }, ··· 351 351 return NULL; 352 352 } 353 353 354 + static u32 arm_cspmu_get_pmiidr(struct arm_cspmu *cspmu) 355 + { 356 + u32 pmiidr, pmpidr; 357 + 358 + pmiidr = readl(cspmu->base0 + PMIIDR); 359 + 360 + if (pmiidr != 0) 361 + return pmiidr; 362 + 363 + /* Construct PMIIDR value from PMPIDRs. */ 364 + 365 + pmpidr = readl(cspmu->base0 + PMPIDR0); 366 + pmiidr |= FIELD_PREP(PMIIDR_PRODUCTID_PART_0, 367 + FIELD_GET(PMPIDR0_PART_0, pmpidr)); 368 + 369 + pmpidr = readl(cspmu->base0 + PMPIDR1); 370 + pmiidr |= FIELD_PREP(PMIIDR_PRODUCTID_PART_1, 371 + FIELD_GET(PMPIDR1_PART_1, pmpidr)); 372 + pmiidr |= FIELD_PREP(PMIIDR_IMPLEMENTER_DES_0, 373 + FIELD_GET(PMPIDR1_DES_0, pmpidr)); 374 + 375 + pmpidr = readl(cspmu->base0 + PMPIDR2); 376 + pmiidr |= FIELD_PREP(PMIIDR_VARIANT, 377 + FIELD_GET(PMPIDR2_REVISION, pmpidr)); 378 + pmiidr |= FIELD_PREP(PMIIDR_IMPLEMENTER_DES_1, 379 + FIELD_GET(PMPIDR2_DES_1, pmpidr)); 380 + 381 + pmpidr = readl(cspmu->base0 + PMPIDR3); 382 + pmiidr |= FIELD_PREP(PMIIDR_REVISION, 383 + FIELD_GET(PMPIDR3_REVAND, pmpidr)); 384 + 385 + pmpidr = readl(cspmu->base0 + PMPIDR4); 386 + pmiidr |= FIELD_PREP(PMIIDR_IMPLEMENTER_DES_2, 387 + FIELD_GET(PMPIDR4_DES_2, pmpidr)); 388 + 389 + return pmiidr; 390 + } 391 + 354 392 #define DEFAULT_IMPL_OP(name) .name = arm_cspmu_##name 355 393 356 394 static int arm_cspmu_init_impl_ops(struct arm_cspmu *cspmu) ··· 399 361 400 362 /* Start with a default PMU implementation */ 401 363 cspmu->impl.module = THIS_MODULE; 402 - cspmu->impl.pmiidr = readl(cspmu->base0 + PMIIDR); 364 + cspmu->impl.pmiidr = arm_cspmu_get_pmiidr(cspmu); 403 365 cspmu->impl.ops = (struct arm_cspmu_impl_ops) { 404 366 DEFAULT_IMPL_OP(get_event_attrs), 405 367 DEFAULT_IMPL_OP(get_format_attrs), ··· 853 815 return; 854 816 855 817 arm_cspmu_disable_counter(cspmu, hwc->idx); 818 + 819 + if (cspmu->impl.ops.reset_ev_filter) 820 + cspmu->impl.ops.reset_ev_filter(cspmu, event); 821 + 856 822 arm_cspmu_event_update(event); 857 823 858 824 hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE; ··· 1407 1365 1408 1366 /* Unbind the driver from all matching backend devices. */ 1409 1367 while ((dev = driver_find_device(&arm_cspmu_driver.driver, NULL, 1410 - match, arm_cspmu_match_device))) 1368 + match, arm_cspmu_match_device))) { 1411 1369 device_release_driver(dev); 1370 + put_device(dev); 1371 + } 1412 1372 1413 1373 mutex_lock(&arm_cspmu_lock); 1414 1374
+36 -3
drivers/perf/arm_cspmu/arm_cspmu.h
··· 86 86 #define PMCFGR 0xE00 87 87 #define PMCR 0xE04 88 88 #define PMIIDR 0xE08 89 + #define PMPIDR0 0xFE0 90 + #define PMPIDR1 0xFE4 91 + #define PMPIDR2 0xFE8 92 + #define PMPIDR3 0xFEC 93 + #define PMPIDR4 0xFD0 89 94 90 95 /* PMCFGR register field */ 91 96 #define PMCFGR_NCG GENMASK(31, 28) ··· 120 115 #define PMCR_E BIT(0) 121 116 122 117 /* PMIIDR register field */ 123 - #define ARM_CSPMU_PMIIDR_IMPLEMENTER GENMASK(11, 0) 124 - #define ARM_CSPMU_PMIIDR_PRODUCTID GENMASK(31, 20) 118 + #define PMIIDR_IMPLEMENTER GENMASK(11, 0) 119 + #define PMIIDR_IMPLEMENTER_DES_0 GENMASK(3, 0) 120 + #define PMIIDR_IMPLEMENTER_DES_1 GENMASK(6, 4) 121 + #define PMIIDR_IMPLEMENTER_DES_2 GENMASK(11, 8) 122 + #define PMIIDR_REVISION GENMASK(15, 12) 123 + #define PMIIDR_VARIANT GENMASK(19, 16) 124 + #define PMIIDR_PRODUCTID GENMASK(31, 20) 125 + #define PMIIDR_PRODUCTID_PART_0 GENMASK(27, 20) 126 + #define PMIIDR_PRODUCTID_PART_1 GENMASK(31, 28) 127 + 128 + /* PMPIDR0 register field */ 129 + #define PMPIDR0_PART_0 GENMASK(7, 0) 130 + 131 + /* PMPIDR1 register field */ 132 + #define PMPIDR1_DES_0 GENMASK(7, 4) 133 + #define PMPIDR1_PART_1 GENMASK(3, 0) 134 + 135 + /* PMPIDR2 register field */ 136 + #define PMPIDR2_REVISION GENMASK(7, 4) 137 + #define PMPIDR2_DES_1 GENMASK(2, 0) 138 + 139 + /* PMPIDR3 register field */ 140 + #define PMPIDR3_REVAND GENMASK(7, 4) 141 + #define PMPIDR3_CMOD GENMASK(3, 0) 142 + 143 + /* PMPIDR4 register field */ 144 + #define PMPIDR4_SIZE GENMASK(7, 4) 145 + #define PMPIDR4_DES_2 GENMASK(3, 0) 125 146 126 147 /* JEDEC-assigned JEP106 identification code */ 127 148 #define ARM_CSPMU_IMPL_ID_NVIDIA 0x36B ··· 183 152 bool (*is_cycle_counter_event)(const struct perf_event *event); 184 153 /* Decode event type/id from configs */ 185 154 u32 (*event_type)(const struct perf_event *event); 186 - /* Set event filters */ 155 + /* Set/reset event filters */ 187 156 void (*set_cc_filter)(struct arm_cspmu *cspmu, 188 157 const struct perf_event *event); 189 158 void (*set_ev_filter)(struct arm_cspmu *cspmu, 190 159 const struct perf_event *event); 160 + void (*reset_ev_filter)(struct arm_cspmu *cspmu, 161 + const struct perf_event *event); 191 162 /* Implementation specific event validation */ 192 163 int (*validate_event)(struct arm_cspmu *cspmu, 193 164 struct perf_event *event);
+141 -53
drivers/perf/arm_cspmu/nvidia_cspmu.c
··· 23 23 24 24 #define NV_GENERIC_FILTER_ID_MASK GENMASK_ULL(31, 0) 25 25 26 - #define NV_PRODID_MASK GENMASK(31, 0) 26 + #define NV_PRODID_MASK (PMIIDR_PRODUCTID | PMIIDR_VARIANT | PMIIDR_REVISION) 27 27 28 28 #define NV_FORMAT_NAME_GENERIC 0 29 29 ··· 40 40 41 41 struct nv_cspmu_ctx { 42 42 const char *name; 43 - u32 filter_mask; 44 - u32 filter_default_val; 43 + 45 44 struct attribute **event_attr; 46 45 struct attribute **format_attr; 46 + 47 + u32 filter_mask; 48 + u32 filter_default_val; 49 + u32 filter2_mask; 50 + u32 filter2_default_val; 51 + 52 + u32 (*get_filter)(const struct perf_event *event); 53 + u32 (*get_filter2)(const struct perf_event *event); 54 + 55 + void *data; 56 + 57 + int (*init_data)(struct arm_cspmu *cspmu); 47 58 }; 48 59 49 60 static struct attribute *scf_pmu_event_attrs[] = { ··· 155 144 static struct attribute *generic_pmu_format_attrs[] = { 156 145 ARM_CSPMU_FORMAT_EVENT_ATTR, 157 146 ARM_CSPMU_FORMAT_FILTER_ATTR, 147 + ARM_CSPMU_FORMAT_FILTER2_ATTR, 158 148 NULL, 159 149 }; 160 150 ··· 196 184 return filter_val; 197 185 } 198 186 187 + static u32 nv_cspmu_event_filter2(const struct perf_event *event) 188 + { 189 + const struct nv_cspmu_ctx *ctx = 190 + to_nv_cspmu_ctx(to_arm_cspmu(event->pmu)); 191 + 192 + const u32 filter_val = event->attr.config2 & ctx->filter2_mask; 193 + 194 + if (filter_val == 0) 195 + return ctx->filter2_default_val; 196 + 197 + return filter_val; 198 + } 199 + 199 200 static void nv_cspmu_set_ev_filter(struct arm_cspmu *cspmu, 200 201 const struct perf_event *event) 201 202 { 202 - u32 filter = nv_cspmu_event_filter(event); 203 - u32 offset = PMEVFILTR + (4 * event->hw.idx); 203 + u32 filter, offset; 204 + const struct nv_cspmu_ctx *ctx = 205 + to_nv_cspmu_ctx(to_arm_cspmu(event->pmu)); 206 + offset = 4 * event->hw.idx; 204 207 205 - writel(filter, cspmu->base0 + offset); 208 + if (ctx->get_filter) { 209 + filter = ctx->get_filter(event); 210 + writel(filter, cspmu->base0 + PMEVFILTR + offset); 211 + } 212 + 213 + if (ctx->get_filter2) { 214 + filter = ctx->get_filter2(event); 215 + writel(filter, cspmu->base0 + PMEVFILT2R + offset); 216 + } 206 217 } 207 218 208 219 static void nv_cspmu_set_cc_filter(struct arm_cspmu *cspmu, ··· 245 210 struct nv_cspmu_match { 246 211 u32 prodid; 247 212 u32 prodid_mask; 248 - u64 filter_mask; 249 - u32 filter_default_val; 250 213 const char *name_pattern; 251 214 enum nv_cspmu_name_fmt name_fmt; 252 - struct attribute **event_attr; 253 - struct attribute **format_attr; 215 + struct nv_cspmu_ctx template_ctx; 216 + struct arm_cspmu_impl_ops ops; 254 217 }; 255 218 256 219 static const struct nv_cspmu_match nv_cspmu_match[] = { 257 220 { 258 - .prodid = 0x103, 221 + .prodid = 0x10300000, 259 222 .prodid_mask = NV_PRODID_MASK, 260 - .filter_mask = NV_PCIE_FILTER_ID_MASK, 261 - .filter_default_val = NV_PCIE_FILTER_ID_MASK, 262 223 .name_pattern = "nvidia_pcie_pmu_%u", 263 224 .name_fmt = NAME_FMT_SOCKET, 264 - .event_attr = mcf_pmu_event_attrs, 265 - .format_attr = pcie_pmu_format_attrs 225 + .template_ctx = { 226 + .event_attr = mcf_pmu_event_attrs, 227 + .format_attr = pcie_pmu_format_attrs, 228 + .filter_mask = NV_PCIE_FILTER_ID_MASK, 229 + .filter_default_val = NV_PCIE_FILTER_ID_MASK, 230 + .filter2_mask = 0x0, 231 + .filter2_default_val = 0x0, 232 + .get_filter = nv_cspmu_event_filter, 233 + .get_filter2 = NULL, 234 + .data = NULL, 235 + .init_data = NULL 236 + }, 266 237 }, 267 238 { 268 - .prodid = 0x104, 239 + .prodid = 0x10400000, 269 240 .prodid_mask = NV_PRODID_MASK, 270 - .filter_mask = NV_NVL_C2C_FILTER_ID_MASK, 271 - .filter_default_val = NV_NVL_C2C_FILTER_ID_MASK, 272 241 .name_pattern = "nvidia_nvlink_c2c1_pmu_%u", 273 242 .name_fmt = NAME_FMT_SOCKET, 274 - .event_attr = mcf_pmu_event_attrs, 275 - .format_attr = nvlink_c2c_pmu_format_attrs 243 + .template_ctx = { 244 + .event_attr = mcf_pmu_event_attrs, 245 + .format_attr = nvlink_c2c_pmu_format_attrs, 246 + .filter_mask = NV_NVL_C2C_FILTER_ID_MASK, 247 + .filter_default_val = NV_NVL_C2C_FILTER_ID_MASK, 248 + .filter2_mask = 0x0, 249 + .filter2_default_val = 0x0, 250 + .get_filter = nv_cspmu_event_filter, 251 + .get_filter2 = NULL, 252 + .data = NULL, 253 + .init_data = NULL 254 + }, 276 255 }, 277 256 { 278 - .prodid = 0x105, 257 + .prodid = 0x10500000, 279 258 .prodid_mask = NV_PRODID_MASK, 280 - .filter_mask = NV_NVL_C2C_FILTER_ID_MASK, 281 - .filter_default_val = NV_NVL_C2C_FILTER_ID_MASK, 282 259 .name_pattern = "nvidia_nvlink_c2c0_pmu_%u", 283 260 .name_fmt = NAME_FMT_SOCKET, 284 - .event_attr = mcf_pmu_event_attrs, 285 - .format_attr = nvlink_c2c_pmu_format_attrs 261 + .template_ctx = { 262 + .event_attr = mcf_pmu_event_attrs, 263 + .format_attr = nvlink_c2c_pmu_format_attrs, 264 + .filter_mask = NV_NVL_C2C_FILTER_ID_MASK, 265 + .filter_default_val = NV_NVL_C2C_FILTER_ID_MASK, 266 + .filter2_mask = 0x0, 267 + .filter2_default_val = 0x0, 268 + .get_filter = nv_cspmu_event_filter, 269 + .get_filter2 = NULL, 270 + .data = NULL, 271 + .init_data = NULL 272 + }, 286 273 }, 287 274 { 288 - .prodid = 0x106, 275 + .prodid = 0x10600000, 289 276 .prodid_mask = NV_PRODID_MASK, 290 - .filter_mask = NV_CNVL_FILTER_ID_MASK, 291 - .filter_default_val = NV_CNVL_FILTER_ID_MASK, 292 277 .name_pattern = "nvidia_cnvlink_pmu_%u", 293 278 .name_fmt = NAME_FMT_SOCKET, 294 - .event_attr = mcf_pmu_event_attrs, 295 - .format_attr = cnvlink_pmu_format_attrs 279 + .template_ctx = { 280 + .event_attr = mcf_pmu_event_attrs, 281 + .format_attr = cnvlink_pmu_format_attrs, 282 + .filter_mask = NV_CNVL_FILTER_ID_MASK, 283 + .filter_default_val = NV_CNVL_FILTER_ID_MASK, 284 + .filter2_mask = 0x0, 285 + .filter2_default_val = 0x0, 286 + .get_filter = nv_cspmu_event_filter, 287 + .get_filter2 = NULL, 288 + .data = NULL, 289 + .init_data = NULL 290 + }, 296 291 }, 297 292 { 298 - .prodid = 0x2CF, 293 + .prodid = 0x2CF00000, 299 294 .prodid_mask = NV_PRODID_MASK, 300 - .filter_mask = 0x0, 301 - .filter_default_val = 0x0, 302 295 .name_pattern = "nvidia_scf_pmu_%u", 303 296 .name_fmt = NAME_FMT_SOCKET, 304 - .event_attr = scf_pmu_event_attrs, 305 - .format_attr = scf_pmu_format_attrs 297 + .template_ctx = { 298 + .event_attr = scf_pmu_event_attrs, 299 + .format_attr = scf_pmu_format_attrs, 300 + .filter_mask = 0x0, 301 + .filter_default_val = 0x0, 302 + .filter2_mask = 0x0, 303 + .filter2_default_val = 0x0, 304 + .get_filter = nv_cspmu_event_filter, 305 + .get_filter2 = NULL, 306 + .data = NULL, 307 + .init_data = NULL 308 + }, 306 309 }, 307 310 { 308 311 .prodid = 0, 309 312 .prodid_mask = 0, 310 - .filter_mask = NV_GENERIC_FILTER_ID_MASK, 311 - .filter_default_val = NV_GENERIC_FILTER_ID_MASK, 312 313 .name_pattern = "nvidia_uncore_pmu_%u", 313 314 .name_fmt = NAME_FMT_GENERIC, 314 - .event_attr = generic_pmu_event_attrs, 315 - .format_attr = generic_pmu_format_attrs 315 + .template_ctx = { 316 + .event_attr = generic_pmu_event_attrs, 317 + .format_attr = generic_pmu_format_attrs, 318 + .filter_mask = NV_GENERIC_FILTER_ID_MASK, 319 + .filter_default_val = NV_GENERIC_FILTER_ID_MASK, 320 + .filter2_mask = NV_GENERIC_FILTER_ID_MASK, 321 + .filter2_default_val = NV_GENERIC_FILTER_ID_MASK, 322 + .get_filter = nv_cspmu_event_filter, 323 + .get_filter2 = nv_cspmu_event_filter2, 324 + .data = NULL, 325 + .init_data = NULL 326 + }, 316 327 }, 317 328 }; 318 329 ··· 391 310 return name; 392 311 } 393 312 313 + #define SET_OP(name, impl, match, default_op) \ 314 + do { \ 315 + if (match->ops.name) \ 316 + impl->name = match->ops.name; \ 317 + else if (default_op != NULL) \ 318 + impl->name = default_op; \ 319 + } while (false) 320 + 394 321 static int nv_cspmu_init_ops(struct arm_cspmu *cspmu) 395 322 { 396 - u32 prodid; 397 323 struct nv_cspmu_ctx *ctx; 398 324 struct device *dev = cspmu->dev; 399 325 struct arm_cspmu_impl_ops *impl_ops = &cspmu->impl.ops; ··· 410 322 if (!ctx) 411 323 return -ENOMEM; 412 324 413 - prodid = FIELD_GET(ARM_CSPMU_PMIIDR_PRODUCTID, cspmu->impl.pmiidr); 414 - 415 325 /* Find matching PMU. */ 416 326 for (; match->prodid; match++) { 417 327 const u32 prodid_mask = match->prodid_mask; 418 328 419 - if ((match->prodid & prodid_mask) == (prodid & prodid_mask)) 329 + if ((match->prodid & prodid_mask) == 330 + (cspmu->impl.pmiidr & prodid_mask)) 420 331 break; 421 332 } 422 333 423 - ctx->name = nv_cspmu_format_name(cspmu, match); 424 - ctx->filter_mask = match->filter_mask; 425 - ctx->filter_default_val = match->filter_default_val; 426 - ctx->event_attr = match->event_attr; 427 - ctx->format_attr = match->format_attr; 334 + /* Initialize the context with the matched template. */ 335 + memcpy(ctx, &match->template_ctx, sizeof(struct nv_cspmu_ctx)); 336 + ctx->name = nv_cspmu_format_name(cspmu, match); 428 337 429 338 cspmu->impl.ctx = ctx; 430 339 431 340 /* NVIDIA specific callbacks. */ 432 - impl_ops->set_cc_filter = nv_cspmu_set_cc_filter; 433 - impl_ops->set_ev_filter = nv_cspmu_set_ev_filter; 434 - impl_ops->get_event_attrs = nv_cspmu_get_event_attrs; 435 - impl_ops->get_format_attrs = nv_cspmu_get_format_attrs; 436 - impl_ops->get_name = nv_cspmu_get_name; 341 + SET_OP(set_cc_filter, impl_ops, match, nv_cspmu_set_cc_filter); 342 + SET_OP(set_ev_filter, impl_ops, match, nv_cspmu_set_ev_filter); 343 + SET_OP(get_event_attrs, impl_ops, match, nv_cspmu_get_event_attrs); 344 + SET_OP(get_format_attrs, impl_ops, match, nv_cspmu_get_format_attrs); 345 + SET_OP(get_name, impl_ops, match, nv_cspmu_get_name); 346 + 347 + if (ctx->init_data) 348 + return ctx->init_data(cspmu); 437 349 438 350 return 0; 439 351 }
+6
drivers/perf/arm_pmu.c
··· 928 928 if (ret) 929 929 return ret; 930 930 931 + /* 932 + * By this stage we know our supported CPUs on either DT/ACPI platforms, 933 + * detect the SMT implementation. 934 + */ 935 + pmu->has_smt = topology_core_has_smt(cpumask_first(&pmu->supported_cpus)); 936 + 931 937 if (!pmu->set_event_filter) 932 938 pmu->pmu.capabilities |= PERF_PMU_CAP_NO_EXCLUDE; 933 939
+24
drivers/perf/arm_pmuv3.c
··· 981 981 static bool armv8pmu_can_use_pmccntr(struct pmu_hw_events *cpuc, 982 982 struct perf_event *event) 983 983 { 984 + struct arm_pmu *cpu_pmu = to_arm_pmu(event->pmu); 984 985 struct hw_perf_event *hwc = &event->hw; 985 986 unsigned long evtype = hwc->config_base & ARMV8_PMU_EVTYPE_EVENT; 986 987 ··· 1000 999 * So don't use it for branch events. 1001 1000 */ 1002 1001 if (has_branch_stack(event)) 1002 + return false; 1003 + 1004 + /* 1005 + * The PMCCNTR_EL0 increments from the processor clock rather than 1006 + * the PE clock (ARM DDI0487 L.b D13.1.3) which means it'll continue 1007 + * counting on a WFI PE if one of its SMT sibling is not idle on a 1008 + * multi-threaded implementation. So don't use it on SMT cores. 1009 + */ 1010 + if (cpu_pmu->has_smt) 1003 1011 return false; 1004 1012 1005 1013 return true; ··· 1475 1465 1476 1466 PMUV3_INIT_SIMPLE(armv8_pmuv3) 1477 1467 1468 + PMUV3_INIT_SIMPLE(armv8_c1_nano) 1469 + PMUV3_INIT_SIMPLE(armv8_c1_premium) 1470 + PMUV3_INIT_SIMPLE(armv8_c1_pro) 1471 + PMUV3_INIT_SIMPLE(armv8_c1_ultra) 1478 1472 PMUV3_INIT_SIMPLE(armv8_cortex_a34) 1479 1473 PMUV3_INIT_SIMPLE(armv8_cortex_a55) 1480 1474 PMUV3_INIT_SIMPLE(armv8_cortex_a65) ··· 1486 1472 PMUV3_INIT_SIMPLE(armv8_cortex_a76) 1487 1473 PMUV3_INIT_SIMPLE(armv8_cortex_a77) 1488 1474 PMUV3_INIT_SIMPLE(armv8_cortex_a78) 1475 + PMUV3_INIT_SIMPLE(armv9_cortex_a320) 1489 1476 PMUV3_INIT_SIMPLE(armv9_cortex_a510) 1490 1477 PMUV3_INIT_SIMPLE(armv9_cortex_a520) 1478 + PMUV3_INIT_SIMPLE(armv9_cortex_a520ae) 1491 1479 PMUV3_INIT_SIMPLE(armv9_cortex_a710) 1492 1480 PMUV3_INIT_SIMPLE(armv9_cortex_a715) 1493 1481 PMUV3_INIT_SIMPLE(armv9_cortex_a720) 1482 + PMUV3_INIT_SIMPLE(armv9_cortex_a720ae) 1494 1483 PMUV3_INIT_SIMPLE(armv9_cortex_a725) 1495 1484 PMUV3_INIT_SIMPLE(armv8_cortex_x1) 1496 1485 PMUV3_INIT_SIMPLE(armv9_cortex_x2) ··· 1525 1508 1526 1509 static const struct of_device_id armv8_pmu_of_device_ids[] = { 1527 1510 {.compatible = "arm,armv8-pmuv3", .data = armv8_pmuv3_pmu_init}, 1511 + {.compatible = "arm,c1-nano-pmu", .data = armv8_c1_nano_pmu_init}, 1512 + {.compatible = "arm,c1-premium-pmu", .data = armv8_c1_premium_pmu_init}, 1513 + {.compatible = "arm,c1-pro-pmu", .data = armv8_c1_pro_pmu_init}, 1514 + {.compatible = "arm,c1-ultra-pmu", .data = armv8_c1_ultra_pmu_init}, 1528 1515 {.compatible = "arm,cortex-a34-pmu", .data = armv8_cortex_a34_pmu_init}, 1529 1516 {.compatible = "arm,cortex-a35-pmu", .data = armv8_cortex_a35_pmu_init}, 1530 1517 {.compatible = "arm,cortex-a53-pmu", .data = armv8_cortex_a53_pmu_init}, ··· 1541 1520 {.compatible = "arm,cortex-a76-pmu", .data = armv8_cortex_a76_pmu_init}, 1542 1521 {.compatible = "arm,cortex-a77-pmu", .data = armv8_cortex_a77_pmu_init}, 1543 1522 {.compatible = "arm,cortex-a78-pmu", .data = armv8_cortex_a78_pmu_init}, 1523 + {.compatible = "arm,cortex-a320-pmu", .data = armv9_cortex_a320_pmu_init}, 1544 1524 {.compatible = "arm,cortex-a510-pmu", .data = armv9_cortex_a510_pmu_init}, 1545 1525 {.compatible = "arm,cortex-a520-pmu", .data = armv9_cortex_a520_pmu_init}, 1526 + {.compatible = "arm,cortex-a520ae-pmu", .data = armv9_cortex_a520ae_pmu_init}, 1546 1527 {.compatible = "arm,cortex-a710-pmu", .data = armv9_cortex_a710_pmu_init}, 1547 1528 {.compatible = "arm,cortex-a715-pmu", .data = armv9_cortex_a715_pmu_init}, 1548 1529 {.compatible = "arm,cortex-a720-pmu", .data = armv9_cortex_a720_pmu_init}, 1530 + {.compatible = "arm,cortex-a720ae-pmu", .data = armv9_cortex_a720ae_pmu_init}, 1549 1531 {.compatible = "arm,cortex-a725-pmu", .data = armv9_cortex_a725_pmu_init}, 1550 1532 {.compatible = "arm,cortex-x1-pmu", .data = armv8_cortex_x1_pmu_init}, 1551 1533 {.compatible = "arm,cortex-x2-pmu", .data = armv9_cortex_x2_pmu_init},
+37
drivers/perf/arm_spe_pmu.c
··· 87 87 #define SPE_PMU_FEAT_INV_FILT_EVT (1UL << 6) 88 88 #define SPE_PMU_FEAT_DISCARD (1UL << 7) 89 89 #define SPE_PMU_FEAT_EFT (1UL << 8) 90 + #define SPE_PMU_FEAT_FDS (1UL << 9) 90 91 #define SPE_PMU_FEAT_DEV_PROBED (1UL << 63) 91 92 u64 features; 92 93 ··· 253 252 #define ATTR_CFG_FLD_inv_event_filter_LO 0 254 253 #define ATTR_CFG_FLD_inv_event_filter_HI 63 255 254 255 + #define ATTR_CFG_FLD_inv_data_src_filter_CFG config4 /* inverse of PMSDSFR_EL1 */ 256 + #define ATTR_CFG_FLD_inv_data_src_filter_LO 0 257 + #define ATTR_CFG_FLD_inv_data_src_filter_HI 63 258 + 256 259 GEN_PMU_FORMAT_ATTR(ts_enable); 257 260 GEN_PMU_FORMAT_ATTR(pa_enable); 258 261 GEN_PMU_FORMAT_ATTR(pct_enable); ··· 273 268 GEN_PMU_FORMAT_ATTR(float_filter_mask); 274 269 GEN_PMU_FORMAT_ATTR(event_filter); 275 270 GEN_PMU_FORMAT_ATTR(inv_event_filter); 271 + GEN_PMU_FORMAT_ATTR(inv_data_src_filter); 276 272 GEN_PMU_FORMAT_ATTR(min_latency); 277 273 GEN_PMU_FORMAT_ATTR(discard); 278 274 ··· 294 288 &format_attr_float_filter_mask.attr, 295 289 &format_attr_event_filter.attr, 296 290 &format_attr_inv_event_filter.attr, 291 + &format_attr_inv_data_src_filter.attr, 297 292 &format_attr_min_latency.attr, 298 293 &format_attr_discard.attr, 299 294 NULL, ··· 311 304 return 0; 312 305 313 306 if (attr == &format_attr_inv_event_filter.attr && !(spe_pmu->features & SPE_PMU_FEAT_INV_FILT_EVT)) 307 + return 0; 308 + 309 + if (attr == &format_attr_inv_data_src_filter.attr && 310 + !(spe_pmu->features & SPE_PMU_FEAT_FDS)) 314 311 return 0; 315 312 316 313 if ((attr == &format_attr_branch_filter_mask.attr || ··· 441 430 if (ATTR_CFG_GET_FLD(attr, inv_event_filter)) 442 431 reg |= PMSFCR_EL1_FnE; 443 432 433 + if (ATTR_CFG_GET_FLD(attr, inv_data_src_filter)) 434 + reg |= PMSFCR_EL1_FDS; 435 + 444 436 if (ATTR_CFG_GET_FLD(attr, min_latency)) 445 437 reg |= PMSFCR_EL1_FL; 446 438 ··· 466 452 { 467 453 struct perf_event_attr *attr = &event->attr; 468 454 return FIELD_PREP(PMSLATFR_EL1_MINLAT, ATTR_CFG_GET_FLD(attr, min_latency)); 455 + } 456 + 457 + static u64 arm_spe_event_to_pmsdsfr(struct perf_event *event) 458 + { 459 + struct perf_event_attr *attr = &event->attr; 460 + 461 + /* 462 + * Data src filter is inverted so that the default value of 0 is 463 + * equivalent to no filtering. 464 + */ 465 + return ~ATTR_CFG_GET_FLD(attr, inv_data_src_filter); 469 466 } 470 467 471 468 static void arm_spe_pmu_pad_buf(struct perf_output_handle *handle, int len) ··· 816 791 if (arm_spe_event_to_pmsnevfr(event) & spe_pmu->pmsevfr_res0) 817 792 return -EOPNOTSUPP; 818 793 794 + if (arm_spe_event_to_pmsdsfr(event) != U64_MAX && 795 + !(spe_pmu->features & SPE_PMU_FEAT_FDS)) 796 + return -EOPNOTSUPP; 797 + 819 798 if (attr->exclude_idle) 820 799 return -EOPNOTSUPP; 821 800 ··· 893 864 if (spe_pmu->features & SPE_PMU_FEAT_INV_FILT_EVT) { 894 865 reg = arm_spe_event_to_pmsnevfr(event); 895 866 write_sysreg_s(reg, SYS_PMSNEVFR_EL1); 867 + } 868 + 869 + if (spe_pmu->features & SPE_PMU_FEAT_FDS) { 870 + reg = arm_spe_event_to_pmsdsfr(event); 871 + write_sysreg_s(reg, SYS_PMSDSFR_EL1); 896 872 } 897 873 898 874 reg = arm_spe_event_to_pmslatfr(event); ··· 1158 1124 1159 1125 if (FIELD_GET(PMSIDR_EL1_EFT, reg)) 1160 1126 spe_pmu->features |= SPE_PMU_FEAT_EFT; 1127 + 1128 + if (FIELD_GET(PMSIDR_EL1_FDS, reg)) 1129 + spe_pmu->features |= SPE_PMU_FEAT_FDS; 1161 1130 1162 1131 /* This field has a spaced out encoding, so just use a look-up */ 1163 1132 fld = FIELD_GET(PMSIDR_EL1_INTERVAL, reg);
+79 -16
drivers/perf/fsl_imx8_ddr_perf.c
··· 5 5 */ 6 6 7 7 #include <linux/bitfield.h> 8 + #include <linux/clk.h> 8 9 #include <linux/init.h> 9 10 #include <linux/interrupt.h> 10 11 #include <linux/io.h> ··· 53 52 #define to_ddr_pmu(p) container_of(p, struct ddr_pmu, pmu) 54 53 55 54 #define DDR_PERF_DEV_NAME "imx8_ddr" 55 + #define DB_PERF_DEV_NAME "imx8_db" 56 56 #define DDR_CPUHP_CB_NAME DDR_PERF_DEV_NAME "_perf_pmu" 57 57 58 58 static DEFINE_IDA(ddr_ida); 59 + static DEFINE_IDA(db_ida); 59 60 60 61 /* DDR Perf hardware feature */ 61 62 #define DDR_CAP_AXI_ID_FILTER 0x1 /* support AXI ID filter */ 62 63 #define DDR_CAP_AXI_ID_FILTER_ENHANCED 0x3 /* support enhanced AXI ID filter */ 63 64 #define DDR_CAP_AXI_ID_PORT_CHANNEL_FILTER 0x4 /* support AXI ID PORT CHANNEL filter */ 64 65 66 + /* Perf type */ 67 + enum fsl_ddr_type { 68 + DDR_PERF_TYPE = 0, /* ddr Perf (default) */ 69 + DB_PERF_TYPE, /* db Perf */ 70 + }; 71 + 65 72 struct fsl_ddr_devtype_data { 66 73 unsigned int quirks; /* quirks needed for different DDR Perf core */ 67 74 const char *identifier; /* system PMU identifier for userspace */ 75 + enum fsl_ddr_type type; /* types of Perf, ddr or db */ 68 76 }; 69 77 70 78 static const struct fsl_ddr_devtype_data imx8_devtype_data; ··· 107 97 .identifier = "i.MX8DXL", 108 98 }; 109 99 100 + static const struct fsl_ddr_devtype_data imx8dxl_db_devtype_data = { 101 + .quirks = DDR_CAP_AXI_ID_PORT_CHANNEL_FILTER, 102 + .identifier = "i.MX8DXL", 103 + .type = DB_PERF_TYPE, 104 + }; 105 + 110 106 static const struct of_device_id imx_ddr_pmu_dt_ids[] = { 111 107 { .compatible = "fsl,imx8-ddr-pmu", .data = &imx8_devtype_data}, 112 108 { .compatible = "fsl,imx8m-ddr-pmu", .data = &imx8m_devtype_data}, ··· 121 105 { .compatible = "fsl,imx8mn-ddr-pmu", .data = &imx8mn_devtype_data}, 122 106 { .compatible = "fsl,imx8mp-ddr-pmu", .data = &imx8mp_devtype_data}, 123 107 { .compatible = "fsl,imx8dxl-ddr-pmu", .data = &imx8dxl_devtype_data}, 108 + { .compatible = "fsl,imx8dxl-db-pmu", .data = &imx8dxl_db_devtype_data}, 124 109 { /* sentinel */ } 125 110 }; 126 111 MODULE_DEVICE_TABLE(of, imx_ddr_pmu_dt_ids); ··· 301 284 NULL, 302 285 }; 303 286 287 + static const int ddr_perf_db_visible_event_list[] = { 288 + EVENT_CYCLES_ID, 289 + 0x41, 290 + 0x42, 291 + }; 292 + 293 + static umode_t ddr_perf_events_attrs_is_visible(struct kobject *kobj, 294 + struct attribute *attr, int n) 295 + { 296 + struct device *dev = kobj_to_dev(kobj); 297 + struct ddr_pmu *pmu = dev_get_drvdata(dev); 298 + struct perf_pmu_events_attr *pmu_attr; 299 + unsigned int i; 300 + 301 + pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr.attr); 302 + 303 + if (pmu->devtype_data->type == DDR_PERF_TYPE) 304 + return attr->mode; 305 + 306 + /* DB Type */ 307 + for (i = 0; i < ARRAY_SIZE(ddr_perf_db_visible_event_list); i++) 308 + if (pmu_attr->id == ddr_perf_db_visible_event_list[i]) 309 + return attr->mode; 310 + 311 + return 0; 312 + } 313 + 304 314 static const struct attribute_group ddr_perf_events_attr_group = { 305 315 .name = "events", 306 316 .attrs = ddr_perf_events_attrs, 317 + .is_visible = ddr_perf_events_attrs_is_visible, 307 318 }; 308 319 309 320 PMU_FORMAT_ATTR(event, "config:0-7"); ··· 690 645 { 691 646 } 692 647 693 - static int ddr_perf_init(struct ddr_pmu *pmu, void __iomem *base, 694 - struct device *dev) 648 + static void ddr_perf_init(struct ddr_pmu *pmu, void __iomem *base, 649 + struct device *dev) 695 650 { 696 651 *pmu = (struct ddr_pmu) { 697 652 .pmu = (struct pmu) { ··· 712 667 .base = base, 713 668 .dev = dev, 714 669 }; 715 - 716 - pmu->id = ida_alloc(&ddr_ida, GFP_KERNEL); 717 - return pmu->id; 718 670 } 719 671 720 672 static irqreturn_t ddr_perf_irq_handler(int irq, void *p) ··· 777 735 778 736 static int ddr_perf_probe(struct platform_device *pdev) 779 737 { 738 + struct clk_bulk_data *clks; 780 739 struct ddr_pmu *pmu; 781 740 struct device_node *np; 782 741 void __iomem *base; 742 + struct ida *ida; 783 743 char *name; 744 + int nclks; 784 745 int num; 785 746 int ret; 786 747 int irq; ··· 798 753 if (!pmu) 799 754 return -ENOMEM; 800 755 801 - num = ddr_perf_init(pmu, base, &pdev->dev); 756 + ddr_perf_init(pmu, base, &pdev->dev); 802 757 803 758 platform_set_drvdata(pdev, pmu); 804 759 805 - name = devm_kasprintf(&pdev->dev, GFP_KERNEL, DDR_PERF_DEV_NAME "%d", 806 - num); 807 - if (!name) { 808 - ret = -ENOMEM; 809 - goto cpuhp_state_err; 810 - } 760 + nclks = devm_clk_bulk_get_all_enabled(&pdev->dev, &clks); 761 + if (nclks < 0) 762 + return dev_err_probe(&pdev->dev, nclks, "Failure get clks\n"); 811 763 812 764 pmu->devtype_data = of_device_get_match_data(&pdev->dev); 765 + 766 + ida = pmu->devtype_data->type == DDR_PERF_TYPE ? &ddr_ida : &db_ida; 767 + num = ida_alloc(ida, GFP_KERNEL); 768 + if (num < 0) 769 + return num; 770 + 771 + pmu->id = num; 772 + 773 + if (pmu->devtype_data->type == DDR_PERF_TYPE) 774 + name = devm_kasprintf(&pdev->dev, GFP_KERNEL, DDR_PERF_DEV_NAME "%d", num); 775 + else 776 + name = devm_kasprintf(&pdev->dev, GFP_KERNEL, DB_PERF_DEV_NAME "%d", num); 777 + 778 + if (!name) { 779 + ret = -ENOMEM; 780 + goto idr_free; 781 + } 813 782 814 783 pmu->cpu = raw_smp_processor_id(); 815 784 ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, ··· 833 774 834 775 if (ret < 0) { 835 776 dev_err(&pdev->dev, "cpuhp_setup_state_multi failed\n"); 836 - goto cpuhp_state_err; 777 + goto idr_free; 837 778 } 838 779 839 780 pmu->cpuhp_state = ret; ··· 880 821 cpuhp_state_remove_instance_nocalls(pmu->cpuhp_state, &pmu->node); 881 822 cpuhp_instance_err: 882 823 cpuhp_remove_multi_state(pmu->cpuhp_state); 883 - cpuhp_state_err: 884 - ida_free(&ddr_ida, pmu->id); 824 + idr_free: 825 + ida_free(ida, pmu->id); 885 826 dev_warn(&pdev->dev, "i.MX8 DDR Perf PMU failed (%d), disabled\n", ret); 886 827 return ret; 887 828 } ··· 895 836 896 837 perf_pmu_unregister(&pmu->pmu); 897 838 898 - ida_free(&ddr_ida, pmu->id); 839 + if (pmu->devtype_data->type == DDR_PERF_TYPE) 840 + ida_free(&ddr_ida, pmu->id); 841 + else 842 + ida_free(&db_ida, pmu->id); 843 + 899 844 } 900 845 901 846 static struct platform_driver imx_ddr_pmu_driver = {
+24
drivers/resctrl/Kconfig
··· 1 + menuconfig ARM64_MPAM_DRIVER 2 + bool "MPAM driver" 3 + depends on ARM64 && ARM64_MPAM && EXPERT 4 + help 5 + Memory System Resource Partitioning and Monitoring (MPAM) driver for 6 + System IP, e.g. caches and memory controllers. 7 + 8 + if ARM64_MPAM_DRIVER 9 + 10 + config ARM64_MPAM_DRIVER_DEBUG 11 + bool "Enable debug messages from the MPAM driver" 12 + help 13 + Say yes here to enable debug messages from the MPAM driver. 14 + 15 + config MPAM_KUNIT_TEST 16 + bool "KUnit tests for MPAM driver " if !KUNIT_ALL_TESTS 17 + depends on KUNIT=y 18 + default KUNIT_ALL_TESTS 19 + help 20 + Enable this option to run tests in the MPAM driver. 21 + 22 + If unsure, say N. 23 + 24 + endif
+4
drivers/resctrl/Makefile
··· 1 + obj-$(CONFIG_ARM64_MPAM_DRIVER) += mpam.o 2 + mpam-y += mpam_devices.o 3 + 4 + ccflags-$(CONFIG_ARM64_MPAM_DRIVER_DEBUG) += -DDEBUG
+2723
drivers/resctrl/mpam_devices.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (C) 2025 Arm Ltd. 3 + 4 + #define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__ 5 + 6 + #include <linux/acpi.h> 7 + #include <linux/atomic.h> 8 + #include <linux/arm_mpam.h> 9 + #include <linux/bitfield.h> 10 + #include <linux/bitmap.h> 11 + #include <linux/cacheinfo.h> 12 + #include <linux/cpu.h> 13 + #include <linux/cpumask.h> 14 + #include <linux/device.h> 15 + #include <linux/errno.h> 16 + #include <linux/gfp.h> 17 + #include <linux/interrupt.h> 18 + #include <linux/irq.h> 19 + #include <linux/irqdesc.h> 20 + #include <linux/list.h> 21 + #include <linux/lockdep.h> 22 + #include <linux/mutex.h> 23 + #include <linux/platform_device.h> 24 + #include <linux/printk.h> 25 + #include <linux/srcu.h> 26 + #include <linux/spinlock.h> 27 + #include <linux/types.h> 28 + #include <linux/workqueue.h> 29 + 30 + #include "mpam_internal.h" 31 + 32 + DEFINE_STATIC_KEY_FALSE(mpam_enabled); /* This moves to arch code */ 33 + 34 + /* 35 + * mpam_list_lock protects the SRCU lists when writing. Once the 36 + * mpam_enabled key is enabled these lists are read-only, 37 + * unless the error interrupt disables the driver. 38 + */ 39 + static DEFINE_MUTEX(mpam_list_lock); 40 + static LIST_HEAD(mpam_all_msc); 41 + 42 + struct srcu_struct mpam_srcu; 43 + 44 + /* 45 + * Number of MSCs that have been probed. Once all MSCs have been probed MPAM 46 + * can be enabled. 47 + */ 48 + static atomic_t mpam_num_msc; 49 + 50 + static int mpam_cpuhp_state; 51 + static DEFINE_MUTEX(mpam_cpuhp_state_lock); 52 + 53 + /* 54 + * The smallest common values for any CPU or MSC in the system. 55 + * Generating traffic outside this range will result in screaming interrupts. 56 + */ 57 + u16 mpam_partid_max; 58 + u8 mpam_pmg_max; 59 + static bool partid_max_init, partid_max_published; 60 + static DEFINE_SPINLOCK(partid_max_lock); 61 + 62 + /* 63 + * mpam is enabled once all devices have been probed from CPU online callbacks, 64 + * scheduled via this work_struct. If access to an MSC depends on a CPU that 65 + * was not brought online at boot, this can happen surprisingly late. 66 + */ 67 + static DECLARE_WORK(mpam_enable_work, &mpam_enable); 68 + 69 + /* 70 + * All mpam error interrupts indicate a software bug. On receipt, disable the 71 + * driver. 72 + */ 73 + static DECLARE_WORK(mpam_broken_work, &mpam_disable); 74 + 75 + /* When mpam is disabled, the printed reason to aid debugging */ 76 + static char *mpam_disable_reason; 77 + 78 + /* 79 + * An MSC is a physical container for controls and monitors, each identified by 80 + * their RIS index. These share a base-address, interrupts and some MMIO 81 + * registers. A vMSC is a virtual container for RIS in an MSC that control or 82 + * monitor the same thing. Members of a vMSC are all RIS in the same MSC, but 83 + * not all RIS in an MSC share a vMSC. 84 + * 85 + * Components are a group of vMSC that control or monitor the same thing but 86 + * are from different MSC, so have different base-address, interrupts etc. 87 + * Classes are the set components of the same type. 88 + * 89 + * The features of a vMSC is the union of the RIS it contains. 90 + * The features of a Class and Component are the common subset of the vMSC 91 + * they contain. 92 + * 93 + * e.g. The system cache may have bandwidth controls on multiple interfaces, 94 + * for regulating traffic from devices independently of traffic from CPUs. 95 + * If these are two RIS in one MSC, they will be treated as controlling 96 + * different things, and will not share a vMSC/component/class. 97 + * 98 + * e.g. The L2 may have one MSC and two RIS, one for cache-controls another 99 + * for bandwidth. These two RIS are members of the same vMSC. 100 + * 101 + * e.g. The set of RIS that make up the L2 are grouped as a component. These 102 + * are sometimes termed slices. They should be configured the same, as if there 103 + * were only one. 104 + * 105 + * e.g. The SoC probably has more than one L2, each attached to a distinct set 106 + * of CPUs. All the L2 components are grouped as a class. 107 + * 108 + * When creating an MSC, struct mpam_msc is added to the all mpam_all_msc list, 109 + * then linked via struct mpam_ris to a vmsc, component and class. 110 + * The same MSC may exist under different class->component->vmsc paths, but the 111 + * RIS index will be unique. 112 + */ 113 + LIST_HEAD(mpam_classes); 114 + 115 + /* List of all objects that can be free()d after synchronise_srcu() */ 116 + static LLIST_HEAD(mpam_garbage); 117 + 118 + static inline void init_garbage(struct mpam_garbage *garbage) 119 + { 120 + init_llist_node(&garbage->llist); 121 + } 122 + 123 + #define add_to_garbage(x) \ 124 + do { \ 125 + __typeof__(x) _x = (x); \ 126 + _x->garbage.to_free = _x; \ 127 + llist_add(&_x->garbage.llist, &mpam_garbage); \ 128 + } while (0) 129 + 130 + static void mpam_free_garbage(void) 131 + { 132 + struct mpam_garbage *iter, *tmp; 133 + struct llist_node *to_free = llist_del_all(&mpam_garbage); 134 + 135 + if (!to_free) 136 + return; 137 + 138 + synchronize_srcu(&mpam_srcu); 139 + 140 + llist_for_each_entry_safe(iter, tmp, to_free, llist) { 141 + if (iter->pdev) 142 + devm_kfree(&iter->pdev->dev, iter->to_free); 143 + else 144 + kfree(iter->to_free); 145 + } 146 + } 147 + 148 + /* 149 + * Once mpam is enabled, new requestors cannot further reduce the available 150 + * partid. Assert that the size is fixed, and new requestors will be turned 151 + * away. 152 + */ 153 + static void mpam_assert_partid_sizes_fixed(void) 154 + { 155 + WARN_ON_ONCE(!partid_max_published); 156 + } 157 + 158 + static u32 __mpam_read_reg(struct mpam_msc *msc, u16 reg) 159 + { 160 + WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &msc->accessibility)); 161 + 162 + return readl_relaxed(msc->mapped_hwpage + reg); 163 + } 164 + 165 + static inline u32 _mpam_read_partsel_reg(struct mpam_msc *msc, u16 reg) 166 + { 167 + lockdep_assert_held_once(&msc->part_sel_lock); 168 + return __mpam_read_reg(msc, reg); 169 + } 170 + 171 + #define mpam_read_partsel_reg(msc, reg) _mpam_read_partsel_reg(msc, MPAMF_##reg) 172 + 173 + static void __mpam_write_reg(struct mpam_msc *msc, u16 reg, u32 val) 174 + { 175 + WARN_ON_ONCE(reg + sizeof(u32) > msc->mapped_hwpage_sz); 176 + WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &msc->accessibility)); 177 + 178 + writel_relaxed(val, msc->mapped_hwpage + reg); 179 + } 180 + 181 + static inline void _mpam_write_partsel_reg(struct mpam_msc *msc, u16 reg, u32 val) 182 + { 183 + lockdep_assert_held_once(&msc->part_sel_lock); 184 + __mpam_write_reg(msc, reg, val); 185 + } 186 + 187 + #define mpam_write_partsel_reg(msc, reg, val) _mpam_write_partsel_reg(msc, MPAMCFG_##reg, val) 188 + 189 + static inline u32 _mpam_read_monsel_reg(struct mpam_msc *msc, u16 reg) 190 + { 191 + mpam_mon_sel_lock_held(msc); 192 + return __mpam_read_reg(msc, reg); 193 + } 194 + 195 + #define mpam_read_monsel_reg(msc, reg) _mpam_read_monsel_reg(msc, MSMON_##reg) 196 + 197 + static inline void _mpam_write_monsel_reg(struct mpam_msc *msc, u16 reg, u32 val) 198 + { 199 + mpam_mon_sel_lock_held(msc); 200 + __mpam_write_reg(msc, reg, val); 201 + } 202 + 203 + #define mpam_write_monsel_reg(msc, reg, val) _mpam_write_monsel_reg(msc, MSMON_##reg, val) 204 + 205 + static u64 mpam_msc_read_idr(struct mpam_msc *msc) 206 + { 207 + u64 idr_high = 0, idr_low; 208 + 209 + lockdep_assert_held(&msc->part_sel_lock); 210 + 211 + idr_low = mpam_read_partsel_reg(msc, IDR); 212 + if (FIELD_GET(MPAMF_IDR_EXT, idr_low)) 213 + idr_high = mpam_read_partsel_reg(msc, IDR + 4); 214 + 215 + return (idr_high << 32) | idr_low; 216 + } 217 + 218 + static void mpam_msc_clear_esr(struct mpam_msc *msc) 219 + { 220 + u64 esr_low = __mpam_read_reg(msc, MPAMF_ESR); 221 + 222 + if (!esr_low) 223 + return; 224 + 225 + /* 226 + * Clearing the high/low bits of MPAMF_ESR can not be atomic. 227 + * Clear the top half first, so that the pending error bits in the 228 + * lower half prevent hardware from updating either half of the 229 + * register. 230 + */ 231 + if (msc->has_extd_esr) 232 + __mpam_write_reg(msc, MPAMF_ESR + 4, 0); 233 + __mpam_write_reg(msc, MPAMF_ESR, 0); 234 + } 235 + 236 + static u64 mpam_msc_read_esr(struct mpam_msc *msc) 237 + { 238 + u64 esr_high = 0, esr_low; 239 + 240 + esr_low = __mpam_read_reg(msc, MPAMF_ESR); 241 + if (msc->has_extd_esr) 242 + esr_high = __mpam_read_reg(msc, MPAMF_ESR + 4); 243 + 244 + return (esr_high << 32) | esr_low; 245 + } 246 + 247 + static void __mpam_part_sel_raw(u32 partsel, struct mpam_msc *msc) 248 + { 249 + lockdep_assert_held(&msc->part_sel_lock); 250 + 251 + mpam_write_partsel_reg(msc, PART_SEL, partsel); 252 + } 253 + 254 + static void __mpam_part_sel(u8 ris_idx, u16 partid, struct mpam_msc *msc) 255 + { 256 + u32 partsel = FIELD_PREP(MPAMCFG_PART_SEL_RIS, ris_idx) | 257 + FIELD_PREP(MPAMCFG_PART_SEL_PARTID_SEL, partid); 258 + 259 + __mpam_part_sel_raw(partsel, msc); 260 + } 261 + 262 + static void __mpam_intpart_sel(u8 ris_idx, u16 intpartid, struct mpam_msc *msc) 263 + { 264 + u32 partsel = FIELD_PREP(MPAMCFG_PART_SEL_RIS, ris_idx) | 265 + FIELD_PREP(MPAMCFG_PART_SEL_PARTID_SEL, intpartid) | 266 + MPAMCFG_PART_SEL_INTERNAL; 267 + 268 + __mpam_part_sel_raw(partsel, msc); 269 + } 270 + 271 + int mpam_register_requestor(u16 partid_max, u8 pmg_max) 272 + { 273 + guard(spinlock)(&partid_max_lock); 274 + if (!partid_max_init) { 275 + mpam_partid_max = partid_max; 276 + mpam_pmg_max = pmg_max; 277 + partid_max_init = true; 278 + } else if (!partid_max_published) { 279 + mpam_partid_max = min(mpam_partid_max, partid_max); 280 + mpam_pmg_max = min(mpam_pmg_max, pmg_max); 281 + } else { 282 + /* New requestors can't lower the values */ 283 + if (partid_max < mpam_partid_max || pmg_max < mpam_pmg_max) 284 + return -EBUSY; 285 + } 286 + 287 + return 0; 288 + } 289 + EXPORT_SYMBOL(mpam_register_requestor); 290 + 291 + static struct mpam_class * 292 + mpam_class_alloc(u8 level_idx, enum mpam_class_types type) 293 + { 294 + struct mpam_class *class; 295 + 296 + lockdep_assert_held(&mpam_list_lock); 297 + 298 + class = kzalloc(sizeof(*class), GFP_KERNEL); 299 + if (!class) 300 + return ERR_PTR(-ENOMEM); 301 + init_garbage(&class->garbage); 302 + 303 + INIT_LIST_HEAD_RCU(&class->components); 304 + /* Affinity is updated when ris are added */ 305 + class->level = level_idx; 306 + class->type = type; 307 + INIT_LIST_HEAD_RCU(&class->classes_list); 308 + ida_init(&class->ida_csu_mon); 309 + ida_init(&class->ida_mbwu_mon); 310 + 311 + list_add_rcu(&class->classes_list, &mpam_classes); 312 + 313 + return class; 314 + } 315 + 316 + static void mpam_class_destroy(struct mpam_class *class) 317 + { 318 + lockdep_assert_held(&mpam_list_lock); 319 + 320 + list_del_rcu(&class->classes_list); 321 + add_to_garbage(class); 322 + } 323 + 324 + static struct mpam_class * 325 + mpam_class_find(u8 level_idx, enum mpam_class_types type) 326 + { 327 + struct mpam_class *class; 328 + 329 + lockdep_assert_held(&mpam_list_lock); 330 + 331 + list_for_each_entry(class, &mpam_classes, classes_list) { 332 + if (class->type == type && class->level == level_idx) 333 + return class; 334 + } 335 + 336 + return mpam_class_alloc(level_idx, type); 337 + } 338 + 339 + static struct mpam_component * 340 + mpam_component_alloc(struct mpam_class *class, int id) 341 + { 342 + struct mpam_component *comp; 343 + 344 + lockdep_assert_held(&mpam_list_lock); 345 + 346 + comp = kzalloc(sizeof(*comp), GFP_KERNEL); 347 + if (!comp) 348 + return ERR_PTR(-ENOMEM); 349 + init_garbage(&comp->garbage); 350 + 351 + comp->comp_id = id; 352 + INIT_LIST_HEAD_RCU(&comp->vmsc); 353 + /* Affinity is updated when RIS are added */ 354 + INIT_LIST_HEAD_RCU(&comp->class_list); 355 + comp->class = class; 356 + 357 + list_add_rcu(&comp->class_list, &class->components); 358 + 359 + return comp; 360 + } 361 + 362 + static void __destroy_component_cfg(struct mpam_component *comp); 363 + 364 + static void mpam_component_destroy(struct mpam_component *comp) 365 + { 366 + struct mpam_class *class = comp->class; 367 + 368 + lockdep_assert_held(&mpam_list_lock); 369 + 370 + __destroy_component_cfg(comp); 371 + 372 + list_del_rcu(&comp->class_list); 373 + add_to_garbage(comp); 374 + 375 + if (list_empty(&class->components)) 376 + mpam_class_destroy(class); 377 + } 378 + 379 + static struct mpam_component * 380 + mpam_component_find(struct mpam_class *class, int id) 381 + { 382 + struct mpam_component *comp; 383 + 384 + lockdep_assert_held(&mpam_list_lock); 385 + 386 + list_for_each_entry(comp, &class->components, class_list) { 387 + if (comp->comp_id == id) 388 + return comp; 389 + } 390 + 391 + return mpam_component_alloc(class, id); 392 + } 393 + 394 + static struct mpam_vmsc * 395 + mpam_vmsc_alloc(struct mpam_component *comp, struct mpam_msc *msc) 396 + { 397 + struct mpam_vmsc *vmsc; 398 + 399 + lockdep_assert_held(&mpam_list_lock); 400 + 401 + vmsc = kzalloc(sizeof(*vmsc), GFP_KERNEL); 402 + if (!vmsc) 403 + return ERR_PTR(-ENOMEM); 404 + init_garbage(&vmsc->garbage); 405 + 406 + INIT_LIST_HEAD_RCU(&vmsc->ris); 407 + INIT_LIST_HEAD_RCU(&vmsc->comp_list); 408 + vmsc->comp = comp; 409 + vmsc->msc = msc; 410 + 411 + list_add_rcu(&vmsc->comp_list, &comp->vmsc); 412 + 413 + return vmsc; 414 + } 415 + 416 + static void mpam_vmsc_destroy(struct mpam_vmsc *vmsc) 417 + { 418 + struct mpam_component *comp = vmsc->comp; 419 + 420 + lockdep_assert_held(&mpam_list_lock); 421 + 422 + list_del_rcu(&vmsc->comp_list); 423 + add_to_garbage(vmsc); 424 + 425 + if (list_empty(&comp->vmsc)) 426 + mpam_component_destroy(comp); 427 + } 428 + 429 + static struct mpam_vmsc * 430 + mpam_vmsc_find(struct mpam_component *comp, struct mpam_msc *msc) 431 + { 432 + struct mpam_vmsc *vmsc; 433 + 434 + lockdep_assert_held(&mpam_list_lock); 435 + 436 + list_for_each_entry(vmsc, &comp->vmsc, comp_list) { 437 + if (vmsc->msc->id == msc->id) 438 + return vmsc; 439 + } 440 + 441 + return mpam_vmsc_alloc(comp, msc); 442 + } 443 + 444 + /* 445 + * The cacheinfo structures are only populated when CPUs are online. 446 + * This helper walks the acpi tables to include offline CPUs too. 447 + */ 448 + int mpam_get_cpumask_from_cache_id(unsigned long cache_id, u32 cache_level, 449 + cpumask_t *affinity) 450 + { 451 + return acpi_pptt_get_cpumask_from_cache_id(cache_id, affinity); 452 + } 453 + 454 + /* 455 + * cpumask_of_node() only knows about online CPUs. This can't tell us whether 456 + * a class is represented on all possible CPUs. 457 + */ 458 + static void get_cpumask_from_node_id(u32 node_id, cpumask_t *affinity) 459 + { 460 + int cpu; 461 + 462 + for_each_possible_cpu(cpu) { 463 + if (node_id == cpu_to_node(cpu)) 464 + cpumask_set_cpu(cpu, affinity); 465 + } 466 + } 467 + 468 + static int mpam_ris_get_affinity(struct mpam_msc *msc, cpumask_t *affinity, 469 + enum mpam_class_types type, 470 + struct mpam_class *class, 471 + struct mpam_component *comp) 472 + { 473 + int err; 474 + 475 + switch (type) { 476 + case MPAM_CLASS_CACHE: 477 + err = mpam_get_cpumask_from_cache_id(comp->comp_id, class->level, 478 + affinity); 479 + if (err) { 480 + dev_warn_once(&msc->pdev->dev, 481 + "Failed to determine CPU affinity\n"); 482 + return err; 483 + } 484 + 485 + if (cpumask_empty(affinity)) 486 + dev_warn_once(&msc->pdev->dev, "no CPUs associated with cache node\n"); 487 + 488 + break; 489 + case MPAM_CLASS_MEMORY: 490 + get_cpumask_from_node_id(comp->comp_id, affinity); 491 + /* affinity may be empty for CPU-less memory nodes */ 492 + break; 493 + case MPAM_CLASS_UNKNOWN: 494 + return 0; 495 + } 496 + 497 + cpumask_and(affinity, affinity, &msc->accessibility); 498 + 499 + return 0; 500 + } 501 + 502 + static int mpam_ris_create_locked(struct mpam_msc *msc, u8 ris_idx, 503 + enum mpam_class_types type, u8 class_id, 504 + int component_id) 505 + { 506 + int err; 507 + struct mpam_vmsc *vmsc; 508 + struct mpam_msc_ris *ris; 509 + struct mpam_class *class; 510 + struct mpam_component *comp; 511 + struct platform_device *pdev = msc->pdev; 512 + 513 + lockdep_assert_held(&mpam_list_lock); 514 + 515 + if (ris_idx > MPAM_MSC_MAX_NUM_RIS) 516 + return -EINVAL; 517 + 518 + if (test_and_set_bit(ris_idx, &msc->ris_idxs)) 519 + return -EBUSY; 520 + 521 + ris = devm_kzalloc(&msc->pdev->dev, sizeof(*ris), GFP_KERNEL); 522 + if (!ris) 523 + return -ENOMEM; 524 + init_garbage(&ris->garbage); 525 + ris->garbage.pdev = pdev; 526 + 527 + class = mpam_class_find(class_id, type); 528 + if (IS_ERR(class)) 529 + return PTR_ERR(class); 530 + 531 + comp = mpam_component_find(class, component_id); 532 + if (IS_ERR(comp)) { 533 + if (list_empty(&class->components)) 534 + mpam_class_destroy(class); 535 + return PTR_ERR(comp); 536 + } 537 + 538 + vmsc = mpam_vmsc_find(comp, msc); 539 + if (IS_ERR(vmsc)) { 540 + if (list_empty(&comp->vmsc)) 541 + mpam_component_destroy(comp); 542 + return PTR_ERR(vmsc); 543 + } 544 + 545 + err = mpam_ris_get_affinity(msc, &ris->affinity, type, class, comp); 546 + if (err) { 547 + if (list_empty(&vmsc->ris)) 548 + mpam_vmsc_destroy(vmsc); 549 + return err; 550 + } 551 + 552 + ris->ris_idx = ris_idx; 553 + INIT_LIST_HEAD_RCU(&ris->msc_list); 554 + INIT_LIST_HEAD_RCU(&ris->vmsc_list); 555 + ris->vmsc = vmsc; 556 + 557 + cpumask_or(&comp->affinity, &comp->affinity, &ris->affinity); 558 + cpumask_or(&class->affinity, &class->affinity, &ris->affinity); 559 + list_add_rcu(&ris->vmsc_list, &vmsc->ris); 560 + list_add_rcu(&ris->msc_list, &msc->ris); 561 + 562 + return 0; 563 + } 564 + 565 + static void mpam_ris_destroy(struct mpam_msc_ris *ris) 566 + { 567 + struct mpam_vmsc *vmsc = ris->vmsc; 568 + struct mpam_msc *msc = vmsc->msc; 569 + struct mpam_component *comp = vmsc->comp; 570 + struct mpam_class *class = comp->class; 571 + 572 + lockdep_assert_held(&mpam_list_lock); 573 + 574 + /* 575 + * It is assumed affinities don't overlap. If they do the class becomes 576 + * unusable immediately. 577 + */ 578 + cpumask_andnot(&class->affinity, &class->affinity, &ris->affinity); 579 + cpumask_andnot(&comp->affinity, &comp->affinity, &ris->affinity); 580 + clear_bit(ris->ris_idx, &msc->ris_idxs); 581 + list_del_rcu(&ris->msc_list); 582 + list_del_rcu(&ris->vmsc_list); 583 + add_to_garbage(ris); 584 + 585 + if (list_empty(&vmsc->ris)) 586 + mpam_vmsc_destroy(vmsc); 587 + } 588 + 589 + int mpam_ris_create(struct mpam_msc *msc, u8 ris_idx, 590 + enum mpam_class_types type, u8 class_id, int component_id) 591 + { 592 + int err; 593 + 594 + mutex_lock(&mpam_list_lock); 595 + err = mpam_ris_create_locked(msc, ris_idx, type, class_id, 596 + component_id); 597 + mutex_unlock(&mpam_list_lock); 598 + if (err) 599 + mpam_free_garbage(); 600 + 601 + return err; 602 + } 603 + 604 + static struct mpam_msc_ris *mpam_get_or_create_ris(struct mpam_msc *msc, 605 + u8 ris_idx) 606 + { 607 + int err; 608 + struct mpam_msc_ris *ris; 609 + 610 + lockdep_assert_held(&mpam_list_lock); 611 + 612 + if (!test_bit(ris_idx, &msc->ris_idxs)) { 613 + err = mpam_ris_create_locked(msc, ris_idx, MPAM_CLASS_UNKNOWN, 614 + 0, 0); 615 + if (err) 616 + return ERR_PTR(err); 617 + } 618 + 619 + list_for_each_entry(ris, &msc->ris, msc_list) { 620 + if (ris->ris_idx == ris_idx) 621 + return ris; 622 + } 623 + 624 + return ERR_PTR(-ENOENT); 625 + } 626 + 627 + /* 628 + * IHI009A.a has this nugget: "If a monitor does not support automatic behaviour 629 + * of NRDY, software can use this bit for any purpose" - so hardware might not 630 + * implement this - but it isn't RES0. 631 + * 632 + * Try and see what values stick in this bit. If we can write either value, 633 + * its probably not implemented by hardware. 634 + */ 635 + static bool _mpam_ris_hw_probe_hw_nrdy(struct mpam_msc_ris *ris, u32 mon_reg) 636 + { 637 + u32 now; 638 + u64 mon_sel; 639 + bool can_set, can_clear; 640 + struct mpam_msc *msc = ris->vmsc->msc; 641 + 642 + if (WARN_ON_ONCE(!mpam_mon_sel_lock(msc))) 643 + return false; 644 + 645 + mon_sel = FIELD_PREP(MSMON_CFG_MON_SEL_MON_SEL, 0) | 646 + FIELD_PREP(MSMON_CFG_MON_SEL_RIS, ris->ris_idx); 647 + _mpam_write_monsel_reg(msc, mon_reg, mon_sel); 648 + 649 + _mpam_write_monsel_reg(msc, mon_reg, MSMON___NRDY); 650 + now = _mpam_read_monsel_reg(msc, mon_reg); 651 + can_set = now & MSMON___NRDY; 652 + 653 + _mpam_write_monsel_reg(msc, mon_reg, 0); 654 + now = _mpam_read_monsel_reg(msc, mon_reg); 655 + can_clear = !(now & MSMON___NRDY); 656 + mpam_mon_sel_unlock(msc); 657 + 658 + return (!can_set || !can_clear); 659 + } 660 + 661 + #define mpam_ris_hw_probe_hw_nrdy(_ris, _mon_reg) \ 662 + _mpam_ris_hw_probe_hw_nrdy(_ris, MSMON_##_mon_reg) 663 + 664 + static void mpam_ris_hw_probe(struct mpam_msc_ris *ris) 665 + { 666 + int err; 667 + struct mpam_msc *msc = ris->vmsc->msc; 668 + struct device *dev = &msc->pdev->dev; 669 + struct mpam_props *props = &ris->props; 670 + struct mpam_class *class = ris->vmsc->comp->class; 671 + 672 + lockdep_assert_held(&msc->probe_lock); 673 + lockdep_assert_held(&msc->part_sel_lock); 674 + 675 + /* Cache Capacity Partitioning */ 676 + if (FIELD_GET(MPAMF_IDR_HAS_CCAP_PART, ris->idr)) { 677 + u32 ccap_features = mpam_read_partsel_reg(msc, CCAP_IDR); 678 + 679 + props->cmax_wd = FIELD_GET(MPAMF_CCAP_IDR_CMAX_WD, ccap_features); 680 + if (props->cmax_wd && 681 + FIELD_GET(MPAMF_CCAP_IDR_HAS_CMAX_SOFTLIM, ccap_features)) 682 + mpam_set_feature(mpam_feat_cmax_softlim, props); 683 + 684 + if (props->cmax_wd && 685 + !FIELD_GET(MPAMF_CCAP_IDR_NO_CMAX, ccap_features)) 686 + mpam_set_feature(mpam_feat_cmax_cmax, props); 687 + 688 + if (props->cmax_wd && 689 + FIELD_GET(MPAMF_CCAP_IDR_HAS_CMIN, ccap_features)) 690 + mpam_set_feature(mpam_feat_cmax_cmin, props); 691 + 692 + props->cassoc_wd = FIELD_GET(MPAMF_CCAP_IDR_CASSOC_WD, ccap_features); 693 + if (props->cassoc_wd && 694 + FIELD_GET(MPAMF_CCAP_IDR_HAS_CASSOC, ccap_features)) 695 + mpam_set_feature(mpam_feat_cmax_cassoc, props); 696 + } 697 + 698 + /* Cache Portion partitioning */ 699 + if (FIELD_GET(MPAMF_IDR_HAS_CPOR_PART, ris->idr)) { 700 + u32 cpor_features = mpam_read_partsel_reg(msc, CPOR_IDR); 701 + 702 + props->cpbm_wd = FIELD_GET(MPAMF_CPOR_IDR_CPBM_WD, cpor_features); 703 + if (props->cpbm_wd) 704 + mpam_set_feature(mpam_feat_cpor_part, props); 705 + } 706 + 707 + /* Memory bandwidth partitioning */ 708 + if (FIELD_GET(MPAMF_IDR_HAS_MBW_PART, ris->idr)) { 709 + u32 mbw_features = mpam_read_partsel_reg(msc, MBW_IDR); 710 + 711 + /* portion bitmap resolution */ 712 + props->mbw_pbm_bits = FIELD_GET(MPAMF_MBW_IDR_BWPBM_WD, mbw_features); 713 + if (props->mbw_pbm_bits && 714 + FIELD_GET(MPAMF_MBW_IDR_HAS_PBM, mbw_features)) 715 + mpam_set_feature(mpam_feat_mbw_part, props); 716 + 717 + props->bwa_wd = FIELD_GET(MPAMF_MBW_IDR_BWA_WD, mbw_features); 718 + if (props->bwa_wd && FIELD_GET(MPAMF_MBW_IDR_HAS_MAX, mbw_features)) 719 + mpam_set_feature(mpam_feat_mbw_max, props); 720 + 721 + if (props->bwa_wd && FIELD_GET(MPAMF_MBW_IDR_HAS_MIN, mbw_features)) 722 + mpam_set_feature(mpam_feat_mbw_min, props); 723 + 724 + if (props->bwa_wd && FIELD_GET(MPAMF_MBW_IDR_HAS_PROP, mbw_features)) 725 + mpam_set_feature(mpam_feat_mbw_prop, props); 726 + } 727 + 728 + /* Priority partitioning */ 729 + if (FIELD_GET(MPAMF_IDR_HAS_PRI_PART, ris->idr)) { 730 + u32 pri_features = mpam_read_partsel_reg(msc, PRI_IDR); 731 + 732 + props->intpri_wd = FIELD_GET(MPAMF_PRI_IDR_INTPRI_WD, pri_features); 733 + if (props->intpri_wd && FIELD_GET(MPAMF_PRI_IDR_HAS_INTPRI, pri_features)) { 734 + mpam_set_feature(mpam_feat_intpri_part, props); 735 + if (FIELD_GET(MPAMF_PRI_IDR_INTPRI_0_IS_LOW, pri_features)) 736 + mpam_set_feature(mpam_feat_intpri_part_0_low, props); 737 + } 738 + 739 + props->dspri_wd = FIELD_GET(MPAMF_PRI_IDR_DSPRI_WD, pri_features); 740 + if (props->dspri_wd && FIELD_GET(MPAMF_PRI_IDR_HAS_DSPRI, pri_features)) { 741 + mpam_set_feature(mpam_feat_dspri_part, props); 742 + if (FIELD_GET(MPAMF_PRI_IDR_DSPRI_0_IS_LOW, pri_features)) 743 + mpam_set_feature(mpam_feat_dspri_part_0_low, props); 744 + } 745 + } 746 + 747 + /* Performance Monitoring */ 748 + if (FIELD_GET(MPAMF_IDR_HAS_MSMON, ris->idr)) { 749 + u32 msmon_features = mpam_read_partsel_reg(msc, MSMON_IDR); 750 + 751 + /* 752 + * If the firmware max-nrdy-us property is missing, the 753 + * CSU counters can't be used. Should we wait forever? 754 + */ 755 + err = device_property_read_u32(&msc->pdev->dev, 756 + "arm,not-ready-us", 757 + &msc->nrdy_usec); 758 + 759 + if (FIELD_GET(MPAMF_MSMON_IDR_MSMON_CSU, msmon_features)) { 760 + u32 csumonidr; 761 + 762 + csumonidr = mpam_read_partsel_reg(msc, CSUMON_IDR); 763 + props->num_csu_mon = FIELD_GET(MPAMF_CSUMON_IDR_NUM_MON, csumonidr); 764 + if (props->num_csu_mon) { 765 + bool hw_managed; 766 + 767 + mpam_set_feature(mpam_feat_msmon_csu, props); 768 + 769 + if (FIELD_GET(MPAMF_CSUMON_IDR_HAS_XCL, csumonidr)) 770 + mpam_set_feature(mpam_feat_msmon_csu_xcl, props); 771 + 772 + /* Is NRDY hardware managed? */ 773 + hw_managed = mpam_ris_hw_probe_hw_nrdy(ris, CSU); 774 + if (hw_managed) 775 + mpam_set_feature(mpam_feat_msmon_csu_hw_nrdy, props); 776 + } 777 + 778 + /* 779 + * Accept the missing firmware property if NRDY appears 780 + * un-implemented. 781 + */ 782 + if (err && mpam_has_feature(mpam_feat_msmon_csu_hw_nrdy, props)) 783 + dev_err_once(dev, "Counters are not usable because not-ready timeout was not provided by firmware."); 784 + } 785 + if (FIELD_GET(MPAMF_MSMON_IDR_MSMON_MBWU, msmon_features)) { 786 + bool has_long, hw_managed; 787 + u32 mbwumon_idr = mpam_read_partsel_reg(msc, MBWUMON_IDR); 788 + 789 + props->num_mbwu_mon = FIELD_GET(MPAMF_MBWUMON_IDR_NUM_MON, mbwumon_idr); 790 + if (props->num_mbwu_mon) { 791 + mpam_set_feature(mpam_feat_msmon_mbwu, props); 792 + 793 + if (FIELD_GET(MPAMF_MBWUMON_IDR_HAS_RWBW, mbwumon_idr)) 794 + mpam_set_feature(mpam_feat_msmon_mbwu_rwbw, props); 795 + 796 + has_long = FIELD_GET(MPAMF_MBWUMON_IDR_HAS_LONG, mbwumon_idr); 797 + if (has_long) { 798 + if (FIELD_GET(MPAMF_MBWUMON_IDR_LWD, mbwumon_idr)) 799 + mpam_set_feature(mpam_feat_msmon_mbwu_63counter, props); 800 + else 801 + mpam_set_feature(mpam_feat_msmon_mbwu_44counter, props); 802 + } else { 803 + mpam_set_feature(mpam_feat_msmon_mbwu_31counter, props); 804 + } 805 + 806 + /* Is NRDY hardware managed? */ 807 + hw_managed = mpam_ris_hw_probe_hw_nrdy(ris, MBWU); 808 + if (hw_managed) 809 + mpam_set_feature(mpam_feat_msmon_mbwu_hw_nrdy, props); 810 + 811 + /* 812 + * Don't warn about any missing firmware property for 813 + * MBWU NRDY - it doesn't make any sense! 814 + */ 815 + } 816 + } 817 + } 818 + 819 + /* 820 + * RIS with PARTID narrowing don't have enough storage for one 821 + * configuration per PARTID. If these are in a class we could use, 822 + * reduce the supported partid_max to match the number of intpartid. 823 + * If the class is unknown, just ignore it. 824 + */ 825 + if (FIELD_GET(MPAMF_IDR_HAS_PARTID_NRW, ris->idr) && 826 + class->type != MPAM_CLASS_UNKNOWN) { 827 + u32 nrwidr = mpam_read_partsel_reg(msc, PARTID_NRW_IDR); 828 + u16 partid_max = FIELD_GET(MPAMF_PARTID_NRW_IDR_INTPARTID_MAX, nrwidr); 829 + 830 + mpam_set_feature(mpam_feat_partid_nrw, props); 831 + msc->partid_max = min(msc->partid_max, partid_max); 832 + } 833 + } 834 + 835 + static int mpam_msc_hw_probe(struct mpam_msc *msc) 836 + { 837 + u64 idr; 838 + u16 partid_max; 839 + u8 ris_idx, pmg_max; 840 + struct mpam_msc_ris *ris; 841 + struct device *dev = &msc->pdev->dev; 842 + 843 + lockdep_assert_held(&msc->probe_lock); 844 + 845 + idr = __mpam_read_reg(msc, MPAMF_AIDR); 846 + if ((idr & MPAMF_AIDR_ARCH_MAJOR_REV) != MPAM_ARCHITECTURE_V1) { 847 + dev_err_once(dev, "MSC does not match MPAM architecture v1.x\n"); 848 + return -EIO; 849 + } 850 + 851 + /* Grab an IDR value to find out how many RIS there are */ 852 + mutex_lock(&msc->part_sel_lock); 853 + idr = mpam_msc_read_idr(msc); 854 + mutex_unlock(&msc->part_sel_lock); 855 + 856 + msc->ris_max = FIELD_GET(MPAMF_IDR_RIS_MAX, idr); 857 + 858 + /* Use these values so partid/pmg always starts with a valid value */ 859 + msc->partid_max = FIELD_GET(MPAMF_IDR_PARTID_MAX, idr); 860 + msc->pmg_max = FIELD_GET(MPAMF_IDR_PMG_MAX, idr); 861 + 862 + for (ris_idx = 0; ris_idx <= msc->ris_max; ris_idx++) { 863 + mutex_lock(&msc->part_sel_lock); 864 + __mpam_part_sel(ris_idx, 0, msc); 865 + idr = mpam_msc_read_idr(msc); 866 + mutex_unlock(&msc->part_sel_lock); 867 + 868 + partid_max = FIELD_GET(MPAMF_IDR_PARTID_MAX, idr); 869 + pmg_max = FIELD_GET(MPAMF_IDR_PMG_MAX, idr); 870 + msc->partid_max = min(msc->partid_max, partid_max); 871 + msc->pmg_max = min(msc->pmg_max, pmg_max); 872 + msc->has_extd_esr = FIELD_GET(MPAMF_IDR_HAS_EXTD_ESR, idr); 873 + 874 + mutex_lock(&mpam_list_lock); 875 + ris = mpam_get_or_create_ris(msc, ris_idx); 876 + mutex_unlock(&mpam_list_lock); 877 + if (IS_ERR(ris)) 878 + return PTR_ERR(ris); 879 + ris->idr = idr; 880 + 881 + mutex_lock(&msc->part_sel_lock); 882 + __mpam_part_sel(ris_idx, 0, msc); 883 + mpam_ris_hw_probe(ris); 884 + mutex_unlock(&msc->part_sel_lock); 885 + } 886 + 887 + /* Clear any stale errors */ 888 + mpam_msc_clear_esr(msc); 889 + 890 + spin_lock(&partid_max_lock); 891 + mpam_partid_max = min(mpam_partid_max, msc->partid_max); 892 + mpam_pmg_max = min(mpam_pmg_max, msc->pmg_max); 893 + spin_unlock(&partid_max_lock); 894 + 895 + msc->probed = true; 896 + 897 + return 0; 898 + } 899 + 900 + struct mon_read { 901 + struct mpam_msc_ris *ris; 902 + struct mon_cfg *ctx; 903 + enum mpam_device_features type; 904 + u64 *val; 905 + int err; 906 + }; 907 + 908 + static bool mpam_ris_has_mbwu_long_counter(struct mpam_msc_ris *ris) 909 + { 910 + return (mpam_has_feature(mpam_feat_msmon_mbwu_63counter, &ris->props) || 911 + mpam_has_feature(mpam_feat_msmon_mbwu_44counter, &ris->props)); 912 + } 913 + 914 + static u64 mpam_msc_read_mbwu_l(struct mpam_msc *msc) 915 + { 916 + int retry = 3; 917 + u32 mbwu_l_low; 918 + u64 mbwu_l_high1, mbwu_l_high2; 919 + 920 + mpam_mon_sel_lock_held(msc); 921 + 922 + WARN_ON_ONCE((MSMON_MBWU_L + sizeof(u64)) > msc->mapped_hwpage_sz); 923 + WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &msc->accessibility)); 924 + 925 + mbwu_l_high2 = __mpam_read_reg(msc, MSMON_MBWU_L + 4); 926 + do { 927 + mbwu_l_high1 = mbwu_l_high2; 928 + mbwu_l_low = __mpam_read_reg(msc, MSMON_MBWU_L); 929 + mbwu_l_high2 = __mpam_read_reg(msc, MSMON_MBWU_L + 4); 930 + 931 + retry--; 932 + } while (mbwu_l_high1 != mbwu_l_high2 && retry > 0); 933 + 934 + if (mbwu_l_high1 == mbwu_l_high2) 935 + return (mbwu_l_high1 << 32) | mbwu_l_low; 936 + 937 + pr_warn("Failed to read a stable value\n"); 938 + return MSMON___L_NRDY; 939 + } 940 + 941 + static void mpam_msc_zero_mbwu_l(struct mpam_msc *msc) 942 + { 943 + mpam_mon_sel_lock_held(msc); 944 + 945 + WARN_ON_ONCE((MSMON_MBWU_L + sizeof(u64)) > msc->mapped_hwpage_sz); 946 + WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), &msc->accessibility)); 947 + 948 + __mpam_write_reg(msc, MSMON_MBWU_L, 0); 949 + __mpam_write_reg(msc, MSMON_MBWU_L + 4, 0); 950 + } 951 + 952 + static void gen_msmon_ctl_flt_vals(struct mon_read *m, u32 *ctl_val, 953 + u32 *flt_val) 954 + { 955 + struct mon_cfg *ctx = m->ctx; 956 + 957 + /* 958 + * For CSU counters its implementation-defined what happens when not 959 + * filtering by partid. 960 + */ 961 + *ctl_val = MSMON_CFG_x_CTL_MATCH_PARTID; 962 + 963 + *flt_val = FIELD_PREP(MSMON_CFG_x_FLT_PARTID, ctx->partid); 964 + 965 + if (m->ctx->match_pmg) { 966 + *ctl_val |= MSMON_CFG_x_CTL_MATCH_PMG; 967 + *flt_val |= FIELD_PREP(MSMON_CFG_x_FLT_PMG, ctx->pmg); 968 + } 969 + 970 + switch (m->type) { 971 + case mpam_feat_msmon_csu: 972 + *ctl_val |= MSMON_CFG_CSU_CTL_TYPE_CSU; 973 + 974 + if (mpam_has_feature(mpam_feat_msmon_csu_xcl, &m->ris->props)) 975 + *flt_val |= FIELD_PREP(MSMON_CFG_CSU_FLT_XCL, ctx->csu_exclude_clean); 976 + 977 + break; 978 + case mpam_feat_msmon_mbwu_31counter: 979 + case mpam_feat_msmon_mbwu_44counter: 980 + case mpam_feat_msmon_mbwu_63counter: 981 + *ctl_val |= MSMON_CFG_MBWU_CTL_TYPE_MBWU; 982 + 983 + if (mpam_has_feature(mpam_feat_msmon_mbwu_rwbw, &m->ris->props)) 984 + *flt_val |= FIELD_PREP(MSMON_CFG_MBWU_FLT_RWBW, ctx->opts); 985 + 986 + break; 987 + default: 988 + pr_warn("Unexpected monitor type %d\n", m->type); 989 + } 990 + } 991 + 992 + static void read_msmon_ctl_flt_vals(struct mon_read *m, u32 *ctl_val, 993 + u32 *flt_val) 994 + { 995 + struct mpam_msc *msc = m->ris->vmsc->msc; 996 + 997 + switch (m->type) { 998 + case mpam_feat_msmon_csu: 999 + *ctl_val = mpam_read_monsel_reg(msc, CFG_CSU_CTL); 1000 + *flt_val = mpam_read_monsel_reg(msc, CFG_CSU_FLT); 1001 + break; 1002 + case mpam_feat_msmon_mbwu_31counter: 1003 + case mpam_feat_msmon_mbwu_44counter: 1004 + case mpam_feat_msmon_mbwu_63counter: 1005 + *ctl_val = mpam_read_monsel_reg(msc, CFG_MBWU_CTL); 1006 + *flt_val = mpam_read_monsel_reg(msc, CFG_MBWU_FLT); 1007 + break; 1008 + default: 1009 + pr_warn("Unexpected monitor type %d\n", m->type); 1010 + } 1011 + } 1012 + 1013 + /* Remove values set by the hardware to prevent apparent mismatches. */ 1014 + static inline void clean_msmon_ctl_val(u32 *cur_ctl) 1015 + { 1016 + *cur_ctl &= ~MSMON_CFG_x_CTL_OFLOW_STATUS; 1017 + 1018 + if (FIELD_GET(MSMON_CFG_x_CTL_TYPE, *cur_ctl) == MSMON_CFG_MBWU_CTL_TYPE_MBWU) 1019 + *cur_ctl &= ~MSMON_CFG_MBWU_CTL_OFLOW_STATUS_L; 1020 + } 1021 + 1022 + static void write_msmon_ctl_flt_vals(struct mon_read *m, u32 ctl_val, 1023 + u32 flt_val) 1024 + { 1025 + struct mpam_msc *msc = m->ris->vmsc->msc; 1026 + 1027 + /* 1028 + * Write the ctl_val with the enable bit cleared, reset the counter, 1029 + * then enable counter. 1030 + */ 1031 + switch (m->type) { 1032 + case mpam_feat_msmon_csu: 1033 + mpam_write_monsel_reg(msc, CFG_CSU_FLT, flt_val); 1034 + mpam_write_monsel_reg(msc, CFG_CSU_CTL, ctl_val); 1035 + mpam_write_monsel_reg(msc, CSU, 0); 1036 + mpam_write_monsel_reg(msc, CFG_CSU_CTL, ctl_val | MSMON_CFG_x_CTL_EN); 1037 + break; 1038 + case mpam_feat_msmon_mbwu_31counter: 1039 + case mpam_feat_msmon_mbwu_44counter: 1040 + case mpam_feat_msmon_mbwu_63counter: 1041 + mpam_write_monsel_reg(msc, CFG_MBWU_FLT, flt_val); 1042 + mpam_write_monsel_reg(msc, CFG_MBWU_CTL, ctl_val); 1043 + mpam_write_monsel_reg(msc, CFG_MBWU_CTL, ctl_val | MSMON_CFG_x_CTL_EN); 1044 + /* Counting monitors require NRDY to be reset by software */ 1045 + if (m->type == mpam_feat_msmon_mbwu_31counter) 1046 + mpam_write_monsel_reg(msc, MBWU, 0); 1047 + else 1048 + mpam_msc_zero_mbwu_l(m->ris->vmsc->msc); 1049 + break; 1050 + default: 1051 + pr_warn("Unexpected monitor type %d\n", m->type); 1052 + } 1053 + } 1054 + 1055 + static u64 mpam_msmon_overflow_val(enum mpam_device_features type) 1056 + { 1057 + /* TODO: implement scaling counters */ 1058 + switch (type) { 1059 + case mpam_feat_msmon_mbwu_63counter: 1060 + return BIT_ULL(hweight_long(MSMON___LWD_VALUE)); 1061 + case mpam_feat_msmon_mbwu_44counter: 1062 + return BIT_ULL(hweight_long(MSMON___L_VALUE)); 1063 + case mpam_feat_msmon_mbwu_31counter: 1064 + return BIT_ULL(hweight_long(MSMON___VALUE)); 1065 + default: 1066 + return 0; 1067 + } 1068 + } 1069 + 1070 + static void __ris_msmon_read(void *arg) 1071 + { 1072 + u64 now; 1073 + bool nrdy = false; 1074 + bool config_mismatch; 1075 + bool overflow; 1076 + struct mon_read *m = arg; 1077 + struct mon_cfg *ctx = m->ctx; 1078 + bool reset_on_next_read = false; 1079 + struct mpam_msc_ris *ris = m->ris; 1080 + struct msmon_mbwu_state *mbwu_state; 1081 + struct mpam_props *rprops = &ris->props; 1082 + struct mpam_msc *msc = m->ris->vmsc->msc; 1083 + u32 mon_sel, ctl_val, flt_val, cur_ctl, cur_flt; 1084 + 1085 + if (!mpam_mon_sel_lock(msc)) { 1086 + m->err = -EIO; 1087 + return; 1088 + } 1089 + mon_sel = FIELD_PREP(MSMON_CFG_MON_SEL_MON_SEL, ctx->mon) | 1090 + FIELD_PREP(MSMON_CFG_MON_SEL_RIS, ris->ris_idx); 1091 + mpam_write_monsel_reg(msc, CFG_MON_SEL, mon_sel); 1092 + 1093 + switch (m->type) { 1094 + case mpam_feat_msmon_mbwu_31counter: 1095 + case mpam_feat_msmon_mbwu_44counter: 1096 + case mpam_feat_msmon_mbwu_63counter: 1097 + mbwu_state = &ris->mbwu_state[ctx->mon]; 1098 + if (mbwu_state) { 1099 + reset_on_next_read = mbwu_state->reset_on_next_read; 1100 + mbwu_state->reset_on_next_read = false; 1101 + } 1102 + break; 1103 + default: 1104 + break; 1105 + } 1106 + 1107 + /* 1108 + * Read the existing configuration to avoid re-writing the same values. 1109 + * This saves waiting for 'nrdy' on subsequent reads. 1110 + */ 1111 + read_msmon_ctl_flt_vals(m, &cur_ctl, &cur_flt); 1112 + 1113 + if (mpam_feat_msmon_mbwu_31counter == m->type) 1114 + overflow = cur_ctl & MSMON_CFG_x_CTL_OFLOW_STATUS; 1115 + else if (mpam_feat_msmon_mbwu_44counter == m->type || 1116 + mpam_feat_msmon_mbwu_63counter == m->type) 1117 + overflow = cur_ctl & MSMON_CFG_MBWU_CTL_OFLOW_STATUS_L; 1118 + 1119 + clean_msmon_ctl_val(&cur_ctl); 1120 + gen_msmon_ctl_flt_vals(m, &ctl_val, &flt_val); 1121 + config_mismatch = cur_flt != flt_val || 1122 + cur_ctl != (ctl_val | MSMON_CFG_x_CTL_EN); 1123 + 1124 + if (config_mismatch || reset_on_next_read) { 1125 + write_msmon_ctl_flt_vals(m, ctl_val, flt_val); 1126 + overflow = false; 1127 + } else if (overflow) { 1128 + mpam_write_monsel_reg(msc, CFG_MBWU_CTL, 1129 + cur_ctl & 1130 + ~(MSMON_CFG_x_CTL_OFLOW_STATUS | 1131 + MSMON_CFG_MBWU_CTL_OFLOW_STATUS_L)); 1132 + } 1133 + 1134 + switch (m->type) { 1135 + case mpam_feat_msmon_csu: 1136 + now = mpam_read_monsel_reg(msc, CSU); 1137 + if (mpam_has_feature(mpam_feat_msmon_csu_hw_nrdy, rprops)) 1138 + nrdy = now & MSMON___NRDY; 1139 + now = FIELD_GET(MSMON___VALUE, now); 1140 + break; 1141 + case mpam_feat_msmon_mbwu_31counter: 1142 + case mpam_feat_msmon_mbwu_44counter: 1143 + case mpam_feat_msmon_mbwu_63counter: 1144 + if (m->type != mpam_feat_msmon_mbwu_31counter) { 1145 + now = mpam_msc_read_mbwu_l(msc); 1146 + if (mpam_has_feature(mpam_feat_msmon_mbwu_hw_nrdy, rprops)) 1147 + nrdy = now & MSMON___L_NRDY; 1148 + 1149 + if (m->type == mpam_feat_msmon_mbwu_63counter) 1150 + now = FIELD_GET(MSMON___LWD_VALUE, now); 1151 + else 1152 + now = FIELD_GET(MSMON___L_VALUE, now); 1153 + } else { 1154 + now = mpam_read_monsel_reg(msc, MBWU); 1155 + if (mpam_has_feature(mpam_feat_msmon_mbwu_hw_nrdy, rprops)) 1156 + nrdy = now & MSMON___NRDY; 1157 + now = FIELD_GET(MSMON___VALUE, now); 1158 + } 1159 + 1160 + if (nrdy) 1161 + break; 1162 + 1163 + mbwu_state = &ris->mbwu_state[ctx->mon]; 1164 + 1165 + if (overflow) 1166 + mbwu_state->correction += mpam_msmon_overflow_val(m->type); 1167 + 1168 + /* 1169 + * Include bandwidth consumed before the last hardware reset and 1170 + * a counter size increment for each overflow. 1171 + */ 1172 + now += mbwu_state->correction; 1173 + break; 1174 + default: 1175 + m->err = -EINVAL; 1176 + } 1177 + mpam_mon_sel_unlock(msc); 1178 + 1179 + if (nrdy) { 1180 + m->err = -EBUSY; 1181 + return; 1182 + } 1183 + 1184 + *m->val += now; 1185 + } 1186 + 1187 + static int _msmon_read(struct mpam_component *comp, struct mon_read *arg) 1188 + { 1189 + int err, any_err = 0; 1190 + struct mpam_vmsc *vmsc; 1191 + 1192 + guard(srcu)(&mpam_srcu); 1193 + list_for_each_entry_srcu(vmsc, &comp->vmsc, comp_list, 1194 + srcu_read_lock_held(&mpam_srcu)) { 1195 + struct mpam_msc *msc = vmsc->msc; 1196 + struct mpam_msc_ris *ris; 1197 + 1198 + list_for_each_entry_srcu(ris, &vmsc->ris, vmsc_list, 1199 + srcu_read_lock_held(&mpam_srcu)) { 1200 + arg->ris = ris; 1201 + 1202 + err = smp_call_function_any(&msc->accessibility, 1203 + __ris_msmon_read, arg, 1204 + true); 1205 + if (!err && arg->err) 1206 + err = arg->err; 1207 + 1208 + /* 1209 + * Save one error to be returned to the caller, but 1210 + * keep reading counters so that get reprogrammed. On 1211 + * platforms with NRDY this lets us wait once. 1212 + */ 1213 + if (err) 1214 + any_err = err; 1215 + } 1216 + } 1217 + 1218 + return any_err; 1219 + } 1220 + 1221 + static enum mpam_device_features mpam_msmon_choose_counter(struct mpam_class *class) 1222 + { 1223 + struct mpam_props *cprops = &class->props; 1224 + 1225 + if (mpam_has_feature(mpam_feat_msmon_mbwu_63counter, cprops)) 1226 + return mpam_feat_msmon_mbwu_63counter; 1227 + if (mpam_has_feature(mpam_feat_msmon_mbwu_44counter, cprops)) 1228 + return mpam_feat_msmon_mbwu_44counter; 1229 + 1230 + return mpam_feat_msmon_mbwu_31counter; 1231 + } 1232 + 1233 + int mpam_msmon_read(struct mpam_component *comp, struct mon_cfg *ctx, 1234 + enum mpam_device_features type, u64 *val) 1235 + { 1236 + int err; 1237 + struct mon_read arg; 1238 + u64 wait_jiffies = 0; 1239 + struct mpam_class *class = comp->class; 1240 + struct mpam_props *cprops = &class->props; 1241 + 1242 + might_sleep(); 1243 + 1244 + if (!mpam_is_enabled()) 1245 + return -EIO; 1246 + 1247 + if (!mpam_has_feature(type, cprops)) 1248 + return -EOPNOTSUPP; 1249 + 1250 + if (type == mpam_feat_msmon_mbwu) 1251 + type = mpam_msmon_choose_counter(class); 1252 + 1253 + arg = (struct mon_read) { 1254 + .ctx = ctx, 1255 + .type = type, 1256 + .val = val, 1257 + }; 1258 + *val = 0; 1259 + 1260 + err = _msmon_read(comp, &arg); 1261 + if (err == -EBUSY && class->nrdy_usec) 1262 + wait_jiffies = usecs_to_jiffies(class->nrdy_usec); 1263 + 1264 + while (wait_jiffies) 1265 + wait_jiffies = schedule_timeout_uninterruptible(wait_jiffies); 1266 + 1267 + if (err == -EBUSY) { 1268 + arg = (struct mon_read) { 1269 + .ctx = ctx, 1270 + .type = type, 1271 + .val = val, 1272 + }; 1273 + *val = 0; 1274 + 1275 + err = _msmon_read(comp, &arg); 1276 + } 1277 + 1278 + return err; 1279 + } 1280 + 1281 + void mpam_msmon_reset_mbwu(struct mpam_component *comp, struct mon_cfg *ctx) 1282 + { 1283 + struct mpam_msc *msc; 1284 + struct mpam_vmsc *vmsc; 1285 + struct mpam_msc_ris *ris; 1286 + 1287 + if (!mpam_is_enabled()) 1288 + return; 1289 + 1290 + guard(srcu)(&mpam_srcu); 1291 + list_for_each_entry_srcu(vmsc, &comp->vmsc, comp_list, 1292 + srcu_read_lock_held(&mpam_srcu)) { 1293 + if (!mpam_has_feature(mpam_feat_msmon_mbwu, &vmsc->props)) 1294 + continue; 1295 + 1296 + msc = vmsc->msc; 1297 + list_for_each_entry_srcu(ris, &vmsc->ris, vmsc_list, 1298 + srcu_read_lock_held(&mpam_srcu)) { 1299 + if (!mpam_has_feature(mpam_feat_msmon_mbwu, &ris->props)) 1300 + continue; 1301 + 1302 + if (WARN_ON_ONCE(!mpam_mon_sel_lock(msc))) 1303 + continue; 1304 + 1305 + ris->mbwu_state[ctx->mon].correction = 0; 1306 + ris->mbwu_state[ctx->mon].reset_on_next_read = true; 1307 + mpam_mon_sel_unlock(msc); 1308 + } 1309 + } 1310 + } 1311 + 1312 + static void mpam_reset_msc_bitmap(struct mpam_msc *msc, u16 reg, u16 wd) 1313 + { 1314 + u32 num_words, msb; 1315 + u32 bm = ~0; 1316 + int i; 1317 + 1318 + lockdep_assert_held(&msc->part_sel_lock); 1319 + 1320 + if (wd == 0) 1321 + return; 1322 + 1323 + /* 1324 + * Write all ~0 to all but the last 32bit-word, which may 1325 + * have fewer bits... 1326 + */ 1327 + num_words = DIV_ROUND_UP(wd, 32); 1328 + for (i = 0; i < num_words - 1; i++, reg += sizeof(bm)) 1329 + __mpam_write_reg(msc, reg, bm); 1330 + 1331 + /* 1332 + * ....and then the last (maybe) partial 32bit word. When wd is a 1333 + * multiple of 32, msb should be 31 to write a full 32bit word. 1334 + */ 1335 + msb = (wd - 1) % 32; 1336 + bm = GENMASK(msb, 0); 1337 + __mpam_write_reg(msc, reg, bm); 1338 + } 1339 + 1340 + /* Called via IPI. Call while holding an SRCU reference */ 1341 + static void mpam_reprogram_ris_partid(struct mpam_msc_ris *ris, u16 partid, 1342 + struct mpam_config *cfg) 1343 + { 1344 + u32 pri_val = 0; 1345 + u16 cmax = MPAMCFG_CMAX_CMAX; 1346 + struct mpam_msc *msc = ris->vmsc->msc; 1347 + struct mpam_props *rprops = &ris->props; 1348 + u16 dspri = GENMASK(rprops->dspri_wd, 0); 1349 + u16 intpri = GENMASK(rprops->intpri_wd, 0); 1350 + 1351 + mutex_lock(&msc->part_sel_lock); 1352 + __mpam_part_sel(ris->ris_idx, partid, msc); 1353 + 1354 + if (mpam_has_feature(mpam_feat_partid_nrw, rprops)) { 1355 + /* Update the intpartid mapping */ 1356 + mpam_write_partsel_reg(msc, INTPARTID, 1357 + MPAMCFG_INTPARTID_INTERNAL | partid); 1358 + 1359 + /* 1360 + * Then switch to the 'internal' partid to update the 1361 + * configuration. 1362 + */ 1363 + __mpam_intpart_sel(ris->ris_idx, partid, msc); 1364 + } 1365 + 1366 + if (mpam_has_feature(mpam_feat_cpor_part, rprops) && 1367 + mpam_has_feature(mpam_feat_cpor_part, cfg)) { 1368 + if (cfg->reset_cpbm) 1369 + mpam_reset_msc_bitmap(msc, MPAMCFG_CPBM, rprops->cpbm_wd); 1370 + else 1371 + mpam_write_partsel_reg(msc, CPBM, cfg->cpbm); 1372 + } 1373 + 1374 + if (mpam_has_feature(mpam_feat_mbw_part, rprops) && 1375 + mpam_has_feature(mpam_feat_mbw_part, cfg)) { 1376 + if (cfg->reset_mbw_pbm) 1377 + mpam_reset_msc_bitmap(msc, MPAMCFG_MBW_PBM, rprops->mbw_pbm_bits); 1378 + else 1379 + mpam_write_partsel_reg(msc, MBW_PBM, cfg->mbw_pbm); 1380 + } 1381 + 1382 + if (mpam_has_feature(mpam_feat_mbw_min, rprops) && 1383 + mpam_has_feature(mpam_feat_mbw_min, cfg)) 1384 + mpam_write_partsel_reg(msc, MBW_MIN, 0); 1385 + 1386 + if (mpam_has_feature(mpam_feat_mbw_max, rprops) && 1387 + mpam_has_feature(mpam_feat_mbw_max, cfg)) { 1388 + if (cfg->reset_mbw_max) 1389 + mpam_write_partsel_reg(msc, MBW_MAX, MPAMCFG_MBW_MAX_MAX); 1390 + else 1391 + mpam_write_partsel_reg(msc, MBW_MAX, cfg->mbw_max); 1392 + } 1393 + 1394 + if (mpam_has_feature(mpam_feat_mbw_prop, rprops) && 1395 + mpam_has_feature(mpam_feat_mbw_prop, cfg)) 1396 + mpam_write_partsel_reg(msc, MBW_PROP, 0); 1397 + 1398 + if (mpam_has_feature(mpam_feat_cmax_cmax, rprops)) 1399 + mpam_write_partsel_reg(msc, CMAX, cmax); 1400 + 1401 + if (mpam_has_feature(mpam_feat_cmax_cmin, rprops)) 1402 + mpam_write_partsel_reg(msc, CMIN, 0); 1403 + 1404 + if (mpam_has_feature(mpam_feat_cmax_cassoc, rprops)) 1405 + mpam_write_partsel_reg(msc, CASSOC, MPAMCFG_CASSOC_CASSOC); 1406 + 1407 + if (mpam_has_feature(mpam_feat_intpri_part, rprops) || 1408 + mpam_has_feature(mpam_feat_dspri_part, rprops)) { 1409 + /* aces high? */ 1410 + if (!mpam_has_feature(mpam_feat_intpri_part_0_low, rprops)) 1411 + intpri = 0; 1412 + if (!mpam_has_feature(mpam_feat_dspri_part_0_low, rprops)) 1413 + dspri = 0; 1414 + 1415 + if (mpam_has_feature(mpam_feat_intpri_part, rprops)) 1416 + pri_val |= FIELD_PREP(MPAMCFG_PRI_INTPRI, intpri); 1417 + if (mpam_has_feature(mpam_feat_dspri_part, rprops)) 1418 + pri_val |= FIELD_PREP(MPAMCFG_PRI_DSPRI, dspri); 1419 + 1420 + mpam_write_partsel_reg(msc, PRI, pri_val); 1421 + } 1422 + 1423 + mutex_unlock(&msc->part_sel_lock); 1424 + } 1425 + 1426 + /* Call with msc cfg_lock held */ 1427 + static int mpam_restore_mbwu_state(void *_ris) 1428 + { 1429 + int i; 1430 + struct mon_read mwbu_arg; 1431 + struct mpam_msc_ris *ris = _ris; 1432 + struct mpam_class *class = ris->vmsc->comp->class; 1433 + 1434 + for (i = 0; i < ris->props.num_mbwu_mon; i++) { 1435 + if (ris->mbwu_state[i].enabled) { 1436 + mwbu_arg.ris = ris; 1437 + mwbu_arg.ctx = &ris->mbwu_state[i].cfg; 1438 + mwbu_arg.type = mpam_msmon_choose_counter(class); 1439 + 1440 + __ris_msmon_read(&mwbu_arg); 1441 + } 1442 + } 1443 + 1444 + return 0; 1445 + } 1446 + 1447 + /* Call with MSC cfg_lock held */ 1448 + static int mpam_save_mbwu_state(void *arg) 1449 + { 1450 + int i; 1451 + u64 val; 1452 + struct mon_cfg *cfg; 1453 + u32 cur_flt, cur_ctl, mon_sel; 1454 + struct mpam_msc_ris *ris = arg; 1455 + struct msmon_mbwu_state *mbwu_state; 1456 + struct mpam_msc *msc = ris->vmsc->msc; 1457 + 1458 + for (i = 0; i < ris->props.num_mbwu_mon; i++) { 1459 + mbwu_state = &ris->mbwu_state[i]; 1460 + cfg = &mbwu_state->cfg; 1461 + 1462 + if (WARN_ON_ONCE(!mpam_mon_sel_lock(msc))) 1463 + return -EIO; 1464 + 1465 + mon_sel = FIELD_PREP(MSMON_CFG_MON_SEL_MON_SEL, i) | 1466 + FIELD_PREP(MSMON_CFG_MON_SEL_RIS, ris->ris_idx); 1467 + mpam_write_monsel_reg(msc, CFG_MON_SEL, mon_sel); 1468 + 1469 + cur_flt = mpam_read_monsel_reg(msc, CFG_MBWU_FLT); 1470 + cur_ctl = mpam_read_monsel_reg(msc, CFG_MBWU_CTL); 1471 + mpam_write_monsel_reg(msc, CFG_MBWU_CTL, 0); 1472 + 1473 + if (mpam_ris_has_mbwu_long_counter(ris)) { 1474 + val = mpam_msc_read_mbwu_l(msc); 1475 + mpam_msc_zero_mbwu_l(msc); 1476 + } else { 1477 + val = mpam_read_monsel_reg(msc, MBWU); 1478 + mpam_write_monsel_reg(msc, MBWU, 0); 1479 + } 1480 + 1481 + cfg->mon = i; 1482 + cfg->pmg = FIELD_GET(MSMON_CFG_x_FLT_PMG, cur_flt); 1483 + cfg->match_pmg = FIELD_GET(MSMON_CFG_x_CTL_MATCH_PMG, cur_ctl); 1484 + cfg->partid = FIELD_GET(MSMON_CFG_x_FLT_PARTID, cur_flt); 1485 + mbwu_state->correction += val; 1486 + mbwu_state->enabled = FIELD_GET(MSMON_CFG_x_CTL_EN, cur_ctl); 1487 + mpam_mon_sel_unlock(msc); 1488 + } 1489 + 1490 + return 0; 1491 + } 1492 + 1493 + static void mpam_init_reset_cfg(struct mpam_config *reset_cfg) 1494 + { 1495 + *reset_cfg = (struct mpam_config) { 1496 + .reset_cpbm = true, 1497 + .reset_mbw_pbm = true, 1498 + .reset_mbw_max = true, 1499 + }; 1500 + bitmap_fill(reset_cfg->features, MPAM_FEATURE_LAST); 1501 + } 1502 + 1503 + /* 1504 + * Called via smp_call_on_cpu() to prevent migration, while still being 1505 + * pre-emptible. Caller must hold mpam_srcu. 1506 + */ 1507 + static int mpam_reset_ris(void *arg) 1508 + { 1509 + u16 partid, partid_max; 1510 + struct mpam_config reset_cfg; 1511 + struct mpam_msc_ris *ris = arg; 1512 + 1513 + if (ris->in_reset_state) 1514 + return 0; 1515 + 1516 + mpam_init_reset_cfg(&reset_cfg); 1517 + 1518 + spin_lock(&partid_max_lock); 1519 + partid_max = mpam_partid_max; 1520 + spin_unlock(&partid_max_lock); 1521 + for (partid = 0; partid <= partid_max; partid++) 1522 + mpam_reprogram_ris_partid(ris, partid, &reset_cfg); 1523 + 1524 + return 0; 1525 + } 1526 + 1527 + /* 1528 + * Get the preferred CPU for this MSC. If it is accessible from this CPU, 1529 + * this CPU is preferred. This can be preempted/migrated, it will only result 1530 + * in more work. 1531 + */ 1532 + static int mpam_get_msc_preferred_cpu(struct mpam_msc *msc) 1533 + { 1534 + int cpu = raw_smp_processor_id(); 1535 + 1536 + if (cpumask_test_cpu(cpu, &msc->accessibility)) 1537 + return cpu; 1538 + 1539 + return cpumask_first_and(&msc->accessibility, cpu_online_mask); 1540 + } 1541 + 1542 + static int mpam_touch_msc(struct mpam_msc *msc, int (*fn)(void *a), void *arg) 1543 + { 1544 + lockdep_assert_irqs_enabled(); 1545 + lockdep_assert_cpus_held(); 1546 + WARN_ON_ONCE(!srcu_read_lock_held((&mpam_srcu))); 1547 + 1548 + return smp_call_on_cpu(mpam_get_msc_preferred_cpu(msc), fn, arg, true); 1549 + } 1550 + 1551 + struct mpam_write_config_arg { 1552 + struct mpam_msc_ris *ris; 1553 + struct mpam_component *comp; 1554 + u16 partid; 1555 + }; 1556 + 1557 + static int __write_config(void *arg) 1558 + { 1559 + struct mpam_write_config_arg *c = arg; 1560 + 1561 + mpam_reprogram_ris_partid(c->ris, c->partid, &c->comp->cfg[c->partid]); 1562 + 1563 + return 0; 1564 + } 1565 + 1566 + static void mpam_reprogram_msc(struct mpam_msc *msc) 1567 + { 1568 + u16 partid; 1569 + bool reset; 1570 + struct mpam_config *cfg; 1571 + struct mpam_msc_ris *ris; 1572 + struct mpam_write_config_arg arg; 1573 + 1574 + /* 1575 + * No lock for mpam_partid_max as partid_max_published has been 1576 + * set by mpam_enabled(), so the values can no longer change. 1577 + */ 1578 + mpam_assert_partid_sizes_fixed(); 1579 + 1580 + mutex_lock(&msc->cfg_lock); 1581 + list_for_each_entry_srcu(ris, &msc->ris, msc_list, 1582 + srcu_read_lock_held(&mpam_srcu)) { 1583 + if (!mpam_is_enabled() && !ris->in_reset_state) { 1584 + mpam_touch_msc(msc, &mpam_reset_ris, ris); 1585 + ris->in_reset_state = true; 1586 + continue; 1587 + } 1588 + 1589 + arg.comp = ris->vmsc->comp; 1590 + arg.ris = ris; 1591 + reset = true; 1592 + for (partid = 0; partid <= mpam_partid_max; partid++) { 1593 + cfg = &ris->vmsc->comp->cfg[partid]; 1594 + if (!bitmap_empty(cfg->features, MPAM_FEATURE_LAST)) 1595 + reset = false; 1596 + 1597 + arg.partid = partid; 1598 + mpam_touch_msc(msc, __write_config, &arg); 1599 + } 1600 + ris->in_reset_state = reset; 1601 + 1602 + if (mpam_has_feature(mpam_feat_msmon_mbwu, &ris->props)) 1603 + mpam_touch_msc(msc, &mpam_restore_mbwu_state, ris); 1604 + } 1605 + mutex_unlock(&msc->cfg_lock); 1606 + } 1607 + 1608 + static void _enable_percpu_irq(void *_irq) 1609 + { 1610 + int *irq = _irq; 1611 + 1612 + enable_percpu_irq(*irq, IRQ_TYPE_NONE); 1613 + } 1614 + 1615 + static int mpam_cpu_online(unsigned int cpu) 1616 + { 1617 + struct mpam_msc *msc; 1618 + 1619 + guard(srcu)(&mpam_srcu); 1620 + list_for_each_entry_srcu(msc, &mpam_all_msc, all_msc_list, 1621 + srcu_read_lock_held(&mpam_srcu)) { 1622 + if (!cpumask_test_cpu(cpu, &msc->accessibility)) 1623 + continue; 1624 + 1625 + if (msc->reenable_error_ppi) 1626 + _enable_percpu_irq(&msc->reenable_error_ppi); 1627 + 1628 + if (atomic_fetch_inc(&msc->online_refs) == 0) 1629 + mpam_reprogram_msc(msc); 1630 + } 1631 + 1632 + return 0; 1633 + } 1634 + 1635 + /* Before mpam is enabled, try to probe new MSC */ 1636 + static int mpam_discovery_cpu_online(unsigned int cpu) 1637 + { 1638 + int err = 0; 1639 + struct mpam_msc *msc; 1640 + bool new_device_probed = false; 1641 + 1642 + if (mpam_is_enabled()) 1643 + return 0; 1644 + 1645 + guard(srcu)(&mpam_srcu); 1646 + list_for_each_entry_srcu(msc, &mpam_all_msc, all_msc_list, 1647 + srcu_read_lock_held(&mpam_srcu)) { 1648 + if (!cpumask_test_cpu(cpu, &msc->accessibility)) 1649 + continue; 1650 + 1651 + mutex_lock(&msc->probe_lock); 1652 + if (!msc->probed) 1653 + err = mpam_msc_hw_probe(msc); 1654 + mutex_unlock(&msc->probe_lock); 1655 + 1656 + if (err) 1657 + break; 1658 + new_device_probed = true; 1659 + } 1660 + 1661 + if (new_device_probed && !err) 1662 + schedule_work(&mpam_enable_work); 1663 + if (err) { 1664 + mpam_disable_reason = "error during probing"; 1665 + schedule_work(&mpam_broken_work); 1666 + } 1667 + 1668 + return err; 1669 + } 1670 + 1671 + static int mpam_cpu_offline(unsigned int cpu) 1672 + { 1673 + struct mpam_msc *msc; 1674 + 1675 + guard(srcu)(&mpam_srcu); 1676 + list_for_each_entry_srcu(msc, &mpam_all_msc, all_msc_list, 1677 + srcu_read_lock_held(&mpam_srcu)) { 1678 + if (!cpumask_test_cpu(cpu, &msc->accessibility)) 1679 + continue; 1680 + 1681 + if (msc->reenable_error_ppi) 1682 + disable_percpu_irq(msc->reenable_error_ppi); 1683 + 1684 + if (atomic_dec_and_test(&msc->online_refs)) { 1685 + struct mpam_msc_ris *ris; 1686 + 1687 + mutex_lock(&msc->cfg_lock); 1688 + list_for_each_entry_srcu(ris, &msc->ris, msc_list, 1689 + srcu_read_lock_held(&mpam_srcu)) { 1690 + mpam_touch_msc(msc, &mpam_reset_ris, ris); 1691 + 1692 + /* 1693 + * The reset state for non-zero partid may be 1694 + * lost while the CPUs are offline. 1695 + */ 1696 + ris->in_reset_state = false; 1697 + 1698 + if (mpam_is_enabled()) 1699 + mpam_touch_msc(msc, &mpam_save_mbwu_state, ris); 1700 + } 1701 + mutex_unlock(&msc->cfg_lock); 1702 + } 1703 + } 1704 + 1705 + return 0; 1706 + } 1707 + 1708 + static void mpam_register_cpuhp_callbacks(int (*online)(unsigned int online), 1709 + int (*offline)(unsigned int offline), 1710 + char *name) 1711 + { 1712 + mutex_lock(&mpam_cpuhp_state_lock); 1713 + if (mpam_cpuhp_state) { 1714 + cpuhp_remove_state(mpam_cpuhp_state); 1715 + mpam_cpuhp_state = 0; 1716 + } 1717 + 1718 + mpam_cpuhp_state = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, name, online, 1719 + offline); 1720 + if (mpam_cpuhp_state <= 0) { 1721 + pr_err("Failed to register cpuhp callbacks"); 1722 + mpam_cpuhp_state = 0; 1723 + } 1724 + mutex_unlock(&mpam_cpuhp_state_lock); 1725 + } 1726 + 1727 + static int __setup_ppi(struct mpam_msc *msc) 1728 + { 1729 + int cpu; 1730 + 1731 + msc->error_dev_id = alloc_percpu(struct mpam_msc *); 1732 + if (!msc->error_dev_id) 1733 + return -ENOMEM; 1734 + 1735 + for_each_cpu(cpu, &msc->accessibility) 1736 + *per_cpu_ptr(msc->error_dev_id, cpu) = msc; 1737 + 1738 + return 0; 1739 + } 1740 + 1741 + static int mpam_msc_setup_error_irq(struct mpam_msc *msc) 1742 + { 1743 + int irq; 1744 + 1745 + irq = platform_get_irq_byname_optional(msc->pdev, "error"); 1746 + if (irq <= 0) 1747 + return 0; 1748 + 1749 + /* Allocate and initialise the percpu device pointer for PPI */ 1750 + if (irq_is_percpu(irq)) 1751 + return __setup_ppi(msc); 1752 + 1753 + /* sanity check: shared interrupts can be routed anywhere? */ 1754 + if (!cpumask_equal(&msc->accessibility, cpu_possible_mask)) { 1755 + pr_err_once("msc:%u is a private resource with a shared error interrupt", 1756 + msc->id); 1757 + return -EINVAL; 1758 + } 1759 + 1760 + return 0; 1761 + } 1762 + 1763 + /* 1764 + * An MSC can control traffic from a set of CPUs, but may only be accessible 1765 + * from a (hopefully wider) set of CPUs. The common reason for this is power 1766 + * management. If all the CPUs in a cluster are in PSCI:CPU_SUSPEND, the 1767 + * corresponding cache may also be powered off. By making accesses from 1768 + * one of those CPUs, we ensure we don't access a cache that's powered off. 1769 + */ 1770 + static void update_msc_accessibility(struct mpam_msc *msc) 1771 + { 1772 + u32 affinity_id; 1773 + int err; 1774 + 1775 + err = device_property_read_u32(&msc->pdev->dev, "cpu_affinity", 1776 + &affinity_id); 1777 + if (err) 1778 + cpumask_copy(&msc->accessibility, cpu_possible_mask); 1779 + else 1780 + acpi_pptt_get_cpus_from_container(affinity_id, &msc->accessibility); 1781 + } 1782 + 1783 + /* 1784 + * There are two ways of reaching a struct mpam_msc_ris. Via the 1785 + * class->component->vmsc->ris, or via the msc. 1786 + * When destroying the msc, the other side needs unlinking and cleaning up too. 1787 + */ 1788 + static void mpam_msc_destroy(struct mpam_msc *msc) 1789 + { 1790 + struct platform_device *pdev = msc->pdev; 1791 + struct mpam_msc_ris *ris, *tmp; 1792 + 1793 + lockdep_assert_held(&mpam_list_lock); 1794 + 1795 + list_for_each_entry_safe(ris, tmp, &msc->ris, msc_list) 1796 + mpam_ris_destroy(ris); 1797 + 1798 + list_del_rcu(&msc->all_msc_list); 1799 + platform_set_drvdata(pdev, NULL); 1800 + 1801 + add_to_garbage(msc); 1802 + } 1803 + 1804 + static void mpam_msc_drv_remove(struct platform_device *pdev) 1805 + { 1806 + struct mpam_msc *msc = platform_get_drvdata(pdev); 1807 + 1808 + mutex_lock(&mpam_list_lock); 1809 + mpam_msc_destroy(msc); 1810 + mutex_unlock(&mpam_list_lock); 1811 + 1812 + mpam_free_garbage(); 1813 + } 1814 + 1815 + static struct mpam_msc *do_mpam_msc_drv_probe(struct platform_device *pdev) 1816 + { 1817 + int err; 1818 + u32 tmp; 1819 + struct mpam_msc *msc; 1820 + struct resource *msc_res; 1821 + struct device *dev = &pdev->dev; 1822 + 1823 + lockdep_assert_held(&mpam_list_lock); 1824 + 1825 + msc = devm_kzalloc(&pdev->dev, sizeof(*msc), GFP_KERNEL); 1826 + if (!msc) 1827 + return ERR_PTR(-ENOMEM); 1828 + init_garbage(&msc->garbage); 1829 + msc->garbage.pdev = pdev; 1830 + 1831 + err = devm_mutex_init(dev, &msc->probe_lock); 1832 + if (err) 1833 + return ERR_PTR(err); 1834 + 1835 + err = devm_mutex_init(dev, &msc->part_sel_lock); 1836 + if (err) 1837 + return ERR_PTR(err); 1838 + 1839 + err = devm_mutex_init(dev, &msc->error_irq_lock); 1840 + if (err) 1841 + return ERR_PTR(err); 1842 + 1843 + err = devm_mutex_init(dev, &msc->cfg_lock); 1844 + if (err) 1845 + return ERR_PTR(err); 1846 + 1847 + mpam_mon_sel_lock_init(msc); 1848 + msc->id = pdev->id; 1849 + msc->pdev = pdev; 1850 + INIT_LIST_HEAD_RCU(&msc->all_msc_list); 1851 + INIT_LIST_HEAD_RCU(&msc->ris); 1852 + 1853 + update_msc_accessibility(msc); 1854 + if (cpumask_empty(&msc->accessibility)) { 1855 + dev_err_once(dev, "MSC is not accessible from any CPU!"); 1856 + return ERR_PTR(-EINVAL); 1857 + } 1858 + 1859 + err = mpam_msc_setup_error_irq(msc); 1860 + if (err) 1861 + return ERR_PTR(err); 1862 + 1863 + if (device_property_read_u32(&pdev->dev, "pcc-channel", &tmp)) 1864 + msc->iface = MPAM_IFACE_MMIO; 1865 + else 1866 + msc->iface = MPAM_IFACE_PCC; 1867 + 1868 + if (msc->iface == MPAM_IFACE_MMIO) { 1869 + void __iomem *io; 1870 + 1871 + io = devm_platform_get_and_ioremap_resource(pdev, 0, 1872 + &msc_res); 1873 + if (IS_ERR(io)) { 1874 + dev_err_once(dev, "Failed to map MSC base address\n"); 1875 + return ERR_CAST(io); 1876 + } 1877 + msc->mapped_hwpage_sz = msc_res->end - msc_res->start; 1878 + msc->mapped_hwpage = io; 1879 + } else { 1880 + return ERR_PTR(-EINVAL); 1881 + } 1882 + 1883 + list_add_rcu(&msc->all_msc_list, &mpam_all_msc); 1884 + platform_set_drvdata(pdev, msc); 1885 + 1886 + return msc; 1887 + } 1888 + 1889 + static int fw_num_msc; 1890 + 1891 + static int mpam_msc_drv_probe(struct platform_device *pdev) 1892 + { 1893 + int err; 1894 + struct mpam_msc *msc = NULL; 1895 + void *plat_data = pdev->dev.platform_data; 1896 + 1897 + mutex_lock(&mpam_list_lock); 1898 + msc = do_mpam_msc_drv_probe(pdev); 1899 + mutex_unlock(&mpam_list_lock); 1900 + 1901 + if (IS_ERR(msc)) 1902 + return PTR_ERR(msc); 1903 + 1904 + /* Create RIS entries described by firmware */ 1905 + err = acpi_mpam_parse_resources(msc, plat_data); 1906 + if (err) { 1907 + mpam_msc_drv_remove(pdev); 1908 + return err; 1909 + } 1910 + 1911 + if (atomic_add_return(1, &mpam_num_msc) == fw_num_msc) 1912 + mpam_register_cpuhp_callbacks(mpam_discovery_cpu_online, NULL, 1913 + "mpam:drv_probe"); 1914 + 1915 + return 0; 1916 + } 1917 + 1918 + static struct platform_driver mpam_msc_driver = { 1919 + .driver = { 1920 + .name = "mpam_msc", 1921 + }, 1922 + .probe = mpam_msc_drv_probe, 1923 + .remove = mpam_msc_drv_remove, 1924 + }; 1925 + 1926 + /* Any of these features mean the BWA_WD field is valid. */ 1927 + static bool mpam_has_bwa_wd_feature(struct mpam_props *props) 1928 + { 1929 + if (mpam_has_feature(mpam_feat_mbw_min, props)) 1930 + return true; 1931 + if (mpam_has_feature(mpam_feat_mbw_max, props)) 1932 + return true; 1933 + if (mpam_has_feature(mpam_feat_mbw_prop, props)) 1934 + return true; 1935 + return false; 1936 + } 1937 + 1938 + /* Any of these features mean the CMAX_WD field is valid. */ 1939 + static bool mpam_has_cmax_wd_feature(struct mpam_props *props) 1940 + { 1941 + if (mpam_has_feature(mpam_feat_cmax_cmax, props)) 1942 + return true; 1943 + if (mpam_has_feature(mpam_feat_cmax_cmin, props)) 1944 + return true; 1945 + return false; 1946 + } 1947 + 1948 + #define MISMATCHED_HELPER(parent, child, helper, field, alias) \ 1949 + helper(parent) && \ 1950 + ((helper(child) && (parent)->field != (child)->field) || \ 1951 + (!helper(child) && !(alias))) 1952 + 1953 + #define MISMATCHED_FEAT(parent, child, feat, field, alias) \ 1954 + mpam_has_feature((feat), (parent)) && \ 1955 + ((mpam_has_feature((feat), (child)) && (parent)->field != (child)->field) || \ 1956 + (!mpam_has_feature((feat), (child)) && !(alias))) 1957 + 1958 + #define CAN_MERGE_FEAT(parent, child, feat, alias) \ 1959 + (alias) && !mpam_has_feature((feat), (parent)) && \ 1960 + mpam_has_feature((feat), (child)) 1961 + 1962 + /* 1963 + * Combine two props fields. 1964 + * If this is for controls that alias the same resource, it is safe to just 1965 + * copy the values over. If two aliasing controls implement the same scheme 1966 + * a safe value must be picked. 1967 + * For non-aliasing controls, these control different resources, and the 1968 + * resulting safe value must be compatible with both. When merging values in 1969 + * the tree, all the aliasing resources must be handled first. 1970 + * On mismatch, parent is modified. 1971 + */ 1972 + static void __props_mismatch(struct mpam_props *parent, 1973 + struct mpam_props *child, bool alias) 1974 + { 1975 + if (CAN_MERGE_FEAT(parent, child, mpam_feat_cpor_part, alias)) { 1976 + parent->cpbm_wd = child->cpbm_wd; 1977 + } else if (MISMATCHED_FEAT(parent, child, mpam_feat_cpor_part, 1978 + cpbm_wd, alias)) { 1979 + pr_debug("cleared cpor_part\n"); 1980 + mpam_clear_feature(mpam_feat_cpor_part, parent); 1981 + parent->cpbm_wd = 0; 1982 + } 1983 + 1984 + if (CAN_MERGE_FEAT(parent, child, mpam_feat_mbw_part, alias)) { 1985 + parent->mbw_pbm_bits = child->mbw_pbm_bits; 1986 + } else if (MISMATCHED_FEAT(parent, child, mpam_feat_mbw_part, 1987 + mbw_pbm_bits, alias)) { 1988 + pr_debug("cleared mbw_part\n"); 1989 + mpam_clear_feature(mpam_feat_mbw_part, parent); 1990 + parent->mbw_pbm_bits = 0; 1991 + } 1992 + 1993 + /* bwa_wd is a count of bits, fewer bits means less precision */ 1994 + if (alias && !mpam_has_bwa_wd_feature(parent) && 1995 + mpam_has_bwa_wd_feature(child)) { 1996 + parent->bwa_wd = child->bwa_wd; 1997 + } else if (MISMATCHED_HELPER(parent, child, mpam_has_bwa_wd_feature, 1998 + bwa_wd, alias)) { 1999 + pr_debug("took the min bwa_wd\n"); 2000 + parent->bwa_wd = min(parent->bwa_wd, child->bwa_wd); 2001 + } 2002 + 2003 + if (alias && !mpam_has_cmax_wd_feature(parent) && mpam_has_cmax_wd_feature(child)) { 2004 + parent->cmax_wd = child->cmax_wd; 2005 + } else if (MISMATCHED_HELPER(parent, child, mpam_has_cmax_wd_feature, 2006 + cmax_wd, alias)) { 2007 + pr_debug("%s took the min cmax_wd\n", __func__); 2008 + parent->cmax_wd = min(parent->cmax_wd, child->cmax_wd); 2009 + } 2010 + 2011 + if (CAN_MERGE_FEAT(parent, child, mpam_feat_cmax_cassoc, alias)) { 2012 + parent->cassoc_wd = child->cassoc_wd; 2013 + } else if (MISMATCHED_FEAT(parent, child, mpam_feat_cmax_cassoc, 2014 + cassoc_wd, alias)) { 2015 + pr_debug("%s cleared cassoc_wd\n", __func__); 2016 + mpam_clear_feature(mpam_feat_cmax_cassoc, parent); 2017 + parent->cassoc_wd = 0; 2018 + } 2019 + 2020 + /* For num properties, take the minimum */ 2021 + if (CAN_MERGE_FEAT(parent, child, mpam_feat_msmon_csu, alias)) { 2022 + parent->num_csu_mon = child->num_csu_mon; 2023 + } else if (MISMATCHED_FEAT(parent, child, mpam_feat_msmon_csu, 2024 + num_csu_mon, alias)) { 2025 + pr_debug("took the min num_csu_mon\n"); 2026 + parent->num_csu_mon = min(parent->num_csu_mon, 2027 + child->num_csu_mon); 2028 + } 2029 + 2030 + if (CAN_MERGE_FEAT(parent, child, mpam_feat_msmon_mbwu, alias)) { 2031 + parent->num_mbwu_mon = child->num_mbwu_mon; 2032 + } else if (MISMATCHED_FEAT(parent, child, mpam_feat_msmon_mbwu, 2033 + num_mbwu_mon, alias)) { 2034 + pr_debug("took the min num_mbwu_mon\n"); 2035 + parent->num_mbwu_mon = min(parent->num_mbwu_mon, 2036 + child->num_mbwu_mon); 2037 + } 2038 + 2039 + if (CAN_MERGE_FEAT(parent, child, mpam_feat_intpri_part, alias)) { 2040 + parent->intpri_wd = child->intpri_wd; 2041 + } else if (MISMATCHED_FEAT(parent, child, mpam_feat_intpri_part, 2042 + intpri_wd, alias)) { 2043 + pr_debug("%s took the min intpri_wd\n", __func__); 2044 + parent->intpri_wd = min(parent->intpri_wd, child->intpri_wd); 2045 + } 2046 + 2047 + if (CAN_MERGE_FEAT(parent, child, mpam_feat_dspri_part, alias)) { 2048 + parent->dspri_wd = child->dspri_wd; 2049 + } else if (MISMATCHED_FEAT(parent, child, mpam_feat_dspri_part, 2050 + dspri_wd, alias)) { 2051 + pr_debug("%s took the min dspri_wd\n", __func__); 2052 + parent->dspri_wd = min(parent->dspri_wd, child->dspri_wd); 2053 + } 2054 + 2055 + /* TODO: alias support for these two */ 2056 + /* {int,ds}pri may not have differing 0-low behaviour */ 2057 + if (mpam_has_feature(mpam_feat_intpri_part, parent) && 2058 + (!mpam_has_feature(mpam_feat_intpri_part, child) || 2059 + mpam_has_feature(mpam_feat_intpri_part_0_low, parent) != 2060 + mpam_has_feature(mpam_feat_intpri_part_0_low, child))) { 2061 + pr_debug("%s cleared intpri_part\n", __func__); 2062 + mpam_clear_feature(mpam_feat_intpri_part, parent); 2063 + mpam_clear_feature(mpam_feat_intpri_part_0_low, parent); 2064 + } 2065 + if (mpam_has_feature(mpam_feat_dspri_part, parent) && 2066 + (!mpam_has_feature(mpam_feat_dspri_part, child) || 2067 + mpam_has_feature(mpam_feat_dspri_part_0_low, parent) != 2068 + mpam_has_feature(mpam_feat_dspri_part_0_low, child))) { 2069 + pr_debug("%s cleared dspri_part\n", __func__); 2070 + mpam_clear_feature(mpam_feat_dspri_part, parent); 2071 + mpam_clear_feature(mpam_feat_dspri_part_0_low, parent); 2072 + } 2073 + 2074 + if (alias) { 2075 + /* Merge features for aliased resources */ 2076 + bitmap_or(parent->features, parent->features, child->features, MPAM_FEATURE_LAST); 2077 + } else { 2078 + /* Clear missing features for non aliasing */ 2079 + bitmap_and(parent->features, parent->features, child->features, MPAM_FEATURE_LAST); 2080 + } 2081 + } 2082 + 2083 + /* 2084 + * If a vmsc doesn't match class feature/configuration, do the right thing(tm). 2085 + * For 'num' properties we can just take the minimum. 2086 + * For properties where the mismatched unused bits would make a difference, we 2087 + * nobble the class feature, as we can't configure all the resources. 2088 + * e.g. The L3 cache is composed of two resources with 13 and 17 portion 2089 + * bitmaps respectively. 2090 + */ 2091 + static void 2092 + __class_props_mismatch(struct mpam_class *class, struct mpam_vmsc *vmsc) 2093 + { 2094 + struct mpam_props *cprops = &class->props; 2095 + struct mpam_props *vprops = &vmsc->props; 2096 + struct device *dev = &vmsc->msc->pdev->dev; 2097 + 2098 + lockdep_assert_held(&mpam_list_lock); /* we modify class */ 2099 + 2100 + dev_dbg(dev, "Merging features for class:0x%lx &= vmsc:0x%lx\n", 2101 + (long)cprops->features, (long)vprops->features); 2102 + 2103 + /* Take the safe value for any common features */ 2104 + __props_mismatch(cprops, vprops, false); 2105 + } 2106 + 2107 + static void 2108 + __vmsc_props_mismatch(struct mpam_vmsc *vmsc, struct mpam_msc_ris *ris) 2109 + { 2110 + struct mpam_props *rprops = &ris->props; 2111 + struct mpam_props *vprops = &vmsc->props; 2112 + struct device *dev = &vmsc->msc->pdev->dev; 2113 + 2114 + lockdep_assert_held(&mpam_list_lock); /* we modify vmsc */ 2115 + 2116 + dev_dbg(dev, "Merging features for vmsc:0x%lx |= ris:0x%lx\n", 2117 + (long)vprops->features, (long)rprops->features); 2118 + 2119 + /* 2120 + * Merge mismatched features - Copy any features that aren't common, 2121 + * but take the safe value for any common features. 2122 + */ 2123 + __props_mismatch(vprops, rprops, true); 2124 + } 2125 + 2126 + /* 2127 + * Copy the first component's first vMSC's properties and features to the 2128 + * class. __class_props_mismatch() will remove conflicts. 2129 + * It is not possible to have a class with no components, or a component with 2130 + * no resources. The vMSC properties have already been built. 2131 + */ 2132 + static void mpam_enable_init_class_features(struct mpam_class *class) 2133 + { 2134 + struct mpam_vmsc *vmsc; 2135 + struct mpam_component *comp; 2136 + 2137 + comp = list_first_entry(&class->components, 2138 + struct mpam_component, class_list); 2139 + vmsc = list_first_entry(&comp->vmsc, 2140 + struct mpam_vmsc, comp_list); 2141 + 2142 + class->props = vmsc->props; 2143 + } 2144 + 2145 + static void mpam_enable_merge_vmsc_features(struct mpam_component *comp) 2146 + { 2147 + struct mpam_vmsc *vmsc; 2148 + struct mpam_msc_ris *ris; 2149 + struct mpam_class *class = comp->class; 2150 + 2151 + list_for_each_entry(vmsc, &comp->vmsc, comp_list) { 2152 + list_for_each_entry(ris, &vmsc->ris, vmsc_list) { 2153 + __vmsc_props_mismatch(vmsc, ris); 2154 + class->nrdy_usec = max(class->nrdy_usec, 2155 + vmsc->msc->nrdy_usec); 2156 + } 2157 + } 2158 + } 2159 + 2160 + static void mpam_enable_merge_class_features(struct mpam_component *comp) 2161 + { 2162 + struct mpam_vmsc *vmsc; 2163 + struct mpam_class *class = comp->class; 2164 + 2165 + list_for_each_entry(vmsc, &comp->vmsc, comp_list) 2166 + __class_props_mismatch(class, vmsc); 2167 + } 2168 + 2169 + /* 2170 + * Merge all the common resource features into class. 2171 + * vmsc features are bitwise-or'd together by mpam_enable_merge_vmsc_features() 2172 + * as the first step so that mpam_enable_init_class_features() can initialise 2173 + * the class with a representative set of features. 2174 + * Next the mpam_enable_merge_class_features() bitwise-and's all the vmsc 2175 + * features to form the class features. 2176 + * Other features are the min/max as appropriate. 2177 + * 2178 + * To avoid walking the whole tree twice, the class->nrdy_usec property is 2179 + * updated when working with the vmsc as it is a max(), and doesn't need 2180 + * initialising first. 2181 + */ 2182 + static void mpam_enable_merge_features(struct list_head *all_classes_list) 2183 + { 2184 + struct mpam_class *class; 2185 + struct mpam_component *comp; 2186 + 2187 + lockdep_assert_held(&mpam_list_lock); 2188 + 2189 + list_for_each_entry(class, all_classes_list, classes_list) { 2190 + list_for_each_entry(comp, &class->components, class_list) 2191 + mpam_enable_merge_vmsc_features(comp); 2192 + 2193 + mpam_enable_init_class_features(class); 2194 + 2195 + list_for_each_entry(comp, &class->components, class_list) 2196 + mpam_enable_merge_class_features(comp); 2197 + } 2198 + } 2199 + 2200 + static char *mpam_errcode_names[16] = { 2201 + [MPAM_ERRCODE_NONE] = "No error", 2202 + [MPAM_ERRCODE_PARTID_SEL_RANGE] = "PARTID_SEL_Range", 2203 + [MPAM_ERRCODE_REQ_PARTID_RANGE] = "Req_PARTID_Range", 2204 + [MPAM_ERRCODE_MSMONCFG_ID_RANGE] = "MSMONCFG_ID_RANGE", 2205 + [MPAM_ERRCODE_REQ_PMG_RANGE] = "Req_PMG_Range", 2206 + [MPAM_ERRCODE_MONITOR_RANGE] = "Monitor_Range", 2207 + [MPAM_ERRCODE_INTPARTID_RANGE] = "intPARTID_Range", 2208 + [MPAM_ERRCODE_UNEXPECTED_INTERNAL] = "Unexpected_INTERNAL", 2209 + [MPAM_ERRCODE_UNDEFINED_RIS_PART_SEL] = "Undefined_RIS_PART_SEL", 2210 + [MPAM_ERRCODE_RIS_NO_CONTROL] = "RIS_No_Control", 2211 + [MPAM_ERRCODE_UNDEFINED_RIS_MON_SEL] = "Undefined_RIS_MON_SEL", 2212 + [MPAM_ERRCODE_RIS_NO_MONITOR] = "RIS_No_Monitor", 2213 + [12 ... 15] = "Reserved" 2214 + }; 2215 + 2216 + static int mpam_enable_msc_ecr(void *_msc) 2217 + { 2218 + struct mpam_msc *msc = _msc; 2219 + 2220 + __mpam_write_reg(msc, MPAMF_ECR, MPAMF_ECR_INTEN); 2221 + 2222 + return 0; 2223 + } 2224 + 2225 + /* This can run in mpam_disable(), and the interrupt handler on the same CPU */ 2226 + static int mpam_disable_msc_ecr(void *_msc) 2227 + { 2228 + struct mpam_msc *msc = _msc; 2229 + 2230 + __mpam_write_reg(msc, MPAMF_ECR, 0); 2231 + 2232 + return 0; 2233 + } 2234 + 2235 + static irqreturn_t __mpam_irq_handler(int irq, struct mpam_msc *msc) 2236 + { 2237 + u64 reg; 2238 + u16 partid; 2239 + u8 errcode, pmg, ris; 2240 + 2241 + if (WARN_ON_ONCE(!msc) || 2242 + WARN_ON_ONCE(!cpumask_test_cpu(smp_processor_id(), 2243 + &msc->accessibility))) 2244 + return IRQ_NONE; 2245 + 2246 + reg = mpam_msc_read_esr(msc); 2247 + 2248 + errcode = FIELD_GET(MPAMF_ESR_ERRCODE, reg); 2249 + if (!errcode) 2250 + return IRQ_NONE; 2251 + 2252 + /* Clear level triggered irq */ 2253 + mpam_msc_clear_esr(msc); 2254 + 2255 + partid = FIELD_GET(MPAMF_ESR_PARTID_MON, reg); 2256 + pmg = FIELD_GET(MPAMF_ESR_PMG, reg); 2257 + ris = FIELD_GET(MPAMF_ESR_RIS, reg); 2258 + 2259 + pr_err_ratelimited("error irq from msc:%u '%s', partid:%u, pmg: %u, ris: %u\n", 2260 + msc->id, mpam_errcode_names[errcode], partid, pmg, 2261 + ris); 2262 + 2263 + /* Disable this interrupt. */ 2264 + mpam_disable_msc_ecr(msc); 2265 + 2266 + /* Are we racing with the thread disabling MPAM? */ 2267 + if (!mpam_is_enabled()) 2268 + return IRQ_HANDLED; 2269 + 2270 + /* 2271 + * Schedule the teardown work. Don't use a threaded IRQ as we can't 2272 + * unregister the interrupt from the threaded part of the handler. 2273 + */ 2274 + mpam_disable_reason = "hardware error interrupt"; 2275 + schedule_work(&mpam_broken_work); 2276 + 2277 + return IRQ_HANDLED; 2278 + } 2279 + 2280 + static irqreturn_t mpam_ppi_handler(int irq, void *dev_id) 2281 + { 2282 + struct mpam_msc *msc = *(struct mpam_msc **)dev_id; 2283 + 2284 + return __mpam_irq_handler(irq, msc); 2285 + } 2286 + 2287 + static irqreturn_t mpam_spi_handler(int irq, void *dev_id) 2288 + { 2289 + struct mpam_msc *msc = dev_id; 2290 + 2291 + return __mpam_irq_handler(irq, msc); 2292 + } 2293 + 2294 + static int mpam_register_irqs(void) 2295 + { 2296 + int err, irq; 2297 + struct mpam_msc *msc; 2298 + 2299 + lockdep_assert_cpus_held(); 2300 + 2301 + guard(srcu)(&mpam_srcu); 2302 + list_for_each_entry_srcu(msc, &mpam_all_msc, all_msc_list, 2303 + srcu_read_lock_held(&mpam_srcu)) { 2304 + irq = platform_get_irq_byname_optional(msc->pdev, "error"); 2305 + if (irq <= 0) 2306 + continue; 2307 + 2308 + /* The MPAM spec says the interrupt can be SPI, PPI or LPI */ 2309 + /* We anticipate sharing the interrupt with other MSCs */ 2310 + if (irq_is_percpu(irq)) { 2311 + err = request_percpu_irq(irq, &mpam_ppi_handler, 2312 + "mpam:msc:error", 2313 + msc->error_dev_id); 2314 + if (err) 2315 + return err; 2316 + 2317 + msc->reenable_error_ppi = irq; 2318 + smp_call_function_many(&msc->accessibility, 2319 + &_enable_percpu_irq, &irq, 2320 + true); 2321 + } else { 2322 + err = devm_request_irq(&msc->pdev->dev, irq, 2323 + &mpam_spi_handler, IRQF_SHARED, 2324 + "mpam:msc:error", msc); 2325 + if (err) 2326 + return err; 2327 + } 2328 + 2329 + mutex_lock(&msc->error_irq_lock); 2330 + msc->error_irq_req = true; 2331 + mpam_touch_msc(msc, mpam_enable_msc_ecr, msc); 2332 + msc->error_irq_hw_enabled = true; 2333 + mutex_unlock(&msc->error_irq_lock); 2334 + } 2335 + 2336 + return 0; 2337 + } 2338 + 2339 + static void mpam_unregister_irqs(void) 2340 + { 2341 + int irq; 2342 + struct mpam_msc *msc; 2343 + 2344 + guard(cpus_read_lock)(); 2345 + guard(srcu)(&mpam_srcu); 2346 + list_for_each_entry_srcu(msc, &mpam_all_msc, all_msc_list, 2347 + srcu_read_lock_held(&mpam_srcu)) { 2348 + irq = platform_get_irq_byname_optional(msc->pdev, "error"); 2349 + if (irq <= 0) 2350 + continue; 2351 + 2352 + mutex_lock(&msc->error_irq_lock); 2353 + if (msc->error_irq_hw_enabled) { 2354 + mpam_touch_msc(msc, mpam_disable_msc_ecr, msc); 2355 + msc->error_irq_hw_enabled = false; 2356 + } 2357 + 2358 + if (msc->error_irq_req) { 2359 + if (irq_is_percpu(irq)) { 2360 + msc->reenable_error_ppi = 0; 2361 + free_percpu_irq(irq, msc->error_dev_id); 2362 + } else { 2363 + devm_free_irq(&msc->pdev->dev, irq, msc); 2364 + } 2365 + msc->error_irq_req = false; 2366 + } 2367 + mutex_unlock(&msc->error_irq_lock); 2368 + } 2369 + } 2370 + 2371 + static void __destroy_component_cfg(struct mpam_component *comp) 2372 + { 2373 + struct mpam_msc *msc; 2374 + struct mpam_vmsc *vmsc; 2375 + struct mpam_msc_ris *ris; 2376 + 2377 + lockdep_assert_held(&mpam_list_lock); 2378 + 2379 + add_to_garbage(comp->cfg); 2380 + list_for_each_entry(vmsc, &comp->vmsc, comp_list) { 2381 + msc = vmsc->msc; 2382 + 2383 + if (mpam_mon_sel_lock(msc)) { 2384 + list_for_each_entry(ris, &vmsc->ris, vmsc_list) 2385 + add_to_garbage(ris->mbwu_state); 2386 + mpam_mon_sel_unlock(msc); 2387 + } 2388 + } 2389 + } 2390 + 2391 + static void mpam_reset_component_cfg(struct mpam_component *comp) 2392 + { 2393 + int i; 2394 + struct mpam_props *cprops = &comp->class->props; 2395 + 2396 + mpam_assert_partid_sizes_fixed(); 2397 + 2398 + if (!comp->cfg) 2399 + return; 2400 + 2401 + for (i = 0; i <= mpam_partid_max; i++) { 2402 + comp->cfg[i] = (struct mpam_config) {}; 2403 + if (cprops->cpbm_wd) 2404 + comp->cfg[i].cpbm = GENMASK(cprops->cpbm_wd - 1, 0); 2405 + if (cprops->mbw_pbm_bits) 2406 + comp->cfg[i].mbw_pbm = GENMASK(cprops->mbw_pbm_bits - 1, 0); 2407 + if (cprops->bwa_wd) 2408 + comp->cfg[i].mbw_max = GENMASK(15, 16 - cprops->bwa_wd); 2409 + } 2410 + } 2411 + 2412 + static int __allocate_component_cfg(struct mpam_component *comp) 2413 + { 2414 + struct mpam_vmsc *vmsc; 2415 + 2416 + mpam_assert_partid_sizes_fixed(); 2417 + 2418 + if (comp->cfg) 2419 + return 0; 2420 + 2421 + comp->cfg = kcalloc(mpam_partid_max + 1, sizeof(*comp->cfg), GFP_KERNEL); 2422 + if (!comp->cfg) 2423 + return -ENOMEM; 2424 + 2425 + /* 2426 + * The array is free()d in one go, so only cfg[0]'s structure needs 2427 + * to be initialised. 2428 + */ 2429 + init_garbage(&comp->cfg[0].garbage); 2430 + 2431 + mpam_reset_component_cfg(comp); 2432 + 2433 + list_for_each_entry(vmsc, &comp->vmsc, comp_list) { 2434 + struct mpam_msc *msc; 2435 + struct mpam_msc_ris *ris; 2436 + struct msmon_mbwu_state *mbwu_state; 2437 + 2438 + if (!vmsc->props.num_mbwu_mon) 2439 + continue; 2440 + 2441 + msc = vmsc->msc; 2442 + list_for_each_entry(ris, &vmsc->ris, vmsc_list) { 2443 + if (!ris->props.num_mbwu_mon) 2444 + continue; 2445 + 2446 + mbwu_state = kcalloc(ris->props.num_mbwu_mon, 2447 + sizeof(*ris->mbwu_state), 2448 + GFP_KERNEL); 2449 + if (!mbwu_state) { 2450 + __destroy_component_cfg(comp); 2451 + return -ENOMEM; 2452 + } 2453 + 2454 + init_garbage(&mbwu_state[0].garbage); 2455 + 2456 + if (mpam_mon_sel_lock(msc)) { 2457 + ris->mbwu_state = mbwu_state; 2458 + mpam_mon_sel_unlock(msc); 2459 + } 2460 + } 2461 + } 2462 + 2463 + return 0; 2464 + } 2465 + 2466 + static int mpam_allocate_config(void) 2467 + { 2468 + struct mpam_class *class; 2469 + struct mpam_component *comp; 2470 + 2471 + lockdep_assert_held(&mpam_list_lock); 2472 + 2473 + list_for_each_entry(class, &mpam_classes, classes_list) { 2474 + list_for_each_entry(comp, &class->components, class_list) { 2475 + int err = __allocate_component_cfg(comp); 2476 + if (err) 2477 + return err; 2478 + } 2479 + } 2480 + 2481 + return 0; 2482 + } 2483 + 2484 + static void mpam_enable_once(void) 2485 + { 2486 + int err; 2487 + 2488 + /* 2489 + * Once the cpuhp callbacks have been changed, mpam_partid_max can no 2490 + * longer change. 2491 + */ 2492 + spin_lock(&partid_max_lock); 2493 + partid_max_published = true; 2494 + spin_unlock(&partid_max_lock); 2495 + 2496 + /* 2497 + * If all the MSC have been probed, enabling the IRQs happens next. 2498 + * That involves cross-calling to a CPU that can reach the MSC, and 2499 + * the locks must be taken in this order: 2500 + */ 2501 + cpus_read_lock(); 2502 + mutex_lock(&mpam_list_lock); 2503 + do { 2504 + mpam_enable_merge_features(&mpam_classes); 2505 + 2506 + err = mpam_register_irqs(); 2507 + if (err) { 2508 + pr_warn("Failed to register irqs: %d\n", err); 2509 + break; 2510 + } 2511 + 2512 + err = mpam_allocate_config(); 2513 + if (err) { 2514 + pr_err("Failed to allocate configuration arrays.\n"); 2515 + break; 2516 + } 2517 + } while (0); 2518 + mutex_unlock(&mpam_list_lock); 2519 + cpus_read_unlock(); 2520 + 2521 + if (err) { 2522 + mpam_disable_reason = "Failed to enable."; 2523 + schedule_work(&mpam_broken_work); 2524 + return; 2525 + } 2526 + 2527 + static_branch_enable(&mpam_enabled); 2528 + mpam_register_cpuhp_callbacks(mpam_cpu_online, mpam_cpu_offline, 2529 + "mpam:online"); 2530 + 2531 + /* Use printk() to avoid the pr_fmt adding the function name. */ 2532 + printk(KERN_INFO "MPAM enabled with %u PARTIDs and %u PMGs\n", 2533 + mpam_partid_max + 1, mpam_pmg_max + 1); 2534 + } 2535 + 2536 + static void mpam_reset_component_locked(struct mpam_component *comp) 2537 + { 2538 + struct mpam_vmsc *vmsc; 2539 + 2540 + lockdep_assert_cpus_held(); 2541 + mpam_assert_partid_sizes_fixed(); 2542 + 2543 + mpam_reset_component_cfg(comp); 2544 + 2545 + guard(srcu)(&mpam_srcu); 2546 + list_for_each_entry_srcu(vmsc, &comp->vmsc, comp_list, 2547 + srcu_read_lock_held(&mpam_srcu)) { 2548 + struct mpam_msc *msc = vmsc->msc; 2549 + struct mpam_msc_ris *ris; 2550 + 2551 + list_for_each_entry_srcu(ris, &vmsc->ris, vmsc_list, 2552 + srcu_read_lock_held(&mpam_srcu)) { 2553 + if (!ris->in_reset_state) 2554 + mpam_touch_msc(msc, mpam_reset_ris, ris); 2555 + ris->in_reset_state = true; 2556 + } 2557 + } 2558 + } 2559 + 2560 + static void mpam_reset_class_locked(struct mpam_class *class) 2561 + { 2562 + struct mpam_component *comp; 2563 + 2564 + lockdep_assert_cpus_held(); 2565 + 2566 + guard(srcu)(&mpam_srcu); 2567 + list_for_each_entry_srcu(comp, &class->components, class_list, 2568 + srcu_read_lock_held(&mpam_srcu)) 2569 + mpam_reset_component_locked(comp); 2570 + } 2571 + 2572 + static void mpam_reset_class(struct mpam_class *class) 2573 + { 2574 + cpus_read_lock(); 2575 + mpam_reset_class_locked(class); 2576 + cpus_read_unlock(); 2577 + } 2578 + 2579 + /* 2580 + * Called in response to an error IRQ. 2581 + * All of MPAMs errors indicate a software bug, restore any modified 2582 + * controls to their reset values. 2583 + */ 2584 + void mpam_disable(struct work_struct *ignored) 2585 + { 2586 + int idx; 2587 + struct mpam_class *class; 2588 + struct mpam_msc *msc, *tmp; 2589 + 2590 + mutex_lock(&mpam_cpuhp_state_lock); 2591 + if (mpam_cpuhp_state) { 2592 + cpuhp_remove_state(mpam_cpuhp_state); 2593 + mpam_cpuhp_state = 0; 2594 + } 2595 + mutex_unlock(&mpam_cpuhp_state_lock); 2596 + 2597 + static_branch_disable(&mpam_enabled); 2598 + 2599 + mpam_unregister_irqs(); 2600 + 2601 + idx = srcu_read_lock(&mpam_srcu); 2602 + list_for_each_entry_srcu(class, &mpam_classes, classes_list, 2603 + srcu_read_lock_held(&mpam_srcu)) 2604 + mpam_reset_class(class); 2605 + srcu_read_unlock(&mpam_srcu, idx); 2606 + 2607 + mutex_lock(&mpam_list_lock); 2608 + list_for_each_entry_safe(msc, tmp, &mpam_all_msc, all_msc_list) 2609 + mpam_msc_destroy(msc); 2610 + mutex_unlock(&mpam_list_lock); 2611 + mpam_free_garbage(); 2612 + 2613 + pr_err_once("MPAM disabled due to %s\n", mpam_disable_reason); 2614 + } 2615 + 2616 + /* 2617 + * Enable mpam once all devices have been probed. 2618 + * Scheduled by mpam_discovery_cpu_online() once all devices have been created. 2619 + * Also scheduled when new devices are probed when new CPUs come online. 2620 + */ 2621 + void mpam_enable(struct work_struct *work) 2622 + { 2623 + static atomic_t once; 2624 + struct mpam_msc *msc; 2625 + bool all_devices_probed = true; 2626 + 2627 + /* Have we probed all the hw devices? */ 2628 + guard(srcu)(&mpam_srcu); 2629 + list_for_each_entry_srcu(msc, &mpam_all_msc, all_msc_list, 2630 + srcu_read_lock_held(&mpam_srcu)) { 2631 + mutex_lock(&msc->probe_lock); 2632 + if (!msc->probed) 2633 + all_devices_probed = false; 2634 + mutex_unlock(&msc->probe_lock); 2635 + 2636 + if (!all_devices_probed) 2637 + break; 2638 + } 2639 + 2640 + if (all_devices_probed && !atomic_fetch_inc(&once)) 2641 + mpam_enable_once(); 2642 + } 2643 + 2644 + #define maybe_update_config(cfg, feature, newcfg, member, changes) do { \ 2645 + if (mpam_has_feature(feature, newcfg) && \ 2646 + (newcfg)->member != (cfg)->member) { \ 2647 + (cfg)->member = (newcfg)->member; \ 2648 + mpam_set_feature(feature, cfg); \ 2649 + \ 2650 + (changes) = true; \ 2651 + } \ 2652 + } while (0) 2653 + 2654 + static bool mpam_update_config(struct mpam_config *cfg, 2655 + const struct mpam_config *newcfg) 2656 + { 2657 + bool has_changes = false; 2658 + 2659 + maybe_update_config(cfg, mpam_feat_cpor_part, newcfg, cpbm, has_changes); 2660 + maybe_update_config(cfg, mpam_feat_mbw_part, newcfg, mbw_pbm, has_changes); 2661 + maybe_update_config(cfg, mpam_feat_mbw_max, newcfg, mbw_max, has_changes); 2662 + 2663 + return has_changes; 2664 + } 2665 + 2666 + int mpam_apply_config(struct mpam_component *comp, u16 partid, 2667 + struct mpam_config *cfg) 2668 + { 2669 + struct mpam_write_config_arg arg; 2670 + struct mpam_msc_ris *ris; 2671 + struct mpam_vmsc *vmsc; 2672 + struct mpam_msc *msc; 2673 + 2674 + lockdep_assert_cpus_held(); 2675 + 2676 + /* Don't pass in the current config! */ 2677 + WARN_ON_ONCE(&comp->cfg[partid] == cfg); 2678 + 2679 + if (!mpam_update_config(&comp->cfg[partid], cfg)) 2680 + return 0; 2681 + 2682 + arg.comp = comp; 2683 + arg.partid = partid; 2684 + 2685 + guard(srcu)(&mpam_srcu); 2686 + list_for_each_entry_srcu(vmsc, &comp->vmsc, comp_list, 2687 + srcu_read_lock_held(&mpam_srcu)) { 2688 + msc = vmsc->msc; 2689 + 2690 + mutex_lock(&msc->cfg_lock); 2691 + list_for_each_entry_srcu(ris, &vmsc->ris, vmsc_list, 2692 + srcu_read_lock_held(&mpam_srcu)) { 2693 + arg.ris = ris; 2694 + mpam_touch_msc(msc, __write_config, &arg); 2695 + } 2696 + mutex_unlock(&msc->cfg_lock); 2697 + } 2698 + 2699 + return 0; 2700 + } 2701 + 2702 + static int __init mpam_msc_driver_init(void) 2703 + { 2704 + if (!system_supports_mpam()) 2705 + return -EOPNOTSUPP; 2706 + 2707 + init_srcu_struct(&mpam_srcu); 2708 + 2709 + fw_num_msc = acpi_mpam_count_msc(); 2710 + if (fw_num_msc <= 0) { 2711 + pr_err("No MSC devices found in firmware\n"); 2712 + return -EINVAL; 2713 + } 2714 + 2715 + return platform_driver_register(&mpam_msc_driver); 2716 + } 2717 + 2718 + /* Must occur after arm64_mpam_register_cpus() from arch_initcall() */ 2719 + subsys_initcall(mpam_msc_driver_init); 2720 + 2721 + #ifdef CONFIG_MPAM_KUNIT_TEST 2722 + #include "test_mpam_devices.c" 2723 + #endif
+658
drivers/resctrl/mpam_internal.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + // Copyright (C) 2025 Arm Ltd. 3 + 4 + #ifndef MPAM_INTERNAL_H 5 + #define MPAM_INTERNAL_H 6 + 7 + #include <linux/arm_mpam.h> 8 + #include <linux/atomic.h> 9 + #include <linux/bitmap.h> 10 + #include <linux/cpumask.h> 11 + #include <linux/io.h> 12 + #include <linux/jump_label.h> 13 + #include <linux/llist.h> 14 + #include <linux/mutex.h> 15 + #include <linux/srcu.h> 16 + #include <linux/spinlock.h> 17 + #include <linux/srcu.h> 18 + #include <linux/types.h> 19 + 20 + #define MPAM_MSC_MAX_NUM_RIS 16 21 + 22 + struct platform_device; 23 + 24 + DECLARE_STATIC_KEY_FALSE(mpam_enabled); 25 + 26 + #ifdef CONFIG_MPAM_KUNIT_TEST 27 + #define PACKED_FOR_KUNIT __packed 28 + #else 29 + #define PACKED_FOR_KUNIT 30 + #endif 31 + 32 + static inline bool mpam_is_enabled(void) 33 + { 34 + return static_branch_likely(&mpam_enabled); 35 + } 36 + 37 + /* 38 + * Structures protected by SRCU may not be freed for a surprising amount of 39 + * time (especially if perf is running). To ensure the MPAM error interrupt can 40 + * tear down all the structures, build a list of objects that can be garbage 41 + * collected once synchronize_srcu() has returned. 42 + * If pdev is non-NULL, use devm_kfree(). 43 + */ 44 + struct mpam_garbage { 45 + /* member of mpam_garbage */ 46 + struct llist_node llist; 47 + 48 + void *to_free; 49 + struct platform_device *pdev; 50 + }; 51 + 52 + struct mpam_msc { 53 + /* member of mpam_all_msc */ 54 + struct list_head all_msc_list; 55 + 56 + int id; 57 + struct platform_device *pdev; 58 + 59 + /* Not modified after mpam_is_enabled() becomes true */ 60 + enum mpam_msc_iface iface; 61 + u32 nrdy_usec; 62 + cpumask_t accessibility; 63 + bool has_extd_esr; 64 + 65 + int reenable_error_ppi; 66 + struct mpam_msc * __percpu *error_dev_id; 67 + 68 + atomic_t online_refs; 69 + 70 + /* 71 + * probe_lock is only taken during discovery. After discovery these 72 + * properties become read-only and the lists are protected by SRCU. 73 + */ 74 + struct mutex probe_lock; 75 + bool probed; 76 + u16 partid_max; 77 + u8 pmg_max; 78 + unsigned long ris_idxs; 79 + u32 ris_max; 80 + 81 + /* 82 + * error_irq_lock is taken when registering/unregistering the error 83 + * interrupt and maniupulating the below flags. 84 + */ 85 + struct mutex error_irq_lock; 86 + bool error_irq_req; 87 + bool error_irq_hw_enabled; 88 + 89 + /* mpam_msc_ris of this component */ 90 + struct list_head ris; 91 + 92 + /* 93 + * part_sel_lock protects access to the MSC hardware registers that are 94 + * affected by MPAMCFG_PART_SEL. (including the ID registers that vary 95 + * by RIS). 96 + * If needed, take msc->probe_lock first. 97 + */ 98 + struct mutex part_sel_lock; 99 + 100 + /* 101 + * cfg_lock protects the msc configuration and guards against mbwu_state 102 + * save and restore racing. 103 + */ 104 + struct mutex cfg_lock; 105 + 106 + /* 107 + * mon_sel_lock protects access to the MSC hardware registers that are 108 + * affected by MPAMCFG_MON_SEL, and the mbwu_state. 109 + * Access to mon_sel is needed from both process and interrupt contexts, 110 + * but is complicated by firmware-backed platforms that can't make any 111 + * access unless they can sleep. 112 + * Always use the mpam_mon_sel_lock() helpers. 113 + * Accesses to mon_sel need to be able to fail if they occur in the wrong 114 + * context. 115 + * If needed, take msc->probe_lock first. 116 + */ 117 + raw_spinlock_t _mon_sel_lock; 118 + unsigned long _mon_sel_flags; 119 + 120 + void __iomem *mapped_hwpage; 121 + size_t mapped_hwpage_sz; 122 + 123 + struct mpam_garbage garbage; 124 + }; 125 + 126 + /* Returning false here means accesses to mon_sel must fail and report an error. */ 127 + static inline bool __must_check mpam_mon_sel_lock(struct mpam_msc *msc) 128 + { 129 + /* Locking will require updating to support a firmware backed interface */ 130 + if (WARN_ON_ONCE(msc->iface != MPAM_IFACE_MMIO)) 131 + return false; 132 + 133 + raw_spin_lock_irqsave(&msc->_mon_sel_lock, msc->_mon_sel_flags); 134 + return true; 135 + } 136 + 137 + static inline void mpam_mon_sel_unlock(struct mpam_msc *msc) 138 + { 139 + raw_spin_unlock_irqrestore(&msc->_mon_sel_lock, msc->_mon_sel_flags); 140 + } 141 + 142 + static inline void mpam_mon_sel_lock_held(struct mpam_msc *msc) 143 + { 144 + lockdep_assert_held_once(&msc->_mon_sel_lock); 145 + } 146 + 147 + static inline void mpam_mon_sel_lock_init(struct mpam_msc *msc) 148 + { 149 + raw_spin_lock_init(&msc->_mon_sel_lock); 150 + } 151 + 152 + /* Bits for mpam features bitmaps */ 153 + enum mpam_device_features { 154 + mpam_feat_cpor_part, 155 + mpam_feat_cmax_softlim, 156 + mpam_feat_cmax_cmax, 157 + mpam_feat_cmax_cmin, 158 + mpam_feat_cmax_cassoc, 159 + mpam_feat_mbw_part, 160 + mpam_feat_mbw_min, 161 + mpam_feat_mbw_max, 162 + mpam_feat_mbw_prop, 163 + mpam_feat_intpri_part, 164 + mpam_feat_intpri_part_0_low, 165 + mpam_feat_dspri_part, 166 + mpam_feat_dspri_part_0_low, 167 + mpam_feat_msmon, 168 + mpam_feat_msmon_csu, 169 + mpam_feat_msmon_csu_capture, 170 + mpam_feat_msmon_csu_xcl, 171 + mpam_feat_msmon_csu_hw_nrdy, 172 + mpam_feat_msmon_mbwu, 173 + mpam_feat_msmon_mbwu_31counter, 174 + mpam_feat_msmon_mbwu_44counter, 175 + mpam_feat_msmon_mbwu_63counter, 176 + mpam_feat_msmon_mbwu_capture, 177 + mpam_feat_msmon_mbwu_rwbw, 178 + mpam_feat_msmon_mbwu_hw_nrdy, 179 + mpam_feat_partid_nrw, 180 + MPAM_FEATURE_LAST 181 + }; 182 + 183 + struct mpam_props { 184 + DECLARE_BITMAP(features, MPAM_FEATURE_LAST); 185 + 186 + u16 cpbm_wd; 187 + u16 mbw_pbm_bits; 188 + u16 bwa_wd; 189 + u16 cmax_wd; 190 + u16 cassoc_wd; 191 + u16 intpri_wd; 192 + u16 dspri_wd; 193 + u16 num_csu_mon; 194 + u16 num_mbwu_mon; 195 + 196 + /* 197 + * Kunit tests use memset() to set up feature combinations that should be 198 + * removed, and will false-positive if the compiler introduces padding that 199 + * isn't cleared during sanitisation. 200 + */ 201 + } PACKED_FOR_KUNIT; 202 + 203 + #define mpam_has_feature(_feat, x) test_bit(_feat, (x)->features) 204 + #define mpam_set_feature(_feat, x) set_bit(_feat, (x)->features) 205 + #define mpam_clear_feature(_feat, x) clear_bit(_feat, (x)->features) 206 + 207 + /* The values for MSMON_CFG_MBWU_FLT.RWBW */ 208 + enum mon_filter_options { 209 + COUNT_BOTH = 0, 210 + COUNT_WRITE = 1, 211 + COUNT_READ = 2, 212 + }; 213 + 214 + struct mon_cfg { 215 + u16 mon; 216 + u8 pmg; 217 + bool match_pmg; 218 + bool csu_exclude_clean; 219 + u32 partid; 220 + enum mon_filter_options opts; 221 + }; 222 + 223 + /* Changes to msmon_mbwu_state are protected by the msc's mon_sel_lock. */ 224 + struct msmon_mbwu_state { 225 + bool enabled; 226 + bool reset_on_next_read; 227 + struct mon_cfg cfg; 228 + 229 + /* 230 + * The value to add to the new reading to account for power management, 231 + * and overflow. 232 + */ 233 + u64 correction; 234 + 235 + struct mpam_garbage garbage; 236 + }; 237 + 238 + struct mpam_class { 239 + /* mpam_components in this class */ 240 + struct list_head components; 241 + 242 + cpumask_t affinity; 243 + 244 + struct mpam_props props; 245 + u32 nrdy_usec; 246 + u8 level; 247 + enum mpam_class_types type; 248 + 249 + /* member of mpam_classes */ 250 + struct list_head classes_list; 251 + 252 + struct ida ida_csu_mon; 253 + struct ida ida_mbwu_mon; 254 + 255 + struct mpam_garbage garbage; 256 + }; 257 + 258 + struct mpam_config { 259 + /* Which configuration values are valid. */ 260 + DECLARE_BITMAP(features, MPAM_FEATURE_LAST); 261 + 262 + u32 cpbm; 263 + u32 mbw_pbm; 264 + u16 mbw_max; 265 + 266 + bool reset_cpbm; 267 + bool reset_mbw_pbm; 268 + bool reset_mbw_max; 269 + 270 + struct mpam_garbage garbage; 271 + }; 272 + 273 + struct mpam_component { 274 + u32 comp_id; 275 + 276 + /* mpam_vmsc in this component */ 277 + struct list_head vmsc; 278 + 279 + cpumask_t affinity; 280 + 281 + /* 282 + * Array of configuration values, indexed by partid. 283 + * Read from cpuhp callbacks, hold the cpuhp lock when writing. 284 + */ 285 + struct mpam_config *cfg; 286 + 287 + /* member of mpam_class:components */ 288 + struct list_head class_list; 289 + 290 + /* parent: */ 291 + struct mpam_class *class; 292 + 293 + struct mpam_garbage garbage; 294 + }; 295 + 296 + struct mpam_vmsc { 297 + /* member of mpam_component:vmsc_list */ 298 + struct list_head comp_list; 299 + 300 + /* mpam_msc_ris in this vmsc */ 301 + struct list_head ris; 302 + 303 + struct mpam_props props; 304 + 305 + /* All RIS in this vMSC are members of this MSC */ 306 + struct mpam_msc *msc; 307 + 308 + /* parent: */ 309 + struct mpam_component *comp; 310 + 311 + struct mpam_garbage garbage; 312 + }; 313 + 314 + struct mpam_msc_ris { 315 + u8 ris_idx; 316 + u64 idr; 317 + struct mpam_props props; 318 + bool in_reset_state; 319 + 320 + cpumask_t affinity; 321 + 322 + /* member of mpam_vmsc:ris */ 323 + struct list_head vmsc_list; 324 + 325 + /* member of mpam_msc:ris */ 326 + struct list_head msc_list; 327 + 328 + /* parent: */ 329 + struct mpam_vmsc *vmsc; 330 + 331 + /* msmon mbwu configuration is preserved over reset */ 332 + struct msmon_mbwu_state *mbwu_state; 333 + 334 + struct mpam_garbage garbage; 335 + }; 336 + 337 + static inline int mpam_alloc_csu_mon(struct mpam_class *class) 338 + { 339 + struct mpam_props *cprops = &class->props; 340 + 341 + if (!mpam_has_feature(mpam_feat_msmon_csu, cprops)) 342 + return -EOPNOTSUPP; 343 + 344 + return ida_alloc_max(&class->ida_csu_mon, cprops->num_csu_mon - 1, 345 + GFP_KERNEL); 346 + } 347 + 348 + static inline void mpam_free_csu_mon(struct mpam_class *class, int csu_mon) 349 + { 350 + ida_free(&class->ida_csu_mon, csu_mon); 351 + } 352 + 353 + static inline int mpam_alloc_mbwu_mon(struct mpam_class *class) 354 + { 355 + struct mpam_props *cprops = &class->props; 356 + 357 + if (!mpam_has_feature(mpam_feat_msmon_mbwu, cprops)) 358 + return -EOPNOTSUPP; 359 + 360 + return ida_alloc_max(&class->ida_mbwu_mon, cprops->num_mbwu_mon - 1, 361 + GFP_KERNEL); 362 + } 363 + 364 + static inline void mpam_free_mbwu_mon(struct mpam_class *class, int mbwu_mon) 365 + { 366 + ida_free(&class->ida_mbwu_mon, mbwu_mon); 367 + } 368 + 369 + /* List of all classes - protected by srcu*/ 370 + extern struct srcu_struct mpam_srcu; 371 + extern struct list_head mpam_classes; 372 + 373 + /* System wide partid/pmg values */ 374 + extern u16 mpam_partid_max; 375 + extern u8 mpam_pmg_max; 376 + 377 + /* Scheduled work callback to enable mpam once all MSC have been probed */ 378 + void mpam_enable(struct work_struct *work); 379 + void mpam_disable(struct work_struct *work); 380 + 381 + int mpam_apply_config(struct mpam_component *comp, u16 partid, 382 + struct mpam_config *cfg); 383 + 384 + int mpam_msmon_read(struct mpam_component *comp, struct mon_cfg *ctx, 385 + enum mpam_device_features, u64 *val); 386 + void mpam_msmon_reset_mbwu(struct mpam_component *comp, struct mon_cfg *ctx); 387 + 388 + int mpam_get_cpumask_from_cache_id(unsigned long cache_id, u32 cache_level, 389 + cpumask_t *affinity); 390 + 391 + /* 392 + * MPAM MSCs have the following register layout. See: 393 + * Arm Memory System Resource Partitioning and Monitoring (MPAM) System 394 + * Component Specification. 395 + * https://developer.arm.com/documentation/ihi0099/aa/ 396 + */ 397 + #define MPAM_ARCHITECTURE_V1 0x10 398 + 399 + /* Memory mapped control pages */ 400 + /* ID Register offsets in the memory mapped page */ 401 + #define MPAMF_IDR 0x0000 /* features id register */ 402 + #define MPAMF_IIDR 0x0018 /* implementer id register */ 403 + #define MPAMF_AIDR 0x0020 /* architectural id register */ 404 + #define MPAMF_IMPL_IDR 0x0028 /* imp-def partitioning */ 405 + #define MPAMF_CPOR_IDR 0x0030 /* cache-portion partitioning */ 406 + #define MPAMF_CCAP_IDR 0x0038 /* cache-capacity partitioning */ 407 + #define MPAMF_MBW_IDR 0x0040 /* mem-bw partitioning */ 408 + #define MPAMF_PRI_IDR 0x0048 /* priority partitioning */ 409 + #define MPAMF_MSMON_IDR 0x0080 /* performance monitoring features */ 410 + #define MPAMF_CSUMON_IDR 0x0088 /* cache-usage monitor */ 411 + #define MPAMF_MBWUMON_IDR 0x0090 /* mem-bw usage monitor */ 412 + #define MPAMF_PARTID_NRW_IDR 0x0050 /* partid-narrowing */ 413 + 414 + /* Configuration and Status Register offsets in the memory mapped page */ 415 + #define MPAMCFG_PART_SEL 0x0100 /* partid to configure */ 416 + #define MPAMCFG_CPBM 0x1000 /* cache-portion config */ 417 + #define MPAMCFG_CMAX 0x0108 /* cache-capacity config */ 418 + #define MPAMCFG_CMIN 0x0110 /* cache-capacity config */ 419 + #define MPAMCFG_CASSOC 0x0118 /* cache-associativity config */ 420 + #define MPAMCFG_MBW_MIN 0x0200 /* min mem-bw config */ 421 + #define MPAMCFG_MBW_MAX 0x0208 /* max mem-bw config */ 422 + #define MPAMCFG_MBW_WINWD 0x0220 /* mem-bw accounting window config */ 423 + #define MPAMCFG_MBW_PBM 0x2000 /* mem-bw portion bitmap config */ 424 + #define MPAMCFG_PRI 0x0400 /* priority partitioning config */ 425 + #define MPAMCFG_MBW_PROP 0x0500 /* mem-bw stride config */ 426 + #define MPAMCFG_INTPARTID 0x0600 /* partid-narrowing config */ 427 + 428 + #define MSMON_CFG_MON_SEL 0x0800 /* monitor selector */ 429 + #define MSMON_CFG_CSU_FLT 0x0810 /* cache-usage monitor filter */ 430 + #define MSMON_CFG_CSU_CTL 0x0818 /* cache-usage monitor config */ 431 + #define MSMON_CFG_MBWU_FLT 0x0820 /* mem-bw monitor filter */ 432 + #define MSMON_CFG_MBWU_CTL 0x0828 /* mem-bw monitor config */ 433 + #define MSMON_CSU 0x0840 /* current cache-usage */ 434 + #define MSMON_CSU_CAPTURE 0x0848 /* last cache-usage value captured */ 435 + #define MSMON_MBWU 0x0860 /* current mem-bw usage value */ 436 + #define MSMON_MBWU_CAPTURE 0x0868 /* last mem-bw value captured */ 437 + #define MSMON_MBWU_L 0x0880 /* current long mem-bw usage value */ 438 + #define MSMON_MBWU_L_CAPTURE 0x0890 /* last long mem-bw value captured */ 439 + #define MSMON_CAPT_EVNT 0x0808 /* signal a capture event */ 440 + #define MPAMF_ESR 0x00F8 /* error status register */ 441 + #define MPAMF_ECR 0x00F0 /* error control register */ 442 + 443 + /* MPAMF_IDR - MPAM features ID register */ 444 + #define MPAMF_IDR_PARTID_MAX GENMASK(15, 0) 445 + #define MPAMF_IDR_PMG_MAX GENMASK(23, 16) 446 + #define MPAMF_IDR_HAS_CCAP_PART BIT(24) 447 + #define MPAMF_IDR_HAS_CPOR_PART BIT(25) 448 + #define MPAMF_IDR_HAS_MBW_PART BIT(26) 449 + #define MPAMF_IDR_HAS_PRI_PART BIT(27) 450 + #define MPAMF_IDR_EXT BIT(28) 451 + #define MPAMF_IDR_HAS_IMPL_IDR BIT(29) 452 + #define MPAMF_IDR_HAS_MSMON BIT(30) 453 + #define MPAMF_IDR_HAS_PARTID_NRW BIT(31) 454 + #define MPAMF_IDR_HAS_RIS BIT(32) 455 + #define MPAMF_IDR_HAS_EXTD_ESR BIT(38) 456 + #define MPAMF_IDR_HAS_ESR BIT(39) 457 + #define MPAMF_IDR_RIS_MAX GENMASK(59, 56) 458 + 459 + /* MPAMF_MSMON_IDR - MPAM performance monitoring ID register */ 460 + #define MPAMF_MSMON_IDR_MSMON_CSU BIT(16) 461 + #define MPAMF_MSMON_IDR_MSMON_MBWU BIT(17) 462 + #define MPAMF_MSMON_IDR_HAS_LOCAL_CAPT_EVNT BIT(31) 463 + 464 + /* MPAMF_CPOR_IDR - MPAM features cache portion partitioning ID register */ 465 + #define MPAMF_CPOR_IDR_CPBM_WD GENMASK(15, 0) 466 + 467 + /* MPAMF_CCAP_IDR - MPAM features cache capacity partitioning ID register */ 468 + #define MPAMF_CCAP_IDR_CMAX_WD GENMASK(5, 0) 469 + #define MPAMF_CCAP_IDR_CASSOC_WD GENMASK(12, 8) 470 + #define MPAMF_CCAP_IDR_HAS_CASSOC BIT(28) 471 + #define MPAMF_CCAP_IDR_HAS_CMIN BIT(29) 472 + #define MPAMF_CCAP_IDR_NO_CMAX BIT(30) 473 + #define MPAMF_CCAP_IDR_HAS_CMAX_SOFTLIM BIT(31) 474 + 475 + /* MPAMF_MBW_IDR - MPAM features memory bandwidth partitioning ID register */ 476 + #define MPAMF_MBW_IDR_BWA_WD GENMASK(5, 0) 477 + #define MPAMF_MBW_IDR_HAS_MIN BIT(10) 478 + #define MPAMF_MBW_IDR_HAS_MAX BIT(11) 479 + #define MPAMF_MBW_IDR_HAS_PBM BIT(12) 480 + #define MPAMF_MBW_IDR_HAS_PROP BIT(13) 481 + #define MPAMF_MBW_IDR_WINDWR BIT(14) 482 + #define MPAMF_MBW_IDR_BWPBM_WD GENMASK(28, 16) 483 + 484 + /* MPAMF_PRI_IDR - MPAM features priority partitioning ID register */ 485 + #define MPAMF_PRI_IDR_HAS_INTPRI BIT(0) 486 + #define MPAMF_PRI_IDR_INTPRI_0_IS_LOW BIT(1) 487 + #define MPAMF_PRI_IDR_INTPRI_WD GENMASK(9, 4) 488 + #define MPAMF_PRI_IDR_HAS_DSPRI BIT(16) 489 + #define MPAMF_PRI_IDR_DSPRI_0_IS_LOW BIT(17) 490 + #define MPAMF_PRI_IDR_DSPRI_WD GENMASK(25, 20) 491 + 492 + /* MPAMF_CSUMON_IDR - MPAM cache storage usage monitor ID register */ 493 + #define MPAMF_CSUMON_IDR_NUM_MON GENMASK(15, 0) 494 + #define MPAMF_CSUMON_IDR_HAS_OFLOW_CAPT BIT(24) 495 + #define MPAMF_CSUMON_IDR_HAS_CEVNT_OFLW BIT(25) 496 + #define MPAMF_CSUMON_IDR_HAS_OFSR BIT(26) 497 + #define MPAMF_CSUMON_IDR_HAS_OFLOW_LNKG BIT(27) 498 + #define MPAMF_CSUMON_IDR_HAS_XCL BIT(29) 499 + #define MPAMF_CSUMON_IDR_CSU_RO BIT(30) 500 + #define MPAMF_CSUMON_IDR_HAS_CAPTURE BIT(31) 501 + 502 + /* MPAMF_MBWUMON_IDR - MPAM memory bandwidth usage monitor ID register */ 503 + #define MPAMF_MBWUMON_IDR_NUM_MON GENMASK(15, 0) 504 + #define MPAMF_MBWUMON_IDR_HAS_RWBW BIT(28) 505 + #define MPAMF_MBWUMON_IDR_LWD BIT(29) 506 + #define MPAMF_MBWUMON_IDR_HAS_LONG BIT(30) 507 + #define MPAMF_MBWUMON_IDR_HAS_CAPTURE BIT(31) 508 + 509 + /* MPAMF_PARTID_NRW_IDR - MPAM PARTID narrowing ID register */ 510 + #define MPAMF_PARTID_NRW_IDR_INTPARTID_MAX GENMASK(15, 0) 511 + 512 + /* MPAMF_IIDR - MPAM implementation ID register */ 513 + #define MPAMF_IIDR_IMPLEMENTER GENMASK(11, 0) 514 + #define MPAMF_IIDR_REVISION GENMASK(15, 12) 515 + #define MPAMF_IIDR_VARIANT GENMASK(19, 16) 516 + #define MPAMF_IIDR_PRODUCTID GENMASK(31, 20) 517 + 518 + /* MPAMF_AIDR - MPAM architecture ID register */ 519 + #define MPAMF_AIDR_ARCH_MINOR_REV GENMASK(3, 0) 520 + #define MPAMF_AIDR_ARCH_MAJOR_REV GENMASK(7, 4) 521 + 522 + /* MPAMCFG_PART_SEL - MPAM partition configuration selection register */ 523 + #define MPAMCFG_PART_SEL_PARTID_SEL GENMASK(15, 0) 524 + #define MPAMCFG_PART_SEL_INTERNAL BIT(16) 525 + #define MPAMCFG_PART_SEL_RIS GENMASK(27, 24) 526 + 527 + /* MPAMCFG_CASSOC - MPAM cache maximum associativity partition configuration register */ 528 + #define MPAMCFG_CASSOC_CASSOC GENMASK(15, 0) 529 + 530 + /* MPAMCFG_CMAX - MPAM cache capacity configuration register */ 531 + #define MPAMCFG_CMAX_SOFTLIM BIT(31) 532 + #define MPAMCFG_CMAX_CMAX GENMASK(15, 0) 533 + 534 + /* MPAMCFG_CMIN - MPAM cache capacity configuration register */ 535 + #define MPAMCFG_CMIN_CMIN GENMASK(15, 0) 536 + 537 + /* 538 + * MPAMCFG_MBW_MIN - MPAM memory minimum bandwidth partitioning configuration 539 + * register 540 + */ 541 + #define MPAMCFG_MBW_MIN_MIN GENMASK(15, 0) 542 + 543 + /* 544 + * MPAMCFG_MBW_MAX - MPAM memory maximum bandwidth partitioning configuration 545 + * register 546 + */ 547 + #define MPAMCFG_MBW_MAX_MAX GENMASK(15, 0) 548 + #define MPAMCFG_MBW_MAX_HARDLIM BIT(31) 549 + 550 + /* 551 + * MPAMCFG_MBW_WINWD - MPAM memory bandwidth partitioning window width 552 + * register 553 + */ 554 + #define MPAMCFG_MBW_WINWD_US_FRAC GENMASK(7, 0) 555 + #define MPAMCFG_MBW_WINWD_US_INT GENMASK(23, 8) 556 + 557 + /* MPAMCFG_PRI - MPAM priority partitioning configuration register */ 558 + #define MPAMCFG_PRI_INTPRI GENMASK(15, 0) 559 + #define MPAMCFG_PRI_DSPRI GENMASK(31, 16) 560 + 561 + /* 562 + * MPAMCFG_MBW_PROP - Memory bandwidth proportional stride partitioning 563 + * configuration register 564 + */ 565 + #define MPAMCFG_MBW_PROP_STRIDEM1 GENMASK(15, 0) 566 + #define MPAMCFG_MBW_PROP_EN BIT(31) 567 + 568 + /* 569 + * MPAMCFG_INTPARTID - MPAM internal partition narrowing configuration register 570 + */ 571 + #define MPAMCFG_INTPARTID_INTPARTID GENMASK(15, 0) 572 + #define MPAMCFG_INTPARTID_INTERNAL BIT(16) 573 + 574 + /* MSMON_CFG_MON_SEL - Memory system performance monitor selection register */ 575 + #define MSMON_CFG_MON_SEL_MON_SEL GENMASK(15, 0) 576 + #define MSMON_CFG_MON_SEL_RIS GENMASK(27, 24) 577 + 578 + /* MPAMF_ESR - MPAM Error Status Register */ 579 + #define MPAMF_ESR_PARTID_MON GENMASK(15, 0) 580 + #define MPAMF_ESR_PMG GENMASK(23, 16) 581 + #define MPAMF_ESR_ERRCODE GENMASK(27, 24) 582 + #define MPAMF_ESR_OVRWR BIT(31) 583 + #define MPAMF_ESR_RIS GENMASK(35, 32) 584 + 585 + /* MPAMF_ECR - MPAM Error Control Register */ 586 + #define MPAMF_ECR_INTEN BIT(0) 587 + 588 + /* Error conditions in accessing memory mapped registers */ 589 + #define MPAM_ERRCODE_NONE 0 590 + #define MPAM_ERRCODE_PARTID_SEL_RANGE 1 591 + #define MPAM_ERRCODE_REQ_PARTID_RANGE 2 592 + #define MPAM_ERRCODE_MSMONCFG_ID_RANGE 3 593 + #define MPAM_ERRCODE_REQ_PMG_RANGE 4 594 + #define MPAM_ERRCODE_MONITOR_RANGE 5 595 + #define MPAM_ERRCODE_INTPARTID_RANGE 6 596 + #define MPAM_ERRCODE_UNEXPECTED_INTERNAL 7 597 + #define MPAM_ERRCODE_UNDEFINED_RIS_PART_SEL 8 598 + #define MPAM_ERRCODE_RIS_NO_CONTROL 9 599 + #define MPAM_ERRCODE_UNDEFINED_RIS_MON_SEL 10 600 + #define MPAM_ERRCODE_RIS_NO_MONITOR 11 601 + 602 + /* 603 + * MSMON_CFG_CSU_CTL - Memory system performance monitor configure cache storage 604 + * usage monitor control register 605 + * MSMON_CFG_MBWU_CTL - Memory system performance monitor configure memory 606 + * bandwidth usage monitor control register 607 + */ 608 + #define MSMON_CFG_x_CTL_TYPE GENMASK(7, 0) 609 + #define MSMON_CFG_MBWU_CTL_OFLOW_STATUS_L BIT(15) 610 + #define MSMON_CFG_x_CTL_MATCH_PARTID BIT(16) 611 + #define MSMON_CFG_x_CTL_MATCH_PMG BIT(17) 612 + #define MSMON_CFG_MBWU_CTL_SCLEN BIT(19) 613 + #define MSMON_CFG_x_CTL_SUBTYPE GENMASK(22, 20) 614 + #define MSMON_CFG_x_CTL_OFLOW_FRZ BIT(24) 615 + #define MSMON_CFG_x_CTL_OFLOW_INTR BIT(25) 616 + #define MSMON_CFG_x_CTL_OFLOW_STATUS BIT(26) 617 + #define MSMON_CFG_x_CTL_CAPT_RESET BIT(27) 618 + #define MSMON_CFG_x_CTL_CAPT_EVNT GENMASK(30, 28) 619 + #define MSMON_CFG_x_CTL_EN BIT(31) 620 + 621 + #define MSMON_CFG_MBWU_CTL_TYPE_MBWU 0x42 622 + #define MSMON_CFG_CSU_CTL_TYPE_CSU 0x43 623 + 624 + /* 625 + * MSMON_CFG_CSU_FLT - Memory system performance monitor configure cache storage 626 + * usage monitor filter register 627 + * MSMON_CFG_MBWU_FLT - Memory system performance monitor configure memory 628 + * bandwidth usage monitor filter register 629 + */ 630 + #define MSMON_CFG_x_FLT_PARTID GENMASK(15, 0) 631 + #define MSMON_CFG_x_FLT_PMG GENMASK(23, 16) 632 + 633 + #define MSMON_CFG_MBWU_FLT_RWBW GENMASK(31, 30) 634 + #define MSMON_CFG_CSU_FLT_XCL BIT(31) 635 + 636 + /* 637 + * MSMON_CSU - Memory system performance monitor cache storage usage monitor 638 + * register 639 + * MSMON_CSU_CAPTURE - Memory system performance monitor cache storage usage 640 + * capture register 641 + * MSMON_MBWU - Memory system performance monitor memory bandwidth usage 642 + * monitor register 643 + * MSMON_MBWU_CAPTURE - Memory system performance monitor memory bandwidth usage 644 + * capture register 645 + */ 646 + #define MSMON___VALUE GENMASK(30, 0) 647 + #define MSMON___NRDY BIT(31) 648 + #define MSMON___L_NRDY BIT(63) 649 + #define MSMON___L_VALUE GENMASK(43, 0) 650 + #define MSMON___LWD_VALUE GENMASK(62, 0) 651 + 652 + /* 653 + * MSMON_CAPT_EVNT - Memory system performance monitoring capture event 654 + * generation register 655 + */ 656 + #define MSMON_CAPT_EVNT_NOW BIT(0) 657 + 658 + #endif /* MPAM_INTERNAL_H */
+389
drivers/resctrl/test_mpam_devices.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (C) 2025 Arm Ltd. 3 + /* This file is intended to be included into mpam_devices.c */ 4 + 5 + #include <kunit/test.h> 6 + 7 + /* 8 + * This test catches fields that aren't being sanitised - but can't tell you 9 + * which one... 10 + */ 11 + static void test__props_mismatch(struct kunit *test) 12 + { 13 + struct mpam_props parent = { 0 }; 14 + struct mpam_props child; 15 + 16 + memset(&child, 0xff, sizeof(child)); 17 + __props_mismatch(&parent, &child, false); 18 + 19 + memset(&child, 0, sizeof(child)); 20 + KUNIT_EXPECT_EQ(test, memcmp(&parent, &child, sizeof(child)), 0); 21 + 22 + memset(&child, 0xff, sizeof(child)); 23 + __props_mismatch(&parent, &child, true); 24 + 25 + KUNIT_EXPECT_EQ(test, memcmp(&parent, &child, sizeof(child)), 0); 26 + } 27 + 28 + static struct list_head fake_classes_list; 29 + static struct mpam_class fake_class = { 0 }; 30 + static struct mpam_component fake_comp1 = { 0 }; 31 + static struct mpam_component fake_comp2 = { 0 }; 32 + static struct mpam_vmsc fake_vmsc1 = { 0 }; 33 + static struct mpam_vmsc fake_vmsc2 = { 0 }; 34 + static struct mpam_msc fake_msc1 = { 0 }; 35 + static struct mpam_msc fake_msc2 = { 0 }; 36 + static struct mpam_msc_ris fake_ris1 = { 0 }; 37 + static struct mpam_msc_ris fake_ris2 = { 0 }; 38 + static struct platform_device fake_pdev = { 0 }; 39 + 40 + static inline void reset_fake_hierarchy(void) 41 + { 42 + INIT_LIST_HEAD(&fake_classes_list); 43 + 44 + memset(&fake_class, 0, sizeof(fake_class)); 45 + fake_class.level = 3; 46 + fake_class.type = MPAM_CLASS_CACHE; 47 + INIT_LIST_HEAD_RCU(&fake_class.components); 48 + INIT_LIST_HEAD(&fake_class.classes_list); 49 + 50 + memset(&fake_comp1, 0, sizeof(fake_comp1)); 51 + memset(&fake_comp2, 0, sizeof(fake_comp2)); 52 + fake_comp1.comp_id = 1; 53 + fake_comp2.comp_id = 2; 54 + INIT_LIST_HEAD(&fake_comp1.vmsc); 55 + INIT_LIST_HEAD(&fake_comp1.class_list); 56 + INIT_LIST_HEAD(&fake_comp2.vmsc); 57 + INIT_LIST_HEAD(&fake_comp2.class_list); 58 + 59 + memset(&fake_vmsc1, 0, sizeof(fake_vmsc1)); 60 + memset(&fake_vmsc2, 0, sizeof(fake_vmsc2)); 61 + INIT_LIST_HEAD(&fake_vmsc1.ris); 62 + INIT_LIST_HEAD(&fake_vmsc1.comp_list); 63 + fake_vmsc1.msc = &fake_msc1; 64 + INIT_LIST_HEAD(&fake_vmsc2.ris); 65 + INIT_LIST_HEAD(&fake_vmsc2.comp_list); 66 + fake_vmsc2.msc = &fake_msc2; 67 + 68 + memset(&fake_ris1, 0, sizeof(fake_ris1)); 69 + memset(&fake_ris2, 0, sizeof(fake_ris2)); 70 + fake_ris1.ris_idx = 1; 71 + INIT_LIST_HEAD(&fake_ris1.msc_list); 72 + fake_ris2.ris_idx = 2; 73 + INIT_LIST_HEAD(&fake_ris2.msc_list); 74 + 75 + fake_msc1.pdev = &fake_pdev; 76 + fake_msc2.pdev = &fake_pdev; 77 + 78 + list_add(&fake_class.classes_list, &fake_classes_list); 79 + } 80 + 81 + static void test_mpam_enable_merge_features(struct kunit *test) 82 + { 83 + reset_fake_hierarchy(); 84 + 85 + mutex_lock(&mpam_list_lock); 86 + 87 + /* One Class+Comp, two RIS in one vMSC with common features */ 88 + fake_comp1.class = &fake_class; 89 + list_add(&fake_comp1.class_list, &fake_class.components); 90 + fake_comp2.class = NULL; 91 + fake_vmsc1.comp = &fake_comp1; 92 + list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc); 93 + fake_vmsc2.comp = NULL; 94 + fake_ris1.vmsc = &fake_vmsc1; 95 + list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris); 96 + fake_ris2.vmsc = &fake_vmsc1; 97 + list_add(&fake_ris2.vmsc_list, &fake_vmsc1.ris); 98 + 99 + mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props); 100 + mpam_set_feature(mpam_feat_cpor_part, &fake_ris2.props); 101 + fake_ris1.props.cpbm_wd = 4; 102 + fake_ris2.props.cpbm_wd = 4; 103 + 104 + mpam_enable_merge_features(&fake_classes_list); 105 + 106 + KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props)); 107 + KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 4); 108 + 109 + reset_fake_hierarchy(); 110 + 111 + /* One Class+Comp, two RIS in one vMSC with non-overlapping features */ 112 + fake_comp1.class = &fake_class; 113 + list_add(&fake_comp1.class_list, &fake_class.components); 114 + fake_comp2.class = NULL; 115 + fake_vmsc1.comp = &fake_comp1; 116 + list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc); 117 + fake_vmsc2.comp = NULL; 118 + fake_ris1.vmsc = &fake_vmsc1; 119 + list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris); 120 + fake_ris2.vmsc = &fake_vmsc1; 121 + list_add(&fake_ris2.vmsc_list, &fake_vmsc1.ris); 122 + 123 + mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props); 124 + mpam_set_feature(mpam_feat_cmax_cmin, &fake_ris2.props); 125 + fake_ris1.props.cpbm_wd = 4; 126 + fake_ris2.props.cmax_wd = 4; 127 + 128 + mpam_enable_merge_features(&fake_classes_list); 129 + 130 + /* Multiple RIS within one MSC controlling the same resource can be mismatched */ 131 + KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props)); 132 + KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cmax_cmin, &fake_class.props)); 133 + KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cmax_cmin, &fake_vmsc1.props)); 134 + KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 4); 135 + KUNIT_EXPECT_EQ(test, fake_vmsc1.props.cmax_wd, 4); 136 + KUNIT_EXPECT_EQ(test, fake_class.props.cmax_wd, 4); 137 + 138 + reset_fake_hierarchy(); 139 + 140 + /* One Class+Comp, two MSC with overlapping features */ 141 + fake_comp1.class = &fake_class; 142 + list_add(&fake_comp1.class_list, &fake_class.components); 143 + fake_comp2.class = NULL; 144 + fake_vmsc1.comp = &fake_comp1; 145 + list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc); 146 + fake_vmsc2.comp = &fake_comp1; 147 + list_add(&fake_vmsc2.comp_list, &fake_comp1.vmsc); 148 + fake_ris1.vmsc = &fake_vmsc1; 149 + list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris); 150 + fake_ris2.vmsc = &fake_vmsc2; 151 + list_add(&fake_ris2.vmsc_list, &fake_vmsc2.ris); 152 + 153 + mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props); 154 + mpam_set_feature(mpam_feat_cpor_part, &fake_ris2.props); 155 + fake_ris1.props.cpbm_wd = 4; 156 + fake_ris2.props.cpbm_wd = 4; 157 + 158 + mpam_enable_merge_features(&fake_classes_list); 159 + 160 + KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props)); 161 + KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 4); 162 + 163 + reset_fake_hierarchy(); 164 + 165 + /* One Class+Comp, two MSC with non-overlapping features */ 166 + fake_comp1.class = &fake_class; 167 + list_add(&fake_comp1.class_list, &fake_class.components); 168 + fake_comp2.class = NULL; 169 + fake_vmsc1.comp = &fake_comp1; 170 + list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc); 171 + fake_vmsc2.comp = &fake_comp1; 172 + list_add(&fake_vmsc2.comp_list, &fake_comp1.vmsc); 173 + fake_ris1.vmsc = &fake_vmsc1; 174 + list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris); 175 + fake_ris2.vmsc = &fake_vmsc2; 176 + list_add(&fake_ris2.vmsc_list, &fake_vmsc2.ris); 177 + 178 + mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props); 179 + mpam_set_feature(mpam_feat_cmax_cmin, &fake_ris2.props); 180 + fake_ris1.props.cpbm_wd = 4; 181 + fake_ris2.props.cmax_wd = 4; 182 + 183 + mpam_enable_merge_features(&fake_classes_list); 184 + 185 + /* 186 + * Multiple RIS in different MSC can't control the same resource, 187 + * mismatched features can not be supported. 188 + */ 189 + KUNIT_EXPECT_FALSE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props)); 190 + KUNIT_EXPECT_FALSE(test, mpam_has_feature(mpam_feat_cmax_cmin, &fake_class.props)); 191 + KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 0); 192 + KUNIT_EXPECT_EQ(test, fake_class.props.cmax_wd, 0); 193 + 194 + reset_fake_hierarchy(); 195 + 196 + /* One Class+Comp, two MSC with incompatible overlapping features */ 197 + fake_comp1.class = &fake_class; 198 + list_add(&fake_comp1.class_list, &fake_class.components); 199 + fake_comp2.class = NULL; 200 + fake_vmsc1.comp = &fake_comp1; 201 + list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc); 202 + fake_vmsc2.comp = &fake_comp1; 203 + list_add(&fake_vmsc2.comp_list, &fake_comp1.vmsc); 204 + fake_ris1.vmsc = &fake_vmsc1; 205 + list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris); 206 + fake_ris2.vmsc = &fake_vmsc2; 207 + list_add(&fake_ris2.vmsc_list, &fake_vmsc2.ris); 208 + 209 + mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props); 210 + mpam_set_feature(mpam_feat_cpor_part, &fake_ris2.props); 211 + mpam_set_feature(mpam_feat_mbw_part, &fake_ris1.props); 212 + mpam_set_feature(mpam_feat_mbw_part, &fake_ris2.props); 213 + fake_ris1.props.cpbm_wd = 5; 214 + fake_ris2.props.cpbm_wd = 3; 215 + fake_ris1.props.mbw_pbm_bits = 5; 216 + fake_ris2.props.mbw_pbm_bits = 3; 217 + 218 + mpam_enable_merge_features(&fake_classes_list); 219 + 220 + /* 221 + * Multiple RIS in different MSC can't control the same resource, 222 + * mismatched features can not be supported. 223 + */ 224 + KUNIT_EXPECT_FALSE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props)); 225 + KUNIT_EXPECT_FALSE(test, mpam_has_feature(mpam_feat_mbw_part, &fake_class.props)); 226 + KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 0); 227 + KUNIT_EXPECT_EQ(test, fake_class.props.mbw_pbm_bits, 0); 228 + 229 + reset_fake_hierarchy(); 230 + 231 + /* One Class+Comp, two MSC with overlapping features that need tweaking */ 232 + fake_comp1.class = &fake_class; 233 + list_add(&fake_comp1.class_list, &fake_class.components); 234 + fake_comp2.class = NULL; 235 + fake_vmsc1.comp = &fake_comp1; 236 + list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc); 237 + fake_vmsc2.comp = &fake_comp1; 238 + list_add(&fake_vmsc2.comp_list, &fake_comp1.vmsc); 239 + fake_ris1.vmsc = &fake_vmsc1; 240 + list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris); 241 + fake_ris2.vmsc = &fake_vmsc2; 242 + list_add(&fake_ris2.vmsc_list, &fake_vmsc2.ris); 243 + 244 + mpam_set_feature(mpam_feat_mbw_min, &fake_ris1.props); 245 + mpam_set_feature(mpam_feat_mbw_min, &fake_ris2.props); 246 + mpam_set_feature(mpam_feat_cmax_cmax, &fake_ris1.props); 247 + mpam_set_feature(mpam_feat_cmax_cmax, &fake_ris2.props); 248 + fake_ris1.props.bwa_wd = 5; 249 + fake_ris2.props.bwa_wd = 3; 250 + fake_ris1.props.cmax_wd = 5; 251 + fake_ris2.props.cmax_wd = 3; 252 + 253 + mpam_enable_merge_features(&fake_classes_list); 254 + 255 + /* 256 + * RIS with different control properties need to be sanitised so the 257 + * class has the common set of properties. 258 + */ 259 + KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_mbw_min, &fake_class.props)); 260 + KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cmax_cmax, &fake_class.props)); 261 + KUNIT_EXPECT_EQ(test, fake_class.props.bwa_wd, 3); 262 + KUNIT_EXPECT_EQ(test, fake_class.props.cmax_wd, 3); 263 + 264 + reset_fake_hierarchy(); 265 + 266 + /* One Class Two Comp with overlapping features */ 267 + fake_comp1.class = &fake_class; 268 + list_add(&fake_comp1.class_list, &fake_class.components); 269 + fake_comp2.class = &fake_class; 270 + list_add(&fake_comp2.class_list, &fake_class.components); 271 + fake_vmsc1.comp = &fake_comp1; 272 + list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc); 273 + fake_vmsc2.comp = &fake_comp2; 274 + list_add(&fake_vmsc2.comp_list, &fake_comp2.vmsc); 275 + fake_ris1.vmsc = &fake_vmsc1; 276 + list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris); 277 + fake_ris2.vmsc = &fake_vmsc2; 278 + list_add(&fake_ris2.vmsc_list, &fake_vmsc2.ris); 279 + 280 + mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props); 281 + mpam_set_feature(mpam_feat_cpor_part, &fake_ris2.props); 282 + fake_ris1.props.cpbm_wd = 4; 283 + fake_ris2.props.cpbm_wd = 4; 284 + 285 + mpam_enable_merge_features(&fake_classes_list); 286 + 287 + KUNIT_EXPECT_TRUE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props)); 288 + KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 4); 289 + 290 + reset_fake_hierarchy(); 291 + 292 + /* One Class Two Comp with non-overlapping features */ 293 + fake_comp1.class = &fake_class; 294 + list_add(&fake_comp1.class_list, &fake_class.components); 295 + fake_comp2.class = &fake_class; 296 + list_add(&fake_comp2.class_list, &fake_class.components); 297 + fake_vmsc1.comp = &fake_comp1; 298 + list_add(&fake_vmsc1.comp_list, &fake_comp1.vmsc); 299 + fake_vmsc2.comp = &fake_comp2; 300 + list_add(&fake_vmsc2.comp_list, &fake_comp2.vmsc); 301 + fake_ris1.vmsc = &fake_vmsc1; 302 + list_add(&fake_ris1.vmsc_list, &fake_vmsc1.ris); 303 + fake_ris2.vmsc = &fake_vmsc2; 304 + list_add(&fake_ris2.vmsc_list, &fake_vmsc2.ris); 305 + 306 + mpam_set_feature(mpam_feat_cpor_part, &fake_ris1.props); 307 + mpam_set_feature(mpam_feat_cmax_cmin, &fake_ris2.props); 308 + fake_ris1.props.cpbm_wd = 4; 309 + fake_ris2.props.cmax_wd = 4; 310 + 311 + mpam_enable_merge_features(&fake_classes_list); 312 + 313 + /* 314 + * Multiple components can't control the same resource, mismatched features can 315 + * not be supported. 316 + */ 317 + KUNIT_EXPECT_FALSE(test, mpam_has_feature(mpam_feat_cpor_part, &fake_class.props)); 318 + KUNIT_EXPECT_FALSE(test, mpam_has_feature(mpam_feat_cmax_cmin, &fake_class.props)); 319 + KUNIT_EXPECT_EQ(test, fake_class.props.cpbm_wd, 0); 320 + KUNIT_EXPECT_EQ(test, fake_class.props.cmax_wd, 0); 321 + 322 + mutex_unlock(&mpam_list_lock); 323 + } 324 + 325 + static void test_mpam_reset_msc_bitmap(struct kunit *test) 326 + { 327 + char __iomem *buf = kunit_kzalloc(test, SZ_16K, GFP_KERNEL); 328 + struct mpam_msc fake_msc = {}; 329 + u32 *test_result; 330 + 331 + if (!buf) 332 + return; 333 + 334 + fake_msc.mapped_hwpage = buf; 335 + fake_msc.mapped_hwpage_sz = SZ_16K; 336 + cpumask_copy(&fake_msc.accessibility, cpu_possible_mask); 337 + 338 + /* Satisfy lockdep checks */ 339 + mutex_init(&fake_msc.part_sel_lock); 340 + mutex_lock(&fake_msc.part_sel_lock); 341 + 342 + test_result = (u32 *)(buf + MPAMCFG_CPBM); 343 + 344 + mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 0); 345 + KUNIT_EXPECT_EQ(test, test_result[0], 0); 346 + KUNIT_EXPECT_EQ(test, test_result[1], 0); 347 + test_result[0] = 0; 348 + test_result[1] = 0; 349 + 350 + mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 1); 351 + KUNIT_EXPECT_EQ(test, test_result[0], 1); 352 + KUNIT_EXPECT_EQ(test, test_result[1], 0); 353 + test_result[0] = 0; 354 + test_result[1] = 0; 355 + 356 + mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 16); 357 + KUNIT_EXPECT_EQ(test, test_result[0], 0xffff); 358 + KUNIT_EXPECT_EQ(test, test_result[1], 0); 359 + test_result[0] = 0; 360 + test_result[1] = 0; 361 + 362 + mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 32); 363 + KUNIT_EXPECT_EQ(test, test_result[0], 0xffffffff); 364 + KUNIT_EXPECT_EQ(test, test_result[1], 0); 365 + test_result[0] = 0; 366 + test_result[1] = 0; 367 + 368 + mpam_reset_msc_bitmap(&fake_msc, MPAMCFG_CPBM, 33); 369 + KUNIT_EXPECT_EQ(test, test_result[0], 0xffffffff); 370 + KUNIT_EXPECT_EQ(test, test_result[1], 1); 371 + test_result[0] = 0; 372 + test_result[1] = 0; 373 + 374 + mutex_unlock(&fake_msc.part_sel_lock); 375 + } 376 + 377 + static struct kunit_case mpam_devices_test_cases[] = { 378 + KUNIT_CASE(test_mpam_reset_msc_bitmap), 379 + KUNIT_CASE(test_mpam_enable_merge_features), 380 + KUNIT_CASE(test__props_mismatch), 381 + {} 382 + }; 383 + 384 + static struct kunit_suite mpam_devices_test_suite = { 385 + .name = "mpam_devices_test_suite", 386 + .test_cases = mpam_devices_test_cases, 387 + }; 388 + 389 + kunit_test_suites(&mpam_devices_test_suite);
+26 -1
include/linux/acpi.h
··· 8 8 #ifndef _LINUX_ACPI_H 9 9 #define _LINUX_ACPI_H 10 10 11 + #include <linux/cleanup.h> 11 12 #include <linux/errno.h> 12 13 #include <linux/ioport.h> /* for struct resource */ 13 14 #include <linux/resource_ext.h> ··· 221 220 void acpi_reserve_initial_tables (void); 222 221 void acpi_table_init_complete (void); 223 222 int acpi_table_init (void); 223 + 224 + static inline struct acpi_table_header *acpi_get_table_pointer(char *signature, u32 instance) 225 + { 226 + struct acpi_table_header *table; 227 + int status = acpi_get_table(signature, instance, &table); 228 + 229 + if (ACPI_FAILURE(status)) 230 + return ERR_PTR(-ENOENT); 231 + return table; 232 + } 233 + DEFINE_FREE(acpi_put_table, struct acpi_table_header *, if (!IS_ERR_OR_NULL(_T)) acpi_put_table(_T)) 224 234 225 235 int acpi_table_parse(char *id, acpi_tbl_table_handler handler); 226 236 int __init_or_acpilib acpi_table_parse_entries(char *id, ··· 767 755 int acpi_gtdt_init(struct acpi_table_header *table, int *platform_timer_count); 768 756 int acpi_gtdt_map_ppi(int type); 769 757 bool acpi_gtdt_c3stop(int type); 770 - int acpi_arch_timer_mem_init(struct arch_timer_mem *timer_mem, int *timer_count); 771 758 #endif 772 759 773 760 #ifndef ACPI_HAVE_ARCH_SET_ROOT_POINTER ··· 1559 1548 int find_acpi_cpu_topology_cluster(unsigned int cpu); 1560 1549 int find_acpi_cpu_topology_package(unsigned int cpu); 1561 1550 int find_acpi_cpu_topology_hetero_id(unsigned int cpu); 1551 + void acpi_pptt_get_cpus_from_container(u32 acpi_cpu_id, cpumask_t *cpus); 1552 + int find_acpi_cache_level_from_id(u32 cache_id); 1553 + int acpi_pptt_get_cpumask_from_cache_id(u32 cache_id, cpumask_t *cpus); 1562 1554 #else 1563 1555 static inline int acpi_pptt_cpu_is_thread(unsigned int cpu) 1564 1556 { ··· 1582 1568 static inline int find_acpi_cpu_topology_hetero_id(unsigned int cpu) 1583 1569 { 1584 1570 return -EINVAL; 1571 + } 1572 + static inline void acpi_pptt_get_cpus_from_container(u32 acpi_cpu_id, 1573 + cpumask_t *cpus) { } 1574 + static inline int find_acpi_cache_level_from_id(u32 cache_id) 1575 + { 1576 + return -ENOENT; 1577 + } 1578 + static inline int acpi_pptt_get_cpumask_from_cache_id(u32 cache_id, 1579 + cpumask_t *cpus) 1580 + { 1581 + return -ENOENT; 1585 1582 } 1586 1583 #endif 1587 1584
+16 -1
include/linux/arch_topology.h
··· 89 89 void reset_cpu_topology(void); 90 90 int parse_acpi_topology(void); 91 91 void freq_inv_set_max_ratio(int cpu, u64 max_rate); 92 - #endif 92 + 93 + /* 94 + * Architectures like ARM64 don't have reliable architectural way to get SMT 95 + * information and depend on the firmware (ACPI/OF) report. Non-SMT core won't 96 + * initialize thread_id so we can use this to detect the SMT implementation. 97 + */ 98 + static inline bool topology_core_has_smt(int cpu) 99 + { 100 + return cpu_topology[cpu].thread_id != -1; 101 + } 102 + 103 + #else 104 + 105 + static inline bool topology_core_has_smt(int cpu) { return false; } 106 + 107 + #endif /* CONFIG_GENERIC_ARCH_TOPOLOGY */ 93 108 94 109 #endif /* _LINUX_ARCH_TOPOLOGY_H_ */
+66
include/linux/arm_mpam.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (C) 2025 Arm Ltd. */ 3 + 4 + #ifndef __LINUX_ARM_MPAM_H 5 + #define __LINUX_ARM_MPAM_H 6 + 7 + #include <linux/acpi.h> 8 + #include <linux/types.h> 9 + 10 + struct mpam_msc; 11 + 12 + enum mpam_msc_iface { 13 + MPAM_IFACE_MMIO, /* a real MPAM MSC */ 14 + MPAM_IFACE_PCC, /* a fake MPAM MSC */ 15 + }; 16 + 17 + enum mpam_class_types { 18 + MPAM_CLASS_CACHE, /* Caches, e.g. L2, L3 */ 19 + MPAM_CLASS_MEMORY, /* Main memory */ 20 + MPAM_CLASS_UNKNOWN, /* Everything else, e.g. SMMU */ 21 + }; 22 + 23 + #define MPAM_CLASS_ID_DEFAULT 255 24 + 25 + #ifdef CONFIG_ACPI_MPAM 26 + int acpi_mpam_parse_resources(struct mpam_msc *msc, 27 + struct acpi_mpam_msc_node *tbl_msc); 28 + 29 + int acpi_mpam_count_msc(void); 30 + #else 31 + static inline int acpi_mpam_parse_resources(struct mpam_msc *msc, 32 + struct acpi_mpam_msc_node *tbl_msc) 33 + { 34 + return -EINVAL; 35 + } 36 + 37 + static inline int acpi_mpam_count_msc(void) { return -EINVAL; } 38 + #endif 39 + 40 + #ifdef CONFIG_ARM64_MPAM_DRIVER 41 + int mpam_ris_create(struct mpam_msc *msc, u8 ris_idx, 42 + enum mpam_class_types type, u8 class_id, int component_id); 43 + #else 44 + static inline int mpam_ris_create(struct mpam_msc *msc, u8 ris_idx, 45 + enum mpam_class_types type, u8 class_id, 46 + int component_id) 47 + { 48 + return -EINVAL; 49 + } 50 + #endif 51 + 52 + /** 53 + * mpam_register_requestor() - Register a requestor with the MPAM driver 54 + * @partid_max: The maximum PARTID value the requestor can generate. 55 + * @pmg_max: The maximum PMG value the requestor can generate. 56 + * 57 + * Registers a requestor with the MPAM driver to ensure the chosen system-wide 58 + * minimum PARTID and PMG values will allow the requestors features to be used. 59 + * 60 + * Returns an error if the registration is too late, and a larger PARTID/PMG 61 + * value has been advertised to user-space. In this case the requestor should 62 + * not use its MPAM features. Returns 0 on success. 63 + */ 64 + int mpam_register_requestor(u16 partid_max, u8 pmg_max); 65 + 66 + #endif /* __LINUX_ARM_MPAM_H */
+2
include/linux/efi.h
··· 1126 1126 extern void efi_call_virt_check_flags(unsigned long flags, const void *caller); 1127 1127 extern unsigned long efi_call_virt_save_flags(void); 1128 1128 1129 + void efi_runtime_assert_lock_held(void); 1130 + 1129 1131 enum efi_secureboot_mode { 1130 1132 efi_secureboot_mode_unset, 1131 1133 efi_secureboot_mode_unknown,
+1 -1
include/linux/huge_mm.h
··· 11 11 int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm, 12 12 pmd_t *dst_pmd, pmd_t *src_pmd, unsigned long addr, 13 13 struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma); 14 - void huge_pmd_set_accessed(struct vm_fault *vmf); 14 + bool huge_pmd_set_accessed(struct vm_fault *vmf); 15 15 int copy_huge_pud(struct mm_struct *dst_mm, struct mm_struct *src_mm, 16 16 pud_t *dst_pud, pud_t *src_pud, unsigned long addr, 17 17 struct vm_area_struct *vma);
+1
include/linux/perf/arm_pmu.h
··· 119 119 120 120 /* PMUv3 only */ 121 121 int pmuver; 122 + bool has_smt; 122 123 u64 reg_pmmir; 123 124 u64 reg_brbidr; 124 125 #define ARMV8_PMUV3_MAX_COMMON_EVENTS 0x40
+4
include/linux/pgtable.h
··· 1232 1232 #define flush_tlb_fix_spurious_fault(vma, address, ptep) flush_tlb_page(vma, address) 1233 1233 #endif 1234 1234 1235 + #ifndef flush_tlb_fix_spurious_fault_pmd 1236 + #define flush_tlb_fix_spurious_fault_pmd(vma, address, pmdp) do { } while (0) 1237 + #endif 1238 + 1235 1239 /* 1236 1240 * When walking page tables, get the address of the next boundary, 1237 1241 * or the end address of the range if that comes earlier. Although no
+1
include/linux/platform_device.h
··· 234 234 extern int platform_device_add(struct platform_device *pdev); 235 235 extern void platform_device_del(struct platform_device *pdev); 236 236 extern void platform_device_put(struct platform_device *pdev); 237 + DEFINE_FREE(platform_device_put, struct platform_device *, if (_T) platform_device_put(_T)) 237 238 238 239 struct platform_driver { 239 240 int (*probe)(struct platform_device *);
+2
include/uapi/linux/perf_event.h
··· 382 382 #define PERF_ATTR_SIZE_VER6 120 /* Add: aux_sample_size */ 383 383 #define PERF_ATTR_SIZE_VER7 128 /* Add: sig_data */ 384 384 #define PERF_ATTR_SIZE_VER8 136 /* Add: config3 */ 385 + #define PERF_ATTR_SIZE_VER9 144 /* add: config4 */ 385 386 386 387 /* 387 388 * 'struct perf_event_attr' contains various attributes that define ··· 546 545 __u64 sig_data; 547 546 548 547 __u64 config3; /* extension of config2 */ 548 + __u64 config4; /* extension of config3 */ 549 549 }; 550 550 551 551 /*
+21 -12
mm/huge_memory.c
··· 1642 1642 EXPORT_SYMBOL_GPL(vmf_insert_folio_pud); 1643 1643 #endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */ 1644 1644 1645 - void touch_pmd(struct vm_area_struct *vma, unsigned long addr, 1645 + /** 1646 + * touch_pmd - Mark page table pmd entry as accessed and dirty (for write) 1647 + * @vma: The VMA covering @addr 1648 + * @addr: The virtual address 1649 + * @pmd: pmd pointer into the page table mapping @addr 1650 + * @write: Whether it's a write access 1651 + * 1652 + * Return: whether the pmd entry is changed 1653 + */ 1654 + bool touch_pmd(struct vm_area_struct *vma, unsigned long addr, 1646 1655 pmd_t *pmd, bool write) 1647 1656 { 1648 - pmd_t _pmd; 1657 + pmd_t entry; 1649 1658 1650 - _pmd = pmd_mkyoung(*pmd); 1659 + entry = pmd_mkyoung(*pmd); 1651 1660 if (write) 1652 - _pmd = pmd_mkdirty(_pmd); 1661 + entry = pmd_mkdirty(entry); 1653 1662 if (pmdp_set_access_flags(vma, addr & HPAGE_PMD_MASK, 1654 - pmd, _pmd, write)) 1663 + pmd, entry, write)) { 1655 1664 update_mmu_cache_pmd(vma, addr, pmd); 1665 + return true; 1666 + } 1667 + 1668 + return false; 1656 1669 } 1657 1670 1658 1671 int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm, ··· 1855 1842 } 1856 1843 #endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */ 1857 1844 1858 - void huge_pmd_set_accessed(struct vm_fault *vmf) 1845 + bool huge_pmd_set_accessed(struct vm_fault *vmf) 1859 1846 { 1860 1847 bool write = vmf->flags & FAULT_FLAG_WRITE; 1861 1848 1862 - vmf->ptl = pmd_lock(vmf->vma->vm_mm, vmf->pmd); 1863 1849 if (unlikely(!pmd_same(*vmf->pmd, vmf->orig_pmd))) 1864 - goto unlock; 1850 + return false; 1865 1851 1866 - touch_pmd(vmf->vma, vmf->address, vmf->pmd, write); 1867 - 1868 - unlock: 1869 - spin_unlock(vmf->ptl); 1852 + return touch_pmd(vmf->vma, vmf->address, vmf->pmd, write); 1870 1853 } 1871 1854 1872 1855 static vm_fault_t do_huge_zero_wp_pmd(struct vm_fault *vmf)
+1 -1
mm/internal.h
··· 1402 1402 */ 1403 1403 void touch_pud(struct vm_area_struct *vma, unsigned long addr, 1404 1404 pud_t *pud, bool write); 1405 - void touch_pmd(struct vm_area_struct *vma, unsigned long addr, 1405 + bool touch_pmd(struct vm_area_struct *vma, unsigned long addr, 1406 1406 pmd_t *pmd, bool write); 1407 1407 1408 1408 /*
+46 -16
mm/memory.c
··· 6134 6134 } 6135 6135 6136 6136 /* 6137 + * The page faults may be spurious because of the racy access to the 6138 + * page table. For example, a non-populated virtual page is accessed 6139 + * on 2 CPUs simultaneously, thus the page faults are triggered on 6140 + * both CPUs. However, it's possible that one CPU (say CPU A) cannot 6141 + * find the reason for the page fault if the other CPU (say CPU B) has 6142 + * changed the page table before the PTE is checked on CPU A. Most of 6143 + * the time, the spurious page faults can be ignored safely. However, 6144 + * if the page fault is for the write access, it's possible that a 6145 + * stale read-only TLB entry exists in the local CPU and needs to be 6146 + * flushed on some architectures. This is called the spurious page 6147 + * fault fixing. 6148 + * 6149 + * Note: flush_tlb_fix_spurious_fault() is defined as flush_tlb_page() 6150 + * by default and used as such on most architectures, while 6151 + * flush_tlb_fix_spurious_fault_pmd() is defined as NOP by default and 6152 + * used as such on most architectures. 6153 + */ 6154 + static void fix_spurious_fault(struct vm_fault *vmf, 6155 + enum pgtable_level ptlevel) 6156 + { 6157 + /* Skip spurious TLB flush for retried page fault */ 6158 + if (vmf->flags & FAULT_FLAG_TRIED) 6159 + return; 6160 + /* 6161 + * This is needed only for protection faults but the arch code 6162 + * is not yet telling us if this is a protection fault or not. 6163 + * This still avoids useless tlb flushes for .text page faults 6164 + * with threads. 6165 + */ 6166 + if (vmf->flags & FAULT_FLAG_WRITE) { 6167 + if (ptlevel == PGTABLE_LEVEL_PTE) 6168 + flush_tlb_fix_spurious_fault(vmf->vma, vmf->address, 6169 + vmf->pte); 6170 + else 6171 + flush_tlb_fix_spurious_fault_pmd(vmf->vma, vmf->address, 6172 + vmf->pmd); 6173 + } 6174 + } 6175 + /* 6137 6176 * These routines also need to handle stuff like marking pages dirty 6138 6177 * and/or accessed for architectures that don't do it in hardware (most 6139 6178 * RISC architectures). The early dirtying is also good on the i386. ··· 6253 6214 } 6254 6215 entry = pte_mkyoung(entry); 6255 6216 if (ptep_set_access_flags(vmf->vma, vmf->address, vmf->pte, entry, 6256 - vmf->flags & FAULT_FLAG_WRITE)) { 6217 + vmf->flags & FAULT_FLAG_WRITE)) 6257 6218 update_mmu_cache_range(vmf, vmf->vma, vmf->address, 6258 6219 vmf->pte, 1); 6259 - } else { 6260 - /* Skip spurious TLB flush for retried page fault */ 6261 - if (vmf->flags & FAULT_FLAG_TRIED) 6262 - goto unlock; 6263 - /* 6264 - * This is needed only for protection faults but the arch code 6265 - * is not yet telling us if this is a protection fault or not. 6266 - * This still avoids useless tlb flushes for .text page faults 6267 - * with threads. 6268 - */ 6269 - if (vmf->flags & FAULT_FLAG_WRITE) 6270 - flush_tlb_fix_spurious_fault(vmf->vma, vmf->address, 6271 - vmf->pte); 6272 - } 6220 + else 6221 + fix_spurious_fault(vmf, PGTABLE_LEVEL_PTE); 6273 6222 unlock: 6274 6223 pte_unmap_unlock(vmf->pte, vmf->ptl); 6275 6224 return 0; ··· 6354 6327 if (!(ret & VM_FAULT_FALLBACK)) 6355 6328 return ret; 6356 6329 } else { 6357 - huge_pmd_set_accessed(&vmf); 6330 + vmf.ptl = pmd_lock(mm, vmf.pmd); 6331 + if (!huge_pmd_set_accessed(&vmf)) 6332 + fix_spurious_fault(&vmf, PGTABLE_LEVEL_PMD); 6333 + spin_unlock(vmf.ptl); 6358 6334 return 0; 6359 6335 } 6360 6336 }
+2 -2
tools/arch/arm64/include/asm/cputype.h
··· 245 245 #define MIDR_FUJITSU_ERRATUM_010001_MASK (~MIDR_CPU_VAR_REV(1, 0)) 246 246 #define TCR_CLEAR_FUJITSU_ERRATUM_010001 (TCR_NFD1 | TCR_NFD0) 247 247 248 - #ifndef __ASSEMBLY__ 248 + #ifndef __ASSEMBLER__ 249 249 250 250 #include <asm/sysreg.h> 251 251 ··· 338 338 { 339 339 return read_cpuid(CTR_EL0); 340 340 } 341 - #endif /* __ASSEMBLY__ */ 341 + #endif /* __ASSEMBLER__ */ 342 342 343 343 #endif
+2 -2
tools/arch/arm64/include/asm/esr.h
··· 385 385 #define ESR_ELx_MOPS_ISS_SRCREG(esr) (((esr) & (UL(0x1f) << 5)) >> 5) 386 386 #define ESR_ELx_MOPS_ISS_SIZEREG(esr) (((esr) & (UL(0x1f) << 0)) >> 0) 387 387 388 - #ifndef __ASSEMBLY__ 388 + #ifndef __ASSEMBLER__ 389 389 #include <asm/types.h> 390 390 391 391 static inline unsigned long esr_brk_comment(unsigned long esr) ··· 450 450 } 451 451 452 452 const char *esr_get_class_string(unsigned long esr); 453 - #endif /* __ASSEMBLY */ 453 + #endif /* __ASSEMBLER__ */ 454 454 455 455 #endif /* __ASM_ESR_H */
+3 -3
tools/arch/arm64/include/asm/gpr-num.h
··· 2 2 #ifndef __ASM_GPR_NUM_H 3 3 #define __ASM_GPR_NUM_H 4 4 5 - #ifdef __ASSEMBLY__ 5 + #ifdef __ASSEMBLER__ 6 6 7 7 .irp num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30 8 8 .equ .L__gpr_num_x\num, \num ··· 11 11 .equ .L__gpr_num_xzr, 31 12 12 .equ .L__gpr_num_wzr, 31 13 13 14 - #else /* __ASSEMBLY__ */ 14 + #else /* __ASSEMBLER__ */ 15 15 16 16 #define __DEFINE_ASM_GPR_NUMS \ 17 17 " .irp num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30\n" \ ··· 21 21 " .equ .L__gpr_num_xzr, 31\n" \ 22 22 " .equ .L__gpr_num_wzr, 31\n" 23 23 24 - #endif /* __ASSEMBLY__ */ 24 + #endif /* __ASSEMBLER__ */ 25 25 26 26 #endif /* __ASM_GPR_NUM_H */
+5 -7
tools/arch/arm64/include/asm/sysreg.h
··· 51 51 52 52 #ifndef CONFIG_BROKEN_GAS_INST 53 53 54 - #ifdef __ASSEMBLY__ 54 + #ifdef __ASSEMBLER__ 55 55 // The space separator is omitted so that __emit_inst(x) can be parsed as 56 56 // either an assembler directive or an assembler macro argument. 57 57 #define __emit_inst(x) .inst(x) ··· 70 70 (((x) >> 24) & 0x000000ff)) 71 71 #endif /* CONFIG_CPU_BIG_ENDIAN */ 72 72 73 - #ifdef __ASSEMBLY__ 73 + #ifdef __ASSEMBLER__ 74 74 #define __emit_inst(x) .long __INSTR_BSWAP(x) 75 - #else /* __ASSEMBLY__ */ 75 + #else /* __ASSEMBLER__ */ 76 76 #define __emit_inst(x) ".long " __stringify(__INSTR_BSWAP(x)) "\n\t" 77 - #endif /* __ASSEMBLY__ */ 77 + #endif /* __ASSEMBLER__ */ 78 78 79 79 #endif /* CONFIG_BROKEN_GAS_INST */ 80 80 ··· 1078 1078 #define GCS_CAP(x) ((((unsigned long)x) & GCS_CAP_ADDR_MASK) | \ 1079 1079 GCS_CAP_VALID_TOKEN) 1080 1080 1081 - #define ARM64_FEATURE_FIELD_BITS 4 1082 - 1083 - #ifdef __ASSEMBLY__ 1081 + #ifdef __ASSEMBLER__ 1084 1082 1085 1083 .macro mrs_s, rt, sreg 1086 1084 __emit_inst(0xd5200000|(\sreg)|(.L__gpr_num_\rt))
+1 -1
tools/arch/arm64/include/uapi/asm/kvm.h
··· 31 31 #define KVM_SPSR_FIQ 4 32 32 #define KVM_NR_SPSR 5 33 33 34 - #ifndef __ASSEMBLY__ 34 + #ifndef __ASSEMBLER__ 35 35 #include <linux/psci.h> 36 36 #include <linux/types.h> 37 37 #include <asm/ptrace.h>
+1 -4
tools/testing/selftests/arm64/fp/fp-ptrace.c
··· 1071 1071 1072 1072 static bool sve_write_fpsimd_supported(struct test_config *config) 1073 1073 { 1074 - if (!sve_supported()) 1074 + if (!sve_supported() && !sme_supported()) 1075 1075 return false; 1076 1076 1077 1077 if ((config->svcr_in & SVCR_ZA) != (config->svcr_expected & SVCR_ZA)) ··· 1230 1230 1231 1231 vl = vl_expected(config); 1232 1232 vq = __sve_vq_from_vl(vl); 1233 - 1234 - if (!vl) 1235 - return; 1236 1233 1237 1234 iov.iov_len = SVE_PT_SIZE(vq, SVE_PT_REGS_FPSIMD); 1238 1235 iov.iov_base = malloc(iov.iov_len);
+61
tools/testing/selftests/arm64/fp/sve-ptrace.c
··· 394 394 free(svebuf); 395 395 } 396 396 397 + /* Write the FPSIMD registers via the SVE regset when SVE is not supported */ 398 + static void ptrace_sve_fpsimd_no_sve(pid_t child) 399 + { 400 + void *svebuf; 401 + struct user_sve_header *sve; 402 + struct user_fpsimd_state *fpsimd, new_fpsimd; 403 + unsigned int i, j; 404 + unsigned char *p; 405 + int ret; 406 + 407 + svebuf = malloc(SVE_PT_SIZE(0, SVE_PT_REGS_FPSIMD)); 408 + if (!svebuf) { 409 + ksft_test_result_fail("Failed to allocate FPSIMD buffer\n"); 410 + return; 411 + } 412 + 413 + /* On a system without SVE the VL should be set to 0 */ 414 + memset(svebuf, 0, SVE_PT_SIZE(0, SVE_PT_REGS_FPSIMD)); 415 + sve = svebuf; 416 + sve->flags = SVE_PT_REGS_FPSIMD; 417 + sve->size = SVE_PT_SIZE(0, SVE_PT_REGS_FPSIMD); 418 + sve->vl = 0; 419 + 420 + /* Try to set a known FPSIMD state via PT_REGS_SVE */ 421 + fpsimd = (struct user_fpsimd_state *)((char *)sve + 422 + SVE_PT_FPSIMD_OFFSET); 423 + for (i = 0; i < 32; ++i) { 424 + p = (unsigned char *)&fpsimd->vregs[i]; 425 + 426 + for (j = 0; j < sizeof(fpsimd->vregs[i]); ++j) 427 + p[j] = j; 428 + } 429 + 430 + ret = set_sve(child, &vec_types[0], sve); 431 + ksft_test_result(ret == 0, "FPSIMD write via SVE\n"); 432 + if (ret) { 433 + ksft_test_result_skip("Verify FPSIMD write via SVE\n"); 434 + goto out; 435 + } 436 + 437 + /* Verify via the FPSIMD regset */ 438 + if (get_fpsimd(child, &new_fpsimd)) { 439 + ksft_test_result_skip("Verify FPSIMD write via SVE\n"); 440 + goto out; 441 + } 442 + ksft_test_result(memcmp(fpsimd, &new_fpsimd, sizeof(*fpsimd)) == 0, 443 + "Verify FPSIMD write via SVE\n"); 444 + 445 + out: 446 + free(svebuf); 447 + } 448 + 397 449 /* Validate attempting to set SVE data and read SVE data */ 398 450 static void ptrace_set_sve_get_sve_data(pid_t child, 399 451 const struct vec_type *type, ··· 876 824 vec_types[i].name, vl); 877 825 } 878 826 } 827 + } 828 + 829 + /* We support SVE writes of FPSMID format on SME only systems */ 830 + if (!(getauxval(AT_HWCAP) & HWCAP_SVE) && 831 + (getauxval(AT_HWCAP2) & HWCAP2_SME)) { 832 + ptrace_sve_fpsimd_no_sve(child); 833 + } else { 834 + ksft_test_result_skip("FPSIMD write via SVE\n"); 835 + ksft_test_result_skip("Verify FPSIMD write via SVE\n"); 879 836 } 880 837 881 838 ret = EXIT_SUCCESS;
+1 -1
tools/testing/selftests/arm64/fp/zt-test.S
··· 276 276 bl putdec 277 277 puts ", iteration=" 278 278 mov x0, x22 279 - bl putdec 279 + bl putdecn 280 280 puts "\tExpected [" 281 281 mov x0, x10 282 282 mov x1, x12
+7 -3
tools/testing/selftests/kvm/arm64/set_id_regs.c
··· 268 268 /* Return a safe value to a given ftr_bits an ftr value */ 269 269 uint64_t get_safe_value(const struct reg_ftr_bits *ftr_bits, uint64_t ftr) 270 270 { 271 - uint64_t ftr_max = GENMASK_ULL(ARM64_FEATURE_FIELD_BITS - 1, 0); 271 + uint64_t ftr_max = ftr_bits->mask >> ftr_bits->shift; 272 + 273 + TEST_ASSERT(ftr_max > 1, "This test doesn't support single bit features"); 272 274 273 275 if (ftr_bits->sign == FTR_UNSIGNED) { 274 276 switch (ftr_bits->type) { ··· 322 320 /* Return an invalid value to a given ftr_bits an ftr value */ 323 321 uint64_t get_invalid_value(const struct reg_ftr_bits *ftr_bits, uint64_t ftr) 324 322 { 325 - uint64_t ftr_max = GENMASK_ULL(ARM64_FEATURE_FIELD_BITS - 1, 0); 323 + uint64_t ftr_max = ftr_bits->mask >> ftr_bits->shift; 324 + 325 + TEST_ASSERT(ftr_max > 1, "This test doesn't support single bit features"); 326 326 327 327 if (ftr_bits->sign == FTR_UNSIGNED) { 328 328 switch (ftr_bits->type) { ··· 676 672 clidr = vcpu_get_reg(vcpu, KVM_ARM64_SYS_REG(SYS_CLIDR_EL1)); 677 673 678 674 /* find the first empty level in the cache hierarchy */ 679 - for (level = 1; level < 7; level++) { 675 + for (level = 1; level <= 7; level++) { 680 676 if (!CLIDR_CTYPE(clidr, level)) 681 677 break; 682 678 }