/* * Memory Device Interface * * Copyright ProfitBricks GmbH 2012 * Copyright (C) 2014 Red Hat Inc * Copyright (c) 2018 Red Hat Inc * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. */ #include "qemu/osdep.h" #include "hw/mem/memory-device.h" #include "hw/qdev.h" #include "qapi/error.h" #include "hw/boards.h" #include "qemu/range.h" static gint memory_device_addr_sort(gconstpointer a, gconstpointer b) { const MemoryDeviceState *md_a = MEMORY_DEVICE(a); const MemoryDeviceState *md_b = MEMORY_DEVICE(b); const MemoryDeviceClass *mdc_a = MEMORY_DEVICE_GET_CLASS(a); const MemoryDeviceClass *mdc_b = MEMORY_DEVICE_GET_CLASS(b); const uint64_t addr_a = mdc_a->get_addr(md_a); const uint64_t addr_b = mdc_b->get_addr(md_b); if (addr_a > addr_b) { return 1; } else if (addr_a < addr_b) { return -1; } return 0; } static int memory_device_build_list(Object *obj, void *opaque) { GSList **list = opaque; if (object_dynamic_cast(obj, TYPE_MEMORY_DEVICE)) { DeviceState *dev = DEVICE(obj); if (dev->realized) { /* only realized memory devices matter */ *list = g_slist_insert_sorted(*list, dev, memory_device_addr_sort); } } object_child_foreach(obj, memory_device_build_list, opaque); return 0; } MemoryDeviceInfoList *qmp_memory_device_list(void) { GSList *devices = NULL, *item; MemoryDeviceInfoList *list = NULL, *prev = NULL; object_child_foreach(qdev_get_machine(), memory_device_build_list, &devices); for (item = devices; item; item = g_slist_next(item)) { const MemoryDeviceState *md = MEMORY_DEVICE(item->data); const MemoryDeviceClass *mdc = MEMORY_DEVICE_GET_CLASS(item->data); MemoryDeviceInfoList *elem = g_new0(MemoryDeviceInfoList, 1); MemoryDeviceInfo *info = g_new0(MemoryDeviceInfo, 1); mdc->fill_device_info(md, info); elem->value = info; elem->next = NULL; if (prev) { prev->next = elem; } else { list = elem; } prev = elem; } g_slist_free(devices); return list; } static int memory_device_plugged_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_plugged_size(md); } } object_child_foreach(obj, memory_device_plugged_size, opaque); return 0; } uint64_t get_plugged_memory_size(void) { uint64_t size = 0; memory_device_plugged_size(qdev_get_machine(), &size); return size; } static const TypeInfo memory_device_info = { .name = TYPE_MEMORY_DEVICE, .parent = TYPE_INTERFACE, .class_size = sizeof(MemoryDeviceClass), }; static void memory_device_register_types(void) { type_register_static(&memory_device_info); } type_init(memory_device_register_types)