^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Kernel traps/events for Hexagon processor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/sched/debug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/sched/task_stack.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/kallsyms.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/kdebug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/syscalls.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/tracehook.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <asm/traps.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <asm/vm_fault.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <asm/syscall.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <asm/registers.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/unistd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <asm/sections.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #ifdef CONFIG_KGDB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) # include <linux/kgdb.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define TRAP_SYSCALL 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define TRAP_DEBUG 0xdb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) void __init trap_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #ifdef CONFIG_GENERIC_BUG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /* Maybe should resemble arch/sh/kernel/traps.c ?? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) int is_valid_bugaddr(unsigned long addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #endif /* CONFIG_GENERIC_BUG */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static const char *ex_name(int ex)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) switch (ex) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) case HVM_GE_C_XPROT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) case HVM_GE_C_XUSER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return "Execute protection fault";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) case HVM_GE_C_RPROT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) case HVM_GE_C_RUSER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return "Read protection fault";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) case HVM_GE_C_WPROT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) case HVM_GE_C_WUSER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) return "Write protection fault";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) case HVM_GE_C_XMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) return "Misaligned instruction";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) case HVM_GE_C_WREG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return "Multiple writes to same register in packet";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) case HVM_GE_C_PCAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return "Program counter values that are not properly aligned";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) case HVM_GE_C_RMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return "Misaligned data load";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) case HVM_GE_C_WMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return "Misaligned data store";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) case HVM_GE_C_INVI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) case HVM_GE_C_PRIVI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return "Illegal instruction";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) case HVM_GE_C_BUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return "Precise bus error";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) case HVM_GE_C_CACHE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return "Cache error";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) case 0xdb:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return "Debugger trap";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return "Unrecognized exception";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static void do_show_stack(struct task_struct *task, unsigned long *fp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) unsigned long ip, const char *loglvl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) int kstack_depth_to_print = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) unsigned long offset, size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) const char *name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) unsigned long *newfp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) unsigned long low, high;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) char tmpstr[128];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) char *modname;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) if (task == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) task = current;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) printk("%sCPU#%d, %s/%d, Call Trace:\n", loglvl, raw_smp_processor_id(),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) task->comm, task_pid_nr(task));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (fp == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (task == current) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) asm("%0 = r30" : "=r" (fp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) fp = (unsigned long *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ((struct hexagon_switch_stack *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) task->thread.switch_sp)->fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if ((((unsigned long) fp) & 0x3) || ((unsigned long) fp < 0x1000)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) printk("%s-- Corrupt frame pointer %p\n", loglvl, fp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* Saved link reg is one word above FP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if (!ip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) ip = *(fp+1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) /* Expect kernel stack to be in-bounds */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) low = (unsigned long)task_stack_page(task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) high = low + THREAD_SIZE - 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) low += sizeof(struct thread_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) for (i = 0; i < kstack_depth_to_print; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) name = kallsyms_lookup(ip, &size, &offset, &modname, tmpstr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) printk("%s[%p] 0x%lx: %s + 0x%lx", loglvl, fp, ip, name, offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (((unsigned long) fp < low) || (high < (unsigned long) fp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) printk(KERN_CONT " (FP out of bounds!)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) if (modname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) printk(KERN_CONT " [%s] ", modname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) printk(KERN_CONT "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) newfp = (unsigned long *) *fp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (((unsigned long) newfp) & 0x3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) printk("%s-- Corrupt frame pointer %p\n", loglvl, newfp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) /* Attempt to continue past exception. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (0 == newfp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) struct pt_regs *regs = (struct pt_regs *) (((void *)fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) + 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) if (regs->syscall_nr != -1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) printk("%s-- trap0 -- syscall_nr: %ld", loglvl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) regs->syscall_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) printk(KERN_CONT " psp: %lx elr: %lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) pt_psp(regs), pt_elr(regs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) /* really want to see more ... */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) kstack_depth_to_print += 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) printk("%s-- %s (0x%lx) badva: %lx\n", loglvl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) ex_name(pt_cause(regs)), pt_cause(regs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) pt_badva(regs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) newfp = (unsigned long *) regs->r30;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) ip = pt_elr(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) ip = *(newfp + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) /* If link reg is null, we are done. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (ip == 0x0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) /* If newfp isn't larger, we're tracing garbage. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (newfp > fp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) fp = newfp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) void show_stack(struct task_struct *task, unsigned long *fp, const char *loglvl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) /* Saved link reg is one word above FP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) do_show_stack(task, fp, 0, loglvl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) int die(const char *str, struct pt_regs *regs, long err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) static struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) spinlock_t lock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) int counter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) } die = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) .lock = __SPIN_LOCK_UNLOCKED(die.lock),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) .counter = 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) console_verbose();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) oops_enter();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) spin_lock_irq(&die.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) bust_spinlocks(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) printk(KERN_EMERG "Oops: %s[#%d]:\n", str, ++die.counter);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) if (notify_die(DIE_OOPS, str, regs, err, pt_cause(regs), SIGSEGV) ==
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) NOTIFY_STOP)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) print_modules();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) show_regs(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) do_show_stack(current, ®s->r30, pt_elr(regs), KERN_EMERG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) bust_spinlocks(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) spin_unlock_irq(&die.lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (in_interrupt())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) panic("Fatal exception in interrupt");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (panic_on_oops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) panic("Fatal exception");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) oops_exit();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) do_exit(err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) int die_if_kernel(char *str, struct pt_regs *regs, long err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (!user_mode(regs))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) return die(str, regs, err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * It's not clear that misaligned fetches are ever recoverable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) static void misaligned_instruction(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) die_if_kernel("Misaligned Instruction", regs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) force_sig(SIGBUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) * Misaligned loads and stores, on the other hand, can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) * emulated, and probably should be, some day. But for now
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * they will be considered fatal.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) static void misaligned_data_load(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) die_if_kernel("Misaligned Data Load", regs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) force_sig(SIGBUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static void misaligned_data_store(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) die_if_kernel("Misaligned Data Store", regs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) force_sig(SIGBUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static void illegal_instruction(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) die_if_kernel("Illegal Instruction", regs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) force_sig(SIGILL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) * Precise bus errors may be recoverable with a a retry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) * but for now, treat them as irrecoverable.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) static void precise_bus_error(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) die_if_kernel("Precise Bus Error", regs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) force_sig(SIGBUS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * If anything is to be done here other than panic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * it will probably be complex and migrate to another
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) * source module. For now, just die.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static void cache_error(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) die("Cache Error", regs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * General exception handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) void do_genex(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) * Decode Cause and Dispatch
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) switch (pt_cause(regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) case HVM_GE_C_XPROT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) case HVM_GE_C_XUSER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) execute_protection_fault(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) case HVM_GE_C_RPROT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) case HVM_GE_C_RUSER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) read_protection_fault(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) case HVM_GE_C_WPROT:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) case HVM_GE_C_WUSER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) write_protection_fault(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) case HVM_GE_C_XMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) misaligned_instruction(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) case HVM_GE_C_WREG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) illegal_instruction(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) case HVM_GE_C_PCAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) misaligned_instruction(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) case HVM_GE_C_RMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) misaligned_data_load(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) case HVM_GE_C_WMAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) misaligned_data_store(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) case HVM_GE_C_INVI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) case HVM_GE_C_PRIVI:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) illegal_instruction(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) case HVM_GE_C_BUS:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) precise_bus_error(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) case HVM_GE_C_CACHE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) cache_error(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) /* Halt and catch fire */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) panic("Unrecognized exception 0x%lx\n", pt_cause(regs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) /* Indirect system call dispatch */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) long sys_syscall(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) printk(KERN_ERR "sys_syscall invoked!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) return -ENOSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) void do_trap0(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) syscall_fn syscall;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) switch (pt_cause(regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) case TRAP_SYSCALL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) /* System call is trap0 #1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) /* allow strace to catch syscall args */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) if (unlikely(test_thread_flag(TIF_SYSCALL_TRACE) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) tracehook_report_syscall_entry(regs)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) return; /* return -ENOSYS somewhere? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) /* Interrupts should be re-enabled for syscall processing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) __vmsetie(VM_INT_ENABLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * System call number is in r6, arguments in r0..r5.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * Fortunately, no Linux syscall has more than 6 arguments,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) * and Hexagon ABI passes first 6 arguments in registers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * 64-bit arguments are passed in odd/even register pairs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) * Fortunately, we have no system calls that take more
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * than three arguments with more than one 64-bit value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * Should that change, we'd need to redesign to copy
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) * between user and kernel stacks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) regs->syscall_nr = regs->r06;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) * GPR R0 carries the first parameter, and is also used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) * to report the return value. We need a backup of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) * the user's value in case we need to do a late restart
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * of the system call.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) regs->restart_r0 = regs->r00;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if ((unsigned long) regs->syscall_nr >= __NR_syscalls) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) regs->r00 = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) syscall = (syscall_fn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) (sys_call_table[regs->syscall_nr]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) regs->r00 = syscall(regs->r00, regs->r01,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) regs->r02, regs->r03,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) regs->r04, regs->r05);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) /* allow strace to get the syscall return state */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (unlikely(test_thread_flag(TIF_SYSCALL_TRACE)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) tracehook_report_syscall_exit(regs, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) case TRAP_DEBUG:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) /* Trap0 0xdb is debug breakpoint */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (user_mode(regs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) * Some architecures add some per-thread state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) * to distinguish between breakpoint traps and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) * trace traps. We may want to do that, and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) * set the si_code value appropriately, or we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) * may want to use a different trap0 flavor.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) force_sig_fault(SIGTRAP, TRAP_BRKPT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) (void __user *) pt_elr(regs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) #ifdef CONFIG_KGDB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) kgdb_handle_exception(pt_cause(regs), SIGTRAP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) TRAP_BRKPT, regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) /* Ignore other trap0 codes for now, especially 0 (Angel calls) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) * Machine check exception handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) void do_machcheck(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /* Halt and catch fire */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) __vmstop();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) * Treat this like the old 0xdb trap.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) void do_debug_exception(struct pt_regs *regs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) regs->hvmer.vmest &= ~HVM_VMEST_CAUSE_MSK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) regs->hvmer.vmest |= (TRAP_DEBUG << HVM_VMEST_CAUSE_SFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) do_trap0(regs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) }