From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=45728 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OY0xw-0003lf-JI for qemu-devel@nongnu.org; Sun, 11 Jul 2010 14:09:25 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OY0xv-0006K0-Cf for qemu-devel@nongnu.org; Sun, 11 Jul 2010 14:09:24 -0400 Received: from mx1.redhat.com ([209.132.183.28]:27179) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OY0xv-0006Ji-5h for qemu-devel@nongnu.org; Sun, 11 Jul 2010 14:09:23 -0400 From: Alex Williamson Date: Sun, 11 Jul 2010 12:09:17 -0600 Message-ID: <20100711180917.20121.51464.stgit@localhost6.localdomain6> In-Reply-To: <20100711180910.20121.93313.stgit@localhost6.localdomain6> References: <20100711180910.20121.93313.stgit@localhost6.localdomain6> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Subject: [Qemu-devel] [RFC PATCH 1/5] qemu_ram_map/unmap: Allow pre-allocated space to be mapped List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: kvm@vger.kernel.org, qemu-devel@nongnu.org Cc: chrisw@redhat.com, alex.williamson@redhat.com, pugs@cisco.com, mst@redhat.com For assigned devices, we want to map the PCI BARs into the VM address space. This is just like mapping an option ROM except the host backing is an mmap area instead of a chunk of vmalloc memory. This allow registration and removal of such areas. Signed-off-by: Alex Williamson --- cpu-common.h | 3 +++ exec.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 0 deletions(-) diff --git a/cpu-common.h b/cpu-common.h index 71e7933..8d03f4e 100644 --- a/cpu-common.h +++ b/cpu-common.h @@ -40,7 +40,10 @@ static inline void cpu_register_physical_memory(target_phys_addr_t start_addr, } ram_addr_t cpu_get_physical_page_desc(target_phys_addr_t addr); +ram_addr_t qemu_ram_map(DeviceState *dev, const char *name, + ram_addr_t size, void *host); ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size); +void qemu_ram_unmap(ram_addr_t addr); void qemu_ram_free(ram_addr_t addr); /* This should only be used for ram local to a device. */ void *qemu_get_ram_ptr(ram_addr_t addr); diff --git a/exec.c b/exec.c index 5420f56..a98b4e9 100644 --- a/exec.c +++ b/exec.c @@ -2808,6 +2808,49 @@ static ram_addr_t last_ram_offset(void) return last; } +ram_addr_t qemu_ram_map(DeviceState *dev, const char *name, + ram_addr_t size, void *host) +{ + RAMBlock *new_block, *block; + + size = TARGET_PAGE_ALIGN(size); + new_block = qemu_mallocz(sizeof(*new_block)); + + if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) { + char *id = dev->parent_bus->info->get_dev_path(dev); + if (id) { + snprintf(new_block->idstr, sizeof(new_block->idstr), "%s/", id); + qemu_free(id); + } + } + pstrcat(new_block->idstr, sizeof(new_block->idstr), name); + + QLIST_FOREACH(block, &ram_list.blocks, next) { + if (!strcmp(block->idstr, new_block->idstr)) { + fprintf(stderr, "RAMBlock \"%s\" already registered, abort!\n", + new_block->idstr); + abort(); + } + } + + new_block->host = host; + + new_block->offset = find_ram_offset(size); + new_block->length = size; + + QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next); + + ram_list.phys_dirty = qemu_realloc(ram_list.phys_dirty, + last_ram_offset() >> TARGET_PAGE_BITS); + memset(ram_list.phys_dirty + (new_block->offset >> TARGET_PAGE_BITS), + 0xff, size >> TARGET_PAGE_BITS); + + if (kvm_enabled()) + kvm_setup_guest_memory(new_block->host, size); + + return new_block->offset; +} + ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size) { RAMBlock *new_block, *block; @@ -2874,6 +2917,19 @@ ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size) return new_block->offset; } +void qemu_ram_unmap(ram_addr_t addr) +{ + RAMBlock *block; + + QLIST_FOREACH(block, &ram_list.blocks, next) { + if (addr == block->offset) { + QLIST_REMOVE(block, next); + qemu_free(block); + return; + } + } +} + void qemu_ram_free(ram_addr_t addr) { RAMBlock *block;