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 /arch/x86/kvm/x86.c | |
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>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 34 |
1 files changed, 25 insertions, 9 deletions
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); |