1f81e4fa4SJesse Taube // SPDX-License-Identifier: GPL-2.0-only
2f81e4fa4SJesse Taube /*
3f81e4fa4SJesse Taube * SBI DBTR testsuite
4f81e4fa4SJesse Taube *
5f81e4fa4SJesse Taube * Copyright (C) 2025, Rivos Inc., Jesse Taube <jesse@rivosinc.com>
6f81e4fa4SJesse Taube */
7f81e4fa4SJesse Taube
8f81e4fa4SJesse Taube #include <libcflat.h>
9f81e4fa4SJesse Taube #include <bitops.h>
10f81e4fa4SJesse Taube
11f81e4fa4SJesse Taube #include <asm/io.h>
12f81e4fa4SJesse Taube #include <asm/processor.h>
13f81e4fa4SJesse Taube
14f81e4fa4SJesse Taube #include "sbi-tests.h"
15f81e4fa4SJesse Taube
16f81e4fa4SJesse Taube #define RV_MAX_TRIGGERS 32
17f81e4fa4SJesse Taube
18f81e4fa4SJesse Taube #define SBI_DBTR_TRIG_STATE_MAPPED BIT(0)
19f81e4fa4SJesse Taube #define SBI_DBTR_TRIG_STATE_U BIT(1)
20f81e4fa4SJesse Taube #define SBI_DBTR_TRIG_STATE_S BIT(2)
21f81e4fa4SJesse Taube #define SBI_DBTR_TRIG_STATE_VU BIT(3)
22f81e4fa4SJesse Taube #define SBI_DBTR_TRIG_STATE_VS BIT(4)
23f81e4fa4SJesse Taube #define SBI_DBTR_TRIG_STATE_HAVE_HW_TRIG BIT(5)
24f81e4fa4SJesse Taube #define SBI_DBTR_TRIG_STATE_RESERVED GENMASK(7, 6)
25f81e4fa4SJesse Taube
26f81e4fa4SJesse Taube #define SBI_DBTR_TRIG_STATE_HW_TRIG_IDX_SHIFT 8
27f81e4fa4SJesse Taube #define SBI_DBTR_TRIG_STATE_HW_TRIG_IDX(trig_state) (trig_state >> SBI_DBTR_TRIG_STATE_HW_TRIG_IDX_SHIFT)
28f81e4fa4SJesse Taube
29f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_TYPE_SHIFT (__riscv_xlen - 4)
30f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_DMODE BIT_UL(__riscv_xlen - 5)
31f81e4fa4SJesse Taube
32f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL6_LOAD BIT(0)
33f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL6_STORE BIT(1)
34f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL6_EXECUTE BIT(2)
35f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL6_U BIT(3)
36f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL6_S BIT(4)
37f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL6_M BIT(6)
38f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL6_SIZE_SHIFT 16
39f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL6_SIZE_MASK 0x7
40f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL6_SELECT BIT(21)
41f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL6_VU BIT(23)
42f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL6_VS BIT(24)
43f81e4fa4SJesse Taube
44f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL_LOAD BIT(0)
45f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL_STORE BIT(1)
46f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL_EXECUTE BIT(2)
47f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL_U BIT(3)
48f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL_S BIT(4)
49f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL_M BIT(6)
50f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL_SIZELO_SHIFT 16
51f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL_SIZELO_MASK 0x3
52f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL_SELECT BIT(19)
53f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL_SIZEHI_SHIFT 21
54f81e4fa4SJesse Taube #define SBI_DBTR_TDATA1_MCONTROL_SIZEHI_MASK 0x3
55f81e4fa4SJesse Taube
56f81e4fa4SJesse Taube enum McontrolType {
57f81e4fa4SJesse Taube SBI_DBTR_TDATA1_TYPE_NONE = (0UL << SBI_DBTR_TDATA1_TYPE_SHIFT),
58f81e4fa4SJesse Taube SBI_DBTR_TDATA1_TYPE_LEGACY = (1UL << SBI_DBTR_TDATA1_TYPE_SHIFT),
59f81e4fa4SJesse Taube SBI_DBTR_TDATA1_TYPE_MCONTROL = (2UL << SBI_DBTR_TDATA1_TYPE_SHIFT),
60f81e4fa4SJesse Taube SBI_DBTR_TDATA1_TYPE_ICOUNT = (3UL << SBI_DBTR_TDATA1_TYPE_SHIFT),
61f81e4fa4SJesse Taube SBI_DBTR_TDATA1_TYPE_ITRIGGER = (4UL << SBI_DBTR_TDATA1_TYPE_SHIFT),
62f81e4fa4SJesse Taube SBI_DBTR_TDATA1_TYPE_ETRIGGER = (5UL << SBI_DBTR_TDATA1_TYPE_SHIFT),
63f81e4fa4SJesse Taube SBI_DBTR_TDATA1_TYPE_MCONTROL6 = (6UL << SBI_DBTR_TDATA1_TYPE_SHIFT),
64f81e4fa4SJesse Taube SBI_DBTR_TDATA1_TYPE_TMEXTTRIGGER = (7UL << SBI_DBTR_TDATA1_TYPE_SHIFT),
65f81e4fa4SJesse Taube SBI_DBTR_TDATA1_TYPE_RESERVED0 = (8UL << SBI_DBTR_TDATA1_TYPE_SHIFT),
66f81e4fa4SJesse Taube SBI_DBTR_TDATA1_TYPE_RESERVED1 = (9UL << SBI_DBTR_TDATA1_TYPE_SHIFT),
67f81e4fa4SJesse Taube SBI_DBTR_TDATA1_TYPE_RESERVED2 = (10UL << SBI_DBTR_TDATA1_TYPE_SHIFT),
68f81e4fa4SJesse Taube SBI_DBTR_TDATA1_TYPE_RESERVED3 = (11UL << SBI_DBTR_TDATA1_TYPE_SHIFT),
69f81e4fa4SJesse Taube SBI_DBTR_TDATA1_TYPE_CUSTOM0 = (12UL << SBI_DBTR_TDATA1_TYPE_SHIFT),
70f81e4fa4SJesse Taube SBI_DBTR_TDATA1_TYPE_CUSTOM1 = (13UL << SBI_DBTR_TDATA1_TYPE_SHIFT),
71f81e4fa4SJesse Taube SBI_DBTR_TDATA1_TYPE_CUSTOM2 = (14UL << SBI_DBTR_TDATA1_TYPE_SHIFT),
72f81e4fa4SJesse Taube SBI_DBTR_TDATA1_TYPE_DISABLED = (15UL << SBI_DBTR_TDATA1_TYPE_SHIFT),
73f81e4fa4SJesse Taube };
74f81e4fa4SJesse Taube
75f81e4fa4SJesse Taube enum Tdata1Size {
76f81e4fa4SJesse Taube SIZE_ANY = 0,
77f81e4fa4SJesse Taube SIZE_8BIT,
78f81e4fa4SJesse Taube SIZE_16BIT,
79f81e4fa4SJesse Taube SIZE_32BIT,
80f81e4fa4SJesse Taube SIZE_48BIT,
81f81e4fa4SJesse Taube SIZE_64BIT,
82f81e4fa4SJesse Taube };
83f81e4fa4SJesse Taube
84f81e4fa4SJesse Taube enum Tdata1Value {
85f81e4fa4SJesse Taube VALUE_NONE = 0,
86f81e4fa4SJesse Taube VALUE_LOAD = BIT(0),
87f81e4fa4SJesse Taube VALUE_STORE = BIT(1),
88f81e4fa4SJesse Taube VALUE_EXECUTE = BIT(2),
89f81e4fa4SJesse Taube };
90f81e4fa4SJesse Taube
91f81e4fa4SJesse Taube enum Tdata1Mode {
92f81e4fa4SJesse Taube MODE_NONE = 0,
93f81e4fa4SJesse Taube MODE_M = BIT(0),
94f81e4fa4SJesse Taube MODE_U = BIT(1),
95f81e4fa4SJesse Taube MODE_S = BIT(2),
96f81e4fa4SJesse Taube MODE_VU = BIT(3),
97f81e4fa4SJesse Taube MODE_VS = BIT(4),
98f81e4fa4SJesse Taube };
99f81e4fa4SJesse Taube
100f81e4fa4SJesse Taube enum sbi_ext_dbtr_fid {
101f81e4fa4SJesse Taube SBI_EXT_DBTR_NUM_TRIGGERS = 0,
102f81e4fa4SJesse Taube SBI_EXT_DBTR_SETUP_SHMEM,
103f81e4fa4SJesse Taube SBI_EXT_DBTR_TRIGGER_READ,
104f81e4fa4SJesse Taube SBI_EXT_DBTR_TRIGGER_INSTALL,
105f81e4fa4SJesse Taube SBI_EXT_DBTR_TRIGGER_UPDATE,
106f81e4fa4SJesse Taube SBI_EXT_DBTR_TRIGGER_UNINSTALL,
107f81e4fa4SJesse Taube SBI_EXT_DBTR_TRIGGER_ENABLE,
108f81e4fa4SJesse Taube SBI_EXT_DBTR_TRIGGER_DISABLE,
109f81e4fa4SJesse Taube };
110f81e4fa4SJesse Taube
111f81e4fa4SJesse Taube struct sbi_dbtr_data_msg {
112f81e4fa4SJesse Taube unsigned long tstate;
113f81e4fa4SJesse Taube unsigned long tdata1;
114f81e4fa4SJesse Taube unsigned long tdata2;
115f81e4fa4SJesse Taube unsigned long tdata3;
116f81e4fa4SJesse Taube };
117f81e4fa4SJesse Taube
118f81e4fa4SJesse Taube struct sbi_dbtr_id_msg {
119f81e4fa4SJesse Taube unsigned long idx;
120f81e4fa4SJesse Taube };
121f81e4fa4SJesse Taube
122f81e4fa4SJesse Taube /* SBI shared mem messages layout */
123f81e4fa4SJesse Taube struct sbi_dbtr_shmem_entry {
124f81e4fa4SJesse Taube union {
125f81e4fa4SJesse Taube struct sbi_dbtr_data_msg data;
126f81e4fa4SJesse Taube struct sbi_dbtr_id_msg id;
127f81e4fa4SJesse Taube };
128f81e4fa4SJesse Taube };
129f81e4fa4SJesse Taube
130f81e4fa4SJesse Taube static bool dbtr_handled;
131f81e4fa4SJesse Taube
132f81e4fa4SJesse Taube /* Expected to be leaf function as not to disrupt frame-pointer */
exec_call(void)133f81e4fa4SJesse Taube static __attribute__((naked)) void exec_call(void)
134f81e4fa4SJesse Taube {
135f81e4fa4SJesse Taube /* skip over nop when triggered instead of ret. */
136f81e4fa4SJesse Taube asm volatile (".option push\n"
137*1b7dc511SJesse Taube ".option norvc\n"
138f81e4fa4SJesse Taube "nop\n"
139f81e4fa4SJesse Taube "ret\n"
140f81e4fa4SJesse Taube ".option pop\n");
141f81e4fa4SJesse Taube }
142f81e4fa4SJesse Taube
dbtr_exception_handler(struct pt_regs * regs)143f81e4fa4SJesse Taube static void dbtr_exception_handler(struct pt_regs *regs)
144f81e4fa4SJesse Taube {
145f81e4fa4SJesse Taube dbtr_handled = true;
146f81e4fa4SJesse Taube
147f81e4fa4SJesse Taube /* Reading *epc may cause a fault, skip over nop */
148f81e4fa4SJesse Taube if ((void *)regs->epc == exec_call) {
149f81e4fa4SJesse Taube regs->epc += 4;
150f81e4fa4SJesse Taube return;
151f81e4fa4SJesse Taube }
152f81e4fa4SJesse Taube
153f81e4fa4SJesse Taube /* WARNING: Skips over the trapped intruction */
154f81e4fa4SJesse Taube regs->epc += RV_INSN_LEN(readw((void *)regs->epc));
155f81e4fa4SJesse Taube }
156f81e4fa4SJesse Taube
do_store(void * tdata2)157f81e4fa4SJesse Taube static bool do_store(void *tdata2)
158f81e4fa4SJesse Taube {
159f81e4fa4SJesse Taube bool ret;
160f81e4fa4SJesse Taube
161f81e4fa4SJesse Taube writel(0, tdata2);
162f81e4fa4SJesse Taube
163f81e4fa4SJesse Taube ret = dbtr_handled;
164f81e4fa4SJesse Taube dbtr_handled = false;
165f81e4fa4SJesse Taube
166f81e4fa4SJesse Taube return ret;
167f81e4fa4SJesse Taube }
168f81e4fa4SJesse Taube
do_load(void * tdata2)169f81e4fa4SJesse Taube static bool do_load(void *tdata2)
170f81e4fa4SJesse Taube {
171f81e4fa4SJesse Taube bool ret;
172f81e4fa4SJesse Taube
173f81e4fa4SJesse Taube readl(tdata2);
174f81e4fa4SJesse Taube
175f81e4fa4SJesse Taube ret = dbtr_handled;
176f81e4fa4SJesse Taube dbtr_handled = false;
177f81e4fa4SJesse Taube
178f81e4fa4SJesse Taube return ret;
179f81e4fa4SJesse Taube }
180f81e4fa4SJesse Taube
do_exec(void)181f81e4fa4SJesse Taube static bool do_exec(void)
182f81e4fa4SJesse Taube {
183f81e4fa4SJesse Taube bool ret;
184f81e4fa4SJesse Taube
185f81e4fa4SJesse Taube exec_call();
186f81e4fa4SJesse Taube
187f81e4fa4SJesse Taube ret = dbtr_handled;
188f81e4fa4SJesse Taube dbtr_handled = false;
189f81e4fa4SJesse Taube
190f81e4fa4SJesse Taube return ret;
191f81e4fa4SJesse Taube }
192f81e4fa4SJesse Taube
mcontrol_size(enum Tdata1Size mode)193f81e4fa4SJesse Taube static unsigned long mcontrol_size(enum Tdata1Size mode)
194f81e4fa4SJesse Taube {
195f81e4fa4SJesse Taube unsigned long ret = 0;
196f81e4fa4SJesse Taube
197f81e4fa4SJesse Taube ret |= ((mode >> 2) & SBI_DBTR_TDATA1_MCONTROL_SIZEHI_MASK)
198f81e4fa4SJesse Taube << SBI_DBTR_TDATA1_MCONTROL_SIZEHI_SHIFT;
199f81e4fa4SJesse Taube ret |= (mode & SBI_DBTR_TDATA1_MCONTROL_SIZELO_MASK)
200f81e4fa4SJesse Taube << SBI_DBTR_TDATA1_MCONTROL_SIZELO_SHIFT;
201f81e4fa4SJesse Taube
202f81e4fa4SJesse Taube return ret;
203f81e4fa4SJesse Taube }
204f81e4fa4SJesse Taube
mcontrol6_size(enum Tdata1Size mode)205f81e4fa4SJesse Taube static unsigned long mcontrol6_size(enum Tdata1Size mode)
206f81e4fa4SJesse Taube {
207f81e4fa4SJesse Taube return (mode & SBI_DBTR_TDATA1_MCONTROL6_SIZE_MASK)
208f81e4fa4SJesse Taube << SBI_DBTR_TDATA1_MCONTROL6_SIZE_SHIFT;
209f81e4fa4SJesse Taube }
210f81e4fa4SJesse Taube
gen_tdata1_mcontrol(enum Tdata1Mode mode,enum Tdata1Value value)211f81e4fa4SJesse Taube static unsigned long gen_tdata1_mcontrol(enum Tdata1Mode mode, enum Tdata1Value value)
212f81e4fa4SJesse Taube {
213f81e4fa4SJesse Taube unsigned long tdata1 = SBI_DBTR_TDATA1_TYPE_MCONTROL;
214f81e4fa4SJesse Taube
215f81e4fa4SJesse Taube if (value & VALUE_LOAD)
216f81e4fa4SJesse Taube tdata1 |= SBI_DBTR_TDATA1_MCONTROL_LOAD;
217f81e4fa4SJesse Taube
218f81e4fa4SJesse Taube if (value & VALUE_STORE)
219f81e4fa4SJesse Taube tdata1 |= SBI_DBTR_TDATA1_MCONTROL_STORE;
220f81e4fa4SJesse Taube
221f81e4fa4SJesse Taube if (value & VALUE_EXECUTE)
222f81e4fa4SJesse Taube tdata1 |= SBI_DBTR_TDATA1_MCONTROL_EXECUTE;
223f81e4fa4SJesse Taube
224f81e4fa4SJesse Taube if (mode & MODE_M)
225f81e4fa4SJesse Taube tdata1 |= SBI_DBTR_TDATA1_MCONTROL_M;
226f81e4fa4SJesse Taube
227f81e4fa4SJesse Taube if (mode & MODE_U)
228f81e4fa4SJesse Taube tdata1 |= SBI_DBTR_TDATA1_MCONTROL_U;
229f81e4fa4SJesse Taube
230f81e4fa4SJesse Taube if (mode & MODE_S)
231f81e4fa4SJesse Taube tdata1 |= SBI_DBTR_TDATA1_MCONTROL_S;
232f81e4fa4SJesse Taube
233f81e4fa4SJesse Taube return tdata1;
234f81e4fa4SJesse Taube }
235f81e4fa4SJesse Taube
gen_tdata1_mcontrol6(enum Tdata1Mode mode,enum Tdata1Value value)236f81e4fa4SJesse Taube static unsigned long gen_tdata1_mcontrol6(enum Tdata1Mode mode, enum Tdata1Value value)
237f81e4fa4SJesse Taube {
238f81e4fa4SJesse Taube unsigned long tdata1 = SBI_DBTR_TDATA1_TYPE_MCONTROL6;
239f81e4fa4SJesse Taube
240f81e4fa4SJesse Taube if (value & VALUE_LOAD)
241f81e4fa4SJesse Taube tdata1 |= SBI_DBTR_TDATA1_MCONTROL6_LOAD;
242f81e4fa4SJesse Taube
243f81e4fa4SJesse Taube if (value & VALUE_STORE)
244f81e4fa4SJesse Taube tdata1 |= SBI_DBTR_TDATA1_MCONTROL6_STORE;
245f81e4fa4SJesse Taube
246f81e4fa4SJesse Taube if (value & VALUE_EXECUTE)
247f81e4fa4SJesse Taube tdata1 |= SBI_DBTR_TDATA1_MCONTROL6_EXECUTE;
248f81e4fa4SJesse Taube
249f81e4fa4SJesse Taube if (mode & MODE_M)
250f81e4fa4SJesse Taube tdata1 |= SBI_DBTR_TDATA1_MCONTROL6_M;
251f81e4fa4SJesse Taube
252f81e4fa4SJesse Taube if (mode & MODE_U)
253f81e4fa4SJesse Taube tdata1 |= SBI_DBTR_TDATA1_MCONTROL6_U;
254f81e4fa4SJesse Taube
255f81e4fa4SJesse Taube if (mode & MODE_S)
256f81e4fa4SJesse Taube tdata1 |= SBI_DBTR_TDATA1_MCONTROL6_S;
257f81e4fa4SJesse Taube
258f81e4fa4SJesse Taube if (mode & MODE_VU)
259f81e4fa4SJesse Taube tdata1 |= SBI_DBTR_TDATA1_MCONTROL6_VU;
260f81e4fa4SJesse Taube
261f81e4fa4SJesse Taube if (mode & MODE_VS)
262f81e4fa4SJesse Taube tdata1 |= SBI_DBTR_TDATA1_MCONTROL6_VS;
263f81e4fa4SJesse Taube
264f81e4fa4SJesse Taube return tdata1;
265f81e4fa4SJesse Taube }
266f81e4fa4SJesse Taube
gen_tdata1(enum McontrolType type,enum Tdata1Value value,enum Tdata1Mode mode)267f81e4fa4SJesse Taube static unsigned long gen_tdata1(enum McontrolType type, enum Tdata1Value value, enum Tdata1Mode mode)
268f81e4fa4SJesse Taube {
269f81e4fa4SJesse Taube switch (type) {
270f81e4fa4SJesse Taube case SBI_DBTR_TDATA1_TYPE_MCONTROL:
271f81e4fa4SJesse Taube return gen_tdata1_mcontrol(mode, value) | mcontrol_size(SIZE_32BIT);
272f81e4fa4SJesse Taube case SBI_DBTR_TDATA1_TYPE_MCONTROL6:
273f81e4fa4SJesse Taube return gen_tdata1_mcontrol6(mode, value) | mcontrol6_size(SIZE_32BIT);
274f81e4fa4SJesse Taube default:
275f81e4fa4SJesse Taube assert_msg(false, "Invalid mcontrol type: %lu", (unsigned long)type);
276f81e4fa4SJesse Taube }
277f81e4fa4SJesse Taube }
278f81e4fa4SJesse Taube
sbi_debug_num_triggers(unsigned long trig_tdata1)279f81e4fa4SJesse Taube static struct sbiret sbi_debug_num_triggers(unsigned long trig_tdata1)
280f81e4fa4SJesse Taube {
281f81e4fa4SJesse Taube return sbi_ecall(SBI_EXT_DBTR, SBI_EXT_DBTR_NUM_TRIGGERS, trig_tdata1, 0, 0, 0, 0, 0);
282f81e4fa4SJesse Taube }
283f81e4fa4SJesse Taube
sbi_debug_set_shmem_raw(unsigned long shmem_phys_lo,unsigned long shmem_phys_hi,unsigned long flags)284f81e4fa4SJesse Taube static struct sbiret sbi_debug_set_shmem_raw(unsigned long shmem_phys_lo,
285f81e4fa4SJesse Taube unsigned long shmem_phys_hi,
286f81e4fa4SJesse Taube unsigned long flags)
287f81e4fa4SJesse Taube {
288f81e4fa4SJesse Taube return sbi_ecall(SBI_EXT_DBTR, SBI_EXT_DBTR_SETUP_SHMEM, shmem_phys_lo,
289f81e4fa4SJesse Taube shmem_phys_hi, flags, 0, 0, 0);
290f81e4fa4SJesse Taube }
291f81e4fa4SJesse Taube
sbi_debug_set_shmem(void * shmem)292f81e4fa4SJesse Taube static struct sbiret sbi_debug_set_shmem(void *shmem)
293f81e4fa4SJesse Taube {
294f81e4fa4SJesse Taube unsigned long base_addr_lo, base_addr_hi;
295f81e4fa4SJesse Taube
296f81e4fa4SJesse Taube split_phys_addr(virt_to_phys(shmem), &base_addr_hi, &base_addr_lo);
297f81e4fa4SJesse Taube return sbi_debug_set_shmem_raw(base_addr_lo, base_addr_hi, 0);
298f81e4fa4SJesse Taube }
299f81e4fa4SJesse Taube
sbi_debug_read_triggers(unsigned long trig_idx_base,unsigned long trig_count)300f81e4fa4SJesse Taube static struct sbiret sbi_debug_read_triggers(unsigned long trig_idx_base,
301f81e4fa4SJesse Taube unsigned long trig_count)
302f81e4fa4SJesse Taube {
303f81e4fa4SJesse Taube return sbi_ecall(SBI_EXT_DBTR, SBI_EXT_DBTR_TRIGGER_READ, trig_idx_base,
304f81e4fa4SJesse Taube trig_count, 0, 0, 0, 0);
305f81e4fa4SJesse Taube }
306f81e4fa4SJesse Taube
sbi_debug_install_triggers(unsigned long trig_count)307f81e4fa4SJesse Taube static struct sbiret sbi_debug_install_triggers(unsigned long trig_count)
308f81e4fa4SJesse Taube {
309f81e4fa4SJesse Taube return sbi_ecall(SBI_EXT_DBTR, SBI_EXT_DBTR_TRIGGER_INSTALL, trig_count, 0, 0, 0, 0, 0);
310f81e4fa4SJesse Taube }
311f81e4fa4SJesse Taube
sbi_debug_update_triggers(unsigned long trig_count)312f81e4fa4SJesse Taube static struct sbiret sbi_debug_update_triggers(unsigned long trig_count)
313f81e4fa4SJesse Taube {
314f81e4fa4SJesse Taube return sbi_ecall(SBI_EXT_DBTR, SBI_EXT_DBTR_TRIGGER_UPDATE, trig_count, 0, 0, 0, 0, 0);
315f81e4fa4SJesse Taube }
316f81e4fa4SJesse Taube
sbi_debug_uninstall_triggers(unsigned long trig_idx_base,unsigned long trig_idx_mask)317f81e4fa4SJesse Taube static struct sbiret sbi_debug_uninstall_triggers(unsigned long trig_idx_base,
318f81e4fa4SJesse Taube unsigned long trig_idx_mask)
319f81e4fa4SJesse Taube {
320f81e4fa4SJesse Taube return sbi_ecall(SBI_EXT_DBTR, SBI_EXT_DBTR_TRIGGER_UNINSTALL, trig_idx_base,
321f81e4fa4SJesse Taube trig_idx_mask, 0, 0, 0, 0);
322f81e4fa4SJesse Taube }
323f81e4fa4SJesse Taube
sbi_debug_enable_triggers(unsigned long trig_idx_base,unsigned long trig_idx_mask)324f81e4fa4SJesse Taube static struct sbiret sbi_debug_enable_triggers(unsigned long trig_idx_base,
325f81e4fa4SJesse Taube unsigned long trig_idx_mask)
326f81e4fa4SJesse Taube {
327f81e4fa4SJesse Taube return sbi_ecall(SBI_EXT_DBTR, SBI_EXT_DBTR_TRIGGER_ENABLE, trig_idx_base,
328f81e4fa4SJesse Taube trig_idx_mask, 0, 0, 0, 0);
329f81e4fa4SJesse Taube }
330f81e4fa4SJesse Taube
sbi_debug_disable_triggers(unsigned long trig_idx_base,unsigned long trig_idx_mask)331f81e4fa4SJesse Taube static struct sbiret sbi_debug_disable_triggers(unsigned long trig_idx_base,
332f81e4fa4SJesse Taube unsigned long trig_idx_mask)
333f81e4fa4SJesse Taube {
334f81e4fa4SJesse Taube return sbi_ecall(SBI_EXT_DBTR, SBI_EXT_DBTR_TRIGGER_DISABLE, trig_idx_base,
335f81e4fa4SJesse Taube trig_idx_mask, 0, 0, 0, 0);
336f81e4fa4SJesse Taube }
337f81e4fa4SJesse Taube
dbtr_install_trigger(struct sbi_dbtr_shmem_entry * shmem,void * trigger,unsigned long control)338f81e4fa4SJesse Taube static bool dbtr_install_trigger(struct sbi_dbtr_shmem_entry *shmem, void *trigger,
339f81e4fa4SJesse Taube unsigned long control)
340f81e4fa4SJesse Taube {
341f81e4fa4SJesse Taube struct sbiret sbi_ret;
342f81e4fa4SJesse Taube bool ret;
343f81e4fa4SJesse Taube
344f81e4fa4SJesse Taube shmem->data.tdata1 = control;
345f81e4fa4SJesse Taube shmem->data.tdata2 = (unsigned long)trigger;
346f81e4fa4SJesse Taube
347f81e4fa4SJesse Taube sbi_ret = sbi_debug_install_triggers(1);
348f81e4fa4SJesse Taube ret = sbiret_report_error(&sbi_ret, SBI_SUCCESS, "sbi_debug_install_triggers");
349f81e4fa4SJesse Taube if (ret)
350f81e4fa4SJesse Taube install_exception_handler(EXC_BREAKPOINT, dbtr_exception_handler);
351f81e4fa4SJesse Taube
352f81e4fa4SJesse Taube return ret;
353f81e4fa4SJesse Taube }
354f81e4fa4SJesse Taube
dbtr_uninstall_trigger(void)355f81e4fa4SJesse Taube static bool dbtr_uninstall_trigger(void)
356f81e4fa4SJesse Taube {
357f81e4fa4SJesse Taube struct sbiret ret;
358f81e4fa4SJesse Taube
359f81e4fa4SJesse Taube install_exception_handler(EXC_BREAKPOINT, NULL);
360f81e4fa4SJesse Taube
361f81e4fa4SJesse Taube ret = sbi_debug_uninstall_triggers(0, 1);
362f81e4fa4SJesse Taube return sbiret_report_error(&ret, SBI_SUCCESS, "sbi_debug_uninstall_triggers");
363f81e4fa4SJesse Taube }
364f81e4fa4SJesse Taube
dbtr_test_num_triggers(void)365f81e4fa4SJesse Taube static unsigned long dbtr_test_num_triggers(void)
366f81e4fa4SJesse Taube {
367f81e4fa4SJesse Taube struct sbiret ret;
368f81e4fa4SJesse Taube unsigned long tdata1 = 0;
369f81e4fa4SJesse Taube /* sbi_debug_num_triggers will return trig_max in sbiret.value when trig_tdata1 == 0 */
370f81e4fa4SJesse Taube
371f81e4fa4SJesse Taube report_prefix_push("available triggers");
372f81e4fa4SJesse Taube
373f81e4fa4SJesse Taube /* should be at least one trigger. */
374f81e4fa4SJesse Taube ret = sbi_debug_num_triggers(tdata1);
375f81e4fa4SJesse Taube sbiret_report_error(&ret, SBI_SUCCESS, "sbi_debug_num_triggers");
376f81e4fa4SJesse Taube
377f81e4fa4SJesse Taube if (ret.value == 0) {
378f81e4fa4SJesse Taube report_fail("Returned 0 triggers available");
379f81e4fa4SJesse Taube } else {
380f81e4fa4SJesse Taube report_pass("Returned triggers available");
381f81e4fa4SJesse Taube report_info("Returned %lu triggers available", ret.value);
382f81e4fa4SJesse Taube }
383f81e4fa4SJesse Taube
384f81e4fa4SJesse Taube report_prefix_pop();
385f81e4fa4SJesse Taube return ret.value;
386f81e4fa4SJesse Taube }
387f81e4fa4SJesse Taube
dbtr_test_type(unsigned long * num_trig)388f81e4fa4SJesse Taube static enum McontrolType dbtr_test_type(unsigned long *num_trig)
389f81e4fa4SJesse Taube {
390f81e4fa4SJesse Taube struct sbiret ret;
391f81e4fa4SJesse Taube unsigned long tdata1 = SBI_DBTR_TDATA1_TYPE_MCONTROL6;
392f81e4fa4SJesse Taube
393f81e4fa4SJesse Taube report_prefix_push("test type");
394f81e4fa4SJesse Taube report_prefix_push("sbi_debug_num_triggers");
395f81e4fa4SJesse Taube
396f81e4fa4SJesse Taube ret = sbi_debug_num_triggers(tdata1);
397f81e4fa4SJesse Taube sbiret_report_error(&ret, SBI_SUCCESS, "mcontrol6");
398f81e4fa4SJesse Taube *num_trig = ret.value;
399f81e4fa4SJesse Taube if (ret.value > 0) {
400f81e4fa4SJesse Taube report_pass("Returned mcontrol6 triggers available");
401f81e4fa4SJesse Taube report_info("Returned %lu mcontrol6 triggers available",
402f81e4fa4SJesse Taube ret.value);
403f81e4fa4SJesse Taube report_prefix_popn(2);
404f81e4fa4SJesse Taube return tdata1;
405f81e4fa4SJesse Taube }
406f81e4fa4SJesse Taube
407f81e4fa4SJesse Taube tdata1 = SBI_DBTR_TDATA1_TYPE_MCONTROL;
408f81e4fa4SJesse Taube
409f81e4fa4SJesse Taube ret = sbi_debug_num_triggers(tdata1);
410f81e4fa4SJesse Taube sbiret_report_error(&ret, SBI_SUCCESS, "mcontrol");
411f81e4fa4SJesse Taube *num_trig = ret.value;
412f81e4fa4SJesse Taube if (ret.value > 0) {
413f81e4fa4SJesse Taube report_pass("Returned mcontrol triggers available");
414f81e4fa4SJesse Taube report_info("Returned %lu mcontrol triggers available",
415f81e4fa4SJesse Taube ret.value);
416f81e4fa4SJesse Taube report_prefix_popn(2);
417f81e4fa4SJesse Taube return tdata1;
418f81e4fa4SJesse Taube }
419f81e4fa4SJesse Taube
420f81e4fa4SJesse Taube report_fail("Returned 0 mcontrol(6) triggers available");
421f81e4fa4SJesse Taube report_prefix_popn(2);
422f81e4fa4SJesse Taube
423f81e4fa4SJesse Taube return SBI_DBTR_TDATA1_TYPE_NONE;
424f81e4fa4SJesse Taube }
425f81e4fa4SJesse Taube
dbtr_test_store_install_uninstall(struct sbi_dbtr_shmem_entry * shmem,enum McontrolType type)426f81e4fa4SJesse Taube static struct sbiret dbtr_test_store_install_uninstall(struct sbi_dbtr_shmem_entry *shmem,
427f81e4fa4SJesse Taube enum McontrolType type)
428f81e4fa4SJesse Taube {
429f81e4fa4SJesse Taube static unsigned long test;
430f81e4fa4SJesse Taube struct sbiret ret;
431f81e4fa4SJesse Taube
432f81e4fa4SJesse Taube report_prefix_push("store trigger");
433f81e4fa4SJesse Taube
434f81e4fa4SJesse Taube shmem->data.tdata1 = gen_tdata1(type, VALUE_STORE, MODE_S);
435f81e4fa4SJesse Taube shmem->data.tdata2 = (unsigned long)&test;
436f81e4fa4SJesse Taube
437f81e4fa4SJesse Taube ret = sbi_debug_install_triggers(1);
438f81e4fa4SJesse Taube if (!sbiret_report_error(&ret, SBI_SUCCESS, "sbi_debug_install_triggers")) {
439f81e4fa4SJesse Taube report_prefix_pop();
440f81e4fa4SJesse Taube return ret;
441f81e4fa4SJesse Taube }
442f81e4fa4SJesse Taube
443f81e4fa4SJesse Taube install_exception_handler(EXC_BREAKPOINT, dbtr_exception_handler);
444f81e4fa4SJesse Taube
445f81e4fa4SJesse Taube report(do_store(&test), "triggered");
446f81e4fa4SJesse Taube
447f81e4fa4SJesse Taube if (do_load(&test))
448f81e4fa4SJesse Taube report_fail("triggered by load");
449f81e4fa4SJesse Taube
450f81e4fa4SJesse Taube ret = sbi_debug_uninstall_triggers(0, 1);
451f81e4fa4SJesse Taube sbiret_report_error(&ret, SBI_SUCCESS, "sbi_debug_uninstall_triggers");
452f81e4fa4SJesse Taube
453f81e4fa4SJesse Taube if (do_store(&test))
454f81e4fa4SJesse Taube report_fail("triggered after uninstall");
455f81e4fa4SJesse Taube
456f81e4fa4SJesse Taube install_exception_handler(EXC_BREAKPOINT, NULL);
457f81e4fa4SJesse Taube report_prefix_pop();
458f81e4fa4SJesse Taube
459f81e4fa4SJesse Taube return ret;
460f81e4fa4SJesse Taube }
461f81e4fa4SJesse Taube
dbtr_test_update(struct sbi_dbtr_shmem_entry * shmem,enum McontrolType type)462f81e4fa4SJesse Taube static void dbtr_test_update(struct sbi_dbtr_shmem_entry *shmem, enum McontrolType type)
463f81e4fa4SJesse Taube {
464f81e4fa4SJesse Taube static unsigned long test;
465f81e4fa4SJesse Taube struct sbiret ret;
466f81e4fa4SJesse Taube bool kfail;
467f81e4fa4SJesse Taube
468f81e4fa4SJesse Taube report_prefix_push("update trigger");
469f81e4fa4SJesse Taube
470f81e4fa4SJesse Taube if (!dbtr_install_trigger(shmem, NULL, gen_tdata1(type, VALUE_NONE, MODE_NONE))) {
471f81e4fa4SJesse Taube report_prefix_pop();
472f81e4fa4SJesse Taube return;
473f81e4fa4SJesse Taube }
474f81e4fa4SJesse Taube
475f81e4fa4SJesse Taube shmem->id.idx = 0;
476f81e4fa4SJesse Taube shmem->data.tdata1 = gen_tdata1(type, VALUE_STORE, MODE_S);
477f81e4fa4SJesse Taube shmem->data.tdata2 = (unsigned long)&test;
478f81e4fa4SJesse Taube
479f81e4fa4SJesse Taube ret = sbi_debug_update_triggers(1);
480f81e4fa4SJesse Taube sbiret_report_error(&ret, SBI_SUCCESS, "sbi_debug_update_triggers");
481f81e4fa4SJesse Taube
482f81e4fa4SJesse Taube /*
483f81e4fa4SJesse Taube * Known broken update_triggers.
484f81e4fa4SJesse Taube * https://lore.kernel.org/opensbi/aDdp1UeUh7GugeHp@ghost/T/#t
485f81e4fa4SJesse Taube */
486f81e4fa4SJesse Taube kfail = __sbi_get_imp_id() == SBI_IMPL_OPENSBI &&
487f81e4fa4SJesse Taube __sbi_get_imp_version() < sbi_impl_opensbi_mk_version(1, 7);
488f81e4fa4SJesse Taube report_kfail(kfail, do_store(&test), "triggered");
489f81e4fa4SJesse Taube
490f81e4fa4SJesse Taube dbtr_uninstall_trigger();
491f81e4fa4SJesse Taube report_prefix_pop();
492f81e4fa4SJesse Taube }
493f81e4fa4SJesse Taube
dbtr_test_load(struct sbi_dbtr_shmem_entry * shmem,enum McontrolType type)494f81e4fa4SJesse Taube static void dbtr_test_load(struct sbi_dbtr_shmem_entry *shmem, enum McontrolType type)
495f81e4fa4SJesse Taube {
496f81e4fa4SJesse Taube static unsigned long test;
497f81e4fa4SJesse Taube
498f81e4fa4SJesse Taube report_prefix_push("load trigger");
499f81e4fa4SJesse Taube if (!dbtr_install_trigger(shmem, &test, gen_tdata1(type, VALUE_LOAD, MODE_S))) {
500f81e4fa4SJesse Taube report_prefix_pop();
501f81e4fa4SJesse Taube return;
502f81e4fa4SJesse Taube }
503f81e4fa4SJesse Taube
504f81e4fa4SJesse Taube report(do_load(&test), "triggered");
505f81e4fa4SJesse Taube
506f81e4fa4SJesse Taube if (do_store(&test))
507f81e4fa4SJesse Taube report_fail("triggered by store");
508f81e4fa4SJesse Taube
509f81e4fa4SJesse Taube dbtr_uninstall_trigger();
510f81e4fa4SJesse Taube report_prefix_pop();
511f81e4fa4SJesse Taube }
512f81e4fa4SJesse Taube
dbtr_test_disable_enable(struct sbi_dbtr_shmem_entry * shmem,enum McontrolType type)513f81e4fa4SJesse Taube static void dbtr_test_disable_enable(struct sbi_dbtr_shmem_entry *shmem, enum McontrolType type)
514f81e4fa4SJesse Taube {
515f81e4fa4SJesse Taube static unsigned long test;
516f81e4fa4SJesse Taube struct sbiret ret;
517f81e4fa4SJesse Taube
518f81e4fa4SJesse Taube report_prefix_push("disable trigger");
519f81e4fa4SJesse Taube if (!dbtr_install_trigger(shmem, &test, gen_tdata1(type, VALUE_STORE, MODE_S))) {
520f81e4fa4SJesse Taube report_prefix_pop();
521f81e4fa4SJesse Taube return;
522f81e4fa4SJesse Taube }
523f81e4fa4SJesse Taube
524f81e4fa4SJesse Taube ret = sbi_debug_disable_triggers(0, 1);
525f81e4fa4SJesse Taube sbiret_report_error(&ret, SBI_SUCCESS, "sbi_debug_disable_triggers");
526f81e4fa4SJesse Taube
527f81e4fa4SJesse Taube if (!report(!do_store(&test), "should not trigger")) {
528f81e4fa4SJesse Taube dbtr_uninstall_trigger();
529f81e4fa4SJesse Taube report_prefix_pop();
530f81e4fa4SJesse Taube report_skip("enable trigger: no disable");
531f81e4fa4SJesse Taube
532f81e4fa4SJesse Taube return;
533f81e4fa4SJesse Taube }
534f81e4fa4SJesse Taube
535f81e4fa4SJesse Taube report_prefix_pop();
536f81e4fa4SJesse Taube report_prefix_push("enable trigger");
537f81e4fa4SJesse Taube
538f81e4fa4SJesse Taube ret = sbi_debug_enable_triggers(0, 1);
539f81e4fa4SJesse Taube sbiret_report_error(&ret, SBI_SUCCESS, "sbi_debug_enable_triggers");
540f81e4fa4SJesse Taube
541f81e4fa4SJesse Taube report(do_store(&test), "triggered");
542f81e4fa4SJesse Taube
543f81e4fa4SJesse Taube dbtr_uninstall_trigger();
544f81e4fa4SJesse Taube report_prefix_pop();
545f81e4fa4SJesse Taube }
546f81e4fa4SJesse Taube
dbtr_test_exec(struct sbi_dbtr_shmem_entry * shmem,enum McontrolType type)547f81e4fa4SJesse Taube static void dbtr_test_exec(struct sbi_dbtr_shmem_entry *shmem, enum McontrolType type)
548f81e4fa4SJesse Taube {
549f81e4fa4SJesse Taube static unsigned long test;
550f81e4fa4SJesse Taube
551f81e4fa4SJesse Taube report_prefix_push("exec trigger");
552f81e4fa4SJesse Taube /* check if loads and stores trigger exec */
553f81e4fa4SJesse Taube if (!dbtr_install_trigger(shmem, &test, gen_tdata1(type, VALUE_EXECUTE, MODE_S))) {
554f81e4fa4SJesse Taube report_prefix_pop();
555f81e4fa4SJesse Taube return;
556f81e4fa4SJesse Taube }
557f81e4fa4SJesse Taube
558f81e4fa4SJesse Taube if (do_load(&test))
559f81e4fa4SJesse Taube report_fail("triggered by load");
560f81e4fa4SJesse Taube
561f81e4fa4SJesse Taube if (do_store(&test))
562f81e4fa4SJesse Taube report_fail("triggered by store");
563f81e4fa4SJesse Taube
564f81e4fa4SJesse Taube dbtr_uninstall_trigger();
565f81e4fa4SJesse Taube
566f81e4fa4SJesse Taube /* Check if exec works */
567f81e4fa4SJesse Taube if (!dbtr_install_trigger(shmem, exec_call, gen_tdata1(type, VALUE_EXECUTE, MODE_S))) {
568f81e4fa4SJesse Taube report_prefix_pop();
569f81e4fa4SJesse Taube return;
570f81e4fa4SJesse Taube }
571f81e4fa4SJesse Taube report(do_exec(), "triggered");
572f81e4fa4SJesse Taube
573f81e4fa4SJesse Taube dbtr_uninstall_trigger();
574f81e4fa4SJesse Taube report_prefix_pop();
575f81e4fa4SJesse Taube }
576f81e4fa4SJesse Taube
dbtr_test_read(struct sbi_dbtr_shmem_entry * shmem,enum McontrolType type)577f81e4fa4SJesse Taube static void dbtr_test_read(struct sbi_dbtr_shmem_entry *shmem, enum McontrolType type)
578f81e4fa4SJesse Taube {
579f81e4fa4SJesse Taube const unsigned long tstatus_expected = SBI_DBTR_TRIG_STATE_S | SBI_DBTR_TRIG_STATE_MAPPED;
580f81e4fa4SJesse Taube const unsigned long tdata1 = gen_tdata1(type, VALUE_STORE, MODE_S);
581f81e4fa4SJesse Taube static unsigned long test;
582f81e4fa4SJesse Taube struct sbiret ret;
583f81e4fa4SJesse Taube
584f81e4fa4SJesse Taube report_prefix_push("read trigger");
585f81e4fa4SJesse Taube if (!dbtr_install_trigger(shmem, &test, tdata1)) {
586f81e4fa4SJesse Taube report_prefix_pop();
587f81e4fa4SJesse Taube return;
588f81e4fa4SJesse Taube }
589f81e4fa4SJesse Taube
590f81e4fa4SJesse Taube ret = sbi_debug_read_triggers(0, 1);
591f81e4fa4SJesse Taube sbiret_report_error(&ret, SBI_SUCCESS, "sbi_debug_read_triggers");
592f81e4fa4SJesse Taube
593f81e4fa4SJesse Taube if (!report(shmem->data.tdata1 == tdata1, "tdata1 expected: 0x%016lx", tdata1))
594f81e4fa4SJesse Taube report_info("tdata1 found: 0x%016lx", shmem->data.tdata1);
595f81e4fa4SJesse Taube if (!report(shmem->data.tdata2 == ((unsigned long)&test), "tdata2 expected: 0x%016lx",
596f81e4fa4SJesse Taube (unsigned long)&test))
597f81e4fa4SJesse Taube report_info("tdata2 found: 0x%016lx", shmem->data.tdata2);
598f81e4fa4SJesse Taube if (!report(shmem->data.tstate == tstatus_expected, "tstate expected: 0x%016lx", tstatus_expected))
599f81e4fa4SJesse Taube report_info("tstate found: 0x%016lx", shmem->data.tstate);
600f81e4fa4SJesse Taube
601f81e4fa4SJesse Taube dbtr_uninstall_trigger();
602f81e4fa4SJesse Taube report_prefix_pop();
603f81e4fa4SJesse Taube }
604f81e4fa4SJesse Taube
check_exec(unsigned long base)605f81e4fa4SJesse Taube static void check_exec(unsigned long base)
606f81e4fa4SJesse Taube {
607f81e4fa4SJesse Taube struct sbiret ret;
608f81e4fa4SJesse Taube
609f81e4fa4SJesse Taube report(do_exec(), "exec triggered");
610f81e4fa4SJesse Taube
611f81e4fa4SJesse Taube ret = sbi_debug_uninstall_triggers(base, 1);
612f81e4fa4SJesse Taube sbiret_report_error(&ret, SBI_SUCCESS, "sbi_debug_uninstall_triggers");
613f81e4fa4SJesse Taube }
614f81e4fa4SJesse Taube
dbtr_test_multiple(struct sbi_dbtr_shmem_entry * shmem,enum McontrolType type,unsigned long num_trigs)615f81e4fa4SJesse Taube static void dbtr_test_multiple(struct sbi_dbtr_shmem_entry *shmem, enum McontrolType type,
616f81e4fa4SJesse Taube unsigned long num_trigs)
617f81e4fa4SJesse Taube {
618f81e4fa4SJesse Taube static unsigned long test[2];
619f81e4fa4SJesse Taube struct sbiret ret;
620f81e4fa4SJesse Taube bool have_three = num_trigs > 2;
621f81e4fa4SJesse Taube
622f81e4fa4SJesse Taube if (num_trigs < 2) {
623f81e4fa4SJesse Taube report_skip("test multiple");
624f81e4fa4SJesse Taube return;
625f81e4fa4SJesse Taube }
626f81e4fa4SJesse Taube
627f81e4fa4SJesse Taube report_prefix_push("test multiple");
628f81e4fa4SJesse Taube
629f81e4fa4SJesse Taube if (!dbtr_install_trigger(shmem, &test[0], gen_tdata1(type, VALUE_STORE, MODE_S))) {
630f81e4fa4SJesse Taube report_prefix_pop();
631f81e4fa4SJesse Taube return;
632f81e4fa4SJesse Taube }
633f81e4fa4SJesse Taube if (!dbtr_install_trigger(shmem, &test[1], gen_tdata1(type, VALUE_LOAD, MODE_S)))
634f81e4fa4SJesse Taube goto error;
635f81e4fa4SJesse Taube if (have_three &&
636f81e4fa4SJesse Taube !dbtr_install_trigger(shmem, exec_call, gen_tdata1(type, VALUE_EXECUTE, MODE_S))) {
637f81e4fa4SJesse Taube ret = sbi_debug_uninstall_triggers(1, 1);
638f81e4fa4SJesse Taube sbiret_report_error(&ret, SBI_SUCCESS, "sbi_debug_uninstall_triggers");
639f81e4fa4SJesse Taube goto error;
640f81e4fa4SJesse Taube }
641f81e4fa4SJesse Taube
642f81e4fa4SJesse Taube report(do_store(&test[0]), "store triggered");
643f81e4fa4SJesse Taube
644f81e4fa4SJesse Taube if (do_load(&test[0]))
645f81e4fa4SJesse Taube report_fail("store triggered by load");
646f81e4fa4SJesse Taube
647f81e4fa4SJesse Taube report(do_load(&test[1]), "load triggered");
648f81e4fa4SJesse Taube
649f81e4fa4SJesse Taube if (do_store(&test[1]))
650f81e4fa4SJesse Taube report_fail("load triggered by store");
651f81e4fa4SJesse Taube
652f81e4fa4SJesse Taube if (have_three)
653f81e4fa4SJesse Taube check_exec(2);
654f81e4fa4SJesse Taube
655f81e4fa4SJesse Taube ret = sbi_debug_uninstall_triggers(1, 1);
656f81e4fa4SJesse Taube sbiret_report_error(&ret, SBI_SUCCESS, "sbi_debug_uninstall_triggers");
657f81e4fa4SJesse Taube
658f81e4fa4SJesse Taube if (do_load(&test[1]))
659f81e4fa4SJesse Taube report_fail("load triggered after uninstall");
660f81e4fa4SJesse Taube
661f81e4fa4SJesse Taube report(do_store(&test[0]), "store triggered");
662f81e4fa4SJesse Taube
663f81e4fa4SJesse Taube if (!have_three &&
664f81e4fa4SJesse Taube dbtr_install_trigger(shmem, exec_call, gen_tdata1(type, VALUE_EXECUTE, MODE_S)))
665f81e4fa4SJesse Taube check_exec(1);
666f81e4fa4SJesse Taube
667f81e4fa4SJesse Taube error:
668f81e4fa4SJesse Taube ret = sbi_debug_uninstall_triggers(0, 1);
669f81e4fa4SJesse Taube sbiret_report_error(&ret, SBI_SUCCESS, "sbi_debug_uninstall_triggers");
670f81e4fa4SJesse Taube
671f81e4fa4SJesse Taube install_exception_handler(EXC_BREAKPOINT, NULL);
672f81e4fa4SJesse Taube report_prefix_pop();
673f81e4fa4SJesse Taube }
674f81e4fa4SJesse Taube
dbtr_test_multiple_types(struct sbi_dbtr_shmem_entry * shmem,unsigned long type)675f81e4fa4SJesse Taube static void dbtr_test_multiple_types(struct sbi_dbtr_shmem_entry *shmem, unsigned long type)
676f81e4fa4SJesse Taube {
677f81e4fa4SJesse Taube static unsigned long test;
678f81e4fa4SJesse Taube
679f81e4fa4SJesse Taube report_prefix_push("test multiple types");
680f81e4fa4SJesse Taube
681f81e4fa4SJesse Taube /* check if loads and stores trigger exec */
682f81e4fa4SJesse Taube if (!dbtr_install_trigger(shmem, &test,
683f81e4fa4SJesse Taube gen_tdata1(type, VALUE_EXECUTE | VALUE_LOAD | VALUE_STORE, MODE_S))) {
684f81e4fa4SJesse Taube report_prefix_pop();
685f81e4fa4SJesse Taube return;
686f81e4fa4SJesse Taube }
687f81e4fa4SJesse Taube
688f81e4fa4SJesse Taube report(do_load(&test), "load triggered");
689f81e4fa4SJesse Taube
690f81e4fa4SJesse Taube report(do_store(&test), "store triggered");
691f81e4fa4SJesse Taube
692f81e4fa4SJesse Taube dbtr_uninstall_trigger();
693f81e4fa4SJesse Taube
694f81e4fa4SJesse Taube /* Check if exec works */
695f81e4fa4SJesse Taube if (!dbtr_install_trigger(shmem, exec_call,
696f81e4fa4SJesse Taube gen_tdata1(type, VALUE_EXECUTE | VALUE_LOAD | VALUE_STORE, MODE_S))) {
697f81e4fa4SJesse Taube report_prefix_pop();
698f81e4fa4SJesse Taube return;
699f81e4fa4SJesse Taube }
700f81e4fa4SJesse Taube
701f81e4fa4SJesse Taube report(do_exec(), "exec triggered");
702f81e4fa4SJesse Taube
703f81e4fa4SJesse Taube dbtr_uninstall_trigger();
704f81e4fa4SJesse Taube report_prefix_pop();
705f81e4fa4SJesse Taube }
706f81e4fa4SJesse Taube
dbtr_test_disable_uninstall(struct sbi_dbtr_shmem_entry * shmem,enum McontrolType type)707f81e4fa4SJesse Taube static void dbtr_test_disable_uninstall(struct sbi_dbtr_shmem_entry *shmem, enum McontrolType type)
708f81e4fa4SJesse Taube {
709f81e4fa4SJesse Taube static unsigned long test;
710f81e4fa4SJesse Taube struct sbiret ret;
711f81e4fa4SJesse Taube
712f81e4fa4SJesse Taube report_prefix_push("disable uninstall");
713f81e4fa4SJesse Taube if (!dbtr_install_trigger(shmem, &test, gen_tdata1(type, VALUE_STORE, MODE_S))) {
714f81e4fa4SJesse Taube report_prefix_pop();
715f81e4fa4SJesse Taube return;
716f81e4fa4SJesse Taube }
717f81e4fa4SJesse Taube
718f81e4fa4SJesse Taube ret = sbi_debug_disable_triggers(0, 1);
719f81e4fa4SJesse Taube sbiret_report_error(&ret, SBI_SUCCESS, "sbi_debug_disable_triggers");
720f81e4fa4SJesse Taube
721f81e4fa4SJesse Taube dbtr_uninstall_trigger();
722f81e4fa4SJesse Taube
723f81e4fa4SJesse Taube if (!dbtr_install_trigger(shmem, &test, gen_tdata1(type, VALUE_STORE, MODE_S))) {
724f81e4fa4SJesse Taube report_prefix_pop();
725f81e4fa4SJesse Taube return;
726f81e4fa4SJesse Taube }
727f81e4fa4SJesse Taube
728f81e4fa4SJesse Taube report(do_store(&test), "triggered");
729f81e4fa4SJesse Taube
730f81e4fa4SJesse Taube dbtr_uninstall_trigger();
731f81e4fa4SJesse Taube report_prefix_pop();
732f81e4fa4SJesse Taube }
733f81e4fa4SJesse Taube
dbtr_test_uninstall_enable(struct sbi_dbtr_shmem_entry * shmem,enum McontrolType type)734f81e4fa4SJesse Taube static void dbtr_test_uninstall_enable(struct sbi_dbtr_shmem_entry *shmem, enum McontrolType type)
735f81e4fa4SJesse Taube {
736f81e4fa4SJesse Taube static unsigned long test;
737f81e4fa4SJesse Taube struct sbiret ret;
738f81e4fa4SJesse Taube
739f81e4fa4SJesse Taube report_prefix_push("uninstall enable");
740f81e4fa4SJesse Taube if (!dbtr_install_trigger(shmem, &test, gen_tdata1(type, VALUE_STORE, MODE_S))) {
741f81e4fa4SJesse Taube report_prefix_pop();
742f81e4fa4SJesse Taube return;
743f81e4fa4SJesse Taube }
744f81e4fa4SJesse Taube dbtr_uninstall_trigger();
745f81e4fa4SJesse Taube
746f81e4fa4SJesse Taube ret = sbi_debug_enable_triggers(0, 1);
747f81e4fa4SJesse Taube sbiret_report_error(&ret, SBI_SUCCESS, "sbi_debug_enable_triggers");
748f81e4fa4SJesse Taube
749f81e4fa4SJesse Taube install_exception_handler(EXC_BREAKPOINT, dbtr_exception_handler);
750f81e4fa4SJesse Taube
751f81e4fa4SJesse Taube report(!do_store(&test), "should not trigger");
752f81e4fa4SJesse Taube
753f81e4fa4SJesse Taube install_exception_handler(EXC_BREAKPOINT, NULL);
754f81e4fa4SJesse Taube report_prefix_pop();
755f81e4fa4SJesse Taube }
756f81e4fa4SJesse Taube
dbtr_test_uninstall_update(struct sbi_dbtr_shmem_entry * shmem,enum McontrolType type)757f81e4fa4SJesse Taube static void dbtr_test_uninstall_update(struct sbi_dbtr_shmem_entry *shmem, enum McontrolType type)
758f81e4fa4SJesse Taube {
759f81e4fa4SJesse Taube static unsigned long test;
760f81e4fa4SJesse Taube struct sbiret ret;
761f81e4fa4SJesse Taube bool kfail;
762f81e4fa4SJesse Taube
763f81e4fa4SJesse Taube report_prefix_push("uninstall update");
764f81e4fa4SJesse Taube if (!dbtr_install_trigger(shmem, NULL, gen_tdata1(type, VALUE_NONE, MODE_NONE))) {
765f81e4fa4SJesse Taube report_prefix_pop();
766f81e4fa4SJesse Taube return;
767f81e4fa4SJesse Taube }
768f81e4fa4SJesse Taube
769f81e4fa4SJesse Taube dbtr_uninstall_trigger();
770f81e4fa4SJesse Taube
771f81e4fa4SJesse Taube shmem->id.idx = 0;
772f81e4fa4SJesse Taube shmem->data.tdata1 = gen_tdata1(type, VALUE_STORE, MODE_S);
773f81e4fa4SJesse Taube shmem->data.tdata2 = (unsigned long)&test;
774f81e4fa4SJesse Taube
775f81e4fa4SJesse Taube /*
776f81e4fa4SJesse Taube * Known broken update_triggers.
777f81e4fa4SJesse Taube * https://lore.kernel.org/opensbi/aDdp1UeUh7GugeHp@ghost/T/#t
778f81e4fa4SJesse Taube */
779f81e4fa4SJesse Taube kfail = __sbi_get_imp_id() == SBI_IMPL_OPENSBI &&
780f81e4fa4SJesse Taube __sbi_get_imp_version() < sbi_impl_opensbi_mk_version(1, 7);
781f81e4fa4SJesse Taube ret = sbi_debug_update_triggers(1);
782f81e4fa4SJesse Taube sbiret_kfail_error(kfail, &ret, SBI_ERR_FAILURE, "sbi_debug_update_triggers");
783f81e4fa4SJesse Taube
784f81e4fa4SJesse Taube install_exception_handler(EXC_BREAKPOINT, dbtr_exception_handler);
785f81e4fa4SJesse Taube
786f81e4fa4SJesse Taube report(!do_store(&test), "should not trigger");
787f81e4fa4SJesse Taube
788f81e4fa4SJesse Taube install_exception_handler(EXC_BREAKPOINT, NULL);
789f81e4fa4SJesse Taube report_prefix_pop();
790f81e4fa4SJesse Taube }
791f81e4fa4SJesse Taube
dbtr_test_disable_read(struct sbi_dbtr_shmem_entry * shmem,enum McontrolType type)792f81e4fa4SJesse Taube static void dbtr_test_disable_read(struct sbi_dbtr_shmem_entry *shmem, enum McontrolType type)
793f81e4fa4SJesse Taube {
794f81e4fa4SJesse Taube const unsigned long tstatus_expected = SBI_DBTR_TRIG_STATE_S | SBI_DBTR_TRIG_STATE_MAPPED;
795f81e4fa4SJesse Taube const unsigned long tdata1 = gen_tdata1(type, VALUE_STORE, MODE_NONE);
796f81e4fa4SJesse Taube static unsigned long test;
797f81e4fa4SJesse Taube struct sbiret ret;
798f81e4fa4SJesse Taube
799f81e4fa4SJesse Taube report_prefix_push("disable read");
800f81e4fa4SJesse Taube if (!dbtr_install_trigger(shmem, &test, gen_tdata1(type, VALUE_STORE, MODE_S))) {
801f81e4fa4SJesse Taube report_prefix_pop();
802f81e4fa4SJesse Taube return;
803f81e4fa4SJesse Taube }
804f81e4fa4SJesse Taube
805f81e4fa4SJesse Taube ret = sbi_debug_disable_triggers(0, 1);
806f81e4fa4SJesse Taube sbiret_report_error(&ret, SBI_SUCCESS, "sbi_debug_disable_triggers");
807f81e4fa4SJesse Taube
808f81e4fa4SJesse Taube ret = sbi_debug_read_triggers(0, 1);
809f81e4fa4SJesse Taube sbiret_report_error(&ret, SBI_SUCCESS, "sbi_debug_read_triggers");
810f81e4fa4SJesse Taube
811f81e4fa4SJesse Taube if (!report(shmem->data.tdata1 == tdata1, "tdata1 expected: 0x%016lx", tdata1))
812f81e4fa4SJesse Taube report_info("tdata1 found: 0x%016lx", shmem->data.tdata1);
813f81e4fa4SJesse Taube if (!report(shmem->data.tdata2 == ((unsigned long)&test), "tdata2 expected: 0x%016lx",
814f81e4fa4SJesse Taube (unsigned long)&test))
815f81e4fa4SJesse Taube report_info("tdata2 found: 0x%016lx", shmem->data.tdata2);
816f81e4fa4SJesse Taube if (!report(shmem->data.tstate == tstatus_expected, "tstate expected: 0x%016lx", tstatus_expected))
817f81e4fa4SJesse Taube report_info("tstate found: 0x%016lx", shmem->data.tstate);
818f81e4fa4SJesse Taube
819f81e4fa4SJesse Taube dbtr_uninstall_trigger();
820f81e4fa4SJesse Taube report_prefix_pop();
821f81e4fa4SJesse Taube }
822f81e4fa4SJesse Taube
check_dbtr(void)823f81e4fa4SJesse Taube void check_dbtr(void)
824f81e4fa4SJesse Taube {
825f81e4fa4SJesse Taube static struct sbi_dbtr_shmem_entry shmem[RV_MAX_TRIGGERS] = {};
826f81e4fa4SJesse Taube unsigned long num_trigs;
827f81e4fa4SJesse Taube enum McontrolType trig_type;
828f81e4fa4SJesse Taube struct sbiret ret;
829f81e4fa4SJesse Taube
830f81e4fa4SJesse Taube report_prefix_push("dbtr");
831f81e4fa4SJesse Taube
832f81e4fa4SJesse Taube if (!sbi_probe(SBI_EXT_DBTR)) {
833f81e4fa4SJesse Taube report_skip("extension not available");
834f81e4fa4SJesse Taube goto exit_test;
835f81e4fa4SJesse Taube }
836f81e4fa4SJesse Taube
837f81e4fa4SJesse Taube num_trigs = dbtr_test_num_triggers();
838f81e4fa4SJesse Taube if (!num_trigs)
839f81e4fa4SJesse Taube goto exit_test;
840f81e4fa4SJesse Taube
841f81e4fa4SJesse Taube trig_type = dbtr_test_type(&num_trigs);
842f81e4fa4SJesse Taube if (trig_type == SBI_DBTR_TDATA1_TYPE_NONE)
843f81e4fa4SJesse Taube goto exit_test;
844f81e4fa4SJesse Taube
845f81e4fa4SJesse Taube ret = sbi_debug_set_shmem(shmem);
846f81e4fa4SJesse Taube sbiret_report_error(&ret, SBI_SUCCESS, "sbi_debug_set_shmem");
847f81e4fa4SJesse Taube
848f81e4fa4SJesse Taube ret = dbtr_test_store_install_uninstall(&shmem[0], trig_type);
849f81e4fa4SJesse Taube /* install or uninstall failed */
850f81e4fa4SJesse Taube if (ret.error != SBI_SUCCESS)
851f81e4fa4SJesse Taube goto exit_test;
852f81e4fa4SJesse Taube
853f81e4fa4SJesse Taube dbtr_test_load(&shmem[0], trig_type);
854f81e4fa4SJesse Taube dbtr_test_exec(&shmem[0], trig_type);
855f81e4fa4SJesse Taube dbtr_test_read(&shmem[0], trig_type);
856f81e4fa4SJesse Taube dbtr_test_disable_enable(&shmem[0], trig_type);
857f81e4fa4SJesse Taube dbtr_test_update(&shmem[0], trig_type);
858f81e4fa4SJesse Taube dbtr_test_multiple_types(&shmem[0], trig_type);
859f81e4fa4SJesse Taube dbtr_test_multiple(shmem, trig_type, num_trigs);
860f81e4fa4SJesse Taube dbtr_test_disable_uninstall(&shmem[0], trig_type);
861f81e4fa4SJesse Taube dbtr_test_uninstall_enable(&shmem[0], trig_type);
862f81e4fa4SJesse Taube dbtr_test_uninstall_update(&shmem[0], trig_type);
863f81e4fa4SJesse Taube dbtr_test_disable_read(&shmem[0], trig_type);
864f81e4fa4SJesse Taube
865f81e4fa4SJesse Taube exit_test:
866f81e4fa4SJesse Taube report_prefix_pop();
867f81e4fa4SJesse Taube }
868