mirror of https://github.com/OpenIPC/firmware.git
149 lines
4.0 KiB
Diff
149 lines
4.0 KiB
Diff
diff -drupN a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
|
|
--- a/arch/arm64/kernel/traps.c 2018-08-06 17:23:04.000000000 +0300
|
|
+++ b/arch/arm64/kernel/traps.c 2022-06-12 05:28:14.000000000 +0300
|
|
@@ -33,11 +33,13 @@
|
|
#include <linux/syscalls.h>
|
|
|
|
#include <asm/atomic.h>
|
|
+#include <asm/barrier.h>
|
|
#include <asm/bug.h>
|
|
#include <asm/debug-monitors.h>
|
|
#include <asm/esr.h>
|
|
#include <asm/insn.h>
|
|
#include <asm/traps.h>
|
|
+#include <asm/stack_pointer.h>
|
|
#include <asm/stacktrace.h>
|
|
#include <asm/exception.h>
|
|
#include <asm/system_misc.h>
|
|
@@ -147,6 +149,9 @@ static void dump_backtrace(struct pt_reg
|
|
if (!tsk)
|
|
tsk = current;
|
|
|
|
+ if (!try_get_task_stack(tsk))
|
|
+ return;
|
|
+
|
|
/*
|
|
* Switching between stacks is valid when tracing current and in
|
|
* non-preemptible context.
|
|
@@ -212,6 +217,8 @@ static void dump_backtrace(struct pt_reg
|
|
stack + sizeof(struct pt_regs));
|
|
}
|
|
}
|
|
+
|
|
+ put_task_stack(tsk);
|
|
}
|
|
|
|
void show_stack(struct task_struct *tsk, unsigned long *sp)
|
|
@@ -227,10 +234,9 @@ void show_stack(struct task_struct *tsk,
|
|
#endif
|
|
#define S_SMP " SMP"
|
|
|
|
-static int __die(const char *str, int err, struct thread_info *thread,
|
|
- struct pt_regs *regs)
|
|
+static int __die(const char *str, int err, struct pt_regs *regs)
|
|
{
|
|
- struct task_struct *tsk = thread->task;
|
|
+ struct task_struct *tsk = current;
|
|
static int die_counter;
|
|
int ret;
|
|
|
|
@@ -245,7 +251,8 @@ static int __die(const char *str, int er
|
|
print_modules();
|
|
__show_regs(regs);
|
|
pr_emerg("Process %.*s (pid: %d, stack limit = 0x%p)\n",
|
|
- TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1);
|
|
+ TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk),
|
|
+ end_of_stack(tsk));
|
|
|
|
if (!user_mode(regs)) {
|
|
dump_mem(KERN_EMERG, "Stack: ", regs->sp,
|
|
@@ -264,7 +271,6 @@ static DEFINE_RAW_SPINLOCK(die_lock);
|
|
*/
|
|
void die(const char *str, struct pt_regs *regs, int err)
|
|
{
|
|
- struct thread_info *thread = current_thread_info();
|
|
int ret;
|
|
|
|
oops_enter();
|
|
@@ -272,9 +278,9 @@ void die(const char *str, struct pt_regs
|
|
raw_spin_lock_irq(&die_lock);
|
|
console_verbose();
|
|
bust_spinlocks(1);
|
|
- ret = __die(str, err, thread, regs);
|
|
+ ret = __die(str, err, regs);
|
|
|
|
- if (regs && kexec_should_crash(thread->task))
|
|
+ if (regs && kexec_should_crash(current))
|
|
crash_kexec(regs);
|
|
|
|
bust_spinlocks(0);
|
|
@@ -435,9 +441,10 @@ int cpu_enable_cache_maint_trap(void *__
|
|
}
|
|
|
|
#define __user_cache_maint(insn, address, res) \
|
|
- if (address >= user_addr_max()) \
|
|
+ if (address >= user_addr_max()) { \
|
|
res = -EFAULT; \
|
|
- else \
|
|
+ } else { \
|
|
+ uaccess_ttbr0_enable(); \
|
|
asm volatile ( \
|
|
"1: " insn ", %1\n" \
|
|
" mov %w0, #0\n" \
|
|
@@ -449,7 +456,9 @@ int cpu_enable_cache_maint_trap(void *__
|
|
" .popsection\n" \
|
|
_ASM_EXTABLE(1b, 3b) \
|
|
: "=r" (res) \
|
|
- : "r" (address), "i" (-EFAULT) )
|
|
+ : "r" (address), "i" (-EFAULT)); \
|
|
+ uaccess_ttbr0_disable(); \
|
|
+ }
|
|
|
|
static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)
|
|
{
|
|
@@ -492,6 +501,25 @@ static void ctr_read_handler(unsigned in
|
|
regs->pc += 4;
|
|
}
|
|
|
|
+static void cntvct_read_handler(unsigned int esr, struct pt_regs *regs)
|
|
+{
|
|
+ int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT;
|
|
+
|
|
+ isb();
|
|
+ if (rt != 31)
|
|
+ regs->regs[rt] = arch_counter_get_cntvct();
|
|
+ regs->pc += 4;
|
|
+}
|
|
+
|
|
+static void cntfrq_read_handler(unsigned int esr, struct pt_regs *regs)
|
|
+{
|
|
+ int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT;
|
|
+
|
|
+ if (rt != 31)
|
|
+ regs->regs[rt] = read_sysreg(cntfrq_el0);
|
|
+ regs->pc += 4;
|
|
+}
|
|
+
|
|
struct sys64_hook {
|
|
unsigned int esr_mask;
|
|
unsigned int esr_val;
|
|
@@ -510,6 +538,18 @@ static struct sys64_hook sys64_hooks[] =
|
|
.esr_val = ESR_ELx_SYS64_ISS_SYS_CTR_READ,
|
|
.handler = ctr_read_handler,
|
|
},
|
|
+ {
|
|
+ /* Trap read access to CNTVCT_EL0 */
|
|
+ .esr_mask = ESR_ELx_SYS64_ISS_SYS_OP_MASK,
|
|
+ .esr_val = ESR_ELx_SYS64_ISS_SYS_CNTVCT,
|
|
+ .handler = cntvct_read_handler,
|
|
+ },
|
|
+ {
|
|
+ /* Trap read access to CNTFRQ_EL0 */
|
|
+ .esr_mask = ESR_ELx_SYS64_ISS_SYS_OP_MASK,
|
|
+ .esr_val = ESR_ELx_SYS64_ISS_SYS_CNTFRQ,
|
|
+ .handler = cntfrq_read_handler,
|
|
+ },
|
|
{},
|
|
};
|
|
|