hwpmc/core: Adopt to upcoming Skylake TSX errata.
The forthcoming microcode update will fix a TSX bug by clobbering PMC3 when TSX instructions are executed (even speculatively). There is an alternate mode where CPU executes all TSX instructions by aborting them, in which case PMC3 is still available to OS. Any code that correctly uses TSX must be ready to handle abort anyway. Since it is believed that FreeBSD population of hwpmc(4) users is significantly larger than the population of TSX users, switch the microcode into TSX abort mode whenever a pmc is allocated, and back to bug avoidance mode when the last pmc is deallocated. Sponsored by: The FreeBSD Foundation MFC after: 1 week
This commit is contained in:
parent
069ffc8a67
commit
ac70750c65
@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/bus.h>
|
||||
#include <sys/pmc.h>
|
||||
#include <sys/pmckern.h>
|
||||
#include <sys/smp.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
#include <machine/intr_machdep.h>
|
||||
@ -103,6 +104,9 @@ static int core_iap_width;
|
||||
static int core_iap_npmc;
|
||||
static int core_iap_wroffset;
|
||||
|
||||
static u_int pmc_alloc_refs;
|
||||
static bool pmc_tsx_force_abort_set;
|
||||
|
||||
static int
|
||||
core_pcpu_noop(struct pmc_mdep *md, int cpu)
|
||||
{
|
||||
@ -216,6 +220,15 @@ iaf_reload_count_to_perfctr_value(pmc_value_t rlc)
|
||||
return (1ULL << core_iaf_width) - rlc;
|
||||
}
|
||||
|
||||
static void
|
||||
tweak_tsx_force_abort(void *arg)
|
||||
{
|
||||
u_int val;
|
||||
|
||||
val = (uintptr_t)arg;
|
||||
wrmsr(MSR_TSX_FORCE_ABORT, val);
|
||||
}
|
||||
|
||||
static int
|
||||
iaf_allocate_pmc(int cpu, int ri, struct pmc *pm,
|
||||
const struct pmc_op_pmcallocate *a)
|
||||
@ -253,6 +266,12 @@ iaf_allocate_pmc(int cpu, int ri, struct pmc *pm,
|
||||
if (ev == 0x0 && umask == 0x3 && ri != 2)
|
||||
return (EINVAL);
|
||||
|
||||
pmc_alloc_refs++;
|
||||
if ((cpu_stdext_feature3 & CPUID_STDEXT3_TSXFA) != 0 &&
|
||||
!pmc_tsx_force_abort_set) {
|
||||
pmc_tsx_force_abort_set = true;
|
||||
smp_rendezvous(NULL, tweak_tsx_force_abort, NULL, (void *)1);
|
||||
}
|
||||
|
||||
flags = 0;
|
||||
if (config & IAP_OS)
|
||||
@ -389,6 +408,12 @@ iaf_release_pmc(int cpu, int ri, struct pmc *pmc)
|
||||
KASSERT(core_pcpu[cpu]->pc_corepmcs[ri + core_iaf_ri].phw_pmc == NULL,
|
||||
("[core,%d] PHW pmc non-NULL", __LINE__));
|
||||
|
||||
MPASS(pmc_alloc_refs > 0);
|
||||
if (pmc_alloc_refs-- == 1 && pmc_tsx_force_abort_set) {
|
||||
pmc_tsx_force_abort_set = false;
|
||||
smp_rendezvous(NULL, tweak_tsx_force_abort, NULL, (void *)0);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user