This patch introduces a kvm version of cpu_physical_memory_rw. The main motivation is to bypass tcg version, which contains tcg-specific code, as well as data structures not used by kvm, such as l1_phys_map.
In this patch, I'm using a runtime selection of which function to call, but the mid-term goal is to use function pointers in a way very close to which QEMUAccel used to be. Signed-off-by: Glauber Costa <[email protected]> --- exec.c | 13 +++++++++++-- kvm-all.c | 39 +++++++++++++++++++++++++++++++++++---- kvm.h | 2 ++ 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/exec.c b/exec.c index 04eadfe..d5c88b1 100644 --- a/exec.c +++ b/exec.c @@ -2938,8 +2938,8 @@ int cpu_physical_memory_do_io(target_phys_addr_t addr, uint8_t *buf, int l, int return l; } -void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, - int len, int is_write) +static void tcg_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, + int len, int is_write) { int l; uint8_t *ptr; @@ -2997,6 +2997,15 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, } } +void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, + int len, int is_write) +{ + if (kvm_enabled()) + kvm_cpu_physical_memory_rw(addr, buf, len, is_write); + else + tcg_physical_memory_rw(addr, buf, len, is_write); +} + /* 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) diff --git a/kvm-all.c b/kvm-all.c index 11034df..15eb326 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -540,7 +540,7 @@ void kvm_set_phys_mem(target_phys_addr_t start_addr, mem = kvm_lookup_slot(s, start_addr); if (mem) { - if ((flags == IO_MEM_UNASSIGNED) || (flags >= TLB_MMIO)) { + if ((flags == IO_MEM_UNASSIGNED)) { mem->memory_size = 0; mem->start_addr = start_addr; mem->phys_offset = 0; @@ -559,6 +559,8 @@ void kvm_set_phys_mem(target_phys_addr_t start_addr, mem->phys_offset) return; + if ((phys_offset & ~TARGET_PAGE_MASK) != 0) + return; /* unregister whole slot */ memcpy(&slot, mem, sizeof(slot)); mem->memory_size = 0; @@ -588,16 +590,21 @@ void kvm_set_phys_mem(target_phys_addr_t start_addr, } } /* KVM does not need to know about this memory */ - if (flags >= IO_MEM_UNASSIGNED) + if (flags == IO_MEM_UNASSIGNED) return; - mem = kvm_alloc_slot(s); + if (!mem) + mem = kvm_alloc_slot(s); mem->memory_size = size; mem->start_addr = start_addr; mem->phys_offset = phys_offset; mem->flags = 0; - kvm_set_user_memory_region(s, mem); + if (flags < TLB_MMIO) + kvm_set_user_memory_region(s, mem); + else{ + mem->phys_offset = flags; + } /* FIXME deal with errors */ } @@ -663,3 +670,27 @@ int kvm_has_sync_mmu(void) return 0; } + +void kvm_cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, + int len, int is_write) +{ + KVMSlot *mem; + KVMState *s = kvm_state; + int l; + + mem = kvm_lookup_slot(s, addr); + if (!mem) + return; + + if ((mem->phys_offset & ~TARGET_PAGE_MASK) >= TLB_MMIO) { + l = 0; + while (len > l) + l += cpu_physical_memory_do_io(addr + l, buf + l, len - l, is_write, mem->phys_offset); + } else { + uint8_t *uaddr = phys_ram_base + mem->phys_offset + (addr - mem->start_addr); + if (!is_write) + memcpy(buf, uaddr, len); + else + memcpy(uaddr, buf, len); + } +} diff --git a/kvm.h b/kvm.h index efce145..e3e9ca0 100644 --- a/kvm.h +++ b/kvm.h @@ -49,6 +49,8 @@ int kvm_has_sync_mmu(void); int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size); int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size); +void kvm_cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, + int len, int is_write); /* internal API */ struct KVMState; -- 1.5.6.5 -- 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
