Skip to content

Commit 2721e8d

Browse files
Dapeng MiPeter Zijlstra
authored andcommitted
perf/x86/intel: Allocate arch-PEBS buffer and initialize PEBS_BASE MSR
Arch-PEBS introduces a new MSR IA32_PEBS_BASE to store the arch-PEBS buffer physical address. This patch allocates arch-PEBS buffer and then initialize IA32_PEBS_BASE MSR with the buffer physical address. Co-developed-by: Kan Liang <kan.liang@linux.intel.com> Signed-off-by: Kan Liang <kan.liang@linux.intel.com> Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://patch.msgid.link/20251029102136.61364-10-dapeng1.mi@linux.intel.com
1 parent d21954c commit 2721e8d

4 files changed

Lines changed: 92 additions & 15 deletions

File tree

arch/x86/events/intel/core.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5227,7 +5227,13 @@ int intel_cpuc_prepare(struct cpu_hw_events *cpuc, int cpu)
52275227

52285228
static int intel_pmu_cpu_prepare(int cpu)
52295229
{
5230-
return intel_cpuc_prepare(&per_cpu(cpu_hw_events, cpu), cpu);
5230+
int ret;
5231+
5232+
ret = intel_cpuc_prepare(&per_cpu(cpu_hw_events, cpu), cpu);
5233+
if (ret)
5234+
return ret;
5235+
5236+
return alloc_arch_pebs_buf_on_cpu(cpu);
52315237
}
52325238

52335239
static void flip_smm_bit(void *data)
@@ -5458,6 +5464,7 @@ static void intel_pmu_cpu_starting(int cpu)
54585464
return;
54595465

54605466
init_debug_store_on_cpu(cpu);
5467+
init_arch_pebs_on_cpu(cpu);
54615468
/*
54625469
* Deal with CPUs that don't clear their LBRs on power-up, and that may
54635470
* even boot with LBRs enabled.
@@ -5555,6 +5562,7 @@ static void free_excl_cntrs(struct cpu_hw_events *cpuc)
55555562
static void intel_pmu_cpu_dying(int cpu)
55565563
{
55575564
fini_debug_store_on_cpu(cpu);
5565+
fini_arch_pebs_on_cpu(cpu);
55585566
}
55595567

55605568
void intel_cpuc_finish(struct cpu_hw_events *cpuc)
@@ -5575,6 +5583,7 @@ static void intel_pmu_cpu_dead(int cpu)
55755583
{
55765584
struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
55775585

5586+
release_arch_pebs_buf_on_cpu(cpu);
55785587
intel_cpuc_finish(cpuc);
55795588

55805589
if (is_hybrid() && cpuc->pmu)

arch/x86/events/intel/ds.c

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -625,13 +625,18 @@ static int alloc_pebs_buffer(int cpu)
625625
int max, node = cpu_to_node(cpu);
626626
void *buffer, *insn_buff, *cea;
627627

628-
if (!x86_pmu.ds_pebs)
628+
if (!intel_pmu_has_pebs())
629629
return 0;
630630

631631
buffer = dsalloc_pages(bsiz, GFP_KERNEL, cpu);
632632
if (unlikely(!buffer))
633633
return -ENOMEM;
634634

635+
if (x86_pmu.arch_pebs) {
636+
hwev->pebs_vaddr = buffer;
637+
return 0;
638+
}
639+
635640
/*
636641
* HSW+ already provides us the eventing ip; no need to allocate this
637642
* buffer then.
@@ -644,7 +649,7 @@ static int alloc_pebs_buffer(int cpu)
644649
}
645650
per_cpu(insn_buffer, cpu) = insn_buff;
646651
}
647-
hwev->ds_pebs_vaddr = buffer;
652+
hwev->pebs_vaddr = buffer;
648653
/* Update the cpu entry area mapping */
649654
cea = &get_cpu_entry_area(cpu)->cpu_debug_buffers.pebs_buffer;
650655
ds->pebs_buffer_base = (unsigned long) cea;
@@ -660,17 +665,20 @@ static void release_pebs_buffer(int cpu)
660665
struct cpu_hw_events *hwev = per_cpu_ptr(&cpu_hw_events, cpu);
661666
void *cea;
662667

663-
if (!x86_pmu.ds_pebs)
668+
if (!intel_pmu_has_pebs())
664669
return;
665670

666-
kfree(per_cpu(insn_buffer, cpu));
667-
per_cpu(insn_buffer, cpu) = NULL;
671+
if (x86_pmu.ds_pebs) {
672+
kfree(per_cpu(insn_buffer, cpu));
673+
per_cpu(insn_buffer, cpu) = NULL;
668674

669-
/* Clear the fixmap */
670-
cea = &get_cpu_entry_area(cpu)->cpu_debug_buffers.pebs_buffer;
671-
ds_clear_cea(cea, x86_pmu.pebs_buffer_size);
672-
dsfree_pages(hwev->ds_pebs_vaddr, x86_pmu.pebs_buffer_size);
673-
hwev->ds_pebs_vaddr = NULL;
675+
/* Clear the fixmap */
676+
cea = &get_cpu_entry_area(cpu)->cpu_debug_buffers.pebs_buffer;
677+
ds_clear_cea(cea, x86_pmu.pebs_buffer_size);
678+
}
679+
680+
dsfree_pages(hwev->pebs_vaddr, x86_pmu.pebs_buffer_size);
681+
hwev->pebs_vaddr = NULL;
674682
}
675683

676684
static int alloc_bts_buffer(int cpu)
@@ -823,6 +831,56 @@ void reserve_ds_buffers(void)
823831
}
824832
}
825833

834+
inline int alloc_arch_pebs_buf_on_cpu(int cpu)
835+
{
836+
if (!x86_pmu.arch_pebs)
837+
return 0;
838+
839+
return alloc_pebs_buffer(cpu);
840+
}
841+
842+
inline void release_arch_pebs_buf_on_cpu(int cpu)
843+
{
844+
if (!x86_pmu.arch_pebs)
845+
return;
846+
847+
release_pebs_buffer(cpu);
848+
}
849+
850+
void init_arch_pebs_on_cpu(int cpu)
851+
{
852+
struct cpu_hw_events *cpuc = per_cpu_ptr(&cpu_hw_events, cpu);
853+
u64 arch_pebs_base;
854+
855+
if (!x86_pmu.arch_pebs)
856+
return;
857+
858+
if (!cpuc->pebs_vaddr) {
859+
WARN(1, "Fail to allocate PEBS buffer on CPU %d\n", cpu);
860+
x86_pmu.pebs_active = 0;
861+
return;
862+
}
863+
864+
/*
865+
* 4KB-aligned pointer of the output buffer
866+
* (__alloc_pages_node() return page aligned address)
867+
* Buffer Size = 4KB * 2^SIZE
868+
* contiguous physical buffer (__alloc_pages_node() with order)
869+
*/
870+
arch_pebs_base = virt_to_phys(cpuc->pebs_vaddr) | PEBS_BUFFER_SHIFT;
871+
wrmsr_on_cpu(cpu, MSR_IA32_PEBS_BASE, (u32)arch_pebs_base,
872+
(u32)(arch_pebs_base >> 32));
873+
x86_pmu.pebs_active = 1;
874+
}
875+
876+
inline void fini_arch_pebs_on_cpu(int cpu)
877+
{
878+
if (!x86_pmu.arch_pebs)
879+
return;
880+
881+
wrmsr_on_cpu(cpu, MSR_IA32_PEBS_BASE, 0, 0);
882+
}
883+
826884
/*
827885
* BTS
828886
*/
@@ -2883,8 +2941,8 @@ static void intel_pmu_drain_arch_pebs(struct pt_regs *iregs,
28832941
return;
28842942
}
28852943

2886-
base = cpuc->ds_pebs_vaddr;
2887-
top = (void *)((u64)cpuc->ds_pebs_vaddr +
2944+
base = cpuc->pebs_vaddr;
2945+
top = (void *)((u64)cpuc->pebs_vaddr +
28882946
(index.wr << ARCH_PEBS_INDEX_WR_SHIFT));
28892947

28902948
index.wr = 0;

arch/x86/events/perf_event.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,9 @@ struct cpu_hw_events {
283283
* Intel DebugStore bits
284284
*/
285285
struct debug_store *ds;
286-
void *ds_pebs_vaddr;
287286
void *ds_bts_vaddr;
287+
/* DS based PEBS or arch-PEBS buffer address */
288+
void *pebs_vaddr;
288289
u64 pebs_enabled;
289290
int n_pebs;
290291
int n_large_pebs;
@@ -1617,6 +1618,14 @@ extern void intel_cpuc_finish(struct cpu_hw_events *cpuc);
16171618

16181619
int intel_pmu_init(void);
16191620

1621+
int alloc_arch_pebs_buf_on_cpu(int cpu);
1622+
1623+
void release_arch_pebs_buf_on_cpu(int cpu);
1624+
1625+
void init_arch_pebs_on_cpu(int cpu);
1626+
1627+
void fini_arch_pebs_on_cpu(int cpu);
1628+
16201629
void init_debug_store_on_cpu(int cpu);
16211630

16221631
void fini_debug_store_on_cpu(int cpu);

arch/x86/include/asm/intel_ds.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
#include <linux/percpu-defs.h>
55

66
#define BTS_BUFFER_SIZE (PAGE_SIZE << 4)
7-
#define PEBS_BUFFER_SIZE (PAGE_SIZE << 4)
7+
#define PEBS_BUFFER_SHIFT 4
8+
#define PEBS_BUFFER_SIZE (PAGE_SIZE << PEBS_BUFFER_SHIFT)
89

910
/* The maximal number of PEBS events: */
1011
#define MAX_PEBS_EVENTS_FMT4 8

0 commit comments

Comments
 (0)