summary refs log tree commit diff stats
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/s390x/css.c15
-rw-r--r--hw/s390x/css.h1
-rw-r--r--hw/s390x/s390-skeys.c2
-rw-r--r--hw/s390x/sclp.c8
-rw-r--r--hw/watchdog/watchdog.c14
-rw-r--r--hw/watchdog/wdt_diag288.c7
6 files changed, 33 insertions, 14 deletions
diff --git a/hw/s390x/css.c b/hw/s390x/css.c
index 343c3520de..e83bf60a74 100644
--- a/hw/s390x/css.c
+++ b/hw/s390x/css.c
@@ -49,6 +49,7 @@ typedef struct IoAdapter {
 
 typedef struct ChannelSubSys {
     QTAILQ_HEAD(, CrwContainer) pending_crws;
+    bool sei_pending;
     bool do_crw_mchk;
     bool crws_lost;
     uint8_t max_cssid;
@@ -701,7 +702,7 @@ int css_do_csch(SubchDev *sch)
 
     /* Trigger the clear function. */
     s->ctrl &= ~(SCSW_CTRL_MASK_FCTL | SCSW_CTRL_MASK_ACTL);
-    s->ctrl |= SCSW_FCTL_CLEAR_FUNC | SCSW_FCTL_CLEAR_FUNC;
+    s->ctrl |= SCSW_FCTL_CLEAR_FUNC | SCSW_ACTL_CLEAR_PEND;
 
     do_subchannel_work(sch, NULL);
     ret = 0;
@@ -1359,7 +1360,15 @@ void css_generate_chp_crws(uint8_t cssid, uint8_t chpid)
 
 void css_generate_css_crws(uint8_t cssid)
 {
-    css_queue_crw(CRW_RSC_CSS, 0, 0, cssid);
+    if (!channel_subsys->sei_pending) {
+        css_queue_crw(CRW_RSC_CSS, 0, 0, cssid);
+    }
+    channel_subsys->sei_pending = true;
+}
+
+void css_clear_sei_pending(void)
+{
+    channel_subsys->sei_pending = false;
 }
 
 int css_enable_mcsse(void)
@@ -1509,6 +1518,7 @@ static void css_init(void)
 {
     channel_subsys = g_malloc0(sizeof(*channel_subsys));
     QTAILQ_INIT(&channel_subsys->pending_crws);
+    channel_subsys->sei_pending = false;
     channel_subsys->do_crw_mchk = true;
     channel_subsys->crws_lost = false;
     channel_subsys->chnmon_active = false;
@@ -1561,6 +1571,7 @@ void css_reset(void)
         QTAILQ_REMOVE(&channel_subsys->pending_crws, crw_cont, sibling);
         g_free(crw_cont);
     }
+    channel_subsys->sei_pending = false;
     channel_subsys->do_crw_mchk = true;
     channel_subsys->crws_lost = false;
 
diff --git a/hw/s390x/css.h b/hw/s390x/css.h
index a09bb1f87c..a47937dee5 100644
--- a/hw/s390x/css.h
+++ b/hw/s390x/css.h
@@ -103,6 +103,7 @@ void css_generate_sch_crws(uint8_t cssid, uint8_t ssid, uint16_t schid,
                            int hotplugged, int add);
 void css_generate_chp_crws(uint8_t cssid, uint8_t chpid);
 void css_generate_css_crws(uint8_t cssid);
+void css_clear_sei_pending(void);
 void css_adapter_interrupt(uint8_t isc);
 
 #define CSS_IO_ADAPTER_VIRTIO 1
diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c
index f2b732e300..0cd340747d 100644
--- a/hw/s390x/s390-skeys.c
+++ b/hw/s390x/s390-skeys.c
@@ -237,7 +237,7 @@ static const TypeInfo qemu_s390_skeys_info = {
     .instance_init = qemu_s390_skeys_init,
     .instance_size = sizeof(QEMUS390SKeysState),
     .class_init    = qemu_s390_skeys_class_init,
-    .instance_size = sizeof(S390SKeysClass),
+    .class_size    = sizeof(S390SKeysClass),
 };
 
 static void s390_storage_keys_save(QEMUFile *f, void *opaque)
diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c
index 74f2b40154..23dee88dd9 100644
--- a/hw/s390x/sclp.c
+++ b/hw/s390x/sclp.c
@@ -465,6 +465,12 @@ static void sclp_realize(DeviceState *dev, Error **errp)
     if (err) {
         goto out;
     }
+    /*
+     * qdev_device_add searches the sysbus for TYPE_SCLP_EVENTS_BUS. As long
+     * as we can't find a fitting bus via the qom tree, we have to add the
+     * event facility to the sysbus, so e.g. a sclp console can be created.
+     */
+    qdev_set_parent_bus(DEVICE(sclp->event_facility), sysbus_get_default());
 
     ret = s390_set_memory_limit(machine->maxram_size, &hw_limit);
     if (ret == -E2BIG) {
@@ -533,8 +539,6 @@ static void sclp_init(Object *obj)
 
     new = object_new(TYPE_SCLP_EVENT_FACILITY);
     object_property_add_child(obj, TYPE_SCLP_EVENT_FACILITY, new, NULL);
-    /* qdev_device_add searches the sysbus for TYPE_SCLP_EVENTS_BUS */
-    qdev_set_parent_bus(DEVICE(new), sysbus_get_default());
     object_unref(new);
     sclp->event_facility = EVENT_FACILITY(new);
 
diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c
index 8d4b0eeeb0..81de0e50b1 100644
--- a/hw/watchdog/watchdog.c
+++ b/hw/watchdog/watchdog.c
@@ -29,15 +29,6 @@
 #include "qapi-event.h"
 #include "hw/nmi.h"
 
-/* Possible values for action parameter. */
-#define WDT_RESET        1	/* Hard reset. */
-#define WDT_SHUTDOWN     2	/* Shutdown. */
-#define WDT_POWEROFF     3	/* Quit. */
-#define WDT_PAUSE        4	/* Pause. */
-#define WDT_DEBUG        5	/* Prints a message and continues running. */
-#define WDT_NONE         6	/* Do nothing. */
-#define WDT_NMI          7	/* Inject nmi into the guest */
-
 static int watchdog_action = WDT_RESET;
 static QLIST_HEAD(watchdog_list, WatchdogTimerModel) watchdog_list;
 
@@ -105,6 +96,11 @@ int select_watchdog_action(const char *p)
     return 0;
 }
 
+int get_watchdog_action(void)
+{
+    return watchdog_action;
+}
+
 /* This actually performs the "action" once a watchdog has expired,
  * ie. reboot, shutdown, exit, etc.
  */
diff --git a/hw/watchdog/wdt_diag288.c b/hw/watchdog/wdt_diag288.c
index 2a885a447c..ddda723906 100644
--- a/hw/watchdog/wdt_diag288.c
+++ b/hw/watchdog/wdt_diag288.c
@@ -51,6 +51,13 @@ static void diag288_timer_expired(void *dev)
 {
     qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n");
     watchdog_perform_action();
+    /* Reset the watchdog only if the guest was notified about expiry. */
+    switch (get_watchdog_action()) {
+    case WDT_DEBUG:
+    case WDT_NONE:
+    case WDT_PAUSE:
+         return;
+    }
     wdt_diag288_reset(dev);
 }