void intel_pmu_lbr_add(struct perf_event *event)
 {
+       struct kmem_cache *kmem_cache = event->pmu->task_ctx_cache;
        struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
 
        if (!x86_pmu.lbr_nr)
        perf_sched_cb_inc(event->ctx->pmu);
        if (!cpuc->lbr_users++ && !event->total_time_running)
                intel_pmu_lbr_reset();
+
+       if (static_cpu_has(X86_FEATURE_ARCH_LBR) &&
+           kmem_cache && !cpuc->lbr_xsave &&
+           (cpuc->lbr_users != cpuc->lbr_pebs_users))
+               cpuc->lbr_xsave = kmem_cache_alloc(kmem_cache, GFP_KERNEL);
+}
+
+void release_lbr_buffers(void)
+{
+       struct kmem_cache *kmem_cache = x86_get_pmu()->task_ctx_cache;
+       struct cpu_hw_events *cpuc;
+       int cpu;
+
+       if (!static_cpu_has(X86_FEATURE_ARCH_LBR))
+               return;
+
+       for_each_possible_cpu(cpu) {
+               cpuc = per_cpu_ptr(&cpu_hw_events, cpu);
+               if (kmem_cache && cpuc->lbr_xsave) {
+                       kmem_cache_free(kmem_cache, cpuc->lbr_xsave);
+                       cpuc->lbr_xsave = NULL;
+               }
+       }
 }
 
 void intel_pmu_lbr_del(struct perf_event *event)
        intel_pmu_store_lbr(cpuc, NULL);
 }
 
+static void intel_pmu_arch_lbr_read_xsave(struct cpu_hw_events *cpuc)
+{
+       struct x86_perf_task_context_arch_lbr_xsave *xsave = cpuc->lbr_xsave;
+
+       if (!xsave) {
+               intel_pmu_store_lbr(cpuc, NULL);
+               return;
+       }
+       copy_dynamic_supervisor_to_kernel(&xsave->xsave, XFEATURE_MASK_LBR);
+
+       intel_pmu_store_lbr(cpuc, xsave->lbr.entries);
+}
+
 void intel_pmu_lbr_read(void)
 {
        struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
                x86_pmu.lbr_ctl_map = NULL;
 
        x86_pmu.lbr_reset = intel_pmu_arch_lbr_reset;
-       x86_pmu.lbr_read = intel_pmu_arch_lbr_read;
        if (arch_lbr_xsave) {
                x86_pmu.lbr_save = intel_pmu_arch_lbr_xsaves;
                x86_pmu.lbr_restore = intel_pmu_arch_lbr_xrstors;
+               x86_pmu.lbr_read = intel_pmu_arch_lbr_read_xsave;
                pr_cont("XSAVE ");
        } else {
                x86_pmu.lbr_save = intel_pmu_arch_lbr_save;
                x86_pmu.lbr_restore = intel_pmu_arch_lbr_restore;
+               x86_pmu.lbr_read = intel_pmu_arch_lbr_read;
        }
 
        pr_cont("Architectural LBR, ");