18d7f2e76SPhilippe Mathieu-Daudé /*
28d7f2e76SPhilippe Mathieu-Daudé * Dynamic device configuration and creation.
38d7f2e76SPhilippe Mathieu-Daudé *
48d7f2e76SPhilippe Mathieu-Daudé * Copyright (c) 2009 CodeSourcery
58d7f2e76SPhilippe Mathieu-Daudé *
68d7f2e76SPhilippe Mathieu-Daudé * This library is free software; you can redistribute it and/or
78d7f2e76SPhilippe Mathieu-Daudé * modify it under the terms of the GNU Lesser General Public
88d7f2e76SPhilippe Mathieu-Daudé * License as published by the Free Software Foundation; either
98d7f2e76SPhilippe Mathieu-Daudé * version 2.1 of the License, or (at your option) any later version.
108d7f2e76SPhilippe Mathieu-Daudé *
118d7f2e76SPhilippe Mathieu-Daudé * This library is distributed in the hope that it will be useful,
128d7f2e76SPhilippe Mathieu-Daudé * but WITHOUT ANY WARRANTY; without even the implied warranty of
138d7f2e76SPhilippe Mathieu-Daudé * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
148d7f2e76SPhilippe Mathieu-Daudé * Lesser General Public License for more details.
158d7f2e76SPhilippe Mathieu-Daudé *
168d7f2e76SPhilippe Mathieu-Daudé * You should have received a copy of the GNU Lesser General Public
178d7f2e76SPhilippe Mathieu-Daudé * License along with this library; if not, see <http://www.gnu.org/licenses/>.
188d7f2e76SPhilippe Mathieu-Daudé */
198d7f2e76SPhilippe Mathieu-Daudé
208d7f2e76SPhilippe Mathieu-Daudé #include "qemu/osdep.h"
218d7f2e76SPhilippe Mathieu-Daudé #include "hw/sysbus.h"
228d7f2e76SPhilippe Mathieu-Daudé #include "monitor/hmp.h"
238d7f2e76SPhilippe Mathieu-Daudé #include "monitor/monitor.h"
248d7f2e76SPhilippe Mathieu-Daudé #include "monitor/qdev.h"
258d7f2e76SPhilippe Mathieu-Daudé #include "sysemu/arch_init.h"
263f98408eSVladimir Sementsov-Ogievskiy #include "sysemu/runstate.h"
278d7f2e76SPhilippe Mathieu-Daudé #include "qapi/error.h"
288d7f2e76SPhilippe Mathieu-Daudé #include "qapi/qapi-commands-qdev.h"
298d7f2e76SPhilippe Mathieu-Daudé #include "qapi/qmp/dispatch.h"
308d7f2e76SPhilippe Mathieu-Daudé #include "qapi/qmp/qdict.h"
318d7f2e76SPhilippe Mathieu-Daudé #include "qapi/qmp/qerror.h"
328d7f2e76SPhilippe Mathieu-Daudé #include "qapi/qmp/qstring.h"
338d7f2e76SPhilippe Mathieu-Daudé #include "qapi/qobject-input-visitor.h"
348d7f2e76SPhilippe Mathieu-Daudé #include "qemu/config-file.h"
358d7f2e76SPhilippe Mathieu-Daudé #include "qemu/error-report.h"
368d7f2e76SPhilippe Mathieu-Daudé #include "qemu/help_option.h"
378d7f2e76SPhilippe Mathieu-Daudé #include "qemu/option.h"
388d7f2e76SPhilippe Mathieu-Daudé #include "qemu/qemu-print.h"
398d7f2e76SPhilippe Mathieu-Daudé #include "qemu/option_int.h"
408d7f2e76SPhilippe Mathieu-Daudé #include "sysemu/block-backend.h"
418d7f2e76SPhilippe Mathieu-Daudé #include "migration/misc.h"
428d7f2e76SPhilippe Mathieu-Daudé #include "qemu/cutils.h"
438d7f2e76SPhilippe Mathieu-Daudé #include "hw/qdev-properties.h"
448d7f2e76SPhilippe Mathieu-Daudé #include "hw/clock.h"
458d7f2e76SPhilippe Mathieu-Daudé #include "hw/boards.h"
468d7f2e76SPhilippe Mathieu-Daudé
478d7f2e76SPhilippe Mathieu-Daudé /*
488d7f2e76SPhilippe Mathieu-Daudé * Aliases were a bad idea from the start. Let's keep them
498d7f2e76SPhilippe Mathieu-Daudé * from spreading further.
508d7f2e76SPhilippe Mathieu-Daudé */
518d7f2e76SPhilippe Mathieu-Daudé typedef struct QDevAlias
528d7f2e76SPhilippe Mathieu-Daudé {
538d7f2e76SPhilippe Mathieu-Daudé const char *typename;
548d7f2e76SPhilippe Mathieu-Daudé const char *alias;
558d7f2e76SPhilippe Mathieu-Daudé uint32_t arch_mask;
568d7f2e76SPhilippe Mathieu-Daudé } QDevAlias;
578d7f2e76SPhilippe Mathieu-Daudé
588d7f2e76SPhilippe Mathieu-Daudé /* default virtio transport per architecture */
59a1b47343SPhilippe Mathieu-Daudé #define QEMU_ARCH_VIRTIO_PCI (QEMU_ARCH_ALPHA | \
60a1b47343SPhilippe Mathieu-Daudé QEMU_ARCH_ARM | \
61a1b47343SPhilippe Mathieu-Daudé QEMU_ARCH_HPPA | \
62a1b47343SPhilippe Mathieu-Daudé QEMU_ARCH_I386 | \
63a1b47343SPhilippe Mathieu-Daudé QEMU_ARCH_LOONGARCH | \
64a1b47343SPhilippe Mathieu-Daudé QEMU_ARCH_MIPS | \
65eef0a1e3SThomas Huth QEMU_ARCH_OPENRISC | \
66a1b47343SPhilippe Mathieu-Daudé QEMU_ARCH_PPC | \
67a1b47343SPhilippe Mathieu-Daudé QEMU_ARCH_RISCV | \
68a1b47343SPhilippe Mathieu-Daudé QEMU_ARCH_SH4 | \
69a1b47343SPhilippe Mathieu-Daudé QEMU_ARCH_SPARC | \
70a1b47343SPhilippe Mathieu-Daudé QEMU_ARCH_XTENSA)
718d7f2e76SPhilippe Mathieu-Daudé #define QEMU_ARCH_VIRTIO_CCW (QEMU_ARCH_S390X)
728d7f2e76SPhilippe Mathieu-Daudé #define QEMU_ARCH_VIRTIO_MMIO (QEMU_ARCH_M68K)
738d7f2e76SPhilippe Mathieu-Daudé
748d7f2e76SPhilippe Mathieu-Daudé /* Please keep this table sorted by typename. */
758d7f2e76SPhilippe Mathieu-Daudé static const QDevAlias qdev_alias_table[] = {
768d7f2e76SPhilippe Mathieu-Daudé { "AC97", "ac97" }, /* -soundhw name */
778d7f2e76SPhilippe Mathieu-Daudé { "e1000", "e1000-82540em" },
788d7f2e76SPhilippe Mathieu-Daudé { "ES1370", "es1370" }, /* -soundhw name */
798d7f2e76SPhilippe Mathieu-Daudé { "ich9-ahci", "ahci" },
808d7f2e76SPhilippe Mathieu-Daudé { "lsi53c895a", "lsi" },
818d7f2e76SPhilippe Mathieu-Daudé { "virtio-9p-device", "virtio-9p", QEMU_ARCH_VIRTIO_MMIO },
828d7f2e76SPhilippe Mathieu-Daudé { "virtio-9p-ccw", "virtio-9p", QEMU_ARCH_VIRTIO_CCW },
838d7f2e76SPhilippe Mathieu-Daudé { "virtio-9p-pci", "virtio-9p", QEMU_ARCH_VIRTIO_PCI },
848d7f2e76SPhilippe Mathieu-Daudé { "virtio-balloon-device", "virtio-balloon", QEMU_ARCH_VIRTIO_MMIO },
858d7f2e76SPhilippe Mathieu-Daudé { "virtio-balloon-ccw", "virtio-balloon", QEMU_ARCH_VIRTIO_CCW },
868d7f2e76SPhilippe Mathieu-Daudé { "virtio-balloon-pci", "virtio-balloon", QEMU_ARCH_VIRTIO_PCI },
878d7f2e76SPhilippe Mathieu-Daudé { "virtio-blk-device", "virtio-blk", QEMU_ARCH_VIRTIO_MMIO },
888d7f2e76SPhilippe Mathieu-Daudé { "virtio-blk-ccw", "virtio-blk", QEMU_ARCH_VIRTIO_CCW },
898d7f2e76SPhilippe Mathieu-Daudé { "virtio-blk-pci", "virtio-blk", QEMU_ARCH_VIRTIO_PCI },
908d7f2e76SPhilippe Mathieu-Daudé { "virtio-gpu-device", "virtio-gpu", QEMU_ARCH_VIRTIO_MMIO },
918d7f2e76SPhilippe Mathieu-Daudé { "virtio-gpu-ccw", "virtio-gpu", QEMU_ARCH_VIRTIO_CCW },
928d7f2e76SPhilippe Mathieu-Daudé { "virtio-gpu-pci", "virtio-gpu", QEMU_ARCH_VIRTIO_PCI },
938d7f2e76SPhilippe Mathieu-Daudé { "virtio-gpu-gl-device", "virtio-gpu-gl", QEMU_ARCH_VIRTIO_MMIO },
948d7f2e76SPhilippe Mathieu-Daudé { "virtio-gpu-gl-pci", "virtio-gpu-gl", QEMU_ARCH_VIRTIO_PCI },
958e7b21caSGurchetan Singh { "virtio-gpu-rutabaga-device", "virtio-gpu-rutabaga",
968e7b21caSGurchetan Singh QEMU_ARCH_VIRTIO_MMIO },
978e7b21caSGurchetan Singh { "virtio-gpu-rutabaga-pci", "virtio-gpu-rutabaga", QEMU_ARCH_VIRTIO_PCI },
988d7f2e76SPhilippe Mathieu-Daudé { "virtio-input-host-device", "virtio-input-host", QEMU_ARCH_VIRTIO_MMIO },
998d7f2e76SPhilippe Mathieu-Daudé { "virtio-input-host-ccw", "virtio-input-host", QEMU_ARCH_VIRTIO_CCW },
1008d7f2e76SPhilippe Mathieu-Daudé { "virtio-input-host-pci", "virtio-input-host", QEMU_ARCH_VIRTIO_PCI },
1018d7f2e76SPhilippe Mathieu-Daudé { "virtio-iommu-pci", "virtio-iommu", QEMU_ARCH_VIRTIO_PCI },
1028d7f2e76SPhilippe Mathieu-Daudé { "virtio-keyboard-device", "virtio-keyboard", QEMU_ARCH_VIRTIO_MMIO },
1038d7f2e76SPhilippe Mathieu-Daudé { "virtio-keyboard-ccw", "virtio-keyboard", QEMU_ARCH_VIRTIO_CCW },
1048d7f2e76SPhilippe Mathieu-Daudé { "virtio-keyboard-pci", "virtio-keyboard", QEMU_ARCH_VIRTIO_PCI },
1058d7f2e76SPhilippe Mathieu-Daudé { "virtio-mouse-device", "virtio-mouse", QEMU_ARCH_VIRTIO_MMIO },
1068d7f2e76SPhilippe Mathieu-Daudé { "virtio-mouse-ccw", "virtio-mouse", QEMU_ARCH_VIRTIO_CCW },
1078d7f2e76SPhilippe Mathieu-Daudé { "virtio-mouse-pci", "virtio-mouse", QEMU_ARCH_VIRTIO_PCI },
1088d7f2e76SPhilippe Mathieu-Daudé { "virtio-net-device", "virtio-net", QEMU_ARCH_VIRTIO_MMIO },
1098d7f2e76SPhilippe Mathieu-Daudé { "virtio-net-ccw", "virtio-net", QEMU_ARCH_VIRTIO_CCW },
1108d7f2e76SPhilippe Mathieu-Daudé { "virtio-net-pci", "virtio-net", QEMU_ARCH_VIRTIO_PCI },
1118d7f2e76SPhilippe Mathieu-Daudé { "virtio-rng-device", "virtio-rng", QEMU_ARCH_VIRTIO_MMIO },
1128d7f2e76SPhilippe Mathieu-Daudé { "virtio-rng-ccw", "virtio-rng", QEMU_ARCH_VIRTIO_CCW },
1138d7f2e76SPhilippe Mathieu-Daudé { "virtio-rng-pci", "virtio-rng", QEMU_ARCH_VIRTIO_PCI },
1148d7f2e76SPhilippe Mathieu-Daudé { "virtio-scsi-device", "virtio-scsi", QEMU_ARCH_VIRTIO_MMIO },
1158d7f2e76SPhilippe Mathieu-Daudé { "virtio-scsi-ccw", "virtio-scsi", QEMU_ARCH_VIRTIO_CCW },
1168d7f2e76SPhilippe Mathieu-Daudé { "virtio-scsi-pci", "virtio-scsi", QEMU_ARCH_VIRTIO_PCI },
1178d7f2e76SPhilippe Mathieu-Daudé { "virtio-serial-device", "virtio-serial", QEMU_ARCH_VIRTIO_MMIO },
1188d7f2e76SPhilippe Mathieu-Daudé { "virtio-serial-ccw", "virtio-serial", QEMU_ARCH_VIRTIO_CCW },
1198d7f2e76SPhilippe Mathieu-Daudé { "virtio-serial-pci", "virtio-serial", QEMU_ARCH_VIRTIO_PCI},
1202880e676SManos Pitsidianakis { "virtio-sound-device", "virtio-sound", QEMU_ARCH_VIRTIO_MMIO },
12124269085SManos Pitsidianakis { "virtio-sound-pci", "virtio-sound", QEMU_ARCH_VIRTIO_PCI },
1228d7f2e76SPhilippe Mathieu-Daudé { "virtio-tablet-device", "virtio-tablet", QEMU_ARCH_VIRTIO_MMIO },
1238d7f2e76SPhilippe Mathieu-Daudé { "virtio-tablet-ccw", "virtio-tablet", QEMU_ARCH_VIRTIO_CCW },
1248d7f2e76SPhilippe Mathieu-Daudé { "virtio-tablet-pci", "virtio-tablet", QEMU_ARCH_VIRTIO_PCI },
1258d7f2e76SPhilippe Mathieu-Daudé { }
1268d7f2e76SPhilippe Mathieu-Daudé };
1278d7f2e76SPhilippe Mathieu-Daudé
qdev_class_get_alias(DeviceClass * dc)1288d7f2e76SPhilippe Mathieu-Daudé static const char *qdev_class_get_alias(DeviceClass *dc)
1298d7f2e76SPhilippe Mathieu-Daudé {
1308d7f2e76SPhilippe Mathieu-Daudé const char *typename = object_class_get_name(OBJECT_CLASS(dc));
1318d7f2e76SPhilippe Mathieu-Daudé int i;
1328d7f2e76SPhilippe Mathieu-Daudé
1338d7f2e76SPhilippe Mathieu-Daudé for (i = 0; qdev_alias_table[i].typename; i++) {
1348d7f2e76SPhilippe Mathieu-Daudé if (qdev_alias_table[i].arch_mask &&
1358d7f2e76SPhilippe Mathieu-Daudé !(qdev_alias_table[i].arch_mask & arch_type)) {
1368d7f2e76SPhilippe Mathieu-Daudé continue;
1378d7f2e76SPhilippe Mathieu-Daudé }
1388d7f2e76SPhilippe Mathieu-Daudé
1398d7f2e76SPhilippe Mathieu-Daudé if (strcmp(qdev_alias_table[i].typename, typename) == 0) {
1408d7f2e76SPhilippe Mathieu-Daudé return qdev_alias_table[i].alias;
1418d7f2e76SPhilippe Mathieu-Daudé }
1428d7f2e76SPhilippe Mathieu-Daudé }
1438d7f2e76SPhilippe Mathieu-Daudé
1448d7f2e76SPhilippe Mathieu-Daudé return NULL;
1458d7f2e76SPhilippe Mathieu-Daudé }
1468d7f2e76SPhilippe Mathieu-Daudé
qdev_class_has_alias(DeviceClass * dc)1478d7f2e76SPhilippe Mathieu-Daudé static bool qdev_class_has_alias(DeviceClass *dc)
1488d7f2e76SPhilippe Mathieu-Daudé {
1498d7f2e76SPhilippe Mathieu-Daudé return (qdev_class_get_alias(dc) != NULL);
1508d7f2e76SPhilippe Mathieu-Daudé }
1518d7f2e76SPhilippe Mathieu-Daudé
qdev_print_devinfo(DeviceClass * dc)1528d7f2e76SPhilippe Mathieu-Daudé static void qdev_print_devinfo(DeviceClass *dc)
1538d7f2e76SPhilippe Mathieu-Daudé {
1548d7f2e76SPhilippe Mathieu-Daudé qemu_printf("name \"%s\"", object_class_get_name(OBJECT_CLASS(dc)));
1558d7f2e76SPhilippe Mathieu-Daudé if (dc->bus_type) {
1568d7f2e76SPhilippe Mathieu-Daudé qemu_printf(", bus %s", dc->bus_type);
1578d7f2e76SPhilippe Mathieu-Daudé }
1588d7f2e76SPhilippe Mathieu-Daudé if (qdev_class_has_alias(dc)) {
1598d7f2e76SPhilippe Mathieu-Daudé qemu_printf(", alias \"%s\"", qdev_class_get_alias(dc));
1608d7f2e76SPhilippe Mathieu-Daudé }
1618d7f2e76SPhilippe Mathieu-Daudé if (dc->desc) {
1628d7f2e76SPhilippe Mathieu-Daudé qemu_printf(", desc \"%s\"", dc->desc);
1638d7f2e76SPhilippe Mathieu-Daudé }
1648d7f2e76SPhilippe Mathieu-Daudé if (!dc->user_creatable) {
1658d7f2e76SPhilippe Mathieu-Daudé qemu_printf(", no-user");
1668d7f2e76SPhilippe Mathieu-Daudé }
1678d7f2e76SPhilippe Mathieu-Daudé qemu_printf("\n");
1688d7f2e76SPhilippe Mathieu-Daudé }
1698d7f2e76SPhilippe Mathieu-Daudé
qdev_print_devinfos(bool show_no_user)1708d7f2e76SPhilippe Mathieu-Daudé static void qdev_print_devinfos(bool show_no_user)
1718d7f2e76SPhilippe Mathieu-Daudé {
1728d7f2e76SPhilippe Mathieu-Daudé static const char *cat_name[DEVICE_CATEGORY_MAX + 1] = {
1738d7f2e76SPhilippe Mathieu-Daudé [DEVICE_CATEGORY_BRIDGE] = "Controller/Bridge/Hub",
1748d7f2e76SPhilippe Mathieu-Daudé [DEVICE_CATEGORY_USB] = "USB",
1758d7f2e76SPhilippe Mathieu-Daudé [DEVICE_CATEGORY_STORAGE] = "Storage",
1768d7f2e76SPhilippe Mathieu-Daudé [DEVICE_CATEGORY_NETWORK] = "Network",
1778d7f2e76SPhilippe Mathieu-Daudé [DEVICE_CATEGORY_INPUT] = "Input",
1788d7f2e76SPhilippe Mathieu-Daudé [DEVICE_CATEGORY_DISPLAY] = "Display",
1798d7f2e76SPhilippe Mathieu-Daudé [DEVICE_CATEGORY_SOUND] = "Sound",
1808d7f2e76SPhilippe Mathieu-Daudé [DEVICE_CATEGORY_MISC] = "Misc",
1818d7f2e76SPhilippe Mathieu-Daudé [DEVICE_CATEGORY_CPU] = "CPU",
1828d7f2e76SPhilippe Mathieu-Daudé [DEVICE_CATEGORY_WATCHDOG]= "Watchdog",
1838d7f2e76SPhilippe Mathieu-Daudé [DEVICE_CATEGORY_MAX] = "Uncategorized",
1848d7f2e76SPhilippe Mathieu-Daudé };
1858d7f2e76SPhilippe Mathieu-Daudé GSList *list, *elt;
1868d7f2e76SPhilippe Mathieu-Daudé int i;
1878d7f2e76SPhilippe Mathieu-Daudé bool cat_printed;
1888d7f2e76SPhilippe Mathieu-Daudé
1898d7f2e76SPhilippe Mathieu-Daudé module_load_qom_all();
1908d7f2e76SPhilippe Mathieu-Daudé list = object_class_get_list_sorted(TYPE_DEVICE, false);
1918d7f2e76SPhilippe Mathieu-Daudé
1928d7f2e76SPhilippe Mathieu-Daudé for (i = 0; i <= DEVICE_CATEGORY_MAX; i++) {
1938d7f2e76SPhilippe Mathieu-Daudé cat_printed = false;
1948d7f2e76SPhilippe Mathieu-Daudé for (elt = list; elt; elt = elt->next) {
1958d7f2e76SPhilippe Mathieu-Daudé DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, elt->data,
1968d7f2e76SPhilippe Mathieu-Daudé TYPE_DEVICE);
1978d7f2e76SPhilippe Mathieu-Daudé if ((i < DEVICE_CATEGORY_MAX
1988d7f2e76SPhilippe Mathieu-Daudé ? !test_bit(i, dc->categories)
1998d7f2e76SPhilippe Mathieu-Daudé : !bitmap_empty(dc->categories, DEVICE_CATEGORY_MAX))
2008d7f2e76SPhilippe Mathieu-Daudé || (!show_no_user
2018d7f2e76SPhilippe Mathieu-Daudé && !dc->user_creatable)) {
2028d7f2e76SPhilippe Mathieu-Daudé continue;
2038d7f2e76SPhilippe Mathieu-Daudé }
2048d7f2e76SPhilippe Mathieu-Daudé if (!cat_printed) {
2058d7f2e76SPhilippe Mathieu-Daudé qemu_printf("%s%s devices:\n", i ? "\n" : "", cat_name[i]);
2068d7f2e76SPhilippe Mathieu-Daudé cat_printed = true;
2078d7f2e76SPhilippe Mathieu-Daudé }
2088d7f2e76SPhilippe Mathieu-Daudé qdev_print_devinfo(dc);
2098d7f2e76SPhilippe Mathieu-Daudé }
2108d7f2e76SPhilippe Mathieu-Daudé }
2118d7f2e76SPhilippe Mathieu-Daudé
2128d7f2e76SPhilippe Mathieu-Daudé g_slist_free(list);
2138d7f2e76SPhilippe Mathieu-Daudé }
2148d7f2e76SPhilippe Mathieu-Daudé
find_typename_by_alias(const char * alias)2158d7f2e76SPhilippe Mathieu-Daudé static const char *find_typename_by_alias(const char *alias)
2168d7f2e76SPhilippe Mathieu-Daudé {
2178d7f2e76SPhilippe Mathieu-Daudé int i;
2188d7f2e76SPhilippe Mathieu-Daudé
2198d7f2e76SPhilippe Mathieu-Daudé for (i = 0; qdev_alias_table[i].alias; i++) {
2208d7f2e76SPhilippe Mathieu-Daudé if (qdev_alias_table[i].arch_mask &&
2218d7f2e76SPhilippe Mathieu-Daudé !(qdev_alias_table[i].arch_mask & arch_type)) {
2228d7f2e76SPhilippe Mathieu-Daudé continue;
2238d7f2e76SPhilippe Mathieu-Daudé }
2248d7f2e76SPhilippe Mathieu-Daudé
2258d7f2e76SPhilippe Mathieu-Daudé if (strcmp(qdev_alias_table[i].alias, alias) == 0) {
2268d7f2e76SPhilippe Mathieu-Daudé return qdev_alias_table[i].typename;
2278d7f2e76SPhilippe Mathieu-Daudé }
2288d7f2e76SPhilippe Mathieu-Daudé }
2298d7f2e76SPhilippe Mathieu-Daudé
2308d7f2e76SPhilippe Mathieu-Daudé return NULL;
2318d7f2e76SPhilippe Mathieu-Daudé }
2328d7f2e76SPhilippe Mathieu-Daudé
qdev_get_device_class(const char ** driver,Error ** errp)2338d7f2e76SPhilippe Mathieu-Daudé static DeviceClass *qdev_get_device_class(const char **driver, Error **errp)
2348d7f2e76SPhilippe Mathieu-Daudé {
2358d7f2e76SPhilippe Mathieu-Daudé ObjectClass *oc;
2368d7f2e76SPhilippe Mathieu-Daudé DeviceClass *dc;
2378d7f2e76SPhilippe Mathieu-Daudé const char *original_name = *driver;
2388d7f2e76SPhilippe Mathieu-Daudé
2398d7f2e76SPhilippe Mathieu-Daudé oc = module_object_class_by_name(*driver);
2408d7f2e76SPhilippe Mathieu-Daudé if (!oc) {
2418d7f2e76SPhilippe Mathieu-Daudé const char *typename = find_typename_by_alias(*driver);
2428d7f2e76SPhilippe Mathieu-Daudé
2438d7f2e76SPhilippe Mathieu-Daudé if (typename) {
2448d7f2e76SPhilippe Mathieu-Daudé *driver = typename;
2458d7f2e76SPhilippe Mathieu-Daudé oc = module_object_class_by_name(*driver);
2468d7f2e76SPhilippe Mathieu-Daudé }
2478d7f2e76SPhilippe Mathieu-Daudé }
2488d7f2e76SPhilippe Mathieu-Daudé
2498d7f2e76SPhilippe Mathieu-Daudé if (!object_class_dynamic_cast(oc, TYPE_DEVICE)) {
2508d7f2e76SPhilippe Mathieu-Daudé if (*driver != original_name) {
2518d7f2e76SPhilippe Mathieu-Daudé error_setg(errp, "'%s' (alias '%s') is not a valid device model"
2528d7f2e76SPhilippe Mathieu-Daudé " name", original_name, *driver);
2538d7f2e76SPhilippe Mathieu-Daudé } else {
2548d7f2e76SPhilippe Mathieu-Daudé error_setg(errp, "'%s' is not a valid device model name", *driver);
2558d7f2e76SPhilippe Mathieu-Daudé }
2568d7f2e76SPhilippe Mathieu-Daudé return NULL;
2578d7f2e76SPhilippe Mathieu-Daudé }
2588d7f2e76SPhilippe Mathieu-Daudé
2598d7f2e76SPhilippe Mathieu-Daudé if (object_class_is_abstract(oc)) {
2608d7f2e76SPhilippe Mathieu-Daudé error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
2618d7f2e76SPhilippe Mathieu-Daudé "a non-abstract device type");
2628d7f2e76SPhilippe Mathieu-Daudé return NULL;
2638d7f2e76SPhilippe Mathieu-Daudé }
2648d7f2e76SPhilippe Mathieu-Daudé
2658d7f2e76SPhilippe Mathieu-Daudé dc = DEVICE_CLASS(oc);
2668d7f2e76SPhilippe Mathieu-Daudé if (!dc->user_creatable ||
2678d7f2e76SPhilippe Mathieu-Daudé (phase_check(PHASE_MACHINE_READY) && !dc->hotpluggable)) {
2688d7f2e76SPhilippe Mathieu-Daudé error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
2698d7f2e76SPhilippe Mathieu-Daudé "a pluggable device type");
2708d7f2e76SPhilippe Mathieu-Daudé return NULL;
2718d7f2e76SPhilippe Mathieu-Daudé }
2728d7f2e76SPhilippe Mathieu-Daudé
2738d7f2e76SPhilippe Mathieu-Daudé if (object_class_dynamic_cast(oc, TYPE_SYS_BUS_DEVICE)) {
2748d7f2e76SPhilippe Mathieu-Daudé /* sysbus devices need to be allowed by the machine */
2758d7f2e76SPhilippe Mathieu-Daudé MachineClass *mc = MACHINE_CLASS(object_get_class(qdev_get_machine()));
2768d7f2e76SPhilippe Mathieu-Daudé if (!device_type_is_dynamic_sysbus(mc, *driver)) {
2778d7f2e76SPhilippe Mathieu-Daudé error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "driver",
2788d7f2e76SPhilippe Mathieu-Daudé "a dynamic sysbus device type for the machine");
2798d7f2e76SPhilippe Mathieu-Daudé return NULL;
2808d7f2e76SPhilippe Mathieu-Daudé }
2818d7f2e76SPhilippe Mathieu-Daudé }
2828d7f2e76SPhilippe Mathieu-Daudé
2838d7f2e76SPhilippe Mathieu-Daudé return dc;
2848d7f2e76SPhilippe Mathieu-Daudé }
2858d7f2e76SPhilippe Mathieu-Daudé
2868d7f2e76SPhilippe Mathieu-Daudé
qdev_device_help(QemuOpts * opts)2878d7f2e76SPhilippe Mathieu-Daudé int qdev_device_help(QemuOpts *opts)
2888d7f2e76SPhilippe Mathieu-Daudé {
2898d7f2e76SPhilippe Mathieu-Daudé Error *local_err = NULL;
2908d7f2e76SPhilippe Mathieu-Daudé const char *driver;
2918d7f2e76SPhilippe Mathieu-Daudé ObjectPropertyInfoList *prop_list;
2928d7f2e76SPhilippe Mathieu-Daudé ObjectPropertyInfoList *prop;
2938d7f2e76SPhilippe Mathieu-Daudé GPtrArray *array;
2948d7f2e76SPhilippe Mathieu-Daudé int i;
2958d7f2e76SPhilippe Mathieu-Daudé
2968d7f2e76SPhilippe Mathieu-Daudé driver = qemu_opt_get(opts, "driver");
2978d7f2e76SPhilippe Mathieu-Daudé if (driver && is_help_option(driver)) {
2988d7f2e76SPhilippe Mathieu-Daudé qdev_print_devinfos(false);
2998d7f2e76SPhilippe Mathieu-Daudé return 1;
3008d7f2e76SPhilippe Mathieu-Daudé }
3018d7f2e76SPhilippe Mathieu-Daudé
3028d7f2e76SPhilippe Mathieu-Daudé if (!driver || !qemu_opt_has_help_opt(opts)) {
3038d7f2e76SPhilippe Mathieu-Daudé return 0;
3048d7f2e76SPhilippe Mathieu-Daudé }
3058d7f2e76SPhilippe Mathieu-Daudé
3068d7f2e76SPhilippe Mathieu-Daudé if (!object_class_by_name(driver)) {
3078d7f2e76SPhilippe Mathieu-Daudé const char *typename = find_typename_by_alias(driver);
3088d7f2e76SPhilippe Mathieu-Daudé
3098d7f2e76SPhilippe Mathieu-Daudé if (typename) {
3108d7f2e76SPhilippe Mathieu-Daudé driver = typename;
3118d7f2e76SPhilippe Mathieu-Daudé }
3128d7f2e76SPhilippe Mathieu-Daudé }
3138d7f2e76SPhilippe Mathieu-Daudé
3148d7f2e76SPhilippe Mathieu-Daudé prop_list = qmp_device_list_properties(driver, &local_err);
3158d7f2e76SPhilippe Mathieu-Daudé if (local_err) {
3168d7f2e76SPhilippe Mathieu-Daudé goto error;
3178d7f2e76SPhilippe Mathieu-Daudé }
3188d7f2e76SPhilippe Mathieu-Daudé
3198d7f2e76SPhilippe Mathieu-Daudé if (prop_list) {
3208d7f2e76SPhilippe Mathieu-Daudé qemu_printf("%s options:\n", driver);
3218d7f2e76SPhilippe Mathieu-Daudé } else {
3228d7f2e76SPhilippe Mathieu-Daudé qemu_printf("There are no options for %s.\n", driver);
3238d7f2e76SPhilippe Mathieu-Daudé }
3248d7f2e76SPhilippe Mathieu-Daudé array = g_ptr_array_new();
3258d7f2e76SPhilippe Mathieu-Daudé for (prop = prop_list; prop; prop = prop->next) {
3268d7f2e76SPhilippe Mathieu-Daudé g_ptr_array_add(array,
3278d7f2e76SPhilippe Mathieu-Daudé object_property_help(prop->value->name,
3288d7f2e76SPhilippe Mathieu-Daudé prop->value->type,
3298d7f2e76SPhilippe Mathieu-Daudé prop->value->default_value,
3308d7f2e76SPhilippe Mathieu-Daudé prop->value->description));
3318d7f2e76SPhilippe Mathieu-Daudé }
3328d7f2e76SPhilippe Mathieu-Daudé g_ptr_array_sort(array, (GCompareFunc)qemu_pstrcmp0);
3338d7f2e76SPhilippe Mathieu-Daudé for (i = 0; i < array->len; i++) {
3348d7f2e76SPhilippe Mathieu-Daudé qemu_printf("%s\n", (char *)array->pdata[i]);
3358d7f2e76SPhilippe Mathieu-Daudé }
3368d7f2e76SPhilippe Mathieu-Daudé g_ptr_array_set_free_func(array, g_free);
3378d7f2e76SPhilippe Mathieu-Daudé g_ptr_array_free(array, true);
3388d7f2e76SPhilippe Mathieu-Daudé qapi_free_ObjectPropertyInfoList(prop_list);
3398d7f2e76SPhilippe Mathieu-Daudé return 1;
3408d7f2e76SPhilippe Mathieu-Daudé
3418d7f2e76SPhilippe Mathieu-Daudé error:
3428d7f2e76SPhilippe Mathieu-Daudé error_report_err(local_err);
3438d7f2e76SPhilippe Mathieu-Daudé return 1;
3448d7f2e76SPhilippe Mathieu-Daudé }
3458d7f2e76SPhilippe Mathieu-Daudé
qdev_get_peripheral(void)3468d7f2e76SPhilippe Mathieu-Daudé static Object *qdev_get_peripheral(void)
3478d7f2e76SPhilippe Mathieu-Daudé {
3488d7f2e76SPhilippe Mathieu-Daudé static Object *dev;
3498d7f2e76SPhilippe Mathieu-Daudé
3508d7f2e76SPhilippe Mathieu-Daudé if (dev == NULL) {
3518d7f2e76SPhilippe Mathieu-Daudé dev = container_get(qdev_get_machine(), "/peripheral");
3528d7f2e76SPhilippe Mathieu-Daudé }
3538d7f2e76SPhilippe Mathieu-Daudé
3548d7f2e76SPhilippe Mathieu-Daudé return dev;
3558d7f2e76SPhilippe Mathieu-Daudé }
3568d7f2e76SPhilippe Mathieu-Daudé
qdev_get_peripheral_anon(void)3578d7f2e76SPhilippe Mathieu-Daudé static Object *qdev_get_peripheral_anon(void)
3588d7f2e76SPhilippe Mathieu-Daudé {
3598d7f2e76SPhilippe Mathieu-Daudé static Object *dev;
3608d7f2e76SPhilippe Mathieu-Daudé
3618d7f2e76SPhilippe Mathieu-Daudé if (dev == NULL) {
3628d7f2e76SPhilippe Mathieu-Daudé dev = container_get(qdev_get_machine(), "/peripheral-anon");
3638d7f2e76SPhilippe Mathieu-Daudé }
3648d7f2e76SPhilippe Mathieu-Daudé
3658d7f2e76SPhilippe Mathieu-Daudé return dev;
3668d7f2e76SPhilippe Mathieu-Daudé }
3678d7f2e76SPhilippe Mathieu-Daudé
qbus_error_append_bus_list_hint(DeviceState * dev,Error * const * errp)3688d7f2e76SPhilippe Mathieu-Daudé static void qbus_error_append_bus_list_hint(DeviceState *dev,
3698d7f2e76SPhilippe Mathieu-Daudé Error *const *errp)
3708d7f2e76SPhilippe Mathieu-Daudé {
3718d7f2e76SPhilippe Mathieu-Daudé BusState *child;
3728d7f2e76SPhilippe Mathieu-Daudé const char *sep = " ";
3738d7f2e76SPhilippe Mathieu-Daudé
3748d7f2e76SPhilippe Mathieu-Daudé error_append_hint(errp, "child buses at \"%s\":",
3758d7f2e76SPhilippe Mathieu-Daudé dev->id ? dev->id : object_get_typename(OBJECT(dev)));
3768d7f2e76SPhilippe Mathieu-Daudé QLIST_FOREACH(child, &dev->child_bus, sibling) {
3778d7f2e76SPhilippe Mathieu-Daudé error_append_hint(errp, "%s\"%s\"", sep, child->name);
3788d7f2e76SPhilippe Mathieu-Daudé sep = ", ";
3798d7f2e76SPhilippe Mathieu-Daudé }
3808d7f2e76SPhilippe Mathieu-Daudé error_append_hint(errp, "\n");
3818d7f2e76SPhilippe Mathieu-Daudé }
3828d7f2e76SPhilippe Mathieu-Daudé
qbus_error_append_dev_list_hint(BusState * bus,Error * const * errp)3838d7f2e76SPhilippe Mathieu-Daudé static void qbus_error_append_dev_list_hint(BusState *bus,
3848d7f2e76SPhilippe Mathieu-Daudé Error *const *errp)
3858d7f2e76SPhilippe Mathieu-Daudé {
3868d7f2e76SPhilippe Mathieu-Daudé BusChild *kid;
3878d7f2e76SPhilippe Mathieu-Daudé const char *sep = " ";
3888d7f2e76SPhilippe Mathieu-Daudé
3898d7f2e76SPhilippe Mathieu-Daudé error_append_hint(errp, "devices at \"%s\":", bus->name);
3908d7f2e76SPhilippe Mathieu-Daudé QTAILQ_FOREACH(kid, &bus->children, sibling) {
3918d7f2e76SPhilippe Mathieu-Daudé DeviceState *dev = kid->child;
3928d7f2e76SPhilippe Mathieu-Daudé error_append_hint(errp, "%s\"%s\"", sep,
3938d7f2e76SPhilippe Mathieu-Daudé object_get_typename(OBJECT(dev)));
3948d7f2e76SPhilippe Mathieu-Daudé if (dev->id) {
3958d7f2e76SPhilippe Mathieu-Daudé error_append_hint(errp, "/\"%s\"", dev->id);
3968d7f2e76SPhilippe Mathieu-Daudé }
3978d7f2e76SPhilippe Mathieu-Daudé sep = ", ";
3988d7f2e76SPhilippe Mathieu-Daudé }
3998d7f2e76SPhilippe Mathieu-Daudé error_append_hint(errp, "\n");
4008d7f2e76SPhilippe Mathieu-Daudé }
4018d7f2e76SPhilippe Mathieu-Daudé
qbus_find_bus(DeviceState * dev,char * elem)4028d7f2e76SPhilippe Mathieu-Daudé static BusState *qbus_find_bus(DeviceState *dev, char *elem)
4038d7f2e76SPhilippe Mathieu-Daudé {
4048d7f2e76SPhilippe Mathieu-Daudé BusState *child;
4058d7f2e76SPhilippe Mathieu-Daudé
4068d7f2e76SPhilippe Mathieu-Daudé QLIST_FOREACH(child, &dev->child_bus, sibling) {
4078d7f2e76SPhilippe Mathieu-Daudé if (strcmp(child->name, elem) == 0) {
4088d7f2e76SPhilippe Mathieu-Daudé return child;
4098d7f2e76SPhilippe Mathieu-Daudé }
4108d7f2e76SPhilippe Mathieu-Daudé }
4118d7f2e76SPhilippe Mathieu-Daudé return NULL;
4128d7f2e76SPhilippe Mathieu-Daudé }
4138d7f2e76SPhilippe Mathieu-Daudé
qbus_find_dev(BusState * bus,char * elem)4148d7f2e76SPhilippe Mathieu-Daudé static DeviceState *qbus_find_dev(BusState *bus, char *elem)
4158d7f2e76SPhilippe Mathieu-Daudé {
4168d7f2e76SPhilippe Mathieu-Daudé BusChild *kid;
4178d7f2e76SPhilippe Mathieu-Daudé
4188d7f2e76SPhilippe Mathieu-Daudé /*
4198d7f2e76SPhilippe Mathieu-Daudé * try to match in order:
4208d7f2e76SPhilippe Mathieu-Daudé * (1) instance id, if present
4218d7f2e76SPhilippe Mathieu-Daudé * (2) driver name
4228d7f2e76SPhilippe Mathieu-Daudé * (3) driver alias, if present
4238d7f2e76SPhilippe Mathieu-Daudé */
4248d7f2e76SPhilippe Mathieu-Daudé QTAILQ_FOREACH(kid, &bus->children, sibling) {
4258d7f2e76SPhilippe Mathieu-Daudé DeviceState *dev = kid->child;
4268d7f2e76SPhilippe Mathieu-Daudé if (dev->id && strcmp(dev->id, elem) == 0) {
4278d7f2e76SPhilippe Mathieu-Daudé return dev;
4288d7f2e76SPhilippe Mathieu-Daudé }
4298d7f2e76SPhilippe Mathieu-Daudé }
4308d7f2e76SPhilippe Mathieu-Daudé QTAILQ_FOREACH(kid, &bus->children, sibling) {
4318d7f2e76SPhilippe Mathieu-Daudé DeviceState *dev = kid->child;
4328d7f2e76SPhilippe Mathieu-Daudé if (strcmp(object_get_typename(OBJECT(dev)), elem) == 0) {
4338d7f2e76SPhilippe Mathieu-Daudé return dev;
4348d7f2e76SPhilippe Mathieu-Daudé }
4358d7f2e76SPhilippe Mathieu-Daudé }
4368d7f2e76SPhilippe Mathieu-Daudé QTAILQ_FOREACH(kid, &bus->children, sibling) {
4378d7f2e76SPhilippe Mathieu-Daudé DeviceState *dev = kid->child;
4388d7f2e76SPhilippe Mathieu-Daudé DeviceClass *dc = DEVICE_GET_CLASS(dev);
4398d7f2e76SPhilippe Mathieu-Daudé
4408d7f2e76SPhilippe Mathieu-Daudé if (qdev_class_has_alias(dc) &&
4418d7f2e76SPhilippe Mathieu-Daudé strcmp(qdev_class_get_alias(dc), elem) == 0) {
4428d7f2e76SPhilippe Mathieu-Daudé return dev;
4438d7f2e76SPhilippe Mathieu-Daudé }
4448d7f2e76SPhilippe Mathieu-Daudé }
4458d7f2e76SPhilippe Mathieu-Daudé return NULL;
4468d7f2e76SPhilippe Mathieu-Daudé }
4478d7f2e76SPhilippe Mathieu-Daudé
qbus_is_full(BusState * bus)4488d7f2e76SPhilippe Mathieu-Daudé static inline bool qbus_is_full(BusState *bus)
4498d7f2e76SPhilippe Mathieu-Daudé {
4508d7f2e76SPhilippe Mathieu-Daudé BusClass *bus_class;
4518d7f2e76SPhilippe Mathieu-Daudé
4528d7f2e76SPhilippe Mathieu-Daudé if (bus->full) {
4538d7f2e76SPhilippe Mathieu-Daudé return true;
4548d7f2e76SPhilippe Mathieu-Daudé }
4558d7f2e76SPhilippe Mathieu-Daudé bus_class = BUS_GET_CLASS(bus);
4568d7f2e76SPhilippe Mathieu-Daudé return bus_class->max_dev && bus->num_children >= bus_class->max_dev;
4578d7f2e76SPhilippe Mathieu-Daudé }
4588d7f2e76SPhilippe Mathieu-Daudé
4598d7f2e76SPhilippe Mathieu-Daudé /*
4608d7f2e76SPhilippe Mathieu-Daudé * Search the tree rooted at @bus for a bus.
4618d7f2e76SPhilippe Mathieu-Daudé * If @name, search for a bus with that name. Note that bus names
4628d7f2e76SPhilippe Mathieu-Daudé * need not be unique. Yes, that's screwed up.
4638d7f2e76SPhilippe Mathieu-Daudé * Else search for a bus that is a subtype of @bus_typename.
4648d7f2e76SPhilippe Mathieu-Daudé * If more than one exists, prefer one that can take another device.
4658d7f2e76SPhilippe Mathieu-Daudé * Return the bus if found, else %NULL.
4668d7f2e76SPhilippe Mathieu-Daudé */
qbus_find_recursive(BusState * bus,const char * name,const char * bus_typename)4678d7f2e76SPhilippe Mathieu-Daudé static BusState *qbus_find_recursive(BusState *bus, const char *name,
4688d7f2e76SPhilippe Mathieu-Daudé const char *bus_typename)
4698d7f2e76SPhilippe Mathieu-Daudé {
4708d7f2e76SPhilippe Mathieu-Daudé BusChild *kid;
4718d7f2e76SPhilippe Mathieu-Daudé BusState *pick, *child, *ret;
4728d7f2e76SPhilippe Mathieu-Daudé bool match;
4738d7f2e76SPhilippe Mathieu-Daudé
4748d7f2e76SPhilippe Mathieu-Daudé assert(name || bus_typename);
4758d7f2e76SPhilippe Mathieu-Daudé if (name) {
4768d7f2e76SPhilippe Mathieu-Daudé match = !strcmp(bus->name, name);
4778d7f2e76SPhilippe Mathieu-Daudé } else {
4788d7f2e76SPhilippe Mathieu-Daudé match = !!object_dynamic_cast(OBJECT(bus), bus_typename);
4798d7f2e76SPhilippe Mathieu-Daudé }
4808d7f2e76SPhilippe Mathieu-Daudé
4818d7f2e76SPhilippe Mathieu-Daudé if (match && !qbus_is_full(bus)) {
4828d7f2e76SPhilippe Mathieu-Daudé return bus; /* root matches and isn't full */
4838d7f2e76SPhilippe Mathieu-Daudé }
4848d7f2e76SPhilippe Mathieu-Daudé
4858d7f2e76SPhilippe Mathieu-Daudé pick = match ? bus : NULL;
4868d7f2e76SPhilippe Mathieu-Daudé
4878d7f2e76SPhilippe Mathieu-Daudé QTAILQ_FOREACH(kid, &bus->children, sibling) {
4888d7f2e76SPhilippe Mathieu-Daudé DeviceState *dev = kid->child;
4898d7f2e76SPhilippe Mathieu-Daudé QLIST_FOREACH(child, &dev->child_bus, sibling) {
4908d7f2e76SPhilippe Mathieu-Daudé ret = qbus_find_recursive(child, name, bus_typename);
4918d7f2e76SPhilippe Mathieu-Daudé if (ret && !qbus_is_full(ret)) {
4928d7f2e76SPhilippe Mathieu-Daudé return ret; /* a descendant matches and isn't full */
4938d7f2e76SPhilippe Mathieu-Daudé }
4948d7f2e76SPhilippe Mathieu-Daudé if (ret && !pick) {
4958d7f2e76SPhilippe Mathieu-Daudé pick = ret;
4968d7f2e76SPhilippe Mathieu-Daudé }
4978d7f2e76SPhilippe Mathieu-Daudé }
4988d7f2e76SPhilippe Mathieu-Daudé }
4998d7f2e76SPhilippe Mathieu-Daudé
5008d7f2e76SPhilippe Mathieu-Daudé /* root or a descendant matches, but is full */
5018d7f2e76SPhilippe Mathieu-Daudé return pick;
5028d7f2e76SPhilippe Mathieu-Daudé }
5038d7f2e76SPhilippe Mathieu-Daudé
qbus_find(const char * path,Error ** errp)5048d7f2e76SPhilippe Mathieu-Daudé static BusState *qbus_find(const char *path, Error **errp)
5058d7f2e76SPhilippe Mathieu-Daudé {
5068d7f2e76SPhilippe Mathieu-Daudé DeviceState *dev;
5078d7f2e76SPhilippe Mathieu-Daudé BusState *bus;
5088d7f2e76SPhilippe Mathieu-Daudé char elem[128];
5098d7f2e76SPhilippe Mathieu-Daudé int pos, len;
5108d7f2e76SPhilippe Mathieu-Daudé
5118d7f2e76SPhilippe Mathieu-Daudé /* find start element */
5128d7f2e76SPhilippe Mathieu-Daudé if (path[0] == '/') {
5138d7f2e76SPhilippe Mathieu-Daudé bus = sysbus_get_default();
5148d7f2e76SPhilippe Mathieu-Daudé pos = 0;
5158d7f2e76SPhilippe Mathieu-Daudé } else {
5168d7f2e76SPhilippe Mathieu-Daudé if (sscanf(path, "%127[^/]%n", elem, &len) != 1) {
5178d7f2e76SPhilippe Mathieu-Daudé assert(!path[0]);
5188d7f2e76SPhilippe Mathieu-Daudé elem[0] = len = 0;
5198d7f2e76SPhilippe Mathieu-Daudé }
5208d7f2e76SPhilippe Mathieu-Daudé bus = qbus_find_recursive(sysbus_get_default(), elem, NULL);
5218d7f2e76SPhilippe Mathieu-Daudé if (!bus) {
5228d7f2e76SPhilippe Mathieu-Daudé error_setg(errp, "Bus '%s' not found", elem);
5238d7f2e76SPhilippe Mathieu-Daudé return NULL;
5248d7f2e76SPhilippe Mathieu-Daudé }
5258d7f2e76SPhilippe Mathieu-Daudé pos = len;
5268d7f2e76SPhilippe Mathieu-Daudé }
5278d7f2e76SPhilippe Mathieu-Daudé
5288d7f2e76SPhilippe Mathieu-Daudé for (;;) {
5298d7f2e76SPhilippe Mathieu-Daudé assert(path[pos] == '/' || !path[pos]);
5308d7f2e76SPhilippe Mathieu-Daudé while (path[pos] == '/') {
5318d7f2e76SPhilippe Mathieu-Daudé pos++;
5328d7f2e76SPhilippe Mathieu-Daudé }
5338d7f2e76SPhilippe Mathieu-Daudé if (path[pos] == '\0') {
5348d7f2e76SPhilippe Mathieu-Daudé break;
5358d7f2e76SPhilippe Mathieu-Daudé }
5368d7f2e76SPhilippe Mathieu-Daudé
5378d7f2e76SPhilippe Mathieu-Daudé /* find device */
5388d7f2e76SPhilippe Mathieu-Daudé if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
5398d7f2e76SPhilippe Mathieu-Daudé g_assert_not_reached();
5408d7f2e76SPhilippe Mathieu-Daudé elem[0] = len = 0;
5418d7f2e76SPhilippe Mathieu-Daudé }
5428d7f2e76SPhilippe Mathieu-Daudé pos += len;
5438d7f2e76SPhilippe Mathieu-Daudé dev = qbus_find_dev(bus, elem);
5448d7f2e76SPhilippe Mathieu-Daudé if (!dev) {
5458d7f2e76SPhilippe Mathieu-Daudé error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
5468d7f2e76SPhilippe Mathieu-Daudé "Device '%s' not found", elem);
5478d7f2e76SPhilippe Mathieu-Daudé qbus_error_append_dev_list_hint(bus, errp);
5488d7f2e76SPhilippe Mathieu-Daudé return NULL;
5498d7f2e76SPhilippe Mathieu-Daudé }
5508d7f2e76SPhilippe Mathieu-Daudé
5518d7f2e76SPhilippe Mathieu-Daudé assert(path[pos] == '/' || !path[pos]);
5528d7f2e76SPhilippe Mathieu-Daudé while (path[pos] == '/') {
5538d7f2e76SPhilippe Mathieu-Daudé pos++;
5548d7f2e76SPhilippe Mathieu-Daudé }
5558d7f2e76SPhilippe Mathieu-Daudé if (path[pos] == '\0') {
5568d7f2e76SPhilippe Mathieu-Daudé /* last specified element is a device. If it has exactly
5578d7f2e76SPhilippe Mathieu-Daudé * one child bus accept it nevertheless */
5588d7f2e76SPhilippe Mathieu-Daudé if (dev->num_child_bus == 1) {
5598d7f2e76SPhilippe Mathieu-Daudé bus = QLIST_FIRST(&dev->child_bus);
5608d7f2e76SPhilippe Mathieu-Daudé break;
5618d7f2e76SPhilippe Mathieu-Daudé }
5628d7f2e76SPhilippe Mathieu-Daudé if (dev->num_child_bus) {
5638d7f2e76SPhilippe Mathieu-Daudé error_setg(errp, "Device '%s' has multiple child buses",
5648d7f2e76SPhilippe Mathieu-Daudé elem);
5658d7f2e76SPhilippe Mathieu-Daudé qbus_error_append_bus_list_hint(dev, errp);
5668d7f2e76SPhilippe Mathieu-Daudé } else {
5678d7f2e76SPhilippe Mathieu-Daudé error_setg(errp, "Device '%s' has no child bus", elem);
5688d7f2e76SPhilippe Mathieu-Daudé }
5698d7f2e76SPhilippe Mathieu-Daudé return NULL;
5708d7f2e76SPhilippe Mathieu-Daudé }
5718d7f2e76SPhilippe Mathieu-Daudé
5728d7f2e76SPhilippe Mathieu-Daudé /* find bus */
5738d7f2e76SPhilippe Mathieu-Daudé if (sscanf(path+pos, "%127[^/]%n", elem, &len) != 1) {
5748d7f2e76SPhilippe Mathieu-Daudé g_assert_not_reached();
5758d7f2e76SPhilippe Mathieu-Daudé elem[0] = len = 0;
5768d7f2e76SPhilippe Mathieu-Daudé }
5778d7f2e76SPhilippe Mathieu-Daudé pos += len;
5788d7f2e76SPhilippe Mathieu-Daudé bus = qbus_find_bus(dev, elem);
5798d7f2e76SPhilippe Mathieu-Daudé if (!bus) {
5808d7f2e76SPhilippe Mathieu-Daudé error_setg(errp, "Bus '%s' not found", elem);
5818d7f2e76SPhilippe Mathieu-Daudé qbus_error_append_bus_list_hint(dev, errp);
5828d7f2e76SPhilippe Mathieu-Daudé return NULL;
5838d7f2e76SPhilippe Mathieu-Daudé }
5848d7f2e76SPhilippe Mathieu-Daudé }
5858d7f2e76SPhilippe Mathieu-Daudé
5868d7f2e76SPhilippe Mathieu-Daudé if (qbus_is_full(bus)) {
5878d7f2e76SPhilippe Mathieu-Daudé error_setg(errp, "Bus '%s' is full", path);
5888d7f2e76SPhilippe Mathieu-Daudé return NULL;
5898d7f2e76SPhilippe Mathieu-Daudé }
5908d7f2e76SPhilippe Mathieu-Daudé return bus;
5918d7f2e76SPhilippe Mathieu-Daudé }
5928d7f2e76SPhilippe Mathieu-Daudé
5938d7f2e76SPhilippe Mathieu-Daudé /* Takes ownership of @id, will be freed when deleting the device */
qdev_set_id(DeviceState * dev,char * id,Error ** errp)5948d7f2e76SPhilippe Mathieu-Daudé const char *qdev_set_id(DeviceState *dev, char *id, Error **errp)
5958d7f2e76SPhilippe Mathieu-Daudé {
5968d7f2e76SPhilippe Mathieu-Daudé ObjectProperty *prop;
5978d7f2e76SPhilippe Mathieu-Daudé
5988d7f2e76SPhilippe Mathieu-Daudé assert(!dev->id && !dev->realized);
5998d7f2e76SPhilippe Mathieu-Daudé
6008d7f2e76SPhilippe Mathieu-Daudé /*
6018d7f2e76SPhilippe Mathieu-Daudé * object_property_[try_]add_child() below will assert the device
6028d7f2e76SPhilippe Mathieu-Daudé * has no parent
6038d7f2e76SPhilippe Mathieu-Daudé */
6048d7f2e76SPhilippe Mathieu-Daudé if (id) {
6058d7f2e76SPhilippe Mathieu-Daudé prop = object_property_try_add_child(qdev_get_peripheral(), id,
6068d7f2e76SPhilippe Mathieu-Daudé OBJECT(dev), NULL);
6078d7f2e76SPhilippe Mathieu-Daudé if (prop) {
6088d7f2e76SPhilippe Mathieu-Daudé dev->id = id;
6098d7f2e76SPhilippe Mathieu-Daudé } else {
6108d7f2e76SPhilippe Mathieu-Daudé error_setg(errp, "Duplicate device ID '%s'", id);
6118d7f2e76SPhilippe Mathieu-Daudé g_free(id);
6128d7f2e76SPhilippe Mathieu-Daudé return NULL;
6138d7f2e76SPhilippe Mathieu-Daudé }
6148d7f2e76SPhilippe Mathieu-Daudé } else {
6158d7f2e76SPhilippe Mathieu-Daudé static int anon_count;
6168d7f2e76SPhilippe Mathieu-Daudé gchar *name = g_strdup_printf("device[%d]", anon_count++);
6178d7f2e76SPhilippe Mathieu-Daudé prop = object_property_add_child(qdev_get_peripheral_anon(), name,
6188d7f2e76SPhilippe Mathieu-Daudé OBJECT(dev));
6198d7f2e76SPhilippe Mathieu-Daudé g_free(name);
6208d7f2e76SPhilippe Mathieu-Daudé }
6218d7f2e76SPhilippe Mathieu-Daudé
6228d7f2e76SPhilippe Mathieu-Daudé return prop->name;
6238d7f2e76SPhilippe Mathieu-Daudé }
6248d7f2e76SPhilippe Mathieu-Daudé
qdev_device_add_from_qdict(const QDict * opts,bool from_json,Error ** errp)6258d7f2e76SPhilippe Mathieu-Daudé DeviceState *qdev_device_add_from_qdict(const QDict *opts,
6268d7f2e76SPhilippe Mathieu-Daudé bool from_json, Error **errp)
6278d7f2e76SPhilippe Mathieu-Daudé {
6288d7f2e76SPhilippe Mathieu-Daudé ERRP_GUARD();
6298d7f2e76SPhilippe Mathieu-Daudé DeviceClass *dc;
6308d7f2e76SPhilippe Mathieu-Daudé const char *driver, *path;
6318d7f2e76SPhilippe Mathieu-Daudé char *id;
6328d7f2e76SPhilippe Mathieu-Daudé DeviceState *dev = NULL;
6338d7f2e76SPhilippe Mathieu-Daudé BusState *bus = NULL;
6348d7f2e76SPhilippe Mathieu-Daudé
6358d7f2e76SPhilippe Mathieu-Daudé driver = qdict_get_try_str(opts, "driver");
6368d7f2e76SPhilippe Mathieu-Daudé if (!driver) {
6378d7f2e76SPhilippe Mathieu-Daudé error_setg(errp, QERR_MISSING_PARAMETER, "driver");
6388d7f2e76SPhilippe Mathieu-Daudé return NULL;
6398d7f2e76SPhilippe Mathieu-Daudé }
6408d7f2e76SPhilippe Mathieu-Daudé
6418d7f2e76SPhilippe Mathieu-Daudé /* find driver */
6428d7f2e76SPhilippe Mathieu-Daudé dc = qdev_get_device_class(&driver, errp);
6438d7f2e76SPhilippe Mathieu-Daudé if (!dc) {
6448d7f2e76SPhilippe Mathieu-Daudé return NULL;
6458d7f2e76SPhilippe Mathieu-Daudé }
6468d7f2e76SPhilippe Mathieu-Daudé
6478d7f2e76SPhilippe Mathieu-Daudé /* find bus */
6488d7f2e76SPhilippe Mathieu-Daudé path = qdict_get_try_str(opts, "bus");
6498d7f2e76SPhilippe Mathieu-Daudé if (path != NULL) {
6508d7f2e76SPhilippe Mathieu-Daudé bus = qbus_find(path, errp);
6518d7f2e76SPhilippe Mathieu-Daudé if (!bus) {
6528d7f2e76SPhilippe Mathieu-Daudé return NULL;
6538d7f2e76SPhilippe Mathieu-Daudé }
6548d7f2e76SPhilippe Mathieu-Daudé if (!object_dynamic_cast(OBJECT(bus), dc->bus_type)) {
6558d7f2e76SPhilippe Mathieu-Daudé error_setg(errp, "Device '%s' can't go on %s bus",
6568d7f2e76SPhilippe Mathieu-Daudé driver, object_get_typename(OBJECT(bus)));
6578d7f2e76SPhilippe Mathieu-Daudé return NULL;
6588d7f2e76SPhilippe Mathieu-Daudé }
6598d7f2e76SPhilippe Mathieu-Daudé } else if (dc->bus_type != NULL) {
6608d7f2e76SPhilippe Mathieu-Daudé bus = qbus_find_recursive(sysbus_get_default(), NULL, dc->bus_type);
6618d7f2e76SPhilippe Mathieu-Daudé if (!bus || qbus_is_full(bus)) {
6628d7f2e76SPhilippe Mathieu-Daudé error_setg(errp, "No '%s' bus found for device '%s'",
6638d7f2e76SPhilippe Mathieu-Daudé dc->bus_type, driver);
6648d7f2e76SPhilippe Mathieu-Daudé return NULL;
6658d7f2e76SPhilippe Mathieu-Daudé }
6668d7f2e76SPhilippe Mathieu-Daudé }
6678d7f2e76SPhilippe Mathieu-Daudé
6688d7f2e76SPhilippe Mathieu-Daudé if (qdev_should_hide_device(opts, from_json, errp)) {
6698d7f2e76SPhilippe Mathieu-Daudé if (bus && !qbus_is_hotpluggable(bus)) {
6707f65e789SPhilippe Mathieu-Daudé error_setg(errp, "Bus '%s' does not support hotplugging",
6717f65e789SPhilippe Mathieu-Daudé bus->name);
6728d7f2e76SPhilippe Mathieu-Daudé }
6738d7f2e76SPhilippe Mathieu-Daudé return NULL;
6748d7f2e76SPhilippe Mathieu-Daudé } else if (*errp) {
6758d7f2e76SPhilippe Mathieu-Daudé return NULL;
6768d7f2e76SPhilippe Mathieu-Daudé }
6778d7f2e76SPhilippe Mathieu-Daudé
6788d7f2e76SPhilippe Mathieu-Daudé if (phase_check(PHASE_MACHINE_READY) && bus && !qbus_is_hotpluggable(bus)) {
6797f65e789SPhilippe Mathieu-Daudé error_setg(errp, "Bus '%s' does not support hotplugging", bus->name);
6808d7f2e76SPhilippe Mathieu-Daudé return NULL;
6818d7f2e76SPhilippe Mathieu-Daudé }
6828d7f2e76SPhilippe Mathieu-Daudé
68334a8892dSPeter Xu if (migration_is_running()) {
6848d7f2e76SPhilippe Mathieu-Daudé error_setg(errp, "device_add not allowed while migrating");
6858d7f2e76SPhilippe Mathieu-Daudé return NULL;
6868d7f2e76SPhilippe Mathieu-Daudé }
6878d7f2e76SPhilippe Mathieu-Daudé
6888d7f2e76SPhilippe Mathieu-Daudé /* create device */
6898d7f2e76SPhilippe Mathieu-Daudé dev = qdev_new(driver);
6908d7f2e76SPhilippe Mathieu-Daudé
6918d7f2e76SPhilippe Mathieu-Daudé /* Check whether the hotplug is allowed by the machine */
6928d7f2e76SPhilippe Mathieu-Daudé if (phase_check(PHASE_MACHINE_READY)) {
6938d7f2e76SPhilippe Mathieu-Daudé if (!qdev_hotplug_allowed(dev, errp)) {
6948d7f2e76SPhilippe Mathieu-Daudé goto err_del_dev;
6958d7f2e76SPhilippe Mathieu-Daudé }
6968d7f2e76SPhilippe Mathieu-Daudé
6978d7f2e76SPhilippe Mathieu-Daudé if (!bus && !qdev_get_machine_hotplug_handler(dev)) {
6988d7f2e76SPhilippe Mathieu-Daudé /* No bus, no machine hotplug handler --> device is not hotpluggable */
6998d7f2e76SPhilippe Mathieu-Daudé error_setg(errp, "Device '%s' can not be hotplugged on this machine",
7008d7f2e76SPhilippe Mathieu-Daudé driver);
7018d7f2e76SPhilippe Mathieu-Daudé goto err_del_dev;
7028d7f2e76SPhilippe Mathieu-Daudé }
7038d7f2e76SPhilippe Mathieu-Daudé }
7048d7f2e76SPhilippe Mathieu-Daudé
7058d7f2e76SPhilippe Mathieu-Daudé /*
7068d7f2e76SPhilippe Mathieu-Daudé * set dev's parent and register its id.
7078d7f2e76SPhilippe Mathieu-Daudé * If it fails it means the id is already taken.
7088d7f2e76SPhilippe Mathieu-Daudé */
7098d7f2e76SPhilippe Mathieu-Daudé id = g_strdup(qdict_get_try_str(opts, "id"));
7108d7f2e76SPhilippe Mathieu-Daudé if (!qdev_set_id(dev, id, errp)) {
7118d7f2e76SPhilippe Mathieu-Daudé goto err_del_dev;
7128d7f2e76SPhilippe Mathieu-Daudé }
7138d7f2e76SPhilippe Mathieu-Daudé
7148d7f2e76SPhilippe Mathieu-Daudé /* set properties */
7158d7f2e76SPhilippe Mathieu-Daudé dev->opts = qdict_clone_shallow(opts);
7168d7f2e76SPhilippe Mathieu-Daudé qdict_del(dev->opts, "driver");
7178d7f2e76SPhilippe Mathieu-Daudé qdict_del(dev->opts, "bus");
7188d7f2e76SPhilippe Mathieu-Daudé qdict_del(dev->opts, "id");
7198d7f2e76SPhilippe Mathieu-Daudé
7208d7f2e76SPhilippe Mathieu-Daudé object_set_properties_from_keyval(&dev->parent_obj, dev->opts, from_json,
7218d7f2e76SPhilippe Mathieu-Daudé errp);
7228d7f2e76SPhilippe Mathieu-Daudé if (*errp) {
7238d7f2e76SPhilippe Mathieu-Daudé goto err_del_dev;
7248d7f2e76SPhilippe Mathieu-Daudé }
7258d7f2e76SPhilippe Mathieu-Daudé
7268d7f2e76SPhilippe Mathieu-Daudé if (!qdev_realize(dev, bus, errp)) {
7278d7f2e76SPhilippe Mathieu-Daudé goto err_del_dev;
7288d7f2e76SPhilippe Mathieu-Daudé }
7298d7f2e76SPhilippe Mathieu-Daudé return dev;
7308d7f2e76SPhilippe Mathieu-Daudé
7318d7f2e76SPhilippe Mathieu-Daudé err_del_dev:
7328d7f2e76SPhilippe Mathieu-Daudé if (dev) {
7338d7f2e76SPhilippe Mathieu-Daudé object_unparent(OBJECT(dev));
7348d7f2e76SPhilippe Mathieu-Daudé object_unref(OBJECT(dev));
7358d7f2e76SPhilippe Mathieu-Daudé }
7368d7f2e76SPhilippe Mathieu-Daudé return NULL;
7378d7f2e76SPhilippe Mathieu-Daudé }
7388d7f2e76SPhilippe Mathieu-Daudé
7398d7f2e76SPhilippe Mathieu-Daudé /* Takes ownership of @opts on success */
qdev_device_add(QemuOpts * opts,Error ** errp)7408d7f2e76SPhilippe Mathieu-Daudé DeviceState *qdev_device_add(QemuOpts *opts, Error **errp)
7418d7f2e76SPhilippe Mathieu-Daudé {
7428d7f2e76SPhilippe Mathieu-Daudé QDict *qdict = qemu_opts_to_qdict(opts, NULL);
7438d7f2e76SPhilippe Mathieu-Daudé DeviceState *ret;
7448d7f2e76SPhilippe Mathieu-Daudé
7458d7f2e76SPhilippe Mathieu-Daudé ret = qdev_device_add_from_qdict(qdict, false, errp);
7468d7f2e76SPhilippe Mathieu-Daudé if (ret) {
7478d7f2e76SPhilippe Mathieu-Daudé qemu_opts_del(opts);
7488d7f2e76SPhilippe Mathieu-Daudé }
7498d7f2e76SPhilippe Mathieu-Daudé qobject_unref(qdict);
7508d7f2e76SPhilippe Mathieu-Daudé return ret;
7518d7f2e76SPhilippe Mathieu-Daudé }
7528d7f2e76SPhilippe Mathieu-Daudé
7538d7f2e76SPhilippe Mathieu-Daudé #define qdev_printf(fmt, ...) monitor_printf(mon, "%*s" fmt, indent, "", ## __VA_ARGS__)
7548d7f2e76SPhilippe Mathieu-Daudé
qdev_print_props(Monitor * mon,DeviceState * dev,const Property * props,int indent)755d36f165dSPaolo Bonzini static void qdev_print_props(Monitor *mon, DeviceState *dev, const Property *props,
7568d7f2e76SPhilippe Mathieu-Daudé int indent)
7578d7f2e76SPhilippe Mathieu-Daudé {
7588d7f2e76SPhilippe Mathieu-Daudé if (!props)
7598d7f2e76SPhilippe Mathieu-Daudé return;
7608d7f2e76SPhilippe Mathieu-Daudé for (; props->name; props++) {
7618d7f2e76SPhilippe Mathieu-Daudé char *value;
7628d7f2e76SPhilippe Mathieu-Daudé char *legacy_name = g_strdup_printf("legacy-%s", props->name);
7638d7f2e76SPhilippe Mathieu-Daudé
7648d7f2e76SPhilippe Mathieu-Daudé if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
7658d7f2e76SPhilippe Mathieu-Daudé value = object_property_get_str(OBJECT(dev), legacy_name, NULL);
7668d7f2e76SPhilippe Mathieu-Daudé } else {
7678d7f2e76SPhilippe Mathieu-Daudé value = object_property_print(OBJECT(dev), props->name, true,
7688d7f2e76SPhilippe Mathieu-Daudé NULL);
7698d7f2e76SPhilippe Mathieu-Daudé }
7708d7f2e76SPhilippe Mathieu-Daudé g_free(legacy_name);
7718d7f2e76SPhilippe Mathieu-Daudé
7728d7f2e76SPhilippe Mathieu-Daudé if (!value) {
7738d7f2e76SPhilippe Mathieu-Daudé continue;
7748d7f2e76SPhilippe Mathieu-Daudé }
7758d7f2e76SPhilippe Mathieu-Daudé qdev_printf("%s = %s\n", props->name,
7768d7f2e76SPhilippe Mathieu-Daudé *value ? value : "<null>");
7778d7f2e76SPhilippe Mathieu-Daudé g_free(value);
7788d7f2e76SPhilippe Mathieu-Daudé }
7798d7f2e76SPhilippe Mathieu-Daudé }
7808d7f2e76SPhilippe Mathieu-Daudé
bus_print_dev(BusState * bus,Monitor * mon,DeviceState * dev,int indent)7818d7f2e76SPhilippe Mathieu-Daudé static void bus_print_dev(BusState *bus, Monitor *mon, DeviceState *dev, int indent)
7828d7f2e76SPhilippe Mathieu-Daudé {
7838d7f2e76SPhilippe Mathieu-Daudé BusClass *bc = BUS_GET_CLASS(bus);
7848d7f2e76SPhilippe Mathieu-Daudé
7858d7f2e76SPhilippe Mathieu-Daudé if (bc->print_dev) {
7868d7f2e76SPhilippe Mathieu-Daudé bc->print_dev(mon, dev, indent);
7878d7f2e76SPhilippe Mathieu-Daudé }
7888d7f2e76SPhilippe Mathieu-Daudé }
7898d7f2e76SPhilippe Mathieu-Daudé
qdev_print(Monitor * mon,DeviceState * dev,int indent)7908d7f2e76SPhilippe Mathieu-Daudé static void qdev_print(Monitor *mon, DeviceState *dev, int indent)
7918d7f2e76SPhilippe Mathieu-Daudé {
7928d7f2e76SPhilippe Mathieu-Daudé ObjectClass *class;
7938d7f2e76SPhilippe Mathieu-Daudé NamedGPIOList *ngl;
7948d7f2e76SPhilippe Mathieu-Daudé NamedClockList *ncl;
7958d7f2e76SPhilippe Mathieu-Daudé
7968d7f2e76SPhilippe Mathieu-Daudé QLIST_FOREACH(ngl, &dev->gpios, node) {
7978d7f2e76SPhilippe Mathieu-Daudé if (ngl->num_in) {
7988d7f2e76SPhilippe Mathieu-Daudé qdev_printf("gpio-in \"%s\" %d\n", ngl->name ? ngl->name : "",
7998d7f2e76SPhilippe Mathieu-Daudé ngl->num_in);
8008d7f2e76SPhilippe Mathieu-Daudé }
8018d7f2e76SPhilippe Mathieu-Daudé if (ngl->num_out) {
8028d7f2e76SPhilippe Mathieu-Daudé qdev_printf("gpio-out \"%s\" %d\n", ngl->name ? ngl->name : "",
8038d7f2e76SPhilippe Mathieu-Daudé ngl->num_out);
8048d7f2e76SPhilippe Mathieu-Daudé }
8058d7f2e76SPhilippe Mathieu-Daudé }
8068d7f2e76SPhilippe Mathieu-Daudé QLIST_FOREACH(ncl, &dev->clocks, node) {
8078d7f2e76SPhilippe Mathieu-Daudé g_autofree char *freq_str = clock_display_freq(ncl->clock);
8088d7f2e76SPhilippe Mathieu-Daudé qdev_printf("clock-%s%s \"%s\" freq_hz=%s\n",
8098d7f2e76SPhilippe Mathieu-Daudé ncl->output ? "out" : "in",
8108d7f2e76SPhilippe Mathieu-Daudé ncl->alias ? " (alias)" : "",
8118d7f2e76SPhilippe Mathieu-Daudé ncl->name, freq_str);
8128d7f2e76SPhilippe Mathieu-Daudé }
8138d7f2e76SPhilippe Mathieu-Daudé class = object_get_class(OBJECT(dev));
8148d7f2e76SPhilippe Mathieu-Daudé do {
8158d7f2e76SPhilippe Mathieu-Daudé qdev_print_props(mon, dev, DEVICE_CLASS(class)->props_, indent);
8168d7f2e76SPhilippe Mathieu-Daudé class = object_class_get_parent(class);
8178d7f2e76SPhilippe Mathieu-Daudé } while (class != object_class_by_name(TYPE_DEVICE));
8188d7f2e76SPhilippe Mathieu-Daudé bus_print_dev(dev->parent_bus, mon, dev, indent);
8198d7f2e76SPhilippe Mathieu-Daudé }
8208d7f2e76SPhilippe Mathieu-Daudé
qbus_print(Monitor * mon,BusState * bus,int indent,bool details)82146e23b2eSBALATON Zoltan static void qbus_print(Monitor *mon, BusState *bus, int indent, bool details)
8228d7f2e76SPhilippe Mathieu-Daudé {
8238d7f2e76SPhilippe Mathieu-Daudé BusChild *kid;
8248d7f2e76SPhilippe Mathieu-Daudé
8258d7f2e76SPhilippe Mathieu-Daudé qdev_printf("bus: %s\n", bus->name);
8268d7f2e76SPhilippe Mathieu-Daudé indent += 2;
8278d7f2e76SPhilippe Mathieu-Daudé qdev_printf("type %s\n", object_get_typename(OBJECT(bus)));
8288d7f2e76SPhilippe Mathieu-Daudé QTAILQ_FOREACH(kid, &bus->children, sibling) {
82946e23b2eSBALATON Zoltan BusState *child_bus;
8308d7f2e76SPhilippe Mathieu-Daudé DeviceState *dev = kid->child;
83146e23b2eSBALATON Zoltan qdev_printf("dev: %s, id \"%s\"\n", object_get_typename(OBJECT(dev)),
83246e23b2eSBALATON Zoltan dev->id ? dev->id : "");
83346e23b2eSBALATON Zoltan if (details) {
83446e23b2eSBALATON Zoltan qdev_print(mon, dev, indent + 2);
83546e23b2eSBALATON Zoltan }
83646e23b2eSBALATON Zoltan QLIST_FOREACH(child_bus, &dev->child_bus, sibling) {
83746e23b2eSBALATON Zoltan qbus_print(mon, child_bus, indent + 2, details);
83846e23b2eSBALATON Zoltan }
8398d7f2e76SPhilippe Mathieu-Daudé }
8408d7f2e76SPhilippe Mathieu-Daudé }
8418d7f2e76SPhilippe Mathieu-Daudé #undef qdev_printf
8428d7f2e76SPhilippe Mathieu-Daudé
hmp_info_qtree(Monitor * mon,const QDict * qdict)8438d7f2e76SPhilippe Mathieu-Daudé void hmp_info_qtree(Monitor *mon, const QDict *qdict)
8448d7f2e76SPhilippe Mathieu-Daudé {
84546e23b2eSBALATON Zoltan bool details = !qdict_get_try_bool(qdict, "brief", false);
84646e23b2eSBALATON Zoltan
84746e23b2eSBALATON Zoltan if (sysbus_get_default()) {
84846e23b2eSBALATON Zoltan qbus_print(mon, sysbus_get_default(), 0, details);
84946e23b2eSBALATON Zoltan }
8508d7f2e76SPhilippe Mathieu-Daudé }
8518d7f2e76SPhilippe Mathieu-Daudé
hmp_info_qdm(Monitor * mon,const QDict * qdict)8528d7f2e76SPhilippe Mathieu-Daudé void hmp_info_qdm(Monitor *mon, const QDict *qdict)
8538d7f2e76SPhilippe Mathieu-Daudé {
8548d7f2e76SPhilippe Mathieu-Daudé qdev_print_devinfos(true);
8558d7f2e76SPhilippe Mathieu-Daudé }
8568d7f2e76SPhilippe Mathieu-Daudé
qmp_device_add(QDict * qdict,QObject ** ret_data,Error ** errp)8578d7f2e76SPhilippe Mathieu-Daudé void qmp_device_add(QDict *qdict, QObject **ret_data, Error **errp)
8588d7f2e76SPhilippe Mathieu-Daudé {
8598d7f2e76SPhilippe Mathieu-Daudé DeviceState *dev;
8608d7f2e76SPhilippe Mathieu-Daudé
861*be93fd53SStefan Hajnoczi dev = qdev_device_add_from_qdict(qdict, true, errp);
862012b1701SDmitrii Gavrilov if (!dev) {
8638d7f2e76SPhilippe Mathieu-Daudé /*
8648d7f2e76SPhilippe Mathieu-Daudé * Drain all pending RCU callbacks. This is done because
8658d7f2e76SPhilippe Mathieu-Daudé * some bus related operations can delay a device removal
8668d7f2e76SPhilippe Mathieu-Daudé * (in this case this can happen if device is added and then
8678d7f2e76SPhilippe Mathieu-Daudé * removed due to a configuration error)
8688d7f2e76SPhilippe Mathieu-Daudé * to a RCU callback, but user might expect that this interface
8698d7f2e76SPhilippe Mathieu-Daudé * will finish its job completely once qmp command returns result
8708d7f2e76SPhilippe Mathieu-Daudé * to the user
8718d7f2e76SPhilippe Mathieu-Daudé */
8728d7f2e76SPhilippe Mathieu-Daudé drain_call_rcu();
8738d7f2e76SPhilippe Mathieu-Daudé }
8748d7f2e76SPhilippe Mathieu-Daudé object_unref(OBJECT(dev));
8758d7f2e76SPhilippe Mathieu-Daudé }
8768d7f2e76SPhilippe Mathieu-Daudé
8779e4cc917SVladimir Sementsov-Ogievskiy /*
8789e4cc917SVladimir Sementsov-Ogievskiy * Note that creating new APIs using error classes other than GenericError is
8799e4cc917SVladimir Sementsov-Ogievskiy * not recommended. Set use_generic_error=true for new interfaces.
8809e4cc917SVladimir Sementsov-Ogievskiy */
find_device_state(const char * id,bool use_generic_error,Error ** errp)8819e4cc917SVladimir Sementsov-Ogievskiy static DeviceState *find_device_state(const char *id, bool use_generic_error,
8829e4cc917SVladimir Sementsov-Ogievskiy Error **errp)
8838d7f2e76SPhilippe Mathieu-Daudé {
8848d7f2e76SPhilippe Mathieu-Daudé Object *obj = object_resolve_path_at(qdev_get_peripheral(), id);
8858d7f2e76SPhilippe Mathieu-Daudé DeviceState *dev;
8868d7f2e76SPhilippe Mathieu-Daudé
8878d7f2e76SPhilippe Mathieu-Daudé if (!obj) {
8889e4cc917SVladimir Sementsov-Ogievskiy error_set(errp,
8899e4cc917SVladimir Sementsov-Ogievskiy (use_generic_error ?
8909e4cc917SVladimir Sementsov-Ogievskiy ERROR_CLASS_GENERIC_ERROR : ERROR_CLASS_DEVICE_NOT_FOUND),
8918d7f2e76SPhilippe Mathieu-Daudé "Device '%s' not found", id);
8928d7f2e76SPhilippe Mathieu-Daudé return NULL;
8938d7f2e76SPhilippe Mathieu-Daudé }
8948d7f2e76SPhilippe Mathieu-Daudé
8958d7f2e76SPhilippe Mathieu-Daudé dev = (DeviceState *)object_dynamic_cast(obj, TYPE_DEVICE);
8968d7f2e76SPhilippe Mathieu-Daudé if (!dev) {
897e1999904SVladimir Sementsov-Ogievskiy error_setg(errp, "%s is not a device", id);
8988d7f2e76SPhilippe Mathieu-Daudé return NULL;
8998d7f2e76SPhilippe Mathieu-Daudé }
9008d7f2e76SPhilippe Mathieu-Daudé
9018d7f2e76SPhilippe Mathieu-Daudé return dev;
9028d7f2e76SPhilippe Mathieu-Daudé }
9038d7f2e76SPhilippe Mathieu-Daudé
qdev_unplug(DeviceState * dev,Error ** errp)9048d7f2e76SPhilippe Mathieu-Daudé void qdev_unplug(DeviceState *dev, Error **errp)
9058d7f2e76SPhilippe Mathieu-Daudé {
9068d7f2e76SPhilippe Mathieu-Daudé DeviceClass *dc = DEVICE_GET_CLASS(dev);
9078d7f2e76SPhilippe Mathieu-Daudé HotplugHandler *hotplug_ctrl;
9088d7f2e76SPhilippe Mathieu-Daudé HotplugHandlerClass *hdc;
9098d7f2e76SPhilippe Mathieu-Daudé Error *local_err = NULL;
9108d7f2e76SPhilippe Mathieu-Daudé
9118d7f2e76SPhilippe Mathieu-Daudé if (qdev_unplug_blocked(dev, errp)) {
9128d7f2e76SPhilippe Mathieu-Daudé return;
9138d7f2e76SPhilippe Mathieu-Daudé }
9148d7f2e76SPhilippe Mathieu-Daudé
9158d7f2e76SPhilippe Mathieu-Daudé if (dev->parent_bus && !qbus_is_hotpluggable(dev->parent_bus)) {
9167f65e789SPhilippe Mathieu-Daudé error_setg(errp, "Bus '%s' does not support hotplugging",
9177f65e789SPhilippe Mathieu-Daudé dev->parent_bus->name);
9188d7f2e76SPhilippe Mathieu-Daudé return;
9198d7f2e76SPhilippe Mathieu-Daudé }
9208d7f2e76SPhilippe Mathieu-Daudé
9218d7f2e76SPhilippe Mathieu-Daudé if (!dc->hotpluggable) {
922f95b25c3SPhilippe Mathieu-Daudé error_setg(errp, "Device '%s' does not support hotplugging",
9238d7f2e76SPhilippe Mathieu-Daudé object_get_typename(OBJECT(dev)));
9248d7f2e76SPhilippe Mathieu-Daudé return;
9258d7f2e76SPhilippe Mathieu-Daudé }
9268d7f2e76SPhilippe Mathieu-Daudé
92734a8892dSPeter Xu if (migration_is_running() && !dev->allow_unplug_during_migration) {
9288d7f2e76SPhilippe Mathieu-Daudé error_setg(errp, "device_del not allowed while migrating");
9298d7f2e76SPhilippe Mathieu-Daudé return;
9308d7f2e76SPhilippe Mathieu-Daudé }
9318d7f2e76SPhilippe Mathieu-Daudé
9328d7f2e76SPhilippe Mathieu-Daudé qdev_hot_removed = true;
9338d7f2e76SPhilippe Mathieu-Daudé
9348d7f2e76SPhilippe Mathieu-Daudé hotplug_ctrl = qdev_get_hotplug_handler(dev);
9358d7f2e76SPhilippe Mathieu-Daudé /* hotpluggable device MUST have HotplugHandler, if it doesn't
9368d7f2e76SPhilippe Mathieu-Daudé * then something is very wrong with it */
9378d7f2e76SPhilippe Mathieu-Daudé g_assert(hotplug_ctrl);
9388d7f2e76SPhilippe Mathieu-Daudé
9398d7f2e76SPhilippe Mathieu-Daudé /* If device supports async unplug just request it to be done,
9408d7f2e76SPhilippe Mathieu-Daudé * otherwise just remove it synchronously */
9418d7f2e76SPhilippe Mathieu-Daudé hdc = HOTPLUG_HANDLER_GET_CLASS(hotplug_ctrl);
9428d7f2e76SPhilippe Mathieu-Daudé if (hdc->unplug_request) {
9438d7f2e76SPhilippe Mathieu-Daudé hotplug_handler_unplug_request(hotplug_ctrl, dev, &local_err);
9448d7f2e76SPhilippe Mathieu-Daudé } else {
9458d7f2e76SPhilippe Mathieu-Daudé hotplug_handler_unplug(hotplug_ctrl, dev, &local_err);
9468d7f2e76SPhilippe Mathieu-Daudé if (!local_err) {
9478d7f2e76SPhilippe Mathieu-Daudé object_unparent(OBJECT(dev));
9488d7f2e76SPhilippe Mathieu-Daudé }
9498d7f2e76SPhilippe Mathieu-Daudé }
9508d7f2e76SPhilippe Mathieu-Daudé error_propagate(errp, local_err);
9518d7f2e76SPhilippe Mathieu-Daudé }
9528d7f2e76SPhilippe Mathieu-Daudé
qmp_device_del(const char * id,Error ** errp)9538d7f2e76SPhilippe Mathieu-Daudé void qmp_device_del(const char *id, Error **errp)
9548d7f2e76SPhilippe Mathieu-Daudé {
9559e4cc917SVladimir Sementsov-Ogievskiy DeviceState *dev = find_device_state(id, false, errp);
9568d7f2e76SPhilippe Mathieu-Daudé if (dev != NULL) {
9578d7f2e76SPhilippe Mathieu-Daudé if (dev->pending_deleted_event &&
9588d7f2e76SPhilippe Mathieu-Daudé (dev->pending_deleted_expires_ms == 0 ||
9598d7f2e76SPhilippe Mathieu-Daudé dev->pending_deleted_expires_ms > qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL))) {
9608d7f2e76SPhilippe Mathieu-Daudé error_setg(errp, "Device %s is already in the "
9618d7f2e76SPhilippe Mathieu-Daudé "process of unplug", id);
9628d7f2e76SPhilippe Mathieu-Daudé return;
9638d7f2e76SPhilippe Mathieu-Daudé }
9648d7f2e76SPhilippe Mathieu-Daudé
9658d7f2e76SPhilippe Mathieu-Daudé qdev_unplug(dev, errp);
9668d7f2e76SPhilippe Mathieu-Daudé }
9678d7f2e76SPhilippe Mathieu-Daudé }
9688d7f2e76SPhilippe Mathieu-Daudé
qdev_sync_config(DeviceState * dev,Error ** errp)9693f98408eSVladimir Sementsov-Ogievskiy int qdev_sync_config(DeviceState *dev, Error **errp)
9703f98408eSVladimir Sementsov-Ogievskiy {
9713f98408eSVladimir Sementsov-Ogievskiy DeviceClass *dc = DEVICE_GET_CLASS(dev);
9723f98408eSVladimir Sementsov-Ogievskiy
9733f98408eSVladimir Sementsov-Ogievskiy if (!dc->sync_config) {
9743f98408eSVladimir Sementsov-Ogievskiy error_setg(errp, "device-sync-config is not supported for '%s'",
9753f98408eSVladimir Sementsov-Ogievskiy object_get_typename(OBJECT(dev)));
9763f98408eSVladimir Sementsov-Ogievskiy return -ENOTSUP;
9773f98408eSVladimir Sementsov-Ogievskiy }
9783f98408eSVladimir Sementsov-Ogievskiy
9793f98408eSVladimir Sementsov-Ogievskiy return dc->sync_config(dev, errp);
9803f98408eSVladimir Sementsov-Ogievskiy }
9813f98408eSVladimir Sementsov-Ogievskiy
qmp_device_sync_config(const char * id,Error ** errp)9823f98408eSVladimir Sementsov-Ogievskiy void qmp_device_sync_config(const char *id, Error **errp)
9833f98408eSVladimir Sementsov-Ogievskiy {
9843f98408eSVladimir Sementsov-Ogievskiy DeviceState *dev;
9853f98408eSVladimir Sementsov-Ogievskiy
9863f98408eSVladimir Sementsov-Ogievskiy /*
9873f98408eSVladimir Sementsov-Ogievskiy * During migration there is a race between syncing`configuration
9883f98408eSVladimir Sementsov-Ogievskiy * and migrating it (if migrate first, that target would get
9893f98408eSVladimir Sementsov-Ogievskiy * outdated version), so let's just not allow it.
9903f98408eSVladimir Sementsov-Ogievskiy */
9913f98408eSVladimir Sementsov-Ogievskiy
9923f98408eSVladimir Sementsov-Ogievskiy if (migration_is_running()) {
9933f98408eSVladimir Sementsov-Ogievskiy error_setg(errp, "Config synchronization is not allowed "
9943f98408eSVladimir Sementsov-Ogievskiy "during migration");
9953f98408eSVladimir Sementsov-Ogievskiy return;
9963f98408eSVladimir Sementsov-Ogievskiy }
9973f98408eSVladimir Sementsov-Ogievskiy
9983f98408eSVladimir Sementsov-Ogievskiy dev = find_device_state(id, true, errp);
9993f98408eSVladimir Sementsov-Ogievskiy if (!dev) {
10003f98408eSVladimir Sementsov-Ogievskiy return;
10013f98408eSVladimir Sementsov-Ogievskiy }
10023f98408eSVladimir Sementsov-Ogievskiy
10033f98408eSVladimir Sementsov-Ogievskiy qdev_sync_config(dev, errp);
10043f98408eSVladimir Sementsov-Ogievskiy }
10053f98408eSVladimir Sementsov-Ogievskiy
hmp_device_add(Monitor * mon,const QDict * qdict)10068d7f2e76SPhilippe Mathieu-Daudé void hmp_device_add(Monitor *mon, const QDict *qdict)
10078d7f2e76SPhilippe Mathieu-Daudé {
10088d7f2e76SPhilippe Mathieu-Daudé Error *err = NULL;
1009*be93fd53SStefan Hajnoczi QemuOpts *opts;
1010*be93fd53SStefan Hajnoczi DeviceState *dev;
10118d7f2e76SPhilippe Mathieu-Daudé
1012*be93fd53SStefan Hajnoczi opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict, &err);
1013*be93fd53SStefan Hajnoczi if (!opts) {
1014*be93fd53SStefan Hajnoczi goto out;
1015*be93fd53SStefan Hajnoczi }
1016*be93fd53SStefan Hajnoczi if (qdev_device_help(opts)) {
1017*be93fd53SStefan Hajnoczi qemu_opts_del(opts);
1018*be93fd53SStefan Hajnoczi return;
1019*be93fd53SStefan Hajnoczi }
1020*be93fd53SStefan Hajnoczi dev = qdev_device_add(opts, &err);
1021*be93fd53SStefan Hajnoczi if (!dev) {
1022*be93fd53SStefan Hajnoczi /*
1023*be93fd53SStefan Hajnoczi * Drain all pending RCU callbacks. This is done because
1024*be93fd53SStefan Hajnoczi * some bus related operations can delay a device removal
1025*be93fd53SStefan Hajnoczi * (in this case this can happen if device is added and then
1026*be93fd53SStefan Hajnoczi * removed due to a configuration error)
1027*be93fd53SStefan Hajnoczi * to a RCU callback, but user might expect that this interface
1028*be93fd53SStefan Hajnoczi * will finish its job completely once qmp command returns result
1029*be93fd53SStefan Hajnoczi * to the user
1030*be93fd53SStefan Hajnoczi */
1031*be93fd53SStefan Hajnoczi drain_call_rcu();
1032*be93fd53SStefan Hajnoczi
1033*be93fd53SStefan Hajnoczi qemu_opts_del(opts);
1034*be93fd53SStefan Hajnoczi }
1035*be93fd53SStefan Hajnoczi object_unref(dev);
1036*be93fd53SStefan Hajnoczi out:
10378d7f2e76SPhilippe Mathieu-Daudé hmp_handle_error(mon, err);
10388d7f2e76SPhilippe Mathieu-Daudé }
10398d7f2e76SPhilippe Mathieu-Daudé
hmp_device_del(Monitor * mon,const QDict * qdict)10408d7f2e76SPhilippe Mathieu-Daudé void hmp_device_del(Monitor *mon, const QDict *qdict)
10418d7f2e76SPhilippe Mathieu-Daudé {
10428d7f2e76SPhilippe Mathieu-Daudé const char *id = qdict_get_str(qdict, "id");
10438d7f2e76SPhilippe Mathieu-Daudé Error *err = NULL;
10448d7f2e76SPhilippe Mathieu-Daudé
10458d7f2e76SPhilippe Mathieu-Daudé qmp_device_del(id, &err);
10468d7f2e76SPhilippe Mathieu-Daudé hmp_handle_error(mon, err);
10478d7f2e76SPhilippe Mathieu-Daudé }
10488d7f2e76SPhilippe Mathieu-Daudé
device_add_completion(ReadLineState * rs,int nb_args,const char * str)10498d7f2e76SPhilippe Mathieu-Daudé void device_add_completion(ReadLineState *rs, int nb_args, const char *str)
10508d7f2e76SPhilippe Mathieu-Daudé {
10518d7f2e76SPhilippe Mathieu-Daudé GSList *list, *elt;
10528d7f2e76SPhilippe Mathieu-Daudé size_t len;
10538d7f2e76SPhilippe Mathieu-Daudé
10548d7f2e76SPhilippe Mathieu-Daudé if (nb_args != 2) {
10558d7f2e76SPhilippe Mathieu-Daudé return;
10568d7f2e76SPhilippe Mathieu-Daudé }
10578d7f2e76SPhilippe Mathieu-Daudé
10588d7f2e76SPhilippe Mathieu-Daudé len = strlen(str);
10598d7f2e76SPhilippe Mathieu-Daudé readline_set_completion_index(rs, len);
10608d7f2e76SPhilippe Mathieu-Daudé list = elt = object_class_get_list(TYPE_DEVICE, false);
10618d7f2e76SPhilippe Mathieu-Daudé while (elt) {
10628d7f2e76SPhilippe Mathieu-Daudé DeviceClass *dc = OBJECT_CLASS_CHECK(DeviceClass, elt->data,
10638d7f2e76SPhilippe Mathieu-Daudé TYPE_DEVICE);
10648d7f2e76SPhilippe Mathieu-Daudé
10658d7f2e76SPhilippe Mathieu-Daudé if (dc->user_creatable) {
10668d7f2e76SPhilippe Mathieu-Daudé readline_add_completion_of(rs, str,
10678d7f2e76SPhilippe Mathieu-Daudé object_class_get_name(OBJECT_CLASS(dc)));
10688d7f2e76SPhilippe Mathieu-Daudé }
10698d7f2e76SPhilippe Mathieu-Daudé elt = elt->next;
10708d7f2e76SPhilippe Mathieu-Daudé }
10718d7f2e76SPhilippe Mathieu-Daudé g_slist_free(list);
10728d7f2e76SPhilippe Mathieu-Daudé }
10738d7f2e76SPhilippe Mathieu-Daudé
qdev_add_hotpluggable_device(Object * obj,void * opaque)10748d7f2e76SPhilippe Mathieu-Daudé static int qdev_add_hotpluggable_device(Object *obj, void *opaque)
10758d7f2e76SPhilippe Mathieu-Daudé {
10768d7f2e76SPhilippe Mathieu-Daudé GSList **list = opaque;
10778d7f2e76SPhilippe Mathieu-Daudé DeviceState *dev = (DeviceState *)object_dynamic_cast(obj, TYPE_DEVICE);
10788d7f2e76SPhilippe Mathieu-Daudé
10798d7f2e76SPhilippe Mathieu-Daudé if (dev == NULL) {
10808d7f2e76SPhilippe Mathieu-Daudé return 0;
10818d7f2e76SPhilippe Mathieu-Daudé }
10828d7f2e76SPhilippe Mathieu-Daudé
10838d7f2e76SPhilippe Mathieu-Daudé if (dev->realized && object_property_get_bool(obj, "hotpluggable", NULL)) {
10848d7f2e76SPhilippe Mathieu-Daudé *list = g_slist_append(*list, dev);
10858d7f2e76SPhilippe Mathieu-Daudé }
10868d7f2e76SPhilippe Mathieu-Daudé
10878d7f2e76SPhilippe Mathieu-Daudé return 0;
10888d7f2e76SPhilippe Mathieu-Daudé }
10898d7f2e76SPhilippe Mathieu-Daudé
qdev_build_hotpluggable_device_list(Object * peripheral)10908d7f2e76SPhilippe Mathieu-Daudé static GSList *qdev_build_hotpluggable_device_list(Object *peripheral)
10918d7f2e76SPhilippe Mathieu-Daudé {
10928d7f2e76SPhilippe Mathieu-Daudé GSList *list = NULL;
10938d7f2e76SPhilippe Mathieu-Daudé
10948d7f2e76SPhilippe Mathieu-Daudé object_child_foreach(peripheral, qdev_add_hotpluggable_device, &list);
10958d7f2e76SPhilippe Mathieu-Daudé
10968d7f2e76SPhilippe Mathieu-Daudé return list;
10978d7f2e76SPhilippe Mathieu-Daudé }
10988d7f2e76SPhilippe Mathieu-Daudé
peripheral_device_del_completion(ReadLineState * rs,const char * str)10998d7f2e76SPhilippe Mathieu-Daudé static void peripheral_device_del_completion(ReadLineState *rs,
11008d7f2e76SPhilippe Mathieu-Daudé const char *str)
11018d7f2e76SPhilippe Mathieu-Daudé {
11028d7f2e76SPhilippe Mathieu-Daudé Object *peripheral = container_get(qdev_get_machine(), "/peripheral");
11038d7f2e76SPhilippe Mathieu-Daudé GSList *list, *item;
11048d7f2e76SPhilippe Mathieu-Daudé
11058d7f2e76SPhilippe Mathieu-Daudé list = qdev_build_hotpluggable_device_list(peripheral);
11068d7f2e76SPhilippe Mathieu-Daudé if (!list) {
11078d7f2e76SPhilippe Mathieu-Daudé return;
11088d7f2e76SPhilippe Mathieu-Daudé }
11098d7f2e76SPhilippe Mathieu-Daudé
11108d7f2e76SPhilippe Mathieu-Daudé for (item = list; item; item = g_slist_next(item)) {
11118d7f2e76SPhilippe Mathieu-Daudé DeviceState *dev = item->data;
11128d7f2e76SPhilippe Mathieu-Daudé
11138d7f2e76SPhilippe Mathieu-Daudé if (dev->id) {
11148d7f2e76SPhilippe Mathieu-Daudé readline_add_completion_of(rs, str, dev->id);
11158d7f2e76SPhilippe Mathieu-Daudé }
11168d7f2e76SPhilippe Mathieu-Daudé }
11178d7f2e76SPhilippe Mathieu-Daudé
11188d7f2e76SPhilippe Mathieu-Daudé g_slist_free(list);
11198d7f2e76SPhilippe Mathieu-Daudé }
11208d7f2e76SPhilippe Mathieu-Daudé
device_del_completion(ReadLineState * rs,int nb_args,const char * str)11218d7f2e76SPhilippe Mathieu-Daudé void device_del_completion(ReadLineState *rs, int nb_args, const char *str)
11228d7f2e76SPhilippe Mathieu-Daudé {
11238d7f2e76SPhilippe Mathieu-Daudé if (nb_args != 2) {
11248d7f2e76SPhilippe Mathieu-Daudé return;
11258d7f2e76SPhilippe Mathieu-Daudé }
11268d7f2e76SPhilippe Mathieu-Daudé
11278d7f2e76SPhilippe Mathieu-Daudé readline_set_completion_index(rs, strlen(str));
11288d7f2e76SPhilippe Mathieu-Daudé peripheral_device_del_completion(rs, str);
11298d7f2e76SPhilippe Mathieu-Daudé }
11308d7f2e76SPhilippe Mathieu-Daudé
blk_by_qdev_id(const char * id,Error ** errp)11318d7f2e76SPhilippe Mathieu-Daudé BlockBackend *blk_by_qdev_id(const char *id, Error **errp)
11328d7f2e76SPhilippe Mathieu-Daudé {
11338d7f2e76SPhilippe Mathieu-Daudé DeviceState *dev;
11348d7f2e76SPhilippe Mathieu-Daudé BlockBackend *blk;
11358d7f2e76SPhilippe Mathieu-Daudé
11368d7f2e76SPhilippe Mathieu-Daudé GLOBAL_STATE_CODE();
11378d7f2e76SPhilippe Mathieu-Daudé
11389e4cc917SVladimir Sementsov-Ogievskiy dev = find_device_state(id, false, errp);
11398d7f2e76SPhilippe Mathieu-Daudé if (dev == NULL) {
11408d7f2e76SPhilippe Mathieu-Daudé return NULL;
11418d7f2e76SPhilippe Mathieu-Daudé }
11428d7f2e76SPhilippe Mathieu-Daudé
11438d7f2e76SPhilippe Mathieu-Daudé blk = blk_by_dev(dev);
11448d7f2e76SPhilippe Mathieu-Daudé if (!blk) {
11458d7f2e76SPhilippe Mathieu-Daudé error_setg(errp, "Device does not have a block device backend");
11468d7f2e76SPhilippe Mathieu-Daudé }
11478d7f2e76SPhilippe Mathieu-Daudé return blk;
11488d7f2e76SPhilippe Mathieu-Daudé }
11498d7f2e76SPhilippe Mathieu-Daudé
11508d7f2e76SPhilippe Mathieu-Daudé QemuOptsList qemu_device_opts = {
11518d7f2e76SPhilippe Mathieu-Daudé .name = "device",
11528d7f2e76SPhilippe Mathieu-Daudé .implied_opt_name = "driver",
11538d7f2e76SPhilippe Mathieu-Daudé .head = QTAILQ_HEAD_INITIALIZER(qemu_device_opts.head),
11548d7f2e76SPhilippe Mathieu-Daudé .desc = {
11558d7f2e76SPhilippe Mathieu-Daudé /*
11568d7f2e76SPhilippe Mathieu-Daudé * no elements => accept any
11578d7f2e76SPhilippe Mathieu-Daudé * sanity checking will happen later
11588d7f2e76SPhilippe Mathieu-Daudé * when setting device properties
11598d7f2e76SPhilippe Mathieu-Daudé */
11608d7f2e76SPhilippe Mathieu-Daudé { /* end of list */ }
11618d7f2e76SPhilippe Mathieu-Daudé },
11628d7f2e76SPhilippe Mathieu-Daudé };
11638d7f2e76SPhilippe Mathieu-Daudé
11648d7f2e76SPhilippe Mathieu-Daudé QemuOptsList qemu_global_opts = {
11658d7f2e76SPhilippe Mathieu-Daudé .name = "global",
11668d7f2e76SPhilippe Mathieu-Daudé .head = QTAILQ_HEAD_INITIALIZER(qemu_global_opts.head),
11678d7f2e76SPhilippe Mathieu-Daudé .desc = {
11688d7f2e76SPhilippe Mathieu-Daudé {
11698d7f2e76SPhilippe Mathieu-Daudé .name = "driver",
11708d7f2e76SPhilippe Mathieu-Daudé .type = QEMU_OPT_STRING,
11718d7f2e76SPhilippe Mathieu-Daudé },{
11728d7f2e76SPhilippe Mathieu-Daudé .name = "property",
11738d7f2e76SPhilippe Mathieu-Daudé .type = QEMU_OPT_STRING,
11748d7f2e76SPhilippe Mathieu-Daudé },{
11758d7f2e76SPhilippe Mathieu-Daudé .name = "value",
11768d7f2e76SPhilippe Mathieu-Daudé .type = QEMU_OPT_STRING,
11778d7f2e76SPhilippe Mathieu-Daudé },
11788d7f2e76SPhilippe Mathieu-Daudé { /* end of list */ }
11798d7f2e76SPhilippe Mathieu-Daudé },
11808d7f2e76SPhilippe Mathieu-Daudé };
11818d7f2e76SPhilippe Mathieu-Daudé
qemu_global_option(const char * str)11828d7f2e76SPhilippe Mathieu-Daudé int qemu_global_option(const char *str)
11838d7f2e76SPhilippe Mathieu-Daudé {
11848d7f2e76SPhilippe Mathieu-Daudé char driver[64], property[64];
11858d7f2e76SPhilippe Mathieu-Daudé QemuOpts *opts;
11868d7f2e76SPhilippe Mathieu-Daudé int rc, offset;
11878d7f2e76SPhilippe Mathieu-Daudé
11888d7f2e76SPhilippe Mathieu-Daudé rc = sscanf(str, "%63[^.=].%63[^=]%n", driver, property, &offset);
11898d7f2e76SPhilippe Mathieu-Daudé if (rc == 2 && str[offset] == '=') {
11908d7f2e76SPhilippe Mathieu-Daudé opts = qemu_opts_create(&qemu_global_opts, NULL, 0, &error_abort);
11918d7f2e76SPhilippe Mathieu-Daudé qemu_opt_set(opts, "driver", driver, &error_abort);
11928d7f2e76SPhilippe Mathieu-Daudé qemu_opt_set(opts, "property", property, &error_abort);
11938d7f2e76SPhilippe Mathieu-Daudé qemu_opt_set(opts, "value", str + offset + 1, &error_abort);
11948d7f2e76SPhilippe Mathieu-Daudé return 0;
11958d7f2e76SPhilippe Mathieu-Daudé }
11968d7f2e76SPhilippe Mathieu-Daudé
11978d7f2e76SPhilippe Mathieu-Daudé opts = qemu_opts_parse_noisily(&qemu_global_opts, str, false);
11988d7f2e76SPhilippe Mathieu-Daudé if (!opts) {
11998d7f2e76SPhilippe Mathieu-Daudé return -1;
12008d7f2e76SPhilippe Mathieu-Daudé }
12018d7f2e76SPhilippe Mathieu-Daudé if (!qemu_opt_get(opts, "driver")
12028d7f2e76SPhilippe Mathieu-Daudé || !qemu_opt_get(opts, "property")
12038d7f2e76SPhilippe Mathieu-Daudé || !qemu_opt_get(opts, "value")) {
12048d7f2e76SPhilippe Mathieu-Daudé error_report("options 'driver', 'property', and 'value'"
12058d7f2e76SPhilippe Mathieu-Daudé " are required");
12068d7f2e76SPhilippe Mathieu-Daudé return -1;
12078d7f2e76SPhilippe Mathieu-Daudé }
12088d7f2e76SPhilippe Mathieu-Daudé
12098d7f2e76SPhilippe Mathieu-Daudé return 0;
12108d7f2e76SPhilippe Mathieu-Daudé }
12118d7f2e76SPhilippe Mathieu-Daudé
qmp_command_available(const QmpCommand * cmd,Error ** errp)12128d7f2e76SPhilippe Mathieu-Daudé bool qmp_command_available(const QmpCommand *cmd, Error **errp)
12138d7f2e76SPhilippe Mathieu-Daudé {
12148d7f2e76SPhilippe Mathieu-Daudé if (!phase_check(PHASE_MACHINE_READY) &&
12158d7f2e76SPhilippe Mathieu-Daudé !(cmd->options & QCO_ALLOW_PRECONFIG)) {
12168d7f2e76SPhilippe Mathieu-Daudé error_setg(errp, "The command '%s' is permitted only after machine initialization has completed",
12178d7f2e76SPhilippe Mathieu-Daudé cmd->name);
12188d7f2e76SPhilippe Mathieu-Daudé return false;
12198d7f2e76SPhilippe Mathieu-Daudé }
12208d7f2e76SPhilippe Mathieu-Daudé return true;
12218d7f2e76SPhilippe Mathieu-Daudé }
1222