diff --git a/arch/arm64/kvm/hyp_events.c b/arch/arm64/kvm/hyp_events.c index 6b05da594062..7786f3b226ed 100644 --- a/arch/arm64/kvm/hyp_events.c +++ b/arch/arm64/kvm/hyp_events.c @@ -54,7 +54,11 @@ struct hyp_event { #include #undef HYP_EVENT +#undef HE_PRINTK +#define __entry REC +#define HE_PRINTK(fmt, args...) "\"" fmt "\", " __stringify(args) #define HYP_EVENT(__name, __proto, __struct, __assign, __printk) \ + static char hyp_event_print_fmt_##__name[] = __printk; \ static struct trace_event_functions hyp_event_funcs_##__name = { \ .trace = &hyp_event_trace_##__name, \ }; \ @@ -66,6 +70,7 @@ struct hyp_event { static struct trace_event_call hyp_event_call_##__name = { \ .class = &hyp_event_class_##__name, \ .event.funcs = &hyp_event_funcs_##__name, \ + .print_fmt = hyp_event_print_fmt_##__name, \ }; \ static bool hyp_event_enabled_##__name; \ struct hyp_event __section("_hyp_events") hyp_event_##__name = { \ @@ -191,6 +196,46 @@ static const struct file_operations hyp_event_id_fops = { .release = single_release, }; +static int hyp_event_format_show(struct seq_file *m, void *v) +{ + struct hyp_event *evt = (struct hyp_event *)m->private; + struct trace_event_fields *field; + unsigned int offset = sizeof(struct hyp_entry_hdr); + + seq_printf(m, "name: %s\n", evt->name); + seq_printf(m, "ID: %d\n", evt->call->event.type); + seq_puts(m, "format:\n\tfield:unsigned short common_type;\toffset:0;\tsize:2;\tsigned:0;\n"); + seq_puts(m, "\n"); + + field = &evt->call->class->fields_array[0]; + while (field->name) { + seq_printf(m, "\tfield:%s %s;\toffset:%u;\tsize:%u;\tsigned:%d;\n", + field->type, field->name, offset, field->size, + !!field->is_signed); + offset += field->size; + field++; + } + + if (field != &evt->call->class->fields_array[0]) + seq_puts(m, "\n"); + + seq_printf(m, "print fmt: %s\n", evt->call->print_fmt); + + return 0; +} + +static int hyp_event_format_open(struct inode *inode, struct file *file) +{ + return single_open(file, hyp_event_format_show, inode->i_private); +} + +static const struct file_operations hyp_event_format_fops = { + .open = hyp_event_format_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static char early_events[COMMAND_LINE_SIZE]; static __init int setup_hyp_event_early(char *str) @@ -262,6 +307,13 @@ void kvm_hyp_init_events_tracefs(struct dentry *parent) &hyp_event_id_fops); if (!d) pr_err("Failed to create events/hyp/%s/id\n", event->name); + + d = tracefs_create_file("format", 0400, event_dir, (void *)event, + &hyp_event_format_fops); + if (!d) + pr_err("Failed to create events/hyp/%s/format\n", + event->name); + } }