aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/x86.c
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 /arch/x86/kvm/x86.c
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>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r--arch/x86/kvm/x86.c34
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);