/* * 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 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 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; } /* * Check that the low-order bits of the address are appropriate * for the alignment implied by len. */ if (info->address & align) return -EINVAL; return 0; }
int arch_validate_hwbkpt_settings(struct perf_event *bp) { 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 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; } /* */ if (info->address & align) return -EINVAL; return 0; }
int arch_validate_hwbkpt_settings(struct perf_event *bp) { 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; } if (info->name) info->address = (unsigned long)kallsyms_lookup_name(info->name); if (info->address & align) return -EINVAL; return 0; }
/* * Validate the arch-specific HW Breakpoint register settings. */ int arch_validate_hwbkpt_settings(struct perf_event *bp) { struct arch_hw_breakpoint *info = counter_arch_bp(bp); int ret; u64 alignment_mask, offset; /* Build the arch_hw_breakpoint. */ ret = arch_build_bp_info(bp); if (ret) return ret; /* * Check address alignment. * We don't do any clever alignment correction for watchpoints * because using 64-bit unaligned addresses is deprecated for * AArch64. * * AArch32 tasks expect some simple alignment fixups, so emulate * that here. */ if (is_compat_task()) { if (info->ctrl.len == ARM_BREAKPOINT_LEN_8) alignment_mask = 0x7; else alignment_mask = 0x3; offset = info->address & alignment_mask; switch (offset) { case 0: /* Aligned */ break; case 1: /* Allow single byte watchpoint. */ if (info->ctrl.len == ARM_BREAKPOINT_LEN_1) break; case 2: /* Allow halfword watchpoints and breakpoints. */ if (info->ctrl.len == ARM_BREAKPOINT_LEN_2) break; default: return -EINVAL; } info->address &= ~alignment_mask; info->ctrl.len <<= offset; } else { if (info->ctrl.type == ARM_BREAKPOINT_EXECUTE) alignment_mask = 0x3; else alignment_mask = 0x7; if (info->address & alignment_mask) return -EINVAL; } /* * Disallow per-task kernel breakpoints since these would * complicate the stepping code. */ if (info->ctrl.privilege == AARCH64_BREAKPOINT_EL1 && bp->hw.bp_target) return -EINVAL; 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; }