2017-04-19 18:22:26 +05:30
/*
* Dynamic Ftrace based Kprobes Optimization
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA .
*
* Copyright ( C ) Hitachi Ltd . , 2012
* Copyright 2016 Naveen N . Rao < naveen . n . rao @ linux . vnet . ibm . com >
* IBM Corporation
*/
# include <linux/kprobes.h>
# include <linux/ptrace.h>
# include <linux/hardirq.h>
# include <linux/preempt.h>
# include <linux/ftrace.h>
/* Ftrace callback handler for kprobes */
void kprobe_ftrace_handler ( unsigned long nip , unsigned long parent_nip ,
struct ftrace_ops * ops , struct pt_regs * regs )
{
struct kprobe * p ;
struct kprobe_ctlblk * kcb ;
p = get_kprobe ( ( kprobe_opcode_t * ) nip ) ;
if ( unlikely ( ! p ) | | kprobe_disabled ( p ) )
2018-06-20 01:15:45 +09:00
return ;
2017-04-19 18:22:26 +05:30
kcb = get_kprobe_ctlblk ( ) ;
if ( kprobe_running ( ) ) {
kprobes_inc_nmissed_count ( p ) ;
} else {
/*
* On powerpc , NIP is * before * this instruction for the
* pre handler
*/
regs - > nip - = MCOUNT_INSN_SIZE ;
__this_cpu_write ( current_kprobe , p ) ;
kcb - > kprobe_status = KPROBE_HIT_ACTIVE ;
2018-06-20 01:12:51 +09:00
if ( ! p - > pre_handler | | ! p - > pre_handler ( p , regs ) ) {
/*
* Emulate singlestep ( and also recover regs - > nip )
* as if there is a nop
*/
regs - > nip + = MCOUNT_INSN_SIZE ;
if ( unlikely ( p - > post_handler ) ) {
kcb - > kprobe_status = KPROBE_HIT_SSDONE ;
p - > post_handler ( p , regs , 0 ) ;
}
2017-09-22 14:40:47 +05:30
}
2018-06-20 01:15:45 +09:00
/*
* If pre_handler returns ! 0 , it changes regs - > nip . We have to
* skip emulating post_handler .
*/
__this_cpu_write ( current_kprobe , NULL ) ;
2017-04-19 18:22:26 +05:30
}
}
NOKPROBE_SYMBOL ( kprobe_ftrace_handler ) ;
int arch_prepare_kprobe_ftrace ( struct kprobe * p )
{
p - > ainsn . insn = NULL ;
p - > ainsn . boostable = - 1 ;
return 0 ;
}