1 /*
2 * Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 */
6
7 #pragma once
8
9 #include <config.h>
10
11 #define DBGDSCR_int "p14,0,%0,c0,c1,0"
12 /* Not guaranteed in v7, only v7.1+ */
13 #define DBGDSCR_ext "p14, 0, %0, c0, c2, 2"
14 #define DBGSDER "p15, 0, %0, c1, c1, 1"
15
16 #define DBGWFAR "p14,0,%0,c0,c6,0"
17 #define DFAR "p15,0,%0,c6,c0,0"
18
19 #define DBGDSCR_SECURE_MODE_DISABLED (BIT(18))
20
21 #define DBGSDER_ENABLE_SECURE_USER_NON_INVASIVE_DEBUG (BIT(1))
22
23 #if defined(CONFIG_DEBUG_BUILD) || defined (CONFIG_HARDWARE_DEBUG_API)
24
25 #ifndef __ASSEMBLER__
26 #include <stdint.h>
27 #include <arch/machine/registerset.h>
28
29 void debug_init(void) VISIBLE;
30
31 typedef void (*break_handler_t)(user_context_t *context);
32
33 void software_breakpoint(uint32_t va, user_context_t *context) VISIBLE;
34 void breakpoint_multiplexer(uint32_t va, user_context_t *context) VISIBLE;
35
36 int set_breakpoint(uint32_t va, break_handler_t handler) VISIBLE;
37 void clear_breakpoint(uint32_t va) VISIBLE;
38
39 enum vector_ids {
40 VECTOR_RESET = 0,
41 VECTOR_UNDEFINED = 1,
42 VECTOR_SWI = 2,
43 VECTOR_PREFETCH_ABORT = 3,
44 VECTOR_DATA_ABORT = 4,
45 VECTOR_IRQ = 6,
46 VECTOR_FIQ = 7
47 };
48 typedef uint32_t vector_t;
49
50 typedef void (*catch_handler_t)(user_context_t *context, vector_t vector);
51
52 void set_catch_handler(catch_handler_t handler) VISIBLE;
53 void catch_vector(vector_t vector) VISIBLE;
54 void uncatch_vector(vector_t vector) VISIBLE;
55 #endif /* !__ASSEMBLER__ */
56
57 /*********************************/
58 /*** cp14 register definitions ***/
59 /*********************************/
60
61 /* Debug ID Register */
62 #define DIDR_BRP_OFFSET 24
63 #define DIDR_BRP_SIZE 4
64 #define DIDR_VERSION_OFFSET 16
65 #define DIDR_VERSION_SIZE 4
66 #define DIDR_VARIANT_OFFSET 4
67 #define DIDR_VARIANT_SIZE 4
68 #define DIDR_REVISION_OFFSET 0
69 #define DIDR_REVISION_SIZE 4
70
71 #ifndef __ASSEMBLER__
getDIDR(void)72 static inline uint32_t getDIDR(void)
73 {
74 uint32_t x;
75
76 asm volatile("mrc p14, 0, %0, c0, c0, 0" : "=r"(x));
77
78 return x;
79 }
80
81 #ifdef CONFIG_HARDWARE_DEBUG_API
82
83 #define DEBUG_REPLY_N_REQUIRED_REGISTERS (1)
84
85 /* Get Watchpoint Fault Address register value (for async watchpoints). */
getWFAR(void)86 static inline word_t getWFAR(void)
87 {
88 word_t ret;
89
90 MRC(DBGWFAR, ret);
91 return ret;
92 }
93 #endif
94 #endif /* !__ASSEMBLER__ */
95
96 /* Debug Status and Control Register */
97 #define DSCR_MONITOR_MODE_ENABLE 15
98 #define DSCR_MODE_SELECT 14
99 #define DSCR_ENTRY_OFFSET 2
100 #define DSCR_ENTRY_SIZE 4
101
102 #define DEBUG_ENTRY_DBGTAP_HALT 0
103 #define DEBUG_ENTRY_BREAKPOINT 1
104 #define DEBUG_ENTRY_ASYNC_WATCHPOINT 2
105 #define DEBUG_ENTRY_EXPLICIT_BKPT 3
106 #define DEBUG_ENTRY_EDBGRQ 4
107 #define DEBUG_ENTRY_VECTOR_CATCH 5
108 #define DEBUG_ENTRY_DATA_ABORT 6
109 #define DEBUG_ENTRY_INSTRUCTION_ABORT 7
110 #define DEBUG_ENTRY_SYNC_WATCHPOINT (0xA)
111
112 /* Vector Catch Register */
113 #define VCR_FIQ 7
114 #define VCR_IRQ 6
115 #define VCR_DATA 4
116 #define VCR_PREFETCH 3
117 #define VCR_SWI 2
118 #define VCR_UNDEF 1
119 #define VCR_RESET 0
120
121 #ifndef __ASSEMBLER__
getVCR(void)122 static inline uint32_t getVCR(void)
123 {
124 uint32_t x;
125
126 asm volatile("mrc p14, 0, %0, c0, c7, 0" : "=r"(x));
127
128 return x;
129 }
130
setVCR(uint32_t x)131 static inline void setVCR(uint32_t x)
132 {
133 asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r"(x));
134 }
135
136 #endif /* !__ASSEMBLER__ */
137
138 /* Breakpoint Control Registers */
139 #define BCR_MEANING 21
140 #define BCR_ENABLE_LINKING 20
141 #define BCR_LINKED_BRP 16
142 #define BCR_BYTE_SELECT 5
143 #define BCR_SUPERVISOR 1
144 #define BCR_ENABLE 0
145
146 #define FSR_SHORTDESC_STATUS_DEBUG_EVENT (0x2)
147 #define FSR_LONGDESC_STATUS_DEBUG_EVENT (0x22)
148 #define FSR_LPAE_SHIFT (9)
149 #define FSR_STATUS_BIT4_SHIFT (10)
150
151 #ifndef __ASSEMBLER__
152
153 #ifdef CONFIG_HARDWARE_DEBUG_API
154 /** Determines whether or not a Prefetch Abort or Data Abort was really a debug
155 * exception.
156 *
157 * Examines the FSR bits, looking for the "Debug event" value, and also examines
158 * DBGDSCR looking for the "Async watchpoint abort" value, since async
159 * watchpoints behave differently.
160 */
161 bool_t isDebugFault(word_t hsr_or_fsr);
162
163 /** Determines and carries out what needs to be done for a debug exception.
164 *
165 * This could be handling a single-stepping exception, or a breakpoint or
166 * watchpoint.
167 */
168 seL4_Fault_t handleUserLevelDebugException(word_t fault_vaddr);
169
170 /** These next two functions are part of some state flags.
171 *
172 * A bitfield of all currently enabled breakpoints for a thread is kept in that
173 * thread's TCB. These two functions here set and unset the bits in that
174 * bitfield.
175 */
setBreakpointUsedFlag(tcb_t * t,uint16_t bp_num)176 static inline void setBreakpointUsedFlag(tcb_t *t, uint16_t bp_num)
177 {
178 if (t != NULL) {
179 t->tcbArch.tcbContext.breakpointState.used_breakpoints_bf |= BIT(bp_num);
180 }
181 }
182
unsetBreakpointUsedFlag(tcb_t * t,uint16_t bp_num)183 static inline void unsetBreakpointUsedFlag(tcb_t *t, uint16_t bp_num)
184 {
185 if (t != NULL) {
186 t->tcbArch.tcbContext.breakpointState.used_breakpoints_bf &= ~BIT(bp_num);
187 }
188 }
189
190 #endif /* CONFIG_HARDWARE_DEBUG_API */
191
192 #endif /* !__ASSEMBLER__ */
193
194 #endif /* defined(CONFIG_DEBUG_BUILD) || defined (CONFIG_HARDWARE_DEBUG_API) */
195