diff options
74 files changed, 840 insertions, 447 deletions
diff --git a/.travis.yml b/.travis.yml index 638fba4799..6c1038a0f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,13 +51,6 @@ addons: - sparse - uuid-dev - gcovr - homebrew: - packages: - - ccache - - glib - - pixman - - gnu-sed - update: true # The channel name "irc.oftc.net#qemu" is encrypted against qemu/qemu @@ -89,12 +82,12 @@ git: before_script: - - if [ "$TRAVIS_OS_NAME" == "osx" ] ; then export PATH="/usr/local/opt/ccache/libexec:$PATH" ; fi - if command -v ccache ; then ccache --zero-stats ; fi - mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR} - ${SRC_DIR}/configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; } script: - - make -j3 && travis_retry ${TEST_CMD} + - BUILD_RC=0 && make -j3 || BUILD_RC=$? + - if [ "$BUILD_RC" -eq 0 ] ; then travis_retry ${TEST_CMD} ; else $(exit $BUILD_RC); fi after_script: - if command -v ccache ; then ccache --show-stats ; fi @@ -239,6 +232,21 @@ matrix: os: osx osx_image: xcode10.3 compiler: clang + addons: + homebrew: + packages: + - ccache + - glib + - pixman + - gnu-sed + - python + update: true + before_script: + - brew link --overwrite python + - export PATH="/usr/local/opt/ccache/libexec:$PATH" + - if command -v ccache ; then ccache --zero-stats ; fi + - mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR} + - ${SRC_DIR}/configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; } # Python builds @@ -262,8 +270,8 @@ matrix: - env: - CONFIG="--python=/usr/bin/python3 --target-list=x86_64-softmmu,mips-softmmu,mips64el-softmmu,aarch64-softmmu,arm-softmmu,s390x-softmmu,alpha-softmmu,ppc-softmmu,ppc64-softmmu,m68k-softmmu,sparc-softmmu" - TEST_CMD="make check-acceptance" - after_failure: - - cat tests/results/latest/job.log + after_script: + - python3 -c 'import json; r = json.load(open("tests/results/latest/results.json")); [print(t["logfile"]) for t in r["tests"] if t["status"] not in ("PASS", "SKIP")]' | xargs cat addons: apt: packages: diff --git a/chardev/char.c b/chardev/char.c index 7b6b2cb123..e7e7492b0e 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -37,6 +37,7 @@ #include "qemu/help_option.h" #include "qemu/module.h" #include "qemu/option.h" +#include "qemu/id.h" #include "chardev/char-mux.h" @@ -944,10 +945,10 @@ void qemu_chr_set_feature(Chardev *chr, return set_bit(feature, chr->features); } -Chardev *qemu_chardev_new(const char *id, const char *typename, - ChardevBackend *backend, - GMainContext *gcontext, - Error **errp) +static Chardev *chardev_new(const char *id, const char *typename, + ChardevBackend *backend, + GMainContext *gcontext, + Error **errp) { Object *obj; Chardev *chr = NULL; @@ -991,6 +992,21 @@ end: return chr; } +Chardev *qemu_chardev_new(const char *id, const char *typename, + ChardevBackend *backend, + GMainContext *gcontext, + Error **errp) +{ + g_autofree char *genid = NULL; + + if (!id) { + genid = id_generate(ID_CHR); + id = genid; + } + + return chardev_new(id, typename, backend, gcontext, errp); +} + ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend, Error **errp) { @@ -1003,8 +1019,8 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend, return NULL; } - chr = qemu_chardev_new(id, object_class_get_name(OBJECT_CLASS(cc)), - backend, NULL, errp); + chr = chardev_new(id, object_class_get_name(OBJECT_CLASS(cc)), + backend, NULL, errp); if (!chr) { return NULL; } @@ -1061,8 +1077,8 @@ ChardevReturn *qmp_chardev_change(const char *id, ChardevBackend *backend, return NULL; } - chr_new = qemu_chardev_new(NULL, object_class_get_name(OBJECT_CLASS(cc)), - backend, chr->gcontext, errp); + chr_new = chardev_new(NULL, object_class_get_name(OBJECT_CLASS(cc)), + backend, chr->gcontext, errp); if (!chr_new) { return NULL; } diff --git a/configure b/configure index 0ce2c0354a..28ee2a254f 100755 --- a/configure +++ b/configure @@ -3702,6 +3702,9 @@ if $pkg_config --atleast-version=$glib_req_ver gio-2.0; then gio_cflags=$($pkg_config --cflags gio-2.0) gio_libs=$($pkg_config --libs gio-2.0) gdbus_codegen=$($pkg_config --variable=gdbus_codegen gio-2.0) + if [ ! -x "$gdbus_codegen" ]; then + gdbus_codegen= + fi else gio=no fi diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c index 6ce038a453..761cc17ea9 100644 --- a/hw/arm/omap1.c +++ b/hw/arm/omap1.c @@ -3889,7 +3889,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *dram, s->ih[0] = qdev_create(NULL, "omap-intc"); qdev_prop_set_uint32(s->ih[0], "size", 0x100); - qdev_prop_set_ptr(s->ih[0], "clk", omap_findclk(s, "arminth_ck")); + omap_intc_set_iclk(OMAP_INTC(s->ih[0]), omap_findclk(s, "arminth_ck")); qdev_init_nofail(s->ih[0]); busdev = SYS_BUS_DEVICE(s->ih[0]); sysbus_connect_irq(busdev, 0, @@ -3899,7 +3899,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *dram, sysbus_mmio_map(busdev, 0, 0xfffecb00); s->ih[1] = qdev_create(NULL, "omap-intc"); qdev_prop_set_uint32(s->ih[1], "size", 0x800); - qdev_prop_set_ptr(s->ih[1], "clk", omap_findclk(s, "arminth_ck")); + omap_intc_set_iclk(OMAP_INTC(s->ih[1]), omap_findclk(s, "arminth_ck")); qdev_init_nofail(s->ih[1]); busdev = SYS_BUS_DEVICE(s->ih[1]); sysbus_connect_irq(busdev, 0, @@ -4012,7 +4012,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *dram, s->gpio = qdev_create(NULL, "omap-gpio"); qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model); - qdev_prop_set_ptr(s->gpio, "clk", omap_findclk(s, "arm_gpio_ck")); + omap_gpio_set_clk(OMAP1_GPIO(s->gpio), omap_findclk(s, "arm_gpio_ck")); qdev_init_nofail(s->gpio); sysbus_connect_irq(SYS_BUS_DEVICE(s->gpio), 0, qdev_get_gpio_in(s->ih[0], OMAP_INT_GPIO_BANK1)); @@ -4030,7 +4030,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *dram, s->i2c[0] = qdev_create(NULL, "omap_i2c"); qdev_prop_set_uint8(s->i2c[0], "revision", 0x11); - qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "mpuper_ck")); + omap_i2c_set_fclk(OMAP_I2C(s->i2c[0]), omap_findclk(s, "mpuper_ck")); qdev_init_nofail(s->i2c[0]); busdev = SYS_BUS_DEVICE(s->i2c[0]); sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(s->ih[1], OMAP_INT_I2C)); diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c index 457f152bac..e1c11de5ce 100644 --- a/hw/arm/omap2.c +++ b/hw/arm/omap2.c @@ -2308,8 +2308,8 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sdram, /* Actually mapped at any 2K boundary in the ARM11 private-peripheral if */ s->ih[0] = qdev_create(NULL, "omap2-intc"); qdev_prop_set_uint8(s->ih[0], "revision", 0x21); - qdev_prop_set_ptr(s->ih[0], "fclk", omap_findclk(s, "mpu_intc_fclk")); - qdev_prop_set_ptr(s->ih[0], "iclk", omap_findclk(s, "mpu_intc_iclk")); + omap_intc_set_fclk(OMAP_INTC(s->ih[0]), omap_findclk(s, "mpu_intc_fclk")); + omap_intc_set_iclk(OMAP_INTC(s->ih[0]), omap_findclk(s, "mpu_intc_iclk")); qdev_init_nofail(s->ih[0]); busdev = SYS_BUS_DEVICE(s->ih[0]); sysbus_connect_irq(busdev, 0, @@ -2425,8 +2425,8 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sdram, s->i2c[0] = qdev_create(NULL, "omap_i2c"); qdev_prop_set_uint8(s->i2c[0], "revision", 0x34); - qdev_prop_set_ptr(s->i2c[0], "iclk", omap_findclk(s, "i2c1.iclk")); - qdev_prop_set_ptr(s->i2c[0], "fclk", omap_findclk(s, "i2c1.fclk")); + omap_i2c_set_iclk(OMAP_I2C(s->i2c[0]), omap_findclk(s, "i2c1.iclk")); + omap_i2c_set_fclk(OMAP_I2C(s->i2c[0]), omap_findclk(s, "i2c1.fclk")); qdev_init_nofail(s->i2c[0]); busdev = SYS_BUS_DEVICE(s->i2c[0]); sysbus_connect_irq(busdev, 0, @@ -2437,8 +2437,8 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sdram, s->i2c[1] = qdev_create(NULL, "omap_i2c"); qdev_prop_set_uint8(s->i2c[1], "revision", 0x34); - qdev_prop_set_ptr(s->i2c[1], "iclk", omap_findclk(s, "i2c2.iclk")); - qdev_prop_set_ptr(s->i2c[1], "fclk", omap_findclk(s, "i2c2.fclk")); + omap_i2c_set_iclk(OMAP_I2C(s->i2c[1]), omap_findclk(s, "i2c2.iclk")); + omap_i2c_set_fclk(OMAP_I2C(s->i2c[1]), omap_findclk(s, "i2c2.fclk")); qdev_init_nofail(s->i2c[1]); busdev = SYS_BUS_DEVICE(s->i2c[1]); sysbus_connect_irq(busdev, 0, @@ -2449,13 +2449,14 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sdram, s->gpio = qdev_create(NULL, "omap2-gpio"); qdev_prop_set_int32(s->gpio, "mpu_model", s->mpu_model); - qdev_prop_set_ptr(s->gpio, "iclk", omap_findclk(s, "gpio_iclk")); - qdev_prop_set_ptr(s->gpio, "fclk0", omap_findclk(s, "gpio1_dbclk")); - qdev_prop_set_ptr(s->gpio, "fclk1", omap_findclk(s, "gpio2_dbclk")); - qdev_prop_set_ptr(s->gpio, "fclk2", omap_findclk(s, "gpio3_dbclk")); - qdev_prop_set_ptr(s->gpio, "fclk3", omap_findclk(s, "gpio4_dbclk")); + omap2_gpio_set_iclk(OMAP2_GPIO(s->gpio), omap_findclk(s, "gpio_iclk")); + omap2_gpio_set_fclk(OMAP2_GPIO(s->gpio), 0, omap_findclk(s, "gpio1_dbclk")); + omap2_gpio_set_fclk(OMAP2_GPIO(s->gpio), 1, omap_findclk(s, "gpio2_dbclk")); + omap2_gpio_set_fclk(OMAP2_GPIO(s->gpio), 2, omap_findclk(s, "gpio3_dbclk")); + omap2_gpio_set_fclk(OMAP2_GPIO(s->gpio), 3, omap_findclk(s, "gpio4_dbclk")); if (s->mpu_model == omap2430) { - qdev_prop_set_ptr(s->gpio, "fclk4", omap_findclk(s, "gpio5_dbclk")); + omap2_gpio_set_fclk(OMAP2_GPIO(s->gpio), 4, + omap_findclk(s, "gpio5_dbclk")); } qdev_init_nofail(s->gpio); busdev = SYS_BUS_DEVICE(s->gpio); diff --git a/hw/char/omap_uart.c b/hw/char/omap_uart.c index 13e4f43c4c..e8da933378 100644 --- a/hw/char/omap_uart.c +++ b/hw/char/omap_uart.c @@ -27,7 +27,7 @@ struct omap_uart_s { MemoryRegion iomem; hwaddr base; - SerialState *serial; /* TODO */ + SerialMM *serial; /* TODO */ struct omap_target_agent_s *ta; omap_clk fclk; qemu_irq irq; diff --git a/hw/char/serial-isa.c b/hw/char/serial-isa.c index 9e31c51bb6..db8644551e 100644 --- a/hw/char/serial-isa.c +++ b/hw/char/serial-isa.c @@ -73,9 +73,8 @@ static void serial_isa_realizefn(DeviceState *dev, Error **errp) } index++; - s->baudbase = 115200; isa_init_irq(isadev, &s->irq, isa->isairq); - serial_realize_core(s, errp); + object_property_set_bool(OBJECT(s), true, "realized", errp); qdev_set_legacy_instance_id(dev, isa->iobase, 3); memory_region_init_io(&s->io, OBJECT(isa), &serial_io_ops, s, "serial", 8); @@ -111,10 +110,19 @@ static void serial_isa_class_initfn(ObjectClass *klass, void *data) set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } +static void serial_isa_initfn(Object *o) +{ + ISASerialState *self = ISA_SERIAL(o); + + object_initialize_child(o, "serial", &self->state, sizeof(self->state), + TYPE_SERIAL, &error_abort, NULL); +} + static const TypeInfo serial_isa_info = { .name = TYPE_ISA_SERIAL, .parent = TYPE_ISA_DEVICE, .instance_size = sizeof(ISASerialState), + .instance_init = serial_isa_initfn, .class_init = serial_isa_class_initfn, }; diff --git a/hw/char/serial-pci-multi.c b/hw/char/serial-pci-multi.c index 5f13b5663b..e343a1235c 100644 --- a/hw/char/serial-pci-multi.c +++ b/hw/char/serial-pci-multi.c @@ -56,7 +56,7 @@ static void multi_serial_pci_exit(PCIDevice *dev) for (i = 0; i < pci->ports; i++) { s = pci->state + i; - serial_exit_core(s); + object_property_set_bool(OBJECT(s), false, "realized", NULL); memory_region_del_subregion(&pci->iobar, &s->io); g_free(pci->name[i]); } @@ -77,43 +77,43 @@ static void multi_serial_irq_mux(void *opaque, int n, int level) pci_set_irq(&pci->dev, pending); } +static size_t multi_serial_get_port_count(PCIDeviceClass *pc) +{ + switch (pc->device_id) { + case 0x0003: + return 2; + case 0x0004: + return 4; + } + + g_assert_not_reached(); +} + + static void multi_serial_pci_realize(PCIDevice *dev, Error **errp) { PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev); PCIMultiSerialState *pci = DO_UPCAST(PCIMultiSerialState, dev, dev); SerialState *s; Error *err = NULL; - int i, nr_ports = 0; - - switch (pc->device_id) { - case 0x0003: - nr_ports = 2; - break; - case 0x0004: - nr_ports = 4; - break; - } - assert(nr_ports > 0); - assert(nr_ports <= PCI_SERIAL_MAX_PORTS); + size_t i, nports = multi_serial_get_port_count(pc); pci->dev.config[PCI_CLASS_PROG] = pci->prog_if; pci->dev.config[PCI_INTERRUPT_PIN] = 0x01; - memory_region_init(&pci->iobar, OBJECT(pci), "multiserial", 8 * nr_ports); + memory_region_init(&pci->iobar, OBJECT(pci), "multiserial", 8 * nports); pci_register_bar(&pci->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &pci->iobar); - pci->irqs = qemu_allocate_irqs(multi_serial_irq_mux, pci, - nr_ports); + pci->irqs = qemu_allocate_irqs(multi_serial_irq_mux, pci, nports); - for (i = 0; i < nr_ports; i++) { + for (i = 0; i < nports; i++) { s = pci->state + i; - s->baudbase = 115200; - serial_realize_core(s, &err); + object_property_set_bool(OBJECT(s), true, "realized", &err); if (err != NULL) { error_propagate(errp, err); multi_serial_pci_exit(dev); return; } s->irq = pci->irqs[i]; - pci->name[i] = g_strdup_printf("uart #%d", i + 1); + pci->name[i] = g_strdup_printf("uart #%zu", i + 1); memory_region_init_io(&s->io, OBJECT(pci), &serial_io_ops, s, pci->name[i], 8); memory_region_add_subregion(&pci->iobar, 8 * i, &s->io); @@ -180,10 +180,24 @@ static void multi_4x_serial_pci_class_initfn(ObjectClass *klass, void *data) set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } +static void multi_serial_init(Object *o) +{ + PCIDevice *dev = PCI_DEVICE(o); + PCIMultiSerialState *pms = DO_UPCAST(PCIMultiSerialState, dev, dev); + size_t i, nports = multi_serial_get_port_count(PCI_DEVICE_GET_CLASS(dev)); + + for (i = 0; i < nports; i++) { + object_initialize_child(o, "serial[*]", &pms->state[i], + sizeof(pms->state[i]), + TYPE_SERIAL, &error_abort, NULL); + } +} + static const TypeInfo multi_2x_serial_pci_info = { .name = "pci-serial-2x", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCIMultiSerialState), + .instance_init = multi_serial_init, .class_init = multi_2x_serial_pci_class_initfn, .interfaces = (InterfaceInfo[]) { { INTERFACE_CONVENTIONAL_PCI_DEVICE }, @@ -195,6 +209,7 @@ static const TypeInfo multi_4x_serial_pci_info = { .name = "pci-serial-4x", .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCIMultiSerialState), + .instance_init = multi_serial_init, .class_init = multi_4x_serial_pci_class_initfn, .interfaces = (InterfaceInfo[]) { { INTERFACE_CONVENTIONAL_PCI_DEVICE }, diff --git a/hw/char/serial-pci.c b/hw/char/serial-pci.c index cb9b76e22b..b6a73c65a9 100644 --- a/hw/char/serial-pci.c +++ b/hw/char/serial-pci.c @@ -40,6 +40,8 @@ typedef struct PCISerialState { uint8_t prog_if; } PCISerialState; +#define TYPE_PCI_SERIAL "pci-serial" +#define PCI_SERIAL(s) OBJECT_CHECK(PCISerialState, (s), TYPE_PCI_SERIAL) static void serial_pci_realize(PCIDevice *dev, Error **errp) { @@ -47,8 +49,7 @@ static void serial_pci_realize(PCIDevice *dev, Error **errp) SerialState *s = &pci->state; Error *err = NULL; - s->baudbase = 115200; - serial_realize_core(s, &err); + object_property_set_bool(OBJECT(s), true, "realized", &err); if (err != NULL) { error_propagate(errp, err); return; @@ -67,7 +68,7 @@ static void serial_pci_exit(PCIDevice *dev) PCISerialState *pci = DO_UPCAST(PCISerialState, dev, dev); SerialState *s = &pci->state; - serial_exit_core(s); + object_property_set_bool(OBJECT(s), false, "realized", NULL); qemu_free_irq(s->irq); } @@ -103,10 +104,19 @@ static void serial_pci_class_initfn(ObjectClass *klass, void *data) set_bit(DEVICE_CATEGORY_INPUT, dc->categories); } +static void serial_pci_init(Object *o) +{ + PCISerialState *ps = PCI_SERIAL(o); + + object_initialize_child(o, "serial", &ps->state, sizeof(ps->state), + TYPE_SERIAL, &error_abort, NULL); +} + static const TypeInfo serial_pci_info = { - .name = "pci-serial", + .name = TYPE_PCI_SERIAL, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(PCISerialState), + .instance_init = serial_pci_init, .class_init = serial_pci_class_initfn, .interfaces = (InterfaceInfo[]) { { INTERFACE_CONVENTIONAL_PCI_DEVICE }, diff --git a/hw/char/serial.c b/hw/char/serial.c index b4aa250950..6c327183c7 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -34,6 +34,7 @@ #include "sysemu/runstate.h" #include "qemu/error-report.h" #include "trace.h" +#include "hw/qdev-properties.h" //#define DEBUG_SERIAL @@ -933,8 +934,10 @@ static int serial_be_change(void *opaque) return 0; } -void serial_realize_core(SerialState *s, Error **errp) +static void serial_realize(DeviceState *dev, Error **errp) { + SerialState *s = SERIAL(dev); + s->modem_status_poll = timer_new_ns(QEMU_CLOCK_VIRTUAL, (QEMUTimerCB *) serial_update_msl, s); s->fifo_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, (QEMUTimerCB *) fifo_timeout_int, s); @@ -947,8 +950,10 @@ void serial_realize_core(SerialState *s, Error **errp) serial_reset(s); } -void serial_exit_core(SerialState *s) +static void serial_unrealize(DeviceState *dev, Error **errp) { + SerialState *s = SERIAL(dev); + qemu_chr_fe_deinit(&s->chr, false); timer_del(s->modem_status_poll); @@ -980,40 +985,89 @@ const MemoryRegionOps serial_io_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -SerialState *serial_init(int base, qemu_irq irq, int baudbase, - Chardev *chr, MemoryRegion *system_io) +static void serial_io_realize(DeviceState *dev, Error **errp) { - SerialState *s; + SerialIO *sio = SERIAL_IO(dev); + SerialState *s = &sio->serial; + Error *local_err = NULL; + + object_property_set_bool(OBJECT(s), true, "realized", &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + memory_region_init_io(&s->io, NULL, &serial_io_ops, s, "serial", 8); + sysbus_init_mmio(SYS_BUS_DEVICE(sio), &s->io); + sysbus_init_irq(SYS_BUS_DEVICE(sio), &s->irq); +} - s = g_malloc0(sizeof(SerialState)); +static void serial_io_class_init(ObjectClass *klass, void* data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); - s->irq = irq; - s->baudbase = baudbase; - qemu_chr_fe_init(&s->chr, chr, &error_abort); - serial_realize_core(s, &error_fatal); + dc->realize = serial_io_realize; + /* No dc->vmsd: class has no migratable state */ +} - vmstate_register(NULL, base, &vmstate_serial, s); +static void serial_io_instance_init(Object *o) +{ + SerialIO *sio = SERIAL_IO(o); - memory_region_init_io(&s->io, NULL, &serial_io_ops, s, "serial", 8); - memory_region_add_subregion(system_io, base, &s->io); + object_initialize_child(o, "serial", &sio->serial, sizeof(sio->serial), + TYPE_SERIAL, &error_abort, NULL); - return s; + qdev_alias_all_properties(DEVICE(&sio->serial), o); } + +static const TypeInfo serial_io_info = { + .name = TYPE_SERIAL_IO, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(SerialIO), + .instance_init = serial_io_instance_init, + .class_init = serial_io_class_init, +}; + +static Property serial_properties[] = { + DEFINE_PROP_CHR("chardev", SerialState, chr), + DEFINE_PROP_UINT32("baudbase", SerialState, baudbase, 115200), + DEFINE_PROP_END_OF_LIST(), +}; + +static void serial_class_init(ObjectClass *klass, void* data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + /* internal device for serialio/serialmm, not user-creatable */ + dc->user_creatable = false; + dc->realize = serial_realize; + dc->unrealize = serial_unrealize; + dc->vmsd = &vmstate_serial; + dc->props = serial_properties; +} + +static const TypeInfo serial_info = { + .name = TYPE_SERIAL, + .parent = TYPE_DEVICE, + .instance_size = sizeof(SerialState), + .class_init = serial_class_init, +}; + /* Memory mapped interface */ static uint64_t serial_mm_read(void *opaque, hwaddr addr, unsigned size) { - SerialState *s = opaque; - return serial_ioport_read(s, addr >> s->it_shift, 1); + SerialMM *s = SERIAL_MM(opaque); + return serial_ioport_read(&s->serial, addr >> s->regshift, 1); } static void serial_mm_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { - SerialState *s = opaque; + SerialMM *s = SERIAL_MM(opaque); value &= 255; - serial_ioport_write(s, addr >> s->it_shift, value, 1); + serial_ioport_write(&s->serial, addr >> s->regshift, value, 1); } static const MemoryRegionOps serial_mm_ops[3] = { @@ -1040,25 +1094,89 @@ static const MemoryRegionOps serial_mm_ops[3] = { }, }; -SerialState *serial_mm_init(MemoryRegion *address_space, - hwaddr base, int it_shift, - qemu_irq irq, int baudbase, - Chardev *chr, enum device_endian end) +static void serial_mm_realize(DeviceState *dev, Error **errp) { - SerialState *s; + SerialMM *smm = SERIAL_MM(dev); + SerialState *s = &smm->serial; + Error *local_err = NULL; - s = g_malloc0(sizeof(SerialState)); + object_property_set_bool(OBJECT(s), true, "realized", &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + memory_region_init_io(&s->io, NULL, &serial_mm_ops[smm->endianness], smm, + "serial", 8 << smm->regshift); + sysbus_init_mmio(SYS_BUS_DEVICE(smm), &s->io); + sysbus_init_irq(SYS_BUS_DEVICE(smm), &smm->serial.irq); +} + +SerialMM *serial_mm_init(MemoryRegion *address_space, + hwaddr base, int regshift, + qemu_irq irq, int baudbase, + Chardev *chr, enum device_endian end) +{ + SerialMM *smm = SERIAL_MM(qdev_create(NULL, TYPE_SERIAL_MM)); + MemoryRegion *mr; - s->it_shift = it_shift; - s->irq = irq; - s->baudbase = baudbase; - qemu_chr_fe_init(&s->chr, chr, &error_abort); + qdev_prop_set_uint8(DEVICE(smm), "regshift", regshift); + qdev_prop_set_uint32(DEVICE(smm), "baudbase", baudbase); + qdev_prop_set_chr(DEVICE(smm), "chardev", chr); + qdev_set_legacy_instance_id(DEVICE(smm), base, 2); + qdev_prop_set_uint8(DEVICE(smm), "endianness", end); + qdev_init_nofail(DEVICE(smm)); - serial_realize_core(s, &error_fatal); - vmstate_register(NULL, base, &vmstate_serial, s); + sysbus_connect_irq(SYS_BUS_DEVICE(smm), 0, irq); + mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(smm), 0); + memory_region_add_subregion(address_space, base, mr); - memory_region_init_io(&s->io, NULL, &serial_mm_ops[end], s, - "serial", 8 << it_shift); - memory_region_add_subregion(address_space, base, &s->io); - return s; + return smm; } + +static void serial_mm_instance_init(Object *o) +{ + SerialMM *smm = SERIAL_MM(o); + + object_initialize_child(o, "serial", &smm->serial, sizeof(smm->serial), + TYPE_SERIAL, &error_abort, NULL); + + qdev_alias_all_properties(DEVICE(&smm->serial), o); +} + +static Property serial_mm_properties[] = { + /* + * Set the spacing between adjacent memory-mapped UART registers. + * Each register will be at (1 << regshift) bytes after the + * previous one. + */ + DEFINE_PROP_UINT8("regshift", SerialMM, regshift, 0), + DEFINE_PROP_UINT8("endianness", SerialMM, endianness, DEVICE_NATIVE_ENDIAN), + DEFINE_PROP_END_OF_LIST(), +}; + +static void serial_mm_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->props = serial_mm_properties; + dc->realize = serial_mm_realize; +} + +static const TypeInfo serial_mm_info = { + .name = TYPE_SERIAL_MM, + .parent = TYPE_SYS_BUS_DEVICE, + .class_init = serial_mm_class_init, + .instance_init = serial_mm_instance_init, + .instance_size = sizeof(SerialMM), + .class_init = serial_mm_class_init, +}; + +static void serial_register_types(void) +{ + type_register_static(&serial_info); + type_register_static(&serial_io_info); + type_register_static(&serial_mm_info); +} + +type_init(serial_register_types) diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index ac28890e5a..6ca7697599 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -501,13 +501,6 @@ const PropertyInfo qdev_prop_string = { .set = set_string, }; -/* --- pointer --- */ - -/* Not a proper property, just for dirty hacks. TODO Remove it! */ -const PropertyInfo qdev_prop_ptr = { - .name = "ptr", -}; - /* --- mac address --- */ /* @@ -1165,17 +1158,6 @@ void qdev_prop_set_enum(DeviceState *dev, const char *name, int value) name, &error_abort); } -void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value) -{ - Property *prop; - void **ptr; - - prop = qdev_prop_find(dev, name); - assert(prop && prop->info == &qdev_prop_ptr); - ptr = qdev_get_prop_ptr(dev, prop); - *ptr = value; -} - static GPtrArray *global_props(void) { static GPtrArray *gp; diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 501228ba08..9f1753f5cf 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -394,11 +394,8 @@ static NamedGPIOList *qdev_get_named_gpio_list(DeviceState *dev, NamedGPIOList *ngl; QLIST_FOREACH(ngl, &dev->gpios, node) { - /* NULL is a valid and matchable name, otherwise do a normal - * strcmp match. - */ - if ((!ngl->name && !name) || - (name && ngl->name && strcmp(name, ngl->name) == 0)) { + /* NULL is a valid and matchable name. */ + if (g_strcmp0(name, ngl->name) == 0) { return ngl; } } @@ -739,14 +736,6 @@ void qdev_property_add_static(DeviceState *dev, Property *prop, if (prop->info->create) { prop->info->create(obj, prop, &local_err); } else { - /* - * TODO qdev_prop_ptr does not have getters or setters. It must - * go now that it can be replaced with links. The test should be - * removed along with it: all static properties are read/write. - */ - if (!prop->info->get && !prop->info->set) { - return; - } object_property_add(obj, prop->name, prop->info->name, prop->info->get, prop->info->set, prop->info->release, diff --git a/hw/core/sysbus.c b/hw/core/sysbus.c index 9e69c83aed..08b0311c5f 100644 --- a/hw/core/sysbus.c +++ b/hw/core/sysbus.c @@ -250,38 +250,6 @@ DeviceState *sysbus_create_varargs(const char *name, return dev; } -DeviceState *sysbus_try_create_varargs(const char *name, - hwaddr addr, ...) -{ - DeviceState *dev; - SysBusDevice *s; - va_list va; - qemu_irq irq; - int n; - - dev = qdev_try_create(NULL, name); - if (!dev) { - return NULL; - } - s = SYS_BUS_DEVICE(dev); - qdev_init_nofail(dev); - if (addr != (hwaddr)-1) { - sysbus_mmio_map(s, 0, addr); - } - va_start(va, addr); - n = 0; - while (1) { - irq = va_arg(va, qemu_irq); - if (!irq) { - break; - } - sysbus_connect_irq(s, n, irq); - n++; - } - va_end(va); - return dev; -} - static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent) { SysBusDevice *s = SYS_BUS_DEVICE(dev); diff --git a/hw/cris/axis_dev88.c b/hw/cris/axis_dev88.c index 940c7dd122..be7760476a 100644 --- a/hw/cris/axis_dev88.c +++ b/hw/cris/axis_dev88.c @@ -253,7 +253,6 @@ void axisdev88_init(MachineState *machine) const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; CRISCPU *cpu; - CPUCRISState *env; DeviceState *dev; SysBusDevice *s; DriveInfo *nand; @@ -267,7 +266,6 @@ void axisdev88_init(MachineState *machine) /* init CPUs */ cpu = CRIS_CPU(cpu_create(machine->cpu_type)); - env = &cpu->env; /* allocate RAM */ memory_region_allocate_system_memory(phys_ram, NULL, "axisdev88.ram", @@ -297,8 +295,6 @@ void axisdev88_init(MachineState *machine) dev = qdev_create(NULL, "etraxfs,pic"); - /* FIXME: Is there a proper way to signal vectors to the CPU core? */ - qdev_prop_set_ptr(dev, "interrupt_vector", &env->interrupt_vector); qdev_init_nofail(dev); s = SYS_BUS_DEVICE(dev); sysbus_mmio_map(s, 0, 0x3001c000); diff --git a/hw/display/sm501.c b/hw/display/sm501.c index 1f33c87e65..66a1bfbe60 100644 --- a/hw/display/sm501.c +++ b/hw/display/sm501.c @@ -1930,7 +1930,7 @@ typedef struct { SM501State state; uint32_t vram_size; uint32_t base; - void *chr_state; + SerialMM serial; } SM501SysBusState; static void sm501_realize_sysbus(DeviceState *dev, Error **errp) @@ -1938,6 +1938,7 @@ static void sm501_realize_sysbus(DeviceState *dev, Error **errp) SM501SysBusState *s = SYSBUS_SM501(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); DeviceState *usb_dev; + MemoryRegion *mr; sm501_init(&s->state, dev, s->vram_size); if (get_local_mem_size(&s->state) != s->vram_size) { @@ -1958,17 +1959,15 @@ static void sm501_realize_sysbus(DeviceState *dev, Error **errp) sysbus_pass_irq(sbd, SYS_BUS_DEVICE(usb_dev)); /* bridge to serial emulation module */ - if (s->chr_state) { - serial_mm_init(&s->state.mmio_region, SM501_UART0, 2, - NULL, /* TODO : chain irq to IRL */ - 115200, s->chr_state, DEVICE_LITTLE_ENDIAN); - } + qdev_init_nofail(DEVICE(&s->serial)); + mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->serial), 0); + memory_region_add_subregion(&s->state.mmio_region, SM501_UART0, mr); + /* TODO : chain irq to IRL */ } static Property sm501_sysbus_properties[] = { DEFINE_PROP_UINT32("vram-size", SM501SysBusState, vram_size, 0), DEFINE_PROP_UINT32("base", SM501SysBusState, base, 0), - DEFINE_PROP_PTR("chr-state", SM501SysBusState, chr_state), DEFINE_PROP_END_OF_LIST(), }; @@ -1999,9 +1998,20 @@ static void sm501_sysbus_class_init(ObjectClass *klass, void *data) dc->props = sm501_sysbus_properties; dc->reset = sm501_reset_sysbus; dc->vmsd = &vmstate_sm501_sysbus; - /* Note: pointer property "chr-state" may remain null, thus - * no need for dc->user_creatable = false; - */ +} + +static void sm501_sysbus_init(Object *o) +{ + SM501SysBusState *sm501 = SYSBUS_SM501(o); + SerialMM *smm = &sm501->serial; + + sysbus_init_child_obj(o, "serial", smm, sizeof(SerialMM), TYPE_SERIAL_MM); + qdev_set_legacy_instance_id(DEVICE(smm), SM501_UART0, 2); + qdev_prop_set_uint8(DEVICE(smm), "regshift", 2); + qdev_prop_set_uint8(DEVICE(smm), "endianness", DEVICE_LITTLE_ENDIAN); + + object_property_add_alias(o, "chardev", + OBJECT(smm), "chardev", &error_abort); } static const TypeInfo sm501_sysbus_info = { @@ -2009,6 +2019,7 @@ static const TypeInfo sm501_sysbus_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(SM501SysBusState), .class_init = sm501_sysbus_class_init, + .instance_init = sm501_sysbus_init, }; #define TYPE_PCI_SM501 "sm501" diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index 0e5bbcdc7f..3e4da0c47f 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -346,7 +346,7 @@ static void sparc32_ledma_device_realize(DeviceState *dev, Error **errp) d = qdev_create(NULL, TYPE_LANCE); object_property_add_child(OBJECT(dev), "lance", OBJECT(d), errp); qdev_set_nic_properties(d, nd); - qdev_prop_set_ptr(d, "dma", dev); + object_property_set_link(OBJECT(d), OBJECT(dev), "dma", errp); qdev_init_nofail(d); } diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c index 41e1aa798c..85c16897ae 100644 --- a/hw/gpio/omap_gpio.c +++ b/hw/gpio/omap_gpio.c @@ -40,10 +40,6 @@ struct omap_gpio_s { uint16_t pins; }; -#define TYPE_OMAP1_GPIO "omap-gpio" -#define OMAP1_GPIO(obj) \ - OBJECT_CHECK(struct omap_gpif_s, (obj), TYPE_OMAP1_GPIO) - struct omap_gpif_s { SysBusDevice parent_obj; @@ -212,10 +208,6 @@ struct omap2_gpio_s { uint8_t delay; }; -#define TYPE_OMAP2_GPIO "omap2-gpio" -#define OMAP2_GPIO(obj) \ - OBJECT_CHECK(struct omap2_gpif_s, (obj), TYPE_OMAP2_GPIO) - struct omap2_gpif_s { SysBusDevice parent_obj; @@ -747,21 +739,13 @@ static void omap2_gpio_realize(DeviceState *dev, Error **errp) } } -/* Using qdev pointer properties for the clocks is not ideal. - * qdev should support a generic means of defining a 'port' with - * an arbitrary interface for connecting two devices. Then we - * could reframe the omap clock API in terms of clock ports, - * and get some type safety. For now the best qdev provides is - * passing an arbitrary pointer. - * (It's not possible to pass in the string which is the clock - * name, because this device does not have the necessary information - * (ie the struct omap_mpu_state_s*) to do the clockname to pointer - * translation.) - */ +void omap_gpio_set_clk(omap_gpif *gpio, omap_clk clk) +{ + gpio->clk = clk; +} static Property omap_gpio_properties[] = { DEFINE_PROP_INT32("mpu_model", struct omap_gpif_s, mpu_model, 0), - DEFINE_PROP_PTR("clk", struct omap_gpif_s, clk), DEFINE_PROP_END_OF_LIST(), }; @@ -784,15 +768,19 @@ static const TypeInfo omap_gpio_info = { .class_init = omap_gpio_class_init, }; +void omap2_gpio_set_iclk(omap2_gpif *gpio, omap_clk clk) +{ + gpio->iclk = clk; +} + +void omap2_gpio_set_fclk(omap2_gpif *gpio, uint8_t i, omap_clk clk) +{ + assert(i <= 5); + gpio->fclk[i] = clk; +} + static Property omap2_gpio_properties[] = { DEFINE_PROP_INT32("mpu_model", struct omap2_gpif_s, mpu_model, 0), - DEFINE_PROP_PTR("iclk", struct omap2_gpif_s, iclk), - DEFINE_PROP_PTR("fclk0", struct omap2_gpif_s, fclk[0]), - DEFINE_PROP_PTR("fclk1", struct omap2_gpif_s, fclk[1]), - DEFINE_PROP_PTR("fclk2", struct omap2_gpif_s, fclk[2]), - DEFINE_PROP_PTR("fclk3", struct omap2_gpif_s, fclk[3]), - DEFINE_PROP_PTR("fclk4", struct omap2_gpif_s, fclk[4]), - DEFINE_PROP_PTR("fclk5", struct omap2_gpif_s, fclk[5]), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/i2c/omap_i2c.c b/hw/i2c/omap_i2c.c index 3ba965a58f..3ccbd5cc2c 100644 --- a/hw/i2c/omap_i2c.c +++ b/hw/i2c/omap_i2c.c @@ -28,10 +28,7 @@ #include "qemu/error-report.h" #include "qapi/error.h" -#define TYPE_OMAP_I2C "omap_i2c" -#define OMAP_I2C(obj) OBJECT_CHECK(OMAPI2CState, (obj), TYPE_OMAP_I2C) - -typedef struct OMAPI2CState { +struct OMAPI2CState { SysBusDevice parent_obj; MemoryRegion iomem; @@ -56,7 +53,7 @@ typedef struct OMAPI2CState { uint8_t divider; uint8_t times[2]; uint16_t test; -} OMAPI2CState; +}; #define OMAP2_INTR_REV 0x34 #define OMAP2_GC_REV 0x34 @@ -504,10 +501,18 @@ static void omap_i2c_realize(DeviceState *dev, Error **errp) } } +void omap_i2c_set_iclk(OMAPI2CState *i2c, omap_clk clk) +{ + i2c->iclk = clk; +} + +void omap_i2c_set_fclk(OMAPI2CState *i2c, omap_clk clk) +{ + i2c->fclk = clk; +} + static Property omap_i2c_properties[] = { DEFINE_PROP_UINT8("revision", OMAPI2CState, revision, 0), - DEFINE_PROP_PTR("iclk", OMAPI2CState, iclk), - DEFINE_PROP_PTR("fclk", OMAPI2CState, fclk), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/i2c/smbus_eeprom.c b/hw/i2c/smbus_eeprom.c index 54c86a0112..5adf3b15b5 100644 --- a/hw/i2c/smbus_eeprom.c +++ b/hw/i2c/smbus_eeprom.c @@ -44,7 +44,7 @@ typedef struct SMBusEEPROMDevice { SMBusDevice smbusdev; uint8_t data[SMBUS_EEPROM_SIZE]; - void *init_data; + uint8_t *init_data; uint8_t offset; bool accessed; } SMBusEEPROMDevice; @@ -129,14 +129,14 @@ static void smbus_eeprom_reset(DeviceState *dev) static void smbus_eeprom_realize(DeviceState *dev, Error **errp) { + SMBusEEPROMDevice *eeprom = SMBUS_EEPROM(dev); + smbus_eeprom_reset(dev); + if (eeprom->init_data == NULL) { + error_setg(errp, "init_data cannot be NULL"); + } } -static Property smbus_eeprom_properties[] = { - DEFINE_PROP_PTR("data", SMBusEEPROMDevice, init_data), - DEFINE_PROP_END_OF_LIST(), -}; - static void smbus_eeprom_class_initfn(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -146,9 +146,8 @@ static void smbus_eeprom_class_initfn(ObjectClass *klass, void *data) dc->reset = smbus_eeprom_reset; sc->receive_byte = eeprom_receive_byte; sc->write_data = eeprom_write_data; - dc->props = smbus_eeprom_properties; dc->vmsd = &vmstate_smbus_eeprom; - /* Reason: pointer property "data" */ + /* Reason: init_data */ dc->user_creatable = false; } @@ -172,7 +171,8 @@ void smbus_eeprom_init_one(I2CBus *smbus, uint8_t address, uint8_t *eeprom_buf) dev = qdev_create((BusState *) smbus, TYPE_SMBUS_EEPROM); qdev_prop_set_uint8(dev, "address", address); - qdev_prop_set_ptr(dev, "data", eeprom_buf); + /* FIXME: use an array of byte or block backend property? */ + SMBUS_EEPROM(dev)->init_data = eeprom_buf; qdev_init_nofail(dev); } diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 42014b06de..8054bc4147 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1156,9 +1156,9 @@ static void pc_superio_init(ISABus *isa_bus, bool create_fdctrl, bool no_vmport) vmmouse = NULL; } if (vmmouse) { - DeviceState *dev = DEVICE(vmmouse); - qdev_prop_set_ptr(dev, "ps2_mouse", i8042); - qdev_init_nofail(dev); + object_property_set_link(OBJECT(vmmouse), OBJECT(i8042), + "i8042", &error_abort); + qdev_init_nofail(DEVICE(vmmouse)); } port92 = isa_create_simple(isa_bus, TYPE_PORT92); @@ -1198,7 +1198,6 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi, * when the HPET wants to take over. Thus we have to disable the latter. */ if (!no_hpet && (!kvm_irqchip_in_kernel() || kvm_has_pit_state2())) { - /* In order to set property, here not using sysbus_try_create_simple */ hpet = qdev_try_create(NULL, TYPE_HPET); if (hpet) { /* For pc-piix-*, hpet's intcap is always IRQ2. For pc-q35-1.7 diff --git a/hw/i386/vmmouse.c b/hw/i386/vmmouse.c index 41ad91ad53..c0c329f817 100644 --- a/hw/i386/vmmouse.c +++ b/hw/i386/vmmouse.c @@ -66,7 +66,7 @@ typedef struct VMMouseState uint16_t status; uint8_t absolute; QEMUPutMouseEntry *entry; - void *ps2_mouse; + ISAKBDState *i8042; } VMMouseState; static uint32_t vmmouse_get_status(VMMouseState *s) @@ -105,7 +105,7 @@ static void vmmouse_mouse_event(void *opaque, int x, int y, int dz, int buttons_ /* need to still generate PS2 events to notify driver to read from queue */ - i8042_isa_mouse_fake_event(s->ps2_mouse); + i8042_isa_mouse_fake_event(s->i8042); } static void vmmouse_remove_handler(VMMouseState *s) @@ -275,7 +275,7 @@ static void vmmouse_realizefn(DeviceState *dev, Error **errp) } static Property vmmouse_properties[] = { - DEFINE_PROP_PTR("ps2_mouse", VMMouseState, ps2_mouse), + DEFINE_PROP_LINK("i8042", VMMouseState, i8042, TYPE_I8042, ISAKBDState *), DEFINE_PROP_END_OF_LIST(), }; @@ -287,8 +287,6 @@ static void vmmouse_class_initfn(ObjectClass *klass, void *data) dc->reset = vmmouse_reset; dc->vmsd = &vmstate_vmmouse; dc->props = vmmouse_properties; - /* Reason: pointer property "ps2_mouse" */ - dc->user_creatable = false; } static const TypeInfo vmmouse_info = { diff --git a/hw/i386/x86-iommu-stub.c b/hw/i386/x86-iommu-stub.c index 03576cdccb..c5ba077f9d 100644 --- a/hw/i386/x86-iommu-stub.c +++ b/hw/i386/x86-iommu-stub.c @@ -32,3 +32,12 @@ X86IOMMUState *x86_iommu_get_default(void) return NULL; } +bool x86_iommu_ir_supported(X86IOMMUState *s) +{ + return false; +} + +IommuType x86_iommu_get_type(void) +{ + abort(); +} diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c index 2f09f780ba..60a4130320 100644 --- a/hw/input/pckbd.c +++ b/hw/input/pckbd.c @@ -482,17 +482,15 @@ void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, #define I8042(obj) OBJECT_CHECK(ISAKBDState, (obj), TYPE_I8042) -typedef struct ISAKBDState { +struct ISAKBDState { ISADevice parent_obj; KBDState kbd; MemoryRegion io[2]; -} ISAKBDState; +}; -void i8042_isa_mouse_fake_event(void *opaque) +void i8042_isa_mouse_fake_event(ISAKBDState *isa) { - ISADevice *dev = opaque; - ISAKBDState *isa = I8042(dev); KBDState *s = &isa->kbd; ps2_mouse_fake_event(s->mouse); diff --git a/hw/intc/etraxfs_pic.c b/hw/intc/etraxfs_pic.c index 77f652acec..12988c7aa9 100644 --- a/hw/intc/etraxfs_pic.c +++ b/hw/intc/etraxfs_pic.c @@ -27,8 +27,6 @@ #include "qemu/module.h" #include "hw/irq.h" #include "hw/qdev-properties.h" -//#include "pc.h" -//#include "etraxfs.h" #define D(x) @@ -48,7 +46,6 @@ struct etrax_pic SysBusDevice parent_obj; MemoryRegion mmio; - void *interrupt_vector; qemu_irq parent_irq; qemu_irq parent_nmi; uint32_t regs[R_MAX]; @@ -79,11 +76,7 @@ static void pic_update(struct etrax_pic *fs) } } - if (fs->interrupt_vector) { - /* hack alert: ptr property */ - *(uint32_t*)(fs->interrupt_vector) = vector; - } - qemu_set_irq(fs->parent_irq, !!vector); + qemu_set_irq(fs->parent_irq, vector); } static uint64_t @@ -163,28 +156,11 @@ static void etraxfs_pic_init(Object *obj) sysbus_init_mmio(sbd, &s->mmio); } -static Property etraxfs_pic_properties[] = { - DEFINE_PROP_PTR("interrupt_vector", struct etrax_pic, interrupt_vector), - DEFINE_PROP_END_OF_LIST(), -}; - -static void etraxfs_pic_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - - dc->props = etraxfs_pic_properties; - /* - * Note: pointer property "interrupt_vector" may remain null, thus - * no need for dc->user_creatable = false; - */ -} - static const TypeInfo etraxfs_pic_info = { .name = TYPE_ETRAX_FS_PIC, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(struct etrax_pic), .instance_init = etraxfs_pic_init, - .class_init = etraxfs_pic_class_init, }; static void etraxfs_pic_register_types(void) diff --git a/hw/intc/grlib_irqmp.c b/hw/intc/grlib_irqmp.c index bc78e1a14f..794c643af2 100644 --- a/hw/intc/grlib_irqmp.c +++ b/hw/intc/grlib_irqmp.c @@ -25,6 +25,7 @@ */ #include "qemu/osdep.h" +#include "hw/irq.h" #include "hw/sysbus.h" #include "cpu.h" @@ -58,10 +59,8 @@ typedef struct IRQMP { MemoryRegion iomem; - void *set_pil_in; - void *set_pil_in_opaque; - IRQMPState *state; + qemu_irq irq; } IRQMP; struct IRQMPState { @@ -82,7 +81,6 @@ static void grlib_irqmp_check_irqs(IRQMPState *state) uint32_t pend = 0; uint32_t level0 = 0; uint32_t level1 = 0; - set_pil_in_fn set_pil_in; assert(state != NULL); assert(state->parent != NULL); @@ -97,14 +95,8 @@ static void grlib_irqmp_check_irqs(IRQMPState *state) trace_grlib_irqmp_check_irqs(state->pending, state->force[0], state->mask[0], level1, level0); - set_pil_in = (set_pil_in_fn)state->parent->set_pil_in; - /* Trigger level1 interrupt first and level0 if there is no level1 */ - if (level1 != 0) { - set_pil_in(state->parent->set_pil_in_opaque, level1); - } else { - set_pil_in(state->parent->set_pil_in_opaque, level0); - } + qemu_set_irq(state->parent->irq, level1 ?: level0); } static void grlib_irqmp_ack_mask(IRQMPState *state, uint32_t mask) @@ -335,6 +327,7 @@ static void grlib_irqmp_init(Object *obj) IRQMP *irqmp = GRLIB_IRQMP(obj); SysBusDevice *dev = SYS_BUS_DEVICE(obj); + qdev_init_gpio_out_named(DEVICE(obj), &irqmp->irq, "grlib-irq", 1); memory_region_init_io(&irqmp->iomem, obj, &grlib_irqmp_ops, irqmp, "irqmp", IRQMP_REG_SIZE); @@ -343,31 +336,11 @@ static void grlib_irqmp_init(Object *obj) sysbus_init_mmio(dev, &irqmp->iomem); } -static void grlib_irqmp_realize(DeviceState *dev, Error **errp) -{ - IRQMP *irqmp = GRLIB_IRQMP(dev); - - /* Check parameters */ - if (irqmp->set_pil_in == NULL) { - error_setg(errp, "set_pil_in cannot be NULL."); - } -} - -static Property grlib_irqmp_properties[] = { - DEFINE_PROP_PTR("set_pil_in", IRQMP, set_pil_in), - DEFINE_PROP_PTR("set_pil_in_opaque", IRQMP, set_pil_in_opaque), - DEFINE_PROP_END_OF_LIST(), -}; - static void grlib_irqmp_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); dc->reset = grlib_irqmp_reset; - dc->props = grlib_irqmp_properties; - /* Reason: pointer properties "set_pil_in", "set_pil_in_opaque" */ - dc->user_creatable = false; - dc->realize = grlib_irqmp_realize; } static const TypeInfo grlib_irqmp_info = { diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c index 854b709ca0..73bb1c2af4 100644 --- a/hw/intc/omap_intc.c +++ b/hw/intc/omap_intc.c @@ -38,10 +38,6 @@ struct omap_intr_handler_bank_s { unsigned char priority[32]; }; -#define TYPE_OMAP_INTC "common-omap-intc" -#define OMAP_INTC(obj) \ - OBJECT_CHECK(struct omap_intr_handler_s, (obj), TYPE_OMAP_INTC) - struct omap_intr_handler_s { SysBusDevice parent_obj; @@ -391,9 +387,18 @@ static void omap_intc_realize(DeviceState *dev, Error **errp) } } +void omap_intc_set_iclk(omap_intr_handler *intc, omap_clk clk) +{ + intc->iclk = clk; +} + +void omap_intc_set_fclk(omap_intr_handler *intc, omap_clk clk) +{ + intc->fclk = clk; +} + static Property omap_intc_properties[] = { DEFINE_PROP_UINT32("size", struct omap_intr_handler_s, size, 0x100), - DEFINE_PROP_PTR("clk", struct omap_intr_handler_s, iclk), DEFINE_PROP_END_OF_LIST(), }; @@ -647,8 +652,6 @@ static void omap2_intc_realize(DeviceState *dev, Error **errp) static Property omap2_intc_properties[] = { DEFINE_PROP_UINT8("revision", struct omap_intr_handler_s, revision, 0x21), - DEFINE_PROP_PTR("iclk", struct omap_intr_handler_s, iclk), - DEFINE_PROP_PTR("fclk", struct omap_intr_handler_s, fclk), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/m68k/q800.c b/hw/m68k/q800.c index 0e5a08f993..12491ecde6 100644 --- a/hw/m68k/q800.c +++ b/hw/m68k/q800.c @@ -266,7 +266,8 @@ static void q800_init(MachineState *machine) qdev_set_nic_properties(dev, &nd_table[0]); qdev_prop_set_uint8(dev, "it_shift", 2); qdev_prop_set_bit(dev, "big_endian", true); - qdev_prop_set_ptr(dev, "dma_mr", get_system_memory()); + object_property_set_link(OBJECT(dev), OBJECT(get_system_memory()), + "dma_mr", &error_abort); qdev_init_nofail(dev); sysbus = SYS_BUS_DEVICE(dev); sysbus_mmio_map(sysbus, 0, SONIC_BASE); diff --git a/hw/mips/boston.c b/hw/mips/boston.c index ca7d813a52..23fdd5ec6a 100644 --- a/hw/mips/boston.c +++ b/hw/mips/boston.c @@ -50,7 +50,7 @@ typedef struct { MachineState *mach; MIPSCPSState cps; - SerialState *uart; + SerialMM *uart; CharBackend lcd_display; char lcd_content[8]; diff --git a/hw/mips/cps.c b/hw/mips/cps.c index 1660f86908..c49868d5da 100644 --- a/hw/mips/cps.c +++ b/hw/mips/cps.c @@ -106,7 +106,7 @@ static void mips_cps_realize(DeviceState *dev, Error **errp) object_property_set_bool(OBJECT(&s->itu), saar_present, "saar-present", &err); if (saar_present) { - qdev_prop_set_ptr(DEVICE(&s->itu), "saar", (void *)&env->CP0_SAAR); + s->itu.saar = &env->CP0_SAAR; } object_property_set_bool(OBJECT(&s->itu), true, "realized", &err); if (err != NULL) { diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c index 291fd6c1b8..66fd4d867d 100644 --- a/hw/mips/mips_jazz.c +++ b/hw/mips/mips_jazz.c @@ -290,7 +290,8 @@ static void mips_jazz_init(MachineState *machine, dev = qdev_create(NULL, "dp8393x"); qdev_set_nic_properties(dev, nd); qdev_prop_set_uint8(dev, "it_shift", 2); - qdev_prop_set_ptr(dev, "dma_mr", rc4030_dma_mr); + object_property_set_link(OBJECT(dev), OBJECT(rc4030_dma_mr), + "dma_mr", &error_abort); qdev_init_nofail(dev); sysbus = SYS_BUS_DEVICE(dev); sysbus_mmio_map(sysbus, 0, 0x80001000); diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 783cd99848..ea92e5e27d 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -83,7 +83,7 @@ typedef struct { uint32_t i2csel; CharBackend display; char display_text[9]; - SerialState *uart; + SerialMM *uart; bool display_inited; } MaltaFPGAState; diff --git a/hw/mips/mips_mipssim.c b/hw/mips/mips_mipssim.c index 282bbecb24..84c03dd035 100644 --- a/hw/mips/mips_mipssim.c +++ b/hw/mips/mips_mipssim.c @@ -40,6 +40,7 @@ #include "hw/loader.h" #include "elf.h" #include "hw/sysbus.h" +#include "hw/qdev-properties.h" #include "exec/address-spaces.h" #include "qemu/error-report.h" #include "sysemu/qtest.h" @@ -219,9 +220,16 @@ mips_mipssim_init(MachineState *machine) * A single 16450 sits at offset 0x3f8. It is attached to * MIPS CPU INT2, which is interrupt 4. */ - if (serial_hd(0)) - serial_init(0x3f8, env->irq[4], 115200, serial_hd(0), - get_system_io()); + if (serial_hd(0)) { + DeviceState *dev = qdev_create(NULL, TYPE_SERIAL_IO); + + qdev_prop_set_chr(dev, "chardev", serial_hd(0)); + qdev_set_legacy_instance_id(dev, 0x3f8, 2); + qdev_init_nofail(dev); + sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, env->irq[4]); + sysbus_add_io(SYS_BUS_DEVICE(dev), 0x3f8, + sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0)); + } if (nd_table[0].used) /* MIPSnet uses the MIPS CPU INT0, which is interrupt 2. */ diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c index 3d991af163..cdc2631c0c 100644 --- a/hw/net/dp8393x.c +++ b/hw/net/dp8393x.c @@ -175,7 +175,7 @@ typedef struct dp8393xState { int loopback_packet; /* Memory access */ - void *dma_mr; + MemoryRegion *dma_mr; AddressSpace as; } dp8393xState; @@ -948,7 +948,8 @@ static const VMStateDescription vmstate_dp8393x = { static Property dp8393x_properties[] = { DEFINE_NIC_PROPERTIES(dp8393xState, conf), - DEFINE_PROP_PTR("dma_mr", dp8393xState, dma_mr), + DEFINE_PROP_LINK("dma_mr", dp8393xState, dma_mr, + TYPE_MEMORY_REGION, MemoryRegion *), DEFINE_PROP_UINT8("it_shift", dp8393xState, it_shift, 0), DEFINE_PROP_BOOL("big_endian", dp8393xState, big_endian, false), DEFINE_PROP_END_OF_LIST(), @@ -963,8 +964,6 @@ static void dp8393x_class_init(ObjectClass *klass, void *data) dc->reset = dp8393x_reset; dc->vmsd = &vmstate_dp8393x; dc->props = dp8393x_properties; - /* Reason: dma_mr property can't be set */ - dc->user_creatable = false; } static const TypeInfo dp8393x_info = { diff --git a/hw/net/etraxfs_eth.c b/hw/net/etraxfs_eth.c index 4cfbf1135a..f30d963487 100644 --- a/hw/net/etraxfs_eth.c +++ b/hw/net/etraxfs_eth.c @@ -338,14 +338,8 @@ typedef struct ETRAXFSEthState uint8_t macaddr[2][6]; uint32_t regs[FS_ETH_MAX_REGS]; - union { - void *vdma_out; - struct etraxfs_dma_client *dma_out; - }; - union { - void *vdma_in; - struct etraxfs_dma_client *dma_in; - }; + struct etraxfs_dma_client *dma_out; + struct etraxfs_dma_client *dma_in; /* MDIO bus. */ struct qemu_mdio mdio_bus; @@ -635,8 +629,6 @@ static void etraxfs_eth_realize(DeviceState *dev, Error **errp) static Property etraxfs_eth_properties[] = { DEFINE_PROP_UINT32("phyaddr", ETRAXFSEthState, phyaddr, 1), - DEFINE_PROP_PTR("dma_out", ETRAXFSEthState, vdma_out), - DEFINE_PROP_PTR("dma_in", ETRAXFSEthState, vdma_in), DEFINE_NIC_PROPERTIES(ETRAXFSEthState, conf), DEFINE_PROP_END_OF_LIST(), }; @@ -648,10 +640,40 @@ static void etraxfs_eth_class_init(ObjectClass *klass, void *data) dc->realize = etraxfs_eth_realize; dc->reset = etraxfs_eth_reset; dc->props = etraxfs_eth_properties; - /* Reason: pointer properties "dma_out", "dma_in" */ + /* Reason: dma_out, dma_in are not user settable */ dc->user_creatable = false; } + +/* Instantiate an ETRAXFS Ethernet MAC. */ +DeviceState * +etraxfs_eth_init(NICInfo *nd, hwaddr base, int phyaddr, + struct etraxfs_dma_client *dma_out, + struct etraxfs_dma_client *dma_in) +{ + DeviceState *dev; + qemu_check_nic_model(nd, "fseth"); + + dev = qdev_create(NULL, "etraxfs-eth"); + qdev_set_nic_properties(dev, nd); + qdev_prop_set_uint32(dev, "phyaddr", phyaddr); + + /* + * TODO: QOM design, define a QOM interface for "I am an etraxfs + * DMA client" (which replaces the current 'struct + * etraxfs_dma_client' ad-hoc interface), implement it on the + * ethernet device, and then have QOM link properties on the DMA + * controller device so that you can pass the interface + * implementations to it. + */ + ETRAX_FS_ETH(dev)->dma_out = dma_out; + ETRAX_FS_ETH(dev)->dma_in = dma_in; + qdev_init_nofail(dev); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); + + return dev; +} + static const TypeInfo etraxfs_eth_info = { .name = TYPE_ETRAX_FS_ETH, .parent = TYPE_SYS_BUS_DEVICE, diff --git a/hw/net/lance.c b/hw/net/lance.c index 6631e2a4e0..4d96299041 100644 --- a/hw/net/lance.c +++ b/hw/net/lance.c @@ -138,7 +138,8 @@ static void lance_instance_init(Object *obj) } static Property lance_properties[] = { - DEFINE_PROP_PTR("dma", SysBusPCNetState, state.dma_opaque), + DEFINE_PROP_LINK("dma", SysBusPCNetState, state.dma_opaque, + TYPE_DEVICE, DeviceState *), DEFINE_NIC_PROPERTIES(SysBusPCNetState, state.conf), DEFINE_PROP_END_OF_LIST(), }; @@ -153,8 +154,6 @@ static void lance_class_init(ObjectClass *klass, void *data) dc->reset = lance_reset; dc->vmsd = &vmstate_lance; dc->props = lance_properties; - /* Reason: pointer property "dma" */ - dc->user_creatable = false; } static const TypeInfo lance_info = { diff --git a/hw/net/pcnet-pci.c b/hw/net/pcnet-pci.c index 4723c30c79..d067d21e2c 100644 --- a/hw/net/pcnet-pci.c +++ b/hw/net/pcnet-pci.c @@ -231,7 +231,7 @@ static void pci_pcnet_realize(PCIDevice *pci_dev, Error **errp) s->irq = pci_allocate_irq(pci_dev); s->phys_mem_read = pci_physical_memory_read; s->phys_mem_write = pci_physical_memory_write; - s->dma_opaque = pci_dev; + s->dma_opaque = DEVICE(pci_dev); pcnet_common_init(DEVICE(pci_dev), s, &net_pci_pcnet_info); } diff --git a/hw/net/pcnet.h b/hw/net/pcnet.h index 28d19a5c6f..f49b213c57 100644 --- a/hw/net/pcnet.h +++ b/hw/net/pcnet.h @@ -50,7 +50,7 @@ struct PCNetState_st { uint8_t *buf, int len, int do_bswap); void (*phys_mem_write)(void *dma_opaque, hwaddr addr, uint8_t *buf, int len, int do_bswap); - void *dma_opaque; + DeviceState *dma_opaque; int tx_busy; int looptest; }; diff --git a/hw/semihosting/console.c b/hw/semihosting/console.c index b4b17c8afb..6346bd7f50 100644 --- a/hw/semihosting/console.c +++ b/hw/semihosting/console.c @@ -20,8 +20,15 @@ #include "hw/semihosting/semihost.h" #include "hw/semihosting/console.h" #include "exec/gdbstub.h" +#include "exec/exec-all.h" #include "qemu/log.h" #include "chardev/char.h" +#include <pthread.h> +#include "chardev/char-fe.h" +#include "sysemu/sysemu.h" +#include "qemu/main-loop.h" +#include "qapi/error.h" +#include "qemu/fifo8.h" int qemu_semihosting_log_out(const char *s, int len) { @@ -98,3 +105,75 @@ void qemu_semihosting_console_outc(CPUArchState *env, target_ulong addr) __func__, addr); } } + +#define FIFO_SIZE 1024 + +/* Access to this structure is protected by the BQL */ +typedef struct SemihostingConsole { + CharBackend backend; + GSList *sleeping_cpus; + bool got; + Fifo8 fifo; +} SemihostingConsole; + +static SemihostingConsole console; + +static int console_can_read(void *opaque) +{ + SemihostingConsole *c = opaque; + int ret; + g_assert(qemu_mutex_iothread_locked()); + ret = (int) fifo8_num_free(&c->fifo); + return ret; +} + +static void console_wake_up(gpointer data, gpointer user_data) +{ + CPUState *cs = (CPUState *) data; + /* cpu_handle_halt won't know we have work so just unbung here */ + cs->halted = 0; + qemu_cpu_kick(cs); +} + +static void console_read(void *opaque, const uint8_t *buf, int size) +{ + SemihostingConsole *c = opaque; + g_assert(qemu_mutex_iothread_locked()); + while (size-- && !fifo8_is_full(&c->fifo)) { + fifo8_push(&c->fifo, *buf++); + } + g_slist_foreach(c->sleeping_cpus, console_wake_up, NULL); + c->sleeping_cpus = NULL; +} + +target_ulong qemu_semihosting_console_inc(CPUArchState *env) +{ + uint8_t ch; + SemihostingConsole *c = &console; + g_assert(qemu_mutex_iothread_locked()); + g_assert(current_cpu); + if (fifo8_is_empty(&c->fifo)) { + c->sleeping_cpus = g_slist_prepend(c->sleeping_cpus, current_cpu); + current_cpu->halted = 1; + current_cpu->exception_index = EXCP_HALTED; + cpu_loop_exit(current_cpu); + /* never returns */ + } + ch = fifo8_pop(&c->fifo); + return (target_ulong) ch; +} + +void qemu_semihosting_console_init(void) +{ + Chardev *chr = semihosting_get_chardev(); + + if (chr) { + fifo8_create(&console.fifo, FIFO_SIZE); + qemu_chr_fe_init(&console.backend, chr, &error_abort); + qemu_chr_fe_set_handlers(&console.backend, + console_can_read, + console_read, + NULL, NULL, &console, + NULL, true); + } +} diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c index ee0840f380..72bb5285cc 100644 --- a/hw/sh4/r2d.c +++ b/hw/sh4/r2d.c @@ -272,7 +272,7 @@ static void r2d_init(MachineState *machine) busdev = SYS_BUS_DEVICE(dev); qdev_prop_set_uint32(dev, "vram-size", SM501_VRAM_SIZE); qdev_prop_set_uint32(dev, "base", 0x10000000); - qdev_prop_set_ptr(dev, "chr-state", serial_hd(2)); + qdev_prop_set_chr(dev, "chardev", serial_hd(2)); qdev_init_nofail(dev); sysbus_mmio_map(busdev, 0, 0x10000000); sysbus_mmio_map(busdev, 1, 0x13e00000); diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c index c5f1b1ee72..8038887ff7 100644 --- a/hw/sparc/leon3.c +++ b/hw/sparc/leon3.c @@ -143,9 +143,14 @@ void leon3_irq_ack(void *irq_manager, int intno) grlib_irqmp_ack((DeviceState *)irq_manager, intno); } -static void leon3_set_pil_in(void *opaque, uint32_t pil_in) +/* + * This device assumes that the incoming 'level' value on the + * qemu_irq is the interrupt number, not just a simple 0/1 level. + */ +static void leon3_set_pil_in(void *opaque, int n, int level) { - CPUSPARCState *env = (CPUSPARCState *)opaque; + CPUSPARCState *env = opaque; + uint32_t pil_in = level; CPUState *cs; assert(env != NULL); @@ -225,8 +230,10 @@ static void leon3_generic_hw_init(MachineState *machine) /* Allocate IRQ manager */ dev = qdev_create(NULL, TYPE_GRLIB_IRQMP); - qdev_prop_set_ptr(dev, "set_pil_in", leon3_set_pil_in); - qdev_prop_set_ptr(dev, "set_pil_in_opaque", env); + qdev_init_gpio_in_named_with_opaque(DEVICE(cpu), leon3_set_pil_in, + env, "pil", 1); + qdev_connect_gpio_out_named(dev, "grlib-irq", 0, + qdev_get_gpio_in_named(DEVICE(cpu), "pil", 0)); qdev_init_nofail(dev); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, LEON3_IRQMP_OFFSET); env->irq_manager = dev; diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h index f3aa670036..6be386d0e2 100644 --- a/include/hw/arm/omap.h +++ b/include/hw/arm/omap.h @@ -67,6 +67,58 @@ void omap_clk_setrate(omap_clk clk, int divide, int multiply); int64_t omap_clk_getrate(omap_clk clk); void omap_clk_reparent(omap_clk clk, omap_clk parent); +/* omap_intc.c */ +#define TYPE_OMAP_INTC "common-omap-intc" +#define OMAP_INTC(obj) \ + OBJECT_CHECK(omap_intr_handler, (obj), TYPE_OMAP_INTC) + +typedef struct omap_intr_handler_s omap_intr_handler; + +/* + * TODO: Ideally we should have a clock framework that + * let us wire these clocks up with QOM properties or links. + * + * qdev should support a generic means of defining a 'port' with + * an arbitrary interface for connecting two devices. Then we + * could reframe the omap clock API in terms of clock ports, + * and get some type safety. For now the best qdev provides is + * passing an arbitrary pointer. + * (It's not possible to pass in the string which is the clock + * name, because this device does not have the necessary information + * (ie the struct omap_mpu_state_s*) to do the clockname to pointer + * translation.) + */ +void omap_intc_set_iclk(omap_intr_handler *intc, omap_clk clk); +void omap_intc_set_fclk(omap_intr_handler *intc, omap_clk clk); + +/* omap_i2c.c */ +#define TYPE_OMAP_I2C "omap_i2c" +#define OMAP_I2C(obj) OBJECT_CHECK(OMAPI2CState, (obj), TYPE_OMAP_I2C) + +typedef struct OMAPI2CState OMAPI2CState; + +/* TODO: clock framework (see above) */ +void omap_i2c_set_iclk(OMAPI2CState *i2c, omap_clk clk); +void omap_i2c_set_fclk(OMAPI2CState *i2c, omap_clk clk); + +/* omap_gpio.c */ +#define TYPE_OMAP1_GPIO "omap-gpio" +#define OMAP1_GPIO(obj) \ + OBJECT_CHECK(struct omap_gpif_s, (obj), TYPE_OMAP1_GPIO) + +#define TYPE_OMAP2_GPIO "omap2-gpio" +#define OMAP2_GPIO(obj) \ + OBJECT_CHECK(struct omap2_gpif_s, (obj), TYPE_OMAP2_GPIO) + +typedef struct omap_gpif_s omap_gpif; +typedef struct omap2_gpif_s omap2_gpif; + +/* TODO: clock framework (see above) */ +void omap_gpio_set_clk(omap_gpif *gpio, omap_clk clk); + +void omap2_gpio_set_iclk(omap2_gpif *gpio, omap_clk clk); +void omap2_gpio_set_fclk(omap2_gpif *gpio, uint8_t i, omap_clk clk); + /* OMAP2 l4 Interconnect */ struct omap_l4_s; struct omap_l4_region_s { diff --git a/include/hw/char/serial.h b/include/hw/char/serial.h index 8be3d8a4f9..535fa23a2b 100644 --- a/include/hw/char/serial.h +++ b/include/hw/char/serial.h @@ -30,10 +30,13 @@ #include "exec/memory.h" #include "qemu/fifo8.h" #include "chardev/char.h" +#include "hw/sysbus.h" #define UART_FIFO_LENGTH 16 /* 16550A Fifo Length */ typedef struct SerialState { + DeviceState parent; + uint16_t divider; uint8_t rbr; /* receive register */ uint8_t thr; /* transmit holding register */ @@ -54,8 +57,7 @@ typedef struct SerialState { qemu_irq irq; CharBackend chr; int last_break_enable; - int it_shift; - int baudbase; + uint32_t baudbase; uint32_t tsr_retry; guint watch_tag; uint32_t wakeup; @@ -77,20 +79,39 @@ typedef struct SerialState { MemoryRegion io; } SerialState; +typedef struct SerialMM { + SysBusDevice parent; + + SerialState serial; + + uint8_t regshift; + uint8_t endianness; +} SerialMM; + +typedef struct SerialIO { + SysBusDevice parent; + + SerialState serial; +} SerialIO; + extern const VMStateDescription vmstate_serial; extern const MemoryRegionOps serial_io_ops; -void serial_realize_core(SerialState *s, Error **errp); -void serial_exit_core(SerialState *s); void serial_set_frequency(SerialState *s, uint32_t frequency); -/* legacy pre qom */ -SerialState *serial_init(int base, qemu_irq irq, int baudbase, - Chardev *chr, MemoryRegion *system_io); -SerialState *serial_mm_init(MemoryRegion *address_space, - hwaddr base, int it_shift, - qemu_irq irq, int baudbase, - Chardev *chr, enum device_endian end); +#define TYPE_SERIAL "serial" +#define SERIAL(s) OBJECT_CHECK(SerialState, (s), TYPE_SERIAL) + +#define TYPE_SERIAL_MM "serial-mm" +#define SERIAL_MM(s) OBJECT_CHECK(SerialMM, (s), TYPE_SERIAL_MM) + +#define TYPE_SERIAL_IO "serial-io" +#define SERIAL_IO(s) OBJECT_CHECK(SerialIO, (s), TYPE_SERIAL_IO) + +SerialMM *serial_mm_init(MemoryRegion *address_space, + hwaddr base, int regshift, + qemu_irq irq, int baudbase, + Chardev *chr, enum device_endian end); /* serial-isa.c */ diff --git a/include/hw/cris/etraxfs.h b/include/hw/cris/etraxfs.h index aa146a2cd8..403e7f95e6 100644 --- a/include/hw/cris/etraxfs.h +++ b/include/hw/cris/etraxfs.h @@ -30,23 +30,9 @@ #include "hw/qdev-properties.h" #include "hw/sysbus.h" -/* Instantiate an ETRAXFS Ethernet MAC. */ -static inline DeviceState * -etraxfs_eth_init(NICInfo *nd, hwaddr base, int phyaddr, - void *dma_out, void *dma_in) -{ - DeviceState *dev; - qemu_check_nic_model(nd, "fseth"); - - dev = qdev_create(NULL, "etraxfs-eth"); - qdev_set_nic_properties(dev, nd); - qdev_prop_set_uint32(dev, "phyaddr", phyaddr); - qdev_prop_set_ptr(dev, "dma_out", dma_out); - qdev_prop_set_ptr(dev, "dma_in", dma_in); - qdev_init_nofail(dev); - sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base); - return dev; -} +DeviceState *etraxfs_eth_init(NICInfo *nd, hwaddr base, int phyaddr, + struct etraxfs_dma_client *dma_out, + struct etraxfs_dma_client *dma_in); static inline DeviceState *etraxfs_ser_create(hwaddr addr, qemu_irq irq, diff --git a/include/hw/input/i8042.h b/include/hw/input/i8042.h index 246e6f3335..8eaebf50ce 100644 --- a/include/hw/input/i8042.h +++ b/include/hw/input/i8042.h @@ -14,10 +14,12 @@ #define I8042_A20_LINE "a20" +typedef struct ISAKBDState ISAKBDState; + void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq, MemoryRegion *region, ram_addr_t size, hwaddr mask); -void i8042_isa_mouse_fake_event(void *opaque); +void i8042_isa_mouse_fake_event(ISAKBDState *isa); void i8042_setup_a20_line(ISADevice *dev, qemu_irq a20_out); #endif /* HW_INPUT_I8042_H */ diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index c6a8cb5516..a90a9cec80 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -18,7 +18,6 @@ extern const PropertyInfo qdev_prop_size; extern const PropertyInfo qdev_prop_string; extern const PropertyInfo qdev_prop_chr; extern const PropertyInfo qdev_prop_tpm; -extern const PropertyInfo qdev_prop_ptr; extern const PropertyInfo qdev_prop_macaddr; extern const PropertyInfo qdev_prop_on_off_auto; extern const PropertyInfo qdev_prop_losttickpolicy; @@ -171,25 +170,6 @@ extern const PropertyInfo qdev_prop_pcie_link_width; #define DEFINE_PROP_PCI_DEVFN(_n, _s, _f, _d) \ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_pci_devfn, int32_t) -/* - * Please avoid pointer properties. If you must use them, you must - * cover them in their device's class init function as follows: - * - * - If the property must be set, the device cannot be used with - * device_add, so add code like this: - * |* Reason: pointer property "NAME-OF-YOUR-PROP" *| - * DeviceClass *dc = DEVICE_CLASS(class); - * dc->user_creatable = false; - * - * - If the property may safely remain null, document it like this: - * |* - * * Note: pointer property "interrupt_vector" may remain null, thus - * * no need for dc->user_creatable = false; - * *| - */ -#define DEFINE_PROP_PTR(_n, _s, _f) \ - DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, void*) - #define DEFINE_PROP_CHR(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharBackend) #define DEFINE_PROP_STRING(_n, _s, _f) \ @@ -216,8 +196,6 @@ extern const PropertyInfo qdev_prop_pcie_link_width; DEFINE_PROP_UNSIGNED(_n, _s, _f, 0, qdev_prop_blocksize, uint16_t) #define DEFINE_PROP_PCI_HOST_DEVADDR(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_pci_host_devaddr, PCIHostDeviceAddress) -#define DEFINE_PROP_MEMORY_REGION(_n, _s, _f) \ - DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, MemoryRegion *) #define DEFINE_PROP_OFF_AUTO_PCIBAR(_n, _s, _f, _d) \ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_off_auto_pcibar, \ OffAutoPCIBAR) @@ -264,8 +242,6 @@ void qdev_prop_set_drive(DeviceState *dev, const char *name, void qdev_prop_set_macaddr(DeviceState *dev, const char *name, const uint8_t *value); void qdev_prop_set_enum(DeviceState *dev, const char *name, int value); -/* FIXME: Remove opaque pointer properties. */ -void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value); void qdev_prop_register_global(GlobalProperty *prop); int qdev_prop_check_globals(void); diff --git a/include/hw/semihosting/console.h b/include/hw/semihosting/console.h index 9be9754bcd..0238f540f4 100644 --- a/include/hw/semihosting/console.h +++ b/include/hw/semihosting/console.h @@ -38,6 +38,22 @@ int qemu_semihosting_console_outs(CPUArchState *env, target_ulong s); void qemu_semihosting_console_outc(CPUArchState *env, target_ulong c); /** + * qemu_semihosting_console_inc: + * @env: CPUArchState + * + * Receive single character from debug console. This may be the remote + * gdb session if a softmmu guest is currently being debugged. As this + * call may block if no data is available we suspend the CPU and will + * re-execute the instruction when data is there. Therefore two + * conditions must be met: + * - CPUState is synchronized before calling this function + * - pc is only updated once the character is successfully returned + * + * Returns: character read OR cpu_loop_exit! + */ +target_ulong qemu_semihosting_console_inc(CPUArchState *env); + +/** * qemu_semihosting_log_out: * @s: pointer to string * @len: length of string diff --git a/include/hw/semihosting/semihost.h b/include/hw/semihosting/semihost.h index 60fc42d851..b8ce5117ae 100644 --- a/include/hw/semihosting/semihost.h +++ b/include/hw/semihosting/semihost.h @@ -56,6 +56,9 @@ static inline Chardev *semihosting_get_chardev(void) { return NULL; } +static inline void qemu_semihosting_console_init(void) +{ +} #else /* !CONFIG_USER_ONLY */ bool semihosting_enabled(void); SemihostingTarget semihosting_get_target(void); @@ -68,6 +71,7 @@ Chardev *semihosting_get_chardev(void); void qemu_semihosting_enable(void); int qemu_semihosting_config_options(const char *opt); void qemu_semihosting_connect_chardevs(void); +void qemu_semihosting_console_init(void); #endif /* CONFIG_USER_ONLY */ #endif /* SEMIHOST_H */ diff --git a/include/hw/sysbus.h b/include/hw/sysbus.h index 27e80881da..c4a1c0adfa 100644 --- a/include/hw/sysbus.h +++ b/include/hw/sysbus.h @@ -24,10 +24,6 @@ typedef struct SysBusDevice SysBusDevice; /** * SysBusDeviceClass: - * @init: Callback function invoked when the #DeviceState.realized property - * is changed to %true. Deprecated, new types inheriting directly from - * TYPE_SYS_BUS_DEVICE should use #DeviceClass.realize instead, new leaf - * types should consult their respective parent type. * * SysBusDeviceClass is not overriding #DeviceClass.realize, so derived * classes overriding it are not required to invoke its implementation. @@ -117,8 +113,7 @@ void foreach_dynamic_sysbus_device(FindSysbusDeviceFunc *func, void *opaque); /* Legacy helper function for creating devices. */ DeviceState *sysbus_create_varargs(const char *name, hwaddr addr, ...); -DeviceState *sysbus_try_create_varargs(const char *name, - hwaddr addr, ...); + static inline DeviceState *sysbus_create_simple(const char *name, hwaddr addr, qemu_irq irq) @@ -126,11 +121,5 @@ static inline DeviceState *sysbus_create_simple(const char *name, return sysbus_create_varargs(name, addr, irq, NULL); } -static inline DeviceState *sysbus_try_create_simple(const char *name, - hwaddr addr, - qemu_irq irq) -{ - return sysbus_try_create_varargs(name, addr, irq, NULL); -} #endif /* HW_SYSBUS_H */ diff --git a/include/qemu/id.h b/include/qemu/id.h index 40c70103e4..b55c406e69 100644 --- a/include/qemu/id.h +++ b/include/qemu/id.h @@ -4,6 +4,7 @@ typedef enum IdSubSystems { ID_QDEV, ID_BLOCK, + ID_CHR, ID_MAX /* last element, used as array size */ } IdSubSystems; diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c index 31c845a70d..bbe9fefca8 100644 --- a/linux-user/aarch64/cpu_loop.c +++ b/linux-user/aarch64/cpu_loop.c @@ -130,6 +130,7 @@ void cpu_loop(CPUARMState *env) break; case EXCP_SEMIHOST: env->xregs[0] = do_arm_semihosting(env); + env->pc += 4; break; case EXCP_YIELD: /* nothing to do here for user-mode, just resume guest code */ diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c index 7be4071751..1fae90c6df 100644 --- a/linux-user/arm/cpu_loop.c +++ b/linux-user/arm/cpu_loop.c @@ -377,6 +377,7 @@ void cpu_loop(CPUARMState *env) break; case EXCP_SEMIHOST: env->regs[0] = do_arm_semihosting(env); + env->regs[15] += env->thumb ? 2 : 4; break; case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ diff --git a/linux-user/arm/semihost.c b/linux-user/arm/semihost.c index a16b525eec..a1f0f6050e 100644 --- a/linux-user/arm/semihost.c +++ b/linux-user/arm/semihost.c @@ -14,6 +14,7 @@ #include "cpu.h" #include "hw/semihosting/console.h" #include "qemu.h" +#include <termios.h> int qemu_semihosting_console_outs(CPUArchState *env, target_ulong addr) { @@ -47,3 +48,29 @@ void qemu_semihosting_console_outc(CPUArchState *env, target_ulong addr) } } } + +/* + * For linux-user we can safely block. However as we want to return as + * soon as a character is read we need to tweak the termio to disable + * line buffering. We restore the old mode afterwards in case the + * program is expecting more normal behaviour. This is slow but + * nothing using semihosting console reading is expecting to be fast. + */ +target_ulong qemu_semihosting_console_inc(CPUArchState *env) +{ + uint8_t c; + struct termios old_tio, new_tio; + + /* Disable line-buffering and echo */ + tcgetattr(STDIN_FILENO, &old_tio); + new_tio = old_tio; + new_tio.c_lflag &= (~ICANON & ~ECHO); + tcsetattr(STDIN_FILENO, TCSANOW, &new_tio); + + c = getchar(); + + /* restore config */ + tcsetattr(STDIN_FILENO, TCSANOW, &old_tio); + + return (target_ulong) c; +} diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c index 236e8e41dd..f4494f98ac 100644 --- a/qom/qom-qmp-cmds.c +++ b/qom/qom-qmp-cmds.c @@ -142,16 +142,6 @@ static ObjectPropertyInfo *make_device_property_info(ObjectClass *klass, continue; } - /* - * TODO Properties without a parser are just for dirty hacks. - * qdev_prop_ptr is the only such PropertyInfo. It's marked - * for removal. This conditional should be removed along with - * it. - */ - if (!prop->info->set && !prop->info->create) { - return NULL; /* no way to set it, don't show */ - } - info = g_malloc0(sizeof(*info)); info->name = g_strdup(prop->name); info->type = default_type ? g_strdup(default_type) diff --git a/stubs/semihost.c b/stubs/semihost.c index f90589259c..1d8b37f7b2 100644 --- a/stubs/semihost.c +++ b/stubs/semihost.c @@ -69,3 +69,7 @@ void semihosting_arg_fallback(const char *file, const char *cmd) void qemu_semihosting_connect_chardevs(void) { } + +void qemu_semihosting_console_init(void) +{ +} diff --git a/target/arm/arm-semi.c b/target/arm/arm-semi.c index 6f7b6d801b..47d61f6fe1 100644 --- a/target/arm/arm-semi.c +++ b/target/arm/arm-semi.c @@ -802,8 +802,7 @@ target_ulong do_arm_semihosting(CPUARMState *env) return guestfd_fns[gf->type].readfn(cpu, gf, arg1, len); case TARGET_SYS_READC: - qemu_log_mask(LOG_UNIMP, "%s: SYS_READC not implemented", __func__); - return 0; + return qemu_semihosting_console_inc(env); case TARGET_SYS_ISTTY: GET_ARG(0); diff --git a/target/arm/helper.c b/target/arm/helper.c index b6bec42f48..19a57a17da 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -8566,12 +8566,6 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs) case EXCP_VFIQ: addr += 0x100; break; - case EXCP_SEMIHOST: - qemu_log_mask(CPU_LOG_INT, - "...handling as semihosting call 0x%" PRIx64 "\n", - env->xregs[0]); - env->xregs[0] = do_arm_semihosting(env); - return; default: cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index); } @@ -8620,11 +8614,13 @@ static void handle_semihosting(CPUState *cs) "...handling as semihosting call 0x%" PRIx64 "\n", env->xregs[0]); env->xregs[0] = do_arm_semihosting(env); + env->pc += 4; } else { qemu_log_mask(CPU_LOG_INT, "...handling as semihosting call 0x%x\n", env->regs[0]); env->regs[0] = do_arm_semihosting(env); + env->regs[15] += env->thumb ? 2 : 4; } } #endif diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c index 76de317e6a..33d414a684 100644 --- a/target/arm/m_helper.c +++ b/target/arm/m_helper.c @@ -2185,6 +2185,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs) "...handling as semihosting call 0x%x\n", env->regs[0]); env->regs[0] = do_arm_semihosting(env); + env->regs[15] += env->thumb ? 2 : 4; return; case EXCP_BKPT: armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG, false); diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index d4bebbe629..972c28c3c9 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -1937,7 +1937,7 @@ static void disas_exc(DisasContext *s, uint32_t insn) break; } #endif - gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST); + gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST); } else { unsupported_encoding(s, insn); } diff --git a/target/arm/translate.c b/target/arm/translate.c index 2b6c1f91bf..5185e08641 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1124,7 +1124,7 @@ static inline void gen_hlt(DisasContext *s, int imm) s->current_el != 0 && #endif (imm == (s->thumb ? 0x3c : 0xf000))) { - gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST); + gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST); return; } @@ -8457,7 +8457,7 @@ static bool trans_BKPT(DisasContext *s, arg_BKPT *a) !IS_USER(s) && #endif (a->imm == 0xab)) { - gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST); + gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST); } else { gen_exception_bkpt_insn(s, syn_aa32_bkpt(a->imm, false)); } @@ -10266,7 +10266,7 @@ static bool trans_SVC(DisasContext *s, arg_SVC *a) !IS_USER(s) && #endif (a->imm == semihost_imm)) { - gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST); + gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST); } else { gen_set_pc_im(s, s->base.pc_next); s->svc_imm = a->imm; diff --git a/target/cris/cpu.c b/target/cris/cpu.c index 7adfd6caf4..6a857f548d 100644 --- a/target/cris/cpu.c +++ b/target/cris/cpu.c @@ -147,6 +147,14 @@ static void cris_cpu_set_irq(void *opaque, int irq, int level) CPUState *cs = CPU(cpu); int type = irq == CRIS_CPU_IRQ ? CPU_INTERRUPT_HARD : CPU_INTERRUPT_NMI; + if (irq == CRIS_CPU_IRQ) { + /* + * The PIC passes us the vector for the IRQ as the value it sends + * over the qemu_irq line + */ + cpu->env.interrupt_vector = level; + } + if (level) { cpu_interrupt(cs, type); } else { diff --git a/target/cris/cpu.h b/target/cris/cpu.h index aba0a66474..a7c2a8e15b 100644 --- a/target/cris/cpu.h +++ b/target/cris/cpu.h @@ -34,6 +34,7 @@ #define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_3 /* CRUS CPU device objects interrupt lines. */ +/* PIC passes the vector for the IRQ as the value of it sends over qemu_irq */ #define CRIS_CPU_IRQ 0 #define CRIS_CPU_NMI 1 diff --git a/tests/Makefile.include b/tests/Makefile.include index 49e3b0d319..7a767bf114 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -969,7 +969,7 @@ FP_TEST_BIN=$(BUILD_DIR)/tests/fp/fp-test # the build dir is created by configure .PHONY: $(FP_TEST_BIN) -$(FP_TEST_BIN): +$(FP_TEST_BIN): config-host.h $(test-util-obj-y) $(call quiet-command, \ $(MAKE) $(SUBDIR_MAKEFLAGS) -C $(dir $@) V="$(V)" $(notdir $@), \ "BUILD", "$(notdir $@)") diff --git a/tests/fp/Makefile b/tests/fp/Makefile index 5a35e7c210..56768ecfd2 100644 --- a/tests/fp/Makefile +++ b/tests/fp/Makefile @@ -554,15 +554,13 @@ TF_OBJS_LIB += $(TF_OBJS_TEST) BINARIES := fp-test$(EXESUF) fp-bench$(EXESUF) -# everything depends on config-host.h because platform.h includes it -all: $(BUILD_DIR)/config-host.h - $(MAKE) $(BINARIES) +# We require artefacts from the main build including config-host.h +# because platform.h includes it. Rather than re-invoking the main +# build we just error out if things aren't there. +$(LIBQEMUUTIL) $(BUILD_DIR)/config-host.h: + $(error $@ missing, re-run parent build) -$(LIBQEMUUTIL): - $(MAKE) -C $(BUILD_DIR) libqemuutil.a - -$(BUILD_DIR)/config-host.h: - $(MAKE) -C $(BUILD_DIR) config-host.h +all: $(BUILD_DIR)/config-host.h $(BINARIES) # libtestfloat.a depends on libsoftfloat.a, so specify it first FP_TEST_LIBS := libtestfloat.a libsoftfloat.a $(LIBQEMUUTIL) diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target index 950dbb4bac..7b4eede3f0 100644 --- a/tests/tcg/aarch64/Makefile.softmmu-target +++ b/tests/tcg/aarch64/Makefile.softmmu-target @@ -31,7 +31,16 @@ LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc memory: CFLAGS+=-DCHECK_UNALIGNED=1 # Running -QEMU_OPTS+=-M virt -cpu max -display none -semihosting-config enable=on,target=native,chardev=output -kernel +QEMU_BASE_MACHINE=-M virt -cpu max -display none +QEMU_OPTS+=$(QEMU_BASE_MACHINE) -semihosting-config enable=on,target=native,chardev=output -kernel + +# console test is manual only +QEMU_SEMIHOST=-chardev stdio,mux=on,id=stdio0 -semihosting-config enable=on,chardev=stdio0 -mon chardev=stdio0,mode=readline +run-semiconsole: QEMU_OPTS=$(QEMU_BASE_MACHINE) $(QEMU_SEMIHOST) -kernel +run-semiconsole: semiconsole + $(call skip-test, $<, "MANUAL ONLY") +run-plugin-semiconsole-with-%: semiconsole + $(call skip-test, $<, "MANUAL ONLY") # Simple Record/Replay Test .PHONY: memory-record diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target index 96d2321045..df3fe8032c 100644 --- a/tests/tcg/aarch64/Makefile.target +++ b/tests/tcg/aarch64/Makefile.target @@ -32,4 +32,11 @@ run-plugin-semihosting-with-%: $(call strip-plugin,$<) 2> $<.err, \ "$< on $(TARGET_NAME) with $*") +AARCH64_TESTS += semiconsole +run-semiconsole: semiconsole + $(call skip-test, $<, "MANUAL ONLY") + +run-plugin-semiconsole-with-%: + $(call skip-test, $<, "MANUAL ONLY") + TESTS += $(AARCH64_TESTS) diff --git a/tests/tcg/aarch64/system/semiconsole.c b/tests/tcg/aarch64/system/semiconsole.c new file mode 100644 index 0000000000..bfe7c9e26b --- /dev/null +++ b/tests/tcg/aarch64/system/semiconsole.c @@ -0,0 +1,38 @@ +/* + * Semihosting Console Test + * + * Copyright (c) 2019 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include <inttypes.h> +#include <minilib.h> + +#define SYS_READC 0x7 + +uintptr_t __semi_call(uintptr_t type, uintptr_t arg0) +{ + register uintptr_t t asm("x0") = type; + register uintptr_t a0 asm("x1") = arg0; + asm("hlt 0xf000" + : "=r" (t) + : "r" (t), "r" (a0)); + + return t; +} + +int main(void) +{ + char c; + + ml_printf("Semihosting Console Test\n"); + ml_printf("hit X to exit:"); + + do { + c = __semi_call(SYS_READC, 0); + __sys_outc(c); + } while (c != 'X'); + + return 0; +} diff --git a/tests/tcg/arm/Makefile.target b/tests/tcg/arm/Makefile.target index 0765f37ff0..11c39c601e 100644 --- a/tests/tcg/arm/Makefile.target +++ b/tests/tcg/arm/Makefile.target @@ -31,15 +31,43 @@ run-fcvt: fcvt # Semihosting smoke test for linux-user ARM_TESTS += semihosting +semihosting: CFLAGS += -mthumb run-semihosting: semihosting $(call run-test,$<,$(QEMU) $< 2> $<.err, "$< on $(TARGET_NAME)") +ARM_TESTS += semihosting-arm +semihosting-arm: CFLAGS += -marm +semihosting-arm: semihosting.c + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) + +run-semihosting-arm: semihosting-arm + $(call run-test,$<,$(QEMU) $< 2> $<.err, "$< on $(TARGET_NAME)") + run-plugin-semihosting-with-%: $(call run-test, $@, $(QEMU) $(QEMU_OPTS) \ -plugin $(PLUGIN_DIR)/$(call extract-plugin,$@) \ $(call strip-plugin,$<) 2> $<.err, \ "$< on $(TARGET_NAME) with $*") +ARM_TESTS += semiconsole semiconsole-arm + +semiconsole: CFLAGS += -mthumb +run-semiconsole: semiconsole + $(call skip-test, $<, "MANUAL ONLY") + +run-plugin-semiconsole-with-%: + $(call skip-test, $<, "MANUAL ONLY") + +semiconsole-arm: CFLAGS += -marm +semiconsole-arm: semiconsole.c + $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) + +run-semiconsole-arm: semiconsole-arm + $(call skip-test, $<, "MANUAL ONLY") + +run-plugin-semiconsole-arm-with-%: + $(call skip-test, $<, "MANUAL ONLY") + TESTS += $(ARM_TESTS) # On ARM Linux only supports 4k pages diff --git a/tests/tcg/arm/semicall.h b/tests/tcg/arm/semicall.h new file mode 100644 index 0000000000..d4f6818192 --- /dev/null +++ b/tests/tcg/arm/semicall.h @@ -0,0 +1,35 @@ +/* + * Semihosting Tests + * + * Copyright (c) 2019 + * Written by Alex Bennée <alex.bennee@linaro.org> + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#define SYS_WRITE0 0x04 +#define SYS_READC 0x07 +#define SYS_REPORTEXC 0x18 + +uintptr_t __semi_call(uintptr_t type, uintptr_t arg0) +{ +#if defined(__arm__) + register uintptr_t t asm("r0") = type; + register uintptr_t a0 asm("r1") = arg0; +#ifdef __thumb__ +# define SVC "svc 0xab" +#else +# define SVC "svc 0x123456" +#endif + asm(SVC : "=r" (t) + : "r" (t), "r" (a0)); +#else + register uintptr_t t asm("x0") = type; + register uintptr_t a0 asm("x1") = arg0; + asm("hlt 0xf000" + : "=r" (t) + : "r" (t), "r" (a0)); +#endif + + return t; +} diff --git a/tests/tcg/arm/semiconsole.c b/tests/tcg/arm/semiconsole.c new file mode 100644 index 0000000000..6ef0bd2450 --- /dev/null +++ b/tests/tcg/arm/semiconsole.c @@ -0,0 +1,27 @@ +/* + * linux-user semihosting console + * + * Copyright (c) 2019 + * Written by Alex Bennée <alex.bennee@linaro.org> + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +#include <stdio.h> +#include <stdint.h> +#include "semicall.h" + +int main(void) +{ + char c; + + printf("Semihosting Console Test\n"); + printf("hit X to exit:"); + + do { + c = __semi_call(SYS_READC, 0); + printf("got '%c'\n", c); + } while (c != 'X'); + + return 0; +} diff --git a/tests/tcg/arm/semihosting.c b/tests/tcg/arm/semihosting.c index 09c89cb481..33faac9916 100644 --- a/tests/tcg/arm/semihosting.c +++ b/tests/tcg/arm/semihosting.c @@ -8,26 +8,7 @@ */ #include <stdint.h> - -#define SYS_WRITE0 0x04 -#define SYS_REPORTEXC 0x18 - -void __semi_call(uintptr_t type, uintptr_t arg0) -{ -#if defined(__arm__) - register uintptr_t t asm("r0") = type; - register uintptr_t a0 asm("r1") = arg0; - asm("svc 0xab" - : /* no return */ - : "r" (t), "r" (a0)); -#else - register uintptr_t t asm("x0") = type; - register uintptr_t a0 asm("x1") = arg0; - asm("hlt 0xf000" - : /* no return */ - : "r" (t), "r" (a0)); -#endif -} +#include "semicall.h" int main(int argc, char *argv[argc]) { diff --git a/tests/vm/freebsd b/tests/vm/freebsd index 1825cc5821..33a736298a 100755 --- a/tests/vm/freebsd +++ b/tests/vm/freebsd @@ -32,6 +32,7 @@ class FreeBSDVM(basevm.BaseVM): "git", "pkgconf", "bzip2", + "python37", # gnu tools "bash", @@ -63,7 +64,7 @@ class FreeBSDVM(basevm.BaseVM): mkdir src build; cd src; tar -xf /dev/vtbd1; cd ../build - ../src/configure --python=python3.6 {configure_opts}; + ../src/configure --python=python3.7 {configure_opts}; gmake --output-sync -j{jobs} {target} {verbose}; """ diff --git a/tests/vm/openbsd b/tests/vm/openbsd index 6df5162dbf..d6173506f7 100755 --- a/tests/vm/openbsd +++ b/tests/vm/openbsd @@ -22,8 +22,8 @@ class OpenBSDVM(basevm.BaseVM): name = "openbsd" arch = "x86_64" - link = "https://cdn.openbsd.org/pub/OpenBSD/6.5/amd64/install65.iso" - csum = "38d1f8cadd502f1c27bf05c5abde6cc505dd28f3f34f8a941048ff9a54f9f608" + link = "https://cdn.openbsd.org/pub/OpenBSD/6.6/amd64/install66.iso" + csum = "b22e63df56e6266de6bbeed8e9be0fbe9ee2291551c5bc03f3cc2e4ab9436ee3" size = "20G" pkgs = [ # tools diff --git a/util/id.c b/util/id.c index af1c5f1b81..5addb4460e 100644 --- a/util/id.c +++ b/util/id.c @@ -34,6 +34,7 @@ bool id_wellformed(const char *id) static const char *const id_subsys_str[ID_MAX] = { [ID_QDEV] = "qdev", [ID_BLOCK] = "block", + [ID_CHR] = "chr", }; /* diff --git a/vl.c b/vl.c index 86474a55c9..b211921258 100644 --- a/vl.c +++ b/vl.c @@ -4238,6 +4238,9 @@ int main(int argc, char **argv, char **envp) qemu_opts_foreach(qemu_find_opts("mon"), mon_init_func, NULL, &error_fatal); + /* connect semihosting console input if requested */ + qemu_semihosting_console_init(); + if (foreach_device_config(DEV_SERIAL, serial_parse) < 0) exit(1); if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0) |