|
@@ -92,11 +92,19 @@ static const struct kvm_io_device_ops coalesced_mmio_ops = {
|
|
|
int kvm_coalesced_mmio_init(struct kvm *kvm)
|
|
|
{
|
|
|
struct kvm_coalesced_mmio_dev *dev;
|
|
|
+ struct page *page;
|
|
|
int ret;
|
|
|
|
|
|
+ ret = -ENOMEM;
|
|
|
+ page = alloc_page(GFP_KERNEL | __GFP_ZERO);
|
|
|
+ if (!page)
|
|
|
+ goto out_err;
|
|
|
+ kvm->coalesced_mmio_ring = page_address(page);
|
|
|
+
|
|
|
+ ret = -ENOMEM;
|
|
|
dev = kzalloc(sizeof(struct kvm_coalesced_mmio_dev), GFP_KERNEL);
|
|
|
if (!dev)
|
|
|
- return -ENOMEM;
|
|
|
+ goto out_free_page;
|
|
|
spin_lock_init(&dev->lock);
|
|
|
kvm_iodevice_init(&dev->dev, &coalesced_mmio_ops);
|
|
|
dev->kvm = kvm;
|
|
@@ -104,11 +112,24 @@ int kvm_coalesced_mmio_init(struct kvm *kvm)
|
|
|
|
|
|
ret = kvm_io_bus_register_dev(kvm, &kvm->mmio_bus, &dev->dev);
|
|
|
if (ret < 0)
|
|
|
- kfree(dev);
|
|
|
+ goto out_free_dev;
|
|
|
+
|
|
|
+ return ret;
|
|
|
|
|
|
+out_free_dev:
|
|
|
+ kfree(dev);
|
|
|
+out_free_page:
|
|
|
+ __free_page(page);
|
|
|
+out_err:
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+void kvm_coalesced_mmio_free(struct kvm *kvm)
|
|
|
+{
|
|
|
+ if (kvm->coalesced_mmio_ring)
|
|
|
+ free_page((unsigned long)kvm->coalesced_mmio_ring);
|
|
|
+}
|
|
|
+
|
|
|
int kvm_vm_ioctl_register_coalesced_mmio(struct kvm *kvm,
|
|
|
struct kvm_coalesced_mmio_zone *zone)
|
|
|
{
|