diff options
Diffstat (limited to 'hw')
39 files changed, 456 insertions, 369 deletions
@@ -23,10 +23,14 @@ #include "hw/pc.h" #include "hw/acpi.h" #include "monitor/monitor.h" +#include "qemu/config-file.h" +#include "qapi/opts-visitor.h" +#include "qapi/dealloc-visitor.h" +#include "qapi-visit.h" struct acpi_table_header { uint16_t _length; /* our length, not actual part of the hdr */ - /* XXX why we have 2 length fields here? */ + /* allows easier parsing for fw_cfg clients */ char sig[4]; /* ACPI signature (4 ASCII characters) */ uint32_t length; /* Length of table, in bytes, including header */ uint8_t revision; /* ACPI Specification minor version # */ @@ -41,16 +45,29 @@ struct acpi_table_header { #define ACPI_TABLE_HDR_SIZE sizeof(struct acpi_table_header) #define ACPI_TABLE_PFX_SIZE sizeof(uint16_t) /* size of the extra prefix */ -static const char dfl_hdr[ACPI_TABLE_HDR_SIZE] = - "\0\0" /* fake _length (2) */ +static const char unsigned dfl_hdr[ACPI_TABLE_HDR_SIZE - ACPI_TABLE_PFX_SIZE] = "QEMU\0\0\0\0\1\0" /* sig (4), len(4), revno (1), csum (1) */ "QEMUQEQEMUQEMU\1\0\0\0" /* OEM id (6), table (8), revno (4) */ "QEMU\1\0\0\0" /* ASL compiler ID (4), version (4) */ ; -char *acpi_tables; +char unsigned *acpi_tables; size_t acpi_tables_len; +static QemuOptsList qemu_acpi_opts = { + .name = "acpi", + .implied_opt_name = "data", + .head = QTAILQ_HEAD_INITIALIZER(qemu_acpi_opts.head), + .desc = { { 0 } } /* validated with OptsVisitor */ +}; + +static void acpi_register_config(void) +{ + qemu_add_opts(&qemu_acpi_opts); +} + +machine_init(acpi_register_config); + static int acpi_checksum(const uint8_t *data, int len) { int sum, i; @@ -61,184 +78,235 @@ static int acpi_checksum(const uint8_t *data, int len) return (-sum) & 0xff; } -/* XXX fixme: this function uses obsolete argument parsing interface */ -int acpi_table_add(const char *t) -{ - char buf[1024], *p, *f; - unsigned long val; - size_t len, start, allen; - bool has_header; - int changed; - int r; - struct acpi_table_header hdr; - - r = 0; - r |= get_param_value(buf, sizeof(buf), "data", t) ? 1 : 0; - r |= get_param_value(buf, sizeof(buf), "file", t) ? 2 : 0; - switch (r) { - case 0: - buf[0] = '\0'; - /* fallthrough for default behavior */ - case 1: - has_header = false; - break; - case 2: - has_header = true; - break; - default: - fprintf(stderr, "acpitable: both data and file are specified\n"); - return -1; - } - if (!acpi_tables) { - allen = sizeof(uint16_t); - acpi_tables = g_malloc0(allen); +/* Install a copy of the ACPI table specified in @blob. + * + * If @has_header is set, @blob starts with the System Description Table Header + * structure. Otherwise, "dfl_hdr" is prepended. In any case, each header field + * is optionally overwritten from @hdrs. + * + * It is valid to call this function with + * (@blob == NULL && bloblen == 0 && !has_header). + * + * @hdrs->file and @hdrs->data are ignored. + * + * SIZE_MAX is considered "infinity" in this function. + * + * The number of tables that can be installed is not limited, but the 16-bit + * counter at the beginning of "acpi_tables" wraps around after UINT16_MAX. + */ +static void acpi_table_install(const char unsigned *blob, size_t bloblen, + bool has_header, + const struct AcpiTableOptions *hdrs, + Error **errp) +{ + size_t body_start; + const char unsigned *hdr_src; + size_t body_size, acpi_payload_size; + struct acpi_table_header *ext_hdr; + unsigned changed_fields; + + /* Calculate where the ACPI table body starts within the blob, plus where + * to copy the ACPI table header from. + */ + if (has_header) { + /* _length | ACPI header in blob | blob body + * ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^ + * ACPI_TABLE_PFX_SIZE sizeof dfl_hdr body_size + * == body_start + * + * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * acpi_payload_size == bloblen + */ + body_start = sizeof dfl_hdr; + + if (bloblen < body_start) { + error_setg(errp, "ACPI table claiming to have header is too " + "short, available: %zu, expected: %zu", bloblen, + body_start); + return; + } + hdr_src = blob; } else { - allen = acpi_tables_len; + /* _length | ACPI header in template | blob body + * ^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^ + * ACPI_TABLE_PFX_SIZE sizeof dfl_hdr body_size + * == bloblen + * + * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + * acpi_payload_size + */ + body_start = 0; + hdr_src = dfl_hdr; } + body_size = bloblen - body_start; + acpi_payload_size = sizeof dfl_hdr + body_size; - start = allen; - acpi_tables = g_realloc(acpi_tables, start + ACPI_TABLE_HDR_SIZE); - allen += has_header ? ACPI_TABLE_PFX_SIZE : ACPI_TABLE_HDR_SIZE; + if (acpi_payload_size > UINT16_MAX) { + error_setg(errp, "ACPI table too big, requested: %zu, max: %u", + acpi_payload_size, (unsigned)UINT16_MAX); + return; + } - /* now read in the data files, reallocating buffer as needed */ + /* We won't fail from here on. Initialize / extend the globals. */ + if (acpi_tables == NULL) { + acpi_tables_len = sizeof(uint16_t); + acpi_tables = g_malloc0(acpi_tables_len); + } - for (f = strtok(buf, ":"); f; f = strtok(NULL, ":")) { - int fd = open(f, O_RDONLY | O_BINARY); + acpi_tables = g_realloc(acpi_tables, acpi_tables_len + + ACPI_TABLE_PFX_SIZE + + sizeof dfl_hdr + body_size); - if (fd < 0) { - fprintf(stderr, "can't open file %s: %s\n", f, strerror(errno)); - return -1; - } + ext_hdr = (struct acpi_table_header *)(acpi_tables + acpi_tables_len); + acpi_tables_len += ACPI_TABLE_PFX_SIZE; - for (;;) { - char data[8192]; - r = read(fd, data, sizeof(data)); - if (r == 0) { - break; - } else if (r > 0) { - acpi_tables = g_realloc(acpi_tables, allen + r); - memcpy(acpi_tables + allen, data, r); - allen += r; - } else if (errno != EINTR) { - fprintf(stderr, "can't read file %s: %s\n", - f, strerror(errno)); - close(fd); - return -1; - } - } + memcpy(acpi_tables + acpi_tables_len, hdr_src, sizeof dfl_hdr); + acpi_tables_len += sizeof dfl_hdr; - close(fd); + if (blob != NULL) { + memcpy(acpi_tables + acpi_tables_len, blob + body_start, body_size); + acpi_tables_len += body_size; } - /* now fill in the header fields */ + /* increase number of tables */ + cpu_to_le16wu((uint16_t *)acpi_tables, + le16_to_cpupu((uint16_t *)acpi_tables) + 1u); - f = acpi_tables + start; /* start of the table */ - changed = 0; + /* Update the header fields. The strings need not be NUL-terminated. */ + changed_fields = 0; + ext_hdr->_length = cpu_to_le16(acpi_payload_size); - /* copy the header to temp place to align the fields */ - memcpy(&hdr, has_header ? f : dfl_hdr, ACPI_TABLE_HDR_SIZE); + if (hdrs->has_sig) { + strncpy(ext_hdr->sig, hdrs->sig, sizeof ext_hdr->sig); + ++changed_fields; + } - /* length of the table minus our prefix */ - len = allen - start - ACPI_TABLE_PFX_SIZE; + if (has_header && le32_to_cpu(ext_hdr->length) != acpi_payload_size) { + fprintf(stderr, + "warning: ACPI table has wrong length, header says " + "%" PRIu32 ", actual size %zu bytes\n", + le32_to_cpu(ext_hdr->length), acpi_payload_size); + } + ext_hdr->length = cpu_to_le32(acpi_payload_size); - hdr._length = cpu_to_le16(len); + if (hdrs->has_rev) { + ext_hdr->revision = hdrs->rev; + ++changed_fields; + } - if (get_param_value(buf, sizeof(buf), "sig", t)) { - /* strncpy is justified: the field need not be NUL-terminated. */ - strncpy(hdr.sig, buf, sizeof(hdr.sig)); - ++changed; + ext_hdr->checksum = 0; + + if (hdrs->has_oem_id) { + strncpy(ext_hdr->oem_id, hdrs->oem_id, sizeof ext_hdr->oem_id); + ++changed_fields; + } + if (hdrs->has_oem_table_id) { + strncpy(ext_hdr->oem_table_id, hdrs->oem_table_id, + sizeof ext_hdr->oem_table_id); + ++changed_fields; + } + if (hdrs->has_oem_rev) { + ext_hdr->oem_revision = cpu_to_le32(hdrs->oem_rev); + ++changed_fields; + } + if (hdrs->has_asl_compiler_id) { + strncpy(ext_hdr->asl_compiler_id, hdrs->asl_compiler_id, + sizeof ext_hdr->asl_compiler_id); + ++changed_fields; + } + if (hdrs->has_asl_compiler_rev) { + ext_hdr->asl_compiler_revision = cpu_to_le32(hdrs->asl_compiler_rev); + ++changed_fields; } - /* length of the table including header, in bytes */ - if (has_header) { - /* check if actual length is correct */ - val = le32_to_cpu(hdr.length); - if (val != len) { - fprintf(stderr, - "warning: acpitable has wrong length," - " header says %lu, actual size %zu bytes\n", - val, len); - ++changed; - } + if (!has_header && changed_fields == 0) { + fprintf(stderr, "warning: ACPI table: no headers are specified\n"); } - /* we may avoid putting length here if has_header is true */ - hdr.length = cpu_to_le32(len); - if (get_param_value(buf, sizeof(buf), "rev", t)) { - val = strtoul(buf, &p, 0); - if (val > 255 || *p) { - fprintf(stderr, "acpitable: \"rev=%s\" is invalid\n", buf); - return -1; - } - hdr.revision = (uint8_t)val; - ++changed; + /* recalculate checksum */ + ext_hdr->checksum = acpi_checksum((const char unsigned *)ext_hdr + + ACPI_TABLE_PFX_SIZE, acpi_payload_size); +} + +void acpi_table_add(const QemuOpts *opts, Error **errp) +{ + AcpiTableOptions *hdrs = NULL; + Error *err = NULL; + char **pathnames = NULL; + char **cur; + size_t bloblen = 0; + char unsigned *blob = NULL; + + { + OptsVisitor *ov; + + ov = opts_visitor_new(opts); + visit_type_AcpiTableOptions(opts_get_visitor(ov), &hdrs, NULL, &err); + opts_visitor_cleanup(ov); } - if (get_param_value(buf, sizeof(buf), "oem_id", t)) { - /* strncpy is justified: the field need not be NUL-terminated. */ - strncpy(hdr.oem_id, buf, sizeof(hdr.oem_id)); - ++changed; + if (err) { + goto out; + } + if (hdrs->has_file == hdrs->has_data) { + error_setg(&err, "'-acpitable' requires one of 'data' or 'file'"); + goto out; } - if (get_param_value(buf, sizeof(buf), "oem_table_id", t)) { - /* strncpy is justified: the field need not be NUL-terminated. */ - strncpy(hdr.oem_table_id, buf, sizeof(hdr.oem_table_id)); - ++changed; + pathnames = g_strsplit(hdrs->has_file ? hdrs->file : hdrs->data, ":", 0); + if (pathnames == NULL || pathnames[0] == NULL) { + error_setg(&err, "'-acpitable' requires at least one pathname"); + goto out; } - if (get_param_value(buf, sizeof(buf), "oem_rev", t)) { - val = strtol(buf, &p, 0); - if (*p) { - fprintf(stderr, "acpitable: \"oem_rev=%s\" is invalid\n", buf); - return -1; + /* now read in the data files, reallocating buffer as needed */ + for (cur = pathnames; *cur; ++cur) { + int fd = open(*cur, O_RDONLY | O_BINARY); + + if (fd < 0) { + error_setg(&err, "can't open file %s: %s", *cur, strerror(errno)); + goto out; } - hdr.oem_revision = cpu_to_le32(val); - ++changed; - } - if (get_param_value(buf, sizeof(buf), "asl_compiler_id", t)) { - /* strncpy is justified: the field need not be NUL-terminated. */ - strncpy(hdr.asl_compiler_id, buf, sizeof(hdr.asl_compiler_id)); - ++changed; - } + for (;;) { + char unsigned data[8192]; + ssize_t r; - if (get_param_value(buf, sizeof(buf), "asl_compiler_rev", t)) { - val = strtol(buf, &p, 0); - if (*p) { - fprintf(stderr, "acpitable: \"%s=%s\" is invalid\n", - "asl_compiler_rev", buf); - return -1; + r = read(fd, data, sizeof data); + if (r == 0) { + break; + } else if (r > 0) { + blob = g_realloc(blob, bloblen + r); + memcpy(blob + bloblen, data, r); + bloblen += r; + } else if (errno != EINTR) { + error_setg(&err, "can't read file %s: %s", + *cur, strerror(errno)); + close(fd); + goto out; + } } - hdr.asl_compiler_revision = cpu_to_le32(val); - ++changed; - } - if (!has_header && !changed) { - fprintf(stderr, "warning: acpitable: no table headers are specified\n"); + close(fd); } + acpi_table_install(blob, bloblen, hdrs->has_file, hdrs, &err); - /* now calculate checksum of the table, complete with the header */ - /* we may as well leave checksum intact if has_header is true */ - /* alternatively there may be a way to set cksum to a given value */ - hdr.checksum = 0; /* for checksum calculation */ +out: + g_free(blob); + g_strfreev(pathnames); - /* put header back */ - memcpy(f, &hdr, sizeof(hdr)); + if (hdrs != NULL) { + QapiDeallocVisitor *dv; - if (changed || !has_header || 1) { - ((struct acpi_table_header *)f)->checksum = - acpi_checksum((uint8_t *)f + ACPI_TABLE_PFX_SIZE, len); + dv = qapi_dealloc_visitor_new(); + visit_type_AcpiTableOptions(qapi_dealloc_get_visitor(dv), &hdrs, NULL, + NULL); + qapi_dealloc_visitor_cleanup(dv); } - /* increase number of tables */ - (*(uint16_t *)acpi_tables) = - cpu_to_le32(le32_to_cpu(*(uint16_t *)acpi_tables) + 1); - - acpi_tables_len = allen; - return 0; - + error_propagate(errp, err); } static void acpi_notify_wakeup(Notifier *notifier, void *data) @@ -472,8 +540,9 @@ static const MemoryRegionOps acpi_pm_cnt_ops = { .endianness = DEVICE_LITTLE_ENDIAN, }; -void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent) +void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, uint8_t s4_val) { + ar->pm1.cnt.s4_val = s4_val; ar->wakeup.notify = acpi_notify_wakeup; qemu_register_wakeup_notifier(&ar->wakeup); memory_region_init_io(&ar->pm1.cnt.io, &acpi_pm_cnt_ops, ar, "acpi-cnt", 2); @@ -142,7 +142,7 @@ void acpi_pm1_evt_init(ACPIREGS *ar, acpi_update_sci_fn update_sci, MemoryRegion *parent); /* PM1a_CNT: piix and ich9 don't implement PM1b CNT. */ -void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent); +void acpi_pm1_cnt_init(ACPIREGS *ar, MemoryRegion *parent, uint8_t s4_val); void acpi_pm1_cnt_update(ACPIREGS *ar, bool sci_enable, bool sci_disable); void acpi_pm1_cnt_reset(ACPIREGS *ar); diff --git a/hw/acpi_ich9.c b/hw/acpi_ich9.c index 29f84ffb45..7b34a03866 100644 --- a/hw/acpi_ich9.c +++ b/hw/acpi_ich9.c @@ -212,7 +212,7 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, acpi_pm_tmr_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io); acpi_pm1_evt_init(&pm->acpi_regs, ich9_pm_update_sci_fn, &pm->io); - acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io); + acpi_pm1_cnt_init(&pm->acpi_regs, &pm->io, 2); acpi_gpe_init(&pm->acpi_regs, ICH9_PMIO_GPE0_LEN); memory_region_init_io(&pm->io_gpe, &ich9_gpe_ops, pm, "apci-gpe0", diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c index 7a4b712919..48a32b5aa0 100644 --- a/hw/acpi_piix4.c +++ b/hw/acpi_piix4.c @@ -418,7 +418,7 @@ static int piix4_pm_initfn(PCIDevice *dev) acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io); acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io); - acpi_pm1_cnt_init(&s->ar, &s->io); + acpi_pm1_cnt_init(&s->ar, &s->io, s->s4_val); acpi_gpe_init(&s->ar, GPE_LEN); s->powerdown_notifier.notify = piix4_pm_powerdown_req; diff --git a/hw/apic_common.c b/hw/apic_common.c index d0c261602c..37985097ca 100644 --- a/hw/apic_common.c +++ b/hw/apic_common.c @@ -218,7 +218,7 @@ static void apic_reset_common(DeviceState *d) bool bsp; bsp = cpu_is_bsp(s->cpu); - s->apicbase = 0xfee00000 | + s->apicbase = APIC_DEFAULT_ADDRESS | (bsp ? MSR_IA32_APICBASE_BSP : 0) | MSR_IA32_APICBASE_ENABLE; s->vapic_paddr = 0; diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c index 6747c1c547..b28e7d372f 100644 --- a/hw/arm/nseries.c +++ b/hw/arm/nseries.c @@ -129,8 +129,6 @@ static void n800_mmc_cs_cb(void *opaque, int line, int level) /* TODO: this seems to actually be connected to the menelaus, to * which also both MMC slots connect. */ omap_mmc_enable((struct omap_mmc_s *) opaque, !level); - - printf("%s: MMC slot %i active\n", __FUNCTION__, level + 1); } static void n8x0_gpio_setup(struct n800_s *s) @@ -428,9 +426,6 @@ struct mipid_s { static void mipid_reset(struct mipid_s *s) { - if (!s->sleep) - fprintf(stderr, "%s: Display off\n", __FUNCTION__); - s->pm = 0; s->cmd = 0; @@ -578,11 +573,9 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len) case 0x28: /* DISPOFF */ s->onoff = 0; - fprintf(stderr, "%s: Display off\n", __FUNCTION__); break; case 0x29: /* DISPON */ s->onoff = 1; - fprintf(stderr, "%s: Display on\n", __FUNCTION__); break; case 0x2a: /* CASET */ @@ -669,7 +662,8 @@ static uint32_t mipid_txrx(void *opaque, uint32_t cmd, int len) default: bad_cmd: - fprintf(stderr, "%s: unknown command %02x\n", __FUNCTION__, s->cmd); + qemu_log_mask(LOG_GUEST_ERROR, + "%s: unknown command %02x\n", __func__, s->cmd); break; } @@ -1347,7 +1341,6 @@ static void n8x0_init(QEMUMachineInitArgs *args, if (option_rom[0].name && (args->boot_device[0] == 'n' || !args->kernel_filename)) { - int rom_size; uint8_t nolo_tags[0x10000]; /* No, wait, better start at the ROM. */ s->mpu->cpu->env.regs[15] = OMAP2_Q2_BASE + 0x400000; @@ -1361,10 +1354,9 @@ static void n8x0_init(QEMUMachineInitArgs *args, * * The code above is for loading the `zImage' file from Nokia * images. */ - rom_size = load_image_targphys(option_rom[0].name, - OMAP2_Q2_BASE + 0x400000, - sdram_size - 0x400000); - printf("%i bytes of image loaded\n", rom_size); + load_image_targphys(option_rom[0].name, + OMAP2_Q2_BASE + 0x400000, + sdram_size - 0x400000); n800_setup_nolo_tags(nolo_tags); cpu_physical_memory_write(OMAP2_SRAM_BASE, nolo_tags, 0x10000); diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c index 7467cca4f7..b7ca511d45 100644 --- a/hw/arm/pxa2xx.c +++ b/hw/arm/pxa2xx.c @@ -1981,9 +1981,11 @@ static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem, memory_region_init_io(&s->iomem, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000); memory_region_add_subregion(sysmem, base, &s->iomem); - if (chr) + if (chr) { + qemu_chr_fe_claim_no_fail(chr); qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty, pxa2xx_fir_rx, pxa2xx_fir_event, s); + } register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save, pxa2xx_fir_load, s); diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c index 6f362865f9..5b9257a9de 100644 --- a/hw/arm/xilinx_zynq.c +++ b/hw/arm/xilinx_zynq.c @@ -86,8 +86,7 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq, spi = (SSIBus *)qdev_get_child_bus(dev, bus_name); for (j = 0; j < num_ss; ++j) { - flash_dev = ssi_create_slave_no_init(spi, "n25q128"); - qdev_init_nofail(flash_dev); + flash_dev = ssi_create_slave(spi, "n25q128"); cs_line = qdev_get_gpio_in(flash_dev, 0); sysbus_connect_irq(busdev, i * num_ss + j + 1, cs_line); diff --git a/hw/arm_gic_common.c b/hw/arm_gic_common.c index f2dc8bf555..71594f1f87 100644 --- a/hw/arm_gic_common.c +++ b/hw/arm_gic_common.c @@ -20,90 +20,65 @@ #include "hw/arm_gic_internal.h" -static void gic_save(QEMUFile *f, void *opaque) +static void gic_pre_save(void *opaque) { GICState *s = (GICState *)opaque; ARMGICCommonClass *c = ARM_GIC_COMMON_GET_CLASS(s); - int i; - int j; if (c->pre_save) { c->pre_save(s); } - - qemu_put_be32(f, s->enabled); - for (i = 0; i < s->num_cpu; i++) { - qemu_put_be32(f, s->cpu_enabled[i]); - for (j = 0; j < GIC_INTERNAL; j++) { - qemu_put_be32(f, s->priority1[j][i]); - } - for (j = 0; j < s->num_irq; j++) { - qemu_put_be32(f, s->last_active[j][i]); - } - qemu_put_be32(f, s->priority_mask[i]); - qemu_put_be32(f, s->running_irq[i]); - qemu_put_be32(f, s->running_priority[i]); - qemu_put_be32(f, s->current_pending[i]); - } - for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) { - qemu_put_be32(f, s->priority2[i]); - } - for (i = 0; i < s->num_irq; i++) { - qemu_put_be32(f, s->irq_target[i]); - qemu_put_byte(f, s->irq_state[i].enabled); - qemu_put_byte(f, s->irq_state[i].pending); - qemu_put_byte(f, s->irq_state[i].active); - qemu_put_byte(f, s->irq_state[i].level); - qemu_put_byte(f, s->irq_state[i].model); - qemu_put_byte(f, s->irq_state[i].trigger); - } } -static int gic_load(QEMUFile *f, void *opaque, int version_id) +static int gic_post_load(void *opaque, int version_id) { GICState *s = (GICState *)opaque; ARMGICCommonClass *c = ARM_GIC_COMMON_GET_CLASS(s); - int i; - int j; - - if (version_id != 3) { - return -EINVAL; - } - - s->enabled = qemu_get_be32(f); - for (i = 0; i < s->num_cpu; i++) { - s->cpu_enabled[i] = qemu_get_be32(f); - for (j = 0; j < GIC_INTERNAL; j++) { - s->priority1[j][i] = qemu_get_be32(f); - } - for (j = 0; j < s->num_irq; j++) { - s->last_active[j][i] = qemu_get_be32(f); - } - s->priority_mask[i] = qemu_get_be32(f); - s->running_irq[i] = qemu_get_be32(f); - s->running_priority[i] = qemu_get_be32(f); - s->current_pending[i] = qemu_get_be32(f); - } - for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) { - s->priority2[i] = qemu_get_be32(f); - } - for (i = 0; i < s->num_irq; i++) { - s->irq_target[i] = qemu_get_be32(f); - s->irq_state[i].enabled = qemu_get_byte(f); - s->irq_state[i].pending = qemu_get_byte(f); - s->irq_state[i].active = qemu_get_byte(f); - s->irq_state[i].level = qemu_get_byte(f); - s->irq_state[i].model = qemu_get_byte(f); - s->irq_state[i].trigger = qemu_get_byte(f); - } if (c->post_load) { c->post_load(s); } - return 0; } +static const VMStateDescription vmstate_gic_irq_state = { + .name = "arm_gic_irq_state", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8(enabled, gic_irq_state), + VMSTATE_UINT8(pending, gic_irq_state), + VMSTATE_UINT8(active, gic_irq_state), + VMSTATE_UINT8(level, gic_irq_state), + VMSTATE_BOOL(model, gic_irq_state), + VMSTATE_BOOL(trigger, gic_irq_state), + VMSTATE_END_OF_LIST() + } +}; + +static const VMStateDescription vmstate_gic = { + .name = "arm_gic", + .version_id = 4, + .minimum_version_id = 4, + .pre_save = gic_pre_save, + .post_load = gic_post_load, + .fields = (VMStateField[]) { + VMSTATE_BOOL(enabled, GICState), + VMSTATE_BOOL_ARRAY(cpu_enabled, GICState, NCPU), + VMSTATE_STRUCT_ARRAY(irq_state, GICState, GIC_MAXIRQ, 1, + vmstate_gic_irq_state, gic_irq_state), + VMSTATE_UINT8_ARRAY(irq_target, GICState, GIC_MAXIRQ), + VMSTATE_UINT8_2DARRAY(priority1, GICState, GIC_INTERNAL, NCPU), + VMSTATE_UINT8_ARRAY(priority2, GICState, GIC_MAXIRQ - GIC_INTERNAL), + VMSTATE_UINT16_2DARRAY(last_active, GICState, GIC_MAXIRQ, NCPU), + VMSTATE_UINT16_ARRAY(priority_mask, GICState, NCPU), + VMSTATE_UINT16_ARRAY(running_irq, GICState, NCPU), + VMSTATE_UINT16_ARRAY(running_priority, GICState, NCPU), + VMSTATE_UINT16_ARRAY(current_pending, GICState, NCPU), + VMSTATE_END_OF_LIST() + } +}; + static void arm_gic_common_realize(DeviceState *dev, Error **errp) { GICState *s = ARM_GIC_COMMON(dev); @@ -131,8 +106,6 @@ static void arm_gic_common_realize(DeviceState *dev, Error **errp) num_irq); return; } - - register_savevm(NULL, "arm_gic", -1, 3, gic_save, gic_load, s); } static void arm_gic_common_reset(DeviceState *dev) @@ -149,7 +122,7 @@ static void arm_gic_common_reset(DeviceState *dev) s->current_pending[i] = 1023; s->running_irq[i] = 1023; s->running_priority[i] = 0x100; - s->cpu_enabled[i] = 0; + s->cpu_enabled[i] = false; } for (i = 0; i < 16; i++) { GIC_SET_ENABLED(i, ALL_CPU_MASK); @@ -161,7 +134,7 @@ static void arm_gic_common_reset(DeviceState *dev) s->irq_target[i] = 1; } } - s->enabled = 0; + s->enabled = false; } static Property arm_gic_common_properties[] = { @@ -182,6 +155,7 @@ static void arm_gic_common_class_init(ObjectClass *klass, void *data) dc->reset = arm_gic_common_reset; dc->realize = arm_gic_common_realize; dc->props = arm_gic_common_properties; + dc->vmsd = &vmstate_gic; dc->no_user = 1; } diff --git a/hw/arm_gic_internal.h b/hw/arm_gic_internal.h index 3e1928b7eb..99a3bc362b 100644 --- a/hw/arm_gic_internal.h +++ b/hw/arm_gic_internal.h @@ -45,14 +45,14 @@ #define GIC_SET_ACTIVE(irq, cm) s->irq_state[irq].active |= (cm) #define GIC_CLEAR_ACTIVE(irq, cm) s->irq_state[irq].active &= ~(cm) #define GIC_TEST_ACTIVE(irq, cm) ((s->irq_state[irq].active & (cm)) != 0) -#define GIC_SET_MODEL(irq) s->irq_state[irq].model = 1 -#define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = 0 +#define GIC_SET_MODEL(irq) s->irq_state[irq].model = true +#define GIC_CLEAR_MODEL(irq) s->irq_state[irq].model = false #define GIC_TEST_MODEL(irq) s->irq_state[irq].model #define GIC_SET_LEVEL(irq, cm) s->irq_state[irq].level = (cm) #define GIC_CLEAR_LEVEL(irq, cm) s->irq_state[irq].level &= ~(cm) #define GIC_TEST_LEVEL(irq, cm) ((s->irq_state[irq].level & (cm)) != 0) -#define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = 1 -#define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = 0 +#define GIC_SET_TRIGGER(irq) s->irq_state[irq].trigger = true +#define GIC_CLEAR_TRIGGER(irq) s->irq_state[irq].trigger = false #define GIC_TEST_TRIGGER(irq) s->irq_state[irq].trigger #define GIC_GET_PRIORITY(irq, cpu) (((irq) < GIC_INTERNAL) ? \ s->priority1[irq][cpu] : \ @@ -61,30 +61,30 @@ typedef struct gic_irq_state { /* The enable bits are only banked for per-cpu interrupts. */ - unsigned enabled:NCPU; - unsigned pending:NCPU; - unsigned active:NCPU; - unsigned level:NCPU; - unsigned model:1; /* 0 = N:N, 1 = 1:N */ - unsigned trigger:1; /* nonzero = edge triggered. */ + uint8_t enabled; + uint8_t pending; + uint8_t active; + uint8_t level; + bool model; /* 0 = N:N, 1 = 1:N */ + bool trigger; /* nonzero = edge triggered. */ } gic_irq_state; typedef struct GICState { SysBusDevice busdev; qemu_irq parent_irq[NCPU]; - int enabled; - int cpu_enabled[NCPU]; + bool enabled; + bool cpu_enabled[NCPU]; gic_irq_state irq_state[GIC_MAXIRQ]; - int irq_target[GIC_MAXIRQ]; - int priority1[GIC_INTERNAL][NCPU]; - int priority2[GIC_MAXIRQ - GIC_INTERNAL]; - int last_active[GIC_MAXIRQ][NCPU]; - - int priority_mask[NCPU]; - int running_irq[NCPU]; - int running_priority[NCPU]; - int current_pending[NCPU]; + uint8_t irq_target[GIC_MAXIRQ]; + uint8_t priority1[GIC_INTERNAL][NCPU]; + uint8_t priority2[GIC_MAXIRQ - GIC_INTERNAL]; + uint16_t last_active[GIC_MAXIRQ][NCPU]; + + uint16_t priority_mask[NCPU]; + uint16_t running_irq[NCPU]; + uint16_t running_priority[NCPU]; + uint16_t current_pending[NCPU]; uint32_t num_cpu; diff --git a/hw/arm_mptimer.c b/hw/arm_mptimer.c index f59a9f11f0..317f5e43ed 100644 --- a/hw/arm_mptimer.c +++ b/hw/arm_mptimer.c @@ -253,14 +253,15 @@ static int arm_mptimer_init(SysBusDevice *dev) static const VMStateDescription vmstate_timerblock = { .name = "arm_mptimer_timerblock", - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .fields = (VMStateField[]) { VMSTATE_UINT32(count, TimerBlock), VMSTATE_UINT32(load, TimerBlock), VMSTATE_UINT32(control, TimerBlock), VMSTATE_UINT32(status, TimerBlock), VMSTATE_INT64(tick, TimerBlock), + VMSTATE_TIMER(timer, TimerBlock), VMSTATE_END_OF_LIST() } }; diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c index d198cfd96e..235120024f 100644 --- a/hw/armv7m_nvic.c +++ b/hw/armv7m_nvic.c @@ -458,10 +458,10 @@ static void armv7m_nvic_reset(DeviceState *dev) * as enabled by default, and with a priority mask which allows * all interrupts through. */ - s->gic.cpu_enabled[0] = 1; + s->gic.cpu_enabled[0] = true; s->gic.priority_mask[0] = 0x100; /* The NVIC as a whole is always enabled. */ - s->gic.enabled = 1; + s->gic.enabled = true; systick_reset(s); } diff --git a/hw/bt-hci-csr.c b/hw/bt-hci-csr.c index e4ada3c731..55c819b085 100644 --- a/hw/bt-hci-csr.c +++ b/hw/bt-hci-csr.c @@ -439,6 +439,7 @@ CharDriverState *uart_hci_init(qemu_irq wakeup) s->chr.opaque = s; s->chr.chr_write = csrhci_write; s->chr.chr_ioctl = csrhci_ioctl; + s->chr.avail_connections = 1; s->hci = qemu_next_hci(); s->hci->opaque = s; diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c index 5426f10018..421ec998d6 100644 --- a/hw/cadence_uart.c +++ b/hw/cadence_uart.c @@ -157,6 +157,7 @@ static void uart_rx_reset(UartState *s) { s->rx_wpos = 0; s->rx_count = 0; + qemu_chr_accept_input(s->chr); s->r[R_SR] |= UART_SR_INTR_REMPTY; s->r[R_SR] &= ~UART_SR_INTR_RFUL; diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c index c151c95c3e..cc95e5c3f0 100644 --- a/hw/i386/kvmvapic.c +++ b/hw/i386/kvmvapic.c @@ -13,8 +13,6 @@ #include "sysemu/kvm.h" #include "hw/apic_internal.h" -#define APIC_DEFAULT_ADDRESS 0xfee00000 - #define VAPIC_IO_PORT 0x7e #define VAPIC_CPU_SHIFT 7 diff --git a/hw/i386/pc.c b/hw/i386/pc.c index b1e06fa0e7..ebbf059225 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -51,6 +51,7 @@ #include "exec/address-spaces.h" #include "sysemu/arch_init.h" #include "qemu/bitmap.h" +#include "qemu/config-file.h" /* debug PC/ISA interrupts */ //#define DEBUG_IRQ @@ -71,6 +72,8 @@ #define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3) #define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4) +#define IO_APIC_DEFAULT_ADDRESS 0xfec00000 + #define E820_NR_ENTRIES 16 struct e820_entry { @@ -888,7 +891,7 @@ void pc_cpus_init(const char *cpu_model) void pc_acpi_init(const char *default_dsdt) { - char *filename = NULL, *arg = NULL; + char *filename; if (acpi_tables != NULL) { /* manually set via -acpitable, leave it alone */ @@ -898,15 +901,26 @@ void pc_acpi_init(const char *default_dsdt) filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, default_dsdt); if (filename == NULL) { fprintf(stderr, "WARNING: failed to find %s\n", default_dsdt); - return; - } + } else { + char *arg; + QemuOpts *opts; + Error *err = NULL; - arg = g_strdup_printf("file=%s", filename); - if (acpi_table_add(arg) != 0) { - fprintf(stderr, "WARNING: failed to load %s\n", filename); + arg = g_strdup_printf("file=%s", filename); + + /* creates a deep copy of "arg" */ + opts = qemu_opts_parse(qemu_find_opts("acpi"), arg, 0); + g_assert(opts != NULL); + + acpi_table_add(opts, &err); + if (err) { + fprintf(stderr, "WARNING: failed to load %s: %s\n", filename, + error_get_pretty(err)); + error_free(err); + } + g_free(arg); + g_free(filename); } - g_free(arg); - g_free(filename); } void *pc_memory_init(MemoryRegion *system_memory, @@ -1158,7 +1172,7 @@ void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name) } qdev_init_nofail(dev); d = SYS_BUS_DEVICE(dev); - sysbus_mmio_map(d, 0, 0xfec00000); + sysbus_mmio_map(d, 0, IO_APIC_DEFAULT_ADDRESS); for (i = 0; i < IOAPIC_NUM_PINS; i++) { gsi_state->ioapic_irq[i] = qdev_get_gpio_in(dev, i); diff --git a/hw/ipoctal232.c b/hw/ipoctal232.c index 1da6a99175..685fee2d2e 100644 --- a/hw/ipoctal232.c +++ b/hw/ipoctal232.c @@ -93,7 +93,6 @@ typedef struct SCC2698Block SCC2698Block; struct SCC2698Channel { IPOctalState *ipoctal; CharDriverState *dev; - char *devpath; bool rx_enabled; uint8_t mr[2]; uint8_t mr_idx; @@ -545,25 +544,12 @@ static int ipoctal_init(IPackDevice *ip) ch->ipoctal = s; /* Redirect IP-Octal channels to host character devices */ - if (ch->devpath) { - const char chr_name[] = "ipoctal"; - char label[ARRAY_SIZE(chr_name) + 2]; - static int index; - - snprintf(label, sizeof(label), "%s%d", chr_name, index); - - ch->dev = qemu_chr_new(label, ch->devpath, NULL); - - if (ch->dev) { - index++; - qemu_chr_add_handlers(ch->dev, hostdev_can_receive, - hostdev_receive, hostdev_event, ch); - DPRINTF("Redirecting channel %u to %s (%s)\n", - i, ch->devpath, label); - } else { - DPRINTF("Could not redirect channel %u to %s\n", - i, ch->devpath); - } + if (ch->dev) { + qemu_chr_add_handlers(ch->dev, hostdev_can_receive, + hostdev_receive, hostdev_event, ch); + DPRINTF("Redirecting channel %u to %s\n", i, ch->dev->label); + } else { + DPRINTF("Could not redirect channel %u, no chardev set\n", i); } } @@ -571,14 +557,14 @@ static int ipoctal_init(IPackDevice *ip) } static Property ipoctal_properties[] = { - DEFINE_PROP_STRING("serial0", IPOctalState, ch[0].devpath), - DEFINE_PROP_STRING("serial1", IPOctalState, ch[1].devpath), - DEFINE_PROP_STRING("serial2", IPOctalState, ch[2].devpath), - DEFINE_PROP_STRING("serial3", IPOctalState, ch[3].devpath), - DEFINE_PROP_STRING("serial4", IPOctalState, ch[4].devpath), - DEFINE_PROP_STRING("serial5", IPOctalState, ch[5].devpath), - DEFINE_PROP_STRING("serial6", IPOctalState, ch[6].devpath), - DEFINE_PROP_STRING("serial7", IPOctalState, ch[7].devpath), + DEFINE_PROP_CHR("chardev0", IPOctalState, ch[0].dev), + DEFINE_PROP_CHR("chardev1", IPOctalState, ch[1].dev), + DEFINE_PROP_CHR("chardev2", IPOctalState, ch[2].dev), + DEFINE_PROP_CHR("chardev3", IPOctalState, ch[3].dev), + DEFINE_PROP_CHR("chardev4", IPOctalState, ch[4].dev), + DEFINE_PROP_CHR("chardev5", IPOctalState, ch[5].dev), + DEFINE_PROP_CHR("chardev6", IPOctalState, ch[6].dev), + DEFINE_PROP_CHR("chardev7", IPOctalState, ch[7].dev), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/ivshmem.c b/hw/ivshmem.c index 68a2cf2e69..af2789e9ac 100644 --- a/hw/ivshmem.c +++ b/hw/ivshmem.c @@ -292,6 +292,7 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, EventNotifier * fprintf(stderr, "creating eventfd for eventfd %d failed\n", eventfd); exit(-1); } + qemu_chr_fe_claim_no_fail(chr); /* if MSI is supported we need multiple interrupts */ if (ivshmem_has_feature(s, IVSHMEM_MSI)) { diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c index aacf0f05ed..e5de801671 100644 --- a/hw/mcf_uart.c +++ b/hw/mcf_uart.c @@ -280,6 +280,7 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr) s->chr = chr; s->irq = irq; if (chr) { + qemu_chr_fe_claim_no_fail(chr); qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive, mcf_uart_event, s); } diff --git a/hw/microblaze/petalogix_ml605_mmu.c b/hw/microblaze/petalogix_ml605_mmu.c index cfc02207ab..07dc808405 100644 --- a/hw/microblaze/petalogix_ml605_mmu.c +++ b/hw/microblaze/petalogix_ml605_mmu.c @@ -158,8 +158,7 @@ petalogix_ml605_init(QEMUMachineInitArgs *args) for (i = 0; i < NUM_SPI_FLASHES; i++) { qemu_irq cs_line; - dev = ssi_create_slave_no_init(spi, "n25q128"); - qdev_init_nofail(dev); + dev = ssi_create_slave(spi, "n25q128"); cs_line = qdev_get_gpio_in(dev, 0); sysbus_connect_irq(busdev, i+1, cs_line); } @@ -297,6 +297,7 @@ static void nand_command(NANDFlashState *s) break; case NAND_CMD_BLOCKERASE2: + s->addr &= (1ull << s->addrlen * 8) - 1; if (nand_flash_ids[s->chip_id].options & NAND_SAMSUNG_LP) s->addr <<= 16; else diff --git a/hw/onenand.c b/hw/onenand.c index ddba366ef5..57a346d7da 100644 --- a/hw/onenand.c +++ b/hw/onenand.c @@ -185,7 +185,8 @@ static const VMStateDescription vmstate_onenand = { VMSTATE_UINT8(ecc.cp, OneNANDState), VMSTATE_UINT16_ARRAY(ecc.lp, OneNANDState, 2), VMSTATE_UINT16(ecc.count, OneNANDState), - VMSTATE_BUFFER_UNSAFE(otp, OneNANDState, 0, ((64 + 2) << PAGE_SHIFT)), + VMSTATE_BUFFER_POINTER_UNSAFE(otp, OneNANDState, 0, + ((64 + 2) << PAGE_SHIFT)), VMSTATE_END_OF_LIST() } }; @@ -109,11 +109,11 @@ void ioapic_init_gsi(GSIState *gsi_state, const char *parent_name); /* acpi.c */ extern int acpi_enabled; -extern char *acpi_tables; +extern char unsigned *acpi_tables; extern size_t acpi_tables_len; void acpi_bios_init(void); -int acpi_table_add(const char *table_desc); +void acpi_table_add(const QemuOpts *opts, Error **errp); /* acpi_piix.c */ diff --git a/hw/pci/pci-hotplug.c b/hw/pci/pci-hotplug.c index f38df30540..180ee07fef 100644 --- a/hw/pci/pci-hotplug.c +++ b/hw/pci/pci-hotplug.c @@ -99,7 +99,7 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter, dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1); dinfo->bus = scsibus->busnr; scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit, - false, -1); + false, -1, NULL); if (!scsidev) { return -1; } diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c index 5d57babe07..646dc794bf 100644 --- a/hw/pflash_cfi01.c +++ b/hw/pflash_cfi01.c @@ -67,8 +67,7 @@ struct pflash_t { uint64_t sector_len; uint8_t width; uint8_t be; - int wcycle; /* if 0, the flash is read normally */ - int bypass; + uint8_t wcycle; /* if 0, the flash is read normally */ int ro; uint8_t cmd; uint8_t status; @@ -78,7 +77,7 @@ struct pflash_t { uint16_t ident3; uint8_t cfi_len; uint8_t cfi_table[0x52]; - hwaddr counter; + uint64_t counter; unsigned int writeblock_size; QEMUTimer *timer; MemoryRegion mem; @@ -86,6 +85,19 @@ struct pflash_t { void *storage; }; +static const VMStateDescription vmstate_pflash = { + .name = "pflash_cfi01", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_UINT8(wcycle, pflash_t), + VMSTATE_UINT8(cmd, pflash_t), + VMSTATE_UINT8(status, pflash_t), + VMSTATE_UINT64(counter, pflash_t), + VMSTATE_END_OF_LIST() + } +}; + static void pflash_timer (void *opaque) { pflash_t *pfl = opaque; @@ -93,12 +105,8 @@ static void pflash_timer (void *opaque) DPRINTF("%s: command %02x done\n", __func__, pfl->cmd); /* Reset flash */ pfl->status ^= 0x80; - if (pfl->bypass) { - pfl->wcycle = 2; - } else { - memory_region_rom_device_set_readable(&pfl->mem, true); - pfl->wcycle = 0; - } + memory_region_rom_device_set_readable(&pfl->mem, true); + pfl->wcycle = 0; pfl->cmd = 0; } @@ -228,7 +236,7 @@ static inline void pflash_data_write(pflash_t *pfl, hwaddr offset, uint8_t *p = pfl->storage; DPRINTF("%s: block write offset " TARGET_FMT_plx - " value %x counter " TARGET_FMT_plx "\n", + " value %x counter %016" PRIx64 "\n", __func__, offset, value, pfl->counter); switch (width) { case 1: @@ -452,7 +460,6 @@ static void pflash_write(pflash_t *pfl, hwaddr offset, reset_flash: memory_region_rom_device_set_readable(&pfl->mem, true); - pfl->bypass = 0; pfl->wcycle = 0; pfl->cmd = 0; } @@ -707,6 +714,7 @@ static void pflash_cfi01_class_init(ObjectClass *klass, void *data) k->init = pflash_cfi01_init; dc->props = pflash_cfi01_properties; + dc->vmsd = &vmstate_pflash; } diff --git a/hw/pl050.c b/hw/pl050.c index bc31ab6885..76735a0eda 100644 --- a/hw/pl050.c +++ b/hw/pl050.c @@ -24,14 +24,13 @@ typedef struct { static const VMStateDescription vmstate_pl050 = { .name = "pl050", - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .fields = (VMStateField[]) { VMSTATE_UINT32(cr, pl050_state), VMSTATE_UINT32(clk, pl050_state), VMSTATE_UINT32(last, pl050_state), VMSTATE_INT32(pending, pl050_state), - VMSTATE_INT32(is_mouse, pl050_state), VMSTATE_END_OF_LIST() } }; diff --git a/hw/pl330.c b/hw/pl330.c index 1a04773a71..60aa4a8f9f 100644 --- a/hw/pl330.c +++ b/hw/pl330.c @@ -870,9 +870,8 @@ static void pl330_dmasev(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len) ch->parent->int_status |= (1 << ev_id); DB_PRINT("event interrupt raised %d\n", ev_id); qemu_irq_raise(ch->parent->irq[ev_id]); - } else { - ch->parent->ev_status |= (1 << ev_id); } + ch->parent->ev_status |= (1 << ev_id); } static void pl330_dmast(PL330Chan *ch, uint8_t opcode, uint8_t *args, int len) diff --git a/hw/qdev-properties-system.c b/hw/qdev-properties-system.c index d9934b5b9c..a22b155b6f 100644 --- a/hw/qdev-properties-system.c +++ b/hw/qdev-properties-system.c @@ -123,11 +123,10 @@ static int parse_chr(DeviceState *dev, const char *str, void **ptr) if (chr == NULL) { return -ENOENT; } - if (chr->avail_connections < 1) { + if (qemu_chr_fe_claim(chr) != 0) { return -EEXIST; } *ptr = chr; - --chr->avail_connections; return 0; } @@ -140,7 +139,7 @@ static void release_chr(Object *obj, const char *name, void *opaque) if (chr) { qemu_chr_add_handlers(chr, NULL, NULL, NULL, NULL); - ++chr->avail_connections; + qemu_chr_fe_release(chr); } } diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c index 08787c2a9b..ac2093a5ef 100644 --- a/hw/scsi-bus.c +++ b/hw/scsi-bus.c @@ -207,7 +207,8 @@ static int scsi_qdev_exit(DeviceState *qdev) /* handle legacy '-drive if=scsi,...' cmd line args */ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, - int unit, bool removable, int bootindex) + int unit, bool removable, int bootindex, + const char *serial) { const char *driver; DeviceState *dev; @@ -221,6 +222,9 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, if (object_property_find(OBJECT(dev), "removable", NULL)) { qdev_prop_set_bit(dev, "removable", removable); } + if (serial) { + qdev_prop_set_string(dev, "serial", serial); + } if (qdev_prop_set_drive(dev, "drive", bdrv) < 0) { qdev_free(dev); return NULL; @@ -243,7 +247,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus) continue; } qemu_opts_loc_restore(dinfo->opts); - if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1)) { + if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1, NULL)) { res = -1; break; } @@ -160,7 +160,8 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d) } SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv, - int unit, bool removable, int bootindex); + int unit, bool removable, int bootindex, + const char *serial); int scsi_bus_legacy_handle_cmdline(SCSIBus *bus); /* @@ -478,7 +478,7 @@ static const VMStateDescription sd_vmstate = { VMSTATE_UINT64(data_start, SDState), VMSTATE_UINT32(data_offset, SDState), VMSTATE_UINT8_ARRAY(data, SDState, 512), - VMSTATE_BUFFER_UNSAFE(buf, SDState, 1, 512), + VMSTATE_BUFFER_POINTER_UNSAFE(buf, SDState, 1, 512), VMSTATE_BOOL(enable, SDState), VMSTATE_END_OF_LIST() } diff --git a/hw/sh_serial.c b/hw/sh_serial.c index 40e797c5a2..462969557c 100644 --- a/hw/sh_serial.c +++ b/hw/sh_serial.c @@ -396,9 +396,11 @@ void sh_serial_init(MemoryRegion *sysmem, s->chr = chr; - if (chr) + if (chr) { + qemu_chr_fe_claim_no_fail(chr); qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1, sh_serial_event, s); + } s->eri = eri_source; s->rxi = rxi_source; diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index d3f01aa2a7..21651b3637 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -625,7 +625,7 @@ static int usb_msd_initfn_storage(USBDevice *dev) usb_desc_init(dev); scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info_storage); scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable, - s->conf.bootindex); + s->conf.bootindex, s->serial); if (!scsi_dev) { return -1; } diff --git a/hw/vt82c686.c b/hw/vt82c686.c index 452950826c..9d9b64eedd 100644 --- a/hw/vt82c686.c +++ b/hw/vt82c686.c @@ -360,7 +360,7 @@ static int vt82c686b_pm_initfn(PCIDevice *dev) acpi_pm_tmr_init(&s->ar, pm_tmr_timer, &s->io); acpi_pm1_evt_init(&s->ar, pm_tmr_timer, &s->io); - acpi_pm1_cnt_init(&s->ar, &s->io); + acpi_pm1_cnt_init(&s->ar, &s->io, 2); return 0; } diff --git a/hw/xen_backend.c b/hw/xen_backend.c index 24381b55e5..02693d7565 100644 --- a/hw/xen_backend.c +++ b/hw/xen_backend.c @@ -85,12 +85,20 @@ char *xenstore_read_str(const char *base, const char *node) int xenstore_write_int(const char *base, const char *node, int ival) { - char val[32]; + char val[12]; snprintf(val, sizeof(val), "%d", ival); return xenstore_write_str(base, node, val); } +int xenstore_write_int64(const char *base, const char *node, int64_t ival) +{ + char val[21]; + + snprintf(val, sizeof(val), "%"PRId64, ival); + return xenstore_write_str(base, node, val); +} + int xenstore_read_int(const char *base, const char *node, int *ival) { char *val; @@ -114,6 +122,11 @@ int xenstore_write_be_int(struct XenDevice *xendev, const char *node, int ival) return xenstore_write_int(xendev->be, node, ival); } +int xenstore_write_be_int64(struct XenDevice *xendev, const char *node, int64_t ival) +{ + return xenstore_write_int64(xendev->be, node, ival); +} + char *xenstore_read_be_str(struct XenDevice *xendev, const char *node) { return xenstore_read_str(xendev->be, node); diff --git a/hw/xen_backend.h b/hw/xen_backend.h index 6d5c699c51..d04b985d10 100644 --- a/hw/xen_backend.h +++ b/hw/xen_backend.h @@ -63,11 +63,13 @@ extern const char *xen_protocol; /* xenstore helper functions */ int xenstore_write_str(const char *base, const char *node, const char *val); int xenstore_write_int(const char *base, const char *node, int ival); +int xenstore_write_int64(const char *base, const char *node, int64_t ival); char *xenstore_read_str(const char *base, const char *node); int xenstore_read_int(const char *base, const char *node, int *ival); int xenstore_write_be_str(struct XenDevice *xendev, const char *node, const char *val); int xenstore_write_be_int(struct XenDevice *xendev, const char *node, int ival); +int xenstore_write_be_int64(struct XenDevice *xendev, const char *node, int64_t ival); char *xenstore_read_be_str(struct XenDevice *xendev, const char *node); int xenstore_read_be_int(struct XenDevice *xendev, const char *node, int *ival); char *xenstore_read_fe_str(struct XenDevice *xendev, const char *node); diff --git a/hw/xen_console.c b/hw/xen_console.c index a8db6f8d8f..c56ef4737f 100644 --- a/hw/xen_console.c +++ b/hw/xen_console.c @@ -241,9 +241,17 @@ static int con_initialise(struct XenDevice *xendev) return -1; xen_be_bind_evtchn(&con->xendev); - if (con->chr) - qemu_chr_add_handlers(con->chr, xencons_can_receive, xencons_receive, - NULL, con); + if (con->chr) { + if (qemu_chr_fe_claim(con->chr) == 0) { + qemu_chr_add_handlers(con->chr, xencons_can_receive, + xencons_receive, NULL, con); + } else { + xen_be_printf(xendev, 0, + "xen_console_init error chardev %s already used\n", + con->chr->label); + con->chr = NULL; + } + } xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n", con->ring_ref, @@ -260,8 +268,10 @@ static void con_disconnect(struct XenDevice *xendev) if (!xendev->dev) { return; } - if (con->chr) + if (con->chr) { qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL); + qemu_chr_fe_release(con->chr); + } xen_be_unbind_evtchn(&con->xendev); if (con->sring) { diff --git a/hw/xen_disk.c b/hw/xen_disk.c index 83329e2e69..47a51cf014 100644 --- a/hw/xen_disk.c +++ b/hw/xen_disk.c @@ -700,7 +700,7 @@ static void blk_alloc(struct XenDevice *xendev) static int blk_init(struct XenDevice *xendev) { struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); - int index, qflags, info = 0; + int info = 0; /* read xenstore entries */ if (blkdev->params == NULL) { @@ -743,10 +743,7 @@ static int blk_init(struct XenDevice *xendev) } /* read-only ? */ - qflags = BDRV_O_NOCACHE | BDRV_O_CACHE_WB | BDRV_O_NATIVE_AIO; - if (strcmp(blkdev->mode, "w") == 0) { - qflags |= BDRV_O_RDWR; - } else { + if (strcmp(blkdev->mode, "w")) { info |= VDISK_READONLY; } @@ -755,6 +752,41 @@ static int blk_init(struct XenDevice *xendev) info |= VDISK_CDROM; } + blkdev->file_blk = BLOCK_SIZE; + + /* fill info + * blk_connect supplies sector-size and sectors + */ + xenstore_write_be_int(&blkdev->xendev, "feature-flush-cache", 1); + xenstore_write_be_int(&blkdev->xendev, "feature-persistent", 1); + xenstore_write_be_int(&blkdev->xendev, "info", info); + return 0; + +out_error: + g_free(blkdev->params); + blkdev->params = NULL; + g_free(blkdev->mode); + blkdev->mode = NULL; + g_free(blkdev->type); + blkdev->type = NULL; + g_free(blkdev->dev); + blkdev->dev = NULL; + g_free(blkdev->devtype); + blkdev->devtype = NULL; + return -1; +} + +static int blk_connect(struct XenDevice *xendev) +{ + struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); + int pers, index, qflags; + + /* read-only ? */ + qflags = BDRV_O_CACHE_WB | BDRV_O_NATIVE_AIO; + if (strcmp(blkdev->mode, "w") == 0) { + qflags |= BDRV_O_RDWR; + } + /* init qemu block driver */ index = (blkdev->xendev.dev - 202 * 256) / 16; blkdev->dinfo = drive_get(IF_XEN, 0, index); @@ -770,7 +802,7 @@ static int blk_init(struct XenDevice *xendev) } } if (!blkdev->bs) { - goto out_error; + return -1; } } else { /* setup via qemu cmdline -> already setup for us */ @@ -778,7 +810,6 @@ static int blk_init(struct XenDevice *xendev) blkdev->bs = blkdev->dinfo->bdrv; } bdrv_attach_dev_nofail(blkdev->bs, blkdev); - blkdev->file_blk = BLOCK_SIZE; blkdev->file_size = bdrv_getlength(blkdev->bs); if (blkdev->file_size < 0) { xen_be_printf(&blkdev->xendev, 1, "bdrv_getlength: %d (%s) | drv %s\n", @@ -792,33 +823,10 @@ static int blk_init(struct XenDevice *xendev) blkdev->type, blkdev->fileproto, blkdev->filename, blkdev->file_size, blkdev->file_size >> 20); - /* fill info */ - xenstore_write_be_int(&blkdev->xendev, "feature-flush-cache", 1); - xenstore_write_be_int(&blkdev->xendev, "feature-persistent", 1); - xenstore_write_be_int(&blkdev->xendev, "info", info); - xenstore_write_be_int(&blkdev->xendev, "sector-size", blkdev->file_blk); - xenstore_write_be_int(&blkdev->xendev, "sectors", - blkdev->file_size / blkdev->file_blk); - return 0; - -out_error: - g_free(blkdev->params); - blkdev->params = NULL; - g_free(blkdev->mode); - blkdev->mode = NULL; - g_free(blkdev->type); - blkdev->type = NULL; - g_free(blkdev->dev); - blkdev->dev = NULL; - g_free(blkdev->devtype); - blkdev->devtype = NULL; - return -1; -} - -static int blk_connect(struct XenDevice *xendev) -{ - struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); - int pers; + /* Fill in number of sector size and number of sectors */ + xenstore_write_be_int(&blkdev->xendev, "sector-size", blkdev->file_blk); + xenstore_write_be_int64(&blkdev->xendev, "sectors", + blkdev->file_size / blkdev->file_blk); if (xenstore_read_fe_int(&blkdev->xendev, "ring-ref", &blkdev->ring_ref) == -1) { return -1; diff --git a/hw/xilinx_axienet.c b/hw/xilinx_axienet.c index 5785290224..07c4badd98 100644 --- a/hw/xilinx_axienet.c +++ b/hw/xilinx_axienet.c @@ -516,6 +516,8 @@ static void enet_write(void *opaque, hwaddr addr, s->rcw[addr & 1] = value; if ((addr & 1) && value & RCW1_RST) { axienet_rx_reset(s); + } else { + qemu_flush_queued_packets(qemu_get_queue(s->nic)); } break; |