}
 
 static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu,
-                                       gpa_t addr)
+                                       gpa_t addr, int len, int is_write)
 {
        struct kvm_io_device *dev;
 
-       dev = kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, addr);
+       dev = kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, addr, len, is_write);
 
        return dev;
 }
        kvm_run->exit_reason = KVM_EXIT_MMIO;
        return 0;
 mmio:
-       mmio_dev = vcpu_find_mmio_dev(vcpu, p->addr);
+       mmio_dev = vcpu_find_mmio_dev(vcpu, p->addr, p->size, !p->dir);
        if (mmio_dev) {
                if (!p->dir)
                        kvm_iodevice_write(mmio_dev, p->addr, p->size,
 
        mutex_unlock(&pit_state->lock);
 }
 
-static int pit_in_range(struct kvm_io_device *this, gpa_t addr)
+static int pit_in_range(struct kvm_io_device *this, gpa_t addr,
+                       int len, int is_write)
 {
        return ((addr >= KVM_PIT_BASE_ADDRESS) &&
                (addr < KVM_PIT_BASE_ADDRESS + KVM_PIT_MEM_LENGTH));
        mutex_unlock(&pit_state->lock);
 }
 
-static int speaker_in_range(struct kvm_io_device *this, gpa_t addr)
+static int speaker_in_range(struct kvm_io_device *this, gpa_t addr,
+                           int len, int is_write)
 {
        return (addr == KVM_SPEAKER_BASE_ADDRESS);
 }
 
        return s->elcr;
 }
 
-static int picdev_in_range(struct kvm_io_device *this, gpa_t addr)
+static int picdev_in_range(struct kvm_io_device *this, gpa_t addr,
+                          int len, int is_write)
 {
        switch (addr) {
        case 0x20:
 
 
 }
 
-static int apic_mmio_range(struct kvm_io_device *this, gpa_t addr)
+static int apic_mmio_range(struct kvm_io_device *this, gpa_t addr,
+                          int len, int size)
 {
        struct kvm_lapic *apic = (struct kvm_lapic *)this->private;
        int ret = 0;
 
  * Only apic need an MMIO device hook, so shortcut now..
  */
 static struct kvm_io_device *vcpu_find_pervcpu_dev(struct kvm_vcpu *vcpu,
-                                               gpa_t addr)
+                                               gpa_t addr, int len,
+                                               int is_write)
 {
        struct kvm_io_device *dev;
 
        if (vcpu->arch.apic) {
                dev = &vcpu->arch.apic->dev;
-               if (dev->in_range(dev, addr))
+               if (dev->in_range(dev, addr, len, is_write))
                        return dev;
        }
        return NULL;
 
 
 static struct kvm_io_device *vcpu_find_mmio_dev(struct kvm_vcpu *vcpu,
-                                               gpa_t addr)
+                                               gpa_t addr, int len,
+                                               int is_write)
 {
        struct kvm_io_device *dev;
 
-       dev = vcpu_find_pervcpu_dev(vcpu, addr);
+       dev = vcpu_find_pervcpu_dev(vcpu, addr, len, is_write);
        if (dev == NULL)
-               dev = kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, addr);
+               dev = kvm_io_bus_find_dev(&vcpu->kvm->mmio_bus, addr, len,
+                                         is_write);
        return dev;
 }
 
         * Is this MMIO handled locally?
         */
        mutex_lock(&vcpu->kvm->lock);
-       mmio_dev = vcpu_find_mmio_dev(vcpu, gpa);
+       mmio_dev = vcpu_find_mmio_dev(vcpu, gpa, bytes, 0);
        if (mmio_dev) {
                kvm_iodevice_read(mmio_dev, gpa, bytes, val);
                mutex_unlock(&vcpu->kvm->lock);
         * Is this MMIO handled locally?
         */
        mutex_lock(&vcpu->kvm->lock);
-       mmio_dev = vcpu_find_mmio_dev(vcpu, gpa);
+       mmio_dev = vcpu_find_mmio_dev(vcpu, gpa, bytes, 1);
        if (mmio_dev) {
                kvm_iodevice_write(mmio_dev, gpa, bytes, val);
                mutex_unlock(&vcpu->kvm->lock);
 }
 
 static struct kvm_io_device *vcpu_find_pio_dev(struct kvm_vcpu *vcpu,
-                                              gpa_t addr)
+                                              gpa_t addr, int len,
+                                              int is_write)
 {
-       return kvm_io_bus_find_dev(&vcpu->kvm->pio_bus, addr);
+       return kvm_io_bus_find_dev(&vcpu->kvm->pio_bus, addr, len, is_write);
 }
 
 int kvm_emulate_pio(struct kvm_vcpu *vcpu, struct kvm_run *run, int in,
 
        kvm_x86_ops->skip_emulated_instruction(vcpu);
 
-       pio_dev = vcpu_find_pio_dev(vcpu, port);
+       pio_dev = vcpu_find_pio_dev(vcpu, port, size, !in);
        if (pio_dev) {
                kernel_pio(pio_dev, vcpu, vcpu->arch.pio_data);
                complete_pio(vcpu);
                }
        }
 
-       pio_dev = vcpu_find_pio_dev(vcpu, port);
+       pio_dev = vcpu_find_pio_dev(vcpu, port,
+                                   vcpu->arch.pio.cur_count,
+                                   !vcpu->arch.pio.in);
        if (!vcpu->arch.pio.in) {
                /* string PIO write */
                ret = pio_copy_data(vcpu);
 
 
 void kvm_io_bus_init(struct kvm_io_bus *bus);
 void kvm_io_bus_destroy(struct kvm_io_bus *bus);
-struct kvm_io_device *kvm_io_bus_find_dev(struct kvm_io_bus *bus, gpa_t addr);
+struct kvm_io_device *kvm_io_bus_find_dev(struct kvm_io_bus *bus,
+                                         gpa_t addr, int len, int is_write);
 void kvm_io_bus_register_dev(struct kvm_io_bus *bus,
                             struct kvm_io_device *dev);
 
 
                        __kvm_ioapic_update_eoi(ioapic, i);
 }
 
-static int ioapic_in_range(struct kvm_io_device *this, gpa_t addr)
+static int ioapic_in_range(struct kvm_io_device *this, gpa_t addr,
+                          int len, int is_write)
 {
        struct kvm_ioapic *ioapic = (struct kvm_ioapic *)this->private;
 
 
                      gpa_t addr,
                      int len,
                      const void *val);
-       int (*in_range)(struct kvm_io_device *this, gpa_t addr);
+       int (*in_range)(struct kvm_io_device *this, gpa_t addr, int len,
+                       int is_write);
        void (*destructor)(struct kvm_io_device *this);
 
        void             *private;
        dev->write(dev, addr, len, val);
 }
 
-static inline int kvm_iodevice_inrange(struct kvm_io_device *dev, gpa_t addr)
+static inline int kvm_iodevice_inrange(struct kvm_io_device *dev,
+                                      gpa_t addr, int len, int is_write)
 {
-       return dev->in_range(dev, addr);
+       return dev->in_range(dev, addr, len, is_write);
 }
 
 static inline void kvm_iodevice_destructor(struct kvm_io_device *dev)
 
        }
 }
 
-struct kvm_io_device *kvm_io_bus_find_dev(struct kvm_io_bus *bus, gpa_t addr)
+struct kvm_io_device *kvm_io_bus_find_dev(struct kvm_io_bus *bus,
+                                         gpa_t addr, int len, int is_write)
 {
        int i;
 
        for (i = 0; i < bus->dev_count; i++) {
                struct kvm_io_device *pos = bus->devs[i];
 
-               if (pos->in_range(pos, addr))
+               if (pos->in_range(pos, addr, len, is_write))
                        return pos;
        }