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