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