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
29void debug_init(void) VISIBLE;
30
31typedef void (*break_handler_t)(user_context_t *context);
32
33void software_breakpoint(uint32_t va, user_context_t *context) VISIBLE;
34void breakpoint_multiplexer(uint32_t va, user_context_t *context) VISIBLE;
35
36int set_breakpoint(uint32_t va, break_handler_t handler) VISIBLE;
37void clear_breakpoint(uint32_t va) VISIBLE;
38
39enum 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};
48typedef uint32_t vector_t;
49
50typedef void (*catch_handler_t)(user_context_t *context, vector_t vector);
51
52void set_catch_handler(catch_handler_t handler) VISIBLE;
53void catch_vector(vector_t vector) VISIBLE;
54void 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__
72static 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). */
86static 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__
122static 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
131static 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 */
161bool_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 */
168seL4_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 */
176static 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
183static 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