mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 07:43:54 -06:00
pc-dimm: factor out capacity and slot checks into MemoryDevice
Move the checks into memory_device_get_free_addr(). This will check before doing any calculations if we have KVM/vhost slots left and if the total region size would be exceeded. Of course, while at it, make it independent of pc-dimm code. Signed-off-by: David Hildenbrand <david@redhat.com> Message-Id: <20180423165126.15441-7-david@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
This commit is contained in:
parent
bb0831bdf4
commit
1b6d6af21b
3 changed files with 51 additions and 61 deletions
|
@ -15,6 +15,8 @@
|
|||
#include "qapi/error.h"
|
||||
#include "hw/boards.h"
|
||||
#include "qemu/range.h"
|
||||
#include "hw/virtio/vhost.h"
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
static gint memory_device_addr_sort(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
|
@ -48,6 +50,50 @@ static int memory_device_build_list(Object *obj, void *opaque)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int memory_device_used_region_size(Object *obj, void *opaque)
|
||||
{
|
||||
uint64_t *size = opaque;
|
||||
|
||||
if (object_dynamic_cast(obj, TYPE_MEMORY_DEVICE)) {
|
||||
const DeviceState *dev = DEVICE(obj);
|
||||
const MemoryDeviceState *md = MEMORY_DEVICE(obj);
|
||||
const MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(obj);
|
||||
|
||||
if (dev->realized) {
|
||||
*size += mdc->get_region_size(md);
|
||||
}
|
||||
}
|
||||
|
||||
object_child_foreach(obj, memory_device_used_region_size, opaque);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void memory_device_check_addable(MachineState *ms, uint64_t size,
|
||||
Error **errp)
|
||||
{
|
||||
uint64_t used_region_size = 0;
|
||||
|
||||
/* we will need a new memory slot for kvm and vhost */
|
||||
if (kvm_enabled() && !kvm_has_free_slot(ms)) {
|
||||
error_setg(errp, "hypervisor has no free memory slots left");
|
||||
return;
|
||||
}
|
||||
if (!vhost_has_free_slot()) {
|
||||
error_setg(errp, "a used vhost backend has no free memory slots left");
|
||||
return;
|
||||
}
|
||||
|
||||
/* will we exceed the total amount of memory specified */
|
||||
memory_device_used_region_size(OBJECT(ms), &used_region_size);
|
||||
if (used_region_size + size > ms->maxram_size - ms->ram_size) {
|
||||
error_setg(errp, "not enough space, currently 0x%" PRIx64
|
||||
" in use of total hot pluggable 0x" RAM_ADDR_FMT,
|
||||
used_region_size, ms->maxram_size - ms->ram_size);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint64_t memory_device_get_free_addr(MachineState *ms, const uint64_t *hint,
|
||||
uint64_t align, uint64_t size,
|
||||
Error **errp)
|
||||
|
@ -73,6 +119,11 @@ uint64_t memory_device_get_free_addr(MachineState *ms, const uint64_t *hint,
|
|||
g_assert(QEMU_ALIGN_UP(address_space_start, align) == address_space_start);
|
||||
g_assert(address_space_end >= address_space_start);
|
||||
|
||||
memory_device_check_addable(ms, size, errp);
|
||||
if (*errp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (hint && QEMU_ALIGN_UP(*hint, align) != *hint) {
|
||||
error_setg(errp, "address must be aligned to 0x%" PRIx64 " bytes",
|
||||
align);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue