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 int event_type(void)
27 return 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 typedef struct QuiesceNotifier QuiesceNotifier
;
70 static struct QuiesceNotifier
{
75 static void quiesce_powerdown_req(Notifier
*n
, void *opaque
)
77 QuiesceNotifier
*qn
= container_of(n
, QuiesceNotifier
, notifier
);
78 SCLPEvent
*event
= qn
->event
;
80 event
->event_pending
= true;
81 /* trigger SCLP read operation */
82 sclp_service_interrupt(0);
85 static int quiesce_init(SCLPEvent
*event
)
87 event
->event_type
= SCLP_EVENT_SIGNAL_QUIESCE
;
89 qn
.notifier
.notify
= quiesce_powerdown_req
;
92 qemu_register_powerdown_notifier(&qn
.notifier
);
97 static void quiesce_class_init(ObjectClass
*klass
, void *data
)
99 SCLPEventClass
*k
= SCLP_EVENT_CLASS(klass
);
101 k
->init
= quiesce_init
;
103 k
->get_send_mask
= send_mask
;
104 k
->get_receive_mask
= receive_mask
;
105 k
->event_type
= event_type
;
106 k
->read_event_data
= read_event_data
;
107 k
->write_event_data
= NULL
;
110 static const TypeInfo sclp_quiesce_info
= {
111 .name
= "sclpquiesce",
112 .parent
= TYPE_SCLP_EVENT
,
113 .instance_size
= sizeof(SCLPEvent
),
114 .class_init
= quiesce_class_init
,
115 .class_size
= sizeof(SCLPEventClass
),
118 static void register_types(void)
120 type_register_static(&sclp_quiesce_info
);
123 type_init(register_types
)