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 .fields
= (VMStateField
[]) {
73 VMSTATE_BOOL(event_pending
, SCLPEvent
),
78 typedef struct QuiesceNotifier QuiesceNotifier
;
80 static struct QuiesceNotifier
{
85 static void quiesce_powerdown_req(Notifier
*n
, void *opaque
)
87 QuiesceNotifier
*qn
= container_of(n
, QuiesceNotifier
, notifier
);
88 SCLPEvent
*event
= qn
->event
;
90 event
->event_pending
= true;
91 /* trigger SCLP read operation */
92 sclp_service_interrupt(0);
95 static int quiesce_init(SCLPEvent
*event
)
97 qn
.notifier
.notify
= quiesce_powerdown_req
;
100 qemu_register_powerdown_notifier(&qn
.notifier
);
105 static void quiesce_reset(DeviceState
*dev
)
107 SCLPEvent
*event
= SCLP_EVENT(dev
);
109 event
->event_pending
= false;
112 static void quiesce_class_init(ObjectClass
*klass
, void *data
)
114 DeviceClass
*dc
= DEVICE_CLASS(klass
);
115 SCLPEventClass
*k
= SCLP_EVENT_CLASS(klass
);
117 dc
->reset
= quiesce_reset
;
118 dc
->vmsd
= &vmstate_sclpquiesce
;
119 k
->init
= quiesce_init
;
121 k
->get_send_mask
= send_mask
;
122 k
->get_receive_mask
= receive_mask
;
123 k
->can_handle_event
= can_handle_event
;
124 k
->read_event_data
= read_event_data
;
125 k
->write_event_data
= NULL
;
128 static const TypeInfo sclp_quiesce_info
= {
129 .name
= "sclpquiesce",
130 .parent
= TYPE_SCLP_EVENT
,
131 .instance_size
= sizeof(SCLPEvent
),
132 .class_init
= quiesce_class_init
,
133 .class_size
= sizeof(SCLPEventClass
),
136 static void register_types(void)
138 type_register_static(&sclp_quiesce_info
);
141 type_init(register_types
)