Loading arch/arm/include/asm/traps.h +2 −0 Original line number Diff line number Diff line Loading @@ -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); Loading arch/arm/kernel/traps.c +72 −0 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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. Loading arch/arm64/include/asm/traps.h +2 −0 Original line number Diff line number Diff line Loading @@ -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 drivers/clocksource/Kconfig +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading drivers/clocksource/arm_arch_timer.c +3 −0 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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 Loading
arch/arm/include/asm/traps.h +2 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
arch/arm/kernel/traps.c +72 −0 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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. Loading
arch/arm64/include/asm/traps.h +2 −0 Original line number Diff line number Diff line Loading @@ -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
drivers/clocksource/Kconfig +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
drivers/clocksource/arm_arch_timer.c +3 −0 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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