From patchwork Tue May 20 15:15:19 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Igor Mammedov X-Patchwork-Id: 350759 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 592BA140088 for ; Wed, 21 May 2014 01:27:02 +1000 (EST) Received: from localhost ([::1]:54044 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WmlwS-0001dJ-9K for incoming@patchwork.ozlabs.org; Tue, 20 May 2014 11:27:00 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54695) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WmlpP-0000IK-2M for qemu-devel@nongnu.org; Tue, 20 May 2014 11:19:47 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WmlpK-00018b-Ed for qemu-devel@nongnu.org; Tue, 20 May 2014 11:19:43 -0400 Received: from mx1.redhat.com ([209.132.183.28]:43090) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WmlpK-00018U-7S for qemu-devel@nongnu.org; Tue, 20 May 2014 11:19:38 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s4KFIcSO005195 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 20 May 2014 11:18:38 -0400 Received: from dell-pet610-01.lab.eng.brq.redhat.com (dell-pet610-01.lab.eng.brq.redhat.com [10.34.42.20]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s4KFGs7b027688; Tue, 20 May 2014 11:18:32 -0400 From: Igor Mammedov To: qemu-devel@nongnu.org Date: Tue, 20 May 2014 17:15:19 +0200 Message-Id: <1400598934-31921-17-git-send-email-imammedo@redhat.com> In-Reply-To: <1400598934-31921-1-git-send-email-imammedo@redhat.com> References: <1400598934-31921-1-git-send-email-imammedo@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.22 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: peter.maydell@linaro.org, alex@alex.org.uk, mst@redhat.com, aik@ozlabs.ru, hutao@cn.fujitsu.com, mjt@tls.msk.ru, tangchen@cn.fujitsu.com, kraxel@redhat.com, pasteka@kabsi.at, s.priebe@profihost.ag, agarcia@igalia.com, armbru@redhat.com, aliguori@amazon.com, david@gibson.dropbear.id.au, lersek@redhat.com, ehabkost@redhat.com, marcel.a@redhat.com, stefanha@redhat.com, cornelia.huck@de.ibm.com, rth@twiddle.net, agraf@suse.de, andrey@xdel.ru, vasilis.liaskovitis@profitbricks.com, pbonzini@redhat.com, afaerber@suse.de, aurelien@aurel32.net Subject: [Qemu-devel] [PATCH v2 16/31] dimm: add busy address check and address auto-allocation X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org - if 'addr' property is not specified on -device/device_add command, treat default value as request for assigning DimmDevice to the first free memory region. - if 'addr' is provided with -device/device_add command, attempt to use it or fail command if it's already occupied or falls inside of an existing DimmDevice memory region. Signed-off-by: Igor Mammedov Signed-off-by: Tang Chen --- v2: * abort if hotplug address-space size is too big, reported by Hu Tao * do not reset previous error in dimm_get_free_addr(), fixed by Tang Chen --- hw/i386/pc.c | 9 ++++++ hw/mem/dimm.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++ include/hw/mem/dimm.h | 5 +++ 3 files changed, 90 insertions(+), 0 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 868af17..42f41df 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -1552,6 +1552,15 @@ static void pc_dimm_plug(HotplugHandler *hotplug_dev, goto out; } + addr = dimm_get_free_addr(pcms->hotplug_memory_base, + memory_region_size(&pcms->hotplug_memory), + !addr ? NULL : &addr, + memory_region_size(mr), &local_err); + if (local_err) { + goto out; + } + object_property_set_int(OBJECT(dev), addr, DIMM_ADDR_PROP, &local_err); + memory_region_add_subregion(&pcms->hotplug_memory, addr - pcms->hotplug_memory_base, mr); vmstate_register_ram(mr, dev); diff --git a/hw/mem/dimm.c b/hw/mem/dimm.c index 713ded5..1c726c6 100644 --- a/hw/mem/dimm.c +++ b/hw/mem/dimm.c @@ -21,6 +21,82 @@ #include "hw/mem/dimm.h" #include "qemu/config-file.h" #include "qapi/visitor.h" +#include "qemu/range.h" + +static gint dimm_addr_sort(gconstpointer a, gconstpointer b) +{ + DimmDevice *x = DIMM(a); + DimmDevice *y = DIMM(b); + + return x->addr - y->addr; +} + +static int dimm_built_list(Object *obj, void *opaque) +{ + GSList **list = opaque; + + if (object_dynamic_cast(obj, TYPE_DIMM)) { + DeviceState *dev = DEVICE(obj); + if (dev->realized) { /* only realized DIMMs matter */ + *list = g_slist_insert_sorted(*list, dev, dimm_addr_sort); + } + } + + object_child_foreach(obj, dimm_built_list, opaque); + return 0; +} + +uint64_t dimm_get_free_addr(uint64_t address_space_start, + uint64_t address_space_size, + uint64_t *hint, uint64_t size, + Error **errp) +{ + GSList *list = NULL, *item; + uint64_t new_addr, ret = 0; + uint64_t address_space_end = address_space_start + address_space_size; + + assert(address_space_end > address_space_size); + object_child_foreach(qdev_get_machine(), dimm_built_list, &list); + + if (hint) { + new_addr = *hint; + } else { + new_addr = address_space_start; + } + + /* find address range that will fit new DIMM */ + for (item = list; item; item = g_slist_next(item)) { + DimmDevice *dimm = item->data; + uint64_t dimm_size = object_property_get_int(OBJECT(dimm), + DIMM_SIZE_PROP, + errp); + if (errp && *errp) { + goto out; + } + + if (ranges_overlap(dimm->addr, dimm_size, new_addr, size)) { + if (hint) { + DeviceState *d = DEVICE(dimm); + error_setg(errp, "address range conflicts with '%s'", d->id); + goto out; + } + new_addr = dimm->addr + dimm_size; + } + } + ret = new_addr; + + if (new_addr < address_space_start) { + error_setg(errp, "can't add memory [0x%" PRIx64 ":0x%" PRIx64 + "] at 0x%" PRIx64, new_addr, size, address_space_start); + } else if ((new_addr + size) > address_space_end) { + error_setg(errp, "can't add memory [0x%" PRIx64 ":0x%" PRIx64 + "] beyond 0x%" PRIx64, new_addr, size, address_space_end); + } + +out: + g_slist_free(list); + return ret; +} static Property dimm_properties[] = { DEFINE_PROP_UINT64(DIMM_ADDR_PROP, DimmDevice, addr, 0), diff --git a/include/hw/mem/dimm.h b/include/hw/mem/dimm.h index 8839fb9..55bdfb2 100644 --- a/include/hw/mem/dimm.h +++ b/include/hw/mem/dimm.h @@ -70,4 +70,9 @@ typedef struct DimmDeviceClass { MemoryRegion *(*get_memory_region)(DimmDevice *dimm); } DimmDeviceClass; + +uint64_t dimm_get_free_addr(uint64_t address_space_start, + uint64_t address_space_size, + uint64_t *hint, uint64_t size, + Error **errp); #endif