Commit 6f9c8900 authored by Daniel Lezcano's avatar Daniel Lezcano

Merge tag 'arch-timer-errata' of...

Merge tag 'arch-timer-errata' of git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms into clockevents/4.12

arm64 arch timer workaround series, including the base patches
that will also go via the arm64 tree.
Signed-off-by: default avatarDaniel Lezcano <daniel.lezcano@linaro.org>
parents 28e71e2f d003d029
...@@ -54,6 +54,7 @@ stable kernels. ...@@ -54,6 +54,7 @@ stable kernels.
| ARM | Cortex-A57 | #852523 | N/A | | ARM | Cortex-A57 | #852523 | N/A |
| ARM | Cortex-A57 | #834220 | ARM64_ERRATUM_834220 | | ARM | Cortex-A57 | #834220 | ARM64_ERRATUM_834220 |
| ARM | Cortex-A72 | #853709 | N/A | | ARM | Cortex-A72 | #853709 | N/A |
| ARM | Cortex-A73 | #858921 | ARM64_ERRATUM_858921 |
| ARM | MMU-500 | #841119,#826419 | N/A | | ARM | MMU-500 | #841119,#826419 | N/A |
| | | | | | | | | |
| Cavium | ThunderX ITS | #22375, #24313 | CAVIUM_ERRATUM_22375 | | Cavium | ThunderX ITS | #22375, #24313 | CAVIUM_ERRATUM_22375 |
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <linux/bug.h> #include <linux/bug.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/jump_label.h> #include <linux/jump_label.h>
#include <linux/smp.h>
#include <linux/types.h> #include <linux/types.h>
#include <clocksource/arm_arch_timer.h> #include <clocksource/arm_arch_timer.h>
...@@ -37,23 +38,43 @@ extern struct static_key_false arch_timer_read_ool_enabled; ...@@ -37,23 +38,43 @@ extern struct static_key_false arch_timer_read_ool_enabled;
#define needs_unstable_timer_counter_workaround() false #define needs_unstable_timer_counter_workaround() false
#endif #endif
enum arch_timer_erratum_match_type {
ate_match_dt,
ate_match_local_cap_id,
ate_match_acpi_oem_info,
};
struct clock_event_device;
struct arch_timer_erratum_workaround { struct arch_timer_erratum_workaround {
const char *id; /* Indicate the Erratum ID */ enum arch_timer_erratum_match_type match_type;
const void *id;
const char *desc;
u32 (*read_cntp_tval_el0)(void); u32 (*read_cntp_tval_el0)(void);
u32 (*read_cntv_tval_el0)(void); u32 (*read_cntv_tval_el0)(void);
u64 (*read_cntvct_el0)(void); u64 (*read_cntvct_el0)(void);
int (*set_next_event_phys)(unsigned long, struct clock_event_device *);
int (*set_next_event_virt)(unsigned long, struct clock_event_device *);
}; };
extern const struct arch_timer_erratum_workaround *timer_unstable_counter_workaround; DECLARE_PER_CPU(const struct arch_timer_erratum_workaround *,
timer_unstable_counter_workaround);
#define arch_timer_reg_read_stable(reg) \ #define arch_timer_reg_read_stable(reg) \
({ \ ({ \
u64 _val; \ u64 _val; \
if (needs_unstable_timer_counter_workaround()) \ if (needs_unstable_timer_counter_workaround()) { \
_val = timer_unstable_counter_workaround->read_##reg();\ const struct arch_timer_erratum_workaround *wa; \
preempt_disable(); \
wa = __this_cpu_read(timer_unstable_counter_workaround); \
if (wa && wa->read_##reg) \
_val = wa->read_##reg(); \
else \ else \
_val = read_sysreg(reg); \ _val = read_sysreg(reg); \
preempt_enable(); \
} else { \
_val = read_sysreg(reg); \
} \
_val; \ _val; \
}) })
......
...@@ -37,7 +37,8 @@ ...@@ -37,7 +37,8 @@
#define ARM64_HAS_NO_FPSIMD 16 #define ARM64_HAS_NO_FPSIMD 16
#define ARM64_WORKAROUND_REPEAT_TLBI 17 #define ARM64_WORKAROUND_REPEAT_TLBI 17
#define ARM64_WORKAROUND_QCOM_FALKOR_E1003 18 #define ARM64_WORKAROUND_QCOM_FALKOR_E1003 18
#define ARM64_WORKAROUND_858921 19
#define ARM64_NCAPS 19 #define ARM64_NCAPS 20
#endif /* __ASM_CPUCAPS_H */ #endif /* __ASM_CPUCAPS_H */
...@@ -80,6 +80,7 @@ ...@@ -80,6 +80,7 @@
#define ARM_CPU_PART_FOUNDATION 0xD00 #define ARM_CPU_PART_FOUNDATION 0xD00
#define ARM_CPU_PART_CORTEX_A57 0xD07 #define ARM_CPU_PART_CORTEX_A57 0xD07
#define ARM_CPU_PART_CORTEX_A53 0xD03 #define ARM_CPU_PART_CORTEX_A53 0xD03
#define ARM_CPU_PART_CORTEX_A73 0xD09
#define APM_CPU_PART_POTENZA 0x000 #define APM_CPU_PART_POTENZA 0x000
...@@ -92,6 +93,7 @@ ...@@ -92,6 +93,7 @@
#define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53) #define MIDR_CORTEX_A53 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
#define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57) #define MIDR_CORTEX_A57 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
#define MIDR_CORTEX_A73 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A73)
#define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX) #define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
#define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX) #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
#define MIDR_QCOM_FALKOR_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR_V1) #define MIDR_QCOM_FALKOR_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR_V1)
......
...@@ -175,6 +175,8 @@ ...@@ -175,6 +175,8 @@
#define ESR_ELx_SYS64_ISS_SYS_CTR_READ (ESR_ELx_SYS64_ISS_SYS_CTR | \ #define ESR_ELx_SYS64_ISS_SYS_CTR_READ (ESR_ELx_SYS64_ISS_SYS_CTR | \
ESR_ELx_SYS64_ISS_DIR_READ) ESR_ELx_SYS64_ISS_DIR_READ)
#define ESR_ELx_SYS64_ISS_SYS_CNTVCT (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \
ESR_ELx_SYS64_ISS_DIR_READ)
#ifndef __ASSEMBLY__ #ifndef __ASSEMBLY__
#include <asm/types.h> #include <asm/types.h>
......
...@@ -53,6 +53,13 @@ static int cpu_enable_trap_ctr_access(void *__unused) ...@@ -53,6 +53,13 @@ static int cpu_enable_trap_ctr_access(void *__unused)
.midr_range_min = min, \ .midr_range_min = min, \
.midr_range_max = max .midr_range_max = max
#define MIDR_ALL_VERSIONS(model) \
.def_scope = SCOPE_LOCAL_CPU, \
.matches = is_affected_midr_range, \
.midr_model = model, \
.midr_range_min = 0, \
.midr_range_max = (MIDR_VARIANT_MASK | MIDR_REVISION_MASK)
const struct arm64_cpu_capabilities arm64_errata[] = { const struct arm64_cpu_capabilities arm64_errata[] = {
#if defined(CONFIG_ARM64_ERRATUM_826319) || \ #if defined(CONFIG_ARM64_ERRATUM_826319) || \
defined(CONFIG_ARM64_ERRATUM_827319) || \ defined(CONFIG_ARM64_ERRATUM_827319) || \
...@@ -150,6 +157,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = { ...@@ -150,6 +157,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
MIDR_CPU_VAR_REV(0, 0), MIDR_CPU_VAR_REV(0, 0),
MIDR_CPU_VAR_REV(0, 0)), MIDR_CPU_VAR_REV(0, 0)),
}, },
#endif
#ifdef CONFIG_ARM64_ERRATUM_858921
{
/* Cortex-A73 all versions */
.desc = "ARM erratum 858921",
.capability = ARM64_WORKAROUND_858921,
MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
},
#endif #endif
{ {
} }
......
...@@ -1090,20 +1090,29 @@ static void __init setup_feature_capabilities(void) ...@@ -1090,20 +1090,29 @@ static void __init setup_feature_capabilities(void)
* Check if the current CPU has a given feature capability. * Check if the current CPU has a given feature capability.
* Should be called from non-preemptible context. * Should be called from non-preemptible context.
*/ */
bool this_cpu_has_cap(unsigned int cap) static bool __this_cpu_has_cap(const struct arm64_cpu_capabilities *cap_array,
unsigned int cap)
{ {
const struct arm64_cpu_capabilities *caps; const struct arm64_cpu_capabilities *caps;
if (WARN_ON(preemptible())) if (WARN_ON(preemptible()))
return false; return false;
for (caps = arm64_features; caps->desc; caps++) for (caps = cap_array; caps->desc; caps++)
if (caps->capability == cap && caps->matches) if (caps->capability == cap && caps->matches)
return caps->matches(caps, SCOPE_LOCAL_CPU); return caps->matches(caps, SCOPE_LOCAL_CPU);
return false; return false;
} }
extern const struct arm64_cpu_capabilities arm64_errata[];
bool this_cpu_has_cap(unsigned int cap)
{
return (__this_cpu_has_cap(arm64_features, cap) ||
__this_cpu_has_cap(arm64_errata, cap));
}
void __init setup_cpu_features(void) void __init setup_cpu_features(void)
{ {
u32 cwg; u32 cwg;
......
...@@ -505,6 +505,14 @@ static void ctr_read_handler(unsigned int esr, struct pt_regs *regs) ...@@ -505,6 +505,14 @@ static void ctr_read_handler(unsigned int esr, struct pt_regs *regs)
regs->pc += 4; regs->pc += 4;
} }
static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs)
{
int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT;
pt_regs_write_reg(regs, rt, arch_counter_get_cntvct());
regs->pc += 4;
}
struct sys64_hook { struct sys64_hook {
unsigned int esr_mask; unsigned int esr_mask;
unsigned int esr_val; unsigned int esr_val;
...@@ -523,6 +531,12 @@ static struct sys64_hook sys64_hooks[] = { ...@@ -523,6 +531,12 @@ static struct sys64_hook sys64_hooks[] = {
.esr_val = ESR_ELx_SYS64_ISS_SYS_CTR_READ, .esr_val = ESR_ELx_SYS64_ISS_SYS_CTR_READ,
.handler = ctr_read_handler, .handler = ctr_read_handler,
}, },
{
/* Trap read access to CNTVCT_EL0 */
.esr_mask = ESR_ELx_SYS64_ISS_SYS_OP_MASK,
.esr_val = ESR_ELx_SYS64_ISS_SYS_CNTVCT,
.handler = cntvct_read_handler,
},
{}, {},
}; };
......
...@@ -368,6 +368,17 @@ config HISILICON_ERRATUM_161010101 ...@@ -368,6 +368,17 @@ config HISILICON_ERRATUM_161010101
161010101. The workaround will be active if the hisilicon,erratum-161010101 161010101. The workaround will be active if the hisilicon,erratum-161010101
property is found in the timer node. property is found in the timer node.
config ARM64_ERRATUM_858921
bool "Workaround for Cortex-A73 erratum 858921"
default y
select ARM_ARCH_TIMER_OOL_WORKAROUND
depends on ARM_ARCH_TIMER && ARM64
help
This option enables a workaround applicable to Cortex-A73
(all versions), whose counter may return incorrect values.
The workaround will be dynamically enabled when an affected
core is detected.
config ARM_GLOBAL_TIMER config ARM_GLOBAL_TIMER
bool "Support for the ARM global timer" if COMPILE_TEST bool "Support for the ARM global timer" if COMPILE_TEST
select CLKSRC_OF if OF select CLKSRC_OF if OF
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment