Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d2bc82c5 authored by Neeraj Upadhyay's avatar Neeraj Upadhyay Committed by Gerrit - the friendly Code Review server
Browse files

arm64: Add CNTVCT_EL0 cp15 AArch32 trap handler



Cntvct access was disabled by default, in
'commit 7b4edf240be4 ("clocksource: arch_timer: make
virtual counter access configurable"). There is a
trap handler added for user access using mrs instruction
in 'commit 9ce281d317a1 ("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: default avatarNeeraj Upadhyay <neeraju@codeaurora.org>
parent 0b6670db
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -261,6 +261,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>

+12 −1
Original line number Diff line number Diff line
@@ -710,7 +710,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
@@ -740,6 +740,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
+63 −0
Original line number Diff line number Diff line
@@ -584,6 +584,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);