// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2021 - Google LLC
 * Author: David Brazdil <dbrazdil@google.com>
 */

#include <linux/kcov.h>
#include <linux/kvm_host.h>

#include <asm/kvm_mmu.h>

#define KVM_KCOV_DISABLED		0
#define KVM_KCOV_ENABLED		BIT(0)
#define KVM_KCOV_PREEMPT		BIT(1)

static void kcov_stop_kvm_cb(void);

static kvm_pfn_t *kcov_map_area(void *start, size_t size)
{
	kvm_pfn_t *pfns;
	void *cur, *end = start + PAGE_ALIGN(size * sizeof(unsigned long));
	size_t nr_pfns, idx;
	int ret;

	/*
	 * The following code assumes area is page-aligned. Otherwise need
	 * to account for the offset in all pages.
	 */
	WARN_ON(!PAGE_ALIGNED(start));

	nr_pfns = (end - start) / PAGE_SIZE;
	pfns = kmalloc(sizeof(kvm_pfn_t) * nr_pfns, GFP_KERNEL);
	BUG_ON(!pfns);

	for (cur = start; cur < end; cur += PAGE_SIZE) {
		idx = (cur - start) / PAGE_SIZE;
		pfns[idx] = __phys_to_pfn(page_to_phys(vmalloc_to_page(cur)));

		ret = kvm_share_hyp(cur, cur + PAGE_SIZE - 1); /* XXX */
		BUG_ON(ret);
	}

	ret = kvm_share_hyp(pfns, pfns + nr_pfns);
	BUG_ON(ret);
	return pfns;
}

static void kcov_unmap_area(kvm_pfn_t *pfns, void *start, size_t size)
{
	void *cur, *end = start + PAGE_ALIGN(size * sizeof(unsigned long));
	size_t nr_pfns = (end - start) / PAGE_SIZE;

	for (cur = start; cur < end; cur += PAGE_SIZE)
		kvm_unshare_hyp(cur, cur + PAGE_SIZE - 1); /* XXX */

	kvm_unshare_hyp(pfns, pfns + nr_pfns);
	kfree(pfns);
}

int kcov_start_kvm(void)
{
	struct task_struct *t = current;
	kvm_pfn_t *pfns;
	int err, ret = KVM_KCOV_ENABLED;

	/* Step 1: Are we in a task? */
	if (!in_task())
		return KVM_KCOV_DISABLED;

	/* Step 2: Is kcov enabled for this task? Are we inside a kcov hyp section already? */
	switch (t->kcov_mode) {
	case KCOV_MODE_TRACE_PC:
		kcov_prepare_switch(t); /* modifies mode, fails step 4 */
		break;
	default:
		return KVM_KCOV_DISABLED;
	}

	/* Step 3: Should we map in the area? */
	if (!t->kcov_stop_cb) {
		t->kcov_stop_cb = kcov_stop_kvm_cb;
		t->kcov_stop_cb_arg = kcov_map_area(t->kcov_area, t->kcov_size);
	} else if (t->kcov_stop_cb != kcov_stop_kvm_cb) {
		return KVM_KCOV_DISABLED;
	}
	pfns = t->kcov_stop_cb_arg;

	/* Step 4: Disable preemption to pin the area to this core. */
	if (preemptible()) {
		preempt_disable();
		ret |= KVM_KCOV_PREEMPT;
	}

	/* Step 5: Tell hyp to use this area. */
	err = kvm_call_hyp_nvhe(__kvm_kcov_set_area, kern_hyp_va(pfns), t->kcov_size);
	BUG_ON(err);

	return ret;
}

void kcov_stop_kvm(int ret)
{
	struct task_struct *t = current;

	if (!(ret & KVM_KCOV_ENABLED))
		return;

	/* Step 5B: Tell hyp to stop using this area. */
	WARN_ON(kvm_call_hyp_nvhe(__kvm_kcov_set_area, NULL, 0));

	/* Step 4B: Reenable preemption. */
	if (ret & KVM_KCOV_PREEMPT)
		preempt_enable();

	/* Step 2B: Get out of the kcov hyp section. */
	kcov_finish_switch(t);
}

static void kcov_stop_kvm_cb(void)
{
	struct task_struct *t = current;

	/* Warn if still in the kcov hyp section. */
	WARN_ON(t->kcov_mode != KCOV_MODE_TRACE_PC);

	kcov_prepare_switch(t);
	kcov_unmap_area(t->kcov_stop_cb_arg, t->kcov_area, t->kcov_size);
	kcov_finish_switch(t);
}
