Expand the VIRT_DEBUG memory map entry from 0x100 to
RISCV_DM_SIZE (0x1000 = 4 KiB) to accommodate the full
Debug Module address space: DMI registers, work area, and ROM
entry vector.

Create the Debug Module device via riscv_dm_create() and wire
each hart's halt-request GPIO to it. Set dm_halt_addr so the
CPU enters the DM ROM entry point on debug-mode entry.

Signed-off-by: Chao Liu <[email protected]>
---
 hw/riscv/virt.c | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index bbce2fb667..0a7e29a743 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -58,6 +58,7 @@
 #include "qapi/qapi-visit-common.h"
 #include "hw/virtio/virtio-iommu.h"
 #include "hw/uefi/var-service-api.h"
+#include "hw/riscv/dm.h"
 
 /* KVM AIA only supports APLIC MSI. APLIC Wired is always emulated by QEMU. */
 static bool virt_use_kvm_aia_aplic_imsic(RISCVVirtAIAType aia_type)
@@ -80,7 +81,7 @@ static bool virt_aclint_allowed(void)
 }
 
 static const MemMapEntry virt_memmap[] = {
-    [VIRT_DEBUG] =        {        0x0,         0x100 },
+    [VIRT_DEBUG] =        {        0x0, RISCV_DM_SIZE },
     [VIRT_MROM] =         {     0x1000,        0xf000 },
     [VIRT_TEST] =         {   0x100000,        0x1000 },
     [VIRT_RTC] =          {   0x101000,        0x1000 },
@@ -1702,6 +1703,24 @@ static void virt_machine_init(MachineState *machine)
 
     create_platform_bus(s, mmio_irqchip);
 
+    /* Create Debug Module and connect each hart's halt-request IRQ */
+    int total_harts = machine->smp.cpus;
+    DeviceState *dm = riscv_dm_create(system_memory,
+                                      s->memmap[VIRT_DEBUG].base,
+                                      total_harts);
+
+    for (int h = 0; h < total_harts; h++) {
+        CPUState *cs = qemu_get_cpu(h);
+        RISCVCPU *rcpu = RISCV_CPU(cs);
+
+        qdev_connect_gpio_out(dm, h,
+                              qdev_get_gpio_in_named(DEVICE(cs),
+                                                     "dm-halt-req", 0));
+        rcpu->env.dm_rom_present = true;
+        rcpu->env.dm_halt_addr = s->memmap[VIRT_DEBUG].base +
+                                 RISCV_DM_ROM_ENTRY;
+    }
+
     serial_mm_init(system_memory, s->memmap[VIRT_UART0].base,
         0, qdev_get_gpio_in(mmio_irqchip, UART0_IRQ), 399193,
         serial_hd(0), DEVICE_LITTLE_ENDIAN);
-- 
2.53.0


Reply via email to