]> Git Repo - qemu.git/blob - hw/s390-virtio-bus.c
Merge remote-tracking branch 'qmp/queue/qmp' into staging
[qemu.git] / hw / s390-virtio-bus.c
1 /*
2  * QEMU S390 virtio target
3  *
4  * Copyright (c) 2009 Alexander Graf <[email protected]>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "hw.h"
21 #include "block.h"
22 #include "sysemu.h"
23 #include "net.h"
24 #include "boards.h"
25 #include "monitor.h"
26 #include "loader.h"
27 #include "elf.h"
28 #include "hw/virtio.h"
29 #include "hw/virtio-serial.h"
30 #include "hw/virtio-net.h"
31 #include "hw/sysbus.h"
32 #include "kvm.h"
33
34 #include "hw/s390-virtio-bus.h"
35
36 /* #define DEBUG_S390 */
37
38 #ifdef DEBUG_S390
39 #define dprintf(fmt, ...) \
40     do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0)
41 #else
42 #define dprintf(fmt, ...) \
43     do { } while (0)
44 #endif
45
46 #define VIRTIO_EXT_CODE   0x2603
47
48 static const TypeInfo s390_virtio_bus_info = {
49     .name = TYPE_S390_VIRTIO_BUS,
50     .parent = TYPE_BUS,
51     .instance_size = sizeof(VirtIOS390Bus),
52 };
53
54 static const VirtIOBindings virtio_s390_bindings;
55
56 static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev);
57
58 /* length of VirtIO device pages */
59 const target_phys_addr_t virtio_size = S390_DEVICE_PAGES * TARGET_PAGE_SIZE;
60
61 static void s390_virtio_bus_reset(void *opaque)
62 {
63     VirtIOS390Bus *bus = opaque;
64     bus->next_ring = bus->dev_page + TARGET_PAGE_SIZE;
65 }
66
67 void s390_virtio_reset_idx(VirtIOS390Device *dev)
68 {
69     int i;
70     target_phys_addr_t idx_addr;
71     uint8_t num_vq;
72
73     num_vq = s390_virtio_device_num_vq(dev);
74     for (i = 0; i < num_vq; i++) {
75         idx_addr = virtio_queue_get_avail_addr(dev->vdev, i) +
76             VIRTIO_VRING_AVAIL_IDX_OFFS;
77         stw_phys(idx_addr, 0);
78         idx_addr = virtio_queue_get_used_addr(dev->vdev, i) +
79             VIRTIO_VRING_USED_IDX_OFFS;
80         stw_phys(idx_addr, 0);
81     }
82 }
83
84 VirtIOS390Bus *s390_virtio_bus_init(ram_addr_t *ram_size)
85 {
86     VirtIOS390Bus *bus;
87     BusState *_bus;
88     DeviceState *dev;
89
90     /* Create bridge device */
91     dev = qdev_create(NULL, "s390-virtio-bridge");
92     qdev_init_nofail(dev);
93
94     /* Create bus on bridge device */
95
96     _bus = qbus_create(TYPE_S390_VIRTIO_BUS, dev, "s390-virtio");
97     bus = DO_UPCAST(VirtIOS390Bus, bus, _bus);
98
99     bus->dev_page = *ram_size;
100     bus->dev_offs = bus->dev_page;
101     bus->next_ring = bus->dev_page + TARGET_PAGE_SIZE;
102
103     /* Enable hotplugging */
104     _bus->allow_hotplug = 1;
105
106     /* Allocate RAM for VirtIO device pages (descriptors, queues, rings) */
107     *ram_size += S390_DEVICE_PAGES * TARGET_PAGE_SIZE;
108
109     qemu_register_reset(s390_virtio_bus_reset, bus);
110     return bus;
111 }
112
113 static void s390_virtio_irq(CPUS390XState *env, int config_change, uint64_t token)
114 {
115     if (kvm_enabled()) {
116         kvm_s390_virtio_irq(env, config_change, token);
117     } else {
118         cpu_inject_ext(env, VIRTIO_EXT_CODE, config_change, token);
119     }
120 }
121
122 static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
123 {
124     VirtIOS390Bus *bus;
125     int dev_len;
126
127     bus = DO_UPCAST(VirtIOS390Bus, bus, dev->qdev.parent_bus);
128     dev->vdev = vdev;
129     dev->dev_offs = bus->dev_offs;
130     dev->feat_len = sizeof(uint32_t); /* always keep 32 bits features */
131
132     dev_len = VIRTIO_DEV_OFFS_CONFIG;
133     dev_len += s390_virtio_device_num_vq(dev) * VIRTIO_VQCONFIG_LEN;
134     dev_len += dev->feat_len * 2;
135     dev_len += vdev->config_len;
136
137     bus->dev_offs += dev_len;
138
139     virtio_bind_device(vdev, &virtio_s390_bindings, dev);
140     dev->host_features = vdev->get_features(vdev, dev->host_features);
141     s390_virtio_device_sync(dev);
142     s390_virtio_reset_idx(dev);
143     if (dev->qdev.hotplugged) {
144         S390CPU *cpu = s390_cpu_addr2state(0);
145         CPUS390XState *env = &cpu->env;
146         s390_virtio_irq(env, VIRTIO_PARAM_DEV_ADD, dev->dev_offs);
147     }
148
149     return 0;
150 }
151
152 static int s390_virtio_net_init(VirtIOS390Device *dev)
153 {
154     VirtIODevice *vdev;
155
156     vdev = virtio_net_init((DeviceState *)dev, &dev->nic, &dev->net);
157     if (!vdev) {
158         return -1;
159     }
160
161     return s390_virtio_device_init(dev, vdev);
162 }
163
164 static int s390_virtio_blk_init(VirtIOS390Device *dev)
165 {
166     VirtIODevice *vdev;
167
168     vdev = virtio_blk_init((DeviceState *)dev, &dev->blk);
169     if (!vdev) {
170         return -1;
171     }
172
173     return s390_virtio_device_init(dev, vdev);
174 }
175
176 static int s390_virtio_serial_init(VirtIOS390Device *dev)
177 {
178     VirtIOS390Bus *bus;
179     VirtIODevice *vdev;
180     int r;
181
182     bus = DO_UPCAST(VirtIOS390Bus, bus, dev->qdev.parent_bus);
183
184     vdev = virtio_serial_init((DeviceState *)dev, &dev->serial);
185     if (!vdev) {
186         return -1;
187     }
188
189     r = s390_virtio_device_init(dev, vdev);
190     if (!r) {
191         bus->console = dev;
192     }
193
194     return r;
195 }
196
197 static int s390_virtio_scsi_init(VirtIOS390Device *dev)
198 {
199     VirtIODevice *vdev;
200
201     vdev = virtio_scsi_init((DeviceState *)dev, &dev->scsi);
202     if (!vdev) {
203         return -1;
204     }
205
206     return s390_virtio_device_init(dev, vdev);
207 }
208
209 static uint64_t s390_virtio_device_vq_token(VirtIOS390Device *dev, int vq)
210 {
211     ram_addr_t token_off;
212
213     token_off = (dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG) +
214                 (vq * VIRTIO_VQCONFIG_LEN) +
215                 VIRTIO_VQCONFIG_OFFS_TOKEN;
216
217     return ldq_be_phys(token_off);
218 }
219
220 static ram_addr_t s390_virtio_device_num_vq(VirtIOS390Device *dev)
221 {
222     VirtIODevice *vdev = dev->vdev;
223     int num_vq;
224
225     for (num_vq = 0; num_vq < VIRTIO_PCI_QUEUE_MAX; num_vq++) {
226         if (!virtio_queue_get_num(vdev, num_vq)) {
227             break;
228         }
229     }
230
231     return num_vq;
232 }
233
234 static ram_addr_t s390_virtio_next_ring(VirtIOS390Bus *bus)
235 {
236     ram_addr_t r = bus->next_ring;
237
238     bus->next_ring += VIRTIO_RING_LEN;
239     return r;
240 }
241
242 void s390_virtio_device_sync(VirtIOS390Device *dev)
243 {
244     VirtIOS390Bus *bus = DO_UPCAST(VirtIOS390Bus, bus, dev->qdev.parent_bus);
245     ram_addr_t cur_offs;
246     uint8_t num_vq;
247     int i;
248
249     virtio_reset(dev->vdev);
250
251     /* Sync dev space */
252     stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_TYPE, dev->vdev->device_id);
253
254     stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, s390_virtio_device_num_vq(dev));
255     stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_FEATURE_LEN, dev->feat_len);
256
257     stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG_LEN, dev->vdev->config_len);
258
259     num_vq = s390_virtio_device_num_vq(dev);
260     stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_NUM_VQ, num_vq);
261
262     /* Sync virtqueues */
263     for (i = 0; i < num_vq; i++) {
264         ram_addr_t vq = (dev->dev_offs + VIRTIO_DEV_OFFS_CONFIG) +
265                         (i * VIRTIO_VQCONFIG_LEN);
266         ram_addr_t vring;
267
268         vring = s390_virtio_next_ring(bus);
269         virtio_queue_set_addr(dev->vdev, i, vring);
270         virtio_queue_set_vector(dev->vdev, i, i);
271         stq_be_phys(vq + VIRTIO_VQCONFIG_OFFS_ADDRESS, vring);
272         stw_be_phys(vq + VIRTIO_VQCONFIG_OFFS_NUM, virtio_queue_get_num(dev->vdev, i));
273     }
274
275     cur_offs = dev->dev_offs;
276     cur_offs += VIRTIO_DEV_OFFS_CONFIG;
277     cur_offs += num_vq * VIRTIO_VQCONFIG_LEN;
278
279     /* Sync feature bitmap */
280     stl_le_phys(cur_offs, dev->host_features);
281
282     dev->feat_offs = cur_offs + dev->feat_len;
283     cur_offs += dev->feat_len * 2;
284
285     /* Sync config space */
286     if (dev->vdev->get_config) {
287         dev->vdev->get_config(dev->vdev, dev->vdev->config);
288     }
289
290     cpu_physical_memory_write(cur_offs,
291                               dev->vdev->config, dev->vdev->config_len);
292     cur_offs += dev->vdev->config_len;
293 }
294
295 void s390_virtio_device_update_status(VirtIOS390Device *dev)
296 {
297     VirtIODevice *vdev = dev->vdev;
298     uint32_t features;
299
300     virtio_set_status(vdev, ldub_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS));
301
302     /* Update guest supported feature bitmap */
303
304     features = bswap32(ldl_be_phys(dev->feat_offs));
305     virtio_set_features(vdev, features);
306 }
307
308 VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus)
309 {
310     return bus->console;
311 }
312
313 /* Find a device by vring address */
314 VirtIOS390Device *s390_virtio_bus_find_vring(VirtIOS390Bus *bus,
315                                              ram_addr_t mem,
316                                              int *vq_num)
317 {
318     BusChild *kid;
319     int i;
320
321     QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
322         VirtIOS390Device *dev = (VirtIOS390Device *)kid->child;
323
324         for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
325             if (!virtio_queue_get_addr(dev->vdev, i))
326                 break;
327             if (virtio_queue_get_addr(dev->vdev, i) == mem) {
328                 if (vq_num) {
329                     *vq_num = i;
330                 }
331                 return dev;
332             }
333         }
334     }
335
336     return NULL;
337 }
338
339 /* Find a device by device descriptor location */
340 VirtIOS390Device *s390_virtio_bus_find_mem(VirtIOS390Bus *bus, ram_addr_t mem)
341 {
342     BusChild *kid;
343
344     QTAILQ_FOREACH(kid, &bus->bus.children, sibling) {
345         VirtIOS390Device *dev = (VirtIOS390Device *)kid->child;
346         if (dev->dev_offs == mem) {
347             return dev;
348         }
349     }
350
351     return NULL;
352 }
353
354 static void virtio_s390_notify(void *opaque, uint16_t vector)
355 {
356     VirtIOS390Device *dev = (VirtIOS390Device*)opaque;
357     uint64_t token = s390_virtio_device_vq_token(dev, vector);
358     S390CPU *cpu = s390_cpu_addr2state(0);
359     CPUS390XState *env = &cpu->env;
360
361     s390_virtio_irq(env, 0, token);
362 }
363
364 static unsigned virtio_s390_get_features(void *opaque)
365 {
366     VirtIOS390Device *dev = (VirtIOS390Device*)opaque;
367     return dev->host_features;
368 }
369
370 /**************** S390 Virtio Bus Device Descriptions *******************/
371
372 static const VirtIOBindings virtio_s390_bindings = {
373     .notify = virtio_s390_notify,
374     .get_features = virtio_s390_get_features,
375 };
376
377 static Property s390_virtio_net_properties[] = {
378     DEFINE_NIC_PROPERTIES(VirtIOS390Device, nic),
379     DEFINE_PROP_UINT32("x-txtimer", VirtIOS390Device,
380                        net.txtimer, TX_TIMER_INTERVAL),
381     DEFINE_PROP_INT32("x-txburst", VirtIOS390Device,
382                       net.txburst, TX_BURST),
383     DEFINE_PROP_STRING("tx", VirtIOS390Device, net.tx),
384     DEFINE_PROP_END_OF_LIST(),
385 };
386
387 static void s390_virtio_net_class_init(ObjectClass *klass, void *data)
388 {
389     DeviceClass *dc = DEVICE_CLASS(klass);
390     VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
391
392     k->init = s390_virtio_net_init;
393     dc->props = s390_virtio_net_properties;
394 }
395
396 static TypeInfo s390_virtio_net = {
397     .name          = "virtio-net-s390",
398     .parent        = TYPE_VIRTIO_S390_DEVICE,
399     .instance_size = sizeof(VirtIOS390Device),
400     .class_init    = s390_virtio_net_class_init,
401 };
402
403 static Property s390_virtio_blk_properties[] = {
404     DEFINE_BLOCK_PROPERTIES(VirtIOS390Device, blk.conf),
405     DEFINE_BLOCK_CHS_PROPERTIES(VirtIOS390Device, blk.conf),
406     DEFINE_PROP_STRING("serial", VirtIOS390Device, blk.serial),
407 #ifdef __linux__
408     DEFINE_PROP_BIT("scsi", VirtIOS390Device, blk.scsi, 0, true),
409 #endif
410     DEFINE_PROP_END_OF_LIST(),
411 };
412
413 static void s390_virtio_blk_class_init(ObjectClass *klass, void *data)
414 {
415     DeviceClass *dc = DEVICE_CLASS(klass);
416     VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
417
418     k->init = s390_virtio_blk_init;
419     dc->props = s390_virtio_blk_properties;
420 }
421
422 static TypeInfo s390_virtio_blk = {
423     .name          = "virtio-blk-s390",
424     .parent        = TYPE_VIRTIO_S390_DEVICE,
425     .instance_size = sizeof(VirtIOS390Device),
426     .class_init    = s390_virtio_blk_class_init,
427 };
428
429 static Property s390_virtio_serial_properties[] = {
430     DEFINE_PROP_UINT32("max_ports", VirtIOS390Device,
431                        serial.max_virtserial_ports, 31),
432     DEFINE_PROP_END_OF_LIST(),
433 };
434
435 static void s390_virtio_serial_class_init(ObjectClass *klass, void *data)
436 {
437     DeviceClass *dc = DEVICE_CLASS(klass);
438     VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
439
440     k->init = s390_virtio_serial_init;
441     dc->props = s390_virtio_serial_properties;
442 }
443
444 static TypeInfo s390_virtio_serial = {
445     .name          = "virtio-serial-s390",
446     .parent        = TYPE_VIRTIO_S390_DEVICE,
447     .instance_size = sizeof(VirtIOS390Device),
448     .class_init    = s390_virtio_serial_class_init,
449 };
450
451 static int s390_virtio_busdev_init(DeviceState *dev)
452 {
453     VirtIOS390Device *_dev = (VirtIOS390Device *)dev;
454     VirtIOS390DeviceClass *_info = VIRTIO_S390_DEVICE_GET_CLASS(dev);
455
456     return _info->init(_dev);
457 }
458
459 static void virtio_s390_device_class_init(ObjectClass *klass, void *data)
460 {
461     DeviceClass *dc = DEVICE_CLASS(klass);
462
463     dc->init = s390_virtio_busdev_init;
464     dc->bus_type = TYPE_S390_VIRTIO_BUS;
465     dc->unplug = qdev_simple_unplug_cb;
466 }
467
468 static TypeInfo virtio_s390_device_info = {
469     .name = TYPE_VIRTIO_S390_DEVICE,
470     .parent = TYPE_DEVICE,
471     .instance_size = sizeof(VirtIOS390Device),
472     .class_init = virtio_s390_device_class_init,
473     .class_size = sizeof(VirtIOS390DeviceClass),
474     .abstract = true,
475 };
476
477 static Property s390_virtio_scsi_properties[] = {
478     DEFINE_VIRTIO_SCSI_PROPERTIES(VirtIOS390Device, host_features, scsi),
479     DEFINE_PROP_END_OF_LIST(),
480 };
481
482 static void s390_virtio_scsi_class_init(ObjectClass *klass, void *data)
483 {
484     DeviceClass *dc = DEVICE_CLASS(klass);
485     VirtIOS390DeviceClass *k = VIRTIO_S390_DEVICE_CLASS(klass);
486
487     k->init = s390_virtio_scsi_init;
488     dc->props = s390_virtio_scsi_properties;
489 }
490
491 static TypeInfo s390_virtio_scsi = {
492     .name          = "virtio-scsi-s390",
493     .parent        = TYPE_VIRTIO_S390_DEVICE,
494     .instance_size = sizeof(VirtIOS390Device),
495     .class_init    = s390_virtio_scsi_class_init,
496 };
497
498 /***************** S390 Virtio Bus Bridge Device *******************/
499 /* Only required to have the virtio bus as child in the system bus */
500
501 static int s390_virtio_bridge_init(SysBusDevice *dev)
502 {
503     /* nothing */
504     return 0;
505 }
506
507 static void s390_virtio_bridge_class_init(ObjectClass *klass, void *data)
508 {
509     DeviceClass *dc = DEVICE_CLASS(klass);
510     SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
511
512     k->init = s390_virtio_bridge_init;
513     dc->no_user = 1;
514 }
515
516 static TypeInfo s390_virtio_bridge_info = {
517     .name          = "s390-virtio-bridge",
518     .parent        = TYPE_SYS_BUS_DEVICE,
519     .instance_size = sizeof(SysBusDevice),
520     .class_init    = s390_virtio_bridge_class_init,
521 };
522
523 static void s390_virtio_register_types(void)
524 {
525     type_register_static(&s390_virtio_bus_info);
526     type_register_static(&virtio_s390_device_info);
527     type_register_static(&s390_virtio_serial);
528     type_register_static(&s390_virtio_blk);
529     type_register_static(&s390_virtio_net);
530     type_register_static(&s390_virtio_scsi);
531     type_register_static(&s390_virtio_bridge_info);
532 }
533
534 type_init(s390_virtio_register_types)
This page took 0.053901 seconds and 4 git commands to generate.