// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2022 SiFive
 *
 * Authors:
 *     Vincent Chen <vincent.chen@sifive.com>
 *     Greentime Hu <greentime.hu@sifive.com>
 */

#include <linux/errno.h>
#include <linux/err.h>
#include <linux/kvm_host.h>
#include <linux/uaccess.h>
#include <asm/cpufeature.h>
#include <asm/kvm_vcpu_vector.h>
#include <asm/vector.h>

#ifdef CONFIG_RISCV_ISA_V
void kvm_riscv_vcpu_vector_reset(struct kvm_vcpu *vcpu)
{
	unsigned long *isa = vcpu->arch.isa;
	struct kvm_cpu_context *cntx = &vcpu->arch.guest_context;

	cntx->sstatus &= ~SR_VS;

	cntx->vector.vlenb = riscv_v_vsize / 32;

	if (riscv_isa_extension_available(isa, v)) {
		cntx->sstatus |= SR_VS_INITIAL;
		WARN_ON(!cntx->vector.datap);
		memset(cntx->vector.datap, 0, riscv_v_vsize);
	} else {
		cntx->sstatus |= SR_VS_OFF;
	}
}

static void kvm_riscv_vcpu_vector_clean(struct kvm_cpu_context *cntx)
{
	cntx->sstatus &= ~SR_VS;
	cntx->sstatus |= SR_VS_CLEAN;
}

void kvm_riscv_vcpu_guest_vector_save(struct kvm_cpu_context *cntx,
				      unsigned long *isa)
{
	if ((cntx->sstatus & SR_VS) == SR_VS_DIRTY) {
		if (riscv_isa_extension_available(isa, v))
			__kvm_riscv_vector_save(cntx);
		kvm_riscv_vcpu_vector_clean(cntx);
	}
}

void kvm_riscv_vcpu_guest_vector_restore(struct kvm_cpu_context *cntx,
					 unsigned long *isa)
{
	if ((cntx->sstatus & SR_VS) != SR_VS_OFF) {
		if (riscv_isa_extension_available(isa, v))
			__kvm_riscv_vector_restore(cntx);
		kvm_riscv_vcpu_vector_clean(cntx);
	}
}

void kvm_riscv_vcpu_host_vector_save(struct kvm_cpu_context *cntx)
{
	/* No need to check host sstatus as it can be modified outside */
	if (riscv_isa_extension_available(NULL, v))
		__kvm_riscv_vector_save(cntx);
}

void kvm_riscv_vcpu_host_vector_restore(struct kvm_cpu_context *cntx)
{
	if (riscv_isa_extension_available(NULL, v))
		__kvm_riscv_vector_restore(cntx);
}

int kvm_riscv_vcpu_alloc_vector_context(struct kvm_vcpu *vcpu)
{
	vcpu->arch.guest_context.vector.datap = kzalloc(riscv_v_vsize, GFP_KERNEL);
	if (!vcpu->arch.guest_context.vector.datap)
		return -ENOMEM;

	vcpu->arch.host_context.vector.datap = kzalloc(riscv_v_vsize, GFP_KERNEL);
	if (!vcpu->arch.host_context.vector.datap)
		return -ENOMEM;

	return 0;
}

void kvm_riscv_vcpu_free_vector_context(struct kvm_vcpu *vcpu)
{
	kfree(vcpu->arch.guest_context.vector.datap);
	kfree(vcpu->arch.host_context.vector.datap);
}
#endif

static int kvm_riscv_vcpu_vreg_addr(struct kvm_vcpu *vcpu,
				    unsigned long reg_num,
				    size_t reg_size,
				    void **reg_addr)
{
	struct kvm_cpu_context *cntx = &vcpu->arch.guest_context;
	size_t vlenb = riscv_v_vsize / 32;

	if (reg_num < KVM_REG_RISCV_VECTOR_REG(0)) {
		if (reg_size != sizeof(unsigned long))
			return -EINVAL;
		switch (reg_num) {
		case KVM_REG_RISCV_VECTOR_CSR_REG(vstart):
			*reg_addr = &cntx->vector.vstart;
			break;
		case KVM_REG_RISCV_VECTOR_CSR_REG(vl):
			*reg_addr = &cntx->vector.vl;
			break;
		case KVM_REG_RISCV_VECTOR_CSR_REG(vtype):
			*reg_addr = &cntx->vector.vtype;
			break;
		case KVM_REG_RISCV_VECTOR_CSR_REG(vcsr):
			*reg_addr = &cntx->vector.vcsr;
			break;
		case KVM_REG_RISCV_VECTOR_CSR_REG(vlenb):
			*reg_addr = &cntx->vector.vlenb;
			break;
		case KVM_REG_RISCV_VECTOR_CSR_REG(datap):
		default:
			return -ENOENT;
		}
	} else if (reg_num <= KVM_REG_RISCV_VECTOR_REG(31)) {
		if (reg_size != vlenb)
			return -EINVAL;
		*reg_addr = cntx->vector.datap +
			    (reg_num - KVM_REG_RISCV_VECTOR_REG(0)) * vlenb;
	} else {
		return -ENOENT;
	}

	return 0;
}

int kvm_riscv_vcpu_get_reg_vector(struct kvm_vcpu *vcpu,
				  const struct kvm_one_reg *reg)
{
	unsigned long *isa = vcpu->arch.isa;
	unsigned long __user *uaddr =
			(unsigned long __user *)(unsigned long)reg->addr;
	unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK |
					    KVM_REG_SIZE_MASK |
					    KVM_REG_RISCV_VECTOR);
	size_t reg_size = KVM_REG_SIZE(reg->id);
	void *reg_addr;
	int rc;

	if (!riscv_isa_extension_available(isa, v))
		return -ENOENT;

	rc = kvm_riscv_vcpu_vreg_addr(vcpu, reg_num, reg_size, &reg_addr);
	if (rc)
		return rc;

	if (copy_to_user(uaddr, reg_addr, reg_size))
		return -EFAULT;

	return 0;
}

int kvm_riscv_vcpu_set_reg_vector(struct kvm_vcpu *vcpu,
				  const struct kvm_one_reg *reg)
{
	unsigned long *isa = vcpu->arch.isa;
	unsigned long __user *uaddr =
			(unsigned long __user *)(unsigned long)reg->addr;
	unsigned long reg_num = reg->id & ~(KVM_REG_ARCH_MASK |
					    KVM_REG_SIZE_MASK |
					    KVM_REG_RISCV_VECTOR);
	size_t reg_size = KVM_REG_SIZE(reg->id);
	void *reg_addr;
	int rc;

	if (!riscv_isa_extension_available(isa, v))
		return -ENOENT;

	if (reg_num == KVM_REG_RISCV_VECTOR_CSR_REG(vlenb)) {
		struct kvm_cpu_context *cntx = &vcpu->arch.guest_context;
		unsigned long reg_val;

		if (copy_from_user(&reg_val, uaddr, reg_size))
			return -EFAULT;
		if (reg_val != cntx->vector.vlenb)
			return -EINVAL;

		return 0;
	}

	rc = kvm_riscv_vcpu_vreg_addr(vcpu, reg_num, reg_size, &reg_addr);
	if (rc)
		return rc;

	if (copy_from_user(reg_addr, uaddr, reg_size))
		return -EFAULT;

	return 0;
}
