Statistics
| Branch: | Revision:

root / qdev-monitor.c @ 2ff3de68

History | View | Annotate | Download (18.1 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 "hw/sysbus.h"
22
#include "monitor/monitor.h"
23
#include "monitor/qdev.h"
24
#include "qmp-commands.h"
25
#include "sysemu/arch_init.h"
26
#include "qemu/config-file.h"
27

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

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

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

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

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

    
70
    return NULL;
71
}
72

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

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

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

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

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

    
105
static int set_property(const char *name, const char *value, void *opaque)
106
{
107
    DeviceState *dev = opaque;
108
    Error *err = NULL;
109

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

    
115
    qdev_prop_parse(dev, name, value, &err);
116
    if (err != NULL) {
117
        qerror_report_err(err);
118
        error_free(err);
119
        return -1;
120
    }
121
    return 0;
122
}
123

    
124
static const char *find_typename_by_alias(const char *alias)
125
{
126
    int i;
127

    
128
    for (i = 0; qdev_alias_table[i].alias; i++) {
129
        if (qdev_alias_table[i].arch_mask &&
130
            !(qdev_alias_table[i].arch_mask & arch_type)) {
131
            continue;
132
        }
133

    
134
        if (strcmp(qdev_alias_table[i].alias, alias) == 0) {
135
            return qdev_alias_table[i].typename;
136
        }
137
    }
138

    
139
    return NULL;
140
}
141

    
142
int qdev_device_help(QemuOpts *opts)
143
{
144
    const char *driver;
145
    Property *prop;
146
    ObjectClass *klass;
147

    
148
    driver = qemu_opt_get(opts, "driver");
149
    if (driver && is_help_option(driver)) {
150
        bool show_no_user = false;
151
        object_class_foreach(qdev_print_devinfo, TYPE_DEVICE, false, &show_no_user);
152
        return 1;
153
    }
154

    
155
    if (!driver || !qemu_opt_has_help_opt(opts)) {
156
        return 0;
157
    }
158

    
159
    klass = object_class_by_name(driver);
160
    if (!klass) {
161
        const char *typename = find_typename_by_alias(driver);
162

    
163
        if (typename) {
164
            driver = typename;
165
            klass = object_class_by_name(driver);
166
        }
167
    }
168

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

    
191
static Object *qdev_get_peripheral(void)
192
{
193
    static Object *dev;
194

    
195
    if (dev == NULL) {
196
        dev = container_get(qdev_get_machine(), "/peripheral");
197
    }
198

    
199
    return dev;
200
}
201

    
202
static Object *qdev_get_peripheral_anon(void)
203
{
204
    static Object *dev;
205

    
206
    if (dev == NULL) {
207
        dev = container_get(qdev_get_machine(), "/peripheral-anon");
208
    }
209

    
210
    return dev;
211
}
212

    
213
static void qbus_list_bus(DeviceState *dev)
214
{
215
    BusState *child;
216
    const char *sep = " ";
217

    
218
    error_printf("child busses at \"%s\":",
219
                 dev->id ? dev->id : object_get_typename(OBJECT(dev)));
220
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
221
        error_printf("%s\"%s\"", sep, child->name);
222
        sep = ", ";
223
    }
224
    error_printf("\n");
225
}
226

    
227
static void qbus_list_dev(BusState *bus)
228
{
229
    BusChild *kid;
230
    const char *sep = " ";
231

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

    
243
static BusState *qbus_find_bus(DeviceState *dev, char *elem)
244
{
245
    BusState *child;
246

    
247
    QLIST_FOREACH(child, &dev->child_bus, sibling) {
248
        if (strcmp(child->name, elem) == 0) {
249
            return child;
250
        }
251
    }
252
    return NULL;
253
}
254

    
255
static DeviceState *qbus_find_dev(BusState *bus, char *elem)
256
{
257
    BusChild *kid;
258

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

    
281
        if (qdev_class_has_alias(dc) &&
282
            strcmp(qdev_class_get_alias(dc), elem) == 0) {
283
            return dev;
284
        }
285
    }
286
    return NULL;
287
}
288

    
289
static BusState *qbus_find_recursive(BusState *bus, const char *name,
290
                                     const char *bus_typename)
291
{
292
    BusClass *bus_class = BUS_GET_CLASS(bus);
293
    BusChild *kid;
294
    BusState *child, *ret;
295
    int match = 1;
296

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

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

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

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

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

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

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

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

    
415
DeviceState *qdev_device_add(QemuOpts *opts)
416
{
417
    ObjectClass *obj;
418
    DeviceClass *k;
419
    const char *driver, *path, *id;
420
    DeviceState *qdev;
421
    BusState *bus = NULL;
422

    
423
    driver = qemu_opt_get(opts, "driver");
424
    if (!driver) {
425
        qerror_report(QERR_MISSING_PARAMETER, "driver");
426
        return NULL;
427
    }
428

    
429
    /* find driver */
430
    obj = object_class_by_name(driver);
431
    if (!obj) {
432
        const char *typename = find_typename_by_alias(driver);
433

    
434
        if (typename) {
435
            driver = typename;
436
            obj = object_class_by_name(driver);
437
        }
438
    }
439

    
440
    if (!obj) {
441
        qerror_report(QERR_INVALID_PARAMETER_VALUE, "driver", "device type");
442
        return NULL;
443
    }
444

    
445
    k = DEVICE_CLASS(obj);
446

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

    
472
    /* create device, set properties */
473
    qdev = DEVICE(object_new(driver));
474

    
475
    if (bus) {
476
        qdev_set_parent_bus(qdev, bus);
477
    }
478

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

    
505

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
628
    qdev_unplug(dev, errp);
629
}
630

    
631
void qdev_machine_init(void)
632
{
633
    qdev_get_peripheral_anon();
634
    qdev_get_peripheral();
635
}
636

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

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

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

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

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