Skip to content

Commit

Permalink
Merge branch 'for-next/timers' of git://git.kernel.org/pub/scm/linux/…
Browse files Browse the repository at this point in the history
…kernel/git/arm64/linux into for-next/core

Conflicts:
	arch/arm64/Kconfig
	arch/arm64/include/asm/arch_timer.h
  • Loading branch information
wildea01 committed May 1, 2019
2 parents 50abbe1 + 0ea4153 commit 24cf262
Show file tree
Hide file tree
Showing 12 changed files with 185 additions and 109 deletions.
1 change: 1 addition & 0 deletions Documentation/arm64/silicon-errata.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ stable kernels.
| ARM | Cortex-A76 | #1188873 | ARM64_ERRATUM_1188873 |
| ARM | Cortex-A76 | #1165522 | ARM64_ERRATUM_1165522 |
| ARM | Cortex-A76 | #1286807 | ARM64_ERRATUM_1286807 |
| ARM | Neoverse-N1 | #1188873 | ARM64_ERRATUM_1188873 |
| ARM | MMU-500 | #841119,#826419 | N/A |
| | | | |
| Cavium | ThunderX ITS | #22375, #24313 | CAVIUM_ERRATUM_22375 |
Expand Down
18 changes: 16 additions & 2 deletions arch/arm/include/asm/arch_timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
#include <clocksource/arm_arch_timer.h>

#ifdef CONFIG_ARM_ARCH_TIMER
/* 32bit ARM doesn't know anything about timer errata... */
#define has_erratum_handler(h) (false)
#define erratum_handler(h) (arch_timer_##h)

int arch_timer_arch_init(void);

/*
Expand Down Expand Up @@ -79,7 +83,7 @@ static inline u32 arch_timer_get_cntfrq(void)
return val;
}

static inline u64 arch_counter_get_cntpct(void)
static inline u64 __arch_counter_get_cntpct(void)
{
u64 cval;

Expand All @@ -88,7 +92,12 @@ static inline u64 arch_counter_get_cntpct(void)
return cval;
}

static inline u64 arch_counter_get_cntvct(void)
static inline u64 __arch_counter_get_cntpct_stable(void)
{
return __arch_counter_get_cntpct();
}

static inline u64 __arch_counter_get_cntvct(void)
{
u64 cval;

Expand All @@ -97,6 +106,11 @@ static inline u64 arch_counter_get_cntvct(void)
return cval;
}

static inline u64 __arch_counter_get_cntvct_stable(void)
{
return __arch_counter_get_cntvct();
}

static inline u32 arch_timer_get_cntkctl(void)
{
u32 cntkctl;
Expand Down
2 changes: 2 additions & 0 deletions arch/arm/include/asm/cp15.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@
#define BPIALL __ACCESS_CP15(c7, 0, c5, 6)
#define ICIALLU __ACCESS_CP15(c7, 0, c5, 0)

#define CNTVCT __ACCESS_CP15_64(1, c14)

extern unsigned long cr_alignment; /* defined in entry-armv.S */

static inline unsigned long get_cr(void)
Expand Down
5 changes: 3 additions & 2 deletions arch/arm/vdso/vgettimeofday.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
#include <linux/compiler.h>
#include <linux/hrtimer.h>
#include <linux/time.h>
#include <asm/arch_timer.h>
#include <asm/barrier.h>
#include <asm/bug.h>
#include <asm/cp15.h>
#include <asm/page.h>
#include <asm/unistd.h>
#include <asm/vdso_datapage.h>
Expand Down Expand Up @@ -123,7 +123,8 @@ static notrace u64 get_ns(struct vdso_data *vdata)
u64 cycle_now;
u64 nsec;

cycle_now = arch_counter_get_cntvct();
isb();
cycle_now = read_sysreg(CNTVCT);

cycle_delta = (cycle_now - vdata->cs_cycle_last) & vdata->cs_mask;

Expand Down
12 changes: 7 additions & 5 deletions arch/arm64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -477,15 +477,17 @@ config ARM64_ERRATUM_1024718
If unsure, say Y.

config ARM64_ERRATUM_1188873
bool "Cortex-A76: MRC read following MRRC read of specific Generic Timer in AArch32 might give incorrect result"
bool "Cortex-A76/Neoverse-N1: MRC read following MRRC read of specific Generic Timer in AArch32 might give incorrect result"
default y
depends on COMPAT
select ARM_ARCH_TIMER_OOL_WORKAROUND
help
This option adds a workaround for ARM Cortex-A76 erratum 1188873.
This option adds a workaround for ARM Cortex-A76/Neoverse-N1
erratum 1188873.

Affected Cortex-A76 cores (r0p0, r1p0, r2p0) could cause
register corruption when accessing the timer registers from
AArch32 userspace.
Affected Cortex-A76/Neoverse-N1 cores (r0p0, r1p0, r2p0) could
cause register corruption when accessing the timer registers
from AArch32 userspace.

If unsure, say Y.

Expand Down
86 changes: 66 additions & 20 deletions arch/arm64/include/asm/arch_timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,23 @@
#include <clocksource/arm_arch_timer.h>

#if IS_ENABLED(CONFIG_ARM_ARCH_TIMER_OOL_WORKAROUND)
extern struct static_key_false arch_timer_read_ool_enabled;
#define needs_unstable_timer_counter_workaround() \
static_branch_unlikely(&arch_timer_read_ool_enabled)
#define has_erratum_handler(h) \
({ \
const struct arch_timer_erratum_workaround *__wa; \
__wa = __this_cpu_read(timer_unstable_counter_workaround); \
(__wa && __wa->h); \
})

#define erratum_handler(h) \
({ \
const struct arch_timer_erratum_workaround *__wa; \
__wa = __this_cpu_read(timer_unstable_counter_workaround); \
(__wa && __wa->h) ? __wa->h : arch_timer_##h; \
})

#else
#define needs_unstable_timer_counter_workaround() false
#define has_erratum_handler(h) false
#define erratum_handler(h) (arch_timer_##h)
#endif

enum arch_timer_erratum_match_type {
Expand All @@ -61,23 +73,37 @@ struct arch_timer_erratum_workaround {
DECLARE_PER_CPU(const struct arch_timer_erratum_workaround *,
timer_unstable_counter_workaround);

/* inline sysreg accessors that make erratum_handler() work */
static inline notrace u32 arch_timer_read_cntp_tval_el0(void)
{
return read_sysreg(cntp_tval_el0);
}

static inline notrace u32 arch_timer_read_cntv_tval_el0(void)
{
return read_sysreg(cntv_tval_el0);
}

static inline notrace u64 arch_timer_read_cntpct_el0(void)
{
return read_sysreg(cntpct_el0);
}

static inline notrace u64 arch_timer_read_cntvct_el0(void)
{
return read_sysreg(cntvct_el0);
}

#define arch_timer_reg_read_stable(reg) \
({ \
u64 _val; \
if (needs_unstable_timer_counter_workaround()) { \
const struct arch_timer_erratum_workaround *wa; \
({ \
u64 _val; \
\
preempt_disable_notrace(); \
wa = __this_cpu_read(timer_unstable_counter_workaround); \
if (wa && wa->read_##reg) \
_val = wa->read_##reg(); \
else \
_val = read_sysreg(reg); \
_val = erratum_handler(read_ ## reg)(); \
preempt_enable_notrace(); \
} else { \
_val = read_sysreg(reg); \
} \
_val; \
})
\
_val; \
})

/*
* These register accessors are marked inline so the compiler can
Expand Down Expand Up @@ -167,7 +193,7 @@ static inline void arch_timer_set_cntkctl(u32 cntkctl)
: "=r" (tmp) : "r" (_val)); \
} while (0)

static inline u64 arch_counter_get_cntpct(void)
static inline u64 __arch_counter_get_cntpct_stable(void)
{
u64 cnt;

Expand All @@ -177,7 +203,17 @@ static inline u64 arch_counter_get_cntpct(void)
return cnt;
}

static inline u64 arch_counter_get_cntvct(void)
static inline u64 __arch_counter_get_cntpct(void)
{
u64 cnt;

isb();
cnt = read_sysreg(cntpct_el0);
arch_counter_enforce_ordering(cnt);
return cnt;
}

static inline u64 __arch_counter_get_cntvct_stable(void)
{
u64 cnt;

Expand All @@ -187,6 +223,16 @@ static inline u64 arch_counter_get_cntvct(void)
return cnt;
}

static inline u64 __arch_counter_get_cntvct(void)
{
u64 cnt;

isb();
cnt = read_sysreg(cntvct_el0);
arch_counter_enforce_ordering(cnt);
return cnt;
}

#undef arch_counter_enforce_ordering

static inline int arch_timer_arch_init(void)
Expand Down
2 changes: 2 additions & 0 deletions arch/arm64/include/asm/cputype.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@
#define ARM_CPU_PART_CORTEX_A35 0xD04
#define ARM_CPU_PART_CORTEX_A55 0xD05
#define ARM_CPU_PART_CORTEX_A76 0xD0B
#define ARM_CPU_PART_NEOVERSE_N1 0xD0C

#define APM_CPU_PART_POTENZA 0x000

Expand Down Expand Up @@ -118,6 +119,7 @@
#define MIDR_CORTEX_A35 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A35)
#define MIDR_CORTEX_A55 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A55)
#define MIDR_CORTEX_A76 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A76)
#define MIDR_NEOVERSE_N1 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N1)
#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_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
Expand Down
13 changes: 11 additions & 2 deletions arch/arm64/kernel/cpu_errata.c
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,16 @@ static const struct midr_range workaround_clean_cache[] = {
};
#endif

#ifdef CONFIG_ARM64_ERRATUM_1188873
static const struct midr_range erratum_1188873_list[] = {
/* Cortex-A76 r0p0 to r2p0 */
MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 2, 0),
/* Neoverse-N1 r0p0 to r2p0 */
MIDR_RANGE(MIDR_NEOVERSE_N1, 0, 0, 2, 0),
{},
};
#endif

const struct arm64_cpu_capabilities arm64_errata[] = {
#ifdef CONFIG_ARM64_WORKAROUND_CLEAN_CACHE
{
Expand Down Expand Up @@ -801,10 +811,9 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
},
#ifdef CONFIG_ARM64_ERRATUM_1188873
{
/* Cortex-A76 r0p0 to r2p0 */
.desc = "ARM erratum 1188873",
.capability = ARM64_WORKAROUND_1188873,
ERRATA_MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 2, 0),
ERRATA_MIDR_RANGE_LIST(erratum_1188873_list),
},
#endif
#ifdef CONFIG_ARM64_ERRATUM_1165522
Expand Down
19 changes: 17 additions & 2 deletions arch/arm64/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,21 @@ alternative_if ARM64_WORKAROUND_845719
alternative_else_nop_endif
#endif
3:
#ifdef CONFIG_ARM64_ERRATUM_1188873
alternative_if_not ARM64_WORKAROUND_1188873
b 4f
alternative_else_nop_endif
/*
* if (x22.mode32 == cntkctl_el1.el0vcten)
* cntkctl_el1.el0vcten = ~cntkctl_el1.el0vcten
*/
mrs x1, cntkctl_el1
eon x0, x1, x22, lsr #3
tbz x0, #1, 4f
eor x1, x1, #2 // ARCH_TIMER_USR_VCT_ACCESS_EN
msr cntkctl_el1, x1
4:
#endif
apply_ssbd 0, x0, x1
.endif

Expand All @@ -362,11 +377,11 @@ alternative_else_nop_endif
.if \el == 0
alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0
#ifdef CONFIG_UNMAP_KERNEL_AT_EL0
bne 4f
bne 5f
msr far_el1, x30
tramp_alias x30, tramp_exit_native
br x30
4:
5:
tramp_alias x30, tramp_exit_compat
br x30
#endif
Expand Down
4 changes: 2 additions & 2 deletions arch/arm64/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs)
{
int rt = ESR_ELx_SYS64_ISS_RT(esr);

pt_regs_write_reg(regs, rt, arch_counter_get_cntvct());
pt_regs_write_reg(regs, rt, arch_timer_read_counter());
arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE);
}

Expand Down Expand Up @@ -668,7 +668,7 @@ static void compat_cntvct_read_handler(unsigned int esr, struct pt_regs *regs)
{
int rt = (esr & ESR_ELx_CP15_64_ISS_RT_MASK) >> ESR_ELx_CP15_64_ISS_RT_SHIFT;
int rt2 = (esr & ESR_ELx_CP15_64_ISS_RT2_MASK) >> ESR_ELx_CP15_64_ISS_RT2_SHIFT;
u64 val = arch_counter_get_cntvct();
u64 val = arch_timer_read_counter();

pt_regs_write_reg(regs, rt, lower_32_bits(val));
pt_regs_write_reg(regs, rt2, upper_32_bits(val));
Expand Down
Loading

0 comments on commit 24cf262

Please sign in to comment.