Commit 7cd01b08 authored by Naveen N. Rao's avatar Naveen N. Rao Committed by Michael Ellerman
Browse files

powerpc: Add support for function error injection



We implement regs_set_return_value() and override_function_with_return()
for this purpose.

On powerpc, a return from a function (blr) just branches to the location
contained in the link register. So, we can just update pt_regs rather
than redirecting execution to a dummy function that returns.

Signed-off-by: default avatarNaveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Reviewed-by: default avatarSamuel Mendoza-Jonas <sam@mendozajonas.com>
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
parent b4d16ab5
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -190,6 +190,7 @@ config PPC
	select HAVE_EBPF_JIT			if PPC64
	select HAVE_EBPF_JIT			if PPC64
	select HAVE_EFFICIENT_UNALIGNED_ACCESS	if !(CPU_LITTLE_ENDIAN && POWER7_CPU)
	select HAVE_EFFICIENT_UNALIGNED_ACCESS	if !(CPU_LITTLE_ENDIAN && POWER7_CPU)
	select HAVE_FTRACE_MCOUNT_RECORD
	select HAVE_FTRACE_MCOUNT_RECORD
	select HAVE_FUNCTION_ERROR_INJECTION
	select HAVE_FUNCTION_GRAPH_TRACER
	select HAVE_FUNCTION_GRAPH_TRACER
	select HAVE_FUNCTION_TRACER
	select HAVE_FUNCTION_TRACER
	select HAVE_GCC_PLUGINS			if GCC_VERSION >= 50200   # plugin support on gcc <= 5.1 is buggy on PPC
	select HAVE_GCC_PLUGINS			if GCC_VERSION >= 50200   # plugin support on gcc <= 5.1 is buggy on PPC
+13 −0
Original line number Original line Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0+ */

#ifndef _ASM_ERROR_INJECTION_H
#define _ASM_ERROR_INJECTION_H

#include <linux/compiler.h>
#include <linux/linkage.h>
#include <asm/ptrace.h>
#include <asm-generic/error-injection.h>

void override_function_with_return(struct pt_regs *regs);

#endif /* _ASM_ERROR_INJECTION_H */
+5 −0
Original line number Original line Diff line number Diff line
@@ -133,6 +133,11 @@ static inline long regs_return_value(struct pt_regs *regs)
		return -regs->gpr[3];
		return -regs->gpr[3];
}
}


static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc)
{
	regs->gpr[3] = rc;
}

#ifdef __powerpc64__
#ifdef __powerpc64__
#define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1)
#define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1)
#else
#else
+2 −0
Original line number Original line Diff line number Diff line
@@ -12,6 +12,8 @@ obj-y += string.o alloc.o code-patching.o feature-fixups.o


obj-$(CONFIG_PPC32)	+= div64.o copy_32.o crtsavres.o strlen_32.o
obj-$(CONFIG_PPC32)	+= div64.o copy_32.o crtsavres.o strlen_32.o


obj-$(CONFIG_FUNCTION_ERROR_INJECTION)	+= error-inject.o

# See corresponding test in arch/powerpc/Makefile
# See corresponding test in arch/powerpc/Makefile
# 64-bit linker creates .sfpr on demand for final link (vmlinux),
# 64-bit linker creates .sfpr on demand for final link (vmlinux),
# so it is only needed for modules, and only for older linkers which
# so it is only needed for modules, and only for older linkers which
+16 −0
Original line number Original line Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0+

#include <linux/error-injection.h>
#include <linux/kprobes.h>
#include <linux/uaccess.h>

void override_function_with_return(struct pt_regs *regs)
{
	/*
	 * Emulate 'blr'. 'regs' represents the state on entry of a predefined
	 * function in the kernel/module, captured on a kprobe. We don't need
	 * to worry about 32-bit userspace on a 64-bit kernel.
	 */
	regs->nip = regs->link;
}
NOKPROBE_SYMBOL(override_function_with_return);