18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * PowerPC BookIII S hardware breakpoint definitions 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright 2010, IBM Corporation. 68c2ecf20Sopenharmony_ci * Author: K.Prasad <prasad@linux.vnet.ibm.com> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#ifndef _PPC_BOOK3S_64_HW_BREAKPOINT_H 108c2ecf20Sopenharmony_ci#define _PPC_BOOK3S_64_HW_BREAKPOINT_H 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <asm/cpu_has_feature.h> 138c2ecf20Sopenharmony_ci#include <asm/inst.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#ifdef __KERNEL__ 168c2ecf20Sopenharmony_cistruct arch_hw_breakpoint { 178c2ecf20Sopenharmony_ci unsigned long address; 188c2ecf20Sopenharmony_ci u16 type; 198c2ecf20Sopenharmony_ci u16 len; /* length of the target data symbol */ 208c2ecf20Sopenharmony_ci u16 hw_len; /* length programmed in hw */ 218c2ecf20Sopenharmony_ci u8 flags; 228c2ecf20Sopenharmony_ci}; 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci/* Note: Don't change the first 6 bits below as they are in the same order 258c2ecf20Sopenharmony_ci * as the dabr and dabrx. 268c2ecf20Sopenharmony_ci */ 278c2ecf20Sopenharmony_ci#define HW_BRK_TYPE_READ 0x01 288c2ecf20Sopenharmony_ci#define HW_BRK_TYPE_WRITE 0x02 298c2ecf20Sopenharmony_ci#define HW_BRK_TYPE_TRANSLATE 0x04 308c2ecf20Sopenharmony_ci#define HW_BRK_TYPE_USER 0x08 318c2ecf20Sopenharmony_ci#define HW_BRK_TYPE_KERNEL 0x10 328c2ecf20Sopenharmony_ci#define HW_BRK_TYPE_HYP 0x20 338c2ecf20Sopenharmony_ci#define HW_BRK_TYPE_EXTRANEOUS_IRQ 0x80 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci/* bits that overlap with the bottom 3 bits of the dabr */ 368c2ecf20Sopenharmony_ci#define HW_BRK_TYPE_RDWR (HW_BRK_TYPE_READ | HW_BRK_TYPE_WRITE) 378c2ecf20Sopenharmony_ci#define HW_BRK_TYPE_DABR (HW_BRK_TYPE_RDWR | HW_BRK_TYPE_TRANSLATE) 388c2ecf20Sopenharmony_ci#define HW_BRK_TYPE_PRIV_ALL (HW_BRK_TYPE_USER | HW_BRK_TYPE_KERNEL | \ 398c2ecf20Sopenharmony_ci HW_BRK_TYPE_HYP) 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci#define HW_BRK_FLAG_DISABLED 0x1 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* Minimum granularity */ 448c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_8xx 458c2ecf20Sopenharmony_ci#define HW_BREAKPOINT_SIZE 0x4 468c2ecf20Sopenharmony_ci#else 478c2ecf20Sopenharmony_ci#define HW_BREAKPOINT_SIZE 0x8 488c2ecf20Sopenharmony_ci#endif 498c2ecf20Sopenharmony_ci#define HW_BREAKPOINT_SIZE_QUADWORD 0x10 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci#define DABR_MAX_LEN 8 528c2ecf20Sopenharmony_ci#define DAWR_MAX_LEN 512 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic inline int nr_wp_slots(void) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci return cpu_has_feature(CPU_FTR_DAWR1) ? 2 : 1; 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cibool wp_check_constraints(struct pt_regs *regs, struct ppc_inst instr, 608c2ecf20Sopenharmony_ci unsigned long ea, int type, int size, 618c2ecf20Sopenharmony_ci struct arch_hw_breakpoint *info); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_civoid wp_get_instr_detail(struct pt_regs *regs, struct ppc_inst *instr, 648c2ecf20Sopenharmony_ci int *type, int *size, unsigned long *ea); 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#ifdef CONFIG_HAVE_HW_BREAKPOINT 678c2ecf20Sopenharmony_ci#include <linux/kdebug.h> 688c2ecf20Sopenharmony_ci#include <asm/reg.h> 698c2ecf20Sopenharmony_ci#include <asm/debug.h> 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cistruct perf_event_attr; 728c2ecf20Sopenharmony_cistruct perf_event; 738c2ecf20Sopenharmony_cistruct pmu; 748c2ecf20Sopenharmony_cistruct perf_sample_data; 758c2ecf20Sopenharmony_cistruct task_struct; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ciextern int hw_breakpoint_slots(int type); 788c2ecf20Sopenharmony_ciextern int arch_bp_generic_fields(int type, int *gen_bp_type); 798c2ecf20Sopenharmony_ciextern int arch_check_bp_in_kernelspace(struct arch_hw_breakpoint *hw); 808c2ecf20Sopenharmony_ciextern int hw_breakpoint_arch_parse(struct perf_event *bp, 818c2ecf20Sopenharmony_ci const struct perf_event_attr *attr, 828c2ecf20Sopenharmony_ci struct arch_hw_breakpoint *hw); 838c2ecf20Sopenharmony_ciextern int hw_breakpoint_exceptions_notify(struct notifier_block *unused, 848c2ecf20Sopenharmony_ci unsigned long val, void *data); 858c2ecf20Sopenharmony_ciint arch_install_hw_breakpoint(struct perf_event *bp); 868c2ecf20Sopenharmony_civoid arch_uninstall_hw_breakpoint(struct perf_event *bp); 878c2ecf20Sopenharmony_civoid hw_breakpoint_pmu_read(struct perf_event *bp); 888c2ecf20Sopenharmony_ciextern void flush_ptrace_hw_breakpoint(struct task_struct *tsk); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ciextern struct pmu perf_ops_bp; 918c2ecf20Sopenharmony_ciextern void ptrace_triggered(struct perf_event *bp, 928c2ecf20Sopenharmony_ci struct perf_sample_data *data, struct pt_regs *regs); 938c2ecf20Sopenharmony_cistatic inline void hw_breakpoint_disable(void) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci int i; 968c2ecf20Sopenharmony_ci struct arch_hw_breakpoint null_brk = {0}; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci if (!ppc_breakpoint_available()) 998c2ecf20Sopenharmony_ci return; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci for (i = 0; i < nr_wp_slots(); i++) 1028c2ecf20Sopenharmony_ci __set_breakpoint(i, &null_brk); 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ciextern void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs); 1058c2ecf20Sopenharmony_ciint hw_breakpoint_handler(struct die_args *args); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci#else /* CONFIG_HAVE_HW_BREAKPOINT */ 1088c2ecf20Sopenharmony_cistatic inline void hw_breakpoint_disable(void) { } 1098c2ecf20Sopenharmony_cistatic inline void thread_change_pc(struct task_struct *tsk, 1108c2ecf20Sopenharmony_ci struct pt_regs *regs) { } 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci#endif /* CONFIG_HAVE_HW_BREAKPOINT */ 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_DAWR 1168c2ecf20Sopenharmony_ciextern bool dawr_force_enable; 1178c2ecf20Sopenharmony_cistatic inline bool dawr_enabled(void) 1188c2ecf20Sopenharmony_ci{ 1198c2ecf20Sopenharmony_ci return dawr_force_enable; 1208c2ecf20Sopenharmony_ci} 1218c2ecf20Sopenharmony_ciint set_dawr(int nr, struct arch_hw_breakpoint *brk); 1228c2ecf20Sopenharmony_ci#else 1238c2ecf20Sopenharmony_cistatic inline bool dawr_enabled(void) { return false; } 1248c2ecf20Sopenharmony_cistatic inline int set_dawr(int nr, struct arch_hw_breakpoint *brk) { return -1; } 1258c2ecf20Sopenharmony_ci#endif 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci#endif /* __KERNEL__ */ 1288c2ecf20Sopenharmony_ci#endif /* _PPC_BOOK3S_64_HW_BREAKPOINT_H */ 129