arch/s390/kernel/traps.c

Source file repositories/reference/linux-study-clean/arch/s390/kernel/traps.c

File Facts

System
Linux kernel
Corpus path
arch/s390/kernel/traps.c
Extension
.c
Size
12802 bytes
Lines
451
Domain
Architecture Layer
Bucket
arch/s390
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

if (opcode == S390_BREAKPOINT_U16) {
			if (current->ptrace)
				force_sig_fault(SIGTRAP, TRAP_BRKPT, location);
			else
				signal = SIGILL;
#ifdef CONFIG_UPROBES
		} else if (opcode == UPROBE_SWBP_INSN) {
			is_uprobe_insn = 1;
#endif
		} else {
			signal = SIGILL;
		}
	}
	/*
	 * This is either an illegal op in kernel mode, or user space trapped
	 * on a uprobes illegal instruction. See if kprobes or uprobes picks
	 * it up. If not, SIGILL.
	 */
	if (is_uprobe_insn || !user_mode(regs)) {
		if (notify_die(DIE_BPT, "bpt", regs, 0, 3, SIGTRAP) != NOTIFY_STOP)
			signal = SIGILL;
	}
	if (signal)
		do_trap(regs, signal, ILL_ILLOPC, "illegal operation");
}
NOKPROBE_SYMBOL(illegal_op);

static void vector_exception(struct pt_regs *regs)
{
	int si_code, vic;

	/* get vector interrupt code from fpc */
	save_user_fpu_regs();
	vic = (current->thread.ufpu.fpc & 0xf00) >> 8;
	switch (vic) {
	case 1: /* invalid vector operation */
		si_code = FPE_FLTINV;
		break;
	case 2: /* division by zero */
		si_code = FPE_FLTDIV;
		break;
	case 3: /* overflow */
		si_code = FPE_FLTOVF;
		break;
	case 4: /* underflow */
		si_code = FPE_FLTUND;
		break;
	case 5:	/* inexact */
		si_code = FPE_FLTRES;
		break;
	default: /* unknown cause */
		si_code = 0;
	}
	do_trap(regs, SIGFPE, si_code, "vector exception");
}

static void data_exception(struct pt_regs *regs)
{
	save_user_fpu_regs();
	if (current->thread.ufpu.fpc & FPC_DXC_MASK)
		do_fp_trap(regs, current->thread.ufpu.fpc);
	else
		do_trap(regs, SIGILL, ILL_ILLOPN, "data exception");
}

static void space_switch_exception(struct pt_regs *regs)
{
	/* Set user psw back to home space mode. */
	if (user_mode(regs))
		regs->psw.mask |= PSW_ASC_HOME;
	/* Send SIGILL. */
	do_trap(regs, SIGILL, ILL_PRVOPC, "space switch event");
}

#if defined(CONFIG_BUG) && defined(CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS)

void *__warn_args(struct arch_va_list *args, struct pt_regs *regs)
{
	struct stack_frame *stack_frame;

	/*
	 * Generate va_list from pt_regs. See ELF Application Binary Interface
	 * s390x Supplement documentation for details.
	 *
	 * - __overflow_arg_area needs to point to the parameter area, which
	 *   is right above the standard stack frame (160 bytes)
	 *
	 * - __reg_save_area needs to point to a register save area where
	 *   general registers (%r2 - %r6) can be found at offset 16. Which
	 *   means that the gprs save area of pt_regs can be used

Annotation

Implementation Notes