Merge branch 'x86-tsx-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 12 Mar 2019 16:02:36 +0000 (09:02 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 12 Mar 2019 16:02:36 +0000 (09:02 -0700)
Pull x86 tsx fixes from Thomas Gleixner:
 "This update provides kernel side handling for the TSX erratum of Intel
  Skylake (and later) CPUs.

  On these CPUs Intel Transactional Synchronization Extensions (TSX)
  functions can result in unpredictable system behavior under certain
  circumstances.

  The issue is mitigated with an microcode update which utilizes
  Performance Monitoring Counter (PMC) 3 when TSX functions are in use.
  This mitigation is enabled unconditionally by the updated microcode.

  As a consequence the usage of TSX functions can cause corrupted
  performance monitoring results for events which utilize PMC3. The
  corruption is silent on kernels which have no update for this issue.

  This update makes the kernel aware of the PMC3 utilization by the
  microcode:

  The microcode offers a possibility to enforce TSX abort which prevents
  the malfunction and frees up PMC3. The enforced TSX abort requires the
  TSX using application to have a software fallback path implemented;
  abort handlers which solely retry the transaction will fail over and
  over.

  The enforced TSX abort request is issued by the kernel when:

   - enforced TSX abort is enabled (PMU attribute)

   - A performance monitoring request needs PMC3

  When PMC3 is not longer used by the kernel the TSX force abort request
  is cleared.

  The enforced TSX abort mechanism is enabled by default and can be
  controlled by the administrator via the new PMU attribute
  'allow_tsx_force_abort'. This attribute is only visible when updated
  microcode is detected on affected systems. Writing '0' disables the
  enforced TSX abort mechanism, '1' enables it.

  As a result of disabling the enforced TSX abort mechanism, PMC3 is
  permanentely unavailable for performance monitoring which can cause
  performance monitoring requests to fail or switch to multiplexing
  mode"

* branch 'x86-tsx-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  perf/x86/intel: Implement support for TSX Force Abort
  x86: Add TSX Force Abort CPUID/MSR
  perf/x86/intel: Generalize dynamic constraint creation
  perf/x86/intel: Make cpuc allocations consistent

1  2 
arch/x86/events/intel/core.c
arch/x86/events/perf_event.h

index 7ec265bacb6a2622ceba7d42dcc98ebca7b2ec31,dadb8f7e5a0dd9999dcd90c4c54e39b9784e6f5c..35102ecdfc8d5debd884581bb1d40e2a9029a59f
@@@ -18,7 -18,6 +18,7 @@@
  #include <asm/hardirq.h>
  #include <asm/intel-family.h>
  #include <asm/apic.h>
 +#include <asm/cpu_device_id.h>
  
  #include "../perf_event.h"
  
@@@ -2000,6 -1999,39 +2000,39 @@@ static void intel_pmu_nhm_enable_all(in
        intel_pmu_enable_all(added);
  }
  
+ static void intel_set_tfa(struct cpu_hw_events *cpuc, bool on)
+ {
+       u64 val = on ? MSR_TFA_RTM_FORCE_ABORT : 0;
+       if (cpuc->tfa_shadow != val) {
+               cpuc->tfa_shadow = val;
+               wrmsrl(MSR_TSX_FORCE_ABORT, val);
+       }
+ }
+ static void intel_tfa_commit_scheduling(struct cpu_hw_events *cpuc, int idx, int cntr)
+ {
+       /*
+        * We're going to use PMC3, make sure TFA is set before we touch it.
+        */
+       if (cntr == 3 && !cpuc->is_fake)
+               intel_set_tfa(cpuc, true);
+ }
+ static void intel_tfa_pmu_enable_all(int added)
+ {
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       /*
+        * If we find PMC3 is no longer used when we enable the PMU, we can
+        * clear TFA.
+        */
+       if (!test_bit(3, cpuc->active_mask))
+               intel_set_tfa(cpuc, false);
+       intel_pmu_enable_all(added);
+ }
  static void enable_counter_freeze(void)
  {
        update_debugctlmsr(get_debugctlmsr() |
@@@ -2769,6 -2801,35 +2802,35 @@@ intel_stop_scheduling(struct cpu_hw_eve
        raw_spin_unlock(&excl_cntrs->lock);
  }
  
+ static struct event_constraint *
+ dyn_constraint(struct cpu_hw_events *cpuc, struct event_constraint *c, int idx)
+ {
+       WARN_ON_ONCE(!cpuc->constraint_list);
+       if (!(c->flags & PERF_X86_EVENT_DYNAMIC)) {
+               struct event_constraint *cx;
+               /*
+                * grab pre-allocated constraint entry
+                */
+               cx = &cpuc->constraint_list[idx];
+               /*
+                * initialize dynamic constraint
+                * with static constraint
+                */
+               *cx = *c;
+               /*
+                * mark constraint as dynamic
+                */
+               cx->flags |= PERF_X86_EVENT_DYNAMIC;
+               c = cx;
+       }
+       return c;
+ }
  static struct event_constraint *
  intel_get_excl_constraints(struct cpu_hw_events *cpuc, struct perf_event *event,
                           int idx, struct event_constraint *c)
         * only needed when constraint has not yet
         * been cloned (marked dynamic)
         */
-       if (!(c->flags & PERF_X86_EVENT_DYNAMIC)) {
-               struct event_constraint *cx;
-               /*
-                * grab pre-allocated constraint entry
-                */
-               cx = &cpuc->constraint_list[idx];
-               /*
-                * initialize dynamic constraint
-                * with static constraint
-                */
-               *cx = *c;
-               /*
-                * mark constraint as dynamic, so we
-                * can free it later on
-                */
-               cx->flags |= PERF_X86_EVENT_DYNAMIC;
-               c = cx;
-       }
+       c = dyn_constraint(cpuc, c, idx);
  
        /*
         * From here on, the constraint is dynamic.
@@@ -3207,27 -3248,16 +3249,27 @@@ static struct perf_guest_switch_msr *in
        arr[0].msr = MSR_CORE_PERF_GLOBAL_CTRL;
        arr[0].host = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask;
        arr[0].guest = x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_host_mask;
 -      /*
 -       * If PMU counter has PEBS enabled it is not enough to disable counter
 -       * on a guest entry since PEBS memory write can overshoot guest entry
 -       * and corrupt guest memory. Disabling PEBS solves the problem.
 -       */
 -      arr[1].msr = MSR_IA32_PEBS_ENABLE;
 -      arr[1].host = cpuc->pebs_enabled;
 -      arr[1].guest = 0;
 +      if (x86_pmu.flags & PMU_FL_PEBS_ALL)
 +              arr[0].guest &= ~cpuc->pebs_enabled;
 +      else
 +              arr[0].guest &= ~(cpuc->pebs_enabled & PEBS_COUNTER_MASK);
 +      *nr = 1;
 +
 +      if (x86_pmu.pebs && x86_pmu.pebs_no_isolation) {
 +              /*
 +               * If PMU counter has PEBS enabled it is not enough to
 +               * disable counter on a guest entry since PEBS memory
 +               * write can overshoot guest entry and corrupt guest
 +               * memory. Disabling PEBS solves the problem.
 +               *
 +               * Don't do this if the CPU already enforces it.
 +               */
 +              arr[1].msr = MSR_IA32_PEBS_ENABLE;
 +              arr[1].host = cpuc->pebs_enabled;
 +              arr[1].guest = 0;
 +              *nr = 2;
 +      }
  
 -      *nr = 2;
        return arr;
  }
  
@@@ -3357,6 -3387,26 +3399,26 @@@ glp_get_event_constraints(struct cpu_hw
        return c;
  }
  
+ static bool allow_tsx_force_abort = true;
+ static struct event_constraint *
+ tfa_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
+                         struct perf_event *event)
+ {
+       struct event_constraint *c = hsw_get_event_constraints(cpuc, idx, event);
+       /*
+        * Without TFA we must not use PMC3.
+        */
+       if (!allow_tsx_force_abort && test_bit(3, c->idxmsk)) {
+               c = dyn_constraint(cpuc, c, idx);
+               c->idxmsk64 &= ~(1ULL << 3);
+               c->weight--;
+       }
+       return c;
+ }
  /*
   * Broadwell:
   *
@@@ -3410,7 -3460,7 +3472,7 @@@ ssize_t intel_event_sysfs_show(char *pa
        return x86_event_sysfs_show(page, config, event);
  }
  
- struct intel_shared_regs *allocate_shared_regs(int cpu)
+ static struct intel_shared_regs *allocate_shared_regs(int cpu)
  {
        struct intel_shared_regs *regs;
        int i;
@@@ -3442,23 -3492,24 +3504,24 @@@ static struct intel_excl_cntrs *allocat
        return c;
  }
  
- static int intel_pmu_cpu_prepare(int cpu)
- {
-       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
  
+ int intel_cpuc_prepare(struct cpu_hw_events *cpuc, int cpu)
+ {
        if (x86_pmu.extra_regs || x86_pmu.lbr_sel_map) {
                cpuc->shared_regs = allocate_shared_regs(cpu);
                if (!cpuc->shared_regs)
                        goto err;
        }
  
-       if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) {
+       if (x86_pmu.flags & (PMU_FL_EXCL_CNTRS | PMU_FL_TFA)) {
                size_t sz = X86_PMC_IDX_MAX * sizeof(struct event_constraint);
  
-               cpuc->constraint_list = kzalloc(sz, GFP_KERNEL);
+               cpuc->constraint_list = kzalloc_node(sz, GFP_KERNEL, cpu_to_node(cpu));
                if (!cpuc->constraint_list)
                        goto err_shared_regs;
+       }
  
+       if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) {
                cpuc->excl_cntrs = allocate_excl_cntrs(cpu);
                if (!cpuc->excl_cntrs)
                        goto err_constraint_list;
        return -ENOMEM;
  }
  
+ static int intel_pmu_cpu_prepare(int cpu)
+ {
+       return intel_cpuc_prepare(&per_cpu(cpu_hw_events, cpu), cpu);
+ }
  static void flip_smm_bit(void *data)
  {
        unsigned long set = *(unsigned long *)data;
@@@ -3554,9 -3610,8 +3622,8 @@@ static void intel_pmu_cpu_starting(int 
        }
  }
  
- static void free_excl_cntrs(int cpu)
+ static void free_excl_cntrs(struct cpu_hw_events *cpuc)
  {
-       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
        struct intel_excl_cntrs *c;
  
        c = cpuc->excl_cntrs;
                if (c->core_id == -1 || --c->refcnt == 0)
                        kfree(c);
                cpuc->excl_cntrs = NULL;
-               kfree(cpuc->constraint_list);
-               cpuc->constraint_list = NULL;
        }
+       kfree(cpuc->constraint_list);
+       cpuc->constraint_list = NULL;
  }
  
  static void intel_pmu_cpu_dying(int cpu)
                disable_counter_freeze();
  }
  
static void intel_pmu_cpu_dead(int cpu)
void intel_cpuc_finish(struct cpu_hw_events *cpuc)
  {
-       struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
        struct intel_shared_regs *pc;
  
        pc = cpuc->shared_regs;
                cpuc->shared_regs = NULL;
        }
  
-       free_excl_cntrs(cpu);
+       free_excl_cntrs(cpuc);
+ }
+ static void intel_pmu_cpu_dead(int cpu)
+ {
+       intel_cpuc_finish(&per_cpu(cpu_hw_events, cpu));
  }
  
  static void intel_pmu_sched_task(struct perf_event_context *ctx,
@@@ -3760,62 -3820,36 +3832,62 @@@ static __init void intel_clovertown_qui
        x86_pmu.pebs_constraints = NULL;
  }
  
 -static int intel_snb_pebs_broken(int cpu)
 +static const struct x86_cpu_desc isolation_ucodes[] = {
 +      INTEL_CPU_DESC(INTEL_FAM6_HASWELL_CORE,          3, 0x0000001f),
 +      INTEL_CPU_DESC(INTEL_FAM6_HASWELL_ULT,           1, 0x0000001e),
 +      INTEL_CPU_DESC(INTEL_FAM6_HASWELL_GT3E,          1, 0x00000015),
 +      INTEL_CPU_DESC(INTEL_FAM6_HASWELL_X,             2, 0x00000037),
 +      INTEL_CPU_DESC(INTEL_FAM6_HASWELL_X,             4, 0x0000000a),
 +      INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_CORE,        4, 0x00000023),
 +      INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_GT3E,        1, 0x00000014),
 +      INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_XEON_D,      2, 0x00000010),
 +      INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_XEON_D,      3, 0x07000009),
 +      INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_XEON_D,      4, 0x0f000009),
 +      INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_XEON_D,      5, 0x0e000002),
 +      INTEL_CPU_DESC(INTEL_FAM6_BROADWELL_X,           2, 0x0b000014),
 +      INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X,             3, 0x00000021),
 +      INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_X,             4, 0x00000000),
 +      INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_MOBILE,        3, 0x0000007c),
 +      INTEL_CPU_DESC(INTEL_FAM6_SKYLAKE_DESKTOP,       3, 0x0000007c),
 +      INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_DESKTOP,      9, 0x0000004e),
 +      INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_MOBILE,       9, 0x0000004e),
 +      INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_MOBILE,      10, 0x0000004e),
 +      INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_MOBILE,      11, 0x0000004e),
 +      INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_MOBILE,      12, 0x0000004e),
 +      INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_DESKTOP,     10, 0x0000004e),
 +      INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_DESKTOP,     11, 0x0000004e),
 +      INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_DESKTOP,     12, 0x0000004e),
 +      INTEL_CPU_DESC(INTEL_FAM6_KABYLAKE_DESKTOP,     13, 0x0000004e),
 +      {}
 +};
 +
 +static void intel_check_pebs_isolation(void)
  {
 -      u32 rev = UINT_MAX; /* default to broken for unknown models */
 +      x86_pmu.pebs_no_isolation = !x86_cpu_has_min_microcode_rev(isolation_ucodes);
 +}
  
 -      switch (cpu_data(cpu).x86_model) {
 -      case INTEL_FAM6_SANDYBRIDGE:
 -              rev = 0x28;
 -              break;
 +static __init void intel_pebs_isolation_quirk(void)
 +{
 +      WARN_ON_ONCE(x86_pmu.check_microcode);
 +      x86_pmu.check_microcode = intel_check_pebs_isolation;
 +      intel_check_pebs_isolation();
 +}
  
 -      case INTEL_FAM6_SANDYBRIDGE_X:
 -              switch (cpu_data(cpu).x86_stepping) {
 -              case 6: rev = 0x618; break;
 -              case 7: rev = 0x70c; break;
 -              }
 -      }
 +static const struct x86_cpu_desc pebs_ucodes[] = {
 +      INTEL_CPU_DESC(INTEL_FAM6_SANDYBRIDGE,          7, 0x00000028),
 +      INTEL_CPU_DESC(INTEL_FAM6_SANDYBRIDGE_X,        6, 0x00000618),
 +      INTEL_CPU_DESC(INTEL_FAM6_SANDYBRIDGE_X,        7, 0x0000070c),
 +      {}
 +};
  
 -      return (cpu_data(cpu).microcode < rev);
 +static bool intel_snb_pebs_broken(void)
 +{
 +      return !x86_cpu_has_min_microcode_rev(pebs_ucodes);
  }
  
  static void intel_snb_check_microcode(void)
  {
 -      int pebs_broken = 0;
 -      int cpu;
 -
 -      for_each_online_cpu(cpu) {
 -              if ((pebs_broken = intel_snb_pebs_broken(cpu)))
 -                      break;
 -      }
 -
 -      if (pebs_broken == x86_pmu.pebs_broken)
 +      if (intel_snb_pebs_broken() == x86_pmu.pebs_broken)
                return;
  
        /*
@@@ -3932,22 -3966,23 +4004,22 @@@ static __init void intel_nehalem_quirk(
        }
  }
  
 -static bool intel_glp_counter_freezing_broken(int cpu)
 -{
 -      u32 rev = UINT_MAX; /* default to broken for unknown stepping */
 -
 -      switch (cpu_data(cpu).x86_stepping) {
 -      case 1:
 -              rev = 0x28;
 -              break;
 -      case 8:
 -              rev = 0x6;
 -              break;
 -      }
 +static const struct x86_cpu_desc counter_freezing_ucodes[] = {
 +      INTEL_CPU_DESC(INTEL_FAM6_ATOM_GOLDMONT,         2, 0x0000000e),
 +      INTEL_CPU_DESC(INTEL_FAM6_ATOM_GOLDMONT,         9, 0x0000002e),
 +      INTEL_CPU_DESC(INTEL_FAM6_ATOM_GOLDMONT,        10, 0x00000008),
 +      INTEL_CPU_DESC(INTEL_FAM6_ATOM_GOLDMONT_X,       1, 0x00000028),
 +      INTEL_CPU_DESC(INTEL_FAM6_ATOM_GOLDMONT_PLUS,    1, 0x00000028),
 +      INTEL_CPU_DESC(INTEL_FAM6_ATOM_GOLDMONT_PLUS,    8, 0x00000006),
 +      {}
 +};
  
 -      return (cpu_data(cpu).microcode < rev);
 +static bool intel_counter_freezing_broken(void)
 +{
 +      return !x86_cpu_has_min_microcode_rev(counter_freezing_ucodes);
  }
  
 -static __init void intel_glp_counter_freezing_quirk(void)
 +static __init void intel_counter_freezing_quirk(void)
  {
        /* Check if it's already disabled */
        if (disable_counter_freezing)
         * If the system starts with the wrong ucode, leave the
         * counter-freezing feature permanently disabled.
         */
 -      if (intel_glp_counter_freezing_broken(raw_smp_processor_id())) {
 +      if (intel_counter_freezing_broken()) {
                pr_info("PMU counter freezing disabled due to CPU errata,"
                        "please upgrade microcode\n");
                x86_pmu.counter_freezing = false;
@@@ -4107,8 -4142,11 +4179,11 @@@ static struct attribute *intel_pmu_caps
         NULL
  };
  
+ DEVICE_BOOL_ATTR(allow_tsx_force_abort, 0644, allow_tsx_force_abort);
  static struct attribute *intel_pmu_attrs[] = {
        &dev_attr_freeze_on_smi.attr,
+       NULL, /* &dev_attr_allow_tsx_force_abort.attr.attr */
        NULL,
  };
  
@@@ -4220,8 -4258,6 +4295,8 @@@ __init int intel_pmu_init(void
  
        case INTEL_FAM6_CORE2_MEROM:
                x86_add_quirk(intel_clovertown_quirk);
 +              /* fall through */
 +
        case INTEL_FAM6_CORE2_MEROM_L:
        case INTEL_FAM6_CORE2_PENRYN:
        case INTEL_FAM6_CORE2_DUNNINGTON:
  
        case INTEL_FAM6_ATOM_GOLDMONT:
        case INTEL_FAM6_ATOM_GOLDMONT_X:
 +              x86_add_quirk(intel_counter_freezing_quirk);
                memcpy(hw_cache_event_ids, glm_hw_cache_event_ids,
                       sizeof(hw_cache_event_ids));
                memcpy(hw_cache_extra_regs, glm_hw_cache_extra_regs,
                break;
  
        case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
 -              x86_add_quirk(intel_glp_counter_freezing_quirk);
 +              x86_add_quirk(intel_counter_freezing_quirk);
                memcpy(hw_cache_event_ids, glp_hw_cache_event_ids,
                       sizeof(hw_cache_event_ids));
                memcpy(hw_cache_extra_regs, glp_hw_cache_extra_regs,
        case INTEL_FAM6_HASWELL_ULT:
        case INTEL_FAM6_HASWELL_GT3E:
                x86_add_quirk(intel_ht_bug);
 +              x86_add_quirk(intel_pebs_isolation_quirk);
                x86_pmu.late_ack = true;
                memcpy(hw_cache_event_ids, hsw_hw_cache_event_ids, sizeof(hw_cache_event_ids));
                memcpy(hw_cache_extra_regs, hsw_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
        case INTEL_FAM6_BROADWELL_XEON_D:
        case INTEL_FAM6_BROADWELL_GT3E:
        case INTEL_FAM6_BROADWELL_X:
 +              x86_add_quirk(intel_pebs_isolation_quirk);
                x86_pmu.late_ack = true;
                memcpy(hw_cache_event_ids, hsw_hw_cache_event_ids, sizeof(hw_cache_event_ids));
                memcpy(hw_cache_extra_regs, hsw_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
        case INTEL_FAM6_SKYLAKE_X:
        case INTEL_FAM6_KABYLAKE_MOBILE:
        case INTEL_FAM6_KABYLAKE_DESKTOP:
 +              x86_add_quirk(intel_pebs_isolation_quirk);
                x86_pmu.late_ack = true;
                memcpy(hw_cache_event_ids, skl_hw_cache_event_ids, sizeof(hw_cache_event_ids));
                memcpy(hw_cache_extra_regs, skl_hw_cache_extra_regs, sizeof(hw_cache_extra_regs));
                tsx_attr = hsw_tsx_events_attrs;
                intel_pmu_pebs_data_source_skl(
                        boot_cpu_data.x86_model == INTEL_FAM6_SKYLAKE_X);
+               if (boot_cpu_has(X86_FEATURE_TSX_FORCE_ABORT)) {
+                       x86_pmu.flags |= PMU_FL_TFA;
+                       x86_pmu.get_event_constraints = tfa_get_event_constraints;
+                       x86_pmu.enable_all = intel_tfa_pmu_enable_all;
+                       x86_pmu.commit_scheduling = intel_tfa_commit_scheduling;
+                       intel_pmu_attrs[1] = &dev_attr_allow_tsx_force_abort.attr.attr;
+               }
                pr_cont("Skylake events, ");
                name = "skylake";
                break;
@@@ -4758,7 -4799,7 +4842,7 @@@ static __init int fixup_ht_bug(void
        hardlockup_detector_perf_restart();
  
        for_each_online_cpu(c)
-               free_excl_cntrs(c);
+               free_excl_cntrs(&per_cpu(cpu_hw_events, c));
  
        cpus_read_unlock();
        pr_info("PMU erratum BJ122, BV98, HSD29 workaround disabled, HT off\n");
index 7e75f474b076518e4bb512655224ef1e059e336c,a345d079f876bb7dcc986c33136ced74fd193c31..b04ae6c8775e0e298726b9414e2a07b31edbdfb9
@@@ -242,6 -242,11 +242,11 @@@ struct cpu_hw_events 
        struct intel_excl_cntrs         *excl_cntrs;
        int excl_thread_id; /* 0 or 1 */
  
+       /*
+        * SKL TSX_FORCE_ABORT shadow
+        */
+       u64                             tfa_shadow;
        /*
         * AMD specific bits
         */
@@@ -601,14 -606,13 +606,14 @@@ struct x86_pmu 
        /*
         * Intel DebugStore bits
         */
 -      unsigned int    bts             :1,
 -                      bts_active      :1,
 -                      pebs            :1,
 -                      pebs_active     :1,
 -                      pebs_broken     :1,
 -                      pebs_prec_dist  :1,
 -                      pebs_no_tlb     :1;
 +      unsigned int    bts                     :1,
 +                      bts_active              :1,
 +                      pebs                    :1,
 +                      pebs_active             :1,
 +                      pebs_broken             :1,
 +                      pebs_prec_dist          :1,
 +                      pebs_no_tlb             :1,
 +                      pebs_no_isolation       :1;
        int             pebs_record_size;
        int             pebs_buffer_size;
        void            (*drain_pebs)(struct pt_regs *regs);
@@@ -682,6 -686,7 +687,7 @@@ do {                                                                       
  #define PMU_FL_EXCL_CNTRS     0x4 /* has exclusive counter requirements  */
  #define PMU_FL_EXCL_ENABLED   0x8 /* exclusive counter active */
  #define PMU_FL_PEBS_ALL               0x10 /* all events are valid PEBS events */
+ #define PMU_FL_TFA            0x20 /* deal with TSX force abort */
  
  #define EVENT_VAR(_id)  event_attr_##_id
  #define EVENT_PTR(_id) &event_attr_##_id.attr.attr
@@@ -890,7 -895,8 +896,8 @@@ struct event_constraint 
  x86_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
                          struct perf_event *event);
  
- struct intel_shared_regs *allocate_shared_regs(int cpu);
+ extern int intel_cpuc_prepare(struct cpu_hw_events *cpuc, int cpu);
+ extern void intel_cpuc_finish(struct cpu_hw_events *cpuc);
  
  int intel_pmu_init(void);
  
@@@ -1026,9 -1032,13 +1033,13 @@@ static inline int intel_pmu_init(void
        return 0;
  }
  
- static inline struct intel_shared_regs *allocate_shared_regs(int cpu)
+ static inline int intel_cpuc_prepare(struct cpu_hw_event *cpuc, int cpu)
+ {
+       return 0;
+ }
+ static inline void intel_cpuc_finish(struct cpu_hw_event *cpuc)
  {
-       return NULL;
  }
  
  static inline int is_ht_workaround_enabled(void)