diff options
author | Avi Kivity <avi@redhat.com> | 2010-01-19 05:51:22 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-05-11 07:56:58 -0400 |
commit | 70252a1053636c35776d6bc843dd3b260d9d6de1 (patch) | |
tree | 7cd2d992be2673f056521ec273c6973c25027bc0 /arch/x86/kvm/x86.c | |
parent | 1499e54af03ae51a937c59035bc86002deae0572 (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.c | 58 |
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) | |||
3596 | static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len, | 3596 | static 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 | ||
3606 | static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v) | 3617 | static 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 | ||
3615 | static void kvm_set_segment(struct kvm_vcpu *vcpu, | 3638 | static 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; |