summary refs log tree commit diff stats
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/char/spapr_vty.c11
-rw-r--r--hw/core/qdev-properties-system.c8
-rw-r--r--hw/core/qdev-properties.c14
-rw-r--r--hw/ide/atapi.c51
-rw-r--r--hw/net/virtio-net.c4
-rw-r--r--hw/ppc/pnv.c16
-rw-r--r--hw/ppc/pnv_core.c1
-rw-r--r--hw/ppc/pnv_lpc.c3
-rw-r--r--hw/ppc/pnv_xscom.c10
-rw-r--r--hw/ppc/spapr_pci.c18
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),