xref: /openbmc/qemu/hw/s390x/event-facility.c (revision 1b111dc1)
1 /*
2  * SCLP
3  *    Event Facility
4  *       handles SCLP event types
5  *          - Signal Quiesce - system power down
6  *          - ASCII Console Data - VT220 read and write
7  *
8  * Copyright IBM, Corp. 2012
9  *
10  * Authors:
11  *  Heinz Graalfs <graalfs@de.ibm.com>
12  *
13  * This work is licensed under the terms of the GNU GPL, version 2 or (at your
14  * option) any later version.  See the COPYING file in the top-level directory.
15  *
16  */
17 
18 #include "monitor/monitor.h"
19 #include "sysemu/sysemu.h"
20 
21 #include "hw/s390x/sclp.h"
22 #include "hw/s390x/event-facility.h"
23 
24 typedef struct EventTypesBus {
25     BusState qbus;
26 } EventTypesBus;
27 
28 struct SCLPEventFacility {
29     EventTypesBus sbus;
30     DeviceState *qdev;
31     /* guest' receive mask */
32     unsigned int receive_mask;
33 };
34 
35 /* return true if any child has event pending set */
36 static bool event_pending(SCLPEventFacility *ef)
37 {
38     BusChild *kid;
39     SCLPEvent *event;
40     SCLPEventClass *event_class;
41 
42     QTAILQ_FOREACH(kid, &ef->sbus.qbus.children, sibling) {
43         DeviceState *qdev = kid->child;
44         event = DO_UPCAST(SCLPEvent, qdev, qdev);
45         event_class = SCLP_EVENT_GET_CLASS(event);
46         if (event->event_pending &&
47             event_class->get_send_mask() & ef->receive_mask) {
48             return true;
49         }
50     }
51     return false;
52 }
53 
54 static unsigned int get_host_send_mask(SCLPEventFacility *ef)
55 {
56     unsigned int mask;
57     BusChild *kid;
58     SCLPEventClass *child;
59 
60     mask = 0;
61 
62     QTAILQ_FOREACH(kid, &ef->sbus.qbus.children, sibling) {
63         DeviceState *qdev = kid->child;
64         child = SCLP_EVENT_GET_CLASS((SCLPEvent *) qdev);
65         mask |= child->get_send_mask();
66     }
67     return mask;
68 }
69 
70 static unsigned int get_host_receive_mask(SCLPEventFacility *ef)
71 {
72     unsigned int mask;
73     BusChild *kid;
74     SCLPEventClass *child;
75 
76     mask = 0;
77 
78     QTAILQ_FOREACH(kid, &ef->sbus.qbus.children, sibling) {
79         DeviceState *qdev = kid->child;
80         child = SCLP_EVENT_GET_CLASS((SCLPEvent *) qdev);
81         mask |= child->get_receive_mask();
82     }
83     return mask;
84 }
85 
86 static uint16_t write_event_length_check(SCCB *sccb)
87 {
88     int slen;
89     unsigned elen = 0;
90     EventBufferHeader *event;
91     WriteEventData *wed = (WriteEventData *) sccb;
92 
93     event = (EventBufferHeader *) &wed->ebh;
94     for (slen = sccb_data_len(sccb); slen > 0; slen -= elen) {
95         elen = be16_to_cpu(event->length);
96         if (elen < sizeof(*event) || elen > slen) {
97             return SCLP_RC_EVENT_BUFFER_SYNTAX_ERROR;
98         }
99         event = (void *) event + elen;
100     }
101     if (slen) {
102         return SCLP_RC_INCONSISTENT_LENGTHS;
103     }
104     return SCLP_RC_NORMAL_COMPLETION;
105 }
106 
107 static uint16_t handle_write_event_buf(SCLPEventFacility *ef,
108                                        EventBufferHeader *event_buf, SCCB *sccb)
109 {
110     uint16_t rc;
111     BusChild *kid;
112     SCLPEvent *event;
113     SCLPEventClass *ec;
114 
115     rc = SCLP_RC_INVALID_FUNCTION;
116 
117     QTAILQ_FOREACH(kid, &ef->sbus.qbus.children, sibling) {
118         DeviceState *qdev = kid->child;
119         event = (SCLPEvent *) qdev;
120         ec = SCLP_EVENT_GET_CLASS(event);
121 
122         if (ec->write_event_data &&
123             ec->can_handle_event(event_buf->type)) {
124             rc = ec->write_event_data(event, event_buf);
125             break;
126         }
127     }
128     return rc;
129 }
130 
131 static uint16_t handle_sccb_write_events(SCLPEventFacility *ef, SCCB *sccb)
132 {
133     uint16_t rc;
134     int slen;
135     unsigned elen = 0;
136     EventBufferHeader *event_buf;
137     WriteEventData *wed = (WriteEventData *) sccb;
138 
139     event_buf = &wed->ebh;
140     rc = SCLP_RC_NORMAL_COMPLETION;
141 
142     /* loop over all contained event buffers */
143     for (slen = sccb_data_len(sccb); slen > 0; slen -= elen) {
144         elen = be16_to_cpu(event_buf->length);
145 
146         /* in case of a previous error mark all trailing buffers
147          * as not accepted */
148         if (rc != SCLP_RC_NORMAL_COMPLETION) {
149             event_buf->flags &= ~(SCLP_EVENT_BUFFER_ACCEPTED);
150         } else {
151             rc = handle_write_event_buf(ef, event_buf, sccb);
152         }
153         event_buf = (void *) event_buf + elen;
154     }
155     return rc;
156 }
157 
158 static void write_event_data(SCLPEventFacility *ef, SCCB *sccb)
159 {
160     if (sccb->h.function_code != SCLP_FC_NORMAL_WRITE) {
161         sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_FUNCTION);
162         goto out;
163     }
164     if (be16_to_cpu(sccb->h.length) < 8) {
165         sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
166         goto out;
167     }
168     /* first do a sanity check of the write events */
169     sccb->h.response_code = cpu_to_be16(write_event_length_check(sccb));
170 
171     /* if no early error, then execute */
172     if (sccb->h.response_code == be16_to_cpu(SCLP_RC_NORMAL_COMPLETION)) {
173         sccb->h.response_code =
174                 cpu_to_be16(handle_sccb_write_events(ef, sccb));
175     }
176 
177 out:
178     return;
179 }
180 
181 static uint16_t handle_sccb_read_events(SCLPEventFacility *ef, SCCB *sccb,
182                                         unsigned int mask)
183 {
184     uint16_t rc;
185     int slen;
186     unsigned elen;
187     BusChild *kid;
188     SCLPEvent *event;
189     SCLPEventClass *ec;
190     EventBufferHeader *event_buf;
191     ReadEventData *red = (ReadEventData *) sccb;
192 
193     event_buf = &red->ebh;
194     event_buf->length = 0;
195     slen = sizeof(sccb->data);
196 
197     rc = SCLP_RC_NO_EVENT_BUFFERS_STORED;
198 
199     QTAILQ_FOREACH(kid, &ef->sbus.qbus.children, sibling) {
200         DeviceState *qdev = kid->child;
201         event = (SCLPEvent *) qdev;
202         ec = SCLP_EVENT_GET_CLASS(event);
203 
204         if (mask & ec->get_send_mask()) {
205             if (ec->read_event_data(event, event_buf, &slen)) {
206                 elen = be16_to_cpu(event_buf->length);
207                 event_buf = (EventBufferHeader *) ((char *)event_buf + elen);
208                 rc = SCLP_RC_NORMAL_COMPLETION;
209             }
210         }
211     }
212 
213     if (sccb->h.control_mask[2] & SCLP_VARIABLE_LENGTH_RESPONSE) {
214         /* architecture suggests to reset variable-length-response bit */
215         sccb->h.control_mask[2] &= ~SCLP_VARIABLE_LENGTH_RESPONSE;
216         /* with a new length value */
217         sccb->h.length = cpu_to_be16(SCCB_SIZE - slen);
218     }
219     return rc;
220 }
221 
222 static void read_event_data(SCLPEventFacility *ef, SCCB *sccb)
223 {
224     unsigned int sclp_active_selection_mask;
225     unsigned int sclp_cp_receive_mask;
226 
227     ReadEventData *red = (ReadEventData *) sccb;
228 
229     if (be16_to_cpu(sccb->h.length) != SCCB_SIZE) {
230         sccb->h.response_code = cpu_to_be16(SCLP_RC_INSUFFICIENT_SCCB_LENGTH);
231         goto out;
232     }
233 
234     sclp_cp_receive_mask = ef->receive_mask;
235 
236     /* get active selection mask */
237     switch (sccb->h.function_code) {
238     case SCLP_UNCONDITIONAL_READ:
239         sclp_active_selection_mask = sclp_cp_receive_mask;
240         break;
241     case SCLP_SELECTIVE_READ:
242         if (!(sclp_cp_receive_mask & be32_to_cpu(red->mask))) {
243             sccb->h.response_code =
244                     cpu_to_be16(SCLP_RC_INVALID_SELECTION_MASK);
245             goto out;
246         }
247         sclp_active_selection_mask = be32_to_cpu(red->mask);
248         break;
249     default:
250         sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_FUNCTION);
251         goto out;
252     }
253     sccb->h.response_code = cpu_to_be16(
254             handle_sccb_read_events(ef, sccb, sclp_active_selection_mask));
255 
256 out:
257     return;
258 }
259 
260 static void write_event_mask(SCLPEventFacility *ef, SCCB *sccb)
261 {
262     WriteEventMask *we_mask = (WriteEventMask *) sccb;
263 
264     /* Attention: We assume that Linux uses 4-byte masks, what it actually
265        does. Architecture allows for masks of variable size, though */
266     if (be16_to_cpu(we_mask->mask_length) != 4) {
267         sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_MASK_LENGTH);
268         goto out;
269     }
270 
271     /* keep track of the guest's capability masks */
272     ef->receive_mask = be32_to_cpu(we_mask->cp_receive_mask);
273 
274     /* return the SCLP's capability masks to the guest */
275     we_mask->send_mask = cpu_to_be32(get_host_send_mask(ef));
276     we_mask->receive_mask = cpu_to_be32(get_host_receive_mask(ef));
277 
278     sccb->h.response_code = cpu_to_be16(SCLP_RC_NORMAL_COMPLETION);
279 
280 out:
281     return;
282 }
283 
284 /* qemu object creation and initialization functions */
285 
286 #define TYPE_SCLP_EVENTS_BUS "s390-sclp-events-bus"
287 
288 static void sclp_events_bus_class_init(ObjectClass *klass, void *data)
289 {
290 }
291 
292 static const TypeInfo s390_sclp_events_bus_info = {
293     .name = TYPE_SCLP_EVENTS_BUS,
294     .parent = TYPE_BUS,
295     .class_init = sclp_events_bus_class_init,
296 };
297 
298 static void command_handler(SCLPEventFacility *ef, SCCB *sccb, uint64_t code)
299 {
300     switch (code) {
301     case SCLP_CMD_READ_EVENT_DATA:
302         read_event_data(ef, sccb);
303         break;
304     case SCLP_CMD_WRITE_EVENT_DATA:
305         write_event_data(ef, sccb);
306         break;
307     case SCLP_CMD_WRITE_EVENT_MASK:
308         write_event_mask(ef, sccb);
309         break;
310     default:
311         sccb->h.response_code = cpu_to_be16(SCLP_RC_INVALID_SCLP_COMMAND);
312         break;
313     }
314 }
315 
316 static int init_event_facility(S390SCLPDevice *sdev)
317 {
318     SCLPEventFacility *event_facility;
319     DeviceState *quiesce;
320 
321     event_facility = g_malloc0(sizeof(SCLPEventFacility));
322     sdev->ef = event_facility;
323     sdev->sclp_command_handler = command_handler;
324     sdev->event_pending = event_pending;
325 
326     /* Spawn a new sclp-events facility */
327     qbus_create_inplace(&event_facility->sbus, sizeof(event_facility->sbus),
328                         TYPE_SCLP_EVENTS_BUS, DEVICE(sdev), NULL);
329     event_facility->sbus.qbus.allow_hotplug = 0;
330     event_facility->qdev = (DeviceState *) sdev;
331 
332     quiesce = qdev_create(&event_facility->sbus.qbus, "sclpquiesce");
333     if (!quiesce) {
334         return -1;
335     }
336     qdev_init_nofail(quiesce);
337 
338     return 0;
339 }
340 
341 static void reset_event_facility(DeviceState *dev)
342 {
343     S390SCLPDevice *sdev = SCLP_S390_DEVICE(dev);
344 
345     sdev->ef->receive_mask = 0;
346 }
347 
348 static void init_event_facility_class(ObjectClass *klass, void *data)
349 {
350     DeviceClass *dc = DEVICE_CLASS(klass);
351     S390SCLPDeviceClass *k = SCLP_S390_DEVICE_CLASS(klass);
352 
353     dc->reset = reset_event_facility;
354     k->init = init_event_facility;
355 }
356 
357 static const TypeInfo s390_sclp_event_facility_info = {
358     .name          = "s390-sclp-event-facility",
359     .parent        = TYPE_DEVICE_S390_SCLP,
360     .instance_size = sizeof(S390SCLPDevice),
361     .class_init    = init_event_facility_class,
362 };
363 
364 static int event_qdev_init(DeviceState *qdev)
365 {
366     SCLPEvent *event = DO_UPCAST(SCLPEvent, qdev, qdev);
367     SCLPEventClass *child = SCLP_EVENT_GET_CLASS(event);
368 
369     return child->init(event);
370 }
371 
372 static int event_qdev_exit(DeviceState *qdev)
373 {
374     SCLPEvent *event = DO_UPCAST(SCLPEvent, qdev, qdev);
375     SCLPEventClass *child = SCLP_EVENT_GET_CLASS(event);
376     if (child->exit) {
377         child->exit(event);
378     }
379     return 0;
380 }
381 
382 static void event_class_init(ObjectClass *klass, void *data)
383 {
384     DeviceClass *dc = DEVICE_CLASS(klass);
385 
386     dc->bus_type = TYPE_SCLP_EVENTS_BUS;
387     dc->unplug = qdev_simple_unplug_cb;
388     dc->init = event_qdev_init;
389     dc->exit = event_qdev_exit;
390 }
391 
392 static const TypeInfo s390_sclp_event_type_info = {
393     .name = TYPE_SCLP_EVENT,
394     .parent = TYPE_DEVICE,
395     .instance_size = sizeof(SCLPEvent),
396     .class_init = event_class_init,
397     .class_size = sizeof(SCLPEventClass),
398     .abstract = true,
399 };
400 
401 static void register_types(void)
402 {
403     type_register_static(&s390_sclp_events_bus_info);
404     type_register_static(&s390_sclp_event_facility_info);
405     type_register_static(&s390_sclp_event_type_info);
406 }
407 
408 type_init(register_types)
409