DEFINE_MUTEX(event_mutex);
 
 LIST_HEAD(ftrace_events);
+static LIST_HEAD(ftrace_generic_fields);
 static LIST_HEAD(ftrace_common_fields);
 
 #define GFP_TRACE (GFP_KERNEL | __GFP_ZERO)
        struct ftrace_event_field *field;
        struct list_head *head;
 
+       field = __find_event_field(&ftrace_generic_fields, name);
+       if (field)
+               return field;
+
        field = __find_event_field(&ftrace_common_fields, name);
        if (field)
                return field;
 }
 EXPORT_SYMBOL_GPL(trace_define_field);
 
+#define __generic_field(type, item, filter_type)                       \
+       ret = __trace_define_field(&ftrace_generic_fields, #type,       \
+                                  #item, 0, 0, is_signed_type(type),   \
+                                  filter_type);                        \
+       if (ret)                                                        \
+               return ret;
+
 #define __common_field(type, item)                                     \
        ret = __trace_define_field(&ftrace_common_fields, #type,        \
                                   "common_" #item,                     \
        if (ret)                                                        \
                return ret;
 
+static int trace_define_generic_fields(void)
+{
+       int ret;
+
+       __generic_field(int, cpu, FILTER_OTHER);
+       __generic_field(char *, comm, FILTER_PTR_STRING);
+
+       return ret;
+}
+
 static int trace_define_common_fields(void)
 {
        int ret;
        if (!entry)
                pr_warn("Could not create tracefs 'available_events' entry\n");
 
+       if (trace_define_generic_fields())
+               pr_warn("tracing: Failed to allocated generic fields");
+
        if (trace_define_common_fields())
                pr_warn("tracing: Failed to allocate common fields");
 
 
        return match;
 }
 
+/* Filter predicate for CPUs. */
+static int filter_pred_cpu(struct filter_pred *pred, void *event)
+{
+       int cpu, cmp;
+       int match = 0;
+
+       cpu = raw_smp_processor_id();
+       cmp = pred->val;
+
+       switch (pred->op) {
+       case OP_EQ:
+               match = cpu == cmp;
+               break;
+       case OP_LT:
+               match = cpu < cmp;
+               break;
+       case OP_LE:
+               match = cpu <= cmp;
+               break;
+       case OP_GT:
+               match = cpu > cmp;
+               break;
+       case OP_GE:
+               match = cpu >= cmp;
+               break;
+       default:
+               break;
+       }
+
+       return !!match == !pred->not;
+}
+
+/* Filter predicate for COMM. */
+static int filter_pred_comm(struct filter_pred *pred, void *event)
+{
+       int cmp, match;
+
+       cmp = pred->regex.match(current->comm, &pred->regex,
+                               pred->regex.field_len);
+       match = cmp ^ pred->not;
+
+       return match;
+}
+
 static int filter_pred_none(struct filter_pred *pred, void *event)
 {
        return 0;
        if (is_string_field(field)) {
                filter_build_regex(pred);
 
-               if (field->filter_type == FILTER_STATIC_STRING) {
+               if (!strcmp(field->name, "comm")) {
+                       fn = filter_pred_comm;
+                       pred->regex.field_len = TASK_COMM_LEN;
+               } else if (field->filter_type == FILTER_STATIC_STRING) {
                        fn = filter_pred_string;
                        pred->regex.field_len = field->size;
                } else if (field->filter_type == FILTER_DYN_STRING)
                }
                pred->val = val;
 
-               fn = select_comparison_fn(pred->op, field->size,
+               if (!strcmp(field->name, "cpu"))
+                       fn = filter_pred_cpu;
+               else
+                       fn = select_comparison_fn(pred->op, field->size,
                                          field->is_signed);
                if (!fn) {
                        parse_error(ps, FILT_ERR_INVALID_OP, 0);