109a07294SPaul Mundt /* 209a07294SPaul Mundt * arch/sh/kernel/hw_breakpoint.c 309a07294SPaul Mundt * 409a07294SPaul Mundt * Unified kernel/user-space hardware breakpoint facility for the on-chip UBC. 509a07294SPaul Mundt * 64352fc1bSPaul Mundt * Copyright (C) 2009 - 2010 Paul Mundt 709a07294SPaul Mundt * 809a07294SPaul Mundt * This file is subject to the terms and conditions of the GNU General Public 909a07294SPaul Mundt * License. See the file "COPYING" in the main directory of this archive 1009a07294SPaul Mundt * for more details. 1109a07294SPaul Mundt */ 1209a07294SPaul Mundt #include <linux/init.h> 1309a07294SPaul Mundt #include <linux/perf_event.h> 1409a07294SPaul Mundt #include <linux/hw_breakpoint.h> 1509a07294SPaul Mundt #include <linux/percpu.h> 1609a07294SPaul Mundt #include <linux/kallsyms.h> 1709a07294SPaul Mundt #include <linux/notifier.h> 1809a07294SPaul Mundt #include <linux/kprobes.h> 1909a07294SPaul Mundt #include <linux/kdebug.h> 2009a07294SPaul Mundt #include <linux/io.h> 214352fc1bSPaul Mundt #include <linux/clk.h> 2209a07294SPaul Mundt #include <asm/hw_breakpoint.h> 2309a07294SPaul Mundt #include <asm/mmu_context.h> 2434d0b5afSPaul Mundt #include <asm/ptrace.h> 2509a07294SPaul Mundt 2609a07294SPaul Mundt /* 2709a07294SPaul Mundt * Stores the breakpoints currently in use on each breakpoint address 2809a07294SPaul Mundt * register for each cpus 2909a07294SPaul Mundt */ 3009a07294SPaul Mundt static DEFINE_PER_CPU(struct perf_event *, bp_per_reg[HBP_NUM]); 3109a07294SPaul Mundt 324352fc1bSPaul Mundt /* 334352fc1bSPaul Mundt * A dummy placeholder for early accesses until the CPUs get a chance to 344352fc1bSPaul Mundt * register their UBCs later in the boot process. 354352fc1bSPaul Mundt */ 364352fc1bSPaul Mundt static struct sh_ubc ubc_dummy = { .num_events = 0 }; 3709a07294SPaul Mundt 384352fc1bSPaul Mundt static struct sh_ubc *sh_ubc __read_mostly = &ubc_dummy; 3909a07294SPaul Mundt 4009a07294SPaul Mundt /* 4109a07294SPaul Mundt * Install a perf counter breakpoint. 4209a07294SPaul Mundt * 4309a07294SPaul Mundt * We seek a free UBC channel and use it for this breakpoint. 4409a07294SPaul Mundt * 4509a07294SPaul Mundt * Atomic: we hold the counter->ctx->lock and we only handle variables 4609a07294SPaul Mundt * and registers local to this cpu. 4709a07294SPaul Mundt */ 4809a07294SPaul Mundt int arch_install_hw_breakpoint(struct perf_event *bp) 4909a07294SPaul Mundt { 5009a07294SPaul Mundt struct arch_hw_breakpoint *info = counter_arch_bp(bp); 5109a07294SPaul Mundt int i; 5209a07294SPaul Mundt 534352fc1bSPaul Mundt for (i = 0; i < sh_ubc->num_events; i++) { 5409a07294SPaul Mundt struct perf_event **slot = &__get_cpu_var(bp_per_reg[i]); 5509a07294SPaul Mundt 5609a07294SPaul Mundt if (!*slot) { 5709a07294SPaul Mundt *slot = bp; 5809a07294SPaul Mundt break; 5909a07294SPaul Mundt } 6009a07294SPaul Mundt } 6109a07294SPaul Mundt 624352fc1bSPaul Mundt if (WARN_ONCE(i == sh_ubc->num_events, "Can't find any breakpoint slot")) 6309a07294SPaul Mundt return -EBUSY; 6409a07294SPaul Mundt 654352fc1bSPaul Mundt clk_enable(sh_ubc->clk); 664352fc1bSPaul Mundt sh_ubc->enable(info, i); 6709a07294SPaul Mundt 6809a07294SPaul Mundt return 0; 6909a07294SPaul Mundt } 7009a07294SPaul Mundt 7109a07294SPaul Mundt /* 7209a07294SPaul Mundt * Uninstall the breakpoint contained in the given counter. 7309a07294SPaul Mundt * 7409a07294SPaul Mundt * First we search the debug address register it uses and then we disable 7509a07294SPaul Mundt * it. 7609a07294SPaul Mundt * 7709a07294SPaul Mundt * Atomic: we hold the counter->ctx->lock and we only handle variables 7809a07294SPaul Mundt * and registers local to this cpu. 7909a07294SPaul Mundt */ 8009a07294SPaul Mundt void arch_uninstall_hw_breakpoint(struct perf_event *bp) 8109a07294SPaul Mundt { 8209a07294SPaul Mundt struct arch_hw_breakpoint *info = counter_arch_bp(bp); 8309a07294SPaul Mundt int i; 8409a07294SPaul Mundt 854352fc1bSPaul Mundt for (i = 0; i < sh_ubc->num_events; i++) { 8609a07294SPaul Mundt struct perf_event **slot = &__get_cpu_var(bp_per_reg[i]); 8709a07294SPaul Mundt 8809a07294SPaul Mundt if (*slot == bp) { 8909a07294SPaul Mundt *slot = NULL; 9009a07294SPaul Mundt break; 9109a07294SPaul Mundt } 9209a07294SPaul Mundt } 9309a07294SPaul Mundt 944352fc1bSPaul Mundt if (WARN_ONCE(i == sh_ubc->num_events, "Can't find any breakpoint slot")) 9509a07294SPaul Mundt return; 9609a07294SPaul Mundt 974352fc1bSPaul Mundt sh_ubc->disable(info, i); 984352fc1bSPaul Mundt clk_disable(sh_ubc->clk); 9909a07294SPaul Mundt } 10009a07294SPaul Mundt 10109a07294SPaul Mundt static int get_hbp_len(u16 hbp_len) 10209a07294SPaul Mundt { 10309a07294SPaul Mundt unsigned int len_in_bytes = 0; 10409a07294SPaul Mundt 10509a07294SPaul Mundt switch (hbp_len) { 10609a07294SPaul Mundt case SH_BREAKPOINT_LEN_1: 10709a07294SPaul Mundt len_in_bytes = 1; 10809a07294SPaul Mundt break; 10909a07294SPaul Mundt case SH_BREAKPOINT_LEN_2: 11009a07294SPaul Mundt len_in_bytes = 2; 11109a07294SPaul Mundt break; 11209a07294SPaul Mundt case SH_BREAKPOINT_LEN_4: 11309a07294SPaul Mundt len_in_bytes = 4; 11409a07294SPaul Mundt break; 11509a07294SPaul Mundt case SH_BREAKPOINT_LEN_8: 11609a07294SPaul Mundt len_in_bytes = 8; 11709a07294SPaul Mundt break; 11809a07294SPaul Mundt } 11909a07294SPaul Mundt return len_in_bytes; 12009a07294SPaul Mundt } 12109a07294SPaul Mundt 12209a07294SPaul Mundt /* 12309a07294SPaul Mundt * Check for virtual address in user space. 12409a07294SPaul Mundt */ 12509a07294SPaul Mundt int arch_check_va_in_userspace(unsigned long va, u16 hbp_len) 12609a07294SPaul Mundt { 12709a07294SPaul Mundt unsigned int len; 12809a07294SPaul Mundt 12909a07294SPaul Mundt len = get_hbp_len(hbp_len); 13009a07294SPaul Mundt 13109a07294SPaul Mundt return (va <= TASK_SIZE - len); 13209a07294SPaul Mundt } 13309a07294SPaul Mundt 13409a07294SPaul Mundt /* 13509a07294SPaul Mundt * Check for virtual address in kernel space. 13609a07294SPaul Mundt */ 13709a07294SPaul Mundt static int arch_check_va_in_kernelspace(unsigned long va, u8 hbp_len) 13809a07294SPaul Mundt { 13909a07294SPaul Mundt unsigned int len; 14009a07294SPaul Mundt 14109a07294SPaul Mundt len = get_hbp_len(hbp_len); 14209a07294SPaul Mundt 14309a07294SPaul Mundt return (va >= TASK_SIZE) && ((va + len - 1) >= TASK_SIZE); 14409a07294SPaul Mundt } 14509a07294SPaul Mundt 14609a07294SPaul Mundt int arch_bp_generic_fields(int sh_len, int sh_type, 14709a07294SPaul Mundt int *gen_len, int *gen_type) 14809a07294SPaul Mundt { 14909a07294SPaul Mundt /* Len */ 15009a07294SPaul Mundt switch (sh_len) { 15109a07294SPaul Mundt case SH_BREAKPOINT_LEN_1: 15209a07294SPaul Mundt *gen_len = HW_BREAKPOINT_LEN_1; 15309a07294SPaul Mundt break; 15409a07294SPaul Mundt case SH_BREAKPOINT_LEN_2: 15509a07294SPaul Mundt *gen_len = HW_BREAKPOINT_LEN_2; 15609a07294SPaul Mundt break; 15709a07294SPaul Mundt case SH_BREAKPOINT_LEN_4: 15809a07294SPaul Mundt *gen_len = HW_BREAKPOINT_LEN_4; 15909a07294SPaul Mundt break; 16009a07294SPaul Mundt case SH_BREAKPOINT_LEN_8: 16109a07294SPaul Mundt *gen_len = HW_BREAKPOINT_LEN_8; 16209a07294SPaul Mundt break; 16309a07294SPaul Mundt default: 16409a07294SPaul Mundt return -EINVAL; 16509a07294SPaul Mundt } 16609a07294SPaul Mundt 16709a07294SPaul Mundt /* Type */ 16809a07294SPaul Mundt switch (sh_type) { 16909a07294SPaul Mundt case SH_BREAKPOINT_READ: 17009a07294SPaul Mundt *gen_type = HW_BREAKPOINT_R; 17109a07294SPaul Mundt case SH_BREAKPOINT_WRITE: 17209a07294SPaul Mundt *gen_type = HW_BREAKPOINT_W; 17309a07294SPaul Mundt break; 17409a07294SPaul Mundt case SH_BREAKPOINT_RW: 17509a07294SPaul Mundt *gen_type = HW_BREAKPOINT_W | HW_BREAKPOINT_R; 17609a07294SPaul Mundt break; 17709a07294SPaul Mundt default: 17809a07294SPaul Mundt return -EINVAL; 17909a07294SPaul Mundt } 18009a07294SPaul Mundt 18109a07294SPaul Mundt return 0; 18209a07294SPaul Mundt } 18309a07294SPaul Mundt 18409a07294SPaul Mundt static int arch_build_bp_info(struct perf_event *bp) 18509a07294SPaul Mundt { 18609a07294SPaul Mundt struct arch_hw_breakpoint *info = counter_arch_bp(bp); 18709a07294SPaul Mundt 18809a07294SPaul Mundt info->address = bp->attr.bp_addr; 18909a07294SPaul Mundt 19009a07294SPaul Mundt /* Len */ 19109a07294SPaul Mundt switch (bp->attr.bp_len) { 19209a07294SPaul Mundt case HW_BREAKPOINT_LEN_1: 19309a07294SPaul Mundt info->len = SH_BREAKPOINT_LEN_1; 19409a07294SPaul Mundt break; 19509a07294SPaul Mundt case HW_BREAKPOINT_LEN_2: 19609a07294SPaul Mundt info->len = SH_BREAKPOINT_LEN_2; 19709a07294SPaul Mundt break; 19809a07294SPaul Mundt case HW_BREAKPOINT_LEN_4: 19909a07294SPaul Mundt info->len = SH_BREAKPOINT_LEN_4; 20009a07294SPaul Mundt break; 20109a07294SPaul Mundt case HW_BREAKPOINT_LEN_8: 20209a07294SPaul Mundt info->len = SH_BREAKPOINT_LEN_8; 20309a07294SPaul Mundt break; 20409a07294SPaul Mundt default: 20509a07294SPaul Mundt return -EINVAL; 20609a07294SPaul Mundt } 20709a07294SPaul Mundt 20809a07294SPaul Mundt /* Type */ 20909a07294SPaul Mundt switch (bp->attr.bp_type) { 21009a07294SPaul Mundt case HW_BREAKPOINT_R: 21109a07294SPaul Mundt info->type = SH_BREAKPOINT_READ; 21209a07294SPaul Mundt break; 21309a07294SPaul Mundt case HW_BREAKPOINT_W: 21409a07294SPaul Mundt info->type = SH_BREAKPOINT_WRITE; 21509a07294SPaul Mundt break; 21609a07294SPaul Mundt case HW_BREAKPOINT_W | HW_BREAKPOINT_R: 21709a07294SPaul Mundt info->type = SH_BREAKPOINT_RW; 21809a07294SPaul Mundt break; 21909a07294SPaul Mundt default: 22009a07294SPaul Mundt return -EINVAL; 22109a07294SPaul Mundt } 22209a07294SPaul Mundt 22309a07294SPaul Mundt return 0; 22409a07294SPaul Mundt } 22509a07294SPaul Mundt 22609a07294SPaul Mundt /* 22709a07294SPaul Mundt * Validate the arch-specific HW Breakpoint register settings 22809a07294SPaul Mundt */ 22909a07294SPaul Mundt int arch_validate_hwbkpt_settings(struct perf_event *bp, 23009a07294SPaul Mundt struct task_struct *tsk) 23109a07294SPaul Mundt { 23209a07294SPaul Mundt struct arch_hw_breakpoint *info = counter_arch_bp(bp); 23309a07294SPaul Mundt unsigned int align; 23409a07294SPaul Mundt int ret; 23509a07294SPaul Mundt 23609a07294SPaul Mundt ret = arch_build_bp_info(bp); 23709a07294SPaul Mundt if (ret) 23809a07294SPaul Mundt return ret; 23909a07294SPaul Mundt 24009a07294SPaul Mundt ret = -EINVAL; 24109a07294SPaul Mundt 24209a07294SPaul Mundt switch (info->len) { 24309a07294SPaul Mundt case SH_BREAKPOINT_LEN_1: 24409a07294SPaul Mundt align = 0; 24509a07294SPaul Mundt break; 24609a07294SPaul Mundt case SH_BREAKPOINT_LEN_2: 24709a07294SPaul Mundt align = 1; 24809a07294SPaul Mundt break; 24909a07294SPaul Mundt case SH_BREAKPOINT_LEN_4: 25009a07294SPaul Mundt align = 3; 25109a07294SPaul Mundt break; 25209a07294SPaul Mundt case SH_BREAKPOINT_LEN_8: 25309a07294SPaul Mundt align = 7; 25409a07294SPaul Mundt break; 25509a07294SPaul Mundt default: 25609a07294SPaul Mundt return ret; 25709a07294SPaul Mundt } 25809a07294SPaul Mundt 259*105244ecSPaul Mundt /* 260*105244ecSPaul Mundt * For kernel-addresses, either the address or symbol name can be 261*105244ecSPaul Mundt * specified. 262*105244ecSPaul Mundt */ 263*105244ecSPaul Mundt if (info->name) 264*105244ecSPaul Mundt info->address = (unsigned long)kallsyms_lookup_name(info->name); 26509a07294SPaul Mundt 26609a07294SPaul Mundt /* 26709a07294SPaul Mundt * Check that the low-order bits of the address are appropriate 26809a07294SPaul Mundt * for the alignment implied by len. 26909a07294SPaul Mundt */ 27009a07294SPaul Mundt if (info->address & align) 27109a07294SPaul Mundt return -EINVAL; 27209a07294SPaul Mundt 27309a07294SPaul Mundt /* Check that the virtual address is in the proper range */ 27409a07294SPaul Mundt if (tsk) { 27509a07294SPaul Mundt if (!arch_check_va_in_userspace(info->address, info->len)) 27609a07294SPaul Mundt return -EFAULT; 27709a07294SPaul Mundt } else { 27809a07294SPaul Mundt if (!arch_check_va_in_kernelspace(info->address, info->len)) 27909a07294SPaul Mundt return -EFAULT; 28009a07294SPaul Mundt } 28109a07294SPaul Mundt 28209a07294SPaul Mundt return 0; 28309a07294SPaul Mundt } 28409a07294SPaul Mundt 28509a07294SPaul Mundt /* 28609a07294SPaul Mundt * Release the user breakpoints used by ptrace 28709a07294SPaul Mundt */ 28809a07294SPaul Mundt void flush_ptrace_hw_breakpoint(struct task_struct *tsk) 28909a07294SPaul Mundt { 29009a07294SPaul Mundt int i; 29109a07294SPaul Mundt struct thread_struct *t = &tsk->thread; 29209a07294SPaul Mundt 2934352fc1bSPaul Mundt for (i = 0; i < sh_ubc->num_events; i++) { 29409a07294SPaul Mundt unregister_hw_breakpoint(t->ptrace_bps[i]); 29509a07294SPaul Mundt t->ptrace_bps[i] = NULL; 29609a07294SPaul Mundt } 29709a07294SPaul Mundt } 29809a07294SPaul Mundt 29909a07294SPaul Mundt static int __kprobes hw_breakpoint_handler(struct die_args *args) 30009a07294SPaul Mundt { 30109a07294SPaul Mundt int cpu, i, rc = NOTIFY_STOP; 30209a07294SPaul Mundt struct perf_event *bp; 3034352fc1bSPaul Mundt unsigned int cmf, resume_mask; 30409a07294SPaul Mundt 3054352fc1bSPaul Mundt /* 3064352fc1bSPaul Mundt * Do an early return if none of the channels triggered. 3074352fc1bSPaul Mundt */ 3084352fc1bSPaul Mundt cmf = sh_ubc->triggered_mask(); 3094352fc1bSPaul Mundt if (unlikely(!cmf)) 3104352fc1bSPaul Mundt return NOTIFY_DONE; 3114352fc1bSPaul Mundt 3124352fc1bSPaul Mundt /* 3134352fc1bSPaul Mundt * By default, resume all of the active channels. 3144352fc1bSPaul Mundt */ 3154352fc1bSPaul Mundt resume_mask = sh_ubc->active_mask(); 3164352fc1bSPaul Mundt 3174352fc1bSPaul Mundt /* 3184352fc1bSPaul Mundt * Disable breakpoints during exception handling. 3194352fc1bSPaul Mundt */ 3204352fc1bSPaul Mundt sh_ubc->disable_all(); 32109a07294SPaul Mundt 32209a07294SPaul Mundt cpu = get_cpu(); 3234352fc1bSPaul Mundt for (i = 0; i < sh_ubc->num_events; i++) { 3244352fc1bSPaul Mundt unsigned long event_mask = (1 << i); 3254352fc1bSPaul Mundt 3264352fc1bSPaul Mundt if (likely(!(cmf & event_mask))) 3274352fc1bSPaul Mundt continue; 3284352fc1bSPaul Mundt 32909a07294SPaul Mundt /* 33009a07294SPaul Mundt * The counter may be concurrently released but that can only 33109a07294SPaul Mundt * occur from a call_rcu() path. We can then safely fetch 33209a07294SPaul Mundt * the breakpoint, use its callback, touch its counter 33309a07294SPaul Mundt * while we are in an rcu_read_lock() path. 33409a07294SPaul Mundt */ 33509a07294SPaul Mundt rcu_read_lock(); 33609a07294SPaul Mundt 33709a07294SPaul Mundt bp = per_cpu(bp_per_reg[i], cpu); 3384352fc1bSPaul Mundt if (bp) 33909a07294SPaul Mundt rc = NOTIFY_DONE; 3404352fc1bSPaul Mundt 3414352fc1bSPaul Mundt /* 3424352fc1bSPaul Mundt * Reset the condition match flag to denote completion of 3434352fc1bSPaul Mundt * exception handling. 3444352fc1bSPaul Mundt */ 3454352fc1bSPaul Mundt sh_ubc->clear_triggered_mask(event_mask); 3464352fc1bSPaul Mundt 3474352fc1bSPaul Mundt /* 3484352fc1bSPaul Mundt * bp can be NULL due to concurrent perf counter 3494352fc1bSPaul Mundt * removing. 3504352fc1bSPaul Mundt */ 3514352fc1bSPaul Mundt if (!bp) { 35209a07294SPaul Mundt rcu_read_unlock(); 35309a07294SPaul Mundt break; 35409a07294SPaul Mundt } 35509a07294SPaul Mundt 3564352fc1bSPaul Mundt /* 3574352fc1bSPaul Mundt * Don't restore the channel if the breakpoint is from 3584352fc1bSPaul Mundt * ptrace, as it always operates in one-shot mode. 3594352fc1bSPaul Mundt */ 3604352fc1bSPaul Mundt if (bp->overflow_handler == ptrace_triggered) 3614352fc1bSPaul Mundt resume_mask &= ~(1 << i); 3624352fc1bSPaul Mundt 363a28b460eSPaul Mundt perf_bp_event(bp, args->regs); 36409a07294SPaul Mundt 3654352fc1bSPaul Mundt /* Deliver the signal to userspace */ 3664352fc1bSPaul Mundt if (arch_check_va_in_userspace(bp->attr.bp_addr, 3674352fc1bSPaul Mundt bp->attr.bp_len)) { 3684352fc1bSPaul Mundt siginfo_t info; 3694352fc1bSPaul Mundt 3704352fc1bSPaul Mundt info.si_signo = args->signr; 3714352fc1bSPaul Mundt info.si_errno = notifier_to_errno(rc); 3724352fc1bSPaul Mundt info.si_code = TRAP_HWBKPT; 3734352fc1bSPaul Mundt 3744352fc1bSPaul Mundt force_sig_info(args->signr, &info, current); 3754352fc1bSPaul Mundt } 3764352fc1bSPaul Mundt 37709a07294SPaul Mundt rcu_read_unlock(); 37809a07294SPaul Mundt } 37909a07294SPaul Mundt 3804352fc1bSPaul Mundt if (cmf == 0) 3814352fc1bSPaul Mundt rc = NOTIFY_DONE; 38209a07294SPaul Mundt 3834352fc1bSPaul Mundt sh_ubc->enable_all(resume_mask); 38409a07294SPaul Mundt 38509a07294SPaul Mundt put_cpu(); 38609a07294SPaul Mundt 38709a07294SPaul Mundt return rc; 38809a07294SPaul Mundt } 38909a07294SPaul Mundt 39009a07294SPaul Mundt BUILD_TRAP_HANDLER(breakpoint) 39109a07294SPaul Mundt { 39209a07294SPaul Mundt unsigned long ex = lookup_exception_vector(); 39309a07294SPaul Mundt TRAP_HANDLER_DECL; 39409a07294SPaul Mundt 3954352fc1bSPaul Mundt notify_die(DIE_BREAKPOINT, "breakpoint", regs, 0, ex, SIGTRAP); 39609a07294SPaul Mundt } 39709a07294SPaul Mundt 39809a07294SPaul Mundt /* 39909a07294SPaul Mundt * Handle debug exception notifications. 40009a07294SPaul Mundt */ 40109a07294SPaul Mundt int __kprobes hw_breakpoint_exceptions_notify(struct notifier_block *unused, 40209a07294SPaul Mundt unsigned long val, void *data) 40309a07294SPaul Mundt { 404b74ab703SPaul Mundt struct die_args *args = data; 405b74ab703SPaul Mundt 40609a07294SPaul Mundt if (val != DIE_BREAKPOINT) 40709a07294SPaul Mundt return NOTIFY_DONE; 40809a07294SPaul Mundt 409b74ab703SPaul Mundt /* 410b74ab703SPaul Mundt * If the breakpoint hasn't been triggered by the UBC, it's 411b74ab703SPaul Mundt * probably from a debugger, so don't do anything more here. 4124352fc1bSPaul Mundt * 4134352fc1bSPaul Mundt * This also permits the UBC interface clock to remain off for 4144352fc1bSPaul Mundt * non-UBC breakpoints, as we don't need to check the triggered 4154352fc1bSPaul Mundt * or active channel masks. 416b74ab703SPaul Mundt */ 4174352fc1bSPaul Mundt if (args->trapnr != sh_ubc->trap_nr) 418b74ab703SPaul Mundt return NOTIFY_DONE; 419b74ab703SPaul Mundt 42009a07294SPaul Mundt return hw_breakpoint_handler(data); 42109a07294SPaul Mundt } 42209a07294SPaul Mundt 42309a07294SPaul Mundt void hw_breakpoint_pmu_read(struct perf_event *bp) 42409a07294SPaul Mundt { 42509a07294SPaul Mundt /* TODO */ 42609a07294SPaul Mundt } 42709a07294SPaul Mundt 42809a07294SPaul Mundt void hw_breakpoint_pmu_unthrottle(struct perf_event *bp) 42909a07294SPaul Mundt { 43009a07294SPaul Mundt /* TODO */ 43109a07294SPaul Mundt } 4324352fc1bSPaul Mundt 4334352fc1bSPaul Mundt int register_sh_ubc(struct sh_ubc *ubc) 4344352fc1bSPaul Mundt { 4354352fc1bSPaul Mundt /* Bail if it's already assigned */ 4364352fc1bSPaul Mundt if (sh_ubc != &ubc_dummy) 4374352fc1bSPaul Mundt return -EBUSY; 4384352fc1bSPaul Mundt sh_ubc = ubc; 4394352fc1bSPaul Mundt 4404352fc1bSPaul Mundt pr_info("HW Breakpoints: %s UBC support registered\n", ubc->name); 4414352fc1bSPaul Mundt 4424352fc1bSPaul Mundt WARN_ON(ubc->num_events > HBP_NUM); 4434352fc1bSPaul Mundt 4444352fc1bSPaul Mundt return 0; 4454352fc1bSPaul Mundt } 446