aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2017-08-23 09:04:20 +0100
committerPeter Maydell <peter.maydell@linaro.org>2017-08-23 09:04:20 +0100
commit56d7305db6d7c9b98c2bb44c53e67f1ec8336daa (patch)
treeead34d859da5143adb967e6a8b8aeefcfc510735 /hw
parent1f296733876434118fd766cfef5eb6f29ecab6a8 (diff)
parent1f98e55385d11da1dc0de6440e66f19d191d2a1b (diff)
downloadqemu-56d7305db6d7c9b98c2bb44c53e67f1ec8336daa.zip
qemu-56d7305db6d7c9b98c2bb44c53e67f1ec8336daa.tar.gz
qemu-56d7305db6d7c9b98c2bb44c53e67f1ec8336daa.tar.bz2
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.10-20170823' into staging
ppc patch queue 2017-08-23 This is identical to the pull request from yesterday (20180822), except that a bug in one patch is fixed so that it doesn't break TCG on a ppc host. Last minute ppc related fixes for qemu-2.10. I'm not sure if these are critical enough to prompt another rc, but I'm submitting them for consideration. First, is Cornelia's fix for 480bc11e6 which meant "make check" would always fail on a ppc host. Tracking that down delayed submission of the rest of these patches, sorry. The rest are all fairly important bugfixes for qemu crashes or guest behaviour regression on ppc. Patches 2-4 specifically are fixes for regressions from qemu-2.9, caused by the compatibility mode and hotplug handling cleanups for the pseries machine type. # gpg: Signature made Wed 23 Aug 2017 01:31:47 BST # gpg: using RSA key 0x6C38CACA20D9B392 # gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>" # gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>" # gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>" # gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>" # Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392 * remotes/dgibson/tags/ppc-for-2.10-20170823: hw/ppc/spapr_iommu: Fix crash when removing the "spapr-tce-table" device hw/ppc/spapr_rtc: Mark the RTC device with user_creatable = false hw/ppc/spapr: Fix segfault when instantiating a 'pc-dimm' without 'memdev' spapr: Allow configure-connector to be called multiple times ppc: fix ppc_set_compat() with KVM PR target/ppc: 'PVR != host PVR' in KVM_SET_SREGS workaround boot-serial-test: prefer tcg accelerator Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/i386/pc.c14
-rw-r--r--hw/mem/nvdimm.c2
-rw-r--r--hw/mem/pc-dimm.c14
-rw-r--r--hw/ppc/spapr.c42
-rw-r--r--hw/ppc/spapr_drc.c30
-rw-r--r--hw/ppc/spapr_iommu.c2
-rw-r--r--hw/ppc/spapr_rtc.c2
7 files changed, 81 insertions, 25 deletions
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 5943539..2108104 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1691,10 +1691,15 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev,
PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
PCDIMMDevice *dimm = PC_DIMM(dev);
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
- MemoryRegion *mr = ddc->get_memory_region(dimm);
+ MemoryRegion *mr;
uint64_t align = TARGET_PAGE_SIZE;
bool is_nvdimm = object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM);
+ mr = ddc->get_memory_region(dimm, &local_err);
+ if (local_err) {
+ goto out;
+ }
+
if (memory_region_get_alignment(mr) && pcmc->enforce_aligned_dimm) {
align = memory_region_get_alignment(mr);
}
@@ -1758,10 +1763,15 @@ static void pc_dimm_unplug(HotplugHandler *hotplug_dev,
PCMachineState *pcms = PC_MACHINE(hotplug_dev);
PCDIMMDevice *dimm = PC_DIMM(dev);
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
- MemoryRegion *mr = ddc->get_memory_region(dimm);
+ MemoryRegion *mr;
HotplugHandlerClass *hhc;
Error *local_err = NULL;
+ mr = ddc->get_memory_region(dimm, &local_err);
+ if (local_err) {
+ goto out;
+ }
+
hhc = HOTPLUG_HANDLER_GET_CLASS(pcms->acpi_dev);
hhc->unplug(HOTPLUG_HANDLER(pcms->acpi_dev), dev, &local_err);
diff --git a/hw/mem/nvdimm.c b/hw/mem/nvdimm.c
index db896b0..952fce5 100644
--- a/hw/mem/nvdimm.c
+++ b/hw/mem/nvdimm.c
@@ -71,7 +71,7 @@ static void nvdimm_init(Object *obj)
NULL, NULL);
}
-static MemoryRegion *nvdimm_get_memory_region(PCDIMMDevice *dimm)
+static MemoryRegion *nvdimm_get_memory_region(PCDIMMDevice *dimm, Error **errp)
{
NVDIMMDevice *nvdimm = NVDIMM(dimm);
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index ea67b46..bdf6649 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -363,7 +363,10 @@ static void pc_dimm_get_size(Object *obj, Visitor *v, const char *name,
PCDIMMDevice *dimm = PC_DIMM(obj);
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(obj);
- mr = ddc->get_memory_region(dimm);
+ mr = ddc->get_memory_region(dimm, errp);
+ if (!mr) {
+ return;
+ }
value = memory_region_size(mr);
visit_type_uint64(v, name, &value, errp);
@@ -411,9 +414,14 @@ static void pc_dimm_unrealize(DeviceState *dev, Error **errp)
host_memory_backend_set_mapped(dimm->hostmem, false);
}
-static MemoryRegion *pc_dimm_get_memory_region(PCDIMMDevice *dimm)
+static MemoryRegion *pc_dimm_get_memory_region(PCDIMMDevice *dimm, Error **errp)
{
- return host_memory_backend_get_memory(dimm->hostmem, &error_abort);
+ if (!dimm->hostmem) {
+ error_setg(errp, "'" PC_DIMM_MEMDEV_PROP "' property must be set");
+ return NULL;
+ }
+
+ return host_memory_backend_get_memory(dimm->hostmem, errp);
}
static MemoryRegion *pc_dimm_get_vmstate_memory_region(PCDIMMDevice *dimm)
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index f7a1972..cec441c 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2772,10 +2772,15 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
sPAPRMachineState *ms = SPAPR_MACHINE(hotplug_dev);
PCDIMMDevice *dimm = PC_DIMM(dev);
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
- MemoryRegion *mr = ddc->get_memory_region(dimm);
- uint64_t align = memory_region_get_alignment(mr);
- uint64_t size = memory_region_size(mr);
- uint64_t addr;
+ MemoryRegion *mr;
+ uint64_t align, size, addr;
+
+ mr = ddc->get_memory_region(dimm, &local_err);
+ if (local_err) {
+ goto out;
+ }
+ align = memory_region_get_alignment(mr);
+ size = memory_region_size(mr);
pc_dimm_memory_plug(dev, &ms->hotplug_memory, mr, align, &local_err);
if (local_err) {
@@ -2808,10 +2813,16 @@ static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
{
PCDIMMDevice *dimm = PC_DIMM(dev);
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
- MemoryRegion *mr = ddc->get_memory_region(dimm);
- uint64_t size = memory_region_size(mr);
+ MemoryRegion *mr;
+ uint64_t size;
char *mem_dev;
+ mr = ddc->get_memory_region(dimm, errp);
+ if (!mr) {
+ return;
+ }
+ size = memory_region_size(mr);
+
if (size % SPAPR_MEMORY_BLOCK_SIZE) {
error_setg(errp, "Hotplugged memory size must be a multiple of "
"%lld MB", SPAPR_MEMORY_BLOCK_SIZE / M_BYTE);
@@ -2882,7 +2893,7 @@ static sPAPRDIMMState *spapr_recover_pending_dimm_state(sPAPRMachineState *ms,
{
sPAPRDRConnector *drc;
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
- MemoryRegion *mr = ddc->get_memory_region(dimm);
+ MemoryRegion *mr = ddc->get_memory_region(dimm, &error_abort);
uint64_t size = memory_region_size(mr);
uint32_t nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE;
uint32_t avail_lmbs = 0;
@@ -2912,7 +2923,7 @@ void spapr_lmb_release(DeviceState *dev)
sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_hotplug_handler(dev));
PCDIMMDevice *dimm = PC_DIMM(dev);
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
- MemoryRegion *mr = ddc->get_memory_region(dimm);
+ MemoryRegion *mr = ddc->get_memory_region(dimm, &error_abort);
sPAPRDIMMState *ds = spapr_pending_dimm_unplugs_find(spapr, PC_DIMM(dev));
/* This information will get lost if a migration occurs
@@ -2945,12 +2956,19 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev,
Error *local_err = NULL;
PCDIMMDevice *dimm = PC_DIMM(dev);
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
- MemoryRegion *mr = ddc->get_memory_region(dimm);
- uint64_t size = memory_region_size(mr);
- uint32_t nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE;
- uint64_t addr_start, addr;
+ MemoryRegion *mr;
+ uint32_t nr_lmbs;
+ uint64_t size, addr_start, addr;
int i;
sPAPRDRConnector *drc;
+
+ mr = ddc->get_memory_region(dimm, &local_err);
+ if (local_err) {
+ goto out;
+ }
+ size = memory_region_size(mr);
+ nr_lmbs = size / SPAPR_MEMORY_BLOCK_SIZE;
+
addr_start = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP,
&local_err);
if (local_err) {
diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c
index 5260b5d..605697d 100644
--- a/hw/ppc/spapr_drc.c
+++ b/hw/ppc/spapr_drc.c
@@ -442,12 +442,17 @@ void spapr_drc_reset(sPAPRDRConnector *drc)
if (drc->dev) {
/* A device present at reset is ready to go, same as coldplugged */
drc->state = drck->ready_state;
+ /*
+ * Ensure that we are able to send the FDT fragment again
+ * via configure-connector call if the guest requests.
+ */
+ drc->ccs_offset = drc->fdt_start_offset;
+ drc->ccs_depth = 0;
} else {
drc->state = drck->empty_state;
+ drc->ccs_offset = -1;
+ drc->ccs_depth = -1;
}
-
- drc->ccs_offset = -1;
- drc->ccs_depth = -1;
}
static void drc_reset(void *opaque)
@@ -1071,8 +1076,14 @@ static void rtas_ibm_configure_connector(PowerPCCPU *cpu,
}
if ((drc->state != SPAPR_DRC_STATE_LOGICAL_UNISOLATE)
- && (drc->state != SPAPR_DRC_STATE_PHYSICAL_UNISOLATE)) {
- /* Need to unisolate the device before configuring */
+ && (drc->state != SPAPR_DRC_STATE_PHYSICAL_UNISOLATE)
+ && (drc->state != SPAPR_DRC_STATE_LOGICAL_CONFIGURED)
+ && (drc->state != SPAPR_DRC_STATE_PHYSICAL_CONFIGURED)) {
+ /*
+ * Need to unisolate the device before configuring
+ * or it should already be in configured state to
+ * allow configure-connector be called repeatedly.
+ */
rc = SPAPR_DR_CC_RESPONSE_NOT_CONFIGURABLE;
goto out;
}
@@ -1108,8 +1119,13 @@ static void rtas_ibm_configure_connector(PowerPCCPU *cpu,
/* done sending the device tree, move to configured state */
trace_spapr_drc_set_configured(drc_index);
drc->state = drck->ready_state;
- drc->ccs_offset = -1;
- drc->ccs_depth = -1;
+ /*
+ * Ensure that we are able to send the FDT fragment
+ * again via configure-connector call if the guest requests.
+ */
+ drc->ccs_offset = drc->fdt_start_offset;
+ drc->ccs_depth = 0;
+ fdt_offset_next = drc->fdt_start_offset;
resp = SPAPR_DR_CC_RESPONSE_SUCCESS;
} else {
resp = SPAPR_DR_CC_RESPONSE_PREV_PARENT;
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index e614621..ed2d535 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -618,6 +618,8 @@ static void spapr_tce_table_class_init(ObjectClass *klass, void *data)
dc->init = spapr_tce_table_realize;
dc->reset = spapr_tce_reset;
dc->unrealize = spapr_tce_table_unrealize;
+ /* Reason: This is just an internal device for handling the hypercalls */
+ dc->user_creatable = false;
QLIST_INIT(&spapr_tce_tables);
diff --git a/hw/ppc/spapr_rtc.c b/hw/ppc/spapr_rtc.c
index 00a4e4c..9ec3078 100644
--- a/hw/ppc/spapr_rtc.c
+++ b/hw/ppc/spapr_rtc.c
@@ -164,6 +164,8 @@ static void spapr_rtc_class_init(ObjectClass *oc, void *data)
dc->realize = spapr_rtc_realize;
dc->vmsd = &vmstate_spapr_rtc;
+ /* Reason: This is an internal device only for handling the hypercalls */
+ dc->user_creatable = false;
spapr_rtas_register(RTAS_GET_TIME_OF_DAY, "get-time-of-day",
rtas_get_time_of_day);