This patch is userspace part of the "batch writes to MMIO" patch.
It defines delayed MMIO zone using kvm_set_mmio() (for VGA and e1000). It empties the ring buffer and process the MMIO accesses. Signed-off-by: Laurent Vivier <[EMAIL PROTECTED]> --- libkvm/libkvm-x86.c | 18 ++++++++++++++++++ libkvm/libkvm.c | 13 +++++++++++++ libkvm/libkvm.h | 2 ++ qemu/hw/cirrus_vga.c | 2 ++ qemu/hw/e1000.c | 8 ++++++++ qemu/hw/vga.c | 4 ++++ qemu/qemu-kvm.c | 6 ++++++ qemu/qemu-kvm.h | 2 ++ 8 files changed, 55 insertions(+), 0 deletions(-) diff --git a/libkvm/libkvm-x86.c b/libkvm/libkvm-x86.c index d46fdcc..911e079 100644 --- a/libkvm/libkvm-x86.c +++ b/libkvm/libkvm-x86.c @@ -391,6 +391,24 @@ int kvm_set_pit(kvm_context_t kvm, struct kvm_pit_state *s) #endif +int kvm_set_mmio(kvm_context_t kvm, + uint8_t is_delayed, uint64_t addr, uint32_t size) +{ + struct kvm_mmio_zone zone; + int r; + + zone.is_delayed = is_delayed; + zone.addr = addr; + zone.size = size; + + r = ioctl(kvm->vm_fd, KVM_SET_MMIO, &zone); + if (r == -1) { + r = -errno; + perror("kvm_set_mmio"); + } + return r; +} + void kvm_show_code(kvm_context_t kvm, int vcpu) { #define SHOW_CODE_LEN 50 diff --git a/libkvm/libkvm.c b/libkvm/libkvm.c index d1e95a4..b891630 100644 --- a/libkvm/libkvm.c +++ b/libkvm/libkvm.c @@ -861,6 +861,9 @@ int kvm_run(kvm_context_t kvm, int vcpu) int r; int fd = kvm->vcpu_fd[vcpu]; struct kvm_run *run = kvm->run[vcpu]; +#if defined(__x86_64__) || defined(__i386__) + struct kvm_batch *batch = (void *)run + 2 * PAGE_SIZE; +#endif again: if (!kvm->irqchip_in_kernel) @@ -879,6 +882,16 @@ again: post_kvm_run(kvm, vcpu); +#if defined(__x86_64__) || defined(__i386__) + while (batch->first != batch->last) { + kvm->callbacks->mmio_write(kvm->opaque, + batch->mmio[batch->first].phys_addr, + &batch->mmio[batch->first].data[0], + batch->mmio[batch->first].len); + batch->first = (batch->first + 1) % KVM_MAX_BATCH; + } +#endif + if (r == -1) { r = handle_io_window(kvm); goto more; diff --git a/libkvm/libkvm.h b/libkvm/libkvm.h index 31c0d59..1f453e1 100644 --- a/libkvm/libkvm.h +++ b/libkvm/libkvm.h @@ -448,6 +448,8 @@ int kvm_get_dirty_pages_range(kvm_context_t kvm, unsigned long phys_addr, unsigned long end_addr, void *buf, void*opaque, int (*cb)(unsigned long start, unsigned long len, void*bitmap, void *opaque)); +int kvm_set_mmio(kvm_context_t kvm, + uint8_t is_delayed, uint64_t addr, uint32_t size); /*! * \brief Create a memory alias diff --git a/qemu/hw/cirrus_vga.c b/qemu/hw/cirrus_vga.c index 2c4aeec..4ef8085 100644 --- a/qemu/hw/cirrus_vga.c +++ b/qemu/hw/cirrus_vga.c @@ -3291,6 +3291,8 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci) cirrus_vga_mem_write, s); cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, vga_io_memory); + if (kvm_enabled()) + qemu_kvm_set_mmio(1, isa_mem_base + 0x000a0000, 0x20000); s->sr[0x06] = 0x0f; if (device_id == CIRRUS_ID_CLGD5446) { diff --git a/qemu/hw/e1000.c b/qemu/hw/e1000.c index 0728539..d223631 100644 --- a/qemu/hw/e1000.c +++ b/qemu/hw/e1000.c @@ -26,6 +26,7 @@ #include "hw.h" #include "pci.h" #include "net.h" +#include "qemu-kvm.h" #include "e1000_hw.h" @@ -938,6 +939,13 @@ e1000_mmio_map(PCIDevice *pci_dev, int region_num, d->mmio_base = addr; cpu_register_physical_memory(addr, PNPMMIO_SIZE, d->mmio_index); + + if (kvm_enabled()) { + qemu_kvm_set_mmio(1, addr, PNPMMIO_SIZE); + qemu_kvm_set_mmio(0, addr + E1000_TCTL, 4); + qemu_kvm_set_mmio(0, addr + E1000_TDT, 4); + qemu_kvm_set_mmio(0, addr + E1000_ICR, 4); + } } static int diff --git a/qemu/hw/vga.c b/qemu/hw/vga.c index 3a49573..844c2a7 100644 --- a/qemu/hw/vga.c +++ b/qemu/hw/vga.c @@ -2257,6 +2257,8 @@ void vga_init(VGAState *s) vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s); cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000, vga_io_memory); + if (kvm_enabled()) + qemu_kvm_set_mmio(1, isa_mem_base + 0x000a0000, 0x20000); } /* Memory mapped interface */ @@ -2332,6 +2334,8 @@ static void vga_mm_init(VGAState *s, target_phys_addr_t vram_base, cpu_register_physical_memory(ctrl_base, 0x100000, s_ioport_ctrl); s->bank_offset = 0; cpu_register_physical_memory(vram_base + 0x000a0000, 0x20000, vga_io_memory); + if (kvm_enabled()) + qemu_kvm_set_mmio(1, vram_base + 0x000a0000, 0x20000); } int isa_vga_init(DisplayState *ds, uint8_t *vga_ram_base, diff --git a/qemu/qemu-kvm.c b/qemu/qemu-kvm.c index e522269..9f03ab1 100644 --- a/qemu/qemu-kvm.c +++ b/qemu/qemu-kvm.c @@ -955,3 +955,9 @@ void kvm_mutex_lock(void) pthread_mutex_lock(&qemu_mutex); cpu_single_env = NULL; } + +int qemu_kvm_set_mmio(int is_delayed, + target_phys_addr_t addr, unsigned int size) +{ + return kvm_set_mmio(kvm_context, is_delayed, addr, size); +} diff --git a/qemu/qemu-kvm.h b/qemu/qemu-kvm.h index 21606e9..37d4d11 100644 --- a/qemu/qemu-kvm.h +++ b/qemu/qemu-kvm.h @@ -75,6 +75,8 @@ int handle_tpr_access(void *opaque, int vcpu, void kvm_tpr_vcpu_start(CPUState *env); int qemu_kvm_get_dirty_pages(unsigned long phys_addr, void *buf); +int qemu_kvm_set_mmio(int is_delayed, + target_phys_addr_t addr, unsigned int size); void qemu_kvm_system_reset_request(void); -- 1.5.2.4 ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ _______________________________________________ kvm-devel mailing list kvm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-devel