The raw interface enables userspace tools such as trace-cmd to directly read the ring-buffer without any decoding by the kernel.
Signed-off-by: Vincent Donnefort <vdonnef...@google.com> diff --git a/arch/arm64/kvm/hyp_trace.c b/arch/arm64/kvm/hyp_trace.c index 78193dbd8a33..3d2a58977442 100644 --- a/arch/arm64/kvm/hyp_trace.c +++ b/arch/arm64/kvm/hyp_trace.c @@ -749,6 +749,85 @@ static const struct file_operations hyp_trace_pipe_fops = { .release = hyp_trace_pipe_release, }; +static ssize_t +hyp_trace_raw_read(struct file *file, char __user *ubuf, + size_t cnt, loff_t *ppos) +{ + struct ht_iterator *iter = (struct ht_iterator *)file->private_data; + size_t size; + int ret; + + if (iter->copy_leftover) + goto read; + +again: + ret = ring_buffer_read_page(iter->trace_buffer, + (struct buffer_data_read_page *)iter->spare, + cnt, iter->cpu, 0); + if (ret < 0) { + if (!ring_buffer_empty_cpu(iter->trace_buffer, iter->cpu)) + return 0; + + ret = ring_buffer_wait(iter->trace_buffer, iter->cpu, 0, NULL, + NULL); + if (ret < 0) + return ret; + + goto again; + } + + iter->copy_leftover = 0; + +read: + size = PAGE_SIZE - iter->copy_leftover; + if (size > cnt) + size = cnt; + + ret = copy_to_user(ubuf, iter->spare + PAGE_SIZE - size, size); + if (ret == size) + return -EFAULT; + + size -= ret; + *ppos += size; + iter->copy_leftover = ret; + + return size; +} + +static int hyp_trace_raw_open(struct inode *inode, struct file *file) +{ + int ret = hyp_trace_pipe_open(inode, file); + struct ht_iterator *iter; + + if (ret) + return ret; + + iter = file->private_data; + iter->spare = ring_buffer_alloc_read_page(iter->trace_buffer, iter->cpu); + if (IS_ERR(iter->spare)) { + ret = PTR_ERR(iter->spare); + iter->spare = NULL; + return ret; + } + + return 0; +} + +static int hyp_trace_raw_release(struct inode *inode, struct file *file) +{ + struct ht_iterator *iter = file->private_data; + + ring_buffer_free_read_page(iter->trace_buffer, iter->cpu, iter->spare); + + return hyp_trace_pipe_release(inode, file); +} + +static const struct file_operations hyp_trace_raw_fops = { + .open = hyp_trace_raw_open, + .read = hyp_trace_raw_read, + .release = hyp_trace_raw_release, +}; + static int hyp_trace_clock_show(struct seq_file *m, void *v) { seq_puts(m, "[boot]\n"); @@ -803,6 +882,9 @@ int hyp_trace_init_tracefs(void) tracefs_create_file("trace_pipe", TRACEFS_MODE_READ, per_cpu_dir, (void *)cpu, &hyp_trace_pipe_fops); + + tracefs_create_file("trace_pipe_raw", TRACEFS_MODE_READ, per_cpu_dir, + (void *)cpu, &hyp_trace_pipe_fops); } return 0; -- 2.47.1.613.gc27f4b7a9f-goog