From: Andrea Arcangeli <[email protected]> Add can_dma and post_dma methods needed before/after direct IO to guest physical memory.
Signed-off-by: Andrea Arcangeli <[email protected]> --- diff --git a/cpu-all.h b/cpu-all.h --- a/cpu-all.h +++ b/cpu-all.h @@ -912,6 +912,11 @@ CPUReadMemoryFunc **cpu_get_io_memory_re void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, size_t len, int is_write); +void cpu_physical_memory_write_post_dma(target_phys_addr_t addr, + size_t len); +uint8_t *cpu_physical_memory_can_dma(target_phys_addr_t addr, + size_t len, int is_write, + int alignment); static inline void cpu_physical_memory_read(target_phys_addr_t addr, uint8_t *buf, size_t len) { diff --git a/exec.c b/exec.c --- a/exec.c +++ b/exec.c @@ -2974,6 +2974,111 @@ void cpu_physical_memory_rw(target_phys_ } } +uint8_t *cpu_physical_memory_can_dma(target_phys_addr_t addr, + size_t len, int is_write, + int alignment) +{ + int l, first = 1; + uint8_t *ptr = NULL; + target_phys_addr_t page; + unsigned long pd, pd_first = 0; + PhysPageDesc *p; + + if (len & (alignment-1)) + goto out; + + while (len > 0) { + page = addr & TARGET_PAGE_MASK; + p = phys_page_find(page >> TARGET_PAGE_BITS); + + l = (page + TARGET_PAGE_SIZE) - addr; + if (l > len) + l = len; + + if (!p) + pd = IO_MEM_UNASSIGNED; + else + pd = p->phys_offset; + + if (is_write) { + if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) + return NULL; + } else { + if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM && + !(pd & IO_MEM_ROMD)) + return NULL; + } + + if (first) { + first = 0; + ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) + + (addr & ~TARGET_PAGE_MASK); + if ((unsigned long)ptr & (alignment-1)) + return NULL; + pd_first = pd; + } + + /* nonlinear range */ + if (pd_first != pd) + return NULL; + pd_first += TARGET_PAGE_SIZE; + + len -= l; + addr += l; + } + +out: + return ptr; +} + +void cpu_physical_memory_write_post_dma(target_phys_addr_t addr, + size_t len) +{ + int l; + uint8_t *ptr; + target_phys_addr_t page; + unsigned long pd; + PhysPageDesc *p; + + while (len > 0) { + page = addr & TARGET_PAGE_MASK; + + l = (page + TARGET_PAGE_SIZE) - addr; + if (l > len) + l = len; + + p = phys_page_find(page >> TARGET_PAGE_BITS); + if (!p) + pd = IO_MEM_UNASSIGNED; + else + pd = p->phys_offset; + + if ((pd & ~TARGET_PAGE_MASK) != IO_MEM_RAM) { + printf("ERROR cpu_physical_memory_post_dma: memory layout changed\n"); + continue; + } else { + unsigned long addr1; + addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK); + /* RAM case */ + ptr = phys_ram_base + addr1; + if (!cpu_physical_memory_is_dirty(addr1)) { + /* invalidate code */ + tb_invalidate_phys_page_range(addr1, addr1 + l, 0); + /* set dirty bit */ + phys_ram_dirty[addr1 >> TARGET_PAGE_BITS] |= + (0xff & ~CODE_DIRTY_FLAG); + } + /* qemu doesn't execute guest code directly, but kvm does + therefore fluch instruction caches */ + if (kvm_enabled()) + flush_icache_range((unsigned long)ptr, + ((unsigned long)ptr)+l); + } + len -= l; + addr += l; + } +} + /* used for ROM loading : can write in RAM and ROM */ void cpu_physical_memory_write_rom(target_phys_addr_t addr, const uint8_t *buf, int len) -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
