summary refs log tree commit diff stats
path: root/hw/mem/memory-device.c
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2023-11-07 09:41:42 +0800
committerStefan Hajnoczi <stefanha@redhat.com>2023-11-07 09:41:42 +0800
commit17735e93719cbb44010aa517a24527b13e5f70d8 (patch)
tree56164b909180c9b5f97a4090e3c3a7a8951aa75e /hw/mem/memory-device.c
parent9f33cf2a89b5f8b437f3c62158c9ac2aa6ba9d48 (diff)
parent00313b517d09c0b141fb32997791f911c28fd3ff (diff)
downloadfocaccia-qemu-17735e93719cbb44010aa517a24527b13e5f70d8.tar.gz
focaccia-qemu-17735e93719cbb44010aa517a24527b13e5f70d8.zip
Merge tag 'pull-hv-balloon-20231106' of https://github.com/maciejsszmigiero/qemu into staging
Hyper-V Dynamic Memory protocol driver.

This driver is like virtio-balloon on steroids for Windows guests:
it allows both changing the guest memory allocation via ballooning and
inserting pieces of extra RAM into it on demand from a provided memory
backend via Windows-native Hyper-V Dynamic Memory protocol.

* Preparatory patches to support empty memory devices and ones with
large alignment requirements.

* Revert of recently added "hw/virtio/virtio-pmem: Replace impossible
check by assertion" commit 5960f254dbb4 since this series makes this
situation possible again.

* Protocol definitions.

* Hyper-V DM protocol driver (hv-balloon) base (ballooning only).

* Hyper-V DM protocol driver (hv-balloon) hot-add support.

* qapi query-memory-devices support for the driver.

* qapi HV_BALLOON_STATUS_REPORT event.

* The relevant PC machine plumbing.

* New MAINTAINERS entry for the above.

# -----BEGIN PGP SIGNATURE-----
#
# iQGzBAABCAAdFiEE4ndqq6COJv9aG0oJUrHW6VHQzgcFAmVI81IACgkQUrHW6VHQ
# zgdzTgv+I5eV2R01YLOBBJhBjzxZ4/BUqkuUHNxHpfjuCqEIzPb7FIfoZ4ZyXZFT
# YJdSE4lPeTZLrmmi/Nt6G0rUKDvdCeIgkS2VLHFSsTV8IzcT71BTRGzV0zAjUF5v
# yDH6uzo6e9gmaziIalRjibUxSDjCQmoCifms2rS2DwazADudUp+naGfm+3uyA0gM
# raOfBfRkNZsDqhXg2ayuqPIES75xQONoON9xYPKDAthS48POEbqtWBKuFopr3kXY
# y0eph+NAw+RajCyLYKM3poIgaSu3l4WegInuKQffzqKR8dxrbwPdCmtgo6NSHx0W
# uDfl7FUBnGzrR18VU4ZfTSrF5SVscGwF9EL7uocJen15inJjl1q3G53uZgyGzHLC
# cw8fKMjucmE8njQR2qiMyX0b+T4+9nKO1rykBgTG/+c9prRUVoxYpFCF117Ei0U8
# QzLGACW1oK+LV41bekWAye7w9pShUtFaxffhPbJeZDDGh7q0x61R3Z3yKkA07p46
# /YWWFWUD
# =RAb0
# -----END PGP SIGNATURE-----
# gpg: Signature made Mon 06 Nov 2023 22:08:18 HKT
# gpg:                using RSA key E2776AABA08E26FF5A1B4A0952B1D6E951D0CE07
# gpg: Good signature from "Maciej S. Szmigiero <mail@maciej.szmigiero.name>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 727A 0D4D DB9E D9F6 039B  ECEF 847F 5E37 90CE 0977
#      Subkey fingerprint: E277 6AAB A08E 26FF 5A1B  4A09 52B1 D6E9 51D0 CE07

* tag 'pull-hv-balloon-20231106' of https://github.com/maciejsszmigiero/qemu:
  MAINTAINERS: Add an entry for Hyper-V Dynamic Memory Protocol
  hw/i386/pc: Support hv-balloon
  qapi: Add HV_BALLOON_STATUS_REPORT event and its QMP query command
  qapi: Add query-memory-devices support to hv-balloon
  Add Hyper-V Dynamic Memory Protocol driver (hv-balloon) hot-add support
  Add Hyper-V Dynamic Memory Protocol driver (hv-balloon) base
  Add Hyper-V Dynamic Memory Protocol definitions
  memory-device: Drop size alignment check
  Revert "hw/virtio/virtio-pmem: Replace impossible check by assertion"
  memory-device: Support empty memory devices

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'hw/mem/memory-device.c')
-rw-r--r--hw/mem/memory-device.c49
1 files changed, 40 insertions, 9 deletions
diff --git a/hw/mem/memory-device.c b/hw/mem/memory-device.c
index ae38f48f16..e0704b8dc3 100644
--- a/hw/mem/memory-device.c
+++ b/hw/mem/memory-device.c
@@ -20,6 +20,22 @@
 #include "exec/address-spaces.h"
 #include "trace.h"
 
+static bool memory_device_is_empty(const MemoryDeviceState *md)
+{
+    const MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(md);
+    Error *local_err = NULL;
+    MemoryRegion *mr;
+
+    /* dropping const here is fine as we don't touch the memory region */
+    mr = mdc->get_memory_region((MemoryDeviceState *)md, &local_err);
+    if (local_err) {
+        /* Not empty, we'll report errors later when ontaining the MR again. */
+        error_free(local_err);
+        return false;
+    }
+    return !mr;
+}
+
 static gint memory_device_addr_sort(gconstpointer a, gconstpointer b)
 {
     const MemoryDeviceState *md_a = MEMORY_DEVICE(a);
@@ -220,12 +236,6 @@ static uint64_t memory_device_get_free_addr(MachineState *ms,
         return 0;
     }
 
-    if (!QEMU_IS_ALIGNED(size, align)) {
-        error_setg(errp, "backend memory size must be multiple of 0x%"
-                   PRIx64, align);
-        return 0;
-    }
-
     if (hint) {
         if (range_init(&new, *hint, size) || !range_contains_range(&as, &new)) {
             error_setg(errp, "can't add memory device [0x%" PRIx64 ":0x%" PRIx64
@@ -249,6 +259,10 @@ static uint64_t memory_device_get_free_addr(MachineState *ms,
         uint64_t next_addr;
         Range tmp;
 
+        if (memory_device_is_empty(md)) {
+            continue;
+        }
+
         range_init_nofail(&tmp, mdc->get_addr(md),
                           memory_device_get_region_size(md, &error_abort));
 
@@ -292,6 +306,7 @@ MemoryDeviceInfoList *qmp_memory_device_list(void)
         const MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(item->data);
         MemoryDeviceInfo *info = g_new0(MemoryDeviceInfo, 1);
 
+        /* Let's query infotmation even for empty memory devices. */
         mdc->fill_device_info(md, info);
 
         QAPI_LIST_APPEND(tail, info);
@@ -311,7 +326,7 @@ static int memory_device_plugged_size(Object *obj, void *opaque)
         const MemoryDeviceState *md = MEMORY_DEVICE(obj);
         const MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(obj);
 
-        if (dev->realized) {
+        if (dev->realized && !memory_device_is_empty(md)) {
             *size += mdc->get_plugged_size(md, &error_abort);
         }
     }
@@ -337,6 +352,11 @@ void memory_device_pre_plug(MemoryDeviceState *md, MachineState *ms,
     uint64_t addr, align = 0;
     MemoryRegion *mr;
 
+    /* We support empty memory devices even without device memory. */
+    if (memory_device_is_empty(md)) {
+        return;
+    }
+
     if (!ms->device_memory) {
         error_setg(errp, "the configuration is not prepared for memory devices"
                          " (e.g., for memory hotplug), consider specifying the"
@@ -380,10 +400,17 @@ out:
 void memory_device_plug(MemoryDeviceState *md, MachineState *ms)
 {
     const MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(md);
-    const unsigned int memslots = memory_device_get_memslots(md);
-    const uint64_t addr = mdc->get_addr(md);
+    unsigned int memslots;
+    uint64_t addr;
     MemoryRegion *mr;
 
+    if (memory_device_is_empty(md)) {
+        return;
+    }
+
+    memslots = memory_device_get_memslots(md);
+    addr = mdc->get_addr(md);
+
     /*
      * We expect that a previous call to memory_device_pre_plug() succeeded, so
      * it can't fail at this point.
@@ -408,6 +435,10 @@ void memory_device_unplug(MemoryDeviceState *md, MachineState *ms)
     const unsigned int memslots = memory_device_get_memslots(md);
     MemoryRegion *mr;
 
+    if (memory_device_is_empty(md)) {
+        return;
+    }
+
     /*
      * We expect that a previous call to memory_device_pre_plug() succeeded, so
      * it can't fail at this point.