1 /* 2 * QEMU RISC-V Native Debug Support 3 * 4 * Copyright (c) 2022 Wind River Systems, Inc. 5 * 6 * Author: 7 * Bin Meng <bin.meng@windriver.com> 8 * 9 * This provides the native debug support via the Trigger Module, as defined 10 * in the RISC-V Debug Specification: 11 * https://github.com/riscv/riscv-debug-spec/raw/master/riscv-debug-stable.pdf 12 * 13 * This program is free software; you can redistribute it and/or modify it 14 * under the terms and conditions of the GNU General Public License, 15 * version 2 or later, as published by the Free Software Foundation. 16 * 17 * This program is distributed in the hope it will be useful, but WITHOUT 18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 20 * more details. 21 * 22 * You should have received a copy of the GNU General Public License along with 23 * this program. If not, see <http://www.gnu.org/licenses/>. 24 */ 25 26 #include "qemu/osdep.h" 27 #include "qemu/log.h" 28 #include "qapi/error.h" 29 #include "cpu.h" 30 #include "trace.h" 31 #include "exec/exec-all.h" 32 33 /* 34 * The following M-mode trigger CSRs are implemented: 35 * 36 * - tselect 37 * - tdata1 38 * - tdata2 39 * - tdata3 40 * 41 * We don't support writable 'type' field in the tdata1 register, so there is 42 * no need to implement the "tinfo" CSR. 43 * 44 * The following triggers are implemented: 45 * 46 * Index | Type | tdata mapping | Description 47 * ------+------+------------------------+------------ 48 * 0 | 2 | tdata1, tdata2 | Address / Data Match 49 * 1 | 2 | tdata1, tdata2 | Address / Data Match 50 */ 51 52 /* tdata availability of a trigger */ 53 typedef bool tdata_avail[TDATA_NUM]; 54 55 static tdata_avail tdata_mapping[TRIGGER_NUM] = { 56 [TRIGGER_TYPE2_IDX_0 ... TRIGGER_TYPE2_IDX_1] = { true, true, false }, 57 }; 58 59 /* only breakpoint size 1/2/4/8 supported */ 60 static int access_size[SIZE_NUM] = { 61 [SIZE_ANY] = 0, 62 [SIZE_1B] = 1, 63 [SIZE_2B] = 2, 64 [SIZE_4B] = 4, 65 [SIZE_6B] = -1, 66 [SIZE_8B] = 8, 67 [6 ... 15] = -1, 68 }; 69 70 static inline target_ulong trigger_type(CPURISCVState *env, 71 trigger_type_t type) 72 { 73 target_ulong tdata1; 74 75 switch (riscv_cpu_mxl(env)) { 76 case MXL_RV32: 77 tdata1 = RV32_TYPE(type); 78 break; 79 case MXL_RV64: 80 tdata1 = RV64_TYPE(type); 81 break; 82 default: 83 g_assert_not_reached(); 84 } 85 86 return tdata1; 87 } 88 89 bool tdata_available(CPURISCVState *env, int tdata_index) 90 { 91 if (unlikely(tdata_index >= TDATA_NUM)) { 92 return false; 93 } 94 95 if (unlikely(env->trigger_cur >= TRIGGER_NUM)) { 96 return false; 97 } 98 99 return tdata_mapping[env->trigger_cur][tdata_index]; 100 } 101 102 target_ulong tselect_csr_read(CPURISCVState *env) 103 { 104 return env->trigger_cur; 105 } 106 107 void tselect_csr_write(CPURISCVState *env, target_ulong val) 108 { 109 /* all target_ulong bits of tselect are implemented */ 110 env->trigger_cur = val; 111 } 112 113 static target_ulong tdata1_validate(CPURISCVState *env, target_ulong val, 114 trigger_type_t t) 115 { 116 uint32_t type, dmode; 117 target_ulong tdata1; 118 119 switch (riscv_cpu_mxl(env)) { 120 case MXL_RV32: 121 type = extract32(val, 28, 4); 122 dmode = extract32(val, 27, 1); 123 tdata1 = RV32_TYPE(t); 124 break; 125 case MXL_RV64: 126 type = extract64(val, 60, 4); 127 dmode = extract64(val, 59, 1); 128 tdata1 = RV64_TYPE(t); 129 break; 130 default: 131 g_assert_not_reached(); 132 } 133 134 if (type != t) { 135 qemu_log_mask(LOG_GUEST_ERROR, 136 "ignoring type write to tdata1 register\n"); 137 } 138 if (dmode != 0) { 139 qemu_log_mask(LOG_UNIMP, "debug mode is not supported\n"); 140 } 141 142 return tdata1; 143 } 144 145 static inline void warn_always_zero_bit(target_ulong val, target_ulong mask, 146 const char *msg) 147 { 148 if (val & mask) { 149 qemu_log_mask(LOG_UNIMP, "%s bit is always zero\n", msg); 150 } 151 } 152 153 static uint32_t type2_breakpoint_size(CPURISCVState *env, target_ulong ctrl) 154 { 155 uint32_t size, sizelo, sizehi = 0; 156 157 if (riscv_cpu_mxl(env) == MXL_RV64) { 158 sizehi = extract32(ctrl, 21, 2); 159 } 160 sizelo = extract32(ctrl, 16, 2); 161 size = (sizehi << 2) | sizelo; 162 163 return size; 164 } 165 166 static inline bool type2_breakpoint_enabled(target_ulong ctrl) 167 { 168 bool mode = !!(ctrl & (TYPE2_U | TYPE2_S | TYPE2_M)); 169 bool rwx = !!(ctrl & (TYPE2_LOAD | TYPE2_STORE | TYPE2_EXEC)); 170 171 return mode && rwx; 172 } 173 174 static target_ulong type2_mcontrol_validate(CPURISCVState *env, 175 target_ulong ctrl) 176 { 177 target_ulong val; 178 uint32_t size; 179 180 /* validate the generic part first */ 181 val = tdata1_validate(env, ctrl, TRIGGER_TYPE_AD_MATCH); 182 183 /* validate unimplemented (always zero) bits */ 184 warn_always_zero_bit(ctrl, TYPE2_MATCH, "match"); 185 warn_always_zero_bit(ctrl, TYPE2_CHAIN, "chain"); 186 warn_always_zero_bit(ctrl, TYPE2_ACTION, "action"); 187 warn_always_zero_bit(ctrl, TYPE2_TIMING, "timing"); 188 warn_always_zero_bit(ctrl, TYPE2_SELECT, "select"); 189 warn_always_zero_bit(ctrl, TYPE2_HIT, "hit"); 190 191 /* validate size encoding */ 192 size = type2_breakpoint_size(env, ctrl); 193 if (access_size[size] == -1) { 194 qemu_log_mask(LOG_UNIMP, "access size %d is not supported, using SIZE_ANY\n", 195 size); 196 } else { 197 val |= (ctrl & TYPE2_SIZELO); 198 if (riscv_cpu_mxl(env) == MXL_RV64) { 199 val |= (ctrl & TYPE2_SIZEHI); 200 } 201 } 202 203 /* keep the mode and attribute bits */ 204 val |= (ctrl & (TYPE2_U | TYPE2_S | TYPE2_M | 205 TYPE2_LOAD | TYPE2_STORE | TYPE2_EXEC)); 206 207 return val; 208 } 209 210 static void type2_breakpoint_insert(CPURISCVState *env, target_ulong index) 211 { 212 target_ulong ctrl = env->type2_trig[index].mcontrol; 213 target_ulong addr = env->type2_trig[index].maddress; 214 bool enabled = type2_breakpoint_enabled(ctrl); 215 CPUState *cs = env_cpu(env); 216 int flags = BP_CPU | BP_STOP_BEFORE_ACCESS; 217 uint32_t size; 218 219 if (!enabled) { 220 return; 221 } 222 223 if (ctrl & TYPE2_EXEC) { 224 cpu_breakpoint_insert(cs, addr, flags, &env->type2_trig[index].bp); 225 } 226 227 if (ctrl & TYPE2_LOAD) { 228 flags |= BP_MEM_READ; 229 } 230 if (ctrl & TYPE2_STORE) { 231 flags |= BP_MEM_WRITE; 232 } 233 234 if (flags & BP_MEM_ACCESS) { 235 size = type2_breakpoint_size(env, ctrl); 236 if (size != 0) { 237 cpu_watchpoint_insert(cs, addr, size, flags, 238 &env->type2_trig[index].wp); 239 } else { 240 cpu_watchpoint_insert(cs, addr, 8, flags, 241 &env->type2_trig[index].wp); 242 } 243 } 244 } 245 246 static void type2_breakpoint_remove(CPURISCVState *env, target_ulong index) 247 { 248 CPUState *cs = env_cpu(env); 249 250 if (env->type2_trig[index].bp) { 251 cpu_breakpoint_remove_by_ref(cs, env->type2_trig[index].bp); 252 env->type2_trig[index].bp = NULL; 253 } 254 255 if (env->type2_trig[index].wp) { 256 cpu_watchpoint_remove_by_ref(cs, env->type2_trig[index].wp); 257 env->type2_trig[index].wp = NULL; 258 } 259 } 260 261 static target_ulong type2_reg_read(CPURISCVState *env, 262 target_ulong trigger_index, int tdata_index) 263 { 264 uint32_t index = trigger_index - TRIGGER_TYPE2_IDX_0; 265 target_ulong tdata; 266 267 switch (tdata_index) { 268 case TDATA1: 269 tdata = env->type2_trig[index].mcontrol; 270 break; 271 case TDATA2: 272 tdata = env->type2_trig[index].maddress; 273 break; 274 default: 275 g_assert_not_reached(); 276 } 277 278 return tdata; 279 } 280 281 static void type2_reg_write(CPURISCVState *env, target_ulong trigger_index, 282 int tdata_index, target_ulong val) 283 { 284 uint32_t index = trigger_index - TRIGGER_TYPE2_IDX_0; 285 target_ulong new_val; 286 287 switch (tdata_index) { 288 case TDATA1: 289 new_val = type2_mcontrol_validate(env, val); 290 if (new_val != env->type2_trig[index].mcontrol) { 291 env->type2_trig[index].mcontrol = new_val; 292 type2_breakpoint_remove(env, index); 293 type2_breakpoint_insert(env, index); 294 } 295 break; 296 case TDATA2: 297 if (val != env->type2_trig[index].maddress) { 298 env->type2_trig[index].maddress = val; 299 type2_breakpoint_remove(env, index); 300 type2_breakpoint_insert(env, index); 301 } 302 break; 303 default: 304 g_assert_not_reached(); 305 } 306 307 return; 308 } 309 310 typedef target_ulong (*tdata_read_func)(CPURISCVState *env, 311 target_ulong trigger_index, 312 int tdata_index); 313 314 static tdata_read_func trigger_read_funcs[TRIGGER_NUM] = { 315 [TRIGGER_TYPE2_IDX_0 ... TRIGGER_TYPE2_IDX_1] = type2_reg_read, 316 }; 317 318 typedef void (*tdata_write_func)(CPURISCVState *env, 319 target_ulong trigger_index, 320 int tdata_index, 321 target_ulong val); 322 323 static tdata_write_func trigger_write_funcs[TRIGGER_NUM] = { 324 [TRIGGER_TYPE2_IDX_0 ... TRIGGER_TYPE2_IDX_1] = type2_reg_write, 325 }; 326 327 target_ulong tdata_csr_read(CPURISCVState *env, int tdata_index) 328 { 329 tdata_read_func read_func = trigger_read_funcs[env->trigger_cur]; 330 331 return read_func(env, env->trigger_cur, tdata_index); 332 } 333 334 void tdata_csr_write(CPURISCVState *env, int tdata_index, target_ulong val) 335 { 336 tdata_write_func write_func = trigger_write_funcs[env->trigger_cur]; 337 338 return write_func(env, env->trigger_cur, tdata_index, val); 339 } 340 341 void riscv_cpu_debug_excp_handler(CPUState *cs) 342 { 343 RISCVCPU *cpu = RISCV_CPU(cs); 344 CPURISCVState *env = &cpu->env; 345 346 if (cs->watchpoint_hit) { 347 if (cs->watchpoint_hit->flags & BP_CPU) { 348 cs->watchpoint_hit = NULL; 349 riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, 0); 350 } 351 } else { 352 if (cpu_breakpoint_test(cs, env->pc, BP_CPU)) { 353 riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, 0); 354 } 355 } 356 } 357 358 bool riscv_cpu_debug_check_breakpoint(CPUState *cs) 359 { 360 RISCVCPU *cpu = RISCV_CPU(cs); 361 CPURISCVState *env = &cpu->env; 362 CPUBreakpoint *bp; 363 target_ulong ctrl; 364 target_ulong pc; 365 int i; 366 367 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { 368 for (i = 0; i < TRIGGER_TYPE2_NUM; i++) { 369 ctrl = env->type2_trig[i].mcontrol; 370 pc = env->type2_trig[i].maddress; 371 372 if ((ctrl & TYPE2_EXEC) && (bp->pc == pc)) { 373 /* check U/S/M bit against current privilege level */ 374 if ((ctrl >> 3) & BIT(env->priv)) { 375 return true; 376 } 377 } 378 } 379 } 380 381 return false; 382 } 383 384 bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp) 385 { 386 RISCVCPU *cpu = RISCV_CPU(cs); 387 CPURISCVState *env = &cpu->env; 388 target_ulong ctrl; 389 target_ulong addr; 390 int flags; 391 int i; 392 393 for (i = 0; i < TRIGGER_TYPE2_NUM; i++) { 394 ctrl = env->type2_trig[i].mcontrol; 395 addr = env->type2_trig[i].maddress; 396 flags = 0; 397 398 if (ctrl & TYPE2_LOAD) { 399 flags |= BP_MEM_READ; 400 } 401 if (ctrl & TYPE2_STORE) { 402 flags |= BP_MEM_WRITE; 403 } 404 405 if ((wp->flags & flags) && (wp->vaddr == addr)) { 406 /* check U/S/M bit against current privilege level */ 407 if ((ctrl >> 3) & BIT(env->priv)) { 408 return true; 409 } 410 } 411 } 412 413 return false; 414 } 415