]> git.ipfire.org Git - thirdparty/qemu.git/blame - hw/s390x/virtio-ccw.c
Include hw/hw.h exactly where needed
[thirdparty/qemu.git] / hw / s390x / virtio-ccw.c
CommitLineData
a5cf2bb4
CH
1/*
2 * virtio ccw target implementation
3 *
de6a9218 4 * Copyright 2012,2015 IBM Corp.
a5cf2bb4 5 * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
de6a9218 6 * Pierre Morel <pmorel@linux.vnet.ibm.com>
a5cf2bb4
CH
7 *
8 * This work is licensed under the terms of the GNU GPL, version 2 or (at
9 * your option) any later version. See the COPYING file in the top-level
10 * directory.
11 */
12
9615495a 13#include "qemu/osdep.h"
da34e65c 14#include "qapi/error.h"
a5cf2bb4 15#include "sysemu/sysemu.h"
bd3f16ac 16#include "sysemu/kvm.h"
a5cf2bb4 17#include "net/net.h"
0d09e41a 18#include "hw/virtio/virtio.h"
ca77ee28 19#include "migration/qemu-file-types.h"
0d09e41a 20#include "hw/virtio/virtio-net.h"
a5cf2bb4
CH
21#include "hw/sysbus.h"
22#include "qemu/bitops.h"
d49b6836 23#include "qemu/error-report.h"
0b8fa32f 24#include "qemu/module.h"
c42767f2 25#include "hw/virtio/virtio-access.h"
0d09e41a 26#include "hw/virtio/virtio-bus.h"
d426d9fb
CH
27#include "hw/s390x/adapter.h"
28#include "hw/s390x/s390_flic.h"
a5cf2bb4 29
bd3f16ac
PB
30#include "hw/s390x/ioinst.h"
31#include "hw/s390x/css.h"
a5cf2bb4
CH
32#include "virtio-ccw.h"
33#include "trace.h"
dd70bd0d 34#include "hw/s390x/css-bridge.h"
517ff12c 35#include "hw/s390x/s390-virtio-ccw.h"
a5cf2bb4 36
797b6086
HP
37#define NR_CLASSIC_INDICATOR_BITS 64
38
517ff12c
HP
39static int virtio_ccw_dev_post_load(void *opaque, int version_id)
40{
41 VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(opaque);
42 CcwDevice *ccw_dev = CCW_DEVICE(dev);
43 CCWDeviceClass *ck = CCW_DEVICE_GET_CLASS(ccw_dev);
44
45 ccw_dev->sch->driver_data = dev;
46 if (ccw_dev->sch->thinint_active) {
47 dev->routes.adapter.adapter_id = css_get_adapter_id(
48 CSS_IO_ADAPTER_VIRTIO,
49 dev->thinint_isc);
50 }
51 /* Re-fill subch_id after loading the subchannel states.*/
52 if (ck->refill_ids) {
53 ck->refill_ids(ccw_dev);
54 }
55 return 0;
56}
57
58typedef struct VirtioCcwDeviceTmp {
59 VirtioCcwDevice *parent;
60 uint16_t config_vector;
61} VirtioCcwDeviceTmp;
62
44b1ff31 63static int virtio_ccw_dev_tmp_pre_save(void *opaque)
517ff12c
HP
64{
65 VirtioCcwDeviceTmp *tmp = opaque;
66 VirtioCcwDevice *dev = tmp->parent;
67 VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
68
69 tmp->config_vector = vdev->config_vector;
44b1ff31
DDAG
70
71 return 0;
517ff12c
HP
72}
73
74static int virtio_ccw_dev_tmp_post_load(void *opaque, int version_id)
75{
76 VirtioCcwDeviceTmp *tmp = opaque;
77 VirtioCcwDevice *dev = tmp->parent;
78 VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
79
80 vdev->config_vector = tmp->config_vector;
81 return 0;
82}
83
84const VMStateDescription vmstate_virtio_ccw_dev_tmp = {
85 .name = "s390_virtio_ccw_dev_tmp",
86 .pre_save = virtio_ccw_dev_tmp_pre_save,
87 .post_load = virtio_ccw_dev_tmp_post_load,
88 .fields = (VMStateField[]) {
89 VMSTATE_UINT16(config_vector, VirtioCcwDeviceTmp),
90 VMSTATE_END_OF_LIST()
91 }
92};
93
94const VMStateDescription vmstate_virtio_ccw_dev = {
95 .name = "s390_virtio_ccw_dev",
96 .version_id = 1,
97 .minimum_version_id = 1,
98 .post_load = virtio_ccw_dev_post_load,
99 .fields = (VMStateField[]) {
100 VMSTATE_CCW_DEVICE(parent_obj, VirtioCcwDevice),
101 VMSTATE_PTR_TO_IND_ADDR(indicators, VirtioCcwDevice),
102 VMSTATE_PTR_TO_IND_ADDR(indicators2, VirtioCcwDevice),
103 VMSTATE_PTR_TO_IND_ADDR(summary_indicator, VirtioCcwDevice),
104 /*
105 * Ugly hack because VirtIODevice does not migrate itself.
106 * This also makes legacy via vmstate_save_state possible.
107 */
108 VMSTATE_WITH_TMP(VirtioCcwDevice, VirtioCcwDeviceTmp,
109 vmstate_virtio_ccw_dev_tmp),
110 VMSTATE_STRUCT(routes, VirtioCcwDevice, 1, vmstate_adapter_routes,
111 AdapterRoutes),
112 VMSTATE_UINT8(thinint_isc, VirtioCcwDevice),
113 VMSTATE_INT32(revision, VirtioCcwDevice),
114 VMSTATE_END_OF_LIST()
115 }
116};
117
1bf4d7aa
AF
118static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size,
119 VirtioCcwDevice *dev);
d51fcfac 120
a5cf2bb4
CH
121VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch)
122{
123 VirtIODevice *vdev = NULL;
f24a6840 124 VirtioCcwDevice *dev = sch->driver_data;
a5cf2bb4 125
f24a6840
PB
126 if (dev) {
127 vdev = virtio_bus_get_device(&dev->bus);
a5cf2bb4
CH
128 }
129 return vdev;
130}
131
7c55f68a 132static void virtio_ccw_start_ioeventfd(VirtioCcwDevice *dev)
b4436a0b 133{
7c55f68a
CH
134 virtio_bus_start_ioeventfd(&dev->bus);
135}
b4436a0b 136
7c55f68a
CH
137static void virtio_ccw_stop_ioeventfd(VirtioCcwDevice *dev)
138{
139 virtio_bus_stop_ioeventfd(&dev->bus);
b4436a0b
CH
140}
141
8e93cef1 142static bool virtio_ccw_ioeventfd_enabled(DeviceState *d)
b4436a0b 143{
7c55f68a 144 VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
b4436a0b 145
8e93cef1 146 return (dev->flags & VIRTIO_CCW_FLAG_USE_IOEVENTFD) != 0;
7c55f68a
CH
147}
148
149static int virtio_ccw_ioeventfd_assign(DeviceState *d, EventNotifier *notifier,
150 int n, bool assign)
151{
152 VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
b804e8a6
JL
153 CcwDevice *ccw_dev = CCW_DEVICE(dev);
154 SubchDev *sch = ccw_dev->sch;
7c55f68a
CH
155 uint32_t sch_id = (css_build_subchannel_id(sch) << 16) | sch->schid;
156
157 return s390_assign_subch_ioeventfd(notifier, sch_id, n, assign);
b4436a0b
CH
158}
159
a5cf2bb4 160/* Communication blocks used by several channel commands. */
0db87e0d 161typedef struct VqInfoBlockLegacy {
a5cf2bb4
CH
162 uint64_t queue;
163 uint32_t align;
164 uint16_t index;
165 uint16_t num;
0db87e0d
CH
166} QEMU_PACKED VqInfoBlockLegacy;
167
168typedef struct VqInfoBlock {
169 uint64_t desc;
170 uint32_t res0;
171 uint16_t index;
172 uint16_t num;
173 uint64_t avail;
174 uint64_t used;
a5cf2bb4
CH
175} QEMU_PACKED VqInfoBlock;
176
177typedef struct VqConfigBlock {
178 uint16_t index;
179 uint16_t num_max;
180} QEMU_PACKED VqConfigBlock;
181
182typedef struct VirtioFeatDesc {
183 uint32_t features;
184 uint8_t index;
185} QEMU_PACKED VirtioFeatDesc;
186
7e749462
CH
187typedef struct VirtioThinintInfo {
188 hwaddr summary_indicator;
189 hwaddr device_indicator;
190 uint64_t ind_bit;
191 uint8_t isc;
192} QEMU_PACKED VirtioThinintInfo;
193
c42767f2
TH
194typedef struct VirtioRevInfo {
195 uint16_t revision;
196 uint16_t length;
197 uint8_t data[0];
198} QEMU_PACKED VirtioRevInfo;
199
a5cf2bb4 200/* Specify where the virtqueues for the subchannel are in guest memory. */
0db87e0d
CH
201static int virtio_ccw_set_vqs(SubchDev *sch, VqInfoBlock *info,
202 VqInfoBlockLegacy *linfo)
a5cf2bb4 203{
f24a6840 204 VirtIODevice *vdev = virtio_ccw_get_vdev(sch);
0db87e0d
CH
205 uint16_t index = info ? info->index : linfo->index;
206 uint16_t num = info ? info->num : linfo->num;
207 uint64_t desc = info ? info->desc : linfo->queue;
a5cf2bb4 208
b1914b82 209 if (index >= VIRTIO_QUEUE_MAX) {
a5cf2bb4
CH
210 return -EINVAL;
211 }
212
213 /* Current code in virtio.c relies on 4K alignment. */
0db87e0d 214 if (linfo && desc && (linfo->align != 4096)) {
a5cf2bb4
CH
215 return -EINVAL;
216 }
217
f24a6840 218 if (!vdev) {
a5cf2bb4
CH
219 return -EINVAL;
220 }
221
0db87e0d
CH
222 if (info) {
223 virtio_queue_set_rings(vdev, index, desc, info->avail, info->used);
224 } else {
225 virtio_queue_set_addr(vdev, index, desc);
226 }
227 if (!desc) {
955cc8c9 228 virtio_queue_set_vector(vdev, index, VIRTIO_NO_VECTOR);
a5cf2bb4 229 } else {
79cd0c80
CH
230 if (info) {
231 /* virtio-1 allows changing the ring size. */
8c797e75 232 if (virtio_queue_get_max_num(vdev, index) < num) {
79cd0c80
CH
233 /* Fail if we exceed the maximum number. */
234 return -EINVAL;
235 }
236 virtio_queue_set_num(vdev, index, num);
237 } else if (virtio_queue_get_num(vdev, index) > num) {
238 /* Fail if we don't have a big enough queue. */
a5cf2bb4
CH
239 return -EINVAL;
240 }
79cd0c80 241 /* We ignore possible increased num for legacy for compatibility. */
f24a6840 242 virtio_queue_set_vector(vdev, index, index);
a5cf2bb4
CH
243 }
244 /* tell notify handler in case of config change */
b1914b82 245 vdev->config_vector = VIRTIO_QUEUE_MAX;
a5cf2bb4
CH
246 return 0;
247}
248
fa8b0ca5
CH
249static void virtio_ccw_reset_virtio(VirtioCcwDevice *dev, VirtIODevice *vdev)
250{
b804e8a6
JL
251 CcwDevice *ccw_dev = CCW_DEVICE(dev);
252
fa8b0ca5
CH
253 virtio_ccw_stop_ioeventfd(dev);
254 virtio_reset(vdev);
255 if (dev->indicators) {
256 release_indicator(&dev->routes.adapter, dev->indicators);
257 dev->indicators = NULL;
258 }
259 if (dev->indicators2) {
260 release_indicator(&dev->routes.adapter, dev->indicators2);
261 dev->indicators2 = NULL;
262 }
263 if (dev->summary_indicator) {
264 release_indicator(&dev->routes.adapter, dev->summary_indicator);
265 dev->summary_indicator = NULL;
266 }
b804e8a6 267 ccw_dev->sch->thinint_active = false;
fa8b0ca5
CH
268}
269
0db87e0d
CH
270static int virtio_ccw_handle_set_vq(SubchDev *sch, CCW1 ccw, bool check_len,
271 bool is_legacy)
a5cf2bb4
CH
272{
273 int ret;
274 VqInfoBlock info;
0db87e0d
CH
275 VqInfoBlockLegacy linfo;
276 size_t info_len = is_legacy ? sizeof(linfo) : sizeof(info);
277
278 if (check_len) {
279 if (ccw.count != info_len) {
280 return -EINVAL;
281 }
282 } else if (ccw.count < info_len) {
283 /* Can't execute command. */
284 return -EINVAL;
285 }
286 if (!ccw.cda) {
287 return -EFAULT;
288 }
289 if (is_legacy) {
f57ba058 290 ccw_dstream_read(&sch->cds, linfo);
c9aacaad
PM
291 linfo.queue = be64_to_cpu(linfo.queue);
292 linfo.align = be32_to_cpu(linfo.align);
293 linfo.index = be16_to_cpu(linfo.index);
294 linfo.num = be16_to_cpu(linfo.num);
0db87e0d
CH
295 ret = virtio_ccw_set_vqs(sch, NULL, &linfo);
296 } else {
f57ba058 297 ccw_dstream_read(&sch->cds, info);
c9aacaad
PM
298 info.desc = be64_to_cpu(info.desc);
299 info.index = be16_to_cpu(info.index);
300 info.num = be16_to_cpu(info.num);
301 info.avail = be64_to_cpu(info.avail);
302 info.used = be64_to_cpu(info.used);
0db87e0d
CH
303 ret = virtio_ccw_set_vqs(sch, &info, NULL);
304 }
305 sch->curr_status.scsw.count = 0;
306 return ret;
307}
308
309static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw)
310{
311 int ret;
c42767f2 312 VirtioRevInfo revinfo;
a5cf2bb4
CH
313 uint8_t status;
314 VirtioFeatDesc features;
a5cf2bb4
CH
315 hwaddr indicators;
316 VqConfigBlock vq_config;
317 VirtioCcwDevice *dev = sch->driver_data;
f24a6840 318 VirtIODevice *vdev = virtio_ccw_get_vdev(sch);
a5cf2bb4
CH
319 bool check_len;
320 int len;
f57ba058 321 VirtioThinintInfo thinint;
a5cf2bb4
CH
322
323 if (!dev) {
324 return -EINVAL;
325 }
326
327 trace_virtio_ccw_interpret_ccw(sch->cssid, sch->ssid, sch->schid,
328 ccw.cmd_code);
329 check_len = !((ccw.flags & CCW_FLAG_SLI) && !(ccw.flags & CCW_FLAG_DC));
330
47e13dfd
HP
331 if (dev->force_revision_1 && dev->revision < 0 &&
332 ccw.cmd_code != CCW_CMD_SET_VIRTIO_REV) {
333 /*
334 * virtio-1 drivers must start with negotiating to a revision >= 1,
335 * so post a command reject for all other commands
336 */
337 return -ENOSYS;
338 }
339
a5cf2bb4
CH
340 /* Look at the command. */
341 switch (ccw.cmd_code) {
342 case CCW_CMD_SET_VQ:
0db87e0d 343 ret = virtio_ccw_handle_set_vq(sch, ccw, check_len, dev->revision < 1);
a5cf2bb4
CH
344 break;
345 case CCW_CMD_VDEV_RESET:
fa8b0ca5 346 virtio_ccw_reset_virtio(dev, vdev);
a5cf2bb4
CH
347 ret = 0;
348 break;
349 case CCW_CMD_READ_FEAT:
350 if (check_len) {
351 if (ccw.count != sizeof(features)) {
352 ret = -EINVAL;
353 break;
354 }
355 } else if (ccw.count < sizeof(features)) {
356 /* Can't execute command. */
357 ret = -EINVAL;
358 break;
359 }
360 if (!ccw.cda) {
361 ret = -EFAULT;
362 } else {
9b706dbb
MT
363 VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev);
364
f57ba058
HP
365 ccw_dstream_advance(&sch->cds, sizeof(features.features));
366 ccw_dstream_read(&sch->cds, features.index);
6b8f1020 367 if (features.index == 0) {
542571d5
CH
368 if (dev->revision >= 1) {
369 /* Don't offer legacy features for modern devices. */
370 features.features = (uint32_t)
9b706dbb 371 (vdev->host_features & ~vdc->legacy_features);
542571d5
CH
372 } else {
373 features.features = (uint32_t)vdev->host_features;
374 }
b4f8f9df 375 } else if ((features.index == 1) && (dev->revision >= 1)) {
c42767f2 376 /*
b4f8f9df
CH
377 * Only offer feature bits beyond 31 if the guest has
378 * negotiated at least revision 1.
c42767f2 379 */
b4f8f9df 380 features.features = (uint32_t)(vdev->host_features >> 32);
a5cf2bb4
CH
381 } else {
382 /* Return zeroes if the guest supports more feature bits. */
383 features.features = 0;
384 }
f57ba058 385 ccw_dstream_rewind(&sch->cds);
c9aacaad 386 features.features = cpu_to_le32(features.features);
f57ba058 387 ccw_dstream_write(&sch->cds, features.features);
a5cf2bb4
CH
388 sch->curr_status.scsw.count = ccw.count - sizeof(features);
389 ret = 0;
390 }
391 break;
392 case CCW_CMD_WRITE_FEAT:
393 if (check_len) {
394 if (ccw.count != sizeof(features)) {
395 ret = -EINVAL;
396 break;
397 }
398 } else if (ccw.count < sizeof(features)) {
399 /* Can't execute command. */
400 ret = -EINVAL;
401 break;
402 }
403 if (!ccw.cda) {
404 ret = -EFAULT;
405 } else {
f57ba058 406 ccw_dstream_read(&sch->cds, features);
c9aacaad 407 features.features = le32_to_cpu(features.features);
6b8f1020 408 if (features.index == 0) {
c42767f2
TH
409 virtio_set_features(vdev,
410 (vdev->guest_features & 0xffffffff00000000ULL) |
411 features.features);
b4f8f9df 412 } else if ((features.index == 1) && (dev->revision >= 1)) {
c42767f2 413 /*
b4f8f9df
CH
414 * If the guest did not negotiate at least revision 1,
415 * we did not offer it any feature bits beyond 31. Such a
416 * guest passing us any bit here is therefore buggy.
c42767f2 417 */
c42767f2
TH
418 virtio_set_features(vdev,
419 (vdev->guest_features & 0x00000000ffffffffULL) |
420 ((uint64_t)features.features << 32));
a5cf2bb4
CH
421 } else {
422 /*
423 * If the guest supports more feature bits, assert that it
424 * passes us zeroes for those we don't support.
425 */
426 if (features.features) {
74a69e03
AF
427 qemu_log_mask(LOG_GUEST_ERROR,
428 "Guest bug: features[%i]=%x (expected 0)",
429 features.index, features.features);
a5cf2bb4
CH
430 /* XXX: do a unit check here? */
431 }
432 }
433 sch->curr_status.scsw.count = ccw.count - sizeof(features);
434 ret = 0;
435 }
436 break;
437 case CCW_CMD_READ_CONF:
438 if (check_len) {
f24a6840 439 if (ccw.count > vdev->config_len) {
a5cf2bb4
CH
440 ret = -EINVAL;
441 break;
442 }
443 }
f24a6840 444 len = MIN(ccw.count, vdev->config_len);
a5cf2bb4
CH
445 if (!ccw.cda) {
446 ret = -EFAULT;
447 } else {
f24a6840 448 virtio_bus_get_vdev_config(&dev->bus, vdev->config);
f57ba058 449 ccw_dstream_write_buf(&sch->cds, vdev->config, len);
a5cf2bb4
CH
450 sch->curr_status.scsw.count = ccw.count - len;
451 ret = 0;
452 }
453 break;
454 case CCW_CMD_WRITE_CONF:
455 if (check_len) {
f24a6840 456 if (ccw.count > vdev->config_len) {
a5cf2bb4
CH
457 ret = -EINVAL;
458 break;
459 }
460 }
f24a6840 461 len = MIN(ccw.count, vdev->config_len);
a5cf2bb4
CH
462 if (!ccw.cda) {
463 ret = -EFAULT;
464 } else {
f57ba058
HP
465 ret = ccw_dstream_read_buf(&sch->cds, vdev->config, len);
466 if (!ret) {
f24a6840 467 virtio_bus_set_vdev_config(&dev->bus, vdev->config);
a5cf2bb4 468 sch->curr_status.scsw.count = ccw.count - len;
a5cf2bb4
CH
469 }
470 }
471 break;
e32652f7
PM
472 case CCW_CMD_READ_STATUS:
473 if (check_len) {
474 if (ccw.count != sizeof(status)) {
475 ret = -EINVAL;
476 break;
477 }
478 } else if (ccw.count < sizeof(status)) {
479 /* Can't execute command. */
480 ret = -EINVAL;
481 break;
482 }
483 if (!ccw.cda) {
484 ret = -EFAULT;
485 } else {
486 address_space_stb(&address_space_memory, ccw.cda, vdev->status,
487 MEMTXATTRS_UNSPECIFIED, NULL);
3c254ab8 488 sch->curr_status.scsw.count = ccw.count - sizeof(vdev->status);
e32652f7
PM
489 ret = 0;
490 }
491 break;
a5cf2bb4
CH
492 case CCW_CMD_WRITE_STATUS:
493 if (check_len) {
494 if (ccw.count != sizeof(status)) {
495 ret = -EINVAL;
496 break;
497 }
498 } else if (ccw.count < sizeof(status)) {
499 /* Can't execute command. */
500 ret = -EINVAL;
501 break;
502 }
503 if (!ccw.cda) {
504 ret = -EFAULT;
505 } else {
f57ba058 506 ccw_dstream_read(&sch->cds, status);
b4436a0b
CH
507 if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
508 virtio_ccw_stop_ioeventfd(dev);
509 }
0b352fd6
CH
510 if (virtio_set_status(vdev, status) == 0) {
511 if (vdev->status == 0) {
fa8b0ca5 512 virtio_ccw_reset_virtio(dev, vdev);
0b352fd6
CH
513 }
514 if (status & VIRTIO_CONFIG_S_DRIVER_OK) {
515 virtio_ccw_start_ioeventfd(dev);
516 }
517 sch->curr_status.scsw.count = ccw.count - sizeof(status);
518 ret = 0;
519 } else {
520 /* Trigger a command reject. */
521 ret = -ENOSYS;
b4436a0b 522 }
a5cf2bb4
CH
523 }
524 break;
525 case CCW_CMD_SET_IND:
526 if (check_len) {
527 if (ccw.count != sizeof(indicators)) {
528 ret = -EINVAL;
529 break;
530 }
531 } else if (ccw.count < sizeof(indicators)) {
532 /* Can't execute command. */
533 ret = -EINVAL;
534 break;
535 }
7e749462
CH
536 if (sch->thinint_active) {
537 /* Trigger a command reject. */
538 ret = -ENOSYS;
539 break;
540 }
797b6086
HP
541 if (virtio_get_num_queues(vdev) > NR_CLASSIC_INDICATOR_BITS) {
542 /* More queues than indicator bits --> trigger a reject */
543 ret = -ENOSYS;
544 break;
545 }
d1db1fa8 546 if (!ccw.cda) {
a5cf2bb4
CH
547 ret = -EFAULT;
548 } else {
f57ba058 549 ccw_dstream_read(&sch->cds, indicators);
c9aacaad 550 indicators = be64_to_cpu(indicators);
7bca3892 551 dev->indicators = get_indicator(indicators, sizeof(uint64_t));
a5cf2bb4
CH
552 sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
553 ret = 0;
554 }
555 break;
556 case CCW_CMD_SET_CONF_IND:
557 if (check_len) {
558 if (ccw.count != sizeof(indicators)) {
559 ret = -EINVAL;
560 break;
561 }
562 } else if (ccw.count < sizeof(indicators)) {
563 /* Can't execute command. */
564 ret = -EINVAL;
565 break;
566 }
d1db1fa8 567 if (!ccw.cda) {
a5cf2bb4
CH
568 ret = -EFAULT;
569 } else {
f57ba058 570 ccw_dstream_read(&sch->cds, indicators);
c9aacaad 571 indicators = be64_to_cpu(indicators);
7bca3892 572 dev->indicators2 = get_indicator(indicators, sizeof(uint64_t));
a5cf2bb4
CH
573 sch->curr_status.scsw.count = ccw.count - sizeof(indicators);
574 ret = 0;
575 }
576 break;
577 case CCW_CMD_READ_VQ_CONF:
578 if (check_len) {
579 if (ccw.count != sizeof(vq_config)) {
580 ret = -EINVAL;
581 break;
582 }
583 } else if (ccw.count < sizeof(vq_config)) {
584 /* Can't execute command. */
585 ret = -EINVAL;
586 break;
587 }
588 if (!ccw.cda) {
589 ret = -EFAULT;
590 } else {
f57ba058 591 ccw_dstream_read(&sch->cds, vq_config.index);
c9aacaad 592 vq_config.index = be16_to_cpu(vq_config.index);
b1914b82 593 if (vq_config.index >= VIRTIO_QUEUE_MAX) {
d03a3630
CH
594 ret = -EINVAL;
595 break;
596 }
f24a6840 597 vq_config.num_max = virtio_queue_get_num(vdev,
a5cf2bb4 598 vq_config.index);
c9aacaad 599 vq_config.num_max = cpu_to_be16(vq_config.num_max);
f57ba058 600 ccw_dstream_write(&sch->cds, vq_config.num_max);
a5cf2bb4
CH
601 sch->curr_status.scsw.count = ccw.count - sizeof(vq_config);
602 ret = 0;
603 }
604 break;
7e749462
CH
605 case CCW_CMD_SET_IND_ADAPTER:
606 if (check_len) {
f57ba058 607 if (ccw.count != sizeof(thinint)) {
7e749462
CH
608 ret = -EINVAL;
609 break;
610 }
f57ba058 611 } else if (ccw.count < sizeof(thinint)) {
7e749462
CH
612 /* Can't execute command. */
613 ret = -EINVAL;
614 break;
615 }
7e749462
CH
616 if (!ccw.cda) {
617 ret = -EFAULT;
618 } else if (dev->indicators && !sch->thinint_active) {
619 /* Trigger a command reject. */
620 ret = -ENOSYS;
621 } else {
f57ba058 622 if (ccw_dstream_read(&sch->cds, thinint)) {
7e749462
CH
623 ret = -EFAULT;
624 } else {
c9aacaad
PM
625 thinint.ind_bit = be64_to_cpu(thinint.ind_bit);
626 thinint.summary_indicator =
627 be64_to_cpu(thinint.summary_indicator);
628 thinint.device_indicator =
629 be64_to_cpu(thinint.device_indicator);
7d45285f 630
7bca3892 631 dev->summary_indicator =
f57ba058 632 get_indicator(thinint.summary_indicator, sizeof(uint8_t));
7d45285f 633 dev->indicators =
f57ba058
HP
634 get_indicator(thinint.device_indicator,
635 thinint.ind_bit / 8 + 1);
636 dev->thinint_isc = thinint.isc;
637 dev->routes.adapter.ind_offset = thinint.ind_bit;
d426d9fb 638 dev->routes.adapter.summary_offset = 7;
dde522bb
FL
639 dev->routes.adapter.adapter_id = css_get_adapter_id(
640 CSS_IO_ADAPTER_VIRTIO,
641 dev->thinint_isc);
7bca3892
CH
642 sch->thinint_active = ((dev->indicators != NULL) &&
643 (dev->summary_indicator != NULL));
f57ba058 644 sch->curr_status.scsw.count = ccw.count - sizeof(thinint);
7e749462
CH
645 ret = 0;
646 }
647 }
648 break;
c42767f2
TH
649 case CCW_CMD_SET_VIRTIO_REV:
650 len = sizeof(revinfo);
651 if (ccw.count < len) {
652 ret = -EINVAL;
653 break;
654 }
655 if (!ccw.cda) {
656 ret = -EFAULT;
657 break;
658 }
f57ba058 659 ccw_dstream_read_buf(&sch->cds, &revinfo, 4);
c9aacaad
PM
660 revinfo.revision = be16_to_cpu(revinfo.revision);
661 revinfo.length = be16_to_cpu(revinfo.length);
c42767f2
TH
662 if (ccw.count < len + revinfo.length ||
663 (check_len && ccw.count > len + revinfo.length)) {
664 ret = -EINVAL;
665 break;
666 }
667 /*
668 * Once we start to support revisions with additional data, we'll
669 * need to fetch it here. Nothing to do for now, though.
670 */
671 if (dev->revision >= 0 ||
47e13dfd
HP
672 revinfo.revision > virtio_ccw_rev_max(dev) ||
673 (dev->force_revision_1 && !revinfo.revision)) {
c42767f2
TH
674 ret = -ENOSYS;
675 break;
676 }
677 ret = 0;
678 dev->revision = revinfo.revision;
679 break;
a5cf2bb4 680 default:
8d034a6f 681 ret = -ENOSYS;
a5cf2bb4
CH
682 break;
683 }
684 return ret;
685}
686
c42767f2
TH
687static void virtio_sch_disable_cb(SubchDev *sch)
688{
689 VirtioCcwDevice *dev = sch->driver_data;
690
691 dev->revision = -1;
692}
693
1fa75523 694static void virtio_ccw_device_realize(VirtioCcwDevice *dev, Error **errp)
a5cf2bb4 695{
1fa75523 696 VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
b804e8a6 697 CcwDevice *ccw_dev = CCW_DEVICE(dev);
d8d98db5 698 CCWDeviceClass *ck = CCW_DEVICE_GET_CLASS(ccw_dev);
817d4a6b 699 SubchDev *sch;
cf249935 700 Error *err = NULL;
a5cf2bb4 701
36699ab4 702 sch = css_create_sch(ccw_dev->devno, errp);
cf249935
SS
703 if (!sch) {
704 return;
a5cf2bb4 705 }
47e13dfd
HP
706 if (!virtio_ccw_rev_max(dev) && dev->force_revision_1) {
707 error_setg(&err, "Invalid value of property max_rev "
708 "(is %d expected >= 1)", virtio_ccw_rev_max(dev));
d8d98db5 709 goto out_err;
47e13dfd 710 }
a5cf2bb4 711
cf249935 712 sch->driver_data = dev;
a5cf2bb4 713 sch->ccw_cb = virtio_ccw_cb;
c42767f2 714 sch->disable_cb = virtio_sch_disable_cb;
a5cf2bb4
CH
715 sch->id.reserved = 0xff;
716 sch->id.cu_type = VIRTIO_CCW_CU_TYPE;
bab482d7 717 sch->do_subchannel_work = do_subchannel_work_virtual;
b804e8a6 718 ccw_dev->sch = sch;
cf249935 719 dev->indicators = NULL;
c42767f2 720 dev->revision = -1;
cf249935
SS
721 css_sch_build_virtual_schib(sch, 0, VIRTIO_CCW_CHPID_TYPE);
722
723 trace_virtio_ccw_new_device(
724 sch->cssid, sch->ssid, sch->schid, sch->devno,
2a78ac66 725 ccw_dev->devno.valid ? "user-configured" : "auto-configured");
c42767f2 726
cda3c19f 727 if (kvm_enabled() && !kvm_eventfds_enabled()) {
ca2b413c
PB
728 dev->flags &= ~VIRTIO_CCW_FLAG_USE_IOEVENTFD;
729 }
730
1fa75523
CH
731 if (k->realize) {
732 k->realize(dev, &err);
d8d98db5
DJS
733 if (err) {
734 goto out_err;
735 }
1fa75523 736 }
d8d98db5
DJS
737
738 ck->realize(ccw_dev, &err);
1fa75523 739 if (err) {
d8d98db5 740 goto out_err;
1fa75523 741 }
d8d98db5
DJS
742
743 return;
744
745out_err:
746 error_propagate(errp, err);
747 css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
748 ccw_dev->sch = NULL;
749 g_free(sch);
a5cf2bb4
CH
750}
751
2d6ff33a 752static void virtio_ccw_device_unrealize(VirtioCcwDevice *dev, Error **errp)
a5cf2bb4 753{
2d6ff33a 754 VirtIOCCWDeviceClass *dc = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
b804e8a6
JL
755 CcwDevice *ccw_dev = CCW_DEVICE(dev);
756 SubchDev *sch = ccw_dev->sch;
a5cf2bb4 757
2d6ff33a
TH
758 if (dc->unrealize) {
759 dc->unrealize(dev, errp);
760 }
761
a5cf2bb4
CH
762 if (sch) {
763 css_subch_assign(sch->cssid, sch->ssid, sch->schid, sch->devno, NULL);
764 g_free(sch);
24118af8 765 ccw_dev->sch = NULL;
a5cf2bb4 766 }
7bca3892 767 if (dev->indicators) {
d426d9fb 768 release_indicator(&dev->routes.adapter, dev->indicators);
7bca3892
CH
769 dev->indicators = NULL;
770 }
a5cf2bb4
CH
771}
772
a5cf2bb4
CH
773/* DeviceState to VirtioCcwDevice. Note: used on datapath,
774 * be careful and test performance if you change this.
775 */
776static inline VirtioCcwDevice *to_virtio_ccw_dev_fast(DeviceState *d)
777{
b804e8a6
JL
778 CcwDevice *ccw_dev = to_ccw_dev_fast(d);
779
780 return container_of(ccw_dev, VirtioCcwDevice, parent_obj);
a5cf2bb4
CH
781}
782
7e749462
CH
783static uint8_t virtio_set_ind_atomic(SubchDev *sch, uint64_t ind_loc,
784 uint8_t to_be_set)
785{
786 uint8_t ind_old, ind_new;
787 hwaddr len = 1;
788 uint8_t *ind_addr;
789
790 ind_addr = cpu_physical_memory_map(ind_loc, &len, 1);
791 if (!ind_addr) {
792 error_report("%s(%x.%x.%04x): unable to access indicator",
793 __func__, sch->cssid, sch->ssid, sch->schid);
794 return -1;
795 }
796 do {
797 ind_old = *ind_addr;
798 ind_new = ind_old | to_be_set;
799 } while (atomic_cmpxchg(ind_addr, ind_old, ind_new) != ind_old);
06409bd9 800 trace_virtio_ccw_set_ind(ind_loc, ind_old, ind_new);
7e749462
CH
801 cpu_physical_memory_unmap(ind_addr, len, 1, len);
802
803 return ind_old;
804}
805
a5cf2bb4
CH
806static void virtio_ccw_notify(DeviceState *d, uint16_t vector)
807{
808 VirtioCcwDevice *dev = to_virtio_ccw_dev_fast(d);
b804e8a6
JL
809 CcwDevice *ccw_dev = to_ccw_dev_fast(d);
810 SubchDev *sch = ccw_dev->sch;
a5cf2bb4
CH
811 uint64_t indicators;
812
7a5342e7 813 if (vector == VIRTIO_NO_VECTOR) {
a5cf2bb4
CH
814 return;
815 }
7a5342e7
HP
816 /*
817 * vector < VIRTIO_QUEUE_MAX: notification for a virtqueue
818 * vector == VIRTIO_QUEUE_MAX: configuration change notification
819 * bits beyond that are unused and should never be notified for
820 */
821 assert(vector <= VIRTIO_QUEUE_MAX);
a5cf2bb4 822
b1914b82 823 if (vector < VIRTIO_QUEUE_MAX) {
7c486976
CH
824 if (!dev->indicators) {
825 return;
826 }
7e749462
CH
827 if (sch->thinint_active) {
828 /*
829 * In the adapter interrupt case, indicators points to a
830 * memory area that may be (way) larger than 64 bit and
831 * ind_bit indicates the start of the indicators in a big
832 * endian notation.
833 */
d426d9fb
CH
834 uint64_t ind_bit = dev->routes.adapter.ind_offset;
835
7bca3892 836 virtio_set_ind_atomic(sch, dev->indicators->addr +
d426d9fb
CH
837 (ind_bit + vector) / 8,
838 0x80 >> ((ind_bit + vector) % 8));
7bca3892 839 if (!virtio_set_ind_atomic(sch, dev->summary_indicator->addr,
7e749462 840 0x01)) {
25a08b8d 841 css_adapter_interrupt(CSS_IO_ADAPTER_VIRTIO, dev->thinint_isc);
7e749462
CH
842 }
843 } else {
7a5342e7 844 assert(vector < NR_CLASSIC_INDICATOR_BITS);
42874d3a
PM
845 indicators = address_space_ldq(&address_space_memory,
846 dev->indicators->addr,
847 MEMTXATTRS_UNSPECIFIED,
848 NULL);
7e749462 849 indicators |= 1ULL << vector;
42874d3a
PM
850 address_space_stq(&address_space_memory, dev->indicators->addr,
851 indicators, MEMTXATTRS_UNSPECIFIED, NULL);
7e749462
CH
852 css_conditional_io_interrupt(sch);
853 }
a5cf2bb4 854 } else {
7c486976
CH
855 if (!dev->indicators2) {
856 return;
857 }
42874d3a
PM
858 indicators = address_space_ldq(&address_space_memory,
859 dev->indicators2->addr,
860 MEMTXATTRS_UNSPECIFIED,
861 NULL);
7a5342e7 862 indicators |= 1ULL;
42874d3a
PM
863 address_space_stq(&address_space_memory, dev->indicators2->addr,
864 indicators, MEMTXATTRS_UNSPECIFIED, NULL);
7e749462 865 css_conditional_io_interrupt(sch);
a5cf2bb4 866 }
a5cf2bb4
CH
867}
868
a5cf2bb4
CH
869static void virtio_ccw_reset(DeviceState *d)
870{
871 VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
f24a6840 872 VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
838fb84f 873 VirtIOCCWDeviceClass *vdc = VIRTIO_CCW_DEVICE_GET_CLASS(dev);
a5cf2bb4 874
fa8b0ca5 875 virtio_ccw_reset_virtio(dev, vdev);
838fb84f
CH
876 if (vdc->parent_reset) {
877 vdc->parent_reset(d);
878 }
a5cf2bb4
CH
879}
880
b4436a0b
CH
881static void virtio_ccw_vmstate_change(DeviceState *d, bool running)
882{
883 VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
884
885 if (running) {
886 virtio_ccw_start_ioeventfd(dev);
887 } else {
888 virtio_ccw_stop_ioeventfd(dev);
889 }
890}
891
320ce850
CH
892static bool virtio_ccw_query_guest_notifiers(DeviceState *d)
893{
b804e8a6 894 CcwDevice *dev = CCW_DEVICE(d);
320ce850
CH
895
896 return !!(dev->sch->curr_status.pmcw.flags & PMCW_FLAGS_MASK_ENA);
897}
898
d426d9fb
CH
899static int virtio_ccw_get_mappings(VirtioCcwDevice *dev)
900{
901 int r;
b804e8a6 902 CcwDevice *ccw_dev = CCW_DEVICE(dev);
d426d9fb 903
b804e8a6 904 if (!ccw_dev->sch->thinint_active) {
d426d9fb
CH
905 return -EINVAL;
906 }
907
908 r = map_indicator(&dev->routes.adapter, dev->summary_indicator);
909 if (r) {
910 return r;
911 }
912 r = map_indicator(&dev->routes.adapter, dev->indicators);
913 if (r) {
914 return r;
915 }
916 dev->routes.adapter.summary_addr = dev->summary_indicator->map;
917 dev->routes.adapter.ind_addr = dev->indicators->map;
918
919 return 0;
920}
921
922static int virtio_ccw_setup_irqroutes(VirtioCcwDevice *dev, int nvqs)
923{
924 int i;
925 VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
926 int ret;
927 S390FLICState *fs = s390_get_flic();
6762808f 928 S390FLICStateClass *fsc = s390_get_flic_class(fs);
d426d9fb
CH
929
930 ret = virtio_ccw_get_mappings(dev);
931 if (ret) {
932 return ret;
933 }
934 for (i = 0; i < nvqs; i++) {
935 if (!virtio_queue_get_num(vdev, i)) {
936 break;
937 }
938 }
939 dev->routes.num_routes = i;
940 return fsc->add_adapter_routes(fs, &dev->routes);
941}
942
943static void virtio_ccw_release_irqroutes(VirtioCcwDevice *dev, int nvqs)
944{
945 S390FLICState *fs = s390_get_flic();
6762808f 946 S390FLICStateClass *fsc = s390_get_flic_class(fs);
d426d9fb
CH
947
948 fsc->release_adapter_routes(fs, &dev->routes);
949}
950
951static int virtio_ccw_add_irqfd(VirtioCcwDevice *dev, int n)
952{
953 VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
954 VirtQueue *vq = virtio_get_queue(vdev, n);
955 EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
956
1c9b71a7
EA
957 return kvm_irqchip_add_irqfd_notifier_gsi(kvm_state, notifier, NULL,
958 dev->routes.gsi[n]);
d426d9fb
CH
959}
960
961static void virtio_ccw_remove_irqfd(VirtioCcwDevice *dev, int n)
962{
963 VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
964 VirtQueue *vq = virtio_get_queue(vdev, n);
965 EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
966 int ret;
967
1c9b71a7
EA
968 ret = kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, notifier,
969 dev->routes.gsi[n]);
d426d9fb
CH
970 assert(ret == 0);
971}
972
320ce850
CH
973static int virtio_ccw_set_guest_notifier(VirtioCcwDevice *dev, int n,
974 bool assign, bool with_irqfd)
975{
f24a6840
PB
976 VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
977 VirtQueue *vq = virtio_get_queue(vdev, n);
320ce850 978 EventNotifier *notifier = virtio_queue_get_guest_notifier(vq);
f24a6840 979 VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev);
320ce850
CH
980
981 if (assign) {
982 int r = event_notifier_init(notifier, 0);
983
984 if (r < 0) {
985 return r;
986 }
987 virtio_queue_set_guest_notifier_fd_handler(vq, true, with_irqfd);
d426d9fb
CH
988 if (with_irqfd) {
989 r = virtio_ccw_add_irqfd(dev, n);
990 if (r) {
991 virtio_queue_set_guest_notifier_fd_handler(vq, false,
992 with_irqfd);
993 return r;
994 }
995 }
996 /*
997 * We do not support individual masking for channel devices, so we
998 * need to manually trigger any guest masking callbacks here.
320ce850 999 */
2858bc68 1000 if (k->guest_notifier_mask && vdev->use_guest_notifier_mask) {
f24a6840 1001 k->guest_notifier_mask(vdev, n, false);
320ce850
CH
1002 }
1003 /* get lost events and re-inject */
1004 if (k->guest_notifier_pending &&
f24a6840 1005 k->guest_notifier_pending(vdev, n)) {
320ce850
CH
1006 event_notifier_set(notifier);
1007 }
1008 } else {
2858bc68 1009 if (k->guest_notifier_mask && vdev->use_guest_notifier_mask) {
f24a6840 1010 k->guest_notifier_mask(vdev, n, true);
320ce850 1011 }
d426d9fb
CH
1012 if (with_irqfd) {
1013 virtio_ccw_remove_irqfd(dev, n);
1014 }
320ce850
CH
1015 virtio_queue_set_guest_notifier_fd_handler(vq, false, with_irqfd);
1016 event_notifier_cleanup(notifier);
1017 }
1018 return 0;
1019}
1020
1021static int virtio_ccw_set_guest_notifiers(DeviceState *d, int nvqs,
1022 bool assigned)
1023{
1024 VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
f24a6840 1025 VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
b804e8a6
JL
1026 CcwDevice *ccw_dev = CCW_DEVICE(d);
1027 bool with_irqfd = ccw_dev->sch->thinint_active && kvm_irqfds_enabled();
320ce850
CH
1028 int r, n;
1029
d426d9fb
CH
1030 if (with_irqfd && assigned) {
1031 /* irq routes need to be set up before assigning irqfds */
1032 r = virtio_ccw_setup_irqroutes(dev, nvqs);
1033 if (r < 0) {
1034 goto irqroute_error;
1035 }
1036 }
320ce850
CH
1037 for (n = 0; n < nvqs; n++) {
1038 if (!virtio_queue_get_num(vdev, n)) {
1039 break;
1040 }
d426d9fb 1041 r = virtio_ccw_set_guest_notifier(dev, n, assigned, with_irqfd);
320ce850
CH
1042 if (r < 0) {
1043 goto assign_error;
1044 }
1045 }
d426d9fb
CH
1046 if (with_irqfd && !assigned) {
1047 /* release irq routes after irqfds have been released */
1048 virtio_ccw_release_irqroutes(dev, nvqs);
1049 }
320ce850
CH
1050 return 0;
1051
1052assign_error:
1053 while (--n >= 0) {
1054 virtio_ccw_set_guest_notifier(dev, n, !assigned, false);
1055 }
d426d9fb
CH
1056irqroute_error:
1057 if (with_irqfd && assigned) {
1058 virtio_ccw_release_irqroutes(dev, nvqs);
1059 }
320ce850
CH
1060 return r;
1061}
1062
bcb2b582
JF
1063static void virtio_ccw_save_queue(DeviceState *d, int n, QEMUFile *f)
1064{
1065 VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
1066 VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
1067
1068 qemu_put_be16(f, virtio_queue_vector(vdev, n));
1069}
1070
1071static int virtio_ccw_load_queue(DeviceState *d, int n, QEMUFile *f)
1072{
1073 VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
1074 VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
1075 uint16_t vector;
1076
1077 qemu_get_be16s(f, &vector);
1078 virtio_queue_set_vector(vdev, n , vector);
1079
1080 return 0;
1081}
1082
1083static void virtio_ccw_save_config(DeviceState *d, QEMUFile *f)
1084{
1085 VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
517ff12c 1086 vmstate_save_state(f, &vmstate_virtio_ccw_dev, dev, NULL);
bcb2b582
JF
1087}
1088
1089static int virtio_ccw_load_config(DeviceState *d, QEMUFile *f)
1090{
1091 VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
517ff12c 1092 return vmstate_load_state(f, &vmstate_virtio_ccw_dev, dev, 1);
bcb2b582
JF
1093}
1094
d1b4259f
MC
1095static void virtio_ccw_pre_plugged(DeviceState *d, Error **errp)
1096{
1097 VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
1098 VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
1099
1100 if (dev->max_rev >= 1) {
1101 virtio_add_feature(&vdev->host_features, VIRTIO_F_VERSION_1);
1102 }
1103}
1104
fb846a09 1105/* This is called by virtio-bus just after the device is plugged. */
e8398045 1106static void virtio_ccw_device_plugged(DeviceState *d, Error **errp)
fb846a09
CH
1107{
1108 VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
10ceaa1e 1109 VirtIODevice *vdev = virtio_bus_get_device(&dev->bus);
b804e8a6
JL
1110 CcwDevice *ccw_dev = CCW_DEVICE(d);
1111 SubchDev *sch = ccw_dev->sch;
10ceaa1e 1112 int n = virtio_get_num_queues(vdev);
0708afa7 1113 S390FLICState *flic = s390_get_flic();
10ceaa1e 1114
d1b4259f
MC
1115 if (!virtio_has_feature(vdev->host_features, VIRTIO_F_VERSION_1)) {
1116 dev->max_rev = 0;
1117 }
1118
b1914b82 1119 if (virtio_get_num_queues(vdev) > VIRTIO_QUEUE_MAX) {
b34aee54 1120 error_setg(errp, "The number of virtqueues %d "
b1914b82
HP
1121 "exceeds virtio limit %d", n,
1122 VIRTIO_QUEUE_MAX);
10ceaa1e
JW
1123 return;
1124 }
0708afa7
HP
1125 if (virtio_get_num_queues(vdev) > flic->adapter_routes_max_batch) {
1126 error_setg(errp, "The number of virtqueues %d "
1127 "exceeds flic adapter route limit %d", n,
1128 flic->adapter_routes_max_batch);
1129 return;
1130 }
fb846a09
CH
1131
1132 sch->id.cu_model = virtio_bus_get_vdev_id(&dev->bus);
1133
542571d5 1134
fb846a09
CH
1135 css_generate_sch_crws(sch->cssid, sch->ssid, sch->schid,
1136 d->hotplugged, 1);
1137}
1138
1139static void virtio_ccw_device_unplugged(DeviceState *d)
1140{
1141 VirtioCcwDevice *dev = VIRTIO_CCW_DEVICE(d);
1142
1143 virtio_ccw_stop_ioeventfd(dev);
1144}
a5cf2bb4
CH
1145/**************** Virtio-ccw Bus Device Descriptions *******************/
1146
5e5ced38 1147static void virtio_ccw_busdev_realize(DeviceState *dev, Error **errp)
a5cf2bb4
CH
1148{
1149 VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev;
a5cf2bb4 1150
1bf4d7aa 1151 virtio_ccw_bus_new(&_dev->bus, sizeof(_dev->bus), _dev);
1fa75523 1152 virtio_ccw_device_realize(_dev, errp);
a5cf2bb4
CH
1153}
1154
24118af8 1155static void virtio_ccw_busdev_unrealize(DeviceState *dev, Error **errp)
a5cf2bb4
CH
1156{
1157 VirtioCcwDevice *_dev = (VirtioCcwDevice *)dev;
a5cf2bb4 1158
2d6ff33a 1159 virtio_ccw_device_unrealize(_dev, errp);
a5cf2bb4
CH
1160}
1161
b804e8a6
JL
1162static void virtio_ccw_busdev_unplug(HotplugHandler *hotplug_dev,
1163 DeviceState *dev, Error **errp)
a5cf2bb4 1164{
b804e8a6 1165 VirtioCcwDevice *_dev = to_virtio_ccw_dev_fast(dev);
a5cf2bb4 1166
0b81c1ef 1167 virtio_ccw_stop_ioeventfd(_dev);
a5cf2bb4
CH
1168}
1169
1170static void virtio_ccw_device_class_init(ObjectClass *klass, void *data)
1171{
1172 DeviceClass *dc = DEVICE_CLASS(klass);
b804e8a6 1173 CCWDeviceClass *k = CCW_DEVICE_CLASS(dc);
838fb84f 1174 VirtIOCCWDeviceClass *vdc = VIRTIO_CCW_DEVICE_CLASS(klass);
a5cf2bb4 1175
b804e8a6 1176 k->unplug = virtio_ccw_busdev_unplug;
5e5ced38 1177 dc->realize = virtio_ccw_busdev_realize;
24118af8 1178 dc->unrealize = virtio_ccw_busdev_unrealize;
a5cf2bb4 1179 dc->bus_type = TYPE_VIRTUAL_CSS_BUS;
838fb84f 1180 device_class_set_parent_reset(dc, virtio_ccw_reset, &vdc->parent_reset);
a5cf2bb4
CH
1181}
1182
1183static const TypeInfo virtio_ccw_device_info = {
1184 .name = TYPE_VIRTIO_CCW_DEVICE,
b804e8a6 1185 .parent = TYPE_CCW_DEVICE,
a5cf2bb4
CH
1186 .instance_size = sizeof(VirtioCcwDevice),
1187 .class_init = virtio_ccw_device_class_init,
1188 .class_size = sizeof(VirtIOCCWDeviceClass),
1189 .abstract = true,
1190};
1191
a5cf2bb4
CH
1192/* virtio-ccw-bus */
1193
1bf4d7aa
AF
1194static void virtio_ccw_bus_new(VirtioBusState *bus, size_t bus_size,
1195 VirtioCcwDevice *dev)
a5cf2bb4
CH
1196{
1197 DeviceState *qdev = DEVICE(dev);
f4dd69aa 1198 char virtio_bus_name[] = "virtio-bus";
a5cf2bb4 1199
fb17dfe0
AF
1200 qbus_create_inplace(bus, bus_size, TYPE_VIRTIO_CCW_BUS,
1201 qdev, virtio_bus_name);
a5cf2bb4
CH
1202}
1203
1204static void virtio_ccw_bus_class_init(ObjectClass *klass, void *data)
1205{
1206 VirtioBusClass *k = VIRTIO_BUS_CLASS(klass);
1207 BusClass *bus_class = BUS_CLASS(klass);
1208
1209 bus_class->max_dev = 1;
1210 k->notify = virtio_ccw_notify;
b4436a0b 1211 k->vmstate_change = virtio_ccw_vmstate_change;
320ce850 1212 k->query_guest_notifiers = virtio_ccw_query_guest_notifiers;
320ce850 1213 k->set_guest_notifiers = virtio_ccw_set_guest_notifiers;
bcb2b582
JF
1214 k->save_queue = virtio_ccw_save_queue;
1215 k->load_queue = virtio_ccw_load_queue;
1216 k->save_config = virtio_ccw_save_config;
1217 k->load_config = virtio_ccw_load_config;
d1b4259f 1218 k->pre_plugged = virtio_ccw_pre_plugged;
fb846a09
CH
1219 k->device_plugged = virtio_ccw_device_plugged;
1220 k->device_unplugged = virtio_ccw_device_unplugged;
8e93cef1 1221 k->ioeventfd_enabled = virtio_ccw_ioeventfd_enabled;
7c55f68a 1222 k->ioeventfd_assign = virtio_ccw_ioeventfd_assign;
a5cf2bb4
CH
1223}
1224
1225static const TypeInfo virtio_ccw_bus_info = {
1226 .name = TYPE_VIRTIO_CCW_BUS,
1227 .parent = TYPE_VIRTIO_BUS,
1228 .instance_size = sizeof(VirtioCcwBusState),
1229 .class_init = virtio_ccw_bus_class_init,
1230};
1231
1232static void virtio_ccw_register(void)
1233{
1234 type_register_static(&virtio_ccw_bus_info);
a5cf2bb4 1235 type_register_static(&virtio_ccw_device_info);
a5cf2bb4
CH
1236}
1237
1238type_init(virtio_ccw_register)