// SPDX-License-Identifier: GPL-2.0-only
//
// VCPU stall detector.
//  Copyright (C) Google, 2022

#include <linux/cpu.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>

#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/nmi.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/param.h>
#include <linux/percpu.h>
#include <linux/platform_device.h>
#include <linux/slab.h>

#define VCPU_STALL_REG_STATUS		(0x00)
#define VCPU_STALL_REG_LOAD_CNT		(0x04)
#define VCPU_STALL_REG_CURRENT_CNT	(0x08)
#define VCPU_STALL_REG_CLOCK_FREQ_HZ	(0x0C)
#define VCPU_STALL_REG_LEN		(0x10)

#define VCPU_STALL_DEFAULT_CLOCK_HZ	(10)
#define VCPU_STALL_MAX_CLOCK_HZ		(100)
#define VCPU_STALL_DEFAULT_TIMEOUT_SEC	(8)
#define VCPU_STALL_MAX_TIMEOUT_SEC	(600)

struct vcpu_stall_detect_config {
	u32 clock_freq_hz;
	u32 stall_timeout_sec;

	void __iomem *membase;
	struct platform_device *dev;
	enum cpuhp_state hp_online;
};

struct vcpu_stall_priv {
	struct hrtimer vcpu_hrtimer;
	bool is_initialized;
};

/* The vcpu stall configuration structure which applies to all the CPUs */
static struct vcpu_stall_detect_config vcpu_stall_config;

#define vcpu_stall_reg_write(vcpu, reg, value)				\
	writel_relaxed((value),						\
		       (void __iomem *)(vcpu_stall_config.membase +	\
		       (vcpu) * VCPU_STALL_REG_LEN + (reg)))


static struct vcpu_stall_priv __percpu *vcpu_stall_detectors;

static enum hrtimer_restart
vcpu_stall_detect_timer_fn(struct hrtimer *hrtimer)
{
	u32 ticks, ping_timeout_ms;

	/* Reload the stall detector counter register every
	 * `ping_timeout_ms` to prevent the virtual device
	 * from decrementing it to 0. The virtual device decrements this
	 * register at 'clock_freq_hz' frequency.
	 */
	ticks = vcpu_stall_config.clock_freq_hz *
		vcpu_stall_config.stall_timeout_sec;
	vcpu_stall_reg_write(smp_processor_id(),
			     VCPU_STALL_REG_LOAD_CNT, ticks);

	ping_timeout_ms = vcpu_stall_config.stall_timeout_sec *
			  MSEC_PER_SEC / 2;
	hrtimer_forward_now(hrtimer,
			    ms_to_ktime(ping_timeout_ms));

	return HRTIMER_RESTART;
}

static int start_stall_detector_cpu(unsigned int cpu)
{
	u32 ticks, ping_timeout_ms;
	struct vcpu_stall_priv *vcpu_stall_detector =
		this_cpu_ptr(vcpu_stall_detectors);
	struct hrtimer *vcpu_hrtimer = &vcpu_stall_detector->vcpu_hrtimer;

	vcpu_stall_reg_write(cpu, VCPU_STALL_REG_CLOCK_FREQ_HZ,
			     vcpu_stall_config.clock_freq_hz);

	/* Compute the number of ticks required for the stall detector
	 * counter register based on the internal clock frequency and the
	 * timeout value given from the device tree.
	 */
	ticks = vcpu_stall_config.clock_freq_hz *
		vcpu_stall_config.stall_timeout_sec;
	vcpu_stall_reg_write(cpu, VCPU_STALL_REG_LOAD_CNT, ticks);

	/* Enable the internal clock and start the stall detector */
	vcpu_stall_reg_write(cpu, VCPU_STALL_REG_STATUS, 1);

	/* Pet the stall detector at half of its expiration timeout
	 * to prevent spurious resets.
	 */
	ping_timeout_ms = vcpu_stall_config.stall_timeout_sec *
			  MSEC_PER_SEC / 2;

	hrtimer_init(vcpu_hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	vcpu_hrtimer->function = vcpu_stall_detect_timer_fn;
	vcpu_stall_detector->is_initialized = true;

	hrtimer_start(vcpu_hrtimer, ms_to_ktime(ping_timeout_ms),
		      HRTIMER_MODE_REL_PINNED);

	return 0;
}

static int stop_stall_detector_cpu(unsigned int cpu)
{
	struct vcpu_stall_priv *vcpu_stall_detector =
		per_cpu_ptr(vcpu_stall_detectors, cpu);

	if (!vcpu_stall_detector->is_initialized)
		return 0;

	/* Disable the stall detector for the current CPU */
	hrtimer_cancel(&vcpu_stall_detector->vcpu_hrtimer);
	vcpu_stall_reg_write(cpu, VCPU_STALL_REG_STATUS, 0);
	vcpu_stall_detector->is_initialized = false;

	return 0;
}

static int vcpu_stall_detect_probe(struct platform_device *pdev)
{
	int ret;
	struct resource *r;
	void __iomem *membase;
	u32 clock_freq_hz = VCPU_STALL_DEFAULT_CLOCK_HZ;
	u32 stall_timeout_sec = VCPU_STALL_DEFAULT_TIMEOUT_SEC;
	struct device_node *np = pdev->dev.of_node;

	vcpu_stall_detectors = devm_alloc_percpu(&pdev->dev,
						 typeof(struct vcpu_stall_priv));
	if (!vcpu_stall_detectors)
		return -ENOMEM;

	membase = devm_platform_get_and_ioremap_resource(pdev, 0, &r);
	if (IS_ERR(membase)) {
		dev_err(&pdev->dev, "Failed to get memory resource\n");
		return PTR_ERR(membase);
	}

	if (!of_property_read_u32(np, "clock-frequency", &clock_freq_hz)) {
		if (!(clock_freq_hz > 0 &&
		      clock_freq_hz < VCPU_STALL_MAX_CLOCK_HZ)) {
			dev_warn(&pdev->dev, "clk out of range\n");
			clock_freq_hz = VCPU_STALL_DEFAULT_CLOCK_HZ;
		}
	}

	if (!of_property_read_u32(np, "timeout-sec", &stall_timeout_sec)) {
		if (!(stall_timeout_sec > 0 &&
		      stall_timeout_sec < VCPU_STALL_MAX_TIMEOUT_SEC)) {
			dev_warn(&pdev->dev, "stall timeout out of range\n");
			stall_timeout_sec = VCPU_STALL_DEFAULT_TIMEOUT_SEC;
		}
	}

	vcpu_stall_config = (struct vcpu_stall_detect_config) {
		.membase		= membase,
		.clock_freq_hz		= clock_freq_hz,
		.stall_timeout_sec	= stall_timeout_sec
	};

	ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
				"virt/vcpu_stall_detector:online",
				start_stall_detector_cpu,
				stop_stall_detector_cpu);
	if (ret < 0) {
		dev_err(&pdev->dev, "failed to install cpu hotplug");
		goto err;
	}

	vcpu_stall_config.hp_online = ret;
	return 0;
err:
	return ret;
}

static int vcpu_stall_detect_remove(struct platform_device *pdev)
{
	int cpu;

	cpuhp_remove_state(vcpu_stall_config.hp_online);

	for_each_possible_cpu(cpu)
		stop_stall_detector_cpu(cpu);

	return 0;
}

static const struct of_device_id vcpu_stall_detect_of_match[] = {
	{ .compatible = "qemu,vcpu-stall-detector", },
	{}
};

MODULE_DEVICE_TABLE(of, vcpu_stall_detect_of_match);

static struct platform_driver vcpu_stall_detect_driver = {
	.probe  = vcpu_stall_detect_probe,
	.remove = vcpu_stall_detect_remove,
	.driver = {
		.name           = KBUILD_MODNAME,
		.of_match_table = vcpu_stall_detect_of_match,
	},
};

module_platform_driver(vcpu_stall_detect_driver);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Sebastian Ene <sebastianene@google.com>");
MODULE_DESCRIPTION("VCPU stall detector");
