staticint coalesced_mmio_in_range(struct kvm_coalesced_mmio_dev *dev,
gpa_t addr, int len)
{ /* is it in a batchable area ? * (addr,len) is fully included in * (zone->addr, zone->size)
*/ if (len < 0) return 0; if (addr + len < addr) return 0; if (addr < dev->zone.addr) return 0; if (addr + len > dev->zone.addr + dev->zone.size) return 0; return 1;
}
if (!coalesced_mmio_in_range(dev, addr, len)) return -EOPNOTSUPP;
spin_lock(&dev->kvm->ring_lock);
/* * last is the index of the entry to fill. Verify userspace hasn't * set last to be out of range, and that there is room in the ring. * Leave one entry free in the ring so that userspace can differentiate * between an empty ring and a full ring.
*/
insert = READ_ONCE(ring->last); if (insert >= KVM_COALESCED_MMIO_MAX ||
(insert + 1) % KVM_COALESCED_MMIO_MAX == READ_ONCE(ring->first)) {
spin_unlock(&dev->kvm->ring_lock); return -EOPNOTSUPP;
}
int kvm_coalesced_mmio_init(struct kvm *kvm)
{ struct page *page;
page = alloc_page(GFP_KERNEL_ACCOUNT | __GFP_ZERO); if (!page) return -ENOMEM;
kvm->coalesced_mmio_ring = page_address(page);
/* * We're using this spinlock to sync access to the coalesced ring. * The list doesn't need its own lock since device registration and * unregistration should only happen when kvm->slots_lock is held.
*/
spin_lock_init(&kvm->ring_lock);
INIT_LIST_HEAD(&kvm->coalesced_zones);
return 0;
}
void kvm_coalesced_mmio_free(struct kvm *kvm)
{ if (kvm->coalesced_mmio_ring)
free_page((unsignedlong)kvm->coalesced_mmio_ring);
}
int kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm, struct kvm_coalesced_mmio_zone *zone)
{ int ret; struct kvm_coalesced_mmio_dev *dev;
if (zone->pio != 1 && zone->pio != 0) return -EINVAL;
dev = kzalloc(sizeof(struct kvm_coalesced_mmio_dev),
GFP_KERNEL_ACCOUNT); if (!dev) return -ENOMEM;
int kvm_vm_ioctl_unregister_coalesced_mmio(struct kvm *kvm, struct kvm_coalesced_mmio_zone *zone)
{ struct kvm_coalesced_mmio_dev *dev, *tmp; int r;
if (zone->pio != 1 && zone->pio != 0) return -EINVAL;
mutex_lock(&kvm->slots_lock);
list_for_each_entry_safe(dev, tmp, &kvm->coalesced_zones, list) { if (zone->pio == dev->zone.pio &&
coalesced_mmio_in_range(dev, zone->addr, zone->size)) {
r = kvm_io_bus_unregister_dev(kvm,
zone->pio ? KVM_PIO_BUS : KVM_MMIO_BUS, &dev->dev); /* * On failure, unregister destroys all devices on the * bus, including the target device. There's no need * to restart the walk as there aren't any zones left.
*/ if (r) break;
}
}
mutex_unlock(&kvm->slots_lock);
/* * Ignore the result of kvm_io_bus_unregister_dev(), from userspace's * perspective, the coalesced MMIO is most definitely unregistered.
*/ return 0;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.