Wire up pre_write/post_write/post_read callbacks for the newly
declared registers (DATA, PROGBUF, COMMAND, ABSTRACTAUTO,
ABSTRACTCS W1C) and expand the register_info table.

Refactor dm_dmcontrol_pre_write for clarity, fix haltsum0/1 to
use hartsel-based windowing, expand dm_reg_present for all
optional registers, add DATA area remap in ROM read/write, and
add realize-time validation for datacount and progbufsize.

Signed-off-by: Chao Liu <[email protected]>
---
 hw/riscv/dm.c | 772 +++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 571 insertions(+), 201 deletions(-)

diff --git a/hw/riscv/dm.c b/hw/riscv/dm.c
index 427507e77e..169863c54c 100644
--- a/hw/riscv/dm.c
+++ b/hw/riscv/dm.c
@@ -228,6 +228,7 @@ REG32(HALTSUM0, 0x100)
 #define DM_NOP    0x13u
 #define DM_EBREAK 0x100073u
 
+
 typedef struct DMHartSelection {
     int all[RISCV_DM_HAWINDOW_SIZE + 1];
     int all_count;
@@ -235,19 +236,6 @@ typedef struct DMHartSelection {
     int valid_count;
 } DMHartSelection;
 
-static inline uint32_t dm_get_hartsel(RISCVDMState *s)
-{
-    uint32_t hi = ARRAY_FIELD_EX32(s->regs, DMCONTROL, HARTSELHI);
-    uint32_t lo = ARRAY_FIELD_EX32(s->regs, DMCONTROL, HARTSELLO);
-
-    return (hi << 10) | lo;
-}
-
-static inline bool dm_hart_valid(RISCVDMState *s, uint32_t hartsel)
-{
-    return hartsel < s->num_harts;
-}
-
 static inline uint32_t dm_rom_read32(RISCVDMState *s, uint32_t offset)
 {
     return ldl_le_p(s->rom_ptr + offset);
@@ -294,54 +282,58 @@ static void dm_flush_cmd_space(RISCVDMState *s)
     dm_rom_write32(s, RISCV_DM_ROM_WHERETO, DM_JAL(0x1C));
 }
 
-static void dm_invalidate_dynamic_code(RISCVDMState *s)
+static inline uint32_t dm_get_hartsel(RISCVDMState *s)
 {
-    if (tcg_enabled()) {
-        ram_addr_t base = memory_region_get_ram_addr(&s->rom_mr);
-
-        tb_invalidate_phys_range(NULL, base + RISCV_DM_ROM_WHERETO,
-                                 base + RISCV_DM_ROM_DATA - 1);
-    }
+    uint32_t hi = ARRAY_FIELD_EX32(s->regs, DMCONTROL, HARTSELHI);
+    uint32_t lo = ARRAY_FIELD_EX32(s->regs, DMCONTROL, HARTSELLO);
+    return (hi << 10) | lo;
 }
 
-static void dm_update_impebreak(RISCVDMState *s)
+static inline bool dm_hart_valid(RISCVDMState *s, uint32_t hartsel)
 {
-    hwaddr ebreak_addr = RISCV_DM_ROM_PROGBUF + s->progbuf_size * 4;
+    return hartsel < s->num_harts;
+}
 
-    if (ebreak_addr + 4 > RISCV_DM_ROM_DATA) {
-        return;
+static void dm_selection_add(RISCVDMState *s, DMHartSelection *sel, int 
hartsel)
+{
+    for (int i = 0; i < sel->all_count; i++) {
+        if (sel->all[i] == hartsel) {
+            return;
+        }
+    }
+    sel->all[sel->all_count++] = hartsel;
+    if (dm_hart_valid(s, hartsel)) {
+        sel->harts[sel->valid_count++] = hartsel;
     }
-
-    dm_rom_write32(s, ebreak_addr, s->impebreak ? DM_EBREAK : DM_NOP);
 }
 
-static void dm_reset_rom_state(RISCVDMState *s)
+static void dm_collect_selected_harts(RISCVDMState *s, DMHartSelection *sel)
 {
-    if (!s->rom_ptr) {
-        return;
-    }
+    uint32_t hartsel = dm_get_hartsel(s);
 
-    memset(s->rom_ptr + RISCV_DM_ROM_WORK_BASE, 0, RISCV_DM_ROM_WORK_SIZE);
+    memset(sel, 0, sizeof(*sel));
+    dm_selection_add(s, sel, hartsel);
 
-    dm_flush_cmd_space(s);
+    if (!ARRAY_FIELD_EX32(s->regs, DMCONTROL, HASEL)) {
+        return;
+    }
 
-    for (uint32_t i = 0; i < s->num_abstract_data; i++) {
-        dm_sync_data_to_rom(s, i);
+    uint32_t wsel = ARRAY_FIELD_EX32(s->regs, HAWINDOWSEL, HAWINDOWSEL);
+    if (wsel >= RISCV_DM_MAX_HARTS / RISCV_DM_HAWINDOW_SIZE) {
+        return;
     }
-    for (uint32_t i = 0; i < s->progbuf_size; i++) {
-        dm_sync_progbuf_to_rom(s, i);
+    uint32_t window = s->hawindow[wsel];
+    uint32_t base = wsel * RISCV_DM_HAWINDOW_SIZE;
+    for (int i = 0; i < RISCV_DM_HAWINDOW_SIZE; i++) {
+        if ((window >> i) & 1) {
+            dm_selection_add(s, sel, base + i);
+        }
     }
-
-    dm_update_impebreak(s);
-    dm_invalidate_dynamic_code(s);
 }
 
-static inline void dm_set_cmderr(RISCVDMState *s, uint32_t err)
+static inline bool dm_ndmreset_active(RISCVDMState *s)
 {
-    uint32_t cur = ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, CMDERR);
-    if (cur == RISCV_DM_CMDERR_NONE) {
-        ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, CMDERR, err);
-    }
+    return ARRAY_FIELD_EX32(s->regs, DMCONTROL, NDMRESET);
 }
 
 static bool dm_abstract_cmd_completed(RISCVDMState *s, uint32_t hartsel)
@@ -361,135 +353,137 @@ static bool dm_abstract_cmd_completed(RISCVDMState *s, 
uint32_t hartsel)
     return !(flags & RISCV_DM_FLAG_GOING);
 }
 
-static void dm_selection_add(RISCVDMState *s, DMHartSelection *sel, int 
hartsel)
+static void dm_invalidate_dynamic_code(RISCVDMState *s)
 {
-    for (int i = 0; i < sel->all_count; i++) {
-        if (sel->all[i] == hartsel) {
-            return;
-        }
-    }
+    if (tcg_enabled()) {
+        ram_addr_t base = memory_region_get_ram_addr(&s->rom_mr);
 
-    sel->all[sel->all_count++] = hartsel;
-    if (dm_hart_valid(s, hartsel)) {
-        sel->harts[sel->valid_count++] = hartsel;
+        tb_invalidate_phys_range(NULL, base + RISCV_DM_ROM_WHERETO,
+                                 base + RISCV_DM_ROM_DATA - 1);
     }
 }
 
-static void dm_collect_selected_harts(RISCVDMState *s, DMHartSelection *sel)
+static bool dm_data_reg_present(RISCVDMState *s, hwaddr addr)
 {
-    uint32_t hartsel = dm_get_hartsel(s);
-    uint32_t wsel;
-    uint32_t window;
-    uint32_t base;
+    unsigned int index = (addr - A_DATA0) / 4;
 
-    memset(sel, 0, sizeof(*sel));
-    dm_selection_add(s, sel, hartsel);
+    return index < s->num_abstract_data;
+}
 
-    if (!ARRAY_FIELD_EX32(s->regs, DMCONTROL, HASEL)) {
-        return;
-    }
+static bool dm_progbuf_reg_present(RISCVDMState *s, hwaddr addr)
+{
+    unsigned int index = (addr - A_PROGBUF0) / 4;
 
-    wsel = ARRAY_FIELD_EX32(s->regs, HAWINDOWSEL, HAWINDOWSEL);
-    if (wsel >= RISCV_DM_MAX_HARTS / RISCV_DM_HAWINDOW_SIZE) {
-        return;
-    }
+    return index < s->progbuf_size;
+}
 
-    window = s->hawindow[wsel];
-    base = wsel * RISCV_DM_HAWINDOW_SIZE;
-    for (int i = 0; i < RISCV_DM_HAWINDOW_SIZE; i++) {
-        if ((window >> i) & 1) {
-            dm_selection_add(s, sel, base + i);
-        }
+static bool dm_sba_addr_reg_present(RISCVDMState *s, hwaddr addr)
+{
+    switch (addr) {
+    case A_SBADDRESS0:
+        return s->sba_addr_width > 0;
+    case A_SBADDRESS1:
+        return s->sba_addr_width > 32;
+    case A_SBADDRESS2:
+        return s->sba_addr_width > 64;
+    case A_SBADDRESS3:
+        return s->sba_addr_width > 96;
+    default:
+        return false;
     }
 }
 
-static inline bool dm_ndmreset_active(RISCVDMState *s)
+static bool dm_sba_data_reg_present(RISCVDMState *s, hwaddr addr)
 {
-    return ARRAY_FIELD_EX32(s->regs, DMCONTROL, NDMRESET);
+    bool sbdata0 = ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS8) ||
+                   ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS16) ||
+                   ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS32) ||
+                   ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS64) ||
+                   ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS128);
+    bool sbdata1 = ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS64) ||
+                   ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS128);
+    bool sbdata23 = ARRAY_FIELD_EX32(s->regs, SBCS, SBACCESS128);
+
+    switch (addr) {
+    case A_SBDATA0:
+        return sbdata0;
+    case A_SBDATA1:
+        return sbdata1;
+    case A_SBDATA2:
+    case A_SBDATA3:
+        return sbdata23;
+    default:
+        return false;
+    }
 }
 
 static bool dm_reg_present(RISCVDMState *s, hwaddr addr)
 {
+    if (addr >= A_DATA0 && addr <= A_DATA11) {
+        return dm_data_reg_present(s, addr);
+    }
+
+    if (addr >= A_PROGBUF0 && addr <= A_PROGBUF15) {
+        return dm_progbuf_reg_present(s, addr);
+    }
+
     switch (addr) {
+    case A_AUTHDATA:
+    case A_DMCS2:
+        return false;
     case A_HALTSUM1:
         return s->num_harts >= 33;
+    case A_HALTSUM2:
+        return s->num_harts >= 1025;
+    case A_HALTSUM3:
+        return s->num_harts >= 32769;
+    case A_SBADDRESS0:
+    case A_SBADDRESS1:
+    case A_SBADDRESS2:
+    case A_SBADDRESS3:
+        return dm_sba_addr_reg_present(s, addr);
+    case A_SBDATA0:
+    case A_SBDATA1:
+    case A_SBDATA2:
+    case A_SBDATA3:
+        return dm_sba_data_reg_present(s, addr);
     default:
         return true;
     }
 }
 
-static void dm_status_refresh(RISCVDMState *s)
+static void dm_update_impebreak(RISCVDMState *s)
 {
-    DMHartSelection sel;
-    bool anyhalted = false;
-    bool allhalted = true;
-    bool anyrunning = false;
-    bool allrunning = true;
-    bool anyunavail = false;
-    bool allunavail = true;
-    bool anyresumeack = false;
-    bool allresumeack = true;
-    bool anyhavereset = false;
-    bool allhavereset = true;
-    bool anynonexistent;
-    bool allnonexistent;
-    bool reset_unavail = dm_ndmreset_active(s) ||
-                         ARRAY_FIELD_EX32(s->regs, DMCONTROL, HARTRESET);
+    hwaddr ebreak_addr = RISCV_DM_ROM_PROGBUF + s->progbuf_size * 4;
 
-    dm_collect_selected_harts(s, &sel);
+    if (ebreak_addr + 4 > RISCV_DM_ROM_DATA) {
+        return;
+    }
 
-    anynonexistent = sel.all_count > sel.valid_count;
-    allnonexistent = sel.valid_count == 0 && sel.all_count > 0;
+    dm_rom_write32(s, ebreak_addr, s->impebreak ? DM_EBREAK : DM_NOP);
+}
 
-    if (sel.valid_count == 0) {
-        allhalted = false;
-        allrunning = false;
-        allunavail = false;
-        allresumeack = false;
-        allhavereset = false;
+static void dm_reset_rom_state(RISCVDMState *s)
+{
+    if (!s->rom_ptr) {
+        return;
     }
 
-    for (int i = 0; i < sel.valid_count; i++) {
-        int h = sel.harts[i];
-        bool halted = s->hart_halted[h];
-        bool resumeack = s->hart_resumeack[h];
-        bool havereset = s->hart_havereset[h];
+    memset(s->rom_ptr + RISCV_DM_ROM_WORK_BASE, 0, RISCV_DM_ROM_WORK_SIZE);
 
-        if (reset_unavail) {
-            anyunavail = true;
-            allhalted = false;
-            allrunning = false;
-        } else {
-            anyhalted |= halted;
-            allhalted &= halted;
-            anyrunning |= !halted;
-            allrunning &= !halted;
-        }
+    dm_flush_cmd_space(s);
 
-        allunavail &= reset_unavail;
-        anyresumeack |= resumeack;
-        allresumeack &= resumeack;
-        anyhavereset |= havereset;
-        allhavereset &= havereset;
+    for (uint32_t i = 0; i < s->num_abstract_data; i++) {
+        dm_sync_data_to_rom(s, i);
+    }
+    for (uint32_t i = 0; i < s->progbuf_size; i++) {
+        dm_sync_progbuf_to_rom(s, i);
     }
 
-    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYHALTED, anyhalted);
-    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLHALTED, allhalted);
-    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYRUNNING, anyrunning);
-    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLRUNNING, allrunning);
-    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYUNAVAIL, anyunavail);
-    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLUNAVAIL, allunavail);
-    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYNONEXISTENT, anynonexistent);
-    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLNONEXISTENT, allnonexistent);
-    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYRESUMEACK, anyresumeack);
-    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLRESUMEACK, allresumeack);
-    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYHAVERESET, anyhavereset);
-    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLHAVERESET, allhavereset);
-    ARRAY_FIELD_DP32(s->regs, DMSTATUS, HASRESETHALTREQ, 1);
+    dm_update_impebreak(s);
+    dm_invalidate_dynamic_code(s);
 }
 
-static void dm_debug_reset(RISCVDMState *s);
-
 static void dm_cpu_reset_on_cpu(CPUState *cpu, run_on_cpu_data data)
 {
     bool request_reset_halt = data.host_int;
@@ -543,20 +537,93 @@ static void dm_reset_all_harts(RISCVDMState *s)
     }
 }
 
+
+static inline void dm_set_cmderr(RISCVDMState *s, uint32_t err)
+{
+    uint32_t cur = ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, CMDERR);
+    if (cur == RISCV_DM_CMDERR_NONE) {
+        ARRAY_FIELD_DP32(s->regs, ABSTRACTCS, CMDERR, err);
+    }
+}
+
+static void dm_status_refresh(RISCVDMState *s)
+{
+    DMHartSelection sel;
+    bool anyhalted = false, allhalted = true;
+    bool anyrunning = false, allrunning = true;
+    bool anyunavail = false, allunavail = true;
+    bool anyresumeack = false, allresumeack = true;
+    bool anyhavereset = false, allhavereset = true;
+    bool anynonexistent = false, allnonexistent = false;
+    bool reset_unavail = dm_ndmreset_active(s) ||
+                         ARRAY_FIELD_EX32(s->regs, DMCONTROL, HARTRESET);
+
+    dm_collect_selected_harts(s, &sel);
+
+    anynonexistent = (sel.all_count > sel.valid_count);
+    allnonexistent = (sel.valid_count == 0 && sel.all_count > 0);
+
+    if (sel.valid_count == 0) {
+        allhalted = false;
+        allrunning = false;
+        allunavail = false;
+        allresumeack = false;
+        allhavereset = false;
+    }
+
+    for (int i = 0; i < sel.valid_count; i++) {
+        int h = sel.harts[i];
+        bool halted = s->hart_halted[h];
+        bool resumeack = s->hart_resumeack[h];
+        bool havereset = s->hart_havereset[h];
+
+        if (reset_unavail) {
+            anyunavail = true;
+            allhalted = false;
+            allrunning = false;
+        } else {
+            anyhalted |= halted;
+            allhalted &= halted;
+            anyrunning |= !halted;
+            allrunning &= !halted;
+        }
+
+        allunavail &= reset_unavail;
+        anyresumeack |= resumeack;
+        allresumeack &= resumeack;
+        anyhavereset |= havereset;
+        allhavereset &= havereset;
+    }
+
+    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYHALTED, anyhalted);
+    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLHALTED, allhalted);
+    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYRUNNING, anyrunning);
+    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLRUNNING, allrunning);
+    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYUNAVAIL, anyunavail);
+    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLUNAVAIL, allunavail);
+    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYNONEXISTENT, anynonexistent);
+    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLNONEXISTENT, allnonexistent);
+    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYRESUMEACK, anyresumeack);
+    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLRESUMEACK, allresumeack);
+    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ANYHAVERESET, anyhavereset);
+    ARRAY_FIELD_DP32(s->regs, DMSTATUS, ALLHAVERESET, allhavereset);
+    ARRAY_FIELD_DP32(s->regs, DMSTATUS, HASRESETHALTREQ, 1);
+}
+
+
+static void dm_debug_reset(RISCVDMState *s);
 static uint64_t dm_dmcontrol_pre_write(RegisterInfo *reg, uint64_t val64)
 {
     RISCVDMState *s = RISCV_DM(reg->opaque);
-    uint32_t val = val64;
+    uint32_t val = (uint32_t)val64;
     uint32_t cur_ctl = s->regs[R_DMCONTROL];
     bool busy = ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, BUSY);
     bool ndmreset_was = FIELD_EX32(cur_ctl, DMCONTROL, NDMRESET);
     bool hartreset_was = FIELD_EX32(cur_ctl, DMCONTROL, HARTRESET);
-    bool dmactive = FIELD_EX32(val, DMCONTROL, DMACTIVE);
-    DMHartSelection sel;
-    uint32_t stored = 0;
 
     trace_riscv_dm_control_write(s->regs[R_DMCONTROL], val, busy);
 
+    /* If busy, preserve hart selection and suppress run-control */
     if (busy) {
         val = FIELD_DP32(val, DMCONTROL, HARTSELHI,
                          ARRAY_FIELD_EX32(s->regs, DMCONTROL, HARTSELHI));
@@ -569,25 +636,34 @@ static uint64_t dm_dmcontrol_pre_write(RegisterInfo *reg, 
uint64_t val64)
         val = FIELD_DP32(val, DMCONTROL, ACKHAVERESET, 0);
     }
 
+    bool dmactive = FIELD_EX32(val, DMCONTROL, DMACTIVE);
+
     if (!dmactive) {
+        /* dmactive=0: reset the DM */
         dm_debug_reset(s);
+        /* Return the reset value (only dmactive=0) */
         return 0;
     }
 
+    /* Store first so helpers see updated fields */
     s->regs[R_DMCONTROL] = val;
+
+    DMHartSelection sel;
     dm_collect_selected_harts(s, &sel);
 
-    if (FIELD_EX32(val, DMCONTROL, NDMRESET) && !ndmreset_was) {
+    bool ndmreset = FIELD_EX32(val, DMCONTROL, NDMRESET);
+    bool hartreset = FIELD_EX32(val, DMCONTROL, HARTRESET);
+
+    if (ndmreset && !ndmreset_was) {
         dm_reset_all_harts(s);
     }
-
-    if (FIELD_EX32(val, DMCONTROL, HARTRESET) && !hartreset_was) {
+    if (hartreset && !hartreset_was) {
         dm_reset_selected_harts(s, &sel);
     }
 
-    ARRAY_FIELD_DP32(s->regs, DMSTATUS, NDMRESETPENDING,
-                     FIELD_EX32(val, DMCONTROL, NDMRESET));
+    ARRAY_FIELD_DP32(s->regs, DMSTATUS, NDMRESETPENDING, ndmreset);
 
+    /* ACKHAVERESET: clear havereset for selected harts */
     if (!busy && FIELD_EX32(val, DMCONTROL, ACKHAVERESET)) {
         for (int i = 0; i < sel.valid_count; i++) {
             s->hart_havereset[sel.harts[i]] = false;
@@ -606,22 +682,24 @@ static uint64_t dm_dmcontrol_pre_write(RegisterInfo *reg, 
uint64_t val64)
         }
     }
 
-    if (!busy && FIELD_EX32(val, DMCONTROL, RESUMEREQ) &&
-        !FIELD_EX32(val, DMCONTROL, HALTREQ)) {
+    /* RESUMEREQ */
+    bool resumereq = FIELD_EX32(val, DMCONTROL, RESUMEREQ);
+    bool haltreq = FIELD_EX32(val, DMCONTROL, HALTREQ);
+
+    if (!busy && resumereq && !haltreq) {
         for (int i = 0; i < sel.valid_count; i++) {
             int h = sel.harts[i];
-
             s->hart_resumeack[h] = false;
             dm_rom_write8(s, RISCV_DM_ROM_FLAGS + h, RISCV_DM_FLAG_RESUME);
             trace_riscv_dm_control_resume(h);
         }
     }
 
+    /* HALTREQ */
     if (!busy) {
-        if (FIELD_EX32(val, DMCONTROL, HALTREQ)) {
+        if (haltreq) {
             for (int i = 0; i < sel.valid_count; i++) {
                 int h = sel.harts[i];
-
                 dm_rom_write8(s, RISCV_DM_ROM_FLAGS + h, RISCV_DM_FLAG_CLEAR);
                 qemu_set_irq(s->halt_irqs[h], 1);
                 trace_riscv_dm_control_halt(h);
@@ -633,6 +711,12 @@ static uint64_t dm_dmcontrol_pre_write(RegisterInfo *reg, 
uint64_t val64)
         }
     }
 
+    /*
+     * Build the stored value: only keep fields with readable semantics.
+     * WARZ fields (haltreq, resumereq, ackhavereset, setresethaltreq,
+     * clrresethaltreq, setkeepalive, clrkeepalive, ackunavail) read as 0.
+     */
+    uint32_t stored = 0;
     stored = FIELD_DP32(stored, DMCONTROL, DMACTIVE, 1);
     stored = FIELD_DP32(stored, DMCONTROL, NDMRESET,
                         FIELD_EX32(val, DMCONTROL, NDMRESET));
@@ -643,17 +727,17 @@ static uint64_t dm_dmcontrol_pre_write(RegisterInfo *reg, 
uint64_t val64)
     stored = FIELD_DP32(stored, DMCONTROL, HASEL,
                         FIELD_EX32(val, DMCONTROL, HASEL));
     stored = FIELD_DP32(stored, DMCONTROL, HARTRESET,
-                        FIELD_EX32(val, DMCONTROL, HARTRESET));
+                        hartreset);
 
     s->dm_active = true;
     dm_status_refresh(s);
+
     return stored;
 }
 
 static uint64_t dm_dmstatus_post_read(RegisterInfo *reg, uint64_t val)
 {
     RISCVDMState *s = RISCV_DM(reg->opaque);
-
     dm_status_refresh(s);
     return s->regs[R_DMSTATUS];
 }
@@ -661,8 +745,7 @@ static uint64_t dm_dmstatus_post_read(RegisterInfo *reg, 
uint64_t val)
 static uint64_t dm_hartinfo_post_read(RegisterInfo *reg, uint64_t val)
 {
     RISCVDMState *s = RISCV_DM(reg->opaque);
-    uint32_t v = val;
-
+    uint32_t v = 0;
     v = FIELD_DP32(v, HARTINFO, DATAADDR, RISCV_DM_ROM_DATA);
     v = FIELD_DP32(v, HARTINFO, DATASIZE, s->num_abstract_data);
     v = FIELD_DP32(v, HARTINFO, DATAACCESS, 1);
@@ -673,9 +756,7 @@ static uint64_t dm_hartinfo_post_read(RegisterInfo *reg, 
uint64_t val)
 static uint64_t dm_hawindowsel_pre_write(RegisterInfo *reg, uint64_t val64)
 {
     uint32_t max_sel = RISCV_DM_MAX_HARTS / RISCV_DM_HAWINDOW_SIZE;
-    uint32_t val = val64 & R_HAWINDOWSEL_HAWINDOWSEL_MASK;
-
-    (void)reg;
+    uint32_t val = (uint32_t)val64 & R_HAWINDOWSEL_HAWINDOWSEL_MASK;
     if (val >= max_sel) {
         val = max_sel - 1;
     }
@@ -686,9 +767,8 @@ static uint64_t dm_hawindow_pre_write(RegisterInfo *reg, 
uint64_t val64)
 {
     RISCVDMState *s = RISCV_DM(reg->opaque);
     uint32_t wsel = ARRAY_FIELD_EX32(s->regs, HAWINDOWSEL, HAWINDOWSEL);
-
     if (wsel < RISCV_DM_MAX_HARTS / RISCV_DM_HAWINDOW_SIZE) {
-        s->hawindow[wsel] = val64;
+        s->hawindow[wsel] = (uint32_t)val64;
     }
     return (uint32_t)val64;
 }
@@ -697,69 +777,312 @@ static uint64_t dm_hawindow_post_read(RegisterInfo *reg, 
uint64_t val)
 {
     RISCVDMState *s = RISCV_DM(reg->opaque);
     uint32_t wsel = ARRAY_FIELD_EX32(s->regs, HAWINDOWSEL, HAWINDOWSEL);
-
-    (void)val;
     if (wsel < RISCV_DM_MAX_HARTS / RISCV_DM_HAWINDOW_SIZE) {
         return s->hawindow[wsel];
     }
     return 0;
 }
 
+static uint64_t dm_abstractcs_pre_write(RegisterInfo *reg, uint64_t val64)
+{
+    RISCVDMState *s = RISCV_DM(reg->opaque);
+
+    if (ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, BUSY)) {
+        dm_set_cmderr(s, RISCV_DM_CMDERR_BUSY);
+        return s->regs[R_ABSTRACTCS];
+    }
+
+    /* W1C on CMDERR */
+    uint32_t w1c_bits = FIELD_EX32((uint32_t)val64, ABSTRACTCS, CMDERR);
+    uint32_t cur = s->regs[R_ABSTRACTCS];
+    uint32_t cmderr = FIELD_EX32(cur, ABSTRACTCS, CMDERR);
+    cmderr &= ~w1c_bits;
+    cur = FIELD_DP32(cur, ABSTRACTCS, CMDERR, cmderr);
+
+    return cur;
+}
+
+static uint64_t dm_command_pre_write(RegisterInfo *reg, uint64_t val64)
+{
+    RISCVDMState *s = RISCV_DM(reg->opaque);
+
+    /* Stub: abstract command execution added in a follow-on patch. */
+    s->last_cmd = (uint32_t)val64;
+    return s->regs[R_COMMAND];
+}
+
+static uint64_t dm_command_post_read(RegisterInfo *reg, uint64_t val)
+{
+    return 0;
+}
+
+static uint64_t dm_abstractauto_pre_write(RegisterInfo *reg, uint64_t val64)
+{
+    RISCVDMState *s = RISCV_DM(reg->opaque);
+
+    if (ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, BUSY)) {
+        dm_set_cmderr(s, RISCV_DM_CMDERR_BUSY);
+        return s->regs[R_ABSTRACTAUTO];
+    }
+
+    /* Stub: autoexec trigger logic added in a follow-on patch. */
+    uint32_t data_count = MIN(s->num_abstract_data, 12);
+    uint32_t pbuf_size = MIN(s->progbuf_size, 16);
+    uint32_t data_mask = data_count ? ((1u << data_count) - 1u) : 0;
+    uint32_t pbuf_mask = pbuf_size ? ((1u << pbuf_size) - 1u) : 0;
+    uint32_t mask = data_mask | (pbuf_mask << 16);
+
+    return (uint32_t)val64 & mask;
+}
+
+static uint64_t dm_data_pre_write(RegisterInfo *reg, uint64_t val64)
+{
+    RISCVDMState *s = RISCV_DM(reg->opaque);
+
+    if (ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, BUSY)) {
+        dm_set_cmderr(s, RISCV_DM_CMDERR_BUSY);
+        return s->regs[reg->access->addr / 4];
+    }
+    return (uint32_t)val64;
+}
+
+static void dm_data_post_write(RegisterInfo *reg, uint64_t val64)
+{
+    RISCVDMState *s = RISCV_DM(reg->opaque);
+    int index = (reg->access->addr - A_DATA0) / 4;
+
+    dm_sync_data_to_rom(s, index);
+}
+
+static uint64_t dm_data_post_read(RegisterInfo *reg, uint64_t val)
+{
+    return val;
+}
+
+static uint64_t dm_progbuf_pre_write(RegisterInfo *reg, uint64_t val64)
+{
+    RISCVDMState *s = RISCV_DM(reg->opaque);
+
+    if (ARRAY_FIELD_EX32(s->regs, ABSTRACTCS, BUSY)) {
+        dm_set_cmderr(s, RISCV_DM_CMDERR_BUSY);
+        return s->regs[reg->access->addr / 4];
+    }
+    return (uint32_t)val64;
+}
+
+static void dm_progbuf_post_write(RegisterInfo *reg, uint64_t val64)
+{
+    RISCVDMState *s = RISCV_DM(reg->opaque);
+    int index = (reg->access->addr - A_PROGBUF0) / 4;
+
+    dm_sync_progbuf_to_rom(s, index);
+}
+
+static uint64_t dm_progbuf_post_read(RegisterInfo *reg, uint64_t val)
+{
+    return val;
+}
+
 static uint64_t dm_haltsum0_post_read(RegisterInfo *reg, uint64_t val)
 {
     RISCVDMState *s = RISCV_DM(reg->opaque);
-    uint32_t sum = 0;
-    uint32_t base = 0;
-    uint32_t limit = MIN(s->num_harts, 32u);
-
-    (void)val;
-    for (uint32_t h = base; h < limit; h++) {
-        if (s->hart_halted[h]) {
-            sum |= 1u << (h - base);
+    uint32_t result = 0;
+    uint32_t base = dm_get_hartsel(s) & ~0x1fu;
+
+    for (uint32_t i = 0; i < 32; i++) {
+        uint32_t h = base + i;
+        if (h < s->num_harts && s->hart_halted[h]) {
+            result |= (1u << i);
         }
     }
-    return sum;
+    return result;
 }
 
 static uint64_t dm_haltsum1_post_read(RegisterInfo *reg, uint64_t val)
 {
     RISCVDMState *s = RISCV_DM(reg->opaque);
-    uint32_t sum = 0;
-
-    (void)reg;
-    (void)val;
-    for (uint32_t h = 0; h < s->num_harts; h++) {
-        if (s->hart_halted[h]) {
-            sum |= 1u << (h / 32);
+    uint32_t result = 0;
+    uint32_t base = dm_get_hartsel(s) & ~0x3ffu;
+
+    for (uint32_t g = 0; g < 32; g++) {
+        for (uint32_t i = 0; i < 32; i++) {
+            uint32_t h = base + g * 32 + i;
+            if (h < s->num_harts && s->hart_halted[h]) {
+                result |= (1u << g);
+                break;
+            }
         }
     }
-    return sum;
+    return result;
 }
 
+
 static RegisterAccessInfo riscv_dm_regs_info[] = {
+    { .name = "DATA0",  .addr = A_DATA0,  .pre_write = dm_data_pre_write,
+      .post_write = dm_data_post_write, .post_read = dm_data_post_read, },
+    { .name = "DATA1",  .addr = A_DATA1,  .pre_write = dm_data_pre_write,
+      .post_write = dm_data_post_write, .post_read = dm_data_post_read, },
+    { .name = "DATA2",  .addr = A_DATA2,  .pre_write = dm_data_pre_write,
+      .post_write = dm_data_post_write, .post_read = dm_data_post_read, },
+    { .name = "DATA3",  .addr = A_DATA3,  .pre_write = dm_data_pre_write,
+      .post_write = dm_data_post_write, .post_read = dm_data_post_read, },
+    { .name = "DATA4",  .addr = A_DATA4,  .pre_write = dm_data_pre_write,
+      .post_write = dm_data_post_write, .post_read = dm_data_post_read, },
+    { .name = "DATA5",  .addr = A_DATA5,  .pre_write = dm_data_pre_write,
+      .post_write = dm_data_post_write, .post_read = dm_data_post_read, },
+    { .name = "DATA6",  .addr = A_DATA6,  .pre_write = dm_data_pre_write,
+      .post_write = dm_data_post_write, .post_read = dm_data_post_read, },
+    { .name = "DATA7",  .addr = A_DATA7,  .pre_write = dm_data_pre_write,
+      .post_write = dm_data_post_write, .post_read = dm_data_post_read, },
+    { .name = "DATA8",  .addr = A_DATA8,  .pre_write = dm_data_pre_write,
+      .post_write = dm_data_post_write, .post_read = dm_data_post_read, },
+    { .name = "DATA9",  .addr = A_DATA9,  .pre_write = dm_data_pre_write,
+      .post_write = dm_data_post_write, .post_read = dm_data_post_read, },
+    { .name = "DATA10", .addr = A_DATA10, .pre_write = dm_data_pre_write,
+      .post_write = dm_data_post_write, .post_read = dm_data_post_read, },
+    { .name = "DATA11", .addr = A_DATA11, .pre_write = dm_data_pre_write,
+      .post_write = dm_data_post_write, .post_read = dm_data_post_read, },
+
     { .name = "DMCONTROL", .addr = A_DMCONTROL,
       .pre_write = dm_dmcontrol_pre_write, },
+
     { .name = "DMSTATUS", .addr = A_DMSTATUS,
-      .ro = 0xffffffff,
+      .ro = 0xFFFFFFFF,
       .post_read = dm_dmstatus_post_read, },
+
     { .name = "HARTINFO", .addr = A_HARTINFO,
-      .ro = 0xffffffff,
+      .ro = 0xFFFFFFFF,
       .post_read = dm_hartinfo_post_read, },
+
     { .name = "HALTSUM1", .addr = A_HALTSUM1,
-      .ro = 0xffffffff,
+      .ro = 0xFFFFFFFF,
       .post_read = dm_haltsum1_post_read, },
+
     { .name = "HAWINDOWSEL", .addr = A_HAWINDOWSEL,
       .pre_write = dm_hawindowsel_pre_write, },
+
     { .name = "HAWINDOW", .addr = A_HAWINDOW,
       .pre_write = dm_hawindow_pre_write,
       .post_read = dm_hawindow_post_read, },
+
     { .name = "ABSTRACTCS", .addr = A_ABSTRACTCS,
-      .ro = 0xffffffff, },
+      .ro = R_ABSTRACTCS_DATACOUNT_MASK | R_ABSTRACTCS_BUSY_MASK |
+            R_ABSTRACTCS_PROGBUFSIZE_MASK,
+      .pre_write = dm_abstractcs_pre_write, },
+
+    { .name = "COMMAND", .addr = A_COMMAND,
+      .pre_write = dm_command_pre_write,
+      .post_read = dm_command_post_read, },
+
+    { .name = "ABSTRACTAUTO", .addr = A_ABSTRACTAUTO,
+      .pre_write = dm_abstractauto_pre_write, },
+
+    { .name = "CONFSTRPTR0", .addr = A_CONFSTRPTR0, .ro = 0xFFFFFFFF, },
+    { .name = "CONFSTRPTR1", .addr = A_CONFSTRPTR1, .ro = 0xFFFFFFFF, },
+    { .name = "CONFSTRPTR2", .addr = A_CONFSTRPTR2, .ro = 0xFFFFFFFF, },
+    { .name = "CONFSTRPTR3", .addr = A_CONFSTRPTR3, .ro = 0xFFFFFFFF, },
+
+    { .name = "NEXTDM", .addr = A_NEXTDM, .ro = 0xFFFFFFFF, },
+
+    { .name = "PROGBUF0", .addr = A_PROGBUF0,
+      .pre_write = dm_progbuf_pre_write,
+      .post_write = dm_progbuf_post_write,
+      .post_read = dm_progbuf_post_read, },
+    { .name = "PROGBUF1", .addr = A_PROGBUF1,
+      .pre_write = dm_progbuf_pre_write,
+      .post_write = dm_progbuf_post_write,
+      .post_read = dm_progbuf_post_read, },
+    { .name = "PROGBUF2", .addr = A_PROGBUF2,
+      .pre_write = dm_progbuf_pre_write,
+      .post_write = dm_progbuf_post_write,
+      .post_read = dm_progbuf_post_read, },
+    { .name = "PROGBUF3", .addr = A_PROGBUF3,
+      .pre_write = dm_progbuf_pre_write,
+      .post_write = dm_progbuf_post_write,
+      .post_read = dm_progbuf_post_read, },
+    { .name = "PROGBUF4", .addr = A_PROGBUF4,
+      .pre_write = dm_progbuf_pre_write,
+      .post_write = dm_progbuf_post_write,
+      .post_read = dm_progbuf_post_read, },
+    { .name = "PROGBUF5", .addr = A_PROGBUF5,
+      .pre_write = dm_progbuf_pre_write,
+      .post_write = dm_progbuf_post_write,
+      .post_read = dm_progbuf_post_read, },
+    { .name = "PROGBUF6", .addr = A_PROGBUF6,
+      .pre_write = dm_progbuf_pre_write,
+      .post_write = dm_progbuf_post_write,
+      .post_read = dm_progbuf_post_read, },
+    { .name = "PROGBUF7", .addr = A_PROGBUF7,
+      .pre_write = dm_progbuf_pre_write,
+      .post_write = dm_progbuf_post_write,
+      .post_read = dm_progbuf_post_read, },
+    { .name = "PROGBUF8", .addr = A_PROGBUF8,
+      .pre_write = dm_progbuf_pre_write,
+      .post_write = dm_progbuf_post_write,
+      .post_read = dm_progbuf_post_read, },
+    { .name = "PROGBUF9", .addr = A_PROGBUF9,
+      .pre_write = dm_progbuf_pre_write,
+      .post_write = dm_progbuf_post_write,
+      .post_read = dm_progbuf_post_read, },
+    { .name = "PROGBUF10", .addr = A_PROGBUF10,
+      .pre_write = dm_progbuf_pre_write,
+      .post_write = dm_progbuf_post_write,
+      .post_read = dm_progbuf_post_read, },
+    { .name = "PROGBUF11", .addr = A_PROGBUF11,
+      .pre_write = dm_progbuf_pre_write,
+      .post_write = dm_progbuf_post_write,
+      .post_read = dm_progbuf_post_read, },
+    { .name = "PROGBUF12", .addr = A_PROGBUF12,
+      .pre_write = dm_progbuf_pre_write,
+      .post_write = dm_progbuf_post_write,
+      .post_read = dm_progbuf_post_read, },
+    { .name = "PROGBUF13", .addr = A_PROGBUF13,
+      .pre_write = dm_progbuf_pre_write,
+      .post_write = dm_progbuf_post_write,
+      .post_read = dm_progbuf_post_read, },
+    { .name = "PROGBUF14", .addr = A_PROGBUF14,
+      .pre_write = dm_progbuf_pre_write,
+      .post_write = dm_progbuf_post_write,
+      .post_read = dm_progbuf_post_read, },
+    { .name = "PROGBUF15", .addr = A_PROGBUF15,
+      .pre_write = dm_progbuf_pre_write,
+      .post_write = dm_progbuf_post_write,
+      .post_read = dm_progbuf_post_read, },
+
+    { .name = "AUTHDATA", .addr = A_AUTHDATA, },
+
+    { .name = "DMCS2", .addr = A_DMCS2, },
+
+    { .name = "HALTSUM2", .addr = A_HALTSUM2, .ro = 0xFFFFFFFF, },
+    { .name = "HALTSUM3", .addr = A_HALTSUM3, .ro = 0xFFFFFFFF, },
+
+    { .name = "SBADDRESS3", .addr = A_SBADDRESS3, },
+
+    { .name = "SBCS", .addr = A_SBCS,
+      .ro = R_SBCS_SBACCESS8_MASK | R_SBCS_SBACCESS16_MASK |
+            R_SBCS_SBACCESS32_MASK | R_SBCS_SBACCESS64_MASK |
+            R_SBCS_SBACCESS128_MASK | R_SBCS_SBASIZE_MASK |
+            R_SBCS_SBBUSY_MASK | R_SBCS_SBVERSION_MASK, },
+
+    { .name = "SBADDRESS0", .addr = A_SBADDRESS0, },
+
+    { .name = "SBADDRESS1", .addr = A_SBADDRESS1, },
+
+    { .name = "SBADDRESS2", .addr = A_SBADDRESS2, },
+
+    { .name = "SBDATA0", .addr = A_SBDATA0, },
+
+    { .name = "SBDATA1", .addr = A_SBDATA1, },
+
+    { .name = "SBDATA2", .addr = A_SBDATA2, },
+    { .name = "SBDATA3", .addr = A_SBDATA3, },
+
     { .name = "HALTSUM0", .addr = A_HALTSUM0,
-      .ro = 0xffffffff,
+      .ro = 0xFFFFFFFF,
       .post_read = dm_haltsum0_post_read, },
 };
 
+
 static uint64_t riscv_dm_read(void *opaque, hwaddr addr, unsigned size)
 {
     RegisterInfoArray *reg_array = opaque;
@@ -829,6 +1152,16 @@ static uint64_t dm_rom_read(void *opaque, hwaddr offset, 
unsigned size)
     uint64_t ret;
 
     ret = ldn_le_p(s->rom_ptr + offset, size);
+
+    /* DATA area remap: reads from ROM DATA area return register values */
+    if (offset >= RISCV_DM_ROM_DATA &&
+        offset < RISCV_DM_ROM_DATA + s->num_abstract_data * 4) {
+        int idx = (offset - RISCV_DM_ROM_DATA) / 4;
+        if (size == 4) {
+            ret = s->regs[R_DATA0 + idx];
+        }
+    }
+
     trace_riscv_dm_rom_access(offset, ret, size, false);
     return ret;
 }
@@ -837,54 +1170,59 @@ static void dm_rom_write(void *opaque, hwaddr offset,
                          uint64_t value, unsigned size)
 {
     RISCVDMState *s = opaque;
-    uint32_t hartsel;
 
     stn_le_p(s->rom_ptr + offset, size, value);
 
     trace_riscv_dm_rom_access(offset, value, size, true);
 
+    /* CPU wrote to HARTID register → hart has halted */
     if (offset == RISCV_DM_ROM_HARTID && size == 4) {
-        hartsel = value;
+        uint32_t hartsel = (uint32_t)value;
         if (dm_hart_valid(s, hartsel)) {
             riscv_dm_hart_halted(s, hartsel);
         }
-        return;
     }
 
+    /* CPU wrote GOING acknowledgment */
     if (offset == RISCV_DM_ROM_GOING && size == 4) {
-        hartsel = dm_rom_read32(s, RISCV_DM_ROM_HARTID);
+        uint32_t hartsel = dm_rom_read32(s, RISCV_DM_ROM_HARTID);
         if (dm_hart_valid(s, hartsel)) {
             dm_rom_write8(s, RISCV_DM_ROM_FLAGS + hartsel,
                           RISCV_DM_FLAG_CLEAR);
             trace_riscv_dm_going(hartsel);
         }
-        return;
     }
 
+    /* CPU wrote RESUME acknowledgment */
     if (offset == RISCV_DM_ROM_RESUME && size == 4) {
-        hartsel = value;
+        uint32_t hartsel = (uint32_t)value;
         if (dm_hart_valid(s, hartsel)) {
             riscv_dm_hart_resumed(s, hartsel);
         }
-        return;
     }
 
+    /* CPU wrote EXCEPTION */
     if (offset == RISCV_DM_ROM_EXCP && size == 4) {
-        hartsel = dm_rom_read32(s, RISCV_DM_ROM_HARTID);
+        uint32_t hartsel = dm_rom_read32(s, RISCV_DM_ROM_HARTID);
         if (dm_hart_valid(s, hartsel)) {
             riscv_dm_abstracts_exception(s, hartsel);
         }
     }
+
+    /* DATA area remap: writes to ROM DATA area update registers */
+    if (offset >= RISCV_DM_ROM_DATA &&
+        offset < RISCV_DM_ROM_DATA + s->num_abstract_data * 4 && size == 4) {
+        int idx = (offset - RISCV_DM_ROM_DATA) / 4;
+        s->regs[R_DATA0 + idx] = (uint32_t)value;
+    }
 }
 
 static const MemoryRegionOps dm_rom_ops = {
     .read = dm_rom_read,
     .write = dm_rom_write,
     .endianness = DEVICE_LITTLE_ENDIAN,
-    .impl = {
-        .min_access_size = 1,
-        .max_access_size = 4,
-    },
+    .impl.min_access_size = 1,
+    .impl.max_access_size = 4,
 };
 
 static bool dm_rom_realize(RISCVDMState *s, Error **errp)
@@ -967,12 +1305,18 @@ static bool dm_rom_realize(RISCVDMState *s, Error **errp)
                              "riscv-dm.rom-entry", &s->rom_mr,
                              RISCV_DM_ROM_ENTRY, RISCV_DM_ROM_ENTRY_SIZE);
 
+    /*
+     * Expose debug backing store in two non-overlapping physical windows:
+     * - work area at low addresses (mailbox/data/progbuf/flags)
+     * - ROM entry vector at VIRT_DM_ROM base
+     */
     sysbus_init_mmio(sbd, &s->rom_work_alias_mr);
     sysbus_init_mmio(sbd, &s->rom_entry_alias_mr);
 
     return true;
 }
 
+
 void riscv_dm_hart_halted(RISCVDMState *s, uint32_t hartsel)
 {
     if (!dm_hart_valid(s, hartsel)) {
@@ -998,6 +1342,7 @@ void riscv_dm_hart_resumed(RISCVDMState *s, uint32_t 
hartsel)
     s->hart_halted[hartsel] = false;
     s->hart_resumeack[hartsel] = true;
     dm_rom_write8(s, RISCV_DM_ROM_FLAGS + hartsel, RISCV_DM_FLAG_CLEAR);
+
     dm_status_refresh(s);
     trace_riscv_dm_hart_resumed(hartsel);
 }
@@ -1014,6 +1359,7 @@ void riscv_dm_abstracts_exception(RISCVDMState *s, 
uint32_t hartsel)
     trace_riscv_dm_abstract_cmd_exception(hartsel);
 }
 
+
 static void dm_debug_reset(RISCVDMState *s)
 {
     s->dm_active = false;
@@ -1048,15 +1394,18 @@ static void dm_debug_reset(RISCVDMState *s)
     dm_status_refresh(s);
 }
 
+
 static void riscv_dm_init(Object *obj)
 {
     RISCVDMState *s = RISCV_DM(obj);
     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 
-    s->reg_array = register_init_block32(DEVICE(obj), riscv_dm_regs_info,
-                                         ARRAY_SIZE(riscv_dm_regs_info),
-                                         s->regs_info, s->regs, &riscv_dm_ops,
-                                         false, RISCV_DM_REG_SIZE);
+    s->reg_array =
+        register_init_block32(DEVICE(obj), riscv_dm_regs_info,
+                              ARRAY_SIZE(riscv_dm_regs_info),
+                              s->regs_info, s->regs,
+                              &riscv_dm_ops, false,
+                              RISCV_DM_REG_SIZE);
 
     sysbus_init_mmio(sbd, &s->reg_array->mem);
 }
@@ -1071,6 +1420,25 @@ static void riscv_dm_realize(DeviceState *dev, Error 
**errp)
         return;
     }
 
+    if (s->num_abstract_data == 0 || s->num_abstract_data > 12) {
+        error_setg(errp, "riscv-dm: datacount %u must be in range 1..12",
+                   s->num_abstract_data);
+        return;
+    }
+
+    if (s->progbuf_size > 16) {
+        error_setg(errp, "riscv-dm: progbufsize %u exceeds maximum 16",
+                   s->progbuf_size);
+        return;
+    }
+
+    if (s->progbuf_size == 1 && !s->impebreak) {
+        error_setg(errp,
+                   "riscv-dm: progbufsize 1 requires impebreak to be enabled");
+        return;
+    }
+
+    /* Allocate per-hart state */
     if (s->num_harts > 0) {
         s->hart_halted = g_new0(bool, s->num_harts);
         s->hart_resumeack = g_new0(bool, s->num_harts);
@@ -1089,19 +1457,19 @@ static void riscv_dm_realize(DeviceState *dev, Error 
**errp)
         return;
     }
 
+    /* Apply initial reset */
     dm_debug_reset(s);
 }
 
 static void riscv_dm_reset_hold(Object *obj, ResetType type)
 {
-    (void)type;
-    dm_debug_reset(RISCV_DM(obj));
+    RISCVDMState *s = RISCV_DM(obj);
+    dm_debug_reset(s);
 }
 
 static void riscv_dm_unrealize(DeviceState *dev)
 {
     RISCVDMState *s = RISCV_DM(dev);
-
     g_free(s->hart_halted);
     g_free(s->hart_resumeack);
     g_free(s->hart_havereset);
@@ -1109,6 +1477,7 @@ static void riscv_dm_unrealize(DeviceState *dev)
     g_free(s->halt_irqs);
 }
 
+
 static const Property riscv_dm_props[] = {
     DEFINE_PROP_UINT32("num-harts", RISCVDMState, num_harts, 1),
     DEFINE_PROP_UINT32("datacount", RISCVDMState, num_abstract_data, 2),
@@ -1183,5 +1552,6 @@ DeviceState *riscv_dm_create(MemoryRegion *sys_mem, 
hwaddr base,
     /* MMIO region 2: debug ROM entry vector */
     memory_region_add_subregion(sys_mem, base + RISCV_DM_ROM_ENTRY,
                                 sysbus_mmio_get_region(sbd, 2));
+
     return dev;
 }
-- 
2.53.0


Reply via email to