aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2010-01-20 05:01:20 -0500
committerAvi Kivity <avi@redhat.com>2011-05-11 07:56:58 -0400
commitcef4dea07f6720b36cc93e18a2e68be4bdb71a92 (patch)
treef6c67df1a54a2770d23086446807ca62f964c2e1
parent5287f194bf0d7062d6d99b725366202556f03e28 (diff)
KVM: 16-byte mmio support
Since sse instructions can issue 16-byte mmios, we need to support them. We can't increase the kvm_run mmio buffer size to 16 bytes without breaking compatibility, so instead we break the large mmios into two smaller 8-byte ones. Since the bus is 64-bit we aren't breaking any atomicity guarantees. Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--arch/x86/include/asm/kvm_host.h1
-rw-r--r--arch/x86/kvm/x86.c34
-rw-r--r--include/linux/kvm_host.h7
3 files changed, 32 insertions, 10 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 35f81b110260..e820c6339b8b 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -30,6 +30,7 @@
30#define KVM_MEMORY_SLOTS 32 30#define KVM_MEMORY_SLOTS 32
31/* memory slots that does not exposed to userspace */ 31/* memory slots that does not exposed to userspace */
32#define KVM_PRIVATE_MEM_SLOTS 4 32#define KVM_PRIVATE_MEM_SLOTS 4
33#define KVM_MMIO_SIZE 16
33 34
34#define KVM_PIO_PAGE_OFFSET 1 35#define KVM_PIO_PAGE_OFFSET 1
35#define KVM_COALESCED_MMIO_PAGE_OFFSET 2 36#define KVM_COALESCED_MMIO_PAGE_OFFSET 2
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index bb6b9d3f5e93..11d692c7018d 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3833,8 +3833,10 @@ mmio:
3833 vcpu->mmio_needed = 1; 3833 vcpu->mmio_needed = 1;
3834 vcpu->run->exit_reason = KVM_EXIT_MMIO; 3834 vcpu->run->exit_reason = KVM_EXIT_MMIO;
3835 vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa; 3835 vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa;
3836 vcpu->run->mmio.len = vcpu->mmio_size = bytes; 3836 vcpu->mmio_size = bytes;
3837 vcpu->run->mmio.len = min(vcpu->mmio_size, 8);
3837 vcpu->run->mmio.is_write = vcpu->mmio_is_write = 0; 3838 vcpu->run->mmio.is_write = vcpu->mmio_is_write = 0;
3839 vcpu->mmio_index = 0;
3838 3840
3839 return X86EMUL_IO_NEEDED; 3841 return X86EMUL_IO_NEEDED;
3840} 3842}
@@ -3886,11 +3888,14 @@ mmio:
3886 val += handled; 3888 val += handled;
3887 3889
3888 vcpu->mmio_needed = 1; 3890 vcpu->mmio_needed = 1;
3891 memcpy(vcpu->mmio_data, val, bytes);
3889 vcpu->run->exit_reason = KVM_EXIT_MMIO; 3892 vcpu->run->exit_reason = KVM_EXIT_MMIO;
3890 vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa; 3893 vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa;
3891 vcpu->run->mmio.len = vcpu->mmio_size = bytes; 3894 vcpu->mmio_size = bytes;
3895 vcpu->run->mmio.len = min(vcpu->mmio_size, 8);
3892 vcpu->run->mmio.is_write = vcpu->mmio_is_write = 1; 3896 vcpu->run->mmio.is_write = vcpu->mmio_is_write = 1;
3893 memcpy(vcpu->run->mmio.data, val, bytes); 3897 memcpy(vcpu->run->mmio.data, vcpu->mmio_data, 8);
3898 vcpu->mmio_index = 0;
3894 3899
3895 return X86EMUL_CONTINUE; 3900 return X86EMUL_CONTINUE;
3896} 3901}
@@ -4498,11 +4503,9 @@ restart:
4498 if (!vcpu->arch.pio.in) 4503 if (!vcpu->arch.pio.in)
4499 vcpu->arch.pio.count = 0; 4504 vcpu->arch.pio.count = 0;
4500 r = EMULATE_DO_MMIO; 4505 r = EMULATE_DO_MMIO;
4501 } else if (vcpu->mmio_needed) { 4506 } else if (vcpu->mmio_needed)
4502 if (vcpu->mmio_is_write)
4503 vcpu->mmio_needed = 0;
4504 r = EMULATE_DO_MMIO; 4507 r = EMULATE_DO_MMIO;
4505 } else if (r == EMULATION_RESTART) 4508 else if (r == EMULATION_RESTART)
4506 goto restart; 4509 goto restart;
4507 else 4510 else
4508 r = EMULATE_DONE; 4511 r = EMULATE_DONE;
@@ -5450,9 +5453,22 @@ static int complete_mmio(struct kvm_vcpu *vcpu)
5450 return 1; 5453 return 1;
5451 5454
5452 if (vcpu->mmio_needed) { 5455 if (vcpu->mmio_needed) {
5453 memcpy(vcpu->mmio_data, run->mmio.data, 8);
5454 vcpu->mmio_read_completed = 1;
5455 vcpu->mmio_needed = 0; 5456 vcpu->mmio_needed = 0;
5457 if (!vcpu->mmio_is_write)
5458 memcpy(vcpu->mmio_data, run->mmio.data, 8);
5459 vcpu->mmio_index += 8;
5460 if (vcpu->mmio_index < vcpu->mmio_size) {
5461 run->exit_reason = KVM_EXIT_MMIO;
5462 run->mmio.phys_addr = vcpu->mmio_phys_addr + vcpu->mmio_index;
5463 memcpy(run->mmio.data, vcpu->mmio_data + vcpu->mmio_index, 8);
5464 run->mmio.len = min(vcpu->mmio_size - vcpu->mmio_index, 8);
5465 run->mmio.is_write = vcpu->mmio_is_write;
5466 vcpu->mmio_needed = 1;
5467 return 0;
5468 }
5469 if (vcpu->mmio_is_write)
5470 return 1;
5471 vcpu->mmio_read_completed = 1;
5456 } 5472 }
5457 vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); 5473 vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
5458 r = emulate_instruction(vcpu, EMULTYPE_NO_DECODE); 5474 r = emulate_instruction(vcpu, EMULTYPE_NO_DECODE);
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 7ca831e55186..d1f507567068 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -27,6 +27,10 @@
27 27
28#include <asm/kvm_host.h> 28#include <asm/kvm_host.h>
29 29
30#ifndef KVM_MMIO_SIZE
31#define KVM_MMIO_SIZE 8
32#endif
33
30/* 34/*
31 * vcpu->requests bit members 35 * vcpu->requests bit members
32 */ 36 */
@@ -132,7 +136,8 @@ struct kvm_vcpu {
132 int mmio_read_completed; 136 int mmio_read_completed;
133 int mmio_is_write; 137 int mmio_is_write;
134 int mmio_size; 138 int mmio_size;
135 unsigned char mmio_data[8]; 139 int mmio_index;
140 unsigned char mmio_data[KVM_MMIO_SIZE];
136 gpa_t mmio_phys_addr; 141 gpa_t mmio_phys_addr;
137#endif 142#endif
138 143