aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/x86.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2010-01-19 05:51:22 -0500
committerAvi Kivity <avi@redhat.com>2011-05-11 07:56:58 -0400
commit70252a1053636c35776d6bc843dd3b260d9d6de1 (patch)
tree7cd2d992be2673f056521ec273c6973c25027bc0 /arch/x86/kvm/x86.c
parent1499e54af03ae51a937c59035bc86002deae0572 (diff)
KVM: extend in-kernel mmio to handle >8 byte transactions
Needed for coalesced mmio using sse. Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r--arch/x86/kvm/x86.c58
1 files changed, 46 insertions, 12 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 692c70d6fd02..3b234c18b635 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3596,20 +3596,43 @@ static void kvm_init_msr_list(void)
3596static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len, 3596static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len,
3597 const void *v) 3597 const void *v)
3598{ 3598{
3599 if (vcpu->arch.apic && 3599 int handled = 0;
3600 !kvm_iodevice_write(&vcpu->arch.apic->dev, addr, len, v)) 3600 int n;
3601 return 0; 3601
3602 do {
3603 n = min(len, 8);
3604 if (!(vcpu->arch.apic &&
3605 !kvm_iodevice_write(&vcpu->arch.apic->dev, addr, n, v))
3606 && kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, addr, n, v))
3607 break;
3608 handled += n;
3609 addr += n;
3610 len -= n;
3611 v += n;
3612 } while (len);
3602 3613
3603 return kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, addr, len, v); 3614 return handled;
3604} 3615}
3605 3616
3606static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v) 3617static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v)
3607{ 3618{
3608 if (vcpu->arch.apic && 3619 int handled = 0;
3609 !kvm_iodevice_read(&vcpu->arch.apic->dev, addr, len, v)) 3620 int n;
3610 return 0; 3621
3622 do {
3623 n = min(len, 8);
3624 if (!(vcpu->arch.apic &&
3625 !kvm_iodevice_read(&vcpu->arch.apic->dev, addr, n, v))
3626 && kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, addr, n, v))
3627 break;
3628 trace_kvm_mmio(KVM_TRACE_MMIO_READ, n, addr, *(u64 *)v);
3629 handled += n;
3630 addr += n;
3631 len -= n;
3632 v += n;
3633 } while (len);
3611 3634
3612 return kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, addr, len, v); 3635 return handled;
3613} 3636}
3614 3637
3615static void kvm_set_segment(struct kvm_vcpu *vcpu, 3638static void kvm_set_segment(struct kvm_vcpu *vcpu,
@@ -3769,6 +3792,7 @@ static int emulator_read_emulated(unsigned long addr,
3769 struct kvm_vcpu *vcpu) 3792 struct kvm_vcpu *vcpu)
3770{ 3793{
3771 gpa_t gpa; 3794 gpa_t gpa;
3795 int handled;
3772 3796
3773 if (vcpu->mmio_read_completed) { 3797 if (vcpu->mmio_read_completed) {
3774 memcpy(val, vcpu->mmio_data, bytes); 3798 memcpy(val, vcpu->mmio_data, bytes);
@@ -3795,10 +3819,14 @@ mmio:
3795 /* 3819 /*
3796 * Is this MMIO handled locally? 3820 * Is this MMIO handled locally?
3797 */ 3821 */
3798 if (!vcpu_mmio_read(vcpu, gpa, bytes, val)) { 3822 handled = vcpu_mmio_read(vcpu, gpa, bytes, val);
3799 trace_kvm_mmio(KVM_TRACE_MMIO_READ, bytes, gpa, *(u64 *)val); 3823
3824 if (handled == bytes)
3800 return X86EMUL_CONTINUE; 3825 return X86EMUL_CONTINUE;
3801 } 3826
3827 gpa += handled;
3828 bytes -= handled;
3829 val += handled;
3802 3830
3803 trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, 0); 3831 trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, 0);
3804 3832
@@ -3830,6 +3858,7 @@ static int emulator_write_emulated_onepage(unsigned long addr,
3830 struct kvm_vcpu *vcpu) 3858 struct kvm_vcpu *vcpu)
3831{ 3859{
3832 gpa_t gpa; 3860 gpa_t gpa;
3861 int handled;
3833 3862
3834 gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, exception); 3863 gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, exception);
3835 3864
@@ -3848,9 +3877,14 @@ mmio:
3848 /* 3877 /*
3849 * Is this MMIO handled locally? 3878 * Is this MMIO handled locally?
3850 */ 3879 */
3851 if (!vcpu_mmio_write(vcpu, gpa, bytes, val)) 3880 handled = vcpu_mmio_write(vcpu, gpa, bytes, val);
3881 if (handled == bytes)
3852 return X86EMUL_CONTINUE; 3882 return X86EMUL_CONTINUE;
3853 3883
3884 gpa += handled;
3885 bytes -= handled;
3886 val += handled;
3887
3854 vcpu->mmio_needed = 1; 3888 vcpu->mmio_needed = 1;
3855 vcpu->run->exit_reason = KVM_EXIT_MMIO; 3889 vcpu->run->exit_reason = KVM_EXIT_MMIO;
3856 vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa; 3890 vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa;