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

Commit 0ab98780 authored by Se Wang (Patrick) Oh's avatar Se Wang (Patrick) Oh Committed by Prasad Sodagudi
Browse files

arm: traps: emulate a MRCC instruction reading CNTPCT register



A user space application is planned to support feature for
synchronized timestamp among debug packets across peripherals.
As part of the feature, it is responsible for providing physical
timer count value to user space. If memory mapped timer is used
in ARM arch, Usersapce can't read the physical timer count directly
with a MRCC ASM instruction. So Kernel traps the instruction and
returns the physical timer count.

Change-Id: Ia3f0d9c8c06ca9e2204187890c0c57c8640e4f7e
Signed-off-by: default avatarSe Wang (Patrick) Oh <sewango@codeaurora.org>
[psodagud: trivial merge conflict resolution]
Signed-off-by: default avatarPrasad Sodagudi <psodagud@codeaurora.org>
parent f1a1ad6d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ static inline int in_exception_text(unsigned long ptr)
	return in ? : __in_irqentry_text(ptr);
}

extern void get_pct_hook_init(void);
extern void __init early_trap_init(void *);
extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame);
extern void ptrace_break(struct task_struct *tsk, struct pt_regs *regs);
+37 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include <linux/irq.h>

#include <linux/atomic.h>
#include <asm/arch_timer.h>
#include <asm/cacheflush.h>
#include <asm/exception.h>
#include <asm/unistd.h>
@@ -719,6 +720,42 @@ late_initcall(arm_mrc_hook_init);

#endif

static int get_pct_trap(struct pt_regs *regs, unsigned int instr)
{
	u64 cntpct;
	unsigned int res;
	int rd = (instr >> 12) & 0xF;
	int rn =  (instr >> 16) & 0xF;

	res = arm_check_condition(instr, regs->ARM_cpsr);
	if (res == ARM_OPCODE_CONDTEST_FAIL) {
		regs->ARM_pc += 4;
		return 0;
	}

	if (rd == 15 || rn == 15)
		return 1;
	cntpct = arch_counter_get_cntpct();
	regs->uregs[rd] = cntpct;
	regs->uregs[rn] = cntpct >> 32;
	regs->ARM_pc += 4;
	return 0;
}

static struct undef_hook get_pct_hook = {
	.instr_mask	= 0x0ff00fff,
	.instr_val	= 0x0c500f0e,
	.cpsr_mask	= MODE_MASK,
	.cpsr_val	= USR_MODE,
	.fn		= get_pct_trap,
};

void get_pct_hook_init(void)
{
	register_undef_hook(&get_pct_hook);
}
EXPORT_SYMBOL(get_pct_hook_init);

/*
 * A data abort trap was taken, but we did not handle the instruction.
 * Try to abort the user program, or panic if it was the kernel.
+1 −0
Original line number Diff line number Diff line
@@ -60,4 +60,5 @@ static inline int in_exception_text(unsigned long ptr)
	return in ? : __in_irqentry_text(ptr);
}

static inline void get_pct_hook_init(void) {}
#endif
+2 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <linux/acpi.h>

#include <asm/arch_timer.h>
#include <asm/traps.h>
#include <asm/virt.h>

#include <clocksource/arm_arch_timer.h>
@@ -1381,6 +1382,7 @@ static int __init arch_timer_mem_of_init(struct device_node *np)
	ret = arch_timer_mem_frame_register(frame);
	if (!ret && !arch_timer_needs_of_probing())
		ret = arch_timer_common_init();
	get_pct_hook_init();
out:
	kfree(timer_mem);
	return ret;