3 * Signal Quiesce - trigger system powerdown request
5 * Copyright IBM, Corp. 2012
8 * Heinz Graalfs <graalfs@de.ibm.com>
10 * This work is licensed under the terms of the GNU GPL, version 2 or (at your
11 * option) any later version. See the COPYING file in the top-level directory.
15 #include "sysemu/sysemu.h"
16 #include "hw/s390x/sclp.h"
17 #include "hw/s390x/event-facility.h"
19 typedef struct SignalQuiesce
{
20 EventBufferHeader ebh
;
23 } QEMU_PACKED SignalQuiesce
;
25 static bool can_handle_event(uint8_t type
)
27 return type
== SCLP_EVENT_SIGNAL_QUIESCE
;
30 static unsigned int send_mask(void)
32 return SCLP_EVENT_MASK_SIGNAL_QUIESCE
;
35 static unsigned int receive_mask(void)
40 static int read_event_data(SCLPEvent
*event
, EventBufferHeader
*evt_buf_hdr
,
43 SignalQuiesce
*sq
= (SignalQuiesce
*) evt_buf_hdr
;
45 if (*slen
< sizeof(SignalQuiesce
)) {
49 if (!event
->event_pending
) {
52 event
->event_pending
= false;
54 sq
->ebh
.length
= cpu_to_be16(sizeof(SignalQuiesce
));
55 sq
->ebh
.type
= SCLP_EVENT_SIGNAL_QUIESCE
;
56 sq
->ebh
.flags
|= SCLP_EVENT_BUFFER_ACCEPTED
;
58 * system_powerdown does not have a timeout. Fortunately the
59 * timeout value is currently ignored by Linux, anyway
61 sq
->timeout
= cpu_to_be16(0);
62 sq
->unit
= cpu_to_be16(0);
63 *slen
-= sizeof(SignalQuiesce
);
68 static const VMStateDescription vmstate_sclpquiesce
= {
69 .name
= "sclpquiesce",
71 .minimum_version_id
= 0,
72 .minimum_version_id_old
= 0,
73 .fields
= (VMStateField
[]) {
74 VMSTATE_BOOL(event_pending
, SCLPEvent
),
79 typedef struct QuiesceNotifier QuiesceNotifier
;
81 static struct QuiesceNotifier
{
86 static void quiesce_powerdown_req(Notifier
*n
, void *opaque
)
88 QuiesceNotifier
*qn
= container_of(n
, QuiesceNotifier
, notifier
);
89 SCLPEvent
*event
= qn
->event
;
91 event
->event_pending
= true;
92 /* trigger SCLP read operation */
93 sclp_service_interrupt(0);
96 static int quiesce_init(SCLPEvent
*event
)
98 qn
.notifier
.notify
= quiesce_powerdown_req
;
101 qemu_register_powerdown_notifier(&qn
.notifier
);
106 static void quiesce_reset(DeviceState
*dev
)
108 SCLPEvent
*event
= SCLP_EVENT(dev
);
110 event
->event_pending
= false;
113 static void quiesce_class_init(ObjectClass
*klass
, void *data
)
115 DeviceClass
*dc
= DEVICE_CLASS(klass
);
116 SCLPEventClass
*k
= SCLP_EVENT_CLASS(klass
);
118 dc
->reset
= quiesce_reset
;
119 dc
->vmsd
= &vmstate_sclpquiesce
;
120 k
->init
= quiesce_init
;
122 k
->get_send_mask
= send_mask
;
123 k
->get_receive_mask
= receive_mask
;
124 k
->can_handle_event
= can_handle_event
;
125 k
->read_event_data
= read_event_data
;
126 k
->write_event_data
= NULL
;
129 static const TypeInfo sclp_quiesce_info
= {
130 .name
= "sclpquiesce",
131 .parent
= TYPE_SCLP_EVENT
,
132 .instance_size
= sizeof(SCLPEvent
),
133 .class_init
= quiesce_class_init
,
134 .class_size
= sizeof(SCLPEventClass
),
137 static void register_types(void)
139 type_register_static(&sclp_quiesce_info
);
142 type_init(register_types
)