arm64: compat: Add CNTFRQ trap handler
authorMarc Zyngier <marc.zyngier@arm.com>
Thu, 27 Sep 2018 16:15:33 +0000 (17:15 +0100)
committerCatalin Marinas <catalin.marinas@arm.com>
Mon, 1 Oct 2018 12:36:03 +0000 (13:36 +0100)
Just like CNTVCT, we need to handle userspace trapping into the
kernel if we're decided that the timer wasn't fit for purpose...
64bit userspace is already dealt with, but we're missing the
equivalent compat handling.

Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
arch/arm64/include/asm/esr.h
arch/arm64/kernel/traps.c

index 5548712ce6e54c27f5b981a0b56d6718747a22d8..fb7dfe1b51bb186e58b722c671836e05fa58fc27 100644 (file)
 #define ESR_ELx_CP15_64_ISS_SYS_CNTVCT (ESR_ELx_CP15_64_ISS_SYS_VAL(1, 14) | \
                                         ESR_ELx_CP15_64_ISS_DIR_READ)
 
+#define ESR_ELx_CP15_32_ISS_SYS_CNTFRQ (ESR_ELx_CP15_32_ISS_SYS_VAL(0, 0, 14, 0) |\
+                                        ESR_ELx_CP15_32_ISS_DIR_READ)
+
 #ifndef __ASSEMBLY__
 #include <asm/types.h>
 
index 3602b900ff1c4be90411fb869ac226f2099d09c1..58134a97928f6e083d1c45e344849215451c10c9 100644 (file)
@@ -625,7 +625,20 @@ static void arm64_compat_skip_faulting_instruction(struct pt_regs *regs,
        arm64_skip_faulting_instruction(regs, sz);
 }
 
+static void compat_cntfrq_read_handler(unsigned int esr, struct pt_regs *regs)
+{
+       int reg = (esr & ESR_ELx_CP15_32_ISS_RT_MASK) >> ESR_ELx_CP15_32_ISS_RT_SHIFT;
+
+       pt_regs_write_reg(regs, reg, arch_timer_get_rate());
+       arm64_compat_skip_faulting_instruction(regs, 4);
+}
+
 static struct sys64_hook cp15_32_hooks[] = {
+       {
+               .esr_mask = ESR_ELx_CP15_32_ISS_SYS_MASK,
+               .esr_val = ESR_ELx_CP15_32_ISS_SYS_CNTFRQ,
+               .handler = compat_cntfrq_read_handler,
+       },
        {},
 };