Statistics
| Branch: | Revision:

root / hw / s390-virtio-bus.c @ a8170e5e

History | View | Annotate | Download (14.6 kB)

1
/*
2
 * QEMU S390 virtio target
3
 *
4
 * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
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 hwaddr 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
    hwaddr 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)