qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v2 8/8] q800: add NMI handler


From: Mark Cave-Ayland
Subject: [PATCH v2 8/8] q800: add NMI handler
Date: Wed, 20 Oct 2021 14:41:31 +0100

This allows the programmer's switch to be triggered via the monitor for 
debugging
purposes. Since the CPU level 7 interrupt is level-triggered, use a timer to 
hold
the NMI active for 100ms before releasing it again.

Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewied-by: Laurent Vivier <laurent@vivier.eu>
---
 hw/m68k/q800.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c
index 83fde39298..a081051a8d 100644
--- a/hw/m68k/q800.c
+++ b/hw/m68k/q800.c
@@ -28,6 +28,7 @@
 #include "cpu.h"
 #include "hw/boards.h"
 #include "hw/or-irq.h"
+#include "hw/nmi.h"
 #include "elf.h"
 #include "hw/loader.h"
 #include "ui/console.h"
@@ -102,12 +103,14 @@ struct GLUEState {
     uint8_t ipr;
     uint8_t auxmode;
     qemu_irq irqs[1];
+    QEMUTimer *nmi_release;
 };
 
 #define GLUE_IRQ_IN_VIA1       0
 #define GLUE_IRQ_IN_VIA2       1
 #define GLUE_IRQ_IN_SONIC      2
 #define GLUE_IRQ_IN_ESCC       3
+#define GLUE_IRQ_IN_NMI        4
 
 #define GLUE_IRQ_NUBUS_9       0
 
@@ -167,6 +170,10 @@ static void GLUE_set_irq(void *opaque, int irq, int level)
             irq = 3;
             break;
 
+        case GLUE_IRQ_IN_NMI:
+            irq = 6;
+            break;
+
         default:
             g_assert_not_reached();
         }
@@ -189,6 +196,10 @@ static void GLUE_set_irq(void *opaque, int irq, int level)
             irq = 3;
             break;
 
+        case GLUE_IRQ_IN_NMI:
+            irq = 6;
+            break;
+
         default:
             g_assert_not_reached();
         }
@@ -216,12 +227,30 @@ static void glue_auxmode_set_irq(void *opaque, int irq, 
int level)
     s->auxmode = level;
 }
 
+static void glue_nmi(NMIState *n, int cpu_index, Error **errp)
+{
+    GLUEState *s = GLUE(n);
+
+    /* Hold NMI active for 100ms */
+    GLUE_set_irq(s, GLUE_IRQ_IN_NMI, 1);
+    timer_mod(s->nmi_release, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 100);
+}
+
+static void glue_nmi_release(void *opaque)
+{
+    GLUEState *s = GLUE(opaque);
+
+    GLUE_set_irq(s, GLUE_IRQ_IN_NMI, 0);
+}
+
 static void glue_reset(DeviceState *dev)
 {
     GLUEState *s = GLUE(dev);
 
     s->ipr = 0;
     s->auxmode = 0;
+
+    timer_del(s->nmi_release);
 }
 
 static const VMStateDescription vmstate_glue = {
@@ -231,6 +260,7 @@ static const VMStateDescription vmstate_glue = {
     .fields = (VMStateField[]) {
         VMSTATE_UINT8(ipr, GLUEState),
         VMSTATE_UINT8(auxmode, GLUEState),
+        VMSTATE_TIMER_PTR(nmi_release, GLUEState),
         VMSTATE_END_OF_LIST(),
     },
 };
@@ -246,6 +276,13 @@ static Property glue_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
+static void glue_finalize(Object *obj)
+{
+    GLUEState *s = GLUE(obj);
+
+    timer_free(s->nmi_release);
+}
+
 static void glue_init(Object *obj)
 {
     DeviceState *dev = DEVICE(obj);
@@ -255,15 +292,20 @@ static void glue_init(Object *obj)
     qdev_init_gpio_in_named(dev, glue_auxmode_set_irq, "auxmode", 1);
 
     qdev_init_gpio_out(dev, s->irqs, 1);
+
+    /* NMI release timer */
+    s->nmi_release = timer_new_ms(QEMU_CLOCK_VIRTUAL, glue_nmi_release, s);
 }
 
 static void glue_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
+    NMIClass *nc = NMI_CLASS(klass);
 
     dc->vmsd = &vmstate_glue;
     dc->reset = glue_reset;
     device_class_set_props(dc, glue_properties);
+    nc->nmi_monitor_handler = glue_nmi;
 }
 
 static const TypeInfo glue_info = {
@@ -271,7 +313,12 @@ static const TypeInfo glue_info = {
     .parent = TYPE_SYS_BUS_DEVICE,
     .instance_size = sizeof(GLUEState),
     .instance_init = glue_init,
+    .instance_finalize = glue_finalize,
     .class_init = glue_class_init,
+    .interfaces = (InterfaceInfo[]) {
+         { TYPE_NMI },
+         { }
+    },
 };
 
 static void main_cpu_reset(void *opaque)
-- 
2.20.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]