arm64: Add CNTVCT_EL0 cp15 AArch32 trap handler

Cntvct access was disabled by default, in
'commit 7b4edf240b ("clocksource: arch_timer: make
virtual counter access configurable"). There is a
trap handler added for user access using mrs instruction
in 'commit 9ce281d317 ("arm64: Add CNTVCT_EL0 trap
handler")' However, el0 running in AArch32 can try to
access cntvct using mrrc instruction. So, add a trap
handler to support that.

Change-Id: I788c03d87cd5a2d0e8d02da6662e2a1fb5e92827
Signed-off-by: Neeraj Upadhyay <neeraju@codeaurora.org>
This commit is contained in:
Neeraj Upadhyay 2018-04-10 16:33:47 +05:30
commit 65a0707548
3 changed files with 111 additions and 1 deletions

View file

@ -224,6 +224,42 @@
(ESR_ELx_CP15_32_ISS_SYS_VAL(0, 0, 14, 0) | \
ESR_ELx_CP15_32_ISS_DIR_READ)
/* ISS field definitions for CP15 AArch32 64-bit access traps */
#define ESR_ELx_CP15_64_ISS_CV_SHIFT 24
#define ESR_ELx_CP15_64_ISS_CV_MASK \
(UL(0x1) << ESR_ELx_CP15_64_ISS_CV_SHIFT)
#define ESR_ELx_CP15_64_ISS_DIR_MASK 0x1
#define ESR_ELx_CP15_64_ISS_DIR_READ 0x1
#define ESR_ELx_CP15_64_ISS_DIR_WRITE 0x0
#define ESR_ELx_CP15_64_ISS_RT_SHIFT 5
#define ESR_ELx_CP15_64_ISS_RT_MASK \
(UL(0x1f) << ESR_ELx_CP15_64_ISS_RT_SHIFT)
#define ESR_ELx_CP15_64_ISS_CRM_SHIFT 1
#define ESR_ELx_CP15_64_ISS_CRM_MASK \
(UL(0xf) << ESR_ELx_CP15_64_ISS_CRM_SHIFT)
#define ESR_ELx_CP15_64_ISS_RT2_SHIFT 10
#define ESR_ELx_CP15_64_ISS_RT2_MASK \
(UL(0x1f) << ESR_ELx_CP15_64_ISS_RT2_SHIFT)
#define ESR_ELx_CP15_64_ISS_OP1_SHIFT 16
#define ESR_ELx_CP15_64_ISS_OP1_MASK \
(UL(0xf) << ESR_ELx_CP15_64_ISS_OP1_SHIFT)
#define ESR_ELx_CP15_64_ISS_COND_SHIFT 20
#define ESR_ELx_CP15_64_ISS_COND_MASK \
(UL(0xf) << ESR_ELx_CP15_64_ISS_COND_SHIFT)
#define ESR_ELx_CP15_64_ISS_SYS_MASK (ESR_ELx_CP15_64_ISS_OP1_MASK | \
ESR_ELx_CP15_64_ISS_CRM_MASK)
#define ESR_ELx_CP15_64_ISS_SYS_VAL(op1, crm) \
(((op1) << ESR_ELx_CP15_64_ISS_OP1_SHIFT) | \
((crm) << ESR_ELx_CP15_64_ISS_CRM_SHIFT))
#define ESR_ELx_CP15_64_ISS_SYS_OP_MASK (ESR_ELx_CP15_64_ISS_SYS_MASK | \
ESR_ELx_CP15_64_ISS_DIR_MASK)
#define ESR_ELx_CP15_64_ISS_SYS_CNTVCT \
(ESR_ELx_CP15_64_ISS_SYS_VAL(1, 14) | \
ESR_ELx_CP15_64_ISS_DIR_READ)
#ifndef __ASSEMBLY__
#include <asm/types.h>

View file

@ -603,7 +603,7 @@ el0_sync_compat:
cmp x24, #ESR_ELx_EC_CP15_32 // CP15 MRC/MCR trap
b.eq el0_cp15_32_compat
cmp x24, #ESR_ELx_EC_CP15_64 // CP15 MRRC/MCRR trap
b.eq el0_undef
b.eq el0_cp15_64_compat
cmp x24, #ESR_ELx_EC_CP14_MR // CP14 MRC/MCR trap
b.eq el0_undef
cmp x24, #ESR_ELx_EC_CP14_LS // CP14 LDC/STC trap
@ -633,6 +633,17 @@ el0_cp15_32_compat:
bl do_cp15_32_instr_compat
b ret_to_user
el0_cp15_64_compat:
/*
* AArch32 CP15 MRRC/MCRR trap handling
*/
enable_dbg_and_irq
ct_user_exit
mov x0, x25
mov x1, sp
bl do_cp15_64_instr_compat
b ret_to_user
.align 6
el0_irq_compat:
kernel_entry 0, 32

View file

@ -659,6 +659,69 @@ asmlinkage void __exception do_cp15_32_instr_compat(unsigned int esr,
force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0);
}
static void cntvct_cp15_64_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;
int cv =
(esr & ESR_ELx_CP15_64_ISS_CV_MASK) >> ESR_ELx_CP15_64_ISS_CV_SHIFT;
int cond =
(esr & ESR_ELx_CP15_64_ISS_COND_MASK) >>
ESR_ELx_CP15_64_ISS_COND_SHIFT;
bool read_reg = 1;
if (rt == 15 || rt2 == 15 || rt == rt2)
read_reg = 0;
if ((rt == 13 || rt2 == 13) && !compat_arm_instr_set(regs))
read_reg = 0;
if (cv && cond != 0xf &&
!(*aarch32_opcode_cond_checks[cond])(regs->pstate & 0xffffffff))
read_reg = 0;
if (read_reg) {
u64 cval = arch_counter_get_cntvct();
regs->regs[rt] = cval & 0xffffffff;
regs->regs[rt2] = cval >> 32;
}
regs->pc += 4;
}
struct cp15_64_hook {
unsigned int esr_mask;
unsigned int esr_val;
void (*handler)(unsigned int esr, struct pt_regs *regs);
};
static struct cp15_64_hook cp15_64_hooks[] = {
{
/* Trap CP15 AArch32 read access to CNTVCT_EL0 */
.esr_mask = ESR_ELx_CP15_64_ISS_SYS_OP_MASK,
.esr_val = ESR_ELx_CP15_64_ISS_SYS_CNTVCT,
.handler = cntvct_cp15_64_read_handler,
},
{},
};
asmlinkage void __exception do_cp15_64_instr_compat(unsigned int esr,
struct pt_regs *regs)
{
struct cp15_64_hook *hook;
for (hook = cp15_64_hooks; hook->handler; hook++)
if ((hook->esr_mask & esr) == hook->esr_val) {
hook->handler(esr, regs);
return;
}
force_signal_inject(SIGILL, ILL_ILLOPC, regs, 0);
}
#endif
long compat_arm_syscall(struct pt_regs *regs);