@@ -436,6 +436,11 @@ static LIST_HEAD(pmus);
436
436
static DEFINE_MUTEX (pmus_lock );
437
437
static struct srcu_struct pmus_srcu ;
438
438
static cpumask_var_t perf_online_mask ;
439
+ static cpumask_var_t perf_online_core_mask ;
440
+ static cpumask_var_t perf_online_die_mask ;
441
+ static cpumask_var_t perf_online_cluster_mask ;
442
+ static cpumask_var_t perf_online_pkg_mask ;
443
+ static cpumask_var_t perf_online_sys_mask ;
439
444
static struct kmem_cache * perf_event_cache ;
440
445
441
446
/*
@@ -11578,10 +11583,60 @@ perf_event_mux_interval_ms_store(struct device *dev,
11578
11583
}
11579
11584
static DEVICE_ATTR_RW (perf_event_mux_interval_ms );
11580
11585
11586
+ static inline const struct cpumask * perf_scope_cpu_topology_cpumask (unsigned int scope , int cpu )
11587
+ {
11588
+ switch (scope ) {
11589
+ case PERF_PMU_SCOPE_CORE :
11590
+ return topology_sibling_cpumask (cpu );
11591
+ case PERF_PMU_SCOPE_DIE :
11592
+ return topology_die_cpumask (cpu );
11593
+ case PERF_PMU_SCOPE_CLUSTER :
11594
+ return topology_cluster_cpumask (cpu );
11595
+ case PERF_PMU_SCOPE_PKG :
11596
+ return topology_core_cpumask (cpu );
11597
+ case PERF_PMU_SCOPE_SYS_WIDE :
11598
+ return cpu_online_mask ;
11599
+ }
11600
+
11601
+ return NULL ;
11602
+ }
11603
+
11604
+ static inline struct cpumask * perf_scope_cpumask (unsigned int scope )
11605
+ {
11606
+ switch (scope ) {
11607
+ case PERF_PMU_SCOPE_CORE :
11608
+ return perf_online_core_mask ;
11609
+ case PERF_PMU_SCOPE_DIE :
11610
+ return perf_online_die_mask ;
11611
+ case PERF_PMU_SCOPE_CLUSTER :
11612
+ return perf_online_cluster_mask ;
11613
+ case PERF_PMU_SCOPE_PKG :
11614
+ return perf_online_pkg_mask ;
11615
+ case PERF_PMU_SCOPE_SYS_WIDE :
11616
+ return perf_online_sys_mask ;
11617
+ }
11618
+
11619
+ return NULL ;
11620
+ }
11621
+
11622
+ static ssize_t cpumask_show (struct device * dev , struct device_attribute * attr ,
11623
+ char * buf )
11624
+ {
11625
+ struct pmu * pmu = dev_get_drvdata (dev );
11626
+ struct cpumask * mask = perf_scope_cpumask (pmu -> scope );
11627
+
11628
+ if (mask )
11629
+ return cpumap_print_to_pagebuf (true, buf , mask );
11630
+ return 0 ;
11631
+ }
11632
+
11633
+ static DEVICE_ATTR_RO (cpumask );
11634
+
11581
11635
static struct attribute * pmu_dev_attrs [] = {
11582
11636
& dev_attr_type .attr ,
11583
11637
& dev_attr_perf_event_mux_interval_ms .attr ,
11584
11638
& dev_attr_nr_addr_filters .attr ,
11639
+ & dev_attr_cpumask .attr ,
11585
11640
NULL ,
11586
11641
};
11587
11642
@@ -11593,6 +11648,10 @@ static umode_t pmu_dev_is_visible(struct kobject *kobj, struct attribute *a, int
11593
11648
if (n == 2 && !pmu -> nr_addr_filters )
11594
11649
return 0 ;
11595
11650
11651
+ /* cpumask */
11652
+ if (n == 3 && pmu -> scope == PERF_PMU_SCOPE_NONE )
11653
+ return 0 ;
11654
+
11596
11655
return a -> mode ;
11597
11656
}
11598
11657
@@ -11677,6 +11736,11 @@ int perf_pmu_register(struct pmu *pmu, const char *name, int type)
11677
11736
goto free_pdc ;
11678
11737
}
11679
11738
11739
+ if (WARN_ONCE (pmu -> scope >= PERF_PMU_MAX_SCOPE , "Can not register a pmu with an invalid scope.\n" )) {
11740
+ ret = - EINVAL ;
11741
+ goto free_pdc ;
11742
+ }
11743
+
11680
11744
pmu -> name = name ;
11681
11745
11682
11746
if (type >= 0 )
@@ -11831,6 +11895,22 @@ static int perf_try_init_event(struct pmu *pmu, struct perf_event *event)
11831
11895
event_has_any_exclude_flag (event ))
11832
11896
ret = - EINVAL ;
11833
11897
11898
+ if (pmu -> scope != PERF_PMU_SCOPE_NONE && event -> cpu >= 0 ) {
11899
+ const struct cpumask * cpumask = perf_scope_cpu_topology_cpumask (pmu -> scope , event -> cpu );
11900
+ struct cpumask * pmu_cpumask = perf_scope_cpumask (pmu -> scope );
11901
+ int cpu ;
11902
+
11903
+ if (pmu_cpumask && cpumask ) {
11904
+ cpu = cpumask_any_and (pmu_cpumask , cpumask );
11905
+ if (cpu >= nr_cpu_ids )
11906
+ ret = - ENODEV ;
11907
+ else
11908
+ event -> cpu = cpu ;
11909
+ } else {
11910
+ ret = - ENODEV ;
11911
+ }
11912
+ }
11913
+
11834
11914
if (ret && event -> destroy )
11835
11915
event -> destroy (event );
11836
11916
}
@@ -13784,6 +13864,12 @@ static void __init perf_event_init_all_cpus(void)
13784
13864
int cpu ;
13785
13865
13786
13866
zalloc_cpumask_var (& perf_online_mask , GFP_KERNEL );
13867
+ zalloc_cpumask_var (& perf_online_core_mask , GFP_KERNEL );
13868
+ zalloc_cpumask_var (& perf_online_die_mask , GFP_KERNEL );
13869
+ zalloc_cpumask_var (& perf_online_cluster_mask , GFP_KERNEL );
13870
+ zalloc_cpumask_var (& perf_online_pkg_mask , GFP_KERNEL );
13871
+ zalloc_cpumask_var (& perf_online_sys_mask , GFP_KERNEL );
13872
+
13787
13873
13788
13874
for_each_possible_cpu (cpu ) {
13789
13875
swhash = & per_cpu (swevent_htable , cpu );
@@ -13833,21 +13919,59 @@ static void __perf_event_exit_context(void *__info)
13833
13919
raw_spin_unlock (& ctx -> lock );
13834
13920
}
13835
13921
13922
+ static void perf_event_clear_cpumask (unsigned int cpu )
13923
+ {
13924
+ int target [PERF_PMU_MAX_SCOPE ];
13925
+ unsigned int scope ;
13926
+ struct pmu * pmu ;
13927
+
13928
+ cpumask_clear_cpu (cpu , perf_online_mask );
13929
+
13930
+ for (scope = PERF_PMU_SCOPE_NONE + 1 ; scope < PERF_PMU_MAX_SCOPE ; scope ++ ) {
13931
+ const struct cpumask * cpumask = perf_scope_cpu_topology_cpumask (scope , cpu );
13932
+ struct cpumask * pmu_cpumask = perf_scope_cpumask (scope );
13933
+
13934
+ target [scope ] = -1 ;
13935
+ if (WARN_ON_ONCE (!pmu_cpumask || !cpumask ))
13936
+ continue ;
13937
+
13938
+ if (!cpumask_test_and_clear_cpu (cpu , pmu_cpumask ))
13939
+ continue ;
13940
+ target [scope ] = cpumask_any_but (cpumask , cpu );
13941
+ if (target [scope ] < nr_cpu_ids )
13942
+ cpumask_set_cpu (target [scope ], pmu_cpumask );
13943
+ }
13944
+
13945
+ /* migrate */
13946
+ list_for_each_entry_rcu (pmu , & pmus , entry , lockdep_is_held (& pmus_srcu )) {
13947
+ if (pmu -> scope == PERF_PMU_SCOPE_NONE ||
13948
+ WARN_ON_ONCE (pmu -> scope >= PERF_PMU_MAX_SCOPE ))
13949
+ continue ;
13950
+
13951
+ if (target [pmu -> scope ] >= 0 && target [pmu -> scope ] < nr_cpu_ids )
13952
+ perf_pmu_migrate_context (pmu , cpu , target [pmu -> scope ]);
13953
+ }
13954
+ }
13955
+
13836
13956
static void perf_event_exit_cpu_context (int cpu )
13837
13957
{
13838
13958
struct perf_cpu_context * cpuctx ;
13839
13959
struct perf_event_context * ctx ;
13840
13960
13841
13961
// XXX simplify cpuctx->online
13842
13962
mutex_lock (& pmus_lock );
13963
+ /*
13964
+ * Clear the cpumasks, and migrate to other CPUs if possible.
13965
+ * Must be invoked before the __perf_event_exit_context.
13966
+ */
13967
+ perf_event_clear_cpumask (cpu );
13843
13968
cpuctx = per_cpu_ptr (& perf_cpu_context , cpu );
13844
13969
ctx = & cpuctx -> ctx ;
13845
13970
13846
13971
mutex_lock (& ctx -> mutex );
13847
13972
smp_call_function_single (cpu , __perf_event_exit_context , ctx , 1 );
13848
13973
cpuctx -> online = 0 ;
13849
13974
mutex_unlock (& ctx -> mutex );
13850
- cpumask_clear_cpu (cpu , perf_online_mask );
13851
13975
mutex_unlock (& pmus_lock );
13852
13976
}
13853
13977
#else
@@ -13856,6 +13980,42 @@ static void perf_event_exit_cpu_context(int cpu) { }
13856
13980
13857
13981
#endif
13858
13982
13983
+ static void perf_event_setup_cpumask (unsigned int cpu )
13984
+ {
13985
+ struct cpumask * pmu_cpumask ;
13986
+ unsigned int scope ;
13987
+
13988
+ cpumask_set_cpu (cpu , perf_online_mask );
13989
+
13990
+ /*
13991
+ * Early boot stage, the cpumask hasn't been set yet.
13992
+ * The perf_online_<domain>_masks includes the first CPU of each domain.
13993
+ * Always uncondifionally set the boot CPU for the perf_online_<domain>_masks.
13994
+ */
13995
+ if (!topology_sibling_cpumask (cpu )) {
13996
+ for (scope = PERF_PMU_SCOPE_NONE + 1 ; scope < PERF_PMU_MAX_SCOPE ; scope ++ ) {
13997
+ pmu_cpumask = perf_scope_cpumask (scope );
13998
+ if (WARN_ON_ONCE (!pmu_cpumask ))
13999
+ continue ;
14000
+ cpumask_set_cpu (cpu , pmu_cpumask );
14001
+ }
14002
+ return ;
14003
+ }
14004
+
14005
+ for (scope = PERF_PMU_SCOPE_NONE + 1 ; scope < PERF_PMU_MAX_SCOPE ; scope ++ ) {
14006
+ const struct cpumask * cpumask = perf_scope_cpu_topology_cpumask (scope , cpu );
14007
+
14008
+ pmu_cpumask = perf_scope_cpumask (scope );
14009
+
14010
+ if (WARN_ON_ONCE (!pmu_cpumask || !cpumask ))
14011
+ continue ;
14012
+
14013
+ if (!cpumask_empty (cpumask ) &&
14014
+ cpumask_any_and (pmu_cpumask , cpumask ) >= nr_cpu_ids )
14015
+ cpumask_set_cpu (cpu , pmu_cpumask );
14016
+ }
14017
+ }
14018
+
13859
14019
int perf_event_init_cpu (unsigned int cpu )
13860
14020
{
13861
14021
struct perf_cpu_context * cpuctx ;
@@ -13864,7 +14024,7 @@ int perf_event_init_cpu(unsigned int cpu)
13864
14024
perf_swevent_init_cpu (cpu );
13865
14025
13866
14026
mutex_lock (& pmus_lock );
13867
- cpumask_set_cpu (cpu , perf_online_mask );
14027
+ perf_event_setup_cpumask (cpu );
13868
14028
cpuctx = per_cpu_ptr (& perf_cpu_context , cpu );
13869
14029
ctx = & cpuctx -> ctx ;
13870
14030
0 commit comments