/*
 * Copyright 2019 Advanced Micro Devices, Inc.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: AMD
 *
 */

#include "mod_vmid.h"

struct core_vmid {
	struct mod_vmid public;
	struct dc *dc;

	unsigned int num_vmid;
	unsigned int num_vmids_available;
	uint64_t ptb_assigned_to_vmid[MAX_VMID];
	struct dc_virtual_addr_space_config base_config;
};

#define MOD_VMID_TO_CORE(mod_vmid)\
		container_of(mod_vmid, struct core_vmid, public)

static void add_ptb_to_table(struct core_vmid *core_vmid, unsigned int vmid, uint64_t ptb)
{
	core_vmid->ptb_assigned_to_vmid[vmid] = ptb;
	core_vmid->num_vmids_available--;
}

static void clear_entry_from_vmid_table(struct core_vmid *core_vmid, unsigned int vmid)
{
	core_vmid->ptb_assigned_to_vmid[vmid] = 0;
	core_vmid->num_vmids_available++;
}

static void evict_vmids(struct core_vmid *core_vmid)
{
	int i;
	uint16_t ord = dc_get_vmid_use_vector(core_vmid->dc);

	// At this point any positions with value 0 are unused vmids, evict them
	for (i = 1; i < core_vmid->num_vmid; i++) {
		if (ord & (1u << i))
			clear_entry_from_vmid_table(core_vmid, i);
	}
}

// Return value of -1 indicates vmid table unitialized or ptb dne in the table
static int get_existing_vmid_for_ptb(struct core_vmid *core_vmid, uint64_t ptb)
{
	int i;

	for (i = 0; i < core_vmid->num_vmid; i++) {
		if (core_vmid->ptb_assigned_to_vmid[i] == ptb)
			return i;
	}

	return -1;
}

// Expected to be called only when there's an available vmid
static int get_next_available_vmid(struct core_vmid *core_vmid)
{
	int i;

	for (i = 1; i < core_vmid->num_vmid; i++) {
		if (core_vmid->ptb_assigned_to_vmid[i] == 0)
			return i;
	}

	return -1;
}

uint8_t mod_vmid_get_for_ptb(struct mod_vmid *mod_vmid, uint64_t ptb)
{
	struct core_vmid *core_vmid = MOD_VMID_TO_CORE(mod_vmid);
	unsigned int vmid = 0;

	// Physical address gets vmid 0
	if (ptb == 0)
		return 0;

	vmid = get_existing_vmid_for_ptb(core_vmid, ptb);

	if (vmid == -1) {
		struct dc_virtual_addr_space_config va_config = core_vmid->base_config;

		va_config.page_table_base_addr = ptb;

		if (core_vmid->num_vmids_available == 0)
			evict_vmids(core_vmid);

		vmid = get_next_available_vmid(core_vmid);
		add_ptb_to_table(core_vmid, vmid, ptb);

		dc_setup_vm_context(core_vmid->dc, &va_config, vmid);
	}

	return vmid;
}

void mod_vmid_reset(struct mod_vmid *mod_vmid)
{
	struct core_vmid *core_vmid = MOD_VMID_TO_CORE(mod_vmid);

	core_vmid->num_vmids_available = core_vmid->num_vmid - 1;
	memset(core_vmid->ptb_assigned_to_vmid, 0, sizeof(core_vmid->ptb_assigned_to_vmid[0]) * MAX_VMID);
}

struct mod_vmid *mod_vmid_create(
		struct dc *dc,
		unsigned int num_vmid,
		struct dc_virtual_addr_space_config *va_config)
{
	struct core_vmid *core_vmid;

	if (num_vmid <= 1)
		goto fail_no_vm_ctx;

	if (dc == NULL)
		goto fail_dc_null;

	core_vmid = kzalloc(sizeof(struct core_vmid), GFP_KERNEL);

	if (core_vmid == NULL)
		goto fail_alloc_context;

	core_vmid->dc = dc;
	core_vmid->num_vmid = num_vmid;
	core_vmid->num_vmids_available = num_vmid - 1;
	core_vmid->base_config = *va_config;

	memset(core_vmid->ptb_assigned_to_vmid, 0, sizeof(core_vmid->ptb_assigned_to_vmid[0]) * MAX_VMID);

	return &core_vmid->public;

fail_no_vm_ctx:
fail_alloc_context:
fail_dc_null:
	return NULL;
}

void mod_vmid_destroy(struct mod_vmid *mod_vmid)
{
	if (mod_vmid != NULL) {
		struct core_vmid *core_vmid = MOD_VMID_TO_CORE(mod_vmid);

		kfree(core_vmid);
	}
}
