/*
 * Copyright(c) 2011-2017 Intel Corporation. All rights reserved.
 *
 * 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 (including the next
 * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
 */
#include "i915_drv.h"
#include "gvt.h"

/**
 * intel_vgpu_find_page_track - find page track rcord of guest page
 * @vgpu: a vGPU
 * @gfn: the gfn of guest page
 *
 * Returns:
 * A pointer to struct intel_vgpu_page_track if found, else NULL returned.
 */
struct intel_vgpu_page_track *intel_vgpu_find_page_track(
		struct intel_vgpu *vgpu, unsigned long gfn)
{
	return radix_tree_lookup(&vgpu->page_track_tree, gfn);
}

/**
 * intel_vgpu_register_page_track - register a guest page to be tacked
 * @vgpu: a vGPU
 * @gfn: the gfn of guest page
 * @handler: page track handler
 * @priv: tracker private
 *
 * Returns:
 * zero on success, negative error code if failed.
 */
int intel_vgpu_register_page_track(struct intel_vgpu *vgpu, unsigned long gfn,
		gvt_page_track_handler_t handler, void *priv)
{
	struct intel_vgpu_page_track *track;
	int ret;

	track = intel_vgpu_find_page_track(vgpu, gfn);
	if (track)
		return -EEXIST;

	track = kzalloc(sizeof(*track), GFP_KERNEL);
	if (!track)
		return -ENOMEM;

	track->handler = handler;
	track->priv_data = priv;

	ret = radix_tree_insert(&vgpu->page_track_tree, gfn, track);
	if (ret) {
		kfree(track);
		return ret;
	}

	return 0;
}

/**
 * intel_vgpu_unregister_page_track - unregister the tracked guest page
 * @vgpu: a vGPU
 * @gfn: the gfn of guest page
 *
 */
void intel_vgpu_unregister_page_track(struct intel_vgpu *vgpu,
		unsigned long gfn)
{
	struct intel_vgpu_page_track *track;

	track = radix_tree_delete(&vgpu->page_track_tree, gfn);
	if (track) {
		if (track->tracked)
			intel_gvt_page_track_remove(vgpu, gfn);
		kfree(track);
	}
}

/**
 * intel_vgpu_enable_page_track - set write-protection on guest page
 * @vgpu: a vGPU
 * @gfn: the gfn of guest page
 *
 * Returns:
 * zero on success, negative error code if failed.
 */
int intel_vgpu_enable_page_track(struct intel_vgpu *vgpu, unsigned long gfn)
{
	struct intel_vgpu_page_track *track;
	int ret;

	track = intel_vgpu_find_page_track(vgpu, gfn);
	if (!track)
		return -ENXIO;

	if (track->tracked)
		return 0;

	ret = intel_gvt_page_track_add(vgpu, gfn);
	if (ret)
		return ret;
	track->tracked = true;
	return 0;
}

/**
 * intel_vgpu_disable_page_track - cancel write-protection on guest page
 * @vgpu: a vGPU
 * @gfn: the gfn of guest page
 *
 * Returns:
 * zero on success, negative error code if failed.
 */
int intel_vgpu_disable_page_track(struct intel_vgpu *vgpu, unsigned long gfn)
{
	struct intel_vgpu_page_track *track;
	int ret;

	track = intel_vgpu_find_page_track(vgpu, gfn);
	if (!track)
		return -ENXIO;

	if (!track->tracked)
		return 0;

	ret = intel_gvt_page_track_remove(vgpu, gfn);
	if (ret)
		return ret;
	track->tracked = false;
	return 0;
}

/**
 * intel_vgpu_page_track_handler - called when write to write-protected page
 * @vgpu: a vGPU
 * @gpa: the gpa of this write
 * @data: the writed data
 * @bytes: the length of this write
 *
 * Returns:
 * zero on success, negative error code if failed.
 */
int intel_vgpu_page_track_handler(struct intel_vgpu *vgpu, u64 gpa,
		void *data, unsigned int bytes)
{
	struct intel_vgpu_page_track *page_track;
	int ret = 0;

	page_track = intel_vgpu_find_page_track(vgpu, gpa >> PAGE_SHIFT);
	if (!page_track)
		return -ENXIO;

	if (unlikely(vgpu->failsafe)) {
		/* Remove write protection to prevent furture traps. */
		intel_gvt_page_track_remove(vgpu, gpa >> PAGE_SHIFT);
	} else {
		ret = page_track->handler(page_track, gpa, data, bytes);
		if (ret)
			gvt_err("guest page write error, gpa %llx\n", gpa);
	}

	return ret;
}
