@@ -46,15 +46,19 @@ static const char * ops[] = { OPS };
4646enum filter_pred_fn {
4747 FILTER_PRED_FN_NOP ,
4848 FILTER_PRED_FN_64 ,
49+ FILTER_PRED_FN_64_CPUMASK ,
4950 FILTER_PRED_FN_S64 ,
5051 FILTER_PRED_FN_U64 ,
5152 FILTER_PRED_FN_32 ,
53+ FILTER_PRED_FN_32_CPUMASK ,
5254 FILTER_PRED_FN_S32 ,
5355 FILTER_PRED_FN_U32 ,
5456 FILTER_PRED_FN_16 ,
57+ FILTER_PRED_FN_16_CPUMASK ,
5558 FILTER_PRED_FN_S16 ,
5659 FILTER_PRED_FN_U16 ,
5760 FILTER_PRED_FN_8 ,
61+ FILTER_PRED_FN_8_CPUMASK ,
5862 FILTER_PRED_FN_S8 ,
5963 FILTER_PRED_FN_U8 ,
6064 FILTER_PRED_FN_COMM ,
@@ -643,6 +647,39 @@ predicate_parse(const char *str, int nr_parens, int nr_preds,
643647 return ERR_PTR (ret );
644648}
645649
650+ static inline int
651+ do_filter_cpumask (int op , const struct cpumask * mask , const struct cpumask * cmp )
652+ {
653+ switch (op ) {
654+ case OP_EQ :
655+ return cpumask_equal (mask , cmp );
656+ case OP_NE :
657+ return !cpumask_equal (mask , cmp );
658+ case OP_BAND :
659+ return cpumask_intersects (mask , cmp );
660+ default :
661+ return 0 ;
662+ }
663+ }
664+
665+ /* Optimisation of do_filter_cpumask() for scalar fields */
666+ static inline int
667+ do_filter_scalar_cpumask (int op , unsigned int cpu , const struct cpumask * mask )
668+ {
669+ switch (op ) {
670+ case OP_EQ :
671+ return cpumask_test_cpu (cpu , mask ) &&
672+ cpumask_nth (1 , mask ) >= nr_cpu_ids ;
673+ case OP_NE :
674+ return !cpumask_test_cpu (cpu , mask ) ||
675+ cpumask_nth (1 , mask ) < nr_cpu_ids ;
676+ case OP_BAND :
677+ return cpumask_test_cpu (cpu , mask );
678+ default :
679+ return 0 ;
680+ }
681+ }
682+
646683enum pred_cmp_types {
647684 PRED_CMP_TYPE_NOP ,
648685 PRED_CMP_TYPE_LT ,
@@ -686,6 +723,18 @@ static int filter_pred_##type(struct filter_pred *pred, void *event) \
686723 } \
687724}
688725
726+ #define DEFINE_CPUMASK_COMPARISON_PRED (size ) \
727+ static int filter_pred_##size##_cpumask(struct filter_pred *pred, void *event) \
728+ { \
729+ u##size *addr = (u##size *)(event + pred->offset); \
730+ unsigned int cpu = *addr; \
731+ \
732+ if (cpu >= nr_cpu_ids) \
733+ return 0; \
734+ \
735+ return do_filter_scalar_cpumask(pred->op, cpu, pred->mask); \
736+ }
737+
689738#define DEFINE_EQUALITY_PRED (size ) \
690739static int filter_pred_##size(struct filter_pred *pred, void *event) \
691740{ \
@@ -707,6 +756,11 @@ DEFINE_COMPARISON_PRED(u16);
707756DEFINE_COMPARISON_PRED (s8 );
708757DEFINE_COMPARISON_PRED (u8 );
709758
759+ DEFINE_CPUMASK_COMPARISON_PRED (64 );
760+ DEFINE_CPUMASK_COMPARISON_PRED (32 );
761+ DEFINE_CPUMASK_COMPARISON_PRED (16 );
762+ DEFINE_CPUMASK_COMPARISON_PRED (8 );
763+
710764DEFINE_EQUALITY_PRED (64 );
711765DEFINE_EQUALITY_PRED (32 );
712766DEFINE_EQUALITY_PRED (16 );
@@ -891,16 +945,7 @@ static int filter_pred_cpumask(struct filter_pred *pred, void *event)
891945 const struct cpumask * mask = (event + loc );
892946 const struct cpumask * cmp = pred -> mask ;
893947
894- switch (pred -> op ) {
895- case OP_EQ :
896- return cpumask_equal (mask , cmp );
897- case OP_NE :
898- return !cpumask_equal (mask , cmp );
899- case OP_BAND :
900- return cpumask_intersects (mask , cmp );
901- default :
902- return 0 ;
903- }
948+ return do_filter_cpumask (pred -> op , mask , cmp );
904949}
905950
906951/* Filter predicate for COMM. */
@@ -1351,24 +1396,32 @@ static int filter_pred_fn_call(struct filter_pred *pred, void *event)
13511396 switch (pred -> fn_num ) {
13521397 case FILTER_PRED_FN_64 :
13531398 return filter_pred_64 (pred , event );
1399+ case FILTER_PRED_FN_64_CPUMASK :
1400+ return filter_pred_64_cpumask (pred , event );
13541401 case FILTER_PRED_FN_S64 :
13551402 return filter_pred_s64 (pred , event );
13561403 case FILTER_PRED_FN_U64 :
13571404 return filter_pred_u64 (pred , event );
13581405 case FILTER_PRED_FN_32 :
13591406 return filter_pred_32 (pred , event );
1407+ case FILTER_PRED_FN_32_CPUMASK :
1408+ return filter_pred_32_cpumask (pred , event );
13601409 case FILTER_PRED_FN_S32 :
13611410 return filter_pred_s32 (pred , event );
13621411 case FILTER_PRED_FN_U32 :
13631412 return filter_pred_u32 (pred , event );
13641413 case FILTER_PRED_FN_16 :
13651414 return filter_pred_16 (pred , event );
1415+ case FILTER_PRED_FN_16_CPUMASK :
1416+ return filter_pred_16_cpumask (pred , event );
13661417 case FILTER_PRED_FN_S16 :
13671418 return filter_pred_s16 (pred , event );
13681419 case FILTER_PRED_FN_U16 :
13691420 return filter_pred_u16 (pred , event );
13701421 case FILTER_PRED_FN_8 :
13711422 return filter_pred_8 (pred , event );
1423+ case FILTER_PRED_FN_8_CPUMASK :
1424+ return filter_pred_8_cpumask (pred , event );
13721425 case FILTER_PRED_FN_S8 :
13731426 return filter_pred_s8 (pred , event );
13741427 case FILTER_PRED_FN_U8 :
@@ -1606,6 +1659,7 @@ static int parse_pred(const char *str, void *data,
16061659
16071660 switch (field -> filter_type ) {
16081661 case FILTER_CPUMASK :
1662+ case FILTER_OTHER :
16091663 break ;
16101664 default :
16111665 parse_error (pe , FILT_ERR_ILLEGAL_FIELD_OP , pos + i );
@@ -1658,8 +1712,24 @@ static int parse_pred(const char *str, void *data,
16581712
16591713 /* Move along */
16601714 i ++ ;
1661- if (field -> filter_type == FILTER_CPUMASK )
1715+ if (field -> filter_type == FILTER_CPUMASK ) {
16621716 pred -> fn_num = FILTER_PRED_FN_CPUMASK ;
1717+ } else {
1718+ switch (field -> size ) {
1719+ case 8 :
1720+ pred -> fn_num = FILTER_PRED_FN_64_CPUMASK ;
1721+ break ;
1722+ case 4 :
1723+ pred -> fn_num = FILTER_PRED_FN_32_CPUMASK ;
1724+ break ;
1725+ case 2 :
1726+ pred -> fn_num = FILTER_PRED_FN_16_CPUMASK ;
1727+ break ;
1728+ case 1 :
1729+ pred -> fn_num = FILTER_PRED_FN_8_CPUMASK ;
1730+ break ;
1731+ }
1732+ }
16631733
16641734 /* This is either a string, or an integer */
16651735 } else if (str [i ] == '\'' || str [i ] == '"' ) {
0 commit comments