Implement data cache maintenance coherency functions, by using FLUSH_DCACHE_GPA ioctl. Introduce kvm_arm_maintain_cache_coherency() for flushing the data cache if necessary, a very simple logic is implemented to reduce number of flushes due to reads. Two wrapping functions are exposed, for easier usage. Signed-off-by: Jérémy Fanguède <j.fanguede@xxxxxxxxxxxxxxxxxxxxxx> --- include/sysemu/kvm.h | 3 +++ stubs/kvm.c | 9 +++++++++ target-arm/kvm.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 63 insertions(+) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 197e6c0..986f365 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -451,4 +451,7 @@ int kvm_set_one_reg(CPUState *cs, uint64_t id, void *source); * Returns: 0 on success, or a negative errno on failure. */ int kvm_get_one_reg(CPUState *cs, uint64_t id, void *target); + +void kvm_arch_cache_flush_needed(hwaddr addr, int len, bool is_write); +void kvm_arch_cache_coherency_pre_run(void); #endif diff --git a/stubs/kvm.c b/stubs/kvm.c index e7c60b6..8ed5380 100644 --- a/stubs/kvm.c +++ b/stubs/kvm.c @@ -5,3 +5,12 @@ int kvm_arch_irqchip_create(KVMState *s) { return 0; } + + +void kvm_arch_cache_flush_needed(hwaddr addr, int len, bool is_write) +{ +} + +void kvm_arch_cache_coherency_pre_run(void) +{ +} diff --git a/target-arm/kvm.c b/target-arm/kvm.c index fdd9ba3..548dae2 100644 --- a/target-arm/kvm.c +++ b/target-arm/kvm.c @@ -598,3 +598,54 @@ int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, { return 0; } + +static void kvm_arm_flush_cache_addr(hwaddr addr, int len) +{ + int ret; + struct kvm_mem_addr mem_addr; + mem_addr.addr = addr; + mem_addr.len = len; + ret = kvm_vm_ioctl(kvm_state, KVM_FLUSH_DCACHE_GPA, &mem_addr); + if (ret) { + fprintf(stderr, "error: Failed to flush CPU caches %d\n", ret); + } +} + +static void kvm_arm_maintain_cache_coherency(hwaddr addr, int len, + bool enter_guest, bool is_write) +{ + static hwaddr prev_addr; + static int prev_len; + hwaddr end_line, prev_end_line; + + if (enter_guest) { + /* We will return to the guest after that, restore the default + configuration */ + prev_addr = 0x0; + return; + } + + /* Assume the minimal CPU cache line is 32 B */ + end_line = (addr + len) & ~0x1f; + prev_end_line = (prev_addr + prev_len) & ~0x1f; + + /* Don't flush two times in a row the same line" + Always flush on a write */ + if ((prev_addr & ~0x1f) != (addr & ~0x1f) + || (prev_end_line < end_line) + || is_write) { + kvm_arm_flush_cache_addr(addr, len); + prev_addr = addr; + prev_len = len; + } +} + +void kvm_arch_cache_flush_needed(hwaddr addr, int len, bool is_write) +{ + kvm_arm_maintain_cache_coherency(addr, len, false, is_write); +} + +void kvm_arch_cache_coherency_pre_run(void) +{ + kvm_arm_maintain_cache_coherency(0, 0, true, false); +} -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html