aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2012-04-18 19:22:47 +0300
committerMarcelo Tosatti <mtosatti@redhat.com>2012-04-19 20:35:07 -0300
commitf78146b0f9230765c6315b2e14f56112513389ad (patch)
tree2e6780f2989c73c1bf214a5728514c1dc8e15f09 /include
parenteac0556750e727ff39144a9a9e59d5ccf1fc0e2a (diff)
KVM: Fix page-crossing MMIO
MMIO that are split across a page boundary are currently broken - the code does not expect to be aborted by the exit to userspace for the first MMIO fragment. This patch fixes the problem by generalizing the current code for handling 16-byte MMIOs to handle a number of "fragments", and changes the MMIO code to create those fragments. Signed-off-by: Avi Kivity <avi@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'include')
-rw-r--r--include/linux/kvm_host.h31
1 files changed, 27 insertions, 4 deletions
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index a2d00b1bbf54..186ffab0b9f0 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -35,6 +35,20 @@
#endif
/*
+ * If we support unaligned MMIO, at most one fragment will be split into two:
+ */
+#ifdef KVM_UNALIGNED_MMIO
+# define KVM_EXTRA_MMIO_FRAGMENTS 1
+#else
+# define KVM_EXTRA_MMIO_FRAGMENTS 0
+#endif
+
+#define KVM_USER_MMIO_SIZE 8
+
+#define KVM_MAX_MMIO_FRAGMENTS \
+ (KVM_MMIO_SIZE / KVM_USER_MMIO_SIZE + KVM_EXTRA_MMIO_FRAGMENTS)
+
+/*
* vcpu->requests bit members
*/
#define KVM_REQ_TLB_FLUSH 0
@@ -117,6 +131,16 @@ enum {
EXITING_GUEST_MODE
};
+/*
+ * Sometimes a large or cross-page mmio needs to be broken up into separate
+ * exits for userspace servicing.
+ */
+struct kvm_mmio_fragment {
+ gpa_t gpa;
+ void *data;
+ unsigned len;
+};
+
struct kvm_vcpu {
struct kvm *kvm;
#ifdef CONFIG_PREEMPT_NOTIFIERS
@@ -144,10 +168,9 @@ struct kvm_vcpu {
int mmio_needed;
int mmio_read_completed;
int mmio_is_write;
- int mmio_size;
- int mmio_index;
- unsigned char mmio_data[KVM_MMIO_SIZE];
- gpa_t mmio_phys_addr;
+ int mmio_cur_fragment;
+ int mmio_nr_fragments;
+ struct kvm_mmio_fragment mmio_fragments[KVM_MAX_MMIO_FRAGMENTS];
#endif
#ifdef CONFIG_KVM_ASYNC_PF