// SPDX-License-Identifier: GPL-2.0
/*
 * ARM Generic Interrupt Controller (GIC) v3 host support
 */

#include <linux/kernel.h>
#include <linux/kvm.h>
#include <linux/sizes.h>
#include <asm/cputype.h>
#include <asm/kvm_para.h>
#include <asm/kvm.h>

#include "kvm_util.h"
#include "vgic.h"
#include "gic.h"
#include "gic_v3.h"

/*
 * vGIC-v3 default host setup
 *
 * Input args:
 *	vm - KVM VM
 *	nr_vcpus - Number of vCPUs supported by this VM
 *
 * Output args: None
 *
 * Return: GIC file-descriptor or negative error code upon failure
 *
 * The function creates a vGIC-v3 device and maps the distributor and
 * redistributor regions of the guest. Since it depends on the number of
 * vCPUs for the VM, it must be called after all the vCPUs have been created.
 */
int vgic_v3_setup(struct kvm_vm *vm, unsigned int nr_vcpus, uint32_t nr_irqs)
{
	int gic_fd;
	uint64_t attr;
	struct list_head *iter;
	unsigned int nr_gic_pages, nr_vcpus_created = 0;

	TEST_ASSERT(nr_vcpus, "Number of vCPUs cannot be empty");

	/*
	 * Make sure that the caller is infact calling this
	 * function after all the vCPUs are added.
	 */
	list_for_each(iter, &vm->vcpus)
		nr_vcpus_created++;
	TEST_ASSERT(nr_vcpus == nr_vcpus_created,
			"Number of vCPUs requested (%u) doesn't match with the ones created for the VM (%u)",
			nr_vcpus, nr_vcpus_created);

	/* Distributor setup */
	gic_fd = __kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V3);
	if (gic_fd < 0)
		return gic_fd;

	kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0, &nr_irqs);

	kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
			    KVM_DEV_ARM_VGIC_CTRL_INIT, NULL);

	attr = GICD_BASE_GPA;
	kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
			    KVM_VGIC_V3_ADDR_TYPE_DIST, &attr);
	nr_gic_pages = vm_calc_num_guest_pages(vm->mode, KVM_VGIC_V3_DIST_SIZE);
	virt_map(vm, GICD_BASE_GPA, GICD_BASE_GPA, nr_gic_pages);

	/* Redistributor setup */
	attr = REDIST_REGION_ATTR_ADDR(nr_vcpus, GICR_BASE_GPA, 0, 0);
	kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
			    KVM_VGIC_V3_ADDR_TYPE_REDIST_REGION, &attr);
	nr_gic_pages = vm_calc_num_guest_pages(vm->mode,
						KVM_VGIC_V3_REDIST_SIZE * nr_vcpus);
	virt_map(vm, GICR_BASE_GPA, GICR_BASE_GPA, nr_gic_pages);

	kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
			    KVM_DEV_ARM_VGIC_CTRL_INIT, NULL);

	return gic_fd;
}

/* should only work for level sensitive interrupts */
int _kvm_irq_set_level_info(int gic_fd, uint32_t intid, int level)
{
	uint64_t attr = 32 * (intid / 32);
	uint64_t index = intid % 32;
	uint64_t val;
	int ret;

	ret = __kvm_device_attr_get(gic_fd, KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO,
				    attr, &val);
	if (ret != 0)
		return ret;

	val |= 1U << index;
	ret = __kvm_device_attr_set(gic_fd, KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO,
				    attr, &val);
	return ret;
}

void kvm_irq_set_level_info(int gic_fd, uint32_t intid, int level)
{
	int ret = _kvm_irq_set_level_info(gic_fd, intid, level);

	TEST_ASSERT(!ret, KVM_IOCTL_ERROR(KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO, ret));
}

int _kvm_arm_irq_line(struct kvm_vm *vm, uint32_t intid, int level)
{
	uint32_t irq = intid & KVM_ARM_IRQ_NUM_MASK;

	TEST_ASSERT(!INTID_IS_SGI(intid), "KVM_IRQ_LINE's interface itself "
		"doesn't allow injecting SGIs. There's no mask for it.");

	if (INTID_IS_PPI(intid))
		irq |= KVM_ARM_IRQ_TYPE_PPI << KVM_ARM_IRQ_TYPE_SHIFT;
	else
		irq |= KVM_ARM_IRQ_TYPE_SPI << KVM_ARM_IRQ_TYPE_SHIFT;

	return _kvm_irq_line(vm, irq, level);
}

void kvm_arm_irq_line(struct kvm_vm *vm, uint32_t intid, int level)
{
	int ret = _kvm_arm_irq_line(vm, intid, level);

	TEST_ASSERT(!ret, KVM_IOCTL_ERROR(KVM_IRQ_LINE, ret));
}

static void vgic_poke_irq(int gic_fd, uint32_t intid, struct kvm_vcpu *vcpu,
			  uint64_t reg_off)
{
	uint64_t reg = intid / 32;
	uint64_t index = intid % 32;
	uint64_t attr = reg_off + reg * 4;
	uint64_t val;
	bool intid_is_private = INTID_IS_SGI(intid) || INTID_IS_PPI(intid);

	uint32_t group = intid_is_private ? KVM_DEV_ARM_VGIC_GRP_REDIST_REGS
					  : KVM_DEV_ARM_VGIC_GRP_DIST_REGS;

	if (intid_is_private) {
		/* TODO: only vcpu 0 implemented for now. */
		assert(vcpu->id == 0);
		attr += SZ_64K;
	}

	/* Check that the addr part of the attr is within 32 bits. */
	assert((attr & ~KVM_DEV_ARM_VGIC_OFFSET_MASK) == 0);

	/*
	 * All calls will succeed, even with invalid intid's, as long as the
	 * addr part of the attr is within 32 bits (checked above). An invalid
	 * intid will just make the read/writes point to above the intended
	 * register space (i.e., ICPENDR after ISPENDR).
	 */
	kvm_device_attr_get(gic_fd, group, attr, &val);
	val |= 1ULL << index;
	kvm_device_attr_set(gic_fd, group, attr, &val);
}

void kvm_irq_write_ispendr(int gic_fd, uint32_t intid, struct kvm_vcpu *vcpu)
{
	vgic_poke_irq(gic_fd, intid, vcpu, GICD_ISPENDR);
}

void kvm_irq_write_isactiver(int gic_fd, uint32_t intid, struct kvm_vcpu *vcpu)
{
	vgic_poke_irq(gic_fd, intid, vcpu, GICD_ISACTIVER);
}

int vgic_its_setup(struct kvm_vm *vm)
{
	int its_fd = kvm_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_ITS);
	u64 attr;

	attr = GITS_BASE_GPA;
	kvm_device_attr_set(its_fd, KVM_DEV_ARM_VGIC_GRP_ADDR,
			    KVM_VGIC_ITS_ADDR_TYPE, &attr);

	kvm_device_attr_set(its_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
			    KVM_DEV_ARM_VGIC_CTRL_INIT, NULL);

	virt_map(vm, GITS_BASE_GPA, GITS_BASE_GPA,
		 vm_calc_num_guest_pages(vm->mode, KVM_VGIC_V3_ITS_SIZE));

	return its_fd;
}
