@@ -88,6 +88,16 @@ struct MemoryDeviceClass {
*/
MemoryRegion *(*get_memory_region)(MemoryDeviceState *md, Error **errp);
+ /*
+ * Optional: Return the desired minimum alignment of the device in guest
+ * physical address space. The final alignment is computed based on this
+ * alignment and the alignment requirements of the memory region.
+ *
+ * Called when plugging the memory device to detect the required alignment
+ * during address assignment.
+ */
+ uint64_t (*get_min_alignment)(const MemoryDeviceState *md);
+
/*
* Translate the memory device into #MemoryDeviceInfo.
*/
@@ -259,7 +259,7 @@ void memory_device_pre_plug(MemoryDeviceState *md, MachineState *ms,
{
const MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(md);
Error *local_err = NULL;
- uint64_t addr, align;
+ uint64_t addr, align = 0;
MemoryRegion *mr;
mr = mdc->get_memory_region(md, &local_err);
@@ -267,7 +267,14 @@ void memory_device_pre_plug(MemoryDeviceState *md, MachineState *ms,
goto out;
}
- align = legacy_align ? *legacy_align : memory_region_get_alignment(mr);
+ if (legacy_align) {
+ align = *legacy_align;
+ } else {
+ if (mdc->get_min_alignment) {
+ align = mdc->get_min_alignment(md);
+ }
+ align = MAX(align, memory_region_get_alignment(mr));
+ }
addr = mdc->get_addr(md);
addr = memory_device_get_free_addr(ms, !addr ? NULL : &addr, align,
memory_region_size(mr), &local_err);