diff mbox

[SRU,Zesty] arm64: Add CNTFRQ_EL0 trap handler

Message ID 20170508170217.344d4opjhsxtnatx@xps13.dannf
State New
Headers show

Commit Message

dann frazier May 8, 2017, 5:02 p.m. UTC
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(+)

Comments

Brad Figg May 9, 2017, 9:50 p.m. UTC | #1
Clean cherrypick and good test results.
Colin Ian King May 9, 2017, 9:54 p.m. UTC | #2
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>
Thadeu Lima de Souza Cascardo May 10, 2017, 7:52 p.m. UTC | #3
Applied to zesty master-next branch.

Thanks.
Cascardo.
diff mbox

Patch

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,
+	},
 	{},
 };