/* DF-5483/5484 probe #2 -- the acpi_pst_intel_init() dance (0x1a0 bit16)
 * and the EST CPUID advertisement, under the repro CPU config. */
#include <sys/param.h>
#include <sys/module.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <machine/cpufunc.h>
#include <machine/specialreg.h>

#define INTEL_MSR_MISC_ENABLE	0x1a0
#define INTEL_MSR_MISC_EST_EN	0x10000ULL

static int
msrprobe2_modevent(module_t mod, int type, void *data)
{
	uint64_t misc_enable;
	int error;

	switch (type) {
	case MOD_LOAD:
		kprintf("msrprobe2: cpu_vendor_id %d cpu_id %#x "
		    "cpu_feature2 %#x (CPUID2_EST %s)\n",
		    cpu_vendor_id, cpu_id, cpu_feature2,
		    (cpu_feature2 & CPUID2_EST) ? "SET" : "clear");

		/* exact acpi_pst_intel_init() sequence, safe variant */
		error = rdmsr_safe(INTEL_MSR_MISC_ENABLE, &misc_enable);
		kprintf("msrprobe2: rdmsr(0x1a0) -> error %d val %#llx\n",
		    error, (unsigned long long)misc_enable);
		if (error == 0 && (misc_enable & INTEL_MSR_MISC_EST_EN) == 0) {
			error = wrmsr_safe(INTEL_MSR_MISC_ENABLE,
			    misc_enable | INTEL_MSR_MISC_EST_EN);
			kprintf("msrprobe2: wrmsr(0x1a0,|EST) -> error %d\n",
			    error);
			error = rdmsr_safe(INTEL_MSR_MISC_ENABLE, &misc_enable);
			kprintf("msrprobe2: rdmsr(0x1a0) -> error %d "
			    "val %#llx -> EST bit %s\n", error,
			    (unsigned long long)misc_enable,
			    (misc_enable & INTEL_MSR_MISC_EST_EN) ?
			    "STUCK (init would succeed)" :
			    "DROPPED (init -> EIO -> domain DEAD)");
		}

		/* perfect-status PERF_CTL write-back, exact set_pstate value */
		error = wrmsr_safe(0x199, 0x0e00);
		kprintf("msrprobe2: wrmsr_safe(0x199, 0x0e00) -> error %d "
		    "(raw wrmsr at pstate_machdep.c:533 would %s)\n", error,
		    error ? "#GP panic" : "succeed");
		return 0;
	case MOD_UNLOAD:
		return 0;
	}
	return EOPNOTSUPP;
}

static moduledata_t msrprobe2_mod = {
	"msrprobe2",
	msrprobe2_modevent,
	NULL
};
DECLARE_MODULE(msrprobe2, msrprobe2_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
