Path: blob/master/arch/powerpc/kernel/hw_breakpoint.c
10817 views
/*1* HW_breakpoint: a unified kernel/user-space hardware breakpoint facility,2* using the CPU's debug registers. Derived from3* "arch/x86/kernel/hw_breakpoint.c"4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License as published by7* the Free Software Foundation; either version 2 of the License, or8* (at your option) any later version.9*10* This program is distributed in the hope that it will be useful,11* but WITHOUT ANY WARRANTY; without even the implied warranty of12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13* GNU General Public License for more details.14*15* You should have received a copy of the GNU General Public License16* along with this program; if not, write to the Free Software17* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.18*19* Copyright 2010 IBM Corporation20* Author: K.Prasad <[email protected]>21*22*/2324#include <linux/hw_breakpoint.h>25#include <linux/notifier.h>26#include <linux/kprobes.h>27#include <linux/percpu.h>28#include <linux/kernel.h>29#include <linux/module.h>30#include <linux/sched.h>31#include <linux/init.h>32#include <linux/smp.h>3334#include <asm/hw_breakpoint.h>35#include <asm/processor.h>36#include <asm/sstep.h>37#include <asm/uaccess.h>3839/*40* Stores the breakpoints currently in use on each breakpoint address41* register for every cpu42*/43static DEFINE_PER_CPU(struct perf_event *, bp_per_reg);4445/*46* Returns total number of data or instruction breakpoints available.47*/48int hw_breakpoint_slots(int type)49{50if (type == TYPE_DATA)51return HBP_NUM;52return 0; /* no instruction breakpoints available */53}5455/*56* Install a perf counter breakpoint.57*58* We seek a free debug address register and use it for this59* breakpoint.60*61* Atomic: we hold the counter->ctx->lock and we only handle variables62* and registers local to this cpu.63*/64int arch_install_hw_breakpoint(struct perf_event *bp)65{66struct arch_hw_breakpoint *info = counter_arch_bp(bp);67struct perf_event **slot = &__get_cpu_var(bp_per_reg);6869*slot = bp;7071/*72* Do not install DABR values if the instruction must be single-stepped.73* If so, DABR will be populated in single_step_dabr_instruction().74*/75if (current->thread.last_hit_ubp != bp)76set_dabr(info->address | info->type | DABR_TRANSLATION);7778return 0;79}8081/*82* Uninstall the breakpoint contained in the given counter.83*84* First we search the debug address register it uses and then we disable85* it.86*87* Atomic: we hold the counter->ctx->lock and we only handle variables88* and registers local to this cpu.89*/90void arch_uninstall_hw_breakpoint(struct perf_event *bp)91{92struct perf_event **slot = &__get_cpu_var(bp_per_reg);9394if (*slot != bp) {95WARN_ONCE(1, "Can't find the breakpoint");96return;97}9899*slot = NULL;100set_dabr(0);101}102103/*104* Perform cleanup of arch-specific counters during unregistration105* of the perf-event106*/107void arch_unregister_hw_breakpoint(struct perf_event *bp)108{109/*110* If the breakpoint is unregistered between a hw_breakpoint_handler()111* and the single_step_dabr_instruction(), then cleanup the breakpoint112* restoration variables to prevent dangling pointers.113*/114if (bp->ctx->task)115bp->ctx->task->thread.last_hit_ubp = NULL;116}117118/*119* Check for virtual address in kernel space.120*/121int arch_check_bp_in_kernelspace(struct perf_event *bp)122{123struct arch_hw_breakpoint *info = counter_arch_bp(bp);124125return is_kernel_addr(info->address);126}127128int arch_bp_generic_fields(int type, int *gen_bp_type)129{130switch (type) {131case DABR_DATA_READ:132*gen_bp_type = HW_BREAKPOINT_R;133break;134case DABR_DATA_WRITE:135*gen_bp_type = HW_BREAKPOINT_W;136break;137case (DABR_DATA_WRITE | DABR_DATA_READ):138*gen_bp_type = (HW_BREAKPOINT_W | HW_BREAKPOINT_R);139break;140default:141return -EINVAL;142}143return 0;144}145146/*147* Validate the arch-specific HW Breakpoint register settings148*/149int arch_validate_hwbkpt_settings(struct perf_event *bp)150{151int ret = -EINVAL;152struct arch_hw_breakpoint *info = counter_arch_bp(bp);153154if (!bp)155return ret;156157switch (bp->attr.bp_type) {158case HW_BREAKPOINT_R:159info->type = DABR_DATA_READ;160break;161case HW_BREAKPOINT_W:162info->type = DABR_DATA_WRITE;163break;164case HW_BREAKPOINT_R | HW_BREAKPOINT_W:165info->type = (DABR_DATA_READ | DABR_DATA_WRITE);166break;167default:168return ret;169}170171info->address = bp->attr.bp_addr;172info->len = bp->attr.bp_len;173174/*175* Since breakpoint length can be a maximum of HW_BREAKPOINT_LEN(8)176* and breakpoint addresses are aligned to nearest double-word177* HW_BREAKPOINT_ALIGN by rounding off to the lower address, the178* 'symbolsize' should satisfy the check below.179*/180if (info->len >181(HW_BREAKPOINT_LEN - (info->address & HW_BREAKPOINT_ALIGN)))182return -EINVAL;183return 0;184}185186/*187* Restores the breakpoint on the debug registers.188* Invoke this function if it is known that the execution context is189* about to change to cause loss of MSR_SE settings.190*/191void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs)192{193struct arch_hw_breakpoint *info;194195if (likely(!tsk->thread.last_hit_ubp))196return;197198info = counter_arch_bp(tsk->thread.last_hit_ubp);199regs->msr &= ~MSR_SE;200set_dabr(info->address | info->type | DABR_TRANSLATION);201tsk->thread.last_hit_ubp = NULL;202}203204/*205* Handle debug exception notifications.206*/207int __kprobes hw_breakpoint_handler(struct die_args *args)208{209int rc = NOTIFY_STOP;210struct perf_event *bp;211struct pt_regs *regs = args->regs;212int stepped = 1;213struct arch_hw_breakpoint *info;214unsigned int instr;215unsigned long dar = regs->dar;216217/* Disable breakpoints during exception handling */218set_dabr(0);219220/*221* The counter may be concurrently released but that can only222* occur from a call_rcu() path. We can then safely fetch223* the breakpoint, use its callback, touch its counter224* while we are in an rcu_read_lock() path.225*/226rcu_read_lock();227228bp = __get_cpu_var(bp_per_reg);229if (!bp)230goto out;231info = counter_arch_bp(bp);232233/*234* Return early after invoking user-callback function without restoring235* DABR if the breakpoint is from ptrace which always operates in236* one-shot mode. The ptrace-ed process will receive the SIGTRAP signal237* generated in do_dabr().238*/239if (bp->overflow_handler == ptrace_triggered) {240perf_bp_event(bp, regs);241rc = NOTIFY_DONE;242goto out;243}244245/*246* Verify if dar lies within the address range occupied by the symbol247* being watched to filter extraneous exceptions. If it doesn't,248* we still need to single-step the instruction, but we don't249* generate an event.250*/251info->extraneous_interrupt = !((bp->attr.bp_addr <= dar) &&252(dar - bp->attr.bp_addr < bp->attr.bp_len));253254/* Do not emulate user-space instructions, instead single-step them */255if (user_mode(regs)) {256bp->ctx->task->thread.last_hit_ubp = bp;257regs->msr |= MSR_SE;258goto out;259}260261stepped = 0;262instr = 0;263if (!__get_user_inatomic(instr, (unsigned int *) regs->nip))264stepped = emulate_step(regs, instr);265266/*267* emulate_step() could not execute it. We've failed in reliably268* handling the hw-breakpoint. Unregister it and throw a warning269* message to let the user know about it.270*/271if (!stepped) {272WARN(1, "Unable to handle hardware breakpoint. Breakpoint at "273"0x%lx will be disabled.", info->address);274perf_event_disable(bp);275goto out;276}277/*278* As a policy, the callback is invoked in a 'trigger-after-execute'279* fashion280*/281if (!info->extraneous_interrupt)282perf_bp_event(bp, regs);283284set_dabr(info->address | info->type | DABR_TRANSLATION);285out:286rcu_read_unlock();287return rc;288}289290/*291* Handle single-step exceptions following a DABR hit.292*/293int __kprobes single_step_dabr_instruction(struct die_args *args)294{295struct pt_regs *regs = args->regs;296struct perf_event *bp = NULL;297struct arch_hw_breakpoint *bp_info;298299bp = current->thread.last_hit_ubp;300/*301* Check if we are single-stepping as a result of a302* previous HW Breakpoint exception303*/304if (!bp)305return NOTIFY_DONE;306307bp_info = counter_arch_bp(bp);308309/*310* We shall invoke the user-defined callback function in the single311* stepping handler to confirm to 'trigger-after-execute' semantics312*/313if (!bp_info->extraneous_interrupt)314perf_bp_event(bp, regs);315316set_dabr(bp_info->address | bp_info->type | DABR_TRANSLATION);317current->thread.last_hit_ubp = NULL;318319/*320* If the process was being single-stepped by ptrace, let the321* other single-step actions occur (e.g. generate SIGTRAP).322*/323if (test_thread_flag(TIF_SINGLESTEP))324return NOTIFY_DONE;325326return NOTIFY_STOP;327}328329/*330* Handle debug exception notifications.331*/332int __kprobes hw_breakpoint_exceptions_notify(333struct notifier_block *unused, unsigned long val, void *data)334{335int ret = NOTIFY_DONE;336337switch (val) {338case DIE_DABR_MATCH:339ret = hw_breakpoint_handler(data);340break;341case DIE_SSTEP:342ret = single_step_dabr_instruction(data);343break;344}345346return ret;347}348349/*350* Release the user breakpoints used by ptrace351*/352void flush_ptrace_hw_breakpoint(struct task_struct *tsk)353{354struct thread_struct *t = &tsk->thread;355356unregister_hw_breakpoint(t->ptrace_bps[0]);357t->ptrace_bps[0] = NULL;358}359360void hw_breakpoint_pmu_read(struct perf_event *bp)361{362/* TODO */363}364365366