/*
 * DF-5160 fixed-body module (apfix.ko) — demonstrates the patched
 * aperf_sensor_task() semantics on the same faulting platform:
 * rdmsr_safe() returns EFAULT(14), the sample is skipped, NO trap.
 *
 * Mirrors the fix.diff body:
 *
 *	crit_enter();
 *	tsc = rdtsc_ordered();
 *	if (rdmsr_safe(MSR_APERF, &aperf)) {
 *		crit_exit();
 *		return;
 *	}
 *	if (rdmsr_safe(MSR_MPERF, &mperf)) {
 *		crit_exit();
 *		return;
 *	}
 *	crit_exit();
 */
#include <sys/param.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/thread2.h>

#include <machine/clock.h>
#include <machine/cpufunc.h>

#define MSR_MPERF	0xE7
#define MSR_APERF	0xE8

static int
apfix_modevent(module_t mod, int type, void *arg)
{
	uint64_t aperf, mperf, tsc;
	uint32_t regs[4];
	int err;

	switch (type) {
	case MOD_LOAD:
		do_cpuid(0x00000006, regs);
		kprintf("apfix: CPUID.06H ECX=%08x (gate bit0=%d)\n",
		    regs[2], (regs[2] & 1) != 0);

		/* patched aperf.c:157-169 body, verbatim shape */
		crit_enter();
		tsc = rdtsc_ordered();
		err = rdmsr_safe(MSR_APERF, &aperf);
		if (err) {
			crit_exit();
			kprintf("apfix: rdmsr_safe(MSR_APERF)=%d -> sample "
			    "skipped, NO TRAP (patched aperf.c:159)\n", err);
			return 0;
		}
		err = rdmsr_safe(MSR_MPERF, &mperf);
		if (err) {
			crit_exit();
			kprintf("apfix: rdmsr_safe(MSR_MPERF)=%d -> sample "
			    "skipped, NO TRAP (patched aperf.c:162)\n", err);
			return 0;
		}
		crit_exit();
		kprintf("apfix: MSR pair readable (aperf=%llu mperf=%llu), "
		    "continuing sample normally\n",
		    (unsigned long long)aperf, (unsigned long long)mperf);
		return 0;
	default:
		return EOPNOTSUPP;
	}
}

static moduledata_t apfix_mod = {
	"apfix",
	apfix_modevent,
	NULL
};
DECLARE_MODULE(apfix, apfix_mod, SI_SUB_DRIVERS, SI_ORDER_ANY);
