cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

traps.c (5737B)


      1// SPDX-License-Identifier: GPL-2.0
      2// Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
      3
      4#include <linux/sched.h>
      5#include <linux/signal.h>
      6#include <linux/kernel.h>
      7#include <linux/mm.h>
      8#include <linux/module.h>
      9#include <linux/user.h>
     10#include <linux/string.h>
     11#include <linux/linkage.h>
     12#include <linux/init.h>
     13#include <linux/ptrace.h>
     14#include <linux/kallsyms.h>
     15#include <linux/rtc.h>
     16#include <linux/uaccess.h>
     17#include <linux/kprobes.h>
     18#include <linux/kdebug.h>
     19#include <linux/sched/debug.h>
     20
     21#include <asm/setup.h>
     22#include <asm/traps.h>
     23#include <asm/pgalloc.h>
     24#include <asm/siginfo.h>
     25
     26#include <asm/mmu_context.h>
     27
     28#ifdef CONFIG_CPU_HAS_FPU
     29#include <abi/fpu.h>
     30#endif
     31
     32int show_unhandled_signals = 1;
     33
     34/* Defined in entry.S */
     35asmlinkage void csky_trap(void);
     36
     37asmlinkage void csky_systemcall(void);
     38asmlinkage void csky_cmpxchg(void);
     39asmlinkage void csky_get_tls(void);
     40asmlinkage void csky_irq(void);
     41
     42asmlinkage void csky_pagefault(void);
     43
     44/* Defined in head.S */
     45asmlinkage void _start_smp_secondary(void);
     46
     47void __init pre_trap_init(void)
     48{
     49	int i;
     50
     51	mtcr("vbr", vec_base);
     52
     53	for (i = 1; i < 128; i++)
     54		VEC_INIT(i, csky_trap);
     55}
     56
     57void __init trap_init(void)
     58{
     59	VEC_INIT(VEC_AUTOVEC, csky_irq);
     60
     61	/* setup trap0 trap2 trap3 */
     62	VEC_INIT(VEC_TRAP0, csky_systemcall);
     63	VEC_INIT(VEC_TRAP2, csky_cmpxchg);
     64	VEC_INIT(VEC_TRAP3, csky_get_tls);
     65
     66	/* setup MMU TLB exception */
     67	VEC_INIT(VEC_TLBINVALIDL, csky_pagefault);
     68	VEC_INIT(VEC_TLBINVALIDS, csky_pagefault);
     69	VEC_INIT(VEC_TLBMODIFIED, csky_pagefault);
     70
     71#ifdef CONFIG_CPU_HAS_FPU
     72	init_fpu();
     73#endif
     74
     75#ifdef CONFIG_SMP
     76	mtcr("cr<28, 0>", virt_to_phys(vec_base));
     77
     78	VEC_INIT(VEC_RESET, (void *)virt_to_phys(_start_smp_secondary));
     79#endif
     80}
     81
     82static DEFINE_SPINLOCK(die_lock);
     83
     84void die(struct pt_regs *regs, const char *str)
     85{
     86	static int die_counter;
     87	int ret;
     88
     89	oops_enter();
     90
     91	spin_lock_irq(&die_lock);
     92	console_verbose();
     93	bust_spinlocks(1);
     94
     95	pr_emerg("%s [#%d]\n", str, ++die_counter);
     96	print_modules();
     97	show_regs(regs);
     98	show_stack(current, (unsigned long *)regs->regs[4], KERN_INFO);
     99
    100	ret = notify_die(DIE_OOPS, str, regs, 0, trap_no(regs), SIGSEGV);
    101
    102	bust_spinlocks(0);
    103	add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
    104	spin_unlock_irq(&die_lock);
    105	oops_exit();
    106
    107	if (in_interrupt())
    108		panic("Fatal exception in interrupt");
    109	if (panic_on_oops)
    110		panic("Fatal exception");
    111	if (ret != NOTIFY_STOP)
    112		make_task_dead(SIGSEGV);
    113}
    114
    115void do_trap(struct pt_regs *regs, int signo, int code, unsigned long addr)
    116{
    117	struct task_struct *tsk = current;
    118
    119	if (show_unhandled_signals && unhandled_signal(tsk, signo)
    120	    && printk_ratelimit()) {
    121		pr_info("%s[%d]: unhandled signal %d code 0x%x at 0x%08lx",
    122			tsk->comm, task_pid_nr(tsk), signo, code, addr);
    123		print_vma_addr(KERN_CONT " in ", instruction_pointer(regs));
    124		pr_cont("\n");
    125		show_regs(regs);
    126	}
    127
    128	force_sig_fault(signo, code, (void __user *)addr);
    129}
    130
    131static void do_trap_error(struct pt_regs *regs, int signo, int code,
    132	unsigned long addr, const char *str)
    133{
    134	current->thread.trap_no = trap_no(regs);
    135
    136	if (user_mode(regs)) {
    137		do_trap(regs, signo, code, addr);
    138	} else {
    139		if (!fixup_exception(regs))
    140			die(regs, str);
    141	}
    142}
    143
    144#define DO_ERROR_INFO(name, signo, code, str)				\
    145asmlinkage __visible void name(struct pt_regs *regs)			\
    146{									\
    147	do_trap_error(regs, signo, code, regs->pc, "Oops - " str);	\
    148}
    149
    150DO_ERROR_INFO(do_trap_unknown,
    151	SIGILL, ILL_ILLTRP, "unknown exception");
    152DO_ERROR_INFO(do_trap_zdiv,
    153	SIGFPE, FPE_INTDIV, "error zero div exception");
    154DO_ERROR_INFO(do_trap_buserr,
    155	SIGSEGV, ILL_ILLADR, "error bus error exception");
    156
    157asmlinkage void do_trap_misaligned(struct pt_regs *regs)
    158{
    159#ifdef CONFIG_CPU_NEED_SOFTALIGN
    160	csky_alignment(regs);
    161#else
    162	current->thread.trap_no = trap_no(regs);
    163	do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->pc,
    164		      "Oops - load/store address misaligned");
    165#endif
    166}
    167
    168asmlinkage void do_trap_bkpt(struct pt_regs *regs)
    169{
    170#ifdef CONFIG_KPROBES
    171	if (kprobe_single_step_handler(regs))
    172		return;
    173#endif
    174#ifdef CONFIG_UPROBES
    175	if (uprobe_single_step_handler(regs))
    176		return;
    177#endif
    178	if (user_mode(regs)) {
    179		send_sig(SIGTRAP, current, 0);
    180		return;
    181	}
    182
    183	do_trap_error(regs, SIGILL, ILL_ILLTRP, regs->pc,
    184		      "Oops - illegal trap exception");
    185}
    186
    187asmlinkage void do_trap_illinsn(struct pt_regs *regs)
    188{
    189	current->thread.trap_no = trap_no(regs);
    190
    191#ifdef CONFIG_KPROBES
    192	if (kprobe_breakpoint_handler(regs))
    193		return;
    194#endif
    195#ifdef CONFIG_UPROBES
    196	if (uprobe_breakpoint_handler(regs))
    197		return;
    198#endif
    199#ifndef CONFIG_CPU_NO_USER_BKPT
    200	if (*(uint16_t *)instruction_pointer(regs) != USR_BKPT) {
    201		send_sig(SIGTRAP, current, 0);
    202		return;
    203	}
    204#endif
    205
    206	do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->pc,
    207		      "Oops - illegal instruction exception");
    208}
    209
    210asmlinkage void do_trap_fpe(struct pt_regs *regs)
    211{
    212#ifdef CONFIG_CPU_HAS_FPU
    213	return fpu_fpe(regs);
    214#else
    215	do_trap_error(regs, SIGILL, ILL_ILLOPC, regs->pc,
    216		      "Oops - fpu instruction exception");
    217#endif
    218}
    219
    220asmlinkage void do_trap_priv(struct pt_regs *regs)
    221{
    222#ifdef CONFIG_CPU_HAS_FPU
    223	if (user_mode(regs) && fpu_libc_helper(regs))
    224		return;
    225#endif
    226	do_trap_error(regs, SIGILL, ILL_PRVOPC, regs->pc,
    227		      "Oops - illegal privileged exception");
    228}
    229
    230asmlinkage void trap_c(struct pt_regs *regs)
    231{
    232	switch (trap_no(regs)) {
    233	case VEC_ZERODIV:
    234		do_trap_zdiv(regs);
    235		break;
    236	case VEC_TRACE:
    237		do_trap_bkpt(regs);
    238		break;
    239	case VEC_ILLEGAL:
    240		do_trap_illinsn(regs);
    241		break;
    242	case VEC_TRAP1:
    243	case VEC_BREAKPOINT:
    244		do_trap_bkpt(regs);
    245		break;
    246	case VEC_ACCESS:
    247		do_trap_buserr(regs);
    248		break;
    249	case VEC_ALIGN:
    250		do_trap_misaligned(regs);
    251		break;
    252	case VEC_FPE:
    253		do_trap_fpe(regs);
    254		break;
    255	case VEC_PRIV:
    256		do_trap_priv(regs);
    257		break;
    258	default:
    259		do_trap_unknown(regs);
    260		break;
    261	}
    262}