int virtio_load(VirtIODevice *vdev, QEMUFile *f)

{

    int i, ret;

    int32_t config_len;

    uint32_t num;

    uint32_t features;

    uint32_t supported_features;

    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));

    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);



    if (k->load_config) {

        ret = k->load_config(qbus->parent, f);

        if (ret)

            return ret;

    }



    qemu_get_8s(f, &vdev->status);

    qemu_get_8s(f, &vdev->isr);

    qemu_get_be16s(f, &vdev->queue_sel);

    if (vdev->queue_sel >= VIRTIO_PCI_QUEUE_MAX) {

        return -1;

    }

    qemu_get_be32s(f, &features);



    if (virtio_set_features(vdev, features) < 0) {

        supported_features = k->get_features(qbus->parent);

        error_report("Features 0x%x unsupported. Allowed features: 0x%x",

                     features, supported_features);

        return -1;

    }

    config_len = qemu_get_be32(f);

    if (config_len != vdev->config_len) {

        error_report("Unexpected config length 0x%x. Expected 0x%zx",

                     config_len, vdev->config_len);

        return -1;

    }

    qemu_get_buffer(f, vdev->config, vdev->config_len);



    num = qemu_get_be32(f);



    if (num > VIRTIO_PCI_QUEUE_MAX) {

        error_report("Invalid number of PCI queues: 0x%x", num);

        return -1;

    }



    for (i = 0; i < num; i++) {

        vdev->vq[i].vring.num = qemu_get_be32(f);

        if (k->has_variable_vring_alignment) {

            vdev->vq[i].vring.align = qemu_get_be32(f);

        }

        vdev->vq[i].pa = qemu_get_be64(f);

        qemu_get_be16s(f, &vdev->vq[i].last_avail_idx);

        vdev->vq[i].signalled_used_valid = false;

        vdev->vq[i].notification = true;



        if (vdev->vq[i].pa) {

            uint16_t nheads;

            virtqueue_init(&vdev->vq[i]);

            nheads = vring_avail_idx(&vdev->vq[i]) - vdev->vq[i].last_avail_idx;

            /* Check it isn't doing very strange things with descriptor numbers. */

            if (nheads > vdev->vq[i].vring.num) {

                error_report("VQ %d size 0x%x Guest index 0x%x "

                             "inconsistent with Host index 0x%x: delta 0x%x",

                             i, vdev->vq[i].vring.num,

                             vring_avail_idx(&vdev->vq[i]),

                             vdev->vq[i].last_avail_idx, nheads);

                return -1;

            }

        } else if (vdev->vq[i].last_avail_idx) {

            error_report("VQ %d address 0x0 "

                         "inconsistent with Host index 0x%x",

                         i, vdev->vq[i].last_avail_idx);

                return -1;

	}

        if (k->load_queue) {

            ret = k->load_queue(qbus->parent, i, f);

            if (ret)

                return ret;

        }

    }



    virtio_notify_vector(vdev, VIRTIO_NO_VECTOR);

    return 0;

}

int virtio_load(VirtIODevice *vdev, QEMUFile *f)

{

    int i, ret;

    int32_t config_len;

    uint32_t num;

    uint32_t features;

    uint32_t supported_features;

    BusState *qbus = qdev_get_parent_bus(DEVICE(vdev));

    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);



    if (k->load_config) {

        ret = k->load_config(qbus->parent, f);

        if (ret)

            return ret;

    }



    qemu_get_8s(f, &vdev->status);

    qemu_get_8s(f, &vdev->isr);

    qemu_get_be16s(f, &vdev->queue_sel);

    if (vdev->queue_sel >= VIRTIO_PCI_QUEUE_MAX) {

        return -1;

    }

    qemu_get_be32s(f, &features);



    if (virtio_set_features(vdev, features) < 0) {

        supported_features = k->get_features(qbus->parent);

        error_report("Features 0x%x unsupported. Allowed features: 0x%x",

                     features, supported_features);

        return -1;

    }

    config_len = qemu_get_be32(f);

    if (config_len != vdev->config_len) {

        error_report("Unexpected config length 0x%x. Expected 0x%zx",

                     config_len, vdev->config_len);

        return -1;

    }

    qemu_get_buffer(f, vdev->config, vdev->config_len);



    num = qemu_get_be32(f);



    if (num > VIRTIO_PCI_QUEUE_MAX) {

        error_report("Invalid number of PCI queues: 0x%x", num);

        return -1;

    }



    for (i = 0; i < num; i++) {

        vdev->vq[i].vring.num = qemu_get_be32(f);

        if (k->has_variable_vring_alignment) {

            vdev->vq[i].vring.align = qemu_get_be32(f);

        }

        vdev->vq[i].pa = qemu_get_be64(f);

        qemu_get_be16s(f, &vdev->vq[i].last_avail_idx);

        vdev->vq[i].signalled_used_valid = false;

        vdev->vq[i].notification = true;



        if (vdev->vq[i].pa) {

            uint16_t nheads;

            virtqueue_init(&vdev->vq[i]);

            nheads = vring_avail_idx(&vdev->vq[i]) - vdev->vq[i].last_avail_idx;

            

            if (nheads > vdev->vq[i].vring.num) {

                error_report("VQ %d size 0x%x Guest index 0x%x "

                             "inconsistent with Host index 0x%x: delta 0x%x",

                             i, vdev->vq[i].vring.num,

                             vring_avail_idx(&vdev->vq[i]),

                             vdev->vq[i].last_avail_idx, nheads);

                return -1;

            }

        } else if (vdev->vq[i].last_avail_idx) {

            error_report("VQ %d address 0x0 "

                         "inconsistent with Host index 0x%x",

                         i, vdev->vq[i].last_avail_idx);

                return -1;

	}

        if (k->load_queue) {

            ret = k->load_queue(qbus->parent, i, f);

            if (ret)

                return ret;

        }

    }



    virtio_notify_vector(vdev, VIRTIO_NO_VECTOR);

    return 0;

}

int FUNC_0(VirtIODevice *VAR_0, QEMUFile *VAR_1)

{

    int VAR_2, VAR_3;

    int32_t config_len;

    uint32_t num;

    uint32_t features;

    uint32_t supported_features;

    BusState *qbus = qdev_get_parent_bus(DEVICE(VAR_0));

    VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);



    if (k->load_config) {

        VAR_3 = k->load_config(qbus->parent, VAR_1);

        if (VAR_3)

            return VAR_3;

    }



    qemu_get_8s(VAR_1, &VAR_0->status);

    qemu_get_8s(VAR_1, &VAR_0->isr);

    qemu_get_be16s(VAR_1, &VAR_0->queue_sel);

    if (VAR_0->queue_sel >= VIRTIO_PCI_QUEUE_MAX) {

        return -1;

    }

    qemu_get_be32s(VAR_1, &features);



    if (virtio_set_features(VAR_0, features) < 0) {

        supported_features = k->get_features(qbus->parent);

        error_report("Features 0x%x unsupported. Allowed features: 0x%x",

                     features, supported_features);

        return -1;

    }

    config_len = qemu_get_be32(VAR_1);

    if (config_len != VAR_0->config_len) {

        error_report("Unexpected config length 0x%x. Expected 0x%zx",

                     config_len, VAR_0->config_len);

        return -1;

    }

    qemu_get_buffer(VAR_1, VAR_0->config, VAR_0->config_len);



    num = qemu_get_be32(VAR_1);



    if (num > VIRTIO_PCI_QUEUE_MAX) {

        error_report("Invalid number of PCI queues: 0x%x", num);

        return -1;

    }



    for (VAR_2 = 0; VAR_2 < num; VAR_2++) {

        VAR_0->vq[VAR_2].vring.num = qemu_get_be32(VAR_1);

        if (k->has_variable_vring_alignment) {

            VAR_0->vq[VAR_2].vring.align = qemu_get_be32(VAR_1);

        }

        VAR_0->vq[VAR_2].pa = qemu_get_be64(VAR_1);

        qemu_get_be16s(VAR_1, &VAR_0->vq[VAR_2].last_avail_idx);

        VAR_0->vq[VAR_2].signalled_used_valid = false;

        VAR_0->vq[VAR_2].notification = true;



        if (VAR_0->vq[VAR_2].pa) {

            uint16_t nheads;

            virtqueue_init(&VAR_0->vq[VAR_2]);

            nheads = vring_avail_idx(&VAR_0->vq[VAR_2]) - VAR_0->vq[VAR_2].last_avail_idx;

            

            if (nheads > VAR_0->vq[VAR_2].vring.num) {

                error_report("VQ %d size 0x%x Guest index 0x%x "

                             "inconsistent with Host index 0x%x: delta 0x%x",

                             VAR_2, VAR_0->vq[VAR_2].vring.num,

                             vring_avail_idx(&VAR_0->vq[VAR_2]),

                             VAR_0->vq[VAR_2].last_avail_idx, nheads);

                return -1;

            }

        } else if (VAR_0->vq[VAR_2].last_avail_idx) {

            error_report("VQ %d address 0x0 "

                         "inconsistent with Host index 0x%x",

                         VAR_2, VAR_0->vq[VAR_2].last_avail_idx);

                return -1;

	}

        if (k->load_queue) {

            VAR_3 = k->load_queue(qbus->parent, VAR_2, VAR_1);

            if (VAR_3)

                return VAR_3;

        }

    }



    virtio_notify_vector(VAR_0, VIRTIO_NO_VECTOR);

    return 0;

}

int FUNC_0(VirtIODevice *VAR_0, QEMUFile *VAR_1)
{ int VAR_2, VAR_3; int32_t config_len; uint32_t num; uint32_t features; uint32_t supported_features; BusState *qbus = qdev_get_parent_bus(DEVICE(VAR_0)); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); if (k->load_config) { VAR_3 = k->load_config(qbus->parent, VAR_1); if (VAR_3)
return VAR_3; } qemu_get_8s(VAR_1, &VAR_0->status); qemu_get_8s(VAR_1, &VAR_0->isr); qemu_get_be16s(VAR_1, &VAR_0->queue_sel); if (VAR_0->queue_sel >= VIRTIO_PCI_QUEUE_MAX) { return -1; } qemu_get_be32s(VAR_1, &features); if (virtio_set_features(VAR_0, features) < 0) { supported_features = k->get_features(qbus->parent); error_report("Features 0x%x unsupported. Allowed features: 0x%x",
features, supported_features); return -1; } config_len = qemu_get_be32(VAR_1); if (config_len != VAR_0->config_len) { error_report("Unexpected config length 0x%x. Expected 0x%zx",
config_len, VAR_0->config_len); return -1; } qemu_get_buffer(VAR_1, VAR_0->config, VAR_0->config_len); num = qemu_get_be32(VAR_1); if (num > VIRTIO_PCI_QUEUE_MAX) { error_report("Invalid number of PCI queues: 0x%x", num); return -1; } for (VAR_2 = 0; VAR_2 < num; VAR_2++) { VAR_0->vq[VAR_2].vring.num = qemu_get_be32(VAR_1); if (k->has_variable_vring_alignment) { VAR_0->vq[VAR_2].vring.align = qemu_get_be32(VAR_1); } VAR_0->vq[VAR_2].pa = qemu_get_be64(VAR_1); qemu_get_be16s(VAR_1, &VAR_0->vq[VAR_2].last_avail_idx); VAR_0->vq[VAR_2].signalled_used_valid = false; VAR_0->vq[VAR_2].notification = true; if (VAR_0->vq[VAR_2].pa) { uint16_t nheads; virtqueue_init(&VAR_0->vq[VAR_2]); nheads = vring_avail_idx(&VAR_0->vq[VAR_2]) - VAR_0->vq[VAR_2].last_avail_idx; if (nheads > VAR_0->vq[VAR_2].vring.num) { error_report("VQ %d size 0x%x Guest index 0x%x "
"inconsistent with Host index 0x%x: delta 0x%x",
VAR_2, VAR_0->vq[VAR_2].vring.num,
vring_avail_idx(&VAR_0->vq[VAR_2]),
VAR_0->vq[VAR_2].last_avail_idx, nheads); return -1; } } else if (VAR_0->vq[VAR_2].last_avail_idx) { error_report("VQ %d address 0x0 "
"inconsistent with Host index 0x%x",
VAR_2, VAR_0->vq[VAR_2].last_avail_idx); return -1; } if (k->load_queue) { VAR_3 = k->load_queue(qbus->parent, VAR_2, VAR_1); if (VAR_3)
return VAR_3; } } virtio_notify_vector(VAR_0, VIRTIO_NO_VECTOR); return 0; }