Commit | Line | Data |
---|---|---|
1a59d1b8 | 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ |
5aae8a53 P |
2 | /* |
3 | * PowerPC BookIII S hardware breakpoint definitions | |
4 | * | |
5aae8a53 P |
5 | * Copyright 2010, IBM Corporation. |
6 | * Author: K.Prasad <prasad@linux.vnet.ibm.com> | |
5aae8a53 P |
7 | */ |
8 | ||
9 | #ifndef _PPC_BOOK3S_64_HW_BREAKPOINT_H | |
10 | #define _PPC_BOOK3S_64_HW_BREAKPOINT_H | |
11 | ||
deb2bd9b RB |
12 | #include <asm/cpu_has_feature.h> |
13 | ||
5aae8a53 | 14 | #ifdef __KERNEL__ |
5aae8a53 | 15 | struct arch_hw_breakpoint { |
5aae8a53 | 16 | unsigned long address; |
9422de3e MN |
17 | u16 type; |
18 | u16 len; /* length of the target data symbol */ | |
b57aeab8 | 19 | u16 hw_len; /* length programmed in hw */ |
5b905d77 | 20 | u8 flags; |
1e60f356 | 21 | bool perf_single_step; /* temporarily uninstalled for a perf single step */ |
5aae8a53 P |
22 | }; |
23 | ||
028cc22d | 24 | /* Note: Don't change the first 6 bits below as they are in the same order |
9422de3e MN |
25 | * as the dabr and dabrx. |
26 | */ | |
27 | #define HW_BRK_TYPE_READ 0x01 | |
28 | #define HW_BRK_TYPE_WRITE 0x02 | |
29 | #define HW_BRK_TYPE_TRANSLATE 0x04 | |
30 | #define HW_BRK_TYPE_USER 0x08 | |
31 | #define HW_BRK_TYPE_KERNEL 0x10 | |
32 | #define HW_BRK_TYPE_HYP 0x20 | |
33 | #define HW_BRK_TYPE_EXTRANEOUS_IRQ 0x80 | |
34 | ||
35 | /* bits that overlap with the bottom 3 bits of the dabr */ | |
36 | #define HW_BRK_TYPE_RDWR (HW_BRK_TYPE_READ | HW_BRK_TYPE_WRITE) | |
37 | #define HW_BRK_TYPE_DABR (HW_BRK_TYPE_RDWR | HW_BRK_TYPE_TRANSLATE) | |
38 | #define HW_BRK_TYPE_PRIV_ALL (HW_BRK_TYPE_USER | HW_BRK_TYPE_KERNEL | \ | |
39 | HW_BRK_TYPE_HYP) | |
40 | ||
5b905d77 RB |
41 | #define HW_BRK_FLAG_DISABLED 0x1 |
42 | ||
e68ef121 | 43 | /* Minimum granularity */ |
39413ae0 | 44 | #ifdef CONFIG_PPC_8xx |
e68ef121 | 45 | #define HW_BREAKPOINT_SIZE 0x4 |
39413ae0 | 46 | #else |
e68ef121 | 47 | #define HW_BREAKPOINT_SIZE 0x8 |
39413ae0 | 48 | #endif |
4759c11e | 49 | #define HW_BREAKPOINT_SIZE_QUADWORD 0x10 |
c3f68b04 | 50 | |
b811be61 RB |
51 | #define DABR_MAX_LEN 8 |
52 | #define DAWR_MAX_LEN 512 | |
53 | ||
a6ba44e8 RB |
54 | static inline int nr_wp_slots(void) |
55 | { | |
deb2bd9b | 56 | return cpu_has_feature(CPU_FTR_DAWR1) ? 2 : 1; |
a6ba44e8 RB |
57 | } |
58 | ||
c545b9f0 | 59 | bool wp_check_constraints(struct pt_regs *regs, ppc_inst_t instr, |
edc8dd99 RB |
60 | unsigned long ea, int type, int size, |
61 | struct arch_hw_breakpoint *info); | |
62 | ||
c545b9f0 | 63 | void wp_get_instr_detail(struct pt_regs *regs, ppc_inst_t *instr, |
edc8dd99 RB |
64 | int *type, int *size, unsigned long *ea); |
65 | ||
9422de3e | 66 | #ifdef CONFIG_HAVE_HW_BREAKPOINT |
5aae8a53 P |
67 | #include <linux/kdebug.h> |
68 | #include <asm/reg.h> | |
ae3a197e | 69 | #include <asm/debug.h> |
5aae8a53 | 70 | |
5d5176ba | 71 | struct perf_event_attr; |
5aae8a53 P |
72 | struct perf_event; |
73 | struct pmu; | |
74 | struct perf_sample_data; | |
62b84265 | 75 | struct task_struct; |
5aae8a53 | 76 | |
d09ec738 | 77 | extern int hw_breakpoint_slots(int type); |
5aae8a53 | 78 | extern int arch_bp_generic_fields(int type, int *gen_bp_type); |
8e983ff9 | 79 | extern int arch_check_bp_in_kernelspace(struct arch_hw_breakpoint *hw); |
5d5176ba FW |
80 | extern int hw_breakpoint_arch_parse(struct perf_event *bp, |
81 | const struct perf_event_attr *attr, | |
82 | struct arch_hw_breakpoint *hw); | |
5aae8a53 P |
83 | extern int hw_breakpoint_exceptions_notify(struct notifier_block *unused, |
84 | unsigned long val, void *data); | |
85 | int arch_install_hw_breakpoint(struct perf_event *bp); | |
86 | void arch_uninstall_hw_breakpoint(struct perf_event *bp); | |
87 | void hw_breakpoint_pmu_read(struct perf_event *bp); | |
88 | extern void flush_ptrace_hw_breakpoint(struct task_struct *tsk); | |
89 | ||
90 | extern struct pmu perf_ops_bp; | |
29dfc4fd | 91 | extern void ptrace_triggered(struct perf_event *bp, |
5aae8a53 P |
92 | struct perf_sample_data *data, struct pt_regs *regs); |
93 | static inline void hw_breakpoint_disable(void) | |
94 | { | |
c2919132 RB |
95 | int i; |
96 | struct arch_hw_breakpoint null_brk = {0}; | |
97 | ||
98 | if (!ppc_breakpoint_available()) | |
99 | return; | |
100 | ||
101 | for (i = 0; i < nr_wp_slots(); i++) | |
102 | __set_breakpoint(i, &null_brk); | |
5aae8a53 | 103 | } |
06532a67 | 104 | extern void thread_change_pc(struct task_struct *tsk, struct pt_regs *regs); |
b0d876da | 105 | int hw_breakpoint_handler(struct die_args *args); |
5aae8a53 | 106 | |
a278e7ea MN |
107 | #else /* CONFIG_HAVE_HW_BREAKPOINT */ |
108 | static inline void hw_breakpoint_disable(void) { } | |
109 | static inline void thread_change_pc(struct task_struct *tsk, | |
110 | struct pt_regs *regs) { } | |
111 | ||
112 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | |
113 | ||
114 | ||
115 | #ifdef CONFIG_PPC_DAWR | |
c1fe190c MN |
116 | extern bool dawr_force_enable; |
117 | static inline bool dawr_enabled(void) | |
118 | { | |
119 | return dawr_force_enable; | |
120 | } | |
a18b8346 | 121 | int set_dawr(int nr, struct arch_hw_breakpoint *brk); |
a278e7ea | 122 | #else |
c1fe190c | 123 | static inline bool dawr_enabled(void) { return false; } |
a18b8346 | 124 | static inline int set_dawr(int nr, struct arch_hw_breakpoint *brk) { return -1; } |
a278e7ea MN |
125 | #endif |
126 | ||
5aae8a53 P |
127 | #endif /* __KERNEL__ */ |
128 | #endif /* _PPC_BOOK3S_64_HW_BREAKPOINT_H */ |