From 5eea60c60b5214f93e6382bb534b54bef3eb5ab2 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 17 Jun 2014 18:31:15 +0100 Subject: !fixup: fix get_qemu_addr_of_guest_buffer() Fix get_qemu_addr_of_guest_buffer() to use cpu_physical_memory_map(), which is the API the memory subsystem really wants you to use for this kind of thing. This should be squashed into the earlier patch. --- hw/misc/android_pipe.c | 59 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/hw/misc/android_pipe.c b/hw/misc/android_pipe.c index 45ffc690e8..84d7a6882e 100644 --- a/hw/misc/android_pipe.c +++ b/hw/misc/android_pipe.c @@ -1017,32 +1017,39 @@ struct PipeDevice { uint64_t params_addr; }; -/* Return the QEMU accessible pointer of the drivers virtual address. +/* Map the guest buffer specified by the guest vaddr 'address'. + * Returns a host pointer which should be unmapped later via + * cpu_physical_memory_unmap(), or NULL if mapping failed (likely + * because the vaddr doesn't actually point at RAM). + * Note that for RAM the "mapping" process doesn't actually involve a + * data copy. * - * TODO: fix the driver to pass physical addresses (a la virt-io) + * TODO: using cpu_get_phys_page_debug() is a bit bogus, and we could + * avoid it if we fixed the driver to do the sane thing and pass us + * physical addresses rather than virtual ones. */ -static void * get_qemu_addr_of_guest_buffer(target_ulong address, size_t size) +static void *map_guest_buffer(target_ulong address, size_t size, int is_write) { hwaddr l = size; - uint8_t *ptr; - hwaddr addr1; -/* MemoryRegion *mr; */ + void *ptr; - target_ulong page = address & TARGET_PAGE_MASK; - size_t page_off = (address - page); + /* Convert virtual address to physical address */ + hwaddr phys = cpu_get_phys_page_debug(current_cpu, address); - hwaddr phys = cpu_get_phys_page_debug(current_cpu, page); - -/* fprintf(stderr,"%s: translating %"HWADDR_PRIx" of size %zd\n", */ -/* __func__, phys, size); */ - - //mr = - address_space_translate(&address_space_memory, phys + page_off, &addr1, &l, true); - -// addr1 += memory_region_get_ram_addr(mr); - ptr = qemu_get_ram_ptr(addr1); + ptr = cpu_physical_memory_map(phys, &l, is_write); + if (!ptr) { + /* Can't happen for RAM */ + return NULL; + } + if (l != size) { + /* This will only happen if the address pointed at non-RAM, + * or if the size means the buffer end is beyond the end of + * the RAM block. + */ + cpu_physical_memory_unmap(ptr, l, 0, 0); + return NULL; + } -/* fprintf(stderr,"%s: left = %zd, ptr = %p\n", __func__, l, ptr); */ return ptr; } @@ -1095,24 +1102,34 @@ pipeDevice_doCommand( PipeDevice* dev, uint32_t command ) case PIPE_CMD_READ_BUFFER: { /* Translate virtual address into physical one, into emulator memory. */ GoldfishPipeBuffer buffer; - buffer.data = get_qemu_addr_of_guest_buffer(dev->address, dev->size); + buffer.data = map_guest_buffer(dev->address, dev->size, 1); + if (!buffer.data) { + dev->status = PIPE_ERROR_INVAL; + break; + } buffer.size = dev->size; dev->status = pipe->funcs->recvBuffers(pipe->opaque, &buffer, 1); DD("%s: CMD_READ_BUFFER channel=0x%llx address=0x%16llx size=%d > status=%d", __FUNCTION__, (unsigned long long)dev->channel, (unsigned long long)dev->address, dev->size, dev->status); + cpu_physical_memory_unmap(buffer.data, dev->size, 1, dev->size); break; } case PIPE_CMD_WRITE_BUFFER: { /* Translate virtual address into physical one, into emulator memory. */ GoldfishPipeBuffer buffer; - buffer.data = get_qemu_addr_of_guest_buffer(dev->address, dev->size); + buffer.data = map_guest_buffer(dev->address, dev->size, 0); + if (!buffer.data) { + dev->status = PIPE_ERROR_INVAL; + break; + } buffer.size = dev->size; dev->status = pipe->funcs->sendBuffers(pipe->opaque, &buffer, 1); DD("%s: CMD_WRITE_BUFFER channel=0x%llx address=0x%16llx size=%d > status=%d", __FUNCTION__, (unsigned long long)dev->channel, (unsigned long long)dev->address, dev->size, dev->status); + cpu_physical_memory_unmap(buffer.data, dev->size, 0, dev->size); break; } -- cgit v1.2.3