FROMLIST: KVM: arm64: Add raw interface for hyp tracefs

The raw interface enables userspace tools such as trace-cmd to directly
read the ring-buffer without any decoding by the kernel.

Bug: 357781595
Link: https://lore.kernel.org/all/20240911093029.3279154-11-vdonnefort@google.com/
Change-Id: I337dc86a95e7182f60d9376d1a23f3e75fb20290
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
This commit is contained in:
Vincent Donnefort
2023-06-13 11:38:55 +01:00
committed by Keir Fraser
parent 2dc09955d6
commit 532d6ef155
+82
View File
@@ -739,6 +739,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");
@@ -793,6 +872,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;