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.
14 #include "qemu/osdep.h"
16 #include "sysemu/sysemu.h"
17 #include "hw/s390x/sclp.h"
18 #include "hw/s390x/event-facility.h"
20 typedef struct SignalQuiesce
{
21 EventBufferHeader ebh
;
24 } QEMU_PACKED SignalQuiesce
;
26 static bool can_handle_event(uint8_t type
)
28 return type
== SCLP_EVENT_SIGNAL_QUIESCE
;
31 static unsigned int send_mask(void)
33 return SCLP_EVENT_MASK_SIGNAL_QUIESCE
;
36 static unsigned int receive_mask(void)
41 static int read_event_data(SCLPEvent
*event
, EventBufferHeader
*evt_buf_hdr
,
44 SignalQuiesce
*sq
= (SignalQuiesce
*) evt_buf_hdr
;
46 if (*slen
< sizeof(SignalQuiesce
)) {
50 if (!event
->event_pending
) {
53 event
->event_pending
= false;
55 sq
->ebh
.length
= cpu_to_be16(sizeof(SignalQuiesce
));
56 sq
->ebh
.type
= SCLP_EVENT_SIGNAL_QUIESCE
;
57 sq
->ebh
.flags
|= SCLP_EVENT_BUFFER_ACCEPTED
;
59 * system_powerdown does not have a timeout. Fortunately the
60 * timeout value is currently ignored by Linux, anyway
62 sq
->timeout
= cpu_to_be16(0);
63 sq
->unit
= cpu_to_be16(0);
64 *slen
-= sizeof(SignalQuiesce
);
69 static const VMStateDescription vmstate_sclpquiesce
= {
70 .name
= TYPE_SCLP_QUIESCE
,
72 .minimum_version_id
= 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 set_bit(DEVICE_CATEGORY_MISC
, dc
->categories
);
122 * Reason: This is just an internal device - the notifier should
123 * not be registered multiple times in quiesce_init()
125 dc
->user_creatable
= false;
127 k
->init
= quiesce_init
;
128 k
->get_send_mask
= send_mask
;
129 k
->get_receive_mask
= receive_mask
;
130 k
->can_handle_event
= can_handle_event
;
131 k
->read_event_data
= read_event_data
;
132 k
->write_event_data
= NULL
;
135 static const TypeInfo sclp_quiesce_info
= {
136 .name
= TYPE_SCLP_QUIESCE
,
137 .parent
= TYPE_SCLP_EVENT
,
138 .instance_size
= sizeof(SCLPEvent
),
139 .class_init
= quiesce_class_init
,
140 .class_size
= sizeof(SCLPEventClass
),
143 static void register_types(void)
145 type_register_static(&sclp_quiesce_info
);
148 type_init(register_types
)