// SPDX-License-Identifier: GPL-2.0
#include <linux/atomic.h>
#include <linux/mmu_context.h>
#include <linux/percpu.h>
#include <linux/spinlock.h>

static DEFINE_RAW_SPINLOCK(cpu_mmid_lock);

static atomic64_t mmid_version;
static unsigned int num_mmids;
static unsigned long *mmid_map;

static DEFINE_PER_CPU(u64, reserved_mmids);
static cpumask_t tlb_flush_pending;

static bool asid_versions_eq(int cpu, u64 a, u64 b)
{
	return ((a ^ b) & asid_version_mask(cpu)) == 0;
}

void get_new_mmu_context(struct mm_struct *mm)
{
	unsigned int cpu;
	u64 asid;

	/*
	 * This function is specific to ASIDs, and should not be called when
	 * MMIDs are in use.
	 */
	if (WARN_ON(IS_ENABLED(CONFIG_DEBUG_VM) && cpu_has_mmid))
		return;

	cpu = smp_processor_id();
	asid = asid_cache(cpu);

	if (!((asid += cpu_asid_inc()) & cpu_asid_mask(&cpu_data[cpu]))) {
		if (cpu_has_vtag_icache)
			flush_icache_all();
		local_flush_tlb_all();	/* start new asid cycle */
	}

	set_cpu_context(cpu, mm, asid);
	asid_cache(cpu) = asid;
}
EXPORT_SYMBOL_GPL(get_new_mmu_context);

void check_mmu_context(struct mm_struct *mm)
{
	unsigned int cpu = smp_processor_id();

	/*
	 * This function is specific to ASIDs, and should not be called when
	 * MMIDs are in use.
	 */
	if (WARN_ON(IS_ENABLED(CONFIG_DEBUG_VM) && cpu_has_mmid))
		return;

	/* Check if our ASID is of an older version and thus invalid */
	if (!asid_versions_eq(cpu, cpu_context(cpu, mm), asid_cache(cpu)))
		get_new_mmu_context(mm);
}
EXPORT_SYMBOL_GPL(check_mmu_context);

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

	/* Update the list of reserved MMIDs and the MMID bitmap */
	bitmap_zero(mmid_map, num_mmids);

	/* Reserve an MMID for kmap/wired entries */
	__set_bit(MMID_KERNEL_WIRED, mmid_map);

	for_each_possible_cpu(cpu) {
		mmid = xchg_relaxed(&cpu_data[cpu].asid_cache, 0);

		/*
		 * If this CPU has already been through a
		 * rollover, but hasn't run another task in
		 * the meantime, we must preserve its reserved
		 * MMID, as this is the only trace we have of
		 * the process it is still running.
		 */
		if (mmid == 0)
			mmid = per_cpu(reserved_mmids, cpu);

		__set_bit(mmid & cpu_asid_mask(&cpu_data[cpu]), mmid_map);
		per_cpu(reserved_mmids, cpu) = mmid;
	}

	/*
	 * Queue a TLB invalidation for each CPU to perform on next
	 * context-switch
	 */
	cpumask_setall(&tlb_flush_pending);
}

static bool check_update_reserved_mmid(u64 mmid, u64 newmmid)
{
	bool hit;
	int cpu;

	/*
	 * Iterate over the set of reserved MMIDs looking for a match.
	 * If we find one, then we can update our mm to use newmmid
	 * (i.e. the same MMID in the current generation) but we can't
	 * exit the loop early, since we need to ensure that all copies
	 * of the old MMID are updated to reflect the mm. Failure to do
	 * so could result in us missing the reserved MMID in a future
	 * generation.
	 */
	hit = false;
	for_each_possible_cpu(cpu) {
		if (per_cpu(reserved_mmids, cpu) == mmid) {
			hit = true;
			per_cpu(reserved_mmids, cpu) = newmmid;
		}
	}

	return hit;
}

static u64 get_new_mmid(struct mm_struct *mm)
{
	static u32 cur_idx = MMID_KERNEL_WIRED + 1;
	u64 mmid, version, mmid_mask;

	mmid = cpu_context(0, mm);
	version = atomic64_read(&mmid_version);
	mmid_mask = cpu_asid_mask(&boot_cpu_data);

	if (!asid_versions_eq(0, mmid, 0)) {
		u64 newmmid = version | (mmid & mmid_mask);

		/*
		 * If our current MMID was active during a rollover, we
		 * can continue to use it and this was just a false alarm.
		 */
		if (check_update_reserved_mmid(mmid, newmmid)) {
			mmid = newmmid;
			goto set_context;
		}

		/*
		 * We had a valid MMID in a previous life, so try to re-use
		 * it if possible.
		 */
		if (!__test_and_set_bit(mmid & mmid_mask, mmid_map)) {
			mmid = newmmid;
			goto set_context;
		}
	}

	/* Allocate a free MMID */
	mmid = find_next_zero_bit(mmid_map, num_mmids, cur_idx);
	if (mmid != num_mmids)
		goto reserve_mmid;

	/* We're out of MMIDs, so increment the global version */
	version = atomic64_add_return_relaxed(asid_first_version(0),
					      &mmid_version);

	/* Note currently active MMIDs & mark TLBs as requiring flushes */
	flush_context();

	/* We have more MMIDs than CPUs, so this will always succeed */
	mmid = find_first_zero_bit(mmid_map, num_mmids);

reserve_mmid:
	__set_bit(mmid, mmid_map);
	cur_idx = mmid;
	mmid |= version;
set_context:
	set_cpu_context(0, mm, mmid);
	return mmid;
}

void check_switch_mmu_context(struct mm_struct *mm)
{
	unsigned int cpu = smp_processor_id();
	u64 ctx, old_active_mmid;
	unsigned long flags;

	if (!cpu_has_mmid) {
		check_mmu_context(mm);
		write_c0_entryhi(cpu_asid(cpu, mm));
		goto setup_pgd;
	}

	/*
	 * MMID switch fast-path, to avoid acquiring cpu_mmid_lock when it's
	 * unnecessary.
	 *
	 * The memory ordering here is subtle. If our active_mmids is non-zero
	 * and the MMID matches the current version, then we update the CPU's
	 * asid_cache with a relaxed cmpxchg. Racing with a concurrent rollover
	 * means that either:
	 *
	 * - We get a zero back from the cmpxchg and end up waiting on
	 *   cpu_mmid_lock in check_mmu_context(). Taking the lock synchronises
	 *   with the rollover and so we are forced to see the updated
	 *   generation.
	 *
	 * - We get a valid MMID back from the cmpxchg, which means the
	 *   relaxed xchg in flush_context will treat us as reserved
	 *   because atomic RmWs are totally ordered for a given location.
	 */
	ctx = cpu_context(cpu, mm);
	old_active_mmid = READ_ONCE(cpu_data[cpu].asid_cache);
	if (!old_active_mmid ||
	    !asid_versions_eq(cpu, ctx, atomic64_read(&mmid_version)) ||
	    !cmpxchg_relaxed(&cpu_data[cpu].asid_cache, old_active_mmid, ctx)) {
		raw_spin_lock_irqsave(&cpu_mmid_lock, flags);

		ctx = cpu_context(cpu, mm);
		if (!asid_versions_eq(cpu, ctx, atomic64_read(&mmid_version)))
			ctx = get_new_mmid(mm);

		WRITE_ONCE(cpu_data[cpu].asid_cache, ctx);
		raw_spin_unlock_irqrestore(&cpu_mmid_lock, flags);
	}

	/*
	 * Invalidate the local TLB if needed. Note that we must only clear our
	 * bit in tlb_flush_pending after this is complete, so that the
	 * cpu_has_shared_ftlb_entries case below isn't misled.
	 */
	if (cpumask_test_cpu(cpu, &tlb_flush_pending)) {
		if (cpu_has_vtag_icache)
			flush_icache_all();
		local_flush_tlb_all();
		cpumask_clear_cpu(cpu, &tlb_flush_pending);
	}

	write_c0_memorymapid(ctx & cpu_asid_mask(&boot_cpu_data));

	/*
	 * If this CPU shares FTLB entries with its siblings and one or more of
	 * those siblings hasn't yet invalidated its TLB following a version
	 * increase then we need to invalidate any TLB entries for our MMID
	 * that we might otherwise pick up from a sibling.
	 *
	 * We ifdef on CONFIG_SMP because cpu_sibling_map isn't defined in
	 * CONFIG_SMP=n kernels.
	 */
#ifdef CONFIG_SMP
	if (cpu_has_shared_ftlb_entries &&
	    cpumask_intersects(&tlb_flush_pending, &cpu_sibling_map[cpu])) {
		/* Ensure we operate on the new MMID */
		mtc0_tlbw_hazard();

		/*
		 * Invalidate all TLB entries associated with the new
		 * MMID, and wait for the invalidation to complete.
		 */
		ginvt_mmid();
		sync_ginv();
	}
#endif

setup_pgd:
	TLBMISS_HANDLER_SETUP_PGD(mm->pgd);
}
EXPORT_SYMBOL_GPL(check_switch_mmu_context);

static int mmid_init(void)
{
	if (!cpu_has_mmid)
		return 0;

	/*
	 * Expect allocation after rollover to fail if we don't have at least
	 * one more MMID than CPUs.
	 */
	num_mmids = asid_first_version(0);
	WARN_ON(num_mmids <= num_possible_cpus());

	atomic64_set(&mmid_version, asid_first_version(0));
	mmid_map = bitmap_zalloc(num_mmids, GFP_KERNEL);
	if (!mmid_map)
		panic("Failed to allocate bitmap for %u MMIDs\n", num_mmids);

	/* Reserve an MMID for kmap/wired entries */
	__set_bit(MMID_KERNEL_WIRED, mmid_map);

	pr_info("MMID allocator initialised with %u entries\n", num_mmids);
	return 0;
}
early_initcall(mmid_init);
