/*
 *
 * (C) COPYRIGHT 2010-2018 ARM Limited. All rights reserved.
 *
 * This program is free software and is provided to you under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation, and any use by you of this program is subject to the terms
 * of such GNU licence.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you can access it online at
 * http://www.gnu.org/licenses/gpl-2.0.html.
 *
 * SPDX-License-Identifier: GPL-2.0
 *
 */

#include "mali_kbase_gwt.h"
#include <linux/list_sort.h>

static inline void kbase_gpu_gwt_setup_page_permission(
				struct kbase_context *kctx,
				unsigned long flag,
				struct rb_node *node)
{
	struct rb_node *rbnode = node;

	while (rbnode) {
		struct kbase_va_region *reg;
		int err = 0;

		reg = rb_entry(rbnode, struct kbase_va_region, rblink);
		if (reg->nr_pages && !(reg->flags & KBASE_REG_FREE) &&
					(reg->flags & KBASE_REG_GPU_WR)) {
			err = kbase_mmu_update_pages(kctx, reg->start_pfn,
					kbase_get_gpu_phy_pages(reg),
					reg->gpu_alloc->nents,
					reg->flags & flag);
			if (err)
				dev_warn(kctx->kbdev->dev, "kbase_mmu_update_pages failure\n");
		}

		rbnode = rb_next(rbnode);
	}
}

static void kbase_gpu_gwt_setup_pages(struct kbase_context *kctx,
					unsigned long flag)
{
	kbase_gpu_gwt_setup_page_permission(kctx, flag,
				rb_first(&(kctx->reg_rbtree_same)));
	kbase_gpu_gwt_setup_page_permission(kctx, flag,
				rb_first(&(kctx->reg_rbtree_exec)));
	kbase_gpu_gwt_setup_page_permission(kctx, flag,
				rb_first(&(kctx->reg_rbtree_custom)));
}


int kbase_gpu_gwt_start(struct kbase_context *kctx)
{
	kbase_gpu_vm_lock(kctx);
	if (kctx->gwt_enabled) {
		kbase_gpu_vm_unlock(kctx);
		return -EBUSY;
	}

	INIT_LIST_HEAD(&kctx->gwt_current_list);
	INIT_LIST_HEAD(&kctx->gwt_snapshot_list);

	/* If GWT is enabled using new vector dumping format
	 * from user space, back up status of the job serialization flag and
	 * use full serialisation of jobs for dumping.
	 * Status will be restored on end of dumping in gwt_stop.
	 */
	kctx->kbdev->backup_serialize_jobs = kctx->kbdev->serialize_jobs;
	kctx->kbdev->serialize_jobs = KBASE_SERIALIZE_INTRA_SLOT |
						KBASE_SERIALIZE_INTER_SLOT;

	/* Mark gwt enabled before making pages read only in case a
	   write page fault is triggered while we're still in this loop.
	   (kbase_gpu_vm_lock() doesn't prevent this!)
	*/
	kctx->gwt_enabled = true;
	kctx->gwt_was_enabled = true;

	kbase_gpu_gwt_setup_pages(kctx, ~KBASE_REG_GPU_WR);

	kbase_gpu_vm_unlock(kctx);
	return 0;
}

int kbase_gpu_gwt_stop(struct kbase_context *kctx)
{
	struct kbasep_gwt_list_element *pos, *n;

	kbase_gpu_vm_lock(kctx);
	if (!kctx->gwt_enabled) {
		kbase_gpu_vm_unlock(kctx);
		return -EINVAL;
	}

	list_for_each_entry_safe(pos, n, &kctx->gwt_current_list, link) {
		list_del(&pos->link);
		kfree(pos);
	}

	list_for_each_entry_safe(pos, n, &kctx->gwt_snapshot_list, link) {
		list_del(&pos->link);
		kfree(pos);
	}

	kctx->kbdev->serialize_jobs = kctx->kbdev->backup_serialize_jobs;

	kbase_gpu_gwt_setup_pages(kctx, ~0UL);

	kctx->gwt_enabled = false;
	kbase_gpu_vm_unlock(kctx);
	return 0;
}


static int list_cmp_function(void *priv, struct list_head *a,
				struct list_head *b)
{
	struct kbasep_gwt_list_element *elementA = container_of(a,
				struct kbasep_gwt_list_element, link);
	struct kbasep_gwt_list_element *elementB = container_of(b,
				struct kbasep_gwt_list_element, link);

	CSTD_UNUSED(priv);

	if (elementA->page_addr > elementB->page_addr)
		return 1;
	return -1;
}

static void kbase_gpu_gwt_collate(struct kbase_context *kctx,
		struct list_head *snapshot_list)
{
	struct kbasep_gwt_list_element *pos, *n;
	struct kbasep_gwt_list_element *collated = NULL;

	/* Sort the list */
	list_sort(NULL, snapshot_list, list_cmp_function);

	/* Combine contiguous areas. */
	list_for_each_entry_safe(pos, n, snapshot_list, link) {
		if (collated == NULL ||	collated->region !=
					pos->region ||
					(collated->page_addr +
					(collated->num_pages * PAGE_SIZE)) !=
					pos->page_addr) {
			/* This is the first time through, a new region or
			 * is not contiguous - start collating to this element
			 */
			collated = pos;
		} else {
			/* contiguous so merge */
			collated->num_pages += pos->num_pages;
			/* remove element from list */
			list_del(&pos->link);
			kfree(pos);
		}
	}
}

int kbase_gpu_gwt_dump(struct kbase_context *kctx,
			union kbase_ioctl_cinstr_gwt_dump *gwt_dump)
{
	const u32 ubuf_size = gwt_dump->in.len;
	u32 ubuf_count = 0;
	__user void *user_addr = (__user void *)
			(uintptr_t)gwt_dump->in.addr_buffer;
	__user void *user_sizes = (__user void *)
			(uintptr_t)gwt_dump->in.size_buffer;

	kbase_gpu_vm_lock(kctx);

	if (!kctx->gwt_enabled) {
		kbase_gpu_vm_unlock(kctx);
		/* gwt_dump shouldn't be called when gwt is disabled */
		return -EPERM;
	}

	if (!gwt_dump->in.len || !gwt_dump->in.addr_buffer
			|| !gwt_dump->in.size_buffer) {
		kbase_gpu_vm_unlock(kctx);
		/* We don't have any valid user space buffer to copy the
		 * write modified addresses.
		 */
		return -EINVAL;
	}

	if (list_empty(&kctx->gwt_snapshot_list) &&
			!list_empty(&kctx->gwt_current_list)) {

		list_replace_init(&kctx->gwt_current_list,
					&kctx->gwt_snapshot_list);

		/* We have collected all write faults so far
		 * and they will be passed on to user space.
		 * Reset the page flags state to allow collection of
		 * further write faults.
		 */
		kbase_gpu_gwt_setup_pages(kctx, ~KBASE_REG_GPU_WR);

		/* Sort and combine consecutive pages in the dump list*/
		kbase_gpu_gwt_collate(kctx, &kctx->gwt_snapshot_list);
	}

	while ((!list_empty(&kctx->gwt_snapshot_list))) {
		u64 addr_buffer[32];
		u64 num_page_buffer[32];
		u32 count = 0;
		int err;
		struct kbasep_gwt_list_element *dump_info, *n;

		list_for_each_entry_safe(dump_info, n,
				&kctx->gwt_snapshot_list, link) {
			addr_buffer[count] = dump_info->page_addr;
			num_page_buffer[count] = dump_info->num_pages;
			count++;
			list_del(&dump_info->link);
			kfree(dump_info);
			if (ARRAY_SIZE(addr_buffer) == count ||
					ubuf_size == (ubuf_count + count))
				break;
		}

		if (count) {
			err = copy_to_user((user_addr +
					(ubuf_count * sizeof(u64))),
					(void *)addr_buffer,
					count * sizeof(u64));
			if (err) {
				dev_err(kctx->kbdev->dev, "Copy to user failure\n");
				kbase_gpu_vm_unlock(kctx);
				return err;
			}
			err = copy_to_user((user_sizes +
					(ubuf_count * sizeof(u64))),
					(void *)num_page_buffer,
					count * sizeof(u64));
			if (err) {
				dev_err(kctx->kbdev->dev, "Copy to user failure\n");
				kbase_gpu_vm_unlock(kctx);
				return err;
			}

			ubuf_count += count;
		}

		if (ubuf_count == ubuf_size)
			break;
	}

	if (!list_empty(&kctx->gwt_snapshot_list))
		gwt_dump->out.more_data_available = 1;
	else
		gwt_dump->out.more_data_available = 0;

	gwt_dump->out.no_of_addr_collected = ubuf_count;
	kbase_gpu_vm_unlock(kctx);
	return 0;
}
