aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/ppc/spapr.c24
-rw-r--r--hw/ppc/spapr_events.c3
-rw-r--r--hw/ppc/spapr_ovec.c7
-rw-r--r--include/hw/ppc/spapr.h2
-rw-r--r--include/hw/ppc/spapr_ovec.h1
5 files changed, 23 insertions, 14 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 2c403b5..6c47466 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4048,6 +4048,18 @@ static void spapr_machine_device_unplug(HotplugHandler *hotplug_dev,
}
}
+bool spapr_memory_hot_unplug_supported(SpaprMachineState *spapr)
+{
+ return spapr_ovec_test(spapr->ov5_cas, OV5_HP_EVT) ||
+ /*
+ * CAS will process all pending unplug requests.
+ *
+ * HACK: a guest could theoretically have cleared all bits in OV5,
+ * but none of the guests we care for do.
+ */
+ spapr_ovec_empty(spapr->ov5_cas);
+}
+
static void spapr_machine_device_unplug_request(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
@@ -4056,16 +4068,9 @@ 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 (!smc->pre_6_0_memory_unplug ||
- spapr_ovec_test(sms->ov5_cas, OV5_HP_EVT)) {
+ if (spapr_memory_hot_unplug_supported(sms)) {
spapr_memory_unplug_request(hotplug_dev, dev, errp);
} else {
- /* NOTE: this means there is a window after guest reset, prior to
- * CAS negotiation, where unplug requests will fail due to the
- * capability not being detected yet. This is a bit different than
- * the case with PCI unplug, where the events will be queued and
- * eventually handled by the guest after boot
- */
error_setg(errp, "Memory hot unplug not supported for this guest");
}
} else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) {
@@ -4543,11 +4548,8 @@ DEFINE_SPAPR_MACHINE(6_0, "6.0", true);
*/
static void spapr_machine_5_2_class_options(MachineClass *mc)
{
- SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc);
-
spapr_machine_6_0_class_options(mc);
compat_props_add(mc->compat_props, hw_compat_5_2, hw_compat_5_2_len);
- smc->pre_6_0_memory_unplug = true;
}
DEFINE_SPAPR_MACHINE(5_2, "5.2", false);
diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c
index 6aedd98..d51daed 100644
--- a/hw/ppc/spapr_events.c
+++ b/hw/ppc/spapr_events.c
@@ -658,8 +658,7 @@ 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_MACHINE_GET_CLASS(spapr)->pre_6_0_memory_unplug ||
- spapr_ovec_test(spapr->ov5_cas, OV5_HP_EVT));
+ g_assert(spapr_memory_hot_unplug_supported(spapr));
hp->drc_id.count_indexed.count =
cpu_to_be32(drc_id->count_indexed.count);
hp->drc_id.count_indexed.index =
diff --git a/hw/ppc/spapr_ovec.c b/hw/ppc/spapr_ovec.c
index dd003f1..b2567ca 100644
--- a/hw/ppc/spapr_ovec.c
+++ b/hw/ppc/spapr_ovec.c
@@ -125,6 +125,13 @@ bool spapr_ovec_test(SpaprOptionVector *ov, long bitnr)
return test_bit(bitnr, ov->bitmap) ? true : false;
}
+bool spapr_ovec_empty(SpaprOptionVector *ov)
+{
+ g_assert(ov);
+
+ return bitmap_empty(ov->bitmap, OV_MAXBITS);
+}
+
static void guest_byte_to_bitmap(uint8_t entry, unsigned long *bitmap,
long bitmap_offset)
{
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 1cc1957..3ad2ff7 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -142,7 +142,6 @@ struct SpaprMachineClass {
hwaddr rma_limit; /* clamp the RMA to this size */
bool pre_5_1_assoc_refpoints;
bool pre_5_2_numa_associativity;
- bool pre_6_0_memory_unplug;
bool (*phb_placement)(SpaprMachineState *spapr, uint32_t index,
uint64_t *buid, hwaddr *pio,
@@ -950,4 +949,5 @@ bool spapr_check_pagesize(SpaprMachineState *spapr, hwaddr pagesize,
void spapr_set_all_lpcrs(target_ulong value, target_ulong mask);
hwaddr spapr_get_rtas_addr(void);
+bool spapr_memory_hot_unplug_supported(SpaprMachineState *spapr);
#endif /* HW_SPAPR_H */
diff --git a/include/hw/ppc/spapr_ovec.h b/include/hw/ppc/spapr_ovec.h
index d4dee9e..48b716a 100644
--- a/include/hw/ppc/spapr_ovec.h
+++ b/include/hw/ppc/spapr_ovec.h
@@ -71,6 +71,7 @@ void spapr_ovec_cleanup(SpaprOptionVector *ov);
void spapr_ovec_set(SpaprOptionVector *ov, long bitnr);
void spapr_ovec_clear(SpaprOptionVector *ov, long bitnr);
bool spapr_ovec_test(SpaprOptionVector *ov, long bitnr);
+bool spapr_ovec_empty(SpaprOptionVector *ov);
SpaprOptionVector *spapr_ovec_parse_vector(target_ulong table_addr, int vector);
int spapr_dt_ovec(void *fdt, int fdt_offset,
SpaprOptionVector *ov, const char *name);