Blob Blame Raw
From 1fc9b693c54c93736c6f902f3df8b94440e8cc5d Mon Sep 17 00:00:00 2001
From: Greg Kurz <>
Date: Tue, 19 Jan 2021 15:09:53 -0500
Subject: [PATCH 5/9] spapr: Allow memory unplug to always succeed

RH-Author: Greg Kurz <>
Message-id: <>
Patchwork-id: 100686
O-Subject: [RHEL-8.4.0 qemu-kvm PATCH v2 5/6] spapr: Allow memory unplug to always succeed
Bugzilla: 1901837
RH-Acked-by: Miroslav Rezanina <>
RH-Acked-by: Laurent Vivier <>
RH-Acked-by: David Gibson <>

From: Greg Kurz <>

It is currently impossible to hot-unplug a memory device between
machine reset and CAS.

(qemu) device_del dimm1
Error: Memory hot unplug not supported for this guest

This limitation was introduced in order to provide an explicit
error path for older guests that didn't support hot-plug event
sources (and thus memory hot-unplug).

The linux kernel has been supporting these since 4.11. All recent
enough guests are thus capable of handling the removal of a memory
device at all time, including during early boot.

Lift the limitation for the latest machine type. This means that
trying to unplug memory from a guest that doesn't support it will
likely just do nothing and the memory will only get removed at
next reboot. Such older guests can still get the existing behavior
by using an older machine type.

Signed-off-by: Greg Kurz <>
Message-Id: <160794035064.23292.17560963281911312439.stgit@bahia.lan>
Signed-off-by: David Gibson <>
(cherry picked from commit 1e8b5b1aa16b7d73ba8ba52c95d0b52329d5c9d0)
Signed-off-by: Greg Kurz <>


Conflicts around the addition of pre_6_0_memory_unplug. Ignore the
change that sets pre_6_0_memory_unplug for older machine types.
This is ok because pre_6_0_memory_unplug is removed in a subsequent
patch anyway.

Signed-off-by: Jon Maloy <>
 hw/ppc/spapr.c         | 3 ++-
 hw/ppc/spapr_events.c  | 3 ++-
 include/hw/ppc/spapr.h | 1 +
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 992bd08aaa..f8de33e3e5 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4001,7 +4001,8 @@ static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev,
     SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
     if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
-        if (spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) {
+        if (!smc->pre_6_0_memory_unplug ||
+            spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) {
             spapr_memory_unplug_request(hotplug_dev, dev, errp);
         } else {
             /* NOTE: this means there is a window after guest reset, prior to
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index 15b92b63ad..6e284aa4bc 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -547,7 +547,8 @@ static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action,
         /* we should not be using count_indexed value unless the guest
          * supports dedicated hotplug event source
-        g_assert(spapr_ovec_test(spapr->ov5_cas, OV5_HP_EVT));
+        g_assert(!SPAPR_MACHINE_GET_CLASS(spapr)->pre_6_0_memory_unplug ||
+                 spapr_ovec_test(spapr->ov5_cas, OV5_HP_EVT));
         hp->drc_id.count_indexed.count =
         hp->drc_id.count_indexed.index =
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index e5e2a99046..ac6961ed16 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -124,6 +124,7 @@ struct SpaprMachineClass {
     bool pre_4_1_migration; /* don't migrate hpt-max-page-size */
     bool linux_pci_probe;
     bool smp_threads_vsmt; /* set VSMT to smp_threads by default */
+    bool pre_6_0_memory_unplug;
     bool has_power9_support;
     void (*phb_placement)(SpaprMachineState *spapr, uint32_t index,