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 <chao.liu.zevorn@gmail.com>
---
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