memory-device: Add get_min_alignment() callback

Add a callback that can be used to express additional alignment
requirements (exceeding the ones from the memory region).

Will be used by virtio-mem to express special alignment requirements due
to manually configured, big block sizes (e.g., 1GB with an ordinary
memory-backend-ram). This avoids failing later when realizing, because
auto-detection wasn't able to assign a properly aligned address.

Reviewed-by: Pankaj Gupta <pankaj.gupta.linux@gmail.com>
Cc: "Michael S. Tsirkin" <mst@redhat.com>
Cc: Wei Yang <richardw.yang@linux.intel.com>
Cc: Dr. David Alan Gilbert <dgilbert@redhat.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Pankaj Gupta <pankaj.gupta.linux@gmail.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20201008083029.9504-6-david@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
David Hildenbrand 2020-10-08 10:30:28 +02:00 committed by Michael S. Tsirkin
parent 780a4d24e7
commit c726aa6941
2 changed files with 19 additions and 2 deletions

View File

@ -259,7 +259,7 @@ void memory_device_pre_plug(MemoryDeviceState *md, MachineState *ms,
{ {
const MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(md); const MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(md);
Error *local_err = NULL; Error *local_err = NULL;
uint64_t addr, align; uint64_t addr, align = 0;
MemoryRegion *mr; MemoryRegion *mr;
mr = mdc->get_memory_region(md, &local_err); mr = mdc->get_memory_region(md, &local_err);
@ -267,7 +267,14 @@ void memory_device_pre_plug(MemoryDeviceState *md, MachineState *ms,
goto out; 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 = mdc->get_addr(md);
addr = memory_device_get_free_addr(ms, !addr ? NULL : &addr, align, addr = memory_device_get_free_addr(ms, !addr ? NULL : &addr, align,
memory_region_size(mr), &local_err); memory_region_size(mr), &local_err);

View File

@ -88,6 +88,16 @@ struct MemoryDeviceClass {
*/ */
MemoryRegion *(*get_memory_region)(MemoryDeviceState *md, Error **errp); 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. * Translate the memory device into #MemoryDeviceInfo.
*/ */