162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Kernel traps/events for Hexagon processor 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/init.h> 962306a36Sopenharmony_ci#include <linux/sched/signal.h> 1062306a36Sopenharmony_ci#include <linux/sched/debug.h> 1162306a36Sopenharmony_ci#include <linux/sched/task_stack.h> 1262306a36Sopenharmony_ci#include <linux/module.h> 1362306a36Sopenharmony_ci#include <linux/kallsyms.h> 1462306a36Sopenharmony_ci#include <linux/kdebug.h> 1562306a36Sopenharmony_ci#include <linux/syscalls.h> 1662306a36Sopenharmony_ci#include <linux/signal.h> 1762306a36Sopenharmony_ci#include <linux/ptrace.h> 1862306a36Sopenharmony_ci#include <asm/traps.h> 1962306a36Sopenharmony_ci#include <asm/vm_fault.h> 2062306a36Sopenharmony_ci#include <asm/syscall.h> 2162306a36Sopenharmony_ci#include <asm/registers.h> 2262306a36Sopenharmony_ci#include <asm/unistd.h> 2362306a36Sopenharmony_ci#include <asm/sections.h> 2462306a36Sopenharmony_ci#ifdef CONFIG_KGDB 2562306a36Sopenharmony_ci# include <linux/kgdb.h> 2662306a36Sopenharmony_ci#endif 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define TRAP_SYSCALL 1 2962306a36Sopenharmony_ci#define TRAP_DEBUG 0xdb 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#ifdef CONFIG_GENERIC_BUG 3262306a36Sopenharmony_ci/* Maybe should resemble arch/sh/kernel/traps.c ?? */ 3362306a36Sopenharmony_ciint is_valid_bugaddr(unsigned long addr) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci return 1; 3662306a36Sopenharmony_ci} 3762306a36Sopenharmony_ci#endif /* CONFIG_GENERIC_BUG */ 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic const char *ex_name(int ex) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci switch (ex) { 4262306a36Sopenharmony_ci case HVM_GE_C_XPROT: 4362306a36Sopenharmony_ci case HVM_GE_C_XUSER: 4462306a36Sopenharmony_ci return "Execute protection fault"; 4562306a36Sopenharmony_ci case HVM_GE_C_RPROT: 4662306a36Sopenharmony_ci case HVM_GE_C_RUSER: 4762306a36Sopenharmony_ci return "Read protection fault"; 4862306a36Sopenharmony_ci case HVM_GE_C_WPROT: 4962306a36Sopenharmony_ci case HVM_GE_C_WUSER: 5062306a36Sopenharmony_ci return "Write protection fault"; 5162306a36Sopenharmony_ci case HVM_GE_C_XMAL: 5262306a36Sopenharmony_ci return "Misaligned instruction"; 5362306a36Sopenharmony_ci case HVM_GE_C_WREG: 5462306a36Sopenharmony_ci return "Multiple writes to same register in packet"; 5562306a36Sopenharmony_ci case HVM_GE_C_PCAL: 5662306a36Sopenharmony_ci return "Program counter values that are not properly aligned"; 5762306a36Sopenharmony_ci case HVM_GE_C_RMAL: 5862306a36Sopenharmony_ci return "Misaligned data load"; 5962306a36Sopenharmony_ci case HVM_GE_C_WMAL: 6062306a36Sopenharmony_ci return "Misaligned data store"; 6162306a36Sopenharmony_ci case HVM_GE_C_INVI: 6262306a36Sopenharmony_ci case HVM_GE_C_PRIVI: 6362306a36Sopenharmony_ci return "Illegal instruction"; 6462306a36Sopenharmony_ci case HVM_GE_C_BUS: 6562306a36Sopenharmony_ci return "Precise bus error"; 6662306a36Sopenharmony_ci case HVM_GE_C_CACHE: 6762306a36Sopenharmony_ci return "Cache error"; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci case 0xdb: 7062306a36Sopenharmony_ci return "Debugger trap"; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci default: 7362306a36Sopenharmony_ci return "Unrecognized exception"; 7462306a36Sopenharmony_ci } 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic void do_show_stack(struct task_struct *task, unsigned long *fp, 7862306a36Sopenharmony_ci unsigned long ip, const char *loglvl) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci int kstack_depth_to_print = 24; 8162306a36Sopenharmony_ci unsigned long offset, size; 8262306a36Sopenharmony_ci const char *name = NULL; 8362306a36Sopenharmony_ci unsigned long *newfp; 8462306a36Sopenharmony_ci unsigned long low, high; 8562306a36Sopenharmony_ci char tmpstr[128]; 8662306a36Sopenharmony_ci char *modname; 8762306a36Sopenharmony_ci int i; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci if (task == NULL) 9062306a36Sopenharmony_ci task = current; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci printk("%sCPU#%d, %s/%d, Call Trace:\n", loglvl, raw_smp_processor_id(), 9362306a36Sopenharmony_ci task->comm, task_pid_nr(task)); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci if (fp == NULL) { 9662306a36Sopenharmony_ci if (task == current) { 9762306a36Sopenharmony_ci asm("%0 = r30" : "=r" (fp)); 9862306a36Sopenharmony_ci } else { 9962306a36Sopenharmony_ci fp = (unsigned long *) 10062306a36Sopenharmony_ci ((struct hexagon_switch_stack *) 10162306a36Sopenharmony_ci task->thread.switch_sp)->fp; 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci if ((((unsigned long) fp) & 0x3) || ((unsigned long) fp < 0x1000)) { 10662306a36Sopenharmony_ci printk("%s-- Corrupt frame pointer %p\n", loglvl, fp); 10762306a36Sopenharmony_ci return; 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci /* Saved link reg is one word above FP */ 11162306a36Sopenharmony_ci if (!ip) 11262306a36Sopenharmony_ci ip = *(fp+1); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci /* Expect kernel stack to be in-bounds */ 11562306a36Sopenharmony_ci low = (unsigned long)task_stack_page(task); 11662306a36Sopenharmony_ci high = low + THREAD_SIZE - 8; 11762306a36Sopenharmony_ci low += sizeof(struct thread_info); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci for (i = 0; i < kstack_depth_to_print; i++) { 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci name = kallsyms_lookup(ip, &size, &offset, &modname, tmpstr); 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci printk("%s[%p] 0x%lx: %s + 0x%lx", loglvl, fp, ip, name, offset); 12462306a36Sopenharmony_ci if (((unsigned long) fp < low) || (high < (unsigned long) fp)) 12562306a36Sopenharmony_ci printk(KERN_CONT " (FP out of bounds!)"); 12662306a36Sopenharmony_ci if (modname) 12762306a36Sopenharmony_ci printk(KERN_CONT " [%s] ", modname); 12862306a36Sopenharmony_ci printk(KERN_CONT "\n"); 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci newfp = (unsigned long *) *fp; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci if (((unsigned long) newfp) & 0x3) { 13362306a36Sopenharmony_ci printk("%s-- Corrupt frame pointer %p\n", loglvl, newfp); 13462306a36Sopenharmony_ci break; 13562306a36Sopenharmony_ci } 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci /* Attempt to continue past exception. */ 13862306a36Sopenharmony_ci if (0 == newfp) { 13962306a36Sopenharmony_ci struct pt_regs *regs = (struct pt_regs *) (((void *)fp) 14062306a36Sopenharmony_ci + 8); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci if (regs->syscall_nr != -1) { 14362306a36Sopenharmony_ci printk("%s-- trap0 -- syscall_nr: %ld", loglvl, 14462306a36Sopenharmony_ci regs->syscall_nr); 14562306a36Sopenharmony_ci printk(KERN_CONT " psp: %lx elr: %lx\n", 14662306a36Sopenharmony_ci pt_psp(regs), pt_elr(regs)); 14762306a36Sopenharmony_ci break; 14862306a36Sopenharmony_ci } else { 14962306a36Sopenharmony_ci /* really want to see more ... */ 15062306a36Sopenharmony_ci kstack_depth_to_print += 6; 15162306a36Sopenharmony_ci printk("%s-- %s (0x%lx) badva: %lx\n", loglvl, 15262306a36Sopenharmony_ci ex_name(pt_cause(regs)), pt_cause(regs), 15362306a36Sopenharmony_ci pt_badva(regs)); 15462306a36Sopenharmony_ci } 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci newfp = (unsigned long *) regs->r30; 15762306a36Sopenharmony_ci ip = pt_elr(regs); 15862306a36Sopenharmony_ci } else { 15962306a36Sopenharmony_ci ip = *(newfp + 1); 16062306a36Sopenharmony_ci } 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci /* If link reg is null, we are done. */ 16362306a36Sopenharmony_ci if (ip == 0x0) 16462306a36Sopenharmony_ci break; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci /* If newfp isn't larger, we're tracing garbage. */ 16762306a36Sopenharmony_ci if (newfp > fp) 16862306a36Sopenharmony_ci fp = newfp; 16962306a36Sopenharmony_ci else 17062306a36Sopenharmony_ci break; 17162306a36Sopenharmony_ci } 17262306a36Sopenharmony_ci} 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_civoid show_stack(struct task_struct *task, unsigned long *fp, const char *loglvl) 17562306a36Sopenharmony_ci{ 17662306a36Sopenharmony_ci /* Saved link reg is one word above FP */ 17762306a36Sopenharmony_ci do_show_stack(task, fp, 0, loglvl); 17862306a36Sopenharmony_ci} 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ciint die(const char *str, struct pt_regs *regs, long err) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci static struct { 18362306a36Sopenharmony_ci spinlock_t lock; 18462306a36Sopenharmony_ci int counter; 18562306a36Sopenharmony_ci } die = { 18662306a36Sopenharmony_ci .lock = __SPIN_LOCK_UNLOCKED(die.lock), 18762306a36Sopenharmony_ci .counter = 0 18862306a36Sopenharmony_ci }; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci console_verbose(); 19162306a36Sopenharmony_ci oops_enter(); 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci spin_lock_irq(&die.lock); 19462306a36Sopenharmony_ci bust_spinlocks(1); 19562306a36Sopenharmony_ci printk(KERN_EMERG "Oops: %s[#%d]:\n", str, ++die.counter); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci if (notify_die(DIE_OOPS, str, regs, err, pt_cause(regs), SIGSEGV) == 19862306a36Sopenharmony_ci NOTIFY_STOP) 19962306a36Sopenharmony_ci return 1; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci print_modules(); 20262306a36Sopenharmony_ci show_regs(regs); 20362306a36Sopenharmony_ci do_show_stack(current, ®s->r30, pt_elr(regs), KERN_EMERG); 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci bust_spinlocks(0); 20662306a36Sopenharmony_ci add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci spin_unlock_irq(&die.lock); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci if (in_interrupt()) 21162306a36Sopenharmony_ci panic("Fatal exception in interrupt"); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci if (panic_on_oops) 21462306a36Sopenharmony_ci panic("Fatal exception"); 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci oops_exit(); 21762306a36Sopenharmony_ci make_task_dead(err); 21862306a36Sopenharmony_ci return 0; 21962306a36Sopenharmony_ci} 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ciint die_if_kernel(char *str, struct pt_regs *regs, long err) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci if (!user_mode(regs)) 22462306a36Sopenharmony_ci return die(str, regs, err); 22562306a36Sopenharmony_ci else 22662306a36Sopenharmony_ci return 0; 22762306a36Sopenharmony_ci} 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci/* 23062306a36Sopenharmony_ci * It's not clear that misaligned fetches are ever recoverable. 23162306a36Sopenharmony_ci */ 23262306a36Sopenharmony_cistatic void misaligned_instruction(struct pt_regs *regs) 23362306a36Sopenharmony_ci{ 23462306a36Sopenharmony_ci die_if_kernel("Misaligned Instruction", regs, 0); 23562306a36Sopenharmony_ci force_sig(SIGBUS); 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci/* 23962306a36Sopenharmony_ci * Misaligned loads and stores, on the other hand, can be 24062306a36Sopenharmony_ci * emulated, and probably should be, some day. But for now 24162306a36Sopenharmony_ci * they will be considered fatal. 24262306a36Sopenharmony_ci */ 24362306a36Sopenharmony_cistatic void misaligned_data_load(struct pt_regs *regs) 24462306a36Sopenharmony_ci{ 24562306a36Sopenharmony_ci die_if_kernel("Misaligned Data Load", regs, 0); 24662306a36Sopenharmony_ci force_sig(SIGBUS); 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_cistatic void misaligned_data_store(struct pt_regs *regs) 25062306a36Sopenharmony_ci{ 25162306a36Sopenharmony_ci die_if_kernel("Misaligned Data Store", regs, 0); 25262306a36Sopenharmony_ci force_sig(SIGBUS); 25362306a36Sopenharmony_ci} 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_cistatic void illegal_instruction(struct pt_regs *regs) 25662306a36Sopenharmony_ci{ 25762306a36Sopenharmony_ci die_if_kernel("Illegal Instruction", regs, 0); 25862306a36Sopenharmony_ci force_sig(SIGILL); 25962306a36Sopenharmony_ci} 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci/* 26262306a36Sopenharmony_ci * Precise bus errors may be recoverable with a a retry, 26362306a36Sopenharmony_ci * but for now, treat them as irrecoverable. 26462306a36Sopenharmony_ci */ 26562306a36Sopenharmony_cistatic void precise_bus_error(struct pt_regs *regs) 26662306a36Sopenharmony_ci{ 26762306a36Sopenharmony_ci die_if_kernel("Precise Bus Error", regs, 0); 26862306a36Sopenharmony_ci force_sig(SIGBUS); 26962306a36Sopenharmony_ci} 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci/* 27262306a36Sopenharmony_ci * If anything is to be done here other than panic, 27362306a36Sopenharmony_ci * it will probably be complex and migrate to another 27462306a36Sopenharmony_ci * source module. For now, just die. 27562306a36Sopenharmony_ci */ 27662306a36Sopenharmony_cistatic void cache_error(struct pt_regs *regs) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci die("Cache Error", regs, 0); 27962306a36Sopenharmony_ci} 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci/* 28262306a36Sopenharmony_ci * General exception handler 28362306a36Sopenharmony_ci */ 28462306a36Sopenharmony_civoid do_genex(struct pt_regs *regs) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci /* 28762306a36Sopenharmony_ci * Decode Cause and Dispatch 28862306a36Sopenharmony_ci */ 28962306a36Sopenharmony_ci switch (pt_cause(regs)) { 29062306a36Sopenharmony_ci case HVM_GE_C_XPROT: 29162306a36Sopenharmony_ci case HVM_GE_C_XUSER: 29262306a36Sopenharmony_ci execute_protection_fault(regs); 29362306a36Sopenharmony_ci break; 29462306a36Sopenharmony_ci case HVM_GE_C_RPROT: 29562306a36Sopenharmony_ci case HVM_GE_C_RUSER: 29662306a36Sopenharmony_ci read_protection_fault(regs); 29762306a36Sopenharmony_ci break; 29862306a36Sopenharmony_ci case HVM_GE_C_WPROT: 29962306a36Sopenharmony_ci case HVM_GE_C_WUSER: 30062306a36Sopenharmony_ci write_protection_fault(regs); 30162306a36Sopenharmony_ci break; 30262306a36Sopenharmony_ci case HVM_GE_C_XMAL: 30362306a36Sopenharmony_ci misaligned_instruction(regs); 30462306a36Sopenharmony_ci break; 30562306a36Sopenharmony_ci case HVM_GE_C_WREG: 30662306a36Sopenharmony_ci illegal_instruction(regs); 30762306a36Sopenharmony_ci break; 30862306a36Sopenharmony_ci case HVM_GE_C_PCAL: 30962306a36Sopenharmony_ci misaligned_instruction(regs); 31062306a36Sopenharmony_ci break; 31162306a36Sopenharmony_ci case HVM_GE_C_RMAL: 31262306a36Sopenharmony_ci misaligned_data_load(regs); 31362306a36Sopenharmony_ci break; 31462306a36Sopenharmony_ci case HVM_GE_C_WMAL: 31562306a36Sopenharmony_ci misaligned_data_store(regs); 31662306a36Sopenharmony_ci break; 31762306a36Sopenharmony_ci case HVM_GE_C_INVI: 31862306a36Sopenharmony_ci case HVM_GE_C_PRIVI: 31962306a36Sopenharmony_ci illegal_instruction(regs); 32062306a36Sopenharmony_ci break; 32162306a36Sopenharmony_ci case HVM_GE_C_BUS: 32262306a36Sopenharmony_ci precise_bus_error(regs); 32362306a36Sopenharmony_ci break; 32462306a36Sopenharmony_ci case HVM_GE_C_CACHE: 32562306a36Sopenharmony_ci cache_error(regs); 32662306a36Sopenharmony_ci break; 32762306a36Sopenharmony_ci default: 32862306a36Sopenharmony_ci /* Halt and catch fire */ 32962306a36Sopenharmony_ci panic("Unrecognized exception 0x%lx\n", pt_cause(regs)); 33062306a36Sopenharmony_ci break; 33162306a36Sopenharmony_ci } 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci/* Indirect system call dispatch */ 33562306a36Sopenharmony_cilong sys_syscall(void) 33662306a36Sopenharmony_ci{ 33762306a36Sopenharmony_ci printk(KERN_ERR "sys_syscall invoked!\n"); 33862306a36Sopenharmony_ci return -ENOSYS; 33962306a36Sopenharmony_ci} 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_civoid do_trap0(struct pt_regs *regs) 34262306a36Sopenharmony_ci{ 34362306a36Sopenharmony_ci syscall_fn syscall; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci switch (pt_cause(regs)) { 34662306a36Sopenharmony_ci case TRAP_SYSCALL: 34762306a36Sopenharmony_ci /* System call is trap0 #1 */ 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci /* allow strace to catch syscall args */ 35062306a36Sopenharmony_ci if (unlikely(test_thread_flag(TIF_SYSCALL_TRACE) && 35162306a36Sopenharmony_ci ptrace_report_syscall_entry(regs))) 35262306a36Sopenharmony_ci return; /* return -ENOSYS somewhere? */ 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci /* Interrupts should be re-enabled for syscall processing */ 35562306a36Sopenharmony_ci __vmsetie(VM_INT_ENABLE); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci /* 35862306a36Sopenharmony_ci * System call number is in r6, arguments in r0..r5. 35962306a36Sopenharmony_ci * Fortunately, no Linux syscall has more than 6 arguments, 36062306a36Sopenharmony_ci * and Hexagon ABI passes first 6 arguments in registers. 36162306a36Sopenharmony_ci * 64-bit arguments are passed in odd/even register pairs. 36262306a36Sopenharmony_ci * Fortunately, we have no system calls that take more 36362306a36Sopenharmony_ci * than three arguments with more than one 64-bit value. 36462306a36Sopenharmony_ci * Should that change, we'd need to redesign to copy 36562306a36Sopenharmony_ci * between user and kernel stacks. 36662306a36Sopenharmony_ci */ 36762306a36Sopenharmony_ci regs->syscall_nr = regs->r06; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci /* 37062306a36Sopenharmony_ci * GPR R0 carries the first parameter, and is also used 37162306a36Sopenharmony_ci * to report the return value. We need a backup of 37262306a36Sopenharmony_ci * the user's value in case we need to do a late restart 37362306a36Sopenharmony_ci * of the system call. 37462306a36Sopenharmony_ci */ 37562306a36Sopenharmony_ci regs->restart_r0 = regs->r00; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci if ((unsigned long) regs->syscall_nr >= __NR_syscalls) { 37862306a36Sopenharmony_ci regs->r00 = -1; 37962306a36Sopenharmony_ci } else { 38062306a36Sopenharmony_ci syscall = (syscall_fn) 38162306a36Sopenharmony_ci (sys_call_table[regs->syscall_nr]); 38262306a36Sopenharmony_ci regs->r00 = syscall(regs->r00, regs->r01, 38362306a36Sopenharmony_ci regs->r02, regs->r03, 38462306a36Sopenharmony_ci regs->r04, regs->r05); 38562306a36Sopenharmony_ci } 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci /* allow strace to get the syscall return state */ 38862306a36Sopenharmony_ci if (unlikely(test_thread_flag(TIF_SYSCALL_TRACE))) 38962306a36Sopenharmony_ci ptrace_report_syscall_exit(regs, 0); 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci break; 39262306a36Sopenharmony_ci case TRAP_DEBUG: 39362306a36Sopenharmony_ci /* Trap0 0xdb is debug breakpoint */ 39462306a36Sopenharmony_ci if (user_mode(regs)) { 39562306a36Sopenharmony_ci /* 39662306a36Sopenharmony_ci * Some architecures add some per-thread state 39762306a36Sopenharmony_ci * to distinguish between breakpoint traps and 39862306a36Sopenharmony_ci * trace traps. We may want to do that, and 39962306a36Sopenharmony_ci * set the si_code value appropriately, or we 40062306a36Sopenharmony_ci * may want to use a different trap0 flavor. 40162306a36Sopenharmony_ci */ 40262306a36Sopenharmony_ci force_sig_fault(SIGTRAP, TRAP_BRKPT, 40362306a36Sopenharmony_ci (void __user *) pt_elr(regs)); 40462306a36Sopenharmony_ci } else { 40562306a36Sopenharmony_ci#ifdef CONFIG_KGDB 40662306a36Sopenharmony_ci kgdb_handle_exception(pt_cause(regs), SIGTRAP, 40762306a36Sopenharmony_ci TRAP_BRKPT, regs); 40862306a36Sopenharmony_ci#endif 40962306a36Sopenharmony_ci } 41062306a36Sopenharmony_ci break; 41162306a36Sopenharmony_ci } 41262306a36Sopenharmony_ci /* Ignore other trap0 codes for now, especially 0 (Angel calls) */ 41362306a36Sopenharmony_ci} 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci/* 41662306a36Sopenharmony_ci * Machine check exception handler 41762306a36Sopenharmony_ci */ 41862306a36Sopenharmony_civoid do_machcheck(struct pt_regs *regs) 41962306a36Sopenharmony_ci{ 42062306a36Sopenharmony_ci /* Halt and catch fire */ 42162306a36Sopenharmony_ci __vmstop(); 42262306a36Sopenharmony_ci} 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci/* 42562306a36Sopenharmony_ci * Treat this like the old 0xdb trap. 42662306a36Sopenharmony_ci */ 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_civoid do_debug_exception(struct pt_regs *regs) 42962306a36Sopenharmony_ci{ 43062306a36Sopenharmony_ci regs->hvmer.vmest &= ~HVM_VMEST_CAUSE_MSK; 43162306a36Sopenharmony_ci regs->hvmer.vmest |= (TRAP_DEBUG << HVM_VMEST_CAUSE_SFT); 43262306a36Sopenharmony_ci do_trap0(regs); 43362306a36Sopenharmony_ci} 434