From patchwork Mon Jan 25 07:46:44 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sheng Yang X-Patchwork-Id: 75026 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.2) with ESMTP id o0P7la4O011715 for ; Mon, 25 Jan 2010 07:47:36 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752027Ab0AYHre (ORCPT ); Mon, 25 Jan 2010 02:47:34 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752008Ab0AYHre (ORCPT ); Mon, 25 Jan 2010 02:47:34 -0500 Received: from mga03.intel.com ([143.182.124.21]:10315 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751868Ab0AYHre (ORCPT ); Mon, 25 Jan 2010 02:47:34 -0500 Received: from azsmga001.ch.intel.com ([10.2.17.19]) by azsmga101.ch.intel.com with ESMTP; 24 Jan 2010 23:47:33 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="4.47,316,1257148800"; d="scan'208";a="236386958" Received: from syang10-desktop.sh.intel.com (HELO syang10-desktop) ([10.239.36.165]) by azsmga001.ch.intel.com with ESMTP; 24 Jan 2010 23:47:32 -0800 Received: from yasker by syang10-desktop with local (Exim 4.69) (envelope-from ) id 1NZJeo-0003WK-8r; Mon, 25 Jan 2010 15:46:46 +0800 From: Sheng Yang To: Avi Kivity , Marcelo Tosatti Cc: kvm@vger.kernel.org, Sheng Yang Subject: [PATCH] kvm: Flush coalesced MMIO buffer periodly Date: Mon, 25 Jan 2010 15:46:44 +0800 Message-Id: <1264405604-13506-1-git-send-email-sheng@linux.intel.com> X-Mailer: git-send-email 1.6.3.3 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org diff --git a/cpu-all.h b/cpu-all.h index 8ed76c7..51effc0 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -916,6 +916,8 @@ void qemu_register_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size); void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size); +void qemu_flush_coalesced_mmio_buffer(void); + /*******************************************/ /* host CPU ticks (if available) */ diff --git a/exec.c b/exec.c index 99e88e1..40c01a1 100644 --- a/exec.c +++ b/exec.c @@ -2424,6 +2424,12 @@ void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size) kvm_uncoalesce_mmio_region(addr, size); } +void qemu_flush_coalesced_mmio_buffer(void) +{ + if (kvm_enabled()) + kvm_flush_coalesced_mmio_buffer(); +} + #ifdef __linux__ #include diff --git a/kvm-all.c b/kvm-all.c index 0423fff..3d9fcc0 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -25,6 +25,9 @@ #include "hw/hw.h" #include "gdbstub.h" #include "kvm.h" +#ifndef KVM_UPSTREAM +#include "libkvm.h" +#endif #ifdef KVM_UPSTREAM /* KVM uses PAGE_SIZE in it's definition of COALESCED_MMIO_MAX */ @@ -385,6 +388,23 @@ int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size) return ret; } +void kvm_flush_coalesced_mmio_buffer(void) +{ +#ifdef KVM_CAP_COALESCED_MMIO + if (kvm_state->coalesced_mmio_ring) { + struct kvm_coalesced_mmio_ring *ring = + kvm_state->coalesced_mmio_ring; + while (ring->first != ring->last) { + cpu_physical_memory_rw(ring->coalesced_mmio[ring->first].phys_addr, + &ring->coalesced_mmio[ring->first].data[0], + ring->coalesced_mmio[ring->first].len, 1); + smp_wmb(); + ring->first = (ring->first + 1) % KVM_COALESCED_MMIO_MAX; + } + } +#endif +} + int kvm_check_extension(KVMState *s, unsigned int extension) { int ret; diff --git a/qemu-kvm.c b/qemu-kvm.c index 599c3d6..70d7658 100644 --- a/qemu-kvm.c +++ b/qemu-kvm.c @@ -463,6 +463,12 @@ static void kvm_create_vcpu(CPUState *env, int id) goto err_fd; } +#ifdef KVM_CAP_COALESCED_MMIO + if (kvm_state->coalesced_mmio && !kvm_state->coalesced_mmio_ring) + kvm_state->coalesced_mmio_ring = (void *) env->kvm_run + + kvm_state->coalesced_mmio * PAGE_SIZE; +#endif + return; err_fd: close(env->kvm_fd); @@ -927,8 +933,7 @@ int kvm_run(CPUState *env) #if defined(KVM_CAP_COALESCED_MMIO) if (kvm_state->coalesced_mmio) { - struct kvm_coalesced_mmio_ring *ring = - (void *) run + kvm_state->coalesced_mmio * PAGE_SIZE; + struct kvm_coalesced_mmio_ring *ring = kvm_state->coalesced_mmio_ring; while (ring->first != ring->last) { cpu_physical_memory_rw(ring->coalesced_mmio[ring->first].phys_addr, &ring->coalesced_mmio[ring->first].data[0], diff --git a/qemu-kvm.h b/qemu-kvm.h index 6b3e5a1..066e1c0 100644 --- a/qemu-kvm.h +++ b/qemu-kvm.h @@ -435,6 +435,7 @@ int kvm_register_coalesced_mmio(kvm_context_t kvm, uint64_t addr, uint32_t size); int kvm_unregister_coalesced_mmio(kvm_context_t kvm, uint64_t addr, uint32_t size); +void kvm_flush_coalesced_mmio_buffer(void); /*! * \brief Create a memory alias @@ -1144,6 +1145,7 @@ typedef struct KVMState { int fd; int vmfd; int coalesced_mmio; + struct kvm_coalesced_mmio_ring *coalesced_mmio_ring; int broken_set_mem_region; int migration_log; int vcpu_events; diff --git a/vl.c b/vl.c index 9edea10..f39ad56 100644 --- a/vl.c +++ b/vl.c @@ -3227,6 +3227,7 @@ static void gui_update(void *opaque) DisplayState *ds = opaque; DisplayChangeListener *dcl = ds->listeners; + qemu_flush_coalesced_mmio_buffer(); dpy_refresh(ds); while (dcl != NULL) { @@ -3242,6 +3243,7 @@ static void nographic_update(void *opaque) { uint64_t interval = GUI_REFRESH_INTERVAL; + qemu_flush_coalesced_mmio_buffer(); qemu_mod_timer(nographic_timer, interval + qemu_get_clock(rt_clock)); }