Message ID | 20170508170217.344d4opjhsxtnatx@xps13.dannf |
---|---|
State | New |
Headers | show |
Clean cherrypick and good test results.
On 08/05/17 18:02, dann frazier wrote: > From: Marc Zyngier <marc.zyngier@arm.com> > > BugLink http://bugs.launchpad.net/bugs/1688164 > > We now trap accesses to CNTVCT_EL0 when the counter is broken > enough to require the kernel to mediate the access. But it > turns out that some existing userspace (such as OpenMPI) do > probe for the counter frequency, leading to an UNDEF exception > as CNTVCT_EL0 and CNTFRQ_EL0 share the same control bit. > > The fix is to handle the exception the same way we do for CNTVCT_EL0. > > Fixes: a86bd139f2ae ("arm64: arch_timer: Enable CNTVCT_EL0 trap if workaround is enabled") > Reported-by: Hanjun Guo <guohanjun@huawei.com> > Tested-by: Hanjun Guo <guohanjun@huawei.com> > Reviewed-by: Hanjun Guo <guohanjun@huawei.com> > Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> > Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> > (cherry picked from commit 9842119a238bfb92cbab63258dabb54f0e7b111b) > Signed-off-by: dann frazier <dann.frazier@canonical.com> > --- > arch/arm64/include/asm/esr.h | 4 ++++ > arch/arm64/kernel/traps.c | 14 ++++++++++++++ > 2 files changed, 18 insertions(+) > > diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h > index ad42e79a5d4d..85997c0e5443 100644 > --- a/arch/arm64/include/asm/esr.h > +++ b/arch/arm64/include/asm/esr.h > @@ -177,6 +177,10 @@ > > #define ESR_ELx_SYS64_ISS_SYS_CNTVCT (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \ > ESR_ELx_SYS64_ISS_DIR_READ) > + > +#define ESR_ELx_SYS64_ISS_SYS_CNTFRQ (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 0, 14, 0) | \ > + ESR_ELx_SYS64_ISS_DIR_READ) > + > #ifndef __ASSEMBLY__ > #include <asm/types.h> > > diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c > index cca9ae4b367a..27a74311f2a5 100644 > --- a/arch/arm64/kernel/traps.c > +++ b/arch/arm64/kernel/traps.c > @@ -508,6 +508,14 @@ static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs) > regs->pc += 4; > } > > +static void cntfrq_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, read_sysreg(cntfrq_el0)); > + regs->pc += 4; > +} > + > struct sys64_hook { > unsigned int esr_mask; > unsigned int esr_val; > @@ -532,6 +540,12 @@ static struct sys64_hook sys64_hooks[] = { > .esr_val = ESR_ELx_SYS64_ISS_SYS_CNTVCT, > .handler = cntvct_read_handler, > }, > + { > + /* Trap read access to CNTFRQ_EL0 */ > + .esr_mask = ESR_ELx_SYS64_ISS_SYS_OP_MASK, > + .esr_val = ESR_ELx_SYS64_ISS_SYS_CNTFRQ, > + .handler = cntfrq_read_handler, > + }, > {}, > }; > > Thanks Dann, Testing shows this fixes the issue and this is a clean cherry pick that fixes the this issue. Acked-by: Colin Ian King <colin.king@canonical.com>
Applied to zesty master-next branch. Thanks. Cascardo.
diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h index ad42e79a5d4d..85997c0e5443 100644 --- a/arch/arm64/include/asm/esr.h +++ b/arch/arm64/include/asm/esr.h @@ -177,6 +177,10 @@ #define ESR_ELx_SYS64_ISS_SYS_CNTVCT (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \ ESR_ELx_SYS64_ISS_DIR_READ) + +#define ESR_ELx_SYS64_ISS_SYS_CNTFRQ (ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 0, 14, 0) | \ + ESR_ELx_SYS64_ISS_DIR_READ) + #ifndef __ASSEMBLY__ #include <asm/types.h> diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index cca9ae4b367a..27a74311f2a5 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -508,6 +508,14 @@ static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs) regs->pc += 4; } +static void cntfrq_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, read_sysreg(cntfrq_el0)); + regs->pc += 4; +} + struct sys64_hook { unsigned int esr_mask; unsigned int esr_val; @@ -532,6 +540,12 @@ static struct sys64_hook sys64_hooks[] = { .esr_val = ESR_ELx_SYS64_ISS_SYS_CNTVCT, .handler = cntvct_read_handler, }, + { + /* Trap read access to CNTFRQ_EL0 */ + .esr_mask = ESR_ELx_SYS64_ISS_SYS_OP_MASK, + .esr_val = ESR_ELx_SYS64_ISS_SYS_CNTFRQ, + .handler = cntfrq_read_handler, + }, {}, };