@@ -37,6 +37,12 @@ static cpumask_t core_imc_cpumask;
37
37
struct imc_pmu_ref * core_imc_refc ;
38
38
static struct imc_pmu * core_imc_pmu ;
39
39
40
+ /* Thread IMC data structures and variables */
41
+
42
+ static DEFINE_PER_CPU (u64 * , thread_imc_mem ) ;
43
+ static struct imc_pmu * thread_imc_pmu ;
44
+ static int thread_imc_mem_size ;
45
+
40
46
struct imc_pmu * imc_event_to_pmu (struct perf_event * event )
41
47
{
42
48
return container_of (event -> pmu , struct imc_pmu , pmu );
@@ -728,15 +734,188 @@ static int core_imc_event_init(struct perf_event *event)
728
734
return 0 ;
729
735
}
730
736
731
- static u64 * get_event_base_addr (struct perf_event * event )
737
+ /*
738
+ * Allocates a page of memory for each of the online cpus, and write the
739
+ * physical base address of that page to the LDBAR for that cpu.
740
+ *
741
+ * LDBAR Register Layout:
742
+ *
743
+ * 0 4 8 12 16 20 24 28
744
+ * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
745
+ * | | [ ] [ Counter Address [8:50]
746
+ * | * Mode |
747
+ * | * PB Scope
748
+ * * Enable/Disable
749
+ *
750
+ * 32 36 40 44 48 52 56 60
751
+ * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - |
752
+ * Counter Address [8:50] ]
753
+ *
754
+ */
755
+ static int thread_imc_mem_alloc (int cpu_id , int size )
756
+ {
757
+ u64 ldbar_value , * local_mem = per_cpu (thread_imc_mem , cpu_id );
758
+ int phys_id = topology_physical_package_id (cpu_id );
759
+
760
+ if (!local_mem ) {
761
+ /*
762
+ * This case could happen only once at start, since we dont
763
+ * free the memory in cpu offline path.
764
+ */
765
+ local_mem = page_address (alloc_pages_node (phys_id ,
766
+ GFP_KERNEL | __GFP_ZERO | __GFP_THISNODE ,
767
+ get_order (size )));
768
+ if (!local_mem )
769
+ return - ENOMEM ;
770
+
771
+ per_cpu (thread_imc_mem , cpu_id ) = local_mem ;
772
+ }
773
+
774
+ ldbar_value = ((u64 )local_mem & THREAD_IMC_LDBAR_MASK ) | THREAD_IMC_ENABLE ;
775
+
776
+ mtspr (SPRN_LDBAR , ldbar_value );
777
+ return 0 ;
778
+ }
779
+
780
+ static int ppc_thread_imc_cpu_online (unsigned int cpu )
732
781
{
782
+ return thread_imc_mem_alloc (cpu , thread_imc_mem_size );
783
+ }
784
+
785
+ static int ppc_thread_imc_cpu_offline (unsigned int cpu )
786
+ {
787
+ mtspr (SPRN_LDBAR , 0 );
788
+ return 0 ;
789
+ }
790
+
791
+ static int thread_imc_cpu_init (void )
792
+ {
793
+ return cpuhp_setup_state (CPUHP_AP_PERF_POWERPC_THREAD_IMC_ONLINE ,
794
+ "perf/powerpc/imc_thread:online" ,
795
+ ppc_thread_imc_cpu_online ,
796
+ ppc_thread_imc_cpu_offline );
797
+ }
798
+
799
+ void thread_imc_pmu_sched_task (struct perf_event_context * ctx ,
800
+ bool sched_in )
801
+ {
802
+ int core_id ;
803
+ struct imc_pmu_ref * ref ;
804
+
805
+ if (!is_core_imc_mem_inited (smp_processor_id ()))
806
+ return ;
807
+
808
+ core_id = smp_processor_id () / threads_per_core ;
733
809
/*
734
- * Subsequent patch will add code to detect caller imc pmu
735
- * and return accordingly.
810
+ * imc pmus are enabled only when it is used.
811
+ * See if this is triggered for the first time.
812
+ * If yes, take the mutex lock and enable the counters.
813
+ * If not, just increment the count in ref count struct.
736
814
*/
815
+ ref = & core_imc_refc [core_id ];
816
+ if (!ref )
817
+ return ;
818
+
819
+ if (sched_in ) {
820
+ mutex_lock (& ref -> lock );
821
+ if (ref -> refc == 0 ) {
822
+ if (opal_imc_counters_start (OPAL_IMC_COUNTERS_CORE ,
823
+ get_hard_smp_processor_id (smp_processor_id ()))) {
824
+ mutex_unlock (& ref -> lock );
825
+ pr_err ("thread-imc: Unable to start the counter\
826
+ for core %d\n" , core_id );
827
+ return ;
828
+ }
829
+ }
830
+ ++ ref -> refc ;
831
+ mutex_unlock (& ref -> lock );
832
+ } else {
833
+ mutex_lock (& ref -> lock );
834
+ ref -> refc -- ;
835
+ if (ref -> refc == 0 ) {
836
+ if (opal_imc_counters_stop (OPAL_IMC_COUNTERS_CORE ,
837
+ get_hard_smp_processor_id (smp_processor_id ()))) {
838
+ mutex_unlock (& ref -> lock );
839
+ pr_err ("thread-imc: Unable to stop the counters\
840
+ for core %d\n" , core_id );
841
+ return ;
842
+ }
843
+ } else if (ref -> refc < 0 ) {
844
+ ref -> refc = 0 ;
845
+ }
846
+ mutex_unlock (& ref -> lock );
847
+ }
848
+
849
+ return ;
850
+ }
851
+
852
+ static int thread_imc_event_init (struct perf_event * event )
853
+ {
854
+ u32 config = event -> attr .config ;
855
+ struct task_struct * target ;
856
+ struct imc_pmu * pmu ;
857
+
858
+ if (event -> attr .type != event -> pmu -> type )
859
+ return - ENOENT ;
860
+
861
+ /* Sampling not supported */
862
+ if (event -> hw .sample_period )
863
+ return - EINVAL ;
864
+
865
+ event -> hw .idx = -1 ;
866
+ pmu = imc_event_to_pmu (event );
867
+
868
+ /* Sanity check for config offset */
869
+ if (((config & IMC_EVENT_OFFSET_MASK ) > pmu -> counter_mem_size ))
870
+ return - EINVAL ;
871
+
872
+ target = event -> hw .target ;
873
+ if (!target )
874
+ return - EINVAL ;
875
+
876
+ event -> pmu -> task_ctx_nr = perf_sw_context ;
877
+ return 0 ;
878
+ }
879
+
880
+ static bool is_thread_imc_pmu (struct perf_event * event )
881
+ {
882
+ if (!strncmp (event -> pmu -> name , "thread_imc" , strlen ("thread_imc" )))
883
+ return true;
884
+
885
+ return false;
886
+ }
887
+
888
+ static u64 * get_event_base_addr (struct perf_event * event )
889
+ {
890
+ u64 addr ;
891
+
892
+ if (is_thread_imc_pmu (event )) {
893
+ addr = (u64 )per_cpu (thread_imc_mem , smp_processor_id ());
894
+ return (u64 * )(addr + (event -> attr .config & IMC_EVENT_OFFSET_MASK ));
895
+ }
896
+
737
897
return (u64 * )event -> hw .event_base ;
738
898
}
739
899
900
+ static void thread_imc_pmu_start_txn (struct pmu * pmu ,
901
+ unsigned int txn_flags )
902
+ {
903
+ if (txn_flags & ~PERF_PMU_TXN_ADD )
904
+ return ;
905
+ perf_pmu_disable (pmu );
906
+ }
907
+
908
+ static void thread_imc_pmu_cancel_txn (struct pmu * pmu )
909
+ {
910
+ perf_pmu_enable (pmu );
911
+ }
912
+
913
+ static int thread_imc_pmu_commit_txn (struct pmu * pmu )
914
+ {
915
+ perf_pmu_enable (pmu );
916
+ return 0 ;
917
+ }
918
+
740
919
static u64 imc_read_counter (struct perf_event * event )
741
920
{
742
921
u64 * addr , data ;
@@ -794,6 +973,26 @@ static int imc_event_add(struct perf_event *event, int flags)
794
973
return 0 ;
795
974
}
796
975
976
+ static int thread_imc_event_add (struct perf_event * event , int flags )
977
+ {
978
+ if (flags & PERF_EF_START )
979
+ imc_event_start (event , flags );
980
+
981
+ /* Enable the sched_task to start the engine */
982
+ perf_sched_cb_inc (event -> ctx -> pmu );
983
+ return 0 ;
984
+ }
985
+
986
+ static void thread_imc_event_del (struct perf_event * event , int flags )
987
+ {
988
+ /*
989
+ * Take a snapshot and calculate the delta and update
990
+ * the event counter values.
991
+ */
992
+ imc_event_update (event );
993
+ perf_sched_cb_dec (event -> ctx -> pmu );
994
+ }
995
+
797
996
/* update_pmu_ops : Populate the appropriate operations for "pmu" */
798
997
static int update_pmu_ops (struct imc_pmu * pmu )
799
998
{
@@ -815,6 +1014,15 @@ static int update_pmu_ops(struct imc_pmu *pmu)
815
1014
pmu -> pmu .event_init = core_imc_event_init ;
816
1015
pmu -> attr_groups [IMC_CPUMASK_ATTR ] = & imc_pmu_cpumask_attr_group ;
817
1016
break ;
1017
+ case IMC_DOMAIN_THREAD :
1018
+ pmu -> pmu .event_init = thread_imc_event_init ;
1019
+ pmu -> pmu .sched_task = thread_imc_pmu_sched_task ;
1020
+ pmu -> pmu .add = thread_imc_event_add ;
1021
+ pmu -> pmu .del = thread_imc_event_del ;
1022
+ pmu -> pmu .start_txn = thread_imc_pmu_start_txn ;
1023
+ pmu -> pmu .cancel_txn = thread_imc_pmu_cancel_txn ;
1024
+ pmu -> pmu .commit_txn = thread_imc_pmu_commit_txn ;
1025
+ break ;
818
1026
default :
819
1027
break ;
820
1028
}
@@ -882,6 +1090,31 @@ static void cleanup_all_core_imc_memory(void)
882
1090
kfree (core_imc_refc );
883
1091
}
884
1092
1093
+ static void thread_imc_ldbar_disable (void * dummy )
1094
+ {
1095
+ /*
1096
+ * By Zeroing LDBAR, we disable thread-imc
1097
+ * updates.
1098
+ */
1099
+ mtspr (SPRN_LDBAR , 0 );
1100
+ }
1101
+
1102
+ void thread_imc_disable (void )
1103
+ {
1104
+ on_each_cpu (thread_imc_ldbar_disable , NULL , 1 );
1105
+ }
1106
+
1107
+ static void cleanup_all_thread_imc_memory (void )
1108
+ {
1109
+ int i , order = get_order (thread_imc_mem_size );
1110
+
1111
+ for_each_online_cpu (i ) {
1112
+ if (per_cpu (thread_imc_mem , i ))
1113
+ free_pages ((u64 )per_cpu (thread_imc_mem , i ), order );
1114
+
1115
+ }
1116
+ }
1117
+
885
1118
/*
886
1119
* Common function to unregister cpu hotplug callback and
887
1120
* free the memory.
@@ -908,6 +1141,12 @@ static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr)
908
1141
cleanup_all_core_imc_memory ();
909
1142
}
910
1143
1144
+ /* Free thread_imc memory */
1145
+ if (pmu_ptr -> domain == IMC_DOMAIN_THREAD ) {
1146
+ cpuhp_remove_state (CPUHP_AP_PERF_POWERPC_THREAD_IMC_ONLINE );
1147
+ cleanup_all_thread_imc_memory ();
1148
+ }
1149
+
911
1150
/* Only free the attr_groups which are dynamically allocated */
912
1151
kfree (pmu_ptr -> attr_groups [IMC_EVENT_ATTR ]-> attrs );
913
1152
kfree (pmu_ptr -> attr_groups [IMC_EVENT_ATTR ]);
@@ -923,7 +1162,7 @@ static int imc_mem_init(struct imc_pmu *pmu_ptr, struct device_node *parent,
923
1162
int pmu_index )
924
1163
{
925
1164
const char * s ;
926
- int nr_cores ;
1165
+ int nr_cores , cpu , res ;
927
1166
928
1167
if (of_property_read_string (parent , "name" , & s ))
929
1168
return - ENODEV ;
@@ -959,6 +1198,21 @@ static int imc_mem_init(struct imc_pmu *pmu_ptr, struct device_node *parent,
959
1198
960
1199
core_imc_pmu = pmu_ptr ;
961
1200
break ;
1201
+ case IMC_DOMAIN_THREAD :
1202
+ /* Update the pmu name */
1203
+ pmu_ptr -> pmu .name = kasprintf (GFP_KERNEL , "%s%s" , s , "_imc" );
1204
+ if (!pmu_ptr -> pmu .name )
1205
+ return - ENOMEM ;
1206
+
1207
+ thread_imc_mem_size = pmu_ptr -> counter_mem_size ;
1208
+ for_each_online_cpu (cpu ) {
1209
+ res = thread_imc_mem_alloc (cpu , pmu_ptr -> counter_mem_size );
1210
+ if (res )
1211
+ return res ;
1212
+ }
1213
+
1214
+ thread_imc_pmu = pmu_ptr ;
1215
+ break ;
962
1216
default :
963
1217
return - EINVAL ;
964
1218
}
@@ -1016,6 +1270,14 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id
1016
1270
return ret ;
1017
1271
}
1018
1272
1273
+ break ;
1274
+ case IMC_DOMAIN_THREAD :
1275
+ ret = thread_imc_cpu_init ();
1276
+ if (ret ) {
1277
+ cleanup_all_thread_imc_memory ();
1278
+ return ret ;
1279
+ }
1280
+
1019
1281
break ;
1020
1282
default :
1021
1283
return -1 ; /* Unknown domain */
0 commit comments