|
|
a19a21 |
From f94b3a4eb9d709f1f6a14ad9ad6ebcc1b67b6923 Mon Sep 17 00:00:00 2001
|
|
|
a19a21 |
From: Greg Kurz <gkurz@redhat.com>
|
|
|
a19a21 |
Date: Tue, 19 Jan 2021 15:09:54 -0500
|
|
|
a19a21 |
Subject: [PATCH 6/9] spapr: Improve handling of memory unplug with old guests
|
|
|
a19a21 |
|
|
|
a19a21 |
RH-Author: Greg Kurz <gkurz@redhat.com>
|
|
|
a19a21 |
Message-id: <20210119150954.1017058-7-gkurz@redhat.com>
|
|
|
a19a21 |
Patchwork-id: 100684
|
|
|
a19a21 |
O-Subject: [RHEL-8.4.0 qemu-kvm PATCH v2 6/6] spapr: Improve handling of memory unplug with old guests
|
|
|
a19a21 |
Bugzilla: 1901837
|
|
|
a19a21 |
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
|
|
|
a19a21 |
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
|
|
|
a19a21 |
RH-Acked-by: David Gibson <dgibson@redhat.com>
|
|
|
a19a21 |
|
|
|
a19a21 |
From: Greg Kurz <groug@kaod.org>
|
|
|
a19a21 |
|
|
|
a19a21 |
Since commit 1e8b5b1aa16b ("spapr: Allow memory unplug to always succeed")
|
|
|
a19a21 |
trying to unplug memory from a guest that doesn't support it (eg. rhel6)
|
|
|
a19a21 |
no longer generates an error like it used to. Instead, it leaves the
|
|
|
a19a21 |
memory around : only a subsequent reboot or manual use of drmgr within
|
|
|
a19a21 |
the guest can complete the hot-unplug sequence. A flag was added to
|
|
|
a19a21 |
SpaprMachineClass so that this new behavior only applies to the default
|
|
|
a19a21 |
machine type.
|
|
|
a19a21 |
|
|
|
a19a21 |
We can do better. CAS processes all pending hot-unplug requests. This
|
|
|
a19a21 |
means that we don't really care about what the guest supports if
|
|
|
a19a21 |
the hot-unplug request happens before CAS.
|
|
|
a19a21 |
|
|
|
a19a21 |
All guests that we care for, even old ones, set enough bits in OV5
|
|
|
a19a21 |
that lead to a non-empty bitmap in spapr->ov5_cas. Use that as a
|
|
|
a19a21 |
heuristic to decide if CAS has already occured or not.
|
|
|
a19a21 |
|
|
|
a19a21 |
Always accept unplug requests that happen before CAS since CAS will
|
|
|
a19a21 |
process them. Restore the previous behavior of rejecting them after
|
|
|
a19a21 |
CAS when we know that the guest doesn't support memory hot-unplug.
|
|
|
a19a21 |
|
|
|
a19a21 |
This behavior is suitable for all machine types : this allows to
|
|
|
a19a21 |
drop the pre_6_0_memory_unplug flag.
|
|
|
a19a21 |
|
|
|
a19a21 |
Fixes: 1e8b5b1aa16b ("spapr: Allow memory unplug to always succeed")
|
|
|
a19a21 |
Signed-off-by: Greg Kurz <groug@kaod.org>
|
|
|
a19a21 |
Message-Id: <161012708715.801107.11418801796987916516.stgit@bahia.lan>
|
|
|
a19a21 |
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
|
|
|
a19a21 |
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
|
|
|
a19a21 |
(cherry picked from commit 73598c75df0585e039825e642adede21912dabc7)
|
|
|
a19a21 |
Signed-off-by: Greg Kurz <gkurz@redhat.com>
|
|
|
a19a21 |
|
|
|
a19a21 |
Conflicts:
|
|
|
a19a21 |
hw/ppc/spapr.c
|
|
|
a19a21 |
include/hw/ppc/spapr.h
|
|
|
a19a21 |
|
|
|
a19a21 |
Contextual conflicts around the removal of pre_6_0_memory_unplug,
|
|
|
a19a21 |
which was only partially backported from upstream 1e8b5b1aa16b, and
|
|
|
a19a21 |
the addition of spapr_memory_hot_unplug_supported().
|
|
|
a19a21 |
|
|
|
a19a21 |
Signed-off-by: Jon Maloy <jmaloy.redhat.com>
|
|
|
a19a21 |
---
|
|
|
a19a21 |
hw/ppc/spapr.c | 21 +++++++++++++--------
|
|
|
a19a21 |
hw/ppc/spapr_events.c | 3 +--
|
|
|
a19a21 |
hw/ppc/spapr_ovec.c | 7 +++++++
|
|
|
a19a21 |
include/hw/ppc/spapr.h | 2 +-
|
|
|
a19a21 |
include/hw/ppc/spapr_ovec.h | 1 +
|
|
|
a19a21 |
5 files changed, 23 insertions(+), 11 deletions(-)
|
|
|
a19a21 |
|
|
|
a19a21 |
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
|
|
|
a19a21 |
index f8de33e3e5..00b1ef075e 100644
|
|
|
a19a21 |
--- a/hw/ppc/spapr.c
|
|
|
a19a21 |
+++ b/hw/ppc/spapr.c
|
|
|
a19a21 |
@@ -3993,6 +3993,18 @@ static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev,
|
|
|
a19a21 |
}
|
|
|
a19a21 |
}
|
|
|
a19a21 |
|
|
|
a19a21 |
+bool spapr_memory_hot_unplug_supported(SpaprMachineState *spapr)
|
|
|
a19a21 |
+{
|
|
|
a19a21 |
+ return spapr_ovec_test(spapr->ov5_cas, OV5_HP_EVT) ||
|
|
|
a19a21 |
+ /*
|
|
|
a19a21 |
+ * CAS will process all pending unplug requests.
|
|
|
a19a21 |
+ *
|
|
|
a19a21 |
+ * HACK: a guest could theoretically have cleared all bits in OV5,
|
|
|
a19a21 |
+ * but none of the guests we care for do.
|
|
|
a19a21 |
+ */
|
|
|
a19a21 |
+ spapr_ovec_empty(spapr->ov5_cas);
|
|
|
a19a21 |
+}
|
|
|
a19a21 |
+
|
|
|
a19a21 |
static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev,
|
|
|
a19a21 |
DeviceState *dev, Error **errp)
|
|
|
a19a21 |
{
|
|
|
a19a21 |
@@ -4001,16 +4013,9 @@ static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev,
|
|
|
a19a21 |
SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
|
|
|
a19a21 |
|
|
|
a19a21 |
if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
|
|
a19a21 |
- if (!smc->pre_6_0_memory_unplug ||
|
|
|
a19a21 |
- spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) {
|
|
|
a19a21 |
+ if (spapr_memory_hot_unplug_supported(sms)) {
|
|
|
a19a21 |
spapr_memory_unplug_request(hotplug_dev, dev, errp);
|
|
|
a19a21 |
} else {
|
|
|
a19a21 |
- /* NOTE: this means there is a window after guest reset, prior to
|
|
|
a19a21 |
- * CAS negotiation, where unplug requests will fail due to the
|
|
|
a19a21 |
- * capability not being detected yet. This is a bit different than
|
|
|
a19a21 |
- * the case with PCI unplug, where the events will be queued and
|
|
|
a19a21 |
- * eventually handled by the guest after boot
|
|
|
a19a21 |
- */
|
|
|
a19a21 |
error_setg(errp, "Memory hot unplug not supported for this guest");
|
|
|
a19a21 |
}
|
|
|
a19a21 |
} else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
|
|
|
a19a21 |
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
|
|
|
a19a21 |
index 6e284aa4bc..08168acd65 100644
|
|
|
a19a21 |
--- a/hw/ppc/spapr_events.c
|
|
|
a19a21 |
+++ b/hw/ppc/spapr_events.c
|
|
|
a19a21 |
@@ -547,8 +547,7 @@ static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action,
|
|
|
a19a21 |
/* we should not be using count_indexed value unless the guest
|
|
|
a19a21 |
* supports dedicated hotplug event source
|
|
|
a19a21 |
*/
|
|
|
a19a21 |
- g_assert(!SPAPR_MACHINE_GET_CLASS(spapr)->pre_6_0_memory_unplug ||
|
|
|
a19a21 |
- spapr_ovec_test(spapr->ov5_cas, OV5_HP_EVT));
|
|
|
a19a21 |
+ g_assert(spapr_memory_hot_unplug_supported(spapr));
|
|
|
a19a21 |
hp->drc_id.count_indexed.count =
|
|
|
a19a21 |
cpu_to_be32(drc_id->count_indexed.count);
|
|
|
a19a21 |
hp->drc_id.count_indexed.index =
|
|
|
a19a21 |
diff --git a/hw/ppc/spapr_ovec.c b/hw/ppc/spapr_ovec.c
|
|
|
a19a21 |
index 811fadf143..f858afc7d5 100644
|
|
|
a19a21 |
--- a/hw/ppc/spapr_ovec.c
|
|
|
a19a21 |
+++ b/hw/ppc/spapr_ovec.c
|
|
|
a19a21 |
@@ -135,6 +135,13 @@ bool spapr_ovec_test(SpaprOptionVector *ov, long bitnr)
|
|
|
a19a21 |
return test_bit(bitnr, ov->bitmap) ? true : false;
|
|
|
a19a21 |
}
|
|
|
a19a21 |
|
|
|
a19a21 |
+bool spapr_ovec_empty(SpaprOptionVector *ov)
|
|
|
a19a21 |
+{
|
|
|
a19a21 |
+ g_assert(ov);
|
|
|
a19a21 |
+
|
|
|
a19a21 |
+ return bitmap_empty(ov->bitmap, OV_MAXBITS);
|
|
|
a19a21 |
+}
|
|
|
a19a21 |
+
|
|
|
a19a21 |
static void guest_byte_to_bitmap(uint8_t entry, unsigned long *bitmap,
|
|
|
a19a21 |
long bitmap_offset)
|
|
|
a19a21 |
{
|
|
|
a19a21 |
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
|
|
|
a19a21 |
index ac6961ed16..7aaf5d9996 100644
|
|
|
a19a21 |
--- a/include/hw/ppc/spapr.h
|
|
|
a19a21 |
+++ b/include/hw/ppc/spapr.h
|
|
|
a19a21 |
@@ -124,7 +124,6 @@ struct SpaprMachineClass {
|
|
|
a19a21 |
bool pre_4_1_migration; /* don't migrate hpt-max-page-size */
|
|
|
a19a21 |
bool linux_pci_probe;
|
|
|
a19a21 |
bool smp_threads_vsmt; /* set VSMT to smp_threads by default */
|
|
|
a19a21 |
- bool pre_6_0_memory_unplug;
|
|
|
a19a21 |
|
|
|
a19a21 |
bool has_power9_support;
|
|
|
a19a21 |
void (*phb_placement)(SpaprMachineState *spapr, uint32_t index,
|
|
|
a19a21 |
@@ -894,4 +893,5 @@ void spapr_check_pagesize(SpaprMachineState *spapr, hwaddr pagesize,
|
|
|
a19a21 |
#define SPAPR_OV5_XIVE_BOTH 0x80 /* Only to advertise on the platform */
|
|
|
a19a21 |
|
|
|
a19a21 |
void spapr_set_all_lpcrs(target_ulong value, target_ulong mask);
|
|
|
a19a21 |
+bool spapr_memory_hot_unplug_supported(SpaprMachineState *spapr);
|
|
|
a19a21 |
#endif /* HW_SPAPR_H */
|
|
|
a19a21 |
diff --git a/include/hw/ppc/spapr_ovec.h b/include/hw/ppc/spapr_ovec.h
|
|
|
a19a21 |
index 7891e9caac..98c73bf601 100644
|
|
|
a19a21 |
--- a/include/hw/ppc/spapr_ovec.h
|
|
|
a19a21 |
+++ b/include/hw/ppc/spapr_ovec.h
|
|
|
a19a21 |
@@ -73,6 +73,7 @@ void spapr_ovec_cleanup(SpaprOptionVector *ov);
|
|
|
a19a21 |
void spapr_ovec_set(SpaprOptionVector *ov, long bitnr);
|
|
|
a19a21 |
void spapr_ovec_clear(SpaprOptionVector *ov, long bitnr);
|
|
|
a19a21 |
bool spapr_ovec_test(SpaprOptionVector *ov, long bitnr);
|
|
|
a19a21 |
+bool spapr_ovec_empty(SpaprOptionVector *ov);
|
|
|
a19a21 |
SpaprOptionVector *spapr_ovec_parse_vector(target_ulong table_addr, int vector);
|
|
|
a19a21 |
int spapr_ovec_populate_dt(void *fdt, int fdt_offset,
|
|
|
a19a21 |
SpaprOptionVector *ov, const char *name);
|
|
|
a19a21 |
--
|
|
|
a19a21 |
2.18.2
|
|
|
a19a21 |
|