// 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"

bool kvm_supports_vgic_v3(void)
{
	struct kvm_vm *vm = vm_create_barebones();
	int r;

	r = __kvm_test_create_device(vm, KVM_DEV_TYPE_ARM_VGIC_V3);
	kvm_vm_free(vm);

	return !r;
}

/*
 * 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, u32 nr_irqs)
{
	int gic_fd;
	u64 attr;
	unsigned int nr_gic_pages;

	/* 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);

	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);

	return gic_fd;
}

void __vgic_v3_init(int fd)
{
	kvm_device_attr_set(fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
			    KVM_DEV_ARM_VGIC_CTRL_INIT, NULL);
}

int vgic_v3_setup(struct kvm_vm *vm, unsigned int nr_vcpus, u32 nr_irqs)
{
	unsigned int nr_vcpus_created = 0;
	struct list_head *iter;
	int fd;

	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);

	fd = __vgic_v3_setup(vm, nr_vcpus, nr_irqs);
	if (fd < 0)
		return fd;

	__vgic_v3_init(fd);
	return fd;
}

/* should only work for level sensitive interrupts */
int _kvm_irq_set_level_info(int gic_fd, u32 intid, int level)
{
	u64 attr = 32 * (intid / 32);
	u64 index = intid % 32;
	u64 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, u32 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, u32 intid, int level)
{
	u32 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, u32 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, u32 intid, struct kvm_vcpu *vcpu,
			  u64 reg_off)
{
	u64 reg = intid / 32;
	u64 index = intid % 32;
	u64 attr = reg_off + reg * 4;
	u64 val;
	bool intid_is_private = INTID_IS_SGI(intid) || INTID_IS_PPI(intid);

	u32 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, u32 intid, struct kvm_vcpu *vcpu)
{
	vgic_poke_irq(gic_fd, intid, vcpu, GICD_ISPENDR);
}

void kvm_irq_write_isactiver(int gic_fd, u32 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;
}
