Statistics
| Branch: | Revision:

root / qdev-monitor.c @ d1a0cf73

History | View | Annotate | Download (18 kB)

1
/*
2
 *  Dynamic device configuration and creation.
3
 *
4
 *  Copyright (c) 2009 CodeSourcery
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/qdev.h"
21
#include "monitor/monitor.h"
22
#include "monitor/qdev.h"
23
#include "qmp-commands.h"
24
#include "sysemu/arch_init.h"
25
#include "qemu/config-file.h"
26

    
27
/*
28
 * Aliases were a bad idea from the start.  Let's keep them
29
 * from spreading further.
30
 */
31
typedef struct QDevAlias
32
{
33
    const char *typename;
34
    const char *alias;
35
    uint32_t arch_mask;
36
} QDevAlias;
37

    
38
static const QDevAlias qdev_alias_table[] = {
39
    { "virtio-blk-pci", "virtio-blk", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
40
    { "virtio-net-pci", "virtio-net", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
41
    { "virtio-serial-pci", "virtio-serial", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
42
    { "virtio-balloon-pci", "virtio-balloon",
43
            QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
44
    { "virtio-blk-s390", "virtio-blk", QEMU_ARCH_S390X },
45
    { "virtio-net-s390", "virtio-net", QEMU_ARCH_S390X },
46
    { "virtio-serial-s390", "virtio-serial", QEMU_ARCH_S390X },
47
    { "lsi53c895a", "lsi" },
48
    { "ich9-ahci", "ahci" },
49
    { "kvm-pci-assign", "pci-assign" },
50
    { }
51
};
52

    
53
static const char *qdev_class_get_alias(DeviceClass *dc)
54
{
55
    const char *typename = object_class_get_name(OBJECT_CLASS(dc));
56
    int i;
57

    
58
    for (i = 0; qdev_alias_table[i].typename; i++) {
59
        if (qdev_alias_table[i].arch_mask &&
60
            !(qdev_alias_table[i].arch_mask & arch_type)) {
61
            continue;
62
        }
63

    
64
        if (strcmp(qdev_alias_table[i].typename, typename) == 0) {
65
            return qdev_alias_table[i].alias;
66
        }
67
    }
68

    
69
    return NULL;
70
}
71

    
72
static bool qdev_class_has_alias(DeviceClass *dc)
73
{
74
    return (qdev_class_get_alias(dc) != NULL);
75
}
76

    
77
static void qdev_print_devinfo(ObjectClass *klass, void *opaque)
78
{
79
    DeviceClass *dc;
80
    bool *show_no_user = opaque;
81

    
82
    dc = (DeviceClass *)object_class_dynamic_cast(klass, TYPE_DEVICE);
83

    
84
    if (!dc || (show_no_user && !*show_no_user && dc->no_user)) {
85
        return;
86
    }
87

    
88
    error_printf("name \"%s\"", object_class_get_name(klass));
89
    if (dc->bus_type) {
90
        error_printf(", bus %s", dc->bus_type);
91
    }
92
    if (qdev_class_has_alias(dc)) {
93
        error_printf(", alias \"%s\"", qdev_class_get_alias(dc));
94
    }
95
    if (dc->desc) {
96
        error_printf(", desc \"%s\"", dc->desc);
97
    }
98
    if (dc->no_user) {
99
        error_printf(", no-user");
100
    }
101
    error_printf("\n");
102
}
103

    
104
static int set_property(const char *name, const char *value, void *opaque)
105
{
106
    DeviceState *dev = opaque;
107

    
108
    if (strcmp(name, "driver") == 0)
109
        return 0;
110
    if (strcmp(name, "bus") == 0)
111
        return 0;
112

    
113
    if (qdev_prop_parse(dev, name, value) == -1) {
114
        return -1;
115
    }
116
    return 0;
117
}
118

    
119
static const char *find_typename_by_alias(const char *alias)
120
{
121
    int i;
122

    
123
    for (i = 0; qdev_alias_table[i].alias; i++) {
124
        if (qdev_alias_table[i].arch_mask &&
125
            !(qdev_alias_table[i].arch_mask & arch_type)) {
126
            continue;
127
        }
128

    
129
        if (strcmp(qdev_alias_table[i].alias, alias) == 0) {
130
            return qdev_alias_table[i].typename;
131
        }
132
    }
133

    
134
    return NULL;
135
}
136

    
137
int qdev_device_help(QemuOpts *opts)
138
{
139
    const char *driver;
140
    Property *prop;
141
    ObjectClass *klass;
142

    
143
    driver = qemu_opt_get(opts, "driver");
144
    if (driver && is_help_option(driver)) {
145
        bool show_no_user = false;
146
        object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, &show_no_user);
147
        return 1;
148
    }
149

    
150
    if (!driver || !qemu_opt_has_help_opt(opts)) {
151
        return 0;
152
    }
153

    
154
    klass = object_class_by_name(driver);
155
    if (!klass) {
156
        const char *typename = find_typename_by_alias(driver);
157

    
158
        if (typename) {
159
            driver = typename;
160
            klass = object_class_by_name(driver);
161
        }
162
    }
163

    
164
    if (!klass) {
165
        return 0;
166
    }
167
    do {
168
        for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) {
169
            /*
170
             * TODO Properties without a parser are just for dirty hacks.
171
             * qdev_prop_ptr is the only such PropertyInfo.  It's marked
172
             * for removal.  This conditional should be removed along with
173
             * it.
174
             */
175
            if (!prop->info->set) {
176
                continue;           /* no way to set it, don't show */
177
            }
178
            error_printf("%s.%s=%s\n", driver, prop->name,
179
                         prop->info->legacy_name ?: prop->info->name);
180
        }
181
        klass = object_class_get_parent(klass);
182
    } while (klass != object_class_by_name(TYPE_DEVICE));
183
    return 1;
184
}
185

    
186
static Object *qdev_get_peripheral(void)
187
{
188
    static Object *dev;
189

    
190
    if (dev == NULL) {
191
        dev = container_get(qdev_get_machine(), "/peripheral");
192
    }
193

    
194
    return dev;
195
}
196

    
197
static Object *qdev_get_peripheral_anon(void)
198
{
199
    static Object *dev;
200

    
201
    if (dev == NULL) {
202
        dev = container_get(qdev_get_machine(), "/peripheral-anon");
203
    }
204

    
205
    return dev;
206
}
207

    
208
static void qbus_list_bus(DeviceState *dev)
209
{
210
    BusState *child;
211
    const char *sep = " ";
212

    
213
    error_printf("child busses at \"%s\":",
214
                 dev->id ? dev->id : object_get_typename(OBJECT(dev)));
215
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
216
        error_printf("%s\"%s\"", sep, child->name);
217
        sep = ", ";
218
    }
219
    error_printf("\n");
220
}
221

    
222
static void qbus_list_dev(BusState *bus)
223
{
224
    BusChild *kid;
225
    const char *sep = " ";
226

    
227
    error_printf("devices at \"%s\":", bus->name);
228
    QTAILQ_FOREACH(kid, &bus->children, sibling) {
229
        DeviceState *dev = kid->child;
230
        error_printf("%s\"%s\"", sep, object_get_typename(OBJECT(dev)));
231
        if (dev->id)
232
            error_printf("/\"%s\"", dev->id);
233
        sep = ", ";
234
    }
235
    error_printf("\n");
236
}
237

    
238
static BusState *qbus_find_bus(DeviceState *dev, char *elem)
239
{
240
    BusState *child;
241

    
242
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
243
        if (strcmp(child->name, elem) == 0) {
244
            return child;
245
        }
246
    }
247
    return NULL;
248
}
249

    
250
static DeviceState *qbus_find_dev(BusState *bus, char *elem)
251
{
252
    BusChild *kid;
253

    
254
    /*
255
     * try to match in order:
256
     *   (1) instance id, if present
257
     *   (2) driver name
258
     *   (3) driver alias, if present
259
     */
260
    QTAILQ_FOREACH(kid, &bus->children, sibling) {
261
        DeviceState *dev = kid->child;
262
        if (dev->id  &&  strcmp(dev->id, elem) == 0) {
263
            return dev;
264
        }
265
    }
266
    QTAILQ_FOREACH(kid, &bus->children, sibling) {
267
        DeviceState *dev = kid->child;
268
        if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
269
            return dev;
270
        }
271
    }
272
    QTAILQ_FOREACH(kid, &bus->children, sibling) {
273
        DeviceState *dev = kid->child;
274
        DeviceClass *dc = DEVICE_GET_CLASS(dev);
275

    
276
        if (qdev_class_has_alias(dc) &&
277
            strcmp(qdev_class_get_alias(dc), elem) == 0) {
278
            return dev;
279
        }
280
    }
281
    return NULL;
282
}
283

    
284
static BusState *qbus_find_recursive(BusState *bus, const char *name,
285
                                     const char *bus_typename)
286
{
287
    BusClass *bus_class = BUS_GET_CLASS(bus);
288
    BusChild *kid;
289
    BusState *child, *ret;
290
    int match = 1;
291

    
292
    if (name && (strcmp(bus->name, name) != 0)) {
293
        match = 0;
294
    }
295
    if (bus_typename && !object_dynamic_cast(OBJECT(bus), bus_typename)) {
296
        match = 0;
297
    }
298
    if ((bus_class->max_dev != 0) && (bus_class->max_dev <= bus->max_index)) {
299
        if (name != NULL) {
300
            /* bus was explicitly specified: return an error. */
301
            qerror_report(ERROR_CLASS_GENERIC_ERROR, "Bus '%s' is full",
302
                          bus->name);
303
            return NULL;
304
        } else {
305
            /* bus was not specified: try to find another one. */
306
            match = 0;
307
        }
308
    }
309
    if (match) {
310
        return bus;
311
    }
312

    
313
    QTAILQ_FOREACH(kid, &bus->children, sibling) {
314
        DeviceState *dev = kid->child;
315
        QLIST_FOREACH(child, &dev->child_bus, sibling) {
316
            ret = qbus_find_recursive(child, name, bus_typename);
317
            if (ret) {
318
                return ret;
319
            }
320
        }
321
    }
322
    return NULL;
323
}
324

    
325
static BusState *qbus_find(const char *path)
326
{
327
    DeviceState *dev;
328
    BusState *bus;
329
    char elem[128];
330
    int pos, len;
331

    
332
    /* find start element */
333
    if (path[0] == '/') {
334
        bus = sysbus_get_default();
335
        pos = 0;
336
    } else {
337
        if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
338
            assert(!path[0]);
339
            elem[0] = len = 0;
340
        }
341
        bus = qbus_find_recursive(sysbus_get_default(), elem, NULL);
342
        if (!bus) {
343
            qerror_report(QERR_BUS_NOT_FOUND, elem);
344
            return NULL;
345
        }
346
        pos = len;
347
    }
348

    
349
    for (;;) {
350
        assert(path[pos] == '/' || !path[pos]);
351
        while (path[pos] == '/') {
352
            pos++;
353
        }
354
        if (path[pos] == '\0') {
355
            return bus;
356
        }
357

    
358
        /* find device */
359
        if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
360
            assert(0);
361
            elem[0] = len = 0;
362
        }
363
        pos += len;
364
        dev = qbus_find_dev(bus, elem);
365
        if (!dev) {
366
            qerror_report(QERR_DEVICE_NOT_FOUND, elem);
367
            if (!monitor_cur_is_qmp()) {
368
                qbus_list_dev(bus);
369
            }
370
            return NULL;
371
        }
372

    
373
        assert(path[pos] == '/' || !path[pos]);
374
        while (path[pos] == '/') {
375
            pos++;
376
        }
377
        if (path[pos] == '\0') {
378
            /* last specified element is a device.  If it has exactly
379
             * one child bus accept it nevertheless */
380
            switch (dev->num_child_bus) {
381
            case 0:
382
                qerror_report(QERR_DEVICE_NO_BUS, elem);
383
                return NULL;
384
            case 1:
385
                return QLIST_FIRST(&dev->child_bus);
386
            default:
387
                qerror_report(QERR_DEVICE_MULTIPLE_BUSSES, elem);
388
                if (!monitor_cur_is_qmp()) {
389
                    qbus_list_bus(dev);
390
                }
391
                return NULL;
392
            }
393
        }
394

    
395
        /* find bus */
396
        if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
397
            assert(0);
398
            elem[0] = len = 0;
399
        }
400
        pos += len;
401
        bus = qbus_find_bus(dev, elem);
402
        if (!bus) {
403
            qerror_report(QERR_BUS_NOT_FOUND, elem);
404
            if (!monitor_cur_is_qmp()) {
405
                qbus_list_bus(dev);
406
            }
407
            return NULL;
408
        }
409
    }
410
}
411

    
412
DeviceState *qdev_device_add(QemuOpts *opts)
413
{
414
    ObjectClass *obj;
415
    DeviceClass *k;
416
    const char *driver, *path, *id;
417
    DeviceState *qdev;
418
    BusState *bus;
419

    
420
    driver = qemu_opt_get(opts, "driver");
421
    if (!driver) {
422
        qerror_report(QERR_MISSING_PARAMETER, "driver");
423
        return NULL;
424
    }
425

    
426
    /* find driver */
427
    obj = object_class_by_name(driver);
428
    if (!obj) {
429
        const char *typename = find_typename_by_alias(driver);
430

    
431
        if (typename) {
432
            driver = typename;
433
            obj = object_class_by_name(driver);
434
        }
435
    }
436

    
437
    if (!obj) {
438
        qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type");
439
        return NULL;
440
    }
441

    
442
    k = DEVICE_CLASS(obj);
443

    
444
    /* find bus */
445
    path = qemu_opt_get(opts, "bus");
446
    if (path != NULL) {
447
        bus = qbus_find(path);
448
        if (!bus) {
449
            return NULL;
450
        }
451
        if (!object_dynamic_cast(OBJECT(bus), k->bus_type)) {
452
            qerror_report(QERR_BAD_BUS_FOR_DEVICE,
453
                          driver, object_get_typename(OBJECT(bus)));
454
            return NULL;
455
        }
456
    } else {
457
        bus = qbus_find_recursive(sysbus_get_default(), NULL, k->bus_type);
458
        if (!bus) {
459
            qerror_report(QERR_NO_BUS_FOR_DEVICE,
460
                          k->bus_type, driver);
461
            return NULL;
462
        }
463
    }
464
    if (qdev_hotplug && !bus->allow_hotplug) {
465
        qerror_report(QERR_BUS_NO_HOTPLUG, bus->name);
466
        return NULL;
467
    }
468

    
469
    if (!bus) {
470
        bus = sysbus_get_default();
471
    }
472

    
473
    /* create device, set properties */
474
    qdev = DEVICE(object_new(driver));
475
    qdev_set_parent_bus(qdev, bus);
476

    
477
    id = qemu_opts_id(opts);
478
    if (id) {
479
        qdev->id = id;
480
    }
481
    if (qemu_opt_foreach(opts, set_property, qdev, 1) != 0) {
482
        qdev_free(qdev);
483
        return NULL;
484
    }
485
    if (qdev->id) {
486
        object_property_add_child(qdev_get_peripheral(), qdev->id,
487
                                  OBJECT(qdev), NULL);
488
    } else {
489
        static int anon_count;
490
        gchar *name = g_strdup_printf("device[%d]", anon_count++);
491
        object_property_add_child(qdev_get_peripheral_anon(), name,
492
                                  OBJECT(qdev), NULL);
493
        g_free(name);
494
    }        
495
    if (qdev_init(qdev) < 0) {
496
        qerror_report(QERR_DEVICE_INIT_FAILED, driver);
497
        return NULL;
498
    }
499
    qdev->opts = opts;
500
    return qdev;
501
}
502

    
503

    
504
#define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
505
static void qbus_print(Monitor *mon, BusState *bus, int indent);
506

    
507
static void qdev_print_props(Monitor *mon, DeviceState *dev, Property *props,
508
                             int indent)
509
{
510
    if (!props)
511
        return;
512
    for (; props->name; props++) {
513
        Error *err = NULL;
514
        char *value;
515
        char *legacy_name = g_strdup_printf("legacy-%s", props->name);
516
        if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
517
            value = object_property_get_str(OBJECT(dev), legacy_name, &err);
518
        } else {
519
            value = object_property_print(OBJECT(dev), props->name, &err);
520
        }
521
        g_free(legacy_name);
522

    
523
        if (err) {
524
            error_free(err);
525
            continue;
526
        }
527
        qdev_printf("%s = %s\n", props->name,
528
                    value && *value ? value : "<null>");
529
        g_free(value);
530
    }
531
}
532

    
533
static void bus_print_dev(BusState *bus, Monitor *mon, DeviceState *dev, int indent)
534
{
535
    BusClass *bc = BUS_GET_CLASS(bus);
536

    
537
    if (bc->print_dev) {
538
        bc->print_dev(mon, dev, indent);
539
    }
540
}
541

    
542
static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
543
{
544
    ObjectClass *class;
545
    BusState *child;
546
    qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
547
                dev->id ? dev->id : "");
548
    indent += 2;
549
    if (dev->num_gpio_in) {
550
        qdev_printf("gpio-in %d\n", dev->num_gpio_in);
551
    }
552
    if (dev->num_gpio_out) {
553
        qdev_printf("gpio-out %d\n", dev->num_gpio_out);
554
    }
555
    class = object_get_class(OBJECT(dev));
556
    do {
557
        qdev_print_props(mon, dev, DEVICE_CLASS(class)->props, indent);
558
        class = object_class_get_parent(class);
559
    } while (class != object_class_by_name(TYPE_DEVICE));
560
    bus_print_dev(dev->parent_bus, mon, dev, indent);
561
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
562
        qbus_print(mon, child, indent);
563
    }
564
}
565

    
566
static void qbus_print(Monitor *mon, BusState *bus, int indent)
567
{
568
    BusChild *kid;
569

    
570
    qdev_printf("bus: %s\n", bus->name);
571
    indent += 2;
572
    qdev_printf("type %s\n", object_get_typename(OBJECT(bus)));
573
    QTAILQ_FOREACH(kid, &bus->children, sibling) {
574
        DeviceState *dev = kid->child;
575
        qdev_print(mon, dev, indent);
576
    }
577
}
578
#undef qdev_printf
579

    
580
void do_info_qtree(Monitor *mon, const QDict *qdict)
581
{
582
    if (sysbus_get_default())
583
        qbus_print(mon, sysbus_get_default(), 0);
584
}
585

    
586
void do_info_qdm(Monitor *mon, const QDict *qdict)
587
{
588
    object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, NULL);
589
}
590

    
591
int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
592
{
593
    Error *local_err = NULL;
594
    QemuOpts *opts;
595
    DeviceState *dev;
596

    
597
    opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict, &local_err);
598
    if (error_is_set(&local_err)) {
599
        qerror_report_err(local_err);
600
        error_free(local_err);
601
        return -1;
602
    }
603
    if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
604
        qemu_opts_del(opts);
605
        return 0;
606
    }
607
    dev = qdev_device_add(opts);
608
    if (!dev) {
609
        qemu_opts_del(opts);
610
        return -1;
611
    }
612
    object_unref(OBJECT(dev));
613
    return 0;
614
}
615

    
616
void qmp_device_del(const char *id, Error **errp)
617
{
618
    DeviceState *dev;
619

    
620
    dev = qdev_find_recursive(sysbus_get_default(), id);
621
    if (NULL == dev) {
622
        error_set(errp, QERR_DEVICE_NOT_FOUND, id);
623
        return;
624
    }
625

    
626
    qdev_unplug(dev, errp);
627
}
628

    
629
void qdev_machine_init(void)
630
{
631
    qdev_get_peripheral_anon();
632
    qdev_get_peripheral();
633
}
634

    
635
QemuOptsList qemu_device_opts = {
636
    .name = "device",
637
    .implied_opt_name = "driver",
638
    .head = QTAILQ_HEAD_INITIALIZER(qemu_device_opts.head),
639
    .desc = {
640
        /*
641
         * no elements => accept any
642
         * sanity checking will happen later
643
         * when setting device properties
644
         */
645
        { /* end of list */ }
646
    },
647
};
648

    
649
QemuOptsList qemu_global_opts = {
650
    .name = "global",
651
    .head = QTAILQ_HEAD_INITIALIZER(qemu_global_opts.head),
652
    .desc = {
653
        {
654
            .name = "driver",
655
            .type = QEMU_OPT_STRING,
656
        },{
657
            .name = "property",
658
            .type = QEMU_OPT_STRING,
659
        },{
660
            .name = "value",
661
            .type = QEMU_OPT_STRING,
662
        },
663
        { /* end of list */ }
664
    },
665
};
666

    
667
int qemu_global_option(const char *str)
668
{
669
    char driver[64], property[64];
670
    QemuOpts *opts;
671
    int rc, offset;
672

    
673
    rc = sscanf(str, "%63[^.].%63[^=]%n", driver, property, &offset);
674
    if (rc < 2 || str[offset] != '=') {
675
        error_report("can't parse: \"%s\"", str);
676
        return -1;
677
    }
678

    
679
    opts = qemu_opts_create_nofail(&qemu_global_opts);
680
    qemu_opt_set(opts, "driver", driver);
681
    qemu_opt_set(opts, "property", property);
682
    qemu_opt_set(opts, "value", str+offset+1);
683
    return 0;
684
}