// SPDX-License-Identifier: GPL-2.0
/*
 * VMID allocator.
 *
 * Based on Arm64 ASID allocator algorithm.
 * Please refer arch/arm64/mm/context.c for detailed
 * comments on algorithm.
 *
 * Copyright (C) 2002-2003 Deep Blue Solutions Ltd, all rights reserved.
 * Copyright (C) 2012 ARM Ltd.
 */

#include <linux/bitfield.h>
#include <linux/bitops.h>

#include <asm/kvm_asm.h>
#include <asm/kvm_mmu.h>

unsigned int kvm_arm_vmid_bits;
static DEFINE_RAW_SPINLOCK(cpu_vmid_lock);

static atomic64_t vmid_generation;
static unsigned long *vmid_map;

static DEFINE_PER_CPU(atomic64_t, active_vmids);
static DEFINE_PER_CPU(u64, reserved_vmids);

#define VMID_MASK		(~GENMASK(kvm_arm_vmid_bits - 1, 0))
#define VMID_FIRST_VERSION	(1UL << kvm_arm_vmid_bits)

#define NUM_USER_VMIDS		VMID_FIRST_VERSION
#define vmid2idx(vmid)		((vmid) & ~VMID_MASK)
#define idx2vmid(idx)		vmid2idx(idx)

/*
 * As vmid #0 is always reserved, we will never allocate one
 * as below and can be treated as invalid. This is used to
 * set the active_vmids on vCPU schedule out.
 */
#define VMID_ACTIVE_INVALID		VMID_FIRST_VERSION

#define vmid_gen_match(vmid) \
	(!(((vmid) ^ atomic64_read(&vmid_generation)) >> kvm_arm_vmid_bits))

static void flush_context(void)
{
	int cpu;
	u64 vmid;

	bitmap_clear(vmid_map, 0, NUM_USER_VMIDS);

	for_each_possible_cpu(cpu) {
		vmid = atomic64_xchg_relaxed(&per_cpu(active_vmids, cpu), 0);

		/* Preserve reserved VMID */
		if (vmid == 0)
			vmid = per_cpu(reserved_vmids, cpu);
		__set_bit(vmid2idx(vmid), vmid_map);
		per_cpu(reserved_vmids, cpu) = vmid;
	}

	/*
	 * Unlike ASID allocator, we expect less frequent rollover in
	 * case of VMIDs. Hence, instead of marking the CPU as
	 * flush_pending and issuing a local context invalidation on
	 * the next context-switch, we broadcast TLB flush + I-cache
	 * invalidation over the inner shareable domain on rollover.
	 */
	 kvm_call_hyp(__kvm_flush_vm_context);
}

static bool check_update_reserved_vmid(u64 vmid, u64 newvmid)
{
	int cpu;
	bool hit = false;

	/*
	 * Iterate over the set of reserved VMIDs looking for a match
	 * and update to use newvmid (i.e. the same VMID in the current
	 * generation).
	 */
	for_each_possible_cpu(cpu) {
		if (per_cpu(reserved_vmids, cpu) == vmid) {
			hit = true;
			per_cpu(reserved_vmids, cpu) = newvmid;
		}
	}

	return hit;
}

static u64 new_vmid(struct kvm_vmid *kvm_vmid)
{
	static u32 cur_idx = 1;
	u64 vmid = atomic64_read(&kvm_vmid->id);
	u64 generation = atomic64_read(&vmid_generation);

	if (vmid != 0) {
		u64 newvmid = generation | (vmid & ~VMID_MASK);

		if (check_update_reserved_vmid(vmid, newvmid)) {
			atomic64_set(&kvm_vmid->id, newvmid);
			return newvmid;
		}

		if (!__test_and_set_bit(vmid2idx(vmid), vmid_map)) {
			atomic64_set(&kvm_vmid->id, newvmid);
			return newvmid;
		}
	}

	vmid = find_next_zero_bit(vmid_map, NUM_USER_VMIDS, cur_idx);
	if (vmid != NUM_USER_VMIDS)
		goto set_vmid;

	/* We're out of VMIDs, so increment the global generation count */
	generation = atomic64_add_return_relaxed(VMID_FIRST_VERSION,
						 &vmid_generation);
	flush_context();

	/* We have more VMIDs than CPUs, so this will always succeed */
	vmid = find_next_zero_bit(vmid_map, NUM_USER_VMIDS, 1);

set_vmid:
	__set_bit(vmid, vmid_map);
	cur_idx = vmid;
	vmid = idx2vmid(vmid) | generation;
	atomic64_set(&kvm_vmid->id, vmid);
	return vmid;
}

/* Called from vCPU sched out with preemption disabled */
void kvm_arm_vmid_clear_active(void)
{
	atomic64_set(this_cpu_ptr(&active_vmids), VMID_ACTIVE_INVALID);
}

void kvm_arm_vmid_update(struct kvm_vmid *kvm_vmid)
{
	unsigned long flags;
	u64 vmid, old_active_vmid;

	vmid = atomic64_read(&kvm_vmid->id);

	/*
	 * Please refer comments in check_and_switch_context() in
	 * arch/arm64/mm/context.c.
	 *
	 * Unlike ASID allocator, we set the active_vmids to
	 * VMID_ACTIVE_INVALID on vCPU schedule out to avoid
	 * reserving the VMID space needlessly on rollover.
	 * Hence explicitly check here for a "!= 0" to
	 * handle the sync with a concurrent rollover.
	 */
	old_active_vmid = atomic64_read(this_cpu_ptr(&active_vmids));
	if (old_active_vmid != 0 && vmid_gen_match(vmid) &&
	    0 != atomic64_cmpxchg_relaxed(this_cpu_ptr(&active_vmids),
					  old_active_vmid, vmid))
		return;

	raw_spin_lock_irqsave(&cpu_vmid_lock, flags);

	/* Check that our VMID belongs to the current generation. */
	vmid = atomic64_read(&kvm_vmid->id);
	if (!vmid_gen_match(vmid))
		vmid = new_vmid(kvm_vmid);

	atomic64_set(this_cpu_ptr(&active_vmids), vmid);
	raw_spin_unlock_irqrestore(&cpu_vmid_lock, flags);
}

/*
 * Initialize the VMID allocator
 */
int kvm_arm_vmid_alloc_init(void)
{
	kvm_arm_vmid_bits = kvm_get_vmid_bits();

	/*
	 * Expect allocation after rollover to fail if we don't have
	 * at least one more VMID than CPUs. VMID #0 is always reserved.
	 */
	WARN_ON(NUM_USER_VMIDS - 1 <= num_possible_cpus());
	atomic64_set(&vmid_generation, VMID_FIRST_VERSION);
	vmid_map = kcalloc(BITS_TO_LONGS(NUM_USER_VMIDS),
			   sizeof(*vmid_map), GFP_KERNEL);
	if (!vmid_map)
		return -ENOMEM;

	return 0;
}

void kvm_arm_vmid_alloc_free(void)
{
	kfree(vmid_map);
}
