+bool riscv_enable_virt2phys = true;
+bool riscv_ebreakm = true;
+bool riscv_ebreaks = true;
+bool riscv_ebreaku = true;
+
+bool riscv_enable_virtual;
+
+static enum {
+ RO_NORMAL,
+ RO_REVERSED
+} resume_order;
+
+const virt2phys_info_t sv32 = {
+ .name = "Sv32",
+ .va_bits = 32,
+ .level = 2,
+ .pte_shift = 2,
+ .vpn_shift = {12, 22},
+ .vpn_mask = {0x3ff, 0x3ff},
+ .pte_ppn_shift = {10, 20},
+ .pte_ppn_mask = {0x3ff, 0xfff},
+ .pa_ppn_shift = {12, 22},
+ .pa_ppn_mask = {0x3ff, 0xfff},
+};
+
+const virt2phys_info_t sv39 = {
+ .name = "Sv39",
+ .va_bits = 39,
+ .level = 3,
+ .pte_shift = 3,
+ .vpn_shift = {12, 21, 30},
+ .vpn_mask = {0x1ff, 0x1ff, 0x1ff},
+ .pte_ppn_shift = {10, 19, 28},
+ .pte_ppn_mask = {0x1ff, 0x1ff, 0x3ffffff},
+ .pa_ppn_shift = {12, 21, 30},
+ .pa_ppn_mask = {0x1ff, 0x1ff, 0x3ffffff},
+};
+
+const virt2phys_info_t sv48 = {
+ .name = "Sv48",
+ .va_bits = 48,
+ .level = 4,
+ .pte_shift = 3,
+ .vpn_shift = {12, 21, 30, 39},
+ .vpn_mask = {0x1ff, 0x1ff, 0x1ff, 0x1ff},
+ .pte_ppn_shift = {10, 19, 28, 37},
+ .pte_ppn_mask = {0x1ff, 0x1ff, 0x1ff, 0x1ffff},
+ .pa_ppn_shift = {12, 21, 30, 39},
+ .pa_ppn_mask = {0x1ff, 0x1ff, 0x1ff, 0x1ffff},
+};
+
+void riscv_sample_buf_maybe_add_timestamp(struct target *target, bool before)
+{
+ RISCV_INFO(r);
+ uint32_t now = timeval_ms() & 0xffffffff;
+ if (r->sample_buf.used + 5 < r->sample_buf.size) {
+ if (before)
+ r->sample_buf.buf[r->sample_buf.used++] = RISCV_SAMPLE_BUF_TIMESTAMP_BEFORE;
+ else
+ r->sample_buf.buf[r->sample_buf.used++] = RISCV_SAMPLE_BUF_TIMESTAMP_AFTER;
+ r->sample_buf.buf[r->sample_buf.used++] = now & 0xff;
+ r->sample_buf.buf[r->sample_buf.used++] = (now >> 8) & 0xff;
+ r->sample_buf.buf[r->sample_buf.used++] = (now >> 16) & 0xff;
+ r->sample_buf.buf[r->sample_buf.used++] = (now >> 24) & 0xff;
+ }
+}
+
+static int riscv_resume_go_all_harts(struct target *target);
+
+void select_dmi_via_bscan(struct target *target)
+{
+ jtag_add_ir_scan(target->tap, &select_user4, TAP_IDLE);
+ if (bscan_tunnel_type == BSCAN_TUNNEL_DATA_REGISTER)
+ jtag_add_dr_scan(target->tap, bscan_tunnel_data_register_select_dmi_num_fields,
+ bscan_tunnel_data_register_select_dmi, TAP_IDLE);
+ else /* BSCAN_TUNNEL_NESTED_TAP */
+ jtag_add_dr_scan(target->tap, bscan_tunnel_nested_tap_select_dmi_num_fields,
+ bscan_tunnel_nested_tap_select_dmi, TAP_IDLE);
+}
+
+uint32_t dtmcontrol_scan_via_bscan(struct target *target, uint32_t out)
+{
+ /* On BSCAN TAP: Select IR=USER4, issue tunneled IR scan via BSCAN TAP's DR */
+ uint8_t tunneled_ir_width[4] = {bscan_tunnel_ir_width};
+ uint8_t tunneled_dr_width[4] = {32};
+ uint8_t out_value[5] = {0};
+ uint8_t in_value[5] = {0};
+
+ buf_set_u32(out_value, 0, 32, out);
+ struct scan_field tunneled_ir[4] = {};
+ struct scan_field tunneled_dr[4] = {};
+
+ if (bscan_tunnel_type == BSCAN_TUNNEL_DATA_REGISTER) {
+ tunneled_ir[0].num_bits = 3;
+ tunneled_ir[0].out_value = bscan_zero;
+ tunneled_ir[0].in_value = NULL;
+ tunneled_ir[1].num_bits = bscan_tunnel_ir_width;
+ tunneled_ir[1].out_value = ir_dtmcontrol;
+ tunneled_ir[1].in_value = NULL;
+ tunneled_ir[2].num_bits = 7;
+ tunneled_ir[2].out_value = tunneled_ir_width;
+ tunneled_ir[2].in_value = NULL;
+ tunneled_ir[3].num_bits = 1;
+ tunneled_ir[3].out_value = bscan_zero;
+ tunneled_ir[3].in_value = NULL;
+
+ tunneled_dr[0].num_bits = 3;
+ tunneled_dr[0].out_value = bscan_zero;
+ tunneled_dr[0].in_value = NULL;
+ tunneled_dr[1].num_bits = 32 + 1;
+ tunneled_dr[1].out_value = out_value;
+ tunneled_dr[1].in_value = in_value;
+ tunneled_dr[2].num_bits = 7;
+ tunneled_dr[2].out_value = tunneled_dr_width;
+ tunneled_dr[2].in_value = NULL;
+ tunneled_dr[3].num_bits = 1;
+ tunneled_dr[3].out_value = bscan_one;
+ tunneled_dr[3].in_value = NULL;
+ } else {
+ /* BSCAN_TUNNEL_NESTED_TAP */
+ tunneled_ir[3].num_bits = 3;
+ tunneled_ir[3].out_value = bscan_zero;
+ tunneled_ir[3].in_value = NULL;
+ tunneled_ir[2].num_bits = bscan_tunnel_ir_width;
+ tunneled_ir[2].out_value = ir_dtmcontrol;
+ tunneled_ir[1].in_value = NULL;
+ tunneled_ir[1].num_bits = 7;
+ tunneled_ir[1].out_value = tunneled_ir_width;
+ tunneled_ir[2].in_value = NULL;
+ tunneled_ir[0].num_bits = 1;
+ tunneled_ir[0].out_value = bscan_zero;
+ tunneled_ir[0].in_value = NULL;
+
+ tunneled_dr[3].num_bits = 3;
+ tunneled_dr[3].out_value = bscan_zero;
+ tunneled_dr[3].in_value = NULL;
+ tunneled_dr[2].num_bits = 32 + 1;
+ tunneled_dr[2].out_value = out_value;
+ tunneled_dr[2].in_value = in_value;
+ tunneled_dr[1].num_bits = 7;
+ tunneled_dr[1].out_value = tunneled_dr_width;
+ tunneled_dr[1].in_value = NULL;
+ tunneled_dr[0].num_bits = 1;
+ tunneled_dr[0].out_value = bscan_one;
+ tunneled_dr[0].in_value = NULL;
+ }
+ jtag_add_ir_scan(target->tap, &select_user4, TAP_IDLE);
+ jtag_add_dr_scan(target->tap, ARRAY_SIZE(tunneled_ir), tunneled_ir, TAP_IDLE);
+ jtag_add_dr_scan(target->tap, ARRAY_SIZE(tunneled_dr), tunneled_dr, TAP_IDLE);
+ select_dmi_via_bscan(target);
+
+ int retval = jtag_execute_queue();
+ if (retval != ERROR_OK) {
+ LOG_ERROR("failed jtag scan: %d", retval);
+ return retval;
+ }
+ /* Note the starting offset is bit 1, not bit 0. In BSCAN tunnel, there is a one-bit TCK skew between
+ output and input */
+ uint32_t in = buf_get_u32(in_value, 1, 32);
+ LOG_DEBUG("DTMCS: 0x%x -> 0x%x", out, in);