arm64: Add CNTVCT_EL0 cp15 AArch32 trap handler
Cntvct access was disabled by default, in 'commit7b4edf240b("clocksource: arch_timer: make virtual counter access configurable"). There is a trap handler added for user access using mrs instruction in 'commit9ce281d317("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:
parent
2d764241e6
commit
65a0707548
3 changed files with 111 additions and 1 deletions
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in a new issue