@@ -905,6 +905,50 @@ struct mon_read {
905905 int err ;
906906};
907907
908+ static bool mpam_ris_has_mbwu_long_counter (struct mpam_msc_ris * ris )
909+ {
910+ return (mpam_has_feature (mpam_feat_msmon_mbwu_63counter , & ris -> props ) ||
911+ mpam_has_feature (mpam_feat_msmon_mbwu_44counter , & ris -> props ));
912+ }
913+
914+ static u64 mpam_msc_read_mbwu_l (struct mpam_msc * msc )
915+ {
916+ int retry = 3 ;
917+ u32 mbwu_l_low ;
918+ u64 mbwu_l_high1 , mbwu_l_high2 ;
919+
920+ mpam_mon_sel_lock_held (msc );
921+
922+ WARN_ON_ONCE ((MSMON_MBWU_L + sizeof (u64 )) > msc -> mapped_hwpage_sz );
923+ WARN_ON_ONCE (!cpumask_test_cpu (smp_processor_id (), & msc -> accessibility ));
924+
925+ mbwu_l_high2 = __mpam_read_reg (msc , MSMON_MBWU_L + 4 );
926+ do {
927+ mbwu_l_high1 = mbwu_l_high2 ;
928+ mbwu_l_low = __mpam_read_reg (msc , MSMON_MBWU_L );
929+ mbwu_l_high2 = __mpam_read_reg (msc , MSMON_MBWU_L + 4 );
930+
931+ retry -- ;
932+ } while (mbwu_l_high1 != mbwu_l_high2 && retry > 0 );
933+
934+ if (mbwu_l_high1 == mbwu_l_high2 )
935+ return (mbwu_l_high1 << 32 ) | mbwu_l_low ;
936+
937+ pr_warn ("Failed to read a stable value\n" );
938+ return MSMON___L_NRDY ;
939+ }
940+
941+ static void mpam_msc_zero_mbwu_l (struct mpam_msc * msc )
942+ {
943+ mpam_mon_sel_lock_held (msc );
944+
945+ WARN_ON_ONCE ((MSMON_MBWU_L + sizeof (u64 )) > msc -> mapped_hwpage_sz );
946+ WARN_ON_ONCE (!cpumask_test_cpu (smp_processor_id (), & msc -> accessibility ));
947+
948+ __mpam_write_reg (msc , MSMON_MBWU_L , 0 );
949+ __mpam_write_reg (msc , MSMON_MBWU_L + 4 , 0 );
950+ }
951+
908952static void gen_msmon_ctl_flt_vals (struct mon_read * m , u32 * ctl_val ,
909953 u32 * flt_val )
910954{
@@ -931,7 +975,9 @@ static void gen_msmon_ctl_flt_vals(struct mon_read *m, u32 *ctl_val,
931975 * flt_val |= FIELD_PREP (MSMON_CFG_CSU_FLT_XCL , ctx -> csu_exclude_clean );
932976
933977 break ;
934- case mpam_feat_msmon_mbwu :
978+ case mpam_feat_msmon_mbwu_31counter :
979+ case mpam_feat_msmon_mbwu_44counter :
980+ case mpam_feat_msmon_mbwu_63counter :
935981 * ctl_val |= MSMON_CFG_MBWU_CTL_TYPE_MBWU ;
936982
937983 if (mpam_has_feature (mpam_feat_msmon_mbwu_rwbw , & m -> ris -> props ))
@@ -953,7 +999,9 @@ static void read_msmon_ctl_flt_vals(struct mon_read *m, u32 *ctl_val,
953999 * ctl_val = mpam_read_monsel_reg (msc , CFG_CSU_CTL );
9541000 * flt_val = mpam_read_monsel_reg (msc , CFG_CSU_FLT );
9551001 break ;
956- case mpam_feat_msmon_mbwu :
1002+ case mpam_feat_msmon_mbwu_31counter :
1003+ case mpam_feat_msmon_mbwu_44counter :
1004+ case mpam_feat_msmon_mbwu_63counter :
9571005 * ctl_val = mpam_read_monsel_reg (msc , CFG_MBWU_CTL );
9581006 * flt_val = mpam_read_monsel_reg (msc , CFG_MBWU_FLT );
9591007 break ;
@@ -966,6 +1014,9 @@ static void read_msmon_ctl_flt_vals(struct mon_read *m, u32 *ctl_val,
9661014static inline void clean_msmon_ctl_val (u32 * cur_ctl )
9671015{
9681016 * cur_ctl &= ~MSMON_CFG_x_CTL_OFLOW_STATUS ;
1017+
1018+ if (FIELD_GET (MSMON_CFG_x_CTL_TYPE , * cur_ctl ) == MSMON_CFG_MBWU_CTL_TYPE_MBWU )
1019+ * cur_ctl &= ~MSMON_CFG_MBWU_CTL_OFLOW_STATUS_L ;
9691020}
9701021
9711022static void write_msmon_ctl_flt_vals (struct mon_read * m , u32 ctl_val ,
@@ -984,12 +1035,17 @@ static void write_msmon_ctl_flt_vals(struct mon_read *m, u32 ctl_val,
9841035 mpam_write_monsel_reg (msc , CSU , 0 );
9851036 mpam_write_monsel_reg (msc , CFG_CSU_CTL , ctl_val | MSMON_CFG_x_CTL_EN );
9861037 break ;
987- case mpam_feat_msmon_mbwu :
1038+ case mpam_feat_msmon_mbwu_31counter :
1039+ case mpam_feat_msmon_mbwu_44counter :
1040+ case mpam_feat_msmon_mbwu_63counter :
9881041 mpam_write_monsel_reg (msc , CFG_MBWU_FLT , flt_val );
9891042 mpam_write_monsel_reg (msc , CFG_MBWU_CTL , ctl_val );
9901043 mpam_write_monsel_reg (msc , CFG_MBWU_CTL , ctl_val | MSMON_CFG_x_CTL_EN );
9911044 /* Counting monitors require NRDY to be reset by software */
992- mpam_write_monsel_reg (msc , MBWU , 0 );
1045+ if (m -> type == mpam_feat_msmon_mbwu_31counter )
1046+ mpam_write_monsel_reg (msc , MBWU , 0 );
1047+ else
1048+ mpam_msc_zero_mbwu_l (m -> ris -> vmsc -> msc );
9931049 break ;
9941050 default :
9951051 pr_warn ("Unexpected monitor type %d\n" , m -> type );
@@ -998,8 +1054,17 @@ static void write_msmon_ctl_flt_vals(struct mon_read *m, u32 ctl_val,
9981054
9991055static u64 mpam_msmon_overflow_val (enum mpam_device_features type )
10001056{
1001- /* TODO: scaling, and long counters */
1002- return BIT_ULL (hweight_long (MSMON___VALUE ));
1057+ /* TODO: implement scaling counters */
1058+ switch (type ) {
1059+ case mpam_feat_msmon_mbwu_63counter :
1060+ return BIT_ULL (hweight_long (MSMON___LWD_VALUE ));
1061+ case mpam_feat_msmon_mbwu_44counter :
1062+ return BIT_ULL (hweight_long (MSMON___L_VALUE ));
1063+ case mpam_feat_msmon_mbwu_31counter :
1064+ return BIT_ULL (hweight_long (MSMON___VALUE ));
1065+ default :
1066+ return 0 ;
1067+ }
10031068}
10041069
10051070static void __ris_msmon_read (void * arg )
@@ -1029,7 +1094,12 @@ static void __ris_msmon_read(void *arg)
10291094 * This saves waiting for 'nrdy' on subsequent reads.
10301095 */
10311096 read_msmon_ctl_flt_vals (m , & cur_ctl , & cur_flt );
1032- overflow = cur_ctl & MSMON_CFG_x_CTL_OFLOW_STATUS ;
1097+
1098+ if (mpam_feat_msmon_mbwu_31counter == m -> type )
1099+ overflow = cur_ctl & MSMON_CFG_x_CTL_OFLOW_STATUS ;
1100+ else if (mpam_feat_msmon_mbwu_44counter == m -> type ||
1101+ mpam_feat_msmon_mbwu_63counter == m -> type )
1102+ overflow = cur_ctl & MSMON_CFG_MBWU_CTL_OFLOW_STATUS_L ;
10331103
10341104 clean_msmon_ctl_val (& cur_ctl );
10351105 gen_msmon_ctl_flt_vals (m , & ctl_val , & flt_val );
@@ -1041,7 +1111,9 @@ static void __ris_msmon_read(void *arg)
10411111 overflow = false;
10421112 } else if (overflow ) {
10431113 mpam_write_monsel_reg (msc , CFG_MBWU_CTL ,
1044- cur_ctl & ~MSMON_CFG_x_CTL_OFLOW_STATUS );
1114+ cur_ctl &
1115+ ~(MSMON_CFG_x_CTL_OFLOW_STATUS |
1116+ MSMON_CFG_MBWU_CTL_OFLOW_STATUS_L ));
10451117 }
10461118
10471119 switch (m -> type ) {
@@ -1051,11 +1123,24 @@ static void __ris_msmon_read(void *arg)
10511123 nrdy = now & MSMON___NRDY ;
10521124 now = FIELD_GET (MSMON___VALUE , now );
10531125 break ;
1054- case mpam_feat_msmon_mbwu :
1055- now = mpam_read_monsel_reg (msc , MBWU );
1056- if (mpam_has_feature (mpam_feat_msmon_mbwu_hw_nrdy , rprops ))
1057- nrdy = now & MSMON___NRDY ;
1058- now = FIELD_GET (MSMON___VALUE , now );
1126+ case mpam_feat_msmon_mbwu_31counter :
1127+ case mpam_feat_msmon_mbwu_44counter :
1128+ case mpam_feat_msmon_mbwu_63counter :
1129+ if (m -> type != mpam_feat_msmon_mbwu_31counter ) {
1130+ now = mpam_msc_read_mbwu_l (msc );
1131+ if (mpam_has_feature (mpam_feat_msmon_mbwu_hw_nrdy , rprops ))
1132+ nrdy = now & MSMON___L_NRDY ;
1133+
1134+ if (m -> type == mpam_feat_msmon_mbwu_63counter )
1135+ now = FIELD_GET (MSMON___LWD_VALUE , now );
1136+ else
1137+ now = FIELD_GET (MSMON___L_VALUE , now );
1138+ } else {
1139+ now = mpam_read_monsel_reg (msc , MBWU );
1140+ if (mpam_has_feature (mpam_feat_msmon_mbwu_hw_nrdy , rprops ))
1141+ nrdy = now & MSMON___NRDY ;
1142+ now = FIELD_GET (MSMON___VALUE , now );
1143+ }
10591144
10601145 if (nrdy )
10611146 break ;
@@ -1118,13 +1203,26 @@ static int _msmon_read(struct mpam_component *comp, struct mon_read *arg)
11181203 return any_err ;
11191204}
11201205
1206+ static enum mpam_device_features mpam_msmon_choose_counter (struct mpam_class * class )
1207+ {
1208+ struct mpam_props * cprops = & class -> props ;
1209+
1210+ if (mpam_has_feature (mpam_feat_msmon_mbwu_63counter , cprops ))
1211+ return mpam_feat_msmon_mbwu_63counter ;
1212+ if (mpam_has_feature (mpam_feat_msmon_mbwu_44counter , cprops ))
1213+ return mpam_feat_msmon_mbwu_44counter ;
1214+
1215+ return mpam_feat_msmon_mbwu_31counter ;
1216+ }
1217+
11211218int mpam_msmon_read (struct mpam_component * comp , struct mon_cfg * ctx ,
11221219 enum mpam_device_features type , u64 * val )
11231220{
11241221 int err ;
11251222 struct mon_read arg ;
11261223 u64 wait_jiffies = 0 ;
1127- struct mpam_props * cprops = & comp -> class -> props ;
1224+ struct mpam_class * class = comp -> class ;
1225+ struct mpam_props * cprops = & class -> props ;
11281226
11291227 might_sleep ();
11301228
@@ -1134,6 +1232,9 @@ int mpam_msmon_read(struct mpam_component *comp, struct mon_cfg *ctx,
11341232 if (!mpam_has_feature (type , cprops ))
11351233 return - EOPNOTSUPP ;
11361234
1235+ if (type == mpam_feat_msmon_mbwu )
1236+ type = mpam_msmon_choose_counter (class );
1237+
11371238 arg = (struct mon_read ) {
11381239 .ctx = ctx ,
11391240 .type = type ,
@@ -1142,8 +1243,8 @@ int mpam_msmon_read(struct mpam_component *comp, struct mon_cfg *ctx,
11421243 * val = 0 ;
11431244
11441245 err = _msmon_read (comp , & arg );
1145- if (err == - EBUSY && comp -> class -> nrdy_usec )
1146- wait_jiffies = usecs_to_jiffies (comp -> class -> nrdy_usec );
1246+ if (err == - EBUSY && class -> nrdy_usec )
1247+ wait_jiffies = usecs_to_jiffies (class -> nrdy_usec );
11471248
11481249 while (wait_jiffies )
11491250 wait_jiffies = schedule_timeout_uninterruptible (wait_jiffies );
@@ -1282,12 +1383,13 @@ static int mpam_restore_mbwu_state(void *_ris)
12821383 int i ;
12831384 struct mon_read mwbu_arg ;
12841385 struct mpam_msc_ris * ris = _ris ;
1386+ struct mpam_class * class = ris -> vmsc -> comp -> class ;
12851387
12861388 for (i = 0 ; i < ris -> props .num_mbwu_mon ; i ++ ) {
12871389 if (ris -> mbwu_state [i ].enabled ) {
12881390 mwbu_arg .ris = ris ;
12891391 mwbu_arg .ctx = & ris -> mbwu_state [i ].cfg ;
1290- mwbu_arg .type = mpam_feat_msmon_mbwu ;
1392+ mwbu_arg .type = mpam_msmon_choose_counter ( class ) ;
12911393
12921394 __ris_msmon_read (& mwbu_arg );
12931395 }
@@ -1322,8 +1424,13 @@ static int mpam_save_mbwu_state(void *arg)
13221424 cur_ctl = mpam_read_monsel_reg (msc , CFG_MBWU_CTL );
13231425 mpam_write_monsel_reg (msc , CFG_MBWU_CTL , 0 );
13241426
1325- val = mpam_read_monsel_reg (msc , MBWU );
1326- mpam_write_monsel_reg (msc , MBWU , 0 );
1427+ if (mpam_ris_has_mbwu_long_counter (ris )) {
1428+ val = mpam_msc_read_mbwu_l (msc );
1429+ mpam_msc_zero_mbwu_l (msc );
1430+ } else {
1431+ val = mpam_read_monsel_reg (msc , MBWU );
1432+ mpam_write_monsel_reg (msc , MBWU , 0 );
1433+ }
13271434
13281435 cfg -> mon = i ;
13291436 cfg -> pmg = FIELD_GET (MSMON_CFG_x_FLT_PMG , cur_flt );
0 commit comments