aboutsummaryrefslogtreecommitdiff
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)
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.