diff options
Diffstat (limited to 'hw')
| -rw-r--r-- | hw/char/spapr_vty.c | 11 | ||||
| -rw-r--r-- | hw/core/qdev-properties-system.c | 8 | ||||
| -rw-r--r-- | hw/core/qdev-properties.c | 14 | ||||
| -rw-r--r-- | hw/ide/atapi.c | 51 | ||||
| -rw-r--r-- | hw/net/virtio-net.c | 4 | ||||
| -rw-r--r-- | hw/ppc/pnv.c | 16 | ||||
| -rw-r--r-- | hw/ppc/pnv_core.c | 1 | ||||
| -rw-r--r-- | hw/ppc/pnv_lpc.c | 3 | ||||
| -rw-r--r-- | hw/ppc/pnv_xscom.c | 10 | ||||
| -rw-r--r-- | hw/ppc/spapr_pci.c | 18 |
10 files changed, 95 insertions, 41 deletions
diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c index 31822fed9a..06b9b3917f 100644 --- a/hw/char/spapr_vty.c +++ b/hw/char/spapr_vty.c @@ -1,4 +1,5 @@ #include "qemu/osdep.h" +#include "qemu/error-report.h" #include "qapi/error.h" #include "qemu-common.h" #include "cpu.h" @@ -37,7 +38,15 @@ static void vty_receive(void *opaque, const uint8_t *buf, int size) qemu_irq_pulse(spapr_vio_qirq(&dev->sdev)); } for (i = 0; i < size; i++) { - assert((dev->in - dev->out) < VTERM_BUFSIZE); + if (dev->in - dev->out >= VTERM_BUFSIZE) { + static bool reported; + if (!reported) { + error_report("VTY input buffer exhausted - characters dropped." + " (input size = %i)", size); + reported = true; + } + break; + } dev->buf[dev->in++ % VTERM_BUFSIZE] = buf[i]; } } diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index c35f0f59d6..1b7ea50e9f 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -200,18 +200,14 @@ static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque, } s = qemu_chr_find(str); - g_free(str); if (s == NULL) { error_setg(errp, "Property '%s.%s' can't find value '%s'", object_get_typename(obj), prop->name, str); - return; - } - - if (!qemu_chr_fe_init(be, s, errp)) { + } else if (!qemu_chr_fe_init(be, s, errp)) { error_prepend(errp, "Property '%s.%s' can't take value '%s': ", object_get_typename(obj), prop->name, str); - return; } + g_free(str); } static void release_chr(Object *obj, const char *name, void *opaque) diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index 311af6da76..2a82768067 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -705,13 +705,19 @@ static void get_pci_host_devaddr(Object *obj, Visitor *v, const char *name, DeviceState *dev = DEVICE(obj); Property *prop = opaque; PCIHostDeviceAddress *addr = qdev_get_prop_ptr(dev, prop); - char buffer[] = "xxxx:xx:xx.x"; + char buffer[] = "ffff:ff:ff.f"; char *p = buffer; int rc = 0; - rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%d", - addr->domain, addr->bus, addr->slot, addr->function); - assert(rc == sizeof(buffer) - 1); + /* + * Catch "invalid" device reference from vfio-pci and allow the + * default buffer representing the non-existant device to be used. + */ + if (~addr->domain || ~addr->bus || ~addr->slot || ~addr->function) { + rc = snprintf(buffer, sizeof(buffer), "%04x:%02x:%02x.%0d", + addr->domain, addr->bus, addr->slot, addr->function); + assert(rc == sizeof(buffer) - 1); + } visit_type_str(v, name, &p, errp); } diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c index 6189675036..fc1d19c6d4 100644 --- a/hw/ide/atapi.c +++ b/hw/ide/atapi.c @@ -637,6 +637,23 @@ static unsigned int event_status_media(IDEState *s, return 8; /* We wrote to 4 extra bytes from the header */ } +/* + * Before transferring data or otherwise signalling acceptance of a command + * marked CONDDATA, we must check the validity of the byte_count_limit. + */ +static bool validate_bcl(IDEState *s) +{ + /* TODO: Check IDENTIFY data word 125 for defacult BCL (currently 0) */ + if (s->atapi_dma || atapi_byte_count_limit(s)) { + return true; + } + + /* TODO: Move abort back into core.c and introduce proper error flow between + * ATAPI layer and IDE core layer */ + ide_abort_command(s); + return false; +} + static void cmd_get_event_status_notification(IDEState *s, uint8_t *buf) { @@ -1028,12 +1045,19 @@ static void cmd_read_cd(IDEState *s, uint8_t* buf) return; } - transfer_request = buf[9]; - switch(transfer_request & 0xf8) { - case 0x00: + transfer_request = buf[9] & 0xf8; + if (transfer_request == 0x00) { /* nothing */ ide_atapi_cmd_ok(s); - break; + return; + } + + /* Check validity of BCL before transferring data */ + if (!validate_bcl(s)) { + return; + } + + switch (transfer_request) { case 0x10: /* normal read */ ide_atapi_cmd_read(s, lba, nb_sectors, 2048); @@ -1266,6 +1290,14 @@ enum { * See ATA8-ACS3 "7.21.5 Byte Count Limit" */ NONDATA = 0x04, + + /* + * CONDDATA implies a command that transfers data only conditionally based + * on the presence of suboptions. It should be exempt from the BCL check at + * command validation time, but it needs to be checked at the command + * handler level instead. + */ + CONDDATA = 0x08, }; static const struct AtapiCmd { @@ -1289,7 +1321,7 @@ static const struct AtapiCmd { [ 0xad ] = { cmd_read_dvd_structure, CHECK_READY }, [ 0xbb ] = { cmd_set_speed, NONDATA }, [ 0xbd ] = { cmd_mechanism_status, 0 }, - [ 0xbe ] = { cmd_read_cd, CHECK_READY }, + [ 0xbe ] = { cmd_read_cd, CHECK_READY | CONDDATA }, /* [1] handler detects and reports not ready condition itself */ }; @@ -1348,15 +1380,12 @@ void ide_atapi_cmd(IDEState *s) return; } - /* Nondata commands permit the byte_count_limit to be 0. + /* Commands that don't transfer DATA permit the byte_count_limit to be 0. * If this is a data-transferring PIO command and BCL is 0, * we abort at the /ATA/ level, not the ATAPI level. * See ATA8 ACS3 section 7.17.6.49 and 7.21.5 */ - if (cmd->handler && !(cmd->flags & NONDATA)) { - /* TODO: Check IDENTIFY data word 125 for default BCL (currently 0) */ - if (!(atapi_byte_count_limit(s) || s->atapi_dma)) { - /* TODO: Move abort back into core.c and make static inline again */ - ide_abort_command(s); + if (cmd->handler && !(cmd->flags & (NONDATA | CONDDATA))) { + if (!validate_bcl(s)) { return; } } diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index b68c69d8f6..5009533cfa 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -508,6 +508,10 @@ static void virtio_net_set_queues(VirtIONet *n) int i; int r; + if (n->nic->peer_deleted) { + return; + } + for (i = 0; i < n->max_queues; i++) { if (i < n->curr_queues) { r = peer_attach(n, i); diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 82276e0857..9df7b25315 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -110,7 +110,7 @@ static void powernv_create_core_node(PnvChip *chip, PnvCore *pc, void *fdt) CPUState *cs = CPU(DEVICE(pc->threads)); DeviceClass *dc = DEVICE_GET_CLASS(cs); PowerPCCPU *cpu = POWERPC_CPU(cs); - int smt_threads = ppc_get_compat_smt_threads(cpu); + int smt_threads = CPU_CORE(pc)->nr_threads; CPUPPCState *env = &cpu->env; PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); uint32_t servers_prop[smt_threads]; @@ -206,10 +206,6 @@ static void powernv_create_core_node(PnvChip *chip, PnvCore *pc, void *fdt) _FDT((fdt_setprop(fdt, offset, "ibm,pa-features", pa_features, sizeof(pa_features)))); - if (cpu->cpu_version) { - _FDT((fdt_setprop_cell(fdt, offset, "cpu-version", cpu->cpu_version))); - } - /* Build interrupt servers properties */ for (i = 0; i < smt_threads; i++) { servers_prop[i] = cpu_to_be32(pc->pir + i); @@ -525,6 +521,7 @@ static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data) k->cores_mask = POWER8E_CORE_MASK; k->core_pir = pnv_chip_core_pir_p8; k->xscom_base = 0x003fc0000000000ull; + k->xscom_core_base = 0x10000000ull; dc->desc = "PowerNV Chip POWER8E"; } @@ -546,6 +543,7 @@ static void pnv_chip_power8_class_init(ObjectClass *klass, void *data) k->cores_mask = POWER8_CORE_MASK; k->core_pir = pnv_chip_core_pir_p8; k->xscom_base = 0x003fc0000000000ull; + k->xscom_core_base = 0x10000000ull; dc->desc = "PowerNV Chip POWER8"; } @@ -567,6 +565,7 @@ static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data) k->cores_mask = POWER8_CORE_MASK; k->core_pir = pnv_chip_core_pir_p8; k->xscom_base = 0x003fc0000000000ull; + k->xscom_core_base = 0x10000000ull; dc->desc = "PowerNV Chip POWER8NVL"; } @@ -588,6 +587,7 @@ static void pnv_chip_power9_class_init(ObjectClass *klass, void *data) k->cores_mask = POWER9_CORE_MASK; k->core_pir = pnv_chip_core_pir_p9; k->xscom_base = 0x00603fc00000000ull; + k->xscom_core_base = 0x0ull; dc->desc = "PowerNV Chip POWER9"; } @@ -620,7 +620,7 @@ static void pnv_chip_core_sanitize(PnvChip *chip, Error **errp) chip->cores_mask &= pcc->cores_mask; /* now that we have a sane layout, let check the number of cores */ - cores_max = hweight_long(chip->cores_mask); + cores_max = ctpop64(chip->cores_mask); if (chip->nr_cores > cores_max) { error_setg(errp, "warning: too many cores for chip ! Limit is %d", cores_max); @@ -695,7 +695,9 @@ static void pnv_chip_realize(DeviceState *dev, Error **errp) object_unref(OBJECT(pnv_core)); /* Each core has an XSCOM MMIO region */ - pnv_xscom_add_subregion(chip, PNV_XSCOM_EX_CORE_BASE(core_hwid), + pnv_xscom_add_subregion(chip, + PNV_XSCOM_EX_CORE_BASE(pcc->xscom_core_base, + core_hwid), &PNV_CORE(pnv_core)->xscom_regs); i++; } diff --git a/hw/ppc/pnv_core.c b/hw/ppc/pnv_core.c index 2acda9637d..76ce854b0c 100644 --- a/hw/ppc/pnv_core.c +++ b/hw/ppc/pnv_core.c @@ -24,6 +24,7 @@ #include "hw/ppc/ppc.h" #include "hw/ppc/pnv.h" #include "hw/ppc/pnv_core.h" +#include "hw/ppc/pnv_xscom.h" static void powernv_cpu_reset(void *opaque) { diff --git a/hw/ppc/pnv_lpc.c b/hw/ppc/pnv_lpc.c index 00dbd8b07b..0e2117f0f5 100644 --- a/hw/ppc/pnv_lpc.c +++ b/hw/ppc/pnv_lpc.c @@ -23,8 +23,9 @@ #include "qapi/error.h" #include "qemu/log.h" -#include "hw/ppc/pnv_lpc.h" #include "hw/ppc/pnv.h" +#include "hw/ppc/pnv_lpc.h" +#include "hw/ppc/pnv_xscom.h" #include "hw/ppc/fdt.h" #include <libfdt.h> diff --git a/hw/ppc/pnv_xscom.c b/hw/ppc/pnv_xscom.c index 5aaa264bd7..8da271872f 100644 --- a/hw/ppc/pnv_xscom.c +++ b/hw/ppc/pnv_xscom.c @@ -25,8 +25,8 @@ #include "hw/sysbus.h" #include "hw/ppc/fdt.h" -#include "hw/ppc/pnv_xscom.h" #include "hw/ppc/pnv.h" +#include "hw/ppc/pnv_xscom.h" #include <libfdt.h> @@ -124,8 +124,8 @@ static uint64_t xscom_read(void *opaque, hwaddr addr, unsigned width) goto complete; } - val = address_space_ldq(&chip->xscom_as, pcba << 3, MEMTXATTRS_UNSPECIFIED, - &result); + val = address_space_ldq(&chip->xscom_as, (uint64_t) pcba << 3, + MEMTXATTRS_UNSPECIFIED, &result); if (result != MEMTX_OK) { qemu_log_mask(LOG_GUEST_ERROR, "XSCOM read failed at @0x%" HWADDR_PRIx " pcba=0x%08x\n", addr, pcba); @@ -150,8 +150,8 @@ static void xscom_write(void *opaque, hwaddr addr, uint64_t val, goto complete; } - address_space_stq(&chip->xscom_as, pcba << 3, val, MEMTXATTRS_UNSPECIFIED, - &result); + address_space_stq(&chip->xscom_as, (uint64_t) pcba << 3, val, + MEMTXATTRS_UNSPECIFIED, &result); if (result != MEMTX_OK) { qemu_log_mask(LOG_GUEST_ERROR, "XSCOM write failed at @0x%" HWADDR_PRIx " pcba=0x%08x data=0x%" PRIx64 "\n", diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 7cde30ee09..f9661b7d1a 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1658,19 +1658,25 @@ static int spapr_pci_post_load(void *opaque, int version_id) return 0; } +static bool version_before_3(void *opaque, int version_id) +{ + return version_id < 3; +} + static const VMStateDescription vmstate_spapr_pci = { .name = "spapr_pci", - .version_id = 2, + .version_id = 3, .minimum_version_id = 2, .pre_save = spapr_pci_pre_save, .post_load = spapr_pci_post_load, .fields = (VMStateField[]) { VMSTATE_UINT64_EQUAL(buid, sPAPRPHBState), - VMSTATE_UINT32_EQUAL(dma_liobn[0], sPAPRPHBState), - VMSTATE_UINT64_EQUAL(mem_win_addr, sPAPRPHBState), - VMSTATE_UINT64_EQUAL(mem_win_size, sPAPRPHBState), - VMSTATE_UINT64_EQUAL(io_win_addr, sPAPRPHBState), - VMSTATE_UINT64_EQUAL(io_win_size, sPAPRPHBState), + VMSTATE_UNUSED_TEST(version_before_3, + sizeof(uint32_t) /* dma_liobn[0] */ + + sizeof(uint64_t) /* mem_win_addr */ + + sizeof(uint64_t) /* mem_win_size */ + + sizeof(uint64_t) /* io_win_addr */ + + sizeof(uint64_t) /* io_win_size */), VMSTATE_STRUCT_ARRAY(lsi_table, sPAPRPHBState, PCI_NUM_PINS, 0, vmstate_spapr_pci_lsi, struct spapr_pci_lsi), VMSTATE_INT32(msi_devs_num, sPAPRPHBState), |