DF-5484 / rawpst.c
/* * DF-5484 trigger -- the EXACT instruction sequence of * acpi_pst_intel_set_pstate() (sys/platform/pc64/acpica/acpi_pstate_machdep.c:530-533): * * ctl = rdmsr(INTEL_MSR_PERF_CTL); // :530 * ctl &= ~INTEL_MSR_PERF_MASK; // :531 * ctl |= (pstate->st_cval & INTEL_MSR_PERF_MASK); // :532 * wrmsr(INTEL_MSR_PERF_CTL, ctl); // :533 * * (the ctrl->pr_res == NULL branch, i.e. _PCT Fixed Hardware -- the common * Intel BIOS configuration) * * On this VMM (KVM -cpu host, Skylake) wrmsr_safe(0x199) returns error 14: * the MSR write takes #GP. The raw driver wrmsr therefore takes a fatal * kernel #GP (Fatal trap 9) the first time the driver selects a P-state. * Reachable (a) unattended at boot via acpi_pst_postattach -> * acpi_pst_global_set_pstate, (b) on every * `sysctl hw.acpi.cpu.px_global=<freq>` write, (c) on every type-0x80 * _PPC notify -> acpi_pst_global_fixup_pstate -- on any VMM that * advertises CPUID2_EST without virtualizing IA32_PERF_CTL. */ #include <sys/param.h> #include <sys/module.h> #include <sys/kernel.h> #include <sys/systm.h> #include <machine/cpufunc.h> #define INTEL_MSR_PERF_CTL 0x199 #define INTEL_MSR_PERF_MASK 0xffffULL static int rawpst_modevent(module_t mod, int type, void *data) { uint64_t ctl, val = 0; int error; switch (type) { case MOD_LOAD: kprintf("rawpst: safe probe: rdmsr_safe(0x199) -> "); error = rdmsr_safe(INTEL_MSR_PERF_CTL, &val); kprintf("error %d val %#llx\n", error, (unsigned long long)val); kprintf("rawpst: safe probe: wrmsr_safe(0x199, val) -> "); error = wrmsr_safe(INTEL_MSR_PERF_CTL, val); kprintf("error %d\n", error); kprintf("rawpst: raw driver sequence " "(pstate_machdep.c:530-533), cval=0x0e00 -- " "expect Fatal trap 9\n"); ctl = rdmsr(INTEL_MSR_PERF_CTL); /* :530 */ ctl &= ~INTEL_MSR_PERF_MASK; /* :531 */ ctl |= (0x0e00ULL & INTEL_MSR_PERF_MASK); /* :532 */ wrmsr(INTEL_MSR_PERF_CTL, ctl); /* :533 */ kprintf("rawpst: survived (MSR virtualized)\n"); return 0; case MOD_UNLOAD: return 0; } return EOPNOTSUPP; } static moduledata_t rawpst_mod = { "rawpst", rawpst_modevent, NULL }; DECLARE_MODULE(rawpst, rawpst_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); |