diff options
61 files changed, 1689 insertions, 260 deletions
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 20cc45602f45..638342d0a095 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt | |||
| @@ -4106,6 +4106,23 @@ | |||
| 4106 | expediting. Set to zero to disable automatic | 4106 | expediting. Set to zero to disable automatic |
| 4107 | expediting. | 4107 | expediting. |
| 4108 | 4108 | ||
| 4109 | ssbd= [ARM64,HW] | ||
| 4110 | Speculative Store Bypass Disable control | ||
| 4111 | |||
| 4112 | On CPUs that are vulnerable to the Speculative | ||
| 4113 | Store Bypass vulnerability and offer a | ||
| 4114 | firmware based mitigation, this parameter | ||
| 4115 | indicates how the mitigation should be used: | ||
| 4116 | |||
| 4117 | force-on: Unconditionally enable mitigation for | ||
| 4118 | for both kernel and userspace | ||
| 4119 | force-off: Unconditionally disable mitigation for | ||
| 4120 | for both kernel and userspace | ||
| 4121 | kernel: Always enable mitigation in the | ||
| 4122 | kernel, and offer a prctl interface | ||
| 4123 | to allow userspace to register its | ||
| 4124 | interest in being mitigated too. | ||
| 4125 | |||
| 4109 | stack_guard_gap= [MM] | 4126 | stack_guard_gap= [MM] |
| 4110 | override the default stack gap protection. The value | 4127 | override the default stack gap protection. The value |
| 4111 | is in page units and it defines how many pages prior | 4128 | is in page units and it defines how many pages prior |
diff --git a/arch/arm/common/mcpm_entry.c b/arch/arm/common/mcpm_entry.c index 2b913f17d50f..ad574d20415c 100644 --- a/arch/arm/common/mcpm_entry.c +++ b/arch/arm/common/mcpm_entry.c | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/export.h> | ||
| 12 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 13 | #include <linux/init.h> | 14 | #include <linux/init.h> |
| 14 | #include <linux/irqflags.h> | 15 | #include <linux/irqflags.h> |
| @@ -174,6 +175,7 @@ bool mcpm_is_available(void) | |||
| 174 | { | 175 | { |
| 175 | return (platform_ops) ? true : false; | 176 | return (platform_ops) ? true : false; |
| 176 | } | 177 | } |
| 178 | EXPORT_SYMBOL_GPL(mcpm_is_available); | ||
| 177 | 179 | ||
| 178 | /* | 180 | /* |
| 179 | * We can't use regular spinlocks. In the switcher case, it is possible | 181 | * We can't use regular spinlocks. In the switcher case, it is possible |
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 343fc9e6f78d..2d75e77bf7bb 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h | |||
| @@ -325,6 +325,18 @@ static inline bool kvm_arm_harden_branch_predictor(void) | |||
| 325 | } | 325 | } |
| 326 | } | 326 | } |
| 327 | 327 | ||
| 328 | #define KVM_SSBD_UNKNOWN -1 | ||
| 329 | #define KVM_SSBD_FORCE_DISABLE 0 | ||
| 330 | #define KVM_SSBD_KERNEL 1 | ||
| 331 | #define KVM_SSBD_FORCE_ENABLE 2 | ||
| 332 | #define KVM_SSBD_MITIGATED 3 | ||
| 333 | |||
| 334 | static inline int kvm_arm_have_ssbd(void) | ||
| 335 | { | ||
| 336 | /* No way to detect it yet, pretend it is not there. */ | ||
| 337 | return KVM_SSBD_UNKNOWN; | ||
| 338 | } | ||
| 339 | |||
| 328 | static inline void kvm_vcpu_load_sysregs(struct kvm_vcpu *vcpu) {} | 340 | static inline void kvm_vcpu_load_sysregs(struct kvm_vcpu *vcpu) {} |
| 329 | static inline void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu) {} | 341 | static inline void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu) {} |
| 330 | 342 | ||
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h index c94d291fd1a8..8553d68b7c8a 100644 --- a/arch/arm/include/asm/kvm_mmu.h +++ b/arch/arm/include/asm/kvm_mmu.h | |||
| @@ -356,6 +356,11 @@ static inline int kvm_map_vectors(void) | |||
| 356 | return 0; | 356 | return 0; |
| 357 | } | 357 | } |
| 358 | 358 | ||
| 359 | static inline int hyp_map_aux_data(void) | ||
| 360 | { | ||
| 361 | return 0; | ||
| 362 | } | ||
| 363 | |||
| 359 | #define kvm_phys_to_vttbr(addr) (addr) | 364 | #define kvm_phys_to_vttbr(addr) (addr) |
| 360 | 365 | ||
| 361 | #endif /* !__ASSEMBLY__ */ | 366 | #endif /* !__ASSEMBLY__ */ |
diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c index 1d7061a38922..be42c4f66a40 100644 --- a/arch/arm/kernel/perf_event_v6.c +++ b/arch/arm/kernel/perf_event_v6.c | |||
| @@ -303,12 +303,10 @@ static void armv6pmu_enable_event(struct perf_event *event) | |||
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | static irqreturn_t | 305 | static irqreturn_t |
| 306 | armv6pmu_handle_irq(int irq_num, | 306 | armv6pmu_handle_irq(struct arm_pmu *cpu_pmu) |
| 307 | void *dev) | ||
| 308 | { | 307 | { |
| 309 | unsigned long pmcr = armv6_pmcr_read(); | 308 | unsigned long pmcr = armv6_pmcr_read(); |
| 310 | struct perf_sample_data data; | 309 | struct perf_sample_data data; |
| 311 | struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev; | ||
| 312 | struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events); | 310 | struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events); |
| 313 | struct pt_regs *regs; | 311 | struct pt_regs *regs; |
| 314 | int idx; | 312 | int idx; |
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index 870b66c1e4ef..57f01e059f39 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c | |||
| @@ -946,11 +946,10 @@ static void armv7pmu_disable_event(struct perf_event *event) | |||
| 946 | raw_spin_unlock_irqrestore(&events->pmu_lock, flags); | 946 | raw_spin_unlock_irqrestore(&events->pmu_lock, flags); |
| 947 | } | 947 | } |
| 948 | 948 | ||
| 949 | static irqreturn_t armv7pmu_handle_irq(int irq_num, void *dev) | 949 | static irqreturn_t armv7pmu_handle_irq(struct arm_pmu *cpu_pmu) |
| 950 | { | 950 | { |
| 951 | u32 pmnc; | 951 | u32 pmnc; |
| 952 | struct perf_sample_data data; | 952 | struct perf_sample_data data; |
| 953 | struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev; | ||
| 954 | struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events); | 953 | struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events); |
| 955 | struct pt_regs *regs; | 954 | struct pt_regs *regs; |
| 956 | int idx; | 955 | int idx; |
diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c index fcf218da660e..88d1a76f5367 100644 --- a/arch/arm/kernel/perf_event_xscale.c +++ b/arch/arm/kernel/perf_event_xscale.c | |||
| @@ -142,11 +142,10 @@ xscale1_pmnc_counter_has_overflowed(unsigned long pmnc, | |||
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | static irqreturn_t | 144 | static irqreturn_t |
| 145 | xscale1pmu_handle_irq(int irq_num, void *dev) | 145 | xscale1pmu_handle_irq(struct arm_pmu *cpu_pmu) |
| 146 | { | 146 | { |
| 147 | unsigned long pmnc; | 147 | unsigned long pmnc; |
| 148 | struct perf_sample_data data; | 148 | struct perf_sample_data data; |
| 149 | struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev; | ||
| 150 | struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events); | 149 | struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events); |
| 151 | struct pt_regs *regs; | 150 | struct pt_regs *regs; |
| 152 | int idx; | 151 | int idx; |
| @@ -489,11 +488,10 @@ xscale2_pmnc_counter_has_overflowed(unsigned long of_flags, | |||
| 489 | } | 488 | } |
| 490 | 489 | ||
| 491 | static irqreturn_t | 490 | static irqreturn_t |
| 492 | xscale2pmu_handle_irq(int irq_num, void *dev) | 491 | xscale2pmu_handle_irq(struct arm_pmu *cpu_pmu) |
| 493 | { | 492 | { |
| 494 | unsigned long pmnc, of_flags; | 493 | unsigned long pmnc, of_flags; |
| 495 | struct perf_sample_data data; | 494 | struct perf_sample_data data; |
| 496 | struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev; | ||
| 497 | struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events); | 495 | struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events); |
| 498 | struct pt_regs *regs; | 496 | struct pt_regs *regs; |
| 499 | int idx; | 497 | int idx; |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 4759566a78cb..9795b59aa28a 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig | |||
| @@ -7,11 +7,13 @@ config ARM64 | |||
| 7 | select ACPI_REDUCED_HARDWARE_ONLY if ACPI | 7 | select ACPI_REDUCED_HARDWARE_ONLY if ACPI |
| 8 | select ACPI_MCFG if ACPI | 8 | select ACPI_MCFG if ACPI |
| 9 | select ACPI_SPCR_TABLE if ACPI | 9 | select ACPI_SPCR_TABLE if ACPI |
| 10 | select ACPI_PPTT if ACPI | ||
| 10 | select ARCH_CLOCKSOURCE_DATA | 11 | select ARCH_CLOCKSOURCE_DATA |
| 11 | select ARCH_HAS_DEBUG_VIRTUAL | 12 | select ARCH_HAS_DEBUG_VIRTUAL |
| 12 | select ARCH_HAS_DEVMEM_IS_ALLOWED | 13 | select ARCH_HAS_DEVMEM_IS_ALLOWED |
| 13 | select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI | 14 | select ARCH_HAS_ACPI_TABLE_UPGRADE if ACPI |
| 14 | select ARCH_HAS_ELF_RANDOMIZE | 15 | select ARCH_HAS_ELF_RANDOMIZE |
| 16 | select ARCH_HAS_FAST_MULTIPLIER | ||
| 15 | select ARCH_HAS_FORTIFY_SOURCE | 17 | select ARCH_HAS_FORTIFY_SOURCE |
| 16 | select ARCH_HAS_GCOV_PROFILE_ALL | 18 | select ARCH_HAS_GCOV_PROFILE_ALL |
| 17 | select ARCH_HAS_GIGANTIC_PAGE if (MEMORY_ISOLATION && COMPACTION) || CMA | 19 | select ARCH_HAS_GIGANTIC_PAGE if (MEMORY_ISOLATION && COMPACTION) || CMA |
| @@ -923,6 +925,15 @@ config HARDEN_EL2_VECTORS | |||
| 923 | 925 | ||
| 924 | If unsure, say Y. | 926 | If unsure, say Y. |
| 925 | 927 | ||
| 928 | config ARM64_SSBD | ||
| 929 | bool "Speculative Store Bypass Disable" if EXPERT | ||
| 930 | default y | ||
| 931 | help | ||
| 932 | This enables mitigation of the bypassing of previous stores | ||
| 933 | by speculative loads. | ||
| 934 | |||
| 935 | If unsure, say Y. | ||
| 936 | |||
| 926 | menuconfig ARMV8_DEPRECATED | 937 | menuconfig ARMV8_DEPRECATED |
| 927 | bool "Emulate deprecated/obsolete ARMv8 instructions" | 938 | bool "Emulate deprecated/obsolete ARMv8 instructions" |
| 928 | depends on COMPAT | 939 | depends on COMPAT |
| @@ -1034,6 +1045,7 @@ config ARM64_PAN | |||
| 1034 | 1045 | ||
| 1035 | config ARM64_LSE_ATOMICS | 1046 | config ARM64_LSE_ATOMICS |
| 1036 | bool "Atomic instructions" | 1047 | bool "Atomic instructions" |
| 1048 | default y | ||
| 1037 | help | 1049 | help |
| 1038 | As part of the Large System Extensions, ARMv8.1 introduces new | 1050 | As part of the Large System Extensions, ARMv8.1 introduces new |
| 1039 | atomic instructions that are designed specifically to scale in | 1051 | atomic instructions that are designed specifically to scale in |
| @@ -1042,7 +1054,8 @@ config ARM64_LSE_ATOMICS | |||
| 1042 | Say Y here to make use of these instructions for the in-kernel | 1054 | Say Y here to make use of these instructions for the in-kernel |
| 1043 | atomic routines. This incurs a small overhead on CPUs that do | 1055 | atomic routines. This incurs a small overhead on CPUs that do |
| 1044 | not support these instructions and requires the kernel to be | 1056 | not support these instructions and requires the kernel to be |
| 1045 | built with binutils >= 2.25. | 1057 | built with binutils >= 2.25 in order for the new instructions |
| 1058 | to be used. | ||
| 1046 | 1059 | ||
| 1047 | config ARM64_VHE | 1060 | config ARM64_VHE |
| 1048 | bool "Enable support for Virtualization Host Extensions (VHE)" | 1061 | bool "Enable support for Virtualization Host Extensions (VHE)" |
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h index 32f465a80e4e..0db62a4cbce2 100644 --- a/arch/arm64/include/asm/acpi.h +++ b/arch/arm64/include/asm/acpi.h | |||
| @@ -86,6 +86,10 @@ static inline bool acpi_has_cpu_in_madt(void) | |||
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | struct acpi_madt_generic_interrupt *acpi_cpu_get_madt_gicc(int cpu); | 88 | struct acpi_madt_generic_interrupt *acpi_cpu_get_madt_gicc(int cpu); |
| 89 | static inline u32 get_acpi_id_for_cpu(unsigned int cpu) | ||
| 90 | { | ||
| 91 | return acpi_cpu_get_madt_gicc(cpu)->uid; | ||
| 92 | } | ||
| 89 | 93 | ||
| 90 | static inline void arch_fix_phys_package_id(int num, u32 slot) { } | 94 | static inline void arch_fix_phys_package_id(int num, u32 slot) { } |
| 91 | void __init acpi_init_cpus(void); | 95 | void __init acpi_init_cpus(void); |
diff --git a/arch/arm64/include/asm/cache.h b/arch/arm64/include/asm/cache.h index 9bbffc7a301f..5df5cfe1c143 100644 --- a/arch/arm64/include/asm/cache.h +++ b/arch/arm64/include/asm/cache.h | |||
| @@ -33,7 +33,7 @@ | |||
| 33 | #define ICACHE_POLICY_VIPT 2 | 33 | #define ICACHE_POLICY_VIPT 2 |
| 34 | #define ICACHE_POLICY_PIPT 3 | 34 | #define ICACHE_POLICY_PIPT 3 |
| 35 | 35 | ||
| 36 | #define L1_CACHE_SHIFT 7 | 36 | #define L1_CACHE_SHIFT (6) |
| 37 | #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) | 37 | #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) |
| 38 | 38 | ||
| 39 | /* | 39 | /* |
| @@ -43,7 +43,7 @@ | |||
| 43 | * cache before the transfer is done, causing old data to be seen by | 43 | * cache before the transfer is done, causing old data to be seen by |
| 44 | * the CPU. | 44 | * the CPU. |
| 45 | */ | 45 | */ |
| 46 | #define ARCH_DMA_MINALIGN L1_CACHE_BYTES | 46 | #define ARCH_DMA_MINALIGN (128) |
| 47 | 47 | ||
| 48 | #ifndef __ASSEMBLY__ | 48 | #ifndef __ASSEMBLY__ |
| 49 | 49 | ||
| @@ -77,7 +77,7 @@ static inline u32 cache_type_cwg(void) | |||
| 77 | static inline int cache_line_size(void) | 77 | static inline int cache_line_size(void) |
| 78 | { | 78 | { |
| 79 | u32 cwg = cache_type_cwg(); | 79 | u32 cwg = cache_type_cwg(); |
| 80 | return cwg ? 4 << cwg : L1_CACHE_BYTES; | 80 | return cwg ? 4 << cwg : ARCH_DMA_MINALIGN; |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | #endif /* __ASSEMBLY__ */ | 83 | #endif /* __ASSEMBLY__ */ |
diff --git a/arch/arm64/include/asm/cmpxchg.h b/arch/arm64/include/asm/cmpxchg.h index 4f5fd2a36e6e..3b0938281541 100644 --- a/arch/arm64/include/asm/cmpxchg.h +++ b/arch/arm64/include/asm/cmpxchg.h | |||
| @@ -204,7 +204,9 @@ static inline void __cmpwait_case_##name(volatile void *ptr, \ | |||
| 204 | unsigned long tmp; \ | 204 | unsigned long tmp; \ |
| 205 | \ | 205 | \ |
| 206 | asm volatile( \ | 206 | asm volatile( \ |
| 207 | " ldxr" #sz "\t%" #w "[tmp], %[v]\n" \ | 207 | " sevl\n" \ |
| 208 | " wfe\n" \ | ||
| 209 | " ldxr" #sz "\t%" #w "[tmp], %[v]\n" \ | ||
| 208 | " eor %" #w "[tmp], %" #w "[tmp], %" #w "[val]\n" \ | 210 | " eor %" #w "[tmp], %" #w "[tmp], %" #w "[val]\n" \ |
| 209 | " cbnz %" #w "[tmp], 1f\n" \ | 211 | " cbnz %" #w "[tmp], 1f\n" \ |
| 210 | " wfe\n" \ | 212 | " wfe\n" \ |
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h index bc51b72fafd4..8a699c708fc9 100644 --- a/arch/arm64/include/asm/cpucaps.h +++ b/arch/arm64/include/asm/cpucaps.h | |||
| @@ -48,7 +48,8 @@ | |||
| 48 | #define ARM64_HAS_CACHE_IDC 27 | 48 | #define ARM64_HAS_CACHE_IDC 27 |
| 49 | #define ARM64_HAS_CACHE_DIC 28 | 49 | #define ARM64_HAS_CACHE_DIC 28 |
| 50 | #define ARM64_HW_DBM 29 | 50 | #define ARM64_HW_DBM 29 |
| 51 | #define ARM64_SSBD 30 | ||
| 51 | 52 | ||
| 52 | #define ARM64_NCAPS 30 | 53 | #define ARM64_NCAPS 31 |
| 53 | 54 | ||
| 54 | #endif /* __ASM_CPUCAPS_H */ | 55 | #endif /* __ASM_CPUCAPS_H */ |
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index 09b0f2a80c8f..55bc1f073bfb 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h | |||
| @@ -537,6 +537,28 @@ static inline u64 read_zcr_features(void) | |||
| 537 | return zcr; | 537 | return zcr; |
| 538 | } | 538 | } |
| 539 | 539 | ||
| 540 | #define ARM64_SSBD_UNKNOWN -1 | ||
| 541 | #define ARM64_SSBD_FORCE_DISABLE 0 | ||
| 542 | #define ARM64_SSBD_KERNEL 1 | ||
| 543 | #define ARM64_SSBD_FORCE_ENABLE 2 | ||
| 544 | #define ARM64_SSBD_MITIGATED 3 | ||
| 545 | |||
| 546 | static inline int arm64_get_ssbd_state(void) | ||
| 547 | { | ||
| 548 | #ifdef CONFIG_ARM64_SSBD | ||
| 549 | extern int ssbd_state; | ||
| 550 | return ssbd_state; | ||
| 551 | #else | ||
| 552 | return ARM64_SSBD_UNKNOWN; | ||
| 553 | #endif | ||
| 554 | } | ||
| 555 | |||
| 556 | #ifdef CONFIG_ARM64_SSBD | ||
| 557 | void arm64_set_ssbd_mitigation(bool state); | ||
| 558 | #else | ||
| 559 | static inline void arm64_set_ssbd_mitigation(bool state) {} | ||
| 560 | #endif | ||
| 561 | |||
| 540 | #endif /* __ASSEMBLY__ */ | 562 | #endif /* __ASSEMBLY__ */ |
| 541 | 563 | ||
| 542 | #endif | 564 | #endif |
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h index fac1c4de7898..433b9554c6a1 100644 --- a/arch/arm64/include/asm/elf.h +++ b/arch/arm64/include/asm/elf.h | |||
| @@ -121,6 +121,9 @@ | |||
| 121 | 121 | ||
| 122 | #ifndef __ASSEMBLY__ | 122 | #ifndef __ASSEMBLY__ |
| 123 | 123 | ||
| 124 | #include <linux/bug.h> | ||
| 125 | #include <asm/processor.h> /* for signal_minsigstksz, used by ARCH_DLINFO */ | ||
| 126 | |||
| 124 | typedef unsigned long elf_greg_t; | 127 | typedef unsigned long elf_greg_t; |
| 125 | 128 | ||
| 126 | #define ELF_NGREG (sizeof(struct user_pt_regs) / sizeof(elf_greg_t)) | 129 | #define ELF_NGREG (sizeof(struct user_pt_regs) / sizeof(elf_greg_t)) |
| @@ -148,6 +151,16 @@ typedef struct user_fpsimd_state elf_fpregset_t; | |||
| 148 | do { \ | 151 | do { \ |
| 149 | NEW_AUX_ENT(AT_SYSINFO_EHDR, \ | 152 | NEW_AUX_ENT(AT_SYSINFO_EHDR, \ |
| 150 | (elf_addr_t)current->mm->context.vdso); \ | 153 | (elf_addr_t)current->mm->context.vdso); \ |
| 154 | \ | ||
| 155 | /* \ | ||
| 156 | * Should always be nonzero unless there's a kernel bug. \ | ||
| 157 | * If we haven't determined a sensible value to give to \ | ||
| 158 | * userspace, omit the entry: \ | ||
| 159 | */ \ | ||
| 160 | if (likely(signal_minsigstksz)) \ | ||
| 161 | NEW_AUX_ENT(AT_MINSIGSTKSZ, signal_minsigstksz); \ | ||
| 162 | else \ | ||
| 163 | NEW_AUX_ENT(AT_IGNORE, 0); \ | ||
| 151 | } while (0) | 164 | } while (0) |
| 152 | 165 | ||
| 153 | #define ARCH_HAS_SETUP_ADDITIONAL_PAGES | 166 | #define ARCH_HAS_SETUP_ADDITIONAL_PAGES |
diff --git a/arch/arm64/include/asm/fpsimdmacros.h b/arch/arm64/include/asm/fpsimdmacros.h index e050d765ca9e..46843515d77b 100644 --- a/arch/arm64/include/asm/fpsimdmacros.h +++ b/arch/arm64/include/asm/fpsimdmacros.h | |||
| @@ -207,12 +207,14 @@ | |||
| 207 | str w\nxtmp, [\xpfpsr, #4] | 207 | str w\nxtmp, [\xpfpsr, #4] |
| 208 | .endm | 208 | .endm |
| 209 | 209 | ||
| 210 | .macro sve_load nxbase, xpfpsr, xvqminus1, nxtmp | 210 | .macro sve_load nxbase, xpfpsr, xvqminus1, nxtmp, xtmp2 |
| 211 | mrs_s x\nxtmp, SYS_ZCR_EL1 | 211 | mrs_s x\nxtmp, SYS_ZCR_EL1 |
| 212 | bic x\nxtmp, x\nxtmp, ZCR_ELx_LEN_MASK | 212 | bic \xtmp2, x\nxtmp, ZCR_ELx_LEN_MASK |
| 213 | orr x\nxtmp, x\nxtmp, \xvqminus1 | 213 | orr \xtmp2, \xtmp2, \xvqminus1 |
| 214 | msr_s SYS_ZCR_EL1, x\nxtmp // self-synchronising | 214 | cmp \xtmp2, x\nxtmp |
| 215 | 215 | b.eq 921f | |
| 216 | msr_s SYS_ZCR_EL1, \xtmp2 // self-synchronising | ||
| 217 | 921: | ||
| 216 | _for n, 0, 31, _sve_ldr_v \n, \nxbase, \n - 34 | 218 | _for n, 0, 31, _sve_ldr_v \n, \nxbase, \n - 34 |
| 217 | _sve_ldr_p 0, \nxbase | 219 | _sve_ldr_p 0, \nxbase |
| 218 | _sve_wrffr 0 | 220 | _sve_wrffr 0 |
diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index f6648a3e4152..951b2076a5e2 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h | |||
| @@ -20,6 +20,9 @@ | |||
| 20 | 20 | ||
| 21 | #include <asm/virt.h> | 21 | #include <asm/virt.h> |
| 22 | 22 | ||
| 23 | #define VCPU_WORKAROUND_2_FLAG_SHIFT 0 | ||
| 24 | #define VCPU_WORKAROUND_2_FLAG (_AC(1, UL) << VCPU_WORKAROUND_2_FLAG_SHIFT) | ||
| 25 | |||
| 23 | #define ARM_EXIT_WITH_SERROR_BIT 31 | 26 | #define ARM_EXIT_WITH_SERROR_BIT 31 |
| 24 | #define ARM_EXCEPTION_CODE(x) ((x) & ~(1U << ARM_EXIT_WITH_SERROR_BIT)) | 27 | #define ARM_EXCEPTION_CODE(x) ((x) & ~(1U << ARM_EXIT_WITH_SERROR_BIT)) |
| 25 | #define ARM_SERROR_PENDING(x) !!((x) & (1U << ARM_EXIT_WITH_SERROR_BIT)) | 28 | #define ARM_SERROR_PENDING(x) !!((x) & (1U << ARM_EXIT_WITH_SERROR_BIT)) |
| @@ -71,14 +74,37 @@ extern u32 __kvm_get_mdcr_el2(void); | |||
| 71 | 74 | ||
| 72 | extern u32 __init_stage2_translation(void); | 75 | extern u32 __init_stage2_translation(void); |
| 73 | 76 | ||
| 77 | /* Home-grown __this_cpu_{ptr,read} variants that always work at HYP */ | ||
| 78 | #define __hyp_this_cpu_ptr(sym) \ | ||
| 79 | ({ \ | ||
| 80 | void *__ptr = hyp_symbol_addr(sym); \ | ||
| 81 | __ptr += read_sysreg(tpidr_el2); \ | ||
| 82 | (typeof(&sym))__ptr; \ | ||
| 83 | }) | ||
| 84 | |||
| 85 | #define __hyp_this_cpu_read(sym) \ | ||
| 86 | ({ \ | ||
| 87 | *__hyp_this_cpu_ptr(sym); \ | ||
| 88 | }) | ||
| 89 | |||
| 74 | #else /* __ASSEMBLY__ */ | 90 | #else /* __ASSEMBLY__ */ |
| 75 | 91 | ||
| 76 | .macro get_host_ctxt reg, tmp | 92 | .macro hyp_adr_this_cpu reg, sym, tmp |
| 77 | adr_l \reg, kvm_host_cpu_state | 93 | adr_l \reg, \sym |
| 78 | mrs \tmp, tpidr_el2 | 94 | mrs \tmp, tpidr_el2 |
| 79 | add \reg, \reg, \tmp | 95 | add \reg, \reg, \tmp |
| 80 | .endm | 96 | .endm |
| 81 | 97 | ||
| 98 | .macro hyp_ldr_this_cpu reg, sym, tmp | ||
| 99 | adr_l \reg, \sym | ||
| 100 | mrs \tmp, tpidr_el2 | ||
| 101 | ldr \reg, [\reg, \tmp] | ||
| 102 | .endm | ||
| 103 | |||
| 104 | .macro get_host_ctxt reg, tmp | ||
| 105 | hyp_adr_this_cpu \reg, kvm_host_cpu_state, \tmp | ||
| 106 | .endm | ||
| 107 | |||
| 82 | .macro get_vcpu_ptr vcpu, ctxt | 108 | .macro get_vcpu_ptr vcpu, ctxt |
| 83 | get_host_ctxt \ctxt, \vcpu | 109 | get_host_ctxt \ctxt, \vcpu |
| 84 | ldr \vcpu, [\ctxt, #HOST_CONTEXT_VCPU] | 110 | ldr \vcpu, [\ctxt, #HOST_CONTEXT_VCPU] |
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 469de8acd06f..95d8a0e15b5f 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h | |||
| @@ -216,6 +216,9 @@ struct kvm_vcpu_arch { | |||
| 216 | /* Exception Information */ | 216 | /* Exception Information */ |
| 217 | struct kvm_vcpu_fault_info fault; | 217 | struct kvm_vcpu_fault_info fault; |
| 218 | 218 | ||
| 219 | /* State of various workarounds, see kvm_asm.h for bit assignment */ | ||
| 220 | u64 workaround_flags; | ||
| 221 | |||
| 219 | /* Guest debug state */ | 222 | /* Guest debug state */ |
| 220 | u64 debug_flags; | 223 | u64 debug_flags; |
| 221 | 224 | ||
| @@ -452,6 +455,29 @@ static inline bool kvm_arm_harden_branch_predictor(void) | |||
| 452 | return cpus_have_const_cap(ARM64_HARDEN_BRANCH_PREDICTOR); | 455 | return cpus_have_const_cap(ARM64_HARDEN_BRANCH_PREDICTOR); |
| 453 | } | 456 | } |
| 454 | 457 | ||
| 458 | #define KVM_SSBD_UNKNOWN -1 | ||
| 459 | #define KVM_SSBD_FORCE_DISABLE 0 | ||
| 460 | #define KVM_SSBD_KERNEL 1 | ||
| 461 | #define KVM_SSBD_FORCE_ENABLE 2 | ||
| 462 | #define KVM_SSBD_MITIGATED 3 | ||
| 463 | |||
| 464 | static inline int kvm_arm_have_ssbd(void) | ||
| 465 | { | ||
| 466 | switch (arm64_get_ssbd_state()) { | ||
| 467 | case ARM64_SSBD_FORCE_DISABLE: | ||
| 468 | return KVM_SSBD_FORCE_DISABLE; | ||
| 469 | case ARM64_SSBD_KERNEL: | ||
| 470 | return KVM_SSBD_KERNEL; | ||
| 471 | case ARM64_SSBD_FORCE_ENABLE: | ||
| 472 | return KVM_SSBD_FORCE_ENABLE; | ||
| 473 | case ARM64_SSBD_MITIGATED: | ||
| 474 | return KVM_SSBD_MITIGATED; | ||
| 475 | case ARM64_SSBD_UNKNOWN: | ||
| 476 | default: | ||
| 477 | return KVM_SSBD_UNKNOWN; | ||
| 478 | } | ||
| 479 | } | ||
| 480 | |||
| 455 | void kvm_vcpu_load_sysregs(struct kvm_vcpu *vcpu); | 481 | void kvm_vcpu_load_sysregs(struct kvm_vcpu *vcpu); |
| 456 | void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu); | 482 | void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu); |
| 457 | 483 | ||
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h index 6128992c2ded..fb9a7127bb75 100644 --- a/arch/arm64/include/asm/kvm_mmu.h +++ b/arch/arm64/include/asm/kvm_mmu.h | |||
| @@ -72,7 +72,6 @@ | |||
| 72 | #ifdef __ASSEMBLY__ | 72 | #ifdef __ASSEMBLY__ |
| 73 | 73 | ||
| 74 | #include <asm/alternative.h> | 74 | #include <asm/alternative.h> |
| 75 | #include <asm/cpufeature.h> | ||
| 76 | 75 | ||
| 77 | /* | 76 | /* |
| 78 | * Convert a kernel VA into a HYP VA. | 77 | * Convert a kernel VA into a HYP VA. |
| @@ -473,6 +472,30 @@ static inline int kvm_map_vectors(void) | |||
| 473 | } | 472 | } |
| 474 | #endif | 473 | #endif |
| 475 | 474 | ||
| 475 | #ifdef CONFIG_ARM64_SSBD | ||
| 476 | DECLARE_PER_CPU_READ_MOSTLY(u64, arm64_ssbd_callback_required); | ||
| 477 | |||
| 478 | static inline int hyp_map_aux_data(void) | ||
| 479 | { | ||
| 480 | int cpu, err; | ||
| 481 | |||
| 482 | for_each_possible_cpu(cpu) { | ||
| 483 | u64 *ptr; | ||
| 484 | |||
| 485 | ptr = per_cpu_ptr(&arm64_ssbd_callback_required, cpu); | ||
| 486 | err = create_hyp_mappings(ptr, ptr + 1, PAGE_HYP); | ||
| 487 | if (err) | ||
| 488 | return err; | ||
| 489 | } | ||
| 490 | return 0; | ||
| 491 | } | ||
| 492 | #else | ||
| 493 | static inline int hyp_map_aux_data(void) | ||
| 494 | { | ||
| 495 | return 0; | ||
| 496 | } | ||
| 497 | #endif | ||
| 498 | |||
| 476 | #define kvm_phys_to_vttbr(addr) phys_to_ttbr(addr) | 499 | #define kvm_phys_to_vttbr(addr) phys_to_ttbr(addr) |
| 477 | 500 | ||
| 478 | #endif /* __ASSEMBLY__ */ | 501 | #endif /* __ASSEMBLY__ */ |
diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index 767598932549..65ab83e8926e 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h | |||
| @@ -35,6 +35,8 @@ | |||
| 35 | #ifdef __KERNEL__ | 35 | #ifdef __KERNEL__ |
| 36 | 36 | ||
| 37 | #include <linux/build_bug.h> | 37 | #include <linux/build_bug.h> |
| 38 | #include <linux/cache.h> | ||
| 39 | #include <linux/init.h> | ||
| 38 | #include <linux/stddef.h> | 40 | #include <linux/stddef.h> |
| 39 | #include <linux/string.h> | 41 | #include <linux/string.h> |
| 40 | 42 | ||
| @@ -244,6 +246,9 @@ void cpu_enable_pan(const struct arm64_cpu_capabilities *__unused); | |||
| 244 | void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused); | 246 | void cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused); |
| 245 | void cpu_clear_disr(const struct arm64_cpu_capabilities *__unused); | 247 | void cpu_clear_disr(const struct arm64_cpu_capabilities *__unused); |
| 246 | 248 | ||
| 249 | extern unsigned long __ro_after_init signal_minsigstksz; /* sigframe size */ | ||
| 250 | extern void __init minsigstksz_setup(void); | ||
| 251 | |||
| 247 | /* Userspace interface for PR_SVE_{SET,GET}_VL prctl()s: */ | 252 | /* Userspace interface for PR_SVE_{SET,GET}_VL prctl()s: */ |
| 248 | #define SVE_SET_VL(arg) sve_set_current_vl(arg) | 253 | #define SVE_SET_VL(arg) sve_set_current_vl(arg) |
| 249 | #define SVE_GET_VL() sve_get_current_vl() | 254 | #define SVE_GET_VL() sve_get_current_vl() |
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h index 740aa03c5f0d..cbcf11b5e637 100644 --- a/arch/arm64/include/asm/thread_info.h +++ b/arch/arm64/include/asm/thread_info.h | |||
| @@ -94,6 +94,7 @@ void arch_release_task_struct(struct task_struct *tsk); | |||
| 94 | #define TIF_32BIT 22 /* 32bit process */ | 94 | #define TIF_32BIT 22 /* 32bit process */ |
| 95 | #define TIF_SVE 23 /* Scalable Vector Extension in use */ | 95 | #define TIF_SVE 23 /* Scalable Vector Extension in use */ |
| 96 | #define TIF_SVE_VL_INHERIT 24 /* Inherit sve_vl_onexec across exec */ | 96 | #define TIF_SVE_VL_INHERIT 24 /* Inherit sve_vl_onexec across exec */ |
| 97 | #define TIF_SSBD 25 /* Wants SSB mitigation */ | ||
| 97 | 98 | ||
| 98 | #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) | 99 | #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) |
| 99 | #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) | 100 | #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) |
diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h index c4f2d50491eb..df48212f767b 100644 --- a/arch/arm64/include/asm/topology.h +++ b/arch/arm64/include/asm/topology.h | |||
| @@ -7,14 +7,16 @@ | |||
| 7 | struct cpu_topology { | 7 | struct cpu_topology { |
| 8 | int thread_id; | 8 | int thread_id; |
| 9 | int core_id; | 9 | int core_id; |
| 10 | int cluster_id; | 10 | int package_id; |
| 11 | int llc_id; | ||
| 11 | cpumask_t thread_sibling; | 12 | cpumask_t thread_sibling; |
| 12 | cpumask_t core_sibling; | 13 | cpumask_t core_sibling; |
| 14 | cpumask_t llc_siblings; | ||
| 13 | }; | 15 | }; |
| 14 | 16 | ||
| 15 | extern struct cpu_topology cpu_topology[NR_CPUS]; | 17 | extern struct cpu_topology cpu_topology[NR_CPUS]; |
| 16 | 18 | ||
| 17 | #define topology_physical_package_id(cpu) (cpu_topology[cpu].cluster_id) | 19 | #define topology_physical_package_id(cpu) (cpu_topology[cpu].package_id) |
| 18 | #define topology_core_id(cpu) (cpu_topology[cpu].core_id) | 20 | #define topology_core_id(cpu) (cpu_topology[cpu].core_id) |
| 19 | #define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling) | 21 | #define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling) |
| 20 | #define topology_sibling_cpumask(cpu) (&cpu_topology[cpu].thread_sibling) | 22 | #define topology_sibling_cpumask(cpu) (&cpu_topology[cpu].thread_sibling) |
diff --git a/arch/arm64/include/uapi/asm/auxvec.h b/arch/arm64/include/uapi/asm/auxvec.h index ec0a86d484e1..743c0b84fd30 100644 --- a/arch/arm64/include/uapi/asm/auxvec.h +++ b/arch/arm64/include/uapi/asm/auxvec.h | |||
| @@ -19,7 +19,8 @@ | |||
| 19 | 19 | ||
| 20 | /* vDSO location */ | 20 | /* vDSO location */ |
| 21 | #define AT_SYSINFO_EHDR 33 | 21 | #define AT_SYSINFO_EHDR 33 |
| 22 | #define AT_MINSIGSTKSZ 51 /* stack needed for signal delivery */ | ||
| 22 | 23 | ||
| 23 | #define AT_VECTOR_SIZE_ARCH 1 /* entries in ARCH_DLINFO */ | 24 | #define AT_VECTOR_SIZE_ARCH 2 /* entries in ARCH_DLINFO */ |
| 24 | 25 | ||
| 25 | #endif | 26 | #endif |
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index bf825f38d206..0025f8691046 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile | |||
| @@ -54,6 +54,7 @@ arm64-obj-$(CONFIG_ARM64_RELOC_TEST) += arm64-reloc-test.o | |||
| 54 | arm64-reloc-test-y := reloc_test_core.o reloc_test_syms.o | 54 | arm64-reloc-test-y := reloc_test_core.o reloc_test_syms.o |
| 55 | arm64-obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | 55 | arm64-obj-$(CONFIG_CRASH_DUMP) += crash_dump.o |
| 56 | arm64-obj-$(CONFIG_ARM_SDE_INTERFACE) += sdei.o | 56 | arm64-obj-$(CONFIG_ARM_SDE_INTERFACE) += sdei.o |
| 57 | arm64-obj-$(CONFIG_ARM64_SSBD) += ssbd.o | ||
| 57 | 58 | ||
| 58 | obj-y += $(arm64-obj-y) vdso/ probes/ | 59 | obj-y += $(arm64-obj-y) vdso/ probes/ |
| 59 | obj-m += $(arm64-obj-m) | 60 | obj-m += $(arm64-obj-m) |
diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c index 6e47fc3ab549..97d45d5151d4 100644 --- a/arch/arm64/kernel/armv8_deprecated.c +++ b/arch/arm64/kernel/armv8_deprecated.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
| 14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
| 15 | #include <linux/sysctl.h> | 15 | #include <linux/sysctl.h> |
| 16 | #include <linux/uaccess.h> | ||
| 16 | 17 | ||
| 17 | #include <asm/cpufeature.h> | 18 | #include <asm/cpufeature.h> |
| 18 | #include <asm/insn.h> | 19 | #include <asm/insn.h> |
| @@ -20,8 +21,6 @@ | |||
| 20 | #include <asm/system_misc.h> | 21 | #include <asm/system_misc.h> |
| 21 | #include <asm/traps.h> | 22 | #include <asm/traps.h> |
| 22 | #include <asm/kprobes.h> | 23 | #include <asm/kprobes.h> |
| 23 | #include <linux/uaccess.h> | ||
| 24 | #include <asm/cpufeature.h> | ||
| 25 | 24 | ||
| 26 | #define CREATE_TRACE_POINTS | 25 | #define CREATE_TRACE_POINTS |
| 27 | #include "trace-events-emulation.h" | 26 | #include "trace-events-emulation.h" |
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c index 5bdda651bd05..323aeb5f2fe6 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c | |||
| @@ -136,6 +136,7 @@ int main(void) | |||
| 136 | #ifdef CONFIG_KVM_ARM_HOST | 136 | #ifdef CONFIG_KVM_ARM_HOST |
| 137 | DEFINE(VCPU_CONTEXT, offsetof(struct kvm_vcpu, arch.ctxt)); | 137 | DEFINE(VCPU_CONTEXT, offsetof(struct kvm_vcpu, arch.ctxt)); |
| 138 | DEFINE(VCPU_FAULT_DISR, offsetof(struct kvm_vcpu, arch.fault.disr_el1)); | 138 | DEFINE(VCPU_FAULT_DISR, offsetof(struct kvm_vcpu, arch.fault.disr_el1)); |
| 139 | DEFINE(VCPU_WORKAROUND_FLAGS, offsetof(struct kvm_vcpu, arch.workaround_flags)); | ||
| 139 | DEFINE(CPU_GP_REGS, offsetof(struct kvm_cpu_context, gp_regs)); | 140 | DEFINE(CPU_GP_REGS, offsetof(struct kvm_cpu_context, gp_regs)); |
| 140 | DEFINE(CPU_USER_PT_REGS, offsetof(struct kvm_regs, regs)); | 141 | DEFINE(CPU_USER_PT_REGS, offsetof(struct kvm_regs, regs)); |
| 141 | DEFINE(CPU_FP_REGS, offsetof(struct kvm_regs, fp_regs)); | 142 | DEFINE(CPU_FP_REGS, offsetof(struct kvm_regs, fp_regs)); |
diff --git a/arch/arm64/kernel/cacheinfo.c b/arch/arm64/kernel/cacheinfo.c index 380f2e2fbed5..0bf0a835122f 100644 --- a/arch/arm64/kernel/cacheinfo.c +++ b/arch/arm64/kernel/cacheinfo.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 18 | */ | 18 | */ |
| 19 | 19 | ||
| 20 | #include <linux/acpi.h> | ||
| 20 | #include <linux/cacheinfo.h> | 21 | #include <linux/cacheinfo.h> |
| 21 | #include <linux/of.h> | 22 | #include <linux/of.h> |
| 22 | 23 | ||
| @@ -46,7 +47,7 @@ static void ci_leaf_init(struct cacheinfo *this_leaf, | |||
| 46 | 47 | ||
| 47 | static int __init_cache_level(unsigned int cpu) | 48 | static int __init_cache_level(unsigned int cpu) |
| 48 | { | 49 | { |
| 49 | unsigned int ctype, level, leaves, of_level; | 50 | unsigned int ctype, level, leaves, fw_level; |
| 50 | struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); | 51 | struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); |
| 51 | 52 | ||
| 52 | for (level = 1, leaves = 0; level <= MAX_CACHE_LEVEL; level++) { | 53 | for (level = 1, leaves = 0; level <= MAX_CACHE_LEVEL; level++) { |
| @@ -59,15 +60,19 @@ static int __init_cache_level(unsigned int cpu) | |||
| 59 | leaves += (ctype == CACHE_TYPE_SEPARATE) ? 2 : 1; | 60 | leaves += (ctype == CACHE_TYPE_SEPARATE) ? 2 : 1; |
| 60 | } | 61 | } |
| 61 | 62 | ||
| 62 | of_level = of_find_last_cache_level(cpu); | 63 | if (acpi_disabled) |
| 63 | if (level < of_level) { | 64 | fw_level = of_find_last_cache_level(cpu); |
| 65 | else | ||
| 66 | fw_level = acpi_find_last_cache_level(cpu); | ||
| 67 | |||
| 68 | if (level < fw_level) { | ||
| 64 | /* | 69 | /* |
| 65 | * some external caches not specified in CLIDR_EL1 | 70 | * some external caches not specified in CLIDR_EL1 |
| 66 | * the information may be available in the device tree | 71 | * the information may be available in the device tree |
| 67 | * only unified external caches are considered here | 72 | * only unified external caches are considered here |
| 68 | */ | 73 | */ |
| 69 | leaves += (of_level - level); | 74 | leaves += (fw_level - level); |
| 70 | level = of_level; | 75 | level = fw_level; |
| 71 | } | 76 | } |
| 72 | 77 | ||
| 73 | this_cpu_ci->num_levels = level; | 78 | this_cpu_ci->num_levels = level; |
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index e4a1182deff7..1d2b6d768efe 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c | |||
| @@ -16,6 +16,8 @@ | |||
| 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 17 | */ | 17 | */ |
| 18 | 18 | ||
| 19 | #include <linux/arm-smccc.h> | ||
| 20 | #include <linux/psci.h> | ||
| 19 | #include <linux/types.h> | 21 | #include <linux/types.h> |
| 20 | #include <asm/cpu.h> | 22 | #include <asm/cpu.h> |
| 21 | #include <asm/cputype.h> | 23 | #include <asm/cputype.h> |
| @@ -232,6 +234,178 @@ enable_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry) | |||
| 232 | } | 234 | } |
| 233 | #endif /* CONFIG_HARDEN_BRANCH_PREDICTOR */ | 235 | #endif /* CONFIG_HARDEN_BRANCH_PREDICTOR */ |
| 234 | 236 | ||
| 237 | #ifdef CONFIG_ARM64_SSBD | ||
| 238 | DEFINE_PER_CPU_READ_MOSTLY(u64, arm64_ssbd_callback_required); | ||
| 239 | |||
| 240 | int ssbd_state __read_mostly = ARM64_SSBD_KERNEL; | ||
| 241 | |||
| 242 | static const struct ssbd_options { | ||
| 243 | const char *str; | ||
| 244 | int state; | ||
| 245 | } ssbd_options[] = { | ||
| 246 | { "force-on", ARM64_SSBD_FORCE_ENABLE, }, | ||
| 247 | { "force-off", ARM64_SSBD_FORCE_DISABLE, }, | ||
| 248 | { "kernel", ARM64_SSBD_KERNEL, }, | ||
| 249 | }; | ||
| 250 | |||
| 251 | static int __init ssbd_cfg(char *buf) | ||
| 252 | { | ||
| 253 | int i; | ||
| 254 | |||
| 255 | if (!buf || !buf[0]) | ||
| 256 | return -EINVAL; | ||
| 257 | |||
| 258 | for (i = 0; i < ARRAY_SIZE(ssbd_options); i++) { | ||
| 259 | int len = strlen(ssbd_options[i].str); | ||
| 260 | |||
| 261 | if (strncmp(buf, ssbd_options[i].str, len)) | ||
| 262 | continue; | ||
| 263 | |||
| 264 | ssbd_state = ssbd_options[i].state; | ||
| 265 | return 0; | ||
| 266 | } | ||
| 267 | |||
| 268 | return -EINVAL; | ||
| 269 | } | ||
| 270 | early_param("ssbd", ssbd_cfg); | ||
| 271 | |||
| 272 | void __init arm64_update_smccc_conduit(struct alt_instr *alt, | ||
| 273 | __le32 *origptr, __le32 *updptr, | ||
| 274 | int nr_inst) | ||
| 275 | { | ||
| 276 | u32 insn; | ||
| 277 | |||
| 278 | BUG_ON(nr_inst != 1); | ||
| 279 | |||
| 280 | switch (psci_ops.conduit) { | ||
| 281 | case PSCI_CONDUIT_HVC: | ||
| 282 | insn = aarch64_insn_get_hvc_value(); | ||
| 283 | break; | ||
| 284 | case PSCI_CONDUIT_SMC: | ||
| 285 | insn = aarch64_insn_get_smc_value(); | ||
| 286 | break; | ||
| 287 | default: | ||
| 288 | return; | ||
| 289 | } | ||
| 290 | |||
| 291 | *updptr = cpu_to_le32(insn); | ||
| 292 | } | ||
| 293 | |||
| 294 | void __init arm64_enable_wa2_handling(struct alt_instr *alt, | ||
| 295 | __le32 *origptr, __le32 *updptr, | ||
| 296 | int nr_inst) | ||
| 297 | { | ||
| 298 | BUG_ON(nr_inst != 1); | ||
| 299 | /* | ||
| 300 | * Only allow mitigation on EL1 entry/exit and guest | ||
| 301 | * ARCH_WORKAROUND_2 handling if the SSBD state allows it to | ||
| 302 | * be flipped. | ||
| 303 | */ | ||
| 304 | if (arm64_get_ssbd_state() == ARM64_SSBD_KERNEL) | ||
| 305 | *updptr = cpu_to_le32(aarch64_insn_gen_nop()); | ||
| 306 | } | ||
| 307 | |||
| 308 | void arm64_set_ssbd_mitigation(bool state) | ||
| 309 | { | ||
| 310 | switch (psci_ops.conduit) { | ||
| 311 | case PSCI_CONDUIT_HVC: | ||
| 312 | arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_2, state, NULL); | ||
| 313 | break; | ||
| 314 | |||
| 315 | case PSCI_CONDUIT_SMC: | ||
| 316 | arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2, state, NULL); | ||
| 317 | break; | ||
| 318 | |||
| 319 | default: | ||
| 320 | WARN_ON_ONCE(1); | ||
| 321 | break; | ||
| 322 | } | ||
| 323 | } | ||
| 324 | |||
| 325 | static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry, | ||
| 326 | int scope) | ||
| 327 | { | ||
| 328 | struct arm_smccc_res res; | ||
| 329 | bool required = true; | ||
| 330 | s32 val; | ||
| 331 | |||
| 332 | WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible()); | ||
| 333 | |||
| 334 | if (psci_ops.smccc_version == SMCCC_VERSION_1_0) { | ||
| 335 | ssbd_state = ARM64_SSBD_UNKNOWN; | ||
| 336 | return false; | ||
| 337 | } | ||
| 338 | |||
| 339 | switch (psci_ops.conduit) { | ||
| 340 | case PSCI_CONDUIT_HVC: | ||
| 341 | arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, | ||
| 342 | ARM_SMCCC_ARCH_WORKAROUND_2, &res); | ||
| 343 | break; | ||
| 344 | |||
| 345 | case PSCI_CONDUIT_SMC: | ||
| 346 | arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, | ||
| 347 | ARM_SMCCC_ARCH_WORKAROUND_2, &res); | ||
| 348 | break; | ||
| 349 | |||
| 350 | default: | ||
| 351 | ssbd_state = ARM64_SSBD_UNKNOWN; | ||
| 352 | return false; | ||
| 353 | } | ||
| 354 | |||
| 355 | val = (s32)res.a0; | ||
| 356 | |||
| 357 | switch (val) { | ||
| 358 | case SMCCC_RET_NOT_SUPPORTED: | ||
| 359 | ssbd_state = ARM64_SSBD_UNKNOWN; | ||
| 360 | return false; | ||
| 361 | |||
| 362 | case SMCCC_RET_NOT_REQUIRED: | ||
| 363 | pr_info_once("%s mitigation not required\n", entry->desc); | ||
| 364 | ssbd_state = ARM64_SSBD_MITIGATED; | ||
| 365 | return false; | ||
| 366 | |||
| 367 | case SMCCC_RET_SUCCESS: | ||
| 368 | required = true; | ||
| 369 | break; | ||
| 370 | |||
| 371 | case 1: /* Mitigation not required on this CPU */ | ||
| 372 | required = false; | ||
| 373 | break; | ||
| 374 | |||
| 375 | default: | ||
| 376 | WARN_ON(1); | ||
| 377 | return false; | ||
| 378 | } | ||
| 379 | |||
| 380 | switch (ssbd_state) { | ||
| 381 | case ARM64_SSBD_FORCE_DISABLE: | ||
| 382 | pr_info_once("%s disabled from command-line\n", entry->desc); | ||
| 383 | arm64_set_ssbd_mitigation(false); | ||
| 384 | required = false; | ||
| 385 | break; | ||
| 386 | |||
| 387 | case ARM64_SSBD_KERNEL: | ||
| 388 | if (required) { | ||
| 389 | __this_cpu_write(arm64_ssbd_callback_required, 1); | ||
| 390 | arm64_set_ssbd_mitigation(true); | ||
| 391 | } | ||
| 392 | break; | ||
| 393 | |||
| 394 | case ARM64_SSBD_FORCE_ENABLE: | ||
| 395 | pr_info_once("%s forced from command-line\n", entry->desc); | ||
| 396 | arm64_set_ssbd_mitigation(true); | ||
| 397 | required = true; | ||
| 398 | break; | ||
| 399 | |||
| 400 | default: | ||
| 401 | WARN_ON(1); | ||
| 402 | break; | ||
| 403 | } | ||
| 404 | |||
| 405 | return required; | ||
| 406 | } | ||
| 407 | #endif /* CONFIG_ARM64_SSBD */ | ||
| 408 | |||
| 235 | #define CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max) \ | 409 | #define CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max) \ |
| 236 | .matches = is_affected_midr_range, \ | 410 | .matches = is_affected_midr_range, \ |
| 237 | .midr_range = MIDR_RANGE(model, v_min, r_min, v_max, r_max) | 411 | .midr_range = MIDR_RANGE(model, v_min, r_min, v_max, r_max) |
| @@ -488,6 +662,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = { | |||
| 488 | ERRATA_MIDR_RANGE_LIST(arm64_harden_el2_vectors), | 662 | ERRATA_MIDR_RANGE_LIST(arm64_harden_el2_vectors), |
| 489 | }, | 663 | }, |
| 490 | #endif | 664 | #endif |
| 665 | #ifdef CONFIG_ARM64_SSBD | ||
| 666 | { | ||
| 667 | .desc = "Speculative Store Bypass Disable", | ||
| 668 | .capability = ARM64_SSBD, | ||
| 669 | .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, | ||
| 670 | .matches = has_ssbd_mitigation, | ||
| 671 | }, | ||
| 672 | #endif | ||
| 491 | { | 673 | { |
| 492 | } | 674 | } |
| 493 | }; | 675 | }; |
diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 9d1b06d67c53..d2856b129097 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c | |||
| @@ -1606,7 +1606,6 @@ static void __init setup_system_capabilities(void) | |||
| 1606 | void __init setup_cpu_features(void) | 1606 | void __init setup_cpu_features(void) |
| 1607 | { | 1607 | { |
| 1608 | u32 cwg; | 1608 | u32 cwg; |
| 1609 | int cls; | ||
| 1610 | 1609 | ||
| 1611 | setup_system_capabilities(); | 1610 | setup_system_capabilities(); |
| 1612 | mark_const_caps_ready(); | 1611 | mark_const_caps_ready(); |
| @@ -1619,6 +1618,7 @@ void __init setup_cpu_features(void) | |||
| 1619 | pr_info("emulated: Privileged Access Never (PAN) using TTBR0_EL1 switching\n"); | 1618 | pr_info("emulated: Privileged Access Never (PAN) using TTBR0_EL1 switching\n"); |
| 1620 | 1619 | ||
| 1621 | sve_setup(); | 1620 | sve_setup(); |
| 1621 | minsigstksz_setup(); | ||
| 1622 | 1622 | ||
| 1623 | /* Advertise that we have computed the system capabilities */ | 1623 | /* Advertise that we have computed the system capabilities */ |
| 1624 | set_sys_caps_initialised(); | 1624 | set_sys_caps_initialised(); |
| @@ -1627,13 +1627,9 @@ void __init setup_cpu_features(void) | |||
| 1627 | * Check for sane CTR_EL0.CWG value. | 1627 | * Check for sane CTR_EL0.CWG value. |
| 1628 | */ | 1628 | */ |
| 1629 | cwg = cache_type_cwg(); | 1629 | cwg = cache_type_cwg(); |
| 1630 | cls = cache_line_size(); | ||
| 1631 | if (!cwg) | 1630 | if (!cwg) |
| 1632 | pr_warn("No Cache Writeback Granule information, assuming cache line size %d\n", | 1631 | pr_warn("No Cache Writeback Granule information, assuming %d\n", |
| 1633 | cls); | 1632 | ARCH_DMA_MINALIGN); |
| 1634 | if (L1_CACHE_BYTES < cls) | ||
| 1635 | pr_warn("L1_CACHE_BYTES smaller than the Cache Writeback Granule (%d < %d)\n", | ||
| 1636 | L1_CACHE_BYTES, cls); | ||
| 1637 | } | 1633 | } |
| 1638 | 1634 | ||
| 1639 | static bool __maybe_unused | 1635 | static bool __maybe_unused |
diff --git a/arch/arm64/kernel/entry-fpsimd.S b/arch/arm64/kernel/entry-fpsimd.S index 73f17bffcd23..12d4958e6429 100644 --- a/arch/arm64/kernel/entry-fpsimd.S +++ b/arch/arm64/kernel/entry-fpsimd.S | |||
| @@ -49,7 +49,7 @@ ENTRY(sve_save_state) | |||
| 49 | ENDPROC(sve_save_state) | 49 | ENDPROC(sve_save_state) |
| 50 | 50 | ||
| 51 | ENTRY(sve_load_state) | 51 | ENTRY(sve_load_state) |
| 52 | sve_load 0, x1, x2, 3 | 52 | sve_load 0, x1, x2, 3, x4 |
| 53 | ret | 53 | ret |
| 54 | ENDPROC(sve_load_state) | 54 | ENDPROC(sve_load_state) |
| 55 | 55 | ||
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index ec2ee720e33e..28ad8799406f 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 18 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | #include <linux/arm-smccc.h> | ||
| 21 | #include <linux/init.h> | 22 | #include <linux/init.h> |
| 22 | #include <linux/linkage.h> | 23 | #include <linux/linkage.h> |
| 23 | 24 | ||
| @@ -137,6 +138,25 @@ alternative_else_nop_endif | |||
| 137 | add \dst, \dst, #(\sym - .entry.tramp.text) | 138 | add \dst, \dst, #(\sym - .entry.tramp.text) |
| 138 | .endm | 139 | .endm |
| 139 | 140 | ||
| 141 | // This macro corrupts x0-x3. It is the caller's duty | ||
| 142 | // to save/restore them if required. | ||
| 143 | .macro apply_ssbd, state, targ, tmp1, tmp2 | ||
| 144 | #ifdef CONFIG_ARM64_SSBD | ||
| 145 | alternative_cb arm64_enable_wa2_handling | ||
| 146 | b \targ | ||
| 147 | alternative_cb_end | ||
| 148 | ldr_this_cpu \tmp2, arm64_ssbd_callback_required, \tmp1 | ||
| 149 | cbz \tmp2, \targ | ||
| 150 | ldr \tmp2, [tsk, #TSK_TI_FLAGS] | ||
| 151 | tbnz \tmp2, #TIF_SSBD, \targ | ||
| 152 | mov w0, #ARM_SMCCC_ARCH_WORKAROUND_2 | ||
| 153 | mov w1, #\state | ||
| 154 | alternative_cb arm64_update_smccc_conduit | ||
| 155 | nop // Patched to SMC/HVC #0 | ||
| 156 | alternative_cb_end | ||
| 157 | #endif | ||
| 158 | .endm | ||
| 159 | |||
| 140 | .macro kernel_entry, el, regsize = 64 | 160 | .macro kernel_entry, el, regsize = 64 |
| 141 | .if \regsize == 32 | 161 | .if \regsize == 32 |
| 142 | mov w0, w0 // zero upper 32 bits of x0 | 162 | mov w0, w0 // zero upper 32 bits of x0 |
| @@ -163,6 +183,14 @@ alternative_else_nop_endif | |||
| 163 | ldr x19, [tsk, #TSK_TI_FLAGS] // since we can unmask debug | 183 | ldr x19, [tsk, #TSK_TI_FLAGS] // since we can unmask debug |
| 164 | disable_step_tsk x19, x20 // exceptions when scheduling. | 184 | disable_step_tsk x19, x20 // exceptions when scheduling. |
| 165 | 185 | ||
| 186 | apply_ssbd 1, 1f, x22, x23 | ||
| 187 | |||
| 188 | #ifdef CONFIG_ARM64_SSBD | ||
| 189 | ldp x0, x1, [sp, #16 * 0] | ||
| 190 | ldp x2, x3, [sp, #16 * 1] | ||
| 191 | #endif | ||
| 192 | 1: | ||
| 193 | |||
| 166 | mov x29, xzr // fp pointed to user-space | 194 | mov x29, xzr // fp pointed to user-space |
| 167 | .else | 195 | .else |
| 168 | add x21, sp, #S_FRAME_SIZE | 196 | add x21, sp, #S_FRAME_SIZE |
| @@ -303,6 +331,8 @@ alternative_if ARM64_WORKAROUND_845719 | |||
| 303 | alternative_else_nop_endif | 331 | alternative_else_nop_endif |
| 304 | #endif | 332 | #endif |
| 305 | 3: | 333 | 3: |
| 334 | apply_ssbd 0, 5f, x0, x1 | ||
| 335 | 5: | ||
| 306 | .endif | 336 | .endif |
| 307 | 337 | ||
| 308 | msr elr_el1, x21 // set up the return data | 338 | msr elr_el1, x21 // set up the return data |
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c index 4bcdd0318729..3b527ae46e49 100644 --- a/arch/arm64/kernel/fpsimd.c +++ b/arch/arm64/kernel/fpsimd.c | |||
| @@ -31,7 +31,6 @@ | |||
| 31 | #include <linux/percpu.h> | 31 | #include <linux/percpu.h> |
| 32 | #include <linux/prctl.h> | 32 | #include <linux/prctl.h> |
| 33 | #include <linux/preempt.h> | 33 | #include <linux/preempt.h> |
| 34 | #include <linux/prctl.h> | ||
| 35 | #include <linux/ptrace.h> | 34 | #include <linux/ptrace.h> |
| 36 | #include <linux/sched/signal.h> | 35 | #include <linux/sched/signal.h> |
| 37 | #include <linux/sched/task_stack.h> | 36 | #include <linux/sched/task_stack.h> |
| @@ -129,7 +128,7 @@ static int sve_default_vl = -1; | |||
| 129 | #ifdef CONFIG_ARM64_SVE | 128 | #ifdef CONFIG_ARM64_SVE |
| 130 | 129 | ||
| 131 | /* Maximum supported vector length across all CPUs (initially poisoned) */ | 130 | /* Maximum supported vector length across all CPUs (initially poisoned) */ |
| 132 | int __ro_after_init sve_max_vl = -1; | 131 | int __ro_after_init sve_max_vl = SVE_VL_MIN; |
| 133 | /* Set of available vector lengths, as vq_to_bit(vq): */ | 132 | /* Set of available vector lengths, as vq_to_bit(vq): */ |
| 134 | static __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX); | 133 | static __ro_after_init DECLARE_BITMAP(sve_vq_map, SVE_VQ_MAX); |
| 135 | static void __percpu *efi_sve_state; | 134 | static void __percpu *efi_sve_state; |
| @@ -360,22 +359,13 @@ static int sve_proc_do_default_vl(struct ctl_table *table, int write, | |||
| 360 | return ret; | 359 | return ret; |
| 361 | 360 | ||
| 362 | /* Writing -1 has the special meaning "set to max": */ | 361 | /* Writing -1 has the special meaning "set to max": */ |
| 363 | if (vl == -1) { | 362 | if (vl == -1) |
| 364 | /* Fail safe if sve_max_vl wasn't initialised */ | 363 | vl = sve_max_vl; |
| 365 | if (WARN_ON(!sve_vl_valid(sve_max_vl))) | ||
| 366 | vl = SVE_VL_MIN; | ||
| 367 | else | ||
| 368 | vl = sve_max_vl; | ||
| 369 | |||
| 370 | goto chosen; | ||
| 371 | } | ||
| 372 | 364 | ||
| 373 | if (!sve_vl_valid(vl)) | 365 | if (!sve_vl_valid(vl)) |
| 374 | return -EINVAL; | 366 | return -EINVAL; |
| 375 | 367 | ||
| 376 | vl = find_supported_vector_length(vl); | 368 | sve_default_vl = find_supported_vector_length(vl); |
| 377 | chosen: | ||
| 378 | sve_default_vl = vl; | ||
| 379 | return 0; | 369 | return 0; |
| 380 | } | 370 | } |
| 381 | 371 | ||
diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c index 1ec5f28c39fc..6b2686d54411 100644 --- a/arch/arm64/kernel/hibernate.c +++ b/arch/arm64/kernel/hibernate.c | |||
| @@ -313,6 +313,17 @@ int swsusp_arch_suspend(void) | |||
| 313 | 313 | ||
| 314 | sleep_cpu = -EINVAL; | 314 | sleep_cpu = -EINVAL; |
| 315 | __cpu_suspend_exit(); | 315 | __cpu_suspend_exit(); |
| 316 | |||
| 317 | /* | ||
| 318 | * Just in case the boot kernel did turn the SSBD | ||
| 319 | * mitigation off behind our back, let's set the state | ||
| 320 | * to what we expect it to be. | ||
| 321 | */ | ||
| 322 | switch (arm64_get_ssbd_state()) { | ||
| 323 | case ARM64_SSBD_FORCE_ENABLE: | ||
| 324 | case ARM64_SSBD_KERNEL: | ||
| 325 | arm64_set_ssbd_mitigation(true); | ||
| 326 | } | ||
| 316 | } | 327 | } |
| 317 | 328 | ||
| 318 | local_daif_restore(flags); | 329 | local_daif_restore(flags); |
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index 85a251b6dfa8..33147aacdafd 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c | |||
| @@ -670,11 +670,10 @@ static void armv8pmu_disable_event(struct perf_event *event) | |||
| 670 | raw_spin_unlock_irqrestore(&events->pmu_lock, flags); | 670 | raw_spin_unlock_irqrestore(&events->pmu_lock, flags); |
| 671 | } | 671 | } |
| 672 | 672 | ||
| 673 | static irqreturn_t armv8pmu_handle_irq(int irq_num, void *dev) | 673 | static irqreturn_t armv8pmu_handle_irq(struct arm_pmu *cpu_pmu) |
| 674 | { | 674 | { |
| 675 | u32 pmovsr; | 675 | u32 pmovsr; |
| 676 | struct perf_sample_data data; | 676 | struct perf_sample_data data; |
| 677 | struct arm_pmu *cpu_pmu = (struct arm_pmu *)dev; | ||
| 678 | struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events); | 677 | struct pmu_hw_events *cpuc = this_cpu_ptr(cpu_pmu->hw_events); |
| 679 | struct pt_regs *regs; | 678 | struct pt_regs *regs; |
| 680 | int idx; | 679 | int idx; |
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c index 7ff81fed46e1..bd732644c2f6 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c | |||
| @@ -766,9 +766,6 @@ static void sve_init_header_from_task(struct user_sve_header *header, | |||
| 766 | vq = sve_vq_from_vl(header->vl); | 766 | vq = sve_vq_from_vl(header->vl); |
| 767 | 767 | ||
| 768 | header->max_vl = sve_max_vl; | 768 | header->max_vl = sve_max_vl; |
| 769 | if (WARN_ON(!sve_vl_valid(sve_max_vl))) | ||
| 770 | header->max_vl = header->vl; | ||
| 771 | |||
| 772 | header->size = SVE_PT_SIZE(vq, header->flags); | 769 | header->size = SVE_PT_SIZE(vq, header->flags); |
| 773 | header->max_size = SVE_PT_SIZE(sve_vq_from_vl(header->max_vl), | 770 | header->max_size = SVE_PT_SIZE(sve_vq_from_vl(header->max_vl), |
| 774 | SVE_PT_REGS_SVE); | 771 | SVE_PT_REGS_SVE); |
| @@ -1046,8 +1043,6 @@ static const struct user_regset_view user_aarch64_view = { | |||
| 1046 | }; | 1043 | }; |
| 1047 | 1044 | ||
| 1048 | #ifdef CONFIG_COMPAT | 1045 | #ifdef CONFIG_COMPAT |
| 1049 | #include <linux/compat.h> | ||
| 1050 | |||
| 1051 | enum compat_regset { | 1046 | enum compat_regset { |
| 1052 | REGSET_COMPAT_GPR, | 1047 | REGSET_COMPAT_GPR, |
| 1053 | REGSET_COMPAT_VFP, | 1048 | REGSET_COMPAT_VFP, |
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 154b7d30145d..511af13e8d8f 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 18 | */ | 18 | */ |
| 19 | 19 | ||
| 20 | #include <linux/cache.h> | ||
| 20 | #include <linux/compat.h> | 21 | #include <linux/compat.h> |
| 21 | #include <linux/errno.h> | 22 | #include <linux/errno.h> |
| 22 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
| @@ -570,8 +571,15 @@ badframe: | |||
| 570 | return 0; | 571 | return 0; |
| 571 | } | 572 | } |
| 572 | 573 | ||
| 573 | /* Determine the layout of optional records in the signal frame */ | 574 | /* |
| 574 | static int setup_sigframe_layout(struct rt_sigframe_user_layout *user) | 575 | * Determine the layout of optional records in the signal frame |
| 576 | * | ||
| 577 | * add_all: if true, lays out the biggest possible signal frame for | ||
| 578 | * this task; otherwise, generates a layout for the current state | ||
| 579 | * of the task. | ||
| 580 | */ | ||
| 581 | static int setup_sigframe_layout(struct rt_sigframe_user_layout *user, | ||
| 582 | bool add_all) | ||
| 575 | { | 583 | { |
| 576 | int err; | 584 | int err; |
| 577 | 585 | ||
| @@ -581,7 +589,7 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user) | |||
| 581 | return err; | 589 | return err; |
| 582 | 590 | ||
| 583 | /* fault information, if valid */ | 591 | /* fault information, if valid */ |
| 584 | if (current->thread.fault_code) { | 592 | if (add_all || current->thread.fault_code) { |
| 585 | err = sigframe_alloc(user, &user->esr_offset, | 593 | err = sigframe_alloc(user, &user->esr_offset, |
| 586 | sizeof(struct esr_context)); | 594 | sizeof(struct esr_context)); |
| 587 | if (err) | 595 | if (err) |
| @@ -591,8 +599,14 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user) | |||
| 591 | if (system_supports_sve()) { | 599 | if (system_supports_sve()) { |
| 592 | unsigned int vq = 0; | 600 | unsigned int vq = 0; |
| 593 | 601 | ||
| 594 | if (test_thread_flag(TIF_SVE)) | 602 | if (add_all || test_thread_flag(TIF_SVE)) { |
| 595 | vq = sve_vq_from_vl(current->thread.sve_vl); | 603 | int vl = sve_max_vl; |
| 604 | |||
| 605 | if (!add_all) | ||
| 606 | vl = current->thread.sve_vl; | ||
| 607 | |||
| 608 | vq = sve_vq_from_vl(vl); | ||
| 609 | } | ||
| 596 | 610 | ||
| 597 | err = sigframe_alloc(user, &user->sve_offset, | 611 | err = sigframe_alloc(user, &user->sve_offset, |
| 598 | SVE_SIG_CONTEXT_SIZE(vq)); | 612 | SVE_SIG_CONTEXT_SIZE(vq)); |
| @@ -603,7 +617,6 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user) | |||
| 603 | return sigframe_alloc_end(user); | 617 | return sigframe_alloc_end(user); |
| 604 | } | 618 | } |
| 605 | 619 | ||
| 606 | |||
| 607 | static int setup_sigframe(struct rt_sigframe_user_layout *user, | 620 | static int setup_sigframe(struct rt_sigframe_user_layout *user, |
| 608 | struct pt_regs *regs, sigset_t *set) | 621 | struct pt_regs *regs, sigset_t *set) |
| 609 | { | 622 | { |
| @@ -701,7 +714,7 @@ static int get_sigframe(struct rt_sigframe_user_layout *user, | |||
| 701 | int err; | 714 | int err; |
| 702 | 715 | ||
| 703 | init_user_layout(user); | 716 | init_user_layout(user); |
| 704 | err = setup_sigframe_layout(user); | 717 | err = setup_sigframe_layout(user, false); |
| 705 | if (err) | 718 | if (err) |
| 706 | return err; | 719 | return err; |
| 707 | 720 | ||
| @@ -830,11 +843,12 @@ static void do_signal(struct pt_regs *regs) | |||
| 830 | unsigned long continue_addr = 0, restart_addr = 0; | 843 | unsigned long continue_addr = 0, restart_addr = 0; |
| 831 | int retval = 0; | 844 | int retval = 0; |
| 832 | struct ksignal ksig; | 845 | struct ksignal ksig; |
| 846 | bool syscall = in_syscall(regs); | ||
| 833 | 847 | ||
| 834 | /* | 848 | /* |
| 835 | * If we were from a system call, check for system call restarting... | 849 | * If we were from a system call, check for system call restarting... |
| 836 | */ | 850 | */ |
| 837 | if (in_syscall(regs)) { | 851 | if (syscall) { |
| 838 | continue_addr = regs->pc; | 852 | continue_addr = regs->pc; |
| 839 | restart_addr = continue_addr - (compat_thumb_mode(regs) ? 2 : 4); | 853 | restart_addr = continue_addr - (compat_thumb_mode(regs) ? 2 : 4); |
| 840 | retval = regs->regs[0]; | 854 | retval = regs->regs[0]; |
| @@ -886,7 +900,7 @@ static void do_signal(struct pt_regs *regs) | |||
| 886 | * Handle restarting a different system call. As above, if a debugger | 900 | * Handle restarting a different system call. As above, if a debugger |
| 887 | * has chosen to restart at a different PC, ignore the restart. | 901 | * has chosen to restart at a different PC, ignore the restart. |
| 888 | */ | 902 | */ |
| 889 | if (in_syscall(regs) && regs->pc == restart_addr) { | 903 | if (syscall && regs->pc == restart_addr) { |
| 890 | if (retval == -ERESTART_RESTARTBLOCK) | 904 | if (retval == -ERESTART_RESTARTBLOCK) |
| 891 | setup_restart_syscall(regs); | 905 | setup_restart_syscall(regs); |
| 892 | user_rewind_single_step(current); | 906 | user_rewind_single_step(current); |
| @@ -936,3 +950,28 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, | |||
| 936 | thread_flags = READ_ONCE(current_thread_info()->flags); | 950 | thread_flags = READ_ONCE(current_thread_info()->flags); |
| 937 | } while (thread_flags & _TIF_WORK_MASK); | 951 | } while (thread_flags & _TIF_WORK_MASK); |
| 938 | } | 952 | } |
| 953 | |||
| 954 | unsigned long __ro_after_init signal_minsigstksz; | ||
| 955 | |||
| 956 | /* | ||
| 957 | * Determine the stack space required for guaranteed signal devliery. | ||
| 958 | * This function is used to populate AT_MINSIGSTKSZ at process startup. | ||
| 959 | * cpufeatures setup is assumed to be complete. | ||
| 960 | */ | ||
| 961 | void __init minsigstksz_setup(void) | ||
| 962 | { | ||
| 963 | struct rt_sigframe_user_layout user; | ||
| 964 | |||
| 965 | init_user_layout(&user); | ||
| 966 | |||
| 967 | /* | ||
| 968 | * If this fails, SIGFRAME_MAXSZ needs to be enlarged. It won't | ||
| 969 | * be big enough, but it's our best guess: | ||
| 970 | */ | ||
| 971 | if (WARN_ON(setup_sigframe_layout(&user, true))) | ||
| 972 | return; | ||
| 973 | |||
| 974 | signal_minsigstksz = sigframe_size(&user) + | ||
| 975 | round_up(sizeof(struct frame_record), 16) + | ||
| 976 | 16; /* max alignment padding */ | ||
| 977 | } | ||
diff --git a/arch/arm64/kernel/ssbd.c b/arch/arm64/kernel/ssbd.c new file mode 100644 index 000000000000..3432e5ef9f41 --- /dev/null +++ b/arch/arm64/kernel/ssbd.c | |||
| @@ -0,0 +1,110 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Copyright (C) 2018 ARM Ltd, All Rights Reserved. | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <linux/errno.h> | ||
| 7 | #include <linux/sched.h> | ||
| 8 | #include <linux/thread_info.h> | ||
| 9 | |||
| 10 | #include <asm/cpufeature.h> | ||
| 11 | |||
| 12 | /* | ||
| 13 | * prctl interface for SSBD | ||
| 14 | * FIXME: Drop the below ifdefery once merged in 4.18. | ||
| 15 | */ | ||
| 16 | #ifdef PR_SPEC_STORE_BYPASS | ||
| 17 | static int ssbd_prctl_set(struct task_struct *task, unsigned long ctrl) | ||
| 18 | { | ||
| 19 | int state = arm64_get_ssbd_state(); | ||
| 20 | |||
| 21 | /* Unsupported */ | ||
| 22 | if (state == ARM64_SSBD_UNKNOWN) | ||
| 23 | return -EINVAL; | ||
| 24 | |||
| 25 | /* Treat the unaffected/mitigated state separately */ | ||
| 26 | if (state == ARM64_SSBD_MITIGATED) { | ||
| 27 | switch (ctrl) { | ||
| 28 | case PR_SPEC_ENABLE: | ||
| 29 | return -EPERM; | ||
| 30 | case PR_SPEC_DISABLE: | ||
| 31 | case PR_SPEC_FORCE_DISABLE: | ||
| 32 | return 0; | ||
| 33 | } | ||
| 34 | } | ||
| 35 | |||
| 36 | /* | ||
| 37 | * Things are a bit backward here: the arm64 internal API | ||
| 38 | * *enables the mitigation* when the userspace API *disables | ||
| 39 | * speculation*. So much fun. | ||
| 40 | */ | ||
| 41 | switch (ctrl) { | ||
| 42 | case PR_SPEC_ENABLE: | ||
| 43 | /* If speculation is force disabled, enable is not allowed */ | ||
| 44 | if (state == ARM64_SSBD_FORCE_ENABLE || | ||
| 45 | task_spec_ssb_force_disable(task)) | ||
| 46 | return -EPERM; | ||
| 47 | task_clear_spec_ssb_disable(task); | ||
| 48 | clear_tsk_thread_flag(task, TIF_SSBD); | ||
| 49 | break; | ||
| 50 | case PR_SPEC_DISABLE: | ||
| 51 | if (state == ARM64_SSBD_FORCE_DISABLE) | ||
| 52 | return -EPERM; | ||
| 53 | task_set_spec_ssb_disable(task); | ||
| 54 | set_tsk_thread_flag(task, TIF_SSBD); | ||
| 55 | break; | ||
| 56 | case PR_SPEC_FORCE_DISABLE: | ||
| 57 | if (state == ARM64_SSBD_FORCE_DISABLE) | ||
| 58 | return -EPERM; | ||
| 59 | task_set_spec_ssb_disable(task); | ||
| 60 | task_set_spec_ssb_force_disable(task); | ||
| 61 | set_tsk_thread_flag(task, TIF_SSBD); | ||
| 62 | break; | ||
| 63 | default: | ||
| 64 | return -ERANGE; | ||
| 65 | } | ||
| 66 | |||
| 67 | return 0; | ||
| 68 | } | ||
| 69 | |||
| 70 | int arch_prctl_spec_ctrl_set(struct task_struct *task, unsigned long which, | ||
| 71 | unsigned long ctrl) | ||
| 72 | { | ||
| 73 | switch (which) { | ||
| 74 | case PR_SPEC_STORE_BYPASS: | ||
| 75 | return ssbd_prctl_set(task, ctrl); | ||
| 76 | default: | ||
| 77 | return -ENODEV; | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | static int ssbd_prctl_get(struct task_struct *task) | ||
| 82 | { | ||
| 83 | switch (arm64_get_ssbd_state()) { | ||
| 84 | case ARM64_SSBD_UNKNOWN: | ||
| 85 | return -EINVAL; | ||
| 86 | case ARM64_SSBD_FORCE_ENABLE: | ||
| 87 | return PR_SPEC_DISABLE; | ||
| 88 | case ARM64_SSBD_KERNEL: | ||
| 89 | if (task_spec_ssb_force_disable(task)) | ||
| 90 | return PR_SPEC_PRCTL | PR_SPEC_FORCE_DISABLE; | ||
| 91 | if (task_spec_ssb_disable(task)) | ||
| 92 | return PR_SPEC_PRCTL | PR_SPEC_DISABLE; | ||
| 93 | return PR_SPEC_PRCTL | PR_SPEC_ENABLE; | ||
| 94 | case ARM64_SSBD_FORCE_DISABLE: | ||
| 95 | return PR_SPEC_ENABLE; | ||
| 96 | default: | ||
| 97 | return PR_SPEC_NOT_AFFECTED; | ||
| 98 | } | ||
| 99 | } | ||
| 100 | |||
| 101 | int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which) | ||
| 102 | { | ||
| 103 | switch (which) { | ||
| 104 | case PR_SPEC_STORE_BYPASS: | ||
| 105 | return ssbd_prctl_get(task); | ||
| 106 | default: | ||
| 107 | return -ENODEV; | ||
| 108 | } | ||
| 109 | } | ||
| 110 | #endif /* PR_SPEC_STORE_BYPASS */ | ||
diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c index a307b9e13392..70c283368b64 100644 --- a/arch/arm64/kernel/suspend.c +++ b/arch/arm64/kernel/suspend.c | |||
| @@ -62,6 +62,14 @@ void notrace __cpu_suspend_exit(void) | |||
| 62 | */ | 62 | */ |
| 63 | if (hw_breakpoint_restore) | 63 | if (hw_breakpoint_restore) |
| 64 | hw_breakpoint_restore(cpu); | 64 | hw_breakpoint_restore(cpu); |
| 65 | |||
| 66 | /* | ||
| 67 | * On resume, firmware implementing dynamic mitigation will | ||
| 68 | * have turned the mitigation on. If the user has forcefully | ||
| 69 | * disabled it, make sure their wishes are obeyed. | ||
| 70 | */ | ||
| 71 | if (arm64_get_ssbd_state() == ARM64_SSBD_FORCE_DISABLE) | ||
| 72 | arm64_set_ssbd_mitigation(false); | ||
| 65 | } | 73 | } |
| 66 | 74 | ||
| 67 | /* | 75 | /* |
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c index 21868530018e..f845a8617812 100644 --- a/arch/arm64/kernel/topology.c +++ b/arch/arm64/kernel/topology.c | |||
| @@ -11,7 +11,9 @@ | |||
| 11 | * for more details. | 11 | * for more details. |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #include <linux/acpi.h> | ||
| 14 | #include <linux/arch_topology.h> | 15 | #include <linux/arch_topology.h> |
| 16 | #include <linux/cacheinfo.h> | ||
| 15 | #include <linux/cpu.h> | 17 | #include <linux/cpu.h> |
| 16 | #include <linux/cpumask.h> | 18 | #include <linux/cpumask.h> |
| 17 | #include <linux/init.h> | 19 | #include <linux/init.h> |
| @@ -22,6 +24,7 @@ | |||
| 22 | #include <linux/sched.h> | 24 | #include <linux/sched.h> |
| 23 | #include <linux/sched/topology.h> | 25 | #include <linux/sched/topology.h> |
| 24 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
| 27 | #include <linux/smp.h> | ||
| 25 | #include <linux/string.h> | 28 | #include <linux/string.h> |
| 26 | 29 | ||
| 27 | #include <asm/cpu.h> | 30 | #include <asm/cpu.h> |
| @@ -47,7 +50,7 @@ static int __init get_cpu_for_node(struct device_node *node) | |||
| 47 | return cpu; | 50 | return cpu; |
| 48 | } | 51 | } |
| 49 | 52 | ||
| 50 | static int __init parse_core(struct device_node *core, int cluster_id, | 53 | static int __init parse_core(struct device_node *core, int package_id, |
| 51 | int core_id) | 54 | int core_id) |
| 52 | { | 55 | { |
| 53 | char name[10]; | 56 | char name[10]; |
| @@ -63,7 +66,7 @@ static int __init parse_core(struct device_node *core, int cluster_id, | |||
| 63 | leaf = false; | 66 | leaf = false; |
| 64 | cpu = get_cpu_for_node(t); | 67 | cpu = get_cpu_for_node(t); |
| 65 | if (cpu >= 0) { | 68 | if (cpu >= 0) { |
| 66 | cpu_topology[cpu].cluster_id = cluster_id; | 69 | cpu_topology[cpu].package_id = package_id; |
| 67 | cpu_topology[cpu].core_id = core_id; | 70 | cpu_topology[cpu].core_id = core_id; |
| 68 | cpu_topology[cpu].thread_id = i; | 71 | cpu_topology[cpu].thread_id = i; |
| 69 | } else { | 72 | } else { |
| @@ -85,7 +88,7 @@ static int __init parse_core(struct device_node *core, int cluster_id, | |||
| 85 | return -EINVAL; | 88 | return -EINVAL; |
| 86 | } | 89 | } |
| 87 | 90 | ||
| 88 | cpu_topology[cpu].cluster_id = cluster_id; | 91 | cpu_topology[cpu].package_id = package_id; |
| 89 | cpu_topology[cpu].core_id = core_id; | 92 | cpu_topology[cpu].core_id = core_id; |
| 90 | } else if (leaf) { | 93 | } else if (leaf) { |
| 91 | pr_err("%pOF: Can't get CPU for leaf core\n", core); | 94 | pr_err("%pOF: Can't get CPU for leaf core\n", core); |
| @@ -101,7 +104,7 @@ static int __init parse_cluster(struct device_node *cluster, int depth) | |||
| 101 | bool leaf = true; | 104 | bool leaf = true; |
| 102 | bool has_cores = false; | 105 | bool has_cores = false; |
| 103 | struct device_node *c; | 106 | struct device_node *c; |
| 104 | static int cluster_id __initdata; | 107 | static int package_id __initdata; |
| 105 | int core_id = 0; | 108 | int core_id = 0; |
| 106 | int i, ret; | 109 | int i, ret; |
| 107 | 110 | ||
| @@ -140,7 +143,7 @@ static int __init parse_cluster(struct device_node *cluster, int depth) | |||
| 140 | } | 143 | } |
| 141 | 144 | ||
| 142 | if (leaf) { | 145 | if (leaf) { |
| 143 | ret = parse_core(c, cluster_id, core_id++); | 146 | ret = parse_core(c, package_id, core_id++); |
| 144 | } else { | 147 | } else { |
| 145 | pr_err("%pOF: Non-leaf cluster with core %s\n", | 148 | pr_err("%pOF: Non-leaf cluster with core %s\n", |
| 146 | cluster, name); | 149 | cluster, name); |
| @@ -158,7 +161,7 @@ static int __init parse_cluster(struct device_node *cluster, int depth) | |||
| 158 | pr_warn("%pOF: empty cluster\n", cluster); | 161 | pr_warn("%pOF: empty cluster\n", cluster); |
| 159 | 162 | ||
| 160 | if (leaf) | 163 | if (leaf) |
| 161 | cluster_id++; | 164 | package_id++; |
| 162 | 165 | ||
| 163 | return 0; | 166 | return 0; |
| 164 | } | 167 | } |
| @@ -194,7 +197,7 @@ static int __init parse_dt_topology(void) | |||
| 194 | * only mark cores described in the DT as possible. | 197 | * only mark cores described in the DT as possible. |
| 195 | */ | 198 | */ |
| 196 | for_each_possible_cpu(cpu) | 199 | for_each_possible_cpu(cpu) |
| 197 | if (cpu_topology[cpu].cluster_id == -1) | 200 | if (cpu_topology[cpu].package_id == -1) |
| 198 | ret = -EINVAL; | 201 | ret = -EINVAL; |
| 199 | 202 | ||
| 200 | out_map: | 203 | out_map: |
| @@ -212,7 +215,14 @@ EXPORT_SYMBOL_GPL(cpu_topology); | |||
| 212 | 215 | ||
| 213 | const struct cpumask *cpu_coregroup_mask(int cpu) | 216 | const struct cpumask *cpu_coregroup_mask(int cpu) |
| 214 | { | 217 | { |
| 215 | return &cpu_topology[cpu].core_sibling; | 218 | const cpumask_t *core_mask = &cpu_topology[cpu].core_sibling; |
| 219 | |||
| 220 | if (cpu_topology[cpu].llc_id != -1) { | ||
| 221 | if (cpumask_subset(&cpu_topology[cpu].llc_siblings, core_mask)) | ||
| 222 | core_mask = &cpu_topology[cpu].llc_siblings; | ||
| 223 | } | ||
| 224 | |||
| 225 | return core_mask; | ||
| 216 | } | 226 | } |
| 217 | 227 | ||
| 218 | static void update_siblings_masks(unsigned int cpuid) | 228 | static void update_siblings_masks(unsigned int cpuid) |
| @@ -224,7 +234,12 @@ static void update_siblings_masks(unsigned int cpuid) | |||
| 224 | for_each_possible_cpu(cpu) { | 234 | for_each_possible_cpu(cpu) { |
| 225 | cpu_topo = &cpu_topology[cpu]; | 235 | cpu_topo = &cpu_topology[cpu]; |
| 226 | 236 | ||
| 227 | if (cpuid_topo->cluster_id != cpu_topo->cluster_id) | 237 | if (cpuid_topo->llc_id == cpu_topo->llc_id) { |
| 238 | cpumask_set_cpu(cpu, &cpuid_topo->llc_siblings); | ||
| 239 | cpumask_set_cpu(cpuid, &cpu_topo->llc_siblings); | ||
| 240 | } | ||
| 241 | |||
| 242 | if (cpuid_topo->package_id != cpu_topo->package_id) | ||
| 228 | continue; | 243 | continue; |
| 229 | 244 | ||
| 230 | cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); | 245 | cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); |
| @@ -245,7 +260,7 @@ void store_cpu_topology(unsigned int cpuid) | |||
| 245 | struct cpu_topology *cpuid_topo = &cpu_topology[cpuid]; | 260 | struct cpu_topology *cpuid_topo = &cpu_topology[cpuid]; |
| 246 | u64 mpidr; | 261 | u64 mpidr; |
| 247 | 262 | ||
| 248 | if (cpuid_topo->cluster_id != -1) | 263 | if (cpuid_topo->package_id != -1) |
| 249 | goto topology_populated; | 264 | goto topology_populated; |
| 250 | 265 | ||
| 251 | mpidr = read_cpuid_mpidr(); | 266 | mpidr = read_cpuid_mpidr(); |
| @@ -259,19 +274,19 @@ void store_cpu_topology(unsigned int cpuid) | |||
| 259 | /* Multiprocessor system : Multi-threads per core */ | 274 | /* Multiprocessor system : Multi-threads per core */ |
| 260 | cpuid_topo->thread_id = MPIDR_AFFINITY_LEVEL(mpidr, 0); | 275 | cpuid_topo->thread_id = MPIDR_AFFINITY_LEVEL(mpidr, 0); |
| 261 | cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 1); | 276 | cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 1); |
| 262 | cpuid_topo->cluster_id = MPIDR_AFFINITY_LEVEL(mpidr, 2) | | 277 | cpuid_topo->package_id = MPIDR_AFFINITY_LEVEL(mpidr, 2) | |
| 263 | MPIDR_AFFINITY_LEVEL(mpidr, 3) << 8; | 278 | MPIDR_AFFINITY_LEVEL(mpidr, 3) << 8; |
| 264 | } else { | 279 | } else { |
| 265 | /* Multiprocessor system : Single-thread per core */ | 280 | /* Multiprocessor system : Single-thread per core */ |
| 266 | cpuid_topo->thread_id = -1; | 281 | cpuid_topo->thread_id = -1; |
| 267 | cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0); | 282 | cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0); |
| 268 | cpuid_topo->cluster_id = MPIDR_AFFINITY_LEVEL(mpidr, 1) | | 283 | cpuid_topo->package_id = MPIDR_AFFINITY_LEVEL(mpidr, 1) | |
| 269 | MPIDR_AFFINITY_LEVEL(mpidr, 2) << 8 | | 284 | MPIDR_AFFINITY_LEVEL(mpidr, 2) << 8 | |
| 270 | MPIDR_AFFINITY_LEVEL(mpidr, 3) << 16; | 285 | MPIDR_AFFINITY_LEVEL(mpidr, 3) << 16; |
| 271 | } | 286 | } |
| 272 | 287 | ||
| 273 | pr_debug("CPU%u: cluster %d core %d thread %d mpidr %#016llx\n", | 288 | pr_debug("CPU%u: cluster %d core %d thread %d mpidr %#016llx\n", |
| 274 | cpuid, cpuid_topo->cluster_id, cpuid_topo->core_id, | 289 | cpuid, cpuid_topo->package_id, cpuid_topo->core_id, |
| 275 | cpuid_topo->thread_id, mpidr); | 290 | cpuid_topo->thread_id, mpidr); |
| 276 | 291 | ||
| 277 | topology_populated: | 292 | topology_populated: |
| @@ -287,7 +302,11 @@ static void __init reset_cpu_topology(void) | |||
| 287 | 302 | ||
| 288 | cpu_topo->thread_id = -1; | 303 | cpu_topo->thread_id = -1; |
| 289 | cpu_topo->core_id = 0; | 304 | cpu_topo->core_id = 0; |
| 290 | cpu_topo->cluster_id = -1; | 305 | cpu_topo->package_id = -1; |
| 306 | |||
| 307 | cpu_topo->llc_id = -1; | ||
| 308 | cpumask_clear(&cpu_topo->llc_siblings); | ||
| 309 | cpumask_set_cpu(cpu, &cpu_topo->llc_siblings); | ||
| 291 | 310 | ||
| 292 | cpumask_clear(&cpu_topo->core_sibling); | 311 | cpumask_clear(&cpu_topo->core_sibling); |
| 293 | cpumask_set_cpu(cpu, &cpu_topo->core_sibling); | 312 | cpumask_set_cpu(cpu, &cpu_topo->core_sibling); |
| @@ -296,6 +315,59 @@ static void __init reset_cpu_topology(void) | |||
| 296 | } | 315 | } |
| 297 | } | 316 | } |
| 298 | 317 | ||
| 318 | #ifdef CONFIG_ACPI | ||
| 319 | /* | ||
| 320 | * Propagate the topology information of the processor_topology_node tree to the | ||
| 321 | * cpu_topology array. | ||
| 322 | */ | ||
| 323 | static int __init parse_acpi_topology(void) | ||
| 324 | { | ||
| 325 | bool is_threaded; | ||
| 326 | int cpu, topology_id; | ||
| 327 | |||
| 328 | is_threaded = read_cpuid_mpidr() & MPIDR_MT_BITMASK; | ||
| 329 | |||
| 330 | for_each_possible_cpu(cpu) { | ||
| 331 | int i, cache_id; | ||
| 332 | |||
| 333 | topology_id = find_acpi_cpu_topology(cpu, 0); | ||
| 334 | if (topology_id < 0) | ||
| 335 | return topology_id; | ||
| 336 | |||
| 337 | if (is_threaded) { | ||
| 338 | cpu_topology[cpu].thread_id = topology_id; | ||
| 339 | topology_id = find_acpi_cpu_topology(cpu, 1); | ||
| 340 | cpu_topology[cpu].core_id = topology_id; | ||
| 341 | } else { | ||
| 342 | cpu_topology[cpu].thread_id = -1; | ||
| 343 | cpu_topology[cpu].core_id = topology_id; | ||
| 344 | } | ||
| 345 | topology_id = find_acpi_cpu_topology_package(cpu); | ||
| 346 | cpu_topology[cpu].package_id = topology_id; | ||
| 347 | |||
| 348 | i = acpi_find_last_cache_level(cpu); | ||
| 349 | |||
| 350 | if (i > 0) { | ||
| 351 | /* | ||
| 352 | * this is the only part of cpu_topology that has | ||
| 353 | * a direct relationship with the cache topology | ||
| 354 | */ | ||
| 355 | cache_id = find_acpi_cpu_cache_topology(cpu, i); | ||
| 356 | if (cache_id > 0) | ||
| 357 | cpu_topology[cpu].llc_id = cache_id; | ||
| 358 | } | ||
| 359 | } | ||
| 360 | |||
| 361 | return 0; | ||
| 362 | } | ||
| 363 | |||
| 364 | #else | ||
| 365 | static inline int __init parse_acpi_topology(void) | ||
| 366 | { | ||
| 367 | return -EINVAL; | ||
| 368 | } | ||
| 369 | #endif | ||
| 370 | |||
| 299 | void __init init_cpu_topology(void) | 371 | void __init init_cpu_topology(void) |
| 300 | { | 372 | { |
| 301 | reset_cpu_topology(); | 373 | reset_cpu_topology(); |
| @@ -304,6 +376,8 @@ void __init init_cpu_topology(void) | |||
| 304 | * Discard anything that was parsed if we hit an error so we | 376 | * Discard anything that was parsed if we hit an error so we |
| 305 | * don't use partial information. | 377 | * don't use partial information. |
| 306 | */ | 378 | */ |
| 307 | if (of_have_populated_dt() && parse_dt_topology()) | 379 | if (!acpi_disabled && parse_acpi_topology()) |
| 380 | reset_cpu_topology(); | ||
| 381 | else if (of_have_populated_dt() && parse_dt_topology()) | ||
| 308 | reset_cpu_topology(); | 382 | reset_cpu_topology(); |
| 309 | } | 383 | } |
diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index 0221aca6493d..605d1b60469c 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S | |||
| @@ -34,25 +34,25 @@ jiffies = jiffies_64; | |||
| 34 | * 4 KB (see related ASSERT() below) \ | 34 | * 4 KB (see related ASSERT() below) \ |
| 35 | */ \ | 35 | */ \ |
| 36 | . = ALIGN(SZ_4K); \ | 36 | . = ALIGN(SZ_4K); \ |
| 37 | VMLINUX_SYMBOL(__hyp_idmap_text_start) = .; \ | 37 | __hyp_idmap_text_start = .; \ |
| 38 | *(.hyp.idmap.text) \ | 38 | *(.hyp.idmap.text) \ |
| 39 | VMLINUX_SYMBOL(__hyp_idmap_text_end) = .; \ | 39 | __hyp_idmap_text_end = .; \ |
| 40 | VMLINUX_SYMBOL(__hyp_text_start) = .; \ | 40 | __hyp_text_start = .; \ |
| 41 | *(.hyp.text) \ | 41 | *(.hyp.text) \ |
| 42 | VMLINUX_SYMBOL(__hyp_text_end) = .; | 42 | __hyp_text_end = .; |
| 43 | 43 | ||
| 44 | #define IDMAP_TEXT \ | 44 | #define IDMAP_TEXT \ |
| 45 | . = ALIGN(SZ_4K); \ | 45 | . = ALIGN(SZ_4K); \ |
| 46 | VMLINUX_SYMBOL(__idmap_text_start) = .; \ | 46 | __idmap_text_start = .; \ |
| 47 | *(.idmap.text) \ | 47 | *(.idmap.text) \ |
| 48 | VMLINUX_SYMBOL(__idmap_text_end) = .; | 48 | __idmap_text_end = .; |
| 49 | 49 | ||
| 50 | #ifdef CONFIG_HIBERNATION | 50 | #ifdef CONFIG_HIBERNATION |
| 51 | #define HIBERNATE_TEXT \ | 51 | #define HIBERNATE_TEXT \ |
| 52 | . = ALIGN(SZ_4K); \ | 52 | . = ALIGN(SZ_4K); \ |
| 53 | VMLINUX_SYMBOL(__hibernate_exit_text_start) = .;\ | 53 | __hibernate_exit_text_start = .; \ |
| 54 | *(.hibernate_exit.text) \ | 54 | *(.hibernate_exit.text) \ |
| 55 | VMLINUX_SYMBOL(__hibernate_exit_text_end) = .; | 55 | __hibernate_exit_text_end = .; |
| 56 | #else | 56 | #else |
| 57 | #define HIBERNATE_TEXT | 57 | #define HIBERNATE_TEXT |
| 58 | #endif | 58 | #endif |
| @@ -60,10 +60,10 @@ jiffies = jiffies_64; | |||
| 60 | #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 | 60 | #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 |
| 61 | #define TRAMP_TEXT \ | 61 | #define TRAMP_TEXT \ |
| 62 | . = ALIGN(PAGE_SIZE); \ | 62 | . = ALIGN(PAGE_SIZE); \ |
| 63 | VMLINUX_SYMBOL(__entry_tramp_text_start) = .; \ | 63 | __entry_tramp_text_start = .; \ |
| 64 | *(.entry.tramp.text) \ | 64 | *(.entry.tramp.text) \ |
| 65 | . = ALIGN(PAGE_SIZE); \ | 65 | . = ALIGN(PAGE_SIZE); \ |
| 66 | VMLINUX_SYMBOL(__entry_tramp_text_end) = .; | 66 | __entry_tramp_text_end = .; |
| 67 | #else | 67 | #else |
| 68 | #define TRAMP_TEXT | 68 | #define TRAMP_TEXT |
| 69 | #endif | 69 | #endif |
diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S index bffece27b5c1..05d836979032 100644 --- a/arch/arm64/kvm/hyp/hyp-entry.S +++ b/arch/arm64/kvm/hyp/hyp-entry.S | |||
| @@ -106,8 +106,44 @@ el1_hvc_guest: | |||
| 106 | */ | 106 | */ |
| 107 | ldr x1, [sp] // Guest's x0 | 107 | ldr x1, [sp] // Guest's x0 |
| 108 | eor w1, w1, #ARM_SMCCC_ARCH_WORKAROUND_1 | 108 | eor w1, w1, #ARM_SMCCC_ARCH_WORKAROUND_1 |
| 109 | cbz w1, wa_epilogue | ||
| 110 | |||
| 111 | /* ARM_SMCCC_ARCH_WORKAROUND_2 handling */ | ||
| 112 | eor w1, w1, #(ARM_SMCCC_ARCH_WORKAROUND_1 ^ \ | ||
| 113 | ARM_SMCCC_ARCH_WORKAROUND_2) | ||
| 109 | cbnz w1, el1_trap | 114 | cbnz w1, el1_trap |
| 110 | mov x0, x1 | 115 | |
| 116 | #ifdef CONFIG_ARM64_SSBD | ||
| 117 | alternative_cb arm64_enable_wa2_handling | ||
| 118 | b wa2_end | ||
| 119 | alternative_cb_end | ||
| 120 | get_vcpu_ptr x2, x0 | ||
| 121 | ldr x0, [x2, #VCPU_WORKAROUND_FLAGS] | ||
| 122 | |||
| 123 | // Sanitize the argument and update the guest flags | ||
| 124 | ldr x1, [sp, #8] // Guest's x1 | ||
| 125 | clz w1, w1 // Murphy's device: | ||
| 126 | lsr w1, w1, #5 // w1 = !!w1 without using | ||
| 127 | eor w1, w1, #1 // the flags... | ||
| 128 | bfi x0, x1, #VCPU_WORKAROUND_2_FLAG_SHIFT, #1 | ||
| 129 | str x0, [x2, #VCPU_WORKAROUND_FLAGS] | ||
| 130 | |||
| 131 | /* Check that we actually need to perform the call */ | ||
| 132 | hyp_ldr_this_cpu x0, arm64_ssbd_callback_required, x2 | ||
| 133 | cbz x0, wa2_end | ||
| 134 | |||
| 135 | mov w0, #ARM_SMCCC_ARCH_WORKAROUND_2 | ||
| 136 | smc #0 | ||
| 137 | |||
| 138 | /* Don't leak data from the SMC call */ | ||
| 139 | mov x3, xzr | ||
| 140 | wa2_end: | ||
| 141 | mov x2, xzr | ||
| 142 | mov x1, xzr | ||
| 143 | #endif | ||
| 144 | |||
| 145 | wa_epilogue: | ||
| 146 | mov x0, xzr | ||
| 111 | add sp, sp, #16 | 147 | add sp, sp, #16 |
| 112 | eret | 148 | eret |
| 113 | 149 | ||
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index d9645236e474..c50cedc447f1 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 15 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 16 | */ | 16 | */ |
| 17 | 17 | ||
| 18 | #include <linux/arm-smccc.h> | ||
| 18 | #include <linux/types.h> | 19 | #include <linux/types.h> |
| 19 | #include <linux/jump_label.h> | 20 | #include <linux/jump_label.h> |
| 20 | #include <uapi/linux/psci.h> | 21 | #include <uapi/linux/psci.h> |
| @@ -389,6 +390,39 @@ static bool __hyp_text fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code) | |||
| 389 | return false; | 390 | return false; |
| 390 | } | 391 | } |
| 391 | 392 | ||
| 393 | static inline bool __hyp_text __needs_ssbd_off(struct kvm_vcpu *vcpu) | ||
| 394 | { | ||
| 395 | if (!cpus_have_const_cap(ARM64_SSBD)) | ||
| 396 | return false; | ||
| 397 | |||
| 398 | return !(vcpu->arch.workaround_flags & VCPU_WORKAROUND_2_FLAG); | ||
| 399 | } | ||
| 400 | |||
| 401 | static void __hyp_text __set_guest_arch_workaround_state(struct kvm_vcpu *vcpu) | ||
| 402 | { | ||
| 403 | #ifdef CONFIG_ARM64_SSBD | ||
| 404 | /* | ||
| 405 | * The host runs with the workaround always present. If the | ||
| 406 | * guest wants it disabled, so be it... | ||
| 407 | */ | ||
| 408 | if (__needs_ssbd_off(vcpu) && | ||
| 409 | __hyp_this_cpu_read(arm64_ssbd_callback_required)) | ||
| 410 | arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2, 0, NULL); | ||
| 411 | #endif | ||
| 412 | } | ||
| 413 | |||
| 414 | static void __hyp_text __set_host_arch_workaround_state(struct kvm_vcpu *vcpu) | ||
| 415 | { | ||
| 416 | #ifdef CONFIG_ARM64_SSBD | ||
| 417 | /* | ||
| 418 | * If the guest has disabled the workaround, bring it back on. | ||
| 419 | */ | ||
| 420 | if (__needs_ssbd_off(vcpu) && | ||
| 421 | __hyp_this_cpu_read(arm64_ssbd_callback_required)) | ||
| 422 | arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_2, 1, NULL); | ||
| 423 | #endif | ||
| 424 | } | ||
| 425 | |||
| 392 | /* Switch to the guest for VHE systems running in EL2 */ | 426 | /* Switch to the guest for VHE systems running in EL2 */ |
| 393 | int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) | 427 | int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) |
| 394 | { | 428 | { |
| @@ -409,6 +443,8 @@ int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) | |||
| 409 | sysreg_restore_guest_state_vhe(guest_ctxt); | 443 | sysreg_restore_guest_state_vhe(guest_ctxt); |
| 410 | __debug_switch_to_guest(vcpu); | 444 | __debug_switch_to_guest(vcpu); |
| 411 | 445 | ||
| 446 | __set_guest_arch_workaround_state(vcpu); | ||
| 447 | |||
| 412 | do { | 448 | do { |
| 413 | /* Jump in the fire! */ | 449 | /* Jump in the fire! */ |
| 414 | exit_code = __guest_enter(vcpu, host_ctxt); | 450 | exit_code = __guest_enter(vcpu, host_ctxt); |
| @@ -416,6 +452,8 @@ int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu) | |||
| 416 | /* And we're baaack! */ | 452 | /* And we're baaack! */ |
| 417 | } while (fixup_guest_exit(vcpu, &exit_code)); | 453 | } while (fixup_guest_exit(vcpu, &exit_code)); |
| 418 | 454 | ||
| 455 | __set_host_arch_workaround_state(vcpu); | ||
| 456 | |||
| 419 | fp_enabled = fpsimd_enabled_vhe(); | 457 | fp_enabled = fpsimd_enabled_vhe(); |
| 420 | 458 | ||
| 421 | sysreg_save_guest_state_vhe(guest_ctxt); | 459 | sysreg_save_guest_state_vhe(guest_ctxt); |
| @@ -465,6 +503,8 @@ int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu) | |||
| 465 | __sysreg_restore_state_nvhe(guest_ctxt); | 503 | __sysreg_restore_state_nvhe(guest_ctxt); |
| 466 | __debug_switch_to_guest(vcpu); | 504 | __debug_switch_to_guest(vcpu); |
| 467 | 505 | ||
| 506 | __set_guest_arch_workaround_state(vcpu); | ||
| 507 | |||
| 468 | do { | 508 | do { |
| 469 | /* Jump in the fire! */ | 509 | /* Jump in the fire! */ |
| 470 | exit_code = __guest_enter(vcpu, host_ctxt); | 510 | exit_code = __guest_enter(vcpu, host_ctxt); |
| @@ -472,6 +512,8 @@ int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu) | |||
| 472 | /* And we're baaack! */ | 512 | /* And we're baaack! */ |
| 473 | } while (fixup_guest_exit(vcpu, &exit_code)); | 513 | } while (fixup_guest_exit(vcpu, &exit_code)); |
| 474 | 514 | ||
| 515 | __set_host_arch_workaround_state(vcpu); | ||
| 516 | |||
| 475 | fp_enabled = __fpsimd_enabled_nvhe(); | 517 | fp_enabled = __fpsimd_enabled_nvhe(); |
| 476 | 518 | ||
| 477 | __sysreg_save_state_nvhe(guest_ctxt); | 519 | __sysreg_save_state_nvhe(guest_ctxt); |
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index 3256b9228e75..a74311beda35 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c | |||
| @@ -122,6 +122,10 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) | |||
| 122 | /* Reset PMU */ | 122 | /* Reset PMU */ |
| 123 | kvm_pmu_vcpu_reset(vcpu); | 123 | kvm_pmu_vcpu_reset(vcpu); |
| 124 | 124 | ||
| 125 | /* Default workaround setup is enabled (if supported) */ | ||
| 126 | if (kvm_arm_have_ssbd() == KVM_SSBD_KERNEL) | ||
| 127 | vcpu->arch.workaround_flags |= VCPU_WORKAROUND_2_FLAG; | ||
| 128 | |||
| 125 | /* Reset timer */ | 129 | /* Reset timer */ |
| 126 | return kvm_timer_vcpu_reset(vcpu); | 130 | return kvm_timer_vcpu_reset(vcpu); |
| 127 | } | 131 | } |
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c index db01f2709842..49e217ac7e1e 100644 --- a/arch/arm64/mm/dma-mapping.c +++ b/arch/arm64/mm/dma-mapping.c | |||
| @@ -504,6 +504,11 @@ static int __init arm64_dma_init(void) | |||
| 504 | max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT)) | 504 | max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT)) |
| 505 | swiotlb = 1; | 505 | swiotlb = 1; |
| 506 | 506 | ||
| 507 | WARN_TAINT(ARCH_DMA_MINALIGN < cache_line_size(), | ||
| 508 | TAINT_CPU_OUT_OF_SPEC, | ||
| 509 | "ARCH_DMA_MINALIGN smaller than CTR_EL0.CWG (%d < %d)", | ||
| 510 | ARCH_DMA_MINALIGN, cache_line_size()); | ||
| 511 | |||
| 507 | return atomic_pool_init(); | 512 | return atomic_pool_init(); |
| 508 | } | 513 | } |
| 509 | arch_initcall(arm64_dma_init); | 514 | arch_initcall(arm64_dma_init); |
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 576f15153080..b8eecc7b9531 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c | |||
| @@ -235,8 +235,9 @@ static bool is_el1_instruction_abort(unsigned int esr) | |||
| 235 | return ESR_ELx_EC(esr) == ESR_ELx_EC_IABT_CUR; | 235 | return ESR_ELx_EC(esr) == ESR_ELx_EC_IABT_CUR; |
| 236 | } | 236 | } |
| 237 | 237 | ||
| 238 | static inline bool is_permission_fault(unsigned int esr, struct pt_regs *regs, | 238 | static inline bool is_el1_permission_fault(unsigned int esr, |
| 239 | unsigned long addr) | 239 | struct pt_regs *regs, |
| 240 | unsigned long addr) | ||
| 240 | { | 241 | { |
| 241 | unsigned int ec = ESR_ELx_EC(esr); | 242 | unsigned int ec = ESR_ELx_EC(esr); |
| 242 | unsigned int fsc_type = esr & ESR_ELx_FSC_TYPE; | 243 | unsigned int fsc_type = esr & ESR_ELx_FSC_TYPE; |
| @@ -254,6 +255,22 @@ static inline bool is_permission_fault(unsigned int esr, struct pt_regs *regs, | |||
| 254 | return false; | 255 | return false; |
| 255 | } | 256 | } |
| 256 | 257 | ||
| 258 | static void die_kernel_fault(const char *msg, unsigned long addr, | ||
| 259 | unsigned int esr, struct pt_regs *regs) | ||
| 260 | { | ||
| 261 | bust_spinlocks(1); | ||
| 262 | |||
| 263 | pr_alert("Unable to handle kernel %s at virtual address %016lx\n", msg, | ||
| 264 | addr); | ||
| 265 | |||
| 266 | mem_abort_decode(esr); | ||
| 267 | |||
| 268 | show_pte(addr); | ||
| 269 | die("Oops", regs, esr); | ||
| 270 | bust_spinlocks(0); | ||
| 271 | do_exit(SIGKILL); | ||
| 272 | } | ||
| 273 | |||
| 257 | static void __do_kernel_fault(unsigned long addr, unsigned int esr, | 274 | static void __do_kernel_fault(unsigned long addr, unsigned int esr, |
| 258 | struct pt_regs *regs) | 275 | struct pt_regs *regs) |
| 259 | { | 276 | { |
| @@ -266,9 +283,7 @@ static void __do_kernel_fault(unsigned long addr, unsigned int esr, | |||
| 266 | if (!is_el1_instruction_abort(esr) && fixup_exception(regs)) | 283 | if (!is_el1_instruction_abort(esr) && fixup_exception(regs)) |
| 267 | return; | 284 | return; |
| 268 | 285 | ||
| 269 | bust_spinlocks(1); | 286 | if (is_el1_permission_fault(esr, regs, addr)) { |
| 270 | |||
| 271 | if (is_permission_fault(esr, regs, addr)) { | ||
| 272 | if (esr & ESR_ELx_WNR) | 287 | if (esr & ESR_ELx_WNR) |
| 273 | msg = "write to read-only memory"; | 288 | msg = "write to read-only memory"; |
| 274 | else | 289 | else |
| @@ -279,15 +294,7 @@ static void __do_kernel_fault(unsigned long addr, unsigned int esr, | |||
| 279 | msg = "paging request"; | 294 | msg = "paging request"; |
| 280 | } | 295 | } |
| 281 | 296 | ||
| 282 | pr_alert("Unable to handle kernel %s at virtual address %08lx\n", msg, | 297 | die_kernel_fault(msg, addr, esr, regs); |
| 283 | addr); | ||
| 284 | |||
| 285 | mem_abort_decode(esr); | ||
| 286 | |||
| 287 | show_pte(addr); | ||
| 288 | die("Oops", regs, esr); | ||
| 289 | bust_spinlocks(0); | ||
| 290 | do_exit(SIGKILL); | ||
| 291 | } | 298 | } |
| 292 | 299 | ||
| 293 | static void __do_user_fault(struct siginfo *info, unsigned int esr) | 300 | static void __do_user_fault(struct siginfo *info, unsigned int esr) |
| @@ -447,16 +454,19 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, | |||
| 447 | mm_flags |= FAULT_FLAG_WRITE; | 454 | mm_flags |= FAULT_FLAG_WRITE; |
| 448 | } | 455 | } |
| 449 | 456 | ||
| 450 | if (addr < TASK_SIZE && is_permission_fault(esr, regs, addr)) { | 457 | if (addr < TASK_SIZE && is_el1_permission_fault(esr, regs, addr)) { |
| 451 | /* regs->orig_addr_limit may be 0 if we entered from EL0 */ | 458 | /* regs->orig_addr_limit may be 0 if we entered from EL0 */ |
| 452 | if (regs->orig_addr_limit == KERNEL_DS) | 459 | if (regs->orig_addr_limit == KERNEL_DS) |
| 453 | die("Accessing user space memory with fs=KERNEL_DS", regs, esr); | 460 | die_kernel_fault("access to user memory with fs=KERNEL_DS", |
| 461 | addr, esr, regs); | ||
| 454 | 462 | ||
| 455 | if (is_el1_instruction_abort(esr)) | 463 | if (is_el1_instruction_abort(esr)) |
| 456 | die("Attempting to execute userspace memory", regs, esr); | 464 | die_kernel_fault("execution of user memory", |
| 465 | addr, esr, regs); | ||
| 457 | 466 | ||
| 458 | if (!search_exception_tables(regs->pc)) | 467 | if (!search_exception_tables(regs->pc)) |
| 459 | die("Accessing user space memory outside uaccess.h routines", regs, esr); | 468 | die_kernel_fault("access to user memory outside uaccess routines", |
| 469 | addr, esr, regs); | ||
| 460 | } | 470 | } |
| 461 | 471 | ||
| 462 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, addr); | 472 | perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, addr); |
diff --git a/arch/riscv/kernel/cacheinfo.c b/arch/riscv/kernel/cacheinfo.c index 10ed2749e246..0bc86e5f8f3f 100644 --- a/arch/riscv/kernel/cacheinfo.c +++ b/arch/riscv/kernel/cacheinfo.c | |||
| @@ -20,7 +20,6 @@ static void ci_leaf_init(struct cacheinfo *this_leaf, | |||
| 20 | struct device_node *node, | 20 | struct device_node *node, |
| 21 | enum cache_type type, unsigned int level) | 21 | enum cache_type type, unsigned int level) |
| 22 | { | 22 | { |
| 23 | this_leaf->of_node = node; | ||
| 24 | this_leaf->level = level; | 23 | this_leaf->level = level; |
| 25 | this_leaf->type = type; | 24 | this_leaf->type = type; |
| 26 | /* not a sector cache */ | 25 | /* not a sector cache */ |
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 516d7b36d6fb..b533eeb6139d 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig | |||
| @@ -547,6 +547,9 @@ config ACPI_CONFIGFS | |||
| 547 | 547 | ||
| 548 | if ARM64 | 548 | if ARM64 |
| 549 | source "drivers/acpi/arm64/Kconfig" | 549 | source "drivers/acpi/arm64/Kconfig" |
| 550 | |||
| 551 | config ACPI_PPTT | ||
| 552 | bool | ||
| 550 | endif | 553 | endif |
| 551 | 554 | ||
| 552 | config TPS68470_PMIC_OPREGION | 555 | config TPS68470_PMIC_OPREGION |
diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 48e202752754..6d59aa109a91 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile | |||
| @@ -88,6 +88,7 @@ obj-$(CONFIG_ACPI_BGRT) += bgrt.o | |||
| 88 | obj-$(CONFIG_ACPI_CPPC_LIB) += cppc_acpi.o | 88 | obj-$(CONFIG_ACPI_CPPC_LIB) += cppc_acpi.o |
| 89 | obj-$(CONFIG_ACPI_SPCR_TABLE) += spcr.o | 89 | obj-$(CONFIG_ACPI_SPCR_TABLE) += spcr.o |
| 90 | obj-$(CONFIG_ACPI_DEBUGGER_USER) += acpi_dbg.o | 90 | obj-$(CONFIG_ACPI_DEBUGGER_USER) += acpi_dbg.o |
| 91 | obj-$(CONFIG_ACPI_PPTT) += pptt.o | ||
| 91 | 92 | ||
| 92 | # processor has its own "processor." module_param namespace | 93 | # processor has its own "processor." module_param namespace |
| 93 | processor-y := processor_driver.o | 94 | processor-y := processor_driver.o |
diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c new file mode 100644 index 000000000000..e5ea1974d1e3 --- /dev/null +++ b/drivers/acpi/pptt.c | |||
| @@ -0,0 +1,655 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * pptt.c - parsing of Processor Properties Topology Table (PPTT) | ||
| 4 | * | ||
| 5 | * Copyright (C) 2018, ARM | ||
| 6 | * | ||
| 7 | * This file implements parsing of the Processor Properties Topology Table | ||
| 8 | * which is optionally used to describe the processor and cache topology. | ||
| 9 | * Due to the relative pointers used throughout the table, this doesn't | ||
| 10 | * leverage the existing subtable parsing in the kernel. | ||
| 11 | * | ||
| 12 | * The PPTT structure is an inverted tree, with each node potentially | ||
| 13 | * holding one or two inverted tree data structures describing | ||
| 14 | * the caches available at that level. Each cache structure optionally | ||
| 15 | * contains properties describing the cache at a given level which can be | ||
| 16 | * used to override hardware probed values. | ||
| 17 | */ | ||
| 18 | #define pr_fmt(fmt) "ACPI PPTT: " fmt | ||
| 19 | |||
| 20 | #include <linux/acpi.h> | ||
| 21 | #include <linux/cacheinfo.h> | ||
| 22 | #include <acpi/processor.h> | ||
| 23 | |||
| 24 | static struct acpi_subtable_header *fetch_pptt_subtable(struct acpi_table_header *table_hdr, | ||
| 25 | u32 pptt_ref) | ||
| 26 | { | ||
| 27 | struct acpi_subtable_header *entry; | ||
| 28 | |||
| 29 | /* there isn't a subtable at reference 0 */ | ||
| 30 | if (pptt_ref < sizeof(struct acpi_subtable_header)) | ||
| 31 | return NULL; | ||
| 32 | |||
| 33 | if (pptt_ref + sizeof(struct acpi_subtable_header) > table_hdr->length) | ||
| 34 | return NULL; | ||
| 35 | |||
| 36 | entry = ACPI_ADD_PTR(struct acpi_subtable_header, table_hdr, pptt_ref); | ||
| 37 | |||
| 38 | if (entry->length == 0) | ||
| 39 | return NULL; | ||
| 40 | |||
| 41 | if (pptt_ref + entry->length > table_hdr->length) | ||
| 42 | return NULL; | ||
| 43 | |||
| 44 | return entry; | ||
| 45 | } | ||
| 46 | |||
| 47 | static struct acpi_pptt_processor *fetch_pptt_node(struct acpi_table_header *table_hdr, | ||
| 48 | u32 pptt_ref) | ||
| 49 | { | ||
| 50 | return (struct acpi_pptt_processor *)fetch_pptt_subtable(table_hdr, pptt_ref); | ||
| 51 | } | ||
| 52 | |||
| 53 | static struct acpi_pptt_cache *fetch_pptt_cache(struct acpi_table_header *table_hdr, | ||
| 54 | u32 pptt_ref) | ||
| 55 | { | ||
| 56 | return (struct acpi_pptt_cache *)fetch_pptt_subtable(table_hdr, pptt_ref); | ||
| 57 | } | ||
| 58 | |||
| 59 | static struct acpi_subtable_header *acpi_get_pptt_resource(struct acpi_table_header *table_hdr, | ||
| 60 | struct acpi_pptt_processor *node, | ||
| 61 | int resource) | ||
| 62 | { | ||
| 63 | u32 *ref; | ||
| 64 | |||
| 65 | if (resource >= node->number_of_priv_resources) | ||
| 66 | return NULL; | ||
| 67 | |||
| 68 | ref = ACPI_ADD_PTR(u32, node, sizeof(struct acpi_pptt_processor)); | ||
| 69 | ref += resource; | ||
| 70 | |||
| 71 | return fetch_pptt_subtable(table_hdr, *ref); | ||
| 72 | } | ||
| 73 | |||
| 74 | static inline bool acpi_pptt_match_type(int table_type, int type) | ||
| 75 | { | ||
| 76 | return ((table_type & ACPI_PPTT_MASK_CACHE_TYPE) == type || | ||
| 77 | table_type & ACPI_PPTT_CACHE_TYPE_UNIFIED & type); | ||
| 78 | } | ||
| 79 | |||
| 80 | /** | ||
| 81 | * acpi_pptt_walk_cache() - Attempt to find the requested acpi_pptt_cache | ||
| 82 | * @table_hdr: Pointer to the head of the PPTT table | ||
| 83 | * @local_level: passed res reflects this cache level | ||
| 84 | * @res: cache resource in the PPTT we want to walk | ||
| 85 | * @found: returns a pointer to the requested level if found | ||
| 86 | * @level: the requested cache level | ||
| 87 | * @type: the requested cache type | ||
| 88 | * | ||
| 89 | * Attempt to find a given cache level, while counting the max number | ||
| 90 | * of cache levels for the cache node. | ||
| 91 | * | ||
| 92 | * Given a pptt resource, verify that it is a cache node, then walk | ||
| 93 | * down each level of caches, counting how many levels are found | ||
| 94 | * as well as checking the cache type (icache, dcache, unified). If a | ||
| 95 | * level & type match, then we set found, and continue the search. | ||
| 96 | * Once the entire cache branch has been walked return its max | ||
| 97 | * depth. | ||
| 98 | * | ||
| 99 | * Return: The cache structure and the level we terminated with. | ||
| 100 | */ | ||
| 101 | static int acpi_pptt_walk_cache(struct acpi_table_header *table_hdr, | ||
| 102 | int local_level, | ||
| 103 | struct acpi_subtable_header *res, | ||
| 104 | struct acpi_pptt_cache **found, | ||
| 105 | int level, int type) | ||
| 106 | { | ||
| 107 | struct acpi_pptt_cache *cache; | ||
| 108 | |||
| 109 | if (res->type != ACPI_PPTT_TYPE_CACHE) | ||
| 110 | return 0; | ||
| 111 | |||
| 112 | cache = (struct acpi_pptt_cache *) res; | ||
| 113 | while (cache) { | ||
| 114 | local_level++; | ||
| 115 | |||
| 116 | if (local_level == level && | ||
| 117 | cache->flags & ACPI_PPTT_CACHE_TYPE_VALID && | ||
| 118 | acpi_pptt_match_type(cache->attributes, type)) { | ||
| 119 | if (*found != NULL && cache != *found) | ||
| 120 | pr_warn("Found duplicate cache level/type unable to determine uniqueness\n"); | ||
| 121 | |||
| 122 | pr_debug("Found cache @ level %d\n", level); | ||
| 123 | *found = cache; | ||
| 124 | /* | ||
| 125 | * continue looking at this node's resource list | ||
| 126 | * to verify that we don't find a duplicate | ||
| 127 | * cache node. | ||
| 128 | */ | ||
| 129 | } | ||
| 130 | cache = fetch_pptt_cache(table_hdr, cache->next_level_of_cache); | ||
| 131 | } | ||
| 132 | return local_level; | ||
| 133 | } | ||
| 134 | |||
| 135 | static struct acpi_pptt_cache *acpi_find_cache_level(struct acpi_table_header *table_hdr, | ||
| 136 | struct acpi_pptt_processor *cpu_node, | ||
| 137 | int *starting_level, int level, | ||
| 138 | int type) | ||
| 139 | { | ||
| 140 | struct acpi_subtable_header *res; | ||
| 141 | int number_of_levels = *starting_level; | ||
| 142 | int resource = 0; | ||
| 143 | struct acpi_pptt_cache *ret = NULL; | ||
| 144 | int local_level; | ||
| 145 | |||
| 146 | /* walk down from processor node */ | ||
| 147 | while ((res = acpi_get_pptt_resource(table_hdr, cpu_node, resource))) { | ||
| 148 | resource++; | ||
| 149 | |||
| 150 | local_level = acpi_pptt_walk_cache(table_hdr, *starting_level, | ||
| 151 | res, &ret, level, type); | ||
| 152 | /* | ||
| 153 | * we are looking for the max depth. Since its potentially | ||
| 154 | * possible for a given node to have resources with differing | ||
| 155 | * depths verify that the depth we have found is the largest. | ||
| 156 | */ | ||
| 157 | if (number_of_levels < local_level) | ||
| 158 | number_of_levels = local_level; | ||
| 159 | } | ||
| 160 | if (number_of_levels > *starting_level) | ||
| 161 | *starting_level = number_of_levels; | ||
| 162 | |||
| 163 | return ret; | ||
| 164 | } | ||
| 165 | |||
| 166 | /** | ||
| 167 | * acpi_count_levels() - Given a PPTT table, and a cpu node, count the caches | ||
| 168 | * @table_hdr: Pointer to the head of the PPTT table | ||
| 169 | * @cpu_node: processor node we wish to count caches for | ||
| 170 | * | ||
| 171 | * Given a processor node containing a processing unit, walk into it and count | ||
| 172 | * how many levels exist solely for it, and then walk up each level until we hit | ||
| 173 | * the root node (ignore the package level because it may be possible to have | ||
| 174 | * caches that exist across packages). Count the number of cache levels that | ||
| 175 | * exist at each level on the way up. | ||
| 176 | * | ||
| 177 | * Return: Total number of levels found. | ||
| 178 | */ | ||
| 179 | static int acpi_count_levels(struct acpi_table_header *table_hdr, | ||
| 180 | struct acpi_pptt_processor *cpu_node) | ||
| 181 | { | ||
| 182 | int total_levels = 0; | ||
| 183 | |||
| 184 | do { | ||
| 185 | acpi_find_cache_level(table_hdr, cpu_node, &total_levels, 0, 0); | ||
| 186 | cpu_node = fetch_pptt_node(table_hdr, cpu_node->parent); | ||
| 187 | } while (cpu_node); | ||
| 188 | |||
| 189 | return total_levels; | ||
| 190 | } | ||
| 191 | |||
| 192 | /** | ||
| 193 | * acpi_pptt_leaf_node() - Given a processor node, determine if its a leaf | ||
| 194 | * @table_hdr: Pointer to the head of the PPTT table | ||
| 195 | * @node: passed node is checked to see if its a leaf | ||
| 196 | * | ||
| 197 | * Determine if the *node parameter is a leaf node by iterating the | ||
| 198 | * PPTT table, looking for nodes which reference it. | ||
| 199 | * | ||
| 200 | * Return: 0 if we find a node referencing the passed node (or table error), | ||
| 201 | * or 1 if we don't. | ||
| 202 | */ | ||
| 203 | static int acpi_pptt_leaf_node(struct acpi_table_header *table_hdr, | ||
| 204 | struct acpi_pptt_processor *node) | ||
| 205 | { | ||
| 206 | struct acpi_subtable_header *entry; | ||
| 207 | unsigned long table_end; | ||
| 208 | u32 node_entry; | ||
| 209 | struct acpi_pptt_processor *cpu_node; | ||
| 210 | u32 proc_sz; | ||
| 211 | |||
| 212 | table_end = (unsigned long)table_hdr + table_hdr->length; | ||
| 213 | node_entry = ACPI_PTR_DIFF(node, table_hdr); | ||
| 214 | entry = ACPI_ADD_PTR(struct acpi_subtable_header, table_hdr, | ||
| 215 | sizeof(struct acpi_table_pptt)); | ||
| 216 | proc_sz = sizeof(struct acpi_pptt_processor *); | ||
| 217 | |||
| 218 | while ((unsigned long)entry + proc_sz < table_end) { | ||
| 219 | cpu_node = (struct acpi_pptt_processor *)entry; | ||
| 220 | if (entry->type == ACPI_PPTT_TYPE_PROCESSOR && | ||
| 221 | cpu_node->parent == node_entry) | ||
| 222 | return 0; | ||
| 223 | if (entry->length == 0) | ||
| 224 | return 0; | ||
| 225 | entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry, | ||
| 226 | entry->length); | ||
| 227 | |||
| 228 | } | ||
| 229 | return 1; | ||
| 230 | } | ||
| 231 | |||
| 232 | /** | ||
| 233 | * acpi_find_processor_node() - Given a PPTT table find the requested processor | ||
| 234 | * @table_hdr: Pointer to the head of the PPTT table | ||
| 235 | * @acpi_cpu_id: cpu we are searching for | ||
| 236 | * | ||
| 237 | * Find the subtable entry describing the provided processor. | ||
| 238 | * This is done by iterating the PPTT table looking for processor nodes | ||
| 239 | * which have an acpi_processor_id that matches the acpi_cpu_id parameter | ||
| 240 | * passed into the function. If we find a node that matches this criteria | ||
| 241 | * we verify that its a leaf node in the topology rather than depending | ||
| 242 | * on the valid flag, which doesn't need to be set for leaf nodes. | ||
| 243 | * | ||
| 244 | * Return: NULL, or the processors acpi_pptt_processor* | ||
| 245 | */ | ||
| 246 | static struct acpi_pptt_processor *acpi_find_processor_node(struct acpi_table_header *table_hdr, | ||
| 247 | u32 acpi_cpu_id) | ||
| 248 | { | ||
| 249 | struct acpi_subtable_header *entry; | ||
| 250 | unsigned long table_end; | ||
| 251 | struct acpi_pptt_processor *cpu_node; | ||
| 252 | u32 proc_sz; | ||
| 253 | |||
| 254 | table_end = (unsigned long)table_hdr + table_hdr->length; | ||
| 255 | entry = ACPI_ADD_PTR(struct acpi_subtable_header, table_hdr, | ||
| 256 | sizeof(struct acpi_table_pptt)); | ||
| 257 | proc_sz = sizeof(struct acpi_pptt_processor *); | ||
| 258 | |||
| 259 | /* find the processor structure associated with this cpuid */ | ||
| 260 | while ((unsigned long)entry + proc_sz < table_end) { | ||
| 261 | cpu_node = (struct acpi_pptt_processor *)entry; | ||
| 262 | |||
| 263 | if (entry->length == 0) { | ||
| 264 | pr_warn("Invalid zero length subtable\n"); | ||
| 265 | break; | ||
| 266 | } | ||
| 267 | if (entry->type == ACPI_PPTT_TYPE_PROCESSOR && | ||
| 268 | acpi_cpu_id == cpu_node->acpi_processor_id && | ||
| 269 | acpi_pptt_leaf_node(table_hdr, cpu_node)) { | ||
| 270 | return (struct acpi_pptt_processor *)entry; | ||
| 271 | } | ||
| 272 | |||
| 273 | entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry, | ||
| 274 | entry->length); | ||
| 275 | } | ||
| 276 | |||
| 277 | return NULL; | ||
| 278 | } | ||
| 279 | |||
| 280 | static int acpi_find_cache_levels(struct acpi_table_header *table_hdr, | ||
| 281 | u32 acpi_cpu_id) | ||
| 282 | { | ||
| 283 | int number_of_levels = 0; | ||
| 284 | struct acpi_pptt_processor *cpu; | ||
| 285 | |||
| 286 | cpu = acpi_find_processor_node(table_hdr, acpi_cpu_id); | ||
| 287 | if (cpu) | ||
| 288 | number_of_levels = acpi_count_levels(table_hdr, cpu); | ||
| 289 | |||
| 290 | return number_of_levels; | ||
| 291 | } | ||
| 292 | |||
| 293 | static u8 acpi_cache_type(enum cache_type type) | ||
| 294 | { | ||
| 295 | switch (type) { | ||
| 296 | case CACHE_TYPE_DATA: | ||
| 297 | pr_debug("Looking for data cache\n"); | ||
| 298 | return ACPI_PPTT_CACHE_TYPE_DATA; | ||
| 299 | case CACHE_TYPE_INST: | ||
| 300 | pr_debug("Looking for instruction cache\n"); | ||
| 301 | return ACPI_PPTT_CACHE_TYPE_INSTR; | ||
| 302 | default: | ||
| 303 | case CACHE_TYPE_UNIFIED: | ||
| 304 | pr_debug("Looking for unified cache\n"); | ||
| 305 | /* | ||
| 306 | * It is important that ACPI_PPTT_CACHE_TYPE_UNIFIED | ||
| 307 | * contains the bit pattern that will match both | ||
| 308 | * ACPI unified bit patterns because we use it later | ||
| 309 | * to match both cases. | ||
| 310 | */ | ||
| 311 | return ACPI_PPTT_CACHE_TYPE_UNIFIED; | ||
| 312 | } | ||
| 313 | } | ||
| 314 | |||
| 315 | static struct acpi_pptt_cache *acpi_find_cache_node(struct acpi_table_header *table_hdr, | ||
| 316 | u32 acpi_cpu_id, | ||
| 317 | enum cache_type type, | ||
| 318 | unsigned int level, | ||
| 319 | struct acpi_pptt_processor **node) | ||
| 320 | { | ||
| 321 | int total_levels = 0; | ||
| 322 | struct acpi_pptt_cache *found = NULL; | ||
| 323 | struct acpi_pptt_processor *cpu_node; | ||
| 324 | u8 acpi_type = acpi_cache_type(type); | ||
| 325 | |||
| 326 | pr_debug("Looking for CPU %d's level %d cache type %d\n", | ||
| 327 | acpi_cpu_id, level, acpi_type); | ||
| 328 | |||
| 329 | cpu_node = acpi_find_processor_node(table_hdr, acpi_cpu_id); | ||
| 330 | |||
| 331 | while (cpu_node && !found) { | ||
| 332 | found = acpi_find_cache_level(table_hdr, cpu_node, | ||
| 333 | &total_levels, level, acpi_type); | ||
| 334 | *node = cpu_node; | ||
| 335 | cpu_node = fetch_pptt_node(table_hdr, cpu_node->parent); | ||
| 336 | } | ||
| 337 | |||
| 338 | return found; | ||
| 339 | } | ||
| 340 | |||
| 341 | /* total number of attributes checked by the properties code */ | ||
| 342 | #define PPTT_CHECKED_ATTRIBUTES 4 | ||
| 343 | |||
| 344 | /** | ||
| 345 | * update_cache_properties() - Update cacheinfo for the given processor | ||
| 346 | * @this_leaf: Kernel cache info structure being updated | ||
| 347 | * @found_cache: The PPTT node describing this cache instance | ||
| 348 | * @cpu_node: A unique reference to describe this cache instance | ||
| 349 | * | ||
| 350 | * The ACPI spec implies that the fields in the cache structures are used to | ||
| 351 | * extend and correct the information probed from the hardware. Lets only | ||
| 352 | * set fields that we determine are VALID. | ||
| 353 | * | ||
| 354 | * Return: nothing. Side effect of updating the global cacheinfo | ||
| 355 | */ | ||
| 356 | static void update_cache_properties(struct cacheinfo *this_leaf, | ||
| 357 | struct acpi_pptt_cache *found_cache, | ||
| 358 | struct acpi_pptt_processor *cpu_node) | ||
| 359 | { | ||
| 360 | int valid_flags = 0; | ||
| 361 | |||
| 362 | this_leaf->fw_token = cpu_node; | ||
| 363 | if (found_cache->flags & ACPI_PPTT_SIZE_PROPERTY_VALID) { | ||
| 364 | this_leaf->size = found_cache->size; | ||
| 365 | valid_flags++; | ||
| 366 | } | ||
| 367 | if (found_cache->flags & ACPI_PPTT_LINE_SIZE_VALID) { | ||
| 368 | this_leaf->coherency_line_size = found_cache->line_size; | ||
| 369 | valid_flags++; | ||
| 370 | } | ||
| 371 | if (found_cache->flags & ACPI_PPTT_NUMBER_OF_SETS_VALID) { | ||
| 372 | this_leaf->number_of_sets = found_cache->number_of_sets; | ||
| 373 | valid_flags++; | ||
| 374 | } | ||
| 375 | if (found_cache->flags & ACPI_PPTT_ASSOCIATIVITY_VALID) { | ||
| 376 | this_leaf->ways_of_associativity = found_cache->associativity; | ||
| 377 | valid_flags++; | ||
| 378 | } | ||
| 379 | if (found_cache->flags & ACPI_PPTT_WRITE_POLICY_VALID) { | ||
| 380 | switch (found_cache->attributes & ACPI_PPTT_MASK_WRITE_POLICY) { | ||
| 381 | case ACPI_PPTT_CACHE_POLICY_WT: | ||
| 382 | this_leaf->attributes = CACHE_WRITE_THROUGH; | ||
| 383 | break; | ||
| 384 | case ACPI_PPTT_CACHE_POLICY_WB: | ||
| 385 | this_leaf->attributes = CACHE_WRITE_BACK; | ||
| 386 | break; | ||
| 387 | } | ||
| 388 | } | ||
| 389 | if (found_cache->flags & ACPI_PPTT_ALLOCATION_TYPE_VALID) { | ||
| 390 | switch (found_cache->attributes & ACPI_PPTT_MASK_ALLOCATION_TYPE) { | ||
| 391 | case ACPI_PPTT_CACHE_READ_ALLOCATE: | ||
| 392 | this_leaf->attributes |= CACHE_READ_ALLOCATE; | ||
| 393 | break; | ||
| 394 | case ACPI_PPTT_CACHE_WRITE_ALLOCATE: | ||
| 395 | this_leaf->attributes |= CACHE_WRITE_ALLOCATE; | ||
| 396 | break; | ||
| 397 | case ACPI_PPTT_CACHE_RW_ALLOCATE: | ||
| 398 | case ACPI_PPTT_CACHE_RW_ALLOCATE_ALT: | ||
| 399 | this_leaf->attributes |= | ||
| 400 | CACHE_READ_ALLOCATE | CACHE_WRITE_ALLOCATE; | ||
| 401 | break; | ||
| 402 | } | ||
| 403 | } | ||
| 404 | /* | ||
| 405 | * If the above flags are valid, and the cache type is NOCACHE | ||
| 406 | * update the cache type as well. | ||
| 407 | */ | ||
| 408 | if (this_leaf->type == CACHE_TYPE_NOCACHE && | ||
| 409 | valid_flags == PPTT_CHECKED_ATTRIBUTES) | ||
| 410 | this_leaf->type = CACHE_TYPE_UNIFIED; | ||
| 411 | } | ||
| 412 | |||
| 413 | static void cache_setup_acpi_cpu(struct acpi_table_header *table, | ||
| 414 | unsigned int cpu) | ||
| 415 | { | ||
| 416 | struct acpi_pptt_cache *found_cache; | ||
| 417 | struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); | ||
| 418 | u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu); | ||
| 419 | struct cacheinfo *this_leaf; | ||
| 420 | unsigned int index = 0; | ||
| 421 | struct acpi_pptt_processor *cpu_node = NULL; | ||
| 422 | |||
| 423 | while (index < get_cpu_cacheinfo(cpu)->num_leaves) { | ||
| 424 | this_leaf = this_cpu_ci->info_list + index; | ||
| 425 | found_cache = acpi_find_cache_node(table, acpi_cpu_id, | ||
| 426 | this_leaf->type, | ||
| 427 | this_leaf->level, | ||
| 428 | &cpu_node); | ||
| 429 | pr_debug("found = %p %p\n", found_cache, cpu_node); | ||
| 430 | if (found_cache) | ||
| 431 | update_cache_properties(this_leaf, | ||
| 432 | found_cache, | ||
| 433 | cpu_node); | ||
| 434 | |||
| 435 | index++; | ||
| 436 | } | ||
| 437 | } | ||
| 438 | |||
| 439 | /* Passing level values greater than this will result in search termination */ | ||
| 440 | #define PPTT_ABORT_PACKAGE 0xFF | ||
| 441 | |||
| 442 | static struct acpi_pptt_processor *acpi_find_processor_package_id(struct acpi_table_header *table_hdr, | ||
| 443 | struct acpi_pptt_processor *cpu, | ||
| 444 | int level, int flag) | ||
| 445 | { | ||
| 446 | struct acpi_pptt_processor *prev_node; | ||
| 447 | |||
| 448 | while (cpu && level) { | ||
| 449 | if (cpu->flags & flag) | ||
| 450 | break; | ||
| 451 | pr_debug("level %d\n", level); | ||
| 452 | prev_node = fetch_pptt_node(table_hdr, cpu->parent); | ||
| 453 | if (prev_node == NULL) | ||
| 454 | break; | ||
| 455 | cpu = prev_node; | ||
| 456 | level--; | ||
| 457 | } | ||
| 458 | return cpu; | ||
| 459 | } | ||
| 460 | |||
| 461 | /** | ||
| 462 | * topology_get_acpi_cpu_tag() - Find a unique topology value for a feature | ||
| 463 | * @table: Pointer to the head of the PPTT table | ||
| 464 | * @cpu: Kernel logical cpu number | ||
| 465 | * @level: A level that terminates the search | ||
| 466 | * @flag: A flag which terminates the search | ||
| 467 | * | ||
| 468 | * Get a unique value given a cpu, and a topology level, that can be | ||
| 469 | * matched to determine which cpus share common topological features | ||
| 470 | * at that level. | ||
| 471 | * | ||
| 472 | * Return: Unique value, or -ENOENT if unable to locate cpu | ||
| 473 | */ | ||
| 474 | static int topology_get_acpi_cpu_tag(struct acpi_table_header *table, | ||
| 475 | unsigned int cpu, int level, int flag) | ||
| 476 | { | ||
| 477 | struct acpi_pptt_processor *cpu_node; | ||
| 478 | u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu); | ||
| 479 | |||
| 480 | cpu_node = acpi_find_processor_node(table, acpi_cpu_id); | ||
| 481 | if (cpu_node) { | ||
| 482 | cpu_node = acpi_find_processor_package_id(table, cpu_node, | ||
| 483 | level, flag); | ||
| 484 | /* Only the first level has a guaranteed id */ | ||
| 485 | if (level == 0) | ||
| 486 | return cpu_node->acpi_processor_id; | ||
| 487 | return ACPI_PTR_DIFF(cpu_node, table); | ||
| 488 | } | ||
| 489 | pr_warn_once("PPTT table found, but unable to locate core %d (%d)\n", | ||
| 490 | cpu, acpi_cpu_id); | ||
| 491 | return -ENOENT; | ||
| 492 | } | ||
| 493 | |||
| 494 | static int find_acpi_cpu_topology_tag(unsigned int cpu, int level, int flag) | ||
| 495 | { | ||
| 496 | struct acpi_table_header *table; | ||
| 497 | acpi_status status; | ||
| 498 | int retval; | ||
| 499 | |||
| 500 | status = acpi_get_table(ACPI_SIG_PPTT, 0, &table); | ||
| 501 | if (ACPI_FAILURE(status)) { | ||
| 502 | pr_warn_once("No PPTT table found, cpu topology may be inaccurate\n"); | ||
| 503 | return -ENOENT; | ||
| 504 | } | ||
| 505 | retval = topology_get_acpi_cpu_tag(table, cpu, level, flag); | ||
| 506 | pr_debug("Topology Setup ACPI cpu %d, level %d ret = %d\n", | ||
| 507 | cpu, level, retval); | ||
| 508 | acpi_put_table(table); | ||
| 509 | |||
| 510 | return retval; | ||
| 511 | } | ||
| 512 | |||
| 513 | /** | ||
| 514 | * acpi_find_last_cache_level() - Determines the number of cache levels for a PE | ||
| 515 | * @cpu: Kernel logical cpu number | ||
| 516 | * | ||
| 517 | * Given a logical cpu number, returns the number of levels of cache represented | ||
| 518 | * in the PPTT. Errors caused by lack of a PPTT table, or otherwise, return 0 | ||
| 519 | * indicating we didn't find any cache levels. | ||
| 520 | * | ||
| 521 | * Return: Cache levels visible to this core. | ||
| 522 | */ | ||
| 523 | int acpi_find_last_cache_level(unsigned int cpu) | ||
| 524 | { | ||
| 525 | u32 acpi_cpu_id; | ||
| 526 | struct acpi_table_header *table; | ||
| 527 | int number_of_levels = 0; | ||
| 528 | acpi_status status; | ||
| 529 | |||
| 530 | pr_debug("Cache Setup find last level cpu=%d\n", cpu); | ||
| 531 | |||
| 532 | acpi_cpu_id = get_acpi_id_for_cpu(cpu); | ||
| 533 | status = acpi_get_table(ACPI_SIG_PPTT, 0, &table); | ||
| 534 | if (ACPI_FAILURE(status)) { | ||
| 535 | pr_warn_once("No PPTT table found, cache topology may be inaccurate\n"); | ||
| 536 | } else { | ||
| 537 | number_of_levels = acpi_find_cache_levels(table, acpi_cpu_id); | ||
| 538 | acpi_put_table(table); | ||
| 539 | } | ||
| 540 | pr_debug("Cache Setup find last level level=%d\n", number_of_levels); | ||
| 541 | |||
| 542 | return number_of_levels; | ||
| 543 | } | ||
| 544 | |||
| 545 | /** | ||
| 546 | * cache_setup_acpi() - Override CPU cache topology with data from the PPTT | ||
| 547 | * @cpu: Kernel logical cpu number | ||
| 548 | * | ||
| 549 | * Updates the global cache info provided by cpu_get_cacheinfo() | ||
| 550 | * when there are valid properties in the acpi_pptt_cache nodes. A | ||
| 551 | * successful parse may not result in any updates if none of the | ||
| 552 | * cache levels have any valid flags set. Futher, a unique value is | ||
| 553 | * associated with each known CPU cache entry. This unique value | ||
| 554 | * can be used to determine whether caches are shared between cpus. | ||
| 555 | * | ||
| 556 | * Return: -ENOENT on failure to find table, or 0 on success | ||
| 557 | */ | ||
| 558 | int cache_setup_acpi(unsigned int cpu) | ||
| 559 | { | ||
| 560 | struct acpi_table_header *table; | ||
| 561 | acpi_status status; | ||
| 562 | |||
| 563 | pr_debug("Cache Setup ACPI cpu %d\n", cpu); | ||
| 564 | |||
| 565 | status = acpi_get_table(ACPI_SIG_PPTT, 0, &table); | ||
| 566 | if (ACPI_FAILURE(status)) { | ||
| 567 | pr_warn_once("No PPTT table found, cache topology may be inaccurate\n"); | ||
| 568 | return -ENOENT; | ||
| 569 | } | ||
| 570 | |||
| 571 | cache_setup_acpi_cpu(table, cpu); | ||
| 572 | acpi_put_table(table); | ||
| 573 | |||
| 574 | return status; | ||
| 575 | } | ||
| 576 | |||
| 577 | /** | ||
| 578 | * find_acpi_cpu_topology() - Determine a unique topology value for a given cpu | ||
| 579 | * @cpu: Kernel logical cpu number | ||
| 580 | * @level: The topological level for which we would like a unique ID | ||
| 581 | * | ||
| 582 | * Determine a topology unique ID for each thread/core/cluster/mc_grouping | ||
| 583 | * /socket/etc. This ID can then be used to group peers, which will have | ||
| 584 | * matching ids. | ||
| 585 | * | ||
| 586 | * The search terminates when either the requested level is found or | ||
| 587 | * we reach a root node. Levels beyond the termination point will return the | ||
| 588 | * same unique ID. The unique id for level 0 is the acpi processor id. All | ||
| 589 | * other levels beyond this use a generated value to uniquely identify | ||
| 590 | * a topological feature. | ||
| 591 | * | ||
| 592 | * Return: -ENOENT if the PPTT doesn't exist, or the cpu cannot be found. | ||
| 593 | * Otherwise returns a value which represents a unique topological feature. | ||
| 594 | */ | ||
| 595 | int find_acpi_cpu_topology(unsigned int cpu, int level) | ||
| 596 | { | ||
| 597 | return find_acpi_cpu_topology_tag(cpu, level, 0); | ||
| 598 | } | ||
| 599 | |||
| 600 | /** | ||
| 601 | * find_acpi_cpu_cache_topology() - Determine a unique cache topology value | ||
| 602 | * @cpu: Kernel logical cpu number | ||
| 603 | * @level: The cache level for which we would like a unique ID | ||
| 604 | * | ||
| 605 | * Determine a unique ID for each unified cache in the system | ||
| 606 | * | ||
| 607 | * Return: -ENOENT if the PPTT doesn't exist, or the cpu cannot be found. | ||
| 608 | * Otherwise returns a value which represents a unique topological feature. | ||
| 609 | */ | ||
| 610 | int find_acpi_cpu_cache_topology(unsigned int cpu, int level) | ||
| 611 | { | ||
| 612 | struct acpi_table_header *table; | ||
| 613 | struct acpi_pptt_cache *found_cache; | ||
| 614 | acpi_status status; | ||
| 615 | u32 acpi_cpu_id = get_acpi_id_for_cpu(cpu); | ||
| 616 | struct acpi_pptt_processor *cpu_node = NULL; | ||
| 617 | int ret = -1; | ||
| 618 | |||
| 619 | status = acpi_get_table(ACPI_SIG_PPTT, 0, &table); | ||
| 620 | if (ACPI_FAILURE(status)) { | ||
| 621 | pr_warn_once("No PPTT table found, topology may be inaccurate\n"); | ||
| 622 | return -ENOENT; | ||
| 623 | } | ||
| 624 | |||
| 625 | found_cache = acpi_find_cache_node(table, acpi_cpu_id, | ||
| 626 | CACHE_TYPE_UNIFIED, | ||
| 627 | level, | ||
| 628 | &cpu_node); | ||
| 629 | if (found_cache) | ||
| 630 | ret = ACPI_PTR_DIFF(cpu_node, table); | ||
| 631 | |||
| 632 | acpi_put_table(table); | ||
| 633 | |||
| 634 | return ret; | ||
| 635 | } | ||
| 636 | |||
| 637 | |||
| 638 | /** | ||
| 639 | * find_acpi_cpu_topology_package() - Determine a unique cpu package value | ||
| 640 | * @cpu: Kernel logical cpu number | ||
| 641 | * | ||
| 642 | * Determine a topology unique package ID for the given cpu. | ||
| 643 | * This ID can then be used to group peers, which will have matching ids. | ||
| 644 | * | ||
| 645 | * The search terminates when either a level is found with the PHYSICAL_PACKAGE | ||
| 646 | * flag set or we reach a root node. | ||
| 647 | * | ||
| 648 | * Return: -ENOENT if the PPTT doesn't exist, or the cpu cannot be found. | ||
| 649 | * Otherwise returns a value which represents the package for this cpu. | ||
| 650 | */ | ||
| 651 | int find_acpi_cpu_topology_package(unsigned int cpu) | ||
| 652 | { | ||
| 653 | return find_acpi_cpu_topology_tag(cpu, PPTT_ABORT_PACKAGE, | ||
| 654 | ACPI_PPTT_PHYSICAL_PACKAGE); | ||
| 655 | } | ||
diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 4a3410aa6540..a3d012b08fc5 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c | |||
| @@ -462,7 +462,7 @@ static const char * const table_sigs[] = { | |||
| 462 | ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT, | 462 | ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT, |
| 463 | ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT, | 463 | ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT, |
| 464 | ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, ACPI_SIG_IORT, | 464 | ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, ACPI_SIG_IORT, |
| 465 | ACPI_SIG_NFIT, ACPI_SIG_HMAT, NULL }; | 465 | ACPI_SIG_NFIT, ACPI_SIG_HMAT, ACPI_SIG_PPTT, NULL }; |
| 466 | 466 | ||
| 467 | #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header) | 467 | #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header) |
| 468 | 468 | ||
diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index edf726267282..2880e2ab01f5 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c | |||
| @@ -32,50 +32,10 @@ struct cpu_cacheinfo *get_cpu_cacheinfo(unsigned int cpu) | |||
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | #ifdef CONFIG_OF | 34 | #ifdef CONFIG_OF |
| 35 | static int cache_setup_of_node(unsigned int cpu) | ||
| 36 | { | ||
| 37 | struct device_node *np; | ||
| 38 | struct cacheinfo *this_leaf; | ||
| 39 | struct device *cpu_dev = get_cpu_device(cpu); | ||
| 40 | struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); | ||
| 41 | unsigned int index = 0; | ||
| 42 | |||
| 43 | /* skip if of_node is already populated */ | ||
| 44 | if (this_cpu_ci->info_list->of_node) | ||
| 45 | return 0; | ||
| 46 | |||
| 47 | if (!cpu_dev) { | ||
| 48 | pr_err("No cpu device for CPU %d\n", cpu); | ||
| 49 | return -ENODEV; | ||
| 50 | } | ||
| 51 | np = cpu_dev->of_node; | ||
| 52 | if (!np) { | ||
| 53 | pr_err("Failed to find cpu%d device node\n", cpu); | ||
| 54 | return -ENOENT; | ||
| 55 | } | ||
| 56 | |||
| 57 | while (index < cache_leaves(cpu)) { | ||
| 58 | this_leaf = this_cpu_ci->info_list + index; | ||
| 59 | if (this_leaf->level != 1) | ||
| 60 | np = of_find_next_cache_node(np); | ||
| 61 | else | ||
| 62 | np = of_node_get(np);/* cpu node itself */ | ||
| 63 | if (!np) | ||
| 64 | break; | ||
| 65 | this_leaf->of_node = np; | ||
| 66 | index++; | ||
| 67 | } | ||
| 68 | |||
| 69 | if (index != cache_leaves(cpu)) /* not all OF nodes populated */ | ||
| 70 | return -ENOENT; | ||
| 71 | |||
| 72 | return 0; | ||
| 73 | } | ||
| 74 | |||
| 75 | static inline bool cache_leaves_are_shared(struct cacheinfo *this_leaf, | 35 | static inline bool cache_leaves_are_shared(struct cacheinfo *this_leaf, |
| 76 | struct cacheinfo *sib_leaf) | 36 | struct cacheinfo *sib_leaf) |
| 77 | { | 37 | { |
| 78 | return sib_leaf->of_node == this_leaf->of_node; | 38 | return sib_leaf->fw_token == this_leaf->fw_token; |
| 79 | } | 39 | } |
| 80 | 40 | ||
| 81 | /* OF properties to query for a given cache type */ | 41 | /* OF properties to query for a given cache type */ |
| @@ -111,7 +71,7 @@ static inline int get_cacheinfo_idx(enum cache_type type) | |||
| 111 | return type; | 71 | return type; |
| 112 | } | 72 | } |
| 113 | 73 | ||
| 114 | static void cache_size(struct cacheinfo *this_leaf) | 74 | static void cache_size(struct cacheinfo *this_leaf, struct device_node *np) |
| 115 | { | 75 | { |
| 116 | const char *propname; | 76 | const char *propname; |
| 117 | const __be32 *cache_size; | 77 | const __be32 *cache_size; |
| @@ -120,13 +80,14 @@ static void cache_size(struct cacheinfo *this_leaf) | |||
| 120 | ct_idx = get_cacheinfo_idx(this_leaf->type); | 80 | ct_idx = get_cacheinfo_idx(this_leaf->type); |
| 121 | propname = cache_type_info[ct_idx].size_prop; | 81 | propname = cache_type_info[ct_idx].size_prop; |
| 122 | 82 | ||
| 123 | cache_size = of_get_property(this_leaf->of_node, propname, NULL); | 83 | cache_size = of_get_property(np, propname, NULL); |
| 124 | if (cache_size) | 84 | if (cache_size) |
| 125 | this_leaf->size = of_read_number(cache_size, 1); | 85 | this_leaf->size = of_read_number(cache_size, 1); |
| 126 | } | 86 | } |
| 127 | 87 | ||
| 128 | /* not cache_line_size() because that's a macro in include/linux/cache.h */ | 88 | /* not cache_line_size() because that's a macro in include/linux/cache.h */ |
| 129 | static void cache_get_line_size(struct cacheinfo *this_leaf) | 89 | static void cache_get_line_size(struct cacheinfo *this_leaf, |
| 90 | struct device_node *np) | ||
| 130 | { | 91 | { |
| 131 | const __be32 *line_size; | 92 | const __be32 *line_size; |
| 132 | int i, lim, ct_idx; | 93 | int i, lim, ct_idx; |
| @@ -138,7 +99,7 @@ static void cache_get_line_size(struct cacheinfo *this_leaf) | |||
| 138 | const char *propname; | 99 | const char *propname; |
| 139 | 100 | ||
| 140 | propname = cache_type_info[ct_idx].line_size_props[i]; | 101 | propname = cache_type_info[ct_idx].line_size_props[i]; |
| 141 | line_size = of_get_property(this_leaf->of_node, propname, NULL); | 102 | line_size = of_get_property(np, propname, NULL); |
| 142 | if (line_size) | 103 | if (line_size) |
| 143 | break; | 104 | break; |
| 144 | } | 105 | } |
| @@ -147,7 +108,7 @@ static void cache_get_line_size(struct cacheinfo *this_leaf) | |||
| 147 | this_leaf->coherency_line_size = of_read_number(line_size, 1); | 108 | this_leaf->coherency_line_size = of_read_number(line_size, 1); |
| 148 | } | 109 | } |
| 149 | 110 | ||
| 150 | static void cache_nr_sets(struct cacheinfo *this_leaf) | 111 | static void cache_nr_sets(struct cacheinfo *this_leaf, struct device_node *np) |
| 151 | { | 112 | { |
| 152 | const char *propname; | 113 | const char *propname; |
| 153 | const __be32 *nr_sets; | 114 | const __be32 *nr_sets; |
| @@ -156,7 +117,7 @@ static void cache_nr_sets(struct cacheinfo *this_leaf) | |||
| 156 | ct_idx = get_cacheinfo_idx(this_leaf->type); | 117 | ct_idx = get_cacheinfo_idx(this_leaf->type); |
| 157 | propname = cache_type_info[ct_idx].nr_sets_prop; | 118 | propname = cache_type_info[ct_idx].nr_sets_prop; |
| 158 | 119 | ||
| 159 | nr_sets = of_get_property(this_leaf->of_node, propname, NULL); | 120 | nr_sets = of_get_property(np, propname, NULL); |
| 160 | if (nr_sets) | 121 | if (nr_sets) |
| 161 | this_leaf->number_of_sets = of_read_number(nr_sets, 1); | 122 | this_leaf->number_of_sets = of_read_number(nr_sets, 1); |
| 162 | } | 123 | } |
| @@ -175,41 +136,77 @@ static void cache_associativity(struct cacheinfo *this_leaf) | |||
| 175 | this_leaf->ways_of_associativity = (size / nr_sets) / line_size; | 136 | this_leaf->ways_of_associativity = (size / nr_sets) / line_size; |
| 176 | } | 137 | } |
| 177 | 138 | ||
| 178 | static bool cache_node_is_unified(struct cacheinfo *this_leaf) | 139 | static bool cache_node_is_unified(struct cacheinfo *this_leaf, |
| 140 | struct device_node *np) | ||
| 179 | { | 141 | { |
| 180 | return of_property_read_bool(this_leaf->of_node, "cache-unified"); | 142 | return of_property_read_bool(np, "cache-unified"); |
| 181 | } | 143 | } |
| 182 | 144 | ||
| 183 | static void cache_of_override_properties(unsigned int cpu) | 145 | static void cache_of_set_props(struct cacheinfo *this_leaf, |
| 146 | struct device_node *np) | ||
| 184 | { | 147 | { |
| 185 | int index; | 148 | /* |
| 149 | * init_cache_level must setup the cache level correctly | ||
| 150 | * overriding the architecturally specified levels, so | ||
| 151 | * if type is NONE at this stage, it should be unified | ||
| 152 | */ | ||
| 153 | if (this_leaf->type == CACHE_TYPE_NOCACHE && | ||
| 154 | cache_node_is_unified(this_leaf, np)) | ||
| 155 | this_leaf->type = CACHE_TYPE_UNIFIED; | ||
| 156 | cache_size(this_leaf, np); | ||
| 157 | cache_get_line_size(this_leaf, np); | ||
| 158 | cache_nr_sets(this_leaf, np); | ||
| 159 | cache_associativity(this_leaf); | ||
| 160 | } | ||
| 161 | |||
| 162 | static int cache_setup_of_node(unsigned int cpu) | ||
| 163 | { | ||
| 164 | struct device_node *np; | ||
| 186 | struct cacheinfo *this_leaf; | 165 | struct cacheinfo *this_leaf; |
| 166 | struct device *cpu_dev = get_cpu_device(cpu); | ||
| 187 | struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); | 167 | struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); |
| 168 | unsigned int index = 0; | ||
| 188 | 169 | ||
| 189 | for (index = 0; index < cache_leaves(cpu); index++) { | 170 | /* skip if fw_token is already populated */ |
| 171 | if (this_cpu_ci->info_list->fw_token) { | ||
| 172 | return 0; | ||
| 173 | } | ||
| 174 | |||
| 175 | if (!cpu_dev) { | ||
| 176 | pr_err("No cpu device for CPU %d\n", cpu); | ||
| 177 | return -ENODEV; | ||
| 178 | } | ||
| 179 | np = cpu_dev->of_node; | ||
| 180 | if (!np) { | ||
| 181 | pr_err("Failed to find cpu%d device node\n", cpu); | ||
| 182 | return -ENOENT; | ||
| 183 | } | ||
| 184 | |||
| 185 | while (index < cache_leaves(cpu)) { | ||
| 190 | this_leaf = this_cpu_ci->info_list + index; | 186 | this_leaf = this_cpu_ci->info_list + index; |
| 191 | /* | 187 | if (this_leaf->level != 1) |
| 192 | * init_cache_level must setup the cache level correctly | 188 | np = of_find_next_cache_node(np); |
| 193 | * overriding the architecturally specified levels, so | 189 | else |
| 194 | * if type is NONE at this stage, it should be unified | 190 | np = of_node_get(np);/* cpu node itself */ |
| 195 | */ | 191 | if (!np) |
| 196 | if (this_leaf->type == CACHE_TYPE_NOCACHE && | 192 | break; |
| 197 | cache_node_is_unified(this_leaf)) | 193 | cache_of_set_props(this_leaf, np); |
| 198 | this_leaf->type = CACHE_TYPE_UNIFIED; | 194 | this_leaf->fw_token = np; |
| 199 | cache_size(this_leaf); | 195 | index++; |
| 200 | cache_get_line_size(this_leaf); | ||
| 201 | cache_nr_sets(this_leaf); | ||
| 202 | cache_associativity(this_leaf); | ||
| 203 | } | 196 | } |
| 197 | |||
| 198 | if (index != cache_leaves(cpu)) /* not all OF nodes populated */ | ||
| 199 | return -ENOENT; | ||
| 200 | |||
| 201 | return 0; | ||
| 204 | } | 202 | } |
| 205 | #else | 203 | #else |
| 206 | static void cache_of_override_properties(unsigned int cpu) { } | ||
| 207 | static inline int cache_setup_of_node(unsigned int cpu) { return 0; } | 204 | static inline int cache_setup_of_node(unsigned int cpu) { return 0; } |
| 208 | static inline bool cache_leaves_are_shared(struct cacheinfo *this_leaf, | 205 | static inline bool cache_leaves_are_shared(struct cacheinfo *this_leaf, |
| 209 | struct cacheinfo *sib_leaf) | 206 | struct cacheinfo *sib_leaf) |
| 210 | { | 207 | { |
| 211 | /* | 208 | /* |
| 212 | * For non-DT systems, assume unique level 1 cache, system-wide | 209 | * For non-DT/ACPI systems, assume unique level 1 caches, system-wide |
| 213 | * shared caches for all other levels. This will be used only if | 210 | * shared caches for all other levels. This will be used only if |
| 214 | * arch specific code has not populated shared_cpu_map | 211 | * arch specific code has not populated shared_cpu_map |
| 215 | */ | 212 | */ |
| @@ -217,6 +214,11 @@ static inline bool cache_leaves_are_shared(struct cacheinfo *this_leaf, | |||
| 217 | } | 214 | } |
| 218 | #endif | 215 | #endif |
| 219 | 216 | ||
| 217 | int __weak cache_setup_acpi(unsigned int cpu) | ||
| 218 | { | ||
| 219 | return -ENOTSUPP; | ||
| 220 | } | ||
| 221 | |||
| 220 | static int cache_shared_cpu_map_setup(unsigned int cpu) | 222 | static int cache_shared_cpu_map_setup(unsigned int cpu) |
| 221 | { | 223 | { |
| 222 | struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); | 224 | struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); |
| @@ -230,8 +232,8 @@ static int cache_shared_cpu_map_setup(unsigned int cpu) | |||
| 230 | if (of_have_populated_dt()) | 232 | if (of_have_populated_dt()) |
| 231 | ret = cache_setup_of_node(cpu); | 233 | ret = cache_setup_of_node(cpu); |
| 232 | else if (!acpi_disabled) | 234 | else if (!acpi_disabled) |
| 233 | /* No cache property/hierarchy support yet in ACPI */ | 235 | ret = cache_setup_acpi(cpu); |
| 234 | ret = -ENOTSUPP; | 236 | |
| 235 | if (ret) | 237 | if (ret) |
| 236 | return ret; | 238 | return ret; |
| 237 | 239 | ||
| @@ -282,16 +284,11 @@ static void cache_shared_cpu_map_remove(unsigned int cpu) | |||
| 282 | cpumask_clear_cpu(cpu, &sib_leaf->shared_cpu_map); | 284 | cpumask_clear_cpu(cpu, &sib_leaf->shared_cpu_map); |
| 283 | cpumask_clear_cpu(sibling, &this_leaf->shared_cpu_map); | 285 | cpumask_clear_cpu(sibling, &this_leaf->shared_cpu_map); |
| 284 | } | 286 | } |
| 285 | of_node_put(this_leaf->of_node); | 287 | if (of_have_populated_dt()) |
| 288 | of_node_put(this_leaf->fw_token); | ||
| 286 | } | 289 | } |
| 287 | } | 290 | } |
| 288 | 291 | ||
| 289 | static void cache_override_properties(unsigned int cpu) | ||
| 290 | { | ||
| 291 | if (of_have_populated_dt()) | ||
| 292 | return cache_of_override_properties(cpu); | ||
| 293 | } | ||
| 294 | |||
| 295 | static void free_cache_attributes(unsigned int cpu) | 292 | static void free_cache_attributes(unsigned int cpu) |
| 296 | { | 293 | { |
| 297 | if (!per_cpu_cacheinfo(cpu)) | 294 | if (!per_cpu_cacheinfo(cpu)) |
| @@ -325,12 +322,17 @@ static int detect_cache_attributes(unsigned int cpu) | |||
| 325 | if (per_cpu_cacheinfo(cpu) == NULL) | 322 | if (per_cpu_cacheinfo(cpu) == NULL) |
| 326 | return -ENOMEM; | 323 | return -ENOMEM; |
| 327 | 324 | ||
| 325 | /* | ||
| 326 | * populate_cache_leaves() may completely setup the cache leaves and | ||
| 327 | * shared_cpu_map or it may leave it partially setup. | ||
| 328 | */ | ||
| 328 | ret = populate_cache_leaves(cpu); | 329 | ret = populate_cache_leaves(cpu); |
| 329 | if (ret) | 330 | if (ret) |
| 330 | goto free_ci; | 331 | goto free_ci; |
| 331 | /* | 332 | /* |
| 332 | * For systems using DT for cache hierarchy, of_node and shared_cpu_map | 333 | * For systems using DT for cache hierarchy, fw_token |
| 333 | * will be set up here only if they are not populated already | 334 | * and shared_cpu_map will be set up here only if they are |
| 335 | * not populated already | ||
| 334 | */ | 336 | */ |
| 335 | ret = cache_shared_cpu_map_setup(cpu); | 337 | ret = cache_shared_cpu_map_setup(cpu); |
| 336 | if (ret) { | 338 | if (ret) { |
| @@ -338,7 +340,6 @@ static int detect_cache_attributes(unsigned int cpu) | |||
| 338 | goto free_ci; | 340 | goto free_ci; |
| 339 | } | 341 | } |
| 340 | 342 | ||
| 341 | cache_override_properties(cpu); | ||
| 342 | return 0; | 343 | return 0; |
| 343 | 344 | ||
| 344 | free_ci: | 345 | free_ci: |
diff --git a/drivers/perf/Kconfig b/drivers/perf/Kconfig index 28bb5a029558..08ebaf7cca8b 100644 --- a/drivers/perf/Kconfig +++ b/drivers/perf/Kconfig | |||
| @@ -6,30 +6,32 @@ menu "Performance monitor support" | |||
| 6 | depends on PERF_EVENTS | 6 | depends on PERF_EVENTS |
| 7 | 7 | ||
| 8 | config ARM_CCI_PMU | 8 | config ARM_CCI_PMU |
| 9 | bool | 9 | tristate "ARM CCI PMU driver" |
| 10 | depends on (ARM && CPU_V7) || ARM64 | ||
| 10 | select ARM_CCI | 11 | select ARM_CCI |
| 12 | help | ||
| 13 | Support for PMU events monitoring on the ARM CCI (Cache Coherent | ||
| 14 | Interconnect) family of products. | ||
| 15 | |||
| 16 | If compiled as a module, it will be called arm-cci. | ||
| 11 | 17 | ||
| 12 | config ARM_CCI400_PMU | 18 | config ARM_CCI400_PMU |
| 13 | bool "ARM CCI400 PMU support" | 19 | bool "support CCI-400" |
| 14 | depends on (ARM && CPU_V7) || ARM64 | 20 | default y |
| 21 | depends on ARM_CCI_PMU | ||
| 15 | select ARM_CCI400_COMMON | 22 | select ARM_CCI400_COMMON |
| 16 | select ARM_CCI_PMU | ||
| 17 | help | 23 | help |
| 18 | Support for PMU events monitoring on the ARM CCI-400 (cache coherent | 24 | CCI-400 provides 4 independent event counters counting events related |
| 19 | interconnect). CCI-400 supports counting events related to the | 25 | to the connected slave/master interfaces, plus a cycle counter. |
| 20 | connected slave/master interfaces. | ||
| 21 | 26 | ||
| 22 | config ARM_CCI5xx_PMU | 27 | config ARM_CCI5xx_PMU |
| 23 | bool "ARM CCI-500/CCI-550 PMU support" | 28 | bool "support CCI-500/CCI-550" |
| 24 | depends on (ARM && CPU_V7) || ARM64 | 29 | default y |
| 25 | select ARM_CCI_PMU | 30 | depends on ARM_CCI_PMU |
| 26 | help | 31 | help |
| 27 | Support for PMU events monitoring on the ARM CCI-500/CCI-550 cache | 32 | CCI-500/CCI-550 both provide 8 independent event counters, which can |
| 28 | coherent interconnects. Both of them provide 8 independent event counters, | 33 | count events pertaining to the slave/master interfaces as well as the |
| 29 | which can count events pertaining to the slave/master interfaces as well | 34 | internal events to the CCI. |
| 30 | as the internal events to the CCI. | ||
| 31 | |||
| 32 | If unsure, say Y | ||
| 33 | 35 | ||
| 34 | config ARM_CCN | 36 | config ARM_CCN |
| 35 | tristate "ARM CCN driver support" | 37 | tristate "ARM CCN driver support" |
| @@ -94,7 +96,7 @@ config XGENE_PMU | |||
| 94 | 96 | ||
| 95 | config ARM_SPE_PMU | 97 | config ARM_SPE_PMU |
| 96 | tristate "Enable support for the ARMv8.2 Statistical Profiling Extension" | 98 | tristate "Enable support for the ARMv8.2 Statistical Profiling Extension" |
| 97 | depends on PERF_EVENTS && ARM64 | 99 | depends on ARM64 |
| 98 | help | 100 | help |
| 99 | Enable perf support for the ARMv8.2 Statistical Profiling | 101 | Enable perf support for the ARMv8.2 Statistical Profiling |
| 100 | Extension, which provides periodic sampling of operations in | 102 | Extension, which provides periodic sampling of operations in |
diff --git a/drivers/perf/arm-cci.c b/drivers/perf/arm-cci.c index 383b2d3dcbc6..0d09d8e669cd 100644 --- a/drivers/perf/arm-cci.c +++ b/drivers/perf/arm-cci.c | |||
| @@ -120,9 +120,9 @@ enum cci_models { | |||
| 120 | 120 | ||
| 121 | static void pmu_write_counters(struct cci_pmu *cci_pmu, | 121 | static void pmu_write_counters(struct cci_pmu *cci_pmu, |
| 122 | unsigned long *mask); | 122 | unsigned long *mask); |
| 123 | static ssize_t cci_pmu_format_show(struct device *dev, | 123 | static ssize_t __maybe_unused cci_pmu_format_show(struct device *dev, |
| 124 | struct device_attribute *attr, char *buf); | 124 | struct device_attribute *attr, char *buf); |
| 125 | static ssize_t cci_pmu_event_show(struct device *dev, | 125 | static ssize_t __maybe_unused cci_pmu_event_show(struct device *dev, |
| 126 | struct device_attribute *attr, char *buf); | 126 | struct device_attribute *attr, char *buf); |
| 127 | 127 | ||
| 128 | #define CCI_EXT_ATTR_ENTRY(_name, _func, _config) \ | 128 | #define CCI_EXT_ATTR_ENTRY(_name, _func, _config) \ |
| @@ -1184,16 +1184,11 @@ static int cci_pmu_add(struct perf_event *event, int flags) | |||
| 1184 | struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events; | 1184 | struct cci_pmu_hw_events *hw_events = &cci_pmu->hw_events; |
| 1185 | struct hw_perf_event *hwc = &event->hw; | 1185 | struct hw_perf_event *hwc = &event->hw; |
| 1186 | int idx; | 1186 | int idx; |
| 1187 | int err = 0; | ||
| 1188 | |||
| 1189 | perf_pmu_disable(event->pmu); | ||
| 1190 | 1187 | ||
| 1191 | /* If we don't have a space for the counter then finish early. */ | 1188 | /* If we don't have a space for the counter then finish early. */ |
| 1192 | idx = pmu_get_event_idx(hw_events, event); | 1189 | idx = pmu_get_event_idx(hw_events, event); |
| 1193 | if (idx < 0) { | 1190 | if (idx < 0) |
| 1194 | err = idx; | 1191 | return idx; |
| 1195 | goto out; | ||
| 1196 | } | ||
| 1197 | 1192 | ||
| 1198 | event->hw.idx = idx; | 1193 | event->hw.idx = idx; |
| 1199 | hw_events->events[idx] = event; | 1194 | hw_events->events[idx] = event; |
| @@ -1205,9 +1200,7 @@ static int cci_pmu_add(struct perf_event *event, int flags) | |||
| 1205 | /* Propagate our changes to the userspace mapping. */ | 1200 | /* Propagate our changes to the userspace mapping. */ |
| 1206 | perf_event_update_userpage(event); | 1201 | perf_event_update_userpage(event); |
| 1207 | 1202 | ||
| 1208 | out: | 1203 | return 0; |
| 1209 | perf_pmu_enable(event->pmu); | ||
| 1210 | return err; | ||
| 1211 | } | 1204 | } |
| 1212 | 1205 | ||
| 1213 | static void cci_pmu_del(struct perf_event *event, int flags) | 1206 | static void cci_pmu_del(struct perf_event *event, int flags) |
| @@ -1304,15 +1297,6 @@ static int __hw_perf_event_init(struct perf_event *event) | |||
| 1304 | */ | 1297 | */ |
| 1305 | hwc->config_base |= (unsigned long)mapping; | 1298 | hwc->config_base |= (unsigned long)mapping; |
| 1306 | 1299 | ||
| 1307 | /* | ||
| 1308 | * Limit the sample_period to half of the counter width. That way, the | ||
| 1309 | * new counter value is far less likely to overtake the previous one | ||
| 1310 | * unless you have some serious IRQ latency issues. | ||
| 1311 | */ | ||
| 1312 | hwc->sample_period = CCI_PMU_CNTR_MASK >> 1; | ||
| 1313 | hwc->last_period = hwc->sample_period; | ||
| 1314 | local64_set(&hwc->period_left, hwc->sample_period); | ||
| 1315 | |||
| 1316 | if (event->group_leader != event) { | 1300 | if (event->group_leader != event) { |
| 1317 | if (validate_group(event) != 0) | 1301 | if (validate_group(event) != 0) |
| 1318 | return -EINVAL; | 1302 | return -EINVAL; |
| @@ -1423,6 +1407,7 @@ static int cci_pmu_init(struct cci_pmu *cci_pmu, struct platform_device *pdev) | |||
| 1423 | pmu_format_attr_group.attrs = model->format_attrs; | 1407 | pmu_format_attr_group.attrs = model->format_attrs; |
| 1424 | 1408 | ||
| 1425 | cci_pmu->pmu = (struct pmu) { | 1409 | cci_pmu->pmu = (struct pmu) { |
| 1410 | .module = THIS_MODULE, | ||
| 1426 | .name = cci_pmu->model->name, | 1411 | .name = cci_pmu->model->name, |
| 1427 | .task_ctx_nr = perf_invalid_context, | 1412 | .task_ctx_nr = perf_invalid_context, |
| 1428 | .pmu_enable = cci_pmu_enable, | 1413 | .pmu_enable = cci_pmu_enable, |
| @@ -1466,7 +1451,7 @@ static int cci_pmu_offline_cpu(unsigned int cpu) | |||
| 1466 | return 0; | 1451 | return 0; |
| 1467 | } | 1452 | } |
| 1468 | 1453 | ||
| 1469 | static struct cci_pmu_model cci_pmu_models[] = { | 1454 | static __maybe_unused struct cci_pmu_model cci_pmu_models[] = { |
| 1470 | #ifdef CONFIG_ARM_CCI400_PMU | 1455 | #ifdef CONFIG_ARM_CCI400_PMU |
| 1471 | [CCI400_R0] = { | 1456 | [CCI400_R0] = { |
| 1472 | .name = "CCI_400", | 1457 | .name = "CCI_400", |
| @@ -1588,6 +1573,7 @@ static const struct of_device_id arm_cci_pmu_matches[] = { | |||
| 1588 | #endif | 1573 | #endif |
| 1589 | {}, | 1574 | {}, |
| 1590 | }; | 1575 | }; |
| 1576 | MODULE_DEVICE_TABLE(of, arm_cci_pmu_matches); | ||
| 1591 | 1577 | ||
| 1592 | static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs) | 1578 | static bool is_duplicate_irq(int irq, int *irqs, int nr_irqs) |
| 1593 | { | 1579 | { |
| @@ -1709,14 +1695,27 @@ static int cci_pmu_probe(struct platform_device *pdev) | |||
| 1709 | return 0; | 1695 | return 0; |
| 1710 | } | 1696 | } |
| 1711 | 1697 | ||
| 1698 | static int cci_pmu_remove(struct platform_device *pdev) | ||
| 1699 | { | ||
| 1700 | if (!g_cci_pmu) | ||
| 1701 | return 0; | ||
| 1702 | |||
| 1703 | cpuhp_remove_state(CPUHP_AP_PERF_ARM_CCI_ONLINE); | ||
| 1704 | perf_pmu_unregister(&g_cci_pmu->pmu); | ||
| 1705 | g_cci_pmu = NULL; | ||
| 1706 | |||
| 1707 | return 0; | ||
| 1708 | } | ||
| 1709 | |||
| 1712 | static struct platform_driver cci_pmu_driver = { | 1710 | static struct platform_driver cci_pmu_driver = { |
| 1713 | .driver = { | 1711 | .driver = { |
| 1714 | .name = DRIVER_NAME, | 1712 | .name = DRIVER_NAME, |
| 1715 | .of_match_table = arm_cci_pmu_matches, | 1713 | .of_match_table = arm_cci_pmu_matches, |
| 1716 | }, | 1714 | }, |
| 1717 | .probe = cci_pmu_probe, | 1715 | .probe = cci_pmu_probe, |
| 1716 | .remove = cci_pmu_remove, | ||
| 1718 | }; | 1717 | }; |
| 1719 | 1718 | ||
| 1720 | builtin_platform_driver(cci_pmu_driver); | 1719 | module_platform_driver(cci_pmu_driver); |
| 1721 | MODULE_LICENSE("GPL"); | 1720 | MODULE_LICENSE("GPL v2"); |
| 1722 | MODULE_DESCRIPTION("ARM CCI PMU support"); | 1721 | MODULE_DESCRIPTION("ARM CCI PMU support"); |
diff --git a/drivers/perf/arm-ccn.c b/drivers/perf/arm-ccn.c index 65b7e4042ece..b416ee18e6bb 100644 --- a/drivers/perf/arm-ccn.c +++ b/drivers/perf/arm-ccn.c | |||
| @@ -736,7 +736,7 @@ static int arm_ccn_pmu_event_init(struct perf_event *event) | |||
| 736 | ccn = pmu_to_arm_ccn(event->pmu); | 736 | ccn = pmu_to_arm_ccn(event->pmu); |
| 737 | 737 | ||
| 738 | if (hw->sample_period) { | 738 | if (hw->sample_period) { |
| 739 | dev_warn(ccn->dev, "Sampling not supported!\n"); | 739 | dev_dbg(ccn->dev, "Sampling not supported!\n"); |
| 740 | return -EOPNOTSUPP; | 740 | return -EOPNOTSUPP; |
| 741 | } | 741 | } |
| 742 | 742 | ||
| @@ -744,12 +744,12 @@ static int arm_ccn_pmu_event_init(struct perf_event *event) | |||
| 744 | event->attr.exclude_kernel || event->attr.exclude_hv || | 744 | event->attr.exclude_kernel || event->attr.exclude_hv || |
| 745 | event->attr.exclude_idle || event->attr.exclude_host || | 745 | event->attr.exclude_idle || event->attr.exclude_host || |
| 746 | event->attr.exclude_guest) { | 746 | event->attr.exclude_guest) { |
| 747 | dev_warn(ccn->dev, "Can't exclude execution levels!\n"); | 747 | dev_dbg(ccn->dev, "Can't exclude execution levels!\n"); |
| 748 | return -EINVAL; | 748 | return -EINVAL; |
| 749 | } | 749 | } |
| 750 | 750 | ||
| 751 | if (event->cpu < 0) { | 751 | if (event->cpu < 0) { |
| 752 | dev_warn(ccn->dev, "Can't provide per-task data!\n"); | 752 | dev_dbg(ccn->dev, "Can't provide per-task data!\n"); |
| 753 | return -EOPNOTSUPP; | 753 | return -EOPNOTSUPP; |
| 754 | } | 754 | } |
| 755 | /* | 755 | /* |
| @@ -771,13 +771,13 @@ static int arm_ccn_pmu_event_init(struct perf_event *event) | |||
| 771 | switch (type) { | 771 | switch (type) { |
| 772 | case CCN_TYPE_MN: | 772 | case CCN_TYPE_MN: |
| 773 | if (node_xp != ccn->mn_id) { | 773 | if (node_xp != ccn->mn_id) { |
| 774 | dev_warn(ccn->dev, "Invalid MN ID %d!\n", node_xp); | 774 | dev_dbg(ccn->dev, "Invalid MN ID %d!\n", node_xp); |
| 775 | return -EINVAL; | 775 | return -EINVAL; |
| 776 | } | 776 | } |
| 777 | break; | 777 | break; |
| 778 | case CCN_TYPE_XP: | 778 | case CCN_TYPE_XP: |
| 779 | if (node_xp >= ccn->num_xps) { | 779 | if (node_xp >= ccn->num_xps) { |
| 780 | dev_warn(ccn->dev, "Invalid XP ID %d!\n", node_xp); | 780 | dev_dbg(ccn->dev, "Invalid XP ID %d!\n", node_xp); |
| 781 | return -EINVAL; | 781 | return -EINVAL; |
| 782 | } | 782 | } |
| 783 | break; | 783 | break; |
| @@ -785,11 +785,11 @@ static int arm_ccn_pmu_event_init(struct perf_event *event) | |||
| 785 | break; | 785 | break; |
| 786 | default: | 786 | default: |
| 787 | if (node_xp >= ccn->num_nodes) { | 787 | if (node_xp >= ccn->num_nodes) { |
| 788 | dev_warn(ccn->dev, "Invalid node ID %d!\n", node_xp); | 788 | dev_dbg(ccn->dev, "Invalid node ID %d!\n", node_xp); |
| 789 | return -EINVAL; | 789 | return -EINVAL; |
| 790 | } | 790 | } |
| 791 | if (!arm_ccn_pmu_type_eq(type, ccn->node[node_xp].type)) { | 791 | if (!arm_ccn_pmu_type_eq(type, ccn->node[node_xp].type)) { |
| 792 | dev_warn(ccn->dev, "Invalid type 0x%x for node %d!\n", | 792 | dev_dbg(ccn->dev, "Invalid type 0x%x for node %d!\n", |
| 793 | type, node_xp); | 793 | type, node_xp); |
| 794 | return -EINVAL; | 794 | return -EINVAL; |
| 795 | } | 795 | } |
| @@ -808,19 +808,19 @@ static int arm_ccn_pmu_event_init(struct perf_event *event) | |||
| 808 | if (event_id != e->event) | 808 | if (event_id != e->event) |
| 809 | continue; | 809 | continue; |
| 810 | if (e->num_ports && port >= e->num_ports) { | 810 | if (e->num_ports && port >= e->num_ports) { |
| 811 | dev_warn(ccn->dev, "Invalid port %d for node/XP %d!\n", | 811 | dev_dbg(ccn->dev, "Invalid port %d for node/XP %d!\n", |
| 812 | port, node_xp); | 812 | port, node_xp); |
| 813 | return -EINVAL; | 813 | return -EINVAL; |
| 814 | } | 814 | } |
| 815 | if (e->num_vcs && vc >= e->num_vcs) { | 815 | if (e->num_vcs && vc >= e->num_vcs) { |
| 816 | dev_warn(ccn->dev, "Invalid vc %d for node/XP %d!\n", | 816 | dev_dbg(ccn->dev, "Invalid vc %d for node/XP %d!\n", |
| 817 | vc, node_xp); | 817 | vc, node_xp); |
| 818 | return -EINVAL; | 818 | return -EINVAL; |
| 819 | } | 819 | } |
| 820 | valid = 1; | 820 | valid = 1; |
| 821 | } | 821 | } |
| 822 | if (!valid) { | 822 | if (!valid) { |
| 823 | dev_warn(ccn->dev, "Invalid event 0x%x for node/XP %d!\n", | 823 | dev_dbg(ccn->dev, "Invalid event 0x%x for node/XP %d!\n", |
| 824 | event_id, node_xp); | 824 | event_id, node_xp); |
| 825 | return -EINVAL; | 825 | return -EINVAL; |
| 826 | } | 826 | } |
| @@ -1594,4 +1594,4 @@ module_init(arm_ccn_init); | |||
| 1594 | module_exit(arm_ccn_exit); | 1594 | module_exit(arm_ccn_exit); |
| 1595 | 1595 | ||
| 1596 | MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>"); | 1596 | MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>"); |
| 1597 | MODULE_LICENSE("GPL"); | 1597 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c index 1a0d340b65cf..a6347d487635 100644 --- a/drivers/perf/arm_pmu.c +++ b/drivers/perf/arm_pmu.c | |||
| @@ -339,7 +339,7 @@ static irqreturn_t armpmu_dispatch_irq(int irq, void *dev) | |||
| 339 | return IRQ_NONE; | 339 | return IRQ_NONE; |
| 340 | 340 | ||
| 341 | start_clock = sched_clock(); | 341 | start_clock = sched_clock(); |
| 342 | ret = armpmu->handle_irq(irq, armpmu); | 342 | ret = armpmu->handle_irq(armpmu); |
| 343 | finish_clock = sched_clock(); | 343 | finish_clock = sched_clock(); |
| 344 | 344 | ||
| 345 | perf_sample_event_took(finish_clock - start_clock); | 345 | perf_sample_event_took(finish_clock - start_clock); |
diff --git a/drivers/perf/arm_spe_pmu.c b/drivers/perf/arm_spe_pmu.c index 28bb642af18b..54ec278d2fc4 100644 --- a/drivers/perf/arm_spe_pmu.c +++ b/drivers/perf/arm_spe_pmu.c | |||
| @@ -131,8 +131,7 @@ static ssize_t arm_spe_pmu_cap_show(struct device *dev, | |||
| 131 | struct device_attribute *attr, | 131 | struct device_attribute *attr, |
| 132 | char *buf) | 132 | char *buf) |
| 133 | { | 133 | { |
| 134 | struct platform_device *pdev = to_platform_device(dev); | 134 | struct arm_spe_pmu *spe_pmu = dev_get_drvdata(dev); |
| 135 | struct arm_spe_pmu *spe_pmu = platform_get_drvdata(pdev); | ||
| 136 | struct dev_ext_attribute *ea = | 135 | struct dev_ext_attribute *ea = |
| 137 | container_of(attr, struct dev_ext_attribute, attr); | 136 | container_of(attr, struct dev_ext_attribute, attr); |
| 138 | int cap = (long)ea->var; | 137 | int cap = (long)ea->var; |
| @@ -247,8 +246,7 @@ static ssize_t arm_spe_pmu_get_attr_cpumask(struct device *dev, | |||
| 247 | struct device_attribute *attr, | 246 | struct device_attribute *attr, |
| 248 | char *buf) | 247 | char *buf) |
| 249 | { | 248 | { |
| 250 | struct platform_device *pdev = to_platform_device(dev); | 249 | struct arm_spe_pmu *spe_pmu = dev_get_drvdata(dev); |
| 251 | struct arm_spe_pmu *spe_pmu = platform_get_drvdata(pdev); | ||
| 252 | 250 | ||
| 253 | return cpumap_print_to_pagebuf(true, buf, &spe_pmu->supported_cpus); | 251 | return cpumap_print_to_pagebuf(true, buf, &spe_pmu->supported_cpus); |
| 254 | } | 252 | } |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 8758a2a9e6c1..4b35a66383f9 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
| @@ -1299,4 +1299,23 @@ static inline int lpit_read_residency_count_address(u64 *address) | |||
| 1299 | } | 1299 | } |
| 1300 | #endif | 1300 | #endif |
| 1301 | 1301 | ||
| 1302 | #ifdef CONFIG_ACPI_PPTT | ||
| 1303 | int find_acpi_cpu_topology(unsigned int cpu, int level); | ||
| 1304 | int find_acpi_cpu_topology_package(unsigned int cpu); | ||
| 1305 | int find_acpi_cpu_cache_topology(unsigned int cpu, int level); | ||
| 1306 | #else | ||
| 1307 | static inline int find_acpi_cpu_topology(unsigned int cpu, int level) | ||
| 1308 | { | ||
| 1309 | return -EINVAL; | ||
| 1310 | } | ||
| 1311 | static inline int find_acpi_cpu_topology_package(unsigned int cpu) | ||
| 1312 | { | ||
| 1313 | return -EINVAL; | ||
| 1314 | } | ||
| 1315 | static inline int find_acpi_cpu_cache_topology(unsigned int cpu, int level) | ||
| 1316 | { | ||
| 1317 | return -EINVAL; | ||
| 1318 | } | ||
| 1319 | #endif | ||
| 1320 | |||
| 1302 | #endif /*_LINUX_ACPI_H*/ | 1321 | #endif /*_LINUX_ACPI_H*/ |
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h index a031897fca76..ca1d2cc2cdfa 100644 --- a/include/linux/arm-smccc.h +++ b/include/linux/arm-smccc.h | |||
| @@ -80,6 +80,11 @@ | |||
| 80 | ARM_SMCCC_SMC_32, \ | 80 | ARM_SMCCC_SMC_32, \ |
| 81 | 0, 0x8000) | 81 | 0, 0x8000) |
| 82 | 82 | ||
| 83 | #define ARM_SMCCC_ARCH_WORKAROUND_2 \ | ||
| 84 | ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ | ||
| 85 | ARM_SMCCC_SMC_32, \ | ||
| 86 | 0, 0x7fff) | ||
| 87 | |||
| 83 | #ifndef __ASSEMBLY__ | 88 | #ifndef __ASSEMBLY__ |
| 84 | 89 | ||
| 85 | #include <linux/linkage.h> | 90 | #include <linux/linkage.h> |
| @@ -291,5 +296,10 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, | |||
| 291 | */ | 296 | */ |
| 292 | #define arm_smccc_1_1_hvc(...) __arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__) | 297 | #define arm_smccc_1_1_hvc(...) __arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__) |
| 293 | 298 | ||
| 299 | /* Return codes defined in ARM DEN 0070A */ | ||
| 300 | #define SMCCC_RET_SUCCESS 0 | ||
| 301 | #define SMCCC_RET_NOT_SUPPORTED -1 | ||
| 302 | #define SMCCC_RET_NOT_REQUIRED -2 | ||
| 303 | |||
| 294 | #endif /*__ASSEMBLY__*/ | 304 | #endif /*__ASSEMBLY__*/ |
| 295 | #endif /*__LINUX_ARM_SMCCC_H*/ | 305 | #endif /*__LINUX_ARM_SMCCC_H*/ |
diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h index 3d9805297cda..70e19bc6cc9f 100644 --- a/include/linux/cacheinfo.h +++ b/include/linux/cacheinfo.h | |||
| @@ -34,9 +34,8 @@ enum cache_type { | |||
| 34 | * @shared_cpu_map: logical cpumask representing all the cpus sharing | 34 | * @shared_cpu_map: logical cpumask representing all the cpus sharing |
| 35 | * this cache node | 35 | * this cache node |
| 36 | * @attributes: bitfield representing various cache attributes | 36 | * @attributes: bitfield representing various cache attributes |
| 37 | * @of_node: if devicetree is used, this represents either the cpu node in | 37 | * @fw_token: Unique value used to determine if different cacheinfo |
| 38 | * case there's no explicit cache node or the cache node itself in the | 38 | * structures represent a single hardware cache instance. |
| 39 | * device tree | ||
| 40 | * @disable_sysfs: indicates whether this node is visible to the user via | 39 | * @disable_sysfs: indicates whether this node is visible to the user via |
| 41 | * sysfs or not | 40 | * sysfs or not |
| 42 | * @priv: pointer to any private data structure specific to particular | 41 | * @priv: pointer to any private data structure specific to particular |
| @@ -65,8 +64,7 @@ struct cacheinfo { | |||
| 65 | #define CACHE_ALLOCATE_POLICY_MASK \ | 64 | #define CACHE_ALLOCATE_POLICY_MASK \ |
| 66 | (CACHE_READ_ALLOCATE | CACHE_WRITE_ALLOCATE) | 65 | (CACHE_READ_ALLOCATE | CACHE_WRITE_ALLOCATE) |
| 67 | #define CACHE_ID BIT(4) | 66 | #define CACHE_ID BIT(4) |
| 68 | 67 | void *fw_token; | |
| 69 | struct device_node *of_node; | ||
| 70 | bool disable_sysfs; | 68 | bool disable_sysfs; |
| 71 | void *priv; | 69 | void *priv; |
| 72 | }; | 70 | }; |
| @@ -99,6 +97,23 @@ int func(unsigned int cpu) \ | |||
| 99 | struct cpu_cacheinfo *get_cpu_cacheinfo(unsigned int cpu); | 97 | struct cpu_cacheinfo *get_cpu_cacheinfo(unsigned int cpu); |
| 100 | int init_cache_level(unsigned int cpu); | 98 | int init_cache_level(unsigned int cpu); |
| 101 | int populate_cache_leaves(unsigned int cpu); | 99 | int populate_cache_leaves(unsigned int cpu); |
| 100 | int cache_setup_acpi(unsigned int cpu); | ||
| 101 | #ifndef CONFIG_ACPI_PPTT | ||
| 102 | /* | ||
| 103 | * acpi_find_last_cache_level is only called on ACPI enabled | ||
| 104 | * platforms using the PPTT for topology. This means that if | ||
| 105 | * the platform supports other firmware configuration methods | ||
| 106 | * we need to stub out the call when ACPI is disabled. | ||
| 107 | * ACPI enabled platforms not using PPTT won't be making calls | ||
| 108 | * to this function so we need not worry about them. | ||
| 109 | */ | ||
| 110 | static inline int acpi_find_last_cache_level(unsigned int cpu) | ||
| 111 | { | ||
| 112 | return 0; | ||
| 113 | } | ||
| 114 | #else | ||
| 115 | int acpi_find_last_cache_level(unsigned int cpu); | ||
| 116 | #endif | ||
| 102 | 117 | ||
| 103 | const struct attribute_group *cache_get_priv_group(struct cacheinfo *this_leaf); | 118 | const struct attribute_group *cache_get_priv_group(struct cacheinfo *this_leaf); |
| 104 | 119 | ||
diff --git a/include/linux/perf/arm_pmu.h b/include/linux/perf/arm_pmu.h index 40036a57d072..ad5444491975 100644 --- a/include/linux/perf/arm_pmu.h +++ b/include/linux/perf/arm_pmu.h | |||
| @@ -78,7 +78,7 @@ struct arm_pmu { | |||
| 78 | struct pmu pmu; | 78 | struct pmu pmu; |
| 79 | cpumask_t supported_cpus; | 79 | cpumask_t supported_cpus; |
| 80 | char *name; | 80 | char *name; |
| 81 | irqreturn_t (*handle_irq)(int irq_num, void *dev); | 81 | irqreturn_t (*handle_irq)(struct arm_pmu *pmu); |
| 82 | void (*enable)(struct perf_event *event); | 82 | void (*enable)(struct perf_event *event); |
| 83 | void (*disable)(struct perf_event *event); | 83 | void (*disable)(struct perf_event *event); |
| 84 | int (*get_event_idx)(struct pmu_hw_events *hw_events, | 84 | int (*get_event_idx)(struct pmu_hw_events *hw_events, |
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c index a4c1b76240df..2d9b4795edb2 100644 --- a/virt/kvm/arm/arm.c +++ b/virt/kvm/arm/arm.c | |||
| @@ -1490,6 +1490,10 @@ static int init_hyp_mode(void) | |||
| 1490 | } | 1490 | } |
| 1491 | } | 1491 | } |
| 1492 | 1492 | ||
| 1493 | err = hyp_map_aux_data(); | ||
| 1494 | if (err) | ||
| 1495 | kvm_err("Cannot map host auxilary data: %d\n", err); | ||
| 1496 | |||
| 1493 | return 0; | 1497 | return 0; |
| 1494 | 1498 | ||
| 1495 | out_err: | 1499 | out_err: |
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c index c4762bef13c6..c95ab4c5a475 100644 --- a/virt/kvm/arm/psci.c +++ b/virt/kvm/arm/psci.c | |||
| @@ -405,7 +405,7 @@ static int kvm_psci_call(struct kvm_vcpu *vcpu) | |||
| 405 | int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) | 405 | int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) |
| 406 | { | 406 | { |
| 407 | u32 func_id = smccc_get_function(vcpu); | 407 | u32 func_id = smccc_get_function(vcpu); |
| 408 | u32 val = PSCI_RET_NOT_SUPPORTED; | 408 | u32 val = SMCCC_RET_NOT_SUPPORTED; |
| 409 | u32 feature; | 409 | u32 feature; |
| 410 | 410 | ||
| 411 | switch (func_id) { | 411 | switch (func_id) { |
| @@ -417,7 +417,21 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) | |||
| 417 | switch(feature) { | 417 | switch(feature) { |
| 418 | case ARM_SMCCC_ARCH_WORKAROUND_1: | 418 | case ARM_SMCCC_ARCH_WORKAROUND_1: |
| 419 | if (kvm_arm_harden_branch_predictor()) | 419 | if (kvm_arm_harden_branch_predictor()) |
| 420 | val = 0; | 420 | val = SMCCC_RET_SUCCESS; |
| 421 | break; | ||
| 422 | case ARM_SMCCC_ARCH_WORKAROUND_2: | ||
| 423 | switch (kvm_arm_have_ssbd()) { | ||
| 424 | case KVM_SSBD_FORCE_DISABLE: | ||
| 425 | case KVM_SSBD_UNKNOWN: | ||
| 426 | break; | ||
| 427 | case KVM_SSBD_KERNEL: | ||
| 428 | val = SMCCC_RET_SUCCESS; | ||
| 429 | break; | ||
| 430 | case KVM_SSBD_FORCE_ENABLE: | ||
| 431 | case KVM_SSBD_MITIGATED: | ||
| 432 | val = SMCCC_RET_NOT_REQUIRED; | ||
| 433 | break; | ||
| 434 | } | ||
| 421 | break; | 435 | break; |
| 422 | } | 436 | } |
| 423 | break; | 437 | break; |
