From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([140.186.70.92]:42579) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QHInE-0002aj-FO for qemu-devel@nongnu.org; Tue, 03 May 2011 12:49:49 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QHIn9-0008Oi-LZ for qemu-devel@nongnu.org; Tue, 03 May 2011 12:49:48 -0400 Received: from mail-ww0-f53.google.com ([74.125.82.53]:39017) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QHIn9-0008Nw-Gh for qemu-devel@nongnu.org; Tue, 03 May 2011 12:49:43 -0400 Received: by mail-ww0-f53.google.com with SMTP id 40so288615wwj.10 for ; Tue, 03 May 2011 09:49:43 -0700 (PDT) Sender: Paolo Bonzini From: Paolo Bonzini Date: Tue, 3 May 2011 18:49:32 +0200 Message-Id: <1304441374-27314-3-git-send-email-pbonzini@redhat.com> In-Reply-To: <1304441374-27314-1-git-send-email-pbonzini@redhat.com> References: <1304441374-27314-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PATCH 2/4] exec: introduce cpu_physical_memory_map_fast and cpu_physical_memory_map_check List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Paravirtualized devices (and also some real devices) can assume they are going to access RAM. For this reason, provide a fast-path function with the following properties: 1) it will never allocate a bounce buffer 2) it can be used for read-modify-write operations 3) unlike qemu_get_ram_ptr, it is safe because it recognizes "short" blocks To use cpu_physical_memory_map_fast for RMW, just pass 1 to is_write when unmapping. Signed-off-by: Paolo Bonzini --- cpu-common.h | 4 ++++ exec.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 0 deletions(-) diff --git a/cpu-common.h b/cpu-common.h index 96c02ae..d6e116d 100644 --- a/cpu-common.h +++ b/cpu-common.h @@ -80,6 +80,10 @@ static inline void cpu_physical_memory_write(target_phys_addr_t addr, void *cpu_physical_memory_map(target_phys_addr_t addr, target_phys_addr_t *plen, int is_write); +void *cpu_physical_memory_map_fast(target_phys_addr_t addr, + target_phys_addr_t *plen); +bool cpu_physical_memory_map_check(target_phys_addr_t addr, + target_phys_addr_t len); void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len, int is_write, target_phys_addr_t access_len); void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque)); diff --git a/exec.c b/exec.c index 9b2c9e4..2b88c29 100644 --- a/exec.c +++ b/exec.c @@ -3944,6 +3944,19 @@ static void *cpu_physical_memory_map_internal(target_phys_addr_t addr, /* Map a physical memory region into a host virtual address. * May map a subset of the requested range, given by and returned in *plen. + * May return NULL if extra resources are needed to perform the mapping + * (i.e. cpu_physical_memory_map is needed). + * It may be used for read-modify-write operations. + */ +void *cpu_physical_memory_map_fast(target_phys_addr_t addr, + target_phys_addr_t *plen) +{ + uintptr_t pd; + return cpu_physical_memory_map_internal(addr, plen, &pd); +} + +/* Map a physical memory region into a host virtual address. + * May map a subset of the requested range, given by and returned in *plen. * May return NULL if resources needed to perform the mapping are exhausted. * Use only for reads OR writes - not for read-modify-write operations. * Use cpu_register_map_client() to know when retrying the map operation is @@ -3981,6 +3994,24 @@ void *cpu_physical_memory_map(target_phys_addr_t addr, return bounce.buffer; } +/* Returns true if the entire area between ADDR and ADDR+LEN (inclusive + * and exclusive, respectively) can be mapped by cpu_physical_memory_map_fast + * (possibly in multiple steps). + */ +bool cpu_physical_memory_map_check(target_phys_addr_t addr, + target_phys_addr_t len) +{ + while (len > 0) { + target_phys_addr_t l = len; + if (!cpu_physical_memory_map_fast(addr, &l)) { + return false; + } + len -= l; + addr += l; + } + return true; +} + /* Unmaps a memory region previously mapped by cpu_physical_memory_map(). * Will also mark the memory as dirty if is_write == 1. access_len gives * the amount of memory that was actually read or written by the caller. -- 1.7.4.4