/* * Validate the arch-specific HW Breakpoint register settings */ int arch_validate_hwbkpt_settings(struct perf_event *bp, struct task_struct *tsk) { struct arch_hw_breakpoint *info = counter_arch_bp(bp); unsigned int align; int ret; ret = arch_build_bp_info(bp); if (ret) return ret; ret = -EINVAL; switch (info->len) { case SH_BREAKPOINT_LEN_1: align = 0; break; case SH_BREAKPOINT_LEN_2: align = 1; break; case SH_BREAKPOINT_LEN_4: align = 3; break; case SH_BREAKPOINT_LEN_8: align = 7; break; default: return ret; } /* * For kernel-addresses, either the address or symbol name can be * specified. */ if (info->name) info->address = (unsigned long)kallsyms_lookup_name(info->name); /* * Check that the low-order bits of the address are appropriate * for the alignment implied by len. */ if (info->address & align) return -EINVAL; /* Check that the virtual address is in the proper range */ if (tsk) { if (!arch_check_va_in_userspace(info->address, info->len)) return -EFAULT; } else { if (!arch_check_va_in_kernelspace(info->address, info->len)) return -EFAULT; } return 0; }
/* * Validate the arch-specific HW Breakpoint register settings */ int arch_validate_hwbkpt_settings(struct perf_event *bp, struct task_struct *tsk) { struct arch_hw_breakpoint *info = counter_arch_bp(bp); unsigned int align; int ret; ret = arch_build_bp_info(bp); if (ret) return ret; ret = -EINVAL; if (info->type == X86_BREAKPOINT_EXECUTE) /* * Ptrace-refactoring code * For now, we'll allow instruction breakpoint only for user-space * addresses */ if ((!arch_check_va_in_userspace(info->address, info->len)) && info->len != X86_BREAKPOINT_EXECUTE) return ret; switch (info->len) { case X86_BREAKPOINT_LEN_1: align = 0; break; case X86_BREAKPOINT_LEN_2: align = 1; break; case X86_BREAKPOINT_LEN_4: align = 3; break; #ifdef CONFIG_X86_64 case X86_BREAKPOINT_LEN_8: align = 7; break; #endif default: return ret; } /* * For kernel-addresses, either the address or symbol name can be * specified. */ if (info->name) info->address = (unsigned long) kallsyms_lookup_name(info->name); /* * Check that the low-order bits of the address are appropriate * for the alignment implied by len. */ if (info->address & align) return -EINVAL; /* Check that the virtual address is in the proper range */ if (tsk) { if (!arch_check_va_in_userspace(info->address, info->len)) return -EFAULT; } else { if (!arch_check_va_in_kernelspace(info->address, info->len)) return -EFAULT; } return 0; }