|
From: Laurent V. <Lau...@bu...> - 2008-05-15 13:51:39
|
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 <Lau...@bu...>
---
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
|