Commit 958d3d72 authored by Oleg Nesterov's avatar Oleg Nesterov
Browse files

x86/traps: Introduce fill_trap_info(), simplify DO_ERROR_INFO()



Extract the fill-siginfo code from DO_ERROR_INFO() into the new helper,
fill_trap_info().

It can calculate si_code and si_addr looking at trapnr, so we can remove
these arguments from DO_ERROR_INFO() and simplify the source code. The
generated code is the same, __builtin_constant_p(trapnr) == T.

Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
parent dff0796e
Loading
Loading
Loading
Loading
+38 −15
Original line number Diff line number Diff line
@@ -136,6 +136,33 @@ do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str,
	return -1;
}

static void fill_trap_info(struct pt_regs *regs, int signr, int trapnr,
			   siginfo_t *info)
{
	unsigned long siaddr;
	int sicode;

	switch (trapnr) {
	case X86_TRAP_DE:
		sicode = FPE_INTDIV;
		siaddr = regs->ip;
		break;
	case X86_TRAP_UD:
		sicode = ILL_ILLOPN;
		siaddr = regs->ip;
		break;
	case X86_TRAP_AC:
		sicode = BUS_ADRALN;
		siaddr = 0;
		break;
	}

	info->si_signo = signr;
	info->si_errno = 0;
	info->si_code = sicode;
	info->si_addr = (void __user *)siaddr;
}

static void __kprobes
do_trap(int trapnr, int signr, char *str, struct pt_regs *regs,
	long error_code, siginfo_t *info)
@@ -191,30 +218,26 @@ dotraplinkage void do_##name(struct pt_regs *regs, long error_code) \
	do_error_trap(regs, error_code, str, trapnr, signr, NULL);	\
}

#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr)		\
#define DO_ERROR_INFO(trapnr, signr, str, name)				\
dotraplinkage void do_##name(struct pt_regs *regs, long error_code)	\
{									\
	siginfo_t info;							\
									\
	info.si_signo = signr;						\
	info.si_errno = 0;						\
	info.si_code = sicode;						\
	info.si_addr = (void __user *)siaddr;				\
									\
	fill_trap_info(regs, signr, trapnr, &info);			\
	do_error_trap(regs, error_code, str, trapnr, signr, &info);	\
}

DO_ERROR_INFO(X86_TRAP_DE,     SIGFPE,  "divide error",			divide_error,		     FPE_INTDIV, regs->ip )
DO_ERROR_INFO(X86_TRAP_DE,     SIGFPE,  "divide error",			divide_error)
DO_ERROR     (X86_TRAP_OF,     SIGSEGV, "overflow",			overflow)
DO_ERROR     (X86_TRAP_BR,     SIGSEGV, "bounds",			bounds)
DO_ERROR_INFO(X86_TRAP_UD,     SIGILL,  "invalid opcode",		invalid_op,		     ILL_ILLOPN, regs->ip )
DO_ERROR_INFO(X86_TRAP_UD,     SIGILL,  "invalid opcode",		invalid_op)
DO_ERROR     (X86_TRAP_OLD_MF, SIGFPE,  "coprocessor segment overrun",	coprocessor_segment_overrun)
DO_ERROR     (X86_TRAP_TS,     SIGSEGV, "invalid TSS",			invalid_TSS)
DO_ERROR     (X86_TRAP_NP,     SIGBUS,  "segment not present",		segment_not_present)
#ifdef CONFIG_X86_32
DO_ERROR     (X86_TRAP_SS,     SIGBUS,  "stack segment",		stack_segment)
#endif
DO_ERROR_INFO(X86_TRAP_AC,     SIGBUS,  "alignment check",		alignment_check,	     BUS_ADRALN, 0	  )
DO_ERROR_INFO(X86_TRAP_AC,     SIGBUS,  "alignment check",		alignment_check)

#ifdef CONFIG_X86_64
/* Runs on IST stack */