diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index cec441c..10faae3 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -790,6 +790,31 @@ out:
     return ret;
 }
 
+static bool spapr_hotplugged_dev_before_cas(void)
+{
+    Object *drc_container, *obj;
+    ObjectProperty *prop;
+    ObjectPropertyIterator iter;
+    sPAPRDRConnector *drc;
+    sPAPRDRConnectorClass *drck;
+
+    drc_container = container_get(object_get_root(), "/dr-connector");
+    object_property_iter_init(&iter, drc_container);
+    while ((prop = object_property_iter_next(&iter))) {
+        if (!strstart(prop->type, "link<", NULL)) {
+            continue;
+        }
+        obj = object_property_get_link(drc_container, prop->name, NULL);
+        drc = SPAPR_DR_CONNECTOR(obj);
+        drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
+        if (drc->dev && drc->dev->hotplugged &&
+                (drc->state == drck->empty_state)) {
+            return true;
+        }
+    }
+    return false;
+}
+
 int spapr_h_cas_compose_response(sPAPRMachineState *spapr,
                                  target_ulong addr, target_ulong size,
                                  sPAPROptionVector *ov5_updates)
@@ -797,6 +822,10 @@ int spapr_h_cas_compose_response(sPAPRMachineState *spapr,
     void *fdt, *fdt_skel;
     sPAPRDeviceTreeUpdateHeader hdr = { .version_id = 1 };
 
+    if (spapr_hotplugged_dev_before_cas()) {
+        return 1;
+    }
+
     size -= sizeof(hdr);
 
     /* Create sceleton */
@@ -2710,9 +2739,22 @@ static void spapr_nmi(NMIState *n, int cpu_index, Error **errp)
     }
 }
 
+/*
+ * 'h_client_architecture_support' will set at least OV5_FORM1_AFFINITY
+ * in ov5_cas when intersecting it with spapr->ov5 and ov5_guest. It's safe
+ * then to assume that CAS ov5_cas will have something set after CAS.
+ */
+bool spapr_cas_completed(sPAPRMachineState *spapr)
+{
+    if (spapr->ov5_cas == NULL) {
+        return false;
+    }
+    return !spapr_ovec_is_unset(spapr->ov5_cas);
+}
+
 static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,
                            uint32_t node, bool dedicated_hp_event_source,
-                           Error **errp)
+                           sPAPRMachineState *spapr, Error **errp)
 {
     sPAPRDRConnector *drc;
     uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE;
@@ -2748,10 +2790,18 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size,
         }
         addr += SPAPR_MEMORY_BLOCK_SIZE;
     }
-    /* send hotplug notification to the
-     * guest only in case of hotplugged memory
+
+    /*
+     * Send hotplug notification interrupt to the guest only
+     * in case of hotplugged memory.
+     *
+     * Before CAS, we don't know how to queue up events yet because
+     * we don't know if the guest is able to handle HOTPLUG or
+     * EPOW (see rtas_event_log_to_source). In this case, do
+     * not queue up the event. The memory will be left in
+     * the 'empty_state' and will trigger a CAS reboot later.
      */
-    if (hotplugged) {
+    if (hotplugged && spapr_cas_completed(spapr)) {
         if (dedicated_hp_event_source) {
             drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB,
                                   addr_start / SPAPR_MEMORY_BLOCK_SIZE);
@@ -2795,7 +2845,7 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
 
     spapr_add_lmbs(dev, addr, size, node,
                    spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT),
-                   &local_err);
+                   ms, &local_err);
     if (local_err) {
         goto out_unplug;
     }
@@ -3113,8 +3163,18 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
             /*
              * Send hotplug notification interrupt to the guest only
              * in case of hotplugged CPUs.
+             *
+             * Before CAS, we don't know how to queue up events yet because
+             * we don't know if the guest is able to handle HOTPLUG or
+             * EPOW (see rtas_event_log_to_source). In this case, do
+             * not queue up the event.
+             *
+             * A hotplugged CPU before CAS will trigger a CAS reboot
+             * later on.
              */
-            spapr_hotplug_req_add_by_index(drc);
+            if (spapr_cas_completed(spapr)) {
+                spapr_hotplug_req_add_by_index(drc);
+            }
         } else {
             spapr_drc_reset(drc);
         }
diff --git a/hw/ppc/spapr_ovec.c b/hw/ppc/spapr_ovec.c
index 41df4c3..fe7bc85 100644
--- a/hw/ppc/spapr_ovec.c
+++ b/hw/ppc/spapr_ovec.c
@@ -134,6 +134,13 @@ bool spapr_ovec_test(sPAPROptionVector *ov, long bitnr)
     return test_bit(bitnr, ov->bitmap) ? true : false;
 }
 
+bool spapr_ovec_is_unset(sPAPROptionVector *ov)
+{
+    unsigned long lastbit;
+    lastbit = find_last_bit(ov->bitmap, OV_MAXBITS);
+    return (lastbit == OV_MAXBITS);
+}
+
 static void guest_byte_to_bitmap(uint8_t entry, unsigned long *bitmap,
                                  long bitmap_offset)
 {
diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c
index d84abf1..4dffa2f 100644
--- a/hw/ppc/spapr_pci.c
+++ b/hw/ppc/spapr_pci.c
@@ -1440,10 +1440,18 @@ static void spapr_pci_plug(HotplugHandler *plug_handler,
 
     /* If this is function 0, signal hotplug for all the device functions.
      * Otherwise defer sending the hotplug event.
+     *
+     * Before CAS, we don't know how to queue up events yet because
+     * we don't know if the guest is able to handle HOTPLUG or
+     * EPOW (see rtas_event_log_to_source). In this case, do
+     * not queue up the event. The device will be left in
+     * the 'empty_state' and will trigger a CAS reboot later.
+     *
      */
     if (!spapr_drc_hotplugged(plugged_dev)) {
         spapr_drc_reset(drc);
-    } else if (PCI_FUNC(pdev->devfn) == 0) {
+    } else if (PCI_FUNC(pdev->devfn) == 0 &&
+            spapr_cas_completed(SPAPR_MACHINE(qdev_get_machine()))) {
         int i;
 
         for (i = 0; i < 8; i++) {
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
index 2a303a7..a2999d1 100644
--- a/include/hw/ppc/spapr.h
+++ b/include/hw/ppc/spapr.h
@@ -662,6 +662,8 @@ void spapr_cpu_parse_features(sPAPRMachineState *spapr);
 int spapr_hpt_shift_for_ramsize(uint64_t ramsize);
 void spapr_reallocate_hpt(sPAPRMachineState *spapr, int shift,
                           Error **errp);
+bool spapr_cas_completed(sPAPRMachineState *spapr);
+
 
 /* CPU and LMB DRC release callbacks. */
 void spapr_core_release(DeviceState *dev);
diff --git a/include/hw/ppc/spapr_ovec.h b/include/hw/ppc/spapr_ovec.h
index 9edfa5f..8126374 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_is_unset(sPAPROptionVector *ov);
 sPAPROptionVector *spapr_ovec_parse_vector(target_ulong table_addr, int vector);
 int spapr_ovec_populate_dt(void *fdt, int fdt_offset,
                            sPAPROptionVector *ov, const char *name);
