qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RFC PATCH v1 4/4] Handle memory hotplug error from guest O


From: Tang Chen
Subject: [Qemu-devel] [RFC PATCH v1 4/4] Handle memory hotplug error from guest OS in QEmu.
Date: Wed, 27 Aug 2014 16:09:48 +0800

Before this patch, QEmu is not aware of guest OS error when hotplugging
memory devices. Even if guest OS failed to hot-add memory, the pc-dimm
device will be added to QEmu. Even if guest OS failed to hot-remove memory,
QEmu will remove the pc-dimm device.

For example, for a Linux guest, the Linux kernel limited that the size of
hot-added memory should be mutiple of memory section (128MB by default).
If we add 130MB memory, the Linux kernel won't add it. We are not able
to handle the size check in QEmu commmand line because different OS may
have different limits.

And also, QEmu outputs nothing but guest OS failed to hot-add memory will
confuse users. We should at least report an error.

So, we should report the error to users, and cancel the memory hotplug
progress in QEmu.

Since after previous patch, QEmu will wait on qemu_cond_memhp after sending
SCI, and will be signaled by vcpu thread after OST status is written to
ACPI register, this patch checks OST status, and report an error to users,
and cancel hotplug progress if necessary.

Signed-off-by: Tang Chen <address@hidden>
---
 hw/acpi/memory_hotplug.c | 83 +++++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 79 insertions(+), 4 deletions(-)

diff --git a/hw/acpi/memory_hotplug.c b/hw/acpi/memory_hotplug.c
index 38d9654..59917c3 100644
--- a/hw/acpi/memory_hotplug.c
+++ b/hw/acpi/memory_hotplug.c
@@ -257,25 +257,95 @@ void acpi_memory_hotplug_init(MemoryRegion *as, Object 
*owner,
     qemu_mutex_init(&qemu_memhp_mutex);
 }
 
+static void acpi_handle_memory_insert_error(MemStatus *mdev, char *dev_path,
+                                            Error **errp)
+{
+    switch (mdev->ost_status) {
+    case ACPI_FAILURE:
+        error_setg(errp, "Failed to insert device [%s]", dev_path);
+        break;
+    case ACPI_UNRECOGNIZED_NOTIFY:
+        error_setg(errp, "Unrecongnized notification");
+        break;
+    case ACPI_INSERT_DRIVER_LOAD_FAILURE:
+        error_setg(errp, "Failed to load driver for device [%s]", dev_path);
+        break;
+    case ACPI_INSERT_NOT_SUPPORTED:
+        error_setg(errp, "Insertion is not supported for device [%s]",
+                   dev_path);
+        break;
+    default:
+        error_setg(errp, "Unknown error on insertion of device [%s]", 
dev_path);
+        break;
+    }
+}
+
+static void acpi_handle_memory_eject_error(MemStatus *mdev, char *dev_path,
+                                           Error **errp)
+{
+    switch (mdev->ost_status) {
+    case ACPI_FAILURE:
+        error_setg(errp, "Failed to eject device [%s]", dev_path);
+        break;
+    case ACPI_UNRECOGNIZED_NOTIFY:
+        error_setg(errp, "Unrecongnized notification");
+        break;
+    case ACPI_EJECT_DEVICE_IN_USE:
+    case ACPI_EJECT_DEVICE_BUSY:
+        error_setg(errp, "Device [%s] is busy", dev_path);
+        break;
+    case ACPI_EJECT_DEPENDENCY_BUSY:
+        error_setg(errp, "Ejection dependency is busy or not supported"
+                         " for device [%s]", dev_path);
+        break;
+    case ACPI_EJECT_NOT_SUPPORTED:
+        error_setg(errp, "Ejection is not supported for device [%s]",
+                   dev_path);
+        break;
+    default:
+        error_setg(errp, "Unknown error on ejection of device [%s]", dev_path);
+        break;
+    }
+}
+
+static void acpi_handle_memory_error(MemStatus *mdev, char *dev_path,
+                                     Error **errp)
+{
+    if (mdev->ost_status == ACPI_SUCCESS)
+        return;
+
+    switch (mdev->ost_event) {
+    case ACPI_NOTIFY_DEVICE_CHECK:
+    case ACPI_OSPM_INSERT:
+        acpi_handle_memory_insert_error(mdev, dev_path, errp);
+        break;
+    case ACPI_NOTIFY_EJECT_REQUEST:
+    case ACPI_OSPM_EJECT:
+        acpi_handle_memory_eject_error(mdev, dev_path, errp);
+        break;
+    default:
+        break;
+    }
+}
+
 void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
                          DeviceState *dev, Error **errp)
 {
     MemStatus *mdev;
     Error *local_err = NULL;
     int slot = object_property_get_int(OBJECT(dev), "slot", &local_err);
+    char *dev_path = object_get_canonical_path(OBJECT(dev));
 
     if (local_err) {
         error_propagate(errp, local_err);
-        return;
+        goto ret;
     }
 
     if (slot >= mem_st->dev_count) {
-        char *dev_path = object_get_canonical_path(OBJECT(dev));
         error_setg(errp, "acpi_memory_plug_cb: "
                    "device [%s] returned invalid memory slot[%d]",
                     dev_path, slot);
-        g_free(dev_path);
-        return;
+        goto ret;
     }
 
     mdev = &mem_st->devs[slot];
@@ -300,9 +370,14 @@ void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, 
MemHotplugState *mem_st,
      * and will relock it when signaled.
      */
     qemu_cond_wait(&qemu_memhp_cond, &qemu_memhp_mutex);
+
+    acpi_handle_memory_error(mdev, dev_path, errp);
+
     qemu_mutex_unlock(&qemu_memhp_mutex);
     qemu_mutex_lock_iothread();
 
+ret:
+    g_free(dev_path);
     return;
 }
 
-- 
1.8.4.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]