summaryrefslogtreecommitdiffstats
path: root/target/riscv/debug.h
blob: a1226b4d29242c389e4c110ad511af3004e83e3d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 * QEMU RISC-V Native Debug Support
 *
 * Copyright (c) 2022 Wind River Systems, Inc.
 *
 * Author:
 *   Bin Meng <bin.meng@windriver.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2 or later, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef RISCV_DEBUG_H
#define RISCV_DEBUG_H

#define RV_MAX_TRIGGERS         2

/* register index of tdata CSRs */
enum {
    TDATA1 = 0,
    TDATA2,
    TDATA3,
    TDATA_NUM
};

typedef enum {
    TRIGGER_TYPE_NO_EXIST = 0,      /* trigger does not exist */
    TRIGGER_TYPE_AD_MATCH = 2,      /* address/data match trigger */
    TRIGGER_TYPE_INST_CNT = 3,      /* instruction count trigger */
    TRIGGER_TYPE_INT = 4,           /* interrupt trigger */
    TRIGGER_TYPE_EXCP = 5,          /* exception trigger */
    TRIGGER_TYPE_AD_MATCH6 = 6,     /* new address/data match trigger */
    TRIGGER_TYPE_EXT_SRC = 7,       /* external source trigger */
    TRIGGER_TYPE_UNAVAIL = 15,      /* trigger exists, but unavailable */
    TRIGGER_TYPE_NUM
} trigger_type_t;

/* actions */
typedef enum {
    DBG_ACTION_NONE = -1,           /* sentinel value */
    DBG_ACTION_BP = 0,
    DBG_ACTION_DBG_MODE,
    DBG_ACTION_TRACE0,
    DBG_ACTION_TRACE1,
    DBG_ACTION_TRACE2,
    DBG_ACTION_TRACE3,
    DBG_ACTION_EXT_DBG0 = 8,
    DBG_ACTION_EXT_DBG1
} trigger_action_t;

/* tdata1 field masks */

#define RV32_TYPE(t)    ((uint32_t)(t) << 28)
#define RV32_TYPE_MASK  (0xf << 28)
#define RV32_DMODE      BIT(27)
#define RV32_DATA_MASK  0x7ffffff
#define RV64_TYPE(t)    ((uint64_t)(t) << 60)
#define RV64_TYPE_MASK  (0xfULL << 60)
#define RV64_DMODE      BIT_ULL(59)
#define RV64_DATA_MASK  0x7ffffffffffffff

/* mcontrol field masks */

#define TYPE2_LOAD      BIT(0)
#define TYPE2_STORE     BIT(1)
#define TYPE2_EXEC      BIT(2)
#define TYPE2_U         BIT(3)
#define TYPE2_S         BIT(4)
#define TYPE2_M         BIT(6)
#define TYPE2_MATCH     (0xf << 7)
#define TYPE2_CHAIN     BIT(11)
#define TYPE2_ACTION    (0xf << 12)
#define TYPE2_SIZELO    (0x3 << 16)
#define TYPE2_TIMING    BIT(18)
#define TYPE2_SELECT    BIT(19)
#define TYPE2_HIT       BIT(20)
#define TYPE2_SIZEHI    (0x3 << 21) /* RV64 only */

/* mcontrol6 field masks */

#define TYPE6_LOAD      BIT(0)
#define TYPE6_STORE     BIT(1)
#define TYPE6_EXEC      BIT(2)
#define TYPE6_U         BIT(3)
#define TYPE6_S         BIT(4)
#define TYPE6_M         BIT(6)
#define TYPE6_MATCH     (0xf << 7)
#define TYPE6_CHAIN     BIT(11)
#define TYPE6_ACTION    (0xf << 12)
#define TYPE6_SIZE      (0xf << 16)
#define TYPE6_TIMING    BIT(20)
#define TYPE6_SELECT    BIT(21)
#define TYPE6_HIT       BIT(22)
#define TYPE6_VU        BIT(23)
#define TYPE6_VS        BIT(24)

/* access size */
enum {
    SIZE_ANY = 0,
    SIZE_1B,
    SIZE_2B,
    SIZE_4B,
    SIZE_6B,
    SIZE_8B,
    SIZE_10B,
    SIZE_12B,
    SIZE_14B,
    SIZE_16B,
    SIZE_NUM = 16
};

bool tdata_available(CPURISCVState *env, int tdata_index);

target_ulong tselect_csr_read(CPURISCVState *env);
void tselect_csr_write(CPURISCVState *env, target_ulong val);

target_ulong tdata_csr_read(CPURISCVState *env, int tdata_index);
void tdata_csr_write(CPURISCVState *env, int tdata_index, target_ulong val);

target_ulong tinfo_csr_read(CPURISCVState *env);

void riscv_cpu_debug_excp_handler(CPUState *cs);
bool riscv_cpu_debug_check_breakpoint(CPUState *cs);
bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp);

void riscv_trigger_init(CPURISCVState *env);

#endif /* RISCV_DEBUG_H */