/*
 * s390 storage attributes device -- KVM object
 *
 * Copyright 2016 IBM Corp.
 * Author(s): Claudio Imbrenda <imbrenda@linux.vnet.ibm.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2 or (at
 * your option) any later version. See the COPYING file in the top-level
 * directory.
 */

#include "qemu/osdep.h"
#include "hw/s390x/s390-virtio-ccw.h"
#include "migration/qemu-file.h"
#include "hw/s390x/storage-attributes.h"
#include "qemu/error-report.h"
#include "system/kvm.h"
#include "system/memory_mapping.h"
#include "exec/ram_addr.h"
#include "kvm/kvm_s390x.h"
#include "qapi/error.h"

Object *kvm_s390_stattrib_create(void)
{
    if (kvm_enabled() &&
                kvm_check_extension(kvm_state, KVM_CAP_S390_CMMA_MIGRATION)) {
        return object_new(TYPE_KVM_S390_STATTRIB);
    }
    return NULL;
}

static void kvm_s390_stattrib_instance_init(Object *obj)
{
    KVMS390StAttribState *sas = KVM_S390_STATTRIB(obj);

    sas->still_dirty = 0;
}

static int kvm_s390_stattrib_read_helper(S390StAttribState *sa,
                                         uint64_t *start_gfn,
                                         uint32_t count,
                                         uint8_t *values,
                                         uint32_t flags)
{
    KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa);
    int r;
    struct kvm_s390_cmma_log clog = {
        .values = (uint64_t)values,
        .start_gfn = *start_gfn,
        .count = count,
        .flags = flags,
    };

    r = kvm_vm_ioctl(kvm_state, KVM_S390_GET_CMMA_BITS, &clog);
    if (r < 0) {
        error_report("KVM_S390_GET_CMMA_BITS failed: %s", strerror(-r));
        return r;
    }

    *start_gfn = clog.start_gfn;
    sas->still_dirty = clog.remaining;
    return clog.count;
}

static int kvm_s390_stattrib_get_stattr(S390StAttribState *sa,
                                        uint64_t *start_gfn,
                                        uint32_t count,
                                        uint8_t *values)
{
    return kvm_s390_stattrib_read_helper(sa, start_gfn, count, values, 0);
}

static int kvm_s390_stattrib_peek_stattr(S390StAttribState *sa,
                                         uint64_t start_gfn,
                                         uint32_t count,
                                         uint8_t *values)
{
    return kvm_s390_stattrib_read_helper(sa, &start_gfn, count, values,
                                         KVM_S390_CMMA_PEEK);
}

static int kvm_s390_stattrib_set_stattr(S390StAttribState *sa,
                                        uint64_t start_gfn,
                                        uint32_t count,
                                        uint8_t *values)
{
    KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa);
    S390CcwMachineState *s390ms = S390_CCW_MACHINE(qdev_get_machine());
    unsigned long max = s390_get_memory_limit(s390ms) / TARGET_PAGE_SIZE;

    if (start_gfn + count > max) {
        error_report("Out of memory bounds when setting storage attributes");
        return -1;
    }
    if (!sas->incoming_buffer) {
        sas->incoming_buffer = g_malloc0(max);
    }

    memcpy(sas->incoming_buffer + start_gfn, values, count);

    return 0;
}

static void kvm_s390_stattrib_synchronize(S390StAttribState *sa)
{
    KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa);
    S390CcwMachineState *s390ms = S390_CCW_MACHINE(qdev_get_machine());
    unsigned long max = s390_get_memory_limit(s390ms) / TARGET_PAGE_SIZE;
    unsigned long start_gfn, end_gfn, pages;
    GuestPhysBlockList guest_phys_blocks;
    GuestPhysBlock *block;
    int r;
    struct kvm_s390_cmma_log clog = {
        .flags = 0,
        .mask = ~0ULL,
    };

    if (!sas->incoming_buffer) {
        return;
    }
    guest_phys_blocks_init(&guest_phys_blocks);
    guest_phys_blocks_append(&guest_phys_blocks);

    QTAILQ_FOREACH(block, &guest_phys_blocks.head, next) {
        assert(QEMU_IS_ALIGNED(block->target_start, TARGET_PAGE_SIZE));
        assert(QEMU_IS_ALIGNED(block->target_end, TARGET_PAGE_SIZE));

        start_gfn = block->target_start / TARGET_PAGE_SIZE;
        end_gfn = block->target_end / TARGET_PAGE_SIZE;

        while (start_gfn < end_gfn) {
            /* Don't exceed the maximum buffer size. */
            pages = MIN(end_gfn - start_gfn, KVM_S390_SKEYS_MAX / 2);

            /*
             * If we ever get guest physical memory beyond the configured
             * memory limit, something went very wrong.
             */
            assert(start_gfn + pages <= max);

            clog.start_gfn = start_gfn;
            clog.count = pages;
            clog.values = (uint64_t)(sas->incoming_buffer + start_gfn);
            r = kvm_vm_ioctl(kvm_state, KVM_S390_SET_CMMA_BITS, &clog);
            if (r) {
                error_report("KVM_S390_SET_CMMA_BITS failed: %s", strerror(-r));
                goto out;
            }

            start_gfn += pages;
        }
    }

out:
    guest_phys_blocks_free(&guest_phys_blocks);
    g_free(sas->incoming_buffer);
    sas->incoming_buffer = NULL;
}

static int kvm_s390_stattrib_set_migrationmode(S390StAttribState *sa, bool val,
                                               Error **errp)
{
    struct kvm_device_attr attr = {
        .group = KVM_S390_VM_MIGRATION,
        .attr = val,
        .addr = 0,
    };
    int r;

    r = kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr);
    if (r) {
        error_setg_errno(errp, -r, "setting KVM_S390_VM_MIGRATION failed");
    }
    return r;
}

static long long kvm_s390_stattrib_get_dirtycount(S390StAttribState *sa)
{
    KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa);
    uint8_t val[8];

    kvm_s390_stattrib_peek_stattr(sa, 0, 1, val);
    return sas->still_dirty;
}

static int kvm_s390_stattrib_get_active(S390StAttribState *sa)
{
    return kvm_s390_cmma_active() && sa->migration_enabled;
}

static void kvm_s390_stattrib_class_init(ObjectClass *oc, void *data)
{
    S390StAttribClass *sac = S390_STATTRIB_CLASS(oc);
    DeviceClass *dc = DEVICE_CLASS(oc);

    sac->get_stattr = kvm_s390_stattrib_get_stattr;
    sac->peek_stattr = kvm_s390_stattrib_peek_stattr;
    sac->set_stattr = kvm_s390_stattrib_set_stattr;
    sac->set_migrationmode = kvm_s390_stattrib_set_migrationmode;
    sac->get_dirtycount = kvm_s390_stattrib_get_dirtycount;
    sac->synchronize = kvm_s390_stattrib_synchronize;
    sac->get_active = kvm_s390_stattrib_get_active;

    /* Reason: Can only be instantiated one time (internally) */
    dc->user_creatable = false;
}

static const TypeInfo kvm_s390_stattrib_info = {
    .name          = TYPE_KVM_S390_STATTRIB,
    .parent        = TYPE_S390_STATTRIB,
    .instance_init = kvm_s390_stattrib_instance_init,
    .instance_size = sizeof(KVMS390StAttribState),
    .class_init    = kvm_s390_stattrib_class_init,
    .class_size    = sizeof(S390StAttribClass),
};

static void kvm_s390_stattrib_register_types(void)
{
    type_register_static(&kvm_s390_stattrib_info);
}

type_init(kvm_s390_stattrib_register_types)
