On 6/17/2026 5:16 PM, Igor Mammedov wrote:
On Tue, 16 Jun 2026 17:08:05 +0800
fanhuang <[email protected]> wrote:

Introduce a TYPE_MEMORY_DEVICE subclass `sp-mem` for boot-time
SOFT_RESERVED memory exposed to the guest with a per-device NUMA
proximity domain.

The device targets accelerator memory (HBM and similar) that the
firmware hands to the guest OS as SOFT_RESERVED memory, so a driver
in the guest -- rather than the kernel's general allocator -- owns
the range.

Usage:

     -object memory-backend-ram,id=spm0,size=$SIZE
     -numa node,nodeid=$N
     -device sp-mem,id=dev0,memdev=spm0,node=$N[,addr=$GPA]

The device is boot-time only (no hotplug).

Modulo nitpicking/patch splitting and a migration question LGTM

+            case MEMORY_DEVICE_INFO_KIND_SP_MEM:
+                spmi = value->u.sp_mem.data;
+                monitor_printf(mon, "Memory device [%s]: \"%s\"\n",
+                               MemoryDeviceInfoKind_str(value->type),
+                               spmi->id ? spmi->id : "");
+                monitor_printf(mon, "  addr: 0x%" PRIx64 "\n", spmi->addr);
+                monitor_printf(mon, "  node: %" PRId64 "\n", spmi->node);
+                monitor_printf(mon, "  size: %" PRIu64 "\n", spmi->size);
+                monitor_printf(mon, "  memdev: %s\n", spmi->memdev);
+                break;
              default:
                  g_assert_not_reached();
              }

hmp could be a separate patch.


+static void sp_mem_fill_device_info(const MemoryDeviceState *md,
+                                    MemoryDeviceInfo *info)
+{
+    SpMemDeviceInfo *di = g_new0(SpMemDeviceInfo, 1);
+    SpMemDevice *spm = SP_MEM(md);
+    DeviceState *dev = DEVICE(md);
+
+    di->id = dev->id ? g_strdup(dev->id) : NULL;
+    di->addr = spm->addr;
+    di->size = memory_region_size(
+                   host_memory_backend_get_memory(spm->hostmem));
+    di->node = spm->node;
+    di->memdev = object_get_canonical_path(OBJECT(spm->hostmem));
+
+    info->u.sp_mem.data = di;
+    info->type = MEMORY_DEVICE_INFO_KIND_SP_MEM;
+}

if missing this doesn't break anything, I'd bundle it together with hmp patch



Will split the introspection bits (fill_device_info + the HMP
printer) into their own patch in the next respin.

+
+static void sp_mem_realize(DeviceState *dev, Error **errp)
+{
+    SpMemDevice *spm = SP_MEM(dev);
+
+    if (!spm->hostmem) {
+        error_setg(errp, "'%s' property is required", SP_MEM_MEMDEV_PROP);
+        return;
+    }
+    if (host_memory_backend_is_mapped(spm->hostmem)) {
+        error_setg(errp, "memory backend '%s' is already in use",
+                   object_get_canonical_path_component(OBJECT(spm->hostmem)));
+        return;
+    }
+    host_memory_backend_set_mapped(spm->hostmem, true);
+}
+
+static void sp_mem_unrealize(DeviceState *dev)
+{
+    SpMemDevice *spm = SP_MEM(dev);
+
+    host_memory_backend_set_mapped(spm->hostmem, false);
+}
+
+static const VMStateDescription vmstate_sp_mem = {
+    .name = TYPE_SP_MEM,
+    /* boot-time only; no plug/unplug state to migrate */
+    .unmigratable = 1,

this is explicit migration blocker, isn't it?
are we sure about setting it un-migratable, if yes/no than why?

I don't see how plug/unplug is involved here,
but I'd speculate that we would want to migrate memory content itself.

CCing Peter,
  for a look from migration pov



You're right that the "plug/unplug" wording is off.

The device carries no per-device migration state, so with a normal
RAM backend it would migrate like pc-dimm. I'd originally marked it
unmigratable out of caution, being unsure whether the backend could
be migrated -- but on reflection that's a property of the backend,
not of sp-mem: a backend that can't be migrated can express that
itself, independently of this device. So dropping the flag and
letting sp-mem migrate like pc-dimm, leaving any restriction to the
backend, looks like the more flexible choice.

Peter, does that match your view, or is there a reason to keep a gate
at the device?

Best regards,
FangSheng Huang (Jerry)



Reply via email to