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