mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-11 23:24:22 -04:00
Merge "arm: traps: emulate a MRC instruction reading CNTFRQ register"
This commit is contained in:
commit
b3981928e9
5 changed files with 80 additions and 1 deletions
|
|
@ -28,6 +28,8 @@ static inline int __in_irqentry_text(unsigned long ptr)
|
|||
ptr < (unsigned long)&__irqentry_text_end;
|
||||
}
|
||||
|
||||
extern void get_timer_freq_hook_init(void);
|
||||
extern void get_timer_count_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 pt_regs *regs);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,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>
|
||||
|
|
@ -711,6 +712,77 @@ late_initcall(arm_mrc_hook_init);
|
|||
|
||||
#endif
|
||||
|
||||
static int get_timer_count_trap(struct pt_regs *regs, unsigned int instr)
|
||||
{
|
||||
u64 cval;
|
||||
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;
|
||||
cval = __arch_counter_get_cntvct();
|
||||
regs->uregs[rd] = cval;
|
||||
regs->uregs[rn] = cval >> 32;
|
||||
regs->ARM_pc += 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct undef_hook get_timer_count_hook = {
|
||||
.instr_mask = 0x0ff00fff,
|
||||
.instr_val = 0x0c500f1e,
|
||||
.cpsr_mask = MODE_MASK,
|
||||
.cpsr_val = USR_MODE,
|
||||
.fn = get_timer_count_trap,
|
||||
};
|
||||
|
||||
void get_timer_count_hook_init(void)
|
||||
{
|
||||
register_undef_hook(&get_timer_count_hook);
|
||||
}
|
||||
EXPORT_SYMBOL(get_timer_count_hook_init);
|
||||
|
||||
static int get_freq_trap(struct pt_regs *regs, unsigned int instr)
|
||||
{
|
||||
u32 fval;
|
||||
unsigned int res;
|
||||
int rd = (instr >> 12) & 0xF;
|
||||
|
||||
res = arm_check_condition(instr, regs->ARM_cpsr);
|
||||
if (res == ARM_OPCODE_CONDTEST_FAIL) {
|
||||
regs->ARM_pc += 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rd == 15)
|
||||
return 1;
|
||||
|
||||
fval = arch_timer_get_cntfrq();
|
||||
regs->uregs[rd] = fval;
|
||||
regs->ARM_pc += 4;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct undef_hook get_freq_hook = {
|
||||
.instr_mask = 0x0fff0fff,
|
||||
.instr_val = 0x0e1e0f10,
|
||||
.cpsr_mask = MODE_MASK,
|
||||
.cpsr_val = USR_MODE,
|
||||
.fn = get_freq_trap,
|
||||
};
|
||||
|
||||
void get_timer_freq_hook_init(void)
|
||||
{
|
||||
register_undef_hook(&get_freq_hook);
|
||||
}
|
||||
EXPORT_SYMBOL(get_timer_freq_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.
|
||||
|
|
|
|||
|
|
@ -110,4 +110,6 @@ static inline u32 arm64_ras_serror_get_severity(u32 esr)
|
|||
|
||||
bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned int esr);
|
||||
void __noreturn arm64_serror_panic(struct pt_regs *regs, u32 esr);
|
||||
static inline void get_timer_count_hook_init(void) {}
|
||||
static inline void get_timer_freq_hook_init(void) {}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -387,7 +387,7 @@ config SUN50I_ERRATUM_UNKNOWN1
|
|||
|
||||
config ARM_ARCH_TIMER_VCT_ACCESS
|
||||
bool "Support for ARM architected timer virtual counter access in userspace"
|
||||
default !ARM64
|
||||
default n
|
||||
depends on ARM_ARCH_TIMER
|
||||
help
|
||||
This option enables support for reading the ARM architected timer's
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/acpi.h>
|
||||
|
||||
#include <asm/arch_timer.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/virt.h>
|
||||
|
||||
#include <clocksource/arm_arch_timer.h>
|
||||
|
|
@ -1519,6 +1520,8 @@ 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_timer_count_hook_init();
|
||||
get_timer_freq_hook_init();
|
||||
out:
|
||||
kfree(timer_mem);
|
||||
return ret;
|
||||
|
|
|
|||
Loading…
Reference in a new issue