diff options
author | Avi Kivity <avi@redhat.com> | 2010-01-20 05:01:20 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-05-11 07:56:58 -0400 |
commit | cef4dea07f6720b36cc93e18a2e68be4bdb71a92 (patch) | |
tree | f6c67df1a54a2770d23086446807ca62f964c2e1 | |
parent | 5287f194bf0d7062d6d99b725366202556f03e28 (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.h | 1 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 34 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 7 |
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 | ||