typedef u64 (*hist_field_fn_t) (struct hist_field *field, void *event);
 
+#define HIST_FIELD_OPERANDS_MAX        2
+
 struct hist_field {
        struct ftrace_event_field       *field;
        unsigned long                   flags;
        hist_field_fn_t                 fn;
        unsigned int                    size;
        unsigned int                    offset;
+       unsigned int                    is_signed;
+       struct hist_field               *operands[HIST_FIELD_OPERANDS_MAX];
 };
 
 static u64 hist_field_none(struct hist_field *field, void *event)
 
 static u64 hist_field_log2(struct hist_field *hist_field, void *event)
 {
-       u64 val = *(u64 *)(event + hist_field->field->offset);
+       struct hist_field *operand = hist_field->operands[0];
+
+       u64 val = operand->fn(operand, event);
 
        return (u64) ilog2(roundup_pow_of_two(val));
 }
 
        if (field->field)
                field_name = field->field->name;
+       else if (field->flags & HIST_FIELD_FL_LOG2)
+               field_name = hist_field_name(field->operands[0], ++level);
 
        if (field_name == NULL)
                field_name = "";
        .elt_init       = hist_trigger_elt_comm_init,
 };
 
-static void destroy_hist_field(struct hist_field *hist_field)
+static void destroy_hist_field(struct hist_field *hist_field,
+                              unsigned int level)
 {
+       unsigned int i;
+
+       if (level > 2)
+               return;
+
+       if (!hist_field)
+               return;
+
+       for (i = 0; i < HIST_FIELD_OPERANDS_MAX; i++)
+               destroy_hist_field(hist_field->operands[i], level + 1);
+
        kfree(hist_field);
 }
 
        }
 
        if (flags & HIST_FIELD_FL_LOG2) {
+               unsigned long fl = flags & ~HIST_FIELD_FL_LOG2;
                hist_field->fn = hist_field_log2;
+               hist_field->operands[0] = create_hist_field(field, fl);
+               hist_field->size = hist_field->operands[0]->size;
                goto out;
        }
 
                hist_field->fn = select_value_fn(field->size,
                                                 field->is_signed);
                if (!hist_field->fn) {
-                       destroy_hist_field(hist_field);
+                       destroy_hist_field(hist_field, 0);
                        return NULL;
                }
        }
 
        for (i = 0; i < TRACING_MAP_FIELDS_MAX; i++) {
                if (hist_data->fields[i]) {
-                       destroy_hist_field(hist_data->fields[i]);
+                       destroy_hist_field(hist_data->fields[i], 0);
                        hist_data->fields[i] = NULL;
                }
        }