static int vcpu_mmio_write(struct kvm_vcpu *vcpu, gpa_t addr, int len,
                           const void *v)
 {
-       if (vcpu->arch.apic &&
-           !kvm_iodevice_write(&vcpu->arch.apic->dev, addr, len, v))
-               return 0;
+       int handled = 0;
+       int n;
+
+       do {
+               n = min(len, 8);
+               if (!(vcpu->arch.apic &&
+                     !kvm_iodevice_write(&vcpu->arch.apic->dev, addr, n, v))
+                   && kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, addr, n, v))
+                       break;
+               handled += n;
+               addr += n;
+               len -= n;
+               v += n;
+       } while (len);
 
-       return kvm_io_bus_write(vcpu->kvm, KVM_MMIO_BUS, addr, len, v);
+       return handled;
 }
 
 static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v)
 {
-       if (vcpu->arch.apic &&
-           !kvm_iodevice_read(&vcpu->arch.apic->dev, addr, len, v))
-               return 0;
+       int handled = 0;
+       int n;
+
+       do {
+               n = min(len, 8);
+               if (!(vcpu->arch.apic &&
+                     !kvm_iodevice_read(&vcpu->arch.apic->dev, addr, n, v))
+                   && kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, addr, n, v))
+                       break;
+               trace_kvm_mmio(KVM_TRACE_MMIO_READ, n, addr, *(u64 *)v);
+               handled += n;
+               addr += n;
+               len -= n;
+               v += n;
+       } while (len);
 
-       return kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, addr, len, v);
+       return handled;
 }
 
 static void kvm_set_segment(struct kvm_vcpu *vcpu,
                                  struct kvm_vcpu *vcpu)
 {
        gpa_t                 gpa;
+       int handled;
 
        if (vcpu->mmio_read_completed) {
                memcpy(val, vcpu->mmio_data, bytes);
        /*
         * Is this MMIO handled locally?
         */
-       if (!vcpu_mmio_read(vcpu, gpa, bytes, val)) {
-               trace_kvm_mmio(KVM_TRACE_MMIO_READ, bytes, gpa, *(u64 *)val);
+       handled = vcpu_mmio_read(vcpu, gpa, bytes, val);
+
+       if (handled == bytes)
                return X86EMUL_CONTINUE;
-       }
+
+       gpa += handled;
+       bytes -= handled;
+       val += handled;
 
        trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, 0);
 
                                           struct kvm_vcpu *vcpu)
 {
        gpa_t                 gpa;
+       int handled;
 
        gpa = kvm_mmu_gva_to_gpa_write(vcpu, addr, exception);
 
        /*
         * Is this MMIO handled locally?
         */
-       if (!vcpu_mmio_write(vcpu, gpa, bytes, val))
+       handled = vcpu_mmio_write(vcpu, gpa, bytes, val);
+       if (handled == bytes)
                return X86EMUL_CONTINUE;
 
+       gpa += handled;
+       bytes -= handled;
+       val += handled;
+
        vcpu->mmio_needed = 1;
        vcpu->run->exit_reason = KVM_EXIT_MMIO;
        vcpu->run->mmio.phys_addr = vcpu->mmio_phys_addr = gpa;